diff --git a/clang/include/clang/Serialization/ASTReader.h b/clang/include/clang/Serialization/ASTReader.h index ecb550e26b53..69a012cd17be 100644 --- a/clang/include/clang/Serialization/ASTReader.h +++ b/clang/include/clang/Serialization/ASTReader.h @@ -833,6 +833,21 @@ private: /// \brief Keeps track of the elements added to PendingDeclChains. llvm::SmallSet<serialization::DeclID, 16> PendingDeclChainsKnown; + /// \brief The Decl IDs for the Sema/Lexical DeclContext of a Decl that has + /// been loaded but its DeclContext was not set yet. + struct PendingDeclContextInfo { + Decl *D; + serialization::GlobalDeclID SemaDC; + serialization::GlobalDeclID LexicalDC; + }; + + /// \brief The set of Decls that have been loaded but their DeclContexts are + /// not set yet. + /// + /// The DeclContexts for these Decls will be set once recursive loading has + /// been completed. + std::deque<PendingDeclContextInfo> PendingDeclContextInfos; + /// \brief The set of Objective-C categories that have been deserialized /// since the last time the declaration chains were linked. llvm::SmallPtrSet<ObjCCategoryDecl *, 16> CategoriesDeserialized; @@ -1076,6 +1091,14 @@ private: void finishPendingActions(); + void addPendingDeclContextInfo(Decl *D, + serialization::GlobalDeclID SemaDC, + serialization::GlobalDeclID LexicalDC) { + assert(D); + PendingDeclContextInfo Info = { D, SemaDC, LexicalDC }; + PendingDeclContextInfos.push_back(Info); + } + /// \brief Produce an error diagnostic and return true. /// /// This routine should only be used for fatal errors that have to diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index 6f0dcaae3043..ee558dce08d6 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -6986,7 +6986,7 @@ void ASTReader::ReadComments() { void ASTReader::finishPendingActions() { while (!PendingIdentifierInfos.empty() || !PendingDeclChains.empty() || - !PendingMacroIDs.empty()) { + !PendingMacroIDs.empty() || !PendingDeclContextInfos.empty()) { // If any identifiers with corresponding top-level declarations have // been loaded, load those declarations now. while (!PendingIdentifierInfos.empty()) { @@ -7013,6 +7013,16 @@ void ASTReader::finishPendingActions() { } } PendingMacroIDs.clear(); + + // Wire up the DeclContexts for Decls that we delayed setting until + // recursive loading is completed. + while (!PendingDeclContextInfos.empty()) { + PendingDeclContextInfo Info = PendingDeclContextInfos.front(); + PendingDeclContextInfos.pop_front(); + DeclContext *SemaDC = cast<DeclContext>(GetDecl(Info.SemaDC)); + DeclContext *LexicalDC = cast<DeclContext>(GetDecl(Info.LexicalDC)); + Info.D->setDeclContextsImpl(SemaDC, LexicalDC, getContext()); + } } // If we deserialized any C++ or Objective-C class definitions, any diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp index 64b33b066b07..ea549396f3e9 100644 --- a/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/clang/lib/Serialization/ASTReaderDecl.cpp @@ -44,9 +44,6 @@ namespace clang { unsigned &Idx; TypeID TypeIDForTypeDecl; - DeclID DeclContextIDForTemplateParmDecl; - DeclID LexicalDeclContextIDForTemplateParmDecl; - bool HasPendingBody; uint64_t GetCurrentCursorOffset(); @@ -329,14 +326,6 @@ void ASTDeclReader::Visit(Decl *D) { Reader.PendingBodies[FD] = GetCurrentCursorOffset(); HasPendingBody = true; } - } else if (D->isTemplateParameter()) { - // If we have a fully initialized template parameter, we can now - // set its DeclContext. - DeclContext *SemaDC = cast<DeclContext>( - Reader.GetDecl(DeclContextIDForTemplateParmDecl)); - DeclContext *LexicalDC = cast<DeclContext>( - Reader.GetDecl(LexicalDeclContextIDForTemplateParmDecl)); - D->setDeclContextsImpl(SemaDC, LexicalDC, Reader.getContext()); } } @@ -346,8 +335,11 @@ void ASTDeclReader::VisitDecl(Decl *D) { // parameter immediately, because the template parameter might be // used in the formulation of its DeclContext. Use the translation // unit DeclContext as a placeholder. - DeclContextIDForTemplateParmDecl = ReadDeclID(Record, Idx); - LexicalDeclContextIDForTemplateParmDecl = ReadDeclID(Record, Idx); + GlobalDeclID SemaDCIDForTemplateParmDecl = ReadDeclID(Record, Idx); + GlobalDeclID LexicalDCIDForTemplateParmDecl = ReadDeclID(Record, Idx); + Reader.addPendingDeclContextInfo(D, + SemaDCIDForTemplateParmDecl, + LexicalDCIDForTemplateParmDecl); D->setDeclContext(Reader.getContext().getTranslationUnitDecl()); } else { DeclContext *SemaDC = ReadDeclAs<DeclContext>(Record, Idx); diff --git a/clang/test/PCH/cxx-templates.cpp b/clang/test/PCH/cxx-templates.cpp index d27e9ca93c43..ddebae4df24a 100644 --- a/clang/test/PCH/cxx-templates.cpp +++ b/clang/test/PCH/cxx-templates.cpp @@ -79,3 +79,9 @@ namespace TestNestedExpansion { Int &g(Int, int, double); Int &test = NestedExpansion<char, char, char>().f(0, 1, 2, Int(3), 4, 5.0); } + +namespace rdar13135282 { + void test() { + __mt_alloc<> mt = __mt_alloc<>(); + } +} diff --git a/clang/test/PCH/cxx-templates.h b/clang/test/PCH/cxx-templates.h index 756f208b76fd..3dda05902644 100644 --- a/clang/test/PCH/cxx-templates.h +++ b/clang/test/PCH/cxx-templates.h @@ -220,3 +220,29 @@ template<typename...A> struct NestedExpansion { template<typename...B> auto f(A...a, B...b) -> decltype(g(a + b...)); }; template struct NestedExpansion<char, char, char>; + +namespace rdar13135282 { +template < typename _Alloc > +void foo(_Alloc = _Alloc()); + +template < bool > class __pool; + +template < template < bool > class _PoolTp > +struct __common_pool { + typedef _PoolTp < 0 > pool_type; +}; + +template < template < bool > class _PoolTp > +struct __common_pool_base : __common_pool < _PoolTp > {}; + +template < template < bool > class _PoolTp > +struct A : __common_pool_base < _PoolTp > {}; + +template < typename _Poolp = A < __pool > > +struct __mt_alloc { + typedef typename _Poolp::pool_type __pool_type; + __mt_alloc() { + foo<__mt_alloc<> >(); + } +}; +}