[cfe-commits] r143725 - in /cfe/trunk: lib/Sema/SemaTemplateInstantiateDecl.cpp test/SemaTemplate/class-template-decl.cpp

Devang Patel dpatel at apple.com
Fri Nov 4 11:52:43 PDT 2011


Author: dpatel
Date: Fri Nov  4 13:52:43 2011
New Revision: 143725

URL: http://llvm.org/viewvc/llvm-project?rev=143725&view=rev
Log:
Revert r143551. It is causing g++.dg/template/crash52.C test failure.

Modified:
    cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
    cfe/trunk/test/SemaTemplate/class-template-decl.cpp

Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=143725&r1=143724&r2=143725&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Fri Nov  4 13:52:43 2011
@@ -3148,49 +3148,75 @@
     if (!Record->isDependentContext())
       return D;
 
-    // Determine whether this record is the "templated" declaration describing
-    // a class template or class template partial specialization.
+    // If the RecordDecl is actually the injected-class-name or a
+    // "templated" declaration for a class template, class template
+    // partial specialization, or a member class of a class template,
+    // substitute into the injected-class-name of the class template
+    // or partial specialization to find the new DeclContext.
+    QualType T;
     ClassTemplateDecl *ClassTemplate = Record->getDescribedClassTemplate();
-    if (ClassTemplate)
-      ClassTemplate = ClassTemplate->getCanonicalDecl();
-    else if (ClassTemplatePartialSpecializationDecl *PartialSpec
-               = dyn_cast<ClassTemplatePartialSpecializationDecl>(Record))
-      ClassTemplate = PartialSpec->getSpecializedTemplate()->getCanonicalDecl();
-    
-    // Walk the current context to find either the record or an instantiation of
-    // it.
-    DeclContext *DC = CurContext;
-    while (!DC->isFileContext()) {
-      // If we're performing substitution while we're inside the template
-      // definition, we'll find our own context. We're done.
-      if (DC->Equals(Record))
-        return Record;
-      
-      if (CXXRecordDecl *InstRecord = dyn_cast<CXXRecordDecl>(DC)) {
-        // Check whether we're in the process of instantiating a class template
-        // specialization of the template we're mapping.
-        if (ClassTemplateSpecializationDecl *InstSpec
-                      = dyn_cast<ClassTemplateSpecializationDecl>(InstRecord)){
-          ClassTemplateDecl *SpecTemplate = InstSpec->getSpecializedTemplate();
-          if (ClassTemplate && isInstantiationOf(ClassTemplate, SpecTemplate))
-            return InstRecord;
-        }
-      
-        // Check whether we're in the process of instantiating a member class.
-        if (isInstantiationOf(Record, InstRecord))
-          return InstRecord;
+
+    if (ClassTemplate) {
+      T = ClassTemplate->getInjectedClassNameSpecialization();
+    } else if (ClassTemplatePartialSpecializationDecl *PartialSpec
+                 = dyn_cast<ClassTemplatePartialSpecializationDecl>(Record)) {
+      ClassTemplate = PartialSpec->getSpecializedTemplate();
+
+      // If we call SubstType with an InjectedClassNameType here we
+      // can end up in an infinite loop.
+      T = Context.getTypeDeclType(Record);
+      assert(isa<InjectedClassNameType>(T) &&
+             "type of partial specialization is not an InjectedClassNameType");
+      T = cast<InjectedClassNameType>(T)->getInjectedSpecializationType();
+    }
+
+    if (!T.isNull()) {
+      // Substitute into the injected-class-name to get the type
+      // corresponding to the instantiation we want, which may also be
+      // the current instantiation (if we're in a template
+      // definition). This substitution should never fail, since we
+      // know we can instantiate the injected-class-name or we
+      // wouldn't have gotten to the injected-class-name!
+
+      // FIXME: Can we use the CurrentInstantiationScope to avoid this
+      // extra instantiation in the common case?
+      T = SubstType(T, TemplateArgs, Loc, DeclarationName());
+      assert(!T.isNull() && "Instantiation of injected-class-name cannot fail.");
+
+      if (!T->isDependentType()) {
+        assert(T->isRecordType() && "Instantiation must produce a record type");
+        return T->getAs<RecordType>()->getDecl();
       }
-      
-      
-      // Move to the outer template scope.
-      if (FunctionDecl *FD = dyn_cast<FunctionDecl>(DC)) {
-        if (FD->getFriendObjectKind() && FD->getDeclContext()->isFileContext()){
-          DC = FD->getLexicalDeclContext();
-          continue;
-        }
+
+      // We are performing "partial" template instantiation to create
+      // the member declarations for the members of a class template
+      // specialization. Therefore, D is actually referring to something
+      // in the current instantiation. Look through the current
+      // context, which contains actual instantiations, to find the
+      // instantiation of the "current instantiation" that D refers
+      // to.
+      bool SawNonDependentContext = false;
+      for (DeclContext *DC = CurContext; !DC->isFileContext();
+           DC = DC->getParent()) {
+        if (ClassTemplateSpecializationDecl *Spec
+                          = dyn_cast<ClassTemplateSpecializationDecl>(DC))
+          if (isInstantiationOf(ClassTemplate,
+                                Spec->getSpecializedTemplate()))
+            return Spec;
+
+        if (!DC->isDependentContext())
+          SawNonDependentContext = true;
       }
-      
-      DC = DC->getParent();
+
+      // We're performing "instantiation" of a member of the current
+      // instantiation while we are type-checking the
+      // definition. Compute the declaration context and return that.
+      assert(!SawNonDependentContext &&
+             "No dependent context while instantiating record");
+      DeclContext *DC = computeDeclContext(T);
+      assert(DC &&
+             "Unable to find declaration for the current instantiation");
+      return cast<CXXRecordDecl>(DC);
     }
 
     // Fall through to deal with other dependent record types (e.g.,

Modified: cfe/trunk/test/SemaTemplate/class-template-decl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/class-template-decl.cpp?rev=143725&r1=143724&r2=143725&view=diff
==============================================================================
--- cfe/trunk/test/SemaTemplate/class-template-decl.cpp (original)
+++ cfe/trunk/test/SemaTemplate/class-template-decl.cpp Fri Nov  4 13:52:43 2011
@@ -75,23 +75,3 @@
   }
 }
 
-namespace rdar9676205 {
-  template <unsigned, class _Tp> class tuple_element;
-
-  template <class _T1, class _T2> class pair;
-
-  template <class _T1, class _T2>
-  class tuple_element<0, pair<_T1, _T2> >
-  {
-    template <class _Tp>
-    struct X
-    {
-      template <class _Up, bool = X<_Up>::value>
-      struct Y
-        : public X<_Up>,
-          public Y<_Up>
-      { };
-    };
-  };
-}
-





More information about the cfe-commits mailing list