blob: 17d00f50aa6f21e293e9d2b82ee7e4f58a54c7e9 [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 Dunbar9e1f9822009-11-19 04:14:53 +000019Option::Option(OptionClass _Kind, OptSpecifier _ID, const char *_Name,
Mike Stump1eb44332009-09-09 15:08:12 +000020 const OptionGroup *_Group, const Option *_Alias)
Daniel Dunbar9e1f9822009-11-19 04:14:53 +000021 : Kind(_Kind), ID(_ID.getID()), 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 Dunbar9e1f9822009-11-19 04:14:53 +000073bool Option::matches(OptSpecifier 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 Dunbar9e1f9822009-11-19 04:14:53 +000078 // Check exact match.
79 if (ID == Opt)
Daniel Dunbar1eb4e642009-03-03 05:55:11 +000080 return true;
Mike Stump1eb44332009-09-09 15:08:12 +000081
Daniel Dunbar1eb4e642009-03-03 05:55:11 +000082 if (Group)
83 return Group->matches(Opt);
84 return false;
85}
86
Daniel Dunbar9e1f9822009-11-19 04:14:53 +000087OptionGroup::OptionGroup(OptSpecifier ID, const char *Name,
Daniel Dunbar30b055f2009-03-04 21:53:04 +000088 const OptionGroup *Group)
89 : Option(Option::GroupClass, ID, Name, Group, 0) {
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +000090}
91
Daniel Dunbarf3cad362009-03-25 04:13:45 +000092Arg *OptionGroup::accept(const InputArgList &Args, unsigned &Index) const {
Daniel Dunbarb0c4df52009-03-22 23:26:43 +000093 assert(0 && "accept() should never be called on an OptionGroup");
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +000094 return 0;
Daniel Dunbar1eb4e642009-03-03 05:55:11 +000095}
96
Daniel Dunbara0289fd2009-11-19 04:25:06 +000097InputOption::InputOption(OptSpecifier ID)
98 : Option(Option::InputClass, ID, "<input>", 0, 0) {
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +000099}
100
Daniel Dunbarf3cad362009-03-25 04:13:45 +0000101Arg *InputOption::accept(const InputArgList &Args, unsigned &Index) const {
Daniel Dunbarb0c4df52009-03-22 23:26:43 +0000102 assert(0 && "accept() should never be called on an InputOption");
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +0000103 return 0;
Daniel Dunbar1eb4e642009-03-03 05:55:11 +0000104}
105
Daniel Dunbara0289fd2009-11-19 04:25:06 +0000106UnknownOption::UnknownOption(OptSpecifier ID)
107 : Option(Option::UnknownClass, ID, "<unknown>", 0, 0) {
Daniel Dunbar1eb4e642009-03-03 05:55:11 +0000108}
109
Daniel Dunbarf3cad362009-03-25 04:13:45 +0000110Arg *UnknownOption::accept(const InputArgList &Args, unsigned &Index) const {
Daniel Dunbarb0c4df52009-03-22 23:26:43 +0000111 assert(0 && "accept() should never be called on an UnknownOption");
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +0000112 return 0;
Daniel Dunbar1eb4e642009-03-03 05:55:11 +0000113}
114
Daniel Dunbar9e1f9822009-11-19 04:14:53 +0000115FlagOption::FlagOption(OptSpecifier ID, const char *Name,
Daniel Dunbar30b055f2009-03-04 21:53:04 +0000116 const OptionGroup *Group, const Option *Alias)
117 : Option(Option::FlagClass, ID, Name, Group, Alias) {
Daniel Dunbar1eb4e642009-03-03 05:55:11 +0000118}
119
Daniel Dunbarf3cad362009-03-25 04:13:45 +0000120Arg *FlagOption::accept(const InputArgList &Args, unsigned &Index) const {
Mike Stump1eb44332009-09-09 15:08:12 +0000121 // Matches iff this is an exact match.
Daniel Dunbarbbf842b2009-03-04 23:22:02 +0000122 // FIXME: Avoid strlen.
123 if (strlen(getName()) != strlen(Args.getArgString(Index)))
124 return 0;
125
Daniel Dunbar06482622009-03-05 06:38:47 +0000126 return new FlagArg(this, Index++);
Daniel Dunbar1eb4e642009-03-03 05:55:11 +0000127}
128
Daniel Dunbar9e1f9822009-11-19 04:14:53 +0000129JoinedOption::JoinedOption(OptSpecifier ID, const char *Name,
Daniel Dunbar30b055f2009-03-04 21:53:04 +0000130 const OptionGroup *Group, const Option *Alias)
131 : Option(Option::JoinedClass, ID, Name, Group, Alias) {
Daniel Dunbar1eb4e642009-03-03 05:55:11 +0000132}
133
Daniel Dunbarf3cad362009-03-25 04:13:45 +0000134Arg *JoinedOption::accept(const InputArgList &Args, unsigned &Index) const {
Daniel Dunbarbbf842b2009-03-04 23:22:02 +0000135 // Always matches.
136 return new JoinedArg(this, Index++);
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +0000137}
138
Daniel Dunbar9e1f9822009-11-19 04:14:53 +0000139CommaJoinedOption::CommaJoinedOption(OptSpecifier ID, const char *Name,
Mike Stump1eb44332009-09-09 15:08:12 +0000140 const OptionGroup *Group,
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +0000141 const Option *Alias)
Daniel Dunbar30b055f2009-03-04 21:53:04 +0000142 : Option(Option::CommaJoinedClass, ID, Name, Group, Alias) {
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +0000143}
144
Mike Stump1eb44332009-09-09 15:08:12 +0000145Arg *CommaJoinedOption::accept(const InputArgList &Args,
Daniel Dunbarf3cad362009-03-25 04:13:45 +0000146 unsigned &Index) const {
Daniel Dunbarbbf842b2009-03-04 23:22:02 +0000147 // Always matches. We count the commas now so we can answer
148 // getNumValues easily.
Mike Stump1eb44332009-09-09 15:08:12 +0000149
Daniel Dunbarbbf842b2009-03-04 23:22:02 +0000150 // Get the suffix string.
151 // FIXME: Avoid strlen, and move to helper method?
152 const char *Suffix = Args.getArgString(Index) + strlen(getName());
Daniel Dunbar06482622009-03-05 06:38:47 +0000153 return new CommaJoinedArg(this, Index++, Suffix);
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +0000154}
155
Daniel Dunbar9e1f9822009-11-19 04:14:53 +0000156SeparateOption::SeparateOption(OptSpecifier ID, const char *Name,
Daniel Dunbar30b055f2009-03-04 21:53:04 +0000157 const OptionGroup *Group, const Option *Alias)
158 : Option(Option::SeparateClass, ID, Name, Group, Alias) {
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +0000159}
160
Daniel Dunbarf3cad362009-03-25 04:13:45 +0000161Arg *SeparateOption::accept(const InputArgList &Args, unsigned &Index) const {
Mike Stump1eb44332009-09-09 15:08:12 +0000162 // Matches iff this is an exact match.
Daniel Dunbarbbf842b2009-03-04 23:22:02 +0000163 // FIXME: Avoid strlen.
164 if (strlen(getName()) != strlen(Args.getArgString(Index)))
165 return 0;
166
Daniel Dunbarbbf842b2009-03-04 23:22:02 +0000167 Index += 2;
Daniel Dunbarb0c4df52009-03-22 23:26:43 +0000168 if (Index > Args.getNumInputArgStrings())
169 return 0;
170
Daniel Dunbarbbf842b2009-03-04 23:22:02 +0000171 return new SeparateArg(this, Index - 2, 1);
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +0000172}
173
Daniel Dunbar9e1f9822009-11-19 04:14:53 +0000174MultiArgOption::MultiArgOption(OptSpecifier ID, const char *Name,
Mike Stump1eb44332009-09-09 15:08:12 +0000175 const OptionGroup *Group, const Option *Alias,
Daniel Dunbar30b055f2009-03-04 21:53:04 +0000176 unsigned _NumArgs)
177 : Option(Option::MultiArgClass, ID, Name, Group, Alias), NumArgs(_NumArgs) {
Daniel Dunbar644eade2009-03-12 05:46:32 +0000178 assert(NumArgs > 1 && "Invalid MultiArgOption!");
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +0000179}
180
Daniel Dunbarf3cad362009-03-25 04:13:45 +0000181Arg *MultiArgOption::accept(const InputArgList &Args, unsigned &Index) const {
Mike Stump1eb44332009-09-09 15:08:12 +0000182 // Matches iff this is an exact match.
Daniel Dunbarbbf842b2009-03-04 23:22:02 +0000183 // FIXME: Avoid strlen.
184 if (strlen(getName()) != strlen(Args.getArgString(Index)))
185 return 0;
186
Daniel Dunbarbbf842b2009-03-04 23:22:02 +0000187 Index += 1 + NumArgs;
Daniel Dunbarb0c4df52009-03-22 23:26:43 +0000188 if (Index > Args.getNumInputArgStrings())
189 return 0;
190
Daniel Dunbarbbf842b2009-03-04 23:22:02 +0000191 return new SeparateArg(this, Index - 1 - NumArgs, NumArgs);
Daniel Dunbar1eb4e642009-03-03 05:55:11 +0000192}
193
Daniel Dunbar9e1f9822009-11-19 04:14:53 +0000194JoinedOrSeparateOption::JoinedOrSeparateOption(OptSpecifier ID, const char *Name,
Mike Stump1eb44332009-09-09 15:08:12 +0000195 const OptionGroup *Group,
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +0000196 const Option *Alias)
Daniel Dunbar30b055f2009-03-04 21:53:04 +0000197 : Option(Option::JoinedOrSeparateClass, ID, Name, Group, Alias) {
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +0000198}
199
Mike Stump1eb44332009-09-09 15:08:12 +0000200Arg *JoinedOrSeparateOption::accept(const InputArgList &Args,
Daniel Dunbarb0c4df52009-03-22 23:26:43 +0000201 unsigned &Index) const {
Daniel Dunbarbbf842b2009-03-04 23:22:02 +0000202 // If this is not an exact match, it is a joined arg.
203 // FIXME: Avoid strlen.
204 if (strlen(getName()) != strlen(Args.getArgString(Index)))
205 return new JoinedArg(this, Index++);
206
207 // Otherwise it must be separate.
Daniel Dunbarbbf842b2009-03-04 23:22:02 +0000208 Index += 2;
Daniel Dunbarb0c4df52009-03-22 23:26:43 +0000209 if (Index > Args.getNumInputArgStrings())
210 return 0;
211
Mike Stump1eb44332009-09-09 15:08:12 +0000212 return new SeparateArg(this, Index - 2, 1);
Daniel Dunbar1eb4e642009-03-03 05:55:11 +0000213}
214
Daniel Dunbar9e1f9822009-11-19 04:14:53 +0000215JoinedAndSeparateOption::JoinedAndSeparateOption(OptSpecifier ID,
Mike Stump1eb44332009-09-09 15:08:12 +0000216 const char *Name,
217 const OptionGroup *Group,
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +0000218 const Option *Alias)
Daniel Dunbar30b055f2009-03-04 21:53:04 +0000219 : Option(Option::JoinedAndSeparateClass, ID, Name, Group, Alias) {
Daniel Dunbar1eb4e642009-03-03 05:55:11 +0000220}
221
Mike Stump1eb44332009-09-09 15:08:12 +0000222Arg *JoinedAndSeparateOption::accept(const InputArgList &Args,
Daniel Dunbarb0c4df52009-03-22 23:26:43 +0000223 unsigned &Index) const {
Daniel Dunbarbbf842b2009-03-04 23:22:02 +0000224 // Always matches.
225
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 JoinedAndSeparateArg(this, Index - 2);
Daniel Dunbar2c6f6f32009-03-04 08:33:23 +0000231}
Daniel Dunbar1eb4e642009-03-03 05:55:11 +0000232