LLVM  15.0.0git
YAMLTraits.h
Go to the documentation of this file.
1 //===- llvm/Support/YAMLTraits.h --------------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #ifndef LLVM_SUPPORT_YAMLTRAITS_H
10 #define LLVM_SUPPORT_YAMLTRAITS_H
11 
12 #include "llvm/ADT/BitVector.h"
13 #include "llvm/ADT/Optional.h"
14 #include "llvm/ADT/SmallVector.h"
15 #include "llvm/ADT/StringExtras.h"
16 #include "llvm/ADT/StringMap.h"
17 #include "llvm/ADT/StringRef.h"
18 #include "llvm/ADT/Twine.h"
19 #include "llvm/Support/AlignOf.h"
20 #include "llvm/Support/Allocator.h"
21 #include "llvm/Support/Endian.h"
22 #include "llvm/Support/SMLoc.h"
23 #include "llvm/Support/SourceMgr.h"
26 #include <cassert>
27 #include <map>
28 #include <memory>
29 #include <new>
30 #include <string>
31 #include <system_error>
32 #include <type_traits>
33 #include <vector>
34 
35 namespace llvm {
36 
37 class VersionTuple;
38 
39 namespace yaml {
40 
41 enum class NodeKind : uint8_t {
42  Scalar,
43  Map,
44  Sequence,
45 };
46 
47 struct EmptyContext {};
48 
49 /// This class should be specialized by any type that needs to be converted
50 /// to/from a YAML mapping. For example:
51 ///
52 /// struct MappingTraits<MyStruct> {
53 /// static void mapping(IO &io, MyStruct &s) {
54 /// io.mapRequired("name", s.name);
55 /// io.mapRequired("size", s.size);
56 /// io.mapOptional("age", s.age);
57 /// }
58 /// };
59 template<class T>
60 struct MappingTraits {
61  // Must provide:
62  // static void mapping(IO &io, T &fields);
63  // Optionally may provide:
64  // static std::string validate(IO &io, T &fields);
65  // static void enumInput(IO &io, T &value);
66  //
67  // The optional flow flag will cause generated YAML to use a flow mapping
68  // (e.g. { a: 0, b: 1 }):
69  // static const bool flow = true;
70 };
71 
72 /// This class is similar to MappingTraits<T> but allows you to pass in
73 /// additional context for each map operation. For example:
74 ///
75 /// struct MappingContextTraits<MyStruct, MyContext> {
76 /// static void mapping(IO &io, MyStruct &s, MyContext &c) {
77 /// io.mapRequired("name", s.name);
78 /// io.mapRequired("size", s.size);
79 /// io.mapOptional("age", s.age);
80 /// ++c.TimesMapped;
81 /// }
82 /// };
83 template <class T, class Context> struct MappingContextTraits {
84  // Must provide:
85  // static void mapping(IO &io, T &fields, Context &Ctx);
86  // Optionally may provide:
87  // static std::string validate(IO &io, T &fields, Context &Ctx);
88  //
89  // The optional flow flag will cause generated YAML to use a flow mapping
90  // (e.g. { a: 0, b: 1 }):
91  // static const bool flow = true;
92 };
93 
94 /// This class should be specialized by any integral type that converts
95 /// to/from a YAML scalar where there is a one-to-one mapping between
96 /// in-memory values and a string in YAML. For example:
97 ///
98 /// struct ScalarEnumerationTraits<Colors> {
99 /// static void enumeration(IO &io, Colors &value) {
100 /// io.enumCase(value, "red", cRed);
101 /// io.enumCase(value, "blue", cBlue);
102 /// io.enumCase(value, "green", cGreen);
103 /// }
104 /// };
105 template <typename T, typename Enable = void> struct ScalarEnumerationTraits {
106  // Must provide:
107  // static void enumeration(IO &io, T &value);
108 };
109 
110 /// This class should be specialized by any integer type that is a union
111 /// of bit values and the YAML representation is a flow sequence of
112 /// strings. For example:
113 ///
114 /// struct ScalarBitSetTraits<MyFlags> {
115 /// static void bitset(IO &io, MyFlags &value) {
116 /// io.bitSetCase(value, "big", flagBig);
117 /// io.bitSetCase(value, "flat", flagFlat);
118 /// io.bitSetCase(value, "round", flagRound);
119 /// }
120 /// };
121 template <typename T, typename Enable = void> struct ScalarBitSetTraits {
122  // Must provide:
123  // static void bitset(IO &io, T &value);
124 };
125 
126 /// Describe which type of quotes should be used when quoting is necessary.
127 /// Some non-printable characters need to be double-quoted, while some others
128 /// are fine with simple-quoting, and some don't need any quoting.
129 enum class QuotingType { None, Single, Double };
130 
131 /// This class should be specialized by type that requires custom conversion
132 /// to/from a yaml scalar. For example:
133 ///
134 /// template<>
135 /// struct ScalarTraits<MyType> {
136 /// static void output(const MyType &val, void*, llvm::raw_ostream &out) {
137 /// // stream out custom formatting
138 /// out << llvm::format("%x", val);
139 /// }
140 /// static StringRef input(StringRef scalar, void*, MyType &value) {
141 /// // parse scalar and set `value`
142 /// // return empty string on success, or error string
143 /// return StringRef();
144 /// }
145 /// static QuotingType mustQuote(StringRef) { return QuotingType::Single; }
146 /// };
147 template <typename T, typename Enable = void> struct ScalarTraits {
148  // Must provide:
149  //
150  // Function to write the value as a string:
151  // static void output(const T &value, void *ctxt, llvm::raw_ostream &out);
152  //
153  // Function to convert a string to a value. Returns the empty
154  // StringRef on success or an error string if string is malformed:
155  // static StringRef input(StringRef scalar, void *ctxt, T &value);
156  //
157  // Function to determine if the value should be quoted.
158  // static QuotingType mustQuote(StringRef);
159 };
160 
161 /// This class should be specialized by type that requires custom conversion
162 /// to/from a YAML literal block scalar. For example:
163 ///
164 /// template <>
165 /// struct BlockScalarTraits<MyType> {
166 /// static void output(const MyType &Value, void*, llvm::raw_ostream &Out)
167 /// {
168 /// // stream out custom formatting
169 /// Out << Value;
170 /// }
171 /// static StringRef input(StringRef Scalar, void*, MyType &Value) {
172 /// // parse scalar and set `value`
173 /// // return empty string on success, or error string
174 /// return StringRef();
175 /// }
176 /// };
177 template <typename T>
178 struct BlockScalarTraits {
179  // Must provide:
180  //
181  // Function to write the value as a string:
182  // static void output(const T &Value, void *ctx, llvm::raw_ostream &Out);
183  //
184  // Function to convert a string to a value. Returns the empty
185  // StringRef on success or an error string if string is malformed:
186  // static StringRef input(StringRef Scalar, void *ctxt, T &Value);
187  //
188  // Optional:
189  // static StringRef inputTag(T &Val, std::string Tag)
190  // static void outputTag(const T &Val, raw_ostream &Out)
191 };
192 
193 /// This class should be specialized by type that requires custom conversion
194 /// to/from a YAML scalar with optional tags. For example:
195 ///
196 /// template <>
197 /// struct TaggedScalarTraits<MyType> {
198 /// static void output(const MyType &Value, void*, llvm::raw_ostream
199 /// &ScalarOut, llvm::raw_ostream &TagOut)
200 /// {
201 /// // stream out custom formatting including optional Tag
202 /// Out << Value;
203 /// }
204 /// static StringRef input(StringRef Scalar, StringRef Tag, void*, MyType
205 /// &Value) {
206 /// // parse scalar and set `value`
207 /// // return empty string on success, or error string
208 /// return StringRef();
209 /// }
210 /// static QuotingType mustQuote(const MyType &Value, StringRef) {
211 /// return QuotingType::Single;
212 /// }
213 /// };
214 template <typename T> struct TaggedScalarTraits {
215  // Must provide:
216  //
217  // Function to write the value and tag as strings:
218  // static void output(const T &Value, void *ctx, llvm::raw_ostream &ScalarOut,
219  // llvm::raw_ostream &TagOut);
220  //
221  // Function to convert a string to a value. Returns the empty
222  // StringRef on success or an error string if string is malformed:
223  // static StringRef input(StringRef Scalar, StringRef Tag, void *ctxt, T
224  // &Value);
225  //
226  // Function to determine if the value should be quoted.
227  // static QuotingType mustQuote(const T &Value, StringRef Scalar);
228 };
229 
230 /// This class should be specialized by any type that needs to be converted
231 /// to/from a YAML sequence. For example:
232 ///
233 /// template<>
234 /// struct SequenceTraits<MyContainer> {
235 /// static size_t size(IO &io, MyContainer &seq) {
236 /// return seq.size();
237 /// }
238 /// static MyType& element(IO &, MyContainer &seq, size_t index) {
239 /// if ( index >= seq.size() )
240 /// seq.resize(index+1);
241 /// return seq[index];
242 /// }
243 /// };
244 template<typename T, typename EnableIf = void>
245 struct SequenceTraits {
246  // Must provide:
247  // static size_t size(IO &io, T &seq);
248  // static T::value_type& element(IO &io, T &seq, size_t index);
249  //
250  // The following is option and will cause generated YAML to use
251  // a flow sequence (e.g. [a,b,c]).
252  // static const bool flow = true;
253 };
254 
255 /// This class should be specialized by any type for which vectors of that
256 /// type need to be converted to/from a YAML sequence.
257 template<typename T, typename EnableIf = void>
258 struct SequenceElementTraits {
259  // Must provide:
260  // static const bool flow;
261 };
262 
263 /// This class should be specialized by any type that needs to be converted
264 /// to/from a list of YAML documents.
265 template<typename T>
266 struct DocumentListTraits {
267  // Must provide:
268  // static size_t size(IO &io, T &seq);
269  // static T::value_type& element(IO &io, T &seq, size_t index);
270 };
271 
272 /// This class should be specialized by any type that needs to be converted
273 /// to/from a YAML mapping in the case where the names of the keys are not known
274 /// in advance, e.g. a string map.
275 template <typename T>
276 struct CustomMappingTraits {
277  // static void inputOne(IO &io, StringRef key, T &elem);
278  // static void output(IO &io, T &elem);
279 };
280 
281 /// This class should be specialized by any type that can be represented as
282 /// a scalar, map, or sequence, decided dynamically. For example:
283 ///
284 /// typedef std::unique_ptr<MyBase> MyPoly;
285 ///
286 /// template<>
287 /// struct PolymorphicTraits<MyPoly> {
288 /// static NodeKind getKind(const MyPoly &poly) {
289 /// return poly->getKind();
290 /// }
291 /// static MyScalar& getAsScalar(MyPoly &poly) {
292 /// if (!poly || !isa<MyScalar>(poly))
293 /// poly.reset(new MyScalar());
294 /// return *cast<MyScalar>(poly.get());
295 /// }
296 /// // ...
297 /// };
298 template <typename T> struct PolymorphicTraits {
299  // Must provide:
300  // static NodeKind getKind(const T &poly);
301  // static scalar_type &getAsScalar(T &poly);
302  // static map_type &getAsMap(T &poly);
303  // static sequence_type &getAsSequence(T &poly);
304 };
305 
306 // Only used for better diagnostics of missing traits
307 template <typename T>
308 struct MissingTrait;
309 
310 // Test if ScalarEnumerationTraits<T> is defined on type T.
311 template <class T>
312 struct has_ScalarEnumerationTraits
313 {
314  using Signature_enumeration = void (*)(class IO&, T&);
315 
316  template <typename U>
317  static char test(SameType<Signature_enumeration, &U::enumeration>*);
318 
319  template <typename U>
320  static double test(...);
321 
322  static bool const value =
323  (sizeof(test<ScalarEnumerationTraits<T>>(nullptr)) == 1);
324 };
325 
326 // Test if ScalarBitSetTraits<T> is defined on type T.
327 template <class T>
328 struct has_ScalarBitSetTraits
329 {
330  using Signature_bitset = void (*)(class IO&, T&);
331 
332  template <typename U>
333  static char test(SameType<Signature_bitset, &U::bitset>*);
334 
335  template <typename U>
336  static double test(...);
337 
338  static bool const value = (sizeof(test<ScalarBitSetTraits<T>>(nullptr)) == 1);
339 };
340 
341 // Test if ScalarTraits<T> is defined on type T.
342 template <class T>
343 struct has_ScalarTraits
344 {
345  using Signature_input = StringRef (*)(StringRef, void*, T&);
346  using Signature_output = void (*)(const T&, void*, raw_ostream&);
347  using Signature_mustQuote = QuotingType (*)(StringRef);
348 
349  template <typename U>
350  static char test(SameType<Signature_input, &U::input> *,
351  SameType<Signature_output, &U::output> *,
352  SameType<Signature_mustQuote, &U::mustQuote> *);
353 
354  template <typename U>
355  static double test(...);
356 
357  static bool const value =
358  (sizeof(test<ScalarTraits<T>>(nullptr, nullptr, nullptr)) == 1);
359 };
360 
361 // Test if BlockScalarTraits<T> is defined on type T.
362 template <class T>
363 struct has_BlockScalarTraits
364 {
365  using Signature_input = StringRef (*)(StringRef, void *, T &);
366  using Signature_output = void (*)(const T &, void *, raw_ostream &);
367 
368  template <typename U>
369  static char test(SameType<Signature_input, &U::input> *,
370  SameType<Signature_output, &U::output> *);
371 
372  template <typename U>
373  static double test(...);
374 
375  static bool const value =
376  (sizeof(test<BlockScalarTraits<T>>(nullptr, nullptr)) == 1);
377 };
378 
379 // Test if TaggedScalarTraits<T> is defined on type T.
380 template <class T> struct has_TaggedScalarTraits {
381  using Signature_input = StringRef (*)(StringRef, StringRef, void *, T &);
382  using Signature_output = void (*)(const T &, void *, raw_ostream &,
383  raw_ostream &);
384  using Signature_mustQuote = QuotingType (*)(const T &, StringRef);
385 
386  template <typename U>
387  static char test(SameType<Signature_input, &U::input> *,
388  SameType<Signature_output, &U::output> *,
389  SameType<Signature_mustQuote, &U::mustQuote> *);
390 
391  template <typename U> static double test(...);
392 
393  static bool const value =
394  (sizeof(test<TaggedScalarTraits<T>>(nullptr, nullptr, nullptr)) == 1);
395 };
396 
397 // Test if MappingContextTraits<T> is defined on type T.
398 template <class T, class Context> struct has_MappingTraits {
399  using Signature_mapping = void (*)(class IO &, T &, Context &);
400 
401  template <typename U>
402  static char test(SameType<Signature_mapping, &U::mapping>*);
403 
404  template <typename U>
405  static double test(...);
406 
407  static bool const value =
408  (sizeof(test<MappingContextTraits<T, Context>>(nullptr)) == 1);
409 };
410 
411 // Test if MappingTraits<T> is defined on type T.
412 template <class T> struct has_MappingTraits<T, EmptyContext> {
413  using Signature_mapping = void (*)(class IO &, T &);
414 
415  template <typename U>
416  static char test(SameType<Signature_mapping, &U::mapping> *);
417 
418  template <typename U> static double test(...);
419 
420  static bool const value = (sizeof(test<MappingTraits<T>>(nullptr)) == 1);
421 };
422 
423 // Test if MappingContextTraits<T>::validate() is defined on type T.
424 template <class T, class Context> struct has_MappingValidateTraits {
425  using Signature_validate = std::string (*)(class IO &, T &, Context &);
426 
427  template <typename U>
428  static char test(SameType<Signature_validate, &U::validate>*);
429 
430  template <typename U>
431  static double test(...);
432 
433  static bool const value =
434  (sizeof(test<MappingContextTraits<T, Context>>(nullptr)) == 1);
435 };
436 
437 // Test if MappingTraits<T>::validate() is defined on type T.
438 template <class T> struct has_MappingValidateTraits<T, EmptyContext> {
439  using Signature_validate = std::string (*)(class IO &, T &);
440 
441  template <typename U>
442  static char test(SameType<Signature_validate, &U::validate> *);
443 
444  template <typename U> static double test(...);
445 
446  static bool const value = (sizeof(test<MappingTraits<T>>(nullptr)) == 1);
447 };
448 
449 // Test if MappingContextTraits<T>::enumInput() is defined on type T.
450 template <class T, class Context> struct has_MappingEnumInputTraits {
451  using Signature_validate = void (*)(class IO &, T &);
452 
453  template <typename U>
454  static char test(SameType<Signature_validate, &U::enumInput> *);
455 
456  template <typename U> static double test(...);
457 
458  static bool const value =
459  (sizeof(test<MappingContextTraits<T, Context>>(nullptr)) == 1);
460 };
461 
462 // Test if MappingTraits<T>::enumInput() is defined on type T.
463 template <class T> struct has_MappingEnumInputTraits<T, EmptyContext> {
464  using Signature_validate = void (*)(class IO &, T &);
465 
466  template <typename U>
467  static char test(SameType<Signature_validate, &U::enumInput> *);
468 
469  template <typename U> static double test(...);
470 
471  static bool const value = (sizeof(test<MappingTraits<T>>(nullptr)) == 1);
472 };
473 
474 // Test if SequenceTraits<T> is defined on type T.
475 template <class T>
476 struct has_SequenceMethodTraits
477 {
478  using Signature_size = size_t (*)(class IO&, T&);
479 
480  template <typename U>
481  static char test(SameType<Signature_size, &U::size>*);
482 
483  template <typename U>
484  static double test(...);
485 
486  static bool const value = (sizeof(test<SequenceTraits<T>>(nullptr)) == 1);
487 };
488 
489 // Test if CustomMappingTraits<T> is defined on type T.
490 template <class T>
491 struct has_CustomMappingTraits
492 {
493  using Signature_input = void (*)(IO &io, StringRef key, T &v);
494 
495  template <typename U>
496  static char test(SameType<Signature_input, &U::inputOne>*);
497 
498  template <typename U>
499  static double test(...);
500 
501  static bool const value =
502  (sizeof(test<CustomMappingTraits<T>>(nullptr)) == 1);
503 };
504 
505 // has_FlowTraits<int> will cause an error with some compilers because
506 // it subclasses int. Using this wrapper only instantiates the
507 // real has_FlowTraits only if the template type is a class.
508 template <typename T, bool Enabled = std::is_class<T>::value>
509 class has_FlowTraits
510 {
511 public:
512  static const bool value = false;
513 };
514 
515 // Some older gcc compilers don't support straight forward tests
516 // for members, so test for ambiguity cause by the base and derived
517 // classes both defining the member.
518 template <class T>
519 struct has_FlowTraits<T, true>
520 {
521  struct Fallback { bool flow; };
522  struct Derived : T, Fallback { };
523 
524  template<typename C>
525  static char (&f(SameType<bool Fallback::*, &C::flow>*))[1];
526 
527  template<typename C>
528  static char (&f(...))[2];
529 
530  static bool const value = sizeof(f<Derived>(nullptr)) == 2;
531 };
532 
533 // Test if SequenceTraits<T> is defined on type T
534 template<typename T>
535 struct has_SequenceTraits : public std::integral_constant<bool,
536  has_SequenceMethodTraits<T>::value > { };
537 
538 // Test if DocumentListTraits<T> is defined on type T
539 template <class T>
540 struct has_DocumentListTraits
541 {
542  using Signature_size = size_t (*)(class IO &, T &);
543 
544  template <typename U>
545  static char test(SameType<Signature_size, &U::size>*);
546 
547  template <typename U>
548  static double test(...);
549 
550  static bool const value = (sizeof(test<DocumentListTraits<T>>(nullptr))==1);
551 };
552 
553 template <class T> struct has_PolymorphicTraits {
554  using Signature_getKind = NodeKind (*)(const T &);
555 
556  template <typename U>
557  static char test(SameType<Signature_getKind, &U::getKind> *);
558 
559  template <typename U> static double test(...);
560 
561  static bool const value = (sizeof(test<PolymorphicTraits<T>>(nullptr)) == 1);
562 };
563 
564 inline bool isNumeric(StringRef S) {
565  const auto skipDigits = [](StringRef Input) {
566  return Input.ltrim("0123456789");
567  };
568 
569  // Make S.front() and S.drop_front().front() (if S.front() is [+-]) calls
570  // safe.
571  if (S.empty() || S.equals("+") || S.equals("-"))
572  return false;
573 
574  if (S.equals(".nan") || S.equals(".NaN") || S.equals(".NAN"))
575  return true;
576 
577  // Infinity and decimal numbers can be prefixed with sign.
578  StringRef Tail = (S.front() == '-' || S.front() == '+') ? S.drop_front() : S;
579 
580  // Check for infinity first, because checking for hex and oct numbers is more
581  // expensive.
582  if (Tail.equals(".inf") || Tail.equals(".Inf") || Tail.equals(".INF"))
583  return true;
584 
585  // Section 10.3.2 Tag Resolution
586  // YAML 1.2 Specification prohibits Base 8 and Base 16 numbers prefixed with
587  // [-+], so S should be used instead of Tail.
588  if (S.startswith("0o"))
589  return S.size() > 2 &&
590  S.drop_front(2).find_first_not_of("01234567") == StringRef::npos;
591 
592  if (S.startswith("0x"))
593  return S.size() > 2 && S.drop_front(2).find_first_not_of(
594  "0123456789abcdefABCDEF") == StringRef::npos;
595 
596  // Parse float: [-+]? (\. [0-9]+ | [0-9]+ (\. [0-9]* )?) ([eE] [-+]? [0-9]+)?
597  S = Tail;
598 
599  // Handle cases when the number starts with '.' and hence needs at least one
600  // digit after dot (as opposed by number which has digits before the dot), but
601  // doesn't have one.
602  if (S.startswith(".") &&
603  (S.equals(".") ||
604  (S.size() > 1 && std::strchr("0123456789", S[1]) == nullptr)))
605  return false;
606 
607  if (S.startswith("E") || S.startswith("e"))
608  return false;
609 
610  enum ParseState {
611  Default,
612  FoundDot,
613  FoundExponent,
614  };
615  ParseState State = Default;
616 
617  S = skipDigits(S);
618 
619  // Accept decimal integer.
620  if (S.empty())
621  return true;
622 
623  if (S.front() == '.') {
624  State = FoundDot;
625  S = S.drop_front();
626  } else if (S.front() == 'e' || S.front() == 'E') {
627  State = FoundExponent;
628  S = S.drop_front();
629  } else {
630  return false;
631  }
632 
633  if (State == FoundDot) {
634  S = skipDigits(S);
635  if (S.empty())
636  return true;
637 
638  if (S.front() == 'e' || S.front() == 'E') {
639  State = FoundExponent;
640  S = S.drop_front();
641  } else {
642  return false;
643  }
644  }
645 
646  assert(State == FoundExponent && "Should have found exponent at this point.");
647  if (S.empty())
648  return false;
649 
650  if (S.front() == '+' || S.front() == '-') {
651  S = S.drop_front();
652  if (S.empty())
653  return false;
654  }
655 
656  return skipDigits(S).empty();
657 }
658 
659 inline bool isNull(StringRef S) {
660  return S.equals("null") || S.equals("Null") || S.equals("NULL") ||
661  S.equals("~");
662 }
663 
664 inline bool isBool(StringRef S) {
665  // FIXME: using parseBool is causing multiple tests to fail.
666  return S.equals("true") || S.equals("True") || S.equals("TRUE") ||
667  S.equals("false") || S.equals("False") || S.equals("FALSE");
668 }
669 
670 // 5.1. Character Set
671 // The allowed character range explicitly excludes the C0 control block #x0-#x1F
672 // (except for TAB #x9, LF #xA, and CR #xD which are allowed), DEL #x7F, the C1
673 // control block #x80-#x9F (except for NEL #x85 which is allowed), the surrogate
674 // block #xD800-#xDFFF, #xFFFE, and #xFFFF.
675 inline QuotingType needsQuotes(StringRef S) {
676  if (S.empty())
677  return QuotingType::Single;
678 
679  QuotingType MaxQuotingNeeded = QuotingType::None;
680  if (isSpace(static_cast<unsigned char>(S.front())) ||
681  isSpace(static_cast<unsigned char>(S.back())))
682  MaxQuotingNeeded = QuotingType::Single;
683  if (isNull(S))
684  MaxQuotingNeeded = QuotingType::Single;
685  if (isBool(S))
686  MaxQuotingNeeded = QuotingType::Single;
687  if (isNumeric(S))
688  MaxQuotingNeeded = QuotingType::Single;
689 
690  // 7.3.3 Plain Style
691  // Plain scalars must not begin with most indicators, as this would cause
692  // ambiguity with other YAML constructs.
693  if (std::strchr(R"(-?:\,[]{}#&*!|>'"%@`)", S[0]) != nullptr)
694  MaxQuotingNeeded = QuotingType::Single;
695 
696  for (unsigned char C : S) {
697  // Alphanum is safe.
698  if (isAlnum(C))
699  continue;
700 
701  switch (C) {
702  // Safe scalar characters.
703  case '_':
704  case '-':
705  case '^':
706  case '.':
707  case ',':
708  case ' ':
709  // TAB (0x9) is allowed in unquoted strings.
710  case 0x9:
711  continue;
712  // LF(0xA) and CR(0xD) may delimit values and so require at least single
713  // quotes. LLVM YAML parser cannot handle single quoted multiline so use
714  // double quoting to produce valid YAML.
715  case 0xA:
716  case 0xD:
717  return QuotingType::Double;
718  // DEL (0x7F) are excluded from the allowed character range.
719  case 0x7F:
720  return QuotingType::Double;
721  // Forward slash is allowed to be unquoted, but we quote it anyway. We have
722  // many tests that use FileCheck against YAML output, and this output often
723  // contains paths. If we quote backslashes but not forward slashes then
724  // paths will come out either quoted or unquoted depending on which platform
725  // the test is run on, making FileCheck comparisons difficult.
726  case '/':
727  default: {
728  // C0 control block (0x0 - 0x1F) is excluded from the allowed character
729  // range.
730  if (C <= 0x1F)
731  return QuotingType::Double;
732 
733  // Always double quote UTF-8.
734  if ((C & 0x80) != 0)
735  return QuotingType::Double;
736 
737  // The character is not safe, at least simple quoting needed.
738  MaxQuotingNeeded = QuotingType::Single;
739  }
740  }
741  }
742 
743  return MaxQuotingNeeded;
744 }
745 
746 template <typename T, typename Context>
747 struct missingTraits
748  : public std::integral_constant<bool,
749  !has_ScalarEnumerationTraits<T>::value &&
750  !has_ScalarBitSetTraits<T>::value &&
751  !has_ScalarTraits<T>::value &&
752  !has_BlockScalarTraits<T>::value &&
753  !has_TaggedScalarTraits<T>::value &&
754  !has_MappingTraits<T, Context>::value &&
755  !has_SequenceTraits<T>::value &&
756  !has_CustomMappingTraits<T>::value &&
757  !has_DocumentListTraits<T>::value &&
758  !has_PolymorphicTraits<T>::value> {};
759 
760 template <typename T, typename Context>
761 struct validatedMappingTraits
762  : public std::integral_constant<
763  bool, has_MappingTraits<T, Context>::value &&
764  has_MappingValidateTraits<T, Context>::value> {};
765 
766 template <typename T, typename Context>
767 struct unvalidatedMappingTraits
768  : public std::integral_constant<
769  bool, has_MappingTraits<T, Context>::value &&
770  !has_MappingValidateTraits<T, Context>::value> {};
771 
772 // Base class for Input and Output.
773 class IO {
774 public:
775  IO(void *Ctxt = nullptr);
776  virtual ~IO();
777 
778  virtual bool outputting() const = 0;
779 
780  virtual unsigned beginSequence() = 0;
781  virtual bool preflightElement(unsigned, void *&) = 0;
782  virtual void postflightElement(void*) = 0;
783  virtual void endSequence() = 0;
784  virtual bool canElideEmptySequence() = 0;
785 
786  virtual unsigned beginFlowSequence() = 0;
787  virtual bool preflightFlowElement(unsigned, void *&) = 0;
788  virtual void postflightFlowElement(void*) = 0;
789  virtual void endFlowSequence() = 0;
790 
791  virtual bool mapTag(StringRef Tag, bool Default=false) = 0;
792  virtual void beginMapping() = 0;
793  virtual void endMapping() = 0;
794  virtual bool preflightKey(const char*, bool, bool, bool &, void *&) = 0;
795  virtual void postflightKey(void*) = 0;
796  virtual std::vector<StringRef> keys() = 0;
797 
798  virtual void beginFlowMapping() = 0;
799  virtual void endFlowMapping() = 0;
800 
801  virtual void beginEnumScalar() = 0;
802  virtual bool matchEnumScalar(const char*, bool) = 0;
803  virtual bool matchEnumFallback() = 0;
804  virtual void endEnumScalar() = 0;
805 
806  virtual bool beginBitSetScalar(bool &) = 0;
807  virtual bool bitSetMatch(const char*, bool) = 0;
808  virtual void endBitSetScalar() = 0;
809 
810  virtual void scalarString(StringRef &, QuotingType) = 0;
811  virtual void blockScalarString(StringRef &) = 0;
812  virtual void scalarTag(std::string &) = 0;
813 
814  virtual NodeKind getNodeKind() = 0;
815 
816  virtual void setError(const Twine &) = 0;
817  virtual void setAllowUnknownKeys(bool Allow);
818 
819  template <typename T>
820  void enumCase(T &Val, const char* Str, const T ConstVal) {
821  if ( matchEnumScalar(Str, outputting() && Val == ConstVal) ) {
822  Val = ConstVal;
823  }
824  }
825 
826  // allow anonymous enum values to be used with LLVM_YAML_STRONG_TYPEDEF
827  template <typename T>
828  void enumCase(T &Val, const char* Str, const uint32_t ConstVal) {
829  if ( matchEnumScalar(Str, outputting() && Val == static_cast<T>(ConstVal)) ) {
830  Val = ConstVal;
831  }
832  }
833 
834  template <typename FBT, typename T>
835  void enumFallback(T &Val) {
836  if (matchEnumFallback()) {
837  EmptyContext Context;
838  // FIXME: Force integral conversion to allow strong typedefs to convert.
839  FBT Res = static_cast<typename FBT::BaseType>(Val);
840  yamlize(*this, Res, true, Context);
841  Val = static_cast<T>(static_cast<typename FBT::BaseType>(Res));
842  }
843  }
844 
845  template <typename T>
846  void bitSetCase(T &Val, const char* Str, const T ConstVal) {
847  if ( bitSetMatch(Str, outputting() && (Val & ConstVal) == ConstVal) ) {
848  Val = static_cast<T>(Val | ConstVal);
849  }
850  }
851 
852  // allow anonymous enum values to be used with LLVM_YAML_STRONG_TYPEDEF
853  template <typename T>
854  void bitSetCase(T &Val, const char* Str, const uint32_t ConstVal) {
855  if ( bitSetMatch(Str, outputting() && (Val & ConstVal) == ConstVal) ) {
856  Val = static_cast<T>(Val | ConstVal);
857  }
858  }
859 
860  template <typename T>
861  void maskedBitSetCase(T &Val, const char *Str, T ConstVal, T Mask) {
862  if (bitSetMatch(Str, outputting() && (Val & Mask) == ConstVal))
863  Val = Val | ConstVal;
864  }
865 
866  template <typename T>
867  void maskedBitSetCase(T &Val, const char *Str, uint32_t ConstVal,
868  uint32_t Mask) {
869  if (bitSetMatch(Str, outputting() && (Val & Mask) == ConstVal))
870  Val = Val | ConstVal;
871  }
872 
873  void *getContext() const;
874  void setContext(void *);
875 
876  template <typename T> void mapRequired(const char *Key, T &Val) {
877  EmptyContext Ctx;
878  this->processKey(Key, Val, true, Ctx);
879  }
880 
881  template <typename T, typename Context>
882  void mapRequired(const char *Key, T &Val, Context &Ctx) {
883  this->processKey(Key, Val, true, Ctx);
884  }
885 
886  template <typename T> void mapOptional(const char *Key, T &Val) {
887  EmptyContext Ctx;
888  mapOptionalWithContext(Key, Val, Ctx);
889  }
890 
891  template <typename T, typename DefaultT>
892  void mapOptional(const char *Key, T &Val, const DefaultT &Default) {
893  EmptyContext Ctx;
894  mapOptionalWithContext(Key, Val, Default, Ctx);
895  }
896 
897  template <typename T, typename Context>
898  std::enable_if_t<has_SequenceTraits<T>::value, void>
899  mapOptionalWithContext(const char *Key, T &Val, Context &Ctx) {
900  // omit key/value instead of outputting empty sequence
901  if (this->canElideEmptySequence() && !(Val.begin() != Val.end()))
902  return;
903  this->processKey(Key, Val, false, Ctx);
904  }
905 
906  template <typename T, typename Context>
907  void mapOptionalWithContext(const char *Key, Optional<T> &Val, Context &Ctx) {
908  this->processKeyWithDefault(Key, Val, Optional<T>(), /*Required=*/false,
909  Ctx);
910  }
911 
912  template <typename T, typename Context>
913  std::enable_if_t<!has_SequenceTraits<T>::value, void>
914  mapOptionalWithContext(const char *Key, T &Val, Context &Ctx) {
915  this->processKey(Key, Val, false, Ctx);
916  }
917 
918  template <typename T, typename Context, typename DefaultT>
919  void mapOptionalWithContext(const char *Key, T &Val, const DefaultT &Default,
920  Context &Ctx) {
921  static_assert(std::is_convertible<DefaultT, T>::value,
922  "Default type must be implicitly convertible to value type!");
923  this->processKeyWithDefault(Key, Val, static_cast<const T &>(Default),
924  false, Ctx);
925  }
926 
927 private:
928  template <typename T, typename Context>
929  void processKeyWithDefault(const char *Key, Optional<T> &Val,
930  const Optional<T> &DefaultValue, bool Required,
931  Context &Ctx);
932 
933  template <typename T, typename Context>
934  void processKeyWithDefault(const char *Key, T &Val, const T &DefaultValue,
935  bool Required, Context &Ctx) {
936  void *SaveInfo;
937  bool UseDefault;
938  const bool sameAsDefault = outputting() && Val == DefaultValue;
939  if ( this->preflightKey(Key, Required, sameAsDefault, UseDefault,
940  SaveInfo) ) {
941  yamlize(*this, Val, Required, Ctx);
942  this->postflightKey(SaveInfo);
943  }
944  else {
945  if ( UseDefault )
946  Val = DefaultValue;
947  }
948  }
949 
950  template <typename T, typename Context>
951  void processKey(const char *Key, T &Val, bool Required, Context &Ctx) {
952  void *SaveInfo;
953  bool UseDefault;
954  if ( this->preflightKey(Key, Required, false, UseDefault, SaveInfo) ) {
955  yamlize(*this, Val, Required, Ctx);
956  this->postflightKey(SaveInfo);
957  }
958  }
959 
960 private:
961  void *Ctxt;
962 };
963 
964 namespace detail {
965 
966 template <typename T, typename Context>
967 void doMapping(IO &io, T &Val, Context &Ctx) {
968  MappingContextTraits<T, Context>::mapping(io, Val, Ctx);
969 }
970 
971 template <typename T> void doMapping(IO &io, T &Val, EmptyContext &Ctx) {
972  MappingTraits<T>::mapping(io, Val);
973 }
974 
975 } // end namespace detail
976 
977 template <typename T>
978 std::enable_if_t<has_ScalarEnumerationTraits<T>::value, void>
979 yamlize(IO &io, T &Val, bool, EmptyContext &Ctx) {
980  io.beginEnumScalar();
981  ScalarEnumerationTraits<T>::enumeration(io, Val);
982  io.endEnumScalar();
983 }
984 
985 template <typename T>
986 std::enable_if_t<has_ScalarBitSetTraits<T>::value, void>
987 yamlize(IO &io, T &Val, bool, EmptyContext &Ctx) {
988  bool DoClear;
989  if ( io.beginBitSetScalar(DoClear) ) {
990  if ( DoClear )
991  Val = T();
992  ScalarBitSetTraits<T>::bitset(io, Val);
993  io.endBitSetScalar();
994  }
995 }
996 
997 template <typename T>
998 std::enable_if_t<has_ScalarTraits<T>::value, void> yamlize(IO &io, T &Val, bool,
999  EmptyContext &Ctx) {
1000  if ( io.outputting() ) {
1001  std::string Storage;
1002  raw_string_ostream Buffer(Storage);
1003  ScalarTraits<T>::output(Val, io.getContext(), Buffer);
1004  StringRef Str = Buffer.str();
1005  io.scalarString(Str, ScalarTraits<T>::mustQuote(Str));
1006  }
1007  else {
1008  StringRef Str;
1009  io.scalarString(Str, ScalarTraits<T>::mustQuote(Str));
1010  StringRef Result = ScalarTraits<T>::input(Str, io.getContext(), Val);
1011  if ( !Result.empty() ) {
1012  io.setError(Twine(Result));
1013  }
1014  }
1015 }
1016 
1017 template <typename T>
1018 std::enable_if_t<has_BlockScalarTraits<T>::value, void>
1019 yamlize(IO &YamlIO, T &Val, bool, EmptyContext &Ctx) {
1020  if (YamlIO.outputting()) {
1021  std::string Storage;
1022  raw_string_ostream Buffer(Storage);
1023  BlockScalarTraits<T>::output(Val, YamlIO.getContext(), Buffer);
1024  StringRef Str = Buffer.str();
1025  YamlIO.blockScalarString(Str);
1026  } else {
1027  StringRef Str;
1028  YamlIO.blockScalarString(Str);
1029  StringRef Result =
1030  BlockScalarTraits<T>::input(Str, YamlIO.getContext(), Val);
1031  if (!Result.empty())
1032  YamlIO.setError(Twine(Result));
1033  }
1034 }
1035 
1036 template <typename T>
1037 std::enable_if_t<has_TaggedScalarTraits<T>::value, void>
1038 yamlize(IO &io, T &Val, bool, EmptyContext &Ctx) {
1039  if (io.outputting()) {
1040  std::string ScalarStorage, TagStorage;
1041  raw_string_ostream ScalarBuffer(ScalarStorage), TagBuffer(TagStorage);
1042  TaggedScalarTraits<T>::output(Val, io.getContext(), ScalarBuffer,
1043  TagBuffer);
1044  io.scalarTag(TagBuffer.str());
1045  StringRef ScalarStr = ScalarBuffer.str();
1046  io.scalarString(ScalarStr,
1047  TaggedScalarTraits<T>::mustQuote(Val, ScalarStr));
1048  } else {
1049  std::string Tag;
1050  io.scalarTag(Tag);
1051  StringRef Str;
1052  io.scalarString(Str, QuotingType::None);
1053  StringRef Result =
1054  TaggedScalarTraits<T>::input(Str, Tag, io.getContext(), Val);
1055  if (!Result.empty()) {
1056  io.setError(Twine(Result));
1057  }
1058  }
1059 }
1060 
1061 template <typename T, typename Context>
1062 std::enable_if_t<validatedMappingTraits<T, Context>::value, void>
1063 yamlize(IO &io, T &Val, bool, Context &Ctx) {
1064  if (has_FlowTraits<MappingTraits<T>>::value)
1065  io.beginFlowMapping();
1066  else
1067  io.beginMapping();
1068  if (io.outputting()) {
1069  std::string Err = MappingTraits<T>::validate(io, Val);
1070  if (!Err.empty()) {
1071  errs() << Err << "\n";
1072  assert(Err.empty() && "invalid struct trying to be written as yaml");
1073  }
1074  }
1075  detail::doMapping(io, Val, Ctx);
1076  if (!io.outputting()) {
1077  std::string Err = MappingTraits<T>::validate(io, Val);
1078  if (!Err.empty())
1079  io.setError(Err);
1080  }
1081  if (has_FlowTraits<MappingTraits<T>>::value)
1082  io.endFlowMapping();
1083  else
1084  io.endMapping();
1085 }
1086 
1087 template <typename T, typename Context>
1088 std::enable_if_t<!has_MappingEnumInputTraits<T, Context>::value, bool>
1089 yamlizeMappingEnumInput(IO &io, T &Val) {
1090  return false;
1091 }
1092 
1093 template <typename T, typename Context>
1094 std::enable_if_t<has_MappingEnumInputTraits<T, Context>::value, bool>
1095 yamlizeMappingEnumInput(IO &io, T &Val) {
1096  if (io.outputting())
1097  return false;
1098 
1099  io.beginEnumScalar();
1100  MappingTraits<T>::enumInput(io, Val);
1101  bool Matched = !io.matchEnumFallback();
1102  io.endEnumScalar();
1103  return Matched;
1104 }
1105 
1106 template <typename T, typename Context>
1107 std::enable_if_t<unvalidatedMappingTraits<T, Context>::value, void>
1108 yamlize(IO &io, T &Val, bool, Context &Ctx) {
1109  if (yamlizeMappingEnumInput<T, Context>(io, Val))
1110  return;
1111  if (has_FlowTraits<MappingTraits<T>>::value) {
1112  io.beginFlowMapping();
1113  detail::doMapping(io, Val, Ctx);
1114  io.endFlowMapping();
1115  } else {
1116  io.beginMapping();
1117  detail::doMapping(io, Val, Ctx);
1118  io.endMapping();
1119  }
1120 }
1121 
1122 template <typename T>
1123 std::enable_if_t<has_CustomMappingTraits<T>::value, void>
1124 yamlize(IO &io, T &Val, bool, EmptyContext &Ctx) {
1125  if ( io.outputting() ) {
1126  io.beginMapping();
1128  io.endMapping();
1129  } else {
1130  io.beginMapping();
1131  for (StringRef key : io.keys())
1132  CustomMappingTraits<T>::inputOne(io, key, Val);
1133  io.endMapping();
1134  }
1135 }
1136 
1137 template <typename T>
1138 std::enable_if_t<has_PolymorphicTraits<T>::value, void>
1139 yamlize(IO &io, T &Val, bool, EmptyContext &Ctx) {
1140  switch (io.outputting() ? PolymorphicTraits<T>::getKind(Val)
1141  : io.getNodeKind()) {
1142  case NodeKind::Scalar:
1143  return yamlize(io, PolymorphicTraits<T>::getAsScalar(Val), true, Ctx);
1144  case NodeKind::Map:
1145  return yamlize(io, PolymorphicTraits<T>::getAsMap(Val), true, Ctx);
1146  case NodeKind::Sequence:
1147  return yamlize(io, PolymorphicTraits<T>::getAsSequence(Val), true, Ctx);
1148  }
1149 }
1150 
1151 template <typename T>
1152 std::enable_if_t<missingTraits<T, EmptyContext>::value, void>
1153 yamlize(IO &io, T &Val, bool, EmptyContext &Ctx) {
1154  char missing_yaml_trait_for_type[sizeof(MissingTrait<T>)];
1155 }
1156 
1157 template <typename T, typename Context>
1158 std::enable_if_t<has_SequenceTraits<T>::value, void>
1159 yamlize(IO &io, T &Seq, bool, Context &Ctx) {
1160  if ( has_FlowTraits< SequenceTraits<T>>::value ) {
1161  unsigned incnt = io.beginFlowSequence();
1162  unsigned count = io.outputting() ? SequenceTraits<T>::size(io, Seq) : incnt;
1163  for(unsigned i=0; i < count; ++i) {
1164  void *SaveInfo;
1165  if ( io.preflightFlowElement(i, SaveInfo) ) {
1166  yamlize(io, SequenceTraits<T>::element(io, Seq, i), true, Ctx);
1167  io.postflightFlowElement(SaveInfo);
1168  }
1169  }
1170  io.endFlowSequence();
1171  }
1172  else {
1173  unsigned incnt = io.beginSequence();
1174  unsigned count = io.outputting() ? SequenceTraits<T>::size(io, Seq) : incnt;
1175  for(unsigned i=0; i < count; ++i) {
1176  void *SaveInfo;
1177  if ( io.preflightElement(i, SaveInfo) ) {
1178  yamlize(io, SequenceTraits<T>::element(io, Seq, i), true, Ctx);
1179  io.postflightElement(SaveInfo);
1180  }
1181  }
1182  io.endSequence();
1183  }
1184 }
1185 
1186 template<>
1187 struct ScalarTraits<bool> {
1188  static void output(const bool &, void* , raw_ostream &);
1189  static StringRef input(StringRef, void *, bool &);
1190  static QuotingType mustQuote(StringRef) { return QuotingType::None; }
1191 };
1192 
1193 template<>
1194 struct ScalarTraits<StringRef> {
1195  static void output(const StringRef &, void *, raw_ostream &);
1196  static StringRef input(StringRef, void *, StringRef &);
1197  static QuotingType mustQuote(StringRef S) { return needsQuotes(S); }
1198 };
1199 
1200 template<>
1201 struct ScalarTraits<std::string> {
1202  static void output(const std::string &, void *, raw_ostream &);
1203  static StringRef input(StringRef, void *, std::string &);
1204  static QuotingType mustQuote(StringRef S) { return needsQuotes(S); }
1205 };
1206 
1207 template<>
1208 struct ScalarTraits<uint8_t> {
1209  static void output(const uint8_t &, void *, raw_ostream &);
1210  static StringRef input(StringRef, void *, uint8_t &);
1211  static QuotingType mustQuote(StringRef) { return QuotingType::None; }
1212 };
1213 
1214 template<>
1215 struct ScalarTraits<uint16_t> {
1216  static void output(const uint16_t &, void *, raw_ostream &);
1217  static StringRef input(StringRef, void *, uint16_t &);
1218  static QuotingType mustQuote(StringRef) { return QuotingType::None; }
1219 };
1220 
1221 template<>
1222 struct ScalarTraits<uint32_t> {
1223  static void output(const uint32_t &, void *, raw_ostream &);
1224  static StringRef input(StringRef, void *, uint32_t &);
1225  static QuotingType mustQuote(StringRef) { return QuotingType::None; }
1226 };
1227 
1228 template<>
1229 struct ScalarTraits<uint64_t> {
1230  static void output(const uint64_t &, void *, raw_ostream &);
1231  static StringRef input(StringRef, void *, uint64_t &);
1232  static QuotingType mustQuote(StringRef) { return QuotingType::None; }
1233 };
1234 
1235 template<>
1236 struct ScalarTraits<int8_t> {
1237  static void output(const int8_t &, void *, raw_ostream &);
1238  static StringRef input(StringRef, void *, int8_t &);
1239  static QuotingType mustQuote(StringRef) { return QuotingType::None; }
1240 };
1241 
1242 template<>
1243 struct ScalarTraits<int16_t> {
1244  static void output(const int16_t &, void *, raw_ostream &);
1245  static StringRef input(StringRef, void *, int16_t &);
1246  static QuotingType mustQuote(StringRef) { return QuotingType::None; }
1247 };
1248 
1249 template<>
1250 struct ScalarTraits<int32_t> {
1251  static void output(const int32_t &, void *, raw_ostream &);
1252  static StringRef input(StringRef, void *, int32_t &);
1253  static QuotingType mustQuote(StringRef) { return QuotingType::None; }
1254 };
1255 
1256 template<>
1257 struct ScalarTraits<int64_t> {
1258  static void output(const int64_t &, void *, raw_ostream &);
1259  static StringRef input(StringRef, void *, int64_t &);
1260  static QuotingType mustQuote(StringRef) { return QuotingType::None; }
1261 };
1262 
1263 template<>
1264 struct ScalarTraits<float> {
1265  static void output(const float &, void *, raw_ostream &);
1266  static StringRef input(StringRef, void *, float &);
1267  static QuotingType mustQuote(StringRef) { return QuotingType::None; }
1268 };
1269 
1270 template<>
1271 struct ScalarTraits<double> {
1272  static void output(const double &, void *, raw_ostream &);
1273  static StringRef input(StringRef, void *, double &);
1274  static QuotingType mustQuote(StringRef) { return QuotingType::None; }
1275 };
1276 
1277 // For endian types, we use existing scalar Traits class for the underlying
1278 // type. This way endian aware types are supported whenever the traits are
1279 // defined for the underlying type.
1280 template <typename value_type, support::endianness endian, size_t alignment>
1281 struct ScalarTraits<support::detail::packed_endian_specific_integral<
1282  value_type, endian, alignment>,
1283  std::enable_if_t<has_ScalarTraits<value_type>::value>> {
1284  using endian_type =
1285  support::detail::packed_endian_specific_integral<value_type, endian,
1286  alignment>;
1287 
1288  static void output(const endian_type &E, void *Ctx, raw_ostream &Stream) {
1289  ScalarTraits<value_type>::output(static_cast<value_type>(E), Ctx, Stream);
1290  }
1291 
1292  static StringRef input(StringRef Str, void *Ctx, endian_type &E) {
1293  value_type V;
1294  auto R = ScalarTraits<value_type>::input(Str, Ctx, V);
1295  E = static_cast<endian_type>(V);
1296  return R;
1297  }
1298 
1299  static QuotingType mustQuote(StringRef Str) {
1300  return ScalarTraits<value_type>::mustQuote(Str);
1301  }
1302 };
1303 
1304 template <typename value_type, support::endianness endian, size_t alignment>
1305 struct ScalarEnumerationTraits<
1306  support::detail::packed_endian_specific_integral<value_type, endian,
1307  alignment>,
1308  std::enable_if_t<has_ScalarEnumerationTraits<value_type>::value>> {
1309  using endian_type =
1310  support::detail::packed_endian_specific_integral<value_type, endian,
1311  alignment>;
1312 
1313  static void enumeration(IO &io, endian_type &E) {
1314  value_type V = E;
1315  ScalarEnumerationTraits<value_type>::enumeration(io, V);
1316  E = V;
1317  }
1318 };
1319 
1320 template <typename value_type, support::endianness endian, size_t alignment>
1321 struct ScalarBitSetTraits<
1322  support::detail::packed_endian_specific_integral<value_type, endian,
1323  alignment>,
1324  std::enable_if_t<has_ScalarBitSetTraits<value_type>::value>> {
1325  using endian_type =
1326  support::detail::packed_endian_specific_integral<value_type, endian,
1327  alignment>;
1328  static void bitset(IO &io, endian_type &E) {
1329  value_type V = E;
1330  ScalarBitSetTraits<value_type>::bitset(io, V);
1331  E = V;
1332  }
1333 };
1334 
1335 // Utility for use within MappingTraits<>::mapping() method
1336 // to [de]normalize an object for use with YAML conversion.
1337 template <typename TNorm, typename TFinal>
1338 struct MappingNormalization {
1339  MappingNormalization(IO &i_o, TFinal &Obj)
1340  : io(i_o), BufPtr(nullptr), Result(Obj) {
1341  if ( io.outputting() ) {
1342  BufPtr = new (&Buffer) TNorm(io, Obj);
1343  }
1344  else {
1345  BufPtr = new (&Buffer) TNorm(io);
1346  }
1347  }
1348 
1349  ~MappingNormalization() {
1350  if ( ! io.outputting() ) {
1351  Result = BufPtr->denormalize(io);
1352  }
1353  BufPtr->~TNorm();
1354  }
1355 
1356  TNorm* operator->() { return BufPtr; }
1357 
1358 private:
1359  using Storage = AlignedCharArrayUnion<TNorm>;
1360 
1361  Storage Buffer;
1362  IO &io;
1363  TNorm *BufPtr;
1364  TFinal &Result;
1365 };
1366 
1367 // Utility for use within MappingTraits<>::mapping() method
1368 // to [de]normalize an object for use with YAML conversion.
1369 template <typename TNorm, typename TFinal>
1370 struct MappingNormalizationHeap {
1371  MappingNormalizationHeap(IO &i_o, TFinal &Obj, BumpPtrAllocator *allocator)
1372  : io(i_o), Result(Obj) {
1373  if ( io.outputting() ) {
1374  BufPtr = new (&Buffer) TNorm(io, Obj);
1375  }
1376  else if (allocator) {
1377  BufPtr = allocator->Allocate<TNorm>();
1378  new (BufPtr) TNorm(io);
1379  } else {
1380  BufPtr = new TNorm(io);
1381  }
1382  }
1383 
1384  ~MappingNormalizationHeap() {
1385  if ( io.outputting() ) {
1386  BufPtr->~TNorm();
1387  }
1388  else {
1389  Result = BufPtr->denormalize(io);
1390  }
1391  }
1392 
1393  TNorm* operator->() { return BufPtr; }
1394 
1395 private:
1396  using Storage = AlignedCharArrayUnion<TNorm>;
1397 
1398  Storage Buffer;
1399  IO &io;
1400  TNorm *BufPtr = nullptr;
1401  TFinal &Result;
1402 };
1403 
1404 ///
1405 /// The Input class is used to parse a yaml document into in-memory structs
1406 /// and vectors.
1407 ///
1408 /// It works by using YAMLParser to do a syntax parse of the entire yaml
1409 /// document, then the Input class builds a graph of HNodes which wraps
1410 /// each yaml Node. The extra layer is buffering. The low level yaml
1411 /// parser only lets you look at each node once. The buffering layer lets
1412 /// you search and interate multiple times. This is necessary because
1413 /// the mapRequired() method calls may not be in the same order
1414 /// as the keys in the document.
1415 ///
1416 class Input : public IO {
1417 public:
1418  // Construct a yaml Input object from a StringRef and optional
1419  // user-data. The DiagHandler can be specified to provide
1420  // alternative error reporting.
1421  Input(StringRef InputContent,
1422  void *Ctxt = nullptr,
1424  void *DiagHandlerCtxt = nullptr);
1425  Input(MemoryBufferRef Input,
1426  void *Ctxt = nullptr,
1428  void *DiagHandlerCtxt = nullptr);
1429  ~Input() override;
1430 
1431  // Check if there was an syntax or semantic error during parsing.
1432  std::error_code error();
1433 
1434 private:
1435  bool outputting() const override;
1436  bool mapTag(StringRef, bool) override;
1437  void beginMapping() override;
1438  void endMapping() override;
1439  bool preflightKey(const char *, bool, bool, bool &, void *&) override;
1440  void postflightKey(void *) override;
1441  std::vector<StringRef> keys() override;
1442  void beginFlowMapping() override;
1443  void endFlowMapping() override;
1444  unsigned beginSequence() override;
1445  void endSequence() override;
1446  bool preflightElement(unsigned index, void *&) override;
1447  void postflightElement(void *) override;
1448  unsigned beginFlowSequence() override;
1449  bool preflightFlowElement(unsigned , void *&) override;
1450  void postflightFlowElement(void *) override;
1451  void endFlowSequence() override;
1452  void beginEnumScalar() override;
1453  bool matchEnumScalar(const char*, bool) override;
1454  bool matchEnumFallback() override;
1455  void endEnumScalar() override;
1456  bool beginBitSetScalar(bool &) override;
1457  bool bitSetMatch(const char *, bool ) override;
1458  void endBitSetScalar() override;
1459  void scalarString(StringRef &, QuotingType) override;
1460  void blockScalarString(StringRef &) override;
1461  void scalarTag(std::string &) override;
1462  NodeKind getNodeKind() override;
1463  void setError(const Twine &message) override;
1464  bool canElideEmptySequence() override;
1465 
1466  class HNode {
1467  virtual void anchor();
1468 
1469  public:
1470  HNode(Node *n) : _node(n) { }
1471  virtual ~HNode() = default;
1472 
1473  static bool classof(const HNode *) { return true; }
1474 
1475  Node *_node;
1476  };
1477 
1478  class EmptyHNode : public HNode {
1479  void anchor() override;
1480 
1481  public:
1482  EmptyHNode(Node *n) : HNode(n) { }
1483 
1484  static bool classof(const HNode *n) { return NullNode::classof(n->_node); }
1485 
1486  static bool classof(const EmptyHNode *) { return true; }
1487  };
1488 
1489  class ScalarHNode : public HNode {
1490  void anchor() override;
1491 
1492  public:
1493  ScalarHNode(Node *n, StringRef s) : HNode(n), _value(s) { }
1494 
1495  StringRef value() const { return _value; }
1496 
1497  static bool classof(const HNode *n) {
1498  return ScalarNode::classof(n->_node) ||
1499  BlockScalarNode::classof(n->_node);
1500  }
1501 
1502  static bool classof(const ScalarHNode *) { return true; }
1503 
1504  protected:
1505  StringRef _value;
1506  };
1507 
1508  class MapHNode : public HNode {
1509  void anchor() override;
1510 
1511  public:
1512  MapHNode(Node *n) : HNode(n) { }
1513 
1514  static bool classof(const HNode *n) {
1515  return MappingNode::classof(n->_node);
1516  }
1517 
1518  static bool classof(const MapHNode *) { return true; }
1519 
1520  using NameToNodeAndLoc =
1521  StringMap<std::pair<std::unique_ptr<HNode>, SMRange>>;
1522 
1523  NameToNodeAndLoc Mapping;
1524  SmallVector<std::string, 6> ValidKeys;
1525  };
1526 
1527  class SequenceHNode : public HNode {
1528  void anchor() override;
1529 
1530  public:
1531  SequenceHNode(Node *n) : HNode(n) { }
1532 
1533  static bool classof(const HNode *n) {
1534  return SequenceNode::classof(n->_node);
1535  }
1536 
1537  static bool classof(const SequenceHNode *) { return true; }
1538 
1539  std::vector<std::unique_ptr<HNode>> Entries;
1540  };
1541 
1542  std::unique_ptr<Input::HNode> createHNodes(Node *node);
1543  void setError(HNode *hnode, const Twine &message);
1544  void setError(Node *node, const Twine &message);
1545  void setError(const SMRange &Range, const Twine &message);
1546 
1547  void reportWarning(HNode *hnode, const Twine &message);
1548  void reportWarning(Node *hnode, const Twine &message);
1549  void reportWarning(const SMRange &Range, const Twine &message);
1550 
1551 public:
1552  // These are only used by operator>>. They could be private
1553  // if those templated things could be made friends.
1554  bool setCurrentDocument();
1555  bool nextDocument();
1556 
1557  /// Returns the current node that's being parsed by the YAML Parser.
1558  const Node *getCurrentNode() const;
1559 
1560  void setAllowUnknownKeys(bool Allow) override;
1561 
1562 private:
1563  SourceMgr SrcMgr; // must be before Strm
1564  std::unique_ptr<llvm::yaml::Stream> Strm;
1565  std::unique_ptr<HNode> TopNode;
1566  std::error_code EC;
1567  BumpPtrAllocator StringAllocator;
1568  document_iterator DocIterator;
1569  llvm::BitVector BitValuesUsed;
1570  HNode *CurrentNode = nullptr;
1571  bool ScalarMatchFound = false;
1572  bool AllowUnknownKeys = false;
1573 };
1574 
1575 ///
1576 /// The Output class is used to generate a yaml document from in-memory structs
1577 /// and vectors.
1578 ///
1579 class Output : public IO {
1580 public:
1581  Output(raw_ostream &, void *Ctxt = nullptr, int WrapColumn = 70);
1582  ~Output() override;
1583 
1584  /// Set whether or not to output optional values which are equal
1585  /// to the default value. By default, when outputting if you attempt
1586  /// to write a value that is equal to the default, the value gets ignored.
1587  /// Sometimes, it is useful to be able to see these in the resulting YAML
1588  /// anyway.
1589  void setWriteDefaultValues(bool Write) { WriteDefaultValues = Write; }
1590 
1591  bool outputting() const override;
1592  bool mapTag(StringRef, bool) override;
1593  void beginMapping() override;
1594  void endMapping() override;
1595  bool preflightKey(const char *key, bool, bool, bool &, void *&) override;
1596  void postflightKey(void *) override;
1597  std::vector<StringRef> keys() override;
1598  void beginFlowMapping() override;
1599  void endFlowMapping() override;
1600  unsigned beginSequence() override;
1601  void endSequence() override;
1602  bool preflightElement(unsigned, void *&) override;
1603  void postflightElement(void *) override;
1604  unsigned beginFlowSequence() override;
1605  bool preflightFlowElement(unsigned, void *&) override;
1606  void postflightFlowElement(void *) override;
1607  void endFlowSequence() override;
1608  void beginEnumScalar() override;
1609  bool matchEnumScalar(const char*, bool) override;
1610  bool matchEnumFallback() override;
1611  void endEnumScalar() override;
1612  bool beginBitSetScalar(bool &) override;
1613  bool bitSetMatch(const char *, bool ) override;
1614  void endBitSetScalar() override;
1615  void scalarString(StringRef &, QuotingType) override;
1616  void blockScalarString(StringRef &) override;
1617  void scalarTag(std::string &) override;
1618  NodeKind getNodeKind() override;
1619  void setError(const Twine &message) override;
1620  bool canElideEmptySequence() override;
1621 
1622  // These are only used by operator<<. They could be private
1623  // if that templated operator could be made a friend.
1624  void beginDocuments();
1625  bool preflightDocument(unsigned);
1626  void postflightDocument();
1627  void endDocuments();
1628 
1629 private:
1630  void output(StringRef s);
1631  void outputUpToEndOfLine(StringRef s);
1632  void newLineCheck(bool EmptySequence = false);
1633  void outputNewLine();
1634  void paddedKey(StringRef key);
1635  void flowKey(StringRef Key);
1636 
1637  enum InState {
1638  inSeqFirstElement,
1639  inSeqOtherElement,
1640  inFlowSeqFirstElement,
1641  inFlowSeqOtherElement,
1642  inMapFirstKey,
1643  inMapOtherKey,
1644  inFlowMapFirstKey,
1645  inFlowMapOtherKey
1646  };
1647 
1648  static bool inSeqAnyElement(InState State);
1649  static bool inFlowSeqAnyElement(InState State);
1650  static bool inMapAnyKey(InState State);
1651  static bool inFlowMapAnyKey(InState State);
1652 
1653  raw_ostream &Out;
1654  int WrapColumn;
1655  SmallVector<InState, 8> StateStack;
1656  int Column = 0;
1657  int ColumnAtFlowStart = 0;
1658  int ColumnAtMapFlowStart = 0;
1659  bool NeedBitValueComma = false;
1660  bool NeedFlowSequenceComma = false;
1661  bool EnumerationMatchFound = false;
1662  bool WriteDefaultValues = false;
1663  StringRef Padding;
1664  StringRef PaddingBeforeContainer;
1665 };
1666 
1667 template <typename T, typename Context>
1668 void IO::processKeyWithDefault(const char *Key, Optional<T> &Val,
1669  const Optional<T> &DefaultValue, bool Required,
1670  Context &Ctx) {
1671  assert(DefaultValue.hasValue() == false &&
1672  "Optional<T> shouldn't have a value!");
1673  void *SaveInfo;
1674  bool UseDefault = true;
1675  const bool sameAsDefault = outputting() && !Val.hasValue();
1676  if (!outputting() && !Val.hasValue())
1677  Val = T();
1678  if (Val.hasValue() &&
1679  this->preflightKey(Key, Required, sameAsDefault, UseDefault, SaveInfo)) {
1680 
1681  // When reading an Optional<X> key from a YAML description, we allow the
1682  // special "<none>" value, which can be used to specify that no value was
1683  // requested, i.e. the DefaultValue will be assigned. The DefaultValue is
1684  // usually None.
1685  bool IsNone = false;
1686  if (!outputting())
1687  if (const auto *Node = dyn_cast<ScalarNode>(((Input *)this)->getCurrentNode()))
1688  // We use rtrim to ignore possible white spaces that might exist when a
1689  // comment is present on the same line.
1690  IsNone = Node->getRawValue().rtrim(' ') == "<none>";
1691 
1692  if (IsNone)
1693  Val = DefaultValue;
1694  else
1695  yamlize(*this, Val.getValue(), Required, Ctx);
1696  this->postflightKey(SaveInfo);
1697  } else {
1698  if (UseDefault)
1699  Val = DefaultValue;
1700  }
1701 }
1702 
1703 /// YAML I/O does conversion based on types. But often native data types
1704 /// are just a typedef of built in intergral types (e.g. int). But the C++
1705 /// type matching system sees through the typedef and all the typedefed types
1706 /// look like a built in type. This will cause the generic YAML I/O conversion
1707 /// to be used. To provide better control over the YAML conversion, you can
1708 /// use this macro instead of typedef. It will create a class with one field
1709 /// and automatic conversion operators to and from the base type.
1710 /// Based on BOOST_STRONG_TYPEDEF
1711 #define LLVM_YAML_STRONG_TYPEDEF(_base, _type) \
1712  struct _type { \
1713  _type() = default; \
1714  _type(const _base v) : value(v) {} \
1715  _type(const _type &v) = default; \
1716  _type &operator=(const _type &rhs) = default; \
1717  _type &operator=(const _base &rhs) { value = rhs; return *this; } \
1718  operator const _base & () const { return value; } \
1719  bool operator==(const _type &rhs) const { return value == rhs.value; } \
1720  bool operator==(const _base &rhs) const { return value == rhs; } \
1721  bool operator<(const _type &rhs) const { return value < rhs.value; } \
1722  _base value; \
1723  using BaseType = _base; \
1724  };
1725 
1726 ///
1727 /// Use these types instead of uintXX_t in any mapping to have
1728 /// its yaml output formatted as hexadecimal.
1729 ///
1730 LLVM_YAML_STRONG_TYPEDEF(uint8_t, Hex8)
1734 
1735 template<>
1736 struct ScalarTraits<Hex8> {
1737  static void output(const Hex8 &, void *, raw_ostream &);
1738  static StringRef input(StringRef, void *, Hex8 &);
1739  static QuotingType mustQuote(StringRef) { return QuotingType::None; }
1740 };
1741 
1742 template<>
1743 struct ScalarTraits<Hex16> {
1744  static void output(const Hex16 &, void *, raw_ostream &);
1745  static StringRef input(StringRef, void *, Hex16 &);
1746  static QuotingType mustQuote(StringRef) { return QuotingType::None; }
1747 };
1748 
1749 template<>
1750 struct ScalarTraits<Hex32> {
1751  static void output(const Hex32 &, void *, raw_ostream &);
1752  static StringRef input(StringRef, void *, Hex32 &);
1753  static QuotingType mustQuote(StringRef) { return QuotingType::None; }
1754 };
1755 
1756 template<>
1757 struct ScalarTraits<Hex64> {
1758  static void output(const Hex64 &, void *, raw_ostream &);
1759  static StringRef input(StringRef, void *, Hex64 &);
1760  static QuotingType mustQuote(StringRef) { return QuotingType::None; }
1761 };
1762 
1763 template <> struct ScalarTraits<VersionTuple> {
1764  static void output(const VersionTuple &Value, void *, llvm::raw_ostream &Out);
1765  static StringRef input(StringRef, void *, VersionTuple &);
1766  static QuotingType mustQuote(StringRef) { return QuotingType::None; }
1767 };
1768 
1769 // Define non-member operator>> so that Input can stream in a document list.
1770 template <typename T>
1771 inline std::enable_if_t<has_DocumentListTraits<T>::value, Input &>
1772 operator>>(Input &yin, T &docList) {
1773  int i = 0;
1774  EmptyContext Ctx;
1775  while ( yin.setCurrentDocument() ) {
1776  yamlize(yin, DocumentListTraits<T>::element(yin, docList, i), true, Ctx);
1777  if ( yin.error() )
1778  return yin;
1779  yin.nextDocument();
1780  ++i;
1781  }
1782  return yin;
1783 }
1784 
1785 // Define non-member operator>> so that Input can stream in a map as a document.
1786 template <typename T>
1787 inline std::enable_if_t<has_MappingTraits<T, EmptyContext>::value, Input &>
1788 operator>>(Input &yin, T &docMap) {
1789  EmptyContext Ctx;
1790  yin.setCurrentDocument();
1791  yamlize(yin, docMap, true, Ctx);
1792  return yin;
1793 }
1794 
1795 // Define non-member operator>> so that Input can stream in a sequence as
1796 // a document.
1797 template <typename T>
1798 inline std::enable_if_t<has_SequenceTraits<T>::value, Input &>
1799 operator>>(Input &yin, T &docSeq) {
1800  EmptyContext Ctx;
1801  if (yin.setCurrentDocument())
1802  yamlize(yin, docSeq, true, Ctx);
1803  return yin;
1804 }
1805 
1806 // Define non-member operator>> so that Input can stream in a block scalar.
1807 template <typename T>
1808 inline std::enable_if_t<has_BlockScalarTraits<T>::value, Input &>
1809 operator>>(Input &In, T &Val) {
1810  EmptyContext Ctx;
1811  if (In.setCurrentDocument())
1812  yamlize(In, Val, true, Ctx);
1813  return In;
1814 }
1815 
1816 // Define non-member operator>> so that Input can stream in a string map.
1817 template <typename T>
1818 inline std::enable_if_t<has_CustomMappingTraits<T>::value, Input &>
1819 operator>>(Input &In, T &Val) {
1820  EmptyContext Ctx;
1821  if (In.setCurrentDocument())
1822  yamlize(In, Val, true, Ctx);
1823  return In;
1824 }
1825 
1826 // Define non-member operator>> so that Input can stream in a polymorphic type.
1827 template <typename T>
1828 inline std::enable_if_t<has_PolymorphicTraits<T>::value, Input &>
1829 operator>>(Input &In, T &Val) {
1830  EmptyContext Ctx;
1831  if (In.setCurrentDocument())
1832  yamlize(In, Val, true, Ctx);
1833  return In;
1834 }
1835 
1836 // Provide better error message about types missing a trait specialization
1837 template <typename T>
1838 inline std::enable_if_t<missingTraits<T, EmptyContext>::value, Input &>
1839 operator>>(Input &yin, T &docSeq) {
1840  char missing_yaml_trait_for_type[sizeof(MissingTrait<T>)];
1841  return yin;
1842 }
1843 
1844 // Define non-member operator<< so that Output can stream out document list.
1845 template <typename T>
1846 inline std::enable_if_t<has_DocumentListTraits<T>::value, Output &>
1847 operator<<(Output &yout, T &docList) {
1848  EmptyContext Ctx;
1849  yout.beginDocuments();
1850  const size_t count = DocumentListTraits<T>::size(yout, docList);
1851  for(size_t i=0; i < count; ++i) {
1852  if ( yout.preflightDocument(i) ) {
1853  yamlize(yout, DocumentListTraits<T>::element(yout, docList, i), true,
1854  Ctx);
1855  yout.postflightDocument();
1856  }
1857  }
1858  yout.endDocuments();
1859  return yout;
1860 }
1861 
1862 // Define non-member operator<< so that Output can stream out a map.
1863 template <typename T>
1864 inline std::enable_if_t<has_MappingTraits<T, EmptyContext>::value, Output &>
1865 operator<<(Output &yout, T &map) {
1866  EmptyContext Ctx;
1867  yout.beginDocuments();
1868  if ( yout.preflightDocument(0) ) {
1869  yamlize(yout, map, true, Ctx);
1870  yout.postflightDocument();
1871  }
1872  yout.endDocuments();
1873  return yout;
1874 }
1875 
1876 // Define non-member operator<< so that Output can stream out a sequence.
1877 template <typename T>
1878 inline std::enable_if_t<has_SequenceTraits<T>::value, Output &>
1879 operator<<(Output &yout, T &seq) {
1880  EmptyContext Ctx;
1881  yout.beginDocuments();
1882  if ( yout.preflightDocument(0) ) {
1883  yamlize(yout, seq, true, Ctx);
1884  yout.postflightDocument();
1885  }
1886  yout.endDocuments();
1887  return yout;
1888 }
1889 
1890 // Define non-member operator<< so that Output can stream out a block scalar.
1891 template <typename T>
1892 inline std::enable_if_t<has_BlockScalarTraits<T>::value, Output &>
1893 operator<<(Output &Out, T &Val) {
1894  EmptyContext Ctx;
1895  Out.beginDocuments();
1896  if (Out.preflightDocument(0)) {
1897  yamlize(Out, Val, true, Ctx);
1898  Out.postflightDocument();
1899  }
1900  Out.endDocuments();
1901  return Out;
1902 }
1903 
1904 // Define non-member operator<< so that Output can stream out a string map.
1905 template <typename T>
1906 inline std::enable_if_t<has_CustomMappingTraits<T>::value, Output &>
1907 operator<<(Output &Out, T &Val) {
1908  EmptyContext Ctx;
1909  Out.beginDocuments();
1910  if (Out.preflightDocument(0)) {
1911  yamlize(Out, Val, true, Ctx);
1912  Out.postflightDocument();
1913  }
1914  Out.endDocuments();
1915  return Out;
1916 }
1917 
1918 // Define non-member operator<< so that Output can stream out a polymorphic
1919 // type.
1920 template <typename T>
1921 inline std::enable_if_t<has_PolymorphicTraits<T>::value, Output &>
1922 operator<<(Output &Out, T &Val) {
1923  EmptyContext Ctx;
1924  Out.beginDocuments();
1925  if (Out.preflightDocument(0)) {
1926  // FIXME: The parser does not support explicit documents terminated with a
1927  // plain scalar; the end-marker is included as part of the scalar token.
1928  assert(PolymorphicTraits<T>::getKind(Val) != NodeKind::Scalar && "plain scalar documents are not supported");
1929  yamlize(Out, Val, true, Ctx);
1930  Out.postflightDocument();
1931  }
1932  Out.endDocuments();
1933  return Out;
1934 }
1935 
1936 // Provide better error message about types missing a trait specialization
1937 template <typename T>
1938 inline std::enable_if_t<missingTraits<T, EmptyContext>::value, Output &>
1939 operator<<(Output &yout, T &seq) {
1940  char missing_yaml_trait_for_type[sizeof(MissingTrait<T>)];
1941  return yout;
1942 }
1943 
1944 template <bool B> struct IsFlowSequenceBase {};
1945 template <> struct IsFlowSequenceBase<true> { static const bool flow = true; };
1946 
1947 template <typename T, bool Flow>
1948 struct SequenceTraitsImpl : IsFlowSequenceBase<Flow> {
1949 private:
1950  using type = typename T::value_type;
1951 
1952 public:
1953  static size_t size(IO &io, T &seq) { return seq.size(); }
1954 
1955  static type &element(IO &io, T &seq, size_t index) {
1956  if (index >= seq.size())
1957  seq.resize(index + 1);
1958  return seq[index];
1959  }
1960 };
1961 
1962 // Simple helper to check an expression can be used as a bool-valued template
1963 // argument.
1964 template <bool> struct CheckIsBool { static const bool value = true; };
1965 
1966 // If T has SequenceElementTraits, then vector<T> and SmallVector<T, N> have
1967 // SequenceTraits that do the obvious thing.
1968 template <typename T>
1969 struct SequenceTraits<
1970  std::vector<T>,
1971  std::enable_if_t<CheckIsBool<SequenceElementTraits<T>::flow>::value>>
1972  : SequenceTraitsImpl<std::vector<T>, SequenceElementTraits<T>::flow> {};
1973 template <typename T, unsigned N>
1974 struct SequenceTraits<
1975  SmallVector<T, N>,
1976  std::enable_if_t<CheckIsBool<SequenceElementTraits<T>::flow>::value>>
1977  : SequenceTraitsImpl<SmallVector<T, N>, SequenceElementTraits<T>::flow> {};
1978 template <typename T>
1979 struct SequenceTraits<
1980  SmallVectorImpl<T>,
1981  std::enable_if_t<CheckIsBool<SequenceElementTraits<T>::flow>::value>>
1982  : SequenceTraitsImpl<SmallVectorImpl<T>, SequenceElementTraits<T>::flow> {};
1983 
1984 // Sequences of fundamental types use flow formatting.
1985 template <typename T>
1986 struct SequenceElementTraits<T,
1987  std::enable_if_t<std::is_fundamental<T>::value>> {
1988  static const bool flow = true;
1989 };
1990 
1991 // Sequences of strings use block formatting.
1992 template<> struct SequenceElementTraits<std::string> {
1993  static const bool flow = false;
1994 };
1995 template<> struct SequenceElementTraits<StringRef> {
1996  static const bool flow = false;
1997 };
1998 template<> struct SequenceElementTraits<std::pair<std::string, std::string>> {
1999  static const bool flow = false;
2000 };
2001 
2002 /// Implementation of CustomMappingTraits for std::map<std::string, T>.
2003 template <typename T> struct StdMapStringCustomMappingTraitsImpl {
2004  using map_type = std::map<std::string, T>;
2005 
2006  static void inputOne(IO &io, StringRef key, map_type &v) {
2007  io.mapRequired(key.str().c_str(), v[std::string(key)]);
2008  }
2009 
2010  static void output(IO &io, map_type &v) {
2011  for (auto &p : v)
2012  io.mapRequired(p.first.c_str(), p.second);
2013  }
2014 };
2015 
2016 } // end namespace yaml
2017 } // end namespace llvm
2018 
2019 #define LLVM_YAML_IS_SEQUENCE_VECTOR_IMPL(TYPE, FLOW) \
2020  namespace llvm { \
2021  namespace yaml { \
2022  static_assert( \
2023  !std::is_fundamental<TYPE>::value && \
2024  !std::is_same<TYPE, std::string>::value && \
2025  !std::is_same<TYPE, llvm::StringRef>::value, \
2026  "only use LLVM_YAML_IS_SEQUENCE_VECTOR for types you control"); \
2027  template <> struct SequenceElementTraits<TYPE> { \
2028  static const bool flow = FLOW; \
2029  }; \
2030  } \
2031  }
2032 
2033 /// Utility for declaring that a std::vector of a particular type
2034 /// should be considered a YAML sequence.
2035 #define LLVM_YAML_IS_SEQUENCE_VECTOR(type) \
2036  LLVM_YAML_IS_SEQUENCE_VECTOR_IMPL(type, false)
2037 
2038 /// Utility for declaring that a std::vector of a particular type
2039 /// should be considered a YAML flow sequence.
2040 #define LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(type) \
2041  LLVM_YAML_IS_SEQUENCE_VECTOR_IMPL(type, true)
2042 
2043 #define LLVM_YAML_DECLARE_MAPPING_TRAITS(Type) \
2044  namespace llvm { \
2045  namespace yaml { \
2046  template <> struct MappingTraits<Type> { \
2047  static void mapping(IO &IO, Type &Obj); \
2048  }; \
2049  } \
2050  }
2051 
2052 #define LLVM_YAML_DECLARE_ENUM_TRAITS(Type) \
2053  namespace llvm { \
2054  namespace yaml { \
2055  template <> struct ScalarEnumerationTraits<Type> { \
2056  static void enumeration(IO &io, Type &Value); \
2057  }; \
2058  } \
2059  }
2060 
2061 #define LLVM_YAML_DECLARE_BITSET_TRAITS(Type) \
2062  namespace llvm { \
2063  namespace yaml { \
2064  template <> struct ScalarBitSetTraits<Type> { \
2065  static void bitset(IO &IO, Type &Options); \
2066  }; \
2067  } \
2068  }
2069 
2070 #define LLVM_YAML_DECLARE_SCALAR_TRAITS(Type, MustQuote) \
2071  namespace llvm { \
2072  namespace yaml { \
2073  template <> struct ScalarTraits<Type> { \
2074  static void output(const Type &Value, void *ctx, raw_ostream &Out); \
2075  static StringRef input(StringRef Scalar, void *ctxt, Type &Value); \
2076  static QuotingType mustQuote(StringRef) { return MustQuote; } \
2077  }; \
2078  } \
2079  }
2080 
2081 /// Utility for declaring that a std::vector of a particular type
2082 /// should be considered a YAML document list.
2083 #define LLVM_YAML_IS_DOCUMENT_LIST_VECTOR(_type) \
2084  namespace llvm { \
2085  namespace yaml { \
2086  template <unsigned N> \
2087  struct DocumentListTraits<SmallVector<_type, N>> \
2088  : public SequenceTraitsImpl<SmallVector<_type, N>, false> {}; \
2089  template <> \
2090  struct DocumentListTraits<std::vector<_type>> \
2091  : public SequenceTraitsImpl<std::vector<_type>, false> {}; \
2092  } \
2093  }
2094 
2095 /// Utility for declaring that std::map<std::string, _type> should be considered
2096 /// a YAML map.
2097 #define LLVM_YAML_IS_STRING_MAP(_type) \
2098  namespace llvm { \
2099  namespace yaml { \
2100  template <> \
2101  struct CustomMappingTraits<std::map<std::string, _type>> \
2102  : public StdMapStringCustomMappingTraitsImpl<_type> {}; \
2103  } \
2104  }
2105 
2106 LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(llvm::yaml::Hex64)
2107 LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(llvm::yaml::Hex32)
2108 LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(llvm::yaml::Hex16)
2109 LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(llvm::yaml::Hex8)
2110 
2111 #endif // LLVM_SUPPORT_YAMLTRAITS_H
i
i
Definition: README.txt:29
llvm::SPIRV::StorageClass::Input
@ Input
llvm
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:17
llvm::objcarc::Sequence
Sequence
Definition: PtrState.h:41
Optional.h
StringRef.h
YAMLParser.h
double
into xmm2 addss xmm2 xmm1 xmm3 addss xmm3 movaps xmm0 unpcklps xmm0 ret seems silly when it could just be one addps Expand libm rounding functions main should enable SSE DAZ mode and other fast SSE modes Think about doing i64 math in SSE regs on x86 This testcase should have no SSE instructions in and only one load from a constant double
Definition: README-SSE.txt:85
llvm::StringRef::npos
static constexpr size_t npos
Definition: StringRef.h:60
output
Current output
Definition: README.txt:1350
Allocator.h
true
basic Basic Alias true
Definition: BasicAliasAnalysis.cpp:1909
llvm::yaml::BlockScalarNode::classof
static bool classof(const Node *N)
Definition: YAMLParser.h:269
YamlIO
IO & YamlIO
Definition: ELFYAML.cpp:1235
error
#define error(X)
Definition: SymbolRecordMapping.cpp:14
llvm::BumpPtrAllocator
BumpPtrAllocatorImpl BumpPtrAllocator
The standard BumpPtrAllocator which just uses the default template parameters.
Definition: Allocator.h:372
T
#define T
Definition: Mips16ISelLowering.cpp:341
llvm::errs
raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
Definition: raw_ostream.cpp:893
AlignOf.h
llvm::RISCVFeatures::validate
void validate(const Triple &TT, const FeatureBitset &FeatureBits)
Definition: RISCVBaseInfo.cpp:97
llvm::dwarf::Tag
Tag
Definition: Dwarf.h:105
SpecialSubKind::allocator
@ allocator
llvm::yaml::NullNode::classof
static bool classof(const Node *N)
Definition: YAMLParser.h:203
p
the resulting code requires compare and branches when and if * p
Definition: README.txt:396
llvm::pdb::Double
@ Double
Definition: PDBTypes.h:402
size_t
llvm::RISCVFenceField::R
@ R
Definition: RISCVBaseInfo.h:240
Context
LLVMContext & Context
Definition: NVVMIntrRange.cpp:66
llvm::support::endian
Definition: Endian.h:42
llvm::BitmaskEnumDetail::Mask
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
Definition: BitmaskEnum.h:80
llvm::SmallVector
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
Definition: SmallVector.h:1112
llvm::operator>>
ScaledNumber< DigitsT > operator>>(const ScaledNumber< DigitsT > &L, int16_t Shift)
Definition: ScaledNumber.h:736
llvm::CallingConv::Tail
@ Tail
Tail - This calling convention attemps to make calls as fast as possible while guaranteeing that tail...
Definition: CallingConv.h:81
llvm::msgpack::Type::Map
@ Map
f
Itanium Name Demangler i e convert the string _Z1fv into f()". You can also use the CRTP base ManglingParser to perform some simple analysis on the mangled name
E
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
C
(vector float) vec_cmpeq(*A, *B) C
Definition: README_ALTIVEC.txt:86
llvm::cl::Required
@ Required
Definition: CommandLine.h:117
Twine.h
llvm::SrcMgr
SourceMgr SrcMgr
Definition: Error.cpp:24
llvm::ms_demangle::QualifierMangleMode::Result
@ Result
llvm::AMDGPU::PALMD::Key
Key
PAL metadata keys.
Definition: AMDGPUMetadata.h:486
llvm::seq
auto seq(T Begin, T End)
Iterate over an integral type from Begin up to - but not including - End.
Definition: Sequence.h:306
SMLoc.h
llvm::raw_ostream
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:54
llvm::yaml::ScalarNode::classof
static bool classof(const Node *N)
Definition: YAMLParser.h:235
llvm::operator<<
raw_ostream & operator<<(raw_ostream &OS, const APFixedPoint &FX)
Definition: APFixedPoint.h:230
BitVector.h
llvm::yaml::MappingNode::classof
static bool classof(const Node *N)
Definition: YAMLParser.h:440
llvm::SPIRV::StorageClass::Output
@ Output
llvm::BitVector
Definition: BitVector.h:75
StringMap.h
llvm::yaml::SequenceNode::classof
static bool classof(const Node *N)
Definition: YAMLParser.h:497
input
The initial backend is deliberately restricted to z10 We should add support for later architectures at some point If an asm ties an i32 r result to an i64 input
Definition: README.txt:10
llvm::NVPTX::PTXLdStInstCode::Scalar
@ Scalar
Definition: NVPTX.h:122
llvm::None
const NoneType None
Definition: None.h:24
SourceMgr.h
llvm::tgtok::In
@ In
Definition: TGLexer.h:51
BaseType
BaseType
A given derived pointer can have multiple base pointers through phi/selects.
Definition: SafepointIRVerifier.cpp:314
type
AMD64 Optimization Manual has some nice information about optimizing integer multiplication by a constant How much of it applies to Intel s X86 implementation There are definite trade offs to xmm0 cvttss2siq rdx jb L3 subss xmm0 rax cvttss2siq rdx xorq rdx rax ret instead of xmm1 cvttss2siq rcx movaps xmm2 subss xmm2 cvttss2siq rax rdx xorq rax ucomiss xmm0 cmovb rax ret Seems like the jb branch has high likelihood of being taken It would have saved a few instructions It s not possible to reference and DH registers in an instruction requiring REX prefix divb and mulb both produce results in AH If isel emits a CopyFromReg which gets turned into a movb and that can be allocated a r8b r15b To get around isel emits a CopyFromReg from AX and then right shift it down by and truncate it It s not pretty but it works We need some register allocation magic to make the hack go which would often require a callee saved register Callees usually need to keep this value live for most of their body so it doesn t add a significant burden on them We currently implement this in however this is suboptimal because it means that it would be quite awkward to implement the optimization for callers A better implementation would be to relax the LLVM IR rules for sret arguments to allow a function with an sret argument to have a non void return type
Definition: README-X86-64.txt:70
llvm::count
auto count(R &&Range, const E &Element)
Wrapper function around std::count to count the number of times an element Element occurs in the give...
Definition: STLExtras.h:1699
index
splat index
Definition: README_ALTIVEC.txt:181
uint64_t
LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR
#define LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(type)
s
multiplies can be turned into SHL s
Definition: README.txt:370
LLVM_YAML_STRONG_TYPEDEF
#define LLVM_YAML_STRONG_TYPEDEF(_base, _type)
llvm::SourceMgr::DiagHandlerTy
void(*)(const SMDiagnostic &, void *Context) DiagHandlerTy
Clients that want to handle their own diagnostics in a custom way can register a function pointer+con...
Definition: SourceMgr.h:43
StringExtras.h
node
This currently compiles esp xmm0 movsd esp eax eax esp ret We should use not the dag combiner This is because dagcombine2 needs to be able to see through the X86ISD::Wrapper node
Definition: README-SSE.txt:406
size
i< reg-> size
Definition: README.txt:166
message
message(STATUS "Targeting ${t}") add_subdirectory($
Definition: CMakeLists.txt:33
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
llvm::codeview::CompileSym2Flags::EC
@ EC
mapOptional
static void mapOptional(yaml::IO &IO, const char *Key, EndianType &Val, typename EndianType::value_type Default)
Perform an optional yaml-mapping of an endian-aware type EndianType.
Definition: MinidumpYAML.cpp:20
llvm::size
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
Definition: STLExtras.h:1588
Fallback
@ Fallback
Definition: WholeProgramDevirt.cpp:183
DiagHandler
static void DiagHandler(const SMDiagnostic &Diag, void *Context)
Definition: TextStub.cpp:1094
this
Analysis the ScalarEvolution expression for r is this
Definition: README.txt:8
uint32_t
S
add sub stmia L5 ldr r0 bl L_printf $stub Instead of a and a wouldn t it be better to do three moves *Return an aggregate type is even return S
Definition: README.txt:210
Node
Definition: ItaniumDemangle.h:155
llvm::pdb::Single
@ Single
Definition: PDBTypes.h:401
NodeKind
Determine the kind of a node from its type.
Definition: ItaniumDemangle.h:2360
std
Definition: BitVector.h:851
uint16_t
llvm::TargetStackID::Value
Value
Definition: TargetFrameLowering.h:27
llvm::TargetStackID::Default
@ Default
Definition: TargetFrameLowering.h:28
llvm::pdb::PDB_ColorItem::Padding
@ Padding
llvm::ms_demangle::NodeKind
NodeKind
Definition: MicrosoftDemangleNodes.h:226
SmallVector.h
llvm::TPLoop::Allow
@ Allow
Definition: ARMTargetTransformInfo.h:53
N
#define N
support
Reimplement select in terms of SEL *We would really like to support but we need to prove that the add doesn t need to overflow between the two bit chunks *Implement pre post increment support(e.g. PR935) *Implement smarter const ant generation for binops with large immediates. A few ARMv6T2 ops should be pattern matched
Definition: README.txt:10
llvm::pdb::OMFSegDescFlags::Write
@ Write
raw_ostream.h
n
The same transformation can work with an even modulo with the addition of a and shrink the compare RHS by the same amount Unless the target supports that transformation probably isn t worthwhile The transformation can also easily be made to work with non zero equality for n
Definition: README.txt:685
test
modulo schedule test
Definition: ModuloSchedule.cpp:2102
Endian.h
SpecialSubKind::string
@ string