Author: Richard Smith Date: 2020-08-10T17:03:19-07:00 New Revision: 0fd3d379e26da3cb02b6d960198e2efbc5190650
URL: https://github.com/llvm/llvm-project/commit/0fd3d379e26da3cb02b6d960198e2efbc5190650 DIFF: https://github.com/llvm/llvm-project/commit/0fd3d379e26da3cb02b6d960198e2efbc5190650.diff LOG: Improve diagnostic for an expression that's not constant because it uses the address of a constexpr local variable. Suggest adding 'static' to give the constexpr local variable a constant address. Added: Modified: clang/include/clang/Basic/DiagnosticASTKinds.td clang/lib/AST/ExprConstant.cpp clang/test/SemaCXX/builtins.cpp clang/test/SemaCXX/constant-expression-cxx11.cpp Removed: ################################################################################ diff --git a/clang/include/clang/Basic/DiagnosticASTKinds.td b/clang/include/clang/Basic/DiagnosticASTKinds.td index 10bedaaf7aba..9be75f375119 100644 --- a/clang/include/clang/Basic/DiagnosticASTKinds.td +++ b/clang/include/clang/Basic/DiagnosticASTKinds.td @@ -54,6 +54,9 @@ def note_constexpr_nonliteral : Note< def note_constexpr_non_global : Note< "%select{pointer|reference}0 to %select{|subobject of }1" "%select{temporary|%3}2 is not a constant expression">; +def note_constexpr_not_static : Note< + "address of non-static constexpr variable %0 may diff er on each invocation " + "of the enclosing function; add 'static' to give it a constant address">; def note_constexpr_dynamic_alloc : Note< "%select{pointer|reference}0 to %select{|subobject of }1" "heap-allocated object is not a constant expression">; diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 11ba8db24355..4238adb5a947 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -2055,7 +2055,20 @@ static bool CheckLValueConstantExpression(EvalInfo &Info, SourceLocation Loc, Info.FFDiag(Loc, diag::note_constexpr_non_global, 1) << IsReferenceType << !Designator.Entries.empty() << !!VD << VD; - NoteLValueLocation(Info, Base); + + auto *VarD = dyn_cast_or_null<VarDecl>(VD); + if (VarD && VarD->isConstexpr()) { + // Non-static local constexpr variables have unintuitive semantics: + // constexpr int a = 1; + // constexpr const int *p = &a; + // ... is invalid because the address of 'a' is not constant. Suggest + // adding a 'static' in this case. + Info.Note(VarD->getLocation(), diag::note_constexpr_not_static) + << VarD + << FixItHint::CreateInsertion(VarD->getBeginLoc(), "static "); + } else { + NoteLValueLocation(Info, Base); + } } else { Info.FFDiag(Loc); } diff --git a/clang/test/SemaCXX/builtins.cpp b/clang/test/SemaCXX/builtins.cpp index 80f75c8232c2..8869b6bef04c 100644 --- a/clang/test/SemaCXX/builtins.cpp +++ b/clang/test/SemaCXX/builtins.cpp @@ -113,7 +113,7 @@ static_assert(&const_int == const_ptr, ""); static_assert(const_ptr != test_constexpr_launder(&const_int2), ""); void test_non_constexpr() { - constexpr int i = 42; // expected-note {{declared here}} + constexpr int i = 42; // expected-note {{address of non-static constexpr variable 'i' may diff er on each invocation}} constexpr const int *ip = __builtin_launder(&i); // expected-error {{constexpr variable 'ip' must be initialized by a constant expression}} // expected-note@-1 {{pointer to 'i' is not a constant expression}} } diff --git a/clang/test/SemaCXX/constant-expression-cxx11.cpp b/clang/test/SemaCXX/constant-expression-cxx11.cpp index 14d36543cb20..c3529fc68266 100644 --- a/clang/test/SemaCXX/constant-expression-cxx11.cpp +++ b/clang/test/SemaCXX/constant-expression-cxx11.cpp @@ -2343,3 +2343,8 @@ namespace flexible_array { // constant-evaluate it properly. constexpr A c = {1, 2, 3}; // expected-error {{initialization of flexible array member}} } + +void local_constexpr_var() { + constexpr int a = 0; // expected-note {{address of non-static constexpr variable 'a' may diff er on each invocation of the enclosing function; add 'static' to give it a constant address}} + constexpr const int *p = &a; // expected-error {{constant expression}} expected-note {{pointer to 'a' is not a constant expression}} +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits