Skip to content

Commit

Permalink
[Frontend] Add flag to allow PCM generation despite compiler errors
Browse files Browse the repository at this point in the history
As with precompiled headers, it's useful for indexers to be able to
continue through compiler errors in dependent modules.

Resolves rdar://69816264

Reviewed By: akyrtzi

Differential Revision: https://reviews.llvm.org/D91580
  • Loading branch information
bnbarham authored and akyrtzi committed Nov 18, 2020
1 parent f4c6080 commit 5834996
Show file tree
Hide file tree
Showing 13 changed files with 62 additions and 10 deletions.
2 changes: 2 additions & 0 deletions clang/include/clang/Driver/Options.td
Expand Up @@ -4356,6 +4356,8 @@ def fno_validate_pch : Flag<["-"], "fno-validate-pch">,
HelpText<"Disable validation of precompiled headers">;
def fallow_pch_with_errors : Flag<["-"], "fallow-pch-with-compiler-errors">,
HelpText<"Accept a PCH file that was created with compiler errors">;
def fallow_pcm_with_errors : Flag<["-"], "fallow-pcm-with-compiler-errors">,
HelpText<"Accept a PCM file that was created with compiler errors">;
def dump_deserialized_pch_decls : Flag<["-"], "dump-deserialized-decls">,
HelpText<"Dump declarations that are deserialized from PCH, for testing">;
def error_on_deserialized_pch_decl : Separate<["-"], "error-on-deserialized-decl">,
Expand Down
2 changes: 1 addition & 1 deletion clang/include/clang/Frontend/ASTUnit.h
Expand Up @@ -694,7 +694,7 @@ class ASTUnit {
const FileSystemOptions &FileSystemOpts, bool UseDebugInfo = false,
bool OnlyLocalDecls = false, ArrayRef<RemappedFile> RemappedFiles = None,
CaptureDiagsKind CaptureDiagnostics = CaptureDiagsKind::None,
bool AllowPCHWithCompilerErrors = false,
bool AllowASTWithCompilerErrors = false,
bool UserFilesAreVolatile = false);

private:
Expand Down
2 changes: 2 additions & 0 deletions clang/include/clang/Frontend/FrontendActions.h
Expand Up @@ -117,6 +117,8 @@ class GenerateModuleAction : public ASTFrontendAction {
}

bool hasASTFileSupport() const override { return false; }

bool shouldEraseOutputFiles() override;
};

