File: | build/llvm-toolchain-snapshot-15~++20220420111733+e13d2efed663/clang-tools-extra/clangd/index/YAMLSerialization.cpp |
Warning: | line 124, column 5 1st function call argument is an uninitialized value |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | //===-- YAMLSerialization.cpp ------------------------------------*- C++-*-===// | |||
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 | // | |||
9 | // A YAML index file is a sequence of tagged entries. | |||
10 | // Each entry either encodes a Symbol or the list of references to a symbol | |||
11 | // (a "ref bundle"). | |||
12 | // | |||
13 | //===----------------------------------------------------------------------===// | |||
14 | ||||
15 | #include "Headers.h" | |||
16 | #include "index/Ref.h" | |||
17 | #include "index/Relation.h" | |||
18 | #include "index/Serialization.h" | |||
19 | #include "index/Symbol.h" | |||
20 | #include "index/SymbolLocation.h" | |||
21 | #include "index/SymbolOrigin.h" | |||
22 | #include "clang/Tooling/CompilationDatabase.h" | |||
23 | #include "llvm/ADT/Optional.h" | |||
24 | #include "llvm/ADT/StringRef.h" | |||
25 | #include "llvm/Support/Allocator.h" | |||
26 | #include "llvm/Support/StringSaver.h" | |||
27 | #include "llvm/Support/YAMLTraits.h" | |||
28 | #include "llvm/Support/raw_ostream.h" | |||
29 | #include <cstdint> | |||
30 | ||||
31 | LLVM_YAML_IS_SEQUENCE_VECTOR(clang::clangd::Symbol::IncludeHeaderWithReferences)namespace llvm { namespace yaml { static_assert( !std::is_fundamental <clang::clangd::Symbol::IncludeHeaderWithReferences>::value && !std::is_same<clang::clangd::Symbol::IncludeHeaderWithReferences , std::string>::value && !std::is_same<clang::clangd ::Symbol::IncludeHeaderWithReferences, llvm::StringRef>::value , "only use LLVM_YAML_IS_SEQUENCE_VECTOR for types you control" ); template <> struct SequenceElementTraits<clang::clangd ::Symbol::IncludeHeaderWithReferences> { static const bool flow = false; }; } } | |||
32 | LLVM_YAML_IS_SEQUENCE_VECTOR(clang::clangd::Ref)namespace llvm { namespace yaml { static_assert( !std::is_fundamental <clang::clangd::Ref>::value && !std::is_same< clang::clangd::Ref, std::string>::value && !std::is_same <clang::clangd::Ref, llvm::StringRef>::value, "only use LLVM_YAML_IS_SEQUENCE_VECTOR for types you control" ); template <> struct SequenceElementTraits<clang::clangd ::Ref> { static const bool flow = false; }; } } | |||
33 | ||||
34 | namespace { | |||
35 | using RefBundle = | |||
36 | std::pair<clang::clangd::SymbolID, std::vector<clang::clangd::Ref>>; | |||
37 | // This is a pale imitation of std::variant<Symbol, RefBundle, Relation> | |||
38 | struct VariantEntry { | |||
39 | llvm::Optional<clang::clangd::Symbol> Symbol; | |||
40 | llvm::Optional<RefBundle> Refs; | |||
41 | llvm::Optional<clang::clangd::Relation> Relation; | |||
42 | llvm::Optional<clang::clangd::IncludeGraphNode> Source; | |||
43 | llvm::Optional<clang::tooling::CompileCommand> Cmd; | |||
44 | }; | |||
45 | // A class helps YAML to serialize the 32-bit encoded position (Line&Column), | |||
46 | // as YAMLIO can't directly map bitfields. | |||
47 | struct YPosition { | |||
48 | uint32_t Line; | |||
49 | uint32_t Column; | |||
50 | }; | |||
51 | ||||
52 | // avoid ODR violation of specialization for non-owned CompileCommand | |||
53 | struct CompileCommandYAML : clang::tooling::CompileCommand {}; | |||
54 | ||||
55 | } // namespace | |||
56 | namespace llvm { | |||
57 | namespace yaml { | |||
58 | ||||
59 | using clang::clangd::FileDigest; | |||
60 | using clang::clangd::IncludeGraph; | |||
61 | using clang::clangd::IncludeGraphNode; | |||
62 | using clang::clangd::Ref; | |||
63 | using clang::clangd::RefKind; | |||
64 | using clang::clangd::Relation; | |||
65 | using clang::clangd::RelationKind; | |||
66 | using clang::clangd::Symbol; | |||
67 | using clang::clangd::SymbolID; | |||
68 | using clang::clangd::SymbolLocation; | |||
69 | using clang::index::SymbolInfo; | |||
70 | using clang::index::SymbolKind; | |||
71 | using clang::index::SymbolLanguage; | |||
72 | using clang::tooling::CompileCommand; | |||
73 | ||||
74 | // Helper to (de)serialize the SymbolID. We serialize it as a hex string. | |||
75 | struct NormalizedSymbolID { | |||
76 | NormalizedSymbolID(IO &) {} | |||
77 | NormalizedSymbolID(IO &, const SymbolID &ID) { | |||
78 | llvm::raw_string_ostream OS(HexString); | |||
79 | OS << ID; | |||
80 | } | |||
81 | ||||
82 | SymbolID denormalize(IO &I) { | |||
83 | auto ID = SymbolID::fromStr(HexString); | |||
84 | if (!ID) { | |||
85 | I.setError(llvm::toString(ID.takeError())); | |||
86 | return SymbolID(); | |||
87 | } | |||
88 | return *ID; | |||
89 | } | |||
90 | ||||
91 | std::string HexString; | |||
92 | }; | |||
93 | ||||
94 | struct NormalizedSymbolFlag { | |||
95 | NormalizedSymbolFlag(IO &) {} | |||
96 | NormalizedSymbolFlag(IO &, Symbol::SymbolFlag F) { | |||
97 | Flag = static_cast<uint8_t>(F); | |||
98 | } | |||
99 | ||||
100 | Symbol::SymbolFlag denormalize(IO &) { | |||
101 | return static_cast<Symbol::SymbolFlag>(Flag); | |||
102 | } | |||
103 | ||||
104 | uint8_t Flag = 0; | |||
105 | }; | |||
106 | ||||
107 | template <> struct MappingTraits<YPosition> { | |||
108 | static void mapping(IO &IO, YPosition &Value) { | |||
109 | IO.mapRequired("Line", Value.Line); | |||
110 | IO.mapRequired("Column", Value.Column); | |||
111 | } | |||
112 | }; | |||
113 | ||||
114 | struct NormalizedPosition { | |||
115 | using Position = clang::clangd::SymbolLocation::Position; | |||
116 | NormalizedPosition(IO &) {} | |||
117 | NormalizedPosition(IO &, const Position &Pos) { | |||
118 | P.Line = Pos.line(); | |||
119 | P.Column = Pos.column(); | |||
120 | } | |||
121 | ||||
122 | Position denormalize(IO &) { | |||
123 | Position Pos; | |||
124 | Pos.setLine(P.Line); | |||
| ||||
125 | Pos.setColumn(P.Column); | |||
126 | return Pos; | |||
127 | } | |||
128 | YPosition P; | |||
129 | }; | |||
130 | ||||
131 | struct NormalizedFileURI { | |||
132 | NormalizedFileURI(IO &) {} | |||
133 | NormalizedFileURI(IO &, const char *FileURI) { URI = FileURI; } | |||
134 | ||||
135 | const char *denormalize(IO &IO) { | |||
136 | assert(IO.getContext() &&(static_cast <bool> (IO.getContext() && "Expecting an UniqueStringSaver to allocate data" ) ? void (0) : __assert_fail ("IO.getContext() && \"Expecting an UniqueStringSaver to allocate data\"" , "clang-tools-extra/clangd/index/YAMLSerialization.cpp", 137 , __extension__ __PRETTY_FUNCTION__)) | |||
137 | "Expecting an UniqueStringSaver to allocate data")(static_cast <bool> (IO.getContext() && "Expecting an UniqueStringSaver to allocate data" ) ? void (0) : __assert_fail ("IO.getContext() && \"Expecting an UniqueStringSaver to allocate data\"" , "clang-tools-extra/clangd/index/YAMLSerialization.cpp", 137 , __extension__ __PRETTY_FUNCTION__)); | |||
138 | return static_cast<llvm::UniqueStringSaver *>(IO.getContext()) | |||
139 | ->save(URI) | |||
140 | .data(); | |||
141 | } | |||
142 | ||||
143 | std::string URI; | |||
144 | }; | |||
145 | ||||
146 | template <> struct MappingTraits<SymbolLocation> { | |||
147 | static void mapping(IO &IO, SymbolLocation &Value) { | |||
148 | MappingNormalization<NormalizedFileURI, const char *> NFile(IO, | |||
149 | Value.FileURI); | |||
150 | IO.mapRequired("FileURI", NFile->URI); | |||
151 | MappingNormalization<NormalizedPosition, SymbolLocation::Position> NStart( | |||
152 | IO, Value.Start); | |||
153 | IO.mapRequired("Start", NStart->P); | |||
154 | MappingNormalization<NormalizedPosition, SymbolLocation::Position> NEnd( | |||
155 | IO, Value.End); | |||
156 | IO.mapRequired("End", NEnd->P); | |||
157 | } | |||
158 | }; | |||
159 | ||||
160 | template <> struct MappingTraits<SymbolInfo> { | |||
161 | static void mapping(IO &IO, SymbolInfo &SymInfo) { | |||
162 | // FIXME: expose other fields? | |||
163 | IO.mapRequired("Kind", SymInfo.Kind); | |||
164 | IO.mapRequired("Lang", SymInfo.Lang); | |||
165 | } | |||
166 | }; | |||
167 | ||||
168 | template <> | |||
169 | struct MappingTraits<clang::clangd::Symbol::IncludeHeaderWithReferences> { | |||
170 | static void mapping(IO &IO, | |||
171 | clang::clangd::Symbol::IncludeHeaderWithReferences &Inc) { | |||
172 | IO.mapRequired("Header", Inc.IncludeHeader); | |||
173 | IO.mapRequired("References", Inc.References); | |||
174 | } | |||
175 | }; | |||
176 | ||||
177 | template <> struct MappingTraits<Symbol> { | |||
178 | static void mapping(IO &IO, Symbol &Sym) { | |||
179 | MappingNormalization<NormalizedSymbolID, SymbolID> NSymbolID(IO, Sym.ID); | |||
180 | MappingNormalization<NormalizedSymbolFlag, Symbol::SymbolFlag> NSymbolFlag( | |||
181 | IO, Sym.Flags); | |||
182 | IO.mapRequired("ID", NSymbolID->HexString); | |||
183 | IO.mapRequired("Name", Sym.Name); | |||
184 | IO.mapRequired("Scope", Sym.Scope); | |||
185 | IO.mapRequired("SymInfo", Sym.SymInfo); | |||
186 | IO.mapOptional("CanonicalDeclaration", Sym.CanonicalDeclaration, | |||
187 | SymbolLocation()); | |||
188 | IO.mapOptional("Definition", Sym.Definition, SymbolLocation()); | |||
189 | IO.mapOptional("References", Sym.References, 0u); | |||
190 | IO.mapOptional("Flags", NSymbolFlag->Flag); | |||
191 | IO.mapOptional("Signature", Sym.Signature); | |||
192 | IO.mapOptional("TemplateSpecializationArgs", | |||
193 | Sym.TemplateSpecializationArgs); | |||
194 | IO.mapOptional("CompletionSnippetSuffix", Sym.CompletionSnippetSuffix); | |||
195 | IO.mapOptional("Documentation", Sym.Documentation); | |||
196 | IO.mapOptional("ReturnType", Sym.ReturnType); | |||
197 | IO.mapOptional("Type", Sym.Type); | |||
198 | IO.mapOptional("IncludeHeaders", Sym.IncludeHeaders); | |||
199 | } | |||
200 | }; | |||
201 | ||||
202 | template <> struct ScalarEnumerationTraits<SymbolLanguage> { | |||
203 | static void enumeration(IO &IO, SymbolLanguage &Value) { | |||
204 | IO.enumCase(Value, "C", SymbolLanguage::C); | |||
205 | IO.enumCase(Value, "Cpp", SymbolLanguage::CXX); | |||
206 | IO.enumCase(Value, "ObjC", SymbolLanguage::ObjC); | |||
207 | IO.enumCase(Value, "Swift", SymbolLanguage::Swift); | |||
208 | } | |||
209 | }; | |||
210 | ||||
211 | template <> struct ScalarEnumerationTraits<SymbolKind> { | |||
212 | static void enumeration(IO &IO, SymbolKind &Value) { | |||
213 | #define DEFINE_ENUM(name) IO.enumCase(Value, #name, SymbolKind::name) | |||
214 | ||||
215 | DEFINE_ENUM(Unknown); | |||
216 | DEFINE_ENUM(Function); | |||
217 | DEFINE_ENUM(Module); | |||
218 | DEFINE_ENUM(Namespace); | |||
219 | DEFINE_ENUM(NamespaceAlias); | |||
220 | DEFINE_ENUM(Macro); | |||
221 | DEFINE_ENUM(Enum); | |||
222 | DEFINE_ENUM(Struct); | |||
223 | DEFINE_ENUM(Class); | |||
224 | DEFINE_ENUM(Protocol); | |||
225 | DEFINE_ENUM(Extension); | |||
226 | DEFINE_ENUM(Union); | |||
227 | DEFINE_ENUM(TypeAlias); | |||
228 | DEFINE_ENUM(Function); | |||
229 | DEFINE_ENUM(Variable); | |||
230 | DEFINE_ENUM(Field); | |||
231 | DEFINE_ENUM(EnumConstant); | |||
232 | DEFINE_ENUM(InstanceMethod); | |||
233 | DEFINE_ENUM(ClassMethod); | |||
234 | DEFINE_ENUM(StaticMethod); | |||
235 | DEFINE_ENUM(InstanceProperty); | |||
236 | DEFINE_ENUM(ClassProperty); | |||
237 | DEFINE_ENUM(StaticProperty); | |||
238 | DEFINE_ENUM(Constructor); | |||
239 | DEFINE_ENUM(Destructor); | |||
240 | DEFINE_ENUM(ConversionFunction); | |||
241 | DEFINE_ENUM(Parameter); | |||
242 | DEFINE_ENUM(Using); | |||
243 | ||||
244 | #undef DEFINE_ENUM | |||
245 | } | |||
246 | }; | |||
247 | ||||
248 | template <> struct MappingTraits<RefBundle> { | |||
249 | static void mapping(IO &IO, RefBundle &Refs) { | |||
250 | MappingNormalization<NormalizedSymbolID, SymbolID> NSymbolID(IO, | |||
251 | Refs.first); | |||
252 | IO.mapRequired("ID", NSymbolID->HexString); | |||
253 | IO.mapRequired("References", Refs.second); | |||
254 | } | |||
255 | }; | |||
256 | ||||
257 | struct NormalizedRefKind { | |||
258 | NormalizedRefKind(IO &) {} | |||
259 | NormalizedRefKind(IO &, RefKind O) { Kind = static_cast<uint8_t>(O); } | |||
260 | ||||
261 | RefKind denormalize(IO &) { return static_cast<RefKind>(Kind); } | |||
262 | ||||
263 | uint8_t Kind = 0; | |||
264 | }; | |||
265 | ||||
266 | template <> struct MappingTraits<Ref> { | |||
267 | static void mapping(IO &IO, Ref &R) { | |||
268 | MappingNormalization<NormalizedRefKind, RefKind> NKind(IO, R.Kind); | |||
269 | IO.mapRequired("Kind", NKind->Kind); | |||
270 | IO.mapRequired("Location", R.Location); | |||
271 | } | |||
272 | }; | |||
273 | ||||
274 | struct NormalizedSymbolRole { | |||
275 | NormalizedSymbolRole(IO &) {} | |||
276 | NormalizedSymbolRole(IO &IO, RelationKind R) { | |||
277 | Kind = static_cast<uint8_t>(R); | |||
278 | } | |||
279 | ||||
280 | RelationKind denormalize(IO &IO) { return static_cast<RelationKind>(Kind); } | |||
281 | ||||
282 | uint8_t Kind = 0; | |||
283 | }; | |||
284 | ||||
285 | template <> struct MappingTraits<SymbolID> { | |||
286 | static void mapping(IO &IO, SymbolID &ID) { | |||
287 | MappingNormalization<NormalizedSymbolID, SymbolID> NSymbolID(IO, ID); | |||
288 | IO.mapRequired("ID", NSymbolID->HexString); | |||
289 | } | |||
290 | }; | |||
291 | ||||
292 | template <> struct MappingTraits<Relation> { | |||
293 | static void mapping(IO &IO, Relation &Relation) { | |||
294 | MappingNormalization<NormalizedSymbolRole, RelationKind> NRole( | |||
295 | IO, Relation.Predicate); | |||
296 | IO.mapRequired("Subject", Relation.Subject); | |||
297 | IO.mapRequired("Predicate", NRole->Kind); | |||
298 | IO.mapRequired("Object", Relation.Object); | |||
299 | } | |||
300 | }; | |||
301 | ||||
302 | struct NormalizedSourceFlag { | |||
303 | NormalizedSourceFlag(IO &) {} | |||
304 | NormalizedSourceFlag(IO &, IncludeGraphNode::SourceFlag O) { | |||
305 | Flag = static_cast<uint8_t>(O); | |||
306 | } | |||
307 | ||||
308 | IncludeGraphNode::SourceFlag denormalize(IO &) { | |||
309 | return static_cast<IncludeGraphNode::SourceFlag>(Flag); | |||
310 | } | |||
311 | ||||
312 | uint8_t Flag = 0; | |||
313 | }; | |||
314 | ||||
315 | struct NormalizedFileDigest { | |||
316 | NormalizedFileDigest(IO &) {} | |||
317 | NormalizedFileDigest(IO &, const FileDigest &Digest) { | |||
318 | HexString = llvm::toHex(Digest); | |||
319 | } | |||
320 | ||||
321 | FileDigest denormalize(IO &I) { | |||
322 | FileDigest Digest; | |||
323 | if (HexString.size() == Digest.size() * 2 && | |||
324 | llvm::all_of(HexString, llvm::isHexDigit)) { | |||
325 | memcpy(Digest.data(), llvm::fromHex(HexString).data(), Digest.size()); | |||
326 | } else { | |||
327 | I.setError(std::string("Bad hex file digest: ") + HexString); | |||
328 | } | |||
329 | return Digest; | |||
330 | } | |||
331 | ||||
332 | std::string HexString; | |||
333 | }; | |||
334 | ||||
335 | template <> struct MappingTraits<IncludeGraphNode> { | |||
336 | static void mapping(IO &IO, IncludeGraphNode &Node) { | |||
337 | IO.mapRequired("URI", Node.URI); | |||
338 | MappingNormalization<NormalizedSourceFlag, IncludeGraphNode::SourceFlag> | |||
339 | NSourceFlag(IO, Node.Flags); | |||
340 | IO.mapRequired("Flags", NSourceFlag->Flag); | |||
341 | MappingNormalization<NormalizedFileDigest, FileDigest> NDigest(IO, | |||
342 | Node.Digest); | |||
343 | IO.mapRequired("Digest", NDigest->HexString); | |||
344 | IO.mapRequired("DirectIncludes", Node.DirectIncludes); | |||
345 | } | |||
346 | }; | |||
347 | ||||
348 | template <> struct MappingTraits<CompileCommandYAML> { | |||
349 | static void mapping(IO &IO, CompileCommandYAML &Cmd) { | |||
350 | IO.mapRequired("Directory", Cmd.Directory); | |||
351 | IO.mapRequired("CommandLine", Cmd.CommandLine); | |||
352 | } | |||
353 | }; | |||
354 | ||||
355 | template <> struct MappingTraits<VariantEntry> { | |||
356 | static void mapping(IO &IO, VariantEntry &Variant) { | |||
357 | if (IO.mapTag("!Symbol", Variant.Symbol.hasValue())) { | |||
358 | if (!IO.outputting()) | |||
359 | Variant.Symbol.emplace(); | |||
360 | MappingTraits<Symbol>::mapping(IO, *Variant.Symbol); | |||
361 | } else if (IO.mapTag("!Refs", Variant.Refs.hasValue())) { | |||
362 | if (!IO.outputting()) | |||
363 | Variant.Refs.emplace(); | |||
364 | MappingTraits<RefBundle>::mapping(IO, *Variant.Refs); | |||
365 | } else if (IO.mapTag("!Relations", Variant.Relation.hasValue())) { | |||
366 | if (!IO.outputting()) | |||
367 | Variant.Relation.emplace(); | |||
368 | MappingTraits<Relation>::mapping(IO, *Variant.Relation); | |||
369 | } else if (IO.mapTag("!Source", Variant.Source.hasValue())) { | |||
370 | if (!IO.outputting()) | |||
371 | Variant.Source.emplace(); | |||
372 | MappingTraits<IncludeGraphNode>::mapping(IO, *Variant.Source); | |||
373 | } else if (IO.mapTag("!Cmd", Variant.Cmd.hasValue())) { | |||
374 | if (!IO.outputting()) | |||
375 | Variant.Cmd.emplace(); | |||
376 | MappingTraits<CompileCommandYAML>::mapping( | |||
377 | IO, static_cast<CompileCommandYAML &>(*Variant.Cmd)); | |||
378 | } | |||
379 | } | |||
380 | }; | |||
381 | ||||
382 | } // namespace yaml | |||
383 | } // namespace llvm | |||
384 | ||||
385 | namespace clang { | |||
386 | namespace clangd { | |||
387 | ||||
388 | void writeYAML(const IndexFileOut &O, llvm::raw_ostream &OS) { | |||
389 | llvm::yaml::Output Yout(OS); | |||
390 | for (const auto &Sym : *O.Symbols) { | |||
391 | VariantEntry Entry; | |||
392 | Entry.Symbol = Sym; | |||
393 | Yout << Entry; | |||
394 | } | |||
395 | if (O.Refs) | |||
396 | for (auto &Sym : *O.Refs) { | |||
397 | VariantEntry Entry; | |||
398 | Entry.Refs = Sym; | |||
399 | Yout << Entry; | |||
400 | } | |||
401 | if (O.Relations) | |||
402 | for (auto &R : *O.Relations) { | |||
403 | VariantEntry Entry; | |||
404 | Entry.Relation = R; | |||
405 | Yout << Entry; | |||
406 | } | |||
407 | if (O.Sources) { | |||
408 | for (const auto &Source : *O.Sources) { | |||
409 | VariantEntry Entry; | |||
410 | Entry.Source = Source.getValue(); | |||
411 | Yout << Entry; | |||
412 | } | |||
413 | } | |||
414 | if (O.Cmd) { | |||
415 | VariantEntry Entry; | |||
416 | Entry.Cmd = *O.Cmd; | |||
417 | Yout << Entry; | |||
418 | } | |||
419 | } | |||
420 | ||||
421 | llvm::Expected<IndexFileIn> readYAML(llvm::StringRef Data, | |||
422 | SymbolOrigin Origin) { | |||
423 | SymbolSlab::Builder Symbols; | |||
424 | RefSlab::Builder Refs; | |||
425 | RelationSlab::Builder Relations; | |||
426 | llvm::BumpPtrAllocator | |||
427 | Arena; // store the underlying data of Position::FileURI. | |||
428 | llvm::UniqueStringSaver Strings(Arena); | |||
429 | llvm::yaml::Input Yin(Data, &Strings); | |||
430 | IncludeGraph Sources; | |||
431 | llvm::Optional<tooling::CompileCommand> Cmd; | |||
432 | while (Yin.setCurrentDocument()) { | |||
433 | llvm::yaml::EmptyContext Ctx; | |||
434 | VariantEntry Variant; | |||
435 | yamlize(Yin, Variant, true, Ctx); | |||
436 | if (Yin.error()) | |||
437 | return llvm::errorCodeToError(Yin.error()); | |||
438 | ||||
439 | if (Variant.Symbol) { | |||
440 | Variant.Symbol->Origin = Origin; | |||
441 | Symbols.insert(*Variant.Symbol); | |||
442 | } | |||
443 | if (Variant.Refs) | |||
444 | for (const auto &Ref : Variant.Refs->second) | |||
445 | Refs.insert(Variant.Refs->first, Ref); | |||
446 | if (Variant.Relation) | |||
447 | Relations.insert(*Variant.Relation); | |||
448 | if (Variant.Source) { | |||
449 | auto &IGN = Variant.Source.getValue(); | |||
450 | auto Entry = Sources.try_emplace(IGN.URI).first; | |||
451 | Entry->getValue() = std::move(IGN); | |||
452 | // Fixup refs to refer to map keys which will live on | |||
453 | Entry->getValue().URI = Entry->getKey(); | |||
454 | for (auto &Include : Entry->getValue().DirectIncludes) | |||
455 | Include = Sources.try_emplace(Include).first->getKey(); | |||
456 | } | |||
457 | if (Variant.Cmd) | |||
458 | Cmd = *Variant.Cmd; | |||
459 | Yin.nextDocument(); | |||
460 | } | |||
461 | ||||
462 | IndexFileIn Result; | |||
463 | Result.Symbols.emplace(std::move(Symbols).build()); | |||
464 | Result.Refs.emplace(std::move(Refs).build()); | |||
465 | Result.Relations.emplace(std::move(Relations).build()); | |||
466 | if (Sources.size()) | |||
467 | Result.Sources = std::move(Sources); | |||
468 | Result.Cmd = std::move(Cmd); | |||
469 | return std::move(Result); | |||
470 | } | |||
471 | ||||
472 | std::string toYAML(const Symbol &S) { | |||
473 | std::string Buf; | |||
474 | { | |||
475 | llvm::raw_string_ostream OS(Buf); | |||
476 | llvm::yaml::Output Yout(OS); | |||
477 | Symbol Sym = S; // copy: Yout<< requires mutability. | |||
478 | Yout << Sym; | |||
479 | } | |||
480 | return Buf; | |||
481 | } | |||
482 | ||||
483 | std::string toYAML(const std::pair<SymbolID, llvm::ArrayRef<Ref>> &Data) { | |||
484 | RefBundle Refs = {Data.first, Data.second}; | |||
485 | std::string Buf; | |||
486 | { | |||
487 | llvm::raw_string_ostream OS(Buf); | |||
488 | llvm::yaml::Output Yout(OS); | |||
489 | Yout << Refs; | |||
490 | } | |||
491 | return Buf; | |||
492 | } | |||
493 | ||||
494 | std::string toYAML(const Relation &R) { | |||
495 | std::string Buf; | |||
496 | { | |||
497 | llvm::raw_string_ostream OS(Buf); | |||
498 | llvm::yaml::Output Yout(OS); | |||
499 | Relation Rel = R; // copy: Yout<< requires mutability. | |||
500 | Yout << Rel; | |||
501 | } | |||
502 | return Buf; | |||
503 | } | |||
504 | ||||
505 | std::string toYAML(const Ref &R) { | |||
506 | std::string Buf; | |||
507 | { | |||
508 | llvm::raw_string_ostream OS(Buf); | |||
509 | llvm::yaml::Output Yout(OS); | |||
510 | Ref Reference = R; // copy: Yout<< requires mutability. | |||
511 | Yout << Reference; | |||
| ||||
512 | } | |||
513 | return Buf; | |||
514 | } | |||
515 | ||||
516 | } // namespace clangd | |||
517 | } // namespace clang |
1 | //===- llvm/Support/YAMLTraits.h --------------------------------*- C++ -*-===// | ||||||||||||
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 | |||||||||||||
9 | #ifndef LLVM_SUPPORT_YAMLTRAITS_H | ||||||||||||
10 | #define LLVM_SUPPORT_YAMLTRAITS_H | ||||||||||||
11 | |||||||||||||
12 | #include "llvm/ADT/BitVector.h" | ||||||||||||
13 | #include "llvm/ADT/Optional.h" | ||||||||||||
14 | #include "llvm/ADT/SmallVector.h" | ||||||||||||
15 | #include "llvm/ADT/StringExtras.h" | ||||||||||||
16 | #include "llvm/ADT/StringMap.h" | ||||||||||||
17 | #include "llvm/ADT/StringRef.h" | ||||||||||||
18 | #include "llvm/ADT/Twine.h" | ||||||||||||
19 | #include "llvm/Support/AlignOf.h" | ||||||||||||
20 | #include "llvm/Support/Allocator.h" | ||||||||||||
21 | #include "llvm/Support/Endian.h" | ||||||||||||
22 | #include "llvm/Support/SMLoc.h" | ||||||||||||
23 | #include "llvm/Support/SourceMgr.h" | ||||||||||||
24 | #include "llvm/Support/YAMLParser.h" | ||||||||||||
25 | #include "llvm/Support/raw_ostream.h" | ||||||||||||
26 | #include <cassert> | ||||||||||||
27 | #include <map> | ||||||||||||
28 | #include <memory> | ||||||||||||
29 | #include <new> | ||||||||||||
30 | #include <string> | ||||||||||||
31 | #include <system_error> | ||||||||||||
32 | #include <type_traits> | ||||||||||||
33 | #include <vector> | ||||||||||||
34 | |||||||||||||
35 | namespace llvm { | ||||||||||||
36 | |||||||||||||
37 | class VersionTuple; | ||||||||||||
38 | |||||||||||||
39 | namespace yaml { | ||||||||||||
40 | |||||||||||||
41 | enum class NodeKind : uint8_t { | ||||||||||||
42 | Scalar, | ||||||||||||
43 | Map, | ||||||||||||
44 | Sequence, | ||||||||||||
45 | }; | ||||||||||||
46 | |||||||||||||
47 | struct EmptyContext {}; | ||||||||||||
48 | |||||||||||||
49 | /// This class should be specialized by any type that needs to be converted | ||||||||||||
50 | /// to/from a YAML mapping. For example: | ||||||||||||
51 | /// | ||||||||||||
52 | /// struct MappingTraits<MyStruct> { | ||||||||||||
53 | /// static void mapping(IO &io, MyStruct &s) { | ||||||||||||
54 | /// io.mapRequired("name", s.name); | ||||||||||||
55 | /// io.mapRequired("size", s.size); | ||||||||||||
56 | /// io.mapOptional("age", s.age); | ||||||||||||
57 | /// } | ||||||||||||
58 | /// }; | ||||||||||||
59 | template<class T> | ||||||||||||
60 | struct MappingTraits { | ||||||||||||
61 | // Must provide: | ||||||||||||
62 | // static void mapping(IO &io, T &fields); | ||||||||||||
63 | // Optionally may provide: | ||||||||||||
64 | // static std::string validate(IO &io, T &fields); | ||||||||||||
65 | // static void enumInput(IO &io, T &value); | ||||||||||||
66 | // | ||||||||||||
67 | // The optional flow flag will cause generated YAML to use a flow mapping | ||||||||||||
68 | // (e.g. { a: 0, b: 1 }): | ||||||||||||
69 | // static const bool flow = true; | ||||||||||||
70 | }; | ||||||||||||
71 | |||||||||||||
72 | /// This class is similar to MappingTraits<T> but allows you to pass in | ||||||||||||
73 | /// additional context for each map operation. For example: | ||||||||||||
74 | /// | ||||||||||||
75 | /// struct MappingContextTraits<MyStruct, MyContext> { | ||||||||||||
76 | /// static void mapping(IO &io, MyStruct &s, MyContext &c) { | ||||||||||||
77 | /// io.mapRequired("name", s.name); | ||||||||||||
78 | /// io.mapRequired("size", s.size); | ||||||||||||
79 | /// io.mapOptional("age", s.age); | ||||||||||||
80 | /// ++c.TimesMapped; | ||||||||||||
81 | /// } | ||||||||||||
82 | /// }; | ||||||||||||
83 | template <class T, class Context> struct MappingContextTraits { | ||||||||||||
84 | // Must provide: | ||||||||||||
85 | // static void mapping(IO &io, T &fields, Context &Ctx); | ||||||||||||
86 | // Optionally may provide: | ||||||||||||
87 | // static std::string validate(IO &io, T &fields, Context &Ctx); | ||||||||||||
88 | // | ||||||||||||
89 | // The optional flow flag will cause generated YAML to use a flow mapping | ||||||||||||
90 | // (e.g. { a: 0, b: 1 }): | ||||||||||||
91 | // static const bool flow = true; | ||||||||||||
92 | }; | ||||||||||||
93 | |||||||||||||
94 | /// This class should be specialized by any integral type that converts | ||||||||||||
95 | /// to/from a YAML scalar where there is a one-to-one mapping between | ||||||||||||
96 | /// in-memory values and a string in YAML. For example: | ||||||||||||
97 | /// | ||||||||||||
98 | /// struct ScalarEnumerationTraits<Colors> { | ||||||||||||
99 | /// static void enumeration(IO &io, Colors &value) { | ||||||||||||
100 | /// io.enumCase(value, "red", cRed); | ||||||||||||
101 | /// io.enumCase(value, "blue", cBlue); | ||||||||||||
102 | /// io.enumCase(value, "green", cGreen); | ||||||||||||
103 | /// } | ||||||||||||
104 | /// }; | ||||||||||||
105 | template <typename T, typename Enable = void> struct ScalarEnumerationTraits { | ||||||||||||
106 | // Must provide: | ||||||||||||
107 | // static void enumeration(IO &io, T &value); | ||||||||||||
108 | }; | ||||||||||||
109 | |||||||||||||
110 | /// This class should be specialized by any integer type that is a union | ||||||||||||
111 | /// of bit values and the YAML representation is a flow sequence of | ||||||||||||
112 | /// strings. For example: | ||||||||||||
113 | /// | ||||||||||||
114 | /// struct ScalarBitSetTraits<MyFlags> { | ||||||||||||
115 | /// static void bitset(IO &io, MyFlags &value) { | ||||||||||||
116 | /// io.bitSetCase(value, "big", flagBig); | ||||||||||||
117 | /// io.bitSetCase(value, "flat", flagFlat); | ||||||||||||
118 | /// io.bitSetCase(value, "round", flagRound); | ||||||||||||
119 | /// } | ||||||||||||
120 | /// }; | ||||||||||||
121 | template <typename T, typename Enable = void> struct ScalarBitSetTraits { | ||||||||||||
122 | // Must provide: | ||||||||||||
123 | // static void bitset(IO &io, T &value); | ||||||||||||
124 | }; | ||||||||||||
125 | |||||||||||||
126 | /// Describe which type of quotes should be used when quoting is necessary. | ||||||||||||
127 | /// Some non-printable characters need to be double-quoted, while some others | ||||||||||||
128 | /// are fine with simple-quoting, and some don't need any quoting. | ||||||||||||
129 | enum class QuotingType { None, Single, Double }; | ||||||||||||
130 | |||||||||||||
131 | /// This class should be specialized by type that requires custom conversion | ||||||||||||
132 | /// to/from a yaml scalar. For example: | ||||||||||||
133 | /// | ||||||||||||
134 | /// template<> | ||||||||||||
135 | /// struct ScalarTraits<MyType> { | ||||||||||||
136 | /// static void output(const MyType &val, void*, llvm::raw_ostream &out) { | ||||||||||||
137 | /// // stream out custom formatting | ||||||||||||
138 | /// out << llvm::format("%x", val); | ||||||||||||
139 | /// } | ||||||||||||
140 | /// static StringRef input(StringRef scalar, void*, MyType &value) { | ||||||||||||
141 | /// // parse scalar and set `value` | ||||||||||||
142 | /// // return empty string on success, or error string | ||||||||||||
143 | /// return StringRef(); | ||||||||||||
144 | /// } | ||||||||||||
145 | /// static QuotingType mustQuote(StringRef) { return QuotingType::Single; } | ||||||||||||
146 | /// }; | ||||||||||||
147 | template <typename T, typename Enable = void> struct ScalarTraits { | ||||||||||||
148 | // Must provide: | ||||||||||||
149 | // | ||||||||||||
150 | // Function to write the value as a string: | ||||||||||||
151 | // static void output(const T &value, void *ctxt, llvm::raw_ostream &out); | ||||||||||||
152 | // | ||||||||||||
153 | // Function to convert a string to a value. Returns the empty | ||||||||||||
154 | // StringRef on success or an error string if string is malformed: | ||||||||||||
155 | // static StringRef input(StringRef scalar, void *ctxt, T &value); | ||||||||||||
156 | // | ||||||||||||
157 | // Function to determine if the value should be quoted. | ||||||||||||
158 | // static QuotingType mustQuote(StringRef); | ||||||||||||
159 | }; | ||||||||||||
160 | |||||||||||||
161 | /// This class should be specialized by type that requires custom conversion | ||||||||||||
162 | /// to/from a YAML literal block scalar. For example: | ||||||||||||
163 | /// | ||||||||||||
164 | /// template <> | ||||||||||||
165 | /// struct BlockScalarTraits<MyType> { | ||||||||||||
166 | /// static void output(const MyType &Value, void*, llvm::raw_ostream &Out) | ||||||||||||
167 | /// { | ||||||||||||
168 | /// // stream out custom formatting | ||||||||||||
169 | /// Out << Value; | ||||||||||||
170 | /// } | ||||||||||||
171 | /// static StringRef input(StringRef Scalar, void*, MyType &Value) { | ||||||||||||
172 | /// // parse scalar and set `value` | ||||||||||||
173 | /// // return empty string on success, or error string | ||||||||||||
174 | /// return StringRef(); | ||||||||||||
175 | /// } | ||||||||||||
176 | /// }; | ||||||||||||
177 | template <typename T> | ||||||||||||
178 | struct BlockScalarTraits { | ||||||||||||
179 | // Must provide: | ||||||||||||
180 | // | ||||||||||||
181 | // Function to write the value as a string: | ||||||||||||
182 | // static void output(const T &Value, void *ctx, llvm::raw_ostream &Out); | ||||||||||||
183 | // | ||||||||||||
184 | // Function to convert a string to a value. Returns the empty | ||||||||||||
185 | // StringRef on success or an error string if string is malformed: | ||||||||||||
186 | // static StringRef input(StringRef Scalar, void *ctxt, T &Value); | ||||||||||||
187 | // | ||||||||||||
188 | // Optional: | ||||||||||||
189 | // static StringRef inputTag(T &Val, std::string Tag) | ||||||||||||
190 | // static void outputTag(const T &Val, raw_ostream &Out) | ||||||||||||
191 | }; | ||||||||||||
192 | |||||||||||||
193 | /// This class should be specialized by type that requires custom conversion | ||||||||||||
194 | /// to/from a YAML scalar with optional tags. For example: | ||||||||||||
195 | /// | ||||||||||||
196 | /// template <> | ||||||||||||
197 | /// struct TaggedScalarTraits<MyType> { | ||||||||||||
198 | /// static void output(const MyType &Value, void*, llvm::raw_ostream | ||||||||||||
199 | /// &ScalarOut, llvm::raw_ostream &TagOut) | ||||||||||||
200 | /// { | ||||||||||||
201 | /// // stream out custom formatting including optional Tag | ||||||||||||
202 | /// Out << Value; | ||||||||||||
203 | /// } | ||||||||||||
204 | /// static StringRef input(StringRef Scalar, StringRef Tag, void*, MyType | ||||||||||||
205 | /// &Value) { | ||||||||||||
206 | /// // parse scalar and set `value` | ||||||||||||
207 | /// // return empty string on success, or error string | ||||||||||||
208 | /// return StringRef(); | ||||||||||||
209 | /// } | ||||||||||||
210 | /// static QuotingType mustQuote(const MyType &Value, StringRef) { | ||||||||||||
211 | /// return QuotingType::Single; | ||||||||||||
212 | /// } | ||||||||||||
213 | /// }; | ||||||||||||
214 | template <typename T> struct TaggedScalarTraits { | ||||||||||||
215 | // Must provide: | ||||||||||||
216 | // | ||||||||||||
217 | // Function to write the value and tag as strings: | ||||||||||||
218 | // static void output(const T &Value, void *ctx, llvm::raw_ostream &ScalarOut, | ||||||||||||
219 | // llvm::raw_ostream &TagOut); | ||||||||||||
220 | // | ||||||||||||
221 | // Function to convert a string to a value. Returns the empty | ||||||||||||
222 | // StringRef on success or an error string if string is malformed: | ||||||||||||
223 | // static StringRef input(StringRef Scalar, StringRef Tag, void *ctxt, T | ||||||||||||
224 | // &Value); | ||||||||||||
225 | // | ||||||||||||
226 | // Function to determine if the value should be quoted. | ||||||||||||
227 | // static QuotingType mustQuote(const T &Value, StringRef Scalar); | ||||||||||||
228 | }; | ||||||||||||
229 | |||||||||||||
230 | /// This class should be specialized by any type that needs to be converted | ||||||||||||
231 | /// to/from a YAML sequence. For example: | ||||||||||||
232 | /// | ||||||||||||
233 | /// template<> | ||||||||||||
234 | /// struct SequenceTraits<MyContainer> { | ||||||||||||
235 | /// static size_t size(IO &io, MyContainer &seq) { | ||||||||||||
236 | /// return seq.size(); | ||||||||||||
237 | /// } | ||||||||||||
238 | /// static MyType& element(IO &, MyContainer &seq, size_t index) { | ||||||||||||
239 | /// if ( index >= seq.size() ) | ||||||||||||
240 | /// seq.resize(index+1); | ||||||||||||
241 | /// return seq[index]; | ||||||||||||
242 | /// } | ||||||||||||
243 | /// }; | ||||||||||||
244 | template<typename T, typename EnableIf = void> | ||||||||||||
245 | struct SequenceTraits { | ||||||||||||
246 | // Must provide: | ||||||||||||
247 | // static size_t size(IO &io, T &seq); | ||||||||||||
248 | // static T::value_type& element(IO &io, T &seq, size_t index); | ||||||||||||
249 | // | ||||||||||||
250 | // The following is option and will cause generated YAML to use | ||||||||||||
251 | // a flow sequence (e.g. [a,b,c]). | ||||||||||||
252 | // static const bool flow = true; | ||||||||||||
253 | }; | ||||||||||||
254 | |||||||||||||
255 | /// This class should be specialized by any type for which vectors of that | ||||||||||||
256 | /// type need to be converted to/from a YAML sequence. | ||||||||||||
257 | template<typename T, typename EnableIf = void> | ||||||||||||
258 | struct SequenceElementTraits { | ||||||||||||
259 | // Must provide: | ||||||||||||
260 | // static const bool flow; | ||||||||||||
261 | }; | ||||||||||||
262 | |||||||||||||
263 | /// This class should be specialized by any type that needs to be converted | ||||||||||||
264 | /// to/from a list of YAML documents. | ||||||||||||
265 | template<typename T> | ||||||||||||
266 | struct DocumentListTraits { | ||||||||||||
267 | // Must provide: | ||||||||||||
268 | // static size_t size(IO &io, T &seq); | ||||||||||||
269 | // static T::value_type& element(IO &io, T &seq, size_t index); | ||||||||||||
270 | }; | ||||||||||||
271 | |||||||||||||
272 | /// This class should be specialized by any type that needs to be converted | ||||||||||||
273 | /// to/from a YAML mapping in the case where the names of the keys are not known | ||||||||||||
274 | /// in advance, e.g. a string map. | ||||||||||||
275 | template <typename T> | ||||||||||||
276 | struct CustomMappingTraits { | ||||||||||||
277 | // static void inputOne(IO &io, StringRef key, T &elem); | ||||||||||||
278 | // static void output(IO &io, T &elem); | ||||||||||||
279 | }; | ||||||||||||
280 | |||||||||||||
281 | /// This class should be specialized by any type that can be represented as | ||||||||||||
282 | /// a scalar, map, or sequence, decided dynamically. For example: | ||||||||||||
283 | /// | ||||||||||||
284 | /// typedef std::unique_ptr<MyBase> MyPoly; | ||||||||||||
285 | /// | ||||||||||||
286 | /// template<> | ||||||||||||
287 | /// struct PolymorphicTraits<MyPoly> { | ||||||||||||
288 | /// static NodeKind getKind(const MyPoly &poly) { | ||||||||||||
289 | /// return poly->getKind(); | ||||||||||||
290 | /// } | ||||||||||||
291 | /// static MyScalar& getAsScalar(MyPoly &poly) { | ||||||||||||
292 | /// if (!poly || !isa<MyScalar>(poly)) | ||||||||||||
293 | /// poly.reset(new MyScalar()); | ||||||||||||
294 | /// return *cast<MyScalar>(poly.get()); | ||||||||||||
295 | /// } | ||||||||||||
296 | /// // ... | ||||||||||||
297 | /// }; | ||||||||||||
298 | template <typename T> struct PolymorphicTraits { | ||||||||||||
299 | // Must provide: | ||||||||||||
300 | // static NodeKind getKind(const T &poly); | ||||||||||||
301 | // static scalar_type &getAsScalar(T &poly); | ||||||||||||
302 | // static map_type &getAsMap(T &poly); | ||||||||||||
303 | // static sequence_type &getAsSequence(T &poly); | ||||||||||||
304 | }; | ||||||||||||
305 | |||||||||||||
306 | // Only used for better diagnostics of missing traits | ||||||||||||
307 | template <typename T> | ||||||||||||
308 | struct MissingTrait; | ||||||||||||
309 | |||||||||||||
310 | // Test if ScalarEnumerationTraits<T> is defined on type T. | ||||||||||||
311 | template <class T> | ||||||||||||
312 | struct has_ScalarEnumerationTraits | ||||||||||||
313 | { | ||||||||||||
314 | using Signature_enumeration = void (*)(class IO&, T&); | ||||||||||||
315 | |||||||||||||
316 | template <typename U> | ||||||||||||
317 | static char test(SameType<Signature_enumeration, &U::enumeration>*); | ||||||||||||
318 | |||||||||||||
319 | template <typename U> | ||||||||||||
320 | static double test(...); | ||||||||||||
321 | |||||||||||||
322 | static bool const value = | ||||||||||||
323 | (sizeof(test<ScalarEnumerationTraits<T>>(nullptr)) == 1); | ||||||||||||
324 | }; | ||||||||||||
325 | |||||||||||||
326 | // Test if ScalarBitSetTraits<T> is defined on type T. | ||||||||||||
327 | template <class T> | ||||||||||||
328 | struct has_ScalarBitSetTraits | ||||||||||||
329 | { | ||||||||||||
330 | using Signature_bitset = void (*)(class IO&, T&); | ||||||||||||
331 | |||||||||||||
332 | template <typename U> | ||||||||||||
333 | static char test(SameType<Signature_bitset, &U::bitset>*); | ||||||||||||
334 | |||||||||||||
335 | template <typename U> | ||||||||||||
336 | static double test(...); | ||||||||||||
337 | |||||||||||||
338 | static bool const value = (sizeof(test<ScalarBitSetTraits<T>>(nullptr)) == 1); | ||||||||||||
339 | }; | ||||||||||||
340 | |||||||||||||
341 | // Test if ScalarTraits<T> is defined on type T. | ||||||||||||
342 | template <class T> | ||||||||||||
343 | struct has_ScalarTraits | ||||||||||||
344 | { | ||||||||||||
345 | using Signature_input = StringRef (*)(StringRef, void*, T&); | ||||||||||||
346 | using Signature_output = void (*)(const T&, void*, raw_ostream&); | ||||||||||||
347 | using Signature_mustQuote = QuotingType (*)(StringRef); | ||||||||||||
348 | |||||||||||||
349 | template <typename U> | ||||||||||||
350 | static char test(SameType<Signature_input, &U::input> *, | ||||||||||||
351 | SameType<Signature_output, &U::output> *, | ||||||||||||
352 | SameType<Signature_mustQuote, &U::mustQuote> *); | ||||||||||||
353 | |||||||||||||
354 | template <typename U> | ||||||||||||
355 | static double test(...); | ||||||||||||
356 | |||||||||||||
357 | static bool const value = | ||||||||||||
358 | (sizeof(test<ScalarTraits<T>>(nullptr, nullptr, nullptr)) == 1); | ||||||||||||
359 | }; | ||||||||||||
360 | |||||||||||||
361 | // Test if BlockScalarTraits<T> is defined on type T. | ||||||||||||
362 | template <class T> | ||||||||||||
363 | struct has_BlockScalarTraits | ||||||||||||
364 | { | ||||||||||||
365 | using Signature_input = StringRef (*)(StringRef, void *, T &); | ||||||||||||
366 | using Signature_output = void (*)(const T &, void *, raw_ostream &); | ||||||||||||
367 | |||||||||||||
368 | template <typename U> | ||||||||||||
369 | static char test(SameType<Signature_input, &U::input> *, | ||||||||||||
370 | SameType<Signature_output, &U::output> *); | ||||||||||||
371 | |||||||||||||
372 | template <typename U> | ||||||||||||
373 | static double test(...); | ||||||||||||
374 | |||||||||||||
375 | static bool const value = | ||||||||||||
376 | (sizeof(test<BlockScalarTraits<T>>(nullptr, nullptr)) == 1); | ||||||||||||
377 | }; | ||||||||||||
378 | |||||||||||||
379 | // Test if TaggedScalarTraits<T> is defined on type T. | ||||||||||||
380 | template <class T> struct has_TaggedScalarTraits { | ||||||||||||
381 | using Signature_input = StringRef (*)(StringRef, StringRef, void *, T &); | ||||||||||||
382 | using Signature_output = void (*)(const T &, void *, raw_ostream &, | ||||||||||||
383 | raw_ostream &); | ||||||||||||
384 | using Signature_mustQuote = QuotingType (*)(const T &, StringRef); | ||||||||||||
385 | |||||||||||||
386 | template <typename U> | ||||||||||||
387 | static char test(SameType<Signature_input, &U::input> *, | ||||||||||||
388 | SameType<Signature_output, &U::output> *, | ||||||||||||
389 | SameType<Signature_mustQuote, &U::mustQuote> *); | ||||||||||||
390 | |||||||||||||
391 | template <typename U> static double test(...); | ||||||||||||
392 | |||||||||||||
393 | static bool const value = | ||||||||||||
394 | (sizeof(test<TaggedScalarTraits<T>>(nullptr, nullptr, nullptr)) == 1); | ||||||||||||
395 | }; | ||||||||||||
396 | |||||||||||||
397 | // Test if MappingContextTraits<T> is defined on type T. | ||||||||||||
398 | template <class T, class Context> struct has_MappingTraits { | ||||||||||||
399 | using Signature_mapping = void (*)(class IO &, T &, Context &); | ||||||||||||
400 | |||||||||||||
401 | template <typename U> | ||||||||||||
402 | static char test(SameType<Signature_mapping, &U::mapping>*); | ||||||||||||
403 | |||||||||||||
404 | template <typename U> | ||||||||||||
405 | static double test(...); | ||||||||||||
406 | |||||||||||||
407 | static bool const value = | ||||||||||||
408 | (sizeof(test<MappingContextTraits<T, Context>>(nullptr)) == 1); | ||||||||||||
409 | }; | ||||||||||||
410 | |||||||||||||
411 | // Test if MappingTraits<T> is defined on type T. | ||||||||||||
412 | template <class T> struct has_MappingTraits<T, EmptyContext> { | ||||||||||||
413 | using Signature_mapping = void (*)(class IO &, T &); | ||||||||||||
414 | |||||||||||||
415 | template <typename U> | ||||||||||||
416 | static char test(SameType<Signature_mapping, &U::mapping> *); | ||||||||||||
417 | |||||||||||||
418 | template <typename U> static double test(...); | ||||||||||||
419 | |||||||||||||
420 | static bool const value = (sizeof(test<MappingTraits<T>>(nullptr)) == 1); | ||||||||||||
421 | }; | ||||||||||||
422 | |||||||||||||
423 | // Test if MappingContextTraits<T>::validate() is defined on type T. | ||||||||||||
424 | template <class T, class Context> struct has_MappingValidateTraits { | ||||||||||||
425 | using Signature_validate = std::string (*)(class IO &, T &, Context &); | ||||||||||||
426 | |||||||||||||
427 | template <typename U> | ||||||||||||
428 | static char test(SameType<Signature_validate, &U::validate>*); | ||||||||||||
429 | |||||||||||||
430 | template <typename U> | ||||||||||||
431 | static double test(...); | ||||||||||||
432 | |||||||||||||
433 | static bool const value = | ||||||||||||
434 | (sizeof(test<MappingContextTraits<T, Context>>(nullptr)) == 1); | ||||||||||||
435 | }; | ||||||||||||
436 | |||||||||||||
437 | // Test if MappingTraits<T>::validate() is defined on type T. | ||||||||||||
438 | template <class T> struct has_MappingValidateTraits<T, EmptyContext> { | ||||||||||||
439 | using Signature_validate = std::string (*)(class IO &, T &); | ||||||||||||
440 | |||||||||||||
441 | template <typename U> | ||||||||||||
442 | static char test(SameType<Signature_validate, &U::validate> *); | ||||||||||||
443 | |||||||||||||
444 | template <typename U> static double test(...); | ||||||||||||
445 | |||||||||||||
446 | static bool const value = (sizeof(test<MappingTraits<T>>(nullptr)) == 1); | ||||||||||||
447 | }; | ||||||||||||
448 | |||||||||||||
449 | // Test if MappingContextTraits<T>::enumInput() is defined on type T. | ||||||||||||
450 | template <class T, class Context> struct has_MappingEnumInputTraits { | ||||||||||||
451 | using Signature_validate = void (*)(class IO &, T &); | ||||||||||||
452 | |||||||||||||
453 | template <typename U> | ||||||||||||
454 | static char test(SameType<Signature_validate, &U::enumInput> *); | ||||||||||||
455 | |||||||||||||
456 | template <typename U> static double test(...); | ||||||||||||
457 | |||||||||||||
458 | static bool const value = | ||||||||||||
459 | (sizeof(test<MappingContextTraits<T, Context>>(nullptr)) == 1); | ||||||||||||
460 | }; | ||||||||||||
461 | |||||||||||||
462 | // Test if MappingTraits<T>::enumInput() is defined on type T. | ||||||||||||
463 | template <class T> struct has_MappingEnumInputTraits<T, EmptyContext> { | ||||||||||||
464 | using Signature_validate = void (*)(class IO &, T &); | ||||||||||||
465 | |||||||||||||
466 | template <typename U> | ||||||||||||
467 | static char test(SameType<Signature_validate, &U::enumInput> *); | ||||||||||||
468 | |||||||||||||
469 | template <typename U> static double test(...); | ||||||||||||
470 | |||||||||||||
471 | static bool const value = (sizeof(test<MappingTraits<T>>(nullptr)) == 1); | ||||||||||||
472 | }; | ||||||||||||
473 | |||||||||||||
474 | // Test if SequenceTraits<T> is defined on type T. | ||||||||||||
475 | template <class T> | ||||||||||||
476 | struct has_SequenceMethodTraits | ||||||||||||
477 | { | ||||||||||||
478 | using Signature_size = size_t (*)(class IO&, T&); | ||||||||||||
479 | |||||||||||||
480 | template <typename U> | ||||||||||||
481 | static char test(SameType<Signature_size, &U::size>*); | ||||||||||||
482 | |||||||||||||
483 | template <typename U> | ||||||||||||
484 | static double test(...); | ||||||||||||
485 | |||||||||||||
486 | static bool const value = (sizeof(test<SequenceTraits<T>>(nullptr)) == 1); | ||||||||||||
487 | }; | ||||||||||||
488 | |||||||||||||
489 | // Test if CustomMappingTraits<T> is defined on type T. | ||||||||||||
490 | template <class T> | ||||||||||||
491 | struct has_CustomMappingTraits | ||||||||||||
492 | { | ||||||||||||
493 | using Signature_input = void (*)(IO &io, StringRef key, T &v); | ||||||||||||
494 | |||||||||||||
495 | template <typename U> | ||||||||||||
496 | static char test(SameType<Signature_input, &U::inputOne>*); | ||||||||||||
497 | |||||||||||||
498 | template <typename U> | ||||||||||||
499 | static double test(...); | ||||||||||||
500 | |||||||||||||
501 | static bool const value = | ||||||||||||
502 | (sizeof(test<CustomMappingTraits<T>>(nullptr)) == 1); | ||||||||||||
503 | }; | ||||||||||||
504 | |||||||||||||
505 | // has_FlowTraits<int> will cause an error with some compilers because | ||||||||||||
506 | // it subclasses int. Using this wrapper only instantiates the | ||||||||||||
507 | // real has_FlowTraits only if the template type is a class. | ||||||||||||
508 | template <typename T, bool Enabled = std::is_class<T>::value> | ||||||||||||
509 | class has_FlowTraits | ||||||||||||
510 | { | ||||||||||||
511 | public: | ||||||||||||
512 | static const bool value = false; | ||||||||||||
513 | }; | ||||||||||||
514 | |||||||||||||
515 | // Some older gcc compilers don't support straight forward tests | ||||||||||||
516 | // for members, so test for ambiguity cause by the base and derived | ||||||||||||
517 | // classes both defining the member. | ||||||||||||
518 | template <class T> | ||||||||||||
519 | struct has_FlowTraits<T, true> | ||||||||||||
520 | { | ||||||||||||
521 | struct Fallback { bool flow; }; | ||||||||||||
522 | struct Derived : T, Fallback { }; | ||||||||||||
523 | |||||||||||||
524 | template<typename C> | ||||||||||||
525 | static char (&f(SameType<bool Fallback::*, &C::flow>*))[1]; | ||||||||||||
526 | |||||||||||||
527 | template<typename C> | ||||||||||||
528 | static char (&f(...))[2]; | ||||||||||||
529 | |||||||||||||
530 | static bool const value = sizeof(f<Derived>(nullptr)) == 2; | ||||||||||||
531 | }; | ||||||||||||
532 | |||||||||||||
533 | // Test if SequenceTraits<T> is defined on type T | ||||||||||||
534 | template<typename T> | ||||||||||||
535 | struct has_SequenceTraits : public std::integral_constant<bool, | ||||||||||||
536 | has_SequenceMethodTraits<T>::value > { }; | ||||||||||||
537 | |||||||||||||
538 | // Test if DocumentListTraits<T> is defined on type T | ||||||||||||
539 | template <class T> | ||||||||||||
540 | struct has_DocumentListTraits | ||||||||||||
541 | { | ||||||||||||
542 | using Signature_size = size_t (*)(class IO &, T &); | ||||||||||||
543 | |||||||||||||
544 | template <typename U> | ||||||||||||
545 | static char test(SameType<Signature_size, &U::size>*); | ||||||||||||
546 | |||||||||||||
547 | template <typename U> | ||||||||||||
548 | static double test(...); | ||||||||||||
549 | |||||||||||||
550 | static bool const value = (sizeof(test<DocumentListTraits<T>>(nullptr))==1); | ||||||||||||
551 | }; | ||||||||||||
552 | |||||||||||||
553 | template <class T> struct has_PolymorphicTraits { | ||||||||||||
554 | using Signature_getKind = NodeKind (*)(const T &); | ||||||||||||
555 | |||||||||||||
556 | template <typename U> | ||||||||||||
557 | static char test(SameType<Signature_getKind, &U::getKind> *); | ||||||||||||
558 | |||||||||||||
559 | template <typename U> static double test(...); | ||||||||||||
560 | |||||||||||||
561 | static bool const value = (sizeof(test<PolymorphicTraits<T>>(nullptr)) == 1); | ||||||||||||
562 | }; | ||||||||||||
563 | |||||||||||||
564 | inline bool isNumeric(StringRef S) { | ||||||||||||
565 | const auto skipDigits = [](StringRef Input) { | ||||||||||||
566 | return Input.ltrim("0123456789"); | ||||||||||||
567 | }; | ||||||||||||
568 | |||||||||||||
569 | // Make S.front() and S.drop_front().front() (if S.front() is [+-]) calls | ||||||||||||
570 | // safe. | ||||||||||||
571 | if (S.empty() || S.equals("+") || S.equals("-")) | ||||||||||||
572 | return false; | ||||||||||||
573 | |||||||||||||
574 | if (S.equals(".nan") || S.equals(".NaN") || S.equals(".NAN")) | ||||||||||||
575 | return true; | ||||||||||||
576 | |||||||||||||
577 | // Infinity and decimal numbers can be prefixed with sign. | ||||||||||||
578 | StringRef Tail = (S.front() == '-' || S.front() == '+') ? S.drop_front() : S; | ||||||||||||
579 | |||||||||||||
580 | // Check for infinity first, because checking for hex and oct numbers is more | ||||||||||||
581 | // expensive. | ||||||||||||
582 | if (Tail.equals(".inf") || Tail.equals(".Inf") || Tail.equals(".INF")) | ||||||||||||
583 | return true; | ||||||||||||
584 | |||||||||||||
585 | // Section 10.3.2 Tag Resolution | ||||||||||||
586 | // YAML 1.2 Specification prohibits Base 8 and Base 16 numbers prefixed with | ||||||||||||
587 | // [-+], so S should be used instead of Tail. | ||||||||||||
588 | if (S.startswith("0o")) | ||||||||||||
589 | return S.size() > 2 && | ||||||||||||
590 | S.drop_front(2).find_first_not_of("01234567") == StringRef::npos; | ||||||||||||
591 | |||||||||||||
592 | if (S.startswith("0x")) | ||||||||||||
593 | return S.size() > 2 && S.drop_front(2).find_first_not_of( | ||||||||||||
594 | "0123456789abcdefABCDEF") == StringRef::npos; | ||||||||||||
595 | |||||||||||||
596 | // Parse float: [-+]? (\. [0-9]+ | [0-9]+ (\. [0-9]* )?) ([eE] [-+]? [0-9]+)? | ||||||||||||
597 | S = Tail; | ||||||||||||
598 | |||||||||||||
599 | // Handle cases when the number starts with '.' and hence needs at least one | ||||||||||||
600 | // digit after dot (as opposed by number which has digits before the dot), but | ||||||||||||
601 | // doesn't have one. | ||||||||||||
602 | if (S.startswith(".") && | ||||||||||||
603 | (S.equals(".") || | ||||||||||||
604 | (S.size() > 1 && std::strchr("0123456789", S[1]) == nullptr))) | ||||||||||||
605 | return false; | ||||||||||||
606 | |||||||||||||
607 | if (S.startswith("E") || S.startswith("e")) | ||||||||||||
608 | return false; | ||||||||||||
609 | |||||||||||||
610 | enum ParseState { | ||||||||||||
611 | Default, | ||||||||||||
612 | FoundDot, | ||||||||||||
613 | FoundExponent, | ||||||||||||
614 | }; | ||||||||||||
615 | ParseState State = Default; | ||||||||||||
616 | |||||||||||||
617 | S = skipDigits(S); | ||||||||||||
618 | |||||||||||||
619 | // Accept decimal integer. | ||||||||||||
620 | if (S.empty()) | ||||||||||||
621 | return true; | ||||||||||||
622 | |||||||||||||
623 | if (S.front() == '.') { | ||||||||||||
624 | State = FoundDot; | ||||||||||||
625 | S = S.drop_front(); | ||||||||||||
626 | } else if (S.front() == 'e' || S.front() == 'E') { | ||||||||||||
627 | State = FoundExponent; | ||||||||||||
628 | S = S.drop_front(); | ||||||||||||
629 | } else { | ||||||||||||
630 | return false; | ||||||||||||
631 | } | ||||||||||||
632 | |||||||||||||
633 | if (State == FoundDot) { | ||||||||||||
634 | S = skipDigits(S); | ||||||||||||
635 | if (S.empty()) | ||||||||||||
636 | return true; | ||||||||||||
637 | |||||||||||||
638 | if (S.front() == 'e' || S.front() == 'E') { | ||||||||||||
639 | State = FoundExponent; | ||||||||||||
640 | S = S.drop_front(); | ||||||||||||
641 | } else { | ||||||||||||
642 | return false; | ||||||||||||
643 | } | ||||||||||||
644 | } | ||||||||||||
645 | |||||||||||||
646 | assert(State == FoundExponent && "Should have found exponent at this point.")(static_cast <bool> (State == FoundExponent && "Should have found exponent at this point." ) ? void (0) : __assert_fail ("State == FoundExponent && \"Should have found exponent at this point.\"" , "llvm/include/llvm/Support/YAMLTraits.h", 646, __extension__ __PRETTY_FUNCTION__)); | ||||||||||||
647 | if (S.empty()) | ||||||||||||
648 | return false; | ||||||||||||
649 | |||||||||||||
650 | if (S.front() == '+' || S.front() == '-') { | ||||||||||||
651 | S = S.drop_front(); | ||||||||||||
652 | if (S.empty()) | ||||||||||||
653 | return false; | ||||||||||||
654 | } | ||||||||||||
655 | |||||||||||||
656 | return skipDigits(S).empty(); | ||||||||||||
657 | } | ||||||||||||
658 | |||||||||||||
659 | inline bool isNull(StringRef S) { | ||||||||||||
660 | return S.equals("null") || S.equals("Null") || S.equals("NULL") || | ||||||||||||
661 | S.equals("~"); | ||||||||||||
662 | } | ||||||||||||
663 | |||||||||||||
664 | inline bool isBool(StringRef S) { | ||||||||||||
665 | // FIXME: using parseBool is causing multiple tests to fail. | ||||||||||||
666 | return S.equals("true") || S.equals("True") || S.equals("TRUE") || | ||||||||||||
667 | S.equals("false") || S.equals("False") || S.equals("FALSE"); | ||||||||||||
668 | } | ||||||||||||
669 | |||||||||||||
670 | // 5.1. Character Set | ||||||||||||
671 | // The allowed character range explicitly excludes the C0 control block #x0-#x1F | ||||||||||||
672 | // (except for TAB #x9, LF #xA, and CR #xD which are allowed), DEL #x7F, the C1 | ||||||||||||
673 | // control block #x80-#x9F (except for NEL #x85 which is allowed), the surrogate | ||||||||||||
674 | // block #xD800-#xDFFF, #xFFFE, and #xFFFF. | ||||||||||||
675 | inline QuotingType needsQuotes(StringRef S) { | ||||||||||||
676 | if (S.empty()) | ||||||||||||
677 | return QuotingType::Single; | ||||||||||||
678 | |||||||||||||
679 | QuotingType MaxQuotingNeeded = QuotingType::None; | ||||||||||||
680 | if (isSpace(static_cast<unsigned char>(S.front())) || | ||||||||||||
681 | isSpace(static_cast<unsigned char>(S.back()))) | ||||||||||||
682 | MaxQuotingNeeded = QuotingType::Single; | ||||||||||||
683 | if (isNull(S)) | ||||||||||||
684 | MaxQuotingNeeded = QuotingType::Single; | ||||||||||||
685 | if (isBool(S)) | ||||||||||||
686 | MaxQuotingNeeded = QuotingType::Single; | ||||||||||||
687 | if (isNumeric(S)) | ||||||||||||
688 | MaxQuotingNeeded = QuotingType::Single; | ||||||||||||
689 | |||||||||||||
690 | // 7.3.3 Plain Style | ||||||||||||
691 | // Plain scalars must not begin with most indicators, as this would cause | ||||||||||||
692 | // ambiguity with other YAML constructs. | ||||||||||||
693 | if (std::strchr(R"(-?:\,[]{}#&*!|>'"%@`)", S[0]) != nullptr) | ||||||||||||
694 | MaxQuotingNeeded = QuotingType::Single; | ||||||||||||
695 | |||||||||||||
696 | for (unsigned char C : S) { | ||||||||||||
697 | // Alphanum is safe. | ||||||||||||
698 | if (isAlnum(C)) | ||||||||||||
699 | continue; | ||||||||||||
700 | |||||||||||||
701 | switch (C) { | ||||||||||||
702 | // Safe scalar characters. | ||||||||||||
703 | case '_': | ||||||||||||
704 | case '-': | ||||||||||||
705 | case '^': | ||||||||||||
706 | case '.': | ||||||||||||
707 | case ',': | ||||||||||||
708 | case ' ': | ||||||||||||
709 | // TAB (0x9) is allowed in unquoted strings. | ||||||||||||
710 | case 0x9: | ||||||||||||
711 | continue; | ||||||||||||
712 | // LF(0xA) and CR(0xD) may delimit values and so require at least single | ||||||||||||
713 | // quotes. LLVM YAML parser cannot handle single quoted multiline so use | ||||||||||||
714 | // double quoting to produce valid YAML. | ||||||||||||
715 | case 0xA: | ||||||||||||
716 | case 0xD: | ||||||||||||
717 | return QuotingType::Double; | ||||||||||||
718 | // DEL (0x7F) are excluded from the allowed character range. | ||||||||||||
719 | case 0x7F: | ||||||||||||
720 | return QuotingType::Double; | ||||||||||||
721 | // Forward slash is allowed to be unquoted, but we quote it anyway. We have | ||||||||||||
722 | // many tests that use FileCheck against YAML output, and this output often | ||||||||||||
723 | // contains paths. If we quote backslashes but not forward slashes then | ||||||||||||
724 | // paths will come out either quoted or unquoted depending on which platform | ||||||||||||
725 | // the test is run on, making FileCheck comparisons difficult. | ||||||||||||
726 | case '/': | ||||||||||||
727 | default: { | ||||||||||||
728 | // C0 control block (0x0 - 0x1F) is excluded from the allowed character | ||||||||||||
729 | // range. | ||||||||||||
730 | if (C <= 0x1F) | ||||||||||||
731 | return QuotingType::Double; | ||||||||||||
732 | |||||||||||||
733 | // Always double quote UTF-8. | ||||||||||||
734 | if ((C & 0x80) != 0) | ||||||||||||
735 | return QuotingType::Double; | ||||||||||||
736 | |||||||||||||
737 | // The character is not safe, at least simple quoting needed. | ||||||||||||
738 | MaxQuotingNeeded = QuotingType::Single; | ||||||||||||
739 | } | ||||||||||||
740 | } | ||||||||||||
741 | } | ||||||||||||
742 | |||||||||||||
743 | return MaxQuotingNeeded; | ||||||||||||
744 | } | ||||||||||||
745 | |||||||||||||
746 | template <typename T, typename Context> | ||||||||||||
747 | struct missingTraits | ||||||||||||
748 | : public std::integral_constant<bool, | ||||||||||||
749 | !has_ScalarEnumerationTraits<T>::value && | ||||||||||||
750 | !has_ScalarBitSetTraits<T>::value && | ||||||||||||
751 | !has_ScalarTraits<T>::value && | ||||||||||||
752 | !has_BlockScalarTraits<T>::value && | ||||||||||||
753 | !has_TaggedScalarTraits<T>::value && | ||||||||||||
754 | !has_MappingTraits<T, Context>::value && | ||||||||||||
755 | !has_SequenceTraits<T>::value && | ||||||||||||
756 | !has_CustomMappingTraits<T>::value && | ||||||||||||
757 | !has_DocumentListTraits<T>::value && | ||||||||||||
758 | !has_PolymorphicTraits<T>::value> {}; | ||||||||||||
759 | |||||||||||||
760 | template <typename T, typename Context> | ||||||||||||
761 | struct validatedMappingTraits | ||||||||||||
762 | : public std::integral_constant< | ||||||||||||
763 | bool, has_MappingTraits<T, Context>::value && | ||||||||||||
764 | has_MappingValidateTraits<T, Context>::value> {}; | ||||||||||||
765 | |||||||||||||
766 | template <typename T, typename Context> | ||||||||||||
767 | struct unvalidatedMappingTraits | ||||||||||||
768 | : public std::integral_constant< | ||||||||||||
769 | bool, has_MappingTraits<T, Context>::value && | ||||||||||||
770 | !has_MappingValidateTraits<T, Context>::value> {}; | ||||||||||||
771 | |||||||||||||
772 | // Base class for Input and Output. | ||||||||||||
773 | class IO { | ||||||||||||
774 | public: | ||||||||||||
775 | IO(void *Ctxt = nullptr); | ||||||||||||
776 | virtual ~IO(); | ||||||||||||
777 | |||||||||||||
778 | virtual bool outputting() const = 0; | ||||||||||||
779 | |||||||||||||
780 | virtual unsigned beginSequence() = 0; | ||||||||||||
781 | virtual bool preflightElement(unsigned, void *&) = 0; | ||||||||||||
782 | virtual void postflightElement(void*) = 0; | ||||||||||||
783 | virtual void endSequence() = 0; | ||||||||||||
784 | virtual bool canElideEmptySequence() = 0; | ||||||||||||
785 | |||||||||||||
786 | virtual unsigned beginFlowSequence() = 0; | ||||||||||||
787 | virtual bool preflightFlowElement(unsigned, void *&) = 0; | ||||||||||||
788 | virtual void postflightFlowElement(void*) = 0; | ||||||||||||
789 | virtual void endFlowSequence() = 0; | ||||||||||||
790 | |||||||||||||
791 | virtual bool mapTag(StringRef Tag, bool Default=false) = 0; | ||||||||||||
792 | virtual void beginMapping() = 0; | ||||||||||||
793 | virtual void endMapping() = 0; | ||||||||||||
794 | virtual bool preflightKey(const char*, bool, bool, bool &, void *&) = 0; | ||||||||||||
795 | virtual void postflightKey(void*) = 0; | ||||||||||||
796 | virtual std::vector<StringRef> keys() = 0; | ||||||||||||
797 | |||||||||||||
798 | virtual void beginFlowMapping() = 0; | ||||||||||||
799 | virtual void endFlowMapping() = 0; | ||||||||||||
800 | |||||||||||||
801 | virtual void beginEnumScalar() = 0; | ||||||||||||
802 | virtual bool matchEnumScalar(const char*, bool) = 0; | ||||||||||||
803 | virtual bool matchEnumFallback() = 0; | ||||||||||||
804 | virtual void endEnumScalar() = 0; | ||||||||||||
805 | |||||||||||||
806 | virtual bool beginBitSetScalar(bool &) = 0; | ||||||||||||
807 | virtual bool bitSetMatch(const char*, bool) = 0; | ||||||||||||
808 | virtual void endBitSetScalar() = 0; | ||||||||||||
809 | |||||||||||||
810 | virtual void scalarString(StringRef &, QuotingType) = 0; | ||||||||||||
811 | virtual void blockScalarString(StringRef &) = 0; | ||||||||||||
812 | virtual void scalarTag(std::string &) = 0; | ||||||||||||
813 | |||||||||||||
814 | virtual NodeKind getNodeKind() = 0; | ||||||||||||
815 | |||||||||||||
816 | virtual void setError(const Twine &) = 0; | ||||||||||||
817 | virtual void setAllowUnknownKeys(bool Allow); | ||||||||||||
818 | |||||||||||||
819 | template <typename T> | ||||||||||||
820 | void enumCase(T &Val, const char* Str, const T ConstVal) { | ||||||||||||
821 | if ( matchEnumScalar(Str, outputting() && Val == ConstVal) ) { | ||||||||||||
822 | Val = ConstVal; | ||||||||||||
823 | } | ||||||||||||
824 | } | ||||||||||||
825 | |||||||||||||
826 | // allow anonymous enum values to be used with LLVM_YAML_STRONG_TYPEDEF | ||||||||||||
827 | template <typename T> | ||||||||||||
828 | void enumCase(T &Val, const char* Str, const uint32_t ConstVal) { | ||||||||||||
829 | if ( matchEnumScalar(Str, outputting() && Val == static_cast<T>(ConstVal)) ) { | ||||||||||||
830 | Val = ConstVal; | ||||||||||||
831 | } | ||||||||||||
832 | } | ||||||||||||
833 | |||||||||||||
834 | template <typename FBT, typename T> | ||||||||||||
835 | void enumFallback(T &Val) { | ||||||||||||
836 | if (matchEnumFallback()) { | ||||||||||||
837 | EmptyContext Context; | ||||||||||||
838 | // FIXME: Force integral conversion to allow strong typedefs to convert. | ||||||||||||
839 | FBT Res = static_cast<typename FBT::BaseType>(Val); | ||||||||||||
840 | yamlize(*this, Res, true, Context); | ||||||||||||
841 | Val = static_cast<T>(static_cast<typename FBT::BaseType>(Res)); | ||||||||||||
842 | } | ||||||||||||
843 | } | ||||||||||||
844 | |||||||||||||
845 | template <typename T> | ||||||||||||
846 | void bitSetCase(T &Val, const char* Str, const T ConstVal) { | ||||||||||||
847 | if ( bitSetMatch(Str, outputting() && (Val & ConstVal) == ConstVal) ) { | ||||||||||||
848 | Val = static_cast<T>(Val | ConstVal); | ||||||||||||
849 | } | ||||||||||||
850 | } | ||||||||||||
851 | |||||||||||||
852 | // allow anonymous enum values to be used with LLVM_YAML_STRONG_TYPEDEF | ||||||||||||
853 | template <typename T> | ||||||||||||
854 | void bitSetCase(T &Val, const char* Str, const uint32_t ConstVal) { | ||||||||||||
855 | if ( bitSetMatch(Str, outputting() && (Val & ConstVal) == ConstVal) ) { | ||||||||||||
856 | Val = static_cast<T>(Val | ConstVal); | ||||||||||||
857 | } | ||||||||||||
858 | } | ||||||||||||
859 | |||||||||||||
860 | template <typename T> | ||||||||||||
861 | void maskedBitSetCase(T &Val, const char *Str, T ConstVal, T Mask) { | ||||||||||||
862 | if (bitSetMatch(Str, outputting() && (Val & Mask) == ConstVal)) | ||||||||||||
863 | Val = Val | ConstVal; | ||||||||||||
864 | } | ||||||||||||
865 | |||||||||||||
866 | template <typename T> | ||||||||||||
867 | void maskedBitSetCase(T &Val, const char *Str, uint32_t ConstVal, | ||||||||||||
868 | uint32_t Mask) { | ||||||||||||
869 | if (bitSetMatch(Str, outputting() && (Val & Mask) == ConstVal)) | ||||||||||||
870 | Val = Val | ConstVal; | ||||||||||||
871 | } | ||||||||||||
872 | |||||||||||||
873 | void *getContext() const; | ||||||||||||
874 | void setContext(void *); | ||||||||||||
875 | |||||||||||||
876 | template <typename T> void mapRequired(const char *Key, T &Val) { | ||||||||||||
877 | EmptyContext Ctx; | ||||||||||||
878 | this->processKey(Key, Val, true, Ctx); | ||||||||||||
879 | } | ||||||||||||
880 | |||||||||||||
881 | template <typename T, typename Context> | ||||||||||||
882 | void mapRequired(const char *Key, T &Val, Context &Ctx) { | ||||||||||||
883 | this->processKey(Key, Val, true, Ctx); | ||||||||||||
884 | } | ||||||||||||
885 | |||||||||||||
886 | template <typename T> void mapOptional(const char *Key, T &Val) { | ||||||||||||
887 | EmptyContext Ctx; | ||||||||||||
888 | mapOptionalWithContext(Key, Val, Ctx); | ||||||||||||
889 | } | ||||||||||||
890 | |||||||||||||
891 | template <typename T, typename DefaultT> | ||||||||||||
892 | void mapOptional(const char *Key, T &Val, const DefaultT &Default) { | ||||||||||||
893 | EmptyContext Ctx; | ||||||||||||
894 | mapOptionalWithContext(Key, Val, Default, Ctx); | ||||||||||||
895 | } | ||||||||||||
896 | |||||||||||||
897 | template <typename T, typename Context> | ||||||||||||
898 | std::enable_if_t<has_SequenceTraits<T>::value, void> | ||||||||||||
899 | mapOptionalWithContext(const char *Key, T &Val, Context &Ctx) { | ||||||||||||
900 | // omit key/value instead of outputting empty sequence | ||||||||||||
901 | if (this->canElideEmptySequence() && !(Val.begin() != Val.end())) | ||||||||||||
902 | return; | ||||||||||||
903 | this->processKey(Key, Val, false, Ctx); | ||||||||||||
904 | } | ||||||||||||
905 | |||||||||||||
906 | template <typename T, typename Context> | ||||||||||||
907 | void mapOptionalWithContext(const char *Key, Optional<T> &Val, Context &Ctx) { | ||||||||||||
908 | this->processKeyWithDefault(Key, Val, Optional<T>(), /*Required=*/false, | ||||||||||||
909 | Ctx); | ||||||||||||
910 | } | ||||||||||||
911 | |||||||||||||
912 | template <typename T, typename Context> | ||||||||||||
913 | std::enable_if_t<!has_SequenceTraits<T>::value, void> | ||||||||||||
914 | mapOptionalWithContext(const char *Key, T &Val, Context &Ctx) { | ||||||||||||
915 | this->processKey(Key, Val, false, Ctx); | ||||||||||||
916 | } | ||||||||||||
917 | |||||||||||||
918 | template <typename T, typename Context, typename DefaultT> | ||||||||||||
919 | void mapOptionalWithContext(const char *Key, T &Val, const DefaultT &Default, | ||||||||||||
920 | Context &Ctx) { | ||||||||||||
921 | static_assert(std::is_convertible<DefaultT, T>::value, | ||||||||||||
922 | "Default type must be implicitly convertible to value type!"); | ||||||||||||
923 | this->processKeyWithDefault(Key, Val, static_cast<const T &>(Default), | ||||||||||||
924 | false, Ctx); | ||||||||||||
925 | } | ||||||||||||
926 | |||||||||||||
927 | private: | ||||||||||||
928 | template <typename T, typename Context> | ||||||||||||
929 | void processKeyWithDefault(const char *Key, Optional<T> &Val, | ||||||||||||
930 | const Optional<T> &DefaultValue, bool Required, | ||||||||||||
931 | Context &Ctx); | ||||||||||||
932 | |||||||||||||
933 | template <typename T, typename Context> | ||||||||||||
934 | void processKeyWithDefault(const char *Key, T &Val, const T &DefaultValue, | ||||||||||||
935 | bool Required, Context &Ctx) { | ||||||||||||
936 | void *SaveInfo; | ||||||||||||
937 | bool UseDefault; | ||||||||||||
938 | const bool sameAsDefault = outputting() && Val == DefaultValue; | ||||||||||||
939 | if ( this->preflightKey(Key, Required, sameAsDefault, UseDefault, | ||||||||||||
940 | SaveInfo) ) { | ||||||||||||
941 | yamlize(*this, Val, Required, Ctx); | ||||||||||||
942 | this->postflightKey(SaveInfo); | ||||||||||||
943 | } | ||||||||||||
944 | else { | ||||||||||||
945 | if ( UseDefault ) | ||||||||||||
946 | Val = DefaultValue; | ||||||||||||
947 | } | ||||||||||||
948 | } | ||||||||||||
949 | |||||||||||||
950 | template <typename T, typename Context> | ||||||||||||
951 | void processKey(const char *Key, T &Val, bool Required, Context &Ctx) { | ||||||||||||
952 | void *SaveInfo; | ||||||||||||
953 | bool UseDefault; | ||||||||||||
954 | if ( this->preflightKey(Key, Required, false, UseDefault, SaveInfo) ) { | ||||||||||||
955 | yamlize(*this, Val, Required, Ctx); | ||||||||||||
956 | this->postflightKey(SaveInfo); | ||||||||||||
957 | } | ||||||||||||
958 | } | ||||||||||||
959 | |||||||||||||
960 | private: | ||||||||||||
961 | void *Ctxt; | ||||||||||||
962 | }; | ||||||||||||
963 | |||||||||||||
964 | namespace detail { | ||||||||||||
965 | |||||||||||||
966 | template <typename T, typename Context> | ||||||||||||
967 | void doMapping(IO &io, T &Val, Context &Ctx) { | ||||||||||||
968 | MappingContextTraits<T, Context>::mapping(io, Val, Ctx); | ||||||||||||
969 | } | ||||||||||||
970 | |||||||||||||
971 | template <typename T> void doMapping(IO &io, T &Val, EmptyContext &Ctx) { | ||||||||||||
972 | MappingTraits<T>::mapping(io, Val); | ||||||||||||
973 | } | ||||||||||||
974 | |||||||||||||
975 | } // end namespace detail | ||||||||||||
976 | |||||||||||||
977 | template <typename T> | ||||||||||||
978 | std::enable_if_t<has_ScalarEnumerationTraits<T>::value, void> | ||||||||||||
979 | yamlize(IO &io, T &Val, bool, EmptyContext &Ctx) { | ||||||||||||
980 | io.beginEnumScalar(); | ||||||||||||
981 | ScalarEnumerationTraits<T>::enumeration(io, Val); | ||||||||||||
982 | io.endEnumScalar(); | ||||||||||||
983 | } | ||||||||||||
984 | |||||||||||||
985 | template <typename T> | ||||||||||||
986 | std::enable_if_t<has_ScalarBitSetTraits<T>::value, void> | ||||||||||||
987 | yamlize(IO &io, T &Val, bool, EmptyContext &Ctx) { | ||||||||||||
988 | bool DoClear; | ||||||||||||
989 | if ( io.beginBitSetScalar(DoClear) ) { | ||||||||||||
990 | if ( DoClear ) | ||||||||||||
991 | Val = T(); | ||||||||||||
992 | ScalarBitSetTraits<T>::bitset(io, Val); | ||||||||||||
993 | io.endBitSetScalar(); | ||||||||||||
994 | } | ||||||||||||
995 | } | ||||||||||||
996 | |||||||||||||
997 | template <typename T> | ||||||||||||
998 | std::enable_if_t<has_ScalarTraits<T>::value, void> yamlize(IO &io, T &Val, bool, | ||||||||||||
999 | EmptyContext &Ctx) { | ||||||||||||
1000 | if ( io.outputting() ) { | ||||||||||||
1001 | std::string Storage; | ||||||||||||
1002 | raw_string_ostream Buffer(Storage); | ||||||||||||
1003 | ScalarTraits<T>::output(Val, io.getContext(), Buffer); | ||||||||||||
1004 | StringRef Str = Buffer.str(); | ||||||||||||
1005 | io.scalarString(Str, ScalarTraits<T>::mustQuote(Str)); | ||||||||||||
1006 | } | ||||||||||||
1007 | else { | ||||||||||||
1008 | StringRef Str; | ||||||||||||
1009 | io.scalarString(Str, ScalarTraits<T>::mustQuote(Str)); | ||||||||||||
1010 | StringRef Result = ScalarTraits<T>::input(Str, io.getContext(), Val); | ||||||||||||
1011 | if ( !Result.empty() ) { | ||||||||||||
1012 | io.setError(Twine(Result)); | ||||||||||||
1013 | } | ||||||||||||
1014 | } | ||||||||||||
1015 | } | ||||||||||||
1016 | |||||||||||||
1017 | template <typename T> | ||||||||||||
1018 | std::enable_if_t<has_BlockScalarTraits<T>::value, void> | ||||||||||||
1019 | yamlize(IO &YamlIO, T &Val, bool, EmptyContext &Ctx) { | ||||||||||||
1020 | if (YamlIO.outputting()) { | ||||||||||||
1021 | std::string Storage; | ||||||||||||
1022 | raw_string_ostream Buffer(Storage); | ||||||||||||
1023 | BlockScalarTraits<T>::output(Val, YamlIO.getContext(), Buffer); | ||||||||||||
1024 | StringRef Str = Buffer.str(); | ||||||||||||
1025 | YamlIO.blockScalarString(Str); | ||||||||||||
1026 | } else { | ||||||||||||
1027 | StringRef Str; | ||||||||||||
1028 | YamlIO.blockScalarString(Str); | ||||||||||||
1029 | StringRef Result = | ||||||||||||
1030 | BlockScalarTraits<T>::input(Str, YamlIO.getContext(), Val); | ||||||||||||
1031 | if (!Result.empty()) | ||||||||||||
1032 | YamlIO.setError(Twine(Result)); | ||||||||||||
1033 | } | ||||||||||||
1034 | } | ||||||||||||
1035 | |||||||||||||
1036 | template <typename T> | ||||||||||||
1037 | std::enable_if_t<has_TaggedScalarTraits<T>::value, void> | ||||||||||||
1038 | yamlize(IO &io, T &Val, bool, EmptyContext &Ctx) { | ||||||||||||
1039 | if (io.outputting()) { | ||||||||||||
1040 | std::string ScalarStorage, TagStorage; | ||||||||||||
1041 | raw_string_ostream ScalarBuffer(ScalarStorage), TagBuffer(TagStorage); | ||||||||||||
1042 | TaggedScalarTraits<T>::output(Val, io.getContext(), ScalarBuffer, | ||||||||||||
1043 | TagBuffer); | ||||||||||||
1044 | io.scalarTag(TagBuffer.str()); | ||||||||||||
1045 | StringRef ScalarStr = ScalarBuffer.str(); | ||||||||||||
1046 | io.scalarString(ScalarStr, | ||||||||||||
1047 | TaggedScalarTraits<T>::mustQuote(Val, ScalarStr)); | ||||||||||||
1048 | } else { | ||||||||||||
1049 | std::string Tag; | ||||||||||||
1050 | io.scalarTag(Tag); | ||||||||||||
1051 | StringRef Str; | ||||||||||||
1052 | io.scalarString(Str, QuotingType::None); | ||||||||||||
1053 | StringRef Result = | ||||||||||||
1054 | TaggedScalarTraits<T>::input(Str, Tag, io.getContext(), Val); | ||||||||||||
1055 | if (!Result.empty()) { | ||||||||||||
1056 | io.setError(Twine(Result)); | ||||||||||||
1057 | } | ||||||||||||
1058 | } | ||||||||||||
1059 | } | ||||||||||||
1060 | |||||||||||||
1061 | template <typename T, typename Context> | ||||||||||||
1062 | std::enable_if_t<validatedMappingTraits<T, Context>::value, void> | ||||||||||||
1063 | yamlize(IO &io, T &Val, bool, Context &Ctx) { | ||||||||||||
1064 | if (has_FlowTraits<MappingTraits<T>>::value) | ||||||||||||
1065 | io.beginFlowMapping(); | ||||||||||||
1066 | else | ||||||||||||
1067 | io.beginMapping(); | ||||||||||||
1068 | if (io.outputting()) { | ||||||||||||
1069 | std::string Err = MappingTraits<T>::validate(io, Val); | ||||||||||||
1070 | if (!Err.empty()) { | ||||||||||||
1071 | errs() << Err << "\n"; | ||||||||||||
1072 | assert(Err.empty() && "invalid struct trying to be written as yaml")(static_cast <bool> (Err.empty() && "invalid struct trying to be written as yaml" ) ? void (0) : __assert_fail ("Err.empty() && \"invalid struct trying to be written as yaml\"" , "llvm/include/llvm/Support/YAMLTraits.h", 1072, __extension__ __PRETTY_FUNCTION__)); | ||||||||||||
1073 | } | ||||||||||||
1074 | } | ||||||||||||
1075 | detail::doMapping(io, Val, Ctx); | ||||||||||||
1076 | if (!io.outputting()) { | ||||||||||||
1077 | std::string Err = MappingTraits<T>::validate(io, Val); | ||||||||||||
1078 | if (!Err.empty()) | ||||||||||||
1079 | io.setError(Err); | ||||||||||||
1080 | } | ||||||||||||
1081 | if (has_FlowTraits<MappingTraits<T>>::value) | ||||||||||||
1082 | io.endFlowMapping(); | ||||||||||||
1083 | else | ||||||||||||
1084 | io.endMapping(); | ||||||||||||
1085 | } | ||||||||||||
1086 | |||||||||||||
1087 | template <typename T, typename Context> | ||||||||||||
1088 | std::enable_if_t<!has_MappingEnumInputTraits<T, Context>::value, bool> | ||||||||||||
1089 | yamlizeMappingEnumInput(IO &io, T &Val) { | ||||||||||||
1090 | return false; | ||||||||||||
1091 | } | ||||||||||||
1092 | |||||||||||||
1093 | template <typename T, typename Context> | ||||||||||||
1094 | std::enable_if_t<has_MappingEnumInputTraits<T, Context>::value, bool> | ||||||||||||
1095 | yamlizeMappingEnumInput(IO &io, T &Val) { | ||||||||||||
1096 | if (io.outputting()) | ||||||||||||
1097 | return false; | ||||||||||||
1098 | |||||||||||||
1099 | io.beginEnumScalar(); | ||||||||||||
1100 | MappingTraits<T>::enumInput(io, Val); | ||||||||||||
1101 | bool Matched = !io.matchEnumFallback(); | ||||||||||||
1102 | io.endEnumScalar(); | ||||||||||||
1103 | return Matched; | ||||||||||||
1104 | } | ||||||||||||
1105 | |||||||||||||
1106 | template <typename T, typename Context> | ||||||||||||
1107 | std::enable_if_t<unvalidatedMappingTraits<T, Context>::value, void> | ||||||||||||
1108 | yamlize(IO &io, T &Val, bool, Context &Ctx) { | ||||||||||||
1109 | if (yamlizeMappingEnumInput<T, Context>(io, Val)) | ||||||||||||
1110 | return; | ||||||||||||
1111 | if (has_FlowTraits<MappingTraits<T>>::value
| ||||||||||||
1112 | io.beginFlowMapping(); | ||||||||||||
1113 | detail::doMapping(io, Val, Ctx); | ||||||||||||
1114 | io.endFlowMapping(); | ||||||||||||
1115 | } else { | ||||||||||||
1116 | io.beginMapping(); | ||||||||||||
1117 | detail::doMapping(io, Val, Ctx); | ||||||||||||
1118 | io.endMapping(); | ||||||||||||
1119 | } | ||||||||||||
1120 | } | ||||||||||||
1121 | |||||||||||||
1122 | template <typename T> | ||||||||||||
1123 | std::enable_if_t<has_CustomMappingTraits<T>::value, void> | ||||||||||||
1124 | yamlize(IO &io, T &Val, bool, EmptyContext &Ctx) { | ||||||||||||
1125 | if ( io.outputting() ) { | ||||||||||||
1126 | io.beginMapping(); | ||||||||||||
1127 | CustomMappingTraits<T>::output(io, Val); | ||||||||||||
1128 | io.endMapping(); | ||||||||||||
1129 | } else { | ||||||||||||
1130 | io.beginMapping(); | ||||||||||||
1131 | for (StringRef key : io.keys()) | ||||||||||||
1132 | CustomMappingTraits<T>::inputOne(io, key, Val); | ||||||||||||
1133 | io.endMapping(); | ||||||||||||
1134 | } | ||||||||||||
1135 | } | ||||||||||||
1136 | |||||||||||||
1137 | template <typename T> | ||||||||||||
1138 | std::enable_if_t<has_PolymorphicTraits<T>::value, void> | ||||||||||||
1139 | yamlize(IO &io, T &Val, bool, EmptyContext &Ctx) { | ||||||||||||
1140 | switch (io.outputting() ? PolymorphicTraits<T>::getKind(Val) | ||||||||||||
1141 | : io.getNodeKind()) { | ||||||||||||
1142 | case NodeKind::Scalar: | ||||||||||||
1143 | return yamlize(io, PolymorphicTraits<T>::getAsScalar(Val), true, Ctx); | ||||||||||||
1144 | case NodeKind::Map: | ||||||||||||
1145 | return yamlize(io, PolymorphicTraits<T>::getAsMap(Val), true, Ctx); | ||||||||||||
1146 | case NodeKind::Sequence: | ||||||||||||
1147 | return yamlize(io, PolymorphicTraits<T>::getAsSequence(Val), true, Ctx); | ||||||||||||
1148 | } | ||||||||||||
1149 | } | ||||||||||||
1150 | |||||||||||||
1151 | template <typename T> | ||||||||||||
1152 | std::enable_if_t<missingTraits<T, EmptyContext>::value, void> | ||||||||||||
1153 | yamlize(IO &io, T &Val, bool, EmptyContext &Ctx) { | ||||||||||||
1154 | char missing_yaml_trait_for_type[sizeof(MissingTrait<T>)]; | ||||||||||||
1155 | } | ||||||||||||
1156 | |||||||||||||
1157 | template <typename T, typename Context> | ||||||||||||
1158 | std::enable_if_t<has_SequenceTraits<T>::value, void> | ||||||||||||
1159 | yamlize(IO &io, T &Seq, bool, Context &Ctx) { | ||||||||||||
1160 | if ( has_FlowTraits< SequenceTraits<T>>::value ) { | ||||||||||||
1161 | unsigned incnt = io.beginFlowSequence(); | ||||||||||||
1162 | unsigned count = io.outputting() ? SequenceTraits<T>::size(io, Seq) : incnt; | ||||||||||||
1163 | for(unsigned i=0; i < count; ++i) { | ||||||||||||
1164 | void *SaveInfo; | ||||||||||||
1165 | if ( io.preflightFlowElement(i, SaveInfo) ) { | ||||||||||||
1166 | yamlize(io, SequenceTraits<T>::element(io, Seq, i), true, Ctx); | ||||||||||||
1167 | io.postflightFlowElement(SaveInfo); | ||||||||||||
1168 | } | ||||||||||||
1169 | } | ||||||||||||
1170 | io.endFlowSequence(); | ||||||||||||
1171 | } | ||||||||||||
1172 | else { | ||||||||||||
1173 | unsigned incnt = io.beginSequence(); | ||||||||||||
1174 | unsigned count = io.outputting() ? SequenceTraits<T>::size(io, Seq) : incnt; | ||||||||||||
1175 | for(unsigned i=0; i < count; ++i) { | ||||||||||||
1176 | void *SaveInfo; | ||||||||||||
1177 | if ( io.preflightElement(i, SaveInfo) ) { | ||||||||||||
1178 | yamlize(io, SequenceTraits<T>::element(io, Seq, i), true, Ctx); | ||||||||||||
1179 | io.postflightElement(SaveInfo); | ||||||||||||
1180 | } | ||||||||||||
1181 | } | ||||||||||||
1182 | io.endSequence(); | ||||||||||||
1183 | } | ||||||||||||
1184 | } | ||||||||||||
1185 | |||||||||||||
1186 | template<> | ||||||||||||
1187 | struct ScalarTraits<bool> { | ||||||||||||
1188 | static void output(const bool &, void* , raw_ostream &); | ||||||||||||
1189 | static StringRef input(StringRef, void *, bool &); | ||||||||||||
1190 | static QuotingType mustQuote(StringRef) { return QuotingType::None; } | ||||||||||||
1191 | }; | ||||||||||||
1192 | |||||||||||||
1193 | template<> | ||||||||||||
1194 | struct ScalarTraits<StringRef> { | ||||||||||||
1195 | static void output(const StringRef &, void *, raw_ostream &); | ||||||||||||
1196 | static StringRef input(StringRef, void *, StringRef &); | ||||||||||||
1197 | static QuotingType mustQuote(StringRef S) { return needsQuotes(S); } | ||||||||||||
1198 | }; | ||||||||||||
1199 | |||||||||||||
1200 | template<> | ||||||||||||
1201 | struct ScalarTraits<std::string> { | ||||||||||||
1202 | static void output(const std::string &, void *, raw_ostream &); | ||||||||||||
1203 | static StringRef input(StringRef, void *, std::string &); | ||||||||||||
1204 | static QuotingType mustQuote(StringRef S) { return needsQuotes(S); } | ||||||||||||
1205 | }; | ||||||||||||
1206 | |||||||||||||
1207 | template<> | ||||||||||||
1208 | struct ScalarTraits<uint8_t> { | ||||||||||||
1209 | static void output(const uint8_t &, void *, raw_ostream &); | ||||||||||||
1210 | static StringRef input(StringRef, void *, uint8_t &); | ||||||||||||
1211 | static QuotingType mustQuote(StringRef) { return QuotingType::None; } | ||||||||||||
1212 | }; | ||||||||||||
1213 | |||||||||||||
1214 | template<> | ||||||||||||
1215 | struct ScalarTraits<uint16_t> { | ||||||||||||
1216 | static void output(const uint16_t &, void *, raw_ostream &); | ||||||||||||
1217 | static StringRef input(StringRef, void *, uint16_t &); | ||||||||||||
1218 | static QuotingType mustQuote(StringRef) { return QuotingType::None; } | ||||||||||||
1219 | }; | ||||||||||||
1220 | |||||||||||||
1221 | template<> | ||||||||||||
1222 | struct ScalarTraits<uint32_t> { | ||||||||||||
1223 | static void output(const uint32_t &, void *, raw_ostream &); | ||||||||||||
1224 | static StringRef input(StringRef, void *, uint32_t &); | ||||||||||||
1225 | static QuotingType mustQuote(StringRef) { return QuotingType::None; } | ||||||||||||
1226 | }; | ||||||||||||
1227 | |||||||||||||
1228 | template<> | ||||||||||||
1229 | struct ScalarTraits<uint64_t> { | ||||||||||||
1230 | static void output(const uint64_t &, void *, raw_ostream &); | ||||||||||||
1231 | static StringRef input(StringRef, void *, uint64_t &); | ||||||||||||
1232 | static QuotingType mustQuote(StringRef) { return QuotingType::None; } | ||||||||||||
1233 | }; | ||||||||||||
1234 | |||||||||||||
1235 | template<> | ||||||||||||
1236 | struct ScalarTraits<int8_t> { | ||||||||||||
1237 | static void output(const int8_t &, void *, raw_ostream &); | ||||||||||||
1238 | static StringRef input(StringRef, void *, int8_t &); | ||||||||||||
1239 | static QuotingType mustQuote(StringRef) { return QuotingType::None; } | ||||||||||||
1240 | }; | ||||||||||||
1241 | |||||||||||||
1242 | template<> | ||||||||||||
1243 | struct ScalarTraits<int16_t> { | ||||||||||||
1244 | static void output(const int16_t &, void *, raw_ostream &); | ||||||||||||
1245 | static StringRef input(StringRef, void *, int16_t &); | ||||||||||||
1246 | static QuotingType mustQuote(StringRef) { return QuotingType::None; } | ||||||||||||
1247 | }; | ||||||||||||
1248 | |||||||||||||
1249 | template<> | ||||||||||||
1250 | struct ScalarTraits<int32_t> { | ||||||||||||
1251 | static void output(const int32_t &, void *, raw_ostream &); | ||||||||||||
1252 | static StringRef input(StringRef, void *, int32_t &); | ||||||||||||
1253 | static QuotingType mustQuote(StringRef) { return QuotingType::None; } | ||||||||||||
1254 | }; | ||||||||||||
1255 | |||||||||||||
1256 | template<> | ||||||||||||
1257 | struct ScalarTraits<int64_t> { | ||||||||||||
1258 | static void output(const int64_t &, void *, raw_ostream &); | ||||||||||||
1259 | static StringRef input(StringRef, void *, int64_t &); | ||||||||||||
1260 | static QuotingType mustQuote(StringRef) { return QuotingType::None; } | ||||||||||||
1261 | }; | ||||||||||||
1262 | |||||||||||||
1263 | template<> | ||||||||||||
1264 | struct ScalarTraits<float> { | ||||||||||||
1265 | static void output(const float &, void *, raw_ostream &); | ||||||||||||
1266 | static StringRef input(StringRef, void *, float &); | ||||||||||||
1267 | static QuotingType mustQuote(StringRef) { return QuotingType::None; } | ||||||||||||
1268 | }; | ||||||||||||
1269 | |||||||||||||
1270 | template<> | ||||||||||||
1271 | struct ScalarTraits<double> { | ||||||||||||
1272 | static void output(const double &, void *, raw_ostream &); | ||||||||||||
1273 | static StringRef input(StringRef, void *, double &); | ||||||||||||
1274 | static QuotingType mustQuote(StringRef) { return QuotingType::None; } | ||||||||||||
1275 | }; | ||||||||||||
1276 | |||||||||||||
1277 | // For endian types, we use existing scalar Traits class for the underlying | ||||||||||||
1278 | // type. This way endian aware types are supported whenever the traits are | ||||||||||||
1279 | // defined for the underlying type. | ||||||||||||
1280 | template <typename value_type, support::endianness endian, size_t alignment> | ||||||||||||
1281 | struct ScalarTraits<support::detail::packed_endian_specific_integral< | ||||||||||||
1282 | value_type, endian, alignment>, | ||||||||||||
1283 | std::enable_if_t<has_ScalarTraits<value_type>::value>> { | ||||||||||||
1284 | using endian_type = | ||||||||||||
1285 | support::detail::packed_endian_specific_integral<value_type, endian, | ||||||||||||
1286 | alignment>; | ||||||||||||
1287 | |||||||||||||
1288 | static void output(const endian_type &E, void *Ctx, raw_ostream &Stream) { | ||||||||||||
1289 | ScalarTraits<value_type>::output(static_cast<value_type>(E), Ctx, Stream); | ||||||||||||
1290 | } | ||||||||||||
1291 | |||||||||||||
1292 | static StringRef input(StringRef Str, void *Ctx, endian_type &E) { | ||||||||||||
1293 | value_type V; | ||||||||||||
1294 | auto R = ScalarTraits<value_type>::input(Str, Ctx, V); | ||||||||||||
1295 | E = static_cast<endian_type>(V); | ||||||||||||
1296 | return R; | ||||||||||||
1297 | } | ||||||||||||
1298 | |||||||||||||
1299 | static QuotingType mustQuote(StringRef Str) { | ||||||||||||
1300 | return ScalarTraits<value_type>::mustQuote(Str); | ||||||||||||
1301 | } | ||||||||||||
1302 | }; | ||||||||||||
1303 | |||||||||||||
1304 | template <typename value_type, support::endianness endian, size_t alignment> | ||||||||||||
1305 | struct ScalarEnumerationTraits< | ||||||||||||
1306 | support::detail::packed_endian_specific_integral<value_type, endian, | ||||||||||||
1307 | alignment>, | ||||||||||||
1308 | std::enable_if_t<has_ScalarEnumerationTraits<value_type>::value>> { | ||||||||||||
1309 | using endian_type = | ||||||||||||
1310 | support::detail::packed_endian_specific_integral<value_type, endian, | ||||||||||||
1311 | alignment>; | ||||||||||||
1312 | |||||||||||||
1313 | static void enumeration(IO &io, endian_type &E) { | ||||||||||||
1314 | value_type V = E; | ||||||||||||
1315 | ScalarEnumerationTraits<value_type>::enumeration(io, V); | ||||||||||||
1316 | E = V; | ||||||||||||
1317 | } | ||||||||||||
1318 | }; | ||||||||||||
1319 | |||||||||||||
1320 | template <typename value_type, support::endianness endian, size_t alignment> | ||||||||||||
1321 | struct ScalarBitSetTraits< | ||||||||||||
1322 | support::detail::packed_endian_specific_integral<value_type, endian, | ||||||||||||
1323 | alignment>, | ||||||||||||
1324 | std::enable_if_t<has_ScalarBitSetTraits<value_type>::value>> { | ||||||||||||
1325 | using endian_type = | ||||||||||||
1326 | support::detail::packed_endian_specific_integral<value_type, endian, | ||||||||||||
1327 | alignment>; | ||||||||||||
1328 | static void bitset(IO &io, endian_type &E) { | ||||||||||||
1329 | value_type V = E; | ||||||||||||
1330 | ScalarBitSetTraits<value_type>::bitset(io, V); | ||||||||||||
1331 | E = V; | ||||||||||||
1332 | } | ||||||||||||
1333 | }; | ||||||||||||
1334 | |||||||||||||
1335 | // Utility for use within MappingTraits<>::mapping() method | ||||||||||||
1336 | // to [de]normalize an object for use with YAML conversion. | ||||||||||||
1337 | template <typename TNorm, typename TFinal> | ||||||||||||
1338 | struct MappingNormalization { | ||||||||||||
1339 | MappingNormalization(IO &i_o, TFinal &Obj) | ||||||||||||
1340 | : io(i_o), BufPtr(nullptr), Result(Obj) { | ||||||||||||
1341 | if ( io.outputting() ) { | ||||||||||||
1342 | BufPtr = new (&Buffer) TNorm(io, Obj); | ||||||||||||
1343 | } | ||||||||||||
1344 | else { | ||||||||||||
1345 | BufPtr = new (&Buffer) TNorm(io); | ||||||||||||
1346 | } | ||||||||||||
1347 | } | ||||||||||||
1348 | |||||||||||||
1349 | ~MappingNormalization() { | ||||||||||||
1350 | if ( ! io.outputting() ) { | ||||||||||||
1351 | Result = BufPtr->denormalize(io); | ||||||||||||
1352 | } | ||||||||||||
1353 | BufPtr->~TNorm(); | ||||||||||||
1354 | } | ||||||||||||
1355 | |||||||||||||
1356 | TNorm* operator->() { return BufPtr; } | ||||||||||||
1357 | |||||||||||||
1358 | private: | ||||||||||||
1359 | using Storage = AlignedCharArrayUnion<TNorm>; | ||||||||||||
1360 | |||||||||||||
1361 | Storage Buffer; | ||||||||||||
1362 | IO &io; | ||||||||||||
1363 | TNorm *BufPtr; | ||||||||||||
1364 | TFinal &Result; | ||||||||||||
1365 | }; | ||||||||||||
1366 | |||||||||||||
1367 | // Utility for use within MappingTraits<>::mapping() method | ||||||||||||
1368 | // to [de]normalize an object for use with YAML conversion. | ||||||||||||
1369 | template <typename TNorm, typename TFinal> | ||||||||||||
1370 | struct MappingNormalizationHeap { | ||||||||||||
1371 | MappingNormalizationHeap(IO &i_o, TFinal &Obj, BumpPtrAllocator *allocator) | ||||||||||||
1372 | : io(i_o), Result(Obj) { | ||||||||||||
1373 | if ( io.outputting() ) { | ||||||||||||
1374 | BufPtr = new (&Buffer) TNorm(io, Obj); | ||||||||||||
1375 | } | ||||||||||||
1376 | else if (allocator) { | ||||||||||||
1377 | BufPtr = allocator->Allocate<TNorm>(); | ||||||||||||
1378 | new (BufPtr) TNorm(io); | ||||||||||||
1379 | } else { | ||||||||||||
1380 | BufPtr = new TNorm(io); | ||||||||||||
1381 | } | ||||||||||||
1382 | } | ||||||||||||
1383 | |||||||||||||
1384 | ~MappingNormalizationHeap() { | ||||||||||||
1385 | if ( io.outputting() ) { | ||||||||||||
1386 | BufPtr->~TNorm(); | ||||||||||||
1387 | } | ||||||||||||
1388 | else { | ||||||||||||
1389 | Result = BufPtr->denormalize(io); | ||||||||||||
1390 | } | ||||||||||||
1391 | } | ||||||||||||
1392 | |||||||||||||
1393 | TNorm* operator->() { return BufPtr; } | ||||||||||||
1394 | |||||||||||||
1395 | private: | ||||||||||||
1396 | using Storage = AlignedCharArrayUnion<TNorm>; | ||||||||||||
1397 | |||||||||||||
1398 | Storage Buffer; | ||||||||||||
1399 | IO &io; | ||||||||||||
1400 | TNorm *BufPtr = nullptr; | ||||||||||||
1401 | TFinal &Result; | ||||||||||||
1402 | }; | ||||||||||||
1403 | |||||||||||||
1404 | /// | ||||||||||||
1405 | /// The Input class is used to parse a yaml document into in-memory structs | ||||||||||||
1406 | /// and vectors. | ||||||||||||
1407 | /// | ||||||||||||
1408 | /// It works by using YAMLParser to do a syntax parse of the entire yaml | ||||||||||||
1409 | /// document, then the Input class builds a graph of HNodes which wraps | ||||||||||||
1410 | /// each yaml Node. The extra layer is buffering. The low level yaml | ||||||||||||
1411 | /// parser only lets you look at each node once. The buffering layer lets | ||||||||||||
1412 | /// you search and interate multiple times. This is necessary because | ||||||||||||
1413 | /// the mapRequired() method calls may not be in the same order | ||||||||||||
1414 | /// as the keys in the document. | ||||||||||||
1415 | /// | ||||||||||||
1416 | class Input : public IO { | ||||||||||||
1417 | public: | ||||||||||||
1418 | // Construct a yaml Input object from a StringRef and optional | ||||||||||||
1419 | // user-data. The DiagHandler can be specified to provide | ||||||||||||
1420 | // alternative error reporting. | ||||||||||||
1421 | Input(StringRef InputContent, | ||||||||||||
1422 | void *Ctxt = nullptr, | ||||||||||||
1423 | SourceMgr::DiagHandlerTy DiagHandler = nullptr, | ||||||||||||
1424 | void *DiagHandlerCtxt = nullptr); | ||||||||||||
1425 | Input(MemoryBufferRef Input, | ||||||||||||
1426 | void *Ctxt = nullptr, | ||||||||||||
1427 | SourceMgr::DiagHandlerTy DiagHandler = nullptr, | ||||||||||||
1428 | void *DiagHandlerCtxt = nullptr); | ||||||||||||
1429 | ~Input() override; | ||||||||||||
1430 | |||||||||||||
1431 | // Check if there was an syntax or semantic error during parsing. | ||||||||||||
1432 | std::error_code error(); | ||||||||||||
1433 | |||||||||||||
1434 | private: | ||||||||||||
1435 | bool outputting() const override; | ||||||||||||
1436 | bool mapTag(StringRef, bool) override; | ||||||||||||
1437 | void beginMapping() override; | ||||||||||||
1438 | void endMapping() override; | ||||||||||||
1439 | bool preflightKey(const char *, bool, bool, bool &, void *&) override; | ||||||||||||
1440 | void postflightKey(void *) override; | ||||||||||||
1441 | std::vector<StringRef> keys() override; | ||||||||||||
1442 | void beginFlowMapping() override; | ||||||||||||
1443 | void endFlowMapping() override; | ||||||||||||
1444 | unsigned beginSequence() override; | ||||||||||||
1445 | void endSequence() override; | ||||||||||||
1446 | bool preflightElement(unsigned index, void *&) override; | ||||||||||||
1447 | void postflightElement(void *) override; | ||||||||||||
1448 | unsigned beginFlowSequence() override; | ||||||||||||
1449 | bool preflightFlowElement(unsigned , void *&) override; | ||||||||||||
1450 | void postflightFlowElement(void *) override; | ||||||||||||
1451 | void endFlowSequence() override; | ||||||||||||
1452 | void beginEnumScalar() override; | ||||||||||||
1453 | bool matchEnumScalar(const char*, bool) override; | ||||||||||||
1454 | bool matchEnumFallback() override; | ||||||||||||
1455 | void endEnumScalar() override; | ||||||||||||
1456 | bool beginBitSetScalar(bool &) override; | ||||||||||||
1457 | bool bitSetMatch(const char *, bool ) override; | ||||||||||||
1458 | void endBitSetScalar() override; | ||||||||||||
1459 | void scalarString(StringRef &, QuotingType) override; | ||||||||||||
1460 | void blockScalarString(StringRef &) override; | ||||||||||||
1461 | void scalarTag(std::string &) override; | ||||||||||||
1462 | NodeKind getNodeKind() override; | ||||||||||||
1463 | void setError(const Twine &message) override; | ||||||||||||
1464 | bool canElideEmptySequence() override; | ||||||||||||
1465 | |||||||||||||
1466 | class HNode { | ||||||||||||
1467 | virtual void anchor(); | ||||||||||||
1468 | |||||||||||||
1469 | public: | ||||||||||||
1470 | HNode(Node *n) : _node(n) { } | ||||||||||||
1471 | virtual ~HNode() = default; | ||||||||||||
1472 | |||||||||||||
1473 | static bool classof(const HNode *) { return true; } | ||||||||||||
1474 | |||||||||||||
1475 | Node *_node; | ||||||||||||
1476 | }; | ||||||||||||
1477 | |||||||||||||
1478 | class EmptyHNode : public HNode { | ||||||||||||
1479 | void anchor() override; | ||||||||||||
1480 | |||||||||||||
1481 | public: | ||||||||||||
1482 | EmptyHNode(Node *n) : HNode(n) { } | ||||||||||||
1483 | |||||||||||||
1484 | static bool classof(const HNode *n) { return NullNode::classof(n->_node); } | ||||||||||||
1485 | |||||||||||||
1486 | static bool classof(const EmptyHNode *) { return true; } | ||||||||||||
1487 | }; | ||||||||||||
1488 | |||||||||||||
1489 | class ScalarHNode : public HNode { | ||||||||||||
1490 | void anchor() override; | ||||||||||||
1491 | |||||||||||||
1492 | public: | ||||||||||||
1493 | ScalarHNode(Node *n, StringRef s) : HNode(n), _value(s) { } | ||||||||||||
1494 | |||||||||||||
1495 | StringRef value() const { return _value; } | ||||||||||||
1496 | |||||||||||||
1497 | static bool classof(const HNode *n) { | ||||||||||||
1498 | return ScalarNode::classof(n->_node) || | ||||||||||||
1499 | BlockScalarNode::classof(n->_node); | ||||||||||||
1500 | } | ||||||||||||
1501 | |||||||||||||
1502 | static bool classof(const ScalarHNode *) { return true; } | ||||||||||||
1503 | |||||||||||||
1504 | protected: | ||||||||||||
1505 | StringRef _value; | ||||||||||||
1506 | }; | ||||||||||||
1507 | |||||||||||||
1508 | class MapHNode : public HNode { | ||||||||||||
1509 | void anchor() override; | ||||||||||||
1510 | |||||||||||||
1511 | public: | ||||||||||||
1512 | MapHNode(Node *n) : HNode(n) { } | ||||||||||||
1513 | |||||||||||||
1514 | static bool classof(const HNode *n) { | ||||||||||||
1515 | return MappingNode::classof(n->_node); | ||||||||||||
1516 | } | ||||||||||||
1517 | |||||||||||||
1518 | static bool classof(const MapHNode *) { return true; } | ||||||||||||
1519 | |||||||||||||
1520 | using NameToNodeAndLoc = | ||||||||||||
1521 | StringMap<std::pair<std::unique_ptr<HNode>, SMRange>>; | ||||||||||||
1522 | |||||||||||||
1523 | NameToNodeAndLoc Mapping; | ||||||||||||
1524 | SmallVector<std::string, 6> ValidKeys; | ||||||||||||
1525 | }; | ||||||||||||
1526 | |||||||||||||
1527 | class SequenceHNode : public HNode { | ||||||||||||
1528 | void anchor() override; | ||||||||||||
1529 | |||||||||||||
1530 | public: | ||||||||||||
1531 | SequenceHNode(Node *n) : HNode(n) { } | ||||||||||||
1532 | |||||||||||||
1533 | static bool classof(const HNode *n) { | ||||||||||||
1534 | return SequenceNode::classof(n->_node); | ||||||||||||
1535 | } | ||||||||||||
1536 | |||||||||||||
1537 | static bool classof(const SequenceHNode *) { return true; } | ||||||||||||
1538 | |||||||||||||
1539 | std::vector<std::unique_ptr<HNode>> Entries; | ||||||||||||
1540 | }; | ||||||||||||
1541 | |||||||||||||
1542 | std::unique_ptr<Input::HNode> createHNodes(Node *node); | ||||||||||||
1543 | void setError(HNode *hnode, const Twine &message); | ||||||||||||
1544 | void setError(Node *node, const Twine &message); | ||||||||||||
1545 | void setError(const SMRange &Range, const Twine &message); | ||||||||||||
1546 | |||||||||||||
1547 | void reportWarning(HNode *hnode, const Twine &message); | ||||||||||||
1548 | void reportWarning(Node *hnode, const Twine &message); | ||||||||||||
1549 | void reportWarning(const SMRange &Range, const Twine &message); | ||||||||||||
1550 | |||||||||||||
1551 | public: | ||||||||||||
1552 | // These are only used by operator>>. They could be private | ||||||||||||
1553 | // if those templated things could be made friends. | ||||||||||||
1554 | bool setCurrentDocument(); | ||||||||||||
1555 | bool nextDocument(); | ||||||||||||
1556 | |||||||||||||
1557 | /// Returns the current node that's being parsed by the YAML Parser. | ||||||||||||
1558 | const Node *getCurrentNode() const; | ||||||||||||
1559 | |||||||||||||
1560 | void setAllowUnknownKeys(bool Allow) override; | ||||||||||||
1561 | |||||||||||||
1562 | private: | ||||||||||||
1563 | SourceMgr SrcMgr; // must be before Strm | ||||||||||||
1564 | std::unique_ptr<llvm::yaml::Stream> Strm; | ||||||||||||
1565 | std::unique_ptr<HNode> TopNode; | ||||||||||||
1566 | std::error_code EC; | ||||||||||||
1567 | BumpPtrAllocator StringAllocator; | ||||||||||||
1568 | document_iterator DocIterator; | ||||||||||||
1569 | llvm::BitVector BitValuesUsed; | ||||||||||||
1570 | HNode *CurrentNode = nullptr; | ||||||||||||
1571 | bool ScalarMatchFound = false; | ||||||||||||
1572 | bool AllowUnknownKeys = false; | ||||||||||||
1573 | }; | ||||||||||||
1574 | |||||||||||||
1575 | /// | ||||||||||||
1576 | /// The Output class is used to generate a yaml document from in-memory structs | ||||||||||||
1577 | /// and vectors. | ||||||||||||
1578 | /// | ||||||||||||
1579 | class Output : public IO { | ||||||||||||
1580 | public: | ||||||||||||
1581 | Output(raw_ostream &, void *Ctxt = nullptr, int WrapColumn = 70); | ||||||||||||
1582 | ~Output() override; | ||||||||||||
1583 | |||||||||||||
1584 | /// Set whether or not to output optional values which are equal | ||||||||||||
1585 | /// to the default value. By default, when outputting if you attempt | ||||||||||||
1586 | /// to write a value that is equal to the default, the value gets ignored. | ||||||||||||
1587 | /// Sometimes, it is useful to be able to see these in the resulting YAML | ||||||||||||
1588 | /// anyway. | ||||||||||||
1589 | void setWriteDefaultValues(bool Write) { WriteDefaultValues = Write; } | ||||||||||||
1590 | |||||||||||||
1591 | bool outputting() const override; | ||||||||||||
1592 | bool mapTag(StringRef, bool) override; | ||||||||||||
1593 | void beginMapping() override; | ||||||||||||
1594 | void endMapping() override; | ||||||||||||
1595 | bool preflightKey(const char *key, bool, bool, bool &, void *&) override; | ||||||||||||
1596 | void postflightKey(void *) override; | ||||||||||||
1597 | std::vector<StringRef> keys() override; | ||||||||||||
1598 | void beginFlowMapping() override; | ||||||||||||
1599 | void endFlowMapping() override; | ||||||||||||
1600 | unsigned beginSequence() override; | ||||||||||||
1601 | void endSequence() override; | ||||||||||||
1602 | bool preflightElement(unsigned, void *&) override; | ||||||||||||
1603 | void postflightElement(void *) override; | ||||||||||||
1604 | unsigned beginFlowSequence() override; | ||||||||||||
1605 | bool preflightFlowElement(unsigned, void *&) override; | ||||||||||||
1606 | void postflightFlowElement(void *) override; | ||||||||||||
1607 | void endFlowSequence() override; | ||||||||||||
1608 | void beginEnumScalar() override; | ||||||||||||
1609 | bool matchEnumScalar(const char*, bool) override; | ||||||||||||
1610 | bool matchEnumFallback() override; | ||||||||||||
1611 | void endEnumScalar() override; | ||||||||||||
1612 | bool beginBitSetScalar(bool &) override; | ||||||||||||
1613 | bool bitSetMatch(const char *, bool ) override; | ||||||||||||
1614 | void endBitSetScalar() override; | ||||||||||||
1615 | void scalarString(StringRef &, QuotingType) override; | ||||||||||||
1616 | void blockScalarString(StringRef &) override; | ||||||||||||
1617 | void scalarTag(std::string &) override; | ||||||||||||
1618 | NodeKind getNodeKind() override; | ||||||||||||
1619 | void setError(const Twine &message) override; | ||||||||||||
1620 | bool canElideEmptySequence() override; | ||||||||||||
1621 | |||||||||||||
1622 | // These are only used by operator<<. They could be private | ||||||||||||
1623 | // if that templated operator could be made a friend. | ||||||||||||
1624 | void beginDocuments(); | ||||||||||||
1625 | bool preflightDocument(unsigned); | ||||||||||||
1626 | void postflightDocument(); | ||||||||||||
1627 | void endDocuments(); | ||||||||||||
1628 | |||||||||||||
1629 | private: | ||||||||||||
1630 | void output(StringRef s); | ||||||||||||
1631 | void outputUpToEndOfLine(StringRef s); | ||||||||||||
1632 | void newLineCheck(bool EmptySequence = false); | ||||||||||||
1633 | void outputNewLine(); | ||||||||||||
1634 | void paddedKey(StringRef key); | ||||||||||||
1635 | void flowKey(StringRef Key); | ||||||||||||
1636 | |||||||||||||
1637 | enum InState { | ||||||||||||
1638 | inSeqFirstElement, | ||||||||||||
1639 | inSeqOtherElement, | ||||||||||||
1640 | inFlowSeqFirstElement, | ||||||||||||
1641 | inFlowSeqOtherElement, | ||||||||||||
1642 | inMapFirstKey, | ||||||||||||
1643 | inMapOtherKey, | ||||||||||||
1644 | inFlowMapFirstKey, | ||||||||||||
1645 | inFlowMapOtherKey | ||||||||||||
1646 | }; | ||||||||||||
1647 | |||||||||||||
1648 | static bool inSeqAnyElement(InState State); | ||||||||||||
1649 | static bool inFlowSeqAnyElement(InState State); | ||||||||||||
1650 | static bool inMapAnyKey(InState State); | ||||||||||||
1651 | static bool inFlowMapAnyKey(InState State); | ||||||||||||
1652 | |||||||||||||
1653 | raw_ostream &Out; | ||||||||||||
1654 | int WrapColumn; | ||||||||||||
1655 | SmallVector<InState, 8> StateStack; | ||||||||||||
1656 | int Column = 0; | ||||||||||||
1657 | int ColumnAtFlowStart = 0; | ||||||||||||
1658 | int ColumnAtMapFlowStart = 0; | ||||||||||||
1659 | bool NeedBitValueComma = false; | ||||||||||||
1660 | bool NeedFlowSequenceComma = false; | ||||||||||||
1661 | bool EnumerationMatchFound = false; | ||||||||||||
1662 | bool WriteDefaultValues = false; | ||||||||||||
1663 | StringRef Padding; | ||||||||||||
1664 | StringRef PaddingBeforeContainer; | ||||||||||||
1665 | }; | ||||||||||||
1666 | |||||||||||||
1667 | template <typename T, typename Context> | ||||||||||||
1668 | void IO::processKeyWithDefault(const char *Key, Optional<T> &Val, | ||||||||||||
1669 | const Optional<T> &DefaultValue, bool Required, | ||||||||||||
1670 | Context &Ctx) { | ||||||||||||
1671 | assert(DefaultValue.hasValue() == false &&(static_cast <bool> (DefaultValue.hasValue() == false && "Optional<T> shouldn't have a value!") ? void (0) : __assert_fail ("DefaultValue.hasValue() == false && \"Optional<T> shouldn't have a value!\"" , "llvm/include/llvm/Support/YAMLTraits.h", 1672, __extension__ __PRETTY_FUNCTION__)) | ||||||||||||
1672 | "Optional<T> shouldn't have a value!")(static_cast <bool> (DefaultValue.hasValue() == false && "Optional<T> shouldn't have a value!") ? void (0) : __assert_fail ("DefaultValue.hasValue() == false && \"Optional<T> shouldn't have a value!\"" , "llvm/include/llvm/Support/YAMLTraits.h", 1672, __extension__ __PRETTY_FUNCTION__)); | ||||||||||||
1673 | void *SaveInfo; | ||||||||||||
1674 | bool UseDefault = true; | ||||||||||||
1675 | const bool sameAsDefault = outputting() && !Val.hasValue(); | ||||||||||||
1676 | if (!outputting() && !Val.hasValue()) | ||||||||||||
1677 | Val = T(); | ||||||||||||
1678 | if (Val.hasValue() && | ||||||||||||
1679 | this->preflightKey(Key, Required, sameAsDefault, UseDefault, SaveInfo)) { | ||||||||||||
1680 | |||||||||||||
1681 | // When reading an Optional<X> key from a YAML description, we allow the | ||||||||||||
1682 | // special "<none>" value, which can be used to specify that no value was | ||||||||||||
1683 | // requested, i.e. the DefaultValue will be assigned. The DefaultValue is | ||||||||||||
1684 | // usually None. | ||||||||||||
1685 | bool IsNone = false; | ||||||||||||
1686 | if (!outputting()) | ||||||||||||
1687 | if (const auto *Node = dyn_cast<ScalarNode>(((Input *)this)->getCurrentNode())) | ||||||||||||
1688 | // We use rtrim to ignore possible white spaces that might exist when a | ||||||||||||
1689 | // comment is present on the same line. | ||||||||||||
1690 | IsNone = Node->getRawValue().rtrim(' ') == "<none>"; | ||||||||||||
1691 | |||||||||||||
1692 | if (IsNone) | ||||||||||||
1693 | Val = DefaultValue; | ||||||||||||
1694 | else | ||||||||||||
1695 | yamlize(*this, Val.getValue(), Required, Ctx); | ||||||||||||
1696 | this->postflightKey(SaveInfo); | ||||||||||||
1697 | } else { | ||||||||||||
1698 | if (UseDefault) | ||||||||||||
1699 | Val = DefaultValue; | ||||||||||||
1700 | } | ||||||||||||
1701 | } | ||||||||||||
1702 | |||||||||||||
1703 | /// YAML I/O does conversion based on types. But often native data types | ||||||||||||
1704 | /// are just a typedef of built in intergral types (e.g. int). But the C++ | ||||||||||||
1705 | /// type matching system sees through the typedef and all the typedefed types | ||||||||||||
1706 | /// look like a built in type. This will cause the generic YAML I/O conversion | ||||||||||||
1707 | /// to be used. To provide better control over the YAML conversion, you can | ||||||||||||
1708 | /// use this macro instead of typedef. It will create a class with one field | ||||||||||||
1709 | /// and automatic conversion operators to and from the base type. | ||||||||||||
1710 | /// Based on BOOST_STRONG_TYPEDEF | ||||||||||||
1711 | #define LLVM_YAML_STRONG_TYPEDEF(_base, _type)struct _type { _type() = default; _type(const _base v) : value (v) {} _type(const _type &v) = default; _type &operator =(const _type &rhs) = default; _type &operator=(const _base &rhs) { value = rhs; return *this; } operator const _base & () const { return value; } bool operator==(const _type &rhs) const { return value == rhs.value; } bool operator ==(const _base &rhs) const { return value == rhs; } bool operator <(const _type &rhs) const { return value < rhs.value ; } _base value; using BaseType = _base; }; \ | ||||||||||||
1712 | struct _type { \ | ||||||||||||
1713 | _type() = default; \ | ||||||||||||
1714 | _type(const _base v) : value(v) {} \ | ||||||||||||
1715 | _type(const _type &v) = default; \ | ||||||||||||
1716 | _type &operator=(const _type &rhs) = default; \ | ||||||||||||
1717 | _type &operator=(const _base &rhs) { value = rhs; return *this; } \ | ||||||||||||
1718 | operator const _base & () const { return value; } \ | ||||||||||||
1719 | bool operator==(const _type &rhs) const { return value == rhs.value; } \ | ||||||||||||
1720 | bool operator==(const _base &rhs) const { return value == rhs; } \ | ||||||||||||
1721 | bool operator<(const _type &rhs) const { return value < rhs.value; } \ | ||||||||||||
1722 | _base value; \ | ||||||||||||
1723 | using BaseType = _base; \ | ||||||||||||
1724 | }; | ||||||||||||
1725 | |||||||||||||
1726 | /// | ||||||||||||
1727 | /// Use these types instead of uintXX_t in any mapping to have | ||||||||||||
1728 | /// its yaml output formatted as hexadecimal. | ||||||||||||
1729 | /// | ||||||||||||
1730 | LLVM_YAML_STRONG_TYPEDEF(uint8_t, Hex8)struct Hex8 { Hex8() = default; Hex8(const uint8_t v) : value (v) {} Hex8(const Hex8 &v) = default; Hex8 &operator= (const Hex8 &rhs) = default; Hex8 &operator=(const uint8_t &rhs) { value = rhs; return *this; } operator const uint8_t & () const { return value; } bool operator==(const Hex8 & rhs) const { return value == rhs.value; } bool operator==(const uint8_t &rhs) const { return value == rhs; } bool operator <(const Hex8 &rhs) const { return value < rhs.value ; } uint8_t value; using BaseType = uint8_t; }; | ||||||||||||
1731 | LLVM_YAML_STRONG_TYPEDEF(uint16_t, Hex16)struct Hex16 { Hex16() = default; Hex16(const uint16_t v) : value (v) {} Hex16(const Hex16 &v) = default; Hex16 &operator =(const Hex16 &rhs) = default; Hex16 &operator=(const uint16_t &rhs) { value = rhs; return *this; } operator const uint16_t & () const { return value; } bool operator==(const Hex16 &rhs) const { return value == rhs.value; } bool operator ==(const uint16_t &rhs) const { return value == rhs; } bool operator<(const Hex16 &rhs) const { return value < rhs.value; } uint16_t value; using BaseType = uint16_t; }; | ||||||||||||
1732 | LLVM_YAML_STRONG_TYPEDEF(uint32_t, Hex32)struct Hex32 { Hex32() = default; Hex32(const uint32_t v) : value (v) {} Hex32(const Hex32 &v) = default; Hex32 &operator =(const Hex32 &rhs) = default; Hex32 &operator=(const uint32_t &rhs) { value = rhs; return *this; } operator const uint32_t & () const { return value; } bool operator==(const Hex32 &rhs) const { return value == rhs.value; } bool operator ==(const uint32_t &rhs) const { return value == rhs; } bool operator<(const Hex32 &rhs) const { return value < rhs.value; } uint32_t value; using BaseType = uint32_t; }; | ||||||||||||
1733 | LLVM_YAML_STRONG_TYPEDEF(uint64_t, Hex64)struct Hex64 { Hex64() = default; Hex64(const uint64_t v) : value (v) {} Hex64(const Hex64 &v) = default; Hex64 &operator =(const Hex64 &rhs) = default; Hex64 &operator=(const uint64_t &rhs) { value = rhs; return *this; } operator const uint64_t & () const { return value; } bool operator==(const Hex64 &rhs) const { return value == rhs.value; } bool operator ==(const uint64_t &rhs) const { return value == rhs; } bool operator<(const Hex64 &rhs) const { return value < rhs.value; } uint64_t value; using BaseType = uint64_t; }; | ||||||||||||
1734 | |||||||||||||
1735 | template<> | ||||||||||||
1736 | struct ScalarTraits<Hex8> { | ||||||||||||
1737 | static void output(const Hex8 &, void *, raw_ostream &); | ||||||||||||
1738 | static StringRef input(StringRef, void *, Hex8 &); | ||||||||||||
1739 | static QuotingType mustQuote(StringRef) { return QuotingType::None; } | ||||||||||||
1740 | }; | ||||||||||||
1741 | |||||||||||||
1742 | template<> | ||||||||||||
1743 | struct ScalarTraits<Hex16> { | ||||||||||||
1744 | static void output(const Hex16 &, void *, raw_ostream &); | ||||||||||||
1745 | static StringRef input(StringRef, void *, Hex16 &); | ||||||||||||
1746 | static QuotingType mustQuote(StringRef) { return QuotingType::None; } | ||||||||||||
1747 | }; | ||||||||||||
1748 | |||||||||||||
1749 | template<> | ||||||||||||
1750 | struct ScalarTraits<Hex32> { | ||||||||||||
1751 | static void output(const Hex32 &, void *, raw_ostream &); | ||||||||||||
1752 | static StringRef input(StringRef, void *, Hex32 &); | ||||||||||||
1753 | static QuotingType mustQuote(StringRef) { return QuotingType::None; } | ||||||||||||
1754 | }; | ||||||||||||
1755 | |||||||||||||
1756 | template<> | ||||||||||||
1757 | struct ScalarTraits<Hex64> { | ||||||||||||
1758 | static void output(const Hex64 &, void *, raw_ostream &); | ||||||||||||
1759 | static StringRef input(StringRef, void *, Hex64 &); | ||||||||||||
1760 | static QuotingType mustQuote(StringRef) { return QuotingType::None; } | ||||||||||||
1761 | }; | ||||||||||||
1762 | |||||||||||||
1763 | template <> struct ScalarTraits<VersionTuple> { | ||||||||||||
1764 | static void output(const VersionTuple &Value, void *, llvm::raw_ostream &Out); | ||||||||||||
1765 | static StringRef input(StringRef, void *, VersionTuple &); | ||||||||||||
1766 | static QuotingType mustQuote(StringRef) { return QuotingType::None; } | ||||||||||||
1767 | }; | ||||||||||||
1768 | |||||||||||||
1769 | // Define non-member operator>> so that Input can stream in a document list. | ||||||||||||
1770 | template <typename T> | ||||||||||||
1771 | inline std::enable_if_t<has_DocumentListTraits<T>::value, Input &> | ||||||||||||
1772 | operator>>(Input &yin, T &docList) { | ||||||||||||
1773 | int i = 0; | ||||||||||||
1774 | EmptyContext Ctx; | ||||||||||||
1775 | while ( yin.setCurrentDocument() ) { | ||||||||||||
1776 | yamlize(yin, DocumentListTraits<T>::element(yin, docList, i), true, Ctx); | ||||||||||||
1777 | if ( yin.error() ) | ||||||||||||
1778 | return yin; | ||||||||||||
1779 | yin.nextDocument(); | ||||||||||||
1780 | ++i; | ||||||||||||
1781 | } | ||||||||||||
1782 | return yin; | ||||||||||||
1783 | } | ||||||||||||
1784 | |||||||||||||
1785 | // Define non-member operator>> so that Input can stream in a map as a document. | ||||||||||||
1786 | template <typename T> | ||||||||||||
1787 | inline std::enable_if_t<has_MappingTraits<T, EmptyContext>::value, Input &> | ||||||||||||
1788 | operator>>(Input &yin, T &docMap) { | ||||||||||||
1789 | EmptyContext Ctx; | ||||||||||||
1790 | yin.setCurrentDocument(); | ||||||||||||
1791 | yamlize(yin, docMap, true, Ctx); | ||||||||||||
1792 | return yin; | ||||||||||||
1793 | } | ||||||||||||
1794 | |||||||||||||
1795 | // Define non-member operator>> so that Input can stream in a sequence as | ||||||||||||
1796 | // a document. | ||||||||||||
1797 | template <typename T> | ||||||||||||
1798 | inline std::enable_if_t<has_SequenceTraits<T>::value, Input &> | ||||||||||||
1799 | operator>>(Input &yin, T &docSeq) { | ||||||||||||
1800 | EmptyContext Ctx; | ||||||||||||
1801 | if (yin.setCurrentDocument()) | ||||||||||||
1802 | yamlize(yin, docSeq, true, Ctx); | ||||||||||||
1803 | return yin; | ||||||||||||
1804 | } | ||||||||||||
1805 | |||||||||||||
1806 | // Define non-member operator>> so that Input can stream in a block scalar. | ||||||||||||
1807 | template <typename T> | ||||||||||||
1808 | inline std::enable_if_t<has_BlockScalarTraits<T>::value, Input &> | ||||||||||||
1809 | operator>>(Input &In, T &Val) { | ||||||||||||
1810 | EmptyContext Ctx; | ||||||||||||
1811 | if (In.setCurrentDocument()) | ||||||||||||
1812 | yamlize(In, Val, true, Ctx); | ||||||||||||
1813 | return In; | ||||||||||||
1814 | } | ||||||||||||
1815 | |||||||||||||
1816 | // Define non-member operator>> so that Input can stream in a string map. | ||||||||||||
1817 | template <typename T> | ||||||||||||
1818 | inline std::enable_if_t<has_CustomMappingTraits<T>::value, Input &> | ||||||||||||
1819 | operator>>(Input &In, T &Val) { | ||||||||||||
1820 | EmptyContext Ctx; | ||||||||||||
1821 | if (In.setCurrentDocument()) | ||||||||||||
1822 | yamlize(In, Val, true, Ctx); | ||||||||||||
1823 | return In; | ||||||||||||
1824 | } | ||||||||||||
1825 | |||||||||||||
1826 | // Define non-member operator>> so that Input can stream in a polymorphic type. | ||||||||||||
1827 | template <typename T> | ||||||||||||
1828 | inline std::enable_if_t<has_PolymorphicTraits<T>::value, Input &> | ||||||||||||
1829 | operator>>(Input &In, T &Val) { | ||||||||||||
1830 | EmptyContext Ctx; | ||||||||||||
1831 | if (In.setCurrentDocument()) | ||||||||||||
1832 | yamlize(In, Val, true, Ctx); | ||||||||||||
1833 | return In; | ||||||||||||
1834 | } | ||||||||||||
1835 | |||||||||||||
1836 | // Provide better error message about types missing a trait specialization | ||||||||||||
1837 | template <typename T> | ||||||||||||
1838 | inline std::enable_if_t<missingTraits<T, EmptyContext>::value, Input &> | ||||||||||||
1839 | operator>>(Input &yin, T &docSeq) { | ||||||||||||
1840 | char missing_yaml_trait_for_type[sizeof(MissingTrait<T>)]; | ||||||||||||
1841 | return yin; | ||||||||||||
1842 | } | ||||||||||||
1843 | |||||||||||||
1844 | // Define non-member operator<< so that Output can stream out document list. | ||||||||||||
1845 | template <typename T> | ||||||||||||
1846 | inline std::enable_if_t<has_DocumentListTraits<T>::value, Output &> | ||||||||||||
1847 | operator<<(Output &yout, T &docList) { | ||||||||||||
1848 | EmptyContext Ctx; | ||||||||||||
1849 | yout.beginDocuments(); | ||||||||||||
1850 | const size_t count = DocumentListTraits<T>::size(yout, docList); | ||||||||||||
1851 | for(size_t i=0; i < count; ++i) { | ||||||||||||
1852 | if ( yout.preflightDocument(i) ) { | ||||||||||||
1853 | yamlize(yout, DocumentListTraits<T>::element(yout, docList, i), true, | ||||||||||||
1854 | Ctx); | ||||||||||||
1855 | yout.postflightDocument(); | ||||||||||||
1856 | } | ||||||||||||
1857 | } | ||||||||||||
1858 | yout.endDocuments(); | ||||||||||||
1859 | return yout; | ||||||||||||
1860 | } | ||||||||||||
1861 | |||||||||||||
1862 | // Define non-member operator<< so that Output can stream out a map. | ||||||||||||
1863 | template <typename T> | ||||||||||||
1864 | inline std::enable_if_t<has_MappingTraits<T, EmptyContext>::value, Output &> | ||||||||||||
1865 | operator<<(Output &yout, T &map) { | ||||||||||||
1866 | EmptyContext Ctx; | ||||||||||||
1867 | yout.beginDocuments(); | ||||||||||||
1868 | if ( yout.preflightDocument(0) ) { | ||||||||||||
1869 | yamlize(yout, map, true, Ctx); | ||||||||||||
1870 | yout.postflightDocument(); | ||||||||||||
1871 | } | ||||||||||||
1872 | yout.endDocuments(); | ||||||||||||
1873 | return yout; | ||||||||||||
1874 | } | ||||||||||||
1875 | |||||||||||||
1876 | // Define non-member operator<< so that Output can stream out a sequence. | ||||||||||||
1877 | template <typename T> | ||||||||||||
1878 | inline std::enable_if_t<has_SequenceTraits<T>::value, Output &> | ||||||||||||
1879 | operator<<(Output &yout, T &seq) { | ||||||||||||
1880 | EmptyContext Ctx; | ||||||||||||
1881 | yout.beginDocuments(); | ||||||||||||
1882 | if ( yout.preflightDocument(0) ) { | ||||||||||||
1883 | yamlize(yout, seq, true, Ctx); | ||||||||||||
1884 | yout.postflightDocument(); | ||||||||||||
1885 | } | ||||||||||||
1886 | yout.endDocuments(); | ||||||||||||
1887 | return yout; | ||||||||||||
1888 | } | ||||||||||||
1889 | |||||||||||||
1890 | // Define non-member operator<< so that Output can stream out a block scalar. | ||||||||||||
1891 | template <typename T> | ||||||||||||
1892 | inline std::enable_if_t<has_BlockScalarTraits<T>::value, Output &> | ||||||||||||
1893 | operator<<(Output &Out, T &Val) { | ||||||||||||
1894 | EmptyContext Ctx; | ||||||||||||
1895 | Out.beginDocuments(); | ||||||||||||
1896 | if (Out.preflightDocument(0)) { | ||||||||||||
1897 | yamlize(Out, Val, true, Ctx); | ||||||||||||
1898 | Out.postflightDocument(); | ||||||||||||
1899 | } | ||||||||||||
1900 | Out.endDocuments(); | ||||||||||||
1901 | return Out; | ||||||||||||
1902 | } | ||||||||||||
1903 | |||||||||||||
1904 | // Define non-member operator<< so that Output can stream out a string map. | ||||||||||||
1905 | template <typename T> | ||||||||||||
1906 | inline std::enable_if_t<has_CustomMappingTraits<T>::value, Output &> | ||||||||||||
1907 | operator<<(Output &Out, T &Val) { | ||||||||||||
1908 | EmptyContext Ctx; | ||||||||||||
1909 | Out.beginDocuments(); | ||||||||||||
1910 | if (Out.preflightDocument(0)) { | ||||||||||||
1911 | yamlize(Out, Val, true, Ctx); | ||||||||||||
1912 | Out.postflightDocument(); | ||||||||||||
1913 | } | ||||||||||||
1914 | Out.endDocuments(); | ||||||||||||
1915 | return Out; | ||||||||||||
1916 | } | ||||||||||||
1917 | |||||||||||||
1918 | // Define non-member operator<< so that Output can stream out a polymorphic | ||||||||||||
1919 | // type. | ||||||||||||
1920 | template <typename T> | ||||||||||||
1921 | inline std::enable_if_t<has_PolymorphicTraits<T>::value, Output &> | ||||||||||||
1922 | operator<<(Output &Out, T &Val) { | ||||||||||||
1923 | EmptyContext Ctx; | ||||||||||||
1924 | Out.beginDocuments(); | ||||||||||||
1925 | if (Out.preflightDocument(0)) { | ||||||||||||
1926 | // FIXME: The parser does not support explicit documents terminated with a | ||||||||||||
1927 | // plain scalar; the end-marker is included as part of the scalar token. | ||||||||||||
1928 | assert(PolymorphicTraits<T>::getKind(Val) != NodeKind::Scalar && "plain scalar documents are not supported")(static_cast <bool> (PolymorphicTraits<T>::getKind (Val) != NodeKind::Scalar && "plain scalar documents are not supported" ) ? void (0) : __assert_fail ("PolymorphicTraits<T>::getKind(Val) != NodeKind::Scalar && \"plain scalar documents are not supported\"" , "llvm/include/llvm/Support/YAMLTraits.h", 1928, __extension__ __PRETTY_FUNCTION__)); | ||||||||||||
1929 | yamlize(Out, Val, true, Ctx); | ||||||||||||
1930 | Out.postflightDocument(); | ||||||||||||
1931 | } | ||||||||||||
1932 | Out.endDocuments(); | ||||||||||||
1933 | return Out; | ||||||||||||
1934 | } | ||||||||||||
1935 | |||||||||||||
1936 | // Provide better error message about types missing a trait specialization | ||||||||||||
1937 | template <typename T> | ||||||||||||
1938 | inline std::enable_if_t<missingTraits<T, EmptyContext>::value, Output &> | ||||||||||||
1939 | operator<<(Output &yout, T &seq) { | ||||||||||||
1940 | char missing_yaml_trait_for_type[sizeof(MissingTrait<T>)]; | ||||||||||||
1941 | return yout; | ||||||||||||
1942 | } | ||||||||||||
1943 | |||||||||||||
1944 | template <bool B> struct IsFlowSequenceBase {}; | ||||||||||||
1945 | template <> struct IsFlowSequenceBase<true> { static const bool flow = true; }; | ||||||||||||
1946 | |||||||||||||
1947 | template <typename T, bool Flow> | ||||||||||||
1948 | struct SequenceTraitsImpl : IsFlowSequenceBase<Flow> { | ||||||||||||
1949 | private: | ||||||||||||
1950 | using type = typename T::value_type; | ||||||||||||
1951 | |||||||||||||
1952 | public: | ||||||||||||
1953 | static size_t size(IO &io, T &seq) { return seq.size(); } | ||||||||||||
1954 | |||||||||||||
1955 | static type &element(IO &io, T &seq, size_t index) { | ||||||||||||
1956 | if (index >= seq.size()) | ||||||||||||
1957 | seq.resize(index + 1); | ||||||||||||
1958 | return seq[index]; | ||||||||||||
1959 | } | ||||||||||||
1960 | }; | ||||||||||||
1961 | |||||||||||||
1962 | // Simple helper to check an expression can be used as a bool-valued template | ||||||||||||
1963 | // argument. | ||||||||||||
1964 | template <bool> struct CheckIsBool { static const bool value = true; }; | ||||||||||||
1965 | |||||||||||||
1966 | // If T has SequenceElementTraits, then vector<T> and SmallVector<T, N> have | ||||||||||||
1967 | // SequenceTraits that do the obvious thing. | ||||||||||||
1968 | template <typename T> | ||||||||||||
1969 | struct SequenceTraits< | ||||||||||||
1970 | std::vector<T>, | ||||||||||||
1971 | std::enable_if_t<CheckIsBool<SequenceElementTraits<T>::flow>::value>> | ||||||||||||
1972 | : SequenceTraitsImpl<std::vector<T>, SequenceElementTraits<T>::flow> {}; | ||||||||||||
1973 | template <typename T, unsigned N> | ||||||||||||
1974 | struct SequenceTraits< | ||||||||||||
1975 | SmallVector<T, N>, | ||||||||||||
1976 | std::enable_if_t<CheckIsBool<SequenceElementTraits<T>::flow>::value>> | ||||||||||||
1977 | : SequenceTraitsImpl<SmallVector<T, N>, SequenceElementTraits<T>::flow> {}; | ||||||||||||
1978 | template <typename T> | ||||||||||||
1979 | struct SequenceTraits< | ||||||||||||
1980 | SmallVectorImpl<T>, | ||||||||||||
1981 | std::enable_if_t<CheckIsBool<SequenceElementTraits<T>::flow>::value>> | ||||||||||||
1982 | : SequenceTraitsImpl<SmallVectorImpl<T>, SequenceElementTraits<T>::flow> {}; | ||||||||||||
1983 | |||||||||||||
1984 | // Sequences of fundamental types use flow formatting. | ||||||||||||
1985 | template <typename T> | ||||||||||||
1986 | struct SequenceElementTraits<T, | ||||||||||||
1987 | std::enable_if_t<std::is_fundamental<T>::value>> { | ||||||||||||
1988 | static const bool flow = true; | ||||||||||||
1989 | }; | ||||||||||||
1990 | |||||||||||||
1991 | // Sequences of strings use block formatting. | ||||||||||||
1992 | template<> struct SequenceElementTraits<std::string> { | ||||||||||||
1993 | static const bool flow = false; | ||||||||||||
1994 | }; | ||||||||||||
1995 | template<> struct SequenceElementTraits<StringRef> { | ||||||||||||
1996 | static const bool flow = false; | ||||||||||||
1997 | }; | ||||||||||||
1998 | template<> struct SequenceElementTraits<std::pair<std::string, std::string>> { | ||||||||||||
1999 | static const bool flow = false; | ||||||||||||
2000 | }; | ||||||||||||
2001 | |||||||||||||
2002 | /// Implementation of CustomMappingTraits for std::map<std::string, T>. | ||||||||||||
2003 | template <typename T> struct StdMapStringCustomMappingTraitsImpl { | ||||||||||||
2004 | using map_type = std::map<std::string, T>; | ||||||||||||
2005 | |||||||||||||
2006 | static void inputOne(IO &io, StringRef key, map_type &v) { | ||||||||||||
2007 | io.mapRequired(key.str().c_str(), v[std::string(key)]); | ||||||||||||
2008 | } | ||||||||||||
2009 | |||||||||||||
2010 | static void output(IO &io, map_type &v) { | ||||||||||||
2011 | for (auto &p : v) | ||||||||||||
2012 | io.mapRequired(p.first.c_str(), p.second); | ||||||||||||
2013 | } | ||||||||||||
2014 | }; | ||||||||||||
2015 | |||||||||||||
2016 | } // end namespace yaml | ||||||||||||
2017 | } // end namespace llvm | ||||||||||||
2018 | |||||||||||||
2019 | #define LLVM_YAML_IS_SEQUENCE_VECTOR_IMPL(TYPE, FLOW)namespace llvm { namespace yaml { static_assert( !std::is_fundamental <TYPE>::value && !std::is_same<TYPE, std::string >::value && !std::is_same<TYPE, llvm::StringRef >::value, "only use LLVM_YAML_IS_SEQUENCE_VECTOR for types you control" ); template <> struct SequenceElementTraits<TYPE> { static const bool flow = FLOW; }; } } \ | ||||||||||||
2020 | namespace llvm { \ | ||||||||||||
2021 | namespace yaml { \ | ||||||||||||
2022 | static_assert( \ | ||||||||||||
2023 | !std::is_fundamental<TYPE>::value && \ | ||||||||||||
2024 | !std::is_same<TYPE, std::string>::value && \ | ||||||||||||
2025 | !std::is_same<TYPE, llvm::StringRef>::value, \ | ||||||||||||
2026 | "only use LLVM_YAML_IS_SEQUENCE_VECTOR for types you control"); \ | ||||||||||||
2027 | template <> struct SequenceElementTraits<TYPE> { \ | ||||||||||||
2028 | static const bool flow = FLOW; \ | ||||||||||||
2029 | }; \ | ||||||||||||
2030 | } \ | ||||||||||||
2031 | } | ||||||||||||
2032 | |||||||||||||
2033 | /// Utility for declaring that a std::vector of a particular type | ||||||||||||
2034 | /// should be considered a YAML sequence. | ||||||||||||
2035 | #define LLVM_YAML_IS_SEQUENCE_VECTOR(type)namespace llvm { namespace yaml { static_assert( !std::is_fundamental <type>::value && !std::is_same<type, std::string >::value && !std::is_same<type, llvm::StringRef >::value, "only use LLVM_YAML_IS_SEQUENCE_VECTOR for types you control" ); template <> struct SequenceElementTraits<type> { static const bool flow = false; }; } } \ | ||||||||||||
2036 | LLVM_YAML_IS_SEQUENCE_VECTOR_IMPL(type, false)namespace llvm { namespace yaml { static_assert( !std::is_fundamental <type>::value && !std::is_same<type, std::string >::value && !std::is_same<type, llvm::StringRef >::value, "only use LLVM_YAML_IS_SEQUENCE_VECTOR for types you control" ); template <> struct SequenceElementTraits<type> { static const bool flow = false; }; } } | ||||||||||||
2037 | |||||||||||||
2038 | /// Utility for declaring that a std::vector of a particular type | ||||||||||||
2039 | /// should be considered a YAML flow sequence. | ||||||||||||
2040 | #define LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(type)namespace llvm { namespace yaml { static_assert( !std::is_fundamental <type>::value && !std::is_same<type, std::string >::value && !std::is_same<type, llvm::StringRef >::value, "only use LLVM_YAML_IS_SEQUENCE_VECTOR for types you control" ); template <> struct SequenceElementTraits<type> { static const bool flow = true; }; } } \ | ||||||||||||
2041 | LLVM_YAML_IS_SEQUENCE_VECTOR_IMPL(type, true)namespace llvm { namespace yaml { static_assert( !std::is_fundamental <type>::value && !std::is_same<type, std::string >::value && !std::is_same<type, llvm::StringRef >::value, "only use LLVM_YAML_IS_SEQUENCE_VECTOR for types you control" ); template <> struct SequenceElementTraits<type> { static const bool flow = true; }; } } | ||||||||||||
2042 | |||||||||||||
2043 | #define LLVM_YAML_DECLARE_MAPPING_TRAITS(Type)namespace llvm { namespace yaml { template <> struct MappingTraits <Type> { static void mapping(IO &IO, Type &Obj) ; }; } } \ | ||||||||||||
2044 | namespace llvm { \ | ||||||||||||
2045 | namespace yaml { \ | ||||||||||||
2046 | template <> struct MappingTraits<Type> { \ | ||||||||||||
2047 | static void mapping(IO &IO, Type &Obj); \ | ||||||||||||
2048 | }; \ | ||||||||||||
2049 | } \ | ||||||||||||
2050 | } | ||||||||||||
2051 | |||||||||||||
2052 | #define LLVM_YAML_DECLARE_ENUM_TRAITS(Type)namespace llvm { namespace yaml { template <> struct ScalarEnumerationTraits <Type> { static void enumeration(IO &io, Type & Value); }; } } \ | ||||||||||||
2053 | namespace llvm { \ | ||||||||||||
2054 | namespace yaml { \ | ||||||||||||
2055 | template <> struct ScalarEnumerationTraits<Type> { \ | ||||||||||||
2056 | static void enumeration(IO &io, Type &Value); \ | ||||||||||||
2057 | }; \ | ||||||||||||
2058 | } \ | ||||||||||||
2059 | } | ||||||||||||
2060 | |||||||||||||
2061 | #define LLVM_YAML_DECLARE_BITSET_TRAITS(Type)namespace llvm { namespace yaml { template <> struct ScalarBitSetTraits <Type> { static void bitset(IO &IO, Type &Options ); }; } } \ | ||||||||||||
2062 | namespace llvm { \ | ||||||||||||
2063 | namespace yaml { \ | ||||||||||||
2064 | template <> struct ScalarBitSetTraits<Type> { \ | ||||||||||||
2065 | static void bitset(IO &IO, Type &Options); \ | ||||||||||||
2066 | }; \ | ||||||||||||
2067 | } \ | ||||||||||||
2068 | } | ||||||||||||
2069 | |||||||||||||
2070 | #define LLVM_YAML_DECLARE_SCALAR_TRAITS(Type, MustQuote)namespace llvm { namespace yaml { template <> struct ScalarTraits <Type> { static void output(const Type &Value, void *ctx, raw_ostream &Out); static StringRef input(StringRef Scalar, void *ctxt, Type &Value); static QuotingType mustQuote (StringRef) { return MustQuote; } }; } } \ | ||||||||||||
2071 | namespace llvm { \ | ||||||||||||
2072 | namespace yaml { \ | ||||||||||||
2073 | template <> struct ScalarTraits<Type> { \ | ||||||||||||
2074 | static void output(const Type &Value, void *ctx, raw_ostream &Out); \ | ||||||||||||
2075 | static StringRef input(StringRef Scalar, void *ctxt, Type &Value); \ | ||||||||||||
2076 | static QuotingType mustQuote(StringRef) { return MustQuote; } \ | ||||||||||||
2077 | }; \ | ||||||||||||
2078 | } \ | ||||||||||||
2079 | } | ||||||||||||
2080 | |||||||||||||
2081 | /// Utility for declaring that a std::vector of a particular type | ||||||||||||
2082 | /// should be considered a YAML document list. | ||||||||||||
2083 | #define LLVM_YAML_IS_DOCUMENT_LIST_VECTOR(_type)namespace llvm { namespace yaml { template <unsigned N> struct DocumentListTraits<SmallVector<_type, N>> : public SequenceTraitsImpl<SmallVector<_type, N>, false > {}; template <> struct DocumentListTraits<std:: vector<_type>> : public SequenceTraitsImpl<std::vector <_type>, false> {}; } } \ | ||||||||||||
2084 | namespace llvm { \ | ||||||||||||
2085 | namespace yaml { \ | ||||||||||||
2086 | template <unsigned N> \ | ||||||||||||
2087 | struct DocumentListTraits<SmallVector<_type, N>> \ | ||||||||||||
2088 | : public SequenceTraitsImpl<SmallVector<_type, N>, false> {}; \ | ||||||||||||
2089 | template <> \ | ||||||||||||
2090 | struct DocumentListTraits<std::vector<_type>> \ | ||||||||||||
2091 | : public SequenceTraitsImpl<std::vector<_type>, false> {}; \ | ||||||||||||
2092 | } \ | ||||||||||||
2093 | } | ||||||||||||
2094 | |||||||||||||
2095 | /// Utility for declaring that std::map<std::string, _type> should be considered | ||||||||||||
2096 | /// a YAML map. | ||||||||||||
2097 | #define LLVM_YAML_IS_STRING_MAP(_type)namespace llvm { namespace yaml { template <> struct CustomMappingTraits <std::map<std::string, _type>> : public StdMapStringCustomMappingTraitsImpl <_type> {}; } } \ | ||||||||||||
2098 | namespace llvm { \ | ||||||||||||
2099 | namespace yaml { \ | ||||||||||||
2100 | template <> \ | ||||||||||||
2101 | struct CustomMappingTraits<std::map<std::string, _type>> \ | ||||||||||||
2102 | : public StdMapStringCustomMappingTraitsImpl<_type> {}; \ | ||||||||||||
2103 | } \ | ||||||||||||
2104 | } | ||||||||||||
2105 | |||||||||||||
2106 | LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(llvm::yaml::Hex64)namespace llvm { namespace yaml { static_assert( !std::is_fundamental <llvm::yaml::Hex64>::value && !std::is_same< llvm::yaml::Hex64, std::string>::value && !std::is_same <llvm::yaml::Hex64, llvm::StringRef>::value, "only use LLVM_YAML_IS_SEQUENCE_VECTOR for types you control" ); template <> struct SequenceElementTraits<llvm::yaml ::Hex64> { static const bool flow = true; }; } } | ||||||||||||
2107 | LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(llvm::yaml::Hex32)namespace llvm { namespace yaml { static_assert( !std::is_fundamental <llvm::yaml::Hex32>::value && !std::is_same< llvm::yaml::Hex32, std::string>::value && !std::is_same <llvm::yaml::Hex32, llvm::StringRef>::value, "only use LLVM_YAML_IS_SEQUENCE_VECTOR for types you control" ); template <> struct SequenceElementTraits<llvm::yaml ::Hex32> { static const bool flow = true; }; } } | ||||||||||||
2108 | LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(llvm::yaml::Hex16)namespace llvm { namespace yaml { static_assert( !std::is_fundamental <llvm::yaml::Hex16>::value && !std::is_same< llvm::yaml::Hex16, std::string>::value && !std::is_same <llvm::yaml::Hex16, llvm::StringRef>::value, "only use LLVM_YAML_IS_SEQUENCE_VECTOR for types you control" ); template <> struct SequenceElementTraits<llvm::yaml ::Hex16> { static const bool flow = true; }; } } | ||||||||||||
2109 | LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(llvm::yaml::Hex8)namespace llvm { namespace yaml { static_assert( !std::is_fundamental <llvm::yaml::Hex8>::value && !std::is_same<llvm ::yaml::Hex8, std::string>::value && !std::is_same <llvm::yaml::Hex8, llvm::StringRef>::value, "only use LLVM_YAML_IS_SEQUENCE_VECTOR for types you control" ); template <> struct SequenceElementTraits<llvm::yaml ::Hex8> { static const bool flow = true; }; } } | ||||||||||||
2110 | |||||||||||||
2111 | #endif // LLVM_SUPPORT_YAMLTRAITS_H |
1 | // The -*- C++ -*- dynamic memory management header. |
2 | |
3 | // Copyright (C) 1994-2020 Free Software Foundation, Inc. |
4 | |
5 | // This file is part of GCC. |
6 | // |
7 | // GCC is free software; you can redistribute it and/or modify |
8 | // it under the terms of the GNU General Public License as published by |
9 | // the Free Software Foundation; either version 3, or (at your option) |
10 | // any later version. |
11 | // |
12 | // GCC is distributed in the hope that it will be useful, |
13 | // but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
15 | // GNU General Public License for more details. |
16 | // |
17 | // Under Section 7 of GPL version 3, you are granted additional |
18 | // permissions described in the GCC Runtime Library Exception, version |
19 | // 3.1, as published by the Free Software Foundation. |
20 | |
21 | // You should have received a copy of the GNU General Public License and |
22 | // a copy of the GCC Runtime Library Exception along with this program; |
23 | // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see |
24 | // <http://www.gnu.org/licenses/>. |
25 | |
26 | /** @file new |
27 | * This is a Standard C++ Library header. |
28 | * |
29 | * The header @c new defines several functions to manage dynamic memory and |
30 | * handling memory allocation errors; see |
31 | * https://gcc.gnu.org/onlinedocs/libstdc++/manual/dynamic_memory.html |
32 | * for more. |
33 | */ |
34 | |
35 | #ifndef _NEW |
36 | #define _NEW |
37 | |
38 | #pragma GCC system_header |
39 | |
40 | #include <bits/c++config.h> |
41 | #include <exception> |
42 | |
43 | #pragma GCC visibility push(default) |
44 | |
45 | extern "C++" { |
46 | |
47 | namespace std |
48 | { |
49 | /** |
50 | * @brief Exception possibly thrown by @c new. |
51 | * @ingroup exceptions |
52 | * |
53 | * @c bad_alloc (or classes derived from it) is used to report allocation |
54 | * errors from the throwing forms of @c new. */ |
55 | class bad_alloc : public exception |
56 | { |
57 | public: |
58 | bad_alloc() throw() { } |
59 | |
60 | #if __cplusplus201402L >= 201103L |
61 | bad_alloc(const bad_alloc&) = default; |
62 | bad_alloc& operator=(const bad_alloc&) = default; |
63 | #endif |
64 | |
65 | // This declaration is not useless: |
66 | // http://gcc.gnu.org/onlinedocs/gcc-3.0.2/gcc_6.html#SEC118 |
67 | virtual ~bad_alloc() throw(); |
68 | |
69 | // See comment in eh_exception.cc. |
70 | virtual const char* what() const throw(); |
71 | }; |
72 | |
73 | #if __cplusplus201402L >= 201103L |
74 | class bad_array_new_length : public bad_alloc |
75 | { |
76 | public: |
77 | bad_array_new_length() throw() { } |
78 | |
79 | // This declaration is not useless: |
80 | // http://gcc.gnu.org/onlinedocs/gcc-3.0.2/gcc_6.html#SEC118 |
81 | virtual ~bad_array_new_length() throw(); |
82 | |
83 | // See comment in eh_exception.cc. |
84 | virtual const char* what() const throw(); |
85 | }; |
86 | #endif |
87 | |
88 | #if __cpp_aligned_new |
89 | enum class align_val_t: size_t {}; |
90 | #endif |
91 | |
92 | struct nothrow_t |
93 | { |
94 | #if __cplusplus201402L >= 201103L |
95 | explicit nothrow_t() = default; |
96 | #endif |
97 | }; |
98 | |
99 | extern const nothrow_t nothrow; |
100 | |
101 | /** If you write your own error handler to be called by @c new, it must |
102 | * be of this type. */ |
103 | typedef void (*new_handler)(); |
104 | |
105 | /// Takes a replacement handler as the argument, returns the |
106 | /// previous handler. |
107 | new_handler set_new_handler(new_handler) throw(); |
108 | |
109 | #if __cplusplus201402L >= 201103L |
110 | /// Return the current new handler. |
111 | new_handler get_new_handler() noexcept; |
112 | #endif |
113 | } // namespace std |
114 | |
115 | //@{ |
116 | /** These are replaceable signatures: |
117 | * - normal single new and delete (no arguments, throw @c bad_alloc on error) |
118 | * - normal array new and delete (same) |
119 | * - @c nothrow single new and delete (take a @c nothrow argument, return |
120 | * @c NULL on error) |
121 | * - @c nothrow array new and delete (same) |
122 | * |
123 | * Placement new and delete signatures (take a memory address argument, |
124 | * does nothing) may not be replaced by a user's program. |
125 | */ |
126 | _GLIBCXX_NODISCARD void* operator new(std::size_t) _GLIBCXX_THROW (std::bad_alloc) |
127 | __attribute__((__externally_visible__)); |
128 | _GLIBCXX_NODISCARD void* operator new[](std::size_t) _GLIBCXX_THROW (std::bad_alloc) |
129 | __attribute__((__externally_visible__)); |
130 | void operator delete(void*) _GLIBCXX_USE_NOEXCEPTnoexcept |
131 | __attribute__((__externally_visible__)); |
132 | void operator delete[](void*) _GLIBCXX_USE_NOEXCEPTnoexcept |
133 | __attribute__((__externally_visible__)); |
134 | #if __cpp_sized_deallocation |
135 | void operator delete(void*, std::size_t) _GLIBCXX_USE_NOEXCEPTnoexcept |
136 | __attribute__((__externally_visible__)); |
137 | void operator delete[](void*, std::size_t) _GLIBCXX_USE_NOEXCEPTnoexcept |
138 | __attribute__((__externally_visible__)); |
139 | #endif |
140 | _GLIBCXX_NODISCARD void* operator new(std::size_t, const std::nothrow_t&) _GLIBCXX_USE_NOEXCEPTnoexcept |
141 | __attribute__((__externally_visible__, __malloc__)); |
142 | _GLIBCXX_NODISCARD void* operator new[](std::size_t, const std::nothrow_t&) _GLIBCXX_USE_NOEXCEPTnoexcept |
143 | __attribute__((__externally_visible__, __malloc__)); |
144 | void operator delete(void*, const std::nothrow_t&) _GLIBCXX_USE_NOEXCEPTnoexcept |
145 | __attribute__((__externally_visible__)); |
146 | void operator delete[](void*, const std::nothrow_t&) _GLIBCXX_USE_NOEXCEPTnoexcept |
147 | __attribute__((__externally_visible__)); |
148 | #if __cpp_aligned_new |
149 | _GLIBCXX_NODISCARD void* operator new(std::size_t, std::align_val_t) |
150 | __attribute__((__externally_visible__)); |
151 | _GLIBCXX_NODISCARD void* operator new(std::size_t, std::align_val_t, const std::nothrow_t&) |
152 | _GLIBCXX_USE_NOEXCEPTnoexcept __attribute__((__externally_visible__, __malloc__)); |
153 | void operator delete(void*, std::align_val_t) |
154 | _GLIBCXX_USE_NOEXCEPTnoexcept __attribute__((__externally_visible__)); |
155 | void operator delete(void*, std::align_val_t, const std::nothrow_t&) |
156 | _GLIBCXX_USE_NOEXCEPTnoexcept __attribute__((__externally_visible__)); |
157 | _GLIBCXX_NODISCARD void* operator new[](std::size_t, std::align_val_t) |
158 | __attribute__((__externally_visible__)); |
159 | _GLIBCXX_NODISCARD void* operator new[](std::size_t, std::align_val_t, const std::nothrow_t&) |
160 | _GLIBCXX_USE_NOEXCEPTnoexcept __attribute__((__externally_visible__, __malloc__)); |
161 | void operator delete[](void*, std::align_val_t) |
162 | _GLIBCXX_USE_NOEXCEPTnoexcept __attribute__((__externally_visible__)); |
163 | void operator delete[](void*, std::align_val_t, const std::nothrow_t&) |
164 | _GLIBCXX_USE_NOEXCEPTnoexcept __attribute__((__externally_visible__)); |
165 | #if __cpp_sized_deallocation |
166 | void operator delete(void*, std::size_t, std::align_val_t) |
167 | _GLIBCXX_USE_NOEXCEPTnoexcept __attribute__((__externally_visible__)); |
168 | void operator delete[](void*, std::size_t, std::align_val_t) |
169 | _GLIBCXX_USE_NOEXCEPTnoexcept __attribute__((__externally_visible__)); |
170 | #endif // __cpp_sized_deallocation |
171 | #endif // __cpp_aligned_new |
172 | |
173 | // Default placement versions of operator new. |
174 | _GLIBCXX_NODISCARD inline void* operator new(std::size_t, void* __p) _GLIBCXX_USE_NOEXCEPTnoexcept |
175 | { return __p; } |
176 | _GLIBCXX_NODISCARD inline void* operator new[](std::size_t, void* __p) _GLIBCXX_USE_NOEXCEPTnoexcept |
177 | { return __p; } |
178 | |
179 | // Default placement versions of operator delete. |
180 | inline void operator delete (void*, void*) _GLIBCXX_USE_NOEXCEPTnoexcept { } |
181 | inline void operator delete[](void*, void*) _GLIBCXX_USE_NOEXCEPTnoexcept { } |
182 | //@} |
183 | } // extern "C++" |
184 | |
185 | #if __cplusplus201402L >= 201703L |
186 | #ifdef _GLIBCXX_HAVE_BUILTIN_LAUNDER1 |
187 | namespace std |
188 | { |
189 | #define __cpp_lib_launder 201606 |
190 | /// Pointer optimization barrier [ptr.launder] |
191 | template<typename _Tp> |
192 | [[nodiscard]] constexpr _Tp* |
193 | launder(_Tp* __p) noexcept |
194 | { return __builtin_launder(__p); } |
195 | |
196 | // The program is ill-formed if T is a function type or |
197 | // (possibly cv-qualified) void. |
198 | |
199 | template<typename _Ret, typename... _Args _GLIBCXX_NOEXCEPT_PARM> |
200 | void launder(_Ret (*)(_Args...) _GLIBCXX_NOEXCEPT_QUAL) = delete; |
201 | template<typename _Ret, typename... _Args _GLIBCXX_NOEXCEPT_PARM> |
202 | void launder(_Ret (*)(_Args......) _GLIBCXX_NOEXCEPT_QUAL) = delete; |
203 | |
204 | void launder(void*) = delete; |
205 | void launder(const void*) = delete; |
206 | void launder(volatile void*) = delete; |
207 | void launder(const volatile void*) = delete; |
208 | } |
209 | #endif // _GLIBCXX_HAVE_BUILTIN_LAUNDER |
210 | #endif // C++17 |
211 | |
212 | #if __cplusplus201402L > 201703L |
213 | namespace std |
214 | { |
215 | /// Tag type used to declare a class-specific operator delete that can |
216 | /// invoke the destructor before deallocating the memory. |
217 | struct destroying_delete_t |
218 | { |
219 | explicit destroying_delete_t() = default; |
220 | }; |
221 | /// Tag variable of type destroying_delete_t. |
222 | inline constexpr destroying_delete_t destroying_delete{}; |
223 | } |
224 | // Only define the feature test macro if the compiler supports the feature: |
225 | #if __cpp_impl_destroying_delete201806L |
226 | # define __cpp_lib_destroying_delete 201806L |
227 | #endif |
228 | #endif // C++20 |
229 | |
230 | #pragma GCC visibility pop |
231 | |
232 | #endif |