================ @@ -247,49 +247,87 @@ 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 + Arguments (in or out) + AlwaysIn - AlwaysOut +// with arguments parsed from left to right. +// +// AlwaysOut is not enforced if AlwaysOutAdvisoryOnly is enabled. +// +// 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, bool AlwaysOutAdvisoryOnly) { + assert(!(AlwaysIn & AlwaysOut) && + "parseSanitizeArgs called with contradictory in/out requirements"); + + SanitizerMask Output = Default; + // 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 |= AlwaysIn; ---------------- thurstond wrote:
Done https://github.com/llvm/llvm-project/pull/119819 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits