vingeldal updated this revision to Diff 249980. vingeldal marked 6 inline comments as done. vingeldal added a comment.
Made example code in documentation legal C++ Changed implementation according to comments so that both the pointer matcher and the reference matcher now bind to the same id Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D70265/new/ https://reviews.llvm.org/D70265 Files: clang-tools-extra/clang-tidy/cppcoreguidelines/AvoidNonConstGlobalVariablesCheck.cpp clang-tools-extra/clang-tidy/cppcoreguidelines/AvoidNonConstGlobalVariablesCheck.h clang-tools-extra/clang-tidy/cppcoreguidelines/CMakeLists.txt clang-tools-extra/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp clang-tools-extra/docs/ReleaseNotes.rst clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines-avoid-non-const-global-variables.rst clang-tools-extra/docs/clang-tidy/checks/list.rst clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines-avoid-non-const-global-variables.cpp
Index: clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines-avoid-non-const-global-variables.cpp =================================================================== --- /dev/null +++ clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines-avoid-non-const-global-variables.cpp @@ -0,0 +1,237 @@ +// RUN: %check_clang_tidy %s cppcoreguidelines-avoid-non-const-global-variables %t + +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] + +int &nonConstIntReference = nonConstInt; +// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: variable 'nonConstIntReference' provides global access to a non-const object; consider making the referenced data 'const' [cppcoreguidelines-avoid-non-const-global-variables] + +int *pointerToNonConstInt = &nonConstInt; +// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: variable 'pointerToNonConstInt' is non-const and globally accessible, consider making it const [cppcoreguidelines-avoid-non-const-global-variables] +// CHECK-MESSAGES: :[[@LINE-2]]:6: warning: variable 'pointerToNonConstInt' provides global access to a non-const object; consider making the pointed-to data 'const' [cppcoreguidelines-avoid-non-const-global-variables] + +int *const constPointerToNonConstInt = &nonConstInt; +// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: variable 'constPointerToNonConstInt' provides global access to a non-const object; consider making the pointed-to data 'const' [cppcoreguidelines-avoid-non-const-global-variables] + +namespace namespace_name { +int nonConstNamespaceInt = 0; +// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: variable 'nonConstNamespaceInt' is non-const and globally accessible, consider making it const [cppcoreguidelines-avoid-non-const-global-variables] + +const int constNamespaceInt = 0; +} // namespace namespace_name + +const int constInt = 0; + +const int *pointerToConstInt = &constInt; +// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: variable 'pointerToConstInt' is non-const and globally accessible, consider making it const [cppcoreguidelines-avoid-non-const-global-variables] + +const int *const constPointerToConstInt = &constInt; + +const int &constReferenceToConstInt = constInt; + +constexpr int constexprInt = 0; + +int function() { + int nonConstReturnValue = 0; + return nonConstReturnValue; +} + +namespace { +int nonConstAnonymousNamespaceInt = 0; +// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: variable 'nonConstAnonymousNamespaceInt' is non-const and globally accessible, consider making it const [cppcoreguidelines-avoid-non-const-global-variables] +} // namespace + +class DummyClass { +public: + int nonConstPublicMemberVariable = 0; + const int constPublicMemberVariable = 0; + +private: + int nonConstPrivateMemberVariable = 0; + const int constPrivateMemberVariable = 0; +}; + +DummyClass nonConstClassInstance; +// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: variable 'nonConstClassInstance' is non-const and globally accessible, consider making it const [cppcoreguidelines-avoid-non-const-global-variables] + +DummyClass *pointerToNonConstDummyClass = &nonConstClassInstance; +// CHECK-MESSAGES: :[[@LINE-1]]:13: warning: variable 'pointerToNonConstDummyClass' is non-const and globally accessible, consider making it const [cppcoreguidelines-avoid-non-const-global-variables] +// CHECK-MESSAGES: :[[@LINE-2]]:13: warning: variable 'pointerToNonConstDummyClass' provides global access to a non-const object; consider making the pointed-to data 'const' [cppcoreguidelines-avoid-non-const-global-variables] + +DummyClass &referenceToNonConstDummyClass = nonConstClassInstance; +// CHECK-MESSAGES: :[[@LINE-1]]:13: warning: variable 'referenceToNonConstDummyClass' provides global access to a non-const object; consider making the referenced data 'const' [cppcoreguidelines-avoid-non-const-global-variables] + +int *nonConstPointerToMember = &nonConstClassInstance.nonConstPublicMemberVariable; +// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: variable 'nonConstPointerToMember' is non-const and globally accessible, consider making it const [cppcoreguidelines-avoid-non-const-global-variables] +// CHECK-MESSAGES: :[[@LINE-2]]:6: warning: variable 'nonConstPointerToMember' provides global access to a non-const object; consider making the pointed-to data 'const' [cppcoreguidelines-avoid-non-const-global-variables] +int *const constPointerToNonConstMember = &nonConstClassInstance.nonConstPublicMemberVariable; +// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: variable 'constPointerToNonConstMember' provides global access to a non-const object; consider making the pointed-to data 'const' [cppcoreguidelines-avoid-non-const-global-variables] + +const DummyClass constClassInstance; + +DummyClass *const constPointerToNonConstDummyClass = &nonConstClassInstance; +// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: variable 'constPointerToNonConstDummyClass' provides global access to a non-const object; consider making the pointed-to data 'const' [cppcoreguidelines-avoid-non-const-global-variables] + +const DummyClass *nonConstPointerToConstDummyClass = &constClassInstance; +// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: variable 'nonConstPointerToConstDummyClass' is non-const and globally accessible, consider making it const [cppcoreguidelines-avoid-non-const-global-variables] + +const DummyClass *const constPointerToConstDummyClass = &constClassInstance; + +const int *const constPointerToConstMember = &constClassInstance.nonConstPublicMemberVariable; + +const DummyClass &constReferenceToDummyClass = constClassInstance; + +namespace namespace_name { +DummyClass nonConstNamespaceClassInstance; +// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: variable 'nonConstNamespaceClassInstance' is non-const and globally accessible, consider making it const [cppcoreguidelines-avoid-non-const-global-variables] + +const DummyClass constDummyClassInstance; +} // namespace namespace_name + +// CHECKING FOR NON-CONST GLOBAL ENUM ///////////////////////////////////////// +enum DummyEnum { + first, + second +}; + +DummyEnum nonConstDummyEnumInstance = DummyEnum::first; +// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: variable 'nonConstDummyEnumInstance' is non-const and globally accessible, consider making it const [cppcoreguidelines-avoid-non-const-global-variables] + +DummyEnum *pointerToNonConstDummyEnum = &nonConstDummyEnumInstance; +// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: variable 'pointerToNonConstDummyEnum' is non-const and globally accessible, consider making it const [cppcoreguidelines-avoid-non-const-global-variables] +// CHECK-MESSAGES: :[[@LINE-2]]:12: warning: variable 'pointerToNonConstDummyEnum' provides global access to a non-const object; consider making the pointed-to data 'const' [cppcoreguidelines-avoid-non-const-global-variables] + +DummyEnum &referenceToNonConstDummyEnum = nonConstDummyEnumInstance; +// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: variable 'referenceToNonConstDummyEnum' provides global access to a non-const object; consider making the referenced data 'const' [cppcoreguidelines-avoid-non-const-global-variables] + +DummyEnum *const constPointerToNonConstDummyEnum = &nonConstDummyEnumInstance; +// CHECK-MESSAGES: :[[@LINE-1]]:18: warning: variable 'constPointerToNonConstDummyEnum' provides global access to a non-const object; consider making the pointed-to data 'const' [cppcoreguidelines-avoid-non-const-global-variables] + +const DummyEnum constDummyEnumInstance = DummyEnum::first; + +const DummyEnum *nonConstPointerToConstDummyEnum = &constDummyEnumInstance; +// CHECK-MESSAGES: :[[@LINE-1]]:18: warning: variable 'nonConstPointerToConstDummyEnum' is non-const and globally accessible, consider making it const [cppcoreguidelines-avoid-non-const-global-variables] + +const DummyEnum *const constPointerToConstDummyEnum = &constDummyEnumInstance; + +const DummyEnum &referenceToConstDummyEnum = constDummyEnumInstance; + +namespace namespace_name { +DummyEnum nonConstNamespaceEnumInstance = DummyEnum::first; +// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: variable 'nonConstNamespaceEnumInstance' is non-const and globally accessible, consider making it const [cppcoreguidelines-avoid-non-const-global-variables] + +const DummyEnum constNamespaceEnumInstance = DummyEnum::first; +} // namespace namespace_name + +namespace { +DummyEnum nonConstAnonymousNamespaceEnumInstance = DummyEnum::first; +} +// CHECK-MESSAGES: :[[@LINE-2]]:11: warning: variable 'nonConstAnonymousNamespaceEnumInstance' is non-const and globally accessible, consider making it const [cppcoreguidelines-avoid-non-const-global-variables] + +// CHECKING FOR NON-CONST GLOBAL STRUCT /////////////////////////////////////// +struct DummyStruct { +public: + int structIntElement = 0; + const int constStructIntElement = 0; + +private: + int privateStructIntElement = 0; +}; + +DummyStruct nonConstDummyStructInstance; +// CHECK-MESSAGES: :[[@LINE-1]]:13: warning: variable 'nonConstDummyStructInstance' is non-const and globally accessible, consider making it const [cppcoreguidelines-avoid-non-const-global-variables] + +DummyStruct *pointerToNonConstDummyStruct = &nonConstDummyStructInstance; +// CHECK-MESSAGES: :[[@LINE-1]]:14: warning: variable 'pointerToNonConstDummyStruct' is non-const and globally accessible, consider making it const [cppcoreguidelines-avoid-non-const-global-variables] +// CHECK-MESSAGES: :[[@LINE-2]]:14: warning: variable 'pointerToNonConstDummyStruct' provides global access to a non-const object; consider making the pointed-to data 'const' [cppcoreguidelines-avoid-non-const-global-variables] + +DummyStruct &referenceToNonConstDummyStruct = nonConstDummyStructInstance; +// CHECK-MESSAGES: :[[@LINE-1]]:14: warning: variable 'referenceToNonConstDummyStruct' provides global access to a non-const object; consider making the referenced data 'const' [cppcoreguidelines-avoid-non-const-global-variables] +DummyStruct *const constPointerToNonConstDummyStruct = &nonConstDummyStructInstance; +// CHECK-MESSAGES: :[[@LINE-1]]:20: warning: variable 'constPointerToNonConstDummyStruct' provides global access to a non-const object; consider making the pointed-to data 'const' [cppcoreguidelines-avoid-non-const-global-variables] + +const DummyStruct constDummyStructInstance; + +const DummyStruct *nonConstPointerToConstDummyStruct = &constDummyStructInstance; +// CHECK-MESSAGES: :[[@LINE-1]]:20: warning: variable 'nonConstPointerToConstDummyStruct' is non-const and globally accessible, consider making it const [cppcoreguidelines-avoid-non-const-global-variables] + +const DummyStruct *const constPointerToConstDummyStruct = &constDummyStructInstance; + +const DummyStruct &referenceToConstDummyStruct = constDummyStructInstance; + +namespace namespace_name { +DummyStruct nonConstNamespaceDummyStructInstance; +// CHECK-MESSAGES: :[[@LINE-1]]:13: warning: variable 'nonConstNamespaceDummyStructInstance' is non-const and globally accessible, consider making it const [cppcoreguidelines-avoid-non-const-global-variables] + +const DummyStruct constNamespaceDummyStructInstance; +} // namespace namespace_name + +namespace { +DummyStruct nonConstAnonymousNamespaceStructInstance; +} +// CHECK-MESSAGES: :[[@LINE-2]]:13: warning: variable 'nonConstAnonymousNamespaceStructInstance' is non-const and globally accessible, consider making it const [cppcoreguidelines-avoid-non-const-global-variables] + +// CHECKING FOR NON-CONST GLOBAL UNION //////////////////////////////////////// +union DummyUnion { + int unionInteger; + char unionChar; +}; + +DummyUnion nonConstUnionIntInstance = {0x0}; +// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: variable 'nonConstUnionIntInstance' is non-const and globally accessible, consider making it const [cppcoreguidelines-avoid-non-const-global-variables] + +DummyUnion *nonConstPointerToNonConstUnionInt = &nonConstUnionIntInstance; +// CHECK-MESSAGES: :[[@LINE-1]]:13: warning: variable 'nonConstPointerToNonConstUnionInt' is non-const and globally accessible, consider making it const [cppcoreguidelines-avoid-non-const-global-variables] +// CHECK-MESSAGES: :[[@LINE-2]]:13: warning: variable 'nonConstPointerToNonConstUnionInt' provides global access to a non-const object; consider making the pointed-to data 'const' [cppcoreguidelines-avoid-non-const-global-variables] + +DummyUnion *const constPointerToNonConstUnionInt = &nonConstUnionIntInstance; +// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: variable 'constPointerToNonConstUnionInt' provides global access to a non-const object; consider making the pointed-to data 'const' [cppcoreguidelines-avoid-non-const-global-variables] + +DummyUnion &referenceToNonConstUnionInt = nonConstUnionIntInstance; +// CHECK-MESSAGES: :[[@LINE-1]]:13: warning: variable 'referenceToNonConstUnionInt' provides global access to a non-const object; consider making the referenced data 'const' [cppcoreguidelines-avoid-non-const-global-variables] + +const DummyUnion constUnionIntInstance = {0x0}; + +const DummyUnion *nonConstPointerToConstUnionInt = &constUnionIntInstance; +// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: variable 'nonConstPointerToConstUnionInt' is non-const and globally accessible, consider making it const [cppcoreguidelines-avoid-non-const-global-variables] + +const DummyUnion *const constPointerToConstUnionInt = &constUnionIntInstance; + +const DummyUnion &referenceToConstUnionInt = constUnionIntInstance; + +namespace namespace_name { +DummyUnion nonConstNamespaceDummyUnionInstance; +// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: variable 'nonConstNamespaceDummyUnionInstance' is non-const and globally accessible, consider making it const [cppcoreguidelines-avoid-non-const-global-variables] + +const DummyUnion constNamespaceDummyUnionInstance = {0x0}; +} // namespace namespace_name + +namespace { +DummyUnion nonConstAnonymousNamespaceUnionInstance = {0x0}; +} +// CHECK-MESSAGES: :[[@LINE-2]]:12: warning: variable 'nonConstAnonymousNamespaceUnionInstance' is non-const and globally accessible, consider making it const [cppcoreguidelines-avoid-non-const-global-variables] + +// CHECKING FOR NON-CONST GLOBAL FUNCTION POINTER ///////////////////////////// +int dummyFunction() { + return 0; +} + +typedef int (*functionPointer)(); +functionPointer fp1 = &dummyFunction; +// CHECK-MESSAGES: :[[@LINE-1]]:17: warning: variable 'fp1' is non-const and globally accessible, consider making it const [cppcoreguidelines-avoid-non-const-global-variables] + +typedef int (*const functionConstPointer)(); +functionPointer fp2 = &dummyFunction; +// CHECK-MESSAGES: :[[@LINE-1]]:17: warning: variable 'fp2' is non-const and globally accessible, consider making it const [cppcoreguidelines-avoid-non-const-global-variables] + +// CHECKING FOR NON-CONST GLOBAL TEMPLATE VARIABLE //////////////////////////// +template <class T> +constexpr T templateVariable = T(0L); + +// CHECKING AGAINST FALSE POSITIVES INSIDE FUNCTION SCOPE ///////////////////// +int main() { + for (int i = 0; i < 3; ++i) { + int nonConstLoopVariable = 42; + nonConstInt = nonConstLoopVariable + i; + } +} Index: clang-tools-extra/docs/clang-tidy/checks/list.rst =================================================================== --- clang-tools-extra/docs/clang-tidy/checks/list.rst +++ clang-tools-extra/docs/clang-tidy/checks/list.rst @@ -374,6 +374,7 @@ `clang-analyzer-unix.cstring.NullArg <clang-analyzer-unix.cstring.NullArg.html>`_, `Clang Static Analyzer <https://clang.llvm.org/docs/analyzer/checkers.html>`_, `cppcoreguidelines-avoid-c-arrays <cppcoreguidelines-avoid-c-arrays.html>`_, `modernize-avoid-c-arrays <modernize-avoid-c-arrays.html>`_, `cppcoreguidelines-avoid-magic-numbers <cppcoreguidelines-avoid-magic-numbers.html>`_, `readability-magic-numbers <readability-magic-numbers.html>`_, + `cppcoreguidelines-avoid-non-const-global-variables <cppcoreguidelines-avoid-non-const-global-variables.html>`_, , , "" `cppcoreguidelines-c-copy-assignment-signature <cppcoreguidelines-c-copy-assignment-signature.html>`_, `misc-unconventional-assign-operator <misc-unconventional-assign-operator.html>`_, `cppcoreguidelines-explicit-virtual-functions <cppcoreguidelines-explicit-virtual-functions.html>`_, `modernize-use-override <modernize-use-override.html>`_, "Yes" `cppcoreguidelines-non-private-member-variables-in-classes <cppcoreguidelines-non-private-member-variables-in-classes.html>`_, `misc-non-private-member-variables-in-classes <misc-non-private-member-variables-in-classes.html>`_, @@ -407,3 +408,4 @@ `hicpp-use-override <hicpp-use-override.html>`_, `modernize-use-override <modernize-use-override.html>`_, "Yes" `hicpp-vararg <hicpp-vararg.html>`_, `cppcoreguidelines-pro-type-vararg <cppcoreguidelines-pro-type-vararg.html>`_, `llvm-qualified-auto <llvm-qualified-auto.html>`_, `readability-qualified-auto <readability-qualified-auto.html>`_, "Yes" + Index: clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines-avoid-non-const-global-variables.rst =================================================================== --- /dev/null +++ clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines-avoid-non-const-global-variables.rst @@ -0,0 +1,38 @@ +.. title:: clang-tidy - cppcoreguidelines-avoid-non-const-global-variables + +cppcoreguidelines-avoid-non-const-global-variables +================================================== + +Finds non-const global variables as described in `I.2 of C++ Core Guidelines <https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#Ri-global>` . +As `R.6 of C++ Core Guidelines <https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#Rr-global>` is a duplicate of rule I.2 it also covers that rule. + +.. code-block:: c++ + + char a; // Warns! + const char b = 0; + + namespace some_namespace + { + char c; // Warns! + const char d = 0; + } + + char * c_ptr1 = &some_namespace::c; // Warns! + char *const c_const_ptr = &some_namespace::c; // Warns! + char & c_reference = some_namespace::c; // Warns! + + class Foo // No Warnings inside Foo, only namespace scope is covered + { + public: + char e = 0; + const char f = 0; + protected: + char g = 0; + private: + char h = 0; + }; + +Variables: ``a``, ``c``, ``c_ptr1``, ``c_ptr2``, ``c_const_ptr`` and +``c_reference``, will all generate warnings since they are either: +a globally accessible variable and non-const, a pointer or reference providing +global access to non-const data or both. Index: clang-tools-extra/docs/ReleaseNotes.rst =================================================================== --- clang-tools-extra/docs/ReleaseNotes.rst +++ clang-tools-extra/docs/ReleaseNotes.rst @@ -69,6 +69,10 @@ New checks ^^^^^^^^^^ +- New :doc:`cppcoreguidelines-avoid-non-const-global-variables + <clang-tidy/checks/cppcoreguidelines-avoid-non-const-global-variables>` check. + Finds non-const global variables as described in check I.2 of C++ Core + Guidelines. - New :doc:`bugprone-misplaced-pointer-arithmetic-in-alloc <clang-tidy/checks/bugprone-misplaced-pointer-arithmetic-in-alloc>` check. Index: clang-tools-extra/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp =================================================================== --- clang-tools-extra/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp +++ clang-tools-extra/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp @@ -15,6 +15,7 @@ #include "../modernize/UseOverrideCheck.h" #include "../readability/MagicNumbersCheck.h" #include "AvoidGotoCheck.h" +#include "AvoidNonConstGlobalVariablesCheck.h" #include "InitVariablesCheck.h" #include "InterfacesGlobalInitCheck.h" #include "MacroUsageCheck.h" @@ -48,6 +49,8 @@ "cppcoreguidelines-avoid-goto"); CheckFactories.registerCheck<readability::MagicNumbersCheck>( "cppcoreguidelines-avoid-magic-numbers"); + CheckFactories.registerCheck<AvoidNonConstGlobalVariablesCheck>( + "cppcoreguidelines-avoid-non-const-global-variables"); CheckFactories.registerCheck<modernize::UseOverrideCheck>( "cppcoreguidelines-explicit-virtual-functions"); CheckFactories.registerCheck<InitVariablesCheck>( Index: clang-tools-extra/clang-tidy/cppcoreguidelines/CMakeLists.txt =================================================================== --- clang-tools-extra/clang-tidy/cppcoreguidelines/CMakeLists.txt +++ clang-tools-extra/clang-tidy/cppcoreguidelines/CMakeLists.txt @@ -2,6 +2,7 @@ add_clang_library(clangTidyCppCoreGuidelinesModule AvoidGotoCheck.cpp + AvoidNonConstGlobalVariablesCheck.cpp CppCoreGuidelinesTidyModule.cpp InitVariablesCheck.cpp InterfacesGlobalInitCheck.cpp Index: clang-tools-extra/clang-tidy/cppcoreguidelines/AvoidNonConstGlobalVariablesCheck.h =================================================================== --- /dev/null +++ clang-tools-extra/clang-tidy/cppcoreguidelines/AvoidNonConstGlobalVariablesCheck.h @@ -0,0 +1,35 @@ +//===--- AvoidNonConstGlobalVariablesCheck.h - clang-tidy -------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CPPCOREGUIDELINES_AVOIDNONCONSTGLOBALVARIABLESCHECK_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CPPCOREGUIDELINES_AVOIDNONCONSTGLOBALVARIABLESCHECK_H + +#include "../ClangTidyCheck.h" + +namespace clang { +namespace tidy { +namespace cppcoreguidelines { + +/// Non-const global variables hide dependencies and make the dependencies +/// subject to unpredictable changes. +/// +/// For the user-facing documentation see: +/// 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) {} + void registerMatchers(ast_matchers::MatchFinder *Finder) override; + void check(const ast_matchers::MatchFinder::MatchResult &Result) override; +}; + +} // namespace cppcoreguidelines +} // namespace tidy +} // namespace clang + +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CPPCOREGUIDELINES_AVOIDNONCONSTGLOBALVARIABLESCHECK_H Index: clang-tools-extra/clang-tidy/cppcoreguidelines/AvoidNonConstGlobalVariablesCheck.cpp =================================================================== --- /dev/null +++ clang-tools-extra/clang-tidy/cppcoreguidelines/AvoidNonConstGlobalVariablesCheck.cpp @@ -0,0 +1,67 @@ +//===--- AvoidNonConstGlobalVariablesCheck.cpp - clang-tidy ---------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "AvoidNonConstGlobalVariablesCheck.h" +#include "clang/AST/ASTContext.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" +#include "clang/ASTMatchers/ASTMatchers.h" + +using namespace clang::ast_matchers; + +namespace clang { +namespace tidy { +namespace cppcoreguidelines { + +void AvoidNonConstGlobalVariablesCheck::registerMatchers(MatchFinder *Finder) { + auto GlobalVariable = varDecl( + hasGlobalStorage(), + unless(anyOf( + isConstexpr(), hasType(isConstQualified()), + hasType(referenceType())))); // References can't be changed, only the + // data they reference can be changed. + + auto GlobalReferenceToNonConst = + varDecl(hasGlobalStorage(), hasType(referenceType()), + unless(hasType(references(qualType(isConstQualified()))))); + + auto GlobalPointerToNonConst = + varDecl(hasGlobalStorage(), + hasType(pointerType(pointee(unless(isConstQualified()))))); + + Finder->addMatcher(GlobalVariable.bind("non-const_variable"), this); + Finder->addMatcher(GlobalReferenceToNonConst.bind("indirection_to_non-const"), + this); + Finder->addMatcher(GlobalPointerToNonConst.bind("indirection_to_non-const"), + this); +} + +void AvoidNonConstGlobalVariablesCheck::check( + const MatchFinder::MatchResult &Result) { + + if (const auto *Variable = + Result.Nodes.getNodeAs<VarDecl>("non-const_variable")) { + diag(Variable->getLocation(), "variable %0 is non-const and globally " + "accessible, consider making it const") + << Variable; // FIXME: Add fix-it hint to Variable + // Don't return early, a non-const variable may also be a pointer or + // reference to non-const data. + } + + if (const auto *VD = + Result.Nodes.getNodeAs<VarDecl>("indirection_to_non-const")) { + diag(VD->getLocation(), + "variable %0 provides global access to a non-const object; consider " + "making the %select{referenced|pointed-to}1 data 'const'") + << VD + << VD->getType()->isPointerType(); // FIXME: Add fix-it hint to Variable + } +} + +} // namespace cppcoreguidelines +} // namespace tidy +} // namespace clang
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits