Skip to content

Commit 7fb61f5

Browse files
authored
[clang-tidy] Make misc-use-internal-linkage not diagnose symbols in importable module units (llvm#188679)
Fixes llvm#187884.
1 parent cb1d614 commit 7fb61f5

File tree

5 files changed

+78
-10
lines changed

5 files changed

+78
-10
lines changed

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

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include "clang/ASTMatchers/ASTMatchFinder.h"
1313
#include "clang/ASTMatchers/ASTMatchers.h"
1414
#include "clang/ASTMatchers/ASTMatchersMacros.h"
15+
#include "clang/Basic/Module.h"
1516
#include "clang/Basic/SourceLocation.h"
1617
#include "clang/Basic/Specifiers.h"
1718
#include "clang/Lex/Token.h"
@@ -65,6 +66,15 @@ AST_MATCHER(Decl, isFirstDecl) { return Node.isFirstDecl(); }
6566

6667
AST_MATCHER(FunctionDecl, hasBody) { return Node.hasBody(); }
6768

69+
AST_MATCHER(Decl, isInImportableModuleUnit) {
70+
if (const Module *OwningModule = Node.getOwningModule())
71+
if (OwningModule->Kind == Module::ModuleInterfaceUnit ||
72+
OwningModule->Kind == Module::ModulePartitionInterface ||
73+
OwningModule->Kind == Module::ModulePartitionImplementation)
74+
return true;
75+
return false;
76+
}
77+
6878
AST_MATCHER_P(Decl, isAllRedeclsInMainFile, FileExtensionsSet,
6979
HeaderFileExtensions) {
7080
return llvm::all_of(Node.redecls(), [&](const Decl *D) {
@@ -136,13 +146,9 @@ void UseInternalLinkageCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
136146
void UseInternalLinkageCheck::registerMatchers(MatchFinder *Finder) {
137147
auto Common =
138148
allOf(isFirstDecl(), isAllRedeclsInMainFile(HeaderFileExtensions),
139-
unless(anyOf(
140-
// 1. internal linkage
141-
isInAnonymousNamespace(), hasAncestor(decl(anyOf(
142-
// 2. friend
143-
friendDecl(),
144-
// 3. module export decl
145-
exportDecl()))))));
149+
unless(anyOf(isInAnonymousNamespace(), isInImportableModuleUnit(),
150+
hasAncestor(decl(friendDecl())))));
151+
146152
if (AnalyzeFunctions)
147153
Finder->addMatcher(
148154
functionDecl(
@@ -154,6 +160,7 @@ void UseInternalLinkageCheck::registerMatchers(MatchFinder *Finder) {
154160
isAllocationOrDeallocationOverloadedFunction(), isMain())))
155161
.bind("fn"),
156162
this);
163+
157164
if (AnalyzeVariables)
158165
Finder->addMatcher(
159166
varDecl(Common, hasGlobalStorage(),
@@ -163,6 +170,7 @@ void UseInternalLinkageCheck::registerMatchers(MatchFinder *Finder) {
163170
hasThreadStorageDuration())))
164171
.bind("var"),
165172
this);
173+
166174
if (getLangOpts().CPlusPlus && AnalyzeTypes)
167175
Finder->addMatcher(
168176
tagDecl(Common, isDefinition(), hasNameForLinkage(),

clang-tools-extra/docs/ReleaseNotes.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -350,6 +350,12 @@ Changes in existing checks
350350
<clang-tidy/checks/misc/unused-using-decls>` to not diagnose ``using``
351351
declarations as unused if they're exported from a module.
352352

353+
- Improved :doc:`misc-use-internal-linkage
354+
<clang-tidy/checks/misc/use-internal-linkage>` to not suggest giving
355+
internal linkage to entities defined in C++ module interface units.
356+
Because it only sees one file at a time, the check can't be sure
357+
such entities aren't referenced in any other files of that module.
358+
353359
- Improved :doc:`modernize-pass-by-value
354360
<clang-tidy/checks/modernize/pass-by-value>` check by adding `IgnoreMacros`
355361
option to suppress warnings in macros.
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// RUN: rm -rf %t
2+
// RUN: mkdir -p %t
3+
// RUN: split-file %s %t
4+
// RUN: %clang -std=c++20 --precompile %t/foo.cppm -o %t/foo.pcm
5+
// RUN: %check_clang_tidy -std=c++20 %t/foo.cppm misc-use-internal-linkage %t/out
6+
// RUN: %check_clang_tidy -std=c++20 %t/foo.cpp misc-use-internal-linkage %t/out \
7+
// RUN: -- -- -fmodule-file=foo=%t/foo.pcm
8+
9+
//--- foo.cppm
10+
11+
export module foo;
12+
13+
export void exported_fn();
14+
export extern int exported_var;
15+
export struct ExportedStruct;
16+
17+
//--- foo.cpp
18+
module foo;
19+
20+
void exported_fn() {}
21+
int exported_var;
22+
struct ExportedStruct {};
23+
24+
void internal_fn() {}
25+
// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: function 'internal_fn' can be made static or moved into an anonymous namespace to enforce internal linkage
26+
// CHECK-FIXES: static void internal_fn() {}
27+
int internal_var;
28+
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: variable 'internal_var' can be made static or moved into an anonymous namespace to enforce internal linkage
29+
// CHECK-FIXES: static int internal_var;
30+
struct InternalStruct {};
31+
// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: struct 'InternalStruct' can be moved into an anonymous namespace to enforce internal linkage
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// RUN: %check_clang_tidy -std=c++20-or-later %s misc-use-internal-linkage %t
2+
3+
// Symbols in a partition are visible to any TU in the same module
4+
// that imports that partition, so we shouldn't warn on them.
5+
6+
module foo:bar;
7+
8+
void fn_in_partition() {}
9+
int var_in_partition;
10+
struct StructInPartition {};

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

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
// RUN: %check_clang_tidy -std=c++20-or-later %s misc-use-internal-linkage %t -- -- -I%S/Inputs/use-internal-linkage
2-
3-
module;
1+
// RUN: %check_clang_tidy -std=c++20-or-later %s misc-use-internal-linkage %t
42

53
export module test;
64

@@ -22,3 +20,18 @@ void namespace_export_fn() {}
2220
int namespace_export_var;
2321
struct NamespaceExportStruct {};
2422
} // namespace aa
23+
24+
void unexported_fn() {}
25+
int unexported_var;
26+
struct UnexportedStruct {};
27+
28+
module : private;
29+
30+
void fn_in_private_module_fragment() {}
31+
// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: function 'fn_in_private_module_fragment' can be made static or moved into an anonymous namespace to enforce internal linkage
32+
// CHECK-FIXES: static void fn_in_private_module_fragment() {}
33+
int var_in_private_module_fragment;
34+
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: variable 'var_in_private_module_fragment' can be made static or moved into an anonymous namespace to enforce internal linkage
35+
// CHECK-FIXES: static int var_in_private_module_fragment;
36+
struct StructInPrivateModuleFragment {};
37+
// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: struct 'StructInPrivateModuleFragment' can be moved into an anonymous namespace to enforce internal linkage

0 commit comments

Comments
 (0)