[cfe-commits] r83533 - in /cfe/trunk: include/clang/AST/ASTContext.h include/clang/AST/Decl.h include/clang/Basic/DiagnosticSemaKinds.td lib/AST/ASTContext.cpp lib/AST/Decl.cpp lib/Sema/Sema.h lib/Sema/SemaDecl.cpp lib/Sema/SemaExpr.cpp lib/Sema/SemaTemplate.cpp lib/Sema/SemaTemplateInstantiate.cpp lib/Sema/SemaTemplateInstantiateDecl.cpp test/CXX/temp/temp.spec/temp.expl.spec/p2.cpp
Douglas Gregor
dgregor at apple.com
Thu Oct 8 00:24:58 PDT 2009
Author: dgregor
Date: Thu Oct 8 02:24:58 2009
New Revision: 83533
URL: http://llvm.org/viewvc/llvm-project?rev=83533&view=rev
Log:
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.
Modified:
cfe/trunk/include/clang/AST/ASTContext.h
cfe/trunk/include/clang/AST/Decl.h
cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
cfe/trunk/lib/AST/ASTContext.cpp
cfe/trunk/lib/AST/Decl.cpp
cfe/trunk/lib/Sema/Sema.h
cfe/trunk/lib/Sema/SemaDecl.cpp
cfe/trunk/lib/Sema/SemaExpr.cpp
cfe/trunk/lib/Sema/SemaTemplate.cpp
cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
cfe/trunk/test/CXX/temp/temp.spec/temp.expl.spec/p2.cpp
Modified: cfe/trunk/include/clang/AST/ASTContext.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTContext.h?rev=83533&r1=83532&r2=83533&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/ASTContext.h (original)
+++ cfe/trunk/include/clang/AST/ASTContext.h Thu Oct 8 02:24:58 2009
@@ -154,7 +154,8 @@
///
/// 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 @@
///
/// 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 @@
/// \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.
Modified: cfe/trunk/include/clang/AST/Decl.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Decl.h?rev=83533&r1=83532&r2=83533&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Decl.h (original)
+++ cfe/trunk/include/clang/AST/Decl.h Thu Oct 8 02:24:58 2009
@@ -300,6 +300,29 @@
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 @@
/// 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 @@
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.
///
Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=83533&r1=83532&r2=83533&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Thu Oct 8 02:24:58 2009
@@ -948,9 +948,8 @@
"%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
Modified: cfe/trunk/lib/AST/ASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=83533&r1=83532&r2=83533&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTContext.cpp (original)
+++ cfe/trunk/lib/AST/ASTContext.cpp Thu Oct 8 02:24:58 2009
@@ -232,9 +232,10 @@
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 @@
}
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 *
Modified: cfe/trunk/lib/AST/Decl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Decl.cpp?rev=83533&r1=83532&r2=83533&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Decl.cpp (original)
+++ cfe/trunk/lib/AST/Decl.cpp Thu Oct 8 02:24:58 2009
@@ -371,7 +371,26 @@
}
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 {
Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=83533&r1=83532&r2=83533&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Thu Oct 8 02:24:58 2009
@@ -2519,8 +2519,7 @@
unsigned NumExplicitTemplateArgs,
SourceLocation RAngleLoc,
NamedDecl *&PrevDecl);
- bool CheckMemberFunctionSpecialization(CXXMethodDecl *FD,
- NamedDecl *&PrevDecl);
+ bool CheckMemberSpecialization(NamedDecl *Member, NamedDecl *&PrevDecl);
virtual DeclResult
ActOnExplicitInstantiation(Scope *S,
Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=83533&r1=83532&r2=83533&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Thu Oct 8 02:24:58 2009
@@ -2193,7 +2193,6 @@
// 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 @@
!(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 @@
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 @@
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 @@
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
Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=83533&r1=83532&r2=83533&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Thu Oct 8 02:24:58 2009
@@ -6209,11 +6209,9 @@
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?
Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=83533&r1=83532&r2=83533&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Thu Oct 8 02:24:58 2009
@@ -2365,8 +2365,9 @@
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 @@
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 @@
/// 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 @@
// 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 @@
}
// 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);
Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp?rev=83533&r1=83532&r2=83533&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp Thu Oct 8 02:24:58 2009
@@ -982,9 +982,12 @@
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;
Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=83533&r1=83532&r2=83533&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Thu Oct 8 02:24:58 2009
@@ -155,6 +155,12 @@
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 @@
} 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 @@
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 @@
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 @@
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)
Modified: cfe/trunk/test/CXX/temp/temp.spec/temp.expl.spec/p2.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.spec/temp.expl.spec/p2.cpp?rev=83533&r1=83532&r2=83533&view=diff
==============================================================================
--- cfe/trunk/test/CXX/temp/temp.spec/temp.expl.spec/p2.cpp (original)
+++ cfe/trunk/test/CXX/temp/temp.spec/temp.expl.spec/p2.cpp Thu Oct 8 02:24:58 2009
@@ -49,7 +49,7 @@
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 @@
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;
+
+ template<> float X0<float>::member;
+}
NonDefaultConstructible &get_static_member() {
- return X0<NonDefaultConstructible>::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 { };
More information about the cfe-commits
mailing list