bridges/source/cpp_uno/gcc3_aix_powerpc/cpp2uno.cxx       |   11 +
 bridges/source/cpp_uno/gcc3_ios/cpp2uno.cxx               |   15 +
 bridges/source/cpp_uno/gcc3_linux_aarch64/cpp2uno.cxx     |   11 +
 bridges/source/cpp_uno/gcc3_linux_alpha/cpp2uno.cxx       |   11 +
 bridges/source/cpp_uno/gcc3_linux_arm/cpp2uno.cxx         |   11 +
 bridges/source/cpp_uno/gcc3_linux_hppa/cpp2uno.cxx        |   11 +
 bridges/source/cpp_uno/gcc3_linux_ia64/cpp2uno.cxx        |    9 -
 bridges/source/cpp_uno/gcc3_linux_intel/cpp2uno.cxx       |   14 +
 bridges/source/cpp_uno/gcc3_linux_loongarch64/cpp2uno.cxx |   14 +
 bridges/source/cpp_uno/gcc3_linux_m68k/cpp2uno.cxx        |   11 +
 bridges/source/cpp_uno/gcc3_linux_mips/cpp2uno.cxx        |   11 +
 bridges/source/cpp_uno/gcc3_linux_mips64/cpp2uno.cxx      |   11 +
 bridges/source/cpp_uno/gcc3_linux_powerpc/cpp2uno.cxx     |   11 +
 bridges/source/cpp_uno/gcc3_linux_powerpc64/cpp2uno.cxx   |   11 +
 bridges/source/cpp_uno/gcc3_linux_riscv64/cpp2uno.cxx     |   14 +
 bridges/source/cpp_uno/gcc3_linux_s390/cpp2uno.cxx        |   11 +
 bridges/source/cpp_uno/gcc3_linux_s390x/cpp2uno.cxx       |   11 +
 bridges/source/cpp_uno/gcc3_linux_sparc/cpp2uno.cxx       |   14 +
 bridges/source/cpp_uno/gcc3_linux_sparc64/cpp2uno.cxx     |   14 +
 bridges/source/cpp_uno/gcc3_linux_x86-64/cpp2uno.cxx      |   17 +-
 bridges/source/cpp_uno/gcc3_macosx_x86-64/cpp2uno.cxx     |   11 +
 bridges/source/cpp_uno/gcc3_solaris_intel/cpp2uno.cxx     |   11 +
 bridges/source/cpp_uno/gcc3_solaris_sparc/cpp2uno.cxx     |   14 +
 bridges/source/cpp_uno/msvc_win32_arm64/cpp2uno.cxx       |  113 ++++++++++++--
 bridges/source/cpp_uno/msvc_win32_intel/cpp2uno.cxx       |   79 ++++++++-
 bridges/source/cpp_uno/msvc_win32_x86-64/cpp2uno.cxx      |   89 +++++++++--
 testtools/source/bridgetest/bridgetest.cxx                |    4 
 27 files changed, 487 insertions(+), 77 deletions(-)

New commits:
commit ef533553559fe09b4afab651fc692885d1acf4ed
Author:     Stephan Bergmann <sberg...@redhat.com>
AuthorDate: Wed Jan 4 12:14:22 2023 +0100
Commit:     Stephan Bergmann <sberg...@redhat.com>
CommitDate: Wed Jan 4 13:49:58 2023 +0000

    Rudimentary support for dynamic_cast on UNO proxy objects
    
    <https://gerrit.libreoffice.org/c/core/+/144139> "New loplugin:unocast" had
    argued that uses of dynamic_cast from a UNO interface type are broken in 
general
    (because if the source object is a proxy from the C*+ UNO bridge, its 
vtable's
    RTTI slot will normally not be set up, which can cause a crash), and should 
be
    replaced with uses of XUnoTunnel.  Which the various recent 
"loplugin:unocast
    (...)" commits started to do.  However, it became clear that that is not the
    most ideal way forward:  For one, getting more and more implementations of
    XUnoTunnel::getSomething into existing class hierarchies is error prone, as 
each
    such implementation must manually delegate to all its base class
    implementations.  For another, uses of comphelper::getFromUnoTunnel (which 
often
    needs to do a queryInterface to XUnoTunnel first) are easily more expensive 
than
    uses of dynamic_cast.
    
    Thanks to Noel, the insight here is that for the use case of a dynamic_cast 
from
    a UNO interface type to a local C++ class type, and if the source object is 
a
    proxy, it is sufficient that the dynamic_cast will not crash.  It will
    necessarily always return null (as the proxy will never be the 
implementation of
    a local C++ class type), so it is sufficient to fill the RTTI slots of the
    proxies' vtables with dummy values.  That avoids having to set up proper 
RTTI
    for those potentially multiple-inheritance proxy types.  (And with this in
    place, all those recent "loplugin:unocast (...)" commits can be reverted 
again
    in a next step.)
    
    I verified the changes for the gcc3_linux_aarch64 (on macOS), 
gcc3_linux_intel,
    gcc3_linux_x86-64, gcc3_macosx_x86-64, msvc_win32_intel, and 
msvc_win32_x86-64
    bridges.  The changes for all the other bridges were done blindly.
    
    (For gcc3_linux_x86-64, which already conditionally supported proper RTTI 
for
    UBSan, setting the offset-to-top slot to non-zero had to be made conditional
    too, as the dummy ProxyRtti will always pretend to be a full class rather 
than a
    potential base class that could have a non-zero offset-to-top value.  For
    msvc_win32_*, it turned out that the existing code to set up dummy 
XInterface
    RTTI (which was there for reasons lost to history) was broken.)
    
    Change-Id: Iec4b8067d26b14b6fb02c2fdd15e1eee20919590
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/145038
    Tested-by: Jenkins
    Reviewed-by: Stephan Bergmann <sberg...@redhat.com>

diff --git a/bridges/source/cpp_uno/gcc3_aix_powerpc/cpp2uno.cxx 
b/bridges/source/cpp_uno/gcc3_aix_powerpc/cpp2uno.cxx
index 2e6fdd11a820..92068152245c 100644
--- a/bridges/source/cpp_uno/gcc3_aix_powerpc/cpp2uno.cxx
+++ b/bridges/source/cpp_uno/gcc3_aix_powerpc/cpp2uno.cxx
@@ -30,6 +30,7 @@
 #include "share.hxx"
 
 #include <string.h>
+#include <typeinfo>
 
 using namespace ::com::sun::star::uno;
 
@@ -571,7 +572,7 @@ void 
bridges::cpp_uno::shared::VtableFactory::flushCode(unsigned char const * bp
     __asm__ volatile ("isync" : : : "memory");
 }
 
-struct bridges::cpp_uno::shared::VtableFactory::Slot { void * fn; };
+struct bridges::cpp_uno::shared::VtableFactory::Slot { void const * fn; };
 
 bridges::cpp_uno::shared::VtableFactory::Slot *
 bridges::cpp_uno::shared::VtableFactory::mapBlockToVtable(void * block)
@@ -585,6 +586,12 @@ std::size_t 
bridges::cpp_uno::shared::VtableFactory::getBlockSize(
     return (slotCount + 2) * sizeof (Slot) + slotCount * codeSnippetSize;
 }
 
+namespace {
+// Some dummy type whose RTTI is used in the synthesized proxy vtables to make 
uses of dynamic_cast
+// on such proxy objects not crash:
+struct ProxyRtti {};
+}
+
 bridges::cpp_uno::shared::VtableFactory::Slot *
 bridges::cpp_uno::shared::VtableFactory::initializeBlock(
     void * block, sal_Int32 slotCount, sal_Int32,
@@ -592,7 +599,7 @@ bridges::cpp_uno::shared::VtableFactory::initializeBlock(
 {
     Slot * slots = mapBlockToVtable(block);
     slots[-2].fn = 0;
-    slots[-1].fn = 0;
+    slots[-1].fn = &typeid(ProxyRtti);
     return slots + slotCount;
 }
 
diff --git a/bridges/source/cpp_uno/gcc3_ios/cpp2uno.cxx 
b/bridges/source/cpp_uno/gcc3_ios/cpp2uno.cxx
index 21de11b5ea36..9ba5af012443 100644
--- a/bridges/source/cpp_uno/gcc3_ios/cpp2uno.cxx
+++ b/bridges/source/cpp_uno/gcc3_ios/cpp2uno.cxx
@@ -16,6 +16,11 @@
  *   except in compliance with the License. You may obtain a copy of
  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
  */
+
+#include <sal/config.h>
+
+#include <typeinfo>
+
 #include <com/sun/star/uno/RuntimeException.hpp>
 #include <sal/log.hxx>
 #include <uno/data.h>
@@ -457,7 +462,7 @@ namespace
     }
 }
 
