Bug Summary

File:lib/ObjectYAML/CodeViewYAMLDebugSections.cpp
Warning:line 909, column 3
The left operand of '==' is a garbage value

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name CodeViewYAMLDebugSections.cpp -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-eagerly-assume -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -mrelocation-model pic -pic-level 2 -mthread-model posix -fmath-errno -masm-verbose -mconstructor-aliases -munwind-tables -fuse-init-array -target-cpu x86-64 -dwarf-column-info -debugger-tuning=gdb -momit-leaf-frame-pointer -ffunction-sections -fdata-sections -resource-dir /usr/lib/llvm-7/lib/clang/7.0.0 -D _DEBUG -D _GNU_SOURCE -D __STDC_CONSTANT_MACROS -D __STDC_FORMAT_MACROS -D __STDC_LIMIT_MACROS -I /build/llvm-toolchain-snapshot-7~svn326551/build-llvm/lib/ObjectYAML -I /build/llvm-toolchain-snapshot-7~svn326551/lib/ObjectYAML -I /build/llvm-toolchain-snapshot-7~svn326551/build-llvm/include -I /build/llvm-toolchain-snapshot-7~svn326551/include -U NDEBUG -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/7.3.0/../../../../include/c++/7.3.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/7.3.0/../../../../include/x86_64-linux-gnu/c++/7.3.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/7.3.0/../../../../include/x86_64-linux-gnu/c++/7.3.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/7.3.0/../../../../include/c++/7.3.0/backward -internal-isystem /usr/include/clang/7.0.0/include/ -internal-isystem /usr/local/include -internal-isystem /usr/lib/llvm-7/lib/clang/7.0.0/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -Wwrite-strings -Wno-missing-field-initializers -Wno-long-long -Wno-maybe-uninitialized -Wno-comment -std=c++11 -fdeprecated-macro -fdebug-compilation-dir /build/llvm-toolchain-snapshot-7~svn326551/build-llvm/lib/ObjectYAML -ferror-limit 19 -fmessage-length 0 -fvisibility-inlines-hidden -fobjc-runtime=gcc -fdiagnostics-show-option -vectorize-loops -vectorize-slp -analyzer-checker optin.performance.Padding -analyzer-output=html -analyzer-config stable-report-filename=true -o /tmp/scan-build-2018-03-02-155150-1477-1 -x c++ /build/llvm-toolchain-snapshot-7~svn326551/lib/ObjectYAML/CodeViewYAMLDebugSections.cpp

/build/llvm-toolchain-snapshot-7~svn326551/lib/ObjectYAML/CodeViewYAMLDebugSections.cpp

