The member classes of a current instantiation aren't necessarily a

current instantiation, even though we have a RecordDecl describing
them. Fixes PR9255.

Amusingly, I've had this patch sitting around for a month or two
because it was "obviously" wrong, but hadn't gotten around to writing
a test case to submit the fix :)


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@126038 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Douglas Gregor 2011-02-19 19:24:40 +00:00
Родитель e41721e7df
Коммит d9ea180032
2 изменённых файлов: 37 добавлений и 8 удалений

Просмотреть файл

@ -24,14 +24,26 @@
using namespace clang; using namespace clang;
/// \brief Find the current instantiation that associated with the given type. /// \brief Find the current instantiation that associated with the given type.
static CXXRecordDecl *getCurrentInstantiationOf(QualType T) { static CXXRecordDecl *getCurrentInstantiationOf(QualType T,
DeclContext *CurContext) {
if (T.isNull()) if (T.isNull())
return 0; return 0;
const Type *Ty = T->getCanonicalTypeInternal().getTypePtr(); const Type *Ty = T->getCanonicalTypeInternal().getTypePtr();
if (isa<RecordType>(Ty)) if (const RecordType *RecordTy = dyn_cast<RecordType>(Ty)) {
return cast<CXXRecordDecl>(cast<RecordType>(Ty)->getDecl()); CXXRecordDecl *Record = cast<CXXRecordDecl>(RecordTy->getDecl());
else if (isa<InjectedClassNameType>(Ty)) if (!T->isDependentType())
return Record;
// This may be a member of a class template or class template partial
// specialization. If it's part of the current semantic context, then it's
// an injected-class-name;
for (; !CurContext->isFileContext(); CurContext = CurContext->getParent())
if (CurContext->Equals(Record))
return Record;
return 0;
} else if (isa<InjectedClassNameType>(Ty))
return cast<InjectedClassNameType>(Ty)->getDecl(); return cast<InjectedClassNameType>(Ty)->getDecl();
else else
return 0; return 0;
@ -45,10 +57,11 @@ static CXXRecordDecl *getCurrentInstantiationOf(QualType T) {
/// or NULL if the declaration context cannot be computed (e.g., because it is /// or NULL if the declaration context cannot be computed (e.g., because it is
/// dependent and not the current instantiation). /// dependent and not the current instantiation).
DeclContext *Sema::computeDeclContext(QualType T) { DeclContext *Sema::computeDeclContext(QualType T) {
if (const TagType *Tag = T->getAs<TagType>()) if (!T->isDependentType())
return Tag->getDecl(); if (const TagType *Tag = T->getAs<TagType>())
return Tag->getDecl();
return ::getCurrentInstantiationOf(T); return ::getCurrentInstantiationOf(T, CurContext);
} }
/// \brief Compute the DeclContext that is associated with the given /// \brief Compute the DeclContext that is associated with the given
@ -174,7 +187,7 @@ CXXRecordDecl *Sema::getCurrentInstantiationOf(NestedNameSpecifier *NNS) {
return 0; return 0;
QualType T = QualType(NNS->getAsType(), 0); QualType T = QualType(NNS->getAsType(), 0);
return ::getCurrentInstantiationOf(T); return ::getCurrentInstantiationOf(T, CurContext);
} }
/// \brief Require that the context specified by SS be complete. /// \brief Require that the context specified by SS be complete.

Просмотреть файл

@ -199,3 +199,19 @@ namespace Expressions {
typename Enable_If<Is_Same<U, Class<T> >::value, void>::type typename Enable_If<Is_Same<U, Class<T> >::value, void>::type
Class<T>::foo() {} Class<T>::foo() {}
} }
namespace PR9255 {
template<typename T>
class X0 {
public:
class Inner1;
class Inner2 {
public:
void f()
{
Inner1::f.g();
}
};
};
}