LCOV - code coverage report
Current view: top level - include/llvm/Support - YAMLTraits.h (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 291 295 98.6 %
Date: 2018-02-23 15:42:53 Functions: 1387 1547 89.7 %
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       41729 : inline bool isNumber(StringRef S) {
     453             :   static const char OctalChars[] = "01234567";
     454          77 :   if (S.startswith("0") &&
     455       41883 :       S.drop_front().find_first_not_of(OctalChars) == StringRef::npos)
     456             :     return true;
     457             : 
     458           0 :   if (S.startswith("0o") &&
     459       41677 :       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       41681 :       S.drop_front(2).find_first_not_of(HexChars) == StringRef::npos)
     465             :     return true;
     466             : 
     467             :   static const char DecChars[] = "0123456789";
     468       41675 :   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       82826 :   Regex FloatMatcher("^(\\.[0-9]+|[0-9]+(\\.[0-9]*)?)([eE][-+]?[0-9]+)?$");
     475       41413 :   if (FloatMatcher.match(S))
     476             :     return true;
     477             : 
     478       41411 :   return false;
     479             : }
     480             : 
     481       41723 : inline bool isNumeric(StringRef S) {
     482       83477 :   if ((S.front() == '-' || S.front() == '+') && isNumber(S.drop_front()))
     483             :     return true;
     484             : 
     485       41698 :   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       41741 : inline bool isNull(StringRef S) {
     495             :   return S.equals("null") || S.equals("Null") || S.equals("NULL") ||
     496       41741 :          S.equals("~");
     497             : }
     498             : 
     499       41729 : inline bool isBool(StringRef S) {
     500             :   return S.equals("true") || S.equals("True") || S.equals("TRUE") ||
     501       41729 :          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      119934 : inline QuotingType needsQuotes(StringRef S) {
     510      119934 :   if (S.empty())
     511             :     return QuotingType::Single;
     512      126684 :   if (isspace(S.front()) || isspace(S.back()))
     513             :     return QuotingType::Single;
     514       41736 :   if (isNull(S))
     515             :     return QuotingType::Single;
     516       41729 :   if (isBool(S))
     517             :     return QuotingType::Single;
     518       41723 :   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       41405 :   if (S.find_first_of(Indicators) == 0)
     526             :     return QuotingType::Single;
     527             : 
     528             :   QuotingType MaxQuotingNeeded = QuotingType::None;
     529      945206 :   for (unsigned char C : S) {
     530             :     // Alphanum is safe.
     531      369235 :     if (isAlnum(C))
     532      369235 :       continue;
     533             : 
     534      115787 :     switch (C) {
     535             :     // Safe scalar characters.
     536       53066 :     case '_':
     537             :     case '-':
     538             :     case '/':
     539             :     case '^':
     540             :     case '.':
     541             :     case ',':
     542             :     case ' ':
     543             :     // TAB (0x9), LF (0xA), CR (0xD) and NEL (0x85) are allowed.
     544             :     case 0x9:
     545             :     case 0xA:
     546             :     case 0xD:
     547             :     case 0x85:
     548       53066 :       continue;
     549             :     // DEL (0x7F) are excluded from the allowed character range.
     550             :     case 0x7F:
     551             :       return QuotingType::Double;
     552        9655 :     default: {
     553             :       // C0 control block (0x0 - 0x1F) is excluded from the allowed character
     554             :       // range.
     555        9655 :       if (C <= 0x1F)
     556             :         return QuotingType::Double;
     557             : 
     558             :       // Always double quote UTF-8.
     559        9651 :       if ((C & 0x80) != 0)
     560             :         return QuotingType::Double;
     561             : 
     562             :       // The character is not safe, at least simple quoting needed.
     563             :       MaxQuotingNeeded = QuotingType::Single;
     564             :     }
     565             :     }
     566             :   }
     567             : 
     568             :   return MaxQuotingNeeded;
     569             : }
     570             : 
     571             : template <typename T, typename Context>
     572             : struct missingTraits
     573             :     : public std::integral_constant<bool,
     574             :                                     !has_ScalarEnumerationTraits<T>::value &&
     575             :                                         !has_ScalarBitSetTraits<T>::value &&
     576             :                                         !has_ScalarTraits<T>::value &&
     577             :                                         !has_BlockScalarTraits<T>::value &&
     578             :                                         !has_MappingTraits<T, Context>::value &&
     579             :                                         !has_SequenceTraits<T>::value &&
     580             :                                         !has_CustomMappingTraits<T>::value &&
     581             :                                         !has_DocumentListTraits<T>::value> {};
     582             : 
     583             : template <typename T, typename Context>
     584             : struct validatedMappingTraits
     585             :     : public std::integral_constant<
     586             :           bool, has_MappingTraits<T, Context>::value &&
     587             :                     has_MappingValidateTraits<T, Context>::value> {};
     588             : 
     589             : template <typename T, typename Context>
     590             : struct unvalidatedMappingTraits
     591             :     : public std::integral_constant<
     592             :           bool, has_MappingTraits<T, Context>::value &&
     593             :                     !has_MappingValidateTraits<T, Context>::value> {};
     594             : 
     595             : // Base class for Input and Output.
     596        8006 : class IO {
     597             : public:
     598             :   IO(void *Ctxt = nullptr);
     599             :   virtual ~IO();
     600             : 
     601             :   virtual bool outputting() = 0;
     602             : 
     603             :   virtual unsigned beginSequence() = 0;
     604             :   virtual bool preflightElement(unsigned, void *&) = 0;
     605             :   virtual void postflightElement(void*) = 0;
     606             :   virtual void endSequence() = 0;
     607             :   virtual bool canElideEmptySequence() = 0;
     608             : 
     609             :   virtual unsigned beginFlowSequence() = 0;
     610             :   virtual bool preflightFlowElement(unsigned, void *&) = 0;
     611             :   virtual void postflightFlowElement(void*) = 0;
     612             :   virtual void endFlowSequence() = 0;
     613             : 
     614             :   virtual bool mapTag(StringRef Tag, bool Default=false) = 0;
     615             :   virtual void beginMapping() = 0;
     616             :   virtual void endMapping() = 0;
     617             :   virtual bool preflightKey(const char*, bool, bool, bool &, void *&) = 0;
     618             :   virtual void postflightKey(void*) = 0;
     619             :   virtual std::vector<StringRef> keys() = 0;
     620             : 
     621             :   virtual void beginFlowMapping() = 0;
     622             :   virtual void endFlowMapping() = 0;
     623             : 
     624             :   virtual void beginEnumScalar() = 0;
     625             :   virtual bool matchEnumScalar(const char*, bool) = 0;
     626             :   virtual bool matchEnumFallback() = 0;
     627             :   virtual void endEnumScalar() = 0;
     628             : 
     629             :   virtual bool beginBitSetScalar(bool &) = 0;
     630             :   virtual bool bitSetMatch(const char*, bool) = 0;
     631             :   virtual void endBitSetScalar() = 0;
     632             : 
     633             :   virtual void scalarString(StringRef &, QuotingType) = 0;
     634             :   virtual void blockScalarString(StringRef &) = 0;
     635             : 
     636             :   virtual void setError(const Twine &) = 0;
     637             : 
     638             :   template <typename T>
     639     1228477 :   void enumCase(T &Val, const char* Str, const T ConstVal) {
     640     1228477 :     if ( matchEnumScalar(Str, outputting() && Val == ConstVal) ) {
     641       12867 :       Val = ConstVal;
     642             :     }
     643     1228477 :   }
     644             : 
     645             :   // allow anonymous enum values to be used with LLVM_YAML_STRONG_TYPEDEF
     646             :   template <typename T>
     647       80386 :   void enumCase(T &Val, const char* Str, const uint32_t ConstVal) {
     648       97016 :     if ( matchEnumScalar(Str, outputting() && Val == static_cast<T>(ConstVal)) ) {
     649         893 :       Val = ConstVal;
     650             :     }
     651       80386 :   }
     652             : 
     653             :   template <typename FBT, typename T>
     654        8286 :   void enumFallback(T &Val) {
     655        8286 :     if (matchEnumFallback()) {
     656             :       EmptyContext Context;
     657             :       // FIXME: Force integral conversion to allow strong typedefs to convert.
     658          54 :       FBT Res = static_cast<typename FBT::BaseType>(Val);
     659          54 :       yamlize(*this, Res, true, Context);
     660          54 :       Val = static_cast<T>(static_cast<typename FBT::BaseType>(Res));
     661             :     }
     662        8286 :   }
     663             : 
     664             :   template <typename T>
     665       22203 :   void bitSetCase(T &Val, const char* Str, const T ConstVal) {
     666       24776 :     if ( bitSetMatch(Str, outputting() && (Val & ConstVal) == ConstVal) ) {
     667        5247 :       Val = static_cast<T>(Val | ConstVal);
     668             :     }
     669       22203 :   }
     670             : 
     671             :   // allow anonymous enum values to be used with LLVM_YAML_STRONG_TYPEDEF
     672             :   template <typename T>
     673        7730 :   void bitSetCase(T &Val, const char* Str, const uint32_t ConstVal) {
     674        7730 :     if ( bitSetMatch(Str, outputting() && (Val & ConstVal) == ConstVal) ) {
     675        1349 :       Val = static_cast<T>(Val | ConstVal);
     676             :     }
     677        7730 :   }
     678             : 
     679             :   template <typename T>
     680             :   void maskedBitSetCase(T &Val, const char *Str, T ConstVal, T Mask) {
     681             :     if (bitSetMatch(Str, outputting() && (Val & Mask) == ConstVal))
     682             :       Val = Val | ConstVal;
     683             :   }
     684             : 
     685             :   template <typename T>
     686        2807 :   void maskedBitSetCase(T &Val, const char *Str, uint32_t ConstVal,
     687             :                         uint32_t Mask) {
     688        2807 :     if (bitSetMatch(Str, outputting() && (Val & Mask) == ConstVal))
     689          69 :       Val = Val | ConstVal;
     690        2807 :   }
     691             : 
     692             :   void *getContext();
     693             :   void setContext(void *);
     694             : 
     695             :   template <typename T> void mapRequired(const char *Key, T &Val) {
     696             :     EmptyContext Ctx;
     697      211841 :     this->processKey(Key, Val, true, Ctx);
     698             :   }
     699             : 
     700             :   template <typename T, typename Context>
     701             :   void mapRequired(const char *Key, T &Val, Context &Ctx) {
     702           2 :     this->processKey(Key, Val, true, Ctx);
     703             :   }
     704             : 
     705             :   template <typename T> void mapOptional(const char *Key, T &Val) {
     706             :     EmptyContext Ctx;
     707       31166 :     mapOptionalWithContext(Key, Val, Ctx);
     708             :   }
     709             : 
     710             :   template <typename T>
     711             :   void mapOptional(const char *Key, T &Val, const T &Default) {
     712             :     EmptyContext Ctx;
     713             :     mapOptionalWithContext(Key, Val, Default, Ctx);
     714             :   }
     715             : 
     716             :   template <typename T, typename Context>
     717             :   typename std::enable_if<has_SequenceTraits<T>::value, void>::type
     718       28032 :   mapOptionalWithContext(const char *Key, T &Val, Context &Ctx) {
     719             :     // omit key/value instead of outputting empty sequence
     720       46041 :     if (this->canElideEmptySequence() && !(Val.begin() != Val.end()))
     721             :       return;
     722       14817 :     this->processKey(Key, Val, false, Ctx);
     723             :   }
     724             : 
     725             :   template <typename T, typename Context>
     726        3134 :   void mapOptionalWithContext(const char *Key, Optional<T> &Val, Context &Ctx) {
     727       13170 :     this->processKeyWithDefault(Key, Val, Optional<T>(), /*Required=*/false,
     728             :                                 Ctx);
     729        3134 :   }
     730             : 
     731             :   template <typename T, typename Context>
     732             :   typename std::enable_if<!has_SequenceTraits<T>::value, void>::type
     733             :   mapOptionalWithContext(const char *Key, T &Val, Context &Ctx) {
     734       63441 :     this->processKey(Key, Val, false, Ctx);
     735             :   }
     736             : 
     737             :   template <typename T, typename Context>
     738             :   void mapOptionalWithContext(const char *Key, T &Val, const T &Default,
     739             :                               Context &Ctx) {
     740      324205 :     this->processKeyWithDefault(Key, Val, Default, false, Ctx);
     741             :   }
     742             : 
     743             : private:
     744             :   template <typename T, typename Context>
     745       16867 :   void processKeyWithDefault(const char *Key, Optional<T> &Val,
     746             :                              const Optional<T> &DefaultValue, bool Required,
     747             :                              Context &Ctx) {
     748             :     assert(DefaultValue.hasValue() == false &&
     749             :            "Optional<T> shouldn't have a value!");
     750             :     void *SaveInfo;
     751       16867 :     bool UseDefault = true;
     752       16867 :     const bool sameAsDefault = outputting() && !Val.hasValue();
     753       16867 :     if (!outputting() && !Val.hasValue())
     754       16094 :       Val = T();
     755       29461 :     if (Val.hasValue() &&
     756       12594 :         this->preflightKey(Key, Required, sameAsDefault, UseDefault,
     757             :                            SaveInfo)) {
     758        1515 :       yamlize(*this, Val.getValue(), Required, Ctx);
     759        1515 :       this->postflightKey(SaveInfo);
     760             :     } else {
     761       15352 :       if (UseDefault)
     762             :         Val = DefaultValue;
     763             :     }
     764       16867 :   }
     765             : 
     766             :   template <typename T, typename Context>
     767      317578 :   void processKeyWithDefault(const char *Key, T &Val, const T &DefaultValue,
     768             :                              bool Required, Context &Ctx) {
     769             :     void *SaveInfo;
     770             :     bool UseDefault;
     771      349473 :     const bool sameAsDefault = outputting() && Val == DefaultValue;
     772      317578 :     if ( this->preflightKey(Key, Required, sameAsDefault, UseDefault,
     773             :                                                                   SaveInfo) ) {
     774      169574 :       yamlize(*this, Val, Required, Ctx);
     775      169574 :       this->postflightKey(SaveInfo);
     776             :     }
     777             :     else {
     778      148004 :       if ( UseDefault )
     779       40588 :         Val = DefaultValue;
     780             :     }
     781      317578 :   }
     782             : 
     783             :   template <typename T, typename Context>
     784      290434 :   void processKey(const char *Key, T &Val, bool Required, Context &Ctx) {
     785             :     void *SaveInfo;
     786             :     bool UseDefault;
     787      290434 :     if ( this->preflightKey(Key, Required, false, UseDefault, SaveInfo) ) {
     788      233171 :       yamlize(*this, Val, Required, Ctx);
     789      236642 :       this->postflightKey(SaveInfo);
     790             :     }
     791      290434 :   }
     792             : 
     793             : private:
     794             :   void *Ctxt;
     795             : };
     796             : 
     797             : namespace detail {
     798             : 
     799             : template <typename T, typename Context>
     800             : void doMapping(IO &io, T &Val, Context &Ctx) {
     801           2 :   MappingContextTraits<T, Context>::mapping(io, Val, Ctx);
     802             : }
     803             : 
     804             : template <typename T> void doMapping(IO &io, T &Val, EmptyContext &Ctx) {
     805       84602 :   MappingTraits<T>::mapping(io, Val);
     806             : }
     807             : 
     808             : } // end namespace detail
     809             : 
     810             : template <typename T>
     811             : typename std::enable_if<has_ScalarEnumerationTraits<T>::value, void>::type
     812       46032 : yamlize(IO &io, T &Val, bool, EmptyContext &Ctx) {
     813       46032 :   io.beginEnumScalar();
     814       46032 :   ScalarEnumerationTraits<T>::enumeration(io, Val);
     815       46032 :   io.endEnumScalar();
     816       46032 : }
     817             : 
     818             : template <typename T>
     819             : typename std::enable_if<has_ScalarBitSetTraits<T>::value, void>::type
     820        2963 : yamlize(IO &io, T &Val, bool, EmptyContext &Ctx) {
     821             :   bool DoClear;
     822        2963 :   if ( io.beginBitSetScalar(DoClear) ) {
     823        2963 :     if ( DoClear )
     824        2481 :       Val = static_cast<T>(0);
     825        2963 :     ScalarBitSetTraits<T>::bitset(io, Val);
     826        2963 :     io.endBitSetScalar();
     827             :   }
     828        2963 : }
     829             : 
     830             : template <typename T>
     831             : typename std::enable_if<has_ScalarTraits<T>::value, void>::type
     832      335392 : yamlize(IO &io, T &Val, bool, EmptyContext &Ctx) {
     833      335392 :   if ( io.outputting() ) {
     834             :     std::string Storage;
     835      235481 :     raw_string_ostream Buffer(Storage);
     836      235481 :     ScalarTraits<T>::output(Val, io.getContext(), Buffer);
     837             :     StringRef Str = Buffer.str();
     838      319708 :     io.scalarString(Str, ScalarTraits<T>::mustQuote(Str));
     839             :   }
     840             :   else {
     841       99911 :     StringRef Str;
     842      134475 :     io.scalarString(Str, ScalarTraits<T>::mustQuote(Str));
     843      100807 :     StringRef Result = ScalarTraits<T>::input(Str, io.getContext(), Val);
     844       99911 :     if ( !Result.empty() ) {
     845          40 :       io.setError(Twine(Result));
     846             :     }
     847             :   }
     848      335392 : }
     849             : 
     850             : template <typename T>
     851             : typename std::enable_if<has_BlockScalarTraits<T>::value, void>::type
     852        6864 : yamlize(IO &YamlIO, T &Val, bool, EmptyContext &Ctx) {
     853        6864 :   if (YamlIO.outputting()) {
     854             :     std::string Storage;
     855        3838 :     raw_string_ostream Buffer(Storage);
     856        3838 :     BlockScalarTraits<T>::output(Val, YamlIO.getContext(), Buffer);
     857             :     StringRef Str = Buffer.str();
     858        3838 :     YamlIO.blockScalarString(Str);
     859             :   } else {
     860        3026 :     StringRef Str;
     861        3026 :     YamlIO.blockScalarString(Str);
     862        3026 :     StringRef Result =
     863        3026 :         BlockScalarTraits<T>::input(Str, YamlIO.getContext(), Val);
     864        3026 :     if (!Result.empty())
     865           0 :       YamlIO.setError(Twine(Result));
     866             :   }
     867        6864 : }
     868             : 
     869             : template <typename T, typename Context>
     870             : typename std::enable_if<validatedMappingTraits<T, Context>::value, void>::type
     871         738 : yamlize(IO &io, T &Val, bool, Context &Ctx) {
     872             :   if (has_FlowTraits<MappingTraits<T>>::value)
     873             :     io.beginFlowMapping();
     874             :   else
     875         738 :     io.beginMapping();
     876         738 :   if (io.outputting()) {
     877         190 :     StringRef Err = MappingTraits<T>::validate(io, Val);
     878         190 :     if (!Err.empty()) {
     879           0 :       errs() << Err << "\n";
     880             :       assert(Err.empty() && "invalid struct trying to be written as yaml");
     881             :     }
     882             :   }
     883             :   detail::doMapping(io, Val, Ctx);
     884         738 :   if (!io.outputting()) {
     885         534 :     StringRef Err = MappingTraits<T>::validate(io, Val);
     886         534 :     if (!Err.empty())
     887          12 :       io.setError(Err);
     888             :   }
     889             :   if (has_FlowTraits<MappingTraits<T>>::value)
     890             :     io.endFlowMapping();
     891             :   else
     892         738 :     io.endMapping();
     893         738 : }
     894             : 
     895             : template <typename T, typename Context>
     896             : typename std::enable_if<unvalidatedMappingTraits<T, Context>::value, void>::type
     897       84284 : yamlize(IO &io, T &Val, bool, Context &Ctx) {
     898             :   if (has_FlowTraits<MappingTraits<T>>::value) {
     899       31199 :     io.beginFlowMapping();
     900             :     detail::doMapping(io, Val, Ctx);
     901       31199 :     io.endFlowMapping();
     902             :   } else {
     903       56556 :     io.beginMapping();
     904             :     detail::doMapping(io, Val, Ctx);
     905       56556 :     io.endMapping();
     906             :   }
     907       84284 : }
     908             : 
     909             : template <typename T>
     910             : typename std::enable_if<has_CustomMappingTraits<T>::value, void>::type
     911         159 : yamlize(IO &io, T &Val, bool, EmptyContext &Ctx) {
     912         159 :   if ( io.outputting() ) {
     913          93 :     io.beginMapping();
     914          93 :     CustomMappingTraits<T>::output(io, Val);
     915          93 :     io.endMapping();
     916             :   } else {
     917          66 :     io.beginMapping();
     918         234 :     for (StringRef key : io.keys())
     919         102 :       CustomMappingTraits<T>::inputOne(io, key, Val);
     920          66 :     io.endMapping();
     921             :   }
     922         159 : }
     923             : 
     924             : template <typename T>
     925             : typename std::enable_if<missingTraits<T, EmptyContext>::value, void>::type
     926             : yamlize(IO &io, T &Val, bool, EmptyContext &Ctx) {
     927             :   char missing_yaml_trait_for_type[sizeof(MissingTrait<T>)];
     928             : }
     929             : 
     930             : template <typename T, typename Context>
     931             : typename std::enable_if<has_SequenceTraits<T>::value, void>::type
     932       30767 : yamlize(IO &io, T &Seq, bool, Context &Ctx) {
     933             :   if ( has_FlowTraits< SequenceTraits<T>>::value ) {
     934        2471 :     unsigned incnt = io.beginFlowSequence();
     935        4107 :     unsigned count = io.outputting() ? SequenceTraits<T>::size(io, Seq) : incnt;
     936       34881 :     for(unsigned i=0; i < count; ++i) {
     937             :       void *SaveInfo;
     938       16205 :       if ( io.preflightFlowElement(i, SaveInfo) ) {
     939       27377 :         yamlize(io, SequenceTraits<T>::element(io, Seq, i), true, Ctx);
     940       16205 :         io.postflightFlowElement(SaveInfo);
     941             :       }
     942             :     }
     943        2471 :     io.endFlowSequence();
     944             :   }
     945             :   else {
     946       28296 :     unsigned incnt = io.beginSequence();
     947       48781 :     unsigned count = io.outputting() ? SequenceTraits<T>::size(io, Seq) : incnt;
     948      181202 :     for(unsigned i=0; i < count; ++i) {
     949             :       void *SaveInfo;
     950       76453 :       if ( io.preflightElement(i, SaveInfo) ) {
     951       76957 :         yamlize(io, SequenceTraits<T>::element(io, Seq, i), true, Ctx);
     952       76453 :         io.postflightElement(SaveInfo);
     953             :       }
     954             :     }
     955       28296 :     io.endSequence();
     956             :   }
     957       30767 : }
     958             : 
     959             : template<>
     960             : struct ScalarTraits<bool> {
     961             :   static void output(const bool &, void* , raw_ostream &);
     962             :   static StringRef input(StringRef, void *, bool &);
     963             :   static QuotingType mustQuote(StringRef) { return QuotingType::None; }
     964             : };
     965             : 
     966             : template<>
     967             : struct ScalarTraits<StringRef> {
     968             :   static void output(const StringRef &, void *, raw_ostream &);
     969             :   static StringRef input(StringRef, void *, StringRef &);
     970       32476 :   static QuotingType mustQuote(StringRef S) { return needsQuotes(S); }
     971             : };
     972             : 
     973             : template<>
     974             : struct ScalarTraits<std::string> {
     975             :   static void output(const std::string &, void *, raw_ostream &);
     976             :   static StringRef input(StringRef, void *, std::string &);
     977       22928 :   static QuotingType mustQuote(StringRef S) { return needsQuotes(S); }
     978             : };
     979             : 
     980             : template<>
     981             : struct ScalarTraits<uint8_t> {
     982             :   static void output(const uint8_t &, void *, raw_ostream &);
     983             :   static StringRef input(StringRef, void *, uint8_t &);
     984             :   static QuotingType mustQuote(StringRef) { return QuotingType::None; }
     985             : };
     986             : 
     987             : template<>
     988             : struct ScalarTraits<uint16_t> {
     989             :   static void output(const uint16_t &, void *, raw_ostream &);
     990             :   static StringRef input(StringRef, void *, uint16_t &);
     991             :   static QuotingType mustQuote(StringRef) { return QuotingType::None; }
     992             : };
     993             : 
     994             : template<>
     995             : struct ScalarTraits<uint32_t> {
     996             :   static void output(const uint32_t &, void *, raw_ostream &);
     997             :   static StringRef input(StringRef, void *, uint32_t &);
     998             :   static QuotingType mustQuote(StringRef) { return QuotingType::None; }
     999             : };
    1000             : 
    1001             : template<>
    1002             : struct ScalarTraits<uint64_t> {
    1003             :   static void output(const uint64_t &, void *, raw_ostream &);
    1004             :   static StringRef input(StringRef, void *, uint64_t &);
    1005             :   static QuotingType mustQuote(StringRef) { return QuotingType::None; }
    1006             : };
    1007             : 
    1008             : template<>
    1009             : struct ScalarTraits<int8_t> {
    1010             :   static void output(const int8_t &, void *, raw_ostream &);
    1011             :   static StringRef input(StringRef, void *, int8_t &);
    1012             :   static QuotingType mustQuote(StringRef) { return QuotingType::None; }
    1013             : };
    1014             : 
    1015             : template<>
    1016             : struct ScalarTraits<int16_t> {
    1017             :   static void output(const int16_t &, void *, raw_ostream &);
    1018             :   static StringRef input(StringRef, void *, int16_t &);
    1019             :   static QuotingType mustQuote(StringRef) { return QuotingType::None; }
    1020             : };
    1021             : 
    1022             : template<>
    1023             : struct ScalarTraits<int32_t> {
    1024             :   static void output(const int32_t &, void *, raw_ostream &);
    1025             :   static StringRef input(StringRef, void *, int32_t &);
    1026             :   static QuotingType mustQuote(StringRef) { return QuotingType::None; }
    1027             : };
    1028             : 
    1029             : template<>
    1030             : struct ScalarTraits<int64_t> {
    1031             :   static void output(const int64_t &, void *, raw_ostream &);
    1032             :   static StringRef input(StringRef, void *, int64_t &);
    1033             :   static QuotingType mustQuote(StringRef) { return QuotingType::None; }
    1034             : };
    1035             : 
    1036             : template<>
    1037             : struct ScalarTraits<float> {
    1038             :   static void output(const float &, void *, raw_ostream &);
    1039             :   static StringRef input(StringRef, void *, float &);
    1040             :   static QuotingType mustQuote(StringRef) { return QuotingType::None; }
    1041             : };
    1042             : 
    1043             : template<>
    1044             : struct ScalarTraits<double> {
    1045             :   static void output(const double &, void *, raw_ostream &);
    1046             :   static StringRef input(StringRef, void *, double &);
    1047             :   static QuotingType mustQuote(StringRef) { return QuotingType::None; }
    1048             : };
    1049             : 
    1050             : // For endian types, we just use the existing ScalarTraits for the underlying
    1051             : // type.  This way endian aware types are supported whenever a ScalarTraits
    1052             : // is defined for the underlying type.
    1053             : template <typename value_type, support::endianness endian, size_t alignment>
    1054             : struct ScalarTraits<support::detail::packed_endian_specific_integral<
    1055             :     value_type, endian, alignment>> {
    1056             :   using endian_type =
    1057             :       support::detail::packed_endian_specific_integral<value_type, endian,
    1058             :                                                        alignment>;
    1059             : 
    1060             :   static void output(const endian_type &E, void *Ctx, raw_ostream &Stream) {
    1061         103 :     ScalarTraits<value_type>::output(static_cast<value_type>(E), Ctx, Stream);
    1062             :   }
    1063             : 
    1064             :   static StringRef input(StringRef Str, void *Ctx, endian_type &E) {
    1065             :     value_type V;
    1066          72 :     auto R = ScalarTraits<value_type>::input(Str, Ctx, V);
    1067         144 :     E = static_cast<endian_type>(V);
    1068          72 :     return R;
    1069             :   }
    1070             : 
    1071             :   static QuotingType mustQuote(StringRef Str) {
    1072             :     return ScalarTraits<value_type>::mustQuote(Str);
    1073             :   }
    1074             : };
    1075             : 
    1076             : // Utility for use within MappingTraits<>::mapping() method
    1077             : // to [de]normalize an object for use with YAML conversion.
    1078             : template <typename TNorm, typename TFinal>
    1079             : struct MappingNormalization {
    1080        4326 :   MappingNormalization(IO &i_o, TFinal &Obj)
    1081        4326 :       : io(i_o), BufPtr(nullptr), Result(Obj) {
    1082        4326 :     if ( io.outputting() ) {
    1083         752 :       BufPtr = new (&Buffer) TNorm(io, Obj);
    1084             :     }
    1085             :     else {
    1086        4674 :       BufPtr = new (&Buffer) TNorm(io);
    1087             :     }
    1088         878 :   }
    1089             : 
    1090         878 :   ~MappingNormalization() {
    1091        4326 :     if ( ! io.outputting() ) {
    1092        7496 :       Result = BufPtr->denormalize(io);
    1093             :     }
    1094         857 :     BufPtr->~TNorm();
    1095        1082 :   }
    1096             : 
    1097             :   TNorm* operator->() { return BufPtr; }
    1098             : 
    1099             : private:
    1100             :   using Storage = AlignedCharArrayUnion<TNorm>;
    1101             : 
    1102             :   Storage       Buffer;
    1103             :   IO           &io;
    1104             :   TNorm        *BufPtr;
    1105             :   TFinal       &Result;
    1106             : };
    1107             : 
    1108             : // Utility for use within MappingTraits<>::mapping() method
    1109             : // to [de]normalize an object for use with YAML conversion.
    1110             : template <typename TNorm, typename TFinal>
    1111             : struct MappingNormalizationHeap {
    1112         932 :   MappingNormalizationHeap(IO &i_o, TFinal &Obj, BumpPtrAllocator *allocator)
    1113         932 :     : io(i_o), Result(Obj) {
    1114         932 :     if ( io.outputting() ) {
    1115         826 :       BufPtr = new (&Buffer) TNorm(io, Obj);
    1116             :     }
    1117         106 :     else if (allocator) {
    1118          89 :       BufPtr = allocator->Allocate<TNorm>();
    1119          71 :       new (BufPtr) TNorm(io);
    1120             :     } else {
    1121          17 :       BufPtr = new TNorm(io);
    1122             :     }
    1123         932 :   }
    1124             : 
    1125         932 :   ~MappingNormalizationHeap() {
    1126         932 :     if ( io.outputting() ) {
    1127         826 :       BufPtr->~TNorm();
    1128             :     }
    1129             :     else {
    1130         106 :       Result = BufPtr->denormalize(io);
    1131             :     }
    1132         932 :   }
    1133             : 
    1134             :   TNorm* operator->() { return BufPtr; }
    1135             : 
    1136             : private:
    1137             :   using Storage = AlignedCharArrayUnion<TNorm>;
    1138             : 
    1139             :   Storage       Buffer;
    1140             :   IO           &io;
    1141             :   TNorm        *BufPtr = nullptr;
    1142             :   TFinal       &Result;
    1143             : };
    1144             : 
    1145             : ///
    1146             : /// The Input class is used to parse a yaml document into in-memory structs
    1147             : /// and vectors.
    1148             : ///
    1149             : /// It works by using YAMLParser to do a syntax parse of the entire yaml
    1150             : /// document, then the Input class builds a graph of HNodes which wraps
    1151             : /// each yaml Node.  The extra layer is buffering.  The low level yaml
    1152             : /// parser only lets you look at each node once.  The buffering layer lets
    1153             : /// you search and interate multiple times.  This is necessary because
    1154             : /// the mapRequired() method calls may not be in the same order
    1155             : /// as the keys in the document.
    1156             : ///
    1157        9318 : class Input : public IO {
    1158             : public:
    1159             :   // Construct a yaml Input object from a StringRef and optional
    1160             :   // user-data. The DiagHandler can be specified to provide
    1161             :   // alternative error reporting.
    1162             :   Input(StringRef InputContent,
    1163             :         void *Ctxt = nullptr,
    1164             :         SourceMgr::DiagHandlerTy DiagHandler = nullptr,
    1165             :         void *DiagHandlerCtxt = nullptr);
    1166             :   Input(MemoryBufferRef Input,
    1167             :         void *Ctxt = nullptr,
    1168             :         SourceMgr::DiagHandlerTy DiagHandler = nullptr,
    1169             :         void *DiagHandlerCtxt = nullptr);
    1170             :   ~Input() override;
    1171             : 
    1172             :   // Check if there was an syntax or semantic error during parsing.
    1173             :   std::error_code error();
    1174             : 
    1175             : private:
    1176             :   bool outputting() override;
    1177             :   bool mapTag(StringRef, bool) override;
    1178             :   void beginMapping() override;
    1179             :   void endMapping() override;
    1180             :   bool preflightKey(const char *, bool, bool, bool &, void *&) override;
    1181             :   void postflightKey(void *) override;
    1182             :   std::vector<StringRef> keys() override;
    1183             :   void beginFlowMapping() override;
    1184             :   void endFlowMapping() override;
    1185             :   unsigned beginSequence() override;
    1186             :   void endSequence() override;
    1187             :   bool preflightElement(unsigned index, void *&) override;
    1188             :   void postflightElement(void *) override;
    1189             :   unsigned beginFlowSequence() override;
    1190             :   bool preflightFlowElement(unsigned , void *&) override;
    1191             :   void postflightFlowElement(void *) override;
    1192             :   void endFlowSequence() override;
    1193             :   void beginEnumScalar() override;
    1194             :   bool matchEnumScalar(const char*, bool) override;
    1195             :   bool matchEnumFallback() override;
    1196             :   void endEnumScalar() override;
    1197             :   bool beginBitSetScalar(bool &) override;
    1198             :   bool bitSetMatch(const char *, bool ) override;
    1199             :   void endBitSetScalar() override;
    1200             :   void scalarString(StringRef &, QuotingType) override;
    1201             :   void blockScalarString(StringRef &) override;
    1202             :   void setError(const Twine &message) override;
    1203             :   bool canElideEmptySequence() override;
    1204             : 
    1205             :   class HNode {
    1206             :     virtual void anchor();
    1207             : 
    1208             :   public:
    1209      168582 :     HNode(Node *n) : _node(n) { }
    1210           0 :     virtual ~HNode() = default;
    1211             : 
    1212             :     static bool classof(const HNode *) { return true; }
    1213             : 
    1214             :     Node *_node;
    1215             :   };
    1216             : 
    1217        1386 :   class EmptyHNode : public HNode {
    1218             :     void anchor() override;
    1219             : 
    1220             :   public:
    1221        1464 :     EmptyHNode(Node *n) : HNode(n) { }
    1222             : 
    1223             :     static bool classof(const HNode *n) { return NullNode::classof(n->_node); }
    1224             : 
    1225             :     static bool classof(const EmptyHNode *) { return true; }
    1226             :   };
    1227             : 
    1228      121496 :   class ScalarHNode : public HNode {
    1229             :     void anchor() override;
    1230             : 
    1231             :   public:
    1232      244892 :     ScalarHNode(Node *n, StringRef s) : HNode(n), _value(s) { }
    1233             : 
    1234             :     StringRef value() const { return _value; }
    1235             : 
    1236             :     static bool classof(const HNode *n) {
    1237      340964 :       return ScalarNode::classof(n->_node) ||
    1238             :              BlockScalarNode::classof(n->_node);
    1239             :     }
    1240             : 
    1241             :     static bool classof(const ScalarHNode *) { return true; }
    1242             : 
    1243             :   protected:
    1244             :     StringRef _value;
    1245             :   };
    1246             : 
    1247       34779 :   class MapHNode : public HNode {
    1248             :     void anchor() override;
    1249             : 
    1250             :   public:
    1251       69912 :     MapHNode(Node *n) : HNode(n) { }
    1252             : 
    1253             :     static bool classof(const HNode *n) {
    1254             :       return MappingNode::classof(n->_node);
    1255             :     }
    1256             : 
    1257             :     static bool classof(const MapHNode *) { return true; }
    1258             : 
    1259             :     using NameToNode = StringMap<std::unique_ptr<HNode>>;
    1260             : 
    1261             :     NameToNode Mapping;
    1262             :     SmallVector<std::string, 6> ValidKeys;
    1263             :   };
    1264             : 
    1265        9654 :   class SequenceHNode : public HNode {
    1266             :     void anchor() override;
    1267             : 
    1268             :   public:
    1269       19432 :     SequenceHNode(Node *n) : HNode(n) { }
    1270             : 
    1271             :     static bool classof(const HNode *n) {
    1272             :       return SequenceNode::classof(n->_node);
    1273             :     }
    1274             : 
    1275             :     static bool classof(const SequenceHNode *) { return true; }
    1276             : 
    1277             :     std::vector<std::unique_ptr<HNode>> Entries;
    1278             :   };
    1279             : 
    1280             :   std::unique_ptr<Input::HNode> createHNodes(Node *node);
    1281             :   void setError(HNode *hnode, const Twine &message);
    1282             :   void setError(Node *node, const Twine &message);
    1283             : 
    1284             : public:
    1285             :   // These are only used by operator>>. They could be private
    1286             :   // if those templated things could be made friends.
    1287             :   bool setCurrentDocument();
    1288             :   bool nextDocument();
    1289             : 
    1290             :   /// Returns the current node that's being parsed by the YAML Parser.
    1291             :   const Node *getCurrentNode() const;
    1292             : 
    1293             : private:
    1294             :   SourceMgr                           SrcMgr; // must be before Strm
    1295             :   std::unique_ptr<llvm::yaml::Stream> Strm;
    1296             :   std::unique_ptr<HNode>              TopNode;
    1297             :   std::error_code                     EC;
    1298             :   BumpPtrAllocator                    StringAllocator;
    1299             :   document_iterator                   DocIterator;
    1300             :   std::vector<bool>                   BitValuesUsed;
    1301             :   HNode *CurrentNode = nullptr;
    1302             :   bool                                ScalarMatchFound;
    1303             : };
    1304             : 
    1305             : ///
    1306             : /// The Output class is used to generate a yaml document from in-memory structs
    1307             : /// and vectors.
    1308             : ///
    1309        9855 : class Output : public IO {
    1310             : public:
    1311             :   Output(raw_ostream &, void *Ctxt = nullptr, int WrapColumn = 70);
    1312             :   ~Output() override;
    1313             : 
    1314             :   /// \brief Set whether or not to output optional values which are equal
    1315             :   /// to the default value.  By default, when outputting if you attempt
    1316             :   /// to write a value that is equal to the default, the value gets ignored.
    1317             :   /// Sometimes, it is useful to be able to see these in the resulting YAML
    1318             :   /// anyway.
    1319        3135 :   void setWriteDefaultValues(bool Write) { WriteDefaultValues = Write; }
    1320             : 
    1321             :   bool outputting() override;
    1322             :   bool mapTag(StringRef, bool) override;
    1323             :   void beginMapping() override;
    1324             :   void endMapping() override;
    1325             :   bool preflightKey(const char *key, bool, bool, bool &, void *&) override;
    1326             :   void postflightKey(void *) override;
    1327             :   std::vector<StringRef> keys() override;
    1328             :   void beginFlowMapping() override;
    1329             :   void endFlowMapping() override;
    1330             :   unsigned beginSequence() override;
    1331             :   void endSequence() override;
    1332             :   bool preflightElement(unsigned, void *&) override;
    1333             :   void postflightElement(void *) override;
    1334             :   unsigned beginFlowSequence() override;
    1335             :   bool preflightFlowElement(unsigned, void *&) override;
    1336             :   void postflightFlowElement(void *) override;
    1337             :   void endFlowSequence() override;
    1338             :   void beginEnumScalar() override;
    1339             :   bool matchEnumScalar(const char*, bool) override;
    1340             :   bool matchEnumFallback() override;
    1341             :   void endEnumScalar() override;
    1342             :   bool beginBitSetScalar(bool &) override;
    1343             :   bool bitSetMatch(const char *, bool ) override;
    1344             :   void endBitSetScalar() override;
    1345             :   void scalarString(StringRef &, QuotingType) override;
    1346             :   void blockScalarString(StringRef &) override;
    1347             :   void setError(const Twine &message) override;
    1348             :   bool canElideEmptySequence() override;
    1349             : 
    1350             :   // These are only used by operator<<. They could be private
    1351             :   // if that templated operator could be made a friend.
    1352             :   void beginDocuments();
    1353             :   bool preflightDocument(unsigned);
    1354             :   void postflightDocument();
    1355             :   void endDocuments();
    1356             : 
    1357             : private:
    1358             :   void output(StringRef s);
    1359             :   void outputUpToEndOfLine(StringRef s);
    1360             :   void newLineCheck();
    1361             :   void outputNewLine();
    1362             :   void paddedKey(StringRef key);
    1363             :   void flowKey(StringRef Key);
    1364             : 
    1365             :   enum InState {
    1366             :     inSeq,
    1367             :     inFlowSeq,
    1368             :     inMapFirstKey,
    1369             :     inMapOtherKey,
    1370             :     inFlowMapFirstKey,
    1371             :     inFlowMapOtherKey
    1372             :   };
    1373             : 
    1374             :   raw_ostream &Out;
    1375             :   int WrapColumn;
    1376             :   SmallVector<InState, 8> StateStack;
    1377             :   int Column = 0;
    1378             :   int ColumnAtFlowStart = 0;
    1379             :   int ColumnAtMapFlowStart = 0;
    1380             :   bool NeedBitValueComma = false;
    1381             :   bool NeedFlowSequenceComma = false;
    1382             :   bool EnumerationMatchFound = false;
    1383             :   bool NeedsNewLine = false;
    1384             :   bool WriteDefaultValues = false;
    1385             : };
    1386             : 
    1387             : /// YAML I/O does conversion based on types. But often native data types
    1388             : /// are just a typedef of built in intergral types (e.g. int).  But the C++
    1389             : /// type matching system sees through the typedef and all the typedefed types
    1390             : /// look like a built in type. This will cause the generic YAML I/O conversion
    1391             : /// to be used. To provide better control over the YAML conversion, you can
    1392             : /// use this macro instead of typedef.  It will create a class with one field
    1393             : /// and automatic conversion operators to and from the base type.
    1394             : /// Based on BOOST_STRONG_TYPEDEF
    1395             : #define LLVM_YAML_STRONG_TYPEDEF(_base, _type)                                 \
    1396             :     struct _type {                                                             \
    1397             :         _type() = default;                                                     \
    1398             :         _type(const _base v) : value(v) {}                                     \
    1399             :         _type(const _type &v) = default;                                       \
    1400             :         _type &operator=(const _type &rhs) = default;                          \
    1401             :         _type &operator=(const _base &rhs) { value = rhs; return *this; }      \
    1402             :         operator const _base & () const { return value; }                      \
    1403             :         bool operator==(const _type &rhs) const { return value == rhs.value; } \
    1404             :         bool operator==(const _base &rhs) const { return value == rhs; }       \
    1405             :         bool operator<(const _type &rhs) const { return value < rhs.value; }   \
    1406             :         _base value;                                                           \
    1407             :         using BaseType = _base;                                                \
    1408             :     };
    1409             : 
    1410             : ///
    1411             : /// Use these types instead of uintXX_t in any mapping to have
    1412             : /// its yaml output formatted as hexadecimal.
    1413             : ///
    1414        6351 : LLVM_YAML_STRONG_TYPEDEF(uint8_t, Hex8)
    1415         213 : LLVM_YAML_STRONG_TYPEDEF(uint16_t, Hex16)
    1416        8923 : LLVM_YAML_STRONG_TYPEDEF(uint32_t, Hex32)
    1417       16602 : LLVM_YAML_STRONG_TYPEDEF(uint64_t, Hex64)
    1418             : 
    1419             : template<>
    1420             : struct ScalarTraits<Hex8> {
    1421             :   static void output(const Hex8 &, void *, raw_ostream &);
    1422             :   static StringRef input(StringRef, void *, Hex8 &);
    1423             :   static QuotingType mustQuote(StringRef) { return QuotingType::None; }
    1424             : };
    1425             : 
    1426             : template<>
    1427             : struct ScalarTraits<Hex16> {
    1428             :   static void output(const Hex16 &, void *, raw_ostream &);
    1429             :   static StringRef input(StringRef, void *, Hex16 &);
    1430             :   static QuotingType mustQuote(StringRef) { return QuotingType::None; }
    1431             : };
    1432             : 
    1433             : template<>
    1434             : struct ScalarTraits<Hex32> {
    1435             :   static void output(const Hex32 &, void *, raw_ostream &);
    1436             :   static StringRef input(StringRef, void *, Hex32 &);
    1437             :   static QuotingType mustQuote(StringRef) { return QuotingType::None; }
    1438             : };
    1439             : 
    1440             : template<>
    1441             : struct ScalarTraits<Hex64> {
    1442             :   static void output(const Hex64 &, void *, raw_ostream &);
    1443             :   static StringRef input(StringRef, void *, Hex64 &);
    1444             :   static QuotingType mustQuote(StringRef) { return QuotingType::None; }
    1445             : };
    1446             : 
    1447             : // Define non-member operator>> so that Input can stream in a document list.
    1448             : template <typename T>
    1449             : inline
    1450             : typename std::enable_if<has_DocumentListTraits<T>::value, Input &>::type
    1451         770 : operator>>(Input &yin, T &docList) {
    1452             :   int i = 0;
    1453             :   EmptyContext Ctx;
    1454        2424 :   while ( yin.setCurrentDocument() ) {
    1455         838 :     yamlize(yin, DocumentListTraits<T>::element(yin, docList, i), true, Ctx);
    1456         838 :     if ( yin.error() )
    1457             :       return yin;
    1458         827 :     yin.nextDocument();
    1459         827 :     ++i;
    1460             :   }
    1461             :   return yin;
    1462             : }
    1463             : 
    1464             : // Define non-member operator>> so that Input can stream in a map as a document.
    1465             : template <typename T>
    1466             : inline typename std::enable_if<has_MappingTraits<T, EmptyContext>::value,
    1467             :                                Input &>::type
    1468             : operator>>(Input &yin, T &docMap) {
    1469             :   EmptyContext Ctx;
    1470        1090 :   yin.setCurrentDocument();
    1471        1090 :   yamlize(yin, docMap, true, Ctx);
    1472             :   return yin;
    1473             : }
    1474             : 
    1475             : // Define non-member operator>> so that Input can stream in a sequence as
    1476             : // a document.
    1477             : template <typename T>
    1478             : inline
    1479             : typename std::enable_if<has_SequenceTraits<T>::value, Input &>::type
    1480         431 : operator>>(Input &yin, T &docSeq) {
    1481             :   EmptyContext Ctx;
    1482         431 :   if (yin.setCurrentDocument())
    1483          72 :     yamlize(yin, docSeq, true, Ctx);
    1484         431 :   return yin;
    1485             : }
    1486             : 
    1487             : // Define non-member operator>> so that Input can stream in a block scalar.
    1488             : template <typename T>
    1489             : inline
    1490             : typename std::enable_if<has_BlockScalarTraits<T>::value, Input &>::type
    1491           1 : operator>>(Input &In, T &Val) {
    1492             :   EmptyContext Ctx;
    1493           1 :   if (In.setCurrentDocument())
    1494           1 :     yamlize(In, Val, true, Ctx);
    1495           1 :   return In;
    1496             : }
    1497             : 
    1498             : // Define non-member operator>> so that Input can stream in a string map.
    1499             : template <typename T>
    1500             : inline
    1501             : typename std::enable_if<has_CustomMappingTraits<T>::value, Input &>::type
    1502           2 : operator>>(Input &In, T &Val) {
    1503             :   EmptyContext Ctx;
    1504           2 :   if (In.setCurrentDocument())
    1505           2 :     yamlize(In, Val, true, Ctx);
    1506           2 :   return In;
    1507             : }
    1508             : 
    1509             : // Provide better error message about types missing a trait specialization
    1510             : template <typename T>
    1511             : inline typename std::enable_if<missingTraits<T, EmptyContext>::value,
    1512             :                                Input &>::type
    1513             : operator>>(Input &yin, T &docSeq) {
    1514             :   char missing_yaml_trait_for_type[sizeof(MissingTrait<T>)];
    1515             :   return yin;
    1516             : }
    1517             : 
    1518             : // Define non-member operator<< so that Output can stream out document list.
    1519             : template <typename T>
    1520             : inline
    1521             : typename std::enable_if<has_DocumentListTraits<T>::value, Output &>::type
    1522           3 : operator<<(Output &yout, T &docList) {
    1523             :   EmptyContext Ctx;
    1524           3 :   yout.beginDocuments();
    1525           3 :   const size_t count = DocumentListTraits<T>::size(yout, docList);
    1526          13 :   for(size_t i=0; i < count; ++i) {
    1527           5 :     if ( yout.preflightDocument(i) ) {
    1528           5 :       yamlize(yout, DocumentListTraits<T>::element(yout, docList, i), true,
    1529             :               Ctx);
    1530           5 :       yout.postflightDocument();
    1531             :     }
    1532             :   }
    1533           3 :   yout.endDocuments();
    1534           3 :   return yout;
    1535             : }
    1536             : 
    1537             : // Define non-member operator<< so that Output can stream out a map.
    1538             : template <typename T>
    1539             : inline typename std::enable_if<has_MappingTraits<T, EmptyContext>::value,
    1540             :                                Output &>::type
    1541        4305 : operator<<(Output &yout, T &map) {
    1542             :   EmptyContext Ctx;
    1543        4305 :   yout.beginDocuments();
    1544        4305 :   if ( yout.preflightDocument(0) ) {
    1545        4305 :     yamlize(yout, map, true, Ctx);
    1546        4305 :     yout.postflightDocument();
    1547             :   }
    1548        4305 :   yout.endDocuments();
    1549        4305 :   return yout;
    1550             : }
    1551             : 
    1552             : // Define non-member operator<< so that Output can stream out a sequence.
    1553             : template <typename T>
    1554             : inline
    1555             : typename std::enable_if<has_SequenceTraits<T>::value, Output &>::type
    1556           9 : operator<<(Output &yout, T &seq) {
    1557             :   EmptyContext Ctx;
    1558           9 :   yout.beginDocuments();
    1559           9 :   if ( yout.preflightDocument(0) ) {
    1560           9 :     yamlize(yout, seq, true, Ctx);
    1561           9 :     yout.postflightDocument();
    1562             :   }
    1563           9 :   yout.endDocuments();
    1564           9 :   return yout;
    1565             : }
    1566             : 
    1567             : // Define non-member operator<< so that Output can stream out a block scalar.
    1568             : template <typename T>
    1569             : inline
    1570             : typename std::enable_if<has_BlockScalarTraits<T>::value, Output &>::type
    1571         725 : operator<<(Output &Out, T &Val) {
    1572             :   EmptyContext Ctx;
    1573         725 :   Out.beginDocuments();
    1574         725 :   if (Out.preflightDocument(0)) {
    1575         725 :     yamlize(Out, Val, true, Ctx);
    1576         725 :     Out.postflightDocument();
    1577             :   }
    1578         725 :   Out.endDocuments();
    1579         725 :   return Out;
    1580             : }
    1581             : 
    1582             : // Define non-member operator<< so that Output can stream out a string map.
    1583             : template <typename T>
    1584             : inline
    1585             : typename std::enable_if<has_CustomMappingTraits<T>::value, Output &>::type
    1586           2 : operator<<(Output &Out, T &Val) {
    1587             :   EmptyContext Ctx;
    1588           2 :   Out.beginDocuments();
    1589           2 :   if (Out.preflightDocument(0)) {
    1590           2 :     yamlize(Out, Val, true, Ctx);
    1591           2 :     Out.postflightDocument();
    1592             :   }
    1593           2 :   Out.endDocuments();
    1594           2 :   return Out;
    1595             : }
    1596             : 
    1597             : // Provide better error message about types missing a trait specialization
    1598             : template <typename T>
    1599             : inline typename std::enable_if<missingTraits<T, EmptyContext>::value,
    1600             :                                Output &>::type
    1601             : operator<<(Output &yout, T &seq) {
    1602             :   char missing_yaml_trait_for_type[sizeof(MissingTrait<T>)];
    1603             :   return yout;
    1604             : }
    1605             : 
    1606             : template <bool B> struct IsFlowSequenceBase {};
    1607             : template <> struct IsFlowSequenceBase<true> { static const bool flow = true; };
    1608             : 
    1609             : template <typename T, bool Flow>
    1610             : struct SequenceTraitsImpl : IsFlowSequenceBase<Flow> {
    1611             : private:
    1612             :   using type = typename T::value_type;
    1613             : 
    1614             : public:
    1615       21678 :   static size_t size(IO &io, T &seq) { return seq.size(); }
    1616             : 
    1617       79734 :   static type &element(IO &io, T &seq, size_t index) {
    1618      168553 :     if (index >= seq.size())
    1619       27514 :       seq.resize(index + 1);
    1620      163342 :     return seq[index];
    1621             :   }
    1622             : };
    1623             : 
    1624             : // Simple helper to check an expression can be used as a bool-valued template
    1625             : // argument.
    1626             : template <bool> struct CheckIsBool { static const bool value = true; };
    1627             : 
    1628             : // If T has SequenceElementTraits, then vector<T> and SmallVector<T, N> have
    1629             : // SequenceTraits that do the obvious thing.
    1630             : template <typename T>
    1631             : struct SequenceTraits<std::vector<T>,
    1632             :                       typename std::enable_if<CheckIsBool<
    1633             :                           SequenceElementTraits<T>::flow>::value>::type>
    1634             :     : SequenceTraitsImpl<std::vector<T>, SequenceElementTraits<T>::flow> {};
    1635             : template <typename T, unsigned N>
    1636             : struct SequenceTraits<SmallVector<T, N>,
    1637             :                       typename std::enable_if<CheckIsBool<
    1638             :                           SequenceElementTraits<T>::flow>::value>::type>
    1639             :     : SequenceTraitsImpl<SmallVector<T, N>, SequenceElementTraits<T>::flow> {};
    1640             : 
    1641             : // Sequences of fundamental types use flow formatting.
    1642             : template <typename T>
    1643             : struct SequenceElementTraits<
    1644             :     T, typename std::enable_if<std::is_fundamental<T>::value>::type> {
    1645             :   static const bool flow = true;
    1646             : };
    1647             : 
    1648             : // Sequences of strings use block formatting.
    1649             : template<> struct SequenceElementTraits<std::string> {
    1650             :   static const bool flow = false;
    1651             : };
    1652             : template<> struct SequenceElementTraits<StringRef> {
    1653             :   static const bool flow = false;
    1654             : };
    1655             : template<> struct SequenceElementTraits<std::pair<std::string, std::string>> {
    1656             :   static const bool flow = false;
    1657             : };
    1658             : 
    1659             : /// Implementation of CustomMappingTraits for std::map<std::string, T>.
    1660             : template <typename T> struct StdMapStringCustomMappingTraitsImpl {
    1661             :   using map_type = std::map<std::string, T>;
    1662             : 
    1663          52 :   static void inputOne(IO &io, StringRef key, map_type &v) {
    1664         156 :     io.mapRequired(key.str().c_str(), v[key]);
    1665          52 :   }
    1666             : 
    1667          22 :   static void output(IO &io, map_type &v) {
    1668          60 :     for (auto &p : v)
    1669          38 :       io.mapRequired(p.first.c_str(), p.second);
    1670          22 :   }
    1671             : };
    1672             : 
    1673             : } // end namespace yaml
    1674             : } // end namespace llvm
    1675             : 
    1676             : #define LLVM_YAML_IS_SEQUENCE_VECTOR_IMPL(TYPE, FLOW)                          \
    1677             :   namespace llvm {                                                             \
    1678             :   namespace yaml {                                                             \
    1679             :   static_assert(                                                               \
    1680             :       !std::is_fundamental<TYPE>::value &&                                     \
    1681             :       !std::is_same<TYPE, std::string>::value &&                               \
    1682             :       !std::is_same<TYPE, llvm::StringRef>::value,                             \
    1683             :       "only use LLVM_YAML_IS_SEQUENCE_VECTOR for types you control");          \
    1684             :   template <> struct SequenceElementTraits<TYPE> {                             \
    1685             :     static const bool flow = FLOW;                                             \
    1686             :   };                                                                           \
    1687             :   }                                                                            \
    1688             :   }
    1689             : 
    1690             : /// Utility for declaring that a std::vector of a particular type
    1691             : /// should be considered a YAML sequence.
    1692             : #define LLVM_YAML_IS_SEQUENCE_VECTOR(type)                                     \
    1693             :   LLVM_YAML_IS_SEQUENCE_VECTOR_IMPL(type, false)
    1694             : 
    1695             : /// Utility for declaring that a std::vector of a particular type
    1696             : /// should be considered a YAML flow sequence.
    1697             : #define LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(type)                                \
    1698             :   LLVM_YAML_IS_SEQUENCE_VECTOR_IMPL(type, true)
    1699             : 
    1700             : #define LLVM_YAML_DECLARE_MAPPING_TRAITS(Type)                                 \
    1701             :   namespace llvm {                                                             \
    1702             :   namespace yaml {                                                             \
    1703             :   template <> struct MappingTraits<Type> {                                     \
    1704             :     static void mapping(IO &IO, Type &Obj);                                    \
    1705             :   };                                                                           \
    1706             :   }                                                                            \
    1707             :   }
    1708             : 
    1709             : #define LLVM_YAML_DECLARE_ENUM_TRAITS(Type)                                    \
    1710             :   namespace llvm {                                                             \
    1711             :   namespace yaml {                                                             \
    1712             :   template <> struct ScalarEnumerationTraits<Type> {                           \
    1713             :     static void enumeration(IO &io, Type &Value);                              \
    1714             :   };                                                                           \
    1715             :   }                                                                            \
    1716             :   }
    1717             : 
    1718             : #define LLVM_YAML_DECLARE_BITSET_TRAITS(Type)                                  \
    1719             :   namespace llvm {                                                             \
    1720             :   namespace yaml {                                                             \
    1721             :   template <> struct ScalarBitSetTraits<Type> {                                \
    1722             :     static void bitset(IO &IO, Type &Options);                                 \
    1723             :   };                                                                           \
    1724             :   }                                                                            \
    1725             :   }
    1726             : 
    1727             : #define LLVM_YAML_DECLARE_SCALAR_TRAITS(Type, MustQuote)                       \
    1728             :   namespace llvm {                                                             \
    1729             :   namespace yaml {                                                             \
    1730             :   template <> struct ScalarTraits<Type> {                                      \
    1731             :     static void output(const Type &Value, void *ctx, raw_ostream &Out);        \
    1732             :     static StringRef input(StringRef Scalar, void *ctxt, Type &Value);         \
    1733             :     static QuotingType mustQuote(StringRef) { return MustQuote; }              \
    1734             :   };                                                                           \
    1735             :   }                                                                            \
    1736             :   }
    1737             : 
    1738             : /// Utility for declaring that a std::vector of a particular type
    1739             : /// should be considered a YAML document list.
    1740             : #define LLVM_YAML_IS_DOCUMENT_LIST_VECTOR(_type)                               \
    1741             :   namespace llvm {                                                             \
    1742             :   namespace yaml {                                                             \
    1743             :   template <unsigned N>                                                        \
    1744             :   struct DocumentListTraits<SmallVector<_type, N>>                             \
    1745             :       : public SequenceTraitsImpl<SmallVector<_type, N>, false> {};            \
    1746             :   template <>                                                                  \
    1747             :   struct DocumentListTraits<std::vector<_type>>                                \
    1748             :       : public SequenceTraitsImpl<std::vector<_type>, false> {};               \
    1749             :   }                                                                            \
    1750             :   }
    1751             : 
    1752             : /// Utility for declaring that std::map<std::string, _type> should be considered
    1753             : /// a YAML map.
    1754             : #define LLVM_YAML_IS_STRING_MAP(_type)                                         \
    1755             :   namespace llvm {                                                             \
    1756             :   namespace yaml {                                                             \
    1757             :   template <>                                                                  \
    1758             :   struct CustomMappingTraits<std::map<std::string, _type>>                     \
    1759             :       : public StdMapStringCustomMappingTraitsImpl<_type> {};                  \
    1760             :   }                                                                            \
    1761             :   }
    1762             : 
    1763             : #endif // LLVM_SUPPORT_YAMLTRAITS_H

Generated by: LCOV version 1.13