[cfe-commits] r84188 - in /cfe/trunk: include/clang/AST/Decl.h lib/AST/Decl.cpp lib/Sema/SemaTemplate.cpp

Douglas Gregor dgregor at apple.com
Thu Oct 15 10:21:20 PDT 2009


Author: dgregor
Date: Thu Oct 15 12:21:20 2009
New Revision: 84188

URL: http://llvm.org/viewvc/llvm-project?rev=84188&view=rev
Log:
Simplify checking of explicit template specialization/explicit
instantiation redeclaration semantics for function template
specializations and member functions of class template
specializations. Also, record the point of instantiation for
explicit-instantiated functions and static data members.

Modified:
    cfe/trunk/include/clang/AST/Decl.h
    cfe/trunk/lib/AST/Decl.cpp
    cfe/trunk/lib/Sema/SemaTemplate.cpp

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

==============================================================================
--- cfe/trunk/include/clang/AST/Decl.h (original)
+++ cfe/trunk/include/clang/AST/Decl.h Thu Oct 15 12:21:20 2009
@@ -604,7 +604,8 @@
   
   /// \brief For a static data member that was instantiated from a static
   /// data member of a class template, set the template specialiation kind.
-  void setTemplateSpecializationKind(TemplateSpecializationKind TSK);
+  void setTemplateSpecializationKind(TemplateSpecializationKind TSK,
+                        SourceLocation PointOfInstantiation = SourceLocation());
   
   /// isFileVarDecl - Returns true for file scoped variable declaration.
   bool isFileVarDecl() const {
@@ -1170,7 +1171,16 @@
 
   /// \brief Determine what kind of template instantiation this function
   /// represents.
-  void setTemplateSpecializationKind(TemplateSpecializationKind TSK);
+  void setTemplateSpecializationKind(TemplateSpecializationKind TSK,
+                        SourceLocation PointOfInstantiation = SourceLocation());
+
+  /// \brief Retrieve the (first) point of instantiation of a function template
+  /// specialization or a member of a class template specialization.
+  ///
+  /// \returns the first point of instantiation, if this function was 
+  /// instantiated from a template; otherwie, returns an invalid source 
+  /// location.
+  SourceLocation getPointOfInstantiation() const;
 
   /// \brief Determine whether this is or was instantiated from an out-of-line 
   /// definition of a member function.

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

==============================================================================
--- cfe/trunk/lib/AST/Decl.cpp (original)
+++ cfe/trunk/lib/AST/Decl.cpp Thu Oct 15 12:21:20 2009
@@ -408,10 +408,15 @@
   return getASTContext().getInstantiatedFromStaticDataMember(this);
 }
 
