Skip to content

Commit ec7ddff

Browse files
committed
[clang-tidy] new check readability-mark-static
Add new check readability-mark-static to dectect variable and function can be marked as static.
1 parent a370d57 commit ec7ddff

File tree

11 files changed

+197
-0
lines changed

11 files changed

+197
-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+
MarkStaticCheck.cpp
2627
RedundantInlineSpecifierCheck.cpp
2728
InconsistentDeclarationParameterNameCheck.cpp
2829
IsolateDeclarationCheck.cpp
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
//===--- MarkStaticCheck.cpp - clang-tidy ---------------------------------===//
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+
#include "MarkStaticCheck.h"
10+
#include "clang/AST/Decl.h"
11+
#include "clang/ASTMatchers/ASTMatchFinder.h"
12+
#include "clang/ASTMatchers/ASTMatchers.h"
13+
#include "clang/ASTMatchers/ASTMatchersMacros.h"
14+
#include "clang/Basic/Specifiers.h"
15+
16+
using namespace clang::ast_matchers;
17+
18+
namespace clang::tidy::readability {
19+
20+
namespace {
21+
22+
AST_POLYMORPHIC_MATCHER(isFirstDecl,
23+
AST_POLYMORPHIC_SUPPORTED_TYPES(FunctionDecl,
24+
VarDecl)) {
25+
return Node.isFirstDecl();
26+
}
27+
28+
AST_MATCHER(Decl, isInMainFile) {
29+
return Finder->getASTContext().getSourceManager().isInMainFile(
30+
Node.getLocation());
31+
}
32+
33+
AST_POLYMORPHIC_MATCHER(isExternStorageClass,
34+
AST_POLYMORPHIC_SUPPORTED_TYPES(FunctionDecl,
35+
VarDecl)) {
36+
return Node.getStorageClass() == SC_Extern;
37+
}
38+
39+
} // namespace
40+
41+
void MarkStaticCheck::registerMatchers(MatchFinder *Finder) {
42+
auto Common =
43+
allOf(isFirstDecl(), isInMainFile(),
44+
unless(anyOf(isStaticStorageClass(), isExternStorageClass(),
45+
isInAnonymousNamespace())));
46+
Finder->addMatcher(
47+
functionDecl(Common, unless(cxxMethodDecl()), unless(isMain()))
48+
.bind("fn"),
49+
this);
50+
Finder->addMatcher(varDecl(Common, hasGlobalStorage()).bind("var"), this);
51+
}
52+
53+
void MarkStaticCheck::check(const MatchFinder::MatchResult &Result) {
54+
if (const auto *FD = Result.Nodes.getNodeAs<FunctionDecl>("fn")) {
55+
diag(FD->getLocation(), "function %0 can be static") << FD;
56+
return;
57+
}
58+
if (const auto *VD = Result.Nodes.getNodeAs<VarDecl>("var")) {
59+
diag(VD->getLocation(), "variable %0 can be static") << VD;
60+
return;
61+
}
62+
llvm_unreachable("");
63+
}
64+
65+
} // namespace clang::tidy::readability
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
//===--- MarkStaticCheck.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_MARKSTATICCHECK_H
10+
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_MARKSTATICCHECK_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/mark-static.html
20+
class MarkStaticCheck : public ClangTidyCheck {
21+
public:
22+
MarkStaticCheck(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_MARKSTATICCHECK_H

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

+2
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#include "IsolateDeclarationCheck.h"
3333
#include "MagicNumbersCheck.h"
3434
#include "MakeMemberFunctionConstCheck.h"
35+
#include "MarkStaticCheck.h"
3536
#include "MathMissingParenthesesCheck.h"
3637
#include "MisleadingIndentationCheck.h"
3738
#include "MisplacedArrayIndexCheck.h"
@@ -106,6 +107,7 @@ class ReadabilityModule : public ClangTidyModule {
106107
"readability-identifier-naming");
107108
CheckFactories.registerCheck<ImplicitBoolConversionCheck>(
108109
"readability-implicit-bool-conversion");
110+
CheckFactories.registerCheck<MarkStaticCheck>("readability-mark-static");
109111
CheckFactories.registerCheck<MathMissingParenthesesCheck>(
110112
"readability-math-missing-parentheses");
111113
CheckFactories.registerCheck<RedundantInlineSpecifierCheck>(

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-mark-static
155+
<clang-tidy/checks/readability/mark-static>` 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
@@ -364,6 +364,7 @@ Clang-Tidy Checks
364364
:doc:`readability-isolate-declaration <readability/isolate-declaration>`, "Yes"
365365
:doc:`readability-magic-numbers <readability/magic-numbers>`,
366366
:doc:`readability-make-member-function-const <readability/make-member-function-const>`, "Yes"
367+
:doc:`readability-mark-static <readability/mark-static>`,
367368
:doc:`readability-math-missing-parentheses <readability/math-missing-parentheses>`, "Yes"
368369
:doc:`readability-misleading-indentation <readability/misleading-indentation>`,
369370
:doc:`readability-misplaced-array-index <readability/misplaced-array-index>`, "Yes"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
.. title:: clang-tidy - readability-mark-static
2+
3+
readability-mark-static
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,24 @@
1+
// RUN: %check_clang_tidy %s readability-mark-static %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[]) {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// RUN: %check_clang_tidy %s readability-mark-static %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;

0 commit comments

Comments
 (0)