[clang] [Clang][C++23] Implement P2448R2: Relaxing some constexpr restrictions (PR #77753)
Mariya Podchishchaeva via cfe-commits
cfe-commits at lists.llvm.org
Tue Mar 5 07:12:13 PST 2024
https://github.com/Fznamznon updated https://github.com/llvm/llvm-project/pull/77753
>From 699f47bba02012523e1862f9b15ce9de1d7511b5 Mon Sep 17 00:00:00 2001
From: "Podchishchaeva, Mariya" <mariya.podchishchaeva at intel.com>
Date: Wed, 18 Oct 2023 02:47:33 -0700
Subject: [PATCH 01/11] [Clang][C++23] Implement P2448R2: Relaxing some
constexpr restrictions
Per https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2448r2.html
function/constructor/destructor can be marked `constexpr` even though it never
produces a constant expression.
Non-literal types as return types and parameter types of functions
marked `constexpr` are also allowed.
Since this is not a DR, the diagnostic messages are still preserved for
C++ standards older than C++23.
---
clang/docs/ReleaseNotes.rst | 2 +
.../clang/Basic/DiagnosticSemaKinds.td | 42 +++--
clang/lib/Sema/SemaDeclCXX.cpp | 54 +++++--
clang/test/AST/Interp/cxx23.cpp | 24 +--
clang/test/AST/Interp/literals.cpp | 2 +-
clang/test/AST/Interp/shifts.cpp | 8 +-
clang/test/CXX/basic/basic.types/p10.cpp | 26 +--
.../dcl.dcl/dcl.spec/dcl.constexpr/dtor.cpp | 8 +-
.../dcl.dcl/dcl.spec/dcl.constexpr/p3-2b.cpp | 4 +-
.../CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3.cpp | 27 ++--
.../CXX/dcl.dcl/dcl.spec/dcl.constexpr/p4.cpp | 20 +--
.../CXX/dcl.dcl/dcl.spec/dcl.constexpr/p5.cpp | 6 +-
.../CXX/dcl.dcl/dcl.spec/dcl.constexpr/p6.cpp | 2 +-
.../dcl.fct.def/dcl.fct.def.default/p2.cpp | 6 +-
clang/test/CXX/drs/dr13xx.cpp | 22 +--
clang/test/CXX/drs/dr14xx.cpp | 6 +-
clang/test/CXX/drs/dr16xx.cpp | 12 +-
clang/test/CXX/drs/dr6xx.cpp | 24 +--
clang/test/CXX/expr/expr.const/p2-0x.cpp | 2 +-
clang/test/CXX/expr/expr.const/p5-26.cpp | 4 +-
clang/test/CXX/special/class.copy/p13-0x.cpp | 2 +-
clang/test/PCH/cxx11-constexpr.cpp | 2 +-
clang/test/SemaCXX/builtin_vectorelements.cpp | 2 +-
.../SemaCXX/constant-expression-cxx11.cpp | 29 ++--
.../SemaCXX/constant-expression-cxx14.cpp | 33 ++--
.../SemaCXX/constant-expression-cxx2b.cpp | 18 ++-
.../constexpr-function-recovery-crash.cpp | 4 +-
.../test/SemaCXX/cxx1z-constexpr-lambdas.cpp | 4 +-
.../test/SemaCXX/cxx23-invalid-constexpr.cpp | 152 ++++++++++++++++++
clang/test/SemaCXX/cxx2a-consteval.cpp | 4 +-
.../SemaCXX/deduced-return-type-cxx14.cpp | 8 +-
clang/test/SemaCXX/ms-constexpr-invalid.cpp | 6 +-
clang/test/SemaCXX/ms-constexpr.cpp | 2 +-
clang/test/SemaCXX/sizeless-1.cpp | 2 +-
.../addrspace-constructors.clcpp | 2 +-
clang/www/cxx_status.html | 9 +-
36 files changed, 378 insertions(+), 202 deletions(-)
create mode 100644 clang/test/SemaCXX/cxx23-invalid-constexpr.cpp
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index a18d36a16b1a9c..23342a6a7256d8 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -165,6 +165,8 @@ C++23 Feature Support
- Added a separate warning to warn the use of attributes on lambdas as a C++23 extension
in previous language versions: ``-Wc++23-lambda-attributes``.
+- Implemented `P2448R2: Relaxing some constexpr restrictions <https://wg21.link/P2448R2>`_.
+
C++2c Feature Support
^^^^^^^^^^^^^^^^^^^^^
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 1a79892e40030a..67409374f26dfa 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -2765,10 +2765,14 @@ def err_constexpr_tag : Error<
"cannot be marked %sub{select_constexpr_spec_kind}1">;
def err_constexpr_dtor : Error<
"destructor cannot be declared %sub{select_constexpr_spec_kind}0">;
-def err_constexpr_dtor_subobject : Error<
- "destructor cannot be declared %sub{select_constexpr_spec_kind}0 because "
+def ext_constexpr_dtor_subobject : ExtWarn<
+ "destructor cannot be declared %sub{select_constexpr_spec_kind}0 before C++23 because "
"%select{data member %2|base class %3}1 does not have a "
- "constexpr destructor">;
+ "constexpr destructor">, InGroup<CXX23>, DefaultError;
+def warn_cxx23_compat_constexpr_dtor_subobject : ExtWarn<
+ "%sub{select_constexpr_spec_kind}0 destructor is incompatible with C++ standards before C++23 because "
+ "%select{data member %2|base class %3}1 does not have a "
+ "constexpr destructor">, InGroup<CXXPre23Compat>, DefaultIgnore;
def note_constexpr_dtor_subobject : Note<
"%select{data member %1|base class %2}0 declared here">;
def err_constexpr_wrong_decl_kind : Error<
@@ -2800,11 +2804,14 @@ def note_non_literal_incomplete : Note<
def note_non_literal_virtual_base : Note<"%select{struct|interface|class}0 "
"with virtual base %plural{1:class|:classes}1 is not a literal type">;
def note_constexpr_virtual_base_here : Note<"virtual base class declared here">;
-def err_constexpr_non_literal_return : Error<
- "%select{constexpr|consteval}0 function's return type %1 is not a literal type">;
-def err_constexpr_non_literal_param : Error<
- "%select{constexpr|consteval}2 %select{function|constructor}1's %ordinal0 parameter type %3 is "
- "not a literal type">;
+def ext_constexpr_non_literal_return : ExtWarn<
+ "%select{constexpr|consteval}0 function with non-literal return type %1 is a C++23 extension">, InGroup<CXX23>, DefaultError;
+def warn_cxx23_compat_constexpr_non_literal_return : Warning<
+ "%select{constexpr|consteval}0 function with non-literal return type %1 is incompatible with C++ standards before C++23">, InGroup<CXXPre23Compat>, DefaultIgnore;
+def ext_constexpr_non_literal_param : ExtWarn<
+ "%select{constexpr|consteval}2 %select{function|constructor}1 with %ordinal0 non-literal parameter type %3 is a C++23 extension">, InGroup<CXX23>, DefaultError;
+def warn_cxx23_compat_constexpr_non_literal_param : Warning<
+ "%select{constexpr|consteval}2 %select{function|constructor}1 with %ordinal0 non-literal parameter type %3 is not compatible with C++ standards before C++23">, InGroup<CXXPre23Compat>, DefaultIgnore;
def err_constexpr_body_invalid_stmt : Error<
"statement not allowed in %select{constexpr|consteval}1 %select{function|constructor}0">;
def ext_constexpr_body_invalid_stmt : ExtWarn<
@@ -2865,8 +2872,11 @@ def warn_cxx17_compat_constexpr_local_var_no_init : Warning<
"is incompatible with C++ standards before C++20">,
InGroup<CXXPre20Compat>, DefaultIgnore;
def ext_constexpr_function_never_constant_expr : ExtWarn<
- "%select{constexpr|consteval}1 %select{function|constructor}0 never produces a "
- "constant expression">, InGroup<DiagGroup<"invalid-constexpr">>, DefaultError;
+ "%select{constexpr|consteval}1 %select{function|constructor}0 that never produces a "
+ "constant expression is a C++23 extension">, InGroup<DiagGroup<"invalid-constexpr">>, DefaultError;
+def warn_cxx23_compat_constexpr_function_never_constant_expr : Warning<
+ "%select{constexpr|consteval}1 %select{function|constructor}0 that never produces a "
+ "constant expression is incompatible with C++ standards before C++23">, InGroup<CXXPre23Compat>, DefaultIgnore;
def err_attr_cond_never_constant_expr : Error<
"%0 attribute expression never produces a constant expression">;
def err_diagnose_if_invalid_diagnostic_type : Error<
@@ -9539,14 +9549,14 @@ def err_defaulted_special_member_copy_const_param : Error<
def err_defaulted_copy_assign_not_ref : Error<
"the parameter for an explicitly-defaulted copy assignment operator must be an "
"lvalue reference type">;
-def err_incorrect_defaulted_constexpr : Error<
- "defaulted definition of %sub{select_special_member_kind}0 "
- "is not constexpr">;
+def ext_incorrect_defaulted_constexpr : ExtWarn<
+ "defaulted definition of %sub{select_special_member_kind}0 that marked %select{constexpr|consteval}1 "
+ "but never produces a constant expression is a C++23 extension">, InGroup<CXX23>, DefaultError;
+def warn_cxx23_compat_incorrect_defaulted_constexpr : Warning<
+ "defaulted definition of %sub{select_special_member_kind}0 that marked %select{constexpr|consteval}1 "
+ "but never produces a constant expression is incompatible with C++ standards before C++23">, InGroup<CXXPre23Compat>, DefaultIgnore;
def err_incorrect_defaulted_constexpr_with_vb: Error<
"%sub{select_special_member_kind}0 cannot be 'constexpr' in a class with virtual base class">;
-def err_incorrect_defaulted_consteval : Error<
- "defaulted declaration of %sub{select_special_member_kind}0 "
- "cannot be consteval because implicit definition is not constexpr">;
def warn_defaulted_method_deleted : Warning<
"explicitly defaulted %sub{select_special_member_kind}0 is implicitly "
"deleted">, InGroup<DefaultedFunctionDeleted>;
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 36e53c684ac4dc..aa49dc73e157bf 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -1722,12 +1722,19 @@ static bool CheckConstexprDestructorSubobjects(Sema &SemaRef,
return true;
if (Kind == Sema::CheckConstexprKind::Diagnose) {
- SemaRef.Diag(DD->getLocation(), diag::err_constexpr_dtor_subobject)
+ SemaRef.Diag(DD->getLocation(),
+ SemaRef.getLangOpts().CPlusPlus23
+ ? diag::warn_cxx23_compat_constexpr_dtor_subobject
+ : diag::ext_constexpr_dtor_subobject)
<< static_cast<int>(DD->getConstexprKind()) << !FD
<< (FD ? FD->getDeclName() : DeclarationName()) << T;
SemaRef.Diag(Loc, diag::note_constexpr_dtor_subobject)
<< !FD << (FD ? FD->getDeclName() : DeclarationName()) << T;
}
+
+ if (SemaRef.getLangOpts().CPlusPlus23)
+ return true;
+
return false;
};
@@ -1754,11 +1761,17 @@ static bool CheckConstexprParameterTypes(Sema &SemaRef,
const ParmVarDecl *PD = FD->getParamDecl(ArgIndex);
assert(PD && "null in a parameter list");
SourceLocation ParamLoc = PD->getLocation();
- if (CheckLiteralType(SemaRef, Kind, ParamLoc, *i,
- diag::err_constexpr_non_literal_param, ArgIndex + 1,
- PD->getSourceRange(), isa<CXXConstructorDecl>(FD),
- FD->isConsteval()))
+ if (CheckLiteralType(
+ SemaRef, Kind, ParamLoc, *i,
+ SemaRef.getLangOpts().CPlusPlus23
+ ? diag::warn_cxx23_compat_constexpr_non_literal_param
+ : diag::ext_constexpr_non_literal_param,
+ ArgIndex + 1, PD->getSourceRange(), isa<CXXConstructorDecl>(FD),
+ FD->isConsteval())) {
+ if (SemaRef.getLangOpts().CPlusPlus23)
+ return true;
return false;
+ }
}
return true;
}
@@ -1767,10 +1780,16 @@ static bool CheckConstexprParameterTypes(Sema &SemaRef,
/// true. If not, produce a suitable diagnostic and return false.
static bool CheckConstexprReturnType(Sema &SemaRef, const FunctionDecl *FD,
Sema::CheckConstexprKind Kind) {
- if (CheckLiteralType(SemaRef, Kind, FD->getLocation(), FD->getReturnType(),
- diag::err_constexpr_non_literal_return,
- FD->isConsteval()))
+ if (CheckLiteralType(
+ SemaRef, Kind, FD->getLocation(), FD->getReturnType(),
+ SemaRef.getLangOpts().CPlusPlus23
+ ? diag::warn_cxx23_compat_constexpr_non_literal_return
+ : diag::ext_constexpr_non_literal_return,
+ FD->isConsteval())) {
+ if (SemaRef.getLangOpts().CPlusPlus23)
+ return true;
return false;
+ }
return true;
}
@@ -2458,8 +2477,11 @@ static bool CheckConstexprFunctionBody(Sema &SemaRef, const FunctionDecl *Dcl,
SmallVector<PartialDiagnosticAt, 8> Diags;
if (Kind == Sema::CheckConstexprKind::Diagnose &&
!Expr::isPotentialConstantExpr(Dcl, Diags)) {
- SemaRef.Diag(Dcl->getLocation(),
- diag::ext_constexpr_function_never_constant_expr)
+ SemaRef.Diag(
+ Dcl->getLocation(),
+ SemaRef.getLangOpts().CPlusPlus23
+ ? diag::warn_cxx23_compat_constexpr_function_never_constant_expr
+ : diag::ext_constexpr_function_never_constant_expr)
<< isa<CXXConstructorDecl>(Dcl) << Dcl->isConsteval()
<< Dcl->getNameInfo().getSourceRange();
for (size_t I = 0, N = Diags.size(); I != N; ++I)
@@ -7852,13 +7874,15 @@ bool Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD,
for (const auto &I : RD->vbases())
Diag(I.getBeginLoc(), diag::note_constexpr_virtual_base_here);
} else {
- Diag(MD->getBeginLoc(), MD->isConsteval()
- ? diag::err_incorrect_defaulted_consteval
- : diag::err_incorrect_defaulted_constexpr)
- << CSM;
+ Diag(MD->getBeginLoc(),
+ getLangOpts().CPlusPlus23
+ ? diag::warn_cxx23_compat_incorrect_defaulted_constexpr
+ : diag::ext_incorrect_defaulted_constexpr)
+ << CSM << MD->isConsteval();
}
// FIXME: Explain why the special member can't be constexpr.
- HadError = true;
+ if (!getLangOpts().CPlusPlus23)
+ HadError = true;
}
if (First) {
diff --git a/clang/test/AST/Interp/cxx23.cpp b/clang/test/AST/Interp/cxx23.cpp
index bd1cf186d519c5..6ef7df9662e6a4 100644
--- a/clang/test/AST/Interp/cxx23.cpp
+++ b/clang/test/AST/Interp/cxx23.cpp
@@ -6,57 +6,45 @@
/// FIXME: The new interpreter is missing all the 'control flows through...' diagnostics.
-constexpr int f(int n) { // ref20-error {{constexpr function never produces a constant expression}} \
- // ref23-error {{constexpr function never produces a constant expression}}
+constexpr int f(int n) { // ref20-error {{constexpr function that never produces a constant expression}}
static const int m = n; // ref20-note {{control flows through the definition of a static variable}} \
// ref20-warning {{is a C++23 extension}} \
- // ref23-note {{control flows through the definition of a static variable}} \
// expected20-warning {{is a C++23 extension}}
return m;
}
-constexpr int g(int n) { // ref20-error {{constexpr function never produces a constant expression}} \
- // ref23-error {{constexpr function never produces a constant expression}}
+constexpr int g(int n) { // ref20-error {{constexpr function that never produces a constant expression}}
thread_local const int m = n; // ref20-note {{control flows through the definition of a thread_local variable}} \
// ref20-warning {{is a C++23 extension}} \
- // ref23-note {{control flows through the definition of a thread_local variable}} \
// expected20-warning {{is a C++23 extension}}
return m;
}
-constexpr int c_thread_local(int n) { // ref20-error {{constexpr function never produces a constant expression}} \
- // ref23-error {{constexpr function never produces a constant expression}}
+constexpr int c_thread_local(int n) { // ref20-error {{constexpr function that never produces a constant expression}}
static _Thread_local int m = 0; // ref20-note {{control flows through the definition of a thread_local variable}} \
// ref20-warning {{is a C++23 extension}} \
- // ref23-note {{control flows through the definition of a thread_local variable}} \
// expected20-warning {{is a C++23 extension}}
return m;
}
-constexpr int gnu_thread_local(int n) { // ref20-error {{constexpr function never produces a constant expression}} \
- // ref23-error {{constexpr function never produces a constant expression}}
+constexpr int gnu_thread_local(int n) { // ref20-error {{constexpr function that never produces a constant expression}}
static __thread int m = 0; // ref20-note {{control flows through the definition of a thread_local variable}} \
// ref20-warning {{is a C++23 extension}} \
- // ref23-note {{control flows through the definition of a thread_local variable}} \
// expected20-warning {{is a C++23 extension}}
return m;
}
-constexpr int h(int n) { // ref20-error {{constexpr function never produces a constant expression}} \
- // ref23-error {{constexpr function never produces a constant expression}}
+constexpr int h(int n) { // ref20-error {{constexpr function that never produces a constant expression}}
static const int m = n; // ref20-note {{control flows through the definition of a static variable}} \
// ref20-warning {{is a C++23 extension}} \
- // ref23-note {{control flows through the definition of a static variable}} \
// expected20-warning {{is a C++23 extension}}
return &m - &m;
}
-constexpr int i(int n) { // ref20-error {{constexpr function never produces a constant expression}} \
- // ref23-error {{constexpr function never produces a constant expression}}
+constexpr int i(int n) { // ref20-error {{constexpr function that never produces a constant expression}}
thread_local const int m = n; // ref20-note {{control flows through the definition of a thread_local variable}} \
// ref20-warning {{is a C++23 extension}} \
- // ref23-note {{control flows through the definition of a thread_local variable}} \
// expected20-warning {{is a C++23 extension}}
return &m - &m;
}
diff --git a/clang/test/AST/Interp/literals.cpp b/clang/test/AST/Interp/literals.cpp
index 61825bc11438f6..ab09280e883fba 100644
--- a/clang/test/AST/Interp/literals.cpp
+++ b/clang/test/AST/Interp/literals.cpp
@@ -275,7 +275,7 @@ namespace SizeOf {
#if __cplusplus >= 202002L
/// FIXME: The following code should be accepted.
- consteval int foo(int n) { // ref-error {{consteval function never produces a constant expression}}
+ consteval int foo(int n) { // ref-error {{consteval function that never produces a constant expression}}
return sizeof(int[n]); // ref-note 3{{not valid in a constant expression}}
}
constinit int var = foo(5); // ref-error {{not a constant expression}} \
diff --git a/clang/test/AST/Interp/shifts.cpp b/clang/test/AST/Interp/shifts.cpp
index cf71e7145c2742..f8fa1b5d095da0 100644
--- a/clang/test/AST/Interp/shifts.cpp
+++ b/clang/test/AST/Interp/shifts.cpp
@@ -7,10 +7,10 @@
namespace shifts {
- constexpr void test() { // ref-error {{constexpr function never produces a constant expression}} \
- // ref-cxx17-error {{constexpr function never produces a constant expression}} \
- // expected-error {{constexpr function never produces a constant expression}} \
- // cxx17-error {{constexpr function never produces a constant expression}} \
+ constexpr void test() { // ref-error {{constexpr function that never produces a constant expression}} \
+ // ref-cxx17-error {{constexpr function that never produces a constant expression}} \
+ // expected-error {{constexpr function that never produces a constant expression}} \
+ // cxx17-error {{constexpr function that never produces a constant expression}} \
char c; // cxx17-warning {{uninitialized variable}} \
// ref-cxx17-warning {{uninitialized variable}}
diff --git a/clang/test/CXX/basic/basic.types/p10.cpp b/clang/test/CXX/basic/basic.types/p10.cpp
index a543f248e53711..19e099d5077de7 100644
--- a/clang/test/CXX/basic/basic.types/p10.cpp
+++ b/clang/test/CXX/basic/basic.types/p10.cpp
@@ -8,7 +8,7 @@ struct NonLiteral { NonLiteral(); };
// [C++1y] - void
constexpr void f() {}
#ifndef CXX1Y
-// expected-error at -2 {{'void' is not a literal type}}
+// expected-error at -2 {{constexpr function with non-literal return type 'void' is a C++23 extension}}
#endif
// - a scalar type
@@ -40,12 +40,12 @@ constexpr ClassTemp<int> classtemplate2[] = {};
struct UserProvDtor {
~UserProvDtor(); // expected-note {{has a user-provided destructor}}
};
-constexpr int f(UserProvDtor) { return 0; } // expected-error {{'UserProvDtor' is not a literal type}}
+constexpr int f(UserProvDtor) { return 0; } // expected-error {{non-literal parameter type 'UserProvDtor'}}
struct NonTrivDtor {
constexpr NonTrivDtor();
virtual ~NonTrivDtor() = default; // expected-note {{has a non-trivial destructor}} expected-note {{because it is virtual}}
};
-constexpr int f(NonTrivDtor) { return 0; } // expected-error {{'NonTrivDtor' is not a literal type}}
+constexpr int f(NonTrivDtor) { return 0; } // expected-error {{non-literal parameter type 'NonTrivDtor'}}
struct NonTrivDtorBase {
~NonTrivDtorBase();
};
@@ -53,7 +53,7 @@ template<typename T>
struct DerivedFromNonTrivDtor : T { // expected-note {{'DerivedFromNonTrivDtor<NonTrivDtorBase>' is not literal because it has base class 'NonTrivDtorBase' of non-literal type}}
constexpr DerivedFromNonTrivDtor();
};
-constexpr int f(DerivedFromNonTrivDtor<NonTrivDtorBase>) { return 0; } // expected-error {{constexpr function's 1st parameter type 'DerivedFromNonTrivDtor<NonTrivDtorBase>' is not a literal type}}
+constexpr int f(DerivedFromNonTrivDtor<NonTrivDtorBase>) { return 0; } // expected-error {{constexpr function with 1st non-literal parameter type 'DerivedFromNonTrivDtor<NonTrivDtorBase>' is a C++23 extension}}
struct TrivDtor {
constexpr TrivDtor();
};
@@ -77,11 +77,11 @@ struct CtorTemplate {
struct CopyCtorOnly { // expected-note {{'CopyCtorOnly' is not literal because it is not an aggregate and has no constexpr constructors other than copy or move constructors}}
constexpr CopyCtorOnly(CopyCtorOnly&);
};
-constexpr int f(CopyCtorOnly) { return 0; } // expected-error {{'CopyCtorOnly' is not a literal type}}
+constexpr int f(CopyCtorOnly) { return 0; } // expected-error {{non-literal parameter type 'CopyCtorOnly'}}
struct MoveCtorOnly { // expected-note {{no constexpr constructors other than copy or move constructors}}
constexpr MoveCtorOnly(MoveCtorOnly&&);
};
-constexpr int f(MoveCtorOnly) { return 0; } // expected-error {{'MoveCtorOnly' is not a literal type}}
+constexpr int f(MoveCtorOnly) { return 0; } // expected-error {{non-literal parameter type 'MoveCtorOnly'}}
template<typename T>
struct CtorArg {
constexpr CtorArg(T);
@@ -97,7 +97,7 @@ struct Derived : HasVBase {
template<typename T> struct DerivedFromVBase : T { // expected-note {{struct with virtual base class is not a literal type}}
constexpr DerivedFromVBase();
};
-constexpr int f(DerivedFromVBase<HasVBase>) {} // expected-error {{constexpr function's 1st parameter type 'DerivedFromVBase<HasVBase>' is not a literal type}}
+constexpr int f(DerivedFromVBase<HasVBase>) {} // expected-error {{constexpr function with 1st non-literal parameter type 'DerivedFromVBase<HasVBase>' is a C++23 extension}}
template<typename T> constexpr DerivedFromVBase<T>::DerivedFromVBase() : T() {}
constexpr int nVBase = (DerivedFromVBase<HasVBase>(), 0); // expected-error {{constant expression}} expected-note {{cannot construct object of type 'DerivedFromVBase<HasVBase>' with virtual base class in a constant expression}}
@@ -105,12 +105,12 @@ constexpr int nVBase = (DerivedFromVBase<HasVBase>(), 0); // expected-error {{co
struct NonLitMember {
S s; // expected-note {{has data member 's' of non-literal type 'S'}}
};
-constexpr int f(NonLitMember) {} // expected-error {{1st parameter type 'NonLitMember' is not a literal type}}
+constexpr int f(NonLitMember) {} // expected-error {{1st non-literal parameter type 'NonLitMember' is a C++23 extension}}
struct NonLitBase :
S { // expected-note {{base class 'S' of non-literal type}}
constexpr NonLitBase();
};
-constexpr int f(NonLitBase) { return 0; } // expected-error {{'NonLitBase' is not a literal type}}
+constexpr int f(NonLitBase) { return 0; } // expected-error {{non-literal parameter type 'NonLitBase'}}
struct LitMemBase : Agg {
Agg agg;
};
@@ -120,7 +120,7 @@ struct MemberType {
constexpr MemberType();
};
constexpr int f(MemberType<int>) { return 0; }
-constexpr int f(MemberType<NonLiteral>) { return 0; } // expected-error {{not a literal type}}
+constexpr int f(MemberType<NonLiteral>) { return 0; } // expected-error {{non-literal parameter type}}
// - an array of literal type [C++1y] other than an array of runtime bound
struct ArrGood {
@@ -134,7 +134,7 @@ constexpr int f(ArrGood) { return 0; }
struct ArrBad {
S s[3]; // expected-note {{data member 's' of non-literal type 'S[3]'}}
};
-constexpr int f(ArrBad) { return 0; } // expected-error {{1st parameter type 'ArrBad' is not a literal type}}
+constexpr int f(ArrBad) { return 0; } // expected-error {{1st non-literal parameter type 'ArrBad'}}
constexpr int arb(int n) { // expected-note {{declared here}}
int a[n]; // expected-error {{variable of non-literal type 'int[n]' cannot be defined in a constexpr function}} \
@@ -159,7 +159,7 @@ namespace inherited_ctor {
D(int);
using C::C;
};
- constexpr int f(D) { return 0; } // expected-error {{not a literal type}}
+ constexpr int f(D) { return 0; } // expected-error {{non-literal parameter type}}
// This one is a bit odd: F inherits E's default constructor, which is
// constexpr. Because F has a constructor of its own, it doesn't declare a
@@ -178,7 +178,7 @@ namespace inherited_ctor {
struct H : G { // expected-note {{because}}
using G::G;
};
- constexpr int f(H) { return 0; } // expected-error {{not a literal type}}
+ constexpr int f(H) { return 0; } // expected-error {{non-literal parameter type}}
struct J;
struct I { constexpr I(const J&); };
diff --git a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/dtor.cpp b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/dtor.cpp
index 7ad2e582a81268..1a3da8bdc252ac 100644
--- a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/dtor.cpp
+++ b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/dtor.cpp
@@ -58,12 +58,12 @@ namespace subobject {
struct A {
~A();
};
- struct B : A { // expected-note {{here}}
- constexpr ~B() {} // expected-error {{destructor cannot be declared constexpr because base class 'A' does not have a constexpr destructor}}
+ struct B : A { // cxx2a-note {{here}}
+ constexpr ~B() {} // cxx2a-error {{destructor cannot be declared constexpr before C++23 because base class 'A' does not have a constexpr destructor}}
};
struct C {
- A a; // expected-note {{here}}
- constexpr ~C() {} // expected-error {{destructor cannot be declared constexpr because data member 'a' does not have a constexpr destructor}}
+ A a; // cxx2a-note {{here}}
+ constexpr ~C() {} // cxx2a-error {{destructor cannot be declared constexpr before C++23 because data member 'a' does not have a constexpr destructor}}
};
struct D : A {
A a;
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 c07502c0555b50..e8c71b44edd620 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
@@ -14,7 +14,7 @@ constexpr int i(int n) {
return m;
}
-constexpr int g() { // expected-error {{constexpr function never produces a constant expression}}
+constexpr int g() { // expected-warning {{constexpr function that never produces a constant expression is incompatible with C++ standards before C++23}}
goto test; // expected-note {{subexpression not valid in a constant expression}} \
// expected-warning {{use of this statement in a constexpr function is incompatible with C++ standards before C++23}}
test:
@@ -29,7 +29,7 @@ struct NonLiteral { // expected-note 2 {{'NonLiteral' is not literal}}
NonLiteral() {}
};
-constexpr void non_literal() { // expected-error {{constexpr function never produces a constant expression}}
+constexpr void non_literal() { // expected-warning {{constexpr function that never produces a constant expression is incompatible with C++ standards before C++23}}
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++23}}
}
diff --git a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3.cpp b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3.cpp
index 6214ff8006d67f..d57c098faff6dd 100644
--- a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3.cpp
+++ b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3.cpp
@@ -1,6 +1,6 @@
// RUN: %clang_cc1 -fcxx-exceptions -verify=expected,beforecxx14,beforecxx20,beforecxx23 -std=c++11 %s
-// RUN: %clang_cc1 -fcxx-exceptions -verify=expected,aftercxx14,beforecxx20,beforecxx23 -std=c++14 %s
-// RUN: %clang_cc1 -fcxx-exceptions -verify=expected,aftercxx14,aftercxx20,beforecxx23 -std=c++20 %s
+// RUN: %clang_cc1 -fcxx-exceptions -verify=expected,aftercxx14,beforecxx20,beforecxx23,cxx14_20 -std=c++14 %s
+// RUN: %clang_cc1 -fcxx-exceptions -verify=expected,aftercxx14,aftercxx20,beforecxx23,cxx14_20 -std=c++20 %s
// RUN: %clang_cc1 -fcxx-exceptions -verify=expected,aftercxx14,aftercxx20 -std=c++23 %s
namespace N {
@@ -11,7 +11,7 @@ namespace M {
typedef double D;
}
-struct NonLiteral { // expected-note 2{{no constexpr constructors}}
+struct NonLiteral { // beforecxx23-note 2{{no constexpr constructors}}
NonLiteral() {}
NonLiteral(int) {}
};
@@ -41,18 +41,17 @@ struct T : SS, NonLiteral {
virtual constexpr int OutOfLineVirtual() const; // beforecxx20-error {{virtual function cannot be constexpr}}
// - its return type shall be a literal type;
- // Once we support P2448R2 constexpr functions will be allowd to return non-literal types
- // The destructor will also be allowed
- constexpr NonLiteral NonLiteralReturn() const { return {}; } // expected-error {{constexpr function's return type 'NonLiteral' is not a literal type}}
- constexpr void VoidReturn() const { return; } // beforecxx14-error {{constexpr function's return type 'void' is not a literal type}}
+ // With support for P2448R2 constexpr functions are allowed to return non-literal types in C++23.
+ constexpr NonLiteral NonLiteralReturn() const { return {}; } // beforecxx23-error {{constexpr function with non-literal return type 'NonLiteral' is a C++23 extension}}
+ constexpr void VoidReturn() const { return; } // beforecxx14-error {{constexpr function with non-literal return type 'void' is a C++23 extension}}
constexpr ~T(); // beforecxx20-error {{destructor cannot be declared constexpr}}
typedef NonLiteral F() const;
constexpr F NonLiteralReturn2; // ok until definition
// - each of its parameter types shall be a literal type;
- // Once we support P2448R2 constexpr functions will be allowd to have parameters of non-literal types
- constexpr int NonLiteralParam(NonLiteral) const { return 0; } // expected-error {{constexpr function's 1st parameter type 'NonLiteral' is not a literal type}}
+ // With support for P2448R2 constexpr functions are allowed to have parameters of non-literal types in C++23.
+ constexpr int NonLiteralParam(NonLiteral) const { return 0; } // beforecxx23-error {{constexpr function with 1st non-literal parameter type 'NonLiteral' is a C++23 extension}}
typedef int G(NonLiteral) const;
constexpr G NonLiteralParam2; // ok until definition
@@ -66,7 +65,7 @@ struct T : SS, NonLiteral {
// constexpr since they can't be const.
constexpr T &operator=(const T &) = default; // beforecxx14-error {{an explicitly-defaulted copy assignment operator may not have 'const', 'constexpr' or 'volatile' qualifiers}} \
// beforecxx14-warning {{C++14}} \
- // aftercxx14-error{{defaulted definition of copy assignment operator is not constexpr}}
+ // cxx14_20-error{{defaulted definition of copy assignment operator that marked constexpr but never produces a constant expression}}
};
constexpr int T::OutOfLineVirtual() const { return 0; }
@@ -229,9 +228,9 @@ namespace DR1364 {
return k; // ok, even though lvalue-to-rvalue conversion of a function
// parameter is not allowed in a constant expression.
}
- int kGlobal; // expected-note {{here}}
- constexpr int f() { // expected-error {{constexpr function never produces a constant expression}}
- return kGlobal; // expected-note {{read of non-const}}
+ int kGlobal; // beforecxx23-note {{here}}
+ constexpr int f() { // beforecxx23-error {{constexpr function that never produces a constant expression is a C++23 extension}}
+ return kGlobal; // beforecxx23-note {{read of non-const}}
}
}
@@ -272,7 +271,7 @@ namespace std_example {
int a; // beforecxx20-warning {{uninitialized}}
return a;
}
- constexpr int prev(int x) { // beforecxx14-error {{never produces a constant expression}}
+ constexpr int prev(int x) { // beforecxx14-error {{constexpr function that never produces a constant expression is a C++23 extension}}
return --x; // beforecxx14-note {{subexpression}}
}
diff --git a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p4.cpp b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p4.cpp
index f1f677ebfcd341..71c8d09d3041d4 100644
--- a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p4.cpp
+++ b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p4.cpp
@@ -24,8 +24,8 @@ struct Literal {
// shall be a literal type.
struct S {
constexpr S(int, N::C) {}
- constexpr S(int, NonLiteral, N::C) {} // expected-error {{constexpr constructor's 2nd parameter type 'NonLiteral' is not a literal type}}
- constexpr S(int, NonLiteral = 42) {} // expected-error {{constexpr constructor's 2nd parameter type 'NonLiteral' is not a literal type}}
+ constexpr S(int, NonLiteral, N::C) {} // expected-error {{constexpr constructor with 2nd non-literal parameter type 'NonLiteral' is a C++23 extension}}
+ constexpr S(int, NonLiteral = 42) {} // expected-error {{constexpr constructor with 2nd non-literal parameter type 'NonLiteral' is a C++23 extension}}
// In addition, either its function-body shall be = delete or = default
constexpr S() = default;
@@ -242,15 +242,15 @@ constexpr int f(enable_shared_from_this<int>);
// - every constructor involved in initializing non-static data members and base
// class sub-objects shall be a constexpr constructor.
-// This will no longer be the case once we support P2448R2
+// This is the case before C++23.
struct ConstexprBaseMemberCtors : Literal {
Literal l;
constexpr ConstexprBaseMemberCtors() : Literal(), l() {} // ok
- constexpr ConstexprBaseMemberCtors(char) : // expected-error {{constexpr constructor never produces a constant expression}}
+ constexpr ConstexprBaseMemberCtors(char) : // expected-error {{constexpr constructor that never produces a constant expression is a C++23 extension}}
Literal(0), // expected-note {{non-constexpr constructor}}
l() {}
- constexpr ConstexprBaseMemberCtors(double) : Literal(), // expected-error {{constexpr constructor never produces a constant expression}}
+ constexpr ConstexprBaseMemberCtors(double) : Literal(), // expected-error {{constexpr constructor that never produces a constant expression is a C++23 extension}}
l(0) // expected-note {{non-constexpr constructor}}
{}
};
@@ -272,7 +272,7 @@ struct X {
union XU1 { int a; constexpr XU1() = default; };
#ifndef CXX2A
-// expected-error at -2{{not constexpr}}
+// expected-error at -2{{marked constexpr but never produces a constant expression}}
#endif
union XU2 { int a = 1; constexpr XU2() = default; };
@@ -282,7 +282,7 @@ struct XU3 {
};
constexpr XU3() = default;
#ifndef CXX2A
- // expected-error at -2{{not constexpr}}
+ // expected-error at -2{{marked constexpr but never produces a constant expression}}
#endif
};
struct XU4 {
@@ -306,7 +306,7 @@ static_assert(XU4().a == 1, "");
int kGlobal; // expected-note {{here}}
struct Z {
constexpr Z(int a) : n(a) {}
- constexpr Z() : n(kGlobal) {} // expected-error {{constexpr constructor never produces a constant expression}} expected-note {{read of non-const}}
+ constexpr Z() : n(kGlobal) {} // expected-error {{constexpr constructor that never produces a constant expression is a C++23 extension}} expected-note {{read of non-const}}
int n;
};
@@ -333,7 +333,7 @@ namespace CtorLookup {
constexpr B(B&);
};
constexpr B::B(const B&) = default;
- constexpr B::B(B&) = default; // expected-error {{not constexpr}}
+ constexpr B::B(B&) = default; // expected-error {{marked constexpr but never produces a constant expression}}
struct C {
A a;
@@ -342,7 +342,7 @@ namespace CtorLookup {
constexpr C(C&);
};
constexpr C::C(const C&) = default;
- constexpr C::C(C&) = default; // expected-error {{not constexpr}}
+ constexpr C::C(C&) = default; // expected-error {{marked constexpr but never produces a constant expression}}
}
namespace PR14503 {
diff --git a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p5.cpp b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p5.cpp
index 18b2c6b1d6d15b..7c06e5a9f928ad 100644
--- a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p5.cpp
+++ b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p5.cpp
@@ -30,7 +30,7 @@ static_assert(g4() == 5, "");
constexpr int f(bool b)
{ return b ? throw 0 : 0; } // ok
-constexpr int f() { return throw 0, 0; } // expected-error {{constexpr function never produces a constant expression}} expected-note {{subexpression}}
+constexpr int f() { return throw 0, 0; } // expected-error {{constexpr function that never produces a constant expression is a C++23 extension}} expected-note {{subexpression}}
struct B {
constexpr B(int x) : i(0) { }
@@ -40,14 +40,14 @@ struct B {
int global; // expected-note {{declared here}}
struct D : B {
- constexpr D() : B(global) { } // expected-error {{constexpr constructor never produces a constant expression}} expected-note {{read of non-const}}
+ constexpr D() : B(global) { } // expected-error {{constexpr constructor that never produces a constant expression}} expected-note {{read of non-const}}
};
}
namespace PotentialConstant {
-constexpr int Comma(int n) { return // expected-error {{constexpr function never produces a constant expression}}
+constexpr int Comma(int n) { return // expected-error {{constexpr function that never produces a constant expression}}
(void)(n * 2),
throw 0, // expected-note {{subexpression}}
0;
diff --git a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p6.cpp b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p6.cpp
index 00ef78426289fa..850420ca8ae1c0 100644
--- a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p6.cpp
+++ b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p6.cpp
@@ -64,5 +64,5 @@ namespace TemplateVBase {
constexpr T3() {}
};
constexpr T3<Literal> g3() { return {}; } // ok
- constexpr T3<VirtBase> g4() { return {}; } // expected-error {{not a literal type}}
+ constexpr T3<VirtBase> g4() { return {}; } // expected-error {{non-literal return type}}
}
diff --git a/clang/test/CXX/dcl.decl/dcl.fct.def/dcl.fct.def.default/p2.cpp b/clang/test/CXX/dcl.decl/dcl.fct.def/dcl.fct.def.default/p2.cpp
index 5b525fc91aba1c..9c9034c7f908ba 100644
--- a/clang/test/CXX/dcl.decl/dcl.fct.def/dcl.fct.def.default/p2.cpp
+++ b/clang/test/CXX/dcl.decl/dcl.fct.def/dcl.fct.def.default/p2.cpp
@@ -3,7 +3,7 @@
// An explicitly-defaulted function may be declared constexpr only if it would
// have been implicitly declared as constexpr.
struct S1 {
- constexpr S1() = default; // expected-error {{defaulted definition of default constructor is not constexpr}}
+ constexpr S1() = default; // expected-error {{marked constexpr but never produces a constant expression}}
constexpr S1(const S1&) = default;
constexpr S1(S1&&) = default;
constexpr S1 &operator=(const S1&) const = default; // expected-error {{explicitly-defaulted copy assignment operator may not have}}
@@ -18,8 +18,8 @@ struct NoCopyMove {
};
struct S2 {
constexpr S2() = default;
- constexpr S2(const S2&) = default; // expected-error {{defaulted definition of copy constructor is not constexpr}}
- constexpr S2(S2&&) = default; // expected-error {{defaulted definition of move constructor is not constexpr}}
+ constexpr S2(const S2&) = default; // expected-error {{defaulted definition of copy constructor that marked constexpr but never produces a constant expression is a C++23 extension}}
+ constexpr S2(S2&&) = default; // expected-error {{defaulted definition of move constructor that marked constexpr but never produces a constant expression}}
NoCopyMove ncm;
};
diff --git a/clang/test/CXX/drs/dr13xx.cpp b/clang/test/CXX/drs/dr13xx.cpp
index 359c04b3e0f3d4..be656c4468eaeb 100644
--- a/clang/test/CXX/drs/dr13xx.cpp
+++ b/clang/test/CXX/drs/dr13xx.cpp
@@ -1,8 +1,8 @@
// RUN: %clang_cc1 -std=c++98 %s -verify=expected,cxx98-14,cxx98 -fexceptions -fcxx-exceptions -pedantic-errors
-// RUN: %clang_cc1 -std=c++11 %s -verify=expected,cxx11-17,cxx11-14,cxx98-14,since-cxx11,cxx11 -fexceptions -fcxx-exceptions -pedantic-errors
-// RUN: %clang_cc1 -std=c++14 %s -verify=expected,cxx11-17,cxx11-14,since-cxx14,cxx98-14,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors
-// RUN: %clang_cc1 -std=c++17 %s -verify=expected,cxx11-17,since-cxx14,since-cxx17,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors
-// RUN: %clang_cc1 -std=c++20 %s -verify=expected,since-cxx14,since-cxx20,since-cxx17,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors
+// RUN: %clang_cc1 -std=c++11 %s -verify=expected,cxx11-20,cxx11-17,cxx11-14,cxx98-14,since-cxx11,cxx11 -fexceptions -fcxx-exceptions -pedantic-errors
+// RUN: %clang_cc1 -std=c++14 %s -verify=expected,cxx11-20,cxx11-17,cxx11-14,since-cxx14,cxx98-14,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors
+// RUN: %clang_cc1 -std=c++17 %s -verify=expected,cxx11-20,cxx11-17,since-cxx14,since-cxx17,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors
+// RUN: %clang_cc1 -std=c++20 %s -verify=expected,cxx11-20,since-cxx14,since-cxx20,since-cxx17,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors
// RUN: %clang_cc1 -std=c++23 %s -verify=expected,since-cxx14,since-cxx20,since-cxx17,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors
// RUN: %clang_cc1 -std=c++2c %s -verify=expected,since-cxx14,since-cxx20,since-cxx17,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors
@@ -410,11 +410,11 @@ namespace dr1358 { // dr1358: 3.1
struct B : Virt {
int member;
constexpr B(NonLit u) : member(u) {}
- // since-cxx11-error at -1 {{constexpr constructor's 1st parameter type 'NonLit' is not a literal type}}
- // since-cxx11-note@#dr1358-NonLit {{'NonLit' is not literal because it is not an aggregate and has no constexpr constructors other than copy or move constructors}}
+ // cxx11-20-error at -1 {{constexpr constructor with 1st non-literal parameter type 'NonLit' is a C++23 extension}}
+ // cxx11-20-note@#dr1358-NonLit {{'NonLit' is not literal because it is not an aggregate and has no constexpr constructors other than copy or move constructors}}
constexpr NonLit f(NonLit u) const { return NonLit(); }
- // since-cxx11-error at -1 {{constexpr function's return type 'NonLit' is not a literal type}}
- // since-cxx11-note@#dr1358-NonLit {{'NonLit' is not literal because it is not an aggregate and has no constexpr constructors other than copy or move constructors}}
+ // cxx11-20-error at -1 {{constexpr function with non-literal return type 'NonLit' is a C++23 extension}}
+ // cxx11-20-note@#dr1358-NonLit {{'NonLit' is not literal because it is not an aggregate and has no constexpr constructors other than copy or move constructors}}
};
#endif
}
@@ -423,13 +423,13 @@ namespace dr1359 { // dr1359: 3.5
#if __cplusplus >= 201103L
union A { constexpr A() = default; };
union B { constexpr B() = default; int a; }; // #dr1359-B
- // cxx11-17-error at -1 {{defaulted definition of default constructor is not constexpr}}
+ // cxx11-17-error at -1 {{defaulted definition of default constructor that marked constexpr but never produces a constant expression is a C++23 extension}}
union C { constexpr C() = default; int a, b; }; // #dr1359-C
- // cxx11-17-error at -1 {{defaulted definition of default constructor is not constexpr}}
+ // cxx11-17-error at -1 {{defaulted definition of default constructor that marked constexpr}}
struct X { constexpr X() = default; union {}; };
// since-cxx11-error at -1 {{declaration does not declare anything}}
struct Y { constexpr Y() = default; union { int a; }; }; // #dr1359-Y
- // cxx11-17-error at -1 {{defaulted definition of default constructor is not constexpr}}
+ // cxx11-17-error at -1 {{defaulted definition of default constructor that marked constexpr}}
constexpr A a = A();
constexpr B b = B();
diff --git a/clang/test/CXX/drs/dr14xx.cpp b/clang/test/CXX/drs/dr14xx.cpp
index d262f6f9dcab79..4bce1de0ab5149 100644
--- a/clang/test/CXX/drs/dr14xx.cpp
+++ b/clang/test/CXX/drs/dr14xx.cpp
@@ -153,16 +153,16 @@ namespace dr1460 { // dr1460: 3.5
namespace Defaulted {
union A { constexpr A() = default; };
union B { int n; constexpr B() = default; };
- // cxx11-17-error at -1 {{defaulted definition of default constructor is not constexpr}}
+ // cxx11-17-error at -1 {{defaulted definition of default constructor that marked constexpr but never produces a constant expression is a C++23 extension}}
union C { int n = 0; constexpr C() = default; };
struct D { union {}; constexpr D() = default; };
// expected-error at -1 {{declaration does not declare anything}}
struct E { union { int n; }; constexpr E() = default; };
- // cxx11-17-error at -1 {{defaulted definition of default constructor is not constexpr}}
+ // cxx11-17-error at -1 {{defaulted definition of default constructor that marked constexpr but never produces a constant expression is a C++23 extension}}
struct F { union { int n = 0; }; constexpr F() = default; };
struct G { union { int n = 0; }; union { int m; }; constexpr G() = default; };
- // cxx11-17-error at -1 {{defaulted definition of default constructor is not constexpr}}
+ // cxx11-17-error at -1 {{defaulted definition of default constructor that marked constexpr but never produces a constant expression is a C++23 extension}}
struct H {
union {
int n = 0;
diff --git a/clang/test/CXX/drs/dr16xx.cpp b/clang/test/CXX/drs/dr16xx.cpp
index 3f074c4d57354a..1cf7bb840507ff 100644
--- a/clang/test/CXX/drs/dr16xx.cpp
+++ b/clang/test/CXX/drs/dr16xx.cpp
@@ -1,8 +1,8 @@
// RUN: %clang_cc1 -std=c++98 -triple x86_64-unknown-unknown %s -verify=expected,cxx98-14,cxx98 -fexceptions -fcxx-exceptions -pedantic-errors
-// RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-unknown %s -verify=expected,cxx98-14,since-cxx11,cxx11 -fexceptions -fcxx-exceptions -pedantic-errors
-// RUN: %clang_cc1 -std=c++14 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx14,cxx98-14,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors
-// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx14,since-cxx17,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors
-// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx14,since-cxx20,since-cxx17,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors
+// RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-unknown %s -verify=expected,cxx11-20,cxx98-14,since-cxx11,cxx11 -fexceptions -fcxx-exceptions -pedantic-errors
+// RUN: %clang_cc1 -std=c++14 -triple x86_64-unknown-unknown %s -verify=expected,cxx11-20,since-cxx14,cxx98-14,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors
+// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-unknown %s -verify=expected,cxx11-20,since-cxx14,since-cxx17,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors
+// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-unknown %s -verify=expected,cxx11-20,since-cxx14,since-cxx20,since-cxx17,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors
// RUN: %clang_cc1 -std=c++23 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx14,since-cxx20,since-cxx17,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors
// RUN: %clang_cc1 -std=c++2c -triple x86_64-unknown-unknown %s -verify=expected,since-cxx14,since-cxx20,since-cxx17,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors
@@ -349,8 +349,8 @@ namespace dr1684 { // dr1684: 3.6
};
constexpr int f(NonLiteral &) { return 0; }
constexpr int f(NonLiteral) { return 0; }
- // since-cxx11-error at -1 {{constexpr function's 1st parameter type 'NonLiteral' is not a literal type}}
- // since-cxx11-note@#dr1684-struct {{'NonLiteral' is not literal because it is not an aggregate and has no constexpr constructors other than copy or move constructors}}
+ // cxx11-20-error at -1 {{constexpr function with 1st non-literal parameter type 'NonLiteral' is a C++23 extension}}
+ // cxx11-20-note@#dr1684-struct {{'NonLiteral' is not literal because it is not an aggregate and has no constexpr constructors other than copy or move constructors}}
#endif
}
diff --git a/clang/test/CXX/drs/dr6xx.cpp b/clang/test/CXX/drs/dr6xx.cpp
index 78604d480aa1ca..17e32dcc51ac98 100644
--- a/clang/test/CXX/drs/dr6xx.cpp
+++ b/clang/test/CXX/drs/dr6xx.cpp
@@ -1,8 +1,8 @@
// RUN: %clang_cc1 -std=c++98 %s -verify=expected,cxx98-17,cxx98-14,cxx98 -fexceptions -fcxx-exceptions -pedantic-errors -fno-spell-checking
-// RUN: %clang_cc1 -std=c++11 %s -verify=expected,cxx98-17,cxx11-17,cxx98-14,since-cxx11,cxx11 -fexceptions -fcxx-exceptions -pedantic-errors -fno-spell-checking
-// RUN: %clang_cc1 -std=c++14 %s -verify=expected,cxx98-17,cxx11-17,cxx98-14,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors -fno-spell-checking
-// RUN: %clang_cc1 -std=c++17 %s -verify=expected,cxx98-17,cxx11-17,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors -fno-spell-checking
-// RUN: %clang_cc1 -std=c++20 %s -verify=expected,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors -fno-spell-checking
+// RUN: %clang_cc1 -std=c++11 %s -verify=expected,cxx11-20,cxx98-17,cxx11-17,cxx98-14,since-cxx11,cxx11 -fexceptions -fcxx-exceptions -pedantic-errors -fno-spell-checking
+// RUN: %clang_cc1 -std=c++14 %s -verify=expected,cxx11-20,cxx98-17,cxx11-17,cxx98-14,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors -fno-spell-checking
+// RUN: %clang_cc1 -std=c++17 %s -verify=expected,cxx11-20,cxx98-17,cxx11-17,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors -fno-spell-checking
+// RUN: %clang_cc1 -std=c++20 %s -verify=expected,cxx11-20,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors -fno-spell-checking
// RUN: %clang_cc1 -std=c++23 %s -verify=expected,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors -fno-spell-checking
namespace dr600 { // dr600: 2.8
@@ -584,8 +584,8 @@ namespace dr647 { // dr647: 3.1
struct C {
constexpr C(NonLiteral);
constexpr C(NonLiteral, int) {}
- // since-cxx11-error at -1 {{constexpr constructor's 1st parameter type 'NonLiteral' is not a literal type}}
- // since-cxx11-note@#dr647-NonLiteral {{'NonLiteral' is not literal because it is not an aggregate and has no constexpr constructors other than copy or move constructors}}
+ // cxx11-20-error at -1 {{constexpr constructor with 1st non-literal parameter type 'NonLiteral' is a C++23 extension}}
+ // cxx11-20-note@#dr647-NonLiteral {{'NonLiteral' is not literal because it is not an aggregate and has no constexpr constructors other than copy or move constructors}}
constexpr C() try {} catch (...) {}
// cxx11-17-error at -1 {{function try block in constexpr constructor is a C++20 extension}}
// cxx11-error at -2 {{use of this statement in a constexpr constructor is a C++14 extension}}
@@ -609,15 +609,15 @@ namespace dr647 { // dr647: 3.1
d(0) {}
constexpr E(int)
- // since-cxx11-error at -1 {{constexpr constructor never produces a constant expression}}
- // since-cxx11-note@#dr647-int-d {{non-constexpr constructor 'D' cannot be used in a constant expression}}
- // since-cxx11-note@#dr647-D-float-ctor {{declared here}}
+ // cxx11-20-error at -1 {{constexpr constructor that never produces a constant expression}}
+ // cxx11-20-note@#dr647-int-d {{non-constexpr constructor 'D' cannot be used in a constant expression}}
+ // cxx11-20-note@#dr647-D-float-ctor {{declared here}}
: n(0),
d(0.0f) {} // #dr647-int-d
constexpr E(float f)
- // since-cxx11-error at -1 {{never produces a constant expression}}
- // since-cxx11-note@#dr647-float-d {{non-constexpr constructor}}
- // since-cxx11-note@#dr647-D-float-ctor {{declared here}}
+ // cxx11-20-error at -1 {{never produces a constant expression}}
+ // cxx11-20-note@#dr647-float-d {{non-constexpr constructor}}
+ // cxx11-20-note@#dr647-D-float-ctor {{declared here}}
: n(get()),
d(D(0) + f) {} // #dr647-float-d
};
diff --git a/clang/test/CXX/expr/expr.const/p2-0x.cpp b/clang/test/CXX/expr/expr.const/p2-0x.cpp
index e3cd057baba75f..868dacd4415a39 100644
--- a/clang/test/CXX/expr/expr.const/p2-0x.cpp
+++ b/clang/test/CXX/expr/expr.const/p2-0x.cpp
@@ -302,7 +302,7 @@ constexpr float negpi = -pi; // expect no error on unary operator
#if __cplusplus >= 201703L
namespace CompoundAssignment {
-constexpr int rem() { // expected-error {{constexpr function never produces a constant expression}}
+constexpr int rem() { // expected-error {{constexpr function that never produces a constant expression}}
int x = ~__INT_MAX__;
return x%=-1; // cxx20-note {{value 2147483648 is outside the range of representable values of type 'int'}}
}
diff --git a/clang/test/CXX/expr/expr.const/p5-26.cpp b/clang/test/CXX/expr/expr.const/p5-26.cpp
index de2afa71b42669..3624b1e5a3e3df 100644
--- a/clang/test/CXX/expr/expr.const/p5-26.cpp
+++ b/clang/test/CXX/expr/expr.const/p5-26.cpp
@@ -5,11 +5,11 @@
struct S {};
struct T : S {} t;
-consteval void test() { // cxx23-error{{consteval function never produces a constant expression}}
+consteval void test() {
void* a = &t;
const void* b = &t;
volatile void* c = &t;
- (void)static_cast<T*>(a); //cxx23-note {{cast from 'void *' is not allowed in a constant expression in C++ standards before C++2c}}
+ (void)static_cast<T*>(a);
(void)static_cast<const T*>(a);
(void)static_cast<volatile T*>(a);
diff --git a/clang/test/CXX/special/class.copy/p13-0x.cpp b/clang/test/CXX/special/class.copy/p13-0x.cpp
index 16c8a4029cbac6..2f6173be74a2ae 100644
--- a/clang/test/CXX/special/class.copy/p13-0x.cpp
+++ b/clang/test/CXX/special/class.copy/p13-0x.cpp
@@ -125,7 +125,7 @@ namespace Mutable {
mutable A a;
};
struct C {
- constexpr C(const C &) = default; // expected-error {{not constexpr}}
+ constexpr C(const C &) = default; // expected-error {{marked constexpr but never produces a constant expression}}
A a;
};
}
diff --git a/clang/test/PCH/cxx11-constexpr.cpp b/clang/test/PCH/cxx11-constexpr.cpp
index b315b477dbf1c6..22cc53e9152cd6 100644
--- a/clang/test/PCH/cxx11-constexpr.cpp
+++ b/clang/test/PCH/cxx11-constexpr.cpp
@@ -33,7 +33,7 @@ constexpr T plus_seven(T other) {
#else
static_assert(D(4).k == 9, "");
-constexpr int f(C c) { return 0; } // expected-error {{not a literal type}}
+constexpr int f(C c) { return 0; } // expected-error {{non-literal parameter type}}
// expected-note at 16 {{not an aggregate and has no constexpr constructors}}
constexpr B b; // expected-error {{constant expression}} expected-note {{non-constexpr}}
// expected-note at 12 {{here}}
diff --git a/clang/test/SemaCXX/builtin_vectorelements.cpp b/clang/test/SemaCXX/builtin_vectorelements.cpp
index 59ff09ac72e42d..e83d931ee4026f 100644
--- a/clang/test/SemaCXX/builtin_vectorelements.cpp
+++ b/clang/test/SemaCXX/builtin_vectorelements.cpp
@@ -41,7 +41,7 @@ void test_builtin_vectorelements() {
#if defined(__ARM_FEATURE_SVE)
#include <arm_sve.h>
-consteval int consteval_elements() { // expected-error {{consteval function never produces a constant expression}}
+consteval int consteval_elements() { // expected-error {{consteval function that never produces a constant expression}}
return __builtin_vectorelements(svuint64_t); // expected-note {{cannot determine number of elements for sizeless vectors in a constant expression}} // expected-note {{cannot determine number of elements for sizeless vectors in a constant expression}} // expected-note {{cannot determine number of elements for sizeless vectors in a constant expression}}
}
diff --git a/clang/test/SemaCXX/constant-expression-cxx11.cpp b/clang/test/SemaCXX/constant-expression-cxx11.cpp
index 9e2ae07cbe4c9c..a29659301dfd66 100644
--- a/clang/test/SemaCXX/constant-expression-cxx11.cpp
+++ b/clang/test/SemaCXX/constant-expression-cxx11.cpp
@@ -1273,8 +1273,8 @@ namespace PR11595 {
struct B { B(); A& x; };
static_assert(B().x == 3, ""); // expected-error {{constant expression}} expected-note {{non-literal type 'B' cannot be used in a constant expression}}
- constexpr bool f(int k) { // expected-error {{constexpr function never produces a constant expression}}
- return B().x == k; // expected-note {{non-literal type 'B' cannot be used in a constant expression}}
+ constexpr bool f(int k) { // cxx11_20-error {{constexpr function that never produces a constant expression}}
+ return B().x == k; // cxx11_20-note {{non-literal type 'B' cannot be used in a constant expression}}
}
}
@@ -1326,8 +1326,8 @@ namespace ExternConstexpr {
constexpr int g() { return q; } // expected-note {{outside its lifetime}}
constexpr int q = g(); // expected-error {{constant expression}} expected-note {{in call}}
- extern int r; // expected-note {{here}}
- constexpr int h() { return r; } // expected-error {{never produces a constant}} expected-note {{read of non-const}}
+ extern int r; // cxx11_20-note {{here}}
+ constexpr int h() { return r; } // cxx11_20-error {{never produces a constant}} cxx11_20-note {{read of non-const}}
struct S { int n; };
extern const S s;
@@ -1767,7 +1767,7 @@ namespace TLS {
}
namespace Void {
- constexpr void f() { return; } // cxx11-error{{constexpr function's return type 'void' is not a literal type}}
+ constexpr void f() { return; } // cxx11-error{{constexpr function with non-literal return type 'void' is a C++23 extension}}
void assert_failed(const char *msg, const char *file, int line); // expected-note {{declared here}}
#define ASSERT(expr) ((expr) ? static_cast<void>(0) : assert_failed(#expr, __FILE__, __LINE__))
@@ -1906,9 +1906,9 @@ namespace StmtExpr {
});
}
static_assert(g(123) == 15129, "");
- constexpr int h() { // expected-error {{never produces a constant}}
+ constexpr int h() { // cxx11_20-error {{never produces a constant}}
return ({ // expected-warning {{extension}}
- return 0; // expected-note {{not supported}}
+ return 0; // cxx11_20-note {{not supported}}
1;
});
}
@@ -2093,8 +2093,8 @@ namespace ZeroSizeTypes {
// expected-note at -2 {{subtraction of pointers to type 'int[0]' of zero size}}
int arr[5][0];
- constexpr int f() { // expected-error {{never produces a constant expression}}
- return &arr[3] - &arr[0]; // expected-note {{subtraction of pointers to type 'int[0]' of zero size}}
+ constexpr int f() { // cxx11_20-error {{never produces a constant expression}}
+ return &arr[3] - &arr[0]; // cxx11_20-note {{subtraction of pointers to type 'int[0]' of zero size}}
}
}
@@ -2118,8 +2118,8 @@ namespace NeverConstantTwoWays {
// If we see something non-constant but foldable followed by something
// non-constant and not foldable, we want the first diagnostic, not the
// second.
- constexpr int f(int n) { // expected-error {{never produces a constant expression}}
- return (int *)(long)&n == &n ? // expected-note {{reinterpret_cast}}
+ constexpr int f(int n) { // cxx11_20-error {{never produces a constant expression}}
+ return (int *)(long)&n == &n ? // cxx11_20-note {{reinterpret_cast}}
1 / 0 : // expected-warning {{division by zero}}
0;
}
@@ -2316,10 +2316,11 @@ namespace InheritedCtor {
namespace PR28366 {
namespace ns1 {
-void f(char c) { //expected-note2{{declared here}}
+void f(char c) { //expected-note{{declared here}}
+ //cxx11_20-note at -1{{declared here}}
struct X {
- static constexpr char f() { //expected-error{{never produces a constant expression}}
- return c; //expected-error{{reference to local}} expected-note{{function parameter}}
+ static constexpr char f() { // cxx11_20-error {{never produces a constant expression}}
+ return c; //expected-error{{reference to local}} cxx11_20-note{{function parameter}}
}
};
int I = X::f();
diff --git a/clang/test/SemaCXX/constant-expression-cxx14.cpp b/clang/test/SemaCXX/constant-expression-cxx14.cpp
index 273d7ff3a208e2..c829bcc1fc94d4 100644
--- a/clang/test/SemaCXX/constant-expression-cxx14.cpp
+++ b/clang/test/SemaCXX/constant-expression-cxx14.cpp
@@ -44,13 +44,13 @@ constexpr int g(int k) {
return 3 * k3 + 5 * k2 + n * k - 20;
}
static_assert(g(2) == 42, "");
-constexpr int h(int n) { // expected-error {{constexpr function never produces a constant expression}}
- static const int m = n; // expected-note {{control flows through the definition of a static variable}} \
+constexpr int h(int n) { // cxx14_20-error {{constexpr function that never produces a constant expression}}
+ static const int m = n; // cxx14_20-note {{control flows through the definition of a static variable}} \
// cxx14_20-warning {{definition of a static variable in a constexpr function is a C++23 extension}}
return m;
}
-constexpr int i(int n) { // expected-error {{constexpr function never produces a constant expression}}
- thread_local const int m = n; // expected-note {{control flows through the definition of a thread_local variable}} \
+constexpr int i(int n) { // cxx14_20-error {{constexpr function that never produces a constant expression}}
+ thread_local const int m = n; // cxx14_20-note {{control flows through the definition of a thread_local variable}} \
// cxx14_20-warning {{definition of a thread_local variable in a constexpr function is a C++23 extension}}
return m;
}
@@ -68,6 +68,7 @@ constexpr int j(int k) {
}
}
} // expected-note 2{{control reached end of constexpr function}}
+ // cxx23-warning at -1 {{does not return a value in all control paths}}
static_assert(j(0) == -3, "");
static_assert(j(1) == 5, "");
static_assert(j(2), ""); // expected-error {{constant expression}} expected-note {{in call to 'j(2)'}}
@@ -104,10 +105,10 @@ static_assert(l(false) == 5, "");
static_assert(l(true), ""); // expected-error {{constant expression}} expected-note {{in call to 'l(true)'}}
// Potential constant expression checking is still applied where possible.
-constexpr int htonl(int x) { // expected-error {{never produces a constant expression}}
+constexpr int htonl(int x) { // cxx14_20-error {{never produces a constant expression}}
typedef unsigned char uchar;
uchar arr[4] = { uchar(x >> 24), uchar(x >> 16), uchar(x >> 8), uchar(x) };
- return *reinterpret_cast<int*>(arr); // expected-note {{reinterpret_cast is not allowed in a constant expression}}
+ return *reinterpret_cast<int*>(arr); // cxx14_20-note {{reinterpret_cast is not allowed in a constant expression}}
}
constexpr int maybe_htonl(bool isBigEndian, int x) {
@@ -183,7 +184,7 @@ namespace string_assign {
static_assert(!test1(100), "");
static_assert(!test1(101), ""); // expected-error {{constant expression}} expected-note {{in call to 'test1(101)'}}
- constexpr void f() { // expected-error{{constexpr function never produces a constant expression}} expected-note at +2{{assignment to dereferenced one-past-the-end pointer is not allowed in a constant expression}}
+ constexpr void f() { // cxx14_20-error{{constexpr function that never produces a constant expression}} cxx14_20-note at +2{{assignment to dereferenced one-past-the-end pointer is not allowed in a constant expression}}
char foo[10] = { "z" }; // expected-note {{here}}
foo[10] = 'x'; // expected-warning {{past the end}}
}
@@ -207,14 +208,14 @@ namespace array_resize {
namespace potential_const_expr {
constexpr void set(int &n) { n = 1; }
constexpr int div_zero_1() { int z = 0; set(z); return 100 / z; } // no error
- constexpr int div_zero_2() { // expected-error {{never produces a constant expression}}
+ constexpr int div_zero_2() { // cxx14_20-error {{never produces a constant expression}}
int z = 0;
- return 100 / (set(z), 0); // expected-note {{division by zero}}
+ return 100 / (set(z), 0); // cxx14_20-note {{division by zero}}
}
- int n; // expected-note {{declared here}}
- constexpr int ref() { // expected-error {{never produces a constant expression}}
+ int n; // cxx14_20-note {{declared here}}
+ constexpr int ref() { // cxx14_20-error {{never produces a constant expression}}
int &r = n;
- return r; // expected-note {{read of non-const variable 'n'}}
+ return r; // cxx14_20-note {{read of non-const variable 'n'}}
}
}
@@ -846,8 +847,8 @@ namespace StmtExpr {
static_assert(g() == 0, ""); // expected-error {{constant expression}} expected-note {{in call}}
// FIXME: We should handle the void statement expression case.
- constexpr int h() { // expected-error {{never produces a constant}}
- ({ if (true) {} }); // expected-note {{not supported}}
+ constexpr int h() { // cxx14_20-error {{never produces a constant}}
+ ({ if (true) {} }); // cxx14_20-note {{not supported}}
return 0;
}
}
@@ -1043,9 +1044,9 @@ static_assert(sum(Cs) == 'a' + 'b', ""); // expected-error{{not an integral cons
constexpr int S = sum(Cs); // expected-error{{must be initialized by a constant expression}} expected-note{{in call}}
}
-constexpr void PR28739(int n) { // expected-error {{never produces a constant}}
+constexpr void PR28739(int n) { // cxx14_20-error {{never produces a constant}}
int *p = &n; // expected-note {{array 'p' declared here}}
- p += (__int128)(unsigned long)-1; // expected-note {{cannot refer to element 18446744073709551615 of non-array object in a constant expression}}
+ p += (__int128)(unsigned long)-1; // cxx14_20-note {{cannot refer to element 18446744073709551615 of non-array object in a constant expression}}
// expected-warning at -1 {{the pointer incremented by 18446744073709551615 refers past the last possible element for an array in 64-bit address space containing 32-bit (4-byte) elements (max possible 4611686018427387904 elements)}}
}
diff --git a/clang/test/SemaCXX/constant-expression-cxx2b.cpp b/clang/test/SemaCXX/constant-expression-cxx2b.cpp
index 2ee1d48d1cd697..e92a64d830881f 100644
--- a/clang/test/SemaCXX/constant-expression-cxx2b.cpp
+++ b/clang/test/SemaCXX/constant-expression-cxx2b.cpp
@@ -10,35 +10,41 @@ struct Constexpr{};
#if __cplusplus > 202002L
-constexpr int f(int n) { // expected-error {{constexpr function never produces a constant expression}}
+constexpr int f(int n) { // cxx2a-error {{constexpr function that never produces a constant expression}} \
+ // cxx23-warning {{constexpr function that never produces a constant expression is incompatible with C++ standards before C++23}}
static const int m = n; // expected-note {{control flows through the definition of a static variable}} \
// cxx23-warning {{definition of a static variable in a constexpr function is incompatible with C++ standards before C++23}}
return m;
}
-constexpr int g(int n) { // expected-error {{constexpr function never produces a constant expression}}
+constexpr int g(int n) { // cxx2a-error {{constexpr function that never produces a constant expression}} \
+ // cxx23-warning {{constexpr function that never produces a constant expression is incompatible with C++ standards before C++23}}
thread_local const int m = n; // expected-note {{control flows through the definition of a thread_local variable}} \
// cxx23-warning {{definition of a thread_local variable in a constexpr function is incompatible with C++ standards before C++23}}
return m;
}
-constexpr int c_thread_local(int n) { // expected-error {{constexpr function never produces a constant expression}}
+constexpr int c_thread_local(int n) { // cxx2a-error {{constexpr function that never produces a constant expression}} \
+ // cxx23-warning {{constexpr function that never produces a constant expression is incompatible with C++ standards before C++23}}
static _Thread_local int m = 0; // expected-note {{control flows through the definition of a thread_local variable}} \
// cxx23-warning {{definition of a static variable in a constexpr function is incompatible with C++ standards before C++23}}
return m;
}
-constexpr int gnu_thread_local(int n) { // expected-error {{constexpr function never produces a constant expression}}
+constexpr int gnu_thread_local(int n) { // cxx2a-error {{constexpr function that never produces a constant expression}} \
+ // cxx23-warning {{constexpr function that never produces a constant expression is incompatible with C++ standards before C++23}}
static __thread int m = 0; // expected-note {{control flows through the definition of a thread_local variable}} \
// cxx23-warning {{definition of a static variable in a constexpr function is incompatible with C++ standards before C++23}}
return m;
}
-constexpr int h(int n) { // expected-error {{constexpr function never produces a constant expression}}
+constexpr int h(int n) { // cxx2a-error {{constexpr function that never produces a constant expression}} \
+ // cxx23-warning {{constexpr function that never produces a constant expression is incompatible with C++ standards before C++23}}
static const int m = n; // expected-note {{control flows through the definition of a static variable}} \
// cxx23-warning {{definition of a static variable in a constexpr function is incompatible with C++ standards before C++23}}
return &m - &m;
}
-constexpr int i(int n) { // expected-error {{constexpr function never produces a constant expression}}
+constexpr int i(int n) { // cxx2a-error {{constexpr function that never produces a constant expression}} \
+ // cxx23-warning {{constexpr function that never produces a constant expression is incompatible with C++ standards before C++23}}
thread_local const int m = n; // expected-note {{control flows through the definition of a thread_local variable}} \
// cxx23-warning {{definition of a thread_local variable in a constexpr function is incompatible with C++ standards before C++23}}
return &m - &m;
diff --git a/clang/test/SemaCXX/constexpr-function-recovery-crash.cpp b/clang/test/SemaCXX/constexpr-function-recovery-crash.cpp
index 90ee7892b2fc2e..dd0b911fc516b2 100644
--- a/clang/test/SemaCXX/constexpr-function-recovery-crash.cpp
+++ b/clang/test/SemaCXX/constexpr-function-recovery-crash.cpp
@@ -34,13 +34,13 @@ constexpr int test4() {
return 0;
}
-constexpr int test5() { // expected-error {{constexpr function never produce}}
+constexpr int test5() { // expected-error {{constexpr function that never produce}}
for (;; a++); // expected-error {{use of undeclared identifier}} \
expected-note {{constexpr evaluation hit maximum step limit; possible infinite loop?}}
return 1;
}
-constexpr int test6() { // expected-error {{constexpr function never produce}}
+constexpr int test6() { // expected-error {{constexpr function that never produce}}
int n = 0;
switch (n) {
for (;; a++) { // expected-error {{use of undeclared identifier}}
diff --git a/clang/test/SemaCXX/cxx1z-constexpr-lambdas.cpp b/clang/test/SemaCXX/cxx1z-constexpr-lambdas.cpp
index 6a1f48bf7958fd..46c24cc3e5d0b7 100644
--- a/clang/test/SemaCXX/cxx1z-constexpr-lambdas.cpp
+++ b/clang/test/SemaCXX/cxx1z-constexpr-lambdas.cpp
@@ -6,7 +6,7 @@
namespace test_lambda_is_literal {
#ifdef CPP14_AND_EARLIER
-//expected-error at +4{{not a literal type}}
+//expected-error at +4{{non-literal parameter type}}
//expected-note at +2{{lambda closure types are non-literal types before C++17}}
#endif
auto L = [] { };
@@ -19,7 +19,7 @@ namespace test_constexpr_checking {
namespace ns1 {
struct NonLit { ~NonLit(); }; //expected-note{{not literal}}
- auto L = [](NonLit NL) constexpr { }; //expected-error{{not a literal type}}
+ auto L = [](NonLit NL) constexpr { }; //expected-error{{non-literal parameter type}}
} // end ns1
namespace ns2 {
diff --git a/clang/test/SemaCXX/cxx23-invalid-constexpr.cpp b/clang/test/SemaCXX/cxx23-invalid-constexpr.cpp
new file mode 100644
index 00000000000000..69562ebfeaf736
--- /dev/null
+++ b/clang/test/SemaCXX/cxx23-invalid-constexpr.cpp
@@ -0,0 +1,152 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++23 -Wpre-c++23-compat %s
+
+// This test covers modifications made by P2448R2 in C++23 mode.
+
+// Check that there is no error when a constexpr function that never produces a
+// constant expression, but still an error if such function is called from
+// constexpr context.
+constexpr int F(int N) {
+ // expected-warning at -1 {{constexpr function that never produces a constant expression is incompatible with C++ standards before C++23}}
+ double D = 2.0 / 0.0; // expected-note 2{{division by zero}}
+ return 1;
+}
+
+// No warning here since the function can produce a constant expression.
+constexpr int F0(int N) {
+ if (N == 0)
+ double d2 = 2.0 / 0.0; // expected-note {{division by zero}}
+ return 1;
+}
+
+template <typename T>
+constexpr int FT(T N) {
+ double D = 2.0 / 0.0; // expected-note {{division by zero}}
+ return 1;
+}
+
+class NonLiteral {
+// expected-note at -1 3{{'NonLiteral' is not literal because it is not an aggregate and has no constexpr constructors other than copy or move constructors}}
+public:
+ NonLiteral() {} // expected-note 2{{declared here}}
+ ~NonLiteral() {}
+};
+
+constexpr NonLiteral F1() {
+// expected-warning at -1 {{constexpr function with non-literal return type 'NonLiteral' is incompatible with C++ standards before C++23}}
+// expected-warning at -2 {{constexpr function that never produces a constant expression is incompatible with C++ standards before C++23}}
+ return NonLiteral{};
+// expected-note at -1 {{non-constexpr constructor 'NonLiteral' cannot be used in a constant expression}}
+}
+
+constexpr int F2(NonLiteral N) {
+ // expected-warning at -1 {{constexpr function with 1st non-literal parameter type 'NonLiteral' is not compatible with C++ standards before C++23}}
+ return 8;
+}
+
+class Derived : public NonLiteral { // expected-note {{declared here}}
+ constexpr ~Derived() {};
+ // expected-warning at -1{{constexpr destructor is incompatible with C++ standards before C++23 because base class 'NonLiteral' does not have a constexpr destructor}}
+
+};
+
+class Derived1 : public NonLiteral {
+ constexpr Derived1() : NonLiteral () {}
+ // expected-warning at -1{{constexpr constructor that never produces a constant expression is incompatible with C++ standards before C++23}}
+ // expected-note at -2 {{non-constexpr constructor 'NonLiteral' cannot be used in a constant expression}}
+};
+
+
+struct X { // expected-note 2{{'X' is not literal because it is not an aggregate and has no constexpr constructors other than copy or move constructors}}
+ X(); // expected-note 3{{declared here}}
+ X(const X&); // expected-note 2{{declared here}}
+ X(X&&);
+ X& operator=(X&);
+ X& operator=(X&& other);
+ bool operator==(X const&) const; // expected-note 2{{non-constexpr comparison function declared here}}
+};
+
+template <typename T>
+struct Wrapper {
+ constexpr Wrapper() = default;
+ constexpr Wrapper(Wrapper const&) = default;
+ constexpr Wrapper(T const& t) : t(t) { }
+ constexpr Wrapper(Wrapper &&) = default;
+ constexpr X get() const { return t; } // expected-warning {{constexpr function with non-literal return type 'X' is incompatible with C++ standards before C++23}}
+ constexpr bool operator==(Wrapper const&) const = default; // expected-warning {{defaulted definition of equality comparison operator that is declared constexpr but invokes a non-constexpr comparison function is incompatible with C++ standards before C++23}}
+private:
+ T t; // expected-note {{non-constexpr comparison function would be used to compare member 't'}}
+};
+
+struct WrapperNonT {
+ constexpr WrapperNonT() = default; // expected-warning {{defaulted definition of default constructor that marked constexpr but never produces a constant expression is incompatible with C++ standards before C++23}}
+ // expected-note at -1 {{declared here}}
+ constexpr WrapperNonT(WrapperNonT const&) = default; // expected-warning {{defaulted definition of copy constructor that marked constexpr but never produces a constant expression is incompatible with C++ standards before C++23}}
+ constexpr WrapperNonT(X const& t) : t(t) { } // expected-warning {{constexpr constructor that never produces a constant expression is incompatible with C++ standards before C++23}}
+ // expected-note at -1 {{non-constexpr constructor 'X' cannot be used in a constant expression}}
+ constexpr WrapperNonT(WrapperNonT &&) = default; // expected-warning {{defaulted definition of move constructor that marked constexpr but never produces a constant expression is incompatible with C++ standards before C++23}}
+ constexpr WrapperNonT& operator=(WrapperNonT &) = default; // expected-warning {{defaulted definition of copy assignment operator that marked constexpr but never produces a constant expression is incompatible with C++ standards before C++23}}
+ constexpr WrapperNonT& operator=(WrapperNonT&& other) = default; // expected-warning {{defaulted definition of move assignment operator that marked constexpr but never produces a constant expression is incompatible with C++ standards before C++23}}
+ constexpr X get() const { return t; } // expected-warning {{constexpr function with non-literal return type 'X' is incompatible with C++ standards before C++23}}
+ // expected-warning at -1{{constexpr function that never produces a constant expression is incompatible with C++ standards before C++23}}
+ // expected-note at -2 {{non-constexpr constructor 'X' cannot be used in a constant expression}}
+ constexpr bool operator==(WrapperNonT const&) const = default; // expected-warning {{defaulted definition of equality comparison operator that is declared constexpr but invokes a non-constexpr comparison function is incompatible with C++ standards before C++23}}
+private:
+ X t; // expected-note {{non-constexpr comparison function would be used to compare member 't'}}
+};
+
+struct NonDefaultMembers {
+ constexpr NonDefaultMembers() {}; // expected-warning {{constexpr constructor that never produces a constant expression is incompatible with C++ standards before C++23}}
+ // expected-note at -1 {{non-constexpr constructor 'X' cannot be used in a constant expression}}
+ // expected-note at -2 {{non-literal type 'X' cannot be used in a constant expression}}
+ constexpr NonDefaultMembers(NonDefaultMembers const&) {}; // expected-warning {{constexpr constructor that never produces a constant expression is incompatible with C++ standards before C++23}}
+ // expected-note at -1 {{non-constexpr constructor 'X' cannot be used in a constant expression}}
+ constexpr NonDefaultMembers(NonDefaultMembers &&) {}; // expected-warning {{constexpr constructor that never produces a constant expression is incompatible with C++ standards before C++23}}
+ // expected-note at -1 {{non-constexpr constructor 'X' cannot be used in a constant expression}}
+ constexpr NonDefaultMembers& operator=(NonDefaultMembers &other) {this->t = other.t; return *this;}
+ constexpr NonDefaultMembers& operator=(NonDefaultMembers&& other) {this->t = other.t; return *this;}
+ constexpr bool operator==(NonDefaultMembers const& other) const {return this->t == other.t;}
+ X t;
+};
+
+static int Glob = 0; // expected-note {{declared here}}
+class C1 {
+public:
+ constexpr C1() : D(Glob) {}; // expected-warning {{constexpr constructor that never produces a constant expression is incompatible with C++ standards before C++23}}
+ // expected-note at -1 {{read of non-const variable 'Glob' is not allowed in a constant expression}}
+private:
+ int D;
+};
+
+void test() {
+
+ constexpr int A = F(3); // expected-error {{constexpr variable 'A' must be initialized by a constant expression}}
+ // expected-note at -1 {{in call}}
+ F(3);
+ constexpr int B = F0(0); // expected-error {{constexpr variable 'B' must be initialized by a constant expression}}
+ // expected-note at -1 {{in call}}
+ F0(0);
+ constexpr auto C = F1(); // expected-error {{constexpr variable cannot have non-literal type 'const NonLiteral'}}
+ F1();
+ NonLiteral L;
+ constexpr auto D = F2(L); // expected-error {{constexpr variable 'D' must be initialized by a constant expression}}
+ // expected-note at -1 {{non-literal type 'NonLiteral' cannot be used in a constant expression}}
+
+ constexpr auto E = FT(1); // expected-error {{constexpr variable 'E' must be initialized by a constant expression}}
+ // expected-note at -1 {{in call}}
+ F2(L);
+
+ Wrapper<X> x; // expected-note {{requested here}}
+ WrapperNonT x1;
+ NonDefaultMembers x2;
+
+ // TODO produces note with an invalid source location
+ // static_assert((Wrapper<X>(), true));
+
+ static_assert((WrapperNonT(), true)); // expected-error{{expression is not an integral constant expression}}\
+ // expected-note {{non-constexpr constructor 'WrapperNonT' cannot be used in a constant expression}}
+ static_assert((NonDefaultMembers(), true)); // expected-error{{expression is not an integral constant expression}} \
+ // expected-note {{in call to}}
+ constexpr bool FFF = (NonDefaultMembers() == NonDefaultMembers()); // expected-error{{must be initialized by a constant expression}} \
+ // expected-note{{non-literal}}
+
+}
diff --git a/clang/test/SemaCXX/cxx2a-consteval.cpp b/clang/test/SemaCXX/cxx2a-consteval.cpp
index d8482ec53f0ed4..0a3eb29675844b 100644
--- a/clang/test/SemaCXX/cxx2a-consteval.cpp
+++ b/clang/test/SemaCXX/cxx2a-consteval.cpp
@@ -54,7 +54,7 @@ struct C {
struct D {
C c;
- consteval D() = default; // expected-error {{cannot be consteval}}
+ consteval D() = default; // expected-error {{marked consteval but never produces a constant expression}}
consteval ~D() = default; // expected-error {{destructor cannot be declared consteval}}
};
@@ -884,7 +884,7 @@ void func() {
S<Baz, 3> s7;
}
-consteval int aConstevalFunction() { // expected-error {{consteval function never produces a constant expression}}
+consteval int aConstevalFunction() { // expected-error {{consteval function that never produces a constant expression}}
// Defaulted default constructors are implicitly consteval.
S<Bar, 1> s1;
diff --git a/clang/test/SemaCXX/deduced-return-type-cxx14.cpp b/clang/test/SemaCXX/deduced-return-type-cxx14.cpp
index eac9c587869f55..90856b59e999cd 100644
--- a/clang/test/SemaCXX/deduced-return-type-cxx14.cpp
+++ b/clang/test/SemaCXX/deduced-return-type-cxx14.cpp
@@ -1,8 +1,8 @@
// RUN: %clang_cc1 -std=c++23 -fsyntax-only -verify=expected,cxx20_23,cxx23 %s
// RUN: %clang_cc1 -std=c++23 -fsyntax-only -verify=expected,cxx20_23,cxx23 %s -fdelayed-template-parsing -DDELAYED_TEMPLATE_PARSING
-// RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify=expected,cxx14_20,cxx20_23 %s
-// RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify=expected,cxx14_20,cxx20_23 %s -fdelayed-template-parsing -DDELAYED_TEMPLATE_PARSING
+// RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify=expected,cxx14_20,cxx20_23,cxx20 %s
+// RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify=expected,cxx14_20,cxx20_23,cxx20 %s -fdelayed-template-parsing -DDELAYED_TEMPLATE_PARSING
// RUN: %clang_cc1 -std=c++14 -fsyntax-only -verify=expected,cxx14_20,cxx14 %s
// RUN: %clang_cc1 -std=c++14 -fsyntax-only -verify=expected,cxx14_20,cxx14 %s -fdelayed-template-parsing -DDELAYED_TEMPLATE_PARSING
@@ -299,8 +299,8 @@ namespace Constexpr {
constexpr int q = Y<int>().f(); // expected-error {{must be initialized by a constant expression}} expected-note {{in call to 'Y<int>().f()'}}
}
struct NonLiteral { ~NonLiteral(); } nl; // cxx14-note {{user-provided destructor}}
- // cxx20_23-note at -1 {{'NonLiteral' is not literal because its destructor is not constexpr}}
- constexpr auto f2(int n) { return nl; } // expected-error {{return type 'struct NonLiteral' is not a literal type}}
+ // cxx20-note at -1 {{'NonLiteral' is not literal because its destructor is not constexpr}}
+ constexpr auto f2(int n) { return nl; } // cxx14_20-error {{with non-literal return type 'struct NonLiteral' is a C++23 extension}}
}
// It's not really clear whether these are valid, but this matches g++.
diff --git a/clang/test/SemaCXX/ms-constexpr-invalid.cpp b/clang/test/SemaCXX/ms-constexpr-invalid.cpp
index e5bec0c7119b02..94a4d62515ee87 100644
--- a/clang/test/SemaCXX/ms-constexpr-invalid.cpp
+++ b/clang/test/SemaCXX/ms-constexpr-invalid.cpp
@@ -5,7 +5,7 @@
void runtime() {} // expected-note {{declared here}}
-[[msvc::constexpr]] void f0() { runtime(); } // expected-error {{constexpr function never produces a constant expression}} \
+[[msvc::constexpr]] void f0() { runtime(); } // expected-error {{constexpr function that never produces a constant expression}} \
// expected-note {{non-constexpr function 'runtime' cannot be used in a constant expression}}
[[msvc::constexpr]] constexpr void f1() {} // expected-error {{attribute 'msvc::constexpr' cannot be applied to the constexpr function 'f1'}}
#if __cplusplus >= 202202L
@@ -31,13 +31,13 @@ static_assert(f5()); // expected-error {{static assertion expression is not an i
int f6(int x) { [[msvc::constexpr]] return x > 1 ? 1 + f6(x / 2) : 0; } // expected-note {{declared here}} \
// expected-note {{declared here}}
-constexpr bool f7() { [[msvc::constexpr]] return f6(32) == 5; } // expected-error {{constexpr function never produces a constant expression}} \
+constexpr bool f7() { [[msvc::constexpr]] return f6(32) == 5; } // expected-error {{constexpr function that never produces a constant expression}} \
// expected-note {{non-constexpr function 'f6' cannot be used in a constant expression}} \
// expected-note {{non-constexpr function 'f6' cannot be used in a constant expression}}
static_assert(f7()); // expected-error {{static assertion expression is not an integral constant expression}} \
// expected-note {{in call to 'f7()'}}
-constexpr bool f8() { // expected-error {{constexpr function never produces a constant expression}}
+constexpr bool f8() { // expected-error {{constexpr function that never produces a constant expression}}
[[msvc::constexpr]] f4(32); // expected-error {{'constexpr' attribute only applies to functions and return statements}} \
// expected-note {{non-constexpr function 'f4' cannot be used in a constant expression}} \
// expected-note {{non-constexpr function 'f4' cannot be used in a constant expression}}
diff --git a/clang/test/SemaCXX/ms-constexpr.cpp b/clang/test/SemaCXX/ms-constexpr.cpp
index 79f71a34cb7d84..6bf2dec91250c9 100644
--- a/clang/test/SemaCXX/ms-constexpr.cpp
+++ b/clang/test/SemaCXX/ms-constexpr.cpp
@@ -29,7 +29,7 @@ static_assert(test_get_msconstexpr_true());
struct S2 {
[[msvc::constexpr]] S2() {}
[[msvc::constexpr]] bool value() { return true; }
- static constexpr bool check() { [[msvc::constexpr]] return S2{}.value(); } // expected-error {{constexpr function never produces a constant expression}} \
+ static constexpr bool check() { [[msvc::constexpr]] return S2{}.value(); } // expected-error {{constexpr function that never produces a constant expression}} \
// expected-note {{non-literal type 'S2' cannot be used in a constant expression}} \
// expected-note {{non-literal type 'S2' cannot be used in a constant expression}}
};
diff --git a/clang/test/SemaCXX/sizeless-1.cpp b/clang/test/SemaCXX/sizeless-1.cpp
index 368a3eeb6955bd..1300f9960ca751 100644
--- a/clang/test/SemaCXX/sizeless-1.cpp
+++ b/clang/test/SemaCXX/sizeless-1.cpp
@@ -303,7 +303,7 @@ struct constructible_from_sizeless {
void with_default(svint8_t = svint8_t());
#if __cplusplus >= 201103L
-constexpr int ce_taking_int8(svint8_t) { return 1; } // expected-error {{constexpr function's 1st parameter type 'svint8_t' (aka '__SVInt8_t') is not a literal type}}
+constexpr int ce_taking_int8(svint8_t) { return 1; } // expected-error {{constexpr function with 1st non-literal parameter type 'svint8_t' (aka '__SVInt8_t') is a C++23 extension}}
#endif
#if __cplusplus < 201703L
diff --git a/clang/test/SemaOpenCLCXX/addrspace-constructors.clcpp b/clang/test/SemaOpenCLCXX/addrspace-constructors.clcpp
index 1b97484767b1a5..23102b8ab88725 100644
--- a/clang/test/SemaOpenCLCXX/addrspace-constructors.clcpp
+++ b/clang/test/SemaOpenCLCXX/addrspace-constructors.clcpp
@@ -54,5 +54,5 @@ struct Z {
struct W {
int w;
- constexpr W() __constant = default; // expected-error {{defaulted definition of default constructor is not constexpr}}
+ constexpr W() __constant = default; // expected-error {{defaulted definition of default constructor that marked constexpr but never produces a constant expression is a C++23 extension}}
};
diff --git a/clang/www/cxx_status.html b/clang/www/cxx_status.html
index 197726f3aa3eee..0bec14c62765b7 100755
--- a/clang/www/cxx_status.html
+++ b/clang/www/cxx_status.html
@@ -356,14 +356,7 @@ <h2 id="cxx23">C++23 implementation status</h2>
<tr>
<td>Relaxing some constexpr restrictions</td>
<td><a href="https://wg21.link/P2448R2">P2448R2</a></td>
- <td class="partial" align="center">
- <details><summary>Clang 17 (Partial)</summary>
- We do not support outside of defaulted special memeber functions the change that constexpr functions no
- longer have to be constexpr compatible but rather support a less restricted requirements for constexpr
- functions. Which include allowing non-literal types as return values and parameters, allow calling of
- non-constexpr functions and constructors.
- </details></td>
- </td>
+ <td class="full" align="center">Clang 18</td>
</tr>
<tr>
<td>Using unknown pointers and references in constant expressions</td>
>From 8527b69506cc08bf45d20ad86e891b4b5b3663ea Mon Sep 17 00:00:00 2001
From: "Podchishchaeva, Mariya" <mariya.podchishchaeva at intel.com>
Date: Wed, 17 Jan 2024 03:59:28 -0800
Subject: [PATCH 02/11] Make sure feature is actually backported
---
clang/docs/LanguageExtensions.rst | 1 +
clang/docs/ReleaseNotes.rst | 3 +-
clang/lib/Sema/SemaDeclCXX.cpp | 3 +-
clang/test/CXX/drs/dr13xx.cpp | 9 --
.../test/SemaCXX/cxx23-invalid-constexpr.cpp | 116 ++++++++++--------
5 files changed, 69 insertions(+), 63 deletions(-)
diff --git a/clang/docs/LanguageExtensions.rst b/clang/docs/LanguageExtensions.rst
index c1420079f75118..eb83faebfebba1 100644
--- a/clang/docs/LanguageExtensions.rst
+++ b/clang/docs/LanguageExtensions.rst
@@ -1486,6 +1486,7 @@ Conditional ``explicit`` __cpp_conditional_explicit C++20
``if consteval`` __cpp_if_consteval C++23 C++20
``static operator()`` __cpp_static_call_operator C++23 C++03
Attributes on Lambda-Expressions C++23 C++11
+Relaxing some constexpr restrictions __cpp_constexpr C++23 C++11
-------------------------------------- -------------------------------- ------------- -------------
Designated initializers (N494) C99 C89
Array & element qualification (N2607) C23 C89
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 23342a6a7256d8..ba005ccbc471e8 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -165,7 +165,8 @@ C++23 Feature Support
- Added a separate warning to warn the use of attributes on lambdas as a C++23 extension
in previous language versions: ``-Wc++23-lambda-attributes``.
-- Implemented `P2448R2: Relaxing some constexpr restrictions <https://wg21.link/P2448R2>`_.
+- Implemented `P2448R2: Relaxing some constexpr restrictions <https://wg21.link/P2448R2>`_
+ as a conforming extension.
C++2c Feature Support
^^^^^^^^^^^^^^^^^^^^^
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index aa49dc73e157bf..f4affcd262b23a 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -7873,6 +7873,7 @@ bool Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD,
<< CSM;
for (const auto &I : RD->vbases())
Diag(I.getBeginLoc(), diag::note_constexpr_virtual_base_here);
+ HadError = true;
} else {
Diag(MD->getBeginLoc(),
getLangOpts().CPlusPlus23
@@ -7881,8 +7882,6 @@ bool Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD,
<< CSM << MD->isConsteval();
}
// FIXME: Explain why the special member can't be constexpr.
- if (!getLangOpts().CPlusPlus23)
- HadError = true;
}
if (First) {
diff --git a/clang/test/CXX/drs/dr13xx.cpp b/clang/test/CXX/drs/dr13xx.cpp
index be656c4468eaeb..f025eff3a48c2d 100644
--- a/clang/test/CXX/drs/dr13xx.cpp
+++ b/clang/test/CXX/drs/dr13xx.cpp
@@ -433,18 +433,9 @@ namespace dr1359 { // dr1359: 3.5
constexpr A a = A();
constexpr B b = B();
- // cxx11-17-error at -1 {{no matching constructor for initialization of 'B'}}
- // cxx11-17-note@#dr1359-B {{candidate constructor (the implicit copy constructor) not viable: requires 1 argument, but 0 were provided}}
- // cxx11-17-note@#dr1359-B {{candidate constructor (the implicit move constructor) not viable: requires 1 argument, but 0 were provided}}
constexpr C c = C();
- // cxx11-17-error at -1 {{no matching constructor for initialization of 'C'}}
- // cxx11-17-note@#dr1359-C {{candidate constructor (the implicit copy constructor) not viable: requires 1 argument, but 0 were provided}}
- // cxx11-17-note@#dr1359-C {{candidate constructor (the implicit move constructor) not viable: requires 1 argument, but 0 were provided}}
constexpr X x = X();
constexpr Y y = Y();
- // cxx11-17-error at -1 {{no matching constructor for initialization of 'Y'}}
- // cxx11-17-note@#dr1359-Y {{candidate constructor (the implicit copy constructor) not viable: requires 1 argument, but 0 were provided}}
- // cxx11-17-note@#dr1359-Y {{candidate constructor (the implicit move constructor) not viable: requires 1 argument, but 0 were provided}}
#endif
}
diff --git a/clang/test/SemaCXX/cxx23-invalid-constexpr.cpp b/clang/test/SemaCXX/cxx23-invalid-constexpr.cpp
index 69562ebfeaf736..355495689ccd83 100644
--- a/clang/test/SemaCXX/cxx23-invalid-constexpr.cpp
+++ b/clang/test/SemaCXX/cxx23-invalid-constexpr.cpp
@@ -1,13 +1,18 @@
-// RUN: %clang_cc1 -fsyntax-only -verify -std=c++23 -Wpre-c++23-compat %s
+// RUN: %clang_cc1 -fsyntax-only -verify=expected,cxx23 -std=c++23 -Wpre-c++23-compat %s
+// RUN: %clang_cc1 -fsyntax-only -verify=expected -std=c++20 -Wno-c++23-extensions -Wno-invalid-constexpr %s
+// RUN: %clang_cc1 -fsyntax-only -verify=expected,precxx20 -std=c++17 -Wno-c++23-extensions -Wno-invalid-constexpr %s
+// RUN: %clang_cc1 -fsyntax-only -verify=expected,precxx20 -std=c++14 -Wno-c++23-extensions -Wno-invalid-constexpr %s
+// RUN: %clang_cc1 -fsyntax-only -verify=expected,precxx20,cxx11 -std=c++11 -Wno-c++14-extensions -Wno-c++23-extensions -Wno-invalid-constexpr -Wno-constexpr-not-const %s
-// This test covers modifications made by P2448R2 in C++23 mode.
+// This test covers modifications made by P2448R2.
// Check that there is no error when a constexpr function that never produces a
// constant expression, but still an error if such function is called from
// constexpr context.
constexpr int F(int N) {
- // expected-warning at -1 {{constexpr function that never produces a constant expression is incompatible with C++ standards before C++23}}
- double D = 2.0 / 0.0; // expected-note 2{{division by zero}}
+ // cxx23-warning at -1 {{constexpr function that never produces a constant expression is incompatible with C++ standards before C++23}}
+ double D = 2.0 / 0.0; // cxx23-note {{division by zero}} \
+ // expected-note {{division by zero}}
return 1;
}
@@ -25,44 +30,44 @@ constexpr int FT(T N) {
}
class NonLiteral {
-// expected-note at -1 3{{'NonLiteral' is not literal because it is not an aggregate and has no constexpr constructors other than copy or move constructors}}
+// cxx23-note at -1 3{{'NonLiteral' is not literal because it is not an aggregate and has no constexpr constructors other than copy or move constructors}}
public:
- NonLiteral() {} // expected-note 2{{declared here}}
+ NonLiteral() {} // cxx23-note 2{{declared here}}
~NonLiteral() {}
};
constexpr NonLiteral F1() {
-// expected-warning at -1 {{constexpr function with non-literal return type 'NonLiteral' is incompatible with C++ standards before C++23}}
-// expected-warning at -2 {{constexpr function that never produces a constant expression is incompatible with C++ standards before C++23}}
+// cxx23-warning at -1 {{constexpr function with non-literal return type 'NonLiteral' is incompatible with C++ standards before C++23}}
+// cxx23-warning at -2 {{constexpr function that never produces a constant expression is incompatible with C++ standards before C++23}}
return NonLiteral{};
-// expected-note at -1 {{non-constexpr constructor 'NonLiteral' cannot be used in a constant expression}}
+// cxx23-note at -1 {{non-constexpr constructor 'NonLiteral' cannot be used in a constant expression}}
}
constexpr int F2(NonLiteral N) {
- // expected-warning at -1 {{constexpr function with 1st non-literal parameter type 'NonLiteral' is not compatible with C++ standards before C++23}}
+ // cxx23-warning at -1 {{constexpr function with 1st non-literal parameter type 'NonLiteral' is not compatible with C++ standards before C++23}}
return 8;
}
-class Derived : public NonLiteral { // expected-note {{declared here}}
- constexpr ~Derived() {};
- // expected-warning at -1{{constexpr destructor is incompatible with C++ standards before C++23 because base class 'NonLiteral' does not have a constexpr destructor}}
+class Derived : public NonLiteral { // cxx23-note {{declared here}}
+ constexpr ~Derived() {}; // precxx20-error {{destructor cannot be declared constexpr}}
+ // cxx23-warning at -1{{constexpr destructor is incompatible with C++ standards before C++23 because base class 'NonLiteral' does not have a constexpr destructor}}
};
class Derived1 : public NonLiteral {
constexpr Derived1() : NonLiteral () {}
- // expected-warning at -1{{constexpr constructor that never produces a constant expression is incompatible with C++ standards before C++23}}
- // expected-note at -2 {{non-constexpr constructor 'NonLiteral' cannot be used in a constant expression}}
+ // cxx23-warning at -1{{constexpr constructor that never produces a constant expression is incompatible with C++ standards before C++23}}
+ // cxx23-note at -2 {{non-constexpr constructor 'NonLiteral' cannot be used in a constant expression}}
};
-struct X { // expected-note 2{{'X' is not literal because it is not an aggregate and has no constexpr constructors other than copy or move constructors}}
- X(); // expected-note 3{{declared here}}
- X(const X&); // expected-note 2{{declared here}}
+struct X { // cxx23-note 2{{'X' is not literal because it is not an aggregate and has no constexpr constructors other than copy or move constructors}}
+ X(); // cxx23-note 3{{declared here}}
+ X(const X&); // cxx23-note 2{{declared here}}
X(X&&);
- X& operator=(X&);
- X& operator=(X&& other);
- bool operator==(X const&) const; // expected-note 2{{non-constexpr comparison function declared here}}
+ X& operator=(X&); // cxx11-note 2{{not viable: 'this' argument has type 'const X', but method is not marked const}}
+ X& operator=(X&& other); // cxx11-note 2{{not viable: 'this' argument has type 'const X', but method is not marked const}}
+ bool operator==(X const&) const; // cxx23-note 2{{non-constexpr comparison function declared here}}
};
template <typename T>
@@ -71,48 +76,56 @@ struct Wrapper {
constexpr Wrapper(Wrapper const&) = default;
constexpr Wrapper(T const& t) : t(t) { }
constexpr Wrapper(Wrapper &&) = default;
- constexpr X get() const { return t; } // expected-warning {{constexpr function with non-literal return type 'X' is incompatible with C++ standards before C++23}}
- constexpr bool operator==(Wrapper const&) const = default; // expected-warning {{defaulted definition of equality comparison operator that is declared constexpr but invokes a non-constexpr comparison function is incompatible with C++ standards before C++23}}
+ constexpr X get() const { return t; } // cxx23-warning {{constexpr function with non-literal return type 'X' is incompatible with C++ standards before C++23}}
+ constexpr bool operator==(Wrapper const&) const = default; // cxx23-warning {{defaulted definition of equality comparison operator that is declared constexpr but invokes a non-constexpr comparison function is incompatible with C++ standards before C++23}}
+ // precxx20-warning at -1 2{{defaulted comparison operators are a C++20 extension}}
private:
- T t; // expected-note {{non-constexpr comparison function would be used to compare member 't'}}
+ T t; // cxx23-note {{non-constexpr comparison function would be used to compare member 't'}}
};
struct WrapperNonT {
- constexpr WrapperNonT() = default; // expected-warning {{defaulted definition of default constructor that marked constexpr but never produces a constant expression is incompatible with C++ standards before C++23}}
+ constexpr WrapperNonT() = default; // cxx23-warning {{defaulted definition of default constructor that marked constexpr but never produces a constant expression is incompatible with C++ standards before C++23}}
// expected-note at -1 {{declared here}}
- constexpr WrapperNonT(WrapperNonT const&) = default; // expected-warning {{defaulted definition of copy constructor that marked constexpr but never produces a constant expression is incompatible with C++ standards before C++23}}
- constexpr WrapperNonT(X const& t) : t(t) { } // expected-warning {{constexpr constructor that never produces a constant expression is incompatible with C++ standards before C++23}}
- // expected-note at -1 {{non-constexpr constructor 'X' cannot be used in a constant expression}}
- constexpr WrapperNonT(WrapperNonT &&) = default; // expected-warning {{defaulted definition of move constructor that marked constexpr but never produces a constant expression is incompatible with C++ standards before C++23}}
- constexpr WrapperNonT& operator=(WrapperNonT &) = default; // expected-warning {{defaulted definition of copy assignment operator that marked constexpr but never produces a constant expression is incompatible with C++ standards before C++23}}
- constexpr WrapperNonT& operator=(WrapperNonT&& other) = default; // expected-warning {{defaulted definition of move assignment operator that marked constexpr but never produces a constant expression is incompatible with C++ standards before C++23}}
- constexpr X get() const { return t; } // expected-warning {{constexpr function with non-literal return type 'X' is incompatible with C++ standards before C++23}}
- // expected-warning at -1{{constexpr function that never produces a constant expression is incompatible with C++ standards before C++23}}
- // expected-note at -2 {{non-constexpr constructor 'X' cannot be used in a constant expression}}
- constexpr bool operator==(WrapperNonT const&) const = default; // expected-warning {{defaulted definition of equality comparison operator that is declared constexpr but invokes a non-constexpr comparison function is incompatible with C++ standards before C++23}}
+ constexpr WrapperNonT(WrapperNonT const&) = default; // cxx23-warning {{defaulted definition of copy constructor that marked constexpr but never produces a constant expression is incompatible with C++ standards before C++23}}
+ constexpr WrapperNonT(X const& t) : t(t) { } // cxx23-warning {{constexpr constructor that never produces a constant expression is incompatible with C++ standards before C++23}}
+ // cxx23-note at -1 {{non-constexpr constructor 'X' cannot be used in a constant expression}}
+ constexpr WrapperNonT(WrapperNonT &&) = default; // cxx23-warning {{defaulted definition of move constructor that marked constexpr but never produces a constant expression is incompatible with C++ standards before C++23}}
+ constexpr WrapperNonT& operator=(WrapperNonT &) = default; // cxx23-warning {{defaulted definition of copy assignment operator that marked constexpr but never produces a constant expression is incompatible with C++ standards before C++23}}
+ // cxx11-error at -1 {{an explicitly-defaulted copy assignment operator may not have 'const', 'constexpr' or 'volatile' qualifiers}}
+ constexpr WrapperNonT& operator=(WrapperNonT&& other) = default; // cxx23-warning {{defaulted definition of move assignment operator that marked constexpr but never produces a constant expression is incompatible with C++ standards before C++23}}
+ // cxx11-error at -1 {{an explicitly-defaulted move assignment operator may not have 'const', 'constexpr' or 'volatile' qualifiers}}
+ constexpr X get() const { return t; } // cxx23-warning {{constexpr function with non-literal return type 'X' is incompatible with C++ standards before C++23}}
+ // cxx23-warning at -1{{constexpr function that never produces a constant expression is incompatible with C++ standards before C++23}}
+ // cxx23-note at -2 {{non-constexpr constructor 'X' cannot be used in a constant expression}}
+ constexpr bool operator==(WrapperNonT const&) const = default; // cxx23-warning {{defaulted definition of equality comparison operator that is declared constexpr but invokes a non-constexpr comparison function is incompatible with C++ standards before C++23}}
+ // precxx20-warning at -1 {{defaulted comparison operators are a C++20 extension}}
private:
- X t; // expected-note {{non-constexpr comparison function would be used to compare member 't'}}
+ X t; // cxx23-note {{non-constexpr comparison function would be used to compare member 't'}}
};
struct NonDefaultMembers {
- constexpr NonDefaultMembers() {}; // expected-warning {{constexpr constructor that never produces a constant expression is incompatible with C++ standards before C++23}}
- // expected-note at -1 {{non-constexpr constructor 'X' cannot be used in a constant expression}}
+ constexpr NonDefaultMembers() {}; // cxx23-warning {{constexpr constructor that never produces a constant expression is incompatible with C++ standards before C++23}}
+ // cxx23-note at -1 {{non-constexpr constructor 'X' cannot be used in a constant expression}}
// expected-note at -2 {{non-literal type 'X' cannot be used in a constant expression}}
- constexpr NonDefaultMembers(NonDefaultMembers const&) {}; // expected-warning {{constexpr constructor that never produces a constant expression is incompatible with C++ standards before C++23}}
- // expected-note at -1 {{non-constexpr constructor 'X' cannot be used in a constant expression}}
- constexpr NonDefaultMembers(NonDefaultMembers &&) {}; // expected-warning {{constexpr constructor that never produces a constant expression is incompatible with C++ standards before C++23}}
- // expected-note at -1 {{non-constexpr constructor 'X' cannot be used in a constant expression}}
+ constexpr NonDefaultMembers(NonDefaultMembers const&) {}; // cxx23-warning {{constexpr constructor that never produces a constant expression is incompatible with C++ standards before C++23}}
+ // cxx23-note at -1 {{non-constexpr constructor 'X' cannot be used in a constant expression}}
+ constexpr NonDefaultMembers(NonDefaultMembers &&) {}; // cxx23-warning {{constexpr constructor that never produces a constant expression is incompatible with C++ standards before C++23}}
+ // cxx23-note at -1 {{non-constexpr constructor 'X' cannot be used in a constant expression}}
constexpr NonDefaultMembers& operator=(NonDefaultMembers &other) {this->t = other.t; return *this;}
+ // cxx11-error at -1 {{no viable overloaded '='}}
+ // cxx11-error at -2 {{binding reference of type 'NonDefaultMembers' to value of type 'const NonDefaultMembers' drops 'const' qualifier}}
constexpr NonDefaultMembers& operator=(NonDefaultMembers&& other) {this->t = other.t; return *this;}
+ // cxx11-error at -1 {{no viable overloaded '='}}
+ // cxx11-error at -2 {{binding reference of type 'NonDefaultMembers' to value of type 'const NonDefaultMembers' drops 'const' qualifier}}
constexpr bool operator==(NonDefaultMembers const& other) const {return this->t == other.t;}
X t;
};
-static int Glob = 0; // expected-note {{declared here}}
+static int Glob = 0; // cxx23-note {{declared here}}
class C1 {
public:
- constexpr C1() : D(Glob) {}; // expected-warning {{constexpr constructor that never produces a constant expression is incompatible with C++ standards before C++23}}
- // expected-note at -1 {{read of non-const variable 'Glob' is not allowed in a constant expression}}
+ constexpr C1() : D(Glob) {}; // cxx23-warning {{constexpr constructor that never produces a constant expression is incompatible with C++ standards before C++23}}
+ // cxx23-note at -1 {{read of non-const variable 'Glob' is not allowed in a constant expression}}
private:
int D;
};
@@ -125,26 +138,27 @@ void test() {
constexpr int B = F0(0); // expected-error {{constexpr variable 'B' must be initialized by a constant expression}}
// expected-note at -1 {{in call}}
F0(0);
- constexpr auto C = F1(); // expected-error {{constexpr variable cannot have non-literal type 'const NonLiteral'}}
+ constexpr auto C = F1(); // cxx23-error {{constexpr variable cannot have non-literal type 'const NonLiteral'}}
F1();
NonLiteral L;
- constexpr auto D = F2(L); // expected-error {{constexpr variable 'D' must be initialized by a constant expression}}
- // expected-note at -1 {{non-literal type 'NonLiteral' cannot be used in a constant expression}}
+ constexpr auto D = F2(L); // cxx23-error {{constexpr variable 'D' must be initialized by a constant expression}}
+ // cxx23-note at -1 {{non-literal type 'NonLiteral' cannot be used in a constant expression}}
constexpr auto E = FT(1); // expected-error {{constexpr variable 'E' must be initialized by a constant expression}}
// expected-note at -1 {{in call}}
F2(L);
- Wrapper<X> x; // expected-note {{requested here}}
+ Wrapper<X> x; // cxx23-note {{requested here}}
+ // precxx20-note at -1 {{requested here}}
WrapperNonT x1;
NonDefaultMembers x2;
// TODO produces note with an invalid source location
// static_assert((Wrapper<X>(), true));
- static_assert((WrapperNonT(), true)); // expected-error{{expression is not an integral constant expression}}\
+ static_assert((WrapperNonT(), true),""); // expected-error{{expression is not an integral constant expression}}\
// expected-note {{non-constexpr constructor 'WrapperNonT' cannot be used in a constant expression}}
- static_assert((NonDefaultMembers(), true)); // expected-error{{expression is not an integral constant expression}} \
+ static_assert((NonDefaultMembers(), true),""); // expected-error{{expression is not an integral constant expression}} \
// expected-note {{in call to}}
constexpr bool FFF = (NonDefaultMembers() == NonDefaultMembers()); // expected-error{{must be initialized by a constant expression}} \
// expected-note{{non-literal}}
>From 8ca1f210d51c584783948c2d0ea708ba7bf8796e Mon Sep 17 00:00:00 2001
From: "Podchishchaeva, Mariya" <mariya.podchishchaeva at intel.com>
Date: Wed, 17 Jan 2024 04:14:27 -0800
Subject: [PATCH 03/11] Minor changes applied
---
clang/lib/Sema/SemaDeclCXX.cpp | 20 +++++---------------
clang/test/CXX/drs/dr13xx.cpp | 4 ++--
clang/test/CXX/drs/dr16xx.cpp | 2 +-
clang/test/CXX/drs/dr6xx.cpp | 2 +-
4 files changed, 9 insertions(+), 19 deletions(-)
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index f4affcd262b23a..a9c1bcf5db7267 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -1731,11 +1731,7 @@ static bool CheckConstexprDestructorSubobjects(Sema &SemaRef,
SemaRef.Diag(Loc, diag::note_constexpr_dtor_subobject)
<< !FD << (FD ? FD->getDeclName() : DeclarationName()) << T;
}
-
- if (SemaRef.getLangOpts().CPlusPlus23)
- return true;
-
- return false;
+ return !!SemaRef.getLangOpts().CPlusPlus23;
};
const CXXRecordDecl *RD = DD->getParent();
@@ -1767,11 +1763,8 @@ static bool CheckConstexprParameterTypes(Sema &SemaRef,
? diag::warn_cxx23_compat_constexpr_non_literal_param
: diag::ext_constexpr_non_literal_param,
ArgIndex + 1, PD->getSourceRange(), isa<CXXConstructorDecl>(FD),
- FD->isConsteval())) {
- if (SemaRef.getLangOpts().CPlusPlus23)
- return true;
- return false;
- }
+ FD->isConsteval()))
+ return SemaRef.getLangOpts().CPlusPlus23;
}
return true;
}
@@ -1785,11 +1778,8 @@ static bool CheckConstexprReturnType(Sema &SemaRef, const FunctionDecl *FD,
SemaRef.getLangOpts().CPlusPlus23
? diag::warn_cxx23_compat_constexpr_non_literal_return
: diag::ext_constexpr_non_literal_return,
- FD->isConsteval())) {
- if (SemaRef.getLangOpts().CPlusPlus23)
- return true;
- return false;
- }
+ FD->isConsteval()))
+ return SemaRef.getLangOpts().CPlusPlus23;
return true;
}
diff --git a/clang/test/CXX/drs/dr13xx.cpp b/clang/test/CXX/drs/dr13xx.cpp
index f025eff3a48c2d..f2457194e8d443 100644
--- a/clang/test/CXX/drs/dr13xx.cpp
+++ b/clang/test/CXX/drs/dr13xx.cpp
@@ -411,10 +411,10 @@ namespace dr1358 { // dr1358: 3.1
int member;
constexpr B(NonLit u) : member(u) {}
// cxx11-20-error at -1 {{constexpr constructor with 1st non-literal parameter type 'NonLit' is a C++23 extension}}
- // cxx11-20-note@#dr1358-NonLit {{'NonLit' is not literal because it is not an aggregate and has no constexpr constructors other than copy or move constructors}}
+ // cxx11-20-note@#dr1358-NonLit {{'NonLit' is not literal because it is not an aggregate and has no constexpr constructors other than copy or move constructors}}
constexpr NonLit f(NonLit u) const { return NonLit(); }
// cxx11-20-error at -1 {{constexpr function with non-literal return type 'NonLit' is a C++23 extension}}
- // cxx11-20-note@#dr1358-NonLit {{'NonLit' is not literal because it is not an aggregate and has no constexpr constructors other than copy or move constructors}}
+ // cxx11-20-note@#dr1358-NonLit {{'NonLit' is not literal because it is not an aggregate and has no constexpr constructors other than copy or move constructors}}
};
#endif
}
diff --git a/clang/test/CXX/drs/dr16xx.cpp b/clang/test/CXX/drs/dr16xx.cpp
index 1cf7bb840507ff..c00e1f483c123a 100644
--- a/clang/test/CXX/drs/dr16xx.cpp
+++ b/clang/test/CXX/drs/dr16xx.cpp
@@ -350,7 +350,7 @@ namespace dr1684 { // dr1684: 3.6
constexpr int f(NonLiteral &) { return 0; }
constexpr int f(NonLiteral) { return 0; }
// cxx11-20-error at -1 {{constexpr function with 1st non-literal parameter type 'NonLiteral' is a C++23 extension}}
- // cxx11-20-note@#dr1684-struct {{'NonLiteral' is not literal because it is not an aggregate and has no constexpr constructors other than copy or move constructors}}
+ // cxx11-20-note@#dr1684-struct {{'NonLiteral' is not literal because it is not an aggregate and has no constexpr constructors other than copy or move constructors}}
#endif
}
diff --git a/clang/test/CXX/drs/dr6xx.cpp b/clang/test/CXX/drs/dr6xx.cpp
index 17e32dcc51ac98..7d4ab70a32adb7 100644
--- a/clang/test/CXX/drs/dr6xx.cpp
+++ b/clang/test/CXX/drs/dr6xx.cpp
@@ -585,7 +585,7 @@ namespace dr647 { // dr647: 3.1
constexpr C(NonLiteral);
constexpr C(NonLiteral, int) {}
// cxx11-20-error at -1 {{constexpr constructor with 1st non-literal parameter type 'NonLiteral' is a C++23 extension}}
- // cxx11-20-note@#dr647-NonLiteral {{'NonLiteral' is not literal because it is not an aggregate and has no constexpr constructors other than copy or move constructors}}
+ // cxx11-20-note@#dr647-NonLiteral {{'NonLiteral' is not literal because it is not an aggregate and has no constexpr constructors other than copy or move constructors}}
constexpr C() try {} catch (...) {}
// cxx11-17-error at -1 {{function try block in constexpr constructor is a C++20 extension}}
// cxx11-error at -2 {{use of this statement in a constexpr constructor is a C++14 extension}}
>From b365e48a36550d68dda83515b790e3beaf6d7893 Mon Sep 17 00:00:00 2001
From: "Podchishchaeva, Mariya" <mariya.podchishchaeva at intel.com>
Date: Wed, 17 Jan 2024 04:21:12 -0800
Subject: [PATCH 04/11] Clang 18 is unreleased
---
clang/www/cxx_status.html | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/clang/www/cxx_status.html b/clang/www/cxx_status.html
index 0bec14c62765b7..b60d0329854765 100755
--- a/clang/www/cxx_status.html
+++ b/clang/www/cxx_status.html
@@ -356,7 +356,7 @@ <h2 id="cxx23">C++23 implementation status</h2>
<tr>
<td>Relaxing some constexpr restrictions</td>
<td><a href="https://wg21.link/P2448R2">P2448R2</a></td>
- <td class="full" align="center">Clang 18</td>
+ <td class="unreleased" align="center">Clang 18</td>
</tr>
<tr>
<td>Using unknown pointers and references in constant expressions</td>
>From 1a35417ff41c818bc721fa0aaa944d2eca708849 Mon Sep 17 00:00:00 2001
From: "Podchishchaeva, Mariya" <mariya.podchishchaeva at intel.com>
Date: Wed, 17 Jan 2024 04:55:43 -0800
Subject: [PATCH 05/11] Make format happy
---
clang/lib/Sema/SemaDeclCXX.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 6fadca805b35ac..5adc825c03f06e 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -7871,7 +7871,7 @@ bool Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD,
: diag::ext_incorrect_defaulted_constexpr)
<< CSM << MD->isConsteval();
}
- // FIXME: Explain why the special member can't be constexpr.
+ // FIXME: Explain why the special member can't be constexpr.
}
if (First) {
>From 0a0253fb66a74503b5f91962accdc0c7cdbe7a9a Mon Sep 17 00:00:00 2001
From: "Podchishchaeva, Mariya" <mariya.podchishchaeva at intel.com>
Date: Thu, 18 Jan 2024 06:35:08 -0800
Subject: [PATCH 06/11] Fix diagnostic concern
---
clang/include/clang/Basic/DiagnosticSemaKinds.td | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index af92472bf9e6ae..0be20d46369648 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -2769,7 +2769,7 @@ def ext_constexpr_dtor_subobject : ExtWarn<
"destructor cannot be declared %sub{select_constexpr_spec_kind}0 before C++23 because "
"%select{data member %2|base class %3}1 does not have a "
"constexpr destructor">, InGroup<CXX23>, DefaultError;
-def warn_cxx23_compat_constexpr_dtor_subobject : ExtWarn<
+def warn_cxx23_compat_constexpr_dtor_subobject : Warning<
"%sub{select_constexpr_spec_kind}0 destructor is incompatible with C++ standards before C++23 because "
"%select{data member %2|base class %3}1 does not have a "
"constexpr destructor">, InGroup<CXXPre23Compat>, DefaultIgnore;
>From 28a3fcd825a1c761c7c62774431997c6b9a57293 Mon Sep 17 00:00:00 2001
From: "Podchishchaeva, Mariya" <mariya.podchishchaeva at intel.com>
Date: Tue, 23 Jan 2024 08:51:13 -0800
Subject: [PATCH 07/11] Make defaulted special members actually constexpr
---
.../clang/Basic/DiagnosticSemaKinds.td | 3 -
clang/lib/AST/DeclCXX.cpp | 11 ++--
clang/lib/Sema/SemaDeclCXX.cpp | 61 ++++++++++---------
clang/test/CXX/drs/dr15xx.cpp | 21 ++++---
clang/test/CXX/drs/dr16xx.cpp | 8 +--
.../SemaCXX/constant-expression-cxx11.cpp | 11 ++--
.../test/SemaCXX/cxx23-invalid-constexpr.cpp | 22 +++----
7 files changed, 70 insertions(+), 67 deletions(-)
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 0be20d46369648..a0e203a9bccd64 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -9565,9 +9565,6 @@ def err_defaulted_copy_assign_not_ref : Error<
def ext_incorrect_defaulted_constexpr : ExtWarn<
"defaulted definition of %sub{select_special_member_kind}0 that marked %select{constexpr|consteval}1 "
"but never produces a constant expression is a C++23 extension">, InGroup<CXX23>, DefaultError;
-def warn_cxx23_compat_incorrect_defaulted_constexpr : Warning<
- "defaulted definition of %sub{select_special_member_kind}0 that marked %select{constexpr|consteval}1 "
- "but never produces a constant expression is incompatible with C++ standards before C++23">, InGroup<CXXPre23Compat>, DefaultIgnore;
def err_incorrect_defaulted_constexpr_with_vb: Error<
"%sub{select_special_member_kind}0 cannot be 'constexpr' in a class with virtual base class">;
def warn_defaulted_method_deleted : Warning<
diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp
index 117e802dae2d9d..1da9fa4bbb4eb1 100644
--- a/clang/lib/AST/DeclCXX.cpp
+++ b/clang/lib/AST/DeclCXX.cpp
@@ -400,10 +400,11 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases,
// C++11 [class.ctor]p6:
// If that user-written default constructor would satisfy the
- // requirements of a constexpr constructor, the implicitly-defined
+ // requirements of a constexpr constructor/function(C++23), the implicitly-defined
// default constructor is constexpr.
if (!BaseClassDecl->hasConstexprDefaultConstructor())
- data().DefaultedDefaultConstructorIsConstexpr = false;
+ data().DefaultedDefaultConstructorIsConstexpr =
+ C.getLangOpts().CPlusPlus23;
// C++1z [class.copy]p8:
// The implicitly-declared copy constructor for a class X will have
@@ -548,7 +549,8 @@ void CXXRecordDecl::addedClassSubobject(CXXRecordDecl *Subobj) {
// -- for every subobject of class type or (possibly multi-dimensional)
// array thereof, that class type shall have a constexpr destructor
if (!Subobj->hasConstexprDestructor())
- data().DefaultedDestructorIsConstexpr = false;
+ data().DefaultedDestructorIsConstexpr =
+ getASTContext().getLangOpts().CPlusPlus23;
// C++20 [temp.param]p7:
// A structural type is [...] a literal class type [for which] the types
@@ -1297,7 +1299,8 @@ void CXXRecordDecl::addedMember(Decl *D) {
!FieldRec->hasConstexprDefaultConstructor() && !isUnion())
// The standard requires any in-class initializer to be a constant
// expression. We consider this to be a defect.
- data().DefaultedDefaultConstructorIsConstexpr = false;
+ data().DefaultedDefaultConstructorIsConstexpr =
+ Context.getLangOpts().CPlusPlus23;
// C++11 [class.copy]p8:
// The implicitly-declared copy constructor for a class X will have
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 14712ae34cae42..85cf291519c0ea 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -1873,8 +1873,9 @@ bool Sema::CheckConstexprFunctionDefinition(const FunctionDecl *NewFD,
if (auto *Dtor = dyn_cast<CXXDestructorDecl>(NewFD)) {
// A destructor can be constexpr only if the defaulted destructor could be;
// we don't need to check the members and bases if we already know they all
- // have constexpr destructors.
- if (!Dtor->getParent()->defaultedDestructorIsConstexpr()) {
+ // have constexpr destructors. (removed in C++23)
+ if (!getLangOpts().CPlusPlus23 &&
+ !Dtor->getParent()->defaultedDestructorIsConstexpr()) {
if (Kind == CheckConstexprKind::CheckValid)
return false;
if (!CheckConstexprDestructorSubobjects(*this, Dtor, Kind))
@@ -7535,21 +7536,23 @@ static bool defaultedSpecialMemberIsConstexpr(
// C++1y [class.copy]p26:
// -- [the class] is a literal type, and
- if (!Ctor && !ClassDecl->isLiteral())
+ if (!Ctor && !ClassDecl->isLiteral() && !S.getLangOpts().CPlusPlus23)
return false;
// -- every constructor involved in initializing [...] base class
// sub-objects shall be a constexpr constructor;
// -- the assignment operator selected to copy/move each direct base
// class is a constexpr function, and
- for (const auto &B : ClassDecl->bases()) {
- const RecordType *BaseType = B.getType()->getAs<RecordType>();
- if (!BaseType)
- continue;
- CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(BaseType->getDecl());
- if (!specialMemberIsConstexpr(S, BaseClassDecl, CSM, 0, ConstArg,
- InheritedCtor, Inherited))
- return false;
+ if (!S.getLangOpts().CPlusPlus23) {
+ for (const auto &B : ClassDecl->bases()) {
+ const RecordType *BaseType = B.getType()->getAs<RecordType>();
+ if (!BaseType)
+ continue;
+ CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(BaseType->getDecl());
+ if (!specialMemberIsConstexpr(S, BaseClassDecl, CSM, 0, ConstArg,
+ InheritedCtor, Inherited))
+ return false;
+ }
}
// -- every constructor involved in initializing non-static data members
@@ -7559,20 +7562,22 @@ static bool defaultedSpecialMemberIsConstexpr(
// -- for each non-static data member of X that is of class type (or array
// thereof), the assignment operator selected to copy/move that member is
// a constexpr function
- for (const auto *F : ClassDecl->fields()) {
- if (F->isInvalidDecl())
- continue;
- if (CSM == Sema::CXXDefaultConstructor && F->hasInClassInitializer())
- continue;
- QualType BaseType = S.Context.getBaseElementType(F->getType());
- if (const RecordType *RecordTy = BaseType->getAs<RecordType>()) {
- CXXRecordDecl *FieldRecDecl = cast<CXXRecordDecl>(RecordTy->getDecl());
- if (!specialMemberIsConstexpr(S, FieldRecDecl, CSM,
- BaseType.getCVRQualifiers(),
- ConstArg && !F->isMutable()))
+ if (!S.getLangOpts().CPlusPlus23) {
+ for (const auto *F : ClassDecl->fields()) {
+ if (F->isInvalidDecl())
+ continue;
+ if (CSM == Sema::CXXDefaultConstructor && F->hasInClassInitializer())
+ continue;
+ QualType BaseType = S.Context.getBaseElementType(F->getType());
+ if (const RecordType *RecordTy = BaseType->getAs<RecordType>()) {
+ CXXRecordDecl *FieldRecDecl = cast<CXXRecordDecl>(RecordTy->getDecl());
+ if (!specialMemberIsConstexpr(S, FieldRecDecl, CSM,
+ BaseType.getCVRQualifiers(),
+ ConstArg && !F->isMutable()))
+ return false;
+ } else if (CSM == Sema::CXXDefaultConstructor) {
return false;
- } else if (CSM == Sema::CXXDefaultConstructor) {
- return false;
+ }
}
}
@@ -7864,10 +7869,7 @@ bool Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD,
Diag(I.getBeginLoc(), diag::note_constexpr_virtual_base_here);
HadError = true;
} else {
- Diag(MD->getBeginLoc(),
- getLangOpts().CPlusPlus23
- ? diag::warn_cxx23_compat_incorrect_defaulted_constexpr
- : diag::ext_incorrect_defaulted_constexpr)
+ Diag(MD->getBeginLoc(), diag::ext_incorrect_defaulted_constexpr)
<< CSM << MD->isConsteval();
}
// FIXME: Explain why the special member can't be constexpr.
@@ -9121,7 +9123,8 @@ bool Sema::CheckExplicitlyDefaultedComparison(Scope *S, FunctionDecl *FD,
// declaration, it is implicitly considered to be constexpr.
// FIXME: Only applying this to the first declaration seems problematic, as
// simple reorderings can affect the meaning of the program.
- if (First && !FD->isConstexpr() && Info.Constexpr)
+ if ((First && !FD->isConstexpr() && Info.Constexpr) ||
+ getLangOpts().CPlusPlus23)
FD->setConstexprKind(ConstexprSpecKind::Constexpr);
// C++2a [except.spec]p3:
diff --git a/clang/test/CXX/drs/dr15xx.cpp b/clang/test/CXX/drs/dr15xx.cpp
index 3d4050a5713f92..c79e1b9fdafe01 100644
--- a/clang/test/CXX/drs/dr15xx.cpp
+++ b/clang/test/CXX/drs/dr15xx.cpp
@@ -1,10 +1,10 @@
// RUN: %clang_cc1 -std=c++98 -triple x86_64-unknown-unknown %s -verify=expected -fexceptions -fcxx-exceptions -pedantic-errors
-// RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx11,cxx11-14 -fexceptions -fcxx-exceptions -pedantic-errors
-// RUN: %clang_cc1 -std=c++14 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx11,cxx11-14,cxx14-17 -fexceptions -fcxx-exceptions -pedantic-errors
-// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx11,since-cxx17 -fexceptions -fcxx-exceptions -pedantic-errors
-// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx20,since-cxx11,since-cxx17 -fexceptions -fcxx-exceptions -pedantic-errors
-// RUN: %clang_cc1 -std=c++23 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx20,since-cxx11,since-cxx17 -fexceptions -fcxx-exceptions -pedantic-errors
-// RUN: %clang_cc1 -std=c++2c -triple x86_64-unknown-unknown %s -verify=expected,since-cxx20,since-cxx11,since-cxx17 -fexceptions -fcxx-exceptions -pedantic-errors
+// RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-unknown %s -verify=expected,cxx11-20,since-cxx11,cxx11-14 -fexceptions -fcxx-exceptions -pedantic-errors
+// RUN: %clang_cc1 -std=c++14 -triple x86_64-unknown-unknown %s -verify=expected,cxx11-20,since-cxx11,cxx11-14,cxx14-17 -fexceptions -fcxx-exceptions -pedantic-errors
+// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-unknown %s -verify=expected,cxx11-20,since-cxx11,since-cxx17 -fexceptions -fcxx-exceptions -pedantic-errors
+// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-unknown %s -verify=expected,cxx11-20,since-cxx20,since-cxx11,since-cxx17 -fexceptions -fcxx-exceptions -pedantic-errors
+// RUN: %clang_cc1 -std=c++23 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx23,since-cxx20,since-cxx11,since-cxx17 -fexceptions -fcxx-exceptions -pedantic-errors
+// RUN: %clang_cc1 -std=c++2c -triple x86_64-unknown-unknown %s -verify=expected,since-cxx23,since-cxx20,since-cxx11,since-cxx17 -fexceptions -fcxx-exceptions -pedantic-errors
namespace dr1512 { // dr1512: 4
void f(char *p) {
@@ -368,7 +368,7 @@ namespace dr1573 { // dr1573: 3.9
B b(1, 'x', 4.0, "hello"); // ok
// inherited constructor is effectively constexpr if the user-written constructor would be
- struct C { C(); constexpr C(int) {} };
+ struct C { C(); constexpr C(int) {} }; // #dr1573-C
struct D : C { using C::C; };
constexpr D d = D(0); // ok
struct E : C { using C::C; A a; }; // #dr1573-E
@@ -381,8 +381,11 @@ namespace dr1573 { // dr1573: 3.9
struct F : C { using C::C; C c; }; // #dr1573-F
constexpr F f = F(0);
// since-cxx11-error at -1 {{constexpr variable 'f' must be initialized by a constant expression}}
- // since-cxx11-note at -2 {{constructor inherited from base class 'C' cannot be used in a constant expression; derived class cannot be implicitly initialized}}
- // since-cxx11-note@#dr1573-F {{declared here}}
+ // cxx11-20-note at -2 {{constructor inherited from base class 'C' cannot be used in a constant expression; derived class cannot be implicitly initialized}}
+ // since-cxx23-note at -3 {{in implicit initialization for inherited constructor of 'F'}}
+ // since-cxx23-note@#dr1573-F {{non-constexpr constructor 'C' cannot be used in a constant expression}}
+ // cxx11-20-note@#dr1573-F {{declared here}}
+ // since-cxx23-note@#dr1573-C {{declared here}}
// inherited constructor is effectively deleted if the user-written constructor would be
struct G { G(int); };
diff --git a/clang/test/CXX/drs/dr16xx.cpp b/clang/test/CXX/drs/dr16xx.cpp
index 3f4f75df5b25dd..1dfe092d7b288e 100644
--- a/clang/test/CXX/drs/dr16xx.cpp
+++ b/clang/test/CXX/drs/dr16xx.cpp
@@ -3,8 +3,8 @@
// RUN: %clang_cc1 -std=c++14 -triple x86_64-unknown-unknown %s -verify=expected,cxx11-20,since-cxx14,cxx98-14,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors
// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-unknown %s -verify=expected,cxx11-20,since-cxx14,since-cxx17,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors
// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-unknown %s -verify=expected,cxx11-20,since-cxx14,since-cxx20,since-cxx17,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors
-// RUN: %clang_cc1 -std=c++23 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx14,since-cxx20,since-cxx17,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors
-// RUN: %clang_cc1 -std=c++2c -triple x86_64-unknown-unknown %s -verify=expected,since-cxx14,since-cxx20,since-cxx17,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors
+// RUN: %clang_cc1 -std=c++23 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx23,since-cxx14,since-cxx20,since-cxx17,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors
+// RUN: %clang_cc1 -std=c++2c -triple x86_64-unknown-unknown %s -verify=expected,since-cxx23,since-cxx14,since-cxx20,since-cxx17,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors
#if __cplusplus == 199711L
#define static_assert(...) __extension__ _Static_assert(__VA_ARGS__)
@@ -255,12 +255,12 @@ namespace dr1658 { // dr1658: 5
struct A { A(A&); };
struct B : virtual A { virtual void f() = 0; };
struct C : virtual A { virtual void f(); };
- struct D : A { virtual void f() = 0; };
+ struct D : A { virtual void f() = 0; }; // since-cxx23-note {{previous declaration is here}}
struct X {
friend B::B(const B&) throw();
friend C::C(C&);
- friend D::D(D&);
+ friend D::D(D&); // since-cxx23-error {{non-constexpr declaration of 'D' follows constexpr declaration}}
};
}
diff --git a/clang/test/SemaCXX/constant-expression-cxx11.cpp b/clang/test/SemaCXX/constant-expression-cxx11.cpp
index a29659301dfd66..43e9434dee4557 100644
--- a/clang/test/SemaCXX/constant-expression-cxx11.cpp
+++ b/clang/test/SemaCXX/constant-expression-cxx11.cpp
@@ -1678,7 +1678,7 @@ namespace ImplicitConstexpr {
struct R { constexpr R() noexcept; constexpr R(const R&) noexcept; constexpr R(R&&) noexcept; ~R() noexcept; };
struct S { R r; }; // expected-note 3{{here}}
struct T { T(const T&) noexcept; T(T &&) noexcept; ~T() noexcept; };
- struct U { T t; }; // expected-note 3{{here}}
+ struct U { T t; }; // cxx11_20-note 3{{here}}
static_assert(!__is_literal_type(Q), "");
static_assert(!__is_literal_type(R), "");
static_assert(!__is_literal_type(S), "");
@@ -1691,9 +1691,9 @@ namespace ImplicitConstexpr {
friend S::S() noexcept; // expected-error {{follows constexpr}}
friend S::S(S&&) noexcept; // expected-error {{follows constexpr}}
friend S::S(const S&) noexcept; // expected-error {{follows constexpr}}
- friend constexpr U::U() noexcept; // expected-error {{follows non-constexpr}}
- friend constexpr U::U(U&&) noexcept; // expected-error {{follows non-constexpr}}
- friend constexpr U::U(const U&) noexcept; // expected-error {{follows non-constexpr}}
+ friend constexpr U::U() noexcept; // cxx11_20-error {{follows non-constexpr}}
+ friend constexpr U::U(U&&) noexcept; // cxx11_20-error {{follows non-constexpr}}
+ friend constexpr U::U(const U&) noexcept; // cxx11_20-error {{follows non-constexpr}}
};
}
@@ -2277,7 +2277,8 @@ namespace InheritedCtor {
struct A { constexpr A(int) {} };
struct B : A { int n; using A::A; }; // expected-note {{here}}
- constexpr B b(0); // expected-error {{constant expression}} expected-note {{derived class}}
+ constexpr B b(0); // expected-error {{constant expression}} cxx11_20-note {{derived class}}\
+ // cxx23-note {{not initialized}}
struct C : A { using A::A; struct { union { int n, m = 0; }; union { int a = 0; }; int k = 0; }; struct {}; union {}; }; // expected-warning 6{{}}
constexpr C c(0);
diff --git a/clang/test/SemaCXX/cxx23-invalid-constexpr.cpp b/clang/test/SemaCXX/cxx23-invalid-constexpr.cpp
index 355495689ccd83..da22d11a5dcbf4 100644
--- a/clang/test/SemaCXX/cxx23-invalid-constexpr.cpp
+++ b/clang/test/SemaCXX/cxx23-invalid-constexpr.cpp
@@ -48,10 +48,8 @@ constexpr int F2(NonLiteral N) {
return 8;
}
-class Derived : public NonLiteral { // cxx23-note {{declared here}}
+class Derived : public NonLiteral {
constexpr ~Derived() {}; // precxx20-error {{destructor cannot be declared constexpr}}
- // cxx23-warning at -1{{constexpr destructor is incompatible with C++ standards before C++23 because base class 'NonLiteral' does not have a constexpr destructor}}
-
};
class Derived1 : public NonLiteral {
@@ -84,15 +82,14 @@ struct Wrapper {
};
struct WrapperNonT {
- constexpr WrapperNonT() = default; // cxx23-warning {{defaulted definition of default constructor that marked constexpr but never produces a constant expression is incompatible with C++ standards before C++23}}
- // expected-note at -1 {{declared here}}
- constexpr WrapperNonT(WrapperNonT const&) = default; // cxx23-warning {{defaulted definition of copy constructor that marked constexpr but never produces a constant expression is incompatible with C++ standards before C++23}}
+ constexpr WrapperNonT() = default;
+ constexpr WrapperNonT(WrapperNonT const&) = default;
constexpr WrapperNonT(X const& t) : t(t) { } // cxx23-warning {{constexpr constructor that never produces a constant expression is incompatible with C++ standards before C++23}}
// cxx23-note at -1 {{non-constexpr constructor 'X' cannot be used in a constant expression}}
- constexpr WrapperNonT(WrapperNonT &&) = default; // cxx23-warning {{defaulted definition of move constructor that marked constexpr but never produces a constant expression is incompatible with C++ standards before C++23}}
- constexpr WrapperNonT& operator=(WrapperNonT &) = default; // cxx23-warning {{defaulted definition of copy assignment operator that marked constexpr but never produces a constant expression is incompatible with C++ standards before C++23}}
+ constexpr WrapperNonT(WrapperNonT &&) = default;
+ constexpr WrapperNonT& operator=(WrapperNonT &) = default;
// cxx11-error at -1 {{an explicitly-defaulted copy assignment operator may not have 'const', 'constexpr' or 'volatile' qualifiers}}
- constexpr WrapperNonT& operator=(WrapperNonT&& other) = default; // cxx23-warning {{defaulted definition of move assignment operator that marked constexpr but never produces a constant expression is incompatible with C++ standards before C++23}}
+ constexpr WrapperNonT& operator=(WrapperNonT&& other) = default;
// cxx11-error at -1 {{an explicitly-defaulted move assignment operator may not have 'const', 'constexpr' or 'volatile' qualifiers}}
constexpr X get() const { return t; } // cxx23-warning {{constexpr function with non-literal return type 'X' is incompatible with C++ standards before C++23}}
// cxx23-warning at -1{{constexpr function that never produces a constant expression is incompatible with C++ standards before C++23}}
@@ -153,11 +150,10 @@ void test() {
WrapperNonT x1;
NonDefaultMembers x2;
- // TODO produces note with an invalid source location
+ // TODO these produce notes with an invalid source location.
// static_assert((Wrapper<X>(), true));
-
- static_assert((WrapperNonT(), true),""); // expected-error{{expression is not an integral constant expression}}\
- // expected-note {{non-constexpr constructor 'WrapperNonT' cannot be used in a constant expression}}
+ // static_assert((WrapperNonT(), true),"");
+
static_assert((NonDefaultMembers(), true),""); // expected-error{{expression is not an integral constant expression}} \
// expected-note {{in call to}}
constexpr bool FFF = (NonDefaultMembers() == NonDefaultMembers()); // expected-error{{must be initialized by a constant expression}} \
>From 26fdf352330e173543a973a38882dbd59332c9d9 Mon Sep 17 00:00:00 2001
From: "Podchishchaeva, Mariya" <mariya.podchishchaeva at intel.com>
Date: Wed, 24 Jan 2024 01:02:22 -0800
Subject: [PATCH 08/11] Fix test after merge
---
clang/test/SemaCXX/deduced-return-type-cxx14.cpp | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/clang/test/SemaCXX/deduced-return-type-cxx14.cpp b/clang/test/SemaCXX/deduced-return-type-cxx14.cpp
index 8aa6f6bb05f3aa..367dfc85e229d9 100644
--- a/clang/test/SemaCXX/deduced-return-type-cxx14.cpp
+++ b/clang/test/SemaCXX/deduced-return-type-cxx14.cpp
@@ -1,8 +1,8 @@
// RUN: %clang_cc1 -std=c++23 -fsyntax-only -verify=expected,since-cxx20,since-cxx14,cxx20_23,cxx23 %s
// RUN: %clang_cc1 -std=c++23 -fsyntax-only -verify=expected,since-cxx20,since-cxx14,cxx20_23,cxx23 %s -fdelayed-template-parsing -DDELAYED_TEMPLATE_PARSING
-// RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify=expected,since-cxx20,since-cxx14,cxx14_20,cxx20_23 %s
-// RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify=expected,since-cxx20,since-cxx14,cxx14_20,cxx20_23 %s -fdelayed-template-parsing -DDELAYED_TEMPLATE_PARSING
+// RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify=expected,cxx20,since-cxx20,since-cxx14,cxx14_20,cxx20_23 %s
+// RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify=expected,cxx20,since-cxx20,since-cxx14,cxx14_20,cxx20_23 %s -fdelayed-template-parsing -DDELAYED_TEMPLATE_PARSING
// RUN: %clang_cc1 -std=c++14 -fsyntax-only -verify=expected,since-cxx14,cxx14_20,cxx14 %s
// RUN: %clang_cc1 -std=c++14 -fsyntax-only -verify=expected,since-cxx14,cxx14_20,cxx14 %s -fdelayed-template-parsing -DDELAYED_TEMPLATE_PARSING
>From 96a8f7f2f37b22cd63102b1134cceccc2cc9a734 Mon Sep 17 00:00:00 2001
From: "Podchishchaeva, Mariya" <mariya.podchishchaeva at intel.com>
Date: Wed, 24 Jan 2024 08:39:02 -0800
Subject: [PATCH 09/11] Format
---
clang/lib/AST/DeclCXX.cpp | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp
index 1da9fa4bbb4eb1..63acd10d34b9ee 100644
--- a/clang/lib/AST/DeclCXX.cpp
+++ b/clang/lib/AST/DeclCXX.cpp
@@ -400,8 +400,8 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases,
// C++11 [class.ctor]p6:
// If that user-written default constructor would satisfy the
- // requirements of a constexpr constructor/function(C++23), the implicitly-defined
- // default constructor is constexpr.
+ // requirements of a constexpr constructor/function(C++23), the
+ // implicitly-defined default constructor is constexpr.
if (!BaseClassDecl->hasConstexprDefaultConstructor())
data().DefaultedDefaultConstructorIsConstexpr =
C.getLangOpts().CPlusPlus23;
>From 1ed37bf0d0c060d390b81f77bf31eba5cc6dc685 Mon Sep 17 00:00:00 2001
From: "Podchishchaeva, Mariya" <mariya.podchishchaeva at intel.com>
Date: Tue, 5 Mar 2024 05:45:05 -0800
Subject: [PATCH 10/11] Fix test
---
clang/test/AST/Interp/cxx17.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/clang/test/AST/Interp/cxx17.cpp b/clang/test/AST/Interp/cxx17.cpp
index 5e38d1a5887007..b063a9e71828ce 100644
--- a/clang/test/AST/Interp/cxx17.cpp
+++ b/clang/test/AST/Interp/cxx17.cpp
@@ -83,7 +83,7 @@ static_assert(b() == 11);
/// The diagnostics between the two interpreters used to be different here.
struct S { int a; };
-constexpr S getS() { // both-error {{constexpr function never produces a constant expression}}
+constexpr S getS() { // both-error {{constexpr function that never produces a constant expression}}
(void)(1/0); // both-note 2{{division by zero}} \
// both-warning {{division by zero}}
return S{12};
>From 5b8e47672c8ddbbcbfcfacb245c4db16aab273ba Mon Sep 17 00:00:00 2001
From: "Podchishchaeva, Mariya" <mariya.podchishchaeva at intel.com>
Date: Tue, 5 Mar 2024 07:11:30 -0800
Subject: [PATCH 11/11] Roll back to C++23 only implementation
---
clang/docs/LanguageExtensions.rst | 1 -
clang/docs/ReleaseNotes.rst | 3 +-
.../clang/Basic/DiagnosticSemaKinds.td | 26 +++++++--------
clang/lib/Sema/SemaDeclCXX.cpp | 21 ++++++------
.../test/SemaCXX/cxx23-invalid-constexpr.cpp | 32 ++++++++++++++++---
5 files changed, 52 insertions(+), 31 deletions(-)
diff --git a/clang/docs/LanguageExtensions.rst b/clang/docs/LanguageExtensions.rst
index 898c2cb4bb721e..bcd69198eafdbe 100644
--- a/clang/docs/LanguageExtensions.rst
+++ b/clang/docs/LanguageExtensions.rst
@@ -1487,7 +1487,6 @@ Conditional ``explicit`` __cpp_conditional_explicit C++20
``if consteval`` __cpp_if_consteval C++23 C++20
``static operator()`` __cpp_static_call_operator C++23 C++03
Attributes on Lambda-Expressions C++23 C++11
-Relaxing some constexpr restrictions __cpp_constexpr C++23 C++11
-------------------------------------- -------------------------------- ------------- -------------
Designated initializers (N494) C99 C89
Array & element qualification (N2607) C23 C89
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 28b9159c91127b..58348eaa8a4cb1 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -92,8 +92,7 @@ C++23 Feature Support
- Implemented `P2718R0: Lifetime extension in range-based for loops <https://wg21.link/P2718R0>`_. Also
materialize temporary object which is a prvalue in discarded-value expression.
-- Implemented `P2448R2: Relaxing some constexpr restrictions <https://wg21.link/P2448R2>`_
- as a conforming extension.
+- Implemented `P2448R2: Relaxing some constexpr restrictions <https://wg21.link/P2448R2>`_.
C++2c Feature Support
^^^^^^^^^^^^^^^^^^^^^
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index c50d0d7aae9613..8cd89df2b4f7df 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -2773,11 +2773,11 @@ def err_constexpr_tag : Error<
"cannot be marked %sub{select_constexpr_spec_kind}1">;
def err_constexpr_dtor : Error<
"destructor cannot be declared %sub{select_constexpr_spec_kind}0">;
-def ext_constexpr_dtor_subobject : ExtWarn<
+def err_constexpr_dtor_subobject : Error<
"destructor cannot be declared %sub{select_constexpr_spec_kind}0 before C++23 because "
"%select{data member %2|base class %3}1 does not have a "
- "constexpr destructor">, InGroup<CXX23>, DefaultError;
-def warn_cxx23_compat_constexpr_dtor_subobject : Warning<
+ "constexpr destructor">;
+def warn_cxx20_compat_constexpr_dtor_subobject : Warning<
"%sub{select_constexpr_spec_kind}0 destructor is incompatible with C++ standards before C++23 because "
"%select{data member %2|base class %3}1 does not have a "
"constexpr destructor">, InGroup<CXXPre23Compat>, DefaultIgnore;
@@ -2812,13 +2812,13 @@ def note_non_literal_incomplete : Note<
def note_non_literal_virtual_base : Note<"%select{struct|interface|class}0 "
"with virtual base %plural{1:class|:classes}1 is not a literal type">;
def note_constexpr_virtual_base_here : Note<"virtual base class declared here">;
-def ext_constexpr_non_literal_return : ExtWarn<
- "%select{constexpr|consteval}0 function with non-literal return type %1 is a C++23 extension">, InGroup<CXX23>, DefaultError;
-def warn_cxx23_compat_constexpr_non_literal_return : Warning<
+def err_constexpr_non_literal_return : Error<
+ "%select{constexpr|consteval}0 function with non-literal return type %1 is a C++23 extension">;
+def warn_cxx20_compat_constexpr_non_literal_return : Warning<
"%select{constexpr|consteval}0 function with non-literal return type %1 is incompatible with C++ standards before C++23">, InGroup<CXXPre23Compat>, DefaultIgnore;
-def ext_constexpr_non_literal_param : ExtWarn<
- "%select{constexpr|consteval}2 %select{function|constructor}1 with %ordinal0 non-literal parameter type %3 is a C++23 extension">, InGroup<CXX23>, DefaultError;
-def warn_cxx23_compat_constexpr_non_literal_param : Warning<
+def err_constexpr_non_literal_param : Error<
+ "%select{constexpr|consteval}2 %select{function|constructor}1 with %ordinal0 non-literal parameter type %3 is a C++23 extension">;
+def warn_cxx20_compat_constexpr_non_literal_param : Warning<
"%select{constexpr|consteval}2 %select{function|constructor}1 with %ordinal0 non-literal parameter type %3 is not compatible with C++ standards before C++23">, InGroup<CXXPre23Compat>, DefaultIgnore;
def err_constexpr_body_invalid_stmt : Error<
"statement not allowed in %select{constexpr|consteval}1 %select{function|constructor}0">;
@@ -2882,7 +2882,7 @@ def warn_cxx17_compat_constexpr_local_var_no_init : Warning<
def ext_constexpr_function_never_constant_expr : ExtWarn<
"%select{constexpr|consteval}1 %select{function|constructor}0 that never produces a "
"constant expression is a C++23 extension">, InGroup<DiagGroup<"invalid-constexpr">>, DefaultError;
-def warn_cxx23_compat_constexpr_function_never_constant_expr : Warning<
+def warn_cxx20_compat_constexpr_function_never_constant_expr : Warning<
"%select{constexpr|consteval}1 %select{function|constructor}0 that never produces a "
"constant expression is incompatible with C++ standards before C++23">, InGroup<CXXPre23Compat>, DefaultIgnore;
def err_attr_cond_never_constant_expr : Error<
@@ -9600,9 +9600,9 @@ def err_defaulted_special_member_copy_const_param : Error<
def err_defaulted_copy_assign_not_ref : Error<
"the parameter for an explicitly-defaulted copy assignment operator must be an "
"lvalue reference type">;
-def ext_incorrect_defaulted_constexpr : ExtWarn<
+def err_incorrect_defaulted_constexpr : Error<
"defaulted definition of %sub{select_special_member_kind}0 that marked %select{constexpr|consteval}1 "
- "but never produces a constant expression is a C++23 extension">, InGroup<CXX23>, DefaultError;
+ "but never produces a constant expression is a C++23 extension">;
def err_incorrect_defaulted_constexpr_with_vb: Error<
"%sub{select_special_member_kind}0 cannot be 'constexpr' in a class with virtual base class">;
def warn_defaulted_method_deleted : Warning<
@@ -9722,7 +9722,7 @@ def ext_defaulted_comparison_constexpr_mismatch : Extension<
"%select{|for which the corresponding implicit 'operator==' }0 "
"invokes a non-constexpr comparison function is a C++23 extension">,
InGroup<DiagGroup<"c++23-default-comp-relaxed-constexpr">>;
-def warn_cxx23_compat_defaulted_comparison_constexpr_mismatch : Warning<
+def warn_cxx20_compat_defaulted_comparison_constexpr_mismatch : Warning<
"defaulted definition of %select{%sub{select_defaulted_comparison_kind}1|"
"three-way comparison operator}0 that is "
"declared %select{constexpr|consteval}2 but"
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index ae953085a21b4a..78c94bce1f3d6e 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -1724,8 +1724,8 @@ static bool CheckConstexprDestructorSubobjects(Sema &SemaRef,
if (Kind == Sema::CheckConstexprKind::Diagnose) {
SemaRef.Diag(DD->getLocation(),
SemaRef.getLangOpts().CPlusPlus23
- ? diag::warn_cxx23_compat_constexpr_dtor_subobject
- : diag::ext_constexpr_dtor_subobject)
+ ? diag::warn_cxx20_compat_constexpr_dtor_subobject
+ : diag::err_constexpr_dtor_subobject)
<< static_cast<int>(DD->getConstexprKind()) << !FD
<< (FD ? FD->getDeclName() : DeclarationName()) << T;
SemaRef.Diag(Loc, diag::note_constexpr_dtor_subobject)
@@ -1760,8 +1760,8 @@ static bool CheckConstexprParameterTypes(Sema &SemaRef,
if (CheckLiteralType(
SemaRef, Kind, ParamLoc, *i,
SemaRef.getLangOpts().CPlusPlus23
- ? diag::warn_cxx23_compat_constexpr_non_literal_param
- : diag::ext_constexpr_non_literal_param,
+ ? diag::warn_cxx20_compat_constexpr_non_literal_param
+ : diag::err_constexpr_non_literal_param,
ArgIndex + 1, PD->getSourceRange(), isa<CXXConstructorDecl>(FD),
FD->isConsteval()))
return SemaRef.getLangOpts().CPlusPlus23;
@@ -1776,8 +1776,8 @@ static bool CheckConstexprReturnType(Sema &SemaRef, const FunctionDecl *FD,
if (CheckLiteralType(
SemaRef, Kind, FD->getLocation(), FD->getReturnType(),
SemaRef.getLangOpts().CPlusPlus23
- ? diag::warn_cxx23_compat_constexpr_non_literal_return
- : diag::ext_constexpr_non_literal_return,
+ ? diag::warn_cxx20_compat_constexpr_non_literal_return
+ : diag::err_constexpr_non_literal_return,
FD->isConsteval()))
return SemaRef.getLangOpts().CPlusPlus23;
return true;
@@ -2471,7 +2471,7 @@ static bool CheckConstexprFunctionBody(Sema &SemaRef, const FunctionDecl *Dcl,
SemaRef.Diag(
Dcl->getLocation(),
SemaRef.getLangOpts().CPlusPlus23
- ? diag::warn_cxx23_compat_constexpr_function_never_constant_expr
+ ? diag::warn_cxx20_compat_constexpr_function_never_constant_expr
: diag::ext_constexpr_function_never_constant_expr)
<< isa<CXXConstructorDecl>(Dcl) << Dcl->isConsteval()
<< Dcl->getNameInfo().getSourceRange();
@@ -7881,7 +7881,7 @@ bool Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD,
Diag(I.getBeginLoc(), diag::note_constexpr_virtual_base_here);
HadError = true;
} else {
- Diag(MD->getBeginLoc(), diag::ext_incorrect_defaulted_constexpr)
+ Diag(MD->getBeginLoc(), diag::err_incorrect_defaulted_constexpr)
<< CSM << MD->isConsteval();
}
// FIXME: Explain why the special member can't be constexpr.
@@ -9121,7 +9121,7 @@ bool Sema::CheckExplicitlyDefaultedComparison(Scope *S, FunctionDecl *FD,
!Info.Constexpr) {
Diag(FD->getBeginLoc(),
getLangOpts().CPlusPlus23
- ? diag::warn_cxx23_compat_defaulted_comparison_constexpr_mismatch
+ ? diag::warn_cxx20_compat_defaulted_comparison_constexpr_mismatch
: diag::ext_defaulted_comparison_constexpr_mismatch)
<< FD->isImplicit() << (int)DCK << FD->isConsteval();
DefaultedComparisonAnalyzer(*this, RD, FD, DCK,
@@ -9135,8 +9135,7 @@ bool Sema::CheckExplicitlyDefaultedComparison(Scope *S, FunctionDecl *FD,
// declaration, it is implicitly considered to be constexpr.
// FIXME: Only applying this to the first declaration seems problematic, as
// simple reorderings can affect the meaning of the program.
- if ((First && !FD->isConstexpr() && Info.Constexpr) ||
- getLangOpts().CPlusPlus23)
+ if (First && !FD->isConstexpr() && Info.Constexpr)
FD->setConstexprKind(ConstexprSpecKind::Constexpr);
// C++2a [except.spec]p3:
diff --git a/clang/test/SemaCXX/cxx23-invalid-constexpr.cpp b/clang/test/SemaCXX/cxx23-invalid-constexpr.cpp
index da22d11a5dcbf4..61d87def3718b1 100644
--- a/clang/test/SemaCXX/cxx23-invalid-constexpr.cpp
+++ b/clang/test/SemaCXX/cxx23-invalid-constexpr.cpp
@@ -1,8 +1,4 @@
// RUN: %clang_cc1 -fsyntax-only -verify=expected,cxx23 -std=c++23 -Wpre-c++23-compat %s
-// RUN: %clang_cc1 -fsyntax-only -verify=expected -std=c++20 -Wno-c++23-extensions -Wno-invalid-constexpr %s
-// RUN: %clang_cc1 -fsyntax-only -verify=expected,precxx20 -std=c++17 -Wno-c++23-extensions -Wno-invalid-constexpr %s
-// RUN: %clang_cc1 -fsyntax-only -verify=expected,precxx20 -std=c++14 -Wno-c++23-extensions -Wno-invalid-constexpr %s
-// RUN: %clang_cc1 -fsyntax-only -verify=expected,precxx20,cxx11 -std=c++11 -Wno-c++14-extensions -Wno-c++23-extensions -Wno-invalid-constexpr -Wno-constexpr-not-const %s
// This test covers modifications made by P2448R2.
@@ -158,5 +154,33 @@ void test() {
// expected-note {{in call to}}
constexpr bool FFF = (NonDefaultMembers() == NonDefaultMembers()); // expected-error{{must be initialized by a constant expression}} \
// expected-note{{non-literal}}
+}
+
+struct A {
+ A ();
+ ~A();
+};
+
+template <class T>
+struct opt
+{
+ union {
+ char c;
+ T data;
+ };
+
+ constexpr opt() {}
+ constexpr ~opt() {
+ if (engaged)
+ data.~T();
+ }
+
+ bool engaged = false;
+};
+
+consteval void foo() {
+ opt<A> a;
}
+
+void bar() { foo(); }
More information about the cfe-commits
mailing list