/// 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;
/// 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;
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),
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();
}
Stream.ExitBlock();
+ DoneWritingDeclsAndTypes = true;
+
WriteFileDeclIDsMap();
WriteSourceManagerBlock(Context.getSourceManager(), PP, isysroot);
WriteComments();
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++);
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++;
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) {
--- /dev/null
+// 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