@@ -6172,27 +6172,31 @@ Sema::getDefaultedFunctionKind(const FunctionDecl *FD) {
6172
6172
return DefaultedFunctionKind();
6173
6173
}
6174
6174
6175
- static void DefineImplicitSpecialMember(Sema &S, CXXMethodDecl *MD,
6176
- SourceLocation DefaultLoc) {
6177
- switch (S.getSpecialMember(MD)) {
6175
+ static void DefineDefaultedFunction(Sema &S, FunctionDecl *FD,
6176
+ SourceLocation DefaultLoc) {
6177
+ Sema::DefaultedFunctionKind DFK = S.getDefaultedFunctionKind(FD);
6178
+ if (DFK.isComparison())
6179
+ return S.DefineDefaultedComparison(DefaultLoc, FD, DFK.asComparison());
6180
+
6181
+ switch (DFK.asSpecialMember()) {
6178
6182
case Sema::CXXDefaultConstructor:
6179
6183
S.DefineImplicitDefaultConstructor(DefaultLoc,
6180
- cast<CXXConstructorDecl>(MD ));
6184
+ cast<CXXConstructorDecl>(FD ));
6181
6185
break;
6182
6186
case Sema::CXXCopyConstructor:
6183
- S.DefineImplicitCopyConstructor(DefaultLoc, cast<CXXConstructorDecl>(MD ));
6187
+ S.DefineImplicitCopyConstructor(DefaultLoc, cast<CXXConstructorDecl>(FD ));
6184
6188
break;
6185
6189
case Sema::CXXCopyAssignment:
6186
- S.DefineImplicitCopyAssignment(DefaultLoc, MD );
6190
+ S.DefineImplicitCopyAssignment(DefaultLoc, cast<CXXMethodDecl>(FD) );
6187
6191
break;
6188
6192
case Sema::CXXDestructor:
6189
- S.DefineImplicitDestructor(DefaultLoc, cast<CXXDestructorDecl>(MD ));
6193
+ S.DefineImplicitDestructor(DefaultLoc, cast<CXXDestructorDecl>(FD ));
6190
6194
break;
6191
6195
case Sema::CXXMoveConstructor:
6192
- S.DefineImplicitMoveConstructor(DefaultLoc, cast<CXXConstructorDecl>(MD ));
6196
+ S.DefineImplicitMoveConstructor(DefaultLoc, cast<CXXConstructorDecl>(FD ));
6193
6197
break;
6194
6198
case Sema::CXXMoveAssignment:
6195
- S.DefineImplicitMoveAssignment(DefaultLoc, MD );
6199
+ S.DefineImplicitMoveAssignment(DefaultLoc, cast<CXXMethodDecl>(FD) );
6196
6200
break;
6197
6201
case Sema::CXXInvalid:
6198
6202
llvm_unreachable("Invalid special member.");
@@ -6313,6 +6317,28 @@ static bool canPassInRegisters(Sema &S, CXXRecordDecl *D,
6313
6317
return HasNonDeletedCopyOrMove;
6314
6318
}
6315
6319
6320
+ /// Report an error regarding overriding, along with any relevant
6321
+ /// overridden methods.
6322
+ ///
6323
+ /// \param DiagID the primary error to report.
6324
+ /// \param MD the overriding method.
6325
+ /// \param OEK which overrides to include as notes.
6326
+ static bool
6327
+ ReportOverrides(Sema &S, unsigned DiagID, const CXXMethodDecl *MD,
6328
+ llvm::function_ref<bool(const CXXMethodDecl *)> Report) {
6329
+ bool IssuedDiagnostic = false;
6330
+ for (const CXXMethodDecl *O : MD->overridden_methods()) {
6331
+ if (Report(O)) {
6332
+ if (!IssuedDiagnostic) {
6333
+ S.Diag(MD->getLocation(), DiagID) << MD->getDeclName();
6334
+ IssuedDiagnostic = true;
6335
+ }
6336
+ S.Diag(O->getLocation(), diag::note_overridden_virtual_function);
6337
+ }
6338
+ }
6339
+ return IssuedDiagnostic;
6340
+ }
6341
+
6316
6342
/// Perform semantic checks on a class definition that has been
6317
6343
/// completing, introducing implicitly-declared members, checking for
6318
6344
/// abstract types, etc.
@@ -6427,21 +6453,64 @@ void Sema::CheckCompletedCXXClass(Scope *S, CXXRecordDecl *Record) {
6427
6453
// primary comparison functions (==, <=>).
6428
6454
llvm::SmallVector<FunctionDecl*, 5> DefaultedSecondaryComparisons;
6429
6455
6430
- auto CheckForDefaultedFunction = [&](FunctionDecl *FD) {
6431
- if (!FD || FD->isInvalidDecl() || !FD->isExplicitlyDefaulted())
6456
+ // Perform checks that can't be done until we know all the properties of a
6457
+ // member function (whether it's defaulted, deleted, virtual, overriding,
6458
+ // ...).
6459
+ auto CheckCompletedMemberFunction = [&](CXXMethodDecl *MD) {
6460
+ // A static function cannot override anything.
6461
+ if (MD->getStorageClass() == SC_Static) {
6462
+ if (ReportOverrides(*this, diag::err_static_overrides_virtual, MD,
6463
+ [](const CXXMethodDecl *) { return true; }))
6464
+ return;
6465
+ }
6466
+
6467
+ // A deleted function cannot override a non-deleted function and vice
6468
+ // versa.
6469
+ if (ReportOverrides(*this,
6470
+ MD->isDeleted() ? diag::err_deleted_override
6471
+ : diag::err_non_deleted_override,
6472
+ MD, [&](const CXXMethodDecl *V) {
6473
+ return MD->isDeleted() != V->isDeleted();
6474
+ })) {
6475
+ if (MD->isDefaulted() && MD->isDeleted())
6476
+ // Explain why this defaulted function was deleted.
6477
+ DiagnoseDeletedDefaultedFunction(MD);
6432
6478
return;
6479
+ }
6480
+
6481
+ // A consteval function cannot override a non-consteval function and vice
6482
+ // versa.
6483
+ if (ReportOverrides(*this,
6484
+ MD->isConsteval() ? diag::err_consteval_override
6485
+ : diag::err_non_consteval_override,
6486
+ MD, [&](const CXXMethodDecl *V) {
6487
+ return MD->isConsteval() != V->isConsteval();
6488
+ })) {
6489
+ if (MD->isDefaulted() && MD->isDeleted())
6490
+ // Explain why this defaulted function was deleted.
6491
+ DiagnoseDeletedDefaultedFunction(MD);
6492
+ return;
6493
+ }
6494
+ };
6495
+
6496
+ auto CheckForDefaultedFunction = [&](FunctionDecl *FD) -> bool {
6497
+ if (!FD || FD->isInvalidDecl() || !FD->isExplicitlyDefaulted())
6498
+ return false;
6433
6499
6434
6500
DefaultedFunctionKind DFK = getDefaultedFunctionKind(FD);
6435
6501
if (DFK.asComparison() == DefaultedComparisonKind::NotEqual ||
6436
- DFK.asComparison() == DefaultedComparisonKind::Relational)
6502
+ DFK.asComparison() == DefaultedComparisonKind::Relational) {
6437
6503
DefaultedSecondaryComparisons.push_back(FD);
6438
- else
6439
- CheckExplicitlyDefaultedFunction(S, FD);
6504
+ return true;
6505
+ }
6506
+
6507
+ CheckExplicitlyDefaultedFunction(S, FD);
6508
+ return false;
6440
6509
};
6441
6510
6442
6511
auto CompleteMemberFunction = [&](CXXMethodDecl *M) {
6443
6512
// Check whether the explicitly-defaulted members are valid.
6444
- CheckForDefaultedFunction(M);
6513
+ bool Incomplete = CheckForDefaultedFunction(M);
6445
6514
6446
6515
// Skip the rest of the checks for a member of a dependent class.
6447
6516
if (Record->isDependentType())
@@ -6488,7 +6557,10 @@ void Sema::CheckCompletedCXXClass(Scope *S, CXXRecordDecl *Record) {
6488
6557
// function right away.
6489
6558
// FIXME: We can defer doing this until the vtable is marked as used.
6490
6559
if (M->isDefaulted() && M->isConstexpr() && M->size_overridden_methods())
6491
- DefineImplicitSpecialMember(*this, M, M->getLocation());
6560
+ DefineDefaultedFunction(*this, M, M->getLocation());
6561
+
6562
+ if (!Incomplete)
6563
+ CheckCompletedMemberFunction(M);
6492
6564
};
6493
6565
6494
6566
// Check the destructor before any other member function. We need to
@@ -6534,9 +6606,14 @@ void Sema::CheckCompletedCXXClass(Scope *S, CXXRecordDecl *Record) {
6534
6606
}
6535
6607
6536
6608
// Check the defaulted secondary comparisons after any other member functions.
6537
- for (FunctionDecl *FD : DefaultedSecondaryComparisons)
6609
+ for (FunctionDecl *FD : DefaultedSecondaryComparisons) {
6538
6610
CheckExplicitlyDefaultedFunction(S, FD);
6539
6611
6612
+ // If this is a member function, we deferred checking it until now.
6613
+ if (auto *MD = dyn_cast<CXXMethodDecl>(FD))
6614
+ CheckCompletedMemberFunction(MD);
6615
+ }
6616
+
6540
6617
// ms_struct is a request to use the same ABI rules as MSVC. Check
6541
6618
// whether this class uses any C++ features that are implemented
6542
6619
// completely differently in MSVC, and if so, emit a diagnostic.
@@ -13023,7 +13100,7 @@ void Sema::ActOnFinishCXXNonNestedClass() {
13023
13100
SmallVector<CXXMethodDecl*, 4> WorkList;
13024
13101
std::swap(DelayedDllExportMemberFunctions, WorkList);
13025
13102
for (CXXMethodDecl *M : WorkList) {
13026
- DefineImplicitSpecialMember (*this, M, M->getLocation());
13103
+ DefineDefaultedFunction (*this, M, M->getLocation());
13027
13104
13028
13105
// Pass the method to the consumer to get emitted. This is not necessary
13029
13106
// for explicit instantiation definitions, as they will get emitted
@@ -16368,9 +16445,6 @@ void Sema::SetDeclDeleted(Decl *Dcl, SourceLocation DelLoc) {
16368
16445
Fn->setInvalidDecl();
16369
16446
}
16370
16447
16371
- if (Fn->isDeleted())
16372
- return;
16373
-
16374
16448
// C++11 [basic.start.main]p3:
16375
16449
// A program that defines main as deleted [...] is ill-formed.
16376
16450
if (Fn->isMain())
@@ -16380,25 +16454,6 @@ void Sema::SetDeclDeleted(Decl *Dcl, SourceLocation DelLoc) {
16380
16454
// A deleted function is implicitly inline.
16381
16455
Fn->setImplicitlyInline();
16382
16456
Fn->setDeletedAsWritten();
16383
-
16384
- // See if we're deleting a function which is already known to override a
16385
- // non-deleted virtual function.
16386
- if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(Fn)) {
16387
- bool IssuedDiagnostic = false;
16388
- for (const CXXMethodDecl *O : MD->overridden_methods()) {
16389
- if (!(*MD->begin_overridden_methods())->isDeleted()) {
16390
- if (!IssuedDiagnostic) {
16391
- Diag(DelLoc, diag::err_deleted_override) << MD->getDeclName();
16392
- IssuedDiagnostic = true;
16393
- }
16394
- Diag(O->getLocation(), diag::note_overridden_virtual_function);
16395
- }
16396
- }
16397
- // If this function was implicitly deleted because it was defaulted,
16398
- // explain why it was deleted.
16399
- if (IssuedDiagnostic && MD->isDefaulted())
16400
- DiagnoseDeletedDefaultedFunction(MD);
16401
- }
16402
16457
}
16403
16458
16404
16459
void Sema::SetDeclDefaulted(Decl *Dcl, SourceLocation DefaultLoc) {
@@ -16480,10 +16535,12 @@ void Sema::SetDeclDefaulted(Decl *Dcl, SourceLocation DefaultLoc) {
16480
16535
if (Primary->getCanonicalDecl()->isDefaulted())
16481
16536
return;
16482
16537
16538
+ // FIXME: Once we support defining comparisons out of class, check for a
16539
+ // defaulted comparison here.
16483
16540
if (CheckExplicitlyDefaultedSpecialMember(MD, DefKind.asSpecialMember()))
16484
16541
MD->setInvalidDecl();
16485
16542
else
16486
- DefineImplicitSpecialMember (*this, MD, DefaultLoc);
16543
+ DefineDefaultedFunction (*this, MD, DefaultLoc);
16487
16544
}
16488
16545
16489
16546
static void SearchForReturnInStmt(Sema &Self, Stmt *S) {
0 commit comments