forked from OSchip/llvm-project
[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:
parent
7068aa9841
commit
3ff86f9610
|
@ -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,17 +1942,18 @@ 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;
|
||||
|
@ -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.
|
||||
///
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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())
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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>());
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue