Author: Corentin Jabot
Date: 2022-03-30T19:18:53+02:00
New Revision: 0550601d180111a1c48baf170c2e7e9c7fac28c2

URL: 
https://github.com/llvm/llvm-project/commit/0550601d180111a1c48baf170c2e7e9c7fac28c2
DIFF: 
https://github.com/llvm/llvm-project/commit/0550601d180111a1c48baf170c2e7e9c7fac28c2.diff

LOG: [Clang] Add a compatibiliy warning for non-literals in constexpr.

Reviewed By: aaron.ballman, hubert.reinterpretcast

Differential Revision: https://reviews.llvm.org/D122249

Added: 
    

Modified: 
    clang/include/clang/Basic/DiagnosticSemaKinds.td
    clang/lib/Sema/SemaDeclCXX.cpp
    clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3-2b.cpp
    clang/test/SemaCXX/constant-expression-cxx2b.cpp

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index d3055fed20828..a272cb741270f 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -2721,9 +2721,9 @@ def ext_constexpr_static_var : ExtWarn<
   "definition of a %select{static|thread_local}1 variable "
   "in a constexpr %select{function|constructor}0 "
   "is a C++2b extension">, InGroup<CXX2b>;
-def warn_cxx20_compat_constexpr_static_var : Warning<
-  "definition of a %select{static|thread_local}1 variable "
-  "in a constexpr %select{function|constructor}0 "
+def warn_cxx20_compat_constexpr_var : Warning<
+  "definition of a %select{static variable|thread_local variable|variable "
+  "of non-literal type}1 in a constexpr %select{function|constructor}0 "
   "is incompatible with C++ standards before C++2b">,
   InGroup<CXXPre2bCompat>, DefaultIgnore;
 def err_constexpr_local_var_non_literal_type : Error<

