diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2019-05-02 00:49:14 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2019-05-02 00:49:14 +0000 |
commit | f19a8b05171a67a290e7d3bd6eba0c95c7b3259c (patch) | |
tree | cdee1c4c3c58d6211745af9959e9cb595fa2be20 /clang/lib/AST/Decl.cpp | |
parent | bac77806c588125db314a04dbec0c416e7fec901 (diff) | |
download | bcm5719-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.cpp | 119 |
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; |