Index: include/clang/Driver/Options.td =================================================================== --- include/clang/Driver/Options.td +++ include/clang/Driver/Options.td @@ -728,6 +728,24 @@ def fno_sanitize_stats : Flag<["-"], "fno-sanitize-stats">, Group, Flags<[CC1Option]>, HelpText<"Disable sanitizer statistics gathering.">; +def fsanitize_thread_data_races : Flag<["-"], "fsanitize-thread-data-races">, + Group, Flags<[CC1Option]>, + HelpText<"Enable data race detection in ThreadSanitizer">; +def fno_sanitize_thread_data_races : Flag<["-"], "fno-sanitize-thread-data-races">, + Group, Flags<[CC1Option]>, + HelpText<"Disable data race detection in ThreadSanitizer">; +def fsanitize_thread_stack_traces : Flag<["-"], "fsanitize-thread-stack-traces">, + Group, Flags<[CC1Option]>, + HelpText<"Enable stack trace recording in ThreadSanitizer">; +def fno_sanitize_thread_stack_traces : Flag<["-"], "fno-sanitize-thread-stack-traces">, + Group, Flags<[CC1Option]>, + HelpText<"Disable stack trace recording in ThreadSanitizer">; +def fsanitize_thread_atomics : Flag<["-"], "fsanitize-thread-atomics">, + Group, Flags<[CC1Option]>, + HelpText<"Enable analysis of the synchronization via atomic operations in ThreadSanitizer">; +def fno_sanitize_thread_atomics : Flag<["-"], "fno-sanitize-thread-atomics">, + Group, Flags<[CC1Option]>, + HelpText<"Disable analysis of the synchronization via atomic operations in ThreadSanitizer">; def fsanitize_undefined_strip_path_components_EQ : Joined<["-"], "fsanitize-undefined-strip-path-components=">, Group, Flags<[CC1Option]>, MetaVarName<"">, HelpText<"Strip (or keep only, if negative) a given number of path components " Index: include/clang/Driver/SanitizerArgs.h =================================================================== --- include/clang/Driver/SanitizerArgs.h +++ include/clang/Driver/SanitizerArgs.h @@ -38,6 +38,9 @@ bool LinkCXXRuntimes = false; bool NeedPIE = false; bool Stats = false; + bool TsanDataRaces = true; + bool TsanStackTraces = true; + bool TsanAtomics = true; public: /// Parses the sanitizer arguments from an argument list. Index: include/clang/Frontend/CodeGenOptions.def =================================================================== --- include/clang/Frontend/CodeGenOptions.def +++ include/clang/Frontend/CodeGenOptions.def @@ -163,6 +163,13 @@ ///< in sanitizer coverage. CODEGENOPT(SanitizeCoverageTracePCGuard, 1, 0) ///< Enable PC tracing with guard ///< in sanitizer coverage. +CODEGENOPT(SanitizeThreadDataRaces, 1, 1) ///< Enable data race detection in + ///< ThreadSanitizer +CODEGENOPT(SanitizeThreadStackTraces, 1, 1) ///< Enable stack trace recording in + ///< ThreadSanitizer +CODEGENOPT(SanitizeThreadAtomics, 1, 1) ///< Enable analysis of the + ///< synchronization via atomic + ///< operations in ThreadSanitizer CODEGENOPT(SanitizeStats , 1, 0) ///< Collect statistics for sanitizers. CODEGENOPT(SimplifyLibCalls , 1, 1) ///< Set when -fbuiltin is enabled. CODEGENOPT(SoftFloat , 1, 0) ///< -soft-float. Index: lib/CodeGen/BackendUtil.cpp =================================================================== --- lib/CodeGen/BackendUtil.cpp +++ lib/CodeGen/BackendUtil.cpp @@ -219,7 +219,12 @@ static void addThreadSanitizerPass(const PassManagerBuilder &Builder, legacy::PassManagerBase &PM) { - PM.add(createThreadSanitizerPass()); + const PassManagerBuilderWrapper &BuilderWrapper = + static_cast(Builder); + const CodeGenOptions &CGOpts = BuilderWrapper.getCGOpts(); + PM.add(createThreadSanitizerPass(CGOpts.SanitizeThreadDataRaces, + CGOpts.SanitizeThreadStackTraces, + CGOpts.SanitizeThreadAtomics)); } static void addDataFlowSanitizerPass(const PassManagerBuilder &Builder, Index: lib/Driver/SanitizerArgs.cpp =================================================================== --- lib/Driver/SanitizerArgs.cpp +++ lib/Driver/SanitizerArgs.cpp @@ -437,6 +437,18 @@ TC.getTriple().getArch() == llvm::Triple::x86_64); } + if (AllAddedKinds & Thread) { + TsanDataRaces = Args.hasFlag(options::OPT_fsanitize_thread_data_races, + options::OPT_fno_sanitize_thread_data_races, + TsanDataRaces); + TsanStackTraces = Args.hasFlag(options::OPT_fsanitize_thread_stack_traces, + options::OPT_fno_sanitize_thread_stack_traces, + TsanStackTraces); + TsanAtomics = Args.hasFlag(options::OPT_fsanitize_thread_atomics, + options::OPT_fno_sanitize_thread_atomics, + TsanAtomics); + } + if (AllAddedKinds & CFI) { CfiCrossDso = Args.hasFlag(options::OPT_fsanitize_cfi_cross_dso, options::OPT_fno_sanitize_cfi_cross_dso, false); @@ -685,6 +697,13 @@ if (MsanUseAfterDtor) CmdArgs.push_back(Args.MakeArgString("-fsanitize-memory-use-after-dtor")); + if (!TsanDataRaces) + CmdArgs.push_back(Args.MakeArgString("-fno-sanitize-thread-data-races")); + if (!TsanStackTraces) + CmdArgs.push_back(Args.MakeArgString("-fno-sanitize-thread-stack-traces")); + if (!TsanAtomics) + CmdArgs.push_back(Args.MakeArgString("-fno-sanitize-thread-atomics")); + if (CfiCrossDso) CmdArgs.push_back(Args.MakeArgString("-fsanitize-cfi-cross-dso")); Index: lib/Frontend/CompilerInvocation.cpp =================================================================== --- lib/Frontend/CompilerInvocation.cpp +++ lib/Frontend/CompilerInvocation.cpp @@ -729,6 +729,18 @@ Opts.SanitizeCoverageTracePC = Args.hasArg(OPT_fsanitize_coverage_trace_pc); Opts.SanitizeCoverageTracePCGuard = Args.hasArg(OPT_fsanitize_coverage_trace_pc_guard); + Opts.SanitizeThreadDataRaces = + Args.hasFlag(OPT_fsanitize_thread_data_races, + OPT_fno_sanitize_thread_data_races, + Opts.SanitizeThreadDataRaces); + Opts.SanitizeThreadStackTraces = + Args.hasFlag(OPT_fsanitize_thread_stack_traces, + OPT_fno_sanitize_thread_stack_traces, + Opts.SanitizeThreadStackTraces); + Opts.SanitizeThreadAtomics = + Args.hasFlag(OPT_fsanitize_thread_atomics, + OPT_fno_sanitize_thread_atomics, + Opts.SanitizeThreadAtomics); Opts.SanitizeMemoryTrackOrigins = getLastArgIntValue(Args, OPT_fsanitize_memory_track_origins_EQ, 0, Diags); Opts.SanitizeMemoryUseAfterDtor = Index: test/Driver/fsanitize.c =================================================================== --- test/Driver/fsanitize.c +++ test/Driver/fsanitize.c @@ -278,6 +278,33 @@ // RUN: %clang -target i386-apple-tvossimulator -fsanitize=thread %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-TSAN-I386-TVOSSIMULATOR // CHECK-TSAN-I386-TVOSSIMULATOR: unsupported option '-fsanitize=thread' for target 'i386-apple-tvossimulator' +// RUN: %clang -target x86_64-linux-gnu -fsanitize=thread -fsanitize-thread-data-races %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-TSAN-DATA-RACES +// CHECK-TSAN-DATA-RACES-NOT: -cc1{{.*}}thread-data-races +// RUN: %clang -target x86_64-linux-gnu -fsanitize=thread -fno-sanitize-thread-data-races %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-TSAN-DATA-RACES-OFF +// CHECK-TSAN-DATA-RACES-OFF: -cc1{{.*}}-fno-sanitize-thread-data-races +// RUN: %clang -target x86_64-linux-gnu -fsanitize=thread -fno-sanitize-thread-data-races -fsanitize-thread-data-races %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-TSAN-DATA-RACES-BOTH +// CHECK-TSAN-DATA-RACES-BOTH-NOT: -cc1{{.*}}thread-data-races +// RUN: %clang -target x86_64-linux-gnu -fsanitize=thread -fsanitize-thread-data-races -fno-sanitize-thread-data-races %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-TSAN-DATA-RACES-OFF +// CHECK-TSAN-DATA-RACES-BOTH-OFF: -cc1{{.*}}-fno-sanitize-thread-data-races + +// RUN: %clang -target x86_64-linux-gnu -fsanitize=thread -fsanitize-thread-stack-traces %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-TSAN-STACK-TRACES +// CHECK-TSAN-STACK-TRACES-NOT: -cc1{{.*}}thread-stack-traces +// RUN: %clang -target x86_64-linux-gnu -fsanitize=thread -fno-sanitize-thread-stack-traces %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-TSAN-STACK-TRACES-OFF +// CHECK-TSAN-STACK-TRACES-OFF: -cc1{{.*}}-fno-sanitize-thread-stack-traces +// RUN: %clang -target x86_64-linux-gnu -fsanitize=thread -fno-sanitize-thread-stack-traces -fsanitize-thread-stack-traces %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-TSAN-STACK-TRACES-BOTH +// CHECK-TSAN-STACK-TRACES-BOTH-NOT: -cc1{{.*}}thread-stack-traces +// RUN: %clang -target x86_64-linux-gnu -fsanitize=thread -fsanitize-thread-stack-traces -fno-sanitize-thread-stack-traces %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-TSAN-STACK-TRACES-OFF +// CHECK-TSAN-STACK-TRACES-BOTH-OFF: -cc1{{.*}}-fno-sanitize-thread-stack-traces + +// RUN: %clang -target x86_64-linux-gnu -fsanitize=thread -fsanitize-thread-atomics %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-TSAN-ATOMICS +// CHECK-TSAN-ATOMICS-NOT: -cc1{{.*}}thread-atomics +// RUN: %clang -target x86_64-linux-gnu -fsanitize=thread -fno-sanitize-thread-atomics %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-TSAN-ATOMICS-OFF +// CHECK-TSAN-ATOMICS-OFF: -cc1{{.*}}-fno-sanitize-thread-atomics +// RUN: %clang -target x86_64-linux-gnu -fsanitize=thread -fno-sanitize-thread-atomics -fsanitize-thread-atomics %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-TSAN-STACK-TRACES-BOTH +// CHECK-TSAN-ATOMICS-BOTH-NOT: -cc1{{.*}}thread-atomics +// RUN: %clang -target x86_64-linux-gnu -fsanitize=thread -fsanitize-thread-atomics -fno-sanitize-thread-atomics %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-TSAN-ATOMICS-OFF +// CHECK-TSAN-ATOMICS-BOTH-OFF: -cc1{{.*}}-fno-sanitize-thread-atomics + // RUN: %clang -target x86_64-apple-darwin10 -fsanitize=function %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-FSAN-DARWIN // CHECK-FSAN-DARWIN: unsupported option '-fsanitize=function' for target 'x86_64-apple-darwin10'