//===--- SanitizerArgs.cpp - Arguments for sanitizer tools  ---------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "clang/Driver/SanitizerArgs.h"
#include "ToolChains/CommonArgs.h"
#include "clang/Basic/Sanitizers.h"
#include "clang/Driver/Driver.h"
#include "clang/Driver/DriverDiagnostic.h"
#include "clang/Driver/Options.h"
#include "clang/Driver/ToolChain.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/SpecialCaseList.h"
#include "llvm/Support/AArch64TargetParser.h"
#include "llvm/Support/TargetParser.h"
#include "llvm/Support/VirtualFileSystem.h"
#include "llvm/Transforms/Instrumentation/AddressSanitizerOptions.h"
#include <memory>

using namespace clang;
using namespace clang::driver;
using namespace llvm::opt;

static const SanitizerMask NeedsUbsanRt =
    SanitizerKind::Undefined | SanitizerKind::Integer |
    SanitizerKind::ImplicitConversion | SanitizerKind::Nullability |
    SanitizerKind::CFI | SanitizerKind::FloatDivideByZero |
    SanitizerKind::ObjCCast;
static const SanitizerMask NeedsUbsanCxxRt =
    SanitizerKind::Vptr | SanitizerKind::CFI;
static const SanitizerMask NotAllowedWithTrap = SanitizerKind::Vptr;
static const SanitizerMask NotAllowedWithMinimalRuntime =
    SanitizerKind::Function | SanitizerKind::Vptr;
static const SanitizerMask RequiresPIE =
    SanitizerKind::DataFlow | SanitizerKind::HWAddress | SanitizerKind::Scudo;
static const SanitizerMask NeedsUnwindTables =
    SanitizerKind::Address | SanitizerKind::HWAddress | SanitizerKind::Thread |
    SanitizerKind::Memory | SanitizerKind::DataFlow;
static const SanitizerMask SupportsCoverage =
    SanitizerKind::Address | SanitizerKind::HWAddress |
    SanitizerKind::KernelAddress | SanitizerKind::KernelHWAddress |
    SanitizerKind::MemTag | SanitizerKind::Memory |
    SanitizerKind::KernelMemory | SanitizerKind::Leak |
    SanitizerKind::Undefined | SanitizerKind::Integer | SanitizerKind::Bounds |
    SanitizerKind::ImplicitConversion | SanitizerKind::Nullability |
    SanitizerKind::DataFlow | SanitizerKind::Fuzzer |
    SanitizerKind::FuzzerNoLink | SanitizerKind::FloatDivideByZero |
    SanitizerKind::SafeStack | SanitizerKind::ShadowCallStack |
    SanitizerKind::Thread | SanitizerKind::ObjCCast;
static const SanitizerMask RecoverableByDefault =
    SanitizerKind::Undefined | SanitizerKind::Integer |
    SanitizerKind::ImplicitConversion | SanitizerKind::Nullability |
    SanitizerKind::FloatDivideByZero | SanitizerKind::ObjCCast;
static const SanitizerMask Unrecoverable =
    SanitizerKind::Unreachable | SanitizerKind::Return;
static const SanitizerMask AlwaysRecoverable =
    SanitizerKind::KernelAddress | SanitizerKind::KernelHWAddress;
static const SanitizerMask NeedsLTO = SanitizerKind::CFI;
static const SanitizerMask TrappingSupported =
    (SanitizerKind::Undefined & ~SanitizerKind::Vptr) | SanitizerKind::Integer |
    SanitizerKind::Nullability | SanitizerKind::LocalBounds |
    SanitizerKind::CFI | SanitizerKind::FloatDivideByZero |
    SanitizerKind::ObjCCast;
static const SanitizerMask TrappingDefault = SanitizerKind::CFI;
static const SanitizerMask CFIClasses =
    SanitizerKind::CFIVCall | SanitizerKind::CFINVCall |
    SanitizerKind::CFIMFCall | SanitizerKind::CFIDerivedCast |
    SanitizerKind::CFIUnrelatedCast;
static const SanitizerMask CompatibleWithMinimalRuntime =
    TrappingSupported | SanitizerKind::Scudo | SanitizerKind::ShadowCallStack |
    SanitizerKind::MemTag;

enum CoverageFeature {
  CoverageFunc = 1 << 0,
  CoverageBB = 1 << 1,
  CoverageEdge = 1 << 2,
  CoverageIndirCall = 1 << 3,
  CoverageTraceBB = 1 << 4, // Deprecated.
  CoverageTraceCmp = 1 << 5,
  CoverageTraceDiv = 1 << 6,
  CoverageTraceGep = 1 << 7,
  Coverage8bitCounters = 1 << 8, // Deprecated.
  CoverageTracePC = 1 << 9,
  CoverageTracePCGuard = 1 << 10,
  CoverageNoPrune = 1 << 11,
  CoverageInline8bitCounters = 1 << 12,
  CoveragePCTable = 1 << 13,
  CoverageStackDepth = 1 << 14,
  CoverageInlineBoolFlag = 1 << 15,
  CoverageTraceLoads = 1 << 16,
  CoverageTraceStores = 1 << 17,
};

/// Parse a -fsanitize= or -fno-sanitize= argument's values, diagnosing any
/// invalid components. Returns a SanitizerMask.
static SanitizerMask parseArgValues(const Driver &D, const llvm::opt::Arg *A,
                                    bool DiagnoseErrors);

