[clang][ExprConst] Use call source range for 'in call to' diags

Differential Revision: https://reviews.llvm.org/D156604
This commit is contained in:
Timm Bäder
2023-08-01 11:39:06 +02:00
parent 878950b82c
commit 871ee94141
6 changed files with 50 additions and 35 deletions

View File

@@ -551,8 +551,8 @@ namespace {
/// Temporaries - Temporary lvalues materialized within this stack frame.
MapTy Temporaries;
/// CallLoc - The location of the call expression for this call.
SourceLocation CallLoc;
/// CallRange - The source range of the call expression for this call.
SourceRange CallRange;
/// Index - The call index of this call.
unsigned Index;
@@ -586,7 +586,7 @@ namespace {
llvm::DenseMap<const ValueDecl *, FieldDecl *> LambdaCaptureFields;
FieldDecl *LambdaThisCaptureField = nullptr;
CallStackFrame(EvalInfo &Info, SourceLocation CallLoc,
CallStackFrame(EvalInfo &Info, SourceRange CallRange,
const FunctionDecl *Callee, const LValue *This,
const Expr *CallExpr, CallRef Arguments);
~CallStackFrame();
@@ -630,7 +630,7 @@ namespace {
void describe(llvm::raw_ostream &OS) const override;
Frame *getCaller() const override { return Caller; }
SourceLocation getCallLocation() const override { return CallLoc; }
SourceRange getCallRange() const override { return CallRange; }
const FunctionDecl *getCallee() const override { return Callee; }
bool isStdFunction() const {
@@ -1468,11 +1468,11 @@ void SubobjectDesignator::diagnosePointerArithmetic(EvalInfo &Info,
setInvalid();
}
CallStackFrame::CallStackFrame(EvalInfo &Info, SourceLocation CallLoc,
CallStackFrame::CallStackFrame(EvalInfo &Info, SourceRange CallRange,
const FunctionDecl *Callee, const LValue *This,
const Expr *CallExpr, CallRef Call)
: Info(Info), Caller(Info.CurrentCall), Callee(Callee), This(This),
CallExpr(CallExpr), Arguments(Call), CallLoc(CallLoc),
CallExpr(CallExpr), Arguments(Call), CallRange(CallRange),
Index(Info.NextCallIndex++) {
Info.CurrentCall = this;
++Info.CallStackDepth;
@@ -6245,7 +6245,7 @@ static bool HandleFunctionCall(SourceLocation CallLoc,
if (!Info.CheckCallLimit(CallLoc))
return false;
CallStackFrame Frame(Info, CallLoc, Callee, This, E, Call);
CallStackFrame Frame(Info, E->getSourceRange(), Callee, This, E, Call);
// For a trivial copy or move assignment, perform an APValue copy. This is
// essential for unions, where the operations performed by the assignment
@@ -6310,7 +6310,7 @@ static bool HandleConstructorCall(const Expr *E, const LValue &This,
Info,
ObjectUnderConstruction{This.getLValueBase(), This.Designator.Entries},
RD->getNumBases());
CallStackFrame Frame(Info, CallLoc, Definition, &This, E, Call);
CallStackFrame Frame(Info, E->getSourceRange(), Definition, &This, E, Call);
// FIXME: Creating an APValue just to hold a nonexistent return value is
// wasteful.
@@ -6518,7 +6518,7 @@ static bool HandleConstructorCall(const Expr *E, const LValue &This,
CallScope.destroy();
}
static bool HandleDestructionImpl(EvalInfo &Info, SourceLocation CallLoc,
static bool HandleDestructionImpl(EvalInfo &Info, SourceRange CallRange,
const LValue &This, APValue &Value,
QualType T) {
// Objects can only be destroyed while they're within their lifetimes.
@@ -6528,21 +6528,22 @@ static bool HandleDestructionImpl(EvalInfo &Info, SourceLocation CallLoc,
if (Value.isAbsent() && !T->isNullPtrType()) {
APValue Printable;
This.moveInto(Printable);
Info.FFDiag(CallLoc, diag::note_constexpr_destroy_out_of_lifetime)
<< Printable.getAsString(Info.Ctx, Info.Ctx.getLValueReferenceType(T));
Info.FFDiag(CallRange.getBegin(),
diag::note_constexpr_destroy_out_of_lifetime)
<< Printable.getAsString(Info.Ctx, Info.Ctx.getLValueReferenceType(T));
return false;
}
// Invent an expression for location purposes.
// FIXME: We shouldn't need to do this.
OpaqueValueExpr LocE(CallLoc, Info.Ctx.IntTy, VK_PRValue);
OpaqueValueExpr LocE(CallRange.getBegin(), Info.Ctx.IntTy, VK_PRValue);
// For arrays, destroy elements right-to-left.
if (const ConstantArrayType *CAT = Info.Ctx.getAsConstantArrayType(T)) {
uint64_t Size = CAT->getSize().getZExtValue();
QualType ElemT = CAT->getElementType();
if (!CheckArraySize(Info, CAT, CallLoc))
if (!CheckArraySize(Info, CAT, CallRange.getBegin()))
return false;
LValue ElemLV = This;
@@ -6559,7 +6560,7 @@ static bool HandleDestructionImpl(EvalInfo &Info, SourceLocation CallLoc,
for (; Size != 0; --Size) {
APValue &Elem = Value.getArrayInitializedElt(Size - 1);
if (!HandleLValueArrayAdjustment(Info, &LocE, ElemLV, ElemT, -1) ||
!HandleDestructionImpl(Info, CallLoc, ElemLV, Elem, ElemT))
!HandleDestructionImpl(Info, CallRange, ElemLV, Elem, ElemT))
return false;
}
@@ -6571,7 +6572,9 @@ static bool HandleDestructionImpl(EvalInfo &Info, SourceLocation CallLoc,
const CXXRecordDecl *RD = T->getAsCXXRecordDecl();
if (!RD) {
if (T.isDestructedType()) {
Info.FFDiag(CallLoc, diag::note_constexpr_unsupported_destruction) << T;
Info.FFDiag(CallRange.getBegin(),
diag::note_constexpr_unsupported_destruction)
<< T;
return false;
}
@@ -6580,13 +6583,13 @@ static bool HandleDestructionImpl(EvalInfo &Info, SourceLocation CallLoc,
}
if (RD->getNumVBases()) {
Info.FFDiag(CallLoc, diag::note_constexpr_virtual_base) << RD;
Info.FFDiag(CallRange.getBegin(), diag::note_constexpr_virtual_base) << RD;
return false;
}
const CXXDestructorDecl *DD = RD->getDestructor();
if (!DD && !RD->hasTrivialDestructor()) {
Info.FFDiag(CallLoc);
Info.FFDiag(CallRange.getBegin());
return false;
}
@@ -6605,16 +6608,16 @@ static bool HandleDestructionImpl(EvalInfo &Info, SourceLocation CallLoc,
return true;
}
if (!Info.CheckCallLimit(CallLoc))
if (!Info.CheckCallLimit(CallRange.getBegin()))
return false;
const FunctionDecl *Definition = nullptr;
const Stmt *Body = DD->getBody(Definition);
if (!CheckConstexprFunction(Info, CallLoc, DD, Definition, Body))
if (!CheckConstexprFunction(Info, CallRange.getBegin(), DD, Definition, Body))
return false;
CallStackFrame Frame(Info, CallLoc, Definition, &This, /*CallExpr=*/nullptr,
CallStackFrame Frame(Info, CallRange, Definition, &This, /*CallExpr=*/nullptr,
CallRef());
// We're now in the period of destruction of this object.
@@ -6629,7 +6632,7 @@ static bool HandleDestructionImpl(EvalInfo &Info, SourceLocation CallLoc,
// (Note that formally the lifetime ends when the period of destruction
// begins, even though certain uses of the object remain valid until the
// period of destruction ends.)
Info.FFDiag(CallLoc, diag::note_constexpr_double_destroy);
Info.FFDiag(CallRange.getBegin(), diag::note_constexpr_double_destroy);
return false;
}
@@ -6658,7 +6661,7 @@ static bool HandleDestructionImpl(EvalInfo &Info, SourceLocation CallLoc,
return false;
APValue *SubobjectValue = &Value.getStructField(FD->getFieldIndex());
if (!HandleDestructionImpl(Info, CallLoc, Subobject, *SubobjectValue,
if (!HandleDestructionImpl(Info, CallRange, Subobject, *SubobjectValue,
FD->getType()))
return false;
}
@@ -6677,7 +6680,7 @@ static bool HandleDestructionImpl(EvalInfo &Info, SourceLocation CallLoc,
return false;
APValue *SubobjectValue = &Value.getStructBase(BasesLeft);
if (!HandleDestructionImpl(Info, CallLoc, Subobject, *SubobjectValue,
if (!HandleDestructionImpl(Info, CallRange, Subobject, *SubobjectValue,
BaseType))
return false;
}
@@ -6698,7 +6701,7 @@ struct DestroyObjectHandler {
typedef bool result_type;
bool failed() { return false; }
bool found(APValue &Subobj, QualType SubobjType) {
return HandleDestructionImpl(Info, E->getExprLoc(), This, Subobj,
return HandleDestructionImpl(Info, E->getSourceRange(), This, Subobj,
SubobjType);
}
bool found(APSInt &Value, QualType SubobjType) {
@@ -12167,8 +12170,9 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E,
Callee->getIdentifier()->isStr("is_constant_evaluated")))) {
// FIXME: Find a better way to avoid duplicated diagnostics.
if (Info.EvalStatus.Diag)
Info.report((Info.CallStackDepth == 1) ? E->getExprLoc()
: Info.CurrentCall->CallLoc,
Info.report((Info.CallStackDepth == 1)
? E->getExprLoc()
: Info.CurrentCall->getCallRange().getBegin(),
diag::warn_is_constant_evaluated_always_true_constexpr)
<< (Info.CallStackDepth == 1 ? "__builtin_is_constant_evaluated"
: "std::is_constant_evaluated");

View File

@@ -33,7 +33,7 @@ public:
virtual Frame *getCaller() const = 0;
/// Returns the location of the call site.
virtual SourceLocation getCallLocation() const = 0;
virtual SourceRange getCallRange() const = 0;
/// Returns the called function's declaration.
virtual const FunctionDecl *getCallee() const = 0;

View File

@@ -176,10 +176,10 @@ Frame *InterpFrame::getCaller() const {
return S.getSplitFrame();
}
SourceLocation InterpFrame::getCallLocation() const {
SourceRange InterpFrame::getCallRange() const {
if (!Caller->Func)
return S.getLocation(nullptr, {});
return S.getLocation(Caller->Func, RetPC - sizeof(uintptr_t));
return S.getRange(nullptr, {});
return S.getRange(Caller->Func, RetPC - sizeof(uintptr_t));
}
const FunctionDecl *InterpFrame::getCallee() const {

View File

@@ -56,7 +56,7 @@ public:
Frame *getCaller() const override;
/// Returns the location of the call to the frame.
SourceLocation getCallLocation() const override;
SourceRange getCallRange() const override;
/// Returns the caller.
const FunctionDecl *getCallee() const override;

View File

@@ -129,13 +129,13 @@ void State::addCallStack(unsigned Limit) {
const Frame *Top = getCurrentFrame();
const Frame *Bottom = getBottomFrame();
for (const Frame *F = Top; F != Bottom; F = F->getCaller(), ++CallIdx) {
SourceLocation CallLocation = F->getCallLocation();
SourceRange CallRange = F->getCallRange();
// Skip this call?
if (CallIdx >= SkipStart && CallIdx < SkipEnd) {
if (CallIdx == SkipStart) {
// Note that we're skipping calls.
addDiag(CallLocation, diag::note_constexpr_calls_suppressed)
addDiag(CallRange.getBegin(), diag::note_constexpr_calls_suppressed)
<< unsigned(ActiveCalls - Limit);
}
continue;
@@ -146,7 +146,8 @@ void State::addCallStack(unsigned Limit) {
if (const auto *CD =
dyn_cast_if_present<CXXConstructorDecl>(F->getCallee());
CD && CD->isInheritingConstructor()) {
addDiag(CallLocation, diag::note_constexpr_inherited_ctor_call_here)
addDiag(CallRange.getBegin(),
diag::note_constexpr_inherited_ctor_call_here)
<< CD->getParent();
continue;
}
@@ -154,6 +155,7 @@ void State::addCallStack(unsigned Limit) {
SmallString<128> Buffer;
llvm::raw_svector_ostream Out(Buffer);
F->describe(Out);
addDiag(CallLocation, diag::note_constexpr_call_here) << Out.str();
addDiag(CallRange.getBegin(), diag::note_constexpr_call_here)
<< Out.str() << CallRange;
}
}

View File

@@ -25,3 +25,12 @@ static_assert(divByZero() == 0, "");
/// evaluating the static_assert above.
// CHECK: constexpr-source-ranges.cpp:23:15:{23:15-23:31}
// CHECK: constexpr-source-ranges.cpp:21:12:{21:14-21:20}
constexpr int div(bool a, bool b) {
return 1 / (int)b;
}
constexpr int ints(int a, int b, int c, int d) {
return 1;
}
static_assert(ints(1, div(true, false), 2, div(false, true)) == 1, "");
// CHECK: constexpr-source-ranges.cpp:35:23:{35:23-35:39}