blob: 1b6ba94400adb0377df4c5b4cdf1153f022c7b6d [file] [log] [blame]
Daniel Dunbar3e2cbc32009-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 Dunbar37300482010-05-20 16:54:55 +000012#include "clang/Driver/DriverDiagnostic.h"
Daniel Dunbar16b9fd42009-03-04 22:40:08 +000013#include "clang/Driver/Option.h"
Daniel Dunbar3e2cbc32009-03-04 17:10:42 +000014
Daniel Dunbar5f620c12009-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 Kramer71b0bb92010-05-21 19:58:44 +000019using namespace clang;
Daniel Dunbar3e2cbc32009-03-04 17:10:42 +000020using namespace clang::driver;
21
Daniel Dunbarb8c2f7d2009-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 Dunbardac54a82009-03-25 04:13:45 +000039ArgList::ArgList(arglist_type &_Args) : Args(_Args) {
Daniel Dunbar3e2cbc32009-03-04 17:10:42 +000040}
41
42ArgList::~ArgList() {
Daniel Dunbar3e2cbc32009-03-04 17:10:42 +000043}
Daniel Dunbar16b9fd42009-03-04 22:40:08 +000044
45void ArgList::append(Arg *A) {
Daniel Dunbar16b9fd42009-03-04 22:40:08 +000046 Args.push_back(A);
47}
Daniel Dunbar2c3939c2009-03-12 01:36:44 +000048
Daniel Dunbar8c009572009-11-19 04:14:53 +000049Arg *ArgList::getLastArgNoClaim(OptSpecifier Id) const {
Daniel Dunbar2c3939c2009-03-12 01:36:44 +000050 // FIXME: Make search efficient?
Daniel Dunbarfffd1812009-11-19 04:00:53 +000051 for (const_reverse_iterator it = rbegin(), ie = rend(); it != ie; ++it)
52 if ((*it)->getOption().matches(Id))
Daniel Dunbar7586bb92009-03-12 16:03:38 +000053 return *it;
Daniel Dunbar7586bb92009-03-12 16:03:38 +000054 return 0;
Daniel Dunbar2c3939c2009-03-12 01:36:44 +000055}
Daniel Dunbar7c8d6532009-03-12 18:20:18 +000056
Daniel Dunbar8c009572009-11-19 04:14:53 +000057Arg *ArgList::getLastArg(OptSpecifier Id) const {
Daniel Dunbarfffd1812009-11-19 04:00:53 +000058 Arg *A = getLastArgNoClaim(Id);
59 if (A)
60 A->claim();
61 return A;
62}
63
Daniel Dunbar8c009572009-11-19 04:14:53 +000064Arg *ArgList::getLastArg(OptSpecifier Id0, OptSpecifier Id1) const {
Daniel Dunbarfffd1812009-11-19 04:00:53 +000065 Arg *Res, *A0 = getLastArgNoClaim(Id0), *A1 = getLastArgNoClaim(Id1);
Mike Stump11289f42009-09-09 15:08:12 +000066
Daniel Dunbarc1b70b22009-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 Dunbarfffd1812009-11-19 04:00:53 +000072 if (Res)
Daniel Dunbarc1b70b22009-03-17 18:51:42 +000073 Res->claim();
74
75 return Res;
76}
77
Daniel Dunbar8c009572009-11-19 04:14:53 +000078Arg *ArgList::getLastArg(OptSpecifier Id0, OptSpecifier Id1,
79 OptSpecifier Id2) const {
Bill Wendlingd63bbad2009-06-28 07:36:13 +000080 Arg *Res = 0;
Daniel Dunbarfffd1812009-11-19 04:00:53 +000081 Arg *A0 = getLastArgNoClaim(Id0);
82 Arg *A1 = getLastArgNoClaim(Id1);
83 Arg *A2 = getLastArgNoClaim(Id2);
Bill Wendlingd63bbad2009-06-28 07:36:13 +000084
Ted Kremenek1a0c4d52010-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 Wendlingd63bbad2009-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 Dunbarfffd1812009-11-19 04:00:53 +0000101 if (Res)
Bill Wendlingd63bbad2009-06-28 07:36:13 +0000102 Res->claim();
103
104 return Res;
105}
106
Daniel Dunbar8c009572009-11-19 04:14:53 +0000107bool ArgList::hasFlag(OptSpecifier Pos, OptSpecifier Neg, bool Default) const {
Daniel Dunbar30bf11e2009-04-07 21:08:57 +0000108 if (Arg *A = getLastArg(Pos, Neg))
109 return A->getOption().matches(Pos);
Daniel Dunbar7591f292009-03-18 09:29:36 +0000110 return Default;
111}
112
Daniel Dunbar37300482010-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 Dunbarbd3b1d42010-05-22 05:05:12 +0000121 clang::Diagnostic &Diags) const {
Daniel Dunbar37300482010-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 Dunbar8c009572009-11-19 04:14:53 +0000139void ArgList::AddLastArg(ArgStringList &Output, OptSpecifier Id) const {
Daniel Dunbar7591f292009-03-18 09:29:36 +0000140 if (Arg *A = getLastArg(Id)) {
141 A->claim();
142 A->render(*this, Output);
143 }
144}
145
Daniel Dunbar8c009572009-11-19 04:14:53 +0000146void ArgList::AddAllArgs(ArgStringList &Output, OptSpecifier Id0,
147 OptSpecifier Id1, OptSpecifier Id2) const {
Daniel Dunbarb8c2f7d2009-11-25 11:33:30 +0000148 for (arg_iterator it = filtered_begin(Id0, Id1, Id2),
149 ie = filtered_end(); it != ie; ++it) {
Daniel Dunbara442fd52010-06-11 22:00:13 +0000150 (*it)->claim();
151 (*it)->render(*this, Output);
Daniel Dunbar7591f292009-03-18 09:29:36 +0000152 }
153}
Daniel Dunbare81cc832009-03-20 15:59:01 +0000154
Daniel Dunbar8c009572009-11-19 04:14:53 +0000155void ArgList::AddAllArgValues(ArgStringList &Output, OptSpecifier Id0,
Daniel Dunbarb8c2f7d2009-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) {
Daniel Dunbara442fd52010-06-11 22:00:13 +0000159 (*it)->claim();
160 for (unsigned i = 0, e = (*it)->getNumValues(); i != e; ++i)
161 Output.push_back((*it)->getValue(*this, i));
Daniel Dunbare81cc832009-03-20 15:59:01 +0000162 }
163}
Daniel Dunbardac54a82009-03-25 04:13:45 +0000164
Daniel Dunbar8c009572009-11-19 04:14:53 +0000165void ArgList::AddAllArgsTranslated(ArgStringList &Output, OptSpecifier Id0,
Daniel Dunbar3ba94d82009-04-26 01:07:52 +0000166 const char *Translation,
167 bool Joined) const {
Daniel Dunbarb8c2f7d2009-11-25 11:33:30 +0000168 for (arg_iterator it = filtered_begin(Id0),
169 ie = filtered_end(); it != ie; ++it) {
Daniel Dunbara442fd52010-06-11 22:00:13 +0000170 (*it)->claim();
Daniel Dunbar3ba94d82009-04-26 01:07:52 +0000171
Daniel Dunbarb8c2f7d2009-11-25 11:33:30 +0000172 if (Joined) {
173 Output.push_back(MakeArgString(llvm::StringRef(Translation) +
Daniel Dunbara442fd52010-06-11 22:00:13 +0000174 (*it)->getValue(*this, 0)));
Daniel Dunbarb8c2f7d2009-11-25 11:33:30 +0000175 } else {
176 Output.push_back(Translation);
Daniel Dunbara442fd52010-06-11 22:00:13 +0000177 Output.push_back((*it)->getValue(*this, 0));
Daniel Dunbar4e5696b2009-03-26 15:39:22 +0000178 }
179 }
180}
181
Daniel Dunbar8c009572009-11-19 04:14:53 +0000182void ArgList::ClaimAllArgs(OptSpecifier Id0) const {
Daniel Dunbarb8c2f7d2009-11-25 11:33:30 +0000183 for (arg_iterator it = filtered_begin(Id0),
184 ie = filtered_end(); it != ie; ++it)
Daniel Dunbara442fd52010-06-11 22:00:13 +0000185 (*it)->claim();
Daniel Dunbarc2a71892009-04-03 20:51:31 +0000186}
187
Daniel Dunbar5f620c12009-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 Dunbar26a95c62010-06-09 18:49:38 +0000194const char *ArgList::GetOrMakeJoinedArgString(unsigned Index,
195 llvm::StringRef LHS,
196 llvm::StringRef RHS) const {
197 llvm::StringRef Cur = getArgString(Index);
198 if (Cur.size() == LHS.size() + RHS.size() &&
199 Cur.startswith(LHS) && Cur.endswith(RHS))
200 return Cur.data();
201
202 return MakeArgString(LHS + RHS);
203}
204
Daniel Dunbardac54a82009-03-25 04:13:45 +0000205//
206
Mike Stump11289f42009-09-09 15:08:12 +0000207InputArgList::InputArgList(const char **ArgBegin, const char **ArgEnd)
208 : ArgList(ActualArgs), NumInputArgStrings(ArgEnd - ArgBegin) {
Daniel Dunbardac54a82009-03-25 04:13:45 +0000209 ArgStrings.append(ArgBegin, ArgEnd);
210}
211
212InputArgList::~InputArgList() {
213 // An InputArgList always owns its arguments.
214 for (iterator it = begin(), ie = end(); it != ie; ++it)
215 delete *it;
216}
217
Daniel Dunbar5f620c12009-09-09 22:32:26 +0000218unsigned InputArgList::MakeIndex(llvm::StringRef String0) const {
Daniel Dunbardac54a82009-03-25 04:13:45 +0000219 unsigned Index = ArgStrings.size();
220
221 // Tuck away so we have a reliable const char *.
222 SynthesizedStrings.push_back(String0);
223 ArgStrings.push_back(SynthesizedStrings.back().c_str());
224
225 return Index;
226}
227
Daniel Dunbar5f620c12009-09-09 22:32:26 +0000228unsigned InputArgList::MakeIndex(llvm::StringRef String0,
229 llvm::StringRef String1) const {
Daniel Dunbardac54a82009-03-25 04:13:45 +0000230 unsigned Index0 = MakeIndex(String0);
231 unsigned Index1 = MakeIndex(String1);
232 assert(Index0 + 1 == Index1 && "Unexpected non-consecutive indices!");
233 (void) Index1;
234 return Index0;
235}
236
Daniel Dunbar5f620c12009-09-09 22:32:26 +0000237const char *InputArgList::MakeArgString(llvm::StringRef Str) const {
Daniel Dunbardac54a82009-03-25 04:13:45 +0000238 return getArgString(MakeIndex(Str));
239}
240
241//
242
243DerivedArgList::DerivedArgList(InputArgList &_BaseArgs, bool _OnlyProxy)
244 : ArgList(_OnlyProxy ? _BaseArgs.getArgs() : ActualArgs),
Mike Stump11289f42009-09-09 15:08:12 +0000245 BaseArgs(_BaseArgs), OnlyProxy(_OnlyProxy) {
Daniel Dunbardac54a82009-03-25 04:13:45 +0000246}
247
248DerivedArgList::~DerivedArgList() {
249 // We only own the arguments we explicitly synthesized.
Mike Stump11289f42009-09-09 15:08:12 +0000250 for (iterator it = SynthesizedArgs.begin(), ie = SynthesizedArgs.end();
Daniel Dunbardac54a82009-03-25 04:13:45 +0000251 it != ie; ++it)
252 delete *it;
253}
254
Daniel Dunbar5f620c12009-09-09 22:32:26 +0000255const char *DerivedArgList::MakeArgString(llvm::StringRef Str) const {
Daniel Dunbardac54a82009-03-25 04:13:45 +0000256 return BaseArgs.MakeArgString(Str);
257}
258
Daniel Dunbar53b406f2009-03-29 22:29:05 +0000259Arg *DerivedArgList::MakeFlagArg(const Arg *BaseArg, const Option *Opt) const {
Daniel Dunbar35cbfeb2010-06-09 22:31:08 +0000260 Arg *A = new Arg(Opt, BaseArgs.MakeIndex(Opt->getName()), BaseArg);
Daniel Dunbar86d83892010-03-11 18:04:53 +0000261 SynthesizedArgs.push_back(A);
262 return A;
Daniel Dunbardac54a82009-03-25 04:13:45 +0000263}
264
Mike Stump11289f42009-09-09 15:08:12 +0000265Arg *DerivedArgList::MakePositionalArg(const Arg *BaseArg, const Option *Opt,
Daniel Dunbar5f620c12009-09-09 22:32:26 +0000266 llvm::StringRef Value) const {
Daniel Dunbar8f1ebab2010-06-09 22:31:00 +0000267 unsigned Index = BaseArgs.MakeIndex(Value);
Daniel Dunbar35cbfeb2010-06-09 22:31:08 +0000268 Arg *A = new Arg(Opt, Index, BaseArgs.getArgString(Index), BaseArg);
Daniel Dunbar86d83892010-03-11 18:04:53 +0000269 SynthesizedArgs.push_back(A);
270 return A;
Daniel Dunbardac54a82009-03-25 04:13:45 +0000271}
272
Mike Stump11289f42009-09-09 15:08:12 +0000273Arg *DerivedArgList::MakeSeparateArg(const Arg *BaseArg, const Option *Opt,
Daniel Dunbar5f620c12009-09-09 22:32:26 +0000274 llvm::StringRef Value) const {
Daniel Dunbar8f1ebab2010-06-09 22:31:00 +0000275 unsigned Index = BaseArgs.MakeIndex(Opt->getName(), Value);
Daniel Dunbar35cbfeb2010-06-09 22:31:08 +0000276 Arg *A = new Arg(Opt, Index, BaseArgs.getArgString(Index), BaseArg);
Daniel Dunbar86d83892010-03-11 18:04:53 +0000277 SynthesizedArgs.push_back(A);
278 return A;
Daniel Dunbardac54a82009-03-25 04:13:45 +0000279}
280
Mike Stump11289f42009-09-09 15:08:12 +0000281Arg *DerivedArgList::MakeJoinedArg(const Arg *BaseArg, const Option *Opt,
Daniel Dunbar5f620c12009-09-09 22:32:26 +0000282 llvm::StringRef Value) const {
Daniel Dunbar8f1ebab2010-06-09 22:31:00 +0000283 unsigned Index = BaseArgs.MakeIndex(Opt->getName() + Value.str());
Daniel Dunbar35cbfeb2010-06-09 22:31:08 +0000284 Arg *A = new Arg(Opt, Index,
285 BaseArgs.getArgString(Index) + strlen(Opt->getName()),
286 BaseArg);
Daniel Dunbar86d83892010-03-11 18:04:53 +0000287 SynthesizedArgs.push_back(A);
288 return A;
Daniel Dunbardac54a82009-03-25 04:13:45 +0000289}