[clang] 0550601 - [Clang] Add a compatibiliy warning for non-literals in constexpr.
Corentin Jabot via cfe-commits
cfe-commits at lists.llvm.org
Wed Mar 30 10:18:58 PDT 2022
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}}
More information about the cfe-commits
mailing list