fix: add py::mod_gil_used() spelling, support pedantic tests (#5797)

* tests: add linking warnings/error

Signed-off-by: Henry Schreiner <henryschreineriii@gmail.com>

* tests: check pedantic C++14

* fix: some pedantic warnings

Signed-off-by: Henry Schreiner <henryschreineriii@gmail.com>

* feat: add py::mod_gil_used()

Signed-off-by: Henry Schreiner <henryschreineriii@gmail.com>

* fix: use not_supported()

Signed-off-by: Henry Schreiner <henryschreineriii@gmail.com>

* style: pre-commit fixes

* Update CMakeLists.txt

* fix: remove the true/false parameter from mod_gil_not_used

Signed-off-by: Henry Schreiner <henryschreineriii@gmail.com>

* style: pre-commit fixes

* Update tests/CMakeLists.txt

* fix: deprecate mod_gil_not_used(bool) instead of removing it

Keep the bool constructor public and mark it deprecated, so existing
code that spells mod_gil_not_used(false) still compiles. mod_gil_used()
now sets the flag through its friendship, which keeps the deprecated
constructor the only bool overload and stops pybind11 warning against
itself.

Also use the py:: alias in exo_planet_pybind11.cpp to match its sibling
home_planet_very_lonely_traveler.cpp.

Assisted-by: ClaudeCode:claude-opus-5

* fix: add trailing comma to macros picked up in rebase

test_smart_ptr.cpp and standalone_enum_module.cpp came from master after
this branch was written, so they still invoked variadic macros with no
variadic argument. That is a pedantic error below C++20.

Assisted-by: ClaudeCode:claude-opus-5

---------

Signed-off-by: Henry Schreiner <henryschreineriii@gmail.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
diff --git a/include/pybind11/pybind11.h b/include/pybind11/pybind11.h
index ccd7bae..e41076d 100644
--- a/include/pybind11/pybind11.h
+++ b/include/pybind11/pybind11.h
@@ -1461,13 +1461,24 @@
 // Use to activate Py_MOD_GIL_NOT_USED.
 class mod_gil_not_used {
 public:
-    explicit mod_gil_not_used(bool flag = true) : flag_(flag) {}
+    mod_gil_not_used() : flag_(true) {}
+    PYBIND11_DEPRECATED("use py::mod_gil_not_used() or py::mod_gil_used() instead")
+    explicit mod_gil_not_used(bool flag) : flag_(flag) {}
     bool flag() const { return flag_; }
 
+    friend mod_gil_not_used mod_gil_used();
+
 private:
     bool flag_;
 };
 
+// Use to activate Py_MOD_GIL_USED, the current default.
+inline mod_gil_not_used mod_gil_used() {
+    mod_gil_not_used tag;
+    tag.flag_ = false;
+    return tag;
+}
+
 class multiple_interpreters {
 public:
     enum class level {
@@ -1735,8 +1746,7 @@
     static module_ create_extension_module(const char *name,
                                            const char *doc,
                                            PyModuleDef *def,
-                                           mod_gil_not_used gil_not_used
-                                           = mod_gil_not_used(false)) {
+                                           mod_gil_not_used gil_not_used = mod_gil_used()) {
         // Placement new (not an allocation).
         new (def) PyModuleDef{/* m_base */ PyModuleDef_HEAD_INIT,
                               /* m_name */ name,
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index fc08a90..d6415b9 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -419,14 +419,12 @@
       ${target_name}
       PRIVATE -Wall
               -Wextra
+              -Wpedantic
               -Wconversion
               -Wcast-qual
               -Wdeprecated
               -Wundef
               -Wnon-virtual-dtor)
-    if(DEFINED CMAKE_CXX_STANDARD AND NOT CMAKE_CXX_STANDARD VERSION_LESS 20)
-      target_compile_options(${target_name} PRIVATE -Wpedantic)
-    endif()
   endif()
 
   if(PYBIND11_WERROR)
diff --git a/tests/exo_planet_pybind11.cpp b/tests/exo_planet_pybind11.cpp
index 9d1a2b8..cff21f0 100644
--- a/tests/exo_planet_pybind11.cpp
+++ b/tests/exo_planet_pybind11.cpp
@@ -10,7 +10,7 @@
 namespace pybind11_tests {
 namespace test_cpp_conduit {
 
-PYBIND11_MODULE(exo_planet_pybind11, m) {
+PYBIND11_MODULE(exo_planet_pybind11, m, py::mod_gil_used()) {
     wrap_traveler(m);
     m.def("wrap_very_lonely_traveler", [m]() { wrap_very_lonely_traveler(m); });
 }
diff --git a/tests/extra_setuptools/test_setuphelper.py b/tests/extra_setuptools/test_setuphelper.py
index 2c069ad..22c0c76 100644
--- a/tests/extra_setuptools/test_setuphelper.py
+++ b/tests/extra_setuptools/test_setuphelper.py
@@ -65,7 +65,7 @@
             int f(int x) {
                 return x * 3;
             }
-            PYBIND11_MODULE(simple_setup, m) {
+            PYBIND11_MODULE(simple_setup, m, pybind11::mod_gil_used()) {
                 m.def("f", &f);
             }
             """
diff --git a/tests/home_planet_very_lonely_traveler.cpp b/tests/home_planet_very_lonely_traveler.cpp
index 78d50cf..2a9fc44 100644
--- a/tests/home_planet_very_lonely_traveler.cpp
+++ b/tests/home_planet_very_lonely_traveler.cpp
@@ -5,7 +5,7 @@
 namespace pybind11_tests {
 namespace test_cpp_conduit {
 
-PYBIND11_MODULE(home_planet_very_lonely_traveler, m) {
+PYBIND11_MODULE(home_planet_very_lonely_traveler, m, py::mod_gil_used()) {
     m.def("wrap_very_lonely_traveler", [m]() { wrap_very_lonely_traveler(m); });
 }
 
diff --git a/tests/standalone_enum_module.cpp b/tests/standalone_enum_module.cpp
index 7e917b9..a626986 100644
--- a/tests/standalone_enum_module.cpp
+++ b/tests/standalone_enum_module.cpp
@@ -8,6 +8,6 @@
 
 using namespace standalone_enum_module_ns;
 
-PYBIND11_MODULE(standalone_enum_module, m) { // Added in PR #6015
+PYBIND11_MODULE(standalone_enum_module, m, pybind11::mod_gil_used()) { // Added in PR #6015
     pybind11::enum_<SomeEnum> some_enum_wrapper(m, "SomeEnum");
 }
diff --git a/tests/test_class_sh_trampoline_shared_ptr_cpp_arg.cpp b/tests/test_class_sh_trampoline_shared_ptr_cpp_arg.cpp
index 6936379..b80f3b4 100644
--- a/tests/test_class_sh_trampoline_shared_ptr_cpp_arg.cpp
+++ b/tests/test_class_sh_trampoline_shared_ptr_cpp_arg.cpp
@@ -30,7 +30,7 @@
 
 struct PySpBase : SpBase, py::trampoline_self_life_support {
     using SpBase::SpBase;
-    bool is_base_used() override { PYBIND11_OVERRIDE(bool, SpBase, is_base_used); }
+    bool is_base_used() override { PYBIND11_OVERRIDE(bool, SpBase, is_base_used, ); }
 };
 
 struct SpBaseTester {
diff --git a/tests/test_class_sh_trampoline_unique_ptr.cpp b/tests/test_class_sh_trampoline_unique_ptr.cpp
index debe332..0aeeaa9 100644
--- a/tests/test_class_sh_trampoline_unique_ptr.cpp
+++ b/tests/test_class_sh_trampoline_unique_ptr.cpp
@@ -39,10 +39,10 @@
 class PyClass : public Class, public py::trampoline_self_life_support {
 public:
     std::unique_ptr<Class> clone() const override {
-        PYBIND11_OVERRIDE_PURE(std::unique_ptr<Class>, Class, clone);
+        PYBIND11_OVERRIDE_PURE(std::unique_ptr<Class>, Class, clone, );
     }
 
-    int foo() const override { PYBIND11_OVERRIDE_PURE(int, Class, foo); }
+    int foo() const override { PYBIND11_OVERRIDE_PURE(int, Class, foo, ); }
 };
 
 } // namespace class_sh_trampoline_unique_ptr
diff --git a/tests/test_class_sh_virtual_py_cpp_mix.cpp b/tests/test_class_sh_virtual_py_cpp_mix.cpp
index df8af19..8b8c2b1 100644
--- a/tests/test_class_sh_virtual_py_cpp_mix.cpp
+++ b/tests/test_class_sh_virtual_py_cpp_mix.cpp
@@ -32,13 +32,13 @@
 struct BaseVirtualOverrider : Base, py::trampoline_self_life_support {
     using Base::Base;
 
-    int get() const override { PYBIND11_OVERRIDE(int, Base, get); }
+    int get() const override { PYBIND11_OVERRIDE(int, Base, get, ); }
 };
 
 struct CppDerivedVirtualOverrider : CppDerived, py::trampoline_self_life_support {
     using CppDerived::CppDerived;
 
-    int get() const override { PYBIND11_OVERRIDE(int, CppDerived, get); }
+    int get() const override { PYBIND11_OVERRIDE(int, CppDerived, get, ); }
 };
 
 } // namespace class_sh_virtual_py_cpp_mix
diff --git a/tests/test_cmake_build/embed.cpp b/tests/test_cmake_build/embed.cpp
index 30bc4f1..dabe03a 100644
--- a/tests/test_cmake_build/embed.cpp
+++ b/tests/test_cmake_build/embed.cpp
@@ -1,7 +1,9 @@
 #include <pybind11/embed.h>
+#include <pybind11/pybind11.h>
+
 namespace py = pybind11;
 
-PYBIND11_EMBEDDED_MODULE(test_cmake_build, m) {
+PYBIND11_EMBEDDED_MODULE(test_cmake_build, m, py::multiple_interpreters::not_supported()) {
     m.def("add", [](int i, int j) { return i + j; });
 }
 
diff --git a/tests/test_cross_module_rtti/bindings.cpp b/tests/test_cross_module_rtti/bindings.cpp
index 94fa687..4bd7d37 100644
--- a/tests/test_cross_module_rtti/bindings.cpp
+++ b/tests/test_cross_module_rtti/bindings.cpp
@@ -5,10 +5,10 @@
 class BaseTrampoline : public lib::Base, public pybind11::trampoline_self_life_support {
 public:
     using lib::Base::Base;
-    int get() const override { PYBIND11_OVERLOAD(int, lib::Base, get); }
+    int get() const override { PYBIND11_OVERLOAD(int, lib::Base, get, ); }
 };
 
-PYBIND11_MODULE(test_cross_module_rtti_bindings, m) {
+PYBIND11_MODULE(test_cross_module_rtti_bindings, m, pybind11::mod_gil_used()) {
     pybind11::classh<lib::Base, BaseTrampoline>(m, "Base")
         .def(pybind11::init<int, int>())
         .def_readwrite("a", &lib::Base::a)
diff --git a/tests/test_potentially_slicing_weak_ptr.cpp b/tests/test_potentially_slicing_weak_ptr.cpp
index c1bf36f..70c1512 100644
--- a/tests/test_potentially_slicing_weak_ptr.cpp
+++ b/tests/test_potentially_slicing_weak_ptr.cpp
@@ -58,12 +58,12 @@
 
 struct PyVirtBaseSH : VirtBaseSH, py::trampoline_self_life_support, trampoline_is_alive_simple {
     using VirtBaseSH::VirtBaseSH;
-    int get_code() override { PYBIND11_OVERRIDE(int, VirtBaseSH, get_code); }
+    int get_code() override { PYBIND11_OVERRIDE(int, VirtBaseSH, get_code, ); }
 };
 
 struct PyVirtBaseSP : VirtBaseSP, trampoline_is_alive_simple { // self-life-support not available
     using VirtBaseSP::VirtBaseSP;
-    int get_code() override { PYBIND11_OVERRIDE(int, VirtBaseSP, get_code); }
+    int get_code() override { PYBIND11_OVERRIDE(int, VirtBaseSP, get_code, ); }
 };
 
 template <typename VB>
diff --git a/tests/test_smart_ptr.cpp b/tests/test_smart_ptr.cpp
index 1409089..10f6843 100644
--- a/tests/test_smart_ptr.cpp
+++ b/tests/test_smart_ptr.cpp
@@ -370,13 +370,13 @@
 // Make pybind aware of the ref-counted wrapper type (s):
 PYBIND11_DECLARE_HOLDER_TYPE(T, ref<T>, true)
 PYBIND11_DECLARE_HOLDER_TYPE(T, const_only_shared_ptr<T>, true)
-PYBIND11_DECLARE_HOLDER_TYPE(T, shared_ptr_as_custom_holder<T>)
+PYBIND11_DECLARE_HOLDER_TYPE(T, shared_ptr_as_custom_holder<T>, )
 // The following is not required anymore for std::shared_ptr, but it should compile without error:
-PYBIND11_DECLARE_HOLDER_TYPE(T, std::shared_ptr<T>)
-PYBIND11_DECLARE_HOLDER_TYPE(T, huge_unique_ptr<T>)
-PYBIND11_DECLARE_HOLDER_TYPE(T, custom_unique_ptr<T>)
-PYBIND11_DECLARE_HOLDER_TYPE(T, shared_ptr_with_addressof_operator<T>)
-PYBIND11_DECLARE_HOLDER_TYPE(T, unique_ptr_with_addressof_operator<T>)
+PYBIND11_DECLARE_HOLDER_TYPE(T, std::shared_ptr<T>, )
+PYBIND11_DECLARE_HOLDER_TYPE(T, huge_unique_ptr<T>, )
+PYBIND11_DECLARE_HOLDER_TYPE(T, custom_unique_ptr<T>, )
+PYBIND11_DECLARE_HOLDER_TYPE(T, shared_ptr_with_addressof_operator<T>, )
+PYBIND11_DECLARE_HOLDER_TYPE(T, unique_ptr_with_addressof_operator<T>, )
 
 namespace holder_caster_traits_test {
 struct example_base {};
diff --git a/tests/test_virtual_functions.cpp b/tests/test_virtual_functions.cpp
index 78a4fdf..3a9a1f1 100644
--- a/tests/test_virtual_functions.cpp
+++ b/tests/test_virtual_functions.cpp
@@ -219,7 +219,7 @@
 };
 
 class test_override_cache_helper_trampoline : public test_override_cache_helper {
-    int func() override { PYBIND11_OVERRIDE(int, test_override_cache_helper, func); }
+    int func() override { PYBIND11_OVERRIDE(int, test_override_cache_helper, func, ); }
 };
 
 inline int test_override_cache(std::shared_ptr<test_override_cache_helper> const &instance) {
@@ -279,7 +279,7 @@
             py::print("PyA.f()");
             // This convolution just gives a `void`, but tests that PYBIND11_TYPE() works to
             // protect a type containing a ,
-            PYBIND11_OVERRIDE(PYBIND11_TYPE(typename std::enable_if<true, void>::type), A, f);
+            PYBIND11_OVERRIDE(PYBIND11_TYPE(typename std::enable_if<true, void>::type), A, f, );
         }
     };
 
@@ -302,7 +302,7 @@
         ~PyA2() override { py::print("PyA2.~PyA2()"); }
         void f() override {
             py::print("PyA2.f()");
-            PYBIND11_OVERRIDE(void, A2, f);
+            PYBIND11_OVERRIDE(void, A2, f, );
         }
     };
 
@@ -370,26 +370,26 @@
     public:
         using OverrideTest::OverrideTest;
         std::string str_value() override {
-            PYBIND11_OVERRIDE(std::string, OverrideTest, str_value);
+            PYBIND11_OVERRIDE(std::string, OverrideTest, str_value, );
         }
         // Not allowed (enabling the below should hit a static_assert failure): we can't get a
         // reference to a python numeric value, since we only copy values in the numeric type
         // caster:
 #ifdef PYBIND11_NEVER_DEFINED_EVER
         std::string &str_ref() override {
-            PYBIND11_OVERRIDE(std::string &, OverrideTest, str_ref);
+            PYBIND11_OVERRIDE(std::string &, OverrideTest, str_ref, );
         }
 #endif
         // But we can work around it like this:
     private:
         std::string _tmp;
-        std::string str_ref_helper() { PYBIND11_OVERRIDE(std::string, OverrideTest, str_ref); }
+        std::string str_ref_helper() { PYBIND11_OVERRIDE(std::string, OverrideTest, str_ref, ); }
 
     public:
         std::string &str_ref() override { return _tmp = str_ref_helper(); }
 
-        A A_value() override { PYBIND11_OVERRIDE(A, OverrideTest, A_value); }
-        A &A_ref() override { PYBIND11_OVERRIDE(A &, OverrideTest, A_ref); }
+        A A_value() override { PYBIND11_OVERRIDE(A, OverrideTest, A_value, ); }
+        A &A_ref() override { PYBIND11_OVERRIDE(A &, OverrideTest, A_ref, ); }
     };
 
     py::class_<OverrideTest::A>(m, "OverrideTest_A")
diff --git a/tests/test_with_catch/test_interpreter.cpp b/tests/test_with_catch/test_interpreter.cpp
index daa1041..6010a41 100644
--- a/tests/test_with_catch/test_interpreter.cpp
+++ b/tests/test_with_catch/test_interpreter.cpp
@@ -1,5 +1,6 @@
 #include <pybind11/critical_section.h>
 #include <pybind11/embed.h>
+#include <pybind11/pybind11.h>
 
 // Silence MSVC C++17 deprecation warning from Catch regarding std::uncaught_exceptions (up to
 // catch 2.0.1; this should be fixed in the next catch release after 2.0.1).
@@ -47,8 +48,8 @@
 class PyWidget final : public Widget {
     using Widget::Widget;
 
-    int the_answer() const override { PYBIND11_OVERRIDE_PURE(int, Widget, the_answer); }
-    std::string argv0() const override { PYBIND11_OVERRIDE_PURE(std::string, Widget, argv0); }
+    int the_answer() const override { PYBIND11_OVERRIDE_PURE(int, Widget, the_answer, ); }
+    std::string argv0() const override { PYBIND11_OVERRIDE_PURE(std::string, Widget, argv0, ); }
 };
 
 class test_override_cache_helper {
@@ -64,7 +65,7 @@
 };
 
 class test_override_cache_helper_trampoline : public test_override_cache_helper {
-    int func() override { PYBIND11_OVERRIDE(int, test_override_cache_helper, func); }
+    int func() override { PYBIND11_OVERRIDE(int, test_override_cache_helper, func, ); }
 };
 
 PYBIND11_EMBEDDED_MODULE(widget_module, m, py::multiple_interpreters::per_interpreter_gil()) {
@@ -78,7 +79,7 @@
     sub.def("add", [](int i, int j) { return i + j; });
 }
 
-PYBIND11_EMBEDDED_MODULE(trampoline_module, m) {
+PYBIND11_EMBEDDED_MODULE(trampoline_module, m, py::multiple_interpreters::not_supported()) {
     py::class_<test_override_cache_helper,
                test_override_cache_helper_trampoline,
                std::shared_ptr<test_override_cache_helper>>(m, "test_override_cache_helper")
@@ -94,9 +95,11 @@
         .value("value2", SomeEnum::value2);
 }
 
-PYBIND11_EMBEDDED_MODULE(throw_exception, ) { throw std::runtime_error("C++ Error"); }
+PYBIND11_EMBEDDED_MODULE(throw_exception, , py::multiple_interpreters::not_supported()) {
+    throw std::runtime_error("C++ Error");
+}
 
-PYBIND11_EMBEDDED_MODULE(throw_error_already_set, ) {
+PYBIND11_EMBEDDED_MODULE(throw_error_already_set, , py::multiple_interpreters::not_supported()) {
     auto d = py::dict();
     d["missing"].cast<py::object>();
 }