@@ -825,29 +825,11 @@ void CXXRecordDecl::addedMember(Decl *D) {
825825 data ().HasInheritedDefaultConstructor = true ;
826826 }
827827
828- // Handle destructors.
829- if (const auto *DD = dyn_cast<CXXDestructorDecl>(D)) {
830- SMKind |= SMF_Destructor;
831-
832- if (DD->isUserProvided ())
833- data ().HasIrrelevantDestructor = false ;
834- // If the destructor is explicitly defaulted and not trivial or not public
835- // or if the destructor is deleted, we clear HasIrrelevantDestructor in
836- // finishedDefaultedOrDeletedMember.
837-
838- // C++11 [class.dtor]p5:
839- // A destructor is trivial if [...] the destructor is not virtual.
840- if (DD->isVirtual ()) {
841- data ().HasTrivialSpecialMembers &= ~SMF_Destructor;
842- data ().HasTrivialSpecialMembersForCall &= ~SMF_Destructor;
843- }
844-
845- if (DD->isNoReturn ())
846- data ().IsAnyDestructorNoReturn = true ;
847- }
848-
849828 // Handle member functions.
850829 if (const auto *Method = dyn_cast<CXXMethodDecl>(D)) {
830+ if (const auto *DD = dyn_cast<CXXDestructorDecl>(D))
831+ SMKind |= SMF_Destructor;
832+
851833 if (Method->isCopyAssignmentOperator ()) {
852834 SMKind |= SMF_CopyAssignment;
853835
@@ -893,31 +875,9 @@ void CXXRecordDecl::addedMember(Decl *D) {
893875 data ().HasTrivialSpecialMembersForCall &=
894876 data ().DeclaredSpecialMembers | ~SMKind;
895877
896- if (!Method->isImplicit () && !Method->isUserProvided ()) {
897- // This method is user-declared but not user-provided. We can't work out
898- // whether it's trivial yet (not until we get to the end of the class).
899- // We'll handle this method in finishedDefaultedOrDeletedMember.
900- } else if (Method->isTrivial ()) {
901- data ().HasTrivialSpecialMembers |= SMKind;
902- data ().HasTrivialSpecialMembersForCall |= SMKind;
903- } else if (Method->isTrivialForCall ()) {
904- data ().HasTrivialSpecialMembersForCall |= SMKind;
905- data ().DeclaredNonTrivialSpecialMembers |= SMKind;
906- } else {
907- data ().DeclaredNonTrivialSpecialMembers |= SMKind;
908- // If this is a user-provided function, do not set
909- // DeclaredNonTrivialSpecialMembersForCall here since we don't know
910- // yet whether the method would be considered non-trivial for the
911- // purpose of calls (attribute "trivial_abi" can be dropped from the
912- // class later, which can change the special method's triviality).
913- if (!Method->isUserProvided ())
914- data ().DeclaredNonTrivialSpecialMembersForCall |= SMKind;
915- }
916-
917878 // Note when we have declared a declared special member, and suppress the
918879 // implicit declaration of this special member.
919880 data ().DeclaredSpecialMembers |= SMKind;
920-
921881 if (!Method->isImplicit ()) {
922882 data ().UserDeclaredSpecialMembers |= SMKind;
923883
@@ -934,6 +894,12 @@ void CXXRecordDecl::addedMember(Decl *D) {
934894 // This is an extension in C++03.
935895 data ().PlainOldData = false ;
936896 }
897+ // We delay updating destructor relevant properties until
898+ // addedSelectedDestructor.
899+ // FIXME: Defer this for the other special member functions as well.
900+ if (!Method->isIneligibleOrNotSelected ()) {
901+ addedEligibleSpecialMemberFunction (Method, SMKind);
902+ }
937903 }
938904
939905 return ;
@@ -1393,6 +1359,54 @@ void CXXRecordDecl::addedMember(Decl *D) {
13931359 }
13941360}
13951361
1362+ void CXXRecordDecl::addedSelectedDestructor (CXXDestructorDecl *DD) {
1363+ DD->setIneligibleOrNotSelected (false );
1364+ addedEligibleSpecialMemberFunction (DD, SMF_Destructor);
1365+ }
1366+
1367+ void CXXRecordDecl::addedEligibleSpecialMemberFunction (const CXXMethodDecl *MD,
1368+ unsigned SMKind) {
1369+ if (const auto *DD = dyn_cast<CXXDestructorDecl>(MD)) {
1370+ if (DD->isUserProvided ())
1371+ data ().HasIrrelevantDestructor = false ;
1372+ // If the destructor is explicitly defaulted and not trivial or not public
1373+ // or if the destructor is deleted, we clear HasIrrelevantDestructor in
1374+ // finishedDefaultedOrDeletedMember.
1375+
1376+ // C++11 [class.dtor]p5:
1377+ // A destructor is trivial if [...] the destructor is not virtual.
1378+ if (DD->isVirtual ()) {
1379+ data ().HasTrivialSpecialMembers &= ~SMF_Destructor;
1380+ data ().HasTrivialSpecialMembersForCall &= ~SMF_Destructor;
1381+ }
1382+
1383+ if (DD->isNoReturn ())
1384+ data ().IsAnyDestructorNoReturn = true ;
1385+ }
1386+
1387+ if (!MD->isImplicit () && !MD->isUserProvided ()) {
1388+ // This method is user-declared but not user-provided. We can't work
1389+ // out whether it's trivial yet (not until we get to the end of the
1390+ // class). We'll handle this method in
1391+ // finishedDefaultedOrDeletedMember.
1392+ } else if (MD->isTrivial ()) {
1393+ data ().HasTrivialSpecialMembers |= SMKind;
1394+ data ().HasTrivialSpecialMembersForCall |= SMKind;
1395+ } else if (MD->isTrivialForCall ()) {
1396+ data ().HasTrivialSpecialMembersForCall |= SMKind;
1397+ data ().DeclaredNonTrivialSpecialMembers |= SMKind;
1398+ } else {
1399+ data ().DeclaredNonTrivialSpecialMembers |= SMKind;
1400+ // If this is a user-provided function, do not set
1401+ // DeclaredNonTrivialSpecialMembersForCall here since we don't know
1402+ // yet whether the method would be considered non-trivial for the
1403+ // purpose of calls (attribute "trivial_abi" can be dropped from the
1404+ // class later, which can change the special method's triviality).
1405+ if (!MD->isUserProvided ())
1406+ data ().DeclaredNonTrivialSpecialMembersForCall |= SMKind;
1407+ }
1408+ }
1409+
13961410void CXXRecordDecl::finishedDefaultedOrDeletedMember (CXXMethodDecl *D) {
13971411 assert (!D->isImplicit () && !D->isUserProvided ());
13981412
@@ -1895,7 +1909,14 @@ CXXDestructorDecl *CXXRecordDecl::getDestructor() const {
18951909
18961910 DeclContext::lookup_result R = lookup (Name);
18971911
1898- return R.empty () ? nullptr : dyn_cast<CXXDestructorDecl>(R.front ());
1912+ // If a destructor was marked as not selected, we skip it. We don't always
1913+ // have a selected destructor: dependent types, unnamed structs.
1914+ for (auto *Decl : R) {
1915+ auto * DD = dyn_cast<CXXDestructorDecl>(Decl);
1916+ if (DD && !DD->isIneligibleOrNotSelected ())
1917+ return DD;
1918+ }
1919+ return nullptr ;
18991920}
19001921
19011922static bool isDeclContextInNamespace (const DeclContext *DC) {
0 commit comments