[clang-tidy] Adds `IgnoreMacros` option to cppcoreguidelines-avoid-non-const-global-variables (#198183)

Adds `IgnoreMacros` option to
[cppcoreguidelines-avoid-non-const-global-variables](https://clang.llvm.org/extra/clang-tidy/checks/cppcoreguidelines/avoid-non-const-global-variables.html)

GitOrigin-RevId: c0539034f37048dd534eff70486a86998f6cfb18
diff --git a/clang-tidy/cppcoreguidelines/AvoidNonConstGlobalVariablesCheck.cpp b/clang-tidy/cppcoreguidelines/AvoidNonConstGlobalVariablesCheck.cpp
index 2c0baa5..7f5e27d 100644
--- a/clang-tidy/cppcoreguidelines/AvoidNonConstGlobalVariablesCheck.cpp
+++ b/clang-tidy/cppcoreguidelines/AvoidNonConstGlobalVariablesCheck.cpp
@@ -18,7 +18,8 @@
     StringRef Name, ClangTidyContext *Context)
     : ClangTidyCheck(Name, Context),
       AllowInternalLinkage(Options.get("AllowInternalLinkage", false)),
-      AllowThreadLocal(Options.get("AllowThreadLocal", false)) {}
+      AllowThreadLocal(Options.get("AllowThreadLocal", false)),
+      IgnoreMacros(Options.get("IgnoreMacros", false)) {}
 
 void AvoidNonConstGlobalVariablesCheck::registerMatchers(MatchFinder *Finder) {
   auto NamespaceMatcher = AllowInternalLinkage
@@ -57,8 +58,12 @@
     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")
+    const SourceLocation Loc = Variable->getLocation();
+    if (IgnoreMacros && Loc.isMacroID())
+      return;
+
+    diag(Loc, "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.
@@ -66,7 +71,11 @@
 
   if (const auto *VD =
           Result.Nodes.getNodeAs<VarDecl>("indirection_to_non-const")) {
-    diag(VD->getLocation(),
+    const SourceLocation Loc = VD->getLocation();
+    if (IgnoreMacros && Loc.isMacroID())
+      return;
+
+    diag(Loc,
          "variable %0 provides global access to a non-const object; consider "
          "making the %select{referenced|pointed-to}1 data 'const'")
         << VD
@@ -77,6 +86,7 @@
 void AvoidNonConstGlobalVariablesCheck::storeOptions(
     ClangTidyOptions::OptionMap &Opts) {
   Options.store(Opts, "AllowInternalLinkage", AllowInternalLinkage);
+  Options.store(Opts, "IgnoreMacros", IgnoreMacros);
 }
 
 } // namespace clang::tidy::cppcoreguidelines
diff --git a/clang-tidy/cppcoreguidelines/AvoidNonConstGlobalVariablesCheck.h b/clang-tidy/cppcoreguidelines/AvoidNonConstGlobalVariablesCheck.h
index d8f2a73..9f02082 100644
--- a/clang-tidy/cppcoreguidelines/AvoidNonConstGlobalVariablesCheck.h
+++ b/clang-tidy/cppcoreguidelines/AvoidNonConstGlobalVariablesCheck.h
@@ -28,6 +28,7 @@
 private:
   const bool AllowInternalLinkage;
   const bool AllowThreadLocal;
+  const bool IgnoreMacros;
 };
 
 } // namespace clang::tidy::cppcoreguidelines
diff --git a/docs/ReleaseNotes.rst b/docs/ReleaseNotes.rst
index b3a2e89..f1b49e2 100644
--- a/docs/ReleaseNotes.rst
+++ b/docs/ReleaseNotes.rst
@@ -447,6 +447,11 @@
   lambda coroutines using C++23 deducing ``this`` (explicit object parameter)
   are not flagged.
 
+- Improved :doc:`cppcoreguidelines-avoid-non-const-global-variables
+  <clang-tidy/checks/cppcoreguidelines/avoid-non-const-global-variables>`
+  check by adding the `IgnoreMacros` option. When enabled, non-const global
+  variables defined in macros are ignored.
+
 - Improved :doc:`cppcoreguidelines-init-variables
   <clang-tidy/checks/cppcoreguidelines/init-variables>` check by ensuring that
   member pointers are correctly flagged as uninitialized.
diff --git a/docs/clang-tidy/checks/cppcoreguidelines/avoid-non-const-global-variables.rst b/docs/clang-tidy/checks/cppcoreguidelines/avoid-non-const-global-variables.rst
index b7d2dc8..d122685 100644
--- a/docs/clang-tidy/checks/cppcoreguidelines/avoid-non-const-global-variables.rst
+++ b/docs/clang-tidy/checks/cppcoreguidelines/avoid-non-const-global-variables.rst
@@ -54,3 +54,8 @@
 
    When set to `true`, non-const global variables with thread-local storage
    duration will not generate a warning. The default value is `false`.
+
+.. option:: IgnoreMacros
+
+   When set to `true`, non-const global variables defined in macros will not
+   generate a warning. The default value is `false`.
diff --git a/test/clang-tidy/checkers/cppcoreguidelines/avoid-non-const-global-variables-macros.cpp b/test/clang-tidy/checkers/cppcoreguidelines/avoid-non-const-global-variables-macros.cpp
new file mode 100644
index 0000000..9a099d7
--- /dev/null
+++ b/test/clang-tidy/checkers/cppcoreguidelines/avoid-non-const-global-variables-macros.cpp
@@ -0,0 +1,28 @@
+// RUN: %check_clang_tidy %s cppcoreguidelines-avoid-non-const-global-variables %t -- \
+// RUN: -config="{CheckOptions: {cppcoreguidelines-avoid-non-const-global-variables.IgnoreMacros: false}}"
+// RUN: %check_clang_tidy %s -check-suffixes=IGNORE-MACROS cppcoreguidelines-avoid-non-const-global-variables %t -- \
+// RUN: -config="{CheckOptions: {cppcoreguidelines-avoid-non-const-global-variables.IgnoreMacros: true}}"
+
+int nonConstInt = 0;
+// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: variable 'nonConstInt' is non-const and globally accessible, consider making it const
+// CHECK-MESSAGES-IGNORE-MACROS: :[[@LINE-2]]:5: warning: variable 'nonConstInt' is non-const and globally accessible, consider making it const
+
+int &nonConstReference = nonConstInt;
+// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: variable 'nonConstReference' provides global access to a non-const object; consider making the referenced data 'const'
+// CHECK-MESSAGES-IGNORE-MACROS: :[[@LINE-2]]:6: warning: variable 'nonConstReference' provides global access to a non-const object; consider making the referenced data 'const'
+
+#define DEFINE_NON_CONST_INT int macroInt = 0;
+
+DEFINE_NON_CONST_INT
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: variable 'macroInt' is non-const and globally accessible, consider making it const
+
+#define DEFINE_NON_CONST_REFERENCE int &macroRef = nonConstInt;
+
+DEFINE_NON_CONST_REFERENCE
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: variable 'macroRef' provides global access to a non-const object; consider making the referenced data 'const'
+
+#define DEFINE_NON_CONST_POINTER int *macroPtr = &nonConstInt;
+
+DEFINE_NON_CONST_POINTER
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: variable 'macroPtr' is non-const and globally accessible, consider making it const
+// CHECK-MESSAGES: :[[@LINE-2]]:1: warning: variable 'macroPtr' provides global access to a non-const object; consider making the pointed-to data 'const'