diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -2721,9 +2721,9 @@ "definition of a %select{static|thread_local}1 variable " "in a constexpr %select{function|constructor}0 " "is a C++2b extension">, InGroup; -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, DefaultIgnore; def err_constexpr_local_var_non_literal_type : Error< diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -1893,7 +1893,7 @@ 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(Dcl) << (VD->getTLSKind() == VarDecl::TLS_Dynamic); @@ -1901,10 +1901,15 @@ return false; } } - if (!SemaRef.LangOpts.CPlusPlus2b && - CheckLiteralType(SemaRef, Kind, VD->getLocation(), VD->getType(), - diag::err_constexpr_local_var_non_literal_type, - isa(Dcl))) + if (SemaRef.LangOpts.CPlusPlus2b) { + if (!VD->getType()->isLiteralType(SemaRef.Context)) + SemaRef.Diag(VD->getLocation(), + diag::warn_cxx20_compat_constexpr_var) + << isa(Dcl) << 2; + } else if (CheckLiteralType( + SemaRef, Kind, VD->getLocation(), VD->getType(), + diag::err_constexpr_local_var_non_literal_type, + isa(Dcl))) return false; if (!VD->getType()->isDependentType() && !VD->hasInit() && !VD->isCXXForRangeDecl()) { 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 --- 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 @@ -30,12 +30,13 @@ }; 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 --- a/clang/test/SemaCXX/constant-expression-cxx2b.cpp +++ b/clang/test/SemaCXX/constant-expression-cxx2b.cpp @@ -96,7 +96,7 @@ 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 +164,8 @@ 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; }; @@ -214,7 +215,8 @@ auto non_literal = [](bool b) { // cxx2a-note 2{{declared here}} if (b) - NonLiteral n; // cxx2b-note {{non-literal type 'NonLiteral' cannot be used in a constant expression}} + NonLiteral n; // cxx2b-note {{non-literal type 'NonLiteral' cannot be used in a constant expression}} \ + // cxx2b-warning {{definition of a variable of non-literal type in a constexpr function is incompatible with C++ standards before C++2b}} return 0; }; @@ -230,11 +232,12 @@ constexpr auto dependent_var_def_lambda(void) { return [](bool b) { // cxx2a-note {{declared here}} if (!b) - T t; + T t; // cxx2b-warning {{definition of a variable of non-literal type in a constexpr function is incompatible with C++ standards before C++2b}} return 0; }; } constexpr auto non_literal_valid_in_cxx2b = dependent_var_def_lambda()(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}} \ + // cxx2b-note {{in instantiation}}