File indexing completed on 2026-05-10 08:44:35
0001
0002
0003
0004
0005
0006
0007
0008
0009 #ifndef LLVM_SUPPORT_YAMLTRAITS_H
0010 #define LLVM_SUPPORT_YAMLTRAITS_H
0011
0012 #include "llvm/ADT/ArrayRef.h"
0013 #include "llvm/ADT/BitVector.h"
0014 #include "llvm/ADT/SmallVector.h"
0015 #include "llvm/ADT/StringExtras.h"
0016 #include "llvm/ADT/StringMap.h"
0017 #include "llvm/ADT/StringRef.h"
0018 #include "llvm/ADT/Twine.h"
0019 #include "llvm/Support/AlignOf.h"
0020 #include "llvm/Support/Allocator.h"
0021 #include "llvm/Support/Endian.h"
0022 #include "llvm/Support/SMLoc.h"
0023 #include "llvm/Support/SourceMgr.h"
0024 #include "llvm/Support/YAMLParser.h"
0025 #include "llvm/Support/raw_ostream.h"
0026 #include <array>
0027 #include <cassert>
0028 #include <map>
0029 #include <memory>
0030 #include <new>
0031 #include <optional>
0032 #include <string>
0033 #include <system_error>
0034 #include <type_traits>
0035 #include <vector>
0036
0037 namespace llvm {
0038
0039 class VersionTuple;
0040
0041 namespace yaml {
0042
0043 enum class NodeKind : uint8_t {
0044 Scalar,
0045 Map,
0046 Sequence,
0047 };
0048
0049 struct EmptyContext {};
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061 template<class T>
0062 struct MappingTraits {
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072 };
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085 template <class T, class Context> struct MappingContextTraits {
0086
0087
0088
0089
0090
0091
0092
0093
0094 };
0095
0096
0097
0098
0099
0100
0101
0102
0103
0104
0105
0106
0107 template <typename T, typename Enable = void> struct ScalarEnumerationTraits {
0108
0109
0110 };
0111
0112
0113
0114
0115
0116
0117
0118
0119
0120
0121
0122
0123 template <typename T, typename Enable = void> struct ScalarBitSetTraits {
0124
0125
0126 };
0127
0128
0129
0130
0131 enum class QuotingType { None, Single, Double };
0132
0133
0134
0135
0136
0137
0138
0139
0140
0141
0142
0143
0144
0145
0146
0147
0148
0149 template <typename T, typename Enable = void> struct ScalarTraits {
0150
0151
0152
0153
0154
0155
0156
0157
0158
0159
0160
0161 };
0162
0163
0164
0165
0166
0167
0168
0169
0170
0171
0172
0173
0174
0175
0176
0177
0178
0179 template <typename T>
0180 struct BlockScalarTraits {
0181
0182
0183
0184
0185
0186
0187
0188
0189
0190
0191
0192
0193 };
0194
0195
0196
0197
0198
0199
0200
0201
0202
0203
0204
0205
0206
0207
0208
0209
0210
0211
0212
0213
0214
0215
0216 template <typename T> struct TaggedScalarTraits {
0217
0218
0219
0220
0221
0222
0223
0224
0225
0226
0227
0228
0229
0230 };
0231
0232
0233
0234
0235
0236
0237
0238
0239
0240
0241
0242
0243
0244
0245
0246 template<typename T, typename EnableIf = void>
0247 struct SequenceTraits {
0248
0249
0250
0251
0252
0253
0254
0255 };
0256
0257
0258
0259 template<typename T, typename EnableIf = void>
0260 struct SequenceElementTraits {
0261
0262
0263 };
0264
0265
0266
0267 template<typename T>
0268 struct DocumentListTraits {
0269
0270
0271
0272 };
0273
0274
0275
0276
0277 template <typename T>
0278 struct CustomMappingTraits {
0279
0280
0281 };
0282
0283
0284
0285
0286
0287
0288
0289
0290
0291
0292
0293
0294
0295
0296
0297
0298
0299
0300 template <typename T> struct PolymorphicTraits {
0301
0302
0303
0304
0305
0306 };
0307
0308
0309 template <typename T>
0310 struct MissingTrait;
0311
0312
0313 template <class T>
0314 struct has_ScalarEnumerationTraits
0315 {
0316 using Signature_enumeration = void (*)(class IO&, T&);
0317
0318 template <typename U>
0319 static char test(SameType<Signature_enumeration, &U::enumeration>*);
0320
0321 template <typename U>
0322 static double test(...);
0323
0324 static bool const value =
0325 (sizeof(test<ScalarEnumerationTraits<T>>(nullptr)) == 1);
0326 };
0327
0328
0329 template <class T>
0330 struct has_ScalarBitSetTraits
0331 {
0332 using Signature_bitset = void (*)(class IO&, T&);
0333
0334 template <typename U>
0335 static char test(SameType<Signature_bitset, &U::bitset>*);
0336
0337 template <typename U>
0338 static double test(...);
0339
0340 static bool const value = (sizeof(test<ScalarBitSetTraits<T>>(nullptr)) == 1);
0341 };
0342
0343
0344 template <class T>
0345 struct has_ScalarTraits
0346 {
0347 using Signature_input = StringRef (*)(StringRef, void*, T&);
0348 using Signature_output = void (*)(const T&, void*, raw_ostream&);
0349 using Signature_mustQuote = QuotingType (*)(StringRef);
0350
0351 template <typename U>
0352 static char test(SameType<Signature_input, &U::input> *,
0353 SameType<Signature_output, &U::output> *,
0354 SameType<Signature_mustQuote, &U::mustQuote> *);
0355
0356 template <typename U>
0357 static double test(...);
0358
0359 static bool const value =
0360 (sizeof(test<ScalarTraits<T>>(nullptr, nullptr, nullptr)) == 1);
0361 };
0362
0363
0364 template <class T>
0365 struct has_BlockScalarTraits
0366 {
0367 using Signature_input = StringRef (*)(StringRef, void *, T &);
0368 using Signature_output = void (*)(const T &, void *, raw_ostream &);
0369
0370 template <typename U>
0371 static char test(SameType<Signature_input, &U::input> *,
0372 SameType<Signature_output, &U::output> *);
0373
0374 template <typename U>
0375 static double test(...);
0376
0377 static bool const value =
0378 (sizeof(test<BlockScalarTraits<T>>(nullptr, nullptr)) == 1);
0379 };
0380
0381
0382 template <class T> struct has_TaggedScalarTraits {
0383 using Signature_input = StringRef (*)(StringRef, StringRef, void *, T &);
0384 using Signature_output = void (*)(const T &, void *, raw_ostream &,
0385 raw_ostream &);
0386 using Signature_mustQuote = QuotingType (*)(const T &, StringRef);
0387
0388 template <typename U>
0389 static char test(SameType<Signature_input, &U::input> *,
0390 SameType<Signature_output, &U::output> *,
0391 SameType<Signature_mustQuote, &U::mustQuote> *);
0392
0393 template <typename U> static double test(...);
0394
0395 static bool const value =
0396 (sizeof(test<TaggedScalarTraits<T>>(nullptr, nullptr, nullptr)) == 1);
0397 };
0398
0399
0400 template <class T, class Context> struct has_MappingTraits {
0401 using Signature_mapping = void (*)(class IO &, T &, Context &);
0402
0403 template <typename U>
0404 static char test(SameType<Signature_mapping, &U::mapping>*);
0405
0406 template <typename U>
0407 static double test(...);
0408
0409 static bool const value =
0410 (sizeof(test<MappingContextTraits<T, Context>>(nullptr)) == 1);
0411 };
0412
0413
0414 template <class T> struct has_MappingTraits<T, EmptyContext> {
0415 using Signature_mapping = void (*)(class IO &, T &);
0416
0417 template <typename U>
0418 static char test(SameType<Signature_mapping, &U::mapping> *);
0419
0420 template <typename U> static double test(...);
0421
0422 static bool const value = (sizeof(test<MappingTraits<T>>(nullptr)) == 1);
0423 };
0424
0425
0426 template <class T, class Context> struct has_MappingValidateTraits {
0427 using Signature_validate = std::string (*)(class IO &, T &, Context &);
0428
0429 template <typename U>
0430 static char test(SameType<Signature_validate, &U::validate>*);
0431
0432 template <typename U>
0433 static double test(...);
0434
0435 static bool const value =
0436 (sizeof(test<MappingContextTraits<T, Context>>(nullptr)) == 1);
0437 };
0438
0439
0440 template <class T> struct has_MappingValidateTraits<T, EmptyContext> {
0441 using Signature_validate = std::string (*)(class IO &, T &);
0442
0443 template <typename U>
0444 static char test(SameType<Signature_validate, &U::validate> *);
0445
0446 template <typename U> static double test(...);
0447
0448 static bool const value = (sizeof(test<MappingTraits<T>>(nullptr)) == 1);
0449 };
0450
0451
0452 template <class T, class Context> struct has_MappingEnumInputTraits {
0453 using Signature_validate = void (*)(class IO &, T &);
0454
0455 template <typename U>
0456 static char test(SameType<Signature_validate, &U::enumInput> *);
0457
0458 template <typename U> static double test(...);
0459
0460 static bool const value =
0461 (sizeof(test<MappingContextTraits<T, Context>>(nullptr)) == 1);
0462 };
0463
0464
0465 template <class T> struct has_MappingEnumInputTraits<T, EmptyContext> {
0466 using Signature_validate = void (*)(class IO &, T &);
0467
0468 template <typename U>
0469 static char test(SameType<Signature_validate, &U::enumInput> *);
0470
0471 template <typename U> static double test(...);
0472
0473 static bool const value = (sizeof(test<MappingTraits<T>>(nullptr)) == 1);
0474 };
0475
0476
0477 template <class T>
0478 struct has_SequenceMethodTraits
0479 {
0480 using Signature_size = size_t (*)(class IO&, T&);
0481
0482 template <typename U>
0483 static char test(SameType<Signature_size, &U::size>*);
0484
0485 template <typename U>
0486 static double test(...);
0487
0488 static bool const value = (sizeof(test<SequenceTraits<T>>(nullptr)) == 1);
0489 };
0490
0491
0492 template <class T>
0493 struct has_CustomMappingTraits
0494 {
0495 using Signature_input = void (*)(IO &io, StringRef key, T &v);
0496
0497 template <typename U>
0498 static char test(SameType<Signature_input, &U::inputOne>*);
0499
0500 template <typename U>
0501 static double test(...);
0502
0503 static bool const value =
0504 (sizeof(test<CustomMappingTraits<T>>(nullptr)) == 1);
0505 };
0506
0507
0508
0509
0510 template <typename T, bool Enabled = std::is_class_v<T>> class has_FlowTraits {
0511 public:
0512 static const bool value = false;
0513 };
0514
0515
0516
0517
0518 template <class T>
0519 struct has_FlowTraits<T, true>
0520 {
0521 struct Fallback { bool flow; };
0522 struct Derived : T, Fallback { };
0523
0524 template<typename C>
0525 static char (&f(SameType<bool Fallback::*, &C::flow>*))[1];
0526
0527 template<typename C>
0528 static char (&f(...))[2];
0529
0530 static bool const value = sizeof(f<Derived>(nullptr)) == 2;
0531 };
0532
0533
0534 template<typename T>
0535 struct has_SequenceTraits : public std::integral_constant<bool,
0536 has_SequenceMethodTraits<T>::value > { };
0537
0538
0539 template <class T>
0540 struct has_DocumentListTraits
0541 {
0542 using Signature_size = size_t (*)(class IO &, T &);
0543
0544 template <typename U>
0545 static char test(SameType<Signature_size, &U::size>*);
0546
0547 template <typename U>
0548 static double test(...);
0549
0550 static bool const value = (sizeof(test<DocumentListTraits<T>>(nullptr))==1);
0551 };
0552
0553 template <class T> struct has_PolymorphicTraits {
0554 using Signature_getKind = NodeKind (*)(const T &);
0555
0556 template <typename U>
0557 static char test(SameType<Signature_getKind, &U::getKind> *);
0558
0559 template <typename U> static double test(...);
0560
0561 static bool const value = (sizeof(test<PolymorphicTraits<T>>(nullptr)) == 1);
0562 };
0563
0564 inline bool isNumeric(StringRef S) {
0565 const auto skipDigits = [](StringRef Input) {
0566 return Input.ltrim("0123456789");
0567 };
0568
0569
0570
0571 if (S.empty() || S == "+" || S == "-")
0572 return false;
0573
0574 if (S == ".nan" || S == ".NaN" || S == ".NAN")
0575 return true;
0576
0577
0578 StringRef Tail = (S.front() == '-' || S.front() == '+') ? S.drop_front() : S;
0579
0580
0581
0582 if (Tail == ".inf" || Tail == ".Inf" || Tail == ".INF")
0583 return true;
0584
0585
0586
0587
0588 if (S.starts_with("0o"))
0589 return S.size() > 2 &&
0590 S.drop_front(2).find_first_not_of("01234567") == StringRef::npos;
0591
0592 if (S.starts_with("0x"))
0593 return S.size() > 2 && S.drop_front(2).find_first_not_of(
0594 "0123456789abcdefABCDEF") == StringRef::npos;
0595
0596
0597 S = Tail;
0598
0599
0600
0601
0602 if (S.starts_with(".") &&
0603 (S == "." ||
0604 (S.size() > 1 && std::strchr("0123456789", S[1]) == nullptr)))
0605 return false;
0606
0607 if (S.starts_with("E") || S.starts_with("e"))
0608 return false;
0609
0610 enum ParseState {
0611 Default,
0612 FoundDot,
0613 FoundExponent,
0614 };
0615 ParseState State = Default;
0616
0617 S = skipDigits(S);
0618
0619
0620 if (S.empty())
0621 return true;
0622
0623 if (S.front() == '.') {
0624 State = FoundDot;
0625 S = S.drop_front();
0626 } else if (S.front() == 'e' || S.front() == 'E') {
0627 State = FoundExponent;
0628 S = S.drop_front();
0629 } else {
0630 return false;
0631 }
0632
0633 if (State == FoundDot) {
0634 S = skipDigits(S);
0635 if (S.empty())
0636 return true;
0637
0638 if (S.front() == 'e' || S.front() == 'E') {
0639 State = FoundExponent;
0640 S = S.drop_front();
0641 } else {
0642 return false;
0643 }
0644 }
0645
0646 assert(State == FoundExponent && "Should have found exponent at this point.");
0647 if (S.empty())
0648 return false;
0649
0650 if (S.front() == '+' || S.front() == '-') {
0651 S = S.drop_front();
0652 if (S.empty())
0653 return false;
0654 }
0655
0656 return skipDigits(S).empty();
0657 }
0658
0659 inline bool isNull(StringRef S) {
0660 return S == "null" || S == "Null" || S == "NULL" || S == "~";
0661 }
0662
0663 inline bool isBool(StringRef S) {
0664
0665 return S == "true" || S == "True" || S == "TRUE" || S == "false" ||
0666 S == "False" || S == "FALSE";
0667 }
0668
0669
0670
0671
0672
0673
0674
0675
0676
0677
0678 inline QuotingType needsQuotes(StringRef S, bool ForcePreserveAsString = true) {
0679 if (S.empty())
0680 return QuotingType::Single;
0681
0682 QuotingType MaxQuotingNeeded = QuotingType::None;
0683 if (isSpace(static_cast<unsigned char>(S.front())) ||
0684 isSpace(static_cast<unsigned char>(S.back())))
0685 MaxQuotingNeeded = QuotingType::Single;
0686 if (ForcePreserveAsString) {
0687 if (isNull(S))
0688 MaxQuotingNeeded = QuotingType::Single;
0689 if (isBool(S))
0690 MaxQuotingNeeded = QuotingType::Single;
0691 if (isNumeric(S))
0692 MaxQuotingNeeded = QuotingType::Single;
0693 }
0694
0695
0696
0697
0698 if (std::strchr(R"(-?:\,[]{}#&*!|>'"%@`)", S[0]) != nullptr)
0699 MaxQuotingNeeded = QuotingType::Single;
0700
0701 for (unsigned char C : S) {
0702 // Alphanum is safe.
0703 if (isAlnum(C))
0704 continue;
0705
0706 switch (C) {
0707 // Safe scalar characters.
0708 case '_':
0709 case '-':
0710 case '^':
0711 case '.':
0712 case ',':
0713 case ' ':
0714 // TAB (0x9) is allowed in unquoted strings.
0715 case 0x9:
0716 continue;
0717 // LF(0xA) and CR(0xD) may delimit values and so require at least single
0718 // quotes. LLVM YAML parser cannot handle single quoted multiline so use
0719 // double quoting to produce valid YAML.
0720 case 0xA:
0721 case 0xD:
0722 return QuotingType::Double;
0723 // DEL (0x7F) are excluded from the allowed character range.
0724 case 0x7F:
0725 return QuotingType::Double;
0726 // Forward slash is allowed to be unquoted, but we quote it anyway. We have
0727 // many tests that use FileCheck against YAML output, and this output often
0728 // contains paths. If we quote backslashes but not forward slashes then
0729 // paths will come out either quoted or unquoted depending on which platform
0730 // the test is run on, making FileCheck comparisons difficult.
0731 case '/':
0732 default: {
0733 // C0 control block (0x0 - 0x1F) is excluded from the allowed character
0734 // range.
0735 if (C <= 0x1F)
0736 return QuotingType::Double;
0737
0738 // Always double quote UTF-8.
0739 if ((C & 0x80) != 0)
0740 return QuotingType::Double;
0741
0742 // The character is not safe, at least simple quoting needed.
0743 MaxQuotingNeeded = QuotingType::Single;
0744 }
0745 }
0746 }
0747
0748 return MaxQuotingNeeded;
0749 }
0750
0751 template <typename T, typename Context>
0752 struct missingTraits
0753 : public std::integral_constant<bool,
0754 !has_ScalarEnumerationTraits<T>::value &&
0755 !has_ScalarBitSetTraits<T>::value &&
0756 !has_ScalarTraits<T>::value &&
0757 !has_BlockScalarTraits<T>::value &&
0758 !has_TaggedScalarTraits<T>::value &&
0759 !has_MappingTraits<T, Context>::value &&
0760 !has_SequenceTraits<T>::value &&
0761 !has_CustomMappingTraits<T>::value &&
0762 !has_DocumentListTraits<T>::value &&
0763 !has_PolymorphicTraits<T>::value> {};
0764
0765 template <typename T, typename Context>
0766 struct validatedMappingTraits
0767 : public std::integral_constant<
0768 bool, has_MappingTraits<T, Context>::value &&
0769 has_MappingValidateTraits<T, Context>::value> {};
0770
0771 template <typename T, typename Context>
0772 struct unvalidatedMappingTraits
0773 : public std::integral_constant<
0774 bool, has_MappingTraits<T, Context>::value &&
0775 !has_MappingValidateTraits<T, Context>::value> {};
0776
0777 // Base class for Input and Output.
0778 class IO {
0779 public:
0780 IO(void *Ctxt = nullptr);
0781 virtual ~IO();
0782
0783 virtual bool outputting() const = 0;
0784
0785 virtual unsigned beginSequence() = 0;
0786 virtual bool preflightElement(unsigned, void *&) = 0;
0787 virtual void postflightElement(void*) = 0;
0788 virtual void endSequence() = 0;
0789 virtual bool canElideEmptySequence() = 0;
0790
0791 virtual unsigned beginFlowSequence() = 0;
0792 virtual bool preflightFlowElement(unsigned, void *&) = 0;
0793 virtual void postflightFlowElement(void*) = 0;
0794 virtual void endFlowSequence() = 0;
0795
0796 virtual bool mapTag(StringRef Tag, bool Default=false) = 0;
0797 virtual void beginMapping() = 0;
0798 virtual void endMapping() = 0;
0799 virtual bool preflightKey(const char*, bool, bool, bool &, void *&) = 0;
0800 virtual void postflightKey(void*) = 0;
0801 virtual std::vector<StringRef> keys() = 0;
0802
0803 virtual void beginFlowMapping() = 0;
0804 virtual void endFlowMapping() = 0;
0805
0806 virtual void beginEnumScalar() = 0;
0807 virtual bool matchEnumScalar(const char*, bool) = 0;
0808 virtual bool matchEnumFallback() = 0;
0809 virtual void endEnumScalar() = 0;
0810
0811 virtual bool beginBitSetScalar(bool &) = 0;
0812 virtual bool bitSetMatch(const char*, bool) = 0;
0813 virtual void endBitSetScalar() = 0;
0814
0815 virtual void scalarString(StringRef &, QuotingType) = 0;
0816 virtual void blockScalarString(StringRef &) = 0;
0817 virtual void scalarTag(std::string &) = 0;
0818
0819 virtual NodeKind getNodeKind() = 0;
0820
0821 virtual void setError(const Twine &) = 0;
0822 virtual std::error_code error() = 0;
0823 virtual void setAllowUnknownKeys(bool Allow);
0824
0825 template <typename T>
0826 void enumCase(T &Val, const char* Str, const T ConstVal) {
0827 if ( matchEnumScalar(Str, outputting() && Val == ConstVal) ) {
0828 Val = ConstVal;
0829 }
0830 }
0831
0832 // allow anonymous enum values to be used with LLVM_YAML_STRONG_TYPEDEF
0833 template <typename T>
0834 void enumCase(T &Val, const char* Str, const uint32_t ConstVal) {
0835 if ( matchEnumScalar(Str, outputting() && Val == static_cast<T>(ConstVal)) ) {
0836 Val = ConstVal;
0837 }
0838 }
0839
0840 template <typename FBT, typename T>
0841 void enumFallback(T &Val) {
0842 if (matchEnumFallback()) {
0843 EmptyContext Context;
0844 // FIXME: Force integral conversion to allow strong typedefs to convert.
0845 FBT Res = static_cast<typename FBT::BaseType>(Val);
0846 yamlize(*this, Res, true, Context);
0847 Val = static_cast<T>(static_cast<typename FBT::BaseType>(Res));
0848 }
0849 }
0850
0851 template <typename T>
0852 void bitSetCase(T &Val, const char* Str, const T ConstVal) {
0853 if ( bitSetMatch(Str, outputting() && (Val & ConstVal) == ConstVal) ) {
0854 Val = static_cast<T>(Val | ConstVal);
0855 }
0856 }
0857
0858 // allow anonymous enum values to be used with LLVM_YAML_STRONG_TYPEDEF
0859 template <typename T>
0860 void bitSetCase(T &Val, const char* Str, const uint32_t ConstVal) {
0861 if ( bitSetMatch(Str, outputting() && (Val & ConstVal) == ConstVal) ) {
0862 Val = static_cast<T>(Val | ConstVal);
0863 }
0864 }
0865
0866 template <typename T>
0867 void maskedBitSetCase(T &Val, const char *Str, T ConstVal, T Mask) {
0868 if (bitSetMatch(Str, outputting() && (Val & Mask) == ConstVal))
0869 Val = Val | ConstVal;
0870 }
0871
0872 template <typename T>
0873 void maskedBitSetCase(T &Val, const char *Str, uint32_t ConstVal,
0874 uint32_t Mask) {
0875 if (bitSetMatch(Str, outputting() && (Val & Mask) == ConstVal))
0876 Val = Val | ConstVal;
0877 }
0878
0879 void *getContext() const;
0880 void setContext(void *);
0881
0882 template <typename T> void mapRequired(const char *Key, T &Val) {
0883 EmptyContext Ctx;
0884 this->processKey(Key, Val, true, Ctx);
0885 }
0886
0887 template <typename T, typename Context>
0888 void mapRequired(const char *Key, T &Val, Context &Ctx) {
0889 this->processKey(Key, Val, true, Ctx);
0890 }
0891
0892 template <typename T> void mapOptional(const char *Key, T &Val) {
0893 EmptyContext Ctx;
0894 mapOptionalWithContext(Key, Val, Ctx);
0895 }
0896
0897 template <typename T, typename DefaultT>
0898 void mapOptional(const char *Key, T &Val, const DefaultT &Default) {
0899 EmptyContext Ctx;
0900 mapOptionalWithContext(Key, Val, Default, Ctx);
0901 }
0902
0903 template <typename T, typename Context>
0904 std::enable_if_t<has_SequenceTraits<T>::value, void>
0905 mapOptionalWithContext(const char *Key, T &Val, Context &Ctx) {
0906 // omit key/value instead of outputting empty sequence
0907 if (this->canElideEmptySequence() && !(Val.begin() != Val.end()))
0908 return;
0909 this->processKey(Key, Val, false, Ctx);
0910 }
0911
0912 template <typename T, typename Context>
0913 void mapOptionalWithContext(const char *Key, std::optional<T> &Val,
0914 Context &Ctx) {
0915 this->processKeyWithDefault(Key, Val, std::optional<T>(),
0916 /*Required=*/false, Ctx);
0917 }
0918
0919 template <typename T, typename Context>
0920 std::enable_if_t<!has_SequenceTraits<T>::value, void>
0921 mapOptionalWithContext(const char *Key, T &Val, Context &Ctx) {
0922 this->processKey(Key, Val, false, Ctx);
0923 }
0924
0925 template <typename T, typename Context, typename DefaultT>
0926 void mapOptionalWithContext(const char *Key, T &Val, const DefaultT &Default,
0927 Context &Ctx) {
0928 static_assert(std::is_convertible<DefaultT, T>::value,
0929 "Default type must be implicitly convertible to value type!");
0930 this->processKeyWithDefault(Key, Val, static_cast<const T &>(Default),
0931 false, Ctx);
0932 }
0933
0934 private:
0935 template <typename T, typename Context>
0936 void processKeyWithDefault(const char *Key, std::optional<T> &Val,
0937 const std::optional<T> &DefaultValue,
0938 bool Required, Context &Ctx);
0939
0940 template <typename T, typename Context>
0941 void processKeyWithDefault(const char *Key, T &Val, const T &DefaultValue,
0942 bool Required, Context &Ctx) {
0943 void *SaveInfo;
0944 bool UseDefault;
0945 const bool sameAsDefault = outputting() && Val == DefaultValue;
0946 if ( this->preflightKey(Key, Required, sameAsDefault, UseDefault,
0947 SaveInfo) ) {
0948 yamlize(*this, Val, Required, Ctx);
0949 this->postflightKey(SaveInfo);
0950 }
0951 else {
0952 if ( UseDefault )
0953 Val = DefaultValue;
0954 }
0955 }
0956
0957 template <typename T, typename Context>
0958 void processKey(const char *Key, T &Val, bool Required, Context &Ctx) {
0959 void *SaveInfo;
0960 bool UseDefault;
0961 if ( this->preflightKey(Key, Required, false, UseDefault, SaveInfo) ) {
0962 yamlize(*this, Val, Required, Ctx);
0963 this->postflightKey(SaveInfo);
0964 }
0965 }
0966
0967 private:
0968 void *Ctxt;
0969 };
0970
0971 namespace detail {
0972
0973 template <typename T, typename Context>
0974 void doMapping(IO &io, T &Val, Context &Ctx) {
0975 MappingContextTraits<T, Context>::mapping(io, Val, Ctx);
0976 }
0977
0978 template <typename T> void doMapping(IO &io, T &Val, EmptyContext &Ctx) {
0979 MappingTraits<T>::mapping(io, Val);
0980 }
0981
0982 } // end namespace detail
0983
0984 template <typename T>
0985 std::enable_if_t<has_ScalarEnumerationTraits<T>::value, void>
0986 yamlize(IO &io, T &Val, bool, EmptyContext &Ctx) {
0987 io.beginEnumScalar();
0988 ScalarEnumerationTraits<T>::enumeration(io, Val);
0989 io.endEnumScalar();
0990 }
0991
0992 template <typename T>
0993 std::enable_if_t<has_ScalarBitSetTraits<T>::value, void>
0994 yamlize(IO &io, T &Val, bool, EmptyContext &Ctx) {
0995 bool DoClear;
0996 if ( io.beginBitSetScalar(DoClear) ) {
0997 if ( DoClear )
0998 Val = T();
0999 ScalarBitSetTraits<T>::bitset(io, Val);
1000 io.endBitSetScalar();
1001 }
1002 }
1003
1004 template <typename T>
1005 std::enable_if_t<has_ScalarTraits<T>::value, void> yamlize(IO &io, T &Val, bool,
1006 EmptyContext &Ctx) {
1007 if ( io.outputting() ) {
1008 SmallString<128> Storage;
1009 raw_svector_ostream Buffer(Storage);
1010 ScalarTraits<T>::output(Val, io.getContext(), Buffer);
1011 StringRef Str = Buffer.str();
1012 io.scalarString(Str, ScalarTraits<T>::mustQuote(Str));
1013 }
1014 else {
1015 StringRef Str;
1016 io.scalarString(Str, ScalarTraits<T>::mustQuote(Str));
1017 StringRef Result = ScalarTraits<T>::input(Str, io.getContext(), Val);
1018 if ( !Result.empty() ) {
1019 io.setError(Twine(Result));
1020 }
1021 }
1022 }
1023
1024 template <typename T>
1025 std::enable_if_t<has_BlockScalarTraits<T>::value, void>
1026 yamlize(IO &YamlIO, T &Val, bool, EmptyContext &Ctx) {
1027 if (YamlIO.outputting()) {
1028 std::string Storage;
1029 raw_string_ostream Buffer(Storage);
1030 BlockScalarTraits<T>::output(Val, YamlIO.getContext(), Buffer);
1031 StringRef Str(Storage);
1032 YamlIO.blockScalarString(Str);
1033 } else {
1034 StringRef Str;
1035 YamlIO.blockScalarString(Str);
1036 StringRef Result =
1037 BlockScalarTraits<T>::input(Str, YamlIO.getContext(), Val);
1038 if (!Result.empty())
1039 YamlIO.setError(Twine(Result));
1040 }
1041 }
1042
1043 template <typename T>
1044 std::enable_if_t<has_TaggedScalarTraits<T>::value, void>
1045 yamlize(IO &io, T &Val, bool, EmptyContext &Ctx) {
1046 if (io.outputting()) {
1047 std::string ScalarStorage, TagStorage;
1048 raw_string_ostream ScalarBuffer(ScalarStorage), TagBuffer(TagStorage);
1049 TaggedScalarTraits<T>::output(Val, io.getContext(), ScalarBuffer,
1050 TagBuffer);
1051 io.scalarTag(TagStorage);
1052 StringRef ScalarStr(ScalarStorage);
1053 io.scalarString(ScalarStr,
1054 TaggedScalarTraits<T>::mustQuote(Val, ScalarStr));
1055 } else {
1056 std::string Tag;
1057 io.scalarTag(Tag);
1058 StringRef Str;
1059 io.scalarString(Str, QuotingType::None);
1060 StringRef Result =
1061 TaggedScalarTraits<T>::input(Str, Tag, io.getContext(), Val);
1062 if (!Result.empty()) {
1063 io.setError(Twine(Result));
1064 }
1065 }
1066 }
1067
1068 namespace detail {
1069
1070 template <typename T, typename Context>
1071 std::string doValidate(IO &io, T &Val, Context &Ctx) {
1072 return MappingContextTraits<T, Context>::validate(io, Val, Ctx);
1073 }
1074
1075 template <typename T> std::string doValidate(IO &io, T &Val, EmptyContext &) {
1076 return MappingTraits<T>::validate(io, Val);
1077 }
1078
1079 } // namespace detail
1080
1081 template <typename T, typename Context>
1082 std::enable_if_t<validatedMappingTraits<T, Context>::value, void>
1083 yamlize(IO &io, T &Val, bool, Context &Ctx) {
1084 if (has_FlowTraits<MappingTraits<T>>::value)
1085 io.beginFlowMapping();
1086 else
1087 io.beginMapping();
1088 if (io.outputting()) {
1089 std::string Err = detail::doValidate(io, Val, Ctx);
1090 if (!Err.empty()) {
1091 errs() << Err << "\n";
1092 assert(Err.empty() && "invalid struct trying to be written as yaml");
1093 }
1094 }
1095 detail::doMapping(io, Val, Ctx);
1096 if (!io.outputting()) {
1097 std::string Err = detail::doValidate(io, Val, Ctx);
1098 if (!Err.empty())
1099 io.setError(Err);
1100 }
1101 if (has_FlowTraits<MappingTraits<T>>::value)
1102 io.endFlowMapping();
1103 else
1104 io.endMapping();
1105 }
1106
1107 template <typename T, typename Context>
1108 std::enable_if_t<!has_MappingEnumInputTraits<T, Context>::value, bool>
1109 yamlizeMappingEnumInput(IO &io, T &Val) {
1110 return false;
1111 }
1112
1113 template <typename T, typename Context>
1114 std::enable_if_t<has_MappingEnumInputTraits<T, Context>::value, bool>
1115 yamlizeMappingEnumInput(IO &io, T &Val) {
1116 if (io.outputting())
1117 return false;
1118
1119 io.beginEnumScalar();
1120 MappingTraits<T>::enumInput(io, Val);
1121 bool Matched = !io.matchEnumFallback();
1122 io.endEnumScalar();
1123 return Matched;
1124 }
1125
1126 template <typename T, typename Context>
1127 std::enable_if_t<unvalidatedMappingTraits<T, Context>::value, void>
1128 yamlize(IO &io, T &Val, bool, Context &Ctx) {
1129 if (yamlizeMappingEnumInput<T, Context>(io, Val))
1130 return;
1131 if (has_FlowTraits<MappingTraits<T>>::value) {
1132 io.beginFlowMapping();
1133 detail::doMapping(io, Val, Ctx);
1134 io.endFlowMapping();
1135 } else {
1136 io.beginMapping();
1137 detail::doMapping(io, Val, Ctx);
1138 io.endMapping();
1139 }
1140 }
1141
1142 template <typename T>
1143 std::enable_if_t<has_CustomMappingTraits<T>::value, void>
1144 yamlize(IO &io, T &Val, bool, EmptyContext &Ctx) {
1145 if ( io.outputting() ) {
1146 io.beginMapping();
1147 CustomMappingTraits<T>::output(io, Val);
1148 io.endMapping();
1149 } else {
1150 io.beginMapping();
1151 for (StringRef key : io.keys())
1152 CustomMappingTraits<T>::inputOne(io, key, Val);
1153 io.endMapping();
1154 }
1155 }
1156
1157 template <typename T>
1158 std::enable_if_t<has_PolymorphicTraits<T>::value, void>
1159 yamlize(IO &io, T &Val, bool, EmptyContext &Ctx) {
1160 switch (io.outputting() ? PolymorphicTraits<T>::getKind(Val)
1161 : io.getNodeKind()) {
1162 case NodeKind::Scalar:
1163 return yamlize(io, PolymorphicTraits<T>::getAsScalar(Val), true, Ctx);
1164 case NodeKind::Map:
1165 return yamlize(io, PolymorphicTraits<T>::getAsMap(Val), true, Ctx);
1166 case NodeKind::Sequence:
1167 return yamlize(io, PolymorphicTraits<T>::getAsSequence(Val), true, Ctx);
1168 }
1169 }
1170
1171 template <typename T>
1172 std::enable_if_t<missingTraits<T, EmptyContext>::value, void>
1173 yamlize(IO &io, T &Val, bool, EmptyContext &Ctx) {
1174 char missing_yaml_trait_for_type[sizeof(MissingTrait<T>)];
1175 }
1176
1177 template <typename T, typename Context>
1178 std::enable_if_t<has_SequenceTraits<T>::value, void>
1179 yamlize(IO &io, T &Seq, bool, Context &Ctx) {
1180 if ( has_FlowTraits< SequenceTraits<T>>::value ) {
1181 unsigned incnt = io.beginFlowSequence();
1182 unsigned count = io.outputting() ? SequenceTraits<T>::size(io, Seq) : incnt;
1183 for(unsigned i=0; i < count; ++i) {
1184 void *SaveInfo;
1185 if ( io.preflightFlowElement(i, SaveInfo) ) {
1186 yamlize(io, SequenceTraits<T>::element(io, Seq, i), true, Ctx);
1187 io.postflightFlowElement(SaveInfo);
1188 }
1189 }
1190 io.endFlowSequence();
1191 }
1192 else {
1193 unsigned incnt = io.beginSequence();
1194 unsigned count = io.outputting() ? SequenceTraits<T>::size(io, Seq) : incnt;
1195 for(unsigned i=0; i < count; ++i) {
1196 void *SaveInfo;
1197 if ( io.preflightElement(i, SaveInfo) ) {
1198 yamlize(io, SequenceTraits<T>::element(io, Seq, i), true, Ctx);
1199 io.postflightElement(SaveInfo);
1200 }
1201 }
1202 io.endSequence();
1203 }
1204 }
1205
1206 template<>
1207 struct ScalarTraits<bool> {
1208 static void output(const bool &, void* , raw_ostream &);
1209 static StringRef input(StringRef, void *, bool &);
1210 static QuotingType mustQuote(StringRef) { return QuotingType::None; }
1211 };
1212
1213 template<>
1214 struct ScalarTraits<StringRef> {
1215 static void output(const StringRef &, void *, raw_ostream &);
1216 static StringRef input(StringRef, void *, StringRef &);
1217 static QuotingType mustQuote(StringRef S) { return needsQuotes(S); }
1218 };
1219
1220 template<>
1221 struct ScalarTraits<std::string> {
1222 static void output(const std::string &, void *, raw_ostream &);
1223 static StringRef input(StringRef, void *, std::string &);
1224 static QuotingType mustQuote(StringRef S) { return needsQuotes(S); }
1225 };
1226
1227 template<>
1228 struct ScalarTraits<uint8_t> {
1229 static void output(const uint8_t &, void *, raw_ostream &);
1230 static StringRef input(StringRef, void *, uint8_t &);
1231 static QuotingType mustQuote(StringRef) { return QuotingType::None; }
1232 };
1233
1234 template<>
1235 struct ScalarTraits<uint16_t> {
1236 static void output(const uint16_t &, void *, raw_ostream &);
1237 static StringRef input(StringRef, void *, uint16_t &);
1238 static QuotingType mustQuote(StringRef) { return QuotingType::None; }
1239 };
1240
1241 template<>
1242 struct ScalarTraits<uint32_t> {
1243 static void output(const uint32_t &, void *, raw_ostream &);
1244 static StringRef input(StringRef, void *, uint32_t &);
1245 static QuotingType mustQuote(StringRef) { return QuotingType::None; }
1246 };
1247
1248 template<>
1249 struct ScalarTraits<uint64_t> {
1250 static void output(const uint64_t &, void *, raw_ostream &);
1251 static StringRef input(StringRef, void *, uint64_t &);
1252 static QuotingType mustQuote(StringRef) { return QuotingType::None; }
1253 };
1254
1255 template<>
1256 struct ScalarTraits<int8_t> {
1257 static void output(const int8_t &, void *, raw_ostream &);
1258 static StringRef input(StringRef, void *, int8_t &);
1259 static QuotingType mustQuote(StringRef) { return QuotingType::None; }
1260 };
1261
1262 template<>
1263 struct ScalarTraits<int16_t> {
1264 static void output(const int16_t &, void *, raw_ostream &);
1265 static StringRef input(StringRef, void *, int16_t &);
1266 static QuotingType mustQuote(StringRef) { return QuotingType::None; }
1267 };
1268
1269 template<>
1270 struct ScalarTraits<int32_t> {
1271 static void output(const int32_t &, void *, raw_ostream &);
1272 static StringRef input(StringRef, void *, int32_t &);
1273 static QuotingType mustQuote(StringRef) { return QuotingType::None; }
1274 };
1275
1276 template<>
1277 struct ScalarTraits<int64_t> {
1278 static void output(const int64_t &, void *, raw_ostream &);
1279 static StringRef input(StringRef, void *, int64_t &);
1280 static QuotingType mustQuote(StringRef) { return QuotingType::None; }
1281 };
1282
1283 template<>
1284 struct ScalarTraits<float> {
1285 static void output(const float &, void *, raw_ostream &);
1286 static StringRef input(StringRef, void *, float &);
1287 static QuotingType mustQuote(StringRef) { return QuotingType::None; }
1288 };
1289
1290 template<>
1291 struct ScalarTraits<double> {
1292 static void output(const double &, void *, raw_ostream &);
1293 static StringRef input(StringRef, void *, double &);
1294 static QuotingType mustQuote(StringRef) { return QuotingType::None; }
1295 };
1296
1297 // For endian types, we use existing scalar Traits class for the underlying
1298 // type. This way endian aware types are supported whenever the traits are
1299 // defined for the underlying type.
1300 template <typename value_type, llvm::endianness endian, size_t alignment>
1301 struct ScalarTraits<support::detail::packed_endian_specific_integral<
1302 value_type, endian, alignment>,
1303 std::enable_if_t<has_ScalarTraits<value_type>::value>> {
1304 using endian_type =
1305 support::detail::packed_endian_specific_integral<value_type, endian,
1306 alignment>;
1307
1308 static void output(const endian_type &E, void *Ctx, raw_ostream &Stream) {
1309 ScalarTraits<value_type>::output(static_cast<value_type>(E), Ctx, Stream);
1310 }
1311
1312 static StringRef input(StringRef Str, void *Ctx, endian_type &E) {
1313 value_type V;
1314 auto R = ScalarTraits<value_type>::input(Str, Ctx, V);
1315 E = static_cast<endian_type>(V);
1316 return R;
1317 }
1318
1319 static QuotingType mustQuote(StringRef Str) {
1320 return ScalarTraits<value_type>::mustQuote(Str);
1321 }
1322 };
1323
1324 template <typename value_type, llvm::endianness endian, size_t alignment>
1325 struct ScalarEnumerationTraits<
1326 support::detail::packed_endian_specific_integral<value_type, endian,
1327 alignment>,
1328 std::enable_if_t<has_ScalarEnumerationTraits<value_type>::value>> {
1329 using endian_type =
1330 support::detail::packed_endian_specific_integral<value_type, endian,
1331 alignment>;
1332
1333 static void enumeration(IO &io, endian_type &E) {
1334 value_type V = E;
1335 ScalarEnumerationTraits<value_type>::enumeration(io, V);
1336 E = V;
1337 }
1338 };
1339
1340 template <typename value_type, llvm::endianness endian, size_t alignment>
1341 struct ScalarBitSetTraits<
1342 support::detail::packed_endian_specific_integral<value_type, endian,
1343 alignment>,
1344 std::enable_if_t<has_ScalarBitSetTraits<value_type>::value>> {
1345 using endian_type =
1346 support::detail::packed_endian_specific_integral<value_type, endian,
1347 alignment>;
1348 static void bitset(IO &io, endian_type &E) {
1349 value_type V = E;
1350 ScalarBitSetTraits<value_type>::bitset(io, V);
1351 E = V;
1352 }
1353 };
1354
1355 // Utility for use within MappingTraits<>::mapping() method
1356 // to [de]normalize an object for use with YAML conversion.
1357 template <typename TNorm, typename TFinal>
1358 struct MappingNormalization {
1359 MappingNormalization(IO &i_o, TFinal &Obj)
1360 : io(i_o), BufPtr(nullptr), Result(Obj) {
1361 if ( io.outputting() ) {
1362 BufPtr = new (&Buffer) TNorm(io, Obj);
1363 }
1364 else {
1365 BufPtr = new (&Buffer) TNorm(io);
1366 }
1367 }
1368
1369 ~MappingNormalization() {
1370 if ( ! io.outputting() ) {
1371 Result = BufPtr->denormalize(io);
1372 }
1373 BufPtr->~TNorm();
1374 }
1375
1376 TNorm* operator->() { return BufPtr; }
1377
1378 private:
1379 using Storage = AlignedCharArrayUnion<TNorm>;
1380
1381 Storage Buffer;
1382 IO &io;
1383 TNorm *BufPtr;
1384 TFinal &Result;
1385 };
1386
1387 // Utility for use within MappingTraits<>::mapping() method
1388 // to [de]normalize an object for use with YAML conversion.
1389 template <typename TNorm, typename TFinal>
1390 struct MappingNormalizationHeap {
1391 MappingNormalizationHeap(IO &i_o, TFinal &Obj, BumpPtrAllocator *allocator)
1392 : io(i_o), Result(Obj) {
1393 if ( io.outputting() ) {
1394 BufPtr = new (&Buffer) TNorm(io, Obj);
1395 }
1396 else if (allocator) {
1397 BufPtr = allocator->Allocate<TNorm>();
1398 new (BufPtr) TNorm(io);
1399 } else {
1400 BufPtr = new TNorm(io);
1401 }
1402 }
1403
1404 ~MappingNormalizationHeap() {
1405 if ( io.outputting() ) {
1406 BufPtr->~TNorm();
1407 }
1408 else {
1409 Result = BufPtr->denormalize(io);
1410 }
1411 }
1412
1413 TNorm* operator->() { return BufPtr; }
1414
1415 private:
1416 using Storage = AlignedCharArrayUnion<TNorm>;
1417
1418 Storage Buffer;
1419 IO &io;
1420 TNorm *BufPtr = nullptr;
1421 TFinal &Result;
1422 };
1423
1424 ///
1425 /// The Input class is used to parse a yaml document into in-memory structs
1426 /// and vectors.
1427 ///
1428 /// It works by using YAMLParser to do a syntax parse of the entire yaml
1429 /// document, then the Input class builds a graph of HNodes which wraps
1430 /// each yaml Node. The extra layer is buffering. The low level yaml
1431 /// parser only lets you look at each node once. The buffering layer lets
1432 /// you search and interate multiple times. This is necessary because
1433 /// the mapRequired() method calls may not be in the same order
1434 /// as the keys in the document.
1435 ///
1436 class Input : public IO {
1437 public:
1438 // Construct a yaml Input object from a StringRef and optional
1439 // user-data. The DiagHandler can be specified to provide
1440 // alternative error reporting.
1441 Input(StringRef InputContent,
1442 void *Ctxt = nullptr,
1443 SourceMgr::DiagHandlerTy DiagHandler = nullptr,
1444 void *DiagHandlerCtxt = nullptr);
1445 Input(MemoryBufferRef Input,
1446 void *Ctxt = nullptr,
1447 SourceMgr::DiagHandlerTy DiagHandler = nullptr,
1448 void *DiagHandlerCtxt = nullptr);
1449 ~Input() override;
1450
1451 // Check if there was an syntax or semantic error during parsing.
1452 std::error_code error() override;
1453
1454 private:
1455 bool outputting() const override;
1456 bool mapTag(StringRef, bool) override;
1457 void beginMapping() override;
1458 void endMapping() override;
1459 bool preflightKey(const char *, bool, bool, bool &, void *&) override;
1460 void postflightKey(void *) override;
1461 std::vector<StringRef> keys() override;
1462 void beginFlowMapping() override;
1463 void endFlowMapping() override;
1464 unsigned beginSequence() override;
1465 void endSequence() override;
1466 bool preflightElement(unsigned index, void *&) override;
1467 void postflightElement(void *) override;
1468 unsigned beginFlowSequence() override;
1469 bool preflightFlowElement(unsigned , void *&) override;
1470 void postflightFlowElement(void *) override;
1471 void endFlowSequence() override;
1472 void beginEnumScalar() override;
1473 bool matchEnumScalar(const char*, bool) override;
1474 bool matchEnumFallback() override;
1475 void endEnumScalar() override;
1476 bool beginBitSetScalar(bool &) override;
1477 bool bitSetMatch(const char *, bool ) override;
1478 void endBitSetScalar() override;
1479 void scalarString(StringRef &, QuotingType) override;
1480 void blockScalarString(StringRef &) override;
1481 void scalarTag(std::string &) override;
1482 NodeKind getNodeKind() override;
1483 void setError(const Twine &message) override;
1484 bool canElideEmptySequence() override;
1485
1486 class HNode {
1487 public:
1488 HNode(Node *n) : _node(n) {}
1489
1490 static bool classof(const HNode *) { return true; }
1491
1492 Node *_node;
1493 };
1494
1495 class EmptyHNode : public HNode {
1496 public:
1497 EmptyHNode(Node *n) : HNode(n) { }
1498
1499 static bool classof(const HNode *n) { return NullNode::classof(n->_node); }
1500
1501 static bool classof(const EmptyHNode *) { return true; }
1502 };
1503
1504 class ScalarHNode : public HNode {
1505 public:
1506 ScalarHNode(Node *n, StringRef s) : HNode(n), _value(s) { }
1507
1508 StringRef value() const { return _value; }
1509
1510 static bool classof(const HNode *n) {
1511 return ScalarNode::classof(n->_node) ||
1512 BlockScalarNode::classof(n->_node);
1513 }
1514
1515 static bool classof(const ScalarHNode *) { return true; }
1516
1517 protected:
1518 StringRef _value;
1519 };
1520
1521 class MapHNode : public HNode {
1522 public:
1523 MapHNode(Node *n) : HNode(n) { }
1524
1525 static bool classof(const HNode *n) {
1526 return MappingNode::classof(n->_node);
1527 }
1528
1529 static bool classof(const MapHNode *) { return true; }
1530
1531 using NameToNodeAndLoc = StringMap<std::pair<HNode *, SMRange>>;
1532
1533 NameToNodeAndLoc Mapping;
1534 SmallVector<std::string, 6> ValidKeys;
1535 };
1536
1537 class SequenceHNode : public HNode {
1538 public:
1539 SequenceHNode(Node *n) : HNode(n) { }
1540
1541 static bool classof(const HNode *n) {
1542 return SequenceNode::classof(n->_node);
1543 }
1544
1545 static bool classof(const SequenceHNode *) { return true; }
1546
1547 std::vector<HNode *> Entries;
1548 };
1549
1550 Input::HNode *createHNodes(Node *node);
1551 void setError(HNode *hnode, const Twine &message);
1552 void setError(Node *node, const Twine &message);
1553 void setError(const SMRange &Range, const Twine &message);
1554
1555 void reportWarning(HNode *hnode, const Twine &message);
1556 void reportWarning(Node *hnode, const Twine &message);
1557 void reportWarning(const SMRange &Range, const Twine &message);
1558
1559 /// Release memory used by HNodes.
1560 void releaseHNodeBuffers();
1561
1562 public:
1563 // These are only used by operator>>. They could be private
1564 // if those templated things could be made friends.
1565 bool setCurrentDocument();
1566 bool nextDocument();
1567
1568 /// Returns the current node that's being parsed by the YAML Parser.
1569 const Node *getCurrentNode() const;
1570
1571 void setAllowUnknownKeys(bool Allow) override;
1572
1573 private:
1574 SourceMgr SrcMgr; // must be before Strm
1575 std::unique_ptr<llvm::yaml::Stream> Strm;
1576 HNode *TopNode = nullptr;
1577 std::error_code EC;
1578 BumpPtrAllocator StringAllocator;
1579 SpecificBumpPtrAllocator<EmptyHNode> EmptyHNodeAllocator;
1580 SpecificBumpPtrAllocator<ScalarHNode> ScalarHNodeAllocator;
1581 SpecificBumpPtrAllocator<MapHNode> MapHNodeAllocator;
1582 SpecificBumpPtrAllocator<SequenceHNode> SequenceHNodeAllocator;
1583 document_iterator DocIterator;
1584 llvm::BitVector BitValuesUsed;
1585 HNode *CurrentNode = nullptr;
1586 bool ScalarMatchFound = false;
1587 bool AllowUnknownKeys = false;
1588 };
1589
1590 ///
1591 /// The Output class is used to generate a yaml document from in-memory structs
1592 /// and vectors.
1593 ///
1594 class Output : public IO {
1595 public:
1596 Output(raw_ostream &, void *Ctxt = nullptr, int WrapColumn = 70);
1597 ~Output() override;
1598
1599 /// Set whether or not to output optional values which are equal
1600 /// to the default value. By default, when outputting if you attempt
1601 /// to write a value that is equal to the default, the value gets ignored.
1602 /// Sometimes, it is useful to be able to see these in the resulting YAML
1603 /// anyway.
1604 void setWriteDefaultValues(bool Write) { WriteDefaultValues = Write; }
1605
1606 bool outputting() const override;
1607 bool mapTag(StringRef, bool) override;
1608 void beginMapping() override;
1609 void endMapping() override;
1610 bool preflightKey(const char *key, bool, bool, bool &, void *&) override;
1611 void postflightKey(void *) override;
1612 std::vector<StringRef> keys() override;
1613 void beginFlowMapping() override;
1614 void endFlowMapping() override;
1615 unsigned beginSequence() override;
1616 void endSequence() override;
1617 bool preflightElement(unsigned, void *&) override;
1618 void postflightElement(void *) override;
1619 unsigned beginFlowSequence() override;
1620 bool preflightFlowElement(unsigned, void *&) override;
1621 void postflightFlowElement(void *) override;
1622 void endFlowSequence() override;
1623 void beginEnumScalar() override;
1624 bool matchEnumScalar(const char*, bool) override;
1625 bool matchEnumFallback() override;
1626 void endEnumScalar() override;
1627 bool beginBitSetScalar(bool &) override;
1628 bool bitSetMatch(const char *, bool ) override;
1629 void endBitSetScalar() override;
1630 void scalarString(StringRef &, QuotingType) override;
1631 void blockScalarString(StringRef &) override;
1632 void scalarTag(std::string &) override;
1633 NodeKind getNodeKind() override;
1634 void setError(const Twine &message) override;
1635 std::error_code error() override;
1636 bool canElideEmptySequence() override;
1637
1638 // These are only used by operator<<. They could be private
1639 // if that templated operator could be made a friend.
1640 void beginDocuments();
1641 bool preflightDocument(unsigned);
1642 void postflightDocument();
1643 void endDocuments();
1644
1645 private:
1646 void output(StringRef s);
1647 void output(StringRef, QuotingType);
1648 void outputUpToEndOfLine(StringRef s);
1649 void newLineCheck(bool EmptySequence = false);
1650 void outputNewLine();
1651 void paddedKey(StringRef key);
1652 void flowKey(StringRef Key);
1653
1654 enum InState {
1655 inSeqFirstElement,
1656 inSeqOtherElement,
1657 inFlowSeqFirstElement,
1658 inFlowSeqOtherElement,
1659 inMapFirstKey,
1660 inMapOtherKey,
1661 inFlowMapFirstKey,
1662 inFlowMapOtherKey
1663 };
1664
1665 static bool inSeqAnyElement(InState State);
1666 static bool inFlowSeqAnyElement(InState State);
1667 static bool inMapAnyKey(InState State);
1668 static bool inFlowMapAnyKey(InState State);
1669
1670 raw_ostream &Out;
1671 int WrapColumn;
1672 SmallVector<InState, 8> StateStack;
1673 int Column = 0;
1674 int ColumnAtFlowStart = 0;
1675 int ColumnAtMapFlowStart = 0;
1676 bool NeedBitValueComma = false;
1677 bool NeedFlowSequenceComma = false;
1678 bool EnumerationMatchFound = false;
1679 bool WriteDefaultValues = false;
1680 StringRef Padding;
1681 StringRef PaddingBeforeContainer;
1682 };
1683
1684 template <typename T, typename Context>
1685 void IO::processKeyWithDefault(const char *Key, std::optional<T> &Val,
1686 const std::optional<T> &DefaultValue,
1687 bool Required, Context &Ctx) {
1688 assert(!DefaultValue && "std::optional<T> shouldn't have a value!");
1689 void *SaveInfo;
1690 bool UseDefault = true;
1691 const bool sameAsDefault = outputting() && !Val;
1692 if (!outputting() && !Val)
1693 Val = T();
1694 if (Val &&
1695 this->preflightKey(Key, Required, sameAsDefault, UseDefault, SaveInfo)) {
1696
1697 // When reading an std::optional<X> key from a YAML description, we allow
1698 // the special "<none>" value, which can be used to specify that no value
1699 // was requested, i.e. the DefaultValue will be assigned. The DefaultValue
1700 // is usually None.
1701 bool IsNone = false;
1702 if (!outputting())
1703 if (const auto *Node =
1704 dyn_cast<ScalarNode>(((Input *)this)->getCurrentNode()))
1705 // We use rtrim to ignore possible white spaces that might exist when a
1706 // comment is present on the same line.
1707 IsNone = Node->getRawValue().rtrim(' ') == "<none>";
1708
1709 if (IsNone)
1710 Val = DefaultValue;
1711 else
1712 yamlize(*this, *Val, Required, Ctx);
1713 this->postflightKey(SaveInfo);
1714 } else {
1715 if (UseDefault)
1716 Val = DefaultValue;
1717 }
1718 }
1719
1720 /// YAML I/O does conversion based on types. But often native data types
1721 /// are just a typedef of built in intergral types (e.g. int). But the C++
1722 /// type matching system sees through the typedef and all the typedefed types
1723 /// look like a built in type. This will cause the generic YAML I/O conversion
1724 /// to be used. To provide better control over the YAML conversion, you can
1725 /// use this macro instead of typedef. It will create a class with one field
1726 /// and automatic conversion operators to and from the base type.
1727 /// Based on BOOST_STRONG_TYPEDEF
1728 #define LLVM_YAML_STRONG_TYPEDEF(_base, _type) \
1729 struct _type { \
1730 _type() = default; \
1731 _type(const _base v) : value(v) {} \
1732 _type(const _type &v) = default; \
1733 _type &operator=(const _type &rhs) = default; \
1734 _type &operator=(const _base &rhs) { value = rhs; return *this; } \
1735 operator const _base & () const { return value; } \
1736 bool operator==(const _type &rhs) const { return value == rhs.value; } \
1737 bool operator==(const _base &rhs) const { return value == rhs; } \
1738 bool operator<(const _type &rhs) const { return value < rhs.value; } \
1739 _base value; \
1740 using BaseType = _base; \
1741 };
1742
1743 ///
1744 /// Use these types instead of uintXX_t in any mapping to have
1745 /// its yaml output formatted as hexadecimal.
1746 ///
1747 LLVM_YAML_STRONG_TYPEDEF(uint8_t, Hex8)
1748 LLVM_YAML_STRONG_TYPEDEF(uint16_t, Hex16)
1749 LLVM_YAML_STRONG_TYPEDEF(uint32_t, Hex32)
1750 LLVM_YAML_STRONG_TYPEDEF(uint64_t, Hex64)
1751
1752 template<>
1753 struct ScalarTraits<Hex8> {
1754 static void output(const Hex8 &, void *, raw_ostream &);
1755 static StringRef input(StringRef, void *, Hex8 &);
1756 static QuotingType mustQuote(StringRef) { return QuotingType::None; }
1757 };
1758
1759 template<>
1760 struct ScalarTraits<Hex16> {
1761 static void output(const Hex16 &, void *, raw_ostream &);
1762 static StringRef input(StringRef, void *, Hex16 &);
1763 static QuotingType mustQuote(StringRef) { return QuotingType::None; }
1764 };
1765
1766 template<>
1767 struct ScalarTraits<Hex32> {
1768 static void output(const Hex32 &, void *, raw_ostream &);
1769 static StringRef input(StringRef, void *, Hex32 &);
1770 static QuotingType mustQuote(StringRef) { return QuotingType::None; }
1771 };
1772
1773 template<>
1774 struct ScalarTraits<Hex64> {
1775 static void output(const Hex64 &, void *, raw_ostream &);
1776 static StringRef input(StringRef, void *, Hex64 &);
1777 static QuotingType mustQuote(StringRef) { return QuotingType::None; }
1778 };
1779
1780 template <> struct ScalarTraits<VersionTuple> {
1781 static void output(const VersionTuple &Value, void *, llvm::raw_ostream &Out);
1782 static StringRef input(StringRef, void *, VersionTuple &);
1783 static QuotingType mustQuote(StringRef) { return QuotingType::None; }
1784 };
1785
1786 // Define non-member operator>> so that Input can stream in a document list.
1787 template <typename T>
1788 inline std::enable_if_t<has_DocumentListTraits<T>::value, Input &>
1789 operator>>(Input &yin, T &docList) {
1790 int i = 0;
1791 EmptyContext Ctx;
1792 while ( yin.setCurrentDocument() ) {
1793 yamlize(yin, DocumentListTraits<T>::element(yin, docList, i), true, Ctx);
1794 if ( yin.error() )
1795 return yin;
1796 yin.nextDocument();
1797 ++i;
1798 }
1799 return yin;
1800 }
1801
1802 // Define non-member operator>> so that Input can stream in a map as a document.
1803 template <typename T>
1804 inline std::enable_if_t<has_MappingTraits<T, EmptyContext>::value, Input &>
1805 operator>>(Input &yin, T &docMap) {
1806 EmptyContext Ctx;
1807 yin.setCurrentDocument();
1808 yamlize(yin, docMap, true, Ctx);
1809 return yin;
1810 }
1811
1812 // Define non-member operator>> so that Input can stream in a sequence as
1813 // a document.
1814 template <typename T>
1815 inline std::enable_if_t<has_SequenceTraits<T>::value, Input &>
1816 operator>>(Input &yin, T &docSeq) {
1817 EmptyContext Ctx;
1818 if (yin.setCurrentDocument())
1819 yamlize(yin, docSeq, true, Ctx);
1820 return yin;
1821 }
1822
1823 // Define non-member operator>> so that Input can stream in a block scalar.
1824 template <typename T>
1825 inline std::enable_if_t<has_BlockScalarTraits<T>::value, Input &>
1826 operator>>(Input &In, T &Val) {
1827 EmptyContext Ctx;
1828 if (In.setCurrentDocument())
1829 yamlize(In, Val, true, Ctx);
1830 return In;
1831 }
1832
1833 // Define non-member operator>> so that Input can stream in a string map.
1834 template <typename T>
1835 inline std::enable_if_t<has_CustomMappingTraits<T>::value, Input &>
1836 operator>>(Input &In, T &Val) {
1837 EmptyContext Ctx;
1838 if (In.setCurrentDocument())
1839 yamlize(In, Val, true, Ctx);
1840 return In;
1841 }
1842
1843 // Define non-member operator>> so that Input can stream in a polymorphic type.
1844 template <typename T>
1845 inline std::enable_if_t<has_PolymorphicTraits<T>::value, Input &>
1846 operator>>(Input &In, T &Val) {
1847 EmptyContext Ctx;
1848 if (In.setCurrentDocument())
1849 yamlize(In, Val, true, Ctx);
1850 return In;
1851 }
1852
1853 // Provide better error message about types missing a trait specialization
1854 template <typename T>
1855 inline std::enable_if_t<missingTraits<T, EmptyContext>::value, Input &>
1856 operator>>(Input &yin, T &docSeq) {
1857 char missing_yaml_trait_for_type[sizeof(MissingTrait<T>)];
1858 return yin;
1859 }
1860
1861 // Define non-member operator<< so that Output can stream out document list.
1862 template <typename T>
1863 inline std::enable_if_t<has_DocumentListTraits<T>::value, Output &>
1864 operator<<(Output &yout, T &docList) {
1865 EmptyContext Ctx;
1866 yout.beginDocuments();
1867 const size_t count = DocumentListTraits<T>::size(yout, docList);
1868 for(size_t i=0; i < count; ++i) {
1869 if ( yout.preflightDocument(i) ) {
1870 yamlize(yout, DocumentListTraits<T>::element(yout, docList, i), true,
1871 Ctx);
1872 yout.postflightDocument();
1873 }
1874 }
1875 yout.endDocuments();
1876 return yout;
1877 }
1878
1879 // Define non-member operator<< so that Output can stream out a map.
1880 template <typename T>
1881 inline std::enable_if_t<has_MappingTraits<T, EmptyContext>::value, Output &>
1882 operator<<(Output &yout, T &map) {
1883 EmptyContext Ctx;
1884 yout.beginDocuments();
1885 if ( yout.preflightDocument(0) ) {
1886 yamlize(yout, map, true, Ctx);
1887 yout.postflightDocument();
1888 }
1889 yout.endDocuments();
1890 return yout;
1891 }
1892
1893 // Define non-member operator<< so that Output can stream out a sequence.
1894 template <typename T>
1895 inline std::enable_if_t<has_SequenceTraits<T>::value, Output &>
1896 operator<<(Output &yout, T &seq) {
1897 EmptyContext Ctx;
1898 yout.beginDocuments();
1899 if ( yout.preflightDocument(0) ) {
1900 yamlize(yout, seq, true, Ctx);
1901 yout.postflightDocument();
1902 }
1903 yout.endDocuments();
1904 return yout;
1905 }
1906
1907 // Define non-member operator<< so that Output can stream out a block scalar.
1908 template <typename T>
1909 inline std::enable_if_t<has_BlockScalarTraits<T>::value, Output &>
1910 operator<<(Output &Out, T &Val) {
1911 EmptyContext Ctx;
1912 Out.beginDocuments();
1913 if (Out.preflightDocument(0)) {
1914 yamlize(Out, Val, true, Ctx);
1915 Out.postflightDocument();
1916 }
1917 Out.endDocuments();
1918 return Out;
1919 }
1920
1921 // Define non-member operator<< so that Output can stream out a string map.
1922 template <typename T>
1923 inline std::enable_if_t<has_CustomMappingTraits<T>::value, Output &>
1924 operator<<(Output &Out, T &Val) {
1925 EmptyContext Ctx;
1926 Out.beginDocuments();
1927 if (Out.preflightDocument(0)) {
1928 yamlize(Out, Val, true, Ctx);
1929 Out.postflightDocument();
1930 }
1931 Out.endDocuments();
1932 return Out;
1933 }
1934
1935 // Define non-member operator<< so that Output can stream out a polymorphic
1936 // type.
1937 template <typename T>
1938 inline std::enable_if_t<has_PolymorphicTraits<T>::value, Output &>
1939 operator<<(Output &Out, T &Val) {
1940 EmptyContext Ctx;
1941 Out.beginDocuments();
1942 if (Out.preflightDocument(0)) {
1943 // FIXME: The parser does not support explicit documents terminated with a
1944 // plain scalar; the end-marker is included as part of the scalar token.
1945 assert(PolymorphicTraits<T>::getKind(Val) != NodeKind::Scalar && "plain scalar documents are not supported");
1946 yamlize(Out, Val, true, Ctx);
1947 Out.postflightDocument();
1948 }
1949 Out.endDocuments();
1950 return Out;
1951 }
1952
1953 // Provide better error message about types missing a trait specialization
1954 template <typename T>
1955 inline std::enable_if_t<missingTraits<T, EmptyContext>::value, Output &>
1956 operator<<(Output &yout, T &seq) {
1957 char missing_yaml_trait_for_type[sizeof(MissingTrait<T>)];
1958 return yout;
1959 }
1960
1961 template <bool B> struct IsFlowSequenceBase {};
1962 template <> struct IsFlowSequenceBase<true> { static const bool flow = true; };
1963
1964 template <typename T, typename U = void>
1965 struct IsResizable : std::false_type {};
1966
1967 template <typename T>
1968 struct IsResizable<T, std::void_t<decltype(std::declval<T>().resize(0))>>
1969 : public std::true_type {};
1970
1971 template <typename T, bool B> struct IsResizableBase {
1972 using type = typename T::value_type;
1973
1974 static type &element(IO &io, T &seq, size_t index) {
1975 if (index >= seq.size())
1976 seq.resize(index + 1);
1977 return seq[index];
1978 }
1979 };
1980
1981 template <typename T> struct IsResizableBase<T, false> {
1982 using type = typename T::value_type;
1983
1984 static type &element(IO &io, T &seq, size_t index) {
1985 if (index >= seq.size()) {
1986 io.setError(Twine("value sequence extends beyond static size (") +
1987 Twine(seq.size()) + ")");
1988 return seq[0];
1989 }
1990 return seq[index];
1991 }
1992 };
1993
1994 template <typename T, bool Flow>
1995 struct SequenceTraitsImpl
1996 : IsFlowSequenceBase<Flow>, IsResizableBase<T, IsResizable<T>::value> {
1997 static size_t size(IO &io, T &seq) { return seq.size(); }
1998 };
1999
2000 // Simple helper to check an expression can be used as a bool-valued template
2001 // argument.
2002 template <bool> struct CheckIsBool { static const bool value = true; };
2003
2004 // If T has SequenceElementTraits, then vector<T> and SmallVector<T, N> have
2005 // SequenceTraits that do the obvious thing.
2006 template <typename T>
2007 struct SequenceTraits<
2008 std::vector<T>,
2009 std::enable_if_t<CheckIsBool<SequenceElementTraits<T>::flow>::value>>
2010 : SequenceTraitsImpl<std::vector<T>, SequenceElementTraits<T>::flow> {};
2011 template <typename T, size_t N>
2012 struct SequenceTraits<
2013 std::array<T, N>,
2014 std::enable_if_t<CheckIsBool<SequenceElementTraits<T>::flow>::value>>
2015 : SequenceTraitsImpl<std::array<T, N>, SequenceElementTraits<T>::flow> {};
2016 template <typename T, unsigned N>
2017 struct SequenceTraits<
2018 SmallVector<T, N>,
2019 std::enable_if_t<CheckIsBool<SequenceElementTraits<T>::flow>::value>>
2020 : SequenceTraitsImpl<SmallVector<T, N>, SequenceElementTraits<T>::flow> {};
2021 template <typename T>
2022 struct SequenceTraits<
2023 SmallVectorImpl<T>,
2024 std::enable_if_t<CheckIsBool<SequenceElementTraits<T>::flow>::value>>
2025 : SequenceTraitsImpl<SmallVectorImpl<T>, SequenceElementTraits<T>::flow> {};
2026 template <typename T>
2027 struct SequenceTraits<
2028 MutableArrayRef<T>,
2029 std::enable_if_t<CheckIsBool<SequenceElementTraits<T>::flow>::value>>
2030 : SequenceTraitsImpl<MutableArrayRef<T>, SequenceElementTraits<T>::flow> {};
2031
2032 // Sequences of fundamental types use flow formatting.
2033 template <typename T>
2034 struct SequenceElementTraits<T, std::enable_if_t<std::is_fundamental_v<T>>> {
2035 static const bool flow = true;
2036 };
2037
2038 // Sequences of strings use block formatting.
2039 template<> struct SequenceElementTraits<std::string> {
2040 static const bool flow = false;
2041 };
2042 template<> struct SequenceElementTraits<StringRef> {
2043 static const bool flow = false;
2044 };
2045 template<> struct SequenceElementTraits<std::pair<std::string, std::string>> {
2046 static const bool flow = false;
2047 };
2048
2049 /// Implementation of CustomMappingTraits for std::map<std::string, T>.
2050 template <typename T> struct StdMapStringCustomMappingTraitsImpl {
2051 using map_type = std::map<std::string, T>;
2052
2053 static void inputOne(IO &io, StringRef key, map_type &v) {
2054 io.mapRequired(key.str().c_str(), v[std::string(key)]);
2055 }
2056
2057 static void output(IO &io, map_type &v) {
2058 for (auto &p : v)
2059 io.mapRequired(p.first.c_str(), p.second);
2060 }
2061 };
2062
2063 } // end namespace yaml
2064 } // end namespace llvm
2065
2066 #define LLVM_YAML_IS_SEQUENCE_VECTOR_IMPL(TYPE, FLOW) \
2067 namespace llvm { \
2068 namespace yaml { \
2069 static_assert( \
2070 !std::is_fundamental_v<TYPE> && !std::is_same_v<TYPE, std::string> && \
2071 !std::is_same_v<TYPE, llvm::StringRef>, \
2072 "only use LLVM_YAML_IS_SEQUENCE_VECTOR for types you control"); \
2073 template <> struct SequenceElementTraits<TYPE> { \
2074 static const bool flow = FLOW; \
2075 }; \
2076 } \
2077 }
2078
2079 /// Utility for declaring that a std::vector of a particular type
2080 /// should be considered a YAML sequence.
2081 #define LLVM_YAML_IS_SEQUENCE_VECTOR(type) \
2082 LLVM_YAML_IS_SEQUENCE_VECTOR_IMPL(type, false)
2083
2084 /// Utility for declaring that a std::vector of a particular type
2085 /// should be considered a YAML flow sequence.
2086 #define LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(type) \
2087 LLVM_YAML_IS_SEQUENCE_VECTOR_IMPL(type, true)
2088
2089 #define LLVM_YAML_DECLARE_MAPPING_TRAITS(Type) \
2090 namespace llvm { \
2091 namespace yaml { \
2092 template <> struct LLVM_ABI MappingTraits<Type> { \
2093 static void mapping(IO &IO, Type &Obj); \
2094 }; \
2095 } \
2096 }
2097
2098 #define LLVM_YAML_DECLARE_MAPPING_TRAITS_PRIVATE(Type) \
2099 namespace llvm { \
2100 namespace yaml { \
2101 template <> struct MappingTraits<Type> { \
2102 static void mapping(IO &IO, Type &Obj); \
2103 }; \
2104 } \
2105 }
2106
2107 #define LLVM_YAML_DECLARE_ENUM_TRAITS(Type) \
2108 namespace llvm { \
2109 namespace yaml { \
2110 template <> struct LLVM_ABI ScalarEnumerationTraits<Type> { \
2111 static void enumeration(IO &io, Type &Value); \
2112 }; \
2113 } \
2114 }
2115
2116 #define LLVM_YAML_DECLARE_BITSET_TRAITS(Type) \
2117 namespace llvm { \
2118 namespace yaml { \
2119 template <> struct LLVM_ABI ScalarBitSetTraits<Type> { \
2120 static void bitset(IO &IO, Type &Options); \
2121 }; \
2122 } \
2123 }
2124
2125 #define LLVM_YAML_DECLARE_SCALAR_TRAITS(Type, MustQuote) \
2126 namespace llvm { \
2127 namespace yaml { \
2128 template <> struct LLVM_ABI ScalarTraits<Type> { \
2129 static void output(const Type &Value, void *ctx, raw_ostream &Out); \
2130 static StringRef input(StringRef Scalar, void *ctxt, Type &Value); \
2131 static QuotingType mustQuote(StringRef) { return MustQuote; } \
2132 }; \
2133 } \
2134 }
2135
2136 /// Utility for declaring that a std::vector of a particular type
2137 /// should be considered a YAML document list.
2138 #define LLVM_YAML_IS_DOCUMENT_LIST_VECTOR(_type) \
2139 namespace llvm { \
2140 namespace yaml { \
2141 template <unsigned N> \
2142 struct DocumentListTraits<SmallVector<_type, N>> \
2143 : public SequenceTraitsImpl<SmallVector<_type, N>, false> {}; \
2144 template <> \
2145 struct DocumentListTraits<std::vector<_type>> \
2146 : public SequenceTraitsImpl<std::vector<_type>, false> {}; \
2147 } \
2148 }
2149
2150 /// Utility for declaring that std::map<std::string, _type> should be considered
2151 /// a YAML map.
2152 #define LLVM_YAML_IS_STRING_MAP(_type) \
2153 namespace llvm { \
2154 namespace yaml { \
2155 template <> \
2156 struct CustomMappingTraits<std::map<std::string, _type>> \
2157 : public StdMapStringCustomMappingTraitsImpl<_type> {}; \
2158 } \
2159 }
2160
2161 LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(llvm::yaml::Hex64)
2162 LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(llvm::yaml::Hex32)
2163 LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(llvm::yaml::Hex16)
2164 LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(llvm::yaml::Hex8)
2165
2166 #endif // LLVM_SUPPORT_YAMLTRAITS_H