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