summaryrefslogtreecommitdiffstats
path: root/clang/lib/AST/Decl.cpp
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2019-05-02 00:49:14 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2019-05-02 00:49:14 +0000
commitf19a8b05171a67a290e7d3bd6eba0c95c7b3259c (patch)
treecdee1c4c3c58d6211745af9959e9cb595fa2be20 /clang/lib/AST/Decl.cpp
parentbac77806c588125db314a04dbec0c416e7fec901 (diff)
downloadbcm5719-llvm-f19a8b05171a67a290e7d3bd6eba0c95c7b3259c.tar.gz
bcm5719-llvm-f19a8b05171a67a290e7d3bd6eba0c95c7b3259c.zip
Replace ad-hoc tracking of pattern for an instantiated class-scope
explicit function specialization with the MemberSpecializationInfo used everywhere else. Not NFC: the ad-hoc pattern tracking was not being serialized / deserialized properly. That's fixed here. llvm-svn: 359747
Diffstat (limited to 'clang/lib/AST/Decl.cpp')
-rw-r--r--clang/lib/AST/Decl.cpp119
1 files changed, 74 insertions, 45 deletions
diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp
index 64010666299..2c1dbbd7474 100644
--- a/clang/lib/AST/Decl.cpp
+++ b/clang/lib/AST/Decl.cpp
@@ -3375,7 +3375,13 @@ FunctionDecl *FunctionDecl::getInstantiatedFromMemberFunction() const {
}
MemberSpecializationInfo *FunctionDecl::getMemberSpecializationInfo() const {
- return TemplateOrSpecialization.dyn_cast<MemberSpecializationInfo *>();
+ if (auto *MSI =
+ TemplateOrSpecialization.dyn_cast<MemberSpecializationInfo *>())
+ return MSI;
+ if (auto *FTSI = TemplateOrSpecialization
+ .dyn_cast<FunctionTemplateSpecializationInfo *>())
+ return FTSI->getMemberSpecializationInfo();
+ return nullptr;
}
void
@@ -3394,6 +3400,8 @@ FunctionTemplateDecl *FunctionDecl::getDescribedFunctionTemplate() const {
}
void FunctionDecl::setDescribedFunctionTemplate(FunctionTemplateDecl *Template) {
+ assert(TemplateOrSpecialization.isNull() &&
+ "Member function is already a specialization");
TemplateOrSpecialization = Template;
}
@@ -3402,19 +3410,15 @@ bool FunctionDecl::isImplicitlyInstantiable() const {
if (isInvalidDecl())
return false;
- switch (getTemplateSpecializationKind()) {
+ switch (getTemplateSpecializationKindForInstantiation()) {
case TSK_Undeclared:
case TSK_ExplicitInstantiationDefinition:
+ case TSK_ExplicitSpecialization:
return false;
case TSK_ImplicitInstantiation:
return true;
- // It is possible to instantiate TSK_ExplicitSpecialization kind
- // if the FunctionDecl has a class scope specialization pattern.
- case TSK_ExplicitSpecialization:
- return getClassScopeSpecializationPattern() != nullptr;
-
case TSK_ExplicitInstantiationDeclaration:
// Handled below.
break;
@@ -3437,26 +3441,12 @@ bool FunctionDecl::isImplicitlyInstantiable() const {
}
bool FunctionDecl::isTemplateInstantiation() const {
- switch (getTemplateSpecializationKind()) {
- case TSK_Undeclared:
- case TSK_ExplicitSpecialization:
- return false;
- case TSK_ImplicitInstantiation:
- case TSK_ExplicitInstantiationDeclaration:
- case TSK_ExplicitInstantiationDefinition:
- return true;
- }
- llvm_unreachable("All TSK values handled.");
+ // FIXME: Remove this, it's not clear what it means. (Which template
+ // specialization kind?)
+ return clang::isTemplateInstantiation(getTemplateSpecializationKind());
}
FunctionDecl *FunctionDecl::getTemplateInstantiationPattern() const {
- // Handle class scope explicit specialization special case.
- if (getTemplateSpecializationKind() == TSK_ExplicitSpecialization) {
- if (auto *Spec = getClassScopeSpecializationPattern())
- return getDefinitionOrSelf(Spec);
- return nullptr;
- }
-
// If this is a generic lambda call operator specialization, its
// instantiation pattern is always its primary template's pattern
// even if its primary template was instantiated from another
@@ -3472,6 +3462,15 @@ FunctionDecl *FunctionDecl::getTemplateInstantiationPattern() const {
return getDefinitionOrSelf(getPrimaryTemplate()->getTemplatedDecl());
}
+ if (MemberSpecializationInfo *Info = getMemberSpecializationInfo()) {
+ if (!clang::isTemplateInstantiation(Info->getTemplateSpecializationKind()))
+ return nullptr;
+ return getDefinitionOrSelf(cast<FunctionDecl>(Info->getInstantiatedFrom()));
+ }
+
+ if (!clang::isTemplateInstantiation(getTemplateSpecializationKind()))
+ return nullptr;
+
if (FunctionTemplateDecl *Primary = getPrimaryTemplate()) {
while (Primary->getInstantiatedFromMemberTemplate()) {
// If we have hit a point where the user provided a specialization of
@@ -3484,9 +3483,6 @@ FunctionDecl *FunctionDecl::getTemplateInstantiationPattern() const {
return getDefinitionOrSelf(Primary->getTemplatedDecl());
}
- if (auto *MFD = getInstantiatedFromMemberFunction())
- return getDefinitionOrSelf(MFD);
-
return nullptr;
}
@@ -3494,15 +3490,11 @@ FunctionTemplateDecl *FunctionDecl::getPrimaryTemplate() const {
if (FunctionTemplateSpecializationInfo *Info
= TemplateOrSpecialization
.dyn_cast<FunctionTemplateSpecializationInfo*>()) {
- return Info->Template.getPointer();
+ return Info->getTemplate();
}
return nullptr;
}
-FunctionDecl *FunctionDecl::getClassScopeSpecializationPattern() const {
- return getASTContext().getClassScopeSpecializationPattern(this);
-}
-
FunctionTemplateSpecializationInfo *
FunctionDecl::getTemplateSpecializationInfo() const {
return TemplateOrSpecialization
@@ -3537,15 +3529,19 @@ FunctionDecl::setFunctionTemplateSpecialization(ASTContext &C,
TemplateSpecializationKind TSK,
const TemplateArgumentListInfo *TemplateArgsAsWritten,
SourceLocation PointOfInstantiation) {
+ assert((TemplateOrSpecialization.isNull() ||
+ TemplateOrSpecialization.is<MemberSpecializationInfo *>()) &&
+ "Member function is already a specialization");
assert(TSK != TSK_Undeclared &&
"Must specify the type of function template specialization");
- FunctionTemplateSpecializationInfo *Info
- = TemplateOrSpecialization.dyn_cast<FunctionTemplateSpecializationInfo*>();
- if (!Info)
- Info = FunctionTemplateSpecializationInfo::Create(C, this, Template, TSK,
- TemplateArgs,
- TemplateArgsAsWritten,
- PointOfInstantiation);
+ assert((TemplateOrSpecialization.isNull() ||
+ TSK == TSK_ExplicitSpecialization) &&
+ "Member specialization must be an explicit specialization");
+ FunctionTemplateSpecializationInfo *Info =
+ FunctionTemplateSpecializationInfo::Create(
+ C, this, Template, TSK, TemplateArgs, TemplateArgsAsWritten,
+ PointOfInstantiation,
+ TemplateOrSpecialization.dyn_cast<MemberSpecializationInfo *>());
TemplateOrSpecialization = Info;
Template->addSpecialization(Info, InsertPos);
}
@@ -3596,14 +3592,47 @@ DependentFunctionTemplateSpecializationInfo(const UnresolvedSetImpl &Ts,
TemplateSpecializationKind FunctionDecl::getTemplateSpecializationKind() const {
// For a function template specialization, query the specialization
// information object.
- FunctionTemplateSpecializationInfo *FTSInfo
- = TemplateOrSpecialization.dyn_cast<FunctionTemplateSpecializationInfo*>();
- if (FTSInfo)
+ if (FunctionTemplateSpecializationInfo *FTSInfo =
+ TemplateOrSpecialization
+ .dyn_cast<FunctionTemplateSpecializationInfo *>())
+ return FTSInfo->getTemplateSpecializationKind();
+
+ if (MemberSpecializationInfo *MSInfo =
+ TemplateOrSpecialization.dyn_cast<MemberSpecializationInfo *>())
+ return MSInfo->getTemplateSpecializationKind();
+
+ return TSK_Undeclared;
+}
+
+TemplateSpecializationKind
+FunctionDecl::getTemplateSpecializationKindForInstantiation() const {
+ // This is the same as getTemplateSpecializationKind(), except that for a
+ // function that is both a function template specialization and a member
+ // specialization, we prefer the member specialization information. Eg:
+ //
+ // template<typename T> struct A {
+ // template<typename U> void f() {}
+ // template<> void f<int>() {}
+ // };
+ //
+ // For A<int>::f<int>():
+ // * getTemplateSpecializationKind() will return TSK_ExplicitSpecialization
+ // * getTemplateSpecializationKindForInstantiation() will return
+ // TSK_ImplicitInstantiation
+ //
+ // This reflects the facts that A<int>::f<int> is an explicit specialization
+ // of A<int>::f, and that A<int>::f<int> should be implicitly instantiated
+ // from A::f<int> if a definition is needed.
+ if (FunctionTemplateSpecializationInfo *FTSInfo =
+ TemplateOrSpecialization
+ .dyn_cast<FunctionTemplateSpecializationInfo *>()) {
+ if (auto *MSInfo = FTSInfo->getMemberSpecializationInfo())
+ return MSInfo->getTemplateSpecializationKind();
return FTSInfo->getTemplateSpecializationKind();
+ }
- MemberSpecializationInfo *MSInfo
- = TemplateOrSpecialization.dyn_cast<MemberSpecializationInfo*>();
- if (MSInfo)
+ if (MemberSpecializationInfo *MSInfo =
+ TemplateOrSpecialization.dyn_cast<MemberSpecializationInfo *>())
return MSInfo->getTemplateSpecializationKind();
return TSK_Undeclared;
OpenPOWER on IntegriCloud