diff --git a/lib/Sema/Lookup.h b/lib/Sema/Lookup.h index 73559a246d..97bc4f25a5 100644 --- a/lib/Sema/Lookup.h +++ b/lib/Sema/Lookup.h @@ -343,6 +343,11 @@ public: } else { ResultKind = Found; resolveKind(); + + if (Paths && (ResultKind != Ambiguous)) { + deletePaths(Paths); + Paths = 0; + } } } diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index d6f135863d..84b4c75399 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -2454,7 +2454,8 @@ Sema::ActOnDependentMemberExpr(ExprArg Base, QualType BaseType, } } - assert(BaseType->isDependentType() || Name.isDependentName()); + assert(BaseType->isDependentType() || Name.isDependentName() || + isDependentScopeSpecifier(SS)); // Get the type being accessed in BaseType. If this is an arrow, the BaseExpr // must have pointer type, and the accessed type is the pointee. @@ -3200,7 +3201,8 @@ Sema::OwningExprResult Sema::ActOnMemberAccessExpr(Scope *S, ExprArg BaseArg, Expr *Base = BaseArg.takeAs(); OwningExprResult Result(*this); - if (Base->getType()->isDependentType() || Name.isDependentName()) { + if (Base->getType()->isDependentType() || Name.isDependentName() || + isDependentScopeSpecifier(SS)) { Result = ActOnDependentMemberExpr(ExprArg(*this, Base), Base->getType(), IsArrow, OpLoc, SS, FirstQualifierInScope, 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 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(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 diff --git a/test/CXX/temp/temp.res/temp.local/p3.cpp b/test/CXX/temp/temp.res/temp.local/p3.cpp new file mode 100644 index 0000000000..88f8963e6b --- /dev/null +++ b/test/CXX/temp/temp.res/temp.local/p3.cpp @@ -0,0 +1,32 @@ +// RUN: %clang_cc1 -verify %s + +template struct Base { // expected-note 4 {{member found by ambiguous name lookup}} + static void f(); +}; + +struct X0 { }; + +template struct Derived: Base, Base { + typename Derived::Base b; // expected-error{{member 'Base' found in multiple base classes of different types}} + typename Derived::Base d; // OK + + void g(X0 *t) { + t->Derived::Base::f(); + t->Base::f(); + t->Base::f(); // expected-error{{member 'Base' found in multiple base classes of different types}} \ + // expected-error{{no member named 'f' in 'X0'}} \ + // expected-error{{expected a class or namespace}} + } +}; + +namespace PR6717 { + template + class WebVector { + } + + WebVector(const WebVector& other) { } + + template + WebVector& operator=(const C& other) { } // expected-error{{unknown type name 'WebVector'}} \ + // expected-error{{unqualified-id}} +}