-struct bridges::cpp_uno::shared::VtableFactory::Slot { void * fn; };
+struct bridges::cpp_uno::shared::VtableFactory::Slot { void const * fn; };
 
 bridges::cpp_uno::shared::VtableFactory::Slot *
 bridges::cpp_uno::shared::VtableFactory::mapBlockToVtable(void * block)
@@ -471,6 +476,12 @@ std::size_t 
bridges::cpp_uno::shared::VtableFactory::getBlockSize(
     return (slotCount + 2) * sizeof (Slot);
 }
 
+namespace {
+// Some dummy type whose RTTI is used in the synthesized proxy vtables to make 
uses of dynamic_cast
+// on such proxy objects not crash:
+struct ProxyRtti {};
+}
+
 bridges::cpp_uno::shared::VtableFactory::Slot *
 bridges::cpp_uno::shared::VtableFactory::initializeBlock(
     void * block, sal_Int32 slotCount, sal_Int32,
@@ -478,7 +489,7 @@ bridges::cpp_uno::shared::VtableFactory::initializeBlock(
 {
     Slot * slots = mapBlockToVtable(block);
     slots[-2].fn = 0;
-    slots[-1].fn = 0;
+    slots[-1].fn = &typeid(ProxyRtti);
     return slots + slotCount;
 }
 
diff --git a/bridges/source/cpp_uno/gcc3_linux_aarch64/cpp2uno.cxx 
b/bridges/source/cpp_uno/gcc3_linux_aarch64/cpp2uno.cxx
index 775a4aff6962..669c4443c5f0 100644
--- a/bridges/source/cpp_uno/gcc3_linux_aarch64/cpp2uno.cxx
+++ b/bridges/source/cpp_uno/gcc3_linux_aarch64/cpp2uno.cxx
@@ -24,6 +24,7 @@
 #include <cstddef>
 #include <cstdlib>
 #include <cstring>
+#include <typeinfo>
 
 #include <dlfcn.h>
 
@@ -502,7 +503,7 @@ unsigned char * generateCodeSnippet(
 
 }
 
-struct bridges::cpp_uno::shared::VtableFactory::Slot { void * fn; };
+struct bridges::cpp_uno::shared::VtableFactory::Slot { void const * fn; };
 
 bridges::cpp_uno::shared::VtableFactory::Slot *
 bridges::cpp_uno::shared::VtableFactory::mapBlockToVtable(void * block) {
@@ -515,6 +516,12 @@ std::size_t 
bridges::cpp_uno::shared::VtableFactory::getBlockSize(
     return (slotCount + 2) * sizeof (Slot) + slotCount * codeSnippetSize;
 }
 
+namespace {
+// Some dummy type whose RTTI is used in the synthesized proxy vtables to make 
uses of dynamic_cast
+// on such proxy objects not crash:
+struct ProxyRtti {};
+}
+
 bridges::cpp_uno::shared::VtableFactory::Slot *
 bridges::cpp_uno::shared::VtableFactory::initializeBlock(
     void * block, sal_Int32 slotCount, sal_Int32,
@@ -522,7 +529,7 @@ bridges::cpp_uno::shared::VtableFactory::initializeBlock(
 {
     Slot * slots = mapBlockToVtable(block);
     slots[-2].fn = nullptr;
-    slots[-1].fn = nullptr;
+    slots[-1].fn = &typeid(ProxyRtti);
     return slots + slotCount;
 }
 
diff --git a/bridges/source/cpp_uno/gcc3_linux_alpha/cpp2uno.cxx 
b/bridges/source/cpp_uno/gcc3_linux_alpha/cpp2uno.cxx
index bd0be3981d7c..98709f4c5e90 100644
--- a/bridges/source/cpp_uno/gcc3_linux_alpha/cpp2uno.cxx
+++ b/bridges/source/cpp_uno/gcc3_linux_alpha/cpp2uno.cxx
@@ -30,6 +30,7 @@
 
 #include "share.hxx"
 #include <stdio.h>
+#include <typeinfo>
 
 //Calling Standards:
 //  "Calling Standard for Alpha Systems"
@@ -585,7 +586,7 @@ void 
bridges::cpp_uno::shared::VtableFactory::flushCode(unsigned char const *, u
     __asm__ __volatile__("call_pal 0x86");
 }
 
-struct bridges::cpp_uno::shared::VtableFactory::Slot { void * fn; };
+struct bridges::cpp_uno::shared::VtableFactory::Slot { void const * fn; };
 
 bridges::cpp_uno::shared::VtableFactory::Slot *
 bridges::cpp_uno::shared::VtableFactory::mapBlockToVtable(void * block)
@@ -599,6 +600,12 @@ std::size_t 
bridges::cpp_uno::shared::VtableFactory::getBlockSize(
     return (slotCount + 2) * sizeof (Slot) + slotCount * codeSnippetSize;
 }
 
+namespace {
+// Some dummy type whose RTTI is used in the synthesized proxy vtables to make 
uses of dynamic_cast
+// on such proxy objects not crash:
+struct ProxyRtti {};
+}
+
 bridges::cpp_uno::shared::VtableFactory::Slot *
 bridges::cpp_uno::shared::VtableFactory::initializeBlock(
     void * block, sal_Int32 slotCount, sal_Int32,
@@ -606,7 +613,7 @@ bridges::cpp_uno::shared::VtableFactory::initializeBlock(
 {
     Slot * slots = mapBlockToVtable(block);
     slots[-2].fn = 0;
-    slots[-1].fn = 0;
+    slots[-1].fn = &typeid(ProxyRtti);
     return slots + slotCount;
 }
 
diff --git a/bridges/source/cpp_uno/gcc3_linux_arm/cpp2uno.cxx 
b/bridges/source/cpp_uno/gcc3_linux_arm/cpp2uno.cxx
index 103f2b492e3a..f476cf7df10b 100644
--- a/bridges/source/cpp_uno/gcc3_linux_arm/cpp2uno.cxx
+++ b/bridges/source/cpp_uno/gcc3_linux_arm/cpp2uno.cxx
@@ -18,6 +18,7 @@
  */
 
 #include <malloc.h>
+#include <typeinfo>
 
 #include <rtl/alloc.h>
 #include <sal/log.hxx>
@@ -484,7 +485,7 @@ namespace
     }
 }
 
-struct bridges::cpp_uno::shared::VtableFactory::Slot { void * fn; };
+struct bridges::cpp_uno::shared::VtableFactory::Slot { void const * fn; };
 
 bridges::cpp_uno::shared::VtableFactory::Slot *
 bridges::cpp_uno::shared::VtableFactory::mapBlockToVtable(void * block)
@@ -498,6 +499,12 @@ std::size_t 
bridges::cpp_uno::shared::VtableFactory::getBlockSize(
     return (slotCount + 2) * sizeof (Slot) + slotCount * codeSnippetSize;
 }
 
+namespace {
+// Some dummy type whose RTTI is used in the synthesized proxy vtables to make 
uses of dynamic_cast
+// on such proxy objects not crash:
+struct ProxyRtti {};
+}
+
 bridges::cpp_uno::shared::VtableFactory::Slot *
 bridges::cpp_uno::shared::VtableFactory::initializeBlock(
     void * block, sal_Int32 slotCount, sal_Int32,
@@ -505,7 +512,7 @@ bridges::cpp_uno::shared::VtableFactory::initializeBlock(
 {
     Slot * slots = mapBlockToVtable(block);
     slots[-2].fn = nullptr;
-    slots[-1].fn = nullptr;
+    slots[-1].fn = &typeid(ProxyRtti);
     return slots + slotCount;
 }
 
diff --git a/bridges/source/cpp_uno/gcc3_linux_hppa/cpp2uno.cxx 
b/bridges/source/cpp_uno/gcc3_linux_hppa/cpp2uno.cxx
index 5491e0153b7e..7e8524d1c726 100644
--- a/bridges/source/cpp_uno/gcc3_linux_hppa/cpp2uno.cxx
+++ b/bridges/source/cpp_uno/gcc3_linux_hppa/cpp2uno.cxx
@@ -18,6 +18,7 @@
  */
 
 #include <malloc.h>
+#include <typeinfo>
 
 #include <rtl/alloc.h>
 
@@ -629,7 +630,7 @@ namespace
     }
 }
 
-struct bridges::cpp_uno::shared::VtableFactory::Slot { void * fn; };
+struct bridges::cpp_uno::shared::VtableFactory::Slot { void const * fn; };
 
 bridges::cpp_uno::shared::VtableFactory::Slot *
 bridges::cpp_uno::shared::VtableFactory::mapBlockToVtable(void * block)
@@ -643,6 +644,12 @@ std::size_t 
bridges::cpp_uno::shared::VtableFactory::getBlockSize(
     return (slotCount + 2) * sizeof (Slot) + slotCount * codeSnippetSize;
 }
 
+namespace {
+// Some dummy type whose RTTI is used in the synthesized proxy vtables to make 
uses of dynamic_cast
+// on such proxy objects not crash:
+struct ProxyRtti {};
+}
+
 bridges::cpp_uno::shared::VtableFactory::Slot *
 bridges::cpp_uno::shared::VtableFactory::initializeBlock(
     void * block, sal_Int32 slotCount, sal_Int32,
@@ -650,7 +657,7 @@ bridges::cpp_uno::shared::VtableFactory::initializeBlock(
 {
     Slot * slots = mapBlockToVtable(block);
     slots[-2].fn = 0;
-    slots[-1].fn = 0;
+    slots[-1].fn = &typeid(ProxyRtti);
     return slots + slotCount;
 }
 
diff --git a/bridges/source/cpp_uno/gcc3_linux_ia64/cpp2uno.cxx 
b/bridges/source/cpp_uno/gcc3_linux_ia64/cpp2uno.cxx
index ddcd40818036..0d8303861c28 100644
--- a/bridges/source/cpp_uno/gcc3_linux_ia64/cpp2uno.cxx
+++ b/bridges/source/cpp_uno/gcc3_linux_ia64/cpp2uno.cxx
@@ -30,6 +30,7 @@
 
 #include "share.hxx"
 #include <stdio.h>
+#include <typeinfo>
 
 extern "C" { extern void (*privateSnippetExecutor)(); }
 
@@ -607,10 +608,16 @@ std::size_t 
bridges::cpp_uno::shared::VtableFactory::getBlockSize(
     return (slotCount + 1) * sizeof (Slot) + slotCount * codeSnippetSize;
 }
 
+namespace {
+// Some dummy type whose RTTI is used in the synthesized proxy vtables to make 
uses of dynamic_cast
+// on such proxy objects not crash:
+struct ProxyRtti {};
+}
+
 bridges::cpp_uno::shared::VtableFactory::Slot* 
bridges::cpp_uno::shared::VtableFactory::initializeBlock(void * block, 
sal_Int32 slotCount, sal_Int32, typelib_InterfaceTypeDescription *)
 {
     Slot * slots = mapBlockToVtable(block);
-    slots[-1] = {0,0};
+    slots[-1] = {0,reinterpret_cast<sal_uInt64>(&typeid(ProxyRtti))};
     return slots + slotCount;
 }
 
diff --git a/bridges/source/cpp_uno/gcc3_linux_intel/cpp2uno.cxx 
b/bridges/source/cpp_uno/gcc3_linux_intel/cpp2uno.cxx
index 70c6091ec207..5dd6e1aa90f1 100644
--- a/bridges/source/cpp_uno/gcc3_linux_intel/cpp2uno.cxx
+++ b/bridges/source/cpp_uno/gcc3_linux_intel/cpp2uno.cxx
@@ -18,6 +18,10 @@
  */
 
 
+#include <sal/config.h>
+
+#include <typeinfo>
+
 #include <com/sun/star/uno/genfunc.hxx>
 #include <com/sun/star/uno/RuntimeException.hpp>
 #include <sal/log.hxx>
@@ -438,7 +442,7 @@ unsigned char * codeSnippet(
 
 }
 
-struct bridges::cpp_uno::shared::VtableFactory::Slot { void * fn; };
+struct bridges::cpp_uno::shared::VtableFactory::Slot { void const * fn; };
 
 bridges::cpp_uno::shared::VtableFactory::Slot *
 bridges::cpp_uno::shared::VtableFactory::mapBlockToVtable(void * block) {
@@ -451,6 +455,12 @@ std::size_t 
bridges::cpp_uno::shared::VtableFactory::getBlockSize(
     return (slotCount + 2) * sizeof (Slot) + slotCount * codeSnippetSize;
 }
 
+namespace {
+// Some dummy type whose RTTI is used in the synthesized proxy vtables to make 
uses of dynamic_cast
+// on such proxy objects not crash:
+struct ProxyRtti {};
+}
+
 bridges::cpp_uno::shared::VtableFactory::Slot *
 bridges::cpp_uno::shared::VtableFactory::initializeBlock(
     void * block, sal_Int32 slotCount, sal_Int32,
@@ -458,7 +468,7 @@ bridges::cpp_uno::shared::VtableFactory::initializeBlock(
 {
     Slot * slots = mapBlockToVtable(block);
     slots[-2].fn = nullptr;
-    slots[-1].fn = nullptr;
+    slots[-1].fn = &typeid(ProxyRtti);
     return slots + slotCount;
 }
 
diff --git a/bridges/source/cpp_uno/gcc3_linux_loongarch64/cpp2uno.cxx 
b/bridges/source/cpp_uno/gcc3_linux_loongarch64/cpp2uno.cxx
index 0273b39da4e3..d0c1ce900501 100644
--- a/bridges/source/cpp_uno/gcc3_linux_loongarch64/cpp2uno.cxx
+++ b/bridges/source/cpp_uno/gcc3_linux_loongarch64/cpp2uno.cxx
@@ -31,6 +31,7 @@
 
 #include <stdio.h>
 #include <string.h>
+#include <typeinfo>
 
 using namespace com::sun::star::uno;
 
@@ -480,7 +481,7 @@ void 
bridges::cpp_uno::shared::VtableFactory::flushCode(unsigned char const* bpt
 
 struct bridges::cpp_uno::shared::VtableFactory::Slot
 {
-    void* fn;
+    void const* fn;
 };
 
 bridges::cpp_uno::shared::VtableFactory::Slot*
@@ -494,6 +495,15 @@ std::size_t 
bridges::cpp_uno::shared::VtableFactory::getBlockSize(sal_Int32 slot
     return (slotCount + 2) * sizeof(Slot) + slotCount * codeSnippetSize;
 }
 
+namespace
+{
+// Some dummy type whose RTTI is used in the synthesized proxy vtables to make 
uses of dynamic_cast
+// on such proxy objects not crash:
+struct ProxyRtti
+{
+};
+}
+
 bridges::cpp_uno::shared::VtableFactory::Slot*
 bridges::cpp_uno::shared::VtableFactory::initializeBlock(void* block, 
sal_Int32 slotCount,
                                                          sal_Int32,
@@ -501,7 +511,7 @@ 
bridges::cpp_uno::shared::VtableFactory::initializeBlock(void* block, sal_Int32
 {
     Slot* slots = mapBlockToVtable(block);
     slots[-2].fn = 0; //null
-    slots[-1].fn = 0; //destructor
+    slots[-1].fn = &typeid(ProxyRtti);
     return slots + slotCount;
 }
 
diff --git a/bridges/source/cpp_uno/gcc3_linux_m68k/cpp2uno.cxx 
b/bridges/source/cpp_uno/gcc3_linux_m68k/cpp2uno.cxx
index c293f3ce6b64..ac375e052bf6 100644
--- a/bridges/source/cpp_uno/gcc3_linux_m68k/cpp2uno.cxx
+++ b/bridges/source/cpp_uno/gcc3_linux_m68k/cpp2uno.cxx
@@ -18,6 +18,7 @@
  */
 
 #include <malloc.h>
+#include <typeinfo>
 
 #include <rtl/alloc.h>
 #include <sal/log.hxx>
@@ -441,7 +442,7 @@ namespace
     }
 }
 
-struct bridges::cpp_uno::shared::VtableFactory::Slot { void * fn; };
+struct bridges::cpp_uno::shared::VtableFactory::Slot { void const * fn; };
 
 bridges::cpp_uno::shared::VtableFactory::Slot *
 bridges::cpp_uno::shared::VtableFactory::mapBlockToVtable(void * block)
@@ -455,6 +456,12 @@ std::size_t 
bridges::cpp_uno::shared::VtableFactory::getBlockSize(
     return (slotCount + 2) * sizeof (Slot) + slotCount * codeSnippetSize;
 }
 
+namespace {
+// Some dummy type whose RTTI is used in the synthesized proxy vtables to make 
uses of dynamic_cast
+// on such proxy objects not crash:
+struct ProxyRtti {};
+}
+
 bridges::cpp_uno::shared::VtableFactory::Slot *
 bridges::cpp_uno::shared::VtableFactory::initializeBlock(
     void * block, sal_Int32 slotCount, sal_Int32,
@@ -462,7 +469,7 @@ bridges::cpp_uno::shared::VtableFactory::initializeBlock(
 {
     Slot * slots = mapBlockToVtable(block);
     slots[-2].fn = 0;
-    slots[-1].fn = 0;
+    slots[-1].fn = &typeid(ProxyRtti);
     return slots + slotCount;
 }
 
diff --git a/bridges/source/cpp_uno/gcc3_linux_mips/cpp2uno.cxx 
b/bridges/source/cpp_uno/gcc3_linux_mips/cpp2uno.cxx
index 35e1f231d770..21ec313942ac 100644
--- a/bridges/source/cpp_uno/gcc3_linux_mips/cpp2uno.cxx
+++ b/bridges/source/cpp_uno/gcc3_linux_mips/cpp2uno.cxx
@@ -29,6 +29,7 @@
 
 #include <stdio.h>
 #include <string.h>
+#include <typeinfo>
 
 using namespace com::sun::star::uno;
 
@@ -719,7 +720,7 @@ void 
bridges::cpp_uno::shared::VtableFactory::flushCode(unsigned char const *bpt
 #endif
 }
 
-struct bridges::cpp_uno::shared::VtableFactory::Slot { void * fn; };
+struct bridges::cpp_uno::shared::VtableFactory::Slot { void const * fn; };
 
 bridges::cpp_uno::shared::VtableFactory::Slot *
 bridges::cpp_uno::shared::VtableFactory::mapBlockToVtable(void * block)
@@ -734,6 +735,12 @@ std::size_t 
bridges::cpp_uno::shared::VtableFactory::getBlockSize(
     return (slotCount + 2) * sizeof (Slot) + slotCount * codeSnippetSize;
 }
 
+namespace {
+// Some dummy type whose RTTI is used in the synthesized proxy vtables to make 
uses of dynamic_cast
+// on such proxy objects not crash:
+struct ProxyRtti {};
+}
+
 bridges::cpp_uno::shared::VtableFactory::Slot *
 bridges::cpp_uno::shared::VtableFactory::initializeBlock(
     void * block, sal_Int32 slotCount, sal_Int32,
@@ -741,7 +748,7 @@ bridges::cpp_uno::shared::VtableFactory::initializeBlock(
 {
     Slot * slots = mapBlockToVtable(block);
     slots[-2].fn = 0; //null
-    slots[-1].fn = 0; //destructor
+    slots[-1].fn = &typeid(ProxyRtti);
     return slots + slotCount;
 }
 
diff --git a/bridges/source/cpp_uno/gcc3_linux_mips64/cpp2uno.cxx 
b/bridges/source/cpp_uno/gcc3_linux_mips64/cpp2uno.cxx
index ebde9821eab2..7dbf0022e963 100644
--- a/bridges/source/cpp_uno/gcc3_linux_mips64/cpp2uno.cxx
+++ b/bridges/source/cpp_uno/gcc3_linux_mips64/cpp2uno.cxx
@@ -30,6 +30,7 @@
 
 #include <stdio.h>
 #include <string.h>
+#include <typeinfo>
 
 using namespace com::sun::star::uno;
 
@@ -616,7 +617,7 @@ void 
bridges::cpp_uno::shared::VtableFactory::flushCode(unsigned char const *bpt
 #endif
 }
 
-struct bridges::cpp_uno::shared::VtableFactory::Slot { void * fn; };
+struct bridges::cpp_uno::shared::VtableFactory::Slot { void const * fn; };
 
 bridges::cpp_uno::shared::VtableFactory::Slot *
 bridges::cpp_uno::shared::VtableFactory::mapBlockToVtable(void * block)
@@ -631,6 +632,12 @@ std::size_t 
bridges::cpp_uno::shared::VtableFactory::getBlockSize(
     return (slotCount + 2) * sizeof (Slot) + slotCount * codeSnippetSize;
 }
 
+namespace {
+// Some dummy type whose RTTI is used in the synthesized proxy vtables to make 
uses of dynamic_cast
+// on such proxy objects not crash:
+struct ProxyRtti {};
+}
+
 bridges::cpp_uno::shared::VtableFactory::Slot *
 bridges::cpp_uno::shared::VtableFactory::initializeBlock(
     void * block, sal_Int32 slotCount, sal_Int32,
@@ -638,7 +645,7 @@ bridges::cpp_uno::shared::VtableFactory::initializeBlock(
 {
     Slot * slots = mapBlockToVtable(block);
     slots[-2].fn = 0; //null
-    slots[-1].fn = 0; //destructor
+    slots[-1].fn = &typeid(ProxyRtti);
     return slots + slotCount;
 }
 
diff --git a/bridges/source/cpp_uno/gcc3_linux_powerpc/cpp2uno.cxx 
b/bridges/source/cpp_uno/gcc3_linux_powerpc/cpp2uno.cxx
index 521dccd6dae1..328fb7a17e38 100644
--- a/bridges/source/cpp_uno/gcc3_linux_powerpc/cpp2uno.cxx
+++ b/bridges/source/cpp_uno/gcc3_linux_powerpc/cpp2uno.cxx
@@ -19,6 +19,7 @@
 
 
 #include <string.h>
+#include <typeinfo>
 
 #include <com/sun/star/uno/genfunc.hxx>
 #include <sal/log.hxx>
@@ -702,7 +703,7 @@ void 
bridges::cpp_uno::shared::VtableFactory::flushCode(unsigned char const * bp
     __asm__ volatile ("isync" : : : "memory");
 }
 
-struct bridges::cpp_uno::shared::VtableFactory::Slot { void * fn; };
+struct bridges::cpp_uno::shared::VtableFactory::Slot { void const * fn; };
 
 bridges::cpp_uno::shared::VtableFactory::Slot *
 bridges::cpp_uno::shared::VtableFactory::mapBlockToVtable(void * block)
@@ -716,6 +717,12 @@ std::size_t 
bridges::cpp_uno::shared::VtableFactory::getBlockSize(
     return (slotCount + 2) * sizeof (Slot) + slotCount * codeSnippetSize;
 }
 
+namespace {
+// Some dummy type whose RTTI is used in the synthesized proxy vtables to make 
uses of dynamic_cast
+// on such proxy objects not crash:
+struct ProxyRtti {};
+}
+
 bridges::cpp_uno::shared::VtableFactory::Slot *
 bridges::cpp_uno::shared::VtableFactory::initializeBlock(
     void * block, sal_Int32 slotCount, sal_Int32,
@@ -723,7 +730,7 @@ bridges::cpp_uno::shared::VtableFactory::initializeBlock(
 {
     Slot * slots = mapBlockToVtable(block);
     slots[-2].fn = 0;
-    slots[-1].fn = 0;
+    slots[-1].fn = &typeid(ProxyRtti);
     return slots + slotCount;
 }
 
diff --git a/bridges/source/cpp_uno/gcc3_linux_powerpc64/cpp2uno.cxx 
b/bridges/source/cpp_uno/gcc3_linux_powerpc64/cpp2uno.cxx
index ab3fbd4c76b3..d1a5ee6f4e76 100644
--- a/bridges/source/cpp_uno/gcc3_linux_powerpc64/cpp2uno.cxx
+++ b/bridges/source/cpp_uno/gcc3_linux_powerpc64/cpp2uno.cxx
@@ -31,6 +31,7 @@
 #include "share.hxx"
 #include <stdio.h>
 #include <string.h>
+#include <typeinfo>
 
 #ifdef OSL_BIGENDIAN
 #define IS_BIG_ENDIAN 1
@@ -664,7 +665,7 @@ void 
bridges::cpp_uno::shared::VtableFactory::flushCode(unsigned char const * bp
     __asm__ volatile ("isync" : : : "memory");
 }
 
-struct bridges::cpp_uno::shared::VtableFactory::Slot { void * fn; };
+struct bridges::cpp_uno::shared::VtableFactory::Slot { void const * fn; };
 
 bridges::cpp_uno::shared::VtableFactory::Slot *
 bridges::cpp_uno::shared::VtableFactory::mapBlockToVtable(void * block)
@@ -678,6 +679,12 @@ std::size_t 
bridges::cpp_uno::shared::VtableFactory::getBlockSize(
     return (slotCount + 2) * sizeof (Slot) + slotCount * codeSnippetSize;
 }
 
+namespace {
+// Some dummy type whose RTTI is used in the synthesized proxy vtables to make 
uses of dynamic_cast
+// on such proxy objects not crash:
+struct ProxyRtti {};
+}
+
 bridges::cpp_uno::shared::VtableFactory::Slot *
 bridges::cpp_uno::shared::VtableFactory::initializeBlock(
     void * block, sal_Int32 slotCount, sal_Int32,
@@ -685,7 +692,7 @@ bridges::cpp_uno::shared::VtableFactory::initializeBlock(
 {
     Slot * slots = mapBlockToVtable(block);
     slots[-2].fn = 0;
-    slots[-1].fn = 0;
+    slots[-1].fn = &typeid(ProxyRtti);
     return slots + slotCount;
 }
 
diff --git a/bridges/source/cpp_uno/gcc3_linux_riscv64/cpp2uno.cxx 
b/bridges/source/cpp_uno/gcc3_linux_riscv64/cpp2uno.cxx
index 6af52e9e471a..16f6ba27c0f4 100644
--- a/bridges/source/cpp_uno/gcc3_linux_riscv64/cpp2uno.cxx
+++ b/bridges/source/cpp_uno/gcc3_linux_riscv64/cpp2uno.cxx
@@ -32,6 +32,7 @@
 #include <stdio.h>
 //#include <string.h>
 #include <cstring>
+#include <typeinfo>
 
 using namespace com::sun::star::uno;
 
@@ -709,7 +710,7 @@ void 
bridges::cpp_uno::shared::VtableFactory::flushCode(unsigned char const* bpt
 
 struct bridges::cpp_uno::shared::VtableFactory::Slot
 {
-    void* fn;
+    void const* fn;
 };
 
 bridges::cpp_uno::shared::VtableFactory::Slot*
@@ -723,6 +724,15 @@ std::size_t 
bridges::cpp_uno::shared::VtableFactory::getBlockSize(sal_Int32 slot
     return (slotCount + 2) * sizeof(Slot) + slotCount * codeSnippetSize;
 }
 
+namespace
+{
+// Some dummy type whose RTTI is used in the synthesized proxy vtables to make 
uses of dynamic_cast
+// on such proxy objects not crash:
+struct ProxyRtti
+{
+};
+}
+
 bridges::cpp_uno::shared::VtableFactory::Slot*
 bridges::cpp_uno::shared::VtableFactory::initializeBlock(void* block, 
sal_Int32 slotCount,
                                                          sal_Int32,
@@ -730,7 +740,7 @@ 
bridges::cpp_uno::shared::VtableFactory::initializeBlock(void* block, sal_Int32
 {
     Slot* slots = mapBlockToVtable(block);
     slots[-2].fn = 0; //null
-    slots[-1].fn = 0; //destructor
+    slots[-1].fn = &typeid(ProxyRtti);
     return slots + slotCount;
 }
 
diff --git a/bridges/source/cpp_uno/gcc3_linux_s390/cpp2uno.cxx 
b/bridges/source/cpp_uno/gcc3_linux_s390/cpp2uno.cxx
index b9e61b148304..aca33d1ae511 100644
--- a/bridges/source/cpp_uno/gcc3_linux_s390/cpp2uno.cxx
+++ b/bridges/source/cpp_uno/gcc3_linux_s390/cpp2uno.cxx
@@ -31,6 +31,7 @@
 #include "share.hxx"
 #include <stdio.h>
 #include <string.h>
+#include <typeinfo>
 
 using namespace ::com::sun::star::uno;
 
@@ -602,7 +603,7 @@ void 
bridges::cpp_uno::shared::VtableFactory::flushCode(unsigned char const *, u
 {
 }
 
-struct bridges::cpp_uno::shared::VtableFactory::Slot { void * fn; };
+struct bridges::cpp_uno::shared::VtableFactory::Slot { void const * fn; };
 
 bridges::cpp_uno::shared::VtableFactory::Slot *
 bridges::cpp_uno::shared::VtableFactory::mapBlockToVtable(void * block)
@@ -616,6 +617,12 @@ std::size_t 
bridges::cpp_uno::shared::VtableFactory::getBlockSize(
     return (slotCount + 2) * sizeof (Slot) + slotCount * codeSnippetSize;
 }
 
+namespace {
+// Some dummy type whose RTTI is used in the synthesized proxy vtables to make 
uses of dynamic_cast
+// on such proxy objects not crash:
+struct ProxyRtti {};
+}
+
 bridges::cpp_uno::shared::VtableFactory::Slot *
 bridges::cpp_uno::shared::VtableFactory::initializeBlock(
     void * block, sal_Int32 slotCount, sal_Int32,
@@ -623,7 +630,7 @@ bridges::cpp_uno::shared::VtableFactory::initializeBlock(
 {
     Slot * slots = mapBlockToVtable(block);
     slots[-2].fn = 0;
-    slots[-1].fn = 0;
+    slots[-1].fn = &typeid(ProxyRtti);
     return slots + slotCount;
 }
 
diff --git a/bridges/source/cpp_uno/gcc3_linux_s390x/cpp2uno.cxx 
b/bridges/source/cpp_uno/gcc3_linux_s390x/cpp2uno.cxx
index ed48be648bca..285d1241a2d5 100644
--- a/bridges/source/cpp_uno/gcc3_linux_s390x/cpp2uno.cxx
+++ b/bridges/source/cpp_uno/gcc3_linux_s390x/cpp2uno.cxx
@@ -30,6 +30,7 @@
 
 #include "share.hxx"
 #include <stdio.h>
+#include <typeinfo>
 
 using namespace ::com::sun::star::uno;
 
@@ -565,7 +566,7 @@ void 
bridges::cpp_uno::shared::VtableFactory::flushCode(unsigned char const *, u
 {
 }
 
-struct bridges::cpp_uno::shared::VtableFactory::Slot { void * fn; };
+struct bridges::cpp_uno::shared::VtableFactory::Slot { void const * fn; };
 
 bridges::cpp_uno::shared::VtableFactory::Slot *
 bridges::cpp_uno::shared::VtableFactory::mapBlockToVtable(void * block)
@@ -579,6 +580,12 @@ std::size_t 
bridges::cpp_uno::shared::VtableFactory::getBlockSize(
     return (slotCount + 2) * sizeof (Slot) + slotCount * codeSnippetSize;
 }
 
+namespace {
+// Some dummy type whose RTTI is used in the synthesized proxy vtables to make 
uses of dynamic_cast
+// on such proxy objects not crash:
+struct ProxyRtti {};
+}
+
 bridges::cpp_uno::shared::VtableFactory::Slot *
 bridges::cpp_uno::shared::VtableFactory::initializeBlock(
     void * block, sal_Int32 slotCount, sal_Int32,
@@ -586,7 +593,7 @@ bridges::cpp_uno::shared::VtableFactory::initializeBlock(
 {
     Slot * slots = mapBlockToVtable(block);
     slots[-2].fn = 0;
-    slots[-1].fn = 0;
+    slots[-1].fn = &typeid(ProxyRtti);
     return slots + slotCount;
 }
 
diff --git a/bridges/source/cpp_uno/gcc3_linux_sparc/cpp2uno.cxx 
b/bridges/source/cpp_uno/gcc3_linux_sparc/cpp2uno.cxx
index 8afbd04a7161..950d644df106 100644
--- a/bridges/source/cpp_uno/gcc3_linux_sparc/cpp2uno.cxx
+++ b/bridges/source/cpp_uno/gcc3_linux_sparc/cpp2uno.cxx
@@ -17,6 +17,10 @@
  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
  */
 
+#include <sal/config.h>
+
+#include <typeinfo>
+
 #include <com/sun/star/uno/genfunc.hxx>
 #include <sal/log.hxx>
 #include <typelib/typedescription.hxx>
@@ -477,7 +481,7 @@ unsigned char * codeSnippet(
 
 } //end of namespace
 
-struct bridges::cpp_uno::shared::VtableFactory::Slot { void * fn; };
+struct bridges::cpp_uno::shared::VtableFactory::Slot { void const * fn; };
 
 bridges::cpp_uno::shared::VtableFactory::Slot *
 bridges::cpp_uno::shared::VtableFactory::mapBlockToVtable(void * block)
@@ -491,6 +495,12 @@ std::size_t 
bridges::cpp_uno::shared::VtableFactory::getBlockSize(
     return (slotCount + 2) * sizeof (Slot) + slotCount * codeSnippetSize;
 }
 
+namespace {
+// Some dummy type whose RTTI is used in the synthesized proxy vtables to make 
uses of dynamic_cast
+// on such proxy objects not crash:
+struct ProxyRtti {};
+}
+
 bridges::cpp_uno::shared::VtableFactory::Slot *
 bridges::cpp_uno::shared::VtableFactory::initializeBlock(
     void * block, sal_Int32 slotCount, sal_Int32,
@@ -498,7 +508,7 @@ bridges::cpp_uno::shared::VtableFactory::initializeBlock(
 {
     Slot * slots = mapBlockToVtable(block);
     slots[-2].fn = 0; //null
-    slots[-1].fn = 0; //destructor
+    slots[-1].fn = &typeid(ProxyRtti);
     return slots + slotCount;
 }
 
diff --git a/bridges/source/cpp_uno/gcc3_linux_sparc64/cpp2uno.cxx 
b/bridges/source/cpp_uno/gcc3_linux_sparc64/cpp2uno.cxx
index 9b157f082120..f455be45dc88 100644
--- a/bridges/source/cpp_uno/gcc3_linux_sparc64/cpp2uno.cxx
+++ b/bridges/source/cpp_uno/gcc3_linux_sparc64/cpp2uno.cxx
@@ -17,6 +17,10 @@
  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
  */
 
+#include <sal/config.h>
+
+#include <typeinfo>
+
 #include <com/sun/star/uno/genfunc.hxx>
 #include <sal/log.hxx>
 #include <typelib/typedescription.hxx>
@@ -650,7 +654,7 @@ unsigned char * codeSnippet(
 
 } //end of namespace
 
-struct bridges::cpp_uno::shared::VtableFactory::Slot { void * fn; };
+struct bridges::cpp_uno::shared::VtableFactory::Slot { void const * fn; };
 
 bridges::cpp_uno::shared::VtableFactory::Slot *
 bridges::cpp_uno::shared::VtableFactory::mapBlockToVtable(void * block)
@@ -664,6 +668,12 @@ std::size_t 
bridges::cpp_uno::shared::VtableFactory::getBlockSize(
     return (slotCount + 2) * sizeof (Slot) + slotCount * codeSnippetSize;
 }
 
+namespace {
+// Some dummy type whose RTTI is used in the synthesized proxy vtables to make 
uses of dynamic_cast
+// on such proxy objects not crash:
+struct ProxyRtti {};
+}
+
 bridges::cpp_uno::shared::VtableFactory::Slot *
 bridges::cpp_uno::shared::VtableFactory::initializeBlock(
     void * block, sal_Int32 slotCount, sal_Int32,
@@ -671,7 +681,7 @@ bridges::cpp_uno::shared::VtableFactory::initializeBlock(
 {
     Slot * slots = mapBlockToVtable(block);
     slots[-2].fn = 0; //null
-    slots[-1].fn = 0; //destructor
+    slots[-1].fn = &typeid(ProxyRtti);
     return slots + slotCount;
 }
 
diff --git a/bridges/source/cpp_uno/gcc3_linux_x86-64/cpp2uno.cxx 
b/bridges/source/cpp_uno/gcc3_linux_x86-64/cpp2uno.cxx
index f400c766a2e6..7466d0e225bc 100644
--- a/bridges/source/cpp_uno/gcc3_linux_x86-64/cpp2uno.cxx
+++ b/bridges/source/cpp_uno/gcc3_linux_x86-64/cpp2uno.cxx
@@ -20,6 +20,7 @@
 
 #include <stdio.h>
 #include <stdlib.h>
+#include <typeinfo>
 
 #include <rtl/alloc.h>
 #include <sal/log.hxx>
@@ -445,7 +446,7 @@ static unsigned char * codeSnippet( unsigned char * code,
     return code + codeSnippetSize;
 }
 
-struct bridges::cpp_uno::shared::VtableFactory::Slot { void * fn; };
+struct bridges::cpp_uno::shared::VtableFactory::Slot { void const * fn; };
 
 bridges::cpp_uno::shared::VtableFactory::Slot *
 bridges::cpp_uno::shared::VtableFactory::mapBlockToVtable(void * block)
@@ -459,17 +460,27 @@ std::size_t 
bridges::cpp_uno::shared::VtableFactory::getBlockSize(
     return (slotCount + 2) * sizeof (Slot) + slotCount * codeSnippetSize;
 }
 
+#if ENABLE_RUNTIME_OPTIMIZATIONS
+namespace {
+// Some dummy type whose RTTI is used in the synthesized proxy vtables to make 
uses of dynamic_cast
+// on such proxy objects not crash:
+struct ProxyRtti {};
+}
+#endif
+
 bridges::cpp_uno::shared::VtableFactory::Slot *
 bridges::cpp_uno::shared::VtableFactory::initializeBlock(
     void * block, sal_Int32 slotCount, sal_Int32 vtableNumber,
     typelib_InterfaceTypeDescription * type)
 {
     Slot * slots = mapBlockToVtable(block);
-    slots[-2].fn = reinterpret_cast<void *>(-(vtableNumber * sizeof (void *)));
 #if ENABLE_RUNTIME_OPTIMIZATIONS
-    slots[-1].fn = nullptr;
+    slots[-2].fn = nullptr;
+    slots[-1].fn = &typeid(ProxyRtti);
+    (void)vtableNumber;
     (void)type;
 #else
+    slots[-2].fn = reinterpret_cast<void *>(-(vtableNumber * sizeof (void *)));
     slots[-1].fn = x86_64::getRtti(type->aBase);
 #endif
     return slots + slotCount;
diff --git a/bridges/source/cpp_uno/gcc3_macosx_x86-64/cpp2uno.cxx 
b/bridges/source/cpp_uno/gcc3_macosx_x86-64/cpp2uno.cxx
index efdf211d8a6e..11426e9475b2 100644
--- a/bridges/source/cpp_uno/gcc3_macosx_x86-64/cpp2uno.cxx
+++ b/bridges/source/cpp_uno/gcc3_macosx_x86-64/cpp2uno.cxx
@@ -20,6 +20,7 @@
 
 #include <stdio.h>
 #include <stdlib.h>
+#include <typeinfo>
 
 #include <rtl/alloc.h>
 #include <sal/log.hxx>
@@ -453,7 +454,7 @@ static unsigned char * codeSnippet( unsigned char * code,
     return code + codeSnippetSize;
 }
 
-struct bridges::cpp_uno::shared::VtableFactory::Slot { void * fn; };
+struct bridges::cpp_uno::shared::VtableFactory::Slot { void const * fn; };
 
 bridges::cpp_uno::shared::VtableFactory::Slot *
 bridges::cpp_uno::shared::VtableFactory::mapBlockToVtable(void * block)
@@ -467,6 +468,12 @@ std::size_t 
bridges::cpp_uno::shared::VtableFactory::getBlockSize(
     return (slotCount + 2) * sizeof (Slot) + slotCount * codeSnippetSize;
 }
 
+namespace {
+// Some dummy type whose RTTI is used in the synthesized proxy vtables to make 
uses of dynamic_cast
+// on such proxy objects not crash:
+struct ProxyRtti {};
+}
+
 bridges::cpp_uno::shared::VtableFactory::Slot *
 bridges::cpp_uno::shared::VtableFactory::initializeBlock(
     void * block, sal_Int32 slotCount, sal_Int32,
@@ -474,7 +481,7 @@ bridges::cpp_uno::shared::VtableFactory::initializeBlock(
 {
     Slot * slots = mapBlockToVtable(block);
     slots[-2].fn = nullptr;
-    slots[-1].fn = nullptr;
+    slots[-1].fn = &typeid(ProxyRtti);
     return slots + slotCount;
 }
 
diff --git a/bridges/source/cpp_uno/gcc3_solaris_intel/cpp2uno.cxx 
b/bridges/source/cpp_uno/gcc3_solaris_intel/cpp2uno.cxx
index 5609bd6dc839..33687f1d0a02 100644
--- a/bridges/source/cpp_uno/gcc3_solaris_intel/cpp2uno.cxx
+++ b/bridges/source/cpp_uno/gcc3_solaris_intel/cpp2uno.cxx
@@ -20,6 +20,7 @@
 
 #include <sal/alloca.h>
 #include <strings.h>
+#include <typeinfo>
 
 #include <com/sun/star/uno/genfunc.hxx>
 #include "com/sun/star/uno/RuntimeException.hpp"
@@ -431,7 +432,7 @@ unsigned char * codeSnippet(
 
 }
 
-struct bridges::cpp_uno::shared::VtableFactory::Slot { void * fn; };
+struct bridges::cpp_uno::shared::VtableFactory::Slot { void const * fn; };
 
 bridges::cpp_uno::shared::VtableFactory::Slot *
 bridges::cpp_uno::shared::VtableFactory::mapBlockToVtable(void * block)
@@ -445,6 +446,12 @@ std::size_t 
bridges::cpp_uno::shared::VtableFactory::getBlockSize(
     return (slotCount + 2) * sizeof (Slot) + slotCount * codeSnippetSize;
 }
 
+namespace {
+// Some dummy type whose RTTI is used in the synthesized proxy vtables to make 
uses of dynamic_cast
+// on such proxy objects not crash:
+struct ProxyRtti {};
+}
+
 bridges::cpp_uno::shared::VtableFactory::Slot *
 bridges::cpp_uno::shared::VtableFactory::initializeBlock(
     void * block, sal_Int32 slotCount, sal_Int32,
@@ -452,7 +459,7 @@ bridges::cpp_uno::shared::VtableFactory::initializeBlock(
 {
     Slot * slots = mapBlockToVtable(block);
     slots[-2].fn = 0;
-    slots[-1].fn = 0;
+    slots[-1].fn = &typeid(ProxyRtti);
     return slots + slotCount;
 }
 
diff --git a/bridges/source/cpp_uno/gcc3_solaris_sparc/cpp2uno.cxx 
b/bridges/source/cpp_uno/gcc3_solaris_sparc/cpp2uno.cxx
index 639b8da3dc88..55c1360f844e 100644
--- a/bridges/source/cpp_uno/gcc3_solaris_sparc/cpp2uno.cxx
+++ b/bridges/source/cpp_uno/gcc3_solaris_sparc/cpp2uno.cxx
@@ -17,6 +17,10 @@
  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
  */
 
+#include <sal/config.h>
+
+#include <typeinfo>
+
 #include <com/sun/star/uno/genfunc.hxx>
 #include <sal/log.hxx>
 #include <typelib/typedescription.hxx>
@@ -475,7 +479,7 @@ unsigned char * codeSnippet(
 
 } //end of namespace
 
-struct bridges::cpp_uno::shared::VtableFactory::Slot { void * fn; };
+struct bridges::cpp_uno::shared::VtableFactory::Slot { void const * fn; };
 
 bridges::cpp_uno::shared::VtableFactory::Slot *
 bridges::cpp_uno::shared::VtableFactory::mapBlockToVtable(void * block)
@@ -489,6 +493,12 @@ std::size_t 
bridges::cpp_uno::shared::VtableFactory::getBlockSize(
     return (slotCount + 2) * sizeof (Slot) + slotCount * codeSnippetSize;
 }
 
+namespace {
+// Some dummy type whose RTTI is used in the synthesized proxy vtables to make 
uses of dynamic_cast
+// on such proxy objects not crash:
+struct ProxyRtti {};
+}
+
 bridges::cpp_uno::shared::VtableFactory::Slot *
 bridges::cpp_uno::shared::VtableFactory::initializeBlock(
     void * block, sal_Int32 slotCount, sal_Int32,
@@ -496,7 +506,7 @@ bridges::cpp_uno::shared::VtableFactory::initializeBlock(
 {
     Slot * slots = mapBlockToVtable(block);
     slots[-2].fn = 0; //null
-    slots[-1].fn = 0; //destructor
+    slots[-1].fn = &typeid(ProxyRtti);
     return slots + slotCount;
 }
 
diff --git a/bridges/source/cpp_uno/msvc_win32_arm64/cpp2uno.cxx 
b/bridges/source/cpp_uno/msvc_win32_arm64/cpp2uno.cxx
index cfefa60e748a..fc956121dc07 100644
--- a/bridges/source/cpp_uno/msvc_win32_arm64/cpp2uno.cxx
+++ b/bridges/source/cpp_uno/msvc_win32_arm64/cpp2uno.cxx
@@ -24,6 +24,8 @@
 #include <cstddef>
 #include <cstdlib>
 #include <cstring>
+#include <limits>
+#include <typeinfo>
 
 #include <com/sun/star/uno/XInterface.hpp>
 #include <com/sun/star/uno/genfunc.hxx>
@@ -42,6 +44,8 @@
 
 #include "abi.hxx"
 
+extern "C" IMAGE_DOS_HEADER const __ImageBase;
+
 extern "C" void vtableSlotCall();
 
 using namespace ::com::sun::star;
@@ -357,27 +361,110 @@ std::size_t 
bridges::cpp_uno::shared::VtableFactory::getBlockSize(sal_Int32 slot
     return (slotCount + 1) * sizeof(Slot) + slotCount * codeSnippetSize;
 }
 
+static sal_uInt32 imageRelative(void const* p)
+{
+    assert(reinterpret_cast<sal_uIntPtr>(p) >= 
reinterpret_cast<sal_uIntPtr>(&__ImageBase)
+           && reinterpret_cast<sal_uIntPtr>(p) - 
reinterpret_cast<sal_uIntPtr>(&__ImageBase)
+                  <= std::numeric_limits<sal_uInt32>::max());
+    return reinterpret_cast<sal_uIntPtr>(p) - 
reinterpret_cast<sal_uIntPtr>(&__ImageBase);
+}
+
+namespace
+{
+// Some dummy type whose RTTI is used in the synthesized proxy vtables to make 
uses of dynamic_cast
+// on such proxy objects not crash:
+struct ProxyRtti
+{
+};
+
+// The following vtable RTTI data is based on how the code at
+// 
<https://github.com/llvm/llvm-project/blob/main/clang/lib/CodeGen/MicrosoftCXXABI.cpp>
 computes
+// such data, and on how 
<https://devblogs.microsoft.com/oldnewthing/20041025-00/?p=37483>
+// "Accessing the current module’s HINSTANCE from a static library" obtians 
__ImageBase:
+
+struct RttiClassHierarchyDescriptor;
+
+#pragma warning(push)
+#pragma warning(disable : 4324) // "structure was padded due to alignment 
specifier"
+
+struct alignas(16) RttiBaseClassDescriptor
+{
+    sal_uInt32 n0 = imageRelative(&typeid(ProxyRtti));
+    sal_uInt32 n1 = 0;
+    sal_uInt32 n2 = 0;
+    sal_uInt32 n3 = 0xFFFFFFFF;
+    sal_uInt32 n4 = 0;
+    sal_uInt32 n5 = 0x40;
+    sal_uInt32 n6;
+    RttiBaseClassDescriptor(RttiClassHierarchyDescriptor const* chd)
+        : n6(imageRelative(chd))
+    {
+    }
+};
+
+struct alignas(4) RttiBaseClassArray
+{
+    sal_uInt32 n0;
+    sal_uInt32 n1 = 0;
+    RttiBaseClassArray(RttiBaseClassDescriptor const* bcd)
+        : n0(imageRelative(bcd))
+    {
+    }
+};
+
+struct alignas(8) RttiClassHierarchyDescriptor
+{
+    sal_uInt32 n0 = 0;
+    sal_uInt32 n1 = 0;
+    sal_uInt32 n2 = 1;
+    sal_uInt32 n3;
+    RttiClassHierarchyDescriptor(RttiBaseClassArray const* bca)
+        : n3(imageRelative(bca))
+    {
+    }
+};
+
+struct alignas(16) RttiCompleteObjectLocator
+{
+    sal_uInt32 n0 = 1;
+    sal_uInt32 n1 = 0;
+    sal_uInt32 n2 = 0;
+    sal_uInt32 n3 = imageRelative(&typeid(ProxyRtti));
+    sal_uInt32 n4;
+    sal_uInt32 n5 = imageRelative(this);
+    RttiCompleteObjectLocator(RttiClassHierarchyDescriptor const* chd)
+        : n4(imageRelative(chd))
+    {
+    }
+};
+
+struct Rtti
+{
+    RttiBaseClassDescriptor bcd;
+    RttiBaseClassArray bca;
+    RttiClassHierarchyDescriptor chd;
+    RttiCompleteObjectLocator col;
+    Rtti()
+        : bcd(&chd)
+        , bca(&bcd)
+        , chd(&bca)
+        , col(&chd)
+    {
+    }
+};
+
+#pragma warning(pop)
+}
+
 bridges::cpp_uno::shared::VtableFactory::Slot*
 bridges::cpp_uno::shared::VtableFactory::initializeBlock(void* block, 
sal_Int32 slotCount,
                                                          sal_Int32,
                                                          
typelib_InterfaceTypeDescription*)
 {
-    struct Rtti
-    {
-        sal_Int32 n0, n1, n2;
-        type_info* rtti;
-        Rtti()
-            : n0(0)
-            , n1(0)
-            , n2(0)
-            , rtti(RTTInfos::get("com.sun.star.uno.XInterface"))
-        {
-        }
-    };
     static Rtti rtti;
 
     Slot* slots = mapBlockToVtable(block);
-    slots[-1].fn = &rtti;
+    slots[-1].fn = &rtti.col;
     return slots + slotCount;
 }
 
diff --git a/bridges/source/cpp_uno/msvc_win32_intel/cpp2uno.cxx 
b/bridges/source/cpp_uno/msvc_win32_intel/cpp2uno.cxx
index 0908c7666b50..577c318c5767 100644
--- a/bridges/source/cpp_uno/msvc_win32_intel/cpp2uno.cxx
+++ b/bridges/source/cpp_uno/msvc_win32_intel/cpp2uno.cxx
@@ -18,6 +18,10 @@
  */
 
 
+#include <sal/config.h>
+
+#include <typeinfo>
+
 #include <malloc.h>
 
 #include <com/sun/star/uno/genfunc.hxx>
@@ -124,23 +128,80 @@ std::size_t 
bridges::cpp_uno::shared::VtableFactory::getBlockSize(
     return (slotCount + 1) * sizeof (Slot) + slotCount * codeSnippetSize;
 }
 
+namespace {
+
+// Some dummy type whose RTTI is used in the synthesized proxy vtables to make 
uses of dynamic_cast
+// on such proxy objects not crash:
+struct ProxyRtti {};
+
+// The following vtable RTTI data is based on how the code at
+// 
<https://github.com/llvm/llvm-project/blob/main/clang/lib/CodeGen/MicrosoftCXXABI.cpp>
 computes
+// such data:
+
+struct RttiClassHierarchyDescriptor;
+
+#pragma warning (push)
+#pragma warning (disable: 4324) // "structure was padded due to alignment 
specifier"
+
+struct alignas(16) RttiBaseClassDescriptor {
+    sal_uInt32 n0 = reinterpret_cast<sal_uInt32>(&typeid(ProxyRtti));
+    sal_uInt32 n1 = 0;
+    sal_uInt32 n2 = 0;
+    sal_uInt32 n3 = 0xFFFFFFFF;
+    sal_uInt32 n4 = 0;
+    sal_uInt32 n5 = 0x40;
+    sal_uInt32 n6;
+    RttiBaseClassDescriptor(RttiClassHierarchyDescriptor const * chd):
+        n6(reinterpret_cast<sal_uInt32>(chd)) {}
+};
+
+struct alignas(4) RttiBaseClassArray {
+    sal_uInt32 n0;
+    sal_uInt32 n1 = 0;
+    RttiBaseClassArray(RttiBaseClassDescriptor const * bcd): 
n0(reinterpret_cast<sal_uInt32>(bcd))
+    {}
+};
+
+struct alignas(4) RttiClassHierarchyDescriptor {
+    sal_uInt32 n0 = 0;
+    sal_uInt32 n1 = 0;
+    sal_uInt32 n2 = 1;
+    sal_uInt32 n3;
+    RttiClassHierarchyDescriptor(RttiBaseClassArray const * bca):
+        n3(reinterpret_cast<sal_uInt32>(bca)) {}
+};
+
+struct alignas(16) RttiCompleteObjectLocator {
+    sal_uInt32 n0 = 0;
+    sal_uInt32 n1 = 0;
+    sal_uInt32 n2 = 0;
+    sal_uInt32 n3 = reinterpret_cast<sal_uInt32>(&typeid(ProxyRtti));
+    sal_uInt32 n4;
+    RttiCompleteObjectLocator(RttiClassHierarchyDescriptor const * chd):
+        n4(reinterpret_cast<sal_uInt32>(chd)) {}
+};
+
+struct Rtti {
+    RttiBaseClassDescriptor bcd;
+    RttiBaseClassArray bca;
+    RttiClassHierarchyDescriptor chd;
+    RttiCompleteObjectLocator col;
+    Rtti(): bcd(&chd), bca(&bcd), chd(&bca), col(&chd) {}
+};
+
+#pragma warning (pop)
+
+}
+
 bridges::cpp_uno::shared::VtableFactory::Slot *
 bridges::cpp_uno::shared::VtableFactory::initializeBlock(
     void * block, sal_Int32 slotCount, sal_Int32,
     typelib_InterfaceTypeDescription *)
 {
-    struct Rtti {
-        sal_Int32 n0, n1, n2;
-        type_info * rtti;
-        Rtti():
-            n0(0), n1(0), n2(0),
-            rtti(RTTInfos::get("com.sun.star.uno.XInterface"))
-        {}
-    };
     static Rtti rtti;
 
     Slot * slots = mapBlockToVtable(block);
-    slots[-1].fn = &rtti;
+    slots[-1].fn = &rtti.col;
     return slots + slotCount;
 }
 
diff --git a/bridges/source/cpp_uno/msvc_win32_x86-64/cpp2uno.cxx 
b/bridges/source/cpp_uno/msvc_win32_x86-64/cpp2uno.cxx
index 159eb99a4756..974a4a94d48b 100644
--- a/bridges/source/cpp_uno/msvc_win32_x86-64/cpp2uno.cxx
+++ b/bridges/source/cpp_uno/msvc_win32_x86-64/cpp2uno.cxx
@@ -18,6 +18,12 @@
  */
 
 
+#include <sal/config.h>
+
+#include <cassert>
+#include <limits>
+#include <typeinfo>
+
 #include <malloc.h>
 
 #include <com/sun/star/uno/genfunc.hxx>
@@ -34,6 +40,8 @@
 #include <msvc/cpp2uno.hxx>
 #include <msvc/amd64.hxx>
 
+extern "C" IMAGE_DOS_HEADER const __ImageBase;
+
 using namespace ::com::sun::star;
 
 extern "C" typelib_TypeClass cpp_vtable_call(sal_Int64 nOffsetAndIndex, void 
** pCallStack)
@@ -141,24 +149,87 @@ std::size_t 
bridges::cpp_uno::shared::VtableFactory::getBlockSize(
     return (slotCount + 1) * sizeof (Slot) + slotCount * codeSnippetSize;
 }
 
+static sal_uInt32 imageRelative(void const * p) {
+    assert(
+        reinterpret_cast<sal_uIntPtr>(p) >= 
reinterpret_cast<sal_uIntPtr>(&__ImageBase)
+        && reinterpret_cast<sal_uIntPtr>(p) - 
reinterpret_cast<sal_uIntPtr>(&__ImageBase)
+            <= std::numeric_limits<sal_uInt32>::max());
+    return reinterpret_cast<sal_uIntPtr>(p) - 
reinterpret_cast<sal_uIntPtr>(&__ImageBase);
+}
+
+namespace {
+
+// Some dummy type whose RTTI is used in the synthesized proxy vtables to make 
uses of dynamic_cast
+// on such proxy objects not crash:
+struct ProxyRtti {};
+
+// The following vtable RTTI data is based on how the code at
+// 
<https://github.com/llvm/llvm-project/blob/main/clang/lib/CodeGen/MicrosoftCXXABI.cpp>
 computes
+// such data, and on how 
<https://devblogs.microsoft.com/oldnewthing/20041025-00/?p=37483>
+// "Accessing the current module’s HINSTANCE from a static library" obtians 
__ImageBase:
+
+struct RttiClassHierarchyDescriptor;
+
+#pragma warning (push)
+#pragma warning (disable: 4324) // "structure was padded due to alignment 
specifier"
+
+struct alignas(16) RttiBaseClassDescriptor {
+    sal_uInt32 n0 = imageRelative(&typeid(ProxyRtti));
+    sal_uInt32 n1 = 0;
+    sal_uInt32 n2 = 0;
+    sal_uInt32 n3 = 0xFFFFFFFF;
+    sal_uInt32 n4 = 0;
+    sal_uInt32 n5 = 0x40;
+    sal_uInt32 n6;
+    RttiBaseClassDescriptor(RttiClassHierarchyDescriptor const * chd): 
n6(imageRelative(chd)) {}
+};
+
+struct alignas(4) RttiBaseClassArray {
+    sal_uInt32 n0;
+    sal_uInt32 n1 = 0;
+    RttiBaseClassArray(RttiBaseClassDescriptor const * bcd): 
n0(imageRelative(bcd)) {}
+};
+
+struct alignas(8) RttiClassHierarchyDescriptor {
+    sal_uInt32 n0 = 0;
+    sal_uInt32 n1 = 0;
+    sal_uInt32 n2 = 1;
+    sal_uInt32 n3;
+    RttiClassHierarchyDescriptor(RttiBaseClassArray const * bca): 
n3(imageRelative(bca)) {}
+};
+
+struct alignas(16) RttiCompleteObjectLocator {
+    sal_uInt32 n0 = 1;
+    sal_uInt32 n1 = 0;
+    sal_uInt32 n2 = 0;
+    sal_uInt32 n3 = imageRelative(&typeid(ProxyRtti));
+    sal_uInt32 n4;
+    sal_uInt32 n5 = imageRelative(this);
+    RttiCompleteObjectLocator(RttiClassHierarchyDescriptor const * chd): 
n4(imageRelative(chd)) {}
+};
+
+struct Rtti {
+    RttiBaseClassDescriptor bcd;
+    RttiBaseClassArray bca;
+    RttiClassHierarchyDescriptor chd;
+    RttiCompleteObjectLocator col;
+    Rtti(): bcd(&chd), bca(&bcd), chd(&bca), col(&chd) {}
+};
+
+#pragma warning (pop)
+
+}
+
 bridges::cpp_uno::shared::VtableFactory::Slot *
 bridges::cpp_uno::shared::VtableFactory::initializeBlock(
     void * block,
     sal_Int32 slotCount,
     sal_Int32, typelib_InterfaceTypeDescription *)
 {
-    struct Rtti {
-        sal_Int32 n0, n1, n2;
-        type_info * rtti;
-        Rtti():
-            n0(0), n1(0), n2(0),
-            rtti(RTTInfos::get("com.sun.star.uno.XInterface"))
-        {}
-    };
     static Rtti rtti;
 
     Slot * slots = mapBlockToVtable(block);
-    slots[-1].fn = &rtti;
+    slots[-1].fn = &rtti.col;
     return slots + slotCount;
 }
 
diff --git a/testtools/source/bridgetest/bridgetest.cxx 
b/testtools/source/bridgetest/bridgetest.cxx
index 78bcdc6f0d3a..6067e3a5235a 100644
--- a/testtools/source/bridgetest/bridgetest.cxx
+++ b/testtools/source/bridgetest/bridgetest.cxx
@@ -1263,6 +1263,10 @@ sal_Int32 TestBridgeImpl::run( const Sequence< OUString 
> & rArgs )
         bRet = check( raiseException( xLBT ) , "exception test" )&& bRet;
         bRet = check( raiseOnewayException( xLBT ),
                       "oneway exception test" ) && bRet;
+        // Check that a dynamic_cast from what is potentially a proxy object 
does not cause a crash
+        // (and the choice of TestBridgeImpl as target is rather arbitrary, it 
is just some type for
+        // which the dynamic_cast is known to be null):
+        bRet = (dynamic_cast<TestBridgeImpl *>(xOriginal.get()) == nullptr) && 
bRet;
         if (! bRet)
         {
             throw RuntimeException( "error: test failed!" );

Reply via email to