codemaker/source/cppumaker/cpputype.cxx |   12 ++++++++++--
 include/unotools/weakref.hxx            |    7 ++++++-
 2 files changed, 16 insertions(+), 3 deletions(-)

New commits:
commit 485c9d4f0e59e13e772da8f8a7975f0ddd77c33e
Author:     Stephan Bergmann <sberg...@redhat.com>
AuthorDate: Fri Dec 2 17:01:02 2022 +0100
Commit:     Stephan Bergmann <sberg...@redhat.com>
CommitDate: Sat Dec 3 07:09:38 2022 +0000

    Clarify the use of untools::WeakReference
    
    ...which had been introduced in 78040af9acea0ab681aa54ff23844b647bc9b4f3
    "loplugin:refcounting in sc" as a variation on css::uno::WeakReference from
    include/cppuhelper/weakref.hxx, but without giving much of a rationale.
    
    And, at least for --with-latest-c++ builds using a capable C++20 compiler,
    ensure that the given interface_type is such that the static_cast and
    dynamic_cast in the implementation of unotools::WeakReference::get are 
actually
    sound:  If interface_type could be a UNO interface type, that would imply 
that
    the xInterface obtained from the underlying WeakReferenceHelper::get() 
could be
    a proxy from the C++ UNO bridge, which could (a) be a proxy for only a 
subtype
    of interface_type (e.g., just for XInterface), so that the static_cast 
would be
    broken, and (b) be a proxy for which the vtable's RTTI slot is not set up 
(see
    e.g. the ENABLE_RUNTIME_OPTIMIZATIONS code in
    bridges::cpp_uno::shared::VtableFactory::initializeBlock in
    bridges/source/cpp_uno/gcc3_linux_x86-64/cpp2uno.cxx), so that the 
dynamic_cast
    could crash.  (These issues can even happen when the given interface_type 
is a
    C++ implementation class type, but the given object has been bridged over 
some
    C++ to C++ UNO ("purpose") bridge, but lets leave it at that...)
    
    This required adding some cppu::detail::isUnoInterfaceType predicate to the
    include files generated by cppumaker, which can be useful in other places 
too.
    (For the call to isUnoInterfaceType in the requires-clause of
    unotools::WeakReference<interface_type>::get to give the correct answer, it 
is
    important that interface_type is a complete type---i.e., the corresponding
    codemaker-generated .hpp having been included if interface_type actually 
were a
    UNO include type.  But that is already nicely required by the call to
    std::is_convertible_v in the implementation of that function, anyway.)
    
    Change-Id: Ia5efd70085d2d6d45fa0995d00dc8def564bbe5f
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/143601
    Tested-by: Jenkins
    Reviewed-by: Stephan Bergmann <sberg...@redhat.com>

diff --git a/codemaker/source/cppumaker/cpputype.cxx 
b/codemaker/source/cppumaker/cpputype.cxx
index 03fcd033beca..2c8f938e6bb1 100644
--- a/codemaker/source/cppumaker/cpputype.cxx
+++ b/codemaker/source/cppumaker/cpputype.cxx
@@ -1184,7 +1184,7 @@ void InterfaceType::dumpHppFile(
     out << "\n";
     addDefaultHxxIncludes(includes);
     includes.dump(out, &name_, !(m_cppuTypeLeak || m_cppuTypeDynamic));
-    out << "\n";
+    out << "\n#if defined LIBO_INTERNAL_ONLY\n#include 
<type_traits>\n#endif\n\n";
     dumpGetCppuType(out);
     out << "\n::css::uno::Type const & "
         << codemaker::cpp::scopedCppName(u2b(name_))
@@ -1194,7 +1194,15 @@ void InterfaceType::dumpHppFile(
     dumpType(out, name_, false, false, true);
     out << " >::get();\n";
     dec();
-    out << "}\n\n#endif // "<< headerDefine << "\n";
+    out << "}\n\n#if defined LIBO_INTERNAL_ONLY\nnamespace cppu::detail {\n";
+    if (name_ == "com.sun.star.uno.XInterface") {
+        out << "template<typename> struct IsUnoInterfaceType: 
::std::false_type {};\n"
+               "template<typename T> inline constexpr auto isUnoInterfaceType 
="
+                   " IsUnoInterfaceType<T>::value;\n";
+    }
+    out << "template<> struct IsUnoInterfaceType<";
+    dumpType(out, name_, false, false, true);
+    out << ">: ::std::true_type {};\n}\n#endif\n\n#endif // "<< headerDefine 
<< "\n";
 }
 
 void InterfaceType::dumpAttributes(FileStream & out) const
diff --git a/include/unotools/weakref.hxx b/include/unotools/weakref.hxx
index 554bd433b687..1d9b29f82e70 100644
--- a/include/unotools/weakref.hxx
+++ b/include/unotools/weakref.hxx
@@ -42,7 +42,9 @@ namespace unotools
     behind it *is* thread-safe, so multiple threads can have their own
     WeakReferences to the same XWeak object.
 
-    @tparam interface_type type of interface
+    @tparam interface_type Must be a C++ implementation class type, not a UNO 
interface type.  (See
+    the C++20 requires-clause on the get member.  That clause is not put on 
the class as a whole to
+    avoid overly tight requirements on when interface_type needs to be 
complete.)
 */
 template <class interface_type>
 class SAL_WARN_UNUSED WeakReference : public 
com::sun::star::uno::WeakReferenceHelper
@@ -113,6 +115,9 @@ public:
          @return hard reference or null, if the weakly referenced interface 
has gone
     */
     rtl::Reference<interface_type> SAL_CALL get() const
+#if __cplusplus >= 202002L
+        requires(!cppu::detail::isUnoInterfaceType<interface_type>)
+#endif
     {
         css::uno::Reference<css::uno::XInterface> xInterface = 
WeakReferenceHelper::get();
         // If XInterface is an ambiguous base of interface_type, we have to 
use dynamic_cast,

Reply via email to