/// Parse -f(no-)?sanitize-coverage= flag values, diagnosing any invalid
/// components. Returns OR of members of \c CoverageFeature enumeration.
static int parseCoverageFeatures(const Driver &D, const llvm::opt::Arg *A,
                                 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
/// would produce "-fsanitize=vptr".
static std::string lastArgumentForMask(const Driver &D,
                                       const llvm::opt::ArgList &Args,
                                       SanitizerMask Mask);

/// Produce an argument string from argument \p A, which shows how it provides
/// a value in \p Mask. For instance, the argument
/// "-fsanitize=address,alignment" with mask \c NeedsUbsanRt would produce
/// "-fsanitize=alignment".
static std::string describeSanitizeArg(const llvm::opt::Arg *A,
                                       SanitizerMask Mask);

/// Produce a string containing comma-separated names of sanitizers in \p
/// Sanitizers set.
static std::string toString(const clang::SanitizerSet &Sanitizers);

static void validateSpecialCaseListFormat(const Driver &D,
                                          std::vector<std::string> &SCLFiles,
                                          unsigned MalformedSCLErrorDiagID,
                                          bool DiagnoseErrors) {
  if (SCLFiles.empty())
    return;

  std::string BLError;
  std::unique_ptr<llvm::SpecialCaseList> SCL(
      llvm::SpecialCaseList::create(SCLFiles, D.getVFS(), BLError));
  if (!SCL.get() && DiagnoseErrors)
    D.Diag(MalformedSCLErrorDiagID) << BLError;
}

static void addDefaultIgnorelists(const Driver &D, SanitizerMask Kinds,
                                  std::vector<std::string> &IgnorelistFiles,
                                  bool DiagnoseErrors) {
  struct Ignorelist {
    const char *File;
    SanitizerMask Mask;
  } Ignorelists[] = {{"asan_ignorelist.txt", SanitizerKind::Address},
                     {"hwasan_ignorelist.txt", SanitizerKind::HWAddress},
                     {"memtag_ignorelist.txt", SanitizerKind::MemTag},
                     {"msan_ignorelist.txt", SanitizerKind::Memory},
                     {"tsan_ignorelist.txt", SanitizerKind::Thread},
                     {"dfsan_abilist.txt", SanitizerKind::DataFlow},
                     {"cfi_ignorelist.txt", SanitizerKind::CFI},
                     {"ubsan_ignorelist.txt",
                      SanitizerKind::Undefined | SanitizerKind::Integer |
                          SanitizerKind::Nullability |
                          SanitizerKind::FloatDivideByZero}};

  for (auto BL : Ignorelists) {
    if (!(Kinds & BL.Mask))
      continue;

    clang::SmallString<64> Path(D.ResourceDir);
    llvm::sys::path::append(Path, "share", BL.File);
    if (D.getVFS().exists(Path))
      IgnorelistFiles.push_back(std::string(Path.str()));
    else if (BL.Mask == SanitizerKind::CFI && DiagnoseErrors)
      // If cfi_ignorelist.txt cannot be found in the resource dir, driver
      // should fail.
      D.Diag(clang::diag::err_drv_no_such_file) << Path;
  }
  validateSpecialCaseListFormat(
      D, IgnorelistFiles, clang::diag::err_drv_malformed_sanitizer_ignorelist,
      DiagnoseErrors);
}

/// Parse -f(no-)?sanitize-(coverage-)?(white|ignore)list argument's values,
/// diagnosing any invalid file paths and validating special case list format.
static void parseSpecialCaseListArg(const Driver &D,
                                    const llvm::opt::ArgList &Args,
                                    std::vector<std::string> &SCLFiles,
                                    llvm::opt::OptSpecifier SCLOptionID,
                                    llvm::opt::OptSpecifier NoSCLOptionID,
                                    unsigned MalformedSCLErrorDiagID,
                                    bool DiagnoseErrors) {
  for (const auto *Arg : Args) {
    // Match -fsanitize-(coverage-)?(white|ignore)list.
    if (Arg->getOption().matches(SCLOptionID)) {
      Arg->claim();
      std::string SCLPath = Arg->getValue();
      if (D.getVFS().exists(SCLPath)) {
        SCLFiles.push_back(SCLPath);
      } else if (DiagnoseErrors) {
        D.Diag(clang::diag::err_drv_no_such_file) << SCLPath;
      }
      // Match -fno-sanitize-ignorelist.
    } else if (Arg->getOption().matches(NoSCLOptionID)) {
      Arg->claim();
      SCLFiles.clear();
    }
  }
  validateSpecialCaseListFormat(D, SCLFiles, MalformedSCLErrorDiagID,
                                DiagnoseErrors);
}

/// Sets group bits for every group that has at least one representative already
/// enabled in \p Kinds.
static SanitizerMask setGroupBits(SanitizerMask Kinds) {
#define SANITIZER(NAME, ID)
#define SANITIZER_GROUP(NAME, ID, ALIAS)                                       \
  if (Kinds & SanitizerKind::ID)                                               \
    Kinds |= SanitizerKind::ID##Group;
#include "clang/Basic/Sanitizers.def"
  return Kinds;
}

static SanitizerMask parseSanitizeTrapArgs(const Driver &D,
                                           const llvm::opt::ArgList &Args,
                                           bool DiagnoseErrors) {
  SanitizerMask TrapRemove;     // During the loop below, the accumulated set of
                                // sanitizers disabled by the current sanitizer
                                // argument or any argument after it.
  SanitizerMask TrappingKinds;
  SanitizerMask TrappingSupportedWithGroups = setGroupBits(TrappingSupported);

  for (const llvm::opt::Arg *Arg : llvm::reverse(Args)) {
    if (Arg->getOption().matches(options::OPT_fsanitize_trap_EQ)) {
      Arg->claim();
      SanitizerMask Add = parseArgValues(D, Arg, true);
      Add &= ~TrapRemove;
      SanitizerMask InvalidValues = Add & ~TrappingSupportedWithGroups;
      if (InvalidValues && DiagnoseErrors) {
        SanitizerSet S;
        S.Mask = InvalidValues;
        D.Diag(diag::err_drv_unsupported_option_argument) << "-fsanitize-trap"
                                                          << toString(S);
      }
      TrappingKinds |= expandSanitizerGroups(Add) & ~TrapRemove;
    } else if (Arg->getOption().matches(options::OPT_fno_sanitize_trap_EQ)) {
      Arg->claim();
      TrapRemove |=
          expandSanitizerGroups(parseArgValues(D, Arg, DiagnoseErrors));
    }
  }

  // Apply default trapping behavior.
  TrappingKinds |= TrappingDefault & ~TrapRemove;

  return TrappingKinds;
}

bool SanitizerArgs::needsFuzzerInterceptors() const {
  return needsFuzzer() && !needsAsanRt() && !needsTsanRt() && !needsMsanRt();
}

bool SanitizerArgs::needsUbsanRt() const {
  // All of these include ubsan.
  if (needsAsanRt() || needsMsanRt() || needsHwasanRt() || needsTsanRt() ||
      needsDfsanRt() || needsLsanRt() || needsCfiDiagRt() ||
      (needsScudoRt() && !requiresMinimalRuntime()))
    return false;

  return (Sanitizers.Mask & NeedsUbsanRt & ~TrapSanitizers.Mask) ||
         CoverageFeatures;
}

bool SanitizerArgs::needsCfiRt() const {
  return !(Sanitizers.Mask & SanitizerKind::CFI & ~TrapSanitizers.Mask) &&
         CfiCrossDso && !ImplicitCfiRuntime;
}

bool SanitizerArgs::needsCfiDiagRt() const {
  return (Sanitizers.Mask & SanitizerKind::CFI & ~TrapSanitizers.Mask) &&
         CfiCrossDso && !ImplicitCfiRuntime;
}

bool SanitizerArgs::requiresPIE() const {
  return NeedPIE || (Sanitizers.Mask & RequiresPIE);
}

bool SanitizerArgs::needsUnwindTables() const {
  return static_cast<bool>(Sanitizers.Mask & NeedsUnwindTables);
}

bool SanitizerArgs::needsLTO() const {
  return static_cast<bool>(Sanitizers.Mask & NeedsLTO);
}

SanitizerArgs::SanitizerArgs(const ToolChain &TC,
                             const llvm::opt::ArgList &Args,
                             bool DiagnoseErrors) {
  SanitizerMask AllRemove;      // During the loop below, the accumulated set of
                                // sanitizers disabled by the current sanitizer
                                // argument or any argument after it.
  SanitizerMask AllAddedKinds;      // Mask of all sanitizers ever enabled by
                                    // -fsanitize= flags (directly or via group
                                    // expansion), some of which may be disabled
                                    // later. Used to carefully prune
                                    // unused-argument diagnostics.
  SanitizerMask DiagnosedKinds;      // All Kinds we have diagnosed up to now.
                                     // Used to deduplicate diagnostics.
  SanitizerMask Kinds;
  const SanitizerMask Supported = setGroupBits(TC.getSupportedSanitizers());

  CfiCrossDso = Args.hasFlag(options::OPT_fsanitize_cfi_cross_dso,
                             options::OPT_fno_sanitize_cfi_cross_dso, false);

  ToolChain::RTTIMode RTTIMode = TC.getRTTIMode();

  const Driver &D = TC.getDriver();
  SanitizerMask TrappingKinds = parseSanitizeTrapArgs(D, Args, DiagnoseErrors);
  SanitizerMask InvalidTrappingKinds = TrappingKinds & NotAllowedWithTrap;

  MinimalRuntime =
      Args.hasFlag(options::OPT_fsanitize_minimal_runtime,
                   options::OPT_fno_sanitize_minimal_runtime, MinimalRuntime);

  // The object size sanitizer should not be enabled at -O0.
  Arg *OptLevel = Args.getLastArg(options::OPT_O_Group);
  bool RemoveObjectSizeAtO0 =
      !OptLevel || OptLevel->getOption().matches(options::OPT_O0);

  for (const llvm::opt::Arg *Arg : llvm::reverse(Args)) {
    if (Arg->getOption().matches(options::OPT_fsanitize_EQ)) {
      Arg->claim();
      SanitizerMask Add = parseArgValues(D, Arg, DiagnoseErrors);

      if (RemoveObjectSizeAtO0) {
        AllRemove |= SanitizerKind::ObjectSize;

        // The user explicitly enabled the object size sanitizer. Warn
        // that this does nothing at -O0.
        if ((Add & SanitizerKind::ObjectSize) && DiagnoseErrors)
          D.Diag(diag::warn_drv_object_size_disabled_O0)
              << Arg->getAsString(Args);
      }

      AllAddedKinds |= expandSanitizerGroups(Add);

      // 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 (SanitizerMask KindsToDiagnose =
              Add & InvalidTrappingKinds & ~DiagnosedKinds) {
        if (DiagnoseErrors) {
          std::string Desc = describeSanitizeArg(Arg, KindsToDiagnose);
          D.Diag(diag::err_drv_argument_not_allowed_with)
              << Desc << "-fsanitize-trap=undefined";
        }
        DiagnosedKinds |= KindsToDiagnose;
      }
      Add &= ~InvalidTrappingKinds;

      if (MinimalRuntime) {
        if (SanitizerMask KindsToDiagnose =
                Add & NotAllowedWithMinimalRuntime & ~DiagnosedKinds) {
          if (DiagnoseErrors) {
            std::string Desc = describeSanitizeArg(Arg, KindsToDiagnose);
            D.Diag(diag::err_drv_argument_not_allowed_with)
                << Desc << "-fsanitize-minimal-runtime";
          }
          DiagnosedKinds |= KindsToDiagnose;
        }
        Add &= ~NotAllowedWithMinimalRuntime;
      }

      // FIXME: Make CFI on member function calls compatible with cross-DSO CFI.
      // There are currently two problems:
      // - Virtual function call checks need to pass a pointer to the function
      //   address to llvm.type.test and a pointer to the address point to the
      //   diagnostic function. Currently we pass the same pointer to both
      //   places.
      // - Non-virtual function call checks may need to check multiple type
      //   identifiers.
      // Fixing both of those may require changes to the cross-DSO CFI
      // interface.
      if (CfiCrossDso && (Add & SanitizerKind::CFIMFCall & ~DiagnosedKinds)) {
        if (DiagnoseErrors)
          D.Diag(diag::err_drv_argument_not_allowed_with)
              << "-fsanitize=cfi-mfcall"
              << "-fsanitize-cfi-cross-dso";
        Add &= ~SanitizerKind::CFIMFCall;
        DiagnosedKinds |= SanitizerKind::CFIMFCall;
      }

      if (SanitizerMask KindsToDiagnose = Add & ~Supported & ~DiagnosedKinds) {
        if (DiagnoseErrors) {
          std::string Desc = describeSanitizeArg(Arg, KindsToDiagnose);
          D.Diag(diag::err_drv_unsupported_opt_for_target)
              << Desc << TC.getTriple().str();
        }
        DiagnosedKinds |= KindsToDiagnose;
      }
      Add &= Supported;

      // Test for -fno-rtti + explicit -fsanitizer=vptr before expanding groups
      // so we don't error out if -fno-rtti and -fsanitize=undefined were
      // passed.
      if ((Add & SanitizerKind::Vptr) && (RTTIMode == ToolChain::RM_Disabled)) {
        if (const llvm::opt::Arg *NoRTTIArg = TC.getRTTIArg()) {
          assert(NoRTTIArg->getOption().matches(options::OPT_fno_rtti) &&
                  "RTTI disabled without -fno-rtti option?");
          // The user explicitly passed -fno-rtti with -fsanitize=vptr, but
          // the vptr sanitizer requires RTTI, so this is a user error.
          if (DiagnoseErrors)
            D.Diag(diag::err_drv_argument_not_allowed_with)
                << "-fsanitize=vptr" << NoRTTIArg->getAsString(Args);
        } else {
          // The vptr sanitizer requires RTTI, but RTTI is disabled (by
          // default). Warn that the vptr sanitizer is being disabled.
          if (DiagnoseErrors)
            D.Diag(diag::warn_drv_disabling_vptr_no_rtti_default);
        }

        // Take out the Vptr sanitizer from the enabled sanitizers
        AllRemove |= SanitizerKind::Vptr;
      }

      Add = expandSanitizerGroups(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 &= ~InvalidTrappingKinds;
      if (MinimalRuntime) {
        Add &= ~NotAllowedWithMinimalRuntime;
      }
      if (CfiCrossDso)
        Add &= ~SanitizerKind::CFIMFCall;
      Add &= Supported;

      if (Add & SanitizerKind::Fuzzer)
        Add |= SanitizerKind::FuzzerNoLink;

      // Enable coverage if the fuzzing flag is set.
      if (Add & SanitizerKind::FuzzerNoLink) {
        CoverageFeatures |= CoverageInline8bitCounters | CoverageIndirCall |
                            CoverageTraceCmp | CoveragePCTable;
        // Due to TLS differences, stack depth tracking is only enabled on Linux
        if (TC.getTriple().isOSLinux())
          CoverageFeatures |= CoverageStackDepth;
      }

      Kinds |= Add;
    } else if (Arg->getOption().matches(options::OPT_fno_sanitize_EQ)) {
      Arg->claim();
      SanitizerMask Remove = parseArgValues(D, Arg, DiagnoseErrors);
      AllRemove |= expandSanitizerGroups(Remove);
    }
  }

  std::pair<SanitizerMask, SanitizerMask> IncompatibleGroups[] = {
      std::make_pair(SanitizerKind::Address,
                     SanitizerKind::Thread | SanitizerKind::Memory),
      std::make_pair(SanitizerKind::Thread, SanitizerKind::Memory),
      std::make_pair(SanitizerKind::Leak,
                     SanitizerKind::Thread | SanitizerKind::Memory),
      std::make_pair(SanitizerKind::KernelAddress,
                     SanitizerKind::Address | SanitizerKind::Leak |
                         SanitizerKind::Thread | SanitizerKind::Memory),
      std::make_pair(SanitizerKind::HWAddress,
                     SanitizerKind::Address | SanitizerKind::Thread |
                         SanitizerKind::Memory | SanitizerKind::KernelAddress),
      std::make_pair(SanitizerKind::Scudo,
                     SanitizerKind::Address | SanitizerKind::HWAddress |
                         SanitizerKind::Leak | SanitizerKind::Thread |
                         SanitizerKind::Memory | SanitizerKind::KernelAddress),
      std::make_pair(SanitizerKind::SafeStack,
                     (TC.getTriple().isOSFuchsia() ? SanitizerMask()
                                                   : SanitizerKind::Leak) |
                         SanitizerKind::Address | SanitizerKind::HWAddress |
                         SanitizerKind::Thread | SanitizerKind::Memory |
                         SanitizerKind::KernelAddress),
      std::make_pair(SanitizerKind::KernelHWAddress,
                     SanitizerKind::Address | SanitizerKind::HWAddress |
                         SanitizerKind::Leak | SanitizerKind::Thread |
                         SanitizerKind::Memory | SanitizerKind::KernelAddress |
                         SanitizerKind::SafeStack),
      std::make_pair(SanitizerKind::KernelMemory,
                     SanitizerKind::Address | SanitizerKind::HWAddress |
                         SanitizerKind::Leak | SanitizerKind::Thread |
                         SanitizerKind::Memory | SanitizerKind::KernelAddress |
                         SanitizerKind::Scudo | SanitizerKind::SafeStack),
      std::make_pair(SanitizerKind::MemTag,
                     SanitizerKind::Address | SanitizerKind::KernelAddress |
                         SanitizerKind::HWAddress |
                         SanitizerKind::KernelHWAddress)};
  // Enable toolchain specific default sanitizers if not explicitly disabled.
  SanitizerMask Default = TC.getDefaultSanitizers() & ~AllRemove;

  // Disable default sanitizers that are incompatible with explicitly requested
  // ones.
  for (auto G : IncompatibleGroups) {
    SanitizerMask Group = G.first;
    if ((Default & Group) && (Kinds & G.second))
      Default &= ~Group;
  }

  Kinds |= Default;

  // We disable the vptr sanitizer if it was enabled by group expansion but RTTI
  // is disabled.
  if ((Kinds & SanitizerKind::Vptr) && (RTTIMode == ToolChain::RM_Disabled)) {
    Kinds &= ~SanitizerKind::Vptr;
  }

  // Check that LTO is enabled if we need it.
  if ((Kinds & NeedsLTO) && !D.isUsingLTO() && DiagnoseErrors) {
    D.Diag(diag::err_drv_argument_only_allowed_with)
        << lastArgumentForMask(D, Args, Kinds & NeedsLTO) << "-flto";
  }

  if ((Kinds & SanitizerKind::ShadowCallStack) &&
      ((TC.getTriple().isAArch64() &&
        !llvm::AArch64::isX18ReservedByDefault(TC.getTriple())) ||
       TC.getTriple().isRISCV()) &&
      !Args.hasArg(options::OPT_ffixed_x18) && DiagnoseErrors) {
    D.Diag(diag::err_drv_argument_only_allowed_with)
        << lastArgumentForMask(D, Args, Kinds & SanitizerKind::ShadowCallStack)
        << "-ffixed-x18";
  }

  // Report error if there are non-trapping sanitizers that require
  // c++abi-specific  parts of UBSan runtime, and they are not provided by the
  // toolchain. We don't have a good way to check the latter, so we just
  // check if the toolchan supports vptr.
  if (~Supported & SanitizerKind::Vptr) {
    SanitizerMask KindsToDiagnose = Kinds & ~TrappingKinds & NeedsUbsanCxxRt;
    // The runtime library supports the Microsoft C++ ABI, but only well enough
    // for CFI. FIXME: Remove this once we support vptr on Windows.
    if (TC.getTriple().isOSWindows())
      KindsToDiagnose &= ~SanitizerKind::CFI;
    if (KindsToDiagnose) {
      SanitizerSet S;
      S.Mask = KindsToDiagnose;
      if (DiagnoseErrors)
        D.Diag(diag::err_drv_unsupported_opt_for_target)
            << ("-fno-sanitize-trap=" + toString(S)) << TC.getTriple().str();
      Kinds &= ~KindsToDiagnose;
    }
  }

  // Warn about incompatible groups of sanitizers.
  for (auto G : IncompatibleGroups) {
    SanitizerMask Group = G.first;
    if (Kinds & Group) {
      if (SanitizerMask Incompatible = Kinds & G.second) {
        if (DiagnoseErrors)
          D.Diag(clang::diag::err_drv_argument_not_allowed_with)
              << lastArgumentForMask(D, Args, Group)
              << lastArgumentForMask(D, Args, Incompatible);
        Kinds &= ~Incompatible;
      }
    }
  }
  // FIXME: Currently -fsanitize=leak is silently ignored in the presence of
  // -fsanitize=address. Perhaps it should print an error, or perhaps
  // -f(-no)sanitize=leak should change whether leak detection is enabled by
  // default in ASan?

  // Parse -f(no-)?sanitize-recover flags.
  SanitizerMask RecoverableKinds = RecoverableByDefault | AlwaysRecoverable;
  SanitizerMask DiagnosedUnrecoverableKinds;
  SanitizerMask DiagnosedAlwaysRecoverableKinds;
  for (const auto *Arg : Args) {
    if (Arg->getOption().matches(options::OPT_fsanitize_recover_EQ)) {
      SanitizerMask Add = parseArgValues(D, Arg, DiagnoseErrors);
      // Report error if user explicitly tries to recover from unrecoverable
      // sanitizer.
      if (SanitizerMask KindsToDiagnose =
              Add & Unrecoverable & ~DiagnosedUnrecoverableKinds) {
        SanitizerSet SetToDiagnose;
        SetToDiagnose.Mask |= KindsToDiagnose;
        if (DiagnoseErrors)
          D.Diag(diag::err_drv_unsupported_option_argument)
              << Arg->getOption().getName() << toString(SetToDiagnose);
        DiagnosedUnrecoverableKinds |= KindsToDiagnose;
      }
      RecoverableKinds |= expandSanitizerGroups(Add);
      Arg->claim();
    } else if (Arg->getOption().matches(options::OPT_fno_sanitize_recover_EQ)) {
      SanitizerMask Remove = parseArgValues(D, Arg, DiagnoseErrors);
      // Report error if user explicitly tries to disable recovery from
      // always recoverable sanitizer.
      if (SanitizerMask KindsToDiagnose =
              Remove & AlwaysRecoverable & ~DiagnosedAlwaysRecoverableKinds) {
        SanitizerSet SetToDiagnose;
        SetToDiagnose.Mask |= KindsToDiagnose;
        if (DiagnoseErrors)
          D.Diag(diag::err_drv_unsupported_option_argument)
              << Arg->getOption().getName() << toString(SetToDiagnose);
        DiagnosedAlwaysRecoverableKinds |= KindsToDiagnose;
      }
      RecoverableKinds &= ~expandSanitizerGroups(Remove);
      Arg->claim();
    }
  }
  RecoverableKinds &= Kinds;
  RecoverableKinds &= ~Unrecoverable;

  TrappingKinds &= Kinds;
  RecoverableKinds &= ~TrappingKinds;

  // Setup ignorelist files.
  // Add default ignorelist from resource directory for activated sanitizers,
  // and validate special case lists format.
  if (!Args.hasArgNoClaim(options::OPT_fno_sanitize_ignorelist))
    addDefaultIgnorelists(D, Kinds, SystemIgnorelistFiles, DiagnoseErrors);

  // Parse -f(no-)?sanitize-ignorelist options.
  // This also validates special case lists format.
  parseSpecialCaseListArg(
      D, Args, UserIgnorelistFiles, options::OPT_fsanitize_ignorelist_EQ,
      options::OPT_fno_sanitize_ignorelist,
      clang::diag::err_drv_malformed_sanitizer_ignorelist, DiagnoseErrors);

  // Parse -f[no-]sanitize-memory-track-origins[=level] options.
  if (AllAddedKinds & SanitizerKind::Memory) {
    if (Arg *A =
            Args.getLastArg(options::OPT_fsanitize_memory_track_origins_EQ,
                            options::OPT_fsanitize_memory_track_origins,
                            options::OPT_fno_sanitize_memory_track_origins)) {
      if (A->getOption().matches(options::OPT_fsanitize_memory_track_origins)) {
        MsanTrackOrigins = 2;
      } else if (A->getOption().matches(
                     options::OPT_fno_sanitize_memory_track_origins)) {
        MsanTrackOrigins = 0;
      } else {
        StringRef S = A->getValue();
        if (S.getAsInteger(0, MsanTrackOrigins) || MsanTrackOrigins < 0 ||
            MsanTrackOrigins > 2) {
          if (DiagnoseErrors)
            D.Diag(clang::diag::err_drv_invalid_value)
                << A->getAsString(Args) << S;
        }
      }
    }
    MsanUseAfterDtor =
        Args.hasFlag(options::OPT_fsanitize_memory_use_after_dtor,
                     options::OPT_fno_sanitize_memory_use_after_dtor,
                     MsanUseAfterDtor);
    MsanParamRetval = Args.hasFlag(
        options::OPT_fsanitize_memory_param_retval,
        options::OPT_fno_sanitize_memory_param_retval, MsanParamRetval);
    NeedPIE |= !(TC.getTriple().isOSLinux() &&
                 TC.getTriple().getArch() == llvm::Triple::x86_64);
  } else {
    MsanUseAfterDtor = false;
    MsanParamRetval = false;
  }

  if (AllAddedKinds & SanitizerKind::Thread) {
    TsanMemoryAccess = Args.hasFlag(
        options::OPT_fsanitize_thread_memory_access,
        options::OPT_fno_sanitize_thread_memory_access, TsanMemoryAccess);
    TsanFuncEntryExit = Args.hasFlag(
        options::OPT_fsanitize_thread_func_entry_exit,
        options::OPT_fno_sanitize_thread_func_entry_exit, TsanFuncEntryExit);
    TsanAtomics =
        Args.hasFlag(options::OPT_fsanitize_thread_atomics,
                     options::OPT_fno_sanitize_thread_atomics, TsanAtomics);
  }

  if (AllAddedKinds & SanitizerKind::CFI) {
    // Without PIE, external function address may resolve to a PLT record, which
    // can not be verified by the target module.
    NeedPIE |= CfiCrossDso;
    CfiICallGeneralizePointers =
        Args.hasArg(options::OPT_fsanitize_cfi_icall_generalize_pointers);

    if (CfiCrossDso && CfiICallGeneralizePointers && DiagnoseErrors)
      D.Diag(diag::err_drv_argument_not_allowed_with)
          << "-fsanitize-cfi-cross-dso"
          << "-fsanitize-cfi-icall-generalize-pointers";

    CfiCanonicalJumpTables =
        Args.hasFlag(options::OPT_fsanitize_cfi_canonical_jump_tables,
                     options::OPT_fno_sanitize_cfi_canonical_jump_tables, true);
  }

  Stats = Args.hasFlag(options::OPT_fsanitize_stats,
                       options::OPT_fno_sanitize_stats, false);

  if (MinimalRuntime) {
    SanitizerMask IncompatibleMask =
        Kinds & ~setGroupBits(CompatibleWithMinimalRuntime);
    if (IncompatibleMask && DiagnoseErrors)
      D.Diag(clang::diag::err_drv_argument_not_allowed_with)
          << "-fsanitize-minimal-runtime"
          << lastArgumentForMask(D, Args, IncompatibleMask);

    SanitizerMask NonTrappingCfi = Kinds & SanitizerKind::CFI & ~TrappingKinds;
    if (NonTrappingCfi && DiagnoseErrors)
      D.Diag(clang::diag::err_drv_argument_only_allowed_with)
          << "fsanitize-minimal-runtime"
          << "fsanitize-trap=cfi";
  }

  // Parse -f(no-)?sanitize-coverage flags if coverage is supported by the
  // enabled sanitizers.
  for (const auto *Arg : Args) {
    if (Arg->getOption().matches(options::OPT_fsanitize_coverage)) {
      int LegacySanitizeCoverage;
      if (Arg->getNumValues() == 1 &&
          !StringRef(Arg->getValue(0))
               .getAsInteger(0, LegacySanitizeCoverage)) {
        CoverageFeatures = 0;
        Arg->claim();
        if (LegacySanitizeCoverage != 0 && DiagnoseErrors) {
          D.Diag(diag::warn_drv_deprecated_arg)
              << Arg->getAsString(Args) << "-fsanitize-coverage=trace-pc-guard";
        }
        continue;
      }
      CoverageFeatures |= parseCoverageFeatures(D, Arg, DiagnoseErrors);

      // Disable coverage and not claim the flags if there is at least one
      // non-supporting sanitizer.
      if (!(AllAddedKinds & ~AllRemove & ~setGroupBits(SupportsCoverage))) {
        Arg->claim();
      } else {
        CoverageFeatures = 0;
      }
    } else if (Arg->getOption().matches(options::OPT_fno_sanitize_coverage)) {
      Arg->claim();
      CoverageFeatures &= ~parseCoverageFeatures(D, Arg, DiagnoseErrors);
    }
  }
  // Choose at most one coverage type: function, bb, or edge.
  if (DiagnoseErrors) {
    if ((CoverageFeatures & CoverageFunc) && (CoverageFeatures & CoverageBB))
      D.Diag(clang::diag::err_drv_argument_not_allowed_with)
          << "-fsanitize-coverage=func"
          << "-fsanitize-coverage=bb";
    if ((CoverageFeatures & CoverageFunc) && (CoverageFeatures & CoverageEdge))
      D.Diag(clang::diag::err_drv_argument_not_allowed_with)
          << "-fsanitize-coverage=func"
          << "-fsanitize-coverage=edge";
    if ((CoverageFeatures & CoverageBB) && (CoverageFeatures & CoverageEdge))
      D.Diag(clang::diag::err_drv_argument_not_allowed_with)
          << "-fsanitize-coverage=bb"
          << "-fsanitize-coverage=edge";
    // Basic block tracing and 8-bit counters require some type of coverage
    // enabled.
    if (CoverageFeatures & CoverageTraceBB)
      D.Diag(clang::diag::warn_drv_deprecated_arg)
          << "-fsanitize-coverage=trace-bb"
          << "-fsanitize-coverage=trace-pc-guard";
    if (CoverageFeatures & Coverage8bitCounters)
      D.Diag(clang::diag::warn_drv_deprecated_arg)
          << "-fsanitize-coverage=8bit-counters"
          << "-fsanitize-coverage=trace-pc-guard";
  }

  int InsertionPointTypes = CoverageFunc | CoverageBB | CoverageEdge;
  int InstrumentationTypes = CoverageTracePC | CoverageTracePCGuard |
                             CoverageInline8bitCounters | CoverageTraceLoads |
                             CoverageTraceStores | CoverageInlineBoolFlag;
  if ((CoverageFeatures & InsertionPointTypes) &&
      !(CoverageFeatures & InstrumentationTypes) && DiagnoseErrors) {
    D.Diag(clang::diag::warn_drv_deprecated_arg)
        << "-fsanitize-coverage=[func|bb|edge]"
        << "-fsanitize-coverage=[func|bb|edge],[trace-pc-guard|trace-pc]";
  }

  // trace-pc w/o func/bb/edge implies edge.
  if (!(CoverageFeatures & InsertionPointTypes)) {
    if (CoverageFeatures &
        (CoverageTracePC | CoverageTracePCGuard | CoverageInline8bitCounters |
         CoverageInlineBoolFlag))
      CoverageFeatures |= CoverageEdge;

    if (CoverageFeatures & CoverageStackDepth)
      CoverageFeatures |= CoverageFunc;
  }

  // Parse -fsanitize-coverage-(ignore|white)list options if coverage enabled.
  // This also validates special case lists format.
  // Here, OptSpecifier() acts as a never-matching command-line argument.
  // So, there is no way to clear coverage lists but you can append to them.
  if (CoverageFeatures) {
    parseSpecialCaseListArg(
        D, Args, CoverageAllowlistFiles,
        options::OPT_fsanitize_coverage_allowlist, OptSpecifier(),
        clang::diag::err_drv_malformed_sanitizer_coverage_allowlist,
        DiagnoseErrors);
    parseSpecialCaseListArg(
        D, Args, CoverageIgnorelistFiles,
        options::OPT_fsanitize_coverage_ignorelist, OptSpecifier(),
        clang::diag::err_drv_malformed_sanitizer_coverage_ignorelist,
        DiagnoseErrors);
  }

  SharedRuntime =
      Args.hasFlag(options::OPT_shared_libsan, options::OPT_static_libsan,
                   TC.getTriple().isAndroid() || TC.getTriple().isOSFuchsia() ||
                       TC.getTriple().isOSDarwin());

  ImplicitCfiRuntime = TC.getTriple().isAndroid();

  if (AllAddedKinds & SanitizerKind::Address) {
    NeedPIE |= TC.getTriple().isOSFuchsia();
    if (Arg *A =
            Args.getLastArg(options::OPT_fsanitize_address_field_padding)) {
        StringRef S = A->getValue();
        // Legal values are 0 and 1, 2, but in future we may add more levels.
        if ((S.getAsInteger(0, AsanFieldPadding) || AsanFieldPadding < 0 ||
             AsanFieldPadding > 2) &&
            DiagnoseErrors) {
          D.Diag(clang::diag::err_drv_invalid_value) << A->getAsString(Args) << S;
        }
    }

    if (Arg *WindowsDebugRTArg =
            Args.getLastArg(options::OPT__SLASH_MTd, options::OPT__SLASH_MT,
                            options::OPT__SLASH_MDd, options::OPT__SLASH_MD,
                            options::OPT__SLASH_LDd, options::OPT__SLASH_LD)) {
      switch (WindowsDebugRTArg->getOption().getID()) {
      case options::OPT__SLASH_MTd:
      case options::OPT__SLASH_MDd:
      case options::OPT__SLASH_LDd:
        if (DiagnoseErrors) {
          D.Diag(clang::diag::err_drv_argument_not_allowed_with)
              << WindowsDebugRTArg->getAsString(Args)
              << lastArgumentForMask(D, Args, SanitizerKind::Address);
          D.Diag(clang::diag::note_drv_address_sanitizer_debug_runtime);
        }
      }
    }

    AsanUseAfterScope = Args.hasFlag(
        options::OPT_fsanitize_address_use_after_scope,
        options::OPT_fno_sanitize_address_use_after_scope, AsanUseAfterScope);

    AsanPoisonCustomArrayCookie = Args.hasFlag(
        options::OPT_fsanitize_address_poison_custom_array_cookie,
        options::OPT_fno_sanitize_address_poison_custom_array_cookie,
        AsanPoisonCustomArrayCookie);

    AsanOutlineInstrumentation =
        Args.hasFlag(options::OPT_fsanitize_address_outline_instrumentation,
                     options::OPT_fno_sanitize_address_outline_instrumentation,
                     AsanOutlineInstrumentation);

    // As a workaround for a bug in gold 2.26 and earlier, dead stripping of
    // globals in ASan is disabled by default on ELF targets.
    // See https://sourceware.org/bugzilla/show_bug.cgi?id=19002
    AsanGlobalsDeadStripping =
        !TC.getTriple().isOSBinFormatELF() || TC.getTriple().isOSFuchsia() ||
        TC.getTriple().isPS4() ||
        Args.hasArg(options::OPT_fsanitize_address_globals_dead_stripping);

    AsanUseOdrIndicator =
        Args.hasFlag(options::OPT_fsanitize_address_use_odr_indicator,
                     options::OPT_fno_sanitize_address_use_odr_indicator,
                     AsanUseOdrIndicator);

    if (AllAddedKinds & SanitizerKind::PointerCompare & ~AllRemove) {
      AsanInvalidPointerCmp = true;
    }

    if (AllAddedKinds & SanitizerKind::PointerSubtract & ~AllRemove) {
      AsanInvalidPointerSub = true;
    }

    if (TC.getTriple().isOSDarwin() &&
        (Args.hasArg(options::OPT_mkernel) ||
         Args.hasArg(options::OPT_fapple_kext))) {
      AsanDtorKind = llvm::AsanDtorKind::None;
    }

    if (const auto *Arg =
            Args.getLastArg(options::OPT_sanitize_address_destructor_EQ)) {
      auto parsedAsanDtorKind = AsanDtorKindFromString(Arg->getValue());
      if (parsedAsanDtorKind == llvm::AsanDtorKind::Invalid && DiagnoseErrors) {
        TC.getDriver().Diag(clang::diag::err_drv_unsupported_option_argument)
            << Arg->getOption().getName() << Arg->getValue();
      }
      AsanDtorKind = parsedAsanDtorKind;
    }

    if (const auto *Arg = Args.getLastArg(
            options::OPT_sanitize_address_use_after_return_EQ)) {
      auto parsedAsanUseAfterReturn =
          AsanDetectStackUseAfterReturnModeFromString(Arg->getValue());
      if (parsedAsanUseAfterReturn ==
              llvm::AsanDetectStackUseAfterReturnMode::Invalid &&
          DiagnoseErrors) {
        TC.getDriver().Diag(clang::diag::err_drv_unsupported_option_argument)
            << Arg->getOption().getName() << Arg->getValue();
      }
      AsanUseAfterReturn = parsedAsanUseAfterReturn;
    }

  } else {
    AsanUseAfterScope = false;
    // -fsanitize=pointer-compare/pointer-subtract requires -fsanitize=address.
    SanitizerMask DetectInvalidPointerPairs =
        SanitizerKind::PointerCompare | SanitizerKind::PointerSubtract;
    if ((AllAddedKinds & DetectInvalidPointerPairs & ~AllRemove) &&
        DiagnoseErrors) {
      TC.getDriver().Diag(clang::diag::err_drv_argument_only_allowed_with)
          << lastArgumentForMask(D, Args,
                                 SanitizerKind::PointerCompare |
                                     SanitizerKind::PointerSubtract)
          << "-fsanitize=address";
    }
  }

  if (AllAddedKinds & SanitizerKind::HWAddress) {
    if (Arg *HwasanAbiArg =
            Args.getLastArg(options::OPT_fsanitize_hwaddress_abi_EQ)) {
      HwasanAbi = HwasanAbiArg->getValue();
      if (HwasanAbi != "platform" && HwasanAbi != "interceptor" &&
          DiagnoseErrors)
        D.Diag(clang::diag::err_drv_invalid_value)
            << HwasanAbiArg->getAsString(Args) << HwasanAbi;
    } else {
      HwasanAbi = "interceptor";
    }
    if (TC.getTriple().getArch() == llvm::Triple::x86_64)
      HwasanUseAliases = Args.hasFlag(
          options::OPT_fsanitize_hwaddress_experimental_aliasing,
          options::OPT_fno_sanitize_hwaddress_experimental_aliasing,
          HwasanUseAliases);
  }

  if (AllAddedKinds & SanitizerKind::SafeStack) {
    // SafeStack runtime is built into the system on Android and Fuchsia.
    SafeStackRuntime =
        !TC.getTriple().isAndroid() && !TC.getTriple().isOSFuchsia();
  }

  LinkRuntimes =
      Args.hasFlag(options::OPT_fsanitize_link_runtime,
                   options::OPT_fno_sanitize_link_runtime, LinkRuntimes);

  // Parse -link-cxx-sanitizer flag.
  LinkCXXRuntimes = Args.hasArg(options::OPT_fsanitize_link_cxx_runtime,
                                options::OPT_fno_sanitize_link_cxx_runtime,
                                LinkCXXRuntimes) ||
                    D.CCCIsCXX();

  NeedsMemProfRt = Args.hasFlag(options::OPT_fmemory_profile,
                                options::OPT_fmemory_profile_EQ,
                                options::OPT_fno_memory_profile, false);

  // Finally, initialize the set of available and recoverable sanitizers.
  Sanitizers.Mask |= Kinds;
  RecoverableSanitizers.Mask |= RecoverableKinds;
  TrapSanitizers.Mask |= TrappingKinds;
  assert(!(RecoverableKinds & TrappingKinds) &&
         "Overlap between recoverable and trapping sanitizers");
}

static std::string toString(const clang::SanitizerSet &Sanitizers) {
  std::string Res;
#define SANITIZER(NAME, ID)                                                    \
  if (Sanitizers.has(SanitizerKind::ID)) {                                     \
    if (!Res.empty())                                                          \
      Res += ",";                                                              \
    Res += NAME;                                                               \
  }
#include "clang/Basic/Sanitizers.def"
  return Res;
}

static void addSpecialCaseListOpt(const llvm::opt::ArgList &Args,
                                  llvm::opt::ArgStringList &CmdArgs,
                                  const char *SCLOptFlag,
                                  const std::vector<std::string> &SCLFiles) {
  for (const auto &SCLPath : SCLFiles) {
    SmallString<64> SCLOpt(SCLOptFlag);
    SCLOpt += SCLPath;
    CmdArgs.push_back(Args.MakeArgString(SCLOpt));
  }
}

static void addIncludeLinkerOption(const ToolChain &TC,
                                   const llvm::opt::ArgList &Args,
                                   llvm::opt::ArgStringList &CmdArgs,
                                   StringRef SymbolName) {
  SmallString<64> LinkerOptionFlag;
  LinkerOptionFlag = "--linker-option=/include:";
  if (TC.getTriple().getArch() == llvm::Triple::x86) {
    // Win32 mangles C function names with a '_' prefix.
    LinkerOptionFlag += '_';
  }
  LinkerOptionFlag += SymbolName;
  CmdArgs.push_back(Args.MakeArgString(LinkerOptionFlag));
}

static bool hasTargetFeatureMTE(const llvm::opt::ArgStringList &CmdArgs) {
  for (auto Start = CmdArgs.begin(), End = CmdArgs.end(); Start != End; ++Start) {
    auto It = std::find(Start, End, StringRef("+mte"));
    if (It == End)
      break;
    if (It > Start && *std::prev(It) == StringRef("-target-feature"))
      return true;
    Start = It;
  }
  return false;
}

void SanitizerArgs::addArgs(const ToolChain &TC, const llvm::opt::ArgList &Args,
                            llvm::opt::ArgStringList &CmdArgs,
                            types::ID InputType) const {
  // NVPTX doesn't currently support sanitizers.  Bailing out here means
  // that e.g. -fsanitize=address applies only to host code, which is what we
  // want for now.
  //
  // AMDGPU sanitizer support is experimental and controlled by -fgpu-sanitize.
  if (TC.getTriple().isNVPTX() ||
      (TC.getTriple().isAMDGPU() &&
       !Args.hasFlag(options::OPT_fgpu_sanitize,
                     options::OPT_fno_gpu_sanitize)))
    return;

  // Translate available CoverageFeatures to corresponding clang-cc1 flags.
  // Do it even if Sanitizers.empty() since some forms of coverage don't require
  // sanitizers.
  std::pair<int, const char *> CoverageFlags[] = {
      std::make_pair(CoverageFunc, "-fsanitize-coverage-type=1"),
      std::make_pair(CoverageBB, "-fsanitize-coverage-type=2"),
      std::make_pair(CoverageEdge, "-fsanitize-coverage-type=3"),
      std::make_pair(CoverageIndirCall, "-fsanitize-coverage-indirect-calls"),
      std::make_pair(CoverageTraceBB, "-fsanitize-coverage-trace-bb"),
      std::make_pair(CoverageTraceCmp, "-fsanitize-coverage-trace-cmp"),
      std::make_pair(CoverageTraceDiv, "-fsanitize-coverage-trace-div"),
      std::make_pair(CoverageTraceGep, "-fsanitize-coverage-trace-gep"),
      std::make_pair(Coverage8bitCounters, "-fsanitize-coverage-8bit-counters"),
      std::make_pair(CoverageTracePC, "-fsanitize-coverage-trace-pc"),
      std::make_pair(CoverageTracePCGuard,
                     "-fsanitize-coverage-trace-pc-guard"),
      std::make_pair(CoverageInline8bitCounters,
                     "-fsanitize-coverage-inline-8bit-counters"),
      std::make_pair(CoverageInlineBoolFlag,
                     "-fsanitize-coverage-inline-bool-flag"),
      std::make_pair(CoveragePCTable, "-fsanitize-coverage-pc-table"),
      std::make_pair(CoverageNoPrune, "-fsanitize-coverage-no-prune"),
      std::make_pair(CoverageStackDepth, "-fsanitize-coverage-stack-depth"),
      std::make_pair(CoverageTraceLoads, "-fsanitize-coverage-trace-loads"),
      std::make_pair(CoverageTraceStores, "-fsanitize-coverage-trace-stores")};
  for (auto F : CoverageFlags) {
    if (CoverageFeatures & F.first)
      CmdArgs.push_back(F.second);
  }
  addSpecialCaseListOpt(
      Args, CmdArgs, "-fsanitize-coverage-allowlist=", CoverageAllowlistFiles);
  addSpecialCaseListOpt(Args, CmdArgs, "-fsanitize-coverage-ignorelist=",
                        CoverageIgnorelistFiles);

  if (TC.getTriple().isOSWindows() && needsUbsanRt()) {
    // Instruct the code generator to embed linker directives in the object file
    // that cause the required runtime libraries to be linked.
    CmdArgs.push_back(
        Args.MakeArgString("--dependent-lib=" +
                           TC.getCompilerRTBasename(Args, "ubsan_standalone")));
    if (types::isCXX(InputType))
      CmdArgs.push_back(Args.MakeArgString(
          "--dependent-lib=" +
          TC.getCompilerRTBasename(Args, "ubsan_standalone_cxx")));
  }
  if (TC.getTriple().isOSWindows() && needsStatsRt()) {
    CmdArgs.push_back(Args.MakeArgString(
        "--dependent-lib=" + TC.getCompilerRTBasename(Args, "stats_client")));

    // The main executable must export the stats runtime.
    // FIXME: Only exporting from the main executable (e.g. based on whether the
    // translation unit defines main()) would save a little space, but having
    // multiple copies of the runtime shouldn't hurt.
    CmdArgs.push_back(Args.MakeArgString(
        "--dependent-lib=" + TC.getCompilerRTBasename(Args, "stats")));
    addIncludeLinkerOption(TC, Args, CmdArgs, "__sanitizer_stats_register");
  }

  if (Sanitizers.empty())
    return;
  CmdArgs.push_back(Args.MakeArgString("-fsanitize=" + toString(Sanitizers)));

  if (!RecoverableSanitizers.empty())
    CmdArgs.push_back(Args.MakeArgString("-fsanitize-recover=" +
                                         toString(RecoverableSanitizers)));

  if (!TrapSanitizers.empty())
    CmdArgs.push_back(
        Args.MakeArgString("-fsanitize-trap=" + toString(TrapSanitizers)));

  addSpecialCaseListOpt(Args, CmdArgs,
                        "-fsanitize-ignorelist=", UserIgnorelistFiles);
  addSpecialCaseListOpt(Args, CmdArgs,
                        "-fsanitize-system-ignorelist=", SystemIgnorelistFiles);

  if (MsanTrackOrigins)
    CmdArgs.push_back(Args.MakeArgString("-fsanitize-memory-track-origins=" +
                                         Twine(MsanTrackOrigins)));

  if (MsanUseAfterDtor)
    CmdArgs.push_back("-fsanitize-memory-use-after-dtor");

  if (MsanParamRetval)
    CmdArgs.push_back("-fsanitize-memory-param-retval");

  // FIXME: Pass these parameters as function attributes, not as -llvm flags.
  if (!TsanMemoryAccess) {
    CmdArgs.push_back("-mllvm");
    CmdArgs.push_back("-tsan-instrument-memory-accesses=0");
    CmdArgs.push_back("-mllvm");
    CmdArgs.push_back("-tsan-instrument-memintrinsics=0");
  }
  if (!TsanFuncEntryExit) {
    CmdArgs.push_back("-mllvm");
    CmdArgs.push_back("-tsan-instrument-func-entry-exit=0");
  }
  if (!TsanAtomics) {
    CmdArgs.push_back("-mllvm");
    CmdArgs.push_back("-tsan-instrument-atomics=0");
  }

  if (HwasanUseAliases) {
    CmdArgs.push_back("-mllvm");
    CmdArgs.push_back("-hwasan-experimental-use-page-aliases=1");
  }

  if (CfiCrossDso)
    CmdArgs.push_back("-fsanitize-cfi-cross-dso");

  if (CfiICallGeneralizePointers)
    CmdArgs.push_back("-fsanitize-cfi-icall-generalize-pointers");

  if (CfiCanonicalJumpTables)
    CmdArgs.push_back("-fsanitize-cfi-canonical-jump-tables");

  if (Stats)
    CmdArgs.push_back("-fsanitize-stats");

  if (MinimalRuntime)
    CmdArgs.push_back("-fsanitize-minimal-runtime");

  if (AsanFieldPadding)
    CmdArgs.push_back(Args.MakeArgString("-fsanitize-address-field-padding=" +
                                         Twine(AsanFieldPadding)));

  if (AsanUseAfterScope)
    CmdArgs.push_back("-fsanitize-address-use-after-scope");

  if (AsanPoisonCustomArrayCookie)
    CmdArgs.push_back("-fsanitize-address-poison-custom-array-cookie");

  if (AsanGlobalsDeadStripping)
    CmdArgs.push_back("-fsanitize-address-globals-dead-stripping");

  if (AsanUseOdrIndicator)
    CmdArgs.push_back("-fsanitize-address-use-odr-indicator");

  if (AsanInvalidPointerCmp) {
    CmdArgs.push_back("-mllvm");
    CmdArgs.push_back("-asan-detect-invalid-pointer-cmp");
  }

  if (AsanInvalidPointerSub) {
    CmdArgs.push_back("-mllvm");
    CmdArgs.push_back("-asan-detect-invalid-pointer-sub");
  }

  if (AsanOutlineInstrumentation) {
    CmdArgs.push_back("-mllvm");
    CmdArgs.push_back("-asan-instrumentation-with-call-threshold=0");
  }

  // Only pass the option to the frontend if the user requested,
  // otherwise the frontend will just use the codegen default.
  if (AsanDtorKind != llvm::AsanDtorKind::Invalid) {
    CmdArgs.push_back(Args.MakeArgString("-fsanitize-address-destructor=" +
                                         AsanDtorKindToString(AsanDtorKind)));
  }

  if (AsanUseAfterReturn != llvm::AsanDetectStackUseAfterReturnMode::Invalid) {
    CmdArgs.push_back(Args.MakeArgString(
        "-fsanitize-address-use-after-return=" +
        AsanDetectStackUseAfterReturnModeToString(AsanUseAfterReturn)));
  }

  if (!HwasanAbi.empty()) {
    CmdArgs.push_back("-default-function-attr");
    CmdArgs.push_back(Args.MakeArgString("hwasan-abi=" + HwasanAbi));
  }

  if (Sanitizers.has(SanitizerKind::HWAddress) && !HwasanUseAliases) {
    CmdArgs.push_back("-target-feature");
    CmdArgs.push_back("+tagged-globals");
  }

  // MSan: Workaround for PR16386.
  // ASan: This is mainly to help LSan with cases such as
  // https://github.com/google/sanitizers/issues/373
  // We can't make this conditional on -fsanitize=leak, as that flag shouldn't
  // affect compilation.
  if (Sanitizers.has(SanitizerKind::Memory) ||
      Sanitizers.has(SanitizerKind::Address))
    CmdArgs.push_back("-fno-assume-sane-operator-new");

  // libFuzzer wants to intercept calls to certain library functions, so the
  // following -fno-builtin-* flags force the compiler to emit interposable
  // libcalls to these functions. Other sanitizers effectively do the same thing
  // by marking all library call sites with NoBuiltin attribute in their LLVM
  // pass. (see llvm::maybeMarkSanitizerLibraryCallNoBuiltin)
  if (Sanitizers.has(SanitizerKind::FuzzerNoLink)) {
    CmdArgs.push_back("-fno-builtin-bcmp");
    CmdArgs.push_back("-fno-builtin-memcmp");
    CmdArgs.push_back("-fno-builtin-strncmp");
    CmdArgs.push_back("-fno-builtin-strcmp");
    CmdArgs.push_back("-fno-builtin-strncasecmp");
    CmdArgs.push_back("-fno-builtin-strcasecmp");
    CmdArgs.push_back("-fno-builtin-strstr");
    CmdArgs.push_back("-fno-builtin-strcasestr");
    CmdArgs.push_back("-fno-builtin-memmem");
  }

  // Require -fvisibility= flag on non-Windows when compiling if vptr CFI is
  // enabled.
  if (Sanitizers.hasOneOf(CFIClasses) && !TC.getTriple().isOSWindows() &&
      !Args.hasArg(options::OPT_fvisibility_EQ)) {
    TC.getDriver().Diag(clang::diag::err_drv_argument_only_allowed_with)
        << lastArgumentForMask(TC.getDriver(), Args,
                               Sanitizers.Mask & CFIClasses)
        << "-fvisibility=";
  }

  if (Sanitizers.has(SanitizerKind::MemTag) && !hasTargetFeatureMTE(CmdArgs))
    TC.getDriver().Diag(diag::err_stack_tagging_requires_hardware_feature);
}

SanitizerMask 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) ||
          A->getOption().matches(options::OPT_fsanitize_recover_EQ) ||
          A->getOption().matches(options::OPT_fno_sanitize_recover_EQ) ||
          A->getOption().matches(options::OPT_fsanitize_trap_EQ) ||
          A->getOption().matches(options::OPT_fno_sanitize_trap_EQ)) &&
         "Invalid argument in parseArgValues!");
  SanitizerMask Kinds;
  for (int i = 0, n = A->getNumValues(); i != n; ++i) {
    const char *Value = A->getValue(i);
    SanitizerMask Kind;
    // Special case: don't accept -fsanitize=all.
    if (A->getOption().matches(options::OPT_fsanitize_EQ) &&
        0 == strcmp("all", Value))
      Kind = SanitizerMask();
    else
      Kind = parseSanitizerValue(Value, /*AllowGroups=*/true);

    if (Kind)
      Kinds |= Kind;
    else if (DiagnoseErrors)
      D.Diag(clang::diag::err_drv_unsupported_option_argument)
          << A->getOption().getName() << Value;
  }
  return Kinds;
}

