diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Frontend/PCHReader.cpp | 21 | ||||
-rw-r--r-- | lib/Frontend/PCHWriter.cpp | 27 | ||||
-rw-r--r-- | lib/Sema/ParseAST.cpp | 4 |
3 files changed, 50 insertions, 2 deletions
diff --git a/lib/Frontend/PCHReader.cpp b/lib/Frontend/PCHReader.cpp index 328ed841ce..f5f6f5d41c 100644 --- a/lib/Frontend/PCHReader.cpp +++ b/lib/Frontend/PCHReader.cpp @@ -12,8 +12,10 @@ //===----------------------------------------------------------------------===// #include "clang/Frontend/PCHReader.h" #include "clang/Frontend/FrontendDiagnostic.h" +#include "clang/AST/ASTConsumer.h" #include "clang/AST/ASTContext.h" #include "clang/AST/Decl.h" +#include "clang/AST/DeclGroup.h" #include "clang/AST/Type.h" #include "clang/Lex/MacroInfo.h" #include "clang/Lex/Preprocessor.h" @@ -663,6 +665,14 @@ PCHReader::PCHReadResult PCHReader::ReadPCHBlock() { } #endif break; + + case pch::EXTERNAL_DEFINITIONS: + if (!ExternalDefinitions.empty()) { + Error("Duplicate EXTERNAL_DEFINITIONS record in PCH file"); + return Failure; + } + ExternalDefinitions.swap(Record); + break; } } @@ -1276,6 +1286,17 @@ bool PCHReader::ReadDeclsVisibleInContext(DeclContext *DC, return false; } +void PCHReader::StartTranslationUnit(ASTConsumer *Consumer) { + if (!Consumer) + return; + + for (unsigned I = 0, N = ExternalDefinitions.size(); I != N; ++I) { + Decl *D = GetDecl(ExternalDefinitions[I]); + DeclGroupRef DG(D); + Consumer->HandleTopLevelDecl(DG); + } +} + void PCHReader::PrintStats() { std::fprintf(stderr, "*** PCH Statistics:\n"); diff --git a/lib/Frontend/PCHWriter.cpp b/lib/Frontend/PCHWriter.cpp index 738e5c1879..c7bfa0b74e 100644 --- a/lib/Frontend/PCHWriter.cpp +++ b/lib/Frontend/PCHWriter.cpp @@ -934,8 +934,29 @@ void PCHWriter::WriteDeclsBlock(ASTContext &Context) { W.Code = (pch::DeclCode)0; W.Visit(D); if (DC) W.VisitDeclContext(DC, LexicalOffset, VisibleOffset); - assert(W.Code && "Visitor did not set record code"); + assert(W.Code && "Unhandled declaration kind while generating PCH"); S.EmitRecord(W.Code, Record); + + // Note external declarations so that we can add them to a record + // in the PCH file later. + if (isa<FileScopeAsmDecl>(D)) + ExternalDefinitions.push_back(ID); + else if (VarDecl *Var = dyn_cast<VarDecl>(D)) { + if (// Non-static file-scope variables with initializers or that + // are tentative definitions. + (Var->isFileVarDecl() && + (Var->getInit() || Var->getStorageClass() == VarDecl::None)) || + // Out-of-line definitions of static data members (C++). + (Var->getDeclContext()->isRecord() && + !Var->getLexicalDeclContext()->isRecord() && + Var->getStorageClass() == VarDecl::Static)) + ExternalDefinitions.push_back(ID); + } else if (FunctionDecl *Func = dyn_cast<FunctionDecl>(D)) { + if (Func->isThisDeclarationADefinition() && + Func->getStorageClass() != FunctionDecl::Static && + !Func->isInline()) + ExternalDefinitions.push_back(ID); + } } // Exit the declarations block @@ -1013,9 +1034,11 @@ void PCHWriter::WritePCH(ASTContext &Context, const Preprocessor &PP) { WritePreprocessor(PP); WriteTypesBlock(Context); WriteDeclsBlock(Context); + WriteIdentifierTable(); S.EmitRecord(pch::TYPE_OFFSET, TypeOffsets); S.EmitRecord(pch::DECL_OFFSET, DeclOffsets); - WriteIdentifierTable(); + if (!ExternalDefinitions.empty()) + S.EmitRecord(pch::EXTERNAL_DEFINITIONS, ExternalDefinitions); S.ExitBlock(); } diff --git a/lib/Sema/ParseAST.cpp b/lib/Sema/ParseAST.cpp index 4bcb478e89..bb5acb0ee8 100644 --- a/lib/Sema/ParseAST.cpp +++ b/lib/Sema/ParseAST.cpp @@ -14,6 +14,7 @@ #include <llvm/ADT/OwningPtr.h> #include "clang/Sema/ParseAST.h" #include "clang/AST/ASTConsumer.h" +#include "clang/AST/ExternalASTSource.h" #include "clang/AST/Stmt.h" #include "Sema.h" #include "clang/Parse/Parser.h" @@ -44,6 +45,9 @@ void clang::ParseAST(Preprocessor &PP, ASTConsumer *Consumer, Consumer->Initialize(Ctx); + if (Ctx.getExternalSource()) + Ctx.getExternalSource()->StartTranslationUnit(Consumer); + Parser::DeclGroupPtrTy ADecl; while (!P.ParseTopLevelDecl(ADecl)) { // Not end of file. |