LLVM 24.0.0git
YAMLTraits.cpp
Go to the documentation of this file.
1//===- lib/Support/YAMLTraits.cpp -----------------------------------------===//
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
10#include "llvm/ADT/STLExtras.h"
13#include "llvm/ADT/StringRef.h"
14#include "llvm/ADT/Twine.h"
17#include "llvm/Support/Errc.h"
19#include "llvm/Support/Format.h"
26#include <cassert>
27#include <cstdint>
28#include <cstring>
29#include <string>
30#include <vector>
31
32using namespace llvm;
33using namespace yaml;
34
35//===----------------------------------------------------------------------===//
36// IO
37//===----------------------------------------------------------------------===//
38
39IO::IO(void *Context) : Ctxt(Context) {}
40
41IO::~IO() = default;
42
43void *IO::getContext() const {
44 return Ctxt;
45}
46
47void IO::setContext(void *Context) {
48 Ctxt = Context;
49}
50
51void IO::setAllowUnknownKeys(bool Allow) {
52 llvm_unreachable("Only supported for Input");
53}
54
55//===----------------------------------------------------------------------===//
56// Input
57//===----------------------------------------------------------------------===//
58
59Input::Input(StringRef InputContent, void *Ctxt,
60 SourceMgr::DiagHandlerTy DiagHandler, void *DiagHandlerCtxt)
61 : IO(Ctxt), Strm(new Stream(InputContent, SrcMgr, false, &EC)) {
62 if (DiagHandler)
63 SrcMgr.setDiagHandler(DiagHandler, DiagHandlerCtxt);
64 DocIterator = Strm->begin();
65}
66
68 SourceMgr::DiagHandlerTy DiagHandler, void *DiagHandlerCtxt)
69 : IO(Ctxt), Strm(new Stream(Input, SrcMgr, false, &EC)) {
70 if (DiagHandler)
71 SrcMgr.setDiagHandler(DiagHandler, DiagHandlerCtxt);
72 DocIterator = Strm->begin();
73}
74
75Input::~Input() = default;
76
77std::error_code Input::error() { return EC; }
78
79bool Input::outputting() const {
80 return false;
81}
82
84 if (DocIterator != Strm->end()) {
85 Node *N = DocIterator->getRoot();
86 if (!N) {
88 return false;
89 }
90
91 if (isa<NullNode>(N)) {
92 // Empty files are allowed and ignored
93 ++DocIterator;
94 return setCurrentDocument();
95 }
96 releaseHNodeBuffers();
97 TopNode = createHNodes(N);
98 CurrentNode = TopNode;
99 return true;
100 }
101 return false;
102}
103
105 return ++DocIterator != Strm->end();
106}
107
109 return CurrentNode ? CurrentNode->_node : nullptr;
110}
111
112bool Input::mapTag(StringRef Tag, bool Default) {
113 // CurrentNode can be null if setCurrentDocument() was unable to
114 // parse the document because it was invalid or empty.
115 if (!CurrentNode)
116 return false;
117
118 std::string foundTag = CurrentNode->_node->getVerbatimTag();
119 if (foundTag.empty()) {
120 // If no tag found and 'Tag' is the default, say it was found.
121 return Default;
122 }
123 // Return true iff found tag matches supplied tag.
124 return Tag == foundTag;
125}
126
127void Input::beginMapping() {
128 if (EC)
129 return;
130 // CurrentNode can be null if the document is empty.
131 MapHNode *MN = dyn_cast_or_null<MapHNode>(CurrentNode);
132 if (MN) {
133 MN->ValidKeys.clear();
134 }
135}
136
137std::vector<StringRef> Input::keys() {
138 MapHNode *MN = dyn_cast<MapHNode>(CurrentNode);
139 std::vector<StringRef> Ret;
140 if (!MN) {
141 setError(CurrentNode, "not a mapping");
142 return Ret;
143 }
144 for (auto &P : MN->Mapping)
145 Ret.push_back(P.first());
146 return Ret;
147}
148
149bool Input::preflightKey(StringRef Key, bool Required, bool, bool &UseDefault,
150 void *&SaveInfo) {
151 UseDefault = false;
152 if (EC)
153 return false;
154
155 // CurrentNode is null for empty documents, which is an error in case required
156 // nodes are present.
157 if (!CurrentNode) {
158 if (Required)
160 else
161 UseDefault = true;
162 return false;
163 }
164
165 MapHNode *MN = dyn_cast<MapHNode>(CurrentNode);
166 if (!MN) {
167 if (Required || !isa<EmptyHNode>(CurrentNode))
168 setError(CurrentNode, "not a mapping");
169 else
170 UseDefault = true;
171 return false;
172 }
173 MN->ValidKeys.push_back(Key.str());
174 HNode *Value = MN->Mapping[Key].first;
175 if (!Value) {
176 if (Required)
177 setError(CurrentNode, Twine("missing required key '") + Key + "'");
178 else
179 UseDefault = true;
180 return false;
181 }
182 SaveInfo = CurrentNode;
183 CurrentNode = Value;
184 return true;
185}
186
187void Input::postflightKey(void *saveInfo) {
188 CurrentNode = reinterpret_cast<HNode *>(saveInfo);
189}
190
191void Input::endMapping() {
192 if (EC)
193 return;
194 // CurrentNode can be null if the document is empty.
195 MapHNode *MN = dyn_cast_or_null<MapHNode>(CurrentNode);
196 if (!MN)
197 return;
198 for (const auto &NN : MN->Mapping) {
199 if (!is_contained(MN->ValidKeys, NN.first())) {
200 const SMRange &ReportLoc = NN.second.second;
201 if (!AllowUnknownKeys) {
202 setError(ReportLoc, Twine("unknown key '") + NN.first() + "'");
203 break;
204 } else
205 reportWarning(ReportLoc, Twine("unknown key '") + NN.first() + "'");
206 }
207 }
208}
209
211
213
214unsigned Input::beginSequence() {
215 if (SequenceHNode *SQ = dyn_cast<SequenceHNode>(CurrentNode))
216 return SQ->Entries.size();
217 if (isa<EmptyHNode>(CurrentNode))
218 return 0;
219 // Treat case where there's a scalar "null" value as an empty sequence.
220 if (ScalarHNode *SN = dyn_cast<ScalarHNode>(CurrentNode)) {
221 if (isNull(SN->value()))
222 return 0;
223 }
224 // Any other type of HNode is an error.
225 setError(CurrentNode, "not a sequence");
226 return 0;
227}
228
229void Input::endSequence() {
230}
231
232bool Input::preflightElement(unsigned Index, void *&SaveInfo) {
233 if (EC)
234 return false;
235 if (SequenceHNode *SQ = dyn_cast<SequenceHNode>(CurrentNode)) {
236 SaveInfo = CurrentNode;
237 CurrentNode = SQ->Entries[Index];
238 return true;
239 }
240 return false;
241}
242
243void Input::postflightElement(void *SaveInfo) {
244 CurrentNode = reinterpret_cast<HNode *>(SaveInfo);
245}
246
247unsigned Input::beginFlowSequence() { return beginSequence(); }
248
249bool Input::preflightFlowElement(unsigned index, void *&SaveInfo) {
250 if (EC)
251 return false;
252 if (SequenceHNode *SQ = dyn_cast<SequenceHNode>(CurrentNode)) {
253 SaveInfo = CurrentNode;
254 CurrentNode = SQ->Entries[index];
255 return true;
256 }
257 return false;
258}
259
260void Input::postflightFlowElement(void *SaveInfo) {
261 CurrentNode = reinterpret_cast<HNode *>(SaveInfo);
262}
263
265}
266
268 ScalarMatchFound = false;
269}
270
271bool Input::matchEnumScalar(StringRef Str, bool) {
272 if (ScalarMatchFound)
273 return false;
274 if (ScalarHNode *SN = dyn_cast<ScalarHNode>(CurrentNode)) {
275 if (SN->value() == Str) {
276 ScalarMatchFound = true;
277 return true;
278 }
279 }
280 return false;
281}
282
284 if (ScalarMatchFound)
285 return false;
286 ScalarMatchFound = true;
287 return true;
288}
289
291 if (!ScalarMatchFound) {
292 setError(CurrentNode, "unknown enumerated scalar");
293 }
294}
295
296bool Input::beginBitSetScalar(bool &DoClear) {
297 BitValuesUsed.clear();
298 if (SequenceHNode *SQ = dyn_cast<SequenceHNode>(CurrentNode)) {
299 BitValuesUsed.resize(SQ->Entries.size());
300 } else {
301 setError(CurrentNode, "expected sequence of bit values");
302 }
303 DoClear = true;
304 return true;
305}
306
307bool Input::bitSetMatch(StringRef Str, bool) {
308 if (EC)
309 return false;
310 if (SequenceHNode *SQ = dyn_cast<SequenceHNode>(CurrentNode)) {
311 unsigned Index = 0;
312 for (auto &N : SQ->Entries) {
313 if (ScalarHNode *SN = dyn_cast<ScalarHNode>(N)) {
314 if (SN->value() == Str) {
315 BitValuesUsed[Index] = true;
316 return true;
317 }
318 } else {
319 setError(CurrentNode, "unexpected scalar in sequence of bit values");
320 }
321 ++Index;
322 }
323 } else {
324 setError(CurrentNode, "expected sequence of bit values");
325 }
326 return false;
327}
328
330 if (EC)
331 return;
332 if (SequenceHNode *SQ = dyn_cast<SequenceHNode>(CurrentNode)) {
333 assert(BitValuesUsed.size() == SQ->Entries.size());
334 for (unsigned i = 0; i < SQ->Entries.size(); ++i) {
335 if (!BitValuesUsed[i]) {
336 setError(SQ->Entries[i], "unknown bit value");
337 return;
338 }
339 }
340 }
341}
342
343void Input::scalarString(StringRef &S, QuotingType) {
344 if (ScalarHNode *SN = dyn_cast<ScalarHNode>(CurrentNode)) {
345 S = SN->value();
346 } else {
347 setError(CurrentNode, "unexpected scalar");
348 }
349}
350
351void Input::blockScalarString(StringRef &S) { scalarString(S, QuotingType::None); }
352
353void Input::scalarTag(std::string &Tag) {
354 Tag = CurrentNode->_node->getVerbatimTag();
355}
356
357void Input::setError(HNode *hnode, const Twine &message) {
358 assert(hnode && "HNode must not be NULL");
359 setError(hnode->_node, message);
360}
361
363 if (isa<ScalarHNode>(CurrentNode))
364 return NodeKind::Scalar;
365 else if (isa<MapHNode>(CurrentNode))
366 return NodeKind::Map;
367 else if (isa<SequenceHNode>(CurrentNode))
368 return NodeKind::Sequence;
369 llvm_unreachable("Unsupported node kind");
370}
371
372void Input::setError(Node *node, const Twine &message) {
373 Strm->printError(node, message);
375}
376
377void Input::setError(const SMRange &range, const Twine &message) {
378 Strm->printError(range, message);
380}
381
382void Input::reportWarning(HNode *hnode, const Twine &message) {
383 assert(hnode && "HNode must not be NULL");
384 Strm->printError(hnode->_node, message, SourceMgr::DK_Warning);
385}
386
387void Input::reportWarning(Node *node, const Twine &message) {
388 Strm->printError(node, message, SourceMgr::DK_Warning);
389}
390
391void Input::reportWarning(const SMRange &range, const Twine &message) {
392 Strm->printError(range, message, SourceMgr::DK_Warning);
393}
394
395void Input::releaseHNodeBuffers() {
396 EmptyHNodeAllocator.DestroyAll();
397 ScalarHNodeAllocator.DestroyAll();
398 SequenceHNodeAllocator.DestroyAll();
399 MapHNodeAllocator.DestroyAll();
400}
401
402void Input::saveAliasHNode(Node *N, HNode *HN) {
403 StringRef Anchor = N->getAnchor();
404 if (!Anchor.empty())
405 // YAML 1.2.2 - 3.2.2.2. Anchors and Aliases:
406 //
407 // An alias event refers to the most recent event in the serialization
408 // having the specified anchor. Therefore, anchors need not be unique within
409 // a serialization. In addition, an anchor need not have an alias node
410 // referring to it.
411 AliasMap[Anchor] = HN;
412}
413
414Input::HNode *Input::createHNodes(Node *N) {
415 SmallString<128> StringStorage;
416 switch (N->getType()) {
417 case Node::NK_Scalar: {
418 ScalarNode *SN = dyn_cast<ScalarNode>(N);
419 StringRef KeyStr = SN->getValue(StringStorage);
420 if (!StringStorage.empty()) {
421 // Copy string to permanent storage
422 KeyStr = StringStorage.str().copy(StringAllocator);
423 }
424 auto *SHNode = new (ScalarHNodeAllocator.Allocate()) ScalarHNode(N, KeyStr);
425 saveAliasHNode(SN, SHNode);
426 return SHNode;
427 }
429 BlockScalarNode *BSN = dyn_cast<BlockScalarNode>(N);
430 StringRef ValueCopy = BSN->getValue().copy(StringAllocator);
431 auto *BSHNode =
432 new (ScalarHNodeAllocator.Allocate()) ScalarHNode(N, ValueCopy);
433 saveAliasHNode(BSN, BSHNode);
434 return BSHNode;
435 }
436 case Node::NK_Sequence: {
437 SequenceNode *SQ = dyn_cast<SequenceNode>(N);
438 auto SQHNode = new (SequenceHNodeAllocator.Allocate()) SequenceHNode(N);
439 for (Node &SN : *SQ) {
440 auto Entry = createHNodes(&SN);
441 if (EC)
442 break;
443 SQHNode->Entries.push_back(Entry);
444 }
445 saveAliasHNode(SQ, SQHNode);
446 return SQHNode;
447 }
448 case Node::NK_Mapping: {
449 MappingNode *Map = dyn_cast<MappingNode>(N);
450 auto mapHNode = new (MapHNodeAllocator.Allocate()) MapHNode(N);
451 for (KeyValueNode &KVN : *Map) {
452 Node *KeyNode = KVN.getKey();
453 ScalarNode *Key = dyn_cast_if_present<ScalarNode>(KeyNode);
454 Node *Value = KVN.getValue();
455 if (!Key || !Value) {
456 if (!Key)
457 setError(KeyNode, "Map key must be a scalar");
458 if (!Value)
459 setError(KeyNode, "Map value must not be empty");
460 break;
461 }
462 StringStorage.clear();
463 StringRef KeyStr = Key->getValue(StringStorage);
464 if (!StringStorage.empty()) {
465 // Copy string to permanent storage
466 KeyStr = StringStorage.str().copy(StringAllocator);
467 }
468 if (mapHNode->Mapping.count(KeyStr))
469 // From YAML spec: "The content of a mapping node is an unordered set of
470 // key/value node pairs, with the restriction that each of the keys is
471 // unique."
472 setError(KeyNode, Twine("duplicated mapping key '") + KeyStr + "'");
473 auto ValueHNode = createHNodes(Value);
474 if (EC)
475 break;
476 mapHNode->Mapping[KeyStr] =
477 std::make_pair(std::move(ValueHNode), KeyNode->getSourceRange());
478 }
479 saveAliasHNode(Map, mapHNode);
480 return std::move(mapHNode);
481 }
482 case Node::NK_Null:
483 // TODO: Anchor is not set for NullNode in the parser. Update the parser to
484 // faithfully preserve anchors.
485 return new (EmptyHNodeAllocator.Allocate()) EmptyHNode(N);
486 case Node::NK_Alias: {
487 AliasNode *AN = dyn_cast<AliasNode>(N);
488 auto AliasName = AN->getName();
489 auto AHN = AliasMap.find(AliasName);
490 if (AHN == AliasMap.end()) {
491 setError(AN, Twine("undefined alias '" + AliasName + "'"));
492 return nullptr;
493 }
494 return AHN->second;
495 }
496 default:
497 setError(N, "unknown node kind");
498 return nullptr;
499 }
500}
501
502void Input::setError(const Twine &Message) {
503 setError(CurrentNode, Message);
504}
505
506void Input::setAllowUnknownKeys(bool Allow) { AllowUnknownKeys = Allow; }
507
509 return false;
510}
511
512//===----------------------------------------------------------------------===//
513// Output
514//===----------------------------------------------------------------------===//
515
516Output::Output(raw_ostream &yout, void *context, int WrapColumn)
517 : IO(context), Out(yout), WrapColumn(WrapColumn) {}
518
519Output::~Output() = default;
520
521bool Output::outputting() const {
522 return true;
523}
524
526 StateStack.push_back(inMapFirstKey);
527 PaddingBeforeContainer = Padding;
528 Padding = "\n";
529}
530
532 if (Use) {
533 // If this tag is being written inside a sequence we should write the start
534 // of the sequence before writing the tag, otherwise the tag won't be
535 // attached to the element in the sequence, but rather the sequence itself.
536 bool SequenceElement = false;
537 if (StateStack.size() > 1) {
538 auto &E = StateStack[StateStack.size() - 2];
539 SequenceElement = inSeqAnyElement(E) || inFlowSeqAnyElement(E);
540 }
541 if (SequenceElement && StateStack.back() == inMapFirstKey) {
542 newLineCheck();
543 } else {
544 output(" ");
545 }
546 output(Tag);
547 if (SequenceElement) {
548 // If we're writing the tag during the first element of a map, the tag
549 // takes the place of the first element in the sequence.
550 if (StateStack.back() == inMapFirstKey) {
551 StateStack.pop_back();
552 StateStack.push_back(inMapOtherKey);
553 }
554 // Tags inside maps in sequences should act as keys in the map from a
555 // formatting perspective, so we always want a newline in a sequence.
556 Padding = "\n";
557 }
558 }
559 return Use;
560}
561
563 // If we did not map anything, we should explicitly emit an empty map
564 if (StateStack.back() == inMapFirstKey) {
565 Padding = PaddingBeforeContainer;
566 newLineCheck();
567 output("{}");
568 Padding = "\n";
569 }
570 StateStack.pop_back();
571}
572
573std::vector<StringRef> Output::keys() {
574 report_fatal_error("invalid call");
575}
576
577bool Output::preflightKey(StringRef Key, bool Required, bool SameAsDefault,
578 bool &UseDefault, void *&SaveInfo) {
579 UseDefault = false;
580 SaveInfo = nullptr;
581 if (Required || !SameAsDefault || WriteDefaultValues) {
582 auto State = StateStack.back();
583 if (State == inFlowMapFirstKey || State == inFlowMapOtherKey) {
584 flowKey(Key);
585 } else {
586 newLineCheck();
587 paddedKey(Key);
588 }
589 return true;
590 }
591 return false;
592}
593
595 if (StateStack.back() == inMapFirstKey) {
596 StateStack.pop_back();
597 StateStack.push_back(inMapOtherKey);
598 } else if (StateStack.back() == inFlowMapFirstKey) {
599 StateStack.pop_back();
600 StateStack.push_back(inFlowMapOtherKey);
601 }
602}
603
605 StateStack.push_back(inFlowMapFirstKey);
606 newLineCheck();
607 ColumnAtMapFlowStart = Column;
608 output("{ ");
609}
610
612 StateStack.pop_back();
613 outputUpToEndOfLine(" }");
614}
615
617 outputUpToEndOfLine("---");
618}
619
620bool Output::preflightDocument(unsigned index) {
621 if (index > 0)
622 outputUpToEndOfLine("\n---");
623 return true;
624}
625
628
630 output("\n...\n");
631}
632
634 StateStack.push_back(inSeqFirstElement);
635 PaddingBeforeContainer = Padding;
636 Padding = "\n";
637 return 0;
638}
639
641 // If we did not emit anything, we should explicitly emit an empty sequence
642 if (StateStack.back() == inSeqFirstElement) {
643 Padding = PaddingBeforeContainer;
644 newLineCheck(/*EmptySequence=*/true);
645 output("[]");
646 Padding = "\n";
647 }
648 StateStack.pop_back();
649}
650
651bool Output::preflightElement(unsigned, void *&SaveInfo) {
652 SaveInfo = nullptr;
653 return true;
654}
655
657 if (StateStack.back() == inSeqFirstElement) {
658 StateStack.pop_back();
659 StateStack.push_back(inSeqOtherElement);
660 } else if (StateStack.back() == inFlowSeqFirstElement) {
661 StateStack.pop_back();
662 StateStack.push_back(inFlowSeqOtherElement);
663 }
664}
665
667 StateStack.push_back(inFlowSeqFirstElement);
668 newLineCheck();
669 ColumnAtFlowStart = Column;
670 output("[ ");
671 NeedFlowSequenceComma = false;
672 return 0;
673}
674
676 StateStack.pop_back();
677 outputUpToEndOfLine(" ]");
678}
679
680bool Output::preflightFlowElement(unsigned, void *&SaveInfo) {
681 if (NeedFlowSequenceComma)
682 output(", ");
683 if (WrapColumn && Column > WrapColumn) {
684 output("\n");
685 for (int i = 0; i < ColumnAtFlowStart; ++i)
686 output(" ");
687 Column = ColumnAtFlowStart;
688 output(" ");
689 }
690 SaveInfo = nullptr;
691 return true;
692}
693
695 NeedFlowSequenceComma = true;
696}
697
699 EnumerationMatchFound = false;
700}
701
702bool Output::matchEnumScalar(StringRef Str, bool Match) {
703 if (Match && !EnumerationMatchFound) {
704 newLineCheck();
705 outputUpToEndOfLine(Str);
706 EnumerationMatchFound = true;
707 }
708 return false;
709}
710
712 if (EnumerationMatchFound)
713 return false;
714 EnumerationMatchFound = true;
715 return true;
716}
717
719 if (!EnumerationMatchFound)
720 llvm_unreachable("bad runtime enum value");
721}
722
723bool Output::beginBitSetScalar(bool &DoClear) {
724 newLineCheck();
725 output("[ ");
726 NeedBitValueComma = false;
727 DoClear = false;
728 return true;
729}
730
731bool Output::bitSetMatch(StringRef Str, bool Matches) {
732 if (Matches) {
733 if (NeedBitValueComma)
734 output(", ");
735 output(Str);
736 NeedBitValueComma = true;
737 }
738 return false;
739}
740
742 outputUpToEndOfLine(" ]");
743}
744
746 newLineCheck();
747 if (S.empty()) {
748 // Print '' for the empty string because leaving the field empty is not
749 // allowed.
750 outputUpToEndOfLine("''");
751 return;
752 }
753 output(S, MustQuote);
754 outputUpToEndOfLine("");
755}
756
757/// A literal block scalar has no escapes, so it can only hold printable
758/// characters, tab and line feed. That rules out C1 controls, and NEL, LS and
759/// PS, which YAML 1.1 readers take as line breaks. Invalid UTF-8 stays in the
760/// block, since yaml::escape would drop it. Readers take the indentation from
761/// the first non-empty line, so that line cannot start with a space.
763 if (S.ltrim('\n').starts_with(' '))
764 return false;
765 const UTF8 *Ptr = S.bytes_begin(), *End = S.bytes_end();
766 while (Ptr != End) {
767 if (isASCII(*Ptr)) {
768 if (!isPrint(*Ptr) && *Ptr != '\t' && *Ptr != '\n')
769 return false;
770 ++Ptr;
771 continue;
772 }
773 const UTF8 *Start = Ptr;
774 UTF32 CodePoint;
775 if (convertUTF8Sequence(&Ptr, End, &CodePoint, strictConversion) !=
776 conversionOK) {
777 Ptr = Start + 1;
778 continue;
779 }
780 if (!sys::unicode::isPrintable(CodePoint))
781 return false;
782 }
783 return true;
784}
785
787 // Fall back to a double-quoted scalar, which escapes everything. Input
788 // accepts either form for a block scalar value.
789 if (!canUseBlockScalar(S)) {
791 return;
792 }
793 if (!StateStack.empty())
794 newLineCheck();
795 output(" |");
796 // The default chomping keeps exactly one trailing line break, so strip or
797 // keep them explicitly to preserve the value.
798 if (!S.empty()) {
799 size_t LineBreaks = S.size() - S.rtrim('\n').size();
800 if (LineBreaks == 0)
801 output("-");
802 else if (LineBreaks > 1)
803 output("+");
804 }
805
806 unsigned Indent = StateStack.empty() ? 1 : StateStack.size();
807
808 auto Buffer = MemoryBuffer::getMemBuffer(S, "", false);
809 for (line_iterator Lines(*Buffer, false); !Lines.is_at_end(); ++Lines) {
810 outputNewLine();
811 for (unsigned I = 0; I < Indent; ++I) {
812 output(" ");
813 }
814 output(*Lines);
815 }
816 outputUpToEndOfLine("");
817}
818
819void Output::scalarTag(std::string &Tag) {
820 if (Tag.empty())
821 return;
822 newLineCheck();
823 output(Tag);
824 output(" ");
825}
826
827void Output::setError(const Twine &message) {
828}
829
830std::error_code Output::error() { return {}; }
831
833 // Normally, with an optional key/value where the value is an empty sequence,
834 // the whole key/value can be not written. But, that produces wrong yaml
835 // if the key/value is the only thing in the map and the map is used in
836 // a sequence. This detects if the this sequence is the first key/value
837 // in map that itself is embedded in a sequence.
838 if (StateStack.size() < 2)
839 return true;
840 if (StateStack.back() != inMapFirstKey)
841 return true;
842 return !inSeqAnyElement(StateStack[StateStack.size() - 2]);
843}
844
845void Output::output(StringRef s) {
846 Column += s.size();
847 Out << s;
848}
849
850void Output::output(StringRef S, QuotingType MustQuote) {
851 if (MustQuote == QuotingType::None) {
852 // Only quote if we must.
853 output(S);
854 return;
855 }
856
857 StringLiteral Quote = MustQuote == QuotingType::Single ? StringLiteral("'")
858 : StringLiteral("\"");
859 output(Quote); // Starting quote.
860
861 // When using double-quoted strings (and only in that case), non-printable
862 // characters may be present, and will be escaped using a variety of
863 // unicode-scalar and special short-form escapes. This is handled in
864 // yaml::escape.
865 if (MustQuote == QuotingType::Double) {
866 output(yaml::escape(S, /* EscapePrintable= */ false));
867 output(Quote);
868 return;
869 }
870
871 unsigned i = 0;
872 unsigned j = 0;
873 unsigned End = S.size();
874 const char *Base = S.data();
875
876 // When using single-quoted strings, any single quote ' must be doubled to be
877 // escaped.
878 while (j < End) {
879 if (S[j] == '\'') { // Escape quotes.
880 output(StringRef(&Base[i], j - i)); // "flush".
881 output(StringLiteral("''")); // Print it as ''
882 i = j + 1;
883 }
884 ++j;
885 }
886 output(StringRef(&Base[i], j - i));
887 output(Quote); // Ending quote.
888}
889
890void Output::outputUpToEndOfLine(StringRef s) {
891 output(s);
892 if (StateStack.empty() || (!inFlowSeqAnyElement(StateStack.back()) &&
893 !inFlowMapAnyKey(StateStack.back())))
894 Padding = "\n";
895}
896
897void Output::outputNewLine() {
898 Out << "\n";
899 Column = 0;
900}
901
902// if seq at top, indent as if map, then add "- "
903// if seq in middle, use "- " if firstKey, else use " "
904//
905
906void Output::newLineCheck(bool EmptySequence) {
907 if (Padding != "\n") {
908 output(Padding);
909 Padding = {};
910 return;
911 }
912 outputNewLine();
913 Padding = {};
914
915 if (StateStack.size() == 0 || EmptySequence)
916 return;
917
918 unsigned Indent = StateStack.size() - 1;
919 bool PossiblyNestedSeq = false;
920 auto I = StateStack.rbegin(), E = StateStack.rend();
921
922 if (inSeqAnyElement(*I)) {
923 PossiblyNestedSeq = true; // Not possibly but always.
924 ++Indent;
925 } else if (*I == inMapFirstKey || *I == inFlowMapFirstKey ||
926 inFlowSeqAnyElement(*I)) {
927 PossiblyNestedSeq = true;
928 ++I; // Skip back().
929 }
930
931 unsigned OutputDashCount = 0;
932 if (PossiblyNestedSeq) {
933 // Count up consecutive inSeqFirstElement from the end, unless
934 // inSeqFirstElement is the top of nested sequence.
935 while (I != E) {
936 // Don't count the top of nested sequence.
937 if (!inSeqAnyElement(*I))
938 break;
939
940 ++OutputDashCount;
941
942 // Stop counting if consecutive inSeqFirstElement ends.
943 if (*I++ != inSeqFirstElement)
944 break;
945 }
946 }
947
948 for (unsigned I = OutputDashCount; I < Indent; ++I)
949 output(" ");
950
951 for (unsigned I = 0; I < OutputDashCount; ++I)
952 output("- ");
953}
954
955void Output::paddedKey(StringRef key) {
956 output(key, needsQuotes(key, false));
957 output(":");
958 const char *spaces = " ";
959 if (key.size() < strlen(spaces))
960 Padding = &spaces[key.size()];
961 else
962 Padding = " ";
963}
964
965void Output::flowKey(StringRef Key) {
966 if (StateStack.back() == inFlowMapOtherKey)
967 output(", ");
968 if (WrapColumn && Column > WrapColumn) {
969 output("\n");
970 for (int I = 0; I < ColumnAtMapFlowStart; ++I)
971 output(" ");
972 Column = ColumnAtMapFlowStart;
973 output(" ");
974 }
975 output(Key, needsQuotes(Key, false));
976 output(": ");
977}
978
980
981bool Output::inSeqAnyElement(InState State) {
982 return State == inSeqFirstElement || State == inSeqOtherElement;
983}
984
985bool Output::inFlowSeqAnyElement(InState State) {
986 return State == inFlowSeqFirstElement || State == inFlowSeqOtherElement;
987}
988
989bool Output::inMapAnyKey(InState State) {
990 return State == inMapFirstKey || State == inMapOtherKey;
991}
992
993bool Output::inFlowMapAnyKey(InState State) {
994 return State == inFlowMapFirstKey || State == inFlowMapOtherKey;
995}
996
997//===----------------------------------------------------------------------===//
998// traits for built-in types
999//===----------------------------------------------------------------------===//
1000
1001void ScalarTraits<bool>::output(const bool &Val, void *, raw_ostream &Out) {
1002 Out << (Val ? "true" : "false");
1003}
1004
1005StringRef ScalarTraits<bool>::input(StringRef Scalar, void *, bool &Val) {
1006 if (std::optional<bool> Parsed = parseBool(Scalar)) {
1007 Val = *Parsed;
1008 return StringRef();
1009 }
1010 return "invalid boolean";
1011}
1012
1013void ScalarTraits<StringRef>::output(const StringRef &Val, void *,
1014 raw_ostream &Out) {
1015 Out << Val;
1016}
1017
1018StringRef ScalarTraits<StringRef>::input(StringRef Scalar, void *,
1019 StringRef &Val) {
1020 Val = Scalar;
1021 return StringRef();
1022}
1023
1024void ScalarTraits<std::string>::output(const std::string &Val, void *,
1025 raw_ostream &Out) {
1026 Out << Val;
1027}
1028
1029StringRef ScalarTraits<std::string>::input(StringRef Scalar, void *,
1030 std::string &Val) {
1031 Val = Scalar.str();
1032 return StringRef();
1033}
1034
1035void ScalarTraits<uint8_t>::output(const uint8_t &Val, void *,
1036 raw_ostream &Out) {
1037 // use temp uin32_t because ostream thinks uint8_t is a character
1038 uint32_t Num = Val;
1039 Out << Num;
1040}
1041
1042StringRef ScalarTraits<uint8_t>::input(StringRef Scalar, void *, uint8_t &Val) {
1043 unsigned long long n;
1044 if (getAsUnsignedInteger(Scalar, 0, n))
1045 return "invalid number";
1046 if (n > 0xFF)
1047 return "out of range number";
1048 Val = n;
1049 return StringRef();
1050}
1051
1052void ScalarTraits<uint16_t>::output(const uint16_t &Val, void *,
1053 raw_ostream &Out) {
1054 Out << Val;
1055}
1056
1057StringRef ScalarTraits<uint16_t>::input(StringRef Scalar, void *,
1058 uint16_t &Val) {
1059 unsigned long long n;
1060 if (getAsUnsignedInteger(Scalar, 0, n))
1061 return "invalid number";
1062 if (n > 0xFFFF)
1063 return "out of range number";
1064 Val = n;
1065 return StringRef();
1066}
1067
1068void ScalarTraits<uint32_t>::output(const uint32_t &Val, void *,
1069 raw_ostream &Out) {
1070 Out << Val;
1071}
1072
1073StringRef ScalarTraits<uint32_t>::input(StringRef Scalar, void *,
1074 uint32_t &Val) {
1075 unsigned long long n;
1076 if (getAsUnsignedInteger(Scalar, 0, n))
1077 return "invalid number";
1078 if (n > 0xFFFFFFFFUL)
1079 return "out of range number";
1080 Val = n;
1081 return StringRef();
1082}
1083
1084void ScalarTraits<uint64_t>::output(const uint64_t &Val, void *,
1085 raw_ostream &Out) {
1086 Out << Val;
1087}
1088
1089StringRef ScalarTraits<uint64_t>::input(StringRef Scalar, void *,
1090 uint64_t &Val) {
1091 unsigned long long N;
1092 if (getAsUnsignedInteger(Scalar, 0, N))
1093 return "invalid number";
1094 Val = N;
1095 return StringRef();
1096}
1097
1098void ScalarTraits<int8_t>::output(const int8_t &Val, void *, raw_ostream &Out) {
1099 // use temp in32_t because ostream thinks int8_t is a character
1100 int32_t Num = Val;
1101 Out << Num;
1102}
1103
1104StringRef ScalarTraits<int8_t>::input(StringRef Scalar, void *, int8_t &Val) {
1105 long long N;
1106 if (getAsSignedInteger(Scalar, 0, N))
1107 return "invalid number";
1108 if ((N > 127) || (N < -128))
1109 return "out of range number";
1110 Val = N;
1111 return StringRef();
1112}
1113
1114void ScalarTraits<int16_t>::output(const int16_t &Val, void *,
1115 raw_ostream &Out) {
1116 Out << Val;
1117}
1118
1119StringRef ScalarTraits<int16_t>::input(StringRef Scalar, void *, int16_t &Val) {
1120 long long N;
1121 if (getAsSignedInteger(Scalar, 0, N))
1122 return "invalid number";
1123 if ((N > INT16_MAX) || (N < INT16_MIN))
1124 return "out of range number";
1125 Val = N;
1126 return StringRef();
1127}
1128
1129void ScalarTraits<int32_t>::output(const int32_t &Val, void *,
1130 raw_ostream &Out) {
1131 Out << Val;
1132}
1133
1134StringRef ScalarTraits<int32_t>::input(StringRef Scalar, void *, int32_t &Val) {
1135 long long N;
1136 if (getAsSignedInteger(Scalar, 0, N))
1137 return "invalid number";
1138 if ((N > INT32_MAX) || (N < INT32_MIN))
1139 return "out of range number";
1140 Val = N;
1141 return StringRef();
1142}
1143
1144void ScalarTraits<int64_t>::output(const int64_t &Val, void *,
1145 raw_ostream &Out) {
1146 Out << Val;
1147}
1148
1149StringRef ScalarTraits<int64_t>::input(StringRef Scalar, void *, int64_t &Val) {
1150 long long N;
1151 if (getAsSignedInteger(Scalar, 0, N))
1152 return "invalid number";
1153 Val = N;
1154 return StringRef();
1155}
1156
1157void ScalarTraits<double>::output(const double &Val, void *, raw_ostream &Out) {
1158 Out << format("%g", Val);
1159}
1160
1161StringRef ScalarTraits<double>::input(StringRef Scalar, void *, double &Val) {
1162 if (to_float(Scalar, Val))
1163 return StringRef();
1164 return "invalid floating point number";
1165}
1166
1167void ScalarTraits<float>::output(const float &Val, void *, raw_ostream &Out) {
1168 Out << format("%g", Val);
1169}
1170
1171StringRef ScalarTraits<float>::input(StringRef Scalar, void *, float &Val) {
1172 if (to_float(Scalar, Val))
1173 return StringRef();
1174 return "invalid floating point number";
1175}
1176
1177void ScalarTraits<Hex8>::output(const Hex8 &Val, void *, raw_ostream &Out) {
1178 Out << format("0x%" PRIX8, (uint8_t)Val);
1179}
1180
1181StringRef ScalarTraits<Hex8>::input(StringRef Scalar, void *, Hex8 &Val) {
1182 unsigned long long n;
1183 if (getAsUnsignedInteger(Scalar, 0, n))
1184 return "invalid hex8 number";
1185 if (n > 0xFF)
1186 return "out of range hex8 number";
1187 Val = n;
1188 return StringRef();
1189}
1190
1191void ScalarTraits<Hex16>::output(const Hex16 &Val, void *, raw_ostream &Out) {
1192 Out << format("0x%" PRIX16, (uint16_t)Val);
1193}
1194
1195StringRef ScalarTraits<Hex16>::input(StringRef Scalar, void *, Hex16 &Val) {
1196 unsigned long long n;
1197 if (getAsUnsignedInteger(Scalar, 0, n))
1198 return "invalid hex16 number";
1199 if (n > 0xFFFF)
1200 return "out of range hex16 number";
1201 Val = n;
1202 return StringRef();
1203}
1204
1205void ScalarTraits<Hex32>::output(const Hex32 &Val, void *, raw_ostream &Out) {
1206 Out << format("0x%" PRIX32, (uint32_t)Val);
1207}
1208
1209StringRef ScalarTraits<Hex32>::input(StringRef Scalar, void *, Hex32 &Val) {
1210 unsigned long long n;
1211 if (getAsUnsignedInteger(Scalar, 0, n))
1212 return "invalid hex32 number";
1213 if (n > 0xFFFFFFFFUL)
1214 return "out of range hex32 number";
1215 Val = n;
1216 return StringRef();
1217}
1218
1219void ScalarTraits<Hex64>::output(const Hex64 &Val, void *, raw_ostream &Out) {
1220 Out << format("0x%" PRIX64, (uint64_t)Val);
1221}
1222
1223StringRef ScalarTraits<Hex64>::input(StringRef Scalar, void *, Hex64 &Val) {
1224 unsigned long long Num;
1225 if (getAsUnsignedInteger(Scalar, 0, Num))
1226 return "invalid hex64 number";
1227 Val = Num;
1228 return StringRef();
1229}
1230
1231void ScalarTraits<VersionTuple>::output(const VersionTuple &Val, void *,
1232 llvm::raw_ostream &Out) {
1233 Out << Val.getAsString();
1234}
1235
1236StringRef ScalarTraits<VersionTuple>::input(StringRef Scalar, void *,
1237 VersionTuple &Val) {
1238 if (Val.tryParse(Scalar))
1239 return "invalid version format";
1240 return StringRef();
1241}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
uint64_t uint64_t
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
Infer address spaces
#define I(x, y, z)
Definition MD5.cpp:57
#define P(N)
This file contains some templates that are useful if you are working with the STL at all.
This file defines the SmallString class.
This file contains some functions that are useful when dealing with strings.
static void DiagHandler(const SMDiagnostic &Diag, void *Context)
Defines the llvm::VersionTuple class, which represents a version in the form major[....
static bool canUseBlockScalar(StringRef S)
A literal block scalar has no escapes, so it can only hold printable characters, tab and line feed.
static std::unique_ptr< MemoryBuffer > getMemBuffer(StringRef InputData, StringRef BufferName="", bool RequiresNullTerminator=true)
Open the specified memory range as a MemoryBuffer.
StringRef str() const
Explicit conversion to StringRef.
void(*)(const SMDiagnostic &, void *Context) DiagHandlerTy
Clients that want to handle their own diagnostics in a custom way can register a function pointer+con...
Definition SourceMgr.h:46
A wrapper around a string literal that serves as a proxy for constructing global tables of StringRefs...
Definition StringRef.h:888
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
const unsigned char * bytes_end() const
Definition StringRef.h:125
bool starts_with(StringRef Prefix) const
Check if this string starts with the given Prefix.
Definition StringRef.h:258
constexpr bool empty() const
Check if the string is empty.
Definition StringRef.h:141
constexpr size_t size() const
Get the string size.
Definition StringRef.h:144
constexpr const char * data() const
Get a pointer to the start of the string (which may not be null terminated).
Definition StringRef.h:138
StringRef ltrim(char Char) const
Return string with consecutive Char characters starting from the the left removed.
Definition StringRef.h:826
StringRef rtrim(char Char) const
Return string with consecutive Char characters starting from the right removed.
Definition StringRef.h:838
size_t find(char C, size_t From=0) const
Search for the first character C in the string.
Definition StringRef.h:290
StringRef copy(Allocator &A) const
Definition StringRef.h:160
const unsigned char * bytes_begin() const
Definition StringRef.h:122
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition Twine.h:82
A Use represents the edge between a Value definition and its users.
Definition Use.h:35
LLVM_ABI bool tryParse(StringRef string)
Try to parse the given string as a version number.
LLVM_ABI std::string getAsString() const
Retrieve a string representation of the version number.
A forward iterator which reads text lines from a buffer.
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition raw_ostream.h:53
StringRef getName() const
Definition YAMLParser.h:528
StringRef getValue() const
Gets the value of this node as a StringRef.
Definition YAMLParser.h:275
virtual bool canElideEmptySequence()=0
virtual NodeKind getNodeKind()=0
void setContext(void *)
virtual void endSequence()=0
virtual void endEnumScalar()=0
virtual bool outputting() const =0
virtual unsigned beginFlowSequence()=0
virtual ~IO()
virtual void endFlowSequence()=0
virtual void beginMapping()=0
virtual void setAllowUnknownKeys(bool Allow)
virtual void endMapping()=0
virtual unsigned beginSequence()=0
virtual void beginEnumScalar()=0
void * getContext() const
virtual void endFlowMapping()=0
virtual void beginFlowMapping()=0
virtual bool matchEnumFallback()=0
virtual void endBitSetScalar()=0
virtual std::vector< StringRef > keys()=0
IO(void *Ctxt=nullptr)
void setAllowUnknownKeys(bool Allow) override
~Input() override
Input(StringRef InputContent, void *Ctxt=nullptr, SourceMgr::DiagHandlerTy DiagHandler=nullptr, void *DiagHandlerCtxt=nullptr)
std::error_code error() override
bool setCurrentDocument()
const Node * getCurrentNode() const
Returns the current node that's being parsed by the YAML Parser.
Abstract base class for all Nodes.
Definition YAMLParser.h:121
std::string getVerbatimTag() const
Get the verbatium tag for a given Node.
unsigned beginFlowSequence() override
std::vector< StringRef > keys() override
Output(raw_ostream &, void *Ctxt=nullptr, int WrapColumn=70)
void setError(const Twine &message) override
void scalarString(StringRef &, QuotingType) override
void endBitSetScalar() override
void beginFlowMapping() override
void endFlowMapping() override
void endFlowSequence() override
void postflightElement(void *) override
void endEnumScalar() override
void blockScalarString(StringRef &) override
bool preflightDocument(unsigned)
bool bitSetMatch(StringRef, bool) override
bool canElideEmptySequence() override
void beginMapping() override
void postflightFlowElement(void *) override
void scalarTag(std::string &) override
bool beginBitSetScalar(bool &) override
bool mapTag(StringRef, bool) override
~Output() override
bool preflightElement(unsigned, void *&) override
bool matchEnumFallback() override
void beginEnumScalar() override
bool preflightKey(StringRef Key, bool, bool, bool &, void *&) override
void endSequence() override
bool matchEnumScalar(StringRef, bool) override
bool outputting() const override
unsigned beginSequence() override
NodeKind getNodeKind() override
void endMapping() override
std::error_code error() override
void postflightKey(void *) override
bool preflightFlowElement(unsigned, void *&) override
StringRef getValue(SmallVectorImpl< char > &Storage) const
Gets the value of this node as a StringRef.
This class represents a YAML stream potentially containing multiple documents.
Definition YAMLParser.h:88
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ Entry
Definition COFF.h:862
NodeAddr< NodeBase * > Node
Definition RDFGraph.h:381
LLVM_ABI bool isPrintable(int UCS)
Determines if a character is likely to be displayed correctly on the terminal.
Definition Unicode.cpp:43
QuotingType
Describe which type of quotes should be used when quoting is necessary.
Definition YAMLTraits.h:132
LLVM_ABI std::optional< bool > parseBool(StringRef S)
Parse S as a bool according to https://yaml.org/type/bool.html.
QuotingType needsQuotes(StringRef S, bool ForcePreserveAsString=true)
Definition YAMLTraits.h:590
bool isNull(StringRef S)
Definition YAMLTraits.h:571
LLVM_ABI std::string escape(StringRef Input, bool EscapePrintable=true)
Escape Input for a double quoted scalar; if EscapePrintable is true, all UTF8 sequences will be escap...
This is an optimization pass for GlobalISel generic memory operations.
unsigned char UTF8
Definition ConvertUTF.h:131
LLVM_ABI bool getAsSignedInteger(StringRef Str, unsigned Radix, long long &Result)
std::error_code make_error_code(BitcodeError E)
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
auto dyn_cast_if_present(const Y &Val)
dyn_cast_if_present<X> - Functionally identical to dyn_cast, except that a null (or none in the case ...
Definition Casting.h:732
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
Definition InstrProf.h:143
bool to_float(const Twine &T, float &Num)
ConversionResult convertUTF8Sequence(const UTF8 **source, const UTF8 *sourceEnd, UTF32 *target, ConversionFlags flags)
Convert the first UTF8 sequence in the given source buffer to a UTF32 code point.
Definition ConvertUTF.h:285
@ invalid_argument
Definition Errc.h:56
unsigned int UTF32
Definition ConvertUTF.h:129
@ strictConversion
Definition ConvertUTF.h:156
@ conversionOK
Definition ConvertUTF.h:150
auto dyn_cast_or_null(const Y &Val)
Definition Casting.h:753
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
Definition Error.cpp:163
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
Definition Casting.h:547
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
Definition Format.h:102
LLVM_ATTRIBUTE_VISIBILITY_DEFAULT AnalysisKey InnerAnalysisManagerProxy< AnalysisManagerT, IRUnitT, ExtraArgTs... >::Key
bool isASCII(char C)
Checks whether character C is valid ASCII (high bit is zero).
bool isPrint(char C)
Checks whether character C is printable.
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Definition STLExtras.h:1963
LLVM_ABI bool getAsUnsignedInteger(StringRef Str, unsigned Radix, unsigned long long &Result)
Helper functions for StringRef::getAsInteger.
@ End
Run the machine verifier once, at the end of the pipeline.
Definition CodeGen.h:320
#define N
This class should be specialized by type that requires custom conversion to/from a yaml scalar.
Definition YAMLTraits.h:150