]> granicus.if.org Git - clang/commitdiff
Explicit instantiations of templates now instantiate the definitions
authorDouglas Gregor <dgregor@apple.com>
Wed, 13 May 2009 20:28:22 +0000 (20:28 +0000)
committerDouglas Gregor <dgregor@apple.com>
Wed, 13 May 2009 20:28:22 +0000 (20:28 +0000)
of class members (recursively). Only member classes are actually
instantiated; the instantiation logic for member functions and
variables are just stubs.

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

lib/Sema/Sema.h
lib/Sema/SemaTemplate.cpp
lib/Sema/SemaTemplateInstantiate.cpp
lib/Sema/SemaTemplateInstantiateDecl.cpp
test/SemaTemplate/temp_explicit.cpp

index 46120bcb38d931df38a7e200c36e59f49dc59575..9d5afbbb9c907e6b06119713e0d716f58635e0b5 100644 (file)
@@ -2116,6 +2116,14 @@ public:
                            ClassTemplateSpecializationDecl *ClassTemplateSpec,
                            bool ExplicitInstantiation);
 
+  void InstantiateClassMembers(SourceLocation PointOfInstantiation,
+                               CXXRecordDecl *Instantiation,
+                               const TemplateArgumentList &TemplateArgs);
+
+  void InstantiateClassTemplateSpecializationMembers(
+                                          SourceLocation PointOfInstantiation,
+                           ClassTemplateSpecializationDecl *ClassTemplateSpec);
+
   NestedNameSpecifier *
   InstantiateNestedNameSpecifier(NestedNameSpecifier *NNS,
                                  SourceRange Range,
@@ -2125,6 +2133,9 @@ public:
   InstantiateTemplateName(TemplateName Name, SourceLocation Loc,
                           const TemplateArgumentList &TemplateArgs);
 
+  void InstantiateFunctionDefinition(FunctionDecl *Function);
+  void InstantiateVariableDefinition(VarDecl *Var);
+
   // Simple function for cloning expressions.
   template<typename T> 
   OwningExprResult Clone(T *E) {
index adf9ea4941ff9b5c5fc124c6acee049ba4ef8d45..22f2bef0e9d82c428dd95a9ed1f22ea7b146254c 100644 (file)
@@ -2335,9 +2335,10 @@ Sema::ActOnExplicitInstantiation(Scope *S, SourceLocation TemplateLoc,
       InstantiateClassTemplateSpecialization(Specialization, true))
     return true;
 
-  // FIXME: Instantiate all of the members of the template (that
-  // haven't already been instantiated!).
-
+  // Instantiate the members of this class template specialization.
+  InstantiatingTemplate Inst(*this, TemplateLoc, Specialization);
+  InstantiateClassTemplateSpecializationMembers(TemplateLoc, Specialization);
+  
   return DeclPtrTy::make(Specialization);
 }
 
index 3a2f6777556bc2ae259fe362dcc836585592c15b..9c2c4230f9c6ada0bf5e5178ffe67c263562a195 100644 (file)
@@ -749,6 +749,10 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation,
   // Exit the scope of this instantiation.
   CurContext = PreviousContext;
 
+  // If this is an explicit instantiation, instantiate our members, too.
+  if (!Invalid && ExplicitInstantiation)
+    InstantiateClassMembers(PointOfInstantiation, Instantiation, TemplateArgs);
+
   return Invalid;
 }
 
@@ -787,6 +791,53 @@ Sema::InstantiateClassTemplateSpecialization(
                           ExplicitInstantiation);
 }
 
