Bug Summary

File:home/maarten/src/libreoffice/core/include/com/sun/star/uno/Reference.hxx
Warning:line 109, column 9
Use of memory after it is freed

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name weak.cxx -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -mframe-pointer=all -fmath-errno -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib64/clang/11.0.0 -D BOOST_ERROR_CODE_HEADER_ONLY -D BOOST_SYSTEM_NO_DEPRECATED -D CPPU_ENV=gcc3 -D LINUX -D OSL_DEBUG_LEVEL=1 -D SAL_LOG_INFO -D SAL_LOG_WARN -D UNIX -D UNX -D X86_64 -D _PTHREADS -D _REENTRANT -D CPPUHELPER_DLLIMPLEMENTATION -D EXCEPTIONS_ON -D LIBO_INTERNAL_ONLY -I /home/maarten/src/libreoffice/core/include -I /usr/lib/jvm/java-11-openjdk-11.0.9.10-0.0.ea.fc33.x86_64/include -I /usr/lib/jvm/java-11-openjdk-11.0.9.10-0.0.ea.fc33.x86_64/include/linux -I /home/maarten/src/libreoffice/core/config_host -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/cppuhelper/comprehensive -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/udkapi/comprehensive -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/offapi/comprehensive -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10 -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10/x86_64-redhat-linux -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10/backward -internal-isystem /usr/local/include -internal-isystem /usr/lib64/clang/11.0.0/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O0 -Wno-missing-braces -std=c++17 -fdeprecated-macro -fdebug-compilation-dir /home/maarten/src/libreoffice/core -ferror-limit 19 -fvisibility hidden -fvisibility-inlines-hidden -stack-protector 2 -fgnuc-version=4.2.1 -fcxx-exceptions -fexceptions -debug-info-kind=constructor -analyzer-output=html -faddrsig -o /home/maarten/tmp/wis/scan-build-libreoffice/output/report/2020-10-07-141433-9725-1 -x c++ /home/maarten/src/libreoffice/core/cppuhelper/source/weak.cxx

/home/maarten/src/libreoffice/core/cppuhelper/source/weak.cxx

