Date: Sun, 15 Feb 2026 13:05:28 +0000 From: Dimitry Andric <dim@FreeBSD.org> To: ports-committers@FreeBSD.org, dev-commits-ports-all@FreeBSD.org, dev-commits-ports-branches@FreeBSD.org Subject: git: 7b3fa26bfa43 - 2026Q1 - devel/libddwaf: fix build with clang 21 Message-ID: <6991c498.3f38e.705915b7@gitrepo.freebsd.org>
index | next in thread | raw e-mail
The branch 2026Q1 has been updated by dim: URL: https://cgit.FreeBSD.org/ports/commit/?id=7b3fa26bfa43fd79b4129cf30fe46cc6f21fe9fc commit 7b3fa26bfa43fd79b4129cf30fe46cc6f21fe9fc Author: Dimitry Andric <dim@FreeBSD.org> AuthorDate: 2026-02-13 19:22:32 +0000 Commit: Dimitry Andric <dim@FreeBSD.org> CommitDate: 2026-02-15 13:05:21 +0000 devel/libddwaf: fix build with clang 21 With clang 21 devel/libddwaf fails to build, with errors similar to: In file included from /wrkdirs/usr/ports/devel/libddwaf/work/libddwaf-1.30.1/src/vendor/fmt/format.cc:8: /wrkdirs/usr/ports/devel/libddwaf/work/libddwaf-1.30.1/src/vendor/fmt/format-inl.h:61:19: error: call to consteval function 'ddwaf::fmt::basic_format_string<char, ddwaf::fmt::basic_string_view<char> &, const char (&)[3]>::basic_format_string<FMT_COMPILE_STRING, 0>' is not a constant expression 61 | format_to(it, FMT_STRING("{}{}"), message, SEP); | ^ /wrkdirs/usr/ports/devel/libddwaf/work/libddwaf-1.30.1/src/vendor/fmt/format.h:1905:23: note: expanded from macro 'FMT_STRING' 1905 | #define FMT_STRING(s) FMT_STRING_IMPL(s, fmt::detail::compile_string, ) | ^ /wrkdirs/usr/ports/devel/libddwaf/work/libddwaf-1.30.1/src/vendor/fmt/format.h:1882:3: note: expanded from macro 'FMT_STRING_IMPL' 1882 | [] { \ | ^ /wrkdirs/usr/ports/devel/libddwaf/work/libddwaf-1.30.1/src/vendor/fmt/core.h:688:54: note: subexpression not valid in a constant expression 688 | format_str_.remove_prefix(detail::to_unsigned(it - begin())); | ~~~^~~~~~~~~ /wrkdirs/usr/ports/devel/libddwaf/work/libddwaf-1.30.1/src/vendor/fmt/core.h:2639:5: note: in call to 'this->context_.advance_to(&"{}{}"[1])' 2639 | context_.advance_to(begin); | ^~~~~~~~~~~~~~~~~~~~~~~~~~ /wrkdirs/usr/ports/devel/libddwaf/work/libddwaf-1.30.1/src/vendor/fmt/core.h:2634:5: note: in call to 'this->on_format_specs(0, &"{}{}"[1], &"{}{}"[1])' 2634 | on_format_specs(id, begin, begin); // Call parse() on empty specs. | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /wrkdirs/usr/ports/devel/libddwaf/work/libddwaf-1.30.1/src/vendor/fmt/core.h:2459:5: note: in call to 'handler.on_replacement_field(0, &"{}{}"[1])' 2459 | handler.on_replacement_field(handler.on_arg_id(), begin); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /wrkdirs/usr/ports/devel/libddwaf/work/libddwaf-1.30.1/src/vendor/fmt/core.h:2491:21: note: in call to 'parse_replacement_field<char, ddwaf::fmt::detail::format_string_checker<char, ddwaf::fmt::basic_string_view<char>, char[3]> &>(&"{}{}"[1], &"{}{}"[4], checker(s))' 2491 | begin = p = parse_replacement_field(p - 1, end, handler); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /wrkdirs/usr/ports/devel/libddwaf/work/libddwaf-1.30.1/src/vendor/fmt/core.h:2742:7: note: in call to 'parse_format_string<true, char, ddwaf::fmt::detail::format_string_checker<char, ddwaf::fmt::basic_string_view<char>, char[3]>>({&"{}{}"[0], 4}, checker(s))' 2742 | detail::parse_format_string<true>(str_, checker(s)); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /wrkdirs/usr/ports/devel/libddwaf/work/libddwaf-1.30.1/src/vendor/fmt/format-inl.h:61:19: note: in call to 'basic_format_string<FMT_COMPILE_STRING, 0>([] { struct __attribute__((visibility("hidden"))) FMT_COMPILE_STRING : fmt::detail::compile_string { using char_type [[maybe_unused]] = fmt::remove_cvref_t<decltype("{}{}"[0])>; [[maybe_unused]] constexpr operator fmt::basic_string_view<char_type>() const { return fmt::detail_exported::compile_string_to_view<char_type>("{}{}"); } }; return FMT_COMPILE_STRING(); }())' 61 | format_to(it, FMT_STRING("{}{}"), message, SEP); | ^~~~~~~~~~~~~~~~~~ /wrkdirs/usr/ports/devel/libddwaf/work/libddwaf-1.30.1/src/vendor/fmt/format.h:1905:23: note: expanded from macro 'FMT_STRING' 1905 | #define FMT_STRING(s) FMT_STRING_IMPL(s, fmt::detail::compile_string, ) | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /wrkdirs/usr/ports/devel/libddwaf/work/libddwaf-1.30.1/src/vendor/fmt/format.h:1882:3: note: expanded from macro 'FMT_STRING_IMPL' 1882 | [] { \ | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1883 | /* Use the hidden visibility as a workaround for a GCC bug (#1973). */ \ | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1884 | /* Use a macro-like name to avoid shadowing warnings. */ \ | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1885 | struct FMT_VISIBILITY("hidden") FMT_COMPILE_STRING : base { \ | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1886 | using char_type FMT_MAYBE_UNUSED = fmt::remove_cvref_t<decltype(s[0])>; \ | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1887 | FMT_MAYBE_UNUSED FMT_CONSTEXPR explicit \ | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1888 | operator fmt::basic_string_view<char_type>() const { \ | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1889 | return fmt::detail_exported::compile_string_to_view<char_type>(s); \ | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1890 | } \ | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1891 | }; \ | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1892 | return FMT_COMPILE_STRING(); \ | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1893 | }() | ~~~ This is caused by an outdated vendored version of the fmt library, from <https://github.com/fmtlib/fmt>. Upstream libddwaf updated their vendored copy in <https://github.com/DataDog/libddwaf/commit/d9dd3eb>, which is a bit large due to the vendor update, but the patch applies with a minimum of fuzz, and makes libddwaf build with clang 21. PR: 293165 Approved by: sunpoet (maintainer) MFH: 2026Q1 (cherry picked from commit 76122faa9d1b5e85f9a5f32a5671103d7eef1695) --- devel/libddwaf/files/patch-update-fmt | 12986 ++++++++++++++++++++++++++++++++ 1 file changed, 12986 insertions(+) diff --git a/devel/libddwaf/files/patch-update-fmt b/devel/libddwaf/files/patch-update-fmt new file mode 100644 index 000000000000..846fca81f085 --- /dev/null +++ b/devel/libddwaf/files/patch-update-fmt @@ -0,0 +1,12986 @@ +commit 84a7a52b24e07a02d3c42ec5d247bcd3a02cb7cb +Author: Anil Mahtani <929854+Anilm3@users.noreply.github.com> +Date: 2025-11-05T16:22:50Z + + Cherry-pick: Upgrade fmt dependency and use as header-only (#478) + +diff --git .github/workflows/build.yml .github/workflows/build.yml +index d1a909e..9188a54 100644 +--- .github/workflows/build.yml ++++ .github/workflows/build.yml +@@ -362,11 +362,11 @@ jobs: + + - name: Generate Comparison Table + run: | +- echo "### Artifact Size Comparison 📦" > comparison.md ++ echo "### Dynamic Artifact Size Comparison 📦" > comparison.md + echo "| Artifact | Previous Release | This PR | Difference |" >> comparison.md + echo "|----------|-----------------|---------|------------|" >> comparison.md + +- find ./candidate -regex ".*\.\(a\|a\.stripped\|so\|dll\|lib\|dylib\)" | sed "s@./candidate/\(.*\)@\1@g" | sort | while read file; do ++ find ./candidate -regex ".*\.\(so\|dll\|dylib\)" | sed "s@./candidate/\(.*\)@\1@g" | sort | while read file; do + baseline_size=$(du -b ./baseline/$file | awk '{print $1}') + candidate_size=$(du -b ./candidate/$file | awk '{print $1}') + +@@ -378,6 +378,24 @@ jobs: + fi + done + ++ echo "---" >> comparison.md ++ echo "### Static Artifact Size Comparison 📦" >> comparison.md ++ echo "| Artifact | Previous Release | This PR | Difference |" >> comparison.md ++ echo "|----------|-----------------|---------|------------|" >> comparison.md ++ ++ find ./candidate -regex ".*\.\(a\|a\.stripped\|lib\)" | sed "s@./candidate/\(.*\)@\1@g" | sort | while read file; do ++ baseline_size=$(du -b ./baseline/$file | awk '{print $1}') ++ candidate_size=$(du -b ./candidate/$file | awk '{print $1}') ++ ++ if [[ $baseline_size -gt 0 ]]; then ++ diff=$(echo "scale=2; ($candidate_size-$baseline_size)/($baseline_size + 1)" | bc -l | awk '{printf "%.2f\n", $0}') ++ echo "| $( echo $file | sed 's@\([^/]*\)/\([^/]*/\)*\(.*\)@\1::\3@g')| $baseline_size | $candidate_size | $diff% |" >> comparison.md ++ else ++ echo "| $( echo $file | sed 's@\([^/]*\)/\([^/]*/\)*\(.*\)@\1::\3@g')| $baseline_size | $candidate_size | ∞ |" >> comparison.md ++ fi ++ done ++ ++ + - name: Post PR comment + uses: thollander/actions-comment-pull-request@24bffb9b452ba05a4f3f77933840a6a841d1b32b + with: +diff --git CMakeLists.txt CMakeLists.txt +index cd2f9de..d639967 100644 +--- CMakeLists.txt ++++ CMakeLists.txt +@@ -54,6 +54,7 @@ else() + add_compile_options(/MT) + endif() + ++ add_compile_options(/utf-8) + add_compile_definitions(-D_CRT_SECURE_NO_WARNINGS=1 -Dstrdup=_strdup -Dputenv=_putenv) + endif() + +diff --git cmake/objects.cmake cmake/objects.cmake +index f589f23..8e8692f 100644 +--- cmake/objects.cmake ++++ cmake/objects.cmake +@@ -92,7 +92,6 @@ set(LIBDDWAF_SOURCE + ${libddwaf_SOURCE_DIR}/src/transformer/css_decode.cpp + ${libddwaf_SOURCE_DIR}/src/transformer/html_entity_decode.cpp + ${libddwaf_SOURCE_DIR}/src/transformer/js_decode.cpp +- ${libddwaf_SOURCE_DIR}/src/vendor/fmt/format.cc + ${libddwaf_SOURCE_DIR}/src/vendor/radixlib/radixlib.c + ${libddwaf_SOURCE_DIR}/src/vendor/lua-aho-corasick/ac_fast.cxx + ${libddwaf_SOURCE_DIR}/src/vendor/lua-aho-corasick/ac_slow.cxx +diff --git src/configuration/configuration_manager.cpp src/configuration/configuration_manager.cpp +index 10910a4..b982453 100644 +--- src/configuration/configuration_manager.cpp ++++ src/configuration/configuration_manager.cpp +@@ -26,7 +26,7 @@ + #include "configuration/rule_override_parser.hpp" + #include "configuration/rule_parser.hpp" + #include "configuration/scanner_parser.hpp" +-#include "fmt/core.h" ++#include "fmt/format.h" + #include "log.hpp" + #include "ruleset_info.hpp" + +diff --git src/dynamic_string.hpp src/dynamic_string.hpp +index 3f0e79a..08d6a4d 100644 +--- src/dynamic_string.hpp ++++ src/dynamic_string.hpp +@@ -170,7 +170,7 @@ protected: + + template <> struct fmt::formatter<dynamic_string> : fmt::formatter<std::string_view> { + // Use the parse method from the base class formatter +- template <typename FormatContext> auto format(const dynamic_string &d, FormatContext &ctx) ++ template <typename FormatContext> auto format(const dynamic_string &d, FormatContext &ctx) const + { + return fmt::formatter<std::string_view>::format(std::string_view{d.data(), d.size()}, ctx); + } +diff --git src/log.hpp src/log.hpp +index 2543c8f..1de413a 100644 +--- src/log.hpp ++++ src/log.hpp +@@ -51,10 +51,12 @@ constexpr const char *base_name(const char *path) + # define DDWAF_LOG_HELPER(level, function, file, line, fmt_str, ...) \ + { \ + if (ddwaf::logger::valid(level)) { \ +- constexpr const char *filename = base_name(file); \ +- auto message = ddwaf::fmt::format(fmt_str, ##__VA_ARGS__); \ +- ddwaf::logger::log( \ +- level, function, filename, line, message.c_str(), message.size()); \ ++ try { \ ++ constexpr const char *filename = base_name(file); \ ++ auto message = ddwaf::fmt::format(fmt_str, ##__VA_ARGS__); \ ++ ddwaf::logger::log( \ ++ level, function, filename, line, message.c_str(), message.size()); \ ++ } catch (...) {} \ + } \ + } + +diff --git src/semver.hpp src/semver.hpp +index 9719bc4..c4796c4 100644 +--- src/semver.hpp ++++ src/semver.hpp +@@ -114,7 +114,7 @@ protected: + + template <> struct fmt::formatter<semantic_version> : fmt::formatter<std::string_view> { + // Use the parse method from the base class formatter +- template <typename FormatContext> auto format(semantic_version &v, FormatContext &ctx) ++ template <typename FormatContext> auto format(semantic_version &v, FormatContext &ctx) const + { + return fmt::formatter<std::string_view>::format(v.string(), ctx); + } +diff --git src/tokenizer/sql_base.hpp src/tokenizer/sql_base.hpp +index 460b52e..77e142d 100644 +--- src/tokenizer/sql_base.hpp ++++ src/tokenizer/sql_base.hpp +@@ -55,7 +55,7 @@ std::ostream &operator<<(std::ostream &os, sql_dialect dialect); + + template <> struct fmt::formatter<sql_dialect> : fmt::formatter<std::string_view> { + // Use the parse method from the base class formatter +- template <typename FormatContext> auto format(sql_dialect d, FormatContext &ctx) ++ template <typename FormatContext> auto format(sql_dialect d, FormatContext &ctx) const + { + return fmt::formatter<std::string_view>::format(sql_dialect_to_string(d), ctx); + } +diff --git src/vendor/fmt/base.h src/vendor/fmt/base.h +new file mode 100644 +index 0000000..3c12000 +--- /dev/null ++++ src/vendor/fmt/base.h +@@ -0,0 +1,3015 @@ ++// Formatting library for C++ - the base API for char/UTF-8 ++// ++// Copyright (c) 2012 - present, Victor Zverovich ++// All rights reserved. ++// ++// For the license information refer to format.h. ++ ++#ifndef FMT_BASE_H_ ++#define FMT_BASE_H_ ++ ++#define FMT_HEADER_ONLY ++ ++#if defined(FMT_IMPORT_STD) && !defined(FMT_MODULE) ++# define FMT_MODULE ++#endif ++ ++#ifndef FMT_MODULE ++# include <limits.h> // CHAR_BIT ++# include <stdio.h> // FILE ++# include <string.h> // memcmp ++ ++# include <type_traits> // std::enable_if ++#endif ++ ++// The fmt library version in the form major * 10000 + minor * 100 + patch. ++#define FMT_VERSION 120100 ++ ++// Detect compiler versions. ++#if defined(__clang__) && !defined(__ibmxl__) ++# define FMT_CLANG_VERSION (__clang_major__ * 100 + __clang_minor__) ++#else ++# define FMT_CLANG_VERSION 0 ++#endif ++#if defined(__GNUC__) && !defined(__clang__) && !defined(__INTEL_COMPILER) ++# define FMT_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__) ++#else ++# define FMT_GCC_VERSION 0 ++#endif ++#if defined(__ICL) ++# define FMT_ICC_VERSION __ICL ++#elif defined(__INTEL_COMPILER) ++# define FMT_ICC_VERSION __INTEL_COMPILER ++#else ++# define FMT_ICC_VERSION 0 ++#endif ++#if defined(_MSC_VER) ++# define FMT_MSC_VERSION _MSC_VER ++#else ++# define FMT_MSC_VERSION 0 ++#endif ++ ++// Detect standard library versions. ++#ifdef _GLIBCXX_RELEASE ++# define FMT_GLIBCXX_RELEASE _GLIBCXX_RELEASE ++#else ++# define FMT_GLIBCXX_RELEASE 0 ++#endif ++#ifdef _LIBCPP_VERSION ++# define FMT_LIBCPP_VERSION _LIBCPP_VERSION ++#else ++# define FMT_LIBCPP_VERSION 0 ++#endif ++ ++#ifdef _MSVC_LANG ++# define FMT_CPLUSPLUS _MSVC_LANG ++#else ++# define FMT_CPLUSPLUS __cplusplus ++#endif ++ ++// Detect __has_*. ++#ifdef __has_feature ++# define FMT_HAS_FEATURE(x) __has_feature(x) ++#else ++# define FMT_HAS_FEATURE(x) 0 ++#endif ++#ifdef __has_include ++# define FMT_HAS_INCLUDE(x) __has_include(x) ++#else ++# define FMT_HAS_INCLUDE(x) 0 ++#endif ++#ifdef __has_builtin ++# define FMT_HAS_BUILTIN(x) __has_builtin(x) ++#else ++# define FMT_HAS_BUILTIN(x) 0 ++#endif ++#ifdef __has_cpp_attribute ++# define FMT_HAS_CPP_ATTRIBUTE(x) __has_cpp_attribute(x) ++#else ++# define FMT_HAS_CPP_ATTRIBUTE(x) 0 ++#endif ++ ++#define FMT_HAS_CPP14_ATTRIBUTE(attribute) \ ++ (FMT_CPLUSPLUS >= 201402L && FMT_HAS_CPP_ATTRIBUTE(attribute)) ++ ++#define FMT_HAS_CPP17_ATTRIBUTE(attribute) \ ++ (FMT_CPLUSPLUS >= 201703L && FMT_HAS_CPP_ATTRIBUTE(attribute)) ++ ++// Detect C++14 relaxed constexpr. ++#ifdef FMT_USE_CONSTEXPR ++// Use the provided definition. ++#elif FMT_GCC_VERSION >= 702 && FMT_CPLUSPLUS >= 201402L ++// GCC only allows constexpr member functions in non-literal types since 7.2: ++// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66297. ++# define FMT_USE_CONSTEXPR 1 ++#elif FMT_ICC_VERSION ++# define FMT_USE_CONSTEXPR 0 // https://github.com/fmtlib/fmt/issues/1628 ++#elif FMT_HAS_FEATURE(cxx_relaxed_constexpr) || FMT_MSC_VERSION >= 1912 ++# define FMT_USE_CONSTEXPR 1 ++#else ++# define FMT_USE_CONSTEXPR 0 ++#endif ++#if FMT_USE_CONSTEXPR ++# define FMT_CONSTEXPR constexpr ++#else ++# define FMT_CONSTEXPR ++#endif ++ ++// Detect consteval, C++20 constexpr extensions and std::is_constant_evaluated. ++#ifdef FMT_USE_CONSTEVAL ++// Use the provided definition. ++#elif !defined(__cpp_lib_is_constant_evaluated) ++# define FMT_USE_CONSTEVAL 0 ++#elif FMT_CPLUSPLUS < 201709L ++# define FMT_USE_CONSTEVAL 0 ++#elif FMT_GLIBCXX_RELEASE && FMT_GLIBCXX_RELEASE < 10 ++# define FMT_USE_CONSTEVAL 0 ++#elif FMT_LIBCPP_VERSION && FMT_LIBCPP_VERSION < 10000 ++# define FMT_USE_CONSTEVAL 0 ++#elif defined(__apple_build_version__) && __apple_build_version__ < 14000029L ++# define FMT_USE_CONSTEVAL 0 // consteval is broken in Apple clang < 14. ++#elif FMT_MSC_VERSION && FMT_MSC_VERSION < 1929 ++# define FMT_USE_CONSTEVAL 0 // consteval is broken in MSVC VS2019 < 16.10. ++#elif defined(__cpp_consteval) ++# define FMT_USE_CONSTEVAL 1 ++#elif FMT_GCC_VERSION >= 1002 || FMT_CLANG_VERSION >= 1101 ++# define FMT_USE_CONSTEVAL 1 ++#else ++# define FMT_USE_CONSTEVAL 0 ++#endif ++#if FMT_USE_CONSTEVAL ++# define FMT_CONSTEVAL consteval ++# define FMT_CONSTEXPR20 constexpr ++#else ++# define FMT_CONSTEVAL ++# define FMT_CONSTEXPR20 ++#endif ++ ++// Check if exceptions are disabled. ++#ifdef FMT_USE_EXCEPTIONS ++// Use the provided definition. ++#elif defined(__GNUC__) && !defined(__EXCEPTIONS) ++# define FMT_USE_EXCEPTIONS 0 ++#elif defined(__clang__) && !defined(__cpp_exceptions) ++# define FMT_USE_EXCEPTIONS 0 ++#elif FMT_MSC_VERSION && !_HAS_EXCEPTIONS ++# define FMT_USE_EXCEPTIONS 0 ++#else ++# define FMT_USE_EXCEPTIONS 1 ++#endif ++#if FMT_USE_EXCEPTIONS ++# define FMT_TRY try ++# define FMT_CATCH(x) catch (x) ++#else ++# define FMT_TRY if (true) ++# define FMT_CATCH(x) if (false) ++#endif ++ ++#ifdef FMT_NO_UNIQUE_ADDRESS ++// Use the provided definition. ++#elif FMT_CPLUSPLUS < 202002L ++// Not supported. ++#elif FMT_HAS_CPP_ATTRIBUTE(no_unique_address) ++# define FMT_NO_UNIQUE_ADDRESS [[no_unique_address]] ++// VS2019 v16.10 and later except clang-cl (https://reviews.llvm.org/D110485). ++#elif FMT_MSC_VERSION >= 1929 && !FMT_CLANG_VERSION ++# define FMT_NO_UNIQUE_ADDRESS [[msvc::no_unique_address]] ++#endif ++#ifndef FMT_NO_UNIQUE_ADDRESS ++# define FMT_NO_UNIQUE_ADDRESS ++#endif ++ ++#if FMT_HAS_CPP17_ATTRIBUTE(fallthrough) ++# define FMT_FALLTHROUGH [[fallthrough]] ++#elif defined(__clang__) ++# define FMT_FALLTHROUGH [[clang::fallthrough]] ++#elif FMT_GCC_VERSION >= 700 && \ ++ (!defined(__EDG_VERSION__) || __EDG_VERSION__ >= 520) ++# define FMT_FALLTHROUGH [[gnu::fallthrough]] ++#else ++# define FMT_FALLTHROUGH ++#endif ++ ++// Disable [[noreturn]] on MSVC/NVCC because of bogus unreachable code warnings. ++#if FMT_HAS_CPP_ATTRIBUTE(noreturn) && !FMT_MSC_VERSION && !defined(__NVCC__) ++# define FMT_NORETURN [[noreturn]] ++#else ++# define FMT_NORETURN ++#endif ++ ++#ifdef FMT_NODISCARD ++// Use the provided definition. ++#elif FMT_HAS_CPP17_ATTRIBUTE(nodiscard) ++# define FMT_NODISCARD [[nodiscard]] ++#else ++# define FMT_NODISCARD ++#endif ++ ++#if FMT_GCC_VERSION || FMT_CLANG_VERSION ++# define FMT_VISIBILITY(value) __attribute__((visibility(value))) ++#else ++# define FMT_VISIBILITY(value) ++#endif ++ ++// Detect pragmas. ++#define FMT_PRAGMA_IMPL(x) _Pragma(#x) ++#if FMT_GCC_VERSION >= 504 && !defined(__NVCOMPILER) ++// Workaround a _Pragma bug https://gcc.gnu.org/bugzilla/show_bug.cgi?id=59884 ++// and an nvhpc warning: https://github.com/fmtlib/fmt/pull/2582. ++# define FMT_PRAGMA_GCC(x) FMT_PRAGMA_IMPL(GCC x) ++#else ++# define FMT_PRAGMA_GCC(x) ++#endif ++#if FMT_CLANG_VERSION ++# define FMT_PRAGMA_CLANG(x) FMT_PRAGMA_IMPL(clang x) ++#else ++# define FMT_PRAGMA_CLANG(x) ++#endif ++#if FMT_MSC_VERSION ++# define FMT_MSC_WARNING(...) __pragma(warning(__VA_ARGS__)) ++#else ++# define FMT_MSC_WARNING(...) ++#endif ++ ++// Enable minimal optimizations for more compact code in debug mode. ++FMT_PRAGMA_GCC(push_options) ++#if !defined(__OPTIMIZE__) && !defined(__CUDACC__) && !defined(FMT_MODULE) ++FMT_PRAGMA_GCC(optimize("Og")) ++#endif ++FMT_PRAGMA_CLANG(diagnostic push) ++FMT_PRAGMA_GCC(diagnostic push) ++ ++#ifdef FMT_ALWAYS_INLINE ++// Use the provided definition. ++#elif FMT_GCC_VERSION || FMT_CLANG_VERSION ++# define FMT_ALWAYS_INLINE inline __attribute__((always_inline)) ++#else ++# define FMT_ALWAYS_INLINE inline ++#endif ++// A version of FMT_ALWAYS_INLINE to prevent code bloat in debug mode. ++#ifdef NDEBUG ++# define FMT_INLINE FMT_ALWAYS_INLINE ++#else ++# define FMT_INLINE inline ++#endif ++ ++#ifndef FMT_BEGIN_NAMESPACE ++# define FMT_BEGIN_NAMESPACE \ ++ namespace ddwaf { \ ++ namespace fmt { \ ++ inline namespace v12 { ++# define FMT_END_NAMESPACE \ ++ } \ ++ } \ ++ } ++#endif ++ ++#ifndef FMT_EXPORT ++# define FMT_EXPORT ++# define FMT_BEGIN_EXPORT ++# define FMT_END_EXPORT ++#endif ++ ++#ifdef _WIN32 ++# define FMT_WIN32 1 ++#else ++# define FMT_WIN32 0 ++#endif ++ ++#if !defined(FMT_HEADER_ONLY) && FMT_WIN32 ++# if defined(FMT_LIB_EXPORT) ++# define FMT_API __declspec(dllexport) ++# elif defined(FMT_SHARED) ++# define FMT_API __declspec(dllimport) ++# endif ++#elif defined(FMT_LIB_EXPORT) || defined(FMT_SHARED) ++# define FMT_API FMT_VISIBILITY("default") ++#endif ++#ifndef FMT_API ++# define FMT_API ++#endif ++ ++#ifndef FMT_OPTIMIZE_SIZE ++# define FMT_OPTIMIZE_SIZE 0 ++#endif ++ ++// FMT_BUILTIN_TYPE=0 may result in smaller library size at the cost of higher ++// per-call binary size by passing built-in types through the extension API. ++#ifndef FMT_BUILTIN_TYPES ++# define FMT_BUILTIN_TYPES 1 ++#endif ++ ++#define FMT_APPLY_VARIADIC(expr) \ ++ using unused = int[]; \ ++ (void)unused { 0, (expr, 0)... } ++ ++FMT_BEGIN_NAMESPACE ++ ++// Implementations of enable_if_t and other metafunctions for older systems. ++template <bool B, typename T = void> ++using enable_if_t = typename std::enable_if<B, T>::type; ++template <bool B, typename T, typename F> ++using conditional_t = typename std::conditional<B, T, F>::type; ++template <bool B> using bool_constant = std::integral_constant<bool, B>; ++template <typename T> ++using remove_reference_t = typename std::remove_reference<T>::type; ++template <typename T> ++using remove_const_t = typename std::remove_const<T>::type; ++template <typename T> ++using remove_cvref_t = typename std::remove_cv<remove_reference_t<T>>::type; ++template <typename T> ++using make_unsigned_t = typename std::make_unsigned<T>::type; ++template <typename T> ++using underlying_t = typename std::underlying_type<T>::type; ++template <typename T> using decay_t = typename std::decay<T>::type; ++using nullptr_t = decltype(nullptr); ++ ++#if (FMT_GCC_VERSION && FMT_GCC_VERSION < 500) || FMT_MSC_VERSION ++// A workaround for gcc 4.9 & MSVC v141 to make void_t work in a SFINAE context. ++template <typename...> struct void_t_impl { ++ using type = void; ++}; ++template <typename... T> using void_t = typename void_t_impl<T...>::type; ++#else ++template <typename...> using void_t = void; ++#endif ++ ++struct monostate { ++ constexpr monostate() {} ++}; ++ ++// An enable_if helper to be used in template parameters which results in much ++// shorter symbols: https://godbolt.org/z/sWw4vP. Extra parentheses are needed ++// to workaround a bug in MSVC 2019 (see #1140 and #1186). ++#ifdef FMT_DOC ++# define FMT_ENABLE_IF(...) ++#else ++# define FMT_ENABLE_IF(...) fmt::enable_if_t<(__VA_ARGS__), int> = 0 ++#endif ++ ++template <typename T> constexpr auto min_of(T a, T b) -> T { ++ return a < b ? a : b; ++} ++template <typename T> constexpr auto max_of(T a, T b) -> T { ++ return a > b ? a : b; ++} ++ ++FMT_NORETURN FMT_API void assert_fail(const char* file, int line, ++ const char* message); ++ ++namespace detail { ++// Suppresses "unused variable" warnings with the method described in ++// https://herbsutter.com/2009/10/18/mailbag-shutting-up-compiler-warnings/. ++// (void)var does not work on many Intel compilers. ++template <typename... T> FMT_CONSTEXPR void ignore_unused(const T&...) {} ++ ++constexpr auto is_constant_evaluated(bool default_value = false) noexcept ++ -> bool { ++// Workaround for incompatibility between clang 14 and libstdc++ consteval-based ++// std::is_constant_evaluated: https://github.com/fmtlib/fmt/issues/3247. ++#if FMT_CPLUSPLUS >= 202002L && FMT_GLIBCXX_RELEASE >= 12 && \ ++ (FMT_CLANG_VERSION >= 1400 && FMT_CLANG_VERSION < 1500) ++ ignore_unused(default_value); ++ return __builtin_is_constant_evaluated(); ++#elif defined(__cpp_lib_is_constant_evaluated) ++ ignore_unused(default_value); ++ return std::is_constant_evaluated(); ++#else ++ return default_value; ++#endif ++} ++ ++// Suppresses "conditional expression is constant" warnings. ++template <typename T> FMT_ALWAYS_INLINE constexpr auto const_check(T val) -> T { ++ return val; ++} ++ ++FMT_NORETURN FMT_API void assert_fail(const char* file, int line, ++ const char* message); ++ ++#if defined(FMT_ASSERT) ++// Use the provided definition. ++#elif defined(NDEBUG) ++// FMT_ASSERT is not empty to avoid -Wempty-body. ++# define FMT_ASSERT(condition, message) \ ++ fmt::detail::ignore_unused((condition), (message)) ++#else ++# define FMT_ASSERT(condition, message) \ ++ ((condition) /* void() fails with -Winvalid-constexpr on clang 4.0.1 */ \ ++ ? (void)0 \ ++ : ::ddwaf::fmt::assert_fail(__FILE__, __LINE__, (message))) ++#endif ++ ++#ifdef FMT_USE_INT128 ++// Use the provided definition. ++#elif defined(__SIZEOF_INT128__) && !defined(__NVCC__) && \ ++ !(FMT_CLANG_VERSION && FMT_MSC_VERSION) ++# define FMT_USE_INT128 1 ++using int128_opt = __int128_t; // An optional native 128-bit integer. ++using uint128_opt = __uint128_t; ++inline auto map(int128_opt x) -> int128_opt { return x; } ++inline auto map(uint128_opt x) -> uint128_opt { return x; } ++#else ++# define FMT_USE_INT128 0 ++#endif ++#if !FMT_USE_INT128 ++enum class int128_opt {}; ++enum class uint128_opt {}; ++// Reduce template instantiations. ++inline auto map(int128_opt) -> monostate { return {}; } ++inline auto map(uint128_opt) -> monostate { return {}; } ++#endif ++ ++#ifdef FMT_USE_BITINT ++// Use the provided definition. ++#elif FMT_CLANG_VERSION >= 1500 && !defined(__CUDACC__) ++# define FMT_USE_BITINT 1 ++#else ++# define FMT_USE_BITINT 0 ++#endif ++ ++#if FMT_USE_BITINT ++FMT_PRAGMA_CLANG(diagnostic ignored "-Wbit-int-extension") ++template <int N> using bitint = _BitInt(N); ++template <int N> using ubitint = unsigned _BitInt(N); ++#else ++template <int N> struct bitint {}; ++template <int N> struct ubitint {}; ++#endif // FMT_USE_BITINT ++ ++// Casts a nonnegative integer to unsigned. ++template <typename Int> ++FMT_CONSTEXPR auto to_unsigned(Int value) -> make_unsigned_t<Int> { ++ FMT_ASSERT(std::is_unsigned<Int>::value || value >= 0, "negative value"); ++ return static_cast<make_unsigned_t<Int>>(value); ++} ++ ++template <typename Char> ++using unsigned_char = conditional_t<sizeof(Char) == 1, unsigned char, unsigned>; ++ ++// A heuristic to detect std::string and std::[experimental::]string_view. ++// It is mainly used to avoid dependency on <[experimental/]string_view>. ++template <typename T, typename Enable = void> ++struct is_std_string_like : std::false_type {}; ++template <typename T> ++struct is_std_string_like<T, void_t<decltype(std::declval<T>().find_first_of( ++ typename T::value_type(), 0))>> ++ : std::is_convertible<decltype(std::declval<T>().data()), ++ const typename T::value_type*> {}; ++ ++// Check if the literal encoding is UTF-8. ++enum { is_utf8_enabled = "\u00A7"[1] == '\xA7' }; ++enum { use_utf8 = !FMT_WIN32 || is_utf8_enabled }; ++ ++#ifndef FMT_UNICODE ++# define FMT_UNICODE 1 ++#endif ++ ++static_assert(!FMT_UNICODE || use_utf8, ++ "Unicode support requires compiling with /utf-8"); ++ ++template <typename T> constexpr auto narrow(T*) -> char* { return nullptr; } ++constexpr FMT_ALWAYS_INLINE auto narrow(const char* s) -> const char* { ++ return s; ++} ++ ++template <typename Char> ++FMT_CONSTEXPR auto compare(const Char* s1, const Char* s2, size_t n) -> int { ++ if (!is_constant_evaluated() && sizeof(Char) == 1) return memcmp(s1, s2, n); ++ for (; n != 0; ++s1, ++s2, --n) { ++ if (*s1 < *s2) return -1; ++ if (*s1 > *s2) return 1; ++ } ++ return 0; ++} ++ ++namespace adl { ++using namespace std; ++ ++template <typename Container> ++auto invoke_back_inserter() ++ -> decltype(back_inserter(std::declval<Container&>())); ++} // namespace adl ++ ++template <typename It, typename Enable = std::true_type> ++struct is_back_insert_iterator : std::false_type {}; ++ ++template <typename It> ++struct is_back_insert_iterator< ++ It, bool_constant<std::is_same< ++ decltype(adl::invoke_back_inserter<typename It::container_type>()), ++ It>::value>> : std::true_type {}; ++ ++// Extracts a reference to the container from *insert_iterator. ++template <typename OutputIt> ++inline FMT_CONSTEXPR20 auto get_container(OutputIt it) -> ++ typename OutputIt::container_type& { ++ struct accessor : OutputIt { ++ FMT_CONSTEXPR20 accessor(OutputIt base) : OutputIt(base) {} ++ using OutputIt::container; ++ }; ++ return *accessor(it).container; ++} ++} // namespace detail ++ ++// Parsing-related public API and forward declarations. ++FMT_BEGIN_EXPORT ++ ++/** ++ * An implementation of `std::basic_string_view` for pre-C++17. It provides a ++ * subset of the API. `fmt::basic_string_view` is used for format strings even ++ * if `std::basic_string_view` is available to prevent issues when a library is ++ * compiled with a different `-std` option than the client code (which is not ++ * recommended). ++ */ ++template <typename Char> class basic_string_view { ++ private: ++ const Char* data_; ++ size_t size_; ++ ++ public: ++ using value_type = Char; ++ using iterator = const Char*; ++ ++ constexpr basic_string_view() noexcept : data_(nullptr), size_(0) {} ++ ++ /// Constructs a string view object from a C string and a size. ++ constexpr basic_string_view(const Char* s, size_t count) noexcept ++ : data_(s), size_(count) {} ++ ++ constexpr basic_string_view(nullptr_t) = delete; ++ ++ /// Constructs a string view object from a C string. ++#if FMT_GCC_VERSION ++ FMT_ALWAYS_INLINE ++#endif ++ FMT_CONSTEXPR20 basic_string_view(const Char* s) : data_(s) { ++#if FMT_HAS_BUILTIN(__builtin_strlen) || FMT_GCC_VERSION || FMT_CLANG_VERSION ++ if (std::is_same<Char, char>::value && !detail::is_constant_evaluated()) { ++ size_ = __builtin_strlen(detail::narrow(s)); // strlen is not constexpr. ++ return; ++ } ++#endif ++ size_t len = 0; ++ while (*s++) ++len; ++ size_ = len; ++ } ++ ++ /// Constructs a string view from a `std::basic_string` or a ++ /// `std::basic_string_view` object. ++ template <typename S, ++ FMT_ENABLE_IF(detail::is_std_string_like<S>::value&& std::is_same< ++ typename S::value_type, Char>::value)> ++ FMT_CONSTEXPR basic_string_view(const S& s) noexcept ++ : data_(s.data()), size_(s.size()) {} ++ ++ /// Returns a pointer to the string data. ++ constexpr auto data() const noexcept -> const Char* { return data_; } ++ ++ /// Returns the string size. ++ constexpr auto size() const noexcept -> size_t { return size_; } ++ ++ constexpr auto begin() const noexcept -> iterator { return data_; } ++ constexpr auto end() const noexcept -> iterator { return data_ + size_; } ++ ++ constexpr auto operator[](size_t pos) const noexcept -> const Char& { ++ return data_[pos]; ++ } ++ ++ FMT_CONSTEXPR void remove_prefix(size_t n) noexcept { ++ data_ += n; ++ size_ -= n; ++ } ++ ++ FMT_CONSTEXPR auto starts_with(basic_string_view<Char> sv) const noexcept ++ -> bool { ++ return size_ >= sv.size_ && detail::compare(data_, sv.data_, sv.size_) == 0; ++ } ++ FMT_CONSTEXPR auto starts_with(Char c) const noexcept -> bool { ++ return size_ >= 1 && *data_ == c; ++ } ++ FMT_CONSTEXPR auto starts_with(const Char* s) const -> bool { ++ return starts_with(basic_string_view<Char>(s)); ++ } ++ ++ FMT_CONSTEXPR auto compare(basic_string_view other) const -> int { ++ int result = ++ detail::compare(data_, other.data_, min_of(size_, other.size_)); ++ if (result != 0) return result; ++ return size_ == other.size_ ? 0 : (size_ < other.size_ ? -1 : 1); ++ } ++ ++ FMT_CONSTEXPR friend auto operator==(basic_string_view lhs, ++ basic_string_view rhs) -> bool { ++ return lhs.compare(rhs) == 0; ++ } ++ friend auto operator!=(basic_string_view lhs, basic_string_view rhs) -> bool { ++ return lhs.compare(rhs) != 0; ++ } ++ friend auto operator<(basic_string_view lhs, basic_string_view rhs) -> bool { ++ return lhs.compare(rhs) < 0; ++ } ++ friend auto operator<=(basic_string_view lhs, basic_string_view rhs) -> bool { ++ return lhs.compare(rhs) <= 0; ++ } ++ friend auto operator>(basic_string_view lhs, basic_string_view rhs) -> bool { ++ return lhs.compare(rhs) > 0; ++ } ++ friend auto operator>=(basic_string_view lhs, basic_string_view rhs) -> bool { ++ return lhs.compare(rhs) >= 0; ++ } ++}; ++ ++using string_view = basic_string_view<char>; ++ ++template <typename T> class basic_appender; ++using appender = basic_appender<char>; ++ ++// Checks whether T is a container with contiguous storage. ++template <typename T> struct is_contiguous : std::false_type {}; ++ ++class context; ++template <typename OutputIt, typename Char> class generic_context; ++template <typename Char> class parse_context; ++ ++// Longer aliases for C++20 compatibility. ++template <typename Char> using basic_format_parse_context = parse_context<Char>; ++using format_parse_context = parse_context<char>; ++template <typename OutputIt, typename Char> ++using basic_format_context = ++ conditional_t<std::is_same<OutputIt, appender>::value, context, ++ generic_context<OutputIt, Char>>; ++using format_context = context; ++ ++template <typename Char> ++using buffered_context = ++ conditional_t<std::is_same<Char, char>::value, context, ++ generic_context<basic_appender<Char>, Char>>; ++ ++template <typename Context> class basic_format_arg; ++template <typename Context> class basic_format_args; ++ ++// A separate type would result in shorter symbols but break ABI compatibility ++// between clang and gcc on ARM (#1919). ++using format_args = basic_format_args<context>; ++ ++// A formatter for objects of type T. ++template <typename T, typename Char = char, typename Enable = void> ++struct formatter { ++ // A deleted default constructor indicates a disabled formatter. ++ formatter() = delete; ++}; ++ ++/// Reports a format error at compile time or, via a `format_error` exception, ++/// at runtime. ++// This function is intentionally not constexpr to give a compile-time error. ++FMT_NORETURN FMT_API void report_error(const char* message); ++ ++enum class presentation_type : unsigned char { ++ // Common specifiers: ++ none = 0, ++ debug = 1, // '?' ++ string = 2, // 's' (string, bool) ++ ++ // Integral, bool and character specifiers: ++ dec = 3, // 'd' ++ hex, // 'x' or 'X' ++ oct, // 'o' ++ bin, // 'b' or 'B' ++ chr, // 'c' ++ ++ // String and pointer specifiers: ++ pointer = 3, // 'p' ++ ++ // Floating-point specifiers: ++ exp = 1, // 'e' or 'E' (1 since there is no FP debug presentation) ++ fixed, // 'f' or 'F' ++ general, // 'g' or 'G' ++ hexfloat // 'a' or 'A' ++}; ++ ++enum class align { none, left, right, center, numeric }; ++enum class sign { none, minus, plus, space }; ++enum class arg_id_kind { none, index, name }; ++ ++// Basic format specifiers for built-in and string types. ++class basic_specs { ++ private: ++ // Data is arranged as follows: ++ // ++ // 0 1 2 3 ++ // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 ++ // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ++ // |type |align| w | p | s |u|#|L| f | unused | ++ // +-----+-----+---+---+---+-+-+-+-----+---------------------------+ ++ // ++ // w - dynamic width info ++ // p - dynamic precision info ++ // s - sign ++ // u - uppercase (e.g. 'X' for 'x') ++ // # - alternate form ('#') ++ // L - localized ++ // f - fill size ++ // ++ // Bitfields are not used because of compiler bugs such as gcc bug 61414. ++ enum : unsigned { ++ type_mask = 0x00007, ++ align_mask = 0x00038, ++ width_mask = 0x000C0, ++ precision_mask = 0x00300, ++ sign_mask = 0x00C00, ++ uppercase_mask = 0x01000, ++ alternate_mask = 0x02000, ++ localized_mask = 0x04000, ++ fill_size_mask = 0x38000, ++ ++ align_shift = 3, ++ width_shift = 6, ++ precision_shift = 8, ++ sign_shift = 10, ++ fill_size_shift = 15, ++ ++ max_fill_size = 4 *** 12102 LINES SKIPPED ***home | help
Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?6991c498.3f38e.705915b7>
