[clang] [sanitizer] Refactor -f(no-)?sanitize-recover parsing (PR #119819)

Thurston Dang via cfe-commits cfe-commits at lists.llvm.org
Tue Dec 17 10:52:53 PST 2024


================
@@ -247,48 +247,72 @@ static SanitizerMask setGroupBits(SanitizerMask Kinds) {
   return Kinds;
 }
 
-// Computes the sanitizer mask based on the default plus opt-in (if supported)
-// minus opt-out.
+// Computes the sanitizer mask as:
+//     Default + AlwaysIn + Arguments - AlwaysOut
+// with arguments parsed from left to right.
+//
+// Error messages are optionally printed if the AlwaysIn or AlwaysOut
+// invariants are violated.
 static SanitizerMask
 parseSanitizeArgs(const Driver &D, const llvm::opt::ArgList &Args,
-                  bool DiagnoseErrors, SanitizerMask Supported,
-                  SanitizerMask Default, int OptInID, int OptOutID) {
-  SanitizerMask Remove; // During the loop below, the accumulated set of
-                        // sanitizers disabled by the current sanitizer
-                        // argument or any argument after it.
-  SanitizerMask Kinds;
-  SanitizerMask SupportedWithGroups = setGroupBits(Supported);
-
-  for (const llvm::opt::Arg *Arg : llvm::reverse(Args)) {
+                  bool DiagnoseErrors, SanitizerMask Default,
+                  SanitizerMask AlwaysIn, SanitizerMask AlwaysOut, int OptInID,
+                  int OptOutID) {
+
+  SanitizerMask Output = Default | AlwaysIn;
+  // Keep track of which violations we have already reported, to avoid
+  // duplicate error messages.
+  SanitizerMask DiagnosedAlwaysInViolations;
+  SanitizerMask DiagnosedAlwaysOutViolations;
+  for (const auto *Arg : Args) {
     if (Arg->getOption().matches(OptInID)) {
-      Arg->claim();
-      SanitizerMask Add = parseArgValues(D, Arg, true);
-      Add &= ~Remove;
-      SanitizerMask InvalidValues = Add & ~SupportedWithGroups;
-      if (InvalidValues && DiagnoseErrors) {
-        SanitizerSet S;
-        S.Mask = InvalidValues;
-        D.Diag(diag::err_drv_unsupported_option_argument)
-            << Arg->getSpelling() << toString(S);
+      SanitizerMask Add = parseArgValues(D, Arg, DiagnoseErrors);
+      // Report error if user explicitly tries to opt-in to an always-out
+      // sanitizer.
+      if (SanitizerMask KindsToDiagnose =
+              Add & AlwaysOut & ~DiagnosedAlwaysOutViolations) {
+        if (DiagnoseErrors) {
+          SanitizerSet SetToDiagnose;
+          SetToDiagnose.Mask |= KindsToDiagnose;
+          D.Diag(diag::err_drv_unsupported_option_argument)
+              << Arg->getSpelling() << toString(SetToDiagnose);
+          DiagnosedAlwaysOutViolations |= KindsToDiagnose;
+        }
       }
-      Kinds |= expandSanitizerGroups(Add) & ~Remove;
+      Output |= expandSanitizerGroups(Add);
+      Arg->claim();
     } else if (Arg->getOption().matches(OptOutID)) {
+      SanitizerMask Remove = parseArgValues(D, Arg, DiagnoseErrors);
+      // Report error if user explicitly tries to opt-out of an always-in
+      // sanitizer.
+      if (SanitizerMask KindsToDiagnose =
+              Remove & AlwaysIn & ~DiagnosedAlwaysInViolations) {
+        if (DiagnoseErrors) {
+          SanitizerSet SetToDiagnose;
+          SetToDiagnose.Mask |= KindsToDiagnose;
+          D.Diag(diag::err_drv_unsupported_option_argument)
+              << Arg->getSpelling() << toString(SetToDiagnose);
+          DiagnosedAlwaysInViolations |= KindsToDiagnose;
+        }
+      }
+      Output &= ~expandSanitizerGroups(Remove);
       Arg->claim();
-      Remove |= expandSanitizerGroups(parseArgValues(D, Arg, DiagnoseErrors));
     }
   }
 
-  // Apply default behavior.
-  Kinds |= Default & ~Remove;
+  Output &= ~AlwaysOut;
----------------
thurstond wrote:

Done

https://github.com/llvm/llvm-project/pull/119819


More information about the cfe-commits mailing list