llvmorg-github-actions[bot] wrote:

<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-llvm-ir

@llvm/pr-subscribers-clang-codegen

Author: Fangrui Song (MaskRay)

<details>
<summary>Changes</summary>

`OptionsStruct&lt;..., perContext = true&gt;` lets each LLVMContext hold its
own values of a library's options, so that two contexts in one process
can compile with different values. The static member `Global` becomes
private, and readers call `Ctx.getLibraryOptions().get&lt;T&gt;()`, which
returns the context's copy, (temporary fallback) or `Global` if it has
none. InstCombine is the first such library.

The new cl::parseCommandLineOptions sets per-context libraries' options
in the given cl::LibraryOptionsContext instead of Global. opt parses
into its LLVMContext; clang -cc1 parses -mllvm into its CompilerInstance
and replays the arguments into each code generation LLVMContext. An
embedder calls set({"-x=v"}), which dispatches through the cl::
registry.

https://discourse.llvm.org/t/rfc-declare-library-command-line-options-in-tablegen-one-struct-per-library/91877
LLM-aided

---

Patch is 38.39 KiB, truncated to 20.00 KiB below, full version: 
https://github.com/llvm/llvm-project/pull/231407.diff


25 Files Affected:

- (modified) clang/include/clang/Frontend/CompilerInstance.h (+9) 
- (modified) clang/lib/CIR/FrontendAction/CIRGenAction.cpp (+2) 
- (modified) clang/lib/CodeGen/CodeGenAction.cpp (+2) 
- (modified) clang/lib/Frontend/CompilerInstance.cpp (+3-2) 
- (added) clang/test/CIR/CodeGen/mllvm-library-options.c (+17) 
- (added) clang/test/CodeGen/mllvm-library-options.ll (+21) 
- (modified) llvm/include/llvm/IR/LLVMContext.h (+7) 
- (modified) llvm/include/llvm/Option/LibraryOptions.h (+23-13) 
- (modified) llvm/include/llvm/Option/LibraryOptions.td (+3-1) 
- (modified) llvm/include/llvm/Support/CommandLine.h (+30-5) 
- (added) llvm/include/llvm/Support/LibraryOptionsContext.h (+64) 
- (modified) llvm/lib/IR/LLVMContext.cpp (+4) 
- (modified) llvm/lib/IR/LLVMContextImpl.h (+3) 
- (modified) llvm/lib/Option/LibraryOptions.cpp (+2-2) 
- (modified) llvm/lib/Support/CommandLine.cpp (+82-21) 
- (modified) llvm/lib/Transforms/InstCombine/InstCombineCLOptions.td (+1-1) 
- (modified) llvm/lib/Transforms/InstCombine/InstructionCombining.cpp (+3-1) 
- (modified) llvm/tools/opt/optdriver.cpp (+4-4) 
- (modified) llvm/unittests/IR/CMakeLists.txt (+2) 
- (added) llvm/unittests/IR/LibraryOptionsContextTest.cpp (+69) 
- (modified) llvm/unittests/Option/LibraryOptionsTest.cpp (+49-7) 
- (modified) llvm/unittests/Support/CommandLineTest.cpp (+3-1) 
- (modified) llvm/utils/TableGen/Basic/OptionParserEmitter.cpp (+11-4) 
- (modified) llvm/utils/gn/secondary/llvm/unittests/IR/BUILD.gn (+2) 
- (modified) utils/bazel/llvm-project-overlay/llvm/unittests/BUILD.bazel (+1) 


``````````diff
diff --git a/clang/include/clang/Frontend/CompilerInstance.h 
b/clang/include/clang/Frontend/CompilerInstance.h
index b87dd037480d6..bceb85f6e923b 100644
--- a/clang/include/clang/Frontend/CompilerInstance.h
+++ b/clang/include/clang/Frontend/CompilerInstance.h
@@ -26,6 +26,7 @@
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Support/BuryPointer.h"
 #include "llvm/Support/FileSystem.h"
