From 7518b3784ed2176aad8dcabe0685c6e02c5f1043 Mon Sep 17 00:00:00 2001 From: Argyrios Kyrtzidis Date: Mon, 2 Jul 2012 19:19:01 +0000 Subject: [PATCH] [PCH] Make sure that all newly introduced visible decls in a DeclContext coming from an AST file are registered for serialization. A static data member instantiation of in a chained PCH could be missed when serializing decls; the result was that when emitting the visible decls map of its DeclContext, we would use a DeclID that was not actually emitted, leading to crashes or hangs. Fix this by making sure such decls are always registered for serialization. Also introduce extra sanity checks to make sure we don't register new declarations or types after we have serialized the types/decls block. rdar://11728990 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@159550 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Serialization/ASTWriter.h | 8 ++++ lib/Serialization/ASTReader.cpp | 2 + lib/Serialization/ASTWriter.cpp | 26 ++++++++++++- test/PCH/chain-staticvar-instantiation.cpp | 44 ++++++++++++++++++++++ 4 files changed, 78 insertions(+), 2 deletions(-) create mode 100644 test/PCH/chain-staticvar-instantiation.cpp diff --git a/include/clang/Serialization/ASTWriter.h b/include/clang/Serialization/ASTWriter.h index 472b407992..830a163eed 100644 --- a/include/clang/Serialization/ASTWriter.h +++ b/include/clang/Serialization/ASTWriter.h @@ -110,6 +110,10 @@ private: /// serialization, rather than just queueing updates. bool WritingAST; + /// \brief Indicates that we are done serializing the collection of decls + /// and types to emit. + bool DoneWritingDeclsAndTypes; + /// \brief Indicates that the AST contained compiler errors. bool ASTHasCompilerErrors; @@ -296,6 +300,10 @@ private: /// it. llvm::SmallPtrSet UpdatedDeclContexts; + /// \brief Keeps track of visible decls that were added in DeclContexts + /// coming from another AST file. + SmallVector UpdatingVisibleDecls; + typedef llvm::SmallPtrSet DeclsToRewriteTy; /// \brief Decls that will be replaced in the current dependent AST file. DeclsToRewriteTy DeclsToRewrite; diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp index b118685b9b..3d643f6b43 100644 --- a/lib/Serialization/ASTReader.cpp +++ b/lib/Serialization/ASTReader.cpp @@ -4673,7 +4673,9 @@ Decl *ASTReader::GetDecl(DeclID ID) { unsigned Index = ID - NUM_PREDEF_DECL_IDS; if (Index >= DeclsLoaded.size()) { + assert(0 && "declaration ID out-of-range for AST file"); Error("declaration ID out-of-range for AST file"); + return 0; } if (!DeclsLoaded[Index]) { diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp index 17fef95b6f..8ab1737472 100644 --- a/lib/Serialization/ASTWriter.cpp +++ b/lib/Serialization/ASTWriter.cpp @@ -3140,7 +3140,8 @@ void ASTWriter::SetSelectorOffset(Selector Sel, uint32_t Offset) { ASTWriter::ASTWriter(llvm::BitstreamWriter &Stream) : Stream(Stream), Context(0), PP(0), Chain(0), WritingModule(0), - WritingAST(false), ASTHasCompilerErrors(false), + WritingAST(false), DoneWritingDeclsAndTypes(false), + ASTHasCompilerErrors(false), FirstDeclID(NUM_PREDEF_DECL_IDS), NextDeclID(FirstDeclID), FirstTypeID(NUM_PREDEF_TYPE_IDS), NextTypeID(FirstTypeID), FirstIdentID(NUM_PREDEF_IDENT_IDS), NextIdentID(FirstIdentID), @@ -3400,7 +3401,15 @@ void ASTWriter::WriteASTCore(Sema &SemaRef, MemorizeStatCalls *StatCalls, Record.push_back(reinterpret_cast(NS)); } } - + + // Make sure visible decls, added to DeclContexts previously loaded from + // an AST file, are registered for serialization. + for (SmallVector::iterator + I = UpdatingVisibleDecls.begin(), + E = UpdatingVisibleDecls.end(); I != E; ++I) { + GetDeclRef(*I); + } + // Resolve any declaration pointers within the declaration updates block. ResolveDeclUpdatesBlocks(); @@ -3433,6 +3442,8 @@ void ASTWriter::WriteASTCore(Sema &SemaRef, MemorizeStatCalls *StatCalls, } Stream.ExitBlock(); + DoneWritingDeclsAndTypes = true; + WriteFileDeclIDsMap(); WriteSourceManagerBlock(Context.getSourceManager(), PP, isysroot); WriteComments(); @@ -3819,6 +3830,11 @@ TypeIdx ASTWriter::GetOrCreateTypeIdx(QualType T) { TypeIdx &Idx = TypeIdxs[T]; if (Idx.getIndex() == 0) { + if (DoneWritingDeclsAndTypes) { + assert(0 && "New type seen after serializing all the types to emit!"); + return TypeIdx(); + } + // We haven't seen this type before. Assign it a new ID and put it // into the queue of types to emit. Idx = TypeIdx(NextTypeID++); @@ -3856,6 +3872,11 @@ DeclID ASTWriter::GetDeclRef(const Decl *D) { assert(!(reinterpret_cast(D) & 0x01) && "Invalid decl pointer"); DeclID &ID = DeclIDs[D]; if (ID == 0) { + if (DoneWritingDeclsAndTypes) { + assert(0 && "New decl seen after serializing all the decls to emit!"); + return 0; + } + // We haven't seen this declaration before. Give it a new ID and // enqueue it in the list of declarations to emit. ID = NextDeclID++; @@ -4477,6 +4498,7 @@ void ASTWriter::AddedVisibleDecl(const DeclContext *DC, const Decl *D) { return; // Not a source decl added to a DeclContext from PCH. AddUpdatedDeclContext(DC); + UpdatingVisibleDecls.push_back(D); } void ASTWriter::AddedCXXImplicitMember(const CXXRecordDecl *RD, const Decl *D) { diff --git a/test/PCH/chain-staticvar-instantiation.cpp b/test/PCH/chain-staticvar-instantiation.cpp new file mode 100644 index 0000000000..0ab093f18d --- /dev/null +++ b/test/PCH/chain-staticvar-instantiation.cpp @@ -0,0 +1,44 @@ +// Without PCH +// RUN: %clang_cc1 -fsyntax-only -verify -include %s -include %s %s + +// With PCH +// RUN: %clang_cc1 -fsyntax-only -verify %s -chain-include %s -chain-include %s + +#ifndef HEADER1 +#define HEADER1 +//===----------------------------------------------------------------------===// + +namespace NS { + +template +struct TS +{ + static const _Tp value = __v; +}; + +template +const _Tp TS<_Tp, __v>::value; + +TS g1; + +} + +//===----------------------------------------------------------------------===// +#elif not defined(HEADER2) +#define HEADER2 +#if !defined(HEADER1) +#error Header inclusion order messed up +#endif + +int g2 = NS::TS::value; + +//===----------------------------------------------------------------------===// +#else +//===----------------------------------------------------------------------===// + +#warning reached main file // expected-warning {{reached main file}} + +int g3 = NS::TS::value; + +//===----------------------------------------------------------------------===// +#endif -- 2.40.0