[cfe-commits] r168794 - in /cfe/trunk: lib/Driver/SanitizerArgs.h lib/Driver/Tools.cpp test/Driver/fsanitize.c

Alexey Samsonov samsonov at google.com
Wed Nov 28 09:34:25 PST 2012


Author: samsonov
Date: Wed Nov 28 11:34:24 2012
New Revision: 168794

URL: http://llvm.org/viewvc/llvm-project?rev=168794&view=rev
Log:
Refactor -fsanitize, -f*-sanitizer arguments parsing. Provide a more careful diagnostic for invalid sets of sanitizers

Modified:
    cfe/trunk/lib/Driver/SanitizerArgs.h
    cfe/trunk/lib/Driver/Tools.cpp
    cfe/trunk/test/Driver/fsanitize.c

Modified: cfe/trunk/lib/Driver/SanitizerArgs.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/SanitizerArgs.h?rev=168794&r1=168793&r2=168794&view=diff
==============================================================================
--- cfe/trunk/lib/Driver/SanitizerArgs.h (original)
+++ cfe/trunk/lib/Driver/SanitizerArgs.h Wed Nov 28 11:34:24 2012
@@ -71,18 +71,78 @@
 
   /// Parse a -fsanitize= or -fno-sanitize= argument's values, diagnosing any
   /// invalid components.
