Coverage Report

Created: 2021-01-26 06:56

/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/lib/ASTMatchers/Dynamic/VariantValue.cpp
Line
Count
Source (jump to first uncovered line)
1
//===--- VariantValue.cpp - Polymorphic value type --------------*- C++ -*-===//
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
/// \file
10
/// Polymorphic value type.
11
///
12
//===----------------------------------------------------------------------===//
13
14
#include "clang/ASTMatchers/Dynamic/VariantValue.h"
15
#include "clang/Basic/LLVM.h"
16
#include "llvm/ADT/STLExtras.h"
17
18
namespace clang {
19
namespace ast_matchers {
20
namespace dynamic {
21
22
90
std::string ArgKind::asString() const {
23
90
  switch (getArgKind()) {
24
7
  case AK_Matcher:
25
7
    return (Twine("Matcher<") + MatcherKind.asStringRef() + ">").str();
26
4
  case AK_Boolean:
27
4
    return "boolean";
28
4
  case AK_Double:
29
4
    return "double";
30
10
  case AK_Unsigned:
31
10
    return "unsigned";
32
65
  case AK_String:
33
65
    return "string";
34
0
  }
35
0
  llvm_unreachable("unhandled ArgKind");
36
0
}
37
38
14.1k
bool ArgKind::isConvertibleTo(ArgKind To, unsigned *Specificity) const {
39
14.1k
  if (K != To.K)
40
0
    return false;
41
14.1k
  if (K != AK_Matcher) {
42
0
    if (Specificity)
43
0
      *Specificity = 1;
44
0
    return true;
45
0
  }
46
14.1k
  unsigned Distance;
47
14.1k
  if (!MatcherKind.isBaseOf(To.MatcherKind, &Distance))
48
12.2k
    return false;
49
50
1.89k
  if (Specificity)
51
1.16k
    *Specificity = 100 - Distance;
52
1.89k
  return true;
53
1.89k
}
54
55
bool
56
VariantMatcher::MatcherOps::canConstructFrom(const DynTypedMatcher &Matcher,
57
597
                                             bool &IsExactMatch) const {
58
597
  IsExactMatch = Matcher.getSupportedKind().isSame(NodeKind);
59
597
  return Matcher.canConvertTo(NodeKind);
60
597
}
61
62
DynTypedMatcher VariantMatcher::MatcherOps::convertMatcher(
63
0
    const DynTypedMatcher &Matcher) const {
64
0
  return Matcher.dynCastTo(NodeKind);
65
0
}
66
67
llvm::Optional<DynTypedMatcher>
68
VariantMatcher::MatcherOps::constructVariadicOperator(
69
    DynTypedMatcher::VariadicOperator Op,
70
13
    ArrayRef<VariantMatcher> InnerMatchers) const {
71
13
  std::vector<DynTypedMatcher> DynMatchers;
72
21
  for (const auto &InnerMatcher : InnerMatchers) {
73
    // Abort if any of the inner matchers can't be converted to
74
    // Matcher<T>.
75
21
    if (!InnerMatcher.Value)
76
0
      return llvm::None;
77
21
    llvm::Optional<DynTypedMatcher> Inner =
78
21
        InnerMatcher.Value->getTypedMatcher(*this);
79
21
    if (!Inner)
80
1
      return llvm::None;
81
20
    DynMatchers.push_back(*Inner);
82
20
  }
83
12
  return DynTypedMatcher::constructVariadic(Op, NodeKind, DynMatchers);
84
13
}
85
86
165
VariantMatcher::Payload::~Payload() {}
87
88
class VariantMatcher::SinglePayload : public VariantMatcher::Payload {
89
public:
90
132
  SinglePayload(const DynTypedMatcher &Matcher) : Matcher(Matcher) {}
91
92
23
  llvm::Optional<DynTypedMatcher> getSingleMatcher() const override {
93
23
    return Matcher;
94
23
  }
95
96
6
  std::string getTypeAsString() const override {
97
6
    return (Twine("Matcher<") + Matcher.getSupportedKind().asStringRef() + ">")
98
6
        .str();
99
6
  }
100
101
  llvm::Optional<DynTypedMatcher>
102
291
  getTypedMatcher(const MatcherOps &Ops) const override {
103
291
    bool Ignore;
104
291
    if (Ops.canConstructFrom(Matcher, Ignore))
105
263
      return Matcher;
106
28
    return llvm::None;
107
28
  }
108
109
2
  bool isConvertibleTo(ASTNodeKind Kind, unsigned *Specificity) const override {
110
2
    return ArgKind(Matcher.getSupportedKind())
111
2
        .isConvertibleTo(Kind, Specificity);
112
2
  }
113
114
private:
115
  const DynTypedMatcher Matcher;
116
};
117
118
class VariantMatcher::PolymorphicPayload : public VariantMatcher::Payload {
119
public:
120
  PolymorphicPayload(std::vector<DynTypedMatcher> MatchersIn)
121
27
      : Matchers(std::move(MatchersIn)) {}
122
123
27
  ~PolymorphicPayload() override {}
124
125
2
  llvm::Optional<DynTypedMatcher> getSingleMatcher() const override {
126
2
    if (Matchers.size() != 1)
127
2
      return llvm::Optional<DynTypedMatcher>();
128
0
    return Matchers[0];
129
0
  }
130
131
4
  std::string getTypeAsString() const override {
132
4
    std::string Inner;
133
16
    for (size_t i = 0, e = Matchers.size(); i != e; 
++i12
) {
134
12
      if (i != 0)
135
8
        Inner += "|";
136
12
      Inner += Matchers[i].getSupportedKind().asStringRef();
137
12
    }
138
4
    return (Twine("Matcher<") + Inner + ">").str();
139
4
  }
140
141
  llvm::Optional<DynTypedMatcher>
142
72
  getTypedMatcher(const MatcherOps &Ops) const override {
143
72
    bool FoundIsExact = false;
144
72
    const DynTypedMatcher *Found = nullptr;
145
72
    int NumFound = 0;
146
378
    for (size_t i = 0, e = Matchers.size(); i != e; 
++i306
) {
147
306
      bool IsExactMatch;
148
306
      if (Ops.canConstructFrom(Matchers[i], IsExactMatch)) {
149
70
        if (Found) {
150
0
          if (FoundIsExact) {
151
0
            assert(!IsExactMatch && "We should not have two exact matches.");
152
0
            continue;
153
0
          }
154
70
        }
155
70
        Found = &Matchers[i];
156
70
        FoundIsExact = IsExactMatch;
157
70
        ++NumFound;
158
70
      }
159
306
    }
160
    // We only succeed if we found exactly one, or if we found an exact match.
161
72
    if (Found && 
(70
FoundIsExact70
||
NumFound == 112
))
162
70
      return *Found;
163
2
    return llvm::None;
164
2
  }
165
166
0
  bool isConvertibleTo(ASTNodeKind Kind, unsigned *Specificity) const override {
167
0
    unsigned MaxSpecificity = 0;
168
0
    for (const DynTypedMatcher &Matcher : Matchers) {
169
0
      unsigned ThisSpecificity;
170
0
      if (ArgKind(Matcher.getSupportedKind())
171
0
              .isConvertibleTo(Kind, &ThisSpecificity)) {
172
0
        MaxSpecificity = std::max(MaxSpecificity, ThisSpecificity);
173
0
      }
174
0
    }
175
0
    if (Specificity)
176
0
      *Specificity = MaxSpecificity;
177
0
    return MaxSpecificity > 0;
178
0
  }
179
180
  const std::vector<DynTypedMatcher> Matchers;
181
};
182
183
class VariantMatcher::VariadicOpPayload : public VariantMatcher::Payload {
184
public:
185
  VariadicOpPayload(DynTypedMatcher::VariadicOperator Op,
186
                    std::vector<VariantMatcher> Args)
187
6
      : Op(Op), Args(std::move(Args)) {}
188
189
0
  llvm::Optional<DynTypedMatcher> getSingleMatcher() const override {
190
0
    return llvm::Optional<DynTypedMatcher>();
191
0
  }
192
193
1
  std::string getTypeAsString() const override {
194
1
    std::string Inner;
195
3
    for (size_t i = 0, e = Args.size(); i != e; 
++i2
) {
196
2
      if (i != 0)
197
1
        Inner += "&";
198
2
      Inner += Args[i].getTypeAsString();
199
2
    }
200
1
    return Inner;
201
1
  }
202
203
  llvm::Optional<DynTypedMatcher>
204
13
  getTypedMatcher(const MatcherOps &Ops) const override {
205
13
    return Ops.constructVariadicOperator(Op, Args);
206
13
  }
207
208
0
  bool isConvertibleTo(ASTNodeKind Kind, unsigned *Specificity) const override {
209
0
    for (const VariantMatcher &Matcher : Args) {
210
0
      if (!Matcher.isConvertibleTo(Kind, Specificity))
211
0
        return false;
212
0
    }
213
0
    return true;
214
0
  }
215
216
private:
217
  const DynTypedMatcher::VariadicOperator Op;
218
  const std::vector<VariantMatcher> Args;
219
};
220
221
228
VariantMatcher::VariantMatcher() {}
222
223
132
VariantMatcher VariantMatcher::SingleMatcher(const DynTypedMatcher &Matcher) {
224
132
  return VariantMatcher(std::make_shared<SinglePayload>(Matcher));
225
132
}
226
227
VariantMatcher
228
27
VariantMatcher::PolymorphicMatcher(std::vector<DynTypedMatcher> Matchers) {
229
27
  return VariantMatcher(
230
27
      std::make_shared<PolymorphicPayload>(std::move(Matchers)));
231
27
}
232
233
VariantMatcher VariantMatcher::VariadicOperatorMatcher(
234
    DynTypedMatcher::VariadicOperator Op,
235
6
    std::vector<VariantMatcher> Args) {
236
6
  return VariantMatcher(
237
6
      std::make_shared<VariadicOpPayload>(Op, std::move(Args)));
238
6
}
239
240
25
llvm::Optional<DynTypedMatcher> VariantMatcher::getSingleMatcher() const {
241
25
  return Value ? Value->getSingleMatcher() : 
llvm::Optional<DynTypedMatcher>()0
;
242
25
}
243
244
0
void VariantMatcher::reset() { Value.reset(); }
245
246
11
std::string VariantMatcher::getTypeAsString() const {
247
11
  if (Value) return Value->getTypeAsString();
248
0
  return "<Nothing>";
249
0
}
250
251
1.23k
VariantValue::VariantValue(const VariantValue &Other) : Type(VT_Nothing) {
252
1.23k
  *this = Other;
253
1.23k
}
254
255
4
VariantValue::VariantValue(bool Boolean) : Type(VT_Nothing) {
256
4
  setBoolean(Boolean);
257
4
}
258
259
5
VariantValue::VariantValue(double Double) : Type(VT_Nothing) {
260
5
  setDouble(Double);
261
5
}
262
263
18
VariantValue::VariantValue(unsigned Unsigned) : Type(VT_Nothing) {
264
18
  setUnsigned(Unsigned);
265
18
}
266
267
68
VariantValue::VariantValue(StringRef String) : Type(VT_Nothing) {
268
68
  setString(String);
269
68
}
270
271
2
VariantValue::VariantValue(ASTNodeKind NodeKind) : Type(VT_Nothing) {
272
2
  setNodeKind(NodeKind);
273
2
}
274
275
129
VariantValue::VariantValue(const VariantMatcher &Matcher) : Type(VT_Nothing) {
276
129
  setMatcher(Matcher);
277
129
}
278
279
2.27k
VariantValue::~VariantValue() { reset(); }
280
281
1.96k
VariantValue &VariantValue::operator=(const VariantValue &Other) {
282
1.96k
  if (this == &Other) 
return *this0
;
283
1.96k
  reset();
284
1.96k
  switch (Other.Type) {
285
15
  case VT_Boolean:
286
15
    setBoolean(Other.getBoolean());
287
15
    break;
288
25
  case VT_Double:
289
25
    setDouble(Other.getDouble());
290
25
    break;
291
77
  case VT_Unsigned:
292
77
    setUnsigned(Other.getUnsigned());
293
77
    break;
294
296
  case VT_String:
295
296
    setString(Other.getString());
296
296
    break;
297
1
  case VT_NodeKind:
298
1
    setNodeKind(Other.getNodeKind());
299
1
    break;
300
169
  case VT_Matcher:
301
169
    setMatcher(Other.getMatcher());
302
169
    break;
303
1.38k
  case VT_Nothing:
304
1.38k
    Type = VT_Nothing;
305
1.38k
    break;
306
1.96k
  }
307
1.96k
  return *this;
308
1.96k
}
309
310
5.04k
void VariantValue::reset() {
311
5.04k
  switch (Type) {
312
364
  case VT_String:
313
364
    delete Value.String;
314
364
    break;
315
298
  case VT_Matcher:
316
298
    delete Value.Matcher;
317
298
    break;
318
4
  case VT_NodeKind:
319
4
    delete Value.NodeKind;
320
4
    break;
321
  // Cases that do nothing.
322
19
  case VT_Boolean:
323
49
  case VT_Double:
324
144
  case VT_Unsigned:
325
4.38k
  case VT_Nothing:
326
4.38k
    break;
327
5.04k
  }
328
5.04k
  Type = VT_Nothing;
329
5.04k
}
330
331
30
bool VariantValue::isBoolean() const {
332
30
  return Type == VT_Boolean;
333
30
}
334
335
19
bool VariantValue::getBoolean() const {
336
19
  assert(isBoolean());
337
19
  return Value.Boolean;
338
19
}
339
340
19
void VariantValue::setBoolean(bool NewValue) {
341
19
  reset();
342
19
  Type = VT_Boolean;
343
19
  Value.Boolean = NewValue;
344
19
}
345
346
41
bool VariantValue::isDouble() const {
347
41
  return Type == VT_Double;
348
41
}
349
350
30
double VariantValue::getDouble() const {
351
30
  assert(isDouble());
352
30
  return Value.Double;
353
30
}
354
355
30
void VariantValue::setDouble(double NewValue) {
356
30
  reset();
357
30
  Type = VT_Double;
358
30
  Value.Double = NewValue;
359
30
}
360
361
110
bool VariantValue::isUnsigned() const {
362
110
  return Type == VT_Unsigned;
363
110
}
364
365
91
unsigned VariantValue::getUnsigned() const {
366
91
  assert(isUnsigned());
367
91
  return Value.Unsigned;
368
91
}
369
370
95
void VariantValue::setUnsigned(unsigned NewValue) {
371
95
  reset();
372
95
  Type = VT_Unsigned;
373
95
  Value.Unsigned = NewValue;
374
95
}
375
376
448
bool VariantValue::isString() const {
377
448
  return Type == VT_String;
378
448
}
379
380
360
const std::string &VariantValue::getString() const {
381
360
  assert(isString());
382
360
  return *Value.String;
383
360
}
384
385
364
void VariantValue::setString(StringRef NewValue) {
386
364
  reset();
387
364
  Type = VT_String;
388
364
  Value.String = new std::string(NewValue);
389
364
}
390
391
8
bool VariantValue::isNodeKind() const { return Type == VT_NodeKind; }
392
393
4
const ASTNodeKind &VariantValue::getNodeKind() const {
394
4
  assert(isNodeKind());
395
4
  return *Value.NodeKind;
396
4
}
397
398
4
void VariantValue::setNodeKind(ASTNodeKind NewValue) {
399
4
  reset();
400
4
  Type = VT_NodeKind;
401
4
  Value.NodeKind = new ASTNodeKind(NewValue);
402
4
}
403
404
566
bool VariantValue::isMatcher() const {
405
566
  return Type == VT_Matcher;
406
566
}
407
408
412
const VariantMatcher &VariantValue::getMatcher() const {
409
412
  assert(isMatcher());
410
412
  return *Value.Matcher;
411
412
}
412
413
298
void VariantValue::setMatcher(const VariantMatcher &NewValue) {
414
298
  reset();
415
298
  Type = VT_Matcher;
416
298
  Value.Matcher = new VariantMatcher(NewValue);
417
298
}
418
419
6
bool VariantValue::isConvertibleTo(ArgKind Kind, unsigned *Specificity) const {
420
6
  switch (Kind.getArgKind()) {
421
0
  case ArgKind::AK_Boolean:
422
0
    if (!isBoolean())
423
0
      return false;
424
0
    *Specificity = 1;
425
0
    return true;
426
427
0
  case ArgKind::AK_Double:
428
0
    if (!isDouble())
429
0
      return false;
430
0
    *Specificity = 1;
431
0
    return true;
432
433
0
  case ArgKind::AK_Unsigned:
434
0
    if (!isUnsigned())
435
0
      return false;
436
0
    *Specificity = 1;
437
0
    return true;
438
439
2
  case ArgKind::AK_String:
440
2
    if (!isString())
441
1
      return false;
442
1
    *Specificity = 1;
443
1
    return true;
444
445
4
  case ArgKind::AK_Matcher:
446
4
    if (!isMatcher())
447
2
      return false;
448
2
    return getMatcher().isConvertibleTo(Kind.getMatcherKind(), Specificity);
449
0
  }
450
0
  llvm_unreachable("Invalid Type");
451
0
}
452
453
bool VariantValue::isConvertibleTo(ArrayRef<ArgKind> Kinds,
454
6
                                   unsigned *Specificity) const {
455
6
  unsigned MaxSpecificity = 0;
456
6
  for (const ArgKind& Kind : Kinds) {
457
6
    unsigned ThisSpecificity;
458
6
    if (!isConvertibleTo(Kind, &ThisSpecificity))
459
3
      continue;
460
3
    MaxSpecificity = std::max(MaxSpecificity, ThisSpecificity);
461
3
  }
462
6
  if (Specificity && MaxSpecificity > 0) {
463
3
    *Specificity = MaxSpecificity;
464
3
  }
465
6
  return MaxSpecificity > 0;
466
6
}
467
468
29
std::string VariantValue::getTypeAsString() const {
469
29
  switch (Type) {
470
9
  case VT_String: return "String";
471
9
  case VT_Matcher: return getMatcher().getTypeAsString();
472
2
  case VT_Boolean: return "Boolean";
473
2
  case VT_Double: return "Double";
474
6
  case VT_Unsigned: return "Unsigned";
475
0
  case VT_NodeKind:
476
0
    return getNodeKind().asStringRef().str();
477
1
  case VT_Nothing: return "Nothing";
478
0
  }
479
0
  llvm_unreachable("Invalid Type");
480
0
}
481
482
} // end namespace dynamic
483
} // end namespace ast_matchers
484
} // end namespace clang