Fix some major problems dealing with dependently-qualified names in implicit

member-reference contexts.  Fixes some clang-on-clang asserts.

llvm-svn: 89796
This commit is contained in:
John McCall 2009-11-24 20:33:45 +00:00
parent b3e0168428
commit 45b1a47a9c
2 changed files with 81 additions and 4 deletions

View File

@ -327,7 +327,11 @@ static bool HasDependentTypeAsBase(ASTContext &Context,
// };
CanQual<RecordType> RT = BaseT->getAs<RecordType>();
assert(RT && "base is not a record type");
// Base might be a dependent member type, in which case we
// obviously can't look into it.
if (!RT) continue;
CXXRecordDecl *BaseRecord = cast<CXXRecordDecl>(RT->getDecl());
if (BaseRecord->isDefinition() &&
HasDependentTypeAsBase(Context, BaseRecord, T))
@ -364,14 +368,17 @@ static bool IsImplicitDependentMemberReference(Sema &SemaRef,
QualType QT = GetTypeForQualifier(Context, Qualifier);
CanQualType T = Context.getCanonicalType(QT);
// And now, just walk the non-dependent type hierarchy, trying to
// find the given type as a literal base class.
CXXRecordDecl *Record = cast<CXXRecordDecl>(MD->getParent());
if (Context.getCanonicalType(Context.getTypeDeclType(Record)) == T)
if (Context.getCanonicalType(Context.getTypeDeclType(Record)) == T ||
HasDependentTypeAsBase(Context, Record, T)) {
ThisType = MD->getThisType(Context);
return true;
}
return HasDependentTypeAsBase(Context, Record, T);
return false;
}
/// ActOnDependentIdExpression - Handle a dependent declaration name

View File

@ -14,3 +14,73 @@ int a0[sizeof(X<int>::a) == sizeof(double) ? 1 : -1];
// PR4365.
template<class T> class Q;
template<class T> class R : Q<T> {T current;};
namespace test0 {
template <class T> class Base {
void instance_foo();
static void static_foo();
class Inner {
void instance_foo();
static void static_foo();
};
};
template <class T> class Derived1 : Base<T> {
void test0() {
Base<T>::static_foo();
Base<T>::instance_foo();
}
void test1() {
Base<T>::Inner::static_foo();
Base<T>::Inner::instance_foo(); // expected-error {{call to non-static member function without an object argument}}
}
static void test2() {
Base<T>::static_foo();
Base<T>::instance_foo(); // expected-error {{call to non-static member function without an object argument}}
}
static void test3() {
Base<T>::Inner::static_foo();
Base<T>::Inner::instance_foo(); // expected-error {{call to non-static member function without an object argument}}
}
};
template <class T> class Derived2 : Base<T>::Inner {
void test0() {
Base<T>::static_foo();
Base<T>::instance_foo(); // expected-error {{call to non-static member function without an object argument}}
}
void test1() {
Base<T>::Inner::static_foo();
Base<T>::Inner::instance_foo();
}
static void test2() {
Base<T>::static_foo();
Base<T>::instance_foo(); // expected-error {{call to non-static member function without an object argument}}
}
static void test3() {
Base<T>::Inner::static_foo();
Base<T>::Inner::instance_foo(); // expected-error {{call to non-static member function without an object argument}}
}
};
void test0() {
Derived1<int> d1;
d1.test0();
d1.test1(); // expected-note {{in instantiation of member function}}
d1.test2(); // expected-note {{in instantiation of member function}}
d1.test3(); // expected-note {{in instantiation of member function}}
Derived2<int> d2;
d2.test0(); // expected-note {{in instantiation of member function}}
d2.test1();
d2.test2(); // expected-note {{in instantiation of member function}}
d2.test3(); // expected-note {{in instantiation of member function}}
}
}