diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td b/clang/include/clang/Basic/DiagnosticDriverKinds.td index 401d46a7c130..fe0be427a40b 100644 --- a/clang/include/clang/Basic/DiagnosticDriverKinds.td +++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td @@ -121,6 +121,8 @@ def warn_drv_empty_joined_argument : Warning< InGroup>; def warn_drv_clang_unsupported : Warning< "the clang compiler does not support '%0'">; +def warn_drv_deprecated_arg : Warning< + "argument '%0' is deprecated, use '%1' instead">, InGroup; def warn_drv_assuming_mfloat_abi_is : Warning< "unknown platform, assuming -mfloat-abi=%0">; def warn_ignoring_ftabstop_value : Warning< diff --git a/clang/lib/Driver/Tools.cpp b/clang/lib/Driver/Tools.cpp index 6ae24da49860..973df104d52e 100644 --- a/clang/lib/Driver/Tools.cpp +++ b/clang/lib/Driver/Tools.cpp @@ -1522,9 +1522,10 @@ struct SanitizerArgs { /// 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) { +static std::string describeSanitizeArg(const ArgList &Args, const Arg *A, + unsigned Mask) { if (!A->getOption().matches(options::OPT_fsanitize_EQ)) - return A->getOption().getName(); + return A->getAsString(Args); for (unsigned I = 0, N = A->getNumValues(); I != N; ++I) if (SanitizerArgs::parse(A->getValue(I)) & Mask) @@ -1541,22 +1542,29 @@ static SanitizerArgs getSanitizerArgs(const Driver &D, const ArgList &Args) { 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)) + const char *DeprecatedReplacement = 0; + if ((*I)->getOption().matches(options::OPT_faddress_sanitizer)) { Add = SanitizerArgs::Address; - else if ((*I)->getOption().matches(options::OPT_fno_address_sanitizer)) + DeprecatedReplacement = "-fsanitize=address"; + } else if ((*I)->getOption().matches(options::OPT_fno_address_sanitizer)) { Remove = SanitizerArgs::Address; - else if ((*I)->getOption().matches(options::OPT_fthread_sanitizer)) + DeprecatedReplacement = "-fno-sanitize=address"; + } else if ((*I)->getOption().matches(options::OPT_fthread_sanitizer)) { Add = SanitizerArgs::Thread; - else if ((*I)->getOption().matches(options::OPT_fno_thread_sanitizer)) + DeprecatedReplacement = "-fsanitize=thread"; + } else if ((*I)->getOption().matches(options::OPT_fno_thread_sanitizer)) { Remove = SanitizerArgs::Thread; - else if ((*I)->getOption().matches(options::OPT_fcatch_undefined_behavior)) + DeprecatedReplacement = "-fno-sanitize=thread"; + } else if ((*I)->getOption().matches(options::OPT_fcatch_undefined_behavior)) { Add = SanitizerArgs::Undefined; - else if ((*I)->getOption().matches(options::OPT_fsanitize_EQ)) + DeprecatedReplacement = "-fsanitize=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)) + } else if ((*I)->getOption().matches(options::OPT_fno_sanitize_EQ)) { Remove = SanitizerArgs::parse(D, *I); - else + } else { continue; + } (*I)->claim(); @@ -1566,6 +1574,12 @@ static SanitizerArgs getSanitizerArgs(const Driver &D, const ArgList &Args) { if (Add & SanitizerArgs::NeedsAsanRt) AsanArg = *I; if (Add & SanitizerArgs::NeedsTsanRt) TsanArg = *I; if (Add & SanitizerArgs::NeedsUbsanRt) UbsanArg = *I; + + // If this is a deprecated synonym, produce a warning directing users + // towards the new spelling. + if (DeprecatedReplacement) + D.Diag(diag::warn_drv_deprecated_arg) + << (*I)->getAsString(Args) << DeprecatedReplacement; } // Only one runtime library can be used at once. @@ -1575,10 +1589,10 @@ static SanitizerArgs getSanitizerArgs(const Driver &D, const ArgList &Args) { bool NeedsUbsan = Sanitize.needsUbsanRt(); if (NeedsAsan + NeedsTsan + NeedsUbsan > 1) D.Diag(diag::err_drv_argument_not_allowed_with) - << describeSanitizeArg(NeedsAsan ? AsanArg : TsanArg, + << describeSanitizeArg(Args, NeedsAsan ? AsanArg : TsanArg, NeedsAsan ? SanitizerArgs::NeedsAsanRt : SanitizerArgs::NeedsTsanRt) - << describeSanitizeArg(NeedsUbsan ? UbsanArg : TsanArg, + << describeSanitizeArg(Args, NeedsUbsan ? UbsanArg : TsanArg, NeedsUbsan ? SanitizerArgs::NeedsUbsanRt : SanitizerArgs::NeedsTsanRt); @@ -2671,7 +2685,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, llvm::StringRef NoRttiArg = Args.getLastArg(options::OPT_mkernel, options::OPT_fapple_kext, - options::OPT_fno_rtti)->getOption().getName(); + options::OPT_fno_rtti)->getAsString(Args); D.Diag(diag::err_drv_argument_not_allowed_with) << "-fsanitize=vptr" << NoRttiArg; } diff --git a/clang/test/Driver/fsanitize.c b/clang/test/Driver/fsanitize.c index 047892a6a2a4..63cb92641454 100644 --- a/clang/test/Driver/fsanitize.c +++ b/clang/test/Driver/fsanitize.c @@ -7,10 +7,17 @@ // 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' +// 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' +// CHECK-ASAN-TSAN: '-faddress-sanitizer' not allowed with '-fthread-sanitizer' + +// RUN: %clang -target x86_64-linux-gnu -fcatch-undefined-behavior -fthread-sanitizer -fno-thread-sanitizer -faddress-sanitizer -fno-address-sanitizer -c -o - %s 2>&1 | FileCheck %s --check-prefix=CHECK-DEPRECATED +// CHECK-DEPRECATED: argument '-fcatch-undefined-behavior' is deprecated, use '-fsanitize=undefined' 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