Bug Summary

File:tools/llvm-pdbutil/DumpOutputStyle.cpp
Warning:line 988, column 15
The left operand of '!=' is a garbage value

Annotated Source Code

[?] Use j/k keys for keyboard navigation

/build/llvm-toolchain-snapshot-6.0~svn321639/tools/llvm-pdbutil/DumpOutputStyle.cpp

1//===- DumpOutputStyle.cpp ------------------------------------ *- C++ --*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "DumpOutputStyle.h"
11
12#include "FormatUtil.h"
13#include "InputFile.h"
14#include "MinimalSymbolDumper.h"
15#include "MinimalTypeDumper.h"
16#include "StreamUtil.h"
17#include "llvm-pdbutil.h"
18
19#include "llvm/ADT/STLExtras.h"
20#include "llvm/DebugInfo/CodeView/CVSymbolVisitor.h"
21#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
22#include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h"
23#include "llvm/DebugInfo/CodeView/DebugCrossExSubsection.h"
24#include "llvm/DebugInfo/CodeView/DebugCrossImpSubsection.h"
25#include "llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h"
26#include "llvm/DebugInfo/CodeView/DebugLinesSubsection.h"
27#include "llvm/DebugInfo/CodeView/DebugStringTableSubsection.h"
28#include "llvm/DebugInfo/CodeView/DebugSymbolsSubsection.h"
29#include "llvm/DebugInfo/CodeView/Formatters.h"
30#include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"
31#include "llvm/DebugInfo/CodeView/Line.h"
32#include "llvm/DebugInfo/CodeView/SymbolDeserializer.h"
33#include "llvm/DebugInfo/CodeView/SymbolVisitorCallbackPipeline.h"
34#include "llvm/DebugInfo/CodeView/SymbolVisitorCallbacks.h"
35#include "llvm/DebugInfo/CodeView/TypeHashing.h"
36#include "llvm/DebugInfo/CodeView/TypeIndexDiscovery.h"
37#include "llvm/DebugInfo/MSF/MappedBlockStream.h"
38#include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptor.h"
39#include "llvm/DebugInfo/PDB/Native/DbiStream.h"
40#include "llvm/DebugInfo/PDB/Native/GlobalsStream.h"
41#include "llvm/DebugInfo/PDB/Native/ISectionContribVisitor.h"
42#include "llvm/DebugInfo/PDB/Native/InfoStream.h"
43#include "llvm/DebugInfo/PDB/Native/ModuleDebugStream.h"
44#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
45#include "llvm/DebugInfo/PDB/Native/PublicsStream.h"
46#include "llvm/DebugInfo/PDB/Native/RawError.h"
47#include "llvm/DebugInfo/PDB/Native/SymbolStream.h"
48#include "llvm/DebugInfo/PDB/Native/TpiHashing.h"
49#include "llvm/DebugInfo/PDB/Native/TpiStream.h"
50#include "llvm/Object/COFF.h"
51#include "llvm/Support/BinaryStreamReader.h"
52#include "llvm/Support/FormatAdapters.h"
53#include "llvm/Support/FormatVariadic.h"
54
55#include <cctype>
56
57using namespace llvm;
58using namespace llvm::codeview;
59using namespace llvm::msf;
60using namespace llvm::pdb;
61
62DumpOutputStyle::DumpOutputStyle(InputFile &File)
63 : File(File), P(2, false, outs()) {}
64
65PDBFile &DumpOutputStyle::getPdb() { return File.pdb(); }
66object::COFFObjectFile &DumpOutputStyle::getObj() { return File.obj(); }
67
68Error DumpOutputStyle::dump() {
69 if (opts::dump::DumpSummary) {
70 if (auto EC = dumpFileSummary())
71 return EC;
72 P.NewLine();
73 }
74
75 if (opts::dump::DumpStreams) {
76 if (auto EC = dumpStreamSummary())
77 return EC;
78 P.NewLine();
79 }
80
81 if (opts::dump::DumpSymbolStats) {
82 if (auto EC = dumpSymbolStats())
83 return EC;
84 P.NewLine();
85 }
86
87 if (opts::dump::DumpUdtStats) {
88 if (auto EC = dumpUdtStats())
89 return EC;
90 P.NewLine();
91 }
92
93 if (opts::dump::DumpStringTable) {
94 if (auto EC = dumpStringTable())
95 return EC;
96 P.NewLine();
97 }
98
99 if (opts::dump::DumpModules) {
100 if (auto EC = dumpModules())
101 return EC;
102 }
103
104 if (opts::dump::DumpModuleFiles) {
105 if (auto EC = dumpModuleFiles())
106 return EC;
107 }
108
109 if (opts::dump::DumpLines) {
110 if (auto EC = dumpLines())
111 return EC;
112 }
113
114 if (opts::dump::DumpInlineeLines) {
115 if (auto EC = dumpInlineeLines())
116 return EC;
117 }
118
119 if (opts::dump::DumpXmi) {
120 if (auto EC = dumpXmi())
121 return EC;
122 }
123
124 if (opts::dump::DumpXme) {
125 if (auto EC = dumpXme())
126 return EC;
127 }
128
129 if (File.isObj()) {
130 if (opts::dump::DumpTypes || !opts::dump::DumpTypeIndex.empty() ||
131 opts::dump::DumpTypeExtras)
132 if (auto EC = dumpTypesFromObjectFile())
133 return EC;
134 } else {
135 if (opts::dump::DumpTypes || !opts::dump::DumpTypeIndex.empty() ||
136 opts::dump::DumpTypeExtras) {
137 if (auto EC = dumpTpiStream(StreamTPI))
138 return EC;
139 }
140
141 if (opts::dump::DumpIds || !opts::dump::DumpIdIndex.empty() ||
142 opts::dump::DumpIdExtras) {
143 if (auto EC = dumpTpiStream(StreamIPI))
144 return EC;
145 }
146 }
147
148 if (opts::dump::DumpGlobals) {
149 if (auto EC = dumpGlobals())
150 return EC;
151 }
152
153 if (opts::dump::DumpPublics) {
154 if (auto EC = dumpPublics())
155 return EC;
156 }
157
158 if (opts::dump::DumpSymbols) {
159 auto EC = File.isPdb() ? dumpModuleSymsForPdb() : dumpModuleSymsForObj();
160 if (EC)
161 return EC;
162 }
163
164 if (opts::dump::DumpSectionHeaders) {
165 if (auto EC = dumpSectionHeaders())
166 return EC;
167 }
168
169 if (opts::dump::DumpSectionContribs) {
170 if (auto EC = dumpSectionContribs())
171 return EC;
172 }
173
174 if (opts::dump::DumpSectionMap) {
175 if (auto EC = dumpSectionMap())
176 return EC;
177 }
178
179 return Error::success();
180}
181
182static void printHeader(LinePrinter &P, const Twine &S) {
183 P.NewLine();
184 P.formatLine("{0,=60}", S);
185 P.formatLine("{0}", fmt_repeat('=', 60));
186}
187
188Error DumpOutputStyle::dumpFileSummary() {
189 printHeader(P, "Summary");
190
191 ExitOnError Err("Invalid PDB Format: ");
192
193 AutoIndent Indent(P);
194 if (File.isObj()) {
195 P.formatLine("Dumping File summary is not valid for object files");
196 return Error::success();
197 }
198
199 P.formatLine("Block Size: {0}", getPdb().getBlockSize());
200 P.formatLine("Number of blocks: {0}", getPdb().getBlockCount());
201 P.formatLine("Number of streams: {0}", getPdb().getNumStreams());
202
203 auto &PS = Err(getPdb().getPDBInfoStream());
204 P.formatLine("Signature: {0}", PS.getSignature());
205 P.formatLine("Age: {0}", PS.getAge());
206 P.formatLine("GUID: {0}", fmt_guid(PS.getGuid().Guid));
207 P.formatLine("Features: {0:x+}", static_cast<uint32_t>(PS.getFeatures()));
208 P.formatLine("Has Debug Info: {0}", getPdb().hasPDBDbiStream());
209 P.formatLine("Has Types: {0}", getPdb().hasPDBTpiStream());
210 P.formatLine("Has IDs: {0}", getPdb().hasPDBIpiStream());
211 P.formatLine("Has Globals: {0}", getPdb().hasPDBGlobalsStream());
212 P.formatLine("Has Publics: {0}", getPdb().hasPDBPublicsStream());
213 if (getPdb().hasPDBDbiStream()) {
214 auto &DBI = Err(getPdb().getPDBDbiStream());
215 P.formatLine("Is incrementally linked: {0}", DBI.isIncrementallyLinked());
216 P.formatLine("Has conflicting types: {0}", DBI.hasCTypes());
217 P.formatLine("Is stripped: {0}", DBI.isStripped());
218 }
219
220 return Error::success();
221}
222
223static StatCollection getSymbolStats(const SymbolGroup &SG,
224 StatCollection &CumulativeStats) {
225 StatCollection Stats;
226 if (SG.getFile().isPdb()) {
227 // For PDB files, all symbols are packed into one stream.
228 for (const auto &S : SG.getPdbModuleStream().symbols(nullptr)) {
229 Stats.update(S.kind(), S.length());
230 CumulativeStats.update(S.kind(), S.length());
231 }
232 return Stats;
233 }
234
235 for (const auto &SS : SG.getDebugSubsections()) {
236 // For object files, all symbols are spread across multiple Symbol
237 // subsections of a given .debug$S section.
238 if (SS.kind() != DebugSubsectionKind::Symbols)
239 continue;
240 DebugSymbolsSubsectionRef Symbols;
241 BinaryStreamReader Reader(SS.getRecordData());
242 cantFail(Symbols.initialize(Reader));
243 for (const auto &S : Symbols) {
244 Stats.update(S.kind(), S.length());
245 CumulativeStats.update(S.kind(), S.length());
246 }
247 }
248 return Stats;
249}
250
251static StatCollection getChunkStats(const SymbolGroup &SG,
252 StatCollection &CumulativeStats) {
253 StatCollection Stats;
254 for (const auto &Chunk : SG.getDebugSubsections()) {
255 Stats.update(uint32_t(Chunk.kind()), Chunk.getRecordLength());
256 CumulativeStats.update(uint32_t(Chunk.kind()), Chunk.getRecordLength());
257 }
258 return Stats;
259}
260
261static inline std::string formatModuleDetailKind(DebugSubsectionKind K) {
262 return formatChunkKind(K, false);
263}
264
265static inline std::string formatModuleDetailKind(SymbolKind K) {
266 return formatSymbolKind(K);
267}
268
269template <typename Kind>
270static void printModuleDetailStats(LinePrinter &P, StringRef Label,
271 const StatCollection &Stats) {
272 P.NewLine();
273 P.formatLine(" {0}", Label);
274 AutoIndent Indent(P);
275 P.formatLine("{0,40}: {1,7} entries ({2,8} bytes)", "Total",
276 Stats.Totals.Count, Stats.Totals.Size);
277 P.formatLine("{0}", fmt_repeat('-', 74));
278 for (const auto &K : Stats.Individual) {
279 std::string KindName = formatModuleDetailKind(Kind(K.first));
280 P.formatLine("{0,40}: {1,7} entries ({2,8} bytes)", KindName,
281 K.second.Count, K.second.Size);
282 }
283}
284
285static bool isMyCode(const SymbolGroup &Group) {
286 if (Group.getFile().isObj())
287 return true;
288
289 StringRef Name = Group.name();
290 if (Name.startswith("Import:"))
291 return false;
292 if (Name.endswith_lower(".dll"))
293 return false;
294 if (Name.equals_lower("* linker *"))
295 return false;
296 if (Name.startswith_lower("f:\\binaries\\Intermediate\\vctools"))
297 return false;
298 if (Name.startswith_lower("f:\\dd\\vctools\\crt"))
299 return false;
300 return true;
301}
302
303static bool shouldDumpSymbolGroup(uint32_t Idx, const SymbolGroup &Group) {
304 if (opts::dump::JustMyCode && !isMyCode(Group))
305 return false;
306
307 // If the arg was not specified on the command line, always dump all modules.
308 if (opts::dump::DumpModi.getNumOccurrences() == 0)
309 return true;
310
311 // Otherwise, only dump if this is the same module specified.
312 return (opts::dump::DumpModi == Idx);
313}
314
315Error DumpOutputStyle::dumpStreamSummary() {
316 printHeader(P, "Streams");
317
318 AutoIndent Indent(P);
319 if (File.isObj()) {
320 P.formatLine("Dumping streams is not valid for object files");
321 return Error::success();
322 }
323
324 if (StreamPurposes.empty())
325 discoverStreamPurposes(getPdb(), StreamPurposes);
326
327 uint32_t StreamCount = getPdb().getNumStreams();
328 uint32_t MaxStreamSize = getPdb().getMaxStreamSize();
329
330 for (uint16_t StreamIdx = 0; StreamIdx < StreamCount; ++StreamIdx) {
331 P.formatLine(
332 "Stream {0} ({1} bytes): [{2}]",
333 fmt_align(StreamIdx, AlignStyle::Right, NumDigits(StreamCount)),
334 fmt_align(getPdb().getStreamByteSize(StreamIdx), AlignStyle::Right,
335 NumDigits(MaxStreamSize)),
336 StreamPurposes[StreamIdx].getLongName());
337
338 if (opts::dump::DumpStreamBlocks) {
339 auto Blocks = getPdb().getStreamBlockList(StreamIdx);
340 std::vector<uint32_t> BV(Blocks.begin(), Blocks.end());
341 P.formatLine(" {0} Blocks: [{1}]",
342 fmt_repeat(' ', NumDigits(StreamCount)),
343 make_range(BV.begin(), BV.end()));
344 }
345 }
346
347 return Error::success();
348}
349
350static Expected<ModuleDebugStreamRef> getModuleDebugStream(PDBFile &File,
351 uint32_t Index) {
352 ExitOnError Err("Unexpected error: ");
353
354 auto &Dbi = Err(File.getPDBDbiStream());
355 const auto &Modules = Dbi.modules();
356 auto Modi = Modules.getModuleDescriptor(Index);
357
358 uint16_t ModiStream = Modi.getModuleStreamIndex();
359 if (ModiStream == kInvalidStreamIndex)
360 return make_error<RawError>(raw_error_code::no_stream,
361 "Module stream not present");
362
363 auto ModStreamData = File.createIndexedStream(ModiStream);
364
365 ModuleDebugStreamRef ModS(Modi, std::move(ModStreamData));
366 if (auto EC = ModS.reload())
367 return make_error<RawError>(raw_error_code::corrupt_file,
368 "Invalid module stream");
369
370 return std::move(ModS);
371}
372
373template <typename CallbackT>
374static void
375iterateOneModule(InputFile &File, const Optional<PrintScope> &HeaderScope,
376 const SymbolGroup &SG, uint32_t Modi, CallbackT Callback) {
377 if (HeaderScope) {
378 HeaderScope->P.formatLine(
379 "Mod {0:4} | `{1}`: ",
380 fmt_align(Modi, AlignStyle::Right, HeaderScope->LabelWidth), SG.name());
381 }
382
383 AutoIndent Indent(HeaderScope);
384 Callback(Modi, SG);
385}
386
387template <typename CallbackT>
388static void iterateSymbolGroups(InputFile &Input,
389 const Optional<PrintScope> &HeaderScope,
390 CallbackT Callback) {
391 AutoIndent Indent(HeaderScope);
392
393 ExitOnError Err("Unexpected error processing modules: ");
394
395 if (opts::dump::DumpModi.getNumOccurrences() > 0) {
396 assert(opts::dump::DumpModi.getNumOccurrences() == 1)(static_cast <bool> (opts::dump::DumpModi.getNumOccurrences
() == 1) ? void (0) : __assert_fail ("opts::dump::DumpModi.getNumOccurrences() == 1"
, "/build/llvm-toolchain-snapshot-6.0~svn321639/tools/llvm-pdbutil/DumpOutputStyle.cpp"
, 396, __extension__ __PRETTY_FUNCTION__))
;
397 uint32_t Modi = opts::dump::DumpModi;
398 SymbolGroup SG(&Input, Modi);
399 iterateOneModule(Input, withLabelWidth(HeaderScope, NumDigits(Modi)), SG,
400 Modi, Callback);
401 return;
402 }
403
404 uint32_t I = 0;
405
406 for (const auto &SG : Input.symbol_groups()) {
407 if (shouldDumpSymbolGroup(I, SG))
408 iterateOneModule(Input, withLabelWidth(HeaderScope, NumDigits(I)), SG, I,
409 Callback);
410
411 ++I;
412 }
413}
414
415template <typename SubsectionT>
416static void iterateModuleSubsections(
417 InputFile &File, const Optional<PrintScope> &HeaderScope,
418 llvm::function_ref<void(uint32_t, const SymbolGroup &, SubsectionT &)>
419 Callback) {
420
421 iterateSymbolGroups(File, HeaderScope,
422 [&](uint32_t Modi, const SymbolGroup &SG) {
423 for (const auto &SS : SG.getDebugSubsections()) {
424 SubsectionT Subsection;
425
426 if (SS.kind() != Subsection.kind())
427 continue;
428
429 BinaryStreamReader Reader(SS.getRecordData());
430 if (auto EC = Subsection.initialize(Reader))
431 continue;
432 Callback(Modi, SG, Subsection);
433 }
434 });
435}
436
437Error DumpOutputStyle::dumpModules() {
438 printHeader(P, "Modules");
439 AutoIndent Indent(P);
440
441 if (File.isObj()) {
442 P.formatLine("Dumping modules is not supported for object files");
443 return Error::success();
444 }
445
446 if (!getPdb().hasPDBDbiStream()) {
447 P.formatLine("DBI Stream not present");
448 return Error::success();
449 }
450
451 ExitOnError Err("Unexpected error processing modules: ");
452
453 auto &Stream = Err(getPdb().getPDBDbiStream());
454
455 const DbiModuleList &Modules = Stream.modules();
456 iterateSymbolGroups(
457 File, PrintScope{P, 11}, [&](uint32_t Modi, const SymbolGroup &Strings) {
458 auto Desc = Modules.getModuleDescriptor(Modi);
459 P.formatLine("Obj: `{0}`: ", Desc.getObjFileName());
460 P.formatLine("debug stream: {0}, # files: {1}, has ec info: {2}",
461 Desc.getModuleStreamIndex(), Desc.getNumberOfFiles(),
462 Desc.hasECInfo());
463 StringRef PdbFilePath =
464 Err(Stream.getECName(Desc.getPdbFilePathNameIndex()));
465 StringRef SrcFilePath =
466 Err(Stream.getECName(Desc.getSourceFileNameIndex()));
467 P.formatLine("pdb file ni: {0} `{1}`, src file ni: {2} `{3}`",
468 Desc.getPdbFilePathNameIndex(), PdbFilePath,
469 Desc.getSourceFileNameIndex(), SrcFilePath);
470 });
471 return Error::success();
472}
473
474Error DumpOutputStyle::dumpModuleFiles() {
475 printHeader(P, "Files");
476
477 if (File.isObj()) {
478 P.formatLine("Dumping files is not valid for object files");
479 return Error::success();
480 }
481
482 ExitOnError Err("Unexpected error processing modules: ");
483
484 iterateSymbolGroups(File, PrintScope{P, 11},
485 [this, &Err](uint32_t Modi, const SymbolGroup &Strings) {
486 auto &Stream = Err(getPdb().getPDBDbiStream());
487
488 const DbiModuleList &Modules = Stream.modules();
489 for (const auto &F : Modules.source_files(Modi)) {
490 Strings.formatFromFileName(P, F);
491 }
492 });
493 return Error::success();
494}
495
496Error DumpOutputStyle::dumpSymbolStats() {
497 printHeader(P, "Module Stats");
498
499 ExitOnError Err("Unexpected error processing modules: ");
500
501 StatCollection SymStats;
502 StatCollection ChunkStats;
503
504 Optional<PrintScope> Scope;
505 if (File.isPdb())
506 Scope.emplace(P, 2);
507
508 iterateSymbolGroups(File, Scope, [&](uint32_t Modi, const SymbolGroup &SG) {
509 StatCollection SS = getSymbolStats(SG, SymStats);
510 StatCollection CS = getChunkStats(SG, ChunkStats);
511
512 if (SG.getFile().isPdb()) {
513 AutoIndent Indent(P);
514 auto Modules = cantFail(File.pdb().getPDBDbiStream()).modules();
515 uint32_t ModCount = Modules.getModuleCount();
516 DbiModuleDescriptor Desc = Modules.getModuleDescriptor(Modi);
517 uint32_t StreamIdx = Desc.getModuleStreamIndex();
518
519 if (StreamIdx == kInvalidStreamIndex) {
520 P.formatLine("Mod {0} (debug info not present): [{1}]",
521 fmt_align(Modi, AlignStyle::Right, NumDigits(ModCount)),
522 Desc.getModuleName());
523 return;
524 }
525 P.formatLine("Stream {0}, {1} bytes", StreamIdx,
526 getPdb().getStreamByteSize(StreamIdx));
527
528 printModuleDetailStats<SymbolKind>(P, "Symbols", SS);
529 printModuleDetailStats<DebugSubsectionKind>(P, "Chunks", CS);
530 }
531 });
532
533 P.printLine(" Summary |");
534 AutoIndent Indent(P, 4);
535 if (SymStats.Totals.Count > 0) {
536 printModuleDetailStats<SymbolKind>(P, "Symbols", SymStats);
537 printModuleDetailStats<DebugSubsectionKind>(P, "Chunks", ChunkStats);
538 }
539
540 return Error::success();
541}
542
543static bool isValidNamespaceIdentifier(StringRef S) {
544 if (S.empty())
545 return false;
546
547 if (std::isdigit(S[0]))
548 return false;
549
550 return llvm::all_of(S, [](char C) { return std::isalnum(C); });
551}
552
553namespace {
554constexpr uint32_t kNoneUdtKind = 0;
555constexpr uint32_t kSimpleUdtKind = 1;
556constexpr uint32_t kUnknownUdtKind = 2;
557const StringRef NoneLabel("<none type>");
558const StringRef SimpleLabel("<simple type>");
559const StringRef UnknownLabel("<unknown type>");
560
561} // namespace
562
563static StringRef getUdtStatLabel(uint32_t Kind) {
564 if (Kind == kNoneUdtKind)
565 return NoneLabel;
566
567 if (Kind == kSimpleUdtKind)
568 return SimpleLabel;
569
570 if (Kind == kUnknownUdtKind)
571 return UnknownLabel;
572
573 return formatTypeLeafKind(static_cast<TypeLeafKind>(Kind));
574}
575
576static uint32_t getLongestTypeLeafName(const StatCollection &Stats) {
577 size_t L = 0;
578 for (const auto &Stat : Stats.Individual) {
579 StringRef Label = getUdtStatLabel(Stat.first);
580 L = std::max(L, Label.size());
581 }
582 return static_cast<uint32_t>(L);
583}
584
585Error DumpOutputStyle::dumpUdtStats() {
586 printHeader(P, "S_UDT Record Stats");
587
588 StatCollection UdtStats;
589 StatCollection UdtTargetStats;
590 AutoIndent Indent(P, 4);
591
592 auto &TpiTypes = File.types();
593
594 StringMap<StatCollection::Stat> NamespacedStats;
595
596 size_t LongestNamespace = 0;
597 auto HandleOneSymbol = [&](const CVSymbol &Sym) {
598 if (Sym.kind() != SymbolKind::S_UDT)
599 return;
600 UdtStats.update(SymbolKind::S_UDT, Sym.length());
601
602 UDTSym UDT = cantFail(SymbolDeserializer::deserializeAs<UDTSym>(Sym));
603
604 uint32_t Kind = 0;
605 uint32_t RecordSize = 0;
606
607 if (UDT.Type.isNoneType())
608 Kind = kNoneUdtKind;
609 else if (UDT.Type.isSimple())
610 Kind = kSimpleUdtKind;
611 else if (Optional<CVType> T = TpiTypes.tryGetType(UDT.Type)) {
612 Kind = T->kind();
613 RecordSize = T->length();
614 } else
615 Kind = kUnknownUdtKind;
616
617 UdtTargetStats.update(Kind, RecordSize);
618
619 size_t Pos = UDT.Name.find("::");
620 if (Pos == StringRef::npos)
621 return;
622
623 StringRef Scope = UDT.Name.take_front(Pos);
624 if (Scope.empty() || !isValidNamespaceIdentifier(Scope))
625 return;
626
627 LongestNamespace = std::max(LongestNamespace, Scope.size());
628 NamespacedStats[Scope].update(RecordSize);
629 };
630
631 P.NewLine();
632
633 if (File.isPdb()) {
634 if (!getPdb().hasPDBGlobalsStream()) {
635 P.printLine("- Error: globals stream not present");
636 return Error::success();
637 }
638
639 auto &SymbolRecords = cantFail(getPdb().getPDBSymbolStream());
640 auto ExpGlobals = getPdb().getPDBGlobalsStream();
641 if (!ExpGlobals)
642 return ExpGlobals.takeError();
643
644 for (uint32_t PubSymOff : ExpGlobals->getGlobalsTable()) {
645 CVSymbol Sym = SymbolRecords.readRecord(PubSymOff);
646 HandleOneSymbol(Sym);
647 }
648 } else {
649 for (const auto &Sec : File.symbol_groups()) {
650 for (const auto &SS : Sec.getDebugSubsections()) {
651 if (SS.kind() != DebugSubsectionKind::Symbols)
652 continue;
653
654 DebugSymbolsSubsectionRef Symbols;
655 BinaryStreamReader Reader(SS.getRecordData());
656 cantFail(Symbols.initialize(Reader));
657 for (const auto &S : Symbols)
658 HandleOneSymbol(S);
659 }
660 }
661 }
662
663 LongestNamespace += StringRef(" namespace ''").size();
664 size_t LongestTypeLeafKind = getLongestTypeLeafName(UdtTargetStats);
665 size_t FieldWidth = std::max(LongestNamespace, LongestTypeLeafKind);
666
667 // Compute the max number of digits for count and size fields, including comma
668 // separators.
669 StringRef CountHeader("Count");
670 StringRef SizeHeader("Size");
671 size_t CD = NumDigits(UdtStats.Totals.Count);
672 CD += (CD - 1) / 3;
673 CD = std::max(CD, CountHeader.size());
674
675 size_t SD = NumDigits(UdtStats.Totals.Size);
676 SD += (SD - 1) / 3;
677 SD = std::max(SD, SizeHeader.size());
678
679 uint32_t TableWidth = FieldWidth + 3 + CD + 2 + SD + 1;
680
681 P.formatLine("{0} | {1} {2}",
682 fmt_align("Record Kind", AlignStyle::Right, FieldWidth),
683 fmt_align(CountHeader, AlignStyle::Right, CD),
684 fmt_align(SizeHeader, AlignStyle::Right, SD));
685
686 P.formatLine("{0}", fmt_repeat('-', TableWidth));
687 for (const auto &Stat : UdtTargetStats.Individual) {
688 StringRef Label = getUdtStatLabel(Stat.first);
689 P.formatLine("{0} | {1:N} {2:N}",
690 fmt_align(Label, AlignStyle::Right, FieldWidth),
691 fmt_align(Stat.second.Count, AlignStyle::Right, CD),
692 fmt_align(Stat.second.Size, AlignStyle::Right, SD));
693 }
694 P.formatLine("{0}", fmt_repeat('-', TableWidth));
695 P.formatLine("{0} | {1:N} {2:N}",
696 fmt_align("Total (S_UDT)", AlignStyle::Right, FieldWidth),
697 fmt_align(UdtStats.Totals.Count, AlignStyle::Right, CD),
698 fmt_align(UdtStats.Totals.Size, AlignStyle::Right, SD));
699 P.formatLine("{0}", fmt_repeat('-', TableWidth));
700 for (const auto &Stat : NamespacedStats) {
701 std::string Label = formatv("namespace '{0}'", Stat.getKey());
702 P.formatLine("{0} | {1:N} {2:N}",
703 fmt_align(Label, AlignStyle::Right, FieldWidth),
704 fmt_align(Stat.second.Count, AlignStyle::Right, CD),
705 fmt_align(Stat.second.Size, AlignStyle::Right, SD));
706 }
707 return Error::success();
708}
709
710static void typesetLinesAndColumns(LinePrinter &P, uint32_t Start,
711 const LineColumnEntry &E) {
712 const uint32_t kMaxCharsPerLineNumber = 4; // 4 digit line number
713 uint32_t MinColumnWidth = kMaxCharsPerLineNumber + 5;
714
715 // Let's try to keep it under 100 characters
716 constexpr uint32_t kMaxRowLength = 100;
717 // At least 3 spaces between columns.
718 uint32_t ColumnsPerRow = kMaxRowLength / (MinColumnWidth + 3);
719 uint32_t ItemsLeft = E.LineNumbers.size();
720 auto LineIter = E.LineNumbers.begin();
721 while (ItemsLeft != 0) {
722 uint32_t RowColumns = std::min(ItemsLeft, ColumnsPerRow);
723 for (uint32_t I = 0; I < RowColumns; ++I) {
724 LineInfo Line(LineIter->Flags);
725 std::string LineStr;
726 if (Line.isAlwaysStepInto())
727 LineStr = "ASI";
728 else if (Line.isNeverStepInto())
729 LineStr = "NSI";
730 else
731 LineStr = utostr(Line.getStartLine());
732 char Statement = Line.isStatement() ? ' ' : '!';
733 P.format("{0} {1:X-} {2} ",
734 fmt_align(LineStr, AlignStyle::Right, kMaxCharsPerLineNumber),
735 fmt_align(Start + LineIter->Offset, AlignStyle::Right, 8, '0'),
736 Statement);
737 ++LineIter;
738 --ItemsLeft;
739 }
740 P.NewLine();
741 }
742}
743
744Error DumpOutputStyle::dumpLines() {
745 printHeader(P, "Lines");
746
747 uint32_t LastModi = UINT32_MAX(4294967295U);
748 uint32_t LastNameIndex = UINT32_MAX(4294967295U);
749 iterateModuleSubsections<DebugLinesSubsectionRef>(
750 File, PrintScope{P, 4},
751 [this, &LastModi, &LastNameIndex](uint32_t Modi,
752 const SymbolGroup &Strings,
753 DebugLinesSubsectionRef &Lines) {
754 uint16_t Segment = Lines.header()->RelocSegment;
755 uint32_t Begin = Lines.header()->RelocOffset;
756 uint32_t End = Begin + Lines.header()->CodeSize;
757 for (const auto &Block : Lines) {
758 if (LastModi != Modi || LastNameIndex != Block.NameIndex) {
759 LastModi = Modi;
760 LastNameIndex = Block.NameIndex;
761 Strings.formatFromChecksumsOffset(P, Block.NameIndex);
762 }
763
764 AutoIndent Indent(P, 2);
765 P.formatLine("{0:X-4}:{1:X-8}-{2:X-8}, ", Segment, Begin, End);
766 uint32_t Count = Block.LineNumbers.size();
767 if (Lines.hasColumnInfo())
768 P.format("line/column/addr entries = {0}", Count);
769 else
770 P.format("line/addr entries = {0}", Count);
771
772 P.NewLine();
773 typesetLinesAndColumns(P, Begin, Block);
774 }
775 });
776
777 return Error::success();
778}
779
780Error DumpOutputStyle::dumpInlineeLines() {
781 printHeader(P, "Inlinee Lines");
782
783 iterateModuleSubsections<DebugInlineeLinesSubsectionRef>(
784 File, PrintScope{P, 2},
785 [this](uint32_t Modi, const SymbolGroup &Strings,
786 DebugInlineeLinesSubsectionRef &Lines) {
787 P.formatLine("{0,+8} | {1,+5} | {2}", "Inlinee", "Line", "Source File");
788 for (const auto &Entry : Lines) {
789 P.formatLine("{0,+8} | {1,+5} | ", Entry.Header->Inlinee,
790 fmtle(Entry.Header->SourceLineNum));
791 Strings.formatFromChecksumsOffset(P, Entry.Header->FileID, true);
792 }
793 P.NewLine();
794 });
795
796 return Error::success();
797}
798
799Error DumpOutputStyle::dumpXmi() {
800 printHeader(P, "Cross Module Imports");
801 iterateModuleSubsections<DebugCrossModuleImportsSubsectionRef>(
802 File, PrintScope{P, 2},
803 [this](uint32_t Modi, const SymbolGroup &Strings,
804 DebugCrossModuleImportsSubsectionRef &Imports) {
805 P.formatLine("{0,=32} | {1}", "Imported Module", "Type IDs");
806
807 for (const auto &Xmi : Imports) {
808 auto ExpectedModule =
809 Strings.getNameFromStringTable(Xmi.Header->ModuleNameOffset);
810 StringRef Module;
811 SmallString<32> ModuleStorage;
812 if (!ExpectedModule) {
813 Module = "(unknown module)";
814 consumeError(ExpectedModule.takeError());
815 } else
816 Module = *ExpectedModule;
817 if (Module.size() > 32) {
818 ModuleStorage = "...";
819 ModuleStorage += Module.take_back(32 - 3);
820 Module = ModuleStorage;
821 }
822 std::vector<std::string> TIs;
823 for (const auto I : Xmi.Imports)
824 TIs.push_back(formatv("{0,+10:X+}", fmtle(I)));
825 std::string Result =
826 typesetItemList(TIs, P.getIndentLevel() + 35, 12, " ");
827 P.formatLine("{0,+32} | {1}", Module, Result);
828 }
829 });
830
831 return Error::success();
832}
833
834Error DumpOutputStyle::dumpXme() {
835 printHeader(P, "Cross Module Exports");
836
837 iterateModuleSubsections<DebugCrossModuleExportsSubsectionRef>(
838 File, PrintScope{P, 2},
839 [this](uint32_t Modi, const SymbolGroup &Strings,
840 DebugCrossModuleExportsSubsectionRef &Exports) {
841 P.formatLine("{0,-10} | {1}", "Local ID", "Global ID");
842 for (const auto &Export : Exports) {
843 P.formatLine("{0,+10:X+} | {1}", TypeIndex(Export.Local),
844 TypeIndex(Export.Global));
845 }
846 });
847
848 return Error::success();
849}
850
851Error DumpOutputStyle::dumpStringTable() {
852 printHeader(P, "String Table");
853
854 if (File.isObj()) {
855 P.formatLine("Dumping string table is not supported for object files");
856 return Error::success();
857 }
858
859 AutoIndent Indent(P);
860 auto IS = getPdb().getStringTable();
861 if (!IS) {
862 P.formatLine("Not present in file");
863 consumeError(IS.takeError());
864 return Error::success();
865 }
866
867 if (IS->name_ids().empty()) {
868 P.formatLine("Empty");
869 return Error::success();
870 }
871
872 auto MaxID = std::max_element(IS->name_ids().begin(), IS->name_ids().end());
873 uint32_t Digits = NumDigits(*MaxID);
874
875 P.formatLine("{0} | {1}", fmt_align("ID", AlignStyle::Right, Digits),
876 "String");
877
878 std::vector<uint32_t> SortedIDs(IS->name_ids().begin(), IS->name_ids().end());
879 std::sort(SortedIDs.begin(), SortedIDs.end());
880 for (uint32_t I : SortedIDs) {
881 auto ES = IS->getStringForID(I);
882 llvm::SmallString<32> Str;
883 if (!ES) {
884 consumeError(ES.takeError());
885 Str = "Error reading string";
886 } else if (!ES->empty()) {
887 Str.append("'");
888 Str.append(*ES);
889 Str.append("'");
890 }
891
892 if (!Str.empty())
893 P.formatLine("{0} | {1}", fmt_align(I, AlignStyle::Right, Digits), Str);
894 }
895 return Error::success();
896}
897
898static void buildDepSet(LazyRandomTypeCollection &Types,
899 ArrayRef<TypeIndex> Indices,
900 std::map<TypeIndex, CVType> &DepSet) {
901 SmallVector<TypeIndex, 4> DepList;
902 for (const auto &I : Indices) {
903 TypeIndex TI(I);
904 if (DepSet.find(TI) != DepSet.end() || TI.isSimple() || TI.isNoneType())
905 continue;
906
907 CVType Type = Types.getType(TI);
908 DepSet[TI] = Type;
909 codeview::discoverTypeIndices(Type, DepList);
910 buildDepSet(Types, DepList, DepSet);
911 }
912}
913
914static void
915dumpFullTypeStream(LinePrinter &Printer, LazyRandomTypeCollection &Types,
916 uint32_t NumTypeRecords, uint32_t NumHashBuckets,
917 FixedStreamArray<support::ulittle32_t> HashValues,
918 bool Bytes, bool Extras) {
919
920 Printer.formatLine("Showing {0:N} records", NumTypeRecords);
921 uint32_t Width = NumDigits(TypeIndex::FirstNonSimpleIndex + NumTypeRecords);
922
923 MinimalTypeDumpVisitor V(Printer, Width + 2, Bytes, Extras, Types,
924 NumHashBuckets, HashValues);
925
926 if (auto EC = codeview::visitTypeStream(Types, V)) {
927 Printer.formatLine("An error occurred dumping type records: {0}",
928 toString(std::move(EC)));
929 }
930}
931
932static void dumpPartialTypeStream(LinePrinter &Printer,
933 LazyRandomTypeCollection &Types,
934 TpiStream &Stream, ArrayRef<TypeIndex> TiList,
935 bool Bytes, bool Extras, bool Deps) {
936 uint32_t Width =
937 NumDigits(TypeIndex::FirstNonSimpleIndex + Stream.getNumTypeRecords());
938
939 MinimalTypeDumpVisitor V(Printer, Width + 2, Bytes, Extras, Types,
940 Stream.getNumHashBuckets(), Stream.getHashValues());
941
942 if (opts::dump::DumpTypeDependents) {
943 // If we need to dump all dependents, then iterate each index and find
944 // all dependents, adding them to a map ordered by TypeIndex.
945 std::map<TypeIndex, CVType> DepSet;
946 buildDepSet(Types, TiList, DepSet);
947
948 Printer.formatLine(
949 "Showing {0:N} records and their dependents ({1:N} records total)",
950 TiList.size(), DepSet.size());
951
952 for (auto &Dep : DepSet) {
953 if (auto EC = codeview::visitTypeRecord(Dep.second, Dep.first, V))
954 Printer.formatLine("An error occurred dumping type record {0}: {1}",
955 Dep.first, toString(std::move(EC)));
956 }
957 } else {
958 Printer.formatLine("Showing {0:N} records.", TiList.size());
959
960 for (const auto &I : TiList) {
961 TypeIndex TI(I);
962 CVType Type = Types.getType(TI);
963 if (auto EC = codeview::visitTypeRecord(Type, TI, V))
964 Printer.formatLine("An error occurred dumping type record {0}: {1}", TI,
965 toString(std::move(EC)));
966 }
967 }
968}
969
970Error DumpOutputStyle::dumpTypesFromObjectFile() {
971 LazyRandomTypeCollection Types(100);
972
973 for (const auto &S : getObj().sections()) {
974 StringRef SectionName;
975 if (auto EC = S.getName(SectionName))
1
Taking false branch
66
Taking false branch
976 return errorCodeToError(EC);
977
978 if (SectionName != ".debug$T")
2
Taking false branch
67
Taking false branch
979 continue;
980 StringRef Contents;
981 if (auto EC = S.getContents(Contents))
3
Taking false branch
68
Taking false branch
982 return errorCodeToError(EC);
983
984 uint32_t Magic;
69
'Magic' declared without an initial value
985 BinaryStreamReader Reader(Contents, llvm::support::little);
986 if (auto EC = Reader.readInteger(Magic))
4
Calling 'BinaryStreamReader::readInteger'
58
Returning from 'BinaryStreamReader::readInteger'
59
Taking false branch
70
Calling 'BinaryStreamReader::readInteger'
115
Returning from 'BinaryStreamReader::readInteger'
116
Taking false branch
987 return EC;
988 if (Magic != COFF::DEBUG_SECTION_MAGIC)
60
Assuming 'Magic' is equal to DEBUG_SECTION_MAGIC
61
Taking false branch
117
The left operand of '!=' is a garbage value
989 return make_error<StringError>("Invalid CodeView debug section.",
990 inconvertibleErrorCode());
991
992 Types.reset(Reader, 100);
993
994 if (opts::dump::DumpTypes) {
62
Assuming the condition is false
63
Taking false branch
995 dumpFullTypeStream(P, Types, 0, 0, {}, opts::dump::DumpTypeData, false);
996 } else if (opts::dump::DumpTypeExtras) {
64
Assuming the condition is false
65
Taking false branch
997 auto LocalHashes = LocallyHashedType::hashTypeCollection(Types);
998 auto GlobalHashes = GloballyHashedType::hashTypeCollection(Types);
999 assert(LocalHashes.size() == GlobalHashes.size())(static_cast <bool> (LocalHashes.size() == GlobalHashes
.size()) ? void (0) : __assert_fail ("LocalHashes.size() == GlobalHashes.size()"
, "/build/llvm-toolchain-snapshot-6.0~svn321639/tools/llvm-pdbutil/DumpOutputStyle.cpp"
, 999, __extension__ __PRETTY_FUNCTION__))
;
1000
1001 P.formatLine("Local / Global hashes:");
1002 TypeIndex TI(TypeIndex::FirstNonSimpleIndex);
1003 for (const auto &H : zip(LocalHashes, GlobalHashes)) {
1004 AutoIndent Indent2(P);
1005 LocallyHashedType &L = std::get<0>(H);
1006 GloballyHashedType &G = std::get<1>(H);
1007
1008 P.formatLine("TI: {0}, LocalHash: {1:X}, GlobalHash: {2}", TI, L, G);
1009
1010 ++TI;
1011 }
1012 P.NewLine();
1013 }
1014 }
1015
1016 return Error::success();
1017}
1018
1019Error DumpOutputStyle::dumpTpiStream(uint32_t StreamIdx) {
1020 assert(StreamIdx == StreamTPI || StreamIdx == StreamIPI)(static_cast <bool> (StreamIdx == StreamTPI || StreamIdx
== StreamIPI) ? void (0) : __assert_fail ("StreamIdx == StreamTPI || StreamIdx == StreamIPI"
, "/build/llvm-toolchain-snapshot-6.0~svn321639/tools/llvm-pdbutil/DumpOutputStyle.cpp"
, 1020, __extension__ __PRETTY_FUNCTION__))
;
1021
1022 if (StreamIdx == StreamTPI) {
1023 printHeader(P, "Types (TPI Stream)");
1024 } else if (StreamIdx == StreamIPI) {
1025 printHeader(P, "Types (IPI Stream)");
1026 }
1027
1028 AutoIndent Indent(P);
1029 assert(!File.isObj())(static_cast <bool> (!File.isObj()) ? void (0) : __assert_fail
("!File.isObj()", "/build/llvm-toolchain-snapshot-6.0~svn321639/tools/llvm-pdbutil/DumpOutputStyle.cpp"
, 1029, __extension__ __PRETTY_FUNCTION__))
;
1030
1031 bool Present = false;
1032 bool DumpTypes = false;
1033 bool DumpBytes = false;
1034 bool DumpExtras = false;
1035 std::vector<uint32_t> Indices;
1036 if (StreamIdx == StreamTPI) {
1037 Present = getPdb().hasPDBTpiStream();
1038 DumpTypes = opts::dump::DumpTypes;
1039 DumpBytes = opts::dump::DumpTypeData;
1040 DumpExtras = opts::dump::DumpTypeExtras;
1041 Indices.assign(opts::dump::DumpTypeIndex.begin(),
1042 opts::dump::DumpTypeIndex.end());
1043 } else if (StreamIdx == StreamIPI) {
1044 Present = getPdb().hasPDBIpiStream();
1045 DumpTypes = opts::dump::DumpIds;
1046 DumpBytes = opts::dump::DumpIdData;
1047 DumpExtras = opts::dump::DumpIdExtras;
1048 Indices.assign(opts::dump::DumpIdIndex.begin(),
1049 opts::dump::DumpIdIndex.end());
1050 }
1051
1052 if (!Present) {
1053 P.formatLine("Stream not present");
1054 return Error::success();
1055 }
1056
1057 ExitOnError Err("Unexpected error processing types: ");
1058
1059 auto &Stream = Err((StreamIdx == StreamTPI) ? getPdb().getPDBTpiStream()
1060 : getPdb().getPDBIpiStream());
1061
1062 auto &Types = (StreamIdx == StreamTPI) ? File.types() : File.ids();
1063
1064 if (DumpTypes || !Indices.empty()) {
1065 if (Indices.empty())
1066 dumpFullTypeStream(P, Types, Stream.getNumTypeRecords(),
1067 Stream.getNumHashBuckets(), Stream.getHashValues(),
1068 DumpBytes, DumpExtras);
1069 else {
1070 std::vector<TypeIndex> TiList(Indices.begin(), Indices.end());
1071 dumpPartialTypeStream(P, Types, Stream, TiList, DumpBytes, DumpExtras,
1072 opts::dump::DumpTypeDependents);
1073 }
1074 }
1075
1076 if (DumpExtras) {
1077 P.NewLine();
1078 auto IndexOffsets = Stream.getTypeIndexOffsets();
1079 P.formatLine("Type Index Offsets:");
1080 for (const auto &IO : IndexOffsets) {
1081 AutoIndent Indent2(P);
1082 P.formatLine("TI: {0}, Offset: {1}", IO.Type, fmtle(IO.Offset));
1083 }
1084
1085 P.NewLine();
1086 P.formatLine("Hash Adjusters:");
1087 auto &Adjusters = Stream.getHashAdjusters();
1088 auto &Strings = Err(getPdb().getStringTable());
1089 for (const auto &A : Adjusters) {
1090 AutoIndent Indent2(P);
1091 auto ExpectedStr = Strings.getStringForID(A.first);
1092 TypeIndex TI(A.second);
1093 if (ExpectedStr)
1094 P.formatLine("`{0}` -> {1}", *ExpectedStr, TI);
1095 else {
1096 P.formatLine("unknown str id ({0}) -> {1}", A.first, TI);
1097 consumeError(ExpectedStr.takeError());
1098 }
1099 }
1100 }
1101 return Error::success();
1102}
1103
1104Error DumpOutputStyle::dumpModuleSymsForObj() {
1105 printHeader(P, "Symbols");
1106
1107 AutoIndent Indent(P);
1108
1109 ExitOnError Err("Unexpected error processing symbols: ");
1110
1111 auto &Types = File.types();
1112
1113 SymbolVisitorCallbackPipeline Pipeline;
1114 SymbolDeserializer Deserializer(nullptr, CodeViewContainer::ObjectFile);
1115 MinimalSymbolDumper Dumper(P, opts::dump::DumpSymRecordBytes, Types, Types);
1116
1117 Pipeline.addCallbackToPipeline(Deserializer);
1118 Pipeline.addCallbackToPipeline(Dumper);
1119 CVSymbolVisitor Visitor(Pipeline);
1120
1121 std::unique_ptr<llvm::Error> SymbolError;
1122
1123 iterateModuleSubsections<DebugSymbolsSubsectionRef>(
1124 File, PrintScope{P, 2},
1125 [&](uint32_t Modi, const SymbolGroup &Strings,
1126 DebugSymbolsSubsectionRef &Symbols) {
1127 for (auto Symbol : Symbols) {
1128 if (auto EC = Visitor.visitSymbolRecord(Symbol)) {
1129 SymbolError = llvm::make_unique<Error>(std::move(EC));
1130 return;
1131 }
1132 }
1133 });
1134
1135 if (SymbolError)
1136 return std::move(*SymbolError);
1137
1138 return Error::success();
1139}
1140
1141Error DumpOutputStyle::dumpModuleSymsForPdb() {
1142 printHeader(P, "Symbols");
1143
1144 AutoIndent Indent(P);
1145 if (!getPdb().hasPDBDbiStream()) {
1146 P.formatLine("DBI Stream not present");
1147 return Error::success();
1148 }
1149
1150 ExitOnError Err("Unexpected error processing symbols: ");
1151
1152 auto &Ids = File.ids();
1153 auto &Types = File.types();
1154
1155 iterateSymbolGroups(
1156 File, PrintScope{P, 2}, [&](uint32_t I, const SymbolGroup &Strings) {
1157 auto ExpectedModS = getModuleDebugStream(File.pdb(), I);
1158 if (!ExpectedModS) {
1159 P.formatLine("Error loading module stream {0}. {1}", I,
1160 toString(ExpectedModS.takeError()));
1161 return;
1162 }
1163
1164 ModuleDebugStreamRef &ModS = *ExpectedModS;
1165
1166 SymbolVisitorCallbackPipeline Pipeline;
1167 SymbolDeserializer Deserializer(nullptr, CodeViewContainer::Pdb);
1168 MinimalSymbolDumper Dumper(P, opts::dump::DumpSymRecordBytes, Ids,
1169 Types);
1170
1171 Pipeline.addCallbackToPipeline(Deserializer);
1172 Pipeline.addCallbackToPipeline(Dumper);
1173 CVSymbolVisitor Visitor(Pipeline);
1174 auto SS = ModS.getSymbolsSubstream();
1175 if (auto EC =
1176 Visitor.visitSymbolStream(ModS.getSymbolArray(), SS.Offset)) {
1177 P.formatLine("Error while processing symbol records. {0}",
1178 toString(std::move(EC)));
1179 return;
1180 }
1181 });
1182 return Error::success();
1183}
1184
1185Error DumpOutputStyle::dumpGlobals() {
1186 printHeader(P, "Global Symbols");
1187 AutoIndent Indent(P);
1188
1189 if (File.isObj()) {
1190 P.formatLine("Dumping Globals is not supported for object files");
1191 return Error::success();
1192 }
1193
1194 if (!getPdb().hasPDBGlobalsStream()) {
1195 P.formatLine("Globals stream not present");
1196 return Error::success();
1197 }
1198 ExitOnError Err("Error dumping globals stream: ");
1199 auto &Globals = Err(getPdb().getPDBGlobalsStream());
1200
1201 const GSIHashTable &Table = Globals.getGlobalsTable();
1202 Err(dumpSymbolsFromGSI(Table, opts::dump::DumpGlobalExtras));
1203 return Error::success();
1204}
1205
1206Error DumpOutputStyle::dumpPublics() {
1207 printHeader(P, "Public Symbols");
1208 AutoIndent Indent(P);
1209
1210 if (File.isObj()) {
1211 P.formatLine("Dumping Globals is not supported for object files");
1212 return Error::success();
1213 }
1214
1215 if (!getPdb().hasPDBPublicsStream()) {
1216 P.formatLine("Publics stream not present");
1217 return Error::success();
1218 }
1219 ExitOnError Err("Error dumping publics stream: ");
1220 auto &Publics = Err(getPdb().getPDBPublicsStream());
1221
1222 const GSIHashTable &PublicsTable = Publics.getPublicsTable();
1223 if (opts::dump::DumpPublicExtras) {
1224 P.printLine("Publics Header");
1225 AutoIndent Indent(P);
1226 P.formatLine("sym hash = {0}, thunk table addr = {1}", Publics.getSymHash(),
1227 formatSegmentOffset(Publics.getThunkTableSection(),
1228 Publics.getThunkTableOffset()));
1229 }
1230 Err(dumpSymbolsFromGSI(PublicsTable, opts::dump::DumpPublicExtras));
1231
1232 // Skip the rest if we aren't dumping extras.
1233 if (!opts::dump::DumpPublicExtras)
1234 return Error::success();
1235
1236 P.formatLine("Address Map");
1237 {
1238 // These are offsets into the publics stream sorted by secidx:secrel.
1239 AutoIndent Indent2(P);
1240 for (uint32_t Addr : Publics.getAddressMap())
1241 P.formatLine("off = {0}", Addr);
1242 }
1243
1244 // The thunk map is optional debug info used for ILT thunks.
1245 if (!Publics.getThunkMap().empty()) {
1246 P.formatLine("Thunk Map");
1247 AutoIndent Indent2(P);
1248 for (uint32_t Addr : Publics.getThunkMap())
1249 P.formatLine("{0:x8}", Addr);
1250 }
1251
1252 // The section offsets table appears to be empty when incremental linking
1253 // isn't in use.
1254 if (!Publics.getSectionOffsets().empty()) {
1255 P.formatLine("Section Offsets");
1256 AutoIndent Indent2(P);
1257 for (const SectionOffset &SO : Publics.getSectionOffsets())
1258 P.formatLine("{0:x4}:{1:x8}", uint16_t(SO.Isect), uint32_t(SO.Off));
1259 }
1260
1261 return Error::success();
1262}
1263
1264Error DumpOutputStyle::dumpSymbolsFromGSI(const GSIHashTable &Table,
1265 bool HashExtras) {
1266 auto ExpectedSyms = getPdb().getPDBSymbolStream();
1267 if (!ExpectedSyms)
1268 return ExpectedSyms.takeError();
1269 auto &Types = File.types();
1270 auto &Ids = File.ids();
1271
1272 if (HashExtras) {
1273 P.printLine("GSI Header");
1274 AutoIndent Indent(P);
1275 P.formatLine("sig = {0:X}, hdr = {1:X}, hr size = {2}, num buckets = {3}",
1276 Table.getVerSignature(), Table.getVerHeader(),
1277 Table.getHashRecordSize(), Table.getNumBuckets());
1278 }
1279
1280 {
1281 P.printLine("Records");
1282 SymbolVisitorCallbackPipeline Pipeline;
1283 SymbolDeserializer Deserializer(nullptr, CodeViewContainer::Pdb);
1284 MinimalSymbolDumper Dumper(P, opts::dump::DumpSymRecordBytes, Ids, Types);
1285
1286 Pipeline.addCallbackToPipeline(Deserializer);
1287 Pipeline.addCallbackToPipeline(Dumper);
1288 CVSymbolVisitor Visitor(Pipeline);
1289
1290 BinaryStreamRef SymStream =
1291 ExpectedSyms->getSymbolArray().getUnderlyingStream();
1292 for (uint32_t PubSymOff : Table) {
1293 Expected<CVSymbol> Sym = readSymbolFromStream(SymStream, PubSymOff);
1294 if (!Sym)
1295 return Sym.takeError();
1296 if (auto E = Visitor.visitSymbolRecord(*Sym, PubSymOff))
1297 return E;
1298 }
1299 }
1300
1301 // Return early if we aren't dumping public hash table and address map info.
1302 if (!HashExtras)
1303 return Error::success();
1304
1305 P.formatLine("Hash Entries");
1306 {
1307 AutoIndent Indent2(P);
1308 for (const PSHashRecord &HR : Table.HashRecords)
1309 P.formatLine("off = {0}, refcnt = {1}", uint32_t(HR.Off),
1310 uint32_t(HR.CRef));
1311 }
1312
1313 // FIXME: Dump the bitmap.
1314
1315 P.formatLine("Hash Buckets");
1316 {
1317 AutoIndent Indent2(P);
1318 for (uint32_t Hash : Table.HashBuckets)
1319 P.formatLine("{0:x8}", Hash);
1320 }
1321
1322 return Error::success();
1323}
1324
1325static std::string formatSegMapDescriptorFlag(uint32_t IndentLevel,
1326 OMFSegDescFlags Flags) {
1327 std::vector<std::string> Opts;
1328 if (Flags == OMFSegDescFlags::None)
1329 return "none";
1330
1331 PUSH_FLAG(OMFSegDescFlags, Read, Flags, "read")if (OMFSegDescFlags::Read == (Flags & OMFSegDescFlags::Read
)) Opts.push_back("read");
;
1332 PUSH_FLAG(OMFSegDescFlags, Write, Flags, "write")if (OMFSegDescFlags::Write == (Flags & OMFSegDescFlags::Write
)) Opts.push_back("write");
;
1333 PUSH_FLAG(OMFSegDescFlags, Execute, Flags, "execute")if (OMFSegDescFlags::Execute == (Flags & OMFSegDescFlags::
Execute)) Opts.push_back("execute");
;
1334 PUSH_FLAG(OMFSegDescFlags, AddressIs32Bit, Flags, "32 bit addr")if (OMFSegDescFlags::AddressIs32Bit == (Flags & OMFSegDescFlags
::AddressIs32Bit)) Opts.push_back("32 bit addr");
;
1335 PUSH_FLAG(OMFSegDescFlags, IsSelector, Flags, "selector")if (OMFSegDescFlags::IsSelector == (Flags & OMFSegDescFlags
::IsSelector)) Opts.push_back("selector");
;
1336 PUSH_FLAG(OMFSegDescFlags, IsAbsoluteAddress, Flags, "absolute addr")if (OMFSegDescFlags::IsAbsoluteAddress == (Flags & OMFSegDescFlags
::IsAbsoluteAddress)) Opts.push_back("absolute addr");
;
1337 PUSH_FLAG(OMFSegDescFlags, IsGroup, Flags, "group")if (OMFSegDescFlags::IsGroup == (Flags & OMFSegDescFlags::
IsGroup)) Opts.push_back("group");
;
1338 return typesetItemList(Opts, IndentLevel, 4, " | ");
1339}
1340
1341Error DumpOutputStyle::dumpSectionHeaders() {
1342 dumpSectionHeaders("Section Headers", DbgHeaderType::SectionHdr);
1343 dumpSectionHeaders("Original Section Headers", DbgHeaderType::SectionHdrOrig);
1344 return Error::success();
1345}
1346
1347static Expected<std::pair<std::unique_ptr<MappedBlockStream>,
1348 ArrayRef<llvm::object::coff_section>>>
1349loadSectionHeaders(PDBFile &File, DbgHeaderType Type) {
1350 if (!File.hasPDBDbiStream())
1351 return make_error<StringError>(
1352 "Section headers require a DBI Stream, which could not be loaded",
1353 inconvertibleErrorCode());
1354
1355 auto &Dbi = cantFail(File.getPDBDbiStream());
1356 uint32_t SI = Dbi.getDebugStreamIndex(Type);
1357
1358 if (SI == kInvalidStreamIndex)
1359 return make_error<StringError>(
1360 "PDB does not contain the requested image section header type",
1361 inconvertibleErrorCode());
1362
1363 auto Stream = File.createIndexedStream(SI);
1364 if (!Stream)
1365 return make_error<StringError>("Could not load the required stream data",
1366 inconvertibleErrorCode());
1367
1368 ArrayRef<object::coff_section> Headers;
1369 if (Stream->getLength() % sizeof(object::coff_section) != 0)
1370 return make_error<StringError>(
1371 "Section header array size is not a multiple of section header size",
1372 inconvertibleErrorCode());
1373
1374 uint32_t NumHeaders = Stream->getLength() / sizeof(object::coff_section);
1375 BinaryStreamReader Reader(*Stream);
1376 cantFail(Reader.readArray(Headers, NumHeaders));
1377 return std::make_pair(std::move(Stream), Headers);
1378}
1379
1380void DumpOutputStyle::dumpSectionHeaders(StringRef Label, DbgHeaderType Type) {
1381 printHeader(P, Label);
1382
1383 AutoIndent Indent(P);
1384 if (File.isObj()) {
1385 P.formatLine("Dumping Section Headers is not supported for object files");
1386 return;
1387 }
1388
1389 ExitOnError Err("Error dumping section headers: ");
1390 std::unique_ptr<MappedBlockStream> Stream;
1391 ArrayRef<object::coff_section> Headers;
1392 auto ExpectedHeaders = loadSectionHeaders(getPdb(), Type);
1393 if (!ExpectedHeaders) {
1394 P.printLine(toString(ExpectedHeaders.takeError()));
1395 return;
1396 }
1397 std::tie(Stream, Headers) = std::move(*ExpectedHeaders);
1398
1399 uint32_t I = 1;
1400 for (const auto &Header : Headers) {
1401 P.NewLine();
1402 P.formatLine("SECTION HEADER #{0}", I);
1403 P.formatLine("{0,8} name", Header.Name);
1404 P.formatLine("{0,8:X-} virtual size", uint32_t(Header.VirtualSize));
1405 P.formatLine("{0,8:X-} virtual address", uint32_t(Header.VirtualAddress));
1406 P.formatLine("{0,8:X-} size of raw data", uint32_t(Header.SizeOfRawData));
1407 P.formatLine("{0,8:X-} file pointer to raw data",
1408 uint32_t(Header.PointerToRawData));
1409 P.formatLine("{0,8:X-} file pointer to relocation table",
1410 uint32_t(Header.PointerToRelocations));
1411 P.formatLine("{0,8:X-} file pointer to line numbers",
1412 uint32_t(Header.PointerToLinenumbers));
1413 P.formatLine("{0,8:X-} number of relocations",
1414 uint32_t(Header.NumberOfRelocations));
1415 P.formatLine("{0,8:X-} number of line numbers",
1416 uint32_t(Header.NumberOfLinenumbers));
1417 P.formatLine("{0,8:X-} flags", uint32_t(Header.Characteristics));
1418 AutoIndent IndentMore(P, 9);
1419 P.formatLine("{0}", formatSectionCharacteristics(
1420 P.getIndentLevel(), Header.Characteristics, 1, ""));
1421 ++I;
1422 }
1423 return;
1424}
1425
1426std::vector<std::string> getSectionNames(PDBFile &File) {
1427 auto ExpectedHeaders = loadSectionHeaders(File, DbgHeaderType::SectionHdr);
1428 if (!ExpectedHeaders)
1429 return {};
1430
1431 std::unique_ptr<MappedBlockStream> Stream;
1432 ArrayRef<object::coff_section> Headers;
1433 std::tie(Stream, Headers) = std::move(*ExpectedHeaders);
1434 std::vector<std::string> Names;
1435 for (const auto &H : Headers)
1436 Names.push_back(H.Name);
1437 return Names;
1438}
1439
1440Error DumpOutputStyle::dumpSectionContribs() {
1441 printHeader(P, "Section Contributions");
1442
1443 AutoIndent Indent(P);
1444 if (File.isObj()) {
1445 P.formatLine(
1446 "Dumping section contributions is not supported for object files");
1447 return Error::success();
1448 }
1449
1450 ExitOnError Err("Error dumping section contributions: ");
1451 if (!getPdb().hasPDBDbiStream()) {
1452 P.formatLine(
1453 "Section contribs require a DBI Stream, which could not be loaded");
1454 return Error::success();
1455 }
1456
1457 auto &Dbi = Err(getPdb().getPDBDbiStream());
1458
1459 class Visitor : public ISectionContribVisitor {
1460 public:
1461 Visitor(LinePrinter &P, ArrayRef<std::string> Names) : P(P), Names(Names) {
1462 auto Max = std::max_element(
1463 Names.begin(), Names.end(),
1464 [](StringRef S1, StringRef S2) { return S1.size() < S2.size(); });
1465 MaxNameLen = (Max == Names.end() ? 0 : Max->size());
1466 }
1467 void visit(const SectionContrib &SC) override {
1468 assert(SC.ISect > 0)(static_cast <bool> (SC.ISect > 0) ? void (0) : __assert_fail
("SC.ISect > 0", "/build/llvm-toolchain-snapshot-6.0~svn321639/tools/llvm-pdbutil/DumpOutputStyle.cpp"
, 1468, __extension__ __PRETTY_FUNCTION__))
;
1469 std::string NameInsert;
1470 if (SC.ISect < Names.size()) {
1471 StringRef SectionName = Names[SC.ISect - 1];
1472 NameInsert = formatv("[{0}]", SectionName).str();
1473 } else
1474 NameInsert = "[???]";
1475 P.formatLine("SC{5} | mod = {2}, {0}, size = {1}, data crc = {3}, reloc "
1476 "crc = {4}",
1477 formatSegmentOffset(SC.ISect, SC.Off), fmtle(SC.Size),
1478 fmtle(SC.Imod), fmtle(SC.DataCrc), fmtle(SC.RelocCrc),
1479 fmt_align(NameInsert, AlignStyle::Left, MaxNameLen + 2));
1480 AutoIndent Indent(P, MaxNameLen + 2);
1481 P.formatLine(" {0}",
1482 formatSectionCharacteristics(P.getIndentLevel() + 6,
1483 SC.Characteristics, 3, " | "));
1484 }
1485 void visit(const SectionContrib2 &SC) override {
1486 P.formatLine(
1487 "SC2[{6}] | mod = {2}, {0}, size = {1}, data crc = {3}, reloc "
1488 "crc = {4}, coff section = {5}",
1489 formatSegmentOffset(SC.Base.ISect, SC.Base.Off), fmtle(SC.Base.Size),
1490 fmtle(SC.Base.Imod), fmtle(SC.Base.DataCrc), fmtle(SC.Base.RelocCrc),
1491 fmtle(SC.ISectCoff));
1492 P.formatLine(" {0}", formatSectionCharacteristics(
1493 P.getIndentLevel() + 6,
1494 SC.Base.Characteristics, 3, " | "));
1495 }
1496
1497 private:
1498 LinePrinter &P;
1499 uint32_t MaxNameLen;
1500 ArrayRef<std::string> Names;
1501 };
1502
1503 std::vector<std::string> Names = getSectionNames(getPdb());
1504 Visitor V(P, makeArrayRef(Names));
1505 Dbi.visitSectionContributions(V);
1506 return Error::success();
1507}
1508
1509Error DumpOutputStyle::dumpSectionMap() {
1510 printHeader(P, "Section Map");
1511 AutoIndent Indent(P);
1512
1513 if (File.isObj()) {
1514 P.formatLine("Dumping section map is not supported for object files");
1515 return Error::success();
1516 }
1517
1518 ExitOnError Err("Error dumping section map: ");
1519
1520 if (!getPdb().hasPDBDbiStream()) {
1521 P.formatLine("Dumping the section map requires a DBI Stream, which could "
1522 "not be loaded");
1523 return Error::success();
1524 }
1525
1526 auto &Dbi = Err(getPdb().getPDBDbiStream());
1527
1528 uint32_t I = 0;
1529 for (auto &M : Dbi.getSectionMap()) {
1530 P.formatLine(
1531 "Section {0:4} | ovl = {1}, group = {2}, frame = {3}, name = {4}", I,
1532 fmtle(M.Ovl), fmtle(M.Group), fmtle(M.Frame), fmtle(M.SecName));
1533 P.formatLine(" class = {0}, offset = {1}, size = {2}",
1534 fmtle(M.ClassName), fmtle(M.Offset), fmtle(M.SecByteLength));
1535 P.formatLine(" flags = {0}",
1536 formatSegMapDescriptorFlag(
1537 P.getIndentLevel() + 13,
1538 static_cast<OMFSegDescFlags>(uint16_t(M.Flags))));
1539 ++I;
1540 }
1541 return Error::success();
1542}

