diff options
| author | Duncan P. N. Exon Smith <dexonsmith@apple.com> | 2019-03-12 18:38:04 +0000 |
|---|---|---|
| committer | Duncan P. N. Exon Smith <dexonsmith@apple.com> | 2019-03-12 18:38:04 +0000 |
| commit | 70d759b4eb958505a6893f2a64a0c1f613c95c2e (patch) | |
| tree | 832d1e83afc38045e014cc317839ad3466fc9710 /clang | |
| parent | 4ab0a9f0a4e7daff3fc54fd48d429c6c2017a458 (diff) | |
| download | bcm5719-llvm-70d759b4eb958505a6893f2a64a0c1f613c95c2e.tar.gz bcm5719-llvm-70d759b4eb958505a6893f2a64a0c1f613c95c2e.zip | |
Modules: Add LangOptions::CacheGeneratedPCH
Add an option to cache the generated PCH in the ModuleCache when
emitting it. This protects clients that build PCHs and read them in the
same process, allowing them to avoid race conditions between parallel
jobs the same way that Clang's implicit module build system does.
rdar://problem/48740787
llvm-svn: 355950
Diffstat (limited to 'clang')
| -rw-r--r-- | clang/include/clang/Basic/LangOptions.def | 1 | ||||
| -rw-r--r-- | clang/include/clang/Serialization/ASTWriter.h | 7 | ||||
| -rw-r--r-- | clang/lib/Frontend/FrontendActions.cpp | 4 | ||||
| -rw-r--r-- | clang/lib/Serialization/ASTWriter.cpp | 5 | ||||
| -rw-r--r-- | clang/lib/Serialization/GeneratePCH.cpp | 9 | ||||
| -rw-r--r-- | clang/unittests/Frontend/FrontendActionTest.cpp | 40 |
6 files changed, 57 insertions, 9 deletions
diff --git a/clang/include/clang/Basic/LangOptions.def b/clang/include/clang/Basic/LangOptions.def index 7b2ab7a66fa..8a35f4ed21d 100644 --- a/clang/include/clang/Basic/LangOptions.def +++ b/clang/include/clang/Basic/LangOptions.def @@ -154,6 +154,7 @@ BENIGN_ENUM_LANGOPT(CompilingModule, CompilingModuleKind, 2, CMK_None, "compiling a module interface") BENIGN_LANGOPT(CompilingPCH, 1, 0, "building a pch") BENIGN_LANGOPT(BuildingPCHWithObjectFile, 1, 0, "building a pch which has a corresponding object file") +BENIGN_LANGOPT(CacheGeneratedPCH, 1, 0, "cache generated PCH files in memory") COMPATIBLE_LANGOPT(ModulesDeclUse , 1, 0, "require declaration of module uses") BENIGN_LANGOPT(ModulesSearchAll , 1, 1, "searching even non-imported modules to find unresolved references") COMPATIBLE_LANGOPT(ModulesStrictDeclUse, 1, 0, "requiring declaration of module uses and all headers to be in modules") diff --git a/clang/include/clang/Serialization/ASTWriter.h b/clang/include/clang/Serialization/ASTWriter.h index b0f72224700..3e287d9657f 100644 --- a/clang/include/clang/Serialization/ASTWriter.h +++ b/clang/include/clang/Serialization/ASTWriter.h @@ -570,7 +570,8 @@ public: /// the module but currently is merely a random 32-bit number. ASTFileSignature WriteAST(Sema &SemaRef, const std::string &OutputFile, Module *WritingModule, StringRef isysroot, - bool hasErrors = false); + bool hasErrors = false, + bool ShouldCacheASTInMemory = false); /// Emit a token. void AddToken(const Token &Tok, RecordDataImpl &Record); @@ -974,6 +975,7 @@ class PCHGenerator : public SemaConsumer { llvm::BitstreamWriter Stream; ASTWriter Writer; bool AllowASTWithErrors; + bool ShouldCacheASTInMemory; protected: ASTWriter &getWriter() { return Writer; } @@ -985,7 +987,8 @@ public: StringRef OutputFile, StringRef isysroot, std::shared_ptr<PCHBuffer> Buffer, ArrayRef<std::shared_ptr<ModuleFileExtension>> Extensions, - bool AllowASTWithErrors = false, bool IncludeTimestamps = true); + bool AllowASTWithErrors = false, bool IncludeTimestamps = true, + bool ShouldCacheASTInMemory = false); ~PCHGenerator() override; void InitializeSema(Sema &S) override { SemaPtr = &S; } diff --git a/clang/lib/Frontend/FrontendActions.cpp b/clang/lib/Frontend/FrontendActions.cpp index 5ad9a1cc036..9cb2ab2d5ee 100644 --- a/clang/lib/Frontend/FrontendActions.cpp +++ b/clang/lib/Frontend/FrontendActions.cpp @@ -112,7 +112,7 @@ GeneratePCHAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) { CI.getPreprocessor(), CI.getModuleCache(), OutputFile, Sysroot, Buffer, FrontendOpts.ModuleFileExtensions, CI.getPreprocessorOpts().AllowPCHWithCompilerErrors, - FrontendOpts.IncludeTimestamps)); + FrontendOpts.IncludeTimestamps, +CI.getLangOpts().CacheGeneratedPCH)); Consumers.push_back(CI.getPCHContainerWriter().CreatePCHContainerGenerator( CI, InFile, OutputFile, std::move(OS), Buffer)); @@ -176,6 +176,8 @@ GenerateModuleAction::CreateASTConsumer(CompilerInstance &CI, CI.getFrontendOpts().ModuleFileExtensions, /*AllowASTWithErrors=*/false, /*IncludeTimestamps=*/ + +CI.getFrontendOpts().BuildingImplicitModule, + /*ShouldCacheASTInMemory=*/ +CI.getFrontendOpts().BuildingImplicitModule)); Consumers.push_back(CI.getPCHContainerWriter().CreatePCHContainerGenerator( CI, InFile, OutputFile, std::move(OS), Buffer)); diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index 85bc2818395..933cc6b12c6 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -4596,7 +4596,8 @@ time_t ASTWriter::getTimestampForOutput(const FileEntry *E) const { ASTFileSignature ASTWriter::WriteAST(Sema &SemaRef, const std::string &OutputFile, Module *WritingModule, StringRef isysroot, - bool hasErrors) { + bool hasErrors, + bool ShouldCacheASTInMemory) { WritingAST = true; ASTHasCompilerErrors = hasErrors; @@ -4620,7 +4621,7 @@ ASTFileSignature ASTWriter::WriteAST(Sema &SemaRef, this->BaseDirectory.clear(); WritingAST = false; - if (SemaRef.Context.getLangOpts().ImplicitModules && WritingModule) { + if (ShouldCacheASTInMemory) { // Construct MemoryBuffer and update buffer manager. ModuleCache.addBuiltPCM(OutputFile, llvm::MemoryBuffer::getMemBufferCopy( diff --git a/clang/lib/Serialization/GeneratePCH.cpp b/clang/lib/Serialization/GeneratePCH.cpp index 7c2ef5a13a1..6d98524636f 100644 --- a/clang/lib/Serialization/GeneratePCH.cpp +++ b/clang/lib/Serialization/GeneratePCH.cpp @@ -24,12 +24,14 @@ PCHGenerator::PCHGenerator( const Preprocessor &PP, InMemoryModuleCache &ModuleCache, StringRef OutputFile, StringRef isysroot, std::shared_ptr<PCHBuffer> Buffer, ArrayRef<std::shared_ptr<ModuleFileExtension>> Extensions, - bool AllowASTWithErrors, bool IncludeTimestamps) + bool AllowASTWithErrors, bool IncludeTimestamps, + bool ShouldCacheASTInMemory) : PP(PP), OutputFile(OutputFile), isysroot(isysroot.str()), SemaPtr(nullptr), Buffer(std::move(Buffer)), Stream(this->Buffer->Data), Writer(Stream, this->Buffer->Data, ModuleCache, Extensions, IncludeTimestamps), - AllowASTWithErrors(AllowASTWithErrors) { + AllowASTWithErrors(AllowASTWithErrors), + ShouldCacheASTInMemory(ShouldCacheASTInMemory) { this->Buffer->IsComplete = false; } @@ -61,7 +63,8 @@ void PCHGenerator::HandleTranslationUnit(ASTContext &Ctx) { Writer.WriteAST(*SemaPtr, OutputFile, Module, isysroot, // For serialization we are lenient if the errors were // only warn-as-error kind. - PP.getDiagnostics().hasUncompilableErrorOccurred()); + PP.getDiagnostics().hasUncompilableErrorOccurred(), + ShouldCacheASTInMemory); Buffer->IsComplete = true; } diff --git a/clang/unittests/Frontend/FrontendActionTest.cpp b/clang/unittests/Frontend/FrontendActionTest.cpp index 0203fe4ce2b..20356c6d833 100644 --- a/clang/unittests/Frontend/FrontendActionTest.cpp +++ b/clang/unittests/Frontend/FrontendActionTest.cpp @@ -6,18 +6,20 @@ // //===----------------------------------------------------------------------===// +#include "clang/Frontend/FrontendAction.h" #include "clang/AST/ASTConsumer.h" #include "clang/AST/ASTContext.h" #include "clang/AST/RecursiveASTVisitor.h" #include "clang/Frontend/CompilerInstance.h" #include "clang/Frontend/CompilerInvocation.h" -#include "clang/Frontend/FrontendAction.h" #include "clang/Frontend/FrontendActions.h" #include "clang/Lex/Preprocessor.h" #include "clang/Lex/PreprocessorOptions.h" #include "clang/Sema/Sema.h" +#include "clang/Serialization/InMemoryModuleCache.h" #include "llvm/ADT/Triple.h" #include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/ToolOutputFile.h" #include "gtest/gtest.h" using namespace llvm; @@ -253,4 +255,40 @@ TEST(ASTFrontendAction, ExternalSemaSource) { EXPECT_EQ("This is a note", TDC->Note.str().str()); } +TEST(GeneratePCHFrontendAction, CacheGeneratedPCH) { + // Create a temporary file for writing out the PCH that will be cleaned up. + int PCHFD; + llvm::SmallString<128> PCHFilename; + ASSERT_FALSE( + llvm::sys::fs::createTemporaryFile("test.h", "pch", PCHFD, PCHFilename)); + llvm::ToolOutputFile PCHFile(PCHFilename, PCHFD); + + for (bool ShouldCache : {false, true}) { + auto Invocation = std::make_shared<CompilerInvocation>(); + Invocation->getLangOpts()->CacheGeneratedPCH = ShouldCache; + Invocation->getPreprocessorOpts().addRemappedFile( + "test.h", + MemoryBuffer::getMemBuffer("int foo(void) { return 1; }\n").release()); + Invocation->getFrontendOpts().Inputs.push_back( + FrontendInputFile("test.h", InputKind::C)); + Invocation->getFrontendOpts().OutputFile = StringRef(PCHFilename); + Invocation->getFrontendOpts().ProgramAction = frontend::GeneratePCH; + Invocation->getTargetOpts().Triple = "x86_64-apple-darwin19.0.0"; + CompilerInstance Compiler; + Compiler.setInvocation(std::move(Invocation)); + Compiler.createDiagnostics(); + + GeneratePCHAction TestAction; + ASSERT_TRUE(Compiler.ExecuteAction(TestAction)); + + // Check whether the PCH was cached. + if (ShouldCache) + EXPECT_EQ(InMemoryModuleCache::Final, + Compiler.getModuleCache().getPCMState(PCHFilename)); + else + EXPECT_EQ(InMemoryModuleCache::Unknown, + Compiler.getModuleCache().getPCMState(PCHFilename)); + } +} + } // anonymous namespace |

