git: ab934769498d - main - boost-libs: make boost type_traits build with clang 21

From: Dimitry Andric <dim_at_FreeBSD.org>
Date: Thu, 01 Jan 2026 02:06:13 UTC
The branch main has been updated by dim:

URL: https://cgit.FreeBSD.org/ports/commit/?id=ab934769498d910cfb2e9e6493dd1fedc3cbc5f7

commit ab934769498d910cfb2e9e6493dd1fedc3cbc5f7
Author:     Dimitry Andric <dim@FreeBSD.org>
AuthorDate: 2025-12-31 14:13:21 +0000
Commit:     Dimitry Andric <dim@FreeBSD.org>
CommitDate: 2026-01-01 02:05:54 +0000

    boost-libs: make boost type_traits build with clang 21
    
    Recent versions of clang made -Wenum-constexpr-conversion errors into a
    hard error, as was announced several versions ago.
    
    Boost type_traits has two instances where it attempts to convert
    out-of-range enum values, leading to errors similar to:
    
        In file included from ../src/lib/dhcpsrv/csv_lease_file6.cc:9:
        In file included from ../src/lib/dhcpsrv/dhcpsrv_log.h:11:
        In file included from ../src/lib/log/macros.h:10:
        In file included from ../src/lib/log/logger.h:19:
        In file included from ../src/lib/log/log_formatter.h:19:
        In file included from /usr/local/include/boost/lexical_cast.hpp:33:
        In file included from /usr/local/include/boost/lexical_cast/try_lexical_convert.hpp:31:
        In file included from /usr/local/include/boost/lexical_cast/detail/converter_numeric.hpp:31:
        In file included from /usr/local/include/boost/type_traits/make_unsigned.hpp:14:
        /usr/local/include/boost/type_traits/is_signed.hpp:37:25: error: in-class initializer for static data member is not a constant expression
           37 |    static const no_cv_t minus_one = (static_cast<no_cv_t>(-1));
              |                         ^           ~~~~~~~~~~~~~~~~~~~~~~~~~~
        /usr/local/include/boost/type_traits/is_signed.hpp:45:60: note: in instantiation of template class 'boost::detail::is_signed_values<isc::dhcp::Lease::Type>' requested here
           45 |    BOOST_STATIC_CONSTANT(bool, value = (!(::boost::detail::is_signed_values<T>::minus_one  > boost::detail::is_signed_values<T>::zero)));
              |                                                            ^
        /usr/local/include/boost/config/detail/suffix.hpp:410:72: note: expanded from macro 'BOOST_STATIC_CONSTANT'
          410 | #     define BOOST_STATIC_CONSTANT(type, assignment) static const type assignment
              |                                                                        ^
        /usr/local/include/boost/type_traits/is_signed.hpp:74:40: note: in instantiation of template class 'boost::detail::is_signed_helper<isc::dhcp::Lease::Type>' requested here
           74 |    BOOST_STATIC_CONSTANT(bool, value = type::value);
              |                                        ^
        /usr/local/include/boost/config/detail/suffix.hpp:410:72: note: expanded from macro 'BOOST_STATIC_CONSTANT'
          410 | #     define BOOST_STATIC_CONSTANT(type, assignment) static const type assignment
              |                                                                        ^
        /usr/local/include/boost/type_traits/is_signed.hpp:79:85: note: in instantiation of template class 'boost::detail::is_signed_impl<isc::dhcp::Lease::Type>' requested here
           79 | template <class T> struct is_signed : public integral_constant<bool, boost::detail::is_signed_impl<T>::value> {};
              |                                                                                     ^
        /usr/local/include/boost/lexical_cast/detail/converter_lexical_streams.hpp:315:44: note: in instantiation of template class 'boost::is_signed<isc::dhcp::Lease::Type>' requested here
          315 |         typename boost::enable_if_c<boost::is_signed<Type>::value && !boost::is_enum<Type>::value, bool>::type
              |                                            ^
        /usr/local/include/boost/lexical_cast/detail/converter_lexical.hpp:449:67: note: while substituting deduced template arguments into function template 'stream_in' [with Type = isc::dhcp::Lease::Type]
          449 |                 -> decltype(std::declval<optimized_src_stream&>().stream_in(std::declval<lcast::exact<T>>()), optimized_src_stream{});
              |                                                                   ^
        /usr/local/include/boost/lexical_cast/detail/converter_lexical.hpp:454:46: note: while substituting explicitly-specified template arguments into function template 'detect_type'
          454 |             using from_src_stream = decltype(detect_type<Source>(1));
              |                                              ^
        /usr/local/include/boost/lexical_cast/try_lexical_convert.hpp:67:20: note: in instantiation of template class 'boost::detail::lexical_converter_impl<std::string, isc::dhcp::Lease::Type>' requested here
           67 |             return caster_type::try_convert(arg, result);
              |                    ^
        /usr/local/include/boost/lexical_cast.hpp:42:41: note: in instantiation of function template specialization 'boost::conversion::detail::try_lexical_convert<std::string, isc::dhcp::Lease::Type>' requested here
           42 |         if (!boost::conversion::detail::try_lexical_convert(arg, result)) {
              |                                         ^
        ../src/lib/util/csv_file.h:243:34: note: in instantiation of function template specialization 'boost::lexical_cast<std::string, isc::dhcp::Lease::Type>' requested here
          243 |             values_[at] = boost::lexical_cast<std::string>(value);
              |                                  ^
        ../src/lib/dhcpsrv/csv_lease_file6.cc:54:9: note: in instantiation of function template specialization 'isc::util::CSVRow::writeAt<isc::dhcp::Lease::Type>' requested here
           54 |     row.writeAt(getColumnIndex("lease_type"), lease.type_);
              |         ^
        /usr/local/include/boost/type_traits/is_signed.hpp:37:38: note: integer value -1 is outside the valid range of values [0, 3] for the enumeration type 'Type'
           37 |    static const no_cv_t minus_one = (static_cast<no_cv_t>(-1));
              |                                      ^
    
    This is while compiling net/kea, but other users of boost type traits
    may also have the same issue.
    
    There is an upstream bug report at:
    https://github.com/boostorg/type_traits/issues/202
    
    and an outstanding pull request at:
    https://github.com/boostorg/type_traits/pull/199
    
    Apply the latter as a diff, to work around the problem. Bump
    PORTREVISION to make dependents recompile.
    
    PR:             292071
    Approved by:    fluffy (maintainer)
    MFH:            2025Q4
---
 devel/boost-libs/Makefile                          |  2 +-
 .../files/patch-boost_type__traits_is__signed.hpp  | 48 ++++++++++++++++++++++
 .../patch-boost_type__traits_is__unsigned.hpp      | 42 +++++++++++++++++++
 3 files changed, 91 insertions(+), 1 deletion(-)

diff --git a/devel/boost-libs/Makefile b/devel/boost-libs/Makefile
index f09ecfa90a06..6d415f2bc288 100644
--- a/devel/boost-libs/Makefile
+++ b/devel/boost-libs/Makefile
@@ -1,5 +1,5 @@
 PORTNAME=	boost-libs
-PORTREVISION?=	1
+PORTREVISION?=	2
 
 COMMENT=	Free portable C++ libraries (without Boost.Python)
 WWW=		https://www.boost.org/
diff --git a/devel/boost-libs/files/patch-boost_type__traits_is__signed.hpp b/devel/boost-libs/files/patch-boost_type__traits_is__signed.hpp
new file mode 100644
index 000000000000..0ffb4d40bb46
--- /dev/null
+++ b/devel/boost-libs/files/patch-boost_type__traits_is__signed.hpp
@@ -0,0 +1,48 @@
+--- boost/type_traits/is_signed.hpp.orig	2025-08-06 18:49:14 UTC
++++ boost/type_traits/is_signed.hpp
+@@ -13,6 +13,7 @@
+ #include <boost/type_traits/is_integral.hpp>
+ #include <boost/type_traits/remove_cv.hpp>
+ #include <boost/type_traits/is_enum.hpp>
++#include <boost/core/underlying_type.hpp>
+ #include <climits>
+ 
+ namespace boost {
+@@ -25,6 +26,18 @@ namespace detail{
+ 
+ namespace detail{
+ 
++template <class no_cv_t, bool is_enum>
++struct is_signed_values_underlying_type
++{
++   typedef no_cv_t underlying_type;
++};
++
++template <class no_cv_t>
++struct is_signed_values_underlying_type<no_cv_t, true>
++{
++   typedef typename ::boost::underlying_type<no_cv_t>::type underlying_type;
++};
++
+ template <class T>
+ struct is_signed_values
+ {
+@@ -34,14 +47,15 @@ struct is_signed_values
+    // the correct answer.
+    //
+    typedef typename remove_cv<T>::type no_cv_t;
+-   static const no_cv_t minus_one = (static_cast<no_cv_t>(-1));
+-   static const no_cv_t zero = (static_cast<no_cv_t>(0));
++   typedef typename is_signed_values_underlying_type<no_cv_t, ::boost::is_enum<T>::value>::underlying_type underlying_type;
++
++   static const underlying_type minus_one = (static_cast<underlying_type>(-1));
++   static const underlying_type zero = (static_cast<underlying_type>(0));
+ };
+ 
+ template <class T>
+ struct is_signed_helper
+ {
+-   typedef typename remove_cv<T>::type no_cv_t;
+    BOOST_STATIC_CONSTANT(bool, value = (!(::boost::detail::is_signed_values<T>::minus_one  > boost::detail::is_signed_values<T>::zero)));
+ };
+ 
diff --git a/devel/boost-libs/files/patch-boost_type__traits_is__unsigned.hpp b/devel/boost-libs/files/patch-boost_type__traits_is__unsigned.hpp
new file mode 100644
index 000000000000..0a776dd4790f
--- /dev/null
+++ b/devel/boost-libs/files/patch-boost_type__traits_is__unsigned.hpp
@@ -0,0 +1,42 @@
+--- boost/type_traits/is_unsigned.hpp.orig	2025-08-06 18:49:14 UTC
++++ boost/type_traits/is_unsigned.hpp
+@@ -13,6 +13,7 @@
+ #include <boost/type_traits/is_integral.hpp>
+ #include <boost/type_traits/is_enum.hpp>
+ #include <boost/type_traits/remove_cv.hpp>
++#include <boost/core/underlying_type.hpp>
+ 
+ #include <climits>
+ 
+@@ -26,6 +27,18 @@ namespace detail{
+ 
+ namespace detail{
+ 
++template <class no_cv_t, bool is_enum>
++struct is_unsigned_values_underlying_type
++{
++   typedef no_cv_t underlying_type;
++};
++
++template <class no_cv_t>
++struct is_unsigned_values_underlying_type<no_cv_t, true>
++{
++   typedef typename ::boost::underlying_type<no_cv_t>::type underlying_type;
++};
++
+ template <class T>
+ struct is_unsigned_values
+ {
+@@ -35,8 +48,10 @@ struct is_unsigned_values
+    // the correct answer.
+    //
+    typedef typename remove_cv<T>::type no_cv_t;
+-   static const no_cv_t minus_one = (static_cast<no_cv_t>(-1));
+-   static const no_cv_t zero = (static_cast<no_cv_t>(0));
++   typedef typename is_unsigned_values_underlying_type<no_cv_t, ::boost::is_enum<T>::value>::underlying_type underlying_type;
++
++   static const underlying_type minus_one = (static_cast<underlying_type>(-1));
++   static const underlying_type zero = (static_cast<underlying_type>(0));
+ };
+ 
+ template <class T>