Home | History | Annotate | Download | only in Support
      1 //===- llvm/Support/YAMLTraits.h --------------------------------*- C++ -*-===//
      2 //
      3 //                             The LLVM Linker
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 
     10 #ifndef LLVM_SUPPORT_YAMLTRAITS_H
     11 #define LLVM_SUPPORT_YAMLTRAITS_H
     12 
     13 #include "llvm/ADT/DenseMap.h"
     14 #include "llvm/ADT/DenseMapInfo.h"
     15 #include "llvm/ADT/Optional.h"
     16 #include "llvm/ADT/SmallVector.h"
     17 #include "llvm/ADT/StringMap.h"
     18 #include "llvm/ADT/StringRef.h"
     19 #include "llvm/ADT/StringSwitch.h"
     20 #include "llvm/ADT/Twine.h"
     21 #include "llvm/Support/Compiler.h"
     22 #include "llvm/Support/Regex.h"
     23 #include "llvm/Support/SourceMgr.h"
     24 #include "llvm/Support/YAMLParser.h"
     25 #include "llvm/Support/raw_ostream.h"
     26 #include <system_error>
     27 
     28 namespace llvm {
     29 namespace yaml {
     30 
     31 /// This class should be specialized by any type that needs to be converted
     32 /// to/from a YAML mapping.  For example:
     33 ///
     34 ///     struct MappingTraits<MyStruct> {
     35 ///       static void mapping(IO &io, MyStruct &s) {
     36 ///         io.mapRequired("name", s.name);
     37 ///         io.mapRequired("size", s.size);
     38 ///         io.mapOptional("age",  s.age);
     39 ///       }
     40 ///     };
     41 template<class T>
     42 struct MappingTraits {
     43   // Must provide:
     44   // static void mapping(IO &io, T &fields);
     45   // Optionally may provide:
     46   // static StringRef validate(IO &io, T &fields);
     47   //
     48   // The optional flow flag will cause generated YAML to use a flow mapping
     49   // (e.g. { a: 0, b: 1 }):
     50   // static const bool flow = true;
     51 };
     52 
     53 /// This class should be specialized by any integral type that converts
     54 /// to/from a YAML scalar where there is a one-to-one mapping between
     55 /// in-memory values and a string in YAML.  For example:
     56 ///
     57 ///     struct ScalarEnumerationTraits<Colors> {
     58 ///         static void enumeration(IO &io, Colors &value) {
     59 ///           io.enumCase(value, "red",   cRed);
     60 ///           io.enumCase(value, "blue",  cBlue);
     61 ///           io.enumCase(value, "green", cGreen);
     62 ///         }
     63 ///       };
     64 template<typename T>
     65 struct ScalarEnumerationTraits {
     66   // Must provide:
     67   // static void enumeration(IO &io, T &value);
     68 };
     69 
     70 /// This class should be specialized by any integer type that is a union
     71 /// of bit values and the YAML representation is a flow sequence of
     72 /// strings.  For example:
     73 ///
     74 ///      struct ScalarBitSetTraits<MyFlags> {
     75 ///        static void bitset(IO &io, MyFlags &value) {
     76 ///          io.bitSetCase(value, "big",   flagBig);
     77 ///          io.bitSetCase(value, "flat",  flagFlat);
     78 ///          io.bitSetCase(value, "round", flagRound);
     79 ///        }
     80 ///      };
     81 template<typename T>
     82 struct ScalarBitSetTraits {
     83   // Must provide:
     84   // static void bitset(IO &io, T &value);
     85 };
     86 
     87 /// This class should be specialized by type that requires custom conversion
     88 /// to/from a yaml scalar.  For example:
     89 ///
     90 ///    template<>
     91 ///    struct ScalarTraits<MyType> {
     92 ///      static void output(const MyType &val, void*, llvm::raw_ostream &out) {
     93 ///        // stream out custom formatting
     94 ///        out << llvm::format("%x", val);
     95 ///      }
     96 ///      static StringRef input(StringRef scalar, void*, MyType &value) {
     97 ///        // parse scalar and set `value`
     98 ///        // return empty string on success, or error string
     99 ///        return StringRef();
    100 ///      }
    101 ///      static bool mustQuote(StringRef) { return true; }
    102 ///    };
    103 template<typename T>
    104 struct ScalarTraits {
    105   // Must provide:
    106   //
    107   // Function to write the value as a string:
    108   //static void output(const T &value, void *ctxt, llvm::raw_ostream &out);
    109   //
    110   // Function to convert a string to a value.  Returns the empty
    111   // StringRef on success or an error string if string is malformed:
    112   //static StringRef input(StringRef scalar, void *ctxt, T &value);
    113   //
    114   // Function to determine if the value should be quoted.
    115   //static bool mustQuote(StringRef);
    116 };
    117 
    118 
    119 /// This class should be specialized by type that requires custom conversion
    120 /// to/from a YAML literal block scalar. For example:
    121 ///
    122 ///    template <>
    123 ///    struct BlockScalarTraits<MyType> {
    124 ///      static void output(const MyType &Value, void*, llvm::raw_ostream &Out)
    125 ///      {
    126 ///        // stream out custom formatting
    127 ///        Out << Val;
    128 ///      }
    129 ///      static StringRef input(StringRef Scalar, void*, MyType &Value) {
    130 ///        // parse scalar and set `value`
    131 ///        // return empty string on success, or error string
    132 ///        return StringRef();
    133 ///      }
    134 ///    };
    135 template <typename T>
    136 struct BlockScalarTraits {
    137   // Must provide:
    138   //
    139   // Function to write the value as a string:
    140   // static void output(const T &Value, void *ctx, llvm::raw_ostream &Out);
    141   //
    142   // Function to convert a string to a value.  Returns the empty
    143   // StringRef on success or an error string if string is malformed:
    144   // static StringRef input(StringRef Scalar, void *ctxt, T &Value);
    145 };
    146 
    147 /// This class should be specialized by any type that needs to be converted
    148 /// to/from a YAML sequence.  For example:
    149 ///
    150 ///    template<>
    151 ///    struct SequenceTraits< std::vector<MyType> > {
    152 ///      static size_t size(IO &io, std::vector<MyType> &seq) {
    153 ///        return seq.size();
    154 ///      }
    155 ///      static MyType& element(IO &, std::vector<MyType> &seq, size_t index) {
    156 ///        if ( index >= seq.size() )
    157 ///          seq.resize(index+1);
    158 ///        return seq[index];
    159 ///      }
    160 ///    };
    161 template<typename T>
    162 struct SequenceTraits {
    163   // Must provide:
    164   // static size_t size(IO &io, T &seq);
    165   // static T::value_type& element(IO &io, T &seq, size_t index);
    166   //
    167   // The following is option and will cause generated YAML to use
    168   // a flow sequence (e.g. [a,b,c]).
    169   // static const bool flow = true;
    170 };
    171 
    172 /// This class should be specialized by any type that needs to be converted
    173 /// to/from a list of YAML documents.
    174 template<typename T>
    175 struct DocumentListTraits {
    176   // Must provide:
    177   // static size_t size(IO &io, T &seq);
    178   // static T::value_type& element(IO &io, T &seq, size_t index);
    179 };
    180 
    181 // Only used by compiler if both template types are the same
    182 template <typename T, T>
    183 struct SameType;
    184 
    185 // Only used for better diagnostics of missing traits
    186 template <typename T>
    187 struct MissingTrait;
    188 
    189 // Test if ScalarEnumerationTraits<T> is defined on type T.
    190 template <class T>
    191 struct has_ScalarEnumerationTraits
    192 {
    193   typedef void (*Signature_enumeration)(class IO&, T&);
    194 
    195   template <typename U>
    196   static char test(SameType<Signature_enumeration, &U::enumeration>*);
    197 
    198   template <typename U>
    199   static double test(...);
    200 
    201 public:
    202   static bool const value =
    203     (sizeof(test<ScalarEnumerationTraits<T> >(nullptr)) == 1);
    204 };
    205 
    206 // Test if ScalarBitSetTraits<T> is defined on type T.
    207 template <class T>
    208 struct has_ScalarBitSetTraits
    209 {
    210   typedef void (*Signature_bitset)(class IO&, T&);
    211 
    212   template <typename U>
    213   static char test(SameType<Signature_bitset, &U::bitset>*);
    214 
    215   template <typename U>
    216   static double test(...);
    217 
    218 public:
    219   static bool const value = (sizeof(test<ScalarBitSetTraits<T> >(nullptr)) == 1);
    220 };
    221 
    222 // Test if ScalarTraits<T> is defined on type T.
    223 template <class T>
    224 struct has_ScalarTraits
    225 {
    226   typedef StringRef (*Signature_input)(StringRef, void*, T&);
    227   typedef void (*Signature_output)(const T&, void*, llvm::raw_ostream&);
    228   typedef bool (*Signature_mustQuote)(StringRef);
    229 
    230   template <typename U>
    231   static char test(SameType<Signature_input, &U::input> *,
    232                    SameType<Signature_output, &U::output> *,
    233                    SameType<Signature_mustQuote, &U::mustQuote> *);
    234 
    235   template <typename U>
    236   static double test(...);
    237 
    238 public:
    239   static bool const value =
    240       (sizeof(test<ScalarTraits<T>>(nullptr, nullptr, nullptr)) == 1);
    241 };
    242 
    243 // Test if BlockScalarTraits<T> is defined on type T.
    244 template <class T>
    245 struct has_BlockScalarTraits
    246 {
    247   typedef StringRef (*Signature_input)(StringRef, void *, T &);
    248   typedef void (*Signature_output)(const T &, void *, llvm::raw_ostream &);
    249 
    250   template <typename U>
    251   static char test(SameType<Signature_input, &U::input> *,
    252                    SameType<Signature_output, &U::output> *);
    253 
    254   template <typename U>
    255   static double test(...);
    256 
    257 public:
    258   static bool const value =
    259       (sizeof(test<BlockScalarTraits<T>>(nullptr, nullptr)) == 1);
    260 };
    261 
    262 // Test if MappingTraits<T> is defined on type T.
    263 template <class T>
    264 struct has_MappingTraits
    265 {
    266   typedef void (*Signature_mapping)(class IO&, T&);
    267 
    268   template <typename U>
    269   static char test(SameType<Signature_mapping, &U::mapping>*);
    270 
    271   template <typename U>
    272   static double test(...);
    273 
    274 public:
    275   static bool const value = (sizeof(test<MappingTraits<T> >(nullptr)) == 1);
    276 };
    277 
    278 // Test if MappingTraits<T>::validate() is defined on type T.
    279 template <class T>
    280 struct has_MappingValidateTraits
    281 {
    282   typedef StringRef (*Signature_validate)(class IO&, T&);
    283 
    284   template <typename U>
    285   static char test(SameType<Signature_validate, &U::validate>*);
    286 
    287   template <typename U>
    288   static double test(...);
    289 
    290 public:
    291   static bool const value = (sizeof(test<MappingTraits<T> >(nullptr)) == 1);
    292 };
    293 
    294 // Test if SequenceTraits<T> is defined on type T.
    295 template <class T>
    296 struct has_SequenceMethodTraits
    297 {
    298   typedef size_t (*Signature_size)(class IO&, T&);
    299 
    300   template <typename U>
    301   static char test(SameType<Signature_size, &U::size>*);
    302 
    303   template <typename U>
    304   static double test(...);
    305 
    306 public:
    307   static bool const value =  (sizeof(test<SequenceTraits<T> >(nullptr)) == 1);
    308 };
    309 
    310 // has_FlowTraits<int> will cause an error with some compilers because
    311 // it subclasses int.  Using this wrapper only instantiates the
    312 // real has_FlowTraits only if the template type is a class.
    313 template <typename T, bool Enabled = std::is_class<T>::value>
    314 class has_FlowTraits
    315 {
    316 public:
    317    static const bool value = false;
    318 };
    319 
    320 // Some older gcc compilers don't support straight forward tests
    321 // for members, so test for ambiguity cause by the base and derived
    322 // classes both defining the member.
    323 template <class T>
    324 struct has_FlowTraits<T, true>
    325 {
    326   struct Fallback { bool flow; };
    327   struct Derived : T, Fallback { };
    328 
    329   template<typename C>
    330   static char (&f(SameType<bool Fallback::*, &C::flow>*))[1];
    331 
    332   template<typename C>
    333   static char (&f(...))[2];
    334 
    335 public:
    336   static bool const value = sizeof(f<Derived>(nullptr)) == 2;
    337 };
    338 
    339 // Test if SequenceTraits<T> is defined on type T
    340 template<typename T>
    341 struct has_SequenceTraits : public std::integral_constant<bool,
    342                                       has_SequenceMethodTraits<T>::value > { };
    343 
    344 // Test if DocumentListTraits<T> is defined on type T
    345 template <class T>
    346 struct has_DocumentListTraits
    347 {
    348   typedef size_t (*Signature_size)(class IO&, T&);
    349 
    350   template <typename U>
    351   static char test(SameType<Signature_size, &U::size>*);
    352 
    353   template <typename U>
    354   static double test(...);
    355 
    356 public:
    357   static bool const value = (sizeof(test<DocumentListTraits<T> >(nullptr))==1);
    358 };
    359 
    360 inline bool isNumber(StringRef S) {
    361   static const char OctalChars[] = "01234567";
    362   if (S.startswith("0") &&
    363       S.drop_front().find_first_not_of(OctalChars) == StringRef::npos)
    364     return true;
    365 
    366   if (S.startswith("0o") &&
    367       S.drop_front(2).find_first_not_of(OctalChars) == StringRef::npos)
    368     return true;
    369 
    370   static const char HexChars[] = "0123456789abcdefABCDEF";
    371   if (S.startswith("0x") &&
    372       S.drop_front(2).find_first_not_of(HexChars) == StringRef::npos)
    373     return true;
    374 
    375   static const char DecChars[] = "0123456789";
    376   if (S.find_first_not_of(DecChars) == StringRef::npos)
    377     return true;
    378 
    379   if (S.equals(".inf") || S.equals(".Inf") || S.equals(".INF"))
    380     return true;
    381 
    382   Regex FloatMatcher("^(\\.[0-9]+|[0-9]+(\\.[0-9]*)?)([eE][-+]?[0-9]+)?$");
    383   if (FloatMatcher.match(S))
    384     return true;
    385 
    386   return false;
    387 }
    388 
    389 inline bool isNumeric(StringRef S) {
    390   if ((S.front() == '-' || S.front() == '+') && isNumber(S.drop_front()))
    391     return true;
    392 
    393   if (isNumber(S))
    394     return true;
    395 
    396   if (S.equals(".nan") || S.equals(".NaN") || S.equals(".NAN"))
    397     return true;
    398 
    399   return false;
    400 }
    401 
    402 inline bool isNull(StringRef S) {
    403   return S.equals("null") || S.equals("Null") || S.equals("NULL") ||
    404          S.equals("~");
    405 }
    406 
    407 inline bool isBool(StringRef S) {
    408   return S.equals("true") || S.equals("True") || S.equals("TRUE") ||
    409          S.equals("false") || S.equals("False") || S.equals("FALSE");
    410 }
    411 
    412 inline bool needsQuotes(StringRef S) {
    413   if (S.empty())
    414     return true;
    415   if (isspace(S.front()) || isspace(S.back()))
    416     return true;
    417   if (S.front() == ',')
    418     return true;
    419 
    420   static const char ScalarSafeChars[] =
    421       "abcdefghijklmnopqrstuvwxyz"
    422       "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-/^., \t";
    423   if (S.find_first_not_of(ScalarSafeChars) != StringRef::npos)
    424     return true;
    425 
    426   if (isNull(S))
    427     return true;
    428   if (isBool(S))
    429     return true;
    430   if (isNumeric(S))
    431     return true;
    432 
    433   return false;
    434 }
    435 
    436 template<typename T>
    437 struct missingTraits : public std::integral_constant<bool,
    438                                          !has_ScalarEnumerationTraits<T>::value
    439                                       && !has_ScalarBitSetTraits<T>::value
    440                                       && !has_ScalarTraits<T>::value
    441                                       && !has_BlockScalarTraits<T>::value
    442                                       && !has_MappingTraits<T>::value
    443                                       && !has_SequenceTraits<T>::value
    444                                       && !has_DocumentListTraits<T>::value >  {};
    445 
    446 template<typename T>
    447 struct validatedMappingTraits : public std::integral_constant<bool,
    448                                        has_MappingTraits<T>::value
    449                                     && has_MappingValidateTraits<T>::value> {};
    450 
    451 template<typename T>
    452 struct unvalidatedMappingTraits : public std::integral_constant<bool,
    453                                         has_MappingTraits<T>::value
    454                                     && !has_MappingValidateTraits<T>::value> {};
    455 // Base class for Input and Output.
    456 class IO {
    457 public:
    458 
    459   IO(void *Ctxt=nullptr);
    460   virtual ~IO();
    461 
    462   virtual bool outputting() = 0;
    463 
    464   virtual unsigned beginSequence() = 0;
    465   virtual bool preflightElement(unsigned, void *&) = 0;
    466   virtual void postflightElement(void*) = 0;
    467   virtual void endSequence() = 0;
    468   virtual bool canElideEmptySequence() = 0;
    469 
    470   virtual unsigned beginFlowSequence() = 0;
    471   virtual bool preflightFlowElement(unsigned, void *&) = 0;
    472   virtual void postflightFlowElement(void*) = 0;
    473   virtual void endFlowSequence() = 0;
    474 
    475   virtual bool mapTag(StringRef Tag, bool Default=false) = 0;
    476   virtual void beginMapping() = 0;
    477   virtual void endMapping() = 0;
    478   virtual bool preflightKey(const char*, bool, bool, bool &, void *&) = 0;
    479   virtual void postflightKey(void*) = 0;
    480 
    481   virtual void beginFlowMapping() = 0;
    482   virtual void endFlowMapping() = 0;
    483 
    484   virtual void beginEnumScalar() = 0;
    485   virtual bool matchEnumScalar(const char*, bool) = 0;
    486   virtual bool matchEnumFallback() = 0;
    487   virtual void endEnumScalar() = 0;
    488 
    489   virtual bool beginBitSetScalar(bool &) = 0;
    490   virtual bool bitSetMatch(const char*, bool) = 0;
    491   virtual void endBitSetScalar() = 0;
    492 
    493   virtual void scalarString(StringRef &, bool) = 0;
    494   virtual void blockScalarString(StringRef &) = 0;
    495 
    496   virtual void setError(const Twine &) = 0;
    497 
    498   template <typename T>
    499   void enumCase(T &Val, const char* Str, const T ConstVal) {
    500     if ( matchEnumScalar(Str, outputting() && Val == ConstVal) ) {
    501       Val = ConstVal;
    502     }
    503   }
    504 
    505   // allow anonymous enum values to be used with LLVM_YAML_STRONG_TYPEDEF
    506   template <typename T>
    507   void enumCase(T &Val, const char* Str, const uint32_t ConstVal) {
    508     if ( matchEnumScalar(Str, outputting() && Val == static_cast<T>(ConstVal)) ) {
    509       Val = ConstVal;
    510     }
    511   }
    512 
    513   template <typename FBT, typename T>
    514   void enumFallback(T &Val) {
    515     if ( matchEnumFallback() ) {
    516       // FIXME: Force integral conversion to allow strong typedefs to convert.
    517       FBT Res = (uint64_t)Val;
    518       yamlize(*this, Res, true);
    519       Val = (uint64_t)Res;
    520     }
    521   }
    522 
    523   template <typename T>
    524   void bitSetCase(T &Val, const char* Str, const T ConstVal) {
    525     if ( bitSetMatch(Str, outputting() && (Val & ConstVal) == ConstVal) ) {
    526       Val = Val | ConstVal;
    527     }
    528   }
    529 
    530   // allow anonymous enum values to be used with LLVM_YAML_STRONG_TYPEDEF
    531   template <typename T>
    532   void bitSetCase(T &Val, const char* Str, const uint32_t ConstVal) {
    533     if ( bitSetMatch(Str, outputting() && (Val & ConstVal) == ConstVal) ) {
    534       Val = Val | ConstVal;
    535     }
    536   }
    537 
    538   template <typename T>
    539   void maskedBitSetCase(T &Val, const char *Str, T ConstVal, T Mask) {
    540     if (bitSetMatch(Str, outputting() && (Val & Mask) == ConstVal))
    541       Val = Val | ConstVal;
    542   }
    543 
    544   template <typename T>
    545   void maskedBitSetCase(T &Val, const char *Str, uint32_t ConstVal,
    546                         uint32_t Mask) {
    547     if (bitSetMatch(Str, outputting() && (Val & Mask) == ConstVal))
    548       Val = Val | ConstVal;
    549   }
    550 
    551   void *getContext();
    552   void setContext(void *);
    553 
    554   template <typename T>
    555   void mapRequired(const char* Key, T& Val) {
    556     this->processKey(Key, Val, true);
    557   }
    558 
    559   template <typename T>
    560   typename std::enable_if<has_SequenceTraits<T>::value,void>::type
    561   mapOptional(const char* Key, T& Val) {
    562     // omit key/value instead of outputting empty sequence
    563     if ( this->canElideEmptySequence() && !(Val.begin() != Val.end()) )
    564       return;
    565     this->processKey(Key, Val, false);
    566   }
    567 
    568   template <typename T>
    569   void mapOptional(const char* Key, Optional<T> &Val) {
    570     processKeyWithDefault(Key, Val, Optional<T>(), /*Required=*/false);
    571   }
    572 
    573   template <typename T>
    574   typename std::enable_if<!has_SequenceTraits<T>::value,void>::type
    575   mapOptional(const char* Key, T& Val) {
    576     this->processKey(Key, Val, false);
    577   }
    578 
    579   template <typename T>
    580   void mapOptional(const char* Key, T& Val, const T& Default) {
    581     this->processKeyWithDefault(Key, Val, Default, false);
    582   }
    583 
    584 private:
    585   template <typename T>
    586   void processKeyWithDefault(const char *Key, Optional<T> &Val,
    587                              const Optional<T> &DefaultValue, bool Required) {
    588     assert(DefaultValue.hasValue() == false &&
    589            "Optional<T> shouldn't have a value!");
    590     void *SaveInfo;
    591     bool UseDefault;
    592     const bool sameAsDefault = outputting() && !Val.hasValue();
    593     if (!outputting() && !Val.hasValue())
    594       Val = T();
    595     if (this->preflightKey(Key, Required, sameAsDefault, UseDefault,
    596                            SaveInfo)) {
    597       yamlize(*this, Val.getValue(), Required);
    598       this->postflightKey(SaveInfo);
    599     } else {
    600       if (UseDefault)
    601         Val = DefaultValue;
    602     }
    603   }
    604 
    605   template <typename T>
    606   void processKeyWithDefault(const char *Key, T &Val, const T& DefaultValue,
    607                                                                 bool Required) {
    608     void *SaveInfo;
    609     bool UseDefault;
    610     const bool sameAsDefault = outputting() && Val == DefaultValue;
    611     if ( this->preflightKey(Key, Required, sameAsDefault, UseDefault,
    612                                                                   SaveInfo) ) {
    613       yamlize(*this, Val, Required);
    614       this->postflightKey(SaveInfo);
    615     }
    616     else {
    617       if ( UseDefault )
    618         Val = DefaultValue;
    619     }
    620   }
    621 
    622   template <typename T>
    623   void processKey(const char *Key, T &Val, bool Required) {
    624     void *SaveInfo;
    625     bool UseDefault;
    626     if ( this->preflightKey(Key, Required, false, UseDefault, SaveInfo) ) {
    627       yamlize(*this, Val, Required);
    628       this->postflightKey(SaveInfo);
    629     }
    630   }
    631 
    632 private:
    633   void  *Ctxt;
    634 };
    635 
    636 template<typename T>
    637 typename std::enable_if<has_ScalarEnumerationTraits<T>::value,void>::type
    638 yamlize(IO &io, T &Val, bool) {
    639   io.beginEnumScalar();
    640   ScalarEnumerationTraits<T>::enumeration(io, Val);
    641   io.endEnumScalar();
    642 }
    643 
    644 template<typename T>
    645 typename std::enable_if<has_ScalarBitSetTraits<T>::value,void>::type
    646 yamlize(IO &io, T &Val, bool) {
    647   bool DoClear;
    648   if ( io.beginBitSetScalar(DoClear) ) {
    649     if ( DoClear )
    650       Val = static_cast<T>(0);
    651     ScalarBitSetTraits<T>::bitset(io, Val);
    652     io.endBitSetScalar();
    653   }
    654 }
    655 
    656 template<typename T>
    657 typename std::enable_if<has_ScalarTraits<T>::value,void>::type
    658 yamlize(IO &io, T &Val, bool) {
    659   if ( io.outputting() ) {
    660     std::string Storage;
    661     llvm::raw_string_ostream Buffer(Storage);
    662     ScalarTraits<T>::output(Val, io.getContext(), Buffer);
    663     StringRef Str = Buffer.str();
    664     io.scalarString(Str, ScalarTraits<T>::mustQuote(Str));
    665   }
    666   else {
    667     StringRef Str;
    668     io.scalarString(Str, ScalarTraits<T>::mustQuote(Str));
    669     StringRef Result = ScalarTraits<T>::input(Str, io.getContext(), Val);
    670     if ( !Result.empty() ) {
    671       io.setError(llvm::Twine(Result));
    672     }
    673   }
    674 }
    675 
    676 template <typename T>
    677 typename std::enable_if<has_BlockScalarTraits<T>::value, void>::type
    678 yamlize(IO &YamlIO, T &Val, bool) {
    679   if (YamlIO.outputting()) {
    680     std::string Storage;
    681     llvm::raw_string_ostream Buffer(Storage);
    682     BlockScalarTraits<T>::output(Val, YamlIO.getContext(), Buffer);
    683     StringRef Str = Buffer.str();
    684     YamlIO.blockScalarString(Str);
    685   } else {
    686     StringRef Str;
    687     YamlIO.blockScalarString(Str);
    688     StringRef Result =
    689         BlockScalarTraits<T>::input(Str, YamlIO.getContext(), Val);
    690     if (!Result.empty())
    691       YamlIO.setError(llvm::Twine(Result));
    692   }
    693 }
    694 
    695 template<typename T>
    696 typename std::enable_if<validatedMappingTraits<T>::value, void>::type
    697 yamlize(IO &io, T &Val, bool) {
    698   if (has_FlowTraits<MappingTraits<T>>::value)
    699     io.beginFlowMapping();
    700   else
    701     io.beginMapping();
    702   if (io.outputting()) {
    703     StringRef Err = MappingTraits<T>::validate(io, Val);
    704     if (!Err.empty()) {
    705       llvm::errs() << Err << "\n";
    706       assert(Err.empty() && "invalid struct trying to be written as yaml");
    707     }
    708   }
    709   MappingTraits<T>::mapping(io, Val);
    710   if (!io.outputting()) {
    711     StringRef Err = MappingTraits<T>::validate(io, Val);
    712     if (!Err.empty())
    713       io.setError(Err);
    714   }
    715   if (has_FlowTraits<MappingTraits<T>>::value)
    716     io.endFlowMapping();
    717   else
    718     io.endMapping();
    719 }
    720 
    721 template<typename T>
    722 typename std::enable_if<unvalidatedMappingTraits<T>::value, void>::type
    723 yamlize(IO &io, T &Val, bool) {
    724   if (has_FlowTraits<MappingTraits<T>>::value) {
    725     io.beginFlowMapping();
    726     MappingTraits<T>::mapping(io, Val);
    727     io.endFlowMapping();
    728   } else {
    729     io.beginMapping();
    730     MappingTraits<T>::mapping(io, Val);
    731     io.endMapping();
    732   }
    733 }
    734 
    735 template<typename T>
    736 typename std::enable_if<missingTraits<T>::value, void>::type
    737 yamlize(IO &io, T &Val, bool) {
    738   char missing_yaml_trait_for_type[sizeof(MissingTrait<T>)];
    739 }
    740 
    741 template<typename T>
    742 typename std::enable_if<has_SequenceTraits<T>::value,void>::type
    743 yamlize(IO &io, T &Seq, bool) {
    744   if ( has_FlowTraits< SequenceTraits<T> >::value ) {
    745     unsigned incnt = io.beginFlowSequence();
    746     unsigned count = io.outputting() ? SequenceTraits<T>::size(io, Seq) : incnt;
    747     for(unsigned i=0; i < count; ++i) {
    748       void *SaveInfo;
    749       if ( io.preflightFlowElement(i, SaveInfo) ) {
    750         yamlize(io, SequenceTraits<T>::element(io, Seq, i), true);
    751         io.postflightFlowElement(SaveInfo);
    752       }
    753     }
    754     io.endFlowSequence();
    755   }
    756   else {
    757     unsigned incnt = io.beginSequence();
    758     unsigned count = io.outputting() ? SequenceTraits<T>::size(io, Seq) : incnt;
    759     for(unsigned i=0; i < count; ++i) {
    760       void *SaveInfo;
    761       if ( io.preflightElement(i, SaveInfo) ) {
    762         yamlize(io, SequenceTraits<T>::element(io, Seq, i), true);
    763         io.postflightElement(SaveInfo);
    764       }
    765     }
    766     io.endSequence();
    767   }
    768 }
    769 
    770 template<>
    771 struct ScalarTraits<bool> {
    772   static void output(const bool &, void*, llvm::raw_ostream &);
    773   static StringRef input(StringRef, void*, bool &);
    774   static bool mustQuote(StringRef) { return false; }
    775 };
    776 
    777 template<>
    778 struct ScalarTraits<StringRef> {
    779   static void output(const StringRef &, void*, llvm::raw_ostream &);
    780   static StringRef input(StringRef, void*, StringRef &);
    781   static bool mustQuote(StringRef S) { return needsQuotes(S); }
    782 };
    783 
    784 template<>
    785 struct ScalarTraits<std::string> {
    786   static void output(const std::string &, void*, llvm::raw_ostream &);
    787   static StringRef input(StringRef, void*, std::string &);
    788   static bool mustQuote(StringRef S) { return needsQuotes(S); }
    789 };
    790 
    791 template<>
    792 struct ScalarTraits<uint8_t> {
    793   static void output(const uint8_t &, void*, llvm::raw_ostream &);
    794   static StringRef input(StringRef, void*, uint8_t &);
    795   static bool mustQuote(StringRef) { return false; }
    796 };
    797 
    798 template<>
    799 struct ScalarTraits<uint16_t> {
    800   static void output(const uint16_t &, void*, llvm::raw_ostream &);
    801   static StringRef input(StringRef, void*, uint16_t &);
    802   static bool mustQuote(StringRef) { return false; }
    803 };
    804 
    805 template<>
    806 struct ScalarTraits<uint32_t> {
    807   static void output(const uint32_t &, void*, llvm::raw_ostream &);
    808   static StringRef input(StringRef, void*, uint32_t &);
    809   static bool mustQuote(StringRef) { return false; }
    810 };
    811 
    812 template<>
    813 struct ScalarTraits<uint64_t> {
    814   static void output(const uint64_t &, void*, llvm::raw_ostream &);
    815   static StringRef input(StringRef, void*, uint64_t &);
    816   static bool mustQuote(StringRef) { return false; }
    817 };
    818 
    819 template<>
    820 struct ScalarTraits<int8_t> {
    821   static void output(const int8_t &, void*, llvm::raw_ostream &);
    822   static StringRef input(StringRef, void*, int8_t &);
    823   static bool mustQuote(StringRef) { return false; }
    824 };
    825 
    826 template<>
    827 struct ScalarTraits<int16_t> {
    828   static void output(const int16_t &, void*, llvm::raw_ostream &);
    829   static StringRef input(StringRef, void*, int16_t &);
    830   static bool mustQuote(StringRef) { return false; }
    831 };
    832 
    833 template<>
    834 struct ScalarTraits<int32_t> {
    835   static void output(const int32_t &, void*, llvm::raw_ostream &);
    836   static StringRef input(StringRef, void*, int32_t &);
    837   static bool mustQuote(StringRef) { return false; }
    838 };
    839 
    840 template<>
    841 struct ScalarTraits<int64_t> {
    842   static void output(const int64_t &, void*, llvm::raw_ostream &);
    843   static StringRef input(StringRef, void*, int64_t &);
    844   static bool mustQuote(StringRef) { return false; }
    845 };
    846 
    847 template<>
    848 struct ScalarTraits<float> {
    849   static void output(const float &, void*, llvm::raw_ostream &);
    850   static StringRef input(StringRef, void*, float &);
    851   static bool mustQuote(StringRef) { return false; }
    852 };
    853 
    854 template<>
    855 struct ScalarTraits<double> {
    856   static void output(const double &, void*, llvm::raw_ostream &);
    857   static StringRef input(StringRef, void*, double &);
    858   static bool mustQuote(StringRef) { return false; }
    859 };
    860 
    861 // Utility for use within MappingTraits<>::mapping() method
    862 // to [de]normalize an object for use with YAML conversion.
    863 template <typename TNorm, typename TFinal>
    864 struct MappingNormalization {
    865   MappingNormalization(IO &i_o, TFinal &Obj)
    866       : io(i_o), BufPtr(nullptr), Result(Obj) {
    867     if ( io.outputting() ) {
    868       BufPtr = new (&Buffer) TNorm(io, Obj);
    869     }
    870     else {
    871       BufPtr = new (&Buffer) TNorm(io);
    872     }
    873   }
    874 
    875   ~MappingNormalization() {
    876     if ( ! io.outputting() ) {
    877       Result = BufPtr->denormalize(io);
    878     }
    879     BufPtr->~TNorm();
    880   }
    881 
    882   TNorm* operator->() { return BufPtr; }
    883 
    884 private:
    885   typedef llvm::AlignedCharArrayUnion<TNorm> Storage;
    886 
    887   Storage       Buffer;
    888   IO           &io;
    889   TNorm        *BufPtr;
    890   TFinal       &Result;
    891 };
    892 
    893 // Utility for use within MappingTraits<>::mapping() method
    894 // to [de]normalize an object for use with YAML conversion.
    895 template <typename TNorm, typename TFinal>
    896 struct MappingNormalizationHeap {
    897   MappingNormalizationHeap(IO &i_o, TFinal &Obj)
    898     : io(i_o), BufPtr(nullptr), Result(Obj) {
    899     if ( io.outputting() ) {
    900       BufPtr = new (&Buffer) TNorm(io, Obj);
    901     }
    902     else {
    903       BufPtr = new TNorm(io);
    904     }
    905   }
    906 
    907   ~MappingNormalizationHeap() {
    908     if ( io.outputting() ) {
    909       BufPtr->~TNorm();
    910     }
    911     else {
    912       Result = BufPtr->denormalize(io);
    913     }
    914   }
    915 
    916   TNorm* operator->() { return BufPtr; }
    917 
    918 private:
    919   typedef llvm::AlignedCharArrayUnion<TNorm> Storage;
    920 
    921   Storage       Buffer;
    922   IO           &io;
    923   TNorm        *BufPtr;
    924   TFinal       &Result;
    925 };
    926 
    927 ///
    928 /// The Input class is used to parse a yaml document into in-memory structs
    929 /// and vectors.
    930 ///
    931 /// It works by using YAMLParser to do a syntax parse of the entire yaml
    932 /// document, then the Input class builds a graph of HNodes which wraps
    933 /// each yaml Node.  The extra layer is buffering.  The low level yaml
    934 /// parser only lets you look at each node once.  The buffering layer lets
    935 /// you search and interate multiple times.  This is necessary because
    936 /// the mapRequired() method calls may not be in the same order
    937 /// as the keys in the document.
    938 ///
    939 class Input : public IO {
    940 public:
    941   // Construct a yaml Input object from a StringRef and optional
    942   // user-data. The DiagHandler can be specified to provide
    943   // alternative error reporting.
    944   Input(StringRef InputContent,
    945         void *Ctxt = nullptr,
    946         SourceMgr::DiagHandlerTy DiagHandler = nullptr,
    947         void *DiagHandlerCtxt = nullptr);
    948   ~Input() override;
    949 
    950   // Check if there was an syntax or semantic error during parsing.
    951   std::error_code error();
    952 
    953 private:
    954   bool outputting() override;
    955   bool mapTag(StringRef, bool) override;
    956   void beginMapping() override;
    957   void endMapping() override;
    958   bool preflightKey(const char *, bool, bool, bool &, void *&) override;
    959   void postflightKey(void *) override;
    960   void beginFlowMapping() override;
    961   void endFlowMapping() override;
    962   unsigned beginSequence() override;
    963   void endSequence() override;
    964   bool preflightElement(unsigned index, void *&) override;
    965   void postflightElement(void *) override;
    966   unsigned beginFlowSequence() override;
    967   bool preflightFlowElement(unsigned , void *&) override;
    968   void postflightFlowElement(void *) override;
    969   void endFlowSequence() override;
    970   void beginEnumScalar() override;
    971   bool matchEnumScalar(const char*, bool) override;
    972   bool matchEnumFallback() override;
    973   void endEnumScalar() override;
    974   bool beginBitSetScalar(bool &) override;
    975   bool bitSetMatch(const char *, bool ) override;
    976   void endBitSetScalar() override;
    977   void scalarString(StringRef &, bool) override;
    978   void blockScalarString(StringRef &) override;
    979   void setError(const Twine &message) override;
    980   bool canElideEmptySequence() override;
    981 
    982   class HNode {
    983     virtual void anchor();
    984   public:
    985     HNode(Node *n) : _node(n) { }
    986     virtual ~HNode() { }
    987     static inline bool classof(const HNode *) { return true; }
    988 
    989     Node *_node;
    990   };
    991 
    992   class EmptyHNode : public HNode {
    993     void anchor() override;
    994   public:
    995     EmptyHNode(Node *n) : HNode(n) { }
    996     static inline bool classof(const HNode *n) {
    997       return NullNode::classof(n->_node);
    998     }
    999     static inline bool classof(const EmptyHNode *) { return true; }
   1000   };
   1001 
   1002   class ScalarHNode : public HNode {
   1003     void anchor() override;
   1004   public:
   1005     ScalarHNode(Node *n, StringRef s) : HNode(n), _value(s) { }
   1006 
   1007     StringRef value() const { return _value; }
   1008 
   1009     static inline bool classof(const HNode *n) {
   1010       return ScalarNode::classof(n->_node) ||
   1011              BlockScalarNode::classof(n->_node);
   1012     }
   1013     static inline bool classof(const ScalarHNode *) { return true; }
   1014   protected:
   1015     StringRef _value;
   1016   };
   1017 
   1018   class MapHNode : public HNode {
   1019     void anchor() override;
   1020 
   1021   public:
   1022     MapHNode(Node *n) : HNode(n) { }
   1023 
   1024     static inline bool classof(const HNode *n) {
   1025       return MappingNode::classof(n->_node);
   1026     }
   1027     static inline bool classof(const MapHNode *) { return true; }
   1028 
   1029     typedef llvm::StringMap<std::unique_ptr<HNode>> NameToNode;
   1030 
   1031     bool isValidKey(StringRef key);
   1032 
   1033     NameToNode                        Mapping;
   1034     llvm::SmallVector<const char*, 6> ValidKeys;
   1035   };
   1036 
   1037   class SequenceHNode : public HNode {
   1038     void anchor() override;
   1039 
   1040   public:
   1041     SequenceHNode(Node *n) : HNode(n) { }
   1042 
   1043     static inline bool classof(const HNode *n) {
   1044       return SequenceNode::classof(n->_node);
   1045     }
   1046     static inline bool classof(const SequenceHNode *) { return true; }
   1047 
   1048     std::vector<std::unique_ptr<HNode>> Entries;
   1049   };
   1050 
   1051   std::unique_ptr<Input::HNode> createHNodes(Node *node);
   1052   void setError(HNode *hnode, const Twine &message);
   1053   void setError(Node *node, const Twine &message);
   1054 
   1055 public:
   1056   // These are only used by operator>>. They could be private
   1057   // if those templated things could be made friends.
   1058   bool setCurrentDocument();
   1059   bool nextDocument();
   1060 
   1061   /// Returns the current node that's being parsed by the YAML Parser.
   1062   const Node *getCurrentNode() const;
   1063 
   1064 private:
   1065   llvm::SourceMgr                     SrcMgr; // must be before Strm
   1066   std::unique_ptr<llvm::yaml::Stream> Strm;
   1067   std::unique_ptr<HNode>              TopNode;
   1068   std::error_code                     EC;
   1069   llvm::BumpPtrAllocator              StringAllocator;
   1070   llvm::yaml::document_iterator       DocIterator;
   1071   std::vector<bool>                   BitValuesUsed;
   1072   HNode                              *CurrentNode;
   1073   bool                                ScalarMatchFound;
   1074 };
   1075 
   1076 ///
   1077 /// The Output class is used to generate a yaml document from in-memory structs
   1078 /// and vectors.
   1079 ///
   1080 class Output : public IO {
   1081 public:
   1082   Output(llvm::raw_ostream &, void *Ctxt = nullptr, int WrapColumn = 70);
   1083   ~Output() override;
   1084 
   1085   bool outputting() override;
   1086   bool mapTag(StringRef, bool) override;
   1087   void beginMapping() override;
   1088   void endMapping() override;
   1089   bool preflightKey(const char *key, bool, bool, bool &, void *&) override;
   1090   void postflightKey(void *) override;
   1091   void beginFlowMapping() override;
   1092   void endFlowMapping() override;
   1093   unsigned beginSequence() override;
   1094   void endSequence() override;
   1095   bool preflightElement(unsigned, void *&) override;
   1096   void postflightElement(void *) override;
   1097   unsigned beginFlowSequence() override;
   1098   bool preflightFlowElement(unsigned, void *&) override;
   1099   void postflightFlowElement(void *) override;
   1100   void endFlowSequence() override;
   1101   void beginEnumScalar() override;
   1102   bool matchEnumScalar(const char*, bool) override;
   1103   bool matchEnumFallback() override;
   1104   void endEnumScalar() override;
   1105   bool beginBitSetScalar(bool &) override;
   1106   bool bitSetMatch(const char *, bool ) override;
   1107   void endBitSetScalar() override;
   1108   void scalarString(StringRef &, bool) override;
   1109   void blockScalarString(StringRef &) override;
   1110   void setError(const Twine &message) override;
   1111   bool canElideEmptySequence() override;
   1112 public:
   1113   // These are only used by operator<<. They could be private
   1114   // if that templated operator could be made a friend.
   1115   void beginDocuments();
   1116   bool preflightDocument(unsigned);
   1117   void postflightDocument();
   1118   void endDocuments();
   1119 
   1120 private:
   1121   void output(StringRef s);
   1122   void outputUpToEndOfLine(StringRef s);
   1123   void newLineCheck();
   1124   void outputNewLine();
   1125   void paddedKey(StringRef key);
   1126   void flowKey(StringRef Key);
   1127 
   1128   enum InState {
   1129     inSeq,
   1130     inFlowSeq,
   1131     inMapFirstKey,
   1132     inMapOtherKey,
   1133     inFlowMapFirstKey,
   1134     inFlowMapOtherKey
   1135   };
   1136 
   1137   llvm::raw_ostream       &Out;
   1138   int                      WrapColumn;
   1139   SmallVector<InState, 8>  StateStack;
   1140   int                      Column;
   1141   int                      ColumnAtFlowStart;
   1142   int                      ColumnAtMapFlowStart;
   1143   bool                     NeedBitValueComma;
   1144   bool                     NeedFlowSequenceComma;
   1145   bool                     EnumerationMatchFound;
   1146   bool                     NeedsNewLine;
   1147 };
   1148 
   1149 /// YAML I/O does conversion based on types. But often native data types
   1150 /// are just a typedef of built in intergral types (e.g. int).  But the C++
   1151 /// type matching system sees through the typedef and all the typedefed types
   1152 /// look like a built in type. This will cause the generic YAML I/O conversion
   1153 /// to be used. To provide better control over the YAML conversion, you can
   1154 /// use this macro instead of typedef.  It will create a class with one field
   1155 /// and automatic conversion operators to and from the base type.
   1156 /// Based on BOOST_STRONG_TYPEDEF
   1157 #define LLVM_YAML_STRONG_TYPEDEF(_base, _type)                                 \
   1158     struct _type {                                                             \
   1159         _type() { }                                                            \
   1160         _type(const _base v) : value(v) { }                                    \
   1161         _type(const _type &v) : value(v.value) {}                              \
   1162         _type &operator=(const _type &rhs) { value = rhs.value; return *this; }\
   1163         _type &operator=(const _base &rhs) { value = rhs; return *this; }      \
   1164         operator const _base & () const { return value; }                      \
   1165         bool operator==(const _type &rhs) const { return value == rhs.value; } \
   1166         bool operator==(const _base &rhs) const { return value == rhs; }       \
   1167         bool operator<(const _type &rhs) const { return value < rhs.value; }   \
   1168         _base value;                                                           \
   1169     };
   1170 
   1171 ///
   1172 /// Use these types instead of uintXX_t in any mapping to have
   1173 /// its yaml output formatted as hexadecimal.
   1174 ///
   1175 LLVM_YAML_STRONG_TYPEDEF(uint8_t, Hex8)
   1176 LLVM_YAML_STRONG_TYPEDEF(uint16_t, Hex16)
   1177 LLVM_YAML_STRONG_TYPEDEF(uint32_t, Hex32)
   1178 LLVM_YAML_STRONG_TYPEDEF(uint64_t, Hex64)
   1179 
   1180 template<>
   1181 struct ScalarTraits<Hex8> {
   1182   static void output(const Hex8 &, void*, llvm::raw_ostream &);
   1183   static StringRef input(StringRef, void*, Hex8 &);
   1184   static bool mustQuote(StringRef) { return false; }
   1185 };
   1186 
   1187 template<>
   1188 struct ScalarTraits<Hex16> {
   1189   static void output(const Hex16 &, void*, llvm::raw_ostream &);
   1190   static StringRef input(StringRef, void*, Hex16 &);
   1191   static bool mustQuote(StringRef) { return false; }
   1192 };
   1193 
   1194 template<>
   1195 struct ScalarTraits<Hex32> {
   1196   static void output(const Hex32 &, void*, llvm::raw_ostream &);
   1197   static StringRef input(StringRef, void*, Hex32 &);
   1198   static bool mustQuote(StringRef) { return false; }
   1199 };
   1200 
   1201 template<>
   1202 struct ScalarTraits<Hex64> {
   1203   static void output(const Hex64 &, void*, llvm::raw_ostream &);
   1204   static StringRef input(StringRef, void*, Hex64 &);
   1205   static bool mustQuote(StringRef) { return false; }
   1206 };
   1207 
   1208 // Define non-member operator>> so that Input can stream in a document list.
   1209 template <typename T>
   1210 inline
   1211 typename std::enable_if<has_DocumentListTraits<T>::value, Input &>::type
   1212 operator>>(Input &yin, T &docList) {
   1213   int i = 0;
   1214   while ( yin.setCurrentDocument() ) {
   1215     yamlize(yin, DocumentListTraits<T>::element(yin, docList, i), true);
   1216     if ( yin.error() )
   1217       return yin;
   1218     yin.nextDocument();
   1219     ++i;
   1220   }
   1221   return yin;
   1222 }
   1223 
   1224 // Define non-member operator>> so that Input can stream in a map as a document.
   1225 template <typename T>
   1226 inline
   1227 typename std::enable_if<has_MappingTraits<T>::value, Input &>::type
   1228 operator>>(Input &yin, T &docMap) {
   1229   yin.setCurrentDocument();
   1230   yamlize(yin, docMap, true);
   1231   return yin;
   1232 }
   1233 
   1234 // Define non-member operator>> so that Input can stream in a sequence as
   1235 // a document.
   1236 template <typename T>
   1237 inline
   1238 typename std::enable_if<has_SequenceTraits<T>::value, Input &>::type
   1239 operator>>(Input &yin, T &docSeq) {
   1240   if (yin.setCurrentDocument())
   1241     yamlize(yin, docSeq, true);
   1242   return yin;
   1243 }
   1244 
   1245 // Define non-member operator>> so that Input can stream in a block scalar.
   1246 template <typename T>
   1247 inline
   1248 typename std::enable_if<has_BlockScalarTraits<T>::value, Input &>::type
   1249 operator>>(Input &In, T &Val) {
   1250   if (In.setCurrentDocument())
   1251     yamlize(In, Val, true);
   1252   return In;
   1253 }
   1254 
   1255 // Provide better error message about types missing a trait specialization
   1256 template <typename T>
   1257 inline
   1258 typename std::enable_if<missingTraits<T>::value, Input &>::type
   1259 operator>>(Input &yin, T &docSeq) {
   1260   char missing_yaml_trait_for_type[sizeof(MissingTrait<T>)];
   1261   return yin;
   1262 }
   1263 
   1264 // Define non-member operator<< so that Output can stream out document list.
   1265 template <typename T>
   1266 inline
   1267 typename std::enable_if<has_DocumentListTraits<T>::value, Output &>::type
   1268 operator<<(Output &yout, T &docList) {
   1269   yout.beginDocuments();
   1270   const size_t count = DocumentListTraits<T>::size(yout, docList);
   1271   for(size_t i=0; i < count; ++i) {
   1272     if ( yout.preflightDocument(i) ) {
   1273       yamlize(yout, DocumentListTraits<T>::element(yout, docList, i), true);
   1274       yout.postflightDocument();
   1275     }
   1276   }
   1277   yout.endDocuments();
   1278   return yout;
   1279 }
   1280 
   1281 // Define non-member operator<< so that Output can stream out a map.
   1282 template <typename T>
   1283 inline
   1284 typename std::enable_if<has_MappingTraits<T>::value, Output &>::type
   1285 operator<<(Output &yout, T &map) {
   1286   yout.beginDocuments();
   1287   if ( yout.preflightDocument(0) ) {
   1288     yamlize(yout, map, true);
   1289     yout.postflightDocument();
   1290   }
   1291   yout.endDocuments();
   1292   return yout;
   1293 }
   1294 
   1295 // Define non-member operator<< so that Output can stream out a sequence.
   1296 template <typename T>
   1297 inline
   1298 typename std::enable_if<has_SequenceTraits<T>::value, Output &>::type
   1299 operator<<(Output &yout, T &seq) {
   1300   yout.beginDocuments();
   1301   if ( yout.preflightDocument(0) ) {
   1302     yamlize(yout, seq, true);
   1303     yout.postflightDocument();
   1304   }
   1305   yout.endDocuments();
   1306   return yout;
   1307 }
   1308 
   1309 // Define non-member operator<< so that Output can stream out a block scalar.
   1310 template <typename T>
   1311 inline
   1312 typename std::enable_if<has_BlockScalarTraits<T>::value, Output &>::type
   1313 operator<<(Output &Out, T &Val) {
   1314   Out.beginDocuments();
   1315   if (Out.preflightDocument(0)) {
   1316     yamlize(Out, Val, true);
   1317     Out.postflightDocument();
   1318   }
   1319   Out.endDocuments();
   1320   return Out;
   1321 }
   1322 
   1323 // Provide better error message about types missing a trait specialization
   1324 template <typename T>
   1325 inline
   1326 typename std::enable_if<missingTraits<T>::value, Output &>::type
   1327 operator<<(Output &yout, T &seq) {
   1328   char missing_yaml_trait_for_type[sizeof(MissingTrait<T>)];
   1329   return yout;
   1330 }
   1331 
   1332 } // namespace yaml
   1333 } // namespace llvm
   1334 
   1335 /// Utility for declaring that a std::vector of a particular type
   1336 /// should be considered a YAML sequence.
   1337 #define LLVM_YAML_IS_SEQUENCE_VECTOR(_type)                                 \
   1338   namespace llvm {                                                          \
   1339   namespace yaml {                                                          \
   1340     template<>                                                              \
   1341     struct SequenceTraits< std::vector<_type> > {                           \
   1342       static size_t size(IO &io, std::vector<_type> &seq) {                 \
   1343         return seq.size();                                                  \
   1344       }                                                                     \
   1345       static _type& element(IO &io, std::vector<_type> &seq, size_t index) {\
   1346         if ( index >= seq.size() )                                          \
   1347           seq.resize(index+1);                                              \
   1348         return seq[index];                                                  \
   1349       }                                                                     \
   1350     };                                                                      \
   1351   }                                                                         \
   1352   }
   1353 
   1354 /// Utility for declaring that a std::vector of a particular type
   1355 /// should be considered a YAML flow sequence.
   1356 #define LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(_type)                            \
   1357   namespace llvm {                                                          \
   1358   namespace yaml {                                                          \
   1359     template<>                                                              \
   1360     struct SequenceTraits< std::vector<_type> > {                           \
   1361       static size_t size(IO &io, std::vector<_type> &seq) {                 \
   1362         return seq.size();                                                  \
   1363       }                                                                     \
   1364       static _type& element(IO &io, std::vector<_type> &seq, size_t index) {\
   1365         (void)flow; /* Remove this workaround after PR17897 is fixed */     \
   1366         if ( index >= seq.size() )                                          \
   1367           seq.resize(index+1);                                              \
   1368         return seq[index];                                                  \
   1369       }                                                                     \
   1370       static const bool flow = true;                                        \
   1371     };                                                                      \
   1372   }                                                                         \
   1373   }
   1374 
   1375 /// Utility for declaring that a std::vector of a particular type
   1376 /// should be considered a YAML document list.
   1377 #define LLVM_YAML_IS_DOCUMENT_LIST_VECTOR(_type)                            \
   1378   namespace llvm {                                                          \
   1379   namespace yaml {                                                          \
   1380     template<>                                                              \
   1381     struct DocumentListTraits< std::vector<_type> > {                       \
   1382       static size_t size(IO &io, std::vector<_type> &seq) {                 \
   1383         return seq.size();                                                  \
   1384       }                                                                     \
   1385       static _type& element(IO &io, std::vector<_type> &seq, size_t index) {\
   1386         if ( index >= seq.size() )                                          \
   1387           seq.resize(index+1);                                              \
   1388         return seq[index];                                                  \
   1389       }                                                                     \
   1390     };                                                                      \
   1391   }                                                                         \
   1392   }
   1393 
   1394 #endif // LLVM_SUPPORT_YAMLTRAITS_H
   1395