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