int parseCoverageFeatures(const Driver &D, const llvm::opt::Arg *A,
                          bool DiagnoseErrors) {
  assert(A->getOption().matches(options::OPT_fsanitize_coverage) ||
         A->getOption().matches(options::OPT_fno_sanitize_coverage));
  int Features = 0;
  for (int i = 0, n = A->getNumValues(); i != n; ++i) {
    const char *Value = A->getValue(i);
    int F = llvm::StringSwitch<int>(Value)
                .Case("func", CoverageFunc)
                .Case("bb", CoverageBB)
                .Case("edge", CoverageEdge)
                .Case("indirect-calls", CoverageIndirCall)
                .Case("trace-bb", CoverageTraceBB)
                .Case("trace-cmp", CoverageTraceCmp)
                .Case("trace-div", CoverageTraceDiv)
                .Case("trace-gep", CoverageTraceGep)
                .Case("8bit-counters", Coverage8bitCounters)
                .Case("trace-pc", CoverageTracePC)
                .Case("trace-pc-guard", CoverageTracePCGuard)
                .Case("no-prune", CoverageNoPrune)
                .Case("inline-8bit-counters", CoverageInline8bitCounters)
                .Case("inline-bool-flag", CoverageInlineBoolFlag)
                .Case("pc-table", CoveragePCTable)
                .Case("stack-depth", CoverageStackDepth)
                .Case("trace-loads", CoverageTraceLoads)
                .Case("trace-stores", CoverageTraceStores)
                .Default(0);
    if (F == 0 && DiagnoseErrors)
      D.Diag(clang::diag::err_drv_unsupported_option_argument)
          << A->getOption().getName() << Value;
    Features |= F;
  }
  return Features;
}

