r222105 - [Sanitizer] Parse and produce all sanitizer-relevant arguments in SanitizerArgs.

Alexey Samsonov vonosmas at gmail.com
Sun Nov 16 12:53:53 PST 2014


Author: samsonov
Date: Sun Nov 16 14:53:53 2014
New Revision: 222105

URL: http://llvm.org/viewvc/llvm-project?rev=222105&view=rev
Log:
[Sanitizer] Parse and produce all sanitizer-relevant arguments in SanitizerArgs.

In particular, make SanitizerArgs responsible for parsing
and passing down to frontend -fsanitize-recover and
-fsanitize-undefined-trap-on-error flags.

Simplify parsing -f(no-)sanitize= flags parsing: get rid of
too complex filterUnsupportedKinds function.

No functionality change.

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

Modified: cfe/trunk/include/clang/Driver/SanitizerArgs.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Driver/SanitizerArgs.h?rev=222105&r1=222104&r2=222105&view=diff
==============================================================================
--- cfe/trunk/include/clang/Driver/SanitizerArgs.h (original)
+++ cfe/trunk/include/clang/Driver/SanitizerArgs.h Sun Nov 16 14:53:53 2014
@@ -22,6 +22,8 @@ class ToolChain;
 
 class SanitizerArgs {
   SanitizerSet Sanitizers;
+  bool SanitizeRecover;
+
   std::string BlacklistFile;
   int SanitizeCoverage;
   int MsanTrackOrigins;

Modified: cfe/trunk/lib/Driver/SanitizerArgs.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/SanitizerArgs.cpp?rev=222105&r1=222104&r2=222105&view=diff
==============================================================================
--- cfe/trunk/lib/Driver/SanitizerArgs.cpp (original)
+++ cfe/trunk/lib/Driver/SanitizerArgs.cpp Sun Nov 16 14:53:53 2014
@@ -109,17 +109,32 @@ static std::string lastArgumentForKind(c
 /// "-fsanitize=alignment".
 static std::string describeSanitizeArg(const llvm::opt::Arg *A, unsigned Mask);
 
+/// Produce a string containing comma-separated names of sanitizers in \p
+/// Sanitizers set.
+static std::string toString(const clang::SanitizerSet &Sanitizers);
+
 /// For each sanitizer group bit set in \p Kinds, set the bits for sanitizers
 /// this group enables.
 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::Arg *A,
-                                       bool DiagnoseErrors,
-                                       unsigned &DiagnosedKinds);
+static unsigned getToolchainUnsupportedKinds(const ToolChain &TC) {
+  bool IsFreeBSD = TC.getTriple().getOS() == llvm::Triple::FreeBSD;
+  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;
+
+  unsigned Unsupported = 0;
+  if (!(IsLinux && IsX86_64)) {
+    Unsupported |= Memory | DataFlow;
+  }
+  if (!((IsLinux || IsFreeBSD) && IsX86_64)) {
+    Unsupported |= Thread;
+  }
+  if (!(IsLinux && (IsX86 || IsX86_64))) {
+    Unsupported |= Function;
+  }
+  return Unsupported;
+}
 
 bool SanitizerArgs::needsUbsanRt() const {
   return !UbsanTrapOnError && hasOneOf(Sanitizers, NeedsUbsanRt);
@@ -135,6 +150,7 @@ bool SanitizerArgs::needsUnwindTables()
 
 void SanitizerArgs::clear() {
   Sanitizers.clear();
+  SanitizeRecover = false;
   BlacklistFile = "";
   SanitizeCoverage = 0;
   MsanTrackOrigins = 0;
@@ -153,6 +169,8 @@ SanitizerArgs::SanitizerArgs(const ToolC
                            // argument or any argument after it.
   unsigned DiagnosedKinds = 0;  // All Kinds we have diagnosed up to now.
                                 // Used to deduplicate diagnostics.
+  unsigned Kinds = 0;
+  unsigned NotSupported = getToolchainUnsupportedKinds(TC);
   const Driver &D = TC.getDriver();
   for (ArgList::const_reverse_iterator I = Args.rbegin(), E = Args.rend();
        I != E; ++I) {
@@ -165,20 +183,31 @@ SanitizerArgs::SanitizerArgs(const ToolC
 
     // 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, *I, /*DiagnoseErrors=*/true,
-                                 DiagnosedKinds);
+    if (unsigned KindsToDiagnose = Add & NotSupported & ~DiagnosedKinds) {
+      // Only diagnose the new kinds.
+      std::string Desc = describeSanitizeArg(*I, KindsToDiagnose);
+      D.Diag(diag::err_drv_unsupported_opt_for_target) << Desc
+                                                       << TC.getTriple().str();
+      DiagnosedKinds |= KindsToDiagnose;
+    }
+    Add &= ~NotSupported;
+
     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, *I, /*DiagnoseErrors=*/false,
-                                 DiagnosedKinds);
+    Add &= ~NotSupported;
 
-    addAllOf(Sanitizers, Add);
+    Kinds |= Add;
   }
+  addAllOf(Sanitizers, Kinds);
+
+  SanitizeRecover = Args.hasFlag(options::OPT_fsanitize_recover,
+                                 options::OPT_fno_sanitize_recover, true);
 
   UbsanTrapOnError =
     Args.hasFlag(options::OPT_fsanitize_undefined_trap_on_error,
@@ -316,17 +345,30 @@ SanitizerArgs::SanitizerArgs(const ToolC
       Args.hasArg(options::OPT_fsanitize_link_cxx_runtime) || D.CCCIsCXX();
 }
 
+static std::string toString(const clang::SanitizerSet &Sanitizers) {
+  std::string Res;
+#define SANITIZER(NAME, ID)                                                    \
+  if (Sanitizers.has(clang::SanitizerKind::ID)) {                              \
+    if (!Res.empty())                                                          \
+      Res += ",";                                                              \
+    Res += NAME;                                                               \
+  }
+#include "clang/Basic/Sanitizers.def"
+  return Res;
+}
+
 void SanitizerArgs::addArgs(const llvm::opt::ArgList &Args,
                             llvm::opt::ArgStringList &CmdArgs) const {
   if (Sanitizers.empty())
     return;
-  SmallString<256> SanitizeOpt("-fsanitize=");
-#define SANITIZER(NAME, ID) \
-  if (Sanitizers.has(SanitizerKind::ID)) \
-    SanitizeOpt += NAME ",";
-#include "clang/Basic/Sanitizers.def"
-  SanitizeOpt.pop_back();
-  CmdArgs.push_back(Args.MakeArgString(SanitizeOpt));
+  CmdArgs.push_back(Args.MakeArgString("-fsanitize=" + toString(Sanitizers)));
+
+  if (!SanitizeRecover)
+    CmdArgs.push_back("-fno-sanitize-recover");
+
+  if (UbsanTrapOnError)
+    CmdArgs.push_back("-fsanitize-undefined-trap-on-error");
+
   if (!BlacklistFile.empty()) {
     SmallString<64> BlacklistOpt("-fsanitize-blacklist=");
     BlacklistOpt += BlacklistFile;
@@ -383,39 +425,6 @@ unsigned expandGroups(unsigned Kinds) {
   return Kinds;
 }
 
-unsigned filterUnsupportedKinds(const ToolChain &TC, unsigned Kinds,
-                                const llvm::opt::Arg *A, bool DiagnoseErrors,
-                                unsigned &DiagnosedKinds) {
-  bool IsFreeBSD = TC.getTriple().getOS() == llvm::Triple::FreeBSD;
-  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;
-
-  unsigned KindsToFilterOut = 0;
-  if (!(IsLinux && IsX86_64)) {
-    KindsToFilterOut |= Memory | DataFlow;
-  }
-  if (!((IsLinux || IsFreeBSD) && IsX86_64)) {
-    KindsToFilterOut |= Thread;
-  }
-  if (!(IsLinux && (IsX86 || IsX86_64))) {
-    KindsToFilterOut |= Function;
-  }
-  KindsToFilterOut &= Kinds;
-
-  // Do we have new kinds to diagnose?
-  unsigned KindsToDiagnose = KindsToFilterOut & ~DiagnosedKinds;
-  if (DiagnoseErrors && KindsToDiagnose) {
-    // Only diagnose the new kinds.
-    std::string Desc = describeSanitizeArg(A, KindsToDiagnose);
-    TC.getDriver().Diag(clang::diag::err_drv_unsupported_opt_for_target)
-        << Desc << TC.getTriple().str();
-    DiagnosedKinds |= KindsToFilterOut;
-  }
-
-  return Kinds & ~KindsToFilterOut;
-}
-
 unsigned parseArgValues(const Driver &D, const llvm::opt::Arg *A,
                         bool DiagnoseErrors) {
   unsigned Kind = 0;

Modified: cfe/trunk/lib/Driver/Tools.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/Tools.cpp?rev=222105&r1=222104&r2=222105&view=diff
==============================================================================
--- cfe/trunk/lib/Driver/Tools.cpp (original)
+++ cfe/trunk/lib/Driver/Tools.cpp Sun Nov 16 14:53:53 2014
@@ -3625,15 +3625,6 @@ void Clang::ConstructJob(Compilation &C,
   const SanitizerArgs &Sanitize = getToolChain().getSanitizerArgs();
   Sanitize.addArgs(Args, CmdArgs);
 
-  if (!Args.hasFlag(options::OPT_fsanitize_recover,
-                    options::OPT_fno_sanitize_recover,
-                    true))
-    CmdArgs.push_back("-fno-sanitize-recover");
-
-  if (Args.hasFlag(options::OPT_fsanitize_undefined_trap_on_error,
-                   options::OPT_fno_sanitize_undefined_trap_on_error, false))
-    CmdArgs.push_back("-fsanitize-undefined-trap-on-error");
-
   // Report an error for -faltivec on anything other than PowerPC.
   if (const Arg *A = Args.getLastArg(options::OPT_faltivec))
     if (!(getToolChain().getArch() == llvm::Triple::ppc ||

Modified: cfe/trunk/test/Driver/fsanitize.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Driver/fsanitize.c?rev=222105&r1=222104&r2=222105&view=diff
==============================================================================
--- cfe/trunk/test/Driver/fsanitize.c (original)
+++ cfe/trunk/test/Driver/fsanitize.c Sun Nov 16 14:53:53 2014
@@ -119,11 +119,11 @@
 // RUN: %clang -target arm-linux-androideabi %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-ANDROID-NO-ASAN
 // CHECK-ANDROID-NO-ASAN: "-mrelocation-model" "pic"
 
-// RUN: %clang -target x86_64-linux-gnu %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-RECOVER
-// RUN: %clang -target x86_64-linux-gnu %s -fsanitize-recover -### 2>&1 | FileCheck %s --check-prefix=CHECK-RECOVER
-// RUN: %clang -target x86_64-linux-gnu %s -fno-sanitize-recover -### 2>&1 | FileCheck %s --check-prefix=CHECK-NO-RECOVER
-// RUN: %clang -target x86_64-linux-gnu %s -fno-sanitize-recover -fsanitize-recover -### 2>&1 | FileCheck %s --check-prefix=CHECK-RECOVER
-// RUN: %clang -target x86_64-linux-gnu %s -fsanitize-recover -fno-sanitize-recover -### 2>&1 | FileCheck %s --check-prefix=CHECK-NO-RECOVER
+// RUN: %clang -target x86_64-linux-gnu %s -fsanitize=undefined -### 2>&1 | FileCheck %s --check-prefix=CHECK-RECOVER
+// RUN: %clang -target x86_64-linux-gnu %s -fsanitize=undefined -fsanitize-recover -### 2>&1 | FileCheck %s --check-prefix=CHECK-RECOVER
+// RUN: %clang -target x86_64-linux-gnu %s -fsanitize=undefined -fno-sanitize-recover -### 2>&1 | FileCheck %s --check-prefix=CHECK-NO-RECOVER
+// RUN: %clang -target x86_64-linux-gnu %s -fsanitize=undefined -fno-sanitize-recover -fsanitize-recover -### 2>&1 | FileCheck %s --check-prefix=CHECK-RECOVER
+// RUZ: %clang -target x86_64-linux-gnu %s -fsanitize=undefined -fsanitize-recover -fno-sanitize-recover -### 2>&1 | FileCheck %s --check-prefix=CHECK-NO-RECOVER
 // CHECK-RECOVER-NOT: sanitize-recover
 // CHECK-NO-RECOVER: "-fno-sanitize-recover"
 





More information about the cfe-commits mailing list