[clang] 448b725 - clang/Driver: Use struct type for BoundArch instead of StringRef (#204748)

via cfe-commits cfe-commits at lists.llvm.org
Mon Jun 22 08:19:25 PDT 2026


Author: Matt Arsenault
Date: 2026-06-22T15:19:18Z
New Revision: 448b725bb78bc288c5f6e3ad27856c92902f6537

URL: https://github.com/llvm/llvm-project/commit/448b725bb78bc288c5f6e3ad27856c92902f6537
DIFF: https://github.com/llvm/llvm-project/commit/448b725bb78bc288c5f6e3ad27856c92902f6537.diff

LOG: clang/Driver: Use struct type for BoundArch instead of StringRef (#204748)

Change BoundArch arguments in the clang driver from StringRef (or
sometimes const char*) to a dedicated struct type that contains both
the architecture string and a parsed OffloadArch enum field. In the
future it may be useful to contain other feature bits here.

Co-Authored-By: Claude Opus 4.6 <noreply at anthropic.com>

Added: 
    

Modified: 
    clang/include/clang/Basic/OffloadArch.h
    clang/include/clang/Driver/Action.h
    clang/include/clang/Driver/Compilation.h
    clang/include/clang/Driver/Driver.h
    clang/include/clang/Driver/Job.h
    clang/include/clang/Driver/SanitizerArgs.h
    clang/include/clang/Driver/ToolChain.h
    clang/lib/Driver/Action.cpp
    clang/lib/Driver/Compilation.cpp
    clang/lib/Driver/Driver.cpp
    clang/lib/Driver/SanitizerArgs.cpp
    clang/lib/Driver/ToolChain.cpp
    clang/lib/Driver/ToolChains/AIX.cpp
    clang/lib/Driver/ToolChains/AIX.h
    clang/lib/Driver/ToolChains/AMDGPU.cpp
    clang/lib/Driver/ToolChains/AMDGPU.h
    clang/lib/Driver/ToolChains/AMDGPUOpenMP.cpp
    clang/lib/Driver/ToolChains/AMDGPUOpenMP.h
    clang/lib/Driver/ToolChains/AVR.cpp
    clang/lib/Driver/ToolChains/AVR.h
    clang/lib/Driver/ToolChains/BareMetal.cpp
    clang/lib/Driver/ToolChains/BareMetal.h
    clang/lib/Driver/ToolChains/CSKYToolChain.cpp
    clang/lib/Driver/ToolChains/CSKYToolChain.h
    clang/lib/Driver/ToolChains/Clang.cpp
    clang/lib/Driver/ToolChains/CommonArgs.cpp
    clang/lib/Driver/ToolChains/CrossWindows.cpp
    clang/lib/Driver/ToolChains/CrossWindows.h
    clang/lib/Driver/ToolChains/Cuda.cpp
    clang/lib/Driver/ToolChains/Cuda.h
    clang/lib/Driver/ToolChains/Darwin.cpp
    clang/lib/Driver/ToolChains/Darwin.h
    clang/lib/Driver/ToolChains/Flang.cpp
    clang/lib/Driver/ToolChains/Flang.h
    clang/lib/Driver/ToolChains/FreeBSD.cpp
    clang/lib/Driver/ToolChains/FreeBSD.h
    clang/lib/Driver/ToolChains/Fuchsia.cpp
    clang/lib/Driver/ToolChains/Fuchsia.h
    clang/lib/Driver/ToolChains/Gnu.cpp
    clang/lib/Driver/ToolChains/Gnu.h
    clang/lib/Driver/ToolChains/HIPAMD.cpp
    clang/lib/Driver/ToolChains/HIPAMD.h
    clang/lib/Driver/ToolChains/HIPSPV.cpp
    clang/lib/Driver/ToolChains/HIPSPV.h
    clang/lib/Driver/ToolChains/HIPUtility.cpp
    clang/lib/Driver/ToolChains/HLSL.cpp
    clang/lib/Driver/ToolChains/HLSL.h
    clang/lib/Driver/ToolChains/Haiku.cpp
    clang/lib/Driver/ToolChains/Haiku.h
    clang/lib/Driver/ToolChains/Hexagon.cpp
    clang/lib/Driver/ToolChains/Hexagon.h
    clang/lib/Driver/ToolChains/Linux.cpp
    clang/lib/Driver/ToolChains/Linux.h
    clang/lib/Driver/ToolChains/MSP430.cpp
    clang/lib/Driver/ToolChains/MSP430.h
    clang/lib/Driver/ToolChains/MSVC.cpp
    clang/lib/Driver/ToolChains/MSVC.h
    clang/lib/Driver/ToolChains/Managarm.cpp
    clang/lib/Driver/ToolChains/Managarm.h
    clang/lib/Driver/ToolChains/MinGW.cpp
    clang/lib/Driver/ToolChains/MinGW.h
    clang/lib/Driver/ToolChains/NetBSD.cpp
    clang/lib/Driver/ToolChains/NetBSD.h
    clang/lib/Driver/ToolChains/OHOS.cpp
    clang/lib/Driver/ToolChains/OHOS.h
    clang/lib/Driver/ToolChains/OpenBSD.cpp
    clang/lib/Driver/ToolChains/OpenBSD.h
    clang/lib/Driver/ToolChains/PS4CPU.cpp
    clang/lib/Driver/ToolChains/PS4CPU.h
    clang/lib/Driver/ToolChains/SPIRVOpenMP.cpp
    clang/lib/Driver/ToolChains/SPIRVOpenMP.h
    clang/lib/Driver/ToolChains/SYCL.cpp
    clang/lib/Driver/ToolChains/SYCL.h
    clang/lib/Driver/ToolChains/Serenity.cpp
    clang/lib/Driver/ToolChains/Serenity.h
    clang/lib/Driver/ToolChains/Solaris.cpp
    clang/lib/Driver/ToolChains/Solaris.h
    clang/lib/Driver/ToolChains/VEToolchain.cpp
    clang/lib/Driver/ToolChains/VEToolchain.h
    clang/lib/Driver/ToolChains/WebAssembly.cpp
    clang/lib/Driver/ToolChains/WebAssembly.h
    clang/lib/Driver/ToolChains/XCore.cpp
    clang/lib/Driver/ToolChains/XCore.h
    clang/lib/Driver/ToolChains/ZOS.cpp
    clang/lib/Driver/ToolChains/ZOS.h
    clang/test/Driver/hip-link-bundle-archive.hip
    clang/test/Driver/hip-phases.hip
    clang/test/Driver/hip-target-id.hip
    clang/test/Driver/hip-toolchain-no-rdc.hip
    clang/unittests/Driver/DXCModeTest.cpp

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/Basic/OffloadArch.h b/clang/include/clang/Basic/OffloadArch.h
index 74501a419e362..dc7840cd78a18 100644
--- a/clang/include/clang/Basic/OffloadArch.h
+++ b/clang/include/clang/Basic/OffloadArch.h
@@ -9,8 +9,10 @@
 #ifndef LLVM_CLANG_BASIC_OFFLOADARCH_H
 #define LLVM_CLANG_BASIC_OFFLOADARCH_H
 
+#include "llvm/ADT/StringRef.h"
+#include <tuple>
+
 namespace llvm {
-class StringRef;
 class Triple;
 } // namespace llvm
 
@@ -163,6 +165,34 @@ OffloadArch StringToOffloadArch(llvm::StringRef S);
 llvm::Triple OffloadArchToTriple(const llvm::Triple &DefaultToolchainTriple,
                                  OffloadArch ID);
 
+/// Represents a bound architecture for offload / multiple architecture
+/// compilation.
+struct BoundArch {
+  llvm::StringRef ArchName;
+
+  /// The parsed offload architecture enum.
+  /// Will be OffloadArch::Unknown if ArchName not recognized.
+  OffloadArch Arch = OffloadArch::Unused;
+
+  BoundArch() = default;
+  explicit BoundArch(llvm::StringRef Name)
+      : ArchName(Name),
+        Arch(Name.empty() ? OffloadArch::Unknown : StringToOffloadArch(Name)) {}
+
+  BoundArch(llvm::StringRef Name, OffloadArch A) : ArchName(Name), Arch(A) {}
+
+  bool empty() const { return ArchName.empty(); }
+  explicit operator bool() const { return Arch != OffloadArch::Unused; }
+
+  bool operator==(const BoundArch &Other) const {
+    return Arch == Other.Arch && ArchName == Other.ArchName;
+  }
+
+  bool operator<(const BoundArch &Other) const {
+    return std::tie(Arch, ArchName) < std::tie(Other.Arch, Other.ArchName);
+  }
+};
+
 } // namespace clang
 
 #endif // LLVM_CLANG_BASIC_OFFLOADARCH_H

diff  --git a/clang/include/clang/Driver/Action.h b/clang/include/clang/Driver/Action.h
index 67937b00f6bcf..bbd6f03dd30da 100644
--- a/clang/include/clang/Driver/Action.h
+++ b/clang/include/clang/Driver/Action.h
@@ -10,6 +10,7 @@
 #define LLVM_CLANG_DRIVER_ACTION_H
 
 #include "clang/Basic/LLVM.h"
+#include "clang/Basic/OffloadArch.h"
 #include "clang/Driver/Types.h"
 #include "clang/Driver/Util.h"
 #include "llvm/ADT/ArrayRef.h"
@@ -131,7 +132,7 @@ class Action {
   OffloadKind OffloadingDeviceKind = OFK_None;
 
   /// The Offloading architecture associated with this action.
-  const char *OffloadingArch = nullptr;
+  BoundArch OffloadingArch;
 
   /// The Offloading toolchain associated with this device action.
   const ToolChain *OffloadingToolChain = nullptr;
@@ -192,14 +193,14 @@ class Action {
 
   /// Set the device offload info of this action and propagate it to its
   /// dependences.
-  void propagateDeviceOffloadInfo(OffloadKind OKind, const char *OArch,
+  void propagateDeviceOffloadInfo(OffloadKind OKind, BoundArch OArch,
                                   const ToolChain *OToolChain);
 
   /// Append the host offload info of this action and propagate it to its
   /// dependences.
-  void propagateHostOffloadInfo(unsigned OKinds, const char *OArch);
+  void propagateHostOffloadInfo(unsigned OKinds, BoundArch OArch);
 
-  void setHostOffloadInfo(unsigned OKinds, const char *OArch) {
+  void setHostOffloadInfo(unsigned OKinds, BoundArch OArch) {
     ActiveOffloadKindMask |= OKinds;
     OffloadingArch = OArch;
   }
@@ -213,7 +214,7 @@ class Action {
   }
 
   OffloadKind getOffloadingDeviceKind() const { return OffloadingDeviceKind; }
-  const char *getOffloadingArch() const { return OffloadingArch; }
+  BoundArch getOffloadingArch() const { return OffloadingArch; }
   const ToolChain *getOffloadingToolChain() const {
     return OffloadingToolChain;
   }
@@ -253,14 +254,14 @@ class InputAction : public Action {
 class BindArchAction : public Action {
   virtual void anchor();
 
-  /// The architecture to bind, or 0 if the default architecture
+  /// The architecture to bind, or empty if the default architecture
   /// should be bound.
-  StringRef ArchName;
+  BoundArch ArchName;
 
 public:
-  BindArchAction(Action *Input, StringRef ArchName);
+  BindArchAction(Action *Input, BoundArch ArchName);
 
-  StringRef getArchName() const { return ArchName; }
+  BoundArch getArch() const { return ArchName; }
 
   static bool classof(const Action *A) {
     return A->getKind() == BindArchClass;
@@ -279,7 +280,7 @@ class OffloadAction final : public Action {
   class DeviceDependences final {
   public:
     using ToolChainList = SmallVector<const ToolChain *, 3>;
-    using BoundArchList = SmallVector<const char *, 3>;
+    using BoundArchList = SmallVector<BoundArch, 3>;
     using OffloadKindList = SmallVector<OffloadKind, 3>;
 
   private:
@@ -303,12 +304,11 @@ class OffloadAction final : public Action {
   public:
     /// Add an action along with the associated toolchain, bound arch, and
     /// offload kind.
-    void add(Action &A, const ToolChain &TC, const char *BoundArch,
-             OffloadKind OKind);
+    void add(Action &A, const ToolChain &TC, BoundArch BA, OffloadKind OKind);
 
     /// Add an action along with the associated toolchain, bound arch, and
     /// offload kinds.
-    void add(Action &A, const ToolChain &TC, const char *BoundArch,
+    void add(Action &A, const ToolChain &TC, BoundArch BA,
              unsigned OffloadKindMask);
 
     /// Get each of the individual arrays.
@@ -330,29 +330,29 @@ class OffloadAction final : public Action {
     const ToolChain &HostToolChain;
 
     /// The architectures that should be used with this action.
-    const char *HostBoundArch = nullptr;
+    BoundArch HostBoundArch;
 
     /// The offload kind of each dependence.
     unsigned HostOffloadKinds = 0u;
 
   public:
-    HostDependence(Action &A, const ToolChain &TC, const char *BoundArch,
+    HostDependence(Action &A, const ToolChain &TC, BoundArch BA,
                    const unsigned OffloadKinds)
-        : HostAction(A), HostToolChain(TC), HostBoundArch(BoundArch),
+        : HostAction(A), HostToolChain(TC), HostBoundArch(BA),
           HostOffloadKinds(OffloadKinds) {}
 
     /// Constructor version that obtains the offload kinds from the device
     /// dependencies.
-    HostDependence(Action &A, const ToolChain &TC, const char *BoundArch,
+    HostDependence(Action &A, const ToolChain &TC, BoundArch BoundArch,
                    const DeviceDependences &DDeps);
     Action *getAction() const { return &HostAction; }
     const ToolChain *getToolChain() const { return &HostToolChain; }
-    const char *getBoundArch() const { return HostBoundArch; }
+    BoundArch getBoundArch() const { return HostBoundArch; }
     unsigned getOffloadKinds() const { return HostOffloadKinds; }
   };
 
   using OffloadActionWorkTy =
-      llvm::function_ref<void(Action *, const ToolChain *, const char *)>;
+      llvm::function_ref<void(Action *, const ToolChain *, BoundArch)>;
 
 private:
   /// The host offloading toolchain that should be used with the action.
@@ -598,13 +598,13 @@ class OffloadUnbundlingJobAction final : public JobAction {
     const ToolChain *DependentToolChain = nullptr;
 
     /// The bound architecture of the dependent action.
-    StringRef DependentBoundArch;
+    BoundArch DependentBoundArch;
 
     /// The offload kind of the dependent action.
     const OffloadKind DependentOffloadKind = OFK_None;
 
     DependentActionInfo(const ToolChain *DependentToolChain,
-                        StringRef DependentBoundArch,
+                        BoundArch DependentBoundArch,
                         const OffloadKind DependentOffloadKind)
         : DependentToolChain(DependentToolChain),
           DependentBoundArch(DependentBoundArch),
@@ -621,9 +621,9 @@ class OffloadUnbundlingJobAction final : public JobAction {
   OffloadUnbundlingJobAction(Action *Input);
 
   /// Register information about a dependent action.
-  void registerDependentActionInfo(const ToolChain *TC, StringRef BoundArch,
+  void registerDependentActionInfo(const ToolChain *TC, BoundArch BA,
                                    OffloadKind Kind) {
-    DependentActionInfoArray.push_back({TC, BoundArch, Kind});
+    DependentActionInfoArray.push_back({TC, BA, Kind});
   }
 
   /// Return the information about all depending actions.

diff  --git a/clang/include/clang/Driver/Compilation.h b/clang/include/clang/Driver/Compilation.h
index 4ad2dc34a1f85..825806b6cfe33 100644
--- a/clang/include/clang/Driver/Compilation.h
+++ b/clang/include/clang/Driver/Compilation.h
@@ -10,6 +10,7 @@
 #define LLVM_CLANG_DRIVER_COMPILATION_H
 
 #include "clang/Basic/LLVM.h"
+#include "clang/Basic/OffloadArch.h"
 #include "clang/Driver/Action.h"
 #include "clang/Driver/Job.h"
 #include "clang/Driver/Util.h"
@@ -82,16 +83,16 @@ class Compilation {
   /// architecture, and device offload kind.
   struct TCArgsKey final {
     const ToolChain *TC = nullptr;
-    StringRef BoundArch;
+    BoundArch BoundArchitecture;
     Action::OffloadKind DeviceOffloadKind = Action::OFK_None;
 
-    TCArgsKey(const ToolChain *TC, StringRef BoundArch,
+    TCArgsKey(const ToolChain *TC, BoundArch BA,
               Action::OffloadKind DeviceOffloadKind)
-        : TC(TC), BoundArch(BoundArch), DeviceOffloadKind(DeviceOffloadKind) {}
+        : TC(TC), BoundArchitecture(BA), DeviceOffloadKind(DeviceOffloadKind) {}
 
     bool operator<(const TCArgsKey &K) const {
-      return std::tie(TC, BoundArch, DeviceOffloadKind) <
-             std::tie(K.TC, K.BoundArch, K.DeviceOffloadKind);
+      return std::tie(TC, BoundArchitecture, DeviceOffloadKind) <
+             std::tie(K.TC, K.BoundArchitecture, K.DeviceOffloadKind);
     }
   };
   std::map<TCArgsKey, llvm::opt::DerivedArgList *> TCArgs;
@@ -128,7 +129,7 @@ class Compilation {
 
   /// The bound architecture currently being built, if any. Set around
   /// ConstructJob calls so addCommand can stamp it onto each new Command.
-  StringRef CurrentBoundArch;
+  BoundArch CurrentBoundArch;
 
 public:
   Compilation(const Driver &D, const ToolChain &DefaultToolChain,
@@ -220,8 +221,8 @@ class Compilation {
     Jobs.addJob(std::move(Cmd));
   }
 
-  StringRef getCurrentBoundArch() const { return CurrentBoundArch; }
-  void setCurrentBoundArch(StringRef Arch) { CurrentBoundArch = Arch; }
+  BoundArch getCurrentBoundArch() const { return CurrentBoundArch; }
+  void setCurrentBoundArch(BoundArch BA) { CurrentBoundArch = BA; }
 
   llvm::opt::ArgStringList &getTempFiles() { return TempFiles; }
   const llvm::opt::ArgStringList &getTempFiles() const { return TempFiles; }
@@ -248,11 +249,11 @@ class Compilation {
   /// If a device offloading kind is specified, a translation specific for that
   /// kind is performed, if any.
   ///
-  /// \param BoundArch - The bound architecture name, or 0.
+  /// \param BA - The bound architecture.
   /// \param DeviceOffloadKind - The offload device kind that should be used in
   /// the translation, if any.
   const llvm::opt::DerivedArgList &
-  getArgsForToolChain(const ToolChain *TC, StringRef BoundArch,
+  getArgsForToolChain(const ToolChain *TC, BoundArch BA,
                       Action::OffloadKind DeviceOffloadKind);
 
   /// addTempFile - Add a file to remove on exit, and returns its

diff  --git a/clang/include/clang/Driver/Driver.h b/clang/include/clang/Driver/Driver.h
index 19a371163f050..eece9ac5293f0 100644
--- a/clang/include/clang/Driver/Driver.h
+++ b/clang/include/clang/Driver/Driver.h
@@ -12,6 +12,7 @@
 #include "clang/Basic/Diagnostic.h"
 #include "clang/Basic/HeaderInclude.h"
 #include "clang/Basic/LLVM.h"
+#include "clang/Basic/OffloadArch.h"
 #include "clang/Driver/Action.h"
 #include "clang/Driver/DriverDiagnostic.h"
 #include "clang/Driver/InputInfo.h"
@@ -523,7 +524,7 @@ class Driver {
   /// Returns the set of bound architectures active for this offload kind.
   /// If there are no bound architctures we return a set containing only the
   /// empty string.
-  llvm::SmallVector<StringRef>
+  llvm::SmallVector<BoundArch>
   getOffloadArchs(Compilation &C, const llvm::opt::DerivedArgList &Args,
                   Action::OffloadKind Kind, const ToolChain &TC) const;
 
@@ -658,7 +659,7 @@ class Driver {
   /// return an InputInfo for the result of running \p A.  Will only construct
   /// jobs for a given (Action, ToolChain, BoundArch, DeviceKind) tuple once.
   InputInfoList BuildJobsForAction(
-      Compilation &C, const Action *A, const ToolChain *TC, StringRef BoundArch,
+      Compilation &C, const Action *A, const ToolChain *TC, BoundArch BA,
       bool AtTopLevel, bool MultipleArchs, const char *LinkingOutput,
       std::map<std::pair<const Action *, std::string>, InputInfoList>
           &CachedResults,
@@ -668,17 +669,17 @@ class Driver {
   const char *getDefaultImageName() const;
 
   /// Creates a temp file.
-  /// 1. If \p MultipleArch is false or \p BoundArch is empty, the temp file is
+  /// 1. If \p MultipleArch is false or \p BA is empty, the temp file is
   ///    in the temporary directory with name $Prefix-%%%%%%.$Suffix.
-  /// 2. If \p MultipleArch is true and \p BoundArch is not empty,
+  /// 2. If \p MultipleArch is true and \p BA is not empty,
   ///    2a. If \p NeedUniqueDirectory is false, the temp file is in the
-  ///        temporary directory with name $Prefix-$BoundArch-%%%%%.$Suffix.
+  ///        temporary directory with name $Prefix-$BA-%%%%%.$Suffix.
   ///    2b. If \p NeedUniqueDirectory is true, the temp file is in a unique
   ///        subdiretory with random name under the temporary directory, and
-  ///        the temp file itself has name $Prefix-$BoundArch.$Suffix.
+  ///        the temp file itself has name $Prefix-$BA.$Suffix.
   const char *CreateTempFile(Compilation &C, StringRef Prefix, StringRef Suffix,
                              bool MultipleArchs = false,
-                             StringRef BoundArch = {},
+                             StringRef BoundArchStr = {},
                              bool NeedUniqueDirectory = false) const;
 
   /// GetNamedOutputPath - Return the name to use for the output of
@@ -689,12 +690,12 @@ class Driver {
   /// \param JA - The action of interest.
   /// \param BaseInput - The original input file that this action was
   /// triggered by.
-  /// \param BoundArch - The bound architecture.
+  /// \param BA - The bound architecture.
   /// \param AtTopLevel - Whether this is a "top-level" action.
   /// \param MultipleArchs - Whether multiple -arch options were supplied.
   /// \param NormalizedTriple - The normalized triple of the relevant target.
   const char *GetNamedOutputPath(Compilation &C, const JobAction &JA,
-                                 const char *BaseInput, StringRef BoundArch,
+                                 const char *BaseInput, BoundArch BA,
                                  bool AtTopLevel, bool MultipleArchs,
                                  StringRef NormalizedTriple) const;
 
@@ -785,7 +786,7 @@ class Driver {
   /// jobs specifically for the given action, but will use the cache when
   /// building jobs for the Action's inputs.
   InputInfoList BuildJobsForActionNoCache(
-      Compilation &C, const Action *A, const ToolChain *TC, StringRef BoundArch,
+      Compilation &C, const Action *A, const ToolChain *TC, BoundArch BA,
       bool AtTopLevel, bool MultipleArchs, const char *LinkingOutput,
       std::map<std::pair<const Action *, std::string>, InputInfoList>
           &CachedResults,

diff  --git a/clang/include/clang/Driver/Job.h b/clang/include/clang/Driver/Job.h
index 116254f79ae6f..56a147e717237 100644
--- a/clang/include/clang/Driver/Job.h
+++ b/clang/include/clang/Driver/Job.h
@@ -10,6 +10,7 @@
 #define LLVM_CLANG_DRIVER_JOB_H
 
 #include "clang/Basic/LLVM.h"
+#include "clang/Basic/OffloadArch.h"
 #include "clang/Driver/InputInfo.h"
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/SmallVector.h"
@@ -152,7 +153,7 @@ class Command {
 
   /// The bound architecture for this command (e.g. "arm64", "x86_64").
   /// Non-empty only for Darwin multi-arch builds.
-  std::string BoundArch;
+  std::string BoundArchStr;
 
   /// When a response file is needed, we try to put most arguments in an
   /// exclusive file, while others remains as regular command line arguments.
@@ -195,8 +196,8 @@ class Command {
   const Tool &getCreator() const { return Creator; }
 
   /// Return the bound architecture for this command, if any.
-  StringRef getBoundArch() const { return BoundArch; }
-  void setBoundArch(StringRef Arch) { BoundArch = std::string(Arch); }
+  BoundArch getBoundArch() const { return BoundArch(BoundArchStr); }
+  void setBoundArch(BoundArch BA) { BoundArchStr = BA.ArchName.str(); }
 
   /// Returns the kind of response file supported by the current invocation.
   const ResponseFileSupport &getResponseFileSupport() {

diff  --git a/clang/include/clang/Driver/SanitizerArgs.h b/clang/include/clang/Driver/SanitizerArgs.h
index d4ee17802fd8e..6a01b3e36d44c 100644
--- a/clang/include/clang/Driver/SanitizerArgs.h
+++ b/clang/include/clang/Driver/SanitizerArgs.h
@@ -8,6 +8,7 @@
 #ifndef LLVM_CLANG_DRIVER_SANITIZERARGS_H
 #define LLVM_CLANG_DRIVER_SANITIZERARGS_H
 
+#include "clang/Basic/OffloadArch.h"
 #include "clang/Basic/Sanitizers.h"
 #include "clang/Driver/Action.h"
 #include "clang/Driver/Types.h"
@@ -87,7 +88,7 @@ class SanitizerArgs {
   /// Parses the sanitizer arguments from an argument list.
   SanitizerArgs(const ToolChain &TC, const llvm::opt::ArgList &Args,
                 bool DiagnoseErrors = true, bool DiagnoseBoundArchErrors = true,
-                StringRef BoundArch = "",
+                BoundArch BA = {},
                 Action::OffloadKind DeviceOffloadKind = Action::OFK_None);
 
   bool needsSharedRt() const { return SharedRuntime; }

diff  --git a/clang/include/clang/Driver/ToolChain.h b/clang/include/clang/Driver/ToolChain.h
index 8953c299268df..863ba1084cb1a 100644
--- a/clang/include/clang/Driver/ToolChain.h
+++ b/clang/include/clang/Driver/ToolChain.h
@@ -11,6 +11,7 @@
 
 #include "clang/Basic/LLVM.h"
 #include "clang/Basic/LangOptions.h"
+#include "clang/Basic/OffloadArch.h"
 #include "clang/Basic/Sanitizers.h"
 #include "clang/Driver/Action.h"
 #include "clang/Driver/Multilib.h"
@@ -347,7 +348,7 @@ class ToolChain {
   Multilib::flags_list getMultilibFlags(const llvm::opt::ArgList &) const;
 
   SanitizerArgs getSanitizerArgs(
-      const llvm::opt::ArgList &JobArgs, StringRef BoundArch = "",
+      const llvm::opt::ArgList &JobArgs, BoundArch BA = {},
       Action::OffloadKind DeviceOffloadKind = Action::OFK_None) const;
 
   /// Returns the feature requirement for a sanitizer on a specific arch for
@@ -355,7 +356,7 @@ class ToolChain {
   /// the sanitizer is generally supported but requires a specific feature for
   /// the given BoundArch, or an empty StringRef otherwise.
   virtual StringRef getSanitizerRequirement(SanitizerMask Kinds,
-                                            StringRef BoundArch) const {
+                                            BoundArch BA) const {
     return {};
   }
 
@@ -393,11 +394,11 @@ class ToolChain {
   /// specific translations are needed. If \p DeviceOffloadKind is specified
   /// the translation specific for that offload kind is performed.
   ///
-  /// \param BoundArch - The bound architecture name, or 0.
+  /// \param BA - The bound architecture.
   /// \param DeviceOffloadKind - The device offload kind used for the
   /// translation.
   virtual llvm::opt::DerivedArgList *
-  TranslateArgs(const llvm::opt::DerivedArgList &Args, StringRef BoundArch,
+  TranslateArgs(const llvm::opt::DerivedArgList &Args, BoundArch BA,
                 Action::OffloadKind DeviceOffloadKind) const {
     return nullptr;
   }
@@ -421,7 +422,7 @@ class ToolChain {
   /// a null pointer, otherwise return a DerivedArgList containing the
   /// translated arguments.
   virtual llvm::opt::DerivedArgList *
-  TranslateXarchArgs(const llvm::opt::DerivedArgList &Args, StringRef BoundArch,
+  TranslateXarchArgs(const llvm::opt::DerivedArgList &Args, BoundArch BA,
                      Action::OffloadKind DeviceOffloadKind,
                      SmallVectorImpl<llvm::opt::Arg *> *AllocatedArgs) const;
 
@@ -715,7 +716,7 @@ class ToolChain {
   /// ComputeLLVMTriple - Return the LLVM target triple to use, after taking
   /// command line arguments into account.
   virtual std::string
-  ComputeLLVMTriple(const llvm::opt::ArgList &Args, StringRef BoundArch = {},
+  ComputeLLVMTriple(const llvm::opt::ArgList &Args, BoundArch BA = {},
                     types::ID InputType = types::TY_INVALID) const;
 
   /// ComputeEffectiveClangTriple - Return the Clang triple to use for this
@@ -724,8 +725,7 @@ class ToolChain {
   /// sets the deployment target) determines the version in the triple passed to
   /// Clang.
   virtual std::string
-  ComputeEffectiveClangTriple(const llvm::opt::ArgList &Args,
-                              StringRef BoundArch = {},
+  ComputeEffectiveClangTriple(const llvm::opt::ArgList &Args, BoundArch BA = {},
                               types::ID InputType = types::TY_INVALID) const;
 
   /// getDefaultObjCRuntime - Return the default Objective-C runtime
@@ -754,9 +754,10 @@ class ToolChain {
                             llvm::opt::ArgStringList &CC1Args) const;
 
   /// Add options that need to be passed to cc1 for this target.
-  virtual void addClangTargetOptions(
-      const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args,
-      llvm::StringRef BoundArch, Action::OffloadKind DeviceOffloadKind) const;
+  virtual void
+  addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
+                        llvm::opt::ArgStringList &CC1Args, BoundArch BA,
+                        Action::OffloadKind DeviceOffloadKind) const;
 
   /// Add options that need to be passed to cc1as for this target.
   virtual void
@@ -868,7 +869,7 @@ class ToolChain {
 
   /// Get paths for device libraries.
   virtual llvm::SmallVector<BitCodeLibraryInfo, 12>
-  getDeviceLibs(const llvm::opt::ArgList &Args, llvm::StringRef BoundArch,
+  getDeviceLibs(const llvm::opt::ArgList &Args, BoundArch BA,
                 const Action::OffloadKind DeviceOffloadingKind) const;
 
   /// Add the system specific libraries for the active offload kinds.
@@ -878,7 +879,7 @@ class ToolChain {
 
   /// Return sanitizers which are available in this toolchain.
   virtual SanitizerMask
-  getSupportedSanitizers(StringRef BoundArch,
+  getSupportedSanitizers(BoundArch BA,
                          Action::OffloadKind DeviceOffloadKind) const;
 
   /// Return sanitizers which are enabled by default.

diff  --git a/clang/lib/Driver/Action.cpp b/clang/lib/Driver/Action.cpp
index 72a42a6f957ee..c0b84ffcc95be 100644
--- a/clang/lib/Driver/Action.cpp
+++ b/clang/lib/Driver/Action.cpp
@@ -59,7 +59,7 @@ const char *Action::getClassName(ActionClass AC) {
   llvm_unreachable("invalid class");
 }
 
-void Action::propagateDeviceOffloadInfo(OffloadKind OKind, const char *OArch,
+void Action::propagateDeviceOffloadInfo(OffloadKind OKind, BoundArch OArch,
                                         const ToolChain *OToolChain) {
   // Offload action set its own kinds on their dependences.
   if (Kind == OffloadClass)
@@ -79,7 +79,7 @@ void Action::propagateDeviceOffloadInfo(OffloadKind OKind, const char *OArch,
     A->propagateDeviceOffloadInfo(OffloadingDeviceKind, OArch, OToolChain);
 }
 
-void Action::propagateHostOffloadInfo(unsigned OKinds, const char *OArch) {
+void Action::propagateHostOffloadInfo(unsigned OKinds, BoundArch OArch) {
   // Offload action set its own kinds on their dependences.
   if (Kind == OffloadClass)
     return;
@@ -188,7 +188,7 @@ InputAction::InputAction(const Arg &_Input, types::ID _Type, StringRef _Id)
 
 void BindArchAction::anchor() {}
 
-BindArchAction::BindArchAction(Action *Input, StringRef ArchName)
+BindArchAction::BindArchAction(Action *Input, BoundArch ArchName)
     : Action(BindArchClass, Input), ArchName(ArchName) {}
 
 void OffloadAction::anchor() {}
@@ -198,7 +198,7 @@ OffloadAction::OffloadAction(const HostDependence &HDep)
   OffloadingArch = HDep.getBoundArch();
   ActiveOffloadKindMask = HDep.getOffloadKinds();
   HDep.getAction()->propagateHostOffloadInfo(HDep.getOffloadKinds(),
-                                             HDep.getBoundArch());
+                                             OffloadingArch);
 }
 
 OffloadAction::OffloadAction(const DeviceDependences &DDeps, types::ID Ty)
@@ -226,10 +226,9 @@ OffloadAction::OffloadAction(const HostDependence &HDep,
     : Action(OffloadClass, HDep.getAction()), HostTC(HDep.getToolChain()),
       DevToolChains(DDeps.getToolChains()) {
   // We use the kinds of the host dependence for this action.
-  OffloadingArch = HDep.getBoundArch();
+  BoundArch BA = HDep.getBoundArch();
   ActiveOffloadKindMask = HDep.getOffloadKinds();
-  HDep.getAction()->propagateHostOffloadInfo(HDep.getOffloadKinds(),
-                                             HDep.getBoundArch());
+  HDep.getAction()->propagateHostOffloadInfo(HDep.getOffloadKinds(), BA);
 
   // Add device inputs and propagate info to the device actions. Do work only if
   // we have dependencies.
@@ -314,20 +313,19 @@ OffloadAction::getSingleDeviceDependence(bool DoNotConsiderHostActions) const {
 }
 
 void OffloadAction::DeviceDependences::add(Action &A, const ToolChain &TC,
-                                           const char *BoundArch,
-                                           OffloadKind OKind) {
+                                           BoundArch BA, OffloadKind OKind) {
   DeviceActions.push_back(&A);
   DeviceToolChains.push_back(&TC);
-  DeviceBoundArchs.push_back(BoundArch);
+  DeviceBoundArchs.push_back(BA);
   DeviceOffloadKinds.push_back(OKind);
 }
 
 void OffloadAction::DeviceDependences::add(Action &A, const ToolChain &TC,
-                                           const char *BoundArch,
+                                           BoundArch BA,
                                            unsigned OffloadKindMask) {
   DeviceActions.push_back(&A);
   DeviceToolChains.push_back(&TC);
-  DeviceBoundArchs.push_back(BoundArch);
+  DeviceBoundArchs.push_back(BA);
 
   // Add each active offloading kind from a mask.
   for (OffloadKind OKind : {OFK_OpenMP, OFK_Cuda, OFK_HIP, OFK_SYCL})
@@ -336,9 +334,9 @@ void OffloadAction::DeviceDependences::add(Action &A, const ToolChain &TC,
 }
 
 OffloadAction::HostDependence::HostDependence(Action &A, const ToolChain &TC,
-                                              const char *BoundArch,
+                                              BoundArch BA,
                                               const DeviceDependences &DDeps)
-    : HostAction(A), HostToolChain(TC), HostBoundArch(BoundArch) {
+    : HostAction(A), HostToolChain(TC), HostBoundArch(BA) {
   for (auto K : DDeps.getOffloadKinds())
     HostOffloadKinds |= K;
 }

diff  --git a/clang/lib/Driver/Compilation.cpp b/clang/lib/Driver/Compilation.cpp
index f8ca2a3d09407..377ac7e2ad43e 100644
--- a/clang/lib/Driver/Compilation.cpp
+++ b/clang/lib/Driver/Compilation.cpp
@@ -55,12 +55,12 @@ Compilation::~Compilation() {
 }
 
 const DerivedArgList &
-Compilation::getArgsForToolChain(const ToolChain *TC, StringRef BoundArch,
+Compilation::getArgsForToolChain(const ToolChain *TC, BoundArch BA,
                                  Action::OffloadKind DeviceOffloadKind) {
   if (!TC)
     TC = &DefaultToolChain;
 
-  DerivedArgList *&Entry = TCArgs[{TC, BoundArch, DeviceOffloadKind}];
+  DerivedArgList *&Entry = TCArgs[{TC, BA, DeviceOffloadKind}];
   if (!Entry) {
     SmallVector<Arg *, 4> AllocatedArgs;
     DerivedArgList *OpenMPArgs = nullptr;
@@ -74,10 +74,10 @@ Compilation::getArgsForToolChain(const ToolChain *TC, StringRef BoundArch,
 
     DerivedArgList *NewDAL = nullptr;
     if (!OpenMPArgs) {
-      NewDAL = TC->TranslateXarchArgs(*TranslatedArgs, BoundArch,
-                                      DeviceOffloadKind, &AllocatedArgs);
+      NewDAL = TC->TranslateXarchArgs(*TranslatedArgs, BA, DeviceOffloadKind,
+                                      &AllocatedArgs);
     } else {
-      NewDAL = TC->TranslateXarchArgs(*OpenMPArgs, BoundArch, DeviceOffloadKind,
+      NewDAL = TC->TranslateXarchArgs(*OpenMPArgs, BA, DeviceOffloadKind,
                                       &AllocatedArgs);
       if (!NewDAL)
         NewDAL = OpenMPArgs;
@@ -86,11 +86,11 @@ Compilation::getArgsForToolChain(const ToolChain *TC, StringRef BoundArch,
     }
 
     if (!NewDAL) {
-      Entry = TC->TranslateArgs(*TranslatedArgs, BoundArch, DeviceOffloadKind);
+      Entry = TC->TranslateArgs(*TranslatedArgs, BA, DeviceOffloadKind);
       if (!Entry)
         Entry = TranslatedArgs;
     } else {
-      Entry = TC->TranslateArgs(*NewDAL, BoundArch, DeviceOffloadKind);
+      Entry = TC->TranslateArgs(*NewDAL, BA, DeviceOffloadKind);
       if (!Entry)
         Entry = NewDAL;
       else

diff  --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp
index e67886abc35b6..ea06235de5c1f 100644
--- a/clang/lib/Driver/Driver.cpp
+++ b/clang/lib/Driver/Driver.cpp
@@ -2101,7 +2101,7 @@ void Driver::generateCompilationDiagnostics(
   }
   if (ArchNames.size() > 1) {
     // Build a reproducer only for the bound arch that crashed.
-    StringRef FailingArch = Cmd.getBoundArch();
+    StringRef FailingArch = Cmd.getBoundArch().ArchName;
     if (FailingArch.empty()) {
       Diag(clang::diag::note_drv_command_failed_diag_msg)
           << "Error generating preprocessed source(s) - cannot generate "
@@ -2732,7 +2732,8 @@ bool Driver::HandleImmediateArgs(Compilation &C) {
     // FIXME: Remove when darwin's toolchain is initialized during construction.
     // FIXME: For some more esoteric targets the default toolchain is not the
     //        correct one.
-    C.getArgsForToolChain(&TC, Triple.getArchName(), Action::OFK_Host);
+    C.getArgsForToolChain(&TC, BoundArch(Triple.getArchName()),
+                          Action::OFK_Host);
     RegisterEffectiveTriple TripleRAII(TC, Triple);
     switch (RLT) {
     case ToolChain::RLT_CompilerRT:
@@ -2823,31 +2824,30 @@ static unsigned PrintActions1(const Compilation &C, Action *A,
   if (InputAction *IA = dyn_cast<InputAction>(A)) {
     os << "\"" << IA->getInputArg().getValue() << "\"";
   } else if (BindArchAction *BIA = dyn_cast<BindArchAction>(A)) {
-    os << '"' << BIA->getArchName() << '"' << ", {"
+    os << '"' << BIA->getArch().ArchName << '"' << ", {"
        << PrintActions1(C, *BIA->input_begin(), Ids, SibIndent, SibKind) << "}";
   } else if (OffloadAction *OA = dyn_cast<OffloadAction>(A)) {
     bool IsFirst = true;
-    OA->doOnEachDependence(
-        [&](Action *A, const ToolChain *TC, const char *BoundArch) {
-          assert(TC && "Unknown host toolchain");
-          // E.g. for two CUDA device dependences whose bound arch is sm_20 and
-          // sm_35 this will generate:
-          // "cuda-device" (nvptx64-nvidia-cuda:sm_20) {#ID}, "cuda-device"
-          // (nvptx64-nvidia-cuda:sm_35) {#ID}
-          if (!IsFirst)
-            os << ", ";
-          os << '"';
-          os << A->getOffloadingKindPrefix();
-          os << " (";
-          os << TC->getTripleString();
-          if (BoundArch)
-            os << ":" << BoundArch;
-          os << ")";
-          os << '"';
-          os << " {" << PrintActions1(C, A, Ids, SibIndent, SibKind) << "}";
-          IsFirst = false;
-          SibKind = OtherSibAction;
-        });
+    OA->doOnEachDependence([&](Action *A, const ToolChain *TC, BoundArch BA) {
+      assert(TC && "Unknown host toolchain");
+      // E.g. for two CUDA device dependences whose bound arch is sm_20 and
+      // sm_35 this will generate:
+      // "cuda-device" (nvptx64-nvidia-cuda:sm_20) {#ID}, "cuda-device"
+      // (nvptx64-nvidia-cuda:sm_35) {#ID}
+      if (!IsFirst)
+        os << ", ";
+      os << '"';
+      os << A->getOffloadingKindPrefix();
+      os << " (";
+      os << TC->getTripleString();
+      if (!BA.empty())
+        os << ":" << BA.ArchName;
+      os << ")";
+      os << '"';
+      os << " {" << PrintActions1(C, A, Ids, SibIndent, SibKind) << "}";
+      IsFirst = false;
+      SibKind = OtherSibAction;
+    });
   } else {
     const ActionList *AL = &A->getInputs();
 
@@ -2871,8 +2871,8 @@ static unsigned PrintActions1(const Compilation &C, Action *A,
     auto S = A->getOffloadingKindPrefix();
     if (!S.empty()) {
       offload_os << ", (" << S;
-      if (A->getOffloadingArch())
-        offload_os << ", " << A->getOffloadingArch();
+      if (!A->getOffloadingArch().empty())
+        offload_os << ", " << A->getOffloadingArch().ArchName;
       offload_os << ")";
     }
   }
@@ -2956,7 +2956,7 @@ void Driver::BuildUniversalActions(Compilation &C, const ToolChain &TC,
 
     ActionList Inputs;
     for (unsigned i = 0, e = Archs.size(); i != e; ++i)
-      Inputs.push_back(C.MakeAction<BindArchAction>(Act, Archs[i]));
+      Inputs.push_back(C.MakeAction<BindArchAction>(Act, BoundArch(Archs[i])));
 
     // Lipo if necessary, we do it this way because we need to set the arch flag
     // so that -Xarch_ gets overwritten.
@@ -3415,20 +3415,8 @@ class OffloadingActionBuilder final {
     bool EmitLLVM = false;
     bool EmitAsm = false;
 
-    /// ID to identify each device compilation. For CUDA it is simply the
-    /// GPU arch string. For HIP it is either the GPU arch string or GPU
-    /// arch string plus feature strings delimited by a plus sign, e.g.
-    /// gfx906+xnack.
-    struct TargetID {
-      /// Target ID string which is persistent throughout the compilation.
-      const char *ID;
-      TargetID(OffloadArch Arch) { ID = OffloadArchToString(Arch); }
-      TargetID(const char *ID) : ID(ID) {}
-      operator const char *() { return ID; }
-      operator StringRef() { return StringRef(ID); }
-    };
     /// List of GPU architectures to use in this compilation.
-    SmallVector<TargetID, 4> GpuArchList;
+    SmallVector<BoundArch, 4> GpuArchList;
 
     /// The CUDA actions for the current input.
     ActionList CudaDeviceActions;
@@ -3536,16 +3524,15 @@ class OffloadingActionBuilder final {
 
     void appendTopLevelActions(ActionList &AL) override {
       // Utility to append actions to the top level list.
-      auto AddTopLevel = [&](Action *A, TargetID TargetID,
-                             const ToolChain *TC) {
+      auto AddTopLevel = [&](Action *A, BoundArch BA, const ToolChain *TC) {
         OffloadAction::DeviceDependences Dep;
-        Dep.add(*A, *TC, TargetID, AssociatedOffloadKind);
+        Dep.add(*A, *TC, BA, AssociatedOffloadKind);
         AL.push_back(C.MakeAction<OffloadAction>(Dep, A->getType()));
       };
 
       // If we have a fat binary, add it to the list.
       if (CudaFatBinary) {
-        AddTopLevel(CudaFatBinary, OffloadArch::Unused, FatBinaryToolChain);
+        AddTopLevel(CudaFatBinary, {}, FatBinaryToolChain);
         CudaDeviceActions.clear();
         CudaFatBinary = nullptr;
         return;
@@ -3595,7 +3582,7 @@ class OffloadingActionBuilder final {
         return true;
       }
 
-      std::set<std::pair<StringRef, const ToolChain *>> GpuArchs;
+      std::set<std::pair<BoundArch, const ToolChain *>> GpuArchs;
       for (Action::OffloadKind Kind : {Action::OFK_Cuda, Action::OFK_HIP}) {
         for (auto &I : llvm::make_range(C.getOffloadToolChains(Kind))) {
           for (auto Arch :
@@ -3605,7 +3592,7 @@ class OffloadingActionBuilder final {
       }
 
       for (auto [Arch, TC] : GpuArchs) {
-        GpuArchList.push_back(Arch.data());
+        GpuArchList.push_back(Arch);
         ToolChains.push_back(TC);
       }
 
@@ -3706,7 +3693,7 @@ class OffloadingActionBuilder final {
               C.MakeAction<LinkJobAction>(DeviceActions, types::TY_CUDA_FATBIN);
 
           if (!CompileDeviceOnly) {
-            DA.add(*CudaFatBinary, *FatBinaryToolChain, /*BoundArch=*/nullptr,
+            DA.add(*CudaFatBinary, *FatBinaryToolChain, /*BA=*/{},
                    Action::OFK_Cuda);
             // Clear the fat binary, it is already a dependence to an host
             // action.
@@ -3842,7 +3829,7 @@ class OffloadingActionBuilder final {
             Action *BackendAction = nullptr;
             if (ToolChains[I]->getTriple().isSPIRV() ||
                 (ToolChains[I]->getTriple().isAMDGCN() &&
-                 GpuArchList[I] == StringRef("amdgcnspirv"))) {
+                 GpuArchList[I].ArchName == StringRef("amdgcnspirv"))) {
               // Emit LLVM bitcode for SPIR-V targets. SPIR-V device tool chain
               // (HIPSPVToolChain or HIPAMDToolChain) runs post-link LLVM IR
               // passes.
@@ -3885,7 +3872,7 @@ class OffloadingActionBuilder final {
                                                       types::TY_HIP_FATBIN);
 
           if (!CompileDeviceOnly) {
-            DA.add(*CudaFatBinary, *FatBinaryToolChain, /*BoundArch=*/nullptr,
+            DA.add(*CudaFatBinary, *FatBinaryToolChain, /*BA=*/{},
                    AssociatedOffloadKind);
             // Clear the fat binary, it is already a dependence to an host
             // action.
@@ -3989,7 +3976,7 @@ class OffloadingActionBuilder final {
         auto *TopDeviceLinkAction = C.MakeAction<LinkJobAction>(
             Actions,
             CompileDeviceOnly ? types::TY_HIP_FATBIN : types::TY_Object);
-        DDeps.add(*TopDeviceLinkAction, *FatBinaryToolChain, nullptr,
+        DDeps.add(*TopDeviceLinkAction, *FatBinaryToolChain, /*BA=*/{},
                   AssociatedOffloadKind);
         // Offload the host object to the host linker.
         AL.push_back(
@@ -4127,7 +4114,7 @@ class OffloadingActionBuilder final {
     // for that.
     OffloadAction::HostDependence HDep(
         *HostAction, *C.getSingleOffloadToolChain<Action::OFK_Host>(),
-        /*BoundArch=*/nullptr, DDeps);
+        /*BA=*/{}, DDeps);
     return C.MakeAction<OffloadAction>(HDep, DDeps);
   }
 
@@ -4155,7 +4142,7 @@ class OffloadingActionBuilder final {
           C.MakeAction<OffloadUnbundlingJobAction>(HostAction);
       UnbundlingHostAction->registerDependentActionInfo(
           C.getSingleOffloadToolChain<Action::OFK_Host>(),
-          /*BoundArch=*/StringRef(), Action::OFK_Host);
+          /*BA=*/{}, Action::OFK_Host);
       HostAction = UnbundlingHostAction;
       recordHostAction(HostAction, InputArg);
     }
@@ -4227,7 +4214,7 @@ class OffloadingActionBuilder final {
     // associated with the current input.
     if (HostAction)
       HostAction->propagateHostOffloadInfo(InputArgToOffloadKindMap[InputArg],
-                                           /*BoundArch=*/nullptr);
+                                           /*BA=*/{});
     return false;
   }
 
@@ -4256,7 +4243,7 @@ class OffloadingActionBuilder final {
       // needs to set its offloading kind directly.
       if (HA)
         HA->propagateHostOffloadInfo(SB->getAssociatedOffloadKind(),
-                                     /*BoundArch=*/nullptr);
+                                     /*BA=*/{});
     }
     return HA;
   }
@@ -4287,7 +4274,7 @@ class OffloadingActionBuilder final {
       // is a link action it is assumed to depend on all actions generated so
       // far.
       HostAction->setHostOffloadInfo(ActiveOffloadKinds,
-                                     /*BoundArch=*/nullptr);
+                                     /*BA=*/{});
       // Propagate active offloading kinds for each input to the link action.
       // Each input may have 
diff erent active offloading kind.
       for (auto *A : HostAction->inputs()) {
@@ -4297,7 +4284,7 @@ class OffloadingActionBuilder final {
         auto OFKLoc = InputArgToOffloadKindMap.find(ArgLoc->second);
         if (OFKLoc == InputArgToOffloadKindMap.end())
           continue;
-        A->propagateHostOffloadInfo(OFKLoc->second, /*BoundArch=*/nullptr);
+        A->propagateHostOffloadInfo(OFKLoc->second, /*BA=*/{});
       }
       return HostAction;
     }
@@ -4307,7 +4294,7 @@ class OffloadingActionBuilder final {
     // to do that explicitly here.
     OffloadAction::HostDependence HDep(
         *HostAction, *C.getSingleOffloadToolChain<Action::OFK_Host>(),
-        /*BoundArch*/ nullptr, ActiveOffloadKinds);
+        /*BA=*/{}, ActiveOffloadKinds);
     return C.MakeAction<OffloadAction>(HDep, DDeps);
   }
 };
@@ -4664,7 +4651,7 @@ void Driver::BuildActions(Compilation &C, DerivedArgList &Args,
       OffloadBuilder->appendTopLevelActions(Actions, Current, InputArg);
     else if (Current)
       Current->propagateHostOffloadInfo(C.getActiveOffloadKinds(),
-                                        /*BoundArch=*/nullptr);
+                                        /*BA=*/{});
   }
 
   // Add a link action if necessary.
@@ -4688,7 +4675,7 @@ void Driver::BuildActions(Compilation &C, DerivedArgList &Args,
                Args.hasArg(options::OPT_offload_link)) {
       LA = C.MakeAction<LinkerWrapperJobAction>(LinkerInputs, types::TY_Image);
       LA->propagateHostOffloadInfo(C.getActiveOffloadKinds(),
-                                   /*BoundArch=*/nullptr);
+                                   /*BA=*/{});
     } else {
       // If we are linking but were passed -emit-llvm, we will be calling
       // llvm-link, so set the output type accordingly. This is only allowed in
@@ -4899,7 +4886,7 @@ getConflictOffloadArchCombination(const llvm::DenseSet<StringRef> &Archs,
   return getConflictTargetIDCombination(ArchSet);
 }
 
-llvm::SmallVector<StringRef>
+llvm::SmallVector<BoundArch>
 Driver::getOffloadArchs(Compilation &C, const llvm::opt::DerivedArgList &Args,
                         Action::OffloadKind Kind, const ToolChain &TC) const {
   // --offload and --offload-arch options are mutually exclusive.
@@ -4914,7 +4901,7 @@ Driver::getOffloadArchs(Compilation &C, const llvm::opt::DerivedArgList &Args,
   }
 
   llvm::DenseSet<StringRef> Archs;
-  for (auto *Arg : C.getArgsForToolChain(&TC, /*BoundArch=*/"", Kind)) {
+  for (auto *Arg : C.getArgsForToolChain(&TC, /*BA=*/{}, Kind)) {
     // Add or remove the seen architectures in order of appearance. If an
     // invalid architecture is given we simply exit.
     if (Arg->getOption().matches(options::OPT_offload_arch_EQ)) {
@@ -4934,7 +4921,7 @@ Driver::getOffloadArchs(Compilation &C, const llvm::opt::DerivedArgList &Args,
             if (!CanonicalStr.empty())
               Archs.insert(CanonicalStr);
             else
-              return llvm::SmallVector<StringRef>();
+              return {};
           }
         } else {
           StringRef CanonicalStr =
@@ -4942,7 +4929,7 @@ Driver::getOffloadArchs(Compilation &C, const llvm::opt::DerivedArgList &Args,
           if (!CanonicalStr.empty())
             Archs.insert(CanonicalStr);
           else
-            return llvm::SmallVector<StringRef>();
+            return {};
         }
       }
     } else if (Arg->getOption().matches(options::OPT_no_offload_arch_EQ)) {
@@ -4977,7 +4964,7 @@ Driver::getOffloadArchs(Compilation &C, const llvm::opt::DerivedArgList &Args,
       Archs.insert(StringRef());
     } else if (Kind == Action::OFK_OpenMP) {
       // Accept legacy `-march` device arguments for OpenMP.
-      if (auto *Arg = C.getArgsForToolChain(&TC, /*BoundArch=*/"", Kind)
+      if (auto *Arg = C.getArgsForToolChain(&TC, /*BA=*/{}, Kind)
                           .getLastArg(options::OPT_march_EQ)) {
         Archs.insert(Arg->getValue());
       } else {
@@ -5000,7 +4987,13 @@ Driver::getOffloadArchs(Compilation &C, const llvm::opt::DerivedArgList &Args,
 
   SmallVector<StringRef> Sorted(Archs.begin(), Archs.end());
   llvm::sort(Sorted);
-  return Sorted;
+
+  // Convert to BoundArch, parsing each architecture string once
+  SmallVector<BoundArch> Result;
+  Result.reserve(Sorted.size());
+  for (StringRef Arch : Sorted)
+    Result.push_back(BoundArch(Arch));
+  return Result;
 }
 
 Action *
@@ -5064,9 +5057,9 @@ Driver::BuildOffloadingActions(Compilation &C, llvm::opt::DerivedArgList &Args,
       continue;
 
     // Get the product of all bound architectures and toolchains.
-    SmallVector<std::pair<const ToolChain *, StringRef>> TCAndArchs;
+    SmallVector<std::pair<const ToolChain *, BoundArch>> TCAndArchs;
     for (const ToolChain *TC : ToolChains) {
-      for (StringRef Arch : getOffloadArchs(C, C.getArgs(), Kind, *TC)) {
+      for (BoundArch Arch : getOffloadArchs(C, C.getArgs(), Kind, *TC)) {
         TCAndArchs.push_back(std::make_pair(TC, Arch));
         DeviceActions.push_back(
             C.MakeAction<InputAction>(*InputArg, InputType, CUID));
@@ -5104,7 +5097,7 @@ Driver::BuildOffloadingActions(Compilation &C, llvm::opt::DerivedArgList &Args,
           continue;
 
         // Propagate the ToolChain so we can use it in ConstructPhaseAction.
-        A->propagateDeviceOffloadInfo(Kind, TCAndArch->second.data(),
+        A->propagateDeviceOffloadInfo(Kind, TCAndArch->second,
                                       TCAndArch->first);
         A = ConstructPhaseAction(C, Args, Phase, A, Kind,
                                  TCAndArch->first->getLTOMode(Args, Kind));
@@ -5118,9 +5111,9 @@ Driver::BuildOffloadingActions(Compilation &C, llvm::opt::DerivedArgList &Args,
           HostAction->setCannotBeCollapsedWithNextDependentAction();
           OffloadAction::HostDependence HDep(
               *HostAction, *C.getSingleOffloadToolChain<Action::OFK_Host>(),
-              TCAndArch->second.data(), Kind);
+              TCAndArch->second, Kind);
           OffloadAction::DeviceDependences DDep;
-          DDep.add(*A, *TCAndArch->first, TCAndArch->second.data(), Kind);
+          DDep.add(*A, *TCAndArch->first, TCAndArch->second, Kind);
           A = C.MakeAction<OffloadAction>(HDep, DDep);
         }
 
@@ -5149,16 +5142,16 @@ Driver::BuildOffloadingActions(Compilation &C, llvm::opt::DerivedArgList &Args,
 
     auto *TCAndArch = TCAndArchs.begin();
     for (Action *A : DeviceActions) {
-      DDeps.add(*A, *TCAndArch->first, TCAndArch->second.data(), Kind);
+      DDeps.add(*A, *TCAndArch->first, TCAndArch->second, Kind);
       OffloadAction::DeviceDependences DDep;
-      DDep.add(*A, *TCAndArch->first, TCAndArch->second.data(), Kind);
+      DDep.add(*A, *TCAndArch->first, TCAndArch->second, Kind);
 
       // Compiling CUDA in non-RDC mode uses the PTX output if available.
       for (Action *Input : A->getInputs())
         if (Kind == Action::OFK_Cuda && A->getType() == types::TY_Object &&
             !Args.hasFlag(options::OPT_fgpu_rdc, options::OPT_fno_gpu_rdc,
                           false))
-          DDep.add(*Input, *TCAndArch->first, TCAndArch->second.data(), Kind);
+          DDep.add(*Input, *TCAndArch->first, TCAndArch->second, Kind);
       OffloadActions.push_back(C.MakeAction<OffloadAction>(DDep, A->getType()));
 
       ++TCAndArch;
@@ -5190,15 +5183,15 @@ Driver::BuildOffloadingActions(Compilation &C, llvm::opt::DerivedArgList &Args,
     Action *FatbinAction =
         C.MakeAction<LinkJobAction>(OffloadActions, types::TY_CUDA_FATBIN);
     DDep.add(*FatbinAction, *C.getSingleOffloadToolChain<Action::OFK_Cuda>(),
-             nullptr, Action::OFK_Cuda);
+             /*BA=*/{}, Action::OFK_Cuda);
   } else if (HIPNoRDC && offloadDeviceOnly()) {
     // If we are in device-only non-RDC-mode we just emit the final HIP
     // fatbinary for each translation unit, linking each input individually.
     Action *FatbinAction =
         C.MakeAction<LinkJobAction>(OffloadActions, types::TY_HIP_FATBIN);
     DDep.add(*FatbinAction,
-             *C.getOffloadToolChains<Action::OFK_HIP>().first->second, nullptr,
-             Action::OFK_HIP);
+             *C.getOffloadToolChains<Action::OFK_HIP>().first->second,
+             /*BA=*/{}, Action::OFK_HIP);
   } else if (HIPNoRDC) {
     // Host + device assembly: defer to clang-offload-bundler (see
     // BuildActions).
@@ -5221,14 +5214,14 @@ Driver::BuildOffloadingActions(Compilation &C, llvm::opt::DerivedArgList &Args,
         C.MakeAction<LinkerWrapperJobAction>(AL, types::TY_HIP_FATBIN);
     DDep.add(*PackagerAction,
              *C.getOffloadToolChains<Action::OFK_HIP>().first->second,
-             /*BoundArch=*/nullptr, Action::OFK_HIP);
+             /*BA=*/{}, Action::OFK_HIP);
   } else {
     // Package all the offloading actions into a single output that can be
     // embedded in the host and linked.
     Action *PackagerAction =
         C.MakeAction<OffloadPackagerJobAction>(OffloadActions, types::TY_Image);
     DDep.add(*PackagerAction, *C.getSingleOffloadToolChain<Action::OFK_Host>(),
-             nullptr, C.getActiveOffloadKinds());
+             /*BA=*/{}, C.getActiveOffloadKinds());
   }
 
   // HIP wants '--offload-device-only' to create a fatbinary by default.
@@ -5242,7 +5235,7 @@ Driver::BuildOffloadingActions(Compilation &C, llvm::opt::DerivedArgList &Args,
   }) && isa<CompileJobAction>(HostAction);
   OffloadAction::HostDependence HDep(
       *HostAction, *C.getSingleOffloadToolChain<Action::OFK_Host>(),
-      /*BoundArch=*/nullptr, SingleDeviceOutput ? DDep : DDeps);
+      /*BA=*/{}, SingleDeviceOutput ? DDep : DDeps);
   return C.MakeAction<OffloadAction>(HDep, SingleDeviceOutput ? DDep : DDeps);
 }
 
@@ -5493,7 +5486,7 @@ void Driver::BuildJobs(Compilation &C) const {
     }
 
     BuildJobsForAction(C, A, &C.getDefaultToolChain(),
-                       /*BoundArch*/ StringRef(),
+                       /*BA=*/{},
                        /*AtTopLevel*/ true,
                        /*MultipleArchs*/ ArchNames.size() > 1,
                        /*LinkingOutput*/ LinkingOutput, CachedResults,
@@ -5942,13 +5935,12 @@ class ToolSelector final {
 /// armv7 and armv7s both map to the same triple -- so we need both in our map.
 /// Also, we need to add the offloading device kind, as the same tool chain can
 /// be used for host and device for some programming models, e.g. OpenMP.
-static std::string GetTriplePlusArchString(const ToolChain *TC,
-                                           StringRef BoundArch,
+static std::string GetTriplePlusArchString(const ToolChain *TC, BoundArch BA,
                                            Action::OffloadKind OffloadKind) {
-  std::string TriplePlusArch = TC->getTriple().str();
-  if (!BoundArch.empty()) {
+  std::string TriplePlusArch = TC->getTriple().normalize();
+  if (!BA.empty()) {
     TriplePlusArch += "-";
-    TriplePlusArch += BoundArch;
+    TriplePlusArch += BA.ArchName;
   }
   TriplePlusArch += "-";
   TriplePlusArch += Action::GetOffloadKindName(OffloadKind);
@@ -5956,20 +5948,20 @@ static std::string GetTriplePlusArchString(const ToolChain *TC,
 }
 
 InputInfoList Driver::BuildJobsForAction(
-    Compilation &C, const Action *A, const ToolChain *TC, StringRef BoundArch,
+    Compilation &C, const Action *A, const ToolChain *TC, BoundArch BA,
     bool AtTopLevel, bool MultipleArchs, const char *LinkingOutput,
     std::map<std::pair<const Action *, std::string>, InputInfoList>
         &CachedResults,
     Action::OffloadKind TargetDeviceOffloadKind) const {
   std::pair<const Action *, std::string> ActionTC = {
-      A, GetTriplePlusArchString(TC, BoundArch, TargetDeviceOffloadKind)};
+      A, GetTriplePlusArchString(TC, BA, TargetDeviceOffloadKind)};
   auto CachedResult = CachedResults.find(ActionTC);
   if (CachedResult != CachedResults.end()) {
     return CachedResult->second;
   }
   InputInfoList Result = BuildJobsForActionNoCache(
-      C, A, TC, BoundArch, AtTopLevel, MultipleArchs, LinkingOutput,
-      CachedResults, TargetDeviceOffloadKind);
+      C, A, TC, BA, AtTopLevel, MultipleArchs, LinkingOutput, CachedResults,
+      TargetDeviceOffloadKind);
   CachedResults[ActionTC] = Result;
   return Result;
 }
@@ -5988,9 +5980,10 @@ static void handleTimeTrace(Compilation &C, const ArgList &Args,
     OffloadingPrefix = Action::GetOffloadingFileNamePrefix(
         JA->getOffloadingDeviceKind(), TC ? TC->getEffectiveTriple().str() : "",
         /*CreatePrefixForHost=*/false);
-    if (const char *Arch = JA->getOffloadingArch()) {
+    BoundArch Arch = JA->getOffloadingArch();
+    if (!Arch.empty()) {
       OffloadingPrefix += "-";
-      OffloadingPrefix += Arch;
+      OffloadingPrefix += Arch.ArchName;
     }
   } else if (JA->getOffloadingHostActiveKinds() != Action::OFK_None &&
              C.getDriver().isSaveTempsEnabled()) {
@@ -6038,7 +6031,7 @@ static void handleTimeTrace(Compilation &C, const ArgList &Args,
 }
 
 InputInfoList Driver::BuildJobsForActionNoCache(
-    Compilation &C, const Action *A, const ToolChain *TC, StringRef BoundArch,
+    Compilation &C, const Action *A, const ToolChain *TC, BoundArch BA,
     bool AtTopLevel, bool MultipleArchs, const char *LinkingOutput,
     std::map<std::pair<const Action *, std::string>, InputInfoList>
         &CachedResults,
@@ -6047,8 +6040,8 @@ InputInfoList Driver::BuildJobsForActionNoCache(
 
   // Track the bound arch for commands constructed in this scope so
   // generateCompilationDiagnostics can identify the crashing arch.
-  StringRef SavedBoundArch = C.getCurrentBoundArch();
-  C.setCurrentBoundArch(BoundArch);
+  BoundArch SavedBoundArch = C.getCurrentBoundArch();
+  C.setCurrentBoundArch(BA);
   auto RestoreBoundArch =
       llvm::scope_exit([&] { C.setCurrentBoundArch(SavedBoundArch); });
 
@@ -6059,7 +6052,7 @@ InputInfoList Driver::BuildJobsForActionNoCache(
     // computed. Get the default arguments for OFK_None to ensure that
     // initialization is performed before processing the offload action.
     // FIXME: Remove when darwin's toolchain is initialized during construction.
-    C.getArgsForToolChain(TC, BoundArch, Action::OFK_Host);
+    C.getArgsForToolChain(TC, BA, Action::OFK_Host);
 
     // The offload action is expected to be used in four 
diff erent situations.
     //
@@ -6089,9 +6082,9 @@ InputInfoList Driver::BuildJobsForActionNoCache(
     if (OA->hasSingleDeviceDependence() || !OA->hasHostDependence()) {
       InputInfoList DevA;
       OA->doOnEachDeviceDependence([&](Action *DepA, const ToolChain *DepTC,
-                                       const char *DepBoundArch) {
+                                       BoundArch DepBoundArch) {
         DevA.append(BuildJobsForAction(C, DepA, DepTC, DepBoundArch, AtTopLevel,
-                                       /*MultipleArchs*/ !!DepBoundArch,
+                                       /*MultipleArchs=*/!DepBoundArch.empty(),
                                        LinkingOutput, CachedResults,
                                        DepA->getOffloadingDeviceKind()));
       });
@@ -6104,11 +6097,11 @@ InputInfoList Driver::BuildJobsForActionNoCache(
     // dependence. The dependences can't therefore be a top-level action.
     OA->doOnEachDependence(
         /*IsHostDependence=*/BuildingForOffloadDevice,
-        [&](Action *DepA, const ToolChain *DepTC, const char *DepBoundArch) {
+        [&](Action *DepA, const ToolChain *DepTC, BoundArch DepBoundArch) {
           OffloadDependencesInputInfo.append(BuildJobsForAction(
               C, DepA, DepTC, DepBoundArch, /*AtTopLevel=*/false,
-              /*MultipleArchs*/ !!DepBoundArch, LinkingOutput, CachedResults,
-              DepA->getOffloadingDeviceKind()));
+              /*MultipleArchs=*/!DepBoundArch.empty(), LinkingOutput,
+              CachedResults, DepA->getOffloadingDeviceKind()));
         });
 
     A = BuildingForOffloadDevice
@@ -6119,7 +6112,7 @@ InputInfoList Driver::BuildJobsForActionNoCache(
     // toolchain, return the cached input if so.
     std::pair<const Action *, std::string> ActionTC = {
         OA->getHostDependence(),
-        GetTriplePlusArchString(TC, BoundArch, TargetDeviceOffloadKind)};
+        GetTriplePlusArchString(TC, BA, TargetDeviceOffloadKind)};
     auto It = CachedResults.find(ActionTC);
     if (It != CachedResults.end()) {
       InputInfoList Inputs = It->second;
@@ -6142,12 +6135,12 @@ InputInfoList Driver::BuildJobsForActionNoCache(
 
   if (const BindArchAction *BAA = dyn_cast<BindArchAction>(A)) {
     const ToolChain *TC;
-    StringRef ArchName = BAA->getArchName();
+    BoundArch ArchName = BAA->getArch();
 
     if (!ArchName.empty())
       TC = &getToolChain(C.getArgs(),
-                         computeTargetTriple(*this, TargetTriple,
-                                             C.getArgs(), ArchName));
+                         computeTargetTriple(*this, TargetTriple, C.getArgs(),
+                                             ArchName.ArchName));
     else
       TC = &C.getDefaultToolChain();
 
@@ -6174,11 +6167,11 @@ InputInfoList Driver::BuildJobsForActionNoCache(
   for (const auto *OA : CollapsedOffloadActions)
     cast<OffloadAction>(OA)->doOnEachDependence(
         /*IsHostDependence=*/BuildingForOffloadDevice,
-        [&](Action *DepA, const ToolChain *DepTC, const char *DepBoundArch) {
+        [&](Action *DepA, const ToolChain *DepTC, BoundArch DepBoundArch) {
           OffloadDependencesInputInfo.append(BuildJobsForAction(
-              C, DepA, DepTC, DepBoundArch, /* AtTopLevel */ false,
-              /*MultipleArchs=*/!!DepBoundArch, LinkingOutput, CachedResults,
-              DepA->getOffloadingDeviceKind()));
+              C, DepA, DepTC, DepBoundArch, /*AtTopLevel=*/false,
+              /*MultipleArchs=*/!DepBoundArch.empty(), LinkingOutput,
+              CachedResults, DepA->getOffloadingDeviceKind()));
         });
 
   // Only use pipes when there is exactly one input.
@@ -6190,7 +6183,7 @@ InputInfoList Driver::BuildJobsForActionNoCache(
     bool SubJobAtTopLevel =
         AtTopLevel && (isa<DsymutilJobAction>(A) || isa<VerifyJobAction>(A));
     InputInfos.append(BuildJobsForAction(
-        C, Input, TC, BoundArch, SubJobAtTopLevel, MultipleArchs, LinkingOutput,
+        C, Input, TC, BA, SubJobAtTopLevel, MultipleArchs, LinkingOutput,
         CachedResults, A->getOffloadingDeviceKind()));
   }
 
@@ -6217,14 +6210,14 @@ InputInfoList Driver::BuildJobsForActionNoCache(
   llvm::Triple EffectiveTriple;
   const ToolChain &ToolTC = T->getToolChain();
   const ArgList &Args =
-      C.getArgsForToolChain(TC, BoundArch, A->getOffloadingDeviceKind());
+      C.getArgsForToolChain(TC, BA, A->getOffloadingDeviceKind());
   if (InputInfos.size() != 1) {
     EffectiveTriple =
-        llvm::Triple(ToolTC.ComputeEffectiveClangTriple(Args, BoundArch));
+        llvm::Triple(ToolTC.ComputeEffectiveClangTriple(Args, BA));
   } else {
     // Pass along the input type if it can be unambiguously determined.
-    EffectiveTriple = llvm::Triple(ToolTC.ComputeEffectiveClangTriple(
-        Args, BoundArch, InputInfos[0].getType()));
+    EffectiveTriple = llvm::Triple(
+        ToolTC.ComputeEffectiveClangTriple(Args, BA, InputInfos[0].getType()));
   }
   RegisterEffectiveTriple TripleRAII(ToolTC, EffectiveTriple);
 
@@ -6259,14 +6252,14 @@ InputInfoList Driver::BuildJobsForActionNoCache(
 
       // Get the unique string identifier for this dependence and cache the
       // result.
-      StringRef Arch;
+      BoundArch Arch;
       if (TargetDeviceOffloadKind == Action::OFK_HIP) {
         if (UI.DependentOffloadKind == Action::OFK_Host)
-          Arch = StringRef();
+          Arch = BoundArch();
         else
-          Arch = UI.DependentBoundArch;
+          Arch = BoundArch(UI.DependentBoundArch);
       } else
-        Arch = BoundArch;
+        Arch = BA;
 
       CachedResults[{A, GetTriplePlusArchString(UI.DependentToolChain, Arch,
                                                 UI.DependentOffloadKind)}] = {
@@ -6276,7 +6269,7 @@ InputInfoList Driver::BuildJobsForActionNoCache(
     // Now that we have all the results generated, select the one that should be
     // returned for the current depending action.
     std::pair<const Action *, std::string> ActionTC = {
-        A, GetTriplePlusArchString(TC, BoundArch, TargetDeviceOffloadKind)};
+        A, GetTriplePlusArchString(TC, BA, TargetDeviceOffloadKind)};
     assert(CachedResults.find(ActionTC) != CachedResults.end() &&
            "Result does not exist??");
     Result = CachedResults[ActionTC].front();
@@ -6290,9 +6283,9 @@ InputInfoList Driver::BuildJobsForActionNoCache(
         /*CreatePrefixForHost=*/isa<OffloadPackagerJobAction>(A) ||
             !(A->getOffloadingHostActiveKinds() == Action::OFK_None ||
               AtTopLevel));
-    Result = InputInfo(A, GetNamedOutputPath(C, *JA, BaseInput, BoundArch,
-                                             AtTopLevel, MultipleArchs,
-                                             OffloadingPrefix),
+    Result = InputInfo(A,
+                       GetNamedOutputPath(C, *JA, BaseInput, BA, AtTopLevel,
+                                          MultipleArchs, OffloadingPrefix),
                        BaseInput);
     if (T->canEmitIR())
       handleTimeTrace(C, Args, JA, BaseInput, Result);
@@ -6378,7 +6371,7 @@ static bool HasPreprocessOutput(const Action &JA) {
 
 const char *Driver::CreateTempFile(Compilation &C, StringRef Prefix,
                                    StringRef Suffix, bool MultipleArchs,
-                                   StringRef BoundArch,
+                                   StringRef BoundArchStr,
                                    bool NeedUniqueDirectory) const {
   SmallString<128> TmpName;
   Arg *A = C.getArgs().getLastArg(options::OPT_fcrash_diagnostics_dir);
@@ -6398,14 +6391,14 @@ const char *Driver::CreateTempFile(Compilation &C, StringRef Prefix,
       return "";
     }
   } else {
-    if (MultipleArchs && !BoundArch.empty()) {
+    if (MultipleArchs && !BoundArchStr.empty()) {
       if (NeedUniqueDirectory) {
         TmpName = GetTemporaryDirectory(Prefix);
-        llvm::sys::path::append(TmpName,
-                                Twine(Prefix) + "-" + BoundArch + "." + Suffix);
+        llvm::sys::path::append(TmpName, Twine(Prefix) + "-" + BoundArchStr +
+                                             "." + Suffix);
       } else {
-        TmpName =
-            GetTemporaryPath((Twine(Prefix) + "-" + BoundArch).str(), Suffix);
+        TmpName = GetTemporaryPath((Twine(Prefix) + "-" + BoundArchStr).str(),
+                                   Suffix);
       }
 
     } else {
@@ -6439,11 +6432,10 @@ static const char *GetModuleOutputPath(Compilation &C, const JobAction &JA,
 }
 
 const char *Driver::GetNamedOutputPath(Compilation &C, const JobAction &JA,
-                                       const char *BaseInput,
-                                       StringRef OrigBoundArch, bool AtTopLevel,
-                                       bool MultipleArchs,
+                                       const char *BaseInput, BoundArch BA,
+                                       bool AtTopLevel, bool MultipleArchs,
                                        StringRef OffloadingPrefix) const {
-  std::string BoundArch = sanitizeTargetIDInFileName(OrigBoundArch);
+  std::string BoundArchStr = sanitizeTargetIDInFileName(BA.ArchName);
 
   llvm::PrettyStackTraceString CrashInfo("Computing output path");
 
@@ -6458,7 +6450,7 @@ const char *Driver::GetNamedOutputPath(Compilation &C, const JobAction &JA,
         (JA.getOffloadingDeviceKind() == Action::OFK_None ||
          JA.getOffloadingDeviceKind() == Action::OFK_Host) &&
         Triple.isOSDarwin();
-    return CreateTempFile(C, Prefix, Suffix, MultipleArchs, BoundArch,
+    return CreateTempFile(C, Prefix, Suffix, MultipleArchs, BoundArchStr,
                           NeedUniqueDirectory);
   };
 
@@ -6633,9 +6625,9 @@ const char *Driver::GetNamedOutputPath(Compilation &C, const JobAction &JA,
         llvm::sys::path::replace_extension(Output, "");
       }
       Output += OffloadingPrefix;
-      if (MultipleArchs && !BoundArch.empty()) {
+      if (MultipleArchs && !BoundArchStr.empty()) {
         Output += "-";
-        Output.append(BoundArch);
+        Output.append(BoundArchStr);
       }
       if (UseOutExtension)
         Output += ".out";
@@ -6661,9 +6653,9 @@ const char *Driver::GetNamedOutputPath(Compilation &C, const JobAction &JA,
       End = BaseName.rfind('.');
     SmallString<128> Suffixed(BaseName.substr(0, End));
     Suffixed += OffloadingPrefix;
-    if (MultipleArchs && !BoundArch.empty()) {
+    if (MultipleArchs && !BoundArchStr.empty()) {
       Suffixed += "-";
-      Suffixed.append(BoundArch);
+      Suffixed.append(BoundArchStr);
     }
     // When using both -save-temps and -emit-llvm, use a ".tmp.bc" suffix for
     // the unoptimized bitcode so that it does not get overwritten by the ".bc"

diff  --git a/clang/lib/Driver/SanitizerArgs.cpp b/clang/lib/Driver/SanitizerArgs.cpp
index 74ebd0bf375d3..bf77e748ebd0c 100644
--- a/clang/lib/Driver/SanitizerArgs.cpp
+++ b/clang/lib/Driver/SanitizerArgs.cpp
@@ -399,7 +399,7 @@ bool SanitizerArgs::needsLTO() const {
 SanitizerArgs::SanitizerArgs(const ToolChain &TC,
                              const llvm::opt::ArgList &Args,
                              bool DiagnoseErrors, bool DiagnoseBoundArchErrors,
-                             StringRef BoundArch,
+                             BoundArch BA,
                              Action::OffloadKind DeviceOffloadKind) {
   SanitizerMask AllRemove;      // During the loop below, the accumulated set of
                                 // sanitizers disabled by the current sanitizer
@@ -416,14 +416,13 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
   SanitizerMask Kinds;
 
   // Figure out the base toolchain's sanitizer support so we can diagnose the
-  // 
diff  for a specific BoundArch.
+  // 
diff  for a specific BA.
   const SanitizerMask ToolChainSupported =
-      setGroupBits(TC.getSupportedSanitizers("", DeviceOffloadKind));
+      setGroupBits(TC.getSupportedSanitizers({}, DeviceOffloadKind));
 
   const SanitizerMask BoundArchSupported =
-      BoundArch.empty() ? ToolChainSupported
-                        : setGroupBits(TC.getSupportedSanitizers(
-                              BoundArch, DeviceOffloadKind));
+      BA ? setGroupBits(TC.getSupportedSanitizers(BA, DeviceOffloadKind))
+         : ToolChainSupported;
 
   CfiCrossDso = Args.hasFlag(options::OPT_fsanitize_cfi_cross_dso,
                              options::OPT_fno_sanitize_cfi_cross_dso, false);
@@ -567,7 +566,7 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
         // Check if the toolchain provides a feature requirement hint for
         // any of the unsupported sanitizers
         StringRef Requirement =
-            TC.getSanitizerRequirement(ArchSpecificUnsupported, BoundArch);
+            TC.getSanitizerRequirement(ArchSpecificUnsupported, BA);
         if (!Requirement.empty()) {
           // Emit diagnostic with feature requirement
           //
@@ -579,7 +578,7 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
                         err_drv_unsupported_option_for_offload_arch_req_feature
                   : diag::
                         warn_drv_unsupported_option_for_offload_arch_req_feature)
-              << Arg->getAsString(Args) << BoundArch << Requirement;
+              << Arg->getAsString(Args) << BA.ArchName << Requirement;
         } else {
           // Fall back to generic diagnostic if no requirement was provided
           SanitizerSet UnsupportedSet;

diff  --git a/clang/lib/Driver/ToolChain.cpp b/clang/lib/Driver/ToolChain.cpp
index 8db726cedfe90..7d93e7f65daf5 100644
--- a/clang/lib/Driver/ToolChain.cpp
+++ b/clang/lib/Driver/ToolChain.cpp
@@ -517,15 +517,14 @@ ToolChain::getMultilibFlags(const llvm::opt::ArgList &Args) const {
 }
 
 SanitizerArgs
-ToolChain::getSanitizerArgs(const llvm::opt::ArgList &JobArgs,
-                            StringRef BoundArch,
+ToolChain::getSanitizerArgs(const llvm::opt::ArgList &JobArgs, BoundArch BA,
                             Action::OffloadKind DeviceOffloadKind) const {
   // When -fno-gpu-sanitize is specified for GPU targets, don't emit
   // diagnostics about unsupported sanitizers for specific GPU arches,
   // since sanitizers are disabled for the GPU anyway.
   bool DiagnoseBoundArchErrors =
-      BoundArchSanitizerArgsChecked.insert(BoundArch).second;
-  if (!BoundArch.empty() && getTriple().isGPU() &&
+      BoundArchSanitizerArgsChecked.insert(BA.ArchName).second;
+  if (BA && getTriple().isGPU() &&
       !JobArgs.hasFlag(options::OPT_fgpu_sanitize,
                        options::OPT_fno_gpu_sanitize, true)) {
     DiagnoseBoundArchErrors = false;
@@ -533,7 +532,7 @@ ToolChain::getSanitizerArgs(const llvm::opt::ArgList &JobArgs,
 
   SanitizerArgs SanArgs(*this, JobArgs,
                         /*DiagnoseErrors=*/!SanitizerArgsChecked,
-                        DiagnoseBoundArchErrors, BoundArch, DeviceOffloadKind);
+                        DiagnoseBoundArchErrors, BA, DeviceOffloadKind);
 
   SanitizerArgsChecked = true;
   return SanArgs;
@@ -1431,8 +1430,7 @@ bool ToolChain::isThreadModelSupported(const StringRef Model) const {
   return false;
 }
 
-std::string ToolChain::ComputeLLVMTriple(const ArgList &Args,
-                                         StringRef BoundArch,
+std::string ToolChain::ComputeLLVMTriple(const ArgList &Args, BoundArch BA,
                                          types::ID InputType) const {
   switch (getTriple().getArch()) {
   default:
@@ -1486,9 +1484,9 @@ std::string ToolChain::ComputeLLVMTriple(const ArgList &Args,
 }
 
 std::string ToolChain::ComputeEffectiveClangTriple(const ArgList &Args,
-                                                   StringRef BoundArch,
+                                                   BoundArch BA,
                                                    types::ID InputType) const {
-  return ComputeLLVMTriple(Args, BoundArch, InputType);
+  return ComputeLLVMTriple(Args, BA, InputType);
 }
 
 std::string ToolChain::computeSysRoot() const {
@@ -1501,7 +1499,7 @@ void ToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
 }
 
 void ToolChain::addClangTargetOptions(
-    const ArgList &DriverArgs, ArgStringList &CC1Args, StringRef BoundArch,
+    const ArgList &DriverArgs, ArgStringList &CC1Args, BoundArch BA,
     Action::OffloadKind DeviceOffloadKind) const {}
 
 void ToolChain::addClangCC1ASTargetOptions(const ArgList &Args,
@@ -1840,7 +1838,7 @@ ToolChain::getSystemGPUArchs(const llvm::opt::ArgList &Args) const {
 }
 
 SanitizerMask
-ToolChain::getSupportedSanitizers(StringRef BoundArch,
+ToolChain::getSupportedSanitizers(BoundArch BA,
                                   Action::OffloadKind DeviceOffloadKind) const {
   // Return sanitizers which don't require runtime support and are not
   // platform dependent.
@@ -1881,7 +1879,7 @@ void ToolChain::addSYCLIncludeArgs(const ArgList &DriverArgs,
                                    ArgStringList &CC1Args) const {}
 
 llvm::SmallVector<ToolChain::BitCodeLibraryInfo, 12>
-ToolChain::getDeviceLibs(const ArgList &DriverArgs, StringRef BoundArch,
+ToolChain::getDeviceLibs(const ArgList &DriverArgs, BoundArch BA,
                          const Action::OffloadKind DeviceOffloadingKind) const {
   return {};
 }
@@ -2101,7 +2099,7 @@ static bool isXArchCompatibleTripleArch(const llvm::Triple &TT,
 }
 
 llvm::opt::DerivedArgList *ToolChain::TranslateXarchArgs(
-    const llvm::opt::DerivedArgList &Args, StringRef BoundArch,
+    const llvm::opt::DerivedArgList &Args, BoundArch BA,
     Action::OffloadKind OFK,
     SmallVectorImpl<llvm::opt::Arg *> *AllocatedArgs) const {
   DerivedArgList *DAL = new DerivedArgList(Args.getBaseArgs());
@@ -2119,8 +2117,7 @@ llvm::opt::DerivedArgList *ToolChain::TranslateXarchArgs(
       Skip = IsDevice;
     } else if (A->getOption().matches(options::OPT_Xarch__)) {
       StringRef Val = A->getValue();
-      NeedTrans = Val == getArchName() ||
-                  (!BoundArch.empty() && Val == BoundArch) ||
+      NeedTrans = Val == getArchName() || (BA && Val == BA.ArchName) ||
                   isXArchCompatibleTripleArch(Triple, Val);
       Skip = !NeedTrans;
     }

diff  --git a/clang/lib/Driver/ToolChains/AIX.cpp b/clang/lib/Driver/ToolChains/AIX.cpp
index a6a890db305b9..586bc08067eff 100644
--- a/clang/lib/Driver/ToolChains/AIX.cpp
+++ b/clang/lib/Driver/ToolChains/AIX.cpp
@@ -556,7 +556,7 @@ static void addTocDataOptions(const llvm::opt::ArgList &Args,
 
 void AIX::addClangTargetOptions(
     const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CC1Args,
-    StringRef BoundArch, Action::OffloadKind DeviceOffloadingKind) const {
+    BoundArch BA, Action::OffloadKind DeviceOffloadingKind) const {
   Args.AddLastArg(CC1Args, options::OPT_mignore_xcoff_visibility);
   Args.AddLastArg(CC1Args, options::OPT_mdefault_visibility_export_mapping_EQ);
   Args.addOptInFlag(CC1Args, options::OPT_mxcoff_roptr, options::OPT_mno_xcoff_roptr);

diff  --git a/clang/lib/Driver/ToolChains/AIX.h b/clang/lib/Driver/ToolChains/AIX.h
index afe0556d68ed4..6ae726ef23e7e 100644
--- a/clang/lib/Driver/ToolChains/AIX.h
+++ b/clang/lib/Driver/ToolChains/AIX.h
@@ -85,8 +85,7 @@ class LLVM_LIBRARY_VISIBILITY AIX : public ToolChain {
 
   void addClangTargetOptions(
       const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CC1Args,
-      llvm::StringRef BoundArch,
-      Action::OffloadKind DeviceOffloadingKind) const override;
+      BoundArch BA, Action::OffloadKind DeviceOffloadingKind) const override;
 
   void addProfileRTLibs(const llvm::opt::ArgList &Args,
                         llvm::opt::ArgStringList &CmdArgs) const override;

diff  --git a/clang/lib/Driver/ToolChains/AMDGPU.cpp b/clang/lib/Driver/ToolChains/AMDGPU.cpp
index dfafe48c1900f..325dba03c4136 100644
--- a/clang/lib/Driver/ToolChains/AMDGPU.cpp
+++ b/clang/lib/Driver/ToolChains/AMDGPU.cpp
@@ -690,10 +690,9 @@ Tool *AMDGPUToolChain::buildLinker() const {
 }
 
 DerivedArgList *
-AMDGPUToolChain::TranslateArgs(const DerivedArgList &Args, StringRef BoundArch,
+AMDGPUToolChain::TranslateArgs(const DerivedArgList &Args, BoundArch BA,
                                Action::OffloadKind DeviceOffloadKind) const {
-  DerivedArgList *DAL =
-      Generic_ELF::TranslateArgs(Args, BoundArch, DeviceOffloadKind);
+  DerivedArgList *DAL = Generic_ELF::TranslateArgs(Args, BA, DeviceOffloadKind);
   if (!DAL) {
     DAL = new DerivedArgList(Args.getBaseArgs());
     for (Arg *A : Args)
@@ -730,9 +729,10 @@ AMDGPUToolChain::TranslateArgs(const DerivedArgList &Args, StringRef BoundArch,
     }
   }
 
-  if (!BoundArch.empty()) {
+  if (!BA.empty()) {
     DAL->eraseArg(options::OPT_mcpu_EQ);
-    DAL->AddJoinedArg(nullptr, Opts.getOption(options::OPT_mcpu_EQ), BoundArch);
+    DAL->AddJoinedArg(nullptr, Opts.getOption(options::OPT_mcpu_EQ),
+                      BA.ArchName);
   }
 
   AMDGPUToolChain::ParsedTargetIDType PTID = checkTargetID(*DAL);
@@ -798,7 +798,9 @@ llvm::DenormalMode AMDGPUToolChain::getDefaultDenormalModeForType(
 
   if (JA.getOffloadingDeviceKind() == Action::OFK_HIP ||
       JA.getOffloadingDeviceKind() == Action::OFK_Cuda) {
-    auto Arch = getProcessorFromTargetID(getTriple(), JA.getOffloadingArch());
+    BoundArch BA = JA.getOffloadingArch();
+    // FIXME: Missing conversion from OffloadArch to GPUKind
+    auto Arch = getProcessorFromTargetID(getTriple(), BA.ArchName);
     auto Kind = llvm::AMDGPU::parseArchAMDGCN(Arch);
     if (FPType && FPType == &llvm::APFloat::IEEEsingle() &&
         DriverArgs.hasFlag(options::OPT_fgpu_flush_denormals_to_zero,
@@ -842,10 +844,10 @@ ROCMToolChain::ROCMToolChain(const Driver &D, const llvm::Triple &Triple,
 }
 
 DerivedArgList *
-ROCMToolChain::TranslateArgs(const DerivedArgList &Args, StringRef BoundArch,
+ROCMToolChain::TranslateArgs(const DerivedArgList &Args, BoundArch BA,
                              Action::OffloadKind DeviceOffloadKind) const {
   DerivedArgList *DAL =
-      AMDGPUToolChain::TranslateArgs(Args, BoundArch, DeviceOffloadKind);
+      AMDGPUToolChain::TranslateArgs(Args, BA, DeviceOffloadKind);
 
   // Filter out sanitizer coverage options that are not supported for AMDGPU.
   for (Arg *A : Args) {
@@ -866,7 +868,7 @@ ROCMToolChain::TranslateArgs(const DerivedArgList &Args, StringRef BoundArch,
 
 void AMDGPUToolChain::addClangTargetOptions(
     const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args,
-    llvm::StringRef BoundArch, Action::OffloadKind DeviceOffloadingKind) const {
+    BoundArch BA, Action::OffloadKind DeviceOffloadingKind) const {
   // Default to "hidden" visibility, as object level linking will not be
   // supported for the foreseeable future.
   // TODO: remove the SPIR-V bypass once it can encode (hidden) visibility.
@@ -980,8 +982,8 @@ AMDGPUToolChain::getSystemGPUArchs(const ArgList &Args) const {
 
 void ROCMToolChain::addClangTargetOptions(
     const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args,
-    llvm::StringRef BoundArch, Action::OffloadKind DeviceOffloadingKind) const {
-  AMDGPUToolChain::addClangTargetOptions(DriverArgs, CC1Args, BoundArch,
+    BoundArch BA, Action::OffloadKind DeviceOffloadingKind) const {
+  AMDGPUToolChain::addClangTargetOptions(DriverArgs, CC1Args, BA,
                                          DeviceOffloadingKind);
 
   // For the OpenCL case where there is no offload target, accept -nostdlib to
@@ -1008,9 +1010,8 @@ void ROCMToolChain::addClangTargetOptions(
   // Get the device name and canonicalize it. For offload compilation,
   // BoundArch contains the full target ID. For non-offload (OpenCL),
   // fall back to -mcpu.
-  StringRef TargetID = BoundArch.empty()
-                           ? DriverArgs.getLastArgValue(options::OPT_mcpu_EQ)
-                           : BoundArch;
+  StringRef TargetID =
+      BA ? BA.ArchName : DriverArgs.getLastArgValue(options::OPT_mcpu_EQ);
   StringRef GpuArch = getProcessorFromTargetID(getTriple(), TargetID);
 
   StringRef LibDeviceFile = RocmInstallation->getLibDeviceFile(GpuArch);
@@ -1027,7 +1028,7 @@ void ROCMToolChain::addClangTargetOptions(
   // Add the generic set of libraries.
   BCLibs.append(RocmInstallation->getCommonBitcodeLibs(
       DriverArgs, LibDeviceFile, GpuArch, DeviceOffloadingKind,
-      getSanitizerArgs(DriverArgs, TargetID, DeviceOffloadingKind)
+      getSanitizerArgs(DriverArgs, BoundArch{TargetID}, DeviceOffloadingKind)
           .needsAsanRt()));
 
   for (auto [BCFile, Internalize] : BCLibs) {
@@ -1118,7 +1119,7 @@ ROCMToolChain::getCommonDeviceLibNames(
 
   return RocmInstallation->getCommonBitcodeLibs(
       DriverArgs, LibDeviceFile, GPUArch, DeviceOffloadingKind,
-      getSanitizerArgs(DriverArgs, TargetID, DeviceOffloadingKind)
+      getSanitizerArgs(DriverArgs, BoundArch(TargetID), DeviceOffloadingKind)
           .needsAsanRt());
 }
 
@@ -1146,23 +1147,23 @@ static bool isXnackAvailable(const llvm::Triple &TT, llvm::StringRef TargetID) {
 }
 
 SanitizerMask AMDGPUToolChain::getSupportedSanitizers(
-    StringRef BoundArch, Action::OffloadKind DeviceOffloadKind) const {
+    BoundArch BA, Action::OffloadKind DeviceOffloadKind) const {
   SanitizerMask SupportedMask =
-      ToolChain::getSupportedSanitizers(BoundArch, DeviceOffloadKind);
+      ToolChain::getSupportedSanitizers(BA, DeviceOffloadKind);
 
   // Address sanitizer is potentially supported, but depends on the exact target
   // arch xnack support.
-  if (BoundArch.empty() || isXnackAvailable(getTriple(), BoundArch))
+  if (!BA || isXnackAvailable(getTriple(), BA.ArchName))
     SupportedMask |= SanitizerKind::Address;
 
   return SupportedMask;
 }
 
 StringRef AMDGPUToolChain::getSanitizerRequirement(SanitizerMask Kinds,
-                                                   StringRef BoundArch) const {
+                                                   BoundArch BA) const {
   // Address sanitizer requires xnack+ feature
-  if ((Kinds & SanitizerKind::Address) && !BoundArch.empty() &&
-      !isXnackAvailable(getTriple(), BoundArch)) {
+  if ((Kinds & SanitizerKind::Address) && BA &&
+      !isXnackAvailable(getTriple(), BA.ArchName)) {
     return "xnack+";
   }
   return "";

diff  --git a/clang/lib/Driver/ToolChains/AMDGPU.h b/clang/lib/Driver/ToolChains/AMDGPU.h
index 94f2fbae25388..4aa9402458b38 100644
--- a/clang/lib/Driver/ToolChains/AMDGPU.h
+++ b/clang/lib/Driver/ToolChains/AMDGPU.h
@@ -73,13 +73,12 @@ class LLVM_LIBRARY_VISIBILITY AMDGPUToolChain : public Generic_ELF {
   bool SupportsProfiling() const override { return false; }
 
   llvm::opt::DerivedArgList *
-  TranslateArgs(const llvm::opt::DerivedArgList &Args, StringRef BoundArch,
+  TranslateArgs(const llvm::opt::DerivedArgList &Args, BoundArch BA,
                 Action::OffloadKind DeviceOffloadKind) const override;
 
   void
   addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
-                        llvm::opt::ArgStringList &CC1Args,
-                        llvm::StringRef BoundArch,
+                        llvm::opt::ArgStringList &CC1Args, BoundArch BA,
                         Action::OffloadKind DeviceOffloadKind) const override;
   void
   AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
@@ -102,7 +101,7 @@ class LLVM_LIBRARY_VISIBILITY AMDGPUToolChain : public Generic_ELF {
   const char *getDefaultLinker() const override { return "ld.lld"; }
 
   StringRef getSanitizerRequirement(SanitizerMask Kinds,
-                                    StringRef BoundArch) const override;
+                                    BoundArch BA) const override;
 
   /// Uses amdgpu-arch tool to get arch of the system GPU. Will return error
   /// if unable to find one.
@@ -135,7 +134,7 @@ class LLVM_LIBRARY_VISIBILITY AMDGPUToolChain : public Generic_ELF {
   void addClangWarningOptions(llvm::opt::ArgStringList &CC1Args) const override;
 
   SanitizerMask
-  getSupportedSanitizers(StringRef BoundArch,
+  getSupportedSanitizers(BoundArch BA,
                          Action::OffloadKind DeviceOffloadKind) const override;
 };
 
@@ -145,13 +144,12 @@ class LLVM_LIBRARY_VISIBILITY ROCMToolChain : public AMDGPUToolChain {
                 const llvm::opt::ArgList &Args);
 
   llvm::opt::DerivedArgList *
-  TranslateArgs(const llvm::opt::DerivedArgList &Args, StringRef BoundArch,
+  TranslateArgs(const llvm::opt::DerivedArgList &Args, BoundArch BA,
                 Action::OffloadKind DeviceOffloadKind) const override;
 
   void
   addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
-                        llvm::opt::ArgStringList &CC1Args,
-                        llvm::StringRef BoundArch,
+                        llvm::opt::ArgStringList &CC1Args, BoundArch BA,
                         Action::OffloadKind DeviceOffloadKind) const override;
 
   // Returns a list of device library names shared by 
diff erent languages

diff  --git a/clang/lib/Driver/ToolChains/AMDGPUOpenMP.cpp b/clang/lib/Driver/ToolChains/AMDGPUOpenMP.cpp
index 9a90e491bb27d..c9e724bced9f0 100644
--- a/clang/lib/Driver/ToolChains/AMDGPUOpenMP.cpp
+++ b/clang/lib/Driver/ToolChains/AMDGPUOpenMP.cpp
@@ -32,7 +32,7 @@ AMDGPUOpenMPToolChain::AMDGPUOpenMPToolChain(const Driver &D,
 
 void AMDGPUOpenMPToolChain::addClangTargetOptions(
     const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args,
-    llvm::StringRef BoundArch, Action::OffloadKind DeviceOffloadingKind) const {
+    BoundArch BA, Action::OffloadKind DeviceOffloadingKind) const {
   assert(DeviceOffloadingKind == Action::OFK_OpenMP &&
          "Only OpenMP offloading kinds are supported.");
 
@@ -40,8 +40,7 @@ void AMDGPUOpenMPToolChain::addClangTargetOptions(
                           true))
     return;
 
-  for (auto BCFile :
-       getDeviceLibs(DriverArgs, BoundArch, DeviceOffloadingKind)) {
+  for (auto BCFile : getDeviceLibs(DriverArgs, BA, DeviceOffloadingKind)) {
     CC1Args.push_back(BCFile.ShouldInternalize ? "-mlink-builtin-bitcode"
                                                : "-mlink-bitcode-file");
     CC1Args.push_back(DriverArgs.MakeArgString(BCFile.Path));
@@ -80,15 +79,15 @@ AMDGPUOpenMPToolChain::computeMSVCVersion(const Driver *D,
 
 llvm::SmallVector<ToolChain::BitCodeLibraryInfo, 12>
 AMDGPUOpenMPToolChain::getDeviceLibs(
-    const llvm::opt::ArgList &Args, llvm::StringRef BoundArch,
+    const llvm::opt::ArgList &Args, BoundArch BA,
     const Action::OffloadKind DeviceOffloadingKind) const {
   if (!Args.hasFlag(options::OPT_offloadlib, options::OPT_no_offloadlib, true))
     return {};
 
-  StringRef GpuArch = getProcessorFromTargetID(getTriple(), BoundArch);
+  StringRef GpuArch = getProcessorFromTargetID(getTriple(), BA.ArchName);
   SmallVector<BitCodeLibraryInfo, 12> BCLibs;
-  for (auto BCLib :
-       getCommonDeviceLibNames(Args, BoundArch, GpuArch, DeviceOffloadingKind))
+  for (auto BCLib : getCommonDeviceLibNames(Args, BA.ArchName, GpuArch,
+                                            DeviceOffloadingKind))
     BCLibs.emplace_back(BCLib);
 
   return BCLibs;

diff  --git a/clang/lib/Driver/ToolChains/AMDGPUOpenMP.h b/clang/lib/Driver/ToolChains/AMDGPUOpenMP.h
index bc8b195383c6f..2d5b9e751895f 100644
--- a/clang/lib/Driver/ToolChains/AMDGPUOpenMP.h
+++ b/clang/lib/Driver/ToolChains/AMDGPUOpenMP.h
@@ -35,8 +35,7 @@ class LLVM_LIBRARY_VISIBILITY AMDGPUOpenMPToolChain final
 
   void
   addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
-                        llvm::opt::ArgStringList &CC1Args,
-                        llvm::StringRef BoundArch,
+                        llvm::opt::ArgStringList &CC1Args, BoundArch BA,
                         Action::OffloadKind DeviceOffloadKind) const override;
   CXXStdlibType GetCXXStdlibType(const llvm::opt::ArgList &Args) const override;
   void AddClangCXXStdlibIncludeArgs(
@@ -53,7 +52,7 @@ class LLVM_LIBRARY_VISIBILITY AMDGPUOpenMPToolChain final
                      const llvm::opt::ArgList &Args) const override;
 
   llvm::SmallVector<BitCodeLibraryInfo, 12>
-  getDeviceLibs(const llvm::opt::ArgList &Args, llvm::StringRef BoundArch,
+  getDeviceLibs(const llvm::opt::ArgList &Args, BoundArch BA,
                 const Action::OffloadKind DeviceOffloadKind) const override;
 
   /// OpenMP uses LTO by default to link device bitcode.

diff  --git a/clang/lib/Driver/ToolChains/AVR.cpp b/clang/lib/Driver/ToolChains/AVR.cpp
index c2b5288627b3a..99f75f67be3f5 100644
--- a/clang/lib/Driver/ToolChains/AVR.cpp
+++ b/clang/lib/Driver/ToolChains/AVR.cpp
@@ -466,7 +466,7 @@ void AVRToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
 
 void AVRToolChain::addClangTargetOptions(
     const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args,
-    llvm::StringRef BoundArch, Action::OffloadKind DeviceOffloadKind) const {
+    BoundArch BA, Action::OffloadKind DeviceOffloadKind) const {
   // Reject C/C++ compilation for avr1 devices since they have no SRAM.
   const Driver &D = getDriver();
   std::string CPU = getCPUName(D, DriverArgs, getTriple());

diff  --git a/clang/lib/Driver/ToolChains/AVR.h b/clang/lib/Driver/ToolChains/AVR.h
index e232fb3c0281c..44c1fb21a5d9c 100644
--- a/clang/lib/Driver/ToolChains/AVR.h
+++ b/clang/lib/Driver/ToolChains/AVR.h
@@ -28,8 +28,7 @@ class LLVM_LIBRARY_VISIBILITY AVRToolChain : public Generic_ELF {
 
   void
   addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
-                        llvm::opt::ArgStringList &CC1Args,
-                        llvm::StringRef BoundArch,
+                        llvm::opt::ArgStringList &CC1Args, BoundArch BA,
                         Action::OffloadKind DeviceOffloadKind) const override;
 
   std::optional<std::string> findAVRLibcInstallation() const;

diff  --git a/clang/lib/Driver/ToolChains/BareMetal.cpp b/clang/lib/Driver/ToolChains/BareMetal.cpp
index 0a8e5d7f5b74a..ba454acbf755c 100644
--- a/clang/lib/Driver/ToolChains/BareMetal.cpp
+++ b/clang/lib/Driver/ToolChains/BareMetal.cpp
@@ -351,8 +351,7 @@ void BareMetal::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
 }
 
 void BareMetal::addClangTargetOptions(const ArgList &DriverArgs,
-                                      ArgStringList &CC1Args,
-                                      StringRef BoundArch,
+                                      ArgStringList &CC1Args, BoundArch BA,
                                       Action::OffloadKind) const {
   CC1Args.push_back("-nostdsysteminc");
 }
@@ -650,14 +649,13 @@ void baremetal::Linker::ConstructJob(Compilation &C, const JobAction &JA,
 // code, ignoring all runtime library support issues on the assumption that
 // baremetal targets typically implement their own runtime support.
 SanitizerMask
-BareMetal::getSupportedSanitizers(StringRef BoundArch,
+BareMetal::getSupportedSanitizers(BoundArch BA,
                                   Action::OffloadKind DeviceOffloadKind) const {
   const bool IsX86_64 = getTriple().getArch() == llvm::Triple::x86_64;
   const bool IsAArch64 = getTriple().getArch() == llvm::Triple::aarch64 ||
                          getTriple().getArch() == llvm::Triple::aarch64_be;
   const bool IsRISCV64 = getTriple().isRISCV64();
-  SanitizerMask Res =
-      ToolChain::getSupportedSanitizers(BoundArch, DeviceOffloadKind);
+  SanitizerMask Res = ToolChain::getSupportedSanitizers(BA, DeviceOffloadKind);
   Res |= SanitizerKind::Address;
   Res |= SanitizerKind::KernelAddress;
   Res |= SanitizerKind::PointerCompare;

diff  --git a/clang/lib/Driver/ToolChains/BareMetal.h b/clang/lib/Driver/ToolChains/BareMetal.h
index 14e9c6e990cae..5e6fb3cca5fa4 100644
--- a/clang/lib/Driver/ToolChains/BareMetal.h
+++ b/clang/lib/Driver/ToolChains/BareMetal.h
@@ -67,8 +67,7 @@ class LLVM_LIBRARY_VISIBILITY BareMetal : public Generic_ELF {
                             llvm::opt::ArgStringList &CC1Args) const override;
   void
   addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
-                        llvm::opt::ArgStringList &CC1Args,
-                        llvm::StringRef BoundArch,
+                        llvm::opt::ArgStringList &CC1Args, BoundArch BA,
                         Action::OffloadKind DeviceOffloadKind) const override;
   void AddClangCXXStdlibIncludeArgs(
       const llvm::opt::ArgList &DriverArgs,
@@ -79,7 +78,7 @@ class LLVM_LIBRARY_VISIBILITY BareMetal : public Generic_ELF {
   std::string computeSysRoot() const override;
   std::string getCompilerRTPath() const override;
   SanitizerMask
-  getSupportedSanitizers(StringRef BoundArch,
+  getSupportedSanitizers(BoundArch BA,
                          Action::OffloadKind DeviceOffloadKind) const override;
 
 private:

diff  --git a/clang/lib/Driver/ToolChains/CSKYToolChain.cpp b/clang/lib/Driver/ToolChains/CSKYToolChain.cpp
index 670abb4e75082..bee7b9d728158 100644
--- a/clang/lib/Driver/ToolChains/CSKYToolChain.cpp
+++ b/clang/lib/Driver/ToolChains/CSKYToolChain.cpp
@@ -75,7 +75,7 @@ CSKYToolChain::GetUnwindLibType(const llvm::opt::ArgList &Args) const {
 
 void CSKYToolChain::addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
                                           llvm::opt::ArgStringList &CC1Args,
-                                          llvm::StringRef BoundArch,
+                                          BoundArch BA,
                                           Action::OffloadKind) const {
   CC1Args.push_back("-nostdsysteminc");
 }

diff  --git a/clang/lib/Driver/ToolChains/CSKYToolChain.h b/clang/lib/Driver/ToolChains/CSKYToolChain.h
index 82f5acb42e98f..3eb01d2d764e3 100644
--- a/clang/lib/Driver/ToolChains/CSKYToolChain.h
+++ b/clang/lib/Driver/ToolChains/CSKYToolChain.h
@@ -22,8 +22,7 @@ class LLVM_LIBRARY_VISIBILITY CSKYToolChain : public Generic_ELF {
                 const llvm::opt::ArgList &Args);
 
   void addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
-                             llvm::opt::ArgStringList &CC1Args,
-                             llvm::StringRef BoundArch,
+                             llvm::opt::ArgStringList &CC1Args, BoundArch BA,
                              Action::OffloadKind) const override;
   RuntimeLibType GetDefaultRuntimeLibType() const override;
   UnwindLibType GetUnwindLibType(const llvm::opt::ArgList &Args) const override;

diff  --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp
index ca924ccf9152d..a93dd2969504c 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -1088,11 +1088,10 @@ void Clang::AddPreprocessingOptions(Compilation &C, const JobAction &JA,
     std::set<unsigned> ArchIDs;
     for (auto &I : llvm::make_range(C.getOffloadToolChains(Action::OFK_Cuda))) {
       const ToolChain *TC = I.second;
-      for (StringRef Arch :
+      for (BoundArch Arch :
            D.getOffloadArchs(C, C.getArgs(), Action::OFK_Cuda, *TC)) {
-        OffloadArch OA = StringToOffloadArch(Arch);
-        if (IsNVIDIAOffloadArch(OA))
-          ArchIDs.insert(CudaArchToID(OA));
+        if (IsNVIDIAOffloadArch(Arch.Arch))
+          ArchIDs.insert(CudaArchToID(Arch.Arch));
       }
     }
 
@@ -1314,7 +1313,7 @@ static void renderRemarksOptions(const ArgList &Args, ArgStringList &CmdArgs,
         F += Action::GetOffloadingFileNamePrefix(JA.getOffloadingDeviceKind(),
                                                  Triple.str());
         F += "-";
-        F += JA.getOffloadingArch();
+        F += JA.getOffloadingArch().ArchName;
       }
     }
 
@@ -6194,9 +6193,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
 
   Args.AddLastArg(CmdArgs, options::OPT_fno_knr_functions);
 
-  const char *OffloadArch = JA.getOffloadingArch();
-  auto SanitizeArgs = TC.getSanitizerArgs(Args, OffloadArch ? OffloadArch : "",
-                                          JA.getOffloadingDeviceKind());
+  BoundArch OffloadArch = JA.getOffloadingArch();
+  auto SanitizeArgs =
+      TC.getSanitizerArgs(Args, OffloadArch, JA.getOffloadingDeviceKind());
   Args.AddLastArg(CmdArgs,
                   options::OPT_fallow_runtime_check_skip_hot_cutoff_EQ);
 
@@ -6235,7 +6234,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
   // `--gpu-use-aux-triple-only` is specified.
   if (AuxTriple && !Args.getLastArg(options::OPT_gpu_use_aux_triple_only)) {
     const ArgList &HostArgs =
-        C.getArgsForToolChain(nullptr, StringRef(), Action::OFK_None);
+        C.getArgsForToolChain(nullptr, BoundArch(), Action::OFK_None);
     std::string HostCPU = getCPUName(D, HostArgs, *AuxTriple, /*FromAs*/ false);
     if (!HostCPU.empty()) {
       CmdArgs.push_back("-aux-target-cpu");
@@ -9387,7 +9386,7 @@ void OffloadBundler::ConstructJob(Compilation &C, const JobAction &JA,
 
     if (const auto *OA = dyn_cast<OffloadAction>(CurDep)) {
       CurTC = nullptr;
-      OA->doOnEachDependence([&](Action *A, const ToolChain *TC, const char *) {
+      OA->doOnEachDependence([&](Action *A, const ToolChain *TC, BoundArch BA) {
         assert(CurTC == nullptr && "Expected one dependence!");
         CurKind = A->getOffloadingDeviceKind();
         CurTC = TC;
@@ -9399,10 +9398,9 @@ void OffloadBundler::ConstructJob(Compilation &C, const JobAction &JA,
                                 TCArgs, CurDep->getOffloadingArch()))
                    .normalize(llvm::Triple::CanonicalForm::FOUR_IDENT);
 
-    if ((CurKind != Action::OFK_Host) &&
-        !StringRef(CurDep->getOffloadingArch()).empty()) {
+    if ((CurKind != Action::OFK_Host) && !CurDep->getOffloadingArch().empty()) {
       Triples += '-';
-      Triples += CurDep->getOffloadingArch();
+      Triples += CurDep->getOffloadingArch().ArchName;
     }
   }
   CmdArgs.push_back(TCArgs.MakeArgString(Triples));
@@ -9420,7 +9418,7 @@ void OffloadBundler::ConstructJob(Compilation &C, const JobAction &JA,
     const ToolChain *CurTC = &getToolChain();
     if (const auto *OA = dyn_cast<OffloadAction>(JA.getInputs()[I])) {
       CurTC = nullptr;
-      OA->doOnEachDependence([&](Action *, const ToolChain *TC, const char *) {
+      OA->doOnEachDependence([&](Action *, const ToolChain *TC, BoundArch) {
         assert(CurTC == nullptr && "Expected one dependence!");
         CurTC = TC;
       });
@@ -9483,7 +9481,7 @@ void OffloadBundler::ConstructJobMultipleOutputs(
          Dep.DependentOffloadKind == Action::OFK_Cuda) &&
         !Dep.DependentBoundArch.empty()) {
       Triples += '-';
-      Triples += Dep.DependentBoundArch;
+      Triples += Dep.DependentBoundArch.ArchName;
     }
   }
 
@@ -9532,9 +9530,10 @@ void OffloadPackager::ConstructJob(Compilation &C, const JobAction &JA,
         C.getArgsForToolChain(TC, OffloadAction->getOffloadingArch(),
                               OffloadAction->getOffloadingDeviceKind());
     StringRef File = C.getArgs().MakeArgString(TC->getInputFilename(Input));
-    StringRef Arch = OffloadAction->getOffloadingArch()
-                         ? OffloadAction->getOffloadingArch()
-                         : TCArgs.getLastArgValue(options::OPT_march_EQ);
+    BoundArch Arch = OffloadAction->getOffloadingArch();
+    if (Arch.empty())
+      Arch = BoundArch(TCArgs.getLastArgValue(options::OPT_march_EQ));
+
     StringRef Kind =
       Action::GetOffloadKindName(OffloadAction->getOffloadingDeviceKind());
 
@@ -9550,7 +9549,7 @@ void OffloadPackager::ConstructJob(Compilation &C, const JobAction &JA,
     SmallVector<std::string> Parts{
         "file=" + File.str(),
         "triple=" + TC->ComputeEffectiveClangTriple(TCArgs, Arch),
-        "arch=" + (Arch.empty() ? "generic" : Arch.str()),
+        "arch=" + (Arch.empty() ? "generic" : Arch.ArchName.str()),
         "kind=" + Kind.str(),
     };
 
@@ -9704,7 +9703,7 @@ void LinkerWrapper::ConstructJob(Compilation &C, const JobAction &JA,
       ArgStringList CompilerArgs;
       ArgStringList LinkerArgs;
       const DerivedArgList &ToolChainArgs =
-          C.getArgsForToolChain(TC, /*BoundArch=*/"", Kind);
+          C.getArgsForToolChain(TC, /*BA=*/{}, Kind);
       for (Arg *A : ToolChainArgs) {
         if (A->getOption().matches(OPT_Zlinker_input))
           LinkerArgs.emplace_back(A->getValue());

diff  --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp
index 07ad7d80b39c1..ba4341ed41f1a 100644
--- a/clang/lib/Driver/ToolChains/CommonArgs.cpp
+++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp
@@ -1894,7 +1894,7 @@ const char *tools::SplitDebugName(const JobAction &JA, const ArgList &Args,
                                   const InputInfo &Output) {
   auto AddPostfix = [JA](auto &F) {
     if (JA.getOffloadingDeviceKind() == Action::OFK_HIP)
-      F += (Twine("_") + JA.getOffloadingArch()).str();
+      F += (Twine("_") + JA.getOffloadingArch().ArchName).str();
     F += ".dwo";
   };
   if (Arg *A = Args.getLastArg(options::OPT_gsplit_dwarf_EQ))

diff  --git a/clang/lib/Driver/ToolChains/CrossWindows.cpp b/clang/lib/Driver/ToolChains/CrossWindows.cpp
index 5bd1cd46cc080..180e91e857c0f 100644
--- a/clang/lib/Driver/ToolChains/CrossWindows.cpp
+++ b/clang/lib/Driver/ToolChains/CrossWindows.cpp
@@ -283,9 +283,8 @@ AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args,
 }
 
 clang::SanitizerMask CrossWindowsToolChain::getSupportedSanitizers(
-    StringRef BoundArch, Action::OffloadKind DeviceOffloadKind) const {
-  SanitizerMask Res =
-      ToolChain::getSupportedSanitizers(BoundArch, DeviceOffloadKind);
+    BoundArch BA, Action::OffloadKind DeviceOffloadKind) const {
+  SanitizerMask Res = ToolChain::getSupportedSanitizers(BA, DeviceOffloadKind);
   Res |= SanitizerKind::Address;
   Res |= SanitizerKind::PointerCompare;
   Res |= SanitizerKind::PointerSubtract;

diff  --git a/clang/lib/Driver/ToolChains/CrossWindows.h b/clang/lib/Driver/ToolChains/CrossWindows.h
index d6263823759c7..729d9846934e5 100644
--- a/clang/lib/Driver/ToolChains/CrossWindows.h
+++ b/clang/lib/Driver/ToolChains/CrossWindows.h
@@ -75,7 +75,7 @@ class LLVM_LIBRARY_VISIBILITY CrossWindowsToolChain : public Generic_GCC {
                            llvm::opt::ArgStringList &CmdArgs) const override;
 
   SanitizerMask
-  getSupportedSanitizers(StringRef BoundArch,
+  getSupportedSanitizers(BoundArch BA,
                          Action::OffloadKind DeviceOffloadKind) const override;
 
 protected:

diff  --git a/clang/lib/Driver/ToolChains/Cuda.cpp b/clang/lib/Driver/ToolChains/Cuda.cpp
index b490ee5615d0c..9590ff976275c 100644
--- a/clang/lib/Driver/ToolChains/Cuda.cpp
+++ b/clang/lib/Driver/ToolChains/Cuda.cpp
@@ -397,16 +397,16 @@ void NVPTX::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
       static_cast<const toolchains::NVPTXToolChain &>(getToolChain());
   assert(TC.getTriple().isNVPTX() && "Wrong platform");
 
-  StringRef GPUArchName;
+  BoundArch GPUArch;
   // If this is a CUDA action we need to extract the device architecture
   // from the Job's associated architecture, otherwise use the -march=arch
   // option. This option may come from -Xopenmp-target flag or the default
   // value.
   if (JA.isDeviceOffloading(Action::OFK_Cuda)) {
-    GPUArchName = JA.getOffloadingArch();
+    GPUArch = JA.getOffloadingArch();
   } else {
-    GPUArchName = Args.getLastArgValue(options::OPT_march_EQ);
-    if (GPUArchName.empty()) {
+    GPUArch = BoundArch(Args.getLastArgValue(options::OPT_march_EQ));
+    if (GPUArch.empty()) {
       C.getDriver().Diag(diag::err_drv_offload_missing_gpu_arch)
           << getToolChain().getArchName() << getShortName();
       return;
@@ -414,13 +414,12 @@ void NVPTX::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
   }
 
   // Obtain architecture from the action.
-  OffloadArch gpu_arch = StringToOffloadArch(GPUArchName);
-  assert(gpu_arch != OffloadArch::Unknown &&
+  assert(GPUArch.Arch != OffloadArch::Unknown &&
          "Device action expected to have an architecture.");
 
   // Check that our installation's ptxas supports gpu_arch.
   if (!Args.hasArg(options::OPT_no_cuda_version_check)) {
-    TC.CudaInstallation.CheckCudaVersionSupportsArch(gpu_arch);
+    TC.CudaInstallation.CheckCudaVersionSupportsArch(GPUArch.Arch);
   }
 
   ArgStringList CmdArgs;
@@ -470,7 +469,7 @@ void NVPTX::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
     CmdArgs.push_back("-v");
 
   CmdArgs.push_back("--gpu-name");
-  CmdArgs.push_back(Args.MakeArgString(OffloadArchToString(gpu_arch)));
+  CmdArgs.push_back(Args.MakeArgString(GPUArch.ArchName));
   CmdArgs.push_back("--output-file");
   std::string OutputFileName = TC.getInputFilename(Output);
 
@@ -556,15 +555,16 @@ void NVPTX::FatBinary::ConstructJob(Compilation &C, const JobAction &JA,
     auto *A = II.getAction();
     assert(A->getInputs().size() == 1 &&
            "Device offload action is expected to have a single input");
-    StringRef GpuArch = A->getOffloadingArch();
+    BoundArch GpuArch = A->getOffloadingArch();
     assert(!GpuArch.empty() &&
            "Device action expected to have associated a GPU architecture!");
 
-    if (II.getType() == types::TY_PP_Asm && !shouldIncludePTX(Args, GpuArch))
+    if (II.getType() == types::TY_PP_Asm &&
+        !shouldIncludePTX(Args, GpuArch.ArchName))
       continue;
     StringRef Kind = (II.getType() == types::TY_PP_Asm) ? "ptx" : "elf";
     CmdArgs.push_back(Args.MakeArgString(
-        "--image3=kind=" + Kind + ",sm=" + GpuArch.drop_front(3) +
+        "--image3=kind=" + Kind + ",sm=" + GpuArch.ArchName.drop_front(3) +
         ",file=" + getToolChain().getInputFilename(II)));
   }
 
@@ -758,9 +758,9 @@ NVPTXToolChain::NVPTXToolChain(const Driver &D, const llvm::Triple &Triple,
 
 llvm::opt::DerivedArgList *
 NVPTXToolChain::TranslateArgs(const llvm::opt::DerivedArgList &Args,
-                              StringRef BoundArch,
+                              BoundArch BA,
                               Action::OffloadKind OffloadKind) const {
-  DerivedArgList *DAL = ToolChain::TranslateArgs(Args, BoundArch, OffloadKind);
+  DerivedArgList *DAL = ToolChain::TranslateArgs(Args, BA, OffloadKind);
   if (!DAL)
     DAL = new DerivedArgList(Args.getBaseArgs());
 
@@ -796,8 +796,7 @@ NVPTXToolChain::TranslateArgs(const llvm::opt::DerivedArgList &Args,
 
 void NVPTXToolChain::addClangTargetOptions(
     const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args,
-    llvm::StringRef BoundArch, Action::OffloadKind DeviceOffloadingKind) const {
-}
+    BoundArch BA, Action::OffloadKind DeviceOffloadingKind) const {}
 
 void NVPTXToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
                                                ArgStringList &CC1Args) const {
@@ -884,9 +883,8 @@ CudaToolChain::CudaToolChain(const Driver &D, const llvm::Triple &Triple,
 
 void CudaToolChain::addClangTargetOptions(
     const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args,
-    llvm::StringRef BoundArch, Action::OffloadKind DeviceOffloadingKind) const {
-  HostTC.addClangTargetOptions(DriverArgs, CC1Args, BoundArch,
-                               DeviceOffloadingKind);
+    BoundArch BA, Action::OffloadKind DeviceOffloadingKind) const {
+  HostTC.addClangTargetOptions(DriverArgs, CC1Args, BA, DeviceOffloadingKind);
 
   StringRef GpuArch = DriverArgs.getLastArgValue(options::OPT_march_EQ);
   assert((DeviceOffloadingKind == Action::OFK_OpenMP ||
@@ -987,10 +985,9 @@ std::string CudaToolChain::getInputFilename(const InputInfo &Input) const {
 
 llvm::opt::DerivedArgList *
 CudaToolChain::TranslateArgs(const llvm::opt::DerivedArgList &Args,
-                             StringRef BoundArch,
+                             BoundArch BA,
                              Action::OffloadKind DeviceOffloadKind) const {
-  DerivedArgList *DAL =
-      HostTC.TranslateArgs(Args, BoundArch, DeviceOffloadKind);
+  DerivedArgList *DAL = HostTC.TranslateArgs(Args, BA, DeviceOffloadKind);
   if (!DAL)
     DAL = new DerivedArgList(Args.getBaseArgs());
 
@@ -1003,10 +1000,10 @@ CudaToolChain::TranslateArgs(const llvm::opt::DerivedArgList &Args,
     }
   }
 
-  if (!BoundArch.empty()) {
+  if (BA) {
     DAL->eraseArg(options::OPT_march_EQ);
     DAL->AddJoinedArg(nullptr, Opts.getOption(options::OPT_march_EQ),
-                      BoundArch);
+                      BA.ArchName);
   }
   return DAL;
 }
@@ -1059,7 +1056,7 @@ void CudaToolChain::AddIAMCUIncludeArgs(const ArgList &Args,
 }
 
 SanitizerMask CudaToolChain::getSupportedSanitizers(
-    StringRef BoundArch, Action::OffloadKind DeviceOffloadKind) const {
+    BoundArch BA, Action::OffloadKind DeviceOffloadKind) const {
   // The CudaToolChain only supports sanitizers in the sense that it allows
   // sanitizer arguments on the command line if they are supported by the host
   // toolchain. The CudaToolChain will actually ignore any command line
@@ -1071,7 +1068,7 @@ SanitizerMask CudaToolChain::getSupportedSanitizers(
   // tolerate flags meant only for the host toolchain.
 
   // FIXME: Be accurate and use DeviceOffloadKind.
-  return HostTC.getSupportedSanitizers(BoundArch, DeviceOffloadKind);
+  return HostTC.getSupportedSanitizers(BA, DeviceOffloadKind);
 }
 
 VersionTuple CudaToolChain::computeMSVCVersion(const Driver *D,

diff  --git a/clang/lib/Driver/ToolChains/Cuda.h b/clang/lib/Driver/ToolChains/Cuda.h
index 390ebad9442bc..da527b559dac7 100644
--- a/clang/lib/Driver/ToolChains/Cuda.h
+++ b/clang/lib/Driver/ToolChains/Cuda.h
@@ -85,13 +85,12 @@ class LLVM_LIBRARY_VISIBILITY NVPTXToolChain : public ToolChain {
                  const llvm::opt::ArgList &Args);
 
   llvm::opt::DerivedArgList *
-  TranslateArgs(const llvm::opt::DerivedArgList &Args, StringRef BoundArch,
+  TranslateArgs(const llvm::opt::DerivedArgList &Args, BoundArch BA,
                 Action::OffloadKind DeviceOffloadKind) const override;
 
   void
   addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
-                        llvm::opt::ArgStringList &CC1Args,
-                        llvm::StringRef BoundArch,
+                        llvm::opt::ArgStringList &CC1Args, BoundArch BA,
                         Action::OffloadKind DeviceOffloadKind) const override;
   void
   AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
@@ -145,12 +144,11 @@ class LLVM_LIBRARY_VISIBILITY CudaToolChain : public NVPTXToolChain {
   std::string getInputFilename(const InputInfo &Input) const override;
 
   llvm::opt::DerivedArgList *
-  TranslateArgs(const llvm::opt::DerivedArgList &Args, StringRef BoundArch,
+  TranslateArgs(const llvm::opt::DerivedArgList &Args, BoundArch BA,
                 Action::OffloadKind DeviceOffloadKind) const override;
   void
   addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
-                        llvm::opt::ArgStringList &CC1Args,
-                        llvm::StringRef BoundArch,
+                        llvm::opt::ArgStringList &CC1Args, BoundArch BA,
                         Action::OffloadKind DeviceOffloadKind) const override;
 
   llvm::DenormalMode getDefaultDenormalModeForType(
@@ -172,7 +170,7 @@ class LLVM_LIBRARY_VISIBILITY CudaToolChain : public NVPTXToolChain {
                            llvm::opt::ArgStringList &CC1Args) const override;
 
   SanitizerMask
-  getSupportedSanitizers(StringRef BoundArch,
+  getSupportedSanitizers(BoundArch BA,
                          Action::OffloadKind DeviceOffloadKind) const override;
 
   VersionTuple

diff  --git a/clang/lib/Driver/ToolChains/Darwin.cpp b/clang/lib/Driver/ToolChains/Darwin.cpp
index 59744d1cb3e8c..2d307f5ee6366 100644
--- a/clang/lib/Driver/ToolChains/Darwin.cpp
+++ b/clang/lib/Driver/ToolChains/Darwin.cpp
@@ -1254,9 +1254,9 @@ void Darwin::VerifyTripleForSDK(const llvm::opt::ArgList &Args,
 }
 
 std::string Darwin::ComputeEffectiveClangTriple(const ArgList &Args,
-                                                llvm::StringRef BoundArch,
+                                                BoundArch BA,
                                                 types::ID InputType) const {
-  llvm::Triple Triple(ComputeLLVMTriple(Args, BoundArch, InputType));
+  llvm::Triple Triple(ComputeLLVMTriple(Args, BA, InputType));
 
   // If the target isn't initialized (e.g., an unknown Darwin platform, return
   // the default triple). Note: we intentionally do NOT call
@@ -1349,10 +1349,9 @@ void DarwinClang::addClangWarningOptions(ArgStringList &CC1Args) const {
 
 void DarwinClang::addClangTargetOptions(
     const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args,
-    llvm::StringRef BoundArch, Action::OffloadKind DeviceOffloadKind) const {
+    BoundArch BA, Action::OffloadKind DeviceOffloadKind) const {
 
-  Darwin::addClangTargetOptions(DriverArgs, CC1Args, BoundArch,
-                                DeviceOffloadKind);
+  Darwin::addClangTargetOptions(DriverArgs, CC1Args, BA, DeviceOffloadKind);
 }
 
 /// Take a path that speculatively points into Xcode and return the
@@ -3161,8 +3160,7 @@ void DarwinClang::AddCCKextLibArgs(const ArgList &Args,
     CmdArgs.push_back(Args.MakeArgString(P));
 }
 
-DerivedArgList *MachO::TranslateArgs(const DerivedArgList &Args,
-                                     StringRef BoundArch,
+DerivedArgList *MachO::TranslateArgs(const DerivedArgList &Args, BoundArch BA,
                                      Action::OffloadKind) const {
   DerivedArgList *DAL = new DerivedArgList(Args.getBaseArgs());
   const OptTable &Opts = getDriver().getOpts();
@@ -3231,8 +3229,8 @@ DerivedArgList *MachO::TranslateArgs(const DerivedArgList &Args,
 
   // Add the arch options based on the particular spelling of -arch, to match
   // how the driver works.
-  if (!BoundArch.empty()) {
-    StringRef Name = BoundArch;
+  if (BA) {
+    StringRef Name = BA.ArchName;
     const Option MCpu = Opts.getOption(options::OPT_mcpu_EQ);
     const Option MArch = Opts.getOption(options::OPT_march_EQ);
 
@@ -3440,11 +3438,10 @@ bool Darwin::isSizedDeallocationUnavailable() const {
 
 void MachO::addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
                                   llvm::opt::ArgStringList &CC1Args,
-                                  llvm::StringRef BoundArch,
+                                  BoundArch BA,
                                   Action::OffloadKind DeviceOffloadKind) const {
 
-  ToolChain::addClangTargetOptions(DriverArgs, CC1Args, BoundArch,
-                                   DeviceOffloadKind);
+  ToolChain::addClangTargetOptions(DriverArgs, CC1Args, BA, DeviceOffloadKind);
 
   // On arm64e, we enable all the features required for the Darwin userspace
   // ABI
@@ -3491,10 +3488,9 @@ void MachO::addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
 
 void Darwin::addClangTargetOptions(
     const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args,
-    llvm::StringRef BoundArch, Action::OffloadKind DeviceOffloadKind) const {
+    BoundArch BA, Action::OffloadKind DeviceOffloadKind) const {
 
-  MachO::addClangTargetOptions(DriverArgs, CC1Args, BoundArch,
-                               DeviceOffloadKind);
+  MachO::addClangTargetOptions(DriverArgs, CC1Args, BA, DeviceOffloadKind);
 
   // When compiling device code (e.g. SPIR-V for HIP), skip host-specific
   // flags like -faligned-alloc-unavailable and -fno-sized-deallocation
@@ -3660,14 +3656,13 @@ void Darwin::addClangCC1ASTargetOptions(
 }
 
 DerivedArgList *
-Darwin::TranslateArgs(const DerivedArgList &Args, StringRef BoundArch,
+Darwin::TranslateArgs(const DerivedArgList &Args, BoundArch BA,
                       Action::OffloadKind DeviceOffloadKind) const {
   // First get the generic Apple args, before moving onto Darwin-specific ones.
-  DerivedArgList *DAL =
-      MachO::TranslateArgs(Args, BoundArch, DeviceOffloadKind);
+  DerivedArgList *DAL = MachO::TranslateArgs(Args, BA, DeviceOffloadKind);
 
   // If no architecture is bound, none of the translations here are relevant.
-  if (BoundArch.empty())
+  if (!BA)
     return DAL;
 
   // Add an explicit version min argument for the deployment target. We do this
@@ -3696,12 +3691,12 @@ Darwin::TranslateArgs(const DerivedArgList &Args, StringRef BoundArch,
     }
   }
 
-  auto Arch = tools::darwin::getArchTypeForMachOArchName(BoundArch);
+  auto Arch = tools::darwin::getArchTypeForMachOArchName(BA.ArchName);
   if ((Arch == llvm::Triple::arm || Arch == llvm::Triple::thumb)) {
     if (Args.hasFlag(options::OPT_fomit_frame_pointer,
                      options::OPT_fno_omit_frame_pointer, false))
       getDriver().Diag(clang::diag::warn_drv_unsupported_opt_for_target)
-          << "-fomit-frame-pointer" << BoundArch;
+          << "-fomit-frame-pointer" << BA.ArchName;
   }
 
   return DAL;
@@ -4052,12 +4047,11 @@ void Darwin::CheckObjCARC() const {
 }
 
 SanitizerMask
-Darwin::getSupportedSanitizers(StringRef BoundArch,
+Darwin::getSupportedSanitizers(BoundArch BA,
                                Action::OffloadKind DeviceOffloadKind) const {
   const bool IsX86_64 = getTriple().getArch() == llvm::Triple::x86_64;
   const bool IsAArch64 = getTriple().getArch() == llvm::Triple::aarch64;
-  SanitizerMask Res =
-      ToolChain::getSupportedSanitizers(BoundArch, DeviceOffloadKind);
+  SanitizerMask Res = ToolChain::getSupportedSanitizers(BA, DeviceOffloadKind);
   Res |= SanitizerKind::Address;
   Res |= SanitizerKind::PointerCompare;
   Res |= SanitizerKind::PointerSubtract;

diff  --git a/clang/lib/Driver/ToolChains/Darwin.h b/clang/lib/Driver/ToolChains/Darwin.h
index a737d2ac799c4..7b5f1980a2dc8 100644
--- a/clang/lib/Driver/ToolChains/Darwin.h
+++ b/clang/lib/Driver/ToolChains/Darwin.h
@@ -147,8 +147,7 @@ class LLVM_LIBRARY_VISIBILITY MachO : public ToolChain {
 
   void
   addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
-                        llvm::opt::ArgStringList &CC1Args,
-                        llvm::StringRef BoundArch,
+                        llvm::opt::ArgStringList &CC1Args, BoundArch BA,
                         Action::OffloadKind DeviceOffloadKind) const override;
 
 private:
@@ -251,7 +250,7 @@ class LLVM_LIBRARY_VISIBILITY MachO : public ToolChain {
   bool HasNativeLLVMSupport() const override;
 
   llvm::opt::DerivedArgList *
-  TranslateArgs(const llvm::opt::DerivedArgList &Args, StringRef BoundArch,
+  TranslateArgs(const llvm::opt::DerivedArgList &Args, BoundArch BA,
                 Action::OffloadKind DeviceOffloadKind) const override;
 
   bool IsBlocksDefault() const override {
@@ -404,7 +403,7 @@ class LLVM_LIBRARY_VISIBILITY Darwin : public AppleMachO {
   ~Darwin() override;
 
   std::string ComputeEffectiveClangTriple(const llvm::opt::ArgList &Args,
-                                          llvm::StringRef BoundArch,
+                                          BoundArch BA,
                                           types::ID InputType) const override;
 
   /// @name Darwin Specific Toolchain Implementation
@@ -596,8 +595,7 @@ class LLVM_LIBRARY_VISIBILITY Darwin : public AppleMachO {
 
   void
   addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
-                        llvm::opt::ArgStringList &CC1Args,
-                        llvm::StringRef BoundArch,
+                        llvm::opt::ArgStringList &CC1Args, BoundArch BA,
                         Action::OffloadKind DeviceOffloadKind) const override;
 
   void addClangCC1ASTargetOptions(
@@ -619,7 +617,7 @@ class LLVM_LIBRARY_VISIBILITY Darwin : public AppleMachO {
   bool isCrossCompiling() const override { return false; }
 
   llvm::opt::DerivedArgList *
-  TranslateArgs(const llvm::opt::DerivedArgList &Args, StringRef BoundArch,
+  TranslateArgs(const llvm::opt::DerivedArgList &Args, BoundArch BA,
                 Action::OffloadKind DeviceOffloadKind) const override;
 
   CXXStdlibType GetDefaultCXXStdlibType() const override;
@@ -656,7 +654,7 @@ class LLVM_LIBRARY_VISIBILITY Darwin : public AppleMachO {
   bool SupportsEmbeddedBitcode() const override;
 
   SanitizerMask
-  getSupportedSanitizers(StringRef BoundArch,
+  getSupportedSanitizers(BoundArch BA,
                          Action::OffloadKind DeviceOffloadKind) const override;
 };
 
@@ -686,8 +684,7 @@ class LLVM_LIBRARY_VISIBILITY DarwinClang : public Darwin {
 
   void
   addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
-                        llvm::opt::ArgStringList &CC1Args,
-                        llvm::StringRef BoundArch,
+                        llvm::opt::ArgStringList &CC1Args, BoundArch BA,
                         Action::OffloadKind DeviceOffloadKind) const override;
 
   void AddLinkARCArgs(const llvm::opt::ArgList &Args,

diff  --git a/clang/lib/Driver/ToolChains/Flang.cpp b/clang/lib/Driver/ToolChains/Flang.cpp
index 5f536b5d96f90..1d74a34583311 100644
--- a/clang/lib/Driver/ToolChains/Flang.cpp
+++ b/clang/lib/Driver/ToolChains/Flang.cpp
@@ -528,7 +528,7 @@ static void processVSRuntimeLibrary(const ToolChain &TC, const ArgList &Args,
 }
 
 void Flang::AddAMDGPUTargetArgs(const ArgList &Args, ArgStringList &CmdArgs,
-                                StringRef BoundArch,
+                                BoundArch BA,
                                 Action::OffloadKind DeviceOffloadKind) const {
   if (Arg *A = Args.getLastArg(options::OPT_mcode_object_version_EQ)) {
     StringRef Val = A->getValue();
@@ -539,11 +539,11 @@ void Flang::AddAMDGPUTargetArgs(const ArgList &Args, ArgStringList &CmdArgs,
   }
 
   const ToolChain &TC = getToolChain();
-  TC.addClangTargetOptions(Args, CmdArgs, BoundArch, DeviceOffloadKind);
+  TC.addClangTargetOptions(Args, CmdArgs, BA, DeviceOffloadKind);
 }
 
 void Flang::AddNVPTXTargetArgs(const ArgList &Args, ArgStringList &CmdArgs,
-                               StringRef BoundArch,
+                               BoundArch BA,
                                Action::OffloadKind DeviceOffloadKind) const {
   // we cannot use addClangTargetOptions, as it appends unsupported args for
   // flang: -fcuda-is-device, -fno-threadsafe-statics,
@@ -580,7 +580,7 @@ void Flang::AddNVPTXTargetArgs(const ArgList &Args, ArgStringList &CmdArgs,
 }
 
 void Flang::addTargetOptions(const ArgList &Args, ArgStringList &CmdArgs,
-                             StringRef BoundArch,
+                             BoundArch BA,
                              Action::OffloadKind DeviceOffloadKind) const {
   const ToolChain &TC = getToolChain();
   const llvm::Triple &Triple = TC.getEffectiveTriple();
@@ -607,11 +607,11 @@ void Flang::addTargetOptions(const ArgList &Args, ArgStringList &CmdArgs,
   case llvm::Triple::r600:
   case llvm::Triple::amdgcn:
     getTargetFeatures(D, Triple, Args, CmdArgs, /*ForAs*/ false);
-    AddAMDGPUTargetArgs(Args, CmdArgs, BoundArch, DeviceOffloadKind);
+    AddAMDGPUTargetArgs(Args, CmdArgs, BA, DeviceOffloadKind);
     break;
   case llvm::Triple::nvptx:
   case llvm::Triple::nvptx64:
-    AddNVPTXTargetArgs(Args, CmdArgs, BoundArch, DeviceOffloadKind);
+    AddNVPTXTargetArgs(Args, CmdArgs, BA, DeviceOffloadKind);
     break;
   case llvm::Triple::riscv64:
     getTargetFeatures(D, Triple, Args, CmdArgs, /*ForAs*/ false);

diff  --git a/clang/lib/Driver/ToolChains/Flang.h b/clang/lib/Driver/ToolChains/Flang.h
index f08baa0fd5c12..a887301c703cd 100644
--- a/clang/lib/Driver/ToolChains/Flang.h
+++ b/clang/lib/Driver/ToolChains/Flang.h
@@ -64,8 +64,7 @@ class LLVM_LIBRARY_VISIBILITY Flang : public Tool {
   /// \param [in] BoundArch The bound architecture for offload compilation
   /// \param [in] DeviceOffloadKind The offload kind
   void addTargetOptions(const llvm::opt::ArgList &Args,
-                        llvm::opt::ArgStringList &CmdArgs,
-                        llvm::StringRef BoundArch,
+                        llvm::opt::ArgStringList &CmdArgs, BoundArch BA,
                         Action::OffloadKind DeviceOffloadKind) const;
 
   /// Add specific options for AArch64 target.
@@ -82,13 +81,11 @@ class LLVM_LIBRARY_VISIBILITY Flang : public Tool {
   /// \param [in] BoundArch The bound architecture for offload compilation
   /// \param [in] DeviceOffloadKind The offload kind
   void AddAMDGPUTargetArgs(const llvm::opt::ArgList &Args,
-                           llvm::opt::ArgStringList &CmdArgs,
-                           llvm::StringRef BoundArch,
+                           llvm::opt::ArgStringList &CmdArgs, BoundArch BA,
                            Action::OffloadKind DeviceOffloadKind) const;
 
   void AddNVPTXTargetArgs(const llvm::opt::ArgList &Args,
-                          llvm::opt::ArgStringList &CmdArgs,
-                          llvm::StringRef BoundArch,
+                          llvm::opt::ArgStringList &CmdArgs, BoundArch BA,
                           Action::OffloadKind DeviceOffloadKind) const;
 
   /// Add specific options for LoongArch64 target.

diff  --git a/clang/lib/Driver/ToolChains/FreeBSD.cpp b/clang/lib/Driver/ToolChains/FreeBSD.cpp
index 1218868ac3bda..c45ae14f4e643 100644
--- a/clang/lib/Driver/ToolChains/FreeBSD.cpp
+++ b/clang/lib/Driver/ToolChains/FreeBSD.cpp
@@ -477,14 +477,13 @@ bool FreeBSD::isPIEDefault(const llvm::opt::ArgList &Args) const {
 }
 
 SanitizerMask
-FreeBSD::getSupportedSanitizers(StringRef BoundArch,
+FreeBSD::getSupportedSanitizers(BoundArch BA,
                                 Action::OffloadKind DeviceOffloadKind) const {
   const bool IsAArch64 = getTriple().getArch() == llvm::Triple::aarch64;
   const bool IsX86 = getTriple().getArch() == llvm::Triple::x86;
   const bool IsX86_64 = getTriple().getArch() == llvm::Triple::x86_64;
   const bool IsMIPS64 = getTriple().isMIPS64();
-  SanitizerMask Res =
-      ToolChain::getSupportedSanitizers(BoundArch, DeviceOffloadKind);
+  SanitizerMask Res = ToolChain::getSupportedSanitizers(BA, DeviceOffloadKind);
   Res |= SanitizerKind::Address;
   Res |= SanitizerKind::PointerCompare;
   Res |= SanitizerKind::PointerSubtract;

diff  --git a/clang/lib/Driver/ToolChains/FreeBSD.h b/clang/lib/Driver/ToolChains/FreeBSD.h
index 79a7dbaafe39e..55400e17b5ea4 100644
--- a/clang/lib/Driver/ToolChains/FreeBSD.h
+++ b/clang/lib/Driver/ToolChains/FreeBSD.h
@@ -87,7 +87,7 @@ class LLVM_LIBRARY_VISIBILITY FreeBSD : public Generic_ELF {
   getDefaultUnwindTableLevel(const llvm::opt::ArgList &Args) const override;
   bool isPIEDefault(const llvm::opt::ArgList &Args) const override;
   SanitizerMask
-  getSupportedSanitizers(StringRef BoundArch,
+  getSupportedSanitizers(BoundArch BA,
                          Action::OffloadKind DeviceOffloadKind) const override;
   unsigned GetDefaultDwarfVersion() const override { return 4; }
   // Until dtrace (via CTF) and LLDB can deal with distributed debug info,

diff  --git a/clang/lib/Driver/ToolChains/Fuchsia.cpp b/clang/lib/Driver/ToolChains/Fuchsia.cpp
index d63d0dbd96416..abde9fa10482d 100644
--- a/clang/lib/Driver/ToolChains/Fuchsia.cpp
+++ b/clang/lib/Driver/ToolChains/Fuchsia.cpp
@@ -330,9 +330,9 @@ Fuchsia::Fuchsia(const Driver &D, const llvm::Triple &Triple,
 }
 
 std::string Fuchsia::ComputeEffectiveClangTriple(const ArgList &Args,
-                                                 llvm::StringRef BoundArch,
+                                                 BoundArch BA,
                                                  types::ID InputType) const {
-  llvm::Triple Triple(ComputeLLVMTriple(Args, BoundArch, InputType));
+  llvm::Triple Triple(ComputeLLVMTriple(Args, BA, InputType));
   return Triple.str();
 }
 
@@ -366,7 +366,7 @@ ToolChain::CXXStdlibType Fuchsia::GetCXXStdlibType(const ArgList &Args) const {
 }
 
 void Fuchsia::addClangTargetOptions(const ArgList &DriverArgs,
-                                    ArgStringList &CC1Args, StringRef BoundArch,
+                                    ArgStringList &CC1Args, BoundArch BA,
                                     Action::OffloadKind) const {
   if (!DriverArgs.hasFlag(options::OPT_fuse_init_array,
                           options::OPT_fno_use_init_array, true))
@@ -473,10 +473,9 @@ void Fuchsia::AddCXXStdlibLibArgs(const ArgList &Args,
 }
 
 SanitizerMask
-Fuchsia::getSupportedSanitizers(StringRef BoundArch,
+Fuchsia::getSupportedSanitizers(BoundArch BA,
                                 Action::OffloadKind DeviceOffloadKind) const {
-  SanitizerMask Res =
-      ToolChain::getSupportedSanitizers(BoundArch, DeviceOffloadKind);
+  SanitizerMask Res = ToolChain::getSupportedSanitizers(BA, DeviceOffloadKind);
   Res |= SanitizerKind::Address;
   Res |= SanitizerKind::HWAddress;
   Res |= SanitizerKind::PointerCompare;

diff  --git a/clang/lib/Driver/ToolChains/Fuchsia.h b/clang/lib/Driver/ToolChains/Fuchsia.h
index daeb936b394f4..85d3b5594b672 100644
--- a/clang/lib/Driver/ToolChains/Fuchsia.h
+++ b/clang/lib/Driver/ToolChains/Fuchsia.h
@@ -81,11 +81,11 @@ class LLVM_LIBRARY_VISIBILITY Fuchsia : public ToolChain {
   }
 
   std::string ComputeEffectiveClangTriple(const llvm::opt::ArgList &Args,
-                                          llvm::StringRef BoundArch,
+                                          BoundArch BA,
                                           types::ID InputType) const override;
 
   SanitizerMask
-  getSupportedSanitizers(StringRef BoundArch,
+  getSupportedSanitizers(BoundArch BA,
                          Action::OffloadKind DeviceOffloadKind) const override;
   SanitizerMask getDefaultSanitizers() const override;
 
@@ -100,8 +100,7 @@ class LLVM_LIBRARY_VISIBILITY Fuchsia : public ToolChain {
 
   void
   addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
-                        llvm::opt::ArgStringList &CC1Args,
-                        llvm::StringRef BoundArch,
+                        llvm::opt::ArgStringList &CC1Args, BoundArch BA,
                         Action::OffloadKind DeviceOffloadKind) const override;
   void
   AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,

diff  --git a/clang/lib/Driver/ToolChains/Gnu.cpp b/clang/lib/Driver/ToolChains/Gnu.cpp
index 0bb51de630c99..b58c10145e7f3 100644
--- a/clang/lib/Driver/ToolChains/Gnu.cpp
+++ b/clang/lib/Driver/ToolChains/Gnu.cpp
@@ -3454,8 +3454,7 @@ Generic_GCC::addLibStdCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
 }
 
 llvm::opt::DerivedArgList *
-Generic_GCC::TranslateArgs(const llvm::opt::DerivedArgList &Args,
-                           StringRef BoundArch,
+Generic_GCC::TranslateArgs(const llvm::opt::DerivedArgList &Args, BoundArch BA,
                            Action::OffloadKind DeviceOffloadKind) const {
   if (DeviceOffloadKind == Action::OFK_None ||
       DeviceOffloadKind == Action::OFK_Host)
@@ -3483,13 +3482,13 @@ Generic_GCC::TranslateArgs(const llvm::opt::DerivedArgList &Args,
   }
 
   // Add the bound architecture to the arguments list if present.
-  if (!BoundArch.empty()) {
+  if (!BA.empty()) {
     options::ID Opt = getTriple().isARM() || getTriple().isPPC() ||
                               getTriple().isAArch64() || getTriple().isAMDGPU()
                           ? options::OPT_mcpu_EQ
                           : options::OPT_march_EQ;
     DAL->eraseArg(Opt);
-    DAL->AddJoinedArg(nullptr, Opts.getOption(Opt), BoundArch);
+    DAL->AddJoinedArg(nullptr, Opts.getOption(Opt), BA.ArchName);
   }
 
   return DAL;
@@ -3498,8 +3497,7 @@ Generic_GCC::TranslateArgs(const llvm::opt::DerivedArgList &Args,
 void Generic_ELF::anchor() {}
 
 void Generic_ELF::addClangTargetOptions(const ArgList &DriverArgs,
-                                        ArgStringList &CC1Args,
-                                        StringRef BoundArch,
+                                        ArgStringList &CC1Args, BoundArch BA,
                                         Action::OffloadKind) const {
   if (!DriverArgs.hasFlag(options::OPT_fuse_init_array,
                           options::OPT_fno_use_init_array, true))

diff  --git a/clang/lib/Driver/ToolChains/Gnu.h b/clang/lib/Driver/ToolChains/Gnu.h
index a4c4de65cd44f..d27ce3076a28f 100644
--- a/clang/lib/Driver/ToolChains/Gnu.h
+++ b/clang/lib/Driver/ToolChains/Gnu.h
@@ -373,7 +373,7 @@ class LLVM_LIBRARY_VISIBILITY Generic_GCC : public ToolChain {
   bool isPICDefaultForced() const override;
   bool IsIntegratedAssemblerDefault() const override;
   llvm::opt::DerivedArgList *
-  TranslateArgs(const llvm::opt::DerivedArgList &Args, StringRef BoundArch,
+  TranslateArgs(const llvm::opt::DerivedArgList &Args, BoundArch BA,
                 Action::OffloadKind DeviceOffloadKind) const override;
 
 protected:
@@ -442,8 +442,7 @@ class LLVM_LIBRARY_VISIBILITY Generic_ELF : public Generic_GCC {
 
   void
   addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
-                        llvm::opt::ArgStringList &CC1Args,
-                        llvm::StringRef BoundArch,
+                        llvm::opt::ArgStringList &CC1Args, BoundArch BA,
                         Action::OffloadKind DeviceOffloadKind) const override;
 
   virtual std::string getDynamicLinker(const llvm::opt::ArgList &Args) const {

diff  --git a/clang/lib/Driver/ToolChains/HIPAMD.cpp b/clang/lib/Driver/ToolChains/HIPAMD.cpp
index 185d733216538..139a7a6e90703 100644
--- a/clang/lib/Driver/ToolChains/HIPAMD.cpp
+++ b/clang/lib/Driver/ToolChains/HIPAMD.cpp
@@ -234,7 +234,7 @@ HIPAMDToolChain::HIPAMDToolChain(const Driver &D, const llvm::Triple &Triple,
 
 void HIPAMDToolChain::addClangTargetOptions(
     const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args,
-    llvm::StringRef BoundArch, Action::OffloadKind DeviceOffloadingKind) const {
+    BoundArch BA, Action::OffloadKind DeviceOffloadingKind) const {
   assert(DeviceOffloadingKind == Action::OFK_HIP &&
          "Only HIP offloading kinds are supported for GPUs.");
 
@@ -279,8 +279,7 @@ void HIPAMDToolChain::addClangTargetOptions(
     return; // No DeviceLibs for SPIR-V.
   }
 
-  for (auto BCFile :
-       getDeviceLibs(DriverArgs, BoundArch, DeviceOffloadingKind)) {
+  for (auto BCFile : getDeviceLibs(DriverArgs, BA, DeviceOffloadingKind)) {
     CC1Args.push_back(BCFile.ShouldInternalize ? "-mlink-builtin-bitcode"
                                                : "-mlink-bitcode-file");
     CC1Args.push_back(DriverArgs.MakeArgStringRef(BCFile.Path));
@@ -289,10 +288,10 @@ void HIPAMDToolChain::addClangTargetOptions(
 
 llvm::opt::DerivedArgList *
 HIPAMDToolChain::TranslateArgs(const llvm::opt::DerivedArgList &Args,
-                               StringRef BoundArch,
+                               BoundArch BA,
                                Action::OffloadKind DeviceOffloadKind) const {
   llvm::opt::DerivedArgList *DAL =
-      ROCMToolChain::TranslateArgs(Args, BoundArch, DeviceOffloadKind);
+      ROCMToolChain::TranslateArgs(Args, BA, DeviceOffloadKind);
 
   return DAL;
 }
@@ -335,9 +334,9 @@ VersionTuple HIPAMDToolChain::computeMSVCVersion(const Driver *D,
 
 llvm::SmallVector<ToolChain::BitCodeLibraryInfo, 12>
 HIPAMDToolChain::getDeviceLibs(const llvm::opt::ArgList &DriverArgs,
-                               llvm::StringRef BoundArch,
+                               BoundArch BA,
                                Action::OffloadKind DeviceOffloadingKind) const {
-  assert(!BoundArch.empty() && "Must have an explicit GPU arch.");
+  assert(BA && "Must have an explicit GPU arch.");
 
   llvm::SmallVector<BitCodeLibraryInfo, 12> BCLibs;
   const llvm::Triple &TT = getEffectiveTriple();
@@ -347,7 +346,7 @@ HIPAMDToolChain::getDeviceLibs(const llvm::opt::ArgList &DriverArgs,
       TT.getEnvironment() == llvm::Triple::LLVM)
     return {};
 
-  StringRef GpuArch = getProcessorFromTargetID(getTriple(), BoundArch);
+  StringRef GpuArch = getProcessorFromTargetID(getTriple(), BA.ArchName);
   if (GpuArch == "amdgcnspirv")
     return {};
 
@@ -385,7 +384,7 @@ HIPAMDToolChain::getDeviceLibs(const llvm::opt::ArgList &DriverArgs,
     }
 
     // Add common device libraries like ocml etc.
-    for (auto N : getCommonDeviceLibNames(DriverArgs, BoundArch, GpuArch,
+    for (auto N : getCommonDeviceLibNames(DriverArgs, BA.ArchName, GpuArch,
                                           DeviceOffloadingKind))
       BCLibs.emplace_back(N);
 

diff  --git a/clang/lib/Driver/ToolChains/HIPAMD.h b/clang/lib/Driver/ToolChains/HIPAMD.h
index 00643b1c2b256..a156f9144f7a8 100644
--- a/clang/lib/Driver/ToolChains/HIPAMD.h
+++ b/clang/lib/Driver/ToolChains/HIPAMD.h
@@ -62,13 +62,12 @@ class LLVM_LIBRARY_VISIBILITY HIPAMDToolChain final : public ROCMToolChain {
   }
 
   llvm::opt::DerivedArgList *
-  TranslateArgs(const llvm::opt::DerivedArgList &Args, StringRef BoundArch,
+  TranslateArgs(const llvm::opt::DerivedArgList &Args, BoundArch BA,
                 Action::OffloadKind DeviceOffloadKind) const override;
 
   void
   addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
-                        llvm::opt::ArgStringList &CC1Args,
-                        llvm::StringRef BoundArch,
+                        llvm::opt::ArgStringList &CC1Args, BoundArch BA,
                         Action::OffloadKind DeviceOffloadKind) const override;
   CXXStdlibType GetCXXStdlibType(const llvm::opt::ArgList &Args) const override;
   void
@@ -82,7 +81,7 @@ class LLVM_LIBRARY_VISIBILITY HIPAMDToolChain final : public ROCMToolChain {
   void AddHIPIncludeArgs(const llvm::opt::ArgList &DriverArgs,
                          llvm::opt::ArgStringList &CC1Args) const override;
   llvm::SmallVector<BitCodeLibraryInfo, 12>
-  getDeviceLibs(const llvm::opt::ArgList &Args, llvm::StringRef BoundArch,
+  getDeviceLibs(const llvm::opt::ArgList &Args, BoundArch BA,
                 Action::OffloadKind DeviceOffloadKind) const override;
 
   VersionTuple

diff  --git a/clang/lib/Driver/ToolChains/HIPSPV.cpp b/clang/lib/Driver/ToolChains/HIPSPV.cpp
index 0d93e55137889..d6900c767d1f7 100644
--- a/clang/lib/Driver/ToolChains/HIPSPV.cpp
+++ b/clang/lib/Driver/ToolChains/HIPSPV.cpp
@@ -152,7 +152,7 @@ HIPSPVToolChain::HIPSPVToolChain(const Driver &D, const llvm::Triple &Triple,
 
 void HIPSPVToolChain::addClangTargetOptions(
     const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args,
-    llvm::StringRef BoundArch, Action::OffloadKind DeviceOffloadingKind) const {
+    BoundArch BA, Action::OffloadKind DeviceOffloadingKind) const {
 
   if (!HostTC) {
     assert(DeviceOffloadingKind == Action::OFK_None &&
@@ -160,8 +160,7 @@ void HIPSPVToolChain::addClangTargetOptions(
     return;
   }
 
-  HostTC->addClangTargetOptions(DriverArgs, CC1Args, BoundArch,
-                                DeviceOffloadingKind);
+  HostTC->addClangTargetOptions(DriverArgs, CC1Args, BA, DeviceOffloadingKind);
 
   assert(DeviceOffloadingKind == Action::OFK_HIP &&
          "Only HIP offloading kinds are supported for GPUs.");
@@ -181,7 +180,7 @@ void HIPSPVToolChain::addClangTargetOptions(
         {"-fvisibility=hidden", "-fapply-global-visibility-to-externs"});
 
   for (const BitCodeLibraryInfo &BCFile :
-       getDeviceLibs(DriverArgs, BoundArch, DeviceOffloadingKind))
+       getDeviceLibs(DriverArgs, BA, DeviceOffloadingKind))
     CC1Args.append(
         {"-mlink-builtin-bitcode", DriverArgs.MakeArgString(BCFile.Path)});
 }
@@ -243,7 +242,7 @@ void HIPSPVToolChain::AddHIPIncludeArgs(const ArgList &DriverArgs,
 
 llvm::SmallVector<ToolChain::BitCodeLibraryInfo, 12>
 HIPSPVToolChain::getDeviceLibs(
-    const llvm::opt::ArgList &DriverArgs, llvm::StringRef BoundArch,
+    const llvm::opt::ArgList &DriverArgs, BoundArch BA,
     const Action::OffloadKind DeviceOffloadingKind) const {
   llvm::SmallVector<ToolChain::BitCodeLibraryInfo, 12> BCLibs;
   if (!DriverArgs.hasFlag(options::OPT_offloadlib, options::OPT_no_offloadlib,
@@ -307,7 +306,7 @@ HIPSPVToolChain::getDeviceLibs(
 }
 
 SanitizerMask HIPSPVToolChain::getSupportedSanitizers(
-    StringRef BoundArch, Action::OffloadKind DeviceOffloadKind) const {
+    BoundArch BA, Action::OffloadKind DeviceOffloadKind) const {
   // The HIPSPVToolChain only supports sanitizers in the sense that it allows
   // sanitizer arguments on the command line if they are supported by the host
   // toolchain. The HIPSPVToolChain will actually ignore any command line
@@ -320,8 +319,8 @@ SanitizerMask HIPSPVToolChain::getSupportedSanitizers(
 
   // FIXME: Be accurate and use DeviceOffloadKind.
   if (HostTC)
-    return HostTC->getSupportedSanitizers(BoundArch, DeviceOffloadKind);
-  return ToolChain::getSupportedSanitizers(BoundArch, DeviceOffloadKind);
+    return HostTC->getSupportedSanitizers(BA, DeviceOffloadKind);
+  return ToolChain::getSupportedSanitizers(BA, DeviceOffloadKind);
 }
 
 VersionTuple HIPSPVToolChain::computeMSVCVersion(const Driver *D,

diff  --git a/clang/lib/Driver/ToolChains/HIPSPV.h b/clang/lib/Driver/ToolChains/HIPSPV.h
index 8e2fd91a4b7ac..337c9c9993876 100644
--- a/clang/lib/Driver/ToolChains/HIPSPV.h
+++ b/clang/lib/Driver/ToolChains/HIPSPV.h
@@ -58,8 +58,7 @@ class LLVM_LIBRARY_VISIBILITY HIPSPVToolChain final : public ToolChain {
 
   void
   addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
-                        llvm::opt::ArgStringList &CC1Args,
-                        llvm::StringRef BoundArch,
+                        llvm::opt::ArgStringList &CC1Args, BoundArch BA,
                         Action::OffloadKind DeviceOffloadKind) const override;
   void addClangWarningOptions(llvm::opt::ArgStringList &CC1Args) const override;
   CXXStdlibType GetCXXStdlibType(const llvm::opt::ArgList &Args) const override;
@@ -74,11 +73,11 @@ class LLVM_LIBRARY_VISIBILITY HIPSPVToolChain final : public ToolChain {
   void AddHIPIncludeArgs(const llvm::opt::ArgList &DriverArgs,
                          llvm::opt::ArgStringList &CC1Args) const override;
   llvm::SmallVector<BitCodeLibraryInfo, 12>
-  getDeviceLibs(const llvm::opt::ArgList &Args, llvm::StringRef BoundArch,
+  getDeviceLibs(const llvm::opt::ArgList &Args, BoundArch BA,
                 const Action::OffloadKind DeviceOffloadKind) const override;
 
   SanitizerMask
-  getSupportedSanitizers(StringRef BoundArch,
+  getSupportedSanitizers(BoundArch BA,
                          Action::OffloadKind DeviceOffloadKind) const override;
 
   VersionTuple

diff  --git a/clang/lib/Driver/ToolChains/HIPUtility.cpp b/clang/lib/Driver/ToolChains/HIPUtility.cpp
index e174132cf0f3f..001f9f3400a06 100644
--- a/clang/lib/Driver/ToolChains/HIPUtility.cpp
+++ b/clang/lib/Driver/ToolChains/HIPUtility.cpp
@@ -308,15 +308,15 @@ void HIP::constructHIPFatbinCommand(Compilation &C, const JobAction &JA,
     const auto *A = II.getAction();
     const llvm::Triple &InputTriple = A->getOffloadingToolChain()->getTriple();
 
-    auto ArchStr = llvm::StringRef(A->getOffloadingArch());
+    BoundArch BA = A->getOffloadingArch();
     BundlerTargetArg += ',' + OffloadKind + '-';
-    if (ArchStr == "amdgcnspirv")
+    if (BA.ArchName == "amdgcnspirv")
       BundlerTargetArg +=
           normalizeForBundler(llvm::Triple("spirv64-amd-amdhsa"), true);
     else
-      BundlerTargetArg += normalizeForBundler(InputTriple, !ArchStr.empty());
-    if (!ArchStr.empty())
-      BundlerTargetArg += '-' + ArchStr.str();
+      BundlerTargetArg += normalizeForBundler(InputTriple, !BA.empty());
+    if (BA)
+      BundlerTargetArg += '-' + BA.ArchName.str();
   }
   BundlerArgs.push_back(Args.MakeArgString(BundlerTargetArg));
 

diff  --git a/clang/lib/Driver/ToolChains/HLSL.cpp b/clang/lib/Driver/ToolChains/HLSL.cpp
index 834b8acc78734..558408cc969f0 100644
--- a/clang/lib/Driver/ToolChains/HLSL.cpp
+++ b/clang/lib/Driver/ToolChains/HLSL.cpp
@@ -431,7 +431,7 @@ clang::driver::toolchains::HLSLToolChain::parseTargetProfile(
 }
 
 DerivedArgList *
-HLSLToolChain::TranslateArgs(const DerivedArgList &Args, StringRef BoundArch,
+HLSLToolChain::TranslateArgs(const DerivedArgList &Args, BoundArch BA,
                              Action::OffloadKind DeviceOffloadKind) const {
   DerivedArgList *DAL = new DerivedArgList(Args.getBaseArgs());
 

diff  --git a/clang/lib/Driver/ToolChains/HLSL.h b/clang/lib/Driver/ToolChains/HLSL.h
index 0806c252c1073..83a94d45ad35a 100644
--- a/clang/lib/Driver/ToolChains/HLSL.h
+++ b/clang/lib/Driver/ToolChains/HLSL.h
@@ -76,7 +76,7 @@ class LLVM_LIBRARY_VISIBILITY HLSLToolChain : public ToolChain {
   bool isPICDefaultForced() const override { return false; }
 
   llvm::opt::DerivedArgList *
-  TranslateArgs(const llvm::opt::DerivedArgList &Args, StringRef BoundArch,
+  TranslateArgs(const llvm::opt::DerivedArgList &Args, BoundArch BA,
                 Action::OffloadKind DeviceOffloadKind) const override;
   static std::optional<std::string> parseTargetProfile(StringRef TargetProfile);
 

diff  --git a/clang/lib/Driver/ToolChains/Haiku.cpp b/clang/lib/Driver/ToolChains/Haiku.cpp
index 083769f2c7954..a155f22b75a79 100644
--- a/clang/lib/Driver/ToolChains/Haiku.cpp
+++ b/clang/lib/Driver/ToolChains/Haiku.cpp
@@ -279,10 +279,9 @@ Tool *Haiku::buildLinker() const { return new tools::haiku::Linker(*this); }
 bool Haiku::HasNativeLLVMSupport() const { return true; }
 
 SanitizerMask
-Haiku::getSupportedSanitizers(StringRef BoundArch,
+Haiku::getSupportedSanitizers(BoundArch BA,
                               Action::OffloadKind DeviceOffloadKind) const {
-  SanitizerMask Res =
-      ToolChain::getSupportedSanitizers(BoundArch, DeviceOffloadKind);
+  SanitizerMask Res = ToolChain::getSupportedSanitizers(BA, DeviceOffloadKind);
 
   Res |= SanitizerKind::Address;
 

diff  --git a/clang/lib/Driver/ToolChains/Haiku.h b/clang/lib/Driver/ToolChains/Haiku.h
index 03dbbb8a50e07..bb68bc515c9b0 100644
--- a/clang/lib/Driver/ToolChains/Haiku.h
+++ b/clang/lib/Driver/ToolChains/Haiku.h
@@ -62,7 +62,7 @@ class LLVM_LIBRARY_VISIBILITY Haiku : public Generic_ELF {
   }
 
   SanitizerMask
-  getSupportedSanitizers(StringRef BoundArch,
+  getSupportedSanitizers(BoundArch BA,
                          Action::OffloadKind DeviceOffloadKind) const override;
   unsigned GetDefaultDwarfVersion() const override { return 4; }
 

diff  --git a/clang/lib/Driver/ToolChains/Hexagon.cpp b/clang/lib/Driver/ToolChains/Hexagon.cpp
index ab207317667c6..b671db98a7798 100644
--- a/clang/lib/Driver/ToolChains/Hexagon.cpp
+++ b/clang/lib/Driver/ToolChains/Hexagon.cpp
@@ -780,7 +780,7 @@ unsigned HexagonToolChain::getOptimizationLevel(
 
 void HexagonToolChain::addClangTargetOptions(const ArgList &DriverArgs,
                                              ArgStringList &CC1Args,
-                                             StringRef BoundArch,
+                                             BoundArch BA,
                                              Action::OffloadKind) const {
 
   bool UseInitArrayDefault = getTriple().isMusl();

diff  --git a/clang/lib/Driver/ToolChains/Hexagon.h b/clang/lib/Driver/ToolChains/Hexagon.h
index 9c4a92ba79e67..1f848a8de061d 100644
--- a/clang/lib/Driver/ToolChains/Hexagon.h
+++ b/clang/lib/Driver/ToolChains/Hexagon.h
@@ -77,8 +77,7 @@ class LLVM_LIBRARY_VISIBILITY HexagonToolChain : public Linux {
 
   void
   addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
-                        llvm::opt::ArgStringList &CC1Args,
-                        llvm::StringRef BoundArch,
+                        llvm::opt::ArgStringList &CC1Args, BoundArch BA,
                         Action::OffloadKind DeviceOffloadKind) const override;
   void
   AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,

diff  --git a/clang/lib/Driver/ToolChains/Linux.cpp b/clang/lib/Driver/ToolChains/Linux.cpp
index 512788d235fec..f3d356305245e 100644
--- a/clang/lib/Driver/ToolChains/Linux.cpp
+++ b/clang/lib/Driver/ToolChains/Linux.cpp
@@ -484,10 +484,10 @@ static void setPAuthABIInTriple(const Driver &D, const ArgList &Args,
 }
 
 std::string Linux::ComputeEffectiveClangTriple(const llvm::opt::ArgList &Args,
-                                               llvm::StringRef BoundArch,
+                                               BoundArch BA,
                                                types::ID InputType) const {
   std::string TripleString =
-      Generic_ELF::ComputeEffectiveClangTriple(Args, BoundArch, InputType);
+      Generic_ELF::ComputeEffectiveClangTriple(Args, BA, InputType);
   if (getTriple().isAArch64()) {
     llvm::Triple Triple(TripleString);
     setPAuthABIInTriple(getDriver(), Args, Triple);
@@ -552,12 +552,12 @@ static void handlePAuthABI(const Driver &D, const ArgList &DriverArgs,
 
 void Linux::addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
                                   llvm::opt::ArgStringList &CC1Args,
-                                  StringRef BoundArch,
+                                  BoundArch BA,
                                   Action::OffloadKind DeviceOffloadKind) const {
   llvm::Triple Triple(ComputeEffectiveClangTriple(DriverArgs));
   if (Triple.isAArch64() && Triple.getEnvironment() == llvm::Triple::PAuthTest)
     handlePAuthABI(getDriver(), DriverArgs, CC1Args);
-  Generic_ELF::addClangTargetOptions(DriverArgs, CC1Args, BoundArch,
+  Generic_ELF::addClangTargetOptions(DriverArgs, CC1Args, BA,
                                      DeviceOffloadKind);
 }
 
@@ -958,7 +958,7 @@ bool Linux::IsMathErrnoDefault() const {
 }
 
 SanitizerMask
-Linux::getSupportedSanitizers(StringRef BoundArch,
+Linux::getSupportedSanitizers(BoundArch BA,
                               Action::OffloadKind DeviceOffloadKind) const {
   const bool IsX86 = getTriple().getArch() == llvm::Triple::x86;
   const bool IsX86_64 = getTriple().getArch() == llvm::Triple::x86_64;
@@ -977,8 +977,7 @@ Linux::getSupportedSanitizers(StringRef BoundArch,
   const bool IsSystemZ = getTriple().getArch() == llvm::Triple::systemz;
   const bool IsHexagon = getTriple().getArch() == llvm::Triple::hexagon;
   const bool IsAndroid = getTriple().isAndroid();
-  SanitizerMask Res =
-      ToolChain::getSupportedSanitizers(BoundArch, DeviceOffloadKind);
+  SanitizerMask Res = ToolChain::getSupportedSanitizers(BA, DeviceOffloadKind);
   Res |= SanitizerKind::Address;
   Res |= SanitizerKind::PointerCompare;
   Res |= SanitizerKind::PointerSubtract;

diff  --git a/clang/lib/Driver/ToolChains/Linux.h b/clang/lib/Driver/ToolChains/Linux.h
index 63f77b4b4d87c..6c81bbc71f7c2 100644
--- a/clang/lib/Driver/ToolChains/Linux.h
+++ b/clang/lib/Driver/ToolChains/Linux.h
@@ -52,18 +52,17 @@ class LLVM_LIBRARY_VISIBILITY Linux : public Generic_ELF {
   bool isPIEDefault(const llvm::opt::ArgList &Args) const override;
   bool IsMathErrnoDefault() const override;
   SanitizerMask
-  getSupportedSanitizers(StringRef BoundArch,
+  getSupportedSanitizers(BoundArch BA,
                          Action::OffloadKind DeviceOffloadKind) const override;
   void addProfileRTLibs(const llvm::opt::ArgList &Args,
                         llvm::opt::ArgStringList &CmdArgs) const override;
   std::string ComputeEffectiveClangTriple(
-      const llvm::opt::ArgList &Args, llvm::StringRef BoundArch = {},
+      const llvm::opt::ArgList &Args, BoundArch BA = {},
       types::ID InputType = types::TY_INVALID) const override;
   std::string computeSysRoot() const override;
   void
   addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
-                        llvm::opt::ArgStringList &CC1Args,
-                        llvm::StringRef BoundArch,
+                        llvm::opt::ArgStringList &CC1Args, BoundArch BA,
                         Action::OffloadKind DeviceOffloadKind) const override;
 
   std::string getDynamicLinker(const llvm::opt::ArgList &Args) const override;

diff  --git a/clang/lib/Driver/ToolChains/MSP430.cpp b/clang/lib/Driver/ToolChains/MSP430.cpp
index 5152512cf28da..d543637c311d2 100644
--- a/clang/lib/Driver/ToolChains/MSP430.cpp
+++ b/clang/lib/Driver/ToolChains/MSP430.cpp
@@ -157,7 +157,7 @@ void MSP430ToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
 
 void MSP430ToolChain::addClangTargetOptions(const ArgList &DriverArgs,
                                             ArgStringList &CC1Args,
-                                            StringRef BoundArch,
+                                            BoundArch BA,
                                             Action::OffloadKind) const {
   CC1Args.push_back("-nostdsysteminc");
 

diff  --git a/clang/lib/Driver/ToolChains/MSP430.h b/clang/lib/Driver/ToolChains/MSP430.h
index 41935e1b5173a..865bcfb7cd3da 100644
--- a/clang/lib/Driver/ToolChains/MSP430.h
+++ b/clang/lib/Driver/ToolChains/MSP430.h
@@ -33,8 +33,7 @@ class LLVM_LIBRARY_VISIBILITY MSP430ToolChain : public Generic_ELF {
   AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
                             llvm::opt::ArgStringList &CC1Args) const override;
   void addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
-                             llvm::opt::ArgStringList &CC1Args,
-                             llvm::StringRef BoundArch,
+                             llvm::opt::ArgStringList &CC1Args, BoundArch BA,
                              Action::OffloadKind) const override;
 
   bool isPICDefault() const override { return false; }

diff  --git a/clang/lib/Driver/ToolChains/MSVC.cpp b/clang/lib/Driver/ToolChains/MSVC.cpp
index 0796bdff96d46..eb81f1b4e142c 100644
--- a/clang/lib/Driver/ToolChains/MSVC.cpp
+++ b/clang/lib/Driver/ToolChains/MSVC.cpp
@@ -915,8 +915,9 @@ VersionTuple MSVCToolChain::computeMSVCVersion(const Driver *D,
   return MSVT;
 }
 
-std::string MSVCToolChain::ComputeEffectiveClangTriple(
-    const ArgList &Args, llvm::StringRef BoundArch, types::ID InputType) const {
+std::string
+MSVCToolChain::ComputeEffectiveClangTriple(const ArgList &Args, BoundArch BA,
+                                           types::ID InputType) const {
   // The MSVC version doesn't care about the architecture, even though it
   // may look at the triple internally.
   VersionTuple MSVT = computeMSVCVersion(/*D=*/nullptr, Args);
@@ -926,7 +927,7 @@ std::string MSVCToolChain::ComputeEffectiveClangTriple(
   // For the rest of the triple, however, a computed architecture name may
   // be needed.
   llvm::Triple Triple(
-      ToolChain::ComputeEffectiveClangTriple(Args, BoundArch, InputType));
+      ToolChain::ComputeEffectiveClangTriple(Args, BA, InputType));
   if (Triple.getEnvironment() == llvm::Triple::MSVC) {
     StringRef ObjFmt = Triple.getEnvironmentName().split('-').second;
     if (ObjFmt.empty())
@@ -939,9 +940,8 @@ std::string MSVCToolChain::ComputeEffectiveClangTriple(
 }
 
 SanitizerMask MSVCToolChain::getSupportedSanitizers(
-    StringRef BoundArch, Action::OffloadKind DeviceOffloadKind) const {
-  SanitizerMask Res =
-      ToolChain::getSupportedSanitizers(BoundArch, DeviceOffloadKind);
+    BoundArch BA, Action::OffloadKind DeviceOffloadKind) const {
+  SanitizerMask Res = ToolChain::getSupportedSanitizers(BA, DeviceOffloadKind);
   Res |= SanitizerKind::Address;
   Res |= SanitizerKind::PointerCompare;
   Res |= SanitizerKind::PointerSubtract;
@@ -1078,8 +1078,7 @@ static void TranslatePermissiveMinus(Arg *A, llvm::opt::DerivedArgList &DAL,
 
 llvm::opt::DerivedArgList *
 MSVCToolChain::TranslateArgs(const llvm::opt::DerivedArgList &Args,
-                             StringRef BoundArch,
-                             Action::OffloadKind OFK) const {
+                             BoundArch BA, Action::OffloadKind OFK) const {
   DerivedArgList *DAL = new DerivedArgList(Args.getBaseArgs());
   const OptTable &Opts = getDriver().getOpts();
 
@@ -1134,7 +1133,7 @@ MSVCToolChain::TranslateArgs(const llvm::opt::DerivedArgList &Args,
 }
 
 void MSVCToolChain::addClangTargetOptions(
-    const ArgList &DriverArgs, ArgStringList &CC1Args, StringRef BoundArch,
+    const ArgList &DriverArgs, ArgStringList &CC1Args, BoundArch BA,
     Action::OffloadKind DeviceOffloadKind) const {
   // MSVC STL kindly allows removing all usages of typeid by defining
   // _HAS_STATIC_RTTI to 0. Do so, when compiling with -fno-rtti

diff  --git a/clang/lib/Driver/ToolChains/MSVC.h b/clang/lib/Driver/ToolChains/MSVC.h
index 9f09ff3bbb48d..0ec73fb59b921 100644
--- a/clang/lib/Driver/ToolChains/MSVC.h
+++ b/clang/lib/Driver/ToolChains/MSVC.h
@@ -49,7 +49,7 @@ class LLVM_LIBRARY_VISIBILITY MSVCToolChain : public ToolChain {
                 const llvm::opt::ArgList &Args);
 
   llvm::opt::DerivedArgList *
-  TranslateArgs(const llvm::opt::DerivedArgList &Args, StringRef BoundArch,
+  TranslateArgs(const llvm::opt::DerivedArgList &Args, BoundArch BA,
                 Action::OffloadKind DeviceOffloadKind) const override;
 
   UnwindTableLevel
@@ -114,10 +114,10 @@ class LLVM_LIBRARY_VISIBILITY MSVCToolChain : public ToolChain {
                      const llvm::opt::ArgList &Args) const override;
 
   std::string ComputeEffectiveClangTriple(const llvm::opt::ArgList &Args,
-                                          llvm::StringRef BoundArch,
+                                          BoundArch BA,
                                           types::ID InputType) const override;
   SanitizerMask
-  getSupportedSanitizers(StringRef BoundArch,
+  getSupportedSanitizers(BoundArch BA,
                          Action::OffloadKind DeviceOffloadKind) const override;
 
   void printVerboseInfo(raw_ostream &OS) const override;
@@ -126,8 +126,7 @@ class LLVM_LIBRARY_VISIBILITY MSVCToolChain : public ToolChain {
 
   void
   addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
-                        llvm::opt::ArgStringList &CC1Args,
-                        llvm::StringRef BoundArch,
+                        llvm::opt::ArgStringList &CC1Args, BoundArch BA,
                         Action::OffloadKind DeviceOffloadKind) const override;
 
 protected:

diff  --git a/clang/lib/Driver/ToolChains/Managarm.cpp b/clang/lib/Driver/ToolChains/Managarm.cpp
index 2779136fe9ee3..4566e7258e929 100644
--- a/clang/lib/Driver/ToolChains/Managarm.cpp
+++ b/clang/lib/Driver/ToolChains/Managarm.cpp
@@ -198,11 +198,10 @@ void Managarm::addLibStdCxxIncludePaths(
 }
 
 SanitizerMask
-Managarm::getSupportedSanitizers(StringRef BoundArch,
+Managarm::getSupportedSanitizers(BoundArch BA,
                                  Action::OffloadKind DeviceOffloadKind) const {
   const bool IsX86_64 = getTriple().getArch() == llvm::Triple::x86_64;
-  SanitizerMask Res =
-      ToolChain::getSupportedSanitizers(BoundArch, DeviceOffloadKind);
+  SanitizerMask Res = ToolChain::getSupportedSanitizers(BA, DeviceOffloadKind);
   Res |= SanitizerKind::PointerCompare;
   Res |= SanitizerKind::PointerSubtract;
   Res |= SanitizerKind::KernelAddress;

diff  --git a/clang/lib/Driver/ToolChains/Managarm.h b/clang/lib/Driver/ToolChains/Managarm.h
index 52d0e296cddd3..eef026cc191aa 100644
--- a/clang/lib/Driver/ToolChains/Managarm.h
+++ b/clang/lib/Driver/ToolChains/Managarm.h
@@ -41,7 +41,7 @@ class LLVM_LIBRARY_VISIBILITY Managarm : public Generic_ELF {
   }
 
   SanitizerMask
-  getSupportedSanitizers(StringRef BoundArch,
+  getSupportedSanitizers(BoundArch BA,
                          Action::OffloadKind DeviceOffloadKind) const override;
   std::string computeSysRoot() const override;
 

diff  --git a/clang/lib/Driver/ToolChains/MinGW.cpp b/clang/lib/Driver/ToolChains/MinGW.cpp
index 11dca2fa4231d..4237a6906be3b 100644
--- a/clang/lib/Driver/ToolChains/MinGW.cpp
+++ b/clang/lib/Driver/ToolChains/MinGW.cpp
@@ -627,9 +627,8 @@ toolchains::MinGW::GetExceptionModel(const ArgList &Args) const {
 }
 
 SanitizerMask toolchains::MinGW::getSupportedSanitizers(
-    StringRef BoundArch, Action::OffloadKind DeviceOffloadKind) const {
-  SanitizerMask Res =
-      ToolChain::getSupportedSanitizers(BoundArch, DeviceOffloadKind);
+    BoundArch BA, Action::OffloadKind DeviceOffloadKind) const {
+  SanitizerMask Res = ToolChain::getSupportedSanitizers(BA, DeviceOffloadKind);
   Res |= SanitizerKind::Address;
   Res |= SanitizerKind::PointerCompare;
   Res |= SanitizerKind::PointerSubtract;
@@ -746,7 +745,7 @@ void toolchains::MinGW::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
 
 void toolchains::MinGW::addClangTargetOptions(
     const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args,
-    StringRef BoundArch, Action::OffloadKind DeviceOffloadKind) const {
+    BoundArch BA, Action::OffloadKind DeviceOffloadKind) const {
   if (Arg *A = DriverArgs.getLastArg(options::OPT_mguard_EQ)) {
     StringRef GuardArgs = A->getValue();
     if (GuardArgs == "none") {

diff  --git a/clang/lib/Driver/ToolChains/MinGW.h b/clang/lib/Driver/ToolChains/MinGW.h
index eaec447a16ac6..36ab7b6c6e295 100644
--- a/clang/lib/Driver/ToolChains/MinGW.h
+++ b/clang/lib/Driver/ToolChains/MinGW.h
@@ -74,7 +74,7 @@ class LLVM_LIBRARY_VISIBILITY MinGW : public ToolChain {
   bool isPICDefaultForced() const override;
 
   SanitizerMask
-  getSupportedSanitizers(StringRef BoundArch,
+  getSupportedSanitizers(BoundArch BA,
                          Action::OffloadKind DeviceOffloadKind) const override;
 
   llvm::ExceptionHandling GetExceptionModel(
@@ -85,8 +85,7 @@ class LLVM_LIBRARY_VISIBILITY MinGW : public ToolChain {
                             llvm::opt::ArgStringList &CC1Args) const override;
   void
   addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
-                        llvm::opt::ArgStringList &CC1Args,
-                        llvm::StringRef BoundArch,
+                        llvm::opt::ArgStringList &CC1Args, BoundArch BA,
                         Action::OffloadKind DeviceOffloadKind) const override;
   void AddClangCXXStdlibIncludeArgs(
       const llvm::opt::ArgList &DriverArgs,

diff  --git a/clang/lib/Driver/ToolChains/NetBSD.cpp b/clang/lib/Driver/ToolChains/NetBSD.cpp
index ade8a07cb0b1a..31a5723c17c2f 100644
--- a/clang/lib/Driver/ToolChains/NetBSD.cpp
+++ b/clang/lib/Driver/ToolChains/NetBSD.cpp
@@ -532,12 +532,11 @@ llvm::ExceptionHandling NetBSD::GetExceptionModel(const ArgList &Args) const {
 }
 
 SanitizerMask
-NetBSD::getSupportedSanitizers(StringRef BoundArch,
+NetBSD::getSupportedSanitizers(BoundArch BA,
                                Action::OffloadKind DeviceOffloadKind) const {
   const bool IsX86 = getTriple().getArch() == llvm::Triple::x86;
   const bool IsX86_64 = getTriple().getArch() == llvm::Triple::x86_64;
-  SanitizerMask Res =
-      ToolChain::getSupportedSanitizers(BoundArch, DeviceOffloadKind);
+  SanitizerMask Res = ToolChain::getSupportedSanitizers(BA, DeviceOffloadKind);
   if (IsX86 || IsX86_64) {
     Res |= SanitizerKind::Address;
     Res |= SanitizerKind::PointerCompare;
@@ -562,7 +561,7 @@ NetBSD::getSupportedSanitizers(StringRef BoundArch,
 }
 
 void NetBSD::addClangTargetOptions(const ArgList &DriverArgs,
-                                   ArgStringList &CC1Args, StringRef BoundArch,
+                                   ArgStringList &CC1Args, BoundArch BA,
                                    Action::OffloadKind) const {
   const SanitizerArgs &SanArgs = getSanitizerArgs(DriverArgs);
   if (SanArgs.hasAnySanitizer())

diff  --git a/clang/lib/Driver/ToolChains/NetBSD.h b/clang/lib/Driver/ToolChains/NetBSD.h
index d6072ab37dc11..c6a40ff34036c 100644
--- a/clang/lib/Driver/ToolChains/NetBSD.h
+++ b/clang/lib/Driver/ToolChains/NetBSD.h
@@ -77,13 +77,12 @@ class LLVM_LIBRARY_VISIBILITY NetBSD : public Generic_ELF {
       const llvm::opt::ArgList &Args) const override;
 
   SanitizerMask
-  getSupportedSanitizers(StringRef BoundArch,
+  getSupportedSanitizers(BoundArch BA,
                          Action::OffloadKind DeviceOffloadKind) const override;
 
   void
   addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
-                        llvm::opt::ArgStringList &CC1Args,
-                        llvm::StringRef BoundArch,
+                        llvm::opt::ArgStringList &CC1Args, BoundArch BA,
                         Action::OffloadKind DeviceOffloadKind) const override;
 
 protected:

diff  --git a/clang/lib/Driver/ToolChains/OHOS.cpp b/clang/lib/Driver/ToolChains/OHOS.cpp
index 8ea8980d3746f..dda00c9250a5f 100644
--- a/clang/lib/Driver/ToolChains/OHOS.cpp
+++ b/clang/lib/Driver/ToolChains/OHOS.cpp
@@ -380,10 +380,9 @@ void OHOS::addExtraOpts(llvm::opt::ArgStringList &CmdArgs) const {
 }
 
 SanitizerMask
-OHOS::getSupportedSanitizers(StringRef BoundArch,
+OHOS::getSupportedSanitizers(BoundArch BA,
                              Action::OffloadKind DeviceOffloadKind) const {
-  SanitizerMask Res =
-      ToolChain::getSupportedSanitizers(BoundArch, DeviceOffloadKind);
+  SanitizerMask Res = ToolChain::getSupportedSanitizers(BA, DeviceOffloadKind);
   Res |= SanitizerKind::Address;
   Res |= SanitizerKind::PointerCompare;
   Res |= SanitizerKind::PointerSubtract;

diff  --git a/clang/lib/Driver/ToolChains/OHOS.h b/clang/lib/Driver/ToolChains/OHOS.h
index 493ec156dbd26..bc4bd96e31ed5 100644
--- a/clang/lib/Driver/ToolChains/OHOS.h
+++ b/clang/lib/Driver/ToolChains/OHOS.h
@@ -80,7 +80,7 @@ class LLVM_LIBRARY_VISIBILITY OHOS : public Generic_ELF {
                                  StringRef SysRoot) const override;
   void addExtraOpts(llvm::opt::ArgStringList &CmdArgs) const override;
   SanitizerMask
-  getSupportedSanitizers(StringRef BoundArch,
+  getSupportedSanitizers(BoundArch BA,
                          Action::OffloadKind DeviceOffloadKind) const override;
   void addProfileRTLibs(const llvm::opt::ArgList &Args,
                              llvm::opt::ArgStringList &CmdArgs) const override;

diff  --git a/clang/lib/Driver/ToolChains/OpenBSD.cpp b/clang/lib/Driver/ToolChains/OpenBSD.cpp
index a8ac97ac5f1b9..14680dc4b0e5b 100644
--- a/clang/lib/Driver/ToolChains/OpenBSD.cpp
+++ b/clang/lib/Driver/ToolChains/OpenBSD.cpp
@@ -287,12 +287,11 @@ void openbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
 }
 
 SanitizerMask
-OpenBSD::getSupportedSanitizers(StringRef BoundArch,
+OpenBSD::getSupportedSanitizers(BoundArch BA,
                                 Action::OffloadKind DeviceOffloadKind) const {
   const bool IsX86 = getTriple().getArch() == llvm::Triple::x86;
   const bool IsX86_64 = getTriple().getArch() == llvm::Triple::x86_64;
-  SanitizerMask Res =
-      ToolChain::getSupportedSanitizers(BoundArch, DeviceOffloadKind);
+  SanitizerMask Res = ToolChain::getSupportedSanitizers(BA, DeviceOffloadKind);
   if (IsX86 || IsX86_64) {
     Res |= SanitizerKind::Vptr;
     Res |= SanitizerKind::Fuzzer;

diff  --git a/clang/lib/Driver/ToolChains/OpenBSD.h b/clang/lib/Driver/ToolChains/OpenBSD.h
index 3008932b7d757..a92c4d321bac6 100644
--- a/clang/lib/Driver/ToolChains/OpenBSD.h
+++ b/clang/lib/Driver/ToolChains/OpenBSD.h
@@ -98,7 +98,7 @@ class LLVM_LIBRARY_VISIBILITY OpenBSD : public Generic_ELF {
   unsigned GetDefaultDwarfVersion() const override { return 2; }
 
   SanitizerMask
-  getSupportedSanitizers(StringRef BoundArch,
+  getSupportedSanitizers(BoundArch BA,
                          Action::OffloadKind DeviceOffloadKind) const override;
 
 protected:

diff  --git a/clang/lib/Driver/ToolChains/PS4CPU.cpp b/clang/lib/Driver/ToolChains/PS4CPU.cpp
index f9f66d53a0e81..8c8d0bf033585 100644
--- a/clang/lib/Driver/ToolChains/PS4CPU.cpp
+++ b/clang/lib/Driver/ToolChains/PS4CPU.cpp
@@ -565,9 +565,8 @@ Tool *toolchains::PS5CPU::buildLinker() const {
 }
 
 SanitizerMask toolchains::PS4PS5Base::getSupportedSanitizers(
-    StringRef BoundArch, Action::OffloadKind DeviceOffloadKind) const {
-  SanitizerMask Res =
-      ToolChain::getSupportedSanitizers(BoundArch, DeviceOffloadKind);
+    BoundArch BA, Action::OffloadKind DeviceOffloadKind) const {
+  SanitizerMask Res = ToolChain::getSupportedSanitizers(BA, DeviceOffloadKind);
   Res |= SanitizerKind::Address;
   Res |= SanitizerKind::PointerCompare;
   Res |= SanitizerKind::PointerSubtract;
@@ -576,15 +575,14 @@ SanitizerMask toolchains::PS4PS5Base::getSupportedSanitizers(
 }
 
 SanitizerMask toolchains::PS5CPU::getSupportedSanitizers(
-    StringRef BoundArch, Action::OffloadKind DeviceOffloadKind) const {
-  SanitizerMask Res =
-      PS4PS5Base::getSupportedSanitizers(BoundArch, DeviceOffloadKind);
+    BoundArch BA, Action::OffloadKind DeviceOffloadKind) const {
+  SanitizerMask Res = PS4PS5Base::getSupportedSanitizers(BA, DeviceOffloadKind);
   Res |= SanitizerKind::Thread;
   return Res;
 }
 
 void toolchains::PS4PS5Base::addClangTargetOptions(
-    const ArgList &DriverArgs, ArgStringList &CC1Args, StringRef BoundArch,
+    const ArgList &DriverArgs, ArgStringList &CC1Args, BoundArch BA,
     Action::OffloadKind DeviceOffloadingKind) const {
   // PS4/PS5 do not use init arrays.
   if (DriverArgs.hasArg(options::OPT_fuse_init_array)) {

diff  --git a/clang/lib/Driver/ToolChains/PS4CPU.h b/clang/lib/Driver/ToolChains/PS4CPU.h
index 002e4d313be8b..32d6a9d48e939 100644
--- a/clang/lib/Driver/ToolChains/PS4CPU.h
+++ b/clang/lib/Driver/ToolChains/PS4CPU.h
@@ -107,13 +107,12 @@ class LLVM_LIBRARY_VISIBILITY PS4PS5Base : public Generic_ELF {
   }
 
   SanitizerMask
-  getSupportedSanitizers(StringRef BoundArch,
+  getSupportedSanitizers(BoundArch BA,
                          Action::OffloadKind DeviceOffloadKind) const override;
 
   void addClangTargetOptions(
       const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args,
-      llvm::StringRef BoundArch,
-      Action::OffloadKind DeviceOffloadingKind) const override;
+      BoundArch BA, Action::OffloadKind DeviceOffloadingKind) const override;
 
   void addClangWarningOptions(llvm::opt::ArgStringList &CC1Args) const override;
 
@@ -178,7 +177,7 @@ class LLVM_LIBRARY_VISIBILITY PS5CPU : public PS4PS5Base {
   unsigned GetDefaultDwarfVersion() const override { return 5; }
 
   SanitizerMask
-  getSupportedSanitizers(StringRef BoundArch,
+  getSupportedSanitizers(BoundArch BA,
                          Action::OffloadKind DeviceOffloadKind) const override;
 
   const char *getLinkerBaseName() const override { return "lld"; }

diff  --git a/clang/lib/Driver/ToolChains/SPIRVOpenMP.cpp b/clang/lib/Driver/ToolChains/SPIRVOpenMP.cpp
index 161f8939929aa..23a5789cb3d2d 100644
--- a/clang/lib/Driver/ToolChains/SPIRVOpenMP.cpp
+++ b/clang/lib/Driver/ToolChains/SPIRVOpenMP.cpp
@@ -22,7 +22,7 @@ SPIRVOpenMPToolChain::SPIRVOpenMPToolChain(const Driver &D,
 
 void SPIRVOpenMPToolChain::addClangTargetOptions(
     const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args,
-    llvm::StringRef BoundArch, Action::OffloadKind DeviceOffloadingKind) const {
+    BoundArch BA, Action::OffloadKind DeviceOffloadingKind) const {
 
   if (DeviceOffloadingKind != Action::OFK_OpenMP)
     return;

diff  --git a/clang/lib/Driver/ToolChains/SPIRVOpenMP.h b/clang/lib/Driver/ToolChains/SPIRVOpenMP.h
index 75f9f5626eea4..5177c6b662564 100644
--- a/clang/lib/Driver/ToolChains/SPIRVOpenMP.h
+++ b/clang/lib/Driver/ToolChains/SPIRVOpenMP.h
@@ -21,8 +21,7 @@ class LLVM_LIBRARY_VISIBILITY SPIRVOpenMPToolChain : public SPIRVToolChain {
 
   void addClangTargetOptions(
       const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args,
-      llvm::StringRef BoundArch,
-      Action::OffloadKind DeviceOffloadingKind) const override;
+      BoundArch BA, Action::OffloadKind DeviceOffloadingKind) const override;
 
   const ToolChain &HostTC;
 };

diff  --git a/clang/lib/Driver/ToolChains/SYCL.cpp b/clang/lib/Driver/ToolChains/SYCL.cpp
index 7ee7eaf58a740..d41b5c06da53f 100644
--- a/clang/lib/Driver/ToolChains/SYCL.cpp
+++ b/clang/lib/Driver/ToolChains/SYCL.cpp
@@ -128,17 +128,15 @@ SYCLToolChain::SYCLToolChain(const Driver &D, const llvm::Triple &Triple,
 
 void SYCLToolChain::addClangTargetOptions(
     const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args,
-    llvm::StringRef BoundArch, Action::OffloadKind DeviceOffloadingKind) const {
-  HostTC.addClangTargetOptions(DriverArgs, CC1Args, BoundArch,
-                               DeviceOffloadingKind);
+    BoundArch BA, Action::OffloadKind DeviceOffloadingKind) const {
+  HostTC.addClangTargetOptions(DriverArgs, CC1Args, BA, DeviceOffloadingKind);
 }
 
 llvm::opt::DerivedArgList *
 SYCLToolChain::TranslateArgs(const llvm::opt::DerivedArgList &Args,
-                             StringRef BoundArch,
+                             BoundArch BA,
                              Action::OffloadKind DeviceOffloadKind) const {
-  DerivedArgList *DAL =
-      HostTC.TranslateArgs(Args, BoundArch, DeviceOffloadKind);
+  DerivedArgList *DAL = HostTC.TranslateArgs(Args, BA, DeviceOffloadKind);
 
   bool IsNewDAL = false;
   if (!DAL) {
@@ -174,10 +172,10 @@ SYCLToolChain::TranslateArgs(const llvm::opt::DerivedArgList &Args,
   }
 
   const OptTable &Opts = getDriver().getOpts();
-  if (!BoundArch.empty()) {
+  if (BA) {
     DAL->eraseArg(options::OPT_march_EQ);
     DAL->AddJoinedArg(nullptr, Opts.getOption(options::OPT_march_EQ),
-                      BoundArch);
+                      BA.ArchName);
   }
   return DAL;
 }

diff  --git a/clang/lib/Driver/ToolChains/SYCL.h b/clang/lib/Driver/ToolChains/SYCL.h
index ae512723c0cea..d404ce2f93923 100644
--- a/clang/lib/Driver/ToolChains/SYCL.h
+++ b/clang/lib/Driver/ToolChains/SYCL.h
@@ -27,12 +27,11 @@ class LLVM_LIBRARY_VISIBILITY SYCLToolChain : public ToolChain {
   }
 
   llvm::opt::DerivedArgList *
-  TranslateArgs(const llvm::opt::DerivedArgList &Args, StringRef BoundArch,
+  TranslateArgs(const llvm::opt::DerivedArgList &Args, BoundArch BA,
                 Action::OffloadKind DeviceOffloadKind) const override;
   void
   addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
-                        llvm::opt::ArgStringList &CC1Args,
-                        llvm::StringRef BoundArch,
+                        llvm::opt::ArgStringList &CC1Args, BoundArch BA,
                         Action::OffloadKind DeviceOffloadKind) const override;
 
   bool useIntegratedAs() const override { return true; }

diff  --git a/clang/lib/Driver/ToolChains/Serenity.cpp b/clang/lib/Driver/ToolChains/Serenity.cpp
index 60a966fac39e9..d43dffec8d31f 100644
--- a/clang/lib/Driver/ToolChains/Serenity.cpp
+++ b/clang/lib/Driver/ToolChains/Serenity.cpp
@@ -167,9 +167,9 @@ void tools::serenity::Linker::ConstructJob(Compilation &C, const JobAction &JA,
 }
 
 SanitizerMask
-Serenity::getSupportedSanitizers(StringRef BoundArch,
+Serenity::getSupportedSanitizers(BoundArch BA,
                                  Action::OffloadKind DeviceOffloadKind) const {
-  return ToolChain::getSupportedSanitizers(BoundArch, DeviceOffloadKind) |
+  return ToolChain::getSupportedSanitizers(BA, DeviceOffloadKind) |
          SanitizerKind::KernelAddress;
 }
 

diff  --git a/clang/lib/Driver/ToolChains/Serenity.h b/clang/lib/Driver/ToolChains/Serenity.h
index 3ecd6c6b4f4a5..2cc25c0f9430d 100644
--- a/clang/lib/Driver/ToolChains/Serenity.h
+++ b/clang/lib/Driver/ToolChains/Serenity.h
@@ -65,7 +65,7 @@ class LLVM_LIBRARY_VISIBILITY Serenity final : public Generic_ELF {
   bool isPIEDefault(const llvm::opt::ArgList &) const override { return true; }
 
   SanitizerMask
-  getSupportedSanitizers(StringRef BoundArch,
+  getSupportedSanitizers(BoundArch BA,
                          Action::OffloadKind DeviceOffloadKind) const override;
 
   bool IsMathErrnoDefault() const override { return false; }

diff  --git a/clang/lib/Driver/ToolChains/Solaris.cpp b/clang/lib/Driver/ToolChains/Solaris.cpp
index 9af721ecd053e..e5f1cbb033c3b 100644
--- a/clang/lib/Driver/ToolChains/Solaris.cpp
+++ b/clang/lib/Driver/ToolChains/Solaris.cpp
@@ -329,12 +329,11 @@ Solaris::Solaris(const Driver &D, const llvm::Triple &Triple,
 }
 
 SanitizerMask
-Solaris::getSupportedSanitizers(StringRef BoundArch,
+Solaris::getSupportedSanitizers(BoundArch BA,
                                 Action::OffloadKind DeviceOffloadKind) const {
   const bool IsSparc = getTriple().getArch() == llvm::Triple::sparc;
   const bool IsX86 = getTriple().getArch() == llvm::Triple::x86;
-  SanitizerMask Res =
-      ToolChain::getSupportedSanitizers(BoundArch, DeviceOffloadKind);
+  SanitizerMask Res = ToolChain::getSupportedSanitizers(BA, DeviceOffloadKind);
   // FIXME: Omit SparcV9 and X86_64 until 64-bit support is figured out.
   if (IsSparc || IsX86) {
     Res |= SanitizerKind::Address;

diff  --git a/clang/lib/Driver/ToolChains/Solaris.h b/clang/lib/Driver/ToolChains/Solaris.h
index c31463ee8e13a..54bdd2e88b049 100644
--- a/clang/lib/Driver/ToolChains/Solaris.h
+++ b/clang/lib/Driver/ToolChains/Solaris.h
@@ -65,7 +65,7 @@ class LLVM_LIBRARY_VISIBILITY Solaris : public Generic_ELF {
                            llvm::opt::ArgStringList &CC1Args) const override;
 
   SanitizerMask
-  getSupportedSanitizers(StringRef BoundArch,
+  getSupportedSanitizers(BoundArch BA,
                          Action::OffloadKind DeviceOffloadKind) const override;
 
   const char *getDefaultLinker() const override;

diff  --git a/clang/lib/Driver/ToolChains/VEToolchain.cpp b/clang/lib/Driver/ToolChains/VEToolchain.cpp
index 6093d378f0ec2..b676acf3728f6 100644
--- a/clang/lib/Driver/ToolChains/VEToolchain.cpp
+++ b/clang/lib/Driver/ToolChains/VEToolchain.cpp
@@ -106,8 +106,7 @@ void VEToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
 }
 
 void VEToolChain::addClangTargetOptions(const ArgList &DriverArgs,
-                                        ArgStringList &CC1Args,
-                                        StringRef BoundArch,
+                                        ArgStringList &CC1Args, BoundArch BA,
                                         Action::OffloadKind) const {
   CC1Args.push_back("-nostdsysteminc");
   bool UseInitArrayDefault = true;

diff  --git a/clang/lib/Driver/ToolChains/VEToolchain.h b/clang/lib/Driver/ToolChains/VEToolchain.h
index 2a49f8ed37f01..71cf071ebecec 100644
--- a/clang/lib/Driver/ToolChains/VEToolchain.h
+++ b/clang/lib/Driver/ToolChains/VEToolchain.h
@@ -36,8 +36,7 @@ class LLVM_LIBRARY_VISIBILITY VEToolChain : public Linux {
                             llvm::opt::ArgStringList &CC1Args) const override;
   void
   addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
-                        llvm::opt::ArgStringList &CC1Args,
-                        llvm::StringRef BoundArch,
+                        llvm::opt::ArgStringList &CC1Args, BoundArch BA,
                         Action::OffloadKind DeviceOffloadKind) const override;
   void AddClangCXXStdlibIncludeArgs(
       const llvm::opt::ArgList &DriverArgs,

diff  --git a/clang/lib/Driver/ToolChains/WebAssembly.cpp b/clang/lib/Driver/ToolChains/WebAssembly.cpp
index 5bc43b37d06bf..8ca09b11836e5 100644
--- a/clang/lib/Driver/ToolChains/WebAssembly.cpp
+++ b/clang/lib/Driver/ToolChains/WebAssembly.cpp
@@ -325,8 +325,7 @@ bool WebAssembly::SupportsProfiling() const { return false; }
 bool WebAssembly::HasNativeLLVMSupport() const { return true; }
 
 void WebAssembly::addClangTargetOptions(const ArgList &DriverArgs,
-                                        ArgStringList &CC1Args,
-                                        StringRef BoundArch,
+                                        ArgStringList &CC1Args, BoundArch BA,
                                         Action::OffloadKind) const {
   if (!DriverArgs.hasFlag(options::OPT_fuse_init_array,
                           options::OPT_fno_use_init_array, true))
@@ -572,9 +571,8 @@ void WebAssembly::AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args,
 }
 
 SanitizerMask WebAssembly::getSupportedSanitizers(
-    StringRef BoundArch, Action::OffloadKind DeviceOffloadKind) const {
-  SanitizerMask Res =
-      ToolChain::getSupportedSanitizers(BoundArch, DeviceOffloadKind);
+    BoundArch BA, Action::OffloadKind DeviceOffloadKind) const {
+  SanitizerMask Res = ToolChain::getSupportedSanitizers(BA, DeviceOffloadKind);
   if (getTriple().isOSEmscripten()) {
     Res |= SanitizerKind::Vptr | SanitizerKind::Leak;
   }

diff  --git a/clang/lib/Driver/ToolChains/WebAssembly.h b/clang/lib/Driver/ToolChains/WebAssembly.h
index 756e2a03ff915..f91987ba3883a 100644
--- a/clang/lib/Driver/ToolChains/WebAssembly.h
+++ b/clang/lib/Driver/ToolChains/WebAssembly.h
@@ -53,8 +53,7 @@ class LLVM_LIBRARY_VISIBILITY WebAssembly final : public ToolChain {
   unsigned GetDefaultDwarfVersion() const override { return 4; }
   void
   addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
-                        llvm::opt::ArgStringList &CC1Args,
-                        llvm::StringRef BoundArch,
+                        llvm::opt::ArgStringList &CC1Args, BoundArch BA,
                         Action::OffloadKind DeviceOffloadKind) const override;
   RuntimeLibType GetDefaultRuntimeLibType() const override;
   CXXStdlibType GetCXXStdlibType(const llvm::opt::ArgList &Args) const override;
@@ -67,7 +66,7 @@ class LLVM_LIBRARY_VISIBILITY WebAssembly final : public ToolChain {
   void AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args,
                            llvm::opt::ArgStringList &CmdArgs) const override;
   SanitizerMask
-  getSupportedSanitizers(StringRef BoundArch,
+  getSupportedSanitizers(BoundArch BA,
                          Action::OffloadKind DeviceOffloadKind) const override;
 
   const char *getDefaultLinker() const override;

diff  --git a/clang/lib/Driver/ToolChains/XCore.cpp b/clang/lib/Driver/ToolChains/XCore.cpp
index 37452eff55baa..a381047e5baf1 100644
--- a/clang/lib/Driver/ToolChains/XCore.cpp
+++ b/clang/lib/Driver/ToolChains/XCore.cpp
@@ -126,8 +126,7 @@ void XCoreToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
 }
 
 void XCoreToolChain::addClangTargetOptions(const ArgList &DriverArgs,
-                                           ArgStringList &CC1Args,
-                                           StringRef BoundArch,
+                                           ArgStringList &CC1Args, BoundArch BA,
                                            Action::OffloadKind) const {
   CC1Args.push_back("-nostdsysteminc");
   // Set `-fno-use-cxa-atexit` to default.

diff  --git a/clang/lib/Driver/ToolChains/XCore.h b/clang/lib/Driver/ToolChains/XCore.h
index 1f3272530ddad..cc7638d6566d4 100644
--- a/clang/lib/Driver/ToolChains/XCore.h
+++ b/clang/lib/Driver/ToolChains/XCore.h
@@ -68,8 +68,7 @@ class LLVM_LIBRARY_VISIBILITY XCoreToolChain : public ToolChain {
                             llvm::opt::ArgStringList &CC1Args) const override;
   void
   addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
-                        llvm::opt::ArgStringList &CC1Args,
-                        llvm::StringRef BoundArch,
+                        llvm::opt::ArgStringList &CC1Args, BoundArch BA,
                         Action::OffloadKind DeviceOffloadKind) const override;
   void AddClangCXXStdlibIncludeArgs(
       const llvm::opt::ArgList &DriverArgs,

diff  --git a/clang/lib/Driver/ToolChains/ZOS.cpp b/clang/lib/Driver/ToolChains/ZOS.cpp
index fc7b7a6ed186c..c9e61cf5f43f0 100644
--- a/clang/lib/Driver/ToolChains/ZOS.cpp
+++ b/clang/lib/Driver/ToolChains/ZOS.cpp
@@ -28,7 +28,7 @@ ZOS::ZOS(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
 ZOS::~ZOS() {}
 
 void ZOS::addClangTargetOptions(const ArgList &DriverArgs,
-                                ArgStringList &CC1Args, StringRef BoundArch,
+                                ArgStringList &CC1Args, BoundArch BA,
                                 Action::OffloadKind DeviceOffloadKind) const {
   // Pass "-faligned-alloc-unavailable" only when the user hasn't manually
   // enabled or disabled aligned allocations.

diff  --git a/clang/lib/Driver/ToolChains/ZOS.h b/clang/lib/Driver/ToolChains/ZOS.h
index 5d0b2fef79ec8..c406d20e33f25 100644
--- a/clang/lib/Driver/ToolChains/ZOS.h
+++ b/clang/lib/Driver/ToolChains/ZOS.h
@@ -82,8 +82,7 @@ class LLVM_LIBRARY_VISIBILITY ZOS : public ToolChain {
 
   void addClangTargetOptions(
       const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args,
-      llvm::StringRef BoundArch,
-      Action::OffloadKind DeviceOffloadingKind) const override;
+      BoundArch BA, Action::OffloadKind DeviceOffloadingKind) const override;
 
   const char *getDefaultLinker() const override { return "/bin/ld"; }
 

diff  --git a/clang/test/Driver/hip-link-bundle-archive.hip b/clang/test/Driver/hip-link-bundle-archive.hip
index 6606e19790a52..f1902957fbc13 100644
--- a/clang/test/Driver/hip-link-bundle-archive.hip
+++ b/clang/test/Driver/hip-link-bundle-archive.hip
@@ -68,19 +68,19 @@
 // RUN:   -nogpuinc -nogpulib %s -fgpu-rdc %t/hipBundled2.lib \
 // RUN:   2>&1 | FileCheck -check-prefix=MSVC %s
 
-// GNU1: "{{.*}}clang-offload-bundler" "-unbundle" "-type=a" "-input={{.*}}[[LIB:libhipBundled\.a]]" "-targets=hip-amdgcn-amd-amdhsa-unknown-gfx1030" "-output=[[A1030:.*\.a]]" "-allow-missing-bundles"
-// GNU2: "{{.*}}clang-offload-bundler" "-unbundle" "-type=a" "-input={{.*}}[[LIB:libhipBundled\.a\.5\.2]]" "-targets=hip-amdgcn-amd-amdhsa-unknown-gfx1030" "-output=[[A1030:.*\.a]]" "-allow-missing-bundles"
-// GNU: "{{.*}}lld{{.*}}" {{.*}}"-plugin-opt=mcpu=gfx1030" {{.*}} "[[A1030]]"
-// GNU: "{{.*}}clang-offload-bundler" "-unbundle" "-type=a" "-input={{.*}}[[LIB]]" "-targets=hip-amdgcn-amd-amdhsa-unknown-gfx906" "-output=[[A906:.*\.a]]" "-allow-missing-bundles"
+// GNU1: "{{.*}}clang-offload-bundler" "-unbundle" "-type=a" "-input={{.*}}[[LIB:libhipBundled\.a]]" "-targets=hip-amdgcn-amd-amdhsa-unknown-gfx906" "-output=[[A906:.*\.a]]" "-allow-missing-bundles"
+// GNU2: "{{.*}}clang-offload-bundler" "-unbundle" "-type=a" "-input={{.*}}[[LIB:libhipBundled\.a\.5\.2]]" "-targets=hip-amdgcn-amd-amdhsa-unknown-gfx906" "-output=[[A906:.*\.a]]" "-allow-missing-bundles"
 // GNU: "{{.*}}lld{{.*}}" {{.*}}"-plugin-opt=mcpu=gfx906" {{.*}} "[[A906]]"
+// GNU: "{{.*}}clang-offload-bundler" "-unbundle" "-type=a" "-input={{.*}}[[LIB]]" "-targets=hip-amdgcn-amd-amdhsa-unknown-gfx1030" "-output=[[A1030:.*\.a]]" "-allow-missing-bundles"
+// GNU: "{{.*}}lld{{.*}}" {{.*}}"-plugin-opt=mcpu=gfx1030" {{.*}} "[[A1030]]"
 // GNU-L: "{{.*}}ld{{.*}}" {{.*}}"-o" "a.out" {{.*}}"-lhipBundled"
 // GNU-LA: "{{.*}}ld{{.*}}" {{.*}}"-o" "a.out" {{.*}}"-l:libhipBundled.a"
 // GNU-A: "{{.*}}ld{{.*}}" {{.*}}"-o" "a.out" "{{.*}}[[LIB]]"
 // NONARCHIVE-NOT: "{{.*}}clang-offload-bundler" "-unbundle" "-type=a" "-input={{.*libNonArchive\.a}}"
 // NONE-NOT: "{{.*}}clang-offload-bundler" "-unbundle" "-type=a" "-input={{.*NoneExist\.a}}"
 
-// MSVC: "{{.*}}clang-offload-bundler" "-unbundle" "-type=a" "-input={{.*}}hipBundled2.lib" "-targets=hip-amdgcn-amd-amdhsa-unknown-gfx1030" "-output=[[A1030:.*\.a]]" "-allow-missing-bundles"
-// MSVC: "{{.*}}lld{{.*}}" {{.*}}"-plugin-opt=mcpu=gfx1030" {{.*}} "[[A1030]]"
 // MSVC: "{{.*}}clang-offload-bundler" "-unbundle" "-type=a" "-input={{.*}}hipBundled2.lib" "-targets=hip-amdgcn-amd-amdhsa-unknown-gfx906" "-output=[[A906:.*\.a]]" "-allow-missing-bundles"
 // MSVC: "{{.*}}lld{{.*}}" {{.*}}"-plugin-opt=mcpu=gfx906" {{.*}} "[[A906]]"
+// MSVC: "{{.*}}clang-offload-bundler" "-unbundle" "-type=a" "-input={{.*}}hipBundled2.lib" "-targets=hip-amdgcn-amd-amdhsa-unknown-gfx1030" "-output=[[A1030:.*\.a]]" "-allow-missing-bundles"
+// MSVC: "{{.*}}lld{{.*}}" {{.*}}"-plugin-opt=mcpu=gfx1030" {{.*}} "[[A1030]]"
 // MSVC: "{{.*}}link{{.*}}" {{.*}}"-out:a.exe" {{.*}}hipBundled2.lib"

diff  --git a/clang/test/Driver/hip-phases.hip b/clang/test/Driver/hip-phases.hip
index 4554519960133..c63f1259c4414 100644
--- a/clang/test/Driver/hip-phases.hip
+++ b/clang/test/Driver/hip-phases.hip
@@ -257,8 +257,8 @@
 // DBIN-DAG: [[P4:[0-9]+]]: assembler, {[[P3]]}, object, (device-[[T]], [[ARCH]])
 // DBIN-DAG: [[P5:[0-9]+]]: linker, {[[P4]]}, image, (device-[[T]], [[ARCH]])
 // DBIN-DAG: [[P6:[0-9]+]]: offload, "device-[[T]] (amdgcn-amd-amdhsa:[[ARCH]])" {[[P5]]}, image
-// DBIN-DAG: [[P7:[0-9]+]]: linker, {[[P6]]}, hip-fatbin, (device-hip, )
-// DBIN-DAG: [[P8:[0-9]+]]: offload, "device-[[T]] (amdgcn-amd-amdhsa:)" {[[P7]]}, hip-fatbin
+// DBIN-DAG: [[P7:[0-9]+]]: linker, {[[P6]]}, hip-fatbin, (device-hip)
+// DBIN-DAG: [[P8:[0-9]+]]: offload, "device-[[T]] (amdgcn-amd-amdhsa)" {[[P7]]}, hip-fatbin
 // DBIN-NOT: host
 
 //
@@ -357,8 +357,8 @@
 // DBIN2-DAG: [[P11:[0-9]+]]: assembler, {[[P10]]}, object, (device-[[T]], [[ARCH2]])
 // DBIN2-DAG: [[P12:[0-9]+]]: linker, {[[P11]]}, image, (device-[[T]], [[ARCH2]])
 // DBIN2-DAG: [[P13:[0-9]+]]: offload, "device-[[T]] (amdgcn-amd-amdhsa:[[ARCH2]])" {[[P12]]}, image
-// DBIN2-DAG: [[P14:[0-9]+]]: linker, {[[P6]], [[P13]]}, hip-fatbin, (device-hip, )
-// DBIN2-DAG: [[P15:[0-9]+]]: offload, "device-[[T]] (amdgcn-amd-amdhsa:)" {[[P14]]}, hip-fatbin
+// DBIN2-DAG: [[P14:[0-9]+]]: linker, {[[P6]], [[P13]]}, hip-fatbin, (device-hip)
+// DBIN2-DAG: [[P15:[0-9]+]]: offload, "device-[[T]] (amdgcn-amd-amdhsa)" {[[P14]]}, hip-fatbin
 // DBIN2-NOT: host
 
 //
@@ -391,8 +391,8 @@
 // DASM2-DAG: [[P7:[0-9]+]]: compiler, {[[P6]]}, ir, (device-[[T]], [[ARCH2]])
 // DASM2-DAG: [[P8:[0-9]+]]: backend, {[[P7]]}, assembler, (device-[[T]], [[ARCH2]])
 // DASM2-DAG: [[P9:[0-9]+]]: offload, "device-[[T]] (amdgcn-amd-amdhsa:[[ARCH2]])" {[[P8]]}, assembler
-// DASM2-BUNDLE: [[P10:[0-9]+]]: clang-offload-bundler, {[[P4]], [[P9]]}, assembler, (device-hip, )
-// DASM2-NOBUNDLE-NOT: clang-offload-bundler, {[[P4]], [[P9]]}, assembler, (device-hip, )
+// DASM2-BUNDLE: [[P10:[0-9]+]]: clang-offload-bundler, {[[P4]], [[P9]]}, assembler, (device-hip)
+// DASM2-NOBUNDLE-NOT: clang-offload-bundler, {[[P4]], [[P9]]}, assembler, (device-hip)
 // DASM2-NOT: host
 
 //
@@ -518,8 +518,8 @@
 // PPE-DAG: [[P0:[0-9]+]]: input, "{{.*}}hip-phases.hip", [[T:hip]], (device-[[T]], [[ARCH:gfx803]])
 // PPE-DAG: [[P1:[0-9]+]]: preprocessor, {[[P0]]}, [[T]]-cpp-output, (device-[[T]], [[ARCH]])
 // PPE-DAG: [[P2:[0-9]+]]: offload, "device-[[T]] (amdgcn-amd-amdhsa:[[ARCH]])" {[[P1]]}, [[T]]-cpp-output
-// PPEB-DAG: [[P3:[0-9]+]]: clang-offload-bundler, {[[P2]]}, [[T]]-cpp-output, (device-hip, )
-// PPEN-NOT: clang-offload-bundler, {{.*}}, [[T]]-cpp-output, (device-hip, )
+// PPEB-DAG: [[P3:[0-9]+]]: clang-offload-bundler, {[[P2]]}, [[T]]-cpp-output, (device-hip)
+// PPEN-NOT: clang-offload-bundler, {{.*}}, [[T]]-cpp-output, (device-hip)
 // PPE-NOT: host
 
 // PPE2-DAG: [[P0:[0-9]+]]: input, "{{.*}}hip-phases.hip", [[T:hip]], (device-[[T]], [[ARCH:gfx803]])
@@ -528,8 +528,8 @@
 // PPE2-DAG: [[P5:[0-9]+]]: input, "{{.*}}hip-phases.hip", [[T]], (device-[[T]], [[ARCH2:gfx900]])
 // PPE2-DAG: [[P6:[0-9]+]]: preprocessor, {[[P5]]}, [[T]]-cpp-output, (device-[[T]], [[ARCH2]])
 // PPE2-DAG: [[P9:[0-9]+]]: offload, "device-[[T]] (amdgcn-amd-amdhsa:[[ARCH2]])" {[[P6]]}, [[T]]-cpp-output
-// PPE2B-DAG: [[P10:[0-9]+]]: clang-offload-bundler, {[[P2]], [[P9]]}, [[T]]-cpp-output, (device-hip, )
-// PPE2N-NOT: clang-offload-bundler, {{.*}}, [[T]]-cpp-output, (device-hip, )
+// PPE2B-DAG: [[P10:[0-9]+]]: clang-offload-bundler, {[[P2]], [[P9]]}, [[T]]-cpp-output, (device-hip)
+// PPE2N-NOT: clang-offload-bundler, {{.*}}, [[T]]-cpp-output, (device-hip)
 // PPE2-NOT: host
 
 // LLVM-DAG: [[P0:[0-9]+]]: input, "{{.*}}hip-phases.hip", [[T:hip]], (device-[[T]], [[ARCH:gfx803]])
@@ -549,7 +549,7 @@
 // LLVM2-DAG: [[P7:[0-9]+]]: compiler, {[[P6]]}, ir, (device-[[T]], [[ARCH2]])
 // LLVM2-DAG: [[P8:[0-9]+]]: backend, {[[P7]]}, ir, (device-[[T]], [[ARCH2]])
 // LLVM2-DAG: [[P9:[0-9]+]]: offload, "device-[[T]] (amdgcn-amd-amdhsa:[[ARCH2]])" {[[P8]]}, ir
-// LLVM2-DAG: [[P10:[0-9]+]]: clang-offload-bundler, {[[P4]], [[P9]]}, ir, (device-hip, )
+// LLVM2-DAG: [[P10:[0-9]+]]: clang-offload-bundler, {[[P4]], [[P9]]}, ir, (device-hip)
 // LLVM2-NOT: host
 
 // PPELLVM2-DAG: [[P0:[0-9]+]]: input, "{{.*}}hip-phases.hip", [[T:hip]]-cpp-output
@@ -560,7 +560,7 @@
 // PPELLVM2-DAG: [[P7:[0-9]+]]: compiler, {[[P1]]}, ir, (device-[[T]], [[ARCH2:gfx900]])
 // PPELLVM2-DAG: [[P8:[0-9]+]]: backend, {[[P7]]}, ir, (device-[[T]], [[ARCH2]])
 // PPELLVM2-DAG: [[P9:[0-9]+]]: offload, "device-[[T]] (amdgcn-amd-amdhsa:[[ARCH2]])" {[[P8]]}, ir
-// PPELLVM2-DAG: [[P10:[0-9]+]]: clang-offload-bundler, {[[P4]], [[P9]]}, ir, (device-hip, )
+// PPELLVM2-DAG: [[P10:[0-9]+]]: clang-offload-bundler, {[[P4]], [[P9]]}, ir, (device-hip)
 // PPELLVM2-NOT: host
 
 // Test mixed HIP and C++ compilation. HIP program should have HIP offload kind.

diff  --git a/clang/test/Driver/hip-target-id.hip b/clang/test/Driver/hip-target-id.hip
index 1a1363d577d27..b7889b1634404 100644
--- a/clang/test/Driver/hip-target-id.hip
+++ b/clang/test/Driver/hip-target-id.hip
@@ -65,4 +65,4 @@
 // RUN:   --offload-arch=gfx906 \
 // RUN:   --no-offload-new-driver --rocm-path=%S/Inputs/rocm \
 // RUN:   %s 2>&1 | FileCheck -check-prefix=MULTI %s
-// MULTI: "-targets=host-x86_64-unknown-linux-gnu,hipv4-amdgcn-amd-amdhsa--gfx900:xnack+,hipv4-amdgcn-amd-amdhsa--gfx900:xnack-,hipv4-amdgcn-amd-amdhsa--gfx906,hipv4-amdgcn-amd-amdhsa--gfx908:sramecc+,hipv4-amdgcn-amd-amdhsa--gfx908:sramecc-"
+// MULTI: "-targets=host-x86_64-unknown-linux-gnu,hipv4-amdgcn-amd-amdhsa--gfx900:xnack+,hipv4-amdgcn-amd-amdhsa--gfx900:xnack-,hipv4-amdgcn-amd-amdhsa--gfx908:sramecc+,hipv4-amdgcn-amd-amdhsa--gfx908:sramecc-,hipv4-amdgcn-amd-amdhsa--gfx906"

diff  --git a/clang/test/Driver/hip-toolchain-no-rdc.hip b/clang/test/Driver/hip-toolchain-no-rdc.hip
index a97a25a7b05a8..6f148ce01ff30 100644
--- a/clang/test/Driver/hip-toolchain-no-rdc.hip
+++ b/clang/test/Driver/hip-toolchain-no-rdc.hip
@@ -231,14 +231,14 @@
 // Check mixed AMDGCNSPIRV and concrete GPU arch.
 //
 
+// AMDGCNSPIRV: "-cc1" "-triple" "amdgcn-amd-amdhsa" {{.*}}"-emit-obj" {{.*}} "-target-cpu" "gfx900"{{.*}} "-o" "[[GFX900_OBJ:.*o]]"
+// AMDGCNSPIRV: {{".*lld.*"}} {{.*}}"-plugin-opt=mcpu=gfx900" {{.*}} "-o" "[[GFX900_CO:.*out]]" {{.*}}"[[GFX900_OBJ]]"
 // AMDGCNSPIRV: "-cc1" "-triple" "spirv64-amd-amdhsa" {{.*}}"-emit-llvm-bc" {{.*}}"-flto=full"{{.*}} "-fembed-bitcode=marker" "-disable-llvm-passes" {{.*}} "-o" "[[AMDGCNSPV_BC:.*bc]]"
 // AMDGCNSPIRV: {{".*llvm-link.*"}} "-o" "[[AMDGCNSPV_TMP:.*bc]]" "[[AMDGCNSPV_BC]]"
 // AMDGCNSPIRV: {{".*llvm-spirv.*"}} "--spirv-max-version=1.6" "--spirv-ext=+all" {{.*}} "[[AMDGCNSPV_TMP]]" {{.*}}"-o" "[[AMDGCNSPV_CO:.*out]]"
-// AMDGCNSPIRV: "-cc1" "-triple" "amdgcn-amd-amdhsa" {{.*}}"-emit-obj" {{.*}} "-target-cpu" "gfx900"{{.*}} "-o" "[[GFX900_OBJ:.*o]]"
-// AMDGCNSPIRV: {{".*lld.*"}} {{.*}}"-plugin-opt=mcpu=gfx900" {{.*}} "-o" "[[GFX900_CO:.*out]]" {{.*}}"[[GFX900_OBJ]]"
 // AMDGCNSPIRV: {{".*clang-offload-bundler.*"}} "-type=o"
-// AMDGCNSPIRV-SAME: "-targets={{.*}}hip-spirv64-amd-amdhsa--amdgcnspirv,hip-amdgcn-amd-amdhsa--gfx900"
-// AMDGCNSPIRV-SAME: "-input=[[AMDGCNSPV_CO]]" "-input=[[GFX900_CO]]"
+// AMDGCNSPIRV-SAME: "-targets={{.*}}hipv4-amdgcn-amd-amdhsa--gfx900,hipv4-spirv64-amd-amdhsa--amdgcnspirv"
+// AMDGCNSPIRV-SAME: "-input=[[GFX900_CO]]" "-input=[[AMDGCNSPV_CO]]"
 // AMDGCNSPIRV-NEW: "-cc1" "-triple" "spirv64-amd-amdhsa" {{.*}}"-emit-llvm-bc" {{.*}} "-o" "[[AMDGCNSPV_BC:[^"]*]]"
 
 // Check verbose printing with the new driver.

diff  --git a/clang/unittests/Driver/DXCModeTest.cpp b/clang/unittests/Driver/DXCModeTest.cpp
index 130da620b40b5..300edf6ff7145 100644
--- a/clang/unittests/Driver/DXCModeTest.cpp
+++ b/clang/unittests/Driver/DXCModeTest.cpp
@@ -13,6 +13,7 @@
 #include "clang/Basic/DiagnosticIDs.h"
 #include "clang/Basic/DiagnosticOptions.h"
 #include "clang/Basic/LLVM.h"
+#include "clang/Basic/OffloadArch.h"
 #include "clang/Basic/TargetOptions.h"
 #include "clang/Driver/Compilation.h"
 #include "clang/Driver/CreateInvocationFromArgs.h"
@@ -129,7 +130,7 @@ TEST(DxcModeTest, ValidatorVersionValidation) {
     DAL->append(A);
 
   std::unique_ptr<llvm::opt::DerivedArgList> TranslatedArgs{
-      TC.TranslateArgs(*DAL, "0", Action::OffloadKind::OFK_None)};
+      TC.TranslateArgs(*DAL, BoundArch("0"), Action::OffloadKind::OFK_None)};
   EXPECT_NE(TranslatedArgs, nullptr);
   if (TranslatedArgs) {
     auto *A =
@@ -150,7 +151,7 @@ TEST(DxcModeTest, ValidatorVersionValidation) {
     DAL->append(A);
 
   TranslatedArgs.reset(
-      TC.TranslateArgs(*DAL, "0", Action::OffloadKind::OFK_None));
+      TC.TranslateArgs(*DAL, BoundArch("0"), Action::OffloadKind::OFK_None));
   EXPECT_EQ(Diags.getNumErrors(), 1u);
   EXPECT_STREQ(
       DiagConsumer->Errors.back().c_str(),
@@ -166,7 +167,7 @@ TEST(DxcModeTest, ValidatorVersionValidation) {
     DAL->append(A);
 
   TranslatedArgs.reset(
-      TC.TranslateArgs(*DAL, "0", Action::OffloadKind::OFK_None));
+      TC.TranslateArgs(*DAL, BoundArch("0"), Action::OffloadKind::OFK_None));
   EXPECT_EQ(Diags.getNumErrors(), 2u);
   EXPECT_STREQ(DiagConsumer->Errors.back().c_str(),
                "invalid validator version : 1; format of validator version is "
@@ -181,7 +182,7 @@ TEST(DxcModeTest, ValidatorVersionValidation) {
     DAL->append(A);
 
   TranslatedArgs.reset(
-      TC.TranslateArgs(*DAL, "0", Action::OffloadKind::OFK_None));
+      TC.TranslateArgs(*DAL, BoundArch("0"), Action::OffloadKind::OFK_None));
   EXPECT_EQ(Diags.getNumErrors(), 3u);
   EXPECT_STREQ(
       DiagConsumer->Errors.back().c_str(),
@@ -197,7 +198,7 @@ TEST(DxcModeTest, ValidatorVersionValidation) {
     DAL->append(A);
 
   TranslatedArgs.reset(
-      TC.TranslateArgs(*DAL, "0", Action::OffloadKind::OFK_None));
+      TC.TranslateArgs(*DAL, BoundArch("0"), Action::OffloadKind::OFK_None));
   EXPECT_EQ(Diags.getNumErrors(), 4u);
   EXPECT_STREQ(
       DiagConsumer->Errors.back().c_str(),


        


More information about the cfe-commits mailing list