Skip to content

Commit 24cbbd0

Browse files
committed
reformat
1 parent a370d57 commit 24cbbd0

File tree

11 files changed

+227
-0
lines changed

11 files changed

+227
-0
lines changed

clang-tools-extra/clang-tidy/readability/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ add_clang_library(clangTidyReadabilityModule
2323
IdentifierLengthCheck.cpp
2424
IdentifierNamingCheck.cpp
2525
ImplicitBoolConversionCheck.cpp
26+
UnnecessaryExternalLinkageCheck.cpp
2627
RedundantInlineSpecifierCheck.cpp
2728
InconsistentDeclarationParameterNameCheck.cpp
2829
IsolateDeclarationCheck.cpp

clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp

+3
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@
5858
#include "StringCompareCheck.h"
5959
#include "SuspiciousCallArgumentCheck.h"
6060
#include "UniqueptrDeleteReleaseCheck.h"
61+
#include "UnnecessaryExternalLinkageCheck.h"
6162
#include "UppercaseLiteralSuffixCheck.h"
6263
#include "UseAnyOfAllOfCheck.h"
6364
#include "UseStdMinMaxCheck.h"
@@ -106,6 +107,8 @@ class ReadabilityModule : public ClangTidyModule {
106107
"readability-identifier-naming");
107108
CheckFactories.registerCheck<ImplicitBoolConversionCheck>(
108109
"readability-implicit-bool-conversion");
110+
CheckFactories.registerCheck<UnnecessaryExternalLinkageCheck>(
111+
"readability-unnecessary-external-linkage");
109112
CheckFactories.registerCheck<MathMissingParenthesesCheck>(
110113
"readability-math-missing-parentheses");
111114
CheckFactories.registerCheck<RedundantInlineSpecifierCheck>(
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
//===--- UnnecessaryExternalLinkageCheck.cpp - clang-tidy
2+
//---------------------------------===//
3+
//
4+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5+
// See https://llvm.org/LICENSE.txt for license information.
6+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7+
//
8+
//===----------------------------------------------------------------------===//
9+
10+
#include "UnnecessaryExternalLinkageCheck.h"
11+
#include "clang/AST/Decl.h"
12+
#include "clang/ASTMatchers/ASTMatchFinder.h"
13+
#include "clang/ASTMatchers/ASTMatchers.h"
14+
#include "clang/ASTMatchers/ASTMatchersMacros.h"
15+
#include "clang/Basic/Specifiers.h"
16+
17+
using namespace clang::ast_matchers;
18+
19+
namespace clang::tidy::readability {
20+
21+
namespace {
22+
23+
AST_POLYMORPHIC_MATCHER(isFirstDecl,
24+
AST_POLYMORPHIC_SUPPORTED_TYPES(FunctionDecl,
25+
VarDecl)) {
26+
return Node.isFirstDecl();
27+
}
28+
29+
AST_MATCHER(Decl, isInMainFile) {
30+
for (const Decl *D : Node.redecls())
31+
if (!Finder->getASTContext().getSourceManager().isInMainFile(
32+
D->getLocation()))
33+
return false;
34+
return true;
35+
}
36+
37+
AST_POLYMORPHIC_MATCHER(isExternStorageClass,
38+
AST_POLYMORPHIC_SUPPORTED_TYPES(FunctionDecl,
39+
VarDecl)) {
40+
return Node.getStorageClass() == SC_Extern;
41+
}
42+
43+
} // namespace
44+
45+
void UnnecessaryExternalLinkageCheck::registerMatchers(MatchFinder *Finder) {
46+
auto Common = allOf(isFirstDecl(), isInMainFile(),
47+
unless(anyOf(
48+
// 1. internal linkage
49+
isStaticStorageClass(), isInAnonymousNamespace(),
50+
// 2. explicit external linkage
51+
isExternStorageClass(), isExternC(),
52+
// 3. template
53+
isExplicitTemplateSpecialization(),
54+
clang::ast_matchers::isTemplateInstantiation(),
55+
// 4. friend
56+
hasAncestor(friendDecl()))));
57+
Finder->addMatcher(
58+
functionDecl(Common, unless(cxxMethodDecl()), unless(isMain()))
59+
.bind("fn"),
60+
this);
61+
Finder->addMatcher(varDecl(Common, hasGlobalStorage()).bind("var"), this);
62+
}
63+
64+
static constexpr StringRef Message =
65+
"%0 %1 can be internal linkage, "
66+
"marking as static or using anonymous namespace can avoid external "
67+
"linkage.";
68+
69+
void UnnecessaryExternalLinkageCheck::check(
70+
const MatchFinder::MatchResult &Result) {
71+
if (const auto *FD = Result.Nodes.getNodeAs<FunctionDecl>("fn")) {
72+
diag(FD->getLocation(), Message) << "function" << FD;
73+
return;
74+
}
75+
if (const auto *VD = Result.Nodes.getNodeAs<VarDecl>("var")) {
76+
diag(VD->getLocation(), Message) << "variable" << VD;
77+
return;
78+
}
79+
llvm_unreachable("");
80+
}
81+
82+
} // namespace clang::tidy::readability
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
//===--- UnnecessaryExternalLinkageCheck.h - clang-tidy ---------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_UNNECESSARYEXTERNALLINKAGECHECK_H
10+
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_UNNECESSARYEXTERNALLINKAGECHECK_H
11+
12+
#include "../ClangTidyCheck.h"
13+
14+
namespace clang::tidy::readability {
15+
16+
/// Detects variable and function can be marked as static.
17+
///
18+
/// For the user-facing documentation see:
19+
/// http://clang.llvm.org/extra/clang-tidy/checks/readability/unnecessary-external-linkage.html
20+
class UnnecessaryExternalLinkageCheck : public ClangTidyCheck {
21+
public:
22+
UnnecessaryExternalLinkageCheck(StringRef Name, ClangTidyContext *Context)
23+
: ClangTidyCheck(Name, Context) {}
24+
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
25+
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
26+
std::optional<TraversalKind> getCheckTraversalKind() const override {
27+
return TK_IgnoreUnlessSpelledInSource;
28+
}
29+
};
30+
31+
} // namespace clang::tidy::readability
32+
33+
#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_UNNECESSARYEXTERNALLINKAGECHECK_H

clang-tools-extra/docs/ReleaseNotes.rst

+5
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,11 @@ New checks
151151
Enforces consistent style for enumerators' initialization, covering three
152152
styles: none, first only, or all initialized explicitly.
153153

154+
- New :doc:`readability-unnecessary-external-linkage
155+
<clang-tidy/checks/readability/unnecessary-external-linkage>` check.
156+
157+
Detects variable and function can be marked as static.
158+
154159
- New :doc:`readability-math-missing-parentheses
155160
<clang-tidy/checks/readability/math-missing-parentheses>` check.
156161

clang-tools-extra/docs/clang-tidy/checks/list.rst

+1
Original file line numberDiff line numberDiff line change
@@ -390,6 +390,7 @@ Clang-Tidy Checks
390390
:doc:`readability-string-compare <readability/string-compare>`, "Yes"
391391
:doc:`readability-suspicious-call-argument <readability/suspicious-call-argument>`,
392392
:doc:`readability-uniqueptr-delete-release <readability/uniqueptr-delete-release>`, "Yes"
393+
:doc:`readability-unnecessary-external-linkage <readability/unnecessary-external-linkage>`,
393394
:doc:`readability-uppercase-literal-suffix <readability/uppercase-literal-suffix>`, "Yes"
394395
:doc:`readability-use-anyofallof <readability/use-anyofallof>`,
395396
:doc:`readability-use-std-min-max <readability/use-std-min-max>`, "Yes"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
.. title:: clang-tidy - readability-unnecessary-external-linkage
2+
3+
readability-unnecessary-external-linkage
4+
========================================
5+
6+
Detects variable and function can be marked as static.
7+
8+
Static functions and variables are scoped to a single file. Marking functions
9+
and variables as static helps to better remove dead code. In addition, it gives
10+
the compiler more information and can help compiler make more aggressive
11+
optimizations.
12+
13+
Example:
14+
15+
.. code-block:: c++
16+
int v1; // can be marked as static
17+
18+
void fn1(); // can be marked as static
19+
20+
namespace {
21+
// already in anonymous namespace
22+
int v2;
23+
void fn2();
24+
}
25+
// already declared as extern
26+
extern int v2;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#pragma once
2+
3+
void func_header();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#pragma once
2+
3+
extern int gloabl_header;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// RUN: %check_clang_tidy %s readability-unnecessary-external-linkage %t -- -- -I%S/Inputs/mark-static-var
2+
3+
#include "func.h"
4+
5+
void func() {}
6+
// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: function 'func'
7+
8+
template<class T>
9+
void func_template() {}
10+
// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: function 'func_template'
11+
12+
struct S {
13+
void method();
14+
};
15+
void S::method() {}
16+
17+
void func_header();
18+
extern void func_extern();
19+
static void func_static();
20+
namespace {
21+
void func_anonymous_ns();
22+
} // namespace
23+
24+
int main(int argc, const char*argv[]) {}
25+
26+
extern "C" {
27+
void func_extern_c_1() {}
28+
}
29+
30+
extern "C" void func_extern_c_2() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
// RUN: %check_clang_tidy %s readability-unnecessary-external-linkage %t -- -- -I%S/Inputs/mark-static-var
2+
3+
#include "var.h"
4+
5+
int global;
6+
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: variable 'global'
7+
8+
template<class T>
9+
T global_template;
10+
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: variable 'global_template'
11+
12+
int gloabl_header;
13+
14+
extern int global_extern;
15+
16+
static int global_static;
17+
18+
namespace {
19+
static int global_anonymous_ns;
20+
namespace NS {
21+
static int global_anonymous_ns;
22+
}
23+
}
24+
25+
static void f(int para) {
26+
int local;
27+
static int local_static;
28+
}
29+
30+
struct S {
31+
int m1;
32+
static int m2;
33+
};
34+
int S::m2;
35+
36+
extern "C" {
37+
int global_in_extern_c_1;
38+
}
39+
40+
extern "C" int global_in_extern_c_2;

0 commit comments

Comments
 (0)