Skip to content

Commit fb14c98

Browse files
authored
Merge changes to enable -D option to FileCheck (#8256)
A sequence of changes required to 1. implement the -D option to filecheck 6c5d8d2 2. Add error checking to that option 097206d 3. Add prerequisites for 2 implementation and testing 32ef758, 5b211a2, fa9ba20 They are here included in chronological order, which is not the order listed here. A more minimalist option is available, but it would sacrifice testing or error checking and none of these required more than trivial merge resolutions
2 parents 9009fb8 + 627836c commit fb14c98

7 files changed

Lines changed: 867 additions & 163 deletions

File tree

docs/CommandGuide/FileCheck.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,11 @@ OPTIONS
6060
-verify``. With this option FileCheck will verify that input does not contain
6161
warnings not covered by any ``CHECK:`` patterns.
6262

63+
.. option:: -D<VAR=VALUE>
64+
65+
Sets a filecheck variable ``VAR`` with value ``VALUE`` that can be used in
66+
``CHECK:`` lines.
67+
6368
.. option:: -version
6469

6570
Show the version number of this program.

include/llvm/Support/CommandLine.h

Lines changed: 103 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,12 @@
2121
#define LLVM_SUPPORT_COMMANDLINE_H
2222

2323
#include "llvm/ADT/ArrayRef.h"
24+
#include "llvm/ADT/SmallPtrSet.h"
2425
#include "llvm/ADT/SmallVector.h"
2526
#include "llvm/ADT/StringMap.h"
2627
#include "llvm/ADT/Twine.h"
2728
#include "llvm/Support/Compiler.h"
29+
#include "llvm/Support/ManagedStatic.h"
2830
#include <cassert>
2931
#include <climits>
3032
#include <cstdarg>
@@ -44,8 +46,9 @@ namespace cl {
4446
//===----------------------------------------------------------------------===//
4547
// ParseCommandLineOptions - Command line option processing entry point.
4648
//
47-
void ParseCommandLineOptions(int argc, const char *const *argv,
48-
const char *Overview = nullptr);
49+
bool ParseCommandLineOptions(int argc, const char *const *argv,
50+
const char *Overview = nullptr,
51+
bool IgnoreErrors = false);
4952

5053
//===----------------------------------------------------------------------===//
5154
// ParseEnvironmentOptions - Environment variable option processing alternate
@@ -131,6 +134,9 @@ enum OptionHidden { // Control whether -help shows this option
131134
// enabled, and used, the value for the flag comes from the suffix of the
132135
// argument.
133136
//
137+
// AlwaysPrefix - Only allow the behavior enabled by the Prefix flag and reject
138+
// the Option=Value form.
139+
//
134140
// Grouping - With this option enabled, multiple letter options are allowed to
135141
// bunch together with only a single hyphen for the whole group. This allows
136142
// emulation of the behavior that ls uses for example: ls -la === ls -l -a
@@ -140,7 +146,8 @@ enum FormattingFlags {
140146
NormalFormatting = 0x00, // Nothing special
141147
Positional = 0x01, // Is a positional argument, no '-' required
142148
Prefix = 0x02, // Can this option directly prefix its value?
143-
Grouping = 0x03 // Can this option group with other options?
149+
AlwaysPrefix = 0x03, // Can this option only directly prefix its value?
150+
Grouping = 0x04 // Can this option group with other options?
144151
};
145152

146153
enum MiscFlags { // Miscellaneous flags to adjust argument
@@ -171,6 +178,45 @@ class OptionCategory {
171178
// The general Option Category (used as default category).
172179
extern OptionCategory *GeneralCategory; // HLSL Change - GeneralCategory is now a pointer
173180

181+
//===----------------------------------------------------------------------===//
182+
// SubCommand class
183+
//
184+
class SubCommand {
185+
private:
186+
const char *const Name = nullptr;
187+
const char *const Description = nullptr;
188+
189+
protected:
190+
void registerSubCommand();
191+
void unregisterSubCommand();
192+
193+
public:
194+
SubCommand(const char *const Name, const char *const Description = nullptr)
195+
: Name(Name), Description(Description) {
196+
registerSubCommand();
197+
}
198+
SubCommand() {}
199+
200+
void reset();
201+
202+
operator bool() const;
203+
204+
const char *getName() const { return Name; }
205+
const char *getDescription() const { return Description; }
206+
207+
SmallVector<Option *, 4> PositionalOpts;
208+
SmallVector<Option *, 4> SinkOpts;
209+
StringMap<Option *> OptionsMap;
210+
211+
Option *ConsumeAfterOpt = nullptr; // The ConsumeAfter option if it exists.
212+
};
213+
214+
// A special subcommand representing no subcommand
215+
extern ManagedStatic<SubCommand> TopLevelSubCommand;
216+
217+
// A special subcommand that can be used to put an option into all subcommands.
218+
extern ManagedStatic<SubCommand> AllSubCommands;
219+
174220
//===----------------------------------------------------------------------===//
175221
// Option Base class
176222
//
@@ -200,16 +246,17 @@ class Option {
200246
// detail representing the non-value
201247
unsigned Value : 2;
202248
unsigned HiddenFlag : 2; // enum OptionHidden
203-
unsigned Formatting : 2; // enum FormattingFlags
249+
unsigned Formatting : 3; // enum FormattingFlags
204250
unsigned Misc : 3;
205251
unsigned Position; // Position of last occurrence of the option
206252
unsigned AdditionalVals; // Greater than 0 for multi-valued option.
207253

208254
public:
209-
const char *ArgStr; // The argument string itself (ex: "help", "o")
210-
const char *HelpStr; // The descriptive text message for -help
211-
const char *ValueStr; // String describing what the value of this option is
255+
StringRef ArgStr; // The argument string itself (ex: "help", "o")
256+
StringRef HelpStr; // The descriptive text message for -help
257+
StringRef ValueStr; // String describing what the value of this option is
212258
OptionCategory *Category; // The Category this option belongs to
259+
SmallPtrSet<SubCommand *, 4> Subs; // The subcommands this option belongs to.
213260
bool FullyInitialized; // Has addArguemnt been called?
214261

215262
inline enum NumOccurrencesFlag getNumOccurrencesFlag() const {
@@ -229,21 +276,32 @@ class Option {
229276
inline unsigned getNumAdditionalVals() const { return AdditionalVals; }
230277

231278
// hasArgStr - Return true if the argstr != ""
232-
bool hasArgStr() const { return ArgStr[0] != 0; }
279+
bool hasArgStr() const { return !ArgStr.empty(); }
280+
bool isPositional() const { return getFormattingFlag() == cl::Positional; }
281+
bool isSink() const { return getMiscFlags() & cl::Sink; }
282+
bool isConsumeAfter() const {
283+
return getNumOccurrencesFlag() == cl::ConsumeAfter;
284+
}
285+
bool isInAllSubCommands() const {
286+
return std::any_of(Subs.begin(), Subs.end(), [](const SubCommand *SC) {
287+
return SC == &*AllSubCommands;
288+
});
289+
}
233290

234291
//-------------------------------------------------------------------------===
235292
// Accessor functions set by OptionModifiers
236293
//
237-
void setArgStr(const char *S);
238-
void setDescription(const char *S) { HelpStr = S; }
239-
void setValueStr(const char *S) { ValueStr = S; }
294+
void setArgStr(StringRef S);
295+
void setDescription(StringRef S) { HelpStr = S; }
296+
void setValueStr(StringRef S) { ValueStr = S; }
240297
void setNumOccurrencesFlag(enum NumOccurrencesFlag Val) { Occurrences = Val; }
241298
void setValueExpectedFlag(enum ValueExpected Val) { Value = Val; }
242299
void setHiddenFlag(enum OptionHidden Val) { HiddenFlag = Val; }
243300
void setFormattingFlag(enum FormattingFlags V) { Formatting = V; }
244301
void setMiscFlag(enum MiscFlags M) { Misc |= M; }
245302
void setPosition(unsigned pos) { Position = pos; }
246303
void setCategory(OptionCategory &C) { Category = &C; }
304+
void addSubCommand(SubCommand &S) { Subs.insert(&S); }
247305

248306
protected:
249307
explicit Option(enum NumOccurrencesFlag OccurrencesFlag,
@@ -276,7 +334,7 @@ class Option {
276334

277335
virtual void printOptionValue(size_t GlobalWidth, bool Force) const = 0;
278336

279-
virtual void getExtraOptionNames(SmallVectorImpl<const char *> &) {}
337+
virtual void getExtraOptionNames(SmallVectorImpl<StringRef> &) {}
280338

281339
// addOccurrence - Wrapper around handleOccurrence that enforces Flags.
282340
//
@@ -288,6 +346,7 @@ class Option {
288346

289347
public:
290348
inline int getNumOccurrences() const { return NumOccurrences; }
349+
inline void reset() { NumOccurrences = 0; }
291350
virtual ~Option() {}
292351
};
293352

@@ -350,6 +409,14 @@ struct cat {
350409
template <class Opt> void apply(Opt &O) const { O.setCategory(Category); }
351410
};
352411

412+
// sub - Specify the subcommand that this option belongs to.
413+
struct sub {
414+
SubCommand &Sub;
415+
sub(SubCommand &S) : Sub(S) {}
416+
417+
template <class Opt> void apply(Opt &O) const { O.addSubCommand(Sub); }
418+
};
419+
353420
//===----------------------------------------------------------------------===//
354421
// OptionValue class
355422

@@ -606,7 +673,7 @@ class generic_parser_base {
606673

607674
void initialize() {}
608675

609-
void getExtraOptionNames(SmallVectorImpl<const char *> &OptionNames) {
676+
void getExtraOptionNames(SmallVectorImpl<StringRef> &OptionNames) {
610677
// If there has been no argstr specified, that means that we need to add an
611678
// argument for every possible option. This ensures that our options are
612679
// vectored to us.
@@ -722,7 +789,7 @@ class basic_parser_impl { // non-template implementation of basic_parser<t>
722789
return ValueRequired;
723790
}
724791

725-
void getExtraOptionNames(SmallVectorImpl<const char *> &) {}
792+
void getExtraOptionNames(SmallVectorImpl<StringRef> &) {}
726793

727794
void initialize() {}
728795

@@ -1206,8 +1273,7 @@ class opt : public Option,
12061273
enum ValueExpected getValueExpectedFlagDefault() const override {
12071274
return Parser.getValueExpectedFlagDefault();
12081275
}
1209-
void
1210-
getExtraOptionNames(SmallVectorImpl<const char *> &OptionNames) override {
1276+
void getExtraOptionNames(SmallVectorImpl<StringRef> &OptionNames) override {
12111277
return Parser.getExtraOptionNames(OptionNames);
12121278
}
12131279

@@ -1368,8 +1434,7 @@ class list : public Option, public list_storage<DataType, StorageClass> {
13681434
enum ValueExpected getValueExpectedFlagDefault() const override {
13691435
return Parser.getValueExpectedFlagDefault();
13701436
}
1371-
void
1372-
getExtraOptionNames(SmallVectorImpl<const char *> &OptionNames) override {
1437+
void getExtraOptionNames(SmallVectorImpl<StringRef> &OptionNames) override {
13731438
return Parser.getExtraOptionNames(OptionNames);
13741439
}
13751440

@@ -1508,8 +1573,7 @@ class bits : public Option, public bits_storage<DataType, Storage> {
15081573
enum ValueExpected getValueExpectedFlagDefault() const override {
15091574
return Parser.getValueExpectedFlagDefault();
15101575
}
1511-
void
1512-
getExtraOptionNames(SmallVectorImpl<const char *> &OptionNames) override {
1576+
void getExtraOptionNames(SmallVectorImpl<StringRef> &OptionNames) override {
15131577
return Parser.getExtraOptionNames(OptionNames);
15141578
}
15151579

@@ -1593,6 +1657,7 @@ class alias : public Option {
15931657
error("cl::alias must have argument name specified!");
15941658
if (!AliasFor)
15951659
error("cl::alias must have an cl::aliasopt(option) specified!");
1660+
Subs = AliasFor->Subs;
15961661
addArgument();
15971662
}
15981663

@@ -1673,9 +1738,9 @@ void PrintHelpMessage(bool Hidden = false, bool Categorized = false);
16731738
/// Hopefully this API can be depricated soon. Any situation where options need
16741739
/// to be modified by tools or libraries should be handled by sane APIs rather
16751740
/// than just handing around a global list.
1676-
StringMap<Option *> &getRegisteredOptions();
1677-
// //
1678-
///////////////////////////////////////////////////////////////////////////////
1741+
StringMap<Option *> &getRegisteredOptions(SubCommand &Sub);
1742+
1743+
//===----------------------------------------------------------------------===//
16791744
// Standalone command line processing utilities.
16801745
//
16811746

@@ -1741,7 +1806,8 @@ bool ExpandResponseFiles(StringSaver &Saver, TokenizerCallback Tokenizer,
17411806
/// Some tools (like clang-format) like to be able to hide all options that are
17421807
/// not specific to the tool. This function allows a tool to specify a single
17431808
/// option category to display in the -help output.
1744-
void HideUnrelatedOptions(cl::OptionCategory &Category);
1809+
void HideUnrelatedOptions(cl::OptionCategory &Category,
1810+
SubCommand &Sub = *TopLevelSubCommand);
17451811

17461812
/// \brief Mark all options not part of the categories as cl::ReallyHidden.
17471813
///
@@ -1750,7 +1816,19 @@ void HideUnrelatedOptions(cl::OptionCategory &Category);
17501816
/// Some tools (like clang-format) like to be able to hide all options that are
17511817
/// not specific to the tool. This function allows a tool to specify a single
17521818
/// option category to display in the -help output.
1753-
void HideUnrelatedOptions(ArrayRef<const cl::OptionCategory *> Categories);
1819+
void HideUnrelatedOptions(ArrayRef<const cl::OptionCategory *> Categories,
1820+
SubCommand &Sub = *TopLevelSubCommand);
1821+
1822+
/// \brief Reset all command line options to a state that looks as if they have
1823+
/// never appeared on the command line. This is useful for being able to parse
1824+
/// a command line multiple times (especially useful for writing tests).
1825+
void ResetAllOptionOccurrences();
1826+
1827+
/// \brief Reset the command line parser back to its initial state. This
1828+
/// removes
1829+
/// all options, categories, and subcommands and returns the parser to a state
1830+
/// where no options are supported.
1831+
void ResetCommandLineParser();
17541832

17551833
} // End namespace cl
17561834

0 commit comments

Comments
 (0)