diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/AvoidNonConstGlobalVariablesCheck.h b/clang-tools-extra/clang-tidy/cppcoreguidelines/AvoidNonConstGlobalVariablesCheck.h new file mode 100644 --- /dev/null +++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/AvoidNonConstGlobalVariablesCheck.h @@ -0,0 +1,39 @@ +//===--- 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), + IgnoreDataMembers(Options.get("IgnoreDataMembers", 0)) {} + void storeOptions(ClangTidyOptions::OptionMap &Opts) override; + void registerMatchers(ast_matchers::MatchFinder *Finder) override; + void check(const ast_matchers::MatchFinder::MatchResult &Result) override; + + const bool IgnoreDataMembers; +}; + +} // 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/AvoidNonConstGlobalVariablesCheck.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/AvoidNonConstGlobalVariablesCheck.cpp new file mode 100644 --- /dev/null +++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/AvoidNonConstGlobalVariablesCheck.cpp @@ -0,0 +1,135 @@ +//===--- 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::storeOptions( + ClangTidyOptions::OptionMap &Opts) { + Options.store(Opts, "IgnoreDataMembers", IgnoreDataMembers); +} + +void AvoidNonConstGlobalVariablesCheck::registerMatchers(MatchFinder *Finder) { + auto GlobalVariable = varDecl( + hasGlobalStorage(), + unless(anyOf( + isConstexpr(), hasDeclContext(namespaceDecl(isAnonymous())), + hasType(isConstQualified()), + hasType(referenceType()), // References can't be changed, only the + // data they reference can be changed. + isPrivate(), // Static member variables are VarDecl, not FieldDecl, so + // VarDecl can be private or protected. + isProtected()))); + + auto GlobalReferenceToNonConst = + varDecl(hasGlobalStorage(), hasType(referenceType()), + unless(anyOf(hasType(references(qualType(isConstQualified()))), + hasDeclContext(namespaceDecl(isAnonymous()))))); + + auto GlobalPointerToNonConst = + varDecl(hasGlobalStorage(), + hasType(pointerType(pointee(unless(isConstQualified())))), + unless(hasDeclContext(namespaceDecl(isAnonymous())))); + + auto GlobalMemberVariable = fieldDecl( + unless(anyOf(isPrivate(), isProtected(), hasType(isConstQualified()), + hasAncestor(namespaceDecl(isAnonymous()))))); + + auto GlobalMemberReferenceToNonConst = + fieldDecl(hasType(referenceType()), + unless(anyOf(hasType(references(qualType(isConstQualified()))), + isPrivate(), isProtected(), + hasAncestor(namespaceDecl(isAnonymous()))))); + + auto GlobalMemberPointerToNonConst = + fieldDecl(hasType(pointerType(pointee(unless(isConstQualified())))), + unless(anyOf(isPrivate(), isProtected(), + hasAncestor(namespaceDecl(isAnonymous()))))); + + Finder->addMatcher(GlobalVariable.bind("non-const_variable"), this); + Finder->addMatcher(GlobalReferenceToNonConst.bind("reference_to_non-const"), + this); + Finder->addMatcher(GlobalPointerToNonConst.bind("pointer_to_non-const"), + this); + Finder->addMatcher( + GlobalMemberVariable.bind("non-const_public_member_variable"), this); + Finder->addMatcher( + GlobalMemberReferenceToNonConst.bind("member_reference_to_non-const"), + this); + Finder->addMatcher( + GlobalMemberPointerToNonConst.bind("member_pointer_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 + } + + if (const auto *Reference = + Result.Nodes.getNodeAs("reference_to_non-const")) { + diag(Reference->getLocation(), + "variable %0 provides global access to non-const type, consider " + "making the referenced data const") + << Reference; // FIXME: Add fix-it hint to Reference + return; + } + + if (const auto *Pointer = + Result.Nodes.getNodeAs("pointer_to_non-const")) { + diag(Pointer->getLocation(), + "variable %0 provides global access to non-const type, consider " + "making the pointed-to data const") + << Pointer; // FIXME: Add fix-it hint to Pointer + return; + } + + if (!IgnoreDataMembers) { + if (const auto *MemberVariable = Result.Nodes.getNodeAs( + "non-const_public_member_variable")) { + diag(MemberVariable->getLocation(), + "member variable %0 is globally accessible and non-const, consider " + "making it const") + << MemberVariable; // FIXME: Add fix-it hint to MemberVariable + } + + if (const auto *MemberReference = Result.Nodes.getNodeAs( + "member_reference_to_non-const")) { + diag(MemberReference->getLocation(), + "member variable %0 provides global access to non-const type, " + "consider making the referenced data const") + << MemberReference; // FIXME: Add fix-it hint to MemberReference + return; + } + + if (const auto *MemberPointer = + Result.Nodes.getNodeAs("member_pointer_to_non-const")) { + diag(MemberPointer->getLocation(), + "member variable %0 provides global access to non-const type, " + "consider making the pointed-to data const") + << MemberPointer; // FIXME: Add fix-it hint to MemberPointer + return; + } + } +} + +} // namespace cppcoreguidelines +} // namespace tidy +} // namespace clang diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/CMakeLists.txt b/clang-tools-extra/clang-tidy/cppcoreguidelines/CMakeLists.txt --- a/clang-tools-extra/clang-tidy/cppcoreguidelines/CMakeLists.txt +++ b/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 diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp --- 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 @@ "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 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -94,12 +94,18 @@ Without the null terminator it can result in undefined behaviour when the string is read. + - New :doc:`cert-mem57-cpp ` check. Checks if an object of type with extended alignment is allocated by using the default ``operator new``. +- 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 alias :doc:`cert-pos44-c ` to :doc:`bugprone-bad-signal-to-kill-thread 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 --- /dev/null +++ b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines-avoid-non-const-global-variables.rst @@ -0,0 +1,52 @@ +.. 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 ` . +By default this check considers public member variables to be global variables, +there is an option, ``IgnoreDataMembers``, to turn of checks of member variables. + +.. code-block:: c++ + + char a = 0; // Warns! + const char b = 0; + + namespace some_namespace + { + char c = 0; // Warns! + const char d = 0; + } + + namespace + { + char e = 0; + } + + char * e_ptr1 = &e; // Warns! + char *const e_const_ptr = &e; // Warns! + char & e_reference = e; // Warns! + + class Foo + { + public: + char f = 0; // Warns! + const char g = 0; + const char * e_ptr2 = &e; // Warns! + protected: + char h = 0; + private: + char i = 0; + } + +Variables: ``a``, ``c``, ``e_ptr1``, ``e_ptr2``, ``e_const_ptr``, +``e_reference`` and ``f``, 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. + +Options +------- + +.. option:: IgnoreDataMembers (default = 0) + + The check will not warn about any member variables if this option is set to 1. diff --git a/clang-tools-extra/docs/clang-tidy/checks/list.rst b/clang-tools-extra/docs/clang-tidy/checks/list.rst --- a/clang-tools-extra/docs/clang-tidy/checks/list.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/list.rst @@ -370,6 +370,7 @@ `clang-analyzer-unix.cstring.NullArg `_, `Clang Static Analyzer `_, , "" `cppcoreguidelines-avoid-c-arrays `_, `modernize-avoid-c-arrays `_, , "low" `cppcoreguidelines-avoid-magic-numbers `_, `readability-magic-numbers `_, , "style" + `cppcoreguidelines-avoid-non-const-global-variables `_, , , "" `cppcoreguidelines-c-copy-assignment-signature `_, `misc-unconventional-assign-operator `_, , "medium" `cppcoreguidelines-explicit-virtual-functions `_, `modernize-use-override `_, , "low" `cppcoreguidelines-non-private-member-variables-in-classes `_, `misc-non-private-member-variables-in-classes `_, , "low" diff --git a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines-avoid-non-const-global-variables-IgnoreDataMembers.cpp b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines-avoid-non-const-global-variables-IgnoreDataMembers.cpp new file mode 100644 --- /dev/null +++ b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines-avoid-non-const-global-variables-IgnoreDataMembers.cpp @@ -0,0 +1,24 @@ +// RUN: %check_clang_tidy %s cppcoreguidelines-avoid-non-const-global-variables %t \ +// RUN: -config='{CheckOptions: \ +// RUN: [{key: "cppcoreguidelines-avoid-non-const-global-variables.IgnoreDataMembers", \ +// RUN: value: 1}]}' -- + +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] + +const int constInt = 0; + +class DummyClass { +public: + int nonConstMemberVariable = 0; + const int constMemberVariable = 0; + int *const constMemberPointerToNonConst = &nonConstInt; + int *memberPointerToNonConst = &nonConstInt; + const int *const constMemberPointerToConst = &constInt; + int &nonConstMemberReferenceToNonConst = nonConstInt; + +private: + int *privatePointerToNonConst = &nonConstInt; + int &privateReferenceToNonConst = nonConstInt; + int nonConstPrivateMemberVariable = 0; +}; 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 --- /dev/null +++ b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines-avoid-non-const-global-variables.cpp @@ -0,0 +1,268 @@ +// 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 non-const type, 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 non-const type, 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 non-const type, 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; +} + +class DummyClass { +public: + int nonConstMemberVariable = 0; + // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: member variable 'nonConstMemberVariable' is globally accessible and non-const, consider making it const [cppcoreguidelines-avoid-non-const-global-variables] + const int constMemberVariable = 0; + int *const constMemberPointerToNonConst = &nonConstInt; + // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: member variable 'constMemberPointerToNonConst' provides global access to non-const type, consider making the pointed-to data const [cppcoreguidelines-avoid-non-const-global-variables] + int *memberPointerToNonConst = &nonConstInt; + // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: member variable 'memberPointerToNonConst' is globally accessible and non-const, consider making it const [cppcoreguidelines-avoid-non-const-global-variables] + // CHECK-MESSAGES: :[[@LINE-2]]:8: warning: member variable 'memberPointerToNonConst' provides global access to non-const type, consider making the pointed-to data const [cppcoreguidelines-avoid-non-const-global-variables] + const int *const constMemberPointerToConst = &constInt; + int &nonConstMemberReferenceToNonConst = nonConstInt; + // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: member variable 'nonConstMemberReferenceToNonConst' is globally accessible and non-const, consider making it const [cppcoreguidelines-avoid-non-const-global-variables] + // CHECK-MESSAGES: :[[@LINE-2]]:8: warning: member variable 'nonConstMemberReferenceToNonConst' provides global access to non-const type, consider making the referenced data const [cppcoreguidelines-avoid-non-const-global-variables] + +private: + int *privatePointerToNonConst = &nonConstInt; + int &privateReferenceToNonConst = nonConstInt; + int nonConstPrivateMemberVariable = 0; +}; + +class DummyClassWithNonConstStatic { +public: + static int staticNonConstMemberVariable; + static const int staticConstMemberVariable; + +private: + static int staticNonConstPrivateMemberVariable; + static const int staticConstPrivateMemberVariable = 0; +}; +// CHECK-MESSAGES: :[[@LINE-7]]:14: warning: variable 'staticNonConstMemberVariable' is non-const and globally accessible, consider making it const [cppcoreguidelines-avoid-non-const-global-variables] + +int DummyClassWithNonConstStatic::staticNonConstMemberVariable = 0; +// CHECK-MESSAGES: :[[@LINE-1]]:35: warning: variable 'staticNonConstMemberVariable' is non-const and globally accessible, consider making it const [cppcoreguidelines-avoid-non-const-global-variables] +const int DummyClassWithNonConstStatic::staticConstMemberVariable = 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 non-const type, 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 non-const type, consider making the referenced data const [cppcoreguidelines-avoid-non-const-global-variables] + +int *nonConstPointerToMember = &nonConstClassInstance.nonConstMemberVariable; +// 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 non-const type, consider making the pointed-to data const [cppcoreguidelines-avoid-non-const-global-variables] + +int *const constPointerToNonConstMember = &nonConstClassInstance.nonConstMemberVariable; +// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: variable 'constPointerToNonConstMember' provides global access to non-const type, 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 non-const type, 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.nonConstMemberVariable; + +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 + +namespace { +DummyClass nonConstAnonymousNamespaceClassInstance; +} + +// 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 non-const type, 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 non-const type, 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 non-const type, 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; +} + +// CHECKING FOR NON-CONST GLOBAL STRUCT /////////////////////////////////////// +struct DummyStruct { +public: + int structIntElement = 0; + const int constStructIntElement = 0; + +private: + int privateStructIntElement = 0; +}; +// CHECK-MESSAGES: :[[@LINE-6]]:7: warning: member variable 'structIntElement' is globally accessible and non-const, consider making it const [cppcoreguidelines-avoid-non-const-global-variables] + +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 non-const type, 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 non-const type, 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 non-const type, 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; +} + +// CHECKING FOR NON-CONST GLOBAL UNION //////////////////////////////////////// +union DummyUnion { + int unionInteger; + char unionChar; +}; +// CHECK-MESSAGES: :[[@LINE-3]]:7: warning: member variable 'unionInteger' is globally accessible and non-const, consider making it const [cppcoreguidelines-avoid-non-const-global-variables] +// CHECK-MESSAGES: :[[@LINE-3]]:8: warning: member variable 'unionChar' is globally accessible and non-const, consider making it const [cppcoreguidelines-avoid-non-const-global-variables] + +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 non-const type, 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 non-const type, 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 non-const type, 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}; +} + +// 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; + } +}