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 @@ -5227,7 +5227,7 @@ return ESR_Succeeded; } - Info.FFDiag(S->getBeginLoc()); + Info.FFDiag(S->getBeginLoc()) << S->getSourceRange(); return ESR_Failed; case Stmt::NullStmtClass: @@ -7454,7 +7454,7 @@ /// Report an evaluation error. This should only be called when an error is /// first discovered. When propagating an error, just return false. bool Error(const Expr *E, diag::kind D) { - Info.FFDiag(E, D); + Info.FFDiag(E, D) << E->getSourceRange(); return false; } bool Error(const Expr *E) { diff --git a/clang/lib/AST/Interp/Interp.h b/clang/lib/AST/Interp/Interp.h --- a/clang/lib/AST/Interp/Interp.h +++ b/clang/lib/AST/Interp/Interp.h @@ -1738,7 +1738,8 @@ /// op is not valid in a constant context. inline bool Invalid(InterpState &S, CodePtr OpPC) { const SourceLocation &Loc = S.Current->getLocation(OpPC); - S.FFDiag(Loc, diag::note_invalid_subexpr_in_const_expr); + S.FFDiag(Loc, diag::note_invalid_subexpr_in_const_expr) + << S.Current->getRange(OpPC); return false; } 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 @@ -118,6 +118,7 @@ virtual SourceInfo getSource(CodePtr PC) const; const Expr *getExpr(CodePtr PC) const; SourceLocation getLocation(CodePtr PC) const; + SourceRange getRange(CodePtr PC) const; unsigned getDepth() const { return Depth; } 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 @@ -229,3 +229,6 @@ return S.getLocation(Func, PC); } +SourceRange InterpFrame::getRange(CodePtr PC) const { + return S.getRange(Func, PC); +} diff --git a/clang/lib/AST/Interp/Source.h b/clang/lib/AST/Interp/Source.h --- a/clang/lib/AST/Interp/Source.h +++ b/clang/lib/AST/Interp/Source.h @@ -71,6 +71,7 @@ SourceInfo(const Decl *D) : Source(D) {} SourceLocation getLoc() const; + SourceRange getRange() const; const Stmt *asStmt() const { return Source.dyn_cast(); } const Decl *asDecl() const { return Source.dyn_cast(); } @@ -96,6 +97,7 @@ const Expr *getExpr(const Function *F, CodePtr PC) const; /// Returns the location from which an opcode originates. SourceLocation getLocation(const Function *F, CodePtr PC) const; + SourceRange getRange(const Function *F, CodePtr PC) const; }; } // namespace interp diff --git a/clang/lib/AST/Interp/Source.cpp b/clang/lib/AST/Interp/Source.cpp --- a/clang/lib/AST/Interp/Source.cpp +++ b/clang/lib/AST/Interp/Source.cpp @@ -22,6 +22,16 @@ return SourceLocation(); } +SourceRange SourceInfo::getRange() const { + if (const Expr *E = asExpr()) + return E->getSourceRange(); + if (const Stmt *S = asStmt()) + return S->getSourceRange(); + if (const Decl *D = asDecl()) + return D->getSourceRange(); + return SourceRange(); +} + const Expr *SourceInfo::asExpr() const { if (auto *S = Source.dyn_cast()) return dyn_cast(S); @@ -37,3 +47,7 @@ SourceLocation SourceMapper::getLocation(const Function *F, CodePtr PC) const { return getSource(F, PC).getLoc(); } + +SourceRange SourceMapper::getRange(const Function *F, CodePtr PC) const { + return getSource(F, PC).getRange(); +} diff --git a/clang/test/Misc/constexpr-source-ranges.cpp b/clang/test/Misc/constexpr-source-ranges.cpp new file mode 100644 --- /dev/null +++ b/clang/test/Misc/constexpr-source-ranges.cpp @@ -0,0 +1,9 @@ +// RUN: not %clang_cc1 -fsyntax-only -fdiagnostics-print-source-range-info -fcxx-exceptions %s 2>&1 | FileCheck %s +// RUN: not %clang_cc1 -fsyntax-only -fexperimental-new-constant-interpreter -fdiagnostics-print-source-range-info -fcxx-exceptions %s 2>&1 | FileCheck %s + +constexpr int f() { + throw 1; + return 0; +} + +// CHECK: constexpr-source-ranges.cpp:5:3:{5:3-5:10}