зеркало из https://github.com/microsoft/clang-1.git
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:
Родитель
e41721e7df
Коммит
d9ea180032
|
@ -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();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
Загрузка…
Ссылка в новой задаче