Index: clang/include/clang/Basic/DiagnosticDriverKinds.td =================================================================== --- clang/include/clang/Basic/DiagnosticDriverKinds.td +++ clang/include/clang/Basic/DiagnosticDriverKinds.td @@ -100,6 +100,14 @@ "invalid offload arch combinations: '%0' and '%1' (for a specific processor, " "a feature should either exist in all offload archs, or not exist in any " "offload archs)">; +def warn_drv_unsupported_option_for_offload_arch_req_feature : Warning< + "ignoring '%0' option as it is not currently supported for " + "offload arch '%1'. Use it with an offload arch containing '%2' instead">, + InGroup; +def warn_drv_unsupported_option_for_target : Warning< + "ignoring '%0' option as it is not currently supported for target '%1'">, + InGroup; + def err_drv_invalid_thread_model_for_target : Error< "invalid thread model '%0' in '%1' for this target">; def err_drv_invalid_linker_name : Error< Index: clang/include/clang/Driver/SanitizerArgs.h =================================================================== --- clang/include/clang/Driver/SanitizerArgs.h +++ clang/include/clang/Driver/SanitizerArgs.h @@ -65,7 +65,8 @@ public: /// Parses the sanitizer arguments from an argument list. - SanitizerArgs(const ToolChain &TC, const llvm::opt::ArgList &Args); + SanitizerArgs(const ToolChain &TC, const llvm::opt::ArgList &Args, + bool DiagnoseErrors = true); bool needsSharedRt() const { return SharedRuntime; } Index: clang/include/clang/Driver/ToolChain.h =================================================================== --- clang/include/clang/Driver/ToolChain.h +++ clang/include/clang/Driver/ToolChain.h @@ -162,7 +162,7 @@ Tool *getOffloadBundler() const; Tool *getOffloadWrapper() const; - mutable std::unique_ptr SanitizerArguments; + mutable bool SanitizerArgsChecked = false; mutable std::unique_ptr XRayArguments; /// The effective clang triple for the current Job. @@ -266,7 +266,7 @@ const Multilib &getMultilib() const { return SelectedMultilib; } - const SanitizerArgs& getSanitizerArgs() const; + SanitizerArgs getSanitizerArgs(const llvm::opt::ArgList &JobArgs) const; const XRayArgs& getXRayArgs() const; @@ -485,15 +485,15 @@ virtual bool isPICDefault() const = 0; /// Test whether this toolchain defaults to PIE. - virtual bool isPIEDefault() const = 0; + virtual bool isPIEDefault(const llvm::opt::ArgList &Args) const = 0; /// Test whether this toolchaind defaults to non-executable stacks. virtual bool isNoExecStackDefault() const; /// Tests whether this toolchain forces its default for PIC, PIE or /// non-PIC. If this returns true, any PIC related flags should be ignored - /// and instead the results of \c isPICDefault() and \c isPIEDefault() are - /// used exclusively. + /// and instead the results of \c isPICDefault() and \c isPIEDefault(const + /// llvm::opt::ArgList &Args) are used exclusively. virtual bool isPICDefaultForced() const = 0; /// SupportsProfiling - Does this tool chain support -pg. Index: clang/lib/Driver/Driver.cpp =================================================================== --- clang/lib/Driver/Driver.cpp +++ clang/lib/Driver/Driver.cpp @@ -2913,7 +2913,6 @@ class HIPActionBuilder final : public CudaActionBuilderBase { /// The linker inputs obtained for each device arch. SmallVector DeviceLinkerInputs; - bool GPUSanitize; // The default bundling behavior depends on the type of output, therefore // BundleOutput needs to be tri-value: None, true, or false. // Bundle code objects except --no-gpu-output is specified for device @@ -2926,8 +2925,6 @@ const Driver::InputList &Inputs) : CudaActionBuilderBase(C, Args, Inputs, Action::OFK_HIP) { DefaultCudaArch = CudaArch::GFX803; - GPUSanitize = Args.hasFlag(options::OPT_fgpu_sanitize, - options::OPT_fno_gpu_sanitize, false); if (Args.hasArg(options::OPT_gpu_bundle_output, options::OPT_no_gpu_bundle_output)) BundleOutput = Args.hasFlag(options::OPT_gpu_bundle_output, Index: clang/lib/Driver/SanitizerArgs.cpp =================================================================== --- clang/lib/Driver/SanitizerArgs.cpp +++ clang/lib/Driver/SanitizerArgs.cpp @@ -100,7 +100,8 @@ /// 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); +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 @@ -123,19 +124,21 @@ static void validateSpecialCaseListFormat(const Driver &D, std::vector &SCLFiles, - unsigned MalformedSCLErrorDiagID) { + unsigned MalformedSCLErrorDiagID, + bool DiagnoseErrors) { if (SCLFiles.empty()) return; std::string BLError; std::unique_ptr SCL( llvm::SpecialCaseList::create(SCLFiles, D.getVFS(), BLError)); - if (!SCL.get()) + if (!SCL.get() && DiagnoseErrors) D.Diag(MalformedSCLErrorDiagID) << BLError; } static void addDefaultIgnorelists(const Driver &D, SanitizerMask Kinds, - std::vector &IgnorelistFiles) { + std::vector &IgnorelistFiles, + bool DiagnoseErrors) { struct Ignorelist { const char *File; SanitizerMask Mask; @@ -159,13 +162,14 @@ 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) + 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); + D, IgnorelistFiles, clang::diag::err_drv_malformed_sanitizer_ignorelist, + DiagnoseErrors); } /// Parse -f(no-)?sanitize-(coverage-)?(white|ignore)list argument's values, @@ -175,7 +179,8 @@ std::vector &SCLFiles, llvm::opt::OptSpecifier SCLOptionID, llvm::opt::OptSpecifier NoSCLOptionID, - unsigned MalformedSCLErrorDiagID) { + unsigned MalformedSCLErrorDiagID, + bool DiagnoseErrors) { for (const auto *Arg : Args) { // Match -fsanitize-(coverage-)?(white|ignore)list. if (Arg->getOption().matches(SCLOptionID)) { @@ -183,7 +188,7 @@ std::string SCLPath = Arg->getValue(); if (D.getVFS().exists(SCLPath)) { SCLFiles.push_back(SCLPath); - } else { + } else if (DiagnoseErrors) { D.Diag(clang::diag::err_drv_no_such_file) << SCLPath; } // Match -fno-sanitize-ignorelist. @@ -192,7 +197,8 @@ SCLFiles.clear(); } } - validateSpecialCaseListFormat(D, SCLFiles, MalformedSCLErrorDiagID); + validateSpecialCaseListFormat(D, SCLFiles, MalformedSCLErrorDiagID, + DiagnoseErrors); } /// Sets group bits for every group that has at least one representative already @@ -207,7 +213,8 @@ } static SanitizerMask parseSanitizeTrapArgs(const Driver &D, - const llvm::opt::ArgList &Args) { + 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. @@ -221,7 +228,8 @@ Arg->claim(); SanitizerMask Add = parseArgValues(D, Arg, true); Add &= ~TrapRemove; - if (SanitizerMask InvalidValues = Add & ~TrappingSupportedWithGroups) { + SanitizerMask InvalidValues = Add & ~TrappingSupportedWithGroups; + if (InvalidValues && DiagnoseErrors) { SanitizerSet S; S.Mask = InvalidValues; D.Diag(diag::err_drv_unsupported_option_argument) << "-fsanitize-trap" @@ -230,7 +238,8 @@ TrappingKinds |= expandSanitizerGroups(Add) & ~TrapRemove; } else if (Arg->getOption().matches(options::OPT_fno_sanitize_trap_EQ)) { Arg->claim(); - TrapRemove |= expandSanitizerGroups(parseArgValues(D, Arg, true)); + TrapRemove |= + expandSanitizerGroups(parseArgValues(D, Arg, DiagnoseErrors)); } } @@ -278,7 +287,8 @@ } SanitizerArgs::SanitizerArgs(const ToolChain &TC, - const llvm::opt::ArgList &Args) { + 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. @@ -298,7 +308,7 @@ ToolChain::RTTIMode RTTIMode = TC.getRTTIMode(); const Driver &D = TC.getDriver(); - SanitizerMask TrappingKinds = parseSanitizeTrapArgs(D, Args); + SanitizerMask TrappingKinds = parseSanitizeTrapArgs(D, Args, DiagnoseErrors); SanitizerMask InvalidTrappingKinds = TrappingKinds & NotAllowedWithTrap; MinimalRuntime = @@ -315,14 +325,14 @@ const auto *Arg = *I; if (Arg->getOption().matches(options::OPT_fsanitize_EQ)) { Arg->claim(); - SanitizerMask Add = parseArgValues(D, Arg, /*AllowGroups=*/true); + 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) + if ((Add & SanitizerKind::ObjectSize) && DiagnoseErrors) D.Diag(diag::warn_drv_object_size_disabled_O0) << Arg->getAsString(Args); } @@ -336,9 +346,11 @@ // Diagnose them. if (SanitizerMask KindsToDiagnose = Add & InvalidTrappingKinds & ~DiagnosedKinds) { - std::string Desc = describeSanitizeArg(*I, KindsToDiagnose); - D.Diag(diag::err_drv_argument_not_allowed_with) - << Desc << "-fsanitize-trap=undefined"; + if (DiagnoseErrors) { + std::string Desc = describeSanitizeArg(*I, KindsToDiagnose); + D.Diag(diag::err_drv_argument_not_allowed_with) + << Desc << "-fsanitize-trap=undefined"; + } DiagnosedKinds |= KindsToDiagnose; } Add &= ~InvalidTrappingKinds; @@ -346,9 +358,11 @@ if (MinimalRuntime) { if (SanitizerMask KindsToDiagnose = Add & NotAllowedWithMinimalRuntime & ~DiagnosedKinds) { - std::string Desc = describeSanitizeArg(*I, KindsToDiagnose); - D.Diag(diag::err_drv_argument_not_allowed_with) - << Desc << "-fsanitize-minimal-runtime"; + if (DiagnoseErrors) { + std::string Desc = describeSanitizeArg(*I, KindsToDiagnose); + D.Diag(diag::err_drv_argument_not_allowed_with) + << Desc << "-fsanitize-minimal-runtime"; + } DiagnosedKinds |= KindsToDiagnose; } Add &= ~NotAllowedWithMinimalRuntime; @@ -365,17 +379,20 @@ // Fixing both of those may require changes to the cross-DSO CFI // interface. if (CfiCrossDso && (Add & SanitizerKind::CFIMFCall & ~DiagnosedKinds)) { - D.Diag(diag::err_drv_argument_not_allowed_with) - << "-fsanitize=cfi-mfcall" - << "-fsanitize-cfi-cross-dso"; + 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) { - std::string Desc = describeSanitizeArg(*I, KindsToDiagnose); - D.Diag(diag::err_drv_unsupported_opt_for_target) - << Desc << TC.getTriple().str(); + if (DiagnoseErrors) { + std::string Desc = describeSanitizeArg(*I, KindsToDiagnose); + D.Diag(diag::err_drv_unsupported_opt_for_target) + << Desc << TC.getTriple().str(); + } DiagnosedKinds |= KindsToDiagnose; } Add &= Supported; @@ -389,12 +406,14 @@ "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. - D.Diag(diag::err_drv_argument_not_allowed_with) - << "-fsanitize=vptr" << NoRTTIArg->getAsString(Args); + 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. - D.Diag(diag::warn_drv_disabling_vptr_no_rtti_default); + if (DiagnoseErrors) + D.Diag(diag::warn_drv_disabling_vptr_no_rtti_default); } // Take out the Vptr sanitizer from the enabled sanitizers @@ -429,7 +448,7 @@ Kinds |= Add; } else if (Arg->getOption().matches(options::OPT_fno_sanitize_EQ)) { Arg->claim(); - SanitizerMask Remove = parseArgValues(D, Arg, true); + SanitizerMask Remove = parseArgValues(D, Arg, DiagnoseErrors); AllRemove |= expandSanitizerGroups(Remove); } } @@ -490,7 +509,7 @@ } // Check that LTO is enabled if we need it. - if ((Kinds & NeedsLTO) && !D.isUsingLTO()) { + if ((Kinds & NeedsLTO) && !D.isUsingLTO() && DiagnoseErrors) { D.Diag(diag::err_drv_argument_only_allowed_with) << lastArgumentForMask(D, Args, Kinds & NeedsLTO) << "-flto"; } @@ -499,7 +518,7 @@ ((TC.getTriple().isAArch64() && !llvm::AArch64::isX18ReservedByDefault(TC.getTriple())) || TC.getTriple().isRISCV()) && - !Args.hasArg(options::OPT_ffixed_x18)) { + !Args.hasArg(options::OPT_ffixed_x18) && DiagnoseErrors) { D.Diag(diag::err_drv_argument_only_allowed_with) << lastArgumentForMask(D, Args, Kinds & SanitizerKind::ShadowCallStack) << "-ffixed-x18"; @@ -518,8 +537,9 @@ if (KindsToDiagnose) { SanitizerSet S; S.Mask = KindsToDiagnose; - D.Diag(diag::err_drv_unsupported_opt_for_target) - << ("-fno-sanitize-trap=" + toString(S)) << TC.getTriple().str(); + if (DiagnoseErrors) + D.Diag(diag::err_drv_unsupported_opt_for_target) + << ("-fno-sanitize-trap=" + toString(S)) << TC.getTriple().str(); Kinds &= ~KindsToDiagnose; } } @@ -529,9 +549,10 @@ SanitizerMask Group = G.first; if (Kinds & Group) { if (SanitizerMask Incompatible = Kinds & G.second) { - D.Diag(clang::diag::err_drv_argument_not_allowed_with) - << lastArgumentForMask(D, Args, Group) - << lastArgumentForMask(D, Args, Incompatible); + if (DiagnoseErrors) + D.Diag(clang::diag::err_drv_argument_not_allowed_with) + << lastArgumentForMask(D, Args, Group) + << lastArgumentForMask(D, Args, Incompatible); Kinds &= ~Incompatible; } } @@ -547,29 +568,31 @@ SanitizerMask DiagnosedAlwaysRecoverableKinds; for (const auto *Arg : Args) { if (Arg->getOption().matches(options::OPT_fsanitize_recover_EQ)) { - SanitizerMask Add = parseArgValues(D, Arg, true); + 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; - D.Diag(diag::err_drv_unsupported_option_argument) - << Arg->getOption().getName() << toString(SetToDiagnose); + 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, true); + 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; - D.Diag(diag::err_drv_unsupported_option_argument) - << Arg->getOption().getName() << toString(SetToDiagnose); + if (DiagnoseErrors) + D.Diag(diag::err_drv_unsupported_option_argument) + << Arg->getOption().getName() << toString(SetToDiagnose); DiagnosedAlwaysRecoverableKinds |= KindsToDiagnose; } RecoverableKinds &= ~expandSanitizerGroups(Remove); @@ -586,14 +609,14 @@ // 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); + 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); + 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) { @@ -610,7 +633,9 @@ StringRef S = A->getValue(); if (S.getAsInteger(0, MsanTrackOrigins) || MsanTrackOrigins < 0 || MsanTrackOrigins > 2) { - D.Diag(clang::diag::err_drv_invalid_value) << A->getAsString(Args) << S; + if (DiagnoseErrors) + D.Diag(clang::diag::err_drv_invalid_value) + << A->getAsString(Args) << S; } } } @@ -643,7 +668,7 @@ CfiICallGeneralizePointers = Args.hasArg(options::OPT_fsanitize_cfi_icall_generalize_pointers); - if (CfiCrossDso && CfiICallGeneralizePointers) + if (CfiCrossDso && CfiICallGeneralizePointers && DiagnoseErrors) D.Diag(diag::err_drv_argument_not_allowed_with) << "-fsanitize-cfi-cross-dso" << "-fsanitize-cfi-icall-generalize-pointers"; @@ -659,13 +684,13 @@ if (MinimalRuntime) { SanitizerMask IncompatibleMask = Kinds & ~setGroupBits(CompatibleWithMinimalRuntime); - if (IncompatibleMask) + 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) + if (NonTrappingCfi && DiagnoseErrors) D.Diag(clang::diag::err_drv_argument_only_allowed_with) << "fsanitize-minimal-runtime" << "fsanitize-trap=cfi"; @@ -681,13 +706,13 @@ .getAsInteger(0, LegacySanitizeCoverage)) { CoverageFeatures = 0; Arg->claim(); - if (LegacySanitizeCoverage != 0) { + if (LegacySanitizeCoverage != 0 && DiagnoseErrors) { D.Diag(diag::warn_drv_deprecated_arg) << Arg->getAsString(Args) << "-fsanitize-coverage=trace-pc-guard"; } continue; } - CoverageFeatures |= parseCoverageFeatures(D, Arg); + CoverageFeatures |= parseCoverageFeatures(D, Arg, DiagnoseErrors); // Disable coverage and not claim the flags if there is at least one // non-supporting sanitizer. @@ -698,39 +723,41 @@ } } else if (Arg->getOption().matches(options::OPT_fno_sanitize_coverage)) { Arg->claim(); - CoverageFeatures &= ~parseCoverageFeatures(D, Arg); + CoverageFeatures &= ~parseCoverageFeatures(D, Arg, DiagnoseErrors); } } // Choose at most one coverage type: function, bb, or edge. - 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"; + 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 | CoverageInlineBoolFlag; if ((CoverageFeatures & InsertionPointTypes) && - !(CoverageFeatures & InstrumentationTypes)) { + !(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]"; @@ -755,11 +782,13 @@ parseSpecialCaseListArg( D, Args, CoverageAllowlistFiles, options::OPT_fsanitize_coverage_allowlist, OptSpecifier(), - clang::diag::err_drv_malformed_sanitizer_coverage_whitelist); + clang::diag::err_drv_malformed_sanitizer_coverage_whitelist, + DiagnoseErrors); parseSpecialCaseListArg( D, Args, CoverageIgnorelistFiles, options::OPT_fsanitize_coverage_ignorelist, OptSpecifier(), - clang::diag::err_drv_malformed_sanitizer_coverage_ignorelist); + clang::diag::err_drv_malformed_sanitizer_coverage_ignorelist, + DiagnoseErrors); } SharedRuntime = @@ -775,8 +804,9 @@ 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) { + if ((S.getAsInteger(0, AsanFieldPadding) || AsanFieldPadding < 0 || + AsanFieldPadding > 2) && + DiagnoseErrors) { D.Diag(clang::diag::err_drv_invalid_value) << A->getAsString(Args) << S; } } @@ -789,10 +819,12 @@ case options::OPT__SLASH_MTd: case options::OPT__SLASH_MDd: case options::OPT__SLASH_LDd: - 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); + 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); + } } } @@ -840,7 +872,7 @@ if (const auto *Arg = Args.getLastArg(options::OPT_sanitize_address_destructor_EQ)) { auto parsedAsanDtorKind = AsanDtorKindFromString(Arg->getValue()); - if (parsedAsanDtorKind == llvm::AsanDtorKind::Invalid) { + if (parsedAsanDtorKind == llvm::AsanDtorKind::Invalid && DiagnoseErrors) { TC.getDriver().Diag(clang::diag::err_drv_unsupported_option_argument) << Arg->getOption().getName() << Arg->getValue(); } @@ -852,7 +884,8 @@ auto parsedAsanUseAfterReturn = AsanDetectStackUseAfterReturnModeFromString(Arg->getValue()); if (parsedAsanUseAfterReturn == - llvm::AsanDetectStackUseAfterReturnMode::Invalid) { + llvm::AsanDetectStackUseAfterReturnMode::Invalid && + DiagnoseErrors) { TC.getDriver().Diag(clang::diag::err_drv_unsupported_option_argument) << Arg->getOption().getName() << Arg->getValue(); } @@ -864,7 +897,8 @@ // -fsanitize=pointer-compare/pointer-subtract requires -fsanitize=address. SanitizerMask DetectInvalidPointerPairs = SanitizerKind::PointerCompare | SanitizerKind::PointerSubtract; - if (AllAddedKinds & DetectInvalidPointerPairs & ~AllRemove) { + if ((AllAddedKinds & DetectInvalidPointerPairs & ~AllRemove) && + DiagnoseErrors) { TC.getDriver().Diag(clang::diag::err_drv_argument_only_allowed_with) << lastArgumentForMask(D, Args, SanitizerKind::PointerCompare | @@ -877,7 +911,8 @@ if (Arg *HwasanAbiArg = Args.getLastArg(options::OPT_fsanitize_hwaddress_abi_EQ)) { HwasanAbi = HwasanAbiArg->getValue(); - if (HwasanAbi != "platform" && HwasanAbi != "interceptor") + if (HwasanAbi != "platform" && HwasanAbi != "interceptor" && + DiagnoseErrors) D.Diag(clang::diag::err_drv_invalid_value) << HwasanAbiArg->getAsString(Args) << HwasanAbi; } else { @@ -977,8 +1012,8 @@ // 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, - false))) + !Args.hasFlag(options::OPT_fgpu_sanitize, + options::OPT_fno_gpu_sanitize))) return; // Translate available CoverageFeatures to corresponding clang-cc1 flags. @@ -1220,7 +1255,8 @@ return Kinds; } -int parseCoverageFeatures(const Driver &D, const llvm::opt::Arg *A) { +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; @@ -1244,7 +1280,7 @@ .Case("pc-table", CoveragePCTable) .Case("stack-depth", CoverageStackDepth) .Default(0); - if (F == 0) + if (F == 0 && DiagnoseErrors) D.Diag(clang::diag::err_drv_unsupported_option_argument) << A->getOption().getName() << Value; Features |= F; Index: clang/lib/Driver/ToolChain.cpp =================================================================== --- clang/lib/Driver/ToolChain.cpp +++ clang/lib/Driver/ToolChain.cpp @@ -114,10 +114,14 @@ return false; } -const SanitizerArgs& ToolChain::getSanitizerArgs() const { - if (!SanitizerArguments.get()) - SanitizerArguments.reset(new SanitizerArgs(*this, Args)); - return *SanitizerArguments.get(); +SanitizerArgs +ToolChain::getSanitizerArgs(const llvm::opt::ArgList &JobArgs) const { + if (!SanitizerArgsChecked) { + SanitizerArgs SanArgs(*this, JobArgs); + SanitizerArgsChecked = true; + return SanArgs; + } + return SanitizerArgs(*this, JobArgs, /*DiagnoseErrors=*/false); } const XRayArgs& ToolChain::getXRayArgs() const { Index: clang/lib/Driver/ToolChains/AIX.h =================================================================== --- clang/lib/Driver/ToolChains/AIX.h +++ clang/lib/Driver/ToolChains/AIX.h @@ -63,7 +63,9 @@ return ParseInlineAsmUsingAsmParser; } bool isPICDefault() const override { return true; } - bool isPIEDefault() const override { return false; } + bool isPIEDefault(const llvm::opt::ArgList &Args) const override { + return false; + } bool isPICDefaultForced() const override { return true; } void Index: clang/lib/Driver/ToolChains/AMDGPU.h =================================================================== --- clang/lib/Driver/ToolChains/AMDGPU.h +++ clang/lib/Driver/ToolChains/AMDGPU.h @@ -67,7 +67,9 @@ bool useIntegratedAs() const override { return true; } bool isCrossCompiling() const override { return true; } bool isPICDefault() const override { return false; } - bool isPIEDefault() const override { return false; } + bool isPIEDefault(const llvm::opt::ArgList &Args) const override { + return false; + } bool isPICDefaultForced() const override { return false; } bool SupportsProfiling() const override { return false; } Index: clang/lib/Driver/ToolChains/BareMetal.h =================================================================== --- clang/lib/Driver/ToolChains/BareMetal.h +++ clang/lib/Driver/ToolChains/BareMetal.h @@ -42,7 +42,9 @@ bool useIntegratedAs() const override { return true; } bool isCrossCompiling() const override { return true; } bool isPICDefault() const override { return false; } - bool isPIEDefault() const override { return false; } + bool isPIEDefault(const llvm::opt::ArgList &Args) const override { + return false; + } bool isPICDefaultForced() const override { return false; } bool SupportsProfiling() const override { return false; } Index: clang/lib/Driver/ToolChains/Clang.cpp =================================================================== --- clang/lib/Driver/ToolChains/Clang.cpp +++ clang/lib/Driver/ToolChains/Clang.cpp @@ -749,7 +749,7 @@ static void addPGOAndCoverageFlags(const ToolChain &TC, Compilation &C, const Driver &D, const InputInfo &Output, - const ArgList &Args, + const ArgList &Args, SanitizerArgs &SanArgs, ArgStringList &CmdArgs) { auto *PGOGenerateArg = Args.getLastArg(options::OPT_fprofile_generate, @@ -923,7 +923,7 @@ else if (Val != "single") D.Diag(diag::err_drv_unsupported_option_argument) << A->getOption().getName() << Val; - } else if (TC.getSanitizerArgs().needsTsanRt()) { + } else if (SanArgs.needsTsanRt()) { CmdArgs.push_back("-fprofile-update=atomic"); } @@ -5128,12 +5128,12 @@ // This is a coarse approximation of what llvm-gcc actually does, both // -fasynchronous-unwind-tables and -fnon-call-exceptions interact in more // complicated ways. - bool AsyncUnwindTables = - Args.hasFlag(options::OPT_fasynchronous_unwind_tables, - options::OPT_fno_asynchronous_unwind_tables, - (TC.IsUnwindTablesDefault(Args) || - TC.getSanitizerArgs().needsUnwindTables()) && - !Freestanding); + auto SanitizeArgs = TC.getSanitizerArgs(Args); + bool AsyncUnwindTables = Args.hasFlag( + options::OPT_fasynchronous_unwind_tables, + options::OPT_fno_asynchronous_unwind_tables, + (TC.IsUnwindTablesDefault(Args) || SanitizeArgs.needsUnwindTables()) && + !Freestanding); bool UnwindTables = Args.hasFlag(options::OPT_funwind_tables, options::OPT_fno_unwind_tables, false); if (AsyncUnwindTables) @@ -5374,7 +5374,7 @@ // for sampling, overhead of call arc collection is way too high and there's // no way to collect the output. if (!Triple.isNVPTX() && !Triple.isAMDGCN()) - addPGOAndCoverageFlags(TC, C, D, Output, Args, CmdArgs); + addPGOAndCoverageFlags(TC, C, D, Output, Args, SanitizeArgs, CmdArgs); Args.AddLastArg(CmdArgs, options::OPT_fclang_abi_compat_EQ); @@ -5382,7 +5382,7 @@ if (RawTriple.isPS4CPU() && !Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) { PS4cpu::addProfileRTArgs(TC, Args, CmdArgs); - PS4cpu::addSanitizerArgs(TC, CmdArgs); + PS4cpu::addSanitizerArgs(TC, Args, CmdArgs); } // Pass options for controlling the default header search paths. @@ -5853,8 +5853,7 @@ CmdArgs.push_back("-fno-openmp-extensions"); } - const SanitizerArgs &Sanitize = TC.getSanitizerArgs(); - Sanitize.addArgs(TC, Args, CmdArgs, InputType); + SanitizeArgs.addArgs(TC, Args, CmdArgs, InputType); const XRayArgs &XRay = TC.getXRayArgs(); XRay.addArgs(TC, Args, CmdArgs, InputType); @@ -6798,12 +6797,12 @@ } bool DefaultsSplitLTOUnit = - (WholeProgramVTables || Sanitize.needsLTO()) && + (WholeProgramVTables || SanitizeArgs.needsLTO()) && (LTOMode == LTOK_Full || TC.canSplitThinLTOUnit()); bool SplitLTOUnit = Args.hasFlag(options::OPT_fsplit_lto_unit, options::OPT_fno_split_lto_unit, DefaultsSplitLTOUnit); - if (Sanitize.needsLTO() && !SplitLTOUnit) + if (SanitizeArgs.needsLTO() && !SplitLTOUnit) D.Diag(diag::err_drv_argument_not_allowed_with) << "-fno-split-lto-unit" << "-fsanitize=cfi"; if (SplitLTOUnit) Index: clang/lib/Driver/ToolChains/CloudABI.h =================================================================== --- clang/lib/Driver/ToolChains/CloudABI.h +++ clang/lib/Driver/ToolChains/CloudABI.h @@ -55,7 +55,7 @@ void AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs) const override; - bool isPIEDefault() const override; + bool isPIEDefault(const llvm::opt::ArgList &Args) const override; SanitizerMask getSupportedSanitizers() const override; SanitizerMask getDefaultSanitizers() const override; Index: clang/lib/Driver/ToolChains/CloudABI.cpp =================================================================== --- clang/lib/Driver/ToolChains/CloudABI.cpp +++ clang/lib/Driver/ToolChains/CloudABI.cpp @@ -47,7 +47,7 @@ CmdArgs.push_back("--no-dynamic-linker"); // Provide PIE linker flags in case PIE is default for the architecture. - if (ToolChain.isPIEDefault()) { + if (ToolChain.isPIEDefault(Args)) { CmdArgs.push_back("-pie"); CmdArgs.push_back("-zrelro"); } @@ -125,7 +125,7 @@ return new tools::cloudabi::Linker(*this); } -bool CloudABI::isPIEDefault() const { +bool CloudABI::isPIEDefault(const llvm::opt::ArgList &Args) const { // Only enable PIE on architectures that support PC-relative // addressing. PC-relative addressing is required, as the process // startup code must be able to relocate itself. Index: clang/lib/Driver/ToolChains/CommonArgs.cpp =================================================================== --- clang/lib/Driver/ToolChains/CommonArgs.cpp +++ clang/lib/Driver/ToolChains/CommonArgs.cpp @@ -787,7 +787,7 @@ SmallVectorImpl &NonWholeStaticRuntimes, SmallVectorImpl &HelperStaticRuntimes, SmallVectorImpl &RequiredSymbols) { - const SanitizerArgs &SanArgs = TC.getSanitizerArgs(); + const SanitizerArgs &SanArgs = TC.getSanitizerArgs(Args); // Collect shared runtimes. if (SanArgs.needsSharedRt()) { if (SanArgs.needsAsanRt() && SanArgs.linkRuntimes()) { @@ -923,7 +923,7 @@ NonWholeStaticRuntimes, HelperStaticRuntimes, RequiredSymbols); - const SanitizerArgs &SanArgs = TC.getSanitizerArgs(); + const SanitizerArgs &SanArgs = TC.getSanitizerArgs(Args); // Inject libfuzzer dependencies. if (SanArgs.needsFuzzer() && SanArgs.linkRuntimes() && !Args.hasArg(options::OPT_shared)) { @@ -1116,7 +1116,7 @@ const llvm::Triple &EffectiveTriple = ToolChain.getEffectiveTriple(); const llvm::Triple &Triple = ToolChain.getTriple(); - bool PIE = ToolChain.isPIEDefault(); + bool PIE = ToolChain.isPIEDefault(Args); bool PIC = PIE || ToolChain.isPICDefault(); // The Darwin/MachO default to use PIC does not apply when using -static. if (Triple.isOSBinFormatMachO() && Args.hasArg(options::OPT_static)) Index: clang/lib/Driver/ToolChains/CrossWindows.h =================================================================== --- clang/lib/Driver/ToolChains/CrossWindows.h +++ clang/lib/Driver/ToolChains/CrossWindows.h @@ -57,7 +57,7 @@ bool IsIntegratedAssemblerDefault() const override { return true; } bool IsUnwindTablesDefault(const llvm::opt::ArgList &Args) const override; bool isPICDefault() const override; - bool isPIEDefault() const override; + bool isPIEDefault(const llvm::opt::ArgList &Args) const override; bool isPICDefaultForced() const override; LangOptions::StackProtectorMode Index: clang/lib/Driver/ToolChains/CrossWindows.cpp =================================================================== --- clang/lib/Driver/ToolChains/CrossWindows.cpp +++ clang/lib/Driver/ToolChains/CrossWindows.cpp @@ -185,7 +185,7 @@ } } - if (TC.getSanitizerArgs().needsAsanRt()) { + if (TC.getSanitizerArgs(Args).needsAsanRt()) { // TODO handle /MT[d] /MD[d] if (Args.hasArg(options::OPT_shared)) { CmdArgs.push_back(TC.getCompilerRTArgString(Args, "asan_dll_thunk")); @@ -223,7 +223,7 @@ return getArch() == llvm::Triple::x86_64; } -bool CrossWindowsToolChain::isPIEDefault() const { +bool CrossWindowsToolChain::isPIEDefault(const llvm::opt::ArgList &Args) const { return getArch() == llvm::Triple::x86_64; } Index: clang/lib/Driver/ToolChains/Cuda.h =================================================================== --- clang/lib/Driver/ToolChains/Cuda.h +++ clang/lib/Driver/ToolChains/Cuda.h @@ -157,7 +157,9 @@ bool useIntegratedAs() const override { return false; } bool isCrossCompiling() const override { return true; } bool isPICDefault() const override { return false; } - bool isPIEDefault() const override { return false; } + bool isPIEDefault(const llvm::opt::ArgList &Args) const override { + return false; + } bool isPICDefaultForced() const override { return false; } bool SupportsProfiling() const override { return false; } bool supportsDebugInfoOption(const llvm::opt::Arg *A) const override; Index: clang/lib/Driver/ToolChains/Darwin.h =================================================================== --- clang/lib/Driver/ToolChains/Darwin.h +++ clang/lib/Driver/ToolChains/Darwin.h @@ -254,7 +254,7 @@ } bool isPICDefault() const override; - bool isPIEDefault() const override; + bool isPIEDefault(const llvm::opt::ArgList &Args) const override; bool isPICDefaultForced() const override; bool SupportsProfiling() const override; Index: clang/lib/Driver/ToolChains/Darwin.cpp =================================================================== --- clang/lib/Driver/ToolChains/Darwin.cpp +++ clang/lib/Driver/ToolChains/Darwin.cpp @@ -1357,7 +1357,7 @@ return; } - const SanitizerArgs &Sanitize = getSanitizerArgs(); + const SanitizerArgs &Sanitize = getSanitizerArgs(Args); if (Sanitize.needsAsanRt()) AddLinkSanitizerLibArgs(Args, CmdArgs, "asan"); if (Sanitize.needsLsanRt()) @@ -2778,7 +2778,7 @@ bool MachO::isPICDefault() const { return true; } -bool MachO::isPIEDefault() const { return false; } +bool MachO::isPIEDefault(const llvm::opt::ArgList &Args) const { return false; } bool MachO::isPICDefaultForced() const { return (getArch() == llvm::Triple::x86_64 || Index: clang/lib/Driver/ToolChains/FreeBSD.h =================================================================== --- clang/lib/Driver/ToolChains/FreeBSD.h +++ clang/lib/Driver/ToolChains/FreeBSD.h @@ -74,7 +74,7 @@ llvm::ExceptionHandling GetExceptionModel(const llvm::opt::ArgList &Args) const override; bool IsUnwindTablesDefault(const llvm::opt::ArgList &Args) const override; - bool isPIEDefault() const override; + bool isPIEDefault(const llvm::opt::ArgList &Args) const override; SanitizerMask getSupportedSanitizers() const override; unsigned GetDefaultDwarfVersion() const override; // Until dtrace (via CTF) and LLDB can deal with distributed debug info, Index: clang/lib/Driver/ToolChains/FreeBSD.cpp =================================================================== --- clang/lib/Driver/ToolChains/FreeBSD.cpp +++ clang/lib/Driver/ToolChains/FreeBSD.cpp @@ -145,7 +145,7 @@ const llvm::Triple::ArchType Arch = ToolChain.getArch(); const bool IsPIE = !Args.hasArg(options::OPT_shared) && - (Args.hasArg(options::OPT_pie) || ToolChain.isPIEDefault()); + (Args.hasArg(options::OPT_pie) || ToolChain.isPIEDefault(Args)); ArgStringList CmdArgs; // Silence warning for "clang -g foo.o -o foo" @@ -467,7 +467,9 @@ bool FreeBSD::IsUnwindTablesDefault(const ArgList &Args) const { return true; } -bool FreeBSD::isPIEDefault() const { return getSanitizerArgs().requiresPIE(); } +bool FreeBSD::isPIEDefault(const llvm::opt::ArgList &Args) const { + return getSanitizerArgs(Args).requiresPIE(); +} SanitizerMask FreeBSD::getSupportedSanitizers() const { const bool IsAArch64 = getTriple().getArch() == llvm::Triple::aarch64; Index: clang/lib/Driver/ToolChains/Fuchsia.h =================================================================== --- clang/lib/Driver/ToolChains/Fuchsia.h +++ clang/lib/Driver/ToolChains/Fuchsia.h @@ -54,7 +54,9 @@ return true; } bool isPICDefault() const override { return false; } - bool isPIEDefault() const override { return true; } + bool isPIEDefault(const llvm::opt::ArgList &Args) const override { + return true; + } bool isPICDefaultForced() const override { return false; } llvm::DebuggerKind getDefaultDebuggerTuning() const override { return llvm::DebuggerKind::GDB; Index: clang/lib/Driver/ToolChains/Fuchsia.cpp =================================================================== --- clang/lib/Driver/ToolChains/Fuchsia.cpp +++ clang/lib/Driver/ToolChains/Fuchsia.cpp @@ -89,7 +89,7 @@ else if (Args.hasArg(options::OPT_shared)) CmdArgs.push_back("-shared"); - const SanitizerArgs &SanArgs = ToolChain.getSanitizerArgs(); + const SanitizerArgs &SanArgs = ToolChain.getSanitizerArgs(Args); if (!Args.hasArg(options::OPT_shared)) { std::string Dyld = D.DyldPrefix; @@ -256,8 +256,9 @@ addMultilibFlag( Args.hasFlag(options::OPT_fexceptions, options::OPT_fno_exceptions, true), "fexceptions", Flags); - addMultilibFlag(getSanitizerArgs().needsAsanRt(), "fsanitize=address", Flags); - addMultilibFlag(getSanitizerArgs().needsHwasanRt(), "fsanitize=hwaddress", + addMultilibFlag(getSanitizerArgs(Args).needsAsanRt(), "fsanitize=address", + Flags); + addMultilibFlag(getSanitizerArgs(Args).needsHwasanRt(), "fsanitize=hwaddress", Flags); addMultilibFlag( Index: clang/lib/Driver/ToolChains/Gnu.h =================================================================== --- clang/lib/Driver/ToolChains/Gnu.h +++ clang/lib/Driver/ToolChains/Gnu.h @@ -298,7 +298,7 @@ bool IsUnwindTablesDefault(const llvm::opt::ArgList &Args) const override; bool isPICDefault() const override; - bool isPIEDefault() const override; + bool isPIEDefault(const llvm::opt::ArgList &Args) const override; bool isPICDefaultForced() const override; bool IsIntegratedAssemblerDefault() const override; llvm::opt::DerivedArgList * Index: clang/lib/Driver/ToolChains/Gnu.cpp =================================================================== --- clang/lib/Driver/ToolChains/Gnu.cpp +++ clang/lib/Driver/ToolChains/Gnu.cpp @@ -312,7 +312,7 @@ Arg *A = Args.getLastArg(options::OPT_pie, options::OPT_no_pie, options::OPT_nopie); if (!A) - return TC.isPIEDefault(); + return TC.isPIEDefault(Args); return A->getOption().matches(options::OPT_pie); } @@ -2727,7 +2727,9 @@ } } -bool Generic_GCC::isPIEDefault() const { return false; } +bool Generic_GCC::isPIEDefault(const llvm::opt::ArgList &Args) const { + return false; +} bool Generic_GCC::isPICDefaultForced() const { return getArch() == llvm::Triple::x86_64 && getTriple().isOSWindows(); Index: clang/lib/Driver/ToolChains/HIP.cpp =================================================================== --- clang/lib/Driver/ToolChains/HIP.cpp +++ clang/lib/Driver/ToolChains/HIP.cpp @@ -16,6 +16,7 @@ #include "clang/Driver/DriverDiagnostic.h" #include "clang/Driver/InputInfo.h" #include "clang/Driver/Options.h" +#include "clang/Driver/SanitizerArgs.h" #include "llvm/Support/Alignment.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/Path.h" @@ -37,6 +38,42 @@ const unsigned HIPCodeObjectAlign = 4096; } // namespace +static bool shouldSkipSanitizeOption(const ToolChain &TC, + const llvm::opt::ArgList &DriverArgs, + StringRef TargetID, + const llvm::opt::Arg *A) { + // For actions without targetID, do nothing. + if (TargetID.empty()) + return false; + Option O = A->getOption(); + if (!O.matches(options::OPT_fsanitize_EQ)) + return false; + + if (!DriverArgs.hasFlag(options::OPT_fgpu_sanitize, + -options::OPT_fno_gpu_sanitize)) + return true; + + auto &Diags = TC.getDriver().getDiags(); + + // For simplicity, we only allow -fsanitize=address + SanitizerMask K = parseSanitizerValue(A->getValue(), /*AllowGroups=*/false); + if (K != SanitizerKind::Address) + return true; + + llvm::StringMap FeatureMap; + auto OptionalGpuArch = parseTargetID(TC.getTriple(), TargetID, &FeatureMap); + + assert(OptionalGpuArch && "Invalid Target ID"); + auto Loc = FeatureMap.find("xnack"); + if (Loc == FeatureMap.end() || !Loc->second) { + Diags.Report( + clang::diag::warn_drv_unsupported_option_for_offload_arch_req_feature) + << A->getAsString(DriverArgs) << TargetID << "xnack+"; + return true; + } + return false; +} + void AMDGCN::Linker::constructLldCommand(Compilation &C, const JobAction &JA, const InputInfoList &Inputs, const InputInfo &Output, @@ -86,12 +123,6 @@ for (auto Input : Inputs) LldArgs.push_back(Input.getFilename()); - if (Args.hasFlag(options::OPT_fgpu_sanitize, options::OPT_fno_gpu_sanitize, - false)) - llvm::for_each(TC.getHIPDeviceLibs(Args), [&](auto BCFile) { - LldArgs.push_back(Args.MakeArgString(BCFile.Path)); - }); - const char *Lld = Args.MakeArgString(getToolChain().GetProgramPath("lld")); C.addCommand(std::make_unique(JA, *this, ResponseFileSupport::None(), Lld, LldArgs, Inputs, Output)); @@ -237,6 +268,14 @@ // Lookup binaries into the driver directory, this is used to // discover the clang-offload-bundler executable. getProgramPaths().push_back(getDriver().Dir); + + // Diagnose unsupported sanitizer options only once. + for (auto A : Args.filtered(options::OPT_fsanitize_EQ)) { + SanitizerMask K = parseSanitizerValue(A->getValue(), /*AllowGroups=*/false); + if (K != SanitizerKind::Address) + D.getDiags().Report(clang::diag::warn_drv_unsupported_option_for_target) + << A->getAsString(Args) << getTriple().str(); + } } void HIPToolChain::addClangTargetOptions( @@ -295,7 +334,8 @@ const OptTable &Opts = getDriver().getOpts(); for (Arg *A : Args) { - if (!shouldSkipArgument(A)) + if (!shouldSkipArgument(A) && + !shouldSkipSanitizeOption(*this, Args, BoundArch, A)) DAL->append(A); } @@ -399,7 +439,8 @@ // If --hip-device-lib is not set, add the default bitcode libraries. if (DriverArgs.hasFlag(options::OPT_fgpu_sanitize, - options::OPT_fno_gpu_sanitize, false)) { + options::OPT_fno_gpu_sanitize) && + getSanitizerArgs(DriverArgs).needsAsanRt()) { auto AsanRTL = RocmInstallation.getAsanRTLPath(); if (AsanRTL.empty()) { unsigned DiagID = getDriver().getDiags().getCustomDiagID( @@ -439,22 +480,6 @@ if (PTID.OptionalTargetID && !PTID.OptionalGPUArch) { getDriver().Diag(clang::diag::err_drv_bad_target_id) << PTID.OptionalTargetID.getValue(); - return; - } - - assert(PTID.OptionalFeatures && "Invalid return from getParsedTargetID"); - auto &FeatureMap = PTID.OptionalFeatures.getValue(); - // Sanitizer is not supported with xnack-. - if (DriverArgs.hasFlag(options::OPT_fgpu_sanitize, - options::OPT_fno_gpu_sanitize, false)) { - auto Loc = FeatureMap.find("xnack"); - if (Loc != FeatureMap.end() && !Loc->second) { - auto &Diags = getDriver().getDiags(); - auto DiagID = Diags.getCustomDiagID( - DiagnosticsEngine::Error, - "'-fgpu-sanitize' is not compatible with offload arch '%0'. " - "Use an offload arch without 'xnack-' instead"); - Diags.Report(DiagID) << PTID.OptionalTargetID.getValue(); - } } + return; } Index: clang/lib/Driver/ToolChains/Haiku.h =================================================================== --- clang/lib/Driver/ToolChains/Haiku.h +++ clang/lib/Driver/ToolChains/Haiku.h @@ -22,7 +22,7 @@ Haiku(const Driver &D, const llvm::Triple &Triple, const llvm::opt::ArgList &Args); - bool isPIEDefault() const override { + bool isPIEDefault(const llvm::opt::ArgList &Args) const override { return getTriple().getArch() == llvm::Triple::x86_64; } Index: clang/lib/Driver/ToolChains/Linux.h =================================================================== --- clang/lib/Driver/ToolChains/Linux.h +++ clang/lib/Driver/ToolChains/Linux.h @@ -43,7 +43,7 @@ CXXStdlibType GetDefaultCXXStdlibType() const override; bool IsAArch64OutlineAtomicsDefault(const llvm::opt::ArgList &Args) const override; - bool isPIEDefault() const override; + bool isPIEDefault(const llvm::opt::ArgList &Args) const override; bool isNoExecStackDefault() const override; bool IsMathErrnoDefault() const override; SanitizerMask getSupportedSanitizers() const override; Index: clang/lib/Driver/ToolChains/Linux.cpp =================================================================== --- clang/lib/Driver/ToolChains/Linux.cpp +++ clang/lib/Driver/ToolChains/Linux.cpp @@ -655,9 +655,9 @@ } } -bool Linux::isPIEDefault() const { +bool Linux::isPIEDefault(const llvm::opt::ArgList &Args) const { return (getTriple().isAndroid() && !getTriple().isAndroidVersionLT(16)) || - getTriple().isMusl() || getSanitizerArgs().requiresPIE(); + getTriple().isMusl() || getSanitizerArgs(Args).requiresPIE(); } bool Linux::IsAArch64OutlineAtomicsDefault(const ArgList &Args) const { Index: clang/lib/Driver/ToolChains/MSP430.h =================================================================== --- clang/lib/Driver/ToolChains/MSP430.h +++ clang/lib/Driver/ToolChains/MSP430.h @@ -37,7 +37,9 @@ Action::OffloadKind) const override; bool isPICDefault() const override { return false; } - bool isPIEDefault() const override { return false; } + bool isPIEDefault(const llvm::opt::ArgList &Args) const override { + return false; + } bool isPICDefaultForced() const override { return true; } UnwindLibType Index: clang/lib/Driver/ToolChains/MSVC.h =================================================================== --- clang/lib/Driver/ToolChains/MSVC.h +++ clang/lib/Driver/ToolChains/MSVC.h @@ -52,7 +52,7 @@ bool IsIntegratedAssemblerDefault() const override; bool IsUnwindTablesDefault(const llvm::opt::ArgList &Args) const override; bool isPICDefault() const override; - bool isPIEDefault() const override; + bool isPIEDefault(const llvm::opt::ArgList &Args) const override; bool isPICDefaultForced() const override; /// Set CodeView as the default debug info format for non-MachO binary Index: clang/lib/Driver/ToolChains/MSVC.cpp =================================================================== --- clang/lib/Driver/ToolChains/MSVC.cpp +++ clang/lib/Driver/ToolChains/MSVC.cpp @@ -530,7 +530,7 @@ CmdArgs.push_back(Args.MakeArgString(std::string("-implib:") + ImplibName)); } - if (TC.getSanitizerArgs().needsFuzzer()) { + if (TC.getSanitizerArgs(Args).needsFuzzer()) { if (!Args.hasArg(options::OPT_shared)) CmdArgs.push_back( Args.MakeArgString(std::string("-wholearchive:") + @@ -541,10 +541,10 @@ CmdArgs.push_back(Args.MakeArgString("-incremental:no")); } - if (TC.getSanitizerArgs().needsAsanRt()) { + if (TC.getSanitizerArgs(Args).needsAsanRt()) { CmdArgs.push_back(Args.MakeArgString("-debug")); CmdArgs.push_back(Args.MakeArgString("-incremental:no")); - if (TC.getSanitizerArgs().needsSharedRt() || + if (TC.getSanitizerArgs(Args).needsSharedRt() || Args.hasArg(options::OPT__SLASH_MD, options::OPT__SLASH_MDd)) { for (const auto &Lib : {"asan_dynamic", "asan_dynamic_runtime_thunk"}) CmdArgs.push_back(TC.getCompilerRTArgString(Args, Lib)); @@ -798,7 +798,7 @@ return getArch() == llvm::Triple::x86_64; } -bool MSVCToolChain::isPIEDefault() const { +bool MSVCToolChain::isPIEDefault(const llvm::opt::ArgList &Args) const { return false; } Index: clang/lib/Driver/ToolChains/MinGW.h =================================================================== --- clang/lib/Driver/ToolChains/MinGW.h +++ clang/lib/Driver/ToolChains/MinGW.h @@ -65,7 +65,7 @@ bool IsIntegratedAssemblerDefault() const override; bool IsUnwindTablesDefault(const llvm::opt::ArgList &Args) const override; bool isPICDefault() const override; - bool isPIEDefault() const override; + bool isPIEDefault(const llvm::opt::ArgList &Args) const override; bool isPICDefaultForced() const override; SanitizerMask getSupportedSanitizers() const override; Index: clang/lib/Driver/ToolChains/MinGW.cpp =================================================================== --- clang/lib/Driver/ToolChains/MinGW.cpp +++ clang/lib/Driver/ToolChains/MinGW.cpp @@ -98,7 +98,7 @@ const char *LinkingOutput) const { const ToolChain &TC = getToolChain(); const Driver &D = TC.getDriver(); - const SanitizerArgs &Sanitize = TC.getSanitizerArgs(); + const SanitizerArgs &Sanitize = TC.getSanitizerArgs(Args); ArgStringList CmdArgs; @@ -477,7 +477,9 @@ return getArch() == llvm::Triple::x86_64; } -bool toolchains::MinGW::isPIEDefault() const { return false; } +bool toolchains::MinGW::isPIEDefault(const llvm::opt::ArgList &Args) const { + return false; +} bool toolchains::MinGW::isPICDefaultForced() const { return getArch() == llvm::Triple::x86_64; Index: clang/lib/Driver/ToolChains/NetBSD.cpp =================================================================== --- clang/lib/Driver/ToolChains/NetBSD.cpp +++ clang/lib/Driver/ToolChains/NetBSD.cpp @@ -264,7 +264,7 @@ bool NeedsXRayDeps = addXRayRuntime(ToolChain, Args, CmdArgs); AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA); - const SanitizerArgs &SanArgs = ToolChain.getSanitizerArgs(); + const SanitizerArgs &SanArgs = ToolChain.getSanitizerArgs(Args); if (SanArgs.needsSharedRt()) { CmdArgs.push_back("-rpath"); CmdArgs.push_back(Args.MakeArgString(ToolChain.getCompilerRTPath())); @@ -501,7 +501,7 @@ void NetBSD::addClangTargetOptions(const ArgList &DriverArgs, ArgStringList &CC1Args, Action::OffloadKind) const { - const SanitizerArgs &SanArgs = getSanitizerArgs(); + const SanitizerArgs &SanArgs = getSanitizerArgs(DriverArgs); if (SanArgs.hasAnySanitizer()) CC1Args.push_back("-D_REENTRANT"); Index: clang/lib/Driver/ToolChains/OpenBSD.h =================================================================== --- clang/lib/Driver/ToolChains/OpenBSD.h +++ clang/lib/Driver/ToolChains/OpenBSD.h @@ -59,7 +59,9 @@ bool IsMathErrnoDefault() const override { return false; } bool IsObjCNonFragileABIDefault() const override { return true; } - bool isPIEDefault() const override { return true; } + bool isPIEDefault(const llvm::opt::ArgList &Args) const override { + return true; + } RuntimeLibType GetDefaultRuntimeLibType() const override { return ToolChain::RLT_CompilerRT; Index: clang/lib/Driver/ToolChains/PS4CPU.h =================================================================== --- clang/lib/Driver/ToolChains/PS4CPU.h +++ clang/lib/Driver/ToolChains/PS4CPU.h @@ -23,7 +23,8 @@ void addProfileRTArgs(const ToolChain &TC, const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs); -void addSanitizerArgs(const ToolChain &TC, llvm::opt::ArgStringList &CmdArgs); +void addSanitizerArgs(const ToolChain &TC, const llvm::opt::ArgList &Args, + llvm::opt::ArgStringList &CmdArgs); class LLVM_LIBRARY_VISIBILITY Assemble : public Tool { public: Index: clang/lib/Driver/ToolChains/PS4CPU.cpp =================================================================== --- clang/lib/Driver/ToolChains/PS4CPU.cpp +++ clang/lib/Driver/ToolChains/PS4CPU.cpp @@ -71,8 +71,9 @@ Exec, CmdArgs, Inputs, Output)); } -static void AddPS4SanitizerArgs(const ToolChain &TC, ArgStringList &CmdArgs) { - const SanitizerArgs &SanArgs = TC.getSanitizerArgs(); +static void AddPS4SanitizerArgs(const ToolChain &TC, const ArgList &Args, + ArgStringList &CmdArgs) { + const SanitizerArgs &SanArgs = TC.getSanitizerArgs(Args); if (SanArgs.needsUbsanRt()) { CmdArgs.push_back("-lSceDbgUBSanitizer_stub_weak"); } @@ -81,9 +82,9 @@ } } -void tools::PS4cpu::addSanitizerArgs(const ToolChain &TC, +void tools::PS4cpu::addSanitizerArgs(const ToolChain &TC, const ArgList &Args, ArgStringList &CmdArgs) { - const SanitizerArgs &SanArgs = TC.getSanitizerArgs(); + const SanitizerArgs &SanArgs = TC.getSanitizerArgs(Args); if (SanArgs.needsUbsanRt()) CmdArgs.push_back("--dependent-lib=libSceDbgUBSanitizer_stub_weak.a"); if (SanArgs.needsAsanRt()) @@ -127,7 +128,7 @@ } if(!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) - AddPS4SanitizerArgs(ToolChain, CmdArgs); + AddPS4SanitizerArgs(ToolChain, Args, CmdArgs); Args.AddAllArgs(CmdArgs, options::OPT_L); Args.AddAllArgs(CmdArgs, options::OPT_T_Group); Index: clang/lib/Driver/ToolChains/TCE.h =================================================================== --- clang/lib/Driver/ToolChains/TCE.h +++ clang/lib/Driver/ToolChains/TCE.h @@ -27,7 +27,7 @@ bool IsMathErrnoDefault() const override; bool isPICDefault() const override; - bool isPIEDefault() const override; + bool isPIEDefault(const llvm::opt::ArgList &Args) const override; bool isPICDefaultForced() const override; }; Index: clang/lib/Driver/ToolChains/TCE.cpp =================================================================== --- clang/lib/Driver/ToolChains/TCE.cpp +++ clang/lib/Driver/ToolChains/TCE.cpp @@ -34,7 +34,9 @@ bool TCEToolChain::isPICDefault() const { return false; } -bool TCEToolChain::isPIEDefault() const { return false; } +bool TCEToolChain::isPIEDefault(const llvm::opt::ArgList &Args) const { + return false; +} bool TCEToolChain::isPICDefaultForced() const { return false; } Index: clang/lib/Driver/ToolChains/VEToolchain.h =================================================================== --- clang/lib/Driver/ToolChains/VEToolchain.h +++ clang/lib/Driver/ToolChains/VEToolchain.h @@ -28,7 +28,7 @@ public: bool IsIntegratedAssemblerDefault() const override { return true; } bool isPICDefault() const override; - bool isPIEDefault() const override; + bool isPIEDefault(const llvm::opt::ArgList &Args) const override; bool isPICDefaultForced() const override; bool SupportsProfiling() const override; bool hasBlocksRuntime() const override; Index: clang/lib/Driver/ToolChains/VEToolchain.cpp =================================================================== --- clang/lib/Driver/ToolChains/VEToolchain.cpp +++ clang/lib/Driver/ToolChains/VEToolchain.cpp @@ -53,7 +53,9 @@ bool VEToolChain::isPICDefault() const { return false; } -bool VEToolChain::isPIEDefault() const { return false; } +bool VEToolChain::isPIEDefault(const llvm::opt::ArgList &Args) const { + return false; +} bool VEToolChain::isPICDefaultForced() const { return false; } Index: clang/lib/Driver/ToolChains/WebAssembly.h =================================================================== --- clang/lib/Driver/ToolChains/WebAssembly.h +++ clang/lib/Driver/ToolChains/WebAssembly.h @@ -45,7 +45,7 @@ bool IsObjCNonFragileABIDefault() const override; bool UseObjCMixedDispatch() const override; bool isPICDefault() const override; - bool isPIEDefault() const override; + bool isPIEDefault(const llvm::opt::ArgList &Args) const override; bool isPICDefaultForced() const override; bool IsIntegratedAssemblerDefault() const override; bool hasBlocksRuntime() const override; Index: clang/lib/Driver/ToolChains/WebAssembly.cpp =================================================================== --- clang/lib/Driver/ToolChains/WebAssembly.cpp +++ clang/lib/Driver/ToolChains/WebAssembly.cpp @@ -201,7 +201,9 @@ bool WebAssembly::isPICDefault() const { return false; } -bool WebAssembly::isPIEDefault() const { return false; } +bool WebAssembly::isPIEDefault(const llvm::opt::ArgList &Args) const { + return false; +} bool WebAssembly::isPICDefaultForced() const { return false; } Index: clang/lib/Driver/ToolChains/XCore.h =================================================================== --- clang/lib/Driver/ToolChains/XCore.h +++ clang/lib/Driver/ToolChains/XCore.h @@ -58,7 +58,7 @@ public: bool isPICDefault() const override; - bool isPIEDefault() const override; + bool isPIEDefault(const llvm::opt::ArgList &Args) const override; bool isPICDefaultForced() const override; bool SupportsProfiling() const override; bool hasBlocksRuntime() const override; Index: clang/lib/Driver/ToolChains/XCore.cpp =================================================================== --- clang/lib/Driver/ToolChains/XCore.cpp +++ clang/lib/Driver/ToolChains/XCore.cpp @@ -102,7 +102,9 @@ bool XCoreToolChain::isPICDefault() const { return false; } -bool XCoreToolChain::isPIEDefault() const { return false; } +bool XCoreToolChain::isPIEDefault(const llvm::opt::ArgList &Args) const { + return false; +} bool XCoreToolChain::isPICDefaultForced() const { return false; } Index: clang/lib/Driver/ToolChains/ZOS.h =================================================================== --- clang/lib/Driver/ToolChains/ZOS.h +++ clang/lib/Driver/ToolChains/ZOS.h @@ -23,7 +23,9 @@ ~ZOS() override; bool isPICDefault() const override { return false; } - bool isPIEDefault() const override { return false; } + bool isPIEDefault(const llvm::opt::ArgList &Args) const override { + return false; + } bool isPICDefaultForced() const override { return false; } bool IsIntegratedAssemblerDefault() const override { return true; } Index: clang/test/Driver/hip-sanitize-options.hip =================================================================== --- clang/test/Driver/hip-sanitize-options.hip +++ clang/test/Driver/hip-sanitize-options.hip @@ -1,47 +1,67 @@ // REQUIRES: clang-driver, x86-registered-target, amdgpu-registered-target -// RUN: %clang -### -target x86_64-unknown-linux-gnu --offload-arch=gfx900 \ +// RUN: %clang -### -target x86_64-unknown-linux-gnu --offload-arch=gfx900:xnack+ \ // RUN: -fsanitize=address \ // RUN: -nogpuinc --rocm-path=%S/Inputs/rocm \ -// RUN: %s 2>&1 | FileCheck %s +// RUN: %s 2>&1 | FileCheck -check-prefixes=NORDC %s -// RUN: %clang -### -target x86_64-unknown-linux-gnu --offload-arch=gfx900 \ +// RUN: %clang -### -target x86_64-unknown-linux-gnu --offload-arch=gfx900:xnack+ \ // RUN: -fsanitize=address -fno-gpu-sanitize \ // RUN: -nogpuinc --rocm-path=%S/Inputs/rocm \ // RUN: %s 2>&1 | FileCheck %s -// RUN: %clang -### -target x86_64-unknown-linux-gnu --offload-arch=gfx900 \ +// RUN: %clang -### -target x86_64-unknown-linux-gnu --offload-arch=gfx900:xnack+ \ // RUN: -fsanitize=address -fgpu-sanitize \ // RUN: -nogpuinc --rocm-path=%S/Inputs/rocm \ // RUN: %s 2>&1 | FileCheck -check-prefixes=NORDC %s -// RUN: %clang -### -target x86_64-unknown-linux-gnu --offload-arch=gfx900 \ +// RUN: %clang -### -target x86_64-unknown-linux-gnu --offload-arch=gfx900:xnack+ \ // RUN: -fsanitize=address -fgpu-sanitize -fgpu-rdc \ // RUN: -nogpuinc --rocm-path=%S/Inputs/rocm \ // RUN: %s 2>&1 | FileCheck -check-prefixes=RDC %s -// RUN: %clang -### -target x86_64-unknown-linux-gnu --offload-arch=gfx900 \ +// RUN: %clang -### -target x86_64-unknown-linux-gnu --offload-arch=gfx900:xnack+ \ // RUN: -fsanitize=address -fgpu-sanitize \ // RUN: -nogpuinc --rocm-path=%S/Inputs/rocm-invalid \ // RUN: %s 2>&1 | FileCheck -check-prefixes=FAIL %s // RUN: %clang -### -target x86_64-unknown-linux-gnu --offload-arch=gfx900:xnack- \ -// RUN: -fsanitize=address -fgpu-sanitize \ -// RUN: -nogpuinc --rocm-path=%S/Inputs/rocm \ -// RUN: %s 2>&1 | FileCheck -check-prefix=XNACK %s +// RUN: --offload-arch=gfx900:xnack+ --offload-arch=gfx906 -fsanitize=address -fgpu-sanitize \ +// RUN: -fsanitize=leak -nogpuinc --rocm-path=%S/Inputs/rocm \ +// RUN: %s 2>&1 | FileCheck -check-prefixes=XNACK %s + +// RUN: %clang -### -target x86_64-unknown-linux-gnu --offload-arch=gfx900:xnack- \ +// RUN: --offload-arch=gfx900:xnack+ --offload-arch=gfx906 -fsanitize=address -fgpu-sanitize \ +// RUN: -fsanitize=leak -nogpuinc --rocm-path=%S/Inputs/rocm \ +// RUN: %s 2>&1 | FileCheck -check-prefixes=XNACKNEG %s // CHECK-NOT: {{"[^"]*clang[^"]*".* "-fcuda-is-device".* "-fsanitize=address"}} +// CHECK-NOT: {{"[^"]*clang[^"]*".* "-fcuda-is-device".* "-mlink-bitcode-file" ".*asanrtl.bc"}} // CHECK-NOT: {{"[^"]*lld(\.exe){0,1}".* ".*hip.bc"}} // CHECK: {{"[^"]*clang[^"]*".* "-triple" "x86_64-unknown-linux-gnu".* "-fsanitize=address"}} // NORDC: {{"[^"]*clang[^"]*".* "-emit-obj".* "-fcuda-is-device".* "-mlink-bitcode-file" ".*asanrtl.bc".* "-mlink-builtin-bitcode" ".*hip.bc".* "-fsanitize=address".*}} "-o" "[[OUT:[^"]*.o]]" -// NORDC: {{"[^"]*lld(\.exe){0,1}".*}} "[[OUT]]" {{".*asanrtl.bc" ".*hip.bc"}} +// NORDC-NOT: {{"[^"]*lld(\.exe){0,1}".*}} "[[OUT]]" {{".*asanrtl.bc" ".*hip.bc"}} // NORDC: {{"[^"]*clang[^"]*".* "-triple" "x86_64-unknown-linux-gnu".* "-fsanitize=address"}} // RDC: {{"[^"]*clang[^"]*".* "-triple" "x86_64-unknown-linux-gnu".* "-fsanitize=address"}} -// RDC: {{"[^"]*clang[^"]*".* "-emit-llvm-bc".* "-fcuda-is-device".* "-fsanitize=address".*}} "-o" "[[OUT:[^"]*.bc]]" -// RDC: {{"[^"]*lld(\.exe){0,1}".*}} "[[OUT]]" {{".*asanrtl.bc" ".*hip.bc"}} +// RDC: {{"[^"]*clang[^"]*".* "-emit-llvm-bc".* "-fcuda-is-device".* "-mlink-bitcode-file" ".*asanrtl.bc".* "-mlink-builtin-bitcode" ".*hip.bc".* "-fsanitize=address".*}} "-o" "[[OUT:[^"]*.bc]]" +// RDC-NOT: {{"[^"]*lld(\.exe){0,1}".*}} "[[OUT]]" {{".*asanrtl.bc" ".*hip.bc"}} // FAIL: AMDGPU address sanitizer runtime library (asanrtl) is not found. Please install ROCm device library which supports address sanitizer -// XNACK: error: '-fgpu-sanitize' is not compatible with offload arch 'gfx900:xnack-'. Use an offload arch without 'xnack-' instead +// XNACK-DAG: warning: ignoring '-fsanitize=leak' option as it is not currently supported for target 'amdgcn-amd-amdhsa' +// XNACK-DAG: warning: ignoring '-fsanitize=address' option as it is not currently supported for offload arch 'gfx900:xnack-'. Use it with an offload arch containing 'xnack+' instead +// XNACK-DAG: warning: ignoring '-fsanitize=address' option as it is not currently supported for offload arch 'gfx906'. Use it with an offload arch containing 'xnack+' instead +// XNACK-DAG: {{"[^"]*clang[^"]*".* "-mlink-bitcode-file" ".*asanrtl.bc".* "-target-cpu" "gfx900".* "-target-feature" "\+xnack".* "-fsanitize=address"}} +// XNACK-DAG: {{"[^"]*clang[^"]*".* "-target-cpu" "gfx900".* "-target-feature" "-xnack"}} +// XNACK-DAG: {{"[^"]*clang[^"]*".* "-target-cpu" "gfx906"}} +// XNACK-DAG: {{"[^"]*clang[^"]*".* "-triple" "x86_64-unknown-linux-gnu".* "-fsanitize=address,leak"}} +// XNACKNEG-NOT: {{"[^"]*clang[^"]*".* "-target-cpu" "gfx900".* "-target-feature" "+xnack".* "-fsanitize=address,leak"}} +// XNACKNEG-NOT: {{"[^"]*clang[^"]*".* "-target-cpu" "gfx900".* "-target-feature" "-xnack".* "-fsanitize=address,leak"}} +// XNACKNEG-NOT: {{"[^"]*clang[^"]*".* "-target-cpu" "gfx906".* "-fsanitize=address,leak"}} +// XNACKNEG-NOT: {{"[^"]*clang[^"]*".* "-target-cpu" "gfx900".* "-target-feature" "-xnack".* "-fsanitize=address"}} +// XNACKNEG-NOT: {{"[^"]*clang[^"]*".* "-target-cpu" "gfx906".* "-fsanitize=address"}} +// XNACKNEG-NOT: {{"[^"]*clang[^"]*".* "-mlink-bitcode-file" ".*asanrtl.bc".* "-target-cpu" "gfx900".* "-target-feature" "-xnack"}} +// XNACKNEG-NOT: {{"[^"]*clang[^"]*".* "-mlink-bitcode-file" ".*asanrtl.bc".* "-target-cpu" "gfx906"}} +// XNACKNEG-NOT: {{"[^"]*lld(\.exe){0,1}".* ".*hip.bc"}}