Download raw body.
amd64 build failures 2026-05-30
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
amd64 build failures 2026-05-30