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