xref: /llvm-project/llvm/include/llvm/Option/Option.h (revision dd647e3e608ed0b2bac7c588d5859b80ef4a5976)
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 
19 namespace llvm {
20 
21 class raw_ostream;
22 
23 namespace opt {
24 
25 class Arg;
26 class ArgList;
27 
28 /// ArgStringList - Type used for constructing argv lists for subprocesses.
29 using ArgStringList = SmallVector<const char *, 16>;
30 
31 /// Base flags for all options. Custom flags may be added after.
32 enum DriverFlag {
33   HelpHidden       = (1 << 0),
34   RenderAsInput    = (1 << 1),
35   RenderJoined     = (1 << 2),
36   RenderSeparate   = (1 << 3)
37 };
38 
39 enum 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.
54 class Option {
55 public:
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 
79 protected:
80   const OptTable::Info *Info;
81   const OptTable *Owner;
82 
83 public:
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     assert(Owner && "Must have a valid owner!");
104     return Owner->getOptionName(Info->ID);
105   }
106 
107   const Option getGroup() const {
108     assert(Info && "Must have a valid info!");
109     assert(Owner && "Must have a valid owner!");
110     return Owner->getOption(Info->GroupID);
111   }
112 
113   const Option getAlias() const {
114     assert(Info && "Must have a valid info!");
115     assert(Owner && "Must have a valid owner!");
116     return Owner->getOption(Info->AliasID);
117   }
118 
119   /// Get the alias arguments as a \0 separated list.
120   /// E.g. ["foo", "bar"] would be returned as "foo\0bar\0".
121   const char *getAliasArgs() const {
122     assert(Info && "Must have a valid info!");
123     assert((!Info->AliasArgs || Info->AliasArgs[0] != 0) &&
124            "AliasArgs should be either 0 or non-empty.");
125 
126     return Info->AliasArgs;
127   }
128 
129   /// Get the default prefix for this option.
130   StringRef getPrefix() const {
131     assert(Info && "Must have a valid info!");
132     assert(Owner && "Must have a valid owner!");
133     return Owner->getOptionPrefix(Info->ID);
134   }
135 
136   /// Get the name of this option with the default prefix.
137   StringRef getPrefixedName() const {
138     assert(Info && "Must have a valid info!");
139     assert(Owner && "Must have a valid owner!");
140     return Owner->getOptionPrefixedName(Info->ID);
141   }
142 
143   /// Get the help text for this option.
144   StringRef getHelpText() const {
145     assert(Info && "Must have a valid info!");
146     return Info->HelpText;
147   }
148 
149   /// Get the meta-variable list for this option.
150   StringRef getMetaVar() const {
151     assert(Info && "Must have a valid info!");
152     return Info->MetaVar;
153   }
154 
155   unsigned getNumArgs() const { return Info->Param; }
156 
157   bool hasNoOptAsInput() const { return Info->Flags & RenderAsInput;}
158 
159   RenderStyleKind getRenderStyle() const {
160     if (Info->Flags & RenderJoined)
161       return RenderJoinedStyle;
162     if (Info->Flags & RenderSeparate)
163       return RenderSeparateStyle;
164     switch (getKind()) {
165     case GroupClass:
166     case InputClass:
167     case UnknownClass:
168       return RenderValuesStyle;
169     case JoinedClass:
170     case JoinedAndSeparateClass:
171       return RenderJoinedStyle;
172     case CommaJoinedClass:
173       return RenderCommaJoinedStyle;
174     case FlagClass:
175     case ValuesClass:
176     case SeparateClass:
177     case MultiArgClass:
178     case JoinedOrSeparateClass:
179     case RemainingArgsClass:
180     case RemainingArgsJoinedClass:
181       return RenderSeparateStyle;
182     }
183     llvm_unreachable("Unexpected kind!");
184   }
185 
186   /// Test if this option has the flag \a Val.
187   bool hasFlag(unsigned Val) const {
188     return Info->Flags & Val;
189   }
190 
191   /// Test if this option has the visibility flag \a Val.
192   bool hasVisibilityFlag(unsigned Val) const {
193     return Info->Visibility & Val;
194   }
195 
196   /// getUnaliasedOption - Return the final option this option
197   /// aliases (itself, if the option has no alias).
198   const Option getUnaliasedOption() const {
199     const Option Alias = getAlias();
200     if (Alias.isValid()) return Alias.getUnaliasedOption();
201     return *this;
202   }
203 
204   /// getRenderName - Return the name to use when rendering this
205   /// option.
206   StringRef getRenderName() const {
207     return getUnaliasedOption().getName();
208   }
209 
210   /// matches - Predicate for whether this option is part of the
211   /// given option (which may be a group).
212   ///
213   /// Note that matches against options which are an alias should never be
214   /// done -- aliases do not participate in matching and so such a query will
215   /// always be false.
216   bool matches(OptSpecifier ID) const;
217 
218   /// Potentially accept the current argument, returning a new Arg instance,
219   /// or 0 if the option does not accept this argument (or the argument is
220   /// missing values).
221   ///
222   /// If the option accepts the current argument, accept() sets
223   /// Index to the position where argument parsing should resume
224   /// (even if the argument is missing values).
225   ///
226   /// \p CurArg The argument to be matched. It may be shorter than the
227   /// underlying storage to represent a Joined argument.
228   /// \p GroupedShortOption If true, we are handling the fallback case of
229   /// parsing a prefix of the current argument as a short option.
230   std::unique_ptr<Arg> accept(const ArgList &Args, StringRef CurArg,
231                               bool GroupedShortOption, unsigned &Index) const;
232 
233 private:
234   std::unique_ptr<Arg> acceptInternal(const ArgList &Args, StringRef CurArg,
235                                       unsigned &Index) const;
236 
237 public:
238   void print(raw_ostream &O, bool AddNewLine = true) const;
239   void dump() const;
240 };
241 
242 } // end namespace opt
243 
244 } // end namespace llvm
245 
246 #endif // LLVM_OPTION_OPTION_H
247