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.starts_with("0o"))
588     return S.size() > 2 &&
589            S.drop_front(2).find_first_not_of("01234567") == StringRef::npos;
590 
591   if (S.starts_with("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.starts_with(".") &&
602       (S.equals(".") ||
603        (S.size() > 1 && std::strchr("0123456789", S[1]) == nullptr)))
604     return false;
605 
606   if (S.starts_with("E") || S.starts_with("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 namespace detail {
1062 
1063 template <typename T, typename Context>
1064 std::string doValidate(IO &io, T &Val, Context &Ctx) {
1065   return MappingContextTraits<T, Context>::validate(io, Val, Ctx);
1066 }
1067 
1068 template <typename T> std::string doValidate(IO &io, T &Val, EmptyContext &) {
1069   return MappingTraits<T>::validate(io, Val);
1070 }
1071 
1072 } // namespace detail
1073 
1074 template <typename T, typename Context>
1075 std::enable_if_t<validatedMappingTraits<T, Context>::value, void>
1076 yamlize(IO &io, T &Val, bool, Context &Ctx) {
1077   if (has_FlowTraits<MappingTraits<T>>::value)
1078     io.beginFlowMapping();
1079   else
1080     io.beginMapping();
1081   if (io.outputting()) {
1082     std::string Err = detail::doValidate(io, Val, Ctx);
1083     if (!Err.empty()) {
1084       errs() << Err << "\n";
1085       assert(Err.empty() && "invalid struct trying to be written as yaml");
1086     }
1087   }
1088   detail::doMapping(io, Val, Ctx);
1089   if (!io.outputting()) {
1090     std::string Err = detail::doValidate(io, Val, Ctx);
1091     if (!Err.empty())
1092       io.setError(Err);
1093   }
1094   if (has_FlowTraits<MappingTraits<T>>::value)
1095     io.endFlowMapping();
1096   else
1097     io.endMapping();
1098 }
1099 
1100 template <typename T, typename Context>
1101 std::enable_if_t<!has_MappingEnumInputTraits<T, Context>::value, bool>
1102 yamlizeMappingEnumInput(IO &io, T &Val) {
1103   return false;
1104 }
1105 
1106 template <typename T, typename Context>
1107 std::enable_if_t<has_MappingEnumInputTraits<T, Context>::value, bool>
1108 yamlizeMappingEnumInput(IO &io, T &Val) {
1109   if (io.outputting())
1110     return false;
1111 
1112   io.beginEnumScalar();
1113   MappingTraits<T>::enumInput(io, Val);
1114   bool Matched = !io.matchEnumFallback();
1115   io.endEnumScalar();
1116   return Matched;
1117 }
1118 
1119 template <typename T, typename Context>
1120 std::enable_if_t<unvalidatedMappingTraits<T, Context>::value, void>
1121 yamlize(IO &io, T &Val, bool, Context &Ctx) {
1122   if (yamlizeMappingEnumInput<T, Context>(io, Val))
1123     return;
1124   if (has_FlowTraits<MappingTraits<T>>::value) {
1125     io.beginFlowMapping();
1126     detail::doMapping(io, Val, Ctx);
1127     io.endFlowMapping();
1128   } else {
1129     io.beginMapping();
1130     detail::doMapping(io, Val, Ctx);
1131     io.endMapping();
1132   }
1133 }
1134 
1135 template <typename T>
1136 std::enable_if_t<has_CustomMappingTraits<T>::value, void>
1137 yamlize(IO &io, T &Val, bool, EmptyContext &Ctx) {
1138   if ( io.outputting() ) {
1139     io.beginMapping();
1140     CustomMappingTraits<T>::output(io, Val);
1141     io.endMapping();
1142   } else {
1143     io.beginMapping();
1144     for (StringRef key : io.keys())
1145       CustomMappingTraits<T>::inputOne(io, key, Val);
1146     io.endMapping();
1147   }
1148 }
1149 
1150 template <typename T>
1151 std::enable_if_t<has_PolymorphicTraits<T>::value, void>
1152 yamlize(IO &io, T &Val, bool, EmptyContext &Ctx) {
1153   switch (io.outputting() ? PolymorphicTraits<T>::getKind(Val)
1154                           : io.getNodeKind()) {
1155   case NodeKind::Scalar:
1156     return yamlize(io, PolymorphicTraits<T>::getAsScalar(Val), true, Ctx);
1157   case NodeKind::Map:
1158     return yamlize(io, PolymorphicTraits<T>::getAsMap(Val), true, Ctx);
1159   case NodeKind::Sequence:
1160     return yamlize(io, PolymorphicTraits<T>::getAsSequence(Val), true, Ctx);
1161   }
1162 }
1163 
1164 template <typename T>
1165 std::enable_if_t<missingTraits<T, EmptyContext>::value, void>
1166 yamlize(IO &io, T &Val, bool, EmptyContext &Ctx) {
1167   char missing_yaml_trait_for_type[sizeof(MissingTrait<T>)];
1168 }
1169 
1170 template <typename T, typename Context>
1171 std::enable_if_t<has_SequenceTraits<T>::value, void>
1172 yamlize(IO &io, T &Seq, bool, Context &Ctx) {
1173   if ( has_FlowTraits< SequenceTraits<T>>::value ) {
1174     unsigned incnt = io.beginFlowSequence();
1175     unsigned count = io.outputting() ? SequenceTraits<T>::size(io, Seq) : incnt;
1176     for(unsigned i=0; i < count; ++i) {
1177       void *SaveInfo;
1178       if ( io.preflightFlowElement(i, SaveInfo) ) {
1179         yamlize(io, SequenceTraits<T>::element(io, Seq, i), true, Ctx);
1180         io.postflightFlowElement(SaveInfo);
1181       }
1182     }
1183     io.endFlowSequence();
1184   }
1185   else {
1186     unsigned incnt = io.beginSequence();
1187     unsigned count = io.outputting() ? SequenceTraits<T>::size(io, Seq) : incnt;
1188     for(unsigned i=0; i < count; ++i) {
1189       void *SaveInfo;
1190       if ( io.preflightElement(i, SaveInfo) ) {
1191         yamlize(io, SequenceTraits<T>::element(io, Seq, i), true, Ctx);
1192         io.postflightElement(SaveInfo);
1193       }
1194     }
1195     io.endSequence();
1196   }
1197 }
1198 
1199 template<>
1200 struct ScalarTraits<bool> {
1201   static void output(const bool &, void* , raw_ostream &);
1202   static StringRef input(StringRef, void *, bool &);
1203   static QuotingType mustQuote(StringRef) { return QuotingType::None; }
1204 };
1205 
1206 template<>
1207 struct ScalarTraits<StringRef> {
1208   static void output(const StringRef &, void *, raw_ostream &);
1209   static StringRef input(StringRef, void *, StringRef &);
1210   static QuotingType mustQuote(StringRef S) { return needsQuotes(S); }
1211 };
1212 
1213 template<>
1214 struct ScalarTraits<std::string> {
1215   static void output(const std::string &, void *, raw_ostream &);
1216   static StringRef input(StringRef, void *, std::string &);
1217   static QuotingType mustQuote(StringRef S) { return needsQuotes(S); }
1218 };
1219 
1220 template<>
1221 struct ScalarTraits<uint8_t> {
1222   static void output(const uint8_t &, void *, raw_ostream &);
1223   static StringRef input(StringRef, void *, uint8_t &);
1224   static QuotingType mustQuote(StringRef) { return QuotingType::None; }
1225 };
1226 
1227 template<>
1228 struct ScalarTraits<uint16_t> {
1229   static void output(const uint16_t &, void *, raw_ostream &);
1230   static StringRef input(StringRef, void *, uint16_t &);
1231   static QuotingType mustQuote(StringRef) { return QuotingType::None; }
1232 };
1233 
1234 template<>
1235 struct ScalarTraits<uint32_t> {
1236   static void output(const uint32_t &, void *, raw_ostream &);
1237   static StringRef input(StringRef, void *, uint32_t &);
1238   static QuotingType mustQuote(StringRef) { return QuotingType::None; }
1239 };
1240 
1241 template<>
1242 struct ScalarTraits<uint64_t> {
1243   static void output(const uint64_t &, void *, raw_ostream &);
1244   static StringRef input(StringRef, void *, uint64_t &);
1245   static QuotingType mustQuote(StringRef) { return QuotingType::None; }
1246 };
1247 
1248 template<>
1249 struct ScalarTraits<int8_t> {
1250   static void output(const int8_t &, void *, raw_ostream &);
1251   static StringRef input(StringRef, void *, int8_t &);
1252   static QuotingType mustQuote(StringRef) { return QuotingType::None; }
1253 };
1254 
1255 template<>
1256 struct ScalarTraits<int16_t> {
1257   static void output(const int16_t &, void *, raw_ostream &);
1258   static StringRef input(StringRef, void *, int16_t &);
1259   static QuotingType mustQuote(StringRef) { return QuotingType::None; }
1260 };
1261 
1262 template<>
1263 struct ScalarTraits<int32_t> {
1264   static void output(const int32_t &, void *, raw_ostream &);
1265   static StringRef input(StringRef, void *, int32_t &);
1266   static QuotingType mustQuote(StringRef) { return QuotingType::None; }
1267 };
1268 
1269 template<>
1270 struct ScalarTraits<int64_t> {
1271   static void output(const int64_t &, void *, raw_ostream &);
1272   static StringRef input(StringRef, void *, int64_t &);
1273   static QuotingType mustQuote(StringRef) { return QuotingType::None; }
1274 };
1275 
1276 template<>
1277 struct ScalarTraits<float> {
1278   static void output(const float &, void *, raw_ostream &);
1279   static StringRef input(StringRef, void *, float &);
1280   static QuotingType mustQuote(StringRef) { return QuotingType::None; }
1281 };
1282 
1283 template<>
1284 struct ScalarTraits<double> {
1285   static void output(const double &, void *, raw_ostream &);
1286   static StringRef input(StringRef, void *, double &);
1287   static QuotingType mustQuote(StringRef) { return QuotingType::None; }
1288 };
1289 
1290 // For endian types, we use existing scalar Traits class for the underlying
1291 // type.  This way endian aware types are supported whenever the traits are
1292 // defined for the underlying type.
1293 template <typename value_type, llvm::endianness endian, size_t alignment>
1294 struct ScalarTraits<support::detail::packed_endian_specific_integral<
1295                         value_type, endian, alignment>,
1296                     std::enable_if_t<has_ScalarTraits<value_type>::value>> {
1297   using endian_type =
1298       support::detail::packed_endian_specific_integral<value_type, endian,
1299                                                        alignment>;
1300 
1301   static void output(const endian_type &E, void *Ctx, raw_ostream &Stream) {
1302     ScalarTraits<value_type>::output(static_cast<value_type>(E), Ctx, Stream);
1303   }
1304 
1305   static StringRef input(StringRef Str, void *Ctx, endian_type &E) {
1306     value_type V;
1307     auto R = ScalarTraits<value_type>::input(Str, Ctx, V);
1308     E = static_cast<endian_type>(V);
1309     return R;
1310   }
1311 
1312   static QuotingType mustQuote(StringRef Str) {
1313     return ScalarTraits<value_type>::mustQuote(Str);
1314   }
1315 };
1316 
1317 template <typename value_type, llvm::endianness endian, size_t alignment>
1318 struct ScalarEnumerationTraits<
1319     support::detail::packed_endian_specific_integral<value_type, endian,
1320                                                      alignment>,
1321     std::enable_if_t<has_ScalarEnumerationTraits<value_type>::value>> {
1322   using endian_type =
1323       support::detail::packed_endian_specific_integral<value_type, endian,
1324                                                        alignment>;
1325 
1326   static void enumeration(IO &io, endian_type &E) {
1327     value_type V = E;
1328     ScalarEnumerationTraits<value_type>::enumeration(io, V);
1329     E = V;
1330   }
1331 };
1332 
1333 template <typename value_type, llvm::endianness endian, size_t alignment>
1334 struct ScalarBitSetTraits<
1335     support::detail::packed_endian_specific_integral<value_type, endian,
1336                                                      alignment>,
1337     std::enable_if_t<has_ScalarBitSetTraits<value_type>::value>> {
1338   using endian_type =
1339       support::detail::packed_endian_specific_integral<value_type, endian,
1340                                                        alignment>;
1341   static void bitset(IO &io, endian_type &E) {
1342     value_type V = E;
1343     ScalarBitSetTraits<value_type>::bitset(io, V);
1344     E = V;
1345   }
1346 };
1347 
1348 // Utility for use within MappingTraits<>::mapping() method
1349 // to [de]normalize an object for use with YAML conversion.
1350 template <typename TNorm, typename TFinal>
1351 struct MappingNormalization {
1352   MappingNormalization(IO &i_o, TFinal &Obj)
1353       : io(i_o), BufPtr(nullptr), Result(Obj) {
1354     if ( io.outputting() ) {
1355       BufPtr = new (&Buffer) TNorm(io, Obj);
1356     }
1357     else {
1358       BufPtr = new (&Buffer) TNorm(io);
1359     }
1360   }
1361 
1362   ~MappingNormalization() {
1363     if ( ! io.outputting() ) {
1364       Result = BufPtr->denormalize(io);
1365     }
1366     BufPtr->~TNorm();
1367   }
1368 
1369   TNorm* operator->() { return BufPtr; }
1370 
1371 private:
1372   using Storage = AlignedCharArrayUnion<TNorm>;
1373 
1374   Storage       Buffer;
1375   IO           &io;
1376   TNorm        *BufPtr;
1377   TFinal       &Result;
1378 };
1379 
1380 // Utility for use within MappingTraits<>::mapping() method
1381 // to [de]normalize an object for use with YAML conversion.
1382 template <typename TNorm, typename TFinal>
1383 struct MappingNormalizationHeap {
1384   MappingNormalizationHeap(IO &i_o, TFinal &Obj, BumpPtrAllocator *allocator)
1385     : io(i_o), Result(Obj) {
1386     if ( io.outputting() ) {
1387       BufPtr = new (&Buffer) TNorm(io, Obj);
1388     }
1389     else if (allocator) {
1390       BufPtr = allocator->Allocate<TNorm>();
1391       new (BufPtr) TNorm(io);
1392     } else {
1393       BufPtr = new TNorm(io);
1394     }
1395   }
1396 
1397   ~MappingNormalizationHeap() {
1398     if ( io.outputting() ) {
1399       BufPtr->~TNorm();
1400     }
1401     else {
1402       Result = BufPtr->denormalize(io);
1403     }
1404   }
1405 
1406   TNorm* operator->() { return BufPtr; }
1407 
1408 private:
1409   using Storage = AlignedCharArrayUnion<TNorm>;
1410 
1411   Storage       Buffer;
1412   IO           &io;
1413   TNorm        *BufPtr = nullptr;
1414   TFinal       &Result;
1415 };
1416 
1417 ///
1418 /// The Input class is used to parse a yaml document into in-memory structs
1419 /// and vectors.
1420 ///
1421 /// It works by using YAMLParser to do a syntax parse of the entire yaml
1422 /// document, then the Input class builds a graph of HNodes which wraps
1423 /// each yaml Node.  The extra layer is buffering.  The low level yaml
1424 /// parser only lets you look at each node once.  The buffering layer lets
1425 /// you search and interate multiple times.  This is necessary because
1426 /// the mapRequired() method calls may not be in the same order
1427 /// as the keys in the document.
1428 ///
1429 class Input : public IO {
1430 public:
1431   // Construct a yaml Input object from a StringRef and optional
1432   // user-data. The DiagHandler can be specified to provide
1433   // alternative error reporting.
1434   Input(StringRef InputContent,
1435         void *Ctxt = nullptr,
1436         SourceMgr::DiagHandlerTy DiagHandler = nullptr,
1437         void *DiagHandlerCtxt = nullptr);
1438   Input(MemoryBufferRef Input,
1439         void *Ctxt = nullptr,
1440         SourceMgr::DiagHandlerTy DiagHandler = nullptr,
1441         void *DiagHandlerCtxt = nullptr);
1442   ~Input() override;
1443 
1444   // Check if there was an syntax or semantic error during parsing.
1445   std::error_code error();
1446 
1447 private:
1448   bool outputting() const override;
1449   bool mapTag(StringRef, bool) override;
1450   void beginMapping() override;
1451   void endMapping() override;
1452   bool preflightKey(const char *, bool, bool, bool &, void *&) override;
1453   void postflightKey(void *) override;
1454   std::vector<StringRef> keys() override;
1455   void beginFlowMapping() override;
1456   void endFlowMapping() override;
1457   unsigned beginSequence() override;
1458   void endSequence() override;
1459   bool preflightElement(unsigned index, void *&) override;
1460   void postflightElement(void *) override;
1461   unsigned beginFlowSequence() override;
1462   bool preflightFlowElement(unsigned , void *&) override;
1463   void postflightFlowElement(void *) override;
1464   void endFlowSequence() override;
1465   void beginEnumScalar() override;
1466   bool matchEnumScalar(const char*, bool) override;
1467   bool matchEnumFallback() override;
1468   void endEnumScalar() override;
1469   bool beginBitSetScalar(bool &) override;
1470   bool bitSetMatch(const char *, bool ) override;
1471   void endBitSetScalar() override;
1472   void scalarString(StringRef &, QuotingType) override;
1473   void blockScalarString(StringRef &) override;
1474   void scalarTag(std::string &) override;
1475   NodeKind getNodeKind() override;
1476   void setError(const Twine &message) override;
1477   bool canElideEmptySequence() override;
1478 
1479   class HNode {
1480   public:
1481     HNode(Node *n) : _node(n) {}
1482 
1483     static bool classof(const HNode *) { return true; }
1484 
1485     Node *_node;
1486   };
1487 
1488   class EmptyHNode : public HNode {
1489   public:
1490     EmptyHNode(Node *n) : HNode(n) { }
1491 
1492     static bool classof(const HNode *n) { return NullNode::classof(n->_node); }
1493 
1494     static bool classof(const EmptyHNode *) { return true; }
1495   };
1496 
1497   class ScalarHNode : public HNode {
1498   public:
1499     ScalarHNode(Node *n, StringRef s) : HNode(n), _value(s) { }
1500 
1501     StringRef value() const { return _value; }
1502 
1503     static bool classof(const HNode *n) {
1504       return ScalarNode::classof(n->_node) ||
1505              BlockScalarNode::classof(n->_node);
1506     }
1507 
1508     static bool classof(const ScalarHNode *) { return true; }
1509 
1510   protected:
1511     StringRef _value;
1512   };
1513 
1514   class MapHNode : public HNode {
1515   public:
1516     MapHNode(Node *n) : HNode(n) { }
1517 
1518     static bool classof(const HNode *n) {
1519       return MappingNode::classof(n->_node);
1520     }
1521 
1522     static bool classof(const MapHNode *) { return true; }
1523 
1524     using NameToNodeAndLoc = StringMap<std::pair<HNode *, SMRange>>;
1525 
1526     NameToNodeAndLoc Mapping;
1527     SmallVector<std::string, 6> ValidKeys;
1528   };
1529 
1530   class SequenceHNode : public HNode {
1531   public:
1532     SequenceHNode(Node *n) : HNode(n) { }
1533 
1534     static bool classof(const HNode *n) {
1535       return SequenceNode::classof(n->_node);
1536     }
1537 
1538     static bool classof(const SequenceHNode *) { return true; }
1539 
1540     std::vector<HNode *> Entries;
1541   };
1542 
1543   Input::HNode *createHNodes(Node *node);
1544   void setError(HNode *hnode, const Twine &message);
1545   void setError(Node *node, const Twine &message);
1546   void setError(const SMRange &Range, const Twine &message);
1547 
1548   void reportWarning(HNode *hnode, const Twine &message);
1549   void reportWarning(Node *hnode, const Twine &message);
1550   void reportWarning(const SMRange &Range, const Twine &message);
1551 
1552   /// Release memory used by HNodes.
1553   void releaseHNodeBuffers();
1554 
1555 public:
1556   // These are only used by operator>>. They could be private
1557   // if those templated things could be made friends.
1558   bool setCurrentDocument();
1559   bool nextDocument();
1560 
1561   /// Returns the current node that's being parsed by the YAML Parser.
1562   const Node *getCurrentNode() const;
1563 
1564   void setAllowUnknownKeys(bool Allow) override;
1565 
1566 private:
1567   SourceMgr                           SrcMgr; // must be before Strm
1568   std::unique_ptr<llvm::yaml::Stream> Strm;
1569   HNode *TopNode = nullptr;
1570   std::error_code                     EC;
1571   BumpPtrAllocator                    StringAllocator;
1572   SpecificBumpPtrAllocator<EmptyHNode> EmptyHNodeAllocator;
1573   SpecificBumpPtrAllocator<ScalarHNode> ScalarHNodeAllocator;
1574   SpecificBumpPtrAllocator<MapHNode> MapHNodeAllocator;
1575   SpecificBumpPtrAllocator<SequenceHNode> SequenceHNodeAllocator;
1576   document_iterator                   DocIterator;
1577   llvm::BitVector                     BitValuesUsed;
1578   HNode *CurrentNode = nullptr;
1579   bool                                ScalarMatchFound = false;
1580   bool AllowUnknownKeys = false;
1581 };
1582 
1583 ///
1584 /// The Output class is used to generate a yaml document from in-memory structs
1585 /// and vectors.
1586 ///
1587 class Output : public IO {
1588 public:
1589   Output(raw_ostream &, void *Ctxt = nullptr, int WrapColumn = 70);
1590   ~Output() override;
1591 
1592   /// Set whether or not to output optional values which are equal
1593   /// to the default value.  By default, when outputting if you attempt
1594   /// to write a value that is equal to the default, the value gets ignored.
1595   /// Sometimes, it is useful to be able to see these in the resulting YAML
1596   /// anyway.
1597   void setWriteDefaultValues(bool Write) { WriteDefaultValues = Write; }
1598 
1599   bool outputting() const override;
1600   bool mapTag(StringRef, bool) override;
1601   void beginMapping() override;
1602   void endMapping() override;
1603   bool preflightKey(const char *key, bool, bool, bool &, void *&) override;
1604   void postflightKey(void *) override;
1605   std::vector<StringRef> keys() override;
1606   void beginFlowMapping() override;
1607   void endFlowMapping() override;
1608   unsigned beginSequence() override;
1609   void endSequence() override;
1610   bool preflightElement(unsigned, void *&) override;
1611   void postflightElement(void *) override;
1612   unsigned beginFlowSequence() override;
1613   bool preflightFlowElement(unsigned, void *&) override;
1614   void postflightFlowElement(void *) override;
1615   void endFlowSequence() override;
1616   void beginEnumScalar() override;
1617   bool matchEnumScalar(const char*, bool) override;
1618   bool matchEnumFallback() override;
1619   void endEnumScalar() override;
1620   bool beginBitSetScalar(bool &) override;
1621   bool bitSetMatch(const char *, bool ) override;
1622   void endBitSetScalar() override;
1623   void scalarString(StringRef &, QuotingType) override;
1624   void blockScalarString(StringRef &) override;
1625   void scalarTag(std::string &) override;
1626   NodeKind getNodeKind() override;
1627   void setError(const Twine &message) override;
1628   bool canElideEmptySequence() override;
1629 
1630   // These are only used by operator<<. They could be private
1631   // if that templated operator could be made a friend.
1632   void beginDocuments();
1633   bool preflightDocument(unsigned);
1634   void postflightDocument();
1635   void endDocuments();
1636 
1637 private:
1638   void output(StringRef s);
1639   void outputUpToEndOfLine(StringRef s);
1640   void newLineCheck(bool EmptySequence = false);
1641   void outputNewLine();
1642   void paddedKey(StringRef key);
1643   void flowKey(StringRef Key);
1644 
1645   enum InState {
1646     inSeqFirstElement,
1647     inSeqOtherElement,
1648     inFlowSeqFirstElement,
1649     inFlowSeqOtherElement,
1650     inMapFirstKey,
1651     inMapOtherKey,
1652     inFlowMapFirstKey,
1653     inFlowMapOtherKey
1654   };
1655 
1656   static bool inSeqAnyElement(InState State);
1657   static bool inFlowSeqAnyElement(InState State);
1658   static bool inMapAnyKey(InState State);
1659   static bool inFlowMapAnyKey(InState State);
1660 
1661   raw_ostream &Out;
1662   int WrapColumn;
1663   SmallVector<InState, 8> StateStack;
1664   int Column = 0;
1665   int ColumnAtFlowStart = 0;
1666   int ColumnAtMapFlowStart = 0;
1667   bool NeedBitValueComma = false;
1668   bool NeedFlowSequenceComma = false;
1669   bool EnumerationMatchFound = false;
1670   bool WriteDefaultValues = false;
1671   StringRef Padding;
1672   StringRef PaddingBeforeContainer;
1673 };
1674 
1675 template <typename T, typename Context>
1676 void IO::processKeyWithDefault(const char *Key, std::optional<T> &Val,
1677                                const std::optional<T> &DefaultValue,
1678                                bool Required, Context &Ctx) {
1679   assert(!DefaultValue && "std::optional<T> shouldn't have a value!");
1680   void *SaveInfo;
1681   bool UseDefault = true;
1682   const bool sameAsDefault = outputting() && !Val;
1683   if (!outputting() && !Val)
1684     Val = T();
1685   if (Val &&
1686       this->preflightKey(Key, Required, sameAsDefault, UseDefault, SaveInfo)) {
1687 
1688     // When reading an std::optional<X> key from a YAML description, we allow
1689     // the special "<none>" value, which can be used to specify that no value
1690     // was requested, i.e. the DefaultValue will be assigned. The DefaultValue
1691     // is usually None.
1692     bool IsNone = false;
1693     if (!outputting())
1694       if (const auto *Node =
1695               dyn_cast<ScalarNode>(((Input *)this)->getCurrentNode()))
1696         // We use rtrim to ignore possible white spaces that might exist when a
1697         // comment is present on the same line.
1698         IsNone = Node->getRawValue().rtrim(' ') == "<none>";
1699 
1700     if (IsNone)
1701       Val = DefaultValue;
1702     else
1703       yamlize(*this, *Val, Required, Ctx);
1704     this->postflightKey(SaveInfo);
1705   } else {
1706     if (UseDefault)
1707       Val = DefaultValue;
1708   }
1709 }
1710 
1711 /// YAML I/O does conversion based on types. But often native data types
1712 /// are just a typedef of built in intergral types (e.g. int).  But the C++
1713 /// type matching system sees through the typedef and all the typedefed types
1714 /// look like a built in type. This will cause the generic YAML I/O conversion
1715 /// to be used. To provide better control over the YAML conversion, you can
1716 /// use this macro instead of typedef.  It will create a class with one field
1717 /// and automatic conversion operators to and from the base type.
1718 /// Based on BOOST_STRONG_TYPEDEF
1719 #define LLVM_YAML_STRONG_TYPEDEF(_base, _type)                                 \
1720     struct _type {                                                             \
1721         _type() = default;                                                     \
1722         _type(const _base v) : value(v) {}                                     \
1723         _type(const _type &v) = default;                                       \
1724         _type &operator=(const _type &rhs) = default;                          \
1725         _type &operator=(const _base &rhs) { value = rhs; return *this; }      \
1726         operator const _base & () const { return value; }                      \
1727         bool operator==(const _type &rhs) const { return value == rhs.value; } \
1728         bool operator==(const _base &rhs) const { return value == rhs; }       \
1729         bool operator<(const _type &rhs) const { return value < rhs.value; }   \
1730         _base value;                                                           \
1731         using BaseType = _base;                                                \
1732     };
1733 
1734 ///
1735 /// Use these types instead of uintXX_t in any mapping to have
1736 /// its yaml output formatted as hexadecimal.
1737 ///
1738 LLVM_YAML_STRONG_TYPEDEF(uint8_t, Hex8)
1739 LLVM_YAML_STRONG_TYPEDEF(uint16_t, Hex16)
1740 LLVM_YAML_STRONG_TYPEDEF(uint32_t, Hex32)
1741 LLVM_YAML_STRONG_TYPEDEF(uint64_t, Hex64)
1742 
1743 template<>
1744 struct ScalarTraits<Hex8> {
1745   static void output(const Hex8 &, void *, raw_ostream &);
1746   static StringRef input(StringRef, void *, Hex8 &);
1747   static QuotingType mustQuote(StringRef) { return QuotingType::None; }
1748 };
1749 
1750 template<>
1751 struct ScalarTraits<Hex16> {
1752   static void output(const Hex16 &, void *, raw_ostream &);
1753   static StringRef input(StringRef, void *, Hex16 &);
1754   static QuotingType mustQuote(StringRef) { return QuotingType::None; }
1755 };
1756 
1757 template<>
1758 struct ScalarTraits<Hex32> {
1759   static void output(const Hex32 &, void *, raw_ostream &);
1760   static StringRef input(StringRef, void *, Hex32 &);
1761   static QuotingType mustQuote(StringRef) { return QuotingType::None; }
1762 };
1763 
1764 template<>
1765 struct ScalarTraits<Hex64> {
1766   static void output(const Hex64 &, void *, raw_ostream &);
1767   static StringRef input(StringRef, void *, Hex64 &);
1768   static QuotingType mustQuote(StringRef) { return QuotingType::None; }
1769 };
1770 
1771 template <> struct ScalarTraits<VersionTuple> {
1772   static void output(const VersionTuple &Value, void *, llvm::raw_ostream &Out);
1773   static StringRef input(StringRef, void *, VersionTuple &);
1774   static QuotingType mustQuote(StringRef) { return QuotingType::None; }
1775 };
1776 
1777 // Define non-member operator>> so that Input can stream in a document list.
1778 template <typename T>
1779 inline std::enable_if_t<has_DocumentListTraits<T>::value, Input &>
1780 operator>>(Input &yin, T &docList) {
1781   int i = 0;
1782   EmptyContext Ctx;
1783   while ( yin.setCurrentDocument() ) {
1784     yamlize(yin, DocumentListTraits<T>::element(yin, docList, i), true, Ctx);
1785     if ( yin.error() )
1786       return yin;
1787     yin.nextDocument();
1788     ++i;
1789   }
1790   return yin;
1791 }
1792 
1793 // Define non-member operator>> so that Input can stream in a map as a document.
1794 template <typename T>
1795 inline std::enable_if_t<has_MappingTraits<T, EmptyContext>::value, Input &>
1796 operator>>(Input &yin, T &docMap) {
1797   EmptyContext Ctx;
1798   yin.setCurrentDocument();
1799   yamlize(yin, docMap, true, Ctx);
1800   return yin;
1801 }
1802 
1803 // Define non-member operator>> so that Input can stream in a sequence as
1804 // a document.
1805 template <typename T>
1806 inline std::enable_if_t<has_SequenceTraits<T>::value, Input &>
1807 operator>>(Input &yin, T &docSeq) {
1808   EmptyContext Ctx;
1809   if (yin.setCurrentDocument())
1810     yamlize(yin, docSeq, true, Ctx);
1811   return yin;
1812 }
1813 
1814 // Define non-member operator>> so that Input can stream in a block scalar.
1815 template <typename T>
1816 inline std::enable_if_t<has_BlockScalarTraits<T>::value, Input &>
1817 operator>>(Input &In, T &Val) {
1818   EmptyContext Ctx;
1819   if (In.setCurrentDocument())
1820     yamlize(In, Val, true, Ctx);
1821   return In;
1822 }
1823 
1824 // Define non-member operator>> so that Input can stream in a string map.
1825 template <typename T>
1826 inline std::enable_if_t<has_CustomMappingTraits<T>::value, Input &>
1827 operator>>(Input &In, T &Val) {
1828   EmptyContext Ctx;
1829   if (In.setCurrentDocument())
1830     yamlize(In, Val, true, Ctx);
1831   return In;
1832 }
1833 
1834 // Define non-member operator>> so that Input can stream in a polymorphic type.
1835 template <typename T>
1836 inline std::enable_if_t<has_PolymorphicTraits<T>::value, Input &>
1837 operator>>(Input &In, T &Val) {
1838   EmptyContext Ctx;
1839   if (In.setCurrentDocument())
1840     yamlize(In, Val, true, Ctx);
1841   return In;
1842 }
1843 
1844 // Provide better error message about types missing a trait specialization
1845 template <typename T>
1846 inline std::enable_if_t<missingTraits<T, EmptyContext>::value, Input &>
1847 operator>>(Input &yin, T &docSeq) {
1848   char missing_yaml_trait_for_type[sizeof(MissingTrait<T>)];
1849   return yin;
1850 }
1851 
1852 // Define non-member operator<< so that Output can stream out document list.
1853 template <typename T>
1854 inline std::enable_if_t<has_DocumentListTraits<T>::value, Output &>
1855 operator<<(Output &yout, T &docList) {
1856   EmptyContext Ctx;
1857   yout.beginDocuments();
1858   const size_t count = DocumentListTraits<T>::size(yout, docList);
1859   for(size_t i=0; i < count; ++i) {
1860     if ( yout.preflightDocument(i) ) {
1861       yamlize(yout, DocumentListTraits<T>::element(yout, docList, i), true,
1862               Ctx);
1863       yout.postflightDocument();
1864     }
1865   }
1866   yout.endDocuments();
1867   return yout;
1868 }
1869 
1870 // Define non-member operator<< so that Output can stream out a map.
1871 template <typename T>
1872 inline std::enable_if_t<has_MappingTraits<T, EmptyContext>::value, Output &>
1873 operator<<(Output &yout, T &map) {
1874   EmptyContext Ctx;
1875   yout.beginDocuments();
1876   if ( yout.preflightDocument(0) ) {
1877     yamlize(yout, map, true, Ctx);
1878     yout.postflightDocument();
1879   }
1880   yout.endDocuments();
1881   return yout;
1882 }
1883 
1884 // Define non-member operator<< so that Output can stream out a sequence.
1885 template <typename T>
1886 inline std::enable_if_t<has_SequenceTraits<T>::value, Output &>
1887 operator<<(Output &yout, T &seq) {
1888   EmptyContext Ctx;
1889   yout.beginDocuments();
1890   if ( yout.preflightDocument(0) ) {
1891     yamlize(yout, seq, true, Ctx);
1892     yout.postflightDocument();
1893   }
1894   yout.endDocuments();
1895   return yout;
1896 }
1897 
1898 // Define non-member operator<< so that Output can stream out a block scalar.
1899 template <typename T>
1900 inline std::enable_if_t<has_BlockScalarTraits<T>::value, Output &>
1901 operator<<(Output &Out, T &Val) {
1902   EmptyContext Ctx;
1903   Out.beginDocuments();
1904   if (Out.preflightDocument(0)) {
1905     yamlize(Out, Val, true, Ctx);
1906     Out.postflightDocument();
1907   }
1908   Out.endDocuments();
1909   return Out;
1910 }
1911 
1912 // Define non-member operator<< so that Output can stream out a string map.
1913 template <typename T>
1914 inline std::enable_if_t<has_CustomMappingTraits<T>::value, Output &>
1915 operator<<(Output &Out, T &Val) {
1916   EmptyContext Ctx;
1917   Out.beginDocuments();
1918   if (Out.preflightDocument(0)) {
1919     yamlize(Out, Val, true, Ctx);
1920     Out.postflightDocument();
1921   }
1922   Out.endDocuments();
1923   return Out;
1924 }
1925 
1926 // Define non-member operator<< so that Output can stream out a polymorphic
1927 // type.
1928 template <typename T>
1929 inline std::enable_if_t<has_PolymorphicTraits<T>::value, Output &>
1930 operator<<(Output &Out, T &Val) {
1931   EmptyContext Ctx;
1932   Out.beginDocuments();
1933   if (Out.preflightDocument(0)) {
1934     // FIXME: The parser does not support explicit documents terminated with a
1935     // plain scalar; the end-marker is included as part of the scalar token.
1936     assert(PolymorphicTraits<T>::getKind(Val) != NodeKind::Scalar && "plain scalar documents are not supported");
1937     yamlize(Out, Val, true, Ctx);
1938     Out.postflightDocument();
1939   }
1940   Out.endDocuments();
1941   return Out;
1942 }
1943 
1944 // Provide better error message about types missing a trait specialization
1945 template <typename T>
1946 inline std::enable_if_t<missingTraits<T, EmptyContext>::value, Output &>
1947 operator<<(Output &yout, T &seq) {
1948   char missing_yaml_trait_for_type[sizeof(MissingTrait<T>)];
1949   return yout;
1950 }
1951 
1952 template <bool B> struct IsFlowSequenceBase {};
1953 template <> struct IsFlowSequenceBase<true> { static const bool flow = true; };
1954 
1955 template <typename T, typename U = void>
1956 struct IsResizable : std::false_type {};
1957 
1958 template <typename T>
1959 struct IsResizable<T, std::void_t<decltype(std::declval<T>().resize(0))>>
1960     : public std::true_type {};
1961 
1962 template <typename T, bool B> struct IsResizableBase {
1963   using type = typename T::value_type;
1964 
1965   static type &element(IO &io, T &seq, size_t index) {
1966     if (index >= seq.size())
1967       seq.resize(index + 1);
1968     return seq[index];
1969   }
1970 };
1971 
1972 template <typename T> struct IsResizableBase<T, false> {
1973   using type = typename T::value_type;
1974 
1975   static type &element(IO &io, T &seq, size_t index) {
1976     if (index >= seq.size()) {
1977       io.setError(Twine("value sequence extends beyond static size (") +
1978                   Twine(seq.size()) + ")");
1979       return seq[0];
1980     }
1981     return seq[index];
1982   }
1983 };
1984 
1985 template <typename T, bool Flow>
1986 struct SequenceTraitsImpl
1987     : IsFlowSequenceBase<Flow>, IsResizableBase<T, IsResizable<T>::value> {
1988   static size_t size(IO &io, T &seq) { return seq.size(); }
1989 };
1990 
1991 // Simple helper to check an expression can be used as a bool-valued template
1992 // argument.
1993 template <bool> struct CheckIsBool { static const bool value = true; };
1994 
1995 // If T has SequenceElementTraits, then vector<T> and SmallVector<T, N> have
1996 // SequenceTraits that do the obvious thing.
1997 template <typename T>
1998 struct SequenceTraits<
1999     std::vector<T>,
2000     std::enable_if_t<CheckIsBool<SequenceElementTraits<T>::flow>::value>>
2001     : SequenceTraitsImpl<std::vector<T>, SequenceElementTraits<T>::flow> {};
2002 template <typename T, unsigned N>
2003 struct SequenceTraits<
2004     SmallVector<T, N>,
2005     std::enable_if_t<CheckIsBool<SequenceElementTraits<T>::flow>::value>>
2006     : SequenceTraitsImpl<SmallVector<T, N>, SequenceElementTraits<T>::flow> {};
2007 template <typename T>
2008 struct SequenceTraits<
2009     SmallVectorImpl<T>,
2010     std::enable_if_t<CheckIsBool<SequenceElementTraits<T>::flow>::value>>
2011     : SequenceTraitsImpl<SmallVectorImpl<T>, SequenceElementTraits<T>::flow> {};
2012 template <typename T>
2013 struct SequenceTraits<
2014     MutableArrayRef<T>,
2015     std::enable_if_t<CheckIsBool<SequenceElementTraits<T>::flow>::value>>
2016     : SequenceTraitsImpl<MutableArrayRef<T>, SequenceElementTraits<T>::flow> {};
2017 
2018 // Sequences of fundamental types use flow formatting.
2019 template <typename T>
2020 struct SequenceElementTraits<T, std::enable_if_t<std::is_fundamental_v<T>>> {
2021   static const bool flow = true;
2022 };
2023 
2024 // Sequences of strings use block formatting.
2025 template<> struct SequenceElementTraits<std::string> {
2026   static const bool flow = false;
2027 };
2028 template<> struct SequenceElementTraits<StringRef> {
2029   static const bool flow = false;
2030 };
2031 template<> struct SequenceElementTraits<std::pair<std::string, std::string>> {
2032   static const bool flow = false;
2033 };
2034 
2035 /// Implementation of CustomMappingTraits for std::map<std::string, T>.
2036 template <typename T> struct StdMapStringCustomMappingTraitsImpl {
2037   using map_type = std::map<std::string, T>;
2038 
2039   static void inputOne(IO &io, StringRef key, map_type &v) {
2040     io.mapRequired(key.str().c_str(), v[std::string(key)]);
2041   }
2042 
2043   static void output(IO &io, map_type &v) {
2044     for (auto &p : v)
2045       io.mapRequired(p.first.c_str(), p.second);
2046   }
2047 };
2048 
2049 } // end namespace yaml
2050 } // end namespace llvm
2051 
2052 #define LLVM_YAML_IS_SEQUENCE_VECTOR_IMPL(TYPE, FLOW)                          \
2053   namespace llvm {                                                             \
2054   namespace yaml {                                                             \
2055   static_assert(                                                               \
2056       !std::is_fundamental_v<TYPE> && !std::is_same_v<TYPE, std::string> &&    \
2057           !std::is_same_v<TYPE, llvm::StringRef>,                              \
2058       "only use LLVM_YAML_IS_SEQUENCE_VECTOR for types you control");          \
2059   template <> struct SequenceElementTraits<TYPE> {                             \
2060     static const bool flow = FLOW;                                             \
2061   };                                                                           \
2062   }                                                                            \
2063   }
2064 
2065 /// Utility for declaring that a std::vector of a particular type
2066 /// should be considered a YAML sequence.
2067 #define LLVM_YAML_IS_SEQUENCE_VECTOR(type)                                     \
2068   LLVM_YAML_IS_SEQUENCE_VECTOR_IMPL(type, false)
2069 
2070 /// Utility for declaring that a std::vector of a particular type
2071 /// should be considered a YAML flow sequence.
2072 #define LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(type)                                \
2073   LLVM_YAML_IS_SEQUENCE_VECTOR_IMPL(type, true)
2074 
2075 #define LLVM_YAML_DECLARE_MAPPING_TRAITS(Type)                                 \
2076   namespace llvm {                                                             \
2077   namespace yaml {                                                             \
2078   template <> struct MappingTraits<Type> {                                     \
2079     static void mapping(IO &IO, Type &Obj);                                    \
2080   };                                                                           \
2081   }                                                                            \
2082   }
2083 
2084 #define LLVM_YAML_DECLARE_ENUM_TRAITS(Type)                                    \
2085   namespace llvm {                                                             \
2086   namespace yaml {                                                             \
2087   template <> struct ScalarEnumerationTraits<Type> {                           \
2088     static void enumeration(IO &io, Type &Value);                              \
2089   };                                                                           \
2090   }                                                                            \
2091   }
2092 
2093 #define LLVM_YAML_DECLARE_BITSET_TRAITS(Type)                                  \
2094   namespace llvm {                                                             \
2095   namespace yaml {                                                             \
2096   template <> struct ScalarBitSetTraits<Type> {                                \
2097     static void bitset(IO &IO, Type &Options);                                 \
2098   };                                                                           \
2099   }                                                                            \
2100   }
2101 
2102 #define LLVM_YAML_DECLARE_SCALAR_TRAITS(Type, MustQuote)                       \
2103   namespace llvm {                                                             \
2104   namespace yaml {                                                             \
2105   template <> struct ScalarTraits<Type> {                                      \
2106     static void output(const Type &Value, void *ctx, raw_ostream &Out);        \
2107     static StringRef input(StringRef Scalar, void *ctxt, Type &Value);         \
2108     static QuotingType mustQuote(StringRef) { return MustQuote; }              \
2109   };                                                                           \
2110   }                                                                            \
2111   }
2112 
2113 /// Utility for declaring that a std::vector of a particular type
2114 /// should be considered a YAML document list.
2115 #define LLVM_YAML_IS_DOCUMENT_LIST_VECTOR(_type)                               \
2116   namespace llvm {                                                             \
2117   namespace yaml {                                                             \
2118   template <unsigned N>                                                        \
2119   struct DocumentListTraits<SmallVector<_type, N>>                             \
2120       : public SequenceTraitsImpl<SmallVector<_type, N>, false> {};            \
2121   template <>                                                                  \
2122   struct DocumentListTraits<std::vector<_type>>                                \
2123       : public SequenceTraitsImpl<std::vector<_type>, false> {};               \
2124   }                                                                            \
2125   }
2126 
2127 /// Utility for declaring that std::map<std::string, _type> should be considered
2128 /// a YAML map.
2129 #define LLVM_YAML_IS_STRING_MAP(_type)                                         \
2130   namespace llvm {                                                             \
2131   namespace yaml {                                                             \
2132   template <>                                                                  \
2133   struct CustomMappingTraits<std::map<std::string, _type>>                     \
2134       : public StdMapStringCustomMappingTraitsImpl<_type> {};                  \
2135   }                                                                            \
2136   }
2137 
2138 LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(llvm::yaml::Hex64)
2139 LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(llvm::yaml::Hex32)
2140 LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(llvm::yaml::Hex16)
2141 LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(llvm::yaml::Hex8)
2142 
2143 #endif // LLVM_SUPPORT_YAMLTRAITS_H
2144