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