diff options
author | Douglas Gregor <dgregor@apple.com> | 2010-04-12 20:54:26 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2010-04-12 20:54:26 +0000 |
commit | 01e56aecb77a96dcd93fa0e901b919f2e441981d (patch) | |
tree | 988b720e51cb2656c616b4e4b74a89fda3963a5c /lib/Sema/SemaTemplate.cpp | |
parent | ec55c941f2846db48bce4ed6dd2ce339e1a48962 (diff) |
Implement C++ [temp.local]p4, which specifies how we eliminate
name-lookup ambiguities when there are multiple base classes that are
all specializations of the same class template. This is part of a
general cleanup for ambiguities in template-name lookup. Fixes
PR6717.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@101065 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaTemplate.cpp')
-rw-r--r-- | lib/Sema/SemaTemplate.cpp | 31 |
1 files changed, 23 insertions, 8 deletions
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index d1577a5ab6..828085b8bc 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -63,14 +63,34 @@ static NamedDecl *isAcceptableTemplateName(ASTContext &Context, NamedDecl *D) { } static void FilterAcceptableTemplateNames(ASTContext &C, LookupResult &R) { + // The set of class templates we've already seen. + llvm::SmallPtrSet<ClassTemplateDecl *, 8> ClassTemplates; LookupResult::Filter filter = R.makeFilter(); while (filter.hasNext()) { NamedDecl *Orig = filter.next(); NamedDecl *Repl = isAcceptableTemplateName(C, Orig->getUnderlyingDecl()); if (!Repl) filter.erase(); - else if (Repl != Orig) + else if (Repl != Orig) { + + // C++ [temp.local]p3: + // A lookup that finds an injected-class-name (10.2) can result in an + // ambiguity in certain cases (for example, if it is found in more than + // one base class). If all of the injected-class-names that are found + // refer to specializations of the same class template, and if the name + // is followed by a template-argument-list, the reference refers to the + // class template itself and not a specialization thereof, and is not + // ambiguous. + // + // FIXME: Will we eventually have to do the same for alias templates? + if (ClassTemplateDecl *ClassTmpl = dyn_cast<ClassTemplateDecl>(Repl)) + if (!ClassTemplates.insert(ClassTmpl)) { + filter.erase(); + continue; + } + filter.replace(Repl); + } } filter.done(); } @@ -109,7 +129,7 @@ TemplateNameKind Sema::isTemplateName(Scope *S, LookupOrdinaryName); R.suppressDiagnostics(); LookupTemplateName(R, S, SS, ObjectType, EnteringContext); - if (R.empty()) + if (R.empty() || R.isAmbiguous()) return TNK_Non_template; TemplateName Template; @@ -227,10 +247,6 @@ void Sema::LookupTemplateName(LookupResult &Found, LookupName(Found, S); } - // FIXME: Cope with ambiguous name-lookup results. - assert(!Found.isAmbiguous() && - "Cannot handle template name-lookup ambiguities"); - if (Found.empty() && !isDependent) { // If we did not find any names, attempt to correct any typos. DeclarationName Name = Found.getLookupName(); @@ -271,8 +287,7 @@ void Sema::LookupTemplateName(LookupResult &Found, LookupOrdinaryName); LookupName(FoundOuter, S); FilterAcceptableTemplateNames(Context, FoundOuter); - // FIXME: Handle ambiguities in this lookup better - + if (FoundOuter.empty()) { // - if the name is not found, the name found in the class of the // object expression is used, otherwise |