vingeldal updated this revision to Diff 235483.
vingeldal added a comment.

Updating D70265 <https://reviews.llvm.org/D70265>: [clang-tidy] Add clang tidy 
check I.2 to cppcoreguidelines

- Adjusted the line breaks of some string literals.
- Modified list.rst


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-IgnoreDataMembers.cpp
  
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,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 <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/test/clang-tidy/checkers/cppcoreguidelines-avoid-non-const-global-variables-IgnoreDataMembers.cpp
===================================================================
--- /dev/null
+++ 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;
+};
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
@@ -370,6 +370,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>`_, , "low"
    `cppcoreguidelines-avoid-magic-numbers <cppcoreguidelines-avoid-magic-numbers.html>`_, `readability-magic-numbers <readability-magic-numbers.html>`_, , "style"
+   `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>`_, , "medium"
    `cppcoreguidelines-explicit-virtual-functions <cppcoreguidelines-explicit-virtual-functions.html>`_, `modernize-use-override <modernize-use-override.html>`_, , "low"
    `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>`_, , "low"
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,54 @@
+.. title:: clang-tidy - cppcoreguidelines-avoid-non-const-global-variables
+
+cppcoreguidelines-avoid-non-const-global-variables
+==================================================
+
+Finds non-const global variables as described in check 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.
+https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#Ri-global
+
+.. 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  // 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.
Index: clang-tools-extra/docs/ReleaseNotes.rst
===================================================================
--- clang-tools-extra/docs/ReleaseNotes.rst
+++ 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
   <clang-tidy/checks/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
+  <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 alias :doc:`cert-pos44-c
   <clang-tidy/checks/cert-pos44-c>` to
   :doc:`bugprone-bad-signal-to-kill-thread
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,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
Index: clang-tools-extra/clang-tidy/cppcoreguidelines/AvoidNonConstGlobalVariablesCheck.cpp
===================================================================
--- /dev/null
+++ 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<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
+  }
+
+  if (const auto *Reference =
+          Result.Nodes.getNodeAs<VarDecl>("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<VarDecl>("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<FieldDecl>(
+            "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<FieldDecl>(
+            "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<FieldDecl>("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
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to