[NFC] Start saving InstantiatedFromDecl in non-template functions

In cases where a non-template function is defined inside a function
template, we don't have information about the original uninstantiated
version.  In the case of concepts instantiation, we will need the
ability to get back to the original template.  This patch splits a piece
of the deferred concepts instantaition patch off to accomplish the
storage of this, with minor runtime overhead, and zero additional
storage.
This commit is contained in:
Erich Keane 2022-07-22 12:30:47 -07:00
parent 7068aa9841
commit 3ff86f9610
7 changed files with 58 additions and 11 deletions

View File

@ -1890,7 +1890,10 @@ public:
TK_FunctionTemplateSpecialization,
// A function template specialization that hasn't yet been resolved to a
// particular specialized function template.
TK_DependentFunctionTemplateSpecialization
TK_DependentFunctionTemplateSpecialization,
// A non-template function which is in a dependent scope.
TK_DependentNonTemplate
};
/// Stashed information about a defaulted function definition whose body has
@ -1939,20 +1942,21 @@ private:
/// The template or declaration that this declaration
/// describes or was instantiated from, respectively.
///
/// 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 a MemberSpecializationInfo
/// For non-templates this value will be NULL, unless this declaration was
/// declared directly inside of a function template, in which case it will
/// have a pointer to a FunctionDecl, stored in the NamedDecl. For function
/// declarations that describe a function template, this will be a pointer to
/// a FunctionTemplateDecl, stored in the NamedDecl. For member functions 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::PointerUnion<FunctionTemplateDecl *,
MemberSpecializationInfo *,
llvm::PointerUnion<NamedDecl *, MemberSpecializationInfo *,
FunctionTemplateSpecializationInfo *,
DependentFunctionTemplateSpecializationInfo *>
TemplateOrSpecialization;
TemplateOrSpecialization;
/// Provides source/type location info for the declaration name embedded in
/// the DeclaratorDecl base class.
@ -2695,6 +2699,13 @@ public:
setInstantiationOfMemberFunction(getASTContext(), FD, TSK);
}
/// Specify that this function declaration was instantiated from a
/// FunctionDecl FD. This is only used if this is a function declaration
/// declared locally inside of a function template.
void setInstantiatedFromDecl(FunctionDecl *FD);
FunctionDecl *getInstantiatedFromDecl() const;
/// Retrieves the function template that is described by this
/// function declaration.
///

View File

@ -3109,6 +3109,11 @@ Error ASTNodeImporter::ImportTemplateInformation(
case FunctionDecl::TK_FunctionTemplate:
return Error::success();
case FunctionDecl::TK_DependentNonTemplate:
if (Expected<FunctionDecl *> InstFDOrErr =
import(FromFD->getInstantiatedFromDecl()))
ToFD->setInstantiatedFromDecl(*InstFDOrErr);
return Error::success();
case FunctionDecl::TK_MemberSpecialization: {
TemplateSpecializationKind TSK = FromFD->getTemplateSpecializationKind();

View File

@ -3732,8 +3732,13 @@ const IdentifierInfo *FunctionDecl::getLiteralIdentifier() const {
FunctionDecl::TemplatedKind FunctionDecl::getTemplatedKind() const {
if (TemplateOrSpecialization.isNull())
return TK_NonTemplate;
if (TemplateOrSpecialization.is<FunctionTemplateDecl *>())
if (const auto *ND = TemplateOrSpecialization.dyn_cast<NamedDecl *>()) {
if (isa<FunctionDecl>(ND))
return TK_DependentNonTemplate;
assert(isa<FunctionTemplateDecl>(ND) &&
"No other valid types in NamedDecl");
return TK_FunctionTemplate;
}
if (TemplateOrSpecialization.is<MemberSpecializationInfo *>())
return TK_MemberSpecialization;
if (TemplateOrSpecialization.is<FunctionTemplateSpecializationInfo *>())
@ -3774,15 +3779,28 @@ FunctionDecl::setInstantiationOfMemberFunction(ASTContext &C,
}
FunctionTemplateDecl *FunctionDecl::getDescribedFunctionTemplate() const {
return TemplateOrSpecialization.dyn_cast<FunctionTemplateDecl *>();
return dyn_cast_or_null<FunctionTemplateDecl>(
TemplateOrSpecialization.dyn_cast<NamedDecl *>());
}
void FunctionDecl::setDescribedFunctionTemplate(FunctionTemplateDecl *Template) {
void FunctionDecl::setDescribedFunctionTemplate(
FunctionTemplateDecl *Template) {
assert(TemplateOrSpecialization.isNull() &&
"Member function is already a specialization");
TemplateOrSpecialization = Template;
}
void FunctionDecl::setInstantiatedFromDecl(FunctionDecl *FD) {
assert(TemplateOrSpecialization.isNull() &&
"Function is already a specialization");
TemplateOrSpecialization = FD;
}
FunctionDecl *FunctionDecl::getInstantiatedFromDecl() const {
return dyn_cast_or_null<FunctionDecl>(
TemplateOrSpecialization.dyn_cast<NamedDecl *>());
}
bool FunctionDecl::isImplicitlyInstantiable() const {
// If the function is invalid, it can't be implicitly instantiated.
if (isInvalidDecl())

View File

@ -303,6 +303,7 @@ public:
// Skip templated functions.
switch (Decl->getTemplatedKind()) {
case FunctionDecl::TK_NonTemplate:
case FunctionDecl::TK_DependentNonTemplate:
break;
case FunctionDecl::TK_MemberSpecialization:
case FunctionDecl::TK_FunctionTemplateSpecialization:

View File

@ -2182,6 +2182,11 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(
// definition. We don't want non-template functions to be marked as being
// template instantiations.
Function->setInstantiationOfMemberFunction(D, TSK_ImplicitInstantiation);
} else if (!isFriend) {
// If this is not a function template, and this is not a friend (that is,
// this is a locally declared function), save the instantiation relationship
// for the purposes of constraint instantiation.
Function->setInstantiatedFromDecl(D);
}
if (isFriend) {

View File

@ -953,6 +953,10 @@ void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) {
case FunctionDecl::TK_NonTemplate:
mergeRedeclarable(FD, Redecl);
break;
case FunctionDecl::TK_DependentNonTemplate:
mergeRedeclarable(FD, Redecl);
FD->setInstantiatedFromDecl(readDeclAs<FunctionDecl>());
break;
case FunctionDecl::TK_FunctionTemplate:
// Merged when we merge the template.
FD->setDescribedFunctionTemplate(readDeclAs<FunctionTemplateDecl>());

View File

@ -585,6 +585,9 @@ void ASTDeclWriter::VisitFunctionDecl(FunctionDecl *D) {
switch (D->getTemplatedKind()) {
case FunctionDecl::TK_NonTemplate:
break;
case FunctionDecl::TK_DependentNonTemplate:
Record.AddDeclRef(D->getInstantiatedFromDecl());
break;
case FunctionDecl::TK_FunctionTemplate:
Record.AddDeclRef(D->getDescribedFunctionTemplate());
break;