]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/include/llvm/Support/YAMLTraits.h
Merge clang 7.0.1 and several follow-up changes
[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 (isNull(S))
515     return QuotingType::Single;
516   if (isBool(S))
517     return QuotingType::Single;
518   if (isNumeric(S))
519     return QuotingType::Single;
520
521   // 7.3.3 Plain Style
522   // Plain scalars must not begin with most indicators, as this would cause
523   // ambiguity with other YAML constructs.
524   static constexpr char Indicators[] = R"(-?:\,[]{}#&*!|>'"%@`)";
525   if (S.find_first_of(Indicators) == 0)
526     return QuotingType::Single;
527
528   QuotingType MaxQuotingNeeded = QuotingType::None;
529   for (unsigned char C : S) {
530     // Alphanum is safe.
531     if (isAlnum(C))
532       continue;
533
534     switch (C) {
535     // Safe scalar characters.
536     case '_':
537     case '-':
538     case '/':
539     case '^':
540     case '.':
541     case ',':
542     case ' ':
543     // TAB (0x9) is allowed in unquoted strings.
544     case 0x9:
545       continue;
546     // LF(0xA) and CR(0xD) may delimit values and so require at least single
547     // quotes.
548     case 0xA:
549     case 0xD:
550       MaxQuotingNeeded = QuotingType::Single;
551       continue;
552     // DEL (0x7F) are excluded from the allowed character range.
553     case 0x7F:
554       return QuotingType::Double;
555     default: {
556       // C0 control block (0x0 - 0x1F) is excluded from the allowed character
557       // range.
558       if (C <= 0x1F)
559         return QuotingType::Double;
560
561       // Always double quote UTF-8.
562       if ((C & 0x80) != 0)
563         return QuotingType::Double;
564
565       // The character is not safe, at least simple quoting needed.
566       MaxQuotingNeeded = QuotingType::Single;
567     }
568     }
569   }
570
571   return MaxQuotingNeeded;
572 }
573
574 template <typename T, typename Context>
575 struct missingTraits
576     : public std::integral_constant<bool,
577                                     !has_ScalarEnumerationTraits<T>::value &&
578                                         !has_ScalarBitSetTraits<T>::value &&
579                                         !has_ScalarTraits<T>::value &&
580                                         !has_BlockScalarTraits<T>::value &&
581                                         !has_MappingTraits<T, Context>::value &&
582                                         !has_SequenceTraits<T>::value &&
583                                         !has_CustomMappingTraits<T>::value &&
584                                         !has_DocumentListTraits<T>::value> {};
585
586 template <typename T, typename Context>
587 struct validatedMappingTraits
588     : public std::integral_constant<
589           bool, has_MappingTraits<T, Context>::value &&
590                     has_MappingValidateTraits<T, Context>::value> {};
591
592 template <typename T, typename Context>
593 struct unvalidatedMappingTraits
594     : public std::integral_constant<
595           bool, has_MappingTraits<T, Context>::value &&
596                     !has_MappingValidateTraits<T, Context>::value> {};
597
598 // Base class for Input and Output.
599 class IO {
600 public:
601   IO(void *Ctxt = nullptr);
602   virtual ~IO();
603
604   virtual bool outputting() = 0;
605
606   virtual unsigned beginSequence() = 0;
607   virtual bool preflightElement(unsigned, void *&) = 0;
608   virtual void postflightElement(void*) = 0;
609   virtual void endSequence() = 0;
610   virtual bool canElideEmptySequence() = 0;
611
612   virtual unsigned beginFlowSequence() = 0;
613   virtual bool preflightFlowElement(unsigned, void *&) = 0;
614   virtual void postflightFlowElement(void*) = 0;
615   virtual void endFlowSequence() = 0;
616
617   virtual bool mapTag(StringRef Tag, bool Default=false) = 0;
618   virtual void beginMapping() = 0;
619   virtual void endMapping() = 0;
620   virtual bool preflightKey(const char*, bool, bool, bool &, void *&) = 0;
621   virtual void postflightKey(void*) = 0;
622   virtual std::vector<StringRef> keys() = 0;
623
624   virtual void beginFlowMapping() = 0;
625   virtual void endFlowMapping() = 0;
626
627   virtual void beginEnumScalar() = 0;
628   virtual bool matchEnumScalar(const char*, bool) = 0;
629   virtual bool matchEnumFallback() = 0;
630   virtual void endEnumScalar() = 0;
631
632   virtual bool beginBitSetScalar(bool &) = 0;
633   virtual bool bitSetMatch(const char*, bool) = 0;
634   virtual void endBitSetScalar() = 0;
635
636   virtual void scalarString(StringRef &, QuotingType) = 0;
637   virtual void blockScalarString(StringRef &) = 0;
638
639   virtual void setError(const Twine &) = 0;
640
641   template <typename T>
642   void enumCase(T &Val, const char* Str, const T ConstVal) {
643     if ( matchEnumScalar(Str, outputting() && Val == ConstVal) ) {
644       Val = ConstVal;
645     }
646   }
647
648   // allow anonymous enum values to be used with LLVM_YAML_STRONG_TYPEDEF
649   template <typename T>
650   void enumCase(T &Val, const char* Str, const uint32_t ConstVal) {
651     if ( matchEnumScalar(Str, outputting() && Val == static_cast<T>(ConstVal)) ) {
652       Val = ConstVal;
653     }
654   }
655
656   template <typename FBT, typename T>
657   void enumFallback(T &Val) {
658     if (matchEnumFallback()) {
659       EmptyContext Context;
660       // FIXME: Force integral conversion to allow strong typedefs to convert.
661       FBT Res = static_cast<typename FBT::BaseType>(Val);
662       yamlize(*this, Res, true, Context);
663       Val = static_cast<T>(static_cast<typename FBT::BaseType>(Res));
664     }
665   }
666
667   template <typename T>
668   void bitSetCase(T &Val, const char* Str, const T ConstVal) {
669     if ( bitSetMatch(Str, outputting() && (Val & ConstVal) == ConstVal) ) {
670       Val = static_cast<T>(Val | ConstVal);
671     }
672   }
673
674   // allow anonymous enum values to be used with LLVM_YAML_STRONG_TYPEDEF
675   template <typename T>
676   void bitSetCase(T &Val, const char* Str, const uint32_t ConstVal) {
677     if ( bitSetMatch(Str, outputting() && (Val & ConstVal) == ConstVal) ) {
678       Val = static_cast<T>(Val | ConstVal);
679     }
680   }
681
682   template <typename T>
683   void maskedBitSetCase(T &Val, const char *Str, T ConstVal, T Mask) {
684     if (bitSetMatch(Str, outputting() && (Val & Mask) == ConstVal))
685       Val = Val | ConstVal;
686   }
687
688   template <typename T>
689   void maskedBitSetCase(T &Val, const char *Str, uint32_t ConstVal,
690                         uint32_t Mask) {
691     if (bitSetMatch(Str, outputting() && (Val & Mask) == ConstVal))
692       Val = Val | ConstVal;
693   }
694
695   void *getContext();
696   void setContext(void *);
697
698   template <typename T> void mapRequired(const char *Key, T &Val) {
699     EmptyContext Ctx;
700     this->processKey(Key, Val, true, Ctx);
701   }
702
703   template <typename T, typename Context>
704   void mapRequired(const char *Key, T &Val, Context &Ctx) {
705     this->processKey(Key, Val, true, Ctx);
706   }
707
708   template <typename T> void mapOptional(const char *Key, T &Val) {
709     EmptyContext Ctx;
710     mapOptionalWithContext(Key, Val, Ctx);
711   }
712
713   template <typename T>
714   void mapOptional(const char *Key, T &Val, const T &Default) {
715     EmptyContext Ctx;
716     mapOptionalWithContext(Key, Val, Default, Ctx);
717   }
718
719   template <typename T, typename Context>
720   typename std::enable_if<has_SequenceTraits<T>::value, void>::type
721   mapOptionalWithContext(const char *Key, T &Val, Context &Ctx) {
722     // omit key/value instead of outputting empty sequence
723     if (this->canElideEmptySequence() && !(Val.begin() != Val.end()))
724       return;
725     this->processKey(Key, Val, false, Ctx);
726   }
727
728   template <typename T, typename Context>
729   void mapOptionalWithContext(const char *Key, Optional<T> &Val, Context &Ctx) {
730     this->processKeyWithDefault(Key, Val, Optional<T>(), /*Required=*/false,
731                                 Ctx);
732   }
733
734   template <typename T, typename Context>
735   typename std::enable_if<!has_SequenceTraits<T>::value, void>::type
736   mapOptionalWithContext(const char *Key, T &Val, Context &Ctx) {
737     this->processKey(Key, Val, false, Ctx);
738   }
739
740   template <typename T, typename Context>
741   void mapOptionalWithContext(const char *Key, T &Val, const T &Default,
742                               Context &Ctx) {
743     this->processKeyWithDefault(Key, Val, Default, false, Ctx);
744   }
745
746 private:
747   template <typename T, typename Context>
748   void processKeyWithDefault(const char *Key, Optional<T> &Val,
749                              const Optional<T> &DefaultValue, bool Required,
750                              Context &Ctx) {
751     assert(DefaultValue.hasValue() == false &&
752            "Optional<T> shouldn't have a value!");
753     void *SaveInfo;
754     bool UseDefault = true;
755     const bool sameAsDefault = outputting() && !Val.hasValue();
756     if (!outputting() && !Val.hasValue())
757       Val = T();
758     if (Val.hasValue() &&
759         this->preflightKey(Key, Required, sameAsDefault, UseDefault,
760                            SaveInfo)) {
761       yamlize(*this, Val.getValue(), Required, Ctx);
762       this->postflightKey(SaveInfo);
763     } else {
764       if (UseDefault)
765         Val = DefaultValue;
766     }
767   }
768
769   template <typename T, typename Context>
770   void processKeyWithDefault(const char *Key, T &Val, const T &DefaultValue,
771                              bool Required, Context &Ctx) {
772     void *SaveInfo;
773     bool UseDefault;
774     const bool sameAsDefault = outputting() && Val == DefaultValue;
775     if ( this->preflightKey(Key, Required, sameAsDefault, UseDefault,
776                                                                   SaveInfo) ) {
777       yamlize(*this, Val, Required, Ctx);
778       this->postflightKey(SaveInfo);
779     }
780     else {
781       if ( UseDefault )
782         Val = DefaultValue;
783     }
784   }
785
786   template <typename T, typename Context>
787   void processKey(const char *Key, T &Val, bool Required, Context &Ctx) {
788     void *SaveInfo;
789     bool UseDefault;
790     if ( this->preflightKey(Key, Required, false, UseDefault, SaveInfo) ) {
791       yamlize(*this, Val, Required, Ctx);
792       this->postflightKey(SaveInfo);
793     }
794   }
795
796 private:
797   void *Ctxt;
798 };
799
800 namespace detail {
801
802 template <typename T, typename Context>
803 void doMapping(IO &io, T &Val, Context &Ctx) {
804   MappingContextTraits<T, Context>::mapping(io, Val, Ctx);
805 }
806
807 template <typename T> void doMapping(IO &io, T &Val, EmptyContext &Ctx) {
808   MappingTraits<T>::mapping(io, Val);
809 }
810
811 } // end namespace detail
812
813 template <typename T>
814 typename std::enable_if<has_ScalarEnumerationTraits<T>::value, void>::type
815 yamlize(IO &io, T &Val, bool, EmptyContext &Ctx) {
816   io.beginEnumScalar();
817   ScalarEnumerationTraits<T>::enumeration(io, Val);
818   io.endEnumScalar();
819 }
820
821 template <typename T>
822 typename std::enable_if<has_ScalarBitSetTraits<T>::value, void>::type
823 yamlize(IO &io, T &Val, bool, EmptyContext &Ctx) {
824   bool DoClear;
825   if ( io.beginBitSetScalar(DoClear) ) {
826     if ( DoClear )
827       Val = static_cast<T>(0);
828     ScalarBitSetTraits<T>::bitset(io, Val);
829     io.endBitSetScalar();
830   }
831 }
832
833 template <typename T>
834 typename std::enable_if<has_ScalarTraits<T>::value, void>::type
835 yamlize(IO &io, T &Val, bool, EmptyContext &Ctx) {
836   if ( io.outputting() ) {
837     std::string Storage;
838     raw_string_ostream Buffer(Storage);
839     ScalarTraits<T>::output(Val, io.getContext(), Buffer);
840     StringRef Str = Buffer.str();
841     io.scalarString(Str, ScalarTraits<T>::mustQuote(Str));
842   }
843   else {
844     StringRef Str;
845     io.scalarString(Str, ScalarTraits<T>::mustQuote(Str));
846     StringRef Result = ScalarTraits<T>::input(Str, io.getContext(), Val);
847     if ( !Result.empty() ) {
848       io.setError(Twine(Result));
849     }
850   }
851 }
852
853 template <typename T>
854 typename std::enable_if<has_BlockScalarTraits<T>::value, void>::type
855 yamlize(IO &YamlIO, T &Val, bool, EmptyContext &Ctx) {
856   if (YamlIO.outputting()) {
857     std::string Storage;
858     raw_string_ostream Buffer(Storage);
859     BlockScalarTraits<T>::output(Val, YamlIO.getContext(), Buffer);
860     StringRef Str = Buffer.str();
861     YamlIO.blockScalarString(Str);
862   } else {
863     StringRef Str;
864     YamlIO.blockScalarString(Str);
865     StringRef Result =
866         BlockScalarTraits<T>::input(Str, YamlIO.getContext(), Val);
867     if (!Result.empty())
868       YamlIO.setError(Twine(Result));
869   }
870 }
871
872 template <typename T, typename Context>
873 typename std::enable_if<validatedMappingTraits<T, Context>::value, void>::type
874 yamlize(IO &io, T &Val, bool, Context &Ctx) {
875   if (has_FlowTraits<MappingTraits<T>>::value)
876     io.beginFlowMapping();
877   else
878     io.beginMapping();
879   if (io.outputting()) {
880     StringRef Err = MappingTraits<T>::validate(io, Val);
881     if (!Err.empty()) {
882       errs() << Err << "\n";
883       assert(Err.empty() && "invalid struct trying to be written as yaml");
884     }
885   }
886   detail::doMapping(io, Val, Ctx);
887   if (!io.outputting()) {
888     StringRef Err = MappingTraits<T>::validate(io, Val);
889     if (!Err.empty())
890       io.setError(Err);
891   }
892   if (has_FlowTraits<MappingTraits<T>>::value)
893     io.endFlowMapping();
894   else
895     io.endMapping();
896 }
897
898 template <typename T, typename Context>
899 typename std::enable_if<unvalidatedMappingTraits<T, Context>::value, void>::type
900 yamlize(IO &io, T &Val, bool, Context &Ctx) {
901   if (has_FlowTraits<MappingTraits<T>>::value) {
902     io.beginFlowMapping();
903     detail::doMapping(io, Val, Ctx);
904     io.endFlowMapping();
905   } else {
906     io.beginMapping();
907     detail::doMapping(io, Val, Ctx);
908     io.endMapping();
909   }
910 }
911
912 template <typename T>
913 typename std::enable_if<has_CustomMappingTraits<T>::value, void>::type
914 yamlize(IO &io, T &Val, bool, EmptyContext &Ctx) {
915   if ( io.outputting() ) {
916     io.beginMapping();
917     CustomMappingTraits<T>::output(io, Val);
918     io.endMapping();
919   } else {
920     io.beginMapping();
921     for (StringRef key : io.keys())
922       CustomMappingTraits<T>::inputOne(io, key, Val);
923     io.endMapping();
924   }
925 }
926
927 template <typename T>
928 typename std::enable_if<missingTraits<T, EmptyContext>::value, void>::type
929 yamlize(IO &io, T &Val, bool, EmptyContext &Ctx) {
930   char missing_yaml_trait_for_type[sizeof(MissingTrait<T>)];
931 }
932
933 template <typename T, typename Context>
934 typename std::enable_if<has_SequenceTraits<T>::value, void>::type
935 yamlize(IO &io, T &Seq, bool, Context &Ctx) {
936   if ( has_FlowTraits< SequenceTraits<T>>::value ) {
937     unsigned incnt = io.beginFlowSequence();
938     unsigned count = io.outputting() ? SequenceTraits<T>::size(io, Seq) : incnt;
939     for(unsigned i=0; i < count; ++i) {
940       void *SaveInfo;
941       if ( io.preflightFlowElement(i, SaveInfo) ) {
942         yamlize(io, SequenceTraits<T>::element(io, Seq, i), true, Ctx);
943         io.postflightFlowElement(SaveInfo);
944       }
945     }
946     io.endFlowSequence();
947   }
948   else {
949     unsigned incnt = io.beginSequence();
950     unsigned count = io.outputting() ? SequenceTraits<T>::size(io, Seq) : incnt;
951     for(unsigned i=0; i < count; ++i) {
952       void *SaveInfo;
953       if ( io.preflightElement(i, SaveInfo) ) {
954         yamlize(io, SequenceTraits<T>::element(io, Seq, i), true, Ctx);
955         io.postflightElement(SaveInfo);
956       }
957     }
958     io.endSequence();
959   }
960 }
961
962 template<>
963 struct ScalarTraits<bool> {
964   static void output(const bool &, void* , raw_ostream &);
965   static StringRef input(StringRef, void *, bool &);
966   static QuotingType mustQuote(StringRef) { return QuotingType::None; }
967 };
968
969 template<>
970 struct ScalarTraits<StringRef> {
971   static void output(const StringRef &, void *, raw_ostream &);
972   static StringRef input(StringRef, void *, StringRef &);
973   static QuotingType mustQuote(StringRef S) { return needsQuotes(S); }
974 };
975
976 template<>
977 struct ScalarTraits<std::string> {
978   static void output(const std::string &, void *, raw_ostream &);
979   static StringRef input(StringRef, void *, std::string &);
980   static QuotingType mustQuote(StringRef S) { return needsQuotes(S); }
981 };
982
983 template<>
984 struct ScalarTraits<uint8_t> {
985   static void output(const uint8_t &, void *, raw_ostream &);
986   static StringRef input(StringRef, void *, uint8_t &);
987   static QuotingType mustQuote(StringRef) { return QuotingType::None; }
988 };
989
990 template<>
991 struct ScalarTraits<uint16_t> {
992   static void output(const uint16_t &, void *, raw_ostream &);
993   static StringRef input(StringRef, void *, uint16_t &);
994   static QuotingType mustQuote(StringRef) { return QuotingType::None; }
995 };
996
997 template<>
998 struct ScalarTraits<uint32_t> {
999   static void output(const uint32_t &, void *, raw_ostream &);
1000   static StringRef input(StringRef, void *, uint32_t &);
1001   static QuotingType mustQuote(StringRef) { return QuotingType::None; }
1002 };
1003
1004 template<>
1005 struct ScalarTraits<uint64_t> {
1006   static void output(const uint64_t &, void *, raw_ostream &);
1007   static StringRef input(StringRef, void *, uint64_t &);
1008   static QuotingType mustQuote(StringRef) { return QuotingType::None; }
1009 };
1010
1011 template<>
1012 struct ScalarTraits<int8_t> {
1013   static void output(const int8_t &, void *, raw_ostream &);
1014   static StringRef input(StringRef, void *, int8_t &);
1015   static QuotingType mustQuote(StringRef) { return QuotingType::None; }
1016 };
1017
1018 template<>
1019 struct ScalarTraits<int16_t> {
1020   static void output(const int16_t &, void *, raw_ostream &);
1021   static StringRef input(StringRef, void *, int16_t &);
1022   static QuotingType mustQuote(StringRef) { return QuotingType::None; }
1023 };
1024
1025 template<>
1026 struct ScalarTraits<int32_t> {
1027   static void output(const int32_t &, void *, raw_ostream &);
1028   static StringRef input(StringRef, void *, int32_t &);
1029   static QuotingType mustQuote(StringRef) { return QuotingType::None; }
1030 };
1031
1032 template<>
1033 struct ScalarTraits<int64_t> {
1034   static void output(const int64_t &, void *, raw_ostream &);
1035   static StringRef input(StringRef, void *, int64_t &);
1036   static QuotingType mustQuote(StringRef) { return QuotingType::None; }
1037 };
1038
1039 template<>
1040 struct ScalarTraits<float> {
1041   static void output(const float &, void *, raw_ostream &);
1042   static StringRef input(StringRef, void *, float &);
1043   static QuotingType mustQuote(StringRef) { return QuotingType::None; }
1044 };
1045
1046 template<>
1047 struct ScalarTraits<double> {
1048   static void output(const double &, void *, raw_ostream &);
1049   static StringRef input(StringRef, void *, double &);
1050   static QuotingType mustQuote(StringRef) { return QuotingType::None; }
1051 };
1052
1053 // For endian types, we just use the existing ScalarTraits for the underlying
1054 // type.  This way endian aware types are supported whenever a ScalarTraits
1055 // is defined for the underlying type.
1056 template <typename value_type, support::endianness endian, size_t alignment>
1057 struct ScalarTraits<support::detail::packed_endian_specific_integral<
1058     value_type, endian, alignment>> {
1059   using endian_type =
1060       support::detail::packed_endian_specific_integral<value_type, endian,
1061                                                        alignment>;
1062
1063   static void output(const endian_type &E, void *Ctx, raw_ostream &Stream) {
1064     ScalarTraits<value_type>::output(static_cast<value_type>(E), Ctx, Stream);
1065   }
1066
1067   static StringRef input(StringRef Str, void *Ctx, endian_type &E) {
1068     value_type V;
1069     auto R = ScalarTraits<value_type>::input(Str, Ctx, V);
1070     E = static_cast<endian_type>(V);
1071     return R;
1072   }
1073
1074   static QuotingType mustQuote(StringRef Str) {
1075     return ScalarTraits<value_type>::mustQuote(Str);
1076   }
1077 };
1078
1079 // Utility for use within MappingTraits<>::mapping() method
1080 // to [de]normalize an object for use with YAML conversion.
1081 template <typename TNorm, typename TFinal>
1082 struct MappingNormalization {
1083   MappingNormalization(IO &i_o, TFinal &Obj)
1084       : io(i_o), BufPtr(nullptr), Result(Obj) {
1085     if ( io.outputting() ) {
1086       BufPtr = new (&Buffer) TNorm(io, Obj);
1087     }
1088     else {
1089       BufPtr = new (&Buffer) TNorm(io);
1090     }
1091   }
1092
1093   ~MappingNormalization() {
1094     if ( ! io.outputting() ) {
1095       Result = BufPtr->denormalize(io);
1096     }
1097     BufPtr->~TNorm();
1098   }
1099
1100   TNorm* operator->() { return BufPtr; }
1101
1102 private:
1103   using Storage = AlignedCharArrayUnion<TNorm>;
1104
1105   Storage       Buffer;
1106   IO           &io;
1107   TNorm        *BufPtr;
1108   TFinal       &Result;
1109 };
1110
1111 // Utility for use within MappingTraits<>::mapping() method
1112 // to [de]normalize an object for use with YAML conversion.
1113 template <typename TNorm, typename TFinal>
1114 struct MappingNormalizationHeap {
1115   MappingNormalizationHeap(IO &i_o, TFinal &Obj, BumpPtrAllocator *allocator)
1116     : io(i_o), Result(Obj) {
1117     if ( io.outputting() ) {
1118       BufPtr = new (&Buffer) TNorm(io, Obj);
1119     }
1120     else if (allocator) {
1121       BufPtr = allocator->Allocate<TNorm>();
1122       new (BufPtr) TNorm(io);
1123     } else {
1124       BufPtr = new TNorm(io);
1125     }
1126   }
1127
1128   ~MappingNormalizationHeap() {
1129     if ( io.outputting() ) {
1130       BufPtr->~TNorm();
1131     }
1132     else {
1133       Result = BufPtr->denormalize(io);
1134     }
1135   }
1136
1137   TNorm* operator->() { return BufPtr; }
1138
1139 private:
1140   using Storage = AlignedCharArrayUnion<TNorm>;
1141
1142   Storage       Buffer;
1143   IO           &io;
1144   TNorm        *BufPtr = nullptr;
1145   TFinal       &Result;
1146 };
1147
1148 ///
1149 /// The Input class is used to parse a yaml document into in-memory structs
1150 /// and vectors.
1151 ///
1152 /// It works by using YAMLParser to do a syntax parse of the entire yaml
1153 /// document, then the Input class builds a graph of HNodes which wraps
1154 /// each yaml Node.  The extra layer is buffering.  The low level yaml
1155 /// parser only lets you look at each node once.  The buffering layer lets
1156 /// you search and interate multiple times.  This is necessary because
1157 /// the mapRequired() method calls may not be in the same order
1158 /// as the keys in the document.
1159 ///
1160 class Input : public IO {
1161 public:
1162   // Construct a yaml Input object from a StringRef and optional
1163   // user-data. The DiagHandler can be specified to provide
1164   // alternative error reporting.
1165   Input(StringRef InputContent,
1166         void *Ctxt = nullptr,
1167         SourceMgr::DiagHandlerTy DiagHandler = nullptr,
1168         void *DiagHandlerCtxt = nullptr);
1169   Input(MemoryBufferRef Input,
1170         void *Ctxt = nullptr,
1171         SourceMgr::DiagHandlerTy DiagHandler = nullptr,
1172         void *DiagHandlerCtxt = nullptr);
1173   ~Input() override;
1174
1175   // Check if there was an syntax or semantic error during parsing.
1176   std::error_code error();
1177
1178 private:
1179   bool outputting() override;
1180   bool mapTag(StringRef, bool) override;
1181   void beginMapping() override;
1182   void endMapping() override;
1183   bool preflightKey(const char *, bool, bool, bool &, void *&) override;
1184   void postflightKey(void *) override;
1185   std::vector<StringRef> keys() override;
1186   void beginFlowMapping() override;
1187   void endFlowMapping() override;
1188   unsigned beginSequence() override;
1189   void endSequence() override;
1190   bool preflightElement(unsigned index, void *&) override;
1191   void postflightElement(void *) override;
1192   unsigned beginFlowSequence() override;
1193   bool preflightFlowElement(unsigned , void *&) override;
1194   void postflightFlowElement(void *) override;
1195   void endFlowSequence() override;
1196   void beginEnumScalar() override;
1197   bool matchEnumScalar(const char*, bool) override;
1198   bool matchEnumFallback() override;
1199   void endEnumScalar() override;
1200   bool beginBitSetScalar(bool &) override;
1201   bool bitSetMatch(const char *, bool ) override;
1202   void endBitSetScalar() override;
1203   void scalarString(StringRef &, QuotingType) override;
1204   void blockScalarString(StringRef &) override;
1205   void setError(const Twine &message) override;
1206   bool canElideEmptySequence() override;
1207
1208   class HNode {
1209     virtual void anchor();
1210
1211   public:
1212     HNode(Node *n) : _node(n) { }
1213     virtual ~HNode() = default;
1214
1215     static bool classof(const HNode *) { return true; }
1216
1217     Node *_node;
1218   };
1219
1220   class EmptyHNode : public HNode {
1221     void anchor() override;
1222
1223   public:
1224     EmptyHNode(Node *n) : HNode(n) { }
1225
1226     static bool classof(const HNode *n) { return NullNode::classof(n->_node); }
1227
1228     static bool classof(const EmptyHNode *) { return true; }
1229   };
1230
1231   class ScalarHNode : public HNode {
1232     void anchor() override;
1233
1234   public:
1235     ScalarHNode(Node *n, StringRef s) : HNode(n), _value(s) { }
1236
1237     StringRef value() const { return _value; }
1238
1239     static bool classof(const HNode *n) {
1240       return ScalarNode::classof(n->_node) ||
1241              BlockScalarNode::classof(n->_node);
1242     }
1243
1244     static bool classof(const ScalarHNode *) { return true; }
1245
1246   protected:
1247     StringRef _value;
1248   };
1249
1250   class MapHNode : public HNode {
1251     void anchor() override;
1252
1253   public:
1254     MapHNode(Node *n) : HNode(n) { }
1255
1256     static bool classof(const HNode *n) {
1257       return MappingNode::classof(n->_node);
1258     }
1259
1260     static bool classof(const MapHNode *) { return true; }
1261
1262     using NameToNode = StringMap<std::unique_ptr<HNode>>;
1263
1264     NameToNode Mapping;
1265     SmallVector<std::string, 6> ValidKeys;
1266   };
1267
1268   class SequenceHNode : public HNode {
1269     void anchor() override;
1270
1271   public:
1272     SequenceHNode(Node *n) : HNode(n) { }
1273
1274     static bool classof(const HNode *n) {
1275       return SequenceNode::classof(n->_node);
1276     }
1277
1278     static bool classof(const SequenceHNode *) { return true; }
1279
1280     std::vector<std::unique_ptr<HNode>> Entries;
1281   };
1282
1283   std::unique_ptr<Input::HNode> createHNodes(Node *node);
1284   void setError(HNode *hnode, const Twine &message);
1285   void setError(Node *node, const Twine &message);
1286
1287 public:
1288   // These are only used by operator>>. They could be private
1289   // if those templated things could be made friends.
1290   bool setCurrentDocument();
1291   bool nextDocument();
1292
1293   /// Returns the current node that's being parsed by the YAML Parser.
1294   const Node *getCurrentNode() const;
1295
1296 private:
1297   SourceMgr                           SrcMgr; // must be before Strm
1298   std::unique_ptr<llvm::yaml::Stream> Strm;
1299   std::unique_ptr<HNode>              TopNode;
1300   std::error_code                     EC;
1301   BumpPtrAllocator                    StringAllocator;
1302   document_iterator                   DocIterator;
1303   std::vector<bool>                   BitValuesUsed;
1304   HNode *CurrentNode = nullptr;
1305   bool                                ScalarMatchFound;
1306 };
1307
1308 ///
1309 /// The Output class is used to generate a yaml document from in-memory structs
1310 /// and vectors.
1311 ///
1312 class Output : public IO {
1313 public:
1314   Output(raw_ostream &, void *Ctxt = nullptr, int WrapColumn = 70);
1315   ~Output() override;
1316
1317   /// Set whether or not to output optional values which are equal
1318   /// to the default value.  By default, when outputting if you attempt
1319   /// to write a value that is equal to the default, the value gets ignored.
1320   /// Sometimes, it is useful to be able to see these in the resulting YAML
1321   /// anyway.
1322   void setWriteDefaultValues(bool Write) { WriteDefaultValues = Write; }
1323
1324   bool outputting() override;
1325   bool mapTag(StringRef, bool) override;
1326   void beginMapping() override;
1327   void endMapping() override;
1328   bool preflightKey(const char *key, bool, bool, bool &, void *&) override;
1329   void postflightKey(void *) override;
1330   std::vector<StringRef> keys() override;
1331   void beginFlowMapping() override;
1332   void endFlowMapping() override;
1333   unsigned beginSequence() override;
1334   void endSequence() override;
1335   bool preflightElement(unsigned, void *&) override;
1336   void postflightElement(void *) override;
1337   unsigned beginFlowSequence() override;
1338   bool preflightFlowElement(unsigned, void *&) override;
1339   void postflightFlowElement(void *) override;
1340   void endFlowSequence() override;
1341   void beginEnumScalar() override;
1342   bool matchEnumScalar(const char*, bool) override;
1343   bool matchEnumFallback() override;
1344   void endEnumScalar() override;
1345   bool beginBitSetScalar(bool &) override;
1346   bool bitSetMatch(const char *, bool ) override;
1347   void endBitSetScalar() override;
1348   void scalarString(StringRef &, QuotingType) override;
1349   void blockScalarString(StringRef &) override;
1350   void setError(const Twine &message) override;
1351   bool canElideEmptySequence() override;
1352
1353   // These are only used by operator<<. They could be private
1354   // if that templated operator could be made a friend.
1355   void beginDocuments();
1356   bool preflightDocument(unsigned);
1357   void postflightDocument();
1358   void endDocuments();
1359
1360 private:
1361   void output(StringRef s);
1362   void outputUpToEndOfLine(StringRef s);
1363   void newLineCheck();
1364   void outputNewLine();
1365   void paddedKey(StringRef key);
1366   void flowKey(StringRef Key);
1367
1368   enum InState {
1369     inSeq,
1370     inFlowSeq,
1371     inMapFirstKey,
1372     inMapOtherKey,
1373     inFlowMapFirstKey,
1374     inFlowMapOtherKey
1375   };
1376
1377   raw_ostream &Out;
1378   int WrapColumn;
1379   SmallVector<InState, 8> StateStack;
1380   int Column = 0;
1381   int ColumnAtFlowStart = 0;
1382   int ColumnAtMapFlowStart = 0;
1383   bool NeedBitValueComma = false;
1384   bool NeedFlowSequenceComma = false;
1385   bool EnumerationMatchFound = false;
1386   bool NeedsNewLine = false;
1387   bool WriteDefaultValues = false;
1388 };
1389
1390 /// YAML I/O does conversion based on types. But often native data types
1391 /// are just a typedef of built in intergral types (e.g. int).  But the C++
1392 /// type matching system sees through the typedef and all the typedefed types
1393 /// look like a built in type. This will cause the generic YAML I/O conversion
1394 /// to be used. To provide better control over the YAML conversion, you can
1395 /// use this macro instead of typedef.  It will create a class with one field
1396 /// and automatic conversion operators to and from the base type.
1397 /// Based on BOOST_STRONG_TYPEDEF
1398 #define LLVM_YAML_STRONG_TYPEDEF(_base, _type)                                 \
1399     struct _type {                                                             \
1400         _type() = default;                                                     \
1401         _type(const _base v) : value(v) {}                                     \
1402         _type(const _type &v) = default;                                       \
1403         _type &operator=(const _type &rhs) = default;                          \
1404         _type &operator=(const _base &rhs) { value = rhs; return *this; }      \
1405         operator const _base & () const { return value; }                      \
1406         bool operator==(const _type &rhs) const { return value == rhs.value; } \
1407         bool operator==(const _base &rhs) const { return value == rhs; }       \
1408         bool operator<(const _type &rhs) const { return value < rhs.value; }   \
1409         _base value;                                                           \
1410         using BaseType = _base;                                                \
1411     };
1412
1413 ///
1414 /// Use these types instead of uintXX_t in any mapping to have
1415 /// its yaml output formatted as hexadecimal.
1416 ///
1417 LLVM_YAML_STRONG_TYPEDEF(uint8_t, Hex8)
1418 LLVM_YAML_STRONG_TYPEDEF(uint16_t, Hex16)
1419 LLVM_YAML_STRONG_TYPEDEF(uint32_t, Hex32)
1420 LLVM_YAML_STRONG_TYPEDEF(uint64_t, Hex64)
1421
1422 template<>
1423 struct ScalarTraits<Hex8> {
1424   static void output(const Hex8 &, void *, raw_ostream &);
1425   static StringRef input(StringRef, void *, Hex8 &);
1426   static QuotingType mustQuote(StringRef) { return QuotingType::None; }
1427 };
1428
1429 template<>
1430 struct ScalarTraits<Hex16> {
1431   static void output(const Hex16 &, void *, raw_ostream &);
1432   static StringRef input(StringRef, void *, Hex16 &);
1433   static QuotingType mustQuote(StringRef) { return QuotingType::None; }
1434 };
1435
1436 template<>
1437 struct ScalarTraits<Hex32> {
1438   static void output(const Hex32 &, void *, raw_ostream &);
1439   static StringRef input(StringRef, void *, Hex32 &);
1440   static QuotingType mustQuote(StringRef) { return QuotingType::None; }
1441 };
1442
1443 template<>
1444 struct ScalarTraits<Hex64> {
1445   static void output(const Hex64 &, void *, raw_ostream &);
1446   static StringRef input(StringRef, void *, Hex64 &);
1447   static QuotingType mustQuote(StringRef) { return QuotingType::None; }
1448 };
1449
1450 // Define non-member operator>> so that Input can stream in a document list.
1451 template <typename T>
1452 inline
1453 typename std::enable_if<has_DocumentListTraits<T>::value, Input &>::type
1454 operator>>(Input &yin, T &docList) {
1455   int i = 0;
1456   EmptyContext Ctx;
1457   while ( yin.setCurrentDocument() ) {
1458     yamlize(yin, DocumentListTraits<T>::element(yin, docList, i), true, Ctx);
1459     if ( yin.error() )
1460       return yin;
1461     yin.nextDocument();
1462     ++i;
1463   }
1464   return yin;
1465 }
1466
1467 // Define non-member operator>> so that Input can stream in a map as a document.
1468 template <typename T>
1469 inline typename std::enable_if<has_MappingTraits<T, EmptyContext>::value,
1470                                Input &>::type
1471 operator>>(Input &yin, T &docMap) {
1472   EmptyContext Ctx;
1473   yin.setCurrentDocument();
1474   yamlize(yin, docMap, true, Ctx);
1475   return yin;
1476 }
1477
1478 // Define non-member operator>> so that Input can stream in a sequence as
1479 // a document.
1480 template <typename T>
1481 inline
1482 typename std::enable_if<has_SequenceTraits<T>::value, Input &>::type
1483 operator>>(Input &yin, T &docSeq) {
1484   EmptyContext Ctx;
1485   if (yin.setCurrentDocument())
1486     yamlize(yin, docSeq, true, Ctx);
1487   return yin;
1488 }
1489
1490 // Define non-member operator>> so that Input can stream in a block scalar.
1491 template <typename T>
1492 inline
1493 typename std::enable_if<has_BlockScalarTraits<T>::value, Input &>::type
1494 operator>>(Input &In, T &Val) {
1495   EmptyContext Ctx;
1496   if (In.setCurrentDocument())
1497     yamlize(In, Val, true, Ctx);
1498   return In;
1499 }
1500
1501 // Define non-member operator>> so that Input can stream in a string map.
1502 template <typename T>
1503 inline
1504 typename std::enable_if<has_CustomMappingTraits<T>::value, Input &>::type
1505 operator>>(Input &In, T &Val) {
1506   EmptyContext Ctx;
1507   if (In.setCurrentDocument())
1508     yamlize(In, Val, true, Ctx);
1509   return In;
1510 }
1511
1512 // Provide better error message about types missing a trait specialization
1513 template <typename T>
1514 inline typename std::enable_if<missingTraits<T, EmptyContext>::value,
1515                                Input &>::type
1516 operator>>(Input &yin, T &docSeq) {
1517   char missing_yaml_trait_for_type[sizeof(MissingTrait<T>)];
1518   return yin;
1519 }
1520
1521 // Define non-member operator<< so that Output can stream out document list.
1522 template <typename T>
1523 inline
1524 typename std::enable_if<has_DocumentListTraits<T>::value, Output &>::type
1525 operator<<(Output &yout, T &docList) {
1526   EmptyContext Ctx;
1527   yout.beginDocuments();
1528   const size_t count = DocumentListTraits<T>::size(yout, docList);
1529   for(size_t i=0; i < count; ++i) {
1530     if ( yout.preflightDocument(i) ) {
1531       yamlize(yout, DocumentListTraits<T>::element(yout, docList, i), true,
1532               Ctx);
1533       yout.postflightDocument();
1534     }
1535   }
1536   yout.endDocuments();
1537   return yout;
1538 }
1539
1540 // Define non-member operator<< so that Output can stream out a map.
1541 template <typename T>
1542 inline typename std::enable_if<has_MappingTraits<T, EmptyContext>::value,
1543                                Output &>::type
1544 operator<<(Output &yout, T &map) {
1545   EmptyContext Ctx;
1546   yout.beginDocuments();
1547   if ( yout.preflightDocument(0) ) {
1548     yamlize(yout, map, true, Ctx);
1549     yout.postflightDocument();
1550   }
1551   yout.endDocuments();
1552   return yout;
1553 }
1554
1555 // Define non-member operator<< so that Output can stream out a sequence.
1556 template <typename T>
1557 inline
1558 typename std::enable_if<has_SequenceTraits<T>::value, Output &>::type
1559 operator<<(Output &yout, T &seq) {
1560   EmptyContext Ctx;
1561   yout.beginDocuments();
1562   if ( yout.preflightDocument(0) ) {
1563     yamlize(yout, seq, true, Ctx);
1564     yout.postflightDocument();
1565   }
1566   yout.endDocuments();
1567   return yout;
1568 }
1569
1570 // Define non-member operator<< so that Output can stream out a block scalar.
1571 template <typename T>
1572 inline
1573 typename std::enable_if<has_BlockScalarTraits<T>::value, Output &>::type
1574 operator<<(Output &Out, T &Val) {
1575   EmptyContext Ctx;
1576   Out.beginDocuments();
1577   if (Out.preflightDocument(0)) {
1578     yamlize(Out, Val, true, Ctx);
1579     Out.postflightDocument();
1580   }
1581   Out.endDocuments();
1582   return Out;
1583 }
1584
1585 // Define non-member operator<< so that Output can stream out a string map.
1586 template <typename T>
1587 inline
1588 typename std::enable_if<has_CustomMappingTraits<T>::value, Output &>::type
1589 operator<<(Output &Out, T &Val) {
1590   EmptyContext Ctx;
1591   Out.beginDocuments();
1592   if (Out.preflightDocument(0)) {
1593     yamlize(Out, Val, true, Ctx);
1594     Out.postflightDocument();
1595   }
1596   Out.endDocuments();
1597   return Out;
1598 }
1599
1600 // Provide better error message about types missing a trait specialization
1601 template <typename T>
1602 inline typename std::enable_if<missingTraits<T, EmptyContext>::value,
1603                                Output &>::type
1604 operator<<(Output &yout, T &seq) {
1605   char missing_yaml_trait_for_type[sizeof(MissingTrait<T>)];
1606   return yout;
1607 }
1608
1609 template <bool B> struct IsFlowSequenceBase {};
1610 template <> struct IsFlowSequenceBase<true> { static const bool flow = true; };
1611
1612 template <typename T, bool Flow>
1613 struct SequenceTraitsImpl : IsFlowSequenceBase<Flow> {
1614 private:
1615   using type = typename T::value_type;
1616
1617 public:
1618   static size_t size(IO &io, T &seq) { return seq.size(); }
1619
1620   static type &element(IO &io, T &seq, size_t index) {
1621     if (index >= seq.size())
1622       seq.resize(index + 1);
1623     return seq[index];
1624   }
1625 };
1626
1627 // Simple helper to check an expression can be used as a bool-valued template
1628 // argument.
1629 template <bool> struct CheckIsBool { static const bool value = true; };
1630
1631 // If T has SequenceElementTraits, then vector<T> and SmallVector<T, N> have
1632 // SequenceTraits that do the obvious thing.
1633 template <typename T>
1634 struct SequenceTraits<std::vector<T>,
1635                       typename std::enable_if<CheckIsBool<
1636                           SequenceElementTraits<T>::flow>::value>::type>
1637     : SequenceTraitsImpl<std::vector<T>, SequenceElementTraits<T>::flow> {};
1638 template <typename T, unsigned N>
1639 struct SequenceTraits<SmallVector<T, N>,
1640                       typename std::enable_if<CheckIsBool<
1641                           SequenceElementTraits<T>::flow>::value>::type>
1642     : SequenceTraitsImpl<SmallVector<T, N>, SequenceElementTraits<T>::flow> {};
1643
1644 // Sequences of fundamental types use flow formatting.
1645 template <typename T>
1646 struct SequenceElementTraits<
1647     T, typename std::enable_if<std::is_fundamental<T>::value>::type> {
1648   static const bool flow = true;
1649 };
1650
1651 // Sequences of strings use block formatting.
1652 template<> struct SequenceElementTraits<std::string> {
1653   static const bool flow = false;
1654 };
1655 template<> struct SequenceElementTraits<StringRef> {
1656   static const bool flow = false;
1657 };
1658 template<> struct SequenceElementTraits<std::pair<std::string, std::string>> {
1659   static const bool flow = false;
1660 };
1661
1662 /// Implementation of CustomMappingTraits for std::map<std::string, T>.
1663 template <typename T> struct StdMapStringCustomMappingTraitsImpl {
1664   using map_type = std::map<std::string, T>;
1665
1666   static void inputOne(IO &io, StringRef key, map_type &v) {
1667     io.mapRequired(key.str().c_str(), v[key]);
1668   }
1669
1670   static void output(IO &io, map_type &v) {
1671     for (auto &p : v)
1672       io.mapRequired(p.first.c_str(), p.second);
1673   }
1674 };
1675
1676 } // end namespace yaml
1677 } // end namespace llvm
1678
1679 #define LLVM_YAML_IS_SEQUENCE_VECTOR_IMPL(TYPE, FLOW)                          \
1680   namespace llvm {                                                             \
1681   namespace yaml {                                                             \
1682   static_assert(                                                               \
1683       !std::is_fundamental<TYPE>::value &&                                     \
1684       !std::is_same<TYPE, std::string>::value &&                               \
1685       !std::is_same<TYPE, llvm::StringRef>::value,                             \
1686       "only use LLVM_YAML_IS_SEQUENCE_VECTOR for types you control");          \
1687   template <> struct SequenceElementTraits<TYPE> {                             \
1688     static const bool flow = FLOW;                                             \
1689   };                                                                           \
1690   }                                                                            \
1691   }
1692
1693 /// Utility for declaring that a std::vector of a particular type
1694 /// should be considered a YAML sequence.
1695 #define LLVM_YAML_IS_SEQUENCE_VECTOR(type)                                     \
1696   LLVM_YAML_IS_SEQUENCE_VECTOR_IMPL(type, false)
1697
1698 /// Utility for declaring that a std::vector of a particular type
1699 /// should be considered a YAML flow sequence.
1700 #define LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(type)                                \
1701   LLVM_YAML_IS_SEQUENCE_VECTOR_IMPL(type, true)
1702
1703 #define LLVM_YAML_DECLARE_MAPPING_TRAITS(Type)                                 \
1704   namespace llvm {                                                             \
1705   namespace yaml {                                                             \
1706   template <> struct MappingTraits<Type> {                                     \
1707     static void mapping(IO &IO, Type &Obj);                                    \
1708   };                                                                           \
1709   }                                                                            \
1710   }
1711
1712 #define LLVM_YAML_DECLARE_ENUM_TRAITS(Type)                                    \
1713   namespace llvm {                                                             \
1714   namespace yaml {                                                             \
1715   template <> struct ScalarEnumerationTraits<Type> {                           \
1716     static void enumeration(IO &io, Type &Value);                              \
1717   };                                                                           \
1718   }                                                                            \
1719   }
1720
1721 #define LLVM_YAML_DECLARE_BITSET_TRAITS(Type)                                  \
1722   namespace llvm {                                                             \
1723   namespace yaml {                                                             \
1724   template <> struct ScalarBitSetTraits<Type> {                                \
1725     static void bitset(IO &IO, Type &Options);                                 \
1726   };                                                                           \
1727   }                                                                            \
1728   }
1729
1730 #define LLVM_YAML_DECLARE_SCALAR_TRAITS(Type, MustQuote)                       \
1731   namespace llvm {                                                             \
1732   namespace yaml {                                                             \
1733   template <> struct ScalarTraits<Type> {                                      \
1734     static void output(const Type &Value, void *ctx, raw_ostream &Out);        \
1735     static StringRef input(StringRef Scalar, void *ctxt, Type &Value);         \
1736     static QuotingType mustQuote(StringRef) { return MustQuote; }              \
1737   };                                                                           \
1738   }                                                                            \
1739   }
1740
1741 /// Utility for declaring that a std::vector of a particular type
1742 /// should be considered a YAML document list.
1743 #define LLVM_YAML_IS_DOCUMENT_LIST_VECTOR(_type)                               \
1744   namespace llvm {                                                             \
1745   namespace yaml {                                                             \
1746   template <unsigned N>                                                        \
1747   struct DocumentListTraits<SmallVector<_type, N>>                             \
1748       : public SequenceTraitsImpl<SmallVector<_type, N>, false> {};            \
1749   template <>                                                                  \
1750   struct DocumentListTraits<std::vector<_type>>                                \
1751       : public SequenceTraitsImpl<std::vector<_type>, false> {};               \
1752   }                                                                            \
1753   }
1754
1755 /// Utility for declaring that std::map<std::string, _type> should be considered
1756 /// a YAML map.
1757 #define LLVM_YAML_IS_STRING_MAP(_type)                                         \
1758   namespace llvm {                                                             \
1759   namespace yaml {                                                             \
1760   template <>                                                                  \
1761   struct CustomMappingTraits<std::map<std::string, _type>>                     \
1762       : public StdMapStringCustomMappingTraitsImpl<_type> {};                  \
1763   }                                                                            \
1764   }
1765
1766 #endif // LLVM_SUPPORT_YAMLTRAITS_H