xref: /freebsd/contrib/llvm-project/llvm/lib/Option/Option.cpp (revision be092bcde96bdcfde9013d60e442cca023bfbd1b)
1  //===- Option.cpp - Abstract Driver Options -------------------------------===//
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  #include "llvm/ADT/StringRef.h"
10  #include "llvm/ADT/Twine.h"
11  #include "llvm/Config/llvm-config.h"
12  #include "llvm/Option/Arg.h"
13  #include "llvm/Option/ArgList.h"
14  #include "llvm/Option/Option.h"
15  #include "llvm/Option/OptTable.h"
16  #include "llvm/Support/Compiler.h"
17  #include "llvm/Support/Debug.h"
18  #include "llvm/Support/ErrorHandling.h"
19  #include "llvm/Support/raw_ostream.h"
20  #include <cassert>
21  #include <cstring>
22  
23  using namespace llvm;
24  using namespace llvm::opt;
25  
26  Option::Option(const OptTable::Info *info, const OptTable *owner)
27    : Info(info), Owner(owner) {
28    // Multi-level aliases are not supported. This just simplifies option
29    // tracking, it is not an inherent limitation.
30    assert((!Info || !getAlias().isValid() || !getAlias().getAlias().isValid()) &&
31           "Multi-level aliases are not supported.");
32  
33    if (Info && getAliasArgs()) {
34      assert(getAlias().isValid() && "Only alias options can have alias args.");
35      assert(getKind() == FlagClass && "Only Flag aliases can have alias args.");
36      assert(getAlias().getKind() != FlagClass &&
37             "Cannot provide alias args to a flag option.");
38    }
39  }
40  
41  void Option::print(raw_ostream &O) const {
42    O << "<";
43    switch (getKind()) {
44  #define P(N) case N: O << #N; break
45      P(GroupClass);
46      P(InputClass);
47      P(UnknownClass);
48      P(FlagClass);
49      P(JoinedClass);
50      P(ValuesClass);
51      P(SeparateClass);
52      P(CommaJoinedClass);
53      P(MultiArgClass);
54      P(JoinedOrSeparateClass);
55      P(JoinedAndSeparateClass);
56      P(RemainingArgsClass);
57      P(RemainingArgsJoinedClass);
58  #undef P
59    }
60  
61    if (!Info->Prefixes.empty()) {
62      O << " Prefixes:[";
63      for (size_t I = 0, N = Info->Prefixes.size(); I != N; ++I)
64        O << '"' << Info->Prefixes[I] << (I == N - 1 ? "\"" : "\", ");
65      O << ']';
66    }
67  
68    O << " Name:\"" << getName() << '"';
69  
70    const Option Group = getGroup();
71    if (Group.isValid()) {
72      O << " Group:";
73      Group.print(O);
74    }
75  
76    const Option Alias = getAlias();
77    if (Alias.isValid()) {
78      O << " Alias:";
79      Alias.print(O);
80    }
81  
82    if (getKind() == MultiArgClass)
83      O << " NumArgs:" << getNumArgs();
84  
85    O << ">\n";
86  }
87  
88  #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
89  LLVM_DUMP_METHOD void Option::dump() const { print(dbgs()); }
90  #endif
91  
92  bool Option::matches(OptSpecifier Opt) const {
93    // Aliases are never considered in matching, look through them.
94    const Option Alias = getAlias();
95    if (Alias.isValid())
96      return Alias.matches(Opt);
97  
98    // Check exact match.
99    if (getID() == Opt.getID())
100      return true;
101  
102    const Option Group = getGroup();
103    if (Group.isValid())
104      return Group.matches(Opt);
105    return false;
106  }
107  
108  std::unique_ptr<Arg> Option::acceptInternal(const ArgList &Args,
109                                              StringRef Spelling,
110                                              unsigned &Index) const {
111    size_t ArgSize = Spelling.size();
112    switch (getKind()) {
113    case FlagClass: {
114      if (ArgSize != strlen(Args.getArgString(Index)))
115        return nullptr;
116      return std::make_unique<Arg>(*this, Spelling, Index++);
117    }
118    case JoinedClass: {
119      const char *Value = Args.getArgString(Index) + ArgSize;
120      return std::make_unique<Arg>(*this, Spelling, Index++, Value);
121    }
122    case CommaJoinedClass: {
123      // Always matches.
124      const char *Str = Args.getArgString(Index) + ArgSize;
125      auto A = std::make_unique<Arg>(*this, Spelling, Index++);
126  
127      // Parse out the comma separated values.
128      const char *Prev = Str;
129      for (;; ++Str) {
130        char c = *Str;
131  
132        if (!c || c == ',') {
133          if (Prev != Str) {
134            char *Value = new char[Str - Prev + 1];
135            memcpy(Value, Prev, Str - Prev);
136            Value[Str - Prev] = '\0';
137            A->getValues().push_back(Value);
138          }
139  
140          if (!c)
141            break;
142  
143          Prev = Str + 1;
144        }
145      }
146      A->setOwnsValues(true);
147  
148      return A;
149    }
150    case SeparateClass:
151      // Matches iff this is an exact match.
152      // FIXME: Avoid strlen.
153      if (ArgSize != strlen(Args.getArgString(Index)))
154        return nullptr;
155  
156      Index += 2;
157      if (Index > Args.getNumInputArgStrings() ||
158          Args.getArgString(Index - 1) == nullptr)
159        return nullptr;
160  
161      return std::make_unique<Arg>(*this, Spelling, Index - 2,
162                                   Args.getArgString(Index - 1));
163    case MultiArgClass: {
164      // Matches iff this is an exact match.
165      // FIXME: Avoid strlen.
166      if (ArgSize != strlen(Args.getArgString(Index)))
167        return nullptr;
168  
169      Index += 1 + getNumArgs();
170      if (Index > Args.getNumInputArgStrings())
171        return nullptr;
172  
173      auto A = std::make_unique<Arg>(*this, Spelling, Index - 1 - getNumArgs(),
174                                     Args.getArgString(Index - getNumArgs()));
175      for (unsigned i = 1; i != getNumArgs(); ++i)
176        A->getValues().push_back(Args.getArgString(Index - getNumArgs() + i));
177      return A;
178    }
179    case JoinedOrSeparateClass: {
180      // If this is not an exact match, it is a joined arg.
181      // FIXME: Avoid strlen.
182      if (ArgSize != strlen(Args.getArgString(Index))) {
183        const char *Value = Args.getArgString(Index) + ArgSize;
184        return std::make_unique<Arg>(*this, Spelling, Index++, Value);
185      }
186  
187      // Otherwise it must be separate.
188      Index += 2;
189      if (Index > Args.getNumInputArgStrings() ||
190          Args.getArgString(Index - 1) == nullptr)
191        return nullptr;
192  
193      return std::make_unique<Arg>(*this, Spelling, Index - 2,
194                                   Args.getArgString(Index - 1));
195    }
196    case JoinedAndSeparateClass:
197      // Always matches.
198      Index += 2;
199      if (Index > Args.getNumInputArgStrings() ||
200          Args.getArgString(Index - 1) == nullptr)
201        return nullptr;
202  
203      return std::make_unique<Arg>(*this, Spelling, Index - 2,
204                                   Args.getArgString(Index - 2) + ArgSize,
205                                   Args.getArgString(Index - 1));
206    case RemainingArgsClass: {
207      // Matches iff this is an exact match.
208      // FIXME: Avoid strlen.
209      if (ArgSize != strlen(Args.getArgString(Index)))
210        return nullptr;
211      auto A = std::make_unique<Arg>(*this, Spelling, Index++);
212      while (Index < Args.getNumInputArgStrings() &&
213             Args.getArgString(Index) != nullptr)
214        A->getValues().push_back(Args.getArgString(Index++));
215      return A;
216    }
217    case RemainingArgsJoinedClass: {
218      auto A = std::make_unique<Arg>(*this, Spelling, Index);
219      if (ArgSize != strlen(Args.getArgString(Index))) {
220        // An inexact match means there is a joined arg.
221        A->getValues().push_back(Args.getArgString(Index) + ArgSize);
222      }
223      Index++;
224      while (Index < Args.getNumInputArgStrings() &&
225             Args.getArgString(Index) != nullptr)
226        A->getValues().push_back(Args.getArgString(Index++));
227      return A;
228    }
229  
230    default:
231      llvm_unreachable("Invalid option kind!");
232    }
233  }
234  
235  std::unique_ptr<Arg> Option::accept(const ArgList &Args, StringRef CurArg,
236                                      bool GroupedShortOption,
237                                      unsigned &Index) const {
238    auto A(GroupedShortOption && getKind() == FlagClass
239                               ? std::make_unique<Arg>(*this, CurArg, Index)
240                               : acceptInternal(Args, CurArg, Index));
241    if (!A)
242      return nullptr;
243  
244    const Option &UnaliasedOption = getUnaliasedOption();
245    if (getID() == UnaliasedOption.getID())
246      return A;
247  
248    // "A" is an alias for a different flag. For most clients it's more convenient
249    // if this function returns unaliased Args, so create an unaliased arg for
250    // returning.
251  
252    // This creates a completely new Arg object for the unaliased Arg because
253    // the alias and the unaliased arg can have different Kinds and different
254    // Values (due to AliasArgs<>).
255  
256    // Get the spelling from the unaliased option.
257    StringRef UnaliasedSpelling = Args.MakeArgString(
258        Twine(UnaliasedOption.getPrefix()) + Twine(UnaliasedOption.getName()));
259  
260    // It's a bit weird that aliased and unaliased arg share one index, but
261    // the index is mostly use as a memory optimization in render().
262    // Due to this, ArgList::getArgString(A->getIndex()) will return the spelling
263    // of the aliased arg always, while A->getSpelling() returns either the
264    // unaliased or the aliased arg, depending on which Arg object it's called on.
265    auto UnaliasedA =
266        std::make_unique<Arg>(UnaliasedOption, UnaliasedSpelling, A->getIndex());
267    Arg *RawA = A.get();
268    UnaliasedA->setAlias(std::move(A));
269  
270    if (getKind() != FlagClass) {
271      // Values are usually owned by the ArgList. The exception are
272      // CommaJoined flags, where the Arg owns the values. For aliased flags,
273      // make the unaliased Arg the owner of the values.
274      // FIXME: There aren't many uses of CommaJoined -- try removing
275      // CommaJoined in favor of just calling StringRef::split(',') instead.
276      UnaliasedA->getValues() = RawA->getValues();
277      UnaliasedA->setOwnsValues(RawA->getOwnsValues());
278      RawA->setOwnsValues(false);
279      return UnaliasedA;
280    }
281  
282    // FlagClass aliases can have AliasArgs<>; add those to the unaliased arg.
283    if (const char *Val = getAliasArgs()) {
284      while (*Val != '\0') {
285        UnaliasedA->getValues().push_back(Val);
286  
287        // Move past the '\0' to the next argument.
288        Val += strlen(Val) + 1;
289      }
290    }
291    if (UnaliasedOption.getKind() == JoinedClass && !getAliasArgs())
292      // A Flag alias for a Joined option must provide an argument.
293      UnaliasedA->getValues().push_back("");
294    return UnaliasedA;
295  }
296