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