From 7bb4228dcc414c59295301970c389bf3065a61a1 Mon Sep 17 00:00:00 2001
From: scott snyder <sss@karma>
Date: Fri, 17 Nov 2023 22:09:30 -0500
Subject: [PATCH 1/5] CheckerGccPlugins: Update for gcc14.

Fixes to work with gcc14.
---
 .../src/checker_gccplugins.cxx                | 27 ++++++++++++++++---
 .../CheckerGccPlugins/src/thread_plugin.cxx   | 19 ++++++++++++-
 .../CheckerGccPlugins/test/thread14_test.cxx  |  8 +++++-
 3 files changed, 49 insertions(+), 5 deletions(-)

diff --git a/External/CheckerGccPlugins/src/checker_gccplugins.cxx b/External/CheckerGccPlugins/src/checker_gccplugins.cxx
index 30ceea8b..2b12df26 100644
--- a/External/CheckerGccPlugins/src/checker_gccplugins.cxx
+++ b/External/CheckerGccPlugins/src/checker_gccplugins.cxx
@@ -25,6 +25,8 @@
 #include "cp/cp-tree.h"
 #include "diagnostic.h"
 #include "gimple.h"
+#include "stringpool.h"
+#include "attribs.h"
 
 
 /* Declare GPL compatible license. */
