Coverage Report

Created: 2021-09-21 08:58

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