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