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