r319605 - PR35456: Track definedness of variable template specializations separately from

Richard Smith via cfe-commits cfe-commits at lists.llvm.org
Fri Dec 1 18:48:42 PST 2017


Author: rsmith
Date: Fri Dec  1 18:48:42 2017
New Revision: 319605

URL: http://llvm.org/viewvc/llvm-project?rev=319605&view=rev
Log:
PR35456: Track definedness of variable template specializations separately from
whether they have an initializer.

We cannot distinguish between a declaration of a variable template
specialization and a definition of one that lacks an initializer without this,
and would previously mistake the latter for the former.

Modified:
    cfe/trunk/include/clang/AST/DeclTemplate.h
    cfe/trunk/lib/AST/Decl.cpp
    cfe/trunk/lib/AST/DeclTemplate.cpp
    cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
    cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
    cfe/trunk/lib/Serialization/ASTWriterDecl.cpp
    cfe/trunk/test/CodeGenCXX/cxx1y-variable-template.cpp
    cfe/trunk/test/CodeGenCXX/dllexport.cpp

Modified: cfe/trunk/include/clang/AST/DeclTemplate.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclTemplate.h?rev=319605&r1=319604&r2=319605&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclTemplate.h (original)
+++ cfe/trunk/include/clang/AST/DeclTemplate.h Fri Dec  1 18:48:42 2017
@@ -2540,6 +2540,12 @@ class VarTemplateSpecializationDecl : pu
   /// Really a value of type TemplateSpecializationKind.
   unsigned SpecializationKind : 3;
 
