diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -551,8 +551,8 @@ /// 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 @@ llvm::DenseMap 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ } 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 @@ 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 @@ // (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 @@ 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 @@ 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 @@ 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 @@ 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"); diff --git a/clang/lib/AST/Interp/Frame.h b/clang/lib/AST/Interp/Frame.h --- a/clang/lib/AST/Interp/Frame.h +++ b/clang/lib/AST/Interp/Frame.h @@ -33,7 +33,7 @@ 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; diff --git a/clang/lib/AST/Interp/InterpFrame.h b/clang/lib/AST/Interp/InterpFrame.h --- a/clang/lib/AST/Interp/InterpFrame.h +++ b/clang/lib/AST/Interp/InterpFrame.h @@ -56,7 +56,7 @@ 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; diff --git a/clang/lib/AST/Interp/InterpFrame.cpp b/clang/lib/AST/Interp/InterpFrame.cpp --- a/clang/lib/AST/Interp/InterpFrame.cpp +++ b/clang/lib/AST/Interp/InterpFrame.cpp @@ -176,10 +176,10 @@ 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 { diff --git a/clang/lib/AST/Interp/State.cpp b/clang/lib/AST/Interp/State.cpp --- a/clang/lib/AST/Interp/State.cpp +++ b/clang/lib/AST/Interp/State.cpp @@ -129,13 +129,13 @@ 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 @@ if (const auto *CD = dyn_cast_if_present(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 @@ 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; } } diff --git a/clang/test/Misc/constexpr-source-ranges.cpp b/clang/test/Misc/constexpr-source-ranges.cpp --- a/clang/test/Misc/constexpr-source-ranges.cpp +++ b/clang/test/Misc/constexpr-source-ranges.cpp @@ -25,3 +25,12 @@ /// 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}