11
11
12
12
#include "clang/Frontend/CompilerInstance.h"
13
13
#include "clang/Lex/Preprocessor.h"
14
+ #include "llvm/ADT/SmallString.h"
14
15
#include "llvm/Support/ConvertUTF.h"
15
16
16
17
namespace {
@@ -45,14 +46,13 @@ ConfusableIdentifierCheck::~ConfusableIdentifierCheck() = default;
45
46
// We're skipping 1. and 3. for the sake of simplicity, but this can lead to
46
47
// false positive.
47
48
48
- static std::string skeleton(StringRef Name) {
49
+ static llvm::SmallString<64U> skeleton(StringRef Name) {
49
50
using namespace llvm;
50
- std::string SName = Name.str();
51
- std::string Skeleton;
52
- Skeleton.reserve(1 + Name.size());
51
+ SmallString<64U> Skeleton;
52
+ Skeleton.reserve(1U + Name.size());
53
53
54
- const char *Curr = SName.c_str ();
55
- const char *End = Curr + SName .size();
54
+ const char *Curr = Name.data ();
55
+ const char *End = Curr + Name .size();
56
56
while (Curr < End) {
57
57
58
58
const char *Prev = Curr;
@@ -99,8 +99,6 @@ static bool mayShadowImpl(const NamedDecl *ND0, const NamedDecl *ND1) {
99
99
100
100
static bool isMemberOf(const ConfusableIdentifierCheck::ContextInfo *DC0,
101
101
const ConfusableIdentifierCheck::ContextInfo *DC1) {
102
- if (DC0->Bases.empty())
103
- return false;
104
102
return llvm::is_contained(DC1->Bases, DC0->PrimaryContext);
105
103
}
106
104
@@ -117,16 +115,23 @@ static bool mayShadow(const NamedDecl *ND0,
117
115
const ConfusableIdentifierCheck::ContextInfo *DC0,
118
116
const NamedDecl *ND1,
119
117
const ConfusableIdentifierCheck::ContextInfo *DC1) {
120
- if (!DC0->Bases.empty() && ND1->getAccess() != AS_private &&
121
- isMemberOf(DC1, DC0))
122
- return true;
123
- if (!DC1->Bases.empty() && ND0->getAccess() != AS_private &&
124
- isMemberOf(DC0, DC1))
125
- return true;
126
118
127
- return enclosesContext(DC0, DC1) &&
128
- (mayShadowImpl(ND0, ND1) || mayShadowImpl(DC0->NonTransparentContext,
129
- DC1->NonTransparentContext));
119
+ if (!DC0->Bases.empty() && !DC1->Bases.empty()) {
120
+ // if any of the declaration is a non-private member of the other
121
+ // declaration, it's shadowed by the former
122
+
123
+ if (ND1->getAccess() != AS_private && isMemberOf(DC1, DC0))
124
+ return true;
125
+
126
+ if (ND0->getAccess() != AS_private && isMemberOf(DC0, DC1))
127
+ return true;
128
+ }
129
+
130
+ if (!mayShadowImpl(DC0->NonTransparentContext, DC1->NonTransparentContext) &&
131
+ !mayShadowImpl(ND0, ND1))
132
+ return false;
133
+
134
+ return enclosesContext(DC0, DC1);
130
135
}
131
136
132
137
const ConfusableIdentifierCheck::ContextInfo *
@@ -172,26 +177,41 @@ ConfusableIdentifierCheck::getContextInfo(const DeclContext *DC) {
172
177
173
178
void ConfusableIdentifierCheck::check(
174
179
const ast_matchers::MatchFinder::MatchResult &Result) {
175
- if (const auto *ND = Result.Nodes.getNodeAs<NamedDecl>("nameddecl")) {
176
- if (IdentifierInfo *NDII = ND->getIdentifier()) {
177
- const ContextInfo *Info = getContextInfo(ND->getDeclContext());
178
- StringRef NDName = NDII->getName();
179
- llvm::SmallVector<Entry> &Mapped = Mapper[skeleton(NDName)];
180
- for (const Entry &E : Mapped) {
181
- const IdentifierInfo *ONDII = E.Declaration->getIdentifier();
182
- if (mayShadow(ND, Info, E.Declaration, E.Info)) {
183
- StringRef ONDName = ONDII->getName();
184
- if (ONDName != NDName) {
185
- diag(ND->getLocation(), "%0 is confusable with %1")
186
- << ND << E.Declaration;
187
- diag(E.Declaration->getLocation(), "other declaration found here",
188
- DiagnosticIDs::Note);
189
- }
190
- }
191
- }
192
- Mapped.push_back({ND, Info});
193
- }
180
+ const auto *ND = Result.Nodes.getNodeAs<NamedDecl>("nameddecl");
181
+ if (!ND)
182
+ return;
183
+
184
+ IdentifierInfo *NDII = ND->getIdentifier();
185
+ if (!NDII)
186
+ return;
187
+
188
+ StringRef NDName = NDII->getName();
189
+ if (NDName.empty())
190
+ return;
191
+
192
+ const ContextInfo *Info = getContextInfo(ND->getDeclContext());
193
+
194
+ llvm::SmallVector<Entry> &Mapped = Mapper[skeleton(NDName)];
195
+ for (const Entry &E : Mapped) {
196
+ if (!mayShadow(ND, Info, E.Declaration, E.Info))
197
+ continue;
198
+
199
+ const IdentifierInfo *ONDII = E.Declaration->getIdentifier();
200
+ StringRef ONDName = ONDII->getName();
201
+ if (ONDName == NDName)
202
+ continue;
203
+
204
+ diag(ND->getLocation(), "%0 is confusable with %1") << ND << E.Declaration;
205
+ diag(E.Declaration->getLocation(), "other declaration found here",
206
+ DiagnosticIDs::Note);
194
207
}
208
+
209
+ Mapped.push_back({ND, Info});
210
+ }
211
+
212
+ void ConfusableIdentifierCheck::onEndOfTranslationUnit() {
213
+ Mapper.clear();
214
+ ContextInfos.clear();
195
215
}
196
216
197
217
void ConfusableIdentifierCheck::registerMatchers(
0 commit comments