@@ -17968,7 +17968,6 @@ void Sema::ActOnLastBitfield(SourceLocation DeclLoc,
17968
17968
AllIvarDecls.push_back(Ivar);
17969
17969
}
17970
17970
17971
- namespace {
17972
17971
/// [class.dtor]p4:
17973
17972
/// At the end of the definition of a class, overload resolution is
17974
17973
/// performed among the prospective destructors declared in that class with
@@ -17977,7 +17976,7 @@ namespace {
17977
17976
///
17978
17977
/// We do the overload resolution here, then mark the selected constructor in the AST.
17979
17978
/// Later CXXRecordDecl::getDestructor() will return the selected constructor.
17980
- void ComputeSelectedDestructor(Sema &S, CXXRecordDecl *Record) {
17979
+ static void ComputeSelectedDestructor(Sema &S, CXXRecordDecl *Record) {
17981
17980
if (!Record->hasUserDeclaredDestructor()) {
17982
17981
return;
17983
17982
}
@@ -18035,7 +18034,135 @@ void ComputeSelectedDestructor(Sema &S, CXXRecordDecl *Record) {
18035
18034
Record->addedSelectedDestructor(dyn_cast<CXXDestructorDecl>(OCS.begin()->Function));
18036
18035
}
18037
18036
}
18038
- } // namespace
18037
+
18038
+ /// [class.mem.special]p5
18039
+ /// Two special member functions are of the same kind if:
18040
+ /// - they are both default constructors,
18041
+ /// - they are both copy or move constructors with the same first parameter
18042
+ /// type, or
18043
+ /// - they are both copy or move assignment operators with the same first
18044
+ /// parameter type and the same cv-qualifiers and ref-qualifier, if any.
18045
+ static bool AreSpecialMemberFunctionsSameKind(ASTContext &Context,
18046
+ CXXMethodDecl *M1,
18047
+ CXXMethodDecl *M2,
18048
+ Sema::CXXSpecialMember CSM) {
18049
+ if (CSM == Sema::CXXDefaultConstructor)
18050
+ return true;
18051
+ if (!Context.hasSameType(M1->getParamDecl(0)->getType(),
18052
+ M2->getParamDecl(0)->getType()))
18053
+ return false;
18054
+ if (!Context.hasSameType(M1->getThisType(), M2->getThisType()))
18055
+ return false;
18056
+
18057
+ return true;
18058
+ }
18059
+
18060
+ /// [class.mem.special]p6:
18061
+ /// An eligible special member function is a special member function for which:
18062
+ /// - the function is not deleted,
18063
+ /// - the associated constraints, if any, are satisfied, and
18064
+ /// - no special member function of the same kind whose associated constraints
18065
+ /// [CWG2595], if any, are satisfied is more constrained.
18066
+ static void SetEligibleMethods(Sema &S, CXXRecordDecl *Record,
18067
+ ArrayRef<CXXMethodDecl *> Methods,
18068
+ Sema::CXXSpecialMember CSM) {
18069
+ SmallVector<bool, 4> SatisfactionStatus;
18070
+
18071
+ for (CXXMethodDecl *Method : Methods) {
18072
+ const Expr *Constraints = Method->getTrailingRequiresClause();
18073
+ if (!Constraints)
18074
+ SatisfactionStatus.push_back(true);
18075
+ else {
18076
+ ConstraintSatisfaction Satisfaction;
18077
+ if (S.CheckFunctionConstraints(Method, Satisfaction))
18078
+ SatisfactionStatus.push_back(false);
18079
+ else
18080
+ SatisfactionStatus.push_back(Satisfaction.IsSatisfied);
18081
+ }
18082
+ }
18083
+
18084
+ for (size_t i = 0; i < Methods.size(); i++) {
18085
+ if (!SatisfactionStatus[i])
18086
+ continue;
18087
+ CXXMethodDecl *Method = Methods[i];
18088
+ const Expr *Constraints = Method->getTrailingRequiresClause();
18089
+ bool AnotherMethodIsMoreConstrained = false;
18090
+ for (size_t j = 0; j < Methods.size(); j++) {
18091
+ if (i == j || !SatisfactionStatus[j])
18092
+ continue;
18093
+ CXXMethodDecl *OtherMethod = Methods[j];
18094
+ if (!AreSpecialMemberFunctionsSameKind(S.Context, Method, OtherMethod,
18095
+ CSM))
18096
+ continue;
18097
+
18098
+ const Expr *OtherConstraints = OtherMethod->getTrailingRequiresClause();
18099
+ if (!OtherConstraints)
18100
+ continue;
18101
+ if (!Constraints) {
18102
+ AnotherMethodIsMoreConstrained = true;
18103
+ break;
18104
+ }
18105
+ if (S.IsAtLeastAsConstrained(OtherMethod, {OtherConstraints}, Method,
18106
+ {Constraints},
18107
+ AnotherMethodIsMoreConstrained)) {
18108
+ // There was an error with the constraints comparison. Exit the loop
18109
+ // and don't consider this function eligible.
18110
+ AnotherMethodIsMoreConstrained = true;
18111
+ }
18112
+ if (AnotherMethodIsMoreConstrained)
18113
+ break;
18114
+ }
18115
+ // FIXME: Do not consider deleted methods as eligible after implementing
18116
+ // DR1734 and DR1496.
18117
+ if (!AnotherMethodIsMoreConstrained) {
18118
+ Method->setIneligibleOrNotSelected(false);
18119
+ Record->addedEligibleSpecialMemberFunction(Method, 1 << CSM);
18120
+ }
18121
+ }
18122
+ }
18123
+
18124
+ static void ComputeSpecialMemberFunctionsEligiblity(Sema &S,
18125
+ CXXRecordDecl *Record) {
18126
+ SmallVector<CXXMethodDecl *, 4> DefaultConstructors;
18127
+ SmallVector<CXXMethodDecl *, 4> CopyConstructors;
18128
+ SmallVector<CXXMethodDecl *, 4> MoveConstructors;
18129
+ SmallVector<CXXMethodDecl *, 4> CopyAssignmentOperators;
18130
+ SmallVector<CXXMethodDecl *, 4> MoveAssignmentOperators;
18131
+
18132
+ for (auto *Decl : Record->decls()) {
18133
+ auto *MD = dyn_cast<CXXMethodDecl>(Decl);
18134
+ if (!MD) {
18135
+ auto *FTD = dyn_cast<FunctionTemplateDecl>(Decl);
18136
+ if (FTD)
18137
+ MD = dyn_cast<CXXMethodDecl>(FTD->getTemplatedDecl());
18138
+ }
18139
+ if (!MD)
18140
+ continue;
18141
+ if (auto *CD = dyn_cast<CXXConstructorDecl>(MD)) {
18142
+ if (CD->isInvalidDecl())
18143
+ continue;
18144
+ if (CD->isDefaultConstructor())
18145
+ DefaultConstructors.push_back(MD);
18146
+ else if (CD->isCopyConstructor())
18147
+ CopyConstructors.push_back(MD);
18148
+ else if (CD->isMoveConstructor())
18149
+ MoveConstructors.push_back(MD);
18150
+ } else if (MD->isCopyAssignmentOperator()) {
18151
+ CopyAssignmentOperators.push_back(MD);
18152
+ } else if (MD->isMoveAssignmentOperator()) {
18153
+ MoveAssignmentOperators.push_back(MD);
18154
+ }
18155
+ }
18156
+
18157
+ SetEligibleMethods(S, Record, DefaultConstructors,
18158
+ Sema::CXXDefaultConstructor);
18159
+ SetEligibleMethods(S, Record, CopyConstructors, Sema::CXXCopyConstructor);
18160
+ SetEligibleMethods(S, Record, MoveConstructors, Sema::CXXMoveConstructor);
18161
+ SetEligibleMethods(S, Record, CopyAssignmentOperators,
18162
+ Sema::CXXCopyAssignment);
18163
+ SetEligibleMethods(S, Record, MoveAssignmentOperators,
18164
+ Sema::CXXMoveAssignment);
18165
+ }
18039
18166
18040
18167
void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl,
18041
18168
ArrayRef<Decl *> Fields, SourceLocation LBrac,
@@ -18063,9 +18190,6 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl,
18063
18190
RecordDecl *Record = dyn_cast<RecordDecl>(EnclosingDecl);
18064
18191
CXXRecordDecl *CXXRecord = dyn_cast<CXXRecordDecl>(EnclosingDecl);
18065
18192
18066
- if (CXXRecord && !CXXRecord->isDependentType())
18067
- ComputeSelectedDestructor(*this, CXXRecord);
18068
-
18069
18193
// Start counting up the number of named members; make sure to include
18070
18194
// members of anonymous structs and unions in the total.
18071
18195
unsigned NumNamedMembers = 0;
@@ -18351,6 +18475,8 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl,
18351
18475
Completed = true;
18352
18476
}
18353
18477
}
18478
+ ComputeSelectedDestructor(*this, CXXRecord);
18479
+ ComputeSpecialMemberFunctionsEligiblity(*this, CXXRecord);
18354
18480
}
18355
18481
}
18356
18482
0 commit comments