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