From d964d6380945e0505b623050fe6a3f428008fc2a Mon Sep 17 00:00:00 2001 From: Chandler Carruth Date: Thu, 3 May 2012 23:49:05 +0000 Subject: [PATCH] Fix non-deterministic iteration order when walking the specializations of templates by using the newly introduce FoldingSetVector. This preserves insertion order for all iteration of specializations. I've also included a somewhat terrifying testcase that rapidly builds up a large number of functions. This is enough that any system with ASLR will have non-deterministic debug information generated for the test case without the fix here as the debug information is generated in part by walking these specializations. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@156133 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/DeclTemplate.h | 24 ++++++++++++---------- lib/AST/DeclTemplate.cpp | 15 +++++++------- lib/Serialization/ASTWriterDecl.cpp | 7 ++++--- test/CodeGenCXX/debug-info-determinism.cpp | 16 +++++++++++++++ 4 files changed, 41 insertions(+), 21 deletions(-) create mode 100644 test/CodeGenCXX/debug-info-determinism.cpp diff --git a/include/clang/AST/DeclTemplate.h b/include/clang/AST/DeclTemplate.h index 36549eab38..37628d323d 100644 --- a/include/clang/AST/DeclTemplate.h +++ b/include/clang/AST/DeclTemplate.h @@ -512,7 +512,8 @@ protected: typedef _SETraits SETraits; typedef _DeclType DeclType; - typedef typename llvm::FoldingSet::iterator SetIteratorType; + typedef typename llvm::FoldingSetVector::iterator + SetIteratorType; SetIteratorType SetIter; @@ -541,13 +542,13 @@ protected: }; template - SpecIterator makeSpecIterator(llvm::FoldingSet &Specs, - bool isEnd) { + SpecIterator + makeSpecIterator(llvm::FoldingSetVector &Specs, bool isEnd) { return SpecIterator(isEnd ? Specs.end() : Specs.begin()); } template typename SpecEntryTraits::DeclType* - findSpecializationImpl(llvm::FoldingSet &Specs, + findSpecializationImpl(llvm::FoldingSetVector &Specs, const TemplateArgument *Args, unsigned NumArgs, void *&InsertPos); @@ -706,7 +707,7 @@ protected: /// \brief The function template specializations for this function /// template, including explicit specializations and instantiations. - llvm::FoldingSet Specializations; + llvm::FoldingSetVector Specializations; /// \brief The set of "injected" template arguments used within this /// function template. @@ -732,13 +733,14 @@ protected: /// \brief Retrieve the set of function template specializations of this /// function template. - llvm::FoldingSet &getSpecializations() { + llvm::FoldingSetVector & + getSpecializations() { return getCommonPtr()->Specializations; } /// \brief Add a specialization of this function template. /// - /// \param InsertPos Insert position in the FoldingSet, must have been + /// \param InsertPos Insert position in the FoldingSetVector, must have been /// retrieved by an earlier call to findSpecialization(). void addSpecialization(FunctionTemplateSpecializationInfo* Info, void *InsertPos); @@ -1688,11 +1690,11 @@ protected: /// \brief The class template specializations for this class /// template, including explicit specializations and instantiations. - llvm::FoldingSet Specializations; + llvm::FoldingSetVector Specializations; /// \brief The class template partial specializations for this class /// template. - llvm::FoldingSet + llvm::FoldingSetVector PartialSpecializations; /// \brief The injected-class-name type for this class template. @@ -1710,11 +1712,11 @@ protected: void LoadLazySpecializations(); /// \brief Retrieve the set of specializations of this class template. - llvm::FoldingSet &getSpecializations(); + llvm::FoldingSetVector &getSpecializations(); /// \brief Retrieve the set of partial specializations of this class /// template. - llvm::FoldingSet & + llvm::FoldingSetVector & getPartialSpecializations(); ClassTemplateDecl(DeclContext *DC, SourceLocation L, DeclarationName Name, diff --git a/lib/AST/DeclTemplate.cpp b/lib/AST/DeclTemplate.cpp index 4590195d6b..9a338e5ee6 100644 --- a/lib/AST/DeclTemplate.cpp +++ b/lib/AST/DeclTemplate.cpp @@ -145,7 +145,7 @@ RedeclarableTemplateDecl::CommonBase *RedeclarableTemplateDecl::getCommonPtr() { template typename RedeclarableTemplateDecl::SpecEntryTraits::DeclType* RedeclarableTemplateDecl::findSpecializationImpl( - llvm::FoldingSet &Specs, + llvm::FoldingSetVector &Specs, const TemplateArgument *Args, unsigned NumArgs, void *&InsertPos) { typedef SpecEntryTraits SETraits; @@ -298,13 +298,13 @@ void ClassTemplateDecl::LoadLazySpecializations() { } } -llvm::FoldingSet & +llvm::FoldingSetVector & ClassTemplateDecl::getSpecializations() { LoadLazySpecializations(); return getCommonPtr()->Specializations; } -llvm::FoldingSet & +llvm::FoldingSetVector & ClassTemplateDecl::getPartialSpecializations() { LoadLazySpecializations(); return getCommonPtr()->PartialSpecializations; @@ -363,11 +363,11 @@ void ClassTemplateDecl::AddPartialSpecialization( void ClassTemplateDecl::getPartialSpecializations( SmallVectorImpl &PS) { - llvm::FoldingSet &PartialSpecs + llvm::FoldingSetVector &PartialSpecs = getPartialSpecializations(); PS.clear(); PS.resize(PartialSpecs.size()); - for (llvm::FoldingSet::iterator + for (llvm::FoldingSetVector::iterator P = PartialSpecs.begin(), PEnd = PartialSpecs.end(); P != PEnd; ++P) { assert(!PS[P->getSequenceNumber()]); @@ -378,7 +378,8 @@ void ClassTemplateDecl::getPartialSpecializations( ClassTemplatePartialSpecializationDecl * ClassTemplateDecl::findPartialSpecialization(QualType T) { ASTContext &Context = getASTContext(); - typedef llvm::FoldingSet::iterator + using llvm::FoldingSetVector; + typedef FoldingSetVector::iterator partial_spec_iterator; for (partial_spec_iterator P = getPartialSpecializations().begin(), PEnd = getPartialSpecializations().end(); @@ -394,7 +395,7 @@ ClassTemplatePartialSpecializationDecl * ClassTemplateDecl::findPartialSpecInstantiatedFromMember( ClassTemplatePartialSpecializationDecl *D) { Decl *DCanon = D->getCanonicalDecl(); - for (llvm::FoldingSet::iterator + for (llvm::FoldingSetVector::iterator P = getPartialSpecializations().begin(), PEnd = getPartialSpecializations().end(); P != PEnd; ++P) { diff --git a/lib/Serialization/ASTWriterDecl.cpp b/lib/Serialization/ASTWriterDecl.cpp index 1ee3ac480b..ee30dd8ea9 100644 --- a/lib/Serialization/ASTWriterDecl.cpp +++ b/lib/Serialization/ASTWriterDecl.cpp @@ -1054,7 +1054,7 @@ void ASTDeclWriter::VisitClassTemplateDecl(ClassTemplateDecl *D) { VisitRedeclarableTemplateDecl(D); if (D->isFirstDeclaration()) { - typedef llvm::FoldingSet CTSDSetTy; + typedef llvm::FoldingSetVector CTSDSetTy; CTSDSetTy &CTSDSet = D->getSpecializations(); Record.push_back(CTSDSet.size()); for (CTSDSetTy::iterator I=CTSDSet.begin(), E = CTSDSet.end(); I!=E; ++I) { @@ -1062,7 +1062,8 @@ void ASTDeclWriter::VisitClassTemplateDecl(ClassTemplateDecl *D) { Writer.AddDeclRef(&*I, Record); } - typedef llvm::FoldingSet CTPSDSetTy; + typedef llvm::FoldingSetVector + CTPSDSetTy; CTPSDSetTy &CTPSDSet = D->getPartialSpecializations(); Record.push_back(CTPSDSet.size()); for (CTPSDSetTy::iterator I=CTPSDSet.begin(), E=CTPSDSet.end(); I!=E; ++I) { @@ -1146,7 +1147,7 @@ void ASTDeclWriter::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) { // Write the function specialization declarations. Record.push_back(D->getSpecializations().size()); - for (llvm::FoldingSet::iterator + for (llvm::FoldingSetVector::iterator I = D->getSpecializations().begin(), E = D->getSpecializations().end() ; I != E; ++I) { assert(I->Function->isCanonicalDecl() && diff --git a/test/CodeGenCXX/debug-info-determinism.cpp b/test/CodeGenCXX/debug-info-determinism.cpp new file mode 100644 index 0000000000..a96a14e9ed --- /dev/null +++ b/test/CodeGenCXX/debug-info-determinism.cpp @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -S -emit-llvm -g -o %t1.ll %s +// RUN: %clang_cc1 -S -emit-llvm -g -o %t2.ll %s +// RUN: diff %t1.ll %t2.ll + +template struct C { + template int f() { + int arr[M] = {}; + return arr[M/2] + C().template f(); + } +}; +template <> template <> int C<0>::f<0>() { return 0; } +template <> template <> int C<0>::f<1>() { return 0; } +template <> template <> int C<1>::f<0>() { return 0; } +template <> template <> int C<1>::f<1>() { return 0; } + +int x = C<0>().f<64>(); -- 2.40.0