// If we are providing an explicit specialization of a static variable
// template, make a note of that.
if (PrevVarTemplate && PrevVarTemplate->getInstantiatedFromMemberTemplate())
- NewTemplate->setMemberSpecialization();
+ PrevVarTemplate->setMemberSpecialization();
// Set the lexical context of this template
NewTemplate->setLexicalDeclContext(CurContext);
if (NewVD->isStaticDataMember() && NewVD->isOutOfLine())
NewTemplate->setAccess(NewVD->getAccess());
- if (PrevVarTemplate)
- mergeDeclAttributes(NewVD, PrevVarTemplate->getTemplatedDecl());
-
- AddPushedVisibilityAttribute(NewVD);
-
PushOnScopeChains(NewTemplate, S);
AddToScope = false;
// If we are providing an explicit specialization of a member variable
// template specialization, make a note of that.
if (PrevPartial && PrevPartial->getInstantiatedFromMember())
- Partial->setMemberSpecialization();
+ PrevPartial->setMemberSpecialization();
// Check that all of the template parameters of the variable template
// partial specialization are deducible from the template
ForRedeclaration);
PrevSpec.addDecl(PrevDecl);
D.setRedeclaration(CheckVariableDeclaration(Specialization, PrevSpec));
+ } else if (Specialization->isStaticDataMember() &&
+ Specialization->isOutOfLine()) {
+ Specialization->setAccess(VarTemplate->getAccess());
}
// Link instantiations of static data members back to the template from
Decl *TemplateDeclInstantiator::VisitVarTemplateDecl(VarTemplateDecl *D) {
assert(D->getTemplatedDecl()->isStaticDataMember() &&
"Only static data member templates are allowed.");
- // FIXME: Also only when instantiating a class?
// Create a local instantiation scope for this variable template, which
// will contain the instantiations of the template parameters.
PrevVarTemplate = dyn_cast<VarTemplateDecl>(Found.front());
}
- // FIXME: This, and ForVarTemplate, is a hack that is probably unnecessary.
- // We should use a simplified version of VisitVarDecl.
VarDecl *VarInst =
cast_or_null<VarDecl>(VisitVarDecl(Pattern, /*ForVarTemplate=*/ true));
DeclContext *DC = Owner;
- /* FIXME: This should be handled in VisitVarDecl, as used to produce
- VarInst above.
- // Instantiate the qualifier.
- NestedNameSpecifierLoc QualifierLoc = Pattern->getQualifierLoc();
- if (QualifierLoc) {
- QualifierLoc =
- SemaRef.SubstNestedNameSpecifierLoc(QualifierLoc, TemplateArgs);
- if (!QualifierLoc)
- return 0;
- }
-
- if (QualifierLoc)
- VarInst->setQualifierInfo(QualifierLoc);
- */
-
VarTemplateDecl *Inst = VarTemplateDecl::Create(
SemaRef.Context, DC, D->getLocation(), D->getIdentifier(), InstParams,
VarInst, PrevVarTemplate);
VarTemplatePartialSpecializationDecl *D) {
assert(D->isStaticDataMember() &&
"Only static data member templates are allowed.");
- // FIXME: Also only when instantiating a class?
VarTemplateDecl *VarTemplate = D->getSpecializedTemplate();
InstPartialSpec->setTypeAsWritten(WrittenTy);
InstPartialSpec->setAccess(PartialSpec->getAccess());
- // FIXME: How much of BuildVariableInstantiation() should go in here?
// Add this partial specialization to the set of variable template partial
// specializations. The instantiation of the initializer is not necessary.
VarTemplate->AddPartialSpecialization(InstPartialSpec, /*InsertPos=*/0);
+
+ // Set the initializer, to use as pattern for initialization.
+ if (VarDecl *Def = PartialSpec->getDefinition(SemaRef.getASTContext()))
+ PartialSpec = cast<VarTemplatePartialSpecializationDecl>(Def);
+ SemaRef.BuildVariableInstantiation(InstPartialSpec, PartialSpec, TemplateArgs,
+ LateAttrs, StartingScope);
+ InstPartialSpec->setInit(PartialSpec->getInit());
+
return InstPartialSpec;
}
const MultiLevelTemplateArgumentList &TemplateArgs) {
// Do substitution on the type of the declaration
+ MultiLevelTemplateArgumentList Innermost;
+ Innermost.addOuterTemplateArguments(TemplateArgs.getInnermost());
TypeSourceInfo *DI =
- SubstType(PatternDecl->getTypeSourceInfo(), TemplateArgs,
+ SubstType(PatternDecl->getTypeSourceInfo(), Innermost,
PatternDecl->getTypeSpecStartLoc(), PatternDecl->getDeclName());
if (!DI)
return 0;
if (isa<VarTemplateSpecializationDecl>(NewVar)) {
// Do not instantiate the variable just yet.
+ } else if (ForVarTemplate) {
+ assert(!NewVar->getInit() &&
+ "A variable should not have an initializer if it is templated"
+ " and we are instantiating its template");
+ NewVar->setInit(OldVar->getInit());
} else
InstantiateVariableInitializer(NewVar, OldVar, TemplateArgs);
};
namespace in_class_template {
- // FIXME: member data templates of class templates are not well supported yet.
template<typename T>
class D0 {
template<typename U> static U Data;
template<typename U> static const U Data<U*> = U();
};
+ template const int D0<float>::Data<int*>;
template<typename T>
class D1 {
};
template<typename T>
template<typename U> U* D1<T>::Data<U*> = (U*)(0);
-
- namespace to_be_fixed {
- // FIXME: The following generate runtime exceptions!
+ template int* D1<float>::Data<int*>;
+
+ template<typename T>
+ class D2 {
+ template<typename U> static U Data;
+ template<typename U> static U* Data<U*>;
+ };
+ template<>
+ template<typename U> U* D2<float>::Data<U*> = (U*)(0) + 1;
+ template int* D1<float>::Data<int*>;
+
+ template<typename T>
+ struct D3 {
+ template<typename U> static const U Data = U(100);
+ };
+ template const int D3<float>::Data<int>;
+#ifndef PRECXX11
+ static_assert(D3<float>::Data<int> == 100, "");
+#endif
- //template<>
- //template<typename U> U* D1<float>::Data<U*> = (U*)(0) + 1;
- //template const int D0<float>::Data<int*>;
- //template int* D1<float>::Data<int*>;
+ namespace bug_files {
+ // FIXME: A bug has been filed addressing an issue similar to these.
+ // No error diagnosis should be produced, because an
+ // explicit specialization of a member templates of class
+ // template specialization should not inherit the partial
+ // specializations from the class template specialization.
+
+ template<typename T>
+ class D0 {
+ template<typename U> static U Data;
+ template<typename U> static const U Data<U*> = U(10); // expected-note {{previous definition is here}}
+ };
+ template<>
+ template<typename U> U D0<float>::Data<U*> = U(100); // expected-error{{redefinition of 'Data'}}
+
+ template<typename T>
+ class D1 {
+ template<typename U> static U Data;
+ template<typename U> static U* Data<U*>; // expected-note {{previous definition is here}}
+ };
+ template<typename T>
+ template<typename U> U* D1<T>::Data<U*> = (U*)(0);
+ template<>
+ template<typename U> U* D1<float>::Data<U*> = (U*)(0) + 1; // expected-error{{redefinition of 'Data'}}
+ }
+
+ namespace other_bugs {
+ // FIXME: This fails to properly initilize the variable 'k'.
+
+ template<typename A> struct S {
+ template<typename B> static int V;
+ template<typename B> static int V0;
+ };
+ template struct S<int>;
+ template<typename A> template<typename B> int S<A>::V0 = 123;
+ template<typename A> template<typename B> int S<A>::V<B> = 123;
+ int k = S<int>::V<void>;
}
}