Author: Fangrui Song
Date: 2026-10-08T23:14:26-07:00
New Revision: 16dae0f25275c01fd11c787797c2a546f51f208d

URL: 
https://github.com/llvm/llvm-project/commit/16dae0f25275c01fd11c787797c2a546f51f208d
DIFF: 
https://github.com/llvm/llvm-project/commit/16dae0f25275c01fd11c787797c2a546f51f208d.diff

LOG: [Passes] Port -print-pipeline-passes to PassesOptions (#230220)

-print-pipeline-passes takes an optional value (=text or =tree). Add
FlagOrEnumField, an EnumField whose bare option assigns a given
enumerator and never consumes the next argument, as cl::ValueOptional
does. BoolField and OptionalBoolField use the same BareValue.

clang, flang, LTO, llc, and opt read the format through
PassBuilder::getPrintPipelinePasses() instead of the exported cl::opt.

Aided by Opus 5.5

Added: 
    

Modified: 
    clang/lib/CodeGen/BackendUtil.cpp
    flang/lib/Frontend/FrontendActions.cpp
    llvm/docs/CommandLine.md
    llvm/include/llvm/Option/LibraryOptions.td
    llvm/include/llvm/Passes/PassBuilder.h
    llvm/lib/LTO/LTOBackend.cpp
    llvm/lib/Option/LibraryOptions.cpp
    llvm/lib/Passes/PassBuilder.cpp
    llvm/lib/Passes/PassesOptions.h
    llvm/lib/Passes/PassesOptions.td
    llvm/tools/llc/lib/NewPMDriver.cpp
    llvm/tools/opt/NewPMDriver.cpp
    llvm/unittests/Option/LibraryOptionsTest.cpp
    llvm/unittests/Option/LibraryOpts.td
    llvm/utils/TableGen/Basic/OptionParserEmitter.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/CodeGen/BackendUtil.cpp 
b/clang/lib/CodeGen/BackendUtil.cpp
index 531e53b3329254..1803c7943b326c 100644
--- a/clang/lib/CodeGen/BackendUtil.cpp
+++ b/clang/lib/CodeGen/BackendUtil.cpp
@@ -1185,7 +1185,7 @@ void EmitAssemblyHelper::RunOptimizationPipeline(
   // This should be done for both clang and flang simultaneously.
   // Print a textual, '-passes=' compatible, representation of pipeline if
   // requested.
-  if (PrintPipelinePasses) {
+  if (PB.getPrintPipelinePasses()) {
     MPM.printPipeline(outs(), [&PIC](StringRef ClassName) {
       auto PassName = PIC.getPassNameForClassName(ClassName);
       return PassName.empty() ? ClassName : PassName;

diff  --git a/flang/lib/Frontend/FrontendActions.cpp 
b/flang/lib/Frontend/FrontendActions.cpp
index 06d67e9417bc44..b8b8b426dfe86d 100644
--- a/flang/lib/Frontend/FrontendActions.cpp
+++ b/flang/lib/Frontend/FrontendActions.cpp
@@ -1108,7 +1108,7 @@ void 
CodeGenAction::runOptimizationPipeline(llvm::raw_pwrite_stream &os) {
   // Print a textual, '-passes=' compatible, representation of pipeline if
   // requested. In this case, don't run the passes. This mimics the behavior of
   // clang.
-  if (llvm::PrintPipelinePasses) {
+  if (pb.getPrintPipelinePasses()) {
     mpm.printPipeline(llvm::outs(), [&pic](llvm::StringRef className) {
       auto passName = pic.getPassNameForClassName(className);
       return passName.empty() ? className : passName;

diff  --git a/llvm/docs/CommandLine.md b/llvm/docs/CommandLine.md
index bdb25833caf735..5e3941881f9935 100644
--- a/llvm/docs/CommandLine.md
+++ b/llvm/docs/CommandLine.md
@@ -1588,6 +1588,7 @@ The `BoolField` is set by `-enable-foo` or 
`-enable-foo=true|false|1|0`.
 A `ValueField`, of an integer type, `float`, `double`, or `StringRef`, is set 
by `-foo-threshold=8` or `-foo-threshold 8`.
 An `OptionalBoolField` is a `BoolOrDefault` that stays `Default` unless the 
option is given, replacing `cl::boolOrDefault`; read it with `valueOr(X, 
Default)`.
 An `EnumField` maps each of its comma-separated values to an enumerator, 
replacing `cl::values`: `defm : EnumField<"foo-mode", "FooMode", 
"FooMode::Fast", "fast,safe", ["FooMode::Fast", "FooMode::Safe"], "The mode">;` 
accepts `-foo-mode=fast` and `-foo-mode=safe`.
+A `FlagOrEnumField` takes one more argument, the enumerator the bare option 
selects, replacing `cl::ValueOptional`: with `"FooMode::Fast"`, `-foo-mode` 
sets `FooMode::Fast`, and `-foo-mode safe` does not consume `safe`.
 A `DefaultOnOffField` is a `BoolOrDefault` set by `=Default`, `=Enable`, or 
`=Disable`.
 Both accept `--` for `-`.
 Only `-help-hidden` lists the options, like `cl::Hidden`.

diff  --git a/llvm/include/llvm/Option/LibraryOptions.td 
b/llvm/include/llvm/Option/LibraryOptions.td
index 6a38d87fc13f0c..54e0b540152a7c 100644
--- a/llvm/include/llvm/Option/LibraryOptions.td
+++ b/llvm/include/llvm/Option/LibraryOptions.td
@@ -29,6 +29,15 @@ class Field<string name, string type, code default> {
   code FieldDefault = default;
 }
 
+// The value a FlagOrEq row assigns when given without one.
+class BareValue<code value> { code BareValue = value; }
+
+// The comma-separated <values> of an enum row, which map in order to the C++
+// <enumerators>.
+class EnumValues<string values, list<code> enumerators>
+    : Values<values>, NormalizedValues<enumerators>,
+      MetaVarName<"<"#!subst(",", "|", values)#">">;
+
 // A bool member set by -<name> or -<name>=<true|false|1|0>.
 multiclass BoolField<string name, code default, string help> {
   def NAME : FlagOrEq<["-", "--"], name>, Field<NAME, "bool", default>,
@@ -49,8 +58,16 @@ multiclass OptionalBoolField<string name, string help> {
 multiclass EnumField<string name, string type, code default, string values,
                      list<code> enumerators, string help> {
   def NAME : SeparateOrEq<["-", "--"], name>, Field<NAME, type, default>,
-    Values<values>, NormalizedValues<enumerators>,
-    MetaVarName<"<"#!subst(",", "|", values)#">">, HelpText<help>;
+    EnumValues<values, enumerators>, HelpText<help>;
+}
+
+// An EnumField that -<name> alone sets to <bare>; <default> applies when the
+// option is absent. -<name> doesn't consume the next argument.
+multiclass FlagOrEnumField<string name, string type, code default,
+                           string values, list<code> enumerators, code bare,
+                           string help> {
+  def NAME : FlagOrEq<["-", "--"], name>, Field<NAME, type, default>,
+    EnumValues<values, enumerators>, BareValue<bare>, HelpText<help>;
 }
 
 // A BoolOrDefault member, Default unless -<name>=Enable or -<name>=Disable is

diff  --git a/llvm/include/llvm/Passes/PassBuilder.h 
b/llvm/include/llvm/Passes/PassBuilder.h
index 245725f13ed8a4..502dfd93842bea 100644
--- a/llvm/include/llvm/Passes/PassBuilder.h
+++ b/llvm/include/llvm/Passes/PassBuilder.h
@@ -106,6 +106,11 @@ class PipelineTuningOptions {
   bool DevirtualizeSpeculatively;
 };
 
+enum class PrintPipelinePassesFormat {
+  Text,
+  Tree,
+};
+
 /// This class provides access to building LLVM's passes.
 ///
 /// Its members provide the baseline state available to passes during their
@@ -417,6 +422,11 @@ class PassBuilder {
   /// Print pass names.
   LLVM_ABI void printPassNames(raw_ostream &OS);
 
+  /// The format -print-pipeline-passes requests, or std::nullopt if it is not
+  /// given.
+  LLVM_ABI std::optional<PrintPipelinePassesFormat>
+  getPrintPipelinePasses() const;
+
   /// Register a callback for a default optimizer pipeline extension
   /// point
   ///
@@ -1030,23 +1040,6 @@ class NoOpLoopAnalysis : public 
AnalysisInfoMixin<NoOpLoopAnalysis> {
   }
 };
 
-enum class PrintPipelinePassesFormat {
-  Text,
-  Tree,
-};
-
-struct PrintPipelinePassesFormatParser
-    : public cl::parser<std::optional<PrintPipelinePassesFormat>> {
-  using cl::parser<std::optional<PrintPipelinePassesFormat>>::parser;
-  LLVM_ABI bool parse(cl::Option &O, StringRef ArgName, StringRef ArgValue,
-                      std::optional<PrintPipelinePassesFormat> &Val);
-};
-
-/// Common option used by multiple tools to print pipeline passes
-LLVM_ABI extern cl::opt<std::optional<PrintPipelinePassesFormat>, false,
-                        PrintPipelinePassesFormatParser>
-    PrintPipelinePasses;
-
 LLVM_ABI void printFormattedPipelinePasses(
     raw_ostream &OS, StringRef Pipeline,
     PrintPipelinePassesFormat Format = PrintPipelinePassesFormat::Text);

diff  --git a/llvm/lib/LTO/LTOBackend.cpp b/llvm/lib/LTO/LTOBackend.cpp
index 1136d50e056559..13b5e6e93335dc 100644
--- a/llvm/lib/LTO/LTOBackend.cpp
+++ b/llvm/lib/LTO/LTOBackend.cpp
@@ -378,7 +378,7 @@ static void runNewPMPasses(const Config &Conf, Module &Mod, 
TargetMachine *TM,
   if (!Conf.DisableVerify)
     MPM.addPass(VerifierPass());
 
-  if (PrintPipelinePasses) {
+  if (PB.getPrintPipelinePasses()) {
     std::string PipelineStr;
     raw_string_ostream OS(PipelineStr);
     MPM.printPipeline(OS, [&PIC](StringRef ClassName) {

diff  --git a/llvm/lib/Option/LibraryOptions.cpp 
b/llvm/lib/Option/LibraryOptions.cpp
index 3f54c850ad726a..6bba23a66262f0 100644
--- a/llvm/lib/Option/LibraryOptions.cpp
+++ b/llvm/lib/Option/LibraryOptions.cpp
@@ -24,11 +24,12 @@ void LibraryOptionsParser::forEachOption(
     unsigned Kind = T.getOptionKind(ID);
     if (Kind != Option::FlagOrEqClass && Kind != Option::SeparateOrEqClass)
       continue;
+    StringRef V = T.getOptionMetaVar(ID);
     std::string MetaVar;
-    if (Kind == Option::SeparateOrEqClass) {
-      StringRef V = T.getOptionMetaVar(ID);
+    if (Kind == Option::SeparateOrEqClass)
       MetaVar = ("=" + (V.empty() ? StringRef("<value>") : V)).str();
-    }
+    else if (!V.empty())
+      MetaVar = ("[=" + V + "]").str();
     Fn(T.getOptionName(ID), MetaVar, T.getOptionHelpText(ID));
   }
 }

diff  --git a/llvm/lib/Passes/PassBuilder.cpp b/llvm/lib/Passes/PassBuilder.cpp
index 4f973196eb951e..96d18057a594d4 100644
--- a/llvm/lib/Passes/PassBuilder.cpp
+++ b/llvm/lib/Passes/PassBuilder.cpp
@@ -219,7 +219,6 @@
 #include "llvm/Passes/OptimizationLevel.h"
 #include "llvm/Passes/TriggerCrashPasses.h"
 #include "llvm/Support/CodeGen.h"
-#include "llvm/Support/CommandLine.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/Error.h"
 #include "llvm/Support/ErrorHandling.h"
@@ -425,32 +424,9 @@
 
 using namespace llvm;
 
-cl::opt<std::optional<PrintPipelinePassesFormat>, false,
-        PrintPipelinePassesFormatParser>
-    llvm::PrintPipelinePasses(
-        "print-pipeline-passes", cl::ValueOptional,
-        cl::desc(
-            "Print string describing the pipeline (best-effort only).\n"
-            "  - =text\tPrint a '-passes' compatible string describing the "
-            "pipeline.\n"
-            "  - =tree\tPrint a tree-like structure describing the 
pipeline."));
-
-bool PrintPipelinePassesFormatParser::parse(
-    cl::Option &O, StringRef ArgName, StringRef Arg,
-    std::optional<PrintPipelinePassesFormat> &Val) {
-  std::optional<PrintPipelinePassesFormat> Format =
-      StringSwitch<std::optional<PrintPipelinePassesFormat>>(Arg)
-          .Case("text", PrintPipelinePassesFormat::Text)
-          .Case("", PrintPipelinePassesFormat::Text)
-          .Case("tree", PrintPipelinePassesFormat::Tree)
-          .Default(std::nullopt);
-
-  if (!Format)
-    return O.error(formatv(
-        "'{0}' value invalid for print-pipeline-passes argument!", Arg));
-
-  Val = Format;
-  return false;
+std::optional<PrintPipelinePassesFormat>
+PassBuilder::getPrintPipelinePasses() const {
+  return Opts.print_pipeline_passes;
 }
 
 void llvm::printFormattedPipelinePasses(raw_ostream &OS, StringRef Pipeline,

diff  --git a/llvm/lib/Passes/PassesOptions.h b/llvm/lib/Passes/PassesOptions.h
index 5fa83efdd9f0fe..5e434e5d25d17c 100644
--- a/llvm/lib/Passes/PassesOptions.h
+++ b/llvm/lib/Passes/PassesOptions.h
@@ -10,6 +10,7 @@
 #define LLVM_LIB_PASSES_PASSESOPTIONS_H
 
 #include "llvm/Analysis/InlineAdvisor.h"
+#include "llvm/Passes/PassBuilder.h"
 #include "llvm/Transforms/IPO/Attributor.h"
 
 #define OPTIONS_STRUCT_DECL

diff  --git a/llvm/lib/Passes/PassesOptions.td 
b/llvm/lib/Passes/PassesOptions.td
index add8c5c04165d8..b303cb8b73bae0 100644
--- a/llvm/lib/Passes/PassesOptions.td
+++ b/llvm/lib/Passes/PassesOptions.td
@@ -10,6 +10,13 @@ include "llvm/Option/LibraryOptions.td"
 
 def PassesOptions : OptionsStruct;
 
+// PassBuilder.cpp
+defm : FlagOrEnumField<"print-pipeline-passes",
+  "std::optional<PrintPipelinePassesFormat>", "std::nullopt", "text,tree",
+  ["PrintPipelinePassesFormat::Text", "PrintPipelinePassesFormat::Tree"],
+  "PrintPipelinePassesFormat::Text",
+  "Print string describing the pipeline (best-effort only): =text for a 
'-passes' compatible string, =tree for a tree-like structure">;
+
 // PassBuilderPipelines.cpp
 defm : EnumField<"attributor-enable", "AttributorRunOption", 
"AttributorRunOption::NONE",
   "full,light,module,module-light,cgscc,cgscc-light,none",

diff  --git a/llvm/tools/llc/lib/NewPMDriver.cpp 
b/llvm/tools/llc/lib/NewPMDriver.cpp
index 3eac9bd15355e0..5b9bcef40224dc 100644
--- a/llvm/tools/llc/lib/NewPMDriver.cpp
+++ b/llvm/tools/llc/lib/NewPMDriver.cpp
@@ -182,14 +182,15 @@ int llvm::compileModuleWithNewPM(
   }
 
   // If user only wants to print the pipeline, print it before parsing the MIR.
-  if (PrintPipelinePasses) {
+  if (std::optional<PrintPipelinePassesFormat> Format =
+          PB.getPrintPipelinePasses()) {
     std::string PipelineStr;
     raw_string_ostream OS(PipelineStr);
     MPM.printPipeline(OS, [&PIC](StringRef ClassName) {
       auto PassName = PIC.getPassNameForClassName(ClassName);
       return PassName.empty() ? ClassName : PassName;
     });
-    printFormattedPipelinePasses(outs(), PipelineStr, *PrintPipelinePasses);
+    printFormattedPipelinePasses(outs(), PipelineStr, *Format);
     outs() << '\n';
     return 0;
   }

diff  --git a/llvm/tools/opt/NewPMDriver.cpp b/llvm/tools/opt/NewPMDriver.cpp
index e19dc61e772a31..2dd062f8d2c9c0 100644
--- a/llvm/tools/opt/NewPMDriver.cpp
+++ b/llvm/tools/opt/NewPMDriver.cpp
@@ -571,14 +571,15 @@ bool llvm::runPassPipeline(
 
   // Print a textual, '-passes=' compatible, representation of pipeline if
   // requested.
-  if (PrintPipelinePasses) {
+  if (std::optional<PrintPipelinePassesFormat> Format =
+          PB.getPrintPipelinePasses()) {
     std::string Pipeline;
     raw_string_ostream SOS(Pipeline);
     MPM.printPipeline(SOS, [&PIC](StringRef ClassName) {
       auto PassName = PIC.getPassNameForClassName(ClassName);
       return PassName.empty() ? ClassName : PassName;
     });
-    printFormattedPipelinePasses(outs(), Pipeline, *PrintPipelinePasses);
+    printFormattedPipelinePasses(outs(), Pipeline, *Format);
     outs() << "\n";
 
     if (!DisablePipelineVerification) {

diff  --git a/llvm/unittests/Option/LibraryOptionsTest.cpp 
b/llvm/unittests/Option/LibraryOptionsTest.cpp
index 073a1c96adc7f4..46d638fa583092 100644
--- a/llvm/unittests/Option/LibraryOptionsTest.cpp
+++ b/llvm/unittests/Option/LibraryOptionsTest.cpp
@@ -36,6 +36,7 @@ TEST(LibraryOptionsTest, Apply) {
   EXPECT_EQ(O.limit, std::nullopt);
   EXPECT_EQ(O.mode, test::Mode::A);
   EXPECT_EQ(O.override, BoolOrDefault::Default);
+  EXPECT_EQ(O.print, std::nullopt);
   EXPECT_EQ(O.ratio, 0.5);
   EXPECT_EQ(O.tristate, BoolOrDefault::Default);
   EXPECT_EQ(O.Path, "p");
@@ -71,16 +72,22 @@ TEST(LibraryOptionsTest, Apply) {
   EXPECT_EQ(O.tristate, BoolOrDefault::True);
   EXPECT_THAT(Apply({"-lib-tristate=Default"}), testing::Each(true));
   EXPECT_EQ(O.tristate, BoolOrDefault::Default);
+  EXPECT_THAT(Apply({"-lib-print=a"}), testing::Each(true));
+  EXPECT_EQ(O.print, test::Mode::A);
+  EXPECT_THAT(Apply({"-lib-print"}), testing::Each(true));
+  EXPECT_EQ(O.print, test::Mode::B);
 
   // A rejected value leaves the member unchanged.
-  EXPECT_THAT(Apply({"-lib-enable=2", "-lib-count=-1", "-lib-limit=x",
-                     "-lib-mode=c", "-lib-override=y", "-lib-ratio=y"}),
-              testing::Each(false));
+  EXPECT_THAT(
+      Apply({"-lib-enable=2", "-lib-count=-1", "-lib-limit=x", "-lib-mode=c",
+             "-lib-override=y", "-lib-print=c", "-lib-ratio=y"}),
+      testing::Each(false));
   EXPECT_TRUE(O.enable);
   EXPECT_EQ(O.count, 7u);
   EXPECT_EQ(O.limit, 0u);
   EXPECT_EQ(O.mode, test::Mode::B);
   EXPECT_EQ(O.override, BoolOrDefault::False);
+  EXPECT_EQ(O.print, test::Mode::B);
   EXPECT_EQ(O.ratio, 0.25);
 }
 
@@ -102,13 +109,14 @@ TEST(LibraryOptionsTest, Parser) {
   P.forEachOption([&](StringRef Spelling, StringRef MetaVar, StringRef Help) {
     Rows.push_back((Spelling + "|" + MetaVar + "|" + Help).str());
   });
-  EXPECT_THAT(Rows,
-              testing::ElementsAre(
-                  "lib-count|=<value>|An unsigned", "lib-enable||A bool",
-                  "lib-limit|=<value>|An optional", "lib-mode|=<a|b>|An enum",
-                  "lib-override||An optional bool",
-                  "lib-path|=<value>|A string", "lib-ratio|=<value>|A double",
-                  "lib-tristate|=<Default|Enable|Disable>|A tri-state"));
+  EXPECT_THAT(
+      Rows,
+      testing::ElementsAre(
+          "lib-count|=<value>|An unsigned", "lib-enable||A bool",
+          "lib-limit|=<value>|An optional", "lib-mode|=<a|b>|An enum",
+          "lib-override||An optional bool", "lib-path|=<value>|A string",
+          "lib-print|[=<a|b>]|A flag or enum", "lib-ratio|=<value>|A double",
+          "lib-tristate|=<Default|Enable|Disable>|A tri-state"));
 
   auto Parse = [&](std::initializer_list<const char *> Argv) {
     unsigned Consumed = 0;
@@ -124,6 +132,7 @@ TEST(LibraryOptionsTest, Parser) {
   EXPECT_EQ(Parse({"-lib-other"}), "1 unknown argument '-lib-other'");
   EXPECT_EQ(Parse({"-lib-counts=1"}), "1 unknown argument '-lib-counts=1'");
   EXPECT_EQ(Parse({"-lib-enable", "0"}), "1 ");
+  EXPECT_EQ(Parse({"-lib-print", "a"}), "1 ");
   EXPECT_EQ(Parse({"-lib-count", "x"}),
             "2 invalid value 'x' in '-lib-count=x'");
   EXPECT_EQ(Parse({"-lib-enable=x"}), "1 invalid value 'x' in 
'-lib-enable=x'");

diff  --git a/llvm/unittests/Option/LibraryOpts.td 
b/llvm/unittests/Option/LibraryOpts.td
index 50d282ebccb50c..5fabf7718cfc54 100644
--- a/llvm/unittests/Option/LibraryOpts.td
+++ b/llvm/unittests/Option/LibraryOpts.td
@@ -17,6 +17,9 @@ defm : ValueField<"lib-limit", "std::optional<unsigned>", 
"std::nullopt",
 defm : EnumField<"lib-mode", "test::Mode", "test::Mode::A", "a,b",
   ["test::Mode::A", "test::Mode::B"], "An enum">;
 defm : OptionalBoolField<"lib-override", "An optional bool">;
+defm : FlagOrEnumField<"lib-print", "std::optional<test::Mode>", 
"std::nullopt",
+  "a,b", ["test::Mode::A", "test::Mode::B"], "test::Mode::B",
+  "A flag or enum">;
 defm : ValueField<"lib-ratio", "double", "0.5", "A double">;
 defm : DefaultOnOffField<"lib-tristate", "A tri-state">;
 defm Path : ValueField<"lib-path", "StringRef", "\"p\"", "A string">;

diff  --git a/llvm/utils/TableGen/Basic/OptionParserEmitter.cpp 
b/llvm/utils/TableGen/Basic/OptionParserEmitter.cpp
index 33b4be58580fb2..23b73ee3d9f2f0 100644
--- a/llvm/utils/TableGen/Basic/OptionParserEmitter.cpp
+++ b/llvm/utils/TableGen/Basic/OptionParserEmitter.cpp
@@ -283,8 +283,9 @@ static void emitOptionsStruct(const Record &Struct,
       PrintFatalError(R->getLoc(),
                       "a member is set by a FlagOrEq or SeparateOrEq");
     StringRef Type = R->getValueAsString("FieldType");
-    if (Kind == "FlagOrEq" && Type != "bool" && Type != "llvm::BoolOrDefault")
-      PrintFatalError(R->getLoc(), "a FlagOrEq sets a bool member");
+    if (Kind == "FlagOrEq" && Type != "bool" && Type != "llvm::BoolOrDefault" 
&&
+        !R->getValue("BareValue"))
+      PrintFatalError(R->getLoc(), "a FlagOrEq sets a bool or has a 
BareValue");
     Fields.push_back(R);
   }
   // Members in declaration order.
@@ -344,6 +345,9 @@ static void emitOptionsStruct(const Record &Struct,
   for (const Record *R : Fields) {
     OS << "  case OPT_" << getStructOptionID(*R) << ":\n";
     std::string Member = getMemberName(*R, Prefix);
+    if (R->getValue("BareValue"))
+      OS << "    if (!A.getNumValues()) { " << Member << " = "
+         << R->getValueAsString("BareValue") << "; return true; }\n";
     if (!isa<UnsetInit>(R->getValueInit("NormalizedValues"))) {
       SmallVector<StringRef> Values;
       R->getValueAsString("Values").split(Values, ',');


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

Reply via email to