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