]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/clang/lib/Driver/SanitizerArgs.cpp
Merge ^/head r284188 through r284643.
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / clang / lib / Driver / SanitizerArgs.cpp
1 //===--- SanitizerArgs.cpp - Arguments for sanitizer tools  ---------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 #include "clang/Driver/SanitizerArgs.h"
10 #include "clang/Basic/Sanitizers.h"
11 #include "clang/Driver/Driver.h"
12 #include "clang/Driver/DriverDiagnostic.h"
13 #include "clang/Driver/Options.h"
14 #include "clang/Driver/ToolChain.h"
15 #include "llvm/ADT/StringExtras.h"
16 #include "llvm/ADT/StringSwitch.h"
17 #include "llvm/Support/FileSystem.h"
18 #include "llvm/Support/Path.h"
19 #include "llvm/Support/SpecialCaseList.h"
20 #include <memory>
21
22 using namespace clang;
23 using namespace clang::SanitizerKind;
24 using namespace clang::driver;
25 using namespace llvm::opt;
26
27 enum : SanitizerMask {
28   NeedsUbsanRt = Undefined | Integer,
29   NotAllowedWithTrap = Vptr,
30   RequiresPIE = Memory | DataFlow,
31   NeedsUnwindTables = Address | Thread | Memory | DataFlow,
32   SupportsCoverage = Address | Memory | Leak | Undefined | Integer | DataFlow,
33   RecoverableByDefault = Undefined | Integer,
34   Unrecoverable = Address | Unreachable | Return,
35   LegacyFsanitizeRecoverMask = Undefined | Integer,
36   NeedsLTO = CFI,
37 };
38
39 enum CoverageFeature {
40   CoverageFunc = 1 << 0,
41   CoverageBB = 1 << 1,
42   CoverageEdge = 1 << 2,
43   CoverageIndirCall = 1 << 3,
44   CoverageTraceBB = 1 << 4,
45   CoverageTraceCmp = 1 << 5,
46   Coverage8bitCounters = 1 << 6,
47 };
48
49 /// Parse a -fsanitize= or -fno-sanitize= argument's values, diagnosing any
50 /// invalid components. Returns a SanitizerMask.
51 static SanitizerMask parseArgValues(const Driver &D, const llvm::opt::Arg *A,
52                                     bool DiagnoseErrors);
53
54 /// Parse -f(no-)?sanitize-coverage= flag values, diagnosing any invalid
55 /// components. Returns OR of members of \c CoverageFeature enumeration.
56 static int parseCoverageFeatures(const Driver &D, const llvm::opt::Arg *A);
57
58 /// Produce an argument string from ArgList \p Args, which shows how it
59 /// provides some sanitizer kind from \p Mask. For example, the argument list
60 /// "-fsanitize=thread,vptr -fsanitize=address" with mask \c NeedsUbsanRt
61 /// would produce "-fsanitize=vptr".
62 static std::string lastArgumentForMask(const Driver &D,
63                                        const llvm::opt::ArgList &Args,
64                                        SanitizerMask Mask);
65
66 /// Produce an argument string from argument \p A, which shows how it provides
67 /// a value in \p Mask. For instance, the argument
68 /// "-fsanitize=address,alignment" with mask \c NeedsUbsanRt would produce
69 /// "-fsanitize=alignment".
70 static std::string describeSanitizeArg(const llvm::opt::Arg *A,
71                                        SanitizerMask Mask);
72
73 /// Produce a string containing comma-separated names of sanitizers in \p
74 /// Sanitizers set.
75 static std::string toString(const clang::SanitizerSet &Sanitizers);
76
77 static SanitizerMask getToolchainUnsupportedKinds(const ToolChain &TC) {
78   bool IsFreeBSD = TC.getTriple().getOS() == llvm::Triple::FreeBSD;
79   bool IsLinux = TC.getTriple().getOS() == llvm::Triple::Linux;
80   bool IsX86 = TC.getTriple().getArch() == llvm::Triple::x86;
81   bool IsX86_64 = TC.getTriple().getArch() == llvm::Triple::x86_64;
82   bool IsMIPS64 = TC.getTriple().getArch() == llvm::Triple::mips64 ||
83                   TC.getTriple().getArch() == llvm::Triple::mips64el;
84
85   SanitizerMask Unsupported = 0;
86   if (!(IsLinux && (IsX86_64 || IsMIPS64))) {
87     Unsupported |= Memory | DataFlow;
88   }
89   if (!((IsLinux || IsFreeBSD) && (IsX86_64 || IsMIPS64))) {
90     Unsupported |= Thread;
91   }
92   if (!(IsLinux && (IsX86 || IsX86_64))) {
93     Unsupported |= Function;
94   }
95   return Unsupported;
96 }
97
98 static bool getDefaultBlacklist(const Driver &D, SanitizerMask Kinds,
99                                 std::string &BLPath) {
100   const char *BlacklistFile = nullptr;
101   if (Kinds & Address)
102     BlacklistFile = "asan_blacklist.txt";
103   else if (Kinds & Memory)
104     BlacklistFile = "msan_blacklist.txt";
105   else if (Kinds & Thread)
106     BlacklistFile = "tsan_blacklist.txt";
107   else if (Kinds & DataFlow)
108     BlacklistFile = "dfsan_abilist.txt";
109
110   if (BlacklistFile) {
111     clang::SmallString<64> Path(D.ResourceDir);
112     llvm::sys::path::append(Path, BlacklistFile);
113     BLPath = Path.str();
114     return true;
115   }
116   return false;
117 }
118
119 bool SanitizerArgs::needsUbsanRt() const {
120   return !UbsanTrapOnError && (Sanitizers.Mask & NeedsUbsanRt) &&
121          !Sanitizers.has(Address) &&
122          !Sanitizers.has(Memory) &&
123          !Sanitizers.has(Thread);
124 }
125
126 bool SanitizerArgs::requiresPIE() const {
127   return AsanZeroBaseShadow || (Sanitizers.Mask & RequiresPIE);
128 }
129
130 bool SanitizerArgs::needsUnwindTables() const {
131   return Sanitizers.Mask & NeedsUnwindTables;
132 }
133
134 bool SanitizerArgs::needsLTO() const {
135   return Sanitizers.Mask & NeedsLTO;
136 }
137
138 void SanitizerArgs::clear() {
139   Sanitizers.clear();
140   RecoverableSanitizers.clear();
141   BlacklistFiles.clear();
142   CoverageFeatures = 0;
143   MsanTrackOrigins = 0;
144   AsanFieldPadding = 0;
145   AsanZeroBaseShadow = false;
146   UbsanTrapOnError = false;
147   AsanSharedRuntime = false;
148   LinkCXXRuntimes = false;
149 }
150
151 SanitizerArgs::SanitizerArgs(const ToolChain &TC,
152                              const llvm::opt::ArgList &Args) {
153   clear();
154   SanitizerMask AllRemove = 0;  // During the loop below, the accumulated set of
155                                 // sanitizers disabled by the current sanitizer
156                                 // argument or any argument after it.
157   SanitizerMask AllAddedKinds = 0;  // Mask of all sanitizers ever enabled by
158                                     // -fsanitize= flags (directly or via group
159                                     // expansion), some of which may be disabled
160                                     // later. Used to carefully prune
161                                     // unused-argument diagnostics.
162   SanitizerMask DiagnosedKinds = 0;  // All Kinds we have diagnosed up to now.
163                                      // Used to deduplicate diagnostics.
164   SanitizerMask Kinds = 0;
165   SanitizerMask NotSupported = getToolchainUnsupportedKinds(TC);
166   ToolChain::RTTIMode RTTIMode = TC.getRTTIMode();
167
168   const Driver &D = TC.getDriver();
169   for (ArgList::const_reverse_iterator I = Args.rbegin(), E = Args.rend();
170        I != E; ++I) {
171     const auto *Arg = *I;
172     if (Arg->getOption().matches(options::OPT_fsanitize_EQ)) {
173       Arg->claim();
174       SanitizerMask Add = parseArgValues(D, Arg, true);
175       AllAddedKinds |= expandSanitizerGroups(Add);
176
177       // Avoid diagnosing any sanitizer which is disabled later.
178       Add &= ~AllRemove;
179       // At this point we have not expanded groups, so any unsupported
180       // sanitizers in Add are those which have been explicitly enabled.
181       // Diagnose them.
182       if (SanitizerMask KindsToDiagnose =
183               Add & NotSupported & ~DiagnosedKinds) {
184         // Only diagnose the new kinds.
185         std::string Desc = describeSanitizeArg(*I, KindsToDiagnose);
186         D.Diag(diag::err_drv_unsupported_opt_for_target)
187             << Desc << TC.getTriple().str();
188         DiagnosedKinds |= KindsToDiagnose;
189       }
190       Add &= ~NotSupported;
191
192       // Test for -fno-rtti + explicit -fsanitizer=vptr before expanding groups
193       // so we don't error out if -fno-rtti and -fsanitize=undefined were
194       // passed.
195       if (Add & Vptr &&
196           (RTTIMode == ToolChain::RM_DisabledImplicitly ||
197            RTTIMode == ToolChain::RM_DisabledExplicitly)) {
198         if (RTTIMode == ToolChain::RM_DisabledImplicitly)
199           // Warn about not having rtti enabled if the vptr sanitizer is
200           // explicitly enabled
201           D.Diag(diag::warn_drv_disabling_vptr_no_rtti_default);
202         else {
203           const llvm::opt::Arg *NoRTTIArg = TC.getRTTIArg();
204           assert(NoRTTIArg &&
205                  "RTTI disabled explicitly but we have no argument!");
206           D.Diag(diag::err_drv_argument_not_allowed_with)
207               << "-fsanitize=vptr" << NoRTTIArg->getAsString(Args);
208         }
209
210         // Take out the Vptr sanitizer from the enabled sanitizers
211         AllRemove |= Vptr;
212       }
213
214       Add = expandSanitizerGroups(Add);
215       // Group expansion may have enabled a sanitizer which is disabled later.
216       Add &= ~AllRemove;
217       // Silently discard any unsupported sanitizers implicitly enabled through
218       // group expansion.
219       Add &= ~NotSupported;
220
221       Kinds |= Add;
222     } else if (Arg->getOption().matches(options::OPT_fno_sanitize_EQ)) {
223       Arg->claim();
224       SanitizerMask Remove = parseArgValues(D, Arg, true);
225       AllRemove |= expandSanitizerGroups(Remove);
226     }
227   }
228
229   // We disable the vptr sanitizer if it was enabled by group expansion but RTTI
230   // is disabled.
231   if ((Kinds & Vptr) &&
232       (RTTIMode == ToolChain::RM_DisabledImplicitly ||
233        RTTIMode == ToolChain::RM_DisabledExplicitly)) {
234     Kinds &= ~Vptr;
235   }
236
237   // Warn about undefined sanitizer options that require runtime support.
238   UbsanTrapOnError =
239     Args.hasFlag(options::OPT_fsanitize_undefined_trap_on_error,
240                  options::OPT_fno_sanitize_undefined_trap_on_error, false);
241   if (UbsanTrapOnError && (Kinds & NotAllowedWithTrap)) {
242     D.Diag(clang::diag::err_drv_argument_not_allowed_with)
243         << lastArgumentForMask(D, Args, NotAllowedWithTrap)
244         << "-fsanitize-undefined-trap-on-error";
245     Kinds &= ~NotAllowedWithTrap;
246   }
247
248   // Warn about incompatible groups of sanitizers.
249   std::pair<SanitizerMask, SanitizerMask> IncompatibleGroups[] = {
250       std::make_pair(Address, Thread), std::make_pair(Address, Memory),
251       std::make_pair(Thread, Memory), std::make_pair(Leak, Thread),
252       std::make_pair(Leak, Memory)};
253   for (auto G : IncompatibleGroups) {
254     SanitizerMask Group = G.first;
255     if (Kinds & Group) {
256       if (SanitizerMask Incompatible = Kinds & G.second) {
257         D.Diag(clang::diag::err_drv_argument_not_allowed_with)
258             << lastArgumentForMask(D, Args, Group)
259             << lastArgumentForMask(D, Args, Incompatible);
260         Kinds &= ~Incompatible;
261       }
262     }
263   }
264   // FIXME: Currently -fsanitize=leak is silently ignored in the presence of
265   // -fsanitize=address. Perhaps it should print an error, or perhaps
266   // -f(-no)sanitize=leak should change whether leak detection is enabled by
267   // default in ASan?
268
269   // Parse -f(no-)?sanitize-recover flags.
270   SanitizerMask RecoverableKinds = RecoverableByDefault;
271   SanitizerMask DiagnosedUnrecoverableKinds = 0;
272   for (const auto *Arg : Args) {
273     const char *DeprecatedReplacement = nullptr;
274     if (Arg->getOption().matches(options::OPT_fsanitize_recover)) {
275       DeprecatedReplacement = "-fsanitize-recover=undefined,integer";
276       RecoverableKinds |= expandSanitizerGroups(LegacyFsanitizeRecoverMask);
277       Arg->claim();
278     } else if (Arg->getOption().matches(options::OPT_fno_sanitize_recover)) {
279       DeprecatedReplacement = "-fno-sanitize-recover=undefined,integer";
280       RecoverableKinds &= ~expandSanitizerGroups(LegacyFsanitizeRecoverMask);
281       Arg->claim();
282     } else if (Arg->getOption().matches(options::OPT_fsanitize_recover_EQ)) {
283       SanitizerMask Add = parseArgValues(D, Arg, true);
284       // Report error if user explicitly tries to recover from unrecoverable
285       // sanitizer.
286       if (SanitizerMask KindsToDiagnose =
287               Add & Unrecoverable & ~DiagnosedUnrecoverableKinds) {
288         SanitizerSet SetToDiagnose;
289         SetToDiagnose.Mask |= KindsToDiagnose;
290         D.Diag(diag::err_drv_unsupported_option_argument)
291             << Arg->getOption().getName() << toString(SetToDiagnose);
292         DiagnosedUnrecoverableKinds |= KindsToDiagnose;
293       }
294       RecoverableKinds |= expandSanitizerGroups(Add);
295       Arg->claim();
296     } else if (Arg->getOption().matches(options::OPT_fno_sanitize_recover_EQ)) {
297       RecoverableKinds &= ~expandSanitizerGroups(parseArgValues(D, Arg, true));
298       Arg->claim();
299     }
300     if (DeprecatedReplacement) {
301       D.Diag(diag::warn_drv_deprecated_arg) << Arg->getAsString(Args)
302                                             << DeprecatedReplacement;
303     }
304   }
305   RecoverableKinds &= Kinds;
306   RecoverableKinds &= ~Unrecoverable;
307
308   // Setup blacklist files.
309   // Add default blacklist from resource directory.
310   {
311     std::string BLPath;
312     if (getDefaultBlacklist(D, Kinds, BLPath) && llvm::sys::fs::exists(BLPath))
313       BlacklistFiles.push_back(BLPath);
314   }
315   // Parse -f(no-)sanitize-blacklist options.
316   for (const auto *Arg : Args) {
317     if (Arg->getOption().matches(options::OPT_fsanitize_blacklist)) {
318       Arg->claim();
319       std::string BLPath = Arg->getValue();
320       if (llvm::sys::fs::exists(BLPath))
321         BlacklistFiles.push_back(BLPath);
322       else
323         D.Diag(clang::diag::err_drv_no_such_file) << BLPath;
324     } else if (Arg->getOption().matches(options::OPT_fno_sanitize_blacklist)) {
325       Arg->claim();
326       BlacklistFiles.clear();
327     }
328   }
329   // Validate blacklists format.
330   {
331     std::string BLError;
332     std::unique_ptr<llvm::SpecialCaseList> SCL(
333         llvm::SpecialCaseList::create(BlacklistFiles, BLError));
334     if (!SCL.get())
335       D.Diag(clang::diag::err_drv_malformed_sanitizer_blacklist) << BLError;
336   }
337
338   // Parse -f[no-]sanitize-memory-track-origins[=level] options.
339   if (AllAddedKinds & Memory) {
340     if (Arg *A =
341             Args.getLastArg(options::OPT_fsanitize_memory_track_origins_EQ,
342                             options::OPT_fsanitize_memory_track_origins,
343                             options::OPT_fno_sanitize_memory_track_origins)) {
344       if (A->getOption().matches(options::OPT_fsanitize_memory_track_origins)) {
345         MsanTrackOrigins = 2;
346       } else if (A->getOption().matches(
347                      options::OPT_fno_sanitize_memory_track_origins)) {
348         MsanTrackOrigins = 0;
349       } else {
350         StringRef S = A->getValue();
351         if (S.getAsInteger(0, MsanTrackOrigins) || MsanTrackOrigins < 0 ||
352             MsanTrackOrigins > 2) {
353           D.Diag(clang::diag::err_drv_invalid_value) << A->getAsString(Args) << S;
354         }
355       }
356     }
357   }
358
359   // Parse -f(no-)?sanitize-coverage flags if coverage is supported by the
360   // enabled sanitizers.
361   if (AllAddedKinds & SupportsCoverage) {
362     for (const auto *Arg : Args) {
363       if (Arg->getOption().matches(options::OPT_fsanitize_coverage)) {
364         Arg->claim();
365         int LegacySanitizeCoverage;
366         if (Arg->getNumValues() == 1 &&
367             !StringRef(Arg->getValue(0))
368                  .getAsInteger(0, LegacySanitizeCoverage) &&
369             LegacySanitizeCoverage >= 0 && LegacySanitizeCoverage <= 4) {
370           // TODO: Add deprecation notice for this form.
371           switch (LegacySanitizeCoverage) {
372           case 0:
373             CoverageFeatures = 0;
374             break;
375           case 1:
376             CoverageFeatures = CoverageFunc;
377             break;
378           case 2:
379             CoverageFeatures = CoverageBB;
380             break;
381           case 3:
382             CoverageFeatures = CoverageEdge;
383             break;
384           case 4:
385             CoverageFeatures = CoverageEdge | CoverageIndirCall;
386             break;
387           }
388           continue;
389         }
390         CoverageFeatures |= parseCoverageFeatures(D, Arg);
391       } else if (Arg->getOption().matches(options::OPT_fno_sanitize_coverage)) {
392         Arg->claim();
393         CoverageFeatures &= ~parseCoverageFeatures(D, Arg);
394       }
395     }
396   }
397   // Choose at most one coverage type: function, bb, or edge.
398   if ((CoverageFeatures & CoverageFunc) && (CoverageFeatures & CoverageBB))
399     D.Diag(clang::diag::err_drv_argument_not_allowed_with)
400         << "-fsanitize-coverage=func"
401         << "-fsanitize-coverage=bb";
402   if ((CoverageFeatures & CoverageFunc) && (CoverageFeatures & CoverageEdge))
403     D.Diag(clang::diag::err_drv_argument_not_allowed_with)
404         << "-fsanitize-coverage=func"
405         << "-fsanitize-coverage=edge";
406   if ((CoverageFeatures & CoverageBB) && (CoverageFeatures & CoverageEdge))
407     D.Diag(clang::diag::err_drv_argument_not_allowed_with)
408         << "-fsanitize-coverage=bb"
409         << "-fsanitize-coverage=edge";
410   // Basic block tracing and 8-bit counters require some type of coverage
411   // enabled.
412   int CoverageTypes = CoverageFunc | CoverageBB | CoverageEdge;
413   if ((CoverageFeatures & CoverageTraceBB) &&
414       !(CoverageFeatures & CoverageTypes))
415     D.Diag(clang::diag::err_drv_argument_only_allowed_with)
416         << "-fsanitize-coverage=trace-bb"
417         << "-fsanitize-coverage=(func|bb|edge)";
418   if ((CoverageFeatures & Coverage8bitCounters) &&
419       !(CoverageFeatures & CoverageTypes))
420     D.Diag(clang::diag::err_drv_argument_only_allowed_with)
421         << "-fsanitize-coverage=8bit-counters"
422         << "-fsanitize-coverage=(func|bb|edge)";
423
424   if (AllAddedKinds & Address) {
425     AsanSharedRuntime =
426         Args.hasArg(options::OPT_shared_libasan) ||
427         (TC.getTriple().getEnvironment() == llvm::Triple::Android);
428     AsanZeroBaseShadow =
429         (TC.getTriple().getEnvironment() == llvm::Triple::Android);
430     if (Arg *A =
431             Args.getLastArg(options::OPT_fsanitize_address_field_padding)) {
432         StringRef S = A->getValue();
433         // Legal values are 0 and 1, 2, but in future we may add more levels.
434         if (S.getAsInteger(0, AsanFieldPadding) || AsanFieldPadding < 0 ||
435             AsanFieldPadding > 2) {
436           D.Diag(clang::diag::err_drv_invalid_value) << A->getAsString(Args) << S;
437         }
438     }
439
440     if (Arg *WindowsDebugRTArg =
441             Args.getLastArg(options::OPT__SLASH_MTd, options::OPT__SLASH_MT,
442                             options::OPT__SLASH_MDd, options::OPT__SLASH_MD,
443                             options::OPT__SLASH_LDd, options::OPT__SLASH_LD)) {
444       switch (WindowsDebugRTArg->getOption().getID()) {
445       case options::OPT__SLASH_MTd:
446       case options::OPT__SLASH_MDd:
447       case options::OPT__SLASH_LDd:
448         D.Diag(clang::diag::err_drv_argument_not_allowed_with)
449             << WindowsDebugRTArg->getAsString(Args)
450             << lastArgumentForMask(D, Args, Address);
451         D.Diag(clang::diag::note_drv_address_sanitizer_debug_runtime);
452       }
453     }
454   }
455
456   // Parse -link-cxx-sanitizer flag.
457   LinkCXXRuntimes =
458       Args.hasArg(options::OPT_fsanitize_link_cxx_runtime) || D.CCCIsCXX();
459
460   // Finally, initialize the set of available and recoverable sanitizers.
461   Sanitizers.Mask |= Kinds;
462   RecoverableSanitizers.Mask |= RecoverableKinds;
463 }
464
465 static std::string toString(const clang::SanitizerSet &Sanitizers) {
466   std::string Res;
467 #define SANITIZER(NAME, ID)                                                    \
468   if (Sanitizers.has(ID)) {                                                    \
469     if (!Res.empty())                                                          \
470       Res += ",";                                                              \
471     Res += NAME;                                                               \
472   }
473 #include "clang/Basic/Sanitizers.def"
474   return Res;
475 }
476
477 void SanitizerArgs::addArgs(const llvm::opt::ArgList &Args,
478                             llvm::opt::ArgStringList &CmdArgs) const {
479   if (Sanitizers.empty())
480     return;
481   CmdArgs.push_back(Args.MakeArgString("-fsanitize=" + toString(Sanitizers)));
482
483   if (!RecoverableSanitizers.empty())
484     CmdArgs.push_back(Args.MakeArgString("-fsanitize-recover=" +
485                                          toString(RecoverableSanitizers)));
486
487   if (UbsanTrapOnError)
488     CmdArgs.push_back("-fsanitize-undefined-trap-on-error");
489
490   for (const auto &BLPath : BlacklistFiles) {
491     SmallString<64> BlacklistOpt("-fsanitize-blacklist=");
492     BlacklistOpt += BLPath;
493     CmdArgs.push_back(Args.MakeArgString(BlacklistOpt));
494   }
495
496   if (MsanTrackOrigins)
497     CmdArgs.push_back(Args.MakeArgString("-fsanitize-memory-track-origins=" +
498                                          llvm::utostr(MsanTrackOrigins)));
499   if (AsanFieldPadding)
500     CmdArgs.push_back(Args.MakeArgString("-fsanitize-address-field-padding=" +
501                                          llvm::utostr(AsanFieldPadding)));
502   // Translate available CoverageFeatures to corresponding clang-cc1 flags.
503   std::pair<int, const char *> CoverageFlags[] = {
504     std::make_pair(CoverageFunc, "-fsanitize-coverage-type=1"),
505     std::make_pair(CoverageBB, "-fsanitize-coverage-type=2"),
506     std::make_pair(CoverageEdge, "-fsanitize-coverage-type=3"),
507     std::make_pair(CoverageIndirCall, "-fsanitize-coverage-indirect-calls"),
508     std::make_pair(CoverageTraceBB, "-fsanitize-coverage-trace-bb"),
509     std::make_pair(CoverageTraceCmp, "-fsanitize-coverage-trace-cmp"),
510     std::make_pair(Coverage8bitCounters, "-fsanitize-coverage-8bit-counters")};
511   for (auto F : CoverageFlags) {
512     if (CoverageFeatures & F.first)
513       CmdArgs.push_back(Args.MakeArgString(F.second));
514   }
515
516
517   // MSan: Workaround for PR16386.
518   // ASan: This is mainly to help LSan with cases such as
519   // https://code.google.com/p/address-sanitizer/issues/detail?id=373
520   // We can't make this conditional on -fsanitize=leak, as that flag shouldn't
521   // affect compilation.
522   if (Sanitizers.has(Memory) || Sanitizers.has(Address))
523     CmdArgs.push_back(Args.MakeArgString("-fno-assume-sane-operator-new"));
524 }
525
526 SanitizerMask parseArgValues(const Driver &D, const llvm::opt::Arg *A,
527                              bool DiagnoseErrors) {
528   assert((A->getOption().matches(options::OPT_fsanitize_EQ) ||
529           A->getOption().matches(options::OPT_fno_sanitize_EQ) ||
530           A->getOption().matches(options::OPT_fsanitize_recover_EQ) ||
531           A->getOption().matches(options::OPT_fno_sanitize_recover_EQ)) &&
532          "Invalid argument in parseArgValues!");
533   SanitizerMask Kinds = 0;
534   for (int i = 0, n = A->getNumValues(); i != n; ++i) {
535     const char *Value = A->getValue(i);
536     SanitizerMask Kind;
537     // Special case: don't accept -fsanitize=all.
538     if (A->getOption().matches(options::OPT_fsanitize_EQ) &&
539         0 == strcmp("all", Value))
540       Kind = 0;
541     else
542       Kind = parseSanitizerValue(Value, /*AllowGroups=*/true);
543
544     if (Kind)
545       Kinds |= Kind;
546     else if (DiagnoseErrors)
547       D.Diag(clang::diag::err_drv_unsupported_option_argument)
548           << A->getOption().getName() << Value;
549   }
550   return Kinds;
551 }
552
553 int parseCoverageFeatures(const Driver &D, const llvm::opt::Arg *A) {
554   assert(A->getOption().matches(options::OPT_fsanitize_coverage) ||
555          A->getOption().matches(options::OPT_fno_sanitize_coverage));
556   int Features = 0;
557   for (int i = 0, n = A->getNumValues(); i != n; ++i) {
558     const char *Value = A->getValue(i);
559     int F = llvm::StringSwitch<int>(Value)
560         .Case("func", CoverageFunc)
561         .Case("bb", CoverageBB)
562         .Case("edge", CoverageEdge)
563         .Case("indirect-calls", CoverageIndirCall)
564         .Case("trace-bb", CoverageTraceBB)
565         .Case("trace-cmp", CoverageTraceCmp)
566         .Case("8bit-counters", Coverage8bitCounters)
567         .Default(0);
568     if (F == 0)
569       D.Diag(clang::diag::err_drv_unsupported_option_argument)
570           << A->getOption().getName() << Value;
571     Features |= F;
572   }
573   return Features;
574 }
575
576 std::string lastArgumentForMask(const Driver &D, const llvm::opt::ArgList &Args,
577                                 SanitizerMask Mask) {
578   for (llvm::opt::ArgList::const_reverse_iterator I = Args.rbegin(),
579                                                   E = Args.rend();
580        I != E; ++I) {
581     const auto *Arg = *I;
582     if (Arg->getOption().matches(options::OPT_fsanitize_EQ)) {
583       SanitizerMask AddKinds =
584           expandSanitizerGroups(parseArgValues(D, Arg, false));
585       if (AddKinds & Mask)
586         return describeSanitizeArg(Arg, Mask);
587     } else if (Arg->getOption().matches(options::OPT_fno_sanitize_EQ)) {
588       SanitizerMask RemoveKinds =
589           expandSanitizerGroups(parseArgValues(D, Arg, false));
590       Mask &= ~RemoveKinds;
591     }
592   }
593   llvm_unreachable("arg list didn't provide expected value");
594 }
595
596 std::string describeSanitizeArg(const llvm::opt::Arg *A, SanitizerMask Mask) {
597   assert(A->getOption().matches(options::OPT_fsanitize_EQ)
598          && "Invalid argument in describeSanitizerArg!");
599
600   std::string Sanitizers;
601   for (int i = 0, n = A->getNumValues(); i != n; ++i) {
602     if (expandSanitizerGroups(
603             parseSanitizerValue(A->getValue(i), /*AllowGroups=*/true)) &
604         Mask) {
605       if (!Sanitizers.empty())
606         Sanitizers += ",";
607       Sanitizers += A->getValue(i);
608     }
609   }
610
611   assert(!Sanitizers.empty() && "arg didn't provide expected value");
612   return "-fsanitize=" + Sanitizers;
613 }