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 void endEnumScalar() = 0;
    451 
    452   virtual bool beginBitSetScalar(bool &) = 0;
    453   virtual bool bitSetMatch(const char*, bool) = 0;
    454   virtual void endBitSetScalar() = 0;
    455 
    456   virtual void scalarString(StringRef &, bool) = 0;
    457 
    458   virtual void setError(const Twine &) = 0;
    459 
    460   template <typename T>
    461   void enumCase(T &Val, const char* Str, const T ConstVal) {
    462     if ( matchEnumScalar(Str, outputting() && Val == ConstVal) ) {
    463       Val = ConstVal;
    464     }
    465   }
    466 
    467   // allow anonymous enum values to be used with LLVM_YAML_STRONG_TYPEDEF
    468   template <typename T>
    469   void enumCase(T &Val, const char* Str, const uint32_t ConstVal) {
    470     if ( matchEnumScalar(Str, outputting() && Val == static_cast<T>(ConstVal)) ) {
    471       Val = ConstVal;
    472     }
    473   }
    474 
    475   template <typename T>
    476   void bitSetCase(T &Val, const char* Str, const T ConstVal) {
    477     if ( bitSetMatch(Str, outputting() && (Val & ConstVal) == ConstVal) ) {
    478       Val = Val | ConstVal;
    479     }
    480   }
    481 
    482   // allow anonymous enum values to be used with LLVM_YAML_STRONG_TYPEDEF
    483   template <typename T>
    484   void bitSetCase(T &Val, const char* Str, const uint32_t ConstVal) {
    485     if ( bitSetMatch(Str, outputting() && (Val & ConstVal) == ConstVal) ) {
    486       Val = Val | ConstVal;
    487     }
    488   }
    489 
    490   template <typename T>
    491   void maskedBitSetCase(T &Val, const char *Str, T ConstVal, T Mask) {
    492     if (bitSetMatch(Str, outputting() && (Val & Mask) == ConstVal))
    493       Val = Val | ConstVal;
    494   }
    495 
    496   template <typename T>
    497   void maskedBitSetCase(T &Val, const char *Str, uint32_t ConstVal,
    498                         uint32_t Mask) {
    499     if (bitSetMatch(Str, outputting() && (Val & Mask) == ConstVal))
    500       Val = Val | ConstVal;
    501   }
    502 
    503   void *getContext();
    504   void setContext(void *);
    505 
    506   template <typename T>
    507   void mapRequired(const char* Key, T& Val) {
    508     this->processKey(Key, Val, true);
    509   }
    510 
    511   template <typename T>
    512   typename std::enable_if<has_SequenceTraits<T>::value,void>::type
    513   mapOptional(const char* Key, T& Val) {
    514     // omit key/value instead of outputting empty sequence
    515     if ( this->canElideEmptySequence() && !(Val.begin() != Val.end()) )
    516       return;
    517     this->processKey(Key, Val, false);
    518   }
    519 
    520   template <typename T>
    521   void mapOptional(const char* Key, Optional<T> &Val) {
    522     processKeyWithDefault(Key, Val, Optional<T>(), /*Required=*/false);
    523   }
    524 
    525   template <typename T>
    526   typename std::enable_if<!has_SequenceTraits<T>::value,void>::type
    527   mapOptional(const char* Key, T& Val) {
    528     this->processKey(Key, Val, false);
    529   }
    530 
    531   template <typename T>
    532   void mapOptional(const char* Key, T& Val, const T& Default) {
    533     this->processKeyWithDefault(Key, Val, Default, false);
    534   }
    535 
    536 private:
    537   template <typename T>
    538   void processKeyWithDefault(const char *Key, Optional<T> &Val,
    539                              const Optional<T> &DefaultValue, bool Required) {
    540     assert(DefaultValue.hasValue() == false &&
    541            "Optional<T> shouldn't have a value!");
    542     void *SaveInfo;
    543     bool UseDefault;
    544     const bool sameAsDefault = outputting() && !Val.hasValue();
    545     if (!outputting() && !Val.hasValue())
    546       Val = T();
    547     if (this->preflightKey(Key, Required, sameAsDefault, UseDefault,
    548                            SaveInfo)) {
    549       yamlize(*this, Val.getValue(), Required);
    550       this->postflightKey(SaveInfo);
    551     } else {
    552       if (UseDefault)
    553         Val = DefaultValue;
    554     }
    555   }
    556 
    557   template <typename T>
    558   void processKeyWithDefault(const char *Key, T &Val, const T& DefaultValue,
    559                                                                 bool Required) {
    560     void *SaveInfo;
    561     bool UseDefault;
    562     const bool sameAsDefault = outputting() && Val == DefaultValue;
    563     if ( this->preflightKey(Key, Required, sameAsDefault, UseDefault,
    564                                                                   SaveInfo) ) {
    565       yamlize(*this, Val, Required);
    566       this->postflightKey(SaveInfo);
    567     }
    568     else {
    569       if ( UseDefault )
    570         Val = DefaultValue;
    571     }
    572   }
    573 
    574   template <typename T>
    575   void processKey(const char *Key, T &Val, bool Required) {
    576     void *SaveInfo;
    577     bool UseDefault;
    578     if ( this->preflightKey(Key, Required, false, UseDefault, SaveInfo) ) {
    579       yamlize(*this, Val, Required);
    580       this->postflightKey(SaveInfo);
    581     }
    582   }
    583 
    584 private:
    585   void  *Ctxt;
    586 };
    587 
    588 
    589 
    590 template<typename T>
    591 typename std::enable_if<has_ScalarEnumerationTraits<T>::value,void>::type
    592 yamlize(IO &io, T &Val, bool) {
    593   io.beginEnumScalar();
    594   ScalarEnumerationTraits<T>::enumeration(io, Val);
    595   io.endEnumScalar();
    596 }
    597 
    598 template<typename T>
    599 typename std::enable_if<has_ScalarBitSetTraits<T>::value,void>::type
    600 yamlize(IO &io, T &Val, bool) {
    601   bool DoClear;
    602   if ( io.beginBitSetScalar(DoClear) ) {
    603     if ( DoClear )
    604       Val = static_cast<T>(0);
    605     ScalarBitSetTraits<T>::bitset(io, Val);
    606     io.endBitSetScalar();
    607   }
    608 }
    609 
    610 
    611 template<typename T>
    612 typename std::enable_if<has_ScalarTraits<T>::value,void>::type
    613 yamlize(IO &io, T &Val, bool) {
    614   if ( io.outputting() ) {
    615     std::string Storage;
    616     llvm::raw_string_ostream Buffer(Storage);
    617     ScalarTraits<T>::output(Val, io.getContext(), Buffer);
    618     StringRef Str = Buffer.str();
    619     io.scalarString(Str, ScalarTraits<T>::mustQuote(Str));
    620   }
    621   else {
    622     StringRef Str;
    623     io.scalarString(Str, ScalarTraits<T>::mustQuote(Str));
    624     StringRef Result = ScalarTraits<T>::input(Str, io.getContext(), Val);
    625     if ( !Result.empty() ) {
    626       io.setError(llvm::Twine(Result));
    627     }
    628   }
    629 }
    630 
    631 
    632 template<typename T>
    633 typename std::enable_if<validatedMappingTraits<T>::value, void>::type
    634 yamlize(IO &io, T &Val, bool) {
    635   io.beginMapping();
    636   if (io.outputting()) {
    637     StringRef Err = MappingTraits<T>::validate(io, Val);
    638     if (!Err.empty()) {
    639       llvm::errs() << Err << "\n";
    640       assert(Err.empty() && "invalid struct trying to be written as yaml");
    641     }
    642   }
    643   MappingTraits<T>::mapping(io, Val);
    644   if (!io.outputting()) {
    645     StringRef Err = MappingTraits<T>::validate(io, Val);
    646     if (!Err.empty())
    647       io.setError(Err);
    648   }
    649   io.endMapping();
    650 }
    651 
    652 template<typename T>
    653 typename std::enable_if<unvalidatedMappingTraits<T>::value, void>::type
    654 yamlize(IO &io, T &Val, bool) {
    655   io.beginMapping();
    656   MappingTraits<T>::mapping(io, Val);
    657   io.endMapping();
    658 }
    659 
    660 template<typename T>
    661 typename std::enable_if<missingTraits<T>::value, void>::type
    662 yamlize(IO &io, T &Val, bool) {
    663   char missing_yaml_trait_for_type[sizeof(MissingTrait<T>)];
    664 }
    665 
    666 template<typename T>
    667 typename std::enable_if<has_SequenceTraits<T>::value,void>::type
    668 yamlize(IO &io, T &Seq, bool) {
    669   if ( has_FlowTraits< SequenceTraits<T> >::value ) {
    670     unsigned incnt = io.beginFlowSequence();
    671     unsigned count = io.outputting() ? SequenceTraits<T>::size(io, Seq) : incnt;
    672     for(unsigned i=0; i < count; ++i) {
    673       void *SaveInfo;
    674       if ( io.preflightFlowElement(i, SaveInfo) ) {
    675         yamlize(io, SequenceTraits<T>::element(io, Seq, i), true);
    676         io.postflightFlowElement(SaveInfo);
    677       }
    678     }
    679     io.endFlowSequence();
    680   }
    681   else {
    682     unsigned incnt = io.beginSequence();
    683     unsigned count = io.outputting() ? SequenceTraits<T>::size(io, Seq) : incnt;
    684     for(unsigned i=0; i < count; ++i) {
    685       void *SaveInfo;
    686       if ( io.preflightElement(i, SaveInfo) ) {
    687         yamlize(io, SequenceTraits<T>::element(io, Seq, i), true);
    688         io.postflightElement(SaveInfo);
    689       }
    690     }
    691     io.endSequence();
    692   }
    693 }
    694 
    695 
    696 template<>
    697 struct ScalarTraits<bool> {
    698   static void output(const bool &, void*, llvm::raw_ostream &);
    699   static StringRef input(StringRef, void*, bool &);
    700   static bool mustQuote(StringRef) { return false; }
    701 };
    702 
    703 template<>
    704 struct ScalarTraits<StringRef> {
    705   static void output(const StringRef &, void*, llvm::raw_ostream &);
    706   static StringRef input(StringRef, void*, StringRef &);
    707   static bool mustQuote(StringRef S) { return needsQuotes(S); }
    708 };
    709 
    710 template<>
    711 struct ScalarTraits<std::string> {
    712   static void output(const std::string &, void*, llvm::raw_ostream &);
    713   static StringRef input(StringRef, void*, std::string &);
    714   static bool mustQuote(StringRef S) { return needsQuotes(S); }
    715 };
    716 
    717 template<>
    718 struct ScalarTraits<uint8_t> {
    719   static void output(const uint8_t &, void*, llvm::raw_ostream &);
    720   static StringRef input(StringRef, void*, uint8_t &);
    721   static bool mustQuote(StringRef) { return false; }
    722 };
    723 
    724 template<>
    725 struct ScalarTraits<uint16_t> {
    726   static void output(const uint16_t &, void*, llvm::raw_ostream &);
    727   static StringRef input(StringRef, void*, uint16_t &);
    728   static bool mustQuote(StringRef) { return false; }
    729 };
    730 
    731 template<>
    732 struct ScalarTraits<uint32_t> {
    733   static void output(const uint32_t &, void*, llvm::raw_ostream &);
    734   static StringRef input(StringRef, void*, uint32_t &);
    735   static bool mustQuote(StringRef) { return false; }
    736 };
    737 
    738 template<>
    739 struct ScalarTraits<uint64_t> {
    740   static void output(const uint64_t &, void*, llvm::raw_ostream &);
    741   static StringRef input(StringRef, void*, uint64_t &);
    742   static bool mustQuote(StringRef) { return false; }
    743 };
    744 
    745 template<>
    746 struct ScalarTraits<int8_t> {
    747   static void output(const int8_t &, void*, llvm::raw_ostream &);
    748   static StringRef input(StringRef, void*, int8_t &);
    749   static bool mustQuote(StringRef) { return false; }
    750 };
    751 
    752 template<>
    753 struct ScalarTraits<int16_t> {
    754   static void output(const int16_t &, void*, llvm::raw_ostream &);
    755   static StringRef input(StringRef, void*, int16_t &);
    756   static bool mustQuote(StringRef) { return false; }
    757 };
    758 
    759 template<>
    760 struct ScalarTraits<int32_t> {
    761   static void output(const int32_t &, void*, llvm::raw_ostream &);
    762   static StringRef input(StringRef, void*, int32_t &);
    763   static bool mustQuote(StringRef) { return false; }
    764 };
    765 
    766 template<>
    767 struct ScalarTraits<int64_t> {
    768   static void output(const int64_t &, void*, llvm::raw_ostream &);
    769   static StringRef input(StringRef, void*, int64_t &);
    770   static bool mustQuote(StringRef) { return false; }
    771 };
    772 
    773 template<>
    774 struct ScalarTraits<float> {
    775   static void output(const float &, void*, llvm::raw_ostream &);
    776   static StringRef input(StringRef, void*, float &);
    777   static bool mustQuote(StringRef) { return false; }
    778 };
    779 
    780 template<>
    781 struct ScalarTraits<double> {
    782   static void output(const double &, void*, llvm::raw_ostream &);
    783   static StringRef input(StringRef, void*, double &);
    784   static bool mustQuote(StringRef) { return false; }
    785 };
    786 
    787 
    788 
    789 // Utility for use within MappingTraits<>::mapping() method
    790 // to [de]normalize an object for use with YAML conversion.
    791 template <typename TNorm, typename TFinal>
    792 struct MappingNormalization {
    793   MappingNormalization(IO &i_o, TFinal &Obj)
    794       : io(i_o), BufPtr(nullptr), Result(Obj) {
    795     if ( io.outputting() ) {
    796       BufPtr = new (&Buffer) TNorm(io, Obj);
    797     }
    798     else {
    799       BufPtr = new (&Buffer) TNorm(io);
    800     }
    801   }
    802 
    803   ~MappingNormalization() {
    804     if ( ! io.outputting() ) {
    805       Result = BufPtr->denormalize(io);
    806     }
    807     BufPtr->~TNorm();
    808   }
    809 
    810   TNorm* operator->() { return BufPtr; }
    811 
    812 private:
    813   typedef llvm::AlignedCharArrayUnion<TNorm> Storage;
    814 
    815   Storage       Buffer;
    816   IO           &io;
    817   TNorm        *BufPtr;
    818   TFinal       &Result;
    819 };
    820 
    821 
    822 
    823 // Utility for use within MappingTraits<>::mapping() method
    824 // to [de]normalize an object for use with YAML conversion.
    825 template <typename TNorm, typename TFinal>
    826 struct MappingNormalizationHeap {
    827   MappingNormalizationHeap(IO &i_o, TFinal &Obj)
    828     : io(i_o), BufPtr(NULL), Result(Obj) {
    829     if ( io.outputting() ) {
    830       BufPtr = new (&Buffer) TNorm(io, Obj);
    831     }
    832     else {
    833       BufPtr = new TNorm(io);
    834     }
    835   }
    836 
    837   ~MappingNormalizationHeap() {
    838     if ( io.outputting() ) {
    839       BufPtr->~TNorm();
    840     }
    841     else {
    842       Result = BufPtr->denormalize(io);
    843     }
    844   }
    845 
    846   TNorm* operator->() { return BufPtr; }
    847 
    848 private:
    849   typedef llvm::AlignedCharArrayUnion<TNorm> Storage;
    850 
    851   Storage       Buffer;
    852   IO           &io;
    853   TNorm        *BufPtr;
    854   TFinal       &Result;
    855 };
    856 
    857 
    858 
    859 ///
    860 /// The Input class is used to parse a yaml document into in-memory structs
    861 /// and vectors.
    862 ///
    863 /// It works by using YAMLParser to do a syntax parse of the entire yaml
    864 /// document, then the Input class builds a graph of HNodes which wraps
    865 /// each yaml Node.  The extra layer is buffering.  The low level yaml
    866 /// parser only lets you look at each node once.  The buffering layer lets
    867 /// you search and interate multiple times.  This is necessary because
    868 /// the mapRequired() method calls may not be in the same order
    869 /// as the keys in the document.
    870 ///
    871 class Input : public IO {
    872 public:
    873   // Construct a yaml Input object from a StringRef and optional
    874   // user-data. The DiagHandler can be specified to provide
    875   // alternative error reporting.
    876   Input(StringRef InputContent,
    877         void *Ctxt = nullptr,
    878         SourceMgr::DiagHandlerTy DiagHandler = nullptr,
    879         void *DiagHandlerCtxt = nullptr);
    880   ~Input();
    881 
    882   // Check if there was an syntax or semantic error during parsing.
    883   std::error_code error();
    884 
    885 private:
    886   bool outputting() override;
    887   bool mapTag(StringRef, bool) override;
    888   void beginMapping() override;
    889   void endMapping() override;
    890   bool preflightKey(const char *, bool, bool, bool &, void *&) override;
    891   void postflightKey(void *) override;
    892   unsigned beginSequence() override;
    893   void endSequence() override;
    894   bool preflightElement(unsigned index, void *&) override;
    895   void postflightElement(void *) override;
    896   unsigned beginFlowSequence() override;
    897   bool preflightFlowElement(unsigned , void *&) override;
    898   void postflightFlowElement(void *) override;
    899   void endFlowSequence() override;
    900   void beginEnumScalar() override;
    901   bool matchEnumScalar(const char*, bool) override;
    902   void endEnumScalar() override;
    903   bool beginBitSetScalar(bool &) override;
    904   bool bitSetMatch(const char *, bool ) override;
    905   void endBitSetScalar() override;
    906   void scalarString(StringRef &, bool) override;
    907   void setError(const Twine &message) override;
    908   bool canElideEmptySequence() override;
    909 
    910   class HNode {
    911     virtual void anchor();
    912   public:
    913     HNode(Node *n) : _node(n) { }
    914     virtual ~HNode() { }
    915     static inline bool classof(const HNode *) { return true; }
    916 
    917     Node *_node;
    918   };
    919 
    920   class EmptyHNode : public HNode {
    921     void anchor() override;
    922   public:
    923     EmptyHNode(Node *n) : HNode(n) { }
    924     static inline bool classof(const HNode *n) {
    925       return NullNode::classof(n->_node);
    926     }
    927     static inline bool classof(const EmptyHNode *) { return true; }
    928   };
    929 
    930   class ScalarHNode : public HNode {
    931     void anchor() override;
    932   public:
    933     ScalarHNode(Node *n, StringRef s) : HNode(n), _value(s) { }
    934 
    935     StringRef value() const { return _value; }
    936 
    937     static inline bool classof(const HNode *n) {
    938       return ScalarNode::classof(n->_node);
    939     }
    940     static inline bool classof(const ScalarHNode *) { return true; }
    941   protected:
    942     StringRef _value;
    943   };
    944 
    945   class MapHNode : public HNode {
    946   public:
    947     MapHNode(Node *n) : HNode(n) { }
    948     virtual ~MapHNode();
    949 
    950     static inline bool classof(const HNode *n) {
    951       return MappingNode::classof(n->_node);
    952     }
    953     static inline bool classof(const MapHNode *) { return true; }
    954 
    955     typedef llvm::StringMap<HNode*> NameToNode;
    956 
    957     bool isValidKey(StringRef key);
    958 
    959     NameToNode                        Mapping;
    960     llvm::SmallVector<const char*, 6> ValidKeys;
    961   };
    962 
    963   class SequenceHNode : public HNode {
    964   public:
    965     SequenceHNode(Node *n) : HNode(n) { }
    966     virtual ~SequenceHNode();
    967 
    968     static inline bool classof(const HNode *n) {
    969       return SequenceNode::classof(n->_node);
    970     }
    971     static inline bool classof(const SequenceHNode *) { return true; }
    972 
    973     std::vector<HNode*> Entries;
    974   };
    975 
    976   Input::HNode *createHNodes(Node *node);
    977   void setError(HNode *hnode, const Twine &message);
    978   void setError(Node *node, const Twine &message);
    979 
    980 
    981 public:
    982   // These are only used by operator>>. They could be private
    983   // if those templated things could be made friends.
    984   bool setCurrentDocument();
    985   bool nextDocument();
    986 
    987 private:
    988   llvm::SourceMgr                     SrcMgr; // must be before Strm
    989   std::unique_ptr<llvm::yaml::Stream> Strm;
    990   std::unique_ptr<HNode>              TopNode;
    991   std::error_code                     EC;
    992   llvm::BumpPtrAllocator              StringAllocator;
    993   llvm::yaml::document_iterator       DocIterator;
    994   std::vector<bool>                   BitValuesUsed;
    995   HNode                              *CurrentNode;
    996   bool                                ScalarMatchFound;
    997 };
    998 
    999 
   1000 
   1001 
   1002 ///
   1003 /// The Output class is used to generate a yaml document from in-memory structs
   1004 /// and vectors.
   1005 ///
   1006 class Output : public IO {
   1007 public:
   1008   Output(llvm::raw_ostream &, void *Ctxt=nullptr);
   1009   virtual ~Output();
   1010 
   1011   bool outputting() override;
   1012   bool mapTag(StringRef, bool) override;
   1013   void beginMapping() override;
   1014   void endMapping() override;
   1015   bool preflightKey(const char *key, bool, bool, bool &, void *&) override;
   1016   void postflightKey(void *) override;
   1017   unsigned beginSequence() override;
   1018   void endSequence() override;
   1019   bool preflightElement(unsigned, void *&) override;
   1020   void postflightElement(void *) override;
   1021   unsigned beginFlowSequence() override;
   1022   bool preflightFlowElement(unsigned, void *&) override;
   1023   void postflightFlowElement(void *) override;
   1024   void endFlowSequence() override;
   1025   void beginEnumScalar() override;
   1026   bool matchEnumScalar(const char*, bool) override;
   1027   void endEnumScalar() override;
   1028   bool beginBitSetScalar(bool &) override;
   1029   bool bitSetMatch(const char *, bool ) override;
   1030   void endBitSetScalar() override;
   1031   void scalarString(StringRef &, bool) override;
   1032   void setError(const Twine &message) override;
   1033   bool canElideEmptySequence() override;
   1034 public:
   1035   // These are only used by operator<<. They could be private
   1036   // if that templated operator could be made a friend.
   1037   void beginDocuments();
   1038   bool preflightDocument(unsigned);
   1039   void postflightDocument();
   1040   void endDocuments();
   1041 
   1042 private:
   1043   void output(StringRef s);
   1044   void outputUpToEndOfLine(StringRef s);
   1045   void newLineCheck();
   1046   void outputNewLine();
   1047   void paddedKey(StringRef key);
   1048 
   1049   enum InState { inSeq, inFlowSeq, inMapFirstKey, inMapOtherKey };
   1050 
   1051   llvm::raw_ostream       &Out;
   1052   SmallVector<InState, 8>  StateStack;
   1053   int                      Column;
   1054   int                      ColumnAtFlowStart;
   1055   bool                     NeedBitValueComma;
   1056   bool                     NeedFlowSequenceComma;
   1057   bool                     EnumerationMatchFound;
   1058   bool                     NeedsNewLine;
   1059 };
   1060 
   1061 
   1062 
   1063 
   1064 /// YAML I/O does conversion based on types. But often native data types
   1065 /// are just a typedef of built in intergral types (e.g. int).  But the C++
   1066 /// type matching system sees through the typedef and all the typedefed types
   1067 /// look like a built in type. This will cause the generic YAML I/O conversion
   1068 /// to be used. To provide better control over the YAML conversion, you can
   1069 /// use this macro instead of typedef.  It will create a class with one field
   1070 /// and automatic conversion operators to and from the base type.
   1071 /// Based on BOOST_STRONG_TYPEDEF
   1072 #define LLVM_YAML_STRONG_TYPEDEF(_base, _type)                                 \
   1073     struct _type {                                                             \
   1074         _type() { }                                                            \
   1075         _type(const _base v) : value(v) { }                                    \
   1076         _type(const _type &v) : value(v.value) {}                              \
   1077         _type &operator=(const _type &rhs) { value = rhs.value; return *this; }\
   1078         _type &operator=(const _base &rhs) { value = rhs; return *this; }      \
   1079         operator const _base & () const { return value; }                      \
   1080         bool operator==(const _type &rhs) const { return value == rhs.value; } \
   1081         bool operator==(const _base &rhs) const { return value == rhs; }       \
   1082         bool operator<(const _type &rhs) const { return value < rhs.value; }   \
   1083         _base value;                                                           \
   1084     };
   1085 
   1086 
   1087 
   1088 ///
   1089 /// Use these types instead of uintXX_t in any mapping to have
   1090 /// its yaml output formatted as hexadecimal.
   1091 ///
   1092 LLVM_YAML_STRONG_TYPEDEF(uint8_t, Hex8)
   1093 LLVM_YAML_STRONG_TYPEDEF(uint16_t, Hex16)
   1094 LLVM_YAML_STRONG_TYPEDEF(uint32_t, Hex32)
   1095 LLVM_YAML_STRONG_TYPEDEF(uint64_t, Hex64)
   1096 
   1097 
   1098 template<>
   1099 struct ScalarTraits<Hex8> {
   1100   static void output(const Hex8 &, void*, llvm::raw_ostream &);
   1101   static StringRef input(StringRef, void*, Hex8 &);
   1102   static bool mustQuote(StringRef) { return false; }
   1103 };
   1104 
   1105 template<>
   1106 struct ScalarTraits<Hex16> {
   1107   static void output(const Hex16 &, void*, llvm::raw_ostream &);
   1108   static StringRef input(StringRef, void*, Hex16 &);
   1109   static bool mustQuote(StringRef) { return false; }
   1110 };
   1111 
   1112 template<>
   1113 struct ScalarTraits<Hex32> {
   1114   static void output(const Hex32 &, void*, llvm::raw_ostream &);
   1115   static StringRef input(StringRef, void*, Hex32 &);
   1116   static bool mustQuote(StringRef) { return false; }
   1117 };
   1118 
   1119 template<>
   1120 struct ScalarTraits<Hex64> {
   1121   static void output(const Hex64 &, void*, llvm::raw_ostream &);
   1122   static StringRef input(StringRef, void*, Hex64 &);
   1123   static bool mustQuote(StringRef) { return false; }
   1124 };
   1125 
   1126 
   1127 // Define non-member operator>> so that Input can stream in a document list.
   1128 template <typename T>
   1129 inline
   1130 typename std::enable_if<has_DocumentListTraits<T>::value, Input &>::type
   1131 operator>>(Input &yin, T &docList) {
   1132   int i = 0;
   1133   while ( yin.setCurrentDocument() ) {
   1134     yamlize(yin, DocumentListTraits<T>::element(yin, docList, i), true);
   1135     if ( yin.error() )
   1136       return yin;
   1137     yin.nextDocument();
   1138     ++i;
   1139   }
   1140   return yin;
   1141 }
   1142 
   1143 // Define non-member operator>> so that Input can stream in a map as a document.
   1144 template <typename T>
   1145 inline
   1146 typename std::enable_if<has_MappingTraits<T>::value, Input &>::type
   1147 operator>>(Input &yin, T &docMap) {
   1148   yin.setCurrentDocument();
   1149   yamlize(yin, docMap, true);
   1150   return yin;
   1151 }
   1152 
   1153 // Define non-member operator>> so that Input can stream in a sequence as
   1154 // a document.
   1155 template <typename T>
   1156 inline
   1157 typename std::enable_if<has_SequenceTraits<T>::value, Input &>::type
   1158 operator>>(Input &yin, T &docSeq) {
   1159   if (yin.setCurrentDocument())
   1160     yamlize(yin, docSeq, true);
   1161   return yin;
   1162 }
   1163 
   1164 // Provide better error message about types missing a trait specialization
   1165 template <typename T>
   1166 inline
   1167 typename std::enable_if<missingTraits<T>::value, Input &>::type
   1168 operator>>(Input &yin, T &docSeq) {
   1169   char missing_yaml_trait_for_type[sizeof(MissingTrait<T>)];
   1170   return yin;
   1171 }
   1172 
   1173 
   1174 // Define non-member operator<< so that Output can stream out document list.
   1175 template <typename T>
   1176 inline
   1177 typename std::enable_if<has_DocumentListTraits<T>::value, Output &>::type
   1178 operator<<(Output &yout, T &docList) {
   1179   yout.beginDocuments();
   1180   const size_t count = DocumentListTraits<T>::size(yout, docList);
   1181   for(size_t i=0; i < count; ++i) {
   1182     if ( yout.preflightDocument(i) ) {
   1183       yamlize(yout, DocumentListTraits<T>::element(yout, docList, i), true);
   1184       yout.postflightDocument();
   1185     }
   1186   }
   1187   yout.endDocuments();
   1188   return yout;
   1189 }
   1190 
   1191 // Define non-member operator<< so that Output can stream out a map.
   1192 template <typename T>
   1193 inline
   1194 typename std::enable_if<has_MappingTraits<T>::value, Output &>::type
   1195 operator<<(Output &yout, T &map) {
   1196   yout.beginDocuments();
   1197   if ( yout.preflightDocument(0) ) {
   1198     yamlize(yout, map, true);
   1199     yout.postflightDocument();
   1200   }
   1201   yout.endDocuments();
   1202   return yout;
   1203 }
   1204 
   1205 // Define non-member operator<< so that Output can stream out a sequence.
   1206 template <typename T>
   1207 inline
   1208 typename std::enable_if<has_SequenceTraits<T>::value, Output &>::type
   1209 operator<<(Output &yout, T &seq) {
   1210   yout.beginDocuments();
   1211   if ( yout.preflightDocument(0) ) {
   1212     yamlize(yout, seq, true);
   1213     yout.postflightDocument();
   1214   }
   1215   yout.endDocuments();
   1216   return yout;
   1217 }
   1218 
   1219 // Provide better error message about types missing a trait specialization
   1220 template <typename T>
   1221 inline
   1222 typename std::enable_if<missingTraits<T>::value, Output &>::type
   1223 operator<<(Output &yout, T &seq) {
   1224   char missing_yaml_trait_for_type[sizeof(MissingTrait<T>)];
   1225   return yout;
   1226 }
   1227 
   1228 
   1229 } // namespace yaml
   1230 } // namespace llvm
   1231 
   1232 
   1233 /// Utility for declaring that a std::vector of a particular type
   1234 /// should be considered a YAML sequence.
   1235 #define LLVM_YAML_IS_SEQUENCE_VECTOR(_type)                                 \
   1236   namespace llvm {                                                          \
   1237   namespace yaml {                                                          \
   1238     template<>                                                              \
   1239     struct SequenceTraits< std::vector<_type> > {                           \
   1240       static size_t size(IO &io, std::vector<_type> &seq) {                 \
   1241         return seq.size();                                                  \
   1242       }                                                                     \
   1243       static _type& element(IO &io, std::vector<_type> &seq, size_t index) {\
   1244         if ( index >= seq.size() )                                          \
   1245           seq.resize(index+1);                                              \
   1246         return seq[index];                                                  \
   1247       }                                                                     \
   1248     };                                                                      \
   1249   }                                                                         \
   1250   }
   1251 
   1252 /// Utility for declaring that a std::vector of a particular type
   1253 /// should be considered a YAML flow sequence.
   1254 #define LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(_type)                            \
   1255   namespace llvm {                                                          \
   1256   namespace yaml {                                                          \
   1257     template<>                                                              \
   1258     struct SequenceTraits< std::vector<_type> > {                           \
   1259       static size_t size(IO &io, std::vector<_type> &seq) {                 \
   1260         return seq.size();                                                  \
   1261       }                                                                     \
   1262       static _type& element(IO &io, std::vector<_type> &seq, size_t index) {\
   1263         (void)flow; /* Remove this workaround after PR17897 is fixed */     \
   1264         if ( index >= seq.size() )                                          \
   1265           seq.resize(index+1);                                              \
   1266         return seq[index];                                                  \
   1267       }                                                                     \
   1268       static const bool flow = true;                                        \
   1269     };                                                                      \
   1270   }                                                                         \
   1271   }
   1272 
   1273 /// Utility for declaring that a std::vector of a particular type
   1274 /// should be considered a YAML document list.
   1275 #define LLVM_YAML_IS_DOCUMENT_LIST_VECTOR(_type)                            \
   1276   namespace llvm {                                                          \
   1277   namespace yaml {                                                          \
   1278     template<>                                                              \
   1279     struct DocumentListTraits< std::vector<_type> > {                       \
   1280       static size_t size(IO &io, std::vector<_type> &seq) {                 \
   1281         return seq.size();                                                  \
   1282       }                                                                     \
   1283       static _type& element(IO &io, std::vector<_type> &seq, size_t index) {\
   1284         if ( index >= seq.size() )                                          \
   1285           seq.resize(index+1);                                              \
   1286         return seq[index];                                                  \
   1287       }                                                                     \
   1288     };                                                                      \
   1289   }                                                                         \
   1290   }
   1291 
   1292 
   1293 
   1294 #endif // LLVM_SUPPORT_YAMLTRAITS_H
   1295