blob: 3d07431209e21fae89fc19bd7066d5e3067cf80b [file] [log] [blame]
Daniel Dunbar6ac1e222009-03-04 17:10:42 +00001//===--- ArgList.cpp - Argument List Management -------------------------*-===//
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/ArgList.h"
11#include "clang/Driver/Arg.h"
Daniel Dunbar03e8ab22010-05-20 16:54:55 +000012#include "clang/Driver/DriverDiagnostic.h"
Daniel Dunbar9358dc82009-03-04 22:40:08 +000013#include "clang/Driver/Option.h"
Daniel Dunbar6ac1e222009-03-04 17:10:42 +000014
Daniel Dunbar16484af2009-09-09 22:32:26 +000015#include "llvm/ADT/SmallString.h"
16#include "llvm/ADT/Twine.h"
17#include "llvm/Support/raw_ostream.h"
18
Benjamin Kramera5ddbca2010-05-21 19:58:44 +000019using namespace clang;
Daniel Dunbar6ac1e222009-03-04 17:10:42 +000020using namespace clang::driver;
21
Daniel Dunbar3b84f5b2009-11-25 11:33:30 +000022void arg_iterator::SkipToNextArg() {
23 for (; Current != Args.end(); ++Current) {
24 // Done if there are no filters.
25 if (!Id0.isValid())
26 break;
27
28 // Otherwise require a match.
29 const Option &O = (*Current)->getOption();
30 if (O.matches(Id0) ||
31 (Id1.isValid() && O.matches(Id1)) ||
32 (Id2.isValid() && O.matches(Id2)))
33 break;
34 }
35}
36
37//
38
Daniel Dunbarf3cad362009-03-25 04:13:45 +000039ArgList::ArgList(arglist_type &_Args) : Args(_Args) {
Daniel Dunbar6ac1e222009-03-04 17:10:42 +000040}
41
42ArgList::~ArgList() {
Daniel Dunbar6ac1e222009-03-04 17:10:42 +000043}
Daniel Dunbar9358dc82009-03-04 22:40:08 +000044
45void ArgList::append(Arg *A) {
Daniel Dunbar9358dc82009-03-04 22:40:08 +000046 Args.push_back(A);
47}
Daniel Dunbard8cadd42009-03-12 01:36:44 +000048
Daniel Dunbar9e1f9822009-11-19 04:14:53 +000049Arg *ArgList::getLastArgNoClaim(OptSpecifier Id) const {
Daniel Dunbard8cadd42009-03-12 01:36:44 +000050 // FIXME: Make search efficient?
Daniel Dunbare4bdae72009-11-19 04:00:53 +000051 for (const_reverse_iterator it = rbegin(), ie = rend(); it != ie; ++it)
52 if ((*it)->getOption().matches(Id))
Daniel Dunbar0c562a22009-03-12 16:03:38 +000053 return *it;
Daniel Dunbar0c562a22009-03-12 16:03:38 +000054 return 0;
Daniel Dunbard8cadd42009-03-12 01:36:44 +000055}
Daniel Dunbarbca58cb2009-03-12 18:20:18 +000056
Daniel Dunbar9e1f9822009-11-19 04:14:53 +000057Arg *ArgList::getLastArg(OptSpecifier Id) const {
Daniel Dunbare4bdae72009-11-19 04:00:53 +000058 Arg *A = getLastArgNoClaim(Id);
59 if (A)
60 A->claim();
61 return A;
62}
63
Daniel Dunbar9e1f9822009-11-19 04:14:53 +000064Arg *ArgList::getLastArg(OptSpecifier Id0, OptSpecifier Id1) const {
Daniel Dunbare4bdae72009-11-19 04:00:53 +000065 Arg *Res, *A0 = getLastArgNoClaim(Id0), *A1 = getLastArgNoClaim(Id1);
Mike Stump1eb44332009-09-09 15:08:12 +000066
Daniel Dunbarcd4e1862009-03-17 18:51:42 +000067 if (A0 && A1)
68 Res = A0->getIndex() > A1->getIndex() ? A0 : A1;
69 else
70 Res = A0 ? A0 : A1;
71
Daniel Dunbare4bdae72009-11-19 04:00:53 +000072 if (Res)
Daniel Dunbarcd4e1862009-03-17 18:51:42 +000073 Res->claim();
74
75 return Res;
76}
77
Daniel Dunbar9e1f9822009-11-19 04:14:53 +000078Arg *ArgList::getLastArg(OptSpecifier Id0, OptSpecifier Id1,
79 OptSpecifier Id2) const {
Bill Wendling45483f72009-06-28 07:36:13 +000080 Arg *Res = 0;
Daniel Dunbare4bdae72009-11-19 04:00:53 +000081 Arg *A0 = getLastArgNoClaim(Id0);
82 Arg *A1 = getLastArgNoClaim(Id1);
83 Arg *A2 = getLastArgNoClaim(Id2);
Bill Wendling45483f72009-06-28 07:36:13 +000084
Ted Kremenekcbc6a632010-03-10 19:09:31 +000085 int A0Idx = A0 ? (int) A0->getIndex() : -1;
86 int A1Idx = A1 ? (int) A1->getIndex() : -1;
87 int A2Idx = A2 ? (int) A2->getIndex() : -1;
Bill Wendling45483f72009-06-28 07:36:13 +000088
89 if (A0Idx > A1Idx) {
90 if (A0Idx > A2Idx)
91 Res = A0;
92 else if (A2Idx != -1)
93 Res = A2;
94 } else {
95 if (A1Idx > A2Idx)
96 Res = A1;
97 else if (A2Idx != -1)
98 Res = A2;
99 }
100
Daniel Dunbare4bdae72009-11-19 04:00:53 +0000101 if (Res)
Bill Wendling45483f72009-06-28 07:36:13 +0000102 Res->claim();
103
104 return Res;
105}
106
Daniel Dunbar9e1f9822009-11-19 04:14:53 +0000107bool ArgList::hasFlag(OptSpecifier Pos, OptSpecifier Neg, bool Default) const {
Daniel Dunbar9af66682009-04-07 21:08:57 +0000108 if (Arg *A = getLastArg(Pos, Neg))
109 return A->getOption().matches(Pos);
Daniel Dunbar18a7f332009-03-18 09:29:36 +0000110 return Default;
111}
112
Daniel Dunbar03e8ab22010-05-20 16:54:55 +0000113llvm::StringRef ArgList::getLastArgValue(OptSpecifier Id,
114 llvm::StringRef Default) const {
115 if (Arg *A = getLastArg(Id))
116 return A->getValue(*this);
117 return Default;
118}
119
120int ArgList::getLastArgIntValue(OptSpecifier Id, int Default,
Daniel Dunbar5e30b8b2010-05-22 05:05:12 +0000121 clang::Diagnostic &Diags) const {
Daniel Dunbar03e8ab22010-05-20 16:54:55 +0000122 int Res = Default;
123
124 if (Arg *A = getLastArg(Id)) {
125 if (llvm::StringRef(A->getValue(*this)).getAsInteger(10, Res))
126 Diags.Report(diag::err_drv_invalid_int_value)
127 << A->getAsString(*this) << A->getValue(*this);
128 }
129
130 return Res;
131}
132
133std::vector<std::string> ArgList::getAllArgValues(OptSpecifier Id) const {
134 llvm::SmallVector<const char *, 16> Values;
135 AddAllArgValues(Values, Id);
136 return std::vector<std::string>(Values.begin(), Values.end());
137}
138
Daniel Dunbar9e1f9822009-11-19 04:14:53 +0000139void ArgList::AddLastArg(ArgStringList &Output, OptSpecifier Id) const {
Daniel Dunbar18a7f332009-03-18 09:29:36 +0000140 if (Arg *A = getLastArg(Id)) {
141 A->claim();
142 A->render(*this, Output);
143 }
144}
145
Daniel Dunbar9e1f9822009-11-19 04:14:53 +0000146void ArgList::AddAllArgs(ArgStringList &Output, OptSpecifier Id0,
147 OptSpecifier Id1, OptSpecifier Id2) const {
Daniel Dunbar3b84f5b2009-11-25 11:33:30 +0000148 for (arg_iterator it = filtered_begin(Id0, Id1, Id2),
149 ie = filtered_end(); it != ie; ++it) {
150 it->claim();
151 it->render(*this, Output);
Daniel Dunbar18a7f332009-03-18 09:29:36 +0000152 }
153}
Daniel Dunbaree510312009-03-20 15:59:01 +0000154
Daniel Dunbar9e1f9822009-11-19 04:14:53 +0000155void ArgList::AddAllArgValues(ArgStringList &Output, OptSpecifier Id0,
Daniel Dunbar3b84f5b2009-11-25 11:33:30 +0000156 OptSpecifier Id1, OptSpecifier Id2) const {
157 for (arg_iterator it = filtered_begin(Id0, Id1, Id2),
158 ie = filtered_end(); it != ie; ++it) {
159 it->claim();
160 for (unsigned i = 0, e = it->getNumValues(); i != e; ++i)
161 Output.push_back(it->getValue(*this, i));
Daniel Dunbaree510312009-03-20 15:59:01 +0000162 }
163}
Daniel Dunbarf3cad362009-03-25 04:13:45 +0000164
Daniel Dunbar9e1f9822009-11-19 04:14:53 +0000165void ArgList::AddAllArgsTranslated(ArgStringList &Output, OptSpecifier Id0,
Daniel Dunbar4df9a662009-04-26 01:07:52 +0000166 const char *Translation,
167 bool Joined) const {
Daniel Dunbar3b84f5b2009-11-25 11:33:30 +0000168 for (arg_iterator it = filtered_begin(Id0),
169 ie = filtered_end(); it != ie; ++it) {
170 it->claim();
Daniel Dunbar4df9a662009-04-26 01:07:52 +0000171
Daniel Dunbar3b84f5b2009-11-25 11:33:30 +0000172 if (Joined) {
173 Output.push_back(MakeArgString(llvm::StringRef(Translation) +
174 it->getValue(*this, 0)));
175 } else {
176 Output.push_back(Translation);
177 Output.push_back(it->getValue(*this, 0));
Daniel Dunbar524b9fb2009-03-26 15:39:22 +0000178 }
179 }
180}
181
Daniel Dunbar9e1f9822009-11-19 04:14:53 +0000182void ArgList::ClaimAllArgs(OptSpecifier Id0) const {
Daniel Dunbar3b84f5b2009-11-25 11:33:30 +0000183 for (arg_iterator it = filtered_begin(Id0),
184 ie = filtered_end(); it != ie; ++it)
185 it->claim();
Daniel Dunbar68fb4692009-04-03 20:51:31 +0000186}
187
Daniel Dunbar16484af2009-09-09 22:32:26 +0000188const char *ArgList::MakeArgString(const llvm::Twine &T) const {
189 llvm::SmallString<256> Str;
190 T.toVector(Str);
191 return MakeArgString(Str.str());
192}
193
Daniel Dunbarf3cad362009-03-25 04:13:45 +0000194//
195
Mike Stump1eb44332009-09-09 15:08:12 +0000196InputArgList::InputArgList(const char **ArgBegin, const char **ArgEnd)
197 : ArgList(ActualArgs), NumInputArgStrings(ArgEnd - ArgBegin) {
Daniel Dunbarf3cad362009-03-25 04:13:45 +0000198 ArgStrings.append(ArgBegin, ArgEnd);
199}
200
201InputArgList::~InputArgList() {
202 // An InputArgList always owns its arguments.
203 for (iterator it = begin(), ie = end(); it != ie; ++it)
204 delete *it;
205}
206
Daniel Dunbar16484af2009-09-09 22:32:26 +0000207unsigned InputArgList::MakeIndex(llvm::StringRef String0) const {
Daniel Dunbarf3cad362009-03-25 04:13:45 +0000208 unsigned Index = ArgStrings.size();
209
210 // Tuck away so we have a reliable const char *.
211 SynthesizedStrings.push_back(String0);
212 ArgStrings.push_back(SynthesizedStrings.back().c_str());
213
214 return Index;
215}
216
Daniel Dunbar16484af2009-09-09 22:32:26 +0000217unsigned InputArgList::MakeIndex(llvm::StringRef String0,
218 llvm::StringRef String1) const {
Daniel Dunbarf3cad362009-03-25 04:13:45 +0000219 unsigned Index0 = MakeIndex(String0);
220 unsigned Index1 = MakeIndex(String1);
221 assert(Index0 + 1 == Index1 && "Unexpected non-consecutive indices!");
222 (void) Index1;
223 return Index0;
224}
225
Daniel Dunbar16484af2009-09-09 22:32:26 +0000226const char *InputArgList::MakeArgString(llvm::StringRef Str) const {
Daniel Dunbarf3cad362009-03-25 04:13:45 +0000227 return getArgString(MakeIndex(Str));
228}
229
230//
231
232DerivedArgList::DerivedArgList(InputArgList &_BaseArgs, bool _OnlyProxy)
233 : ArgList(_OnlyProxy ? _BaseArgs.getArgs() : ActualArgs),
Mike Stump1eb44332009-09-09 15:08:12 +0000234 BaseArgs(_BaseArgs), OnlyProxy(_OnlyProxy) {
Daniel Dunbarf3cad362009-03-25 04:13:45 +0000235}
236
237DerivedArgList::~DerivedArgList() {
238 // We only own the arguments we explicitly synthesized.
Mike Stump1eb44332009-09-09 15:08:12 +0000239 for (iterator it = SynthesizedArgs.begin(), ie = SynthesizedArgs.end();
Daniel Dunbarf3cad362009-03-25 04:13:45 +0000240 it != ie; ++it)
241 delete *it;
242}
243
Daniel Dunbar16484af2009-09-09 22:32:26 +0000244const char *DerivedArgList::MakeArgString(llvm::StringRef Str) const {
Daniel Dunbarf3cad362009-03-25 04:13:45 +0000245 return BaseArgs.MakeArgString(Str);
246}
247
Daniel Dunbar478edc22009-03-29 22:29:05 +0000248Arg *DerivedArgList::MakeFlagArg(const Arg *BaseArg, const Option *Opt) const {
Daniel Dunbarfd48cb32010-03-11 18:04:53 +0000249 Arg *A = new FlagArg(Opt, BaseArgs.MakeIndex(Opt->getName()), BaseArg);
250 SynthesizedArgs.push_back(A);
251 return A;
Daniel Dunbarf3cad362009-03-25 04:13:45 +0000252}
253
Mike Stump1eb44332009-09-09 15:08:12 +0000254Arg *DerivedArgList::MakePositionalArg(const Arg *BaseArg, const Option *Opt,
Daniel Dunbar16484af2009-09-09 22:32:26 +0000255 llvm::StringRef Value) const {
Daniel Dunbarfd48cb32010-03-11 18:04:53 +0000256 Arg *A = new PositionalArg(Opt, BaseArgs.MakeIndex(Value), BaseArg);
257 SynthesizedArgs.push_back(A);
258 return A;
Daniel Dunbarf3cad362009-03-25 04:13:45 +0000259}
260
Mike Stump1eb44332009-09-09 15:08:12 +0000261Arg *DerivedArgList::MakeSeparateArg(const Arg *BaseArg, const Option *Opt,
Daniel Dunbar16484af2009-09-09 22:32:26 +0000262 llvm::StringRef Value) const {
Daniel Dunbarfd48cb32010-03-11 18:04:53 +0000263 Arg *A = new SeparateArg(Opt, BaseArgs.MakeIndex(Opt->getName(), Value), 1,
264 BaseArg);
265 SynthesizedArgs.push_back(A);
266 return A;
Daniel Dunbarf3cad362009-03-25 04:13:45 +0000267}
268
Mike Stump1eb44332009-09-09 15:08:12 +0000269Arg *DerivedArgList::MakeJoinedArg(const Arg *BaseArg, const Option *Opt,
Daniel Dunbar16484af2009-09-09 22:32:26 +0000270 llvm::StringRef Value) const {
Daniel Dunbarfd48cb32010-03-11 18:04:53 +0000271 Arg *A = new JoinedArg(Opt, BaseArgs.MakeIndex(Opt->getName() + Value.str()),
272 BaseArg);
273 SynthesizedArgs.push_back(A);
274 return A;
Daniel Dunbarf3cad362009-03-25 04:13:45 +0000275}