diff  --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 48fb642ad15e1..0f56e6024f332 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -1893,7 +1893,7 @@ static bool CheckConstexprDeclStmt(Sema &SemaRef, const 
FunctionDecl *Dcl,
           if (Kind == Sema::CheckConstexprKind::Diagnose) {
             SemaRef.Diag(VD->getLocation(),
                          SemaRef.getLangOpts().CPlusPlus2b
-                             ? diag::warn_cxx20_compat_constexpr_static_var
+                             ? diag::warn_cxx20_compat_constexpr_var
                              : diag::ext_constexpr_static_var)
                 << isa<CXXConstructorDecl>(Dcl)
                 << (VD->getTLSKind() == VarDecl::TLS_Dynamic);
@@ -1901,11 +1901,17 @@ static bool CheckConstexprDeclStmt(Sema &SemaRef, const 
FunctionDecl *Dcl,
             return false;
           }
         }
-        if (!SemaRef.LangOpts.CPlusPlus2b &&
-            CheckLiteralType(SemaRef, Kind, VD->getLocation(), VD->getType(),
-                             diag::err_constexpr_local_var_non_literal_type,
-                             isa<CXXConstructorDecl>(Dcl)))
+        if (SemaRef.LangOpts.CPlusPlus2b) {
+          CheckLiteralType(SemaRef, Kind, VD->getLocation(), VD->getType(),
+                           diag::warn_cxx20_compat_constexpr_var,
+                           isa<CXXConstructorDecl>(Dcl),
+                           /*variable of non-literal type*/ 2);
+        } else if (CheckLiteralType(
+                       SemaRef, Kind, VD->getLocation(), VD->getType(),
+                       diag::err_constexpr_local_var_non_literal_type,
+                       isa<CXXConstructorDecl>(Dcl))) {
           return false;
+        }
         if (!VD->getType()->isDependentType() &&
             !VD->hasInit() && !VD->isCXXForRangeDecl()) {
           if (Kind == Sema::CheckConstexprKind::Diagnose) {

diff  --git a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3-2b.cpp 
b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3-2b.cpp
index 671895b278bdf..3ba5cbba79ce2 100644
--- a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3-2b.cpp
+++ b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3-2b.cpp
@@ -25,17 +25,18 @@ constexpr void h() {
 label:; // expected-warning {{use of this statement in a constexpr function is 
incompatible with C++ standards before C++2b}}
 }
 
-struct NonLiteral {
+struct NonLiteral { // expected-note 2 {{'NonLiteral' is not literal}}
   NonLiteral() {}
 };
 
 constexpr void non_literal() { // expected-error {{constexpr function never 
produces a constant expression}}
-  NonLiteral n;                // expected-note {{non-literal type 
'NonLiteral' cannot be used in a constant expression}}
+  NonLiteral n;                // expected-note {{non-literal type 
'NonLiteral' cannot be used in a constant expression}} \
+                               // expected-warning {{definition of a variable 
of non-literal type in a constexpr function is incompatible with C++ standards 
before C++2b}}
 }
 
 constexpr void non_literal2(bool b) {
   if (!b)
-    NonLiteral n;
+    NonLiteral n; // expected-warning {{definition of a variable of 
non-literal type in a constexpr function is incompatible with C++ standards 
before C++2b}}
 }
 
 constexpr int c_thread_local(int n) {

diff  --git a/clang/test/SemaCXX/constant-expression-cxx2b.cpp 
b/clang/test/SemaCXX/constant-expression-cxx2b.cpp
index 0657a35947ade..5a5fe6c1b7ab2 100644
--- a/clang/test/SemaCXX/constant-expression-cxx2b.cpp
+++ b/clang/test/SemaCXX/constant-expression-cxx2b.cpp
@@ -1,7 +1,8 @@
 // RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify=expected,cxx2a %s 
-fcxx-exceptions -triple=x86_64-linux-gnu -Wno-c++2b-extensions
 // RUN: %clang_cc1 -std=c++2b -fsyntax-only -verify=expected,cxx2b %s 
-fcxx-exceptions -triple=x86_64-linux-gnu -Wpre-c++2b-compat
 
-struct NonLiteral { // cxx2a-note {{'NonLiteral' is not literal}}
+struct NonLiteral { // cxx2a-note {{'NonLiteral' is not literal}} \
+                    // cxx2b-note 2{{'NonLiteral' is not literal}}
   NonLiteral() {}
 };
 
@@ -96,7 +97,7 @@ constexpr int thread_local_constexpr() { // expected-error 
{{constexpr function
 constexpr int non_literal(bool b) {
   if (!b)
     return 0;
-  NonLiteral n;
+  NonLiteral n; // cxx2b-warning {{definition of a variable of non-literal 
type in a constexpr function is incompatible with C++ standards before C++2b}}
 }
 
 constexpr int non_literal_1 = non_literal(false);
@@ -164,7 +165,8 @@ int test_in_lambdas() {
   auto non_literal = [](bool b) constexpr {
     if (!b)
       NonLiteral n; // cxx2b-note {{non-literal type 'NonLiteral' cannot be 
used in a constant expression}} \
-                    // cxx2a-error {{variable of non-literal type 'NonLiteral' 
cannot be defined in a constexpr function before C++2b}}
+                    // cxx2a-error {{variable of non-literal type 'NonLiteral' 
cannot be defined in a constexpr function before C++2b}} \
+                    // cxx2b-warning {{definition of a variable of non-literal 
type in a constexpr function is incompatible with C++ standards before C++2b}}
     return 0;
   };
 
@@ -227,7 +229,7 @@ int test_lambdas_implicitly_constexpr() {
 }
 
 template <typename T>
-constexpr auto dependent_var_def_lambda(void) {
+constexpr auto dependent_var_def_lambda() {
   return [](bool b) { // cxx2a-note {{declared here}}
     if (!b)
       T t;
@@ -237,4 +239,4 @@ constexpr auto dependent_var_def_lambda(void) {
 
 constexpr auto non_literal_valid_in_cxx2b = 
dependent_var_def_lambda<NonLiteral>()(true); // \
     // cxx2a-error {{constexpr variable 'non_literal_valid_in_cxx2b' must be 
initialized by a constant expression}} \
-    // cxx2a-note  {{non-constexpr function}}
+    // cxx2a-note {{non-constexpr function}}


        
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to