зеркало из https://github.com/microsoft/clang-1.git
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
This commit is contained in:
Родитель
ec55c941f2
Коммит
01e56aecb7
|
@ -343,6 +343,11 @@ public:
|
|||
} else {
|
||||
ResultKind = Found;
|
||||
resolveKind();
|
||||
|
||||
if (Paths && (ResultKind != Ambiguous)) {
|
||||
deletePaths(Paths);
|
||||
Paths = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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<Expr>();
|
||||
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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
// RUN: %clang_cc1 -verify %s
|
||||
|
||||
template <class T> struct Base { // expected-note 4 {{member found by ambiguous name lookup}}
|
||||
static void f();
|
||||
};
|
||||
|
||||
struct X0 { };
|
||||
|
||||
template <class T> struct Derived: Base<int>, Base<char> {
|
||||
typename Derived::Base b; // expected-error{{member 'Base' found in multiple base classes of different types}}
|
||||
typename Derived::Base<double> d; // OK
|
||||
|
||||
void g(X0 *t) {
|
||||
t->Derived::Base<T>::f();
|
||||
t->Base<T>::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 <typename T>
|
||||
class WebVector {
|
||||
}
|
||||
|
||||
WebVector(const WebVector<T>& other) { }
|
||||
|
||||
template <typename C>
|
||||
WebVector<T>& operator=(const C& other) { } // expected-error{{unknown type name 'WebVector'}} \
|
||||
// expected-error{{unqualified-id}}
|
||||
}
|
Загрузка…
Ссылка в новой задаче