Skip to content

Commit 72f2b39

Browse files
committed
[clang-tidy] Improved modernize-use-using by fixing a false-negative
The check needs a parent decl to match but if the typedef is in a function, the parent is a declStmt which is not a decl by itself. Improved the matcher to match on either a decl or a declstmt and extract the decl from the stmt in the latter case. fixes #72179
1 parent 3f5e649 commit 72f2b39

File tree

3 files changed

+66
-4
lines changed

3 files changed

+66
-4
lines changed

clang-tools-extra/clang-tidy/modernize/UseUsingCheck.cpp

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

99
#include "UseUsingCheck.h"
1010
#include "clang/AST/ASTContext.h"
11+
#include "clang/AST/DeclGroup.h"
1112
#include "clang/Lex/Lexer.h"
1213

1314
using namespace clang::ast_matchers;
@@ -24,6 +25,7 @@ static constexpr llvm::StringLiteral ExternCDeclName = "extern-c-decl";
2425
static constexpr llvm::StringLiteral ParentDeclName = "parent-decl";
2526
static constexpr llvm::StringLiteral TagDeclName = "tag-decl";
2627
static constexpr llvm::StringLiteral TypedefName = "typedef";
28+
static constexpr llvm::StringLiteral DeclStmtName = "decl-stmt";
2729

2830
UseUsingCheck::UseUsingCheck(StringRef Name, ClangTidyContext *Context)
2931
: ClangTidyCheck(Name, Context),
@@ -41,7 +43,8 @@ void UseUsingCheck::registerMatchers(MatchFinder *Finder) {
4143
unless(isInstantiated()),
4244
optionally(hasAncestor(
4345
linkageSpecDecl(isExternCLinkage()).bind(ExternCDeclName))),
44-
hasParent(decl().bind(ParentDeclName)))
46+
anyOf(hasParent(decl().bind(ParentDeclName)),
47+
hasParent(declStmt().bind(DeclStmtName))))
4548
.bind(TypedefName),
4649
this);
4750

@@ -51,17 +54,32 @@ void UseUsingCheck::registerMatchers(MatchFinder *Finder) {
5154
tagDecl(
5255
anyOf(allOf(unless(anyOf(isImplicit(),
5356
classTemplateSpecializationDecl())),
54-
hasParent(decl().bind(ParentDeclName))),
57+
anyOf(hasParent(decl().bind(ParentDeclName)),
58+
hasParent(declStmt().bind(DeclStmtName)))),
5559
// We want the parent of the ClassTemplateDecl, not the parent
5660
// of the specialization.
5761
classTemplateSpecializationDecl(hasAncestor(classTemplateDecl(
58-
hasParent(decl().bind(ParentDeclName)))))))
62+
anyOf(hasParent(decl().bind(ParentDeclName)),
63+
hasParent(declStmt().bind(DeclStmtName))))))))
5964
.bind(TagDeclName),
6065
this);
6166
}
6267

6368
void UseUsingCheck::check(const MatchFinder::MatchResult &Result) {
6469
const auto *ParentDecl = Result.Nodes.getNodeAs<Decl>(ParentDeclName);
70+
71+
if (!ParentDecl) {
72+
const auto *ParentDeclStmt = Result.Nodes.getNodeAs<DeclStmt>(DeclStmtName);
73+
if (ParentDeclStmt) {
74+
if (ParentDeclStmt->isSingleDecl())
75+
ParentDecl = ParentDeclStmt->getSingleDecl();
76+
else
77+
ParentDecl =
78+
ParentDeclStmt->getDeclGroup().getDeclGroup()
79+
[ParentDeclStmt->getDeclGroup().getDeclGroup().size() - 1];
80+
}
81+
}
82+
6583
if (!ParentDecl)
6684
return;
6785

clang-tools-extra/docs/ReleaseNotes.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,9 @@ Changes in existing checks
235235
analyzed, se the check now handles the common patterns
236236
`const auto e = (*vector_ptr)[i]` and `const auto e = vector_ptr->at(i);`.
237237

238+
- Improved :doc:`modernize-use-using <clang-tidy/checks/modernize/use-using>`
239+
check by adding support for detection of typedefs declared on function level.
240+
238241
- Improved :doc:`readability-implicit-bool-conversion
239242
<clang-tidy/checks/readability/implicit-bool-conversion>` check to provide
240243
valid fix suggestions for ``static_cast`` without a preceding space and

clang-tools-extra/test/clang-tidy/checkers/modernize/use-using.cpp

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %check_clang_tidy %s modernize-use-using %t -- -- -I %S/Inputs/use-using/
1+
// RUN: %check_clang_tidy %s modernize-use-using %t -- -- -fno-delayed-template-parsing -I %S/Inputs/use-using/
22

33
typedef int Type;
44
// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef' [modernize-use-using]
@@ -342,3 +342,44 @@ typedef int InExternCPP;
342342
// CHECK-FIXES: using InExternCPP = int;
343343

344344
}
345+
346+
namespace ISSUE_72179
347+
{
348+
void foo()
349+
{
350+
typedef int a;
351+
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use 'using' instead of 'typedef' [modernize-use-using]
352+
// CHECK-FIXES: using a = int;
353+
354+
}
355+
356+
void foo2()
357+
{
358+
typedef struct { int a; union { int b; }; } c;
359+
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use 'using' instead of 'typedef' [modernize-use-using]
360+
// CHECK-FIXES: using c = struct { int a; union { int b; }; };
361+
}
362+
363+
template <typename T>
364+
void foo3()
365+
{
366+
typedef T b;
367+
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use 'using' instead of 'typedef' [modernize-use-using]
368+
// CHECK-FIXES: using b = T;
369+
}
370+
371+
template <typename T>
372+
class MyClass
373+
{
374+
void foo()
375+
{
376+
typedef MyClass c;
377+
// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use 'using' instead of 'typedef' [modernize-use-using]
378+
// CHECK-FIXES: using c = MyClass;
379+
}
380+
};
381+
382+
const auto foo4 = [](int a){typedef int d;};
383+
// CHECK-MESSAGES: :[[@LINE-1]]:31: warning: use 'using' instead of 'typedef' [modernize-use-using]
384+
// CHECK-FIXES: const auto foo4 = [](int a){using d = int;};
385+
}

0 commit comments

Comments
 (0)