summaryrefslogtreecommitdiff
path: root/clang/lib/Sema/SemaTemplate.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Sema/SemaTemplate.cpp')
-rw-r--r--clang/lib/Sema/SemaTemplate.cpp76
1 files changed, 53 insertions, 23 deletions
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index 1346a4a3f001..cd3ee31fcca6 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -4436,7 +4436,8 @@ ExprResult Sema::BuildTemplateIdExpr(const CXXScopeSpec &SS,
UnresolvedLookupExpr *ULE = UnresolvedLookupExpr::Create(
Context, R.getNamingClass(), SS.getWithLocInContext(Context),
TemplateKWLoc, R.getLookupNameInfo(), RequiresADL, TemplateArgs,
- R.begin(), R.end(), KnownDependent);
+ R.begin(), R.end(), KnownDependent,
+ /*KnownInstantiationDependent=*/false);
// Model the templates with UnresolvedTemplateTy. The expression should then
// either be transformed in an instantiation or be diagnosed in
@@ -9051,7 +9052,8 @@ bool Sema::CheckFunctionTemplateSpecialization(
bool
Sema::CheckMemberSpecialization(NamedDecl *Member, LookupResult &Previous) {
- assert(!isa<TemplateDecl>(Member) && "Only for non-template members");
+ assert(!Member->isTemplateDecl() && !Member->getDescribedTemplate() &&
+ "Only for non-template members");
// Try to find the member we are instantiating.
NamedDecl *FoundInstantiation = nullptr;
@@ -9062,21 +9064,25 @@ Sema::CheckMemberSpecialization(NamedDecl *Member, LookupResult &Previous) {
if (Previous.empty()) {
// Nowhere to look anyway.
} else if (FunctionDecl *Function = dyn_cast<FunctionDecl>(Member)) {
- SmallVector<FunctionDecl *> Candidates;
- bool Ambiguous = false;
- for (LookupResult::iterator I = Previous.begin(), E = Previous.end();
- I != E; ++I) {
- CXXMethodDecl *Method =
- dyn_cast<CXXMethodDecl>((*I)->getUnderlyingDecl());
+ UnresolvedSet<8> Candidates;
+ for (NamedDecl *Candidate : Previous) {
+ auto *Method = dyn_cast<CXXMethodDecl>(Candidate->getUnderlyingDecl());
+ // Ignore any candidates that aren't member functions.
if (!Method)
continue;
+
QualType Adjusted = Function->getType();
if (!hasExplicitCallingConv(Adjusted))
Adjusted = adjustCCAndNoReturn(Adjusted, Method->getType());
+ // Ignore any candidates with the wrong type.
// This doesn't handle deduced return types, but both function
// declarations should be undeduced at this point.
+ // FIXME: The exception specification should probably be ignored when
+ // comparing the types.
if (!Context.hasSameType(Adjusted, Method->getType()))
continue;
+
+ // Ignore any candidates with unsatisfied constraints.
if (ConstraintSatisfaction Satisfaction;
Method->getTrailingRequiresClause() &&
(CheckFunctionConstraints(Method, Satisfaction,
@@ -9084,29 +9090,53 @@ Sema::CheckMemberSpecialization(NamedDecl *Member, LookupResult &Previous) {
/*ForOverloadResolution=*/true) ||
!Satisfaction.IsSatisfied))
continue;
- Candidates.push_back(Method);
- FunctionDecl *MoreConstrained =
- Instantiation ? getMoreConstrainedFunction(
- Method, cast<FunctionDecl>(Instantiation))
- : Method;
- if (!MoreConstrained) {
- Ambiguous = true;
- continue;
+
+ Candidates.addDecl(Candidate);
+ }
+
+ // If we have no viable candidates left after filtering, we are done.
+ if (Candidates.empty())
+ return false;
+
+ // Find the function that is more constrained than every other function it
+ // has been compared to.
+ UnresolvedSetIterator Best = Candidates.begin();
+ CXXMethodDecl *BestMethod = nullptr;
+ for (UnresolvedSetIterator I = Candidates.begin(), E = Candidates.end();
+ I != E; ++I) {
+ auto *Method = cast<CXXMethodDecl>(I->getUnderlyingDecl());
+ if (I == Best ||
+ getMoreConstrainedFunction(Method, BestMethod) == Method) {
+ Best = I;
+ BestMethod = Method;
}
- if (MoreConstrained == Method) {
- Ambiguous = false;
- FoundInstantiation = *I;
- Instantiation = Method;
- InstantiatedFrom = Method->getInstantiatedFromMemberFunction();
- MSInfo = Method->getMemberSpecializationInfo();
+ }
+
+ FoundInstantiation = *Best;
+ Instantiation = BestMethod;
+ InstantiatedFrom = BestMethod->getInstantiatedFromMemberFunction();
+ MSInfo = BestMethod->getMemberSpecializationInfo();
+
+ // Make sure the best candidate is more constrained than all of the others.
+ bool Ambiguous = false;
+ for (UnresolvedSetIterator I = Candidates.begin(), E = Candidates.end();
+ I != E; ++I) {
+ auto *Method = cast<CXXMethodDecl>(I->getUnderlyingDecl());
+ if (I != Best &&
+ getMoreConstrainedFunction(Method, BestMethod) != BestMethod) {
+ Ambiguous = true;
+ break;
}
}
+
if (Ambiguous) {
Diag(Member->getLocation(), diag::err_function_member_spec_ambiguous)
<< Member << (InstantiatedFrom ? InstantiatedFrom : Instantiation);
- for (FunctionDecl *Candidate : Candidates)
+ for (NamedDecl *Candidate : Candidates) {
+ Candidate = Candidate->getUnderlyingDecl();
Diag(Candidate->getLocation(), diag::note_function_member_spec_matched)
<< Candidate;
+ }
return true;
}
} else if (isa<VarDecl>(Member)) {