xref: /freebsd-src/contrib/llvm-project/llvm/lib/Option/Option.cpp (revision 5f757f3ff9144b609b3c433dfd370cc6bdc191ad)
10b57cec5SDimitry Andric //===- Option.cpp - Abstract Driver Options -------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h"
100b57cec5SDimitry Andric #include "llvm/ADT/Twine.h"
110b57cec5SDimitry Andric #include "llvm/Config/llvm-config.h"
120b57cec5SDimitry Andric #include "llvm/Option/Arg.h"
130b57cec5SDimitry Andric #include "llvm/Option/ArgList.h"
140b57cec5SDimitry Andric #include "llvm/Option/Option.h"
150b57cec5SDimitry Andric #include "llvm/Option/OptTable.h"
160b57cec5SDimitry Andric #include "llvm/Support/Compiler.h"
170b57cec5SDimitry Andric #include "llvm/Support/Debug.h"
180b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
190b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
200b57cec5SDimitry Andric #include <cassert>
210b57cec5SDimitry Andric #include <cstring>
220b57cec5SDimitry Andric 
230b57cec5SDimitry Andric using namespace llvm;
240b57cec5SDimitry Andric using namespace llvm::opt;
250b57cec5SDimitry Andric 
Option(const OptTable::Info * info,const OptTable * owner)260b57cec5SDimitry Andric Option::Option(const OptTable::Info *info, const OptTable *owner)
270b57cec5SDimitry Andric   : Info(info), Owner(owner) {
280b57cec5SDimitry Andric   // Multi-level aliases are not supported. This just simplifies option
290b57cec5SDimitry Andric   // tracking, it is not an inherent limitation.
300b57cec5SDimitry Andric   assert((!Info || !getAlias().isValid() || !getAlias().getAlias().isValid()) &&
310b57cec5SDimitry Andric          "Multi-level aliases are not supported.");
320b57cec5SDimitry Andric 
330b57cec5SDimitry Andric   if (Info && getAliasArgs()) {
340b57cec5SDimitry Andric     assert(getAlias().isValid() && "Only alias options can have alias args.");
350b57cec5SDimitry Andric     assert(getKind() == FlagClass && "Only Flag aliases can have alias args.");
360b57cec5SDimitry Andric     assert(getAlias().getKind() != FlagClass &&
370b57cec5SDimitry Andric            "Cannot provide alias args to a flag option.");
380b57cec5SDimitry Andric   }
390b57cec5SDimitry Andric }
400b57cec5SDimitry Andric 
print(raw_ostream & O,bool AddNewLine) const41*5f757f3fSDimitry Andric void Option::print(raw_ostream &O, bool AddNewLine) const {
420b57cec5SDimitry Andric   O << "<";
430b57cec5SDimitry Andric   switch (getKind()) {
440b57cec5SDimitry Andric #define P(N) case N: O << #N; break
450b57cec5SDimitry Andric     P(GroupClass);
460b57cec5SDimitry Andric     P(InputClass);
470b57cec5SDimitry Andric     P(UnknownClass);
480b57cec5SDimitry Andric     P(FlagClass);
490b57cec5SDimitry Andric     P(JoinedClass);
500b57cec5SDimitry Andric     P(ValuesClass);
510b57cec5SDimitry Andric     P(SeparateClass);
520b57cec5SDimitry Andric     P(CommaJoinedClass);
530b57cec5SDimitry Andric     P(MultiArgClass);
540b57cec5SDimitry Andric     P(JoinedOrSeparateClass);
550b57cec5SDimitry Andric     P(JoinedAndSeparateClass);
560b57cec5SDimitry Andric     P(RemainingArgsClass);
570b57cec5SDimitry Andric     P(RemainingArgsJoinedClass);
580b57cec5SDimitry Andric #undef P
590b57cec5SDimitry Andric   }
600b57cec5SDimitry Andric 
61bdd1243dSDimitry Andric   if (!Info->Prefixes.empty()) {
620b57cec5SDimitry Andric     O << " Prefixes:[";
63bdd1243dSDimitry Andric     for (size_t I = 0, N = Info->Prefixes.size(); I != N; ++I)
64bdd1243dSDimitry Andric       O << '"' << Info->Prefixes[I] << (I == N - 1 ? "\"" : "\", ");
650b57cec5SDimitry Andric     O << ']';
660b57cec5SDimitry Andric   }
670b57cec5SDimitry Andric 
680b57cec5SDimitry Andric   O << " Name:\"" << getName() << '"';
690b57cec5SDimitry Andric 
700b57cec5SDimitry Andric   const Option Group = getGroup();
710b57cec5SDimitry Andric   if (Group.isValid()) {
720b57cec5SDimitry Andric     O << " Group:";
73*5f757f3fSDimitry Andric     Group.print(O, /*AddNewLine=*/false);
740b57cec5SDimitry Andric   }
750b57cec5SDimitry Andric 
760b57cec5SDimitry Andric   const Option Alias = getAlias();
770b57cec5SDimitry Andric   if (Alias.isValid()) {
780b57cec5SDimitry Andric     O << " Alias:";
79*5f757f3fSDimitry Andric     Alias.print(O, /*AddNewLine=*/false);
800b57cec5SDimitry Andric   }
810b57cec5SDimitry Andric 
820b57cec5SDimitry Andric   if (getKind() == MultiArgClass)
830b57cec5SDimitry Andric     O << " NumArgs:" << getNumArgs();
840b57cec5SDimitry Andric 
85*5f757f3fSDimitry Andric   O << ">";
86*5f757f3fSDimitry Andric   if (AddNewLine)
87*5f757f3fSDimitry Andric     O << "\n";
880b57cec5SDimitry Andric }
890b57cec5SDimitry Andric 
900b57cec5SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
dump() const910b57cec5SDimitry Andric LLVM_DUMP_METHOD void Option::dump() const { print(dbgs()); }
920b57cec5SDimitry Andric #endif
930b57cec5SDimitry Andric 
matches(OptSpecifier Opt) const940b57cec5SDimitry Andric bool Option::matches(OptSpecifier Opt) const {
950b57cec5SDimitry Andric   // Aliases are never considered in matching, look through them.
960b57cec5SDimitry Andric   const Option Alias = getAlias();
970b57cec5SDimitry Andric   if (Alias.isValid())
980b57cec5SDimitry Andric     return Alias.matches(Opt);
990b57cec5SDimitry Andric 
1000b57cec5SDimitry Andric   // Check exact match.
1010b57cec5SDimitry Andric   if (getID() == Opt.getID())
1020b57cec5SDimitry Andric     return true;
1030b57cec5SDimitry Andric 
1040b57cec5SDimitry Andric   const Option Group = getGroup();
1050b57cec5SDimitry Andric   if (Group.isValid())
1060b57cec5SDimitry Andric     return Group.matches(Opt);
1070b57cec5SDimitry Andric   return false;
1080b57cec5SDimitry Andric }
1090b57cec5SDimitry Andric 
acceptInternal(const ArgList & Args,StringRef Spelling,unsigned & Index) const110349cc55cSDimitry Andric std::unique_ptr<Arg> Option::acceptInternal(const ArgList &Args,
111349cc55cSDimitry Andric                                             StringRef Spelling,
112e8d8bef9SDimitry Andric                                             unsigned &Index) const {
11306c3fb27SDimitry Andric   const size_t SpellingSize = Spelling.size();
11406c3fb27SDimitry Andric   const size_t ArgStringSize = StringRef(Args.getArgString(Index)).size();
1150b57cec5SDimitry Andric   switch (getKind()) {
1160b57cec5SDimitry Andric   case FlagClass: {
11706c3fb27SDimitry Andric     if (SpellingSize != ArgStringSize)
1180b57cec5SDimitry Andric       return nullptr;
119349cc55cSDimitry Andric     return std::make_unique<Arg>(*this, Spelling, Index++);
1200b57cec5SDimitry Andric   }
1210b57cec5SDimitry Andric   case JoinedClass: {
12206c3fb27SDimitry Andric     const char *Value = Args.getArgString(Index) + SpellingSize;
123349cc55cSDimitry Andric     return std::make_unique<Arg>(*this, Spelling, Index++, Value);
1240b57cec5SDimitry Andric   }
1250b57cec5SDimitry Andric   case CommaJoinedClass: {
1260b57cec5SDimitry Andric     // Always matches.
12706c3fb27SDimitry Andric     const char *Str = Args.getArgString(Index) + SpellingSize;
128349cc55cSDimitry Andric     auto A = std::make_unique<Arg>(*this, Spelling, Index++);
1290b57cec5SDimitry Andric 
1300b57cec5SDimitry Andric     // Parse out the comma separated values.
1310b57cec5SDimitry Andric     const char *Prev = Str;
1320b57cec5SDimitry Andric     for (;; ++Str) {
1330b57cec5SDimitry Andric       char c = *Str;
1340b57cec5SDimitry Andric 
1350b57cec5SDimitry Andric       if (!c || c == ',') {
1360b57cec5SDimitry Andric         if (Prev != Str) {
1370b57cec5SDimitry Andric           char *Value = new char[Str - Prev + 1];
1380b57cec5SDimitry Andric           memcpy(Value, Prev, Str - Prev);
1390b57cec5SDimitry Andric           Value[Str - Prev] = '\0';
1400b57cec5SDimitry Andric           A->getValues().push_back(Value);
1410b57cec5SDimitry Andric         }
1420b57cec5SDimitry Andric 
1430b57cec5SDimitry Andric         if (!c)
1440b57cec5SDimitry Andric           break;
1450b57cec5SDimitry Andric 
1460b57cec5SDimitry Andric         Prev = Str + 1;
1470b57cec5SDimitry Andric       }
1480b57cec5SDimitry Andric     }
1490b57cec5SDimitry Andric     A->setOwnsValues(true);
1500b57cec5SDimitry Andric 
1510b57cec5SDimitry Andric     return A;
1520b57cec5SDimitry Andric   }
1530b57cec5SDimitry Andric   case SeparateClass:
1540b57cec5SDimitry Andric     // Matches iff this is an exact match.
15506c3fb27SDimitry Andric     if (SpellingSize != ArgStringSize)
1560b57cec5SDimitry Andric       return nullptr;
1570b57cec5SDimitry Andric 
1580b57cec5SDimitry Andric     Index += 2;
1590b57cec5SDimitry Andric     if (Index > Args.getNumInputArgStrings() ||
1600b57cec5SDimitry Andric         Args.getArgString(Index - 1) == nullptr)
1610b57cec5SDimitry Andric       return nullptr;
1620b57cec5SDimitry Andric 
163349cc55cSDimitry Andric     return std::make_unique<Arg>(*this, Spelling, Index - 2,
164349cc55cSDimitry Andric                                  Args.getArgString(Index - 1));
1650b57cec5SDimitry Andric   case MultiArgClass: {
1660b57cec5SDimitry Andric     // Matches iff this is an exact match.
16706c3fb27SDimitry Andric     if (SpellingSize != ArgStringSize)
1680b57cec5SDimitry Andric       return nullptr;
1690b57cec5SDimitry Andric 
1700b57cec5SDimitry Andric     Index += 1 + getNumArgs();
1710b57cec5SDimitry Andric     if (Index > Args.getNumInputArgStrings())
1720b57cec5SDimitry Andric       return nullptr;
1730b57cec5SDimitry Andric 
174349cc55cSDimitry Andric     auto A = std::make_unique<Arg>(*this, Spelling, Index - 1 - getNumArgs(),
1750b57cec5SDimitry Andric                                    Args.getArgString(Index - getNumArgs()));
1760b57cec5SDimitry Andric     for (unsigned i = 1; i != getNumArgs(); ++i)
1770b57cec5SDimitry Andric       A->getValues().push_back(Args.getArgString(Index - getNumArgs() + i));
1780b57cec5SDimitry Andric     return A;
1790b57cec5SDimitry Andric   }
1800b57cec5SDimitry Andric   case JoinedOrSeparateClass: {
1810b57cec5SDimitry Andric     // If this is not an exact match, it is a joined arg.
18206c3fb27SDimitry Andric     if (SpellingSize != ArgStringSize) {
18306c3fb27SDimitry Andric       const char *Value = Args.getArgString(Index) + SpellingSize;
184349cc55cSDimitry Andric       return std::make_unique<Arg>(*this, Spelling, Index++, Value);
1850b57cec5SDimitry Andric     }
1860b57cec5SDimitry Andric 
1870b57cec5SDimitry Andric     // Otherwise it must be separate.
1880b57cec5SDimitry Andric     Index += 2;
1890b57cec5SDimitry Andric     if (Index > Args.getNumInputArgStrings() ||
1900b57cec5SDimitry Andric         Args.getArgString(Index - 1) == nullptr)
1910b57cec5SDimitry Andric       return nullptr;
1920b57cec5SDimitry Andric 
193349cc55cSDimitry Andric     return std::make_unique<Arg>(*this, Spelling, Index - 2,
194349cc55cSDimitry Andric                                  Args.getArgString(Index - 1));
1950b57cec5SDimitry Andric   }
1960b57cec5SDimitry Andric   case JoinedAndSeparateClass:
1970b57cec5SDimitry Andric     // Always matches.
1980b57cec5SDimitry Andric     Index += 2;
1990b57cec5SDimitry Andric     if (Index > Args.getNumInputArgStrings() ||
2000b57cec5SDimitry Andric         Args.getArgString(Index - 1) == nullptr)
2010b57cec5SDimitry Andric       return nullptr;
2020b57cec5SDimitry Andric 
203349cc55cSDimitry Andric     return std::make_unique<Arg>(*this, Spelling, Index - 2,
20406c3fb27SDimitry Andric                                  Args.getArgString(Index - 2) + SpellingSize,
2050b57cec5SDimitry Andric                                  Args.getArgString(Index - 1));
2060b57cec5SDimitry Andric   case RemainingArgsClass: {
2070b57cec5SDimitry Andric     // Matches iff this is an exact match.
20806c3fb27SDimitry Andric     if (SpellingSize != ArgStringSize)
2090b57cec5SDimitry Andric       return nullptr;
210349cc55cSDimitry Andric     auto A = std::make_unique<Arg>(*this, Spelling, Index++);
2110b57cec5SDimitry Andric     while (Index < Args.getNumInputArgStrings() &&
2120b57cec5SDimitry Andric            Args.getArgString(Index) != nullptr)
2130b57cec5SDimitry Andric       A->getValues().push_back(Args.getArgString(Index++));
2140b57cec5SDimitry Andric     return A;
2150b57cec5SDimitry Andric   }
2160b57cec5SDimitry Andric   case RemainingArgsJoinedClass: {
217349cc55cSDimitry Andric     auto A = std::make_unique<Arg>(*this, Spelling, Index);
21806c3fb27SDimitry Andric     if (SpellingSize != ArgStringSize) {
2190b57cec5SDimitry Andric       // An inexact match means there is a joined arg.
22006c3fb27SDimitry Andric       A->getValues().push_back(Args.getArgString(Index) + SpellingSize);
2210b57cec5SDimitry Andric     }
2220b57cec5SDimitry Andric     Index++;
2230b57cec5SDimitry Andric     while (Index < Args.getNumInputArgStrings() &&
2240b57cec5SDimitry Andric            Args.getArgString(Index) != nullptr)
2250b57cec5SDimitry Andric       A->getValues().push_back(Args.getArgString(Index++));
2260b57cec5SDimitry Andric     return A;
2270b57cec5SDimitry Andric   }
2280b57cec5SDimitry Andric 
2290b57cec5SDimitry Andric   default:
2300b57cec5SDimitry Andric     llvm_unreachable("Invalid option kind!");
2310b57cec5SDimitry Andric   }
2320b57cec5SDimitry Andric }
2330b57cec5SDimitry Andric 
accept(const ArgList & Args,StringRef CurArg,bool GroupedShortOption,unsigned & Index) const234349cc55cSDimitry Andric std::unique_ptr<Arg> Option::accept(const ArgList &Args, StringRef CurArg,
235349cc55cSDimitry Andric                                     bool GroupedShortOption,
236349cc55cSDimitry Andric                                     unsigned &Index) const {
237349cc55cSDimitry Andric   auto A(GroupedShortOption && getKind() == FlagClass
238349cc55cSDimitry Andric                              ? std::make_unique<Arg>(*this, CurArg, Index)
239e8d8bef9SDimitry Andric                              : acceptInternal(Args, CurArg, Index));
2400b57cec5SDimitry Andric   if (!A)
2410b57cec5SDimitry Andric     return nullptr;
2420b57cec5SDimitry Andric 
2430b57cec5SDimitry Andric   const Option &UnaliasedOption = getUnaliasedOption();
2440b57cec5SDimitry Andric   if (getID() == UnaliasedOption.getID())
245349cc55cSDimitry Andric     return A;
2460b57cec5SDimitry Andric 
2470b57cec5SDimitry Andric   // "A" is an alias for a different flag. For most clients it's more convenient
2480b57cec5SDimitry Andric   // if this function returns unaliased Args, so create an unaliased arg for
2490b57cec5SDimitry Andric   // returning.
2500b57cec5SDimitry Andric 
2510b57cec5SDimitry Andric   // This creates a completely new Arg object for the unaliased Arg because
2520b57cec5SDimitry Andric   // the alias and the unaliased arg can have different Kinds and different
2530b57cec5SDimitry Andric   // Values (due to AliasArgs<>).
2540b57cec5SDimitry Andric 
2550b57cec5SDimitry Andric   // Get the spelling from the unaliased option.
2560b57cec5SDimitry Andric   StringRef UnaliasedSpelling = Args.MakeArgString(
2570b57cec5SDimitry Andric       Twine(UnaliasedOption.getPrefix()) + Twine(UnaliasedOption.getName()));
2580b57cec5SDimitry Andric 
2590b57cec5SDimitry Andric   // It's a bit weird that aliased and unaliased arg share one index, but
2600b57cec5SDimitry Andric   // the index is mostly use as a memory optimization in render().
2610b57cec5SDimitry Andric   // Due to this, ArgList::getArgString(A->getIndex()) will return the spelling
2620b57cec5SDimitry Andric   // of the aliased arg always, while A->getSpelling() returns either the
2630b57cec5SDimitry Andric   // unaliased or the aliased arg, depending on which Arg object it's called on.
264349cc55cSDimitry Andric   auto UnaliasedA =
265349cc55cSDimitry Andric       std::make_unique<Arg>(UnaliasedOption, UnaliasedSpelling, A->getIndex());
2660b57cec5SDimitry Andric   Arg *RawA = A.get();
2670b57cec5SDimitry Andric   UnaliasedA->setAlias(std::move(A));
2680b57cec5SDimitry Andric 
2690b57cec5SDimitry Andric   if (getKind() != FlagClass) {
2700b57cec5SDimitry Andric     // Values are usually owned by the ArgList. The exception are
2710b57cec5SDimitry Andric     // CommaJoined flags, where the Arg owns the values. For aliased flags,
2720b57cec5SDimitry Andric     // make the unaliased Arg the owner of the values.
2730b57cec5SDimitry Andric     // FIXME: There aren't many uses of CommaJoined -- try removing
2740b57cec5SDimitry Andric     // CommaJoined in favor of just calling StringRef::split(',') instead.
2750b57cec5SDimitry Andric     UnaliasedA->getValues() = RawA->getValues();
2760b57cec5SDimitry Andric     UnaliasedA->setOwnsValues(RawA->getOwnsValues());
2770b57cec5SDimitry Andric     RawA->setOwnsValues(false);
2780b57cec5SDimitry Andric     return UnaliasedA;
2790b57cec5SDimitry Andric   }
2800b57cec5SDimitry Andric 
2810b57cec5SDimitry Andric   // FlagClass aliases can have AliasArgs<>; add those to the unaliased arg.
2820b57cec5SDimitry Andric   if (const char *Val = getAliasArgs()) {
2830b57cec5SDimitry Andric     while (*Val != '\0') {
2840b57cec5SDimitry Andric       UnaliasedA->getValues().push_back(Val);
2850b57cec5SDimitry Andric 
2860b57cec5SDimitry Andric       // Move past the '\0' to the next argument.
2870b57cec5SDimitry Andric       Val += strlen(Val) + 1;
2880b57cec5SDimitry Andric     }
2890b57cec5SDimitry Andric   }
2900b57cec5SDimitry Andric   if (UnaliasedOption.getKind() == JoinedClass && !getAliasArgs())
2910b57cec5SDimitry Andric     // A Flag alias for a Joined option must provide an argument.
2920b57cec5SDimitry Andric     UnaliasedA->getValues().push_back("");
2930b57cec5SDimitry Andric   return UnaliasedA;
2940b57cec5SDimitry Andric }
295