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