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