diff options
Diffstat (limited to 'clang/lib/Sema/SemaTemplate.cpp')
| -rw-r--r-- | clang/lib/Sema/SemaTemplate.cpp | 76 |
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)) { |
