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 | |
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')
-rw-r--r-- | clang/lib/AST/ASTContext.cpp | 21 | ||||
-rw-r--r-- | clang/lib/AST/Decl.cpp | 119 | ||||
-rw-r--r-- | clang/lib/AST/DeclTemplate.cpp | 22 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 3 | ||||
-rw-r--r-- | clang/lib/Sema/SemaTemplateInstantiate.cpp | 5 | ||||
-rw-r--r-- | clang/lib/Sema/SemaTemplateInstantiateDecl.cpp | 72 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTReaderDecl.cpp | 26 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTWriterDecl.cpp | 13 |
8 files changed, 149 insertions, 132 deletions
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index ad76e529bde..d0a790cad4d 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -1381,24 +1381,6 @@ ASTContext::setTemplateOrSpecializationInfo(VarDecl *Inst, TemplateOrInstantiation[Inst] = TSI; } -FunctionDecl *ASTContext::getClassScopeSpecializationPattern( - const FunctionDecl *FD){ - assert(FD && "Specialization is 0"); - llvm::DenseMap<const FunctionDecl*, FunctionDecl *>::const_iterator Pos - = ClassScopeSpecializationPattern.find(FD); - if (Pos == ClassScopeSpecializationPattern.end()) - return nullptr; - - return Pos->second; -} - -void ASTContext::setClassScopeSpecializationPattern(FunctionDecl *FD, - FunctionDecl *Pattern) { - assert(FD && "Specialization is 0"); - assert(Pattern && "Class scope specialization pattern is 0"); - ClassScopeSpecializationPattern[FD] = Pattern; -} - NamedDecl * ASTContext::getInstantiatedFromUsingDecl(NamedDecl *UUD) { auto Pos = InstantiatedFromUsingDecl.find(UUD); @@ -10033,8 +10015,7 @@ size_t ASTContext::getSideTableAllocatedMemory() const { llvm::capacity_in_bytes(InstantiatedFromUnnamedFieldDecl) + llvm::capacity_in_bytes(OverriddenMethods) + llvm::capacity_in_bytes(Types) + - llvm::capacity_in_bytes(VariableArrayTypes) + - llvm::capacity_in_bytes(ClassScopeSpecializationPattern); + llvm::capacity_in_bytes(VariableArrayTypes); } /// getIntTypeForBitwidth - 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; diff --git a/clang/lib/AST/DeclTemplate.cpp b/clang/lib/AST/DeclTemplate.cpp index 592258d3ffb..3c4cf72f7f5 100644 --- a/clang/lib/AST/DeclTemplate.cpp +++ b/clang/lib/AST/DeclTemplate.cpp @@ -687,22 +687,20 @@ TemplateArgumentList::CreateCopy(ASTContext &Context, return new (Mem) TemplateArgumentList(Args); } -FunctionTemplateSpecializationInfo * -FunctionTemplateSpecializationInfo::Create(ASTContext &C, FunctionDecl *FD, - FunctionTemplateDecl *Template, - TemplateSpecializationKind TSK, - const TemplateArgumentList *TemplateArgs, - const TemplateArgumentListInfo *TemplateArgsAsWritten, - SourceLocation POI) { +FunctionTemplateSpecializationInfo *FunctionTemplateSpecializationInfo::Create( + ASTContext &C, FunctionDecl *FD, FunctionTemplateDecl *Template, + TemplateSpecializationKind TSK, const TemplateArgumentList *TemplateArgs, + const TemplateArgumentListInfo *TemplateArgsAsWritten, SourceLocation POI, + MemberSpecializationInfo *MSInfo) { const ASTTemplateArgumentListInfo *ArgsAsWritten = nullptr; if (TemplateArgsAsWritten) ArgsAsWritten = ASTTemplateArgumentListInfo::Create(C, *TemplateArgsAsWritten); - return new (C) FunctionTemplateSpecializationInfo(FD, Template, TSK, - TemplateArgs, - ArgsAsWritten, - POI); + void *Mem = + C.Allocate(totalSizeToAlloc<MemberSpecializationInfo *>(MSInfo ? 1 : 0)); + return new (Mem) FunctionTemplateSpecializationInfo( + FD, Template, TSK, TemplateArgs, ArgsAsWritten, POI, MSInfo); } //===----------------------------------------------------------------------===// @@ -935,7 +933,7 @@ ClassScopeFunctionSpecializationDecl * ClassScopeFunctionSpecializationDecl::CreateDeserialized(ASTContext &C, unsigned ID) { return new (C, ID) ClassScopeFunctionSpecializationDecl( - nullptr, SourceLocation(), nullptr, false, TemplateArgumentListInfo()); + nullptr, SourceLocation(), nullptr, nullptr); } //===----------------------------------------------------------------------===// diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index e64eeecb2a4..9564c8f0cbd 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -14859,7 +14859,8 @@ void Sema::MarkFunctionReferenced(SourceLocation Loc, FunctionDecl *Func, // Implicit instantiation of function templates and member functions of // class templates. if (Func->isImplicitlyInstantiable()) { - TemplateSpecializationKind TSK = Func->getTemplateSpecializationKind(); + TemplateSpecializationKind TSK = + Func->getTemplateSpecializationKindForInstantiation(); SourceLocation PointOfInstantiation = Func->getPointOfInstantiation(); bool FirstInstantiation = PointOfInstantiation.isInvalid(); if (FirstInstantiation) { diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp index 03822e2c782..af56ff06ac4 100644 --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -133,9 +133,8 @@ Sema::getTemplateInstantiationArgs(NamedDecl *D, // Add template arguments from a function template specialization. else if (FunctionDecl *Function = dyn_cast<FunctionDecl>(Ctx)) { if (!RelativeToPrimary && - (Function->getTemplateSpecializationKind() == - TSK_ExplicitSpecialization && - !Function->getClassScopeSpecializationPattern())) + Function->getTemplateSpecializationKindForInstantiation() == + TSK_ExplicitSpecialization) break; if (const TemplateArgumentList *TemplateArgs diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index 531defdf232..90ae8989c16 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -1951,10 +1951,10 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D, return Function; } -Decl * -TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D, - TemplateParameterList *TemplateParams, - bool IsClassScopeSpecialization) { +Decl *TemplateDeclInstantiator::VisitCXXMethodDecl( + CXXMethodDecl *D, TemplateParameterList *TemplateParams, + Optional<const ASTTemplateArgumentListInfo *> + ClassScopeSpecializationArgs) { FunctionTemplateDecl *FunctionTemplate = D->getDescribedFunctionTemplate(); if (FunctionTemplate && !TemplateParams) { // We are creating a function template specialization from a function @@ -2158,7 +2158,8 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D, IsExplicitSpecialization = true; } else if (const ASTTemplateArgumentListInfo *Info = - D->getTemplateSpecializationArgsAsWritten()) { + ClassScopeSpecializationArgs.getValueOr( + D->getTemplateSpecializationArgsAsWritten())) { SemaRef.LookupQualifiedName(Previous, DC); TemplateArgumentListInfo ExplicitArgs(Info->getLAngleLoc(), @@ -2173,6 +2174,14 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D, Method->setInvalidDecl(); IsExplicitSpecialization = true; + } else if (ClassScopeSpecializationArgs) { + // Class-scope explicit specialization written without explicit template + // arguments. + SemaRef.LookupQualifiedName(Previous, DC); + if (SemaRef.CheckFunctionTemplateSpecialization(Method, nullptr, Previous)) + Method->setInvalidDecl(); + + IsExplicitSpecialization = true; } else if (!FunctionTemplate || TemplateParams || isFriend) { SemaRef.LookupQualifiedName(Previous, Record); @@ -2184,9 +2193,8 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D, Previous.clear(); } - if (!IsClassScopeSpecialization) - SemaRef.CheckFunctionDeclaration(nullptr, Method, Previous, - IsExplicitSpecialization); + SemaRef.CheckFunctionDeclaration(nullptr, Method, Previous, + IsExplicitSpecialization); if (D->isPure()) SemaRef.CheckPureMethod(Method, SourceRange()); @@ -2209,6 +2217,12 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D, if (D->isDeletedAsWritten()) SemaRef.SetDeclDeleted(Method, Method->getLocation()); + // If this is an explicit specialization, mark the implicitly-instantiated + // template specialization as being an explicit specialization too. + // FIXME: Is this necessary? + if (IsExplicitSpecialization && !isFriend) + SemaRef.CompleteMemberSpecialization(Method, Previous); + // If there's a function template, let our caller handle it. if (FunctionTemplate) { // do nothing @@ -2229,7 +2243,7 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D, // Otherwise, add the declaration. We don't need to do this for // class-scope specializations because we'll have matched them with // the appropriate template. - } else if (!IsClassScopeSpecialization) { + } else { Owner->addDecl(Method); } @@ -2839,38 +2853,8 @@ Decl *TemplateDeclInstantiator::VisitUsingPackDecl(UsingPackDecl *D) { Decl *TemplateDeclInstantiator::VisitClassScopeFunctionSpecializationDecl( ClassScopeFunctionSpecializationDecl *Decl) { CXXMethodDecl *OldFD = Decl->getSpecialization(); - CXXMethodDecl *NewFD = - cast_or_null<CXXMethodDecl>(VisitCXXMethodDecl(OldFD, nullptr, true)); - if (!NewFD) - return nullptr; - - TemplateArgumentListInfo ExplicitTemplateArgs; - TemplateArgumentListInfo *ExplicitTemplateArgsPtr = nullptr; - if (Decl->hasExplicitTemplateArgs()) { - if (SemaRef.Subst(Decl->templateArgs().getArgumentArray(), - Decl->templateArgs().size(), ExplicitTemplateArgs, - TemplateArgs)) - return nullptr; - ExplicitTemplateArgsPtr = &ExplicitTemplateArgs; - } - - LookupResult Previous(SemaRef, NewFD->getNameInfo(), Sema::LookupOrdinaryName, - Sema::ForExternalRedeclaration); - SemaRef.LookupQualifiedName(Previous, SemaRef.CurContext); - if (SemaRef.CheckFunctionTemplateSpecialization( - NewFD, ExplicitTemplateArgsPtr, Previous)) { - NewFD->setInvalidDecl(); - return NewFD; - } - - // Associate the specialization with the pattern. - FunctionDecl *Specialization = cast<FunctionDecl>(Previous.getFoundDecl()); - assert(Specialization && "Class scope Specialization is null"); - SemaRef.Context.setClassScopeSpecializationPattern(Specialization, OldFD); - - // FIXME: If this is a definition, check for redefinition errors! - - return NewFD; + return cast_or_null<CXXMethodDecl>( + VisitCXXMethodDecl(OldFD, nullptr, Decl->getTemplateArgsAsWritten())); } Decl *TemplateDeclInstantiator::VisitOMPThreadPrivateDecl( @@ -4068,9 +4052,9 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation, // Never instantiate an explicit specialization except if it is a class scope // explicit specialization. - TemplateSpecializationKind TSK = Function->getTemplateSpecializationKind(); - if (TSK == TSK_ExplicitSpecialization && - !Function->getClassScopeSpecializationPattern()) + TemplateSpecializationKind TSK = + Function->getTemplateSpecializationKindForInstantiation(); + if (TSK == TSK_ExplicitSpecialization) return; // Find the function body that we'll be substituting. diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp index 32bd82d077e..ffe0e8bd74e 100644 --- a/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/clang/lib/Serialization/ASTReaderDecl.cpp @@ -928,12 +928,22 @@ void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) { TemplateArgumentListInfo TemplArgsInfo(LAngleLoc, RAngleLoc); for (unsigned i = 0, e = TemplArgLocs.size(); i != e; ++i) TemplArgsInfo.addArgument(TemplArgLocs[i]); - FunctionTemplateSpecializationInfo *FTInfo - = FunctionTemplateSpecializationInfo::Create(C, FD, Template, TSK, - TemplArgList, - HasTemplateArgumentsAsWritten ? &TemplArgsInfo - : nullptr, - POI); + + MemberSpecializationInfo *MSInfo = nullptr; + if (Record.readInt()) { + auto *FD = ReadDeclAs<FunctionDecl>(); + auto TSK = (TemplateSpecializationKind)Record.readInt(); + SourceLocation POI = ReadSourceLocation(); + + MSInfo = new (C) MemberSpecializationInfo(FD, TSK); + MSInfo->setPointOfInstantiation(POI); + } + + FunctionTemplateSpecializationInfo *FTInfo = + FunctionTemplateSpecializationInfo::Create( + C, FD, Template, TSK, TemplArgList, + HasTemplateArgumentsAsWritten ? &TemplArgsInfo : nullptr, POI, + MSInfo); FD->TemplateOrSpecialization = FTInfo; if (FD->isCanonicalDecl()) { // if canonical add to template's set. @@ -956,7 +966,7 @@ void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) { else { assert(Reader.getContext().getLangOpts().Modules && "already deserialized this template specialization"); - mergeRedeclarable(FD, ExistingInfo->Function, Redecl); + mergeRedeclarable(FD, ExistingInfo->getFunction(), Redecl); } } break; @@ -2244,6 +2254,8 @@ void ASTDeclReader::VisitClassScopeFunctionSpecializationDecl( ClassScopeFunctionSpecializationDecl *D) { VisitDecl(D); D->Specialization = ReadDeclAs<CXXMethodDecl>(); + if (Record.readInt()) + D->TemplateArgs = Record.readASTTemplateArgumentListInfo(); } void ASTDeclReader::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) { diff --git a/clang/lib/Serialization/ASTWriterDecl.cpp b/clang/lib/Serialization/ASTWriterDecl.cpp index c08abb805f3..159a76d5efb 100644 --- a/clang/lib/Serialization/ASTWriterDecl.cpp +++ b/clang/lib/Serialization/ASTWriterDecl.cpp @@ -596,6 +596,16 @@ void ASTDeclWriter::VisitFunctionDecl(FunctionDecl *D) { Record.AddSourceLocation(FTSInfo->getPointOfInstantiation()); + if (MemberSpecializationInfo *MemberInfo = + FTSInfo->getMemberSpecializationInfo()) { + Record.push_back(1); + Record.AddDeclRef(MemberInfo->getInstantiatedFrom()); + Record.push_back(MemberInfo->getTemplateSpecializationKind()); + Record.AddSourceLocation(MemberInfo->getPointOfInstantiation()); + } else { + Record.push_back(0); + } + if (D->isCanonicalDecl()) { // Write the template that contains the specializations set. We will // add a FunctionTemplateSpecializationInfo to it when reading. @@ -1555,6 +1565,9 @@ void ASTDeclWriter::VisitClassScopeFunctionSpecializationDecl( ClassScopeFunctionSpecializationDecl *D) { VisitDecl(D); Record.AddDeclRef(D->getSpecialization()); + Record.push_back(D->hasExplicitTemplateArgs()); + if (D->hasExplicitTemplateArgs()) + Record.AddASTTemplateArgumentListInfo(D->getTemplateArgsAsWritten()); Code = serialization::DECL_CLASS_SCOPE_FUNCTION_SPECIALIZATION; } |