]> granicus.if.org Git - clang/commitdiff
Keep track of whether a member function instantiated from a member
authorDouglas Gregor <dgregor@apple.com>
Wed, 7 Oct 2009 23:56:10 +0000 (23:56 +0000)
committerDouglas Gregor <dgregor@apple.com>
Wed, 7 Oct 2009 23:56:10 +0000 (23:56 +0000)
function of a class template was implicitly instantiated, explicitly
instantiated (declaration or definition), or explicitly
specialized. The same MemberSpecializationInfo structure will be used
for static data members and member classes as well.

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

include/clang/AST/Decl.h
include/clang/AST/DeclTemplate.h
lib/AST/Decl.cpp
lib/Sema/SemaTemplate.cpp
lib/Sema/SemaTemplateInstantiate.cpp
lib/Sema/SemaTemplateInstantiateDecl.cpp
test/SemaTemplate/extern-templates.cpp

index e77c5e41fbf48e243df426fecced55621c458c15..f2ffccd7e095da27dc471b67e43c2bd5bf714952 100644 (file)
@@ -27,6 +27,7 @@ class Stmt;
 class CompoundStmt;
 class StringLiteral;
 class TemplateArgumentList;
+class MemberSpecializationInfo;
 class FunctionTemplateSpecializationInfo;
 class TypeLoc;
 
@@ -830,14 +831,15 @@ private:
   /// For non-templates, this value will be NULL. For function
   /// declarations that describe a function template, this will be a
   /// pointer to a FunctionTemplateDecl. For member functions
-  /// of class template specializations, this will be the
-  /// FunctionDecl from which the member function was instantiated.
+  /// of class template specializations, this will be a MemberSpecializationInfo
+  /// pointer containing information about the specialization.
   /// For function template specializations, this will be a
   /// FunctionTemplateSpecializationInfo, which contains information about
   /// the template being specialized and the template arguments involved in
   /// that specialization.
-  llvm::PointerUnion3<FunctionTemplateDecl*, FunctionDecl*,
-                      FunctionTemplateSpecializationInfo*>
+  llvm::PointerUnion3<FunctionTemplateDecl *, 
+                      MemberSpecializationInfo *,
+                      FunctionTemplateSpecializationInfo *>
     TemplateOrSpecialization;
 
 protected:
@@ -1063,15 +1065,12 @@ public:
   /// the FunctionDecl X<T>::A. When a complete definition of
   /// X<int>::A is required, it will be instantiated from the
   /// declaration returned by getInstantiatedFromMemberFunction().
-  FunctionDecl *getInstantiatedFromMemberFunction() const {
-    return TemplateOrSpecialization.dyn_cast<FunctionDecl*>();
-  }
+  FunctionDecl *getInstantiatedFromMemberFunction() const;
 
   /// \brief Specify that this record is an instantiation of the
-  /// member function RD.
-  void setInstantiationOfMemberFunction(FunctionDecl *RD) {
-    TemplateOrSpecialization = RD;
-  }
+  /// member function FD.
+  void setInstantiationOfMemberFunction(FunctionDecl *FD,
+                                        TemplateSpecializationKind TSK);
 
   /// \brief Retrieves the function template that is described by this
   /// function declaration.
index 5d3e8eab4357aef4509653cb4460c93b0d00f155..3f6f782c29ecf19b71bd2aeabd73cda915c564c0 100644 (file)
@@ -548,6 +548,33 @@ public:
   }
 };
 
