r188350 - Bug fix: disallow a variable template to be redeclared as a non-templated variable
Larisse Voufo
lvoufo at google.com
Tue Aug 13 20:09:19 PDT 2013
Author: lvoufo
Date: Tue Aug 13 22:09:19 2013
New Revision: 188350
URL: http://llvm.org/viewvc/llvm-project?rev=188350&view=rev
Log:
Bug fix: disallow a variable template to be redeclared as a non-templated variable
Modified:
cfe/trunk/include/clang/Sema/Sema.h
cfe/trunk/lib/Sema/SemaDecl.cpp
cfe/trunk/lib/Sema/SemaTemplate.cpp
cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
cfe/trunk/lib/Serialization/ASTWriterDecl.cpp
cfe/trunk/test/CXX/temp/temp.spec/cxx1y-variable-template-no-body.cpp
cfe/trunk/test/CXX/temp/temp.spec/temp.expl.spec/examples.cpp
cfe/trunk/test/PCH/cxx1y-variable-templates.cpp
cfe/trunk/test/SemaCXX/cxx1y-variable-templates_top_level.cpp
Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=188350&r1=188349&r2=188350&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Tue Aug 13 22:09:19 2013
@@ -1472,7 +1472,8 @@ public:
MultiTemplateParamsArg TemplateParamLists,
bool &AddToScope);
// Returns true if the variable declaration is a redeclaration
- bool CheckVariableDeclaration(VarDecl *NewVD, LookupResult &Previous);
+ bool CheckVariableDeclaration(VarDecl *NewVD, LookupResult &Previous,
+ bool IsVariableTemplate = false);
void CheckVariableDeclarationType(VarDecl *NewVD);
void CheckCompleteVariableDeclaration(VarDecl *var);
void MaybeSuggestAddingStaticToDecl(const FunctionDecl *D);
@@ -1868,9 +1869,8 @@ public:
Scope *S, bool MergeTypeWithOld);
void mergeObjCMethodDecls(ObjCMethodDecl *New, ObjCMethodDecl *Old);
void MergeVarDecl(VarDecl *New, LookupResult &Previous,
- bool MergeTypeWithPrevious);
- void MergeVarDeclTypes(VarDecl *New, VarDecl *Old,
- bool MergeTypeWithOld);
+ bool IsVariableTemplate, bool MergeTypeWithPrevious);
+ void MergeVarDeclTypes(VarDecl *New, VarDecl *Old, bool MergeTypeWithOld);
void MergeVarDeclExceptionSpecs(VarDecl *New, VarDecl *Old);
bool MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old, Scope *S);
Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=188350&r1=188349&r2=188350&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Tue Aug 13 22:09:19 2013
@@ -2920,15 +2920,21 @@ void Sema::MergeVarDeclTypes(VarDecl *Ne
/// definitions here, since the initializer hasn't been attached.
///
void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous,
- bool MergeTypeWithPrevious) {
+ bool IsVariableTemplate, bool MergeTypeWithPrevious) {
// If the new decl is already invalid, don't do any other checking.
if (New->isInvalidDecl())
return;
- // Verify the old decl was also a variable.
+ // Verify the old decl was also a variable or variable template.
VarDecl *Old = 0;
- if (!Previous.isSingleResult() ||
- !(Old = dyn_cast<VarDecl>(Previous.getFoundDecl()))) {
+ if (Previous.isSingleResult() &&
+ (Old = dyn_cast<VarDecl>(Previous.getFoundDecl()))) {
+ if (IsVariableTemplate)
+ Old = Old->getDescribedVarTemplate() ? Old : 0;
+ else
+ Old = Old->getDescribedVarTemplate() ? 0 : Old;
+ }
+ if (!Old) {
Diag(New->getLocation(), diag::err_redefinition_different_kind)
<< New->getDeclName();
Diag(Previous.getRepresentativeDecl()->getLocation(),
@@ -4919,6 +4925,7 @@ Sema::ActOnVariableDeclarator(Scope *S,
bool IsExplicitSpecialization = false;
bool IsVariableTemplateSpecialization = false;
bool IsPartialSpecialization = false;
+ bool IsVariableTemplate = false;
bool Invalid = false; // TODO: Can we remove this (error-prone)?
TemplateParameterList *TemplateParams = 0;
VarTemplateDecl *PrevVarTemplate = 0;
@@ -5019,6 +5026,7 @@ Sema::ActOnVariableDeclarator(Scope *S,
} else { // if (TemplateParams->size() > 0)
// This is a template declaration.
+ IsVariableTemplate = true;
// Check that we can declare a template here.
if (CheckTemplateDeclScope(S, TemplateParams))
@@ -5310,9 +5318,11 @@ Sema::ActOnVariableDeclarator(Scope *S,
LookupResult PrevDecl(*this, GetNameForDeclarator(D),
LookupOrdinaryName, ForRedeclaration);
PrevDecl.addDecl(PrevVarTemplate->getTemplatedDecl());
- D.setRedeclaration(CheckVariableDeclaration(NewVD, PrevDecl));
+ D.setRedeclaration(
+ CheckVariableDeclaration(NewVD, PrevDecl, IsVariableTemplate));
} else
- D.setRedeclaration(CheckVariableDeclaration(NewVD, Previous));
+ D.setRedeclaration(
+ CheckVariableDeclaration(NewVD, Previous, IsVariableTemplate));
}
// This is an explicit specialization of a static data member. Check it.
@@ -5340,8 +5350,8 @@ Sema::ActOnVariableDeclarator(Scope *S,
}
}
- // If this is not a variable template, return it now
- if (!TemplateParams || IsVariableTemplateSpecialization)
+ // If this is not a variable template, return it now.
+ if (!IsVariableTemplate)
return NewVD;
// If this is supposed to be a variable template, create it as such.
@@ -5745,7 +5755,8 @@ void Sema::CheckVariableDeclarationType(
///
/// Returns true if the variable declaration is a redeclaration.
bool Sema::CheckVariableDeclaration(VarDecl *NewVD,
- LookupResult &Previous) {
+ LookupResult &Previous,
+ bool IsVariableTemplate) {
CheckVariableDeclarationType(NewVD);
// If the decl is already known invalid, don't check it.
@@ -5795,7 +5806,7 @@ bool Sema::CheckVariableDeclaration(VarD
filterNonConflictingPreviousDecls(Context, NewVD, Previous);
if (!Previous.empty()) {
- MergeVarDecl(NewVD, Previous, MergeTypeWithPrevious);
+ MergeVarDecl(NewVD, Previous, IsVariableTemplate, MergeTypeWithPrevious);
return true;
}
return false;
Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=188350&r1=188349&r2=188350&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Tue Aug 13 22:09:19 2013
@@ -2280,32 +2280,6 @@ static bool CheckTemplateSpecializationS
bool IsPartialSpecialization);
static TemplateSpecializationKind getTemplateSpecializationKind(Decl *D);
-/*
-// Check the new variable specialization against the parsed input.
-//
-// FIXME: Model this against function specializations where
-// a new function declaration is checked against the specialization
-// as candidate for redefinition... (?)
-static bool CheckVariableTemplateSpecializationType() {
-
- if (ExpectedType is undeduced && ParsedType is not undeduced)
- ExpectedType = dedudeType();
-
- if (both types are undeduced)
- ???;
-
- bool CheckType = !ExpectedType()->
-
- if (!Context.hasSameType(DI->getType(), ExpectedDI->getType())) {
- unsigned ErrStr = IsPartialSpecialization ? 2 : 1;
- Diag(D.getIdentifierLoc(), diag::err_invalid_var_template_spec_type)
- << ErrStr << VarTemplate << DI->getType() << ExpectedDI->getType();
- Diag(VarTemplate->getLocation(), diag::note_template_declared_here)
- << 2 << VarTemplate->getDeclName();
- return true;
- }
-}
-*/
DeclResult Sema::ActOnVarTemplateSpecialization(
Scope *S, VarTemplateDecl *VarTemplate, Declarator &D, TypeSourceInfo *DI,
@@ -2359,13 +2333,6 @@ DeclResult Sema::ActOnVarTemplateSpecial
if (!ExpectedDI)
return true;
- /*
- // Check the new variable specialization against the parsed input.
- // (Attributes are merged later below.)
- if (CheckVariableTemplateSpecializationType())
- return true;
- */
-
// Find the variable template (partial) specialization declaration that
// corresponds to these arguments.
if (IsPartialSpecialization) {
Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=188350&r1=188349&r2=188350&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Tue Aug 13 22:09:19 2013
@@ -3365,7 +3365,7 @@ void Sema::BuildVariableInstantiation(
OldVar->hasLinkage())
LookupQualifiedName(Previous, NewVar->getDeclContext(), false);
- CheckVariableDeclaration(NewVar, Previous);
+ CheckVariableDeclaration(NewVar, Previous, ForVarTemplate);
if (OldVar->isOutOfLine()) {
OldVar->getLexicalDeclContext()->addDecl(NewVar);
Modified: cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderDecl.cpp?rev=188350&r1=188349&r2=188350&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReaderDecl.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReaderDecl.cpp Tue Aug 13 22:09:19 2013
@@ -943,7 +943,7 @@ ASTDeclReader::RedeclarableResult ASTDec
VD->setCachedLinkage(Linkage(Record[Idx++]));
// Only true variables (not parameters or implicit parameters) can be merged.
- if (VD->getKind() == Decl::Var)
+ if (VD->getKind() != Decl::ParmVar && VD->getKind() != Decl::ImplicitParam)
mergeRedeclarable(VD, Redecl);
if (uint64_t Val = Record[Idx++]) {
@@ -955,11 +955,22 @@ ASTDeclReader::RedeclarableResult ASTDec
}
}
- if (Record[Idx++]) { // HasMemberSpecializationInfo.
+ enum VarKind {
+ VarNotTemplate = 0, VarTemplate, StaticDataMemberSpecialization
+ };
+ switch ((VarKind)Record[Idx++]) {
+ case VarNotTemplate:
+ break;
+ case VarTemplate:
+ VD->setDescribedVarTemplate(ReadDeclAs<VarTemplateDecl>(Record, Idx));
+ break;
+ case StaticDataMemberSpecialization: { // HasMemberSpecializationInfo.
VarDecl *Tmpl = ReadDeclAs<VarDecl>(Record, Idx);
TemplateSpecializationKind TSK = (TemplateSpecializationKind)Record[Idx++];
SourceLocation POI = ReadSourceLocation(Record, Idx);
Reader.getContext().setInstantiatedFromStaticDataMember(VD, Tmpl, TSK,POI);
+ break;
+ }
}
return Redecl;
@@ -1433,7 +1444,7 @@ void ASTDeclReader::VisitVarTemplateDecl
RedeclarableResult Redecl = VisitRedeclarableTemplateDecl(D);
if (ThisDeclID == Redecl.getFirstID()) {
- // This ClassTemplateDecl owns a CommonPtr; read it to keep track of all of
+ // This VarTemplateDecl owns a CommonPtr; read it to keep track of all of
// the specializations.
SmallVector<serialization::DeclID, 2> SpecIDs;
SpecIDs.push_back(0);
Modified: cfe/trunk/lib/Serialization/ASTWriterDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriterDecl.cpp?rev=188350&r1=188349&r2=188350&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTWriterDecl.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTWriterDecl.cpp Tue Aug 13 22:09:19 2013
@@ -712,14 +712,21 @@ void ASTDeclWriter::VisitVarDecl(VarDecl
} else {
Record.push_back(0);
}
-
- MemberSpecializationInfo *SpecInfo
- = D->isStaticDataMember() ? D->getMemberSpecializationInfo() : 0;
- Record.push_back(SpecInfo != 0);
- if (SpecInfo) {
+
+ enum {
+ VarNotTemplate = 0, VarTemplate, StaticDataMemberSpecialization
+ };
+ if (VarTemplateDecl *TemplD = D->getDescribedVarTemplate()) {
+ Record.push_back(VarTemplate);
+ Writer.AddDeclRef(TemplD, Record);
+ } else if (MemberSpecializationInfo *SpecInfo
+ = D->getMemberSpecializationInfo()) {
+ Record.push_back(StaticDataMemberSpecialization);
Writer.AddDeclRef(SpecInfo->getInstantiatedFrom(), Record);
Record.push_back(SpecInfo->getTemplateSpecializationKind());
Writer.AddSourceLocation(SpecInfo->getPointOfInstantiation(), Record);
+ } else {
+ Record.push_back(VarNotTemplate);
}
if (!D->hasAttrs() &&
@@ -739,7 +746,7 @@ void ASTDeclWriter::VisitVarDecl(VarDecl
!isa<VarTemplateSpecializationDecl>(D) &&
!D->isConstexpr() &&
!D->isPreviousDeclInSameBlockScope() &&
- !SpecInfo)
+ !D->getMemberSpecializationInfo())
AbbrevToUse = Writer.getDeclVarAbbrev();
Code = serialization::DECL_VAR;
Modified: cfe/trunk/test/CXX/temp/temp.spec/cxx1y-variable-template-no-body.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.spec/cxx1y-variable-template-no-body.cpp?rev=188350&r1=188349&r2=188350&view=diff
==============================================================================
--- cfe/trunk/test/CXX/temp/temp.spec/cxx1y-variable-template-no-body.cpp (original)
+++ cfe/trunk/test/CXX/temp/temp.spec/cxx1y-variable-template-no-body.cpp Tue Aug 13 22:09:19 2013
@@ -20,7 +20,7 @@ template<typename T>
T pi0 = T(3.1415926535897932385); // expected-note {{previous definition is here}}
template int pi0 = 10; // expected-error {{variable cannot be defined in an explicit instantiation; if this declaration is meant to be a variable definition, remove the 'template' keyword}} \
- expected-error{{redefinition of 'pi0' with a different type: 'int' vs 'T'}}
+ expected-error{{redefinition of 'pi0' as different kind of symbol}}
#endif
template<typename T>
Modified: cfe/trunk/test/CXX/temp/temp.spec/temp.expl.spec/examples.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.spec/temp.expl.spec/examples.cpp?rev=188350&r1=188349&r2=188350&view=diff
==============================================================================
--- cfe/trunk/test/CXX/temp/temp.spec/temp.expl.spec/examples.cpp (original)
+++ cfe/trunk/test/CXX/temp/temp.spec/temp.expl.spec/examples.cpp Tue Aug 13 22:09:19 2013
@@ -163,8 +163,7 @@ namespace PR9877 {
template<> struct X<1>::Y { static const int Z = 1; };
const int X<0>::Y::Z;
- template<> const int X<1>::Y::Z; // expected-error{{extraneous 'template<>' in declaration of variable 'Z'}} \
- // expected-error{{forward declaration of variable template cannot have a nested name specifier}}
+ template<> const int X<1>::Y::Z; // expected-error{{extraneous 'template<>' in declaration of variable 'Z'}}
}
namespace PR9913 {
Modified: cfe/trunk/test/PCH/cxx1y-variable-templates.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/PCH/cxx1y-variable-templates.cpp?rev=188350&r1=188349&r2=188350&view=diff
==============================================================================
--- cfe/trunk/test/PCH/cxx1y-variable-templates.cpp (original)
+++ cfe/trunk/test/PCH/cxx1y-variable-templates.cpp Tue Aug 13 22:09:19 2013
@@ -168,5 +168,4 @@ namespace spec_join1 {
int* intpb = vd<int>;
}
-
#endif
Modified: cfe/trunk/test/SemaCXX/cxx1y-variable-templates_top_level.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/cxx1y-variable-templates_top_level.cpp?rev=188350&r1=188349&r2=188350&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/cxx1y-variable-templates_top_level.cpp (original)
+++ cfe/trunk/test/SemaCXX/cxx1y-variable-templates_top_level.cpp Tue Aug 13 22:09:19 2013
@@ -72,7 +72,7 @@ namespace odr_tmpl {
}
namespace pvt_cv {
template<typename T> T v; // expected-note {{previous definition is here}}
- int v; // expected-error {{redefinition of 'v' with a different type: 'int' vs 'T'}}
+ int v; // expected-error {{redefinition of 'v' as different kind of symbol}}
}
namespace pvt_cvt {
template<typename T> T v0; // expected-note {{previous definition is here}}
@@ -107,6 +107,9 @@ namespace odr_tmpl {
#ifdef CXX11
template<typename T> extern auto v; // expected-error {{declaration of variable 'v' with type 'auto' requires an initializer}}
#endif
+
+ template<typename T> T var = T(); // expected-note {{previous definition is here}}
+ extern int var; // expected-error {{redefinition of 'var' as different kind of symbol}}
}
#ifdef CXX11
More information about the cfe-commits
mailing list