1 //===- lib/Support/YAMLTraits.cpp -----------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 #include "llvm/Support/YAMLTraits.h"
10 #include "llvm/ADT/STLExtras.h"
11 #include "llvm/ADT/SmallString.h"
12 #include "llvm/ADT/StringExtras.h"
13 #include "llvm/ADT/StringRef.h"
14 #include "llvm/ADT/Twine.h"
15 #include "llvm/Support/Casting.h"
16 #include "llvm/Support/Errc.h"
17 #include "llvm/Support/ErrorHandling.h"
18 #include "llvm/Support/Format.h"
19 #include "llvm/Support/LineIterator.h"
20 #include "llvm/Support/MemoryBuffer.h"
21 #include "llvm/Support/VersionTuple.h"
22 #include "llvm/Support/YAMLParser.h"
23 #include "llvm/Support/raw_ostream.h"
34 //===----------------------------------------------------------------------===//
36 //===----------------------------------------------------------------------===//
38 IO::IO(void *Context
) : Ctxt(Context
) {}
42 void *IO::getContext() const {
46 void IO::setContext(void *Context
) {
50 void IO::setAllowUnknownKeys(bool Allow
) {
51 llvm_unreachable("Only supported for Input");
54 //===----------------------------------------------------------------------===//
56 //===----------------------------------------------------------------------===//
58 Input::Input(StringRef InputContent
, void *Ctxt
,
59 SourceMgr::DiagHandlerTy DiagHandler
, void *DiagHandlerCtxt
)
60 : IO(Ctxt
), Strm(new Stream(InputContent
, SrcMgr
, false, &EC
)) {
62 SrcMgr
.setDiagHandler(DiagHandler
, DiagHandlerCtxt
);
63 DocIterator
= Strm
->begin();
66 Input::Input(MemoryBufferRef Input
, void *Ctxt
,
67 SourceMgr::DiagHandlerTy DiagHandler
, void *DiagHandlerCtxt
)
68 : IO(Ctxt
), Strm(new Stream(Input
, SrcMgr
, false, &EC
)) {
70 SrcMgr
.setDiagHandler(DiagHandler
, DiagHandlerCtxt
);
71 DocIterator
= Strm
->begin();
74 Input::~Input() = default;
76 std::error_code
Input::error() { return EC
; }
78 bool Input::outputting() const {
82 bool Input::setCurrentDocument() {
83 if (DocIterator
!= Strm
->end()) {
84 Node
*N
= DocIterator
->getRoot();
86 EC
= make_error_code(errc::invalid_argument
);
90 if (isa
<NullNode
>(N
)) {
91 // Empty files are allowed and ignored
93 return setCurrentDocument();
95 releaseHNodeBuffers();
96 TopNode
= createHNodes(N
);
97 CurrentNode
= TopNode
;
103 bool Input::nextDocument() {
104 return ++DocIterator
!= Strm
->end();
107 const Node
*Input::getCurrentNode() const {
108 return CurrentNode
? CurrentNode
->_node
: nullptr;
111 bool Input::mapTag(StringRef Tag
, bool Default
) {
112 // CurrentNode can be null if setCurrentDocument() was unable to
113 // parse the document because it was invalid or empty.
117 std::string foundTag
= CurrentNode
->_node
->getVerbatimTag();
118 if (foundTag
.empty()) {
119 // If no tag found and 'Tag' is the default, say it was found.
122 // Return true iff found tag matches supplied tag.
123 return Tag
.equals(foundTag
);
126 void Input::beginMapping() {
129 // CurrentNode can be null if the document is empty.
130 MapHNode
*MN
= dyn_cast_or_null
<MapHNode
>(CurrentNode
);
132 MN
->ValidKeys
.clear();
136 std::vector
<StringRef
> Input::keys() {
137 MapHNode
*MN
= dyn_cast
<MapHNode
>(CurrentNode
);
138 std::vector
<StringRef
> Ret
;
140 setError(CurrentNode
, "not a mapping");
143 for (auto &P
: MN
->Mapping
)
144 Ret
.push_back(P
.first());
148 bool Input::preflightKey(const char *Key
, bool Required
, bool, bool &UseDefault
,
154 // CurrentNode is null for empty documents, which is an error in case required
155 // nodes are present.
158 EC
= make_error_code(errc::invalid_argument
);
164 MapHNode
*MN
= dyn_cast
<MapHNode
>(CurrentNode
);
166 if (Required
|| !isa
<EmptyHNode
>(CurrentNode
))
167 setError(CurrentNode
, "not a mapping");
172 MN
->ValidKeys
.push_back(Key
);
173 HNode
*Value
= MN
->Mapping
[Key
].first
;
176 setError(CurrentNode
, Twine("missing required key '") + Key
+ "'");
181 SaveInfo
= CurrentNode
;
186 void Input::postflightKey(void *saveInfo
) {
187 CurrentNode
= reinterpret_cast<HNode
*>(saveInfo
);
190 void Input::endMapping() {
193 // CurrentNode can be null if the document is empty.
194 MapHNode
*MN
= dyn_cast_or_null
<MapHNode
>(CurrentNode
);
197 for (const auto &NN
: MN
->Mapping
) {
198 if (!is_contained(MN
->ValidKeys
, NN
.first())) {
199 const SMRange
&ReportLoc
= NN
.second
.second
;
200 if (!AllowUnknownKeys
) {
201 setError(ReportLoc
, Twine("unknown key '") + NN
.first() + "'");
204 reportWarning(ReportLoc
, Twine("unknown key '") + NN
.first() + "'");
209 void Input::beginFlowMapping() { beginMapping(); }
211 void Input::endFlowMapping() { endMapping(); }
213 unsigned Input::beginSequence() {
214 if (SequenceHNode
*SQ
= dyn_cast
<SequenceHNode
>(CurrentNode
))
215 return SQ
->Entries
.size();
216 if (isa
<EmptyHNode
>(CurrentNode
))
218 // Treat case where there's a scalar "null" value as an empty sequence.
219 if (ScalarHNode
*SN
= dyn_cast
<ScalarHNode
>(CurrentNode
)) {
220 if (isNull(SN
->value()))
223 // Any other type of HNode is an error.
224 setError(CurrentNode
, "not a sequence");
228 void Input::endSequence() {
231 bool Input::preflightElement(unsigned Index
, void *&SaveInfo
) {
234 if (SequenceHNode
*SQ
= dyn_cast
<SequenceHNode
>(CurrentNode
)) {
235 SaveInfo
= CurrentNode
;
236 CurrentNode
= SQ
->Entries
[Index
];
242 void Input::postflightElement(void *SaveInfo
) {
243 CurrentNode
= reinterpret_cast<HNode
*>(SaveInfo
);
246 unsigned Input::beginFlowSequence() { return beginSequence(); }
248 bool Input::preflightFlowElement(unsigned index
, void *&SaveInfo
) {
251 if (SequenceHNode
*SQ
= dyn_cast
<SequenceHNode
>(CurrentNode
)) {
252 SaveInfo
= CurrentNode
;
253 CurrentNode
= SQ
->Entries
[index
];
259 void Input::postflightFlowElement(void *SaveInfo
) {
260 CurrentNode
= reinterpret_cast<HNode
*>(SaveInfo
);
263 void Input::endFlowSequence() {
266 void Input::beginEnumScalar() {
267 ScalarMatchFound
= false;
270 bool Input::matchEnumScalar(const char *Str
, bool) {
271 if (ScalarMatchFound
)
273 if (ScalarHNode
*SN
= dyn_cast
<ScalarHNode
>(CurrentNode
)) {
274 if (SN
->value().equals(Str
)) {
275 ScalarMatchFound
= true;
282 bool Input::matchEnumFallback() {
283 if (ScalarMatchFound
)
285 ScalarMatchFound
= true;
289 void Input::endEnumScalar() {
290 if (!ScalarMatchFound
) {
291 setError(CurrentNode
, "unknown enumerated scalar");
295 bool Input::beginBitSetScalar(bool &DoClear
) {
296 BitValuesUsed
.clear();
297 if (SequenceHNode
*SQ
= dyn_cast
<SequenceHNode
>(CurrentNode
)) {
298 BitValuesUsed
.resize(SQ
->Entries
.size());
300 setError(CurrentNode
, "expected sequence of bit values");
306 bool Input::bitSetMatch(const char *Str
, bool) {
309 if (SequenceHNode
*SQ
= dyn_cast
<SequenceHNode
>(CurrentNode
)) {
311 for (auto &N
: SQ
->Entries
) {
312 if (ScalarHNode
*SN
= dyn_cast
<ScalarHNode
>(N
)) {
313 if (SN
->value().equals(Str
)) {
314 BitValuesUsed
[Index
] = true;
318 setError(CurrentNode
, "unexpected scalar in sequence of bit values");
323 setError(CurrentNode
, "expected sequence of bit values");
328 void Input::endBitSetScalar() {
331 if (SequenceHNode
*SQ
= dyn_cast
<SequenceHNode
>(CurrentNode
)) {
332 assert(BitValuesUsed
.size() == SQ
->Entries
.size());
333 for (unsigned i
= 0; i
< SQ
->Entries
.size(); ++i
) {
334 if (!BitValuesUsed
[i
]) {
335 setError(SQ
->Entries
[i
], "unknown bit value");
342 void Input::scalarString(StringRef
&S
, QuotingType
) {
343 if (ScalarHNode
*SN
= dyn_cast
<ScalarHNode
>(CurrentNode
)) {
346 setError(CurrentNode
, "unexpected scalar");
350 void Input::blockScalarString(StringRef
&S
) { scalarString(S
, QuotingType::None
); }
352 void Input::scalarTag(std::string
&Tag
) {
353 Tag
= CurrentNode
->_node
->getVerbatimTag();
356 void Input::setError(HNode
*hnode
, const Twine
&message
) {
357 assert(hnode
&& "HNode must not be NULL");
358 setError(hnode
->_node
, message
);
361 NodeKind
Input::getNodeKind() {
362 if (isa
<ScalarHNode
>(CurrentNode
))
363 return NodeKind::Scalar
;
364 else if (isa
<MapHNode
>(CurrentNode
))
365 return NodeKind::Map
;
366 else if (isa
<SequenceHNode
>(CurrentNode
))
367 return NodeKind::Sequence
;
368 llvm_unreachable("Unsupported node kind");
371 void Input::setError(Node
*node
, const Twine
&message
) {
372 Strm
->printError(node
, message
);
373 EC
= make_error_code(errc::invalid_argument
);
376 void Input::setError(const SMRange
&range
, const Twine
&message
) {
377 Strm
->printError(range
, message
);
378 EC
= make_error_code(errc::invalid_argument
);
381 void Input::reportWarning(HNode
*hnode
, const Twine
&message
) {
382 assert(hnode
&& "HNode must not be NULL");
383 Strm
->printError(hnode
->_node
, message
, SourceMgr::DK_Warning
);
386 void Input::reportWarning(Node
*node
, const Twine
&message
) {
387 Strm
->printError(node
, message
, SourceMgr::DK_Warning
);
390 void Input::reportWarning(const SMRange
&range
, const Twine
&message
) {
391 Strm
->printError(range
, message
, SourceMgr::DK_Warning
);
394 void Input::releaseHNodeBuffers() {
395 EmptyHNodeAllocator
.DestroyAll();
396 ScalarHNodeAllocator
.DestroyAll();
397 SequenceHNodeAllocator
.DestroyAll();
398 MapHNodeAllocator
.DestroyAll();
401 Input::HNode
*Input::createHNodes(Node
*N
) {
402 SmallString
<128> StringStorage
;
403 switch (N
->getType()) {
404 case Node::NK_Scalar
: {
405 ScalarNode
*SN
= dyn_cast
<ScalarNode
>(N
);
406 StringRef KeyStr
= SN
->getValue(StringStorage
);
407 if (!StringStorage
.empty()) {
408 // Copy string to permanent storage
409 KeyStr
= StringStorage
.str().copy(StringAllocator
);
411 return new (ScalarHNodeAllocator
.Allocate()) ScalarHNode(N
, KeyStr
);
413 case Node::NK_BlockScalar
: {
414 BlockScalarNode
*BSN
= dyn_cast
<BlockScalarNode
>(N
);
415 StringRef ValueCopy
= BSN
->getValue().copy(StringAllocator
);
416 return new (ScalarHNodeAllocator
.Allocate()) ScalarHNode(N
, ValueCopy
);
418 case Node::NK_Sequence
: {
419 SequenceNode
*SQ
= dyn_cast
<SequenceNode
>(N
);
420 auto SQHNode
= new (SequenceHNodeAllocator
.Allocate()) SequenceHNode(N
);
421 for (Node
&SN
: *SQ
) {
422 auto Entry
= createHNodes(&SN
);
425 SQHNode
->Entries
.push_back(Entry
);
429 case Node::NK_Mapping
: {
430 MappingNode
*Map
= dyn_cast
<MappingNode
>(N
);
431 auto mapHNode
= new (MapHNodeAllocator
.Allocate()) MapHNode(N
);
432 for (KeyValueNode
&KVN
: *Map
) {
433 Node
*KeyNode
= KVN
.getKey();
434 ScalarNode
*Key
= dyn_cast_or_null
<ScalarNode
>(KeyNode
);
435 Node
*Value
= KVN
.getValue();
436 if (!Key
|| !Value
) {
438 setError(KeyNode
, "Map key must be a scalar");
440 setError(KeyNode
, "Map value must not be empty");
443 StringStorage
.clear();
444 StringRef KeyStr
= Key
->getValue(StringStorage
);
445 if (!StringStorage
.empty()) {
446 // Copy string to permanent storage
447 KeyStr
= StringStorage
.str().copy(StringAllocator
);
449 if (mapHNode
->Mapping
.count(KeyStr
))
450 // From YAML spec: "The content of a mapping node is an unordered set of
451 // key/value node pairs, with the restriction that each of the keys is
453 setError(KeyNode
, Twine("duplicated mapping key '") + KeyStr
+ "'");
454 auto ValueHNode
= createHNodes(Value
);
457 mapHNode
->Mapping
[KeyStr
] =
458 std::make_pair(std::move(ValueHNode
), KeyNode
->getSourceRange());
460 return std::move(mapHNode
);
463 return new (EmptyHNodeAllocator
.Allocate()) EmptyHNode(N
);
465 setError(N
, "unknown node kind");
470 void Input::setError(const Twine
&Message
) {
471 setError(CurrentNode
, Message
);
474 void Input::setAllowUnknownKeys(bool Allow
) { AllowUnknownKeys
= Allow
; }
476 bool Input::canElideEmptySequence() {
480 //===----------------------------------------------------------------------===//
482 //===----------------------------------------------------------------------===//
484 Output::Output(raw_ostream
&yout
, void *context
, int WrapColumn
)
485 : IO(context
), Out(yout
), WrapColumn(WrapColumn
) {}
487 Output::~Output() = default;
489 bool Output::outputting() const {
493 void Output::beginMapping() {
494 StateStack
.push_back(inMapFirstKey
);
495 PaddingBeforeContainer
= Padding
;
499 bool Output::mapTag(StringRef Tag
, bool Use
) {
501 // If this tag is being written inside a sequence we should write the start
502 // of the sequence before writing the tag, otherwise the tag won't be
503 // attached to the element in the sequence, but rather the sequence itself.
504 bool SequenceElement
= false;
505 if (StateStack
.size() > 1) {
506 auto &E
= StateStack
[StateStack
.size() - 2];
507 SequenceElement
= inSeqAnyElement(E
) || inFlowSeqAnyElement(E
);
509 if (SequenceElement
&& StateStack
.back() == inMapFirstKey
) {
515 if (SequenceElement
) {
516 // If we're writing the tag during the first element of a map, the tag
517 // takes the place of the first element in the sequence.
518 if (StateStack
.back() == inMapFirstKey
) {
519 StateStack
.pop_back();
520 StateStack
.push_back(inMapOtherKey
);
522 // Tags inside maps in sequences should act as keys in the map from a
523 // formatting perspective, so we always want a newline in a sequence.
530 void Output::endMapping() {
531 // If we did not map anything, we should explicitly emit an empty map
532 if (StateStack
.back() == inMapFirstKey
) {
533 Padding
= PaddingBeforeContainer
;
538 StateStack
.pop_back();
541 std::vector
<StringRef
> Output::keys() {
542 report_fatal_error("invalid call");
545 bool Output::preflightKey(const char *Key
, bool Required
, bool SameAsDefault
,
546 bool &UseDefault
, void *&SaveInfo
) {
549 if (Required
|| !SameAsDefault
|| WriteDefaultValues
) {
550 auto State
= StateStack
.back();
551 if (State
== inFlowMapFirstKey
|| State
== inFlowMapOtherKey
) {
562 void Output::postflightKey(void *) {
563 if (StateStack
.back() == inMapFirstKey
) {
564 StateStack
.pop_back();
565 StateStack
.push_back(inMapOtherKey
);
566 } else if (StateStack
.back() == inFlowMapFirstKey
) {
567 StateStack
.pop_back();
568 StateStack
.push_back(inFlowMapOtherKey
);
572 void Output::beginFlowMapping() {
573 StateStack
.push_back(inFlowMapFirstKey
);
575 ColumnAtMapFlowStart
= Column
;
579 void Output::endFlowMapping() {
580 StateStack
.pop_back();
581 outputUpToEndOfLine(" }");
584 void Output::beginDocuments() {
585 outputUpToEndOfLine("---");
588 bool Output::preflightDocument(unsigned index
) {
590 outputUpToEndOfLine("\n---");
594 void Output::postflightDocument() {
597 void Output::endDocuments() {
601 unsigned Output::beginSequence() {
602 StateStack
.push_back(inSeqFirstElement
);
603 PaddingBeforeContainer
= Padding
;
608 void Output::endSequence() {
609 // If we did not emit anything, we should explicitly emit an empty sequence
610 if (StateStack
.back() == inSeqFirstElement
) {
611 Padding
= PaddingBeforeContainer
;
612 newLineCheck(/*EmptySequence=*/true);
616 StateStack
.pop_back();
619 bool Output::preflightElement(unsigned, void *&SaveInfo
) {
624 void Output::postflightElement(void *) {
625 if (StateStack
.back() == inSeqFirstElement
) {
626 StateStack
.pop_back();
627 StateStack
.push_back(inSeqOtherElement
);
628 } else if (StateStack
.back() == inFlowSeqFirstElement
) {
629 StateStack
.pop_back();
630 StateStack
.push_back(inFlowSeqOtherElement
);
634 unsigned Output::beginFlowSequence() {
635 StateStack
.push_back(inFlowSeqFirstElement
);
637 ColumnAtFlowStart
= Column
;
639 NeedFlowSequenceComma
= false;
643 void Output::endFlowSequence() {
644 StateStack
.pop_back();
645 outputUpToEndOfLine(" ]");
648 bool Output::preflightFlowElement(unsigned, void *&SaveInfo
) {
649 if (NeedFlowSequenceComma
)
651 if (WrapColumn
&& Column
> WrapColumn
) {
653 for (int i
= 0; i
< ColumnAtFlowStart
; ++i
)
655 Column
= ColumnAtFlowStart
;
662 void Output::postflightFlowElement(void *) {
663 NeedFlowSequenceComma
= true;
666 void Output::beginEnumScalar() {
667 EnumerationMatchFound
= false;
670 bool Output::matchEnumScalar(const char *Str
, bool Match
) {
671 if (Match
&& !EnumerationMatchFound
) {
673 outputUpToEndOfLine(Str
);
674 EnumerationMatchFound
= true;
679 bool Output::matchEnumFallback() {
680 if (EnumerationMatchFound
)
682 EnumerationMatchFound
= true;
686 void Output::endEnumScalar() {
687 if (!EnumerationMatchFound
)
688 llvm_unreachable("bad runtime enum value");
691 bool Output::beginBitSetScalar(bool &DoClear
) {
694 NeedBitValueComma
= false;
699 bool Output::bitSetMatch(const char *Str
, bool Matches
) {
701 if (NeedBitValueComma
)
704 NeedBitValueComma
= true;
709 void Output::endBitSetScalar() {
710 outputUpToEndOfLine(" ]");
713 void Output::scalarString(StringRef
&S
, QuotingType MustQuote
) {
716 // Print '' for the empty string because leaving the field empty is not
718 outputUpToEndOfLine("''");
721 if (MustQuote
== QuotingType::None
) {
722 // Only quote if we must.
723 outputUpToEndOfLine(S
);
727 const char *const Quote
= MustQuote
== QuotingType::Single
? "'" : "\"";
728 output(Quote
); // Starting quote.
730 // When using double-quoted strings (and only in that case), non-printable characters may be
731 // present, and will be escaped using a variety of unicode-scalar and special short-form
732 // escapes. This is handled in yaml::escape.
733 if (MustQuote
== QuotingType::Double
) {
734 output(yaml::escape(S
, /* EscapePrintable= */ false));
735 outputUpToEndOfLine(Quote
);
741 unsigned End
= S
.size();
742 const char *Base
= S
.data();
744 // When using single-quoted strings, any single quote ' must be doubled to be escaped.
746 if (S
[j
] == '\'') { // Escape quotes.
747 output(StringRef(&Base
[i
], j
- i
)); // "flush".
748 output(StringLiteral("''")); // Print it as ''
753 output(StringRef(&Base
[i
], j
- i
));
754 outputUpToEndOfLine(Quote
); // Ending quote.
757 void Output::blockScalarString(StringRef
&S
) {
758 if (!StateStack
.empty())
763 unsigned Indent
= StateStack
.empty() ? 1 : StateStack
.size();
765 auto Buffer
= MemoryBuffer::getMemBuffer(S
, "", false);
766 for (line_iterator
Lines(*Buffer
, false); !Lines
.is_at_end(); ++Lines
) {
767 for (unsigned I
= 0; I
< Indent
; ++I
) {
775 void Output::scalarTag(std::string
&Tag
) {
783 void Output::setError(const Twine
&message
) {
786 bool Output::canElideEmptySequence() {
787 // Normally, with an optional key/value where the value is an empty sequence,
788 // the whole key/value can be not written. But, that produces wrong yaml
789 // if the key/value is the only thing in the map and the map is used in
790 // a sequence. This detects if the this sequence is the first key/value
791 // in map that itself is embedded in a sequence.
792 if (StateStack
.size() < 2)
794 if (StateStack
.back() != inMapFirstKey
)
796 return !inSeqAnyElement(StateStack
[StateStack
.size() - 2]);
799 void Output::output(StringRef s
) {
804 void Output::outputUpToEndOfLine(StringRef s
) {
806 if (StateStack
.empty() || (!inFlowSeqAnyElement(StateStack
.back()) &&
807 !inFlowMapAnyKey(StateStack
.back())))
811 void Output::outputNewLine() {
816 // if seq at top, indent as if map, then add "- "
817 // if seq in middle, use "- " if firstKey, else use " "
820 void Output::newLineCheck(bool EmptySequence
) {
821 if (Padding
!= "\n") {
829 if (StateStack
.size() == 0 || EmptySequence
)
832 unsigned Indent
= StateStack
.size() - 1;
833 bool OutputDash
= false;
835 if (StateStack
.back() == inSeqFirstElement
||
836 StateStack
.back() == inSeqOtherElement
) {
838 } else if ((StateStack
.size() > 1) &&
839 ((StateStack
.back() == inMapFirstKey
) ||
840 inFlowSeqAnyElement(StateStack
.back()) ||
841 (StateStack
.back() == inFlowMapFirstKey
)) &&
842 inSeqAnyElement(StateStack
[StateStack
.size() - 2])) {
847 for (unsigned i
= 0; i
< Indent
; ++i
) {
855 void Output::paddedKey(StringRef key
) {
858 const char *spaces
= " ";
859 if (key
.size() < strlen(spaces
))
860 Padding
= &spaces
[key
.size()];
865 void Output::flowKey(StringRef Key
) {
866 if (StateStack
.back() == inFlowMapOtherKey
)
868 if (WrapColumn
&& Column
> WrapColumn
) {
870 for (int I
= 0; I
< ColumnAtMapFlowStart
; ++I
)
872 Column
= ColumnAtMapFlowStart
;
879 NodeKind
Output::getNodeKind() { report_fatal_error("invalid call"); }
881 bool Output::inSeqAnyElement(InState State
) {
882 return State
== inSeqFirstElement
|| State
== inSeqOtherElement
;
885 bool Output::inFlowSeqAnyElement(InState State
) {
886 return State
== inFlowSeqFirstElement
|| State
== inFlowSeqOtherElement
;
889 bool Output::inMapAnyKey(InState State
) {
890 return State
== inMapFirstKey
|| State
== inMapOtherKey
;
893 bool Output::inFlowMapAnyKey(InState State
) {
894 return State
== inFlowMapFirstKey
|| State
== inFlowMapOtherKey
;
897 //===----------------------------------------------------------------------===//
898 // traits for built-in types
899 //===----------------------------------------------------------------------===//
901 void ScalarTraits
<bool>::output(const bool &Val
, void *, raw_ostream
&Out
) {
902 Out
<< (Val
? "true" : "false");
905 StringRef ScalarTraits
<bool>::input(StringRef Scalar
, void *, bool &Val
) {
906 if (std::optional
<bool> Parsed
= parseBool(Scalar
)) {
910 return "invalid boolean";
913 void ScalarTraits
<StringRef
>::output(const StringRef
&Val
, void *,
918 StringRef ScalarTraits
<StringRef
>::input(StringRef Scalar
, void *,
924 void ScalarTraits
<std::string
>::output(const std::string
&Val
, void *,
929 StringRef ScalarTraits
<std::string
>::input(StringRef Scalar
, void *,
935 void ScalarTraits
<uint8_t>::output(const uint8_t &Val
, void *,
937 // use temp uin32_t because ostream thinks uint8_t is a character
942 StringRef ScalarTraits
<uint8_t>::input(StringRef Scalar
, void *, uint8_t &Val
) {
943 unsigned long long n
;
944 if (getAsUnsignedInteger(Scalar
, 0, n
))
945 return "invalid number";
947 return "out of range number";
952 void ScalarTraits
<uint16_t>::output(const uint16_t &Val
, void *,
957 StringRef ScalarTraits
<uint16_t>::input(StringRef Scalar
, void *,
959 unsigned long long n
;
960 if (getAsUnsignedInteger(Scalar
, 0, n
))
961 return "invalid number";
963 return "out of range number";
968 void ScalarTraits
<uint32_t>::output(const uint32_t &Val
, void *,
973 StringRef ScalarTraits
<uint32_t>::input(StringRef Scalar
, void *,
975 unsigned long long n
;
976 if (getAsUnsignedInteger(Scalar
, 0, n
))
977 return "invalid number";
978 if (n
> 0xFFFFFFFFUL
)
979 return "out of range number";
984 void ScalarTraits
<uint64_t>::output(const uint64_t &Val
, void *,
989 StringRef ScalarTraits
<uint64_t>::input(StringRef Scalar
, void *,
991 unsigned long long N
;
992 if (getAsUnsignedInteger(Scalar
, 0, N
))
993 return "invalid number";
998 void ScalarTraits
<int8_t>::output(const int8_t &Val
, void *, raw_ostream
&Out
) {
999 // use temp in32_t because ostream thinks int8_t is a character
1004 StringRef ScalarTraits
<int8_t>::input(StringRef Scalar
, void *, int8_t &Val
) {
1006 if (getAsSignedInteger(Scalar
, 0, N
))
1007 return "invalid number";
1008 if ((N
> 127) || (N
< -128))
1009 return "out of range number";
1014 void ScalarTraits
<int16_t>::output(const int16_t &Val
, void *,
1019 StringRef ScalarTraits
<int16_t>::input(StringRef Scalar
, void *, int16_t &Val
) {
1021 if (getAsSignedInteger(Scalar
, 0, N
))
1022 return "invalid number";
1023 if ((N
> INT16_MAX
) || (N
< INT16_MIN
))
1024 return "out of range number";
1029 void ScalarTraits
<int32_t>::output(const int32_t &Val
, void *,
1034 StringRef ScalarTraits
<int32_t>::input(StringRef Scalar
, void *, int32_t &Val
) {
1036 if (getAsSignedInteger(Scalar
, 0, N
))
1037 return "invalid number";
1038 if ((N
> INT32_MAX
) || (N
< INT32_MIN
))
1039 return "out of range number";
1044 void ScalarTraits
<int64_t>::output(const int64_t &Val
, void *,
1049 StringRef ScalarTraits
<int64_t>::input(StringRef Scalar
, void *, int64_t &Val
) {
1051 if (getAsSignedInteger(Scalar
, 0, N
))
1052 return "invalid number";
1057 void ScalarTraits
<double>::output(const double &Val
, void *, raw_ostream
&Out
) {
1058 Out
<< format("%g", Val
);
1061 StringRef ScalarTraits
<double>::input(StringRef Scalar
, void *, double &Val
) {
1062 if (to_float(Scalar
, Val
))
1064 return "invalid floating point number";
1067 void ScalarTraits
<float>::output(const float &Val
, void *, raw_ostream
&Out
) {
1068 Out
<< format("%g", Val
);
1071 StringRef ScalarTraits
<float>::input(StringRef Scalar
, void *, float &Val
) {
1072 if (to_float(Scalar
, Val
))
1074 return "invalid floating point number";
1077 void ScalarTraits
<Hex8
>::output(const Hex8
&Val
, void *, raw_ostream
&Out
) {
1078 Out
<< format("0x%" PRIX8
, (uint8_t)Val
);
1081 StringRef ScalarTraits
<Hex8
>::input(StringRef Scalar
, void *, Hex8
&Val
) {
1082 unsigned long long n
;
1083 if (getAsUnsignedInteger(Scalar
, 0, n
))
1084 return "invalid hex8 number";
1086 return "out of range hex8 number";
1091 void ScalarTraits
<Hex16
>::output(const Hex16
&Val
, void *, raw_ostream
&Out
) {
1092 Out
<< format("0x%" PRIX16
, (uint16_t)Val
);
1095 StringRef ScalarTraits
<Hex16
>::input(StringRef Scalar
, void *, Hex16
&Val
) {
1096 unsigned long long n
;
1097 if (getAsUnsignedInteger(Scalar
, 0, n
))
1098 return "invalid hex16 number";
1100 return "out of range hex16 number";
1105 void ScalarTraits
<Hex32
>::output(const Hex32
&Val
, void *, raw_ostream
&Out
) {
1106 Out
<< format("0x%" PRIX32
, (uint32_t)Val
);
1109 StringRef ScalarTraits
<Hex32
>::input(StringRef Scalar
, void *, Hex32
&Val
) {
1110 unsigned long long n
;
1111 if (getAsUnsignedInteger(Scalar
, 0, n
))
1112 return "invalid hex32 number";
1113 if (n
> 0xFFFFFFFFUL
)
1114 return "out of range hex32 number";
1119 void ScalarTraits
<Hex64
>::output(const Hex64
&Val
, void *, raw_ostream
&Out
) {
1120 Out
<< format("0x%" PRIX64
, (uint64_t)Val
);
1123 StringRef ScalarTraits
<Hex64
>::input(StringRef Scalar
, void *, Hex64
&Val
) {
1124 unsigned long long Num
;
1125 if (getAsUnsignedInteger(Scalar
, 0, Num
))
1126 return "invalid hex64 number";
1131 void ScalarTraits
<VersionTuple
>::output(const VersionTuple
&Val
, void *,
1132 llvm::raw_ostream
&Out
) {
1133 Out
<< Val
.getAsString();
1136 StringRef ScalarTraits
<VersionTuple
>::input(StringRef Scalar
, void *,
1137 VersionTuple
&Val
) {
1138 if (Val
.tryParse(Scalar
))
1139 return "invalid version format";