class GenerateInterfaceStubsAction : public ASTFrontendAction {
Expand Down
6 changes: 5 additions & 1 deletion clang/include/clang/Frontend/FrontendOptions.h
Expand Up @@ -303,6 +303,9 @@ class FrontendOptions {
/// When using -emit-module, treat the modulemap as a system module.
unsigned IsSystemModule : 1;

/// Output (and read) PCM files regardless of compiler errors.
unsigned AllowPCMWithCompilerErrors : 1;

CodeCompleteOptions CodeCompleteOpts;

/// Specifies the output format of the AST.
Expand Down Expand Up @@ -457,7 +460,8 @@ class FrontendOptions {
UseGlobalModuleIndex(true), GenerateGlobalModuleIndex(true),
ASTDumpDecls(false), ASTDumpLookups(false),
BuildingImplicitModule(false), ModulesEmbedAllFiles(false),
IncludeTimestamps(true), UseTemporary(true), TimeTraceGranularity(500) {}
IncludeTimestamps(true), UseTemporary(true),
AllowPCMWithCompilerErrors(false), TimeTraceGranularity(500) {}

/// getInputKindForExtension - Return the appropriate input kind for a file
/// extension. For example, "c" would return Language::C.
Expand Down
4 changes: 2 additions & 2 deletions clang/lib/Frontend/ASTUnit.cpp
Expand Up @@ -759,7 +759,7 @@ std::unique_ptr<ASTUnit> ASTUnit::LoadFromASTFile(
WhatToLoad ToLoad, IntrusiveRefCntPtr<DiagnosticsEngine> Diags,
const FileSystemOptions &FileSystemOpts, bool UseDebugInfo,
bool OnlyLocalDecls, ArrayRef<RemappedFile> RemappedFiles,
CaptureDiagsKind CaptureDiagnostics, bool AllowPCHWithCompilerErrors,
CaptureDiagsKind CaptureDiagnostics, bool AllowASTWithCompilerErrors,
bool UserFilesAreVolatile) {
std::unique_ptr<ASTUnit> AST(new ASTUnit(true));

Expand Down Expand Up @@ -819,7 +819,7 @@ std::unique_ptr<ASTUnit> ASTUnit::LoadFromASTFile(
AST->Reader = new ASTReader(
PP, *AST->ModuleCache, AST->Ctx.get(), PCHContainerRdr, {},
/*isysroot=*/"",
/*DisableValidation=*/disableValid, AllowPCHWithCompilerErrors);
/*DisableValidation=*/disableValid, AllowASTWithCompilerErrors);

AST->Reader->setListener(std::make_unique<ASTInfoCollector>(
*AST->PP, AST->Ctx.get(), *AST->HSOpts, *AST->PPOpts, *AST->LangOpts,
Expand Down
4 changes: 3 additions & 1 deletion clang/lib/Frontend/CompilerInstance.cpp
Expand Up @@ -1523,7 +1523,9 @@ void CompilerInstance::createASTReader() {
HeaderSearchOptions &HSOpts = getHeaderSearchOpts();
std::string Sysroot = HSOpts.Sysroot;
const PreprocessorOptions &PPOpts = getPreprocessorOpts();
const FrontendOptions &FEOpts = getFrontendOpts();
std::unique_ptr<llvm::Timer> ReadTimer;

if (FrontendTimerGroup)
ReadTimer = std::make_unique<llvm::Timer>("reading_modules",
"Reading modules",
Expand All @@ -1532,7 +1534,7 @@ void CompilerInstance::createASTReader() {
getPreprocessor(), getModuleCache(), &getASTContext(),
getPCHContainerReader(), getFrontendOpts().ModuleFileExtensions,
Sysroot.empty() ? "" : Sysroot.c_str(), PPOpts.DisablePCHValidation,
/*AllowASTWithCompilerErrors=*/false,
/*AllowASTWithCompilerErrors=*/FEOpts.AllowPCMWithCompilerErrors,
/*AllowConfigurationMismatch=*/false, HSOpts.ModulesValidateSystemHeaders,
HSOpts.ValidateASTInputFilesContent,
getFrontendOpts().UseGlobalModuleIndex, std::move(ReadTimer));
Expand Down
4 changes: 3 additions & 1 deletion clang/lib/Frontend/CompilerInvocation.cpp
Expand Up @@ -2027,6 +2027,7 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args,
Opts.IncludeTimestamps = !Args.hasArg(OPT_fno_pch_timestamp);
Opts.UseTemporary = !Args.hasArg(OPT_fno_temp_file);
Opts.IsSystemModule = Args.hasArg(OPT_fsystem_module);
Opts.AllowPCMWithCompilerErrors = Args.hasArg(OPT_fallow_pcm_with_errors);

if (Opts.ProgramAction != frontend::GenerateModule && Opts.IsSystemModule)
Diags.Report(diag::err_drv_argument_only_allowed_with) << "-fsystem-module"
Expand Down Expand Up @@ -3611,7 +3612,8 @@ static void ParsePreprocessorArgs(PreprocessorOptions &Opts, ArgList &Args,
Opts.UsePredefines = !Args.hasArg(OPT_undef);
Opts.DetailedRecord = Args.hasArg(OPT_detailed_preprocessing_record);
Opts.DisablePCHValidation = Args.hasArg(OPT_fno_validate_pch);
Opts.AllowPCHWithCompilerErrors = Args.hasArg(OPT_fallow_pch_with_errors);
Opts.AllowPCHWithCompilerErrors =
Args.hasArg(OPT_fallow_pch_with_errors, OPT_fallow_pcm_with_errors);

Opts.DumpDeserializedPCHDecls = Args.hasArg(OPT_dump_deserialized_pch_decls);
for (const auto *A : Args.filtered(OPT_error_on_deserialized_pch_decl))
Expand Down
10 changes: 8 additions & 2 deletions clang/lib/Frontend/FrontendActions.cpp
Expand Up @@ -177,7 +177,8 @@ GenerateModuleAction::CreateASTConsumer(CompilerInstance &CI,
Consumers.push_back(std::make_unique<PCHGenerator>(
CI.getPreprocessor(), CI.getModuleCache(), OutputFile, Sysroot, Buffer,
CI.getFrontendOpts().ModuleFileExtensions,
/*AllowASTWithErrors=*/false,
/*AllowASTWithErrors=*/
+CI.getFrontendOpts().AllowPCMWithCompilerErrors,
/*IncludeTimestamps=*/
+CI.getFrontendOpts().BuildingImplicitModule,
/*ShouldCacheASTInMemory=*/
Expand All @@ -187,6 +188,11 @@ GenerateModuleAction::CreateASTConsumer(CompilerInstance &CI,
return std::make_unique<MultiplexConsumer>(std::move(Consumers));
}

bool GenerateModuleAction::shouldEraseOutputFiles() {
return !getCompilerInstance().getFrontendOpts().AllowPCMWithCompilerErrors &&
ASTFrontendAction::shouldEraseOutputFiles();
}

bool GenerateModuleFromModuleMapAction::BeginSourceFileAction(
CompilerInstance &CI) {
if (!CI.getLangOpts().Modules) {
Expand Down Expand Up @@ -339,7 +345,7 @@ void VerifyPCHAction::ExecuteAction() {
CI.getPCHContainerReader(), CI.getFrontendOpts().ModuleFileExtensions,
Sysroot.empty() ? "" : Sysroot.c_str(),
/*DisableValidation*/ false,
/*AllowPCHWithCompilerErrors*/ false,
/*AllowASTWithCompilerErrors*/ false,
/*AllowConfigurationMismatch*/ true,
/*ValidateSystemInputs*/ true));

Expand Down
8 changes: 8 additions & 0 deletions clang/test/Modules/Inputs/error.h
@@ -0,0 +1,8 @@
@import undefined

@interface Error
- (int)method;
undefined
@end

undefined
1 change: 1 addition & 0 deletions clang/test/Modules/Inputs/module.map
Expand Up @@ -483,3 +483,4 @@ module template_nontrivial1 {
header "template-nontrivial1.h"
export *
}
module error { header "error.h" }
25 changes: 25 additions & 0 deletions clang/test/Modules/load-module-with-errors.m
@@ -0,0 +1,25 @@
// RUN: rm -rf %t
// RUN: mkdir %t

// Write out a module with errors make sure it can be read
// RUN: %clang_cc1 -fmodules -fallow-pcm-with-compiler-errors \
// RUN: -fmodules-cache-path=%t -x objective-c -emit-module \
// RUN: -fmodule-name=error %S/Inputs/module.map
// RUN: %clang_cc1 -fmodules -fallow-pcm-with-compiler-errors \
// RUN: -fmodules-cache-path=%t -x objective-c -I %S/Inputs \
// RUN: -fimplicit-module-maps -ast-print %s | FileCheck %s

// allow-pcm-with-compiler-errors should also allow errors in PCH
// RUN: %clang_cc1 -fallow-pcm-with-compiler-errors -x c++ -emit-pch \
// RUN: -o %t/check.pch %S/Inputs/error.h

@import error;

void test(id x) {
[x method];
}

// CHECK: @interface Error
// CHECK-NEXT: - (int)method;
// CHECK-NEXT: @end
// CHECK: void test(id x)
2 changes: 1 addition & 1 deletion clang/tools/c-index-test/core_main.cpp
Expand Up @@ -263,7 +263,7 @@ static bool printSourceSymbolsFromModule(StringRef modulePath,
std::string(modulePath), *pchRdr, ASTUnit::LoadASTOnly, Diags,
FileSystemOpts, /*UseDebugInfo=*/false,
/*OnlyLocalDecls=*/true, None, CaptureDiagsKind::None,
/*AllowPCHWithCompilerErrors=*/true,
/*AllowASTWithCompilerErrors=*/true,
/*UserFilesAreVolatile=*/false);
if (!AU) {
errs() << "failed to create TU for: " << modulePath << '\n';
Expand Down
2 changes: 1 addition & 1 deletion clang/tools/libclang/CIndex.cpp
Expand Up @@ -3476,7 +3476,7 @@ enum CXErrorCode clang_createTranslationUnit2(CXIndex CIdx,
ast_filename, CXXIdx->getPCHContainerOperations()->getRawReader(),
ASTUnit::LoadEverything, Diags, FileSystemOpts, /*UseDebugInfo=*/false,
CXXIdx->getOnlyLocalDecls(), None, CaptureDiagsKind::All,
/*AllowPCHWithCompilerErrors=*/true,
/*AllowASTWithCompilerErrors=*/true,
/*UserFilesAreVolatile=*/true);
*out_TU = MakeCXTranslationUnit(CXXIdx, std::move(AU));
return *out_TU ? CXError_Success : CXError_Failure;
Expand Down

0 comments on commit 5834996

Please sign in to comment.