1//===- CodeViewYAMLDebugSections.cpp - CodeView YAMLIO debug sections -----===//
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 classes for handling the YAML representation of CodeView
11// Debug Info.
12//
13//===----------------------------------------------------------------------===//
14
15#include "llvm/ObjectYAML/CodeViewYAMLDebugSections.h"
16#include "llvm/ADT/STLExtras.h"
17#include "llvm/ADT/StringExtras.h"
18#include "llvm/ADT/StringRef.h"
19#include "llvm/BinaryFormat/COFF.h"
20#include "llvm/DebugInfo/CodeView/CodeView.h"
21#include "llvm/DebugInfo/CodeView/CodeViewError.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/DebugFrameDataSubsection.h"
26#include "llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h"
27#include "llvm/DebugInfo/CodeView/DebugLinesSubsection.h"
28#include "llvm/DebugInfo/CodeView/DebugStringTableSubsection.h"
29#include "llvm/DebugInfo/CodeView/DebugSubsection.h"
30#include "llvm/DebugInfo/CodeView/DebugSubsectionVisitor.h"
31#include "llvm/DebugInfo/CodeView/DebugSymbolRVASubsection.h"
32#include "llvm/DebugInfo/CodeView/DebugSymbolsSubsection.h"
33#include "llvm/DebugInfo/CodeView/Line.h"
34#include "llvm/DebugInfo/CodeView/StringsAndChecksums.h"
35#include "llvm/DebugInfo/CodeView/TypeIndex.h"
36#include "llvm/ObjectYAML/CodeViewYAMLSymbols.h"
37#include "llvm/Support/Allocator.h"
38#include "llvm/Support/BinaryStreamReader.h"
39#include "llvm/Support/Endian.h"
40#include "llvm/Support/Error.h"
41#include "llvm/Support/ErrorHandling.h"
42#include "llvm/Support/YAMLTraits.h"
43#include "llvm/Support/raw_ostream.h"
44#include <algorithm>
45#include <cassert>
46#include <cstdint>
47#include <memory>
48#include <string>
49#include <tuple>
50#include <vector>
51
52using namespace llvm;
53using namespace llvm::codeview;
54using namespace llvm::CodeViewYAML;
55using namespace llvm::CodeViewYAML::detail;
56using namespace llvm::yaml;
57
58LLVM_YAML_IS_SEQUENCE_VECTOR(SourceFileChecksumEntry)namespace llvm { namespace yaml { static_assert( !std::is_fundamental
<SourceFileChecksumEntry>::value && !std::is_same
<SourceFileChecksumEntry, std::string>::value &&
!std::is_same<SourceFileChecksumEntry, llvm::StringRef>
::value, "only use LLVM_YAML_IS_SEQUENCE_VECTOR for types you control"
); template <> struct SequenceElementTraits<SourceFileChecksumEntry
> { static const bool flow = false; }; } }
59LLVM_YAML_IS_SEQUENCE_VECTOR(SourceLineEntry)namespace llvm { namespace yaml { static_assert( !std::is_fundamental
<SourceLineEntry>::value && !std::is_same<SourceLineEntry
, std::string>::value && !std::is_same<SourceLineEntry
, llvm::StringRef>::value, "only use LLVM_YAML_IS_SEQUENCE_VECTOR for types you control"
); template <> struct SequenceElementTraits<SourceLineEntry
> { static const bool flow = false; }; } }
60LLVM_YAML_IS_SEQUENCE_VECTOR(SourceColumnEntry)namespace llvm { namespace yaml { static_assert( !std::is_fundamental
<SourceColumnEntry>::value && !std::is_same<
SourceColumnEntry, std::string>::value && !std::is_same
<SourceColumnEntry, llvm::StringRef>::value, "only use LLVM_YAML_IS_SEQUENCE_VECTOR for types you control"
); template <> struct SequenceElementTraits<SourceColumnEntry
> { static const bool flow = false; }; } }
61LLVM_YAML_IS_SEQUENCE_VECTOR(SourceLineBlock)namespace llvm { namespace yaml { static_assert( !std::is_fundamental
<SourceLineBlock>::value && !std::is_same<SourceLineBlock
, std::string>::value && !std::is_same<SourceLineBlock
, llvm::StringRef>::value, "only use LLVM_YAML_IS_SEQUENCE_VECTOR for types you control"
); template <> struct SequenceElementTraits<SourceLineBlock
> { static const bool flow = false; }; } }
62LLVM_YAML_IS_SEQUENCE_VECTOR(SourceLineInfo)namespace llvm { namespace yaml { static_assert( !std::is_fundamental
<SourceLineInfo>::value && !std::is_same<SourceLineInfo
, std::string>::value && !std::is_same<SourceLineInfo
, llvm::StringRef>::value, "only use LLVM_YAML_IS_SEQUENCE_VECTOR for types you control"
); template <> struct SequenceElementTraits<SourceLineInfo
> { static const bool flow = false; }; } }
63LLVM_YAML_IS_SEQUENCE_VECTOR(InlineeSite)namespace llvm { namespace yaml { static_assert( !std::is_fundamental
<InlineeSite>::value && !std::is_same<InlineeSite
, std::string>::value && !std::is_same<InlineeSite
, llvm::StringRef>::value, "only use LLVM_YAML_IS_SEQUENCE_VECTOR for types you control"
); template <> struct SequenceElementTraits<InlineeSite
> { static const bool flow = false; }; } }
64LLVM_YAML_IS_SEQUENCE_VECTOR(InlineeInfo)namespace llvm { namespace yaml { static_assert( !std::is_fundamental
<InlineeInfo>::value && !std::is_same<InlineeInfo
, std::string>::value && !std::is_same<InlineeInfo
, llvm::StringRef>::value, "only use LLVM_YAML_IS_SEQUENCE_VECTOR for types you control"
); template <> struct SequenceElementTraits<InlineeInfo
> { static const bool flow = false; }; } }
65LLVM_YAML_IS_SEQUENCE_VECTOR(CrossModuleExport)namespace llvm { namespace yaml { static_assert( !std::is_fundamental
<CrossModuleExport>::value && !std::is_same<
CrossModuleExport, std::string>::value && !std::is_same
<CrossModuleExport, llvm::StringRef>::value, "only use LLVM_YAML_IS_SEQUENCE_VECTOR for types you control"
); template <> struct SequenceElementTraits<CrossModuleExport
> { static const bool flow = false; }; } }
66LLVM_YAML_IS_SEQUENCE_VECTOR(YAMLCrossModuleImport)namespace llvm { namespace yaml { static_assert( !std::is_fundamental
<YAMLCrossModuleImport>::value && !std::is_same
<YAMLCrossModuleImport, std::string>::value && !
std::is_same<YAMLCrossModuleImport, llvm::StringRef>::value
, "only use LLVM_YAML_IS_SEQUENCE_VECTOR for types you control"
); template <> struct SequenceElementTraits<YAMLCrossModuleImport
> { static const bool flow = false; }; } }
67LLVM_YAML_IS_SEQUENCE_VECTOR(YAMLFrameData)namespace llvm { namespace yaml { static_assert( !std::is_fundamental
<YAMLFrameData>::value && !std::is_same<YAMLFrameData
, std::string>::value && !std::is_same<YAMLFrameData
, llvm::StringRef>::value, "only use LLVM_YAML_IS_SEQUENCE_VECTOR for types you control"
); template <> struct SequenceElementTraits<YAMLFrameData
> { static const bool flow = false; }; } }
68
69LLVM_YAML_DECLARE_SCALAR_TRAITS(HexFormattedString, QuotingType::None)namespace llvm { namespace yaml { template <> struct ScalarTraits
<HexFormattedString> { static void output(const HexFormattedString
&Value, void *ctx, raw_ostream &Out); static StringRef
input(StringRef Scalar, void *ctxt, HexFormattedString &
Value); static QuotingType mustQuote(StringRef) { return QuotingType
::None; } }; } }
70LLVM_YAML_DECLARE_ENUM_TRAITS(DebugSubsectionKind)namespace llvm { namespace yaml { template <> struct ScalarEnumerationTraits
<DebugSubsectionKind> { static void enumeration(IO &
io, DebugSubsectionKind &Value); }; } }
71LLVM_YAML_DECLARE_ENUM_TRAITS(FileChecksumKind)namespace llvm { namespace yaml { template <> struct ScalarEnumerationTraits
<FileChecksumKind> { static void enumeration(IO &io
, FileChecksumKind &Value); }; } }
72LLVM_YAML_DECLARE_BITSET_TRAITS(LineFlags)namespace llvm { namespace yaml { template <> struct ScalarBitSetTraits
<LineFlags> { static void bitset(IO &IO, LineFlags &
Options); }; } }
73
74LLVM_YAML_DECLARE_MAPPING_TRAITS(CrossModuleExport)namespace llvm { namespace yaml { template <> struct MappingTraits
<CrossModuleExport> { static void mapping(IO &IO, CrossModuleExport
&Obj); }; } }
75LLVM_YAML_DECLARE_MAPPING_TRAITS(YAMLFrameData)namespace llvm { namespace yaml { template <> struct MappingTraits
<YAMLFrameData> { static void mapping(IO &IO, YAMLFrameData
&Obj); }; } }
76LLVM_YAML_DECLARE_MAPPING_TRAITS(YAMLCrossModuleImport)namespace llvm { namespace yaml { template <> struct MappingTraits
<YAMLCrossModuleImport> { static void mapping(IO &IO
, YAMLCrossModuleImport &Obj); }; } }
77LLVM_YAML_DECLARE_MAPPING_TRAITS(CrossModuleImportItem)namespace llvm { namespace yaml { template <> struct MappingTraits
<CrossModuleImportItem> { static void mapping(IO &IO
, CrossModuleImportItem &Obj); }; } }
78LLVM_YAML_DECLARE_MAPPING_TRAITS(SourceLineEntry)namespace llvm { namespace yaml { template <> struct MappingTraits
<SourceLineEntry> { static void mapping(IO &IO, SourceLineEntry
&Obj); }; } }
79LLVM_YAML_DECLARE_MAPPING_TRAITS(SourceColumnEntry)namespace llvm { namespace yaml { template <> struct MappingTraits
<SourceColumnEntry> { static void mapping(IO &IO, SourceColumnEntry
&Obj); }; } }
80LLVM_YAML_DECLARE_MAPPING_TRAITS(SourceFileChecksumEntry)namespace llvm { namespace yaml { template <> struct MappingTraits
<SourceFileChecksumEntry> { static void mapping(IO &
IO, SourceFileChecksumEntry &Obj); }; } }
81LLVM_YAML_DECLARE_MAPPING_TRAITS(SourceLineBlock)namespace llvm { namespace yaml { template <> struct MappingTraits
<SourceLineBlock> { static void mapping(IO &IO, SourceLineBlock
&Obj); }; } }
82LLVM_YAML_DECLARE_MAPPING_TRAITS(InlineeSite)namespace llvm { namespace yaml { template <> struct MappingTraits
<InlineeSite> { static void mapping(IO &IO, InlineeSite
&Obj); }; } }
83
84namespace llvm {
85namespace CodeViewYAML {
86namespace detail {
87
88struct YAMLSubsectionBase {
89 explicit YAMLSubsectionBase(DebugSubsectionKind Kind) : Kind(Kind) {}
90 virtual ~YAMLSubsectionBase() = default;
91
92 virtual void map(IO &IO) = 0;
93 virtual std::shared_ptr<DebugSubsection>
94 toCodeViewSubsection(BumpPtrAllocator &Allocator,
95 const codeview::StringsAndChecksums &SC) const = 0;
96
97 DebugSubsectionKind Kind;
98};
99
100} // end namespace detail
101} // end namespace CodeViewYAML
102} // end namespace llvm
103
104namespace {
105
106struct YAMLChecksumsSubsection : public YAMLSubsectionBase {
107 YAMLChecksumsSubsection()
108 : YAMLSubsectionBase(DebugSubsectionKind::FileChecksums) {}
109
110 void map(IO &IO) override;
111 std::shared_ptr<DebugSubsection>
112 toCodeViewSubsection(BumpPtrAllocator &Allocator,
113 const codeview::StringsAndChecksums &SC) const override;
114 static Expected<std::shared_ptr<YAMLChecksumsSubsection>>
115 fromCodeViewSubsection(const DebugStringTableSubsectionRef &Strings,
116 const DebugChecksumsSubsectionRef &FC);
117
118 std::vector<SourceFileChecksumEntry> Checksums;
119};
120
121struct YAMLLinesSubsection : public YAMLSubsectionBase {
122 YAMLLinesSubsection() : YAMLSubsectionBase(DebugSubsectionKind::Lines) {}
123
124 void map(IO &IO) override;
125 std::shared_ptr<DebugSubsection>
126 toCodeViewSubsection(BumpPtrAllocator &Allocator,
127 const codeview::StringsAndChecksums &SC) const override;
128 static Expected<std::shared_ptr<YAMLLinesSubsection>>
129 fromCodeViewSubsection(const DebugStringTableSubsectionRef &Strings,
130 const DebugChecksumsSubsectionRef &Checksums,
131 const DebugLinesSubsectionRef &Lines);
132
133 SourceLineInfo Lines;
134};
135
136struct YAMLInlineeLinesSubsection : public YAMLSubsectionBase {
137 YAMLInlineeLinesSubsection()
138 : YAMLSubsectionBase(DebugSubsectionKind::InlineeLines) {}
139
140 void map(IO &IO) override;
141 std::shared_ptr<DebugSubsection>
142 toCodeViewSubsection(BumpPtrAllocator &Allocator,
143 const codeview::StringsAndChecksums &SC) const override;
144 static Expected<std::shared_ptr<YAMLInlineeLinesSubsection>>
145 fromCodeViewSubsection(const DebugStringTableSubsectionRef &Strings,
146 const DebugChecksumsSubsectionRef &Checksums,
147 const DebugInlineeLinesSubsectionRef &Lines);
148
149 InlineeInfo InlineeLines;
150};
151
152struct YAMLCrossModuleExportsSubsection : public YAMLSubsectionBase {
153 YAMLCrossModuleExportsSubsection()
154 : YAMLSubsectionBase(DebugSubsectionKind::CrossScopeExports) {}
155
156 void map(IO &IO) override;
157 std::shared_ptr<DebugSubsection>
158 toCodeViewSubsection(BumpPtrAllocator &Allocator,
159 const codeview::StringsAndChecksums &SC) const override;
160 static Expected<std::shared_ptr<YAMLCrossModuleExportsSubsection>>
161 fromCodeViewSubsection(const DebugCrossModuleExportsSubsectionRef &Exports);
162
163 std::vector<CrossModuleExport> Exports;
164};
165
166struct YAMLCrossModuleImportsSubsection : public YAMLSubsectionBase {
167 YAMLCrossModuleImportsSubsection()
168 : YAMLSubsectionBase(DebugSubsectionKind::CrossScopeImports) {}
169
170 void map(IO &IO) override;
171 std::shared_ptr<DebugSubsection>
172 toCodeViewSubsection(BumpPtrAllocator &Allocator,
173 const codeview::StringsAndChecksums &SC) const override;
174 static Expected<std::shared_ptr<YAMLCrossModuleImportsSubsection>>
175 fromCodeViewSubsection(const DebugStringTableSubsectionRef &Strings,
176 const DebugCrossModuleImportsSubsectionRef &Imports);
177
178 std::vector<YAMLCrossModuleImport> Imports;
179};
180
181struct YAMLSymbolsSubsection : public YAMLSubsectionBase {
182 YAMLSymbolsSubsection() : YAMLSubsectionBase(DebugSubsectionKind::Symbols) {}
183
184 void map(IO &IO) override;
185 std::shared_ptr<DebugSubsection>
186 toCodeViewSubsection(BumpPtrAllocator &Allocator,
187 const codeview::StringsAndChecksums &SC) const override;
188 static Expected<std::shared_ptr<YAMLSymbolsSubsection>>
189 fromCodeViewSubsection(const DebugSymbolsSubsectionRef &Symbols);
190
191 std::vector<CodeViewYAML::SymbolRecord> Symbols;
192};
193
194struct YAMLStringTableSubsection : public YAMLSubsectionBase {
195 YAMLStringTableSubsection()
196 : YAMLSubsectionBase(DebugSubsectionKind::StringTable) {}
197
198 void map(IO &IO) override;
199 std::shared_ptr<DebugSubsection>
200 toCodeViewSubsection(BumpPtrAllocator &Allocator,
201 const codeview::StringsAndChecksums &SC) const override;
202 static Expected<std::shared_ptr<YAMLStringTableSubsection>>
203 fromCodeViewSubsection(const DebugStringTableSubsectionRef &Strings);
204
205 std::vector<StringRef> Strings;
206};
207
208struct YAMLFrameDataSubsection : public YAMLSubsectionBase {
209 YAMLFrameDataSubsection()
210 : YAMLSubsectionBase(DebugSubsectionKind::FrameData) {}
211
212 void map(IO &IO) override;
213 std::shared_ptr<DebugSubsection>
214 toCodeViewSubsection(BumpPtrAllocator &Allocator,
215 const codeview::StringsAndChecksums &SC) const override;
216 static Expected<std::shared_ptr<YAMLFrameDataSubsection>>
217 fromCodeViewSubsection(const DebugStringTableSubsectionRef &Strings,
218 const DebugFrameDataSubsectionRef &Frames);
219
220 std::vector<YAMLFrameData> Frames;
221};
222
223struct YAMLCoffSymbolRVASubsection : public YAMLSubsectionBase {
224 YAMLCoffSymbolRVASubsection()
225 : YAMLSubsectionBase(DebugSubsectionKind::CoffSymbolRVA) {}
226
227 void map(IO &IO) override;
228 std::shared_ptr<DebugSubsection>
229 toCodeViewSubsection(BumpPtrAllocator &Allocator,
230 const codeview::StringsAndChecksums &SC) const override;
231 static Expected<std::shared_ptr<YAMLCoffSymbolRVASubsection>>
232 fromCodeViewSubsection(const DebugSymbolRVASubsectionRef &RVAs);
233
234 std::vector<uint32_t> RVAs;
235};
236
237} // end anonymous namespace
238
239void ScalarBitSetTraits<LineFlags>::bitset(IO &io, LineFlags &Flags) {
240 io.bitSetCase(Flags, "HasColumnInfo", LF_HaveColumns);
241 io.enumFallback<Hex16>(Flags);
242}
243
244void ScalarEnumerationTraits<FileChecksumKind>::enumeration(
245 IO &io, FileChecksumKind &Kind) {
246 io.enumCase(Kind, "None", FileChecksumKind::None);
247 io.enumCase(Kind, "MD5", FileChecksumKind::MD5);
248 io.enumCase(Kind, "SHA1", FileChecksumKind::SHA1);
249 io.enumCase(Kind, "SHA256", FileChecksumKind::SHA256);
250}
251
252void ScalarTraits<HexFormattedString>::output(const HexFormattedString &Value,
253 void *ctx, raw_ostream &Out) {
254 StringRef Bytes(reinterpret_cast<const char *>(Value.Bytes.data()),
255 Value.Bytes.size());
256 Out << toHex(Bytes);
257}
258
259StringRef ScalarTraits<HexFormattedString>::input(StringRef Scalar, void *ctxt,
260 HexFormattedString &Value) {
261 std::string H = fromHex(Scalar);
262 Value.Bytes.assign(H.begin(), H.end());
263 return StringRef();
264}
265
266void MappingTraits<SourceLineEntry>::mapping(IO &IO, SourceLineEntry &Obj) {
267 IO.mapRequired("Offset", Obj.Offset);
268 IO.mapRequired("LineStart", Obj.LineStart);
269 IO.mapRequired("IsStatement", Obj.IsStatement);
270 IO.mapRequired("EndDelta", Obj.EndDelta);
271}
272
273void MappingTraits<SourceColumnEntry>::mapping(IO &IO, SourceColumnEntry &Obj) {
274 IO.mapRequired("StartColumn", Obj.StartColumn);
275 IO.mapRequired("EndColumn", Obj.EndColumn);
276}
277
278void MappingTraits<SourceLineBlock>::mapping(IO &IO, SourceLineBlock &Obj) {
279 IO.mapRequired("FileName", Obj.FileName);
280 IO.mapRequired("Lines", Obj.Lines);
281 IO.mapRequired("Columns", Obj.Columns);
282}
283
284void MappingTraits<CrossModuleExport>::mapping(IO &IO, CrossModuleExport &Obj) {
285 IO.mapRequired("LocalId", Obj.Local);
286 IO.mapRequired("GlobalId", Obj.Global);
287}
288
289void MappingTraits<YAMLCrossModuleImport>::mapping(IO &IO,
290 YAMLCrossModuleImport &Obj) {
291 IO.mapRequired("Module", Obj.ModuleName);
292 IO.mapRequired("Imports", Obj.ImportIds);
293}
294
295void MappingTraits<SourceFileChecksumEntry>::mapping(
296 IO &IO, SourceFileChecksumEntry &Obj) {
297 IO.mapRequired("FileName", Obj.FileName);
298 IO.mapRequired("Kind", Obj.Kind);
299 IO.mapRequired("Checksum", Obj.ChecksumBytes);
300}
301
302void MappingTraits<InlineeSite>::mapping(IO &IO, InlineeSite &Obj) {
303 IO.mapRequired("FileName", Obj.FileName);
304 IO.mapRequired("LineNum", Obj.SourceLineNum);
305 IO.mapRequired("Inlinee", Obj.Inlinee);
306 IO.mapOptional("ExtraFiles", Obj.ExtraFiles);
307}
308
309void MappingTraits<YAMLFrameData>::mapping(IO &IO, YAMLFrameData &Obj) {
310 IO.mapRequired("CodeSize", Obj.CodeSize);
311 IO.mapRequired("FrameFunc", Obj.FrameFunc);
312 IO.mapRequired("LocalSize", Obj.LocalSize);
313 IO.mapOptional("MaxStackSize", Obj.MaxStackSize);
314 IO.mapOptional("ParamsSize", Obj.ParamsSize);
315 IO.mapOptional("PrologSize", Obj.PrologSize);
316 IO.mapOptional("RvaStart", Obj.RvaStart);
317 IO.mapOptional("SavedRegsSize", Obj.SavedRegsSize);
318}
319
320void YAMLChecksumsSubsection::map(IO &IO) {
321 IO.mapTag("!FileChecksums", true);
322 IO.mapRequired("Checksums", Checksums);
323}
324
325void YAMLLinesSubsection::map(IO &IO) {
326 IO.mapTag("!Lines", true);
327 IO.mapRequired("CodeSize", Lines.CodeSize);
328
329 IO.mapRequired("Flags", Lines.Flags);
330 IO.mapRequired("RelocOffset", Lines.RelocOffset);
331 IO.mapRequired("RelocSegment", Lines.RelocSegment);
332 IO.mapRequired("Blocks", Lines.Blocks);
333}
334
335void YAMLInlineeLinesSubsection::map(IO &IO) {
336 IO.mapTag("!InlineeLines", true);
337 IO.mapRequired("HasExtraFiles", InlineeLines.HasExtraFiles);
338 IO.mapRequired("Sites", InlineeLines.Sites);
339}
340
341void YAMLCrossModuleExportsSubsection::map(IO &IO) {
342 IO.mapTag("!CrossModuleExports", true);
343 IO.mapOptional("Exports", Exports);
344}
345
346void YAMLCrossModuleImportsSubsection::map(IO &IO) {
347 IO.mapTag("!CrossModuleImports", true);
348 IO.mapOptional("Imports", Imports);
349}
350
351void YAMLSymbolsSubsection::map(IO &IO) {
352 IO.mapTag("!Symbols", true);
353 IO.mapRequired("Records", Symbols);
354}
355
356void YAMLStringTableSubsection::map(IO &IO) {
357 IO.mapTag("!StringTable", true);
358 IO.mapRequired("Strings", Strings);
359}
360
361void YAMLFrameDataSubsection::map(IO &IO) {
362 IO.mapTag("!FrameData", true);
363 IO.mapRequired("Frames", Frames);
364}
365
366void YAMLCoffSymbolRVASubsection::map(IO &IO) {
367 IO.mapTag("!COFFSymbolRVAs", true);
368 IO.mapRequired("RVAs", RVAs);
369}
370
371void MappingTraits<YAMLDebugSubsection>::mapping(
372 IO &IO, YAMLDebugSubsection &Subsection) {
373 if (!IO.outputting()) {
374 if (IO.mapTag("!FileChecksums")) {
375 auto SS = std::make_shared<YAMLChecksumsSubsection>();
376 Subsection.Subsection = SS;
377 } else if (IO.mapTag("!Lines")) {
378 Subsection.Subsection = std::make_shared<YAMLLinesSubsection>();
379 } else if (IO.mapTag("!InlineeLines")) {
380 Subsection.Subsection = std::make_shared<YAMLInlineeLinesSubsection>();
381 } else if (IO.mapTag("!CrossModuleExports")) {
382 Subsection.Subsection =
383 std::make_shared<YAMLCrossModuleExportsSubsection>();
384 } else if (IO.mapTag("!CrossModuleImports")) {
385 Subsection.Subsection =
386 std::make_shared<YAMLCrossModuleImportsSubsection>();
387 } else if (IO.mapTag("!Symbols")) {
388 Subsection.Subsection = std::make_shared<YAMLSymbolsSubsection>();
389 } else if (IO.mapTag("!StringTable")) {
390 Subsection.Subsection = std::make_shared<YAMLStringTableSubsection>();
391 } else if (IO.mapTag("!FrameData")) {
392 Subsection.Subsection = std::make_shared<YAMLFrameDataSubsection>();
393 } else if (IO.mapTag("!COFFSymbolRVAs")) {
394 Subsection.Subsection = std::make_shared<YAMLCoffSymbolRVASubsection>();
395 } else {
396 llvm_unreachable("Unexpected subsection tag!")::llvm::llvm_unreachable_internal("Unexpected subsection tag!"
, "/build/llvm-toolchain-snapshot-7~svn326551/lib/ObjectYAML/CodeViewYAMLDebugSections.cpp"
, 396)
;
397 }
398 }
399 Subsection.Subsection->map(IO);
400}
401
402std::shared_ptr<DebugSubsection> YAMLChecksumsSubsection::toCodeViewSubsection(
403 BumpPtrAllocator &Allocator,
404 const codeview::StringsAndChecksums &SC) const {
405 assert(SC.hasStrings())(static_cast <bool> (SC.hasStrings()) ? void (0) : __assert_fail
("SC.hasStrings()", "/build/llvm-toolchain-snapshot-7~svn326551/lib/ObjectYAML/CodeViewYAMLDebugSections.cpp"
, 405, __extension__ __PRETTY_FUNCTION__))
;
406 auto Result = std::make_shared<DebugChecksumsSubsection>(*SC.strings());
407 for (const auto &CS : Checksums) {
408 Result->addChecksum(CS.FileName, CS.Kind, CS.ChecksumBytes.Bytes);
409 }
410 return Result;
411}
412
413std::shared_ptr<DebugSubsection> YAMLLinesSubsection::toCodeViewSubsection(
414 BumpPtrAllocator &Allocator,
415 const codeview::StringsAndChecksums &SC) const {
416 assert(SC.hasStrings() && SC.hasChecksums())(static_cast <bool> (SC.hasStrings() && SC.hasChecksums
()) ? void (0) : __assert_fail ("SC.hasStrings() && SC.hasChecksums()"
, "/build/llvm-toolchain-snapshot-7~svn326551/lib/ObjectYAML/CodeViewYAMLDebugSections.cpp"
, 416, __extension__ __PRETTY_FUNCTION__))
;
417 auto Result =
418 std::make_shared<DebugLinesSubsection>(*SC.checksums(), *SC.strings());
419 Result->setCodeSize(Lines.CodeSize);
420 Result->setRelocationAddress(Lines.RelocSegment, Lines.RelocOffset);
421 Result->setFlags(Lines.Flags);
422 for (const auto &LC : Lines.Blocks) {
423 Result->createBlock(LC.FileName);
424 if (Result->hasColumnInfo()) {
425 for (const auto &Item : zip(LC.Lines, LC.Columns)) {
426 auto &L = std::get<0>(Item);
427 auto &C = std::get<1>(Item);
428 uint32_t LE = L.LineStart + L.EndDelta;
429 Result->addLineAndColumnInfo(L.Offset,
430 LineInfo(L.LineStart, LE, L.IsStatement),
431 C.StartColumn, C.EndColumn);
432 }
433 } else {
434 for (const auto &L : LC.Lines) {
435 uint32_t LE = L.LineStart + L.EndDelta;
436 Result->addLineInfo(L.Offset, LineInfo(L.LineStart, LE, L.IsStatement));
437 }
438 }
439 }
440 return Result;
441}
442
443std::shared_ptr<DebugSubsection>
444YAMLInlineeLinesSubsection::toCodeViewSubsection(
445 BumpPtrAllocator &Allocator,
446 const codeview::StringsAndChecksums &SC) const {
447 assert(SC.hasChecksums())(static_cast <bool> (SC.hasChecksums()) ? void (0) : __assert_fail
("SC.hasChecksums()", "/build/llvm-toolchain-snapshot-7~svn326551/lib/ObjectYAML/CodeViewYAMLDebugSections.cpp"
, 447, __extension__ __PRETTY_FUNCTION__))
;
448 auto Result = std::make_shared<DebugInlineeLinesSubsection>(
449 *SC.checksums(), InlineeLines.HasExtraFiles);
450
451 for (const auto &Site : InlineeLines.Sites) {
452 Result->addInlineSite(TypeIndex(Site.Inlinee), Site.FileName,
453 Site.SourceLineNum);
454 if (!InlineeLines.HasExtraFiles)
455 continue;
456
457 for (auto EF : Site.ExtraFiles) {
458 Result->addExtraFile(EF);
459 }
460 }
461 return Result;
462}
463
464std::shared_ptr<DebugSubsection>
465YAMLCrossModuleExportsSubsection::toCodeViewSubsection(
466 BumpPtrAllocator &Allocator,
467 const codeview::StringsAndChecksums &SC) const {
468 auto Result = std::make_shared<DebugCrossModuleExportsSubsection>();
469 for (const auto &M : Exports)
470 Result->addMapping(M.Local, M.Global);
471 return Result;
472}
473
474std::shared_ptr<DebugSubsection>
475YAMLCrossModuleImportsSubsection::toCodeViewSubsection(
476 BumpPtrAllocator &Allocator,
477 const codeview::StringsAndChecksums &SC) const {
478 assert(SC.hasStrings())(static_cast <bool> (SC.hasStrings()) ? void (0) : __assert_fail
("SC.hasStrings()", "/build/llvm-toolchain-snapshot-7~svn326551/lib/ObjectYAML/CodeViewYAMLDebugSections.cpp"
, 478, __extension__ __PRETTY_FUNCTION__))
;
479
480 auto Result =
481 std::make_shared<DebugCrossModuleImportsSubsection>(*SC.strings());
482 for (const auto &M : Imports) {
483 for (const auto Id : M.ImportIds)
484 Result->addImport(M.ModuleName, Id);
485 }
486 return Result;
487}
488
489std::shared_ptr<DebugSubsection> YAMLSymbolsSubsection::toCodeViewSubsection(
490 BumpPtrAllocator &Allocator,
491 const codeview::StringsAndChecksums &SC) const {
492 auto Result = std::make_shared<DebugSymbolsSubsection>();
493 for (const auto &Sym : Symbols)
494 Result->addSymbol(
495 Sym.toCodeViewSymbol(Allocator, CodeViewContainer::ObjectFile));
496 return Result;
497}
498
499std::shared_ptr<DebugSubsection>
500YAMLStringTableSubsection::toCodeViewSubsection(
501 BumpPtrAllocator &Allocator,
502 const codeview::StringsAndChecksums &SC) const {
503 auto Result = std::make_shared<DebugStringTableSubsection>();
504 for (const auto &Str : this->Strings)
505 Result->insert(Str);
506 return Result;
507}
508
509std::shared_ptr<DebugSubsection> YAMLFrameDataSubsection::toCodeViewSubsection(
510 BumpPtrAllocator &Allocator,
511 const codeview::StringsAndChecksums &SC) const {
512 assert(SC.hasStrings())(static_cast <bool> (SC.hasStrings()) ? void (0) : __assert_fail
("SC.hasStrings()", "/build/llvm-toolchain-snapshot-7~svn326551/lib/ObjectYAML/CodeViewYAMLDebugSections.cpp"
, 512, __extension__ __PRETTY_FUNCTION__))
;
513
514 auto Result = std::make_shared<DebugFrameDataSubsection>();
515 for (const auto &YF : Frames) {
516 codeview::FrameData F;
517 F.CodeSize = YF.CodeSize;
518 F.Flags = YF.Flags;
519 F.LocalSize = YF.LocalSize;
520 F.MaxStackSize = YF.MaxStackSize;
521 F.ParamsSize = YF.ParamsSize;
522 F.PrologSize = YF.PrologSize;
523 F.RvaStart = YF.RvaStart;
524 F.SavedRegsSize = YF.SavedRegsSize;
525 F.FrameFunc = SC.strings()->insert(YF.FrameFunc);
526 Result->addFrameData(F);
527 }
528 return Result;
529}
530
531std::shared_ptr<DebugSubsection>
532YAMLCoffSymbolRVASubsection::toCodeViewSubsection(
533 BumpPtrAllocator &Allocator,
534 const codeview::StringsAndChecksums &SC) const {
535 auto Result = std::make_shared<DebugSymbolRVASubsection>();
536 for (const auto &RVA : RVAs)
537 Result->addRVA(RVA);
538 return Result;
539}
540
541static Expected<SourceFileChecksumEntry>
542convertOneChecksum(const DebugStringTableSubsectionRef &Strings,
543 const FileChecksumEntry &CS) {
544 auto ExpectedString = Strings.getString(CS.FileNameOffset);
545 if (!ExpectedString)
546 return ExpectedString.takeError();
547
548 SourceFileChecksumEntry Result;
549 Result.ChecksumBytes.Bytes = CS.Checksum;
550 Result.Kind = CS.Kind;
551 Result.FileName = *ExpectedString;
552 return Result;
553}
554
555static Expected<StringRef>
556getFileName(const DebugStringTableSubsectionRef &Strings,
557 const DebugChecksumsSubsectionRef &Checksums, uint32_t FileID) {
558 auto Iter = Checksums.getArray().at(FileID);
559 if (Iter == Checksums.getArray().end())
560 return make_error<CodeViewError>(cv_error_code::no_records);
561 uint32_t Offset = Iter->FileNameOffset;
562 return Strings.getString(Offset);
563}
564
565Expected<std::shared_ptr<YAMLChecksumsSubsection>>
566YAMLChecksumsSubsection::fromCodeViewSubsection(
567 const DebugStringTableSubsectionRef &Strings,
568 const DebugChecksumsSubsectionRef &FC) {
569 auto Result = std::make_shared<YAMLChecksumsSubsection>();
570
571 for (const auto &CS : FC) {
572 auto ConvertedCS = convertOneChecksum(Strings, CS);
573 if (!ConvertedCS)
574 return ConvertedCS.takeError();
575 Result->Checksums.push_back(*ConvertedCS);
576 }
577 return Result;
578}
579
580Expected<std::shared_ptr<YAMLLinesSubsection>>
581YAMLLinesSubsection::fromCodeViewSubsection(
582 const DebugStringTableSubsectionRef &Strings,
583 const DebugChecksumsSubsectionRef &Checksums,
584 const DebugLinesSubsectionRef &Lines) {
585 auto Result = std::make_shared<YAMLLinesSubsection>();
586 Result->Lines.CodeSize = Lines.header()->CodeSize;
587 Result->Lines.RelocOffset = Lines.header()->RelocOffset;
588 Result->Lines.RelocSegment = Lines.header()->RelocSegment;
589 Result->Lines.Flags = static_cast<LineFlags>(uint16_t(Lines.header()->Flags));
590 for (const auto &L : Lines) {
591 SourceLineBlock Block;
592 auto EF = getFileName(Strings, Checksums, L.NameIndex);
593 if (!EF)
594 return EF.takeError();
595 Block.FileName = *EF;
596 if (Lines.hasColumnInfo()) {
597 for (const auto &C : L.Columns) {
598 SourceColumnEntry SCE;
599 SCE.EndColumn = C.EndColumn;
600 SCE.StartColumn = C.StartColumn;
601 Block.Columns.push_back(SCE);
602 }
603 }
604 for (const auto &LN : L.LineNumbers) {
605 SourceLineEntry SLE;
606 LineInfo LI(LN.Flags);
607 SLE.Offset = LN.Offset;
608 SLE.LineStart = LI.getStartLine();
609 SLE.EndDelta = LI.getLineDelta();
610 SLE.IsStatement = LI.isStatement();
611 Block.Lines.push_back(SLE);
612 }
613 Result->Lines.Blocks.push_back(Block);
614 }
615 return Result;
616}
617
618Expected<std::shared_ptr<YAMLInlineeLinesSubsection>>
619YAMLInlineeLinesSubsection::fromCodeViewSubsection(
620 const DebugStringTableSubsectionRef &Strings,
621 const DebugChecksumsSubsectionRef &Checksums,
622 const DebugInlineeLinesSubsectionRef &Lines) {
623 auto Result = std::make_shared<YAMLInlineeLinesSubsection>();
624
625 Result->InlineeLines.HasExtraFiles = Lines.hasExtraFiles();
626 for (const auto &IL : Lines) {
627 InlineeSite Site;
628 auto ExpF = getFileName(Strings, Checksums, IL.Header->FileID);
629 if (!ExpF)
630 return ExpF.takeError();
631 Site.FileName = *ExpF;
632 Site.Inlinee = IL.Header->Inlinee.getIndex();
633 Site.SourceLineNum = IL.Header->SourceLineNum;
634 if (Lines.hasExtraFiles()) {
635 for (const auto EF : IL.ExtraFiles) {
636 auto ExpF2 = getFileName(Strings, Checksums, EF);
637 if (!ExpF2)
638 return ExpF2.takeError();
639 Site.ExtraFiles.push_back(*ExpF2);
640 }
641 }
642 Result->InlineeLines.Sites.push_back(Site);
643 }
644 return Result;
645}
646
647Expected<std::shared_ptr<YAMLCrossModuleExportsSubsection>>
648YAMLCrossModuleExportsSubsection::fromCodeViewSubsection(
649 const DebugCrossModuleExportsSubsectionRef &Exports) {
650 auto Result = std::make_shared<YAMLCrossModuleExportsSubsection>();
651 Result->Exports.assign(Exports.begin(), Exports.end());
652 return Result;
653}
654
655Expected<std::shared_ptr<YAMLCrossModuleImportsSubsection>>
656YAMLCrossModuleImportsSubsection::fromCodeViewSubsection(
657 const DebugStringTableSubsectionRef &Strings,
658 const DebugCrossModuleImportsSubsectionRef &Imports) {
659 auto Result = std::make_shared<YAMLCrossModuleImportsSubsection>();
660 for (const auto &CMI : Imports) {
661 YAMLCrossModuleImport YCMI;
662 auto ExpectedStr = Strings.getString(CMI.Header->ModuleNameOffset);
663 if (!ExpectedStr)
664 return ExpectedStr.takeError();
665 YCMI.ModuleName = *ExpectedStr;
666 YCMI.ImportIds.assign(CMI.Imports.begin(), CMI.Imports.end());
667 Result->Imports.push_back(YCMI);
668 }
669 return Result;
670}
671
672Expected<std::shared_ptr<YAMLSymbolsSubsection>>
673YAMLSymbolsSubsection::fromCodeViewSubsection(
674 const DebugSymbolsSubsectionRef &Symbols) {
675 auto Result = std::make_shared<YAMLSymbolsSubsection>();
676 for (const auto &Sym : Symbols) {
677 auto S = CodeViewYAML::SymbolRecord::fromCodeViewSymbol(Sym);
678 if (!S)
679 return joinErrors(make_error<CodeViewError>(
680 cv_error_code::corrupt_record,
681 "Invalid CodeView Symbol Record in SymbolRecord "
682 "subsection of .debug$S while converting to YAML!"),
683 S.takeError());
684
685 Result->Symbols.push_back(*S);
686 }
687 return Result;
688}
689
690Expected<std::shared_ptr<YAMLStringTableSubsection>>
691YAMLStringTableSubsection::fromCodeViewSubsection(
692 const DebugStringTableSubsectionRef &Strings) {
693 auto Result = std::make_shared<YAMLStringTableSubsection>();
694 BinaryStreamReader Reader(Strings.getBuffer());
695 StringRef S;
696 // First item is a single null string, skip it.
697 if (auto EC = Reader.readCString(S))
698 return std::move(EC);
699 assert(S.empty())(static_cast <bool> (S.empty()) ? void (0) : __assert_fail
("S.empty()", "/build/llvm-toolchain-snapshot-7~svn326551/lib/ObjectYAML/CodeViewYAMLDebugSections.cpp"
, 699, __extension__ __PRETTY_FUNCTION__))
;
700 while (Reader.bytesRemaining() > 0) {
701 if (auto EC = Reader.readCString(S))
702 return std::move(EC);
703 Result->Strings.push_back(S);
704 }
705 return Result;
706}
707
708Expected<std::shared_ptr<YAMLFrameDataSubsection>>
709YAMLFrameDataSubsection::fromCodeViewSubsection(
710 const DebugStringTableSubsectionRef &Strings,
711 const DebugFrameDataSubsectionRef &Frames) {
712 auto Result = std::make_shared<YAMLFrameDataSubsection>();
713 for (const auto &F : Frames) {
714 YAMLFrameData YF;
715 YF.CodeSize = F.CodeSize;
716 YF.Flags = F.Flags;
717 YF.LocalSize = F.LocalSize;
718 YF.MaxStackSize = F.MaxStackSize;
719 YF.ParamsSize = F.ParamsSize;
720 YF.PrologSize = F.PrologSize;
721 YF.RvaStart = F.RvaStart;
722 YF.SavedRegsSize = F.SavedRegsSize;
723
724 auto ES = Strings.getString(F.FrameFunc);
725 if (!ES)
726 return joinErrors(
727 make_error<CodeViewError>(
728 cv_error_code::no_records,
729 "Could not find string for string id while mapping FrameData!"),
730 ES.takeError());
731 YF.FrameFunc = *ES;
732 Result->Frames.push_back(YF);
733 }
734 return Result;
735}
736
737Expected<std::shared_ptr<YAMLCoffSymbolRVASubsection>>
738YAMLCoffSymbolRVASubsection::fromCodeViewSubsection(
739 const DebugSymbolRVASubsectionRef &Section) {
740 auto Result = std::make_shared<YAMLCoffSymbolRVASubsection>();
741 for (const auto &RVA : Section) {
742 Result->RVAs.push_back(RVA);
743 }
744 return Result;
745}
746
747Expected<std::vector<std::shared_ptr<DebugSubsection>>>
748llvm::CodeViewYAML::toCodeViewSubsectionList(
749 BumpPtrAllocator &Allocator, ArrayRef<YAMLDebugSubsection> Subsections,
750 const codeview::StringsAndChecksums &SC) {
751 std::vector<std::shared_ptr<DebugSubsection>> Result;
752 if (Subsections.empty())
753 return std::move(Result);
754
755 for (const auto &SS : Subsections) {
756 std::shared_ptr<DebugSubsection> CVS;
757 CVS = SS.Subsection->toCodeViewSubsection(Allocator, SC);
758 assert(CVS != nullptr)(static_cast <bool> (CVS != nullptr) ? void (0) : __assert_fail
("CVS != nullptr", "/build/llvm-toolchain-snapshot-7~svn326551/lib/ObjectYAML/CodeViewYAMLDebugSections.cpp"
, 758, __extension__ __PRETTY_FUNCTION__))
;
759 Result.push_back(std::move(CVS));
760 }
761 return std::move(Result);
762}
763
764namespace {
765
766struct SubsectionConversionVisitor : public DebugSubsectionVisitor {
767 SubsectionConversionVisitor() = default;
768
769 Error visitUnknown(DebugUnknownSubsectionRef &Unknown) override;
770 Error visitLines(DebugLinesSubsectionRef &Lines,
771 const StringsAndChecksumsRef &State) override;
772 Error visitFileChecksums(DebugChecksumsSubsectionRef &Checksums,
773 const StringsAndChecksumsRef &State) override;
774 Error visitInlineeLines(DebugInlineeLinesSubsectionRef &Inlinees,
775 const StringsAndChecksumsRef &State) override;
776 Error visitCrossModuleExports(DebugCrossModuleExportsSubsectionRef &Checksums,
777 const StringsAndChecksumsRef &State) override;
778 Error visitCrossModuleImports(DebugCrossModuleImportsSubsectionRef &Inlinees,
779 const StringsAndChecksumsRef &State) override;
780 Error visitStringTable(DebugStringTableSubsectionRef &ST,
781 const StringsAndChecksumsRef &State) override;
782 Error visitSymbols(DebugSymbolsSubsectionRef &Symbols,
783 const StringsAndChecksumsRef &State) override;
784 Error visitFrameData(DebugFrameDataSubsectionRef &Symbols,
785 const StringsAndChecksumsRef &State) override;
786 Error visitCOFFSymbolRVAs(DebugSymbolRVASubsectionRef &Symbols,
787 const StringsAndChecksumsRef &State) override;
788
789 YAMLDebugSubsection Subsection;
790};
791
792} // end anonymous namespace
793
794Error SubsectionConversionVisitor::visitUnknown(
795 DebugUnknownSubsectionRef &Unknown) {
796 return make_error<CodeViewError>(cv_error_code::operation_unsupported);
797}
798
799Error SubsectionConversionVisitor::visitLines(
800 DebugLinesSubsectionRef &Lines, const StringsAndChecksumsRef &State) {
801 auto Result = YAMLLinesSubsection::fromCodeViewSubsection(
802 State.strings(), State.checksums(), Lines);
803 if (!Result)
804 return Result.takeError();
805 Subsection.Subsection = *Result;
806 return Error::success();
807}
808
809Error SubsectionConversionVisitor::visitFileChecksums(
810 DebugChecksumsSubsectionRef &Checksums,
811 const StringsAndChecksumsRef &State) {
812 auto Result = YAMLChecksumsSubsection::fromCodeViewSubsection(State.strings(),
813 Checksums);
814 if (!Result)
815 return Result.takeError();
816 Subsection.Subsection = *Result;
817 return Error::success();
818}
819
820Error SubsectionConversionVisitor::visitInlineeLines(
821 DebugInlineeLinesSubsectionRef &Inlinees,
822 const StringsAndChecksumsRef &State) {
823 auto Result = YAMLInlineeLinesSubsection::fromCodeViewSubsection(
824 State.strings(), State.checksums(), Inlinees);
825 if (!Result)
826 return Result.takeError();
827 Subsection.Subsection = *Result;
828 return Error::success();
829}
830
831Error SubsectionConversionVisitor::visitCrossModuleExports(
832 DebugCrossModuleExportsSubsectionRef &Exports,
833 const StringsAndChecksumsRef &State) {
834 auto Result =
835 YAMLCrossModuleExportsSubsection::fromCodeViewSubsection(Exports);
836 if (!Result)
837 return Result.takeError();
838 Subsection.Subsection = *Result;
839 return Error::success();
840}
841
842Error SubsectionConversionVisitor::visitCrossModuleImports(
843 DebugCrossModuleImportsSubsectionRef &Imports,
844 const StringsAndChecksumsRef &State) {
845 auto Result = YAMLCrossModuleImportsSubsection::fromCodeViewSubsection(
846 State.strings(), Imports);
847 if (!Result)
848 return Result.takeError();
849 Subsection.Subsection = *Result;
850 return Error::success();
851}
852
853Error SubsectionConversionVisitor::visitStringTable(
854 DebugStringTableSubsectionRef &Strings,
855 const StringsAndChecksumsRef &State) {
856 auto Result = YAMLStringTableSubsection::fromCodeViewSubsection(Strings);
857 if (!Result)
858 return Result.takeError();
859 Subsection.Subsection = *Result;
860 return Error::success();
861}
862
863Error SubsectionConversionVisitor::visitSymbols(
864 DebugSymbolsSubsectionRef &Symbols, const StringsAndChecksumsRef &State) {
865 auto Result = YAMLSymbolsSubsection::fromCodeViewSubsection(Symbols);
866 if (!Result)
867 return Result.takeError();
868 Subsection.Subsection = *Result;
869 return Error::success();
870}
871
872Error SubsectionConversionVisitor::visitFrameData(
873 DebugFrameDataSubsectionRef &Frames, const StringsAndChecksumsRef &State) {
874 auto Result =
875 YAMLFrameDataSubsection::fromCodeViewSubsection(State.strings(), Frames);
876 if (!Result)
877 return Result.takeError();
878 Subsection.Subsection = *Result;
879 return Error::success();
880}
881
882Error SubsectionConversionVisitor::visitCOFFSymbolRVAs(
883 DebugSymbolRVASubsectionRef &RVAs, const StringsAndChecksumsRef &State) {
884 auto Result = YAMLCoffSymbolRVASubsection::fromCodeViewSubsection(RVAs);
885 if (!Result)
886 return Result.takeError();
887 Subsection.Subsection = *Result;
888 return Error::success();
889}
890
891Expected<YAMLDebugSubsection>
892YAMLDebugSubsection::fromCodeViewSubection(const StringsAndChecksumsRef &SC,
893 const DebugSubsectionRecord &SS) {
894 SubsectionConversionVisitor V;
895 if (auto EC = visitDebugSubsection(SS, V, SC))
896 return std::move(EC);
897
898 return V.Subsection;
899}
900
901std::vector<YAMLDebugSubsection>
902llvm::CodeViewYAML::fromDebugS(ArrayRef<uint8_t> Data,
903 const StringsAndChecksumsRef &SC) {
904 BinaryStreamReader Reader(Data, support::little);
905 uint32_t Magic;
1
'Magic' declared without an initial value
906
907 ExitOnError Err("Invalid .debug$S section!");
908 Err(Reader.readInteger(Magic));
2
Calling 'BinaryStreamReader::readInteger'
73
Returning from 'BinaryStreamReader::readInteger'
909 assert(Magic == COFF::DEBUG_SECTION_MAGIC && "Invalid .debug$S section!")(static_cast <bool> (Magic == COFF::DEBUG_SECTION_MAGIC
&& "Invalid .debug$S section!") ? void (0) : __assert_fail
("Magic == COFF::DEBUG_SECTION_MAGIC && \"Invalid .debug$S section!\""
, "/build/llvm-toolchain-snapshot-7~svn326551/lib/ObjectYAML/CodeViewYAMLDebugSections.cpp"
, 909, __extension__ __PRETTY_FUNCTION__))
;
74
Within the expansion of the macro 'assert':
a
The left operand of '==' is a garbage value
910
911 DebugSubsectionArray Subsections;
912 Err(Reader.readArray(Subsections, Reader.bytesRemaining()));
913
914 std::vector<YAMLDebugSubsection> Result;
915
916 for (const auto &SS : Subsections) {
917 auto YamlSS = Err(YAMLDebugSubsection::fromCodeViewSubection(SC, SS));
918 Result.push_back(YamlSS);
919 }
920 return Result;
921}
922
923void llvm::CodeViewYAML::initializeStringsAndChecksums(
924 ArrayRef<YAMLDebugSubsection> Sections, codeview::StringsAndChecksums &SC) {
925 // String Table and Checksums subsections don't use the allocator.
926 BumpPtrAllocator Allocator;
927
928 // It's possible for checksums and strings to even appear in different debug$S
929 // sections, so we have to make this a stateful function that can build up
930 // the strings and checksums field over multiple iterations.
931
932 // File Checksums require the string table, but may become before it, so we
933 // have to scan for strings first, then scan for checksums again from the
934 // beginning.
935 if (!SC.hasStrings()) {
936 for (const auto &SS : Sections) {
937 if (SS.Subsection->Kind != DebugSubsectionKind::StringTable)
938 continue;
939
940 auto Result = SS.Subsection->toCodeViewSubsection(Allocator, SC);
941 SC.setStrings(
942 std::static_pointer_cast<DebugStringTableSubsection>(Result));
943 break;
944 }
945 }
946
947 if (SC.hasStrings() && !SC.hasChecksums()) {
948 for (const auto &SS : Sections) {
949 if (SS.Subsection->Kind != DebugSubsectionKind::FileChecksums)
950 continue;
951
952 auto Result = SS.Subsection->toCodeViewSubsection(Allocator, SC);
953 SC.setChecksums(
954 std::static_pointer_cast<DebugChecksumsSubsection>(Result));
955 break;
956 }
957 }
958}

