diff options
-rw-r--r-- | include/clang/Serialization/ASTWriter.h | 8 | ||||
-rw-r--r-- | lib/Serialization/ASTReader.cpp | 2 | ||||
-rw-r--r-- | lib/Serialization/ASTWriter.cpp | 26 | ||||
-rw-r--r-- | test/PCH/chain-staticvar-instantiation.cpp | 44 |
4 files changed, 78 insertions, 2 deletions
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<const DeclContext *, 16> UpdatedDeclContexts; + /// \brief Keeps track of visible decls that were added in DeclContexts + /// coming from another AST file. + SmallVector<const Decl *, 16> UpdatingVisibleDecls; + typedef llvm::SmallPtrSet<const Decl *, 16> 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<uint64_t>(NS)); } } - + + // Make sure visible decls, added to DeclContexts previously loaded from + // an AST file, are registered for serialization. + for (SmallVector<const Decl *, 16>::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<uintptr_t>(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 <class _Tp, _Tp __v> +struct TS +{ + static const _Tp value = __v; +}; + +template <class _Tp, _Tp __v> +const _Tp TS<_Tp, __v>::value; + +TS<int, 2> g1; + +} + +//===----------------------------------------------------------------------===// +#elif not defined(HEADER2) +#define HEADER2 +#if !defined(HEADER1) +#error Header inclusion order messed up +#endif + +int g2 = NS::TS<int, 2>::value; + +//===----------------------------------------------------------------------===// +#else +//===----------------------------------------------------------------------===// + +#warning reached main file // expected-warning {{reached main file}} + +int g3 = NS::TS<int, 2>::value; + +//===----------------------------------------------------------------------===// +#endif |