/build/llvm-toolchain-snapshot-6.0~svn321639/include/llvm/Support/BinaryStreamReader.h

1//===- BinaryStreamReader.h - Reads objects from a binary stream *- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#ifndef LLVM_SUPPORT_BINARYSTREAMREADER_H
11#define LLVM_SUPPORT_BINARYSTREAMREADER_H
12
13#include "llvm/ADT/ArrayRef.h"
14#include "llvm/ADT/STLExtras.h"
15#include "llvm/Support/BinaryStreamArray.h"
16#include "llvm/Support/BinaryStreamRef.h"
17#include "llvm/Support/ConvertUTF.h"
18#include "llvm/Support/Endian.h"
19#include "llvm/Support/Error.h"
20#include "llvm/Support/type_traits.h"
21
22#include <string>
23#include <type_traits>
24
25namespace llvm {
26
27/// \brief Provides read only access to a subclass of `BinaryStream`. Provides
28/// bounds checking and helpers for writing certain common data types such as
29/// null-terminated strings, integers in various flavors of endianness, etc.
30/// Can be subclassed to provide reading of custom datatypes, although no
31/// are overridable.
32class BinaryStreamReader {
33public:
34 BinaryStreamReader() = default;
35 explicit BinaryStreamReader(BinaryStreamRef Ref);
36 explicit BinaryStreamReader(BinaryStream &Stream);
37 explicit BinaryStreamReader(ArrayRef<uint8_t> Data,
38 llvm::support::endianness Endian);
39 explicit BinaryStreamReader(StringRef Data, llvm::support::endianness Endian);
40
41 BinaryStreamReader(const BinaryStreamReader &Other)
42 : Stream(Other.Stream), Offset(Other.Offset) {}
43
44 BinaryStreamReader &operator=(const BinaryStreamReader &Other) {
45 Stream = Other.Stream;
46 Offset = Other.Offset;
47 return *this;
48 }
49
50 virtual ~BinaryStreamReader() {}
51
52 /// Read as much as possible from the underlying string at the current offset
53 /// without invoking a copy, and set \p Buffer to the resulting data slice.
54 /// Updates the stream's offset to point after the newly read data.
55 ///
56 /// \returns a success error code if the data was successfully read, otherwise
57 /// returns an appropriate error code.
58 Error readLongestContiguousChunk(ArrayRef<uint8_t> &Buffer);
59
60 /// Read \p Size bytes from the underlying stream at the current offset and
61 /// and set \p Buffer to the resulting data slice. Whether a copy occurs
62 /// depends on the implementation of the underlying stream. Updates the
63 /// stream's offset to point after the newly read data.
64 ///
65 /// \returns a success error code if the data was successfully read, otherwise
66 /// returns an appropriate error code.
67 Error readBytes(ArrayRef<uint8_t> &Buffer, uint32_t Size);
68
69 /// Read an integer of the specified endianness into \p Dest and update the
70 /// stream's offset. The data is always copied from the stream's underlying
71 /// buffer into \p Dest. Updates the stream's offset to point after the newly
72 /// read data.
73 ///
74 /// \returns a success error code if the data was successfully read, otherwise
75 /// returns an appropriate error code.
76 template <typename T> Error readInteger(T &Dest) {
77 static_assert(std::is_integral<T>::value,
78 "Cannot call readInteger with non-integral value!");
79
80 ArrayRef<uint8_t> Bytes;
81 if (auto EC = readBytes(Bytes, sizeof(T)))
5
Calling move constructor for 'Error'
29
Returning from move constructor for 'Error'
30
Calling 'Error::operator bool'
39
Returning from 'Error::operator bool'
40
Taking false branch
71
Calling move constructor for 'Error'
95
Returning from move constructor for 'Error'
96
Calling 'Error::operator bool'
105
Returning from 'Error::operator bool'
106
Taking true branch
82 return EC;
41
Calling '~Error'
48
Returning from '~Error'
107
Calling '~Error'
114
Returning from '~Error'
83
84 Dest = llvm::support::endian::read<T, llvm::support::unaligned>(
51
Calling 'read'
55
Returning from 'read'
85 Bytes.data(), Stream.getEndian());
49
Calling 'BinaryStreamRefBase::getEndian'
50
Returning from 'BinaryStreamRefBase::getEndian'
86 return Error::success();
56
Calling 'Error::success'
57
Returning from 'Error::success'
87 }
88
89 /// Similar to readInteger.
90 template <typename T> Error readEnum(T &Dest) {
91 static_assert(std::is_enum<T>::value,
92 "Cannot call readEnum with non-enum value!");
93 typename std::underlying_type<T>::type N;
94 if (auto EC = readInteger(N))
95 return EC;
96 Dest = static_cast<T>(N);
97 return Error::success();
98 }
99
100 /// Read a null terminated string from \p Dest. Whether a copy occurs depends
101 /// on the implementation of the underlying stream. Updates the stream's
102 /// offset to point after the newly read data.
103 ///
104 /// \returns a success error code if the data was successfully read, otherwise
105 /// returns an appropriate error code.
106 Error readCString(StringRef &Dest);
107
108 /// Similar to readCString, however read a null-terminated UTF16 string
109 /// instead.
110 ///
111 /// \returns a success error code if the data was successfully read, otherwise
112 /// returns an appropriate error code.
113 Error readWideString(ArrayRef<UTF16> &Dest);
114
115 /// Read a \p Length byte string into \p Dest. Whether a copy occurs depends
116 /// on the implementation of the underlying stream. Updates the stream's
117 /// offset to point after the newly read data.
118 ///
119 /// \returns a success error code if the data was successfully read, otherwise
120 /// returns an appropriate error code.
121 Error readFixedString(StringRef &Dest, uint32_t Length);
122
123 /// Read the entire remainder of the underlying stream into \p Ref. This is
124 /// equivalent to calling getUnderlyingStream().slice(Offset). Updates the
125 /// stream's offset to point to the end of the stream. Never causes a copy.
126 ///
127 /// \returns a success error code if the data was successfully read, otherwise
128 /// returns an appropriate error code.
129 Error readStreamRef(BinaryStreamRef &Ref);
130
131 /// Read \p Length bytes from the underlying stream into \p Ref. This is
132 /// equivalent to calling getUnderlyingStream().slice(Offset, Length).
133 /// Updates the stream's offset to point after the newly read object. Never
134 /// causes a copy.
135 ///
136 /// \returns a success error code if the data was successfully read, otherwise
137 /// returns an appropriate error code.
138 Error readStreamRef(BinaryStreamRef &Ref, uint32_t Length);
139
140 /// Read \p Length bytes from the underlying stream into \p Stream. This is
141 /// equivalent to calling getUnderlyingStream().slice(Offset, Length).
142 /// Updates the stream's offset to point after the newly read object. Never
143 /// causes a copy.
144 ///
145 /// \returns a success error code if the data was successfully read, otherwise
146 /// returns an appropriate error code.
147 Error readSubstream(BinarySubstreamRef &Stream, uint32_t Size);
148
149 /// Get a pointer to an object of type T from the underlying stream, as if by
150 /// memcpy, and store the result into \p Dest. It is up to the caller to
151 /// ensure that objects of type T can be safely treated in this manner.
152 /// Updates the stream's offset to point after the newly read object. Whether
153 /// a copy occurs depends upon the implementation of the underlying
154 /// stream.
155 ///
156 /// \returns a success error code if the data was successfully read, otherwise
157 /// returns an appropriate error code.
158 template <typename T> Error readObject(const T *&Dest) {
159 ArrayRef<uint8_t> Buffer;
160 if (auto EC = readBytes(Buffer, sizeof(T)))
161 return EC;
162 Dest = reinterpret_cast<const T *>(Buffer.data());
163 return Error::success();
164 }
165
166 /// Get a reference to a \p NumElements element array of objects of type T
167 /// from the underlying stream as if by memcpy, and store the resulting array
168 /// slice into \p array. It is up to the caller to ensure that objects of
169 /// type T can be safely treated in this manner. Updates the stream's offset
170 /// to point after the newly read object. Whether a copy occurs depends upon
171 /// the implementation of the underlying stream.
172 ///
173 /// \returns a success error code if the data was successfully read, otherwise
174 /// returns an appropriate error code.
175 template <typename T>
176 Error readArray(ArrayRef<T> &Array, uint32_t NumElements) {
177 ArrayRef<uint8_t> Bytes;
178 if (NumElements == 0) {
179 Array = ArrayRef<T>();
180 return Error::success();
181 }
182
183 if (NumElements > UINT32_MAX(4294967295U) / sizeof(T))
184 return make_error<BinaryStreamError>(
185 stream_error_code::invalid_array_size);
186
187 if (auto EC = readBytes(Bytes, NumElements * sizeof(T)))
188 return EC;
189
190 assert(alignmentAdjustment(Bytes.data(), alignof(T)) == 0 &&(static_cast <bool> (alignmentAdjustment(Bytes.data(), alignof
(T)) == 0 && "Reading at invalid alignment!") ? void (
0) : __assert_fail ("alignmentAdjustment(Bytes.data(), alignof(T)) == 0 && \"Reading at invalid alignment!\""
, "/build/llvm-toolchain-snapshot-6.0~svn321639/include/llvm/Support/BinaryStreamReader.h"
, 191, __extension__ __PRETTY_FUNCTION__))
191 "Reading at invalid alignment!")(static_cast <bool> (alignmentAdjustment(Bytes.data(), alignof
(T)) == 0 && "Reading at invalid alignment!") ? void (
0) : __assert_fail ("alignmentAdjustment(Bytes.data(), alignof(T)) == 0 && \"Reading at invalid alignment!\""
, "/build/llvm-toolchain-snapshot-6.0~svn321639/include/llvm/Support/BinaryStreamReader.h"
, 191, __extension__ __PRETTY_FUNCTION__))
;
192
193 Array = ArrayRef<T>(reinterpret_cast<const T *>(Bytes.data()), NumElements);
194 return Error::success();
195 }
196
197 /// Read a VarStreamArray of size \p Size bytes and store the result into
198 /// \p Array. Updates the stream's offset to point after the newly read
199 /// array. Never causes a copy (although iterating the elements of the
200 /// VarStreamArray may, depending upon the implementation of the underlying
201 /// stream).
202 ///
203 /// \returns a success error code if the data was successfully read, otherwise
204 /// returns an appropriate error code.
205 template <typename T, typename U>
206 Error readArray(VarStreamArray<T, U> &Array, uint32_t Size) {
207 BinaryStreamRef S;
208 if (auto EC = readStreamRef(S, Size))
209 return EC;
210 Array.setUnderlyingStream(S);
211 return Error::success();
212 }
213
214 /// Read a FixedStreamArray of \p NumItems elements and store the result into
215 /// \p Array. Updates the stream's offset to point after the newly read
216 /// array. Never causes a copy (although iterating the elements of the
217 /// FixedStreamArray may, depending upon the implementation of the underlying
218 /// stream).
219 ///
220 /// \returns a success error code if the data was successfully read, otherwise
221 /// returns an appropriate error code.
222 template <typename T>
223 Error readArray(FixedStreamArray<T> &Array, uint32_t NumItems) {
224 if (NumItems == 0) {
225 Array = FixedStreamArray<T>();
226 return Error::success();
227 }
228
229 if (NumItems > UINT32_MAX(4294967295U) / sizeof(T))
230 return make_error<BinaryStreamError>(
231 stream_error_code::invalid_array_size);
232
233 BinaryStreamRef View;
234 if (auto EC = readStreamRef(View, NumItems * sizeof(T)))
235 return EC;
236
237 Array = FixedStreamArray<T>(View);
238 return Error::success();
239 }
240
241 bool empty() const { return bytesRemaining() == 0; }
242 void setOffset(uint32_t Off) { Offset = Off; }
243 uint32_t getOffset() const { return Offset; }
244 uint32_t getLength() const { return Stream.getLength(); }
245 uint32_t bytesRemaining() const { return getLength() - getOffset(); }
246
247 /// Advance the stream's offset by \p Amount bytes.
248 ///
249 /// \returns a success error code if at least \p Amount bytes remain in the
250 /// stream, otherwise returns an appropriate error code.
251 Error skip(uint32_t Amount);
252
253 /// Examine the next byte of the underlying stream without advancing the
254 /// stream's offset. If the stream is empty the behavior is undefined.
255 ///
256 /// \returns the next byte in the stream.
257 uint8_t peek() const;
258
259 Error padToAlignment(uint32_t Align);
260
261 std::pair<BinaryStreamReader, BinaryStreamReader>
262 split(uint32_t Offset) const;
263
264private:
265 BinaryStreamRef Stream;
266 uint32_t Offset = 0;
267};
268} // namespace llvm
269
270#endif // LLVM_SUPPORT_BINARYSTREAMREADER_H

