On Tue, Jun 02, 2026 at 01:10:45PM +0800, Kevin Lo wrote: > On Sun, May 31, 2026 at 07:15:57PM +0200, Christian Weisgerber wrote: > > > > http://build-failures.rhaalovely.net/amd64/2026-05-30/ > > [snip] > > > inputmethods/libime ports@ > > Use -O1 on datrie.cpp otherwise build fails with SIGSEGV in libime_prediction.
This seems to be resolved via https://github.com/fcitx/libime/pull/99 At least the below backport of that PR builds on amd64. Even better would be an update to >= 1.1.11. Index: Makefile =================================================================== RCS file: /cvs/ports/inputmethods/libime/Makefile,v diff -u -p -r1.13 Makefile --- Makefile 23 Mar 2026 06:22:51 -0000 1.13 +++ Makefile 2 Jun 2026 05:22:25 -0000 @@ -1,7 +1,7 @@ COMMENT = library to support generic input method implementation DISTNAME = libime-1.1.9 -REVISION = 3 +REVISION = 4 SHARED_LIBS += IMECore 0.2 # 0.0 SHARED_LIBS += IMEPinyin 0.2 # 0.0 Index: patches/patch-src_libime_core_datrie_cpp =================================================================== RCS file: patches/patch-src_libime_core_datrie_cpp diff -N patches/patch-src_libime_core_datrie_cpp --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ patches/patch-src_libime_core_datrie_cpp 2 Jun 2026 05:22:22 -0000 @@ -0,0 +1,172 @@ +Avoid UB breaking the build with llvm22 + +https://github.com/fcitx/libime/pull/99 + +Index: src/libime/core/datrie.cpp +--- src/libime/core/datrie.cpp.orig ++++ src/libime/core/datrie.cpp +@@ -23,7 +23,9 @@ + #include <fstream> + #include <ios> + #include <istream> ++#include <iterator> + #include <limits> ++#include <optional> + #include <ostream> + #include <stdexcept> + #include <string> +@@ -96,7 +98,8 @@ class DATriePrivate { (public) + static inline const int32_t CEDAR_NO_VALUE = NanValue<V>::NO_VALUE(); + static inline const int32_t CEDAR_NO_PATH = NanValue<V>::NO_PATH(); + +- static constexpr int MAX_ALLOC_SIZE = 1 << 16; // must be divisible by 256 ++ static constexpr size_t MAX_ALLOC_SIZE = 1 ++ << 16; // must be divisible by 256 + using result_type = value_type; + using uchar = uint8_t; + static_assert(sizeof(value_type) <= sizeof(int32_t), +@@ -481,10 +484,7 @@ class DATriePrivate { (public) + if (m_tail.capacity() < m_tail.size() + needed) { + auto quota = + m_tail.capacity() + +- ((needed > m_tail.size() || needed > MAX_ALLOC_SIZE) +- ? needed +- : (m_tail.size() >= MAX_ALLOC_SIZE ? MAX_ALLOC_SIZE +- : m_tail.size())); ++ std::max(needed, std::min(MAX_ALLOC_SIZE, m_tail.size())); + m_tail.reserve(quota); + } + m_array[from].base = -m_tail.size(); +@@ -592,8 +592,11 @@ class DATriePrivate { (public) + npos.offset ? -static_cast<int>(npos.offset) : m_array[from].base; + if (base >= 0) { // on trie + uchar c = m_ninfo[from].child; +- if (!from && !(c = m_ninfo[base ^ c].sibling)) { // bug fix +- return CEDAR_NO_PATH; // no entry ++ if (!from) { ++ c = m_ninfo[base ^ c].sibling; ++ if (!c) { // bug fix ++ return CEDAR_NO_PATH; // no entry ++ } + } + for (; c && base >= 0; ++len) { + from = static_cast<size_t>(base) ^ c; +@@ -638,11 +641,13 @@ class DATriePrivate { (public) + int _follow(uint32_t &from, const uchar label, const T &cf) { + int to = 0; + const int base = m_array[from].base; +- if (base < 0 || m_array[to = base ^ label].check < 0) { ++ if (base < 0 || m_array[base ^ label].check < 0) { + to = _pop_enode(base, label, static_cast<int>(from)); + _push_sibling(from, to ^ label, label, base >= 0); +- } else if (m_array[to].check != static_cast<int>(from)) { ++ } else if (m_array[base ^ label].check != static_cast<int>(from)) { + to = _resolve(from, base, label, cf); ++ } else { ++ to = base ^ label; + } + return to; + } +@@ -707,7 +712,7 @@ class DATriePrivate { (public) + int _find_place(const uchar *const first, const uchar *const last) { + if (auto bi = m_bheadO) { + const auto bz = m_block[m_bheadO].prev; +- const auto nc = static_cast<short>(last - first + 1); ++ const auto nc = std::distance(first, last); + while (true) { // set candidate block + block &b = m_block[bi]; + if (b.num >= nc && nc < b.reject) { // explore configuration +@@ -715,11 +720,13 @@ class DATriePrivate { (public) + const int base = e ^ *first; + for (const uchar *p = first; + m_array[base ^ *++p].check < 0;) { +- if (p == last) { +- return b.ehead = e; // no conflict ++ if (p + 1 == last) { ++ b.ehead = e; ++ return b.ehead; // no conflict + } + } +- if ((e = -m_array[e].check) == b.ehead) { ++ e = -m_array[e].check; ++ if (e == b.ehead) { + break; + } + } +@@ -892,23 +899,27 @@ class DATriePrivate { (public) + return c_p; + } + // enumerate (equal to or more than one) child nodes +- uchar *_set_child(uchar *p, const int base, uchar c, const int label = -1) { +- --p; ++ uchar *_set_child(uchar *p, const int base, uchar c, ++ const std::optional<uchar> label = std::nullopt) { + if (!c) { +- *++p = c; ++ *p = c; ++ p++; + c = m_ninfo[base ^ c].sibling; + } // 0: terminal +- if (ORDERED) { +- while (c && c < label) { +- *++p = c; ++ if (ORDERED && label.has_value()) { ++ while (c && c < *label) { ++ *p = c; ++ p++; + c = m_ninfo[base ^ c].sibling; + } + } +- if (label != -1) { +- *++p = static_cast<uchar>(label); ++ if (label.has_value()) { ++ *p = *label; ++ p++; + } + while (c) { +- *++p = c; ++ *p = c; ++ p++; + c = m_ninfo[base ^ c].sibling; + } + return p; +@@ -925,30 +936,33 @@ class DATriePrivate { (public) + = _consult(base_n, base_p, m_ninfo[from_n].child, + m_ninfo[from_p].child); + uchar child[256]; +- uchar *const first = &child[0]; ++ uchar *const first = child; + uchar *const last = + flag ? _set_child(first, base_n, m_ninfo[from_n].child, label_n) + : _set_child(first, base_p, m_ninfo[from_p].child); ++ assert(first < last); + const int base = +- (first == last ? _find_place() : _find_place(first, last)) ^ *first; ++ (first + 1 == last ? _find_place() : _find_place(first, last)) ^ ++ *first; + // replace & modify empty list + const int from = flag ? static_cast<int>(from_n) : from_p; + const int base_ = flag ? base_n : base_p; + if (flag && *first == label_n) { + m_ninfo[from].child = label_n; // new child + } +- m_array[from].base = base; // new base +- for (const uchar *p = first; p <= last; ++p) { // to_ => to ++ m_array[from].base = base; // new base ++ for (const uchar *p = first; p < last; ++p) { // to_ => to + const int to = _pop_enode(base, *p, from); + const int to_ = base_ ^ *p; +- m_ninfo[to].sibling = (p == last ? 0 : *(p + 1)); ++ m_ninfo[to].sibling = (p + 1 == last) ? 0 : *(p + 1); + if (flag && to_ == to_pn) { + continue; // skip newcomer (no child) + } + cf(to_, to); + node &n = m_array[to]; + node &n_ = m_array[to_]; +- if ((n.base = n_.base) > 0 && *p) { // copy base; bug fix ++ n.base = n_.base; // copy base; bug fix ++ if (n.base > 0 && *p) { + uchar c = m_ninfo[to].child = m_ninfo[to_].child; + do { + m_array[n.base ^ c].check = to; // adjust grand son's check
