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