[cfe-commits] r82069 - in /cfe/trunk: lib/Sema/Sema.h lib/Sema/SemaTemplateInstantiate.cpp lib/Sema/SemaTemplateInstantiateDecl.cpp test/SemaTemplate/default-expr-arguments.cpp

Douglas Gregor dgregor at apple.com
Wed Sep 16 11:34:49 PDT 2009


Author: dgregor
Date: Wed Sep 16 13:34:49 2009
New Revision: 82069

URL: http://llvm.org/viewvc/llvm-project?rev=82069&view=rev
Log:
Teach Sema::FindInstantiatedDecl to find instantiated RecordDecls even
when we are not instantiating the corresponding "current
instantiation." This happens, e.g., when we are instantiating a
declaration reference that refers into the "current instantiation" but
occurs in a default function argument. The libstdc++ vector default
constructor now instantiates properly.

Modified:
    cfe/trunk/lib/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
    cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
    cfe/trunk/test/SemaTemplate/default-expr-arguments.cpp

Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=82069&r1=82068&r2=82069&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Wed Sep 16 13:34:49 2009
@@ -3103,8 +3103,10 @@
                                   const CXXConstructorDecl *Tmpl,
                             const MultiLevelTemplateArgumentList &TemplateArgs);
 
-  NamedDecl *FindInstantiatedDecl(NamedDecl *D);
-  DeclContext *FindInstantiatedContext(DeclContext *DC);
+  NamedDecl *FindInstantiatedDecl(NamedDecl *D,
+                          const MultiLevelTemplateArgumentList &TemplateArgs);
+  DeclContext *FindInstantiatedContext(DeclContext *DC,
+                          const MultiLevelTemplateArgumentList &TemplateArgs);
 
   // Objective-C declarations.
   virtual DeclPtrTy ActOnStartClassInterface(SourceLocation AtInterfaceLoc,

Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp?rev=82069&r1=82068&r2=82069&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp Wed Sep 16 13:34:49 2009
@@ -429,7 +429,7 @@
       "Reducing depth of template template parameters is not yet implemented");
   }
 
-  return SemaRef.FindInstantiatedDecl(cast<NamedDecl>(D));
+  return SemaRef.FindInstantiatedDecl(cast<NamedDecl>(D), TemplateArgs);
 }
 
 Decl *TemplateInstantiator::TransformDefinition(Decl *D) {
@@ -533,7 +533,8 @@
     if (Arg.getKind() == TemplateArgument::Declaration) {
       ValueDecl *VD = cast<ValueDecl>(Arg.getAsDecl());
 
-      VD = cast_or_null<ValueDecl>(getSema().FindInstantiatedDecl(VD));
+      VD = cast_or_null<ValueDecl>(
+                              getSema().FindInstantiatedDecl(VD, TemplateArgs));
       if (!VD)
         return SemaRef.ExprError();
 
@@ -562,7 +563,7 @@
                                               E->getSourceRange().getBegin()));
   }
 
-  NamedDecl *InstD = SemaRef.FindInstantiatedDecl(D);
+  NamedDecl *InstD = SemaRef.FindInstantiatedDecl(D, TemplateArgs);
   if (!InstD)
     return SemaRef.ExprError();
 

Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=82069&r1=82068&r2=82069&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Wed Sep 16 13:34:49 2009
@@ -491,7 +491,8 @@
     return 0;
 
   // Build the instantiated method declaration.