std::string lastArgumentForMask(const Driver &D, const llvm::opt::ArgList &Args,
                                SanitizerMask Mask) {
  for (llvm::opt::ArgList::const_reverse_iterator I = Args.rbegin(),
                                                  E = Args.rend();
       I != E; ++I) {
    const auto *Arg = *I;
    if (Arg->getOption().matches(options::OPT_fsanitize_EQ)) {
      SanitizerMask AddKinds =
          expandSanitizerGroups(parseArgValues(D, Arg, false));
      if (AddKinds & Mask)
        return describeSanitizeArg(Arg, Mask);
    } else if (Arg->getOption().matches(options::OPT_fno_sanitize_EQ)) {
      SanitizerMask RemoveKinds =
          expandSanitizerGroups(parseArgValues(D, Arg, false));
      Mask &= ~RemoveKinds;
    }
  }
  llvm_unreachable("arg list didn't provide expected value");
}

std::string describeSanitizeArg(const llvm::opt::Arg *A, SanitizerMask Mask) {
  assert(A->getOption().matches(options::OPT_fsanitize_EQ)
         && "Invalid argument in describeSanitizerArg!");

  std::string Sanitizers;
  for (int i = 0, n = A->getNumValues(); i != n; ++i) {
    if (expandSanitizerGroups(
            parseSanitizerValue(A->getValue(i), /*AllowGroups=*/true)) &
        Mask) {
      if (!Sanitizers.empty())
        Sanitizers += ",";
      Sanitizers += A->getValue(i);
    }
  }

  assert(!Sanitizers.empty() && "arg didn't provide expected value");
  return "-fsanitize=" + Sanitizers;
}
