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