-  DeclContext *DC = SemaRef.FindInstantiatedContext(D->getDeclContext());
+  DeclContext *DC = SemaRef.FindInstantiatedContext(D->getDeclContext(),
+                                                    TemplateArgs);
   FunctionDecl *Function =
       FunctionDecl::Create(SemaRef.Context, DC, D->getLocation(),
                            D->getDeclName(), T, D->getDeclaratorInfo(),
@@ -1176,9 +1177,10 @@
 
       // Is this an anonymous union?
       if (FieldDecl *UnionInit = Init->getAnonUnionMember())
-        Member = cast<FieldDecl>(FindInstantiatedDecl(UnionInit));
+        Member = cast<FieldDecl>(FindInstantiatedDecl(UnionInit, TemplateArgs));
       else
-        Member = cast<FieldDecl>(FindInstantiatedDecl(Init->getMember()));
+        Member = cast<FieldDecl>(FindInstantiatedDecl(Init->getMember(),
+                                                      TemplateArgs));
 
       NewInit = BuildMemberInitializer(Member, (Expr **)NewArgs.data(),
                                        NewArgs.size(),
@@ -1333,9 +1335,10 @@
 /// within the current instantiation.
 ///
 /// \returns NULL if there was an error
-DeclContext *Sema::FindInstantiatedContext(DeclContext* DC) {
+DeclContext *Sema::FindInstantiatedContext(DeclContext* DC,
+                          const MultiLevelTemplateArgumentList &TemplateArgs) {
   if (NamedDecl *D = dyn_cast<NamedDecl>(DC)) {
-    Decl* ID = FindInstantiatedDecl(D);
+    Decl* ID = FindInstantiatedDecl(D, TemplateArgs);
     return cast_or_null<DeclContext>(ID);
   } else return DC;
 }
@@ -1366,7 +1369,8 @@
 /// X<T>::<Kind>::KnownValue) to its instantiation
 /// (X<int>::<Kind>::KnownValue). InstantiateCurrentDeclRef() performs
 /// this mapping from within the instantiation of X<int>.
-NamedDecl *Sema::FindInstantiatedDecl(NamedDecl *D) {
+NamedDecl *Sema::FindInstantiatedDecl(NamedDecl *D,
+                          const MultiLevelTemplateArgumentList &TemplateArgs) {
   if (OverloadedFunctionDecl *Ovl = dyn_cast<OverloadedFunctionDecl>(D)) {
     // Transform all of the elements of the overloaded function set.
     OverloadedFunctionDecl *Result
@@ -1376,7 +1380,8 @@
                                                 FEnd = Ovl->function_end();
          F != FEnd; ++F) {
       Result->addOverload(
-                  AnyFunctionDecl::getFromNamedDecl(FindInstantiatedDecl(*F)));
+        AnyFunctionDecl::getFromNamedDecl(FindInstantiatedDecl(*F,
+                                                               TemplateArgs)));
     }
 
     return Result;
@@ -1389,29 +1394,68 @@
     return cast<NamedDecl>(CurrentInstantiationScope->getInstantiationOf(D));
   }
 
-  if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(D))
-    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.
+  if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(D)) {
+    if (!Record->isDependentContext())
+      return D;
+    
+    // If the RecordDecl is actually the injected-class-name or a "templated"
+    // declaration for a class template or class template partial 
+    // specialization, 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) {
+      T = ClassTemplate->getInjectedClassNameType(Context);
+    } else if (ClassTemplatePartialSpecializationDecl *PartialSpec
+                 = dyn_cast<ClassTemplatePartialSpecializationDecl>(Record)) {
+      T = Context.getTypeDeclType(Record);
+      ClassTemplate = PartialSpec->getSpecializedTemplate();
+    }
+    
+    if (!T.isNull()) {
+      // Substitute into the injected-class-name to get the type corresponding
+      // to the instantiation we want. 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, SourceLocation(), 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();
+      }
+    
+      // 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.
       for (DeclContext *DC = CurContext; !DC->isFileContext();
            DC = DC->getParent()) {
         if (ClassTemplateSpecializationDecl *Spec
               = dyn_cast<ClassTemplateSpecializationDecl>(DC))
-          if (isInstantiationOf(ClassTemplate, Spec->getSpecializedTemplate()))
+          if (isInstantiationOf(ClassTemplate, 
+                                Spec->getSpecializedTemplate()))
             return Spec;
       }
 
       assert(false &&
              "Unable to find declaration for the current instantiation");
+      return Record;
     }
+    
+    // Fall through to deal with other dependent record types (e.g.,
+    // anonymous unions in class templates).
+  }
 
-  ParentDC = FindInstantiatedContext(ParentDC);
+  if (!ParentDC->isDependentContext())
+    return D;
+  
+  ParentDC = FindInstantiatedContext(ParentDC, TemplateArgs);
   if (!ParentDC)
     return 0;
 

Modified: cfe/trunk/test/SemaTemplate/default-expr-arguments.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/default-expr-arguments.cpp?rev=82069&r1=82068&r2=82069&view=diff

==============================================================================
--- cfe/trunk/test/SemaTemplate/default-expr-arguments.cpp (original)
+++ cfe/trunk/test/SemaTemplate/default-expr-arguments.cpp Wed Sep 16 13:34:49 2009
@@ -68,3 +68,13 @@
   xn.f(42);
   xn.f(); // expected-note{{in instantiation of default function argument}}
 }
+
+template<typename T>
+struct X1 {
+  typedef T value_type;
+  X1(const value_type& value = value_type());
+};
+
+void test_X1() {
+  X1<int> x1;
+}





More information about the cfe-commits mailing list