1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20#include <sal/config.h>
21#include <sal/log.hxx>
22
23#include <osl/diagnose.h>
24#include <osl/mutex.hxx>
25#include <cppuhelper/weakagg.hxx>
26#include <cppuhelper/exc_hlp.hxx>
27#include <cppuhelper/queryinterface.hxx>
28
29#include <com/sun/star/lang/DisposedException.hpp>
30
31#include <algorithm>
32#include <vector>
33
34using namespace osl;
35using namespace com::sun::star::uno;
36
37/** */ //for docpp
38namespace cppu
39{
40
41// due to static Reflection destruction from usr, there must be a mutex leak (#73272#)
42// this is used to lock all instances of OWeakConnectionPoint and OWeakRefListener as well as OWeakObject::m_pWeakConnectionPoint
43static Mutex & getWeakMutex()
44{
45 static Mutex * s_pMutex = new Mutex();
46 return *s_pMutex;
47}
48
49
50//-- OWeakConnectionPoint ----------------------------------------------------
51
52class OWeakConnectionPoint: public XAdapter
53{
54public:
55 /**
56 Hold the weak object without an acquire (only the pointer).
57 */
58 explicit OWeakConnectionPoint( OWeakObject* pObj )
59 : m_aRefCount( 0 )
60 , m_pObject(pObj)
61 {}
62
63 // noncopyable
64 OWeakConnectionPoint(const OWeakConnectionPoint&) = delete;
65 const OWeakConnectionPoint& operator=(const OWeakConnectionPoint&) = delete;
66
67 // XInterface
68 Any SAL_CALL queryInterface( const Type & rType ) override;
69 void SAL_CALL acquire() throw() override;
70 void SAL_CALL release() throw() override;
71
72 // XAdapter
73 css::uno::Reference< css::uno::XInterface > SAL_CALL queryAdapted() override;
74 void SAL_CALL addReference( const css::uno::Reference< css::uno::XReference >& xRef ) override;
75 void SAL_CALL removeReference( const css::uno::Reference< css::uno::XReference >& xRef ) override;
76
77 /// Called from the weak object if the reference count goes to zero.
78 ///
79 /// @throws css::uno::RuntimeException
80 void dispose();
81
82private:
83 virtual ~OWeakConnectionPoint() {}
84
85 /// The reference counter.
86 oslInterlockedCount m_aRefCount;
87 /// The weak object
88 OWeakObject* m_pObject;
89 /// The container to hold the weak references
90 std::vector<Reference<XReference>> m_aReferences;
91};
92
93// XInterface
94Any SAL_CALL OWeakConnectionPoint::queryInterface( const Type & rType )
95{
96 return ::cppu::queryInterface(
97 rType, static_cast< XAdapter * >( this ), static_cast< XInterface * >( this ) );
98}
99
100// XInterface
101void SAL_CALL OWeakConnectionPoint::acquire() throw()
102{
103 osl_atomic_increment( &m_aRefCount )__sync_add_and_fetch((&m_aRefCount), 1);
104}
105
106// XInterface
107void SAL_CALL OWeakConnectionPoint::release() throw()
108{
109 if (! osl_atomic_decrement( &m_aRefCount )__sync_sub_and_fetch((&m_aRefCount), 1))
110 delete this;
111}
112
113void OWeakConnectionPoint::dispose()
114{
115 std::vector<Reference<XReference>> aCopy;
116 { // only hold the mutex while we access the field
117 MutexGuard aGuard(getWeakMutex());
118 // OWeakObject is not the only owner of this, so clear m_pObject
119 // so that queryAdapted() won't use it now that it's dead
120 m_pObject = nullptr;
121 // other code is going to call removeReference while we are doing this, so we need a
122 // copy, but since we are disposing and going away, we can just take the original data
123 aCopy.swap(m_aReferences);
124 }
125 Any ex;
126 for (const Reference<XReference> & i : aCopy )
127 {
128 try
129 {
130 i->dispose();
131 }
132 catch (css::lang::DisposedException &) {}
133 catch (RuntimeException &)
134 {
135 ex = cppu::getCaughtException();
136 }
137 }
138 if (ex.hasValue())
139 {
140 cppu::throwException(ex);
141 }
142}
143
144// XInterface
145Reference< XInterface > SAL_CALL OWeakConnectionPoint::queryAdapted()
146{
147 Reference< XInterface > ret;
148
149 ClearableMutexGuard guard(getWeakMutex());
150
151 if (m_pObject)
152 {
153 oslInterlockedCount n = osl_atomic_increment( &m_pObject->m_refCount )__sync_add_and_fetch((&m_pObject->m_refCount), 1);
154
155 if (n > 1)
156 {
157 // The reference is incremented. The object cannot be destroyed.
158 // Release the guard at the earliest point.
159 guard.clear();
160 // WeakObject has a (XInterface *) cast operator
161 ret = *m_pObject;
162 osl_atomic_decrement( &m_pObject->m_refCount )__sync_sub_and_fetch((&m_pObject->m_refCount), 1);
163 }
164 else
165 // Another thread wait in the dispose method at the guard
166 osl_atomic_decrement( &m_pObject->m_refCount )__sync_sub_and_fetch((&m_pObject->m_refCount), 1);
167 }
168
169 return ret;
170}
171
172// XInterface
173void SAL_CALL OWeakConnectionPoint::addReference(const Reference< XReference >& rRef)
174{
175 MutexGuard aGuard(getWeakMutex());
176 m_aReferences.push_back( rRef );
177}
178
179// XInterface
180void SAL_CALL OWeakConnectionPoint::removeReference(const Reference< XReference >& rRef)
181{
182 MutexGuard aGuard(getWeakMutex());
183 // Search from end because the thing that last added a ref is most likely to be the
184 // first to remove a ref.
185 // It's not really valid to compare the pointer directly, but it's faster.
186 auto it = std::find_if(m_aReferences.rbegin(), m_aReferences.rend(),
187 [&rRef](const Reference<XReference>& rxRef) { return rxRef.get() == rRef.get(); });
188 if (it != m_aReferences.rend()) {
189 m_aReferences.erase( it.base()-1 );
190 return;
191 }
192 // interface not found, use the correct compare method
193 it = std::find(m_aReferences.rbegin(), m_aReferences.rend(), rRef);
194 if ( it != m_aReferences.rend() )
195 m_aReferences.erase( it.base()-1 );
196}
197
198
199//-- OWeakObject -------------------------------------------------------
200
201
202#ifdef _MSC_VER
203// Accidentally occurs in msvc mapfile = > had to be outlined.
204OWeakObject::OWeakObject()
205 : m_refCount( 0 ),
206 m_pWeakConnectionPoint( nullptr )
207{
208}
209#endif
210
211// XInterface
212Any SAL_CALL OWeakObject::queryInterface( const Type & rType )
213{
214 return ::cppu::queryInterface(
215 rType,
216 static_cast< XWeak * >( this ), static_cast< XInterface * >( this ) );
217}
218
219// XInterface
220void SAL_CALL OWeakObject::acquire() throw()
221{
222 osl_atomic_increment( &m_refCount )__sync_add_and_fetch((&m_refCount), 1);
223}
224
225// XInterface
226void SAL_CALL OWeakObject::release() throw()
227{
228 if (osl_atomic_decrement( &m_refCount )__sync_sub_and_fetch((&m_refCount), 1) == 0) {
229 // notify/clear all weak-refs before object's dtor is executed
230 // (which may check weak-refs to this object):
231 disposeWeakConnectionPoint();
232 // destroy object:
233 delete this;
234 }
235}
236
237void OWeakObject::disposeWeakConnectionPoint()
238{
239 OSL_PRECOND( m_refCount == 0, "OWeakObject::disposeWeakConnectionPoint: only to be called with a ref count of 0!" )do { if (true && (!(m_refCount == 0))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/cppuhelper/source/weak.cxx"
":" "239" ": "), "%s", "OWeakObject::disposeWeakConnectionPoint: only to be called with a ref count of 0!"
); } } while (false)
;
240 if (m_pWeakConnectionPoint != nullptr) {
241 OWeakConnectionPoint * const p = m_pWeakConnectionPoint;
242 m_pWeakConnectionPoint = nullptr;
243 try {
244 p->dispose();
245 }
246 catch (RuntimeException const& exc) {
247 SAL_WARN( "cppuhelper", exc )do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "cppuhelper")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << exc) == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_WARN), ("cppuhelper"), ("/home/maarten/src/libreoffice/core/cppuhelper/source/weak.cxx"
":" "247" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << exc), 0); } else { ::std::ostringstream
sal_detail_stream; sal_detail_stream << exc; ::sal::detail
::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("cppuhelper"), ("/home/maarten/src/libreoffice/core/cppuhelper/source/weak.cxx"
":" "247" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << exc) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("cppuhelper"), ("/home/maarten/src/libreoffice/core/cppuhelper/source/weak.cxx"
":" "247" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << exc), 0); } else { ::std::ostringstream
sal_detail_stream; sal_detail_stream << exc; ::sal::detail
::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("cppuhelper"), ("/home/maarten/src/libreoffice/core/cppuhelper/source/weak.cxx"
":" "247" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
248 }
249 p->release();
250 }
251}
252
253OWeakObject::~OWeakObject() COVERITY_NOEXCEPT_FALSE
254{
255}
256
257// XWeak
258Reference< XAdapter > SAL_CALL OWeakObject::queryAdapter()
259{
260 if (!m_pWeakConnectionPoint)
261 {
262 // only acquire mutex if member is not created
263 MutexGuard aGuard( getWeakMutex() );
264 if( !m_pWeakConnectionPoint )
265 {
266 OWeakConnectionPoint * p = new OWeakConnectionPoint(this);
267 p->acquire();
268 m_pWeakConnectionPoint = p;
269 }
270 }
271
272 return m_pWeakConnectionPoint;
273}
274
275
276//-- OWeakAggObject ----------------------------------------------------
277
278OWeakAggObject::~OWeakAggObject()
279{
280}
281
282// XInterface
283void OWeakAggObject::acquire() throw()
284{
285 Reference<XInterface > x( xDelegator );
286 if (x.is())
287 x->acquire();
288 else
289 OWeakObject::acquire();
290}
291
292// XInterface
293void OWeakAggObject::release() throw()
294{
295 Reference<XInterface > x( xDelegator );
296 if (x.is())
297 x->release();
298 else
299 OWeakObject::release();
300}
301
302// XInterface
303Any OWeakAggObject::queryInterface( const Type & rType )
304{
305 Reference< XInterface > x( xDelegator ); // harden ref
306 return (x.is() ? x->queryInterface( rType ) : queryAggregation( rType ));
307}
308
309// XAggregation
310Any OWeakAggObject::queryAggregation( const Type & rType )
311{
312 return ::cppu::queryInterface(
313 rType,
314 static_cast< XInterface * >( static_cast< OWeakObject * >( this ) ),
315 static_cast< XAggregation * >( this ),
316 static_cast< XWeak * >( this ) );
317}
318
319// XAggregation
320void OWeakAggObject::setDelegator( const Reference<XInterface > & rDelegator )
321{
322 xDelegator = rDelegator;
323}
324
325}
326
327/** */ //for docpp
328namespace com::sun::star::uno
329{
330
331
332//-- OWeakRefListener -----------------------------------------------------
333
334class OWeakRefListener final : public XReference
335{
336public:
337 explicit OWeakRefListener(const Reference< XInterface >& xInt);
338 virtual ~OWeakRefListener();
339
340 // noncopyable
341 OWeakRefListener(const OWeakRefListener&) = delete;
342 const OWeakRefListener& operator=(const OWeakRefListener&) = delete;
343
344 // XInterface
345 Any SAL_CALL queryInterface( const Type & rType ) override;
346 void SAL_CALL acquire() throw() override;
347 void SAL_CALL release() throw() override;
348
349 // XReference
350 void SAL_CALL dispose() override;
351
352 /// The reference counter.
353 oslInterlockedCount m_aRefCount;
354 /// The connection point of the weak object, guarded by getWeakMutex()
355 Reference< XAdapter > m_XWeakConnectionPoint;
356};
357
358OWeakRefListener::OWeakRefListener(const Reference< XInterface >& xInt)
359 : m_aRefCount( 1 )
360{
361 try
362 {
363 Reference< XWeak > xWeak( Reference< XWeak >::query( xInt ) );
364
365 if (xWeak.is())
366 {
367 m_XWeakConnectionPoint = xWeak->queryAdapter();
368
369 if (m_XWeakConnectionPoint.is())
370 {
371 m_XWeakConnectionPoint->addReference(static_cast<XReference*>(this));
372 }
373 }
374 }
375 catch (RuntimeException &) { OSL_ASSERT( false )do { if (true && (!(false))) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/cppuhelper/source/weak.cxx"
":" "375" ": "), "OSL_ASSERT: %s", "false"); } } while (false
)
; } // assert here, but no unexpected()
376 osl_atomic_decrement( &m_aRefCount )__sync_sub_and_fetch((&m_aRefCount), 1);
377}
378
379OWeakRefListener::~OWeakRefListener()
380{
381 try
382 {
383 if (m_XWeakConnectionPoint.is())
8
Taking true branch
384 {
385 acquire(); // don't die again
386 m_XWeakConnectionPoint->removeReference(static_cast<XReference*>(this));
9
Calling '~Reference'
16
Returning from '~Reference'
387 }
388 }
389 catch (RuntimeException &) { OSL_ASSERT( false )do { if (true && (!(false))) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/cppuhelper/source/weak.cxx"
":" "389" ": "), "OSL_ASSERT: %s", "false"); } } while (false
)
; } // assert here, but no unexpected()
390}
17
Calling '~Reference'
391
392// XInterface
393Any SAL_CALL OWeakRefListener::queryInterface( const Type & rType )
394{
395 return ::cppu::queryInterface(
396 rType, static_cast< XReference * >( this ), static_cast< XInterface * >( this ) );
397}
398
399// XInterface
400void SAL_CALL OWeakRefListener::acquire() throw()
401{
402 osl_atomic_increment( &m_aRefCount )__sync_add_and_fetch((&m_aRefCount), 1);
403}
404
405// XInterface
406void SAL_CALL OWeakRefListener::release() throw()
407{
408 if( ! osl_atomic_decrement( &m_aRefCount )__sync_sub_and_fetch((&m_aRefCount), 1) )
5
Assuming the condition is true
6
Taking true branch
12
Assuming the condition is true
13
Taking true branch
409 delete this;
7
Calling '~OWeakRefListener'
14
Memory is released
410}
411
412void SAL_CALL OWeakRefListener::dispose()
413{
414 Reference< XAdapter > xAdp;
415 {
416 MutexGuard guard(cppu::getWeakMutex());
417 if( m_XWeakConnectionPoint.is() )
418 {
419 xAdp = m_XWeakConnectionPoint;
420 m_XWeakConnectionPoint.clear();
421 }
422 }
423
424 if( xAdp.is() )
425 xAdp->removeReference(static_cast<XReference*>(this));
426}
427
428
429//-- WeakReferenceHelper ----------------------------------------------------------
430
431WeakReferenceHelper::WeakReferenceHelper(const Reference< XInterface >& xInt)
432 : m_pImpl( nullptr )
433{
434 if (xInt.is())
435 {
436 m_pImpl = new OWeakRefListener(xInt);
437 m_pImpl->acquire();
438 }
439}
440
441WeakReferenceHelper::WeakReferenceHelper(const WeakReferenceHelper& rWeakRef)
442 : m_pImpl( nullptr )
443{
444 Reference< XInterface > xInt( rWeakRef.get() );
445 if (xInt.is())
446 {
447 m_pImpl = new OWeakRefListener(xInt);
448 m_pImpl->acquire();
449 }
450}
451
452void WeakReferenceHelper::clear()
453{
454 try
455 {
456 if (m_pImpl)
2
Assuming field 'm_pImpl' is non-null
3
Taking true branch
457 {
458 m_pImpl->dispose();
459 m_pImpl->release();
4
Calling 'OWeakRefListener::release'
460 m_pImpl = nullptr;
461 }
462 }
463 catch (RuntimeException &) { OSL_ASSERT( false )do { if (true && (!(false))) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/cppuhelper/source/weak.cxx"
":" "463" ": "), "OSL_ASSERT: %s", "false"); } } while (false
)
; } // assert here, but no unexpected()
464}
465
466WeakReferenceHelper& WeakReferenceHelper::operator=(const WeakReferenceHelper& rWeakRef)
467{
468 if (this == &rWeakRef)
469 {
470 return *this;
471 }
472 Reference< XInterface > xInt( rWeakRef.get() );
473 return operator = ( xInt );
474}
475
476WeakReferenceHelper & WeakReferenceHelper::operator =(
477 WeakReferenceHelper && other)
478{
479 clear();
480 std::swap(m_pImpl, other.m_pImpl);
481 return *this;
482}
483
484WeakReferenceHelper & SAL_CALL
485WeakReferenceHelper::operator= (const Reference< XInterface > & xInt)
486{
487 try
488 {
489 clear();
490 if (xInt.is())
491 {
492 m_pImpl = new OWeakRefListener(xInt);
493 m_pImpl->acquire();
494 }
495 }
496 catch (RuntimeException &) { OSL_ASSERT( false )do { if (true && (!(false))) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/cppuhelper/source/weak.cxx"
":" "496" ": "), "OSL_ASSERT: %s", "false"); } } while (false
)
; } // assert here, but no unexpected()
497 return *this;
498}
499
500WeakReferenceHelper::~WeakReferenceHelper()
501{
502 clear();
1
Calling 'WeakReferenceHelper::clear'
503}
504
505Reference< XInterface > WeakReferenceHelper::get() const
506{
507 try
508 {
509 Reference< XAdapter > xAdp;
510 {
511 // must lock to access m_XWeakConnectionPoint
512 MutexGuard guard(cppu::getWeakMutex());
513 if( m_pImpl && m_pImpl->m_XWeakConnectionPoint.is() )
514 xAdp = m_pImpl->m_XWeakConnectionPoint;
515 }
516
517 if (xAdp.is())
518 return xAdp->queryAdapted();
519 }
520 catch (RuntimeException &)
521 {
522 OSL_ASSERT( false )do { if (true && (!(false))) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/cppuhelper/source/weak.cxx"
":" "522" ": "), "OSL_ASSERT: %s", "false"); } } while (false
)
;
523 } // assert here, but no unexpected()
524
525 return Reference< XInterface >();
526}
527
528}
529
530/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

