[clang-tools-extra] [clang-tidy] Option to ignore anonymous namespaces in avoid-non-const-global-variables (PR #93827)
https://github.com/pascalj created https://github.com/llvm/llvm-project/pull/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 https://github.com/isocpp/CppCoreGuidelines/issues/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. >From 89265bfcca48a879f281b9ef8eb6e0730794f985 Mon Sep 17 00:00:00 2001 From: Pascal Jungblut Date: Thu, 30 May 2024 14:28:50 +0200 Subject: [PATCH] Add option to ignore anonymous namespaces in avoid-non-const-global-variables --- .../AvoidNonConstGlobalVariablesCheck.cpp | 6 +- .../avoid-non-const-global-variables.rst | 22 +++ .../avoid-non-const-global-variables.cpp | 137 -- 3 files changed, 118 insertions(+), 47 deletions(-) diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/AvoidNonConstGlobalVariablesCheck.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/AvoidNonConstGlobalVariablesCheck.cpp index ee17b0e014288..b536016a3cccd 100644 --- a/clang-tools-extra/clang-tidy/cppcoreguidelines/AvoidNonConstGlobalVariablesCheck.cpp +++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/AvoidNonConstGlobalVariablesCheck.cpp @@ -7,7 +7,6 @@ //===--===// #include "AvoidNonConstGlobalVariablesCheck.h" -#include "clang/AST/ASTContext.h" #include "clang/ASTMatchers/ASTMatchFinder.h" #include "clang/ASTMatchers/ASTMatchers.h" @@ -16,9 +15,12 @@ using namespace clang::ast_matchers; namespace clang::tidy::cppcoreguidelines { void AvoidNonConstGlobalVariablesCheck::registerMatchers(MatchFinder *Finder) { + auto NamespaceMatcher = Options.get("AllowAnonymousNamespace", false) + ? namespaceDecl(unless(isAnonymous())) + : namespaceDecl(); auto GlobalContext = varDecl(hasGlobalStorage(), - hasDeclContext(anyOf(namespaceDecl(), translationUnitDecl(; + hasDeclContext(anyOf(NamespaceMatcher, translationUnitDecl(; auto GlobalVariable = varDecl( GlobalContext, diff --git a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/avoid-non-const-global-variables.rst b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/avoid-non-const-global-variables.rst index 21c20af6e8107..e2350872c6ece 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/avoid-non-const-global-variables.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/avoid-non-const-global-variables.rst @@ -41,3 +41,25 @@ The variables ``a``, ``c``, ``c_ptr1``, ``c_const_ptr`` and ``c_reference`` will all generate warnings since they are either a non-const globally accessible variable, a pointer or a reference providing global access to non-const data or both. + +Options +--- + +.. option:: AllowAnonymousNamespace + + When set to `true` (default is `false`), non-const variables in anonymous namespaces will not generate a warning. + +Example +^^^ + +.. code-block:: c++ + + namespace { + int counter = 0; + } + + int Increment() { +return ++counter; + } + +will not generate a warning for `counter` if :option:`AllowAnonymousNamespace` is set to `true`. diff --git a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/avoid-non-const-global-variables.cpp b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/avoid-non-const-global-variables.cpp index 3ca1029433d22..8956dd414356e 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/avoid-non-const-global-variables.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/avoid-non-const-global-variables.cpp @@ -1,21 +1,30 @@ -// RUN: %check_clang_tidy %s cppcoreguidelines-avoid-non-const-global-variables %t +// RUN: %check_clang_tidy %s -check-suffix=DEFAULT cppcoreguidelines-avoid-non-const-global-variables %t +// RUN: %check_clang_tidy %s -check-suffix=NAMESPACE cppcoreguidelines-avoid-non-const-global-variables %t -- \ +// RUN: -config="{CheckOptions: {cppcoreguidelines-avoid-non-const-global-variables.AllowAnonymousNamespace : 'true'}}" + int nonConstInt = 0; -// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: variable 'nonConstInt' is non-const and globally accessible, consider making it const [cppcoreguidelines-avoid-non-const-global-variables] +// CHECK-MESSAGES-DEFAULT: [[@LINE-1]]:5: warning: variable 'nonConstInt' is non-const and globally accessible, consider making it const [cppcoreguidelines-avoid-non-const-global-variables] +// CHECK-MESSAGES-NAMESPACE: [[@LINE-2]]:5: warning: variable 'nonConstInt' is non-const
[clang-tools-extra] [clang-tidy] Option to ignore anonymous namespaces in avoid-non-const-global-variables (PR #93827)
https://github.com/pascalj updated https://github.com/llvm/llvm-project/pull/93827 >From abe862b84fd6915edb281a21e49f1be2aac3a626 Mon Sep 17 00:00:00 2001 From: Pascal Jungblut Date: Thu, 30 May 2024 14:28:50 +0200 Subject: [PATCH] Add option to ignore anonymous namespaces in avoid-non-const-global-variables --- .../AvoidNonConstGlobalVariablesCheck.cpp | 19 +--- .../AvoidNonConstGlobalVariablesCheck.h | 7 -- clang-tools-extra/docs/ReleaseNotes.rst | 5 + .../avoid-non-const-global-variables.rst | 8 +++ .../avoid-non-const-global-variables.cpp | 22 ++- 5 files changed, 51 insertions(+), 10 deletions(-) diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/AvoidNonConstGlobalVariablesCheck.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/AvoidNonConstGlobalVariablesCheck.cpp index ee17b0e014288..a97ec9fe3fe3d 100644 --- a/clang-tools-extra/clang-tidy/cppcoreguidelines/AvoidNonConstGlobalVariablesCheck.cpp +++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/AvoidNonConstGlobalVariablesCheck.cpp @@ -7,7 +7,6 @@ //===--===// #include "AvoidNonConstGlobalVariablesCheck.h" -#include "clang/AST/ASTContext.h" #include "clang/ASTMatchers/ASTMatchFinder.h" #include "clang/ASTMatchers/ASTMatchers.h" @@ -15,13 +14,23 @@ using namespace clang::ast_matchers; namespace clang::tidy::cppcoreguidelines { +AvoidNonConstGlobalVariablesCheck::AvoidNonConstGlobalVariablesCheck( +StringRef Name, ClangTidyContext *Context) +: ClangTidyCheck(Name, Context), + AllowInternalLinkage(Options.get("AllowInternalLinkage", false)) {} + void AvoidNonConstGlobalVariablesCheck::registerMatchers(MatchFinder *Finder) { + auto NamespaceMatcher = AllowInternalLinkage + ? namespaceDecl(unless(isAnonymous())) + : namespaceDecl(); auto GlobalContext = varDecl(hasGlobalStorage(), - hasDeclContext(anyOf(namespaceDecl(), translationUnitDecl(; + hasDeclContext(anyOf(NamespaceMatcher, translationUnitDecl(; auto GlobalVariable = varDecl( GlobalContext, + AllowInternalLinkage ? varDecl(unless(isStaticStorageClass())) + : varDecl(), unless(anyOf( isConstexpr(), hasType(isConstQualified()), hasType(referenceType(); // References can't be changed, only the @@ -43,7 +52,6 @@ void AvoidNonConstGlobalVariablesCheck::registerMatchers(MatchFinder *Finder) { void AvoidNonConstGlobalVariablesCheck::check( const MatchFinder::MatchResult &Result) { - if (const auto *Variable = Result.Nodes.getNodeAs("non-const_variable")) { diag(Variable->getLocation(), "variable %0 is non-const and globally " @@ -63,4 +71,9 @@ void AvoidNonConstGlobalVariablesCheck::check( } } +void AvoidNonConstGlobalVariablesCheck::storeOptions( +ClangTidyOptions::OptionMap &Opts) { + Options.store(Opts, "AllowInternalLinkage", AllowInternalLinkage); +} + } // namespace clang::tidy::cppcoreguidelines diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/AvoidNonConstGlobalVariablesCheck.h b/clang-tools-extra/clang-tidy/cppcoreguidelines/AvoidNonConstGlobalVariablesCheck.h index e816ca9b47d41..a912763489db9 100644 --- a/clang-tools-extra/clang-tidy/cppcoreguidelines/AvoidNonConstGlobalVariablesCheck.h +++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/AvoidNonConstGlobalVariablesCheck.h @@ -20,10 +20,13 @@ namespace clang::tidy::cppcoreguidelines { /// http://clang.llvm.org/extra/clang-tidy/checks/cppcoreguidelines/avoid-non-const-global-variables.html class AvoidNonConstGlobalVariablesCheck : public ClangTidyCheck { public: - AvoidNonConstGlobalVariablesCheck(StringRef Name, ClangTidyContext *Context) - : ClangTidyCheck(Name, Context) {} + AvoidNonConstGlobalVariablesCheck(StringRef Name, ClangTidyContext *Context); void registerMatchers(ast_matchers::MatchFinder *Finder) override; void check(const ast_matchers::MatchFinder::MatchResult &Result) override; + void storeOptions(ClangTidyOptions::OptionMap &Opts) override; + +private: + const bool AllowInternalLinkage; }; } // namespace clang::tidy::cppcoreguidelines diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index 4f674d1a4d556..4db476718f775 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -250,6 +250,11 @@ Changes in existing checks ` check to also handle calls to ``std::forward``. +- Improved :doc:`cppcoreguidelines-avoid-non-const-global-variables + ` check + with a new option `AllowInternalLinkage` to disable the warning for variables + with internal linkage. + - Improved :doc:`cppcoreguidelines-missing-std-forward ` check by no longer giving false positives for deleted functions, by
[clang-tools-extra] [clang-tidy] Option to ignore anonymous namespaces in avoid-non-const-global-variables (PR #93827)
@@ -1,29 +1,39 @@ -// RUN: %check_clang_tidy %s cppcoreguidelines-avoid-non-const-global-variables %t +// RUN: %check_clang_tidy %s -check-suffix=DEFAULT cppcoreguidelines-avoid-non-const-global-variables %t +// RUN: %check_clang_tidy %s -check-suffix=NAMESPACE cppcoreguidelines-avoid-non-const-global-variables %t -- \ pascalj wrote: Thanks for this hint, it made the checks much easier. It now tests only for the cases where the configuration differs. https://github.com/llvm/llvm-project/pull/93827 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] [clang-tidy] Option to ignore anonymous namespaces in avoid-non-const-global-variables (PR #93827)
pascalj wrote: Thanks for your feedback! > * what about "static" non const global variables Good point, forgot about these. If both are allowed, it is more about the internal linkage than it is about the namespace. I renamed the option to `AllowInternalLinkage` and permit variables in anonymous namespaces and static global variables, since they're equivalent (AFAICT). > I'm fine for having an options that control behavior of the check. But please > note that there are other aspects of "I.2: Avoid non-const global variables" > rule that anonymous namespace or static does not solve. Like race-conditions > in multithread env. Or even to force developer not to use global objects to > pass data between functions. > > Even that I see many times that warnings from this check are being nolinted, > I still think that it's doing good job. I completely agree with both you and @carlosgalvezp: this is neither an option that should be enabled by default, nor should people prefer it over nolinting without some thought. However, I see not much harm in giving someone the choice to do so. In the end, all of clang-tidy's checks are optional to some degree. Having said that: if the maintainers prefer not to have this option, this is also fine with me. https://github.com/llvm/llvm-project/pull/93827 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits