cb424d7448
verify-patch-sanity.py validates every active recipe .patch has internally- consistent hunk line counts — catching the 'malformed patch at line N' failure at commit/CI/preflight time instead of hours into a cook. This cycle hit that class three times (qtwaylandscanner, sddm, xwayland), each only discovered when cookbook tried to apply the patch. Running it across the repo found 29 latent malformed patches (validated against GNU patch: e.g. relibc/P3-sysv-ipc reproduces 'malformed patch at line 22'). They were harmless only because they sit in vendored recipes (baked, not re- applied) — but would fail on any version-bump re-derivation. --fix recounts the hunk headers (body untouched) and repaired all 29. Wired into build-preflight.sh (Phase 1.0D) and redbear-ci.yml, with a unit test (test-patch-sanity.sh). Skips archived/legacy trees and unvalidatable formats (empty placeholders, bare-@@ git hunks).
495 lines
18 KiB
C++
495 lines
18 KiB
C++
//===- llvm/IR/DiagnosticInfo.cpp - Diagnostic Definitions ------*- C++ -*-===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This file defines the different classes involved in low level diagnostics.
|
|
//
|
|
// Diagnostics reporting is still done as part of the LLVMContext.
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "llvm/IR/DiagnosticInfo.h"
|
|
#include "llvm/ADT/StringExtras.h"
|
|
#include "llvm/ADT/Twine.h"
|
|
#include "llvm/ADT/iterator_range.h"
|
|
#include "llvm/Demangle/Demangle.h"
|
|
#include "llvm/IR/BasicBlock.h"
|
|
#include "llvm/IR/Constants.h"
|
|
#include "llvm/IR/DebugInfoMetadata.h"
|
|
#include "llvm/IR/DerivedTypes.h"
|
|
#include "llvm/IR/DiagnosticPrinter.h"
|
|
#include "llvm/IR/Function.h"
|
|
#include "llvm/IR/GlobalValue.h"
|
|
#include "llvm/IR/Instruction.h"
|
|
#include "llvm/IR/Instructions.h"
|
|
#include "llvm/IR/IntrinsicInst.h"
|
|
#include "llvm/IR/LLVMContext.h"
|
|
#include "llvm/IR/Metadata.h"
|
|
#include "llvm/IR/Module.h"
|
|
#include "llvm/IR/Type.h"
|
|
#include "llvm/IR/Value.h"
|
|
#include "llvm/Support/Casting.h"
|
|
#include "llvm/Support/ErrorHandling.h"
|
|
#include "llvm/Support/InstructionCost.h"
|
|
#include "llvm/Support/Path.h"
|
|
#include "llvm/Support/ScopedPrinter.h"
|
|
#include "llvm/Support/raw_ostream.h"
|
|
#include <atomic>
|
|
#include <string>
|
|
|
|
using namespace llvm;
|
|
|
|
int llvm::getNextAvailablePluginDiagnosticKind() {
|
|
static std::atomic<int> PluginKindID(DK_FirstPluginKind);
|
|
return ++PluginKindID;
|
|
}
|
|
|
|
const char *OptimizationRemarkAnalysis::AlwaysPrint = "";
|
|
|
|
void DiagnosticInfoGeneric::print(DiagnosticPrinter &DP) const {
|
|
DP << getMsgStr();
|
|
}
|
|
|
|
void DiagnosticInfoGenericWithLoc::print(DiagnosticPrinter &DP) const {
|
|
DP << getLocationStr() << ": " << getMsgStr();
|
|
}
|
|
|
|
DiagnosticInfoInlineAsm::DiagnosticInfoInlineAsm(uint64_t LocCookie,
|
|
const Twine &MsgStr,
|
|
DiagnosticSeverity Severity)
|
|
: DiagnosticInfo(DK_InlineAsm, Severity), LocCookie(LocCookie),
|
|
MsgStr(MsgStr) {}
|
|
|
|
DiagnosticInfoInlineAsm::DiagnosticInfoInlineAsm(const Instruction &I,
|
|
const Twine &MsgStr,
|
|
DiagnosticSeverity Severity)
|
|
: DiagnosticInfo(DK_InlineAsm, Severity), MsgStr(MsgStr), Instr(&I) {
|
|
if (const MDNode *SrcLoc = I.getMetadata("srcloc")) {
|
|
if (SrcLoc->getNumOperands() != 0)
|
|
if (const auto *CI =
|
|
mdconst::dyn_extract<ConstantInt>(SrcLoc->getOperand(0)))
|
|
LocCookie = CI->getZExtValue();
|
|
}
|
|
}
|
|
|
|
void DiagnosticInfoInlineAsm::print(DiagnosticPrinter &DP) const {
|
|
DP << getMsgStr();
|
|
if (getLocCookie())
|
|
DP << " at line " << getLocCookie();
|
|
}
|
|
|
|
DiagnosticInfoRegAllocFailure::DiagnosticInfoRegAllocFailure(
|
|
const Twine &MsgStr, const Function &Fn, const DiagnosticLocation &DL,
|
|
DiagnosticSeverity Severity)
|
|
: DiagnosticInfoWithLocationBase(DK_RegAllocFailure, Severity, Fn,
|
|
DL.isValid() ? DL : Fn.getSubprogram()),
|
|
MsgStr(MsgStr) {}
|
|
|
|
DiagnosticInfoRegAllocFailure::DiagnosticInfoRegAllocFailure(
|
|
const Twine &MsgStr, const Function &Fn, DiagnosticSeverity Severity)
|
|
: DiagnosticInfoWithLocationBase(DK_RegAllocFailure, Severity, Fn,
|
|
Fn.getSubprogram()),
|
|
MsgStr(MsgStr) {}
|
|
|
|
void DiagnosticInfoRegAllocFailure::print(DiagnosticPrinter &DP) const {
|
|
DP << getLocationStr() << ": " << MsgStr << " in function '" << getFunction()
|
|
<< '\'';
|
|
}
|
|
|
|
DiagnosticInfoResourceLimit::DiagnosticInfoResourceLimit(
|
|
const Function &Fn, const char *ResourceName, uint64_t ResourceSize,
|
|
uint64_t ResourceLimit, DiagnosticSeverity Severity, DiagnosticKind Kind)
|
|
: DiagnosticInfoWithLocationBase(Kind, Severity, Fn, Fn.getSubprogram()),
|
|
Fn(Fn), ResourceName(ResourceName), ResourceSize(ResourceSize),
|
|
ResourceLimit(ResourceLimit) {}
|
|
|
|
void DiagnosticInfoResourceLimit::print(DiagnosticPrinter &DP) const {
|
|
DP << getLocationStr() << ": " << getResourceName() << " ("
|
|
<< getResourceSize() << ") exceeds limit (" << getResourceLimit()
|
|
<< ") in function '" << getFunction() << '\'';
|
|
}
|
|
|
|
void DiagnosticInfoDebugMetadataVersion::print(DiagnosticPrinter &DP) const {
|
|
DP << "ignoring debug info with an invalid version (" << getMetadataVersion()
|
|
<< ") in " << getModule();
|
|
}
|
|
|
|
void DiagnosticInfoIgnoringInvalidDebugMetadata::print(
|
|
DiagnosticPrinter &DP) const {
|
|
DP << "ignoring invalid debug info in " << getModule().getModuleIdentifier();
|
|
}
|
|
|
|
void DiagnosticInfoSampleProfile::print(DiagnosticPrinter &DP) const {
|
|
if (!FileName.empty()) {
|
|
DP << getFileName();
|
|
if (LineNum > 0)
|
|
DP << ":" << getLineNum();
|
|
DP << ": ";
|
|
}
|
|
DP << getMsg();
|
|
}
|
|
|
|
void DiagnosticInfoPGOProfile::print(DiagnosticPrinter &DP) const {
|
|
if (getFileName())
|
|
DP << getFileName() << ": ";
|
|
DP << getMsg();
|
|
}
|
|
|
|
void DiagnosticInfo::anchor() {}
|
|
void DiagnosticInfoStackSize::anchor() {}
|
|
void DiagnosticInfoWithLocationBase::anchor() {}
|
|
void DiagnosticInfoIROptimization::anchor() {}
|
|
|
|
DiagnosticLocation::DiagnosticLocation(const DebugLoc &DL) {
|
|
if (!DL)
|
|
return;
|
|
File = DL->getFile();
|
|
Line = DL->getLine();
|
|
Column = DL->getColumn();
|
|
}
|
|
|
|
DiagnosticLocation::DiagnosticLocation(const DISubprogram *SP) {
|
|
if (!SP)
|
|
return;
|
|
|
|
File = SP->getFile();
|
|
Line = SP->getScopeLine();
|
|
Column = 0;
|
|
}
|
|
|
|
StringRef DiagnosticLocation::getRelativePath() const {
|
|
return File->getFilename();
|
|
}
|
|
|
|
std::string DiagnosticLocation::getAbsolutePath() const {
|
|
StringRef Name = File->getFilename();
|
|
if (sys::path::is_absolute(Name))
|
|
return std::string(Name);
|
|
|
|
SmallString<128> Path;
|
|
sys::path::append(Path, File->getDirectory(), Name);
|
|
return sys::path::remove_leading_dotslash(Path).str();
|
|
}
|
|
|
|
std::string DiagnosticInfoWithLocationBase::getAbsolutePath() const {
|
|
return Loc.getAbsolutePath();
|
|
}
|
|
|
|
void DiagnosticInfoWithLocationBase::getLocation(StringRef &RelativePath,
|
|
unsigned &Line,
|
|
unsigned &Column) const {
|
|
RelativePath = Loc.getRelativePath();
|
|
Line = Loc.getLine();
|
|
Column = Loc.getColumn();
|
|
}
|
|
|
|
std::string DiagnosticInfoWithLocationBase::getLocationStr() const {
|
|
StringRef Filename("<unknown>");
|
|
unsigned Line = 0;
|
|
unsigned Column = 0;
|
|
if (isLocationAvailable())
|
|
getLocation(Filename, Line, Column);
|
|
return (Filename + ":" + Twine(Line) + ":" + Twine(Column)).str();
|
|
}
|
|
|
|
DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key,
|
|
const Value *V)
|
|
: Key(std::string(Key)) {
|
|
if (auto *F = dyn_cast<Function>(V)) {
|
|
if (DISubprogram *SP = F->getSubprogram())
|
|
Loc = SP;
|
|
}
|
|
else if (auto *I = dyn_cast<Instruction>(V))
|
|
Loc = I->getDebugLoc();
|
|
|
|
// Only include names that correspond to user variables. FIXME: We should use
|
|
// debug info if available to get the name of the user variable.
|
|
if (isa<llvm::Argument>(V) || isa<GlobalValue>(V))
|
|
Val = std::string(GlobalValue::dropLLVMManglingEscape(V->getName()));
|
|
else if (isa<Constant>(V)) {
|
|
raw_string_ostream OS(Val);
|
|
V->printAsOperand(OS, /*PrintType=*/false);
|
|
} else if (auto *II = dyn_cast<IntrinsicInst>(V)) {
|
|
raw_string_ostream OS(Val);
|
|
OS << "call " << II->getCalledFunction()->getName();
|
|
} else if (auto *I = dyn_cast<Instruction>(V)) {
|
|
Val = I->getOpcodeName();
|
|
} else if (auto *MD = dyn_cast<MetadataAsValue>(V)) {
|
|
if (auto *S = dyn_cast<MDString>(MD->getMetadata()))
|
|
Val = S->getString();
|
|
}
|
|
}
|
|
|
|
DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, const Type *T)
|
|
: Key(std::string(Key)) {
|
|
raw_string_ostream OS(Val);
|
|
OS << *T;
|
|
}
|
|
|
|
DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, StringRef S)
|
|
: Key(std::string(Key)), Val(S.str()) {}
|
|
|
|
DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, int N)
|
|
: Key(std::string(Key)), Val(itostr(N)) {}
|
|
|
|
DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, float N)
|
|
: Key(std::string(Key)), Val(llvm::to_string(N)) {}
|
|
|
|
DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, long N)
|
|
: Key(std::string(Key)), Val(itostr(N)) {}
|
|
|
|
DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, long long N)
|
|
: Key(std::string(Key)), Val(itostr(N)) {}
|
|
|
|
DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, unsigned N)
|
|
: Key(std::string(Key)), Val(utostr(N)) {}
|
|
|
|
DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key,
|
|
unsigned long N)
|
|
: Key(std::string(Key)), Val(utostr(N)) {}
|
|
|
|
DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key,
|
|
unsigned long long N)
|
|
: Key(std::string(Key)), Val(utostr(N)) {}
|
|
|
|
DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key,
|
|
ElementCount EC)
|
|
: Key(std::string(Key)) {
|
|
raw_string_ostream OS(Val);
|
|
EC.print(OS);
|
|
}
|
|
|
|
DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key,
|
|
InstructionCost C)
|
|
: Key(std::string(Key)) {
|
|
raw_string_ostream OS(Val);
|
|
C.print(OS);
|
|
}
|
|
|
|
DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, DebugLoc Loc)
|
|
: Key(std::string(Key)), Loc(Loc) {
|
|
if (Loc) {
|
|
Val = (Loc->getFilename() + ":" + Twine(Loc.getLine()) + ":" +
|
|
Twine(Loc.getCol())).str();
|
|
} else {
|
|
Val = "<UNKNOWN LOCATION>";
|
|
}
|
|
}
|
|
|
|
void DiagnosticInfoOptimizationBase::print(DiagnosticPrinter &DP) const {
|
|
DP << getLocationStr() << ": " << getMsg();
|
|
if (Hotness)
|
|
DP << " (hotness: " << *Hotness << ")";
|
|
}
|
|
|
|
OptimizationRemark::OptimizationRemark(const char *PassName,
|
|
StringRef RemarkName,
|
|
const DiagnosticLocation &Loc,
|
|
const BasicBlock *CodeRegion)
|
|
: DiagnosticInfoIROptimization(DK_OptimizationRemark, DS_Remark, PassName,
|
|
RemarkName, *CodeRegion->getParent(), Loc,
|
|
CodeRegion) {}
|
|
|
|
OptimizationRemark::OptimizationRemark(const char *PassName,
|
|
StringRef RemarkName,
|
|
const Instruction *Inst)
|
|
: DiagnosticInfoIROptimization(DK_OptimizationRemark, DS_Remark, PassName,
|
|
RemarkName, *Inst->getParent()->getParent(),
|
|
Inst->getDebugLoc(), Inst->getParent()) {}
|
|
|
|
static const BasicBlock *getFirstFunctionBlock(const Function *Func) {
|
|
return Func->empty() ? nullptr : &Func->front();
|
|
}
|
|
|
|
OptimizationRemark::OptimizationRemark(const char *PassName,
|
|
StringRef RemarkName,
|
|
const Function *Func)
|
|
: DiagnosticInfoIROptimization(DK_OptimizationRemark, DS_Remark, PassName,
|
|
RemarkName, *Func, Func->getSubprogram(),
|
|
getFirstFunctionBlock(Func)) {}
|
|
|
|
bool OptimizationRemark::isEnabled() const {
|
|
const Function &Fn = getFunction();
|
|
LLVMContext &Ctx = Fn.getContext();
|
|
return Ctx.getDiagHandlerPtr()->isPassedOptRemarkEnabled(getPassName());
|
|
}
|
|
|
|
OptimizationRemarkMissed::OptimizationRemarkMissed(
|
|
const char *PassName, StringRef RemarkName, const DiagnosticLocation &Loc,
|
|
const BasicBlock *CodeRegion)
|
|
: DiagnosticInfoIROptimization(DK_OptimizationRemarkMissed, DS_Remark,
|
|
PassName, RemarkName,
|
|
*CodeRegion->getParent(), Loc, CodeRegion) {}
|
|
|
|
OptimizationRemarkMissed::OptimizationRemarkMissed(const char *PassName,
|
|
StringRef RemarkName,
|
|
const Instruction *Inst)
|
|
: DiagnosticInfoIROptimization(DK_OptimizationRemarkMissed, DS_Remark,
|
|
PassName, RemarkName,
|
|
*Inst->getParent()->getParent(),
|
|
Inst->getDebugLoc(), Inst->getParent()) {}
|
|
|
|
OptimizationRemarkMissed::OptimizationRemarkMissed(const char *PassName,
|
|
StringRef RemarkName,
|
|
const Function *Func)
|
|
: DiagnosticInfoIROptimization(
|
|
DK_OptimizationRemarkMissed, DS_Remark, PassName, RemarkName, *Func,
|
|
Func->getSubprogram(), getFirstFunctionBlock(Func)) {}
|
|
|
|
bool OptimizationRemarkMissed::isEnabled() const {
|
|
const Function &Fn = getFunction();
|
|
LLVMContext &Ctx = Fn.getContext();
|
|
return Ctx.getDiagHandlerPtr()->isMissedOptRemarkEnabled(getPassName());
|
|
}
|
|
|
|
OptimizationRemarkAnalysis::OptimizationRemarkAnalysis(
|
|
const char *PassName, StringRef RemarkName, const DiagnosticLocation &Loc,
|
|
const BasicBlock *CodeRegion)
|
|
: DiagnosticInfoIROptimization(DK_OptimizationRemarkAnalysis, DS_Remark,
|
|
PassName, RemarkName,
|
|
*CodeRegion->getParent(), Loc, CodeRegion) {}
|
|
|
|
OptimizationRemarkAnalysis::OptimizationRemarkAnalysis(const char *PassName,
|
|
StringRef RemarkName,
|
|
const Instruction *Inst)
|
|
: DiagnosticInfoIROptimization(DK_OptimizationRemarkAnalysis, DS_Remark,
|
|
PassName, RemarkName,
|
|
*Inst->getParent()->getParent(),
|
|
Inst->getDebugLoc(), Inst->getParent()) {}
|
|
|
|
OptimizationRemarkAnalysis::OptimizationRemarkAnalysis(
|
|
enum DiagnosticKind Kind, const char *PassName, StringRef RemarkName,
|
|
const DiagnosticLocation &Loc, const BasicBlock *CodeRegion)
|
|
: DiagnosticInfoIROptimization(Kind, DS_Remark, PassName, RemarkName,
|
|
*CodeRegion->getParent(), Loc, CodeRegion) {}
|
|
|
|
OptimizationRemarkAnalysis::OptimizationRemarkAnalysis(const char *PassName,
|
|
StringRef RemarkName,
|
|
const Function *Func)
|
|
: DiagnosticInfoIROptimization(
|
|
DK_OptimizationRemarkAnalysis, DS_Remark, PassName, RemarkName, *Func,
|
|
Func->getSubprogram(), getFirstFunctionBlock(Func)) {}
|
|
|
|
bool OptimizationRemarkAnalysis::isEnabled() const {
|
|
const Function &Fn = getFunction();
|
|
LLVMContext &Ctx = Fn.getContext();
|
|
return Ctx.getDiagHandlerPtr()->isAnalysisRemarkEnabled(getPassName()) ||
|
|
shouldAlwaysPrint();
|
|
}
|
|
|
|
void DiagnosticInfoMIRParser::print(DiagnosticPrinter &DP) const {
|
|
DP << Diagnostic;
|
|
}
|
|
|
|
void DiagnosticInfoSrcMgr::print(DiagnosticPrinter &DP) const {
|
|
DP << Diagnostic;
|
|
}
|
|
|
|
DiagnosticInfoOptimizationFailure::DiagnosticInfoOptimizationFailure(
|
|
const char *PassName, StringRef RemarkName, const DiagnosticLocation &Loc,
|
|
const BasicBlock *CodeRegion)
|
|
: DiagnosticInfoIROptimization(DK_OptimizationFailure, DS_Warning, PassName,
|
|
RemarkName, *CodeRegion->getParent(), Loc,
|
|
CodeRegion) {}
|
|
|
|
bool DiagnosticInfoOptimizationFailure::isEnabled() const {
|
|
// Only print warnings.
|
|
return getSeverity() == DS_Warning;
|
|
}
|
|
|
|
void DiagnosticInfoUnsupported::print(DiagnosticPrinter &DP) const {
|
|
std::string Str;
|
|
raw_string_ostream OS(Str);
|
|
|
|
OS << getLocationStr() << ": in function " << getFunction().getName() << ' '
|
|
<< *getFunction().getFunctionType() << ": " << Msg << '\n';
|
|
OS.flush();
|
|
DP << Str;
|
|
}
|
|
|
|
void DiagnosticInfoInstrumentation::print(DiagnosticPrinter &DP) const {
|
|
DP << Msg;
|
|
}
|
|
|
|
void DiagnosticInfoISelFallback::print(DiagnosticPrinter &DP) const {
|
|
DP << "Instruction selection used fallback path for " << getFunction();
|
|
}
|
|
|
|
void DiagnosticInfoOptimizationBase::insert(StringRef S) {
|
|
Args.emplace_back(S);
|
|
}
|
|
|
|
void DiagnosticInfoOptimizationBase::insert(Argument A) {
|
|
Args.push_back(std::move(A));
|
|
}
|
|
|
|
void DiagnosticInfoOptimizationBase::insert(setIsVerbose V) {
|
|
IsVerbose = true;
|
|
}
|
|
|
|
void DiagnosticInfoOptimizationBase::insert(setExtraArgs EA) {
|
|
FirstExtraArgIndex = Args.size();
|
|
}
|
|
|
|
std::string DiagnosticInfoOptimizationBase::getMsg() const {
|
|
std::string Str;
|
|
raw_string_ostream OS(Str);
|
|
for (const DiagnosticInfoOptimizationBase::Argument &Arg :
|
|
make_range(Args.begin(), FirstExtraArgIndex == -1
|
|
? Args.end()
|
|
: Args.begin() + FirstExtraArgIndex))
|
|
OS << Arg.Val;
|
|
return Str;
|
|
}
|
|
|
|
DiagnosticInfoMisExpect::DiagnosticInfoMisExpect(const Instruction *Inst,
|
|
const Twine &Msg)
|
|
: DiagnosticInfoWithLocationBase(DK_MisExpect, DS_Warning,
|
|
*Inst->getParent()->getParent(),
|
|
Inst->getDebugLoc()),
|
|
Msg(Msg) {}
|
|
|
|
void DiagnosticInfoMisExpect::print(DiagnosticPrinter &DP) const {
|
|
DP << getLocationStr() << ": " << getMsg();
|
|
}
|
|
|
|
void OptimizationRemarkAnalysisFPCommute::anchor() {}
|
|
void OptimizationRemarkAnalysisAliasing::anchor() {}
|
|
|
|
void llvm::diagnoseDontCall(const CallInst &CI) {
|
|
const auto *F =
|
|
dyn_cast<Function>(CI.getCalledOperand()->stripPointerCasts());
|
|
|
|
if (!F)
|
|
return;
|
|
|
|
for (int i = 0; i != 2; ++i) {
|
|
auto AttrName = i == 0 ? "dontcall-error" : "dontcall-warn";
|
|
auto Sev = i == 0 ? DS_Error : DS_Warning;
|
|
|
|
if (F->hasFnAttribute(AttrName)) {
|
|
uint64_t LocCookie = 0;
|
|
auto A = F->getFnAttribute(AttrName);
|
|
if (MDNode *MD = CI.getMetadata("srcloc"))
|
|
LocCookie =
|
|
mdconst::extract<ConstantInt>(MD->getOperand(0))->getZExtValue();
|
|
DiagnosticInfoDontCall D(F->getName(), A.getValueAsString(), Sev,
|
|
LocCookie);
|
|
F->getContext().diagnose(D);
|
|
}
|
|
}
|
|
}
|
|
|
|
void DiagnosticInfoDontCall::print(DiagnosticPrinter &DP) const {
|
|
DP << "call to " << demangle(getFunctionName()) << " marked \"dontcall-";
|
|
if (getSeverity() == DiagnosticSeverity::DS_Error)
|
|
DP << "error\"";
|
|
else
|
|
DP << "warn\"";
|
|
if (!getNote().empty())
|
|
DP << ": " << getNote();
|
|
}
|