diff options
author | John McCall <rjmccall@apple.com> | 2010-01-27 01:50:18 +0000 |
---|---|---|
committer | John McCall <rjmccall@apple.com> | 2010-01-27 01:50:18 +0000 |
commit | c373d48502ca7683ab55385f5bd624d778eb288d (patch) | |
tree | 0de412804faa62614dc3ee788df2b4e95c80a8c8 /lib/Sema | |
parent | d2bf0cdca441216b0ae7791a59516beac403682d (diff) |
Implement access control for overloaded functions. Suppress access control
diagnostics in "early" lookups, such as during typename checks and when building
unresolved lookup expressions.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@94647 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema')
-rw-r--r-- | lib/Sema/Sema.h | 24 | ||||
-rw-r--r-- | lib/Sema/SemaAccess.cpp | 42 | ||||
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 1 | ||||
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 17 | ||||
-rw-r--r-- | lib/Sema/SemaOverload.cpp | 84 | ||||
-rw-r--r-- | lib/Sema/SemaTemplate.cpp | 40 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateDeduction.cpp | 69 |
7 files changed, 182 insertions, 95 deletions
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index d041f54a02..86d867858b 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -60,6 +60,7 @@ namespace clang { class CallExpr; class DeclRefExpr; class UnresolvedLookupExpr; + class UnresolvedMemberExpr; class VarDecl; class ParmVarDecl; class TypedefDecl; @@ -2376,8 +2377,14 @@ public: CXXBasePaths &Paths, bool NoPrivileges = false); - void CheckAccess(const LookupResult &R); + bool CheckUnresolvedMemberAccess(UnresolvedMemberExpr *E, + NamedDecl *D, + AccessSpecifier Access); + bool CheckUnresolvedLookupAccess(UnresolvedLookupExpr *E, + NamedDecl *D, + AccessSpecifier Access); bool CheckAccess(const LookupResult &R, NamedDecl *D, AccessSpecifier Access); + void CheckAccess(const LookupResult &R); bool CheckBaseClassAccess(QualType Derived, QualType Base, unsigned InaccessibleBaseID, @@ -2882,14 +2889,13 @@ public: FunctionTemplateDecl *getMoreSpecializedTemplate(FunctionTemplateDecl *FT1, FunctionTemplateDecl *FT2, TemplatePartialOrderingContext TPOC); - FunctionDecl *getMostSpecialized(FunctionDecl **Specializations, - unsigned NumSpecializations, - TemplatePartialOrderingContext TPOC, - SourceLocation Loc, - const PartialDiagnostic &NoneDiag, - const PartialDiagnostic &AmbigDiag, - const PartialDiagnostic &CandidateDiag, - unsigned *Index = 0); + UnresolvedSetIterator getMostSpecialized(UnresolvedSetIterator SBegin, + UnresolvedSetIterator SEnd, + TemplatePartialOrderingContext TPOC, + SourceLocation Loc, + const PartialDiagnostic &NoneDiag, + const PartialDiagnostic &AmbigDiag, + const PartialDiagnostic &CandidateDiag); ClassTemplatePartialSpecializationDecl * getMoreSpecializedPartialSpecialization( diff --git a/lib/Sema/SemaAccess.cpp b/lib/Sema/SemaAccess.cpp index 51f9e300ef..26bafa525d 100644 --- a/lib/Sema/SemaAccess.cpp +++ b/lib/Sema/SemaAccess.cpp @@ -16,6 +16,8 @@ #include "clang/AST/ASTContext.h" #include "clang/AST/CXXInheritance.h" #include "clang/AST/DeclCXX.h" +#include "clang/AST/ExprCXX.h" + using namespace clang; /// SetMemberAccessSpecifier - Set the access specifier of a member. @@ -231,6 +233,46 @@ bool Sema::CheckAccess(const LookupResult &R, NamedDecl *D, return true; } +bool Sema::CheckUnresolvedLookupAccess(UnresolvedLookupExpr *E, + NamedDecl *D, AccessSpecifier Access) { + if (!getLangOptions().AccessControl || !E->getNamingClass()) + return false; + + // Fake up a lookup result. + LookupResult R(*this, E->getName(), E->getNameLoc(), LookupOrdinaryName); + R.suppressDiagnostics(); + + R.setNamingClass(E->getNamingClass()); + R.addDecl(D, Access); + + // FIXME: protected check (triggers for member-address expressions) + + return CheckAccess(R, D, Access); +} + +/// Perform access-control checking on a previously-unresolved member +/// access which has now been resolved to a member. +bool Sema::CheckUnresolvedMemberAccess(UnresolvedMemberExpr *E, + NamedDecl *D, AccessSpecifier Access) { + if (!getLangOptions().AccessControl) + return false; + + // Fake up a lookup result. + LookupResult R(*this, E->getMemberName(), E->getMemberLoc(), + LookupOrdinaryName); + R.suppressDiagnostics(); + + R.setNamingClass(E->getNamingClass()); + R.addDecl(D, Access); + + if (CheckAccess(R, D, Access)) + return true; + + // FIXME: protected check + + return false; +} + /// Checks access to all the declarations in the given result set. void Sema::CheckAccess(const LookupResult &R) { for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 876fcb32ba..398c156f9b 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -135,6 +135,7 @@ Sema::TypeTy *Sema::getTypeName(IdentifierInfo &II, SourceLocation NameLoc, case LookupResult::NotFoundInCurrentInstantiation: case LookupResult::FoundOverloaded: case LookupResult::FoundUnresolvedValue: + Result.suppressDiagnostics(); return 0; case LookupResult::Ambiguous: diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 1d0374dcbb..5be017a754 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -1497,16 +1497,20 @@ Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS, CheckDeclInExpr(*this, R.getNameLoc(), R.getFoundDecl())) return ExprError(); + // Otherwise, just build an unresolved lookup expression. Suppress + // any lookup-related diagnostics; we'll hash these out later, when + // we've picked a target. + R.suppressDiagnostics(); + bool Dependent = UnresolvedLookupExpr::ComputeDependence(R.begin(), R.end(), 0); UnresolvedLookupExpr *ULE - = UnresolvedLookupExpr::Create(Context, Dependent, + = UnresolvedLookupExpr::Create(Context, Dependent, R.getNamingClass(), (NestedNameSpecifier*) SS.getScopeRep(), SS.getRange(), R.getLookupName(), R.getNameLoc(), NeedsADL, R.isOverloadedResult()); - for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) - ULE->addDecl(*I); + ULE->addDecls(R.begin(), R.end()); return Owned(ULE); } @@ -2544,6 +2548,10 @@ Sema::BuildMemberReferenceExpr(ExprArg Base, QualType BaseExprType, R.isUnresolvableResult() || UnresolvedLookupExpr::ComputeDependence(R.begin(), R.end(), TemplateArgs); + // Suppress any lookup-related diagnostics; we'll do these when we + // pick a member. + R.suppressDiagnostics(); + UnresolvedMemberExpr *MemExpr = UnresolvedMemberExpr::Create(Context, Dependent, R.isUnresolvableResult(), @@ -2552,8 +2560,7 @@ Sema::BuildMemberReferenceExpr(ExprArg Base, QualType BaseExprType, Qualifier, SS.getRange(), MemberName, MemberLoc, TemplateArgs); - for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) - MemExpr->addDecl(*I); + MemExpr->addDecls(R.begin(), R.end()); return Owned(MemExpr); } diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index 47a7d17519..f2f24ea59a 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -4851,6 +4851,14 @@ Sema::PrintOverloadCandidates(OverloadCandidateSet& CandidateSet, } } +static bool CheckUnresolvedAccess(Sema &S, Expr *E, NamedDecl *D, + AccessSpecifier AS) { + if (isa<UnresolvedLookupExpr>(E)) + return S.CheckUnresolvedLookupAccess(cast<UnresolvedLookupExpr>(E), D, AS); + + return S.CheckUnresolvedMemberAccess(cast<UnresolvedMemberExpr>(E), D, AS); +} + /// ResolveAddressOfOverloadedFunction - Try to resolve the address of /// an overloaded function (C++ [over.over]), where @p From is an /// expression with overloaded function type and @p ToType is the type @@ -4928,7 +4936,7 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType, // Look through all of the overloaded functions, searching for one // whose type matches exactly. - llvm::SmallPtrSet<FunctionDecl *, 4> Matches; + UnresolvedSet<4> Matches; // contains only FunctionDecls bool FoundNonTemplateFunction = false; for (UnresolvedSetIterator I = Fns->begin(), E = Fns->end(); I != E; ++I) { // Look through any using declarations to find the underlying function. @@ -4972,8 +4980,8 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType, // a candidate? Find a testcase before changing the code. assert(FunctionType == Context.getCanonicalType(Specialization->getType())); - Matches.insert( - cast<FunctionDecl>(Specialization->getCanonicalDecl())); + Matches.addDecl(cast<FunctionDecl>(Specialization->getCanonicalDecl()), + I.getAccess()); } continue; @@ -4996,7 +5004,8 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType, if (Context.hasSameUnqualifiedType(FunctionType, FunDecl->getType()) || IsNoReturnConversion(Context, FunDecl->getType(), FunctionType, ResultTy)) { - Matches.insert(cast<FunctionDecl>(FunDecl->getCanonicalDecl())); + Matches.addDecl(cast<FunctionDecl>(FunDecl->getCanonicalDecl()), + I.getAccess()); FoundNonTemplateFunction = true; } } @@ -5006,14 +5015,15 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType, if (Matches.empty()) return 0; else if (Matches.size() == 1) { - FunctionDecl *Result = *Matches.begin(); + FunctionDecl *Result = cast<FunctionDecl>(*Matches.begin()); MarkDeclarationReferenced(From->getLocStart(), Result); + if (Complain) + CheckUnresolvedAccess(*this, OvlExpr, Result, Matches.begin().getAccess()); return Result; } // C++ [over.over]p4: // If more than one function is selected, [...] - typedef llvm::SmallPtrSet<FunctionDecl *, 4>::iterator MatchIter; if (!FoundNonTemplateFunction) { // [...] and any given function template specialization F1 is // eliminated if the set contains a second function template @@ -5025,41 +5035,50 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType, // two-pass algorithm (similar to the one used to identify the // best viable function in an overload set) that identifies the // best function template (if it exists). - llvm::SmallVector<FunctionDecl *, 8> TemplateMatches(Matches.begin(), - Matches.end()); - FunctionDecl *Result = - getMostSpecialized(TemplateMatches.data(), TemplateMatches.size(), + + UnresolvedSetIterator Result = + getMostSpecialized(Matches.begin(), Matches.end(), TPOC_Other, From->getLocStart(), PDiag(), PDiag(diag::err_addr_ovl_ambiguous) - << TemplateMatches[0]->getDeclName(), + << Matches[0]->getDeclName(), PDiag(diag::note_ovl_candidate) << (unsigned) oc_function_template); - MarkDeclarationReferenced(From->getLocStart(), Result); - return Result; + assert(Result != Matches.end() && "no most-specialized template"); + MarkDeclarationReferenced(From->getLocStart(), *Result); + if (Complain) + CheckUnresolvedAccess(*this, OvlExpr, *Result, Result.getAccess()); + return cast<FunctionDecl>(*Result); } // [...] any function template specializations in the set are // eliminated if the set also contains a non-template function, [...] - llvm::SmallVector<FunctionDecl *, 4> RemainingMatches; - for (MatchIter M = Matches.begin(), MEnd = Matches.end(); M != MEnd; ++M) - if ((*M)->getPrimaryTemplate() == 0) - RemainingMatches.push_back(*M); + for (unsigned I = 0, N = Matches.size(); I != N; ) { + if (cast<FunctionDecl>(Matches[I].getDecl())->getPrimaryTemplate() == 0) + ++I; + else { + Matches.erase(I); + --N; + } + } // [...] After such eliminations, if any, there shall remain exactly one // selected function. - if (RemainingMatches.size() == 1) { - FunctionDecl *Result = RemainingMatches.front(); - MarkDeclarationReferenced(From->getLocStart(), Result); - return Result; + if (Matches.size() == 1) { + UnresolvedSetIterator Match = Matches.begin(); + MarkDeclarationReferenced(From->getLocStart(), *Match); + if (Complain) + CheckUnresolvedAccess(*this, OvlExpr, *Match, Match.getAccess()); + return cast<FunctionDecl>(*Match); } // FIXME: We should probably return the same thing that BestViableFunction // returns (even if we issue the diagnostics here). Diag(From->getLocStart(), diag::err_addr_ovl_ambiguous) - << RemainingMatches[0]->getDeclName(); - for (unsigned I = 0, N = RemainingMatches.size(); I != N; ++I) - NoteOverloadCandidate(RemainingMatches[I]); + << Matches[0]->getDeclName(); + for (UnresolvedSetIterator I = Matches.begin(), + E = Matches.end(); I != E; ++I) + NoteOverloadCandidate(cast<FunctionDecl>(*I)); return 0; } @@ -5345,6 +5364,7 @@ Sema::BuildOverloadedCallExpr(Expr *Fn, UnresolvedLookupExpr *ULE, switch (BestViableFunction(CandidateSet, Fn->getLocStart(), Best)) { case OR_Success: { FunctionDecl *FDecl = Best->Function; + CheckUnresolvedLookupAccess(ULE, FDecl, Best->getAccess()); Fn = FixOverloadedFunctionReference(Fn, FDecl); return BuildResolvedCallExpr(Fn, FDecl, LParenLoc, Args, NumArgs, RParenLoc); } @@ -5425,8 +5445,9 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned OpcIn, } if (Input->isTypeDependent()) { + CXXRecordDecl *NamingClass = 0; // because lookup ignores member operators UnresolvedLookupExpr *Fn - = UnresolvedLookupExpr::Create(Context, /*Dependent*/ true, + = UnresolvedLookupExpr::Create(Context, /*Dependent*/ true, NamingClass, 0, SourceRange(), OpName, OpLoc, /*ADL*/ true, IsOverloaded(Fns)); Fn->addDecls(Fns.begin(), Fns.end()); @@ -5467,6 +5488,8 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned OpcIn, // We matched an overloaded operator. Build a call to that // operator. + // FIXME: access control + // Convert the arguments. if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(FnDecl)) { if (PerformObjectArgumentInitialization(Input, Method)) @@ -5592,8 +5615,9 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc, } // FIXME: save results of ADL from here? + CXXRecordDecl *NamingClass = 0; // because lookup ignores member operators UnresolvedLookupExpr *Fn - = UnresolvedLookupExpr::Create(Context, /*Dependent*/ true, + = UnresolvedLookupExpr::Create(Context, /*Dependent*/ true, NamingClass, 0, SourceRange(), OpName, OpLoc, /*ADL*/ true, IsOverloaded(Fns)); @@ -5647,6 +5671,8 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc, // We matched an overloaded operator. Build a call to that // operator. + // FIXME: access control + // Convert the arguments. if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(FnDecl)) { OwningExprResult Arg1 @@ -5783,8 +5809,9 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc, // expression. if (Args[0]->isTypeDependent() || Args[1]->isTypeDependent()) { + CXXRecordDecl *NamingClass = 0; // because lookup ignores member operators UnresolvedLookupExpr *Fn - = UnresolvedLookupExpr::Create(Context, /*Dependent*/ true, + = UnresolvedLookupExpr::Create(Context, /*Dependent*/ true, NamingClass, 0, SourceRange(), OpName, LLoc, /*ADL*/ true, /*Overloaded*/ false); // Can't add any actual overloads yet @@ -5819,6 +5846,8 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc, // We matched an overloaded operator. Build a call to that // operator. + // FIXME: access control + // Convert the arguments. CXXMethodDecl *Method = cast<CXXMethodDecl>(FnDecl); if (PerformObjectArgumentInitialization(Args[0], Method) || @@ -5968,6 +5997,7 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, switch (BestViableFunction(CandidateSet, UnresExpr->getLocStart(), Best)) { case OR_Success: Method = cast<CXXMethodDecl>(Best->Function); + CheckUnresolvedMemberAccess(UnresExpr, Method, Best->getAccess()); break; case OR_No_Viable_Function: diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index 00401560c6..f660b3c2ee 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -1525,17 +1525,19 @@ Sema::OwningExprResult Sema::BuildTemplateIdExpr(const CXXScopeSpec &SS, Qualifier = static_cast<NestedNameSpecifier*>(SS.getScopeRep()); QualifierRange = SS.getRange(); } + + // We don't want lookup warnings at this point. + R.suppressDiagnostics(); bool Dependent = UnresolvedLookupExpr::ComputeDependence(R.begin(), R.end(), &TemplateArgs); UnresolvedLookupExpr *ULE - = UnresolvedLookupExpr::Create(Context, Dependent, + = UnresolvedLookupExpr::Create(Context, Dependent, R.getNamingClass(), Qualifier, QualifierRange, R.getLookupName(), R.getNameLoc(), RequiresADL, TemplateArgs); - for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) - ULE->addDecl(*I); + ULE->addDecls(R.begin(), R.end()); return Owned(ULE); } @@ -3817,8 +3819,7 @@ Sema::CheckFunctionTemplateSpecialization(FunctionDecl *FD, LookupResult &Previous) { // The set of function template specializations that could match this // explicit function template specialization. - typedef llvm::SmallVector<FunctionDecl *, 8> CandidateSet; - CandidateSet Candidates; + UnresolvedSet<8> Candidates; DeclContext *FDLookupContext = FD->getDeclContext()->getLookupContext(); for (LookupResult::iterator I = Previous.begin(), E = Previous.end(); @@ -3851,22 +3852,24 @@ Sema::CheckFunctionTemplateSpecialization(FunctionDecl *FD, } // Record this candidate. - Candidates.push_back(Specialization); + Candidates.addDecl(Specialization, I.getAccess()); } } // Find the most specialized function template. - FunctionDecl *Specialization = getMostSpecialized(Candidates.data(), - Candidates.size(), - TPOC_Other, - FD->getLocation(), + UnresolvedSetIterator Result + = getMostSpecialized(Candidates.begin(), Candidates.end(), + TPOC_Other, FD->getLocation(), PartialDiagnostic(diag::err_function_template_spec_no_match) << FD->getDeclName(), PartialDiagnostic(diag::err_function_template_spec_ambiguous) << FD->getDeclName() << (ExplicitTemplateArgs != 0), PartialDiagnostic(diag::note_function_template_spec_matched)); - if (!Specialization) + if (Result == Candidates.end()) return true; + + // Ignore access information; it doesn't figure into redeclaration checking. + FunctionDecl *Specialization = cast<FunctionDecl>(*Result); // FIXME: Check if the prior specialization has a point of instantiation. // If so, we have run afoul of . @@ -4568,7 +4571,7 @@ Sema::DeclResult Sema::ActOnExplicitInstantiation(Scope *S, // A member function [...] of a class template can be explicitly // instantiated from the member definition associated with its class // template. - llvm::SmallVector<FunctionDecl *, 8> Matches; + UnresolvedSet<8> Matches; for (LookupResult::iterator P = Previous.begin(), PEnd = Previous.end(); P != PEnd; ++P) { NamedDecl *Prev = *P; @@ -4577,7 +4580,7 @@ Sema::DeclResult Sema::ActOnExplicitInstantiation(Scope *S, if (Context.hasSameUnqualifiedType(Method->getType(), R)) { Matches.clear(); - Matches.push_back(Method); + Matches.addDecl(Method, P.getAccess()); if (Method->getTemplateSpecializationKind() == TSK_Undeclared) break; } @@ -4599,19 +4602,22 @@ Sema::DeclResult Sema::ActOnExplicitInstantiation(Scope *S, continue; } - Matches.push_back(Specialization); + Matches.addDecl(Specialization, P.getAccess()); } // Find the most specialized function template specialization. - FunctionDecl *Specialization - = getMostSpecialized(Matches.data(), Matches.size(), TPOC_Other, + UnresolvedSetIterator Result + = getMostSpecialized(Matches.begin(), Matches.end(), TPOC_Other, D.getIdentifierLoc(), PartialDiagnostic(diag::err_explicit_instantiation_not_known) << Name, PartialDiagnostic(diag::err_explicit_instantiation_ambiguous) << Name, PartialDiagnostic(diag::note_explicit_instantiation_candidate)); - if (!Specialization) + if (Result == Matches.end()) return true; + + // Ignore access control bits, we don't need them for redeclaration checking. + FunctionDecl *Specialization = cast<FunctionDecl>(*Result); if (Specialization->getTemplateSpecializationKind() == TSK_Undeclared) { Diag(D.getIdentifierLoc(), diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp index 7b433e901e..b9160930cb 100644 --- a/lib/Sema/SemaTemplateDeduction.cpp +++ b/lib/Sema/SemaTemplateDeduction.cpp @@ -1987,11 +1987,11 @@ static bool isSameTemplate(TemplateDecl *T1, TemplateDecl *T2) { /// \brief Retrieve the most specialized of the given function template /// specializations. /// -/// \param Specializations the set of function template specializations that -/// we will be comparing. +/// \param SpecBegin the start iterator of the function template +/// specializations that we will be comparing. /// -/// \param NumSpecializations the number of function template specializations in -/// \p Specializations +/// \param SpecEnd the end iterator of the function template +/// specializations, paired with \p SpecBegin. /// /// \param TPOC the partial ordering context to use to compare the function /// template specializations. @@ -2015,41 +2015,37 @@ static bool isSameTemplate(TemplateDecl *T1, TemplateDecl *T2) { /// specialization. /// /// \returns the most specialized function template specialization, if -/// found. Otherwise, returns NULL. +/// found. Otherwise, returns SpecEnd. /// /// \todo FIXME: Consider passing in the "also-ran" candidates that failed /// template argument deduction. -FunctionDecl *Sema::getMostSpecialized(FunctionDecl **Specializations, - unsigned NumSpecializations, - TemplatePartialOrderingContext TPOC, - SourceLocation Loc, - const PartialDiagnostic &NoneDiag, - const PartialDiagnostic &AmbigDiag, - const PartialDiagnostic &CandidateDiag, - unsigned *Index) { - if (NumSpecializations == 0) { +UnresolvedSetIterator +Sema::getMostSpecialized(UnresolvedSetIterator SpecBegin, + UnresolvedSetIterator SpecEnd, + TemplatePartialOrderingContext TPOC, + SourceLocation Loc, + const PartialDiagnostic &NoneDiag, + const PartialDiagnostic &AmbigDiag, + const PartialDiagnostic &CandidateDiag) { + if (SpecBegin == SpecEnd) { Diag(Loc, NoneDiag); - return 0; + return SpecEnd; } - if (NumSpecializations == 1) { - if (Index) - *Index = 0; - - return Specializations[0]; - } - + if (SpecBegin + 1 == SpecEnd) + return SpecBegin; // Find the function template that is better than all of the templates it // has been compared to. - unsigned Best = 0; + UnresolvedSetIterator Best = SpecBegin; FunctionTemplateDecl *BestTemplate - = Specializations[Best]->getPrimaryTemplate(); + = cast<FunctionDecl>(*Best)->getPrimaryTemplate(); assert(BestTemplate && "Not a function template specialization?"); - for (unsigned I = 1; I != NumSpecializations; ++I) { - FunctionTemplateDecl *Challenger = Specializations[I]->getPrimaryTemplate(); + for (UnresolvedSetIterator I = SpecBegin + 1; I != SpecEnd; ++I) { + FunctionTemplateDecl *Challenger + = cast<FunctionDecl>(*I)->getPrimaryTemplate(); assert(Challenger && "Not a function template specialization?"); - if (isSameTemplate(getMoreSpecializedTemplate(BestTemplate, Challenger, + if (isSameTemplate(getMoreSpecializedTemplate(BestTemplate, Challenger, TPOC), Challenger)) { Best = I; @@ -2060,8 +2056,9 @@ FunctionDecl *Sema::getMostSpecialized(FunctionDecl **Specializations, // Make sure that the "best" function template is more specialized than all // of the others. bool Ambiguous = false; - for (unsigned I = 0; I != NumSpecializations; ++I) { - FunctionTemplateDecl *Challenger = Specializations[I]->getPrimaryTemplate(); + for (UnresolvedSetIterator I = SpecBegin; I != SpecEnd; ++I) { + FunctionTemplateDecl *Challenger + = cast<FunctionDecl>(*I)->getPrimaryTemplate(); if (I != Best && !isSameTemplate(getMoreSpecializedTemplate(BestTemplate, Challenger, TPOC), @@ -2073,22 +2070,20 @@ FunctionDecl *Sema::getMostSpecialized(FunctionDecl **Specializations, if (!Ambiguous) { // We found an answer. Return it. - if (Index) - *Index = Best; - return Specializations[Best]; + return Best; } // Diagnose the ambiguity. Diag(Loc, AmbigDiag); // FIXME: Can we order the candidates in some sane way? - for (unsigned I = 0; I != NumSpecializations; ++I) - Diag(Specializations[I]->getLocation(), CandidateDiag) + for (UnresolvedSetIterator I = SpecBegin; I != SpecEnd; ++I) + Diag((*I)->getLocation(), CandidateDiag) << getTemplateArgumentBindingsText( - Specializations[I]->getPrimaryTemplate()->getTemplateParameters(), - *Specializations[I]->getTemplateSpecializationArgs()); + cast<FunctionDecl>(*I)->getPrimaryTemplate()->getTemplateParameters(), + *cast<FunctionDecl>(*I)->getTemplateSpecializationArgs()); - return 0; + return SpecEnd; } /// \brief Returns the more specialized class template partial specialization |