static unsigned parseArgValues(const Driver &D, const llvm::opt::Arg *A,
bool DiagnoseErrors);
-/// Parse a single flag of the form -f[no]sanitize=.
-/// Sets the masks defining required change of the set of sanitizers.
-/// Returns true if the flag was parsed successfully.
-static bool parseArgument(const Driver &D, const llvm::opt::Arg *A,
- unsigned &Add, unsigned &Remove, bool DiagnoseErrors);
-
/// Produce an argument string from ArgList \p Args, which shows how it
/// provides some sanitizer kind from \p Mask. For example, the argument list
/// "-fsanitize=thread,vptr -fsanitize=address" with mask \c NeedsUbsanRt
const Driver &D = TC.getDriver();
for (ArgList::const_reverse_iterator I = Args.rbegin(), E = Args.rend();
I != E; ++I) {
- unsigned Add, Remove;
- if (!parseArgument(D, *I, Add, Remove, true))
- continue;
- (*I)->claim();
-
- AllRemove |= expandGroups(Remove);
-
- // 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.
- 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;
+ const auto *Arg = *I;
+ if (Arg->getOption().matches(options::OPT_fsanitize_EQ)) {
+ Arg->claim();
+ unsigned Add = parseArgValues(D, Arg, true);
+
+ // 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.
+ 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 &= ~NotSupported;
+
+ Kinds |= Add;
+ } else if (Arg->getOption().matches(options::OPT_fno_sanitize_EQ)) {
+ Arg->claim();
+ unsigned Remove = parseArgValues(D, Arg, true);
+ AllRemove |= expandGroups(Remove);
}
- 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 &= ~NotSupported;
-
- Kinds |= Add;
}
addAllOf(Sanitizers, Kinds);
unsigned parseArgValues(const Driver &D, const llvm::opt::Arg *A,
bool DiagnoseErrors) {
+ assert((A->getOption().matches(options::OPT_fsanitize_EQ) ||
+ A->getOption().matches(options::OPT_fno_sanitize_EQ)) &&
+ "Invalid argument in parseArgValues!");
unsigned Kind = 0;
for (unsigned I = 0, N = A->getNumValues(); I != N; ++I) {
if (unsigned K = parseValue(A->getValue(I)))
return Kind;
}
-bool parseArgument(const Driver &D, const llvm::opt::Arg *A, unsigned &Add,
- unsigned &Remove, bool DiagnoseErrors) {
- Add = 0;
- Remove = 0;
- if (A->getOption().matches(options::OPT_fsanitize_EQ)) {
- Add = parseArgValues(D, A, DiagnoseErrors);
- return true;
- }
- if (A->getOption().matches(options::OPT_fno_sanitize_EQ)) {
- Remove = parseArgValues(D, A, DiagnoseErrors);
- return true;
- }
- return false;
-}
-
std::string lastArgumentForMask(const Driver &D, const llvm::opt::ArgList &Args,
unsigned Mask) {
for (llvm::opt::ArgList::const_reverse_iterator I = Args.rbegin(),
E = Args.rend();
I != E; ++I) {
- unsigned Add, Remove;
- if (parseArgument(D, *I, Add, Remove, false) &&
- (expandGroups(Add) & Mask))
- return describeSanitizeArg(*I, Mask);
- Mask &= ~Remove;
+ const auto *Arg = *I;
+ if (Arg->getOption().matches(options::OPT_fsanitize_EQ)) {
+ unsigned AddKinds = expandGroups(parseArgValues(D, Arg, false));
+ if (AddKinds & Mask)
+ return describeSanitizeArg(Arg, Mask);
+ } else if (Arg->getOption().matches(options::OPT_fno_sanitize_EQ)) {
+ unsigned RemoveKinds = expandGroups(parseArgValues(D, Arg, false));
+ Mask &= ~RemoveKinds;
+ }
}
llvm_unreachable("arg list didn't provide expected value");
}