LCOV - code coverage report
Current view: top level - include/llvm/Support - YAMLTraits.h (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 293 297 98.7 %
Date: 2018-07-13 00:08:38 Functions: 1500 1646 91.1 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13