From 94d48a9d33181fb7a969b3bec502ddbd381b9102 Mon Sep 17 00:00:00 2001 From: Bob Wilson Date: Tue, 22 Apr 2025 10:27:07 -0700 Subject: [PATCH 1/3] [Clang] Fix crash when building a module with CC_PRINT_HEADERS_FORMAT=json (#136227) There is no main file when building a module, so the code in HeaderIncludesJSONCallback::EndOfMainFile() needs to check for that to avoid crashing. --- clang/lib/Frontend/HeaderIncludeGen.cpp | 7 +++++-- clang/test/Preprocessor/print-header-crash.modulemap | 2 ++ 2 files changed, 7 insertions(+), 2 deletions(-) create mode 100644 clang/test/Preprocessor/print-header-crash.modulemap diff --git a/clang/lib/Frontend/HeaderIncludeGen.cpp b/clang/lib/Frontend/HeaderIncludeGen.cpp index 992c2670260e5..792526083b1e6 100644 --- a/clang/lib/Frontend/HeaderIncludeGen.cpp +++ b/clang/lib/Frontend/HeaderIncludeGen.cpp @@ -260,8 +260,11 @@ void HeaderIncludesCallback::FileSkipped(const FileEntryRef &SkippedFile, const void HeaderIncludesJSONCallback::EndOfMainFile() { OptionalFileEntryRef FE = SM.getFileEntryRefForID(SM.getMainFileID()); - SmallString<256> MainFile(FE->getName()); - SM.getFileManager().makeAbsolutePath(MainFile); + SmallString<256> MainFile; + if (FE) { + MainFile += FE->getName(); + SM.getFileManager().makeAbsolutePath(MainFile); + } std::string Str; llvm::raw_string_ostream OS(Str); diff --git a/clang/test/Preprocessor/print-header-crash.modulemap b/clang/test/Preprocessor/print-header-crash.modulemap new file mode 100644 index 0000000000000..5919c70780a95 --- /dev/null +++ b/clang/test/Preprocessor/print-header-crash.modulemap @@ -0,0 +1,2 @@ +// RUN: %clang_cc1 -header-include-format=json -header-include-filtering=only-direct-system -header-include-file %t.txt -emit-module -x c -fmodules -fmodule-name=X %s -o /dev/null +module X {} From d065be049b3697f025de884cfb22520d100fb5cf Mon Sep 17 00:00:00 2001 From: Bob Wilson Date: Wed, 23 Apr 2025 16:09:38 -0700 Subject: [PATCH 2/3] [Clang] Fix crash when -header-include-filtering is not specified (#136232) If you specify -header-include-format=json, the only filtering option currently supported is -header-include-filtering=only-direct-system. If you specify some other filtering option, Clang gives an error message. But, if you do not specify the filtering option at all, Clang crashes when producing the error message, since it tries to get the value of the unused option. --- .../clang/Basic/DiagnosticDriverKinds.td | 8 +++++- clang/lib/Frontend/CompilerInvocation.cpp | 26 ++++++++++++++----- clang/test/Preprocessor/print-header-json.c | 12 +++++++-- clang/tools/driver/driver.cpp | 5 ++++ 4 files changed, 41 insertions(+), 10 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td b/clang/include/clang/Basic/DiagnosticDriverKinds.td index f0faa876a168c..e0b9e1986e744 100644 --- a/clang/include/clang/Basic/DiagnosticDriverKinds.td +++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td @@ -399,8 +399,14 @@ def err_drv_print_header_env_var : Error< "environment variable CC_PRINT_HEADERS_%select{FORMAT|FILTERING}0 has invalid value %1">; def err_drv_print_header_env_var_combination : Error< "unsupported combination: CC_PRINT_HEADERS_FORMAT=%0 and CC_PRINT_HEADERS_FILTERING=%1">; -def err_drv_print_header_env_var_combination_cc1 : Error< +def err_drv_print_header_env_var_invalid_format : Error< + "environment variable CC_PRINT_HEADERS_FORMAT=%0 requires a compatible value for CC_PRINT_HEADERS_FILTERING">; +def err_drv_print_header_cc1_invalid_combination : Error< "unsupported combination: -header-include-format=%0 and -header-include-filtering=%1">; +def err_drv_print_header_cc1_invalid_filtering : Error< + "-header-include-filtering=%0 requires a compatible value for -header-include-format">; +def err_drv_print_header_cc1_invalid_format : Error< + "-header-include-format=%0 requires a compatible value for -header-include-filtering">; def warn_O4_is_O3 : Warning<"-O4 is equivalent to -O3">, InGroup; def warn_drv_optimization_value : Warning<"optimization level '%0' is not supported; using '%1%2' instead">, diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index 5bd12e4591b36..f81edc527cd84 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -2541,13 +2541,25 @@ static bool ParseDependencyOutputArgs(DependencyOutputOptions &Opts, // Check for invalid combinations of header-include-format // and header-include-filtering. - if ((Opts.HeaderIncludeFormat == HIFMT_Textual && - Opts.HeaderIncludeFiltering != HIFIL_None) || - (Opts.HeaderIncludeFormat == HIFMT_JSON && - Opts.HeaderIncludeFiltering != HIFIL_Only_Direct_System)) - Diags.Report(diag::err_drv_print_header_env_var_combination_cc1) - << Args.getLastArg(OPT_header_include_format_EQ)->getValue() - << Args.getLastArg(OPT_header_include_filtering_EQ)->getValue(); + if (Opts.HeaderIncludeFormat == HIFMT_Textual && + Opts.HeaderIncludeFiltering != HIFIL_None) { + if (Args.hasArg(OPT_header_include_format_EQ)) + Diags.Report(diag::err_drv_print_header_cc1_invalid_combination) + << headerIncludeFormatKindToString(Opts.HeaderIncludeFormat) + << headerIncludeFilteringKindToString(Opts.HeaderIncludeFiltering); + else + Diags.Report(diag::err_drv_print_header_cc1_invalid_filtering) + << headerIncludeFilteringKindToString(Opts.HeaderIncludeFiltering); + } else if (Opts.HeaderIncludeFormat == HIFMT_JSON && + Opts.HeaderIncludeFiltering == HIFIL_None) { + if (Args.hasArg(OPT_header_include_filtering_EQ)) + Diags.Report(diag::err_drv_print_header_cc1_invalid_combination) + << headerIncludeFormatKindToString(Opts.HeaderIncludeFormat) + << headerIncludeFilteringKindToString(Opts.HeaderIncludeFiltering); + else + Diags.Report(diag::err_drv_print_header_cc1_invalid_format) + << headerIncludeFormatKindToString(Opts.HeaderIncludeFormat); + } return Diags.getNumErrors() == NumErrorsBefore; } diff --git a/clang/test/Preprocessor/print-header-json.c b/clang/test/Preprocessor/print-header-json.c index d0d5e6b6f7d9e..1ba63ddc7a249 100644 --- a/clang/test/Preprocessor/print-header-json.c +++ b/clang/test/Preprocessor/print-header-json.c @@ -1,11 +1,16 @@ // RUN: %clang_cc1 -E -header-include-format=json -header-include-filtering=only-direct-system -header-include-file %t.txt -I %S/Inputs/print-header-json -isystem %S/Inputs/print-header-json/system %s // RUN: cat %t.txt | FileCheck %s --check-prefix=SUPPORTED + // RUN: not %clang_cc1 -E -header-include-format=textual -header-include-filtering=only-direct-system -header-include-file %t.txt -I %S/Inputs/print-header-json -isystem %S/Inputs/print-header-json/system %s -o /dev/null 2>&1 | FileCheck %s --check-prefix=UNSUPPORTED0 // RUN: not %clang_cc1 -E -header-include-format=json -header-include-filtering=none -header-include-file %t.txt -I %S/Inputs/print-header-json -isystem %S/Inputs/print-header-json/system %s -o /dev/null 2>&1 | FileCheck %s --check-prefix=UNSUPPORTED1 -// RUN: rm %t.txt -// RUN: env CC_PRINT_HEADERS_FORMAT=json CC_PRINT_HEADERS_FILTERING=only-direct-system CC_PRINT_HEADERS_FILE=%t.txt %clang -fsyntax-only -I %S/Inputs/print-header-json -isystem %S/Inputs/print-header-json/system %s -o /dev/null // RUN: env CC_PRINT_HEADERS_FORMAT=textual CC_PRINT_HEADERS_FILTERING=only-direct-system CC_PRINT_HEADERS_FILE=%t.txt not %clang -fsyntax-only -I %S/Inputs/print-header-json -isystem %S/Inputs/print-header-json/system %s -o /dev/null 2>&1 | FileCheck %s --check-prefix=UNSUPPORTED2 // RUN: env CC_PRINT_HEADERS_FORMAT=json CC_PRINT_HEADERS_FILTERING=none CC_PRINT_HEADERS_FILE=%t.txt not %clang -fsyntax-only -I %S/Inputs/print-header-json -isystem %S/Inputs/print-header-json/system %s -o /dev/null 2>&1 | FileCheck %s --check-prefix=UNSUPPORTED3 +// RUN: env CC_PRINT_HEADERS_FORMAT=json CC_PRINT_HEADERS_FILE=%t.txt not %clang -fsyntax-only -I %S/Inputs/print-header-json -isystem %S/Inputs/print-header-json/system %s -o /dev/null 2>&1 | FileCheck %s --check-prefix=UNSUPPORTED4 +// RUN: not %clang_cc1 -E -header-include-filtering=only-direct-system -header-include-file %t.txt -I %S/Inputs/print-header-json -isystem %S/Inputs/print-header-json/system %s -o /dev/null 2>&1 | FileCheck %s --check-prefix=UNSUPPORTED5 +// RUN: not %clang_cc1 -E -header-include-format=json -header-include-file %t.txt -I %S/Inputs/print-header-json -isystem %S/Inputs/print-header-json/system %s -o /dev/null 2>&1 | FileCheck %s --check-prefix=UNSUPPORTED6 + +// RUN: rm %t.txt +// RUN: env CC_PRINT_HEADERS_FORMAT=json CC_PRINT_HEADERS_FILTERING=only-direct-system CC_PRINT_HEADERS_FILE=%t.txt %clang -fsyntax-only -I %S/Inputs/print-header-json -isystem %S/Inputs/print-header-json/system %s -o /dev/null // RUN: cat %t.txt | FileCheck %s --check-prefix=SUPPORTED #include "system0.h" @@ -18,3 +23,6 @@ // UNSUPPORTED1: error: unsupported combination: -header-include-format=json and -header-include-filtering=none // UNSUPPORTED2: error: unsupported combination: CC_PRINT_HEADERS_FORMAT=textual and CC_PRINT_HEADERS_FILTERING=only-direct-system // UNSUPPORTED3: error: unsupported combination: CC_PRINT_HEADERS_FORMAT=json and CC_PRINT_HEADERS_FILTERING=none +// UNSUPPORTED4: error: environment variable CC_PRINT_HEADERS_FORMAT=json requires a compatible value for CC_PRINT_HEADERS_FILTERING +// UNSUPPORTED5: error: -header-include-filtering=only-direct-system requires a compatible value for -header-include-format +// UNSUPPORTED6: error: -header-include-format=json requires a compatible value for -header-include-filtering diff --git a/clang/tools/driver/driver.cpp b/clang/tools/driver/driver.cpp index ea48183af6c1e..35f4c1cf66e9d 100644 --- a/clang/tools/driver/driver.cpp +++ b/clang/tools/driver/driver.cpp @@ -167,6 +167,11 @@ static bool SetBackdoorDriverOutputsFromEnvVars(Driver &TheDriver) { } const char *FilteringStr = ::getenv("CC_PRINT_HEADERS_FILTERING"); + if (!FilteringStr) { + TheDriver.Diag(clang::diag::err_drv_print_header_env_var_invalid_format) + << EnvVar; + return false; + } HeaderIncludeFilteringKind Filtering; if (!stringToHeaderIncludeFiltering(FilteringStr, Filtering)) { TheDriver.Diag(clang::diag::err_drv_print_header_env_var) From 849f653eb7eccbbbe8e1c663c4f5b93970d0bbe2 Mon Sep 17 00:00:00 2001 From: Bob Wilson Date: Mon, 28 Apr 2025 21:54:45 -0700 Subject: [PATCH 3/3] [Clang] Add new -header-include-filtering=direct-per-file option (#137087) This adds a new filtering option to be used along with the -header-include-format=json option. The existing "only-direct-system" filtering option is missing some things: - It does not show module imports. - It does not show includes of non-system headers. This new "direct-per-file" filtering has a separate entry in the JSON output for each non-system source file, showing the direct includes and imports from that file. You can use this to see uses of non-system headers, and also find the paths through non-system headers that lead up to module imports and system headers. Modules are identified here by their modulemap files. --- clang/include/clang/Basic/HeaderInclude.h | 13 +- clang/include/clang/Driver/Options.td | 3 +- clang/lib/Frontend/HeaderIncludeGen.cpp | 140 +++++++++++++++++++- clang/test/Preprocessor/print-header-json.c | 5 + clang/tools/driver/driver.cpp | 2 +- 5 files changed, 153 insertions(+), 10 deletions(-) diff --git a/clang/include/clang/Basic/HeaderInclude.h b/clang/include/clang/Basic/HeaderInclude.h index 83c26543bbd3b..86c21cf292882 100644 --- a/clang/include/clang/Basic/HeaderInclude.h +++ b/clang/include/clang/Basic/HeaderInclude.h @@ -23,8 +23,14 @@ enum HeaderIncludeFormatKind { HIFMT_None, HIFMT_Textual, HIFMT_JSON }; /// Whether header information is filtered or not. If HIFIL_Only_Direct_System /// is used, only information on system headers directly included from -/// non-system headers is emitted. -enum HeaderIncludeFilteringKind { HIFIL_None, HIFIL_Only_Direct_System }; +/// non-system files is emitted. The HIFIL_Direct_Per_File filtering shows the +/// direct imports and includes for each non-system source and header file +/// separately. +enum HeaderIncludeFilteringKind { + HIFIL_None, + HIFIL_Only_Direct_System, + HIFIL_Direct_Per_File +}; inline HeaderIncludeFormatKind stringToHeaderIncludeFormatKind(const char *Str) { @@ -40,6 +46,7 @@ inline bool stringToHeaderIncludeFiltering(const char *Str, llvm::StringSwitch>(Str) .Case("none", {true, HIFIL_None}) .Case("only-direct-system", {true, HIFIL_Only_Direct_System}) + .Case("direct-per-file", {true, HIFIL_Direct_Per_File}) .Default({false, HIFIL_None}); Kind = P.second; return P.first; @@ -64,6 +71,8 @@ headerIncludeFilteringKindToString(HeaderIncludeFilteringKind K) { return "none"; case HIFIL_Only_Direct_System: return "only-direct-system"; + case HIFIL_Direct_Per_File: + return "direct-per-file"; } llvm_unreachable("Unknown HeaderIncludeFilteringKind enum"); } diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index e22c0754324cb..9da753f3177ef 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -7586,7 +7586,8 @@ def header_include_format_EQ : Joined<["-"], "header-include-format=">, MarshallingInfoEnum, "HIFMT_Textual">; def header_include_filtering_EQ : Joined<["-"], "header-include-filtering=">, HelpText<"set the flag that enables filtering header information">, - Values<"none,only-direct-system">, NormalizedValues<["HIFIL_None", "HIFIL_Only_Direct_System"]>, + Values<"none,only-direct-system,direct-per-file">, + NormalizedValues<["HIFIL_None", "HIFIL_Only_Direct_System", "HIFIL_Direct_Per_File"]>, MarshallingInfoEnum, "HIFIL_None">; def show_includes : Flag<["--"], "show-includes">, HelpText<"Print cl.exe style /showIncludes to stdout">; diff --git a/clang/lib/Frontend/HeaderIncludeGen.cpp b/clang/lib/Frontend/HeaderIncludeGen.cpp index 792526083b1e6..8ab335905f9f2 100644 --- a/clang/lib/Frontend/HeaderIncludeGen.cpp +++ b/clang/lib/Frontend/HeaderIncludeGen.cpp @@ -106,6 +106,49 @@ class HeaderIncludesJSONCallback : public PPCallbacks { void FileSkipped(const FileEntryRef &SkippedFile, const Token &FilenameTok, SrcMgr::CharacteristicKind FileType) override; }; + +/// A callback for emitting direct header and module usage information to a +/// file in JSON. The output format is like HeaderIncludesJSONCallback but has +/// an array of separate entries, one for each non-system source file used in +/// the compilation showing only the direct includes and imports from that file. +class HeaderIncludesDirectPerFileCallback : public PPCallbacks { + SourceManager &SM; + HeaderSearch &HSI; + raw_ostream *OutputFile; + bool OwnsOutputFile; + using DependencyMap = llvm::DenseMap>; + DependencyMap Dependencies; + +public: + HeaderIncludesDirectPerFileCallback(const Preprocessor *PP, + raw_ostream *OutputFile_, + bool OwnsOutputFile_) + : SM(PP->getSourceManager()), HSI(PP->getHeaderSearchInfo()), + OutputFile(OutputFile_), OwnsOutputFile(OwnsOutputFile_) {} + + ~HeaderIncludesDirectPerFileCallback() override { + if (OwnsOutputFile) + delete OutputFile; + } + + HeaderIncludesDirectPerFileCallback( + const HeaderIncludesDirectPerFileCallback &) = delete; + HeaderIncludesDirectPerFileCallback & + operator=(const HeaderIncludesDirectPerFileCallback &) = delete; + + void EndOfMainFile() override; + + void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok, + StringRef FileName, bool IsAngled, + CharSourceRange FilenameRange, + OptionalFileEntryRef File, StringRef SearchPath, + StringRef RelativePath, const Module *SuggestedModule, + bool ModuleImported, + SrcMgr::CharacteristicKind FileType) override; + + void moduleImport(SourceLocation ImportLoc, ModuleIdPath Path, + const Module *Imported) override; +}; } static void PrintHeaderInfo(raw_ostream *OutputFile, StringRef Filename, @@ -192,14 +235,21 @@ void clang::AttachHeaderIncludeGen(Preprocessor &PP, MSStyle)); break; } - case HIFMT_JSON: { - assert(DepOpts.HeaderIncludeFiltering == HIFIL_Only_Direct_System && - "only-direct-system is the only option for filtering"); - PP.addPPCallbacks(std::make_unique( - &PP, OutputFile, OwnsOutputFile)); + case HIFMT_JSON: + switch (DepOpts.HeaderIncludeFiltering) { + default: + llvm_unreachable("Unknown HeaderIncludeFilteringKind enum"); + case HIFIL_Only_Direct_System: + PP.addPPCallbacks(std::make_unique( + &PP, OutputFile, OwnsOutputFile)); + break; + case HIFIL_Direct_Per_File: + PP.addPPCallbacks(std::make_unique( + &PP, OutputFile, OwnsOutputFile)); + break; + } break; } - } } void HeaderIncludesCallback::FileChanged(SourceLocation Loc, @@ -322,3 +372,81 @@ void HeaderIncludesJSONCallback::FileSkipped( IncludedHeaders.push_back(SkippedFile.getName().str()); } + +void HeaderIncludesDirectPerFileCallback::EndOfMainFile() { + if (Dependencies.empty()) + return; + + // Sort the files so that the output does not depend on the DenseMap order. + SmallVector SourceFiles; + for (auto F = Dependencies.begin(), FEnd = Dependencies.end(); F != FEnd; + ++F) { + SourceFiles.push_back(F->first); + } + llvm::sort(SourceFiles, [](const FileEntryRef &LHS, const FileEntryRef &RHS) { + return LHS.getUID() < RHS.getUID(); + }); + + std::string Str; + llvm::raw_string_ostream OS(Str); + llvm::json::OStream JOS(OS); + JOS.array([&] { + for (auto S = SourceFiles.begin(), SE = SourceFiles.end(); S != SE; ++S) { + JOS.object([&] { + SmallVector &Deps = Dependencies[*S]; + JOS.attribute("source", S->getName().str()); + JOS.attributeArray("includes", [&] { + for (unsigned I = 0, N = Deps.size(); I != N; ++I) + JOS.value(Deps[I].getName().str()); + }); + }); + } + }); + OS << "\n"; + + if (OutputFile->get_kind() == raw_ostream::OStreamKind::OK_FDStream) { + llvm::raw_fd_ostream *FDS = static_cast(OutputFile); + if (auto L = FDS->lock()) + *OutputFile << Str; + } else + *OutputFile << Str; +} + +void HeaderIncludesDirectPerFileCallback::InclusionDirective( + SourceLocation HashLoc, const Token &IncludeTok, StringRef FileName, + bool IsAngled, CharSourceRange FilenameRange, OptionalFileEntryRef File, + StringRef SearchPath, StringRef RelativePath, const Module *SuggestedModule, + bool ModuleImported, SrcMgr::CharacteristicKind FileType) { + if (!File) + return; + + SourceLocation Loc = SM.getExpansionLoc(HashLoc); + if (SM.isInSystemHeader(Loc)) + return; + OptionalFileEntryRef FromFile = SM.getFileEntryRefForID(SM.getFileID(Loc)); + if (!FromFile) + return; + + Dependencies[*FromFile].push_back(*File); +} + +void HeaderIncludesDirectPerFileCallback::moduleImport(SourceLocation ImportLoc, + ModuleIdPath Path, + const Module *Imported) { + if (!Imported) + return; + + SourceLocation Loc = SM.getExpansionLoc(ImportLoc); + if (SM.isInSystemHeader(Loc)) + return; + OptionalFileEntryRef FromFile = SM.getFileEntryRefForID(SM.getFileID(Loc)); + if (!FromFile) + return; + + OptionalFileEntryRef ModuleMapFile = + HSI.getModuleMap().getModuleMapFileForUniquing(Imported); + if (!ModuleMapFile) + return; + + Dependencies[*FromFile].push_back(*ModuleMapFile); +} diff --git a/clang/test/Preprocessor/print-header-json.c b/clang/test/Preprocessor/print-header-json.c index 1ba63ddc7a249..bb1830e5030d8 100644 --- a/clang/test/Preprocessor/print-header-json.c +++ b/clang/test/Preprocessor/print-header-json.c @@ -13,11 +13,16 @@ // RUN: env CC_PRINT_HEADERS_FORMAT=json CC_PRINT_HEADERS_FILTERING=only-direct-system CC_PRINT_HEADERS_FILE=%t.txt %clang -fsyntax-only -I %S/Inputs/print-header-json -isystem %S/Inputs/print-header-json/system %s -o /dev/null // RUN: cat %t.txt | FileCheck %s --check-prefix=SUPPORTED +// RUN: rm %t.txt +// RUN: env CC_PRINT_HEADERS_FORMAT=json CC_PRINT_HEADERS_FILTERING=direct-per-file CC_PRINT_HEADERS_FILE=%t.txt %clang -fsyntax-only -I %S/Inputs/print-header-json -isystem %S/Inputs/print-header-json/system %s -o /dev/null +// RUN: cat %t.txt | FileCheck %s --check-prefix=SUPPORTED_PERFILE + #include "system0.h" #include "header0.h" #include "system2.h" // SUPPORTED: {"source":"{{[^,]*}}print-header-json.c","includes":["{{[^,]*}}system0.h","{{[^,]*}}system3.h","{{[^,]*}}system2.h"]} +// SUPPORTED_PERFILE: [{"source":"{{[^,]*}}print-header-json.c","includes":["{{[^,]*}}system0.h","{{[^,]*}}header0.h","{{[^,]*}}system2.h"]},{"source":"{{[^,]*}}header0.h","includes":["{{[^,]*}}system3.h","{{[^,]*}}header1.h","{{[^,]*}}header2.h"]}] // UNSUPPORTED0: error: unsupported combination: -header-include-format=textual and -header-include-filtering=only-direct-system // UNSUPPORTED1: error: unsupported combination: -header-include-format=json and -header-include-filtering=none diff --git a/clang/tools/driver/driver.cpp b/clang/tools/driver/driver.cpp index 35f4c1cf66e9d..f5a08aedb090d 100644 --- a/clang/tools/driver/driver.cpp +++ b/clang/tools/driver/driver.cpp @@ -182,7 +182,7 @@ static bool SetBackdoorDriverOutputsFromEnvVars(Driver &TheDriver) { if ((TheDriver.CCPrintHeadersFormat == HIFMT_Textual && Filtering != HIFIL_None) || (TheDriver.CCPrintHeadersFormat == HIFMT_JSON && - Filtering != HIFIL_Only_Direct_System)) { + Filtering == HIFIL_None)) { TheDriver.Diag(clang::diag::err_drv_print_header_env_var_combination) << EnvVar << FilteringStr; return false;