Coverage Report

Created: 2019-07-24 05:18

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/lib/Option/Option.cpp
Line
Count
Source (jump to first uncovered line)
1
//===- Option.cpp - Abstract Driver Options -------------------------------===//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8
9
#include "llvm/ADT/StringRef.h"
10
#include "llvm/ADT/Twine.h"
11
#include "llvm/Config/llvm-config.h"
12
#include "llvm/Option/Arg.h"
13
#include "llvm/Option/ArgList.h"
14
#include "llvm/Option/Option.h"
15
#include "llvm/Option/OptTable.h"
16
#include "llvm/Support/Compiler.h"
17
#include "llvm/Support/Debug.h"
18
#include "llvm/Support/ErrorHandling.h"
19
#include "llvm/Support/raw_ostream.h"
20
#include <cassert>
21
#include <cstring>
22
23
using namespace llvm;
24
using namespace llvm::opt;
25
26
Option::Option(const OptTable::Info *info, const OptTable *owner)
27
229M
  : Info(info), Owner(owner) {
28
229M
  // Multi-level aliases are not supported. This just simplifies option
29
229M
  // tracking, it is not an inherent limitation.
30
229M
  assert((!Info || !getAlias().isValid() || !getAlias().getAlias().isValid()) &&
31
229M
         "Multi-level aliases are not supported.");
32
229M
33
229M
  if (Info && 
getAliasArgs()71.8M
) {
34
50.7k
    assert(getAlias().isValid() && "Only alias options can have alias args.");
35
50.7k
    assert(getKind() == FlagClass && "Only Flag aliases can have alias args.");
36
50.7k
    assert(getAlias().getKind() != FlagClass &&
37
50.7k
           "Cannot provide alias args to a flag option.");
38
50.7k
  }
39
229M
}
40
41
0
void Option::print(raw_ostream &O) const {
42
0
  O << "<";
43
0
  switch (getKind()) {
44
0
#define P(N) case N: O << #N; break
45
0
    P(GroupClass);
46
0
    P(InputClass);
47
0
    P(UnknownClass);
48
0
    P(FlagClass);
49
0
    P(JoinedClass);
50
0
    P(ValuesClass);
51
0
    P(SeparateClass);
52
0
    P(CommaJoinedClass);
53
0
    P(MultiArgClass);
54
0
    P(JoinedOrSeparateClass);
55
0
    P(JoinedAndSeparateClass);
56
0
    P(RemainingArgsClass);
57
0
    P(RemainingArgsJoinedClass);
58
0
#undef P
59
0
  }
60
0
61
0
  if (Info->Prefixes) {
62
0
    O << " Prefixes:[";
63
0
    for (const char *const *Pre = Info->Prefixes; *Pre != nullptr; ++Pre) {
64
0
      O << '"' << *Pre << (*(Pre + 1) == nullptr ? "\"" : "\", ");
65
0
    }
66
0
    O << ']';
67
0
  }
68
0
69
0
  O << " Name:\"" << getName() << '"';
70
0
71
0
  const Option Group = getGroup();
72
0
  if (Group.isValid()) {
73
0
    O << " Group:";
74
0
    Group.print(O);
75
0
  }
76
0
77
0
  const Option Alias = getAlias();
78
0
  if (Alias.isValid()) {
79
0
    O << " Alias:";
80
0
    Alias.print(O);
81
0
  }
82
0
83
0
  if (getKind() == MultiArgClass)
84
0
    O << " NumArgs:" << getNumArgs();
85
0
86
0
  O << ">\n";
87
0
}
88
89
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
90
LLVM_DUMP_METHOD void Option::dump() const { print(dbgs()); }
91
#endif
92
93
105M
bool Option::matches(OptSpecifier Opt) const {
94
105M
  // Aliases are never considered in matching, look through them.
95
105M
  const Option Alias = getAlias();
96
105M
  if (Alias.isValid())
97
136
    return Alias.matches(Opt);
98
105M
99
105M
  // Check exact match.
100
105M
  if (getID() == Opt.getID())
101
3.90M
    return true;
102
101M
103
101M
  const Option Group = getGroup();
104
101M
  if (Group.isValid())
105
61.3M
    return Group.matches(Opt);
106
40.2M
  return false;
107
40.2M
}
108
109
Arg *Option::acceptInternal(const ArgList &Args, unsigned &Index,
110
2.94M
                            unsigned ArgSize) const {
111
2.94M
  StringRef Spelling = StringRef(Args.getArgString(Index), ArgSize);
112
2.94M
  switch (getKind()) {
113
2.94M
  case FlagClass: {
114
723k
    if (ArgSize != strlen(Args.getArgString(Index)))
115
65.3k
      return nullptr;
116
658k
    return new Arg(*this, Spelling, Index++);
117
658k
  }
118
658k
  case JoinedClass: {
119
343k
    const char *Value = Args.getArgString(Index) + ArgSize;
120
343k
    return new Arg(*this, Spelling, Index++, Value);
121
658k
  }
122
658k
  case CommaJoinedClass: {
123
17.2k
    // Always matches.
124
17.2k
    const char *Str = Args.getArgString(Index) + ArgSize;
125
17.2k
    Arg *A = new Arg(*this, Spelling, Index++);
126
17.2k
127
17.2k
    // Parse out the comma separated values.
128
17.2k
    const char *Prev = Str;
129
363k
    for (;; 
++Str346k
) {
130
363k
      char c = *Str;
131
363k
132
363k
      if (!c || 
c == ','346k
) {
133
18.3k
        if (Prev != Str) {
134
18.3k
          char *Value = new char[Str - Prev + 1];
135
18.3k
          memcpy(Value, Prev, Str - Prev);
136
18.3k
          Value[Str - Prev] = '\0';
137
18.3k
          A->getValues().push_back(Value);
138
18.3k
        }
139
18.3k
140
18.3k
        if (!c)
141
17.2k
          break;
142
1.12k
143
1.12k
        Prev = Str + 1;
144
1.12k
      }
145
363k
    }
146
17.2k
    A->setOwnsValues(true);
147
17.2k
148
17.2k
    return A;
149
658k
  }
150
658k
  case SeparateClass:
151
521k
    // Matches iff this is an exact match.
152
521k
    // FIXME: Avoid strlen.
153
521k
    if (ArgSize != strlen(Args.getArgString(Index)))
154
2
      return nullptr;
155
521k
156
521k
    Index += 2;
157
521k
    if (Index > Args.getNumInputArgStrings() ||
158
521k
        
Args.getArgString(Index - 1) == nullptr521k
)
159
4
      return nullptr;
160
521k
161
521k
    return new Arg(*this, Spelling, Index - 2, Args.getArgString(Index - 1));
162
521k
  case MultiArgClass: {
163
6
    // Matches iff this is an exact match.
164
6
    // FIXME: Avoid strlen.
165
6
    if (ArgSize != strlen(Args.getArgString(Index)))
166
0
      return nullptr;
167
6
168
6
    Index += 1 + getNumArgs();
169
6
    if (Index > Args.getNumInputArgStrings())
170
0
      return nullptr;
171
6
172
6
    Arg *A = new Arg(*this, Spelling, Index - 1 - getNumArgs(),
173
6
                     Args.getArgString(Index - getNumArgs()));
174
16
    for (unsigned i = 1; i != getNumArgs(); 
++i10
)
175
10
      A->getValues().push_back(Args.getArgString(Index - getNumArgs() + i));
176
6
    return A;
177
6
  }
178
1.33M
  case JoinedOrSeparateClass: {
179
1.33M
    // If this is not an exact match, it is a joined arg.
180
1.33M
    // FIXME: Avoid strlen.
181
1.33M
    if (ArgSize != strlen(Args.getArgString(Index))) {
182
697k
      const char *Value = Args.getArgString(Index) + ArgSize;
183
697k
      return new Arg(*this, Spelling, Index++, Value);
184
697k
    }
185
639k
186
639k
    // Otherwise it must be separate.
187
639k
    Index += 2;
188
639k
    if (Index > Args.getNumInputArgStrings() ||
189
639k
        
Args.getArgString(Index - 1) == nullptr639k
)
190
10
      return nullptr;
191
639k
192
639k
    return new Arg(*this, Spelling, Index - 2, Args.getArgString(Index - 1));
193
639k
  }
194
639k
  case JoinedAndSeparateClass:
195
25
    // Always matches.
196
25
    Index += 2;
197
25
    if (Index > Args.getNumInputArgStrings() ||
198
25
        Args.getArgString(Index - 1) == nullptr)
199
0
      return nullptr;
200
25
201
25
    return new Arg(*this, Spelling, Index - 2,
202
25
                   Args.getArgString(Index - 2) + ArgSize,
203
25
                   Args.getArgString(Index - 1));
204
978
  case RemainingArgsClass: {
205
978
    // Matches iff this is an exact match.
206
978
    // FIXME: Avoid strlen.
207
978
    if (ArgSize != strlen(Args.getArgString(Index)))
208
9
      return nullptr;
209
969
    Arg *A = new Arg(*this, Spelling, Index++);
210
1.96k
    while (Index < Args.getNumInputArgStrings() &&
211
1.96k
           
Args.getArgString(Index) != nullptr1.01k
)
212
999
      A->getValues().push_back(Args.getArgString(Index++));
213
969
    return A;
214
969
  }
215
969
  case RemainingArgsJoinedClass: {
216
14
    Arg *A = new Arg(*this, Spelling, Index);
217
14
    if (ArgSize != strlen(Args.getArgString(Index))) {
218
4
      // An inexact match means there is a joined arg.
219
4
      A->getValues().push_back(Args.getArgString(Index) + ArgSize);
220
4
    }
221
14
    Index++;
222
37
    while (Index < Args.getNumInputArgStrings() &&
223
37
           
Args.getArgString(Index) != nullptr25
)
224
23
      A->getValues().push_back(Args.getArgString(Index++));
225
14
    return A;
226
969
  }
227
969
228
969
  default:
229
0
    llvm_unreachable("Invalid option kind!");
230
2.94M
  }
231
2.94M
}
232
233
Arg *Option::accept(const ArgList &Args,
234
                    unsigned &Index,
235
2.94M
                    unsigned ArgSize) const {
236
2.94M
  std::unique_ptr<Arg> A(acceptInternal(Args, Index, ArgSize));
237
2.94M
  if (!A)
238
65.3k
    return nullptr;
239
2.87M
240
2.87M
  const Option &UnaliasedOption = getUnaliasedOption();
241
2.87M
  if (getID() == UnaliasedOption.getID())
242
2.83M
    return A.release();
243
46.8k
244
46.8k
  // "A" is an alias for a different flag. For most clients it's more convenient
245
46.8k
  // if this function returns unaliased Args, so create an unaliased arg for
246
46.8k
  // returning.
247
46.8k
248
46.8k
  // This creates a completely new Arg object for the unaliased Arg because
249
46.8k
  // the alias and the unaliased arg can have different Kinds and different
250
46.8k
  // Values (due to AliasArgs<>).
251
46.8k
252
46.8k
  // Get the spelling from the unaliased option.
253
46.8k
  StringRef UnaliasedSpelling = Args.MakeArgString(
254
46.8k
      Twine(UnaliasedOption.getPrefix()) + Twine(UnaliasedOption.getName()));
255
46.8k
256
46.8k
  // It's a bit weird that aliased and unaliased arg share one index, but
257
46.8k
  // the index is mostly use as a memory optimization in render().
258
46.8k
  // Due to this, ArgList::getArgString(A->getIndex()) will return the spelling
259
46.8k
  // of the aliased arg always, while A->getSpelling() returns either the
260
46.8k
  // unaliased or the aliased arg, depending on which Arg object it's called on.
261
46.8k
  Arg *UnaliasedA = new Arg(UnaliasedOption, UnaliasedSpelling, A->getIndex());
262
46.8k
  Arg *RawA = A.get();
263
46.8k
  UnaliasedA->setAlias(std::move(A));
264
46.8k
265
46.8k
  if (getKind() != FlagClass) {
266
44.0k
    // Values are usually owned by the ArgList. The exception are
267
44.0k
    // CommaJoined flags, where the Arg owns the values. For aliased flags,
268
44.0k
    // make the unaliased Arg the owner of the values.
269
44.0k
    // FIXME: There aren't many uses of CommaJoined -- try removing
270
44.0k
    // CommaJoined in favor of just calling StringRef::split(',') instead.
271
44.0k
    UnaliasedA->getValues() = RawA->getValues();
272
44.0k
    UnaliasedA->setOwnsValues(RawA->getOwnsValues());
273
44.0k
    RawA->setOwnsValues(false);
274
44.0k
    return UnaliasedA;
275
44.0k
  }
276
2.83k
277
2.83k
  // FlagClass aliases can have AliasArgs<>; add those to the unaliased arg.
278
2.83k
  if (const char *Val = getAliasArgs()) {
279
1.54k
    while (*Val != '\0') {
280
771
      UnaliasedA->getValues().push_back(Val);
281
771
282
771
      // Move past the '\0' to the next argument.
283
771
      Val += strlen(Val) + 1;
284
771
    }
285
771
  }
286
2.83k
  if (UnaliasedOption.getKind() == JoinedClass && 
!getAliasArgs()771
)
287
2
    // A Flag alias for a Joined option must provide an argument.
288
2
    UnaliasedA->getValues().push_back("");
289
2.83k
  return UnaliasedA;
290
2.83k
}