-  static unsigned parse(const Driver &D, const Arg *A) {
+  static unsigned parse(const Driver &D, const Arg *A, bool DiagnoseErrors) {
     unsigned Kind = 0;
     for (unsigned I = 0, N = A->getNumValues(); I != N; ++I) {
       if (unsigned K = parse(A->getValue(I)))
         Kind |= K;
-      else
+      else if (DiagnoseErrors)
         D.Diag(diag::err_drv_unsupported_option_argument)
           << A->getOption().getName() << A->getValue(I);
     }
     return Kind;
   }
 
+  /// Parse a single flag of the form -f[no]sanitize=, or
+  /// -f*-sanitizer. Sets the masks defining required change of Kind value.
+  /// Returns true if the flag was parsed successfully.
+  static bool parse(const Driver &D, const ArgList &Args, const Arg *A,
+                    unsigned &Add, unsigned &Remove, bool DiagnoseErrors) {
+    Add = 0;
+    Remove = 0;
+    const char *DeprecatedReplacement = 0;
+    if (A->getOption().matches(options::OPT_faddress_sanitizer)) {
+      Add = Address;
+      DeprecatedReplacement = "-fsanitize=address";
+    } else if (A->getOption().matches(options::OPT_fno_address_sanitizer)) {
+      Remove = Address;
+      DeprecatedReplacement = "-fno-sanitize=address";
+    } else if (A->getOption().matches(options::OPT_fthread_sanitizer)) {
+      Add = Thread;
+      DeprecatedReplacement = "-fsanitize=thread";
+    } else if (A->getOption().matches(options::OPT_fno_thread_sanitizer)) {
+      Remove = Thread;
+      DeprecatedReplacement = "-fno-sanitize=thread";
+    } else if (A->getOption().matches(options::OPT_fcatch_undefined_behavior)) {
+      Add = Undefined;
+      DeprecatedReplacement = "-fsanitize=undefined";
+    } else if (A->getOption().matches(options::OPT_fbounds_checking) ||
+               A->getOption().matches(options::OPT_fbounds_checking_EQ)) {
+      Add = Bounds;
+      DeprecatedReplacement = "-fsanitize=bounds";
+    } else if (A->getOption().matches(options::OPT_fsanitize_EQ)) {
+      Add = parse(D, A, DiagnoseErrors);
+    } else if (A->getOption().matches(options::OPT_fno_sanitize_EQ)) {
+      Remove = parse(D, A, DiagnoseErrors);
+    } else {
+      // Flag is not relevant to sanitizers.
+      return false;
+    }
+    // If this is a deprecated synonym, produce a warning directing users
+    // towards the new spelling.
+    if (DeprecatedReplacement && DiagnoseErrors)
+      D.Diag(diag::warn_drv_deprecated_arg)
+        << A->getAsString(Args) << DeprecatedReplacement;
+    return true;
+  }
+
+  /// Produce an argument string from ArgList \p Args, which shows how it
+  /// provides a sanitizer kind in \p Mask. For example, the argument list
+  /// "-fsanitize=thread,vptr -faddress-sanitizer" with mask \c NeedsUbsanRt
+  /// would produce "-fsanitize=vptr".
+  static std::string lastArgumentForKind(const Driver &D, const ArgList &Args,
+                                         unsigned Kind) {
+    for (ArgList::const_reverse_iterator I = Args.rbegin(), E = Args.rend();
+         I != E; ++I) {
+      unsigned Add, Remove;
+      if (parse(D, Args, *I, Add, Remove, false) &&
+          (Add & Kind))
+        return describeSanitizeArg(Args, *I, Kind);
+      Kind &= ~Remove;
+    }
+    llvm_unreachable("arg list didn't provide expected value");
+  }
+
   /// 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

Modified: cfe/trunk/lib/Driver/Tools.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/Tools.cpp?rev=168794&r1=168793&r2=168794&view=diff
==============================================================================
--- cfe/trunk/lib/Driver/Tools.cpp (original)
+++ cfe/trunk/lib/Driver/Tools.cpp Wed Nov 28 11:34:24 2012
@@ -1456,51 +1456,13 @@
 SanitizerArgs::SanitizerArgs(const Driver &D, const ArgList &Args) {
   Kind = 0;
 
-  const Arg *AsanArg, *TsanArg, *UbsanArg;
   for (ArgList::const_iterator I = Args.begin(), E = Args.end(); I != E; ++I) {
-    unsigned Add = 0, Remove = 0;
-    const char *DeprecatedReplacement = 0;
-    if ((*I)->getOption().matches(options::OPT_faddress_sanitizer)) {
-      Add = Address;
-      DeprecatedReplacement = "-fsanitize=address";
-    } else if ((*I)->getOption().matches(options::OPT_fno_address_sanitizer)) {
-      Remove = Address;
-      DeprecatedReplacement = "-fno-sanitize=address";
-    } else if ((*I)->getOption().matches(options::OPT_fthread_sanitizer)) {
-      Add = Thread;
-      DeprecatedReplacement = "-fsanitize=thread";
-    } else if ((*I)->getOption().matches(options::OPT_fno_thread_sanitizer)) {
-      Remove = Thread;
-      DeprecatedReplacement = "-fno-sanitize=thread";
-    } else if ((*I)->getOption().matches(options::OPT_fcatch_undefined_behavior)) {
-      Add = Undefined;
-      DeprecatedReplacement = "-fsanitize=undefined";
-    } else if ((*I)->getOption().matches(options::OPT_fsanitize_EQ)) {
-      Add = parse(D, *I);
-    } else if ((*I)->getOption().matches(options::OPT_fno_sanitize_EQ)) {
-      Remove = parse(D, *I);
-    } else if ((*I)->getOption().matches(options::OPT_fbounds_checking) ||
-               (*I)->getOption().matches(options::OPT_fbounds_checking_EQ)) {
-      Add = Bounds;
-      DeprecatedReplacement = "-fsanitize=bounds";
-    } else {
+    unsigned Add, Remove;
+    if (!parse(D, Args, *I, Add, Remove, true))
       continue;
-    }
-
     (*I)->claim();
-
     Kind |= Add;
     Kind &= ~Remove;
-
-    if (Add & NeedsAsanRt) AsanArg = *I;
-    if (Add & NeedsTsanRt) TsanArg = *I;
-    if (Add & 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.
@@ -1510,10 +1472,8 @@
   bool NeedsUbsan = needsUbsanRt();
   if (NeedsAsan + NeedsTsan + NeedsUbsan > 1)
     D.Diag(diag::err_drv_argument_not_allowed_with)
-      << describeSanitizeArg(Args, NeedsAsan ? AsanArg : TsanArg,
-                             NeedsAsan ? NeedsAsanRt : NeedsTsanRt)
-      << describeSanitizeArg(Args, NeedsUbsan ? UbsanArg : TsanArg,
-                             NeedsUbsan ? NeedsUbsanRt : NeedsTsanRt);
+      << lastArgumentForKind(D, Args, NeedsAsan ? NeedsAsanRt : NeedsTsanRt)
+      << lastArgumentForKind(D, Args, NeedsUbsan ? NeedsUbsanRt : NeedsTsanRt);
 }
 
 /// If AddressSanitizer is enabled, add appropriate linker flags (Linux).

Modified: cfe/trunk/test/Driver/fsanitize.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Driver/fsanitize.c?rev=168794&r1=168793&r2=168794&view=diff
==============================================================================
--- cfe/trunk/test/Driver/fsanitize.c (original)
+++ cfe/trunk/test/Driver/fsanitize.c Wed Nov 28 11:34:24 2012
@@ -20,6 +20,12 @@
 // RUN: %clang -target x86_64-linux-gnu -faddress-sanitizer -fthread-sanitizer -fno-rtti %s -c -o /dev/null 2>&1 | FileCheck %s --check-prefix=CHECK-ASAN-TSAN
 // CHECK-ASAN-TSAN: '-faddress-sanitizer' not allowed with '-fthread-sanitizer'
 
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=address -fsanitize=alignment -fsanitize=vptr -fno-sanitize=vptr %s -c -o /dev/null 2>&1 | FileCheck %s --check-prefix=CHECK-UBSAN-ASAN
+// CHECK-UBSAN-ASAN: '-fsanitize=address' not allowed with '-fsanitize=alignment'
+
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=vptr -fno-sanitize=vptr -fsanitize=undefined,address %s -c -o /dev/null 2>&1 | FileCheck %s --check-prefix=CHECK-VPTR-UBSAN-ASAN
+// CHECK-VPTR-UBSAN-ASAN: '-fsanitize=address' not allowed with '-fsanitize=undefined'
+
 // RUN: %clang -target x86_64-linux-gnu -fcatch-undefined-behavior -fthread-sanitizer -fno-thread-sanitizer -faddress-sanitizer -fno-address-sanitizer -fbounds-checking -c -o /dev/null %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





More information about the cfe-commits mailing list