Skip to content

Commit b492ec5

Browse files
authored
[ErrorHandling] Add reportFatalInternalError + reportFatalUsageError (NFC) (#138251)
This implements the result of the discussion at: https://discourse.llvm.org/t/rfc-report-fatal-error-and-the-default-value-of-gencrashdialog/73587 There are two different use cases for report_fatal_error, so replace it with two functions reportFatalInternalError() and reportFatalUsageError(). The former indicates a bug in LLVM and generates a crash dialog. The latter does not. The names have been suggested by rnk and people seemed to like them. This replaces a lot of the usages that passed an explicit value for GenCrashDiag. I did not bulk replace remaining report_fatal_error usage -- they probably require case by case review for which function to use.
1 parent 3416d4f commit b492ec5

27 files changed

+119
-82
lines changed

clang/lib/AST/ExternalASTSource.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ uint32_t ExternalASTSource::incrementGeneration(ASTContext &C) {
129129
// FIXME: Only bump the generation counter if the current generation number
130130
// has been observed?
131131
if (!++CurrentGeneration)
132-
llvm::report_fatal_error("generation counter overflowed", false);
132+
llvm::reportFatalUsageError("generation counter overflowed");
133133
}
134134

135135
return OldGeneration;

clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -1399,7 +1399,7 @@ int main(int Argc, char **Argv) {
13991399
PassPlugins.setCallback([&](const std::string &PluginPath) {
14001400
auto Plugin = PassPlugin::Load(PluginPath);
14011401
if (!Plugin)
1402-
report_fatal_error(Plugin.takeError(), /*gen_crash_diag=*/false);
1402+
reportFatalUsageError(Plugin.takeError());
14031403
PluginList.emplace_back(Plugin.get());
14041404
});
14051405
cl::ParseCommandLineOptions(NewArgv.size(), &NewArgv[0]);

llvm/include/llvm/CodeGen/CodeGenTargetMachineImpl.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -82,9 +82,9 @@ getEffectiveCodeModel(std::optional<CodeModel::Model> CM,
8282
if (CM) {
8383
// By default, targets do not support the tiny and kernel models.
8484
if (*CM == CodeModel::Tiny)
85-
report_fatal_error("Target does not support the tiny CodeModel", false);
85+
reportFatalUsageError("Target does not support the tiny CodeModel");
8686
if (*CM == CodeModel::Kernel)
87-
report_fatal_error("Target does not support the kernel CodeModel", false);
87+
reportFatalUsageError("Target does not support the kernel CodeModel");
8888
return *CM;
8989
}
9090
return Default;

llvm/include/llvm/Passes/CodeGenPassBuilder.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -1117,7 +1117,7 @@ void CodeGenPassBuilder<Derived, TargetMachineT>::addRegAllocPass(
11171117
addPass(RAGreedyPass());
11181118
break;
11191119
default:
1120-
report_fatal_error("register allocator not supported yet", false);
1120+
reportFatalUsageError("register allocator not supported yet");
11211121
}
11221122
return;
11231123
}

llvm/include/llvm/Support/Error.h

+9-2
Original file line numberDiff line numberDiff line change
@@ -735,10 +735,17 @@ template <class T> class [[nodiscard]] Expected {
735735
#endif
736736
};
737737

738-
/// Report a serious error, calling any installed error handler. See
739-
/// ErrorHandling.h.
738+
/// @deprecated Use reportFatalInternalError() or reportFatalUsageError()
739+
/// instead.
740740
[[noreturn]] void report_fatal_error(Error Err, bool gen_crash_diag = true);
741741

742+
/// Report a fatal error that indicates a bug in LLVM.
743+
/// See ErrorHandling.h for details.
744+
[[noreturn]] void reportFatalInternalError(Error Err);
745+
/// Report a fatal error that does not indicate a bug in LLVM.
746+
/// See ErrorHandling.h for details.
747+
[[noreturn]] void reportFatalUsageError(Error Err);
748+
742749
/// Report a fatal error if Err is a failure value.
743750
///
744751
/// This function can be used to wrap calls to fallible functions ONLY when it

llvm/include/llvm/Support/ErrorHandling.h

+31-9
Original file line numberDiff line numberDiff line change
@@ -59,22 +59,44 @@ namespace llvm {
5959
~ScopedFatalErrorHandler() { remove_fatal_error_handler(); }
6060
};
6161

62-
/// Reports a serious error, calling any installed error handler. These
63-
/// functions are intended to be used for error conditions which are outside
64-
/// the control of the compiler (I/O errors, invalid user input, etc.)
65-
///
66-
/// If no error handler is installed the default is to print the message to
67-
/// standard error, followed by a newline.
68-
/// After the error handler is called this function will call abort(), it
69-
/// does not return.
70-
/// NOTE: The std::string variant was removed to avoid a <string> dependency.
62+
/// @deprecated Use reportFatalInternalError() or reportFatalUsageError()
63+
/// instead.
7164
[[noreturn]] void report_fatal_error(const char *reason,
7265
bool gen_crash_diag = true);
7366
[[noreturn]] void report_fatal_error(StringRef reason,
7467
bool gen_crash_diag = true);
7568
[[noreturn]] void report_fatal_error(const Twine &reason,
7669
bool gen_crash_diag = true);
7770

71+
/// Report a fatal error that likely indicates a bug in LLVM. It serves a
72+
/// similar purpose as an assertion, but is always enabled, regardless of the
73+
/// value of NDEBUG.
74+
///
75+
/// This will call installed error handlers (or print the message by default)
76+
/// and then abort. This will produce a crash trace and *will* ask users to
77+
/// report an LLVM bug.
78+
[[noreturn]] void reportFatalInternalError(const char *reason);
79+
[[noreturn]] void reportFatalInternalError(StringRef reason);
80+
[[noreturn]] void reportFatalInternalError(const Twine &reason);
81+
82+
/// Report a fatal error that does not indicate a bug in LLVM.
83+
///
84+
/// This can be used in contexts where a proper error reporting mechanism
85+
/// (such as Error/Expected or DiagnosticInfo) is currently not supported, and
86+
/// would be too involved to introduce at the moment.
87+
///
88+
/// Examples where this function should be used instead of
89+
/// reportFatalInternalError() include invalid inputs or options, but also
90+
/// environment error conditions outside LLVM's control. It should also be used
91+
/// for known unsupported/unimplemented functionality.
92+
///
93+
/// This will call installed error handlers (or print the message by default)
94+
/// and then exit with code 1. It will not produce a crash trace and will
95+
/// *not* ask users to report an LLVM bug.
96+
[[noreturn]] void reportFatalUsageError(const char *reason);
97+
[[noreturn]] void reportFatalUsageError(StringRef reason);
98+
[[noreturn]] void reportFatalUsageError(const Twine &reason);
99+
78100
/// Installs a new bad alloc error handler that should be used whenever a
79101
/// bad alloc error, e.g. failing malloc/calloc, is encountered by LLVM.
80102
///

llvm/lib/LTO/LTOBackend.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,7 @@ static void RegisterPassPlugins(ArrayRef<std::string> PassPlugins,
195195
for (auto &PluginFN : PassPlugins) {
196196
auto PassPlugin = PassPlugin::Load(PluginFN);
197197
if (!PassPlugin)
198-
report_fatal_error(PassPlugin.takeError(), /*gen_crash_diag=*/false);
198+
reportFatalUsageError(PassPlugin.takeError());
199199
PassPlugin->registerPassBuilderCallbacks(PB);
200200
}
201201
}

llvm/lib/Support/Error.cpp

+7
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,13 @@ void report_fatal_error(Error Err, bool GenCrashDiag) {
174174
report_fatal_error(Twine(ErrMsg), GenCrashDiag);
175175
}
176176

177+
void reportFatalInternalError(Error Err) {
178+
report_fatal_error(std::move(Err), /*GenCrashDiag=*/true);
179+
}
180+
void reportFatalUsageError(Error Err) {
181+
report_fatal_error(std::move(Err), /*GenCrashDiag=*/false);
182+
}
183+
177184
} // end namespace llvm
178185

179186
LLVMErrorTypeId LLVMGetErrorTypeId(LLVMErrorRef Err) {

llvm/lib/Support/ErrorHandling.cpp

+19
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,25 @@ void llvm::report_fatal_error(const Twine &Reason, bool GenCrashDiag) {
126126
exit(1);
127127
}
128128

129+
void llvm::reportFatalInternalError(const char *reason) {
130+
report_fatal_error(reason, /*GenCrashDiag=*/true);
131+
}
132+
void llvm::reportFatalInternalError(StringRef reason) {
133+
report_fatal_error(reason, /*GenCrashDiag=*/true);
134+
}
135+
void llvm::reportFatalInternalError(const Twine &reason) {
136+
report_fatal_error(reason, /*GenCrashDiag=*/true);
137+
}
138+
void llvm::reportFatalUsageError(const char *reason) {
139+
report_fatal_error(reason, /*GenCrashDiag=*/false);
140+
}
141+
void llvm::reportFatalUsageError(StringRef reason) {
142+
report_fatal_error(reason, /*GenCrashDiag=*/false);
143+
}
144+
void llvm::reportFatalUsageError(const Twine &reason) {
145+
report_fatal_error(reason, /*GenCrashDiag=*/false);
146+
}
147+
129148
void llvm::install_bad_alloc_error_handler(fatal_error_handler_t handler,
130149
void *user_data) {
131150
#if LLVM_ENABLE_THREADS == 1

llvm/lib/Support/raw_ostream.cpp

+2-3
Original file line numberDiff line numberDiff line change
@@ -678,9 +678,8 @@ raw_fd_ostream::~raw_fd_ostream() {
678678
// has_error() and clear the error flag with clear_error() before
679679
// destructing raw_ostream objects which may have errors.
680680
if (has_error())
681-
report_fatal_error(Twine("IO failure on output stream: ") +
682-
error().message(),
683-
/*gen_crash_diag=*/false);
681+
reportFatalUsageError(Twine("IO failure on output stream: ") +
682+
error().message());
684683
}
685684

686685
#if defined(_WIN32)

llvm/lib/Target/AMDGPU/AMDGPUAsmPrinter.cpp

+2-3
Original file line numberDiff line numberDiff line change
@@ -163,9 +163,8 @@ void AMDGPUAsmPrinter::emitFunctionBodyStart() {
163163

164164
// TODO: We're checking this late, would be nice to check it earlier.
165165
if (STM.requiresCodeObjectV6() && CodeObjectVersion < AMDGPU::AMDHSA_COV6) {
166-
report_fatal_error(
167-
STM.getCPU() + " is only available on code object version 6 or better",
168-
/*gen_crash_diag*/ false);
166+
reportFatalUsageError(
167+
STM.getCPU() + " is only available on code object version 6 or better");
169168
}
170169

171170
// TODO: Which one is called first, emitStartOfAsmFile or

llvm/lib/Target/DirectX/DXILIntrinsicExpansion.cpp

+5-9
Original file line numberDiff line numberDiff line change
@@ -138,8 +138,7 @@ static Value *expandCrossIntrinsic(CallInst *Orig) {
138138

139139
VectorType *VT = cast<VectorType>(Orig->getType());
140140
if (cast<FixedVectorType>(VT)->getNumElements() != 3)
141-
report_fatal_error(Twine("return vector must have exactly 3 elements"),
142-
/* gen_crash_diag=*/false);
141+
reportFatalUsageError("return vector must have exactly 3 elements");
143142

144143
Value *op0 = Orig->getOperand(0);
145144
Value *op1 = Orig->getOperand(1);
@@ -197,9 +196,8 @@ static Value *expandFloatDotIntrinsic(CallInst *Orig, Value *A, Value *B) {
197196
DotIntrinsic = Intrinsic::dx_dot4;
198197
break;
199198
default:
200-
report_fatal_error(
201-
Twine("Invalid dot product input vector: length is outside 2-4"),
202-
/* gen_crash_diag=*/false);
199+
reportFatalUsageError(
200+
"Invalid dot product input vector: length is outside 2-4");
203201
return nullptr;
204202
}
205203

@@ -359,8 +357,7 @@ static Value *expandNormalizeIntrinsic(CallInst *Orig) {
359357
if (auto *constantFP = dyn_cast<ConstantFP>(X)) {
360358
const APFloat &fpVal = constantFP->getValueAPF();
361359
if (fpVal.isZero())
362-
report_fatal_error(Twine("Invalid input scalar: length is zero"),
363-
/* gen_crash_diag=*/false);
360+
reportFatalUsageError("Invalid input scalar: length is zero");
364361
}
365362
return Builder.CreateFDiv(X, X);
366363
}
@@ -372,8 +369,7 @@ static Value *expandNormalizeIntrinsic(CallInst *Orig) {
372369
if (auto *constantFP = dyn_cast<ConstantFP>(DotProduct)) {
373370
const APFloat &fpVal = constantFP->getValueAPF();
374371
if (fpVal.isZero())
375-
report_fatal_error(Twine("Invalid input vector: length is zero"),
376-
/* gen_crash_diag=*/false);
372+
reportFatalUsageError("Invalid input vector: length is zero");
377373
}
378374

379375
Value *Multiplicand = Builder.CreateIntrinsic(EltTy, Intrinsic::dx_rsqrt,

llvm/lib/Target/DirectX/DXILOpBuilder.cpp

+2-3
Original file line numberDiff line numberDiff line change
@@ -478,10 +478,9 @@ DXILOpBuilder::DXILOpBuilder(Module &M) : M(M), IRB(M.getContext()) {
478478
ShaderStage = TT.getEnvironment();
479479
// Ensure Environment type is known
480480
if (ShaderStage == Triple::UnknownEnvironment) {
481-
report_fatal_error(
481+
reportFatalUsageError(
482482
Twine(DXILVersion.getAsString()) +
483-
": Unknown Compilation Target Shader Stage specified ",
484-
/*gen_crash_diag*/ false);
483+
": Unknown Compilation Target Shader Stage specified ");
485484
}
486485
}
487486

llvm/lib/Target/DirectX/DXILResourceAccess.cpp

+1-2
Original file line numberDiff line numberDiff line change
@@ -115,8 +115,7 @@ static void createStoreIntrinsic(IntrinsicInst *II, StoreInst *SI,
115115
case dxil::ResourceKind::TextureCubeArray:
116116
case dxil::ResourceKind::FeedbackTexture2D:
117117
case dxil::ResourceKind::FeedbackTexture2DArray:
118-
report_fatal_error("DXIL Load not implemented yet",
119-
/*gen_crash_diag=*/false);
118+
reportFatalUsageError("DXIL Load not implemented yet");
120119
return;
121120
case dxil::ResourceKind::CBuffer:
122121
case dxil::ResourceKind::Sampler:

llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp

+2-3
Original file line numberDiff line numberDiff line change
@@ -2486,8 +2486,7 @@ LoongArchTargetLowering::lowerGlobalTLSAddress(SDValue Op,
24862486
assert(N->getOffset() == 0 && "unexpected offset in global node");
24872487

24882488
if (DAG.getTarget().useEmulatedTLS())
2489-
report_fatal_error("the emulated TLS is prohibited",
2490-
/*GenCrashDiag=*/false);
2489+
reportFatalUsageError("the emulated TLS is prohibited");
24912490

24922491
bool IsDesc = DAG.getTarget().useTLSDESC();
24932492

@@ -7121,4 +7120,4 @@ LoongArchTargetLowering::getPreferredVectorAction(MVT VT) const {
71217120
return TypeWidenVector;
71227121

71237122
return TargetLoweringBase::getPreferredVectorAction(VT);
7124-
}
7123+
}

llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.cpp

+3-2
Original file line numberDiff line numberDiff line change
@@ -52,11 +52,12 @@ namespace RISCV {
5252
} // namespace RISCV
5353

5454
// Report an error but don't ask the user to report a bug.
55+
// TODO: Remove these wrappers.
5556
[[noreturn]] static void reportError(const char *Reason) {
56-
report_fatal_error(Reason, /*gen_crash_diag=*/false);
57+
reportFatalUsageError(Reason);
5758
}
5859
[[noreturn]] static void reportError(Error Err) {
59-
report_fatal_error(std::move(Err), /*gen_crash_diag=*/false);
60+
reportFatalUsageError(std::move(Err));
6061
}
6162

6263
namespace RISCVABI {

llvm/lib/Target/RISCV/RISCVISelLowering.cpp

+4-6
Original file line numberDiff line numberDiff line change
@@ -21465,15 +21465,13 @@ SDValue RISCVTargetLowering::LowerFormalArguments(
2146521465
report_fatal_error("'qci-*' interrupt kinds require Xqciint extension");
2146621466

2146721467
if (Kind.starts_with("SiFive-CLIC-") && !Subtarget.hasVendorXSfmclic())
21468-
report_fatal_error(
21469-
"'SiFive-CLIC-*' interrupt kinds require XSfmclic extension",
21470-
/*gen_crash_diag=*/false);
21468+
reportFatalUsageError(
21469+
"'SiFive-CLIC-*' interrupt kinds require XSfmclic extension");
2147121470

2147221471
const TargetFrameLowering *TFI = Subtarget.getFrameLowering();
2147321472
if (Kind.starts_with("SiFive-CLIC-preemptible") && TFI->hasFP(MF))
21474-
report_fatal_error("'SiFive-CLIC-preemptible' interrupt kinds cannot "
21475-
"have a frame pointer",
21476-
/*gen_crash_diag=*/false);
21473+
reportFatalUsageError("'SiFive-CLIC-preemptible' interrupt kinds cannot "
21474+
"have a frame pointer");
2147721475
}
2147821476

2147921477
EVT PtrVT = getPointerTy(DAG.getDataLayout());

llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ static unsigned typeToAddressSpace(const Type *Ty) {
5252
if (auto *ExtTy = dyn_cast<TargetExtType>(Ty);
5353
ExtTy && isTypedPointerWrapper(ExtTy))
5454
return ExtTy->getIntParameter(0);
55-
report_fatal_error("Unable to convert LLVM type to SPIRVType", true);
55+
reportFatalInternalError("Unable to convert LLVM type to SPIRVType");
5656
}
5757

5858
#ifndef NDEBUG

llvm/lib/Transforms/IPO/BlockExtractor.cpp

+6-7
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,8 @@ void BlockExtractor::loadFile() {
8080
if (LineSplit.empty())
8181
continue;
8282
if (LineSplit.size()!=2)
83-
report_fatal_error("Invalid line format, expecting lines like: 'funcname bb1[;bb2..]'",
84-
/*GenCrashDiag=*/false);
83+
reportFatalUsageError(
84+
"Invalid line format, expecting lines like: 'funcname bb1[;bb2..]'");
8585
SmallVector<StringRef, 4> BBNames;
8686
LineSplit[1].split(BBNames, ';', /*MaxSplit=*/-1,
8787
/*KeepEmpty=*/false);
@@ -139,14 +139,13 @@ bool BlockExtractor::runOnModule(Module &M) {
139139
for (const auto &BInfo : BlocksByName) {
140140
Function *F = M.getFunction(BInfo.first);
141141
if (!F)
142-
report_fatal_error("Invalid function name specified in the input file",
143-
/*GenCrashDiag=*/false);
142+
reportFatalUsageError(
143+
"Invalid function name specified in the input file");
144144
for (const auto &BBInfo : BInfo.second) {
145145
auto Res = llvm::find_if(
146146
*F, [&](const BasicBlock &BB) { return BB.getName() == BBInfo; });
147147
if (Res == F->end())
148-
report_fatal_error("Invalid block name specified in the input file",
149-
/*GenCrashDiag=*/false);
148+
reportFatalUsageError("Invalid block name specified in the input file");
150149
GroupsOfBlocks[NextGroupIdx].push_back(&*Res);
151150
}
152151
++NextGroupIdx;
@@ -158,7 +157,7 @@ bool BlockExtractor::runOnModule(Module &M) {
158157
for (BasicBlock *BB : BBs) {
159158
// Check if the module contains BB.
160159
if (BB->getParent()->getParent() != &M)
161-
report_fatal_error("Invalid basic block", /*GenCrashDiag=*/false);
160+
reportFatalUsageError("Invalid basic block");
162161
LLVM_DEBUG(dbgs() << "BlockExtractor: Extracting "
163162
<< BB->getParent()->getName() << ":" << BB->getName()
164163
<< "\n");

llvm/lib/Transforms/IPO/EmbedBitcodePass.cpp

+3-5
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,12 @@ using namespace llvm;
2424

2525
PreservedAnalyses EmbedBitcodePass::run(Module &M, ModuleAnalysisManager &AM) {
2626
if (M.getGlobalVariable("llvm.embedded.module", /*AllowInternal=*/true))
27-
report_fatal_error("Can only embed the module once",
28-
/*gen_crash_diag=*/false);
27+
reportFatalUsageError("Can only embed the module once");
2928

3029
Triple T(M.getTargetTriple());
3130
if (T.getObjectFormat() != Triple::ELF)
32-
report_fatal_error(
33-
"EmbedBitcode pass currently only supports ELF object format",
34-
/*gen_crash_diag=*/false);
31+
reportFatalUsageError(
32+
"EmbedBitcode pass currently only supports ELF object format");
3533

3634
std::string Data;
3735
raw_string_ostream OS(Data);

llvm/lib/Transforms/InstCombine/InstructionCombining.cpp

+5-6
Original file line numberDiff line numberDiff line change
@@ -5645,13 +5645,12 @@ static bool combineInstructionsOverFunction(
56455645

56465646
MadeIRChange = true;
56475647
if (Iteration > Opts.MaxIterations) {
5648-
report_fatal_error(
5648+
reportFatalUsageError(
56495649
"Instruction Combining on " + Twine(F.getName()) +
5650-
" did not reach a fixpoint after " + Twine(Opts.MaxIterations) +
5651-
" iterations. " +
5652-
"Use 'instcombine<no-verify-fixpoint>' or function attribute "
5653-
"'instcombine-no-verify-fixpoint' to suppress this error.",
5654-
/*GenCrashDiag=*/false);
5650+
" did not reach a fixpoint after " + Twine(Opts.MaxIterations) +
5651+
" iterations. " +
5652+
"Use 'instcombine<no-verify-fixpoint>' or function attribute "
5653+
"'instcombine-no-verify-fixpoint' to suppress this error.");
56555654
}
56565655
}
56575656

llvm/lib/Transforms/Instrumentation/GCOVProfiling.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -81,8 +81,8 @@ GCOVOptions GCOVOptions::getDefault() {
8181
Options.Atomic = AtomicCounter;
8282

8383
if (DefaultGCOVVersion.size() != 4) {
84-
llvm::report_fatal_error(Twine("Invalid -default-gcov-version: ") +
85-
DefaultGCOVVersion, /*GenCrashDiag=*/false);
84+
reportFatalUsageError(Twine("Invalid -default-gcov-version: ") +
85+
DefaultGCOVVersion);
8686
}
8787
memcpy(Options.Version, DefaultGCOVVersion.c_str(), 4);
8888
return Options;

0 commit comments

Comments
 (0)