@@ -9062,51 +9062,83 @@ Sema::CheckMemberSpecialization(NamedDecl *Member, LookupResult &Previous) {
9062
9062
if (Previous.empty ()) {
9063
9063
// Nowhere to look anyway.
9064
9064
} else if (FunctionDecl *Function = dyn_cast<FunctionDecl>(Member)) {
9065
- SmallVector<FunctionDecl *> Candidates ;
9066
- bool Ambiguous = false ;
9067
- for (LookupResult::iterator I = Previous. begin (), E = Previous. end ();
9068
- I != E; ++I) {
9069
- CXXMethodDecl *Method =
9070
- dyn_cast<CXXMethodDecl>((*I)-> getUnderlyingDecl ());
9071
- if (!Method)
9065
+ LookupResult::Filter Filter = Previous. makeFilter () ;
9066
+ while (Filter. hasNext ()) {
9067
+ auto *Method =
9068
+ dyn_cast<CXXMethodDecl>(Filter. next ()-> getUnderlyingDecl ());
9069
+ // Discard any candidates that aren't member functions.
9070
+ if (!Method) {
9071
+ Filter. erase ();
9072
9072
continue ;
9073
+ }
9074
+
9073
9075
QualType Adjusted = Function->getType ();
9074
9076
if (!hasExplicitCallingConv (Adjusted))
9075
9077
Adjusted = adjustCCAndNoReturn (Adjusted, Method->getType ());
9078
+ // Discard any candidates with the wrong type.
9076
9079
// This doesn't handle deduced return types, but both function
9077
9080
// declarations should be undeduced at this point.
9078
- if (!Context.hasSameType (Adjusted, Method->getType ()))
9081
+ if (!Context.hasSameType (Adjusted, Method->getType ())) {
9082
+ Filter.erase ();
9079
9083
continue ;
9084
+ }
9085
+
9086
+ // Discard any candidates with unsatisfied constraints.
9080
9087
if (ConstraintSatisfaction Satisfaction;
9081
9088
Method->getTrailingRequiresClause () &&
9082
9089
(CheckFunctionConstraints (Method, Satisfaction,
9083
9090
/* UsageLoc=*/ Member->getLocation (),
9084
9091
/* ForOverloadResolution=*/ true ) ||
9085
- !Satisfaction.IsSatisfied ))
9086
- continue ;
9087
- Candidates.push_back (Method);
9088
- FunctionDecl *MoreConstrained =
9089
- Instantiation ? getMoreConstrainedFunction (
9090
- Method, cast<FunctionDecl>(Instantiation))
9091
- : Method;
9092
- if (!MoreConstrained) {
9093
- Ambiguous = true ;
9092
+ !Satisfaction.IsSatisfied )) {
9093
+ Filter.erase ();
9094
9094
continue ;
9095
9095
}
9096
- if (MoreConstrained == Method) {
9097
- Ambiguous = false ;
9098
- FoundInstantiation = *I;
9099
- Instantiation = Method;
9100
- InstantiatedFrom = Method->getInstantiatedFromMemberFunction ();
9101
- MSInfo = Method->getMemberSpecializationInfo ();
9096
+ }
9097
+ Filter.done ();
9098
+
9099
+ // If we have no candidates left after filtering, we are done.
9100
+ if (Previous.empty ())
9101
+ return false ;
9102
+
9103
+ // Find the function that is more constrained than every other function it
9104
+ // has been compared to.
9105
+ UnresolvedSetIterator Best = Previous.begin ();
9106
+ CXXMethodDecl *BestMethod = nullptr ;
9107
+ for (UnresolvedSetIterator I = Previous.begin (), E = Previous.end (); I != E;
9108
+ ++I) {
9109
+ auto *Method = cast<CXXMethodDecl>(I->getUnderlyingDecl ());
9110
+ if (I == Best ||
9111
+ getMoreConstrainedFunction (Method, BestMethod) == Method) {
9112
+ Best = I;
9113
+ BestMethod = Method;
9114
+ }
9115
+ }
9116
+
9117
+ FoundInstantiation = *Best;
9118
+ Instantiation = BestMethod;
9119
+ InstantiatedFrom = BestMethod->getInstantiatedFromMemberFunction ();
9120
+ MSInfo = BestMethod->getMemberSpecializationInfo ();
9121
+
9122
+ // Make sure the best candidate is more specialized than all of the others.
9123
+ bool Ambiguous = false ;
9124
+ for (UnresolvedSetIterator I = Previous.begin (), E = Previous.end (); I != E;
9125
+ ++I) {
9126
+ auto *Method = cast<CXXMethodDecl>(I->getUnderlyingDecl ());
9127
+ if (I != Best &&
9128
+ getMoreConstrainedFunction (Method, BestMethod) != BestMethod) {
9129
+ Ambiguous = true ;
9130
+ break ;
9102
9131
}
9103
9132
}
9133
+
9104
9134
if (Ambiguous) {
9105
9135
Diag (Member->getLocation (), diag::err_function_member_spec_ambiguous)
9106
9136
<< Member << (InstantiatedFrom ? InstantiatedFrom : Instantiation);
9107
- for (FunctionDecl *Candidate : Candidates)
9137
+ for (NamedDecl *Candidate : Previous) {
9138
+ Candidate = Candidate->getUnderlyingDecl ();
9108
9139
Diag (Candidate->getLocation (), diag::note_function_member_spec_matched)
9109
9140
<< Candidate;
9141
+ }
9110
9142
return true ;
9111
9143
}
9112
9144
} else if (isa<VarDecl>(Member)) {
0 commit comments