From 512767eb3fe9c34c655a480d034147c54f1d4f85 Mon Sep 17 00:00:00 2001 From: Kim Viggedal Date: Fri, 13 Mar 2020 10:05:13 -0400 Subject: [PATCH] Add CppCoreGuidelines I.2 "Avoid non-const global variables" check Cpp Core Guideline I.2, a.k.a "Avoid non-const global variables" For detailed documentation, see: https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#i2-avoid-non-const-global-variables --- .../AvoidNonConstGlobalVariablesCheck.cpp | 67 +++++ .../AvoidNonConstGlobalVariablesCheck.h | 35 +++ .../cppcoreguidelines/CMakeLists.txt | 1 + .../CppCoreGuidelinesTidyModule.cpp | 3 + clang-tools-extra/docs/ReleaseNotes.rst | 4 + ...lines-avoid-non-const-global-variables.rst | 38 +++ .../docs/clang-tidy/checks/list.rst | 2 + ...lines-avoid-non-const-global-variables.cpp | 237 ++++++++++++++++++ 8 files changed, 387 insertions(+) create mode 100644 clang-tools-extra/clang-tidy/cppcoreguidelines/AvoidNonConstGlobalVariablesCheck.cpp create mode 100644 clang-tools-extra/clang-tidy/cppcoreguidelines/AvoidNonConstGlobalVariablesCheck.h create mode 100644 clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines-avoid-non-const-global-variables.rst create mode 100644 clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines-avoid-non-const-global-variables.cpp diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/AvoidNonConstGlobalVariablesCheck.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/AvoidNonConstGlobalVariablesCheck.cpp new file mode 100644 index 000000000000..da94ac03ae19 --- /dev/null +++ b/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("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("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 diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/AvoidNonConstGlobalVariablesCheck.h b/clang-tools-extra/clang-tidy/cppcoreguidelines/AvoidNonConstGlobalVariablesCheck.h new file mode 100644 index 000000000000..4f5a2a025033 --- /dev/null +++ b/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 diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/CMakeLists.txt b/clang-tools-extra/clang-tidy/cppcoreguidelines/CMakeLists.txt index 13c15bc9d227..5c27538d3487 100644 --- a/clang-tools-extra/clang-tidy/cppcoreguidelines/CMakeLists.txt +++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/CMakeLists.txt @@ -2,6 +2,7 @@ set(LLVM_LINK_COMPONENTS support) add_clang_library(clangTidyCppCoreGuidelinesModule AvoidGotoCheck.cpp + AvoidNonConstGlobalVariablesCheck.cpp CppCoreGuidelinesTidyModule.cpp InitVariablesCheck.cpp InterfacesGlobalInitCheck.cpp diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp index 8886eb833795..4cb5022888d3 100644 --- a/clang-tools-extra/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp +++ b/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 @@ public: "cppcoreguidelines-avoid-goto"); CheckFactories.registerCheck( "cppcoreguidelines-avoid-magic-numbers"); + CheckFactories.registerCheck( + "cppcoreguidelines-avoid-non-const-global-variables"); CheckFactories.registerCheck( "cppcoreguidelines-explicit-virtual-functions"); CheckFactories.registerCheck( diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index 95afaf3b659a..3b9212f6723c 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -75,6 +75,10 @@ New module New checks ^^^^^^^^^^ +- New :doc:`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 ` check. 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 new file mode 100644 index 000000000000..4d1ffde62dbb --- /dev/null +++ b/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 ` . +As `R.6 of C++ Core Guidelines ` 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. diff --git a/clang-tools-extra/docs/clang-tidy/checks/list.rst b/clang-tools-extra/docs/clang-tidy/checks/list.rst index 36ad51feff32..5e943c5003f0 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/list.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/list.rst @@ -380,6 +380,7 @@ Clang-Tidy Checks `clang-analyzer-unix.cstring.NullArg `_, `Clang Static Analyzer `_, `cppcoreguidelines-avoid-c-arrays `_, `modernize-avoid-c-arrays `_, `cppcoreguidelines-avoid-magic-numbers `_, `readability-magic-numbers `_, + `cppcoreguidelines-avoid-non-const-global-variables `_, , , "" `cppcoreguidelines-c-copy-assignment-signature `_, `misc-unconventional-assign-operator `_, `cppcoreguidelines-explicit-virtual-functions `_, `modernize-use-override `_, "Yes" `cppcoreguidelines-non-private-member-variables-in-classes `_, `misc-non-private-member-variables-in-classes `_, @@ -413,3 +414,4 @@ Clang-Tidy Checks `hicpp-use-override `_, `modernize-use-override `_, "Yes" `hicpp-vararg `_, `cppcoreguidelines-pro-type-vararg `_, `llvm-qualified-auto `_, `readability-qualified-auto `_, "Yes" + 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 new file mode 100644 index 000000000000..1e554d6e59da --- /dev/null +++ b/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 +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; + } +}