blob: 47a06529654782d1033e22470fae99dda66f9ba0 [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 Dunbar1d189e12009-11-18 20:19:19 +000019Option::Option(OptionClass _Kind, unsigned _ID, const char *_Name,
Mike Stump1eb44332009-09-09 15:08:12 +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),
Mike Stump1eb44332009-09-09 15:08:12 +000024 DriverOption(false), NoArgumentUnused(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 Dunbar1eb4e642009-03-03 05:55:11 +000031}
32
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +000033Option::~Option() {
34}
35
36void Option::dump() const {
37 llvm::errs() << "<";
38 switch (Kind) {
39 default:
40 assert(0 && "Invalid kind");
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#undef P
53 }
54
55 llvm::errs() << " Name:\"" << Name << '"';
56
57 if (Group) {
58 llvm::errs() << " Group:";
59 Group->dump();
60 }
Mike Stump1eb44332009-09-09 15:08:12 +000061
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +000062 if (Alias) {
63 llvm::errs() << " Alias:";
64 Alias->dump();
65 }
Mike Stump1eb44332009-09-09 15:08:12 +000066
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +000067 if (const MultiArgOption *MOA = dyn_cast<MultiArgOption>(this))
68 llvm::errs() << " NumArgs:" << MOA->getNumArgs();
69
70 llvm::errs() << ">\n";
71}
72
Daniel Dunbar1eb4e642009-03-03 05:55:11 +000073bool Option::matches(const Option *Opt) const {
Daniel Dunbarb32aa512009-11-19 03:26:50 +000074 // Aliases are never considered in matching, look through them.
Daniel Dunbar1eb4e642009-03-03 05:55:11 +000075 if (Alias)
76 return Alias->matches(Opt);
Mike Stump1eb44332009-09-09 15:08:12 +000077
Daniel Dunbar1eb4e642009-03-03 05:55:11 +000078 if (this == Opt)
79 return true;
Mike Stump1eb44332009-09-09 15:08:12 +000080
Daniel Dunbar1eb4e642009-03-03 05:55:11 +000081 if (Group)
82 return Group->matches(Opt);
83 return false;
84}
85
Daniel Dunbar1d189e12009-11-18 20:19:19 +000086bool Option::matches(unsigned Id) const {
Daniel Dunbarb32aa512009-11-19 03:26:50 +000087 // Aliases are never considered in matching, look through them.
Daniel Dunbarcf0dd152009-03-12 01:34:20 +000088 if (Alias)
89 return Alias->matches(Id);
Mike Stump1eb44332009-09-09 15:08:12 +000090
Daniel Dunbarcf0dd152009-03-12 01:34:20 +000091 if (ID == Id)
92 return true;
Mike Stump1eb44332009-09-09 15:08:12 +000093
Daniel Dunbarcf0dd152009-03-12 01:34:20 +000094 if (Group)
95 return Group->matches(Id);
96 return false;
97}
98
Daniel Dunbar1d189e12009-11-18 20:19:19 +000099OptionGroup::OptionGroup(unsigned ID, const char *Name,
Daniel Dunbar30b055f2009-03-04 21:53:04 +0000100 const OptionGroup *Group)
101 : Option(Option::GroupClass, ID, Name, Group, 0) {
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +0000102}
103
Daniel Dunbarf3cad362009-03-25 04:13:45 +0000104Arg *OptionGroup::accept(const InputArgList &Args, unsigned &Index) const {
Daniel Dunbarb0c4df52009-03-22 23:26:43 +0000105 assert(0 && "accept() should never be called on an OptionGroup");
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +0000106 return 0;
Daniel Dunbar1eb4e642009-03-03 05:55:11 +0000107}
108
109InputOption::InputOption()
Daniel Dunbarb349fcc2009-03-12 03:42:54 +0000110 : Option(Option::InputClass, options::OPT_INPUT, "<input>", 0, 0) {
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +0000111}
112
Daniel Dunbarf3cad362009-03-25 04:13:45 +0000113Arg *InputOption::accept(const InputArgList &Args, unsigned &Index) const {
Daniel Dunbarb0c4df52009-03-22 23:26:43 +0000114 assert(0 && "accept() should never be called on an InputOption");
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +0000115 return 0;
Daniel Dunbar1eb4e642009-03-03 05:55:11 +0000116}
117
118UnknownOption::UnknownOption()
Daniel Dunbarb349fcc2009-03-12 03:42:54 +0000119 : Option(Option::UnknownClass, options::OPT_UNKNOWN, "<unknown>", 0, 0) {
Daniel Dunbar1eb4e642009-03-03 05:55:11 +0000120}
121
Daniel Dunbarf3cad362009-03-25 04:13:45 +0000122Arg *UnknownOption::accept(const InputArgList &Args, unsigned &Index) const {
Daniel Dunbarb0c4df52009-03-22 23:26:43 +0000123 assert(0 && "accept() should never be called on an UnknownOption");
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +0000124 return 0;
Daniel Dunbar1eb4e642009-03-03 05:55:11 +0000125}
126
Daniel Dunbar1d189e12009-11-18 20:19:19 +0000127FlagOption::FlagOption(unsigned ID, const char *Name,
Daniel Dunbar30b055f2009-03-04 21:53:04 +0000128 const OptionGroup *Group, const Option *Alias)
129 : Option(Option::FlagClass, ID, Name, Group, Alias) {
Daniel Dunbar1eb4e642009-03-03 05:55:11 +0000130}
131
Daniel Dunbarf3cad362009-03-25 04:13:45 +0000132Arg *FlagOption::accept(const InputArgList &Args, unsigned &Index) const {
Mike Stump1eb44332009-09-09 15:08:12 +0000133 // Matches iff this is an exact match.
Daniel Dunbarbbf842b2009-03-04 23:22:02 +0000134 // FIXME: Avoid strlen.
135 if (strlen(getName()) != strlen(Args.getArgString(Index)))
136 return 0;
137
Daniel Dunbar06482622009-03-05 06:38:47 +0000138 return new FlagArg(this, Index++);
Daniel Dunbar1eb4e642009-03-03 05:55:11 +0000139}
140
Daniel Dunbar1d189e12009-11-18 20:19:19 +0000141JoinedOption::JoinedOption(unsigned ID, const char *Name,
Daniel Dunbar30b055f2009-03-04 21:53:04 +0000142 const OptionGroup *Group, const Option *Alias)
143 : Option(Option::JoinedClass, ID, Name, Group, Alias) {
Daniel Dunbar1eb4e642009-03-03 05:55:11 +0000144}
145
Daniel Dunbarf3cad362009-03-25 04:13:45 +0000146Arg *JoinedOption::accept(const InputArgList &Args, unsigned &Index) const {
Daniel Dunbarbbf842b2009-03-04 23:22:02 +0000147 // Always matches.
148 return new JoinedArg(this, Index++);
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +0000149}
150
Daniel Dunbar1d189e12009-11-18 20:19:19 +0000151CommaJoinedOption::CommaJoinedOption(unsigned ID, const char *Name,
Mike Stump1eb44332009-09-09 15:08:12 +0000152 const OptionGroup *Group,
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +0000153 const Option *Alias)
Daniel Dunbar30b055f2009-03-04 21:53:04 +0000154 : Option(Option::CommaJoinedClass, ID, Name, Group, Alias) {
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +0000155}
156
Mike Stump1eb44332009-09-09 15:08:12 +0000157Arg *CommaJoinedOption::accept(const InputArgList &Args,
Daniel Dunbarf3cad362009-03-25 04:13:45 +0000158 unsigned &Index) const {
Daniel Dunbarbbf842b2009-03-04 23:22:02 +0000159 // Always matches. We count the commas now so we can answer
160 // getNumValues easily.
Mike Stump1eb44332009-09-09 15:08:12 +0000161
Daniel Dunbarbbf842b2009-03-04 23:22:02 +0000162 // Get the suffix string.
163 // FIXME: Avoid strlen, and move to helper method?
164 const char *Suffix = Args.getArgString(Index) + strlen(getName());
Daniel Dunbar06482622009-03-05 06:38:47 +0000165 return new CommaJoinedArg(this, Index++, Suffix);
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +0000166}
167
Daniel Dunbar1d189e12009-11-18 20:19:19 +0000168SeparateOption::SeparateOption(unsigned ID, const char *Name,
Daniel Dunbar30b055f2009-03-04 21:53:04 +0000169 const OptionGroup *Group, const Option *Alias)
170 : Option(Option::SeparateClass, ID, Name, Group, Alias) {
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +0000171}
172
Daniel Dunbarf3cad362009-03-25 04:13:45 +0000173Arg *SeparateOption::accept(const InputArgList &Args, unsigned &Index) const {
Mike Stump1eb44332009-09-09 15:08:12 +0000174 // Matches iff this is an exact match.
Daniel Dunbarbbf842b2009-03-04 23:22:02 +0000175 // FIXME: Avoid strlen.
176 if (strlen(getName()) != strlen(Args.getArgString(Index)))
177 return 0;
178
Daniel Dunbarbbf842b2009-03-04 23:22:02 +0000179 Index += 2;
Daniel Dunbarb0c4df52009-03-22 23:26:43 +0000180 if (Index > Args.getNumInputArgStrings())
181 return 0;
182
Daniel Dunbarbbf842b2009-03-04 23:22:02 +0000183 return new SeparateArg(this, Index - 2, 1);
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +0000184}
185
Daniel Dunbar1d189e12009-11-18 20:19:19 +0000186MultiArgOption::MultiArgOption(unsigned ID, const char *Name,
Mike Stump1eb44332009-09-09 15:08:12 +0000187 const OptionGroup *Group, const Option *Alias,
Daniel Dunbar30b055f2009-03-04 21:53:04 +0000188 unsigned _NumArgs)
189 : Option(Option::MultiArgClass, ID, Name, Group, Alias), NumArgs(_NumArgs) {
Daniel Dunbar644eade2009-03-12 05:46:32 +0000190 assert(NumArgs > 1 && "Invalid MultiArgOption!");
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +0000191}
192
Daniel Dunbarf3cad362009-03-25 04:13:45 +0000193Arg *MultiArgOption::accept(const InputArgList &Args, unsigned &Index) const {
Mike Stump1eb44332009-09-09 15:08:12 +0000194 // Matches iff this is an exact match.
Daniel Dunbarbbf842b2009-03-04 23:22:02 +0000195 // FIXME: Avoid strlen.
196 if (strlen(getName()) != strlen(Args.getArgString(Index)))
197 return 0;
198
Daniel Dunbarbbf842b2009-03-04 23:22:02 +0000199 Index += 1 + NumArgs;
Daniel Dunbarb0c4df52009-03-22 23:26:43 +0000200 if (Index > Args.getNumInputArgStrings())
201 return 0;
202
Daniel Dunbarbbf842b2009-03-04 23:22:02 +0000203 return new SeparateArg(this, Index - 1 - NumArgs, NumArgs);
Daniel Dunbar1eb4e642009-03-03 05:55:11 +0000204}
205
Daniel Dunbar1d189e12009-11-18 20:19:19 +0000206JoinedOrSeparateOption::JoinedOrSeparateOption(unsigned ID, const char *Name,
Mike Stump1eb44332009-09-09 15:08:12 +0000207 const OptionGroup *Group,
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +0000208 const Option *Alias)
Daniel Dunbar30b055f2009-03-04 21:53:04 +0000209 : Option(Option::JoinedOrSeparateClass, ID, Name, Group, Alias) {
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +0000210}
211
Mike Stump1eb44332009-09-09 15:08:12 +0000212Arg *JoinedOrSeparateOption::accept(const InputArgList &Args,
Daniel Dunbarb0c4df52009-03-22 23:26:43 +0000213 unsigned &Index) const {
Daniel Dunbarbbf842b2009-03-04 23:22:02 +0000214 // If this is not an exact match, it is a joined arg.
215 // FIXME: Avoid strlen.
216 if (strlen(getName()) != strlen(Args.getArgString(Index)))
217 return new JoinedArg(this, Index++);
218
219 // Otherwise it must be separate.
Daniel Dunbarbbf842b2009-03-04 23:22:02 +0000220 Index += 2;
Daniel Dunbarb0c4df52009-03-22 23:26:43 +0000221 if (Index > Args.getNumInputArgStrings())
222 return 0;
223
Mike Stump1eb44332009-09-09 15:08:12 +0000224 return new SeparateArg(this, Index - 2, 1);
Daniel Dunbar1eb4e642009-03-03 05:55:11 +0000225}
226
Daniel Dunbar1d189e12009-11-18 20:19:19 +0000227JoinedAndSeparateOption::JoinedAndSeparateOption(unsigned ID,
Mike Stump1eb44332009-09-09 15:08:12 +0000228 const char *Name,
229 const OptionGroup *Group,
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +0000230 const Option *Alias)
Daniel Dunbar30b055f2009-03-04 21:53:04 +0000231 : Option(Option::JoinedAndSeparateClass, ID, Name, Group, Alias) {
Daniel Dunbar1eb4e642009-03-03 05:55:11 +0000232}
233
Mike Stump1eb44332009-09-09 15:08:12 +0000234Arg *JoinedAndSeparateOption::accept(const InputArgList &Args,
Daniel Dunbarb0c4df52009-03-22 23:26:43 +0000235 unsigned &Index) const {
Daniel Dunbarbbf842b2009-03-04 23:22:02 +0000236 // Always matches.
237
Daniel Dunbarbbf842b2009-03-04 23:22:02 +0000238 Index += 2;
Daniel Dunbarb0c4df52009-03-22 23:26:43 +0000239 if (Index > Args.getNumInputArgStrings())
240 return 0;
241
Daniel Dunbarbbf842b2009-03-04 23:22:02 +0000242 return new JoinedAndSeparateArg(this, Index - 2);
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +0000243}
Daniel Dunbar1eb4e642009-03-03 05:55:11 +0000244