blob: cd93dd832b1ae70ff81f745860b62991cca7ef4d [file] [log] [blame]
Nick Lewycky3fdcc6f2010-12-31 17:31:54 +00001//===--- Option.cpp - Abstract Driver Options -----------------------------===//
Daniel Dunbar1eb4e642009-03-03 05:55:11 +00002//
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 "clang/Driver/Option.h"
Daniel Dunbarbbf842b2009-03-04 23:22:02 +000011
12#include "clang/Driver/Arg.h"
13#include "clang/Driver/ArgList.h"
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +000014#include "llvm/Support/raw_ostream.h"
David Blaikie548f6c82011-09-23 05:57:42 +000015#include "llvm/Support/ErrorHandling.h"
Daniel Dunbar1eb4e642009-03-03 05:55:11 +000016#include <cassert>
Daniel Dunbarbbf842b2009-03-04 23:22:02 +000017#include <algorithm>
Daniel Dunbar1eb4e642009-03-03 05:55:11 +000018using namespace clang::driver;
19
Daniel Dunbar9e1f9822009-11-19 04:14:53 +000020Option::Option(OptionClass _Kind, OptSpecifier _ID, const char *_Name,
Mike Stump1eb44332009-09-09 15:08:12 +000021 const OptionGroup *_Group, const Option *_Alias)
Daniel Dunbar9e1f9822009-11-19 04:14:53 +000022 : Kind(_Kind), ID(_ID.getID()), Name(_Name), Group(_Group), Alias(_Alias),
Daniel Dunbar0f9098e2009-03-04 21:05:23 +000023 Unsupported(false), LinkerInput(false), NoOptAsInput(false),
Daniel Dunbarcaeed1d2010-08-13 04:44:20 +000024 DriverOption(false), NoArgumentUnused(false), NoForward(false) {
Daniel Dunbar1eb4e642009-03-03 05:55:11 +000025
26 // Multi-level aliases are not supported, and alias options cannot
27 // have groups. This just simplifies option tracking, it is not an
28 // inherent limitation.
29 assert((!Alias || (!Alias->Alias && !Group)) &&
Mike Stump1eb44332009-09-09 15:08:12 +000030 "Multi-level aliases and aliases with groups are unsupported.");
Daniel Dunbare375c4a2010-06-09 22:31:04 +000031
32 // Initialize rendering options based on the class.
33 switch (Kind) {
34 case GroupClass:
35 case InputClass:
36 case UnknownClass:
37 RenderStyle = RenderValuesStyle;
38 break;
39
40 case JoinedClass:
41 case JoinedAndSeparateClass:
42 RenderStyle = RenderJoinedStyle;
43 break;
44
45 case CommaJoinedClass:
46 RenderStyle = RenderCommaJoinedStyle;
47 break;
48
49 case FlagClass:
50 case SeparateClass:
51 case MultiArgClass:
52 case JoinedOrSeparateClass:
53 RenderStyle = RenderSeparateStyle;
54 break;
55 }
Daniel Dunbar1eb4e642009-03-03 05:55:11 +000056}
57
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +000058Option::~Option() {
59}
60
61void Option::dump() const {
62 llvm::errs() << "<";
63 switch (Kind) {
64 default:
David Blaikieb219cfc2011-09-23 05:06:16 +000065 llvm_unreachable("Invalid kind");
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +000066#define P(N) case N: llvm::errs() << #N; break
67 P(GroupClass);
68 P(InputClass);
69 P(UnknownClass);
70 P(FlagClass);
71 P(JoinedClass);
72 P(SeparateClass);
73 P(CommaJoinedClass);
74 P(MultiArgClass);
75 P(JoinedOrSeparateClass);
76 P(JoinedAndSeparateClass);
77#undef P
78 }
79
80 llvm::errs() << " Name:\"" << Name << '"';
81
82 if (Group) {
83 llvm::errs() << " Group:";
84 Group->dump();
85 }
Mike Stump1eb44332009-09-09 15:08:12 +000086
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +000087 if (Alias) {
88 llvm::errs() << " Alias:";
89 Alias->dump();
90 }
Mike Stump1eb44332009-09-09 15:08:12 +000091
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +000092 if (const MultiArgOption *MOA = dyn_cast<MultiArgOption>(this))
93 llvm::errs() << " NumArgs:" << MOA->getNumArgs();
94
95 llvm::errs() << ">\n";
96}
97
Daniel Dunbar9e1f9822009-11-19 04:14:53 +000098bool Option::matches(OptSpecifier Opt) const {
Daniel Dunbarb32aa512009-11-19 03:26:50 +000099 // Aliases are never considered in matching, look through them.
Daniel Dunbar1eb4e642009-03-03 05:55:11 +0000100 if (Alias)
101 return Alias->matches(Opt);
Mike Stump1eb44332009-09-09 15:08:12 +0000102
Daniel Dunbar9e1f9822009-11-19 04:14:53 +0000103 // Check exact match.
104 if (ID == Opt)
Daniel Dunbar1eb4e642009-03-03 05:55:11 +0000105 return true;
Mike Stump1eb44332009-09-09 15:08:12 +0000106
Daniel Dunbar1eb4e642009-03-03 05:55:11 +0000107 if (Group)
108 return Group->matches(Opt);
109 return false;
110}
111
Daniel Dunbar9e1f9822009-11-19 04:14:53 +0000112OptionGroup::OptionGroup(OptSpecifier ID, const char *Name,
Daniel Dunbar30b055f2009-03-04 21:53:04 +0000113 const OptionGroup *Group)
114 : Option(Option::GroupClass, ID, Name, Group, 0) {
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +0000115}
116
Daniel Dunbar785e7962010-06-11 22:00:17 +0000117Arg *OptionGroup::accept(const ArgList &Args, unsigned &Index) const {
David Blaikieb219cfc2011-09-23 05:06:16 +0000118 llvm_unreachable("accept() should never be called on an OptionGroup");
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +0000119 return 0;
Daniel Dunbar1eb4e642009-03-03 05:55:11 +0000120}
121
Daniel Dunbara0289fd2009-11-19 04:25:06 +0000122InputOption::InputOption(OptSpecifier ID)
123 : Option(Option::InputClass, ID, "<input>", 0, 0) {
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +0000124}
125
Daniel Dunbar785e7962010-06-11 22:00:17 +0000126Arg *InputOption::accept(const ArgList &Args, unsigned &Index) const {
David Blaikieb219cfc2011-09-23 05:06:16 +0000127 llvm_unreachable("accept() should never be called on an InputOption");
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +0000128 return 0;
Daniel Dunbar1eb4e642009-03-03 05:55:11 +0000129}
130
Daniel Dunbara0289fd2009-11-19 04:25:06 +0000131UnknownOption::UnknownOption(OptSpecifier ID)
132 : Option(Option::UnknownClass, ID, "<unknown>", 0, 0) {
Daniel Dunbar1eb4e642009-03-03 05:55:11 +0000133}
134
Daniel Dunbar785e7962010-06-11 22:00:17 +0000135Arg *UnknownOption::accept(const ArgList &Args, unsigned &Index) const {
David Blaikieb219cfc2011-09-23 05:06:16 +0000136 llvm_unreachable("accept() should never be called on an UnknownOption");
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +0000137 return 0;
Daniel Dunbar1eb4e642009-03-03 05:55:11 +0000138}
139
Daniel Dunbar9e1f9822009-11-19 04:14:53 +0000140FlagOption::FlagOption(OptSpecifier ID, const char *Name,
Daniel Dunbar30b055f2009-03-04 21:53:04 +0000141 const OptionGroup *Group, const Option *Alias)
142 : Option(Option::FlagClass, ID, Name, Group, Alias) {
Daniel Dunbar1eb4e642009-03-03 05:55:11 +0000143}
144
Daniel Dunbar785e7962010-06-11 22:00:17 +0000145Arg *FlagOption::accept(const ArgList &Args, unsigned &Index) const {
Mike Stump1eb44332009-09-09 15:08:12 +0000146 // Matches iff this is an exact match.
Daniel Dunbarbbf842b2009-03-04 23:22:02 +0000147 // FIXME: Avoid strlen.
Douglas Gregorbcf6a802011-07-05 16:56:25 +0000148 if (getName().size() != strlen(Args.getArgString(Index)))
Daniel Dunbarbbf842b2009-03-04 23:22:02 +0000149 return 0;
150
Daniel Dunbar3856ab32010-06-09 22:44:34 +0000151 return new Arg(getUnaliasedOption(), Index++);
Daniel Dunbar1eb4e642009-03-03 05:55:11 +0000152}
153
Daniel Dunbar9e1f9822009-11-19 04:14:53 +0000154JoinedOption::JoinedOption(OptSpecifier ID, const char *Name,
Daniel Dunbar30b055f2009-03-04 21:53:04 +0000155 const OptionGroup *Group, const Option *Alias)
156 : Option(Option::JoinedClass, ID, Name, Group, Alias) {
Daniel Dunbar1eb4e642009-03-03 05:55:11 +0000157}
158
Daniel Dunbar785e7962010-06-11 22:00:17 +0000159Arg *JoinedOption::accept(const ArgList &Args, unsigned &Index) const {
Daniel Dunbarbbf842b2009-03-04 23:22:02 +0000160 // Always matches.
Douglas Gregorbcf6a802011-07-05 16:56:25 +0000161 const char *Value = Args.getArgString(Index) + getName().size();
Daniel Dunbar3856ab32010-06-09 22:44:34 +0000162 return new Arg(getUnaliasedOption(), Index++, Value);
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +0000163}
164
Daniel Dunbar9e1f9822009-11-19 04:14:53 +0000165CommaJoinedOption::CommaJoinedOption(OptSpecifier ID, const char *Name,
Mike Stump1eb44332009-09-09 15:08:12 +0000166 const OptionGroup *Group,
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +0000167 const Option *Alias)
Daniel Dunbar30b055f2009-03-04 21:53:04 +0000168 : Option(Option::CommaJoinedClass, ID, Name, Group, Alias) {
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +0000169}
170
Daniel Dunbar785e7962010-06-11 22:00:17 +0000171Arg *CommaJoinedOption::accept(const ArgList &Args,
Daniel Dunbarf3cad362009-03-25 04:13:45 +0000172 unsigned &Index) const {
Daniel Dunbar532c1ec2010-06-09 22:31:08 +0000173 // Always matches.
Douglas Gregorbcf6a802011-07-05 16:56:25 +0000174 const char *Str = Args.getArgString(Index) + getName().size();
Daniel Dunbar3856ab32010-06-09 22:44:34 +0000175 Arg *A = new Arg(getUnaliasedOption(), Index++);
Mike Stump1eb44332009-09-09 15:08:12 +0000176
Daniel Dunbar532c1ec2010-06-09 22:31:08 +0000177 // Parse out the comma separated values.
178 const char *Prev = Str;
179 for (;; ++Str) {
180 char c = *Str;
181
182 if (!c || c == ',') {
183 if (Prev != Str) {
184 char *Value = new char[Str - Prev + 1];
185 memcpy(Value, Prev, Str - Prev);
186 Value[Str - Prev] = '\0';
187 A->getValues().push_back(Value);
188 }
189
190 if (!c)
191 break;
192
193 Prev = Str + 1;
194 }
195 }
196 A->setOwnsValues(true);
197
198 return A;
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +0000199}
200
Daniel Dunbar9e1f9822009-11-19 04:14:53 +0000201SeparateOption::SeparateOption(OptSpecifier ID, const char *Name,
Daniel Dunbar30b055f2009-03-04 21:53:04 +0000202 const OptionGroup *Group, const Option *Alias)
203 : Option(Option::SeparateClass, ID, Name, Group, Alias) {
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +0000204}
205
Daniel Dunbar785e7962010-06-11 22:00:17 +0000206Arg *SeparateOption::accept(const ArgList &Args, unsigned &Index) const {
Mike Stump1eb44332009-09-09 15:08:12 +0000207 // Matches iff this is an exact match.
Daniel Dunbarbbf842b2009-03-04 23:22:02 +0000208 // FIXME: Avoid strlen.
Douglas Gregorbcf6a802011-07-05 16:56:25 +0000209 if (getName().size() != strlen(Args.getArgString(Index)))
Daniel Dunbarbbf842b2009-03-04 23:22:02 +0000210 return 0;
211
Daniel Dunbarbbf842b2009-03-04 23:22:02 +0000212 Index += 2;
Daniel Dunbarb0c4df52009-03-22 23:26:43 +0000213 if (Index > Args.getNumInputArgStrings())
214 return 0;
215
Daniel Dunbar3856ab32010-06-09 22:44:34 +0000216 return new Arg(getUnaliasedOption(), Index - 2, Args.getArgString(Index - 1));
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +0000217}
218
Daniel Dunbar9e1f9822009-11-19 04:14:53 +0000219MultiArgOption::MultiArgOption(OptSpecifier ID, const char *Name,
Mike Stump1eb44332009-09-09 15:08:12 +0000220 const OptionGroup *Group, const Option *Alias,
Daniel Dunbar30b055f2009-03-04 21:53:04 +0000221 unsigned _NumArgs)
222 : Option(Option::MultiArgClass, ID, Name, Group, Alias), NumArgs(_NumArgs) {
Daniel Dunbar644eade2009-03-12 05:46:32 +0000223 assert(NumArgs > 1 && "Invalid MultiArgOption!");
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +0000224}
225
Daniel Dunbar785e7962010-06-11 22:00:17 +0000226Arg *MultiArgOption::accept(const ArgList &Args, unsigned &Index) const {
Mike Stump1eb44332009-09-09 15:08:12 +0000227 // Matches iff this is an exact match.
Daniel Dunbarbbf842b2009-03-04 23:22:02 +0000228 // FIXME: Avoid strlen.
Douglas Gregorbcf6a802011-07-05 16:56:25 +0000229 if (getName().size() != strlen(Args.getArgString(Index)))
Daniel Dunbarbbf842b2009-03-04 23:22:02 +0000230 return 0;
231
Daniel Dunbarbbf842b2009-03-04 23:22:02 +0000232 Index += 1 + NumArgs;
Daniel Dunbarb0c4df52009-03-22 23:26:43 +0000233 if (Index > Args.getNumInputArgStrings())
234 return 0;
235
Daniel Dunbar3856ab32010-06-09 22:44:34 +0000236 Arg *A = new Arg(getUnaliasedOption(), Index - 1 - NumArgs,
237 Args.getArgString(Index - NumArgs));
Daniel Dunbar4465a772010-06-09 22:31:00 +0000238 for (unsigned i = 1; i != NumArgs; ++i)
239 A->getValues().push_back(Args.getArgString(Index - NumArgs + i));
240 return A;
Daniel Dunbar1eb4e642009-03-03 05:55:11 +0000241}
242
Daniel Dunbar312a8b72010-06-09 18:49:38 +0000243JoinedOrSeparateOption::JoinedOrSeparateOption(OptSpecifier ID,
244 const char *Name,
Mike Stump1eb44332009-09-09 15:08:12 +0000245 const OptionGroup *Group,
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +0000246 const Option *Alias)
Daniel Dunbar30b055f2009-03-04 21:53:04 +0000247 : Option(Option::JoinedOrSeparateClass, ID, Name, Group, Alias) {
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +0000248}
249
Daniel Dunbar785e7962010-06-11 22:00:17 +0000250Arg *JoinedOrSeparateOption::accept(const ArgList &Args,
Daniel Dunbarb0c4df52009-03-22 23:26:43 +0000251 unsigned &Index) const {
Daniel Dunbarbbf842b2009-03-04 23:22:02 +0000252 // If this is not an exact match, it is a joined arg.
253 // FIXME: Avoid strlen.
Douglas Gregorbcf6a802011-07-05 16:56:25 +0000254 if (getName().size() != strlen(Args.getArgString(Index))) {
255 const char *Value = Args.getArgString(Index) + getName().size();
Daniel Dunbar532c1ec2010-06-09 22:31:08 +0000256 return new Arg(this, Index++, Value);
Daniel Dunbar4465a772010-06-09 22:31:00 +0000257 }
Daniel Dunbarbbf842b2009-03-04 23:22:02 +0000258
259 // Otherwise it must be separate.
Daniel Dunbarbbf842b2009-03-04 23:22:02 +0000260 Index += 2;
Daniel Dunbarb0c4df52009-03-22 23:26:43 +0000261 if (Index > Args.getNumInputArgStrings())
262 return 0;
263
Daniel Dunbar3856ab32010-06-09 22:44:34 +0000264 return new Arg(getUnaliasedOption(), Index - 2, Args.getArgString(Index - 1));
Daniel Dunbar1eb4e642009-03-03 05:55:11 +0000265}
266
Daniel Dunbar9e1f9822009-11-19 04:14:53 +0000267JoinedAndSeparateOption::JoinedAndSeparateOption(OptSpecifier ID,
Mike Stump1eb44332009-09-09 15:08:12 +0000268 const char *Name,
269 const OptionGroup *Group,
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +0000270 const Option *Alias)
Daniel Dunbar30b055f2009-03-04 21:53:04 +0000271 : Option(Option::JoinedAndSeparateClass, ID, Name, Group, Alias) {
Daniel Dunbar1eb4e642009-03-03 05:55:11 +0000272}
273
Daniel Dunbar785e7962010-06-11 22:00:17 +0000274Arg *JoinedAndSeparateOption::accept(const ArgList &Args,
Daniel Dunbarb0c4df52009-03-22 23:26:43 +0000275 unsigned &Index) const {
Daniel Dunbarbbf842b2009-03-04 23:22:02 +0000276 // Always matches.
277
Daniel Dunbarbbf842b2009-03-04 23:22:02 +0000278 Index += 2;
Daniel Dunbarb0c4df52009-03-22 23:26:43 +0000279 if (Index > Args.getNumInputArgStrings())
280 return 0;
281
Daniel Dunbar3856ab32010-06-09 22:44:34 +0000282 return new Arg(getUnaliasedOption(), Index - 2,
Douglas Gregorbcf6a802011-07-05 16:56:25 +0000283 Args.getArgString(Index-2)+getName().size(),
Daniel Dunbar3856ab32010-06-09 22:44:34 +0000284 Args.getArgString(Index-1));
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +0000285}