diff options
-rw-r--r-- | include/clang/Basic/LangOptions.def | 7 | ||||
-rw-r--r-- | include/clang/Basic/Sanitizers.def | 69 | ||||
-rw-r--r-- | include/clang/Driver/Options.td | 3 | ||||
-rw-r--r-- | lib/Driver/Tools.cpp | 183 | ||||
-rw-r--r-- | lib/Frontend/CompilerInvocation.cpp | 31 | ||||
-rw-r--r-- | test/Driver/asan-ld.c | 19 | ||||
-rw-r--r-- | test/Driver/asan.c | 1 | ||||
-rw-r--r-- | test/Driver/darwin-asan-nofortify.c | 1 | ||||
-rw-r--r-- | test/Driver/fsanitize.c | 16 | ||||
-rw-r--r-- | test/Driver/tsan.c | 1 |
10 files changed, 308 insertions, 23 deletions
diff --git a/include/clang/Basic/LangOptions.def b/include/clang/Basic/LangOptions.def index 7bce57352a..fab4a54640 100644 --- a/include/clang/Basic/LangOptions.def +++ b/include/clang/Basic/LangOptions.def @@ -127,8 +127,6 @@ BENIGN_LANGOPT(ParseUnknownAnytype, 1, 0, "__unknown_anytype") BENIGN_LANGOPT(DebuggerSupport , 1, 0, "debugger support") BENIGN_LANGOPT(DebuggerCastResultToId, 1, 0, "for 'po' in the debugger, cast the result to id if it is of unknown type") BENIGN_LANGOPT(DebuggerObjCLiteral , 1, 0, "debugger Objective-C literals and subscripting support") -BENIGN_LANGOPT(SanitizeAddress , 1, 0, "AddressSanitizer enabled") -BENIGN_LANGOPT(SanitizeThread , 1, 0, "ThreadSanitizer enabled") BENIGN_LANGOPT(SpellChecking , 1, 1, "spell-checking") LANGOPT(SinglePrecisionConstants , 1, 0, "treating double-precision floating point constants as single precision constants") @@ -170,6 +168,11 @@ BENIGN_LANGOPT(EmitMicrosoftInlineAsm , 1, 0, BENIGN_LANGOPT(RetainCommentsFromSystemHeaders, 1, 0, "retain documentation comments from system headers in the AST") +/// Runtime sanitizers. +#define SANITIZER(NAME, ID) \ +BENIGN_LANGOPT(Sanitize##ID, 1, 0, NAME " sanitizer") +#include "clang/Basic/Sanitizers.def" + #undef LANGOPT #undef VALUE_LANGOPT #undef BENIGN_LANGOPT diff --git a/include/clang/Basic/Sanitizers.def b/include/clang/Basic/Sanitizers.def new file mode 100644 index 0000000000..085ca16eae --- /dev/null +++ b/include/clang/Basic/Sanitizers.def @@ -0,0 +1,69 @@ +//===--- Sanitizers.def - Runtime sanitizer options -------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the options for specifying which runtime sanitizers to +// enable. Users of this file must define the SANITIZER macro to make use of +// this information. Users of this file can also define the SANITIZER_GROUP +// macro to get information on options which refer to sets of sanitizers. +// +//===----------------------------------------------------------------------===// + +#ifndef SANITIZER +#error "Define SANITIZER prior to including this file!" +#endif + +// SANITIZER(NAME, ID) + +// The first value is the name of the sanitizer as a string. The sanitizer can +// be enabled by specifying -fsanitize=NAME. + +// The second value is an identifier which can be used to refer to the +// sanitizer. + + +// SANITIZER_GROUP(NAME, ID, ALIAS) + +// The first two values have the same semantics as the corresponding SANITIZER +// values. The third value is an expression ORing together the IDs of individual +// sanitizers in this group. + +#ifndef SANITIZER_GROUP +#define SANITIZER_GROUP(NAME, ID, ALIAS) +#endif + + +// AddressSanitizer +SANITIZER("address", Address) + +// ThreadSanitizer +SANITIZER("thread", Thread) + +// UndefinedBehaviorSanitizer +SANITIZER("signed-integer-overflow", SignedIntegerOverflow) +SANITIZER("divide-by-zero", DivideByZero) +SANITIZER("shift", Shift) +SANITIZER("unreachable", Unreachable) +SANITIZER("return", Return) +SANITIZER("vla-bound", VLABound) +SANITIZER("alignment", Alignment) +SANITIZER("null", Null) +SANITIZER("vptr", Vptr) +SANITIZER("object-size", ObjectSize) +SANITIZER("float-cast-overflow", FloatCastOverflow) + +// -fsanitize=undefined (and its alias -fcatch-undefined-behavior). This should +// include all the sanitizers which have low overhead, no ABI or address space +// layout implications, and only catch undefined behavior. +SANITIZER_GROUP("undefined", Undefined, + SignedIntegerOverflow | DivideByZero | Shift | Unreachable | + Return | VLABound | Alignment | Null | Vptr | ObjectSize | + FloatCastOverflow) + +#undef SANITIZER +#undef SANITIZER_GROUP diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td index 3c39eb66e7..ba609faab4 100644 --- a/include/clang/Driver/Options.td +++ b/include/clang/Driver/Options.td @@ -387,6 +387,9 @@ def fmath_errno : Flag<["-"], "fmath-errno">, Group<f_Group>, Flags<[CC1Option]> def fno_math_errno : Flag<["-"], "fno-math-errno">, Group<f_Group>; def fsignaling_math : Flag<["-"], "fsignaling-math">, Group<f_Group>; def fno_signaling_math : Flag<["-"], "fno-signaling-math">, Group<f_Group>; +def fsanitize_EQ : CommaJoined<["-"], "fsanitize=">, Group<f_clang_Group>, + Flags<[CC1Option]>; +def fno_sanitize_EQ : CommaJoined<["-"], "fno-sanitize=">, Group<f_clang_Group>; def funsafe_math_optimizations : Flag<["-"], "funsafe-math-optimizations">, Group<f_Group>; def fno_unsafe_math_optimizations : Flag<["-"], "fno-unsafe-math-optimizations">, diff --git a/lib/Driver/Tools.cpp b/lib/Driver/Tools.cpp index 05487c4193..d1109ff730 100644 --- a/lib/Driver/Tools.cpp +++ b/lib/Driver/Tools.cpp @@ -1452,13 +1452,149 @@ static bool UseRelaxAll(Compilation &C, const ArgList &Args) { RelaxDefault); } +namespace { +struct SanitizerArgs { + /// Assign ordinals to sanitizer flags. We'll use the ordinal values as + /// bit positions within \c Kind. + enum SanitizeOrdinal { +#define SANITIZER(NAME, ID) SO_##ID, +#include "clang/Basic/Sanitizers.def" + SO_Count + }; + + /// Bugs to catch at runtime. + enum SanitizeKind { +#define SANITIZER(NAME, ID) ID = 1 << SO_##ID, +#define SANITIZER_GROUP(NAME, ID, ALIAS) ID = ALIAS, +#include "clang/Basic/Sanitizers.def" + + NeedsAsanRt = Address, + NeedsTsanRt = Thread, + NeedsUbsanRt = Undefined + }; + unsigned Kind; + + SanitizerArgs() : Kind(0) {} + + bool needsAsanRt() const { return Kind & NeedsAsanRt; } + bool needsTsanRt() const { return Kind & NeedsTsanRt; } + bool needsUbsanRt() const { return Kind & NeedsUbsanRt; } + + /// Parse a single value from a -fsanitize= or -fno-sanitize= value list. + /// Returns a member of the \c SanitizeKind enumeration, or \c 0 if \p Value + /// is not known. + static unsigned parse(const char *Value) { + return llvm::StringSwitch<SanitizeKind>(Value) +#define SANITIZER(NAME, ID) .Case(NAME, ID) +#define SANITIZER_GROUP(NAME, ID, ALIAS) .Case(NAME, ID) +#include "clang/Basic/Sanitizers.def" + .Default(SanitizeKind()); + } + + /// Parse a -fsanitize= or -fno-sanitize= argument's values, diagnosing any + /// invalid components. + static unsigned parse(const Driver &D, const Arg *A) { + unsigned Kind = 0; + for (unsigned I = 0, N = A->getNumValues(); I != N; ++I) { + if (unsigned K = parse(A->getValue(I))) + Kind |= K; + else + D.Diag(diag::err_drv_unsupported_option_argument) + << A->getOption().getName() << A->getValue(I); + } + return Kind; + } + + void addArgs(const ArgList &Args, ArgStringList &CmdArgs) const { + if (Kind & Address) + CmdArgs.push_back("-faddress-sanitizer"); + if (Kind & Thread) + CmdArgs.push_back("-fthread-sanitizer"); + if (Kind & Undefined) + CmdArgs.push_back("-fcatch-undefined-behavior"); + if (!Kind) + return; + llvm::SmallString<256> SanitizeOpt("-fsanitize="); +#define SANITIZER(NAME, ID) \ + if (Kind & ID) \ + SanitizeOpt += NAME ","; +#include "clang/Basic/Sanitizers.def" + SanitizeOpt.pop_back(); + CmdArgs.push_back(Args.MakeArgString(SanitizeOpt)); + } +}; +} + +/// Produce an argument string from argument \p A, which shows how it provides a +/// value in \p Mask. For instance, the argument "-fsanitize=address,alignment" +/// with mask \c NeedsUbsanRt would produce "-fsanitize=alignment". +static std::string describeSanitizeArg(const Arg *A, unsigned Mask) { + if (!A->getOption().matches(options::OPT_fsanitize_EQ)) + return A->getOption().getName(); + + for (unsigned I = 0, N = A->getNumValues(); I != N; ++I) + if (SanitizerArgs::parse(A->getValue(I)) & Mask) + return std::string("-fsanitize=") + A->getValue(I); + + llvm_unreachable("arg didn't provide expected value"); +} + +/// Parse the sanitizer arguments from an argument list. +static SanitizerArgs getSanitizerArgs(const Driver &D, const ArgList &Args) { + SanitizerArgs Sanitize; + + const Arg *AsanArg, *TsanArg, *UbsanArg; + + for (ArgList::const_iterator I = Args.begin(), E = Args.end(); I != E; ++I) { + unsigned Add = 0, Remove = 0; + if ((*I)->getOption().matches(options::OPT_faddress_sanitizer)) + Add = SanitizerArgs::Address; + else if ((*I)->getOption().matches(options::OPT_fno_address_sanitizer)) + Remove = SanitizerArgs::Address; + else if ((*I)->getOption().matches(options::OPT_fthread_sanitizer)) + Add = SanitizerArgs::Thread; + else if ((*I)->getOption().matches(options::OPT_fno_thread_sanitizer)) + Remove = SanitizerArgs::Thread; + else if ((*I)->getOption().matches(options::OPT_fcatch_undefined_behavior)) + Add = SanitizerArgs::Undefined; + else if ((*I)->getOption().matches(options::OPT_fsanitize_EQ)) + Add = SanitizerArgs::parse(D, *I); + else if ((*I)->getOption().matches(options::OPT_fno_sanitize_EQ)) + Remove = SanitizerArgs::parse(D, *I); + else + continue; + + (*I)->claim(); + + Sanitize.Kind |= Add; + Sanitize.Kind &= ~Remove; + + if (Add & SanitizerArgs::NeedsAsanRt) AsanArg = *I; + if (Add & SanitizerArgs::NeedsTsanRt) TsanArg = *I; + if (Add & SanitizerArgs::NeedsUbsanRt) UbsanArg = *I; + } + + // Only one runtime library can be used at once. + // FIXME: Allow Ubsan to be combined with the other two. + bool NeedsAsan = Sanitize.needsAsanRt(); + bool NeedsTsan = Sanitize.needsTsanRt(); + bool NeedsUbsan = Sanitize.needsUbsanRt(); + if (NeedsAsan + NeedsTsan + NeedsUbsan > 1) + D.Diag(diag::err_drv_argument_not_allowed_with) + << describeSanitizeArg(NeedsAsan ? AsanArg : TsanArg, + NeedsAsan ? SanitizerArgs::NeedsAsanRt + : SanitizerArgs::NeedsTsanRt) + << describeSanitizeArg(NeedsUbsan ? UbsanArg : TsanArg, + NeedsUbsan ? SanitizerArgs::NeedsUbsanRt + : SanitizerArgs::NeedsTsanRt); + + return Sanitize; +} + /// If AddressSanitizer is enabled, add appropriate linker flags (Linux). /// This needs to be called before we add the C run-time (malloc, etc). static void addAsanRTLinux(const ToolChain &TC, const ArgList &Args, ArgStringList &CmdArgs) { - if (!Args.hasFlag(options::OPT_faddress_sanitizer, - options::OPT_fno_address_sanitizer, false)) - return; if(TC.getTriple().getEnvironment() == llvm::Triple::Android) { if (!Args.hasArg(options::OPT_shared)) { if (!Args.hasArg(options::OPT_pie)) @@ -1490,9 +1626,6 @@ static void addAsanRTLinux(const ToolChain &TC, const ArgList &Args, /// This needs to be called before we add the C run-time (malloc, etc). static void addTsanRTLinux(const ToolChain &TC, const ArgList &Args, ArgStringList &CmdArgs) { - if (!Args.hasFlag(options::OPT_fthread_sanitizer, - options::OPT_fno_thread_sanitizer, false)) - return; if (!Args.hasArg(options::OPT_shared)) { // LibTsan is "libclang_rt.tsan-<ArchName>.a" in the Linux library // resource directory. @@ -1511,8 +1644,6 @@ static void addTsanRTLinux(const ToolChain &TC, const ArgList &Args, /// (Linux). static void addUbsanRTLinux(const ToolChain &TC, const ArgList &Args, ArgStringList &CmdArgs) { - if (!Args.hasArg(options::OPT_fcatch_undefined_behavior)) - return; if (!Args.hasArg(options::OPT_shared)) { // LibUbsan is "libclang_rt.ubsan-<ArchName>.a" in the Linux library // resource directory. @@ -2370,7 +2501,6 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-ffreestanding"); // Forward -f (flag) options which we can pass directly. - Args.AddLastArg(CmdArgs, options::OPT_fcatch_undefined_behavior); Args.AddLastArg(CmdArgs, options::OPT_femit_all_decls); Args.AddLastArg(CmdArgs, options::OPT_fheinous_gnu_extensions); Args.AddLastArg(CmdArgs, options::OPT_flimit_debug_info); @@ -2380,6 +2510,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, Args.AddLastArg(CmdArgs, options::OPT_fdiagnostics_show_template_tree); Args.AddLastArg(CmdArgs, options::OPT_fno_elide_type); + SanitizerArgs Sanitize = getSanitizerArgs(D, Args); + Sanitize.addArgs(Args, CmdArgs); + // Report and error for -faltivec on anything other then PowerPC. if (const Arg *A = Args.getLastArg(options::OPT_faltivec)) if (!(getToolChain().getTriple().getArch() == llvm::Triple::ppc || @@ -2390,14 +2523,6 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, if (getToolChain().SupportsProfiling()) Args.AddLastArg(CmdArgs, options::OPT_pg); - if (Args.hasFlag(options::OPT_faddress_sanitizer, - options::OPT_fno_address_sanitizer, false)) - CmdArgs.push_back("-faddress-sanitizer"); - - if (Args.hasFlag(options::OPT_fthread_sanitizer, - options::OPT_fno_thread_sanitizer, false)) - CmdArgs.push_back("-fthread-sanitizer"); - // -flax-vector-conversions is default. if (!Args.hasFlag(options::OPT_flax_vector_conversions, options::OPT_fno_lax_vector_conversions)) @@ -2544,9 +2669,20 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // -frtti is default. if (!Args.hasFlag(options::OPT_frtti, options::OPT_fno_rtti) || - KernelOrKext) + KernelOrKext) { CmdArgs.push_back("-fno-rtti"); + // -fno-rtti cannot usefully be combined with -fsanitize=vptr. + if (Sanitize.Kind & SanitizerArgs::Vptr) { + llvm::StringRef NoRttiArg = + Args.getLastArg(options::OPT_mkernel, + options::OPT_fapple_kext, + options::OPT_fno_rtti)->getOption().getName(); + D.Diag(diag::err_drv_argument_not_allowed_with) + << "-fsanitize=vptr" << NoRttiArg; + } + } + // -fshort-enums=0 is default for all architectures except Hexagon. if (Args.hasFlag(options::OPT_fshort_enums, options::OPT_fno_short_enums, @@ -5972,8 +6108,11 @@ void linuxtools::Link::ConstructJob(Compilation &C, const JobAction &JA, AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs); + SanitizerArgs Sanitize = getSanitizerArgs(D, Args); + // Call this before we add the C++ ABI library. - addUbsanRTLinux(getToolChain(), Args, CmdArgs); + if (Sanitize.needsUbsanRt()) + addUbsanRTLinux(getToolChain(), Args, CmdArgs); if (D.CCCIsCXX && !Args.hasArg(options::OPT_nostdlib) && @@ -5989,8 +6128,10 @@ void linuxtools::Link::ConstructJob(Compilation &C, const JobAction &JA, } // Call this before we add the C run-time. - addAsanRTLinux(getToolChain(), Args, CmdArgs); - addTsanRTLinux(getToolChain(), Args, CmdArgs); + if (Sanitize.needsAsanRt()) + addAsanRTLinux(getToolChain(), Args, CmdArgs); + if (Sanitize.needsTsanRt()) + addTsanRTLinux(getToolChain(), Args, CmdArgs); if (!Args.hasArg(options::OPT_nostdlib)) { if (!Args.hasArg(options::OPT_nodefaultlibs)) { diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index 703b9e7ff2..8cce72c5ea 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -1273,6 +1273,37 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK, case 1: Opts.setStackProtector(LangOptions::SSPOn); break; case 2: Opts.setStackProtector(LangOptions::SSPReq); break; } + + // Parse -fsanitize= arguments. + std::vector<std::string> Sanitizers = Args.getAllArgValues(OPT_fsanitize_EQ); + for (unsigned I = 0, N = Sanitizers.size(); I != N; ++I) { + // Since the Opts.Sanitize* values are bitfields, it's a little tricky to + // efficiently map string values to them. Perform the mapping indirectly: + // convert strings to enumerated values, then switch over the enum to set + // the right bitfield value. + enum Sanitizer { +#define SANITIZER(NAME, ID) \ + ID, +#include "clang/Basic/Sanitizers.def" + Unknown + }; + switch (llvm::StringSwitch<unsigned>(Sanitizers[I]) +#define SANITIZER(NAME, ID) \ + .Case(NAME, ID) +#include "clang/Basic/Sanitizers.def" + .Default(Unknown)) { +#define SANITIZER(NAME, ID) \ + case ID: \ + Opts.Sanitize##ID = true; \ + break; +#include "clang/Basic/Sanitizers.def" + + case Unknown: + Diags.Report(diag::err_drv_invalid_value) + << "-fsanitize=" << Sanitizers[I]; + break; + } + } } static void ParsePreprocessorArgs(PreprocessorOptions &Opts, ArgList &Args, diff --git a/test/Driver/asan-ld.c b/test/Driver/asan-ld.c index bfb30dc9a2..59dbda15c8 100644 --- a/test/Driver/asan-ld.c +++ b/test/Driver/asan-ld.c @@ -4,6 +4,12 @@ // RUN: -target i386-unknown-linux -faddress-sanitizer \ // RUN: --sysroot=%S/Inputs/basic_linux_tree \ // RUN: | FileCheck --check-prefix=CHECK-LINUX %s +// +// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ +// RUN: -target i386-unknown-linux -fsanitize=address \ +// RUN: --sysroot=%S/Inputs/basic_linux_tree \ +// RUN: | FileCheck --check-prefix=CHECK-LINUX %s +// // CHECK-LINUX: "{{.*}}ld{{(.exe)?}}" // CHECK-LINUX-NOT: "-lc" // CHECK-LINUX: libclang_rt.asan-i386.a" @@ -15,6 +21,12 @@ // RUN: -target arm-linux-androideabi -faddress-sanitizer \ // RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \ // RUN: | FileCheck --check-prefix=CHECK-ANDROID %s +// +// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ +// RUN: -target arm-linux-androideabi -fsanitize=address \ +// RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \ +// RUN: | FileCheck --check-prefix=CHECK-ANDROID %s +// // CHECK-ANDROID: "{{.*}}ld{{(.exe)?}}" // CHECK-ANDROID-NOT: "-lc" // CHECK-ANDROID: libclang_rt.asan-arm-android.so" @@ -25,6 +37,13 @@ // RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \ // RUN: -shared \ // RUN: | FileCheck --check-prefix=CHECK-ANDROID-SHARED %s +// +// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ +// RUN: -target arm-linux-androideabi -fsanitize=address \ +// RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \ +// RUN: -shared \ +// RUN: | FileCheck --check-prefix=CHECK-ANDROID-SHARED %s +// // CHECK-ANDROID-SHARED: "{{.*}}ld{{(.exe)?}}" // CHECK-ANDROID-SHARED-NOT: "-lc" // CHECK-ANDROID-SHARED: libclang_rt.asan-arm-android.so" diff --git a/test/Driver/asan.c b/test/Driver/asan.c index 4c9a1b6c44..c9b3796b44 100644 --- a/test/Driver/asan.c +++ b/test/Driver/asan.c @@ -2,6 +2,7 @@ // RUN: %clang -O1 -target i386-unknown-unknown -faddress-sanitizer %s -S -emit-llvm -o - | FileCheck %s // RUN: %clang -O2 -target i386-unknown-unknown -faddress-sanitizer %s -S -emit-llvm -o - | FileCheck %s // RUN: %clang -O3 -target i386-unknown-unknown -faddress-sanitizer %s -S -emit-llvm -o - | FileCheck %s +// RUN: %clang -target i386-unknown-unknown -fsanitize=address %s -S -emit-llvm -o - | FileCheck %s // Verify that -faddress-sanitizer invokes asan instrumentation. int foo(int *a) { return *a; } diff --git a/test/Driver/darwin-asan-nofortify.c b/test/Driver/darwin-asan-nofortify.c index 42e81f872f..7f325e097b 100644 --- a/test/Driver/darwin-asan-nofortify.c +++ b/test/Driver/darwin-asan-nofortify.c @@ -1,5 +1,6 @@ // Make sure AddressSanitizer disables _FORTIFY_SOURCE on Darwin. // RUN: %clang -faddress-sanitizer %s -E -dM -target x86_64-darwin - | FileCheck %s +// RUN: %clang -fsanitize=address %s -E -dM -target x86_64-darwin - | FileCheck %s // CHECK: #define _FORTIFY_SOURCE 0 diff --git a/test/Driver/fsanitize.c b/test/Driver/fsanitize.c new file mode 100644 index 0000000000..047892a6a2 --- /dev/null +++ b/test/Driver/fsanitize.c @@ -0,0 +1,16 @@ +// RUN: %clang -target x86_64-linux-gnu -fcatch-undefined-behavior %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UNDEFINED +// RUN: %clang -target x86_64-linux-gnu -fsanitize=undefined %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UNDEFINED +// CHECK-UNDEFINED: "-fsanitize={{((signed-integer-overflow|divide-by-zero|shift|unreachable|return|vla-bound|alignment|null|vptr|object-size|float-cast-overflow),?){11}"}} + +// RUN: %clang -target x86_64-linux-gnu -fsanitize=thread,undefined -fno-thread-sanitizer -fno-sanitize=float-cast-overflow,vptr %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-PARTIAL-UNDEFINED +// CHECK-PARTIAL-UNDEFINED: "-fsanitize={{((signed-integer-overflow|divide-by-zero|shift|unreachable|return|vla-bound|alignment|null|object-size),?){9}"}} + +// RUN: %clang -target x86_64-linux-gnu -fsanitize=vptr -fno-rtti %s -c -o - 2>&1 | FileCheck %s --check-prefix=CHECK-VPTR-NO-RTTI +// RUN: %clang -target x86_64-linux-gnu -fsanitize=undefined -fno-rtti %s -c -o - 2>&1 | FileCheck %s --check-prefix=CHECK-VPTR-NO-RTTI +// CHECK-VPTR-NO-RTTI: '-fsanitize=vptr' not allowed with 'fno-rtti' + +// RUN: %clang -target x86_64-linux-gnu -fsanitize=address,thread -fno-rtti %s -c -o - 2>&1 | FileCheck %s --check-prefix=CHECK-SANA-SANT +// CHECK-SANA-SANT: '-fsanitize=address' not allowed with '-fsanitize=thread' + +// RUN: %clang -target x86_64-linux-gnu -faddress-sanitizer -fthread-sanitizer -fno-rtti %s -c -o - 2>&1 | FileCheck %s --check-prefix=CHECK-ASAN-TSAN +// CHECK-ASAN-TSAN: 'faddress-sanitizer' not allowed with 'fthread-sanitizer' diff --git a/test/Driver/tsan.c b/test/Driver/tsan.c index 1dadb8ea26..e454e4e785 100644 --- a/test/Driver/tsan.c +++ b/test/Driver/tsan.c @@ -2,6 +2,7 @@ // RUN: %clang -O1 -target i386-unknown-unknown -fthread-sanitizer %s -S -emit-llvm -o - | FileCheck %s // RUN: %clang -O2 -target i386-unknown-unknown -fthread-sanitizer %s -S -emit-llvm -o - | FileCheck %s // RUN: %clang -O3 -target i386-unknown-unknown -fthread-sanitizer %s -S -emit-llvm -o - | FileCheck %s +// RUN: %clang -target i386-unknown-unknown -fsanitize=thread %s -S -emit-llvm -o - | FileCheck %s // Verify that -fthread-sanitizer invokes tsan instrumentation. int foo(int *a) { return *a; } |