]> granicus.if.org Git - clang/commitdiff
Simplify, and improve the performance of, template instantiation for
authorDouglas Gregor <dgregor@apple.com>
Wed, 27 May 2009 17:54:46 +0000 (17:54 +0000)
committerDouglas Gregor <dgregor@apple.com>
Wed, 27 May 2009 17:54:46 +0000 (17:54 +0000)
declaration references. The key realization is that dependent Decls,
which actually require instantiation, can only refer to the current
instantiation or members thereof. And, since the current context
during instantiation contains all of those members of the current
instantiation, we can simply find the real instantiate that matches up
with the "current instantiation" template.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@72486 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/Sema.h
lib/Sema/SemaTemplateInstantiate.cpp
lib/Sema/SemaTemplateInstantiateDecl.cpp
lib/Sema/SemaTemplateInstantiateExpr.cpp
test/SemaTemplate/instantiate-declref.cpp

index 5b3ea40b0647fb37688b8c13c7f078392eef8241..3825b7cc06a2c3a44b2614f8414e4a0296fccdeb 100644 (file)
@@ -2250,8 +2250,7 @@ public:
                                      FunctionDecl *Function);
   void InstantiateVariableDefinition(VarDecl *Var);
 
-  NamedDecl *
-  InstantiateDeclRef(NamedDecl *D, const TemplateArgumentList &TemplateArgs);
+  NamedDecl *InstantiateCurrentDeclRef(NamedDecl *D);
   
   // Simple function for cloning expressions.
   template<typename T> 