@@ -174,7 +176,7 @@ checker_plugin_info = {
 
 
 # define ATTRIB(A) {A, 0, 0, false, false, false, false, nullptr, nullptr}
-static struct
+static const struct
 attribute_spec attribs[] =
                      
   { ATTRIB("thread_safe"),
@@ -184,8 +186,16 @@ attribute_spec attribs[] =
     ATTRIB("argument_not_const_thread_safe"),
     ATTRIB("check_thread_safety"),
     ATTRIB("check_thread_safety_debug"),
+#if GCC_VERSION < 14000
     ATTRIB(nullptr),
+#endif
+  };
+#if GCC_VERSION >= 14000
+static const scoped_attribute_specs attrib_table =
+  {
+    "ATLAS", attribs
   };
+#endif
 #undef ATTRIB
 
 
@@ -194,7 +204,12 @@ void
 register_checker_attributes (void* /*event_data*/, void* /*data*/)
 {
   //fprintf (stderr, "register_attributes %s\n", thread_safe_attr.name);
-  register_scoped_attributes (attribs, "ATLAS"
+  register_scoped_attributes (
+#if GCC_VERSION >= 14000
+                              attrib_table
+#else
+                              attribs, "ATLAS"
+#endif
 #if GCC_VERSION >= 12000
                               , false
 #endif
@@ -279,7 +294,13 @@ CheckerConfig config;
 
 void inform_url (location_t loc, const char* url)
 {
-  if (!in_system_header_at(loc) && !global_dc->dc_warn_system_headers)
+  if (!in_system_header_at(loc) &&
+#if GCC_VERSION < 14000
+      !global_dc->dc_warn_system_headers
+#else
+      !global_dc->m_warn_system_headers
+#endif
+      )
     inform (loc, "See %s.", url);
 }
 
diff --git a/External/CheckerGccPlugins/src/thread_plugin.cxx b/External/CheckerGccPlugins/src/thread_plugin.cxx
index 8435bb93..393c5316 100644
--- a/External/CheckerGccPlugins/src/thread_plugin.cxx
+++ b/External/CheckerGccPlugins/src/thread_plugin.cxx
@@ -4,7 +4,7 @@
  * @date Sep, 2015
  * @brief Check for possible thread-safety violations.
  *
- * Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
+ * Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
  */
 
 // FIXME: can i unify pointer_is_const_arg / expr_from_arg_p / expr_from_static_p / value_from_struct?
@@ -440,6 +440,10 @@ bool static_p (tree expr)
     return false;
   }
 
+#if GCC_VERSION >= 14000
+  if (TREE_CODE (expr) == CONSTRUCTOR) return false;
+#endif
+
   if (DECL_P (expr)) {
     if (TREE_CODE (expr) == FUNCTION_DECL) return false;
     if (DECL_THREAD_LOCAL_P (expr)) return false;
@@ -464,7 +468,12 @@ bool static_p (tree expr)
 
 bool const_p (tree expr)
 {
+#if GCC_VERSION < 14000
+  // Maybe this was never needed?
+  // But with gcc14, this can be set for non-const static variables
+  // with no state.
   if (TREE_CONSTANT (expr)) return true;
+#endif
   if (TREE_READONLY (expr)) return true;
   tree typ = TREE_TYPE (expr);
   if (typ && TREE_CODE (typ) == REFERENCE_TYPE) {
@@ -1534,7 +1543,11 @@ void check_nonconst_call_from_const_member (tree fndecl,
                                             function* fun)
 {
   if (!DECL_CONST_MEMFUNC_P (fun->decl)) return;
+#if GCC_VERSION >= 14000
+  if (!DECL_OBJECT_MEMBER_FUNCTION_P (fndecl) || DECL_CONST_MEMFUNC_P (fndecl)) return;
+#else
   if (!DECL_NONSTATIC_MEMBER_FUNCTION_P (fndecl) || DECL_CONST_MEMFUNC_P (fndecl)) return;
+#endif
   if (gimple_call_num_args (stmt) < 1) return;
   tree arg0 = gimple_call_arg (stmt, 0);
   if (TREE_CODE (arg0) != SSA_NAME) return;
@@ -1727,7 +1740,11 @@ void check_nonconst_pointer_member_passing (tree fndecl,
   // If we're calling a non-static member function, don't check for the
   // first (this) argument.  That will be checked separately.
   if (!fndecl) return;
+#if GCC_VERSION >= 14000
+  if (DECL_OBJECT_MEMBER_FUNCTION_P (fndecl) && i == 0) return;
+#else
   if (DECL_NONSTATIC_MEMBER_FUNCTION_P (fndecl) && i == 0) return;
+#endif
 
   // Don't warn about thread-safe libc functions.
   if (is_cstdlib (fndecl).second) return;
diff --git a/External/CheckerGccPlugins/test/thread14_test.cxx b/External/CheckerGccPlugins/test/thread14_test.cxx
index c141359e..2c29fccb 100644
--- a/External/CheckerGccPlugins/test/thread14_test.cxx
+++ b/External/CheckerGccPlugins/test/thread14_test.cxx
@@ -1,4 +1,4 @@
-// Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration
+// Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
 //
 // thread14_test: testing check_direct_static_use/check_assign_address_of_static
 //                with a const static object
@@ -59,4 +59,10 @@ const int* f12()
   return &s2.x;
 }
 
+void f20()
+{
+  [[maybe_unused]] int a[256] = {0};
+}
+
+
 
-- 
GitLab


From 6613c97aa6f4785325a42d2c767bb74bf63f81ae Mon Sep 17 00:00:00 2001
From: scott snyder <sss@karma>
Date: Fri, 17 Nov 2023 22:11:00 -0500
Subject: [PATCH 2/5] CheckerGccPlugins: Drop support for gcc versions before
 9.

Drop support for gcc versions before 9.
---
 External/CheckerGccPlugins/src/divcheck_plugin.cxx | 6 +-----
 External/CheckerGccPlugins/src/thread_plugin.cxx   | 4 ----
 2 files changed, 1 insertion(+), 9 deletions(-)

diff --git a/External/CheckerGccPlugins/src/divcheck_plugin.cxx b/External/CheckerGccPlugins/src/divcheck_plugin.cxx
index e1de8202..21a70714 100644
--- a/External/CheckerGccPlugins/src/divcheck_plugin.cxx
+++ b/External/CheckerGccPlugins/src/divcheck_plugin.cxx
@@ -4,7 +4,7 @@
  * @date May, 2015
  * @brief Check for redundant divisions.
  *
- * Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration
+ * Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
  */
 
 
@@ -53,11 +53,7 @@ const pass_data divcheck_pass_data =
 {
   GIMPLE_PASS, /* type */
   "divcheck", /* name */
-#if GCC_VERSION < 9000
-  0, /* optinfo_flags */
-#else
   OPTGROUP_NONE,  /* optinfo_flags */
-#endif
   TV_NONE, /* tv_id */
   0, /* properties_required */
   0, /* properties_provided */
diff --git a/External/CheckerGccPlugins/src/thread_plugin.cxx b/External/CheckerGccPlugins/src/thread_plugin.cxx
index 393c5316..44a0c76e 100644
--- a/External/CheckerGccPlugins/src/thread_plugin.cxx
+++ b/External/CheckerGccPlugins/src/thread_plugin.cxx
@@ -151,11 +151,7 @@ const pass_data thread_pass_data =
 {
   GIMPLE_PASS, /* type */
   "thread", /* name */
-#if GCC_VERSION < 9000
-  0, /* optinfo_flags */
-#else
   OPTGROUP_NONE,  /* optinfo_flags */
-#endif
   TV_NONE, /* tv_id */
   0, /* properties_required */
   0, /* properties_provided */
-- 
GitLab


From c7359adeaf0b6b962f4f51a73d47d135a1866658 Mon Sep 17 00:00:00 2001
From: scott snyder <snyder@bnl.gov>
Date: Wed, 24 Apr 2024 17:03:09 +0200
Subject: [PATCH 3/5] CheckerGccPlugins: Add tests for compiling with LTO on.

Add tests for compiling with LTO on, and a test for linking with LTO.
Also update C++ standard selection to C++20.
---
 External/CheckerGccPlugins/CMakeLists.txt     | 27 +++++++++++++++++--
 .../CheckerGccPlugins/share/ltolink_test.ref  |  0
 .../test/checker_ltolink_test.sh.in           |  8 ++++++
 .../CheckerGccPlugins/test/checker_test.sh.in |  4 +--
 .../CheckerGccPlugins/test/ltolink_test.cxx   |  4 +++
 5 files changed, 39 insertions(+), 4 deletions(-)
 create mode 100644 External/CheckerGccPlugins/share/ltolink_test.ref
 create mode 100755 External/CheckerGccPlugins/test/checker_ltolink_test.sh.in
 create mode 100644 External/CheckerGccPlugins/test/ltolink_test.cxx

diff --git a/External/CheckerGccPlugins/CMakeLists.txt b/External/CheckerGccPlugins/CMakeLists.txt
index 37eccb20..9ff789ba 100644
--- a/External/CheckerGccPlugins/CMakeLists.txt
+++ b/External/CheckerGccPlugins/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
+# Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
 
 # The name of the package:
 atlas_subdir( CheckerGccPlugins )
@@ -46,7 +46,11 @@ function( CheckerGccPlugins_test1 testName mode )
   cmake_parse_arguments( ARG "" "ENVIRONMENT" "" ${ARGN} )
 
   set( _fullName ${testName}_${mode} )
-  set( _checkerTestFlags ${CMAKE_CXX_FLAGS_${mode}} )
+  if( "${mode}" STREQUAL "LTO" )
+    set( _checkerTestFlags "${CMAKE_CXX_FLAGS_RELEASE} -flto " )
+  else()
+    set( _checkerTestFlags ${CMAKE_CXX_FLAGS_${mode}} )
+  endif()
   configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/test/checker_test.sh.in
                   ${CMAKE_CURRENT_BINARY_DIR}/CheckerGccPlugins_${_fullName}.sh
                   @ONLY )
@@ -62,6 +66,7 @@ endfunction( CheckerGccPlugins_test1 )
 function( CheckerGccPlugins_test testName )
 CheckerGccPlugins_test1( ${testName} RELEASE ${ARGN} )
 CheckerGccPlugins_test1( ${testName} DEBUG ${ARGN} )
+CheckerGccPlugins_test1( ${testName} LTO ${ARGN} )
 endfunction( CheckerGccPlugins_test )
 
 
@@ -111,3 +116,21 @@ CheckerGccPlugins_test( thread10 ENVIRONMENT CHECKERGCCPLUGINS_CONFIG=${CMAKE_CU
 CheckerGccPlugins_test( thread16 ENVIRONMENT CHECKERGCCPLUGINS_CONFIG=${CMAKE_CURRENT_SOURCE_DIR}/share/test_unchecked.config )
 CheckerGccPlugins_test( config ENVIRONMENT CHECKERGCCPLUGINS_CONFIG=${CMAKE_CURRENT_SOURCE_DIR}/share/test.config )
 CheckerGccPlugins_test( check_ts2 ENVIRONMENT CHECKERGCCPLUGINS_CONFIG=${CMAKE_CURRENT_SOURCE_DIR}/share/test.config )
+
+
+function( CheckerGccPlugins_ltolink_test )
+  set( testName "ltolink" )
+  set( _checkerTestFlags "${CMAKE_CXX_FLAGS_RELEASE} -flto " )
+  configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/test/checker_ltolink_test.sh.in
+                  ${CMAKE_CURRENT_BINARY_DIR}/CheckerGccPlugins_ltolink.sh
+                  @ONLY )
+  atlas_add_test( ltolink
+                  SCRIPT ${CMAKE_CURRENT_BINARY_DIR}/CheckerGccPlugins_ltolink.sh
+                  ENVIRONMENT ${ARG_ENVIRONMENT}
+                  POST_EXEC_SCRIPT "${CMAKE_CURRENT_SOURCE_DIR}/test/post.sh ltolink '' ${CMAKE_CURRENT_SOURCE_DIR}/share/ltolink_test.ref"
+                   )
+endfunction( CheckerGccPlugins_ltolink_test )
+
+CheckerGccPlugins_ltolink_test()
+
+
diff --git a/External/CheckerGccPlugins/share/ltolink_test.ref b/External/CheckerGccPlugins/share/ltolink_test.ref
new file mode 100644
index 00000000..e69de29b
diff --git a/External/CheckerGccPlugins/test/checker_ltolink_test.sh.in b/External/CheckerGccPlugins/test/checker_ltolink_test.sh.in
new file mode 100755
index 00000000..fcc6d7b6
--- /dev/null
+++ b/External/CheckerGccPlugins/test/checker_ltolink_test.sh.in
@@ -0,0 +1,8 @@
+#!/bin/sh
+#
+# Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
+#
+
+@CMAKE_CXX_COMPILER@ -c -o @testName@_test.o $EXTRA_FLAGS --std=c++20 @_checkerTestFlags@ -fplugin=@CMAKE_LIBRARY_OUTPUT_DIRECTORY@/libchecker_gccplugins.so -fplugin-arg-libchecker_gccplugins-checkers=all @CMAKE_CURRENT_SOURCE_DIR@/test/@testName@_test.cxx
+@CMAKE_CXX_COMPILER@  $EXTRA_FLAGS --std=c++20 @_checkerTestFlags@ -fplugin=@CMAKE_LIBRARY_OUTPUT_DIRECTORY@/libchecker_gccplugins.so -fplugin-arg-libchecker_gccplugins-checkers=all @testName@_test.o -o @testName@_test.exe
+
diff --git a/External/CheckerGccPlugins/test/checker_test.sh.in b/External/CheckerGccPlugins/test/checker_test.sh.in
index 55b6d5f4..db0cd895 100755
--- a/External/CheckerGccPlugins/test/checker_test.sh.in
+++ b/External/CheckerGccPlugins/test/checker_test.sh.in
@@ -1,6 +1,6 @@
 #!/bin/sh
 #
-# Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
+# Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
 #
 
 # Diagnostic format changed in gcc9, but can be changed back to the old format
@@ -12,5 +12,5 @@ if [ $MAJOR_VERSION -ge 9 ]; then
     EXTRA_FLAGS="-fno-diagnostics-show-line-numbers"
 fi
 
-@CMAKE_CXX_COMPILER@ -c -o /dev/null $EXTRA_FLAGS -fdiagnostics-generate-patch --std=c++17 @_checkerTestFlags@ -fplugin=@CMAKE_LIBRARY_OUTPUT_DIRECTORY@/libchecker_gccplugins.so -fplugin-arg-libchecker_gccplugins-checkers=all @CMAKE_CURRENT_SOURCE_DIR@/test/@testName@_test.cxx
+@CMAKE_CXX_COMPILER@ -c -o /dev/null $EXTRA_FLAGS -fdiagnostics-generate-patch --std=c++20 @_checkerTestFlags@ -fplugin=@CMAKE_LIBRARY_OUTPUT_DIRECTORY@/libchecker_gccplugins.so -fplugin-arg-libchecker_gccplugins-checkers=all @CMAKE_CURRENT_SOURCE_DIR@/test/@testName@_test.cxx
 
diff --git a/External/CheckerGccPlugins/test/ltolink_test.cxx b/External/CheckerGccPlugins/test/ltolink_test.cxx
new file mode 100644
index 00000000..f8b643af
--- /dev/null
+++ b/External/CheckerGccPlugins/test/ltolink_test.cxx
@@ -0,0 +1,4 @@
+int main()
+{
+  return 0;
+}
-- 
GitLab


From db4b259850b6d9979305906f949eb9ae18e631e6 Mon Sep 17 00:00:00 2001
From: scott snyder <sss@karma>
Date: Wed, 17 Apr 2024 13:20:50 -0400
Subject: [PATCH 4/5] Fix for running checkers with LTO enabled.

The free_lang_data pass runs just after gimplification
(and before the conversion to SSA).  Normally, it doesn't do much,
but if LTO is enabled, then it will free the C++-specific parts
from the types and declarations.  However, the thread checker
relies on this information.  Further, dataflow analysis requires that
the SSA conversion has taken place, so we can't just shift it
to before free_lang_data.  But it doesn't really matter that much
exactly where free_lang_data runs, so we instead move it to slightly
later, after the checker runs.
---
 .../CheckerGccPlugins/src/thread_plugin.cxx   | 79 ++++++++++++++++++-
 1 file changed, 76 insertions(+), 3 deletions(-)

diff --git a/External/CheckerGccPlugins/src/thread_plugin.cxx b/External/CheckerGccPlugins/src/thread_plugin.cxx
index 44a0c76e..77a83ca0 100644
--- a/External/CheckerGccPlugins/src/thread_plugin.cxx
+++ b/External/CheckerGccPlugins/src/thread_plugin.cxx
@@ -2134,22 +2134,95 @@ void thread_finishdecl_callback (void* gcc_data, void* /*user_data*/)
 }
 
 
+//******************************************************************************
+// Dummy do-nothing pass.  Used to replace free_lang_data in LTO builds.
+// See below.
+//
+
+const pass_data dummy_pass_data =
+{
+  SIMPLE_IPA_PASS, /* type */
+  "*dummy", /* name */
+  OPTGROUP_NONE,  /* optinfo_flags */
+  TV_NONE, /* tv_id */
+  0, /* properties_required */
+  0, /* properties_provided */
+  0, /* properties_destroyed */
+  0, /* todo_flags_start */
+  0  /* todo_flags_finish */
+};
+
+
+class dummy_pass : public simple_ipa_opt_pass
+{
+public:
+  dummy_pass (gcc::context* ctxt)
+    : simple_ipa_opt_pass (dummy_pass_data, ctxt)
+  { 
+  }
+
+  virtual unsigned int execute (function* ) override
+  { return 0; }
+
+  virtual opt_pass* clone() override { return new dummy_pass(*this); }
+};
+
+
 } // anonymous namespace
 
 
 void init_thread_checker (plugin_name_args* plugin_info)
 {
-  struct register_pass_info pass_info = {
+  struct register_pass_info thread_pass_info = {
     new thread_pass(g),
     "ssa",
     0,
     PASS_POS_INSERT_AFTER
   };
-  
+
   register_callback (plugin_info->base_name,
                      PLUGIN_PASS_MANAGER_SETUP,
                      NULL,
-                     &pass_info);
+                     &thread_pass_info);
+
+  // The free_lang_data pass runs just after gimplification
+  // (and before the conversion to SSA).  Normally, it doesn't do much,
+  // but if LTO is enabled, then it will free the C++-specific parts
+  // from the types and declarations.  However, the thread checker
+  // relies on this information.  Further, dataflow analysis requires that
+  // the SSA conversion has taken place, so we can't just shift it
+  // to before free_lang_data.  But it doesn't really matter that much
+  // exactly where free_lang_data runs, so we instead move it to slightly
+  // later, after the checker runs.
+  //
+  // The plugin API doesn't seem to provide a way to reorder existing passes,
+  // so we do this by replacing free_lang_data with a dummy and then adding
+  // a new instance of it further on.
+  if (flag_lto) {
+    struct register_pass_info dummy_pass_info = {
+      new dummy_pass(g),
+      "*free_lang_data",
+      0,
+      PASS_POS_REPLACE
+    };
+
+    struct register_pass_info freelang_pass_info = {
+      make_pass_ipa_free_lang_data(g),
+      "build_ssa_passes",
+      1,
+      PASS_POS_INSERT_AFTER
+    };
+
+    register_callback (plugin_info->base_name,
+                       PLUGIN_PASS_MANAGER_SETUP,
+                       NULL,
+                       &dummy_pass_info);
+
+    register_callback (plugin_info->base_name,
+                       PLUGIN_PASS_MANAGER_SETUP,
+                       NULL,
+                       &freelang_pass_info);
+  }
 
   register_callback (plugin_info->base_name,
                      PLUGIN_FINISH_TYPE,
-- 
GitLab


From 2dc3d98d8978ac574361cf847837a224fc648664 Mon Sep 17 00:00:00 2001
From: scott snyder <snyder@bnl.gov>
Date: Wed, 24 Apr 2024 04:15:36 +0200
Subject: [PATCH 5/5] Fixes to allow specifying the checker plugin on the link
 command with LTO.

In the cmake builds, the -fplugin switch will be given for both
the compile and link steps.  Normally, when that switch is given
during linking, it will not have any effect.  But if link-time
optimization (LTO) is being done, then the compiler will run at link
time and the plugin gets loaded.  The problem then is that it's not
the full compiler that runs, but only the middle/backend.  If the
plugin references symbols from the frontend, then it will fail
to load during the link step, causing the link to fail.
(gcc will load the plugin with RTLD_NOW.)

To resolve this, we launder references to FE symbols through
the shims defined here, which access the symbols via dlsym().
If the first symbol is missing then we return gracefully and
disable the checkers.
---
 .../src/callcheck_plugin.cxx                  |   5 +-
 .../src/check_thread_safety_p.cxx             |   5 +-
 .../src/checker_gccplugins.cxx                |  13 +-
 External/CheckerGccPlugins/src/feshim.cxx     | 237 ++++++++++++++++++
 External/CheckerGccPlugins/src/feshim.h       |  95 +++++++
 .../src/gaudi_inheritance_plugin.cxx          |  11 +-
 .../CheckerGccPlugins/src/naming_plugin.cxx   |  15 +-
 .../CheckerGccPlugins/src/thread_plugin.cxx   |  41 +--
 .../CheckerGccPlugins/src/usingns_plugin.cxx  |   7 +-
 9 files changed, 387 insertions(+), 42 deletions(-)
 create mode 100644 External/CheckerGccPlugins/src/feshim.cxx
 create mode 100644 External/CheckerGccPlugins/src/feshim.h

diff --git a/External/CheckerGccPlugins/src/callcheck_plugin.cxx b/External/CheckerGccPlugins/src/callcheck_plugin.cxx
index 3df23ca6..dc85352f 100644
--- a/External/CheckerGccPlugins/src/callcheck_plugin.cxx
+++ b/External/CheckerGccPlugins/src/callcheck_plugin.cxx
@@ -4,7 +4,7 @@
  * @date Apr, 2019
  * @brief Various ATLAS-specific function call checks.
  *
- * Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration
+ * Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
  */
 
 
@@ -36,6 +36,7 @@
 #include "stringpool.h"
 #include "attribs.h"
 #include "gcc-rich-location.h"
+#include "feshim.h"
 #include <vector>
 #include <unordered_map>
 #include <string>
@@ -343,7 +344,7 @@ unsigned int callcheck_pass::callcheck_execute (function* fun)
           if (!fndecl) {
             fndecl = vcall_fndecl (stmt);
           }
-          std::string name = decl_as_string (fndecl, TFF_SCOPE + TFF_TEMPLATE_NAME);
+          std::string name = CheckerGccPlugins::decl_as_string (fndecl, TFF_SCOPE + TFF_TEMPLATE_NAME);
           hide_targs (name);
           std::string::size_type ipos = name.find (" [with");
           if (ipos != std::string::npos) {
diff --git a/External/CheckerGccPlugins/src/check_thread_safety_p.cxx b/External/CheckerGccPlugins/src/check_thread_safety_p.cxx
index 4a739609..a952a143 100644
--- a/External/CheckerGccPlugins/src/check_thread_safety_p.cxx
+++ b/External/CheckerGccPlugins/src/check_thread_safety_p.cxx
@@ -16,7 +16,7 @@
  * If a decl has the attribute check_thread_safety_debug, then a diagnostic
  * will be printed saying if that decl has thread-safety checking enabled.
  *
- * Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
+ * Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
  */
 
 
@@ -395,7 +395,8 @@ bool check_thread_safety_location_p (location_t loc)
     return false;
   }
 
-  std::string file = LOCATION_FILE(loc);
+  const char* s = LOCATION_FILE(loc);
+  std::string file = s ? s : "";
   thread_safe_files_t::iterator it = thread_safe_files.find (file);
   if (it != thread_safe_files.end()) return it->second;
 
diff --git a/External/CheckerGccPlugins/src/checker_gccplugins.cxx b/External/CheckerGccPlugins/src/checker_gccplugins.cxx
index 2b12df26..e217f040 100644
--- a/External/CheckerGccPlugins/src/checker_gccplugins.cxx
+++ b/External/CheckerGccPlugins/src/checker_gccplugins.cxx
@@ -4,7 +4,7 @@
  * @date Aug, 2014
  * @brief Framework for running checker plugins in gcc.
  *
- * Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
+ * Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
  */
 
 
@@ -20,13 +20,13 @@
 #include "tree-core.h"
 #include "tree-pass.h"
 #include "plugin.h"
-#include "c-family/c-pragma.h"
 #include "tree.h"
 #include "cp/cp-tree.h"
 #include "diagnostic.h"
 #include "gimple.h"
 #include "stringpool.h"
 #include "attribs.h"
+#include "feshim.h"
 
 
 /* Declare GPL compatible license. */
@@ -221,12 +221,14 @@ static
 void
 register_checker_pragmas (void* /*event_data*/, void* /*data*/)
 {
+  using CheckerGccPlugins::c_register_pragma;
   c_register_pragma ("ATLAS", "check_thread_safety",
                      CheckerGccPlugins::handle_check_thread_safety_pragma);
   c_register_pragma ("ATLAS", "no_check_thread_safety",
                      CheckerGccPlugins::handle_no_check_thread_safety_pragma);
 
-  cpp_define (parse_in, "ATLAS_GCC_CHECKERS");
+  using CheckerGccPlugins::cpp_define;
+  cpp_define ("ATLAS_GCC_CHECKERS");
 }
 
 
@@ -246,6 +248,8 @@ plugin_init(struct plugin_name_args   *plugin_info,
     return 1;
   }
 
+  if (!CheckerGccPlugins::init_shims()) return 0;
+
   // Handle command-line arguments.
   if (collect_plugin_args(plugin_info)!=0)
     return 1;
@@ -364,7 +368,8 @@ tree vcall_fndecl (gimplePtr stmt)
           // collide with what we're looking for.  Just ignore such entries.
           // But careful: Can't just compare the types, because TYP
           // may be a const type.
-          TYPE_NAME (strip_typedefs (typ)) == TYPE_NAME (strip_typedefs (CP_DECL_CONTEXT (*it)))
+          TYPE_NAME (CheckerGccPlugins::strip_typedefs (typ)) ==
+          TYPE_NAME (CheckerGccPlugins::strip_typedefs (CP_DECL_CONTEXT (*it)))
           )
       {
         tree fn_ndx_tree = DECL_VINDEX (*it);
diff --git a/External/CheckerGccPlugins/src/feshim.cxx b/External/CheckerGccPlugins/src/feshim.cxx
new file mode 100644
index 00000000..1031de1b
--- /dev/null
+++ b/External/CheckerGccPlugins/src/feshim.cxx
@@ -0,0 +1,237 @@
+/*
+ * Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration.
+ */
+/**
+ * @file CheckerGccPlugins/src/feshim.cxx
+ * @author scott snyder <snyder@bnl.gov>
+ * @date Apr, 2024
+ * @brief Shims for accessing front-end symbols.
+ */
+
+#define FESHIM_CXX
+#define scope_chain dum_scope_chain
+#include "checker_gccplugins.h"
+#include "tree.h"
+#include "cp/cp-tree.h"
+#include "feshim.h"
+#include <dlfcn.h>
+#undef scope_chain
+
+// Shim variables.
+tree cp_global_trees[CPTI_MAX];
+cpp_reader* parse_in = nullptr;
+
+
+namespace CheckerGccPlugins
+{
+
+
+//********************************************************************
+// The shim functions.
+// These will bounce the calls to the real_* pointers which
+// we retrieved in init_shims().
+
+
+typedef void (*c_register_pragma_t) (const char* space,
+                                     const char* type,
+                                     pragma_handler_1arg handler);
+c_register_pragma_t real_c_register_pragma = nullptr;
+
+
+void c_register_pragma (const char *space, const char *name,
+                        pragma_handler_1arg handler)
+{
+  (*real_c_register_pragma) (space, name, handler);
+}
+
+
+//********
+
+
+typedef void (*cpp_define_t) (cpp_reader *, const char *);
+cpp_define_t real_cpp_define = nullptr;
+void cpp_define (const char* def)
+{
+  (*real_cpp_define) (parse_in, def);
+}
+
+
+//********
+
+
+typedef tree (*strip_typedefs_t) (tree t, bool* remove_attributes, unsigned int flags);
+strip_typedefs_t real_strip_typedefs = nullptr;
+tree strip_typedefs (tree t, bool* remove_attributes, unsigned int flags)
+{
+  return (*real_strip_typedefs) (t, remove_attributes, flags);
+}
+
+
+//********
+
+
+typedef tree (*lookup_base_t) (tree t, tree base, /*base_access*/int access,
+                               /*base_kind*/int *kind_ptr,
+                               /*tsubst_flags_t*/int complain
+#if GCC_VERSION >= 14000
+                               , HOST_WIDE_INT offset
+#endif
+                               );
+lookup_base_t real_lookup_base = nullptr;
+tree lookup_base (tree t, tree base)
+{
+  return (*real_lookup_base) (t, base,
+                              0, // ba_any
+                              NULL,
+                              0 // tf_none
+#if GCC_VERSION >= 14000
+                              , -1
+#endif
+                              );
+}
+
+
+//********
+
+
+typedef const char* (*type_as_string_t) (tree t, int flags);
+type_as_string_t real_type_as_string = nullptr;
+const char* type_as_string (tree t, int flags)
+{
+  return (*real_type_as_string) (t, flags);
+}
+
+
+//********
+
+
+typedef const char* (*decl_as_string_t) (tree t, int flags);
+decl_as_string_t real_decl_as_string = nullptr;
+const char* decl_as_string (tree t, int flags)
+{
+  return (*real_decl_as_string) (t, flags);
+}
+
+
+//********
+
+
+typedef tree (*skip_artificial_parms_for_t) (const_tree fn, tree list);
+skip_artificial_parms_for_t real_skip_artificial_parms_for = nullptr;
+tree skip_artificial_parms_for (const_tree fn, tree list)
+{
+  return (*real_skip_artificial_parms_for) (fn, list);
+}
+
+
+//********
+
+
+typedef tree (*dfs_walk_all_t) (tree binfo, tree (*pre_fn) (tree, void *),
+                                tree (*post_fn) (tree, void *), void *data);
+dfs_walk_all_t real_dfs_walk_all = nullptr;
+tree
+dfs_walk_all (tree binfo, tree (*pre_fn) (tree, void *),
+              tree (*post_fn) (tree, void *), void *data)
+{
+  return (*real_dfs_walk_all) (binfo, pre_fn, post_fn, data);
+}
+
+
+//********
+
+
+typedef int (*cp_type_quals_t) (const_tree t);
+cp_type_quals_t real_cp_type_quals = nullptr;
+int cp_type_quals (const_tree t)
+{
+  return (*real_cp_type_quals) (t);
+}
+
+
+//********
+
+
+typedef tree (*look_for_overrides_here_t) (tree type, tree fndecl);
+look_for_overrides_here_t real_look_for_overrides_here = nullptr;
+tree look_for_overrides_here (tree type, tree fndecl)
+{
+  return (*real_look_for_overrides_here) (type, fndecl);
+}
+
+
+//********************************************************************
+// Shim for getting the current namespace.
+
+
+saved_scope** scope_chain_ptr = nullptr;
+tree get_current_namespace()
+{
+  return (*scope_chain_ptr)->old_namespace;
+}
+
+
+//********************************************************************
+
+
+bool init_shims()
+{
+  // Handle referencing the main program.
+  void* handle = dlopen (NULL, 0);
+
+  // Check to see if any FE symbols are present.
+  // If not, exit gracefully and disable the checkers.
+  if (!dlsym (handle, "scope_chain")) {
+    return false;
+  }
+
+  // Helper for looking up a symbol.
+  // Abort if we don't find the symbol.
+  auto findsym = [&] (auto& fn, const char* sym)
+  {
+    void* p = dlsym (handle, sym);
+    if (!p) {
+      fatal_error (input_location, "CheckerGccPlugins: cannot find symbol %<%s%>", sym);
+    }
+    fn = (std::remove_reference_t<decltype(fn)>)p;
+  };
+
+  // Look up this symbol and copy it to our local array.
+  tree* trees;
+  findsym (trees, "cp_global_trees");
+  memcpy (cp_global_trees, trees, sizeof (cp_global_trees));
+
+  // Variable pointers.
+  
+  findsym (scope_chain_ptr, "scope_chain");
+
+  cpp_reader** parse_in_ptr = nullptr;
+  findsym (parse_in_ptr, "parse_in");
+  parse_in = *parse_in_ptr;
+
+
+  // Function pointers.
+
+  findsym (real_c_register_pragma, "_Z17c_register_pragmaPKcS0_PFvP10cpp_readerE");
+  findsym (real_cpp_define, "_Z10cpp_defineP10cpp_readerPKc");
+  findsym (real_strip_typedefs, "_Z14strip_typedefsP9tree_nodePbj");
+  findsym (real_lookup_base,
+#if GCC_VERSION >= 14000
+                                           "_Z11lookup_baseP9tree_nodeS0_iP9base_kindil"
+#else
+                                           "_Z11lookup_baseP9tree_nodeS0_iP9base_kindi"
+#endif
+            );
+  findsym (real_type_as_string, "_Z14type_as_stringP9tree_nodei");
+  findsym (real_decl_as_string, "_Z14decl_as_stringP9tree_nodei");
+  findsym (real_skip_artificial_parms_for, "_Z25skip_artificial_parms_forPK9tree_nodePS_");
+  findsym (real_dfs_walk_all, "_Z12dfs_walk_allP9tree_nodePFS0_S0_PvES3_S1_");
+  findsym (real_cp_type_quals, "_Z13cp_type_qualsPK9tree_node");
+  findsym (real_look_for_overrides_here, "_Z23look_for_overrides_hereP9tree_nodeS0_");
+
+  return true;
+}
+
+
+} // namespace CheckerGccPlugins
+
diff --git a/External/CheckerGccPlugins/src/feshim.h b/External/CheckerGccPlugins/src/feshim.h
new file mode 100644
index 00000000..c125c3c1
--- /dev/null
+++ b/External/CheckerGccPlugins/src/feshim.h
@@ -0,0 +1,95 @@
+// This file's extension implies that it's C, but it's really -*- C++ -*-.
+/*
+ * Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration.
+ */
+/**
+ * @file CheckerGccPlugins/src/feshim.h
+ * @author scott snyder <snyder@bnl.gov>
+ * @date Apr, 2024
+ * @brief Shims for accessing front-end symbols.
+ *
+ * In the cmake builds, the -fplugin switch will be given for both
+ * the compile and link steps.  Normally, when that switch is given
+ * during linking, it will not have any effect.  But if link-time
+ * optimization (LTO) is being done, then the compiler will run at link
+ * time and the plugin gets loaded.  The problem then is that it's not
+ * the full compiler that runs, but only the middle/backend.  If the
+ * plugin references symbols from the frontend, then it will fail
+ * to load during the link step, causing the link to fail.
+ * (gcc will load the plugin with RTLD_NOW.)
+ *
+ * To resolve this, we launder references to FE symbols through
+ * the shims defined here, which access the symbols via dlsym().
+ * If the first symbol is missing then we return gracefully and
+ * disable the checkers.
+ */
+
+
+#ifndef CHECKERGCCPLUGINS_FESHIM_H
+#define CHECKERGCCPLUGINS_FESHIM_H
+
+
+#include "tree-core.h"
+
+
+struct cpp_reader;
+
+
+namespace CheckerGccPlugins
+{
+
+
+//
+// Initialize shims for accessing symbols from the front-end.
+// Returns true on success, false if frontend symbols are not available.
+//
+bool init_shims();
+
+
+// The shim functions.
+
+
+typedef void (*pragma_handler_1arg)(struct cpp_reader *);
+void c_register_pragma (const char *space, const char *name,
+                        pragma_handler_1arg handler);
+
+void cpp_define (const char* def);
+
+
+tree strip_typedefs (tree t,
+                     bool* remove_attributes = NULL,
+                     unsigned int flags = 0);
+
+tree lookup_base (tree t, tree base);
+
+const char* type_as_string (tree t, int flags);
+
+const char* decl_as_string (tree t, int flags);
+
+tree skip_artificial_parms_for (const_tree fn, tree list);
+
+tree
+dfs_walk_all (tree binfo, tree (*pre_fn) (tree, void *),
+              tree (*post_fn) (tree, void *), void *data);
+
+
+int cp_type_quals (const_tree t);
+
+
+tree look_for_overrides_here (tree type, tree fndecl);
+
+
+tree get_current_namespace();
+
+
+} // namespace CheckerGccPlugins
+
+
+// Define this here so that the macros in cp-tree.h that use this function
+// will pick up the shim instead.
+#ifndef FESHIM_CXX
+#define cp_type_quals CheckerGccPlugins::cp_type_quals
+#endif
+
+
+#endif // not CHECKERGCCPLUGINS_FESHIM_H
diff --git a/External/CheckerGccPlugins/src/gaudi_inheritance_plugin.cxx b/External/CheckerGccPlugins/src/gaudi_inheritance_plugin.cxx
index ee0ea09c..ae482f6e 100644
--- a/External/CheckerGccPlugins/src/gaudi_inheritance_plugin.cxx
+++ b/External/CheckerGccPlugins/src/gaudi_inheritance_plugin.cxx
@@ -11,7 +11,7 @@
  * The AthenaBaseComps classes themselves (AthAlgorithm, AthAlgTool,
  * AthService) are excluded from the check.
  *
- * Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+ * Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
  */
 
 
@@ -21,6 +21,7 @@
 #include "cp/cp-tree.h"
 #include "diagnostic.h"
 #include "print-tree.h"
+#include "feshim.h"
 
 
 namespace {
@@ -33,10 +34,10 @@ const char* type_name (tree t)
 {
   unsigned int save = flag_sanitize;
   flag_sanitize = 0;
-  const char* ret = type_as_string (t,
-                                    TFF_PLAIN_IDENTIFIER +
-                                    //TFF_UNQUALIFIED_NAME +
-                                    TFF_NO_OMIT_DEFAULT_TEMPLATE_ARGUMENTS);
+  const char* ret = CheckerGccPlugins::type_as_string (t,
+                                                       TFF_PLAIN_IDENTIFIER +
+                                                       //TFF_UNQUALIFIED_NAME +
+                                                       TFF_NO_OMIT_DEFAULT_TEMPLATE_ARGUMENTS);
   flag_sanitize = save;
   return ret;
 }
diff --git a/External/CheckerGccPlugins/src/naming_plugin.cxx b/External/CheckerGccPlugins/src/naming_plugin.cxx
index e71c1a30..f5442a8d 100644
--- a/External/CheckerGccPlugins/src/naming_plugin.cxx
+++ b/External/CheckerGccPlugins/src/naming_plugin.cxx
@@ -4,7 +4,7 @@
  * @date Aug, 2015
  * @brief Check ATLAS naming conventions.
  *
- * Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
+ * Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
  */
 
 
@@ -33,6 +33,7 @@
 #include "tree-phinodes.h"
 #include "gimple-ssa.h"
 #include "ssa-iterators.h"
+#include "feshim.h"
 
 
 #if GCC_VERSION < 12000
@@ -115,8 +116,7 @@ bool ignore_decl_p1 (tree decl)
 
     // Ignore classes deriving from SG::IAuxStore.
     if (TREE_CODE (type) == RECORD_TYPE && iauxstore_type) {
-      tree base = lookup_base (type, iauxstore_type,
-                               ba_any, NULL, tf_none);
+      tree base = CheckerGccPlugins::lookup_base (type, iauxstore_type);
       if (base != NULL_TREE && base != error_mark_node)
         return true;
     }
@@ -364,10 +364,11 @@ void naming_finishdecl_callback (void* gcc_data, void* /*user_data*/)
 
         // Gaudi plugin service v2
         if (strncmp (name, "_register_", 10) == 0 && !TREE_PUBLIC (decl)) {
-          const char* name = type_as_string (TREE_TYPE (decl),
-                                             TFF_PLAIN_IDENTIFIER +
-                                             TFF_SCOPE +
-                                             TFF_CHASE_TYPEDEF);
+          const char* name = CheckerGccPlugins::type_as_string
+            (TREE_TYPE (decl),
+             TFF_PLAIN_IDENTIFIER +
+             TFF_SCOPE +
+             TFF_CHASE_TYPEDEF);
           if (strncmp (name, "Gaudi::PluginService::", 22) == 0) {
             return;
           }
diff --git a/External/CheckerGccPlugins/src/thread_plugin.cxx b/External/CheckerGccPlugins/src/thread_plugin.cxx
index 77a83ca0..e470fb38 100644
--- a/External/CheckerGccPlugins/src/thread_plugin.cxx
+++ b/External/CheckerGccPlugins/src/thread_plugin.cxx
@@ -41,6 +41,7 @@
 #include <unordered_map>
 #include "stringpool.h"
 #include "attribs.h"
+#include "feshim.h"
 
 
 using namespace CheckerGccPlugins;
@@ -190,10 +191,10 @@ const char* type_name (tree t)
 {
   unsigned int save = flag_sanitize;
   flag_sanitize = 0;
-  const char* ret = type_as_string (t,
-                                    TFF_PLAIN_IDENTIFIER +
-                                    //TFF_UNQUALIFIED_NAME +
-                                    TFF_NO_OMIT_DEFAULT_TEMPLATE_ARGUMENTS);
+  const char* ret = CheckerGccPlugins::type_as_string (t,
+                                                       TFF_PLAIN_IDENTIFIER +
+                                                       //TFF_UNQUALIFIED_NAME +
+                                                       TFF_NO_OMIT_DEFAULT_TEMPLATE_ARGUMENTS);
   flag_sanitize = save;
   return ret;
 }
@@ -319,10 +320,10 @@ bool is_in_std (tree decl_or_type)
 // Is TYPE a mutex type?
 bool is_mutex (tree type)
 {
-  const char* name = type_as_string (type,
-                                     TFF_PLAIN_IDENTIFIER +
-                                     TFF_SCOPE +
-                                     TFF_CHASE_TYPEDEF);
+  const char* name = CheckerGccPlugins::type_as_string (type,
+                                                        TFF_PLAIN_IDENTIFIER +
+                                                        TFF_SCOPE +
+                                                        TFF_CHASE_TYPEDEF);
   if (strcmp (name, "std::mutex") == 0) return true;
   if (strcmp (name, "std::shared_mutex") == 0) return true;
   if (strcmp (name, "std::shared_timed_mutex") == 0) return true;
@@ -349,10 +350,10 @@ bool is_mutex_maybearr (tree type)
 bool is_atomic (tree type)
 {
   if (TREE_CODE (type) != RECORD_TYPE) return false;
-  const char* name = type_as_string (type,
-                                     TFF_PLAIN_IDENTIFIER +
-                                     TFF_SCOPE +
-                                     TFF_CHASE_TYPEDEF);
+  const char* name = CheckerGccPlugins::type_as_string (type,
+                                                        TFF_PLAIN_IDENTIFIER +
+                                                        TFF_SCOPE +
+                                                        TFF_CHASE_TYPEDEF);
   if (strncmp (name, "const ", 6) == 0)
     name += 6;
 
@@ -400,7 +401,9 @@ bool is_atomic_maybearr (tree type)
 // True if the first argument of FNDECL is a TBuffer pointer or reference..
 bool has_tbuffer_arg (tree fndecl)
 {
-  tree args = FUNCTION_FIRST_USER_PARMTYPE (fndecl);
+  //tree args = FUNCTION_FIRST_USER_PARMTYPE (fndecl);
+  tree args = CheckerGccPlugins::skip_artificial_parms_for
+    (fndecl, TYPE_ARG_TYPES (TREE_TYPE (fndecl)));
   if (!args) return false;
   tree arg = TREE_VALUE (args);
   if (!arg) return false;
@@ -419,10 +422,10 @@ bool has_tbuffer_arg (tree fndecl)
 // Is TYPE a thread-local type?
 bool is_thread_local (tree type)
 {
-  const char* name = type_as_string (type,
-                                     TFF_PLAIN_IDENTIFIER +
-                                     TFF_SCOPE +
-                                     TFF_CHASE_TYPEDEF);
+  const char* name = CheckerGccPlugins::type_as_string (type,
+                                                        TFF_PLAIN_IDENTIFIER +
+                                                        TFF_SCOPE +
+                                                        TFF_CHASE_TYPEDEF);
   if (strncmp (name, "boost::thread_specific_ptr<", 27) == 0) return true;
   return false;
 }
@@ -523,7 +526,7 @@ bool is_service (tree typ)
   std::string bname;
   tree binfo = TYPE_BINFO (typ);
   if (!binfo) return false;
-  if (dfs_walk_all (binfo, service_test, nullptr, &bname) != nullptr) {
+  if (CheckerGccPlugins::dfs_walk_all (binfo, service_test, nullptr, &bname) != nullptr) {
     if (bname == "IInterface") {
       std::string typ_name = type_name (typ);
       return endswith (typ_name.c_str(), "Svc");
@@ -2022,7 +2025,7 @@ void find_overridden_functions_r (tree type,
                                   tree fndecl,
                                   std::vector<tree>& basedecls)
 {
-  tree fn = look_for_overrides_here (type, fndecl);
+  tree fn = CheckerGccPlugins::look_for_overrides_here (type, fndecl);
   if (fn) {
     basedecls.push_back (fn);
     return;
diff --git a/External/CheckerGccPlugins/src/usingns_plugin.cxx b/External/CheckerGccPlugins/src/usingns_plugin.cxx
index 09f8514f..3d03bdef 100644
--- a/External/CheckerGccPlugins/src/usingns_plugin.cxx
+++ b/External/CheckerGccPlugins/src/usingns_plugin.cxx
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration
+ * Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
  *
  * @file CheckerGccPlugins/src/usingns_plugin.cxx
  * @author scott snyder <snyder@bnl.gov>
@@ -45,6 +45,7 @@
 #include "tree-phinodes.h"
 #include "gimple-ssa.h"
 #include "ssa-iterators.h"
+#include "feshim.h"
 
 
 #if GCC_VERSION < 12000
@@ -84,7 +85,7 @@ std::vector<location_t> global_using_decls;
 void handle_using_decl (tree /*decl*/)
 {
   // Only warn about declarations in the global namespace.
-  if (current_namespace == global_namespace)
+  if (CheckerGccPlugins::get_current_namespace() == global_namespace)
   {
     // Give a warning now if this decl was from a header file.
     // nb. DECL_SOURCE_LOCATION(decl) is not reliable.
@@ -140,7 +141,7 @@ std::vector<location_t> global_using_stmts;
 void handle_using_stmt (tree stmt)
 {
   // Only warn if we're in the global namespace.
-  if (current_namespace != global_namespace) return;
+  if (CheckerGccPlugins::get_current_namespace() != global_namespace) return;
   if (current_function_decl) return;
 
   // Give a warning now if we're in a header file.
-- 
GitLab