/home/maarten/src/libreoffice/core/include/com/sun/star/uno/Reference.hxx

1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19#ifndef INCLUDED_COM_SUN_STAR_UNO_REFERENCE_HXX
20#define INCLUDED_COM_SUN_STAR_UNO_REFERENCE_HXX
21
22#include "sal/config.h"
23
24#include <cstddef>
25#include <ostream>
26
27#include "com/sun/star/uno/Reference.h"
28#include "com/sun/star/uno/RuntimeException.hpp"
29#include "com/sun/star/uno/XInterface.hpp"
30#include "com/sun/star/uno/Any.hxx"
31#include "cppu/cppudllapi.h"
32
33extern "C" CPPU_DLLPUBLIC__attribute__ ((visibility("default"))) rtl_uString * SAL_CALL cppu_unsatisfied_iquery_msg(
34 typelib_TypeDescriptionReference * pType )
35 SAL_THROW_EXTERN_C()throw ();
36extern "C" CPPU_DLLPUBLIC__attribute__ ((visibility("default"))) rtl_uString * SAL_CALL cppu_unsatisfied_iset_msg(
37 typelib_TypeDescriptionReference * pType )
38 SAL_THROW_EXTERN_C()throw ();
39
40namespace com
41{
42namespace sun
43{
44namespace star
45{
46namespace uno
47{
48
49
50inline XInterface * BaseReference::iquery(
51 XInterface * pInterface, const Type & rType )
52{
53 if (pInterface)
54 {
55 Any aRet( pInterface->queryInterface( rType ) );
56 if (typelib_TypeClass_INTERFACE == aRet.pType->eTypeClass)
57 {
58 XInterface * pRet = static_cast< XInterface * >( aRet.pReserved );
59 aRet.pReserved = NULL__null;
60 return pRet;
61 }
62 }
63 return NULL__null;
64}
65
66template< class interface_type >
67inline XInterface * Reference< interface_type >::iquery(
68 XInterface * pInterface )
69{
70 return BaseReference::iquery(pInterface, interface_type::static_type());
71}
72
73inline XInterface * BaseReference::iquery_throw(
74 XInterface * pInterface, const Type & rType )
75{
76 XInterface * pQueried = iquery( pInterface, rType );
77 if (pQueried)
78 return pQueried;
79 throw RuntimeException(
80 ::rtl::OUString( cppu_unsatisfied_iquery_msg( rType.getTypeLibType() ), SAL_NO_ACQUIRE ),
81 Reference< XInterface >( pInterface ) );
82}
83
84template< class interface_type >
85inline XInterface * Reference< interface_type >::iquery_throw(
86 XInterface * pInterface )
87{
88 return BaseReference::iquery_throw(
89 pInterface, interface_type::static_type());
90}
91
92template< class interface_type >
93inline interface_type * Reference< interface_type >::iset_throw(
94 interface_type * pInterface )
95{
96 if (pInterface)
97 {
98 castToXInterface(pInterface)->acquire();
99 return pInterface;
100 }
101 throw RuntimeException(
102 ::rtl::OUString( cppu_unsatisfied_iset_msg( interface_type::static_type().getTypeLibType() ), SAL_NO_ACQUIRE ),
103 NULL__null );
104}
105
106template< class interface_type >
107inline Reference< interface_type >::~Reference() COVERITY_NOEXCEPT_FALSE
108{
109 if (_pInterface
9.1
Field '_pInterface' is non-null
9.1
Field '_pInterface' is non-null
)
10
Taking true branch
18
Use of memory after it is freed
110 _pInterface->release();
11
Calling 'OWeakRefListener::release'
15
Returning; memory was released
111}
112
113template< class interface_type >
114inline Reference< interface_type >::Reference()
115{
116 _pInterface = NULL__null;
117}
118
119template< class interface_type >
120inline Reference< interface_type >::Reference( const Reference< interface_type > & rRef )
121{
122 _pInterface = rRef._pInterface;
123 if (_pInterface)
124 _pInterface->acquire();
125}
126
127#if defined LIBO_INTERNAL_ONLY1
128template< class interface_type >
129inline Reference< interface_type >::Reference( Reference< interface_type > && rRef ) noexcept
130{
131 _pInterface = rRef._pInterface;
132 rRef._pInterface = nullptr;
133}
134
135template< class interface_type > template< class derived_type >
136inline Reference< interface_type >::Reference(
137 const Reference< derived_type > & rRef,
138 std::enable_if_t<
139 std::is_base_of_v<interface_type, derived_type>
140 && !std::is_same_v<interface_type, XInterface>, void *>)
141{
142 interface_type * p = rRef.get();
143 _pInterface = p;
144 if (_pInterface)
145 _pInterface->acquire();
146}
147#endif
148
149template< class interface_type >
150inline Reference< interface_type >::Reference( interface_type * pInterface )
151{
152 _pInterface = castToXInterface(pInterface);
153 if (_pInterface)
154 _pInterface->acquire();
155}
156
157template< class interface_type >
158inline Reference< interface_type >::Reference( interface_type * pInterface, __sal_NoAcquire )
159{
160 _pInterface = castToXInterface(pInterface);
161}
162
163template< class interface_type >
164inline Reference< interface_type >::Reference( interface_type * pInterface, UnoReference_NoAcquire )
165{
166 _pInterface = castToXInterface(pInterface);
167}
168
169template< class interface_type >
170inline Reference< interface_type >::Reference( const BaseReference & rRef, UnoReference_Query )
171{
172 _pInterface = iquery( rRef.get() );
173}
174
175template< class interface_type >
176inline Reference< interface_type >::Reference( XInterface * pInterface, UnoReference_Query )
177{
178 _pInterface = iquery( pInterface );
179}
180
181template< class interface_type >
182inline Reference< interface_type >::Reference( const Any & rAny, UnoReference_Query )
183{
184 _pInterface = (typelib_TypeClass_INTERFACE == rAny.pType->eTypeClass
185 ? iquery( static_cast< XInterface * >( rAny.pReserved ) ) : NULL__null);
186}
187
188template< class interface_type >
189inline Reference< interface_type >::Reference( const BaseReference & rRef, UnoReference_QueryThrow )
190{
191 _pInterface = iquery_throw( rRef.get() );
192}
193
194template< class interface_type >
195inline Reference< interface_type >::Reference( XInterface * pInterface, UnoReference_QueryThrow )
196{
197 _pInterface = iquery_throw( pInterface );
198}
199
200template< class interface_type >
201inline Reference< interface_type >::Reference( const Any & rAny, UnoReference_QueryThrow )
202{
203 _pInterface = iquery_throw( typelib_TypeClass_INTERFACE == rAny.pType->eTypeClass
204 ? static_cast< XInterface * >( rAny.pReserved ) : NULL__null );
205}
206
207template< class interface_type >
208inline Reference< interface_type >::Reference( const Reference< interface_type > & rRef, UnoReference_SetThrow )
209{
210 _pInterface = castToXInterface( iset_throw( rRef.get() ) );
211}
212
213template< class interface_type >
214inline Reference< interface_type >::Reference( interface_type * pInterface, UnoReference_SetThrow )
215{
216 _pInterface = castToXInterface( iset_throw( pInterface ) );
217}
218
219
220template< class interface_type >
221inline void Reference< interface_type >::clear()
222{
223 if (_pInterface)
224 {
225 XInterface * const pOld = _pInterface;
226 _pInterface = NULL__null;
227 pOld->release();
228 }
229}
230
231template< class interface_type >
232inline bool Reference< interface_type >::set(
233 interface_type * pInterface )
234{
235 if (pInterface)
236 castToXInterface(pInterface)->acquire();
237 XInterface * const pOld = _pInterface;
238 _pInterface = castToXInterface(pInterface);
239 if (pOld)
240 pOld->release();
241 return (NULL__null != pInterface);
242}
243
244template< class interface_type >
245inline bool Reference< interface_type >::set(
246 interface_type * pInterface, __sal_NoAcquire )
247{
248 XInterface * const pOld = _pInterface;
249 _pInterface = castToXInterface(pInterface);
250 if (pOld)
251 pOld->release();
252 return (NULL__null != pInterface);
253}
254
255template< class interface_type >
256inline bool Reference< interface_type >::set(
257 interface_type * pInterface, UnoReference_NoAcquire )
258{
259 return set( pInterface, SAL_NO_ACQUIRE );
260}
261
262
263template< class interface_type >
264inline bool Reference< interface_type >::set(
265 const Reference< interface_type > & rRef )
266{
267 return set( castFromXInterface( rRef._pInterface ) );
268}
269
270template< class interface_type >
271inline bool Reference< interface_type >::set(
272 XInterface * pInterface, UnoReference_Query )
273{
274 return set( castFromXInterface(iquery( pInterface )), SAL_NO_ACQUIRE );
275}
276
277template< class interface_type >
278inline bool Reference< interface_type >::set(
279 const BaseReference & rRef, UnoReference_Query )
280{
281 return set( castFromXInterface(iquery( rRef.get() )), SAL_NO_ACQUIRE );
282}
283
284
285template< class interface_type >
286inline bool Reference< interface_type >::set(
287 Any const & rAny, UnoReference_Query )
288{
289 return set(
290 castFromXInterface(
291 iquery(
292 rAny.pType->eTypeClass == typelib_TypeClass_INTERFACE
293 ? static_cast< XInterface * >( rAny.pReserved ) : NULL__null )),
294 SAL_NO_ACQUIRE );
295}
296
297
298template< class interface_type >
299inline void Reference< interface_type >::set(
300 XInterface * pInterface, UnoReference_QueryThrow )
301{
302 set( castFromXInterface(iquery_throw( pInterface )), SAL_NO_ACQUIRE );
303}
304
305template< class interface_type >
306inline void Reference< interface_type >::set(
307 const BaseReference & rRef, UnoReference_QueryThrow )
308{
309 set( castFromXInterface(iquery_throw( rRef.get() )), SAL_NO_ACQUIRE );
310}
311
312
313template< class interface_type >
314inline void Reference< interface_type >::set(
315 Any const & rAny, UnoReference_QueryThrow )
316{
317 set( castFromXInterface(
318 iquery_throw(
319 rAny.pType->eTypeClass == typelib_TypeClass_INTERFACE
320 ? static_cast< XInterface * >( rAny.pReserved ) : NULL__null )),
321 SAL_NO_ACQUIRE );
322}
323
324template< class interface_type >
325inline void Reference< interface_type >::set(
326 interface_type * pInterface, UnoReference_SetThrow )
327{
328 set( iset_throw( pInterface ), SAL_NO_ACQUIRE );
329}
330
331template< class interface_type >
332inline void Reference< interface_type >::set(
333 const Reference< interface_type > & rRef, UnoReference_SetThrow )
334{
335 set( rRef.get(), UNO_SET_THROW );
336}
337
338
339template< class interface_type >
340inline Reference< interface_type > & Reference< interface_type >::operator = (
341 interface_type * pInterface )
342{
343 set( pInterface );
344 return *this;
345}
346
347template< class interface_type >
348inline Reference< interface_type > & Reference< interface_type >::operator = (
349 const Reference< interface_type > & rRef )
350{
351 set( castFromXInterface( rRef._pInterface ) );
352 return *this;
353}
354
355#if defined LIBO_INTERNAL_ONLY1
356template< class interface_type >
357inline Reference< interface_type > & Reference< interface_type >::operator = (
358 Reference< interface_type > && rRef ) noexcept
359{
360 if (_pInterface)
361 _pInterface->release();
362 _pInterface = rRef._pInterface;
363 rRef._pInterface = nullptr;
364 return *this;
365}
366#endif
367
368template< class interface_type >
369inline Reference< interface_type > Reference< interface_type >::query(
370 const BaseReference & rRef )
371{
372 return Reference< interface_type >(
373 castFromXInterface(iquery( rRef.get() )), SAL_NO_ACQUIRE );
374}
375
376template< class interface_type >
377inline Reference< interface_type > Reference< interface_type >::query(
378 XInterface * pInterface )
379{
380 return Reference< interface_type >(
381 castFromXInterface(iquery( pInterface )), SAL_NO_ACQUIRE );
382}
383
384
385inline bool BaseReference::operator == ( XInterface * pInterface ) const
386{
387 if (_pInterface == pInterface)
388 return true;
389 try
390 {
391 // only the query to XInterface must return the same pointer if they belong to same objects
392 Reference< XInterface > x1( _pInterface, UNO_QUERY );
393 Reference< XInterface > x2( pInterface, UNO_QUERY );
394 return (x1._pInterface == x2._pInterface);
395 }
396 catch (RuntimeException &)
397 {
398 return false;
399 }
400}
401
402
403inline bool BaseReference::operator < (
404 const BaseReference & rRef ) const
405{
406 if (_pInterface == rRef._pInterface)
407 return false;
408 try
409 {
410 // only the query to XInterface must return the same pointer:
411 Reference< XInterface > x1( _pInterface, UNO_QUERY );
412 Reference< XInterface > x2( rRef, UNO_QUERY );
413 return (x1._pInterface < x2._pInterface);
414 }
415 catch (RuntimeException &)
416 {
417 return false;
418 }
419}
420
421
422inline bool BaseReference::operator != ( XInterface * pInterface ) const
423{
424 return (! operator == ( pInterface ));
425}
426
427inline bool BaseReference::operator == ( const BaseReference & rRef ) const
428{
429 return operator == ( rRef._pInterface );
430}
431
432inline bool BaseReference::operator != ( const BaseReference & rRef ) const
433{
434 return (! operator == ( rRef._pInterface ));
435}
436
437#if defined LIBO_INTERNAL_ONLY1
438/**
439 Support for BaseReference in std::ostream (and thus in CPPUNIT_ASSERT or
440 SAL_INFO macros, for example).
441
442 @since LibreOffice 5.4
443*/
444template<typename charT, typename traits> std::basic_ostream<charT, traits> &
445operator <<(
446 std::basic_ostream<charT, traits> & stream, BaseReference const & ref)
447{ return stream << ref.get(); }
448#endif
449
450}
451}
452}
453}
454
455#if defined LIBO_INTERNAL_ONLY1
456namespace std
457{
458
459/**
460 Make css::uno::Reference hashable by default for use in STL containers.
461
462 @since LibreOffice 6.3
463*/
464template<typename T>
465struct hash<::css::uno::Reference<T>>
466{
467 std::size_t operator()(::css::uno::Reference<T> const & s) const
468 { return size_t(s.get()); }
469};
470
471}
472
473#endif
474
475#endif
476
477/* vim:set shiftwidth=4 softtabstop=4 expandtab: */