Skip to content

Commit

Permalink
[clang][ExprConst] Use call source range for 'in call to' diags
Browse files Browse the repository at this point in the history
Differential Revision: https://reviews.llvm.org/D156604
  • Loading branch information
tbaederr committed Aug 16, 2023
1 parent 878950b commit 871ee94
Show file tree
Hide file tree
Showing 6 changed files with 50 additions and 35 deletions.
56 changes: 30 additions & 26 deletions clang/lib/AST/ExprConstant.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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.
Expand All @@ -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;
Expand All @@ -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;
}

Expand All @@ -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;
}

Expand All @@ -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;
}

Expand All @@ -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.
Expand All @@ -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;
}

Expand Down Expand Up @@ -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;
}
Expand All @@ -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;
}
Expand All @@ -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) {
Expand Down Expand Up @@ -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");
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/AST/Interp/Frame.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ class Frame {
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;
Expand Down
6 changes: 3 additions & 3 deletions clang/lib/AST/Interp/InterpFrame.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/AST/Interp/InterpFrame.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ class InterpFrame final : public Frame {
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;
Expand Down
10 changes: 6 additions & 4 deletions clang/lib/AST/Interp/State.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -146,14 +146,16 @@ 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;
}

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;
}
}
9 changes: 9 additions & 0 deletions clang/test/Misc/constexpr-source-ranges.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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}

0 comments on commit 871ee94

Please sign in to comment.