mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-11-27 15:41:46 +00:00
For instantiations of static data members of class templates, keep
track of the kind of specialization or instantiation. Also, check the scope of the specialization and ensure that a specialization declaration without an initializer is not a definition. llvm-svn: 83533
This commit is contained in:
parent
662efc9185
commit
86d142a801
@ -154,7 +154,8 @@ class ASTContext {
|
||||
///
|
||||
/// This data structure stores the mapping from instantiations of static
|
||||
/// data members to the static data member representations within the
|
||||
/// class template from which they were instantiated.
|
||||
/// class template from which they were instantiated along with the kind
|
||||
/// of instantiation or specialization (a TemplateSpecializationKind - 1).
|
||||
///
|
||||
/// Given the following example:
|
||||
///
|
||||
@ -172,8 +173,9 @@ class ASTContext {
|
||||
///
|
||||
/// This mapping will contain an entry that maps from the VarDecl for
|
||||
/// X<int>::value to the corresponding VarDecl for X<T>::value (within the
|
||||
/// class template X).
|
||||
llvm::DenseMap<VarDecl *, VarDecl *> InstantiatedFromStaticDataMember;
|
||||
/// class template X) and will be marked TSK_ImplicitInstantiation.
|
||||
llvm::DenseMap<VarDecl *, MemberSpecializationInfo *>
|
||||
InstantiatedFromStaticDataMember;
|
||||
|
||||
/// \brief Keeps track of the UnresolvedUsingDecls from which UsingDecls
|
||||
/// where created during instantiation.
|
||||
@ -265,11 +267,12 @@ public:
|
||||
/// \brief If this variable is an instantiated static data member of a
|
||||
/// class template specialization, returns the templated static data member
|
||||
/// from which it was instantiated.
|
||||
VarDecl *getInstantiatedFromStaticDataMember(VarDecl *Var);
|
||||
MemberSpecializationInfo *getInstantiatedFromStaticDataMember(VarDecl *Var);
|
||||
|
||||
/// \brief Note that the static data member \p Inst is an instantiation of
|
||||
/// the static data member template \p Tmpl of a class template.
|
||||
void setInstantiatedFromStaticDataMember(VarDecl *Inst, VarDecl *Tmpl);
|
||||
void setInstantiatedFromStaticDataMember(VarDecl *Inst, VarDecl *Tmpl,
|
||||
TemplateSpecializationKind TSK);
|
||||
|
||||
/// \brief If this using decl is instantiated from an unresolved using decl,
|
||||
/// return it.
|
||||
|
@ -300,6 +300,29 @@ struct EvaluatedStmt {
|
||||
APValue Evaluated;
|
||||
};
|
||||
|
||||
// \brief Describes the kind of template specialization that a
|
||||
// particular template specialization declaration represents.
|
||||
enum TemplateSpecializationKind {
|
||||
/// This template specialization was formed from a template-id but
|
||||
/// has not yet been declared, defined, or instantiated.
|
||||
TSK_Undeclared = 0,
|
||||
/// This template specialization was implicitly instantiated from a
|
||||
/// template. (C++ [temp.inst]).
|
||||
TSK_ImplicitInstantiation,
|
||||
/// This template specialization was declared or defined by an
|
||||
/// explicit specialization (C++ [temp.expl.spec]) or partial
|
||||
/// specialization (C++ [temp.class.spec]).
|
||||
TSK_ExplicitSpecialization,
|
||||
/// This template specialization was instantiated from a template
|
||||
/// due to an explicit instantiation declaration request
|
||||
/// (C++0x [temp.explicit]).
|
||||
TSK_ExplicitInstantiationDeclaration,
|
||||
/// This template specialization was instantiated from a template
|
||||
/// due to an explicit instantiation definition request
|
||||
/// (C++ [temp.explicit]).
|
||||
TSK_ExplicitInstantiationDefinition
|
||||
};
|
||||
|
||||
/// VarDecl - An instance of this class is created to represent a variable
|
||||
/// declaration or definition.
|
||||
class VarDecl : public DeclaratorDecl, public Redeclarable<VarDecl> {
|
||||
@ -566,6 +589,14 @@ public:
|
||||
/// from which it was instantiated.
|
||||
VarDecl *getInstantiatedFromStaticDataMember();
|
||||
|
||||
/// \brief If this variable is a static data member, determine what kind of
|
||||
/// template specialization or instantiation this is.
|
||||
TemplateSpecializationKind getTemplateSpecializationKind();
|
||||
|
||||
/// \brief For a static data member that was instantiated from a static
|
||||
/// data member of a class template, set the template specialiation kind.
|
||||
void setTemplateSpecializationKind(TemplateSpecializationKind TSK);
|
||||
|
||||
/// isFileVarDecl - Returns true for file scoped variable declaration.
|
||||
bool isFileVarDecl() const {
|
||||
if (getKind() != Decl::Var)
|
||||
@ -754,29 +785,6 @@ public:
|
||||
static bool classof(const OriginalParmVarDecl *D) { return true; }
|
||||
};
|
||||
|
||||
// \brief Describes the kind of template specialization that a
|
||||
// particular template specialization declaration represents.
|
||||
enum TemplateSpecializationKind {
|
||||
/// This template specialization was formed from a template-id but
|
||||
/// has not yet been declared, defined, or instantiated.
|
||||
TSK_Undeclared = 0,
|
||||
/// This template specialization was implicitly instantiated from a
|
||||
/// template. (C++ [temp.inst]).
|
||||
TSK_ImplicitInstantiation,
|
||||
/// This template specialization was declared or defined by an
|
||||
/// explicit specialization (C++ [temp.expl.spec]) or partial
|
||||
/// specialization (C++ [temp.class.spec]).
|
||||
TSK_ExplicitSpecialization,
|
||||
/// This template specialization was instantiated from a template
|
||||
/// due to an explicit instantiation declaration request
|
||||
/// (C++0x [temp.explicit]).
|
||||
TSK_ExplicitInstantiationDeclaration,
|
||||
/// This template specialization was instantiated from a template
|
||||
/// due to an explicit instantiation definition request
|
||||
/// (C++ [temp.explicit]).
|
||||
TSK_ExplicitInstantiationDefinition
|
||||
};
|
||||
|
||||
/// FunctionDecl - An instance of this class is created to represent a
|
||||
/// function declaration or definition.
|
||||
///
|
||||
|
@ -948,9 +948,8 @@ def err_template_spec_redecl_global_scope : Error<
|
||||
"%select{class template|class template partial|function template|member "
|
||||
"function|static data member|member class}0 specialization of %1 must occur "
|
||||
"at global scope">;
|
||||
def err_function_spec_not_instantiated : Error<
|
||||
"specialization of member function %q0 does not specialize an instantiated "
|
||||
"member function">;
|
||||
def err_spec_member_not_instantiated : Error<
|
||||
"specialization of member %q0 does not specialize an instantiated member">;
|
||||
def note_specialized_decl : Note<"attempt to specialize declaration here">;
|
||||
|
||||
// C++ class template specializations and out-of-line definitions
|
||||
|
@ -232,9 +232,10 @@ void ASTContext::InitBuiltinTypes() {
|
||||
InitBuiltinType(NullPtrTy, BuiltinType::NullPtr);
|
||||
}
|
||||
|
||||
VarDecl *ASTContext::getInstantiatedFromStaticDataMember(VarDecl *Var) {
|
||||
MemberSpecializationInfo *
|
||||
ASTContext::getInstantiatedFromStaticDataMember(VarDecl *Var) {
|
||||
assert(Var->isStaticDataMember() && "Not a static data member");
|
||||
llvm::DenseMap<VarDecl *, VarDecl *>::iterator Pos
|
||||
llvm::DenseMap<VarDecl *, MemberSpecializationInfo *>::iterator Pos
|
||||
= InstantiatedFromStaticDataMember.find(Var);
|
||||
if (Pos == InstantiatedFromStaticDataMember.end())
|
||||
return 0;
|
||||
@ -243,12 +244,14 @@ VarDecl *ASTContext::getInstantiatedFromStaticDataMember(VarDecl *Var) {
|
||||
}
|
||||
|
||||
void
|
||||
ASTContext::setInstantiatedFromStaticDataMember(VarDecl *Inst, VarDecl *Tmpl) {
|
||||
ASTContext::setInstantiatedFromStaticDataMember(VarDecl *Inst, VarDecl *Tmpl,
|
||||
TemplateSpecializationKind TSK) {
|
||||
assert(Inst->isStaticDataMember() && "Not a static data member");
|
||||
assert(Tmpl->isStaticDataMember() && "Not a static data member");
|
||||
assert(!InstantiatedFromStaticDataMember[Inst] &&
|
||||
"Already noted what static data member was instantiated from");
|
||||
InstantiatedFromStaticDataMember[Inst] = Tmpl;
|
||||
InstantiatedFromStaticDataMember[Inst]
|
||||
= new (*this) MemberSpecializationInfo(Tmpl, TSK);
|
||||
}
|
||||
|
||||
UnresolvedUsingDecl *
|
||||
|
@ -371,7 +371,26 @@ SourceRange VarDecl::getSourceRange() const {
|
||||
}
|
||||
|
||||
VarDecl *VarDecl::getInstantiatedFromStaticDataMember() {
|
||||
return getASTContext().getInstantiatedFromStaticDataMember(this);
|
||||
if (MemberSpecializationInfo *MSI
|
||||
= getASTContext().getInstantiatedFromStaticDataMember(this))
|
||||
return cast<VarDecl>(MSI->getInstantiatedFrom());
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
TemplateSpecializationKind VarDecl::getTemplateSpecializationKind() {
|
||||
if (MemberSpecializationInfo *MSI
|
||||
= getASTContext().getInstantiatedFromStaticDataMember(this))
|
||||
return MSI->getTemplateSpecializationKind();
|
||||
|
||||
return TSK_Undeclared;
|
||||
}
|
||||
|
||||
void VarDecl::setTemplateSpecializationKind(TemplateSpecializationKind TSK) {
|
||||
MemberSpecializationInfo *MSI
|
||||
= getASTContext().getInstantiatedFromStaticDataMember(this);
|
||||
assert(MSI && "Not an instantiated static data member?");
|
||||
MSI->setTemplateSpecializationKind(TSK);
|
||||
}
|
||||
|
||||
bool VarDecl::isTentativeDefinition(ASTContext &Context) const {
|
||||
|
@ -2519,8 +2519,7 @@ public:
|
||||
unsigned NumExplicitTemplateArgs,
|
||||
SourceLocation RAngleLoc,
|
||||
NamedDecl *&PrevDecl);
|
||||
bool CheckMemberFunctionSpecialization(CXXMethodDecl *FD,
|
||||
NamedDecl *&PrevDecl);
|
||||
bool CheckMemberSpecialization(NamedDecl *Member, NamedDecl *&PrevDecl);
|
||||
|
||||
virtual DeclResult
|
||||
ActOnExplicitInstantiation(Scope *S,
|
||||
|
@ -2193,7 +2193,6 @@ Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC,
|
||||
|
||||
// Match up the template parameter lists with the scope specifier, then
|
||||
// determine whether we have a template or a template specialization.
|
||||
// FIXME: Actually record when this is an explicit specialization!
|
||||
bool isExplicitSpecialization = false;
|
||||
if (TemplateParameterList *TemplateParams
|
||||
= MatchTemplateParametersToScopeSpecifier(
|
||||
@ -2259,7 +2258,7 @@ Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC,
|
||||
!(NewVD->hasLinkage() &&
|
||||
isOutOfScopePreviousDeclaration(PrevDecl, DC, Context)))
|
||||
PrevDecl = 0;
|
||||
|
||||
|
||||
// Merge the decl with the existing one if appropriate.
|
||||
if (PrevDecl) {
|
||||
if (isa<FieldDecl>(PrevDecl) && D.getCXXScopeSpec().isSet()) {
|
||||
@ -2281,6 +2280,11 @@ Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC,
|
||||
|
||||
CheckVariableDeclaration(NewVD, PrevDecl, Redeclaration);
|
||||
|
||||
// This is an explicit specialization of a static data member. Check it.
|
||||
if (isExplicitSpecialization && !NewVD->isInvalidDecl() &&
|
||||
CheckMemberSpecialization(NewVD, PrevDecl))
|
||||
NewVD->setInvalidDecl();
|
||||
|
||||
// attributes declared post-definition are currently ignored
|
||||
if (PrevDecl) {
|
||||
const VarDecl *Def = 0, *PrevVD = dyn_cast<VarDecl>(PrevDecl);
|
||||
@ -2837,8 +2841,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
|
||||
PrevDecl))
|
||||
NewFD->setInvalidDecl();
|
||||
} else if (isExplicitSpecialization && isa<CXXMethodDecl>(NewFD) &&
|
||||
CheckMemberFunctionSpecialization(cast<CXXMethodDecl>(NewFD),
|
||||
PrevDecl))
|
||||
CheckMemberSpecialization(NewFD, PrevDecl))
|
||||
NewFD->setInvalidDecl();
|
||||
|
||||
// Perform semantic checking on the function declaration.
|
||||
@ -3400,6 +3403,15 @@ void Sema::ActOnUninitializedDecl(DeclPtrTy dcl,
|
||||
return;
|
||||
}
|
||||
|
||||
// C++ [temp.expl.spec]p15:
|
||||
// An explicit specialization of a static data member of a template is a
|
||||
// definition if the declaration includes an initializer; otherwise, it
|
||||
// is a declaration.
|
||||
if (Var->isStaticDataMember() &&
|
||||
Var->getInstantiatedFromStaticDataMember() &&
|
||||
Var->getTemplateSpecializationKind() == TSK_ExplicitSpecialization)
|
||||
return;
|
||||
|
||||
// C++ [dcl.init]p9:
|
||||
// If no initializer is specified for an object, and the object
|
||||
// is of (possibly cv-qualified) non-POD class type (or array
|
||||
|
@ -6209,11 +6209,9 @@ void Sema::MarkDeclarationReferenced(SourceLocation Loc, Decl *D) {
|
||||
|
||||
if (VarDecl *Var = dyn_cast<VarDecl>(D)) {
|
||||
// Implicit instantiation of static data members of class templates.
|
||||
// FIXME: distinguish between implicit instantiations (which we need to
|
||||
// actually instantiate) and explicit specializations.
|
||||
// FIXME: extern templates
|
||||
if (Var->isStaticDataMember() &&
|
||||
Var->getInstantiatedFromStaticDataMember())
|
||||
Var->getInstantiatedFromStaticDataMember() &&
|
||||
Var->getTemplateSpecializationKind() == TSK_ImplicitInstantiation)
|
||||
PendingImplicitInstantiations.push_back(std::make_pair(Var, Loc));
|
||||
|
||||
// FIXME: keep track of references to static data?
|
||||
|
@ -2365,8 +2365,9 @@ static TemplateSpecializationKind getTemplateSpecializationKind(NamedDecl *D) {
|
||||
return CTS->getSpecializationKind();
|
||||
if (FunctionDecl *Function = dyn_cast<FunctionDecl>(D))
|
||||
return Function->getTemplateSpecializationKind();
|
||||
|
||||
// FIXME: static data members!
|
||||
if (VarDecl *Var = dyn_cast<VarDecl>(D))
|
||||
return Var->getTemplateSpecializationKind();
|
||||
|
||||
// FIXME: member classes of class templates!
|
||||
return TSK_Undeclared;
|
||||
}
|
||||
@ -3118,7 +3119,7 @@ Sema::CheckFunctionTemplateSpecialization(FunctionDecl *FD,
|
||||
return false;
|
||||
}
|
||||
|
||||
/// \brief Perform semantic analysis for the given member function
|
||||
/// \brief Perform semantic analysis for the given non-template member
|
||||
/// specialization.
|
||||
///
|
||||
/// This routine performs all of the semantic analysis required for an
|
||||
@ -3126,27 +3127,45 @@ Sema::CheckFunctionTemplateSpecialization(FunctionDecl *FD,
|
||||
/// the function declaration \p FD will become a member function
|
||||
/// specialization.
|
||||
///
|
||||
/// \param FD the function declaration, which will be updated to become a
|
||||
/// function template specialization.
|
||||
/// \param Member the member declaration, which will be updated to become a
|
||||
/// specialization.
|
||||
///
|
||||
/// \param PrevDecl the set of declarations, one of which may be specialized
|
||||
/// by this function specialization.
|
||||
bool
|
||||
Sema::CheckMemberFunctionSpecialization(CXXMethodDecl *FD,
|
||||
NamedDecl *&PrevDecl) {
|
||||
// Try to find the member function we are instantiating.
|
||||
CXXMethodDecl *Instantiation = 0;
|
||||
for (OverloadIterator Ovl(PrevDecl), OvlEnd; Ovl != OvlEnd; ++Ovl) {
|
||||
if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(*Ovl)) {
|
||||
if (Context.hasSameType(FD->getType(), Method->getType())) {
|
||||
Instantiation = Method;
|
||||
break;
|
||||
Sema::CheckMemberSpecialization(NamedDecl *Member, NamedDecl *&PrevDecl) {
|
||||
assert(!isa<TemplateDecl>(Member) && "Only for non-template members");
|
||||
|
||||
// Try to find the member we are instantiating.
|
||||
NamedDecl *Instantiation = 0;
|
||||
NamedDecl *InstantiatedFrom = 0;
|
||||
if (!PrevDecl) {
|
||||
// Nowhere to look anyway.
|
||||
} else if (FunctionDecl *Function = dyn_cast<FunctionDecl>(Member)) {
|
||||
for (OverloadIterator Ovl(PrevDecl), OvlEnd; Ovl != OvlEnd; ++Ovl) {
|
||||
if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(*Ovl)) {
|
||||
if (Context.hasSameType(Function->getType(), Method->getType())) {
|
||||
Instantiation = Method;
|
||||
InstantiatedFrom = Method->getInstantiatedFromMemberFunction();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (isa<VarDecl>(Member)) {
|
||||
if (VarDecl *PrevVar = dyn_cast<VarDecl>(PrevDecl))
|
||||
if (PrevVar->isStaticDataMember()) {
|
||||
Instantiation = PrevDecl;
|
||||
InstantiatedFrom = PrevVar->getInstantiatedFromStaticDataMember();
|
||||
}
|
||||
} else if (isa<RecordDecl>(Member)) {
|
||||
if (CXXRecordDecl *PrevRecord = dyn_cast<CXXRecordDecl>(PrevDecl)) {
|
||||
Instantiation = PrevDecl;
|
||||
InstantiatedFrom = PrevRecord->getInstantiatedFromMemberClass();
|
||||
}
|
||||
}
|
||||
|
||||
if (!Instantiation) {
|
||||
// There is no previous declaration that matches. Since member function
|
||||
// There is no previous declaration that matches. Since member
|
||||
// specializations are always out-of-line, the caller will complain about
|
||||
// this mismatch later.
|
||||
return false;
|
||||
@ -3155,30 +3174,43 @@ Sema::CheckMemberFunctionSpecialization(CXXMethodDecl *FD,
|
||||
// FIXME: Check if the prior declaration has a point of instantiation.
|
||||
// If so, we have run afoul of C++ [temp.expl.spec]p6.
|
||||
|
||||
// Make sure that this is a specialization of a member function.
|
||||
FunctionDecl *FunctionInTemplate
|
||||
= Instantiation->getInstantiatedFromMemberFunction();
|
||||
if (!FunctionInTemplate) {
|
||||
Diag(FD->getLocation(), diag::err_function_spec_not_instantiated)
|
||||
<< FD;
|
||||
// Make sure that this is a specialization of a member.
|
||||
if (!InstantiatedFrom) {
|
||||
Diag(Member->getLocation(), diag::err_spec_member_not_instantiated)
|
||||
<< Member;
|
||||
Diag(Instantiation->getLocation(), diag::note_specialized_decl);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check the scope of this explicit specialization.
|
||||
if (CheckTemplateSpecializationScope(*this,
|
||||
FunctionInTemplate,
|
||||
Instantiation, FD->getLocation(),
|
||||
InstantiatedFrom,
|
||||
Instantiation, Member->getLocation(),
|
||||
false, TSK_ExplicitSpecialization))
|
||||
return true;
|
||||
|
||||
// FIXME: Check for specialization-after-instantiation errors and such.
|
||||
|
||||
// Note that this function is an explicit instantiation of a member function.
|
||||
Instantiation->setTemplateSpecializationKind(TSK_ExplicitSpecialization);
|
||||
FD->setInstantiationOfMemberFunction(FunctionInTemplate,
|
||||
TSK_ExplicitSpecialization);
|
||||
|
||||
// Note that this is an explicit instantiation of a member.
|
||||
if (isa<FunctionDecl>(Member)) {
|
||||
// FIXME: We're also setting the original instantiation we found to be
|
||||
// an explicit specialization, although I'd rather not have to do this.
|
||||
cast<FunctionDecl>(Instantiation)->setTemplateSpecializationKind(
|
||||
TSK_ExplicitSpecialization);
|
||||
cast<FunctionDecl>(Member)->setInstantiationOfMemberFunction(
|
||||
cast<CXXMethodDecl>(InstantiatedFrom),
|
||||
TSK_ExplicitSpecialization);
|
||||
} else if (isa<VarDecl>(Member)) {
|
||||
Context.setInstantiatedFromStaticDataMember(cast<VarDecl>(Member),
|
||||
cast<VarDecl>(InstantiatedFrom),
|
||||
TSK_ExplicitSpecialization);
|
||||
} else {
|
||||
assert(isa<CXXRecordDecl>(Member) && "Only member classes remain");
|
||||
// FIXME: Record TSK_ExplicitSpecialization.
|
||||
cast<CXXRecordDecl>(Member)->setInstantiationOfMemberClass(
|
||||
cast<CXXRecordDecl>(InstantiatedFrom));
|
||||
}
|
||||
|
||||
// Save the caller the trouble of having to figure out which declaration
|
||||
// this specialization matches.
|
||||
PrevDecl = Instantiation;
|
||||
@ -3547,7 +3579,8 @@ Sema::DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
|
||||
}
|
||||
|
||||
// Instantiate static data member.
|
||||
// FIXME: Note that this is an explicit instantiation.
|
||||
// FIXME: Check for prior specializations and such.
|
||||
Prev->setTemplateSpecializationKind(TSK);
|
||||
if (TSK == TSK_ExplicitInstantiationDefinition)
|
||||
InstantiateStaticDataMemberDefinition(D.getIdentifierLoc(), Prev, false);
|
||||
|
||||
|
@ -982,9 +982,12 @@ Sema::InstantiateClassMembers(SourceLocation PointOfInstantiation,
|
||||
if (!Function->getBody() && TSK != TSK_ExplicitInstantiationDeclaration)
|
||||
InstantiateFunctionDefinition(PointOfInstantiation, Function);
|
||||
} else if (VarDecl *Var = dyn_cast<VarDecl>(*D)) {
|
||||
if (Var->isStaticDataMember() &&
|
||||
TSK != TSK_ExplicitInstantiationDeclaration)
|
||||
InstantiateStaticDataMemberDefinition(PointOfInstantiation, Var);
|
||||
if (Var->isStaticDataMember()) {
|
||||
Var->setTemplateSpecializationKind(TSK);
|
||||
|
||||
if (TSK != TSK_ExplicitInstantiationDeclaration)
|
||||
InstantiateStaticDataMemberDefinition(PointOfInstantiation, Var);
|
||||
}
|
||||
} else if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(*D)) {
|
||||
if (Record->isInjectedClassName())
|
||||
continue;
|
||||
|
@ -155,6 +155,12 @@ Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D) {
|
||||
Owner->addDecl(Var);
|
||||
}
|
||||
|
||||
// Link instantiations of static data members back to the template from
|
||||
// which they were instantiated.
|
||||
if (Var->isStaticDataMember())
|
||||
SemaRef.Context.setInstantiatedFromStaticDataMember(Var, D,
|
||||
TSK_ImplicitInstantiation);
|
||||
|
||||
if (D->getInit()) {
|
||||
OwningExprResult Init
|
||||
= SemaRef.SubstExpr(D->getInit(), TemplateArgs);
|
||||
@ -191,11 +197,6 @@ Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D) {
|
||||
} else if (!Var->isStaticDataMember() || Var->isOutOfLine())
|
||||
SemaRef.ActOnUninitializedDecl(Sema::DeclPtrTy::make(Var), false);
|
||||
|
||||
// Link instantiations of static data members back to the template from
|
||||
// which they were instantiated.
|
||||
if (Var->isStaticDataMember())
|
||||
SemaRef.Context.setInstantiatedFromStaticDataMember(Var, D);
|
||||
|
||||
return Var;
|
||||
}
|
||||
|
||||
@ -977,6 +978,10 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
|
||||
|
||||
assert(!Function->getBody() && "Already instantiated!");
|
||||
|
||||
// Never instantiate an explicit specialization.
|
||||
if (Function->getTemplateSpecializationKind() == TSK_ExplicitSpecialization)
|
||||
return;
|
||||
|
||||
// Find the function body that we'll be substituting.
|
||||
const FunctionDecl *PatternDecl = 0;
|
||||
if (FunctionTemplateDecl *Primary = Function->getPrimaryTemplate()) {
|
||||
@ -1084,7 +1089,6 @@ void Sema::InstantiateStaticDataMemberDefinition(
|
||||
return;
|
||||
|
||||
// Find the out-of-line definition of this static data member.
|
||||
// FIXME: Do we have to look for specializations separately?
|
||||
VarDecl *Def = Var->getInstantiatedFromStaticDataMember();
|
||||
bool FoundOutOfLineDef = false;
|
||||
assert(Def && "This data member was not instantiated from a template?");
|
||||
@ -1106,7 +1110,17 @@ void Sema::InstantiateStaticDataMemberDefinition(
|
||||
return;
|
||||
}
|
||||
|
||||
// FIXME: extern templates
|
||||
// Never instantiate an explicit specialization.
|
||||
if (Def->getTemplateSpecializationKind() == TSK_ExplicitSpecialization)
|
||||
return;
|
||||
|
||||
// C++0x [temp.explicit]p9:
|
||||
// Except for inline functions, other explicit instantiation declarations
|
||||
// have the effect of suppressing the implicit instantiation of the entity
|
||||
// to which they refer.
|
||||
if (Def->getTemplateSpecializationKind()
|
||||
== TSK_ExplicitInstantiationDeclaration)
|
||||
return;
|
||||
|
||||
InstantiatingTemplate Inst(*this, PointOfInstantiation, Var);
|
||||
if (Inst)
|
||||
|
@ -49,7 +49,7 @@ namespace N0 {
|
||||
|
||||
template<typename T>
|
||||
struct X0 { // expected-note 2{{here}}
|
||||
static T member;
|
||||
static T member; // expected-note{{here}}
|
||||
|
||||
void f1(T t) { // expected-note{{explicitly specialized declaration is here}}
|
||||
t = 17;
|
||||
@ -106,16 +106,27 @@ void test_x0_cvvoid(N0::X0<const volatile void*> x0, const volatile void *cvp) {
|
||||
x0.f1(cvp); // okay: we've explicitly specialized
|
||||
}
|
||||
|
||||
#if 0
|
||||
// FIXME: update the remainder of this test to check for scopes properly.
|
||||
// -- static data member of a class template
|
||||
template<>
|
||||
NonDefaultConstructible X0<NonDefaultConstructible>::member = 17;
|
||||
namespace N0 {
|
||||
// This actually tests p15; the following is a declaration, not a definition.
|
||||
template<>
|
||||
NonDefaultConstructible X0<NonDefaultConstructible>::member;
|
||||
|
||||
template<> long X0<long>::member = 17;
|
||||
|
||||
NonDefaultConstructible &get_static_member() {
|
||||
return X0<NonDefaultConstructible>::member;
|
||||
template<> float X0<float>::member;
|
||||
}
|
||||
|
||||
NonDefaultConstructible &get_static_member() {
|
||||
return N0::X0<NonDefaultConstructible>::member;
|
||||
}
|
||||
|
||||
template<> int N0::X0<int>::member; // expected-error{{originally}}
|
||||
|
||||
template<> float N0::X0<float>::member = 3.14f;
|
||||
|
||||
#if 0
|
||||
// FIXME: update the remainder of this test to check for scopes properly.
|
||||
// -- member class of a class template
|
||||
template<>
|
||||
struct X0<void*>::Inner { };
|
||||
|
Loading…
Reference in New Issue
Block a user