blob: 6ea02aaf40e0ccfad8984cf0469623a3cb718667 [file] [log] [blame]
Daniel Dunbar1eb4e642009-03-03 05:55:11 +00001//===--- 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 "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"
Daniel Dunbar1eb4e642009-03-03 05:55:11 +000015#include <cassert>
Daniel Dunbarbbf842b2009-03-04 23:22:02 +000016#include <algorithm>
Daniel Dunbar1eb4e642009-03-03 05:55:11 +000017using namespace clang::driver;
18
Daniel Dunbar30b055f2009-03-04 21:53:04 +000019Option::Option(OptionClass _Kind, options::ID _ID, const char *_Name,
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +000020 const OptionGroup *_Group, const Option *_Alias)
Daniel Dunbar30b055f2009-03-04 21:53:04 +000021 : Kind(_Kind), ID(_ID), Name(_Name), Group(_Group), Alias(_Alias),
Daniel Dunbar0f9098e2009-03-04 21:05:23 +000022 Unsupported(false), LinkerInput(false), NoOptAsInput(false),
Daniel Dunbar6d954d72009-03-18 08:01:15 +000023 ForceSeparateRender(false), ForceJoinedRender(false),
24 ForwardToGCC(true)
Daniel Dunbar0f9098e2009-03-04 21:05:23 +000025{
Daniel Dunbar1eb4e642009-03-03 05:55:11 +000026
27 // Multi-level aliases are not supported, and alias options cannot
28 // have groups. This just simplifies option tracking, it is not an
29 // inherent limitation.
30 assert((!Alias || (!Alias->Alias && !Group)) &&
31 "Multi-level aliases and aliases with groups are unsupported.");
32}
33
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +000034Option::~Option() {
35}
36
37void Option::dump() const {
38 llvm::errs() << "<";
39 switch (Kind) {
40 default:
41 assert(0 && "Invalid kind");
42#define P(N) case N: llvm::errs() << #N; break
43 P(GroupClass);
44 P(InputClass);
45 P(UnknownClass);
46 P(FlagClass);
47 P(JoinedClass);
48 P(SeparateClass);
49 P(CommaJoinedClass);
50 P(MultiArgClass);
51 P(JoinedOrSeparateClass);
52 P(JoinedAndSeparateClass);
53#undef P
54 }
55
56 llvm::errs() << " Name:\"" << Name << '"';
57
58 if (Group) {
59 llvm::errs() << " Group:";
60 Group->dump();
61 }
62
63 if (Alias) {
64 llvm::errs() << " Alias:";
65 Alias->dump();
66 }
67
68 if (const MultiArgOption *MOA = dyn_cast<MultiArgOption>(this))
69 llvm::errs() << " NumArgs:" << MOA->getNumArgs();
70
71 llvm::errs() << ">\n";
72}
73
Daniel Dunbar1eb4e642009-03-03 05:55:11 +000074bool Option::matches(const Option *Opt) const {
75 // Aliases are never considered in matching.
76 if (Opt->getAlias())
77 return matches(Opt->getAlias());
78 if (Alias)
79 return Alias->matches(Opt);
80
81 if (this == Opt)
82 return true;
83
84 if (Group)
85 return Group->matches(Opt);
86 return false;
87}
88
Daniel Dunbarcf0dd152009-03-12 01:34:20 +000089bool Option::matches(options::ID Id) const {
90 // FIXME: Decide what to do here; we should either pull out the
91 // handling of alias on the option for Id from the other matches, or
92 // find some other solution (which hopefully doesn't require using
93 // the option table).
94 if (Alias)
95 return Alias->matches(Id);
96
97 if (ID == Id)
98 return true;
99
100 if (Group)
101 return Group->matches(Id);
102 return false;
103}
104
Daniel Dunbar30b055f2009-03-04 21:53:04 +0000105OptionGroup::OptionGroup(options::ID ID, const char *Name,
106 const OptionGroup *Group)
107 : Option(Option::GroupClass, ID, Name, Group, 0) {
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +0000108}
109
Daniel Dunbarf3cad362009-03-25 04:13:45 +0000110Arg *OptionGroup::accept(const InputArgList &Args, unsigned &Index) const {
Daniel Dunbarb0c4df52009-03-22 23:26:43 +0000111 assert(0 && "accept() should never be called on an OptionGroup");
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +0000112 return 0;
Daniel Dunbar1eb4e642009-03-03 05:55:11 +0000113}
114
115InputOption::InputOption()
Daniel Dunbarb349fcc2009-03-12 03:42:54 +0000116 : Option(Option::InputClass, options::OPT_INPUT, "<input>", 0, 0) {
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +0000117}
118
Daniel Dunbarf3cad362009-03-25 04:13:45 +0000119Arg *InputOption::accept(const InputArgList &Args, unsigned &Index) const {
Daniel Dunbarb0c4df52009-03-22 23:26:43 +0000120 assert(0 && "accept() should never be called on an InputOption");
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +0000121 return 0;
Daniel Dunbar1eb4e642009-03-03 05:55:11 +0000122}
123
124UnknownOption::UnknownOption()
Daniel Dunbarb349fcc2009-03-12 03:42:54 +0000125 : Option(Option::UnknownClass, options::OPT_UNKNOWN, "<unknown>", 0, 0) {
Daniel Dunbar1eb4e642009-03-03 05:55:11 +0000126}
127
Daniel Dunbarf3cad362009-03-25 04:13:45 +0000128Arg *UnknownOption::accept(const InputArgList &Args, unsigned &Index) const {
Daniel Dunbarb0c4df52009-03-22 23:26:43 +0000129 assert(0 && "accept() should never be called on an UnknownOption");
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +0000130 return 0;
Daniel Dunbar1eb4e642009-03-03 05:55:11 +0000131}
132
Daniel Dunbar30b055f2009-03-04 21:53:04 +0000133FlagOption::FlagOption(options::ID ID, const char *Name,
134 const OptionGroup *Group, const Option *Alias)
135 : Option(Option::FlagClass, ID, Name, Group, Alias) {
Daniel Dunbar1eb4e642009-03-03 05:55:11 +0000136}
137
Daniel Dunbarf3cad362009-03-25 04:13:45 +0000138Arg *FlagOption::accept(const InputArgList &Args, unsigned &Index) const {
Daniel Dunbarbbf842b2009-03-04 23:22:02 +0000139 // Matches iff this is an exact match.
140 // FIXME: Avoid strlen.
141 if (strlen(getName()) != strlen(Args.getArgString(Index)))
142 return 0;
143
Daniel Dunbar06482622009-03-05 06:38:47 +0000144 return new FlagArg(this, Index++);
Daniel Dunbar1eb4e642009-03-03 05:55:11 +0000145}
146
Daniel Dunbar30b055f2009-03-04 21:53:04 +0000147JoinedOption::JoinedOption(options::ID ID, const char *Name,
148 const OptionGroup *Group, const Option *Alias)
149 : Option(Option::JoinedClass, ID, Name, Group, Alias) {
Daniel Dunbar1eb4e642009-03-03 05:55:11 +0000150}
151
Daniel Dunbarf3cad362009-03-25 04:13:45 +0000152Arg *JoinedOption::accept(const InputArgList &Args, unsigned &Index) const {
Daniel Dunbarbbf842b2009-03-04 23:22:02 +0000153 // Always matches.
154 return new JoinedArg(this, Index++);
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +0000155}
156
Daniel Dunbar30b055f2009-03-04 21:53:04 +0000157CommaJoinedOption::CommaJoinedOption(options::ID ID, const char *Name,
158 const OptionGroup *Group,
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +0000159 const Option *Alias)
Daniel Dunbar30b055f2009-03-04 21:53:04 +0000160 : Option(Option::CommaJoinedClass, ID, Name, Group, Alias) {
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +0000161}
162
Daniel Dunbarf3cad362009-03-25 04:13:45 +0000163Arg *CommaJoinedOption::accept(const InputArgList &Args,
164 unsigned &Index) const {
Daniel Dunbarbbf842b2009-03-04 23:22:02 +0000165 // Always matches. We count the commas now so we can answer
166 // getNumValues easily.
167
168 // Get the suffix string.
169 // FIXME: Avoid strlen, and move to helper method?
170 const char *Suffix = Args.getArgString(Index) + strlen(getName());
Daniel Dunbar06482622009-03-05 06:38:47 +0000171 return new CommaJoinedArg(this, Index++, Suffix);
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +0000172}
173
Daniel Dunbar30b055f2009-03-04 21:53:04 +0000174SeparateOption::SeparateOption(options::ID ID, const char *Name,
175 const OptionGroup *Group, const Option *Alias)
176 : Option(Option::SeparateClass, ID, Name, Group, Alias) {
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +0000177}
178
Daniel Dunbarf3cad362009-03-25 04:13:45 +0000179Arg *SeparateOption::accept(const InputArgList &Args, unsigned &Index) const {
Daniel Dunbarbbf842b2009-03-04 23:22:02 +0000180 // Matches iff this is an exact match.
181 // FIXME: Avoid strlen.
182 if (strlen(getName()) != strlen(Args.getArgString(Index)))
183 return 0;
184
Daniel Dunbarbbf842b2009-03-04 23:22:02 +0000185 Index += 2;
Daniel Dunbarb0c4df52009-03-22 23:26:43 +0000186 if (Index > Args.getNumInputArgStrings())
187 return 0;
188
Daniel Dunbarbbf842b2009-03-04 23:22:02 +0000189 return new SeparateArg(this, Index - 2, 1);
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +0000190}
191
Daniel Dunbar30b055f2009-03-04 21:53:04 +0000192MultiArgOption::MultiArgOption(options::ID ID, const char *Name,
193 const OptionGroup *Group, const Option *Alias,
194 unsigned _NumArgs)
195 : Option(Option::MultiArgClass, ID, Name, Group, Alias), NumArgs(_NumArgs) {
Daniel Dunbar644eade2009-03-12 05:46:32 +0000196 assert(NumArgs > 1 && "Invalid MultiArgOption!");
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +0000197}
198
Daniel Dunbarf3cad362009-03-25 04:13:45 +0000199Arg *MultiArgOption::accept(const InputArgList &Args, unsigned &Index) const {
Daniel Dunbarbbf842b2009-03-04 23:22:02 +0000200 // Matches iff this is an exact match.
201 // FIXME: Avoid strlen.
202 if (strlen(getName()) != strlen(Args.getArgString(Index)))
203 return 0;
204
Daniel Dunbarbbf842b2009-03-04 23:22:02 +0000205 Index += 1 + NumArgs;
Daniel Dunbarb0c4df52009-03-22 23:26:43 +0000206 if (Index > Args.getNumInputArgStrings())
207 return 0;
208
Daniel Dunbarbbf842b2009-03-04 23:22:02 +0000209 return new SeparateArg(this, Index - 1 - NumArgs, NumArgs);
Daniel Dunbar1eb4e642009-03-03 05:55:11 +0000210}
211
Daniel Dunbar30b055f2009-03-04 21:53:04 +0000212JoinedOrSeparateOption::JoinedOrSeparateOption(options::ID ID, const char *Name,
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +0000213 const OptionGroup *Group,
214 const Option *Alias)
Daniel Dunbar30b055f2009-03-04 21:53:04 +0000215 : Option(Option::JoinedOrSeparateClass, ID, Name, Group, Alias) {
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +0000216}
217
Daniel Dunbarf3cad362009-03-25 04:13:45 +0000218Arg *JoinedOrSeparateOption::accept(const InputArgList &Args,
Daniel Dunbarb0c4df52009-03-22 23:26:43 +0000219 unsigned &Index) const {
Daniel Dunbarbbf842b2009-03-04 23:22:02 +0000220 // If this is not an exact match, it is a joined arg.
221 // FIXME: Avoid strlen.
222 if (strlen(getName()) != strlen(Args.getArgString(Index)))
223 return new JoinedArg(this, Index++);
224
225 // Otherwise it must be separate.
Daniel Dunbarbbf842b2009-03-04 23:22:02 +0000226 Index += 2;
Daniel Dunbarb0c4df52009-03-22 23:26:43 +0000227 if (Index > Args.getNumInputArgStrings())
228 return 0;
229
Daniel Dunbarbbf842b2009-03-04 23:22:02 +0000230 return new SeparateArg(this, Index - 2, 1);
Daniel Dunbar1eb4e642009-03-03 05:55:11 +0000231}
232
Daniel Dunbar30b055f2009-03-04 21:53:04 +0000233JoinedAndSeparateOption::JoinedAndSeparateOption(options::ID ID,
234 const char *Name,
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +0000235 const OptionGroup *Group,
236 const Option *Alias)
Daniel Dunbar30b055f2009-03-04 21:53:04 +0000237 : Option(Option::JoinedAndSeparateClass, ID, Name, Group, Alias) {
Daniel Dunbar1eb4e642009-03-03 05:55:11 +0000238}
239
Daniel Dunbarf3cad362009-03-25 04:13:45 +0000240Arg *JoinedAndSeparateOption::accept(const InputArgList &Args,
Daniel Dunbarb0c4df52009-03-22 23:26:43 +0000241 unsigned &Index) const {
Daniel Dunbarbbf842b2009-03-04 23:22:02 +0000242 // Always matches.
243
Daniel Dunbarbbf842b2009-03-04 23:22:02 +0000244 Index += 2;
Daniel Dunbarb0c4df52009-03-22 23:26:43 +0000245 if (Index > Args.getNumInputArgStrings())
246 return 0;
247
Daniel Dunbarbbf842b2009-03-04 23:22:02 +0000248 return new JoinedAndSeparateArg(this, Index - 2);
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +0000249}
Daniel Dunbar1eb4e642009-03-03 05:55:11 +0000250