[clang] [clang][Driver] Add a custom error option in multilib.yaml. (PR #105684)

Simon Tatham via cfe-commits cfe-commits at lists.llvm.org
Tue Aug 27 08:54:48 PDT 2024


https://github.com/statham-arm updated https://github.com/llvm/llvm-project/pull/105684

>From 806ac0bee0478fda32ec0bf5bfb9e28e1bef618d Mon Sep 17 00:00:00 2001
From: Simon Tatham <simon.tatham at arm.com>
Date: Wed, 21 Aug 2024 15:50:32 +0100
Subject: [PATCH 1/3] [clang][Driver] Add a custom error option in
 multilib.yaml.
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Sometimes a collection of multilibs has a gap in it, where a set of
driver command-line options can't work with any of the available
libraries.

For example, the Arm MVE extension requires special startup code (you
need to initialize FPSCR.LTPSIZE), and also benefits greatly from
-mfloat-abi=hard. So a multilib provider might build a library for
systems without MVE, and another for MVE with -mfloat-abi=hard,
anticipating that that's what most MVE users would want. But then if a
user compiles for MVE _without_ -mfloat-abi=hard, thhey can't use
either of those libraries – one has an ABI mismatch, and the other
will fail to set up LTPSIZE.

In that situation, it's useful to include a multilib.yaml entry for
the unworkable intermediate situation, and have it map to a fatal
error message rather than a set of actual libraries. Then the user
gets a build failure with a sensible explanation, instead of selecting
an unworkable library and silently generating bad output. The new
regression test demonstrates this case.

This patch introduces extra syntax into multilib.yaml, so that a
record in the `Variants` list can omit the `Dir` key, and in its
place, provide a `FatalError` key. Then, if that variant is selected,
the error message is emitted as a clang diagnostic, and multilib
selection fails.

In order to emit the error message in `MultilibSet::select`, I had to
pass a `Driver &` to that function, which involved plumbing one
through to every call site, and in the unit tests, constructing one
specially.
---
 clang/docs/Multilib.rst                       |  6 ++
 .../clang/Basic/DiagnosticDriverKinds.td      |  2 +
 clang/include/clang/Driver/Multilib.h         | 17 +++-
 clang/lib/Driver/Driver.cpp                   |  3 +-
 clang/lib/Driver/Multilib.cpp                 | 47 +++++++---
 clang/lib/Driver/ToolChains/BareMetal.cpp     |  9 +-
 clang/lib/Driver/ToolChains/Fuchsia.cpp       |  2 +-
 clang/lib/Driver/ToolChains/Gnu.cpp           | 57 ++++++------
 clang/lib/Driver/ToolChains/OHOS.cpp          |  7 +-
 .../baremetal-multilib-custom-error.yaml      | 63 ++++++++++++++
 .../unittests/Driver/MultilibBuilderTest.cpp  |  9 +-
 clang/unittests/Driver/MultilibTest.cpp       | 87 +++++++++++--------
 .../Driver/SimpleDiagnosticConsumer.h         | 16 ++++
 13 files changed, 236 insertions(+), 89 deletions(-)
 create mode 100644 clang/test/Driver/baremetal-multilib-custom-error.yaml

diff --git a/clang/docs/Multilib.rst b/clang/docs/Multilib.rst
index 063fe9a336f2fe..6d77fda3623b20 100644
--- a/clang/docs/Multilib.rst
+++ b/clang/docs/Multilib.rst
@@ -200,6 +200,12 @@ For a more comprehensive example see
     # to be a match.
     Flags: [--target=thumbv7m-none-eabi, -mfpu=fpv4-sp-d16]
 
+  # If there is no multilib available for a particular set of flags, and the
+  # other multilibs are not adequate fallbacks, then you can define a variant
+  # record with a FatalError key in place of the Dir key.
+  - FatalError: this multilib collection has no hard-float ABI support 
+    Flags: [--target=thumbv7m-none-eabi, -mfloat-abi=hard]
+
 
   # The second section of the file is a list of regular expressions that are
   # used to map from flags generated from command line options to custom flags.
diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td b/clang/include/clang/Basic/DiagnosticDriverKinds.td
index ba90742fbdaabc..97573fcf20c1fb 100644
--- a/clang/include/clang/Basic/DiagnosticDriverKinds.td
+++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td
@@ -810,6 +810,8 @@ def warn_drv_missing_multilib : Warning<
   InGroup<DiagGroup<"missing-multilib">>;
 def note_drv_available_multilibs : Note<
   "available multilibs are:%0">;
+def err_drv_multilib_custom_error : Error<
+  "multilib configuration error: %0">;
 
 def err_drv_experimental_crel : Error<
   "-Wa,--allow-experimental-crel must be specified to use -Wa,--crel. "
diff --git a/clang/include/clang/Driver/Multilib.h b/clang/include/clang/Driver/Multilib.h
index 9a2cc9bb1ba134..2b6a64187f7783 100644
--- a/clang/include/clang/Driver/Multilib.h
+++ b/clang/include/clang/Driver/Multilib.h
@@ -18,6 +18,7 @@
 #include "llvm/Support/SourceMgr.h"
 #include <cassert>
 #include <functional>
+#include <optional>
 #include <string>
 #include <utility>
 #include <vector>
@@ -25,6 +26,8 @@
 namespace clang {
 namespace driver {
 
+class Driver;
+
 /// This corresponds to a single GCC Multilib, or a segment of one controlled
 /// by a command line flag.
 /// See also MultilibBuilder for building a multilib by mutating it
@@ -48,13 +51,19 @@ class Multilib {
   // directory is not mutually exclusive with anything else.
   std::string ExclusiveGroup;
 
+  // Some Multilib objects don't actually represent library directories you can
+  // select. Instead, they represent failures of multilib selection, of the
+  // form 'Sorry, we don't have any library compatible with these constraints'.
+  std::optional<std::string> FatalError;
+
 public:
   /// GCCSuffix, OSSuffix & IncludeSuffix will be appended directly to the
   /// sysroot string so they must either be empty or begin with a '/' character.
   /// This is enforced with an assert in the constructor.
   Multilib(StringRef GCCSuffix = {}, StringRef OSSuffix = {},
            StringRef IncludeSuffix = {}, const flags_list &Flags = flags_list(),
-           StringRef ExclusiveGroup = {});
+           StringRef ExclusiveGroup = {},
+           std::optional<StringRef> FatalError = std::nullopt);
 
   /// Get the detected GCC installation path suffix for the multi-arch
   /// target variant. Always starts with a '/', unless empty
@@ -84,6 +93,10 @@ class Multilib {
   { return GCCSuffix.empty() && OSSuffix.empty() && IncludeSuffix.empty(); }
 
   bool operator==(const Multilib &Other) const;
+
+  bool isFatalError() const { return FatalError.has_value(); }
+
+  const std::string &getFatalError() const { return FatalError.value(); }
 };
 
 raw_ostream &operator<<(raw_ostream &OS, const Multilib &M);
@@ -130,7 +143,7 @@ class MultilibSet {
 
   /// Select compatible variants, \returns false if none are compatible
   bool select(const Multilib::flags_list &Flags,
-              llvm::SmallVectorImpl<Multilib> &) const;
+              llvm::SmallVectorImpl<Multilib> &, const Driver &D) const;
 
   unsigned size() const { return Multilibs.size(); }
 
diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp
index e12416e51f8d24..0ad911972a11ed 100644
--- a/clang/lib/Driver/Driver.cpp
+++ b/clang/lib/Driver/Driver.cpp
@@ -2296,7 +2296,8 @@ bool Driver::HandleImmediateArgs(Compilation &C) {
 
   if (C.getArgs().hasArg(options::OPT_print_multi_lib)) {
     for (const Multilib &Multilib : TC.getMultilibs())
-      llvm::outs() << Multilib << "\n";
+      if (!Multilib.isFatalError())
+        llvm::outs() << Multilib << "\n";
     return false;
   }
 
diff --git a/clang/lib/Driver/Multilib.cpp b/clang/lib/Driver/Multilib.cpp
index 9c091bbfdabab1..4114b7faa15270 100644
--- a/clang/lib/Driver/Multilib.cpp
+++ b/clang/lib/Driver/Multilib.cpp
@@ -9,6 +9,7 @@
 #include "clang/Driver/Multilib.h"
 #include "clang/Basic/LLVM.h"
 #include "clang/Basic/Version.h"
+#include "clang/Driver/Driver.h"
 #include "llvm/ADT/DenseSet.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/StringRef.h"
@@ -31,9 +32,10 @@ using namespace llvm::sys;
 
 Multilib::Multilib(StringRef GCCSuffix, StringRef OSSuffix,
                    StringRef IncludeSuffix, const flags_list &Flags,
-                   StringRef ExclusiveGroup)
+                   StringRef ExclusiveGroup,
+                   std::optional<StringRef> FatalError)
     : GCCSuffix(GCCSuffix), OSSuffix(OSSuffix), IncludeSuffix(IncludeSuffix),
-      Flags(Flags), ExclusiveGroup(ExclusiveGroup) {
+      Flags(Flags), ExclusiveGroup(ExclusiveGroup), FatalError(FatalError) {
   assert(GCCSuffix.empty() ||
          (StringRef(GCCSuffix).front() == '/' && GCCSuffix.size() > 1));
   assert(OSSuffix.empty() ||
@@ -95,7 +97,8 @@ MultilibSet &MultilibSet::FilterOut(FilterCallback F) {
 void MultilibSet::push_back(const Multilib &M) { Multilibs.push_back(M); }
 
 bool MultilibSet::select(const Multilib::flags_list &Flags,
-                         llvm::SmallVectorImpl<Multilib> &Selected) const {
+                         llvm::SmallVectorImpl<Multilib> &Selected,
+                         const Driver &D) const {
   llvm::StringSet<> FlagSet(expandFlags(Flags));
   Selected.clear();
 
@@ -121,6 +124,14 @@ bool MultilibSet::select(const Multilib::flags_list &Flags,
         continue;
     }
 
+    // If this multilib is actually a placeholder containing a fatal
+    // error message written by the multilib.yaml author, display that
+    // error message, and return failure.
+    if (M.isFatalError()) {
+      D.Diag(clang::diag::err_drv_multilib_custom_error) << M.getFatalError();
+      return false;
+    }
+
     // Select this multilib.
     Selected.push_back(M);
   }
@@ -162,7 +173,8 @@ namespace {
 static const VersionTuple MultilibVersionCurrent(1, 0);
 
 struct MultilibSerialization {
-  std::string Dir;
+  std::string Dir;        // if this record successfully selects a library dir
+  std::string FatalError; // if this record reports a fatal error message
   std::vector<std::string> Flags;
   std::string Group;
 };
@@ -205,11 +217,16 @@ struct MultilibSetSerialization {
 
 template <> struct llvm::yaml::MappingTraits<MultilibSerialization> {
   static void mapping(llvm::yaml::IO &io, MultilibSerialization &V) {
-    io.mapRequired("Dir", V.Dir);
+    io.mapOptional("Dir", V.Dir);
+    io.mapOptional("FatalError", V.FatalError);
     io.mapRequired("Flags", V.Flags);
     io.mapOptional("Group", V.Group);
   }
   static std::string validate(IO &io, MultilibSerialization &V) {
+    if (V.Dir.empty() && V.FatalError.empty())
+      return "one of the 'Dir' and 'FatalError' keys must be specified";
+    if (!V.Dir.empty() && !V.FatalError.empty())
+      return "the 'Dir' and 'FatalError' keys may not both be specified";
     if (StringRef(V.Dir).starts_with("/"))
       return "paths must be relative but \"" + V.Dir + "\" starts with \"/\"";
     return std::string{};
@@ -295,14 +312,18 @@ MultilibSet::parseYaml(llvm::MemoryBufferRef Input,
   multilib_list Multilibs;
   Multilibs.reserve(MS.Multilibs.size());
   for (const auto &M : MS.Multilibs) {
-    std::string Dir;
-    if (M.Dir != ".")
-      Dir = "/" + M.Dir;
-    // We transfer M.Group straight into the ExclusiveGroup parameter for the
-    // Multilib constructor. If we later support more than one type of group,
-    // we'll have to look up the group name in MS.Groups, check its type, and
-    // decide what to do here.
-    Multilibs.emplace_back(Dir, Dir, Dir, M.Flags, M.Group);
+    if (!M.FatalError.empty()) {
+      Multilibs.emplace_back("", "", "", M.Flags, M.Group, M.FatalError);
+    } else {
+      std::string Dir;
+      if (M.Dir != ".")
+        Dir = "/" + M.Dir;
+      // We transfer M.Group straight into the ExclusiveGroup parameter for the
+      // Multilib constructor. If we later support more than one type of group,
+      // we'll have to look up the group name in MS.Groups, check its type, and
+      // decide what to do here.
+      Multilibs.emplace_back(Dir, Dir, Dir, M.Flags, M.Group);
+    }
   }
 
   return MultilibSet(std::move(Multilibs), std::move(MS.FlagMatchers));
diff --git a/clang/lib/Driver/ToolChains/BareMetal.cpp b/clang/lib/Driver/ToolChains/BareMetal.cpp
index 0f5f32f3f8f495..e26cdae6bf0391 100644
--- a/clang/lib/Driver/ToolChains/BareMetal.cpp
+++ b/clang/lib/Driver/ToolChains/BareMetal.cpp
@@ -58,7 +58,7 @@ static bool findRISCVMultilibs(const Driver &D,
 
     Result.Multilibs =
         MultilibSetBuilder().Either(Imac, Imafdc).makeMultilibSet();
-    return Result.Multilibs.select(Flags, Result.SelectedMultilibs);
+    return Result.Multilibs.select(Flags, Result.SelectedMultilibs, D);
   }
   if (TargetTriple.isRISCV32()) {
     MultilibBuilder Imac =
@@ -92,7 +92,7 @@ static bool findRISCVMultilibs(const Driver &D,
 
     Result.Multilibs =
         MultilibSetBuilder().Either(I, Im, Iac, Imac, Imafc).makeMultilibSet();
-    return Result.Multilibs.select(Flags, Result.SelectedMultilibs);
+    return Result.Multilibs.select(Flags, Result.SelectedMultilibs, D);
   }
   return false;
 }
@@ -182,12 +182,13 @@ static void findMultilibsFromYAML(const ToolChain &TC, const Driver &D,
   if (ErrorOrMultilibSet.getError())
     return;
   Result.Multilibs = ErrorOrMultilibSet.get();
-  if (Result.Multilibs.select(Flags, Result.SelectedMultilibs))
+  if (Result.Multilibs.select(Flags, Result.SelectedMultilibs, D))
     return;
   D.Diag(clang::diag::warn_drv_missing_multilib) << llvm::join(Flags, " ");
   std::stringstream ss;
   for (const Multilib &Multilib : Result.Multilibs)
-    ss << "\n" << llvm::join(Multilib.flags(), " ");
+    if (!Multilib.isFatalError())
+      ss << "\n" << llvm::join(Multilib.flags(), " ");
   D.Diag(clang::diag::note_drv_available_multilibs) << ss.str();
 }
 
diff --git a/clang/lib/Driver/ToolChains/Fuchsia.cpp b/clang/lib/Driver/ToolChains/Fuchsia.cpp
index 6daa73c7a54c88..d4145685c19b5f 100644
--- a/clang/lib/Driver/ToolChains/Fuchsia.cpp
+++ b/clang/lib/Driver/ToolChains/Fuchsia.cpp
@@ -324,7 +324,7 @@ Fuchsia::Fuchsia(const Driver &D, const llvm::Triple &Triple,
 
   Multilibs.setFilePathsCallback(FilePaths);
 
-  if (Multilibs.select(Flags, SelectedMultilibs)) {
+  if (Multilibs.select(Flags, SelectedMultilibs, D)) {
     // Ensure that -print-multi-directory only outputs one multilib directory.
     Multilib LastSelected = SelectedMultilibs.back();
     SelectedMultilibs = {LastSelected};
diff --git a/clang/lib/Driver/ToolChains/Gnu.cpp b/clang/lib/Driver/ToolChains/Gnu.cpp
index 52c2ee90b1b286..f65ba639fa5239 100644
--- a/clang/lib/Driver/ToolChains/Gnu.cpp
+++ b/clang/lib/Driver/ToolChains/Gnu.cpp
@@ -1041,7 +1041,8 @@ static bool isMSP430(llvm::Triple::ArchType Arch) {
   return Arch == llvm::Triple::msp430;
 }
 
-static bool findMipsCsMultilibs(const Multilib::flags_list &Flags,
+static bool findMipsCsMultilibs(const Driver &D,
+                                const Multilib::flags_list &Flags,
                                 FilterNonExistent &NonExistent,
                                 DetectedMultilibs &Result) {
   // Check for Code Sourcery toolchain multilibs
@@ -1135,7 +1136,7 @@ static bool findMipsCsMultilibs(const Multilib::flags_list &Flags,
   if (CSMipsMultilibs.size() < DebianMipsMultilibs.size())
     std::iter_swap(Candidates, Candidates + 1);
   for (const MultilibSet *Candidate : Candidates) {
-    if (Candidate->select(Flags, Result.SelectedMultilibs)) {
+    if (Candidate->select(Flags, Result.SelectedMultilibs, D)) {
       if (Candidate == &DebianMipsMultilibs)
         Result.BiarchSibling = Multilib();
       Result.Multilibs = *Candidate;
@@ -1145,7 +1146,8 @@ static bool findMipsCsMultilibs(const Multilib::flags_list &Flags,
   return false;
 }
 
-static bool findMipsAndroidMultilibs(llvm::vfs::FileSystem &VFS, StringRef Path,
+static bool findMipsAndroidMultilibs(const Driver &D,
+                                     llvm::vfs::FileSystem &VFS, StringRef Path,
                                      const Multilib::flags_list &Flags,
                                      FilterNonExistent &NonExistent,
                                      DetectedMultilibs &Result) {
@@ -1184,14 +1186,15 @@ static bool findMipsAndroidMultilibs(llvm::vfs::FileSystem &VFS, StringRef Path,
     MS = &AndroidMipselMultilibs;
   else if (VFS.exists(Path + "/32"))
     MS = &AndroidMips64elMultilibs;
-  if (MS->select(Flags, Result.SelectedMultilibs)) {
+  if (MS->select(Flags, Result.SelectedMultilibs, D)) {
     Result.Multilibs = *MS;
     return true;
   }
   return false;
 }
 
-static bool findMipsMuslMultilibs(const Multilib::flags_list &Flags,
+static bool findMipsMuslMultilibs(const Driver &D,
+                                  const Multilib::flags_list &Flags,
                                   FilterNonExistent &NonExistent,
                                   DetectedMultilibs &Result) {
   // Musl toolchain multilibs
@@ -1218,14 +1221,15 @@ static bool findMipsMuslMultilibs(const Multilib::flags_list &Flags,
           {"/../sysroot" + M.osSuffix() + "/usr/include"});
     });
   }
-  if (MuslMipsMultilibs.select(Flags, Result.SelectedMultilibs)) {
+  if (MuslMipsMultilibs.select(Flags, Result.SelectedMultilibs, D)) {
     Result.Multilibs = MuslMipsMultilibs;
     return true;
   }
   return false;
 }
 
-static bool findMipsMtiMultilibs(const Multilib::flags_list &Flags,
+static bool findMipsMtiMultilibs(const Driver &D,
+                                 const Multilib::flags_list &Flags,
                                  FilterNonExistent &NonExistent,
                                  DetectedMultilibs &Result) {
   // CodeScape MTI toolchain v1.2 and early.
@@ -1403,7 +1407,7 @@ static bool findMipsMtiMultilibs(const Multilib::flags_list &Flags,
             });
   }
   for (auto *Candidate : {&MtiMipsMultilibsV1, &MtiMipsMultilibsV2}) {
-    if (Candidate->select(Flags, Result.SelectedMultilibs)) {
+    if (Candidate->select(Flags, Result.SelectedMultilibs, D)) {
       Result.Multilibs = *Candidate;
       return true;
     }
@@ -1411,7 +1415,8 @@ static bool findMipsMtiMultilibs(const Multilib::flags_list &Flags,
   return false;
 }
 
-static bool findMipsImgMultilibs(const Multilib::flags_list &Flags,
+static bool findMipsImgMultilibs(const Driver &D,
+                                 const Multilib::flags_list &Flags,
                                  FilterNonExistent &NonExistent,
                                  DetectedMultilibs &Result) {
   // CodeScape IMG toolchain v1.2 and early.
@@ -1509,7 +1514,7 @@ static bool findMipsImgMultilibs(const Multilib::flags_list &Flags,
             });
   }
   for (auto *Candidate : {&ImgMultilibsV1, &ImgMultilibsV2}) {
-    if (Candidate->select(Flags, Result.SelectedMultilibs)) {
+    if (Candidate->select(Flags, Result.SelectedMultilibs, D)) {
       Result.Multilibs = *Candidate;
       return true;
     }
@@ -1556,25 +1561,25 @@ bool clang::driver::findMIPSMultilibs(const Driver &D,
   addMultilibFlag(!isMipsEL(TargetArch), "-EB", Flags);
 
   if (TargetTriple.isAndroid())
-    return findMipsAndroidMultilibs(D.getVFS(), Path, Flags, NonExistent,
+    return findMipsAndroidMultilibs(D, D.getVFS(), Path, Flags, NonExistent,
                                     Result);
 
   if (TargetTriple.getVendor() == llvm::Triple::MipsTechnologies &&
       TargetTriple.getOS() == llvm::Triple::Linux &&
       TargetTriple.getEnvironment() == llvm::Triple::UnknownEnvironment)
-    return findMipsMuslMultilibs(Flags, NonExistent, Result);
+    return findMipsMuslMultilibs(D, Flags, NonExistent, Result);
 
   if (TargetTriple.getVendor() == llvm::Triple::MipsTechnologies &&
       TargetTriple.getOS() == llvm::Triple::Linux &&
       TargetTriple.isGNUEnvironment())
-    return findMipsMtiMultilibs(Flags, NonExistent, Result);
+    return findMipsMtiMultilibs(D, Flags, NonExistent, Result);
 
   if (TargetTriple.getVendor() == llvm::Triple::ImaginationTechnologies &&
       TargetTriple.getOS() == llvm::Triple::Linux &&
       TargetTriple.isGNUEnvironment())
-    return findMipsImgMultilibs(Flags, NonExistent, Result);
+    return findMipsImgMultilibs(D, Flags, NonExistent, Result);
 
-  if (findMipsCsMultilibs(Flags, NonExistent, Result))
+  if (findMipsCsMultilibs(D, Flags, NonExistent, Result))
     return true;
 
   // Fallback to the regular toolchain-tree structure.
@@ -1582,7 +1587,7 @@ bool clang::driver::findMIPSMultilibs(const Driver &D,
   Result.Multilibs.push_back(Default);
   Result.Multilibs.FilterOut(NonExistent);
 
-  if (Result.Multilibs.select(Flags, Result.SelectedMultilibs)) {
+  if (Result.Multilibs.select(Flags, Result.SelectedMultilibs, D)) {
     Result.BiarchSibling = Multilib();
     return true;
   }
@@ -1629,7 +1634,7 @@ static void findAndroidArmMultilibs(const Driver &D,
   addMultilibFlag(IsArmV7Mode, "-march=armv7-a", Flags);
   addMultilibFlag(IsThumbMode, "-mthumb", Flags);
 
-  if (AndroidArmMultilibs.select(Flags, Result.SelectedMultilibs))
+  if (AndroidArmMultilibs.select(Flags, Result.SelectedMultilibs, D))
     Result.Multilibs = AndroidArmMultilibs;
 }
 
@@ -1655,7 +1660,7 @@ static bool findMSP430Multilibs(const Driver &D,
   addMultilibFlag(Args.hasFlag(options::OPT_fexceptions,
                                options::OPT_fno_exceptions, false),
                   "-exceptions", Flags);
-  if (Result.Multilibs.select(Flags, Result.SelectedMultilibs))
+  if (Result.Multilibs.select(Flags, Result.SelectedMultilibs, D))
     return true;
 
   return false;
@@ -1722,7 +1727,7 @@ static void findCSKYMultilibs(const Driver &D, const llvm::Triple &TargetTriple,
           .makeMultilibSet()
           .FilterOut(NonExistent);
 
-  if (CSKYMultilibs.select(Flags, Result.SelectedMultilibs))
+  if (CSKYMultilibs.select(Flags, Result.SelectedMultilibs, D))
     Result.Multilibs = CSKYMultilibs;
 }
 
@@ -1737,11 +1742,11 @@ static void findCSKYMultilibs(const Driver &D, const llvm::Triple &TargetTriple,
 ///     march=rv32ima are not compatible, because software and hardware
 ///     atomic operation can't work together correctly.
 static bool
-selectRISCVMultilib(const MultilibSet &RISCVMultilibSet, StringRef Arch,
-                    const Multilib::flags_list &Flags,
+selectRISCVMultilib(const Driver &D, const MultilibSet &RISCVMultilibSet,
+                    StringRef Arch, const Multilib::flags_list &Flags,
                     llvm::SmallVectorImpl<Multilib> &SelectedMultilibs) {
   // Try to find the perfect matching multi-lib first.
-  if (RISCVMultilibSet.select(Flags, SelectedMultilibs))
+  if (RISCVMultilibSet.select(Flags, SelectedMultilibs, D))
     return true;
 
   Multilib::flags_list NewFlags;
@@ -1833,7 +1838,7 @@ selectRISCVMultilib(const MultilibSet &RISCVMultilibSet, StringRef Arch,
   MultilibSet NewRISCVMultilibs =
       MultilibSetBuilder().Either(NewMultilibs).makeMultilibSet();
 
-  if (NewRISCVMultilibs.select(NewFlags, SelectedMultilibs))
+  if (NewRISCVMultilibs.select(NewFlags, SelectedMultilibs, D))
     for (const Multilib &NewSelectedM : SelectedMultilibs)
       for (const auto &M : RISCVMultilibSet)
         // Look up the corresponding multi-lib entry in original multi-lib set.
@@ -1894,7 +1899,7 @@ static void findRISCVBareMetalMultilibs(const Driver &D,
     }
   }
 
-  if (selectRISCVMultilib(RISCVMultilibs, MArch, Flags,
+  if (selectRISCVMultilib(D, RISCVMultilibs, MArch, Flags,
                           Result.SelectedMultilibs))
     Result.Multilibs = RISCVMultilibs;
 }
@@ -1937,7 +1942,7 @@ static void findRISCVMultilibs(const Driver &D,
   addMultilibFlag(ABIName == "lp64f", "-mabi=lp64f", Flags);
   addMultilibFlag(ABIName == "lp64d", "-mabi=lp64d", Flags);
 
-  if (RISCVMultilibs.select(Flags, Result.SelectedMultilibs))
+  if (RISCVMultilibs.select(Flags, Result.SelectedMultilibs, D))
     Result.Multilibs = RISCVMultilibs;
 }
 
@@ -2057,7 +2062,7 @@ static bool findBiarchMultilibs(const Driver &D,
   addMultilibFlag(TargetTriple.isArch32Bit(), "-m32", Flags);
   addMultilibFlag(TargetTriple.isArch64Bit() && IsX32, "-mx32", Flags);
 
-  if (!Result.Multilibs.select(Flags, Result.SelectedMultilibs))
+  if (!Result.Multilibs.select(Flags, Result.SelectedMultilibs, D))
     return false;
 
   if (Result.SelectedMultilibs.back() == Alt64 ||
diff --git a/clang/lib/Driver/ToolChains/OHOS.cpp b/clang/lib/Driver/ToolChains/OHOS.cpp
index 4ceafa9e713922..2f0804289c4351 100644
--- a/clang/lib/Driver/ToolChains/OHOS.cpp
+++ b/clang/lib/Driver/ToolChains/OHOS.cpp
@@ -32,7 +32,8 @@ using namespace clang::driver::tools::arm;
 using tools::addMultilibFlag;
 using tools::addPathIfExists;
 
-static bool findOHOSMuslMultilibs(const Multilib::flags_list &Flags,
+static bool findOHOSMuslMultilibs(const Driver &D,
+                                  const Multilib::flags_list &Flags,
                                   DetectedMultilibs &Result) {
   MultilibSet Multilibs;
   Multilibs.push_back(Multilib());
@@ -50,7 +51,7 @@ static bool findOHOSMuslMultilibs(const Multilib::flags_list &Flags,
       Multilib("/a7_hard_neon-vfpv4", {}, {},
                {"-mcpu=cortex-a7", "-mfloat-abi=hard", "-mfpu=neon-vfpv4"}));
 
-  if (Multilibs.select(Flags, Result.SelectedMultilibs)) {
+  if (Multilibs.select(Flags, Result.SelectedMultilibs, D)) {
     Result.Multilibs = Multilibs;
     return true;
   }
@@ -81,7 +82,7 @@ static bool findOHOSMultilibs(const Driver &D,
   addMultilibFlag((ARMFloatABI == tools::arm::FloatABI::Hard),
                   "-mfloat-abi=hard", Flags);
 
-  return findOHOSMuslMultilibs(Flags, Result);
+  return findOHOSMuslMultilibs(D, Flags, Result);
 }
 
 std::string OHOS::getMultiarchTriple(const llvm::Triple &T) const {
diff --git a/clang/test/Driver/baremetal-multilib-custom-error.yaml b/clang/test/Driver/baremetal-multilib-custom-error.yaml
new file mode 100644
index 00000000000000..e8f4ddfca5b333
--- /dev/null
+++ b/clang/test/Driver/baremetal-multilib-custom-error.yaml
@@ -0,0 +1,63 @@
+# REQUIRES: shell
+# UNSUPPORTED: system-windows
+
+# RUN: rm -rf %T/baremetal_multilib
+# RUN: mkdir -p %T/baremetal_multilib/bin
+# RUN: mkdir -p %T/baremetal_multilib/lib/clang-runtimes/arm-none-eabi/thumb/v8-m.main/fp/lib
+# RUN: touch %T/baremetal_multilib/lib/clang-runtimes/arm-none-eabi/thumb/v8-m.main/fp/lib/libclang_rt.builtins.a
+# RUN: ln -s %clang %T/baremetal_multilib/bin/clang
+# RUN: ln -s %s %T/baremetal_multilib/lib/clang-runtimes/multilib.yaml
+
+# RUN: %T/baremetal_multilib/bin/clang -no-canonical-prefixes -print-multi-directory 2>&1 \
+# RUN:     --target=thumbv8m.main-none-eabi -march=armv8.1m.main --sysroot= \
+# RUN:   | FileCheck --check-prefix=CHECK-PRINT-MULTI-DIRECTORY-NOMVE-SOFTFLOAT %s
+# CHECK-PRINT-MULTI-DIRECTORY-NOMVE-SOFTFLOAT: nomve-softfloat
+
+# RUN: not %T/baremetal_multilib/bin/clang -no-canonical-prefixes -print-multi-directory 2>&1 \
+# RUN:     --target=thumbv8m.main-none-eabi -march=armv8.1m.main+mve --sysroot= \
+# RUN:   | FileCheck --check-prefix=CHECK-ERROR %s
+# CHECK-ERROR: multilib configuration error: mve-softfloat is not supported
+
+# RUN: %T/baremetal_multilib/bin/clang -no-canonical-prefixes -print-multi-directory 2>&1 \
+# RUN:     --target=thumbv8m.main-none-eabi -march=armv8.1m.main+mve -mfloat-abi=hard --sysroot= \
+# RUN:   | FileCheck --check-prefix=CHECK-PRINT-MULTI-DIRECTORY-MVE-HARDFLOAT %s
+# CHECK-PRINT-MULTI-DIRECTORY-MVE-HARDFLOAT: mve-hardfloat
+
+# RUN: %T/baremetal_multilib/bin/clang -no-canonical-prefixes -print-multi-lib 2>&1 \
+# RUN:     --target=arm-none-eabi --sysroot= \
+# RUN:   | FileCheck --check-prefix=CHECK-PRINT-MULTI-LIB %s
+# CHECK-PRINT-MULTI-LIB: nomve-softfloat;@-target=thumbv8.1m.main-unknown-none-eabi
+# CHECK-PRINT-MULTI-LIB-NEXT: mve-hardfloat;@-target=thumbv8.1m.main-unknown-none-eabihf at march=thumbv8.1m.main+mve at mfloat-abi=hard
+
+# RUN: %T/baremetal_multilib/bin/clang -no-canonical-prefixes -print-multi-directory 2>&1 \
+# RUN:     --target=arm-none-eabi --sysroot= \
+# RUN:   | FileCheck --check-prefix=CHECK-NO-MATCH-WARNING %s
+# CHECK-NO-MATCH-WARNING: clang: note: available multilibs are:
+# CHECK-NO-MATCH-WARNING-NEXT: --target=thumbv8.1m.main-unknown-none-eabi
+# CHECK-NO-MATCH-WARNING-NEXT: --target=thumbv8.1m.main-unknown-none-eabihf -march=thumbv8.1m.main+mve -mfloat-abi=hard
+
+---
+MultilibVersion: 1.0
+
+Variants:
+- Dir: nomve-softfloat
+  Flags:
+  - --target=thumbv8.1m.main-unknown-none-eabi
+
+- FatalError: mve-softfloat is not supported
+  Flags: 
+  - --target=thumbv8.1m.main-unknown-none-eabi
+  - -march=thumbv8.1m.main+mve
+
+- Dir: mve-hardfloat
+  Flags: 
+  - --target=thumbv8.1m.main-unknown-none-eabihf
+  - -march=thumbv8.1m.main+mve
+  - -mfloat-abi=hard
+
+Mappings:
+- Match: -march=thumbv8\.1m\.main(\+[^\+]+)*\+mve(\+[^\+]+)*
+  Flags:
+  - -march=thumbv8.1m.main+mve
+
+...
diff --git a/clang/unittests/Driver/MultilibBuilderTest.cpp b/clang/unittests/Driver/MultilibBuilderTest.cpp
index e23fe7e2441db5..8a3b73ab5fc5c9 100644
--- a/clang/unittests/Driver/MultilibBuilderTest.cpp
+++ b/clang/unittests/Driver/MultilibBuilderTest.cpp
@@ -13,6 +13,7 @@
 
 #include "clang/Driver/MultilibBuilder.h"
 #include "../../lib/Driver/ToolChains/CommonArgs.h"
+#include "SimpleDiagnosticConsumer.h"
 #include "clang/Basic/LLVM.h"
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/StringRef.h"
@@ -164,7 +165,8 @@ TEST(MultilibBuilderTest, SetSelection1) {
 
   Multilib::flags_list FlagM64 = {"-m64"};
   llvm::SmallVector<Multilib> SelectionM64;
-  ASSERT_TRUE(MS1.select(FlagM64, SelectionM64))
+  Driver TheDriver = diagnostic_test_driver();
+  ASSERT_TRUE(MS1.select(FlagM64, SelectionM64, TheDriver))
       << "Flag set was {\"-m64\"}, but selection not found";
   ASSERT_TRUE(SelectionM64.back().gccSuffix() == "/64")
       << "Selection picked " << SelectionM64.back()
@@ -172,7 +174,7 @@ TEST(MultilibBuilderTest, SetSelection1) {
 
   Multilib::flags_list FlagNoM64 = {"!m64"};
   llvm::SmallVector<Multilib> SelectionNoM64;
-  ASSERT_TRUE(MS1.select(FlagNoM64, SelectionNoM64))
+  ASSERT_TRUE(MS1.select(FlagNoM64, SelectionNoM64, TheDriver))
       << "Flag set was {\"!m64\"}, but selection not found";
   ASSERT_TRUE(SelectionNoM64.back().gccSuffix() == "")
       << "Selection picked " << SelectionNoM64.back()
@@ -200,7 +202,8 @@ TEST(MultilibBuilderTest, SetSelection2) {
       Flags.push_back("!SF");
 
     llvm::SmallVector<Multilib> Selection;
-    ASSERT_TRUE(MS2.select(Flags, Selection))
+    Driver TheDriver = diagnostic_test_driver();
+    ASSERT_TRUE(MS2.select(Flags, Selection, TheDriver))
         << "Selection failed for " << (IsEL ? "-EL" : "!EL") << " "
         << (IsSF ? "-SF" : "!SF");
 
diff --git a/clang/unittests/Driver/MultilibTest.cpp b/clang/unittests/Driver/MultilibTest.cpp
index ed9ac58cecd7b2..c871688c898345 100644
--- a/clang/unittests/Driver/MultilibTest.cpp
+++ b/clang/unittests/Driver/MultilibTest.cpp
@@ -12,6 +12,7 @@
 
 #include "clang/Driver/Multilib.h"
 #include "../../lib/Driver/ToolChains/CommonArgs.h"
+#include "SimpleDiagnosticConsumer.h"
 #include "clang/Basic/LLVM.h"
 #include "clang/Basic/Version.h"
 #include "llvm/ADT/ArrayRef.h"
@@ -153,16 +154,17 @@ TEST(MultilibTest, SetPriority) {
       Multilib("/foo", {}, {}, {"+foo"}),
       Multilib("/bar", {}, {}, {"+bar"}),
   });
+  Driver TheDriver = diagnostic_test_driver();
   Multilib::flags_list Flags1 = {"+foo", "-bar"};
   llvm::SmallVector<Multilib> Selection1;
-  ASSERT_TRUE(MS.select(Flags1, Selection1))
+  ASSERT_TRUE(MS.select(Flags1, Selection1, TheDriver))
       << "Flag set was {\"+foo\"}, but selection not found";
   ASSERT_TRUE(Selection1.back().gccSuffix() == "/foo")
       << "Selection picked " << Selection1.back() << " which was not expected";
 
   Multilib::flags_list Flags2 = {"+foo", "+bar"};
   llvm::SmallVector<Multilib> Selection2;
-  ASSERT_TRUE(MS.select(Flags2, Selection2))
+  ASSERT_TRUE(MS.select(Flags2, Selection2, TheDriver))
       << "Flag set was {\"+bar\"}, but selection not found";
   ASSERT_TRUE(Selection2.back().gccSuffix() == "/bar")
       << "Selection picked " << Selection2.back() << " which was not expected";
@@ -174,16 +176,17 @@ TEST(MultilibTest, SelectMultiple) {
       Multilib("/b", {}, {}, {"y"}),
   });
   llvm::SmallVector<Multilib> Selection;
+  Driver TheDriver = diagnostic_test_driver();
 
-  ASSERT_TRUE(MS.select({"x"}, Selection));
+  ASSERT_TRUE(MS.select({"x"}, Selection, TheDriver));
   ASSERT_EQ(1u, Selection.size());
   EXPECT_EQ("/a", Selection[0].gccSuffix());
 
-  ASSERT_TRUE(MS.select({"y"}, Selection));
+  ASSERT_TRUE(MS.select({"y"}, Selection, TheDriver));
   ASSERT_EQ(1u, Selection.size());
   EXPECT_EQ("/b", Selection[0].gccSuffix());
 
-  ASSERT_TRUE(MS.select({"y", "x"}, Selection));
+  ASSERT_TRUE(MS.select({"y", "x"}, Selection, TheDriver));
   ASSERT_EQ(2u, Selection.size());
   EXPECT_EQ("/a", Selection[0].gccSuffix());
   EXPECT_EQ("/b", Selection[1].gccSuffix());
@@ -277,7 +280,9 @@ Variants: []
 Variants:
 - Flags: []
 )"));
-  EXPECT_TRUE(StringRef(Diagnostic).contains("missing required key 'Dir'"))
+  EXPECT_TRUE(
+      StringRef(Diagnostic)
+          .contains("one of the 'Dir' and 'FatalError' keys must be specified"))
       << Diagnostic;
 
   EXPECT_FALSE(parseYaml(MS, Diagnostic, YAML_PREAMBLE R"(
@@ -364,9 +369,10 @@ TEST(MultilibTest, SelectSoft) {
 - Match: -mfloat-abi=softfp
   Flags: [-mfloat-abi=soft]
 )"));
-  EXPECT_TRUE(MS.select({"-mfloat-abi=soft"}, Selected));
-  EXPECT_TRUE(MS.select({"-mfloat-abi=softfp"}, Selected));
-  EXPECT_FALSE(MS.select({"-mfloat-abi=hard"}, Selected));
+  Driver TheDriver = diagnostic_test_driver();
+  EXPECT_TRUE(MS.select({"-mfloat-abi=soft"}, Selected, TheDriver));
+  EXPECT_TRUE(MS.select({"-mfloat-abi=softfp"}, Selected, TheDriver));
+  EXPECT_FALSE(MS.select({"-mfloat-abi=hard"}, Selected, TheDriver));
 }
 
 TEST(MultilibTest, SelectSoftFP) {
@@ -377,9 +383,10 @@ TEST(MultilibTest, SelectSoftFP) {
 - Dir: f
   Flags: [-mfloat-abi=softfp]
 )"));
-  EXPECT_FALSE(MS.select({"-mfloat-abi=soft"}, Selected));
-  EXPECT_TRUE(MS.select({"-mfloat-abi=softfp"}, Selected));
-  EXPECT_FALSE(MS.select({"-mfloat-abi=hard"}, Selected));
+  Driver TheDriver = diagnostic_test_driver();
+  EXPECT_FALSE(MS.select({"-mfloat-abi=soft"}, Selected, TheDriver));
+  EXPECT_TRUE(MS.select({"-mfloat-abi=softfp"}, Selected, TheDriver));
+  EXPECT_FALSE(MS.select({"-mfloat-abi=hard"}, Selected, TheDriver));
 }
 
 TEST(MultilibTest, SelectHard) {
@@ -392,9 +399,10 @@ TEST(MultilibTest, SelectHard) {
 - Dir: h
   Flags: [-mfloat-abi=hard]
 )"));
-  EXPECT_FALSE(MS.select({"-mfloat-abi=soft"}, Selected));
-  EXPECT_FALSE(MS.select({"-mfloat-abi=softfp"}, Selected));
-  EXPECT_TRUE(MS.select({"-mfloat-abi=hard"}, Selected));
+  Driver TheDriver = diagnostic_test_driver();
+  EXPECT_FALSE(MS.select({"-mfloat-abi=soft"}, Selected, TheDriver));
+  EXPECT_FALSE(MS.select({"-mfloat-abi=softfp"}, Selected, TheDriver));
+  EXPECT_TRUE(MS.select({"-mfloat-abi=hard"}, Selected, TheDriver));
 }
 
 TEST(MultilibTest, SelectFloatABI) {
@@ -412,11 +420,12 @@ TEST(MultilibTest, SelectFloatABI) {
 - Match: -mfloat-abi=softfp
   Flags: [-mfloat-abi=soft]
 )"));
-  MS.select({"-mfloat-abi=soft"}, Selected);
+  Driver TheDriver = diagnostic_test_driver();
+  MS.select({"-mfloat-abi=soft"}, Selected, TheDriver);
   EXPECT_EQ("/s", Selected.back().gccSuffix());
-  MS.select({"-mfloat-abi=softfp"}, Selected);
+  MS.select({"-mfloat-abi=softfp"}, Selected, TheDriver);
   EXPECT_EQ("/f", Selected.back().gccSuffix());
-  MS.select({"-mfloat-abi=hard"}, Selected);
+  MS.select({"-mfloat-abi=hard"}, Selected, TheDriver);
   EXPECT_EQ("/h", Selected.back().gccSuffix());
 }
 
@@ -437,15 +446,18 @@ TEST(MultilibTest, SelectFloatABIReversed) {
 - Match: -mfloat-abi=softfp
   Flags: [-mfloat-abi=soft]
 )"));
-  MS.select({"-mfloat-abi=soft"}, Selected);
+  Driver TheDriver = diagnostic_test_driver();
+  MS.select({"-mfloat-abi=soft"}, Selected, TheDriver);
   EXPECT_EQ("/s", Selected.back().gccSuffix());
-  MS.select({"-mfloat-abi=softfp"}, Selected);
+  MS.select({"-mfloat-abi=softfp"}, Selected, TheDriver);
   EXPECT_EQ("/s", Selected.back().gccSuffix());
-  MS.select({"-mfloat-abi=hard"}, Selected);
+  MS.select({"-mfloat-abi=hard"}, Selected, TheDriver);
   EXPECT_EQ("/h", Selected.back().gccSuffix());
 }
 
 TEST(MultilibTest, SelectMClass) {
+  Driver TheDriver = diagnostic_test_driver();
+
   const char *MultilibSpec = YAML_PREAMBLE R"(
 Variants:
 - Dir: thumb/v6-m/nofp
@@ -494,44 +506,47 @@ TEST(MultilibTest, SelectMClass) {
   ASSERT_TRUE(parseYaml(MS, MultilibSpec));
 
   ASSERT_TRUE(MS.select({"--target=thumbv6m-none-unknown-eabi", "-mfpu=none"},
-                        Selected));
+                        Selected, TheDriver));
   EXPECT_EQ("/thumb/v6-m/nofp", Selected.back().gccSuffix());
 
   ASSERT_TRUE(MS.select({"--target=thumbv7m-none-unknown-eabi", "-mfpu=none"},
-                        Selected));
+                        Selected, TheDriver));
   EXPECT_EQ("/thumb/v7-m/nofp", Selected.back().gccSuffix());
 
   ASSERT_TRUE(MS.select({"--target=thumbv7em-none-unknown-eabi", "-mfpu=none"},
-                        Selected));
+                        Selected, TheDriver));
   EXPECT_EQ("/thumb/v7e-m/nofp", Selected.back().gccSuffix());
 
-  ASSERT_TRUE(MS.select(
-      {"--target=thumbv8m.main-none-unknown-eabi", "-mfpu=none"}, Selected));
+  ASSERT_TRUE(
+      MS.select({"--target=thumbv8m.main-none-unknown-eabi", "-mfpu=none"},
+                Selected, TheDriver));
   EXPECT_EQ("/thumb/v8-m.main/nofp", Selected.back().gccSuffix());
 
-  ASSERT_TRUE(MS.select(
-      {"--target=thumbv8.1m.main-none-unknown-eabi", "-mfpu=none"}, Selected));
+  ASSERT_TRUE(
+      MS.select({"--target=thumbv8.1m.main-none-unknown-eabi", "-mfpu=none"},
+                Selected, TheDriver));
   EXPECT_EQ("/thumb/v8.1-m.main/nofp/nomve", Selected.back().gccSuffix());
 
   ASSERT_TRUE(
       MS.select({"--target=thumbv7em-none-unknown-eabihf", "-mfpu=fpv4-sp-d16"},
-                Selected));
+                Selected, TheDriver));
   EXPECT_EQ("/thumb/v7e-m/fpv4_sp_d16", Selected.back().gccSuffix());
 
-  ASSERT_TRUE(MS.select(
-      {"--target=thumbv7em-none-unknown-eabihf", "-mfpu=fpv5-d16"}, Selected));
+  ASSERT_TRUE(
+      MS.select({"--target=thumbv7em-none-unknown-eabihf", "-mfpu=fpv5-d16"},
+                Selected, TheDriver));
   EXPECT_EQ("/thumb/v7e-m/fpv5_d16", Selected.back().gccSuffix());
 
-  ASSERT_TRUE(
-      MS.select({"--target=thumbv8m.main-none-unknown-eabihf"}, Selected));
+  ASSERT_TRUE(MS.select({"--target=thumbv8m.main-none-unknown-eabihf"},
+                        Selected, TheDriver));
   EXPECT_EQ("/thumb/v8-m.main/fp", Selected.back().gccSuffix());
 
-  ASSERT_TRUE(
-      MS.select({"--target=thumbv8.1m.main-none-unknown-eabihf"}, Selected));
+  ASSERT_TRUE(MS.select({"--target=thumbv8.1m.main-none-unknown-eabihf"},
+                        Selected, TheDriver));
   EXPECT_EQ("/thumb/v8.1-m.main/fp", Selected.back().gccSuffix());
 
   ASSERT_TRUE(MS.select({"--target=thumbv8.1m.main-none-unknown-eabihf",
                          "-mfpu=none", "-march=thumbv8.1m.main+dsp+mve"},
-                        Selected));
+                        Selected, TheDriver));
   EXPECT_EQ("/thumb/v8.1-m.main/nofp/mve", Selected.back().gccSuffix());
 }
diff --git a/clang/unittests/Driver/SimpleDiagnosticConsumer.h b/clang/unittests/Driver/SimpleDiagnosticConsumer.h
index f11cccd64e379d..0e8d328757a9d6 100644
--- a/clang/unittests/Driver/SimpleDiagnosticConsumer.h
+++ b/clang/unittests/Driver/SimpleDiagnosticConsumer.h
@@ -15,6 +15,7 @@
 
 #include "clang/Basic/Diagnostic.h"
 #include "llvm/ADT/SmallString.h"
+#include "llvm/Support/VirtualFileSystem.h"
 
 struct SimpleDiagnosticConsumer : public clang::DiagnosticConsumer {
   void HandleDiagnostic(clang::DiagnosticsEngine::Level DiagLevel,
@@ -36,4 +37,19 @@ struct SimpleDiagnosticConsumer : public clang::DiagnosticConsumer {
   std::vector<llvm::SmallString<32>> Errors;
 };
 
+// Using SimpleDiagnosticConsumer, this function makes a clang Driver, suitable
+// for testing situations where it will only ever be used for emitting
+// diagnostics, such as being passed to `MultilibSet::select`.
+inline clang::driver::Driver diagnostic_test_driver() {
+  llvm::IntrusiveRefCntPtr<clang::DiagnosticIDs> DiagID(
+      new clang::DiagnosticIDs());
+  llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> InMemoryFileSystem(
+      new llvm::vfs::InMemoryFileSystem);
+  auto *DiagConsumer = new SimpleDiagnosticConsumer;
+  llvm::IntrusiveRefCntPtr<clang::DiagnosticOptions> DiagOpts =
+      new clang::DiagnosticOptions();
+  clang::DiagnosticsEngine Diags(DiagID, &*DiagOpts, DiagConsumer);
+  return clang::driver::Driver("/bin/clang", "", Diags, "", InMemoryFileSystem);
+}
+
 #endif // CLANG_UNITTESTS_SIMPLEDIAGNOSTICCONSUMER_H

>From e7bf0bb1650445b17d75658083d550796768c6a8 Mon Sep 17 00:00:00 2001
From: Simon Tatham <simon.tatham at arm.com>
Date: Tue, 27 Aug 2024 09:15:48 +0100
Subject: [PATCH 2/3] fixup: reorder operands to MultilibSet::Select

Review feedback wants the `const Driver &` to come first.
---
 clang/include/clang/Driver/Multilib.h         |  4 +-
 clang/lib/Driver/Multilib.cpp                 |  5 +-
 clang/lib/Driver/ToolChains/BareMetal.cpp     |  6 +-
 clang/lib/Driver/ToolChains/Fuchsia.cpp       |  2 +-
 clang/lib/Driver/ToolChains/Gnu.cpp           | 26 +++---
 clang/lib/Driver/ToolChains/OHOS.cpp          |  2 +-
 .../unittests/Driver/MultilibBuilderTest.cpp  |  6 +-
 clang/unittests/Driver/MultilibTest.cpp       | 91 ++++++++++---------
 8 files changed, 73 insertions(+), 69 deletions(-)

diff --git a/clang/include/clang/Driver/Multilib.h b/clang/include/clang/Driver/Multilib.h
index 2b6a64187f7783..1a79417111eece 100644
--- a/clang/include/clang/Driver/Multilib.h
+++ b/clang/include/clang/Driver/Multilib.h
@@ -142,8 +142,8 @@ class MultilibSet {
   const_iterator end() const { return Multilibs.end(); }
 
   /// Select compatible variants, \returns false if none are compatible
-  bool select(const Multilib::flags_list &Flags,
-              llvm::SmallVectorImpl<Multilib> &, const Driver &D) const;
+  bool select(const Driver &D, const Multilib::flags_list &Flags,
+              llvm::SmallVectorImpl<Multilib> &) const;
 
   unsigned size() const { return Multilibs.size(); }
 
diff --git a/clang/lib/Driver/Multilib.cpp b/clang/lib/Driver/Multilib.cpp
index 4114b7faa15270..e8a27fe9de473a 100644
--- a/clang/lib/Driver/Multilib.cpp
+++ b/clang/lib/Driver/Multilib.cpp
@@ -96,9 +96,8 @@ MultilibSet &MultilibSet::FilterOut(FilterCallback F) {
 
 void MultilibSet::push_back(const Multilib &M) { Multilibs.push_back(M); }
 
-bool MultilibSet::select(const Multilib::flags_list &Flags,
-                         llvm::SmallVectorImpl<Multilib> &Selected,
-                         const Driver &D) const {
+bool MultilibSet::select(const Driver &D, const Multilib::flags_list &Flags,
+                         llvm::SmallVectorImpl<Multilib> &Selected) const {
   llvm::StringSet<> FlagSet(expandFlags(Flags));
   Selected.clear();
 
diff --git a/clang/lib/Driver/ToolChains/BareMetal.cpp b/clang/lib/Driver/ToolChains/BareMetal.cpp
index e26cdae6bf0391..8aed9ed6e18817 100644
--- a/clang/lib/Driver/ToolChains/BareMetal.cpp
+++ b/clang/lib/Driver/ToolChains/BareMetal.cpp
@@ -58,7 +58,7 @@ static bool findRISCVMultilibs(const Driver &D,
 
     Result.Multilibs =
         MultilibSetBuilder().Either(Imac, Imafdc).makeMultilibSet();
-    return Result.Multilibs.select(Flags, Result.SelectedMultilibs, D);
+    return Result.Multilibs.select(D, Flags, Result.SelectedMultilibs);
   }
   if (TargetTriple.isRISCV32()) {
     MultilibBuilder Imac =
@@ -92,7 +92,7 @@ static bool findRISCVMultilibs(const Driver &D,
 
     Result.Multilibs =
         MultilibSetBuilder().Either(I, Im, Iac, Imac, Imafc).makeMultilibSet();
-    return Result.Multilibs.select(Flags, Result.SelectedMultilibs, D);
+    return Result.Multilibs.select(D, Flags, Result.SelectedMultilibs);
   }
   return false;
 }
@@ -182,7 +182,7 @@ static void findMultilibsFromYAML(const ToolChain &TC, const Driver &D,
   if (ErrorOrMultilibSet.getError())
     return;
   Result.Multilibs = ErrorOrMultilibSet.get();
-  if (Result.Multilibs.select(Flags, Result.SelectedMultilibs, D))
+  if (Result.Multilibs.select(D, Flags, Result.SelectedMultilibs))
     return;
   D.Diag(clang::diag::warn_drv_missing_multilib) << llvm::join(Flags, " ");
   std::stringstream ss;
diff --git a/clang/lib/Driver/ToolChains/Fuchsia.cpp b/clang/lib/Driver/ToolChains/Fuchsia.cpp
index d4145685c19b5f..72accbff4a3bf2 100644
--- a/clang/lib/Driver/ToolChains/Fuchsia.cpp
+++ b/clang/lib/Driver/ToolChains/Fuchsia.cpp
@@ -324,7 +324,7 @@ Fuchsia::Fuchsia(const Driver &D, const llvm::Triple &Triple,
 
   Multilibs.setFilePathsCallback(FilePaths);
 
-  if (Multilibs.select(Flags, SelectedMultilibs, D)) {
+  if (Multilibs.select(D, Flags, SelectedMultilibs)) {
     // Ensure that -print-multi-directory only outputs one multilib directory.
     Multilib LastSelected = SelectedMultilibs.back();
     SelectedMultilibs = {LastSelected};
diff --git a/clang/lib/Driver/ToolChains/Gnu.cpp b/clang/lib/Driver/ToolChains/Gnu.cpp
index f65ba639fa5239..426042b272e2dc 100644
--- a/clang/lib/Driver/ToolChains/Gnu.cpp
+++ b/clang/lib/Driver/ToolChains/Gnu.cpp
@@ -1136,7 +1136,7 @@ static bool findMipsCsMultilibs(const Driver &D,
   if (CSMipsMultilibs.size() < DebianMipsMultilibs.size())
     std::iter_swap(Candidates, Candidates + 1);
   for (const MultilibSet *Candidate : Candidates) {
-    if (Candidate->select(Flags, Result.SelectedMultilibs, D)) {
+    if (Candidate->select(D, Flags, Result.SelectedMultilibs)) {
       if (Candidate == &DebianMipsMultilibs)
         Result.BiarchSibling = Multilib();
       Result.Multilibs = *Candidate;
@@ -1186,7 +1186,7 @@ static bool findMipsAndroidMultilibs(const Driver &D,
     MS = &AndroidMipselMultilibs;
   else if (VFS.exists(Path + "/32"))
     MS = &AndroidMips64elMultilibs;
-  if (MS->select(Flags, Result.SelectedMultilibs, D)) {
+  if (MS->select(D, Flags, Result.SelectedMultilibs)) {
     Result.Multilibs = *MS;
     return true;
   }
@@ -1221,7 +1221,7 @@ static bool findMipsMuslMultilibs(const Driver &D,
           {"/../sysroot" + M.osSuffix() + "/usr/include"});
     });
   }
-  if (MuslMipsMultilibs.select(Flags, Result.SelectedMultilibs, D)) {
+  if (MuslMipsMultilibs.select(D, Flags, Result.SelectedMultilibs)) {
     Result.Multilibs = MuslMipsMultilibs;
     return true;
   }
@@ -1407,7 +1407,7 @@ static bool findMipsMtiMultilibs(const Driver &D,
             });
   }
   for (auto *Candidate : {&MtiMipsMultilibsV1, &MtiMipsMultilibsV2}) {
-    if (Candidate->select(Flags, Result.SelectedMultilibs, D)) {
+    if (Candidate->select(D, Flags, Result.SelectedMultilibs)) {
       Result.Multilibs = *Candidate;
       return true;
     }
@@ -1514,7 +1514,7 @@ static bool findMipsImgMultilibs(const Driver &D,
             });
   }
   for (auto *Candidate : {&ImgMultilibsV1, &ImgMultilibsV2}) {
-    if (Candidate->select(Flags, Result.SelectedMultilibs, D)) {
+    if (Candidate->select(D, Flags, Result.SelectedMultilibs)) {
       Result.Multilibs = *Candidate;
       return true;
     }
@@ -1587,7 +1587,7 @@ bool clang::driver::findMIPSMultilibs(const Driver &D,
   Result.Multilibs.push_back(Default);
   Result.Multilibs.FilterOut(NonExistent);
 
-  if (Result.Multilibs.select(Flags, Result.SelectedMultilibs, D)) {
+  if (Result.Multilibs.select(D, Flags, Result.SelectedMultilibs)) {
     Result.BiarchSibling = Multilib();
     return true;
   }
@@ -1634,7 +1634,7 @@ static void findAndroidArmMultilibs(const Driver &D,
   addMultilibFlag(IsArmV7Mode, "-march=armv7-a", Flags);
   addMultilibFlag(IsThumbMode, "-mthumb", Flags);
 
-  if (AndroidArmMultilibs.select(Flags, Result.SelectedMultilibs, D))
+  if (AndroidArmMultilibs.select(D, Flags, Result.SelectedMultilibs))
     Result.Multilibs = AndroidArmMultilibs;
 }
 
@@ -1660,7 +1660,7 @@ static bool findMSP430Multilibs(const Driver &D,
   addMultilibFlag(Args.hasFlag(options::OPT_fexceptions,
                                options::OPT_fno_exceptions, false),
                   "-exceptions", Flags);
-  if (Result.Multilibs.select(Flags, Result.SelectedMultilibs, D))
+  if (Result.Multilibs.select(D, Flags, Result.SelectedMultilibs))
     return true;
 
   return false;
@@ -1727,7 +1727,7 @@ static void findCSKYMultilibs(const Driver &D, const llvm::Triple &TargetTriple,
           .makeMultilibSet()
           .FilterOut(NonExistent);
 
-  if (CSKYMultilibs.select(Flags, Result.SelectedMultilibs, D))
+  if (CSKYMultilibs.select(D, Flags, Result.SelectedMultilibs))
     Result.Multilibs = CSKYMultilibs;
 }
 
@@ -1746,7 +1746,7 @@ selectRISCVMultilib(const Driver &D, const MultilibSet &RISCVMultilibSet,
                     StringRef Arch, const Multilib::flags_list &Flags,
                     llvm::SmallVectorImpl<Multilib> &SelectedMultilibs) {
   // Try to find the perfect matching multi-lib first.
-  if (RISCVMultilibSet.select(Flags, SelectedMultilibs, D))
+  if (RISCVMultilibSet.select(D, Flags, SelectedMultilibs))
     return true;
 
   Multilib::flags_list NewFlags;
@@ -1838,7 +1838,7 @@ selectRISCVMultilib(const Driver &D, const MultilibSet &RISCVMultilibSet,
   MultilibSet NewRISCVMultilibs =
       MultilibSetBuilder().Either(NewMultilibs).makeMultilibSet();
 
-  if (NewRISCVMultilibs.select(NewFlags, SelectedMultilibs, D))
+  if (NewRISCVMultilibs.select(D, NewFlags, SelectedMultilibs))
     for (const Multilib &NewSelectedM : SelectedMultilibs)
       for (const auto &M : RISCVMultilibSet)
         // Look up the corresponding multi-lib entry in original multi-lib set.
@@ -1942,7 +1942,7 @@ static void findRISCVMultilibs(const Driver &D,
   addMultilibFlag(ABIName == "lp64f", "-mabi=lp64f", Flags);
   addMultilibFlag(ABIName == "lp64d", "-mabi=lp64d", Flags);
 
-  if (RISCVMultilibs.select(Flags, Result.SelectedMultilibs, D))
+  if (RISCVMultilibs.select(D, Flags, Result.SelectedMultilibs))
     Result.Multilibs = RISCVMultilibs;
 }
 
@@ -2062,7 +2062,7 @@ static bool findBiarchMultilibs(const Driver &D,
   addMultilibFlag(TargetTriple.isArch32Bit(), "-m32", Flags);
   addMultilibFlag(TargetTriple.isArch64Bit() && IsX32, "-mx32", Flags);
 
-  if (!Result.Multilibs.select(Flags, Result.SelectedMultilibs, D))
+  if (!Result.Multilibs.select(D, Flags, Result.SelectedMultilibs))
     return false;
 
   if (Result.SelectedMultilibs.back() == Alt64 ||
diff --git a/clang/lib/Driver/ToolChains/OHOS.cpp b/clang/lib/Driver/ToolChains/OHOS.cpp
index 2f0804289c4351..6e1a09ae908b2f 100644
--- a/clang/lib/Driver/ToolChains/OHOS.cpp
+++ b/clang/lib/Driver/ToolChains/OHOS.cpp
@@ -51,7 +51,7 @@ static bool findOHOSMuslMultilibs(const Driver &D,
       Multilib("/a7_hard_neon-vfpv4", {}, {},
                {"-mcpu=cortex-a7", "-mfloat-abi=hard", "-mfpu=neon-vfpv4"}));
 
-  if (Multilibs.select(Flags, Result.SelectedMultilibs, D)) {
+  if (Multilibs.select(D, Flags, Result.SelectedMultilibs)) {
     Result.Multilibs = Multilibs;
     return true;
   }
diff --git a/clang/unittests/Driver/MultilibBuilderTest.cpp b/clang/unittests/Driver/MultilibBuilderTest.cpp
index 8a3b73ab5fc5c9..0e5385c913533d 100644
--- a/clang/unittests/Driver/MultilibBuilderTest.cpp
+++ b/clang/unittests/Driver/MultilibBuilderTest.cpp
@@ -166,7 +166,7 @@ TEST(MultilibBuilderTest, SetSelection1) {
   Multilib::flags_list FlagM64 = {"-m64"};
   llvm::SmallVector<Multilib> SelectionM64;
   Driver TheDriver = diagnostic_test_driver();
-  ASSERT_TRUE(MS1.select(FlagM64, SelectionM64, TheDriver))
+  ASSERT_TRUE(MS1.select(TheDriver, FlagM64, SelectionM64))
       << "Flag set was {\"-m64\"}, but selection not found";
   ASSERT_TRUE(SelectionM64.back().gccSuffix() == "/64")
       << "Selection picked " << SelectionM64.back()
@@ -174,7 +174,7 @@ TEST(MultilibBuilderTest, SetSelection1) {
 
   Multilib::flags_list FlagNoM64 = {"!m64"};
   llvm::SmallVector<Multilib> SelectionNoM64;
-  ASSERT_TRUE(MS1.select(FlagNoM64, SelectionNoM64, TheDriver))
+  ASSERT_TRUE(MS1.select(TheDriver, FlagNoM64, SelectionNoM64))
       << "Flag set was {\"!m64\"}, but selection not found";
   ASSERT_TRUE(SelectionNoM64.back().gccSuffix() == "")
       << "Selection picked " << SelectionNoM64.back()
@@ -203,7 +203,7 @@ TEST(MultilibBuilderTest, SetSelection2) {
 
     llvm::SmallVector<Multilib> Selection;
     Driver TheDriver = diagnostic_test_driver();
-    ASSERT_TRUE(MS2.select(Flags, Selection, TheDriver))
+    ASSERT_TRUE(MS2.select(TheDriver, Flags, Selection))
         << "Selection failed for " << (IsEL ? "-EL" : "!EL") << " "
         << (IsSF ? "-SF" : "!SF");
 
diff --git a/clang/unittests/Driver/MultilibTest.cpp b/clang/unittests/Driver/MultilibTest.cpp
index c871688c898345..dfeef7c2077c72 100644
--- a/clang/unittests/Driver/MultilibTest.cpp
+++ b/clang/unittests/Driver/MultilibTest.cpp
@@ -157,14 +157,14 @@ TEST(MultilibTest, SetPriority) {
   Driver TheDriver = diagnostic_test_driver();
   Multilib::flags_list Flags1 = {"+foo", "-bar"};
   llvm::SmallVector<Multilib> Selection1;
-  ASSERT_TRUE(MS.select(Flags1, Selection1, TheDriver))
+  ASSERT_TRUE(MS.select(TheDriver, Flags1, Selection1))
       << "Flag set was {\"+foo\"}, but selection not found";
   ASSERT_TRUE(Selection1.back().gccSuffix() == "/foo")
       << "Selection picked " << Selection1.back() << " which was not expected";
 
   Multilib::flags_list Flags2 = {"+foo", "+bar"};
   llvm::SmallVector<Multilib> Selection2;
-  ASSERT_TRUE(MS.select(Flags2, Selection2, TheDriver))
+  ASSERT_TRUE(MS.select(TheDriver, Flags2, Selection2))
       << "Flag set was {\"+bar\"}, but selection not found";
   ASSERT_TRUE(Selection2.back().gccSuffix() == "/bar")
       << "Selection picked " << Selection2.back() << " which was not expected";
@@ -178,15 +178,15 @@ TEST(MultilibTest, SelectMultiple) {
   llvm::SmallVector<Multilib> Selection;
   Driver TheDriver = diagnostic_test_driver();
 
-  ASSERT_TRUE(MS.select({"x"}, Selection, TheDriver));
+  ASSERT_TRUE(MS.select(TheDriver, {"x"}, Selection));
   ASSERT_EQ(1u, Selection.size());
   EXPECT_EQ("/a", Selection[0].gccSuffix());
 
-  ASSERT_TRUE(MS.select({"y"}, Selection, TheDriver));
+  ASSERT_TRUE(MS.select(TheDriver, {"y"}, Selection));
   ASSERT_EQ(1u, Selection.size());
   EXPECT_EQ("/b", Selection[0].gccSuffix());
 
-  ASSERT_TRUE(MS.select({"y", "x"}, Selection, TheDriver));
+  ASSERT_TRUE(MS.select(TheDriver, {"y", "x"}, Selection));
   ASSERT_EQ(2u, Selection.size());
   EXPECT_EQ("/a", Selection[0].gccSuffix());
   EXPECT_EQ("/b", Selection[1].gccSuffix());
@@ -370,9 +370,9 @@ TEST(MultilibTest, SelectSoft) {
   Flags: [-mfloat-abi=soft]
 )"));
   Driver TheDriver = diagnostic_test_driver();
-  EXPECT_TRUE(MS.select({"-mfloat-abi=soft"}, Selected, TheDriver));
-  EXPECT_TRUE(MS.select({"-mfloat-abi=softfp"}, Selected, TheDriver));
-  EXPECT_FALSE(MS.select({"-mfloat-abi=hard"}, Selected, TheDriver));
+  EXPECT_TRUE(MS.select(TheDriver, {"-mfloat-abi=soft"}, Selected));
+  EXPECT_TRUE(MS.select(TheDriver, {"-mfloat-abi=softfp"}, Selected));
+  EXPECT_FALSE(MS.select(TheDriver, {"-mfloat-abi=hard"}, Selected));
 }
 
 TEST(MultilibTest, SelectSoftFP) {
@@ -384,9 +384,9 @@ TEST(MultilibTest, SelectSoftFP) {
   Flags: [-mfloat-abi=softfp]
 )"));
   Driver TheDriver = diagnostic_test_driver();
-  EXPECT_FALSE(MS.select({"-mfloat-abi=soft"}, Selected, TheDriver));
-  EXPECT_TRUE(MS.select({"-mfloat-abi=softfp"}, Selected, TheDriver));
-  EXPECT_FALSE(MS.select({"-mfloat-abi=hard"}, Selected, TheDriver));
+  EXPECT_FALSE(MS.select(TheDriver, {"-mfloat-abi=soft"}, Selected));
+  EXPECT_TRUE(MS.select(TheDriver, {"-mfloat-abi=softfp"}, Selected));
+  EXPECT_FALSE(MS.select(TheDriver, {"-mfloat-abi=hard"}, Selected));
 }
 
 TEST(MultilibTest, SelectHard) {
@@ -400,9 +400,9 @@ TEST(MultilibTest, SelectHard) {
   Flags: [-mfloat-abi=hard]
 )"));
   Driver TheDriver = diagnostic_test_driver();
-  EXPECT_FALSE(MS.select({"-mfloat-abi=soft"}, Selected, TheDriver));
-  EXPECT_FALSE(MS.select({"-mfloat-abi=softfp"}, Selected, TheDriver));
-  EXPECT_TRUE(MS.select({"-mfloat-abi=hard"}, Selected, TheDriver));
+  EXPECT_FALSE(MS.select(TheDriver, {"-mfloat-abi=soft"}, Selected));
+  EXPECT_FALSE(MS.select(TheDriver, {"-mfloat-abi=softfp"}, Selected));
+  EXPECT_TRUE(MS.select(TheDriver, {"-mfloat-abi=hard"}, Selected));
 }
 
 TEST(MultilibTest, SelectFloatABI) {
@@ -421,11 +421,11 @@ TEST(MultilibTest, SelectFloatABI) {
   Flags: [-mfloat-abi=soft]
 )"));
   Driver TheDriver = diagnostic_test_driver();
-  MS.select({"-mfloat-abi=soft"}, Selected, TheDriver);
+  MS.select(TheDriver, {"-mfloat-abi=soft"}, Selected);
   EXPECT_EQ("/s", Selected.back().gccSuffix());
-  MS.select({"-mfloat-abi=softfp"}, Selected, TheDriver);
+  MS.select(TheDriver, {"-mfloat-abi=softfp"}, Selected);
   EXPECT_EQ("/f", Selected.back().gccSuffix());
-  MS.select({"-mfloat-abi=hard"}, Selected, TheDriver);
+  MS.select(TheDriver, {"-mfloat-abi=hard"}, Selected);
   EXPECT_EQ("/h", Selected.back().gccSuffix());
 }
 
@@ -447,11 +447,11 @@ TEST(MultilibTest, SelectFloatABIReversed) {
   Flags: [-mfloat-abi=soft]
 )"));
   Driver TheDriver = diagnostic_test_driver();
-  MS.select({"-mfloat-abi=soft"}, Selected, TheDriver);
+  MS.select(TheDriver, {"-mfloat-abi=soft"}, Selected);
   EXPECT_EQ("/s", Selected.back().gccSuffix());
-  MS.select({"-mfloat-abi=softfp"}, Selected, TheDriver);
+  MS.select(TheDriver, {"-mfloat-abi=softfp"}, Selected);
   EXPECT_EQ("/s", Selected.back().gccSuffix());
-  MS.select({"-mfloat-abi=hard"}, Selected, TheDriver);
+  MS.select(TheDriver, {"-mfloat-abi=hard"}, Selected);
   EXPECT_EQ("/h", Selected.back().gccSuffix());
 }
 
@@ -505,48 +505,53 @@ TEST(MultilibTest, SelectMClass) {
   llvm::SmallVector<Multilib> Selected;
   ASSERT_TRUE(parseYaml(MS, MultilibSpec));
 
-  ASSERT_TRUE(MS.select({"--target=thumbv6m-none-unknown-eabi", "-mfpu=none"},
-                        Selected, TheDriver));
+  ASSERT_TRUE(MS.select(TheDriver,
+                        {"--target=thumbv6m-none-unknown-eabi", "-mfpu=none"},
+                        Selected));
   EXPECT_EQ("/thumb/v6-m/nofp", Selected.back().gccSuffix());
 
-  ASSERT_TRUE(MS.select({"--target=thumbv7m-none-unknown-eabi", "-mfpu=none"},
-                        Selected, TheDriver));
+  ASSERT_TRUE(MS.select(TheDriver,
+                        {"--target=thumbv7m-none-unknown-eabi", "-mfpu=none"},
+                        Selected));
   EXPECT_EQ("/thumb/v7-m/nofp", Selected.back().gccSuffix());
 
-  ASSERT_TRUE(MS.select({"--target=thumbv7em-none-unknown-eabi", "-mfpu=none"},
-                        Selected, TheDriver));
+  ASSERT_TRUE(MS.select(TheDriver,
+                        {"--target=thumbv7em-none-unknown-eabi", "-mfpu=none"},
+                        Selected));
   EXPECT_EQ("/thumb/v7e-m/nofp", Selected.back().gccSuffix());
 
-  ASSERT_TRUE(
-      MS.select({"--target=thumbv8m.main-none-unknown-eabi", "-mfpu=none"},
-                Selected, TheDriver));
+  ASSERT_TRUE(MS.select(
+      TheDriver, {"--target=thumbv8m.main-none-unknown-eabi", "-mfpu=none"},
+      Selected));
   EXPECT_EQ("/thumb/v8-m.main/nofp", Selected.back().gccSuffix());
 
-  ASSERT_TRUE(
-      MS.select({"--target=thumbv8.1m.main-none-unknown-eabi", "-mfpu=none"},
-                Selected, TheDriver));
+  ASSERT_TRUE(MS.select(
+      TheDriver, {"--target=thumbv8.1m.main-none-unknown-eabi", "-mfpu=none"},
+      Selected));
   EXPECT_EQ("/thumb/v8.1-m.main/nofp/nomve", Selected.back().gccSuffix());
 
   ASSERT_TRUE(
-      MS.select({"--target=thumbv7em-none-unknown-eabihf", "-mfpu=fpv4-sp-d16"},
-                Selected, TheDriver));
+      MS.select(TheDriver,
+                {"--target=thumbv7em-none-unknown-eabihf", "-mfpu=fpv4-sp-d16"},
+                Selected));
   EXPECT_EQ("/thumb/v7e-m/fpv4_sp_d16", Selected.back().gccSuffix());
 
-  ASSERT_TRUE(
-      MS.select({"--target=thumbv7em-none-unknown-eabihf", "-mfpu=fpv5-d16"},
-                Selected, TheDriver));
+  ASSERT_TRUE(MS.select(
+      TheDriver, {"--target=thumbv7em-none-unknown-eabihf", "-mfpu=fpv5-d16"},
+      Selected));
   EXPECT_EQ("/thumb/v7e-m/fpv5_d16", Selected.back().gccSuffix());
 
-  ASSERT_TRUE(MS.select({"--target=thumbv8m.main-none-unknown-eabihf"},
-                        Selected, TheDriver));
+  ASSERT_TRUE(MS.select(
+      TheDriver, {"--target=thumbv8m.main-none-unknown-eabihf"}, Selected));
   EXPECT_EQ("/thumb/v8-m.main/fp", Selected.back().gccSuffix());
 
-  ASSERT_TRUE(MS.select({"--target=thumbv8.1m.main-none-unknown-eabihf"},
-                        Selected, TheDriver));
+  ASSERT_TRUE(MS.select(
+      TheDriver, {"--target=thumbv8.1m.main-none-unknown-eabihf"}, Selected));
   EXPECT_EQ("/thumb/v8.1-m.main/fp", Selected.back().gccSuffix());
 
-  ASSERT_TRUE(MS.select({"--target=thumbv8.1m.main-none-unknown-eabihf",
+  ASSERT_TRUE(MS.select(TheDriver,
+                        {"--target=thumbv8.1m.main-none-unknown-eabihf",
                          "-mfpu=none", "-march=thumbv8.1m.main+dsp+mve"},
-                        Selected, TheDriver));
+                        Selected));
   EXPECT_EQ("/thumb/v8.1-m.main/nofp/mve", Selected.back().gccSuffix());
 }

>From 625e89e856f5f57ba222c710e49e6cc6aa0f9b90 Mon Sep 17 00:00:00 2001
From: Simon Tatham <simon.tatham at arm.com>
Date: Tue, 27 Aug 2024 16:51:29 +0100
Subject: [PATCH 3/3] fixup: avoid using %T/some-subdir-name

I'd copied the framework of this test from one of the existing ones,
and was caught out by the existing test using a deprecated lit feature.
---
 .../baremetal-multilib-custom-error.yaml      | 24 +++++++++----------
 1 file changed, 12 insertions(+), 12 deletions(-)

diff --git a/clang/test/Driver/baremetal-multilib-custom-error.yaml b/clang/test/Driver/baremetal-multilib-custom-error.yaml
index e8f4ddfca5b333..c006bb4072ce2f 100644
--- a/clang/test/Driver/baremetal-multilib-custom-error.yaml
+++ b/clang/test/Driver/baremetal-multilib-custom-error.yaml
@@ -1,35 +1,35 @@
 # REQUIRES: shell
 # UNSUPPORTED: system-windows
 
-# RUN: rm -rf %T/baremetal_multilib
-# RUN: mkdir -p %T/baremetal_multilib/bin
-# RUN: mkdir -p %T/baremetal_multilib/lib/clang-runtimes/arm-none-eabi/thumb/v8-m.main/fp/lib
-# RUN: touch %T/baremetal_multilib/lib/clang-runtimes/arm-none-eabi/thumb/v8-m.main/fp/lib/libclang_rt.builtins.a
-# RUN: ln -s %clang %T/baremetal_multilib/bin/clang
-# RUN: ln -s %s %T/baremetal_multilib/lib/clang-runtimes/multilib.yaml
-
-# RUN: %T/baremetal_multilib/bin/clang -no-canonical-prefixes -print-multi-directory 2>&1 \
+# RUN: rm -rf %t
+# RUN: mkdir -p %t/bin
+# RUN: mkdir -p %t/lib/clang-runtimes/arm-none-eabi/thumb/v8-m.main/fp/lib
+# RUN: touch %t/lib/clang-runtimes/arm-none-eabi/thumb/v8-m.main/fp/lib/libclang_rt.builtins.a
+# RUN: ln -s %clang %t/bin/clang
+# RUN: ln -s %s %t/lib/clang-runtimes/multilib.yaml
+
+# RUN: %t/bin/clang -no-canonical-prefixes -print-multi-directory 2>&1 \
 # RUN:     --target=thumbv8m.main-none-eabi -march=armv8.1m.main --sysroot= \
 # RUN:   | FileCheck --check-prefix=CHECK-PRINT-MULTI-DIRECTORY-NOMVE-SOFTFLOAT %s
 # CHECK-PRINT-MULTI-DIRECTORY-NOMVE-SOFTFLOAT: nomve-softfloat
 
-# RUN: not %T/baremetal_multilib/bin/clang -no-canonical-prefixes -print-multi-directory 2>&1 \
+# RUN: not %t/bin/clang -no-canonical-prefixes -print-multi-directory 2>&1 \
 # RUN:     --target=thumbv8m.main-none-eabi -march=armv8.1m.main+mve --sysroot= \
 # RUN:   | FileCheck --check-prefix=CHECK-ERROR %s
 # CHECK-ERROR: multilib configuration error: mve-softfloat is not supported
 
-# RUN: %T/baremetal_multilib/bin/clang -no-canonical-prefixes -print-multi-directory 2>&1 \
+# RUN: %t/bin/clang -no-canonical-prefixes -print-multi-directory 2>&1 \
 # RUN:     --target=thumbv8m.main-none-eabi -march=armv8.1m.main+mve -mfloat-abi=hard --sysroot= \
 # RUN:   | FileCheck --check-prefix=CHECK-PRINT-MULTI-DIRECTORY-MVE-HARDFLOAT %s
 # CHECK-PRINT-MULTI-DIRECTORY-MVE-HARDFLOAT: mve-hardfloat
 
-# RUN: %T/baremetal_multilib/bin/clang -no-canonical-prefixes -print-multi-lib 2>&1 \
+# RUN: %t/bin/clang -no-canonical-prefixes -print-multi-lib 2>&1 \
 # RUN:     --target=arm-none-eabi --sysroot= \
 # RUN:   | FileCheck --check-prefix=CHECK-PRINT-MULTI-LIB %s
 # CHECK-PRINT-MULTI-LIB: nomve-softfloat;@-target=thumbv8.1m.main-unknown-none-eabi
 # CHECK-PRINT-MULTI-LIB-NEXT: mve-hardfloat;@-target=thumbv8.1m.main-unknown-none-eabihf at march=thumbv8.1m.main+mve at mfloat-abi=hard
 
-# RUN: %T/baremetal_multilib/bin/clang -no-canonical-prefixes -print-multi-directory 2>&1 \
+# RUN: %t/bin/clang -no-canonical-prefixes -print-multi-directory 2>&1 \
 # RUN:     --target=arm-none-eabi --sysroot= \
 # RUN:   | FileCheck --check-prefix=CHECK-NO-MATCH-WARNING %s
 # CHECK-NO-MATCH-WARNING: clang: note: available multilibs are:



More information about the cfe-commits mailing list