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