[cfe-commits] r83509 - in /cfe/trunk: 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

Douglas Gregor dgregor at apple.com
Wed Oct 7 16:56:11 PDT 2009


Author: dgregor
Date: Wed Oct  7 18:56:10 2009
New Revision: 83509

URL: http://llvm.org/viewvc/llvm-project?rev=83509&view=rev
Log:
Keep track of whether a member function instantiated from a member
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.

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

Modified: cfe/trunk/include/clang/AST/Decl.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Decl.h?rev=83509&r1=83508&r2=83509&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/Decl.h (original)
+++ cfe/trunk/include/clang/AST/Decl.h Wed Oct  7 18:56:10 2009
@@ -27,6 +27,7 @@
 class CompoundStmt;
 class StringLiteral;
 class TemplateArgumentList;
+class MemberSpecializationInfo;
 class FunctionTemplateSpecializationInfo;
 class TypeLoc;
 
@@ -830,14 +831,15 @@
   /// 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 @@
   /// 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.

Modified: cfe/trunk/include/clang/AST/DeclTemplate.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclTemplate.h?rev=83509&r1=83508&r2=83509&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/DeclTemplate.h (original)
+++ cfe/trunk/include/clang/AST/DeclTemplate.h Wed Oct  7 18:56:10 2009
@@ -548,6 +548,33 @@
   }
 };
 
+/// \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:

Modified: cfe/trunk/lib/AST/Decl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Decl.cpp?rev=83509&r1=83508&r2=83509&view=diff

==============================================================================
--- cfe/trunk/lib/AST/Decl.cpp (original)
+++ cfe/trunk/lib/AST/Decl.cpp Wed Oct  7 18:56:10 2009
@@ -410,6 +410,16 @@
   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 @@
     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 @@
 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 {

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Wed Oct  7 18:56:10 2009
@@ -3171,10 +3171,13 @@
                                        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.

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp Wed Oct  7 18:56:10 2009
@@ -977,6 +977,8 @@
                                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 @@
           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);
     }
   }
 }

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Wed Oct  7 18:56:10 2009
@@ -522,7 +522,7 @@
     if (!Owner->isDependentContext())
       DC->makeDeclVisibleInContext(Function, /* Recoverable = */ false);
 
-    Function->setInstantiationOfMemberFunction(D);
+    Function->setInstantiationOfMemberFunction(D, TSK_ImplicitInstantiation);
   }
 
   if (InitFunctionInstantiation(Function, D))
@@ -637,7 +637,7 @@
       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

Modified: cfe/trunk/test/SemaTemplate/extern-templates.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/extern-templates.cpp?rev=83509&r1=83508&r2=83509&view=diff

==============================================================================
--- cfe/trunk/test/SemaTemplate/extern-templates.cpp (original)
+++ cfe/trunk/test/SemaTemplate/extern-templates.cpp Wed Oct  7 18:56:10 2009
@@ -31,11 +31,11 @@
 
 // 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*>;





More information about the cfe-commits mailing list