From ba33b2fc798418c8c9dfe801c5b9023d3703f417 Mon Sep 17 00:00:00 2001 From: Francesco Biscani Date: Mon, 20 Nov 2017 14:19:53 +0100 Subject: [PATCH] Add -Wdeprecated to test suite and fix associated warnings (#1191) This commit turns on `-Wdeprecated` in the test suite and fixes several associated deprecation warnings that show up as a result: - in C++17 `static constexpr` members are implicitly inline; our redeclaration (needed for C++11/14) is deprecated in C++17. - various test suite classes have destructors and rely on implicit copy constructors, but implicit copy constructor definitions when a user-declared destructor is present was deprecated in C++11. - Eigen also has various implicit copy constructors, so just disable `-Wdeprecated` in `eigen.h`. --- include/pybind11/complex.h | 4 ++++ include/pybind11/detail/common.h | 4 ++++ include/pybind11/eigen.h | 5 +++++ include/pybind11/pytypes.h | 3 +++ tests/CMakeLists.txt | 2 +- tests/test_call_policies.cpp | 2 ++ tests/test_class.cpp | 10 +++++++++- tests/test_constants_and_functions.cpp | 14 ++++++++++++++ tests/test_factory_constructors.cpp | 1 + tests/test_multiple_inheritance.cpp | 6 +++--- tests/test_smart_ptr.cpp | 4 ++++ 11 files changed, 50 insertions(+), 5 deletions(-) diff --git a/include/pybind11/complex.h b/include/pybind11/complex.h index 5dac27cc..3f896385 100644 --- a/include/pybind11/complex.h +++ b/include/pybind11/complex.h @@ -25,9 +25,13 @@ template struct format_descriptor, detail::enable_i static std::string format() { return std::string(value); } }; +#ifndef PYBIND11_CPP17 + template constexpr const char format_descriptor< std::complex, detail::enable_if_t::value>>::value[3]; +#endif + NAMESPACE_BEGIN(detail) template struct is_fmt_numeric, detail::enable_if_t::value>> { diff --git a/include/pybind11/detail/common.h b/include/pybind11/detail/common.h index 1da36bf3..7692063a 100644 --- a/include/pybind11/detail/common.h +++ b/include/pybind11/detail/common.h @@ -704,9 +704,13 @@ template struct format_descriptor constexpr const char format_descriptor< T, detail::enable_if_t::value>>::value[2]; +#endif + /// RAII wrapper that temporarily clears any Python error state struct error_scope { PyObject *type, *value, *trace; diff --git a/include/pybind11/eigen.h b/include/pybind11/eigen.h index 2a234cef..e8b4249a 100644 --- a/include/pybind11/eigen.h +++ b/include/pybind11/eigen.h @@ -17,6 +17,11 @@ # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Wconversion" # pragma GCC diagnostic ignored "-Wdeprecated-declarations" +# ifdef __clang__ +// Eigen generates a bunch of implicit-copy-constructor-is-deprecated warnings with -Wdeprecated +// under Clang, so disable that warning here: +# pragma GCC diagnostic ignored "-Wdeprecated" +# endif # if __GNUC__ >= 7 # pragma GCC diagnostic ignored "-Wint-in-bool-context" # endif diff --git a/include/pybind11/pytypes.h b/include/pybind11/pytypes.h index d7fa1777..bcee8b5b 100644 --- a/include/pybind11/pytypes.h +++ b/include/pybind11/pytypes.h @@ -295,6 +295,9 @@ public: PyErr_Fetch(&type.ptr(), &value.ptr(), &trace.ptr()); } + error_already_set(const error_already_set &) = default; + error_already_set(error_already_set &&) = default; + inline ~error_already_set(); /// Give the currently-held error back to Python, if any. If there is currently a Python error diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 5953e0ba..8f2f300e 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -124,7 +124,7 @@ function(pybind11_enable_warnings target_name) if(MSVC) target_compile_options(${target_name} PRIVATE /W4) else() - target_compile_options(${target_name} PRIVATE -Wall -Wextra -Wconversion -Wcast-qual) + target_compile_options(${target_name} PRIVATE -Wall -Wextra -Wconversion -Wcast-qual -Wdeprecated) endif() if(PYBIND11_WERROR) diff --git a/tests/test_call_policies.cpp b/tests/test_call_policies.cpp index 8642188f..fd245578 100644 --- a/tests/test_call_policies.cpp +++ b/tests/test_call_policies.cpp @@ -36,6 +36,8 @@ TEST_SUBMODULE(call_policies, m) { class Child { public: Child() { py::print("Allocating child."); } + Child(const Child &) = default; + Child(Child &&) = default; ~Child() { py::print("Releasing child."); } }; py::class_(m, "Child") diff --git a/tests/test_class.cpp b/tests/test_class.cpp index 927adf3f..57db3ab7 100644 --- a/tests/test_class.cpp +++ b/tests/test_class.cpp @@ -14,6 +14,9 @@ TEST_SUBMODULE(class_, m) { // test_instance struct NoConstructor { + NoConstructor() = default; + NoConstructor(const NoConstructor &) = default; + NoConstructor(NoConstructor &&) = default; static NoConstructor *new_instance() { auto *ptr = new NoConstructor(); print_created(ptr, "via new_instance"); @@ -82,7 +85,12 @@ TEST_SUBMODULE(class_, m) { m.def("dog_bark", [](const Dog &dog) { return dog.bark(); }); // test_automatic_upcasting - struct BaseClass { virtual ~BaseClass() {} }; + struct BaseClass { + BaseClass() = default; + BaseClass(const BaseClass &) = default; + BaseClass(BaseClass &&) = default; + virtual ~BaseClass() {} + }; struct DerivedClass1 : BaseClass { }; struct DerivedClass2 : BaseClass { }; diff --git a/tests/test_constants_and_functions.cpp b/tests/test_constants_and_functions.cpp index 8c9ef7f6..e8ec74b7 100644 --- a/tests/test_constants_and_functions.cpp +++ b/tests/test_constants_and_functions.cpp @@ -49,7 +49,14 @@ namespace test_exc_sp { int f1(int x) noexcept { return x+1; } int f2(int x) noexcept(true) { return x+2; } int f3(int x) noexcept(false) { return x+3; } +#if defined(__GNUG__) +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wdeprecated" +#endif int f4(int x) throw() { return x+4; } // Deprecated equivalent to noexcept(true) +#if defined(__GNUG__) +# pragma GCC diagnostic pop +#endif struct C { int m1(int x) noexcept { return x-1; } int m2(int x) const noexcept { return x-2; } @@ -57,8 +64,15 @@ struct C { int m4(int x) const noexcept(true) { return x-4; } int m5(int x) noexcept(false) { return x-5; } int m6(int x) const noexcept(false) { return x-6; } +#if defined(__GNUG__) +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wdeprecated" +#endif int m7(int x) throw() { return x-7; } int m8(int x) const throw() { return x-8; } +#if defined(__GNUG__) +# pragma GCC diagnostic pop +#endif }; } diff --git a/tests/test_factory_constructors.cpp b/tests/test_factory_constructors.cpp index 687a5bf4..5cfbfdc3 100644 --- a/tests/test_factory_constructors.cpp +++ b/tests/test_factory_constructors.cpp @@ -285,6 +285,7 @@ TEST_SUBMODULE(factory_constructors, m) { // test_reallocations // Class that has verbose operator_new/operator_delete calls struct NoisyAlloc { + NoisyAlloc(const NoisyAlloc &) = default; NoisyAlloc(int i) { py::print(py::str("NoisyAlloc(int {})").format(i)); } NoisyAlloc(double d) { py::print(py::str("NoisyAlloc(double {})").format(d)); } ~NoisyAlloc() { py::print("~NoisyAlloc()"); } diff --git a/tests/test_multiple_inheritance.cpp b/tests/test_multiple_inheritance.cpp index 35f9d9c4..ba1674fb 100644 --- a/tests/test_multiple_inheritance.cpp +++ b/tests/test_multiple_inheritance.cpp @@ -130,8 +130,8 @@ TEST_SUBMODULE(multiple_inheritance, m) { // test_mi_unaligned_base // test_mi_base_return // Issue #801: invalid casting to derived type with MI bases - struct I801B1 { int a = 1; virtual ~I801B1() = default; }; - struct I801B2 { int b = 2; virtual ~I801B2() = default; }; + struct I801B1 { int a = 1; I801B1() = default; I801B1(const I801B1 &) = default; virtual ~I801B1() = default; }; + struct I801B2 { int b = 2; I801B2() = default; I801B2(const I801B2 &) = default; virtual ~I801B2() = default; }; struct I801C : I801B1, I801B2 {}; struct I801D : I801C {}; // Indirect MI // Unregistered classes: @@ -205,7 +205,7 @@ TEST_SUBMODULE(multiple_inheritance, m) { // test_diamond_inheritance // Issue #959: segfault when constructing diamond inheritance instance // All of these have int members so that there will be various unequal pointers involved. - struct B { int b; virtual ~B() = default; }; + struct B { int b; B() = default; B(const B&) = default; virtual ~B() = default; }; struct C0 : public virtual B { int c0; }; struct C1 : public virtual B { int c1; }; struct D : public C0, public C1 { int d; }; diff --git a/tests/test_smart_ptr.cpp b/tests/test_smart_ptr.cpp index dccb1e9b..5f298506 100644 --- a/tests/test_smart_ptr.cpp +++ b/tests/test_smart_ptr.cpp @@ -98,6 +98,7 @@ TEST_SUBMODULE(smart_ptr, m) { // Object managed by a std::shared_ptr<> class MyObject2 { public: + MyObject2(const MyObject2 &) = default; MyObject2(int value) : value(value) { print_created(this, toString()); } std::string toString() const { return "MyObject2[" + std::to_string(value) + "]"; } virtual ~MyObject2() { print_destroyed(this); } @@ -116,6 +117,7 @@ TEST_SUBMODULE(smart_ptr, m) { // Object managed by a std::shared_ptr<>, additionally derives from std::enable_shared_from_this<> class MyObject3 : public std::enable_shared_from_this { public: + MyObject3(const MyObject3 &) = default; MyObject3(int value) : value(value) { print_created(this, toString()); } std::string toString() const { return "MyObject3[" + std::to_string(value) + "]"; } virtual ~MyObject3() { print_destroyed(this); } @@ -219,6 +221,8 @@ TEST_SUBMODULE(smart_ptr, m) { // Issue #865: shared_from_this doesn't work with virtual inheritance struct SharedFromThisVBase : std::enable_shared_from_this { + SharedFromThisVBase() = default; + SharedFromThisVBase(const SharedFromThisVBase &) = default; virtual ~SharedFromThisVBase() = default; }; struct SharedFromThisVirt : virtual SharedFromThisVBase {};