1//===- Option.h - Abstract Driver Options -----------------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#ifndef LLVM_OPTION_OPTION_H
10#define LLVM_OPTION_OPTION_H
11
12#include "llvm/ADT/SmallVector.h"
13#include "llvm/ADT/StringRef.h"
14#include "llvm/Option/OptSpecifier.h"
15#include "llvm/Option/OptTable.h"
16#include "llvm/Support/ErrorHandling.h"
17#include <cassert>
18
19namespace llvm {
20
21class raw_ostream;
22
23namespace opt {
24
25class Arg;
26class ArgList;
27
28/// ArgStringList - Type used for constructing argv lists for subprocesses.
29using ArgStringList = SmallVector<const char *, 16>;
30
31/// Base flags for all options. Custom flags may be added after.
32enum DriverFlag {
33 HelpHidden = (1 << 0),
34 RenderAsInput = (1 << 1),
35 RenderJoined = (1 << 2),
36 RenderSeparate = (1 << 3)
37};
38
39enum DriverVisibility {
40 DefaultVis = (1 << 0),
41};
42
43/// Option - Abstract representation for a single form of driver
44/// argument.
45///
46/// An Option class represents a form of option that the driver
47/// takes, for example how many arguments the option has and how
48/// they can be provided. Individual option instances store
49/// additional information about what group the option is a member
50/// of (if any), if the option is an alias, and a number of
51/// flags. At runtime the driver parses the command line into
52/// concrete Arg instances, each of which corresponds to a
53/// particular Option instance.
54class Option {
55public:
56 enum OptionClass {
57 GroupClass = 0,
58 InputClass,
59 UnknownClass,
60 FlagClass,
61 JoinedClass,
62 ValuesClass,
63 SeparateClass,
64 RemainingArgsClass,
65 RemainingArgsJoinedClass,
66 CommaJoinedClass,
67 MultiArgClass,
68 JoinedOrSeparateClass,
69 JoinedAndSeparateClass
70 };
71
72 enum RenderStyleKind {
73 RenderCommaJoinedStyle,
74 RenderJoinedStyle,
75 RenderSeparateStyle,
76 RenderValuesStyle
77 };
78
79protected:
80 const OptTable::Info *Info;
81 const OptTable *Owner;
82
83public:
84 Option(const OptTable::Info *Info, const OptTable *Owner);
85
86 bool isValid() const {
87 return Info != nullptr;
88 }
89
90 unsigned getID() const {
91 assert(Info && "Must have a valid info!");
92 return Info->ID;
93 }
94
95 OptionClass getKind() const {
96 assert(Info && "Must have a valid info!");
97 return OptionClass(Info->Kind);
98 }
99
100 /// Get the name of this option without any prefix.
101 StringRef getName() const {
102 assert(Info && "Must have a valid info!");
103 return Info->getName();
104 }
105
106 const Option getGroup() const {
107 assert(Info && "Must have a valid info!");
108 assert(Owner && "Must have a valid owner!");
109 return Owner->getOption(Opt: Info->GroupID);
110 }
111
112 const Option getAlias() const {
113 assert(Info && "Must have a valid info!");
114 assert(Owner && "Must have a valid owner!");
115 return Owner->getOption(Opt: Info->AliasID);
116 }
117
118 /// Get the alias arguments as a \0 separated list.
119 /// E.g. ["foo", "bar"] would be returned as "foo\0bar\0".
120 const char *getAliasArgs() const {
121 assert(Info && "Must have a valid info!");
122 assert((!Info->AliasArgs || Info->AliasArgs[0] != 0) &&
123 "AliasArgs should be either 0 or non-empty.");
124
125 return Info->AliasArgs;
126 }
127
128 /// Get the default prefix for this option.
129 StringRef getPrefix() const {
130 return Info->Prefixes.empty()
131 ? StringRef()
132 : static_cast<const StringRef &>(Info->Prefixes[0]);
133 }
134
135 /// Get the name of this option with the default prefix.
136 StringLiteral getPrefixedName() const {
137 assert(Info && "Must have a valid info!");
138 return Info->PrefixedName;
139 }
140
141 /// Get the help text for this option.
142 StringRef getHelpText() const {
143 assert(Info && "Must have a valid info!");
144 return Info->HelpText;
145 }
146
147 /// Get the meta-variable list for this option.
148 StringRef getMetaVar() const {
149 assert(Info && "Must have a valid info!");
150 return Info->MetaVar;
151 }
152
153 unsigned getNumArgs() const { return Info->Param; }
154
155 bool hasNoOptAsInput() const { return Info->Flags & RenderAsInput;}
156
157 RenderStyleKind getRenderStyle() const {
158 if (Info->Flags & RenderJoined)
159 return RenderJoinedStyle;
160 if (Info->Flags & RenderSeparate)
161 return RenderSeparateStyle;
162 switch (getKind()) {
163 case GroupClass:
164 case InputClass:
165 case UnknownClass:
166 return RenderValuesStyle;
167 case JoinedClass:
168 case JoinedAndSeparateClass:
169 return RenderJoinedStyle;
170 case CommaJoinedClass:
171 return RenderCommaJoinedStyle;
172 case FlagClass:
173 case ValuesClass:
174 case SeparateClass:
175 case MultiArgClass:
176 case JoinedOrSeparateClass:
177 case RemainingArgsClass:
178 case RemainingArgsJoinedClass:
179 return RenderSeparateStyle;
180 }
181 llvm_unreachable("Unexpected kind!");
182 }
183
184 /// Test if this option has the flag \a Val.
185 bool hasFlag(unsigned Val) const {
186 return Info->Flags & Val;
187 }
188
189 /// Test if this option has the visibility flag \a Val.
190 bool hasVisibilityFlag(unsigned Val) const {
191 return Info->Visibility & Val;
192 }
193
194 /// getUnaliasedOption - Return the final option this option
195 /// aliases (itself, if the option has no alias).
196 const Option getUnaliasedOption() const {
197 const Option Alias = getAlias();
198 if (Alias.isValid()) return Alias.getUnaliasedOption();
199 return *this;
200 }
201
202 /// getRenderName - Return the name to use when rendering this
203 /// option.
204 StringRef getRenderName() const {
205 return getUnaliasedOption().getName();
206 }
207
208 /// matches - Predicate for whether this option is part of the
209 /// given option (which may be a group).
210 ///
211 /// Note that matches against options which are an alias should never be
212 /// done -- aliases do not participate in matching and so such a query will
213 /// always be false.
214 bool matches(OptSpecifier ID) const;
215
216 /// Potentially accept the current argument, returning a new Arg instance,
217 /// or 0 if the option does not accept this argument (or the argument is
218 /// missing values).
219 ///
220 /// If the option accepts the current argument, accept() sets
221 /// Index to the position where argument parsing should resume
222 /// (even if the argument is missing values).
223 ///
224 /// \p CurArg The argument to be matched. It may be shorter than the
225 /// underlying storage to represent a Joined argument.
226 /// \p GroupedShortOption If true, we are handling the fallback case of
227 /// parsing a prefix of the current argument as a short option.
228 std::unique_ptr<Arg> accept(const ArgList &Args, StringRef CurArg,
229 bool GroupedShortOption, unsigned &Index) const;
230
231private:
232 std::unique_ptr<Arg> acceptInternal(const ArgList &Args, StringRef CurArg,
233 unsigned &Index) const;
234
235public:
236 void print(raw_ostream &O, bool AddNewLine = true) const;
237 void dump() const;
238};
239
240} // end namespace opt
241
242} // end namespace llvm
243
244#endif // LLVM_OPTION_OPTION_H
245

source code of llvm/include/llvm/Option/Option.h