+/// \brief Provides information a specialization of a member of a class 
+/// template, which may be a member function, static data member, or
+/// member class.
+class MemberSpecializationInfo {
+  NamedDecl *InstantiatedFrom;
+  TemplateSpecializationKind TSK;
+  
+public:
+  explicit 
+  MemberSpecializationInfo(NamedDecl *IF, TemplateSpecializationKind TSK)
+    : InstantiatedFrom(IF), TSK(TSK) { }
+  
+  /// \brief Retrieve the member declaration from which this member was
+  /// instantiated.
+  NamedDecl *getInstantiatedFrom() const { return InstantiatedFrom; }
+  
+  /// \brief Determine what kind of template specialization this is.
+  TemplateSpecializationKind getTemplateSpecializationKind() const {
+    return TSK;
+  }
+  
+  /// \brief Set the template specialization kind.
+  void setTemplateSpecializationKind(TemplateSpecializationKind TSK) {
+    this->TSK = TSK;
+  }
+};
+  
 /// Declaration of a template function.
 class FunctionTemplateDecl : public TemplateDecl {
 protected:
index fe32c396c587a5a7f4a641afad40ce2df6f1979b..a5c9fa4bac87f4a0365f914adb3f95f0835b2259 100644 (file)
@@ -410,6 +410,16 @@ void FunctionDecl::Destroy(ASTContext& C) {
   for (param_iterator I=param_begin(), E=param_end(); I!=E; ++I)
     (*I)->Destroy(C);
 
+  FunctionTemplateSpecializationInfo *FTSInfo
+    = TemplateOrSpecialization.dyn_cast<FunctionTemplateSpecializationInfo*>();
+  if (FTSInfo)
+    C.Deallocate(FTSInfo);
+  
+  MemberSpecializationInfo *MSInfo
+    = TemplateOrSpecialization.dyn_cast<MemberSpecializationInfo*>();
+  if (MSInfo)
+    C.Deallocate(MSInfo);
+  
   C.Deallocate(ParamInfo);
 
   Decl::Destroy(C);
@@ -670,6 +680,24 @@ OverloadedOperatorKind FunctionDecl::getOverloadedOperator() const {
     return OO_None;
 }
 
+FunctionDecl *FunctionDecl::getInstantiatedFromMemberFunction() const {
+  if (MemberSpecializationInfo *Info 
+        = TemplateOrSpecialization.dyn_cast<MemberSpecializationInfo*>())
+    return cast<FunctionDecl>(Info->getInstantiatedFrom());
+  
+  return 0;
+}
+
+void 
+FunctionDecl::setInstantiationOfMemberFunction(FunctionDecl *FD,
+                                               TemplateSpecializationKind TSK) {
+  assert(TemplateOrSpecialization.isNull() && 
+         "Member function is already a specialization");
+  MemberSpecializationInfo *Info 
+    = new (getASTContext()) MemberSpecializationInfo(FD, TSK);
+  TemplateOrSpecialization = Info;
+}
+
 FunctionTemplateDecl *FunctionDecl::getPrimaryTemplate() const {
   if (FunctionTemplateSpecializationInfo *Info
         = TemplateOrSpecialization
@@ -727,32 +755,30 @@ FunctionDecl::setFunctionTemplateSpecialization(ASTContext &Context,
 TemplateSpecializationKind FunctionDecl::getTemplateSpecializationKind() const {
   // For a function template specialization, query the specialization
   // information object.
-  FunctionTemplateSpecializationInfo *Info
+  FunctionTemplateSpecializationInfo *FTSInfo
     = TemplateOrSpecialization.dyn_cast<FunctionTemplateSpecializationInfo*>();
-  if (Info)
-    return Info->getTemplateSpecializationKind();
-
-  if (!getInstantiatedFromMemberFunction())
-    return TSK_Undeclared;
-
-  // Find the class template specialization corresponding to this instantiation
-  // of a member function.
-  const DeclContext *Parent = getDeclContext();
-  while (Parent && !isa<ClassTemplateSpecializationDecl>(Parent))
-    Parent = Parent->getParent();
-
-  if (!Parent)
-    return TSK_Undeclared;
+  if (FTSInfo)
+    return FTSInfo->getTemplateSpecializationKind();
 
-  return cast<ClassTemplateSpecializationDecl>(Parent)->getSpecializationKind();
+  MemberSpecializationInfo *MSInfo
+    = TemplateOrSpecialization.dyn_cast<MemberSpecializationInfo*>();
+  if (MSInfo)
+    return MSInfo->getTemplateSpecializationKind();
+  
+  return TSK_Undeclared;
 }
 
 void
 FunctionDecl::setTemplateSpecializationKind(TemplateSpecializationKind TSK) {
-  FunctionTemplateSpecializationInfo *Info
-    = TemplateOrSpecialization.dyn_cast<FunctionTemplateSpecializationInfo*>();
-  assert(Info && "Not a function template specialization");
-  Info->setTemplateSpecializationKind(TSK);
+  if (FunctionTemplateSpecializationInfo *FTSInfo
+        = TemplateOrSpecialization.dyn_cast<
+                                        FunctionTemplateSpecializationInfo*>())
+    FTSInfo->setTemplateSpecializationKind(TSK);
+  else if (MemberSpecializationInfo *MSInfo
+             = TemplateOrSpecialization.dyn_cast<MemberSpecializationInfo*>())
+    MSInfo->setTemplateSpecializationKind(TSK);
+  else
+    assert(false && "Function cannot have a template specialization kind");
 }
 
 bool FunctionDecl::isOutOfLine() const {
index f3cd2e41fbd3f63f35238d27a1b8427b5a25839b..339a084d7afbab7b91509644b4ae6bcf81f2bfb0 100644 (file)
@@ -3171,10 +3171,13 @@ Sema::CheckMemberFunctionSpecialization(CXXMethodDecl *FD,
                                        Instantiation, FD->getLocation(), 
                                        false, TSK_ExplicitSpecialization))
     return true;
+
+  // FIXME: Check for specialization-after-instantiation errors and such.
   
-  // FIXME: Mark the new declaration as a member function specialization.
-  // We may also want to mark the original instantiation as having been
-  // explicitly specialized.
+  // Note that this function is an explicit instantiation of a member function.
+  Instantiation->setTemplateSpecializationKind(TSK_ExplicitSpecialization);
+  FD->setInstantiationOfMemberFunction(FunctionInTemplate, 
+                                       TSK_ExplicitSpecialization);
   
   // Save the caller the trouble of having to figure out which declaration
   // this specialization matches.
index 9c96b33cd0e33c84d2dedf7158b75c69aba67d8a..e0ffca9d2d12e9655b858f67eeb90e7971b21bb1 100644 (file)
@@ -977,6 +977,8 @@ Sema::InstantiateClassMembers(SourceLocation PointOfInstantiation,
                                DEnd = Instantiation->decls_end();
        D != DEnd; ++D) {
     if (FunctionDecl *Function = dyn_cast<FunctionDecl>(*D)) {
+      if (Function->getInstantiatedFromMemberFunction())
+        Function->setTemplateSpecializationKind(TSK);
       if (!Function->getBody() && TSK != TSK_ExplicitInstantiationDeclaration)
         InstantiateFunctionDefinition(PointOfInstantiation, Function);
     } else if (VarDecl *Var = dyn_cast<VarDecl>(*D)) {
@@ -984,14 +986,19 @@ Sema::InstantiateClassMembers(SourceLocation PointOfInstantiation,
           TSK != TSK_ExplicitInstantiationDeclaration)
         InstantiateStaticDataMemberDefinition(PointOfInstantiation, Var);
     } else if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(*D)) {
-      if (!Record->isInjectedClassName() && !Record->getDefinition(Context)) {
-        assert(Record->getInstantiatedFromMemberClass() &&
-               "Missing instantiated-from-template information");
+      if (Record->isInjectedClassName())
+        continue;
+      
+      assert(Record->getInstantiatedFromMemberClass() &&
+             "Missing instantiated-from-template information");
+      if (!Record->getDefinition(Context))
         InstantiateClass(PointOfInstantiation, Record,
                          Record->getInstantiatedFromMemberClass(),
                          TemplateArgs,
                          TSK);
-      }
+      else
+        InstantiateClassMembers(PointOfInstantiation, Record, TemplateArgs, 
+                                TSK);
     }
   }
 }
index fa303659412c3c7979994f0cb65e5095df4b4eec..fcacb4a3f000cdde70176bba5d138a13127ccafb 100644 (file)
@@ -522,7 +522,7 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D) {
     if (!Owner->isDependentContext())
       DC->makeDeclVisibleInContext(Function, /* Recoverable = */ false);
 
-    Function->setInstantiationOfMemberFunction(D);
+    Function->setInstantiationOfMemberFunction(D, TSK_ImplicitInstantiation);
   }
 
   if (InitFunctionInstantiation(Function, D))
@@ -637,7 +637,7 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D,
       FunctionTemplate->setLexicalDeclContext(D->getLexicalDeclContext());
     Method->setDescribedFunctionTemplate(FunctionTemplate);
   } else if (!FunctionTemplate)
-    Method->setInstantiationOfMemberFunction(D);
+    Method->setInstantiationOfMemberFunction(D, TSK_ImplicitInstantiation);
 
   // If we are instantiating a member function defined
   // out-of-line, the instantiation will have the same lexical
index 6bdf283391f2daba34d670430a69d0231f30e3d5..7154c7e32f9cf039758608f93a17c885471cfc84 100644 (file)
@@ -31,11 +31,11 @@ void test_intptr(X0<int*> xi, X0<int*>::Inner xii) {
 
 // FIXME: we would like the notes to point to the explicit instantiation at the
 // bottom.
-extern template class X0<long*>; // expected-note{{instantiation}}
+extern template class X0<long*>; // expected-note 2{{instantiation}}
 
 void test_longptr(X0<long*> xl, X0<long*>::Inner xli) {
   xl.f(0);
-  xli.g(0); // expected-note{{instantiation}}
+  xli.g(0);
 }
 
 template class X0<long*>;