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