Coverage Report

Created: 2020-10-24 06:27

/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/lib/ASTMatchers/Dynamic/Marshallers.cpp
Line
Count
Source (jump to first uncovered line)
1
//===--- Marshallers.cpp ----------------------------------------*- 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
#include "Marshallers.h"
10
#include "llvm/ADT/ArrayRef.h"
11
#include "llvm/ADT/Optional.h"
12
#include "llvm/ADT/StringRef.h"
13
#include "llvm/Support/Regex.h"
14
#include <string>
15
16
static llvm::Optional<std::string>
17
getBestGuess(llvm::StringRef Search, llvm::ArrayRef<llvm::StringRef> Allowed,
18
3
             llvm::StringRef DropPrefix = "", unsigned MaxEditDistance = 3) {
19
3
  if (MaxEditDistance != ~0U)
20
3
    ++MaxEditDistance;
21
3
  llvm::StringRef Res;
22
954
  for (const llvm::StringRef &Item : Allowed) {
23
954
    if (Item.equals_lower(Search)) {
24
0
      assert(!Item.equals(Search) && "This should be handled earlier on.");
25
0
      MaxEditDistance = 1;
26
0
      Res = Item;
27
0
      continue;
28
0
    }
29
954
    unsigned Distance = Item.edit_distance(Search);
30
954
    if (Distance < MaxEditDistance) {
31
1
      MaxEditDistance = Distance;
32
1
      Res = Item;
33
1
    }
34
954
  }
35
3
  if (!Res.empty())
36
1
    return Res.str();
37
2
  if (!DropPrefix.empty()) {
38
2
    --MaxEditDistance; // Treat dropping the prefix as 1 edit
39
458
    for (const llvm::StringRef &Item : Allowed) {
40
458
      auto NoPrefix = Item;
41
458
      if (!NoPrefix.consume_front(DropPrefix))
42
0
        continue;
43
458
      if (NoPrefix.equals_lower(Search)) {
44
1
        if (NoPrefix.equals(Search))
45
1
          return Item.str();
46
0
        MaxEditDistance = 1;
47
0
        Res = Item;
48
0
        continue;
49
0
      }
50
457
      unsigned Distance = NoPrefix.edit_distance(Search);
51
457
      if (Distance < MaxEditDistance) {
52
0
        MaxEditDistance = Distance;
53
0
        Res = Item;
54
0
      }
55
457
    }
56
1
    if (!Res.empty())
57
0
      return Res.str();
58
1
  }
59
1
  return llvm::None;
60
1
}
61
62
llvm::Optional<std::string>
63
clang::ast_matchers::dynamic::internal::ArgTypeTraits<
64
3
    clang::attr::Kind>::getBestGuess(const VariantValue &Value) {
65
3
  static constexpr llvm::StringRef Allowed[] = {
66
954
#define ATTR(X) "attr::" #X,
67
3
#include "clang/Basic/AttrList.inc"
68
3
  };
69
3
  if (Value.isString())
70
3
    return ::getBestGuess(Value.getString(), llvm::makeArrayRef(Allowed),
71
3
                          "attr::");
72
0
  return llvm::None;
73
0
}
74
75
llvm::Optional<std::string>
76
clang::ast_matchers::dynamic::internal::ArgTypeTraits<
77
0
    clang::CastKind>::getBestGuess(const VariantValue &Value) {
78
0
  static constexpr llvm::StringRef Allowed[] = {
79
0
#define CAST_OPERATION(Name) "CK_" #Name,
80
0
#include "clang/AST/OperationKinds.def"
81
0
  };
82
0
  if (Value.isString())
83
0
    return ::getBestGuess(Value.getString(), llvm::makeArrayRef(Allowed),
84
0
                          "CK_");
85
0
  return llvm::None;
86
0
}
87
88
llvm::Optional<std::string>
89
clang::ast_matchers::dynamic::internal::ArgTypeTraits<
90
0
    clang::OpenMPClauseKind>::getBestGuess(const VariantValue &Value) {
91
0
  static constexpr llvm::StringRef Allowed[] = {
92
0
#define OMP_CLAUSE_CLASS(Enum, Str, Class) #Enum,
93
0
#include "llvm/Frontend/OpenMP/OMPKinds.def"
94
0
  };
95
0
  if (Value.isString())
96
0
    return ::getBestGuess(Value.getString(), llvm::makeArrayRef(Allowed),
97
0
                          "OMPC_");
98
0
  return llvm::None;
99
0
}
100
101
llvm::Optional<std::string>
102
clang::ast_matchers::dynamic::internal::ArgTypeTraits<
103
0
    clang::UnaryExprOrTypeTrait>::getBestGuess(const VariantValue &Value) {
104
0
  static constexpr llvm::StringRef Allowed[] = {
105
0
#define UNARY_EXPR_OR_TYPE_TRAIT(Spelling, Name, Key) "UETT_" #Name,
106
0
#define CXX11_UNARY_EXPR_OR_TYPE_TRAIT(Spelling, Name, Key) "UETT_" #Name,
107
0
#include "clang/Basic/TokenKinds.def"
108
0
  };
109
0
  if (Value.isString())
110
0
    return ::getBestGuess(Value.getString(), llvm::makeArrayRef(Allowed),
111
0
                          "UETT_");
112
0
  return llvm::None;
113
0
}
114
115
static constexpr std::pair<llvm::StringRef, llvm::Regex::RegexFlags>
116
    RegexMap[] = {
117
        {"NoFlags", llvm::Regex::RegexFlags::NoFlags},
118
        {"IgnoreCase", llvm::Regex::RegexFlags::IgnoreCase},
119
        {"Newline", llvm::Regex::RegexFlags::Newline},
120
        {"BasicRegex", llvm::Regex::RegexFlags::BasicRegex},
121
};
122
123
static llvm::Optional<llvm::Regex::RegexFlags>
124
8
getRegexFlag(llvm::StringRef Flag) {
125
26
  for (const auto &StringFlag : RegexMap) {
126
26
    if (Flag == StringFlag.first)
127
5
      return StringFlag.second;
128
26
  }
129
3
  return llvm::None;
130
8
}
131
132
static llvm::Optional<llvm::StringRef>
133
4
getCloseRegexMatch(llvm::StringRef Flag) {
134
12
  for (const auto &StringFlag : RegexMap) {
135
12
    if (Flag.edit_distance(StringFlag.first) < 3)
136
3
      return StringFlag.first;
137
12
  }
138
1
  return llvm::None;
139
4
}
140
141
llvm::Optional<llvm::Regex::RegexFlags>
142
clang::ast_matchers::dynamic::internal::ArgTypeTraits<
143
5
    llvm::Regex::RegexFlags>::getFlags(llvm::StringRef Flags) {
144
5
  llvm::Optional<llvm::Regex::RegexFlags> Flag;
145
5
  SmallVector<StringRef, 4> Split;
146
5
  Flags.split(Split, '|', -1, false);
147
8
  for (StringRef OrFlag : Split) {
148
8
    if (llvm::Optional<llvm::Regex::RegexFlags> NextFlag =
149
5
            getRegexFlag(OrFlag.trim()))
150
5
      Flag = Flag.getValueOr(llvm::Regex::NoFlags) | *NextFlag;
151
3
    else
152
3
      return None;
153
8
  }
154
2
  return Flag;
155
5
}
156
157
llvm::Optional<std::string>
158
clang::ast_matchers::dynamic::internal::ArgTypeTraits<
159
3
    llvm::Regex::RegexFlags>::getBestGuess(const VariantValue &Value) {
160
3
  if (!Value.isString())
161
0
    return llvm::None;
162
3
  SmallVector<StringRef, 4> Split;
163
3
  llvm::StringRef(Value.getString()).split(Split, '|', -1, false);
164
4
  for (llvm::StringRef &Flag : Split) {
165
4
    if (llvm::Optional<llvm::StringRef> BestGuess =
166
3
            getCloseRegexMatch(Flag.trim()))
167
3
      Flag = *BestGuess;
168
1
    else
169
1
      return None;
170
4
  }
171
2
  if (Split.empty())
172
0
    return None;
173
2
  return llvm::join(Split, " | ");
174
2
}