Bug Summary

File:home/maarten/src/libreoffice/core/sw/source/uibase/app/swdll.cxx
Warning:line 106, column 9
Called C++ object pointer is null

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 swdll.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 -isystem /usr/include/libxml2 -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 SW_DLLIMPLEMENTATION -D SWUI_DLL_NAME="libswuilo.so" -D SYSTEM_LIBXML -D EXCEPTIONS_ON -D LIBO_INTERNAL_ONLY -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/icu/source -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/icu/source/i18n -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/icu/source/common -I /home/maarten/src/libreoffice/core/external/boost/include -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/boost -I /home/maarten/src/libreoffice/core/sw/source/core/inc -I /home/maarten/src/libreoffice/core/sw/source/filter/inc -I /home/maarten/src/libreoffice/core/sw/source/uibase/inc -I /home/maarten/src/libreoffice/core/sw/inc -I /home/maarten/src/libreoffice/core/workdir/SdiTarget/sw/sdi -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/CustomTarget/officecfg/registry -I /home/maarten/src/libreoffice/core/workdir/CustomTarget/sw/generated -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/udkapi/normal -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/offapi/normal -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/oovbaapi/normal -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/sw/source/uibase/app/swdll.cxx

/home/maarten/src/libreoffice/core/sw/source/uibase/app/swdll.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 <memory>
21
22#include <svx/svdobj.hxx>
23
24#include <swdll.hxx>
25#include <wdocsh.hxx>
26#include <globdoc.hxx>
27#include <initui.hxx>
28#include <swmodule.hxx>
29#include <init.hxx>
30#include <dobjfac.hxx>
31
32#include <com/sun/star/frame/Desktop.hpp>
33#include <unotools/configmgr.hxx>
34#include <unotools/moduleoptions.hxx>
35#include <comphelper/unique_disposing_ptr.hxx>
36#include <comphelper/processfactory.hxx>
37
38#include <sal/log.hxx>
39#include <svx/fmobjfac.hxx>
40#include <svx/objfac3d.hxx>
41#include <editeng/acorrcfg.hxx>
42
43#include <swacorr.hxx>
44#include <swabstdlg.hxx>
45
46#include "swdllimpl.hxx"
47
48using namespace com::sun::star;
49
50namespace
51{
52 //Holds a SwDLL and release it on exit, or dispose of the
53 //default XComponent, whichever comes first
54 class SwDLLInstance : public comphelper::unique_disposing_solar_mutex_reset_ptr<SwDLL>
55 {
56 public:
57 SwDLLInstance() : comphelper::unique_disposing_solar_mutex_reset_ptr<SwDLL>(uno::Reference<lang::XComponent>( frame::Desktop::create(comphelper::getProcessComponentContext()), uno::UNO_QUERY_THROW), new SwDLL, true)
3
Calling default constructor for 'SwDLL'
58 {
59 }
60 };
61
62 struct theSwDLLInstance : public rtl::Static<SwDLLInstance, theSwDLLInstance> {};
63}
64
65namespace SwGlobals
66{
67 void ensure()
68 {
69 // coverity[side_effect_free : FALSE] - not actually side-effect-free
70 theSwDLLInstance::get();
71 }
72
73 sw::Filters & getFilters()
74 {
75 return theSwDLLInstance::get()->getFilters();
1
Calling 'Static::get'
76 }
77}
78
79SwDLL::SwDLL()
80 : m_pAutoCorrCfg(nullptr)
81{
82 if ( SfxApplication::GetModule(SfxToolsModule::Writer) ) // Module already active
4
Assuming the condition is false
5
Taking false branch
83 return;
84
85 std::unique_ptr<SvtModuleOptions> xOpt;
86 if (!utl::ConfigManager::IsFuzzing())
6
Assuming the condition is true
7
Taking true branch
87 xOpt.reset(new SvtModuleOptions);
88 SfxObjectFactory* pDocFact = nullptr;
89 SfxObjectFactory* pGlobDocFact = nullptr;
8
'pGlobDocFact' initialized to a null pointer value
90 if (!xOpt || xOpt->IsWriter())
9
Assuming the condition is false
10
Taking false branch
91 {
92 pDocFact = &SwDocShell::Factory();
93 pGlobDocFact = &SwGlobalDocShell::Factory();
94 }
95
96 SfxObjectFactory* pWDocFact = &SwWebDocShell::Factory();
97
98 auto pUniqueModule = std::make_unique<SwModule>(pWDocFact, pDocFact, pGlobDocFact);
11
Calling 'make_unique<SwModule, SfxObjectFactory *&, SfxObjectFactory *&, SfxObjectFactory *&>'
14
Returning from 'make_unique<SwModule, SfxObjectFactory *&, SfxObjectFactory *&, SfxObjectFactory *&>'
99 SwModule* pModule = pUniqueModule.get();
100 SfxApplication::SetModule(SfxToolsModule::Writer, std::move(pUniqueModule));
101
102 pWDocFact->SetDocumentServiceName("com.sun.star.text.WebDocument");
103
104 if (!xOpt || xOpt->IsWriter())
15
Calling 'unique_ptr::operator bool'
18
Returning from 'unique_ptr::operator bool'
19
Assuming the condition is true
20
Taking true branch
105 {
106 pGlobDocFact->SetDocumentServiceName("com.sun.star.text.GlobalDocument");
21
Called C++ object pointer is null
107 pDocFact->SetDocumentServiceName("com.sun.star.text.TextDocument");
108 }
109
110 // register 3D-object-Factory
111 E3dObjFactory();
112
113 // register form::component::Form-object-Factory
114 FmFormObjFactory();
115
116 SdrObjFactory::InsertMakeObjectHdl( LINK( &aSwObjectFactory, SwObjectFactory, MakeObject )::tools::detail::makeLink( ::tools::detail::castTo<SwObjectFactory
*>(&aSwObjectFactory), &SwObjectFactory::LinkStubMakeObject
)
);
117
118 SAL_INFO( "sw.ui", "Init Core/UI/Filter" )do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO
, "sw.ui")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case SAL_DETAIL_LOG_ACTION_LOG
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "Init Core/UI/Filter") == 1) { ::sal_detail_log( (
::SAL_DETAIL_LOG_LEVEL_INFO), ("sw.ui"), ("/home/maarten/src/libreoffice/core/sw/source/uibase/app/swdll.cxx"
":" "118" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "Init Core/UI/Filter"), 0); } else { ::
std::ostringstream sal_detail_stream; sal_detail_stream <<
"Init Core/UI/Filter"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("sw.ui"), ("/home/maarten/src/libreoffice/core/sw/source/uibase/app/swdll.cxx"
":" "118" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "Init Core/UI/Filter") == 1) { ::sal_detail_log( (
::SAL_DETAIL_LOG_LEVEL_INFO), ("sw.ui"), ("/home/maarten/src/libreoffice/core/sw/source/uibase/app/swdll.cxx"
":" "118" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "Init Core/UI/Filter"), 0); } else { ::
std::ostringstream sal_detail_stream; sal_detail_stream <<
"Init Core/UI/Filter"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("sw.ui"), ("/home/maarten/src/libreoffice/core/sw/source/uibase/app/swdll.cxx"
":" "118" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
119 // Initialisation of Statics
120 ::InitCore();
121 filters_.reset(new sw::Filters);
122 ::InitUI();
123
124 pModule->InitAttrPool();
125 // now SWModule can create its Pool
126
127 // register your view-factories here
128 RegisterFactories();
129
130 // register your shell-interfaces here
131 RegisterInterfaces();
132
133 // register your controllers here
134 RegisterControls();
135
136 if (!utl::ConfigManager::IsFuzzing())
137 {
138 // replace SvxAutocorrect with SwAutocorrect
139 SvxAutoCorrCfg& rACfg = SvxAutoCorrCfg::Get();
140 const SvxAutoCorrect* pOld = rACfg.GetAutoCorrect();
141 rACfg.SetAutoCorrect(new SwAutoCorrect( *pOld ));
142 m_pAutoCorrCfg = &rACfg;
143 }
144}
145
146SwDLL::~SwDLL() COVERITY_NOEXCEPT_FALSE
147{
148 if (m_pAutoCorrCfg)
149 {
150 // fdo#86494 SwAutoCorrect must be deleted before FinitCore
151 m_pAutoCorrCfg->SetAutoCorrect(nullptr); // delete SwAutoCorrect before exit handlers
152 }
153
154 // Pool has to be deleted before statics are
155 SW_MOD()( static_cast<SwModule*>(SfxApplication::GetModule(SfxToolsModule
::Writer)))
->RemoveAttrPool();
156
157 ::FinitUI();
158 filters_.reset();
159 ::FinitCore();
160 // sign out object-Factory
161 SdrObjFactory::RemoveMakeObjectHdl(LINK(&aSwObjectFactory, SwObjectFactory, MakeObject )::tools::detail::makeLink( ::tools::detail::castTo<SwObjectFactory
*>(&aSwObjectFactory), &SwObjectFactory::LinkStubMakeObject
)
);
162}
163
164sw::Filters & SwDLL::getFilters()
165{
166 assert(filters_)(static_cast <bool> (filters_) ? void (0) : __assert_fail
("filters_", "/home/maarten/src/libreoffice/core/sw/source/uibase/app/swdll.cxx"
, 166, __extension__ __PRETTY_FUNCTION__))
;
167 return *filters_;
168}
169
170#ifndef DISABLE_DYNLOADING
171
172extern "C" SAL_DLLPUBLIC_EXPORT__attribute__ ((visibility("default")))
173void lok_preload_hook()
174{
175 SwAbstractDialogFactory::Create();
176}
177
178#endif
179
180/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

/home/maarten/src/libreoffice/core/include/rtl/instance.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
20#ifndef INCLUDED_RTL_INSTANCE_HXX
21#define INCLUDED_RTL_INSTANCE_HXX
22
23#include "sal/config.h"
24
25#include <cstddef>
26
27#include "osl/doublecheckedlocking.h"
28#include "osl/getglobalmutex.hxx"
29
30namespace {
31
32/** A non-broken version of the double-checked locking pattern.
33
34 See
35 <http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html>
36 for a description of double-checked locking, why it is broken, and how it
37 can be fixed. Always use this template instead of spelling out the
38 double-checked locking pattern explicitly, and only in those rare cases
39 where that is not possible and you have to spell it out explicitly, at
40 least call OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER() at the right
41 places. That way, all platform-dependent code to make double-checked
42 locking work can be kept in one place.
43
44 Usage scenarios:
45
46 1 Static instance (most common case)
47
48 Pattern:
49
50 T * getInstance()
51 {
52 static T * pInstance = 0;
53 if (!pInstance)
54 {
55 ::osl::MutexGuard aGuard(::osl::Mutex::getGlobalMutex());
56 if (!pInstance)
57 {
58 static T aInstance;
59 pInstance = &aInstance;
60 }
61 }
62 return pInstance;
63 }
64
65 Code:
66
67 #include <rtl/instance.hxx>
68 #include <osl/getglobalmutex.hxx>
69
70 namespace {
71 struct Init
72 {
73 T * operator()()
74 {
75 static T aInstance;
76 return &aInstance;
77 }
78 };
79 }
80
81 T * getInstance()
82 {
83 return rtl_Instance< T, Init, ::osl::MutexGuard,
84 ::osl::GetGlobalMutex >::create(
85 Init(), ::osl::GetGlobalMutex());
86 }
87
88 2 Dynamic instance
89
90 Pattern:
91
92 T * getInstance()
93 {
94 static T * pInstance = 0;
95 if (!pInstance)
96 {
97 ::osl::MutexGuard aGuard(::osl::Mutex::getGlobalMutex());
98 if (!pInstance)
99 pInstance = new T;
100 }
101 return pInstance;
102 }
103
104 Code:
105
106 #include <rtl/instance.hxx>
107 #include <osl/getglobalmutex.hxx>
108
109 namespace {
110 struct Init
111 {
112 T * operator()()
113 {
114 return new T;
115 }
116 };
117 }
118
119 T * getInstance()
120 {
121 return rtl_Instance< T, Init, ::osl::MutexGuard,
122 ::osl::GetGlobalMutex >::create(
123 Init(), ::osl::GetGlobalMutex());
124 }
125
126 3 Other guard/mutex
127
128 Pattern:
129
130 T * getInstance()
131 {
132 static T * pInstance = 0;
133 if (!pInstance)
134 {
135 SomeGuard aGuard(pSomeMutex);
136 if (!pInstance)
137 {
138 static T aInstance;
139 pInstance = &aInstance;
140 }
141 }
142 return pInstance;
143 }
144
145 Code:
146
147 #include <rtl/instance.hxx>
148
149 namespace {
150 struct InitInstance
151 {
152 T * operator()()
153 {
154 static T aInstance;
155 return &aInstance;
156 }
157 };
158
159 struct InitGuard
160 {
161 SomeMutex * operator()()
162 {
163 return pSomeMutex;
164 }
165 };
166 }
167
168 T * getInstance()
169 {
170 return rtl_Instance< T, InitInstance,
171 SomeGuard, InitGuard >::create(
172 InitInstance(), InitMutex());
173 }
174
175 4 Calculate extra data
176
177 Pattern:
178
179 T * getInstance()
180 {
181 static T * pInstance = 0;
182 if (!pInstance)
183 {
184 Data aData(...);
185 ::osl::MutexGuard aGuard(::osl::Mutex::getGlobalMutex());
186 if (!pInstance)
187 {
188 static T aInstance(aData);
189 pInstance = &aInstance;
190 }
191 }
192 return pInstance;
193 }
194
195 Code:
196
197 #include <rtl/instance.hxx>
198 #include <osl/getglobalmutex.hxx>
199
200 namespace {
201 struct InitInstance
202 {
203 T * operator()()
204 {
205 static T aInstance;
206 return &aInstance;
207 }
208 }
209
210 struct InitData
211 {
212 Data const & operator()()
213 {
214 return ...;
215 }
216 }
217 }
218
219 T * getInstance()
220 {
221 return rtl_Instance< T, InitInstance,
222 ::osl::MutexGuard, ::osl::GetGlobalMutex,
223 Data, InitData >::create(
224 InitInstance(), ::osl::GetGlobalMutex(), InitData());
225 }
226
227 Some comments:
228
229 For any instantiation of rtl_Instance, at most one call to a create method
230 may occur in the program code: Each occurrence of a create method within
231 the program code is supposed to return a fresh object instance on the
232 first call, and that same object instance on subsequent calls; but
233 independent occurrences of create methods are supposed to return
234 independent object instances. Since there is a one-to-one correspondence
235 between object instances and instantiations of rtl_Instance, the
236 requirement should be clear. One measure to enforce the requirement is
237 that rtl_Instance lives in an unnamed namespace, so that instantiations of
238 rtl_Instance in different translation units will definitely be different
239 instantiations. A drawback of that measure is that the name of the class
240 needs a funny "hand coded" prefix "rtl_" instead of a proper namespace
241 prefix like "::rtl::".
242
243 A known problem with this template is when two occurrences of calls to
244 create methods with identical template arguments appear in one translation
245 unit. Those two places will share a single object instance. This can be
246 avoided by using different Init structs (see the above code samples) in
247 the two places.
248
249 There is no need to make m_pInstance volatile, in order to avoid usage of
250 stale copies of m_pInstance: At the first check, a thread will see that
251 m_pInstance contains either 0 or a valid pointer. If it contains a valid
252 pointer, it cannot be stale, and that pointer is used. If it contains 0,
253 acquiring the mutex will ensure that the second check sees a non-stale
254 value in all cases.
255
256 On some compilers, the create methods would not be inlined if they
257 contained any static variables, so m_pInstance is made a class member
258 instead (and the create methods are inlined). But on MSC, the definition
259 of the class member m_pInstance would cause compilation to fail with an
260 internal compiler error. Since MSC is able to inline methods containing
261 static variables, m_pInstance is moved into the methods there. Note that
262 this only works well because for any instantiation of rtl_Instance at most
263 one call to a create method should be present, anyway.
264 */
265template< typename Inst, typename InstCtor,
266 typename Guard, typename GuardCtor,
267 typename Data = int, typename DataCtor = int >
268class rtl_Instance
269{
270public:
271 static Inst * create(InstCtor aInstCtor, GuardCtor aGuardCtor)
272 {
273#if defined _MSC_VER
274 static Inst * m_pInstance = 0;
275#endif // _MSC_VER
276 Inst * p = m_pInstance;
277 if (!p)
278 {
279 Guard aGuard(aGuardCtor());
280 p = m_pInstance;
281 if (!p)
282 {
283 p = aInstCtor();
284 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
285 m_pInstance = p;
286 }
287 }
288 else
289 {
290 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
291 }
292 return p;
293 }
294
295 static Inst * create(InstCtor aInstCtor, GuardCtor aGuardCtor,
296 DataCtor aDataCtor)
297 {
298#if defined _MSC_VER
299 static Inst * m_pInstance = 0;
300#endif // _MSC_VER
301 Inst * p = m_pInstance;
302 if (!p)
303 {
304 Data aData(aDataCtor());
305 Guard aGuard(aGuardCtor());
306 p = m_pInstance;
307 if (!p)
308 {
309 p = aInstCtor(aData);
310 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
311 m_pInstance = p;
312 }
313 }
314 else
315 {
316 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
317 }
318 return p;
319 }
320
321 static Inst * create(InstCtor aInstCtor, GuardCtor aGuardCtor,
322 const Data &rData)
323 {
324#if defined _MSC_VER
325 static Inst * m_pInstance = 0;
326#endif // _MSC_VER
327 Inst * p = m_pInstance;
328 if (!p)
329 {
330 Guard aGuard(aGuardCtor());
331 p = m_pInstance;
332 if (!p)
333 {
334 p = aInstCtor(rData);
335 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
336 m_pInstance = p;
337 }
338 }
339 else
340 {
341 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
342 }
343 return p;
344 }
345
346private:
347#if !defined _MSC_VER
348 static Inst * m_pInstance;
349#endif // _MSC_VER
350};
351
352#if !defined _MSC_VER
353template< typename Inst, typename InstCtor,
354 typename Guard, typename GuardCtor,
355 typename Data, typename DataCtor >
356Inst *
357rtl_Instance< Inst, InstCtor, Guard, GuardCtor, Data, DataCtor >::m_pInstance
358= NULL__null;
359#endif // _MSC_VER
360
361}
362
363namespace rtl {
364
365/** Helper base class for a late-initialized (default-constructed)
366 static variable, implementing the double-checked locking pattern correctly.
367
368 @derive
369 Derive from this class (common practice), e.g.
370 <pre>
371 struct MyStatic : public rtl::Static<MyType, MyStatic> {};
372 ...
373 MyType & rStatic = MyStatic::get();
374 ...
375 </pre>
376
377 @tparam T
378 variable's type
379 @tparam Unique
380 Implementation trick to make the inner static holder unique,
381 using the outer class
382 (the one that derives from this base class)
383*/
384#if defined LIBO_INTERNAL_ONLY1
385template<typename T, typename Unique>
386class Static {
387public:
388 /** Gets the static. Mutual exclusion is implied by a functional
389 -fthreadsafe-statics
390
391 @return
392 static variable
393 */
394 static T & get() {
395 static T instance;
2
Calling default constructor for 'SwDLLInstance'
396 return instance;
397 }
398};
399#else
400template<typename T, typename Unique>
401class Static {
402public:
403 /** Gets the static. Mutual exclusion is performed using the
404 osl global mutex.
405
406 @return
407 static variable
408 */
409 static T & get() {
410 return *rtl_Instance<
411 T, StaticInstance,
412 ::osl::MutexGuard, ::osl::GetGlobalMutex >::create(
413 StaticInstance(), ::osl::GetGlobalMutex() );
414 }
415private:
416 struct StaticInstance {
417 T * operator () () {
418 static T instance;
419 return &instance;
420 }
421 };
422};
423#endif
424
425/** Helper base class for a late-initialized (default-constructed)
426 static variable, implementing the double-checked locking pattern correctly.
427
428 @derive
429 Derive from this class (common practice), e.g.
430 <pre>
431 struct MyStatic : public rtl::Static<MyType, MyStatic> {};
432 ...
433 MyType & rStatic = MyStatic::get();
434 ...
435 </pre>
436
437 @tparam T
438 variable's type
439 @tparam Unique
440 Implementation trick to make the inner static holder unique,
441 using the outer class
442 (the one that derives from this base class)
443*/
444#if defined LIBO_INTERNAL_ONLY1
445template<typename T, typename Data, typename Unique>
446class StaticWithArg {
447public:
448 /** Gets the static. Mutual exclusion is implied by a functional
449 -fthreadsafe-statics
450
451 @return
452 static variable
453 */
454 static T & get(const Data& rData) {
455 static T instance(rData);
456 return instance;
457 }
458
459 /** Gets the static. Mutual exclusion is implied by a functional
460 -fthreadsafe-statics
461
462 @return
463 static variable
464 */
465 static T & get(Data& rData) {
466 static T instance(rData);
467 return instance;
468 }
469};
470#else
471template<typename T, typename Data, typename Unique>
472class StaticWithArg {
473public:
474 /** Gets the static. Mutual exclusion is performed using the
475 osl global mutex.
476
477 @return
478 static variable
479 */
480 static T & get(const Data& rData) {
481 return *rtl_Instance<
482 T, StaticInstanceWithArg,
483 ::osl::MutexGuard, ::osl::GetGlobalMutex,
484 Data >::create( StaticInstanceWithArg(),
485 ::osl::GetGlobalMutex(),
486 rData );
487 }
488
489 /** Gets the static. Mutual exclusion is performed using the
490 osl global mutex.
491
492 @return
493 static variable
494 */
495 static T & get(Data& rData) {
496 return *rtl_Instance<
497 T, StaticInstanceWithArg,
498 ::osl::MutexGuard, ::osl::GetGlobalMutex,
499 Data >::create( StaticInstanceWithArg(),
500 ::osl::GetGlobalMutex(),
501 rData );
502 }
503private:
504 struct StaticInstanceWithArg {
505 T * operator () (const Data& rData) {
506 static T instance(rData);
507 return &instance;
508 }
509
510 T * operator () (Data& rData) {
511 static T instance(rData);
512 return &instance;
513 }
514 };
515};
516#endif
517
518/** Helper class for a late-initialized static aggregate, e.g. an array,
519 implementing the double-checked locking pattern correctly.
520
521 @tparam T
522 aggregate's element type
523 @tparam InitAggregate
524 initializer functor class
525*/
526#if defined LIBO_INTERNAL_ONLY1
527template<typename T, typename InitAggregate>
528class StaticAggregate {
529public:
530 /** Gets the static aggregate, late-initializing.
531 Mutual exclusion is implied by a functional
532 -fthreadsafe-statics
533
534 @return
535 aggregate
536 */
537 static T * get() {
538 static T *instance = InitAggregate()();
539 return instance;
540 }
541};
542#else
543template<typename T, typename InitAggregate>
544class StaticAggregate {
545public:
546 /** Gets the static aggregate, late-initializing.
547 Mutual exclusion is performed using the osl global mutex.
548
549 @return
550 aggregate
551 */
552 static T * get() {
553 return rtl_Instance<
554 T, InitAggregate,
555 ::osl::MutexGuard, ::osl::GetGlobalMutex >::create(
556 InitAggregate(), ::osl::GetGlobalMutex() );
557 }
558};
559#endif
560/** Helper base class for a late-initialized static variable,
561 implementing the double-checked locking pattern correctly.
562
563 @derive
564 Derive from this class (common practice),
565 providing an initializer functor class, e.g.
566 <pre>
567 struct MyStatic : public rtl::StaticWithInit<MyType, MyStatic> {
568 MyType operator () () {
569 ...
570 return MyType( ... );
571 }
572 };
573 ...
574 MyType & rStatic = MyStatic::get();
575 ...
576 </pre>
577
578 @tparam T
579 variable's type
580 @tparam InitData
581 initializer functor class
582 @tparam Unique
583 Implementation trick to make the inner static holder unique,
584 using the outer class
585 (the one that derives from this base class).
586 Default is InitData (common practice).
587 @tparam Data
588 Initializer functor's return type.
589 Default is T (common practice).
590*/
591#if defined LIBO_INTERNAL_ONLY1
592template<typename T, typename InitData,
593 typename Unique = InitData, typename Data = T>
594class StaticWithInit {
595public:
596 /** Gets the static. Mutual exclusion is implied by a functional
597 -fthreadsafe-statics
598
599 @return
600 static variable
601 */
602 static T & get() {
603 static T instance = InitData()();
604 return instance;
605 }
606};
607#else
608template<typename T, typename InitData,
609 typename Unique = InitData, typename Data = T>
610class StaticWithInit {
611public:
612 /** Gets the static. Mutual exclusion is performed using the
613 osl global mutex.
614
615 @return
616 static variable
617 */
618 static T & get() {
619 return *rtl_Instance<
620 T, StaticInstanceWithInit,
621 ::osl::MutexGuard, ::osl::GetGlobalMutex,
622 Data, InitData >::create( StaticInstanceWithInit(),
623 ::osl::GetGlobalMutex(),
624 InitData() );
625 }
626private:
627 struct StaticInstanceWithInit {
628 T * operator () ( Data d ) {
629 static T instance(d);
630 return &instance;
631 }
632 };
633};
634#endif
635} // namespace rtl
636
637#endif // INCLUDED_RTL_INSTANCE_HXX
638
639/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

/usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10/bits/unique_ptr.h

1// unique_ptr implementation -*- C++ -*-
2
3// Copyright (C) 2008-2020 Free Software Foundation, Inc.
4//
5// This file is part of the GNU ISO C++ Library. This library is free
6// software; you can redistribute it and/or modify it under the
7// terms of the GNU General Public License as published by the
8// Free Software Foundation; either version 3, or (at your option)
9// any later version.
10
11// This library is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14// GNU General Public License for more details.
15
16// Under Section 7 of GPL version 3, you are granted additional
17// permissions described in the GCC Runtime Library Exception, version
18// 3.1, as published by the Free Software Foundation.
19
20// You should have received a copy of the GNU General Public License and
21// a copy of the GCC Runtime Library Exception along with this program;
22// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23// <http://www.gnu.org/licenses/>.
24
25/** @file bits/unique_ptr.h
26 * This is an internal header file, included by other library headers.
27 * Do not attempt to use it directly. @headername{memory}
28 */
29
30#ifndef _UNIQUE_PTR_H1
31#define _UNIQUE_PTR_H1 1
32
33#include <bits/c++config.h>
34#include <debug/assertions.h>
35#include <type_traits>
36#include <utility>
37#include <tuple>
38#include <bits/stl_function.h>
39#include <bits/functional_hash.h>
40#if __cplusplus201703L > 201703L
41# include <compare>
42# include <ostream>
43#endif
44
45namespace std _GLIBCXX_VISIBILITY(default)__attribute__ ((__visibility__ ("default")))
46{
47_GLIBCXX_BEGIN_NAMESPACE_VERSION
48
49 /**
50 * @addtogroup pointer_abstractions
51 * @{
52 */
53
54#if _GLIBCXX_USE_DEPRECATED1
55#pragma GCC diagnostic push
56#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
57 template<typename> class auto_ptr;
58#pragma GCC diagnostic pop
59#endif
60
61 /// Primary template of default_delete, used by unique_ptr for single objects
62 template<typename _Tp>
63 struct default_delete
64 {
65 /// Default constructor
66 constexpr default_delete() noexcept = default;
67
68 /** @brief Converting constructor.
69 *
70 * Allows conversion from a deleter for objects of another type, `_Up`,
71 * only if `_Up*` is convertible to `_Tp*`.
72 */
73 template<typename _Up,
74 typename = _Require<is_convertible<_Up*, _Tp*>>>
75 default_delete(const default_delete<_Up>&) noexcept { }
76
77 /// Calls `delete __ptr`
78 void
79 operator()(_Tp* __ptr) const
80 {
81 static_assert(!is_void<_Tp>::value,
82 "can't delete pointer to incomplete type");
83 static_assert(sizeof(_Tp)>0,
84 "can't delete pointer to incomplete type");
85 delete __ptr;
86 }
87 };
88
89 // _GLIBCXX_RESOLVE_LIB_DEFECTS
90 // DR 740 - omit specialization for array objects with a compile time length
91
92 /// Specialization of default_delete for arrays, used by `unique_ptr<T[]>`
93 template<typename _Tp>
94 struct default_delete<_Tp[]>
95 {
96 public:
97 /// Default constructor
98 constexpr default_delete() noexcept = default;
99
100 /** @brief Converting constructor.
101 *
102 * Allows conversion from a deleter for arrays of another type, such as
103 * a const-qualified version of `_Tp`.
104 *
105 * Conversions from types derived from `_Tp` are not allowed because
106 * it is undefined to `delete[]` an array of derived types through a
107 * pointer to the base type.
108 */
109 template<typename _Up,
110 typename = _Require<is_convertible<_Up(*)[], _Tp(*)[]>>>
111 default_delete(const default_delete<_Up[]>&) noexcept { }
112
113 /// Calls `delete[] __ptr`
114 template<typename _Up>
115 typename enable_if<is_convertible<_Up(*)[], _Tp(*)[]>::value>::type
116 operator()(_Up* __ptr) const
117 {
118 static_assert(sizeof(_Tp)>0,
119 "can't delete pointer to incomplete type");
120 delete [] __ptr;
121 }
122 };
123
124 /// @cond undocumented
125
126 // Manages the pointer and deleter of a unique_ptr
127 template <typename _Tp, typename _Dp>
128 class __uniq_ptr_impl
129 {
130 template <typename _Up, typename _Ep, typename = void>
131 struct _Ptr
132 {
133 using type = _Up*;
134 };
135
136 template <typename _Up, typename _Ep>
137 struct
138 _Ptr<_Up, _Ep, __void_t<typename remove_reference<_Ep>::type::pointer>>
139 {
140 using type = typename remove_reference<_Ep>::type::pointer;
141 };
142
143 public:
144 using _DeleterConstraint = enable_if<
145 __and_<__not_<is_pointer<_Dp>>,
146 is_default_constructible<_Dp>>::value>;
147
148 using pointer = typename _Ptr<_Tp, _Dp>::type;
149
150 static_assert( !is_rvalue_reference<_Dp>::value,
151 "unique_ptr's deleter type must be a function object type"
152 " or an lvalue reference type" );
153
154 __uniq_ptr_impl() = default;
155 __uniq_ptr_impl(pointer __p) : _M_t() { _M_ptr() = __p; }
156
157 template<typename _Del>
158 __uniq_ptr_impl(pointer __p, _Del&& __d)
159 : _M_t(__p, std::forward<_Del>(__d)) { }
160
161 __uniq_ptr_impl(__uniq_ptr_impl&& __u) noexcept
162 : _M_t(std::move(__u._M_t))
163 { __u._M_ptr() = nullptr; }
164
165 __uniq_ptr_impl& operator=(__uniq_ptr_impl&& __u) noexcept
166 {
167 reset(__u.release());
168 _M_deleter() = std::forward<_Dp>(__u._M_deleter());
169 return *this;
170 }
171
172 pointer& _M_ptr() { return std::get<0>(_M_t); }
173 pointer _M_ptr() const { return std::get<0>(_M_t); }
174 _Dp& _M_deleter() { return std::get<1>(_M_t); }
175 const _Dp& _M_deleter() const { return std::get<1>(_M_t); }
176
177 void reset(pointer __p) noexcept
178 {
179 const pointer __old_p = _M_ptr();
180 _M_ptr() = __p;
181 if (__old_p)
182 _M_deleter()(__old_p);
183 }
184
185 pointer release() noexcept
186 {
187 pointer __p = _M_ptr();
188 _M_ptr() = nullptr;
189 return __p;
190 }
191
192 void
193 swap(__uniq_ptr_impl& __rhs) noexcept
194 {
195 using std::swap;
196 swap(this->_M_ptr(), __rhs._M_ptr());
197 swap(this->_M_deleter(), __rhs._M_deleter());
198 }
199
200 private:
201 tuple<pointer, _Dp> _M_t;
202 };
203
204 // Defines move construction + assignment as either defaulted or deleted.
205 template <typename _Tp, typename _Dp,
206 bool = is_move_constructible<_Dp>::value,
207 bool = is_move_assignable<_Dp>::value>
208 struct __uniq_ptr_data : __uniq_ptr_impl<_Tp, _Dp>
209 {
210 using __uniq_ptr_impl<_Tp, _Dp>::__uniq_ptr_impl;
211 __uniq_ptr_data(__uniq_ptr_data&&) = default;
212 __uniq_ptr_data& operator=(__uniq_ptr_data&&) = default;
213 };
214
215 template <typename _Tp, typename _Dp>
216 struct __uniq_ptr_data<_Tp, _Dp, true, false> : __uniq_ptr_impl<_Tp, _Dp>
217 {
218 using __uniq_ptr_impl<_Tp, _Dp>::__uniq_ptr_impl;
219 __uniq_ptr_data(__uniq_ptr_data&&) = default;
220 __uniq_ptr_data& operator=(__uniq_ptr_data&&) = delete;
221 };
222
223 template <typename _Tp, typename _Dp>
224 struct __uniq_ptr_data<_Tp, _Dp, false, true> : __uniq_ptr_impl<_Tp, _Dp>
225 {
226 using __uniq_ptr_impl<_Tp, _Dp>::__uniq_ptr_impl;
227 __uniq_ptr_data(__uniq_ptr_data&&) = delete;
228 __uniq_ptr_data& operator=(__uniq_ptr_data&&) = default;
229 };
230
231 template <typename _Tp, typename _Dp>
232 struct __uniq_ptr_data<_Tp, _Dp, false, false> : __uniq_ptr_impl<_Tp, _Dp>
233 {
234 using __uniq_ptr_impl<_Tp, _Dp>::__uniq_ptr_impl;
235 __uniq_ptr_data(__uniq_ptr_data&&) = delete;
236 __uniq_ptr_data& operator=(__uniq_ptr_data&&) = delete;
237 };
238 /// @endcond
239
240 /// 20.7.1.2 unique_ptr for single objects.
241 template <typename _Tp, typename _Dp = default_delete<_Tp>>
242 class unique_ptr
243 {
244 template <typename _Up>
245 using _DeleterConstraint =
246 typename __uniq_ptr_impl<_Tp, _Up>::_DeleterConstraint::type;
247
248 __uniq_ptr_data<_Tp, _Dp> _M_t;
249
250 public:
251 using pointer = typename __uniq_ptr_impl<_Tp, _Dp>::pointer;
252 using element_type = _Tp;
253 using deleter_type = _Dp;
254
255 private:
256 // helper template for detecting a safe conversion from another
257 // unique_ptr
258 template<typename _Up, typename _Ep>
259 using __safe_conversion_up = __and_<
260 is_convertible<typename unique_ptr<_Up, _Ep>::pointer, pointer>,
261 __not_<is_array<_Up>>
262 >;
263
264 public:
265 // Constructors.
266
267 /// Default constructor, creates a unique_ptr that owns nothing.
268 template<typename _Del = _Dp, typename = _DeleterConstraint<_Del>>
269 constexpr unique_ptr() noexcept
270 : _M_t()
271 { }
272
273 /** Takes ownership of a pointer.
274 *
275 * @param __p A pointer to an object of @c element_type
276 *
277 * The deleter will be value-initialized.
278 */
279 template<typename _Del = _Dp, typename = _DeleterConstraint<_Del>>
280 explicit
281 unique_ptr(pointer __p) noexcept
282 : _M_t(__p)
283 { }
284
285 /** Takes ownership of a pointer.
286 *
287 * @param __p A pointer to an object of @c element_type
288 * @param __d A reference to a deleter.
289 *
290 * The deleter will be initialized with @p __d
291 */
292 template<typename _Del = deleter_type,
293 typename = _Require<is_copy_constructible<_Del>>>
294 unique_ptr(pointer __p, const deleter_type& __d) noexcept
295 : _M_t(__p, __d) { }
296
297 /** Takes ownership of a pointer.
298 *
299 * @param __p A pointer to an object of @c element_type
300 * @param __d An rvalue reference to a (non-reference) deleter.
301 *
302 * The deleter will be initialized with @p std::move(__d)
303 */
304 template<typename _Del = deleter_type,
305 typename = _Require<is_move_constructible<_Del>>>
306 unique_ptr(pointer __p,
307 __enable_if_t<!is_lvalue_reference<_Del>::value,
308 _Del&&> __d) noexcept
309 : _M_t(__p, std::move(__d))
310 { }
311
312 template<typename _Del = deleter_type,
313 typename _DelUnref = typename remove_reference<_Del>::type>
314 unique_ptr(pointer,
315 __enable_if_t<is_lvalue_reference<_Del>::value,
316 _DelUnref&&>) = delete;
317
318 /// Creates a unique_ptr that owns nothing.
319 template<typename _Del = _Dp, typename = _DeleterConstraint<_Del>>
320 constexpr unique_ptr(nullptr_t) noexcept
321 : _M_t()
322 { }
323
324 // Move constructors.
325
326 /// Move constructor.
327 unique_ptr(unique_ptr&&) = default;
328
329 /** @brief Converting constructor from another type
330 *
331 * Requires that the pointer owned by @p __u is convertible to the
332 * type of pointer owned by this object, @p __u does not own an array,
333 * and @p __u has a compatible deleter type.
334 */
335 template<typename _Up, typename _Ep, typename = _Require<
336 __safe_conversion_up<_Up, _Ep>,
337 typename conditional<is_reference<_Dp>::value,
338 is_same<_Ep, _Dp>,
339 is_convertible<_Ep, _Dp>>::type>>
340 unique_ptr(unique_ptr<_Up, _Ep>&& __u) noexcept
341 : _M_t(__u.release(), std::forward<_Ep>(__u.get_deleter()))
342 { }
343
344#if _GLIBCXX_USE_DEPRECATED1
345#pragma GCC diagnostic push
346#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
347 /// Converting constructor from @c auto_ptr
348 template<typename _Up, typename = _Require<
349 is_convertible<_Up*, _Tp*>, is_same<_Dp, default_delete<_Tp>>>>
350 unique_ptr(auto_ptr<_Up>&& __u) noexcept;
351#pragma GCC diagnostic pop
352#endif
353
354 /// Destructor, invokes the deleter if the stored pointer is not null.
355 ~unique_ptr() noexcept
356 {
357 static_assert(__is_invocable<deleter_type&, pointer>::value,
358 "unique_ptr's deleter must be invocable with a pointer");
359 auto& __ptr = _M_t._M_ptr();
360 if (__ptr != nullptr)
361 get_deleter()(std::move(__ptr));
362 __ptr = pointer();
363 }
364
365 // Assignment.
366
367 /** @brief Move assignment operator.
368 *
369 * Invokes the deleter if this object owns a pointer.
370 */
371 unique_ptr& operator=(unique_ptr&&) = default;
372
373 /** @brief Assignment from another type.
374 *
375 * @param __u The object to transfer ownership from, which owns a
376 * convertible pointer to a non-array object.
377 *
378 * Invokes the deleter if this object owns a pointer.
379 */
380 template<typename _Up, typename _Ep>
381 typename enable_if< __and_<
382 __safe_conversion_up<_Up, _Ep>,
383 is_assignable<deleter_type&, _Ep&&>
384 >::value,
385 unique_ptr&>::type
386 operator=(unique_ptr<_Up, _Ep>&& __u) noexcept
387 {
388 reset(__u.release());
389 get_deleter() = std::forward<_Ep>(__u.get_deleter());
390 return *this;
391 }
392
393 /// Reset the %unique_ptr to empty, invoking the deleter if necessary.
394 unique_ptr&
395 operator=(nullptr_t) noexcept
396 {
397 reset();
398 return *this;
399 }
400
401 // Observers.
402
403 /// Dereference the stored pointer.
404 typename add_lvalue_reference<element_type>::type
405 operator*() const
406 {
407 __glibcxx_assert(get() != pointer());
408 return *get();
409 }
410
411 /// Return the stored pointer.
412 pointer
413 operator->() const noexcept
414 {
415 _GLIBCXX_DEBUG_PEDASSERT(get() != pointer());
416 return get();
417 }
418
419 /// Return the stored pointer.
420 pointer
421 get() const noexcept
422 { return _M_t._M_ptr(); }
423
424 /// Return a reference to the stored deleter.
425 deleter_type&
426 get_deleter() noexcept
427 { return _M_t._M_deleter(); }
428
429 /// Return a reference to the stored deleter.
430 const deleter_type&
431 get_deleter() const noexcept
432 { return _M_t._M_deleter(); }
433
434 /// Return @c true if the stored pointer is not null.
435 explicit operator bool() const noexcept
436 { return get() == pointer() ? false : true; }
16
'?' condition is false
17
Returning the value 1, which participates in a condition later
437
438 // Modifiers.
439
440 /// Release ownership of any stored pointer.
441 pointer
442 release() noexcept
443 { return _M_t.release(); }
444
445 /** @brief Replace the stored pointer.
446 *
447 * @param __p The new pointer to store.
448 *
449 * The deleter will be invoked if a pointer is already owned.
450 */
451 void
452 reset(pointer __p = pointer()) noexcept
453 {
454 static_assert(__is_invocable<deleter_type&, pointer>::value,
455 "unique_ptr's deleter must be invocable with a pointer");
456 _M_t.reset(std::move(__p));
457 }
458
459 /// Exchange the pointer and deleter with another object.
460 void
461 swap(unique_ptr& __u) noexcept
462 {
463 static_assert(__is_swappable<_Dp>::value, "deleter must be swappable");
464 _M_t.swap(__u._M_t);
465 }
466
467 // Disable copy from lvalue.
468 unique_ptr(const unique_ptr&) = delete;
469 unique_ptr& operator=(const unique_ptr&) = delete;
470 };
471
472 /// 20.7.1.3 unique_ptr for array objects with a runtime length
473 // [unique.ptr.runtime]
474 // _GLIBCXX_RESOLVE_LIB_DEFECTS
475 // DR 740 - omit specialization for array objects with a compile time length
476 template<typename _Tp, typename _Dp>
477 class unique_ptr<_Tp[], _Dp>
478 {
479 template <typename _Up>
480 using _DeleterConstraint =
481 typename __uniq_ptr_impl<_Tp, _Up>::_DeleterConstraint::type;
482
483 __uniq_ptr_data<_Tp, _Dp> _M_t;
484
485 template<typename _Up>
486 using __remove_cv = typename remove_cv<_Up>::type;
487
488 // like is_base_of<_Tp, _Up> but false if unqualified types are the same
489 template<typename _Up>
490 using __is_derived_Tp
491 = __and_< is_base_of<_Tp, _Up>,
492 __not_<is_same<__remove_cv<_Tp>, __remove_cv<_Up>>> >;
493
494 public:
495 using pointer = typename __uniq_ptr_impl<_Tp, _Dp>::pointer;
496 using element_type = _Tp;
497 using deleter_type = _Dp;
498
499 // helper template for detecting a safe conversion from another
500 // unique_ptr
501 template<typename _Up, typename _Ep,
502 typename _UPtr = unique_ptr<_Up, _Ep>,
503 typename _UP_pointer = typename _UPtr::pointer,
504 typename _UP_element_type = typename _UPtr::element_type>
505 using __safe_conversion_up = __and_<
506 is_array<_Up>,
507 is_same<pointer, element_type*>,
508 is_same<_UP_pointer, _UP_element_type*>,
509 is_convertible<_UP_element_type(*)[], element_type(*)[]>
510 >;
511
512 // helper template for detecting a safe conversion from a raw pointer
513 template<typename _Up>
514 using __safe_conversion_raw = __and_<
515 __or_<__or_<is_same<_Up, pointer>,
516 is_same<_Up, nullptr_t>>,
517 __and_<is_pointer<_Up>,
518 is_same<pointer, element_type*>,
519 is_convertible<
520 typename remove_pointer<_Up>::type(*)[],
521 element_type(*)[]>
522 >
523 >
524 >;
525
526 // Constructors.
527
528 /// Default constructor, creates a unique_ptr that owns nothing.
529 template<typename _Del = _Dp, typename = _DeleterConstraint<_Del>>
530 constexpr unique_ptr() noexcept
531 : _M_t()
532 { }
533
534 /** Takes ownership of a pointer.
535 *
536 * @param __p A pointer to an array of a type safely convertible
537 * to an array of @c element_type
538 *
539 * The deleter will be value-initialized.
540 */
541 template<typename _Up,
542 typename _Vp = _Dp,
543 typename = _DeleterConstraint<_Vp>,
544 typename = typename enable_if<
545 __safe_conversion_raw<_Up>::value, bool>::type>
546 explicit
547 unique_ptr(_Up __p) noexcept
548 : _M_t(__p)
549 { }
550
551 /** Takes ownership of a pointer.
552 *
553 * @param __p A pointer to an array of a type safely convertible
554 * to an array of @c element_type
555 * @param __d A reference to a deleter.
556 *
557 * The deleter will be initialized with @p __d
558 */
559 template<typename _Up, typename _Del = deleter_type,
560 typename = _Require<__safe_conversion_raw<_Up>,
561 is_copy_constructible<_Del>>>
562 unique_ptr(_Up __p, const deleter_type& __d) noexcept
563 : _M_t(__p, __d) { }
564
565 /** Takes ownership of a pointer.
566 *
567 * @param __p A pointer to an array of a type safely convertible
568 * to an array of @c element_type
569 * @param __d A reference to a deleter.
570 *
571 * The deleter will be initialized with @p std::move(__d)
572 */
573 template<typename _Up, typename _Del = deleter_type,
574 typename = _Require<__safe_conversion_raw<_Up>,
575 is_move_constructible<_Del>>>
576 unique_ptr(_Up __p,
577 __enable_if_t<!is_lvalue_reference<_Del>::value,
578 _Del&&> __d) noexcept
579 : _M_t(std::move(__p), std::move(__d))
580 { }
581
582 template<typename _Up, typename _Del = deleter_type,
583 typename _DelUnref = typename remove_reference<_Del>::type,
584 typename = _Require<__safe_conversion_raw<_Up>>>
585 unique_ptr(_Up,
586 __enable_if_t<is_lvalue_reference<_Del>::value,
587 _DelUnref&&>) = delete;
588
589 /// Move constructor.
590 unique_ptr(unique_ptr&&) = default;
591
592 /// Creates a unique_ptr that owns nothing.
593 template<typename _Del = _Dp, typename = _DeleterConstraint<_Del>>
594 constexpr unique_ptr(nullptr_t) noexcept
595 : _M_t()
596 { }
597
598 template<typename _Up, typename _Ep, typename = _Require<
599 __safe_conversion_up<_Up, _Ep>,
600 typename conditional<is_reference<_Dp>::value,
601 is_same<_Ep, _Dp>,
602 is_convertible<_Ep, _Dp>>::type>>
603 unique_ptr(unique_ptr<_Up, _Ep>&& __u) noexcept
604 : _M_t(__u.release(), std::forward<_Ep>(__u.get_deleter()))
605 { }
606
607 /// Destructor, invokes the deleter if the stored pointer is not null.
608 ~unique_ptr()
609 {
610 auto& __ptr = _M_t._M_ptr();
611 if (__ptr != nullptr)
612 get_deleter()(__ptr);
613 __ptr = pointer();
614 }
615
616 // Assignment.
617
618 /** @brief Move assignment operator.
619 *
620 * Invokes the deleter if this object owns a pointer.
621 */
622 unique_ptr&
623 operator=(unique_ptr&&) = default;
624
625 /** @brief Assignment from another type.
626 *
627 * @param __u The object to transfer ownership from, which owns a
628 * convertible pointer to an array object.
629 *
630 * Invokes the deleter if this object owns a pointer.
631 */
632 template<typename _Up, typename _Ep>
633 typename
634 enable_if<__and_<__safe_conversion_up<_Up, _Ep>,
635 is_assignable<deleter_type&, _Ep&&>
636 >::value,
637 unique_ptr&>::type
638 operator=(unique_ptr<_Up, _Ep>&& __u) noexcept
639 {
640 reset(__u.release());
641 get_deleter() = std::forward<_Ep>(__u.get_deleter());
642 return *this;
643 }
644
645 /// Reset the %unique_ptr to empty, invoking the deleter if necessary.
646 unique_ptr&
647 operator=(nullptr_t) noexcept
648 {
649 reset();
650 return *this;
651 }
652
653 // Observers.
654
655 /// Access an element of owned array.
656 typename std::add_lvalue_reference<element_type>::type
657 operator[](size_t __i) const
658 {
659 __glibcxx_assert(get() != pointer());
660 return get()[__i];
661 }
662
663 /// Return the stored pointer.
664 pointer
665 get() const noexcept
666 { return _M_t._M_ptr(); }
667
668 /// Return a reference to the stored deleter.
669 deleter_type&
670 get_deleter() noexcept
671 { return _M_t._M_deleter(); }
672
673 /// Return a reference to the stored deleter.
674 const deleter_type&
675 get_deleter() const noexcept
676 { return _M_t._M_deleter(); }
677
678 /// Return @c true if the stored pointer is not null.
679 explicit operator bool() const noexcept
680 { return get() == pointer() ? false : true; }
681
682 // Modifiers.
683
684 /// Release ownership of any stored pointer.
685 pointer
686 release() noexcept
687 { return _M_t.release(); }
688
689 /** @brief Replace the stored pointer.
690 *
691 * @param __p The new pointer to store.
692 *
693 * The deleter will be invoked if a pointer is already owned.
694 */
695 template <typename _Up,
696 typename = _Require<
697 __or_<is_same<_Up, pointer>,
698 __and_<is_same<pointer, element_type*>,
699 is_pointer<_Up>,
700 is_convertible<
701 typename remove_pointer<_Up>::type(*)[],
702 element_type(*)[]
703 >
704 >
705 >
706 >>
707 void
708 reset(_Up __p) noexcept
709 { _M_t.reset(std::move(__p)); }
710
711 void reset(nullptr_t = nullptr) noexcept
712 { reset(pointer()); }
713
714 /// Exchange the pointer and deleter with another object.
715 void
716 swap(unique_ptr& __u) noexcept
717 {
718 static_assert(__is_swappable<_Dp>::value, "deleter must be swappable");
719 _M_t.swap(__u._M_t);
720 }
721
722 // Disable copy from lvalue.
723 unique_ptr(const unique_ptr&) = delete;
724 unique_ptr& operator=(const unique_ptr&) = delete;
725 };
726
727 /// @relates unique_ptr @{
728
729 /// Swap overload for unique_ptr
730 template<typename _Tp, typename _Dp>
731 inline
732#if __cplusplus201703L > 201402L || !defined(__STRICT_ANSI__1) // c++1z or gnu++11
733 // Constrained free swap overload, see p0185r1
734 typename enable_if<__is_swappable<_Dp>::value>::type
735#else
736 void
737#endif
738 swap(unique_ptr<_Tp, _Dp>& __x,
739 unique_ptr<_Tp, _Dp>& __y) noexcept
740 { __x.swap(__y); }
741
742#if __cplusplus201703L > 201402L || !defined(__STRICT_ANSI__1) // c++1z or gnu++11
743 template<typename _Tp, typename _Dp>
744 typename enable_if<!__is_swappable<_Dp>::value>::type
745 swap(unique_ptr<_Tp, _Dp>&,
746 unique_ptr<_Tp, _Dp>&) = delete;
747#endif
748
749 /// Equality operator for unique_ptr objects, compares the owned pointers
750 template<typename _Tp, typename _Dp,
751 typename _Up, typename _Ep>
752 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
753 operator==(const unique_ptr<_Tp, _Dp>& __x,
754 const unique_ptr<_Up, _Ep>& __y)
755 { return __x.get() == __y.get(); }
756
757 /// unique_ptr comparison with nullptr
758 template<typename _Tp, typename _Dp>
759 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
760 operator==(const unique_ptr<_Tp, _Dp>& __x, nullptr_t) noexcept
761 { return !__x; }
762
763#ifndef __cpp_lib_three_way_comparison
764 /// unique_ptr comparison with nullptr
765 template<typename _Tp, typename _Dp>
766 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
767 operator==(nullptr_t, const unique_ptr<_Tp, _Dp>& __x) noexcept
768 { return !__x; }
769
770 /// Inequality operator for unique_ptr objects, compares the owned pointers
771 template<typename _Tp, typename _Dp,
772 typename _Up, typename _Ep>
773 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
774 operator!=(const unique_ptr<_Tp, _Dp>& __x,
775 const unique_ptr<_Up, _Ep>& __y)
776 { return __x.get() != __y.get(); }
777
778 /// unique_ptr comparison with nullptr
779 template<typename _Tp, typename _Dp>
780 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
781 operator!=(const unique_ptr<_Tp, _Dp>& __x, nullptr_t) noexcept
782 { return (bool)__x; }
783
784 /// unique_ptr comparison with nullptr
785 template<typename _Tp, typename _Dp>
786 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
787 operator!=(nullptr_t, const unique_ptr<_Tp, _Dp>& __x) noexcept
788 { return (bool)__x; }
789#endif // three way comparison
790
791 /// Relational operator for unique_ptr objects, compares the owned pointers
792 template<typename _Tp, typename _Dp,
793 typename _Up, typename _Ep>
794 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
795 operator<(const unique_ptr<_Tp, _Dp>& __x,
796 const unique_ptr<_Up, _Ep>& __y)
797 {
798 typedef typename
799 std::common_type<typename unique_ptr<_Tp, _Dp>::pointer,
800 typename unique_ptr<_Up, _Ep>::pointer>::type _CT;
801 return std::less<_CT>()(__x.get(), __y.get());
802 }
803
804 /// unique_ptr comparison with nullptr
805 template<typename _Tp, typename _Dp>
806 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
807 operator<(const unique_ptr<_Tp, _Dp>& __x, nullptr_t)
808 {
809 return std::less<typename unique_ptr<_Tp, _Dp>::pointer>()(__x.get(),
810 nullptr);
811 }
812
813 /// unique_ptr comparison with nullptr
814 template<typename _Tp, typename _Dp>
815 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
816 operator<(nullptr_t, const unique_ptr<_Tp, _Dp>& __x)
817 {
818 return std::less<typename unique_ptr<_Tp, _Dp>::pointer>()(nullptr,
819 __x.get());
820 }
821
822 /// Relational operator for unique_ptr objects, compares the owned pointers
823 template<typename _Tp, typename _Dp,
824 typename _Up, typename _Ep>
825 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
826 operator<=(const unique_ptr<_Tp, _Dp>& __x,
827 const unique_ptr<_Up, _Ep>& __y)
828 { return !(__y < __x); }
829
830 /// unique_ptr comparison with nullptr
831 template<typename _Tp, typename _Dp>
832 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
833 operator<=(const unique_ptr<_Tp, _Dp>& __x, nullptr_t)
834 { return !(nullptr < __x); }
835
836 /// unique_ptr comparison with nullptr
837 template<typename _Tp, typename _Dp>
838 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
839 operator<=(nullptr_t, const unique_ptr<_Tp, _Dp>& __x)
840 { return !(__x < nullptr); }
841
842 /// Relational operator for unique_ptr objects, compares the owned pointers
843 template<typename _Tp, typename _Dp,
844 typename _Up, typename _Ep>
845 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
846 operator>(const unique_ptr<_Tp, _Dp>& __x,
847 const unique_ptr<_Up, _Ep>& __y)
848 { return (__y < __x); }
849
850 /// unique_ptr comparison with nullptr
851 template<typename _Tp, typename _Dp>
852 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
853 operator>(const unique_ptr<_Tp, _Dp>& __x, nullptr_t)
854 {
855 return std::less<typename unique_ptr<_Tp, _Dp>::pointer>()(nullptr,
856 __x.get());
857 }
858
859 /// unique_ptr comparison with nullptr
860 template<typename _Tp, typename _Dp>
861 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
862 operator>(nullptr_t, const unique_ptr<_Tp, _Dp>& __x)
863 {
864 return std::less<typename unique_ptr<_Tp, _Dp>::pointer>()(__x.get(),
865 nullptr);
866 }
867
868 /// Relational operator for unique_ptr objects, compares the owned pointers
869 template<typename _Tp, typename _Dp,
870 typename _Up, typename _Ep>
871 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
872 operator>=(const unique_ptr<_Tp, _Dp>& __x,
873 const unique_ptr<_Up, _Ep>& __y)
874 { return !(__x < __y); }
875
876 /// unique_ptr comparison with nullptr
877 template<typename _Tp, typename _Dp>
878 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
879 operator>=(const unique_ptr<_Tp, _Dp>& __x, nullptr_t)
880 { return !(__x < nullptr); }
881
882 /// unique_ptr comparison with nullptr
883 template<typename _Tp, typename _Dp>
884 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
885 operator>=(nullptr_t, const unique_ptr<_Tp, _Dp>& __x)
886 { return !(nullptr < __x); }
887
888#ifdef __cpp_lib_three_way_comparison
889 template<typename _Tp, typename _Dp, typename _Up, typename _Ep>
890 requires three_way_comparable_with<typename unique_ptr<_Tp, _Dp>::pointer,
891 typename unique_ptr<_Up, _Ep>::pointer>
892 inline
893 compare_three_way_result_t<typename unique_ptr<_Tp, _Dp>::pointer,
894 typename unique_ptr<_Up, _Ep>::pointer>
895 operator<=>(const unique_ptr<_Tp, _Dp>& __x,
896 const unique_ptr<_Up, _Ep>& __y)
897 { return compare_three_way()(__x.get(), __y.get()); }
898
899 template<typename _Tp, typename _Dp>
900 requires three_way_comparable<typename unique_ptr<_Tp, _Dp>::pointer>
901 inline
902 compare_three_way_result_t<typename unique_ptr<_Tp, _Dp>::pointer>
903 operator<=>(const unique_ptr<_Tp, _Dp>& __x, nullptr_t)
904 {
905 using pointer = typename unique_ptr<_Tp, _Dp>::pointer;
906 return compare_three_way()(__x.get(), static_cast<pointer>(nullptr));
907 }
908#endif
909 // @} relates unique_ptr
910
911 /// @cond undocumented
912 template<typename _Up, typename _Ptr = typename _Up::pointer,
913 bool = __poison_hash<_Ptr>::__enable_hash_call>
914 struct __uniq_ptr_hash
915#if ! _GLIBCXX_INLINE_VERSION0
916 : private __poison_hash<_Ptr>
917#endif
918 {
919 size_t
920 operator()(const _Up& __u) const
921 noexcept(noexcept(std::declval<hash<_Ptr>>()(std::declval<_Ptr>())))
922 { return hash<_Ptr>()(__u.get()); }
923 };
924
925 template<typename _Up, typename _Ptr>
926 struct __uniq_ptr_hash<_Up, _Ptr, false>
927 : private __poison_hash<_Ptr>
928 { };
929 /// @endcond
930
931 /// std::hash specialization for unique_ptr.
932 template<typename _Tp, typename _Dp>
933 struct hash<unique_ptr<_Tp, _Dp>>
934 : public __hash_base<size_t, unique_ptr<_Tp, _Dp>>,
935 public __uniq_ptr_hash<unique_ptr<_Tp, _Dp>>
936 { };
937
938#if __cplusplus201703L >= 201402L
939 /// @relates unique_ptr @{
940#define __cpp_lib_make_unique201304 201304
941
942 /// @cond undocumented
943
944 template<typename _Tp>
945 struct _MakeUniq
946 { typedef unique_ptr<_Tp> __single_object; };
947
948 template<typename _Tp>
949 struct _MakeUniq<_Tp[]>
950 { typedef unique_ptr<_Tp[]> __array; };
951
952 template<typename _Tp, size_t _Bound>
953 struct _MakeUniq<_Tp[_Bound]>
954 { struct __invalid_type { }; };
955
956 /// @endcond
957
958 /// std::make_unique for single objects
959 template<typename _Tp, typename... _Args>
960 inline typename _MakeUniq<_Tp>::__single_object
961 make_unique(_Args&&... __args)
962 { return unique_ptr<_Tp>(new _Tp(std::forward<_Args>(__args)...)); }
12
Calling 'forward<SfxObjectFactory *&>'
13
Returning from 'forward<SfxObjectFactory *&>'
963
964 /// std::make_unique for arrays of unknown bound
965 template<typename _Tp>
966 inline typename _MakeUniq<_Tp>::__array
967 make_unique(size_t __num)
968 { return unique_ptr<_Tp>(new remove_extent_t<_Tp>[__num]()); }
969
970 /// Disable std::make_unique for arrays of known bound
971 template<typename _Tp, typename... _Args>
972 inline typename _MakeUniq<_Tp>::__invalid_type
973 make_unique(_Args&&...) = delete;
974 // @} relates unique_ptr
975#endif // C++14
976
977#if __cplusplus201703L > 201703L && __cpp_concepts
978 // _GLIBCXX_RESOLVE_LIB_DEFECTS
979 // 2948. unique_ptr does not define operator<< for stream output
980 /// Stream output operator for unique_ptr
981 template<typename _CharT, typename _Traits, typename _Tp, typename _Dp>
982 inline basic_ostream<_CharT, _Traits>&
983 operator<<(basic_ostream<_CharT, _Traits>& __os,
984 const unique_ptr<_Tp, _Dp>& __p)
985 requires requires { __os << __p.get(); }
986 {
987 __os << __p.get();
988 return __os;
989 }
990#endif // C++20
991
992 // @} group pointer_abstractions
993
994#if __cplusplus201703L >= 201703L
995 namespace __detail::__variant
996 {
997 template<typename> struct _Never_valueless_alt; // see <variant>
998
999 // Provide the strong exception-safety guarantee when emplacing a
1000 // unique_ptr into a variant.
1001 template<typename _Tp, typename _Del>
1002 struct _Never_valueless_alt<std::unique_ptr<_Tp, _Del>>
1003 : std::true_type
1004 { };
1005 } // namespace __detail::__variant
1006#endif // C++17
1007
1008_GLIBCXX_END_NAMESPACE_VERSION
1009} // namespace
1010
1011#endif /* _UNIQUE_PTR_H */