]> granicus.if.org Git - clang/commitdiff
The member classes of a current instantiation aren't necessarily a
authorDouglas Gregor <dgregor@apple.com>
Sat, 19 Feb 2011 19:24:40 +0000 (19:24 +0000)
committerDouglas Gregor <dgregor@apple.com>
Sat, 19 Feb 2011 19:24:40 +0000 (19:24 +0000)
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

lib/Sema/SemaCXXScopeSpec.cpp
test/SemaTemplate/current-instantiation.cpp

index c7affed3118e324ddcd36517cc10f5f7fc2be988..aa0efcdc70e197cd19dc4c3db1a50f895beedc87 100644 (file)
 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<RecordType>(Ty))
-    return cast<CXXRecordDecl>(cast<RecordType>(Ty)->getDecl());
-  else if (isa<InjectedClassNameType>(Ty))
+  if (const RecordType *RecordTy = dyn_cast<RecordType>(Ty)) {
+    CXXRecordDecl *Record = cast<CXXRecordDecl>(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<InjectedClassNameType>(Ty))
     return cast<InjectedClassNameType>(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<TagType>())
-    return Tag->getDecl();
+  if (!T->isDependentType())
+    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
@@ -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.
index 8caac9399a8747ba02c3aad265657ab561685327..fe7213f14385114b45162988f12320aaf21a4f73 100644 (file)
@@ -199,3 +199,19 @@ namespace Expressions {
   typename Enable_If<Is_Same<U, Class<T> >::value, void>::type
   Class<T>::foo() {}
 }
+
+namespace PR9255 {
+  template<typename T>
+  class X0  {
+  public:
+    class Inner1;
+
+    class Inner2  {
+    public:
+      void f()
+      {
+        Inner1::f.g();
+      }
+    };
+  };
+}