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