Index: cfe/trunk/include/clang/Driver/Driver.h =================================================================== --- cfe/trunk/include/clang/Driver/Driver.h +++ cfe/trunk/include/clang/Driver/Driver.h @@ -179,9 +179,6 @@ /// stored in it, and will clean them up when torn down. mutable llvm::StringMap ToolChains; - /// Parsed arguments passed to sanitizer tools. - mutable llvm::OwningPtr SanitizerArguments; - private: /// TranslateInputArgs - Create a new derived argument list from the input /// arguments, after applying the standard argument translations. @@ -406,10 +403,6 @@ std::pair getIncludeExcludeOptionFlagMasks() const; public: - /// \brief Returns parsed arguments to sanitizer tools. - const SanitizerArgs & - getOrParseSanitizerArgs(const llvm::opt::ArgList &Args) const; - /// GetReleaseVersion - Parse (([0-9]+)(.([0-9]+)(.([0-9]+)?))?)? and /// return the grouped values as integers. Numbers which are not /// provided are set to 0. Index: cfe/trunk/include/clang/Driver/SanitizerArgs.h =================================================================== --- cfe/trunk/include/clang/Driver/SanitizerArgs.h +++ cfe/trunk/include/clang/Driver/SanitizerArgs.h @@ -25,6 +25,7 @@ /// bit positions within \c Kind. enum SanitizeOrdinal { #define SANITIZER(NAME, ID) SO_##ID, +#define SANITIZER_GROUP(NAME, ID, ALIAS) SO_##ID##Group, #include "clang/Basic/Sanitizers.def" SO_Count }; @@ -32,7 +33,8 @@ /// Bugs to catch at runtime. enum SanitizeKind { #define SANITIZER(NAME, ID) ID = 1 << SO_##ID, -#define SANITIZER_GROUP(NAME, ID, ALIAS) ID = ALIAS, +#define SANITIZER_GROUP(NAME, ID, ALIAS) \ + ID = ALIAS, ID##Group = 1 << SO_##ID##Group, #include "clang/Basic/Sanitizers.def" NeedsAsanRt = Address, NeedsTsanRt = Thread, @@ -47,17 +49,13 @@ std::string BlacklistFile; bool MsanTrackOrigins; - enum AsanZeroBaseShadowKind { - AZBSK_Default, // Default value is toolchain-specific. - AZBSK_On, - AZBSK_Off - } AsanZeroBaseShadow; + bool AsanZeroBaseShadow; bool UbsanTrapOnError; public: SanitizerArgs(); /// Parses the sanitizer arguments from an argument list. - SanitizerArgs(const Driver &D, const llvm::opt::ArgList &Args); + SanitizerArgs(const ToolChain &TC, const llvm::opt::ArgList &Args); bool needsAsanRt() const { return Kind & NeedsAsanRt; } bool needsTsanRt() const { return Kind & NeedsTsanRt; } @@ -73,17 +71,15 @@ bool sanitizesVptr() const { return Kind & Vptr; } bool notAllowedWithTrap() const { return Kind & NotAllowedWithTrap; } - bool hasZeroBaseShadow(const ToolChain &TC) const { - return (Kind & HasZeroBaseShadow) || hasAsanZeroBaseShadow(TC); + bool hasZeroBaseShadow() const { + return (Kind & HasZeroBaseShadow) || AsanZeroBaseShadow; } - void addArgs(const ToolChain &TC, const llvm::opt::ArgList &Args, + void addArgs(const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs) const; private: void clear(); - bool hasAsanZeroBaseShadow(const ToolChain &TC) const; - /// Parse a single value from a -fsanitize= or -fno-sanitize= value list. /// Returns OR of members of the \c SanitizeKind enumeration, or \c 0 /// if \p Value is not known. @@ -119,6 +115,30 @@ static bool getDefaultBlacklistForKind(const Driver &D, unsigned Kind, std::string &BLPath); + + /// Return the smallest superset of sanitizer set \p Kinds such that each + /// member of each group whose flag is set in \p Kinds has its flag set in the + /// result. + static unsigned expandGroups(unsigned Kinds); + + /// Return the subset of \p Kinds supported by toolchain \p TC. If + /// \p DiagnoseErrors is true, produce an error diagnostic for each sanitizer + /// removed from \p Kinds. + static unsigned filterUnsupportedKinds(const ToolChain &TC, unsigned Kinds, + const llvm::opt::ArgList &Args, + const llvm::opt::Arg *A, + bool DiagnoseErrors, + unsigned &DiagnosedKinds); + + /// The flags in \p Mask are unsupported by \p TC. If present in \p Kinds, + /// remove them and produce an error diagnostic referring to \p A if + /// \p DiagnoseErrors is true. + static void filterUnsupportedMask(const ToolChain &TC, unsigned &Kinds, + unsigned Mask, + const llvm::opt::ArgList &Args, + const llvm::opt::Arg *A, + bool DiagnoseErrors, + unsigned &DiagnosedKinds); }; } // namespace driver Index: cfe/trunk/include/clang/Driver/ToolChain.h =================================================================== --- cfe/trunk/include/clang/Driver/ToolChain.h +++ cfe/trunk/include/clang/Driver/ToolChain.h @@ -73,6 +73,8 @@ Tool *getLink() const; Tool *getClangAs() const; + mutable OwningPtr SanitizerArguments; + protected: ToolChain(const Driver &D, const llvm::Triple &T, const llvm::opt::ArgList &Args); Index: cfe/trunk/lib/Driver/Driver.cpp =================================================================== --- cfe/trunk/lib/Driver/Driver.cpp +++ cfe/trunk/lib/Driver/Driver.cpp @@ -16,7 +16,6 @@ #include "clang/Driver/DriverDiagnostic.h" #include "clang/Driver/Job.h" #include "clang/Driver/Options.h" -#include "clang/Driver/SanitizerArgs.h" #include "clang/Driver/Tool.h" #include "clang/Driver/ToolChain.h" #include "llvm/ADT/ArrayRef.h" @@ -2056,10 +2055,3 @@ return std::make_pair(IncludedFlagsBitmask, ExcludedFlagsBitmask); } - -const SanitizerArgs & -Driver::getOrParseSanitizerArgs(const ArgList &Args) const { - if (!SanitizerArguments.get()) - SanitizerArguments.reset(new SanitizerArgs(*this, Args)); - return *SanitizerArguments.get(); -} Index: cfe/trunk/lib/Driver/SanitizerArgs.cpp =================================================================== --- cfe/trunk/lib/Driver/SanitizerArgs.cpp +++ cfe/trunk/lib/Driver/SanitizerArgs.cpp @@ -25,7 +25,7 @@ Kind = 0; BlacklistFile = ""; MsanTrackOrigins = false; - AsanZeroBaseShadow = AZBSK_Default; + AsanZeroBaseShadow = false; UbsanTrapOnError = false; } @@ -33,18 +33,42 @@ clear(); } -SanitizerArgs::SanitizerArgs(const Driver &D, const llvm::opt::ArgList &Args) { +SanitizerArgs::SanitizerArgs(const ToolChain &TC, + const llvm::opt::ArgList &Args) { clear(); - unsigned AllKinds = 0; // All kinds of sanitizers that were turned on - // at least once (possibly, disabled further). - for (ArgList::const_iterator I = Args.begin(), E = Args.end(); I != E; ++I) { + unsigned AllAdd = 0; // All kinds of sanitizers that were turned on + // at least once (possibly, disabled further). + unsigned AllRemove = 0; // During the loop below, the accumulated set of + // sanitizers disabled by the current sanitizer + // argument or any argument after it. + unsigned DiagnosedKinds = 0; // All Kinds we have diagnosed up to now. + // Used to deduplicate diagnostics. + const Driver &D = TC.getDriver(); + for (ArgList::const_reverse_iterator I = Args.rbegin(), E = Args.rend(); + I != E; ++I) { unsigned Add, Remove; if (!parse(D, Args, *I, Add, Remove, true)) continue; (*I)->claim(); + + AllAdd |= expandGroups(Add); + AllRemove |= expandGroups(Remove); + + // Avoid diagnosing any sanitizer which is disabled later. + Add &= ~AllRemove; + // At this point we have not expanded groups, so any unsupported sanitizers + // in Add are those which have been explicitly enabled. Diagnose them. + Add = filterUnsupportedKinds(TC, Add, Args, *I, /*DiagnoseErrors=*/true, + DiagnosedKinds); + Add = expandGroups(Add); + // Group expansion may have enabled a sanitizer which is disabled later. + Add &= ~AllRemove; + // Silently discard any unsupported sanitizers implicitly enabled through + // group expansion. + Add = filterUnsupportedKinds(TC, Add, Args, *I, /*DiagnoseErrors=*/false, + DiagnosedKinds); + Kind |= Add; - Kind &= ~Remove; - AllKinds |= Add; } UbsanTrapOnError = @@ -107,7 +131,7 @@ // If -fsanitize contains extra features of ASan, it should also // explicitly contain -fsanitize=address (probably, turned off later in the // command line). - if ((Kind & AddressFull) != 0 && (AllKinds & Address) == 0) + if ((Kind & AddressFull) != 0 && (AllAdd & Address) == 0) D.Diag(diag::warn_drv_unused_sanitizer) << lastArgumentForKind(D, Args, AddressFull) << "-fsanitize=address"; @@ -148,21 +172,25 @@ // Parse -f(no-)sanitize-address-zero-base-shadow options. if (NeedsAsan) { - if (Arg *A = Args.getLastArg( - options::OPT_fsanitize_address_zero_base_shadow, - options::OPT_fno_sanitize_address_zero_base_shadow)) - AsanZeroBaseShadow = A->getOption().matches( - options::OPT_fsanitize_address_zero_base_shadow) - ? AZBSK_On - : AZBSK_Off; + bool IsAndroid = (TC.getTriple().getEnvironment() == llvm::Triple::Android); + bool ZeroBaseShadowDefault = IsAndroid; + AsanZeroBaseShadow = + Args.hasFlag(options::OPT_fsanitize_address_zero_base_shadow, + options::OPT_fno_sanitize_address_zero_base_shadow, + ZeroBaseShadowDefault); + // Zero-base shadow is a requirement on Android. + if (IsAndroid && !AsanZeroBaseShadow) { + D.Diag(diag::err_drv_argument_not_allowed_with) + << "-fno-sanitize-address-zero-base-shadow" + << lastArgumentForKind(D, Args, Address); + } } } -void SanitizerArgs::addArgs(const ToolChain &TC, const llvm::opt::ArgList &Args, +void SanitizerArgs::addArgs(const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs) const { if (!Kind) return; - const Driver &D = TC.getDriver(); SmallString<256> SanitizeOpt("-fsanitize="); #define SANITIZER(NAME, ID) \ if (Kind & ID) \ @@ -179,36 +207,19 @@ if (MsanTrackOrigins) CmdArgs.push_back(Args.MakeArgString("-fsanitize-memory-track-origins")); - if (needsAsanRt()) { - if (hasAsanZeroBaseShadow(TC)) { - CmdArgs.push_back( - Args.MakeArgString("-fsanitize-address-zero-base-shadow")); - } else if (TC.getTriple().getEnvironment() == llvm::Triple::Android) { - // Zero-base shadow is a requirement on Android. - D.Diag(diag::err_drv_argument_not_allowed_with) - << "-fno-sanitize-address-zero-base-shadow" - << lastArgumentForKind(D, Args, Address); - } - } + if (AsanZeroBaseShadow) + CmdArgs.push_back( + Args.MakeArgString("-fsanitize-address-zero-base-shadow")); // Workaround for PR16386. if (needsMsanRt()) CmdArgs.push_back(Args.MakeArgString("-fno-assume-sane-operator-new")); } -bool SanitizerArgs::hasAsanZeroBaseShadow(const ToolChain &TC) const { - if (!needsAsanRt()) - return false; - if (AsanZeroBaseShadow != AZBSK_Default) - return AsanZeroBaseShadow == AZBSK_On; - // Zero-base shadow is used by default only on Android. - return TC.getTriple().getEnvironment() == llvm::Triple::Android; -} - unsigned SanitizerArgs::parse(const char *Value) { unsigned ParsedKind = llvm::StringSwitch(Value) #define SANITIZER(NAME, ID) .Case(NAME, ID) -#define SANITIZER_GROUP(NAME, ID, ALIAS) .Case(NAME, ID) +#define SANITIZER_GROUP(NAME, ID, ALIAS) .Case(NAME, ID##Group) #include "clang/Basic/Sanitizers.def" .Default(SanitizeKind()); // Assume -fsanitize=address implies -fsanitize=init-order,use-after-return. @@ -219,6 +230,54 @@ return ParsedKind; } +unsigned SanitizerArgs::expandGroups(unsigned Kinds) { +#define SANITIZER(NAME, ID) +#define SANITIZER_GROUP(NAME, ID, ALIAS) if (Kinds & ID##Group) Kinds |= ID; +#include "clang/Basic/Sanitizers.def" + return Kinds; +} + +void SanitizerArgs::filterUnsupportedMask(const ToolChain &TC, unsigned &Kinds, + unsigned Mask, + const llvm::opt::ArgList &Args, + const llvm::opt::Arg *A, + bool DiagnoseErrors, + unsigned &DiagnosedKinds) { + unsigned MaskedKinds = Kinds & Mask; + if (!MaskedKinds) + return; + Kinds &= ~Mask; + // Do we have new kinds to diagnose? + if (DiagnoseErrors && (DiagnosedKinds & MaskedKinds) != MaskedKinds) { + // Only diagnose the new kinds. + std::string Desc = + describeSanitizeArg(Args, A, MaskedKinds & ~DiagnosedKinds); + TC.getDriver().Diag(diag::err_drv_unsupported_opt_for_target) + << Desc << TC.getTriple().str(); + DiagnosedKinds |= MaskedKinds; + } +} + +unsigned SanitizerArgs::filterUnsupportedKinds(const ToolChain &TC, + unsigned Kinds, + const llvm::opt::ArgList &Args, + const llvm::opt::Arg *A, + bool DiagnoseErrors, + unsigned &DiagnosedKinds) { + bool IsLinux = TC.getTriple().getOS() == llvm::Triple::Linux; + bool IsX86 = TC.getTriple().getArch() == llvm::Triple::x86; + bool IsX86_64 = TC.getTriple().getArch() == llvm::Triple::x86_64; + if (!(IsLinux && IsX86_64)) { + filterUnsupportedMask(TC, Kinds, Thread | Memory | DataFlow, Args, A, + DiagnoseErrors, DiagnosedKinds); + } + if (!(IsLinux && (IsX86 || IsX86_64))) { + filterUnsupportedMask(TC, Kinds, Function, Args, A, DiagnoseErrors, + DiagnosedKinds); + } + return Kinds; +} + unsigned SanitizerArgs::parse(const Driver &D, const llvm::opt::Arg *A, bool DiagnoseErrors) { unsigned Kind = 0; @@ -282,7 +341,7 @@ I != E; ++I) { unsigned Add, Remove; if (parse(D, Args, *I, Add, Remove, false) && - (Add & Kind)) + (expandGroups(Add) & Kind)) return describeSanitizeArg(Args, *I, Kind); Kind &= ~Remove; } @@ -295,11 +354,17 @@ if (!A->getOption().matches(options::OPT_fsanitize_EQ)) return A->getAsString(Args); - for (unsigned I = 0, N = A->getNumValues(); I != N; ++I) - if (parse(A->getValue(I)) & Mask) - return std::string("-fsanitize=") + A->getValue(I); + std::string Sanitizers; + for (unsigned I = 0, N = A->getNumValues(); I != N; ++I) { + if (expandGroups(parse(A->getValue(I))) & Mask) { + if (!Sanitizers.empty()) + Sanitizers += ","; + Sanitizers += A->getValue(I); + } + } - llvm_unreachable("arg didn't provide expected value"); + assert(!Sanitizers.empty() && "arg didn't provide expected value"); + return "-fsanitize=" + Sanitizers; } bool SanitizerArgs::getDefaultBlacklistForKind(const Driver &D, unsigned Kind, Index: cfe/trunk/lib/Driver/ToolChain.cpp =================================================================== --- cfe/trunk/lib/Driver/ToolChain.cpp +++ cfe/trunk/lib/Driver/ToolChain.cpp @@ -13,6 +13,7 @@ #include "clang/Driver/Driver.h" #include "clang/Driver/DriverDiagnostic.h" #include "clang/Driver/Options.h" +#include "clang/Driver/SanitizerArgs.h" #include "clang/Driver/ToolChain.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/Option/Arg.h" @@ -43,7 +44,9 @@ } const SanitizerArgs& ToolChain::getSanitizerArgs() const { - return D.getOrParseSanitizerArgs(Args); + if (!SanitizerArguments.get()) + SanitizerArguments.reset(new SanitizerArgs(*this, Args)); + return *SanitizerArguments.get(); } std::string ToolChain::getDefaultUniversalArchName() const { Index: cfe/trunk/lib/Driver/ToolChains.cpp =================================================================== --- cfe/trunk/lib/Driver/ToolChains.cpp +++ cfe/trunk/lib/Driver/ToolChains.cpp @@ -300,10 +300,11 @@ } } - const SanitizerArgs &Sanitize = getDriver().getOrParseSanitizerArgs(Args); + const SanitizerArgs &Sanitize = getSanitizerArgs(); // Add Ubsan runtime library, if required. if (Sanitize.needsUbsanRt()) { + // FIXME: Move this check to SanitizerArgs::filterUnsupportedKinds. if (isTargetIPhoneOS()) { getDriver().Diag(diag::err_drv_clang_unsupported_per_platform) << "-fsanitize=undefined"; @@ -318,6 +319,7 @@ // Add ASAN runtime library, if required. Dynamic libraries and bundles // should not be linked with the runtime library. if (Sanitize.needsAsanRt()) { + // FIXME: Move this check to SanitizerArgs::filterUnsupportedKinds. if (isTargetIPhoneOS() && !isTargetIOSSimulator()) { getDriver().Diag(diag::err_drv_clang_unsupported_per_platform) << "-fsanitize=address"; @@ -2722,7 +2724,7 @@ } bool Linux::isPIEDefault() const { - return getSanitizerArgs().hasZeroBaseShadow(*this); + return getSanitizerArgs().hasZeroBaseShadow(); } /// DragonFly - DragonFly tool chain which can call as(1) and ld(1) directly. Index: cfe/trunk/lib/Driver/Tools.cpp =================================================================== --- cfe/trunk/lib/Driver/Tools.cpp +++ cfe/trunk/lib/Driver/Tools.cpp @@ -2942,8 +2942,8 @@ Args.AddLastArg(CmdArgs, options::OPT_fdiagnostics_show_template_tree); Args.AddLastArg(CmdArgs, options::OPT_fno_elide_type); - const SanitizerArgs &Sanitize = D.getOrParseSanitizerArgs(Args); - Sanitize.addArgs(getToolChain(), Args, CmdArgs); + const SanitizerArgs &Sanitize = getToolChain().getSanitizerArgs(); + Sanitize.addArgs(Args, CmdArgs); if (!Args.hasFlag(options::OPT_fsanitize_recover, options::OPT_fno_sanitize_recover, @@ -6188,10 +6188,10 @@ const Driver &D = ToolChain.getDriver(); const bool isAndroid = ToolChain.getTriple().getEnvironment() == llvm::Triple::Android; - const SanitizerArgs &Sanitize = D.getOrParseSanitizerArgs(Args); + const SanitizerArgs &Sanitize = ToolChain.getSanitizerArgs(); const bool IsPIE = !Args.hasArg(options::OPT_shared) && - (Args.hasArg(options::OPT_pie) || Sanitize.hasZeroBaseShadow(ToolChain)); + (Args.hasArg(options::OPT_pie) || Sanitize.hasZeroBaseShadow()); ArgStringList CmdArgs; @@ -6722,7 +6722,7 @@ ImplibName.str())); } - if (getToolChain().getDriver().getOrParseSanitizerArgs(Args).needsAsanRt()) { + if (getToolChain().getSanitizerArgs().needsAsanRt()) { CmdArgs.push_back(Args.MakeArgString("-debug")); CmdArgs.push_back(Args.MakeArgString("-incremental:no")); SmallString<128> LibSanitizer(getToolChain().getDriver().ResourceDir); Index: cfe/trunk/test/Driver/fsanitize.c =================================================================== --- cfe/trunk/test/Driver/fsanitize.c +++ cfe/trunk/test/Driver/fsanitize.c @@ -7,6 +7,9 @@ // RUN: %clang -target x86_64-linux-gnu -fsanitize=undefined %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UNDEFINED // CHECK-UNDEFINED: "-fsanitize={{((signed-integer-overflow|integer-divide-by-zero|float-divide-by-zero|function|shift|unreachable|return|vla-bound|alignment|null|vptr|object-size|float-cast-overflow|array-bounds|enum|bool),?){16}"}} +// RUN: %clang -target x86_64-apple-darwin10 -fsanitize=undefined %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UNDEFINED-DARWIN +// CHECK-UNDEFINED-DARWIN: "-fsanitize={{((signed-integer-overflow|integer-divide-by-zero|float-divide-by-zero|shift|unreachable|return|vla-bound|alignment|null|vptr|object-size|float-cast-overflow|array-bounds|enum|bool),?){15}"}} + // RUN: %clang -target x86_64-linux-gnu -fsanitize=integer %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-INTEGER // CHECK-INTEGER: "-fsanitize={{((signed-integer-overflow|unsigned-integer-overflow|integer-divide-by-zero|shift),?){4}"}} @@ -96,12 +99,12 @@ // OK // RUN: %clang -target x86_64-linux-gnu -fcatch-undefined-behavior -fthread-sanitizer -fno-thread-sanitizer -faddress-sanitizer -fno-address-sanitizer -fbounds-checking -### %s 2>&1 | FileCheck %s --check-prefix=CHECK-DEPRECATED -// CHECK-DEPRECATED: argument '-fcatch-undefined-behavior' is deprecated, use '-fsanitize=undefined-trap -fsanitize-undefined-trap-on-error' instead -// CHECK-DEPRECATED: argument '-fthread-sanitizer' is deprecated, use '-fsanitize=thread' instead -// CHECK-DEPRECATED: argument '-fno-thread-sanitizer' is deprecated, use '-fno-sanitize=thread' instead -// CHECK-DEPRECATED: argument '-faddress-sanitizer' is deprecated, use '-fsanitize=address' instead -// CHECK-DEPRECATED: argument '-fno-address-sanitizer' is deprecated, use '-fno-sanitize=address' instead // CHECK-DEPRECATED: argument '-fbounds-checking' is deprecated, use '-fsanitize=local-bounds' instead +// CHECK-DEPRECATED: argument '-fno-address-sanitizer' is deprecated, use '-fno-sanitize=address' instead +// CHECK-DEPRECATED: argument '-faddress-sanitizer' is deprecated, use '-fsanitize=address' instead +// CHECK-DEPRECATED: argument '-fno-thread-sanitizer' is deprecated, use '-fno-sanitize=thread' instead +// CHECK-DEPRECATED: argument '-fthread-sanitizer' is deprecated, use '-fsanitize=thread' instead +// CHECK-DEPRECATED: argument '-fcatch-undefined-behavior' is deprecated, use '-fsanitize=undefined-trap -fsanitize-undefined-trap-on-error' instead // RUN: %clang -target x86_64-linux-gnu -fsanitize=thread %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-TSAN-NO-PIE // CHECK-TSAN-NO-PIE: "-mrelocation-model" "pic" "-pic-level" "2" "-pie-level" "2" @@ -152,3 +155,27 @@ // RUN: %clang -target x86_64-linux-gnu -fsanitize=zzz %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-DIAG1 // CHECK-DIAG1: unsupported argument 'zzz' to option 'fsanitize=' // CHECK-DIAG1-NOT: unsupported argument 'zzz' to option 'fsanitize=' + +// RUN: %clang -target i686-linux-gnu -fsanitize=memory %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-MSAN-X86 +// CHECK-MSAN-X86: error: unsupported option '-fsanitize=memory' for target 'i686--linux-gnu' + +// RUN: %clang -target x86_64-apple-darwin10 -fsanitize=memory %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-MSAN-DARWIN +// CHECK-MSAN-DARWIN: unsupported option '-fsanitize=memory' for target 'x86_64-apple-darwin10' + +// RUN: %clang -target x86_64-apple-darwin10 -fsanitize=memory -fno-sanitize=memory %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-MSAN-NOMSAN-DARWIN +// CHECK-MSAN-NOMSAN-DARWIN-NOT: unsupported option + +// RUN: %clang -target x86_64-apple-darwin10 -fsanitize=memory -fsanitize=thread,memory %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-MSAN-TSAN-MSAN-DARWIN +// CHECK-MSAN-TSAN-MSAN-DARWIN: unsupported option '-fsanitize=thread,memory' for target 'x86_64-apple-darwin10' +// CHECK-MSAN-TSAN-MSAN-DARWIN-NOT: unsupported option + +// RUN: %clang -target x86_64-apple-darwin10 -fsanitize=thread,memory -fsanitize=memory %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-TSAN-MSAN-MSAN-DARWIN +// CHECK-TSAN-MSAN-MSAN-DARWIN: unsupported option '-fsanitize=memory' for target 'x86_64-apple-darwin10' +// CHECK-TSAN-MSAN-MSAN-DARWIN: unsupported option '-fsanitize=thread' for target 'x86_64-apple-darwin10' +// CHECK-TSAN-MSAN-MSAN-DARWIN-NOT: unsupported option + +// 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' + +// RUN: %clang -target x86_64-apple-darwin10 -fsanitize=function -fsanitize=undefined %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-FSAN-UBSAN-DARWIN +// CHECK-FSAN-UBSAN-DARWIN: unsupported option '-fsanitize=function' for target 'x86_64-apple-darwin10' Index: cfe/trunk/test/Driver/tsan.c =================================================================== --- cfe/trunk/test/Driver/tsan.c +++ cfe/trunk/test/Driver/tsan.c @@ -1,8 +1,8 @@ -// RUN: %clang -target i386-unknown-unknown -fsanitize=thread %s -S -emit-llvm -o - | FileCheck %s -// RUN: %clang -O1 -target i386-unknown-unknown -fsanitize=thread %s -S -emit-llvm -o - | FileCheck %s -// RUN: %clang -O2 -target i386-unknown-unknown -fsanitize=thread %s -S -emit-llvm -o - | FileCheck %s -// RUN: %clang -O3 -target i386-unknown-unknown -fsanitize=thread %s -S -emit-llvm -o - | FileCheck %s -// RUN: %clang -target i386-unknown-unknown -fsanitize=thread %s -S -emit-llvm -o - | FileCheck %s +// RUN: %clang -target x86_64-unknown-linux -fsanitize=thread %s -S -emit-llvm -o - | FileCheck %s +// RUN: %clang -O1 -target x86_64-unknown-linux -fsanitize=thread %s -S -emit-llvm -o - | FileCheck %s +// RUN: %clang -O2 -target x86_64-unknown-linux -fsanitize=thread %s -S -emit-llvm -o - | FileCheck %s +// RUN: %clang -O3 -target x86_64-unknown-linux -fsanitize=thread %s -S -emit-llvm -o - | FileCheck %s +// RUN: %clang -target x86_64-unknown-linux -fsanitize=thread %s -S -emit-llvm -o - | FileCheck %s // Verify that -fsanitize=thread invokes tsan instrumentation. int foo(int *a) { return *a; }