@@ -1715,6 +1715,8 @@ static bool CheckLiteralType(Sema &SemaRef, Sema::CheckConstexprKind Kind,
1715
1715
static bool CheckConstexprDestructorSubobjects(Sema &SemaRef,
1716
1716
const CXXDestructorDecl *DD,
1717
1717
Sema::CheckConstexprKind Kind) {
1718
+ assert(!SemaRef.getLangOpts().CPlusPlus23 &&
1719
+ "this check is obsolete for C++23");
1718
1720
auto Check = [&](SourceLocation Loc, QualType T, const FieldDecl *FD) {
1719
1721
const CXXRecordDecl *RD =
1720
1722
T->getBaseElementTypeUnsafe()->getAsCXXRecordDecl();
@@ -1746,6 +1748,8 @@ static bool CheckConstexprDestructorSubobjects(Sema &SemaRef,
1746
1748
static bool CheckConstexprParameterTypes(Sema &SemaRef,
1747
1749
const FunctionDecl *FD,
1748
1750
Sema::CheckConstexprKind Kind) {
1751
+ assert(!SemaRef.getLangOpts().CPlusPlus23 &&
1752
+ "this check is obsolete for C++23");
1749
1753
unsigned ArgIndex = 0;
1750
1754
const auto *FT = FD->getType()->castAs<FunctionProtoType>();
1751
1755
for (FunctionProtoType::param_type_iterator i = FT->param_type_begin(),
@@ -1767,6 +1771,8 @@ static bool CheckConstexprParameterTypes(Sema &SemaRef,
1767
1771
/// true. If not, produce a suitable diagnostic and return false.
1768
1772
static bool CheckConstexprReturnType(Sema &SemaRef, const FunctionDecl *FD,
1769
1773
Sema::CheckConstexprKind Kind) {
1774
+ assert(!SemaRef.getLangOpts().CPlusPlus23 &&
1775
+ "this check is obsolete for C++23");
1770
1776
if (CheckLiteralType(SemaRef, Kind, FD->getLocation(), FD->getReturnType(),
1771
1777
diag::err_constexpr_non_literal_return,
1772
1778
FD->isConsteval()))
@@ -1856,25 +1862,28 @@ bool Sema::CheckConstexprFunctionDefinition(const FunctionDecl *NewFD,
1856
1862
}
1857
1863
}
1858
1864
1859
- // - its return type shall be a literal type;
1860
- if (!CheckConstexprReturnType(*this, NewFD, Kind))
1865
+ // - its return type shall be a literal type; (removed in C++23)
1866
+ if (!getLangOpts().CPlusPlus23 &&
1867
+ !CheckConstexprReturnType(*this, NewFD, Kind))
1861
1868
return false;
1862
1869
}
1863
1870
1864
1871
if (auto *Dtor = dyn_cast<CXXDestructorDecl>(NewFD)) {
1865
1872
// A destructor can be constexpr only if the defaulted destructor could be;
1866
1873
// we don't need to check the members and bases if we already know they all
1867
- // have constexpr destructors.
1868
- if (!Dtor->getParent()->defaultedDestructorIsConstexpr()) {
1874
+ // have constexpr destructors. (removed in C++23)
1875
+ if (!getLangOpts().CPlusPlus23 &&
1876
+ !Dtor->getParent()->defaultedDestructorIsConstexpr()) {
1869
1877
if (Kind == CheckConstexprKind::CheckValid)
1870
1878
return false;
1871
1879
if (!CheckConstexprDestructorSubobjects(*this, Dtor, Kind))
1872
1880
return false;
1873
1881
}
1874
1882
}
1875
1883
1876
- // - each of its parameter types shall be a literal type;
1877
- if (!CheckConstexprParameterTypes(*this, NewFD, Kind))
1884
+ // - each of its parameter types shall be a literal type; (removed in C++23)
1885
+ if (!getLangOpts().CPlusPlus23 &&
1886
+ !CheckConstexprParameterTypes(*this, NewFD, Kind))
1878
1887
return false;
1879
1888
1880
1889
Stmt *Body = NewFD->getBody();
@@ -2457,7 +2466,8 @@ static bool CheckConstexprFunctionBody(Sema &SemaRef, const FunctionDecl *Dcl,
2457
2466
// function", so is not checked in CheckValid mode.
2458
2467
SmallVector<PartialDiagnosticAt, 8> Diags;
2459
2468
if (Kind == Sema::CheckConstexprKind::Diagnose &&
2460
- !Expr::isPotentialConstantExpr(Dcl, Diags)) {
2469
+ !Expr::isPotentialConstantExpr(Dcl, Diags) &&
2470
+ !SemaRef.getLangOpts().CPlusPlus23) {
2461
2471
SemaRef.Diag(Dcl->getLocation(),
2462
2472
diag::ext_constexpr_function_never_constant_expr)
2463
2473
<< isa<CXXConstructorDecl>(Dcl) << Dcl->isConsteval()
@@ -7535,21 +7545,23 @@ static bool defaultedSpecialMemberIsConstexpr(
7535
7545
7536
7546
// C++1y [class.copy]p26:
7537
7547
// -- [the class] is a literal type, and
7538
- if (!Ctor && !ClassDecl->isLiteral())
7548
+ if (!Ctor && !ClassDecl->isLiteral() && !S.getLangOpts().CPlusPlus23 )
7539
7549
return false;
7540
7550
7541
7551
// -- every constructor involved in initializing [...] base class
7542
7552
// sub-objects shall be a constexpr constructor;
7543
7553
// -- the assignment operator selected to copy/move each direct base
7544
7554
// class is a constexpr function, and
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;
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
+ }
7553
7565
}
7554
7566
7555
7567
// -- every constructor involved in initializing non-static data members
@@ -7559,20 +7571,22 @@ static bool defaultedSpecialMemberIsConstexpr(
7559
7571
// -- for each non-static data member of X that is of class type (or array
7560
7572
// thereof), the assignment operator selected to copy/move that member is
7561
7573
// a constexpr function
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()))
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) {
7573
7588
return false;
7574
- } else if (CSM == Sema::CXXDefaultConstructor) {
7575
- return false;
7589
+ }
7576
7590
}
7577
7591
}
7578
7592
@@ -7858,18 +7872,17 @@ bool Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD,
7858
7872
MD->isConstexpr() && !Constexpr &&
7859
7873
MD->getTemplatedKind() == FunctionDecl::TK_NonTemplate) {
7860
7874
if (!MD->isConsteval() && RD->getNumVBases()) {
7861
- Diag(MD->getBeginLoc(), diag::err_incorrect_defaulted_constexpr_with_vb)
7875
+ Diag(MD->getBeginLoc(),
7876
+ diag::err_incorrect_defaulted_constexpr_with_vb)
7862
7877
<< CSM;
7863
7878
for (const auto &I : RD->vbases())
7864
7879
Diag(I.getBeginLoc(), diag::note_constexpr_virtual_base_here);
7865
7880
} else {
7866
- Diag(MD->getBeginLoc(), MD->isConsteval()
7867
- ? diag::err_incorrect_defaulted_consteval
7868
- : diag::err_incorrect_defaulted_constexpr)
7869
- << CSM;
7881
+ Diag(MD->getBeginLoc(), diag::err_incorrect_defaulted_constexpr)
7882
+ << CSM << MD->isConsteval();
7870
7883
}
7871
- // FIXME: Explain why the special member can't be constexpr.
7872
- HadError = true;
7884
+ HadError = true;
7885
+ // FIXME: Explain why the special member can't be constexpr.
7873
7886
}
7874
7887
7875
7888
if (First) {
@@ -9101,13 +9114,11 @@ bool Sema::CheckExplicitlyDefaultedComparison(Scope *S, FunctionDecl *FD,
9101
9114
// - if the function is a constructor or destructor, its class does not
9102
9115
// have any virtual base classes.
9103
9116
if (FD->isConstexpr()) {
9104
- if (CheckConstexprReturnType(*this, FD, CheckConstexprKind::Diagnose) &&
9117
+ if (!getLangOpts().CPlusPlus23 &&
9118
+ CheckConstexprReturnType(*this, FD, CheckConstexprKind::Diagnose) &&
9105
9119
CheckConstexprParameterTypes(*this, FD, CheckConstexprKind::Diagnose) &&
9106
9120
!Info.Constexpr) {
9107
- Diag(FD->getBeginLoc(),
9108
- getLangOpts().CPlusPlus23
9109
- ? diag::warn_cxx23_compat_defaulted_comparison_constexpr_mismatch
9110
- : diag::ext_defaulted_comparison_constexpr_mismatch)
9121
+ Diag(FD->getBeginLoc(), diag::err_defaulted_comparison_constexpr_mismatch)
9111
9122
<< FD->isImplicit() << (int)DCK << FD->isConsteval();
9112
9123
DefaultedComparisonAnalyzer(*this, RD, FD, DCK,
9113
9124
DefaultedComparisonAnalyzer::ExplainConstexpr)
0 commit comments