Skip to content

Commit a1f2a65

Browse files
committed
[clang-tidy] fix false positive use-internal-linkage for func decl without body
If in one TU, function only have declaration without body, this function should be external linkage. Fixed #117488
1 parent 0c21ed4 commit a1f2a65

File tree

4 files changed

+43
-29
lines changed

4 files changed

+43
-29
lines changed

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,12 @@
88

99
#include "UseInternalLinkageCheck.h"
1010
#include "../utils/FileExtensionsUtils.h"
11-
#include "../utils/LexerUtils.h"
1211
#include "clang/AST/Decl.h"
1312
#include "clang/ASTMatchers/ASTMatchFinder.h"
1413
#include "clang/ASTMatchers/ASTMatchers.h"
1514
#include "clang/ASTMatchers/ASTMatchersMacros.h"
1615
#include "clang/Basic/SourceLocation.h"
1716
#include "clang/Basic/Specifiers.h"
18-
#include "clang/Basic/TokenKinds.h"
1917
#include "clang/Lex/Token.h"
2018
#include "llvm/ADT/STLExtras.h"
2119

@@ -47,6 +45,8 @@ namespace {
4745

4846
AST_MATCHER(Decl, isFirstDecl) { return Node.isFirstDecl(); }
4947

48+
AST_MATCHER(FunctionDecl, hasBody) { return Node.hasBody(); }
49+
5050
static bool isInMainFile(SourceLocation L, SourceManager &SM,
5151
const FileExtensionsSet &HeaderFileExtensions) {
5252
for (;;) {
@@ -103,7 +103,7 @@ void UseInternalLinkageCheck::registerMatchers(MatchFinder *Finder) {
103103
// 4. friend
104104
hasAncestor(friendDecl()))));
105105
Finder->addMatcher(
106-
functionDecl(Common, unless(cxxMethodDecl()), unless(isMain()))
106+
functionDecl(Common, hasBody(), unless(cxxMethodDecl()), unless(isMain()))
107107
.bind("fn"),
108108
this);
109109
Finder->addMatcher(varDecl(Common, hasGlobalStorage()).bind("var"), this);

clang-tools-extra/docs/ReleaseNotes.rst

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -229,8 +229,9 @@ Changes in existing checks
229229
false positive for C++23 deducing this.
230230

231231
- Improved :doc:`misc-use-internal-linkage
232-
<clang-tidy/checks/misc/use-internal-linkage>` check to insert ``static`` keyword
233-
before type qualifiers such as ``const`` and ``volatile``.
232+
<clang-tidy/checks/misc/use-internal-linkage>` check to insert ``static``
233+
keyword before type qualifiers such as ``const`` and ``volatile`` and fix
234+
false positives for function declaration without body.
234235

235236
- Improved :doc:`modernize-avoid-c-arrays
236237
<clang-tidy/checks/modernize/avoid-c-arrays>` check to suggest using

clang-tools-extra/docs/clang-tidy/checks/misc/use-internal-linkage.rst

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ Example:
1616

1717
int v1; // can be marked as static
1818

19-
void fn1(); // can be marked as static
19+
void fn1() {} // can be marked as static
2020

2121
namespace {
2222
// already in anonymous namespace
@@ -26,6 +26,9 @@ Example:
2626
// already declared as extern
2727
extern int v2;
2828

29+
void fn3(); // without function body in all declaration, maybe external linkage
30+
void fn3();
31+
2932
Options
3033
-------
3134

clang-tools-extra/test/clang-tidy/checkers/misc/use-internal-linkage-func.cpp

Lines changed: 33 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -13,59 +13,59 @@ void func_template() {}
1313
// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: function 'func_template'
1414
// CHECK-FIXES: static void func_template() {}
1515

16-
void func_cpp_inc();
16+
void func_cpp_inc() {}
1717
// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: function 'func_cpp_inc'
18-
// CHECK-FIXES: static void func_cpp_inc();
18+
// CHECK-FIXES: static void func_cpp_inc() {}
1919

20-
int* func_cpp_inc_return_ptr();
20+
int* func_cpp_inc_return_ptr() {}
2121
// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: function 'func_cpp_inc_return_ptr'
22-
// CHECK-FIXES: static int* func_cpp_inc_return_ptr();
22+
// CHECK-FIXES: static int* func_cpp_inc_return_ptr() {}
2323

24-
const int* func_cpp_inc_return_const_ptr();
24+
const int* func_cpp_inc_return_const_ptr() {}
2525
// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: function 'func_cpp_inc_return_const_ptr'
26-
// CHECK-FIXES: static const int* func_cpp_inc_return_const_ptr();
26+
// CHECK-FIXES: static const int* func_cpp_inc_return_const_ptr() {}
2727

28-
int const* func_cpp_inc_return_ptr_const();
28+
int const* func_cpp_inc_return_ptr_const() {}
2929
// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: function 'func_cpp_inc_return_ptr_const'
30-
// CHECK-FIXES: static int const* func_cpp_inc_return_ptr_const();
30+
// CHECK-FIXES: static int const* func_cpp_inc_return_ptr_const() {}
3131

32-
int * const func_cpp_inc_return_const();
32+
int * const func_cpp_inc_return_const() {}
3333
// CHECK-MESSAGES: :[[@LINE-1]]:13: warning: function 'func_cpp_inc_return_const'
34-
// CHECK-FIXES: static int * const func_cpp_inc_return_const();
34+
// CHECK-FIXES: static int * const func_cpp_inc_return_const() {}
3535

36-
volatile const int* func_cpp_inc_return_volatile_const_ptr();
36+
volatile const int* func_cpp_inc_return_volatile_const_ptr() {}
3737
// CHECK-MESSAGES: :[[@LINE-1]]:21: warning: function 'func_cpp_inc_return_volatile_const_ptr'
38-
// CHECK-FIXES: static volatile const int* func_cpp_inc_return_volatile_const_ptr();
38+
// CHECK-FIXES: static volatile const int* func_cpp_inc_return_volatile_const_ptr() {}
3939

40-
[[nodiscard]] void func_nodiscard();
40+
[[nodiscard]] void func_nodiscard() {}
4141
// CHECK-MESSAGES: :[[@LINE-1]]:20: warning: function 'func_nodiscard'
42-
// CHECK-FIXES: {{\[\[nodiscard\]\]}} static void func_nodiscard();
42+
// CHECK-FIXES: {{\[\[nodiscard\]\]}} static void func_nodiscard() {}
4343

4444
#define NDS [[nodiscard]]
4545
#define NNDS
4646

47-
NDS void func_nds();
47+
NDS void func_nds() {}
4848
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: function 'func_nds'
49-
// CHECK-FIXES: NDS static void func_nds();
49+
// CHECK-FIXES: NDS static void func_nds() {}
5050

51-
NNDS void func_nnds();
51+
NNDS void func_nnds() {}
5252
// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: function 'func_nnds'
53-
// CHECK-FIXES: NNDS static void func_nnds();
53+
// CHECK-FIXES: NNDS static void func_nnds() {}
5454

5555
#include "func_cpp.inc"
5656

57-
void func_h_inc();
57+
void func_h_inc() {}
5858

5959
struct S {
6060
void method();
6161
};
6262
void S::method() {}
6363

64-
void func_header();
65-
extern void func_extern();
66-
static void func_static();
64+
void func_header() {}
65+
extern void func_extern() {}
66+
static void func_static() {}
6767
namespace {
68-
void func_anonymous_ns();
68+
void func_anonymous_ns() {}
6969
} // namespace
7070

7171
int main(int argc, const char*argv[]) {}
@@ -75,3 +75,13 @@ void func_extern_c_1() {}
7575
}
7676

7777
extern "C" void func_extern_c_2() {}
78+
79+
namespace gh117488 {
80+
void func_with_body();
81+
// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: function 'func_with_body'
82+
// CHECK-FIXES: static void func_with_body();
83+
void func_with_body() {}
84+
85+
void func_without_body();
86+
void func_without_body();
87+
}

0 commit comments

Comments
 (0)