1af615896SEugene Zelenko //===- Option.cpp - Abstract Driver Options -------------------------------===//
241ee041dSMichael J. Spencer //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
641ee041dSMichael J. Spencer //
741ee041dSMichael J. Spencer //===----------------------------------------------------------------------===//
841ee041dSMichael J. Spencer
9af615896SEugene Zelenko #include "llvm/ADT/StringRef.h"
1041ee041dSMichael J. Spencer #include "llvm/ADT/Twine.h"
11432a3883SNico Weber #include "llvm/Config/llvm-config.h"
1241ee041dSMichael J. Spencer #include "llvm/Option/Arg.h"
1341ee041dSMichael J. Spencer #include "llvm/Option/ArgList.h"
14af615896SEugene Zelenko #include "llvm/Option/Option.h"
15af615896SEugene Zelenko #include "llvm/Option/OptTable.h"
16af615896SEugene Zelenko #include "llvm/Support/Compiler.h"
179a8b5e7eSEric Christopher #include "llvm/Support/Debug.h"
1841ee041dSMichael J. Spencer #include "llvm/Support/ErrorHandling.h"
19be81023dSChandler Carruth #include "llvm/Support/raw_ostream.h"
2041ee041dSMichael J. Spencer #include <cassert>
21af615896SEugene Zelenko #include <cstring>
2241ee041dSMichael J. Spencer
2341ee041dSMichael J. Spencer using namespace llvm;
2441ee041dSMichael J. Spencer using namespace llvm::opt;
2541ee041dSMichael J. Spencer
Option(const OptTable::Info * info,const OptTable * owner)2641ee041dSMichael J. Spencer Option::Option(const OptTable::Info *info, const OptTable *owner)
2741ee041dSMichael J. Spencer : Info(info), Owner(owner) {
2831d6fd84SHans Wennborg // Multi-level aliases are not supported. This just simplifies option
2931d6fd84SHans Wennborg // tracking, it is not an inherent limitation.
3046978d41SRichard Trieu assert((!Info || !getAlias().isValid() || !getAlias().getAlias().isValid()) &&
3131d6fd84SHans Wennborg "Multi-level aliases are not supported.");
325fdcf868SHans Wennborg
335fdcf868SHans Wennborg if (Info && getAliasArgs()) {
345fdcf868SHans Wennborg assert(getAlias().isValid() && "Only alias options can have alias args.");
355fdcf868SHans Wennborg assert(getKind() == FlagClass && "Only Flag aliases can have alias args.");
365fdcf868SHans Wennborg assert(getAlias().getKind() != FlagClass &&
375fdcf868SHans Wennborg "Cannot provide alias args to a flag option.");
385fdcf868SHans Wennborg }
3941ee041dSMichael J. Spencer }
4041ee041dSMichael J. Spencer
print(raw_ostream & O) const419a8b5e7eSEric Christopher void Option::print(raw_ostream &O) const {
429a8b5e7eSEric Christopher O << "<";
4341ee041dSMichael J. Spencer switch (getKind()) {
449a8b5e7eSEric Christopher #define P(N) case N: O << #N; break
4541ee041dSMichael J. Spencer P(GroupClass);
4641ee041dSMichael J. Spencer P(InputClass);
4741ee041dSMichael J. Spencer P(UnknownClass);
4841ee041dSMichael J. Spencer P(FlagClass);
4941ee041dSMichael J. Spencer P(JoinedClass);
50ba5d4af4SYuka Takahashi P(ValuesClass);
5141ee041dSMichael J. Spencer P(SeparateClass);
5241ee041dSMichael J. Spencer P(CommaJoinedClass);
5341ee041dSMichael J. Spencer P(MultiArgClass);
5441ee041dSMichael J. Spencer P(JoinedOrSeparateClass);
5541ee041dSMichael J. Spencer P(JoinedAndSeparateClass);
56d505fbf4SHans Wennborg P(RemainingArgsClass);
5740cfde3cSHans Wennborg P(RemainingArgsJoinedClass);
5841ee041dSMichael J. Spencer #undef P
5941ee041dSMichael J. Spencer }
6041ee041dSMichael J. Spencer
617b78d359SReid Kleckner if (Info->Prefixes) {
629a8b5e7eSEric Christopher O << " Prefixes:[";
632617dcceSCraig Topper for (const char *const *Pre = Info->Prefixes; *Pre != nullptr; ++Pre) {
649a8b5e7eSEric Christopher O << '"' << *Pre << (*(Pre + 1) == nullptr ? "\"" : "\", ");
6541ee041dSMichael J. Spencer }
669a8b5e7eSEric Christopher O << ']';
677b78d359SReid Kleckner }
6841ee041dSMichael J. Spencer
699a8b5e7eSEric Christopher O << " Name:\"" << getName() << '"';
7041ee041dSMichael J. Spencer
7141ee041dSMichael J. Spencer const Option Group = getGroup();
7241ee041dSMichael J. Spencer if (Group.isValid()) {
739a8b5e7eSEric Christopher O << " Group:";
749a8b5e7eSEric Christopher Group.print(O);
7541ee041dSMichael J. Spencer }
7641ee041dSMichael J. Spencer
7741ee041dSMichael J. Spencer const Option Alias = getAlias();
7841ee041dSMichael J. Spencer if (Alias.isValid()) {
799a8b5e7eSEric Christopher O << " Alias:";
809a8b5e7eSEric Christopher Alias.print(O);
8141ee041dSMichael J. Spencer }
8241ee041dSMichael J. Spencer
8341ee041dSMichael J. Spencer if (getKind() == MultiArgClass)
849a8b5e7eSEric Christopher O << " NumArgs:" << getNumArgs();
8541ee041dSMichael J. Spencer
869a8b5e7eSEric Christopher O << ">\n";
8741ee041dSMichael J. Spencer }
8841ee041dSMichael J. Spencer
89615eb470SAaron Ballman #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
dump() const90eb2a2546SYaron Keren LLVM_DUMP_METHOD void Option::dump() const { print(dbgs()); }
918c209aa8SMatthias Braun #endif
929a8b5e7eSEric Christopher
matches(OptSpecifier Opt) const9341ee041dSMichael J. Spencer bool Option::matches(OptSpecifier Opt) const {
9441ee041dSMichael J. Spencer // Aliases are never considered in matching, look through them.
9541ee041dSMichael J. Spencer const Option Alias = getAlias();
9641ee041dSMichael J. Spencer if (Alias.isValid())
9741ee041dSMichael J. Spencer return Alias.matches(Opt);
9841ee041dSMichael J. Spencer
9941ee041dSMichael J. Spencer // Check exact match.
10041ee041dSMichael J. Spencer if (getID() == Opt.getID())
10141ee041dSMichael J. Spencer return true;
10241ee041dSMichael J. Spencer
10341ee041dSMichael J. Spencer const Option Group = getGroup();
10441ee041dSMichael J. Spencer if (Group.isValid())
10541ee041dSMichael J. Spencer return Group.matches(Opt);
10641ee041dSMichael J. Spencer return false;
10741ee041dSMichael J. Spencer }
10841ee041dSMichael J. Spencer
acceptInternal(const ArgList & Args,StringRef Spelling,unsigned & Index) const109*2f955424SNico Weber std::unique_ptr<Arg> Option::acceptInternal(const ArgList &Args,
110*2f955424SNico Weber StringRef Spelling,
111f8a29b17SFangrui Song unsigned &Index) const {
112f8a29b17SFangrui Song size_t ArgSize = Spelling.size();
11341ee041dSMichael J. Spencer switch (getKind()) {
1145fdcf868SHans Wennborg case FlagClass: {
11541ee041dSMichael J. Spencer if (ArgSize != strlen(Args.getArgString(Index)))
1162617dcceSCraig Topper return nullptr;
117*2f955424SNico Weber return std::make_unique<Arg>(*this, Spelling, Index++);
1185fdcf868SHans Wennborg }
11941ee041dSMichael J. Spencer case JoinedClass: {
12041ee041dSMichael J. Spencer const char *Value = Args.getArgString(Index) + ArgSize;
121*2f955424SNico Weber return std::make_unique<Arg>(*this, Spelling, Index++, Value);
12241ee041dSMichael J. Spencer }
12341ee041dSMichael J. Spencer case CommaJoinedClass: {
12441ee041dSMichael J. Spencer // Always matches.
12541ee041dSMichael J. Spencer const char *Str = Args.getArgString(Index) + ArgSize;
126*2f955424SNico Weber auto A = std::make_unique<Arg>(*this, Spelling, Index++);
12741ee041dSMichael J. Spencer
12841ee041dSMichael J. Spencer // Parse out the comma separated values.
12941ee041dSMichael J. Spencer const char *Prev = Str;
13041ee041dSMichael J. Spencer for (;; ++Str) {
13141ee041dSMichael J. Spencer char c = *Str;
13241ee041dSMichael J. Spencer
13341ee041dSMichael J. Spencer if (!c || c == ',') {
13441ee041dSMichael J. Spencer if (Prev != Str) {
13541ee041dSMichael J. Spencer char *Value = new char[Str - Prev + 1];
13641ee041dSMichael J. Spencer memcpy(Value, Prev, Str - Prev);
13741ee041dSMichael J. Spencer Value[Str - Prev] = '\0';
13841ee041dSMichael J. Spencer A->getValues().push_back(Value);
13941ee041dSMichael J. Spencer }
14041ee041dSMichael J. Spencer
14141ee041dSMichael J. Spencer if (!c)
14241ee041dSMichael J. Spencer break;
14341ee041dSMichael J. Spencer
14441ee041dSMichael J. Spencer Prev = Str + 1;
14541ee041dSMichael J. Spencer }
14641ee041dSMichael J. Spencer }
14741ee041dSMichael J. Spencer A->setOwnsValues(true);
14841ee041dSMichael J. Spencer
14941ee041dSMichael J. Spencer return A;
15041ee041dSMichael J. Spencer }
15141ee041dSMichael J. Spencer case SeparateClass:
15241ee041dSMichael J. Spencer // Matches iff this is an exact match.
15341ee041dSMichael J. Spencer // FIXME: Avoid strlen.
15441ee041dSMichael J. Spencer if (ArgSize != strlen(Args.getArgString(Index)))
1552617dcceSCraig Topper return nullptr;
15641ee041dSMichael J. Spencer
15741ee041dSMichael J. Spencer Index += 2;
158e3f146d9SReid Kleckner if (Index > Args.getNumInputArgStrings() ||
159e3f146d9SReid Kleckner Args.getArgString(Index - 1) == nullptr)
1602617dcceSCraig Topper return nullptr;
16141ee041dSMichael J. Spencer
162*2f955424SNico Weber return std::make_unique<Arg>(*this, Spelling, Index - 2,
163*2f955424SNico Weber Args.getArgString(Index - 1));
16441ee041dSMichael J. Spencer case MultiArgClass: {
16541ee041dSMichael J. Spencer // Matches iff this is an exact match.
16641ee041dSMichael J. Spencer // FIXME: Avoid strlen.
16741ee041dSMichael J. Spencer if (ArgSize != strlen(Args.getArgString(Index)))
1682617dcceSCraig Topper return nullptr;
16941ee041dSMichael J. Spencer
17041ee041dSMichael J. Spencer Index += 1 + getNumArgs();
17141ee041dSMichael J. Spencer if (Index > Args.getNumInputArgStrings())
1722617dcceSCraig Topper return nullptr;
17341ee041dSMichael J. Spencer
174*2f955424SNico Weber auto A = std::make_unique<Arg>(*this, Spelling, Index - 1 - getNumArgs(),
17541ee041dSMichael J. Spencer Args.getArgString(Index - getNumArgs()));
17641ee041dSMichael J. Spencer for (unsigned i = 1; i != getNumArgs(); ++i)
17741ee041dSMichael J. Spencer A->getValues().push_back(Args.getArgString(Index - getNumArgs() + i));
17841ee041dSMichael J. Spencer return A;
17941ee041dSMichael J. Spencer }
18041ee041dSMichael J. Spencer case JoinedOrSeparateClass: {
18141ee041dSMichael J. Spencer // If this is not an exact match, it is a joined arg.
18241ee041dSMichael J. Spencer // FIXME: Avoid strlen.
18341ee041dSMichael J. Spencer if (ArgSize != strlen(Args.getArgString(Index))) {
18441ee041dSMichael J. Spencer const char *Value = Args.getArgString(Index) + ArgSize;
185*2f955424SNico Weber return std::make_unique<Arg>(*this, Spelling, Index++, Value);
18641ee041dSMichael J. Spencer }
18741ee041dSMichael J. Spencer
18841ee041dSMichael J. Spencer // Otherwise it must be separate.
18941ee041dSMichael J. Spencer Index += 2;
190e3f146d9SReid Kleckner if (Index > Args.getNumInputArgStrings() ||
191e3f146d9SReid Kleckner Args.getArgString(Index - 1) == nullptr)
1922617dcceSCraig Topper return nullptr;
19341ee041dSMichael J. Spencer
194*2f955424SNico Weber return std::make_unique<Arg>(*this, Spelling, Index - 2,
195*2f955424SNico Weber Args.getArgString(Index - 1));
19641ee041dSMichael J. Spencer }
19741ee041dSMichael J. Spencer case JoinedAndSeparateClass:
19841ee041dSMichael J. Spencer // Always matches.
19941ee041dSMichael J. Spencer Index += 2;
200e3f146d9SReid Kleckner if (Index > Args.getNumInputArgStrings() ||
201e3f146d9SReid Kleckner Args.getArgString(Index - 1) == nullptr)
2022617dcceSCraig Topper return nullptr;
20341ee041dSMichael J. Spencer
204*2f955424SNico Weber return std::make_unique<Arg>(*this, Spelling, Index - 2,
20541ee041dSMichael J. Spencer Args.getArgString(Index - 2) + ArgSize,
20641ee041dSMichael J. Spencer Args.getArgString(Index - 1));
207d505fbf4SHans Wennborg case RemainingArgsClass: {
208d505fbf4SHans Wennborg // Matches iff this is an exact match.
209d505fbf4SHans Wennborg // FIXME: Avoid strlen.
210d505fbf4SHans Wennborg if (ArgSize != strlen(Args.getArgString(Index)))
2112617dcceSCraig Topper return nullptr;
212*2f955424SNico Weber auto A = std::make_unique<Arg>(*this, Spelling, Index++);
213e3f146d9SReid Kleckner while (Index < Args.getNumInputArgStrings() &&
214e3f146d9SReid Kleckner Args.getArgString(Index) != nullptr)
215d505fbf4SHans Wennborg A->getValues().push_back(Args.getArgString(Index++));
216d505fbf4SHans Wennborg return A;
217d505fbf4SHans Wennborg }
21840cfde3cSHans Wennborg case RemainingArgsJoinedClass: {
219*2f955424SNico Weber auto A = std::make_unique<Arg>(*this, Spelling, Index);
22040cfde3cSHans Wennborg if (ArgSize != strlen(Args.getArgString(Index))) {
22140cfde3cSHans Wennborg // An inexact match means there is a joined arg.
22240cfde3cSHans Wennborg A->getValues().push_back(Args.getArgString(Index) + ArgSize);
22340cfde3cSHans Wennborg }
22440cfde3cSHans Wennborg Index++;
22540cfde3cSHans Wennborg while (Index < Args.getNumInputArgStrings() &&
22640cfde3cSHans Wennborg Args.getArgString(Index) != nullptr)
22740cfde3cSHans Wennborg A->getValues().push_back(Args.getArgString(Index++));
22840cfde3cSHans Wennborg return A;
22940cfde3cSHans Wennborg }
23040cfde3cSHans Wennborg
23141ee041dSMichael J. Spencer default:
23241ee041dSMichael J. Spencer llvm_unreachable("Invalid option kind!");
23341ee041dSMichael J. Spencer }
23441ee041dSMichael J. Spencer }
235e3f06b47SNico Weber
accept(const ArgList & Args,StringRef CurArg,bool GroupedShortOption,unsigned & Index) const236*2f955424SNico Weber std::unique_ptr<Arg> Option::accept(const ArgList &Args, StringRef CurArg,
237*2f955424SNico Weber bool GroupedShortOption,
238*2f955424SNico Weber unsigned &Index) const {
239*2f955424SNico Weber auto A(GroupedShortOption && getKind() == FlagClass
240*2f955424SNico Weber ? std::make_unique<Arg>(*this, CurArg, Index)
241f8a29b17SFangrui Song : acceptInternal(Args, CurArg, Index));
242e3f06b47SNico Weber if (!A)
243e3f06b47SNico Weber return nullptr;
244e3f06b47SNico Weber
245e3f06b47SNico Weber const Option &UnaliasedOption = getUnaliasedOption();
246e3f06b47SNico Weber if (getID() == UnaliasedOption.getID())
247*2f955424SNico Weber return A;
248e3f06b47SNico Weber
249e3f06b47SNico Weber // "A" is an alias for a different flag. For most clients it's more convenient
250e3f06b47SNico Weber // if this function returns unaliased Args, so create an unaliased arg for
251e3f06b47SNico Weber // returning.
252e3f06b47SNico Weber
253e3f06b47SNico Weber // This creates a completely new Arg object for the unaliased Arg because
254e3f06b47SNico Weber // the alias and the unaliased arg can have different Kinds and different
255e3f06b47SNico Weber // Values (due to AliasArgs<>).
256e3f06b47SNico Weber
257e3f06b47SNico Weber // Get the spelling from the unaliased option.
258e3f06b47SNico Weber StringRef UnaliasedSpelling = Args.MakeArgString(
259e3f06b47SNico Weber Twine(UnaliasedOption.getPrefix()) + Twine(UnaliasedOption.getName()));
260e3f06b47SNico Weber
261e3f06b47SNico Weber // It's a bit weird that aliased and unaliased arg share one index, but
262e3f06b47SNico Weber // the index is mostly use as a memory optimization in render().
263e3f06b47SNico Weber // Due to this, ArgList::getArgString(A->getIndex()) will return the spelling
264e3f06b47SNico Weber // of the aliased arg always, while A->getSpelling() returns either the
265e3f06b47SNico Weber // unaliased or the aliased arg, depending on which Arg object it's called on.
266*2f955424SNico Weber auto UnaliasedA =
267*2f955424SNico Weber std::make_unique<Arg>(UnaliasedOption, UnaliasedSpelling, A->getIndex());
268e3f06b47SNico Weber Arg *RawA = A.get();
269e3f06b47SNico Weber UnaliasedA->setAlias(std::move(A));
270e3f06b47SNico Weber
271e3f06b47SNico Weber if (getKind() != FlagClass) {
272e3f06b47SNico Weber // Values are usually owned by the ArgList. The exception are
273e3f06b47SNico Weber // CommaJoined flags, where the Arg owns the values. For aliased flags,
274e3f06b47SNico Weber // make the unaliased Arg the owner of the values.
275e3f06b47SNico Weber // FIXME: There aren't many uses of CommaJoined -- try removing
276e3f06b47SNico Weber // CommaJoined in favor of just calling StringRef::split(',') instead.
277e3f06b47SNico Weber UnaliasedA->getValues() = RawA->getValues();
278e3f06b47SNico Weber UnaliasedA->setOwnsValues(RawA->getOwnsValues());
279e3f06b47SNico Weber RawA->setOwnsValues(false);
280e3f06b47SNico Weber return UnaliasedA;
281e3f06b47SNico Weber }
282e3f06b47SNico Weber
283e3f06b47SNico Weber // FlagClass aliases can have AliasArgs<>; add those to the unaliased arg.
284e3f06b47SNico Weber if (const char *Val = getAliasArgs()) {
285e3f06b47SNico Weber while (*Val != '\0') {
286e3f06b47SNico Weber UnaliasedA->getValues().push_back(Val);
287e3f06b47SNico Weber
288e3f06b47SNico Weber // Move past the '\0' to the next argument.
289e3f06b47SNico Weber Val += strlen(Val) + 1;
290e3f06b47SNico Weber }
291e3f06b47SNico Weber }
292e3f06b47SNico Weber if (UnaliasedOption.getKind() == JoinedClass && !getAliasArgs())
293e3f06b47SNico Weber // A Flag alias for a Joined option must provide an argument.
294e3f06b47SNico Weber UnaliasedA->getValues().push_back("");
295e3f06b47SNico Weber return UnaliasedA;
296e3f06b47SNico Weber }
297