From: Douglas Gregor Date: Fri, 30 Apr 2010 05:56:50 +0000 (+0000) Subject: Introduce a sequence number into class template partial X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=dc60c1eb4acbde6edcec9760de92f9098593d915;p=clang Introduce a sequence number into class template partial specializations, which keeps track of the order in which they were originally declared. We use this number so that we can always walk the list of partial specializations in a predictable order during matching or template instantiation. This also fixes a failure in Boost.Proto, where SourceManager::isBeforeInTranslationUnit was behaving poorly in inconsistent ways. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@102693 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/AST/DeclTemplate.h b/include/clang/AST/DeclTemplate.h index 2bb971d814..1ec38bacb5 100644 --- a/include/clang/AST/DeclTemplate.h +++ b/include/clang/AST/DeclTemplate.h @@ -1011,6 +1011,11 @@ class ClassTemplatePartialSpecializationDecl TemplateArgumentLoc *ArgsAsWritten; unsigned NumArgsAsWritten; + /// \brief Sequence number indicating when this class template partial + /// specialization was added to the set of partial specializations for + /// its owning class template. + unsigned SequenceNumber; + /// \brief The class template partial specialization from which this /// class template partial specialization was instantiated. /// @@ -1026,13 +1031,15 @@ class ClassTemplatePartialSpecializationDecl TemplateArgumentListBuilder &Builder, TemplateArgumentLoc *ArgInfos, unsigned NumArgInfos, - ClassTemplatePartialSpecializationDecl *PrevDecl) + ClassTemplatePartialSpecializationDecl *PrevDecl, + unsigned SequenceNumber) : ClassTemplateSpecializationDecl(Context, ClassTemplatePartialSpecialization, DC, L, SpecializedTemplate, Builder, PrevDecl), TemplateParams(Params), ArgsAsWritten(ArgInfos), - NumArgsAsWritten(NumArgInfos), InstantiatedFromMember(0, false) { } + NumArgsAsWritten(NumArgInfos), SequenceNumber(SequenceNumber), + InstantiatedFromMember(0, false) { } public: static ClassTemplatePartialSpecializationDecl * @@ -1042,7 +1049,8 @@ public: TemplateArgumentListBuilder &Builder, const TemplateArgumentListInfo &ArgInfos, QualType CanonInjectedType, - ClassTemplatePartialSpecializationDecl *PrevDecl); + ClassTemplatePartialSpecializationDecl *PrevDecl, + unsigned SequenceNumber); /// Get the list of template parameters TemplateParameterList *getTemplateParameters() const { @@ -1059,6 +1067,10 @@ public: return NumArgsAsWritten; } + /// \brief Get the sequence number for this class template partial + /// specialization. + unsigned getSequenceNumber() const { return SequenceNumber; } + /// \brief Retrieve the member class template partial specialization from /// which this particular class template partial specialization was /// instantiated. @@ -1226,6 +1238,10 @@ public: return CommonPtr->PartialSpecializations; } + /// \brief Retrieve the partial specializations as an ordered list. + void getPartialSpecializations( + llvm::SmallVectorImpl &PS); + /// \brief Find a class template partial specialization with the given /// type T. /// diff --git a/lib/AST/DeclTemplate.cpp b/lib/AST/DeclTemplate.cpp index e3d30a0b27..c498dea177 100644 --- a/lib/AST/DeclTemplate.cpp +++ b/lib/AST/DeclTemplate.cpp @@ -178,6 +178,20 @@ void ClassTemplateDecl::Destroy(ASTContext& C) { C.Deallocate((void*)this); } +void ClassTemplateDecl::getPartialSpecializations( + llvm::SmallVectorImpl &PS) { + llvm::FoldingSet &PartialSpecs + = CommonPtr->PartialSpecializations; + PS.clear(); + PS.resize(PartialSpecs.size()); + for (llvm::FoldingSet::iterator + P = PartialSpecs.begin(), PEnd = PartialSpecs.end(); + P != PEnd; ++P) { + assert(!PS[P->getSequenceNumber()]); + PS[P->getSequenceNumber()] = &*P; + } +} + ClassTemplatePartialSpecializationDecl * ClassTemplateDecl::findPartialSpecialization(QualType T) { ASTContext &Context = getASTContext(); @@ -456,7 +470,8 @@ Create(ASTContext &Context, DeclContext *DC, SourceLocation L, TemplateArgumentListBuilder &Builder, const TemplateArgumentListInfo &ArgInfos, QualType CanonInjectedType, - ClassTemplatePartialSpecializationDecl *PrevDecl) { + ClassTemplatePartialSpecializationDecl *PrevDecl, + unsigned SequenceNumber) { unsigned N = ArgInfos.size(); TemplateArgumentLoc *ClonedArgs = new (Context) TemplateArgumentLoc[N]; for (unsigned I = 0; I != N; ++I) @@ -468,7 +483,8 @@ Create(ASTContext &Context, DeclContext *DC, SourceLocation L, SpecializedTemplate, Builder, ClonedArgs, N, - PrevDecl); + PrevDecl, + SequenceNumber); Result->setSpecializationKind(TSK_ExplicitSpecialization); Context.getInjectedClassNameType(Result, CanonInjectedType); diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index 70a92ca2e7..a84ceab2eb 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -3781,6 +3781,8 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, // Create a new class template partial specialization declaration node. ClassTemplatePartialSpecializationDecl *PrevPartial = cast_or_null(PrevDecl); + unsigned SequenceNumber = PrevPartial? PrevPartial->getSequenceNumber() + : ClassTemplate->getPartialSpecializations().size(); ClassTemplatePartialSpecializationDecl *Partial = ClassTemplatePartialSpecializationDecl::Create(Context, ClassTemplate->getDeclContext(), @@ -3790,7 +3792,8 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, Converted, TemplateArgs, CanonType, - PrevPartial); + PrevPartial, + SequenceNumber); SetNestedNameSpecifier(Partial, SS); if (PrevPartial) { diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp index 7dee0ad99b..a75a80b83d 100644 --- a/lib/Sema/SemaTemplateInstantiate.cpp +++ b/lib/Sema/SemaTemplateInstantiate.cpp @@ -1278,21 +1278,20 @@ Sema::InstantiateClassTemplateSpecialization( typedef std::pair MatchResult; llvm::SmallVector Matched; - for (llvm::FoldingSet::iterator - Partial = Template->getPartialSpecializations().begin(), - PartialEnd = Template->getPartialSpecializations().end(); - Partial != PartialEnd; - ++Partial) { + llvm::SmallVector PartialSpecs; + Template->getPartialSpecializations(PartialSpecs); + for (unsigned I = 0, N = PartialSpecs.size(); I != N; ++I) { + ClassTemplatePartialSpecializationDecl *Partial = PartialSpecs[I]; TemplateDeductionInfo Info(Context, PointOfInstantiation); if (TemplateDeductionResult Result - = DeduceTemplateArguments(&*Partial, + = DeduceTemplateArguments(Partial, ClassTemplateSpec->getTemplateArgs(), Info)) { // FIXME: Store the failed-deduction information for use in // diagnostics, later. (void)Result; } else { - Matched.push_back(std::make_pair(&*Partial, Info.take())); + Matched.push_back(std::make_pair(Partial, Info.take())); } } diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp index 4575d47329..25ba2829ce 100644 --- a/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -620,21 +620,6 @@ Decl *TemplateDeclInstantiator::VisitEnumConstantDecl(EnumConstantDecl *D) { return 0; } -namespace { - class SortDeclByLocation { - SourceManager &SourceMgr; - - public: - explicit SortDeclByLocation(SourceManager &SourceMgr) - : SourceMgr(SourceMgr) { } - - bool operator()(const Decl *X, const Decl *Y) const { - return SourceMgr.isBeforeInTranslationUnit(X->getLocation(), - Y->getLocation()); - } - }; -} - Decl *TemplateDeclInstantiator::VisitClassTemplateDecl(ClassTemplateDecl *D) { bool isFriend = (D->getFriendObjectKind() != Decl::FOK_None); @@ -791,19 +776,10 @@ Decl *TemplateDeclInstantiator::VisitClassTemplateDecl(ClassTemplateDecl *D) { Owner->addDecl(Inst); - // First, we sort the partial specializations by location, so - // that we instantiate them in the order they were declared. - llvm::SmallVector PartialSpecs; - for (llvm::FoldingSet::iterator - P = D->getPartialSpecializations().begin(), - PEnd = D->getPartialSpecializations().end(); - P != PEnd; ++P) - PartialSpecs.push_back(&*P); - std::sort(PartialSpecs.begin(), PartialSpecs.end(), - SortDeclByLocation(SemaRef.SourceMgr)); - // Instantiate all of the partial specializations of this member class // template. + llvm::SmallVector PartialSpecs; + D->getPartialSpecializations(PartialSpecs); for (unsigned I = 0, N = PartialSpecs.size(); I != N; ++I) InstantiateClassTemplatePartialSpecialization(Inst, PartialSpecs[I]); @@ -1768,7 +1744,8 @@ TemplateDeclInstantiator::InstantiateClassTemplatePartialSpecialization( Converted, InstTemplateArgs, CanonType, - 0); + 0, + ClassTemplate->getPartialSpecializations().size()); // Substitute the nested name specifier, if any. if (SubstQualifier(PartialSpec, InstPartialSpec)) return 0;