summaryrefslogtreecommitdiffstats
path: root/clang/lib/Frontend/FrontendAction.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Frontend/FrontendAction.cpp')
-rw-r--r--clang/lib/Frontend/FrontendAction.cpp78
1 files changed, 63 insertions, 15 deletions
diff --git a/clang/lib/Frontend/FrontendAction.cpp b/clang/lib/Frontend/FrontendAction.cpp
index e2fbe965349..ef98172b55b 100644
--- a/clang/lib/Frontend/FrontendAction.cpp
+++ b/clang/lib/Frontend/FrontendAction.cpp
@@ -387,8 +387,7 @@ static std::error_code collectModuleHeaderIncludes(
return std::error_code();
}
-static bool loadModuleMapForModuleBuild(CompilerInstance &CI,
- StringRef Filename, bool IsSystem,
+static bool loadModuleMapForModuleBuild(CompilerInstance &CI, bool IsSystem,
bool IsPreprocessed,
std::string &PresumedModuleMapFile,
unsigned &Offset) {
@@ -523,7 +522,8 @@ getInputBufferForModule(CompilerInstance &CI, Module *M) {
}
bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
- const FrontendInputFile &Input) {
+ const FrontendInputFile &RealInput) {
+ FrontendInputFile Input(RealInput);
assert(!Instance && "Already processing a source file!");
assert(!Input.isEmpty() && "Unexpected empty filename!");
setCurrentInput(Input);
@@ -531,15 +531,69 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
StringRef InputFile = Input.getFile();
bool HasBegunSourceFile = false;
+ bool ReplayASTFile = Input.getKind().getFormat() == InputKind::Precompiled &&
+ usesPreprocessorOnly();
if (!BeginInvocation(CI))
goto failure;
+ // If we're replaying the build of an AST file, import it and set up
+ // the initial state from its build.
+ if (ReplayASTFile) {
+ IntrusiveRefCntPtr<DiagnosticsEngine> Diags(&CI.getDiagnostics());
+
+ // The AST unit populates its own diagnostics engine rather than ours.
+ IntrusiveRefCntPtr<DiagnosticsEngine> ASTDiags(
+ new DiagnosticsEngine(Diags->getDiagnosticIDs(),
+ &Diags->getDiagnosticOptions()));
+ ASTDiags->setClient(Diags->getClient(), /*OwnsClient*/false);
+
+ std::unique_ptr<ASTUnit> AST = ASTUnit::LoadFromASTFile(
+ InputFile, CI.getPCHContainerReader(), ASTDiags, CI.getFileSystemOpts(),
+ CI.getCodeGenOpts().DebugTypeExtRefs);
+ if (!AST)
+ goto failure;
+
+ // Options relating to how we treat the input (but not what we do with it)
+ // are inherited from the AST unit.
+ CI.getLangOpts() = AST->getLangOpts();
+
+ // Preload all the module files loaded transitively by the AST unit.
+ if (auto ASTReader = AST->getASTReader()) {
+ auto &MM = ASTReader->getModuleManager();
+ for (ModuleFile &MF : MM)
+ if (&MF != &MM.getPrimaryModule())
+ CI.getFrontendOpts().ModuleFiles.push_back(MF.FileName);
+ }
+
+ // Set the shared objects, these are reset when we finish processing the
+ // file, otherwise the CompilerInstance will happily destroy them.
+ CI.setFileManager(&AST->getFileManager());
+ CI.createSourceManager(CI.getFileManager());
+ CI.getSourceManager().initializeForReplay(AST->getSourceManager());
+ CI.createPreprocessor(getTranslationUnitKind());
+
+ // Set up the input file for replay purposes.
+ auto Kind = AST->getInputKind();
+ if (Kind.getFormat() == InputKind::ModuleMap) {
+ Module *ASTModule =
+ AST->getPreprocessor().getHeaderSearchInfo().lookupModule(
+ AST->getLangOpts().CurrentModule, /*AllowSearch*/ false);
+ Input = FrontendInputFile(ASTModule->PresumedModuleMapFile, Kind);
+ } else {
+ auto &SM = CI.getSourceManager();
+ FileID ID = SM.getMainFileID();
+ if (auto *File = SM.getFileEntryForID(ID))
+ Input = FrontendInputFile(File->getName(), Kind);
+ else
+ Input = FrontendInputFile(SM.getBuffer(ID), Kind);
+ }
+ setCurrentInput(Input, std::move(AST));
+ }
+
// AST files follow a very different path, since they share objects via the
// AST unit.
if (Input.getKind().getFormat() == InputKind::Precompiled) {
- // FIXME: We should not be asserting on bad command-line arguments.
- assert(!usesPreprocessorOnly() &&
- "Attempt to pass AST file to preprocessor only action!");
+ assert(!usesPreprocessorOnly() && "this case was handled above");
assert(hasASTFileSupport() &&
"This action does not have AST file support!");
@@ -680,7 +734,7 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
std::string PresumedModuleMapFile;
unsigned OffsetToContents;
- if (loadModuleMapForModuleBuild(CI, Input.getFile(), Input.isSystem(),
+ if (loadModuleMapForModuleBuild(CI, Input.isSystem(),
Input.isPreprocessed(),
PresumedModuleMapFile, OffsetToContents))
goto failure;
@@ -829,14 +883,7 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
// If we failed, reset state since the client will not end up calling the
// matching EndSourceFile().
- failure:
- if (isCurrentFileAST()) {
- CI.setASTContext(nullptr);
- CI.setPreprocessor(nullptr);
- CI.setSourceManager(nullptr);
- CI.setFileManager(nullptr);
- }
-
+failure:
if (HasBegunSourceFile)
CI.getDiagnosticClient().EndSourceFile();
CI.clearOutputFiles(/*EraseFiles=*/true);
@@ -914,6 +961,7 @@ void FrontendAction::EndSourceFile() {
CI.resetAndLeakPreprocessor();
CI.resetAndLeakSourceManager();
CI.resetAndLeakFileManager();
+ BuryPointer(CurrentASTUnit.release());
} else {
CI.setPreprocessor(nullptr);
CI.setSourceManager(nullptr);
OpenPOWER on IntegriCloud