Remove explicit no-op dtor in favor of the implicit dtor so as not to disable/depreca...
[oota-llvm.git] / lib / Option / Option.cpp
1 //===--- Option.cpp - Abstract Driver Options -----------------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #include "llvm/Option/Option.h"
11 #include "llvm/ADT/Twine.h"
12 #include "llvm/Option/Arg.h"
13 #include "llvm/Option/ArgList.h"
14 #include "llvm/Support/ErrorHandling.h"
15 #include "llvm/Support/raw_ostream.h"
16 #include <algorithm>
17 #include <cassert>
18
19 using namespace llvm;
20 using namespace llvm::opt;
21
22 Option::Option(const OptTable::Info *info, const OptTable *owner)
23   : Info(info), Owner(owner) {
24
25   // Multi-level aliases are not supported. This just simplifies option
26   // tracking, it is not an inherent limitation.
27   assert((!Info || !getAlias().isValid() || !getAlias().getAlias().isValid()) &&
28          "Multi-level aliases are not supported.");
29
30   if (Info && getAliasArgs()) {
31     assert(getAlias().isValid() && "Only alias options can have alias args.");
32     assert(getKind() == FlagClass && "Only Flag aliases can have alias args.");
33     assert(getAlias().getKind() != FlagClass &&
34            "Cannot provide alias args to a flag option.");
35   }
36 }
37
38 void Option::dump() const {
39   llvm::errs() << "<";
40   switch (getKind()) {
41 #define P(N) case N: llvm::errs() << #N; break
42     P(GroupClass);
43     P(InputClass);
44     P(UnknownClass);
45     P(FlagClass);
46     P(JoinedClass);
47     P(SeparateClass);
48     P(CommaJoinedClass);
49     P(MultiArgClass);
50     P(JoinedOrSeparateClass);
51     P(JoinedAndSeparateClass);
52     P(RemainingArgsClass);
53 #undef P
54   }
55
56   if (Info->Prefixes) {
57     llvm::errs() << " Prefixes:[";
58     for (const char * const *Pre = Info->Prefixes; *Pre != nullptr; ++Pre) {
59       llvm::errs() << '"' << *Pre << (*(Pre + 1) == nullptr ? "\"" : "\", ");
60     }
61     llvm::errs() << ']';
62   }
63
64   llvm::errs() << " Name:\"" << getName() << '"';
65
66   const Option Group = getGroup();
67   if (Group.isValid()) {
68     llvm::errs() << " Group:";
69     Group.dump();
70   }
71
72   const Option Alias = getAlias();
73   if (Alias.isValid()) {
74     llvm::errs() << " Alias:";
75     Alias.dump();
76   }
77
78   if (getKind() == MultiArgClass)
79     llvm::errs() << " NumArgs:" << getNumArgs();
80
81   llvm::errs() << ">\n";
82 }
83
84 bool Option::matches(OptSpecifier Opt) const {
85   // Aliases are never considered in matching, look through them.
86   const Option Alias = getAlias();
87   if (Alias.isValid())
88     return Alias.matches(Opt);
89
90   // Check exact match.
91   if (getID() == Opt.getID())
92     return true;
93
94   const Option Group = getGroup();
95   if (Group.isValid())
96     return Group.matches(Opt);
97   return false;
98 }
99
100 Arg *Option::accept(const ArgList &Args,
101                     unsigned &Index,
102                     unsigned ArgSize) const {
103   const Option &UnaliasedOption = getUnaliasedOption();
104   StringRef Spelling;
105   // If the option was an alias, get the spelling from the unaliased one.
106   if (getID() == UnaliasedOption.getID()) {
107     Spelling = StringRef(Args.getArgString(Index), ArgSize);
108   } else {
109     Spelling = Args.MakeArgString(Twine(UnaliasedOption.getPrefix()) +
110                                   Twine(UnaliasedOption.getName()));
111   }
112
113   switch (getKind()) {
114   case FlagClass: {
115     if (ArgSize != strlen(Args.getArgString(Index)))
116       return nullptr;
117
118     Arg *A = new Arg(UnaliasedOption, Spelling, Index++);
119     if (getAliasArgs()) {
120       const char *Val = getAliasArgs();
121       while (*Val != '\0') {
122         A->getValues().push_back(Val);
123
124         // Move past the '\0' to the next argument.
125         Val += strlen(Val) + 1;
126       }
127     }
128     return A;
129   }
130   case JoinedClass: {
131     const char *Value = Args.getArgString(Index) + ArgSize;
132     return new Arg(UnaliasedOption, Spelling, Index++, Value);
133   }
134   case CommaJoinedClass: {
135     // Always matches.
136     const char *Str = Args.getArgString(Index) + ArgSize;
137     Arg *A = new Arg(UnaliasedOption, Spelling, Index++);
138
139     // Parse out the comma separated values.
140     const char *Prev = Str;
141     for (;; ++Str) {
142       char c = *Str;
143
144       if (!c || c == ',') {
145         if (Prev != Str) {
146           char *Value = new char[Str - Prev + 1];
147           memcpy(Value, Prev, Str - Prev);
148           Value[Str - Prev] = '\0';
149           A->getValues().push_back(Value);
150         }
151
152         if (!c)
153           break;
154
155         Prev = Str + 1;
156       }
157     }
158     A->setOwnsValues(true);
159
160     return A;
161   }
162   case SeparateClass:
163     // Matches iff this is an exact match.
164     // FIXME: Avoid strlen.
165     if (ArgSize != strlen(Args.getArgString(Index)))
166       return nullptr;
167
168     Index += 2;
169     if (Index > Args.getNumInputArgStrings() ||
170         Args.getArgString(Index - 1) == nullptr)
171       return nullptr;
172
173     return new Arg(UnaliasedOption, Spelling,
174                    Index - 2, Args.getArgString(Index - 1));
175   case MultiArgClass: {
176     // Matches iff this is an exact match.
177     // FIXME: Avoid strlen.
178     if (ArgSize != strlen(Args.getArgString(Index)))
179       return nullptr;
180
181     Index += 1 + getNumArgs();
182     if (Index > Args.getNumInputArgStrings())
183       return nullptr;
184
185     Arg *A = new Arg(UnaliasedOption, Spelling, Index - 1 - getNumArgs(),
186                       Args.getArgString(Index - getNumArgs()));
187     for (unsigned i = 1; i != getNumArgs(); ++i)
188       A->getValues().push_back(Args.getArgString(Index - getNumArgs() + i));
189     return A;
190   }
191   case JoinedOrSeparateClass: {
192     // If this is not an exact match, it is a joined arg.
193     // FIXME: Avoid strlen.
194     if (ArgSize != strlen(Args.getArgString(Index))) {
195       const char *Value = Args.getArgString(Index) + ArgSize;
196       return new Arg(*this, Spelling, Index++, Value);
197     }
198
199     // Otherwise it must be separate.
200     Index += 2;
201     if (Index > Args.getNumInputArgStrings() ||
202         Args.getArgString(Index - 1) == nullptr)
203       return nullptr;
204
205     return new Arg(UnaliasedOption, Spelling,
206                    Index - 2, Args.getArgString(Index - 1));
207   }
208   case JoinedAndSeparateClass:
209     // Always matches.
210     Index += 2;
211     if (Index > Args.getNumInputArgStrings() ||
212         Args.getArgString(Index - 1) == nullptr)
213       return nullptr;
214
215     return new Arg(UnaliasedOption, Spelling, Index - 2,
216                    Args.getArgString(Index - 2) + ArgSize,
217                    Args.getArgString(Index - 1));
218   case RemainingArgsClass: {
219     // Matches iff this is an exact match.
220     // FIXME: Avoid strlen.
221     if (ArgSize != strlen(Args.getArgString(Index)))
222       return nullptr;
223     Arg *A = new Arg(UnaliasedOption, Spelling, Index++);
224     while (Index < Args.getNumInputArgStrings() &&
225            Args.getArgString(Index) != nullptr)
226       A->getValues().push_back(Args.getArgString(Index++));
227     return A;
228   }
229   default:
230     llvm_unreachable("Invalid option kind!");
231   }
232 }