[clang][bytecode][NFC] Only get expr when checking for UB (#125397)
[llvm-project.git] / llvm / lib / IR / DiagnosticInfo.cpp
blob0e526ada4b405b35e18a532b056195c07bbf1c79
1 //===- llvm/IR/DiagnosticInfo.cpp - Diagnostic Definitions ------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file defines the different classes involved in low level diagnostics.
11 // Diagnostics reporting is still done as part of the LLVMContext.
12 //===----------------------------------------------------------------------===//
14 #include "llvm/IR/DiagnosticInfo.h"
15 #include "llvm/ADT/StringExtras.h"
16 #include "llvm/ADT/Twine.h"
17 #include "llvm/ADT/iterator_range.h"
18 #include "llvm/Demangle/Demangle.h"
19 #include "llvm/IR/BasicBlock.h"
20 #include "llvm/IR/Constants.h"
21 #include "llvm/IR/DebugInfoMetadata.h"
22 #include "llvm/IR/DerivedTypes.h"
23 #include "llvm/IR/DiagnosticPrinter.h"
24 #include "llvm/IR/Function.h"
25 #include "llvm/IR/GlobalValue.h"
26 #include "llvm/IR/Instruction.h"
27 #include "llvm/IR/Instructions.h"
28 #include "llvm/IR/LLVMContext.h"
29 #include "llvm/IR/Metadata.h"
30 #include "llvm/IR/Module.h"
31 #include "llvm/IR/Type.h"
32 #include "llvm/IR/Value.h"
33 #include "llvm/Support/Casting.h"
34 #include "llvm/Support/ErrorHandling.h"
35 #include "llvm/Support/InstructionCost.h"
36 #include "llvm/Support/Path.h"
37 #include "llvm/Support/ScopedPrinter.h"
38 #include "llvm/Support/raw_ostream.h"
39 #include <atomic>
40 #include <string>
42 using namespace llvm;
44 int llvm::getNextAvailablePluginDiagnosticKind() {
45 static std::atomic<int> PluginKindID(DK_FirstPluginKind);
46 return ++PluginKindID;
49 const char *OptimizationRemarkAnalysis::AlwaysPrint = "";
51 void DiagnosticInfoGeneric::print(DiagnosticPrinter &DP) const {
52 DP << getMsgStr();
55 void DiagnosticInfoGenericWithLoc::print(DiagnosticPrinter &DP) const {
56 DP << getLocationStr() << ": " << getMsgStr();
59 DiagnosticInfoInlineAsm::DiagnosticInfoInlineAsm(uint64_t LocCookie,
60 const Twine &MsgStr,
61 DiagnosticSeverity Severity)
62 : DiagnosticInfo(DK_InlineAsm, Severity), LocCookie(LocCookie),
63 MsgStr(MsgStr) {}
65 DiagnosticInfoInlineAsm::DiagnosticInfoInlineAsm(const Instruction &I,
66 const Twine &MsgStr,
67 DiagnosticSeverity Severity)
68 : DiagnosticInfo(DK_InlineAsm, Severity), MsgStr(MsgStr), Instr(&I) {
69 if (const MDNode *SrcLoc = I.getMetadata("srcloc")) {
70 if (SrcLoc->getNumOperands() != 0)
71 if (const auto *CI =
72 mdconst::dyn_extract<ConstantInt>(SrcLoc->getOperand(0)))
73 LocCookie = CI->getZExtValue();
77 void DiagnosticInfoInlineAsm::print(DiagnosticPrinter &DP) const {
78 DP << getMsgStr();
79 if (getLocCookie())
80 DP << " at line " << getLocCookie();
83 DiagnosticInfoRegAllocFailure::DiagnosticInfoRegAllocFailure(
84 const Twine &MsgStr, const Function &Fn, const DiagnosticLocation &DL,
85 DiagnosticSeverity Severity)
86 : DiagnosticInfoWithLocationBase(DK_RegAllocFailure, Severity, Fn,
87 DL.isValid() ? DL : Fn.getSubprogram()),
88 MsgStr(MsgStr) {}
90 DiagnosticInfoRegAllocFailure::DiagnosticInfoRegAllocFailure(
91 const Twine &MsgStr, const Function &Fn, DiagnosticSeverity Severity)
92 : DiagnosticInfoWithLocationBase(DK_RegAllocFailure, Severity, Fn,
93 Fn.getSubprogram()),
94 MsgStr(MsgStr) {}
96 void DiagnosticInfoRegAllocFailure::print(DiagnosticPrinter &DP) const {
97 DP << getLocationStr() << ": " << MsgStr << " in function '" << getFunction()
98 << '\'';
101 DiagnosticInfoResourceLimit::DiagnosticInfoResourceLimit(
102 const Function &Fn, const char *ResourceName, uint64_t ResourceSize,
103 uint64_t ResourceLimit, DiagnosticSeverity Severity, DiagnosticKind Kind)
104 : DiagnosticInfoWithLocationBase(Kind, Severity, Fn, Fn.getSubprogram()),
105 Fn(Fn), ResourceName(ResourceName), ResourceSize(ResourceSize),
106 ResourceLimit(ResourceLimit) {}
108 void DiagnosticInfoResourceLimit::print(DiagnosticPrinter &DP) const {
109 DP << getLocationStr() << ": " << getResourceName() << " ("
110 << getResourceSize() << ") exceeds limit (" << getResourceLimit()
111 << ") in function '" << getFunction() << '\'';
114 void DiagnosticInfoDebugMetadataVersion::print(DiagnosticPrinter &DP) const {
115 DP << "ignoring debug info with an invalid version (" << getMetadataVersion()
116 << ") in " << getModule();
119 void DiagnosticInfoIgnoringInvalidDebugMetadata::print(
120 DiagnosticPrinter &DP) const {
121 DP << "ignoring invalid debug info in " << getModule().getModuleIdentifier();
124 void DiagnosticInfoSampleProfile::print(DiagnosticPrinter &DP) const {
125 if (!FileName.empty()) {
126 DP << getFileName();
127 if (LineNum > 0)
128 DP << ":" << getLineNum();
129 DP << ": ";
131 DP << getMsg();
134 void DiagnosticInfoPGOProfile::print(DiagnosticPrinter &DP) const {
135 if (getFileName())
136 DP << getFileName() << ": ";
137 DP << getMsg();
140 void DiagnosticInfo::anchor() {}
141 void DiagnosticInfoStackSize::anchor() {}
142 void DiagnosticInfoWithLocationBase::anchor() {}
143 void DiagnosticInfoIROptimization::anchor() {}
145 DiagnosticLocation::DiagnosticLocation(const DebugLoc &DL) {
146 if (!DL)
147 return;
148 File = DL->getFile();
149 Line = DL->getLine();
150 Column = DL->getColumn();
153 DiagnosticLocation::DiagnosticLocation(const DISubprogram *SP) {
154 if (!SP)
155 return;
157 File = SP->getFile();
158 Line = SP->getScopeLine();
159 Column = 0;
162 StringRef DiagnosticLocation::getRelativePath() const {
163 return File->getFilename();
166 std::string DiagnosticLocation::getAbsolutePath() const {
167 StringRef Name = File->getFilename();
168 if (sys::path::is_absolute(Name))
169 return std::string(Name);
171 SmallString<128> Path;
172 sys::path::append(Path, File->getDirectory(), Name);
173 return sys::path::remove_leading_dotslash(Path).str();
176 std::string DiagnosticInfoWithLocationBase::getAbsolutePath() const {
177 return Loc.getAbsolutePath();
180 void DiagnosticInfoWithLocationBase::getLocation(StringRef &RelativePath,
181 unsigned &Line,
182 unsigned &Column) const {
183 RelativePath = Loc.getRelativePath();
184 Line = Loc.getLine();
185 Column = Loc.getColumn();
188 std::string DiagnosticInfoWithLocationBase::getLocationStr() const {
189 StringRef Filename("<unknown>");
190 unsigned Line = 0;
191 unsigned Column = 0;
192 if (isLocationAvailable())
193 getLocation(Filename, Line, Column);
194 return (Filename + ":" + Twine(Line) + ":" + Twine(Column)).str();
197 DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key,
198 const Value *V)
199 : Key(std::string(Key)) {
200 if (auto *F = dyn_cast<Function>(V)) {
201 if (DISubprogram *SP = F->getSubprogram())
202 Loc = SP;
204 else if (auto *I = dyn_cast<Instruction>(V))
205 Loc = I->getDebugLoc();
207 // Only include names that correspond to user variables. FIXME: We should use
208 // debug info if available to get the name of the user variable.
209 if (isa<llvm::Argument>(V) || isa<GlobalValue>(V))
210 Val = std::string(GlobalValue::dropLLVMManglingEscape(V->getName()));
211 else if (isa<Constant>(V)) {
212 raw_string_ostream OS(Val);
213 V->printAsOperand(OS, /*PrintType=*/false);
214 } else if (auto *I = dyn_cast<Instruction>(V)) {
215 Val = I->getOpcodeName();
216 } else if (auto *MD = dyn_cast<MetadataAsValue>(V)) {
217 if (auto *S = dyn_cast<MDString>(MD->getMetadata()))
218 Val = S->getString();
222 DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, const Type *T)
223 : Key(std::string(Key)) {
224 raw_string_ostream OS(Val);
225 OS << *T;
228 DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, StringRef S)
229 : Key(std::string(Key)), Val(S.str()) {}
231 DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, int N)
232 : Key(std::string(Key)), Val(itostr(N)) {}
234 DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, float N)
235 : Key(std::string(Key)), Val(llvm::to_string(N)) {}
237 DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, long N)
238 : Key(std::string(Key)), Val(itostr(N)) {}
240 DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, long long N)
241 : Key(std::string(Key)), Val(itostr(N)) {}
243 DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, unsigned N)
244 : Key(std::string(Key)), Val(utostr(N)) {}
246 DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key,
247 unsigned long N)
248 : Key(std::string(Key)), Val(utostr(N)) {}
250 DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key,
251 unsigned long long N)
252 : Key(std::string(Key)), Val(utostr(N)) {}
254 DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key,
255 ElementCount EC)
256 : Key(std::string(Key)) {
257 raw_string_ostream OS(Val);
258 EC.print(OS);
261 DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key,
262 InstructionCost C)
263 : Key(std::string(Key)) {
264 raw_string_ostream OS(Val);
265 C.print(OS);
268 DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, DebugLoc Loc)
269 : Key(std::string(Key)), Loc(Loc) {
270 if (Loc) {
271 Val = (Loc->getFilename() + ":" + Twine(Loc.getLine()) + ":" +
272 Twine(Loc.getCol())).str();
273 } else {
274 Val = "<UNKNOWN LOCATION>";
278 void DiagnosticInfoOptimizationBase::print(DiagnosticPrinter &DP) const {
279 DP << getLocationStr() << ": " << getMsg();
280 if (Hotness)
281 DP << " (hotness: " << *Hotness << ")";
284 OptimizationRemark::OptimizationRemark(const char *PassName,
285 StringRef RemarkName,
286 const DiagnosticLocation &Loc,
287 const Value *CodeRegion)
288 : DiagnosticInfoIROptimization(
289 DK_OptimizationRemark, DS_Remark, PassName, RemarkName,
290 *cast<BasicBlock>(CodeRegion)->getParent(), Loc, CodeRegion) {}
292 OptimizationRemark::OptimizationRemark(const char *PassName,
293 StringRef RemarkName,
294 const Instruction *Inst)
295 : DiagnosticInfoIROptimization(DK_OptimizationRemark, DS_Remark, PassName,
296 RemarkName, *Inst->getParent()->getParent(),
297 Inst->getDebugLoc(), Inst->getParent()) {}
299 static const BasicBlock *getFirstFunctionBlock(const Function *Func) {
300 return Func->empty() ? nullptr : &Func->front();
303 OptimizationRemark::OptimizationRemark(const char *PassName,
304 StringRef RemarkName,
305 const Function *Func)
306 : DiagnosticInfoIROptimization(DK_OptimizationRemark, DS_Remark, PassName,
307 RemarkName, *Func, Func->getSubprogram(),
308 getFirstFunctionBlock(Func)) {}
310 bool OptimizationRemark::isEnabled() const {
311 const Function &Fn = getFunction();
312 LLVMContext &Ctx = Fn.getContext();
313 return Ctx.getDiagHandlerPtr()->isPassedOptRemarkEnabled(getPassName());
316 OptimizationRemarkMissed::OptimizationRemarkMissed(
317 const char *PassName, StringRef RemarkName, const DiagnosticLocation &Loc,
318 const Value *CodeRegion)
319 : DiagnosticInfoIROptimization(
320 DK_OptimizationRemarkMissed, DS_Remark, PassName, RemarkName,
321 *cast<BasicBlock>(CodeRegion)->getParent(), Loc, CodeRegion) {}
323 OptimizationRemarkMissed::OptimizationRemarkMissed(const char *PassName,
324 StringRef RemarkName,
325 const Instruction *Inst)
326 : DiagnosticInfoIROptimization(DK_OptimizationRemarkMissed, DS_Remark,
327 PassName, RemarkName,
328 *Inst->getParent()->getParent(),
329 Inst->getDebugLoc(), Inst->getParent()) {}
331 OptimizationRemarkMissed::OptimizationRemarkMissed(const char *PassName,
332 StringRef RemarkName,
333 const Function *Func)
334 : DiagnosticInfoIROptimization(
335 DK_OptimizationRemarkMissed, DS_Remark, PassName, RemarkName, *Func,
336 Func->getSubprogram(), getFirstFunctionBlock(Func)) {}
338 bool OptimizationRemarkMissed::isEnabled() const {
339 const Function &Fn = getFunction();
340 LLVMContext &Ctx = Fn.getContext();
341 return Ctx.getDiagHandlerPtr()->isMissedOptRemarkEnabled(getPassName());
344 OptimizationRemarkAnalysis::OptimizationRemarkAnalysis(
345 const char *PassName, StringRef RemarkName, const DiagnosticLocation &Loc,
346 const Value *CodeRegion)
347 : DiagnosticInfoIROptimization(
348 DK_OptimizationRemarkAnalysis, DS_Remark, PassName, RemarkName,
349 *cast<BasicBlock>(CodeRegion)->getParent(), Loc, CodeRegion) {}
351 OptimizationRemarkAnalysis::OptimizationRemarkAnalysis(const char *PassName,
352 StringRef RemarkName,
353 const Instruction *Inst)
354 : DiagnosticInfoIROptimization(DK_OptimizationRemarkAnalysis, DS_Remark,
355 PassName, RemarkName,
356 *Inst->getParent()->getParent(),
357 Inst->getDebugLoc(), Inst->getParent()) {}
359 OptimizationRemarkAnalysis::OptimizationRemarkAnalysis(
360 enum DiagnosticKind Kind, const char *PassName, StringRef RemarkName,
361 const DiagnosticLocation &Loc, const Value *CodeRegion)
362 : DiagnosticInfoIROptimization(Kind, DS_Remark, PassName, RemarkName,
363 *cast<BasicBlock>(CodeRegion)->getParent(),
364 Loc, CodeRegion) {}
366 OptimizationRemarkAnalysis::OptimizationRemarkAnalysis(const char *PassName,
367 StringRef RemarkName,
368 const Function *Func)
369 : DiagnosticInfoIROptimization(
370 DK_OptimizationRemarkAnalysis, DS_Remark, PassName, RemarkName, *Func,
371 Func->getSubprogram(), getFirstFunctionBlock(Func)) {}
373 bool OptimizationRemarkAnalysis::isEnabled() const {
374 const Function &Fn = getFunction();
375 LLVMContext &Ctx = Fn.getContext();
376 return Ctx.getDiagHandlerPtr()->isAnalysisRemarkEnabled(getPassName()) ||
377 shouldAlwaysPrint();
380 void DiagnosticInfoMIRParser::print(DiagnosticPrinter &DP) const {
381 DP << Diagnostic;
384 void DiagnosticInfoSrcMgr::print(DiagnosticPrinter &DP) const {
385 DP << Diagnostic;
388 DiagnosticInfoOptimizationFailure::DiagnosticInfoOptimizationFailure(
389 const char *PassName, StringRef RemarkName, const DiagnosticLocation &Loc,
390 const Value *CodeRegion)
391 : DiagnosticInfoIROptimization(
392 DK_OptimizationFailure, DS_Warning, PassName, RemarkName,
393 *cast<BasicBlock>(CodeRegion)->getParent(), Loc, CodeRegion) {}
395 bool DiagnosticInfoOptimizationFailure::isEnabled() const {
396 // Only print warnings.
397 return getSeverity() == DS_Warning;
400 void DiagnosticInfoUnsupported::print(DiagnosticPrinter &DP) const {
401 std::string Str;
402 raw_string_ostream OS(Str);
404 OS << getLocationStr() << ": in function " << getFunction().getName() << ' '
405 << *getFunction().getFunctionType() << ": " << Msg << '\n';
406 OS.flush();
407 DP << Str;
410 void DiagnosticInfoInstrumentation::print(DiagnosticPrinter &DP) const {
411 DP << Msg;
414 void DiagnosticInfoISelFallback::print(DiagnosticPrinter &DP) const {
415 DP << "Instruction selection used fallback path for " << getFunction();
418 void DiagnosticInfoOptimizationBase::insert(StringRef S) {
419 Args.emplace_back(S);
422 void DiagnosticInfoOptimizationBase::insert(Argument A) {
423 Args.push_back(std::move(A));
426 void DiagnosticInfoOptimizationBase::insert(setIsVerbose V) {
427 IsVerbose = true;
430 void DiagnosticInfoOptimizationBase::insert(setExtraArgs EA) {
431 FirstExtraArgIndex = Args.size();
434 std::string DiagnosticInfoOptimizationBase::getMsg() const {
435 std::string Str;
436 raw_string_ostream OS(Str);
437 for (const DiagnosticInfoOptimizationBase::Argument &Arg :
438 make_range(Args.begin(), FirstExtraArgIndex == -1
439 ? Args.end()
440 : Args.begin() + FirstExtraArgIndex))
441 OS << Arg.Val;
442 return Str;
445 DiagnosticInfoMisExpect::DiagnosticInfoMisExpect(const Instruction *Inst,
446 Twine &Msg)
447 : DiagnosticInfoWithLocationBase(DK_MisExpect, DS_Warning,
448 *Inst->getParent()->getParent(),
449 Inst->getDebugLoc()),
450 Msg(Msg) {}
452 void DiagnosticInfoMisExpect::print(DiagnosticPrinter &DP) const {
453 DP << getLocationStr() << ": " << getMsg();
456 void OptimizationRemarkAnalysisFPCommute::anchor() {}
457 void OptimizationRemarkAnalysisAliasing::anchor() {}
459 void llvm::diagnoseDontCall(const CallInst &CI) {
460 const auto *F =
461 dyn_cast<Function>(CI.getCalledOperand()->stripPointerCasts());
463 if (!F)
464 return;
466 for (int i = 0; i != 2; ++i) {
467 auto AttrName = i == 0 ? "dontcall-error" : "dontcall-warn";
468 auto Sev = i == 0 ? DS_Error : DS_Warning;
470 if (F->hasFnAttribute(AttrName)) {
471 uint64_t LocCookie = 0;
472 auto A = F->getFnAttribute(AttrName);
473 if (MDNode *MD = CI.getMetadata("srcloc"))
474 LocCookie =
475 mdconst::extract<ConstantInt>(MD->getOperand(0))->getZExtValue();
476 DiagnosticInfoDontCall D(F->getName(), A.getValueAsString(), Sev,
477 LocCookie);
478 F->getContext().diagnose(D);
483 void DiagnosticInfoDontCall::print(DiagnosticPrinter &DP) const {
484 DP << "call to " << demangle(getFunctionName()) << " marked \"dontcall-";
485 if (getSeverity() == DiagnosticSeverity::DS_Error)
486 DP << "error\"";
487 else
488 DP << "warn\"";
489 if (!getNote().empty())
490 DP << ": " << getNote();