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