+  /// \brief Whether this declaration is a complete definition of the
+  /// variable template specialization. We can't otherwise tell apart
+  /// an instantiated declaration from an instantiated definition with
+  /// no initializer.
+  unsigned IsCompleteDefinition : 1;
+
 protected:
   VarTemplateSpecializationDecl(Kind DK, ASTContext &Context, DeclContext *DC,
                                 SourceLocation StartLoc, SourceLocation IdLoc,
@@ -2553,6 +2559,7 @@ protected:
 public:
   friend class ASTDeclReader;
   friend class ASTDeclWriter;
+  friend class VarDecl;
 
   static VarTemplateSpecializationDecl *
   Create(ASTContext &Context, DeclContext *DC, SourceLocation StartLoc,
@@ -2616,6 +2623,8 @@ public:
     PointOfInstantiation = Loc;
   }
 
+  void setCompleteDefinition() { IsCompleteDefinition = true; }
+
   /// \brief If this variable template specialization is an instantiation of
   /// a template (rather than an explicit specialization), return the
   /// variable template or variable template partial specialization from which

Modified: cfe/trunk/lib/AST/Decl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Decl.cpp?rev=319605&r1=319604&r2=319605&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Decl.cpp (original)
+++ cfe/trunk/lib/AST/Decl.cpp Fri Dec  1 18:48:42 2017
@@ -2029,9 +2029,12 @@ VarDecl::isThisDeclarationADefinition(AS
   // A variable template specialization (other than a static data member
   // template or an explicit specialization) is a declaration until we
   // instantiate its initializer.
-  if (isa<VarTemplateSpecializationDecl>(this) &&
-      getTemplateSpecializationKind() != TSK_ExplicitSpecialization)
-    return DeclarationOnly;
+  if (auto *VTSD = dyn_cast<VarTemplateSpecializationDecl>(this)) {
+    if (VTSD->getTemplateSpecializationKind() != TSK_ExplicitSpecialization &&
+        !isa<VarTemplatePartialSpecializationDecl>(VTSD) &&
+        !VTSD->IsCompleteDefinition)
+      return DeclarationOnly;
+  }
 
   if (hasExternalStorage())
     return DeclarationOnly;

Modified: cfe/trunk/lib/AST/DeclTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclTemplate.cpp?rev=319605&r1=319604&r2=319605&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclTemplate.cpp (original)
+++ cfe/trunk/lib/AST/DeclTemplate.cpp Fri Dec  1 18:48:42 2017
@@ -1043,13 +1043,13 @@ VarTemplateSpecializationDecl::VarTempla
               SpecializedTemplate->getIdentifier(), T, TInfo, S),
       SpecializedTemplate(SpecializedTemplate),
       TemplateArgs(TemplateArgumentList::CreateCopy(Context, Args)),
-      SpecializationKind(TSK_Undeclared) {}
+      SpecializationKind(TSK_Undeclared), IsCompleteDefinition(false) {}
 
 VarTemplateSpecializationDecl::VarTemplateSpecializationDecl(Kind DK,
                                                              ASTContext &C)
     : VarDecl(DK, C, nullptr, SourceLocation(), SourceLocation(), nullptr,
               QualType(), nullptr, SC_None),
-      SpecializationKind(TSK_Undeclared) {}
+      SpecializationKind(TSK_Undeclared), IsCompleteDefinition(false) {}
 
 VarTemplateSpecializationDecl *VarTemplateSpecializationDecl::Create(
     ASTContext &Context, DeclContext *DC, SourceLocation StartLoc,

Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=319605&r1=319604&r2=319605&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Fri Dec  1 18:48:42 2017
@@ -4021,6 +4021,8 @@ VarTemplateSpecializationDecl *Sema::Bui
 VarTemplateSpecializationDecl *Sema::CompleteVarTemplateSpecializationDecl(
     VarTemplateSpecializationDecl *VarSpec, VarDecl *PatternDecl,
     const MultiLevelTemplateArgumentList &TemplateArgs) {
+  assert(PatternDecl->isThisDeclarationADefinition() &&
+         "don't have a definition to instantiate from");
 
   // Do substitution on the type of the declaration
   TypeSourceInfo *DI =
@@ -4032,6 +4034,9 @@ VarTemplateSpecializationDecl *Sema::Com
   // Update the type of this variable template specialization.
   VarSpec->setType(DI->getType());
 
+  // Convert the declaration into a definition now.
+  VarSpec->setCompleteDefinition();
+
   // Instantiate the initializer.
   InstantiateVariableInitializer(VarSpec, PatternDecl, TemplateArgs);
 
@@ -4225,6 +4230,10 @@ void Sema::InstantiateVariableDefinition
   if (Var->isInvalidDecl())
     return;
 
+  // FIXME: We're missing ASTMutationListener notifications for all of the work
+  // done here. (Some of our callers notify the listeners for the static data
+  // member case, but not in general.)
+
   VarTemplateSpecializationDecl *VarSpec =
       dyn_cast<VarTemplateSpecializationDecl>(Var);
   VarDecl *PatternDecl = nullptr, *Def = nullptr;

Modified: cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderDecl.cpp?rev=319605&r1=319604&r2=319605&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReaderDecl.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReaderDecl.cpp Fri Dec  1 18:48:42 2017
@@ -2198,6 +2198,7 @@ ASTDeclReader::VisitVarTemplateSpecializ
   D->TemplateArgs = TemplateArgumentList::CreateCopy(C, TemplArgs);
   D->PointOfInstantiation = ReadSourceLocation();
   D->SpecializationKind = (TemplateSpecializationKind)Record.readInt();
+  D->IsCompleteDefinition = Record.readInt();
 
   bool writtenAsCanonicalDecl = Record.readInt();
   if (writtenAsCanonicalDecl) {

Modified: cfe/trunk/lib/Serialization/ASTWriterDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriterDecl.cpp?rev=319605&r1=319604&r2=319605&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTWriterDecl.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTWriterDecl.cpp Fri Dec  1 18:48:42 2017
@@ -1494,6 +1494,7 @@ void ASTDeclWriter::VisitVarTemplateSpec
   Record.AddTemplateArgumentList(&D->getTemplateArgs());
   Record.AddSourceLocation(D->getPointOfInstantiation());
   Record.push_back(D->getSpecializationKind());
+  Record.push_back(D->IsCompleteDefinition);
   Record.push_back(D->isCanonicalDecl());
 
   if (D->isCanonicalDecl()) {

Modified: cfe/trunk/test/CodeGenCXX/cxx1y-variable-template.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/cxx1y-variable-template.cpp?rev=319605&r1=319604&r2=319605&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/cxx1y-variable-template.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/cxx1y-variable-template.cpp Fri Dec  1 18:48:42 2017
@@ -18,6 +18,12 @@ int init_arr();
 template<typename T> template<typename U> template<typename V> int Outer<T>::Inner<U>::arr[sizeof(T) + sizeof(U) + sizeof(V)] = { init_arr() };
 int *p = Outer<char[100]>::Inner<char[20]>::arr<char[3]>;
 
+namespace PR35456 {
+// CHECK: @_ZN7PR354561nILi0EEE = linkonce_odr global i32 0
+template<int> int n;
+int *p = &n<0>;
+}
+
 // CHECK: @_ZN5OuterIA100_cE5InnerIA20_cE3arrIA3_cEE = linkonce_odr global [123 x i32] zeroinitializer
 // CHECK: @_ZGVN5OuterIA100_cE5InnerIA20_cE3arrIA3_cEE = linkonce_odr global
 

Modified: cfe/trunk/test/CodeGenCXX/dllexport.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/dllexport.cpp?rev=319605&r1=319604&r2=319605&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/dllexport.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/dllexport.cpp Fri Dec  1 18:48:42 2017
@@ -102,15 +102,9 @@ inline int __declspec(dllexport) inlineS
 
 // Declarations are not exported.
 
-// dllexport implies a definition.
-// MSC-NOT: @"\01??$VarTmplDef at UExplicitInst_Exported@@@@3HA"
-// GNU-NOT: @_Z10VarTmplDefI21ExplicitInst_ExportedE
-template<typename T> __declspec(dllexport) int VarTmplDef;
-INSTVAR(VarTmplDef<ExplicitInst_Exported>)
-
 // MSC-DAG: @"\01??$VarTmplImplicitDef at UImplicitInst_Exported@@@@3HA" = external global
 // GNU-DAG: @_Z18VarTmplImplicitDefI21ImplicitInst_ExportedE          = external global
-template<typename T> __declspec(dllexport) int VarTmplImplicitDef;
+template<typename T> __declspec(dllexport) extern int VarTmplImplicitDef;
 USEVAR(VarTmplImplicitDef<ImplicitInst_Exported>)
 
 // Export definition.




More information about the cfe-commits mailing list