git: 248364560336 - main - devel/cpprestsdk: unbreak build with llvm 20
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Tue, 22 Jul 2025 07:04:56 UTC
The branch main has been updated by tagattie:
URL: https://cgit.FreeBSD.org/ports/commit/?id=24836456033674f65b63cb0057e7ec2f40506130
commit 24836456033674f65b63cb0057e7ec2f40506130
Author: Jan-Espen Oversand <sigsegv@radiotube.org>
AuthorDate: 2025-07-22 06:44:04 +0000
Commit: Hiroki Tagato <tagattie@FreeBSD.org>
CommitDate: 2025-07-22 07:04:46 +0000
devel/cpprestsdk: unbreak build with llvm 20
Cpprestsdk is using a lot of unsigned types for C++ streams, which
apparently is fine with MSVC/win32, with gcc at least up until some
point, but does not work at all with the latest llvm versions. I've
put some effort into not going for anything that pollutes the std
namespace with anything, which I don't think is ok at all with a
library.
PR: 287706
Reported by: Jan-Espen Oversand <sigsegv@radiotube.org> (maintainer)
---
devel/cpprestsdk/Makefile | 2 +-
.../files/patch-include_cpprest_astreambuf.h | 77 +++++++++++
.../patch-include_cpprest_details_char__traits.h | 105 +++++++++++++++
.../files/patch-include_cpprest_streams.h | 144 +++++++++++++++++++++
...h-tests_functional_streams_memstream__tests.cpp | 73 +++++++++++
...h-tests_functional_streams_stdstream__tests.cpp | 30 +++++
devel/cpprestsdk/pkg-plist | 1 +
7 files changed, 431 insertions(+), 1 deletion(-)
diff --git a/devel/cpprestsdk/Makefile b/devel/cpprestsdk/Makefile
index f8f8f672c9fb..d9fcae5c27a0 100644
--- a/devel/cpprestsdk/Makefile
+++ b/devel/cpprestsdk/Makefile
@@ -1,6 +1,6 @@
PORTNAME= cpprestsdk
PORTVERSION= 2.10.19
-PORTREVISION= 4
+PORTREVISION= 5
DISTVERSIONPREFIX= v
CATEGORIES= devel
diff --git a/devel/cpprestsdk/files/patch-include_cpprest_astreambuf.h b/devel/cpprestsdk/files/patch-include_cpprest_astreambuf.h
new file mode 100644
index 000000000000..3daacb5a460c
--- /dev/null
+++ b/devel/cpprestsdk/files/patch-include_cpprest_astreambuf.h
@@ -0,0 +1,77 @@
+--- include/cpprest/astreambuf.h.orig 2023-12-05 04:23:31 UTC
++++ include/cpprest/astreambuf.h
+@@ -15,6 +15,7 @@
+
+ #include "cpprest/asyncrt_utils.h"
+ #include "cpprest/details/basic_types.h"
++#include "cpprest/details/char_traits.h"
+ #include "pplx/pplxtasks.h"
+ #include <atomic>
+ #include <cstring>
+@@ -56,55 +57,28 @@ namespace streams
+ /// <typeparam name="_CharType">
+ /// The data type of the basic element of the stream.
+ /// </typeparam>
++namespace detail
++{
+ template<typename _CharType>
+-struct char_traits : std::char_traits<_CharType>
++struct char_traits : utility::CanUseStdCharTraits<_CharType>::TraitsType
+ {
+ /// <summary>
+ /// Some synchronous functions will return this value if the operation
+ /// requires an asynchronous call in a given situation.
+ /// </summary>
+ /// <returns>An <c>int_type</c> value which implies that an asynchronous call is required.</returns>
+- static typename std::char_traits<_CharType>::int_type requires_async()
++ static typename utility::CanUseStdCharTraits<_CharType>::TraitsType::int_type requires_async()
+ {
+- return std::char_traits<_CharType>::eof() - 1;
++ return utility::CanUseStdCharTraits<_CharType>::TraitsType::eof() - 1;
+ }
+ };
++}
++template<typename _CharType> struct char_traits : detail::char_traits<_CharType> {
++};
+ #if !defined(_WIN32)
+-template<>
+-struct char_traits<unsigned char> : private std::char_traits<char>
+-{
+-public:
+- typedef unsigned char char_type;
+-
+- using std::char_traits<char>::eof;
+- using std::char_traits<char>::int_type;
+- using std::char_traits<char>::off_type;
+- using std::char_traits<char>::pos_type;
+-
+- static size_t length(const unsigned char* str)
+- {
+- return std::char_traits<char>::length(reinterpret_cast<const char*>(str));
+- }
+-
+- static void assign(unsigned char& left, const unsigned char& right) { left = right; }
+- static unsigned char* assign(unsigned char* left, size_t n, unsigned char value)
+- {
+- return reinterpret_cast<unsigned char*>(
+- std::char_traits<char>::assign(reinterpret_cast<char*>(left), n, static_cast<char>(value)));
+- }
+-
+- static unsigned char* copy(unsigned char* left, const unsigned char* right, size_t n)
+- {
+- return reinterpret_cast<unsigned char*>(
+- std::char_traits<char>::copy(reinterpret_cast<char*>(left), reinterpret_cast<const char*>(right), n));
+- }
+-
+- static unsigned char* move(unsigned char* left, const unsigned char* right, size_t n)
+- {
+- return reinterpret_cast<unsigned char*>(
+- std::char_traits<char>::move(reinterpret_cast<char*>(left), reinterpret_cast<const char*>(right), n));
+- }
+-
++template <> struct char_traits<unsigned char> : detail::char_traits<unsigned char> {
++ typedef typename std::char_traits<char>::int_type int_type;
++ static int_type eof() { return std::char_traits<char>::eof(); }
+ static int_type requires_async() { return eof() - 1; }
+ };
+ #endif
diff --git a/devel/cpprestsdk/files/patch-include_cpprest_details_char__traits.h b/devel/cpprestsdk/files/patch-include_cpprest_details_char__traits.h
new file mode 100644
index 000000000000..6ccf51639de7
--- /dev/null
+++ b/devel/cpprestsdk/files/patch-include_cpprest_details_char__traits.h
@@ -0,0 +1,105 @@
+--- include/cpprest/details/char_traits.h.orig 2025-07-02 14:23:43 UTC
++++ include/cpprest/details/char_traits.h
+@@ -0,0 +1,102 @@
++//
++// Created by sigsegv on 6/28/25.
++//
++
++#ifndef CPPRESTSDK_ROOT_CHAR_TRAITS_H
++#define CPPRESTSDK_ROOT_CHAR_TRAITS_H
++
++#include <type_traits>
++#include <string>
++
++namespace utility {
++
++namespace detail {
++
++template <typename T> struct IntTypeFor {
++ typedef typename std::conditional<std::is_unsigned<T>::value, unsigned long long int, long long int>::type type;
++};
++template <> struct IntTypeFor<char> {
++ typedef typename std::char_traits<char>::int_type type;
++};
++template <> struct IntTypeFor<unsigned char> {
++ typedef typename std::make_unsigned<typename std::char_traits<char>::int_type>::type type;
++};
++
++template <typename T> class DetailCharTraits
++{
++public:
++ using char_type = T;
++ using int_type = typename IntTypeFor<T>::type;
++ using off_type = std::streamoff;
++ using pos_type = std::streampos;
++ using state_type = mbstate_t;
++
++ static void assign(char_type& r, const char_type& a) noexcept { r = a; }
++ static char_type to_char_type(int_type c) noexcept { return char_type(c); }
++ static int_type to_int_type(char_type c) noexcept { return c; }
++ static bool eq(char_type a, char_type b) noexcept { return a == b; }
++ static bool lt(char_type a, char_type b) noexcept { return a < b; }
++ static int compare(const char_type* s1,const char_type* s2,size_t n){
++ for (; n--; ++s1, ++s2) {
++ if (!eq(*s1, *s2))
++ return lt(*s1,*s2)?-1:1;
++ }
++ return 0;
++ }
++ static size_t length(const char_type* s){
++ const char_type* p = s;
++ while (*p)
++ ++p;
++ return size_t(p - s);
++ }
++ static const char_type* find(const char_type* s,size_t n,const char_type& a){
++ for (; n--; ++s)
++ {
++ if (eq(*s, a))
++ return s;
++ return nullptr;
++ }
++ }
++ static char_type* move (char_type* r,const char_type* s,size_t n){
++ return (char_type*)memmove(r, s, n * sizeof(char_type));
++ }
++ static char_type* copy (char_type* r,const char_type* s,size_t n){
++ return (char_type*)memcpy (r, s, n * sizeof(char_type));
++ }
++ static char_type* assign(char_type* r,size_t n,char_type a){
++ if (sizeof(char_type) == 1)
++ {
++ return (char_type*)memset(r, a, n);
++ }
++ else
++ {
++ for (char_type *s = r; n--; ++s)
++ {
++ *s = a;
++ }
++ }
++ }
++ static int_type eof() noexcept { return ~0u; }
++ static int_type not_eof(int_type c) noexcept { return c == eof() ? 0 : c; }
++};
++
++template <typename T, typename = bool> struct CanUseStdCharTraits : public std::false_type
++{
++public:
++ typedef DetailCharTraits<T> TraitsType;
++};
++
++template <typename T> struct CanUseStdCharTraits<T, decltype(std::char_traits<T>::eq(std::declval<T>(), std::declval<T>()))> : public std::true_type
++{
++public:
++ typedef std::char_traits<T> TraitsType;
++};
++
++}
++
++template <typename T> struct CanUseStdCharTraits : detail::CanUseStdCharTraits<typename std::remove_const<typename std::remove_reference<T>::type>::type> {
++};
++
++}
++
++#endif // CPPRESTSDK_ROOT_CHAR_TRAITS_H
diff --git a/devel/cpprestsdk/files/patch-include_cpprest_streams.h b/devel/cpprestsdk/files/patch-include_cpprest_streams.h
new file mode 100644
index 000000000000..c1e1a5ba5b7e
--- /dev/null
+++ b/devel/cpprestsdk/files/patch-include_cpprest_streams.h
@@ -0,0 +1,144 @@
+--- include/cpprest/streams.h.orig 2023-12-05 04:23:31 UTC
++++ include/cpprest/streams.h
+@@ -16,6 +16,7 @@
+ #define CASA_STREAMS_H
+
+ #include "cpprest/astreambuf.h"
++#include "cpprest/details/char_traits.h"
+ #include <iosfwd>
+ #include <cstdio>
+
+@@ -60,31 +61,96 @@ class basic_istream_helper (private)
+ concurrency::streams::streambuf<CharType> m_buffer;
+ };
+
+-template<typename CharType>
++template<typename CharType, class Traits = typename utility::CanUseStdCharTraits<CharType>::TraitsType>
+ struct Value2StringFormatter
+ {
++ struct SanitizeInput
++ {
++ const std::basic_string<char> &operator () (const std::basic_string<char> &input)
++ {
++ return input;
++ }
++ template <class InputTraits> std::basic_string<char> operator () (const std::basic_string<unsigned char, InputTraits> &input)
++ {
++ return {reinterpret_cast<const char *>(input.c_str()), input.size()};
++ }
++ const char *operator () (const char *input) {
++ return input;
++ }
++ const char *operator () (const unsigned char *input)
++ {
++ return reinterpret_cast<const char *>(input);
++ }
++ template <class T> T operator () (T input)
++ {
++ return input;
++ }
++ };
++ struct GenerateFormatOutput
++ {
++ std::basic_string<CharType,Traits> &&operator() (std::basic_string<CharType,Traits> &&result)
++ {
++ return std::move(result);
++ }
++ std::basic_string<CharType,Traits> operator() (const std::basic_string<char> &intermediate)
++ {
++ return {reinterpret_cast<const CharType *>(intermediate.c_str()), intermediate.size()};
++ }
++ };
+ template<typename T>
+- static std::basic_string<CharType> format(const T& val)
++ static std::basic_string<CharType, Traits> format(const T& val)
+ {
+- std::basic_ostringstream<CharType> ss;
+- ss << val;
+- return ss.str();
++ typename std::conditional<
++ sizeof(CharType) == 1,
++ std::basic_ostringstream<char>,
++ std::basic_ostringstream<typename std::make_signed<CharType>::type>
++ >::type ss;
++ SanitizeInput sanitizer;
++ ss << sanitizer(val);
++ typename std::conditional<
++ sizeof(CharType) == 1,
++ std::basic_string<char>,
++ std::basic_string<typename std::make_signed<CharType>::type>
++ >::type str = ss.str();
++ GenerateFormatOutput generateFormatOutput;
++ return generateFormatOutput(std::move(str));
+ }
+ };
+
+-template<>
+-struct Value2StringFormatter<uint8_t>
++template<class Traits, typename T>
++struct Value2StringFormatterUint8Format
+ {
+- template<typename T>
+- static std::basic_string<uint8_t> format(const T& val)
++ std::basic_string<uint8_t, Traits> operator () (const T& val)
+ {
+ std::basic_ostringstream<char> ss;
+ ss << val;
+ return reinterpret_cast<const uint8_t*>(ss.str().c_str());
+ }
++};
+
+- static std::basic_string<uint8_t> format(const utf16string& val)
++template <class Traits>
++struct Value2StringFormatterUint8Format<Traits, std::basic_string<uint8_t,Traits>>
++{
++ std::basic_string<uint8_t, Traits> operator () (
++ const std::basic_string<uint8_t, typename utility::CanUseStdCharTraits<uint8_t>::TraitsType>& val)
+ {
++ Value2StringFormatterUint8Format<Traits,std::basic_string<char>> format;
++ return format(reinterpret_cast<const std::basic_string<char>&>(val));
++ }
++};
++
++template<>
++struct Value2StringFormatter<uint8_t>
++{
++ template <typename T, class Traits = typename utility::CanUseStdCharTraits<uint8_t>::TraitsType>
++ static std::basic_string<uint8_t, Traits> format(const T& val)
++ {
++ Value2StringFormatterUint8Format<Traits, T> format;
++ return format(val);
++ }
++
++ static std::basic_string<uint8_t, typename utility::CanUseStdCharTraits<uint8_t>::TraitsType> format(const utf16string& val)
++ {
+ return format(utility::conversions::utf16_to_utf8(val));
+ }
+ };
+@@ -262,7 +328,7 @@ class basic_ostream (public)
+ /// Write the specified string to the output stream.
+ /// </summary>
+ /// <param name="str">Input string.</param>
+- pplx::task<size_t> print(const std::basic_string<CharType>& str) const
++ pplx::task<size_t> print(const std::basic_string<CharType,traits>& str) const
+ {
+ pplx::task<size_t> result;
+ if (!_verify_and_return_task(details::_out_stream_msg, result)) return result;
+@@ -273,7 +339,7 @@ class basic_ostream (public)
+ }
+ else
+ {
+- auto sharedStr = std::make_shared<std::basic_string<CharType>>(str);
++ auto sharedStr = std::make_shared<std::basic_string<CharType,traits>>(str);
+ return helper()->m_buffer.putn_nocopy(sharedStr->c_str(), sharedStr->size()).then([sharedStr](size_t size) {
+ return size;
+ });
+@@ -294,7 +360,7 @@ class basic_ostream (public)
+ if (!_verify_and_return_task(details::_out_stream_msg, result)) return result;
+ // TODO in the future this could be improved to have Value2StringFormatter avoid another unnecessary copy
+ // by putting the string on the heap before calling the print string overload.
+- return print(details::Value2StringFormatter<CharType>::format(val));
++ return print(details::Value2StringFormatter<CharType, traits>::format(val));
+ }
+
+ /// <summary>
diff --git a/devel/cpprestsdk/files/patch-tests_functional_streams_memstream__tests.cpp b/devel/cpprestsdk/files/patch-tests_functional_streams_memstream__tests.cpp
new file mode 100644
index 000000000000..e2b7e2e67e7e
--- /dev/null
+++ b/devel/cpprestsdk/files/patch-tests_functional_streams_memstream__tests.cpp
@@ -0,0 +1,73 @@
+--- tests/functional/streams/memstream_tests.cpp.orig 2023-12-05 04:23:31 UTC
++++ tests/functional/streams/memstream_tests.cpp
+@@ -8,6 +8,7 @@
+ *
+ * =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+ ****/
++#include "cpprest/details/char_traits.h"
+ #include "stdafx.h"
+ #if defined(__cplusplus_winrt)
+ #include <wrl.h>
+@@ -32,7 +33,7 @@ void streambuf_putc(StreamBufferType& wbuf)
+ {
+ VERIFY_IS_TRUE(wbuf.can_write());
+
+- std::basic_string<typename StreamBufferType::char_type> s;
++ std::basic_string<typename StreamBufferType::char_type,typename utility::CanUseStdCharTraits<typename StreamBufferType::char_type>::TraitsType> s;
+ s.push_back((typename StreamBufferType::char_type)0);
+ s.push_back((typename StreamBufferType::char_type)1);
+ s.push_back((typename StreamBufferType::char_type)2);
+@@ -137,7 +138,7 @@ void streambuf_putn(StreamBufferType& wbuf)
+ {
+ VERIFY_IS_TRUE(wbuf.can_write());
+
+- std::basic_string<typename StreamBufferType::char_type> s;
++ std::basic_string<typename StreamBufferType::char_type,typename utility::CanUseStdCharTraits<typename StreamBufferType::char_type>::TraitsType> s;
+ s.push_back((typename StreamBufferType::char_type)0);
+ s.push_back((typename StreamBufferType::char_type)1);
+ s.push_back((typename StreamBufferType::char_type)2);
+@@ -169,7 +170,7 @@ void streambuf_putn(concurrency::streams::rawptr_buffe
+
+ typedef concurrency::streams::rawptr_buffer<CharType> StreamBufferType;
+
+- std::basic_string<CharType> s;
++ std::basic_string<CharType,typename CanUseStdCharTraits<CharType>::TraitsType> s;
+ s.push_back((CharType)0);
+ s.push_back((CharType)1);
+ s.push_back((CharType)2);
+@@ -198,7 +199,7 @@ void streambuf_putn(concurrency::streams::container_bu
+ typedef concurrency::streams::container_buffer<CollectionType> StreamBufferType;
+ typedef typename concurrency::streams::container_buffer<CollectionType>::char_type CharType;
+
+- std::basic_string<CharType> s;
++ std::basic_string<CharType, typename utility::CanUseStdCharTraits<CharType>::TraitsType> s;
+ s.push_back((CharType)0);
+ s.push_back((CharType)1);
+ s.push_back((CharType)2);
+@@ -553,7 +554,7 @@ void streambuf_putn_getn(StreamBufferType& rwbuf)
+ VERIFY_IS_TRUE(rwbuf.can_read());
+ VERIFY_IS_TRUE(rwbuf.can_write());
+ VERIFY_IS_FALSE(rwbuf.is_eof());
+- std::basic_string<typename StreamBufferType::char_type> s;
++ std::basic_string<typename StreamBufferType::char_type, typename utility::CanUseStdCharTraits<typename StreamBufferType::char_type>::TraitsType> s;
+ s.push_back((typename StreamBufferType::char_type)0);
+ s.push_back((typename StreamBufferType::char_type)1);
+ s.push_back((typename StreamBufferType::char_type)2);
+@@ -684,7 +685,7 @@ void streambuf_close_read_with_pending_read(StreamBuff
+ VERIFY_IS_TRUE(rwbuf.can_write());
+
+ // Write 4 characters
+- std::basic_string<typename StreamBufferType::char_type> s;
++ std::basic_string<typename StreamBufferType::char_type, typename utility::CanUseStdCharTraits<typename StreamBufferType::char_type>::TraitsType> s;
+ s.push_back((typename StreamBufferType::char_type)0);
+ s.push_back((typename StreamBufferType::char_type)1);
+ s.push_back((typename StreamBufferType::char_type)2);
+@@ -726,7 +727,7 @@ void streambuf_close_write_with_pending_read(StreamBuf
+ VERIFY_IS_TRUE(rwbuf.can_write());
+
+ // Write 4 characters
+- std::basic_string<typename StreamBufferType::char_type> s;
++ std::basic_string<typename StreamBufferType::char_type, typename utility::CanUseStdCharTraits<typename StreamBufferType::char_type>::TraitsType> s;
+ s.push_back((typename StreamBufferType::char_type)0);
+ s.push_back((typename StreamBufferType::char_type)1);
+ s.push_back((typename StreamBufferType::char_type)2);
diff --git a/devel/cpprestsdk/files/patch-tests_functional_streams_stdstream__tests.cpp b/devel/cpprestsdk/files/patch-tests_functional_streams_stdstream__tests.cpp
new file mode 100644
index 000000000000..4ec6c6af21de
--- /dev/null
+++ b/devel/cpprestsdk/files/patch-tests_functional_streams_stdstream__tests.cpp
@@ -0,0 +1,30 @@
+--- tests/functional/streams/stdstream_tests.cpp.orig 2023-12-05 04:23:31 UTC
++++ tests/functional/streams/stdstream_tests.cpp
+@@ -13,6 +13,7 @@
+ #include "cpprest/filestream.h"
+ #include "cpprest/producerconsumerstream.h"
+ #include "cpprest/rawptrstream.h"
++#include "cpprest/details/char_traits.h"
+
+ #if (!defined(_WIN32) || !defined(CPPREST_EXCLUDE_WEBSOCKETS)) && !defined(__cplusplus_winrt)
+ #include <boost/interprocess/streams/bufferstream.hpp>
+@@ -303,7 +304,8 @@ SUITE(stdstreambuf_tests)
+
+ const std::streamsize iterations = 100;
+
+- const std::string the_alphabet("abcdefghijklmnopqrstuvwxyz");
++ const char *the_alphabet_characters = "abcdefghijklmnopqrstuvwxyz";
++ const std::basic_string<uint8_t,typename utility::CanUseStdCharTraits<uint8_t>::TraitsType> the_alphabet(reinterpret_cast<const uint8_t *>(the_alphabet_characters));
+
+ auto writer = pplx::create_task([ostream, iterations, the_alphabet]() {
+ auto os = ostream;
+@@ -341,7 +343,8 @@ SUITE(stdstreambuf_tests)
+
+ const std::streamsize iterations = 100;
+
+- const std::string the_alphabet("abcdefghijklmnopqrstuvwxyz");
++ const char *the_alphabet_chars = "abcdefghijklmnopqrstuvwxyz";
++ const std::basic_string<uint8_t,typename CanUseStdCharTraits<uint8_t>::TraitsType> the_alphabet(reinterpret_cast<const uint8_t *>(the_alphabet_chars));
+
+ auto writer = pplx::create_task([ostream, iterations, the_alphabet]() {
+ auto os = ostream;
diff --git a/devel/cpprestsdk/pkg-plist b/devel/cpprestsdk/pkg-plist
index 7a229daaec3f..04a70794fecf 100644
--- a/devel/cpprestsdk/pkg-plist
+++ b/devel/cpprestsdk/pkg-plist
@@ -4,6 +4,7 @@ include/cpprest/base_uri.h
include/cpprest/containerstream.h
include/cpprest/details/SafeInt3.hpp
include/cpprest/details/basic_types.h
+include/cpprest/details/char_traits.h
include/cpprest/details/cpprest_compat.h
include/cpprest/details/fileio.h
include/cpprest/details/http_constants.dat