diff options
-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 |