Skip to content

Commit 7c50187

Browse files
authored
[clang-tidy] Option to ignore anonymous namespaces in avoid-non-const-global-variables (llvm#93827)
Add an option to ignore warnings for cppcoreguidelines avoid-non-const-global-variables. Understandably, the core guidelines discourage non const global variables, even at the TU level (see isocpp/CppCoreGuidelines#2195). However, having a small TU with an interface that uses a non const variable from an anonymous namespace can be a valid choice. This adds an option that disables the warning just for anonymous namespaces, i.e. at the file level. The default is still to show a warning, just as before.
1 parent 9a4f57e commit 7c50187

File tree

5 files changed

+51
-10
lines changed

5 files changed

+51
-10
lines changed

clang-tools-extra/clang-tidy/cppcoreguidelines/AvoidNonConstGlobalVariablesCheck.cpp

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,21 +7,30 @@
77
//===----------------------------------------------------------------------===//
88

99
#include "AvoidNonConstGlobalVariablesCheck.h"
10-
#include "clang/AST/ASTContext.h"
1110
#include "clang/ASTMatchers/ASTMatchFinder.h"
1211
#include "clang/ASTMatchers/ASTMatchers.h"
1312

1413
using namespace clang::ast_matchers;
1514

1615
namespace clang::tidy::cppcoreguidelines {
1716

17+
AvoidNonConstGlobalVariablesCheck::AvoidNonConstGlobalVariablesCheck(
18+
StringRef Name, ClangTidyContext *Context)
19+
: ClangTidyCheck(Name, Context),
20+
AllowInternalLinkage(Options.get("AllowInternalLinkage", false)) {}
21+
1822
void AvoidNonConstGlobalVariablesCheck::registerMatchers(MatchFinder *Finder) {
23+
auto NamespaceMatcher = AllowInternalLinkage
24+
? namespaceDecl(unless(isAnonymous()))
25+
: namespaceDecl();
1926
auto GlobalContext =
2027
varDecl(hasGlobalStorage(),
21-
hasDeclContext(anyOf(namespaceDecl(), translationUnitDecl())));
28+
hasDeclContext(anyOf(NamespaceMatcher, translationUnitDecl())));
2229

2330
auto GlobalVariable = varDecl(
2431
GlobalContext,
32+
AllowInternalLinkage ? varDecl(unless(isStaticStorageClass()))
33+
: varDecl(),
2534
unless(anyOf(
2635
isConstexpr(), hasType(isConstQualified()),
2736
hasType(referenceType())))); // References can't be changed, only the
@@ -43,7 +52,6 @@ void AvoidNonConstGlobalVariablesCheck::registerMatchers(MatchFinder *Finder) {
4352

4453
void AvoidNonConstGlobalVariablesCheck::check(
4554
const MatchFinder::MatchResult &Result) {
46-
4755
if (const auto *Variable =
4856
Result.Nodes.getNodeAs<VarDecl>("non-const_variable")) {
4957
diag(Variable->getLocation(), "variable %0 is non-const and globally "
@@ -63,4 +71,9 @@ void AvoidNonConstGlobalVariablesCheck::check(
6371
}
6472
}
6573

74+
void AvoidNonConstGlobalVariablesCheck::storeOptions(
75+
ClangTidyOptions::OptionMap &Opts) {
76+
Options.store(Opts, "AllowInternalLinkage", AllowInternalLinkage);
77+
}
78+
6679
} // namespace clang::tidy::cppcoreguidelines

clang-tools-extra/clang-tidy/cppcoreguidelines/AvoidNonConstGlobalVariablesCheck.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,13 @@ namespace clang::tidy::cppcoreguidelines {
2020
/// http://clang.llvm.org/extra/clang-tidy/checks/cppcoreguidelines/avoid-non-const-global-variables.html
2121
class AvoidNonConstGlobalVariablesCheck : public ClangTidyCheck {
2222
public:
23-
AvoidNonConstGlobalVariablesCheck(StringRef Name, ClangTidyContext *Context)
24-
: ClangTidyCheck(Name, Context) {}
23+
AvoidNonConstGlobalVariablesCheck(StringRef Name, ClangTidyContext *Context);
2524
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
2625
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
26+
void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
27+
28+
private:
29+
const bool AllowInternalLinkage;
2730
};
2831

2932
} // namespace clang::tidy::cppcoreguidelines

clang-tools-extra/docs/ReleaseNotes.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,11 @@ Changes in existing checks
269269
<clang-tidy/checks/bugprone/use-after-move>` check to also handle
270270
calls to ``std::forward``.
271271

272+
- Improved :doc:`cppcoreguidelines-avoid-non-const-global-variables
273+
<clang-tidy/checks/cppcoreguidelines/avoid-non-const-global-variables>` check
274+
with a new option `AllowInternalLinkage` to disable the warning for variables
275+
with internal linkage.
276+
272277
- Improved :doc:`cppcoreguidelines-macro-usage
273278
<clang-tidy/checks/cppcoreguidelines/macro-usage>` check by ignoring macro with
274279
hash preprocessing token.

clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/avoid-non-const-global-variables.rst

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,3 +41,11 @@ The variables ``a``, ``c``, ``c_ptr1``, ``c_const_ptr`` and ``c_reference``
4141
will all generate warnings since they are either a non-const globally accessible
4242
variable, a pointer or a reference providing global access to non-const data
4343
or both.
44+
45+
Options
46+
-------
47+
48+
.. option:: AllowInternalLinkage
49+
50+
When set to `true`, static non-const variables and variables in anonymous
51+
namespaces will not generate a warning. The default value is `false`.

clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/avoid-non-const-global-variables.cpp

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
// RUN: %check_clang_tidy %s cppcoreguidelines-avoid-non-const-global-variables %t
1+
// RUN: %check_clang_tidy %s -check-suffixes=,DEFAULT cppcoreguidelines-avoid-non-const-global-variables %t
2+
// RUN: %check_clang_tidy %s -check-suffixes=,INTERNAL-LINKAGE cppcoreguidelines-avoid-non-const-global-variables %t -- \
3+
// RUN: -config="{CheckOptions: {cppcoreguidelines-avoid-non-const-global-variables.AllowInternalLinkage : 'true'}}"
24

35
int nonConstInt = 0;
46
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: variable 'nonConstInt' is non-const and globally accessible, consider making it const [cppcoreguidelines-avoid-non-const-global-variables]
@@ -38,9 +40,16 @@ int function() {
3840

3941
namespace {
4042
int nonConstAnonymousNamespaceInt = 0;
41-
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: variable 'nonConstAnonymousNamespaceInt' is non-const and globally accessible, consider making it const [cppcoreguidelines-avoid-non-const-global-variables]
43+
// CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:5: warning: variable 'nonConstAnonymousNamespaceInt' is non-const and globally accessible, consider making it const [cppcoreguidelines-avoid-non-const-global-variables]
44+
// CHECK-MESSAGES-INTERNAL-LINKAGE-NOT: :[[@LINE-2]]:5: warning: variable 'nonConstAnonymousNamespaceInt' is non-const and globally accessible, consider making it const [cppcoreguidelines-avoid-non-const-global-variables]
4245
} // namespace
4346

47+
static int nonConstStaticInt = 0;
48+
// CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:12: warning: variable 'nonConstStaticInt' is non-const and globally accessible, consider making it const [cppcoreguidelines-avoid-non-const-global-variables]
49+
// CHECK-MESSAGES-INTERNAL-LINKAGE-NOT: :[[@LINE-2]]:12: warning: variable 'nonConstStaticInt' is non-const and globally accessible, consider making it const [cppcoreguidelines-avoid-non-const-global-variables]
50+
51+
static const int constStaticInt = 0;
52+
4453
class DummyClass {
4554
public:
4655
int nonConstPublicMemberVariable = 0;
@@ -126,7 +135,8 @@ const DummyEnum constNamespaceEnumInstance = DummyEnum::first;
126135
namespace {
127136
DummyEnum nonConstAnonymousNamespaceEnumInstance = DummyEnum::first;
128137
}
129-
// CHECK-MESSAGES: :[[@LINE-2]]:11: warning: variable 'nonConstAnonymousNamespaceEnumInstance' is non-const and globally accessible, consider making it const [cppcoreguidelines-avoid-non-const-global-variables]
138+
// CHECK-MESSAGES-DEFAULT: :[[@LINE-2]]:11: warning: variable 'nonConstAnonymousNamespaceEnumInstance' is non-const and globally accessible, consider making it const [cppcoreguidelines-avoid-non-const-global-variables]
139+
// CHECK-MESSAGES-INTERNAL-LINKAGE-NOT: :[[@LINE-2]]:11: warning: variable 'nonConstAnonymousNamespaceEnumInstance' is non-const and globally accessible, consider making it const [cppcoreguidelines-avoid-non-const-global-variables]
130140

131141
// CHECKING FOR NON-CONST GLOBAL STRUCT ///////////////////////////////////////
132142
struct DummyStruct {
@@ -169,7 +179,8 @@ const DummyStruct constNamespaceDummyStructInstance;
169179
namespace {
170180
DummyStruct nonConstAnonymousNamespaceStructInstance;
171181
}
172-
// CHECK-MESSAGES: :[[@LINE-2]]:13: warning: variable 'nonConstAnonymousNamespaceStructInstance' is non-const and globally accessible, consider making it const [cppcoreguidelines-avoid-non-const-global-variables]
182+
// CHECK-MESSAGES-DEFAULT: :[[@LINE-2]]:13: warning: variable 'nonConstAnonymousNamespaceStructInstance' is non-const and globally accessible, consider making it const [cppcoreguidelines-avoid-non-const-global-variables]
183+
// CHECK-MESSAGES-INTERNAL-LINKAGE-NOT: :[[@LINE-2]]:11: warning: variable 'nonConstAnonymousNamespaceEnumInstance' is non-const and globally accessible, consider making it const [cppcoreguidelines-avoid-non-const-global-variables]
173184

174185
// CHECKING FOR NON-CONST GLOBAL UNION ////////////////////////////////////////
175186
union DummyUnion {
@@ -209,7 +220,8 @@ const DummyUnion constNamespaceDummyUnionInstance = {0x0};
209220
namespace {
210221
DummyUnion nonConstAnonymousNamespaceUnionInstance = {0x0};
211222
}
212-
// CHECK-MESSAGES: :[[@LINE-2]]:12: warning: variable 'nonConstAnonymousNamespaceUnionInstance' is non-const and globally accessible, consider making it const [cppcoreguidelines-avoid-non-const-global-variables]
223+
// CHECK-MESSAGES-DEFAULT: :[[@LINE-2]]:12: warning: variable 'nonConstAnonymousNamespaceUnionInstance' is non-const and globally accessible, consider making it const [cppcoreguidelines-avoid-non-const-global-variables]
224+
// CHECK-MESSAGES-INTERNAL-LINKAGE-NOT: :[[@LINE-3]]:12: warning: variable 'nonConstAnonymousNamespaceUnionInstance' is non-const and globally accessible, consider making it const [cppcoreguidelines-avoid-non-const-global-variables]
213225

214226
// CHECKING FOR NON-CONST GLOBAL FUNCTION POINTER /////////////////////////////
215227
int dummyFunction() {

0 commit comments

Comments
 (0)