@@ -6172,27 +6172,31 @@ Sema::getDefaultedFunctionKind(const FunctionDecl *FD) {
61726172 return DefaultedFunctionKind();
61736173}
61746174
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()) {
61786182 case Sema::CXXDefaultConstructor:
61796183 S.DefineImplicitDefaultConstructor(DefaultLoc,
6180- cast<CXXConstructorDecl>(MD ));
6184+ cast<CXXConstructorDecl>(FD ));
61816185 break;
61826186 case Sema::CXXCopyConstructor:
6183- S.DefineImplicitCopyConstructor(DefaultLoc, cast<CXXConstructorDecl>(MD ));
6187+ S.DefineImplicitCopyConstructor(DefaultLoc, cast<CXXConstructorDecl>(FD ));
61846188 break;
61856189 case Sema::CXXCopyAssignment:
6186- S.DefineImplicitCopyAssignment(DefaultLoc, MD );
6190+ S.DefineImplicitCopyAssignment(DefaultLoc, cast<CXXMethodDecl>(FD) );
61876191 break;
61886192 case Sema::CXXDestructor:
6189- S.DefineImplicitDestructor(DefaultLoc, cast<CXXDestructorDecl>(MD ));
6193+ S.DefineImplicitDestructor(DefaultLoc, cast<CXXDestructorDecl>(FD ));
61906194 break;
61916195 case Sema::CXXMoveConstructor:
6192- S.DefineImplicitMoveConstructor(DefaultLoc, cast<CXXConstructorDecl>(MD ));
6196+ S.DefineImplicitMoveConstructor(DefaultLoc, cast<CXXConstructorDecl>(FD ));
61936197 break;
61946198 case Sema::CXXMoveAssignment:
6195- S.DefineImplicitMoveAssignment(DefaultLoc, MD );
6199+ S.DefineImplicitMoveAssignment(DefaultLoc, cast<CXXMethodDecl>(FD) );
61966200 break;
61976201 case Sema::CXXInvalid:
61986202 llvm_unreachable("Invalid special member.");
@@ -6313,6 +6317,28 @@ static bool canPassInRegisters(Sema &S, CXXRecordDecl *D,
63136317 return HasNonDeletedCopyOrMove;
63146318}
63156319
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+
63166342/// Perform semantic checks on a class definition that has been
63176343/// completing, introducing implicitly-declared members, checking for
63186344/// abstract types, etc.
@@ -6427,21 +6453,64 @@ void Sema::CheckCompletedCXXClass(Scope *S, CXXRecordDecl *Record) {
64276453 // primary comparison functions (==, <=>).
64286454 llvm::SmallVector<FunctionDecl*, 5> DefaultedSecondaryComparisons;
64296455
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);
64326478 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;
64336499
64346500 DefaultedFunctionKind DFK = getDefaultedFunctionKind(FD);
64356501 if (DFK.asComparison() == DefaultedComparisonKind::NotEqual ||
6436- DFK.asComparison() == DefaultedComparisonKind::Relational)
6502+ DFK.asComparison() == DefaultedComparisonKind::Relational) {
64376503 DefaultedSecondaryComparisons.push_back(FD);
6438- else
6439- CheckExplicitlyDefaultedFunction(S, FD);
6504+ return true;
6505+ }
6506+
6507+ CheckExplicitlyDefaultedFunction(S, FD);
6508+ return false;
64406509 };
64416510
64426511 auto CompleteMemberFunction = [&](CXXMethodDecl *M) {
64436512 // Check whether the explicitly-defaulted members are valid.
6444- CheckForDefaultedFunction(M);
6513+ bool Incomplete = CheckForDefaultedFunction(M);
64456514
64466515 // Skip the rest of the checks for a member of a dependent class.
64476516 if (Record->isDependentType())
@@ -6488,7 +6557,10 @@ void Sema::CheckCompletedCXXClass(Scope *S, CXXRecordDecl *Record) {
64886557 // function right away.
64896558 // FIXME: We can defer doing this until the vtable is marked as used.
64906559 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);
64926564 };
64936565
64946566 // Check the destructor before any other member function. We need to
@@ -6534,9 +6606,14 @@ void Sema::CheckCompletedCXXClass(Scope *S, CXXRecordDecl *Record) {
65346606 }
65356607
65366608 // Check the defaulted secondary comparisons after any other member functions.
6537- for (FunctionDecl *FD : DefaultedSecondaryComparisons)
6609+ for (FunctionDecl *FD : DefaultedSecondaryComparisons) {
65386610 CheckExplicitlyDefaultedFunction(S, FD);
65396611
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+
65406617 // ms_struct is a request to use the same ABI rules as MSVC. Check
65416618 // whether this class uses any C++ features that are implemented
65426619 // completely differently in MSVC, and if so, emit a diagnostic.
@@ -13023,7 +13100,7 @@ void Sema::ActOnFinishCXXNonNestedClass() {
1302313100 SmallVector<CXXMethodDecl*, 4> WorkList;
1302413101 std::swap(DelayedDllExportMemberFunctions, WorkList);
1302513102 for (CXXMethodDecl *M : WorkList) {
13026- DefineImplicitSpecialMember (*this, M, M->getLocation());
13103+ DefineDefaultedFunction (*this, M, M->getLocation());
1302713104
1302813105 // Pass the method to the consumer to get emitted. This is not necessary
1302913106 // for explicit instantiation definitions, as they will get emitted
@@ -16371,9 +16448,6 @@ void Sema::SetDeclDeleted(Decl *Dcl, SourceLocation DelLoc) {
1637116448 Fn->setInvalidDecl();
1637216449 }
1637316450
16374- if (Fn->isDeleted())
16375- return;
16376-
1637716451 // C++11 [basic.start.main]p3:
1637816452 // A program that defines main as deleted [...] is ill-formed.
1637916453 if (Fn->isMain())
@@ -16383,25 +16457,6 @@ void Sema::SetDeclDeleted(Decl *Dcl, SourceLocation DelLoc) {
1638316457 // A deleted function is implicitly inline.
1638416458 Fn->setImplicitlyInline();
1638516459 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- }
1640516460}
1640616461
1640716462void Sema::SetDeclDefaulted(Decl *Dcl, SourceLocation DefaultLoc) {
@@ -16483,10 +16538,12 @@ void Sema::SetDeclDefaulted(Decl *Dcl, SourceLocation DefaultLoc) {
1648316538 if (Primary->getCanonicalDecl()->isDefaulted())
1648416539 return;
1648516540
16541+ // FIXME: Once we support defining comparisons out of class, check for a
16542+ // defaulted comparison here.
1648616543 if (CheckExplicitlyDefaultedSpecialMember(MD, DefKind.asSpecialMember()))
1648716544 MD->setInvalidDecl();
1648816545 else
16489- DefineImplicitSpecialMember (*this, MD, DefaultLoc);
16546+ DefineDefaultedFunction (*this, MD, DefaultLoc);
1649016547}
1649116548
1649216549static void SearchForReturnInStmt(Sema &Self, Stmt *S) {
0 commit comments