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