/build/llvm-toolchain-snapshot-6.0~svn321639/include/llvm/Support/Error.h

1//===- llvm/Support/Error.h - Recoverable error handling --------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file defines an API used to report recoverable errors.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef LLVM_SUPPORT_ERROR_H
15#define LLVM_SUPPORT_ERROR_H
16
17#include "llvm/ADT/SmallVector.h"
18#include "llvm/ADT/STLExtras.h"
19#include "llvm/ADT/StringExtras.h"
20#include "llvm/ADT/Twine.h"
21#include "llvm/Config/abi-breaking.h"
22#include "llvm/Support/AlignOf.h"
23#include "llvm/Support/Compiler.h"
24#include "llvm/Support/Debug.h"
25#include "llvm/Support/ErrorHandling.h"
26#include "llvm/Support/ErrorOr.h"
27#include "llvm/Support/raw_ostream.h"
28#include <algorithm>
29#include <cassert>
30#include <cstdint>
31#include <cstdlib>
32#include <functional>
33#include <memory>
34#include <new>
35#include <string>
36#include <system_error>
37#include <type_traits>
38#include <utility>
39#include <vector>
40
41namespace llvm {
42
43class ErrorSuccess;
44
45/// Base class for error info classes. Do not extend this directly: Extend
46/// the ErrorInfo template subclass instead.
47class ErrorInfoBase {
48public:
49 virtual ~ErrorInfoBase() = default;
50
51 /// Print an error message to an output stream.
52 virtual void log(raw_ostream &OS) const = 0;
53
54 /// Return the error message as a string.
55 virtual std::string message() const {
56 std::string Msg;
57 raw_string_ostream OS(Msg);
58 log(OS);
59 return OS.str();
60 }
61
62 /// Convert this error to a std::error_code.
63 ///
64 /// This is a temporary crutch to enable interaction with code still
65 /// using std::error_code. It will be removed in the future.
66 virtual std::error_code convertToErrorCode() const = 0;
67
68 // Returns the class ID for this type.
69 static const void *classID() { return &ID; }
70
71 // Returns the class ID for the dynamic type of this ErrorInfoBase instance.
72 virtual const void *dynamicClassID() const = 0;
73
74 // Check whether this instance is a subclass of the class identified by
75 // ClassID.
76 virtual bool isA(const void *const ClassID) const {
77 return ClassID == classID();
78 }
79
80 // Check whether this instance is a subclass of ErrorInfoT.
81 template <typename ErrorInfoT> bool isA() const {
82 return isA(ErrorInfoT::classID());
83 }
84
85private:
86 virtual void anchor();
87
88 static char ID;
89};
90
91/// Lightweight error class with error context and mandatory checking.
92///
93/// Instances of this class wrap a ErrorInfoBase pointer. Failure states
94/// are represented by setting the pointer to a ErrorInfoBase subclass
95/// instance containing information describing the failure. Success is
96/// represented by a null pointer value.
97///
98/// Instances of Error also contains a 'Checked' flag, which must be set
99/// before the destructor is called, otherwise the destructor will trigger a
100/// runtime error. This enforces at runtime the requirement that all Error
101/// instances be checked or returned to the caller.
102///
103/// There are two ways to set the checked flag, depending on what state the
104/// Error instance is in. For Error instances indicating success, it
105/// is sufficient to invoke the boolean conversion operator. E.g.:
106///
107/// @code{.cpp}
108/// Error foo(<...>);
109///
110/// if (auto E = foo(<...>))
111/// return E; // <- Return E if it is in the error state.
112/// // We have verified that E was in the success state. It can now be safely
113/// // destroyed.
114/// @endcode
115///
116/// A success value *can not* be dropped. For example, just calling 'foo(<...>)'
117/// without testing the return value will raise a runtime error, even if foo
118/// returns success.
119///
120/// For Error instances representing failure, you must use either the
121/// handleErrors or handleAllErrors function with a typed handler. E.g.:
122///
123/// @code{.cpp}
124/// class MyErrorInfo : public ErrorInfo<MyErrorInfo> {
125/// // Custom error info.
126/// };
127///
128/// Error foo(<...>) { return make_error<MyErrorInfo>(...); }
129///
130/// auto E = foo(<...>); // <- foo returns failure with MyErrorInfo.
131/// auto NewE =
132/// handleErrors(E,
133/// [](const MyErrorInfo &M) {
134/// // Deal with the error.
135/// },
136/// [](std::unique_ptr<OtherError> M) -> Error {
137/// if (canHandle(*M)) {
138/// // handle error.
139/// return Error::success();
140/// }
141/// // Couldn't handle this error instance. Pass it up the stack.
142/// return Error(std::move(M));
143/// );
144/// // Note - we must check or return NewE in case any of the handlers
145/// // returned a new error.
146/// @endcode
147///
148/// The handleAllErrors function is identical to handleErrors, except
149/// that it has a void return type, and requires all errors to be handled and
150/// no new errors be returned. It prevents errors (assuming they can all be
151/// handled) from having to be bubbled all the way to the top-level.
152///
153/// *All* Error instances must be checked before destruction, even if
154/// they're moved-assigned or constructed from Success values that have already
155/// been checked. This enforces checking through all levels of the call stack.
156class LLVM_NODISCARD[[clang::warn_unused_result]] Error {
157 // ErrorList needs to be able to yank ErrorInfoBase pointers out of this
158 // class to add to the error list.
159 friend class ErrorList;
160
161 // handleErrors needs to be able to set the Checked flag.
162 template <typename... HandlerTs>
163 friend Error handleErrors(Error E, HandlerTs &&... Handlers);
164
165 // Expected<T> needs to be able to steal the payload when constructed from an
166 // error.
167 template <typename T> friend class Expected;
168
169protected:
170 /// Create a success value. Prefer using 'Error::success()' for readability
171 Error() {
172 setPtr(nullptr);
173 setChecked(false);
174 }
175
176public:
177 /// Create a success value.
178 static ErrorSuccess success();
179
180 // Errors are not copy-constructable.
181 Error(const Error &Other) = delete;
182
183 /// Move-construct an error value. The newly constructed error is considered
184 /// unchecked, even if the source error had been checked. The original error
185 /// becomes a checked Success value, regardless of its original state.
186 Error(Error &&Other) {
187 setChecked(true);
6
Calling 'Error::setChecked'
8
Returning from 'Error::setChecked'
72
Calling 'Error::setChecked'
74
Returning from 'Error::setChecked'
188 *this = std::move(Other);
9
Calling 'move'
10
Returning from 'move'
11
Calling move assignment operator for 'Error'
28
Returning from move assignment operator for 'Error'
75
Calling 'move'
76
Returning from 'move'
77
Calling move assignment operator for 'Error'
94
Returning from move assignment operator for 'Error'
189 }
190
191 /// Create an error value. Prefer using the 'make_error' function, but
192 /// this constructor can be useful when "re-throwing" errors from handlers.
193 Error(std::unique_ptr<ErrorInfoBase> Payload) {
194 setPtr(Payload.release());
195 setChecked(false);
196 }
197
198 // Errors are not copy-assignable.
199 Error &operator=(const Error &Other) = delete;
200
201 /// Move-assign an error value. The current error must represent success, you
202 /// you cannot overwrite an unhandled error. The current error is then
203 /// considered unchecked. The source error becomes a checked success value,
204 /// regardless of its original state.
205 Error &operator=(Error &&Other) {
206 // Don't allow overwriting of unchecked values.
207 assertIsChecked();
12
Calling 'Error::assertIsChecked'
15
Returning from 'Error::assertIsChecked'
78
Calling 'Error::assertIsChecked'
81
Returning from 'Error::assertIsChecked'
208 setPtr(Other.getPtr());
16
Calling 'Error::getPtr'
17
Returning from 'Error::getPtr'
18
Calling 'Error::setPtr'
19
Returning from 'Error::setPtr'
82
Calling 'Error::getPtr'
83
Returning from 'Error::getPtr'
84
Calling 'Error::setPtr'
85
Returning from 'Error::setPtr'
209
210 // This Error is unchecked, even if the source error was checked.
211 setChecked(false);
20
Calling 'Error::setChecked'
22
Returning from 'Error::setChecked'
86
Calling 'Error::setChecked'
88
Returning from 'Error::setChecked'
212
213 // Null out Other's payload and set its checked bit.
214 Other.setPtr(nullptr);
23
Calling 'Error::setPtr'
24
Returning from 'Error::setPtr'
89
Calling 'Error::setPtr'
90
Returning from 'Error::setPtr'
215 Other.setChecked(true);
25
Calling 'Error::setChecked'
27
Returning from 'Error::setChecked'
91
Calling 'Error::setChecked'
93
Returning from 'Error::setChecked'
216
217 return *this;
218 }
219
220 /// Destroy a Error. Fails with a call to abort() if the error is
221 /// unchecked.
222 ~Error() {
223 assertIsChecked();
42
Calling 'Error::assertIsChecked'
45
Returning from 'Error::assertIsChecked'
108
Calling 'Error::assertIsChecked'
111
Returning from 'Error::assertIsChecked'
224 delete getPtr();
46
Calling 'Error::getPtr'
47
Returning from 'Error::getPtr'
112
Calling 'Error::getPtr'
113
Returning from 'Error::getPtr'
225 }
226
227 /// Bool conversion. Returns true if this Error is in a failure state,
228 /// and false if it is in an accept state. If the error is in a Success state
229 /// it will be considered checked.
230 explicit operator bool() {
231 setChecked(getPtr() == nullptr);
31
Calling 'Error::getPtr'
32
Returning from 'Error::getPtr'
33
Calling 'Error::setChecked'
36
Returning from 'Error::setChecked'
97
Calling 'Error::getPtr'
98
Returning from 'Error::getPtr'
99
Calling 'Error::setChecked'
102
Returning from 'Error::setChecked'
232 return getPtr() != nullptr;
37
Calling 'Error::getPtr'
38
Returning from 'Error::getPtr'
103
Calling 'Error::getPtr'
104
Returning from 'Error::getPtr'
233 }
234
235 /// Check whether one error is a subclass of another.
236 template <typename ErrT> bool isA() const {
237 return getPtr() && getPtr()->isA(ErrT::classID());
238 }
239
240 /// Returns the dynamic class id of this error, or null if this is a success
241 /// value.
242 const void* dynamicClassID() const {
243 if (!getPtr())
244 return nullptr;
245 return getPtr()->dynamicClassID();
246 }
247
248private:
249#if LLVM_ENABLE_ABI_BREAKING_CHECKS1
250 // assertIsChecked() happens very frequently, but under normal circumstances
251 // is supposed to be a no-op. So we want it to be inlined, but having a bunch
252 // of debug prints can cause the function to be too large for inlining. So
253 // it's important that we define this function out of line so that it can't be
254 // inlined.
255 LLVM_ATTRIBUTE_NORETURN__attribute__((noreturn))
256 void fatalUncheckedError() const;
257#endif
258
259 void assertIsChecked() {
260#if LLVM_ENABLE_ABI_BREAKING_CHECKS1
261 if (LLVM_UNLIKELY(!getChecked() || getPtr())__builtin_expect((bool)(!getChecked() || getPtr()), false))
13
Within the expansion of the macro 'LLVM_UNLIKELY':
a
Calling 'Error::getChecked'
b
Returning from 'Error::getChecked'
c
Calling 'Error::getPtr'
d
Returning from 'Error::getPtr'
14
Taking false branch
43
Within the expansion of the macro 'LLVM_UNLIKELY':
a
Calling 'Error::getChecked'
b
Returning from 'Error::getChecked'
c
Calling 'Error::getPtr'
d
Returning from 'Error::getPtr'
44
Taking false branch
79
Within the expansion of the macro 'LLVM_UNLIKELY':
a
Calling 'Error::getChecked'
b
Returning from 'Error::getChecked'
c
Calling 'Error::getPtr'
d
Returning from 'Error::getPtr'
80
Taking false branch
109
Within the expansion of the macro 'LLVM_UNLIKELY':
a
Calling 'Error::getChecked'
b
Returning from 'Error::getChecked'
110
Taking false branch
262 fatalUncheckedError();
263#endif
264 }
265
266 ErrorInfoBase *getPtr() const {
267 return reinterpret_cast<ErrorInfoBase*>(
268 reinterpret_cast<uintptr_t>(Payload) &
269 ~static_cast<uintptr_t>(0x1));
270 }
271
272 void setPtr(ErrorInfoBase *EI) {
273#if LLVM_ENABLE_ABI_BREAKING_CHECKS1
274 Payload = reinterpret_cast<ErrorInfoBase*>(
275 (reinterpret_cast<uintptr_t>(EI) &
276 ~static_cast<uintptr_t>(0x1)) |
277 (reinterpret_cast<uintptr_t>(Payload) & 0x1));
278#else
279 Payload = EI;
280#endif
281 }
282
283 bool getChecked() const {
284#if LLVM_ENABLE_ABI_BREAKING_CHECKS1
285 return (reinterpret_cast<uintptr_t>(Payload) & 0x1) == 0;
286#else
287 return true;
288#endif
289 }
290
291 void setChecked(bool V) {
292 Payload = reinterpret_cast<ErrorInfoBase*>(
293 (reinterpret_cast<uintptr_t>(Payload) &
294 ~static_cast<uintptr_t>(0x1)) |
295 (V ? 0 : 1));
7
'?' condition is true
21
'?' condition is false
26
'?' condition is true
34
Assuming 'V' is 0
35
'?' condition is false
73
'?' condition is true
87
'?' condition is false
92
'?' condition is true
100
Assuming 'V' is 0
101
'?' condition is false
296 }
297
298 std::unique_ptr<ErrorInfoBase> takePayload() {
299 std::unique_ptr<ErrorInfoBase> Tmp(getPtr());
300 setPtr(nullptr);
301 setChecked(true);
302 return Tmp;
303 }
304
305 ErrorInfoBase *Payload = nullptr;
306};
307
308/// Subclass of Error for the sole purpose of identifying the success path in
309/// the type system. This allows to catch invalid conversion to Expected<T> at
310/// compile time.
311class ErrorSuccess : public Error {};
312
313inline ErrorSuccess Error::success() { return ErrorSuccess(); }
314
315/// Make a Error instance representing failure using the given error info
316/// type.
317template <typename ErrT, typename... ArgTs> Error make_error(ArgTs &&... Args) {
318 return Error(llvm::make_unique<ErrT>(std::forward<ArgTs>(Args)...));
319}
320
321/// Base class for user error types. Users should declare their error types
322/// like:
323///
324/// class MyError : public ErrorInfo<MyError> {
325/// ....
326/// };
327///
328/// This class provides an implementation of the ErrorInfoBase::kind
329/// method, which is used by the Error RTTI system.
330template <typename ThisErrT, typename ParentErrT = ErrorInfoBase>
331class ErrorInfo : public ParentErrT {
332public:
333 static const void *classID() { return &ThisErrT::ID; }
334
335 const void *dynamicClassID() const override { return &ThisErrT::ID; }
336
337 bool isA(const void *const ClassID) const override {
338 return ClassID == classID() || ParentErrT::isA(ClassID);
339 }
340};
341
342/// Special ErrorInfo subclass representing a list of ErrorInfos.
343/// Instances of this class are constructed by joinError.
344class ErrorList final : public ErrorInfo<ErrorList> {
345 // handleErrors needs to be able to iterate the payload list of an
346 // ErrorList.
347 template <typename... HandlerTs>
348 friend Error handleErrors(Error E, HandlerTs &&... Handlers);
349
350 // joinErrors is implemented in terms of join.
351 friend Error joinErrors(Error, Error);
352
353public:
354 void log(raw_ostream &OS) const override {
355 OS << "Multiple errors:\n";
356 for (auto &ErrPayload : Payloads) {
357 ErrPayload->log(OS);
358 OS << "\n";
359 }
360 }
361
362 std::error_code convertToErrorCode() const override;
363
364 // Used by ErrorInfo::classID.
365 static char ID;
366
367private:
368 ErrorList(std::unique_ptr<ErrorInfoBase> Payload1,
369 std::unique_ptr<ErrorInfoBase> Payload2) {
370 assert(!Payload1->isA<ErrorList>() && !Payload2->isA<ErrorList>() &&(static_cast <bool> (!Payload1->isA<ErrorList>
() && !Payload2->isA<ErrorList>() &&
"ErrorList constructor payloads should be singleton errors")
? void (0) : __assert_fail ("!Payload1->isA<ErrorList>() && !Payload2->isA<ErrorList>() && \"ErrorList constructor payloads should be singleton errors\""
, "/build/llvm-toolchain-snapshot-6.0~svn321639/include/llvm/Support/Error.h"
, 371, __extension__ __PRETTY_FUNCTION__))
371 "ErrorList constructor payloads should be singleton errors")(static_cast <bool> (!Payload1->isA<ErrorList>
() && !Payload2->isA<ErrorList>() &&
"ErrorList constructor payloads should be singleton errors")
? void (0) : __assert_fail ("!Payload1->isA<ErrorList>() && !Payload2->isA<ErrorList>() && \"ErrorList constructor payloads should be singleton errors\""
, "/build/llvm-toolchain-snapshot-6.0~svn321639/include/llvm/Support/Error.h"
, 371, __extension__ __PRETTY_FUNCTION__))
;
372 Payloads.push_back(std::move(Payload1));
373 Payloads.push_back(std::move(Payload2));
374 }
375
376 static Error join(Error E1, Error E2) {
377 if (!E1)
378 return E2;
379 if (!E2)
380 return E1;
381 if (E1.isA<ErrorList>()) {
382 auto &E1List = static_cast<ErrorList &>(*E1.getPtr());
383 if (E2.isA<ErrorList>()) {
384 auto E2Payload = E2.takePayload();
385 auto &E2List = static_cast<ErrorList &>(*E2Payload);
386 for (auto &Payload : E2List.Payloads)
387 E1List.Payloads.push_back(std::move(Payload));
388 } else
389 E1List.Payloads.push_back(E2.takePayload());
390
391 return E1;
392 }
393 if (E2.isA<ErrorList>()) {
394 auto &E2List = static_cast<ErrorList &>(*E2.getPtr());
395 E2List.Payloads.insert(E2List.Payloads.begin(), E1.takePayload());
396 return E2;
397 }
398 return Error(std::unique_ptr<ErrorList>(
399 new ErrorList(E1.takePayload(), E2.takePayload())));
400 }
401
402 std::vector<std::unique_ptr<ErrorInfoBase>> Payloads;
403};
404
405/// Concatenate errors. The resulting Error is unchecked, and contains the
406/// ErrorInfo(s), if any, contained in E1, followed by the
407/// ErrorInfo(s), if any, contained in E2.
408inline Error joinErrors(Error E1, Error E2) {
409 return ErrorList::join(std::move(E1), std::move(E2));
410}
411
412/// Tagged union holding either a T or a Error.
413///
414/// This class parallels ErrorOr, but replaces error_code with Error. Since
415/// Error cannot be copied, this class replaces getError() with
416/// takeError(). It also adds an bool errorIsA<ErrT>() method for testing the
417/// error class type.
418template <class T> class LLVM_NODISCARD[[clang::warn_unused_result]] Expected {
419 template <class T1> friend class ExpectedAsOutParameter;
420 template <class OtherT> friend class Expected;
421
422 static const bool isRef = std::is_reference<T>::value;
423
424 using wrap = ReferenceStorage<typename std::remove_reference<T>::type>;
425
426 using error_type = std::unique_ptr<ErrorInfoBase>;
427
428public:
429 using storage_type = typename std::conditional<isRef, wrap, T>::type;
430 using value_type = T;
431
432private:
433 using reference = typename std::remove_reference<T>::type &;
434 using const_reference = const typename std::remove_reference<T>::type &;
435 using pointer = typename std::remove_reference<T>::type *;
436 using const_pointer = const typename std::remove_reference<T>::type *;
437
438public:
439 /// Create an Expected<T> error value from the given Error.
440 Expected(Error Err)
441 : HasError(true)
442#if LLVM_ENABLE_ABI_BREAKING_CHECKS1
443 // Expected is unchecked upon construction in Debug builds.
444 , Unchecked(true)
445#endif
446 {
447 assert(Err && "Cannot create Expected<T> from Error success value.")(static_cast <bool> (Err && "Cannot create Expected<T> from Error success value."
) ? void (0) : __assert_fail ("Err && \"Cannot create Expected<T> from Error success value.\""
, "/build/llvm-toolchain-snapshot-6.0~svn321639/include/llvm/Support/Error.h"
, 447, __extension__ __PRETTY_FUNCTION__))
;
448 new (getErrorStorage()) error_type(Err.takePayload());
449 }
450
451 /// Forbid to convert from Error::success() implicitly, this avoids having
452 /// Expected<T> foo() { return Error::success(); } which compiles otherwise
453 /// but triggers the assertion above.
454 Expected(ErrorSuccess) = delete;
455
456 /// Create an Expected<T> success value from the given OtherT value, which
457 /// must be convertible to T.
458 template <typename OtherT>
459 Expected(OtherT &&Val,
460 typename std::enable_if<std::is_convertible<OtherT, T>::value>::type
461 * = nullptr)
462 : HasError(false)
463#if LLVM_ENABLE_ABI_BREAKING_CHECKS1
464 // Expected is unchecked upon construction in Debug builds.
465 , Unchecked(true)
466#endif
467 {
468 new (getStorage()) storage_type(std::forward<OtherT>(Val));
469 }
470
471 /// Move construct an Expected<T> value.
472 Expected(Expected &&Other) { moveConstruct(std::move(Other)); }
473
474 /// Move construct an Expected<T> value from an Expected<OtherT>, where OtherT
475 /// must be convertible to T.
476 template <class OtherT>
477 Expected(Expected<OtherT> &&Other,
478 typename std::enable_if<std::is_convertible<OtherT, T>::value>::type
479 * = nullptr) {
480 moveConstruct(std::move(Other));
481 }
482
483 /// Move construct an Expected<T> value from an Expected<OtherT>, where OtherT
484 /// isn't convertible to T.
485 template <class OtherT>
486 explicit Expected(
487 Expected<OtherT> &&Other,
488 typename std::enable_if<!std::is_convertible<OtherT, T>::value>::type * =
489 nullptr) {
490 moveConstruct(std::move(Other));
491 }
492
493 /// Move-assign from another Expected<T>.
494 Expected &operator=(Expected &&Other) {
495 moveAssign(std::move(Other));
496 return *this;
497 }
498
499 /// Destroy an Expected<T>.
500 ~Expected() {
501 assertIsChecked();
502 if (!HasError)
503 getStorage()->~storage_type();
504 else
505 getErrorStorage()->~error_type();
506 }
507
508 /// \brief Return false if there is an error.
509 explicit operator bool() {
510#if LLVM_ENABLE_ABI_BREAKING_CHECKS1
511 Unchecked = HasError;
512#endif
513 return !HasError;
514 }
515
516 /// \brief Returns a reference to the stored T value.
517 reference get() {
518 assertIsChecked();
519 return *getStorage();
520 }
521
522 /// \brief Returns a const reference to the stored T value.
523 const_reference get() const {
524 assertIsChecked();
525 return const_cast<Expected<T> *>(this)->get();
526 }
527
528 /// \brief Check that this Expected<T> is an error of type ErrT.
529 template <typename ErrT> bool errorIsA() const {
530 return HasError && (*getErrorStorage())->template isA<ErrT>();
531 }
532
533 /// \brief Take ownership of the stored error.
534 /// After calling this the Expected<T> is in an indeterminate state that can
535 /// only be safely destructed. No further calls (beside the destructor) should
536 /// be made on the Expected<T> vaule.
537 Error takeError() {
538#if LLVM_ENABLE_ABI_BREAKING_CHECKS1
539 Unchecked = false;
540#endif
541 return HasError ? Error(std::move(*getErrorStorage())) : Error::success();
542 }
543
544 /// \brief Returns a pointer to the stored T value.
545 pointer operator->() {
546 assertIsChecked();
547 return toPointer(getStorage());
548 }
549
550 /// \brief Returns a const pointer to the stored T value.
551 const_pointer operator->() const {
552 assertIsChecked();
553 return toPointer(getStorage());
554 }
555
556 /// \brief Returns a reference to the stored T value.
557 reference operator*() {
558 assertIsChecked();
559 return *getStorage();
560 }
561
562 /// \brief Returns a const reference to the stored T value.
563 const_reference operator*() const {
564 assertIsChecked();
565 return *getStorage();
566 }
567
568private:
569 template <class T1>
570 static bool compareThisIfSameType(const T1 &a, const T1 &b) {
571 return &a == &b;
572 }
573
574 template <class T1, class T2>
575 static bool compareThisIfSameType(const T1 &a, const T2 &b) {
576 return false;
577 }
578
579 template <class OtherT> void moveConstruct(Expected<OtherT> &&Other) {
580 HasError = Other.HasError;
581#if LLVM_ENABLE_ABI_BREAKING_CHECKS1
582 Unchecked = true;
583 Other.Unchecked = false;
584#endif
585
586 if (!HasError)
587 new (getStorage()) storage_type(std::move(*Other.getStorage()));
588 else
589 new (getErrorStorage()) error_type(std::move(*Other.getErrorStorage()));
590 }
591
592 template <class OtherT> void moveAssign(Expected<OtherT> &&Other) {
593 assertIsChecked();
594
595 if (compareThisIfSameType(*this, Other))
596 return;
597
598 this->~Expected();
599 new (this) Expected(std::move(Other));
600 }
601
602 pointer toPointer(pointer Val) { return Val; }
603
604 const_pointer toPointer(const_pointer Val) const { return Val; }
605
606 pointer toPointer(wrap *Val) { return &Val->get(); }
607
608 const_pointer toPointer(const wrap *Val) const { return &Val->get(); }
609
610 storage_type *getStorage() {
611 assert(!HasError && "Cannot get value when an error exists!")(static_cast <bool> (!HasError && "Cannot get value when an error exists!"
) ? void (0) : __assert_fail ("!HasError && \"Cannot get value when an error exists!\""
, "/build/llvm-toolchain-snapshot-6.0~svn321639/include/llvm/Support/Error.h"
, 611, __extension__ __PRETTY_FUNCTION__))
;
612 return reinterpret_cast<storage_type *>(TStorage.buffer);
613 }
614
615 const storage_type *getStorage() const {
616 assert(!HasError && "Cannot get value when an error exists!")(static_cast <bool> (!HasError && "Cannot get value when an error exists!"
) ? void (0) : __assert_fail ("!HasError && \"Cannot get value when an error exists!\""
, "/build/llvm-toolchain-snapshot-6.0~svn321639/include/llvm/Support/Error.h"
, 616, __extension__ __PRETTY_FUNCTION__))
;
617 return reinterpret_cast<const storage_type *>(TStorage.buffer);
618 }
619
620 error_type *getErrorStorage() {
621 assert(HasError && "Cannot get error when a value exists!")(static_cast <bool> (HasError && "Cannot get error when a value exists!"
) ? void (0) : __assert_fail ("HasError && \"Cannot get error when a value exists!\""
, "/build/llvm-toolchain-snapshot-6.0~svn321639/include/llvm/Support/Error.h"
, 621, __extension__ __PRETTY_FUNCTION__))
;
622 return reinterpret_cast<error_type *>(ErrorStorage.buffer);
623 }
624
625 const error_type *getErrorStorage() const {
626 assert(HasError && "Cannot get error when a value exists!")(static_cast <bool> (HasError && "Cannot get error when a value exists!"
) ? void (0) : __assert_fail ("HasError && \"Cannot get error when a value exists!\""
, "/build/llvm-toolchain-snapshot-6.0~svn321639/include/llvm/Support/Error.h"
, 626, __extension__ __PRETTY_FUNCTION__))
;
627 return reinterpret_cast<const error_type *>(ErrorStorage.buffer);
628 }
629
630 // Used by ExpectedAsOutParameter to reset the checked flag.
631 void setUnchecked() {
632#if LLVM_ENABLE_ABI_BREAKING_CHECKS1
633 Unchecked = true;
634#endif
635 }
636
637#if LLVM_ENABLE_ABI_BREAKING_CHECKS1
638 LLVM_ATTRIBUTE_NORETURN__attribute__((noreturn))
639 LLVM_ATTRIBUTE_NOINLINE__attribute__((noinline))
640 void fatalUncheckedExpected() const {
641 dbgs() << "Expected<T> must be checked before access or destruction.\n";
642 if (HasError) {
643 dbgs() << "Unchecked Expected<T> contained error:\n";
644 (*getErrorStorage())->log(dbgs());
645 } else
646 dbgs() << "Expected<T> value was in success state. (Note: Expected<T> "
647 "values in success mode must still be checked prior to being "
648 "destroyed).\n";
649 abort();
650 }
651#endif
652
653 void assertIsChecked() {
654#if LLVM_ENABLE_ABI_BREAKING_CHECKS1
655 if (LLVM_UNLIKELY(Unchecked)__builtin_expect((bool)(Unchecked), false))
656 fatalUncheckedExpected();
657#endif
658 }
659
660 union {
661 AlignedCharArrayUnion<storage_type> TStorage;
662 AlignedCharArrayUnion<error_type> ErrorStorage;
663 };
664 bool HasError : 1;
665#if LLVM_ENABLE_ABI_BREAKING_CHECKS1
666 bool Unchecked : 1;
667#endif
668};
669
670/// Report a serious error, calling any installed error handler. See
671/// ErrorHandling.h.
672LLVM_ATTRIBUTE_NORETURN__attribute__((noreturn)) void report_fatal_error(Error Err,
673 bool gen_crash_diag = true);
674
675/// Report a fatal error if Err is a failure value.
676///
677/// This function can be used to wrap calls to fallible functions ONLY when it
678/// is known that the Error will always be a success value. E.g.
679///
680/// @code{.cpp}
681/// // foo only attempts the fallible operation if DoFallibleOperation is
682/// // true. If DoFallibleOperation is false then foo always returns
683/// // Error::success().
684/// Error foo(bool DoFallibleOperation);
685///
686/// cantFail(foo(false));
687/// @endcode
688inline void cantFail(Error Err, const char *Msg = nullptr) {
689 if (Err) {
690 if (!Msg)
691 Msg = "Failure value returned from cantFail wrapped call";
692 llvm_unreachable(Msg)::llvm::llvm_unreachable_internal(Msg, "/build/llvm-toolchain-snapshot-6.0~svn321639/include/llvm/Support/Error.h"
, 692)
;
693 }
694}
695
696/// Report a fatal error if ValOrErr is a failure value, otherwise unwraps and
697/// returns the contained value.
698///
699/// This function can be used to wrap calls to fallible functions ONLY when it
700/// is known that the Error will always be a success value. E.g.
701///
702/// @code{.cpp}
703/// // foo only attempts the fallible operation if DoFallibleOperation is
704/// // true. If DoFallibleOperation is false then foo always returns an int.
705/// Expected<int> foo(bool DoFallibleOperation);
706///
707/// int X = cantFail(foo(false));
708/// @endcode
709template <typename T>
710T cantFail(Expected<T> ValOrErr, const char *Msg = nullptr) {
711 if (ValOrErr)
712 return std::move(*ValOrErr);
713 else {
714 if (!Msg)
715 Msg = "Failure value returned from cantFail wrapped call";
716 llvm_unreachable(Msg)::llvm::llvm_unreachable_internal(Msg, "/build/llvm-toolchain-snapshot-6.0~svn321639/include/llvm/Support/Error.h"
, 716)
;
717 }
718}
719
720/// Report a fatal error if ValOrErr is a failure value, otherwise unwraps and
721/// returns the contained reference.
722///
723/// This function can be used to wrap calls to fallible functions ONLY when it
724/// is known that the Error will always be a success value. E.g.
725///
726/// @code{.cpp}
727/// // foo only attempts the fallible operation if DoFallibleOperation is
728/// // true. If DoFallibleOperation is false then foo always returns a Bar&.
729/// Expected<Bar&> foo(bool DoFallibleOperation);
730///
731/// Bar &X = cantFail(foo(false));
732/// @endcode
733template <typename T>
734T& cantFail(Expected<T&> ValOrErr, const char *Msg = nullptr) {
735 if (ValOrErr)
736 return *ValOrErr;
737 else {
738 if (!Msg)
739 Msg = "Failure value returned from cantFail wrapped call";
740 llvm_unreachable(Msg)::llvm::llvm_unreachable_internal(Msg, "/build/llvm-toolchain-snapshot-6.0~svn321639/include/llvm/Support/Error.h"
, 740)
;
741 }
742}
743
744/// Helper for testing applicability of, and applying, handlers for
745/// ErrorInfo types.
746template <typename HandlerT>
747class ErrorHandlerTraits
748 : public ErrorHandlerTraits<decltype(
749 &std::remove_reference<HandlerT>::type::operator())> {};
750
751// Specialization functions of the form 'Error (const ErrT&)'.
752template <typename ErrT> class ErrorHandlerTraits<Error (&)(ErrT &)> {
753public:
754 static bool appliesTo(const ErrorInfoBase &E) {
755 return E.template isA<ErrT>();
756 }
757
758 template <typename HandlerT>
759 static Error apply(HandlerT &&H, std::unique_ptr<ErrorInfoBase> E) {
760 assert(appliesTo(*E) && "Applying incorrect handler")(static_cast <bool> (appliesTo(*E) && "Applying incorrect handler"
) ? void (0) : __assert_fail ("appliesTo(*E) && \"Applying incorrect handler\""
, "/build/llvm-toolchain-snapshot-6.0~svn321639/include/llvm/Support/Error.h"
, 760, __extension__ __PRETTY_FUNCTION__))
;
761 return H(static_cast<ErrT &>(*E));
762 }
763};
764
765// Specialization functions of the form 'void (const ErrT&)'.
766template <typename ErrT> class ErrorHandlerTraits<void (&)(ErrT &)> {
767public:
768 static bool appliesTo(const ErrorInfoBase &E) {
769 return E.template isA<ErrT>();
770 }
771
772 template <typename HandlerT>
773 static Error apply(HandlerT &&H, std::unique_ptr<ErrorInfoBase> E) {
774 assert(appliesTo(*E) && "Applying incorrect handler")(static_cast <bool> (appliesTo(*E) && "Applying incorrect handler"
) ? void (0) : __assert_fail ("appliesTo(*E) && \"Applying incorrect handler\""
, "/build/llvm-toolchain-snapshot-6.0~svn321639/include/llvm/Support/Error.h"
, 774, __extension__ __PRETTY_FUNCTION__))
;
775 H(static_cast<ErrT &>(*E));
776 return Error::success();
777 }
778};
779
780/// Specialization for functions of the form 'Error (std::unique_ptr<ErrT>)'.
781template <typename ErrT>
782class ErrorHandlerTraits<Error (&)(std::unique_ptr<ErrT>)> {
783public:
784 static bool appliesTo(const ErrorInfoBase &E) {
785 return E.template isA<ErrT>();
786 }
787
788 template <typename HandlerT>
789 static Error apply(HandlerT &&H, std::unique_ptr<ErrorInfoBase> E) {
790 assert(appliesTo(*E) && "Applying incorrect handler")(static_cast <bool> (appliesTo(*E) && "Applying incorrect handler"
) ? void (0) : __assert_fail ("appliesTo(*E) && \"Applying incorrect handler\""
, "/build/llvm-toolchain-snapshot-6.0~svn321639/include/llvm/Support/Error.h"
, 790, __extension__ __PRETTY_FUNCTION__))
;
791 std::unique_ptr<ErrT> SubE(static_cast<ErrT *>(E.release()));
792 return H(std::move(SubE));
793 }
794};
795
796/// Specialization for functions of the form 'void (std::unique_ptr<ErrT>)'.
797template <typename ErrT>
798class ErrorHandlerTraits<void (&)(std::unique_ptr<ErrT>)> {
799public:
800 static bool appliesTo(const ErrorInfoBase &E) {
801 return E.template isA<ErrT>();
802 }
803
804 template <typename HandlerT>
805 static Error apply(HandlerT &&H, std::unique_ptr<ErrorInfoBase> E) {
806 assert(appliesTo(*E) && "Applying incorrect handler")(static_cast <bool> (appliesTo(*E) && "Applying incorrect handler"
) ? void (0) : __assert_fail ("appliesTo(*E) && \"Applying incorrect handler\""
, "/build/llvm-toolchain-snapshot-6.0~svn321639/include/llvm/Support/Error.h"
, 806, __extension__ __PRETTY_FUNCTION__))
;
807 std::unique_ptr<ErrT> SubE(static_cast<ErrT *>(E.release()));
808 H(std::move(SubE));
809 return Error::success();
810 }
811};
812
813// Specialization for member functions of the form 'RetT (const ErrT&)'.
814template <typename C, typename RetT, typename ErrT>
815class ErrorHandlerTraits<RetT (C::*)(ErrT &)>
816 : public ErrorHandlerTraits<RetT (&)(ErrT &)> {};
817
818// Specialization for member functions of the form 'RetT (const ErrT&) const'.
819template <typename C, typename RetT, typename ErrT>
820class ErrorHandlerTraits<RetT (C::*)(ErrT &) const>
821 : public ErrorHandlerTraits<RetT (&)(ErrT &)> {};
822
823// Specialization for member functions of the form 'RetT (const ErrT&)'.
824template <typename C, typename RetT, typename ErrT>
825class ErrorHandlerTraits<RetT (C::*)(const ErrT &)>
826 : public ErrorHandlerTraits<RetT (&)(ErrT &)> {};
827
828// Specialization for member functions of the form 'RetT (const ErrT&) const'.
829template <typename C, typename RetT, typename ErrT>
830class ErrorHandlerTraits<RetT (C::*)(const ErrT &) const>
831 : public ErrorHandlerTraits<RetT (&)(ErrT &)> {};
832
833/// Specialization for member functions of the form
834/// 'RetT (std::unique_ptr<ErrT>)'.
835template <typename C, typename RetT, typename ErrT>
836class ErrorHandlerTraits<RetT (C::*)(std::unique_ptr<ErrT>)>
837 : public ErrorHandlerTraits<RetT (&)(std::unique_ptr<ErrT>)> {};
838
839/// Specialization for member functions of the form
840/// 'RetT (std::unique_ptr<ErrT>) const'.
841template <typename C, typename RetT, typename ErrT>
842class ErrorHandlerTraits<RetT (C::*)(std::unique_ptr<ErrT>) const>
843 : public ErrorHandlerTraits<RetT (&)(std::unique_ptr<ErrT>)> {};
844
845inline Error handleErrorImpl(std::unique_ptr<ErrorInfoBase> Payload) {
846 return Error(std::move(Payload));
847}
848
849template <typename HandlerT, typename... HandlerTs>
850Error handleErrorImpl(std::unique_ptr<ErrorInfoBase> Payload,
851 HandlerT &&Handler, HandlerTs &&... Handlers) {
852 if (ErrorHandlerTraits<HandlerT>::appliesTo(*Payload))
853 return ErrorHandlerTraits<HandlerT>::apply(std::forward<HandlerT>(Handler),
854 std::move(Payload));
855 return handleErrorImpl(std::move(Payload),
856 std::forward<HandlerTs>(Handlers)...);
857}
858
859/// Pass the ErrorInfo(s) contained in E to their respective handlers. Any
860/// unhandled errors (or Errors returned by handlers) are re-concatenated and
861/// returned.
862/// Because this function returns an error, its result must also be checked
863/// or returned. If you intend to handle all errors use handleAllErrors
864/// (which returns void, and will abort() on unhandled errors) instead.
865template <typename... HandlerTs>
866Error handleErrors(Error E, HandlerTs &&... Hs) {
867 if (!E)
868 return Error::success();
869
870 std::unique_ptr<ErrorInfoBase> Payload = E.takePayload();
871
872 if (Payload->isA<ErrorList>()) {
873 ErrorList &List = static_cast<ErrorList &>(*Payload);
874 Error R;
875 for (auto &P : List.Payloads)
876 R = ErrorList::join(
877 std::move(R),
878 handleErrorImpl(std::move(P), std::forward<HandlerTs>(Hs)...));
879 return R;
880 }
881
882 return handleErrorImpl(std::move(Payload), std::forward<HandlerTs>(Hs)...);
883}
884
885/// Behaves the same as handleErrors, except that it requires that all
886/// errors be handled by the given handlers. If any unhandled error remains
887/// after the handlers have run, report_fatal_error() will be called.
888template <typename... HandlerTs>
889void handleAllErrors(Error E, HandlerTs &&... Handlers) {
890 cantFail(handleErrors(std::move(E), std::forward<HandlerTs>(Handlers)...));
891}
892
893/// Check that E is a non-error, then drop it.
894/// If E is an error report_fatal_error will be called.
895inline void handleAllErrors(Error E) {
896 cantFail(std::move(E));
897}
898
899/// Handle any errors (if present) in an Expected<T>, then try a recovery path.
900///
901/// If the incoming value is a success value it is returned unmodified. If it
902/// is a failure value then it the contained error is passed to handleErrors.
903/// If handleErrors is able to handle the error then the RecoveryPath functor
904/// is called to supply the final result. If handleErrors is not able to
905/// handle all errors then the unhandled errors are returned.
906///
907/// This utility enables the follow pattern:
908///
909/// @code{.cpp}
910/// enum FooStrategy { Aggressive, Conservative };
911/// Expected<Foo> foo(FooStrategy S);
912///
913/// auto ResultOrErr =
914/// handleExpected(
915/// foo(Aggressive),
916/// []() { return foo(Conservative); },
917/// [](AggressiveStrategyError&) {
918/// // Implicitly conusme this - we'll recover by using a conservative
919/// // strategy.
920/// });
921///
922/// @endcode
923template <typename T, typename RecoveryFtor, typename... HandlerTs>
924Expected<T> handleExpected(Expected<T> ValOrErr, RecoveryFtor &&RecoveryPath,
925 HandlerTs &&... Handlers) {
926 if (ValOrErr)
927 return ValOrErr;
928
929 if (auto Err = handleErrors(ValOrErr.takeError(),
930 std::forward<HandlerTs>(Handlers)...))
931 return std::move(Err);
932
933 return RecoveryPath();
934}
935
936/// Log all errors (if any) in E to OS. If there are any errors, ErrorBanner
937/// will be printed before the first one is logged. A newline will be printed
938/// after each error.
939///
940/// This is useful in the base level of your program to allow clean termination
941/// (allowing clean deallocation of resources, etc.), while reporting error
942/// information to the user.
943void logAllUnhandledErrors(Error E, raw_ostream &OS, Twine ErrorBanner);
944
945/// Write all error messages (if any) in E to a string. The newline character
946/// is used to separate error messages.
947inline std::string toString(Error E) {
948 SmallVector<std::string, 2> Errors;
949 handleAllErrors(std::move(E), [&Errors](const ErrorInfoBase &EI) {
950 Errors.push_back(EI.message());
951 });
952 return join(Errors.begin(), Errors.end(), "\n");
953}
954
955/// Consume a Error without doing anything. This method should be used
956/// only where an error can be considered a reasonable and expected return
957/// value.
958///
959/// Uses of this method are potentially indicative of design problems: If it's
960/// legitimate to do nothing while processing an "error", the error-producer
961/// might be more clearly refactored to return an Optional<T>.
962inline void consumeError(Error Err) {
963 handleAllErrors(std::move(Err), [](const ErrorInfoBase &) {});
964}
965
966/// Helper for Errors used as out-parameters.
967///
968/// This helper is for use with the Error-as-out-parameter idiom, where an error
969/// is passed to a function or method by reference, rather than being returned.
970/// In such cases it is helpful to set the checked bit on entry to the function
971/// so that the error can be written to (unchecked Errors abort on assignment)
972/// and clear the checked bit on exit so that clients cannot accidentally forget
973/// to check the result. This helper performs these actions automatically using
974/// RAII:
975///
976/// @code{.cpp}
977/// Result foo(Error &Err) {
978/// ErrorAsOutParameter ErrAsOutParam(&Err); // 'Checked' flag set
979/// // <body of foo>
980/// // <- 'Checked' flag auto-cleared when ErrAsOutParam is destructed.
981/// }
982/// @endcode
983///
984/// ErrorAsOutParameter takes an Error* rather than Error& so that it can be
985/// used with optional Errors (Error pointers that are allowed to be null). If
986/// ErrorAsOutParameter took an Error reference, an instance would have to be
987/// created inside every condition that verified that Error was non-null. By
988/// taking an Error pointer we can just create one instance at the top of the
989/// function.
990class ErrorAsOutParameter {
991public:
992 ErrorAsOutParameter(Error *Err) : Err(Err) {
993 // Raise the checked bit if Err is success.
994 if (Err)
995 (void)!!*Err;
996 }
997
998 ~ErrorAsOutParameter() {
999 // Clear the checked bit.
1000 if (Err && !*Err)
1001 *Err = Error::success();
1002 }
1003
1004private:
1005 Error *Err;
1006};
1007
1008/// Helper for Expected<T>s used as out-parameters.
1009///
1010/// See ErrorAsOutParameter.
1011template <typename T>
1012class ExpectedAsOutParameter {
1013public:
1014 ExpectedAsOutParameter(Expected<T> *ValOrErr)
1015 : ValOrErr(ValOrErr) {
1016 if (ValOrErr)
1017 (void)!!*ValOrErr;
1018 }
1019
1020 ~ExpectedAsOutParameter() {
1021 if (ValOrErr)
1022 ValOrErr->setUnchecked();
1023 }
1024
1025private:
1026 Expected<T> *ValOrErr;
1027};
1028
1029/// This class wraps a std::error_code in a Error.
1030///
1031/// This is useful if you're writing an interface that returns a Error
1032/// (or Expected) and you want to call code that still returns
1033/// std::error_codes.
1034class ECError : public ErrorInfo<ECError> {
1035 friend Error errorCodeToError(std::error_code);
1036
1037public:
1038 void setErrorCode(std::error_code EC) { this->EC = EC; }
1039 std::error_code convertToErrorCode() const override { return EC; }
1040 void log(raw_ostream &OS) const override { OS << EC.message(); }
1041
1042 // Used by ErrorInfo::classID.
1043 static char ID;
1044
1045protected:
1046 ECError() = default;
1047 ECError(std::error_code EC) : EC(EC) {}
1048
1049 std::error_code EC;
1050};
1051
1052/// The value returned by this function can be returned from convertToErrorCode
1053/// for Error values where no sensible translation to std::error_code exists.
1054/// It should only be used in this situation, and should never be used where a
1055/// sensible conversion to std::error_code is available, as attempts to convert
1056/// to/from this error will result in a fatal error. (i.e. it is a programmatic
1057///error to try to convert such a value).
1058std::error_code inconvertibleErrorCode();
1059
1060/// Helper for converting an std::error_code to a Error.
1061Error errorCodeToError(std::error_code EC);
1062
1063/// Helper for converting an ECError to a std::error_code.
1064///
1065/// This method requires that Err be Error() or an ECError, otherwise it
1066/// will trigger a call to abort().
1067std::error_code errorToErrorCode(Error Err);
1068
1069/// Convert an ErrorOr<T> to an Expected<T>.
1070template <typename T> Expected<T> errorOrToExpected(ErrorOr<T> &&EO) {
1071 if (auto EC = EO.getError())
1072 return errorCodeToError(EC);
1073 return std::move(*EO);
1074}
1075
1076/// Convert an Expected<T> to an ErrorOr<T>.
1077template <typename T> ErrorOr<T> expectedToErrorOr(Expected<T> &&E) {
1078 if (auto Err = E.takeError())
1079 return errorToErrorCode(std::move(Err));
1080 return std::move(*E);
1081}
1082
1083/// This class wraps a string in an Error.
1084///
1085/// StringError is useful in cases where the client is not expected to be able
1086/// to consume the specific error message programmatically (for example, if the
1087/// error message is to be presented to the user).
1088class StringError : public ErrorInfo<StringError> {
1089public:
1090 static char ID;
1091
1092 StringError(const Twine &S, std::error_code EC);
1093
1094 void log(raw_ostream &OS) const override;
1095 std::error_code convertToErrorCode() const override;
1096
1097 const std::string &getMessage() const { return Msg; }
1098
1099private:
1100 std::string Msg;
1101 std::error_code EC;
1102};
1103
1104/// Helper for check-and-exit error handling.
1105///
1106/// For tool use only. NOT FOR USE IN LIBRARY CODE.
1107///
1108class ExitOnError {
1109public:
1110 /// Create an error on exit helper.
1111 ExitOnError(std::string Banner = "", int DefaultErrorExitCode = 1)
1112 : Banner(std::move(Banner)),
1113 GetExitCode([=](const Error &) { return DefaultErrorExitCode; }) {}
1114
1115 /// Set the banner string for any errors caught by operator().
1116 void setBanner(std::string Banner) { this->Banner = std::move(Banner); }
1117
1118 /// Set the exit-code mapper function.
1119 void setExitCodeMapper(std::function<int(const Error &)> GetExitCode) {
1120 this->GetExitCode = std::move(GetExitCode);
1121 }
1122
1123 /// Check Err. If it's in a failure state log the error(s) and exit.
1124 void operator()(Error Err) const { checkError(std::move(Err)); }
1125
1126 /// Check E. If it's in a success state then return the contained value. If
1127 /// it's in a failure state log the error(s) and exit.
1128 template <typename T> T operator()(Expected<T> &&E) const {
1129 checkError(E.takeError());
1130 return std::move(*E);
1131 }
1132
1133 /// Check E. If it's in a success state then return the contained reference. If
1134 /// it's in a failure state log the error(s) and exit.
1135 template <typename T> T& operator()(Expected<T&> &&E) const {
1136 checkError(E.takeError());
1137 return *E;
1138 }
1139
1140private:
1141 void checkError(Error Err) const {
1142 if (Err) {
1143 int ExitCode = GetExitCode(Err);
1144 logAllUnhandledErrors(std::move(Err), errs(), Banner);
1145 exit(ExitCode);
1146 }
1147 }
1148
1149 std::string Banner;
1150 std::function<int(const Error &)> GetExitCode;
1151};
1152
1153} // end namespace llvm
1154
1155#endif // LLVM_SUPPORT_ERROR_H

