[clang] 99500e8 - [Clang][C++23] Implement P2448R2: Relaxing some constexpr restrictions (#77753)
via cfe-commits
cfe-commits at lists.llvm.org
Thu Mar 7 00:36:54 PST 2024
Author: Mariya Podchishchaeva
Date: 2024-03-07T09:36:50+01:00
New Revision: 99500e8c08a4d941acb8a7eb00523296fb2acf7a
URL: https://github.com/llvm/llvm-project/commit/99500e8c08a4d941acb8a7eb00523296fb2acf7a
DIFF: https://github.com/llvm/llvm-project/commit/99500e8c08a4d941acb8a7eb00523296fb2acf7a.diff
LOG: [Clang][C++23] Implement P2448R2: Relaxing some constexpr restrictions (#77753)
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.
Added:
clang/test/SemaCXX/cxx23-invalid-constexpr.cpp
Modified:
clang/docs/ReleaseNotes.rst
clang/include/clang/Basic/DiagnosticSemaKinds.td
clang/lib/AST/DeclCXX.cpp
clang/lib/Sema/SemaDeclCXX.cpp
clang/test/AST/Interp/cxx23.cpp
clang/test/CXX/class/class.compare/class.compare.default/p3.cpp
clang/test/CXX/class/class.compare/class.compare.default/p4.cpp
clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/dtor.cpp
clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3-2b.cpp
clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3.cpp
clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p4.cpp
clang/test/CXX/dcl.decl/dcl.fct.def/dcl.fct.def.default/p2.cpp
clang/test/CXX/drs/dr13xx.cpp
clang/test/CXX/drs/dr14xx.cpp
clang/test/CXX/drs/dr15xx.cpp
clang/test/CXX/drs/dr16xx.cpp
clang/test/CXX/drs/dr6xx.cpp
clang/test/CXX/expr/expr.const/p5-26.cpp
clang/test/CXX/special/class.copy/p13-0x.cpp
clang/test/SemaCXX/constant-expression-cxx11.cpp
clang/test/SemaCXX/constant-expression-cxx14.cpp
clang/test/SemaCXX/constant-expression-cxx2b.cpp
clang/test/SemaCXX/cxx2a-consteval.cpp
clang/test/SemaCXX/deduced-return-type-cxx14.cpp
clang/test/SemaOpenCLCXX/addrspace-constructors.clcpp
clang/www/cxx_status.html
Removed:
################################################################################
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 8300a8484585ae..1b901a27fd19d1 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -97,6 +97,8 @@ 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>`_.
+
C++2c Feature Support
^^^^^^^^^^^^^^^^^^^^^
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 5a90e631a894c9..c8dfdc08f5ea07 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -9607,13 +9607,10 @@ 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">;
+ "defaulted definition of %sub{select_special_member_kind}0 cannot be marked %select{constexpr|consteval}1 "
+ "before C++23">;
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>;
@@ -9724,21 +9721,12 @@ def note_defaulted_comparison_cannot_deduce_undeduced_auto : Note<
"%select{|member|base class}0 %1 declared here">;
def note_defaulted_comparison_cannot_deduce_callee : Note<
"selected 'operator<=>' for %select{|member|base class}0 %1 declared here">;
-def ext_defaulted_comparison_constexpr_mismatch : Extension<
+def err_defaulted_comparison_constexpr_mismatch : Error<
"defaulted definition of %select{%sub{select_defaulted_comparison_kind}1|"
- "three-way comparison operator}0 that is "
- "declared %select{constexpr|consteval}2 but"
- "%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<
- "defaulted definition of %select{%sub{select_defaulted_comparison_kind}1|"
- "three-way comparison operator}0 that is "
- "declared %select{constexpr|consteval}2 but"
- "%select{|for which the corresponding implicit 'operator==' }0 "
- "invokes a non-constexpr comparison function is incompatible with C++ "
- "standards before C++23">,
- InGroup<CXXPre23Compat>, DefaultIgnore;
+ "three-way comparison operator}0 cannot be "
+ "declared %select{constexpr|consteval}2 because "
+ "%select{it|for which the corresponding implicit 'operator==' }0 "
+ "invokes a non-constexpr comparison function ">;
def note_defaulted_comparison_not_constexpr : Note<
"non-constexpr comparison function would be used to compare "
"%select{|member %1|base class %1}0">;
diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp
index b4f2327d9c560a..1c3dcf63465c68 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
- // default constructor is constexpr.
+ // 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 199f2523cfb5d2..e258a4f7c89415 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -1715,6 +1715,8 @@ static bool CheckLiteralType(Sema &SemaRef, Sema::CheckConstexprKind Kind,
static bool CheckConstexprDestructorSubobjects(Sema &SemaRef,
const CXXDestructorDecl *DD,
Sema::CheckConstexprKind Kind) {
+ assert(!SemaRef.getLangOpts().CPlusPlus23 &&
+ "this check is obsolete for C++23");
auto Check = [&](SourceLocation Loc, QualType T, const FieldDecl *FD) {
const CXXRecordDecl *RD =
T->getBaseElementTypeUnsafe()->getAsCXXRecordDecl();
@@ -1746,6 +1748,8 @@ static bool CheckConstexprDestructorSubobjects(Sema &SemaRef,
static bool CheckConstexprParameterTypes(Sema &SemaRef,
const FunctionDecl *FD,
Sema::CheckConstexprKind Kind) {
+ assert(!SemaRef.getLangOpts().CPlusPlus23 &&
+ "this check is obsolete for C++23");
unsigned ArgIndex = 0;
const auto *FT = FD->getType()->castAs<FunctionProtoType>();
for (FunctionProtoType::param_type_iterator i = FT->param_type_begin(),
@@ -1767,6 +1771,8 @@ 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) {
+ assert(!SemaRef.getLangOpts().CPlusPlus23 &&
+ "this check is obsolete for C++23");
if (CheckLiteralType(SemaRef, Kind, FD->getLocation(), FD->getReturnType(),
diag::err_constexpr_non_literal_return,
FD->isConsteval()))
@@ -1856,16 +1862,18 @@ bool Sema::CheckConstexprFunctionDefinition(const FunctionDecl *NewFD,
}
}
- // - its return type shall be a literal type;
- if (!CheckConstexprReturnType(*this, NewFD, Kind))
+ // - its return type shall be a literal type; (removed in C++23)
+ if (!getLangOpts().CPlusPlus23 &&
+ !CheckConstexprReturnType(*this, NewFD, Kind))
return false;
}
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))
@@ -1873,8 +1881,9 @@ bool Sema::CheckConstexprFunctionDefinition(const FunctionDecl *NewFD,
}
}
- // - each of its parameter types shall be a literal type;
- if (!CheckConstexprParameterTypes(*this, NewFD, Kind))
+ // - each of its parameter types shall be a literal type; (removed in C++23)
+ if (!getLangOpts().CPlusPlus23 &&
+ !CheckConstexprParameterTypes(*this, NewFD, Kind))
return false;
Stmt *Body = NewFD->getBody();
@@ -2457,7 +2466,8 @@ static bool CheckConstexprFunctionBody(Sema &SemaRef, const FunctionDecl *Dcl,
// function", so is not checked in CheckValid mode.
SmallVector<PartialDiagnosticAt, 8> Diags;
if (Kind == Sema::CheckConstexprKind::Diagnose &&
- !Expr::isPotentialConstantExpr(Dcl, Diags)) {
+ !Expr::isPotentialConstantExpr(Dcl, Diags) &&
+ !SemaRef.getLangOpts().CPlusPlus23) {
SemaRef.Diag(Dcl->getLocation(),
diag::ext_constexpr_function_never_constant_expr)
<< isa<CXXConstructorDecl>(Dcl) << Dcl->isConsteval()
@@ -7535,21 +7545,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 +7571,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;
+ }
}
}
@@ -7858,18 +7872,17 @@ bool Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD,
MD->isConstexpr() && !Constexpr &&
MD->getTemplatedKind() == FunctionDecl::TK_NonTemplate) {
if (!MD->isConsteval() && RD->getNumVBases()) {
- Diag(MD->getBeginLoc(), diag::err_incorrect_defaulted_constexpr_with_vb)
+ Diag(MD->getBeginLoc(),
+ diag::err_incorrect_defaulted_constexpr_with_vb)
<< CSM;
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(), diag::err_incorrect_defaulted_constexpr)
+ << CSM << MD->isConsteval();
}
- // FIXME: Explain why the special member can't be constexpr.
- HadError = true;
+ HadError = true;
+ // FIXME: Explain why the special member can't be constexpr.
}
if (First) {
@@ -9101,13 +9114,11 @@ bool Sema::CheckExplicitlyDefaultedComparison(Scope *S, FunctionDecl *FD,
// - if the function is a constructor or destructor, its class does not
// have any virtual base classes.
if (FD->isConstexpr()) {
- if (CheckConstexprReturnType(*this, FD, CheckConstexprKind::Diagnose) &&
+ if (!getLangOpts().CPlusPlus23 &&
+ CheckConstexprReturnType(*this, FD, CheckConstexprKind::Diagnose) &&
CheckConstexprParameterTypes(*this, FD, CheckConstexprKind::Diagnose) &&
!Info.Constexpr) {
- Diag(FD->getBeginLoc(),
- getLangOpts().CPlusPlus23
- ? diag::warn_cxx23_compat_defaulted_comparison_constexpr_mismatch
- : diag::ext_defaulted_comparison_constexpr_mismatch)
+ Diag(FD->getBeginLoc(), diag::err_defaulted_comparison_constexpr_mismatch)
<< FD->isImplicit() << (int)DCK << FD->isConsteval();
DefaultedComparisonAnalyzer(*this, RD, FD, DCK,
DefaultedComparisonAnalyzer::ExplainConstexpr)
diff --git a/clang/test/AST/Interp/cxx23.cpp b/clang/test/AST/Interp/cxx23.cpp
index f1df936a5abe74..127b58915127cf 100644
--- a/clang/test/AST/Interp/cxx23.cpp
+++ b/clang/test/AST/Interp/cxx23.cpp
@@ -1,82 +1,58 @@
-// RUN: %clang_cc1 -std=c++20 -fsyntax-only -fcxx-exceptions -verify=ref20,all %s
+// RUN: %clang_cc1 -std=c++20 -fsyntax-only -fcxx-exceptions -verify=ref20,all,all-20 %s
// RUN: %clang_cc1 -std=c++23 -fsyntax-only -fcxx-exceptions -verify=ref23,all %s
-// RUN: %clang_cc1 -std=c++20 -fsyntax-only -fcxx-exceptions -verify=expected20,all %s -fexperimental-new-constant-interpreter
+// RUN: %clang_cc1 -std=c++20 -fsyntax-only -fcxx-exceptions -verify=expected20,all,all-20 %s -fexperimental-new-constant-interpreter
// RUN: %clang_cc1 -std=c++23 -fsyntax-only -fcxx-exceptions -verify=expected23,all %s -fexperimental-new-constant-interpreter
/// 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}} \
- // expected20-error {{constexpr function never produces a constant expression}} \
- // expected23-error {{constexpr function never produces a constant expression}}
+ // expected20-error {{constexpr function 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}} \
// expected20-note {{declared here}} \
- // expected23-note {{declared here}}
- return m; // expected20-note {{initializer of 'm' is not a constant expression}} \
- // expected23-note {{initializer of 'm' is not a constant expression}}
+ return m; // expected20-note {{initializer of 'm' is not a constant expression}}
}
constexpr int g(int n) { // ref20-error {{constexpr function never produces a constant expression}} \
- // ref23-error {{constexpr function never produces a constant expression}} \
- // expected20-error {{constexpr function never produces a constant expression}} \
- // expected23-error {{constexpr function never produces a constant expression}}
+ // expected20-error {{constexpr function 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}} \
- // expected20-note {{declared here}} \
- // expected23-note {{declared here}}
- return m; // expected20-note {{initializer of 'm' is not a constant expression}} \
- // expected23-note {{initializer of 'm' is not a constant expression}}
+ // expected20-note {{declared here}}
+ return m; // expected20-note {{initializer of 'm' is not a constant expression}}
}
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}} \
- // expected20-error {{constexpr function never produces a constant expression}} \
- // expected23-error {{constexpr function never produces a constant expression}}
+ // expected20-error {{constexpr function 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}} \
- // expected20-note {{declared here}} \
- // expected23-note {{declared here}}
- return m; // expected20-note {{read of non-const variable}} \
- // expected23-note {{read of non-const variable}}
+ // expected20-note {{declared here}}
+ return m; // expected20-note {{read of non-const variable}}
}
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}} \
- // expected20-error {{constexpr function never produces a constant expression}} \
- // expected23-error {{constexpr function never produces a constant expression}}
+ // expected20-error {{constexpr function 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}} \
- // expected20-note {{declared here}} \
- // expected23-note {{declared here}}
- return m; // expected20-note {{read of non-const variable}} \
- // expected23-note {{read of non-const variable}}
+ // expected20-note {{declared here}}
+ return m; // expected20-note {{read of non-const variable}}
}
-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 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 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;
}
@@ -132,8 +108,9 @@ namespace StaticOperators {
static_assert(f2() == 3);
struct S1 {
- constexpr S1() { // all-error {{never produces a constant expression}}
- throw; // all-note 2{{not valid in a constant expression}}
+ constexpr S1() { // all-20-error {{never produces a constant expression}}
+ throw; // all-note {{not valid in a constant expression}} \
+ // all-20-note {{not valid in a constant expression}}
}
static constexpr int operator()() { return 3; } // ref20-warning {{C++23 extension}} \
// expected20-warning {{C++23 extension}}
diff --git a/clang/test/CXX/class/class.compare/class.compare.default/p3.cpp b/clang/test/CXX/class/class.compare/class.compare.default/p3.cpp
index 166bd97e2731cb..c73eb0dee99515 100644
--- a/clang/test/CXX/class/class.compare/class.compare.default/p3.cpp
+++ b/clang/test/CXX/class/class.compare/class.compare.default/p3.cpp
@@ -1,8 +1,8 @@
// This test is for the [class.compare.default]p3 added by P2002R0
-// Also covers modifications made by P2448R2 and extension warnings
+// Also covers modifications made by P2448R2
-// RUN: %clang_cc1 -std=c++2a -verify %s
-// RUN: %clang_cc1 -std=c++2a -Wc++23-default-comp-relaxed-constexpr -verify=expected,extension %s
+// RUN: %clang_cc1 -std=c++2a -verify=expected,cxx2a %s
+// RUN: %clang_cc1 -std=c++23 -verify=expected %s
namespace std {
struct strong_ordering {
@@ -82,10 +82,12 @@ struct TestB {
};
struct C {
- friend bool operator==(const C&, const C&); // expected-note {{previous}} extension-note 2{{non-constexpr comparison function declared here}}
+ friend bool operator==(const C&, const C&); // expected-note {{previous}} \
+ // cxx2a-note 2{{declared here}}
friend bool operator!=(const C&, const C&) = default; // expected-note {{previous}}
- friend std::strong_ordering operator<=>(const C&, const C&); // expected-note {{previous}} extension-note 2{{non-constexpr comparison function declared here}}
+ friend std::strong_ordering operator<=>(const C&, const C&); // expected-note {{previous}} \
+ // cxx2a-note 2{{declared here}}
friend bool operator<(const C&, const C&) = default; // expected-note {{previous}}
friend bool operator<=(const C&, const C&) = default; // expected-note {{previous}}
friend bool operator>(const C&, const C&) = default; // expected-note {{previous}}
@@ -129,23 +131,23 @@ struct TestD {
struct E {
A a;
- C c; // extension-note 2{{non-constexpr comparison function would be used to compare member 'c'}}
+ C c; // cxx2a-note 2{{non-constexpr comparison function would be used to compare member 'c'}}
A b;
- friend constexpr bool operator==(const E&, const E&) = default; // extension-warning {{declared constexpr but invokes a non-constexpr comparison function is a C++23 extension}}
+ friend constexpr bool operator==(const E&, const E&) = default; // cxx2a-error {{cannot be declared constexpr}}
friend constexpr bool operator!=(const E&, const E&) = default;
- friend constexpr std::strong_ordering operator<=>(const E&, const E&) = default; // extension-warning {{declared constexpr but invokes a non-constexpr comparison function is a C++23 extension}}
+ friend constexpr std::strong_ordering operator<=>(const E&, const E&) = default; // cxx2a-error {{cannot be declared constexpr}}
friend constexpr bool operator<(const E&, const E&) = default;
friend constexpr bool operator<=(const E&, const E&) = default;
friend constexpr bool operator>(const E&, const E&) = default;
friend constexpr bool operator>=(const E&, const E&) = default;
};
-struct E2 : A, C { // extension-note 2{{non-constexpr comparison function would be used to compare base class 'C'}}
- friend constexpr bool operator==(const E2&, const E2&) = default; // extension-warning {{declared constexpr but invokes a non-constexpr comparison function is a C++23 extension}}
+struct E2 : A, C { // cxx2a-note 2{{non-constexpr comparison function would be used to compare base class 'C'}}
+ friend constexpr bool operator==(const E2&, const E2&) = default; // cxx2a-error {{cannot be declared constexpr}}
friend constexpr bool operator!=(const E2&, const E2&) = default;
- friend constexpr std::strong_ordering operator<=>(const E2&, const E2&) = default; // extension-warning {{declared constexpr but invokes a non-constexpr comparison function is a C++23 extension}}
+ friend constexpr std::strong_ordering operator<=>(const E2&, const E2&) = default; // cxx2a-error {{cannot be declared constexpr}}
friend constexpr bool operator<(const E2&, const E2&) = default;
friend constexpr bool operator<=(const E2&, const E2&) = default;
friend constexpr bool operator>(const E2&, const E2&) = default;
@@ -153,14 +155,14 @@ struct E2 : A, C { // extension-note 2{{non-constexpr comparison function would
};
struct F {
- friend bool operator==(const F&, const F&); // extension-note {{non-constexpr comparison function declared here}}
- friend constexpr bool operator!=(const F&, const F&) = default; // extension-warning {{declared constexpr but invokes a non-constexpr comparison function is a C++23 extension}}
-
- friend std::strong_ordering operator<=>(const F&, const F&); // extension-note 4{{non-constexpr comparison function declared here}}
- friend constexpr bool operator<(const F&, const F&) = default; // extension-warning {{declared constexpr but invokes a non-constexpr comparison function is a C++23 extension}}
- friend constexpr bool operator<=(const F&, const F&) = default; // extension-warning {{declared constexpr but invokes a non-constexpr comparison function is a C++23 extension}}
- friend constexpr bool operator>(const F&, const F&) = default; // extension-warning {{declared constexpr but invokes a non-constexpr comparison function is a C++23 extension}}
- friend constexpr bool operator>=(const F&, const F&) = default; // extension-warning {{declared constexpr but invokes a non-constexpr comparison function is a C++23 extension}}
+ friend bool operator==(const F&, const F&); // cxx2a-note {{declared here}}
+ friend constexpr bool operator!=(const F&, const F&) = default; // cxx2a-error {{cannot be declared constexpr}}
+
+ friend std::strong_ordering operator<=>(const F&, const F&); // cxx2a-note 4{{non-constexpr comparison function declared here}}
+ friend constexpr bool operator<(const F&, const F&) = default; // cxx2a-error {{cannot be declared constexpr}}
+ friend constexpr bool operator<=(const F&, const F&) = default; // cxx2a-error {{cannot be declared constexpr}}
+ friend constexpr bool operator>(const F&, const F&) = default; // cxx2a-error {{cannot be declared constexpr}}
+ friend constexpr bool operator>=(const F&, const F&) = default; // cxx2a-error {{cannot be declared constexpr}}
};
// No implicit 'constexpr' if it's not the first declaration.
diff --git a/clang/test/CXX/class/class.compare/class.compare.default/p4.cpp b/clang/test/CXX/class/class.compare/class.compare.default/p4.cpp
index 02cdd7f85aebfa..534c3b34d8832a 100644
--- a/clang/test/CXX/class/class.compare/class.compare.default/p4.cpp
+++ b/clang/test/CXX/class/class.compare/class.compare.default/p4.cpp
@@ -1,9 +1,9 @@
-// RUN: %clang_cc1 -std=c++2a -verify %s
-// RUN: %clang_cc1 -std=c++2a -Wc++23-default-comp-relaxed-constexpr -verify=expected,extension %s
+// RUN: %clang_cc1 -std=c++2a -verify=expected,cxx2a %s
+// RUN: %clang_cc1 -std=c++23 -verify=expected %s
// This test is for [class.compare.default]p3 as modified and renumbered to p4
// by P2002R0.
-// Also covers modifications made by P2448R2 and extension warnings
+// Also covers modifications made by P2448R2
namespace std {
struct strong_ordering {
@@ -78,13 +78,13 @@ void use_g(G g) {
}
struct H {
- bool operator==(const H&) const; // extension-note {{non-constexpr comparison function declared here}}
+ bool operator==(const H&) const; // cxx2a-note {{non-constexpr comparison function declared here}}
constexpr std::strong_ordering operator<=>(const H&) const { return std::strong_ordering::equal; }
};
struct I {
- H h; // extension-note {{non-constexpr comparison function would be used to compare member 'h'}}
- constexpr std::strong_ordering operator<=>(const I&) const = default; // extension-warning {{implicit 'operator==' invokes a non-constexpr comparison function is a C++23 extension}}
+ H h; // cxx2a-note {{non-constexpr comparison function would be used to compare member 'h'}}
+ constexpr std::strong_ordering operator<=>(const I&) const = default; // cxx2a-error {{cannot be declared constexpr}}
};
struct J {
@@ -148,16 +148,16 @@ namespace NoInjectionIfOperatorEqualsDeclared {
namespace GH61238 {
template <typename A> struct my_struct {
- A value; // extension-note {{non-constexpr comparison function would be used to compare member 'value'}}
+ A value; // cxx2a-note {{non-constexpr comparison function would be used to compare member 'value'}}
- constexpr friend bool operator==(const my_struct &, const my_struct &) noexcept = default; // extension-warning {{declared constexpr but invokes a non-constexpr comparison function is a C++23 extension}}
+ constexpr friend bool operator==(const my_struct &, const my_struct &) noexcept = default; // cxx2a-error {{cannot be declared constexpr}}
};
struct non_constexpr_type {
- friend bool operator==(non_constexpr_type, non_constexpr_type) noexcept { // extension-note {{non-constexpr comparison function declared here}}
+ friend bool operator==(non_constexpr_type, non_constexpr_type) noexcept { // cxx2a-note {{non-constexpr comparison function declared here}}
return false;
}
};
-my_struct<non_constexpr_type> obj; // extension-note {{in instantiation of template class 'GH61238::my_struct<GH61238::non_constexpr_type>' requested here}}
+my_struct<non_constexpr_type> obj; // cxx2a-note {{in instantiation of template class 'GH61238::my_struct<GH61238::non_constexpr_type>' requested here}}
}
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..48bc8fb426bcb1 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 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 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..8cb37ae6d1cdec 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,9 +14,8 @@ constexpr int i(int n) {
return m;
}
-constexpr int g() { // expected-error {{constexpr function never produces a constant expression}}
- 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}}
+constexpr int g() {
+ goto test; // expected-warning {{use of this statement in a constexpr function is incompatible with C++ standards before C++23}}
test:
return 0;
}
@@ -29,9 +28,8 @@ struct NonLiteral { // expected-note 2 {{'NonLiteral' is not literal}}
NonLiteral() {}
};
-constexpr void non_literal() { // expected-error {{constexpr function never produces a constant expression}}
- NonLiteral n; // expected-note {{non-literal type 'NonLiteral' cannot be used in a constant expression}} \
- // expected-warning {{definition of a variable of non-literal type in a constexpr function is incompatible with C++ standards before C++23}}
+constexpr void non_literal() {
+ NonLiteral n; // expected-warning {{definition of a variable of non-literal type in a constexpr function is incompatible with C++ standards before C++23}}
}
constexpr void non_literal2(bool b) {
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..4416c825226494 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) {}
};
@@ -43,7 +43,7 @@ struct T : SS, NonLiteral {
// - 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 NonLiteral NonLiteralReturn() const { return {}; } // beforecxx23-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}}
constexpr ~T(); // beforecxx20-error {{destructor cannot be declared constexpr}}
@@ -52,7 +52,7 @@ struct T : SS, NonLiteral {
// - 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}}
+ constexpr int NonLiteralParam(NonLiteral) const { return 0; } // beforecxx23-error {{constexpr function's 1st parameter type 'NonLiteral' is not a literal type}}
typedef int G(NonLiteral) const;
constexpr G NonLiteralParam2; // ok until definition
@@ -66,7 +66,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 cannot be marked constexpr}}
};
constexpr int T::OutOfLineVirtual() const { return 0; }
@@ -229,9 +229,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 never produces a constant expression}}
+ return kGlobal; // beforecxx23-note {{read of non-const}}
}
}
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..92698ec1c7387d 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
@@ -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{{cannot be marked constexpr}}
#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{{cannot be marked constexpr}}
#endif
};
struct XU4 {
@@ -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 {{cannot be marked constexpr}}
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 {{cannot be marked constexpr}}
}
namespace PR14503 {
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..849594307390f4 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 {{defaulted definition of default constructor cannot be marked constexpr}}
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 cannot be marked constexpr}}
+ constexpr S2(S2&&) = default; // expected-error {{defaulted definition of move constructor cannot be marked}}
NoCopyMove ncm;
};
diff --git a/clang/test/CXX/drs/dr13xx.cpp b/clang/test/CXX/drs/dr13xx.cpp
index effdc53040d0b0..d8e3b5d87bd149 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
@@ -485,11 +485,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's 1st parameter type 'NonLit' is not a literal type}}
+ // 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's return type 'NonLit' is not a literal type}}
+ // 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
}
@@ -498,13 +498,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 cannot be marked constexpr before C++23}}
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 cannot be 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 cannot be 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 58a2b3a0d0275d..ed6dda731fd518 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 cannot be marked constexpr}}
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 cannot be marked constexpr}}
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 cannot be marked constexpr}}
struct H {
union {
int n = 0;
diff --git a/clang/test/CXX/drs/dr15xx.cpp b/clang/test/CXX/drs/dr15xx.cpp
index ac503db625ba0e..195c0fa610d579 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) {
@@ -407,7 +407,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
@@ -420,8 +420,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 2dd7d1502e59fb..766c90d3bc7bda 100644
--- a/clang/test/CXX/drs/dr16xx.cpp
+++ b/clang/test/CXX/drs/dr16xx.cpp
@@ -1,10 +1,10 @@
// 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++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++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-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__)
@@ -256,12 +256,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}}
};
}
@@ -350,8 +350,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's 1st parameter type 'NonLiteral' is not a literal type}}
+ // 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 b35d3051ab554c..190e05784f32be 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's 1st parameter type 'NonLiteral' is not a literal type}}
+ // 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 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/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..013d5b56582380 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 {{cannot be marked constexpr}}
A a;
};
}
diff --git a/clang/test/SemaCXX/constant-expression-cxx11.cpp b/clang/test/SemaCXX/constant-expression-cxx11.cpp
index 9e2ae07cbe4c9c..efb391ba0922d8 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 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;
@@ -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}}
};
}
@@ -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;
}
@@ -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);
@@ -2316,10 +2317,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..80a7a2dd31531c 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 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 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 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..2519839b7ac578 100644
--- a/clang/test/SemaCXX/constant-expression-cxx2b.cpp
+++ b/clang/test/SemaCXX/constant-expression-cxx2b.cpp
@@ -10,36 +10,36 @@ struct Constexpr{};
#if __cplusplus > 202002L
-constexpr int f(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 f(int n) { // cxx2a-error {{constexpr function never produces a constant expression}}
+ static const int m = n; // cxx2a-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}}
- thread_local const int m = n; // expected-note {{control flows through the definition of a thread_local variable}} \
+constexpr int g(int n) { // cxx2a-error {{constexpr function never produces a constant expression}}
+ thread_local const int m = n; // cxx2a-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}}
- static _Thread_local int m = 0; // expected-note {{control flows through the definition of a thread_local variable}} \
+constexpr int c_thread_local(int n) { // cxx2a-error {{constexpr function never produces a constant expression}}
+ static _Thread_local int m = 0; // cxx2a-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}}
- static __thread int m = 0; // expected-note {{control flows through the definition of a thread_local variable}} \
+constexpr int gnu_thread_local(int n) { // cxx2a-error {{constexpr function never produces a constant expression}}
+ static __thread int m = 0; // cxx2a-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}}
- static const int m = n; // expected-note {{control flows through the definition of a static variable}} \
+constexpr int h(int n) { // cxx2a-error {{constexpr function never produces a constant expression}}
+ static const int m = n; // cxx2a-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}}
- thread_local const int m = n; // expected-note {{control flows through the definition of a thread_local variable}} \
+constexpr int i(int n) { // cxx2a-error {{constexpr function never produces a constant expression}}
+ thread_local const int m = n; // cxx2a-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/cxx23-invalid-constexpr.cpp b/clang/test/SemaCXX/cxx23-invalid-constexpr.cpp
new file mode 100644
index 00000000000000..4dc16c59d8058d
--- /dev/null
+++ b/clang/test/SemaCXX/cxx23-invalid-constexpr.cpp
@@ -0,0 +1,159 @@
+// RUN: %clang_cc1 -fsyntax-only -verify=expected -std=c++23 %s
+
+// 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) {
+ double D = 2.0 / 0.0; // expected-note {{division by zero}}
+ return 1;
+}
+
+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 {{'NonLiteral' is not literal because it is not an aggregate and has no constexpr constructors}}
+public:
+ NonLiteral() {}
+ ~NonLiteral() {}
+};
+
+constexpr NonLiteral F1() {
+ return NonLiteral{};
+}
+
+constexpr int F2(NonLiteral N) {
+ return 8;
+}
+
+class Derived : public NonLiteral {
+ constexpr ~Derived() {};
+};
+
+class Derived1 : public NonLiteral {
+ constexpr Derived1() : NonLiteral () {}
+};
+
+
+struct X {
+ X();
+ X(const X&);
+ X(X&&);
+ X& operator=(X&);
+ X& operator=(X&& other);
+ bool operator==(X const&) const;
+};
+
+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; }
+ constexpr bool operator==(Wrapper const&) const = default;
+ private:
+ T t;
+};
+
+struct WrapperNonT {
+ constexpr WrapperNonT() = default;
+ constexpr WrapperNonT(WrapperNonT const&) = default;
+ constexpr WrapperNonT(X const& t) : t(t) { }
+ constexpr WrapperNonT(WrapperNonT &&) = default;
+ constexpr WrapperNonT& operator=(WrapperNonT &) = default;
+ constexpr WrapperNonT& operator=(WrapperNonT&& other) = default;
+ constexpr X get() const { return t; }
+ constexpr bool operator==(WrapperNonT const&) const = default;
+ private:
+ X t;
+};
+
+struct NonDefaultMembers {
+ constexpr NonDefaultMembers() {}; // expected-note {{non-literal type 'X' cannot be used in a constant expression}}
+ constexpr NonDefaultMembers(NonDefaultMembers const&) {};
+ constexpr NonDefaultMembers(NonDefaultMembers &&) {};
+ 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;
+};
+
+int Glob = 0;
+class C1 {
+public:
+ constexpr C1() : D(Glob) {};
+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;
+ WrapperNonT x1;
+ NonDefaultMembers x2;
+
+ // TODO these produce notes with an invalid source location.
+ // static_assert((Wrapper<X>(), true));
+ // 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}} \
+ // 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(); }
diff --git a/clang/test/SemaCXX/cxx2a-consteval.cpp b/clang/test/SemaCXX/cxx2a-consteval.cpp
index d8482ec53f0ed4..192621225a543c 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 {{cannot be marked consteval}}
consteval ~D() = default; // expected-error {{destructor cannot be declared consteval}}
};
diff --git a/clang/test/SemaCXX/deduced-return-type-cxx14.cpp b/clang/test/SemaCXX/deduced-return-type-cxx14.cpp
index 415bbbf1a0bc50..431d77ca785b8e 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
@@ -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 {{constexpr function's return type 'struct NonLiteral' is not a literal type}}
}
// It's not really clear whether these are valid, but this matches g++.
diff --git a/clang/test/SemaOpenCLCXX/addrspace-constructors.clcpp b/clang/test/SemaOpenCLCXX/addrspace-constructors.clcpp
index 1b97484767b1a5..067a404c489aa6 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 cannot be marked constexpr}}
};
diff --git a/clang/www/cxx_status.html b/clang/www/cxx_status.html
index 421b3426b006f9..5ed27cdd43b368 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="unreleased" align="center">Clang 19</td>
</tr>
<tr>
<td>Using unknown pointers and references in constant expressions</td>
More information about the cfe-commits
mailing list