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