This is an automated email from the ASF dual-hosted git repository.

jimjag pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/openoffice.git


The following commit(s) were added to refs/heads/trunk by this push:
     new 4ca7e75a8a bridges: add arm64 RTTI synthesis QA harnesses
4ca7e75a8a is described below

commit 4ca7e75a8a392f3dadfa2bcceac9342116803c9d
Author: Jim Jagielski <[email protected]>
AuthorDate: Mon Aug 3 14:36:56 2026 -0400

    bridges: add arm64 RTTI synthesis QA harnesses
---
 .../qa/keyless_rtti_visibility_demo.cxx            |  19 ++++
 .../qa/rtti_crossdylib_test/catcher.cxx            |  10 ++
 .../qa/rtti_crossdylib_test/thrower.cxx            |  47 ++++++++
 .../qa/rtti_crossdylib_test/uno_like.hxx           |   5 +
 .../qa/rtti_synthesis_test.cxx                     | 120 +++++++++++++++++++++
 5 files changed, 201 insertions(+)

diff --git 
a/main/bridges/source/cpp_uno/s5abi_macosx_aarch64/qa/keyless_rtti_visibility_demo.cxx
 
b/main/bridges/source/cpp_uno/s5abi_macosx_aarch64/qa/keyless_rtti_visibility_demo.cxx
new file mode 100644
index 0000000000..b066071014
--- /dev/null
+++ 
b/main/bridges/source/cpp_uno/s5abi_macosx_aarch64/qa/keyless_rtti_visibility_demo.cxx
@@ -0,0 +1,19 @@
+// Demonstrates why arm64 Darwin needs the RTTI synthesis in except.cxx: a
+// class with no key function (every UNO exception, since they declare no
+// virtual functions) gets hidden ("weak private external") typeinfo on
+// arm64 regardless of visibility attributes, whereas the same class gets
+// exported ("weak external") typeinfo on x86_64.  Compare:
+//
+//   clang++ -arch arm64  -c keyless_rtti_visibility_demo.cxx && nm -m 
keyless_rtti_visibility_demo.o | grep __ZTI
+//   clang++ -arch x86_64 -c keyless_rtti_visibility_demo.cxx && nm -m 
keyless_rtti_visibility_demo.o | grep __ZTI
+//
+// A/B (keyless) are hidden on arm64 and exported on x86_64; C/D (have a key
+// function) are exported on both, with or without the visibility attribute.
+struct A { int x; };
+struct __attribute__((visibility("default"))) B { int x; };
+struct C { int x; virtual void key(); };
+void C::key() {}
+struct __attribute__((visibility("default"))) D { int x; virtual void key(); };
+void D::key() {}
+#include <typeinfo>
+const void* refs[] = { &typeid(A), &typeid(B), &typeid(C), &typeid(D) };
diff --git 
a/main/bridges/source/cpp_uno/s5abi_macosx_aarch64/qa/rtti_crossdylib_test/catcher.cxx
 
