From 3995deaf76d0c988d315630ace46eb01dba37174 Mon Sep 17 00:00:00 2001 From: Dale Phurrough <dale@hidale.com> Date: Sat, 28 Aug 2021 01:12:44 +0200 Subject: [PATCH] fix opencv/opencv#20544 nodiscard for msvc/gcc - includes workaround for preprocessor non-compliance - enable attribute syntax checking in msvc --- cmake/OpenCVCompilerOptions.cmake | 3 ++ modules/core/include/opencv2/core/cvdef.h | 39 ++++++++++++-- modules/core/include/opencv2/core/mat.hpp | 62 +++++++++++----------- modules/core/include/opencv2/core/matx.hpp | 14 ++--- 4 files changed, 77 insertions(+), 41 deletions(-) diff --git a/cmake/OpenCVCompilerOptions.cmake b/cmake/OpenCVCompilerOptions.cmake index 303d4f451e..d444085ea3 100644 --- a/cmake/OpenCVCompilerOptions.cmake +++ b/cmake/OpenCVCompilerOptions.cmake @@ -400,6 +400,9 @@ if(MSVC) endif() endif() + # Enable [[attribute]] syntax checking to prevent silent failure: "attribute is ignored in this syntactic position" + add_extra_compiler_option("/w15240") + if(NOT ENABLE_NOISY_WARNINGS) ocv_warnings_disable(CMAKE_CXX_FLAGS /wd4127) # conditional expression is constant ocv_warnings_disable(CMAKE_CXX_FLAGS /wd4251) # class 'std::XXX' needs to have dll-interface to be used by clients of YYY diff --git a/modules/core/include/opencv2/core/cvdef.h b/modules/core/include/opencv2/core/cvdef.h index a4b560b4e1..6011b2a931 100644 --- a/modules/core/include/opencv2/core/cvdef.h +++ b/modules/core/include/opencv2/core/cvdef.h @@ -575,14 +575,47 @@ Cv64suf; # endif #endif +/****************************************************************************************\ +* CV_NODISCARD_STD attribute (C++17) * +* encourages the compiler to issue a warning if the return value is discarded * +\****************************************************************************************/ +#ifndef CV_NODISCARD_STD +# ifndef __has_cpp_attribute +// workaround preprocessor non-compliance https://reviews.llvm.org/D57851 +# define __has_cpp_attribute(__x) 0 +# endif +# if __has_cpp_attribute(nodiscard) +# define CV_NODISCARD_STD [[nodiscard]] +# elif __cplusplus >= 201703L +// available when compiler is C++17 compliant +# define CV_NODISCARD_STD [[nodiscard]] +# elif defined(_MSC_VER) && _MSC_VER >= 1911 && _MSVC_LANG >= 201703L +// available with VS2017 v15.3+ with /std:c++17 or higher; works on functions and classes +# define CV_NODISCARD_STD [[nodiscard]] +# elif defined(__GNUC__) && (((__GNUC__ * 100) + __GNUC_MINOR__) >= 700) && (__cplusplus >= 201103L) +// available with GCC 7.0+; works on functions, works or silently fails on classes +# define CV_NODISCARD_STD [[nodiscard]] +# elif defined(__GNUC__) && (((__GNUC__ * 100) + __GNUC_MINOR__) >= 408) && (__cplusplus >= 201103L) +// available with GCC 4.8+ but it usually does nothing and can fail noisily -- therefore not used +// define CV_NODISCARD_STD [[gnu::warn_unused_result]] +# endif +#endif +#ifndef CV_NODISCARD_STD +# define CV_NODISCARD_STD /* nothing by default */ +#endif + /****************************************************************************************\ -* CV_NODISCARD attribute * -* encourages the compiler to issue a warning if the return value is discarded (C++17) * +* CV_NODISCARD attribute (deprecated, GCC only) * +* DONT USE: use instead the standard CV_NODISCARD_STD macro above * +* this legacy method silently fails to issue warning until some version * +* after gcc 6.3.0. Yet with gcc 7+ you can use the above standard method * +* which makes this method useless. Don't use it. * +* @deprecated use instead CV_NODISCARD_STD * \****************************************************************************************/ #ifndef CV_NODISCARD # if defined(__GNUC__) -# define CV_NODISCARD __attribute__((__warn_unused_result__)) // at least available with GCC 3.4 +# define CV_NODISCARD __attribute__((__warn_unused_result__)) # elif defined(__clang__) && defined(__has_attribute) # if __has_attribute(__warn_unused_result__) # define CV_NODISCARD __attribute__((__warn_unused_result__)) diff --git a/modules/core/include/opencv2/core/mat.hpp b/modules/core/include/opencv2/core/mat.hpp index d0ce61e123..fdcb8fc817 100644 --- a/modules/core/include/opencv2/core/mat.hpp +++ b/modules/core/include/opencv2/core/mat.hpp @@ -1204,14 +1204,14 @@ public: The method creates a square diagonal matrix from specified main diagonal. @param d One-dimensional matrix that represents the main diagonal. */ - static Mat diag(const Mat& d); + CV_NODISCARD_STD static Mat diag(const Mat& d); /** @brief Creates a full copy of the array and the underlying data. The method creates a full copy of the array. The original step[] is not taken into account. So, the array copy is a continuous array occupying total()*elemSize() bytes. */ - Mat clone() const CV_NODISCARD; + CV_NODISCARD_STD Mat clone() const; /** @brief Copies the matrix to another one. @@ -1375,20 +1375,20 @@ public: @param cols Number of columns. @param type Created matrix type. */ - static MatExpr zeros(int rows, int cols, int type); + CV_NODISCARD_STD static MatExpr zeros(int rows, int cols, int type); /** @overload @param size Alternative to the matrix size specification Size(cols, rows) . @param type Created matrix type. */ - static MatExpr zeros(Size size, int type); + CV_NODISCARD_STD static MatExpr zeros(Size size, int type); /** @overload @param ndims Array dimensionality. @param sz Array of integers specifying the array shape. @param type Created matrix type. */ - static MatExpr zeros(int ndims, const int* sz, int type); + CV_NODISCARD_STD static MatExpr zeros(int ndims, const int* sz, int type); /** @brief Returns an array of all 1's of the specified size and type. @@ -1406,20 +1406,20 @@ public: @param cols Number of columns. @param type Created matrix type. */ - static MatExpr ones(int rows, int cols, int type); + CV_NODISCARD_STD static MatExpr ones(int rows, int cols, int type); /** @overload @param size Alternative to the matrix size specification Size(cols, rows) . @param type Created matrix type. */ - static MatExpr ones(Size size, int type); + CV_NODISCARD_STD static MatExpr ones(Size size, int type); /** @overload @param ndims Array dimensionality. @param sz Array of integers specifying the array shape. @param type Created matrix type. */ - static MatExpr ones(int ndims, const int* sz, int type); + CV_NODISCARD_STD static MatExpr ones(int ndims, const int* sz, int type); /** @brief Returns an identity matrix of the specified size and type. @@ -1435,13 +1435,13 @@ public: @param cols Number of columns. @param type Created matrix type. */ - static MatExpr eye(int rows, int cols, int type); + CV_NODISCARD_STD static MatExpr eye(int rows, int cols, int type); /** @overload @param size Alternative matrix size specification as Size(cols, rows) . @param type Created matrix type. */ - static MatExpr eye(Size size, int type); + CV_NODISCARD_STD static MatExpr eye(Size size, int type); /** @brief Allocates new array data if needed. @@ -2302,7 +2302,7 @@ public: Mat_ row(int y) const; Mat_ col(int x) const; Mat_ diag(int d=0) const; - Mat_ clone() const CV_NODISCARD; + CV_NODISCARD_STD Mat_ clone() const; //! overridden forms of Mat::elemSize() etc. size_t elemSize() const; @@ -2315,14 +2315,14 @@ public: size_t stepT(int i=0) const; //! overridden forms of Mat::zeros() etc. Data type is omitted, of course - static MatExpr zeros(int rows, int cols); - static MatExpr zeros(Size size); - static MatExpr zeros(int _ndims, const int* _sizes); - static MatExpr ones(int rows, int cols); - static MatExpr ones(Size size); - static MatExpr ones(int _ndims, const int* _sizes); - static MatExpr eye(int rows, int cols); - static MatExpr eye(Size size); + CV_NODISCARD_STD static MatExpr zeros(int rows, int cols); + CV_NODISCARD_STD static MatExpr zeros(Size size); + CV_NODISCARD_STD static MatExpr zeros(int _ndims, const int* _sizes); + CV_NODISCARD_STD static MatExpr ones(int rows, int cols); + CV_NODISCARD_STD static MatExpr ones(Size size); + CV_NODISCARD_STD static MatExpr ones(int _ndims, const int* _sizes); + CV_NODISCARD_STD static MatExpr eye(int rows, int cols); + CV_NODISCARD_STD static MatExpr eye(Size size); //! some more overridden methods Mat_& adjustROI( int dtop, int dbottom, int dleft, int dright ); @@ -2469,10 +2469,10 @@ public: //! <0 - a diagonal from the lower half) UMat diag(int d=0) const; //! constructs a square diagonal matrix which main diagonal is vector "d" - static UMat diag(const UMat& d); + CV_NODISCARD_STD static UMat diag(const UMat& d); //! returns deep copy of the matrix, i.e. the data is copied - UMat clone() const CV_NODISCARD; + CV_NODISCARD_STD UMat clone() const; //! copies the matrix content to "m". // It calls m.create(this->size(), this->type()). void copyTo( OutputArray m ) const; @@ -2503,14 +2503,14 @@ public: double dot(InputArray m) const; //! Matlab-style matrix initialization - static UMat zeros(int rows, int cols, int type); - static UMat zeros(Size size, int type); - static UMat zeros(int ndims, const int* sz, int type); - static UMat ones(int rows, int cols, int type); - static UMat ones(Size size, int type); - static UMat ones(int ndims, const int* sz, int type); - static UMat eye(int rows, int cols, int type); - static UMat eye(Size size, int type); + CV_NODISCARD_STD static UMat zeros(int rows, int cols, int type); + CV_NODISCARD_STD static UMat zeros(Size size, int type); + CV_NODISCARD_STD static UMat zeros(int ndims, const int* sz, int type); + CV_NODISCARD_STD static UMat ones(int rows, int cols, int type); + CV_NODISCARD_STD static UMat ones(Size size, int type); + CV_NODISCARD_STD static UMat ones(int ndims, const int* sz, int type); + CV_NODISCARD_STD static UMat eye(int rows, int cols, int type); + CV_NODISCARD_STD static UMat eye(Size size, int type); //! allocates new matrix data unless the matrix already has specified size and type. // previous data is unreferenced if needed. @@ -2767,7 +2767,7 @@ public: SparseMat& operator = (const Mat& m); //! creates full copy of the matrix - SparseMat clone() const CV_NODISCARD; + CV_NODISCARD_STD SparseMat clone() const; //! copies all the data to the destination matrix. All the previous content of m is erased void copyTo( SparseMat& m ) const; @@ -3004,7 +3004,7 @@ public: SparseMat_& operator = (const Mat& m); //! makes full copy of the matrix. All the elements are duplicated - SparseMat_ clone() const CV_NODISCARD; + CV_NODISCARD_STD SparseMat_ clone() const; //! equivalent to cv::SparseMat::create(dims, _sizes, DataType<_Tp>::type) void create(int dims, const int* _sizes); //! converts sparse matrix to the old-style CvSparseMat. All the elements are copied diff --git a/modules/core/include/opencv2/core/matx.hpp b/modules/core/include/opencv2/core/matx.hpp index 733f675192..f25c8bce57 100644 --- a/modules/core/include/opencv2/core/matx.hpp +++ b/modules/core/include/opencv2/core/matx.hpp @@ -146,22 +146,22 @@ public: Matx(std::initializer_list<_Tp>); //!< initialize from an initializer list #endif - static Matx all(_Tp alpha); - static Matx zeros(); - static Matx ones(); - static Matx eye(); - static Matx diag(const diag_type& d); + CV_NODISCARD_STD static Matx all(_Tp alpha); + CV_NODISCARD_STD static Matx zeros(); + CV_NODISCARD_STD static Matx ones(); + CV_NODISCARD_STD static Matx eye(); + CV_NODISCARD_STD static Matx diag(const diag_type& d); /** @brief Generates uniformly distributed random numbers @param a Range boundary. @param b The other range boundary (boundaries don't have to be ordered, the lower boundary is inclusive, the upper one is exclusive). */ - static Matx randu(_Tp a, _Tp b); + CV_NODISCARD_STD static Matx randu(_Tp a, _Tp b); /** @brief Generates normally distributed random numbers @param a Mean value. @param b Standard deviation. */ - static Matx randn(_Tp a, _Tp b); + CV_NODISCARD_STD static Matx randn(_Tp a, _Tp b); //! dot product computed with the default precision _Tp dot(const Matx<_Tp, m, n>& v) const;