@@ -247,48 +247,72 @@ static SanitizerMask setGroupBits(SanitizerMask Kinds) {
247247 return Kinds;
248248}
249249
250- // Computes the sanitizer mask based on the default plus opt-in (if supported)
251- // minus opt-out.
250+ // Computes the sanitizer mask as:
251+ // Default + AlwaysIn + Arguments - AlwaysOut
252+ // with arguments parsed from left to right.
253+ //
254+ // Error messages are optionally printed if the AlwaysIn or AlwaysOut
255+ // invariants are violated.
252256static SanitizerMask
253257parseSanitizeArgs (const Driver &D, const llvm::opt::ArgList &Args,
254- bool DiagnoseErrors, SanitizerMask Supported,
255- SanitizerMask Default, int OptInID, int OptOutID) {
256- SanitizerMask Remove; // During the loop below, the accumulated set of
257- // sanitizers disabled by the current sanitizer
258- // argument or any argument after it.
259- SanitizerMask Kinds;
260- SanitizerMask SupportedWithGroups = setGroupBits (Supported);
261-
262- for (const llvm::opt::Arg *Arg : llvm::reverse (Args)) {
258+ bool DiagnoseErrors, SanitizerMask Default,
259+ SanitizerMask AlwaysIn, SanitizerMask AlwaysOut, int OptInID,
260+ int OptOutID) {
261+
262+ SanitizerMask Output = Default | AlwaysIn;
263+ // Keep track of which violations we have already reported, to avoid
264+ // duplicate error messages.
265+ SanitizerMask DiagnosedAlwaysInViolations;
266+ SanitizerMask DiagnosedAlwaysOutViolations;
267+ for (const auto *Arg : Args) {
263268 if (Arg->getOption ().matches (OptInID)) {
264- Arg->claim ();
265- SanitizerMask Add = parseArgValues (D, Arg, true );
266- Add &= ~Remove;
267- SanitizerMask InvalidValues = Add & ~SupportedWithGroups;
268- if (InvalidValues && DiagnoseErrors) {
269- SanitizerSet S;
270- S.Mask = InvalidValues;
271- D.Diag (diag::err_drv_unsupported_option_argument)
272- << Arg->getSpelling () << toString (S);
269+ SanitizerMask Add = parseArgValues (D, Arg, DiagnoseErrors);
270+ // Report error if user explicitly tries to opt-in to an always-out
271+ // sanitizer.
272+ if (SanitizerMask KindsToDiagnose =
273+ Add & AlwaysOut & ~DiagnosedAlwaysOutViolations) {
274+ if (DiagnoseErrors) {
275+ SanitizerSet SetToDiagnose;
276+ SetToDiagnose.Mask |= KindsToDiagnose;
277+ D.Diag (diag::err_drv_unsupported_option_argument)
278+ << Arg->getSpelling () << toString (SetToDiagnose);
279+ DiagnosedAlwaysOutViolations |= KindsToDiagnose;
280+ }
273281 }
274- Kinds |= expandSanitizerGroups (Add) & ~Remove;
282+ Output |= expandSanitizerGroups (Add);
283+ Arg->claim ();
275284 } else if (Arg->getOption ().matches (OptOutID)) {
285+ SanitizerMask Remove = parseArgValues (D, Arg, DiagnoseErrors);
286+ // Report error if user explicitly tries to opt-out of an always-in
287+ // sanitizer.
288+ if (SanitizerMask KindsToDiagnose =
289+ Remove & AlwaysIn & ~DiagnosedAlwaysInViolations) {
290+ if (DiagnoseErrors) {
291+ SanitizerSet SetToDiagnose;
292+ SetToDiagnose.Mask |= KindsToDiagnose;
293+ D.Diag (diag::err_drv_unsupported_option_argument)
294+ << Arg->getSpelling () << toString (SetToDiagnose);
295+ DiagnosedAlwaysInViolations |= KindsToDiagnose;
296+ }
297+ }
298+ Output &= ~expandSanitizerGroups (Remove);
276299 Arg->claim ();
277- Remove |= expandSanitizerGroups (parseArgValues (D, Arg, DiagnoseErrors));
278300 }
279301 }
280302
281- // Apply default behavior.
282- Kinds |= Default & ~Remove;
303+ Output &= ~AlwaysOut;
283304
284- return Kinds ;
305+ return Output ;
285306}
286307
287308static SanitizerMask parseSanitizeTrapArgs (const Driver &D,
288309 const llvm::opt::ArgList &Args,
289310 bool DiagnoseErrors) {
290- return parseSanitizeArgs (D, Args, DiagnoseErrors, TrappingSupported,
291- TrappingDefault, options::OPT_fsanitize_trap_EQ,
311+ SanitizerMask AlwaysTrap; // Empty
312+ SanitizerMask NeverTrap = ~(setGroupBits (TrappingSupported));
313+
314+ return parseSanitizeArgs (D, Args, DiagnoseErrors, TrappingDefault, AlwaysTrap,
315+ NeverTrap, options::OPT_fsanitize_trap_EQ,
292316 options::OPT_fno_sanitize_trap_EQ);
293317}
294318
@@ -652,44 +676,12 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
652676 // default in ASan?
653677
654678 // Parse -f(no-)?sanitize-recover flags.
655- SanitizerMask RecoverableKinds = RecoverableByDefault | AlwaysRecoverable;
656- SanitizerMask DiagnosedUnrecoverableKinds;
657- SanitizerMask DiagnosedAlwaysRecoverableKinds;
658- for (const auto *Arg : Args) {
659- if (Arg->getOption ().matches (options::OPT_fsanitize_recover_EQ)) {
660- SanitizerMask Add = parseArgValues (D, Arg, DiagnoseErrors);
661- // Report error if user explicitly tries to recover from unrecoverable
662- // sanitizer.
663- if (SanitizerMask KindsToDiagnose =
664- Add & Unrecoverable & ~DiagnosedUnrecoverableKinds) {
665- SanitizerSet SetToDiagnose;
666- SetToDiagnose.Mask |= KindsToDiagnose;
667- if (DiagnoseErrors)
668- D.Diag (diag::err_drv_unsupported_option_argument)
669- << Arg->getSpelling () << toString (SetToDiagnose);
670- DiagnosedUnrecoverableKinds |= KindsToDiagnose;
671- }
672- RecoverableKinds |= expandSanitizerGroups (Add);
673- Arg->claim ();
674- } else if (Arg->getOption ().matches (options::OPT_fno_sanitize_recover_EQ)) {
675- SanitizerMask Remove = parseArgValues (D, Arg, DiagnoseErrors);
676- // Report error if user explicitly tries to disable recovery from
677- // always recoverable sanitizer.
678- if (SanitizerMask KindsToDiagnose =
679- Remove & AlwaysRecoverable & ~DiagnosedAlwaysRecoverableKinds) {
680- SanitizerSet SetToDiagnose;
681- SetToDiagnose.Mask |= KindsToDiagnose;
682- if (DiagnoseErrors)
683- D.Diag (diag::err_drv_unsupported_option_argument)
684- << Arg->getSpelling () << toString (SetToDiagnose);
685- DiagnosedAlwaysRecoverableKinds |= KindsToDiagnose;
686- }
687- RecoverableKinds &= ~expandSanitizerGroups (Remove);
688- Arg->claim ();
689- }
690- }
679+ SanitizerMask RecoverableKinds = parseSanitizeArgs (
680+ D, Args, DiagnoseErrors, RecoverableByDefault, AlwaysRecoverable,
681+ Unrecoverable, options::OPT_fsanitize_recover_EQ,
682+ options::OPT_fno_sanitize_recover_EQ);
683+
691684 RecoverableKinds &= Kinds;
692- RecoverableKinds &= ~Unrecoverable;
693685
694686 TrappingKinds &= Kinds;
695687 RecoverableKinds &= ~TrappingKinds;
0 commit comments