b/main/bridges/source/cpp_uno/s5abi_macosx_aarch64/qa/rtti_crossdylib_test/catcher.cxx
new file mode 100644
index 0000000000..8fdbcb5324
--- /dev/null
+++ 
b/main/bridges/source/cpp_uno/s5abi_macosx_aarch64/qa/rtti_crossdylib_test/catcher.cxx
@@ -0,0 +1,10 @@
+// See thrower.cxx for build/run instructions and expected output.
+#include "uno_like.hxx"
+#include <cstdio>
+extern "C" void throw_synth();
+int main() {
+    try { throw_synth(); }
+    catch (com::sun::star::ucb::InteractiveAugmentedIOException&) { 
printf("RESULT: caught as EXACT derived type  (WORKS)\n"); return 0; }
+    catch (com::sun::star::uno::Exception&) { printf("RESULT: caught as BASE 
css::uno::Exception (WORKS)\n"); return 0; }
+    catch (...) { printf("RESULT: caught only by catch(...)  (BROKEN)\n"); 
return 1; }
+}
diff --git 
a/main/bridges/source/cpp_uno/s5abi_macosx_aarch64/qa/rtti_crossdylib_test/thrower.cxx
 
b/main/bridges/source/cpp_uno/s5abi_macosx_aarch64/qa/rtti_crossdylib_test/thrower.cxx
new file mode 100644
index 0000000000..acc100be5d
--- /dev/null
+++ 
b/main/bridges/source/cpp_uno/s5abi_macosx_aarch64/qa/rtti_crossdylib_test/thrower.cxx
@@ -0,0 +1,47 @@
+// Cross-image ABI harness: synthesizes RTTI for a whole exception chain
+// (neither type dlsym-able, mirroring how the real bridge is used) and
+// throws it from a separate dylib.  Not wired into gbuild; build and run
+// manually:
+//
+//   clang++ -std=c++11 -arch arm64 -dynamiclib -o libthrower.dylib 
thrower.cxx \
+//           -install_name @rpath/libthrower.dylib
+//   clang++ -std=c++11 -arch arm64 -o catcher catcher.cxx -L. -lthrower \
+//           -Wl,-rpath,@executable_path
+//   ./catcher
+//
+// Expected: "RESULT: caught as EXACT derived type  (WORKS)".
+#include "uno_like.hxx"
+#include <typeinfo>
+#include <cstring>
+#include <cstdlib>
+#include <cstdint>
+#include <cstdio>
+extern "C" void* __cxa_allocate_exception(size_t) throw();
+extern "C" void __cxa_throw(void*, std::type_info*, void (*)(void*)) 
__attribute__((noreturn));
+// vtable donors: real, compiler-emitted, in THIS dylib
+namespace { struct DonorBase { int a; }; struct DonorDerived : DonorBase { int 
b; }; }
+struct ClassTi { void const* vptr; uintptr_t name; };
+struct SiTi    { void const* vptr; uintptr_t name; void const* base; };
+static const uintptr_t NONUNIQUE = 1ULL << 63;
+static uintptr_t mkname(const char* s){ return (uintptr_t)strdup(s) | 
NONUNIQUE; }
+static std::type_info* synth_base() {
+    static ClassTi* t = 0;
+    if (!t) { t = (ClassTi*)calloc(1,sizeof(ClassTi));
+        t->vptr = ((ClassTi const*)&typeid(DonorBase))->vptr;
+        t->name = mkname("N3com3sun4star3uno9ExceptionE"); }
+    return (std::type_info*)t;
+}
+static std::type_info* synth_derived() {
+    static SiTi* t = 0;
+    if (!t) { t = (SiTi*)calloc(1,sizeof(SiTi));
+        t->vptr = ((SiTi const*)&typeid(DonorDerived))->vptr;
+        t->name = 
mkname("N3com3sun4star3ucb31InteractiveAugmentedIOExceptionE");
+        t->base = synth_base(); }
+    return (std::type_info*)t;
+}
+static void nodel(void*) {}
+extern "C" __attribute__((visibility("default"))) void throw_synth() {
+    void* e = 
__cxa_allocate_exception(sizeof(com::sun::star::ucb::InteractiveAugmentedIOException));
+    memset(e,0,sizeof(com::sun::star::ucb::InteractiveAugmentedIOException));
+    __cxa_throw(e, synth_derived(), nodel);
+}
diff --git 
a/main/bridges/source/cpp_uno/s5abi_macosx_aarch64/qa/rtti_crossdylib_test/uno_like.hxx
 
b/main/bridges/source/cpp_uno/s5abi_macosx_aarch64/qa/rtti_crossdylib_test/uno_like.hxx
new file mode 100644
index 0000000000..5f1ed6b9c3
--- /dev/null
+++ 
b/main/bridges/source/cpp_uno/s5abi_macosx_aarch64/qa/rtti_crossdylib_test/uno_like.hxx
@@ -0,0 +1,5 @@
+#pragma once
+namespace com { namespace sun { namespace star {
+namespace uno { struct Exception { char* Message; void* Context; }; }
+namespace ucb { struct InteractiveAugmentedIOException : public 
::com::sun::star::uno::Exception { int code; }; }
+}}}
diff --git 
a/main/bridges/source/cpp_uno/s5abi_macosx_aarch64/qa/rtti_synthesis_test.cxx 
b/main/bridges/source/cpp_uno/s5abi_macosx_aarch64/qa/rtti_synthesis_test.cxx
new file mode 100644
index 0000000000..272a0d7eef
--- /dev/null
+++ 
b/main/bridges/source/cpp_uno/s5abi_macosx_aarch64/qa/rtti_synthesis_test.cxx
@@ -0,0 +1,120 @@
+// Standalone ABI harness for the RTTI synthesis in ../except.cxx and
+// ../share.hxx.  Not wired into gbuild; compile and run manually:
+//
+//   clang++ -std=c++11 -arch arm64 -o rtti_synthesis_test 
rtti_synthesis_test.cxx
+//   ./rtti_synthesis_test
+//
+// Expected output: test 3 and both variants of test 2 report CAUGHT; only
+// test 1 (the naive hand-built type_info, i.e. the approach the
+// s5abi_macosx_x86-64 bridge uses) reports the catch(...) fallback.
+//
+// Does libc++abi on arm64 Darwin catch an exception thrown with a hand-built
+// type_info?  Mirrors what bridges/.../s5abi_macosx_x86-64/except.cxx does.
+#include <cxxabi.h>
+#include <typeinfo>
+#include <cstdio>
+#include <cstring>
+#include <cstdlib>
+#include <cstdint>
+
+// ---- UNO-like plain structs (no virtual functions), as css::uno::Exception 
is
+struct UnoException { char* Message; void* Context; };
+struct UnoRealDerived : UnoException { int extra; };   // typeid -> real 
__si_class_type_info
+
+// ---- AOO's stand-ins, copied verbatim in shape from s5abi share.hxx ----
+namespace fake {
+class __class_type_info : public std::type_info {
+public:
+    explicit __class_type_info(const char* n) : std::type_info(n) {}
+};
+class __si_class_type_info : public __class_type_info {
+    const __class_type_info* mpBaseType;
+public:
+    __si_class_type_info(const char* n, __class_type_info* b)
+        : __class_type_info(n), mpBaseType(b) {}
+};
+}
+
+// Itanium layout of __cxxabiv1::__si_class_type_info
+struct SiLayout {
+    void const* vptr;
+    char const* name;
+    void const* base;
+};
+
+extern "C" void* __cxa_allocate_exception(size_t) throw();
+extern "C" void __cxa_throw(void*, std::type_info*, void (*)(void*)) 
__attribute__((noreturn));
+
+static void nodelete(void*) {}
+
+static void report(const char* what, int r) {
+    printf("%-46s : %s\n", what,
+           r == 1 ? "CAUGHT as UnoException&  (WORKS)"
+                  : r == 2 ? "caught only by catch(...)  (BROKEN)"
+                           : "??");
+}
+
+// Test 1: naive hand-built type_info (foreign vtable) -- what AOO x86-64 does
+static int test_naive() {
+    static fake::__si_class_type_info* ti =
+        new fake::__si_class_type_info(
+            strdup("N3com3sun4star3ucb31InteractiveAugmentedIOExceptionE"),
+            
(fake::__class_type_info*)const_cast<std::type_info*>(&typeid(UnoException)));
+    void* e = __cxa_allocate_exception(sizeof(UnoException));
+    memset(e, 0, sizeof(UnoException));
+    try {
+        __cxa_throw(e, (std::type_info*)ti, nodelete);
+    } catch (UnoException&) { return 1; }
+      catch (...)           { return 2; }
+    return 0;
+}
+
+// Test 2: vtable borrowed from a real compiler-emitted __si_class_type_info
+static int test_vtable_borrow(bool set_nonunique_bit) {
+    SiLayout const* model =
+        reinterpret_cast<SiLayout const*>(&typeid(UnoRealDerived));
+    SiLayout* ti = (SiLayout*)calloc(1, sizeof(SiLayout));
+    ti->vptr = model->vptr;
+    char const* nm = 
strdup("N3com3sun4star3ucb31InteractiveAugmentedIOExceptionE");
+    if (set_nonunique_bit)
+        nm = (char const*)((uintptr_t)nm | (1ULL << 63));
+    ti->name = nm;
+    ti->base = &typeid(UnoException);
+    void* e = __cxa_allocate_exception(sizeof(UnoException));
+    memset(e, 0, sizeof(UnoException));
+    try {
+        __cxa_throw(e, (std::type_info*)ti, nodelete);
+    } catch (UnoException&) { return 1; }
+      catch (...)           { return 2; }
+    return 0;
+}
+
+// Test 3: sanity -- a genuinely compiler-emitted derived type
+static int test_real() {
+    void* e = __cxa_allocate_exception(sizeof(UnoRealDerived));
+    memset(e, 0, sizeof(UnoRealDerived));
+    try {
+        __cxa_throw(e, (std::type_info*)&typeid(UnoRealDerived), nodelete);
+    } catch (UnoException&) { return 1; }
+      catch (...)           { return 2; }
+    return 0;
+}
+
+int main() {
+    printf("_LIBCPP_TYPEINFO_COMPARISON_IMPLEMENTATION-relevant arch: %s\n",
+#if defined(__APPLE__) && defined(__LP64__) && !defined(__x86_64__)
+           "arm64 Apple -> NonUniqueARMRTTIBit (impl 3)");
+#else
+           "other");
+#endif
+    SiLayout const* m = reinterpret_cast<SiLayout 
const*>(&typeid(UnoRealDerived));
+    printf("real typeid(UnoRealDerived).name ptr = %p  high bit=%d  str=%s\n",
+           (void*)m->name, (int)(((uintptr_t)m->name) >> 63),
+           typeid(UnoRealDerived).name());
+    printf("\n");
+    report("3: real compiler-emitted typeinfo (control)", test_real());
+    report("1: naive hand-built (AOO x86-64 approach)",   test_naive());
+    report("2a: borrowed vtable, plain name",             
test_vtable_borrow(false));
+    report("2b: borrowed vtable, non-unique bit set",     
test_vtable_borrow(true));
+    return 0;
+}

Reply via email to