diff --git a/doc/example/limitations_const_parameter_warning.cpp b/doc/example/limitations_const_parameter_warning.cpp index 8f0de3bc..942264b9 100644 --- a/doc/example/limitations_const_parameter_warning.cpp +++ b/doc/example/limitations_const_parameter_warning.cpp @@ -24,7 +24,7 @@ namespace limitations_const_parameter_warning_explanation { class derived : public base { public: - virtual void method(const int); + void method(const int) override; }; void derived::method(int) {} @@ -35,7 +35,7 @@ namespace { //[ limitations_const_parameter_warning_solution MOCK_BASE_CLASS(mock_base, base) { - void method(const int i) { method_stub(i); } + void method(const int i) override { method_stub(i); } MOCK_METHOD(method_stub, 1, void(int), method) }; //] diff --git a/doc/example/motivation.cpp b/doc/example/motivation.cpp index 100e3cbc..91db1b5d 100644 --- a/doc/example/motivation.cpp +++ b/doc/example/motivation.cpp @@ -40,7 +40,7 @@ class my_view : public view { public: my_view() : called(false) {} - virtual void display(int result) + void display(int result) override { called = true; value = result; diff --git a/include/turtle/config.hpp b/include/turtle/config.hpp index 9395005c..c1f4a848 100644 --- a/include/turtle/config.hpp +++ b/include/turtle/config.hpp @@ -1,7 +1,7 @@ // http://turtle.sourceforge.net // // Copyright Mathieu Champlon 2009 -// Copyright 2020-2025 Alexander Grund +// Copyright 2020-2026 Alexander Grund // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at @@ -32,6 +32,27 @@ # endif #endif +#if defined(__clang__) && defined(__has_warning) +# define MOCK_DIAGNOSTIC_PUSH _Pragma("clang diagnostic push") +# define MOCK_DIAGNOSTIC_POP _Pragma("clang diagnostic pop") +# if __has_warning("-Wsuggest-override") +# define MOCK_DIAGNOSTIC_IGNORE_SUGGEST_OVERRIDE _Pragma("clang diagnostic ignored \"-Wsuggest-override\"") +# endif +#elif defined(__GNUC__) +# define MOCK_DIAGNOSTIC_PUSH _Pragma("GCC diagnostic push") +# define MOCK_DIAGNOSTIC_POP _Pragma("GCC diagnostic pop") +# if(__GNUC__ >= 9) +# define MOCK_DIAGNOSTIC_IGNORE_SUGGEST_OVERRIDE _Pragma("GCC diagnostic ignored \"-Wsuggest-override\"") +# endif +#endif +#ifndef MOCK_DIAGNOSTIC_PUSH +# define MOCK_DIAGNOSTIC_PUSH +# define MOCK_DIAGNOSTIC_POP +#endif +#ifndef MOCK_DIAGNOSTIC_IGNORE_SUGGEST_OVERRIDE +# define MOCK_DIAGNOSTIC_IGNORE_SUGGEST_OVERRIDE +#endif + #if BOOST_VERSION >= 107700 # define MOCK_CXX_VERSION BOOST_CXX_VERSION #elif defined(_MSC_VER) diff --git a/include/turtle/detail/function_impl.hpp b/include/turtle/detail/function_impl.hpp index c11f3862..8ad1971c 100644 --- a/include/turtle/detail/function_impl.hpp +++ b/include/turtle/detail/function_impl.hpp @@ -102,7 +102,7 @@ namespace mock { namespace detail { context_->remove(*this); } - virtual bool verify() const + bool verify() const override { lock _(mutex_); for(const auto& expectation : expectations_) @@ -120,7 +120,7 @@ namespace mock { namespace detail { return valid_; } - virtual void reset() + void reset() override { lock _(mutex_); valid_ = true; diff --git a/include/turtle/detail/invocation.hpp b/include/turtle/detail/invocation.hpp index 5b711e26..5fb974ca 100644 --- a/include/turtle/detail/invocation.hpp +++ b/include/turtle/detail/invocation.hpp @@ -44,7 +44,7 @@ namespace mock { namespace detail { throw std::invalid_argument("'min' > 'max'"); } - virtual bool invoke() + bool invoke() override { if(count_ == max_) return false; @@ -52,16 +52,16 @@ namespace mock { namespace detail { return true; } - virtual bool exhausted() const { return count_ >= max_; } + bool exhausted() const override { return count_ >= max_; } - virtual bool verify() const { return min_ <= count_ && count_ <= max_; } + bool verify() const override { return min_ <= count_ && count_ <= max_; } protected: const std::size_t min_, max_; std::size_t count_; private: - virtual std::ostream& serialize(std::ostream& s) const + std::ostream& serialize(std::ostream& s) const override { return s << "between( " << count_ << "/[" << min_ << ',' << max_ << "] )"; } @@ -73,7 +73,7 @@ namespace mock { namespace detail { explicit exactly(std::size_t count) : between(count, count) {} private: - virtual std::ostream& serialize(std::ostream& s) const + std::ostream& serialize(std::ostream& s) const override { return s << "exactly( " << count_ << '/' << max_ << " )"; } @@ -85,7 +85,7 @@ namespace mock { namespace detail { never() : exactly(0) {} private: - virtual std::ostream& serialize(std::ostream& s) const { return s << "never()"; } + std::ostream& serialize(std::ostream& s) const override { return s << "never()"; } }; class once : public exactly @@ -94,7 +94,7 @@ namespace mock { namespace detail { once() : exactly(1) {} private: - virtual std::ostream& serialize(std::ostream& s) const { return s << "once()"; } + std::ostream& serialize(std::ostream& s) const override { return s << "once()"; } }; class at_least : public between @@ -103,7 +103,7 @@ namespace mock { namespace detail { explicit at_least(std::size_t min) : between(min, (std::numeric_limits::max)()) {} private: - virtual std::ostream& serialize(std::ostream& s) const + std::ostream& serialize(std::ostream& s) const override { return s << "at_least( " << count_ << '/' << min_ << " )"; } @@ -115,7 +115,7 @@ namespace mock { namespace detail { explicit at_most(std::size_t max) : between(0, max) {} private: - virtual std::ostream& serialize(std::ostream& s) const + std::ostream& serialize(std::ostream& s) const override { return s << "at_most( " << count_ << '/' << max_ << " )"; } @@ -127,7 +127,7 @@ namespace mock { namespace detail { unlimited() : at_least(0) {} private: - virtual std::ostream& serialize(std::ostream& s) const { return s << "unlimited()"; } + std::ostream& serialize(std::ostream& s) const override { return s << "unlimited()"; } }; }} // namespace mock::detail diff --git a/include/turtle/detail/mock_impl.hpp b/include/turtle/detail/mock_impl.hpp index 59fe4e0f..3d478938 100644 --- a/include/turtle/detail/mock_impl.hpp +++ b/include/turtle/detail/mock_impl.hpp @@ -1,7 +1,7 @@ // http://turtle.sourceforge.net // // Copyright Mathieu Champlon 2008 -// Copyright 2022-2025 Alexander Grund +// Copyright 2022-2026 Alexander Grund // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at @@ -60,10 +60,13 @@ namespace mock { namespace detail { #define MOCK_FORWARD_PARAM(z, n, S) std::forward(p##n) #define MOCK_FORWARD_PARAMS(n, S) BOOST_PP_ENUM(n, MOCK_FORWARD_PARAM, S) #define MOCK_METHOD_AUX(name, arity, signature, identifier, qualifier) \ + MOCK_DIAGNOSTIC_PUSH \ + MOCK_DIAGNOSTIC_IGNORE_SUGGEST_OVERRIDE \ MOCK_DECL(name, arity, signature, qualifier) \ { \ return MOCK_ANONYMOUS_HELPER(identifier)(MOCK_FORWARD_PARAMS(arity, signature)); \ - } + } \ + MOCK_DIAGNOSTIC_POP #define MOCK_METHOD_EXT(name, arity, signature, identifier) \ MOCK_METHOD_AUX(name, arity, signature, identifier, ) \ diff --git a/include/turtle/detail/object_impl.hpp b/include/turtle/detail/object_impl.hpp index 081aeb26..6555245c 100644 --- a/include/turtle/detail/object_impl.hpp +++ b/include/turtle/detail/object_impl.hpp @@ -25,23 +25,23 @@ namespace mock { namespace detail { public: object_impl() : mutex_(std::make_shared()) {} - virtual void add(const void* /*p*/, - verifiable& v, - boost::unit_test::const_string instance, - boost::optional type, - boost::unit_test::const_string name) + void add(const void* /*p*/, + verifiable& v, + boost::unit_test::const_string instance, + boost::optional type, + boost::unit_test::const_string name) override { lock _(mutex_); if(children_.empty()) detail::root.add(*this); children_[&v].update(parent_, instance, type, name); } - virtual void add(verifiable& v) + void add(verifiable& v) override { lock _(mutex_); group_.add(v); } - virtual void remove(verifiable& v) + void remove(verifiable& v) override { lock _(mutex_); group_.remove(v); @@ -50,7 +50,7 @@ namespace mock { namespace detail { detail::root.remove(*this); } - virtual void serialize(std::ostream& s, const verifiable& v) const + void serialize(std::ostream& s, const verifiable& v) const override { lock _(mutex_); const auto it = children_.find(&v); @@ -60,12 +60,12 @@ namespace mock { namespace detail { s << "?"; } - virtual bool verify() const + bool verify() const override { lock _(mutex_); return group_.verify(); } - virtual void reset() + void reset() override { lock _(mutex_); std::shared_ptr guard = shared_from_this(); diff --git a/include/turtle/detail/root.hpp b/include/turtle/detail/root.hpp index 664ce0ae..adf9321d 100644 --- a/include/turtle/detail/root.hpp +++ b/include/turtle/detail/root.hpp @@ -24,11 +24,11 @@ namespace mock { namespace detail { class root_t : public singleton, public context { public: - virtual void add(const void* p, - verifiable& v, - boost::unit_test::const_string instance, - boost::optional type, - boost::unit_test::const_string name) + void add(const void* p, + verifiable& v, + boost::unit_test::const_string instance, + boost::optional type, + boost::unit_test::const_string name) override { scoped_lock _(mutex_); auto it = children_.lower_bound(&v); @@ -36,13 +36,13 @@ namespace mock { namespace detail { it = children_.insert(it, std::make_pair(&v, counter_child(parents_, p))); it->second.update(instance, type, name); } - virtual void add(verifiable& v) + void add(verifiable& v) override { scoped_lock _(mutex_); group_.add(v); } - virtual void remove(verifiable& v) + void remove(verifiable& v) override { scoped_lock _(mutex_); group_.remove(v); @@ -60,7 +60,7 @@ namespace mock { namespace detail { group_.reset(); } - virtual void serialize(std::ostream& s, const verifiable& v) const + void serialize(std::ostream& s, const verifiable& v) const override { scoped_lock _(mutex_); const auto it = children_.find(&v); diff --git a/include/turtle/stream.hpp b/include/turtle/stream.hpp index 979e6a75..b1bccdff 100644 --- a/include/turtle/stream.hpp +++ b/include/turtle/stream.hpp @@ -46,7 +46,7 @@ namespace detail { namespace conversion { struct holder_imp : holder { explicit holder_imp(const T& t) : t_(t) {} - virtual void serialize(std::ostream& s) const + void serialize(std::ostream& s) const override { // if an error about an ambiguous conversion is generated by the // line below the solution is to add a serialization operator to a diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 486fdb7f..0a121714 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright 2019 Alexander Grund +# Copyright 2019-2026 Alexander Grund # Distributed under the Boost Software License, Version 1.0. # See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt @@ -16,6 +16,14 @@ option(TURTLE_WERROR "Treat warnings as errors" ON) if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") target_compile_options(TurtleTestMain INTERFACE -Wall -Wextra -pedantic) include(CheckCXXCompilerFlag) + # Common warning to check for consistent use of override/final + check_cxx_compiler_flag(-Wsuggest-override TURTLE_CXX_SUGGEST_OVERRIDE) + if(TURTLE_CXX_SUGGEST_OVERRIDE) + # Prior to GCC 9.2 "final" was not considered "override" + if(NOT (CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 9.2)) + target_compile_options(TurtleTestMain INTERFACE -Wsuggest-override) + endif() + endif() check_cxx_compiler_flag(-Wunused-function TURTLE_CXX_UNUSED_FUNCTION) if(TURTLE_CXX_UNUSED_FUNCTION) target_compile_options(TurtleTestMain INTERFACE -Wno-unused-function) diff --git a/test/detail/test_function.cpp b/test/detail/test_function.cpp index 59ed3330..5fc72fe8 100644 --- a/test/detail/test_function.cpp +++ b/test/detail/test_function.cpp @@ -392,7 +392,7 @@ class my_interface }; class my_implementation : public my_interface { - virtual void my_method() {} + virtual void my_method() override {} }; } // namespace @@ -591,7 +591,7 @@ struct base }; struct derived : base { - virtual void f() {} + virtual void f() override {} }; } // namespace