diff --git a/clang/lib/Frontend/CompilerInstance.cpp b/clang/lib/Frontend/CompilerInstance.cpp --- a/clang/lib/Frontend/CompilerInstance.cpp +++ b/clang/lib/Frontend/CompilerInstance.cpp @@ -757,6 +757,8 @@ // Output Files void CompilerInstance::clearOutputFiles(bool EraseFiles) { + // The ASTConsumer can own streams that write to the output files. + assert(!hasASTConsumer() && "ASTConsumer should be reset"); // Ignore errors that occur when trying to discard the temp file. for (OutputFile &OF : OutputFiles) { if (EraseFiles) { @@ -1235,8 +1237,7 @@ // Execute the action to actually build the module in-place. Use a separate // thread so that we get a stack large enough. - llvm::CrashRecoveryContext CRC; - CRC.RunSafelyOnThread( + bool Crashed = !llvm::CrashRecoveryContext().RunSafelyOnThread( [&]() { GenerateModuleFromModuleMapAction Action; Instance.ExecuteAction(Action); @@ -1249,9 +1250,15 @@ diag::remark_module_build_done) << ModuleName; - // Delete any remaining temporary files related to Instance, in case the - // module generation thread crashed. - Instance.clearOutputFiles(/*EraseFiles=*/true); + if (Crashed) { + // Clear the ASTConsumer if it hasn't been already, in case it owns streams + // that must be closed before clearing output files. + Instance.setSema(nullptr); + Instance.setASTConsumer(nullptr); + + // Delete any remaining temporary files related to Instance. + Instance.clearOutputFiles(/*EraseFiles=*/true); + } // If \p AllowPCMWithCompilerErrors is set return 'success' even if errors // occurred. diff --git a/clang/lib/Frontend/FrontendAction.cpp b/clang/lib/Frontend/FrontendAction.cpp --- a/clang/lib/Frontend/FrontendAction.cpp +++ b/clang/lib/Frontend/FrontendAction.cpp @@ -581,6 +581,7 @@ auto FailureCleanup = llvm::make_scope_exit([&]() { if (HasBegunSourceFile) CI.getDiagnosticClient().EndSourceFile(); + CI.setASTConsumer(nullptr); CI.clearOutputFiles(/*EraseFiles=*/true); CI.getLangOpts().setCompilingModule(LangOptions::CMK_None); setCurrentInput(FrontendInputFile());