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@UExplicitInst_Exported@@@@3HA" -// GNU-NOT: @_Z10VarTmplDefI21ExplicitInst_ExportedE -template<typename T> __declspec(dllexport) int VarTmplDef; -INSTVAR(VarTmplDef<ExplicitInst_Exported>) - // MSC-DAG: @"\01??$VarTmplImplicitDef@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. _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits