Skip to content

Commit 003e292

Browse files
authored
Revert "[Clang][C++23] Implement P2448R2 ..." (#85136)
Revert "[Clang][C++23] Implement P2448R2: Relaxing some constexpr restrictions (#77753)" This reverts commit 99500e8 because it causes a behavior change for std=c++20. See #77753.
1 parent af964c7 commit 003e292

File tree

27 files changed

+269
-408
lines changed

27 files changed

+269
-408
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,8 +102,6 @@ C++23 Feature Support
102102
materialize temporary object which is a prvalue in discarded-value expression.
103103
- Implemented `P1774R8: Portable assumptions <https://wg21.link/P1774R8>`_.
104104

105-
- Implemented `P2448R2: Relaxing some constexpr restrictions <https://wg21.link/P2448R2>`_.
106-
107105
C++2c Feature Support
108106
^^^^^^^^^^^^^^^^^^^^^
109107

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9617,10 +9617,13 @@ def err_defaulted_copy_assign_not_ref : Error<
96179617
"the parameter for an explicitly-defaulted copy assignment operator must be an "
96189618
"lvalue reference type">;
96199619
def err_incorrect_defaulted_constexpr : Error<
9620-
"defaulted definition of %sub{select_special_member_kind}0 cannot be marked %select{constexpr|consteval}1 "
9621-
"before C++23">;
9620+
"defaulted definition of %sub{select_special_member_kind}0 "
9621+
"is not constexpr">;
96229622
def err_incorrect_defaulted_constexpr_with_vb: Error<
96239623
"%sub{select_special_member_kind}0 cannot be 'constexpr' in a class with virtual base class">;
9624+
def err_incorrect_defaulted_consteval : Error<
9625+
"defaulted declaration of %sub{select_special_member_kind}0 "
9626+
"cannot be consteval because implicit definition is not constexpr">;
96249627
def warn_defaulted_method_deleted : Warning<
96259628
"explicitly defaulted %sub{select_special_member_kind}0 is implicitly "
96269629
"deleted">, InGroup<DefaultedFunctionDeleted>;
@@ -9731,12 +9734,21 @@ def note_defaulted_comparison_cannot_deduce_undeduced_auto : Note<
97319734
"%select{|member|base class}0 %1 declared here">;
97329735
def note_defaulted_comparison_cannot_deduce_callee : Note<
97339736
"selected 'operator<=>' for %select{|member|base class}0 %1 declared here">;
9734-
def err_defaulted_comparison_constexpr_mismatch : Error<
9737+
def ext_defaulted_comparison_constexpr_mismatch : Extension<
97359738
"defaulted definition of %select{%sub{select_defaulted_comparison_kind}1|"
9736-
"three-way comparison operator}0 cannot be "
9737-
"declared %select{constexpr|consteval}2 because "
9738-
"%select{it|for which the corresponding implicit 'operator==' }0 "
9739-
"invokes a non-constexpr comparison function ">;
9739+
"three-way comparison operator}0 that is "
9740+
"declared %select{constexpr|consteval}2 but"
9741+
"%select{|for which the corresponding implicit 'operator==' }0 "
9742+
"invokes a non-constexpr comparison function is a C++23 extension">,
9743+
InGroup<DiagGroup<"c++23-default-comp-relaxed-constexpr">>;
9744+
def warn_cxx23_compat_defaulted_comparison_constexpr_mismatch : Warning<
9745+
"defaulted definition of %select{%sub{select_defaulted_comparison_kind}1|"
9746+
"three-way comparison operator}0 that is "
9747+
"declared %select{constexpr|consteval}2 but"
9748+
"%select{|for which the corresponding implicit 'operator==' }0 "
9749+
"invokes a non-constexpr comparison function is incompatible with C++ "
9750+
"standards before C++23">,
9751+
InGroup<CXXPre23Compat>, DefaultIgnore;
97409752
def note_defaulted_comparison_not_constexpr : Note<
97419753
"non-constexpr comparison function would be used to compare "
97429754
"%select{|member %1|base class %1}0">;

clang/lib/AST/DeclCXX.cpp

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -400,11 +400,10 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases,
400400

401401
// C++11 [class.ctor]p6:
402402
// If that user-written default constructor would satisfy the
403-
// requirements of a constexpr constructor/function(C++23), the
404-
// implicitly-defined default constructor is constexpr.
403+
// requirements of a constexpr constructor, the implicitly-defined
404+
// default constructor is constexpr.
405405
if (!BaseClassDecl->hasConstexprDefaultConstructor())
406-
data().DefaultedDefaultConstructorIsConstexpr =
407-
C.getLangOpts().CPlusPlus23;
406+
data().DefaultedDefaultConstructorIsConstexpr = false;
408407

409408
// C++1z [class.copy]p8:
410409
// The implicitly-declared copy constructor for a class X will have
@@ -549,8 +548,7 @@ void CXXRecordDecl::addedClassSubobject(CXXRecordDecl *Subobj) {
549548
// -- for every subobject of class type or (possibly multi-dimensional)
550549
// array thereof, that class type shall have a constexpr destructor
551550
if (!Subobj->hasConstexprDestructor())
552-
data().DefaultedDestructorIsConstexpr =
553-
getASTContext().getLangOpts().CPlusPlus23;
551+
data().DefaultedDestructorIsConstexpr = false;
554552

555553
// C++20 [temp.param]p7:
556554
// A structural type is [...] a literal class type [for which] the types
@@ -1299,8 +1297,7 @@ void CXXRecordDecl::addedMember(Decl *D) {
12991297
!FieldRec->hasConstexprDefaultConstructor() && !isUnion())
13001298
// The standard requires any in-class initializer to be a constant
13011299
// expression. We consider this to be a defect.
1302-
data().DefaultedDefaultConstructorIsConstexpr =
1303-
Context.getLangOpts().CPlusPlus23;
1300+
data().DefaultedDefaultConstructorIsConstexpr = false;
13041301

13051302
// C++11 [class.copy]p8:
13061303
// The implicitly-declared copy constructor for a class X will have

clang/lib/Sema/SemaDeclCXX.cpp

Lines changed: 41 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1715,8 +1715,6 @@ static bool CheckLiteralType(Sema &SemaRef, Sema::CheckConstexprKind Kind,
17151715
static bool CheckConstexprDestructorSubobjects(Sema &SemaRef,
17161716
const CXXDestructorDecl *DD,
17171717
Sema::CheckConstexprKind Kind) {
1718-
assert(!SemaRef.getLangOpts().CPlusPlus23 &&
1719-
"this check is obsolete for C++23");
17201718
auto Check = [&](SourceLocation Loc, QualType T, const FieldDecl *FD) {
17211719
const CXXRecordDecl *RD =
17221720
T->getBaseElementTypeUnsafe()->getAsCXXRecordDecl();
@@ -1748,8 +1746,6 @@ static bool CheckConstexprDestructorSubobjects(Sema &SemaRef,
17481746
static bool CheckConstexprParameterTypes(Sema &SemaRef,
17491747
const FunctionDecl *FD,
17501748
Sema::CheckConstexprKind Kind) {
1751-
assert(!SemaRef.getLangOpts().CPlusPlus23 &&
1752-
"this check is obsolete for C++23");
17531749
unsigned ArgIndex = 0;
17541750
const auto *FT = FD->getType()->castAs<FunctionProtoType>();
17551751
for (FunctionProtoType::param_type_iterator i = FT->param_type_begin(),
@@ -1771,8 +1767,6 @@ static bool CheckConstexprParameterTypes(Sema &SemaRef,
17711767
/// true. If not, produce a suitable diagnostic and return false.
17721768
static bool CheckConstexprReturnType(Sema &SemaRef, const FunctionDecl *FD,
17731769
Sema::CheckConstexprKind Kind) {
1774-
assert(!SemaRef.getLangOpts().CPlusPlus23 &&
1775-
"this check is obsolete for C++23");
17761770
if (CheckLiteralType(SemaRef, Kind, FD->getLocation(), FD->getReturnType(),
17771771
diag::err_constexpr_non_literal_return,
17781772
FD->isConsteval()))
@@ -1862,28 +1856,25 @@ bool Sema::CheckConstexprFunctionDefinition(const FunctionDecl *NewFD,
18621856
}
18631857
}
18641858

1865-
// - its return type shall be a literal type; (removed in C++23)
1866-
if (!getLangOpts().CPlusPlus23 &&
1867-
!CheckConstexprReturnType(*this, NewFD, Kind))
1859+
// - its return type shall be a literal type;
1860+
if (!CheckConstexprReturnType(*this, NewFD, Kind))
18681861
return false;
18691862
}
18701863

18711864
if (auto *Dtor = dyn_cast<CXXDestructorDecl>(NewFD)) {
18721865
// A destructor can be constexpr only if the defaulted destructor could be;
18731866
// we don't need to check the members and bases if we already know they all
1874-
// have constexpr destructors. (removed in C++23)
1875-
if (!getLangOpts().CPlusPlus23 &&
1876-
!Dtor->getParent()->defaultedDestructorIsConstexpr()) {
1867+
// have constexpr destructors.
1868+
if (!Dtor->getParent()->defaultedDestructorIsConstexpr()) {
18771869
if (Kind == CheckConstexprKind::CheckValid)
18781870
return false;
18791871
if (!CheckConstexprDestructorSubobjects(*this, Dtor, Kind))
18801872
return false;
18811873
}
18821874
}
18831875

1884-
// - each of its parameter types shall be a literal type; (removed in C++23)
1885-
if (!getLangOpts().CPlusPlus23 &&
1886-
!CheckConstexprParameterTypes(*this, NewFD, Kind))
1876+
// - each of its parameter types shall be a literal type;
1877+
if (!CheckConstexprParameterTypes(*this, NewFD, Kind))
18871878
return false;
18881879

18891880
Stmt *Body = NewFD->getBody();
@@ -2466,8 +2457,7 @@ static bool CheckConstexprFunctionBody(Sema &SemaRef, const FunctionDecl *Dcl,
24662457
// function", so is not checked in CheckValid mode.
24672458
SmallVector<PartialDiagnosticAt, 8> Diags;
24682459
if (Kind == Sema::CheckConstexprKind::Diagnose &&
2469-
!Expr::isPotentialConstantExpr(Dcl, Diags) &&
2470-
!SemaRef.getLangOpts().CPlusPlus23) {
2460+
!Expr::isPotentialConstantExpr(Dcl, Diags)) {
24712461
SemaRef.Diag(Dcl->getLocation(),
24722462
diag::ext_constexpr_function_never_constant_expr)
24732463
<< isa<CXXConstructorDecl>(Dcl) << Dcl->isConsteval()
@@ -7545,23 +7535,21 @@ static bool defaultedSpecialMemberIsConstexpr(
75457535

75467536
// C++1y [class.copy]p26:
75477537
// -- [the class] is a literal type, and
7548-
if (!Ctor && !ClassDecl->isLiteral() && !S.getLangOpts().CPlusPlus23)
7538+
if (!Ctor && !ClassDecl->isLiteral())
75497539
return false;
75507540

75517541
// -- every constructor involved in initializing [...] base class
75527542
// sub-objects shall be a constexpr constructor;
75537543
// -- the assignment operator selected to copy/move each direct base
75547544
// class is a constexpr function, and
7555-
if (!S.getLangOpts().CPlusPlus23) {
7556-
for (const auto &B : ClassDecl->bases()) {
7557-
const RecordType *BaseType = B.getType()->getAs<RecordType>();
7558-
if (!BaseType)
7559-
continue;
7560-
CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(BaseType->getDecl());
7561-
if (!specialMemberIsConstexpr(S, BaseClassDecl, CSM, 0, ConstArg,
7562-
InheritedCtor, Inherited))
7563-
return false;
7564-
}
7545+
for (const auto &B : ClassDecl->bases()) {
7546+
const RecordType *BaseType = B.getType()->getAs<RecordType>();
7547+
if (!BaseType)
7548+
continue;
7549+
CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(BaseType->getDecl());
7550+
if (!specialMemberIsConstexpr(S, BaseClassDecl, CSM, 0, ConstArg,
7551+
InheritedCtor, Inherited))
7552+
return false;
75657553
}
75667554

75677555
// -- every constructor involved in initializing non-static data members
@@ -7571,22 +7559,20 @@ static bool defaultedSpecialMemberIsConstexpr(
75717559
// -- for each non-static data member of X that is of class type (or array
75727560
// thereof), the assignment operator selected to copy/move that member is
75737561
// a constexpr function
7574-
if (!S.getLangOpts().CPlusPlus23) {
7575-
for (const auto *F : ClassDecl->fields()) {
7576-
if (F->isInvalidDecl())
7577-
continue;
7578-
if (CSM == Sema::CXXDefaultConstructor && F->hasInClassInitializer())
7579-
continue;
7580-
QualType BaseType = S.Context.getBaseElementType(F->getType());
7581-
if (const RecordType *RecordTy = BaseType->getAs<RecordType>()) {
7582-
CXXRecordDecl *FieldRecDecl = cast<CXXRecordDecl>(RecordTy->getDecl());
7583-
if (!specialMemberIsConstexpr(S, FieldRecDecl, CSM,
7584-
BaseType.getCVRQualifiers(),
7585-
ConstArg && !F->isMutable()))
7586-
return false;
7587-
} else if (CSM == Sema::CXXDefaultConstructor) {
7562+
for (const auto *F : ClassDecl->fields()) {
7563+
if (F->isInvalidDecl())
7564+
continue;
7565+
if (CSM == Sema::CXXDefaultConstructor && F->hasInClassInitializer())
7566+
continue;
7567+
QualType BaseType = S.Context.getBaseElementType(F->getType());
7568+
if (const RecordType *RecordTy = BaseType->getAs<RecordType>()) {
7569+
CXXRecordDecl *FieldRecDecl = cast<CXXRecordDecl>(RecordTy->getDecl());
7570+
if (!specialMemberIsConstexpr(S, FieldRecDecl, CSM,
7571+
BaseType.getCVRQualifiers(),
7572+
ConstArg && !F->isMutable()))
75887573
return false;
7589-
}
7574+
} else if (CSM == Sema::CXXDefaultConstructor) {
7575+
return false;
75907576
}
75917577
}
75927578

@@ -7872,17 +7858,18 @@ bool Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD,
78727858
MD->isConstexpr() && !Constexpr &&
78737859
MD->getTemplatedKind() == FunctionDecl::TK_NonTemplate) {
78747860
if (!MD->isConsteval() && RD->getNumVBases()) {
7875-
Diag(MD->getBeginLoc(),
7876-
diag::err_incorrect_defaulted_constexpr_with_vb)
7861+
Diag(MD->getBeginLoc(), diag::err_incorrect_defaulted_constexpr_with_vb)
78777862
<< CSM;
78787863
for (const auto &I : RD->vbases())
78797864
Diag(I.getBeginLoc(), diag::note_constexpr_virtual_base_here);
78807865
} else {
7881-
Diag(MD->getBeginLoc(), diag::err_incorrect_defaulted_constexpr)
7882-
<< CSM << MD->isConsteval();
7866+
Diag(MD->getBeginLoc(), MD->isConsteval()
7867+
? diag::err_incorrect_defaulted_consteval
7868+
: diag::err_incorrect_defaulted_constexpr)
7869+
<< CSM;
78837870
}
7884-
HadError = true;
7885-
// FIXME: Explain why the special member can't be constexpr.
7871+
// FIXME: Explain why the special member can't be constexpr.
7872+
HadError = true;
78867873
}
78877874

78887875
if (First) {
@@ -9114,11 +9101,13 @@ bool Sema::CheckExplicitlyDefaultedComparison(Scope *S, FunctionDecl *FD,
91149101
// - if the function is a constructor or destructor, its class does not
91159102
// have any virtual base classes.
91169103
if (FD->isConstexpr()) {
9117-
if (!getLangOpts().CPlusPlus23 &&
9118-
CheckConstexprReturnType(*this, FD, CheckConstexprKind::Diagnose) &&
9104+
if (CheckConstexprReturnType(*this, FD, CheckConstexprKind::Diagnose) &&
91199105
CheckConstexprParameterTypes(*this, FD, CheckConstexprKind::Diagnose) &&
91209106
!Info.Constexpr) {
9121-
Diag(FD->getBeginLoc(), diag::err_defaulted_comparison_constexpr_mismatch)
9107+
Diag(FD->getBeginLoc(),
9108+
getLangOpts().CPlusPlus23
9109+
? diag::warn_cxx23_compat_defaulted_comparison_constexpr_mismatch
9110+
: diag::ext_defaulted_comparison_constexpr_mismatch)
91229111
<< FD->isImplicit() << (int)DCK << FD->isConsteval();
91239112
DefaultedComparisonAnalyzer(*this, RD, FD, DCK,
91249113
DefaultedComparisonAnalyzer::ExplainConstexpr)

0 commit comments

Comments
 (0)