index 1cc999201bb723c4fcaad6e038ed57fecde1a83d..1546e39ee245df5cb87cd2cf0c6f0a7135b5942a 100644 (file)
@@ -407,8 +407,8 @@ QualType
 TemplateTypeInstantiator::InstantiateTypedefType(const TypedefType *T,
                                                  unsigned Quals) const {
   TypedefDecl *Typedef 
-    = cast_or_null<TypedefDecl>(SemaRef.InstantiateDeclRef(T->getDecl(), 
-                                                           TemplateArgs));
+    = cast_or_null<TypedefDecl>(
+                           SemaRef.InstantiateCurrentDeclRef(T->getDecl()));
   if (!Typedef)
     return QualType();
   
@@ -440,8 +440,7 @@ QualType
 TemplateTypeInstantiator::InstantiateRecordType(const RecordType *T,
                                                 unsigned Quals) const {
   RecordDecl *Record 
-    = cast_or_null<RecordDecl>(SemaRef.InstantiateDeclRef(T->getDecl(), 
-                                                          TemplateArgs));
+    = cast_or_null<RecordDecl>(SemaRef.InstantiateCurrentDeclRef(T->getDecl()));
   if (!Record)
     return QualType();
   
@@ -452,8 +451,7 @@ QualType
 TemplateTypeInstantiator::InstantiateEnumType(const EnumType *T,
                                               unsigned Quals) const {
   EnumDecl *Enum 
-    = cast_or_null<EnumDecl>(SemaRef.InstantiateDeclRef(T->getDecl(), 
-                                                        TemplateArgs));
+    = cast_or_null<EnumDecl>(SemaRef.InstantiateCurrentDeclRef(T->getDecl()));
   if (!Enum)
     return QualType();
   
index 41c1944b541cb737717bc060dd90d0efecb30409..33eedcec38a486a99dd8ce0a1498e7138ff30f73 100644 (file)
@@ -671,8 +671,8 @@ static NamedDecl *findInstantiationOf(ASTContext &Ctx,
   return 0;
 }
 
-/// \brief Find the instantiation of the given declaration with the
-/// given template arguments.
+/// \brief Find the instantiation of the given declaration within the
+/// current instantiation.
 ///
 /// This routine is intended to be used when \p D is a declaration
 /// referenced from within a template, that needs to mapped into the
@@ -695,10 +695,9 @@ static NamedDecl *findInstantiationOf(ASTContext &Ctx,
 /// In the instantiation of X<int>::getKind(), we need to map the
 /// EnumConstantDecl for KnownValue (which refers to
 /// X<T>::<Kind>::KnownValue) to its instantiation
-/// (X<int>::<Kind>::KnownValue). InstantiateDeclRef() performs this
-/// mapping, given the template arguments 'int'.
-NamedDecl *
-Sema::InstantiateDeclRef(NamedDecl *D, const TemplateArgumentList &TemplateArgs) {
+/// (X<int>::<Kind>::KnownValue). InstantiateCurrentDeclRef() performs
+/// this mapping from within the instantiation of X<int>.
+NamedDecl * Sema::InstantiateCurrentDeclRef(NamedDecl *D) {
   DeclContext *ParentDC = D->getDeclContext();
   if (isa<ParmVarDecl>(D) || ParentDC->isFunctionOrMethod()) {
     // D is a local of some kind. Look into the map of local
@@ -707,7 +706,7 @@ Sema::InstantiateDeclRef(NamedDecl *D, const TemplateArgumentList &TemplateArgs)
   }
 
   if (NamedDecl *ParentDecl = dyn_cast<NamedDecl>(ParentDC)) {
-    ParentDecl = InstantiateDeclRef(ParentDecl, TemplateArgs);
+    ParentDecl = InstantiateCurrentDeclRef(ParentDecl);
     if (!ParentDecl)
       return 0;
 
@@ -740,20 +739,27 @@ Sema::InstantiateDeclRef(NamedDecl *D, const TemplateArgumentList &TemplateArgs)
     D = Result;
   }
 
-  // D itself might be a class template that we need to instantiate
-  // with the given template arguments.
   if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(D))
-    if (ClassTemplateDecl *ClassTemplate = Record->getDescribedClassTemplate()) {
-      QualType InjectedClassName 
-        = ClassTemplate->getInjectedClassNameType(Context);
-      QualType InstantiatedType = InstantiateType(InjectedClassName,
-                                                  TemplateArgs,
-                                                  Record->getLocation(), 
-                                                  Record->getDeclName());
-      if (InstantiatedType.isNull())
-        return 0;
-      if (const RecordType *RT = InstantiatedType->getAsRecordType())
-        D = RT->getDecl();
+    if (ClassTemplateDecl *ClassTemplate 
+          = Record->getDescribedClassTemplate()) {
+      // When the declaration D was parsed, it referred to the current
+      // instantiation. Therefore, look through the current context,
+      // which contains actual instantiations, to find the
+      // instantiation of the "current instantiation" that D refers
+      // to. Alternatively, we could just instantiate the
+      // injected-class-name with the current template arguments, but
+      // such an instantiation is far more expensive.
+      for (DeclContext *DC = CurContext; !DC->isFileContext(); 
+           DC = DC->getParent()) {
+        if (ClassTemplateSpecializationDecl *Spec 
+              = dyn_cast<ClassTemplateSpecializationDecl>(DC))
+          if (Context.getCanonicalDecl(Spec->getSpecializedTemplate())
+              == Context.getCanonicalDecl(ClassTemplate))
+            return Spec;
+      }
+
+      assert(false && 
+             "Unable to find declaration for the current instantiation");
     }
 
   return D;
index 726ac2b425e75e21b24c925d6f121a6ba48c6d51..31bb91def2cf04960ff8ac5dd3b9c8cf66c88911 100644 (file)
@@ -108,7 +108,6 @@ TemplateExprInstantiator::VisitUnresolvedFunctionNameExpr(
 
 Sema::OwningExprResult
 TemplateExprInstantiator::VisitDeclRefExpr(DeclRefExpr *E) {
-  // FIXME: Recast this in terms of Sema::InstantiateDeclRef.
   NamedDecl *D = E->getDecl();
   if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(D)) {
     assert(NTTP->getDepth() == 0 && "No nested templates yet");
@@ -141,7 +140,7 @@ TemplateExprInstantiator::VisitDeclRefExpr(DeclRefExpr *E) {
   }
 
   ValueDecl *NewD 
-    = dyn_cast_or_null<ValueDecl>(SemaRef.InstantiateDeclRef(D, TemplateArgs));
+    = dyn_cast_or_null<ValueDecl>(SemaRef.InstantiateCurrentDeclRef(D));
   if (!NewD)
     return SemaRef.ExprError();
 
index 3b6db38617b037cb9fad0bd46a3d6609082c33c2..0e1e562056e15a19087605f7d1cac481df4db092 100644 (file)
@@ -24,6 +24,9 @@ namespace N {
               K1 k1 = K1Val;
               Kind1 = K1Val;
               Outer::Inner::InnerTemplate<type>::VeryInner::Kind2 = K2Val;
+
+              InnerTemplate t;
+              InnerTemplate<type> t2;
             }
           };
         };