From bf2b26d805d62ea214c96eac6bfd806ad733fe64 Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Sat, 19 Feb 2011 19:24:40 +0000 Subject: [PATCH] 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 :) llvm-svn: 126038 --- clang/lib/Sema/SemaCXXScopeSpec.cpp | 29 ++++++++++++++----- .../SemaTemplate/current-instantiation.cpp | 16 ++++++++++ 2 files changed, 37 insertions(+), 8 deletions(-) diff --git a/clang/lib/Sema/SemaCXXScopeSpec.cpp b/clang/lib/Sema/SemaCXXScopeSpec.cpp index c7affed3118e..aa0efcdc70e1 100644 --- a/clang/lib/Sema/SemaCXXScopeSpec.cpp +++ b/clang/lib/Sema/SemaCXXScopeSpec.cpp @@ -24,14 +24,26 @@ using namespace clang; /// \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()) return 0; const Type *Ty = T->getCanonicalTypeInternal().getTypePtr(); - if (isa(Ty)) - return cast(cast(Ty)->getDecl()); - else if (isa(Ty)) + if (const RecordType *RecordTy = dyn_cast(Ty)) { + CXXRecordDecl *Record = cast(RecordTy->getDecl()); + 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(Ty)) return cast(Ty)->getDecl(); else 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 /// dependent and not the current instantiation). DeclContext *Sema::computeDeclContext(QualType T) { - if (const TagType *Tag = T->getAs()) - return Tag->getDecl(); + if (!T->isDependentType()) + if (const TagType *Tag = T->getAs()) + return Tag->getDecl(); - return ::getCurrentInstantiationOf(T); + return ::getCurrentInstantiationOf(T, CurContext); } /// \brief Compute the DeclContext that is associated with the given @@ -174,7 +187,7 @@ CXXRecordDecl *Sema::getCurrentInstantiationOf(NestedNameSpecifier *NNS) { return 0; QualType T = QualType(NNS->getAsType(), 0); - return ::getCurrentInstantiationOf(T); + return ::getCurrentInstantiationOf(T, CurContext); } /// \brief Require that the context specified by SS be complete. diff --git a/clang/test/SemaTemplate/current-instantiation.cpp b/clang/test/SemaTemplate/current-instantiation.cpp index 8caac9399a87..fe7213f14385 100644 --- a/clang/test/SemaTemplate/current-instantiation.cpp +++ b/clang/test/SemaTemplate/current-instantiation.cpp @@ -199,3 +199,19 @@ namespace Expressions { typename Enable_If >::value, void>::type Class::foo() {} } + +namespace PR9255 { + template + class X0 { + public: + class Inner1; + + class Inner2 { + public: + void f() + { + Inner1::f.g(); + } + }; + }; +}