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