Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. //===- llvm/Support/YAMLTraits.h --------------------------------*- C++ -*-===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8.  
  9. #ifndef LLVM_SUPPORT_YAMLTRAITS_H
  10. #define LLVM_SUPPORT_YAMLTRAITS_H
  11.  
  12. #include "llvm/ADT/ArrayRef.h"
  13. #include "llvm/ADT/BitVector.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/SMLoc.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 <map>
  28. #include <memory>
  29. #include <new>
  30. #include <optional>
  31. #include <string>
  32. #include <system_error>
  33. #include <type_traits>
  34. #include <vector>
  35.  
  36. namespace llvm {
  37.  
  38. class VersionTuple;
  39.  
  40. namespace yaml {
  41.  
  42. enum class NodeKind : uint8_t {
  43.   Scalar,
  44.   Map,
  45.   Sequence,
  46. };
  47.  
  48. struct EmptyContext {};
  49.  
  50. /// This class should be specialized by any type that needs to be converted
  51. /// to/from a YAML mapping.  For example:
  52. ///
  53. ///     struct MappingTraits<MyStruct> {
  54. ///       static void mapping(IO &io, MyStruct &s) {
  55. ///         io.mapRequired("name", s.name);
  56. ///         io.mapRequired("size", s.size);
  57. ///         io.mapOptional("age",  s.age);
  58. ///       }
  59. ///     };
  60. template<class T>
  61. struct MappingTraits {
  62.   // Must provide:
  63.   // static void mapping(IO &io, T &fields);
  64.   // Optionally may provide:
  65.   // static std::string validate(IO &io, T &fields);
  66.   // static void enumInput(IO &io, T &value);
  67.   //
  68.   // The optional flow flag will cause generated YAML to use a flow mapping
  69.   // (e.g. { a: 0, b: 1 }):
  70.   // static const bool flow = true;
  71. };
  72.  
  73. /// This class is similar to MappingTraits<T> but allows you to pass in
  74. /// additional context for each map operation.  For example:
  75. ///
  76. ///     struct MappingContextTraits<MyStruct, MyContext> {
  77. ///       static void mapping(IO &io, MyStruct &s, MyContext &c) {
  78. ///         io.mapRequired("name", s.name);
  79. ///         io.mapRequired("size", s.size);
  80. ///         io.mapOptional("age",  s.age);
  81. ///         ++c.TimesMapped;
  82. ///       }
  83. ///     };
  84. template <class T, class Context> struct MappingContextTraits {
  85.   // Must provide:
  86.   // static void mapping(IO &io, T &fields, Context &Ctx);
  87.   // Optionally may provide:
  88.   // static std::string validate(IO &io, T &fields, Context &Ctx);
  89.   //
  90.   // The optional flow flag will cause generated YAML to use a flow mapping
  91.   // (e.g. { a: 0, b: 1 }):
  92.   // static const bool flow = true;
  93. };
  94.  
  95. /// This class should be specialized by any integral type that converts
  96. /// to/from a YAML scalar where there is a one-to-one mapping between
  97. /// in-memory values and a string in YAML.  For example:
  98. ///
  99. ///     struct ScalarEnumerationTraits<Colors> {
  100. ///         static void enumeration(IO &io, Colors &value) {
  101. ///           io.enumCase(value, "red",   cRed);
  102. ///           io.enumCase(value, "blue",  cBlue);
  103. ///           io.enumCase(value, "green", cGreen);
  104. ///         }
  105. ///       };
  106. template <typename T, typename Enable = void> struct ScalarEnumerationTraits {
  107.   // Must provide:
  108.   // static void enumeration(IO &io, T &value);
  109. };
  110.  
  111. /// This class should be specialized by any integer type that is a union
  112. /// of bit values and the YAML representation is a flow sequence of
  113. /// strings.  For example:
  114. ///
  115. ///      struct ScalarBitSetTraits<MyFlags> {
  116. ///        static void bitset(IO &io, MyFlags &value) {
  117. ///          io.bitSetCase(value, "big",   flagBig);
  118. ///          io.bitSetCase(value, "flat",  flagFlat);
  119. ///          io.bitSetCase(value, "round", flagRound);
  120. ///        }
  121. ///      };
  122. template <typename T, typename Enable = void> struct ScalarBitSetTraits {
  123.   // Must provide:
  124.   // static void bitset(IO &io, T &value);
  125. };
  126.  
  127. /// Describe which type of quotes should be used when quoting is necessary.
  128. /// Some non-printable characters need to be double-quoted, while some others
  129. /// are fine with simple-quoting, and some don't need any quoting.
  130. enum class QuotingType { None, Single, Double };
  131.  
  132. /// This class should be specialized by type that requires custom conversion
  133. /// to/from a yaml scalar.  For example:
  134. ///
  135. ///    template<>
  136. ///    struct ScalarTraits<MyType> {
  137. ///      static void output(const MyType &val, void*, llvm::raw_ostream &out) {
  138. ///        // stream out custom formatting
  139. ///        out << llvm::format("%x", val);
  140. ///      }
  141. ///      static StringRef input(StringRef scalar, void*, MyType &value) {
  142. ///        // parse scalar and set `value`
  143. ///        // return empty string on success, or error string
  144. ///        return StringRef();
  145. ///      }
  146. ///      static QuotingType mustQuote(StringRef) { return QuotingType::Single; }
  147. ///    };
  148. template <typename T, typename Enable = void> struct ScalarTraits {
  149.   // Must provide:
  150.   //
  151.   // Function to write the value as a string:
  152.   // static void output(const T &value, void *ctxt, llvm::raw_ostream &out);
  153.   //
  154.   // Function to convert a string to a value.  Returns the empty
  155.   // StringRef on success or an error string if string is malformed:
  156.   // static StringRef input(StringRef scalar, void *ctxt, T &value);
  157.   //
  158.   // Function to determine if the value should be quoted.
  159.   // static QuotingType mustQuote(StringRef);
  160. };
  161.  
  162. /// This class should be specialized by type that requires custom conversion
  163. /// to/from a YAML literal block scalar. For example:
  164. ///
  165. ///    template <>
  166. ///    struct BlockScalarTraits<MyType> {
  167. ///      static void output(const MyType &Value, void*, llvm::raw_ostream &Out)
  168. ///      {
  169. ///        // stream out custom formatting
  170. ///        Out << Value;
  171. ///      }
  172. ///      static StringRef input(StringRef Scalar, void*, MyType &Value) {
  173. ///        // parse scalar and set `value`
  174. ///        // return empty string on success, or error string
  175. ///        return StringRef();
  176. ///      }
  177. ///    };
  178. template <typename T>
  179. struct BlockScalarTraits {
  180.   // Must provide:
  181.   //
  182.   // Function to write the value as a string:
  183.   // static void output(const T &Value, void *ctx, llvm::raw_ostream &Out);
  184.   //
  185.   // Function to convert a string to a value.  Returns the empty
  186.   // StringRef on success or an error string if string is malformed:
  187.   // static StringRef input(StringRef Scalar, void *ctxt, T &Value);
  188.   //
  189.   // Optional:
  190.   // static StringRef inputTag(T &Val, std::string Tag)
  191.   // static void outputTag(const T &Val, raw_ostream &Out)
  192. };
  193.  
  194. /// This class should be specialized by type that requires custom conversion
  195. /// to/from a YAML scalar with optional tags. For example:
  196. ///
  197. ///    template <>
  198. ///    struct TaggedScalarTraits<MyType> {
  199. ///      static void output(const MyType &Value, void*, llvm::raw_ostream
  200. ///      &ScalarOut, llvm::raw_ostream &TagOut)
  201. ///      {
  202. ///        // stream out custom formatting including optional Tag
  203. ///        Out << Value;
  204. ///      }
  205. ///      static StringRef input(StringRef Scalar, StringRef Tag, void*, MyType
  206. ///      &Value) {
  207. ///        // parse scalar and set `value`
  208. ///        // return empty string on success, or error string
  209. ///        return StringRef();
  210. ///      }
  211. ///      static QuotingType mustQuote(const MyType &Value, StringRef) {
  212. ///        return QuotingType::Single;
  213. ///      }
  214. ///    };
  215. template <typename T> struct TaggedScalarTraits {
  216.   // Must provide:
  217.   //
  218.   // Function to write the value and tag as strings:
  219.   // static void output(const T &Value, void *ctx, llvm::raw_ostream &ScalarOut,
  220.   // llvm::raw_ostream &TagOut);
  221.   //
  222.   // Function to convert a string to a value.  Returns the empty
  223.   // StringRef on success or an error string if string is malformed:
  224.   // static StringRef input(StringRef Scalar, StringRef Tag, void *ctxt, T
  225.   // &Value);
  226.   //
  227.   // Function to determine if the value should be quoted.
  228.   // static QuotingType mustQuote(const T &Value, StringRef Scalar);
  229. };
  230.  
  231. /// This class should be specialized by any type that needs to be converted
  232. /// to/from a YAML sequence.  For example:
  233. ///
  234. ///    template<>
  235. ///    struct SequenceTraits<MyContainer> {
  236. ///      static size_t size(IO &io, MyContainer &seq) {
  237. ///        return seq.size();
  238. ///      }
  239. ///      static MyType& element(IO &, MyContainer &seq, size_t index) {
  240. ///        if ( index >= seq.size() )
  241. ///          seq.resize(index+1);
  242. ///        return seq[index];
  243. ///      }
  244. ///    };
  245. template<typename T, typename EnableIf = void>
  246. struct SequenceTraits {
  247.   // Must provide:
  248.   // static size_t size(IO &io, T &seq);
  249.   // static T::value_type& element(IO &io, T &seq, size_t index);
  250.   //
  251.   // The following is option and will cause generated YAML to use
  252.   // a flow sequence (e.g. [a,b,c]).
  253.   // static const bool flow = true;
  254. };
  255.  
  256. /// This class should be specialized by any type for which vectors of that
  257. /// type need to be converted to/from a YAML sequence.
  258. template<typename T, typename EnableIf = void>
  259. struct SequenceElementTraits {
  260.   // Must provide:
  261.   // static const bool flow;
  262. };
  263.  
  264. /// This class should be specialized by any type that needs to be converted
  265. /// to/from a list of YAML documents.
  266. template<typename T>
  267. struct DocumentListTraits {
  268.   // Must provide:
  269.   // static size_t size(IO &io, T &seq);
  270.   // static T::value_type& element(IO &io, T &seq, size_t index);
  271. };
  272.  
  273. /// This class should be specialized by any type that needs to be converted
  274. /// to/from a YAML mapping in the case where the names of the keys are not known
  275. /// in advance, e.g. a string map.
  276. template <typename T>
  277. struct CustomMappingTraits {
  278.   // static void inputOne(IO &io, StringRef key, T &elem);
  279.   // static void output(IO &io, T &elem);
  280. };
  281.  
  282. /// This class should be specialized by any type that can be represented as
  283. /// a scalar, map, or sequence, decided dynamically. For example:
  284. ///
  285. ///    typedef std::unique_ptr<MyBase> MyPoly;
  286. ///
  287. ///    template<>
  288. ///    struct PolymorphicTraits<MyPoly> {
  289. ///      static NodeKind getKind(const MyPoly &poly) {
  290. ///        return poly->getKind();
  291. ///      }
  292. ///      static MyScalar& getAsScalar(MyPoly &poly) {
  293. ///        if (!poly || !isa<MyScalar>(poly))
  294. ///          poly.reset(new MyScalar());
  295. ///        return *cast<MyScalar>(poly.get());
  296. ///      }
  297. ///      // ...
  298. ///    };
  299. template <typename T> struct PolymorphicTraits {
  300.   // Must provide:
  301.   // static NodeKind getKind(const T &poly);
  302.   // static scalar_type &getAsScalar(T &poly);
  303.   // static map_type &getAsMap(T &poly);
  304.   // static sequence_type &getAsSequence(T &poly);
  305. };
  306.  
  307. // Only used for better diagnostics of missing traits
  308. template <typename T>
  309. struct MissingTrait;
  310.  
  311. // Test if ScalarEnumerationTraits<T> is defined on type T.
  312. template <class T>
  313. struct has_ScalarEnumerationTraits
  314. {
  315.   using Signature_enumeration = void (*)(class IO&, T&);
  316.  
  317.   template <typename U>
  318.   static char test(SameType<Signature_enumeration, &U::enumeration>*);
  319.  
  320.   template <typename U>
  321.   static double test(...);
  322.  
  323.   static bool const value =
  324.     (sizeof(test<ScalarEnumerationTraits<T>>(nullptr)) == 1);
  325. };
  326.  
  327. // Test if ScalarBitSetTraits<T> is defined on type T.
  328. template <class T>
  329. struct has_ScalarBitSetTraits
  330. {
  331.   using Signature_bitset = void (*)(class IO&, T&);
  332.  
  333.   template <typename U>
  334.   static char test(SameType<Signature_bitset, &U::bitset>*);
  335.  
  336.   template <typename U>
  337.   static double test(...);
  338.  
  339.   static bool const value = (sizeof(test<ScalarBitSetTraits<T>>(nullptr)) == 1);
  340. };
  341.  
  342. // Test if ScalarTraits<T> is defined on type T.
  343. template <class T>
  344. struct has_ScalarTraits
  345. {
  346.   using Signature_input = StringRef (*)(StringRef, void*, T&);
  347.   using Signature_output = void (*)(const T&, void*, raw_ostream&);
  348.   using Signature_mustQuote = QuotingType (*)(StringRef);
  349.  
  350.   template <typename U>
  351.   static char test(SameType<Signature_input, &U::input> *,
  352.                    SameType<Signature_output, &U::output> *,
  353.                    SameType<Signature_mustQuote, &U::mustQuote> *);
  354.  
  355.   template <typename U>
  356.   static double test(...);
  357.  
  358.   static bool const value =
  359.       (sizeof(test<ScalarTraits<T>>(nullptr, nullptr, nullptr)) == 1);
  360. };
  361.  
  362. // Test if BlockScalarTraits<T> is defined on type T.
  363. template <class T>
  364. struct has_BlockScalarTraits
  365. {
  366.   using Signature_input = StringRef (*)(StringRef, void *, T &);
  367.   using Signature_output = void (*)(const T &, void *, raw_ostream &);
  368.  
  369.   template <typename U>
  370.   static char test(SameType<Signature_input, &U::input> *,
  371.                    SameType<Signature_output, &U::output> *);
  372.  
  373.   template <typename U>
  374.   static double test(...);
  375.  
  376.   static bool const value =
  377.       (sizeof(test<BlockScalarTraits<T>>(nullptr, nullptr)) == 1);
  378. };
  379.  
  380. // Test if TaggedScalarTraits<T> is defined on type T.
  381. template <class T> struct has_TaggedScalarTraits {
  382.   using Signature_input = StringRef (*)(StringRef, StringRef, void *, T &);
  383.   using Signature_output = void (*)(const T &, void *, raw_ostream &,
  384.                                     raw_ostream &);
  385.   using Signature_mustQuote = QuotingType (*)(const T &, StringRef);
  386.  
  387.   template <typename U>
  388.   static char test(SameType<Signature_input, &U::input> *,
  389.                    SameType<Signature_output, &U::output> *,
  390.                    SameType<Signature_mustQuote, &U::mustQuote> *);
  391.  
  392.   template <typename U> static double test(...);
  393.  
  394.   static bool const value =
  395.       (sizeof(test<TaggedScalarTraits<T>>(nullptr, nullptr, nullptr)) == 1);
  396. };
  397.  
  398. // Test if MappingContextTraits<T> is defined on type T.
  399. template <class T, class Context> struct has_MappingTraits {
  400.   using Signature_mapping = void (*)(class IO &, T &, Context &);
  401.  
  402.   template <typename U>
  403.   static char test(SameType<Signature_mapping, &U::mapping>*);
  404.  
  405.   template <typename U>
  406.   static double test(...);
  407.  
  408.   static bool const value =
  409.       (sizeof(test<MappingContextTraits<T, Context>>(nullptr)) == 1);
  410. };
  411.  
  412. // Test if MappingTraits<T> is defined on type T.
  413. template <class T> struct has_MappingTraits<T, EmptyContext> {
  414.   using Signature_mapping = void (*)(class IO &, T &);
  415.  
  416.   template <typename U>
  417.   static char test(SameType<Signature_mapping, &U::mapping> *);
  418.  
  419.   template <typename U> static double test(...);
  420.  
  421.   static bool const value = (sizeof(test<MappingTraits<T>>(nullptr)) == 1);
  422. };
  423.  
  424. // Test if MappingContextTraits<T>::validate() is defined on type T.
  425. template <class T, class Context> struct has_MappingValidateTraits {
  426.   using Signature_validate = std::string (*)(class IO &, T &, Context &);
  427.  
  428.   template <typename U>
  429.   static char test(SameType<Signature_validate, &U::validate>*);
  430.  
  431.   template <typename U>
  432.   static double test(...);
  433.  
  434.   static bool const value =
  435.       (sizeof(test<MappingContextTraits<T, Context>>(nullptr)) == 1);
  436. };
  437.  
  438. // Test if MappingTraits<T>::validate() is defined on type T.
  439. template <class T> struct has_MappingValidateTraits<T, EmptyContext> {
  440.   using Signature_validate = std::string (*)(class IO &, T &);
  441.  
  442.   template <typename U>
  443.   static char test(SameType<Signature_validate, &U::validate> *);
  444.  
  445.   template <typename U> static double test(...);
  446.  
  447.   static bool const value = (sizeof(test<MappingTraits<T>>(nullptr)) == 1);
  448. };
  449.  
  450. // Test if MappingContextTraits<T>::enumInput() is defined on type T.
  451. template <class T, class Context> struct has_MappingEnumInputTraits {
  452.   using Signature_validate = void (*)(class IO &, T &);
  453.  
  454.   template <typename U>
  455.   static char test(SameType<Signature_validate, &U::enumInput> *);
  456.  
  457.   template <typename U> static double test(...);
  458.  
  459.   static bool const value =
  460.       (sizeof(test<MappingContextTraits<T, Context>>(nullptr)) == 1);
  461. };
  462.  
  463. // Test if MappingTraits<T>::enumInput() is defined on type T.
  464. template <class T> struct has_MappingEnumInputTraits<T, EmptyContext> {
  465.   using Signature_validate = void (*)(class IO &, T &);
  466.  
  467.   template <typename U>
  468.   static char test(SameType<Signature_validate, &U::enumInput> *);
  469.  
  470.   template <typename U> static double test(...);
  471.  
  472.   static bool const value = (sizeof(test<MappingTraits<T>>(nullptr)) == 1);
  473. };
  474.  
  475. // Test if SequenceTraits<T> is defined on type T.
  476. template <class T>
  477. struct has_SequenceMethodTraits
  478. {
  479.   using Signature_size = size_t (*)(class IO&, T&);
  480.  
  481.   template <typename U>
  482.   static char test(SameType<Signature_size, &U::size>*);
  483.  
  484.   template <typename U>
  485.   static double test(...);
  486.  
  487.   static bool const value =  (sizeof(test<SequenceTraits<T>>(nullptr)) == 1);
  488. };
  489.  
  490. // Test if CustomMappingTraits<T> is defined on type T.
  491. template <class T>
  492. struct has_CustomMappingTraits
  493. {
  494.   using Signature_input = void (*)(IO &io, StringRef key, T &v);
  495.  
  496.   template <typename U>
  497.   static char test(SameType<Signature_input, &U::inputOne>*);
  498.  
  499.   template <typename U>
  500.   static double test(...);
  501.  
  502.   static bool const value =
  503.       (sizeof(test<CustomMappingTraits<T>>(nullptr)) == 1);
  504. };
  505.  
  506. // has_FlowTraits<int> will cause an error with some compilers because
  507. // it subclasses int.  Using this wrapper only instantiates the
  508. // real has_FlowTraits only if the template type is a class.
  509. template <typename T, bool Enabled = std::is_class<T>::value>
  510. class has_FlowTraits
  511. {
  512. public:
  513.    static const bool value = false;
  514. };
  515.  
  516. // Some older gcc compilers don't support straight forward tests
  517. // for members, so test for ambiguity cause by the base and derived
  518. // classes both defining the member.
  519. template <class T>
  520. struct has_FlowTraits<T, true>
  521. {
  522.   struct Fallback { bool flow; };
  523.   struct Derived : T, Fallback { };
  524.  
  525.   template<typename C>
  526.   static char (&f(SameType<bool Fallback::*, &C::flow>*))[1];
  527.  
  528.   template<typename C>
  529.   static char (&f(...))[2];
  530.  
  531.   static bool const value = sizeof(f<Derived>(nullptr)) == 2;
  532. };
  533.  
  534. // Test if SequenceTraits<T> is defined on type T
  535. template<typename T>
  536. struct has_SequenceTraits : public std::integral_constant<bool,
  537.                                       has_SequenceMethodTraits<T>::value > { };
  538.  
  539. // Test if DocumentListTraits<T> is defined on type T
  540. template <class T>
  541. struct has_DocumentListTraits
  542. {
  543.   using Signature_size = size_t (*)(class IO &, T &);
  544.  
  545.   template <typename U>
  546.   static char test(SameType<Signature_size, &U::size>*);
  547.  
  548.   template <typename U>
  549.   static double test(...);
  550.  
  551.   static bool const value = (sizeof(test<DocumentListTraits<T>>(nullptr))==1);
  552. };
  553.  
  554. template <class T> struct has_PolymorphicTraits {
  555.   using Signature_getKind = NodeKind (*)(const T &);
  556.  
  557.   template <typename U>
  558.   static char test(SameType<Signature_getKind, &U::getKind> *);
  559.  
  560.   template <typename U> static double test(...);
  561.  
  562.   static bool const value = (sizeof(test<PolymorphicTraits<T>>(nullptr)) == 1);
  563. };
  564.  
  565. inline bool isNumeric(StringRef S) {
  566.   const auto skipDigits = [](StringRef Input) {
  567.     return Input.ltrim("0123456789");
  568.   };
  569.  
  570.   // Make S.front() and S.drop_front().front() (if S.front() is [+-]) calls
  571.   // safe.
  572.   if (S.empty() || S.equals("+") || S.equals("-"))
  573.     return false;
  574.  
  575.   if (S.equals(".nan") || S.equals(".NaN") || S.equals(".NAN"))
  576.     return true;
  577.  
  578.   // Infinity and decimal numbers can be prefixed with sign.
  579.   StringRef Tail = (S.front() == '-' || S.front() == '+') ? S.drop_front() : S;
  580.  
  581.   // Check for infinity first, because checking for hex and oct numbers is more
  582.   // expensive.
  583.   if (Tail.equals(".inf") || Tail.equals(".Inf") || Tail.equals(".INF"))
  584.     return true;
  585.  
  586.   // Section 10.3.2 Tag Resolution
  587.   // YAML 1.2 Specification prohibits Base 8 and Base 16 numbers prefixed with
  588.   // [-+], so S should be used instead of Tail.
  589.   if (S.startswith("0o"))
  590.     return S.size() > 2 &&
  591.            S.drop_front(2).find_first_not_of("01234567") == StringRef::npos;
  592.  
  593.   if (S.startswith("0x"))
  594.     return S.size() > 2 && S.drop_front(2).find_first_not_of(
  595.                                "0123456789abcdefABCDEF") == StringRef::npos;
  596.  
  597.   // Parse float: [-+]? (\. [0-9]+ | [0-9]+ (\. [0-9]* )?) ([eE] [-+]? [0-9]+)?
  598.   S = Tail;
  599.  
  600.   // Handle cases when the number starts with '.' and hence needs at least one
  601.   // digit after dot (as opposed by number which has digits before the dot), but
  602.   // doesn't have one.
  603.   if (S.startswith(".") &&
  604.       (S.equals(".") ||
  605.        (S.size() > 1 && std::strchr("0123456789", S[1]) == nullptr)))
  606.     return false;
  607.  
  608.   if (S.startswith("E") || S.startswith("e"))
  609.     return false;
  610.  
  611.   enum ParseState {
  612.     Default,
  613.     FoundDot,
  614.     FoundExponent,
  615.   };
  616.   ParseState State = Default;
  617.  
  618.   S = skipDigits(S);
  619.  
  620.   // Accept decimal integer.
  621.   if (S.empty())
  622.     return true;
  623.  
  624.   if (S.front() == '.') {
  625.     State = FoundDot;
  626.     S = S.drop_front();
  627.   } else if (S.front() == 'e' || S.front() == 'E') {
  628.     State = FoundExponent;
  629.     S = S.drop_front();
  630.   } else {
  631.     return false;
  632.   }
  633.  
  634.   if (State == FoundDot) {
  635.     S = skipDigits(S);
  636.     if (S.empty())
  637.       return true;
  638.  
  639.     if (S.front() == 'e' || S.front() == 'E') {
  640.       State = FoundExponent;
  641.       S = S.drop_front();
  642.     } else {
  643.       return false;
  644.     }
  645.   }
  646.  
  647.   assert(State == FoundExponent && "Should have found exponent at this point.");
  648.   if (S.empty())
  649.     return false;
  650.  
  651.   if (S.front() == '+' || S.front() == '-') {
  652.     S = S.drop_front();
  653.     if (S.empty())
  654.       return false;
  655.   }
  656.  
  657.   return skipDigits(S).empty();
  658. }
  659.  
  660. inline bool isNull(StringRef S) {
  661.   return S.equals("null") || S.equals("Null") || S.equals("NULL") ||
  662.          S.equals("~");
  663. }
  664.  
  665. inline bool isBool(StringRef S) {
  666.   // FIXME: using parseBool is causing multiple tests to fail.
  667.   return S.equals("true") || S.equals("True") || S.equals("TRUE") ||
  668.          S.equals("false") || S.equals("False") || S.equals("FALSE");
  669. }
  670.  
  671. // 5.1. Character Set
  672. // The allowed character range explicitly excludes the C0 control block #x0-#x1F
  673. // (except for TAB #x9, LF #xA, and CR #xD which are allowed), DEL #x7F, the C1
  674. // control block #x80-#x9F (except for NEL #x85 which is allowed), the surrogate
  675. // block #xD800-#xDFFF, #xFFFE, and #xFFFF.
  676. inline QuotingType needsQuotes(StringRef S) {
  677.   if (S.empty())
  678.     return QuotingType::Single;
  679.  
  680.   QuotingType MaxQuotingNeeded = QuotingType::None;
  681.   if (isSpace(static_cast<unsigned char>(S.front())) ||
  682.       isSpace(static_cast<unsigned char>(S.back())))
  683.     MaxQuotingNeeded = QuotingType::Single;
  684.   if (isNull(S))
  685.     MaxQuotingNeeded = QuotingType::Single;
  686.   if (isBool(S))
  687.     MaxQuotingNeeded = QuotingType::Single;
  688.   if (isNumeric(S))
  689.     MaxQuotingNeeded = QuotingType::Single;
  690.  
  691.   // 7.3.3 Plain Style
  692.   // Plain scalars must not begin with most indicators, as this would cause
  693.   // ambiguity with other YAML constructs.
  694.   if (std::strchr(R"(-?:\,[]{}#&*!|>'"%@`)", S[0]) != nullptr)
  695.     MaxQuotingNeeded = QuotingType::Single;
  696.  
  697.   for (unsigned char C : S) {
  698.     // Alphanum is safe.
  699.     if (isAlnum(C))
  700.       continue;
  701.  
  702.     switch (C) {
  703.     // Safe scalar characters.
  704.     case '_':
  705.     case '-':
  706.     case '^':
  707.     case '.':
  708.     case ',':
  709.     case ' ':
  710.     // TAB (0x9) is allowed in unquoted strings.
  711.     case 0x9:
  712.       continue;
  713.     // LF(0xA) and CR(0xD) may delimit values and so require at least single
  714.     // quotes. LLVM YAML parser cannot handle single quoted multiline so use
  715.     // double quoting to produce valid YAML.
  716.     case 0xA:
  717.     case 0xD:
  718.       return QuotingType::Double;
  719.     // DEL (0x7F) are excluded from the allowed character range.
  720.     case 0x7F:
  721.       return QuotingType::Double;
  722.     // Forward slash is allowed to be unquoted, but we quote it anyway.  We have
  723.     // many tests that use FileCheck against YAML output, and this output often
  724.     // contains paths.  If we quote backslashes but not forward slashes then
  725.     // paths will come out either quoted or unquoted depending on which platform
  726.     // the test is run on, making FileCheck comparisons difficult.
  727.     case '/':
  728.     default: {
  729.       // C0 control block (0x0 - 0x1F) is excluded from the allowed character
  730.       // range.
  731.       if (C <= 0x1F)
  732.         return QuotingType::Double;
  733.  
  734.       // Always double quote UTF-8.
  735.       if ((C & 0x80) != 0)
  736.         return QuotingType::Double;
  737.  
  738.       // The character is not safe, at least simple quoting needed.
  739.       MaxQuotingNeeded = QuotingType::Single;
  740.     }
  741.     }
  742.   }
  743.  
  744.   return MaxQuotingNeeded;
  745. }
  746.  
  747. template <typename T, typename Context>
  748. struct missingTraits
  749.     : public std::integral_constant<bool,
  750.                                     !has_ScalarEnumerationTraits<T>::value &&
  751.                                         !has_ScalarBitSetTraits<T>::value &&
  752.                                         !has_ScalarTraits<T>::value &&
  753.                                         !has_BlockScalarTraits<T>::value &&
  754.                                         !has_TaggedScalarTraits<T>::value &&
  755.                                         !has_MappingTraits<T, Context>::value &&
  756.                                         !has_SequenceTraits<T>::value &&
  757.                                         !has_CustomMappingTraits<T>::value &&
  758.                                         !has_DocumentListTraits<T>::value &&
  759.                                         !has_PolymorphicTraits<T>::value> {};
  760.  
  761. template <typename T, typename Context>
  762. struct validatedMappingTraits
  763.     : public std::integral_constant<
  764.           bool, has_MappingTraits<T, Context>::value &&
  765.                     has_MappingValidateTraits<T, Context>::value> {};
  766.  
  767. template <typename T, typename Context>
  768. struct unvalidatedMappingTraits
  769.     : public std::integral_constant<
  770.           bool, has_MappingTraits<T, Context>::value &&
  771.                     !has_MappingValidateTraits<T, Context>::value> {};
  772.  
  773. // Base class for Input and Output.
  774. class IO {
  775. public:
  776.   IO(void *Ctxt = nullptr);
  777.   virtual ~IO();
  778.  
  779.   virtual bool outputting() const = 0;
  780.  
  781.   virtual unsigned beginSequence() = 0;
  782.   virtual bool preflightElement(unsigned, void *&) = 0;
  783.   virtual void postflightElement(void*) = 0;
  784.   virtual void endSequence() = 0;
  785.   virtual bool canElideEmptySequence() = 0;
  786.  
  787.   virtual unsigned beginFlowSequence() = 0;
  788.   virtual bool preflightFlowElement(unsigned, void *&) = 0;
  789.   virtual void postflightFlowElement(void*) = 0;
  790.   virtual void endFlowSequence() = 0;
  791.  
  792.   virtual bool mapTag(StringRef Tag, bool Default=false) = 0;
  793.   virtual void beginMapping() = 0;
  794.   virtual void endMapping() = 0;
  795.   virtual bool preflightKey(const char*, bool, bool, bool &, void *&) = 0;
  796.   virtual void postflightKey(void*) = 0;
  797.   virtual std::vector<StringRef> keys() = 0;
  798.  
  799.   virtual void beginFlowMapping() = 0;
  800.   virtual void endFlowMapping() = 0;
  801.  
  802.   virtual void beginEnumScalar() = 0;
  803.   virtual bool matchEnumScalar(const char*, bool) = 0;
  804.   virtual bool matchEnumFallback() = 0;
  805.   virtual void endEnumScalar() = 0;
  806.  
  807.   virtual bool beginBitSetScalar(bool &) = 0;
  808.   virtual bool bitSetMatch(const char*, bool) = 0;
  809.   virtual void endBitSetScalar() = 0;
  810.  
  811.   virtual void scalarString(StringRef &, QuotingType) = 0;
  812.   virtual void blockScalarString(StringRef &) = 0;
  813.   virtual void scalarTag(std::string &) = 0;
  814.  
  815.   virtual NodeKind getNodeKind() = 0;
  816.  
  817.   virtual void setError(const Twine &) = 0;
  818.   virtual void setAllowUnknownKeys(bool Allow);
  819.  
  820.   template <typename T>
  821.   void enumCase(T &Val, const char* Str, const T ConstVal) {
  822.     if ( matchEnumScalar(Str, outputting() && Val == ConstVal) ) {
  823.       Val = ConstVal;
  824.     }
  825.   }
  826.  
  827.   // allow anonymous enum values to be used with LLVM_YAML_STRONG_TYPEDEF
  828.   template <typename T>
  829.   void enumCase(T &Val, const char* Str, const uint32_t ConstVal) {
  830.     if ( matchEnumScalar(Str, outputting() && Val == static_cast<T>(ConstVal)) ) {
  831.       Val = ConstVal;
  832.     }
  833.   }
  834.  
  835.   template <typename FBT, typename T>
  836.   void enumFallback(T &Val) {
  837.     if (matchEnumFallback()) {
  838.       EmptyContext Context;
  839.       // FIXME: Force integral conversion to allow strong typedefs to convert.
  840.       FBT Res = static_cast<typename FBT::BaseType>(Val);
  841.       yamlize(*this, Res, true, Context);
  842.       Val = static_cast<T>(static_cast<typename FBT::BaseType>(Res));
  843.     }
  844.   }
  845.  
  846.   template <typename T>
  847.   void bitSetCase(T &Val, const char* Str, const T ConstVal) {
  848.     if ( bitSetMatch(Str, outputting() && (Val & ConstVal) == ConstVal) ) {
  849.       Val = static_cast<T>(Val | ConstVal);
  850.     }
  851.   }
  852.  
  853.   // allow anonymous enum values to be used with LLVM_YAML_STRONG_TYPEDEF
  854.   template <typename T>
  855.   void bitSetCase(T &Val, const char* Str, const uint32_t ConstVal) {
  856.     if ( bitSetMatch(Str, outputting() && (Val & ConstVal) == ConstVal) ) {
  857.       Val = static_cast<T>(Val | ConstVal);
  858.     }
  859.   }
  860.  
  861.   template <typename T>
  862.   void maskedBitSetCase(T &Val, const char *Str, T ConstVal, T Mask) {
  863.     if (bitSetMatch(Str, outputting() && (Val & Mask) == ConstVal))
  864.       Val = Val | ConstVal;
  865.   }
  866.  
  867.   template <typename T>
  868.   void maskedBitSetCase(T &Val, const char *Str, uint32_t ConstVal,
  869.                         uint32_t Mask) {
  870.     if (bitSetMatch(Str, outputting() && (Val & Mask) == ConstVal))
  871.       Val = Val | ConstVal;
  872.   }
  873.  
  874.   void *getContext() const;
  875.   void setContext(void *);
  876.  
  877.   template <typename T> void mapRequired(const char *Key, T &Val) {
  878.     EmptyContext Ctx;
  879.     this->processKey(Key, Val, true, Ctx);
  880.   }
  881.  
  882.   template <typename T, typename Context>
  883.   void mapRequired(const char *Key, T &Val, Context &Ctx) {
  884.     this->processKey(Key, Val, true, Ctx);
  885.   }
  886.  
  887.   template <typename T> void mapOptional(const char *Key, T &Val) {
  888.     EmptyContext Ctx;
  889.     mapOptionalWithContext(Key, Val, Ctx);
  890.   }
  891.  
  892.   template <typename T, typename DefaultT>
  893.   void mapOptional(const char *Key, T &Val, const DefaultT &Default) {
  894.     EmptyContext Ctx;
  895.     mapOptionalWithContext(Key, Val, Default, Ctx);
  896.   }
  897.  
  898.   template <typename T, typename Context>
  899.   std::enable_if_t<has_SequenceTraits<T>::value, void>
  900.   mapOptionalWithContext(const char *Key, T &Val, Context &Ctx) {
  901.     // omit key/value instead of outputting empty sequence
  902.     if (this->canElideEmptySequence() && !(Val.begin() != Val.end()))
  903.       return;
  904.     this->processKey(Key, Val, false, Ctx);
  905.   }
  906.  
  907.   template <typename T, typename Context>
  908.   void mapOptionalWithContext(const char *Key, std::optional<T> &Val,
  909.                               Context &Ctx) {
  910.     this->processKeyWithDefault(Key, Val, std::optional<T>(),
  911.                                 /*Required=*/false, Ctx);
  912.   }
  913.  
  914.   template <typename T, typename Context>
  915.   std::enable_if_t<!has_SequenceTraits<T>::value, void>
  916.   mapOptionalWithContext(const char *Key, T &Val, Context &Ctx) {
  917.     this->processKey(Key, Val, false, Ctx);
  918.   }
  919.  
  920.   template <typename T, typename Context, typename DefaultT>
  921.   void mapOptionalWithContext(const char *Key, T &Val, const DefaultT &Default,
  922.                               Context &Ctx) {
  923.     static_assert(std::is_convertible<DefaultT, T>::value,
  924.                   "Default type must be implicitly convertible to value type!");
  925.     this->processKeyWithDefault(Key, Val, static_cast<const T &>(Default),
  926.                                 false, Ctx);
  927.   }
  928.  
  929. private:
  930.   template <typename T, typename Context>
  931.   void processKeyWithDefault(const char *Key, std::optional<T> &Val,
  932.                              const std::optional<T> &DefaultValue,
  933.                              bool Required, Context &Ctx);
  934.  
  935.   template <typename T, typename Context>
  936.   void processKeyWithDefault(const char *Key, T &Val, const T &DefaultValue,
  937.                              bool Required, Context &Ctx) {
  938.     void *SaveInfo;
  939.     bool UseDefault;
  940.     const bool sameAsDefault = outputting() && Val == DefaultValue;
  941.     if ( this->preflightKey(Key, Required, sameAsDefault, UseDefault,
  942.                                                                   SaveInfo) ) {
  943.       yamlize(*this, Val, Required, Ctx);
  944.       this->postflightKey(SaveInfo);
  945.     }
  946.     else {
  947.       if ( UseDefault )
  948.         Val = DefaultValue;
  949.     }
  950.   }
  951.  
  952.   template <typename T, typename Context>
  953.   void processKey(const char *Key, T &Val, bool Required, Context &Ctx) {
  954.     void *SaveInfo;
  955.     bool UseDefault;
  956.     if ( this->preflightKey(Key, Required, false, UseDefault, SaveInfo) ) {
  957.       yamlize(*this, Val, Required, Ctx);
  958.       this->postflightKey(SaveInfo);
  959.     }
  960.   }
  961.  
  962. private:
  963.   void *Ctxt;
  964. };
  965.  
  966. namespace detail {
  967.  
  968. template <typename T, typename Context>
  969. void doMapping(IO &io, T &Val, Context &Ctx) {
  970.   MappingContextTraits<T, Context>::mapping(io, Val, Ctx);
  971. }
  972.  
  973. template <typename T> void doMapping(IO &io, T &Val, EmptyContext &Ctx) {
  974.   MappingTraits<T>::mapping(io, Val);
  975. }
  976.  
  977. } // end namespace detail
  978.  
  979. template <typename T>
  980. std::enable_if_t<has_ScalarEnumerationTraits<T>::value, void>
  981. yamlize(IO &io, T &Val, bool, EmptyContext &Ctx) {
  982.   io.beginEnumScalar();
  983.   ScalarEnumerationTraits<T>::enumeration(io, Val);
  984.   io.endEnumScalar();
  985. }
  986.  
  987. template <typename T>
  988. std::enable_if_t<has_ScalarBitSetTraits<T>::value, void>
  989. yamlize(IO &io, T &Val, bool, EmptyContext &Ctx) {
  990.   bool DoClear;
  991.   if ( io.beginBitSetScalar(DoClear) ) {
  992.     if ( DoClear )
  993.       Val = T();
  994.     ScalarBitSetTraits<T>::bitset(io, Val);
  995.     io.endBitSetScalar();
  996.   }
  997. }
  998.  
  999. template <typename T>
  1000. std::enable_if_t<has_ScalarTraits<T>::value, void> yamlize(IO &io, T &Val, bool,
  1001.                                                            EmptyContext &Ctx) {
  1002.   if ( io.outputting() ) {
  1003.     SmallString<128> Storage;
  1004.     raw_svector_ostream Buffer(Storage);
  1005.     ScalarTraits<T>::output(Val, io.getContext(), Buffer);
  1006.     StringRef Str = Buffer.str();
  1007.     io.scalarString(Str, ScalarTraits<T>::mustQuote(Str));
  1008.   }
  1009.   else {
  1010.     StringRef Str;
  1011.     io.scalarString(Str, ScalarTraits<T>::mustQuote(Str));
  1012.     StringRef Result = ScalarTraits<T>::input(Str, io.getContext(), Val);
  1013.     if ( !Result.empty() ) {
  1014.       io.setError(Twine(Result));
  1015.     }
  1016.   }
  1017. }
  1018.  
  1019. template <typename T>
  1020. std::enable_if_t<has_BlockScalarTraits<T>::value, void>
  1021. yamlize(IO &YamlIO, T &Val, bool, EmptyContext &Ctx) {
  1022.   if (YamlIO.outputting()) {
  1023.     std::string Storage;
  1024.     raw_string_ostream Buffer(Storage);
  1025.     BlockScalarTraits<T>::output(Val, YamlIO.getContext(), Buffer);
  1026.     StringRef Str = Buffer.str();
  1027.     YamlIO.blockScalarString(Str);
  1028.   } else {
  1029.     StringRef Str;
  1030.     YamlIO.blockScalarString(Str);
  1031.     StringRef Result =
  1032.         BlockScalarTraits<T>::input(Str, YamlIO.getContext(), Val);
  1033.     if (!Result.empty())
  1034.       YamlIO.setError(Twine(Result));
  1035.   }
  1036. }
  1037.  
  1038. template <typename T>
  1039. std::enable_if_t<has_TaggedScalarTraits<T>::value, void>
  1040. yamlize(IO &io, T &Val, bool, EmptyContext &Ctx) {
  1041.   if (io.outputting()) {
  1042.     std::string ScalarStorage, TagStorage;
  1043.     raw_string_ostream ScalarBuffer(ScalarStorage), TagBuffer(TagStorage);
  1044.     TaggedScalarTraits<T>::output(Val, io.getContext(), ScalarBuffer,
  1045.                                   TagBuffer);
  1046.     io.scalarTag(TagBuffer.str());
  1047.     StringRef ScalarStr = ScalarBuffer.str();
  1048.     io.scalarString(ScalarStr,
  1049.                     TaggedScalarTraits<T>::mustQuote(Val, ScalarStr));
  1050.   } else {
  1051.     std::string Tag;
  1052.     io.scalarTag(Tag);
  1053.     StringRef Str;
  1054.     io.scalarString(Str, QuotingType::None);
  1055.     StringRef Result =
  1056.         TaggedScalarTraits<T>::input(Str, Tag, io.getContext(), Val);
  1057.     if (!Result.empty()) {
  1058.       io.setError(Twine(Result));
  1059.     }
  1060.   }
  1061. }
  1062.  
  1063. template <typename T, typename Context>
  1064. std::enable_if_t<validatedMappingTraits<T, Context>::value, void>
  1065. yamlize(IO &io, T &Val, bool, Context &Ctx) {
  1066.   if (has_FlowTraits<MappingTraits<T>>::value)
  1067.     io.beginFlowMapping();
  1068.   else
  1069.     io.beginMapping();
  1070.   if (io.outputting()) {
  1071.     std::string Err = MappingTraits<T>::validate(io, Val);
  1072.     if (!Err.empty()) {
  1073.       errs() << Err << "\n";
  1074.       assert(Err.empty() && "invalid struct trying to be written as yaml");
  1075.     }
  1076.   }
  1077.   detail::doMapping(io, Val, Ctx);
  1078.   if (!io.outputting()) {
  1079.     std::string Err = MappingTraits<T>::validate(io, Val);
  1080.     if (!Err.empty())
  1081.       io.setError(Err);
  1082.   }
  1083.   if (has_FlowTraits<MappingTraits<T>>::value)
  1084.     io.endFlowMapping();
  1085.   else
  1086.     io.endMapping();
  1087. }
  1088.  
  1089. template <typename T, typename Context>
  1090. std::enable_if_t<!has_MappingEnumInputTraits<T, Context>::value, bool>
  1091. yamlizeMappingEnumInput(IO &io, T &Val) {
  1092.   return false;
  1093. }
  1094.  
  1095. template <typename T, typename Context>
  1096. std::enable_if_t<has_MappingEnumInputTraits<T, Context>::value, bool>
  1097. yamlizeMappingEnumInput(IO &io, T &Val) {
  1098.   if (io.outputting())
  1099.     return false;
  1100.  
  1101.   io.beginEnumScalar();
  1102.   MappingTraits<T>::enumInput(io, Val);
  1103.   bool Matched = !io.matchEnumFallback();
  1104.   io.endEnumScalar();
  1105.   return Matched;
  1106. }
  1107.  
  1108. template <typename T, typename Context>
  1109. std::enable_if_t<unvalidatedMappingTraits<T, Context>::value, void>
  1110. yamlize(IO &io, T &Val, bool, Context &Ctx) {
  1111.   if (yamlizeMappingEnumInput<T, Context>(io, Val))
  1112.     return;
  1113.   if (has_FlowTraits<MappingTraits<T>>::value) {
  1114.     io.beginFlowMapping();
  1115.     detail::doMapping(io, Val, Ctx);
  1116.     io.endFlowMapping();
  1117.   } else {
  1118.     io.beginMapping();
  1119.     detail::doMapping(io, Val, Ctx);
  1120.     io.endMapping();
  1121.   }
  1122. }
  1123.  
  1124. template <typename T>
  1125. std::enable_if_t<has_CustomMappingTraits<T>::value, void>
  1126. yamlize(IO &io, T &Val, bool, EmptyContext &Ctx) {
  1127.   if ( io.outputting() ) {
  1128.     io.beginMapping();
  1129.     CustomMappingTraits<T>::output(io, Val);
  1130.     io.endMapping();
  1131.   } else {
  1132.     io.beginMapping();
  1133.     for (StringRef key : io.keys())
  1134.       CustomMappingTraits<T>::inputOne(io, key, Val);
  1135.     io.endMapping();
  1136.   }
  1137. }
  1138.  
  1139. template <typename T>
  1140. std::enable_if_t<has_PolymorphicTraits<T>::value, void>
  1141. yamlize(IO &io, T &Val, bool, EmptyContext &Ctx) {
  1142.   switch (io.outputting() ? PolymorphicTraits<T>::getKind(Val)
  1143.                           : io.getNodeKind()) {
  1144.   case NodeKind::Scalar:
  1145.     return yamlize(io, PolymorphicTraits<T>::getAsScalar(Val), true, Ctx);
  1146.   case NodeKind::Map:
  1147.     return yamlize(io, PolymorphicTraits<T>::getAsMap(Val), true, Ctx);
  1148.   case NodeKind::Sequence:
  1149.     return yamlize(io, PolymorphicTraits<T>::getAsSequence(Val), true, Ctx);
  1150.   }
  1151. }
  1152.  
  1153. template <typename T>
  1154. std::enable_if_t<missingTraits<T, EmptyContext>::value, void>
  1155. yamlize(IO &io, T &Val, bool, EmptyContext &Ctx) {
  1156.   char missing_yaml_trait_for_type[sizeof(MissingTrait<T>)];
  1157. }
  1158.  
  1159. template <typename T, typename Context>
  1160. std::enable_if_t<has_SequenceTraits<T>::value, void>
  1161. yamlize(IO &io, T &Seq, bool, Context &Ctx) {
  1162.   if ( has_FlowTraits< SequenceTraits<T>>::value ) {
  1163.     unsigned incnt = io.beginFlowSequence();
  1164.     unsigned count = io.outputting() ? SequenceTraits<T>::size(io, Seq) : incnt;
  1165.     for(unsigned i=0; i < count; ++i) {
  1166.       void *SaveInfo;
  1167.       if ( io.preflightFlowElement(i, SaveInfo) ) {
  1168.         yamlize(io, SequenceTraits<T>::element(io, Seq, i), true, Ctx);
  1169.         io.postflightFlowElement(SaveInfo);
  1170.       }
  1171.     }
  1172.     io.endFlowSequence();
  1173.   }
  1174.   else {
  1175.     unsigned incnt = io.beginSequence();
  1176.     unsigned count = io.outputting() ? SequenceTraits<T>::size(io, Seq) : incnt;
  1177.     for(unsigned i=0; i < count; ++i) {
  1178.       void *SaveInfo;
  1179.       if ( io.preflightElement(i, SaveInfo) ) {
  1180.         yamlize(io, SequenceTraits<T>::element(io, Seq, i), true, Ctx);
  1181.         io.postflightElement(SaveInfo);
  1182.       }
  1183.     }
  1184.     io.endSequence();
  1185.   }
  1186. }
  1187.  
  1188. template<>
  1189. struct ScalarTraits<bool> {
  1190.   static void output(const bool &, void* , raw_ostream &);
  1191.   static StringRef input(StringRef, void *, bool &);
  1192.   static QuotingType mustQuote(StringRef) { return QuotingType::None; }
  1193. };
  1194.  
  1195. template<>
  1196. struct ScalarTraits<StringRef> {
  1197.   static void output(const StringRef &, void *, raw_ostream &);
  1198.   static StringRef input(StringRef, void *, StringRef &);
  1199.   static QuotingType mustQuote(StringRef S) { return needsQuotes(S); }
  1200. };
  1201.  
  1202. template<>
  1203. struct ScalarTraits<std::string> {
  1204.   static void output(const std::string &, void *, raw_ostream &);
  1205.   static StringRef input(StringRef, void *, std::string &);
  1206.   static QuotingType mustQuote(StringRef S) { return needsQuotes(S); }
  1207. };
  1208.  
  1209. template<>
  1210. struct ScalarTraits<uint8_t> {
  1211.   static void output(const uint8_t &, void *, raw_ostream &);
  1212.   static StringRef input(StringRef, void *, uint8_t &);
  1213.   static QuotingType mustQuote(StringRef) { return QuotingType::None; }
  1214. };
  1215.  
  1216. template<>
  1217. struct ScalarTraits<uint16_t> {
  1218.   static void output(const uint16_t &, void *, raw_ostream &);
  1219.   static StringRef input(StringRef, void *, uint16_t &);
  1220.   static QuotingType mustQuote(StringRef) { return QuotingType::None; }
  1221. };
  1222.  
  1223. template<>
  1224. struct ScalarTraits<uint32_t> {
  1225.   static void output(const uint32_t &, void *, raw_ostream &);
  1226.   static StringRef input(StringRef, void *, uint32_t &);
  1227.   static QuotingType mustQuote(StringRef) { return QuotingType::None; }
  1228. };
  1229.  
  1230. template<>
  1231. struct ScalarTraits<uint64_t> {
  1232.   static void output(const uint64_t &, void *, raw_ostream &);
  1233.   static StringRef input(StringRef, void *, uint64_t &);
  1234.   static QuotingType mustQuote(StringRef) { return QuotingType::None; }
  1235. };
  1236.  
  1237. template<>
  1238. struct ScalarTraits<int8_t> {
  1239.   static void output(const int8_t &, void *, raw_ostream &);
  1240.   static StringRef input(StringRef, void *, int8_t &);
  1241.   static QuotingType mustQuote(StringRef) { return QuotingType::None; }
  1242. };
  1243.  
  1244. template<>
  1245. struct ScalarTraits<int16_t> {
  1246.   static void output(const int16_t &, void *, raw_ostream &);
  1247.   static StringRef input(StringRef, void *, int16_t &);
  1248.   static QuotingType mustQuote(StringRef) { return QuotingType::None; }
  1249. };
  1250.  
  1251. template<>
  1252. struct ScalarTraits<int32_t> {
  1253.   static void output(const int32_t &, void *, raw_ostream &);
  1254.   static StringRef input(StringRef, void *, int32_t &);
  1255.   static QuotingType mustQuote(StringRef) { return QuotingType::None; }
  1256. };
  1257.  
  1258. template<>
  1259. struct ScalarTraits<int64_t> {
  1260.   static void output(const int64_t &, void *, raw_ostream &);
  1261.   static StringRef input(StringRef, void *, int64_t &);
  1262.   static QuotingType mustQuote(StringRef) { return QuotingType::None; }
  1263. };
  1264.  
  1265. template<>
  1266. struct ScalarTraits<float> {
  1267.   static void output(const float &, void *, raw_ostream &);
  1268.   static StringRef input(StringRef, void *, float &);
  1269.   static QuotingType mustQuote(StringRef) { return QuotingType::None; }
  1270. };
  1271.  
  1272. template<>
  1273. struct ScalarTraits<double> {
  1274.   static void output(const double &, void *, raw_ostream &);
  1275.   static StringRef input(StringRef, void *, double &);
  1276.   static QuotingType mustQuote(StringRef) { return QuotingType::None; }
  1277. };
  1278.  
  1279. // For endian types, we use existing scalar Traits class for the underlying
  1280. // type.  This way endian aware types are supported whenever the traits are
  1281. // defined for the underlying type.
  1282. template <typename value_type, support::endianness endian, size_t alignment>
  1283. struct ScalarTraits<support::detail::packed_endian_specific_integral<
  1284.                         value_type, endian, alignment>,
  1285.                     std::enable_if_t<has_ScalarTraits<value_type>::value>> {
  1286.   using endian_type =
  1287.       support::detail::packed_endian_specific_integral<value_type, endian,
  1288.                                                        alignment>;
  1289.  
  1290.   static void output(const endian_type &E, void *Ctx, raw_ostream &Stream) {
  1291.     ScalarTraits<value_type>::output(static_cast<value_type>(E), Ctx, Stream);
  1292.   }
  1293.  
  1294.   static StringRef input(StringRef Str, void *Ctx, endian_type &E) {
  1295.     value_type V;
  1296.     auto R = ScalarTraits<value_type>::input(Str, Ctx, V);
  1297.     E = static_cast<endian_type>(V);
  1298.     return R;
  1299.   }
  1300.  
  1301.   static QuotingType mustQuote(StringRef Str) {
  1302.     return ScalarTraits<value_type>::mustQuote(Str);
  1303.   }
  1304. };
  1305.  
  1306. template <typename value_type, support::endianness endian, size_t alignment>
  1307. struct ScalarEnumerationTraits<
  1308.     support::detail::packed_endian_specific_integral<value_type, endian,
  1309.                                                      alignment>,
  1310.     std::enable_if_t<has_ScalarEnumerationTraits<value_type>::value>> {
  1311.   using endian_type =
  1312.       support::detail::packed_endian_specific_integral<value_type, endian,
  1313.                                                        alignment>;
  1314.  
  1315.   static void enumeration(IO &io, endian_type &E) {
  1316.     value_type V = E;
  1317.     ScalarEnumerationTraits<value_type>::enumeration(io, V);
  1318.     E = V;
  1319.   }
  1320. };
  1321.  
  1322. template <typename value_type, support::endianness endian, size_t alignment>
  1323. struct ScalarBitSetTraits<
  1324.     support::detail::packed_endian_specific_integral<value_type, endian,
  1325.                                                      alignment>,
  1326.     std::enable_if_t<has_ScalarBitSetTraits<value_type>::value>> {
  1327.   using endian_type =
  1328.       support::detail::packed_endian_specific_integral<value_type, endian,
  1329.                                                        alignment>;
  1330.   static void bitset(IO &io, endian_type &E) {
  1331.     value_type V = E;
  1332.     ScalarBitSetTraits<value_type>::bitset(io, V);
  1333.     E = V;
  1334.   }
  1335. };
  1336.  
  1337. // Utility for use within MappingTraits<>::mapping() method
  1338. // to [de]normalize an object for use with YAML conversion.
  1339. template <typename TNorm, typename TFinal>
  1340. struct MappingNormalization {
  1341.   MappingNormalization(IO &i_o, TFinal &Obj)
  1342.       : io(i_o), BufPtr(nullptr), Result(Obj) {
  1343.     if ( io.outputting() ) {
  1344.       BufPtr = new (&Buffer) TNorm(io, Obj);
  1345.     }
  1346.     else {
  1347.       BufPtr = new (&Buffer) TNorm(io);
  1348.     }
  1349.   }
  1350.  
  1351.   ~MappingNormalization() {
  1352.     if ( ! io.outputting() ) {
  1353.       Result = BufPtr->denormalize(io);
  1354.     }
  1355.     BufPtr->~TNorm();
  1356.   }
  1357.  
  1358.   TNorm* operator->() { return BufPtr; }
  1359.  
  1360. private:
  1361.   using Storage = AlignedCharArrayUnion<TNorm>;
  1362.  
  1363.   Storage       Buffer;
  1364.   IO           &io;
  1365.   TNorm        *BufPtr;
  1366.   TFinal       &Result;
  1367. };
  1368.  
  1369. // Utility for use within MappingTraits<>::mapping() method
  1370. // to [de]normalize an object for use with YAML conversion.
  1371. template <typename TNorm, typename TFinal>
  1372. struct MappingNormalizationHeap {
  1373.   MappingNormalizationHeap(IO &i_o, TFinal &Obj, BumpPtrAllocator *allocator)
  1374.     : io(i_o), Result(Obj) {
  1375.     if ( io.outputting() ) {
  1376.       BufPtr = new (&Buffer) TNorm(io, Obj);
  1377.     }
  1378.     else if (allocator) {
  1379.       BufPtr = allocator->Allocate<TNorm>();
  1380.       new (BufPtr) TNorm(io);
  1381.     } else {
  1382.       BufPtr = new TNorm(io);
  1383.     }
  1384.   }
  1385.  
  1386.   ~MappingNormalizationHeap() {
  1387.     if ( io.outputting() ) {
  1388.       BufPtr->~TNorm();
  1389.     }
  1390.     else {
  1391.       Result = BufPtr->denormalize(io);
  1392.     }
  1393.   }
  1394.  
  1395.   TNorm* operator->() { return BufPtr; }
  1396.  
  1397. private:
  1398.   using Storage = AlignedCharArrayUnion<TNorm>;
  1399.  
  1400.   Storage       Buffer;
  1401.   IO           &io;
  1402.   TNorm        *BufPtr = nullptr;
  1403.   TFinal       &Result;
  1404. };
  1405.  
  1406. ///
  1407. /// The Input class is used to parse a yaml document into in-memory structs
  1408. /// and vectors.
  1409. ///
  1410. /// It works by using YAMLParser to do a syntax parse of the entire yaml
  1411. /// document, then the Input class builds a graph of HNodes which wraps
  1412. /// each yaml Node.  The extra layer is buffering.  The low level yaml
  1413. /// parser only lets you look at each node once.  The buffering layer lets
  1414. /// you search and interate multiple times.  This is necessary because
  1415. /// the mapRequired() method calls may not be in the same order
  1416. /// as the keys in the document.
  1417. ///
  1418. class Input : public IO {
  1419. public:
  1420.   // Construct a yaml Input object from a StringRef and optional
  1421.   // user-data. The DiagHandler can be specified to provide
  1422.   // alternative error reporting.
  1423.   Input(StringRef InputContent,
  1424.         void *Ctxt = nullptr,
  1425.         SourceMgr::DiagHandlerTy DiagHandler = nullptr,
  1426.         void *DiagHandlerCtxt = nullptr);
  1427.   Input(MemoryBufferRef Input,
  1428.         void *Ctxt = nullptr,
  1429.         SourceMgr::DiagHandlerTy DiagHandler = nullptr,
  1430.         void *DiagHandlerCtxt = nullptr);
  1431.   ~Input() override;
  1432.  
  1433.   // Check if there was an syntax or semantic error during parsing.
  1434.   std::error_code error();
  1435.  
  1436. private:
  1437.   bool outputting() const override;
  1438.   bool mapTag(StringRef, bool) override;
  1439.   void beginMapping() override;
  1440.   void endMapping() override;
  1441.   bool preflightKey(const char *, bool, bool, bool &, void *&) override;
  1442.   void postflightKey(void *) override;
  1443.   std::vector<StringRef> keys() override;
  1444.   void beginFlowMapping() override;
  1445.   void endFlowMapping() override;
  1446.   unsigned beginSequence() override;
  1447.   void endSequence() override;
  1448.   bool preflightElement(unsigned index, void *&) override;
  1449.   void postflightElement(void *) override;
  1450.   unsigned beginFlowSequence() override;
  1451.   bool preflightFlowElement(unsigned , void *&) override;
  1452.   void postflightFlowElement(void *) override;
  1453.   void endFlowSequence() override;
  1454.   void beginEnumScalar() override;
  1455.   bool matchEnumScalar(const char*, bool) override;
  1456.   bool matchEnumFallback() override;
  1457.   void endEnumScalar() override;
  1458.   bool beginBitSetScalar(bool &) override;
  1459.   bool bitSetMatch(const char *, bool ) override;
  1460.   void endBitSetScalar() override;
  1461.   void scalarString(StringRef &, QuotingType) override;
  1462.   void blockScalarString(StringRef &) override;
  1463.   void scalarTag(std::string &) override;
  1464.   NodeKind getNodeKind() override;
  1465.   void setError(const Twine &message) override;
  1466.   bool canElideEmptySequence() override;
  1467.  
  1468.   class HNode {
  1469.     virtual void anchor();
  1470.  
  1471.   public:
  1472.     HNode(Node *n) : _node(n) { }
  1473.     virtual ~HNode() = default;
  1474.  
  1475.     static bool classof(const HNode *) { return true; }
  1476.  
  1477.     Node *_node;
  1478.   };
  1479.  
  1480.   class EmptyHNode : public HNode {
  1481.     void anchor() override;
  1482.  
  1483.   public:
  1484.     EmptyHNode(Node *n) : HNode(n) { }
  1485.  
  1486.     static bool classof(const HNode *n) { return NullNode::classof(n->_node); }
  1487.  
  1488.     static bool classof(const EmptyHNode *) { return true; }
  1489.   };
  1490.  
  1491.   class ScalarHNode : public HNode {
  1492.     void anchor() override;
  1493.  
  1494.   public:
  1495.     ScalarHNode(Node *n, StringRef s) : HNode(n), _value(s) { }
  1496.  
  1497.     StringRef value() const { return _value; }
  1498.  
  1499.     static bool classof(const HNode *n) {
  1500.       return ScalarNode::classof(n->_node) ||
  1501.              BlockScalarNode::classof(n->_node);
  1502.     }
  1503.  
  1504.     static bool classof(const ScalarHNode *) { return true; }
  1505.  
  1506.   protected:
  1507.     StringRef _value;
  1508.   };
  1509.  
  1510.   class MapHNode : public HNode {
  1511.     void anchor() override;
  1512.  
  1513.   public:
  1514.     MapHNode(Node *n) : HNode(n) { }
  1515.  
  1516.     static bool classof(const HNode *n) {
  1517.       return MappingNode::classof(n->_node);
  1518.     }
  1519.  
  1520.     static bool classof(const MapHNode *) { return true; }
  1521.  
  1522.     using NameToNodeAndLoc =
  1523.         StringMap<std::pair<std::unique_ptr<HNode>, SMRange>>;
  1524.  
  1525.     NameToNodeAndLoc Mapping;
  1526.     SmallVector<std::string, 6> ValidKeys;
  1527.   };
  1528.  
  1529.   class SequenceHNode : public HNode {
  1530.     void anchor() override;
  1531.  
  1532.   public:
  1533.     SequenceHNode(Node *n) : HNode(n) { }
  1534.  
  1535.     static bool classof(const HNode *n) {
  1536.       return SequenceNode::classof(n->_node);
  1537.     }
  1538.  
  1539.     static bool classof(const SequenceHNode *) { return true; }
  1540.  
  1541.     std::vector<std::unique_ptr<HNode>> Entries;
  1542.   };
  1543.  
  1544.   std::unique_ptr<Input::HNode> createHNodes(Node *node);
  1545.   void setError(HNode *hnode, const Twine &message);
  1546.   void setError(Node *node, const Twine &message);
  1547.   void setError(const SMRange &Range, const Twine &message);
  1548.  
  1549.   void reportWarning(HNode *hnode, const Twine &message);
  1550.   void reportWarning(Node *hnode, const Twine &message);
  1551.   void reportWarning(const SMRange &Range, const Twine &message);
  1552.  
  1553. public:
  1554.   // These are only used by operator>>. They could be private
  1555.   // if those templated things could be made friends.
  1556.   bool setCurrentDocument();
  1557.   bool nextDocument();
  1558.  
  1559.   /// Returns the current node that's being parsed by the YAML Parser.
  1560.   const Node *getCurrentNode() const;
  1561.  
  1562.   void setAllowUnknownKeys(bool Allow) override;
  1563.  
  1564. private:
  1565.   SourceMgr                           SrcMgr; // must be before Strm
  1566.   std::unique_ptr<llvm::yaml::Stream> Strm;
  1567.   std::unique_ptr<HNode>              TopNode;
  1568.   std::error_code                     EC;
  1569.   BumpPtrAllocator                    StringAllocator;
  1570.   document_iterator                   DocIterator;
  1571.   llvm::BitVector                     BitValuesUsed;
  1572.   HNode *CurrentNode = nullptr;
  1573.   bool                                ScalarMatchFound = false;
  1574.   bool AllowUnknownKeys = false;
  1575. };
  1576.  
  1577. ///
  1578. /// The Output class is used to generate a yaml document from in-memory structs
  1579. /// and vectors.
  1580. ///
  1581. class Output : public IO {
  1582. public:
  1583.   Output(raw_ostream &, void *Ctxt = nullptr, int WrapColumn = 70);
  1584.   ~Output() override;
  1585.  
  1586.   /// Set whether or not to output optional values which are equal
  1587.   /// to the default value.  By default, when outputting if you attempt
  1588.   /// to write a value that is equal to the default, the value gets ignored.
  1589.   /// Sometimes, it is useful to be able to see these in the resulting YAML
  1590.   /// anyway.
  1591.   void setWriteDefaultValues(bool Write) { WriteDefaultValues = Write; }
  1592.  
  1593.   bool outputting() const override;
  1594.   bool mapTag(StringRef, bool) override;
  1595.   void beginMapping() override;
  1596.   void endMapping() override;
  1597.   bool preflightKey(const char *key, bool, bool, bool &, void *&) override;
  1598.   void postflightKey(void *) override;
  1599.   std::vector<StringRef> keys() override;
  1600.   void beginFlowMapping() override;
  1601.   void endFlowMapping() override;
  1602.   unsigned beginSequence() override;
  1603.   void endSequence() override;
  1604.   bool preflightElement(unsigned, void *&) override;
  1605.   void postflightElement(void *) override;
  1606.   unsigned beginFlowSequence() override;
  1607.   bool preflightFlowElement(unsigned, void *&) override;
  1608.   void postflightFlowElement(void *) override;
  1609.   void endFlowSequence() override;
  1610.   void beginEnumScalar() override;
  1611.   bool matchEnumScalar(const char*, bool) override;
  1612.   bool matchEnumFallback() override;
  1613.   void endEnumScalar() override;
  1614.   bool beginBitSetScalar(bool &) override;
  1615.   bool bitSetMatch(const char *, bool ) override;
  1616.   void endBitSetScalar() override;
  1617.   void scalarString(StringRef &, QuotingType) override;
  1618.   void blockScalarString(StringRef &) override;
  1619.   void scalarTag(std::string &) override;
  1620.   NodeKind getNodeKind() override;
  1621.   void setError(const Twine &message) override;
  1622.   bool canElideEmptySequence() override;
  1623.  
  1624.   // These are only used by operator<<. They could be private
  1625.   // if that templated operator could be made a friend.
  1626.   void beginDocuments();
  1627.   bool preflightDocument(unsigned);
  1628.   void postflightDocument();
  1629.   void endDocuments();
  1630.  
  1631. private:
  1632.   void output(StringRef s);
  1633.   void outputUpToEndOfLine(StringRef s);
  1634.   void newLineCheck(bool EmptySequence = false);
  1635.   void outputNewLine();
  1636.   void paddedKey(StringRef key);
  1637.   void flowKey(StringRef Key);
  1638.  
  1639.   enum InState {
  1640.     inSeqFirstElement,
  1641.     inSeqOtherElement,
  1642.     inFlowSeqFirstElement,
  1643.     inFlowSeqOtherElement,
  1644.     inMapFirstKey,
  1645.     inMapOtherKey,
  1646.     inFlowMapFirstKey,
  1647.     inFlowMapOtherKey
  1648.   };
  1649.  
  1650.   static bool inSeqAnyElement(InState State);
  1651.   static bool inFlowSeqAnyElement(InState State);
  1652.   static bool inMapAnyKey(InState State);
  1653.   static bool inFlowMapAnyKey(InState State);
  1654.  
  1655.   raw_ostream &Out;
  1656.   int WrapColumn;
  1657.   SmallVector<InState, 8> StateStack;
  1658.   int Column = 0;
  1659.   int ColumnAtFlowStart = 0;
  1660.   int ColumnAtMapFlowStart = 0;
  1661.   bool NeedBitValueComma = false;
  1662.   bool NeedFlowSequenceComma = false;
  1663.   bool EnumerationMatchFound = false;
  1664.   bool WriteDefaultValues = false;
  1665.   StringRef Padding;
  1666.   StringRef PaddingBeforeContainer;
  1667. };
  1668.  
  1669. template <typename T, typename Context>
  1670. void IO::processKeyWithDefault(const char *Key, std::optional<T> &Val,
  1671.                                const std::optional<T> &DefaultValue,
  1672.                                bool Required, Context &Ctx) {
  1673.   assert(!DefaultValue && "std::optional<T> shouldn't have a value!");
  1674.   void *SaveInfo;
  1675.   bool UseDefault = true;
  1676.   const bool sameAsDefault = outputting() && !Val;
  1677.   if (!outputting() && !Val)
  1678.     Val = T();
  1679.   if (Val &&
  1680.       this->preflightKey(Key, Required, sameAsDefault, UseDefault, SaveInfo)) {
  1681.  
  1682.     // When reading an std::optional<X> key from a YAML description, we allow
  1683.     // the special "<none>" value, which can be used to specify that no value
  1684.     // was requested, i.e. the DefaultValue will be assigned. The DefaultValue
  1685.     // is usually None.
  1686.     bool IsNone = false;
  1687.     if (!outputting())
  1688.       if (const auto *Node =
  1689.               dyn_cast<ScalarNode>(((Input *)this)->getCurrentNode()))
  1690.         // We use rtrim to ignore possible white spaces that might exist when a
  1691.         // comment is present on the same line.
  1692.         IsNone = Node->getRawValue().rtrim(' ') == "<none>";
  1693.  
  1694.     if (IsNone)
  1695.       Val = DefaultValue;
  1696.     else
  1697.       yamlize(*this, *Val, Required, Ctx);
  1698.     this->postflightKey(SaveInfo);
  1699.   } else {
  1700.     if (UseDefault)
  1701.       Val = DefaultValue;
  1702.   }
  1703. }
  1704.  
  1705. /// YAML I/O does conversion based on types. But often native data types
  1706. /// are just a typedef of built in intergral types (e.g. int).  But the C++
  1707. /// type matching system sees through the typedef and all the typedefed types
  1708. /// look like a built in type. This will cause the generic YAML I/O conversion
  1709. /// to be used. To provide better control over the YAML conversion, you can
  1710. /// use this macro instead of typedef.  It will create a class with one field
  1711. /// and automatic conversion operators to and from the base type.
  1712. /// Based on BOOST_STRONG_TYPEDEF
  1713. #define LLVM_YAML_STRONG_TYPEDEF(_base, _type)                                 \
  1714.     struct _type {                                                             \
  1715.         _type() = default;                                                     \
  1716.         _type(const _base v) : value(v) {}                                     \
  1717.         _type(const _type &v) = default;                                       \
  1718.         _type &operator=(const _type &rhs) = default;                          \
  1719.         _type &operator=(const _base &rhs) { value = rhs; return *this; }      \
  1720.         operator const _base & () const { return value; }                      \
  1721.         bool operator==(const _type &rhs) const { return value == rhs.value; } \
  1722.         bool operator==(const _base &rhs) const { return value == rhs; }       \
  1723.         bool operator<(const _type &rhs) const { return value < rhs.value; }   \
  1724.         _base value;                                                           \
  1725.         using BaseType = _base;                                                \
  1726.     };
  1727.  
  1728. ///
  1729. /// Use these types instead of uintXX_t in any mapping to have
  1730. /// its yaml output formatted as hexadecimal.
  1731. ///
  1732. LLVM_YAML_STRONG_TYPEDEF(uint8_t, Hex8)
  1733. LLVM_YAML_STRONG_TYPEDEF(uint16_t, Hex16)
  1734. LLVM_YAML_STRONG_TYPEDEF(uint32_t, Hex32)
  1735. LLVM_YAML_STRONG_TYPEDEF(uint64_t, Hex64)
  1736.  
  1737. template<>
  1738. struct ScalarTraits<Hex8> {
  1739.   static void output(const Hex8 &, void *, raw_ostream &);
  1740.   static StringRef input(StringRef, void *, Hex8 &);
  1741.   static QuotingType mustQuote(StringRef) { return QuotingType::None; }
  1742. };
  1743.  
  1744. template<>
  1745. struct ScalarTraits<Hex16> {
  1746.   static void output(const Hex16 &, void *, raw_ostream &);
  1747.   static StringRef input(StringRef, void *, Hex16 &);
  1748.   static QuotingType mustQuote(StringRef) { return QuotingType::None; }
  1749. };
  1750.  
  1751. template<>
  1752. struct ScalarTraits<Hex32> {
  1753.   static void output(const Hex32 &, void *, raw_ostream &);
  1754.   static StringRef input(StringRef, void *, Hex32 &);
  1755.   static QuotingType mustQuote(StringRef) { return QuotingType::None; }
  1756. };
  1757.  
  1758. template<>
  1759. struct ScalarTraits<Hex64> {
  1760.   static void output(const Hex64 &, void *, raw_ostream &);
  1761.   static StringRef input(StringRef, void *, Hex64 &);
  1762.   static QuotingType mustQuote(StringRef) { return QuotingType::None; }
  1763. };
  1764.  
  1765. template <> struct ScalarTraits<VersionTuple> {
  1766.   static void output(const VersionTuple &Value, void *, llvm::raw_ostream &Out);
  1767.   static StringRef input(StringRef, void *, VersionTuple &);
  1768.   static QuotingType mustQuote(StringRef) { return QuotingType::None; }
  1769. };
  1770.  
  1771. // Define non-member operator>> so that Input can stream in a document list.
  1772. template <typename T>
  1773. inline std::enable_if_t<has_DocumentListTraits<T>::value, Input &>
  1774. operator>>(Input &yin, T &docList) {
  1775.   int i = 0;
  1776.   EmptyContext Ctx;
  1777.   while ( yin.setCurrentDocument() ) {
  1778.     yamlize(yin, DocumentListTraits<T>::element(yin, docList, i), true, Ctx);
  1779.     if ( yin.error() )
  1780.       return yin;
  1781.     yin.nextDocument();
  1782.     ++i;
  1783.   }
  1784.   return yin;
  1785. }
  1786.  
  1787. // Define non-member operator>> so that Input can stream in a map as a document.
  1788. template <typename T>
  1789. inline std::enable_if_t<has_MappingTraits<T, EmptyContext>::value, Input &>
  1790. operator>>(Input &yin, T &docMap) {
  1791.   EmptyContext Ctx;
  1792.   yin.setCurrentDocument();
  1793.   yamlize(yin, docMap, true, Ctx);
  1794.   return yin;
  1795. }
  1796.  
  1797. // Define non-member operator>> so that Input can stream in a sequence as
  1798. // a document.
  1799. template <typename T>
  1800. inline std::enable_if_t<has_SequenceTraits<T>::value, Input &>
  1801. operator>>(Input &yin, T &docSeq) {
  1802.   EmptyContext Ctx;
  1803.   if (yin.setCurrentDocument())
  1804.     yamlize(yin, docSeq, true, Ctx);
  1805.   return yin;
  1806. }
  1807.  
  1808. // Define non-member operator>> so that Input can stream in a block scalar.
  1809. template <typename T>
  1810. inline std::enable_if_t<has_BlockScalarTraits<T>::value, Input &>
  1811. operator>>(Input &In, T &Val) {
  1812.   EmptyContext Ctx;
  1813.   if (In.setCurrentDocument())
  1814.     yamlize(In, Val, true, Ctx);
  1815.   return In;
  1816. }
  1817.  
  1818. // Define non-member operator>> so that Input can stream in a string map.
  1819. template <typename T>
  1820. inline std::enable_if_t<has_CustomMappingTraits<T>::value, Input &>
  1821. operator>>(Input &In, T &Val) {
  1822.   EmptyContext Ctx;
  1823.   if (In.setCurrentDocument())
  1824.     yamlize(In, Val, true, Ctx);
  1825.   return In;
  1826. }
  1827.  
  1828. // Define non-member operator>> so that Input can stream in a polymorphic type.
  1829. template <typename T>
  1830. inline std::enable_if_t<has_PolymorphicTraits<T>::value, Input &>
  1831. operator>>(Input &In, T &Val) {
  1832.   EmptyContext Ctx;
  1833.   if (In.setCurrentDocument())
  1834.     yamlize(In, Val, true, Ctx);
  1835.   return In;
  1836. }
  1837.  
  1838. // Provide better error message about types missing a trait specialization
  1839. template <typename T>
  1840. inline std::enable_if_t<missingTraits<T, EmptyContext>::value, Input &>
  1841. operator>>(Input &yin, T &docSeq) {
  1842.   char missing_yaml_trait_for_type[sizeof(MissingTrait<T>)];
  1843.   return yin;
  1844. }
  1845.  
  1846. // Define non-member operator<< so that Output can stream out document list.
  1847. template <typename T>
  1848. inline std::enable_if_t<has_DocumentListTraits<T>::value, Output &>
  1849. operator<<(Output &yout, T &docList) {
  1850.   EmptyContext Ctx;
  1851.   yout.beginDocuments();
  1852.   const size_t count = DocumentListTraits<T>::size(yout, docList);
  1853.   for(size_t i=0; i < count; ++i) {
  1854.     if ( yout.preflightDocument(i) ) {
  1855.       yamlize(yout, DocumentListTraits<T>::element(yout, docList, i), true,
  1856.               Ctx);
  1857.       yout.postflightDocument();
  1858.     }
  1859.   }
  1860.   yout.endDocuments();
  1861.   return yout;
  1862. }
  1863.  
  1864. // Define non-member operator<< so that Output can stream out a map.
  1865. template <typename T>
  1866. inline std::enable_if_t<has_MappingTraits<T, EmptyContext>::value, Output &>
  1867. operator<<(Output &yout, T &map) {
  1868.   EmptyContext Ctx;
  1869.   yout.beginDocuments();
  1870.   if ( yout.preflightDocument(0) ) {
  1871.     yamlize(yout, map, true, Ctx);
  1872.     yout.postflightDocument();
  1873.   }
  1874.   yout.endDocuments();
  1875.   return yout;
  1876. }
  1877.  
  1878. // Define non-member operator<< so that Output can stream out a sequence.
  1879. template <typename T>
  1880. inline std::enable_if_t<has_SequenceTraits<T>::value, Output &>
  1881. operator<<(Output &yout, T &seq) {
  1882.   EmptyContext Ctx;
  1883.   yout.beginDocuments();
  1884.   if ( yout.preflightDocument(0) ) {
  1885.     yamlize(yout, seq, true, Ctx);
  1886.     yout.postflightDocument();
  1887.   }
  1888.   yout.endDocuments();
  1889.   return yout;
  1890. }
  1891.  
  1892. // Define non-member operator<< so that Output can stream out a block scalar.
  1893. template <typename T>
  1894. inline std::enable_if_t<has_BlockScalarTraits<T>::value, Output &>
  1895. operator<<(Output &Out, T &Val) {
  1896.   EmptyContext Ctx;
  1897.   Out.beginDocuments();
  1898.   if (Out.preflightDocument(0)) {
  1899.     yamlize(Out, Val, true, Ctx);
  1900.     Out.postflightDocument();
  1901.   }
  1902.   Out.endDocuments();
  1903.   return Out;
  1904. }
  1905.  
  1906. // Define non-member operator<< so that Output can stream out a string map.
  1907. template <typename T>
  1908. inline std::enable_if_t<has_CustomMappingTraits<T>::value, Output &>
  1909. operator<<(Output &Out, T &Val) {
  1910.   EmptyContext Ctx;
  1911.   Out.beginDocuments();
  1912.   if (Out.preflightDocument(0)) {
  1913.     yamlize(Out, Val, true, Ctx);
  1914.     Out.postflightDocument();
  1915.   }
  1916.   Out.endDocuments();
  1917.   return Out;
  1918. }
  1919.  
  1920. // Define non-member operator<< so that Output can stream out a polymorphic
  1921. // type.
  1922. template <typename T>
  1923. inline std::enable_if_t<has_PolymorphicTraits<T>::value, Output &>
  1924. operator<<(Output &Out, T &Val) {
  1925.   EmptyContext Ctx;
  1926.   Out.beginDocuments();
  1927.   if (Out.preflightDocument(0)) {
  1928.     // FIXME: The parser does not support explicit documents terminated with a
  1929.     // plain scalar; the end-marker is included as part of the scalar token.
  1930.     assert(PolymorphicTraits<T>::getKind(Val) != NodeKind::Scalar && "plain scalar documents are not supported");
  1931.     yamlize(Out, Val, true, Ctx);
  1932.     Out.postflightDocument();
  1933.   }
  1934.   Out.endDocuments();
  1935.   return Out;
  1936. }
  1937.  
  1938. // Provide better error message about types missing a trait specialization
  1939. template <typename T>
  1940. inline std::enable_if_t<missingTraits<T, EmptyContext>::value, Output &>
  1941. operator<<(Output &yout, T &seq) {
  1942.   char missing_yaml_trait_for_type[sizeof(MissingTrait<T>)];
  1943.   return yout;
  1944. }
  1945.  
  1946. template <bool B> struct IsFlowSequenceBase {};
  1947. template <> struct IsFlowSequenceBase<true> { static const bool flow = true; };
  1948.  
  1949. template <typename T, typename U = void>
  1950. struct IsResizable : std::false_type {};
  1951.  
  1952. template <typename T>
  1953. struct IsResizable<T, std::void_t<decltype(std::declval<T>().resize(0))>>
  1954.     : public std::true_type {};
  1955.  
  1956. template <typename T, bool B> struct IsResizableBase {
  1957.   using type = typename T::value_type;
  1958.  
  1959.   static type &element(IO &io, T &seq, size_t index) {
  1960.     if (index >= seq.size())
  1961.       seq.resize(index + 1);
  1962.     return seq[index];
  1963.   }
  1964. };
  1965.  
  1966. template <typename T> struct IsResizableBase<T, false> {
  1967.   using type = typename T::value_type;
  1968.  
  1969.   static type &element(IO &io, T &seq, size_t index) {
  1970.     if (index >= seq.size()) {
  1971.       io.setError(Twine("value sequence extends beyond static size (") +
  1972.                   Twine(seq.size()) + ")");
  1973.       return seq[0];
  1974.     }
  1975.     return seq[index];
  1976.   }
  1977. };
  1978.  
  1979. template <typename T, bool Flow>
  1980. struct SequenceTraitsImpl
  1981.     : IsFlowSequenceBase<Flow>, IsResizableBase<T, IsResizable<T>::value> {
  1982.   static size_t size(IO &io, T &seq) { return seq.size(); }
  1983. };
  1984.  
  1985. // Simple helper to check an expression can be used as a bool-valued template
  1986. // argument.
  1987. template <bool> struct CheckIsBool { static const bool value = true; };
  1988.  
  1989. // If T has SequenceElementTraits, then vector<T> and SmallVector<T, N> have
  1990. // SequenceTraits that do the obvious thing.
  1991. template <typename T>
  1992. struct SequenceTraits<
  1993.     std::vector<T>,
  1994.     std::enable_if_t<CheckIsBool<SequenceElementTraits<T>::flow>::value>>
  1995.     : SequenceTraitsImpl<std::vector<T>, SequenceElementTraits<T>::flow> {};
  1996. template <typename T, unsigned N>
  1997. struct SequenceTraits<
  1998.     SmallVector<T, N>,
  1999.     std::enable_if_t<CheckIsBool<SequenceElementTraits<T>::flow>::value>>
  2000.     : SequenceTraitsImpl<SmallVector<T, N>, SequenceElementTraits<T>::flow> {};
  2001. template <typename T>
  2002. struct SequenceTraits<
  2003.     SmallVectorImpl<T>,
  2004.     std::enable_if_t<CheckIsBool<SequenceElementTraits<T>::flow>::value>>
  2005.     : SequenceTraitsImpl<SmallVectorImpl<T>, SequenceElementTraits<T>::flow> {};
  2006. template <typename T>
  2007. struct SequenceTraits<
  2008.     MutableArrayRef<T>,
  2009.     std::enable_if_t<CheckIsBool<SequenceElementTraits<T>::flow>::value>>
  2010.     : SequenceTraitsImpl<MutableArrayRef<T>, SequenceElementTraits<T>::flow> {};
  2011.  
  2012. // Sequences of fundamental types use flow formatting.
  2013. template <typename T>
  2014. struct SequenceElementTraits<T,
  2015.                              std::enable_if_t<std::is_fundamental<T>::value>> {
  2016.   static const bool flow = true;
  2017. };
  2018.  
  2019. // Sequences of strings use block formatting.
  2020. template<> struct SequenceElementTraits<std::string> {
  2021.   static const bool flow = false;
  2022. };
  2023. template<> struct SequenceElementTraits<StringRef> {
  2024.   static const bool flow = false;
  2025. };
  2026. template<> struct SequenceElementTraits<std::pair<std::string, std::string>> {
  2027.   static const bool flow = false;
  2028. };
  2029.  
  2030. /// Implementation of CustomMappingTraits for std::map<std::string, T>.
  2031. template <typename T> struct StdMapStringCustomMappingTraitsImpl {
  2032.   using map_type = std::map<std::string, T>;
  2033.  
  2034.   static void inputOne(IO &io, StringRef key, map_type &v) {
  2035.     io.mapRequired(key.str().c_str(), v[std::string(key)]);
  2036.   }
  2037.  
  2038.   static void output(IO &io, map_type &v) {
  2039.     for (auto &p : v)
  2040.       io.mapRequired(p.first.c_str(), p.second);
  2041.   }
  2042. };
  2043.  
  2044. } // end namespace yaml
  2045. } // end namespace llvm
  2046.  
  2047. #define LLVM_YAML_IS_SEQUENCE_VECTOR_IMPL(TYPE, FLOW)                          \
  2048.   namespace llvm {                                                             \
  2049.   namespace yaml {                                                             \
  2050.   static_assert(                                                               \
  2051.       !std::is_fundamental_v<TYPE> && !std::is_same_v<TYPE, std::string> &&    \
  2052.           !std::is_same_v<TYPE, llvm::StringRef>,                              \
  2053.       "only use LLVM_YAML_IS_SEQUENCE_VECTOR for types you control");          \
  2054.   template <> struct SequenceElementTraits<TYPE> {                             \
  2055.     static const bool flow = FLOW;                                             \
  2056.   };                                                                           \
  2057.   }                                                                            \
  2058.   }
  2059.  
  2060. /// Utility for declaring that a std::vector of a particular type
  2061. /// should be considered a YAML sequence.
  2062. #define LLVM_YAML_IS_SEQUENCE_VECTOR(type)                                     \
  2063.   LLVM_YAML_IS_SEQUENCE_VECTOR_IMPL(type, false)
  2064.  
  2065. /// Utility for declaring that a std::vector of a particular type
  2066. /// should be considered a YAML flow sequence.
  2067. #define LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(type)                                \
  2068.   LLVM_YAML_IS_SEQUENCE_VECTOR_IMPL(type, true)
  2069.  
  2070. #define LLVM_YAML_DECLARE_MAPPING_TRAITS(Type)                                 \
  2071.   namespace llvm {                                                             \
  2072.   namespace yaml {                                                             \
  2073.   template <> struct MappingTraits<Type> {                                     \
  2074.     static void mapping(IO &IO, Type &Obj);                                    \
  2075.   };                                                                           \
  2076.   }                                                                            \
  2077.   }
  2078.  
  2079. #define LLVM_YAML_DECLARE_ENUM_TRAITS(Type)                                    \
  2080.   namespace llvm {                                                             \
  2081.   namespace yaml {                                                             \
  2082.   template <> struct ScalarEnumerationTraits<Type> {                           \
  2083.     static void enumeration(IO &io, Type &Value);                              \
  2084.   };                                                                           \
  2085.   }                                                                            \
  2086.   }
  2087.  
  2088. #define LLVM_YAML_DECLARE_BITSET_TRAITS(Type)                                  \
  2089.   namespace llvm {                                                             \
  2090.   namespace yaml {                                                             \
  2091.   template <> struct ScalarBitSetTraits<Type> {                                \
  2092.     static void bitset(IO &IO, Type &Options);                                 \
  2093.   };                                                                           \
  2094.   }                                                                            \
  2095.   }
  2096.  
  2097. #define LLVM_YAML_DECLARE_SCALAR_TRAITS(Type, MustQuote)                       \
  2098.   namespace llvm {                                                             \
  2099.   namespace yaml {                                                             \
  2100.   template <> struct ScalarTraits<Type> {                                      \
  2101.     static void output(const Type &Value, void *ctx, raw_ostream &Out);        \
  2102.     static StringRef input(StringRef Scalar, void *ctxt, Type &Value);         \
  2103.     static QuotingType mustQuote(StringRef) { return MustQuote; }              \
  2104.   };                                                                           \
  2105.   }                                                                            \
  2106.   }
  2107.  
  2108. /// Utility for declaring that a std::vector of a particular type
  2109. /// should be considered a YAML document list.
  2110. #define LLVM_YAML_IS_DOCUMENT_LIST_VECTOR(_type)                               \
  2111.   namespace llvm {                                                             \
  2112.   namespace yaml {                                                             \
  2113.   template <unsigned N>                                                        \
  2114.   struct DocumentListTraits<SmallVector<_type, N>>                             \
  2115.       : public SequenceTraitsImpl<SmallVector<_type, N>, false> {};            \
  2116.   template <>                                                                  \
  2117.   struct DocumentListTraits<std::vector<_type>>                                \
  2118.       : public SequenceTraitsImpl<std::vector<_type>, false> {};               \
  2119.   }                                                                            \
  2120.   }
  2121.  
  2122. /// Utility for declaring that std::map<std::string, _type> should be considered
  2123. /// a YAML map.
  2124. #define LLVM_YAML_IS_STRING_MAP(_type)                                         \
  2125.   namespace llvm {                                                             \
  2126.   namespace yaml {                                                             \
  2127.   template <>                                                                  \
  2128.   struct CustomMappingTraits<std::map<std::string, _type>>                     \
  2129.       : public StdMapStringCustomMappingTraitsImpl<_type> {};                  \
  2130.   }                                                                            \
  2131.   }
  2132.  
  2133. LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(llvm::yaml::Hex64)
  2134. LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(llvm::yaml::Hex32)
  2135. LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(llvm::yaml::Hex16)
  2136. LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(llvm::yaml::Hex8)
  2137.  
  2138. #endif // LLVM_SUPPORT_YAMLTRAITS_H
  2139.