[llvm-branch-commits] [clang] [Multilib] Custom flags processing for library selection (PR #110659)

Victor Campos via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Tue Nov 5 07:12:41 PST 2024


https://github.com/vhscampos updated https://github.com/llvm/llvm-project/pull/110659

>From f2525efdd1f70c59923220b787be005903bdced5 Mon Sep 17 00:00:00 2001
From: Victor Campos <victor.campos at arm.com>
Date: Thu, 26 Sep 2024 14:44:33 +0100
Subject: [PATCH 1/3] [Multilib] Custom flags processing for library selection

Select library variants in the multilib system using the flags passed
following the '-fmultilib-flag=' format.

Multilib flags that were not passed in the command-line have their
default value fed into the library selection mechanism.

A warning is shown if the flag's value name is invalid. If the wrong
name is close enough to any valid one, according to edit distance, the
closest valid value name is suggested.

Details about this change can be found in this thread:
https://discourse.llvm.org/t/rfc-multilib-custom-flags/81058
---
 .../clang/Basic/DiagnosticDriverKinds.td      |   6 +
 clang/include/clang/Driver/Multilib.h         |   3 +
 clang/lib/Driver/Driver.cpp                   |   4 +-
 clang/lib/Driver/Multilib.cpp                 | 137 +++++++++++++++++-
 .../baremetal-multilib-custom-flags.yaml      |  57 ++++++++
 5 files changed, 201 insertions(+), 6 deletions(-)
 create mode 100644 clang/test/Driver/baremetal-multilib-custom-flags.yaml

diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td b/clang/include/clang/Basic/DiagnosticDriverKinds.td
index 65551bd7761a9d..6874614557f837 100644
--- a/clang/include/clang/Basic/DiagnosticDriverKinds.td
+++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td
@@ -14,6 +14,12 @@ def err_drv_no_such_file_with_suggestion : Error<
 def err_drv_unsupported_opt : Error<"unsupported option '%0'">;
 def err_drv_unsupported_opt_with_suggestion : Error<
   "unsupported option '%0'; did you mean '%1'?">;
+def warn_drv_unsupported_opt : Warning<
+  "unsupported option '%0'">,
+  InGroup<UnusedCommandLineArgument>;
+def warn_drv_unsupported_opt_with_suggestion : Warning<
+  "unsupported option '%0'; did you mean '%1'?">,
+  InGroup<UnusedCommandLineArgument>;
 def err_drv_unsupported_opt_for_target : Error<
   "unsupported option '%0' for target '%1'">;
 def err_drv_unsupported_opt_for_language_mode : Error<
diff --git a/clang/include/clang/Driver/Multilib.h b/clang/include/clang/Driver/Multilib.h
index 0662feb114c796..d0a3dd827e3531 100644
--- a/clang/include/clang/Driver/Multilib.h
+++ b/clang/include/clang/Driver/Multilib.h
@@ -163,6 +163,9 @@ class MultilibSet {
   const_iterator begin() const { return Multilibs.begin(); }
   const_iterator end() const { return Multilibs.end(); }
 
+  Multilib::flags_list
+  processCustomFlags(const Driver &D, const Multilib::flags_list &Flags) const;
+
   /// Select compatible variants, \returns false if none are compatible
   bool select(const Driver &D, const Multilib::flags_list &Flags,
               llvm::SmallVectorImpl<Multilib> &) const;
diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp
index 9878a9dad78d40..cee10d36070616 100644
--- a/clang/lib/Driver/Driver.cpp
+++ b/clang/lib/Driver/Driver.cpp
@@ -2324,9 +2324,7 @@ bool Driver::HandleImmediateArgs(Compilation &C) {
   }
 
   if (C.getArgs().hasArg(options::OPT_print_multi_lib)) {
-    for (const Multilib &Multilib : TC.getMultilibs())
-      if (!Multilib.isError())
-        llvm::outs() << Multilib << "\n";
+    llvm::outs() << TC.getMultilibs();
     return false;
   }
 
diff --git a/clang/lib/Driver/Multilib.cpp b/clang/lib/Driver/Multilib.cpp
index 236074478e7d84..adabf21057eb35 100644
--- a/clang/lib/Driver/Multilib.cpp
+++ b/clang/lib/Driver/Multilib.cpp
@@ -12,6 +12,7 @@
 #include "clang/Driver/Driver.h"
 #include "llvm/ADT/DenseSet.h"
 #include "llvm/ADT/SmallSet.h"
+#include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Support/Compiler.h"
 #include "llvm/Support/Error.h"
@@ -95,9 +96,113 @@ MultilibSet &MultilibSet::FilterOut(FilterCallback F) {
 
 void MultilibSet::push_back(const Multilib &M) { Multilibs.push_back(M); }
 
+static void WarnUnclaimedMultilibCustomFlags(
+    const Driver &D, const SmallVector<StringRef> &UnclaimedCustomFlagValues,
+    const SmallVector<custom_flag::CustomFlagDeclarationPtr> &CustomFlagDecls) {
+  struct EditDistanceInfo {
+    StringRef FlagValue;
+    unsigned EditDistance;
+  };
+  const unsigned MaxEditDistance = 5;
+
+  for (StringRef Unclaimed : UnclaimedCustomFlagValues) {
+    std::optional<EditDistanceInfo> BestCandidate;
+    for (const auto &Decl : CustomFlagDecls) {
+      for (const auto &Value : Decl->ValueList) {
+        const std::string &FlagValueName = Value.Name;
+        unsigned EditDistance =
+            Unclaimed.edit_distance(FlagValueName, /*AllowReplacements=*/true,
+                                    /*MaxEditDistance=*/MaxEditDistance);
+        if (!BestCandidate || (EditDistance <= MaxEditDistance &&
+                               EditDistance < BestCandidate->EditDistance)) {
+          BestCandidate = {FlagValueName, EditDistance};
+        }
+      }
+    }
+    if (!BestCandidate)
+      D.Diag(clang::diag::warn_drv_unsupported_opt)
+          << (custom_flag::Prefix + Unclaimed).str();
+    else
+      D.Diag(clang::diag::warn_drv_unsupported_opt_with_suggestion)
+          << (custom_flag::Prefix + Unclaimed).str()
+          << (custom_flag::Prefix + BestCandidate->FlagValue).str();
+  }
+}
+
+namespace clang::driver::custom_flag {
+class ValueNameToDetailMap {
+  SmallVector<std::pair<StringRef, const CustomFlagValueDetail *>> Mapping;
+
+public:
+  template <typename It>
+  ValueNameToDetailMap(It FlagDeclsBegin, It FlagDeclsEnd) {
+    for (auto DeclIt = FlagDeclsBegin; DeclIt != FlagDeclsEnd; ++DeclIt) {
+      const CustomFlagDeclarationPtr &Decl = *DeclIt;
+      for (const auto &Value : Decl->ValueList)
+        Mapping.emplace_back(Value.Name, &Value);
+    }
+  }
+
+  const CustomFlagValueDetail *get(StringRef Key) const {
+    auto Iter = llvm::find_if(
+        Mapping, [&](const auto &Pair) { return Pair.first == Key; });
+    return Iter != Mapping.end() ? Iter->second : nullptr;
+  }
+};
+} // namespace clang::driver::custom_flag
+
+Multilib::flags_list
+MultilibSet::processCustomFlags(const Driver &D,
+                                const Multilib::flags_list &Flags) const {
+  Multilib::flags_list Result;
+  SmallVector<const custom_flag::CustomFlagValueDetail *>
+      ClaimedCustomFlagValues;
+  SmallVector<StringRef> UnclaimedCustomFlagValueStrs;
+
+  const auto ValueNameToValueDetail = custom_flag::ValueNameToDetailMap(
+      CustomFlagDecls.begin(), CustomFlagDecls.end());
+
+  for (StringRef Flag : Flags) {
+    if (!Flag.starts_with(custom_flag::Prefix)) {
+      Result.push_back(Flag.str());
+      continue;
+    }
+
+    StringRef CustomFlagValueStr = Flag.substr(custom_flag::Prefix.size());
+    const custom_flag::CustomFlagValueDetail *Detail =
+        ValueNameToValueDetail.get(CustomFlagValueStr);
+    if (Detail)
+      ClaimedCustomFlagValues.push_back(Detail);
+    else
+      UnclaimedCustomFlagValueStrs.push_back(CustomFlagValueStr);
+  }
+
+  llvm::SmallSet<custom_flag::CustomFlagDeclarationPtr, 32>
+      TriggeredCustomFlagDecls;
+
+  for (auto *CustomFlagValue : llvm::reverse(ClaimedCustomFlagValues)) {
+    if (!TriggeredCustomFlagDecls.insert(CustomFlagValue->Decl).second)
+      continue;
+    Result.push_back(std::string(custom_flag::Prefix) + CustomFlagValue->Name);
+  }
+
+  for (const auto &Decl : CustomFlagDecls) {
+    if (TriggeredCustomFlagDecls.contains(Decl))
+      continue;
+    Result.push_back(std::string(custom_flag::Prefix) +
+                     Decl->ValueList[Decl->DefaultValueIdx].Name);
+  }
+
+  WarnUnclaimedMultilibCustomFlags(D, UnclaimedCustomFlagValueStrs,
+                                   CustomFlagDecls);
+
+  return Result;
+}
+
 bool MultilibSet::select(const Driver &D, const Multilib::flags_list &Flags,
                          llvm::SmallVectorImpl<Multilib> &Selected) const {
-  llvm::StringSet<> FlagSet(expandFlags(Flags));
+  Multilib::flags_list FlagsWithCustom = processCustomFlags(D, Flags);
+  llvm::StringSet<> FlagSet(expandFlags(FlagsWithCustom));
   Selected.clear();
   bool AnyErrors = false;
 
@@ -387,8 +492,34 @@ LLVM_DUMP_METHOD void MultilibSet::dump() const {
 }
 
 void MultilibSet::print(raw_ostream &OS) const {
-  for (const auto &M : *this)
-    OS << M << "\n";
+  const auto ValueNameToValueDetail = custom_flag::ValueNameToDetailMap(
+      CustomFlagDecls.begin(), CustomFlagDecls.end());
+
+  for (const auto &M : *this) {
+    if (M.isError())
+      continue;
+    llvm::SmallString<128> Buf;
+    llvm::raw_svector_ostream StrOS(Buf);
+
+    M.print(StrOS);
+
+    for (StringRef Flag : M.flags()) {
+      if (!Flag.starts_with(custom_flag::Prefix))
+        continue;
+
+      StringRef CustomFlagValueStr = Flag.substr(custom_flag::Prefix.size());
+      const custom_flag::CustomFlagValueDetail *Detail =
+          ValueNameToValueDetail.get(CustomFlagValueStr);
+
+      if (!Detail || !Detail->ExtraBuildArgs)
+        continue;
+
+      for (StringRef Arg : *Detail->ExtraBuildArgs)
+        StrOS << '@' << (Arg[0] == '-' ? Arg.substr(1) : Arg);
+    }
+
+    OS << StrOS.str() << '\n';
+  }
 }
 
 raw_ostream &clang::driver::operator<<(raw_ostream &OS, const MultilibSet &MS) {
diff --git a/clang/test/Driver/baremetal-multilib-custom-flags.yaml b/clang/test/Driver/baremetal-multilib-custom-flags.yaml
new file mode 100644
index 00000000000000..3a19951c741247
--- /dev/null
+++ b/clang/test/Driver/baremetal-multilib-custom-flags.yaml
@@ -0,0 +1,57 @@
+# RUN: %clang --multi-lib-config=%s -no-canonical-prefixes -x c %s -### -o /dev/null 2>&1 \
+# RUN:     --target=thumbv8m.main-none-eabi -mfpu=none --sysroot= \
+# RUN:   | FileCheck --check-prefix=CHECK-DEFAULT %s
+
+# CHECK-DEFAULT:      "-cc1" "-triple" "thumbv8m.main-unknown-none-eabi"
+# CHECK-DEFAULT-SAME: "-internal-isystem" "[[SYSROOT:[^"]*]]/bin/../lib/clang-runtimes/arm-none-eabi/thumb/v8-m.main/nofp/include"
+# CHECK-DEFAULT-NEXT: "-L[[SYSROOT]]/bin/../lib/clang-runtimes/arm-none-eabi/thumb/v8-m.main/nofp/lib"
+
+# RUN: %clang --multi-lib-config=%s -no-canonical-prefixes -x c %s -### -o /dev/null 2>&1 \
+# RUN:     --target=thumbv8m.main-none-eabi -mfpu=none -fmultilib-flag=no-multithreaded --sysroot= \
+# RUN:   | FileCheck --check-prefix=CHECK-NOMULTI %s
+
+# CHECK-NOMULTI:      "-cc1" "-triple" "thumbv8m.main-unknown-none-eabi"
+# CHECK-NOMULTI-SAME: "-internal-isystem" "[[SYSROOT:[^"]*]]/bin/../lib/clang-runtimes/arm-none-eabi/thumb/v8-m.main/nofp/include"
+# CHECK-NOMULTI-NEXT: "-L[[SYSROOT]]/bin/../lib/clang-runtimes/arm-none-eabi/thumb/v8-m.main/nofp/lib"
+
+# RUN: %clang --multi-lib-config=%s -no-canonical-prefixes -x c %s -### -o /dev/null 2>&1 \
+# RUN:     --target=thumbv8m.main-none-eabi -mfpu=none -fmultilib-flag=multithreaded --sysroot= \
+# RUN:   | FileCheck --check-prefix=CHECK-MULTI %s
+
+# CHECK-MULTI:      "-cc1" "-triple" "thumbv8m.main-unknown-none-eabi"
+# CHECK-MULTI-SAME: "-internal-isystem" "[[SYSROOT:[^"]*]]/bin/../lib/clang-runtimes/arm-none-eabi/multithreaded/thumb/v8-m.main/nofp/include"
+# CHECK-MULTI-NEXT: "-L[[SYSROOT]]/bin/../lib/clang-runtimes/arm-none-eabi/multithreaded/thumb/v8-m.main/nofp/lib"
+
+# RUN: %clang --multi-lib-config=%s -no-canonical-prefixes -x c %s -### -o /dev/null 2>&1 \
+# RUN:     --target=thumbv8m.main-none-eabi -mfpu=none -fmultilib-flag=singlethreaded -fmultilib-flag=no-io --sysroot= \
+# RUN:   | FileCheck --check-prefix=CHECK-WARNING %s
+# CHECK-WARNING-DAG: warning: unsupported option '-fmultilib-flag=singlethreaded'
+# CHECK-WARNING-DAG: warning: unsupported option '-fmultilib-flag=no-io'; did you mean '-fmultilib-flag=io-none'?
+
+---
+MultilibVersion: 1.0
+
+Groups:
+- Name: stdlib
+  Type: Exclusive
+
+Variants:
+- Dir: arm-none-eabi/thumb/v8-m.main/nofp
+  Flags: [--target=thumbv8m.main-unknown-none-eabi, -mfpu=none, -fmultilib-flag=no-multithreaded]
+  Group: stdlib
+- Dir: arm-none-eabi/multithreaded/thumb/v8-m.main/nofp
+  Flags: [--target=thumbv8m.main-unknown-none-eabi, -mfpu=none, -fmultilib-flag=multithreaded]
+  Group: stdlib
+
+Flags:
+  - Name: multithreading
+    Values:
+    - Name: no-multithreaded
+    - Name: multithreaded
+    Default: no-multithreaded
+  - Name: io
+    Values:
+    - Name: io-none
+    - Name: io-semihosting
+    - Name: io-linux-syscalls
+    Default: io-none
\ No newline at end of file

>From b5af73aa03a755c07fd11cb4402724504141f786 Mon Sep 17 00:00:00 2001
From: Victor Campos <victor.campos at arm.com>
Date: Mon, 4 Nov 2024 15:40:39 +0000
Subject: [PATCH 2/3] Address comments

- Replaced warnings by errors as suggested.
- Added comments to the more intricate parts.
---
 .../clang/Basic/DiagnosticDriverKinds.td      |  6 ---
 clang/lib/Driver/Multilib.cpp                 | 44 ++++++++++++-------
 .../baremetal-multilib-custom-flags.yaml      |  8 ++--
 3 files changed, 32 insertions(+), 26 deletions(-)

diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td b/clang/include/clang/Basic/DiagnosticDriverKinds.td
index 6874614557f837..65551bd7761a9d 100644
--- a/clang/include/clang/Basic/DiagnosticDriverKinds.td
+++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td
@@ -14,12 +14,6 @@ def err_drv_no_such_file_with_suggestion : Error<
 def err_drv_unsupported_opt : Error<"unsupported option '%0'">;
 def err_drv_unsupported_opt_with_suggestion : Error<
   "unsupported option '%0'; did you mean '%1'?">;
-def warn_drv_unsupported_opt : Warning<
-  "unsupported option '%0'">,
-  InGroup<UnusedCommandLineArgument>;
-def warn_drv_unsupported_opt_with_suggestion : Warning<
-  "unsupported option '%0'; did you mean '%1'?">,
-  InGroup<UnusedCommandLineArgument>;
 def err_drv_unsupported_opt_for_target : Error<
   "unsupported option '%0' for target '%1'">;
 def err_drv_unsupported_opt_for_language_mode : Error<
diff --git a/clang/lib/Driver/Multilib.cpp b/clang/lib/Driver/Multilib.cpp
index adabf21057eb35..08b08a8c87eda5 100644
--- a/clang/lib/Driver/Multilib.cpp
+++ b/clang/lib/Driver/Multilib.cpp
@@ -96,9 +96,9 @@ MultilibSet &MultilibSet::FilterOut(FilterCallback F) {
 
 void MultilibSet::push_back(const Multilib &M) { Multilibs.push_back(M); }
 
-static void WarnUnclaimedMultilibCustomFlags(
+static void DiagnoseUnclaimedMultilibCustomFlags(
     const Driver &D, const SmallVector<StringRef> &UnclaimedCustomFlagValues,
-    const SmallVector<custom_flag::CustomFlagDeclarationPtr> &CustomFlagDecls) {
+    const SmallVector<custom_flag::DeclarationPtr> &CustomFlagDecls) {
   struct EditDistanceInfo {
     StringRef FlagValue;
     unsigned EditDistance;
@@ -120,30 +120,32 @@ static void WarnUnclaimedMultilibCustomFlags(
       }
     }
     if (!BestCandidate)
-      D.Diag(clang::diag::warn_drv_unsupported_opt)
+      D.Diag(clang::diag::err_drv_unsupported_opt)
           << (custom_flag::Prefix + Unclaimed).str();
     else
-      D.Diag(clang::diag::warn_drv_unsupported_opt_with_suggestion)
+      D.Diag(clang::diag::err_drv_unsupported_opt_with_suggestion)
           << (custom_flag::Prefix + Unclaimed).str()
           << (custom_flag::Prefix + BestCandidate->FlagValue).str();
   }
 }
 
 namespace clang::driver::custom_flag {
+// Map implemented using linear searches as the expected size is too small for
+// the overhead of a search tree or a hash table.
 class ValueNameToDetailMap {
-  SmallVector<std::pair<StringRef, const CustomFlagValueDetail *>> Mapping;
+  SmallVector<std::pair<StringRef, const ValueDetail *>> Mapping;
 
 public:
   template <typename It>
   ValueNameToDetailMap(It FlagDeclsBegin, It FlagDeclsEnd) {
     for (auto DeclIt = FlagDeclsBegin; DeclIt != FlagDeclsEnd; ++DeclIt) {
-      const CustomFlagDeclarationPtr &Decl = *DeclIt;
+      const DeclarationPtr &Decl = *DeclIt;
       for (const auto &Value : Decl->ValueList)
         Mapping.emplace_back(Value.Name, &Value);
     }
   }
 
-  const CustomFlagValueDetail *get(StringRef Key) const {
+  const ValueDetail *get(StringRef Key) const {
     auto Iter = llvm::find_if(
         Mapping, [&](const auto &Pair) { return Pair.first == Key; });
     return Iter != Mapping.end() ? Iter->second : nullptr;
@@ -155,8 +157,12 @@ Multilib::flags_list
 MultilibSet::processCustomFlags(const Driver &D,
                                 const Multilib::flags_list &Flags) const {
   Multilib::flags_list Result;
-  SmallVector<const custom_flag::CustomFlagValueDetail *>
-      ClaimedCustomFlagValues;
+
+  // Custom flag values detected in the flags list
+  SmallVector<const custom_flag::ValueDetail *> ClaimedCustomFlagValues;
+
+  // Arguments to -fmultilib-flag=<arg> that don't correspond to any valid
+  // custom flag value. An error will be printed out for each of these.
   SmallVector<StringRef> UnclaimedCustomFlagValueStrs;
 
   const auto ValueNameToValueDetail = custom_flag::ValueNameToDetailMap(
@@ -169,7 +175,7 @@ MultilibSet::processCustomFlags(const Driver &D,
     }
 
     StringRef CustomFlagValueStr = Flag.substr(custom_flag::Prefix.size());
-    const custom_flag::CustomFlagValueDetail *Detail =
+    const custom_flag::ValueDetail *Detail =
         ValueNameToValueDetail.get(CustomFlagValueStr);
     if (Detail)
       ClaimedCustomFlagValues.push_back(Detail);
@@ -177,24 +183,30 @@ MultilibSet::processCustomFlags(const Driver &D,
       UnclaimedCustomFlagValueStrs.push_back(CustomFlagValueStr);
   }
 
-  llvm::SmallSet<custom_flag::CustomFlagDeclarationPtr, 32>
-      TriggeredCustomFlagDecls;
+  // Set of custom flag declarations for which a value was passed in the flags
+  // list. This is used to, firstly, detect multiple values for the same flag
+  // declaration (in this case, the last one wins), and secondly, to detect
+  // which declarations had no value passed in (in this case, the default value
+  // is selected).
+  llvm::SmallSet<custom_flag::DeclarationPtr, 32> TriggeredCustomFlagDecls;
 
+  // Detect multiple values for the same flag declaration. Last one wins.
   for (auto *CustomFlagValue : llvm::reverse(ClaimedCustomFlagValues)) {
     if (!TriggeredCustomFlagDecls.insert(CustomFlagValue->Decl).second)
       continue;
     Result.push_back(std::string(custom_flag::Prefix) + CustomFlagValue->Name);
   }
 
+  // Detect flag declarations with no value passed in. Select default value.
   for (const auto &Decl : CustomFlagDecls) {
     if (TriggeredCustomFlagDecls.contains(Decl))
       continue;
     Result.push_back(std::string(custom_flag::Prefix) +
-                     Decl->ValueList[Decl->DefaultValueIdx].Name);
+                     Decl->ValueList[*Decl->DefaultValueIdx].Name);
   }
 
-  WarnUnclaimedMultilibCustomFlags(D, UnclaimedCustomFlagValueStrs,
-                                   CustomFlagDecls);
+  DiagnoseUnclaimedMultilibCustomFlags(D, UnclaimedCustomFlagValueStrs,
+                                       CustomFlagDecls);
 
   return Result;
 }
@@ -508,7 +520,7 @@ void MultilibSet::print(raw_ostream &OS) const {
         continue;
 
       StringRef CustomFlagValueStr = Flag.substr(custom_flag::Prefix.size());
-      const custom_flag::CustomFlagValueDetail *Detail =
+      const custom_flag::ValueDetail *Detail =
           ValueNameToValueDetail.get(CustomFlagValueStr);
 
       if (!Detail || !Detail->ExtraBuildArgs)
diff --git a/clang/test/Driver/baremetal-multilib-custom-flags.yaml b/clang/test/Driver/baremetal-multilib-custom-flags.yaml
index 3a19951c741247..a89917b2fa0d87 100644
--- a/clang/test/Driver/baremetal-multilib-custom-flags.yaml
+++ b/clang/test/Driver/baremetal-multilib-custom-flags.yaml
@@ -22,11 +22,11 @@
 # CHECK-MULTI-SAME: "-internal-isystem" "[[SYSROOT:[^"]*]]/bin/../lib/clang-runtimes/arm-none-eabi/multithreaded/thumb/v8-m.main/nofp/include"
 # CHECK-MULTI-NEXT: "-L[[SYSROOT]]/bin/../lib/clang-runtimes/arm-none-eabi/multithreaded/thumb/v8-m.main/nofp/lib"
 
-# RUN: %clang --multi-lib-config=%s -no-canonical-prefixes -x c %s -### -o /dev/null 2>&1 \
+# RUN: not %clang --multi-lib-config=%s -no-canonical-prefixes -x c %s -### -o /dev/null 2>&1 \
 # RUN:     --target=thumbv8m.main-none-eabi -mfpu=none -fmultilib-flag=singlethreaded -fmultilib-flag=no-io --sysroot= \
-# RUN:   | FileCheck --check-prefix=CHECK-WARNING %s
-# CHECK-WARNING-DAG: warning: unsupported option '-fmultilib-flag=singlethreaded'
-# CHECK-WARNING-DAG: warning: unsupported option '-fmultilib-flag=no-io'; did you mean '-fmultilib-flag=io-none'?
+# RUN:   | FileCheck --check-prefix=CHECK-ERROR %s
+# CHECK-ERROR-DAG: error: unsupported option '-fmultilib-flag=singlethreaded'
+# CHECK-ERROR-DAG: error: unsupported option '-fmultilib-flag=no-io'; did you mean '-fmultilib-flag=io-none'?
 
 ---
 MultilibVersion: 1.0

>From 0b76e71fce2742a8eecaea9a354fc9bd824b5656 Mon Sep 17 00:00:00 2001
From: Victor Campos <victor.campos at arm.com>
Date: Tue, 5 Nov 2024 14:55:03 +0000
Subject: [PATCH 3/3] Add test for -print-multi-lib interaction with
 ExtraBuildArgs

---
 clang/test/Driver/baremetal-multilib-custom-flags.yaml | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/clang/test/Driver/baremetal-multilib-custom-flags.yaml b/clang/test/Driver/baremetal-multilib-custom-flags.yaml
index a89917b2fa0d87..99afd70eccf1f1 100644
--- a/clang/test/Driver/baremetal-multilib-custom-flags.yaml
+++ b/clang/test/Driver/baremetal-multilib-custom-flags.yaml
@@ -28,6 +28,11 @@
 # CHECK-ERROR-DAG: error: unsupported option '-fmultilib-flag=singlethreaded'
 # CHECK-ERROR-DAG: error: unsupported option '-fmultilib-flag=no-io'; did you mean '-fmultilib-flag=io-none'?
 
+# RUN: %clang --multi-lib-config=%s -no-canonical-prefixes -x c %s -### -o /dev/null 2>&1 \
+# RUN:     --target=thumbv8m.main-none-eabi -mfpu=none -print-multi-lib --sysroot= \
+# RUN:   | FileCheck --check-prefix=CHECK-PRINT-MULTI-LIB %s
+# CHECK-PRINT-MULTI-LIB: arm-none-eabi/thumb/v8-m.main/nofp;@-target=thumbv8m.main-unknown-none-eabi at mfpu=none at fmultilib-flag=no-multithreaded at D__SINGLE_THREAD__
+# CHECK-PRINT-MULTI-LIB: arm-none-eabi/multithreaded/thumb/v8-m.main/nofp;@-target=thumbv8m.main-unknown-none-eabi at mfpu=none at fmultilib-flag=multithreaded
 ---
 MultilibVersion: 1.0
 
@@ -47,6 +52,7 @@ Flags:
   - Name: multithreading
     Values:
     - Name: no-multithreaded
+      ExtraBuildArgs: [-D__SINGLE_THREAD__]
     - Name: multithreaded
     Default: no-multithreaded
   - Name: io



More information about the llvm-branch-commits mailing list