def fno_sanitize_blacklist : Flag<["-"], "fno-sanitize-blacklist">,
Group<f_clang_Group>,
HelpText<"Don't use blacklist file for sanitizers">;
+def fsanitize_coverage : Joined<["-"], "fsanitize-coverage=">,
+ Group<f_clang_Group>, Flags<[CC1Option]>,
+ HelpText<"Enable coverage instrumentation for Sanitizers">;
def fsanitize_memory_track_origins_EQ : Joined<["-"], "fsanitize-memory-track-origins=">,
Group<f_clang_Group>, Flags<[CC1Option]>,
HelpText<"Enable origins tracking in MemorySanitizer">;
unsigned Kind;
std::string BlacklistFile;
+ int SanitizeCoverage;
int MsanTrackOrigins;
int AsanFieldPadding;
bool AsanZeroBaseShadow;
///< offset in AddressSanitizer.
CODEGENOPT(SanitizeMemoryTrackOrigins, 2, 0) ///< Enable tracking origins in
///< MemorySanitizer
+CODEGENOPT(SanitizeCoverage, 3, 0) ///< Enable sanitizer coverage instrumentation.
CODEGENOPT(SanitizeUndefinedTrapOnError, 1, 0) ///< Set on
/// -fsanitize-undefined-trap-on-error
CODEGENOPT(SimplifyLibCalls , 1, 1) ///< Set when -fbuiltin is enabled.
PM.add(createBoundsCheckingPass());
}
+static void addSanitizerCoveragePass(const PassManagerBuilder &Builder,
+ PassManagerBase &PM) {
+ const PassManagerBuilderWrapper &BuilderWrapper =
+ static_cast<const PassManagerBuilderWrapper&>(Builder);
+ const CodeGenOptions &CGOpts = BuilderWrapper.getCGOpts();
+ PM.add(createSanitizerCoverageModulePass(CGOpts.SanitizeCoverage));
+}
+
static void addAddressSanitizerPasses(const PassManagerBuilder &Builder,
PassManagerBase &PM) {
PM.add(createAddressSanitizerFunctionPass());
addBoundsCheckingPass);
}
+ if (CodeGenOpts.SanitizeCoverage) {
+ PMBuilder.addExtension(PassManagerBuilder::EP_OptimizerLast,
+ addSanitizerCoveragePass);
+ PMBuilder.addExtension(PassManagerBuilder::EP_EnabledOnOptLevel0,
+ addSanitizerCoveragePass);
+ }
+
if (LangOpts.Sanitize.has(SanitizerKind::Address)) {
PMBuilder.addExtension(PassManagerBuilder::EP_OptimizerLast,
addAddressSanitizerPasses);
void SanitizerArgs::clear() {
Kind = 0;
BlacklistFile = "";
+ SanitizeCoverage = 0;
MsanTrackOrigins = 0;
AsanFieldPadding = 0;
AsanZeroBaseShadow = false;
}
}
+ // Parse -fsanitize-coverage=N
+ if (NeedsAsan) { // Currently asan is required.
+ if (Arg *A = Args.getLastArg(options::OPT_fsanitize_coverage)) {
+ StringRef S = A->getValue();
+ // Legal values are 0..4.
+ if (S.getAsInteger(0, SanitizeCoverage) || SanitizeCoverage < 0 ||
+ SanitizeCoverage > 4)
+ D.Diag(diag::err_drv_invalid_value) << A->getAsString(Args) << S;
+ }
+ }
+
if (NeedsAsan) {
AsanSharedRuntime =
Args.hasArg(options::OPT_shared_libasan) ||
if (AsanFieldPadding)
CmdArgs.push_back(Args.MakeArgString("-fsanitize-address-field-padding=" +
llvm::utostr(AsanFieldPadding)));
+ if (SanitizeCoverage)
+ CmdArgs.push_back(Args.MakeArgString("-fsanitize-coverage=" +
+ llvm::utostr(SanitizeCoverage)));
// Workaround for PR16386.
if (needsMsanRt())
CmdArgs.push_back(Args.MakeArgString("-fno-assume-sane-operator-new"));
Opts.CompressDebugSections = Args.hasArg(OPT_compress_debug_sections);
Opts.DebugCompilationDir = Args.getLastArgValue(OPT_fdebug_compilation_dir);
Opts.LinkBitcodeFile = Args.getLastArgValue(OPT_mlink_bitcode_file);
+ Opts.SanitizeCoverage =
+ getLastArgIntValue(Args, OPT_fsanitize_coverage, 0, Diags);
Opts.SanitizeMemoryTrackOrigins =
getLastArgIntValue(Args, OPT_fsanitize_memory_track_origins_EQ, 0, Diags);
Opts.SanitizeUndefinedTrapOnError =
// RUN: %clang -target x86_64-linux-gnu -fsanitize=memory -fsanitize-memory-track-origins=3 -pie %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-TRACK-ORIGINS-3
// CHECK-TRACK-ORIGINS-3: error: invalid value '3' in '-fsanitize-memory-track-origins=3'
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=address -fsanitize-coverage=0 %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANITIZE-COVERAGE-0
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=address %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANITIZE-COVERAGE-0
+// CHECK-SANITIZE-COVERAGE-0-NOT: fsanitize-coverage
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=address -fsanitize-coverage=1 %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANITIZE-COVERAGE-1
+// CHECK-SANITIZE-COVERAGE-1: fsanitize-coverage=1
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=address -fsanitize-coverage=4 %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANITIZE-COVERAGE-4
+// CHECK-SANITIZE-COVERAGE-4: fsanitize-coverage=4
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=address -fsanitize-coverage=5 %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANITIZE-COVERAGE-5
+// CHECK-SANITIZE-COVERAGE-5: error: invalid value '5' in '-fsanitize-coverage=5'
+
// RUN: %clang -target x86_64-linux-gnu -fsanitize=address -fsanitize-address-field-padding=0 %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-ASAN-FIELD-PADDING-0
// CHECK-ASAN-FIELD-PADDING-0-NOT: -fsanitize-address-field-padding
// RUN: %clang -target x86_64-linux-gnu -fsanitize=address -fsanitize-address-field-padding=1 %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-ASAN-FIELD-PADDING-1