/build/llvm-toolchain-snapshot-7~svn326551/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)))
3
Calling move constructor for 'Error'
27
Returning from move constructor for 'Error'
28
Calling 'Error::operator bool'
37
Returning from 'Error::operator bool'
38
Taking true branch
82 return EC;
39
Calling move constructor for 'Error'
63
Returning from move constructor for 'Error'
64
Calling '~Error'
71
Returning from '~Error'
83
84 Dest = llvm::support::endian::read<T, llvm::support::unaligned>(
85 Bytes.data(), Stream.getEndian());
86 return Error::success();
87 }
72
Returning without writing to 'Dest'
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-7~svn326551/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-7~svn326551/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-7~svn326551/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);
4
Calling 'Error::setChecked'
6
Returning from 'Error::setChecked'
40
Calling 'Error::setChecked'
42
Returning from 'Error::setChecked'
188 *this = std::move(Other);
7
Calling 'move'
8
Returning from 'move'
9
Calling move assignment operator for 'Error'
26
Returning from move assignment operator for 'Error'
43
Calling 'move'
44
Returning from 'move'
45
Calling move assignment operator for 'Error'
62
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();
10
Calling 'Error::assertIsChecked'
13
Returning from 'Error::assertIsChecked'
46
Calling 'Error::assertIsChecked'
49
Returning from 'Error::assertIsChecked'
208 setPtr(Other.getPtr());
14
Calling 'Error::getPtr'
15
Returning from 'Error::getPtr'
16
Calling 'Error::setPtr'
17
Returning from 'Error::setPtr'
50
Calling 'Error::getPtr'
51
Returning from 'Error::getPtr'
52
Calling 'Error::setPtr'
53
Returning from 'Error::setPtr'
209
210 // This Error is unchecked, even if the source error was checked.
211 setChecked(false);
18
Calling 'Error::setChecked'
20
Returning from 'Error::setChecked'
54
Calling 'Error::setChecked'
56
Returning from 'Error::setChecked'
212
213 // Null out Other's payload and set its checked bit.
214 Other.setPtr(nullptr);
21
Calling 'Error::setPtr'
22
Returning from 'Error::setPtr'
57
Calling 'Error::setPtr'
58
Returning from 'Error::setPtr'
215 Other.setChecked(true);
23
Calling 'Error::setChecked'
25
Returning from 'Error::setChecked'
59
Calling 'Error::setChecked'
61
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();
65
Calling 'Error::assertIsChecked'
68
Returning from 'Error::assertIsChecked'
224 delete getPtr();
69
Calling 'Error::getPtr'
70
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);
29
Calling 'Error::getPtr'
30
Returning from 'Error::getPtr'
31
Calling 'Error::setChecked'
34
Returning from 'Error::setChecked'
232 return getPtr() != nullptr;
35
Calling 'Error::getPtr'
36
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))
11
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'
12
Taking false branch
47
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'
48
Taking false branch
66
Within the expansion of the macro 'LLVM_UNLIKELY':
a
Calling 'Error::getChecked'
b
Returning from 'Error::getChecked'
67
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));
5
'?' condition is true
19
'?' condition is false
24
'?' condition is true
32
Assuming 'V' is 0
33
'?' condition is false
41
'?' condition is true
55
'?' condition is false
60
'?' condition is true
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-7~svn326551/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-7~svn326551/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-7~svn326551/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-7~svn326551/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-7~svn326551/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-7~svn326551/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-7~svn326551/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-7~svn326551/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-7~svn326551/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-7~svn326551/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-7~svn326551/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-7~svn326551/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-7~svn326551/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-7~svn326551/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 by contract all errors
886/// *must* be handled by the given handlers (i.e. there must be no remaining
887/// errors after running the handlers, or llvm_unreachable is 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, llvm_unreachable 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 converting an Error to a bool.
967///
968/// This method returns true if Err is in an error state, or false if it is
969/// in a success state. Puts Err in a checked state in both cases (unlike
970/// Error::operator bool(), which only does this for success states).
971inline bool errorToBool(Error Err) {
972 bool IsError = static_cast<bool>(Err);
973 if (IsError)
974 consumeError(std::move(Err));
975 return IsError;
976}
977
978/// Helper for Errors used as out-parameters.
979///
980/// This helper is for use with the Error-as-out-parameter idiom, where an error
981/// is passed to a function or method by reference, rather than being returned.
982/// In such cases it is helpful to set the checked bit on entry to the function
983/// so that the error can be written to (unchecked Errors abort on assignment)
984/// and clear the checked bit on exit so that clients cannot accidentally forget
985/// to check the result. This helper performs these actions automatically using
986/// RAII:
987///
988/// @code{.cpp}
989/// Result foo(Error &Err) {
990/// ErrorAsOutParameter ErrAsOutParam(&Err); // 'Checked' flag set
991/// // <body of foo>
992/// // <- 'Checked' flag auto-cleared when ErrAsOutParam is destructed.
993/// }
994/// @endcode
995///
996/// ErrorAsOutParameter takes an Error* rather than Error& so that it can be
997/// used with optional Errors (Error pointers that are allowed to be null). If
998/// ErrorAsOutParameter took an Error reference, an instance would have to be
999/// created inside every condition that verified that Error was non-null. By
1000/// taking an Error pointer we can just create one instance at the top of the
1001/// function.
1002class ErrorAsOutParameter {
1003public:
1004 ErrorAsOutParameter(Error *Err) : Err(Err) {
1005 // Raise the checked bit if Err is success.
1006 if (Err)
1007 (void)!!*Err;
1008 }
1009
1010 ~ErrorAsOutParameter() {
1011 // Clear the checked bit.
1012 if (Err && !*Err)
1013 *Err = Error::success();
1014 }
1015
1016private:
1017 Error *Err;
1018};
1019
1020/// Helper for Expected<T>s used as out-parameters.
1021///
1022/// See ErrorAsOutParameter.
1023template <typename T>
1024class ExpectedAsOutParameter {
1025public:
1026 ExpectedAsOutParameter(Expected<T> *ValOrErr)
1027 : ValOrErr(ValOrErr) {
1028 if (ValOrErr)
1029 (void)!!*ValOrErr;
1030 }
1031
1032 ~ExpectedAsOutParameter() {
1033 if (ValOrErr)
1034 ValOrErr->setUnchecked();
1035 }
1036
1037private:
1038 Expected<T> *ValOrErr;
1039};
1040
1041/// This class wraps a std::error_code in a Error.
1042///
1043/// This is useful if you're writing an interface that returns a Error
1044/// (or Expected) and you want to call code that still returns
1045/// std::error_codes.
1046class ECError : public ErrorInfo<ECError> {
1047 friend Error errorCodeToError(std::error_code);
1048
1049public:
1050 void setErrorCode(std::error_code EC) { this->EC = EC; }
1051 std::error_code convertToErrorCode() const override { return EC; }
1052 void log(raw_ostream &OS) const override { OS << EC.message(); }
1053
1054 // Used by ErrorInfo::classID.
1055 static char ID;
1056
1057protected:
1058 ECError() = default;
1059 ECError(std::error_code EC) : EC(EC) {}
1060
1061 std::error_code EC;
1062};
1063
1064/// The value returned by this function can be returned from convertToErrorCode
1065/// for Error values where no sensible translation to std::error_code exists.
1066/// It should only be used in this situation, and should never be used where a
1067/// sensible conversion to std::error_code is available, as attempts to convert
1068/// to/from this error will result in a fatal error. (i.e. it is a programmatic
1069///error to try to convert such a value).
1070std::error_code inconvertibleErrorCode();
1071
1072/// Helper for converting an std::error_code to a Error.
1073Error errorCodeToError(std::error_code EC);
1074
1075/// Helper for converting an ECError to a std::error_code.
1076///
1077/// This method requires that Err be Error() or an ECError, otherwise it
1078/// will trigger a call to abort().
1079std::error_code errorToErrorCode(Error Err);
1080
1081/// Convert an ErrorOr<T> to an Expected<T>.
1082template <typename T> Expected<T> errorOrToExpected(ErrorOr<T> &&EO) {
1083 if (auto EC = EO.getError())
1084 return errorCodeToError(EC);
1085 return std::move(*EO);
1086}
1087
1088/// Convert an Expected<T> to an ErrorOr<T>.
1089template <typename T> ErrorOr<T> expectedToErrorOr(Expected<T> &&E) {
1090 if (auto Err = E.takeError())
1091 return errorToErrorCode(std::move(Err));
1092 return std::move(*E);
1093}
1094
1095/// This class wraps a string in an Error.
1096///
1097/// StringError is useful in cases where the client is not expected to be able
1098/// to consume the specific error message programmatically (for example, if the
1099/// error message is to be presented to the user).
1100class StringError : public ErrorInfo<StringError> {
1101public:
1102 static char ID;
1103
1104 StringError(const Twine &S, std::error_code EC);
1105
1106 void log(raw_ostream &OS) const override;
1107 std::error_code convertToErrorCode() const override;
1108
1109 const std::string &getMessage() const { return Msg; }
1110
1111private:
1112 std::string Msg;
1113 std::error_code EC;
1114};
1115
1116/// Helper for check-and-exit error handling.
1117///
1118/// For tool use only. NOT FOR USE IN LIBRARY CODE.
1119///
1120class ExitOnError {
1121public:
1122 /// Create an error on exit helper.
1123 ExitOnError(std::string Banner = "", int DefaultErrorExitCode = 1)
1124 : Banner(std::move(Banner)),
1125 GetExitCode([=](const Error &) { return DefaultErrorExitCode; }) {}
1126
1127 /// Set the banner string for any errors caught by operator().
1128 void setBanner(std::string Banner) { this->Banner = std::move(Banner); }
1129
1130 /// Set the exit-code mapper function.
1131 void setExitCodeMapper(std::function<int(const Error &)> GetExitCode) {
1132 this->GetExitCode = std::move(GetExitCode);
1133 }
1134
1135 /// Check Err. If it's in a failure state log the error(s) and exit.
1136 void operator()(Error Err) const { checkError(std::move(Err)); }
1137
1138 /// Check E. If it's in a success state then return the contained value. If
1139 /// it's in a failure state log the error(s) and exit.
1140 template <typename T> T operator()(Expected<T> &&E) const {
1141 checkError(E.takeError());
1142 return std::move(*E);
1143 }
1144
1145 /// Check E. If it's in a success state then return the contained reference. If
1146 /// it's in a failure state log the error(s) and exit.
1147 template <typename T> T& operator()(Expected<T&> &&E) const {
1148 checkError(E.takeError());
1149 return *E;
1150 }
1151
1152private:
1153 void checkError(Error Err) const {
1154 if (Err) {
1155 int ExitCode = GetExitCode(Err);
1156 logAllUnhandledErrors(std::move(Err), errs(), Banner);
1157 exit(ExitCode);
1158 }
1159 }
1160
1161 std::string Banner;
1162 std::function<int(const Error &)> GetExitCode;
1163};
1164
1165} // end namespace llvm
1166
1167#endif // LLVM_SUPPORT_ERROR_H