Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
14 pmbaty 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/ArrayRef.h"
13
#include "llvm/ADT/BitVector.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"
24
#include "llvm/Support/YAMLParser.h"
25
#include "llvm/Support/raw_ostream.h"
26
#include <cassert>
27
#include <map>
28
#include <memory>
29
#include <new>
30
#include <optional>
31
#include <string>
32
#include <system_error>
33
#include <type_traits>
34
#include <vector>
35
 
36
namespace llvm {
37
 
38
class VersionTuple;
39
 
40
namespace yaml {
41
 
42
enum class NodeKind : uint8_t {
43
  Scalar,
44
  Map,
45
  Sequence,
46
};
47
 
48
struct EmptyContext {};
49
 
50
/// This class should be specialized by any type that needs to be converted
51
/// to/from a YAML mapping.  For example:
52
///
53
///     struct MappingTraits<MyStruct> {
54
///       static void mapping(IO &io, MyStruct &s) {
55
///         io.mapRequired("name", s.name);
56
///         io.mapRequired("size", s.size);
57
///         io.mapOptional("age",  s.age);
58
///       }
59
///     };
60
template<class T>
61
struct MappingTraits {
62
  // Must provide:
63
  // static void mapping(IO &io, T &fields);
64
  // Optionally may provide:
65
  // static std::string validate(IO &io, T &fields);
66
  // static void enumInput(IO &io, T &value);
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 MappingContextTraits<T>::enumInput() is defined on type T.
451
template <class T, class Context> struct has_MappingEnumInputTraits {
452
  using Signature_validate = void (*)(class IO &, T &);
453
 
454
  template <typename U>
455
  static char test(SameType<Signature_validate, &U::enumInput> *);
456
 
457
  template <typename U> static double test(...);
458
 
459
  static bool const value =
460
      (sizeof(test<MappingContextTraits<T, Context>>(nullptr)) == 1);
461
};
462
 
463
// Test if MappingTraits<T>::enumInput() is defined on type T.
464
template <class T> struct has_MappingEnumInputTraits<T, EmptyContext> {
465
  using Signature_validate = void (*)(class IO &, T &);
466
 
467
  template <typename U>
468
  static char test(SameType<Signature_validate, &U::enumInput> *);
469
 
470
  template <typename U> static double test(...);
471
 
472
  static bool const value = (sizeof(test<MappingTraits<T>>(nullptr)) == 1);
473
};
474
 
475
// Test if SequenceTraits<T> is defined on type T.
476
template <class T>
477
struct has_SequenceMethodTraits
478
{
479
  using Signature_size = size_t (*)(class IO&, T&);
480
 
481
  template <typename U>
482
  static char test(SameType<Signature_size, &U::size>*);
483
 
484
  template <typename U>
485
  static double test(...);
486
 
487
  static bool const value =  (sizeof(test<SequenceTraits<T>>(nullptr)) == 1);
488
};
489
 
490
// Test if CustomMappingTraits<T> is defined on type T.
491
template <class T>
492
struct has_CustomMappingTraits
493
{
494
  using Signature_input = void (*)(IO &io, StringRef key, T &v);
495
 
496
  template <typename U>
497
  static char test(SameType<Signature_input, &U::inputOne>*);
498
 
499
  template <typename U>
500
  static double test(...);
501
 
502
  static bool const value =
503
      (sizeof(test<CustomMappingTraits<T>>(nullptr)) == 1);
504
};
505
 
506
// has_FlowTraits<int> will cause an error with some compilers because
507
// it subclasses int.  Using this wrapper only instantiates the
508
// real has_FlowTraits only if the template type is a class.
509
template <typename T, bool Enabled = std::is_class<T>::value>
510
class has_FlowTraits
511
{
512
public:
513
   static const bool value = false;
514
};
515
 
516
// Some older gcc compilers don't support straight forward tests
517
// for members, so test for ambiguity cause by the base and derived
518
// classes both defining the member.
519
template <class T>
520
struct has_FlowTraits<T, true>
521
{
522
  struct Fallback { bool flow; };
523
  struct Derived : T, Fallback { };
524
 
525
  template<typename C>
526
  static char (&f(SameType<bool Fallback::*, &C::flow>*))[1];
527
 
528
  template<typename C>
529
  static char (&f(...))[2];
530
 
531
  static bool const value = sizeof(f<Derived>(nullptr)) == 2;
532
};
533
 
534
// Test if SequenceTraits<T> is defined on type T
535
template<typename T>
536
struct has_SequenceTraits : public std::integral_constant<bool,
537
                                      has_SequenceMethodTraits<T>::value > { };
538
 
539
// Test if DocumentListTraits<T> is defined on type T
540
template <class T>
541
struct has_DocumentListTraits
542
{
543
  using Signature_size = size_t (*)(class IO &, T &);
544
 
545
  template <typename U>
546
  static char test(SameType<Signature_size, &U::size>*);
547
 
548
  template <typename U>
549
  static double test(...);
550
 
551
  static bool const value = (sizeof(test<DocumentListTraits<T>>(nullptr))==1);
552
};
553
 
554
template <class T> struct has_PolymorphicTraits {
555
  using Signature_getKind = NodeKind (*)(const T &);
556
 
557
  template <typename U>
558
  static char test(SameType<Signature_getKind, &U::getKind> *);
559
 
560
  template <typename U> static double test(...);
561
 
562
  static bool const value = (sizeof(test<PolymorphicTraits<T>>(nullptr)) == 1);
563
};
564
 
565
inline bool isNumeric(StringRef S) {
566
  const auto skipDigits = [](StringRef Input) {
567
    return Input.ltrim("0123456789");
568
  };
569
 
570
  // Make S.front() and S.drop_front().front() (if S.front() is [+-]) calls
571
  // safe.
572
  if (S.empty() || S.equals("+") || S.equals("-"))
573
    return false;
574
 
575
  if (S.equals(".nan") || S.equals(".NaN") || S.equals(".NAN"))
576
    return true;
577
 
578
  // Infinity and decimal numbers can be prefixed with sign.
579
  StringRef Tail = (S.front() == '-' || S.front() == '+') ? S.drop_front() : S;
580
 
581
  // Check for infinity first, because checking for hex and oct numbers is more
582
  // expensive.
583
  if (Tail.equals(".inf") || Tail.equals(".Inf") || Tail.equals(".INF"))
584
    return true;
585
 
586
  // Section 10.3.2 Tag Resolution
587
  // YAML 1.2 Specification prohibits Base 8 and Base 16 numbers prefixed with
588
  // [-+], so S should be used instead of Tail.
589
  if (S.startswith("0o"))
590
    return S.size() > 2 &&
591
           S.drop_front(2).find_first_not_of("01234567") == StringRef::npos;
592
 
593
  if (S.startswith("0x"))
594
    return S.size() > 2 && S.drop_front(2).find_first_not_of(
595
                               "0123456789abcdefABCDEF") == StringRef::npos;
596
 
597
  // Parse float: [-+]? (\. [0-9]+ | [0-9]+ (\. [0-9]* )?) ([eE] [-+]? [0-9]+)?
598
  S = Tail;
599
 
600
  // Handle cases when the number starts with '.' and hence needs at least one
601
  // digit after dot (as opposed by number which has digits before the dot), but
602
  // doesn't have one.
603
  if (S.startswith(".") &&
604
      (S.equals(".") ||
605
       (S.size() > 1 && std::strchr("0123456789", S[1]) == nullptr)))
606
    return false;
607
 
608
  if (S.startswith("E") || S.startswith("e"))
609
    return false;
610
 
611
  enum ParseState {
612
    Default,
613
    FoundDot,
614
    FoundExponent,
615
  };
616
  ParseState State = Default;
617
 
618
  S = skipDigits(S);
619
 
620
  // Accept decimal integer.
621
  if (S.empty())
622
    return true;
623
 
624
  if (S.front() == '.') {
625
    State = FoundDot;
626
    S = S.drop_front();
627
  } else if (S.front() == 'e' || S.front() == 'E') {
628
    State = FoundExponent;
629
    S = S.drop_front();
630
  } else {
631
    return false;
632
  }
633
 
634
  if (State == FoundDot) {
635
    S = skipDigits(S);
636
    if (S.empty())
637
      return true;
638
 
639
    if (S.front() == 'e' || S.front() == 'E') {
640
      State = FoundExponent;
641
      S = S.drop_front();
642
    } else {
643
      return false;
644
    }
645
  }
646
 
647
  assert(State == FoundExponent && "Should have found exponent at this point.");
648
  if (S.empty())
649
    return false;
650
 
651
  if (S.front() == '+' || S.front() == '-') {
652
    S = S.drop_front();
653
    if (S.empty())
654
      return false;
655
  }
656
 
657
  return skipDigits(S).empty();
658
}
659
 
660
inline bool isNull(StringRef S) {
661
  return S.equals("null") || S.equals("Null") || S.equals("NULL") ||
662
         S.equals("~");
663
}
664
 
665
inline bool isBool(StringRef S) {
666
  // FIXME: using parseBool is causing multiple tests to fail.
667
  return S.equals("true") || S.equals("True") || S.equals("TRUE") ||
668
         S.equals("false") || S.equals("False") || S.equals("FALSE");
669
}
670
 
671
// 5.1. Character Set
672
// The allowed character range explicitly excludes the C0 control block #x0-#x1F
673
// (except for TAB #x9, LF #xA, and CR #xD which are allowed), DEL #x7F, the C1
674
// control block #x80-#x9F (except for NEL #x85 which is allowed), the surrogate
675
// block #xD800-#xDFFF, #xFFFE, and #xFFFF.
676
inline QuotingType needsQuotes(StringRef S) {
677
  if (S.empty())
678
    return QuotingType::Single;
679
 
680
  QuotingType MaxQuotingNeeded = QuotingType::None;
681
  if (isSpace(static_cast<unsigned char>(S.front())) ||
682
      isSpace(static_cast<unsigned char>(S.back())))
683
    MaxQuotingNeeded = QuotingType::Single;
684
  if (isNull(S))
685
    MaxQuotingNeeded = QuotingType::Single;
686
  if (isBool(S))
687
    MaxQuotingNeeded = QuotingType::Single;
688
  if (isNumeric(S))
689
    MaxQuotingNeeded = QuotingType::Single;
690
 
691
  // 7.3.3 Plain Style
692
  // Plain scalars must not begin with most indicators, as this would cause
693
  // ambiguity with other YAML constructs.
694
  if (std::strchr(R"(-?:\,[]{}#&*!|>'"%@`)", S[0]) != nullptr)
695
    MaxQuotingNeeded = QuotingType::Single;
696
 
697
  for (unsigned char C : S) {
698
    // Alphanum is safe.
699
    if (isAlnum(C))
700
      continue;
701
 
702
    switch (C) {
703
    // Safe scalar characters.
704
    case '_':
705
    case '-':
706
    case '^':
707
    case '.':
708
    case ',':
709
    case ' ':
710
    // TAB (0x9) is allowed in unquoted strings.
711
    case 0x9:
712
      continue;
713
    // LF(0xA) and CR(0xD) may delimit values and so require at least single
714
    // quotes. LLVM YAML parser cannot handle single quoted multiline so use
715
    // double quoting to produce valid YAML.
716
    case 0xA:
717
    case 0xD:
718
      return QuotingType::Double;
719
    // DEL (0x7F) are excluded from the allowed character range.
720
    case 0x7F:
721
      return QuotingType::Double;
722
    // Forward slash is allowed to be unquoted, but we quote it anyway.  We have
723
    // many tests that use FileCheck against YAML output, and this output often
724
    // contains paths.  If we quote backslashes but not forward slashes then
725
    // paths will come out either quoted or unquoted depending on which platform
726
    // the test is run on, making FileCheck comparisons difficult.
727
    case '/':
728
    default: {
729
      // C0 control block (0x0 - 0x1F) is excluded from the allowed character
730
      // range.
731
      if (C <= 0x1F)
732
        return QuotingType::Double;
733
 
734
      // Always double quote UTF-8.
735
      if ((C & 0x80) != 0)
736
        return QuotingType::Double;
737
 
738
      // The character is not safe, at least simple quoting needed.
739
      MaxQuotingNeeded = QuotingType::Single;
740
    }
741
    }
742
  }
743
 
744
  return MaxQuotingNeeded;
745
}
746
 
747
template <typename T, typename Context>
748
struct missingTraits
749
    : public std::integral_constant<bool,
750
                                    !has_ScalarEnumerationTraits<T>::value &&
751
                                        !has_ScalarBitSetTraits<T>::value &&
752
                                        !has_ScalarTraits<T>::value &&
753
                                        !has_BlockScalarTraits<T>::value &&
754
                                        !has_TaggedScalarTraits<T>::value &&
755
                                        !has_MappingTraits<T, Context>::value &&
756
                                        !has_SequenceTraits<T>::value &&
757
                                        !has_CustomMappingTraits<T>::value &&
758
                                        !has_DocumentListTraits<T>::value &&
759
                                        !has_PolymorphicTraits<T>::value> {};
760
 
761
template <typename T, typename Context>
762
struct validatedMappingTraits
763
    : public std::integral_constant<
764
          bool, has_MappingTraits<T, Context>::value &&
765
                    has_MappingValidateTraits<T, Context>::value> {};
766
 
767
template <typename T, typename Context>
768
struct unvalidatedMappingTraits
769
    : public std::integral_constant<
770
          bool, has_MappingTraits<T, Context>::value &&
771
                    !has_MappingValidateTraits<T, Context>::value> {};
772
 
773
// Base class for Input and Output.
774
class IO {
775
public:
776
  IO(void *Ctxt = nullptr);
777
  virtual ~IO();
778
 
779
  virtual bool outputting() const = 0;
780
 
781
  virtual unsigned beginSequence() = 0;
782
  virtual bool preflightElement(unsigned, void *&) = 0;
783
  virtual void postflightElement(void*) = 0;
784
  virtual void endSequence() = 0;
785
  virtual bool canElideEmptySequence() = 0;
786
 
787
  virtual unsigned beginFlowSequence() = 0;
788
  virtual bool preflightFlowElement(unsigned, void *&) = 0;
789
  virtual void postflightFlowElement(void*) = 0;
790
  virtual void endFlowSequence() = 0;
791
 
792
  virtual bool mapTag(StringRef Tag, bool Default=false) = 0;
793
  virtual void beginMapping() = 0;
794
  virtual void endMapping() = 0;
795
  virtual bool preflightKey(const char*, bool, bool, bool &, void *&) = 0;
796
  virtual void postflightKey(void*) = 0;
797
  virtual std::vector<StringRef> keys() = 0;
798
 
799
  virtual void beginFlowMapping() = 0;
800
  virtual void endFlowMapping() = 0;
801
 
802
  virtual void beginEnumScalar() = 0;
803
  virtual bool matchEnumScalar(const char*, bool) = 0;
804
  virtual bool matchEnumFallback() = 0;
805
  virtual void endEnumScalar() = 0;
806
 
807
  virtual bool beginBitSetScalar(bool &) = 0;
808
  virtual bool bitSetMatch(const char*, bool) = 0;
809
  virtual void endBitSetScalar() = 0;
810
 
811
  virtual void scalarString(StringRef &, QuotingType) = 0;
812
  virtual void blockScalarString(StringRef &) = 0;
813
  virtual void scalarTag(std::string &) = 0;
814
 
815
  virtual NodeKind getNodeKind() = 0;
816
 
817
  virtual void setError(const Twine &) = 0;
818
  virtual void setAllowUnknownKeys(bool Allow);
819
 
820
  template <typename T>
821
  void enumCase(T &Val, const char* Str, const T ConstVal) {
822
    if ( matchEnumScalar(Str, outputting() && Val == ConstVal) ) {
823
      Val = ConstVal;
824
    }
825
  }
826
 
827
  // allow anonymous enum values to be used with LLVM_YAML_STRONG_TYPEDEF
828
  template <typename T>
829
  void enumCase(T &Val, const char* Str, const uint32_t ConstVal) {
830
    if ( matchEnumScalar(Str, outputting() && Val == static_cast<T>(ConstVal)) ) {
831
      Val = ConstVal;
832
    }
833
  }
834
 
835
  template <typename FBT, typename T>
836
  void enumFallback(T &Val) {
837
    if (matchEnumFallback()) {
838
      EmptyContext Context;
839
      // FIXME: Force integral conversion to allow strong typedefs to convert.
840
      FBT Res = static_cast<typename FBT::BaseType>(Val);
841
      yamlize(*this, Res, true, Context);
842
      Val = static_cast<T>(static_cast<typename FBT::BaseType>(Res));
843
    }
844
  }
845
 
846
  template <typename T>
847
  void bitSetCase(T &Val, const char* Str, const T ConstVal) {
848
    if ( bitSetMatch(Str, outputting() && (Val & ConstVal) == ConstVal) ) {
849
      Val = static_cast<T>(Val | ConstVal);
850
    }
851
  }
852
 
853
  // allow anonymous enum values to be used with LLVM_YAML_STRONG_TYPEDEF
854
  template <typename T>
855
  void bitSetCase(T &Val, const char* Str, const uint32_t ConstVal) {
856
    if ( bitSetMatch(Str, outputting() && (Val & ConstVal) == ConstVal) ) {
857
      Val = static_cast<T>(Val | ConstVal);
858
    }
859
  }
860
 
861
  template <typename T>
862
  void maskedBitSetCase(T &Val, const char *Str, T ConstVal, T Mask) {
863
    if (bitSetMatch(Str, outputting() && (Val & Mask) == ConstVal))
864
      Val = Val | ConstVal;
865
  }
866
 
867
  template <typename T>
868
  void maskedBitSetCase(T &Val, const char *Str, uint32_t ConstVal,
869
                        uint32_t Mask) {
870
    if (bitSetMatch(Str, outputting() && (Val & Mask) == ConstVal))
871
      Val = Val | ConstVal;
872
  }
873
 
874
  void *getContext() const;
875
  void setContext(void *);
876
 
877
  template <typename T> void mapRequired(const char *Key, T &Val) {
878
    EmptyContext Ctx;
879
    this->processKey(Key, Val, true, Ctx);
880
  }
881
 
882
  template <typename T, typename Context>
883
  void mapRequired(const char *Key, T &Val, Context &Ctx) {
884
    this->processKey(Key, Val, true, Ctx);
885
  }
886
 
887
  template <typename T> void mapOptional(const char *Key, T &Val) {
888
    EmptyContext Ctx;
889
    mapOptionalWithContext(Key, Val, Ctx);
890
  }
891
 
892
  template <typename T, typename DefaultT>
893
  void mapOptional(const char *Key, T &Val, const DefaultT &Default) {
894
    EmptyContext Ctx;
895
    mapOptionalWithContext(Key, Val, Default, Ctx);
896
  }
897
 
898
  template <typename T, typename Context>
899
  std::enable_if_t<has_SequenceTraits<T>::value, void>
900
  mapOptionalWithContext(const char *Key, T &Val, Context &Ctx) {
901
    // omit key/value instead of outputting empty sequence
902
    if (this->canElideEmptySequence() && !(Val.begin() != Val.end()))
903
      return;
904
    this->processKey(Key, Val, false, Ctx);
905
  }
906
 
907
  template <typename T, typename Context>
908
  void mapOptionalWithContext(const char *Key, std::optional<T> &Val,
909
                              Context &Ctx) {
910
    this->processKeyWithDefault(Key, Val, std::optional<T>(),
911
                                /*Required=*/false, Ctx);
912
  }
913
 
914
  template <typename T, typename Context>
915
  std::enable_if_t<!has_SequenceTraits<T>::value, void>
916
  mapOptionalWithContext(const char *Key, T &Val, Context &Ctx) {
917
    this->processKey(Key, Val, false, Ctx);
918
  }
919
 
920
  template <typename T, typename Context, typename DefaultT>
921
  void mapOptionalWithContext(const char *Key, T &Val, const DefaultT &Default,
922
                              Context &Ctx) {
923
    static_assert(std::is_convertible<DefaultT, T>::value,
924
                  "Default type must be implicitly convertible to value type!");
925
    this->processKeyWithDefault(Key, Val, static_cast<const T &>(Default),
926
                                false, Ctx);
927
  }
928
 
929
private:
930
  template <typename T, typename Context>
931
  void processKeyWithDefault(const char *Key, std::optional<T> &Val,
932
                             const std::optional<T> &DefaultValue,
933
                             bool Required, Context &Ctx);
934
 
935
  template <typename T, typename Context>
936
  void processKeyWithDefault(const char *Key, T &Val, const T &DefaultValue,
937
                             bool Required, Context &Ctx) {
938
    void *SaveInfo;
939
    bool UseDefault;
940
    const bool sameAsDefault = outputting() && Val == DefaultValue;
941
    if ( this->preflightKey(Key, Required, sameAsDefault, UseDefault,
942
                                                                  SaveInfo) ) {
943
      yamlize(*this, Val, Required, Ctx);
944
      this->postflightKey(SaveInfo);
945
    }
946
    else {
947
      if ( UseDefault )
948
        Val = DefaultValue;
949
    }
950
  }
951
 
952
  template <typename T, typename Context>
953
  void processKey(const char *Key, T &Val, bool Required, Context &Ctx) {
954
    void *SaveInfo;
955
    bool UseDefault;
956
    if ( this->preflightKey(Key, Required, false, UseDefault, SaveInfo) ) {
957
      yamlize(*this, Val, Required, Ctx);
958
      this->postflightKey(SaveInfo);
959
    }
960
  }
961
 
962
private:
963
  void *Ctxt;
964
};
965
 
966
namespace detail {
967
 
968
template <typename T, typename Context>
969
void doMapping(IO &io, T &Val, Context &Ctx) {
970
  MappingContextTraits<T, Context>::mapping(io, Val, Ctx);
971
}
972
 
973
template <typename T> void doMapping(IO &io, T &Val, EmptyContext &Ctx) {
974
  MappingTraits<T>::mapping(io, Val);
975
}
976
 
977
} // end namespace detail
978
 
979
template <typename T>
980
std::enable_if_t<has_ScalarEnumerationTraits<T>::value, void>
981
yamlize(IO &io, T &Val, bool, EmptyContext &Ctx) {
982
  io.beginEnumScalar();
983
  ScalarEnumerationTraits<T>::enumeration(io, Val);
984
  io.endEnumScalar();
985
}
986
 
987
template <typename T>
988
std::enable_if_t<has_ScalarBitSetTraits<T>::value, void>
989
yamlize(IO &io, T &Val, bool, EmptyContext &Ctx) {
990
  bool DoClear;
991
  if ( io.beginBitSetScalar(DoClear) ) {
992
    if ( DoClear )
993
      Val = T();
994
    ScalarBitSetTraits<T>::bitset(io, Val);
995
    io.endBitSetScalar();
996
  }
997
}
998
 
999
template <typename T>
1000
std::enable_if_t<has_ScalarTraits<T>::value, void> yamlize(IO &io, T &Val, bool,
1001
                                                           EmptyContext &Ctx) {
1002
  if ( io.outputting() ) {
1003
    SmallString<128> Storage;
1004
    raw_svector_ostream Buffer(Storage);
1005
    ScalarTraits<T>::output(Val, io.getContext(), Buffer);
1006
    StringRef Str = Buffer.str();
1007
    io.scalarString(Str, ScalarTraits<T>::mustQuote(Str));
1008
  }
1009
  else {
1010
    StringRef Str;
1011
    io.scalarString(Str, ScalarTraits<T>::mustQuote(Str));
1012
    StringRef Result = ScalarTraits<T>::input(Str, io.getContext(), Val);
1013
    if ( !Result.empty() ) {
1014
      io.setError(Twine(Result));
1015
    }
1016
  }
1017
}
1018
 
1019
template <typename T>
1020
std::enable_if_t<has_BlockScalarTraits<T>::value, void>
1021
yamlize(IO &YamlIO, T &Val, bool, EmptyContext &Ctx) {
1022
  if (YamlIO.outputting()) {
1023
    std::string Storage;
1024
    raw_string_ostream Buffer(Storage);
1025
    BlockScalarTraits<T>::output(Val, YamlIO.getContext(), Buffer);
1026
    StringRef Str = Buffer.str();
1027
    YamlIO.blockScalarString(Str);
1028
  } else {
1029
    StringRef Str;
1030
    YamlIO.blockScalarString(Str);
1031
    StringRef Result =
1032
        BlockScalarTraits<T>::input(Str, YamlIO.getContext(), Val);
1033
    if (!Result.empty())
1034
      YamlIO.setError(Twine(Result));
1035
  }
1036
}
1037
 
1038
template <typename T>
1039
std::enable_if_t<has_TaggedScalarTraits<T>::value, void>
1040
yamlize(IO &io, T &Val, bool, EmptyContext &Ctx) {
1041
  if (io.outputting()) {
1042
    std::string ScalarStorage, TagStorage;
1043
    raw_string_ostream ScalarBuffer(ScalarStorage), TagBuffer(TagStorage);
1044
    TaggedScalarTraits<T>::output(Val, io.getContext(), ScalarBuffer,
1045
                                  TagBuffer);
1046
    io.scalarTag(TagBuffer.str());
1047
    StringRef ScalarStr = ScalarBuffer.str();
1048
    io.scalarString(ScalarStr,
1049
                    TaggedScalarTraits<T>::mustQuote(Val, ScalarStr));
1050
  } else {
1051
    std::string Tag;
1052
    io.scalarTag(Tag);
1053
    StringRef Str;
1054
    io.scalarString(Str, QuotingType::None);
1055
    StringRef Result =
1056
        TaggedScalarTraits<T>::input(Str, Tag, io.getContext(), Val);
1057
    if (!Result.empty()) {
1058
      io.setError(Twine(Result));
1059
    }
1060
  }
1061
}
1062
 
1063
template <typename T, typename Context>
1064
std::enable_if_t<validatedMappingTraits<T, Context>::value, void>
1065
yamlize(IO &io, T &Val, bool, Context &Ctx) {
1066
  if (has_FlowTraits<MappingTraits<T>>::value)
1067
    io.beginFlowMapping();
1068
  else
1069
    io.beginMapping();
1070
  if (io.outputting()) {
1071
    std::string Err = MappingTraits<T>::validate(io, Val);
1072
    if (!Err.empty()) {
1073
      errs() << Err << "\n";
1074
      assert(Err.empty() && "invalid struct trying to be written as yaml");
1075
    }
1076
  }
1077
  detail::doMapping(io, Val, Ctx);
1078
  if (!io.outputting()) {
1079
    std::string Err = MappingTraits<T>::validate(io, Val);
1080
    if (!Err.empty())
1081
      io.setError(Err);
1082
  }
1083
  if (has_FlowTraits<MappingTraits<T>>::value)
1084
    io.endFlowMapping();
1085
  else
1086
    io.endMapping();
1087
}
1088
 
1089
template <typename T, typename Context>
1090
std::enable_if_t<!has_MappingEnumInputTraits<T, Context>::value, bool>
1091
yamlizeMappingEnumInput(IO &io, T &Val) {
1092
  return false;
1093
}
1094
 
1095
template <typename T, typename Context>
1096
std::enable_if_t<has_MappingEnumInputTraits<T, Context>::value, bool>
1097
yamlizeMappingEnumInput(IO &io, T &Val) {
1098
  if (io.outputting())
1099
    return false;
1100
 
1101
  io.beginEnumScalar();
1102
  MappingTraits<T>::enumInput(io, Val);
1103
  bool Matched = !io.matchEnumFallback();
1104
  io.endEnumScalar();
1105
  return Matched;
1106
}
1107
 
1108
template <typename T, typename Context>
1109
std::enable_if_t<unvalidatedMappingTraits<T, Context>::value, void>
1110
yamlize(IO &io, T &Val, bool, Context &Ctx) {
1111
  if (yamlizeMappingEnumInput<T, Context>(io, Val))
1112
    return;
1113
  if (has_FlowTraits<MappingTraits<T>>::value) {
1114
    io.beginFlowMapping();
1115
    detail::doMapping(io, Val, Ctx);
1116
    io.endFlowMapping();
1117
  } else {
1118
    io.beginMapping();
1119
    detail::doMapping(io, Val, Ctx);
1120
    io.endMapping();
1121
  }
1122
}
1123
 
1124
template <typename T>
1125
std::enable_if_t<has_CustomMappingTraits<T>::value, void>
1126
yamlize(IO &io, T &Val, bool, EmptyContext &Ctx) {
1127
  if ( io.outputting() ) {
1128
    io.beginMapping();
1129
    CustomMappingTraits<T>::output(io, Val);
1130
    io.endMapping();
1131
  } else {
1132
    io.beginMapping();
1133
    for (StringRef key : io.keys())
1134
      CustomMappingTraits<T>::inputOne(io, key, Val);
1135
    io.endMapping();
1136
  }
1137
}
1138
 
1139
template <typename T>
1140
std::enable_if_t<has_PolymorphicTraits<T>::value, void>
1141
yamlize(IO &io, T &Val, bool, EmptyContext &Ctx) {
1142
  switch (io.outputting() ? PolymorphicTraits<T>::getKind(Val)
1143
                          : io.getNodeKind()) {
1144
  case NodeKind::Scalar:
1145
    return yamlize(io, PolymorphicTraits<T>::getAsScalar(Val), true, Ctx);
1146
  case NodeKind::Map:
1147
    return yamlize(io, PolymorphicTraits<T>::getAsMap(Val), true, Ctx);
1148
  case NodeKind::Sequence:
1149
    return yamlize(io, PolymorphicTraits<T>::getAsSequence(Val), true, Ctx);
1150
  }
1151
}
1152
 
1153
template <typename T>
1154
std::enable_if_t<missingTraits<T, EmptyContext>::value, void>
1155
yamlize(IO &io, T &Val, bool, EmptyContext &Ctx) {
1156
  char missing_yaml_trait_for_type[sizeof(MissingTrait<T>)];
1157
}
1158
 
1159
template <typename T, typename Context>
1160
std::enable_if_t<has_SequenceTraits<T>::value, void>
1161
yamlize(IO &io, T &Seq, bool, Context &Ctx) {
1162
  if ( has_FlowTraits< SequenceTraits<T>>::value ) {
1163
    unsigned incnt = io.beginFlowSequence();
1164
    unsigned count = io.outputting() ? SequenceTraits<T>::size(io, Seq) : incnt;
1165
    for(unsigned i=0; i < count; ++i) {
1166
      void *SaveInfo;
1167
      if ( io.preflightFlowElement(i, SaveInfo) ) {
1168
        yamlize(io, SequenceTraits<T>::element(io, Seq, i), true, Ctx);
1169
        io.postflightFlowElement(SaveInfo);
1170
      }
1171
    }
1172
    io.endFlowSequence();
1173
  }
1174
  else {
1175
    unsigned incnt = io.beginSequence();
1176
    unsigned count = io.outputting() ? SequenceTraits<T>::size(io, Seq) : incnt;
1177
    for(unsigned i=0; i < count; ++i) {
1178
      void *SaveInfo;
1179
      if ( io.preflightElement(i, SaveInfo) ) {
1180
        yamlize(io, SequenceTraits<T>::element(io, Seq, i), true, Ctx);
1181
        io.postflightElement(SaveInfo);
1182
      }
1183
    }
1184
    io.endSequence();
1185
  }
1186
}
1187
 
1188
template<>
1189
struct ScalarTraits<bool> {
1190
  static void output(const bool &, void* , raw_ostream &);
1191
  static StringRef input(StringRef, void *, bool &);
1192
  static QuotingType mustQuote(StringRef) { return QuotingType::None; }
1193
};
1194
 
1195
template<>
1196
struct ScalarTraits<StringRef> {
1197
  static void output(const StringRef &, void *, raw_ostream &);
1198
  static StringRef input(StringRef, void *, StringRef &);
1199
  static QuotingType mustQuote(StringRef S) { return needsQuotes(S); }
1200
};
1201
 
1202
template<>
1203
struct ScalarTraits<std::string> {
1204
  static void output(const std::string &, void *, raw_ostream &);
1205
  static StringRef input(StringRef, void *, std::string &);
1206
  static QuotingType mustQuote(StringRef S) { return needsQuotes(S); }
1207
};
1208
 
1209
template<>
1210
struct ScalarTraits<uint8_t> {
1211
  static void output(const uint8_t &, void *, raw_ostream &);
1212
  static StringRef input(StringRef, void *, uint8_t &);
1213
  static QuotingType mustQuote(StringRef) { return QuotingType::None; }
1214
};
1215
 
1216
template<>
1217
struct ScalarTraits<uint16_t> {
1218
  static void output(const uint16_t &, void *, raw_ostream &);
1219
  static StringRef input(StringRef, void *, uint16_t &);
1220
  static QuotingType mustQuote(StringRef) { return QuotingType::None; }
1221
};
1222
 
1223
template<>
1224
struct ScalarTraits<uint32_t> {
1225
  static void output(const uint32_t &, void *, raw_ostream &);
1226
  static StringRef input(StringRef, void *, uint32_t &);
1227
  static QuotingType mustQuote(StringRef) { return QuotingType::None; }
1228
};
1229
 
1230
template<>
1231
struct ScalarTraits<uint64_t> {
1232
  static void output(const uint64_t &, void *, raw_ostream &);
1233
  static StringRef input(StringRef, void *, uint64_t &);
1234
  static QuotingType mustQuote(StringRef) { return QuotingType::None; }
1235
};
1236
 
1237
template<>
1238
struct ScalarTraits<int8_t> {
1239
  static void output(const int8_t &, void *, raw_ostream &);
1240
  static StringRef input(StringRef, void *, int8_t &);
1241
  static QuotingType mustQuote(StringRef) { return QuotingType::None; }
1242
};
1243
 
1244
template<>
1245
struct ScalarTraits<int16_t> {
1246
  static void output(const int16_t &, void *, raw_ostream &);
1247
  static StringRef input(StringRef, void *, int16_t &);
1248
  static QuotingType mustQuote(StringRef) { return QuotingType::None; }
1249
};
1250
 
1251
template<>
1252
struct ScalarTraits<int32_t> {
1253
  static void output(const int32_t &, void *, raw_ostream &);
1254
  static StringRef input(StringRef, void *, int32_t &);
1255
  static QuotingType mustQuote(StringRef) { return QuotingType::None; }
1256
};
1257
 
1258
template<>
1259
struct ScalarTraits<int64_t> {
1260
  static void output(const int64_t &, void *, raw_ostream &);
1261
  static StringRef input(StringRef, void *, int64_t &);
1262
  static QuotingType mustQuote(StringRef) { return QuotingType::None; }
1263
};
1264
 
1265
template<>
1266
struct ScalarTraits<float> {
1267
  static void output(const float &, void *, raw_ostream &);
1268
  static StringRef input(StringRef, void *, float &);
1269
  static QuotingType mustQuote(StringRef) { return QuotingType::None; }
1270
};
1271
 
1272
template<>
1273
struct ScalarTraits<double> {
1274
  static void output(const double &, void *, raw_ostream &);
1275
  static StringRef input(StringRef, void *, double &);
1276
  static QuotingType mustQuote(StringRef) { return QuotingType::None; }
1277
};
1278
 
1279
// For endian types, we use existing scalar Traits class for the underlying
1280
// type.  This way endian aware types are supported whenever the traits are
1281
// defined for the underlying type.
1282
template <typename value_type, support::endianness endian, size_t alignment>
1283
struct ScalarTraits<support::detail::packed_endian_specific_integral<
1284
                        value_type, endian, alignment>,
1285
                    std::enable_if_t<has_ScalarTraits<value_type>::value>> {
1286
  using endian_type =
1287
      support::detail::packed_endian_specific_integral<value_type, endian,
1288
                                                       alignment>;
1289
 
1290
  static void output(const endian_type &E, void *Ctx, raw_ostream &Stream) {
1291
    ScalarTraits<value_type>::output(static_cast<value_type>(E), Ctx, Stream);
1292
  }
1293
 
1294
  static StringRef input(StringRef Str, void *Ctx, endian_type &E) {
1295
    value_type V;
1296
    auto R = ScalarTraits<value_type>::input(Str, Ctx, V);
1297
    E = static_cast<endian_type>(V);
1298
    return R;
1299
  }
1300
 
1301
  static QuotingType mustQuote(StringRef Str) {
1302
    return ScalarTraits<value_type>::mustQuote(Str);
1303
  }
1304
};
1305
 
1306
template <typename value_type, support::endianness endian, size_t alignment>
1307
struct ScalarEnumerationTraits<
1308
    support::detail::packed_endian_specific_integral<value_type, endian,
1309
                                                     alignment>,
1310
    std::enable_if_t<has_ScalarEnumerationTraits<value_type>::value>> {
1311
  using endian_type =
1312
      support::detail::packed_endian_specific_integral<value_type, endian,
1313
                                                       alignment>;
1314
 
1315
  static void enumeration(IO &io, endian_type &E) {
1316
    value_type V = E;
1317
    ScalarEnumerationTraits<value_type>::enumeration(io, V);
1318
    E = V;
1319
  }
1320
};
1321
 
1322
template <typename value_type, support::endianness endian, size_t alignment>
1323
struct ScalarBitSetTraits<
1324
    support::detail::packed_endian_specific_integral<value_type, endian,
1325
                                                     alignment>,
1326
    std::enable_if_t<has_ScalarBitSetTraits<value_type>::value>> {
1327
  using endian_type =
1328
      support::detail::packed_endian_specific_integral<value_type, endian,
1329
                                                       alignment>;
1330
  static void bitset(IO &io, endian_type &E) {
1331
    value_type V = E;
1332
    ScalarBitSetTraits<value_type>::bitset(io, V);
1333
    E = V;
1334
  }
1335
};
1336
 
1337
// Utility for use within MappingTraits<>::mapping() method
1338
// to [de]normalize an object for use with YAML conversion.
1339
template <typename TNorm, typename TFinal>
1340
struct MappingNormalization {
1341
  MappingNormalization(IO &i_o, TFinal &Obj)
1342
      : io(i_o), BufPtr(nullptr), Result(Obj) {
1343
    if ( io.outputting() ) {
1344
      BufPtr = new (&Buffer) TNorm(io, Obj);
1345
    }
1346
    else {
1347
      BufPtr = new (&Buffer) TNorm(io);
1348
    }
1349
  }
1350
 
1351
  ~MappingNormalization() {
1352
    if ( ! io.outputting() ) {
1353
      Result = BufPtr->denormalize(io);
1354
    }
1355
    BufPtr->~TNorm();
1356
  }
1357
 
1358
  TNorm* operator->() { return BufPtr; }
1359
 
1360
private:
1361
  using Storage = AlignedCharArrayUnion<TNorm>;
1362
 
1363
  Storage       Buffer;
1364
  IO           &io;
1365
  TNorm        *BufPtr;
1366
  TFinal       &Result;
1367
};
1368
 
1369
// Utility for use within MappingTraits<>::mapping() method
1370
// to [de]normalize an object for use with YAML conversion.
1371
template <typename TNorm, typename TFinal>
1372
struct MappingNormalizationHeap {
1373
  MappingNormalizationHeap(IO &i_o, TFinal &Obj, BumpPtrAllocator *allocator)
1374
    : io(i_o), Result(Obj) {
1375
    if ( io.outputting() ) {
1376
      BufPtr = new (&Buffer) TNorm(io, Obj);
1377
    }
1378
    else if (allocator) {
1379
      BufPtr = allocator->Allocate<TNorm>();
1380
      new (BufPtr) TNorm(io);
1381
    } else {
1382
      BufPtr = new TNorm(io);
1383
    }
1384
  }
1385
 
1386
  ~MappingNormalizationHeap() {
1387
    if ( io.outputting() ) {
1388
      BufPtr->~TNorm();
1389
    }
1390
    else {
1391
      Result = BufPtr->denormalize(io);
1392
    }
1393
  }
1394
 
1395
  TNorm* operator->() { return BufPtr; }
1396
 
1397
private:
1398
  using Storage = AlignedCharArrayUnion<TNorm>;
1399
 
1400
  Storage       Buffer;
1401
  IO           &io;
1402
  TNorm        *BufPtr = nullptr;
1403
  TFinal       &Result;
1404
};
1405
 
1406
///
1407
/// The Input class is used to parse a yaml document into in-memory structs
1408
/// and vectors.
1409
///
1410
/// It works by using YAMLParser to do a syntax parse of the entire yaml
1411
/// document, then the Input class builds a graph of HNodes which wraps
1412
/// each yaml Node.  The extra layer is buffering.  The low level yaml
1413
/// parser only lets you look at each node once.  The buffering layer lets
1414
/// you search and interate multiple times.  This is necessary because
1415
/// the mapRequired() method calls may not be in the same order
1416
/// as the keys in the document.
1417
///
1418
class Input : public IO {
1419
public:
1420
  // Construct a yaml Input object from a StringRef and optional
1421
  // user-data. The DiagHandler can be specified to provide
1422
  // alternative error reporting.
1423
  Input(StringRef InputContent,
1424
        void *Ctxt = nullptr,
1425
        SourceMgr::DiagHandlerTy DiagHandler = nullptr,
1426
        void *DiagHandlerCtxt = nullptr);
1427
  Input(MemoryBufferRef Input,
1428
        void *Ctxt = nullptr,
1429
        SourceMgr::DiagHandlerTy DiagHandler = nullptr,
1430
        void *DiagHandlerCtxt = nullptr);
1431
  ~Input() override;
1432
 
1433
  // Check if there was an syntax or semantic error during parsing.
1434
  std::error_code error();
1435
 
1436
private:
1437
  bool outputting() const override;
1438
  bool mapTag(StringRef, bool) override;
1439
  void beginMapping() override;
1440
  void endMapping() override;
1441
  bool preflightKey(const char *, bool, bool, bool &, void *&) override;
1442
  void postflightKey(void *) override;
1443
  std::vector<StringRef> keys() override;
1444
  void beginFlowMapping() override;
1445
  void endFlowMapping() override;
1446
  unsigned beginSequence() override;
1447
  void endSequence() override;
1448
  bool preflightElement(unsigned index, void *&) override;
1449
  void postflightElement(void *) override;
1450
  unsigned beginFlowSequence() override;
1451
  bool preflightFlowElement(unsigned , void *&) override;
1452
  void postflightFlowElement(void *) override;
1453
  void endFlowSequence() override;
1454
  void beginEnumScalar() override;
1455
  bool matchEnumScalar(const char*, bool) override;
1456
  bool matchEnumFallback() override;
1457
  void endEnumScalar() override;
1458
  bool beginBitSetScalar(bool &) override;
1459
  bool bitSetMatch(const char *, bool ) override;
1460
  void endBitSetScalar() override;
1461
  void scalarString(StringRef &, QuotingType) override;
1462
  void blockScalarString(StringRef &) override;
1463
  void scalarTag(std::string &) override;
1464
  NodeKind getNodeKind() override;
1465
  void setError(const Twine &message) override;
1466
  bool canElideEmptySequence() override;
1467
 
1468
  class HNode {
1469
    virtual void anchor();
1470
 
1471
  public:
1472
    HNode(Node *n) : _node(n) { }
1473
    virtual ~HNode() = default;
1474
 
1475
    static bool classof(const HNode *) { return true; }
1476
 
1477
    Node *_node;
1478
  };
1479
 
1480
  class EmptyHNode : public HNode {
1481
    void anchor() override;
1482
 
1483
  public:
1484
    EmptyHNode(Node *n) : HNode(n) { }
1485
 
1486
    static bool classof(const HNode *n) { return NullNode::classof(n->_node); }
1487
 
1488
    static bool classof(const EmptyHNode *) { return true; }
1489
  };
1490
 
1491
  class ScalarHNode : public HNode {
1492
    void anchor() override;
1493
 
1494
  public:
1495
    ScalarHNode(Node *n, StringRef s) : HNode(n), _value(s) { }
1496
 
1497
    StringRef value() const { return _value; }
1498
 
1499
    static bool classof(const HNode *n) {
1500
      return ScalarNode::classof(n->_node) ||
1501
             BlockScalarNode::classof(n->_node);
1502
    }
1503
 
1504
    static bool classof(const ScalarHNode *) { return true; }
1505
 
1506
  protected:
1507
    StringRef _value;
1508
  };
1509
 
1510
  class MapHNode : public HNode {
1511
    void anchor() override;
1512
 
1513
  public:
1514
    MapHNode(Node *n) : HNode(n) { }
1515
 
1516
    static bool classof(const HNode *n) {
1517
      return MappingNode::classof(n->_node);
1518
    }
1519
 
1520
    static bool classof(const MapHNode *) { return true; }
1521
 
1522
    using NameToNodeAndLoc =
1523
        StringMap<std::pair<std::unique_ptr<HNode>, SMRange>>;
1524
 
1525
    NameToNodeAndLoc Mapping;
1526
    SmallVector<std::string, 6> ValidKeys;
1527
  };
1528
 
1529
  class SequenceHNode : public HNode {
1530
    void anchor() override;
1531
 
1532
  public:
1533
    SequenceHNode(Node *n) : HNode(n) { }
1534
 
1535
    static bool classof(const HNode *n) {
1536
      return SequenceNode::classof(n->_node);
1537
    }
1538
 
1539
    static bool classof(const SequenceHNode *) { return true; }
1540
 
1541
    std::vector<std::unique_ptr<HNode>> Entries;
1542
  };
1543
 
1544
  std::unique_ptr<Input::HNode> createHNodes(Node *node);
1545
  void setError(HNode *hnode, const Twine &message);
1546
  void setError(Node *node, const Twine &message);
1547
  void setError(const SMRange &Range, const Twine &message);
1548
 
1549
  void reportWarning(HNode *hnode, const Twine &message);
1550
  void reportWarning(Node *hnode, const Twine &message);
1551
  void reportWarning(const SMRange &Range, const Twine &message);
1552
 
1553
public:
1554
  // These are only used by operator>>. They could be private
1555
  // if those templated things could be made friends.
1556
  bool setCurrentDocument();
1557
  bool nextDocument();
1558
 
1559
  /// Returns the current node that's being parsed by the YAML Parser.
1560
  const Node *getCurrentNode() const;
1561
 
1562
  void setAllowUnknownKeys(bool Allow) override;
1563
 
1564
private:
1565
  SourceMgr                           SrcMgr; // must be before Strm
1566
  std::unique_ptr<llvm::yaml::Stream> Strm;
1567
  std::unique_ptr<HNode>              TopNode;
1568
  std::error_code                     EC;
1569
  BumpPtrAllocator                    StringAllocator;
1570
  document_iterator                   DocIterator;
1571
  llvm::BitVector                     BitValuesUsed;
1572
  HNode *CurrentNode = nullptr;
1573
  bool                                ScalarMatchFound = false;
1574
  bool AllowUnknownKeys = false;
1575
};
1576
 
1577
///
1578
/// The Output class is used to generate a yaml document from in-memory structs
1579
/// and vectors.
1580
///
1581
class Output : public IO {
1582
public:
1583
  Output(raw_ostream &, void *Ctxt = nullptr, int WrapColumn = 70);
1584
  ~Output() override;
1585
 
1586
  /// Set whether or not to output optional values which are equal
1587
  /// to the default value.  By default, when outputting if you attempt
1588
  /// to write a value that is equal to the default, the value gets ignored.
1589
  /// Sometimes, it is useful to be able to see these in the resulting YAML
1590
  /// anyway.
1591
  void setWriteDefaultValues(bool Write) { WriteDefaultValues = Write; }
1592
 
1593
  bool outputting() const override;
1594
  bool mapTag(StringRef, bool) override;
1595
  void beginMapping() override;
1596
  void endMapping() override;
1597
  bool preflightKey(const char *key, bool, bool, bool &, void *&) override;
1598
  void postflightKey(void *) override;
1599
  std::vector<StringRef> keys() override;
1600
  void beginFlowMapping() override;
1601
  void endFlowMapping() override;
1602
  unsigned beginSequence() override;
1603
  void endSequence() override;
1604
  bool preflightElement(unsigned, void *&) override;
1605
  void postflightElement(void *) override;
1606
  unsigned beginFlowSequence() override;
1607
  bool preflightFlowElement(unsigned, void *&) override;
1608
  void postflightFlowElement(void *) override;
1609
  void endFlowSequence() override;
1610
  void beginEnumScalar() override;
1611
  bool matchEnumScalar(const char*, bool) override;
1612
  bool matchEnumFallback() override;
1613
  void endEnumScalar() override;
1614
  bool beginBitSetScalar(bool &) override;
1615
  bool bitSetMatch(const char *, bool ) override;
1616
  void endBitSetScalar() override;
1617
  void scalarString(StringRef &, QuotingType) override;
1618
  void blockScalarString(StringRef &) override;
1619
  void scalarTag(std::string &) override;
1620
  NodeKind getNodeKind() override;
1621
  void setError(const Twine &message) override;
1622
  bool canElideEmptySequence() override;
1623
 
1624
  // These are only used by operator<<. They could be private
1625
  // if that templated operator could be made a friend.
1626
  void beginDocuments();
1627
  bool preflightDocument(unsigned);
1628
  void postflightDocument();
1629
  void endDocuments();
1630
 
1631
private:
1632
  void output(StringRef s);
1633
  void outputUpToEndOfLine(StringRef s);
1634
  void newLineCheck(bool EmptySequence = false);
1635
  void outputNewLine();
1636
  void paddedKey(StringRef key);
1637
  void flowKey(StringRef Key);
1638
 
1639
  enum InState {
1640
    inSeqFirstElement,
1641
    inSeqOtherElement,
1642
    inFlowSeqFirstElement,
1643
    inFlowSeqOtherElement,
1644
    inMapFirstKey,
1645
    inMapOtherKey,
1646
    inFlowMapFirstKey,
1647
    inFlowMapOtherKey
1648
  };
1649
 
1650
  static bool inSeqAnyElement(InState State);
1651
  static bool inFlowSeqAnyElement(InState State);
1652
  static bool inMapAnyKey(InState State);
1653
  static bool inFlowMapAnyKey(InState State);
1654
 
1655
  raw_ostream &Out;
1656
  int WrapColumn;
1657
  SmallVector<InState, 8> StateStack;
1658
  int Column = 0;
1659
  int ColumnAtFlowStart = 0;
1660
  int ColumnAtMapFlowStart = 0;
1661
  bool NeedBitValueComma = false;
1662
  bool NeedFlowSequenceComma = false;
1663
  bool EnumerationMatchFound = false;
1664
  bool WriteDefaultValues = false;
1665
  StringRef Padding;
1666
  StringRef PaddingBeforeContainer;
1667
};
1668
 
1669
template <typename T, typename Context>
1670
void IO::processKeyWithDefault(const char *Key, std::optional<T> &Val,
1671
                               const std::optional<T> &DefaultValue,
1672
                               bool Required, Context &Ctx) {
1673
  assert(!DefaultValue && "std::optional<T> shouldn't have a value!");
1674
  void *SaveInfo;
1675
  bool UseDefault = true;
1676
  const bool sameAsDefault = outputting() && !Val;
1677
  if (!outputting() && !Val)
1678
    Val = T();
1679
  if (Val &&
1680
      this->preflightKey(Key, Required, sameAsDefault, UseDefault, SaveInfo)) {
1681
 
1682
    // When reading an std::optional<X> key from a YAML description, we allow
1683
    // the special "<none>" value, which can be used to specify that no value
1684
    // was requested, i.e. the DefaultValue will be assigned. The DefaultValue
1685
    // is usually None.
1686
    bool IsNone = false;
1687
    if (!outputting())
1688
      if (const auto *Node =
1689
              dyn_cast<ScalarNode>(((Input *)this)->getCurrentNode()))
1690
        // We use rtrim to ignore possible white spaces that might exist when a
1691
        // comment is present on the same line.
1692
        IsNone = Node->getRawValue().rtrim(' ') == "<none>";
1693
 
1694
    if (IsNone)
1695
      Val = DefaultValue;
1696
    else
1697
      yamlize(*this, *Val, Required, Ctx);
1698
    this->postflightKey(SaveInfo);
1699
  } else {
1700
    if (UseDefault)
1701
      Val = DefaultValue;
1702
  }
1703
}
1704
 
1705
/// YAML I/O does conversion based on types. But often native data types
1706
/// are just a typedef of built in intergral types (e.g. int).  But the C++
1707
/// type matching system sees through the typedef and all the typedefed types
1708
/// look like a built in type. This will cause the generic YAML I/O conversion
1709
/// to be used. To provide better control over the YAML conversion, you can
1710
/// use this macro instead of typedef.  It will create a class with one field
1711
/// and automatic conversion operators to and from the base type.
1712
/// Based on BOOST_STRONG_TYPEDEF
1713
#define LLVM_YAML_STRONG_TYPEDEF(_base, _type)                                 \
1714
    struct _type {                                                             \
1715
        _type() = default;                                                     \
1716
        _type(const _base v) : value(v) {}                                     \
1717
        _type(const _type &v) = default;                                       \
1718
        _type &operator=(const _type &rhs) = default;                          \
1719
        _type &operator=(const _base &rhs) { value = rhs; return *this; }      \
1720
        operator const _base & () const { return value; }                      \
1721
        bool operator==(const _type &rhs) const { return value == rhs.value; } \
1722
        bool operator==(const _base &rhs) const { return value == rhs; }       \
1723
        bool operator<(const _type &rhs) const { return value < rhs.value; }   \
1724
        _base value;                                                           \
1725
        using BaseType = _base;                                                \
1726
    };
1727
 
1728
///
1729
/// Use these types instead of uintXX_t in any mapping to have
1730
/// its yaml output formatted as hexadecimal.
1731
///
1732
LLVM_YAML_STRONG_TYPEDEF(uint8_t, Hex8)
1733
LLVM_YAML_STRONG_TYPEDEF(uint16_t, Hex16)
1734
LLVM_YAML_STRONG_TYPEDEF(uint32_t, Hex32)
1735
LLVM_YAML_STRONG_TYPEDEF(uint64_t, Hex64)
1736
 
1737
template<>
1738
struct ScalarTraits<Hex8> {
1739
  static void output(const Hex8 &, void *, raw_ostream &);
1740
  static StringRef input(StringRef, void *, Hex8 &);
1741
  static QuotingType mustQuote(StringRef) { return QuotingType::None; }
1742
};
1743
 
1744
template<>
1745
struct ScalarTraits<Hex16> {
1746
  static void output(const Hex16 &, void *, raw_ostream &);
1747
  static StringRef input(StringRef, void *, Hex16 &);
1748
  static QuotingType mustQuote(StringRef) { return QuotingType::None; }
1749
};
1750
 
1751
template<>
1752
struct ScalarTraits<Hex32> {
1753
  static void output(const Hex32 &, void *, raw_ostream &);
1754
  static StringRef input(StringRef, void *, Hex32 &);
1755
  static QuotingType mustQuote(StringRef) { return QuotingType::None; }
1756
};
1757
 
1758
template<>
1759
struct ScalarTraits<Hex64> {
1760
  static void output(const Hex64 &, void *, raw_ostream &);
1761
  static StringRef input(StringRef, void *, Hex64 &);
1762
  static QuotingType mustQuote(StringRef) { return QuotingType::None; }
1763
};
1764
 
1765
template <> struct ScalarTraits<VersionTuple> {
1766
  static void output(const VersionTuple &Value, void *, llvm::raw_ostream &Out);
1767
  static StringRef input(StringRef, void *, VersionTuple &);
1768
  static QuotingType mustQuote(StringRef) { return QuotingType::None; }
1769
};
1770
 
1771
// Define non-member operator>> so that Input can stream in a document list.
1772
template <typename T>
1773
inline std::enable_if_t<has_DocumentListTraits<T>::value, Input &>
1774
operator>>(Input &yin, T &docList) {
1775
  int i = 0;
1776
  EmptyContext Ctx;
1777
  while ( yin.setCurrentDocument() ) {
1778
    yamlize(yin, DocumentListTraits<T>::element(yin, docList, i), true, Ctx);
1779
    if ( yin.error() )
1780
      return yin;
1781
    yin.nextDocument();
1782
    ++i;
1783
  }
1784
  return yin;
1785
}
1786
 
1787
// Define non-member operator>> so that Input can stream in a map as a document.
1788
template <typename T>
1789
inline std::enable_if_t<has_MappingTraits<T, EmptyContext>::value, Input &>
1790
operator>>(Input &yin, T &docMap) {
1791
  EmptyContext Ctx;
1792
  yin.setCurrentDocument();
1793
  yamlize(yin, docMap, true, Ctx);
1794
  return yin;
1795
}
1796
 
1797
// Define non-member operator>> so that Input can stream in a sequence as
1798
// a document.
1799
template <typename T>
1800
inline std::enable_if_t<has_SequenceTraits<T>::value, Input &>
1801
operator>>(Input &yin, T &docSeq) {
1802
  EmptyContext Ctx;
1803
  if (yin.setCurrentDocument())
1804
    yamlize(yin, docSeq, true, Ctx);
1805
  return yin;
1806
}
1807
 
1808
// Define non-member operator>> so that Input can stream in a block scalar.
1809
template <typename T>
1810
inline std::enable_if_t<has_BlockScalarTraits<T>::value, Input &>
1811
operator>>(Input &In, T &Val) {
1812
  EmptyContext Ctx;
1813
  if (In.setCurrentDocument())
1814
    yamlize(In, Val, true, Ctx);
1815
  return In;
1816
}
1817
 
1818
// Define non-member operator>> so that Input can stream in a string map.
1819
template <typename T>
1820
inline std::enable_if_t<has_CustomMappingTraits<T>::value, Input &>
1821
operator>>(Input &In, T &Val) {
1822
  EmptyContext Ctx;
1823
  if (In.setCurrentDocument())
1824
    yamlize(In, Val, true, Ctx);
1825
  return In;
1826
}
1827
 
1828
// Define non-member operator>> so that Input can stream in a polymorphic type.
1829
template <typename T>
1830
inline std::enable_if_t<has_PolymorphicTraits<T>::value, Input &>
1831
operator>>(Input &In, T &Val) {
1832
  EmptyContext Ctx;
1833
  if (In.setCurrentDocument())
1834
    yamlize(In, Val, true, Ctx);
1835
  return In;
1836
}
1837
 
1838
// Provide better error message about types missing a trait specialization
1839
template <typename T>
1840
inline std::enable_if_t<missingTraits<T, EmptyContext>::value, Input &>
1841
operator>>(Input &yin, T &docSeq) {
1842
  char missing_yaml_trait_for_type[sizeof(MissingTrait<T>)];
1843
  return yin;
1844
}
1845
 
1846
// Define non-member operator<< so that Output can stream out document list.
1847
template <typename T>
1848
inline std::enable_if_t<has_DocumentListTraits<T>::value, Output &>
1849
operator<<(Output &yout, T &docList) {
1850
  EmptyContext Ctx;
1851
  yout.beginDocuments();
1852
  const size_t count = DocumentListTraits<T>::size(yout, docList);
1853
  for(size_t i=0; i < count; ++i) {
1854
    if ( yout.preflightDocument(i) ) {
1855
      yamlize(yout, DocumentListTraits<T>::element(yout, docList, i), true,
1856
              Ctx);
1857
      yout.postflightDocument();
1858
    }
1859
  }
1860
  yout.endDocuments();
1861
  return yout;
1862
}
1863
 
1864
// Define non-member operator<< so that Output can stream out a map.
1865
template <typename T>
1866
inline std::enable_if_t<has_MappingTraits<T, EmptyContext>::value, Output &>
1867
operator<<(Output &yout, T &map) {
1868
  EmptyContext Ctx;
1869
  yout.beginDocuments();
1870
  if ( yout.preflightDocument(0) ) {
1871
    yamlize(yout, map, true, Ctx);
1872
    yout.postflightDocument();
1873
  }
1874
  yout.endDocuments();
1875
  return yout;
1876
}
1877
 
1878
// Define non-member operator<< so that Output can stream out a sequence.
1879
template <typename T>
1880
inline std::enable_if_t<has_SequenceTraits<T>::value, Output &>
1881
operator<<(Output &yout, T &seq) {
1882
  EmptyContext Ctx;
1883
  yout.beginDocuments();
1884
  if ( yout.preflightDocument(0) ) {
1885
    yamlize(yout, seq, true, Ctx);
1886
    yout.postflightDocument();
1887
  }
1888
  yout.endDocuments();
1889
  return yout;
1890
}
1891
 
1892
// Define non-member operator<< so that Output can stream out a block scalar.
1893
template <typename T>
1894
inline std::enable_if_t<has_BlockScalarTraits<T>::value, Output &>
1895
operator<<(Output &Out, T &Val) {
1896
  EmptyContext Ctx;
1897
  Out.beginDocuments();
1898
  if (Out.preflightDocument(0)) {
1899
    yamlize(Out, Val, true, Ctx);
1900
    Out.postflightDocument();
1901
  }
1902
  Out.endDocuments();
1903
  return Out;
1904
}
1905
 
1906
// Define non-member operator<< so that Output can stream out a string map.
1907
template <typename T>
1908
inline std::enable_if_t<has_CustomMappingTraits<T>::value, Output &>
1909
operator<<(Output &Out, T &Val) {
1910
  EmptyContext Ctx;
1911
  Out.beginDocuments();
1912
  if (Out.preflightDocument(0)) {
1913
    yamlize(Out, Val, true, Ctx);
1914
    Out.postflightDocument();
1915
  }
1916
  Out.endDocuments();
1917
  return Out;
1918
}
1919
 
1920
// Define non-member operator<< so that Output can stream out a polymorphic
1921
// type.
1922
template <typename T>
1923
inline std::enable_if_t<has_PolymorphicTraits<T>::value, Output &>
1924
operator<<(Output &Out, T &Val) {
1925
  EmptyContext Ctx;
1926
  Out.beginDocuments();
1927
  if (Out.preflightDocument(0)) {
1928
    // FIXME: The parser does not support explicit documents terminated with a
1929
    // plain scalar; the end-marker is included as part of the scalar token.
1930
    assert(PolymorphicTraits<T>::getKind(Val) != NodeKind::Scalar && "plain scalar documents are not supported");
1931
    yamlize(Out, Val, true, Ctx);
1932
    Out.postflightDocument();
1933
  }
1934
  Out.endDocuments();
1935
  return Out;
1936
}
1937
 
1938
// Provide better error message about types missing a trait specialization
1939
template <typename T>
1940
inline std::enable_if_t<missingTraits<T, EmptyContext>::value, Output &>
1941
operator<<(Output &yout, T &seq) {
1942
  char missing_yaml_trait_for_type[sizeof(MissingTrait<T>)];
1943
  return yout;
1944
}
1945
 
1946
template <bool B> struct IsFlowSequenceBase {};
1947
template <> struct IsFlowSequenceBase<true> { static const bool flow = true; };
1948
 
1949
template <typename T, typename U = void>
1950
struct IsResizable : std::false_type {};
1951
 
1952
template <typename T>
1953
struct IsResizable<T, std::void_t<decltype(std::declval<T>().resize(0))>>
1954
    : public std::true_type {};
1955
 
1956
template <typename T, bool B> struct IsResizableBase {
1957
  using type = typename T::value_type;
1958
 
1959
  static type &element(IO &io, T &seq, size_t index) {
1960
    if (index >= seq.size())
1961
      seq.resize(index + 1);
1962
    return seq[index];
1963
  }
1964
};
1965
 
1966
template <typename T> struct IsResizableBase<T, false> {
1967
  using type = typename T::value_type;
1968
 
1969
  static type &element(IO &io, T &seq, size_t index) {
1970
    if (index >= seq.size()) {
1971
      io.setError(Twine("value sequence extends beyond static size (") +
1972
                  Twine(seq.size()) + ")");
1973
      return seq[0];
1974
    }
1975
    return seq[index];
1976
  }
1977
};
1978
 
1979
template <typename T, bool Flow>
1980
struct SequenceTraitsImpl
1981
    : IsFlowSequenceBase<Flow>, IsResizableBase<T, IsResizable<T>::value> {
1982
  static size_t size(IO &io, T &seq) { return seq.size(); }
1983
};
1984
 
1985
// Simple helper to check an expression can be used as a bool-valued template
1986
// argument.
1987
template <bool> struct CheckIsBool { static const bool value = true; };
1988
 
1989
// If T has SequenceElementTraits, then vector<T> and SmallVector<T, N> have
1990
// SequenceTraits that do the obvious thing.
1991
template <typename T>
1992
struct SequenceTraits<
1993
    std::vector<T>,
1994
    std::enable_if_t<CheckIsBool<SequenceElementTraits<T>::flow>::value>>
1995
    : SequenceTraitsImpl<std::vector<T>, SequenceElementTraits<T>::flow> {};
1996
template <typename T, unsigned N>
1997
struct SequenceTraits<
1998
    SmallVector<T, N>,
1999
    std::enable_if_t<CheckIsBool<SequenceElementTraits<T>::flow>::value>>
2000
    : SequenceTraitsImpl<SmallVector<T, N>, SequenceElementTraits<T>::flow> {};
2001
template <typename T>
2002
struct SequenceTraits<
2003
    SmallVectorImpl<T>,
2004
    std::enable_if_t<CheckIsBool<SequenceElementTraits<T>::flow>::value>>
2005
    : SequenceTraitsImpl<SmallVectorImpl<T>, SequenceElementTraits<T>::flow> {};
2006
template <typename T>
2007
struct SequenceTraits<
2008
    MutableArrayRef<T>,
2009
    std::enable_if_t<CheckIsBool<SequenceElementTraits<T>::flow>::value>>
2010
    : SequenceTraitsImpl<MutableArrayRef<T>, SequenceElementTraits<T>::flow> {};
2011
 
2012
// Sequences of fundamental types use flow formatting.
2013
template <typename T>
2014
struct SequenceElementTraits<T,
2015
                             std::enable_if_t<std::is_fundamental<T>::value>> {
2016
  static const bool flow = true;
2017
};
2018
 
2019
// Sequences of strings use block formatting.
2020
template<> struct SequenceElementTraits<std::string> {
2021
  static const bool flow = false;
2022
};
2023
template<> struct SequenceElementTraits<StringRef> {
2024
  static const bool flow = false;
2025
};
2026
template<> struct SequenceElementTraits<std::pair<std::string, std::string>> {
2027
  static const bool flow = false;
2028
};
2029
 
2030
/// Implementation of CustomMappingTraits for std::map<std::string, T>.
2031
template <typename T> struct StdMapStringCustomMappingTraitsImpl {
2032
  using map_type = std::map<std::string, T>;
2033
 
2034
  static void inputOne(IO &io, StringRef key, map_type &v) {
2035
    io.mapRequired(key.str().c_str(), v[std::string(key)]);
2036
  }
2037
 
2038
  static void output(IO &io, map_type &v) {
2039
    for (auto &p : v)
2040
      io.mapRequired(p.first.c_str(), p.second);
2041
  }
2042
};
2043
 
2044
} // end namespace yaml
2045
} // end namespace llvm
2046
 
2047
#define LLVM_YAML_IS_SEQUENCE_VECTOR_IMPL(TYPE, FLOW)                          \
2048
  namespace llvm {                                                             \
2049
  namespace yaml {                                                             \
2050
  static_assert(                                                               \
2051
      !std::is_fundamental_v<TYPE> && !std::is_same_v<TYPE, std::string> &&    \
2052
          !std::is_same_v<TYPE, llvm::StringRef>,                              \
2053
      "only use LLVM_YAML_IS_SEQUENCE_VECTOR for types you control");          \
2054
  template <> struct SequenceElementTraits<TYPE> {                             \
2055
    static const bool flow = FLOW;                                             \
2056
  };                                                                           \
2057
  }                                                                            \
2058
  }
2059
 
2060
/// Utility for declaring that a std::vector of a particular type
2061
/// should be considered a YAML sequence.
2062
#define LLVM_YAML_IS_SEQUENCE_VECTOR(type)                                     \
2063
  LLVM_YAML_IS_SEQUENCE_VECTOR_IMPL(type, false)
2064
 
2065
/// Utility for declaring that a std::vector of a particular type
2066
/// should be considered a YAML flow sequence.
2067
#define LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(type)                                \
2068
  LLVM_YAML_IS_SEQUENCE_VECTOR_IMPL(type, true)
2069
 
2070
#define LLVM_YAML_DECLARE_MAPPING_TRAITS(Type)                                 \
2071
  namespace llvm {                                                             \
2072
  namespace yaml {                                                             \
2073
  template <> struct MappingTraits<Type> {                                     \
2074
    static void mapping(IO &IO, Type &Obj);                                    \
2075
  };                                                                           \
2076
  }                                                                            \
2077
  }
2078
 
2079
#define LLVM_YAML_DECLARE_ENUM_TRAITS(Type)                                    \
2080
  namespace llvm {                                                             \
2081
  namespace yaml {                                                             \
2082
  template <> struct ScalarEnumerationTraits<Type> {                           \
2083
    static void enumeration(IO &io, Type &Value);                              \
2084
  };                                                                           \
2085
  }                                                                            \
2086
  }
2087
 
2088
#define LLVM_YAML_DECLARE_BITSET_TRAITS(Type)                                  \
2089
  namespace llvm {                                                             \
2090
  namespace yaml {                                                             \
2091
  template <> struct ScalarBitSetTraits<Type> {                                \
2092
    static void bitset(IO &IO, Type &Options);                                 \
2093
  };                                                                           \
2094
  }                                                                            \
2095
  }
2096
 
2097
#define LLVM_YAML_DECLARE_SCALAR_TRAITS(Type, MustQuote)                       \
2098
  namespace llvm {                                                             \
2099
  namespace yaml {                                                             \
2100
  template <> struct ScalarTraits<Type> {                                      \
2101
    static void output(const Type &Value, void *ctx, raw_ostream &Out);        \
2102
    static StringRef input(StringRef Scalar, void *ctxt, Type &Value);         \
2103
    static QuotingType mustQuote(StringRef) { return MustQuote; }              \
2104
  };                                                                           \
2105
  }                                                                            \
2106
  }
2107
 
2108
/// Utility for declaring that a std::vector of a particular type
2109
/// should be considered a YAML document list.
2110
#define LLVM_YAML_IS_DOCUMENT_LIST_VECTOR(_type)                               \
2111
  namespace llvm {                                                             \
2112
  namespace yaml {                                                             \
2113
  template <unsigned N>                                                        \
2114
  struct DocumentListTraits<SmallVector<_type, N>>                             \
2115
      : public SequenceTraitsImpl<SmallVector<_type, N>, false> {};            \
2116
  template <>                                                                  \
2117
  struct DocumentListTraits<std::vector<_type>>                                \
2118
      : public SequenceTraitsImpl<std::vector<_type>, false> {};               \
2119
  }                                                                            \
2120
  }
2121
 
2122
/// Utility for declaring that std::map<std::string, _type> should be considered
2123
/// a YAML map.
2124
#define LLVM_YAML_IS_STRING_MAP(_type)                                         \
2125
  namespace llvm {                                                             \
2126
  namespace yaml {                                                             \
2127
  template <>                                                                  \
2128
  struct CustomMappingTraits<std::map<std::string, _type>>                     \
2129
      : public StdMapStringCustomMappingTraitsImpl<_type> {};                  \
2130
  }                                                                            \
2131
  }
2132
 
2133
LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(llvm::yaml::Hex64)
2134
LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(llvm::yaml::Hex32)
2135
LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(llvm::yaml::Hex16)
2136
LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(llvm::yaml::Hex8)
2137
 
2138
#endif // LLVM_SUPPORT_YAMLTRAITS_H