Skip to content

Commit b7accb2

Browse files
committed
Fix some bugs.
1 parent 9dd44fe commit b7accb2

File tree

3 files changed

+92
-23
lines changed

3 files changed

+92
-23
lines changed

clang-tools-extra/clang-tidy/misc/ConfusableIdentifierCheck.cpp

Lines changed: 59 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
#include "ConfusableIdentifierCheck.h"
1010

11+
#include "clang/ASTMatchers/ASTMatchers.h"
1112
#include "clang/Frontend/CompilerInstance.h"
1213
#include "clang/Lex/Preprocessor.h"
1314
#include "llvm/ADT/SmallString.h"
@@ -91,16 +92,22 @@ static llvm::SmallString<64U> skeleton(StringRef Name) {
9192
namespace {
9293
struct Entry {
9394
const NamedDecl *ND;
95+
const Decl *Parent;
9496
bool FromDerivedClass;
9597
};
9698
} // namespace
9799

100+
// Map from a context to the declarations in that context with the current
101+
// skeleton. At most one entry per distinct identifier is tracked. The
102+
// context is usually a `DeclContext`, but can also be a template declaration
103+
// that has no corresponding context, such as an alias template or variable
104+
// template.
98105
using DeclsWithinContextMap =
99-
llvm::DenseMap<const DeclContext *, llvm::SmallVector<Entry, 1>>;
106+
llvm::DenseMap<const Decl *, llvm::SmallVector<Entry, 1>>;
100107

101108
static bool addToContext(DeclsWithinContextMap &DeclsWithinContext,
102-
const DeclContext *DC, Entry E) {
103-
auto &Decls = DeclsWithinContext[DC];
109+
const Decl *Context, Entry E) {
110+
auto &Decls = DeclsWithinContext[Context];
104111
if (!Decls.empty() &&
105112
Decls.back().ND->getIdentifier() == E.ND->getIdentifier()) {
106113
// Already have a declaration with this identifier in this context. Don't
@@ -120,23 +127,30 @@ static bool addToContext(DeclsWithinContextMap &DeclsWithinContext,
120127
}
121128

122129
static void addToEnclosingContexts(DeclsWithinContextMap &DeclsWithinContext,
123-
const DeclContext *DC, const NamedDecl *ND) {
124-
while (DC) {
125-
DC = DC->getNonTransparentContext()->getPrimaryContext();
126-
if (!addToContext(DeclsWithinContext, DC, {ND, false}))
130+
const Decl *Parent,
131+
const NamedDecl *ND) {
132+
const Decl *Outer = Parent;
133+
while (Outer) {
134+
if (const auto *NS = dyn_cast<NamespaceDecl>(Outer))
135+
Outer = NS->getCanonicalDecl();
136+
137+
if (!addToContext(DeclsWithinContext, Outer, {ND, Parent, false}))
127138
return;
128139

129-
if (const auto *RD = dyn_cast<CXXRecordDecl>(DC)) {
140+
if (const auto *RD = dyn_cast<CXXRecordDecl>(Outer)) {
130141
RD = RD->getDefinition();
131142
if (RD) {
132143
RD->forallBases([&](const CXXRecordDecl *Base) {
133-
addToContext(DeclsWithinContext, Base, {ND, true});
144+
addToContext(DeclsWithinContext, Base, {ND, Parent, true});
134145
return true;
135146
});
136147
}
137148
}
138149

139-
DC = DC->getParent();
150+
auto *OuterDC = Outer->getDeclContext();
151+
if (!OuterDC)
152+
break;
153+
Outer = cast_or_null<Decl>(OuterDC->getNonTransparentContext());
140154
}
141155
}
142156

@@ -146,6 +160,24 @@ void ConfusableIdentifierCheck::check(
146160
if (!ND)
147161
return;
148162

163+
addDeclToCheck(ND, cast<Decl>(ND->getDeclContext()
164+
->getNonTransparentContext()));
165+
166+
// Associate template parameters with this declaration of this template.
167+
if (const auto *TD = dyn_cast<TemplateDecl>(ND)) {
168+
for (const NamedDecl *Param : *TD->getTemplateParameters())
169+
addDeclToCheck(Param, TD->getTemplatedDecl());
170+
}
171+
172+
// Associate function parameters with this declaration of this function.
173+
if (const auto *FD = dyn_cast<FunctionDecl>(ND)) {
174+
for (const NamedDecl *Param : FD->parameters())
175+
addDeclToCheck(Param, ND);
176+
}
177+
}
178+
179+
void ConfusableIdentifierCheck::addDeclToCheck(const NamedDecl *ND,
180+
const Decl *Parent) {
149181
const IdentifierInfo *NDII = ND->getIdentifier();
150182
if (!NDII)
151183
return;
@@ -154,7 +186,7 @@ void ConfusableIdentifierCheck::check(
154186
if (NDName.empty())
155187
return;
156188

157-
NameToDecls[NDII].push_back(ND);
189+
NameToDecls[NDII].push_back({ND, Parent});
158190
}
159191

160192
void ConfusableIdentifierCheck::onEndOfTranslationUnit() {
@@ -173,20 +205,17 @@ void ConfusableIdentifierCheck::onEndOfTranslationUnit() {
173205
// Find the declaration contexts that transitively contain each identifier.
174206
DeclsWithinContextMap DeclsWithinContext;
175207
for (const IdentifierInfo *II : Idents) {
176-
for (const NamedDecl *ND : NameToDecls[II]) {
177-
addToEnclosingContexts(DeclsWithinContext, ND->getDeclContext(), ND);
208+
for (auto [ND, Parent] : NameToDecls[II]) {
209+
addToEnclosingContexts(DeclsWithinContext, Parent, ND);
178210
}
179211
}
180212

181213
// Check to see if any declaration is declared in a context that
182214
// transitively contains another declaration with a different identifier but
183215
// the same skeleton.
184216
for (const IdentifierInfo *II : Idents) {
185-
for (const NamedDecl *OuterND : NameToDecls[II]) {
186-
const DeclContext *OuterDC = OuterND->getDeclContext()
187-
->getNonTransparentContext()
188-
->getPrimaryContext();
189-
for (Entry Inner : DeclsWithinContext[OuterDC]) {
217+
for (auto [OuterND, OuterParent] : NameToDecls[II]) {
218+
for (Entry Inner : DeclsWithinContext[OuterParent]) {
190219
// Don't complain if the identifiers are the same.
191220
if (OuterND->getIdentifier() == Inner.ND->getIdentifier())
192221
continue;
@@ -198,8 +227,7 @@ void ConfusableIdentifierCheck::onEndOfTranslationUnit() {
198227

199228
// If the declarations are in the same context, only diagnose the
200229
// later one.
201-
if (OuterDC->Equals(
202-
Inner.ND->getDeclContext()->getNonTransparentContext()) &&
230+
if (OuterParent == Inner.Parent &&
203231
Inner.ND->getASTContext()
204232
.getSourceManager()
205233
.isBeforeInTranslationUnit(Inner.ND->getLocation(),
@@ -220,7 +248,17 @@ void ConfusableIdentifierCheck::onEndOfTranslationUnit() {
220248

221249
void ConfusableIdentifierCheck::registerMatchers(
222250
ast_matchers::MatchFinder *Finder) {
223-
Finder->addMatcher(ast_matchers::namedDecl().bind("nameddecl"), this);
251+
// Parameter declarations sometimes use the translation unit or some outer
252+
// enclosing context as their `DeclContext`, instead of their parent, so
253+
// we handle them specially in `check`.
254+
auto AnyParamDecl = ast_matchers::anyOf(
255+
ast_matchers::parmVarDecl(), ast_matchers::templateTypeParmDecl(),
256+
ast_matchers::nonTypeTemplateParmDecl(),
257+
ast_matchers::templateTemplateParmDecl());
258+
Finder->addMatcher(
259+
ast_matchers::namedDecl(ast_matchers::unless(AnyParamDecl))
260+
.bind("nameddecl"),
261+
this);
224262
}
225263

226264
} // namespace clang::tidy::misc

clang-tools-extra/clang-tidy/misc/ConfusableIdentifierCheck.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,11 @@ class ConfusableIdentifierCheck : public ClangTidyCheck {
3131
}
3232

3333
private:
34-
llvm::DenseMap<const IdentifierInfo *,
35-
llvm::SmallVector<const NamedDecl *, 1>>
34+
void addDeclToCheck(const NamedDecl *ND, const Decl *Parent);
35+
36+
llvm::DenseMap<
37+
const IdentifierInfo *,
38+
llvm::SmallVector<std::pair<const NamedDecl *, const Decl *>, 1>>
3639
NameToDecls;
3740
};
3841

clang-tools-extra/test/clang-tidy/checkers/misc/confusable-identifiers.cpp

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,34 @@ template <typename t1, typename tl>
7474
// CHECK-MESSAGES: :[[#@LINE-2]]:20: note: other declaration found here
7575
void f9();
7676

77+
namespace different_contexts {
78+
// No warning for names in unrelated contexts.
79+
template <typename u1> void different_templates_1();
80+
template <typename ul> void different_templates_2();
81+
namespace inner {
82+
int ul;
83+
}
84+
}
85+
86+
namespace same_template {
87+
template <typename u1, typename ul> using T = int;
88+
// CHECK-MESSAGES: :[[#@LINE-1]]:35: warning: 'ul' is confusable with 'u1' [misc-confusable-identifiers]
89+
// CHECK-MESSAGES: :[[#@LINE-2]]:22: note: other declaration found here
90+
91+
template <typename v1, typename vl> int n;
92+
// CHECK-MESSAGES: :[[#@LINE-1]]:35: warning: 'vl' is confusable with 'v1' [misc-confusable-identifiers]
93+
// CHECK-MESSAGES: :[[#@LINE-2]]:22: note: other declaration found here
94+
95+
template <typename w1> int wl;
96+
// CHECK-MESSAGES: :[[#@LINE-1]]:22: warning: 'w1' is confusable with 'wl' [misc-confusable-identifiers]
97+
// CHECK-MESSAGES: :[[#@LINE-2]]:30: note: other declaration found here
98+
99+
int xl;
100+
template <typename x1> int x;
101+
// CHECK-MESSAGES: :[[#@LINE-1]]:22: warning: 'x1' is confusable with 'xl' [misc-confusable-identifiers]
102+
// CHECK-MESSAGES: :[[#@LINE-3]]:7: note: other declaration found here
103+
}
104+
77105
namespace f10 {
78106
int il;
79107
namespace inner {

0 commit comments

Comments
 (0)