1249259Sdim//===- lib/Support/YAMLTraits.cpp -----------------------------------------===// 2249259Sdim// 3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353358Sdim// See https://llvm.org/LICENSE.txt for license information. 5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6249259Sdim// 7249259Sdim//===----------------------------------------------------------------------===// 8249259Sdim 9288943Sdim#include "llvm/Support/YAMLTraits.h" 10321369Sdim#include "llvm/ADT/STLExtras.h" 11288943Sdim#include "llvm/ADT/SmallString.h" 12321369Sdim#include "llvm/ADT/StringExtras.h" 13321369Sdim#include "llvm/ADT/StringRef.h" 14249259Sdim#include "llvm/ADT/Twine.h" 15249259Sdim#include "llvm/Support/Casting.h" 16288943Sdim#include "llvm/Support/Errc.h" 17249259Sdim#include "llvm/Support/ErrorHandling.h" 18249259Sdim#include "llvm/Support/Format.h" 19288943Sdim#include "llvm/Support/LineIterator.h" 20321369Sdim#include "llvm/Support/MemoryBuffer.h" 21327952Sdim#include "llvm/Support/Unicode.h" 22249259Sdim#include "llvm/Support/YAMLParser.h" 23249259Sdim#include "llvm/Support/raw_ostream.h" 24321369Sdim#include <algorithm> 25321369Sdim#include <cassert> 26321369Sdim#include <cstdint> 27321369Sdim#include <cstdlib> 28249259Sdim#include <cstring> 29321369Sdim#include <string> 30321369Sdim#include <vector> 31321369Sdim 32249259Sdimusing namespace llvm; 33249259Sdimusing namespace yaml; 34249259Sdim 35249259Sdim//===----------------------------------------------------------------------===// 36249259Sdim// IO 37249259Sdim//===----------------------------------------------------------------------===// 38249259Sdim 39321369SdimIO::IO(void *Context) : Ctxt(Context) {} 40249259Sdim 41321369SdimIO::~IO() = default; 42249259Sdim 43360784Sdimvoid *IO::getContext() const { 44249259Sdim return Ctxt; 45249259Sdim} 46249259Sdim 47249259Sdimvoid IO::setContext(void *Context) { 48249259Sdim Ctxt = Context; 49249259Sdim} 50249259Sdim 51249259Sdim//===----------------------------------------------------------------------===// 52249259Sdim// Input 53249259Sdim//===----------------------------------------------------------------------===// 54249259Sdim 55314564SdimInput::Input(StringRef InputContent, void *Ctxt, 56314564Sdim SourceMgr::DiagHandlerTy DiagHandler, void *DiagHandlerCtxt) 57321369Sdim : IO(Ctxt), Strm(new Stream(InputContent, SrcMgr, false, &EC)) { 58261991Sdim if (DiagHandler) 59261991Sdim SrcMgr.setDiagHandler(DiagHandler, DiagHandlerCtxt); 60249259Sdim DocIterator = Strm->begin(); 61249259Sdim} 62249259Sdim 63321369SdimInput::Input(MemoryBufferRef Input, void *Ctxt, 64321369Sdim SourceMgr::DiagHandlerTy DiagHandler, void *DiagHandlerCtxt) 65321369Sdim : IO(Ctxt), Strm(new Stream(Input, SrcMgr, false, &EC)) { 66321369Sdim if (DiagHandler) 67321369Sdim SrcMgr.setDiagHandler(DiagHandler, DiagHandlerCtxt); 68321369Sdim DocIterator = Strm->begin(); 69249259Sdim} 70249259Sdim 71321369SdimInput::~Input() = default; 72321369Sdim 73276479Sdimstd::error_code Input::error() { return EC; } 74249259Sdim 75261991Sdim// Pin the vtables to this file. 76261991Sdimvoid Input::HNode::anchor() {} 77261991Sdimvoid Input::EmptyHNode::anchor() {} 78261991Sdimvoid Input::ScalarHNode::anchor() {} 79280031Sdimvoid Input::MapHNode::anchor() {} 80280031Sdimvoid Input::SequenceHNode::anchor() {} 81249259Sdim 82360784Sdimbool Input::outputting() const { 83249259Sdim return false; 84249259Sdim} 85249259Sdim 86249259Sdimbool Input::setCurrentDocument() { 87249259Sdim if (DocIterator != Strm->end()) { 88249259Sdim Node *N = DocIterator->getRoot(); 89261991Sdim if (!N) { 90261991Sdim EC = make_error_code(errc::invalid_argument); 91261991Sdim return false; 92261991Sdim } 93261991Sdim 94249259Sdim if (isa<NullNode>(N)) { 95249259Sdim // Empty files are allowed and ignored 96249259Sdim ++DocIterator; 97249259Sdim return setCurrentDocument(); 98249259Sdim } 99344779Sdim TopNode = createHNodes(N); 100249259Sdim CurrentNode = TopNode.get(); 101249259Sdim return true; 102249259Sdim } 103249259Sdim return false; 104249259Sdim} 105249259Sdim 106276479Sdimbool Input::nextDocument() { 107276479Sdim return ++DocIterator != Strm->end(); 108249259Sdim} 109249259Sdim 110288943Sdimconst Node *Input::getCurrentNode() const { 111288943Sdim return CurrentNode ? CurrentNode->_node : nullptr; 112288943Sdim} 113288943Sdim 114261991Sdimbool Input::mapTag(StringRef Tag, bool Default) { 115353358Sdim // CurrentNode can be null if setCurrentDocument() was unable to 116353358Sdim // parse the document because it was invalid or empty. 117353358Sdim if (!CurrentNode) 118353358Sdim return false; 119353358Sdim 120261991Sdim std::string foundTag = CurrentNode->_node->getVerbatimTag(); 121261991Sdim if (foundTag.empty()) { 122261991Sdim // If no tag found and 'Tag' is the default, say it was found. 123261991Sdim return Default; 124261991Sdim } 125261991Sdim // Return true iff found tag matches supplied tag. 126261991Sdim return Tag.equals(foundTag); 127261991Sdim} 128261991Sdim 129249259Sdimvoid Input::beginMapping() { 130249259Sdim if (EC) 131249259Sdim return; 132261991Sdim // CurrentNode can be null if the document is empty. 133261991Sdim MapHNode *MN = dyn_cast_or_null<MapHNode>(CurrentNode); 134249259Sdim if (MN) { 135249259Sdim MN->ValidKeys.clear(); 136249259Sdim } 137249259Sdim} 138249259Sdim 139314564Sdimstd::vector<StringRef> Input::keys() { 140314564Sdim MapHNode *MN = dyn_cast<MapHNode>(CurrentNode); 141314564Sdim std::vector<StringRef> Ret; 142314564Sdim if (!MN) { 143314564Sdim setError(CurrentNode, "not a mapping"); 144314564Sdim return Ret; 145314564Sdim } 146314564Sdim for (auto &P : MN->Mapping) 147314564Sdim Ret.push_back(P.first()); 148314564Sdim return Ret; 149314564Sdim} 150314564Sdim 151249259Sdimbool Input::preflightKey(const char *Key, bool Required, bool, bool &UseDefault, 152249259Sdim void *&SaveInfo) { 153249259Sdim UseDefault = false; 154249259Sdim if (EC) 155249259Sdim return false; 156261991Sdim 157261991Sdim // CurrentNode is null for empty documents, which is an error in case required 158261991Sdim // nodes are present. 159261991Sdim if (!CurrentNode) { 160261991Sdim if (Required) 161261991Sdim EC = make_error_code(errc::invalid_argument); 162261991Sdim return false; 163261991Sdim } 164261991Sdim 165249259Sdim MapHNode *MN = dyn_cast<MapHNode>(CurrentNode); 166249259Sdim if (!MN) { 167327952Sdim if (Required || !isa<EmptyHNode>(CurrentNode)) 168327952Sdim setError(CurrentNode, "not a mapping"); 169249259Sdim return false; 170249259Sdim } 171249259Sdim MN->ValidKeys.push_back(Key); 172280031Sdim HNode *Value = MN->Mapping[Key].get(); 173249259Sdim if (!Value) { 174249259Sdim if (Required) 175249259Sdim setError(CurrentNode, Twine("missing required key '") + Key + "'"); 176249259Sdim else 177249259Sdim UseDefault = true; 178249259Sdim return false; 179249259Sdim } 180249259Sdim SaveInfo = CurrentNode; 181249259Sdim CurrentNode = Value; 182249259Sdim return true; 183249259Sdim} 184249259Sdim 185249259Sdimvoid Input::postflightKey(void *saveInfo) { 186249259Sdim CurrentNode = reinterpret_cast<HNode *>(saveInfo); 187249259Sdim} 188249259Sdim 189249259Sdimvoid Input::endMapping() { 190249259Sdim if (EC) 191249259Sdim return; 192261991Sdim // CurrentNode can be null if the document is empty. 193261991Sdim MapHNode *MN = dyn_cast_or_null<MapHNode>(CurrentNode); 194249259Sdim if (!MN) 195249259Sdim return; 196276479Sdim for (const auto &NN : MN->Mapping) { 197314564Sdim if (!is_contained(MN->ValidKeys, NN.first())) { 198280031Sdim setError(NN.second.get(), Twine("unknown key '") + NN.first() + "'"); 199249259Sdim break; 200249259Sdim } 201249259Sdim } 202249259Sdim} 203249259Sdim 204288943Sdimvoid Input::beginFlowMapping() { beginMapping(); } 205288943Sdim 206288943Sdimvoid Input::endFlowMapping() { endMapping(); } 207288943Sdim 208249259Sdimunsigned Input::beginSequence() { 209288943Sdim if (SequenceHNode *SQ = dyn_cast<SequenceHNode>(CurrentNode)) 210249259Sdim return SQ->Entries.size(); 211288943Sdim if (isa<EmptyHNode>(CurrentNode)) 212288943Sdim return 0; 213288943Sdim // Treat case where there's a scalar "null" value as an empty sequence. 214288943Sdim if (ScalarHNode *SN = dyn_cast<ScalarHNode>(CurrentNode)) { 215288943Sdim if (isNull(SN->value())) 216288943Sdim return 0; 217249259Sdim } 218288943Sdim // Any other type of HNode is an error. 219288943Sdim setError(CurrentNode, "not a sequence"); 220249259Sdim return 0; 221249259Sdim} 222249259Sdim 223249259Sdimvoid Input::endSequence() { 224249259Sdim} 225249259Sdim 226249259Sdimbool Input::preflightElement(unsigned Index, void *&SaveInfo) { 227249259Sdim if (EC) 228249259Sdim return false; 229249259Sdim if (SequenceHNode *SQ = dyn_cast<SequenceHNode>(CurrentNode)) { 230249259Sdim SaveInfo = CurrentNode; 231280031Sdim CurrentNode = SQ->Entries[Index].get(); 232249259Sdim return true; 233249259Sdim } 234249259Sdim return false; 235249259Sdim} 236249259Sdim 237249259Sdimvoid Input::postflightElement(void *SaveInfo) { 238249259Sdim CurrentNode = reinterpret_cast<HNode *>(SaveInfo); 239249259Sdim} 240249259Sdim 241288943Sdimunsigned Input::beginFlowSequence() { return beginSequence(); } 242249259Sdim 243249259Sdimbool Input::preflightFlowElement(unsigned index, void *&SaveInfo) { 244249259Sdim if (EC) 245249259Sdim return false; 246249259Sdim if (SequenceHNode *SQ = dyn_cast<SequenceHNode>(CurrentNode)) { 247249259Sdim SaveInfo = CurrentNode; 248280031Sdim CurrentNode = SQ->Entries[index].get(); 249249259Sdim return true; 250249259Sdim } 251249259Sdim return false; 252249259Sdim} 253249259Sdim 254249259Sdimvoid Input::postflightFlowElement(void *SaveInfo) { 255249259Sdim CurrentNode = reinterpret_cast<HNode *>(SaveInfo); 256249259Sdim} 257249259Sdim 258249259Sdimvoid Input::endFlowSequence() { 259249259Sdim} 260249259Sdim 261249259Sdimvoid Input::beginEnumScalar() { 262249259Sdim ScalarMatchFound = false; 263249259Sdim} 264249259Sdim 265249259Sdimbool Input::matchEnumScalar(const char *Str, bool) { 266249259Sdim if (ScalarMatchFound) 267249259Sdim return false; 268249259Sdim if (ScalarHNode *SN = dyn_cast<ScalarHNode>(CurrentNode)) { 269249259Sdim if (SN->value().equals(Str)) { 270249259Sdim ScalarMatchFound = true; 271249259Sdim return true; 272249259Sdim } 273249259Sdim } 274249259Sdim return false; 275249259Sdim} 276249259Sdim 277288943Sdimbool Input::matchEnumFallback() { 278288943Sdim if (ScalarMatchFound) 279288943Sdim return false; 280288943Sdim ScalarMatchFound = true; 281288943Sdim return true; 282288943Sdim} 283288943Sdim 284249259Sdimvoid Input::endEnumScalar() { 285249259Sdim if (!ScalarMatchFound) { 286249259Sdim setError(CurrentNode, "unknown enumerated scalar"); 287249259Sdim } 288249259Sdim} 289249259Sdim 290249259Sdimbool Input::beginBitSetScalar(bool &DoClear) { 291249259Sdim BitValuesUsed.clear(); 292249259Sdim if (SequenceHNode *SQ = dyn_cast<SequenceHNode>(CurrentNode)) { 293249259Sdim BitValuesUsed.insert(BitValuesUsed.begin(), SQ->Entries.size(), false); 294249259Sdim } else { 295249259Sdim setError(CurrentNode, "expected sequence of bit values"); 296249259Sdim } 297249259Sdim DoClear = true; 298249259Sdim return true; 299249259Sdim} 300249259Sdim 301249259Sdimbool Input::bitSetMatch(const char *Str, bool) { 302249259Sdim if (EC) 303249259Sdim return false; 304249259Sdim if (SequenceHNode *SQ = dyn_cast<SequenceHNode>(CurrentNode)) { 305249259Sdim unsigned Index = 0; 306280031Sdim for (auto &N : SQ->Entries) { 307280031Sdim if (ScalarHNode *SN = dyn_cast<ScalarHNode>(N.get())) { 308249259Sdim if (SN->value().equals(Str)) { 309249259Sdim BitValuesUsed[Index] = true; 310249259Sdim return true; 311249259Sdim } 312249259Sdim } else { 313249259Sdim setError(CurrentNode, "unexpected scalar in sequence of bit values"); 314249259Sdim } 315249259Sdim ++Index; 316249259Sdim } 317249259Sdim } else { 318249259Sdim setError(CurrentNode, "expected sequence of bit values"); 319249259Sdim } 320249259Sdim return false; 321249259Sdim} 322249259Sdim 323249259Sdimvoid Input::endBitSetScalar() { 324249259Sdim if (EC) 325249259Sdim return; 326249259Sdim if (SequenceHNode *SQ = dyn_cast<SequenceHNode>(CurrentNode)) { 327249259Sdim assert(BitValuesUsed.size() == SQ->Entries.size()); 328249259Sdim for (unsigned i = 0; i < SQ->Entries.size(); ++i) { 329249259Sdim if (!BitValuesUsed[i]) { 330280031Sdim setError(SQ->Entries[i].get(), "unknown bit value"); 331249259Sdim return; 332249259Sdim } 333249259Sdim } 334249259Sdim } 335249259Sdim} 336249259Sdim 337327952Sdimvoid Input::scalarString(StringRef &S, QuotingType) { 338249259Sdim if (ScalarHNode *SN = dyn_cast<ScalarHNode>(CurrentNode)) { 339249259Sdim S = SN->value(); 340249259Sdim } else { 341249259Sdim setError(CurrentNode, "unexpected scalar"); 342249259Sdim } 343249259Sdim} 344249259Sdim 345327952Sdimvoid Input::blockScalarString(StringRef &S) { scalarString(S, QuotingType::None); } 346288943Sdim 347344779Sdimvoid Input::scalarTag(std::string &Tag) { 348344779Sdim Tag = CurrentNode->_node->getVerbatimTag(); 349344779Sdim} 350344779Sdim 351249259Sdimvoid Input::setError(HNode *hnode, const Twine &message) { 352261991Sdim assert(hnode && "HNode must not be NULL"); 353344779Sdim setError(hnode->_node, message); 354249259Sdim} 355249259Sdim 356344779SdimNodeKind Input::getNodeKind() { 357344779Sdim if (isa<ScalarHNode>(CurrentNode)) 358344779Sdim return NodeKind::Scalar; 359344779Sdim else if (isa<MapHNode>(CurrentNode)) 360344779Sdim return NodeKind::Map; 361344779Sdim else if (isa<SequenceHNode>(CurrentNode)) 362344779Sdim return NodeKind::Sequence; 363344779Sdim llvm_unreachable("Unsupported node kind"); 364344779Sdim} 365344779Sdim 366249259Sdimvoid Input::setError(Node *node, const Twine &message) { 367249259Sdim Strm->printError(node, message); 368249259Sdim EC = make_error_code(errc::invalid_argument); 369249259Sdim} 370249259Sdim 371280031Sdimstd::unique_ptr<Input::HNode> Input::createHNodes(Node *N) { 372249259Sdim SmallString<128> StringStorage; 373249259Sdim if (ScalarNode *SN = dyn_cast<ScalarNode>(N)) { 374249259Sdim StringRef KeyStr = SN->getValue(StringStorage); 375249259Sdim if (!StringStorage.empty()) { 376249259Sdim // Copy string to permanent storage 377296417Sdim KeyStr = StringStorage.str().copy(StringAllocator); 378249259Sdim } 379360784Sdim return std::make_unique<ScalarHNode>(N, KeyStr); 380288943Sdim } else if (BlockScalarNode *BSN = dyn_cast<BlockScalarNode>(N)) { 381296417Sdim StringRef ValueCopy = BSN->getValue().copy(StringAllocator); 382360784Sdim return std::make_unique<ScalarHNode>(N, ValueCopy); 383249259Sdim } else if (SequenceNode *SQ = dyn_cast<SequenceNode>(N)) { 384360784Sdim auto SQHNode = std::make_unique<SequenceHNode>(N); 385276479Sdim for (Node &SN : *SQ) { 386344779Sdim auto Entry = createHNodes(&SN); 387249259Sdim if (EC) 388249259Sdim break; 389280031Sdim SQHNode->Entries.push_back(std::move(Entry)); 390249259Sdim } 391280031Sdim return std::move(SQHNode); 392249259Sdim } else if (MappingNode *Map = dyn_cast<MappingNode>(N)) { 393360784Sdim auto mapHNode = std::make_unique<MapHNode>(N); 394276479Sdim for (KeyValueNode &KVN : *Map) { 395280031Sdim Node *KeyNode = KVN.getKey(); 396360784Sdim ScalarNode *Key = dyn_cast_or_null<ScalarNode>(KeyNode); 397327952Sdim Node *Value = KVN.getValue(); 398327952Sdim if (!Key || !Value) { 399327952Sdim if (!Key) 400327952Sdim setError(KeyNode, "Map key must be a scalar"); 401327952Sdim if (!Value) 402327952Sdim setError(KeyNode, "Map value must not be empty"); 403280031Sdim break; 404280031Sdim } 405249259Sdim StringStorage.clear(); 406327952Sdim StringRef KeyStr = Key->getValue(StringStorage); 407249259Sdim if (!StringStorage.empty()) { 408249259Sdim // Copy string to permanent storage 409296417Sdim KeyStr = StringStorage.str().copy(StringAllocator); 410249259Sdim } 411344779Sdim auto ValueHNode = createHNodes(Value); 412249259Sdim if (EC) 413249259Sdim break; 414280031Sdim mapHNode->Mapping[KeyStr] = std::move(ValueHNode); 415249259Sdim } 416280031Sdim return std::move(mapHNode); 417249259Sdim } else if (isa<NullNode>(N)) { 418360784Sdim return std::make_unique<EmptyHNode>(N); 419249259Sdim } else { 420249259Sdim setError(N, "unknown node kind"); 421276479Sdim return nullptr; 422249259Sdim } 423249259Sdim} 424249259Sdim 425249259Sdimvoid Input::setError(const Twine &Message) { 426344779Sdim setError(CurrentNode, Message); 427249259Sdim} 428249259Sdim 429261991Sdimbool Input::canElideEmptySequence() { 430261991Sdim return false; 431261991Sdim} 432261991Sdim 433249259Sdim//===----------------------------------------------------------------------===// 434249259Sdim// Output 435249259Sdim//===----------------------------------------------------------------------===// 436249259Sdim 437288943SdimOutput::Output(raw_ostream &yout, void *context, int WrapColumn) 438321369Sdim : IO(context), Out(yout), WrapColumn(WrapColumn) {} 439249259Sdim 440321369SdimOutput::~Output() = default; 441249259Sdim 442360784Sdimbool Output::outputting() const { 443249259Sdim return true; 444249259Sdim} 445249259Sdim 446249259Sdimvoid Output::beginMapping() { 447249259Sdim StateStack.push_back(inMapFirstKey); 448353358Sdim PaddingBeforeContainer = Padding; 449353358Sdim Padding = "\n"; 450249259Sdim} 451249259Sdim 452261991Sdimbool Output::mapTag(StringRef Tag, bool Use) { 453261991Sdim if (Use) { 454309124Sdim // If this tag is being written inside a sequence we should write the start 455309124Sdim // of the sequence before writing the tag, otherwise the tag won't be 456309124Sdim // attached to the element in the sequence, but rather the sequence itself. 457344779Sdim bool SequenceElement = false; 458344779Sdim if (StateStack.size() > 1) { 459344779Sdim auto &E = StateStack[StateStack.size() - 2]; 460344779Sdim SequenceElement = inSeqAnyElement(E) || inFlowSeqAnyElement(E); 461344779Sdim } 462309124Sdim if (SequenceElement && StateStack.back() == inMapFirstKey) { 463344779Sdim newLineCheck(); 464309124Sdim } else { 465344779Sdim output(" "); 466309124Sdim } 467344779Sdim output(Tag); 468309124Sdim if (SequenceElement) { 469309124Sdim // If we're writing the tag during the first element of a map, the tag 470309124Sdim // takes the place of the first element in the sequence. 471309124Sdim if (StateStack.back() == inMapFirstKey) { 472309124Sdim StateStack.pop_back(); 473309124Sdim StateStack.push_back(inMapOtherKey); 474309124Sdim } 475309124Sdim // Tags inside maps in sequences should act as keys in the map from a 476309124Sdim // formatting perspective, so we always want a newline in a sequence. 477353358Sdim Padding = "\n"; 478309124Sdim } 479261991Sdim } 480261991Sdim return Use; 481261991Sdim} 482261991Sdim 483249259Sdimvoid Output::endMapping() { 484344779Sdim // If we did not map anything, we should explicitly emit an empty map 485353358Sdim if (StateStack.back() == inMapFirstKey) { 486353358Sdim Padding = PaddingBeforeContainer; 487353358Sdim newLineCheck(); 488344779Sdim output("{}"); 489353358Sdim Padding = "\n"; 490353358Sdim } 491249259Sdim StateStack.pop_back(); 492249259Sdim} 493249259Sdim 494314564Sdimstd::vector<StringRef> Output::keys() { 495314564Sdim report_fatal_error("invalid call"); 496314564Sdim} 497314564Sdim 498249259Sdimbool Output::preflightKey(const char *Key, bool Required, bool SameAsDefault, 499249259Sdim bool &UseDefault, void *&) { 500249259Sdim UseDefault = false; 501321369Sdim if (Required || !SameAsDefault || WriteDefaultValues) { 502288943Sdim auto State = StateStack.back(); 503288943Sdim if (State == inFlowMapFirstKey || State == inFlowMapOtherKey) { 504288943Sdim flowKey(Key); 505288943Sdim } else { 506344779Sdim newLineCheck(); 507344779Sdim paddedKey(Key); 508288943Sdim } 509249259Sdim return true; 510249259Sdim } 511249259Sdim return false; 512249259Sdim} 513249259Sdim 514249259Sdimvoid Output::postflightKey(void *) { 515249259Sdim if (StateStack.back() == inMapFirstKey) { 516249259Sdim StateStack.pop_back(); 517249259Sdim StateStack.push_back(inMapOtherKey); 518288943Sdim } else if (StateStack.back() == inFlowMapFirstKey) { 519288943Sdim StateStack.pop_back(); 520288943Sdim StateStack.push_back(inFlowMapOtherKey); 521249259Sdim } 522249259Sdim} 523249259Sdim 524288943Sdimvoid Output::beginFlowMapping() { 525288943Sdim StateStack.push_back(inFlowMapFirstKey); 526344779Sdim newLineCheck(); 527288943Sdim ColumnAtMapFlowStart = Column; 528288943Sdim output("{ "); 529288943Sdim} 530288943Sdim 531288943Sdimvoid Output::endFlowMapping() { 532288943Sdim StateStack.pop_back(); 533344779Sdim outputUpToEndOfLine(" }"); 534288943Sdim} 535288943Sdim 536249259Sdimvoid Output::beginDocuments() { 537344779Sdim outputUpToEndOfLine("---"); 538249259Sdim} 539249259Sdim 540249259Sdimbool Output::preflightDocument(unsigned index) { 541249259Sdim if (index > 0) 542344779Sdim outputUpToEndOfLine("\n---"); 543249259Sdim return true; 544249259Sdim} 545249259Sdim 546249259Sdimvoid Output::postflightDocument() { 547249259Sdim} 548249259Sdim 549249259Sdimvoid Output::endDocuments() { 550249259Sdim output("\n...\n"); 551249259Sdim} 552249259Sdim 553249259Sdimunsigned Output::beginSequence() { 554344779Sdim StateStack.push_back(inSeqFirstElement); 555353358Sdim PaddingBeforeContainer = Padding; 556353358Sdim Padding = "\n"; 557249259Sdim return 0; 558249259Sdim} 559249259Sdim 560249259Sdimvoid Output::endSequence() { 561344779Sdim // If we did not emit anything, we should explicitly emit an empty sequence 562353358Sdim if (StateStack.back() == inSeqFirstElement) { 563353358Sdim Padding = PaddingBeforeContainer; 564353358Sdim newLineCheck(); 565344779Sdim output("[]"); 566353358Sdim Padding = "\n"; 567353358Sdim } 568249259Sdim StateStack.pop_back(); 569249259Sdim} 570249259Sdim 571249259Sdimbool Output::preflightElement(unsigned, void *&) { 572249259Sdim return true; 573249259Sdim} 574249259Sdim 575249259Sdimvoid Output::postflightElement(void *) { 576344779Sdim if (StateStack.back() == inSeqFirstElement) { 577344779Sdim StateStack.pop_back(); 578344779Sdim StateStack.push_back(inSeqOtherElement); 579344779Sdim } else if (StateStack.back() == inFlowSeqFirstElement) { 580344779Sdim StateStack.pop_back(); 581344779Sdim StateStack.push_back(inFlowSeqOtherElement); 582344779Sdim } 583249259Sdim} 584249259Sdim 585249259Sdimunsigned Output::beginFlowSequence() { 586344779Sdim StateStack.push_back(inFlowSeqFirstElement); 587344779Sdim newLineCheck(); 588249259Sdim ColumnAtFlowStart = Column; 589249259Sdim output("[ "); 590249259Sdim NeedFlowSequenceComma = false; 591249259Sdim return 0; 592249259Sdim} 593249259Sdim 594249259Sdimvoid Output::endFlowSequence() { 595249259Sdim StateStack.pop_back(); 596344779Sdim outputUpToEndOfLine(" ]"); 597249259Sdim} 598249259Sdim 599249259Sdimbool Output::preflightFlowElement(unsigned, void *&) { 600249259Sdim if (NeedFlowSequenceComma) 601249259Sdim output(", "); 602288943Sdim if (WrapColumn && Column > WrapColumn) { 603249259Sdim output("\n"); 604249259Sdim for (int i = 0; i < ColumnAtFlowStart; ++i) 605249259Sdim output(" "); 606249259Sdim Column = ColumnAtFlowStart; 607249259Sdim output(" "); 608249259Sdim } 609249259Sdim return true; 610249259Sdim} 611249259Sdim 612249259Sdimvoid Output::postflightFlowElement(void *) { 613249259Sdim NeedFlowSequenceComma = true; 614249259Sdim} 615249259Sdim 616249259Sdimvoid Output::beginEnumScalar() { 617249259Sdim EnumerationMatchFound = false; 618249259Sdim} 619249259Sdim 620249259Sdimbool Output::matchEnumScalar(const char *Str, bool Match) { 621249259Sdim if (Match && !EnumerationMatchFound) { 622344779Sdim newLineCheck(); 623344779Sdim outputUpToEndOfLine(Str); 624249259Sdim EnumerationMatchFound = true; 625249259Sdim } 626249259Sdim return false; 627249259Sdim} 628249259Sdim 629288943Sdimbool Output::matchEnumFallback() { 630288943Sdim if (EnumerationMatchFound) 631288943Sdim return false; 632288943Sdim EnumerationMatchFound = true; 633288943Sdim return true; 634288943Sdim} 635288943Sdim 636249259Sdimvoid Output::endEnumScalar() { 637249259Sdim if (!EnumerationMatchFound) 638249259Sdim llvm_unreachable("bad runtime enum value"); 639249259Sdim} 640249259Sdim 641249259Sdimbool Output::beginBitSetScalar(bool &DoClear) { 642344779Sdim newLineCheck(); 643249259Sdim output("[ "); 644249259Sdim NeedBitValueComma = false; 645249259Sdim DoClear = false; 646249259Sdim return true; 647249259Sdim} 648249259Sdim 649249259Sdimbool Output::bitSetMatch(const char *Str, bool Matches) { 650249259Sdim if (Matches) { 651249259Sdim if (NeedBitValueComma) 652249259Sdim output(", "); 653344779Sdim output(Str); 654249259Sdim NeedBitValueComma = true; 655249259Sdim } 656249259Sdim return false; 657249259Sdim} 658249259Sdim 659249259Sdimvoid Output::endBitSetScalar() { 660344779Sdim outputUpToEndOfLine(" ]"); 661249259Sdim} 662249259Sdim 663327952Sdimvoid Output::scalarString(StringRef &S, QuotingType MustQuote) { 664344779Sdim newLineCheck(); 665261991Sdim if (S.empty()) { 666261991Sdim // Print '' for the empty string because leaving the field empty is not 667261991Sdim // allowed. 668344779Sdim outputUpToEndOfLine("''"); 669261991Sdim return; 670261991Sdim } 671327952Sdim if (MustQuote == QuotingType::None) { 672276479Sdim // Only quote if we must. 673344779Sdim outputUpToEndOfLine(S); 674249259Sdim return; 675249259Sdim } 676327952Sdim 677327952Sdim const char *const Quote = MustQuote == QuotingType::Single ? "'" : "\""; 678327952Sdim output(Quote); // Starting quote. 679327952Sdim 680341825Sdim // When using double-quoted strings (and only in that case), non-printable characters may be 681341825Sdim // present, and will be escaped using a variety of unicode-scalar and special short-form 682341825Sdim // escapes. This is handled in yaml::escape. 683341825Sdim if (MustQuote == QuotingType::Double) { 684353358Sdim output(yaml::escape(S, /* EscapePrintable= */ false)); 685344779Sdim outputUpToEndOfLine(Quote); 686341825Sdim return; 687341825Sdim } 688341825Sdim 689353358Sdim unsigned i = 0; 690353358Sdim unsigned j = 0; 691353358Sdim unsigned End = S.size(); 692353358Sdim const char *Base = S.data(); 693353358Sdim 694341825Sdim // When using single-quoted strings, any single quote ' must be doubled to be escaped. 695249259Sdim while (j < End) { 696341825Sdim if (S[j] == '\'') { // Escape quotes. 697341825Sdim output(StringRef(&Base[i], j - i)); // "flush". 698341825Sdim output(StringLiteral("''")); // Print it as '' 699249259Sdim i = j + 1; 700249259Sdim } 701249259Sdim ++j; 702249259Sdim } 703249259Sdim output(StringRef(&Base[i], j - i)); 704344779Sdim outputUpToEndOfLine(Quote); // Ending quote. 705249259Sdim} 706249259Sdim 707288943Sdimvoid Output::blockScalarString(StringRef &S) { 708288943Sdim if (!StateStack.empty()) 709288943Sdim newLineCheck(); 710288943Sdim output(" |"); 711288943Sdim outputNewLine(); 712288943Sdim 713288943Sdim unsigned Indent = StateStack.empty() ? 1 : StateStack.size(); 714288943Sdim 715288943Sdim auto Buffer = MemoryBuffer::getMemBuffer(S, "", false); 716288943Sdim for (line_iterator Lines(*Buffer, false); !Lines.is_at_end(); ++Lines) { 717288943Sdim for (unsigned I = 0; I < Indent; ++I) { 718288943Sdim output(" "); 719288943Sdim } 720288943Sdim output(*Lines); 721288943Sdim outputNewLine(); 722288943Sdim } 723288943Sdim} 724288943Sdim 725344779Sdimvoid Output::scalarTag(std::string &Tag) { 726344779Sdim if (Tag.empty()) 727344779Sdim return; 728344779Sdim newLineCheck(); 729344779Sdim output(Tag); 730344779Sdim output(" "); 731344779Sdim} 732344779Sdim 733249259Sdimvoid Output::setError(const Twine &message) { 734249259Sdim} 735249259Sdim 736261991Sdimbool Output::canElideEmptySequence() { 737261991Sdim // Normally, with an optional key/value where the value is an empty sequence, 738261991Sdim // the whole key/value can be not written. But, that produces wrong yaml 739261991Sdim // if the key/value is the only thing in the map and the map is used in 740261991Sdim // a sequence. This detects if the this sequence is the first key/value 741261991Sdim // in map that itself is embedded in a sequnce. 742261991Sdim if (StateStack.size() < 2) 743261991Sdim return true; 744261991Sdim if (StateStack.back() != inMapFirstKey) 745261991Sdim return true; 746344779Sdim return !inSeqAnyElement(StateStack[StateStack.size() - 2]); 747261991Sdim} 748261991Sdim 749249259Sdimvoid Output::output(StringRef s) { 750249259Sdim Column += s.size(); 751249259Sdim Out << s; 752249259Sdim} 753249259Sdim 754249259Sdimvoid Output::outputUpToEndOfLine(StringRef s) { 755344779Sdim output(s); 756344779Sdim if (StateStack.empty() || (!inFlowSeqAnyElement(StateStack.back()) && 757344779Sdim !inFlowMapAnyKey(StateStack.back()))) 758353358Sdim Padding = "\n"; 759249259Sdim} 760249259Sdim 761249259Sdimvoid Output::outputNewLine() { 762249259Sdim Out << "\n"; 763249259Sdim Column = 0; 764249259Sdim} 765249259Sdim 766249259Sdim// if seq at top, indent as if map, then add "- " 767249259Sdim// if seq in middle, use "- " if firstKey, else use " " 768249259Sdim// 769249259Sdim 770249259Sdimvoid Output::newLineCheck() { 771353358Sdim if (Padding != "\n") { 772353358Sdim output(Padding); 773353358Sdim Padding = {}; 774249259Sdim return; 775353358Sdim } 776344779Sdim outputNewLine(); 777353358Sdim Padding = {}; 778249259Sdim 779344779Sdim if (StateStack.size() == 0) 780344779Sdim return; 781344779Sdim 782249259Sdim unsigned Indent = StateStack.size() - 1; 783249259Sdim bool OutputDash = false; 784249259Sdim 785344779Sdim if (StateStack.back() == inSeqFirstElement || 786344779Sdim StateStack.back() == inSeqOtherElement) { 787249259Sdim OutputDash = true; 788344779Sdim } else if ((StateStack.size() > 1) && 789344779Sdim ((StateStack.back() == inMapFirstKey) || 790344779Sdim inFlowSeqAnyElement(StateStack.back()) || 791344779Sdim (StateStack.back() == inFlowMapFirstKey)) && 792344779Sdim inSeqAnyElement(StateStack[StateStack.size() - 2])) { 793249259Sdim --Indent; 794249259Sdim OutputDash = true; 795249259Sdim } 796249259Sdim 797249259Sdim for (unsigned i = 0; i < Indent; ++i) { 798249259Sdim output(" "); 799249259Sdim } 800249259Sdim if (OutputDash) { 801249259Sdim output("- "); 802249259Sdim } 803249259Sdim 804249259Sdim} 805249259Sdim 806249259Sdimvoid Output::paddedKey(StringRef key) { 807249259Sdim output(key); 808249259Sdim output(":"); 809249259Sdim const char *spaces = " "; 810249259Sdim if (key.size() < strlen(spaces)) 811353358Sdim Padding = &spaces[key.size()]; 812249259Sdim else 813353358Sdim Padding = " "; 814249259Sdim} 815249259Sdim 816288943Sdimvoid Output::flowKey(StringRef Key) { 817288943Sdim if (StateStack.back() == inFlowMapOtherKey) 818288943Sdim output(", "); 819288943Sdim if (WrapColumn && Column > WrapColumn) { 820288943Sdim output("\n"); 821288943Sdim for (int I = 0; I < ColumnAtMapFlowStart; ++I) 822288943Sdim output(" "); 823288943Sdim Column = ColumnAtMapFlowStart; 824288943Sdim output(" "); 825288943Sdim } 826288943Sdim output(Key); 827288943Sdim output(": "); 828288943Sdim} 829288943Sdim 830344779SdimNodeKind Output::getNodeKind() { report_fatal_error("invalid call"); } 831344779Sdim 832344779Sdimbool Output::inSeqAnyElement(InState State) { 833344779Sdim return State == inSeqFirstElement || State == inSeqOtherElement; 834344779Sdim} 835344779Sdim 836344779Sdimbool Output::inFlowSeqAnyElement(InState State) { 837344779Sdim return State == inFlowSeqFirstElement || State == inFlowSeqOtherElement; 838344779Sdim} 839344779Sdim 840344779Sdimbool Output::inMapAnyKey(InState State) { 841344779Sdim return State == inMapFirstKey || State == inMapOtherKey; 842344779Sdim} 843344779Sdim 844344779Sdimbool Output::inFlowMapAnyKey(InState State) { 845344779Sdim return State == inFlowMapFirstKey || State == inFlowMapOtherKey; 846344779Sdim} 847344779Sdim 848249259Sdim//===----------------------------------------------------------------------===// 849249259Sdim// traits for built-in types 850249259Sdim//===----------------------------------------------------------------------===// 851249259Sdim 852249259Sdimvoid ScalarTraits<bool>::output(const bool &Val, void *, raw_ostream &Out) { 853249259Sdim Out << (Val ? "true" : "false"); 854249259Sdim} 855249259Sdim 856249259SdimStringRef ScalarTraits<bool>::input(StringRef Scalar, void *, bool &Val) { 857249259Sdim if (Scalar.equals("true")) { 858249259Sdim Val = true; 859249259Sdim return StringRef(); 860249259Sdim } else if (Scalar.equals("false")) { 861249259Sdim Val = false; 862249259Sdim return StringRef(); 863249259Sdim } 864249259Sdim return "invalid boolean"; 865249259Sdim} 866249259Sdim 867249259Sdimvoid ScalarTraits<StringRef>::output(const StringRef &Val, void *, 868249259Sdim raw_ostream &Out) { 869249259Sdim Out << Val; 870249259Sdim} 871249259Sdim 872249259SdimStringRef ScalarTraits<StringRef>::input(StringRef Scalar, void *, 873249259Sdim StringRef &Val) { 874249259Sdim Val = Scalar; 875249259Sdim return StringRef(); 876249259Sdim} 877288943Sdim 878276479Sdimvoid ScalarTraits<std::string>::output(const std::string &Val, void *, 879276479Sdim raw_ostream &Out) { 880276479Sdim Out << Val; 881276479Sdim} 882249259Sdim 883276479SdimStringRef ScalarTraits<std::string>::input(StringRef Scalar, void *, 884276479Sdim std::string &Val) { 885276479Sdim Val = Scalar.str(); 886276479Sdim return StringRef(); 887276479Sdim} 888276479Sdim 889249259Sdimvoid ScalarTraits<uint8_t>::output(const uint8_t &Val, void *, 890249259Sdim raw_ostream &Out) { 891249259Sdim // use temp uin32_t because ostream thinks uint8_t is a character 892249259Sdim uint32_t Num = Val; 893249259Sdim Out << Num; 894249259Sdim} 895249259Sdim 896249259SdimStringRef ScalarTraits<uint8_t>::input(StringRef Scalar, void *, uint8_t &Val) { 897249259Sdim unsigned long long n; 898249259Sdim if (getAsUnsignedInteger(Scalar, 0, n)) 899249259Sdim return "invalid number"; 900249259Sdim if (n > 0xFF) 901249259Sdim return "out of range number"; 902249259Sdim Val = n; 903249259Sdim return StringRef(); 904249259Sdim} 905249259Sdim 906249259Sdimvoid ScalarTraits<uint16_t>::output(const uint16_t &Val, void *, 907249259Sdim raw_ostream &Out) { 908249259Sdim Out << Val; 909249259Sdim} 910249259Sdim 911249259SdimStringRef ScalarTraits<uint16_t>::input(StringRef Scalar, void *, 912249259Sdim uint16_t &Val) { 913249259Sdim unsigned long long n; 914249259Sdim if (getAsUnsignedInteger(Scalar, 0, n)) 915249259Sdim return "invalid number"; 916249259Sdim if (n > 0xFFFF) 917249259Sdim return "out of range number"; 918249259Sdim Val = n; 919249259Sdim return StringRef(); 920249259Sdim} 921249259Sdim 922249259Sdimvoid ScalarTraits<uint32_t>::output(const uint32_t &Val, void *, 923249259Sdim raw_ostream &Out) { 924249259Sdim Out << Val; 925249259Sdim} 926249259Sdim 927249259SdimStringRef ScalarTraits<uint32_t>::input(StringRef Scalar, void *, 928249259Sdim uint32_t &Val) { 929249259Sdim unsigned long long n; 930249259Sdim if (getAsUnsignedInteger(Scalar, 0, n)) 931249259Sdim return "invalid number"; 932249259Sdim if (n > 0xFFFFFFFFUL) 933249259Sdim return "out of range number"; 934249259Sdim Val = n; 935249259Sdim return StringRef(); 936249259Sdim} 937249259Sdim 938249259Sdimvoid ScalarTraits<uint64_t>::output(const uint64_t &Val, void *, 939249259Sdim raw_ostream &Out) { 940249259Sdim Out << Val; 941249259Sdim} 942249259Sdim 943249259SdimStringRef ScalarTraits<uint64_t>::input(StringRef Scalar, void *, 944249259Sdim uint64_t &Val) { 945249259Sdim unsigned long long N; 946249259Sdim if (getAsUnsignedInteger(Scalar, 0, N)) 947249259Sdim return "invalid number"; 948249259Sdim Val = N; 949249259Sdim return StringRef(); 950249259Sdim} 951249259Sdim 952249259Sdimvoid ScalarTraits<int8_t>::output(const int8_t &Val, void *, raw_ostream &Out) { 953249259Sdim // use temp in32_t because ostream thinks int8_t is a character 954249259Sdim int32_t Num = Val; 955249259Sdim Out << Num; 956249259Sdim} 957249259Sdim 958249259SdimStringRef ScalarTraits<int8_t>::input(StringRef Scalar, void *, int8_t &Val) { 959249259Sdim long long N; 960249259Sdim if (getAsSignedInteger(Scalar, 0, N)) 961249259Sdim return "invalid number"; 962249259Sdim if ((N > 127) || (N < -128)) 963249259Sdim return "out of range number"; 964249259Sdim Val = N; 965249259Sdim return StringRef(); 966249259Sdim} 967249259Sdim 968249259Sdimvoid ScalarTraits<int16_t>::output(const int16_t &Val, void *, 969249259Sdim raw_ostream &Out) { 970249259Sdim Out << Val; 971249259Sdim} 972249259Sdim 973249259SdimStringRef ScalarTraits<int16_t>::input(StringRef Scalar, void *, int16_t &Val) { 974249259Sdim long long N; 975249259Sdim if (getAsSignedInteger(Scalar, 0, N)) 976249259Sdim return "invalid number"; 977249259Sdim if ((N > INT16_MAX) || (N < INT16_MIN)) 978249259Sdim return "out of range number"; 979249259Sdim Val = N; 980249259Sdim return StringRef(); 981249259Sdim} 982249259Sdim 983249259Sdimvoid ScalarTraits<int32_t>::output(const int32_t &Val, void *, 984249259Sdim raw_ostream &Out) { 985249259Sdim Out << Val; 986249259Sdim} 987249259Sdim 988249259SdimStringRef ScalarTraits<int32_t>::input(StringRef Scalar, void *, int32_t &Val) { 989249259Sdim long long N; 990249259Sdim if (getAsSignedInteger(Scalar, 0, N)) 991249259Sdim return "invalid number"; 992249259Sdim if ((N > INT32_MAX) || (N < INT32_MIN)) 993249259Sdim return "out of range number"; 994249259Sdim Val = N; 995249259Sdim return StringRef(); 996249259Sdim} 997249259Sdim 998249259Sdimvoid ScalarTraits<int64_t>::output(const int64_t &Val, void *, 999249259Sdim raw_ostream &Out) { 1000249259Sdim Out << Val; 1001249259Sdim} 1002249259Sdim 1003249259SdimStringRef ScalarTraits<int64_t>::input(StringRef Scalar, void *, int64_t &Val) { 1004249259Sdim long long N; 1005249259Sdim if (getAsSignedInteger(Scalar, 0, N)) 1006249259Sdim return "invalid number"; 1007249259Sdim Val = N; 1008249259Sdim return StringRef(); 1009249259Sdim} 1010249259Sdim 1011249259Sdimvoid ScalarTraits<double>::output(const double &Val, void *, raw_ostream &Out) { 1012249259Sdim Out << format("%g", Val); 1013249259Sdim} 1014249259Sdim 1015249259SdimStringRef ScalarTraits<double>::input(StringRef Scalar, void *, double &Val) { 1016321369Sdim if (to_float(Scalar, Val)) 1017321369Sdim return StringRef(); 1018321369Sdim return "invalid floating point number"; 1019249259Sdim} 1020249259Sdim 1021249259Sdimvoid ScalarTraits<float>::output(const float &Val, void *, raw_ostream &Out) { 1022249259Sdim Out << format("%g", Val); 1023249259Sdim} 1024249259Sdim 1025249259SdimStringRef ScalarTraits<float>::input(StringRef Scalar, void *, float &Val) { 1026321369Sdim if (to_float(Scalar, Val)) 1027321369Sdim return StringRef(); 1028321369Sdim return "invalid floating point number"; 1029249259Sdim} 1030249259Sdim 1031249259Sdimvoid ScalarTraits<Hex8>::output(const Hex8 &Val, void *, raw_ostream &Out) { 1032249259Sdim uint8_t Num = Val; 1033249259Sdim Out << format("0x%02X", Num); 1034249259Sdim} 1035249259Sdim 1036249259SdimStringRef ScalarTraits<Hex8>::input(StringRef Scalar, void *, Hex8 &Val) { 1037249259Sdim unsigned long long n; 1038249259Sdim if (getAsUnsignedInteger(Scalar, 0, n)) 1039249259Sdim return "invalid hex8 number"; 1040249259Sdim if (n > 0xFF) 1041249259Sdim return "out of range hex8 number"; 1042249259Sdim Val = n; 1043249259Sdim return StringRef(); 1044249259Sdim} 1045249259Sdim 1046249259Sdimvoid ScalarTraits<Hex16>::output(const Hex16 &Val, void *, raw_ostream &Out) { 1047249259Sdim uint16_t Num = Val; 1048249259Sdim Out << format("0x%04X", Num); 1049249259Sdim} 1050249259Sdim 1051249259SdimStringRef ScalarTraits<Hex16>::input(StringRef Scalar, void *, Hex16 &Val) { 1052249259Sdim unsigned long long n; 1053249259Sdim if (getAsUnsignedInteger(Scalar, 0, n)) 1054249259Sdim return "invalid hex16 number"; 1055249259Sdim if (n > 0xFFFF) 1056249259Sdim return "out of range hex16 number"; 1057249259Sdim Val = n; 1058249259Sdim return StringRef(); 1059249259Sdim} 1060249259Sdim 1061249259Sdimvoid ScalarTraits<Hex32>::output(const Hex32 &Val, void *, raw_ostream &Out) { 1062249259Sdim uint32_t Num = Val; 1063249259Sdim Out << format("0x%08X", Num); 1064249259Sdim} 1065249259Sdim 1066249259SdimStringRef ScalarTraits<Hex32>::input(StringRef Scalar, void *, Hex32 &Val) { 1067249259Sdim unsigned long long n; 1068249259Sdim if (getAsUnsignedInteger(Scalar, 0, n)) 1069249259Sdim return "invalid hex32 number"; 1070249259Sdim if (n > 0xFFFFFFFFUL) 1071249259Sdim return "out of range hex32 number"; 1072249259Sdim Val = n; 1073249259Sdim return StringRef(); 1074249259Sdim} 1075249259Sdim 1076249259Sdimvoid ScalarTraits<Hex64>::output(const Hex64 &Val, void *, raw_ostream &Out) { 1077249259Sdim uint64_t Num = Val; 1078249259Sdim Out << format("0x%016llX", Num); 1079249259Sdim} 1080249259Sdim 1081249259SdimStringRef ScalarTraits<Hex64>::input(StringRef Scalar, void *, Hex64 &Val) { 1082249259Sdim unsigned long long Num; 1083249259Sdim if (getAsUnsignedInteger(Scalar, 0, Num)) 1084249259Sdim return "invalid hex64 number"; 1085249259Sdim Val = Num; 1086249259Sdim return StringRef(); 1087249259Sdim} 1088