]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/include/llvm/Support/YAMLTraits.h
Merge llvm, clang, lld, lldb, compiler-rt and libc++ r306325, 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 <map>
30 #include <memory>
31 #include <new>
32 #include <string>
33 #include <system_error>
34 #include <type_traits>
35 #include <vector>
36
37 namespace llvm {
38 namespace yaml {
39
40 struct EmptyContext {};
41
42 /// This class should be specialized by any type that needs to be converted
43 /// to/from a YAML mapping.  For example:
44 ///
45 ///     struct MappingTraits<MyStruct> {
46 ///       static void mapping(IO &io, MyStruct &s) {
47 ///         io.mapRequired("name", s.name);
48 ///         io.mapRequired("size", s.size);
49 ///         io.mapOptional("age",  s.age);
50 ///       }
51 ///     };
52 template<class T>
53 struct MappingTraits {
54   // Must provide:
55   // static void mapping(IO &io, T &fields);
56   // Optionally may provide:
57   // static StringRef validate(IO &io, T &fields);
58   //
59   // The optional flow flag will cause generated YAML to use a flow mapping
60   // (e.g. { a: 0, b: 1 }):
61   // static const bool flow = true;
62 };
63
64 /// This class is similar to MappingTraits<T> but allows you to pass in
65 /// additional context for each map operation.  For example:
66 ///
67 ///     struct MappingContextTraits<MyStruct, MyContext> {
68 ///       static void mapping(IO &io, MyStruct &s, MyContext &c) {
69 ///         io.mapRequired("name", s.name);
70 ///         io.mapRequired("size", s.size);
71 ///         io.mapOptional("age",  s.age);
72 ///         ++c.TimesMapped;
73 ///       }
74 ///     };
75 template <class T, class Context> struct MappingContextTraits {
76   // Must provide:
77   // static void mapping(IO &io, T &fields, Context &Ctx);
78   // Optionally may provide:
79   // static StringRef validate(IO &io, T &fields, Context &Ctx);
80   //
81   // The optional flow flag will cause generated YAML to use a flow mapping
82   // (e.g. { a: 0, b: 1 }):
83   // static const bool flow = true;
84 };
85
86 /// This class should be specialized by any integral type that converts
87 /// to/from a YAML scalar where there is a one-to-one mapping between
88 /// in-memory values and a string in YAML.  For example:
89 ///
90 ///     struct ScalarEnumerationTraits<Colors> {
91 ///         static void enumeration(IO &io, Colors &value) {
92 ///           io.enumCase(value, "red",   cRed);
93 ///           io.enumCase(value, "blue",  cBlue);
94 ///           io.enumCase(value, "green", cGreen);
95 ///         }
96 ///       };
97 template<typename T>
98 struct ScalarEnumerationTraits {
99   // Must provide:
100   // static void enumeration(IO &io, T &value);
101 };
102
103 /// This class should be specialized by any integer type that is a union
104 /// of bit values and the YAML representation is a flow sequence of
105 /// strings.  For example:
106 ///
107 ///      struct ScalarBitSetTraits<MyFlags> {
108 ///        static void bitset(IO &io, MyFlags &value) {
109 ///          io.bitSetCase(value, "big",   flagBig);
110 ///          io.bitSetCase(value, "flat",  flagFlat);
111 ///          io.bitSetCase(value, "round", flagRound);
112 ///        }
113 ///      };
114 template<typename T>
115 struct ScalarBitSetTraits {
116   // Must provide:
117   // static void bitset(IO &io, T &value);
118 };
119
120 /// This class should be specialized by type that requires custom conversion
121 /// to/from a yaml scalar.  For example:
122 ///
123 ///    template<>
124 ///    struct ScalarTraits<MyType> {
125 ///      static void output(const MyType &val, void*, llvm::raw_ostream &out) {
126 ///        // stream out custom formatting
127 ///        out << llvm::format("%x", val);
128 ///      }
129 ///      static StringRef input(StringRef scalar, void*, MyType &value) {
130 ///        // parse scalar and set `value`
131 ///        // return empty string on success, or error string
132 ///        return StringRef();
133 ///      }
134 ///      static bool mustQuote(StringRef) { return true; }
135 ///    };
136 template<typename T>
137 struct ScalarTraits {
138   // Must provide:
139   //
140   // Function to write the value as a string:
141   //static void output(const T &value, void *ctxt, llvm::raw_ostream &out);
142   //
143   // Function to convert a string to a value.  Returns the empty
144   // StringRef on success or an error string if string is malformed:
145   //static StringRef input(StringRef scalar, void *ctxt, T &value);
146   //
147   // Function to determine if the value should be quoted.
148   //static bool mustQuote(StringRef);
149 };
150
151 /// This class should be specialized by type that requires custom conversion
152 /// to/from a YAML literal block scalar. For example:
153 ///
154 ///    template <>
155 ///    struct BlockScalarTraits<MyType> {
156 ///      static void output(const MyType &Value, void*, llvm::raw_ostream &Out)
157 ///      {
158 ///        // stream out custom formatting
159 ///        Out << Val;
160 ///      }
161 ///      static StringRef input(StringRef Scalar, void*, MyType &Value) {
162 ///        // parse scalar and set `value`
163 ///        // return empty string on success, or error string
164 ///        return StringRef();
165 ///      }
166 ///    };
167 template <typename T>
168 struct BlockScalarTraits {
169   // Must provide:
170   //
171   // Function to write the value as a string:
172   // static void output(const T &Value, void *ctx, llvm::raw_ostream &Out);
173   //
174   // Function to convert a string to a value.  Returns the empty
175   // StringRef on success or an error string if string is malformed:
176   // static StringRef input(StringRef Scalar, void *ctxt, T &Value);
177 };
178
179 /// This class should be specialized by any type that needs to be converted
180 /// to/from a YAML sequence.  For example:
181 ///
182 ///    template<>
183 ///    struct SequenceTraits< std::vector<MyType>> {
184 ///      static size_t size(IO &io, std::vector<MyType> &seq) {
185 ///        return seq.size();
186 ///      }
187 ///      static MyType& element(IO &, std::vector<MyType> &seq, size_t index) {
188 ///        if ( index >= seq.size() )
189 ///          seq.resize(index+1);
190 ///        return seq[index];
191 ///      }
192 ///    };
193 template<typename T>
194 struct SequenceTraits {
195   // Must provide:
196   // static size_t size(IO &io, T &seq);
197   // static T::value_type& element(IO &io, T &seq, size_t index);
198   //
199   // The following is option and will cause generated YAML to use
200   // a flow sequence (e.g. [a,b,c]).
201   // static const bool flow = true;
202 };
203
204 /// This class should be specialized by any type that needs to be converted
205 /// to/from a list of YAML documents.
206 template<typename T>
207 struct DocumentListTraits {
208   // Must provide:
209   // static size_t size(IO &io, T &seq);
210   // static T::value_type& element(IO &io, T &seq, size_t index);
211 };
212
213 /// This class should be specialized by any type that needs to be converted
214 /// to/from a YAML mapping in the case where the names of the keys are not known
215 /// in advance, e.g. a string map.
216 template <typename T>
217 struct CustomMappingTraits {
218   // static void inputOne(IO &io, StringRef key, T &elem);
219   // static void output(IO &io, T &elem);
220 };
221
222 // Only used for better diagnostics of missing traits
223 template <typename T>
224 struct MissingTrait;
225
226 // Test if ScalarEnumerationTraits<T> is defined on type T.
227 template <class T>
228 struct has_ScalarEnumerationTraits
229 {
230   using Signature_enumeration = void (*)(class IO&, T&);
231
232   template <typename U>
233   static char test(SameType<Signature_enumeration, &U::enumeration>*);
234
235   template <typename U>
236   static double test(...);
237
238 public:
239   static bool const value =
240     (sizeof(test<ScalarEnumerationTraits<T>>(nullptr)) == 1);
241 };
242
243 // Test if ScalarBitSetTraits<T> is defined on type T.
244 template <class T>
245 struct has_ScalarBitSetTraits
246 {
247   using Signature_bitset = void (*)(class IO&, T&);
248
249   template <typename U>
250   static char test(SameType<Signature_bitset, &U::bitset>*);
251
252   template <typename U>
253   static double test(...);
254
255 public:
256   static bool const value = (sizeof(test<ScalarBitSetTraits<T>>(nullptr)) == 1);
257 };
258
259 // Test if ScalarTraits<T> is defined on type T.
260 template <class T>
261 struct has_ScalarTraits
262 {
263   using Signature_input = StringRef (*)(StringRef, void*, T&);
264   using Signature_output = void (*)(const T&, void*, raw_ostream&);
265   using Signature_mustQuote = bool (*)(StringRef);
266
267   template <typename U>
268   static char test(SameType<Signature_input, &U::input> *,
269                    SameType<Signature_output, &U::output> *,
270                    SameType<Signature_mustQuote, &U::mustQuote> *);
271
272   template <typename U>
273   static double test(...);
274
275 public:
276   static bool const value =
277       (sizeof(test<ScalarTraits<T>>(nullptr, nullptr, nullptr)) == 1);
278 };
279
280 // Test if BlockScalarTraits<T> is defined on type T.
281 template <class T>
282 struct has_BlockScalarTraits
283 {
284   using Signature_input = StringRef (*)(StringRef, void *, T &);
285   using Signature_output = void (*)(const T &, void *, raw_ostream &);
286
287   template <typename U>
288   static char test(SameType<Signature_input, &U::input> *,
289                    SameType<Signature_output, &U::output> *);
290
291   template <typename U>
292   static double test(...);
293
294 public:
295   static bool const value =
296       (sizeof(test<BlockScalarTraits<T>>(nullptr, nullptr)) == 1);
297 };
298
299 // Test if MappingContextTraits<T> is defined on type T.
300 template <class T, class Context> struct has_MappingTraits {
301   using Signature_mapping = void (*)(class IO &, T &, Context &);
302
303   template <typename U>
304   static char test(SameType<Signature_mapping, &U::mapping>*);
305
306   template <typename U>
307   static double test(...);
308
309 public:
310   static bool const value =
311       (sizeof(test<MappingContextTraits<T, Context>>(nullptr)) == 1);
312 };
313
314 // Test if MappingTraits<T> is defined on type T.
315 template <class T> struct has_MappingTraits<T, EmptyContext> {
316   using Signature_mapping = void (*)(class IO &, T &);
317
318   template <typename U>
319   static char test(SameType<Signature_mapping, &U::mapping> *);
320
321   template <typename U> static double test(...);
322
323 public:
324   static bool const value = (sizeof(test<MappingTraits<T>>(nullptr)) == 1);
325 };
326
327 // Test if MappingContextTraits<T>::validate() is defined on type T.
328 template <class T, class Context> struct has_MappingValidateTraits {
329   using Signature_validate = StringRef (*)(class IO &, T &, Context &);
330
331   template <typename U>
332   static char test(SameType<Signature_validate, &U::validate>*);
333
334   template <typename U>
335   static double test(...);
336
337 public:
338   static bool const value =
339       (sizeof(test<MappingContextTraits<T, Context>>(nullptr)) == 1);
340 };
341
342 // Test if MappingTraits<T>::validate() is defined on type T.
343 template <class T> struct has_MappingValidateTraits<T, EmptyContext> {
344   using Signature_validate = StringRef (*)(class IO &, T &);
345
346   template <typename U>
347   static char test(SameType<Signature_validate, &U::validate> *);
348
349   template <typename U> static double test(...);
350
351 public:
352   static bool const value = (sizeof(test<MappingTraits<T>>(nullptr)) == 1);
353 };
354
355 // Test if SequenceTraits<T> is defined on type T.
356 template <class T>
357 struct has_SequenceMethodTraits
358 {
359   using Signature_size = size_t (*)(class IO&, T&);
360
361   template <typename U>
362   static char test(SameType<Signature_size, &U::size>*);
363
364   template <typename U>
365   static double test(...);
366
367 public:
368   static bool const value =  (sizeof(test<SequenceTraits<T>>(nullptr)) == 1);
369 };
370
371 // Test if CustomMappingTraits<T> is defined on type T.
372 template <class T>
373 struct has_CustomMappingTraits
374 {
375   using Signature_input = void (*)(IO &io, StringRef key, T &v);
376
377   template <typename U>
378   static char test(SameType<Signature_input, &U::inputOne>*);
379
380   template <typename U>
381   static double test(...);
382
383 public:
384   static bool const value =
385       (sizeof(test<CustomMappingTraits<T>>(nullptr)) == 1);
386 };
387
388 // has_FlowTraits<int> will cause an error with some compilers because
389 // it subclasses int.  Using this wrapper only instantiates the
390 // real has_FlowTraits only if the template type is a class.
391 template <typename T, bool Enabled = std::is_class<T>::value>
392 class has_FlowTraits
393 {
394 public:
395    static const bool value = false;
396 };
397
398 // Some older gcc compilers don't support straight forward tests
399 // for members, so test for ambiguity cause by the base and derived
400 // classes both defining the member.
401 template <class T>
402 struct has_FlowTraits<T, true>
403 {
404   struct Fallback { bool flow; };
405   struct Derived : T, Fallback { };
406
407   template<typename C>
408   static char (&f(SameType<bool Fallback::*, &C::flow>*))[1];
409
410   template<typename C>
411   static char (&f(...))[2];
412
413 public:
414   static bool const value = sizeof(f<Derived>(nullptr)) == 2;
415 };
416
417 // Test if SequenceTraits<T> is defined on type T
418 template<typename T>
419 struct has_SequenceTraits : public std::integral_constant<bool,
420                                       has_SequenceMethodTraits<T>::value > { };
421
422 // Test if DocumentListTraits<T> is defined on type T
423 template <class T>
424 struct has_DocumentListTraits
425 {
426   using Signature_size = size_t (*)(class IO &, T &);
427
428   template <typename U>
429   static char test(SameType<Signature_size, &U::size>*);
430
431   template <typename U>
432   static double test(...);
433
434 public:
435   static bool const value = (sizeof(test<DocumentListTraits<T>>(nullptr))==1);
436 };
437
438 inline bool isNumber(StringRef S) {
439   static const char OctalChars[] = "01234567";
440   if (S.startswith("0") &&
441       S.drop_front().find_first_not_of(OctalChars) == StringRef::npos)
442     return true;
443
444   if (S.startswith("0o") &&
445       S.drop_front(2).find_first_not_of(OctalChars) == StringRef::npos)
446     return true;
447
448   static const char HexChars[] = "0123456789abcdefABCDEF";
449   if (S.startswith("0x") &&
450       S.drop_front(2).find_first_not_of(HexChars) == StringRef::npos)
451     return true;
452
453   static const char DecChars[] = "0123456789";
454   if (S.find_first_not_of(DecChars) == StringRef::npos)
455     return true;
456
457   if (S.equals(".inf") || S.equals(".Inf") || S.equals(".INF"))
458     return true;
459
460   Regex FloatMatcher("^(\\.[0-9]+|[0-9]+(\\.[0-9]*)?)([eE][-+]?[0-9]+)?$");
461   if (FloatMatcher.match(S))
462     return true;
463
464   return false;
465 }
466
467 inline bool isNumeric(StringRef S) {
468   if ((S.front() == '-' || S.front() == '+') && isNumber(S.drop_front()))
469     return true;
470
471   if (isNumber(S))
472     return true;
473
474   if (S.equals(".nan") || S.equals(".NaN") || S.equals(".NAN"))
475     return true;
476
477   return false;
478 }
479
480 inline bool isNull(StringRef S) {
481   return S.equals("null") || S.equals("Null") || S.equals("NULL") ||
482          S.equals("~");
483 }
484
485 inline bool isBool(StringRef S) {
486   return S.equals("true") || S.equals("True") || S.equals("TRUE") ||
487          S.equals("false") || S.equals("False") || S.equals("FALSE");
488 }
489
490 inline bool needsQuotes(StringRef S) {
491   if (S.empty())
492     return true;
493   if (isspace(S.front()) || isspace(S.back()))
494     return true;
495   if (S.front() == ',')
496     return true;
497
498   static const char ScalarSafeChars[] =
499       "abcdefghijklmnopqrstuvwxyz"
500       "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-/^., \t";
501   if (S.find_first_not_of(ScalarSafeChars) != StringRef::npos)
502     return true;
503
504   if (isNull(S))
505     return true;
506   if (isBool(S))
507     return true;
508   if (isNumeric(S))
509     return true;
510
511   return false;
512 }
513
514 template <typename T, typename Context>
515 struct missingTraits
516     : public std::integral_constant<bool,
517                                     !has_ScalarEnumerationTraits<T>::value &&
518                                         !has_ScalarBitSetTraits<T>::value &&
519                                         !has_ScalarTraits<T>::value &&
520                                         !has_BlockScalarTraits<T>::value &&
521                                         !has_MappingTraits<T, Context>::value &&
522                                         !has_SequenceTraits<T>::value &&
523                                         !has_CustomMappingTraits<T>::value &&
524                                         !has_DocumentListTraits<T>::value> {};
525
526 template <typename T, typename Context>
527 struct validatedMappingTraits
528     : public std::integral_constant<
529           bool, has_MappingTraits<T, Context>::value &&
530                     has_MappingValidateTraits<T, Context>::value> {};
531
532 template <typename T, typename Context>
533 struct unvalidatedMappingTraits
534     : public std::integral_constant<
535           bool, has_MappingTraits<T, Context>::value &&
536                     !has_MappingValidateTraits<T, Context>::value> {};
537
538 // Base class for Input and Output.
539 class IO {
540 public:
541   IO(void *Ctxt = nullptr);
542   virtual ~IO();
543
544   virtual bool outputting() = 0;
545
546   virtual unsigned beginSequence() = 0;
547   virtual bool preflightElement(unsigned, void *&) = 0;
548   virtual void postflightElement(void*) = 0;
549   virtual void endSequence() = 0;
550   virtual bool canElideEmptySequence() = 0;
551
552   virtual unsigned beginFlowSequence() = 0;
553   virtual bool preflightFlowElement(unsigned, void *&) = 0;
554   virtual void postflightFlowElement(void*) = 0;
555   virtual void endFlowSequence() = 0;
556
557   virtual bool mapTag(StringRef Tag, bool Default=false) = 0;
558   virtual void beginMapping() = 0;
559   virtual void endMapping() = 0;
560   virtual bool preflightKey(const char*, bool, bool, bool &, void *&) = 0;
561   virtual void postflightKey(void*) = 0;
562   virtual std::vector<StringRef> keys() = 0;
563
564   virtual void beginFlowMapping() = 0;
565   virtual void endFlowMapping() = 0;
566
567   virtual void beginEnumScalar() = 0;
568   virtual bool matchEnumScalar(const char*, bool) = 0;
569   virtual bool matchEnumFallback() = 0;
570   virtual void endEnumScalar() = 0;
571
572   virtual bool beginBitSetScalar(bool &) = 0;
573   virtual bool bitSetMatch(const char*, bool) = 0;
574   virtual void endBitSetScalar() = 0;
575
576   virtual void scalarString(StringRef &, bool) = 0;
577   virtual void blockScalarString(StringRef &) = 0;
578
579   virtual void setError(const Twine &) = 0;
580
581   template <typename T>
582   void enumCase(T &Val, const char* Str, const T ConstVal) {
583     if ( matchEnumScalar(Str, outputting() && Val == ConstVal) ) {
584       Val = ConstVal;
585     }
586   }
587
588   // allow anonymous enum values to be used with LLVM_YAML_STRONG_TYPEDEF
589   template <typename T>
590   void enumCase(T &Val, const char* Str, const uint32_t ConstVal) {
591     if ( matchEnumScalar(Str, outputting() && Val == static_cast<T>(ConstVal)) ) {
592       Val = ConstVal;
593     }
594   }
595
596   template <typename FBT, typename T>
597   void enumFallback(T &Val) {
598     if (matchEnumFallback()) {
599       EmptyContext Context;
600       // FIXME: Force integral conversion to allow strong typedefs to convert.
601       FBT Res = static_cast<typename FBT::BaseType>(Val);
602       yamlize(*this, Res, true, Context);
603       Val = static_cast<T>(static_cast<typename FBT::BaseType>(Res));
604     }
605   }
606
607   template <typename T>
608   void bitSetCase(T &Val, const char* Str, const T ConstVal) {
609     if ( bitSetMatch(Str, outputting() && (Val & ConstVal) == ConstVal) ) {
610       Val = static_cast<T>(Val | ConstVal);
611     }
612   }
613
614   // allow anonymous enum values to be used with LLVM_YAML_STRONG_TYPEDEF
615   template <typename T>
616   void bitSetCase(T &Val, const char* Str, const uint32_t ConstVal) {
617     if ( bitSetMatch(Str, outputting() && (Val & ConstVal) == ConstVal) ) {
618       Val = static_cast<T>(Val | ConstVal);
619     }
620   }
621
622   template <typename T>
623   void maskedBitSetCase(T &Val, const char *Str, T ConstVal, T Mask) {
624     if (bitSetMatch(Str, outputting() && (Val & Mask) == ConstVal))
625       Val = Val | ConstVal;
626   }
627
628   template <typename T>
629   void maskedBitSetCase(T &Val, const char *Str, uint32_t ConstVal,
630                         uint32_t Mask) {
631     if (bitSetMatch(Str, outputting() && (Val & Mask) == ConstVal))
632       Val = Val | ConstVal;
633   }
634
635   void *getContext();
636   void setContext(void *);
637
638   template <typename T> void mapRequired(const char *Key, T &Val) {
639     EmptyContext Ctx;
640     this->processKey(Key, Val, true, Ctx);
641   }
642
643   template <typename T, typename Context>
644   void mapRequired(const char *Key, T &Val, Context &Ctx) {
645     this->processKey(Key, Val, true, Ctx);
646   }
647
648   template <typename T> void mapOptional(const char *Key, T &Val) {
649     EmptyContext Ctx;
650     mapOptionalWithContext(Key, Val, Ctx);
651   }
652
653   template <typename T>
654   void mapOptional(const char *Key, T &Val, const T &Default) {
655     EmptyContext Ctx;
656     mapOptionalWithContext(Key, Val, Default, Ctx);
657   }
658
659   template <typename T, typename Context>
660   typename std::enable_if<has_SequenceTraits<T>::value, void>::type
661   mapOptionalWithContext(const char *Key, T &Val, Context &Ctx) {
662     // omit key/value instead of outputting empty sequence
663     if (this->canElideEmptySequence() && !(Val.begin() != Val.end()))
664       return;
665     this->processKey(Key, Val, false, Ctx);
666   }
667
668   template <typename T, typename Context>
669   void mapOptionalWithContext(const char *Key, Optional<T> &Val, Context &Ctx) {
670     this->processKeyWithDefault(Key, Val, Optional<T>(), /*Required=*/false,
671                                 Ctx);
672   }
673
674   template <typename T, typename Context>
675   typename std::enable_if<!has_SequenceTraits<T>::value, void>::type
676   mapOptionalWithContext(const char *Key, T &Val, Context &Ctx) {
677     this->processKey(Key, Val, false, Ctx);
678   }
679
680   template <typename T, typename Context>
681   void mapOptionalWithContext(const char *Key, T &Val, const T &Default,
682                               Context &Ctx) {
683     this->processKeyWithDefault(Key, Val, Default, false, Ctx);
684   }
685
686 private:
687   template <typename T, typename Context>
688   void processKeyWithDefault(const char *Key, Optional<T> &Val,
689                              const Optional<T> &DefaultValue, bool Required,
690                              Context &Ctx) {
691     assert(DefaultValue.hasValue() == false &&
692            "Optional<T> shouldn't have a value!");
693     void *SaveInfo;
694     bool UseDefault = true;
695     const bool sameAsDefault = outputting() && !Val.hasValue();
696     if (!outputting() && !Val.hasValue())
697       Val = T();
698     if (Val.hasValue() &&
699         this->preflightKey(Key, Required, sameAsDefault, UseDefault,
700                            SaveInfo)) {
701       yamlize(*this, Val.getValue(), Required, Ctx);
702       this->postflightKey(SaveInfo);
703     } else {
704       if (UseDefault)
705         Val = DefaultValue;
706     }
707   }
708
709   template <typename T, typename Context>
710   void processKeyWithDefault(const char *Key, T &Val, const T &DefaultValue,
711                              bool Required, Context &Ctx) {
712     void *SaveInfo;
713     bool UseDefault;
714     const bool sameAsDefault = outputting() && Val == DefaultValue;
715     if ( this->preflightKey(Key, Required, sameAsDefault, UseDefault,
716                                                                   SaveInfo) ) {
717       yamlize(*this, Val, Required, Ctx);
718       this->postflightKey(SaveInfo);
719     }
720     else {
721       if ( UseDefault )
722         Val = DefaultValue;
723     }
724   }
725
726   template <typename T, typename Context>
727   void processKey(const char *Key, T &Val, bool Required, Context &Ctx) {
728     void *SaveInfo;
729     bool UseDefault;
730     if ( this->preflightKey(Key, Required, false, UseDefault, SaveInfo) ) {
731       yamlize(*this, Val, Required, Ctx);
732       this->postflightKey(SaveInfo);
733     }
734   }
735
736 private:
737   void *Ctxt;
738 };
739
740 namespace detail {
741
742 template <typename T, typename Context>
743 void doMapping(IO &io, T &Val, Context &Ctx) {
744   MappingContextTraits<T, Context>::mapping(io, Val, Ctx);
745 }
746
747 template <typename T> void doMapping(IO &io, T &Val, EmptyContext &Ctx) {
748   MappingTraits<T>::mapping(io, Val);
749 }
750
751 } // end namespace detail
752
753 template <typename T>
754 typename std::enable_if<has_ScalarEnumerationTraits<T>::value, void>::type
755 yamlize(IO &io, T &Val, bool, EmptyContext &Ctx) {
756   io.beginEnumScalar();
757   ScalarEnumerationTraits<T>::enumeration(io, Val);
758   io.endEnumScalar();
759 }
760
761 template <typename T>
762 typename std::enable_if<has_ScalarBitSetTraits<T>::value, void>::type
763 yamlize(IO &io, T &Val, bool, EmptyContext &Ctx) {
764   bool DoClear;
765   if ( io.beginBitSetScalar(DoClear) ) {
766     if ( DoClear )
767       Val = static_cast<T>(0);
768     ScalarBitSetTraits<T>::bitset(io, Val);
769     io.endBitSetScalar();
770   }
771 }
772
773 template <typename T>
774 typename std::enable_if<has_ScalarTraits<T>::value, void>::type
775 yamlize(IO &io, T &Val, bool, EmptyContext &Ctx) {
776   if ( io.outputting() ) {
777     std::string Storage;
778     raw_string_ostream Buffer(Storage);
779     ScalarTraits<T>::output(Val, io.getContext(), Buffer);
780     StringRef Str = Buffer.str();
781     io.scalarString(Str, ScalarTraits<T>::mustQuote(Str));
782   }
783   else {
784     StringRef Str;
785     io.scalarString(Str, ScalarTraits<T>::mustQuote(Str));
786     StringRef Result = ScalarTraits<T>::input(Str, io.getContext(), Val);
787     if ( !Result.empty() ) {
788       io.setError(Twine(Result));
789     }
790   }
791 }
792
793 template <typename T>
794 typename std::enable_if<has_BlockScalarTraits<T>::value, void>::type
795 yamlize(IO &YamlIO, T &Val, bool, EmptyContext &Ctx) {
796   if (YamlIO.outputting()) {
797     std::string Storage;
798     raw_string_ostream Buffer(Storage);
799     BlockScalarTraits<T>::output(Val, YamlIO.getContext(), Buffer);
800     StringRef Str = Buffer.str();
801     YamlIO.blockScalarString(Str);
802   } else {
803     StringRef Str;
804     YamlIO.blockScalarString(Str);
805     StringRef Result =
806         BlockScalarTraits<T>::input(Str, YamlIO.getContext(), Val);
807     if (!Result.empty())
808       YamlIO.setError(Twine(Result));
809   }
810 }
811
812 template <typename T, typename Context>
813 typename std::enable_if<validatedMappingTraits<T, Context>::value, void>::type
814 yamlize(IO &io, T &Val, bool, Context &Ctx) {
815   if (has_FlowTraits<MappingTraits<T>>::value)
816     io.beginFlowMapping();
817   else
818     io.beginMapping();
819   if (io.outputting()) {
820     StringRef Err = MappingTraits<T>::validate(io, Val);
821     if (!Err.empty()) {
822       errs() << Err << "\n";
823       assert(Err.empty() && "invalid struct trying to be written as yaml");
824     }
825   }
826   detail::doMapping(io, Val, Ctx);
827   if (!io.outputting()) {
828     StringRef Err = MappingTraits<T>::validate(io, Val);
829     if (!Err.empty())
830       io.setError(Err);
831   }
832   if (has_FlowTraits<MappingTraits<T>>::value)
833     io.endFlowMapping();
834   else
835     io.endMapping();
836 }
837
838 template <typename T, typename Context>
839 typename std::enable_if<unvalidatedMappingTraits<T, Context>::value, void>::type
840 yamlize(IO &io, T &Val, bool, Context &Ctx) {
841   if (has_FlowTraits<MappingTraits<T>>::value) {
842     io.beginFlowMapping();
843     detail::doMapping(io, Val, Ctx);
844     io.endFlowMapping();
845   } else {
846     io.beginMapping();
847     detail::doMapping(io, Val, Ctx);
848     io.endMapping();
849   }
850 }
851
852 template <typename T>
853 typename std::enable_if<has_CustomMappingTraits<T>::value, void>::type
854 yamlize(IO &io, T &Val, bool, EmptyContext &Ctx) {
855   if ( io.outputting() ) {
856     io.beginMapping();
857     CustomMappingTraits<T>::output(io, Val);
858     io.endMapping();
859   } else {
860     io.beginMapping();
861     for (StringRef key : io.keys())
862       CustomMappingTraits<T>::inputOne(io, key, Val);
863     io.endMapping();
864   }
865 }
866
867 template <typename T>
868 typename std::enable_if<missingTraits<T, EmptyContext>::value, void>::type
869 yamlize(IO &io, T &Val, bool, EmptyContext &Ctx) {
870   char missing_yaml_trait_for_type[sizeof(MissingTrait<T>)];
871 }
872
873 template <typename T, typename Context>
874 typename std::enable_if<has_SequenceTraits<T>::value, void>::type
875 yamlize(IO &io, T &Seq, bool, Context &Ctx) {
876   if ( has_FlowTraits< SequenceTraits<T>>::value ) {
877     unsigned incnt = io.beginFlowSequence();
878     unsigned count = io.outputting() ? SequenceTraits<T>::size(io, Seq) : incnt;
879     for(unsigned i=0; i < count; ++i) {
880       void *SaveInfo;
881       if ( io.preflightFlowElement(i, SaveInfo) ) {
882         yamlize(io, SequenceTraits<T>::element(io, Seq, i), true, Ctx);
883         io.postflightFlowElement(SaveInfo);
884       }
885     }
886     io.endFlowSequence();
887   }
888   else {
889     unsigned incnt = io.beginSequence();
890     unsigned count = io.outputting() ? SequenceTraits<T>::size(io, Seq) : incnt;
891     for(unsigned i=0; i < count; ++i) {
892       void *SaveInfo;
893       if ( io.preflightElement(i, SaveInfo) ) {
894         yamlize(io, SequenceTraits<T>::element(io, Seq, i), true, Ctx);
895         io.postflightElement(SaveInfo);
896       }
897     }
898     io.endSequence();
899   }
900 }
901
902 template<>
903 struct ScalarTraits<bool> {
904   static void output(const bool &, void* , raw_ostream &);
905   static StringRef input(StringRef, void *, bool &);
906   static bool mustQuote(StringRef) { return false; }
907 };
908
909 template<>
910 struct ScalarTraits<StringRef> {
911   static void output(const StringRef &, void *, raw_ostream &);
912   static StringRef input(StringRef, void *, StringRef &);
913   static bool mustQuote(StringRef S) { return needsQuotes(S); }
914 };
915
916 template<>
917 struct ScalarTraits<std::string> {
918   static void output(const std::string &, void *, raw_ostream &);
919   static StringRef input(StringRef, void *, std::string &);
920   static bool mustQuote(StringRef S) { return needsQuotes(S); }
921 };
922
923 template<>
924 struct ScalarTraits<uint8_t> {
925   static void output(const uint8_t &, void *, raw_ostream &);
926   static StringRef input(StringRef, void *, uint8_t &);
927   static bool mustQuote(StringRef) { return false; }
928 };
929
930 template<>
931 struct ScalarTraits<uint16_t> {
932   static void output(const uint16_t &, void *, raw_ostream &);
933   static StringRef input(StringRef, void *, uint16_t &);
934   static bool mustQuote(StringRef) { return false; }
935 };
936
937 template<>
938 struct ScalarTraits<uint32_t> {
939   static void output(const uint32_t &, void *, raw_ostream &);
940   static StringRef input(StringRef, void *, uint32_t &);
941   static bool mustQuote(StringRef) { return false; }
942 };
943
944 template<>
945 struct ScalarTraits<uint64_t> {
946   static void output(const uint64_t &, void *, raw_ostream &);
947   static StringRef input(StringRef, void *, uint64_t &);
948   static bool mustQuote(StringRef) { return false; }
949 };
950
951 template<>
952 struct ScalarTraits<int8_t> {
953   static void output(const int8_t &, void *, raw_ostream &);
954   static StringRef input(StringRef, void *, int8_t &);
955   static bool mustQuote(StringRef) { return false; }
956 };
957
958 template<>
959 struct ScalarTraits<int16_t> {
960   static void output(const int16_t &, void *, raw_ostream &);
961   static StringRef input(StringRef, void *, int16_t &);
962   static bool mustQuote(StringRef) { return false; }
963 };
964
965 template<>
966 struct ScalarTraits<int32_t> {
967   static void output(const int32_t &, void *, raw_ostream &);
968   static StringRef input(StringRef, void *, int32_t &);
969   static bool mustQuote(StringRef) { return false; }
970 };
971
972 template<>
973 struct ScalarTraits<int64_t> {
974   static void output(const int64_t &, void *, raw_ostream &);
975   static StringRef input(StringRef, void *, int64_t &);
976   static bool mustQuote(StringRef) { return false; }
977 };
978
979 template<>
980 struct ScalarTraits<float> {
981   static void output(const float &, void *, raw_ostream &);
982   static StringRef input(StringRef, void *, float &);
983   static bool mustQuote(StringRef) { return false; }
984 };
985
986 template<>
987 struct ScalarTraits<double> {
988   static void output(const double &, void *, raw_ostream &);
989   static StringRef input(StringRef, void *, double &);
990   static bool mustQuote(StringRef) { return false; }
991 };
992
993 // For endian types, we just use the existing ScalarTraits for the underlying
994 // type.  This way endian aware types are supported whenever a ScalarTraits
995 // is defined for the underlying type.
996 template <typename value_type, support::endianness endian, size_t alignment>
997 struct ScalarTraits<support::detail::packed_endian_specific_integral<
998     value_type, endian, alignment>> {
999   using endian_type =
1000       support::detail::packed_endian_specific_integral<value_type, endian,
1001                                                        alignment>;
1002
1003   static void output(const endian_type &E, void *Ctx, raw_ostream &Stream) {
1004     ScalarTraits<value_type>::output(static_cast<value_type>(E), Ctx, Stream);
1005   }
1006
1007   static StringRef input(StringRef Str, void *Ctx, endian_type &E) {
1008     value_type V;
1009     auto R = ScalarTraits<value_type>::input(Str, Ctx, V);
1010     E = static_cast<endian_type>(V);
1011     return R;
1012   }
1013
1014   static bool mustQuote(StringRef Str) {
1015     return ScalarTraits<value_type>::mustQuote(Str);
1016   }
1017 };
1018
1019 // Utility for use within MappingTraits<>::mapping() method
1020 // to [de]normalize an object for use with YAML conversion.
1021 template <typename TNorm, typename TFinal>
1022 struct MappingNormalization {
1023   MappingNormalization(IO &i_o, TFinal &Obj)
1024       : io(i_o), BufPtr(nullptr), Result(Obj) {
1025     if ( io.outputting() ) {
1026       BufPtr = new (&Buffer) TNorm(io, Obj);
1027     }
1028     else {
1029       BufPtr = new (&Buffer) TNorm(io);
1030     }
1031   }
1032
1033   ~MappingNormalization() {
1034     if ( ! io.outputting() ) {
1035       Result = BufPtr->denormalize(io);
1036     }
1037     BufPtr->~TNorm();
1038   }
1039
1040   TNorm* operator->() { return BufPtr; }
1041
1042 private:
1043   using Storage = AlignedCharArrayUnion<TNorm>;
1044
1045   Storage       Buffer;
1046   IO           &io;
1047   TNorm        *BufPtr;
1048   TFinal       &Result;
1049 };
1050
1051 // Utility for use within MappingTraits<>::mapping() method
1052 // to [de]normalize an object for use with YAML conversion.
1053 template <typename TNorm, typename TFinal>
1054 struct MappingNormalizationHeap {
1055   MappingNormalizationHeap(IO &i_o, TFinal &Obj, BumpPtrAllocator *allocator)
1056     : io(i_o), 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   using Storage = AlignedCharArrayUnion<TNorm>;
1081
1082   Storage       Buffer;
1083   IO           &io;
1084   TNorm        *BufPtr = nullptr;
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     using NameToNode = StringMap<std::unique_ptr<HNode>>;
1201
1202     NameToNode Mapping;
1203     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   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   BumpPtrAllocator                    StringAllocator;
1240   document_iterator                   DocIterator;
1241   std::vector<bool>                   BitValuesUsed;
1242   HNode *CurrentNode = nullptr;
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(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   raw_ostream &Out;
1316   int WrapColumn;
1317   SmallVector<InState, 8> StateStack;
1318   int Column = 0;
1319   int ColumnAtFlowStart = 0;
1320   int ColumnAtMapFlowStart = 0;
1321   bool NeedBitValueComma = false;
1322   bool NeedFlowSequenceComma = false;
1323   bool EnumerationMatchFound = false;
1324   bool NeedsNewLine = false;
1325   bool WriteDefaultValues = false;
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         using BaseType = _base;                                                \
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 *, 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 *, 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 *, 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 *, 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   using _type = typename T::value_type;
1549
1550   static size_t size(IO &io, T &seq) { return seq.size(); }
1551
1552   static _type &element(IO &io, T &seq, size_t index) {
1553     if (index >= seq.size())
1554       seq.resize(index + 1);
1555     return seq[index];
1556   }
1557 };
1558
1559 /// Implementation of CustomMappingTraits for std::map<std::string, T>.
1560 template <typename T> struct StdMapStringCustomMappingTraitsImpl {
1561   using map_type = std::map<std::string, T>;
1562
1563   static void inputOne(IO &io, StringRef key, map_type &v) {
1564     io.mapRequired(key.str().c_str(), v[key]);
1565   }
1566
1567   static void output(IO &io, map_type &v) {
1568     for (auto &p : v)
1569       io.mapRequired(p.first.c_str(), p.second);
1570   }
1571 };
1572
1573 } // end namespace yaml
1574 } // end namespace llvm
1575
1576 /// Utility for declaring that a std::vector of a particular type
1577 /// should be considered a YAML sequence.
1578 #define LLVM_YAML_IS_SEQUENCE_VECTOR(_type)                                    \
1579   namespace llvm {                                                             \
1580   namespace yaml {                                                             \
1581   template <>                                                                  \
1582   struct SequenceTraits<std::vector<_type>>                                    \
1583       : public SequenceTraitsImpl<std::vector<_type>> {};                      \
1584   template <unsigned N>                                                        \
1585   struct SequenceTraits<SmallVector<_type, N>>                                 \
1586       : public SequenceTraitsImpl<SmallVector<_type, N>> {};                   \
1587   }                                                                            \
1588   }
1589
1590 /// Utility for declaring that a std::vector of a particular type
1591 /// should be considered a YAML flow sequence.
1592 /// We need to do a partial specialization on the vector version, not a full.
1593 /// If this is a full specialization, the compiler is a bit too "smart" and
1594 /// decides to warn on -Wunused-const-variable.  This workaround can be
1595 /// removed and we can do a full specialization on std::vector<T> once
1596 /// PR28878 is fixed.
1597 #define LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(_type)                               \
1598   namespace llvm {                                                             \
1599   namespace yaml {                                                             \
1600   template <unsigned N>                                                        \
1601   struct SequenceTraits<SmallVector<_type, N>>                                 \
1602       : public SequenceTraitsImpl<SmallVector<_type, N>> {                     \
1603     static const bool flow = true;                                             \
1604   };                                                                           \
1605   template <typename Allocator>                                                \
1606   struct SequenceTraits<std::vector<_type, Allocator>>                         \
1607       : public SequenceTraitsImpl<std::vector<_type, Allocator>> {             \
1608     static const bool flow = true;                                             \
1609   };                                                                           \
1610   }                                                                            \
1611   }
1612
1613 #define LLVM_YAML_DECLARE_MAPPING_TRAITS(Type)                                 \
1614   namespace llvm {                                                             \
1615   namespace yaml {                                                             \
1616   template <> struct MappingTraits<Type> {                                     \
1617     static void mapping(IO &IO, Type &Obj);                                    \
1618   };                                                                           \
1619   }                                                                            \
1620   }
1621
1622 #define LLVM_YAML_DECLARE_ENUM_TRAITS(Type)                                    \
1623   namespace llvm {                                                             \
1624   namespace yaml {                                                             \
1625   template <> struct ScalarEnumerationTraits<Type> {                           \
1626     static void enumeration(IO &io, Type &Value);                              \
1627   };                                                                           \
1628   }                                                                            \
1629   }
1630
1631 #define LLVM_YAML_DECLARE_BITSET_TRAITS(Type)                                  \
1632   namespace llvm {                                                             \
1633   namespace yaml {                                                             \
1634   template <> struct ScalarBitSetTraits<Type> {                                \
1635     static void bitset(IO &IO, Type &Options);                                 \
1636   };                                                                           \
1637   }                                                                            \
1638   }
1639
1640 #define LLVM_YAML_DECLARE_SCALAR_TRAITS(Type, MustQuote)                       \
1641   namespace llvm {                                                             \
1642   namespace yaml {                                                             \
1643   template <> struct ScalarTraits<Type> {                                      \
1644     static void output(const Type &Value, void *ctx, raw_ostream &Out);        \
1645     static StringRef input(StringRef Scalar, void *ctxt, Type &Value);         \
1646     static bool mustQuote(StringRef) { return MustQuote; }                     \
1647   };                                                                           \
1648   }                                                                            \
1649   }
1650
1651 /// Utility for declaring that a std::vector of a particular type
1652 /// should be considered a YAML document list.
1653 #define LLVM_YAML_IS_DOCUMENT_LIST_VECTOR(_type)                               \
1654   namespace llvm {                                                             \
1655   namespace yaml {                                                             \
1656   template <unsigned N>                                                        \
1657   struct DocumentListTraits<SmallVector<_type, N>>                             \
1658       : public SequenceTraitsImpl<SmallVector<_type, N>> {};                   \
1659   template <>                                                                  \
1660   struct DocumentListTraits<std::vector<_type>>                                \
1661       : public SequenceTraitsImpl<std::vector<_type>> {};                      \
1662   }                                                                            \
1663   }
1664
1665 /// Utility for declaring that std::map<std::string, _type> should be considered
1666 /// a YAML map.
1667 #define LLVM_YAML_IS_STRING_MAP(_type)                                         \
1668   namespace llvm {                                                             \
1669   namespace yaml {                                                             \
1670   template <>                                                                  \
1671   struct CustomMappingTraits<std::map<std::string, _type>>                     \
1672       : public StdMapStringCustomMappingTraitsImpl<_type> {};                  \
1673   }                                                                            \
1674   }
1675
1676 #endif // LLVM_SUPPORT_YAMLTRAITS_H