/build/llvm-toolchain-snapshot-6.0~svn321639/include/llvm/Support/Endian.h

1//===- Endian.h - Utilities for IO with endian specific data ----*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file declares generic functions to read and write endian specific data.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef LLVM_SUPPORT_ENDIAN_H
15#define LLVM_SUPPORT_ENDIAN_H
16
17#include "llvm/Support/AlignOf.h"
18#include "llvm/Support/Compiler.h"
19#include "llvm/Support/Host.h"
20#include "llvm/Support/SwapByteOrder.h"
21#include <cassert>
22#include <cstddef>
23#include <cstdint>
24#include <cstring>
25#include <type_traits>
26
27namespace llvm {
28namespace support {
29
30enum endianness {big, little, native};
31
32// These are named values for common alignments.
33enum {aligned = 0, unaligned = 1};
34
35namespace detail {
36
37/// \brief ::value is either alignment, or alignof(T) if alignment is 0.
38template<class T, int alignment>
39struct PickAlignment {
40 enum { value = alignment == 0 ? alignof(T) : alignment };
41};
42
43} // end namespace detail
44
45namespace endian {
46
47constexpr endianness system_endianness() {
48 return sys::IsBigEndianHost ? big : little;
49}
50
51template <typename value_type>
52inline value_type byte_swap(value_type value, endianness endian) {
53 if ((endian != native) && (endian != system_endianness()))
53
Assuming 'endian' is equal to native
54 sys::swapByteOrder(value);
55 return value;
56}
57
58/// Swap the bytes of value to match the given endianness.
59template<typename value_type, endianness endian>
60inline value_type byte_swap(value_type value) {
61 return byte_swap(value, endian);
62}
63
64/// Read a value of a particular endianness from memory.
65template <typename value_type, std::size_t alignment>
66inline value_type read(const void *memory, endianness endian) {
67 value_type ret;
68
69 memcpy(&ret,
70 LLVM_ASSUME_ALIGNED(__builtin_assume_aligned(memory, (detail::PickAlignment<value_type
, alignment>::value))
71 memory, (detail::PickAlignment<value_type, alignment>::value))__builtin_assume_aligned(memory, (detail::PickAlignment<value_type
, alignment>::value))
,
72 sizeof(value_type));
73 return byte_swap<value_type>(ret, endian);
52
Calling 'byte_swap'
54
Returning from 'byte_swap'
74}
75
76template<typename value_type,
77 endianness endian,
78 std::size_t alignment>
79inline value_type read(const void *memory) {
80 return read<value_type, alignment>(memory, endian);
81}
82
83/// Read a value of a particular endianness from a buffer, and increment the
84/// buffer past that value.
85template <typename value_type, std::size_t alignment, typename CharT>
86inline value_type readNext(const CharT *&memory, endianness endian) {
87 value_type ret = read<value_type, alignment>(memory, endian);
88 memory += sizeof(value_type);
89 return ret;
90}
91
92template<typename value_type, endianness endian, std::size_t alignment,
93 typename CharT>
94inline value_type readNext(const CharT *&memory) {
95 return readNext<value_type, alignment, CharT>(memory, endian);
96}
97
98/// Write a value to memory with a particular endianness.
99template <typename value_type, std::size_t alignment>
100inline void write(void *memory, value_type value, endianness endian) {
101 value = byte_swap<value_type>(value, endian);
102 memcpy(LLVM_ASSUME_ALIGNED(__builtin_assume_aligned(memory, (detail::PickAlignment<value_type
, alignment>::value))
103 memory, (detail::PickAlignment<value_type, alignment>::value))__builtin_assume_aligned(memory, (detail::PickAlignment<value_type
, alignment>::value))
,
104 &value, sizeof(value_type));
105}
106
107template<typename value_type,
108 endianness endian,
109 std::size_t alignment>
110inline void write(void *memory, value_type value) {
111 write<value_type, alignment>(memory, value, endian);
112}
113
114template <typename value_type>
115using make_unsigned_t = typename std::make_unsigned<value_type>::type;
116
117/// Read a value of a particular endianness from memory, for a location
118/// that starts at the given bit offset within the first byte.
119template <typename value_type, endianness endian, std::size_t alignment>
120inline value_type readAtBitAlignment(const void *memory, uint64_t startBit) {
121 assert(startBit < 8)(static_cast <bool> (startBit < 8) ? void (0) : __assert_fail
("startBit < 8", "/build/llvm-toolchain-snapshot-6.0~svn321639/include/llvm/Support/Endian.h"
, 121, __extension__ __PRETTY_FUNCTION__))
;
122 if (startBit == 0)
123 return read<value_type, endian, alignment>(memory);
124 else {
125 // Read two values and compose the result from them.
126 value_type val[2];
127 memcpy(&val[0],
128 LLVM_ASSUME_ALIGNED(__builtin_assume_aligned(memory, (detail::PickAlignment<value_type
, alignment>::value))
129 memory, (detail::PickAlignment<value_type, alignment>::value))__builtin_assume_aligned(memory, (detail::PickAlignment<value_type
, alignment>::value))
,
130 sizeof(value_type) * 2);
131 val[0] = byte_swap<value_type, endian>(val[0]);
132 val[1] = byte_swap<value_type, endian>(val[1]);
133
134 // Shift bits from the lower value into place.
135 make_unsigned_t<value_type> lowerVal = val[0] >> startBit;
136 // Mask off upper bits after right shift in case of signed type.
137 make_unsigned_t<value_type> numBitsFirstVal =
138 (sizeof(value_type) * 8) - startBit;
139 lowerVal &= ((make_unsigned_t<value_type>)1 << numBitsFirstVal) - 1;
140
141 // Get the bits from the upper value.
142 make_unsigned_t<value_type> upperVal =
143 val[1] & (((make_unsigned_t<value_type>)1 << startBit) - 1);
144 // Shift them in to place.
145 upperVal <<= numBitsFirstVal;
146
147 return lowerVal | upperVal;
148 }
149}
150
151/// Write a value to memory with a particular endianness, for a location
152/// that starts at the given bit offset within the first byte.
153template <typename value_type, endianness endian, std::size_t alignment>
154inline void writeAtBitAlignment(void *memory, value_type value,
155 uint64_t startBit) {
156 assert(startBit < 8)(static_cast <bool> (startBit < 8) ? void (0) : __assert_fail
("startBit < 8", "/build/llvm-toolchain-snapshot-6.0~svn321639/include/llvm/Support/Endian.h"
, 156, __extension__ __PRETTY_FUNCTION__))
;
157 if (startBit == 0)
158 write<value_type, endian, alignment>(memory, value);
159 else {
160 // Read two values and shift the result into them.
161 value_type val[2];
162 memcpy(&val[0],
163 LLVM_ASSUME_ALIGNED(__builtin_assume_aligned(memory, (detail::PickAlignment<value_type
, alignment>::value))
164 memory, (detail::PickAlignment<value_type, alignment>::value))__builtin_assume_aligned(memory, (detail::PickAlignment<value_type
, alignment>::value))
,
165 sizeof(value_type) * 2);
166 val[0] = byte_swap<value_type, endian>(val[0]);
167 val[1] = byte_swap<value_type, endian>(val[1]);
168
169 // Mask off any existing bits in the upper part of the lower value that
170 // we want to replace.
171 val[0] &= ((make_unsigned_t<value_type>)1 << startBit) - 1;
172 make_unsigned_t<value_type> numBitsFirstVal =
173 (sizeof(value_type) * 8) - startBit;
174 make_unsigned_t<value_type> lowerVal = value;
175 if (startBit > 0) {
176 // Mask off the upper bits in the new value that are not going to go into
177 // the lower value. This avoids a left shift of a negative value, which
178 // is undefined behavior.
179 lowerVal &= (((make_unsigned_t<value_type>)1 << numBitsFirstVal) - 1);
180 // Now shift the new bits into place
181 lowerVal <<= startBit;
182 }
183 val[0] |= lowerVal;
184
185 // Mask off any existing bits in the lower part of the upper value that
186 // we want to replace.
187 val[1] &= ~(((make_unsigned_t<value_type>)1 << startBit) - 1);
188 // Next shift the bits that go into the upper value into position.
189 make_unsigned_t<value_type> upperVal = value >> numBitsFirstVal;
190 // Mask off upper bits after right shift in case of signed type.
191 upperVal &= ((make_unsigned_t<value_type>)1 << startBit) - 1;
192 val[1] |= upperVal;
193
194 // Finally, rewrite values.
195 val[0] = byte_swap<value_type, endian>(val[0]);
196 val[1] = byte_swap<value_type, endian>(val[1]);
197 memcpy(LLVM_ASSUME_ALIGNED(__builtin_assume_aligned(memory, (detail::PickAlignment<value_type
, alignment>::value))
198 memory, (detail::PickAlignment<value_type, alignment>::value))__builtin_assume_aligned(memory, (detail::PickAlignment<value_type
, alignment>::value))
,
199 &val[0], sizeof(value_type) * 2);
200 }
201}
202
203} // end namespace endian
204
205namespace detail {
206
207template<typename value_type,
208 endianness endian,
209 std::size_t alignment>
210struct packed_endian_specific_integral {
211 packed_endian_specific_integral() = default;
212
213 explicit packed_endian_specific_integral(value_type val) { *this = val; }
214
215 operator value_type() const {
216 return endian::read<value_type, endian, alignment>(
217 (const void*)Value.buffer);
218 }
219
220 void operator=(value_type newValue) {
221 endian::write<value_type, endian, alignment>(
222 (void*)Value.buffer, newValue);
223 }
224
225 packed_endian_specific_integral &operator+=(value_type newValue) {
226 *this = *this + newValue;
227 return *this;
228 }
229
230 packed_endian_specific_integral &operator-=(value_type newValue) {
231 *this = *this - newValue;
232 return *this;
233 }
234
235 packed_endian_specific_integral &operator|=(value_type newValue) {
236 *this = *this | newValue;
237 return *this;
238 }
239
240 packed_endian_specific_integral &operator&=(value_type newValue) {
241 *this = *this & newValue;
242 return *this;
243 }
244
245private:
246 AlignedCharArray<PickAlignment<value_type, alignment>::value,
247 sizeof(value_type)> Value;
248
249public:
250 struct ref {
251 explicit ref(void *Ptr) : Ptr(Ptr) {}
252
253 operator value_type() const {
254 return endian::read<value_type, endian, alignment>(Ptr);
255 }
256
257 void operator=(value_type NewValue) {
258 endian::write<value_type, endian, alignment>(Ptr, NewValue);
259 }
260
261 private:
262 void *Ptr;
263 };
264};
265
266} // end namespace detail
267
268using ulittle16_t =
269 detail::packed_endian_specific_integral<uint16_t, little, unaligned>;
270using ulittle32_t =
271 detail::packed_endian_specific_integral<uint32_t, little, unaligned>;
272using ulittle64_t =
273 detail::packed_endian_specific_integral<uint64_t, little, unaligned>;
274
275using little16_t =
276 detail::packed_endian_specific_integral<int16_t, little, unaligned>;
277using little32_t =
278 detail::packed_endian_specific_integral<int32_t, little, unaligned>;
279using little64_t =
280 detail::packed_endian_specific_integral<int64_t, little, unaligned>;
281
282using aligned_ulittle16_t =
283 detail::packed_endian_specific_integral<uint16_t, little, aligned>;
284using aligned_ulittle32_t =
285 detail::packed_endian_specific_integral<uint32_t, little, aligned>;
286using aligned_ulittle64_t =
287 detail::packed_endian_specific_integral<uint64_t, little, aligned>;
288
289using aligned_little16_t =
290 detail::packed_endian_specific_integral<int16_t, little, aligned>;
291using aligned_little32_t =
292 detail::packed_endian_specific_integral<int32_t, little, aligned>;
293using aligned_little64_t =
294 detail::packed_endian_specific_integral<int64_t, little, aligned>;
295
296using ubig16_t =
297 detail::packed_endian_specific_integral<uint16_t, big, unaligned>;
298using ubig32_t =
299 detail::packed_endian_specific_integral<uint32_t, big, unaligned>;
300using ubig64_t =
301 detail::packed_endian_specific_integral<uint64_t, big, unaligned>;
302
303using big16_t =
304 detail::packed_endian_specific_integral<int16_t, big, unaligned>;
305using big32_t =
306 detail::packed_endian_specific_integral<int32_t, big, unaligned>;
307using big64_t =
308 detail::packed_endian_specific_integral<int64_t, big, unaligned>;
309
310using aligned_ubig16_t =
311 detail::packed_endian_specific_integral<uint16_t, big, aligned>;
312using aligned_ubig32_t =
313 detail::packed_endian_specific_integral<uint32_t, big, aligned>;
314using aligned_ubig64_t =
315 detail::packed_endian_specific_integral<uint64_t, big, aligned>;
316
317using aligned_big16_t =
318 detail::packed_endian_specific_integral<int16_t, big, aligned>;
319using aligned_big32_t =
320 detail::packed_endian_specific_integral<int32_t, big, aligned>;
321using aligned_big64_t =
322 detail::packed_endian_specific_integral<int64_t, big, aligned>;
323
324using unaligned_uint16_t =
325 detail::packed_endian_specific_integral<uint16_t, native, unaligned>;
326using unaligned_uint32_t =
327 detail::packed_endian_specific_integral<uint32_t, native, unaligned>;
328using unaligned_uint64_t =
329 detail::packed_endian_specific_integral<uint64_t, native, unaligned>;
330
331using unaligned_int16_t =
332 detail::packed_endian_specific_integral<int16_t, native, unaligned>;
333using unaligned_int32_t =
334 detail::packed_endian_specific_integral<int32_t, native, unaligned>;
335using unaligned_int64_t =
336 detail::packed_endian_specific_integral<int64_t, native, unaligned>;
337
338namespace endian {
339
340template <typename T> inline T read(const void *P, endianness E) {
341 return read<T, unaligned>(P, E);
342}
343
344template <typename T, endianness E> inline T read(const void *P) {
345 return *(const detail::packed_endian_specific_integral<T, E, unaligned> *)P;
346}
347
348inline uint16_t read16(const void *P, endianness E) {
349 return read<uint16_t>(P, E);
350}
351inline uint32_t read32(const void *P, endianness E) {
352 return read<uint32_t>(P, E);
353}
354inline uint64_t read64(const void *P, endianness E) {
355 return read<uint64_t>(P, E);
356}
357
358template <endianness E> inline uint16_t read16(const void *P) {
359 return read<uint16_t, E>(P);
360}
361template <endianness E> inline uint32_t read32(const void *P) {
362 return read<uint32_t, E>(P);
363}
364template <endianness E> inline uint64_t read64(const void *P) {
365 return read<uint64_t, E>(P);
366}
367
368inline uint16_t read16le(const void *P) { return read16<little>(P); }
369inline uint32_t read32le(const void *P) { return read32<little>(P); }
370inline uint64_t read64le(const void *P) { return read64<little>(P); }
371inline uint16_t read16be(const void *P) { return read16<big>(P); }
372inline uint32_t read32be(const void *P) { return read32<big>(P); }
373inline uint64_t read64be(const void *P) { return read64<big>(P); }
374
375template <typename T> inline void write(void *P, T V, endianness E) {
376 write<T, unaligned>(P, V, E);
377}
378
379template <typename T, endianness E> inline void write(void *P, T V) {
380 *(detail::packed_endian_specific_integral<T, E, unaligned> *)P = V;
381}
382
383inline void write16(void *P, uint16_t V, endianness E) {
384 write<uint16_t>(P, V, E);
385}
386inline void write32(void *P, uint32_t V, endianness E) {
387 write<uint32_t>(P, V, E);
388}
389inline void write64(void *P, uint64_t V, endianness E) {
390 write<uint64_t>(P, V, E);
391}
392
393template <endianness E> inline void write16(void *P, uint16_t V) {
394 write<uint16_t, E>(P, V);
395}
396template <endianness E> inline void write32(void *P, uint32_t V) {
397 write<uint32_t, E>(P, V);
398}
399template <endianness E> inline void write64(void *P, uint64_t V) {
400 write<uint64_t, E>(P, V);
401}
402
403inline void write16le(void *P, uint16_t V) { write16<little>(P, V); }
404inline void write32le(void *P, uint32_t V) { write32<little>(P, V); }
405inline void write64le(void *P, uint64_t V) { write64<little>(P, V); }
406inline void write16be(void *P, uint16_t V) { write16<big>(P, V); }
407inline void write32be(void *P, uint32_t V) { write32<big>(P, V); }
408inline void write64be(void *P, uint64_t V) { write64<big>(P, V); }
409
410} // end namespace endian
411
412} // end namespace support
413} // end namespace llvm
414
415#endif // LLVM_SUPPORT_ENDIAN_H