+#include "llvm/Support/LibraryOptionsContext.h"
 #include "llvm/Support/VirtualFileSystem.h"
 #include "llvm/Support/VirtualOutputBackend.h"
 #include <cassert>
@@ -147,6 +148,10 @@ class CompilerInstance : public ModuleLoader {
   /// The frontend timer.
   std::unique_ptr<llvm::Timer> FrontendTimer;
 
+  /// The -mllvm options of per-context libraries, which every LLVMContext that
+  /// compiles for this instance receives.
+  llvm::cl::LibraryOptionsContext LibraryOptions;
+
   /// The ASTReader, if one exists.
   IntrusiveRefCntPtr<ASTReader> TheASTReader;
 
@@ -269,6 +274,10 @@ class CompilerInstance : public ModuleLoader {
   /// This should be called after plugins are loaded and before ExecuteAction.
   void parseLLVMArgs();
 
+  const llvm::cl::LibraryOptionsContext &getLibraryOptions() const {
+    return LibraryOptions;
+  }
+
   /// @}
   /// @name Compiler Invocation and Options
   /// @{
diff --git a/clang/lib/CIR/FrontendAction/CIRGenAction.cpp 
b/clang/lib/CIR/FrontendAction/CIRGenAction.cpp
index 71a7a17146af3..a04aa51e163af 100644
--- a/clang/lib/CIR/FrontendAction/CIRGenAction.cpp
+++ b/clang/lib/CIR/FrontendAction/CIRGenAction.cpp
@@ -35,6 +35,7 @@
 #include "llvm/IR/LLVMContext.h"
 #include "llvm/IR/Module.h"
 #include "llvm/Linker/Linker.h"
+#include "llvm/Support/LibraryOptionsContext.h"
 #include "llvm/Support/MemoryBuffer.h"
 #include "llvm/Support/Path.h"
 #include "llvm/Support/raw_ostream.h"
@@ -367,6 +368,7 @@ CIRGenAction::CIRGenAction(OutputType Act, 
mlir::MLIRContext *MLIRCtx)
 CIRGenAction::~CIRGenAction() { MLIRMod.release(); }
 
 bool CIRGenAction::BeginSourceFileAction(CompilerInstance &CI) {
+  cantFail(Ctx->getLibraryOptions().set(CI.getLibraryOptions().args()));
   if (clang::loadLinkModules(CI, *Ctx, LinkModules))
     return false;
   return ASTFrontendAction::BeginSourceFileAction(CI);
diff --git a/clang/lib/CodeGen/CodeGenAction.cpp 
b/clang/lib/CodeGen/CodeGenAction.cpp
index 1abd8b0455a19..22925cc55f495 100644
--- a/clang/lib/CodeGen/CodeGenAction.cpp
+++ b/clang/lib/CodeGen/CodeGenAction.cpp
@@ -42,6 +42,7 @@
 #include "llvm/LTO/LTOBackend.h"
 #include "llvm/Linker/Linker.h"
 #include "llvm/Pass.h"
+#include "llvm/Support/LibraryOptionsContext.h"
 #include "llvm/Support/ManagedStatic.h"
 #include "llvm/Support/MemoryBuffer.h"
 #include "llvm/Support/Mutex.h"
@@ -366,6 +367,7 @@ CodeGenerator *CodeGenAction::getCodeGenerator() const {
 }
 
 bool CodeGenAction::BeginSourceFileAction(CompilerInstance &CI) {
+  cantFail(VMContext->getLibraryOptions().set(CI.getLibraryOptions().args()));
   if (CI.getFrontendOpts().GenReducedBMI)
     CI.getLangOpts().setCompilingModule(LangOptions::CMK_ModuleInterface);
   return ASTFrontendAction::BeginSourceFileAction(CI);
diff --git a/clang/lib/Frontend/CompilerInstance.cpp 
b/clang/lib/Frontend/CompilerInstance.cpp
index b09c9a9f5a5be..f122208d6b4c8 100644
--- a/clang/lib/Frontend/CompilerInstance.cpp
+++ b/clang/lib/Frontend/CompilerInstance.cpp
@@ -1143,8 +1143,9 @@ void CompilerInstance::parseLLVMArgs() {
     for (unsigned i = 0; i != NumArgs; ++i)
       Args[i + 1] = getFrontendOpts().LLVMArgs[i].c_str();
     Args[NumArgs + 1] = nullptr;
-    llvm::cl::ParseCommandLineOptions(NumArgs + 1, Args.get(), /*Overview=*/"",
-                                      /*Errs=*/nullptr,
+    llvm::cl::parseCommandLineOptions(LibraryOptions,
+                                      ArrayRef(Args.get(), NumArgs + 1),
+                                      /*Overview=*/"", /*Errs=*/nullptr,
                                       /*VFS=*/&getVirtualFileSystem());
   }
 }
diff --git a/clang/test/CIR/CodeGen/mllvm-library-options.c 
b/clang/test/CIR/CodeGen/mllvm-library-options.c
new file mode 100644
index 0000000000000..4f584b4058a81
--- /dev/null
+++ b/clang/test/CIR/CodeGen/mllvm-library-options.c
@@ -0,0 +1,17 @@
+// -mllvm options of per-context libraries reach the LLVMContext that CIR is
+// lowered into.
+// RUN: %clang_cc1 -triple x86_64 -O1 -fclangir -emit-llvm %s -o - | FileCheck 
%s --check-prefixes=CHECK,SINK
+// RUN: %clang_cc1 -triple x86_64 -O1 -fclangir -emit-llvm -mllvm 
-instcombine-code-sinking=0 %s -o - | FileCheck %s --check-prefixes=CHECK,NOSINK
+
+void use(int);
+
+// CHECK-LABEL: define {{.*}} @f(
+// SINK-NOT:      sdiv
+// NOSINK:        sdiv
+// CHECK:         br i1
+// SINK:          sdiv
+void f(int c, int a, int b) {
+  int d = a / b;
+  if (c)
+    use(d);
+}
diff --git a/clang/test/CodeGen/mllvm-library-options.ll 
b/clang/test/CodeGen/mllvm-library-options.ll
new file mode 100644
index 0000000000000..a4938f811537c
--- /dev/null
+++ b/clang/test/CodeGen/mllvm-library-options.ll
@@ -0,0 +1,21 @@
+;; -mllvm options of per-context libraries reach the LLVMContext that compiles.
+; RUN: %clang_cc1 -O1 -emit-llvm %s -o - | FileCheck %s 
--check-prefixes=CHECK,SINK
+; RUN: %clang_cc1 -O1 -emit-llvm -mllvm -instcombine-code-sinking=0 %s -o - | 
FileCheck %s --check-prefixes=CHECK,NOSINK
+
+; CHECK-LABEL: define {{.*}} @f(
+; NOSINK-NEXT: entry:
+; NOSINK-NEXT:  = sdiv
+; CHECK:       {{^}}t:
+; SINK-NEXT:     = sdiv
+define void @f(i1 %c, i32 %a, i32 %b) {
+entry:
+  %d = sdiv i32 %a, %b
+  br i1 %c, label %t, label %e
+t:
+  call void @use(i32 %d)
+  ret void
+e:
+  ret void
+}
+
+declare void @use(i32)
diff --git a/llvm/include/llvm/IR/LLVMContext.h 
b/llvm/include/llvm/IR/LLVMContext.h
index ced9b9227538e..be0d27bacf3e4 100644
--- a/llvm/include/llvm/IR/LLVMContext.h
+++ b/llvm/include/llvm/IR/LLVMContext.h
@@ -32,6 +32,9 @@ class Instruction;
 class LLVMContextImpl;
 class Module;
 class OptPassGate;
+namespace cl {
+class LibraryOptionsContext;
+} // namespace cl
 template <typename T> class SmallVectorImpl;
 template <typename T> class StringMapEntry;
 class StringRef;
@@ -329,6 +332,10 @@ class LLVMContext {
   /// LLVMContext is used by compilation.
   LLVM_ABI void setOptPassGate(OptPassGate &);
 
+  /// The library options this context reads in place of their process-wide
+  /// values.
+  LLVM_ABI cl::LibraryOptionsContext &getLibraryOptions() const;
+
   /// Get or set the current "default" target CPU (target-cpu function
   /// attribute). The intent is that compiler frontends will set this to a 
value
   /// that reflects the attribute that a function would get "by default" 
without
diff --git a/llvm/include/llvm/Option/LibraryOptions.h 
b/llvm/include/llvm/Option/LibraryOptions.h
index 8b5c34525fa7c..19df88f77e586 100644
--- a/llvm/include/llvm/Option/LibraryOptions.h
+++ b/llvm/include/llvm/Option/LibraryOptions.h
@@ -27,6 +27,7 @@
 #include "llvm/Support/Compiler.h"
 #include <optional>
 #include <type_traits>
+#include <utility>
 
 namespace llvm {
 namespace opt {
@@ -118,23 +119,36 @@ class LLVM_ABI LibraryOptTable : public OptTable {
   ~LibraryOptTable() override;
 };
 
-/// Connects an options struct to cl::ParseCommandLineOptions.
+/// Connects options struct T to cl::ParseCommandLineOptions and
+/// cl::LibraryOptionsContext.
 class LLVM_ABI LibraryOptionsParser final : public cl::LibraryOptions {
 public:
-  using ApplyFn = bool (*)(const Arg &, BumpPtrAllocator &);
-  using TableFn = const OptTable &(*)();
-  LibraryOptionsParser(TableFn Table, ApplyFn Apply, void (*Reset)())
-      : Table(Table), Apply(Apply), Reset(Reset) {}
+  template <typename T>
+  explicit LibraryOptionsParser(std::in_place_type_t<T>)
+      : LibraryOptions(T::PerContext), Table(T::optTable), Global(&T::Global),
+        Apply([](void *Opts, const Arg &A, BumpPtrAllocator &Alloc) {
+          return static_cast<T *>(Opts)->apply(A, Alloc);
+        }),
+        Copy([](BumpPtrAllocator &Alloc) -> void * {
+          return new (Alloc) T(T::Global);
+        }),
+        Reset([] { T::Global = T(); }) {}
 
   void forEachOption(
       function_ref<void(StringRef, StringRef, StringRef)> Fn) const override;
-  Error parse(ArrayRef<const char *> Args, unsigned &Consumed,
+  Error parse(void *Opts, ArrayRef<const char *> Args, unsigned &Consumed,
               BumpPtrAllocator &Alloc) override;
+  void *global() override { return Global; }
+  void *copyGlobal(BumpPtrAllocator &Alloc) const override {
+    return Copy(Alloc);
+  }
   void reset() override { Reset(); }
 
 private:
-  TableFn Table;
-  ApplyFn Apply;
+  const OptTable &(*Table)();
+  void *Global;
+  bool (*Apply)(void *Opts, const Arg &A, BumpPtrAllocator &Alloc);
+  void *(*Copy)(BumpPtrAllocator &Alloc);
   void (*Reset)();
 };
 
@@ -144,11 +158,7 @@ class LLVM_ABI LibraryOptionsParser final : public 
cl::LibraryOptions {
 template <typename T> class RegisterLibraryOptions {
   static_assert(std::is_trivially_destructible_v<T>,
                 "an options struct must not need an exit-time destructor");
-  LibraryOptionsParser Parser{T::optTable,
-                              [](const Arg &A, BumpPtrAllocator &Alloc) {
-                                return T::Global.apply(A, Alloc);
-                              },
-                              [] { T::Global = T(); }};
+  LibraryOptionsParser Parser{std::in_place_type<T>};
 
 public:
   RegisterLibraryOptions() { cl::addLibraryOptions(Parser); }
diff --git a/llvm/include/llvm/Option/LibraryOptions.td 
b/llvm/include/llvm/Option/LibraryOptions.td
index d901f8027f702..ab027c056831e 100644
--- a/llvm/include/llvm/Option/LibraryOptions.td
+++ b/llvm/include/llvm/Option/LibraryOptions.td
@@ -17,9 +17,11 @@
 include "llvm/Option/OptParser.td"
 
 // A row whose spelling starts with prefix names its member without it.
-class OptionsStruct<string namespace = "llvm", string prefix = ""> {
+// perContext makes Global private; read through 
cl::LibraryOptionsContext::get.
+class OptionsStruct<string namespace = "llvm", string prefix = "", bit 
perContext = false> {
   string Namespace = namespace;
   string MemberPrefix = prefix;
+  bit PerContext = perContext;
 }
 
 // The builds an option exists in, as a preprocessor expression.
diff --git a/llvm/include/llvm/Support/CommandLine.h 
b/llvm/include/llvm/Support/CommandLine.h
index bc7059244461e..1b3e3745ce724 100644
--- a/llvm/include/llvm/Support/CommandLine.h
+++ b/llvm/include/llvm/Support/CommandLine.h
@@ -50,6 +50,8 @@ class Error;
 /// It is intentionally a short name to make qualified usage concise.
 namespace cl {
 
+class LibraryOptionsContext;
+
 
//===----------------------------------------------------------------------===//
 // Command line option processing entry point.
 //
@@ -70,6 +72,15 @@ LLVM_ABI bool ParseCommandLineOptions(int argc, const char 
*const *argv,
                                       vfs::FileSystem *VFS = nullptr,
                                       const char *EnvVar = nullptr);
 
+// Like ParseCommandLineOptions, but sets the library registered options
+// as per-context in LibraryOptions rather than in their global().
+LLVM_ABI bool parseCommandLineOptions(LibraryOptionsContext &LibraryOptions,
+                                      ArrayRef<const char *> Args,
+                                      StringRef Overview = "",
+                                      raw_ostream *Errs = nullptr,
+                                      vfs::FileSystem *VFS = nullptr,
+                                      const char *EnvVar = nullptr);
+
 // Function pointer type for printing version information.
 using VersionPrinterTy = std::function<void(raw_ostream &)>;
 
@@ -2176,18 +2187,32 @@ class LLVM_ABI LibraryOptions {
           Fn) const = 0;
 
   /// Parses the option spelled by Args[0], which may take Args[1] as its
-  /// value, and sets \p Consumed to the number of arguments it spans. The
-  /// strings in \p Args and the memory from \p Alloc remain valid until
-  /// reset().
-  virtual Error parse(ArrayRef<const char *> Args, unsigned &Consumed,
-                      BumpPtrAllocator &Alloc) = 0;
+  /// value, into \p Opts, which is global() or a copy of it, and sets
+  /// \p Consumed to the number of arguments it spans. The strings in \p Args
+  /// and the memory from \p Alloc remain valid as long as \p Opts is used.
+  virtual Error parse(void *Opts, ArrayRef<const char *> Args,
+                      unsigned &Consumed, BumpPtrAllocator &Alloc) = 0;
+
+  /// Returns the values that ParseCommandLineOptions sets.
+  virtual void *global() = 0;
+
+  /// Returns a copy of global() allocated from \p Alloc.
+  virtual void *copyGlobal(BumpPtrAllocator &Alloc) const = 0;
 
   /// Restores the default values.
   virtual void reset() = 0;
 
+  /// Whether every reader of the options goes through a context's
+  /// LibraryOptionsContext, so that they need not be set in global().
+  bool isPerContext() const { return PerContext; }
+
 protected:
+  explicit LibraryOptions(bool PerContext = false) : PerContext(PerContext) {}
   // Registrations are static and never destroyed through this class.
   ~LibraryOptions() = default;
+
+private:
+  bool PerContext;
 };
 
 /// Makes ParseCommandLineOptions recognize \p L's options. A name that is also
diff --git a/llvm/include/llvm/Support/LibraryOptionsContext.h 
b/llvm/include/llvm/Support/LibraryOptionsContext.h
new file mode 100644
index 0000000000000..150a8c1d5a771
--- /dev/null
+++ b/llvm/include/llvm/Support/LibraryOptionsContext.h
@@ -0,0 +1,64 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_LIBRARYOPTIONSCONTEXT_H
+#define LLVM_SUPPORT_LIBRARYOPTIONSCONTEXT_H
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/Allocator.h"
+#include "llvm/Support/Compiler.h"
+
+namespace llvm {
+
+class Error;
+
+namespace cl {
+
+class LibraryOptions;
+
+// Values of library options that override their global() in one compilation
+// context, such as an LLVMContext.
+class LLVM_ABI LibraryOptionsContext {
+public:
+  // Sets the library options that Args spell, e.g. {"-x=v"}. A library's 
values
+  // start as a copy of its global(), and later calls add to them. Fails at the
+  // first argument that is not a library option or has an invalid value.
+  //
+  // Strings copied from global() die with ResetAllOptionOccurrences. The first
+  // call (or ParseCommandLineOptions) indexes the registry, which is not
+  // thread-safe.
+  Error set(ArrayRef<const char *> Args);
+
+  // Parses the option of L that Args[0] spells, as set() does.
+  Error parse(LibraryOptions &L, ArrayRef<const char *> Args,
+              unsigned &Consumed);
+
+  // The arguments set so far, for replaying into another context.
+  ArrayRef<const char *> args() const { return Args; }
+
+  // T's values, or T::Global if there are none.
+  template <typename T> const T &get() const {
+    if (const void *Opts = Values.lookup(&T::Global))
+      return *static_cast<const T *>(Opts);
+    // TODO: Return the defaults once cl::ParseCommandLineOptions callers have
+    // migrated to parseCommandLineOptions and no longer set T::Global.
+    return T::Global;
+  }
+
+private:
+  DenseMap<const void *, void *> Values;
+  SmallVector<const char *, 0> Args;
+  BumpPtrAllocator Alloc;
+};
+
+} // namespace cl
+} // namespace llvm
+
+#endif // LLVM_SUPPORT_LIBRARYOPTIONSCONTEXT_H
diff --git a/llvm/lib/IR/LLVMContext.cpp b/llvm/lib/IR/LLVMContext.cpp
index 1fcdd3bc4c142..fb3b4bd8b206f 100644
--- a/llvm/lib/IR/LLVMContext.cpp
+++ b/llvm/lib/IR/LLVMContext.cpp
@@ -357,6 +357,10 @@ void LLVMContext::setOptPassGate(OptPassGate& OPG) {
   pImpl->setOptPassGate(OPG);
 }
 
+cl::LibraryOptionsContext &LLVMContext::getLibraryOptions() const {
+  return pImpl->LibraryOptions;
+}
+
 const DiagnosticHandler *LLVMContext::getDiagHandlerPtr() const {
   return pImpl->DiagHandler.get();
 }
diff --git a/llvm/lib/IR/LLVMContextImpl.h b/llvm/lib/IR/LLVMContextImpl.h
index 74a73664473b0..d02d57e4c0197 100644
--- a/llvm/lib/IR/LLVMContextImpl.h
+++ b/llvm/lib/IR/LLVMContextImpl.h
@@ -40,6 +40,7 @@
 #include "llvm/IR/Value.h"
 #include "llvm/Support/Allocator.h"
 #include "llvm/Support/Casting.h"
+#include "llvm/Support/LibraryOptionsContext.h"
 #include "llvm/Support/StringSaver.h"
 #include <algorithm>
 #include <cassert>
@@ -1951,6 +1952,8 @@ class LLVMContextImpl {
   std::string DefaultTargetCPU;
   std::string DefaultTargetFeatures;
 
+  cl::LibraryOptionsContext LibraryOptions;
+
   /// The next available source atom group number. The front end is responsible
   /// for assigning source atom numbers, but certain optimisations need to
   /// assign new group numbers to a set of instructions. Most often code
diff --git a/llvm/lib/Option/LibraryOptions.cpp 
b/llvm/lib/Option/LibraryOptions.cpp
index cfcb82273eb6d..e5848a0498f23 100644
--- a/llvm/lib/Option/LibraryOptions.cpp
+++ b/llvm/lib/Option/LibraryOptions.cpp
@@ -34,7 +34,7 @@ void LibraryOptionsParser::forEachOption(
   }
 }
 
-Error LibraryOptionsParser::parse(ArrayRef<const char *> Args,
+Error LibraryOptionsParser::parse(void *Opts, ArrayRef<const char *> Args,
                                   unsigned &Consumed, BumpPtrAllocator &Alloc) 
{
   InputArgList List(Args.begin(), Args.end());
   Consumed = 0;
@@ -45,7 +45,7 @@ Error LibraryOptionsParser::parse(ArrayRef<const char *> Args,
                              "' requires an argument");
   if (A->getOption().getKind() == Option::UnknownClass)
     return createStringError("unknown argument '" + Twine(Args[0]) + "'");
-  if (!Apply(*A, Alloc))
+  if (!Apply(Opts, *A, Alloc))
     return createStringError("invalid value '" + Twine(A->getValue()) +
                              "' in '" + A->getAsString(List) + "'");
   return Error::success();
diff --git a/llvm/lib/Support/CommandLine.cpp b/llvm/lib/Support/CommandLine.cpp
index 1cb5fccb07a1b..31f07e114cace 100644
--- a/llvm/lib/Support/CommandLine.cpp
+++ b/llvm/lib/Support/CommandLine.cpp
@@ -35,6 +35,7 @@
 #include "llvm/Support/Error.h"
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/FileSystem.h"
+#include "llvm/Support/LibraryOptionsContext.h"
 #include "llvm/Support/ManagedStatic.h"
 #include "llvm/Support/MemoryBuffer.h"
 #include "llvm/Support/Path.h"
@@ -189,7 +190,8 @@ class CommandLineParser {
 
   bool ParseCommandLineOptions(int argc, const char *const *argv,
                                StringRef Overview, raw_ostream *Errs = nullptr,
-                               vfs::FileSystem *VFS = nullptr);
+                               vfs::FileSystem *VFS = nullptr,
+                               LibraryOptionsContext *Context = nullptr);
 
   void forEachSubCommand(Option &Opt, function_ref<void(SubCommand &)> Action) 
{
     if (Opt.Subs.empty()) {
@@ -440,6 +442,26 @@ static CommandLineParser &globalParser() {
   return *GlobalParser;
 }
 
+// Parses the library option spelled by Args[0], which takes at most one
+// separate value, into Opts. Opts may refer to the arguments, so they are
+// copied into Alloc, and appended to Record if given.
+static Error
+parseLibraryOption(LibraryOptions &L, void *Opts, ArrayRef<const char *> Args,
+                   unsigned &Consumed, BumpPtrAllocator &Alloc,
+                   SmallVectorImpl<const char *> *Record = nullptr) {
+  StringSaver Saver(Alloc);
+  const char *Saved[2];
+  unsigned NumArgs = std::min<size_t>(Args.size(), 2);
+  for (unsigned J = 0; J != NumArgs; ++J)
+    Saved[J] = Saver.save(Args[J]).data();
+  Consumed = 1;
+  if (Error E = L.parse(Opts, ArrayRef(Saved, NumArgs), Consumed, Alloc))
+    return E;
+  if (Record)
+    Record->append(Saved, Saved + Consumed);
+  return Error::success();
+}
+
 template <typename T, T TrueVal, T FalseVal>
 static bool parseBool(Option &O, StringRef ArgName, StringRef Arg, T &Value) {
   // ProvideOption passes a null Arg for a bare -flag (treated as true) and an
@@ -1424,14 +1446,15 @@ Error ExpansionContext::readConfigFile(StringRef 
CfgFile,
 }
 
 static void ...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/231407
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to