@@ -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
@@ -16371,9 +16448,6 @@ void Sema::SetDeclDeleted(Decl *Dcl, SourceLocation DelLoc) {
16371
16448
Fn->setInvalidDecl();
16372
16449
}
16373
16450
16374
- if (Fn->isDeleted())
16375
- return;
16376
-
16377
16451
// C++11 [basic.start.main]p3:
16378
16452
// A program that defines main as deleted [...] is ill-formed.
16379
16453
if (Fn->isMain())
@@ -16383,25 +16457,6 @@ void Sema::SetDeclDeleted(Decl *Dcl, SourceLocation DelLoc) {
16383
16457
// A deleted function is implicitly inline.
16384
16458
Fn->setImplicitlyInline();
16385
16459
Fn->setDeletedAsWritten();
16386
-
16387
- // See if we're deleting a function which is already known to override a
16388
- // non-deleted virtual function.
16389
- if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(Fn)) {
16390
- bool IssuedDiagnostic = false;
16391
- for (const CXXMethodDecl *O : MD->overridden_methods()) {
16392
- if (!(*MD->begin_overridden_methods())->isDeleted()) {
16393
- if (!IssuedDiagnostic) {
16394
- Diag(DelLoc, diag::err_deleted_override) << MD->getDeclName();
16395
- IssuedDiagnostic = true;
16396
- }
16397
- Diag(O->getLocation(), diag::note_overridden_virtual_function);
16398
- }
16399
- }
16400
- // If this function was implicitly deleted because it was defaulted,
16401
- // explain why it was deleted.
16402
- if (IssuedDiagnostic && MD->isDefaulted())
16403
- DiagnoseDeletedDefaultedFunction(MD);
16404
- }
16405
16460
}
16406
16461
16407
16462
void Sema::SetDeclDefaulted(Decl *Dcl, SourceLocation DefaultLoc) {
@@ -16483,10 +16538,12 @@ void Sema::SetDeclDefaulted(Decl *Dcl, SourceLocation DefaultLoc) {
16483
16538
if (Primary->getCanonicalDecl()->isDefaulted())
16484
16539
return;
16485
16540
16541
+ // FIXME: Once we support defining comparisons out of class, check for a
16542
+ // defaulted comparison here.
16486
16543
if (CheckExplicitlyDefaultedSpecialMember(MD, DefKind.asSpecialMember()))
16487
16544
MD->setInvalidDecl();
16488
16545
else
16489
- DefineImplicitSpecialMember (*this, MD, DefaultLoc);
16546
+ DefineDefaultedFunction (*this, MD, DefaultLoc);
16490
16547
}
16491
16548
16492
16549
static void SearchForReturnInStmt(Sema &Self, Stmt *S) {
0 commit comments