|
@@ -180,17 +180,17 @@ struct BlockScalarTraits {
|
|
/// to/from a YAML sequence. For example:
|
|
/// to/from a YAML sequence. For example:
|
|
///
|
|
///
|
|
/// template<>
|
|
/// template<>
|
|
-/// struct SequenceTraits< std::vector<MyType>> {
|
|
|
|
-/// static size_t size(IO &io, std::vector<MyType> &seq) {
|
|
|
|
|
|
+/// struct SequenceTraits<MyContainer> {
|
|
|
|
+/// static size_t size(IO &io, MyContainer &seq) {
|
|
/// return seq.size();
|
|
/// return seq.size();
|
|
/// }
|
|
/// }
|
|
-/// static MyType& element(IO &, std::vector<MyType> &seq, size_t index) {
|
|
|
|
|
|
+/// static MyType& element(IO &, MyContainer &seq, size_t index) {
|
|
/// if ( index >= seq.size() )
|
|
/// if ( index >= seq.size() )
|
|
/// seq.resize(index+1);
|
|
/// seq.resize(index+1);
|
|
/// return seq[index];
|
|
/// return seq[index];
|
|
/// }
|
|
/// }
|
|
/// };
|
|
/// };
|
|
-template<typename T>
|
|
|
|
|
|
+template<typename T, typename EnableIf = void>
|
|
struct SequenceTraits {
|
|
struct SequenceTraits {
|
|
// Must provide:
|
|
// Must provide:
|
|
// static size_t size(IO &io, T &seq);
|
|
// static size_t size(IO &io, T &seq);
|
|
@@ -201,6 +201,14 @@ struct SequenceTraits {
|
|
// static const bool flow = true;
|
|
// static const bool flow = true;
|
|
};
|
|
};
|
|
|
|
|
|
|
|
+/// This class should be specialized by any type for which vectors of that
|
|
|
|
+/// type need to be converted to/from a YAML sequence.
|
|
|
|
+template<typename T, typename EnableIf = void>
|
|
|
|
+struct SequenceElementTraits {
|
|
|
|
+ // Must provide:
|
|
|
|
+ // static const bool flow;
|
|
|
|
+};
|
|
|
|
+
|
|
/// This class should be specialized by any type that needs to be converted
|
|
/// This class should be specialized by any type that needs to be converted
|
|
/// to/from a list of YAML documents.
|
|
/// to/from a list of YAML documents.
|
|
template<typename T>
|
|
template<typename T>
|
|
@@ -1542,18 +1550,59 @@ operator<<(Output &yout, T &seq) {
|
|
return yout;
|
|
return yout;
|
|
}
|
|
}
|
|
|
|
|
|
-template <typename T> struct SequenceTraitsImpl {
|
|
|
|
- using _type = typename T::value_type;
|
|
|
|
|
|
+template <bool B> struct IsFlowSequenceBase {};
|
|
|
|
+template <> struct IsFlowSequenceBase<true> { static const bool flow = true; };
|
|
|
|
|
|
|
|
+template <typename T, bool Flow>
|
|
|
|
+struct SequenceTraitsImpl : IsFlowSequenceBase<Flow> {
|
|
|
|
+private:
|
|
|
|
+ using type = typename T::value_type;
|
|
|
|
+
|
|
|
|
+public:
|
|
static size_t size(IO &io, T &seq) { return seq.size(); }
|
|
static size_t size(IO &io, T &seq) { return seq.size(); }
|
|
|
|
|
|
- static _type &element(IO &io, T &seq, size_t index) {
|
|
|
|
|
|
+ static type &element(IO &io, T &seq, size_t index) {
|
|
if (index >= seq.size())
|
|
if (index >= seq.size())
|
|
seq.resize(index + 1);
|
|
seq.resize(index + 1);
|
|
return seq[index];
|
|
return seq[index];
|
|
}
|
|
}
|
|
};
|
|
};
|
|
|
|
|
|
|
|
+// Simple helper to check an expression can be used as a bool-valued template
|
|
|
|
+// argument.
|
|
|
|
+template <bool> struct CheckIsBool { static const bool value = true; };
|
|
|
|
+
|
|
|
|
+// If T has SequenceElementTraits, then vector<T> and SmallVector<T, N> have
|
|
|
|
+// SequenceTraits that do the obvious thing.
|
|
|
|
+template <typename T>
|
|
|
|
+struct SequenceTraits<std::vector<T>,
|
|
|
|
+ typename std::enable_if<CheckIsBool<
|
|
|
|
+ SequenceElementTraits<T>::flow>::value>::type>
|
|
|
|
+ : SequenceTraitsImpl<std::vector<T>, SequenceElementTraits<T>::flow> {};
|
|
|
|
+template <typename T, unsigned N>
|
|
|
|
+struct SequenceTraits<SmallVector<T, N>,
|
|
|
|
+ typename std::enable_if<CheckIsBool<
|
|
|
|
+ SequenceElementTraits<T>::flow>::value>::type>
|
|
|
|
+ : SequenceTraitsImpl<SmallVector<T, N>, SequenceElementTraits<T>::flow> {};
|
|
|
|
+
|
|
|
|
+// Sequences of fundamental types use flow formatting.
|
|
|
|
+template <typename T>
|
|
|
|
+struct SequenceElementTraits<
|
|
|
|
+ T, typename std::enable_if<std::is_fundamental<T>::value>::type> {
|
|
|
|
+ static const bool flow = true;
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+// Sequences of strings use block formatting.
|
|
|
|
+template<> struct SequenceElementTraits<std::string> {
|
|
|
|
+ static const bool flow = false;
|
|
|
|
+};
|
|
|
|
+template<> struct SequenceElementTraits<StringRef> {
|
|
|
|
+ static const bool flow = false;
|
|
|
|
+};
|
|
|
|
+template<> struct SequenceElementTraits<std::pair<std::string, std::string>> {
|
|
|
|
+ static const bool flow = false;
|
|
|
|
+};
|
|
|
|
+
|
|
/// Implementation of CustomMappingTraits for std::map<std::string, T>.
|
|
/// Implementation of CustomMappingTraits for std::map<std::string, T>.
|
|
template <typename T> struct StdMapStringCustomMappingTraitsImpl {
|
|
template <typename T> struct StdMapStringCustomMappingTraitsImpl {
|
|
using map_type = std::map<std::string, T>;
|
|
using map_type = std::map<std::string, T>;
|
|
@@ -1571,42 +1620,29 @@ template <typename T> struct StdMapStringCustomMappingTraitsImpl {
|
|
} // end namespace yaml
|
|
} // end namespace yaml
|
|
} // end namespace llvm
|
|
} // end namespace llvm
|
|
|
|
|
|
-/// Utility for declaring that a std::vector of a particular type
|
|
|
|
-/// should be considered a YAML sequence.
|
|
|
|
-#define LLVM_YAML_IS_SEQUENCE_VECTOR(_type) \
|
|
|
|
|
|
+#define LLVM_YAML_IS_SEQUENCE_VECTOR_IMPL(TYPE, FLOW) \
|
|
namespace llvm { \
|
|
namespace llvm { \
|
|
namespace yaml { \
|
|
namespace yaml { \
|
|
- template <> \
|
|
|
|
- struct SequenceTraits<std::vector<_type>> \
|
|
|
|
- : public SequenceTraitsImpl<std::vector<_type>> {}; \
|
|
|
|
- template <unsigned N> \
|
|
|
|
- struct SequenceTraits<SmallVector<_type, N>> \
|
|
|
|
- : public SequenceTraitsImpl<SmallVector<_type, N>> {}; \
|
|
|
|
|
|
+ static_assert( \
|
|
|
|
+ !std::is_fundamental<TYPE>::value && \
|
|
|
|
+ !std::is_same<TYPE, std::string>::value && \
|
|
|
|
+ !std::is_same<TYPE, llvm::StringRef>::value, \
|
|
|
|
+ "only use LLVM_YAML_IS_SEQUENCE_VECTOR for types you control"); \
|
|
|
|
+ template <> struct SequenceElementTraits<TYPE> { \
|
|
|
|
+ static const bool flow = FLOW; \
|
|
|
|
+ }; \
|
|
} \
|
|
} \
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+/// Utility for declaring that a std::vector of a particular type
|
|
|
|
+/// should be considered a YAML sequence.
|
|
|
|
+#define LLVM_YAML_IS_SEQUENCE_VECTOR(type) \
|
|
|
|
+ LLVM_YAML_IS_SEQUENCE_VECTOR_IMPL(type, false)
|
|
|
|
+
|
|
/// Utility for declaring that a std::vector of a particular type
|
|
/// Utility for declaring that a std::vector of a particular type
|
|
/// should be considered a YAML flow sequence.
|
|
/// should be considered a YAML flow sequence.
|
|
-/// We need to do a partial specialization on the vector version, not a full.
|
|
|
|
-/// If this is a full specialization, the compiler is a bit too "smart" and
|
|
|
|
-/// decides to warn on -Wunused-const-variable. This workaround can be
|
|
|
|
-/// removed and we can do a full specialization on std::vector<T> once
|
|
|
|
-/// PR28878 is fixed.
|
|
|
|
-#define LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(_type) \
|
|
|
|
- namespace llvm { \
|
|
|
|
- namespace yaml { \
|
|
|
|
- template <unsigned N> \
|
|
|
|
- struct SequenceTraits<SmallVector<_type, N>> \
|
|
|
|
- : public SequenceTraitsImpl<SmallVector<_type, N>> { \
|
|
|
|
- static const bool flow = true; \
|
|
|
|
- }; \
|
|
|
|
- template <typename Allocator> \
|
|
|
|
- struct SequenceTraits<std::vector<_type, Allocator>> \
|
|
|
|
- : public SequenceTraitsImpl<std::vector<_type, Allocator>> { \
|
|
|
|
- static const bool flow = true; \
|
|
|
|
- }; \
|
|
|
|
- } \
|
|
|
|
- }
|
|
|
|
|
|
+#define LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(type) \
|
|
|
|
+ LLVM_YAML_IS_SEQUENCE_VECTOR_IMPL(type, true)
|
|
|
|
|
|
#define LLVM_YAML_DECLARE_MAPPING_TRAITS(Type) \
|
|
#define LLVM_YAML_DECLARE_MAPPING_TRAITS(Type) \
|
|
namespace llvm { \
|
|
namespace llvm { \
|
|
@@ -1653,10 +1689,10 @@ template <typename T> struct StdMapStringCustomMappingTraitsImpl {
|
|
namespace yaml { \
|
|
namespace yaml { \
|
|
template <unsigned N> \
|
|
template <unsigned N> \
|
|
struct DocumentListTraits<SmallVector<_type, N>> \
|
|
struct DocumentListTraits<SmallVector<_type, N>> \
|
|
- : public SequenceTraitsImpl<SmallVector<_type, N>> {}; \
|
|
|
|
|
|
+ : public SequenceTraitsImpl<SmallVector<_type, N>, false> {}; \
|
|
template <> \
|
|
template <> \
|
|
struct DocumentListTraits<std::vector<_type>> \
|
|
struct DocumentListTraits<std::vector<_type>> \
|
|
- : public SequenceTraitsImpl<std::vector<_type>> {}; \
|
|
|
|
|
|
+ : public SequenceTraitsImpl<std::vector<_type>, false> {}; \
|
|
} \
|
|
} \
|
|
}
|
|
}
|
|
|
|
|