+/// \brief Instantiate the definitions of all of the member of the
+/// given class, which is an instantiation of a class template or a
+/// member class of a template.
+void
+Sema::InstantiateClassMembers(SourceLocation PointOfInstantiation,
+                              CXXRecordDecl *Instantiation,
+                              const TemplateArgumentList &TemplateArgs) {
+  for (DeclContext::decl_iterator D = Instantiation->decls_begin(Context),
+                               DEnd = Instantiation->decls_end(Context);
+       D != DEnd; ++D) {
+    if (FunctionDecl *Function = dyn_cast<FunctionDecl>(*D)) {
+      if (!Function->getBody(Context))
+        InstantiateFunctionDefinition(Function);
+    } else if (VarDecl *Var = dyn_cast<VarDecl>(*D)) {
+      const VarDecl *Def = 0;
+      if (!Var->getDefinition(Def))
+        InstantiateVariableDefinition(Var);
+    } else if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(*D)) {
+      if (!Record->isInjectedClassName() && !Record->getDefinition(Context)) {
+        assert(Record->getInstantiatedFromMemberClass() && 
+               "Missing instantiated-from-template information");
+        InstantiateClass(Record->getLocation(), Record,
+                         Record->getInstantiatedFromMemberClass(),
+                         TemplateArgs, true);
+      }
+    }
+  }
+}
+
+/// \brief Instantiate the definitions of all of the members of the
+/// given class template specialization, which was named as part of an
+/// explicit instantiation.
+void Sema::InstantiateClassTemplateSpecializationMembers(
+                                           SourceLocation PointOfInstantiation,
+                          ClassTemplateSpecializationDecl *ClassTemplateSpec) {
+  // C++0x [temp.explicit]p7:
+  //   An explicit instantiation that names a class template
+  //   specialization is an explicit instantion of the same kind
+  //   (declaration or definition) of each of its members (not
+  //   including members inherited from base classes) that has not
+  //   been previously explicitly specialized in the translation unit
+  //   containing the explicit instantiation, except as described
+  //   below.
+  InstantiateClassMembers(PointOfInstantiation, ClassTemplateSpec,
+                          ClassTemplateSpec->getTemplateArgs());
+}
+
 /// \brief Instantiate a nested-name-specifier.
 NestedNameSpecifier *
 Sema::InstantiateNestedNameSpecifier(NestedNameSpecifier *NNS,
index b254a40da71acdb248146b73a1dc05513f073918..92d253d3ba72222669a51725fe938a7557539af9 100644 (file)
@@ -550,3 +550,20 @@ TemplateDeclInstantiator::InitMethodInstantiation(CXXMethodDecl *New,
   // FIXME: New needs a pointer to Tmpl
   return false;
 }
+
+/// \brief Instantiate the definition of the given function from its
+/// template.
+///
+/// \param Function the already-instantiated declaration of a
+/// function.
+void Sema::InstantiateFunctionDefinition(FunctionDecl *Function) {
+  // FIXME: Implement this!
+}
+
+/// \brief Instantiate the definition of the given variable from its
+/// template.
+///
+/// \param Var the already-instantiated declaration of a variable.
+void Sema::InstantiateVariableDefinition(VarDecl *Var) {
+  // FIXME: Implement this!
+}
index b6009bd9c164a38d587e94736777d1681993bd4e..0b96c73c1f2b8d0a1e05432230fae28af1972f33 100644 (file)
@@ -1,4 +1,4 @@
-// RUN: clang-cc -fsyntax-only -verify -pedantic %s
+// RUN: clang-cc -fsyntax-only -pedantic -verify %s
 //
 // Tests explicit instantiation of templates.
 template<typename T, typename U = T> class X0 { };
@@ -46,3 +46,28 @@ struct X2 {
 
 template struct X2<int>; // okay
 template struct X2<int&>; // expected-note{{in instantiation of}}
+
+// Check that explicit instantiations instantiate member classes.
+template<typename T> struct X3 {
+  struct Inner { // expected-note{{here}}
+    void f(T*); // expected-error{{pointer to a reference}}
+  };
+};
+
+void f1(X3<int&>); // okay, Inner, not instantiated
+
+template struct X3<int&>; // expected-note{{instantiation}}
+
+template<typename T> struct X4 {
+  struct Inner { // expected-note 2{{here}}
+    struct VeryInner { // expected-note 2{{here}}
+      void f(T*); // expected-error 2{{pointer to a reference}}
+    };
+  };
+};
+
+void f2(X4<int&>); // okay, Inner, not instantiated
+void f3(X4<int&>::Inner); // okay, Inner::VeryInner, not instantiated
+
+template struct X4<int&>; // expected-note{{instantiation}}
+template struct X4<float&>; // expected-note{{instantiation}}