-void VarDecl::setTemplateSpecializationKind(TemplateSpecializationKind TSK) {
+void VarDecl::setTemplateSpecializationKind(TemplateSpecializationKind TSK,
+                                         SourceLocation PointOfInstantiation) {
   MemberSpecializationInfo *MSI = getMemberSpecializationInfo();
   assert(MSI && "Not an instantiated static data member?");
   MSI->setTemplateSpecializationKind(TSK);
+  if (TSK != TSK_ExplicitSpecialization &&
+      PointOfInstantiation.isValid() &&
+      MSI->getPointOfInstantiation().isInvalid())
+    MSI->setPointOfInstantiation(PointOfInstantiation);
 }
 
 bool VarDecl::isTentativeDefinition(ASTContext &Context) const {
@@ -812,18 +817,39 @@
 }
 
 void
-FunctionDecl::setTemplateSpecializationKind(TemplateSpecializationKind TSK) {
+FunctionDecl::setTemplateSpecializationKind(TemplateSpecializationKind TSK,
+                                          SourceLocation PointOfInstantiation) {
   if (FunctionTemplateSpecializationInfo *FTSInfo
         = TemplateOrSpecialization.dyn_cast<
-                                        FunctionTemplateSpecializationInfo*>())
+                                    FunctionTemplateSpecializationInfo*>()) {
     FTSInfo->setTemplateSpecializationKind(TSK);
-  else if (MemberSpecializationInfo *MSInfo
-             = TemplateOrSpecialization.dyn_cast<MemberSpecializationInfo*>())
+    if (TSK != TSK_ExplicitSpecialization &&
+        PointOfInstantiation.isValid() &&
+        FTSInfo->getPointOfInstantiation().isInvalid())
+      FTSInfo->setPointOfInstantiation(PointOfInstantiation);
+  } else if (MemberSpecializationInfo *MSInfo
+             = TemplateOrSpecialization.dyn_cast<MemberSpecializationInfo*>()) {
     MSInfo->setTemplateSpecializationKind(TSK);
-  else
+    if (TSK != TSK_ExplicitSpecialization &&
+        PointOfInstantiation.isValid() &&
+        MSInfo->getPointOfInstantiation().isInvalid())
+      MSInfo->setPointOfInstantiation(PointOfInstantiation);
+  } else
     assert(false && "Function cannot have a template specialization kind");
 }
 
+SourceLocation FunctionDecl::getPointOfInstantiation() const {
+  if (FunctionTemplateSpecializationInfo *FTSInfo
+        = TemplateOrSpecialization.dyn_cast<
+                                        FunctionTemplateSpecializationInfo*>())
+    return FTSInfo->getPointOfInstantiation();
+  else if (MemberSpecializationInfo *MSInfo
+             = TemplateOrSpecialization.dyn_cast<MemberSpecializationInfo*>())
+    return MSInfo->getPointOfInstantiation();
+  
+  return SourceLocation();
+}
+
 bool FunctionDecl::isOutOfLine() const {
   if (Decl::isOutOfLine())
     return true;

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Thu Oct 15 12:21:20 2009
@@ -3980,7 +3980,7 @@
       return DeclPtrTy();
     
     // Instantiate static data member.
-    Prev->setTemplateSpecializationKind(TSK);
+    Prev->setTemplateSpecializationKind(TSK, D.getIdentifierLoc());
     if (TSK == TSK_ExplicitInstantiationDefinition)
       InstantiateStaticDataMemberDefinition(D.getIdentifierLoc(), Prev, false,
                                             /*DefinitionRequired=*/true);
@@ -4054,9 +4054,7 @@
   if (!Specialization)
     return true;
   
-  // FIXME: Use CheckSpecializationInstantiationRedecl
-  switch (Specialization->getTemplateSpecializationKind()) {
-  case TSK_Undeclared:
+  if (Specialization->getTemplateSpecializationKind() == TSK_Undeclared) {
     Diag(D.getIdentifierLoc(), 
          diag::err_explicit_instantiation_member_function_not_instantiated)
       << Specialization
@@ -4064,35 +4062,30 @@
           TSK_ExplicitSpecialization);
     Diag(Specialization->getLocation(), diag::note_explicit_instantiation_here);
     return true;
-
-  case TSK_ExplicitSpecialization:
-    // C++ [temp.explicit]p4:
-    //   For a given set of template parameters, if an explicit instantiation
-    //   of a template appears after a declaration of an explicit 
-    //   specialization for that template, the explicit instantiation has no 
-    //   effect.
-    break;      
-
-  case TSK_ExplicitInstantiationDefinition:
-    // FIXME: Check that we aren't trying to perform an explicit instantiation
-    // declaration now.
-    // Fall through
-      
-  case TSK_ImplicitInstantiation:
-  case TSK_ExplicitInstantiationDeclaration:
-    // Instantiate the function, if this is an explicit instantiation 
-    // definition.
-    if (TSK == TSK_ExplicitInstantiationDefinition)
-      InstantiateFunctionDefinition(D.getIdentifierLoc(), Specialization, 
-                                    false, /*DefinitionRequired=*/true);
-      
-    Specialization->setTemplateSpecializationKind(TSK);
-    break;
+  } 
+  
+  FunctionDecl *PrevDecl = Specialization->getPreviousDeclaration();
+  if (PrevDecl) {
+    bool SuppressNew = false;
+    if (CheckSpecializationInstantiationRedecl(*this, D.getIdentifierLoc(), TSK,
+                                               PrevDecl, 
+                                     PrevDecl->getTemplateSpecializationKind(), 
+                                          PrevDecl->getPointOfInstantiation(),
+                                               SuppressNew))
+      return true;
+    
+    // FIXME: We may still want to build some representation of this
+    // explicit specialization.
+    if (SuppressNew)
+      return DeclPtrTy();
   }
-
-  // Check the scope of this explicit instantiation.
-  FunctionTemplateDecl *FunTmpl = Specialization->getPrimaryTemplate();
   
+  if (TSK == TSK_ExplicitInstantiationDefinition)
+    InstantiateFunctionDefinition(D.getIdentifierLoc(), Specialization, 
+                                  false, /*DefinitionRequired=*/true);
+      
+  Specialization->setTemplateSpecializationKind(TSK, D.getIdentifierLoc());
+ 
   // C++0x [temp.explicit]p2:
   //   If the explicit instantiation is for a member function, a member class 
   //   or a static data member of a class template specialization, the name of
@@ -4100,6 +4093,7 @@
   //   name shall be a simple-template-id.
   //
   // C++98 has the same restriction, just worded differently.
+  FunctionTemplateDecl *FunTmpl = Specialization->getPrimaryTemplate();
   if (D.getKind() != Declarator::DK_TemplateId && !FunTmpl &&
       D.getCXXScopeSpec().isSet() && 
       !ScopeSpecifierHasTemplateId(D.getCXXScopeSpec()))





More information about the cfe-commits mailing list