[clang] 0fd3d37 - Improve diagnostic for an expression that's not constant because it uses

Richard Smith via cfe-commits cfe-commits at lists.llvm.org
Mon Aug 10 17:03:30 PDT 2020


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 at -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}}
+}


        


More information about the cfe-commits mailing list