Index: include/clang/Driver/Options.td =================================================================== --- include/clang/Driver/Options.td +++ include/clang/Driver/Options.td @@ -495,6 +495,8 @@ Flags<[DriverOption]>; def fdebug_pass_arguments : Flag<["-"], "fdebug-pass-arguments">, Group; def fdebug_pass_structure : Flag<["-"], "fdebug-pass-structure">, Group; +def fdepfile_entry : Joined<["-"], "fdepfile-entry=">, + Group, Flags<[CC1Option]>; def fdiagnostics_fixit_info : Flag<["-"], "fdiagnostics-fixit-info">, Group; def fdiagnostics_parseable_fixits : Flag<["-"], "fdiagnostics-parseable-fixits">, Group, Flags<[CoreOption, CC1Option]>, HelpText<"Print fix-its in machine parseable form">; Index: include/clang/Driver/SanitizerArgs.h =================================================================== --- include/clang/Driver/SanitizerArgs.h +++ include/clang/Driver/SanitizerArgs.h @@ -27,6 +27,7 @@ SanitizerSet TrapSanitizers; std::vector BlacklistFiles; + std::vector ExtraDeps; int CoverageFeatures; int MsanTrackOrigins; bool MsanUseAfterDtor; Index: lib/Driver/SanitizerArgs.cpp =================================================================== --- lib/Driver/SanitizerArgs.cpp +++ lib/Driver/SanitizerArgs.cpp @@ -176,6 +176,7 @@ RecoverableSanitizers.clear(); TrapSanitizers.clear(); BlacklistFiles.clear(); + ExtraDeps.clear(); CoverageFeatures = 0; MsanTrackOrigins = 0; MsanUseAfterDtor = false; @@ -383,13 +384,16 @@ if (Arg->getOption().matches(options::OPT_fsanitize_blacklist)) { Arg->claim(); std::string BLPath = Arg->getValue(); - if (llvm::sys::fs::exists(BLPath)) + if (llvm::sys::fs::exists(BLPath)) { BlacklistFiles.push_back(BLPath); - else + ExtraDeps.push_back(BLPath); + } else D.Diag(clang::diag::err_drv_no_such_file) << BLPath; + } else if (Arg->getOption().matches(options::OPT_fno_sanitize_blacklist)) { Arg->claim(); BlacklistFiles.clear(); + ExtraDeps.clear(); } } // Validate blacklists format. @@ -563,6 +567,11 @@ BlacklistOpt += BLPath; CmdArgs.push_back(Args.MakeArgString(BlacklistOpt)); } + for (const auto &Dep : ExtraDeps) { + SmallString<64> ExtraDepOpt("-fdepfile-entry="); + ExtraDepOpt += Dep; + CmdArgs.push_back(Args.MakeArgString(ExtraDepOpt)); + } if (MsanTrackOrigins) CmdArgs.push_back(Args.MakeArgString("-fsanitize-memory-track-origins=" + Index: lib/Frontend/CompilerInvocation.cpp =================================================================== --- lib/Frontend/CompilerInvocation.cpp +++ lib/Frontend/CompilerInvocation.cpp @@ -709,7 +709,7 @@ // Add sanitizer blacklists as extra dependencies. // They won't be discovered by the regular preprocessor, so // we let make / ninja to know about this implicit dependency. - Opts.ExtraDeps = Args.getAllArgValues(OPT_fsanitize_blacklist); + Opts.ExtraDeps = Args.getAllArgValues(OPT_fdepfile_entry); auto ModuleFiles = Args.getAllArgValues(OPT_fmodule_file); Opts.ExtraDeps.insert(Opts.ExtraDeps.end(), ModuleFiles.begin(), ModuleFiles.end()); Index: test/Driver/fsanitize-blacklist.c =================================================================== --- test/Driver/fsanitize-blacklist.c +++ test/Driver/fsanitize-blacklist.c @@ -13,13 +13,25 @@ // RUN: echo "badline" > %t.bad // RUN: %clang -fsanitize=address -fsanitize-blacklist=%t.good -fsanitize-blacklist=%t.second %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-BLACKLIST -// CHECK-BLACKLIST: -fsanitize-blacklist={{.*}}.good -// CHECK-BLACKLIST: -fsanitize-blacklist={{.*}}.second +// CHECK-BLACKLIST: -fsanitize-blacklist={{.*}}.good" "-fsanitize-blacklist={{.*}}.second + +// Now, check for -fdepfile-entry flags. +// RUN: %clang -fsanitize=address -fsanitize-blacklist=%t.good -fsanitize-blacklist=%t.second %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-BLACKLIST2 +// CHECK-BLACKLIST2: -fdepfile-entry={{.*}}.good" "-fdepfile-entry={{.*}}.second + +// Check that the default blacklist is not added as an extra dependency. +// RUN: %clang -fsanitize=address -resource-dir=%S/Inputs/resource_dir %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-DEFAULT-BLACKLIST --implicit-check-not=fdepfile-entry +// CHECK-DEFAULT-BLACKLIST: -fsanitize-blacklist={{.*}}asan_blacklist.txt // Ignore -fsanitize-blacklist flag if there is no -fsanitize flag. // RUN: %clang -fsanitize-blacklist=%t.good %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-NO-SANITIZE --check-prefix=DELIMITERS // CHECK-NO-SANITIZE-NOT: -fsanitize-blacklist +// Ignore -fsanitize-blacklist flag if there is no -fsanitize flag. +// Now, check for the absense of -fdepfile-entry flags. +// RUN: %clang -fsanitize-blacklist=%t.good %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-NO-SANITIZE2 --check-prefix=DELIMITERS +// CHECK-NO-SANITIZE2-NOT: -fdepfile-entry + // Flag -fno-sanitize-blacklist wins if it is specified later. // RUN: %clang -fsanitize=address -fsanitize-blacklist=%t.good -fno-sanitize-blacklist %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-NO-BLACKLIST --check-prefix=DELIMITERS // CHECK-NO-BLACKLIST-NOT: -fsanitize-blacklist Index: test/Frontend/print-header-includes.c =================================================================== --- test/Frontend/print-header-includes.c +++ test/Frontend/print-header-includes.c @@ -14,7 +14,7 @@ // MS-NOT: Note // RUN: echo "fun:foo" > %t.blacklist -// RUN: %clang_cc1 -fsanitize=address -fsanitize-blacklist=%t.blacklist -E --show-includes -o %t.out %s > %t.stdout +// RUN: %clang_cc1 -fsanitize=address -fdepfile-entry=%t.blacklist -E --show-includes -o %t.out %s > %t.stdout // RUN: FileCheck --check-prefix=MS-BLACKLIST < %t.stdout %s // MS-BLACKLIST: Note: including file: {{.*\.blacklist}} // MS-BLACKLIST: Note: including file: {{.*test.h}}