On Tue, Jun 02, 2026 at 07:25:39AM +0200, Theo Buehler wrote: > > 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.
Thanks, this looks much better than mine. Tested on amd64, builds and works. > 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 >
