Keep track of whether a member function instantiated from a member
function of a class template was implicitly instantiated, explicitly instantiated (declaration or definition), or explicitly specialized. The same MemberSpecializationInfo structure will be used for static data members and member classes as well. llvm-svn: 83509
This commit is contained in:
parent
32cc4ec304
commit
d801b06232
|
@ -27,6 +27,7 @@ class Stmt;
|
|||
class CompoundStmt;
|
||||
class StringLiteral;
|
||||
class TemplateArgumentList;
|
||||
class MemberSpecializationInfo;
|
||||
class FunctionTemplateSpecializationInfo;
|
||||
class TypeLoc;
|
||||
|
||||
|
@ -830,14 +831,15 @@ private:
|
|||
/// For non-templates, this value will be NULL. For function
|
||||
/// declarations that describe a function template, this will be a
|
||||
/// pointer to a FunctionTemplateDecl. For member functions
|
||||
/// of class template specializations, this will be the
|
||||
/// FunctionDecl from which the member function was instantiated.
|
||||
/// of class template specializations, this will be a MemberSpecializationInfo
|
||||
/// pointer containing information about the specialization.
|
||||
/// For function template specializations, this will be a
|
||||
/// FunctionTemplateSpecializationInfo, which contains information about
|
||||
/// the template being specialized and the template arguments involved in
|
||||
/// that specialization.
|
||||
llvm::PointerUnion3<FunctionTemplateDecl*, FunctionDecl*,
|
||||
FunctionTemplateSpecializationInfo*>
|
||||
llvm::PointerUnion3<FunctionTemplateDecl *,
|
||||
MemberSpecializationInfo *,
|
||||
FunctionTemplateSpecializationInfo *>
|
||||
TemplateOrSpecialization;
|
||||
|
||||
protected:
|
||||
|
@ -1063,15 +1065,12 @@ public:
|
|||
/// the FunctionDecl X<T>::A. When a complete definition of
|
||||
/// X<int>::A is required, it will be instantiated from the
|
||||
/// declaration returned by getInstantiatedFromMemberFunction().
|
||||
FunctionDecl *getInstantiatedFromMemberFunction() const {
|
||||
return TemplateOrSpecialization.dyn_cast<FunctionDecl*>();
|
||||
}
|
||||
FunctionDecl *getInstantiatedFromMemberFunction() const;
|
||||
|
||||
/// \brief Specify that this record is an instantiation of the
|
||||
/// member function RD.
|
||||
void setInstantiationOfMemberFunction(FunctionDecl *RD) {
|
||||
TemplateOrSpecialization = RD;
|
||||
}
|
||||
/// member function FD.
|
||||
void setInstantiationOfMemberFunction(FunctionDecl *FD,
|
||||
TemplateSpecializationKind TSK);
|
||||
|
||||
/// \brief Retrieves the function template that is described by this
|
||||
/// function declaration.
|
||||
|
|
|
@ -548,6 +548,33 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
/// \brief Provides information a specialization of a member of a class
|
||||
/// template, which may be a member function, static data member, or
|
||||
/// member class.
|
||||
class MemberSpecializationInfo {
|
||||
NamedDecl *InstantiatedFrom;
|
||||
TemplateSpecializationKind TSK;
|
||||
|
||||
public:
|
||||
explicit
|
||||
MemberSpecializationInfo(NamedDecl *IF, TemplateSpecializationKind TSK)
|
||||
: InstantiatedFrom(IF), TSK(TSK) { }
|
||||
|
||||
/// \brief Retrieve the member declaration from which this member was
|
||||
/// instantiated.
|
||||
NamedDecl *getInstantiatedFrom() const { return InstantiatedFrom; }
|
||||
|
||||
/// \brief Determine what kind of template specialization this is.
|
||||
TemplateSpecializationKind getTemplateSpecializationKind() const {
|
||||
return TSK;
|
||||
}
|
||||
|
||||
/// \brief Set the template specialization kind.
|
||||
void setTemplateSpecializationKind(TemplateSpecializationKind TSK) {
|
||||
this->TSK = TSK;
|
||||
}
|
||||
};
|
||||
|
||||
/// Declaration of a template function.
|
||||
class FunctionTemplateDecl : public TemplateDecl {
|
||||
protected:
|
||||
|
|
|
@ -410,6 +410,16 @@ void FunctionDecl::Destroy(ASTContext& C) {
|
|||
for (param_iterator I=param_begin(), E=param_end(); I!=E; ++I)
|
||||
(*I)->Destroy(C);
|
||||
|
||||
FunctionTemplateSpecializationInfo *FTSInfo
|
||||
= TemplateOrSpecialization.dyn_cast<FunctionTemplateSpecializationInfo*>();
|
||||
if (FTSInfo)
|
||||
C.Deallocate(FTSInfo);
|
||||
|
||||
MemberSpecializationInfo *MSInfo
|
||||
= TemplateOrSpecialization.dyn_cast<MemberSpecializationInfo*>();
|
||||
if (MSInfo)
|
||||
C.Deallocate(MSInfo);
|
||||
|
||||
C.Deallocate(ParamInfo);
|
||||
|
||||
Decl::Destroy(C);
|
||||
|
@ -670,6 +680,24 @@ OverloadedOperatorKind FunctionDecl::getOverloadedOperator() const {
|
|||
return OO_None;
|
||||
}
|
||||
|
||||
FunctionDecl *FunctionDecl::getInstantiatedFromMemberFunction() const {
|
||||
if (MemberSpecializationInfo *Info
|
||||
= TemplateOrSpecialization.dyn_cast<MemberSpecializationInfo*>())
|
||||
return cast<FunctionDecl>(Info->getInstantiatedFrom());
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
FunctionDecl::setInstantiationOfMemberFunction(FunctionDecl *FD,
|
||||
TemplateSpecializationKind TSK) {
|
||||
assert(TemplateOrSpecialization.isNull() &&
|
||||
"Member function is already a specialization");
|
||||
MemberSpecializationInfo *Info
|
||||
= new (getASTContext()) MemberSpecializationInfo(FD, TSK);
|
||||
TemplateOrSpecialization = Info;
|
||||
}
|
||||
|
||||
FunctionTemplateDecl *FunctionDecl::getPrimaryTemplate() const {
|
||||
if (FunctionTemplateSpecializationInfo *Info
|
||||
= TemplateOrSpecialization
|
||||
|
@ -727,32 +755,30 @@ FunctionDecl::setFunctionTemplateSpecialization(ASTContext &Context,
|
|||
TemplateSpecializationKind FunctionDecl::getTemplateSpecializationKind() const {
|
||||
// For a function template specialization, query the specialization
|
||||
// information object.
|
||||
FunctionTemplateSpecializationInfo *Info
|
||||
FunctionTemplateSpecializationInfo *FTSInfo
|
||||
= TemplateOrSpecialization.dyn_cast<FunctionTemplateSpecializationInfo*>();
|
||||
if (Info)
|
||||
return Info->getTemplateSpecializationKind();
|
||||
if (FTSInfo)
|
||||
return FTSInfo->getTemplateSpecializationKind();
|
||||
|
||||
if (!getInstantiatedFromMemberFunction())
|
||||
return TSK_Undeclared;
|
||||
MemberSpecializationInfo *MSInfo
|
||||
= TemplateOrSpecialization.dyn_cast<MemberSpecializationInfo*>();
|
||||
if (MSInfo)
|
||||
return MSInfo->getTemplateSpecializationKind();
|
||||
|
||||
// Find the class template specialization corresponding to this instantiation
|
||||
// of a member function.
|
||||
const DeclContext *Parent = getDeclContext();
|
||||
while (Parent && !isa<ClassTemplateSpecializationDecl>(Parent))
|
||||
Parent = Parent->getParent();
|
||||
|
||||
if (!Parent)
|
||||
return TSK_Undeclared;
|
||||
|
||||
return cast<ClassTemplateSpecializationDecl>(Parent)->getSpecializationKind();
|
||||
return TSK_Undeclared;
|
||||
}
|
||||
|
||||
void
|
||||
FunctionDecl::setTemplateSpecializationKind(TemplateSpecializationKind TSK) {
|
||||
FunctionTemplateSpecializationInfo *Info
|
||||
= TemplateOrSpecialization.dyn_cast<FunctionTemplateSpecializationInfo*>();
|
||||
assert(Info && "Not a function template specialization");
|
||||
Info->setTemplateSpecializationKind(TSK);
|
||||
if (FunctionTemplateSpecializationInfo *FTSInfo
|
||||
= TemplateOrSpecialization.dyn_cast<
|
||||
FunctionTemplateSpecializationInfo*>())
|
||||
FTSInfo->setTemplateSpecializationKind(TSK);
|
||||
else if (MemberSpecializationInfo *MSInfo
|
||||
= TemplateOrSpecialization.dyn_cast<MemberSpecializationInfo*>())
|
||||
MSInfo->setTemplateSpecializationKind(TSK);
|
||||
else
|
||||
assert(false && "Function cannot have a template specialization kind");
|
||||
}
|
||||
|
||||
bool FunctionDecl::isOutOfLine() const {
|
||||
|
|
|
@ -3172,9 +3172,12 @@ Sema::CheckMemberFunctionSpecialization(CXXMethodDecl *FD,
|
|||
false, TSK_ExplicitSpecialization))
|
||||
return true;
|
||||
|
||||
// FIXME: Mark the new declaration as a member function specialization.
|
||||
// We may also want to mark the original instantiation as having been
|
||||
// explicitly specialized.
|
||||
// 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);
|
||||
|
||||
// Save the caller the trouble of having to figure out which declaration
|
||||
// this specialization matches.
|
||||
|
|
|
@ -977,6 +977,8 @@ Sema::InstantiateClassMembers(SourceLocation PointOfInstantiation,
|
|||
DEnd = Instantiation->decls_end();
|
||||
D != DEnd; ++D) {
|
||||
if (FunctionDecl *Function = dyn_cast<FunctionDecl>(*D)) {
|
||||
if (Function->getInstantiatedFromMemberFunction())
|
||||
Function->setTemplateSpecializationKind(TSK);
|
||||
if (!Function->getBody() && TSK != TSK_ExplicitInstantiationDeclaration)
|
||||
InstantiateFunctionDefinition(PointOfInstantiation, Function);
|
||||
} else if (VarDecl *Var = dyn_cast<VarDecl>(*D)) {
|
||||
|
@ -984,14 +986,19 @@ Sema::InstantiateClassMembers(SourceLocation PointOfInstantiation,
|
|||
TSK != TSK_ExplicitInstantiationDeclaration)
|
||||
InstantiateStaticDataMemberDefinition(PointOfInstantiation, Var);
|
||||
} else if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(*D)) {
|
||||
if (!Record->isInjectedClassName() && !Record->getDefinition(Context)) {
|
||||
assert(Record->getInstantiatedFromMemberClass() &&
|
||||
"Missing instantiated-from-template information");
|
||||
if (Record->isInjectedClassName())
|
||||
continue;
|
||||
|
||||
assert(Record->getInstantiatedFromMemberClass() &&
|
||||
"Missing instantiated-from-template information");
|
||||
if (!Record->getDefinition(Context))
|
||||
InstantiateClass(PointOfInstantiation, Record,
|
||||
Record->getInstantiatedFromMemberClass(),
|
||||
TemplateArgs,
|
||||
TSK);
|
||||
}
|
||||
else
|
||||
InstantiateClassMembers(PointOfInstantiation, Record, TemplateArgs,
|
||||
TSK);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -522,7 +522,7 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D) {
|
|||
if (!Owner->isDependentContext())
|
||||
DC->makeDeclVisibleInContext(Function, /* Recoverable = */ false);
|
||||
|
||||
Function->setInstantiationOfMemberFunction(D);
|
||||
Function->setInstantiationOfMemberFunction(D, TSK_ImplicitInstantiation);
|
||||
}
|
||||
|
||||
if (InitFunctionInstantiation(Function, D))
|
||||
|
@ -637,7 +637,7 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D,
|
|||
FunctionTemplate->setLexicalDeclContext(D->getLexicalDeclContext());
|
||||
Method->setDescribedFunctionTemplate(FunctionTemplate);
|
||||
} else if (!FunctionTemplate)
|
||||
Method->setInstantiationOfMemberFunction(D);
|
||||
Method->setInstantiationOfMemberFunction(D, TSK_ImplicitInstantiation);
|
||||
|
||||
// If we are instantiating a member function defined
|
||||
// out-of-line, the instantiation will have the same lexical
|
||||
|
|
|
@ -31,11 +31,11 @@ void test_intptr(X0<int*> xi, X0<int*>::Inner xii) {
|
|||
|
||||
// FIXME: we would like the notes to point to the explicit instantiation at the
|
||||
// bottom.
|
||||
extern template class X0<long*>; // expected-note{{instantiation}}
|
||||
extern template class X0<long*>; // expected-note 2{{instantiation}}
|
||||
|
||||
void test_longptr(X0<long*> xl, X0<long*>::Inner xli) {
|
||||
xl.f(0);
|
||||
xli.g(0); // expected-note{{instantiation}}
|
||||
xli.g(0);
|
||||
}
|
||||
|
||||
template class X0<long*>;
|
||||
|
|
Loading…
Reference in New Issue