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