Bug Summary

File:home/maarten/src/libreoffice/core/sw/source/core/unocore/unorefmk.cxx
Warning:line 1022, column 1
Potential leak of memory pointed to by field '_M_pi'

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 unorefmk.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/core/unocore/unorefmk.cxx

/home/maarten/src/libreoffice/core/sw/source/core/unocore/unorefmk.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#include <utility>
22
23#include <comphelper/interfacecontainer2.hxx>
24#include <comphelper/processfactory.hxx>
25#include <comphelper/servicehelper.hxx>
26#include <cppuhelper/exc_hlp.hxx>
27#include <cppuhelper/supportsservice.hxx>
28#include <cppuhelper/weak.hxx>
29#include <osl/mutex.hxx>
30#include <sal/config.h>
31#include <svl/listener.hxx>
32#include <vcl/svapp.hxx>
33#include <sal/log.hxx>
34
35#include <unotextrange.hxx>
36#include <unorefmark.hxx>
37#include <unotextcursor.hxx>
38#include <unomap.hxx>
39#include <unocrsrhelper.hxx>
40#include <doc.hxx>
41#include <ndtxt.hxx>
42#include <fmtrfmrk.hxx>
43#include <txtrfmrk.hxx>
44#include <unometa.hxx>
45#include <unotext.hxx>
46#include <unoport.hxx>
47#include <txtatr.hxx>
48#include <fmtmeta.hxx>
49#include <docsh.hxx>
50
51#include <com/sun/star/frame/XModel.hpp>
52#include <com/sun/star/lang/NoSupportException.hpp>
53#include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
54#include <com/sun/star/rdf/Statement.hpp>
55#include <com/sun/star/rdf/URI.hpp>
56#include <com/sun/star/rdf/URIs.hpp>
57#include <com/sun/star/rdf/XLiteral.hpp>
58#include <com/sun/star/rdf/XRepositorySupplier.hpp>
59#include <com/sun/star/lang/DisposedException.hpp>
60
61using namespace ::com::sun::star;
62
63class SwXReferenceMark::Impl
64 : public SvtListener
65{
66private:
67 ::osl::Mutex m_Mutex; // just for OInterfaceContainerHelper2
68
69public:
70 uno::WeakReference<uno::XInterface> m_wThis;
71 ::comphelper::OInterfaceContainerHelper2 m_EventListeners;
72 bool m_bIsDescriptor;
73 SwDoc* m_pDoc;
74 const SwFormatRefMark* m_pMarkFormat;
75 OUString m_sMarkName;
76
77 Impl(SwDoc* const pDoc, SwFormatRefMark* const pRefMark)
78 : m_EventListeners(m_Mutex)
79 , m_bIsDescriptor(nullptr == pRefMark)
80 , m_pDoc(pDoc)
81 , m_pMarkFormat(pRefMark)
82 {
83 if (pRefMark)
84 {
85 StartListening(pRefMark->GetNotifier());
86 m_sMarkName = pRefMark->GetRefName();
87 }
88 }
89
90 bool IsValid() const { return m_pMarkFormat; }
91 void InsertRefMark( SwPaM & rPam, SwXTextCursor const*const pCursor );
92 void Invalidate();
93protected:
94 virtual void Notify(const SfxHint&) override;
95
96};
97
98void SwXReferenceMark::Impl::Invalidate()
99{
100 EndListeningAll();
101 m_pDoc = nullptr;
102 m_pMarkFormat = nullptr;
103 uno::Reference<uno::XInterface> const xThis(m_wThis);
104 if (!xThis.is())
105 { // fdo#72695: if UNO object is already dead, don't revive it with event
106 return;
107 }
108 lang::EventObject const ev(xThis);
109 m_EventListeners.disposeAndClear(ev);
110}
111
112void SwXReferenceMark::Impl::Notify(const SfxHint& rHint)
113{
114 if(rHint.GetId() == SfxHintId::Dying)
115 Invalidate();
116}
117
118SwXReferenceMark::SwXReferenceMark(
119 SwDoc *const pDoc, SwFormatRefMark *const pRefMark)
120 : m_pImpl( new SwXReferenceMark::Impl(pDoc, pRefMark) )
121{
122}
123
124SwXReferenceMark::~SwXReferenceMark()
125{
126}
127
128uno::Reference<text::XTextContent>
129SwXReferenceMark::CreateXReferenceMark(
130 SwDoc & rDoc, SwFormatRefMark *const pMarkFormat)
131{
132 // i#105557: do not iterate over the registered clients: race condition
133 uno::Reference<text::XTextContent> xMark;
134 if (pMarkFormat)
135 {
136 xMark = pMarkFormat->GetXRefMark();
137 }
138 if (!xMark.is())
139 {
140 SwXReferenceMark *const pMark(new SwXReferenceMark(&rDoc, pMarkFormat));
141 xMark.set(pMark);
142 if (pMarkFormat)
143 {
144 pMarkFormat->SetXRefMark(xMark);
145 }
146 // need a permanent Reference to initialize m_wThis
147 pMark->m_pImpl->m_wThis = xMark;
148 }
149 return xMark;
150}
151
152namespace
153{
154 class theSwXReferenceMarkUnoTunnelId : public rtl::Static< UnoTunnelIdInit, theSwXReferenceMarkUnoTunnelId > {};
155}
156
157const uno::Sequence< sal_Int8 > & SwXReferenceMark::getUnoTunnelId()
158{
159 return theSwXReferenceMarkUnoTunnelId::get().getSeq();
160}
161
162sal_Int64 SAL_CALL
163SwXReferenceMark::getSomething(const uno::Sequence< sal_Int8 >& rId)
164{
165 return ::sw::UnoTunnelImpl<SwXReferenceMark>(rId, this);
166}
167
168OUString SAL_CALL SwXReferenceMark::getImplementationName()
169{
170 return "SwXReferenceMark";
171}
172
173sal_Bool SAL_CALL
174SwXReferenceMark::supportsService(const OUString& rServiceName)
175{
176 return cppu::supportsService(this, rServiceName);
177}
178
179uno::Sequence< OUString > SAL_CALL
180SwXReferenceMark::getSupportedServiceNames()
181{
182 return {
183 "com.sun.star.text.TextContent",
184 "com.sun.star.text.ReferenceMark"
185 };
186}
187
188namespace {
189
190template<typename T> struct NotContainedIn
191{
192 std::vector<T> const& m_rVector;
193 explicit NotContainedIn(std::vector<T> const& rVector)
194 : m_rVector(rVector) { }
195 bool operator() (T const& rT) {
196 return std::find(m_rVector.begin(), m_rVector.end(), rT)
197 == m_rVector.end();
198 }
199};
200
201}
202
203void SwXReferenceMark::Impl::InsertRefMark(SwPaM& rPam,
204 SwXTextCursor const*const pCursor)
205{
206 //! in some cases when this function is called the pDoc pointer member may have become
207 //! invalid/deleted thus we obtain the document pointer from rPaM where it should always
208 //! be valid.
209 SwDoc& rDoc2 = rPam.GetDoc();
210
211 UnoActionContext aCont(&rDoc2);
212 SwFormatRefMark aRefMark(m_sMarkName);
213 bool bMark = *rPam.GetPoint() != *rPam.GetMark();
214
215 const bool bForceExpandHints( !bMark && pCursor && pCursor->IsAtEndOfMeta() );
216 const SetAttrMode nInsertFlags = bForceExpandHints
217 ? ( SetAttrMode::FORCEHINTEXPAND
218 | SetAttrMode::DONTEXPAND)
219 : SetAttrMode::DONTEXPAND;
220
221 std::vector<SwTextAttr *> oldMarks;
222 if (bMark)
223 {
224 oldMarks = rPam.GetNode().GetTextNode()->GetTextAttrsAt(
225 rPam.GetPoint()->nContent.GetIndex(), RES_TXTATR_REFMARK);
226 }
227
228 rDoc2.getIDocumentContentOperations().InsertPoolItem( rPam, aRefMark, nInsertFlags );
229
230 if( bMark && *rPam.GetPoint() > *rPam.GetMark())
231 {
232 rPam.Exchange();
233 }
234
235 // aRefMark was copied into the document pool; now retrieve real format...
236 SwTextAttr * pTextAttr(nullptr);
237 if (bMark)
238 {
239 // #i107672#
240 // ensure that we do not retrieve a different mark at the same position
241 std::vector<SwTextAttr *> const newMarks(
242 rPam.GetNode().GetTextNode()->GetTextAttrsAt(
243 rPam.GetPoint()->nContent.GetIndex(), RES_TXTATR_REFMARK));
244 std::vector<SwTextAttr *>::const_iterator const iter(
245 std::find_if(newMarks.begin(), newMarks.end(),
246 NotContainedIn<SwTextAttr *>(oldMarks)));
247 assert(newMarks.end() != iter)(static_cast <bool> (newMarks.end() != iter) ? void (0)
: __assert_fail ("newMarks.end() != iter", "/home/maarten/src/libreoffice/core/sw/source/core/unocore/unorefmk.cxx"
, 247, __extension__ __PRETTY_FUNCTION__))
;
248 if (newMarks.end() != iter)
249 {
250 pTextAttr = *iter;
251 }
252 }
253 else
254 {
255 SwTextNode *pTextNd = rPam.GetNode().GetTextNode();
256 assert(pTextNd)(static_cast <bool> (pTextNd) ? void (0) : __assert_fail
("pTextNd", "/home/maarten/src/libreoffice/core/sw/source/core/unocore/unorefmk.cxx"
, 256, __extension__ __PRETTY_FUNCTION__))
;
257 pTextAttr = pTextNd ? rPam.GetNode().GetTextNode()->GetTextAttrForCharAt(
258 rPam.GetPoint()->nContent.GetIndex() - 1, RES_TXTATR_REFMARK) : nullptr;
259 }
260
261 if (!pTextAttr)
262 {
263 throw uno::RuntimeException(
264 "SwXReferenceMark::InsertRefMark(): cannot insert attribute", nullptr);
265 }
266
267 m_pMarkFormat = &pTextAttr->GetRefMark();
268 EndListeningAll();
269 StartListening(const_cast<SwFormatRefMark*>(m_pMarkFormat)->GetNotifier());
270}
271
272void SAL_CALL
273SwXReferenceMark::attach(const uno::Reference< text::XTextRange > & xTextRange)
274{
275 SolarMutexGuard aGuard;
276
277 if (!m_pImpl->m_bIsDescriptor)
278 {
279 throw uno::RuntimeException();
280 }
281 uno::Reference<lang::XUnoTunnel> xRangeTunnel( xTextRange, uno::UNO_QUERY);
282 SwXTextRange* pRange = nullptr;
283 OTextCursorHelper* pCursor = nullptr;
284 if(xRangeTunnel.is())
285 {
286 pRange = ::sw::UnoTunnelGetImplementation<SwXTextRange>(xRangeTunnel);
287 pCursor =
288 ::sw::UnoTunnelGetImplementation<OTextCursorHelper>(xRangeTunnel);
289 }
290 SwDoc *const pDocument =
291 pRange ? &pRange->GetDoc() : (pCursor ? pCursor->GetDoc() : nullptr);
292 if (!pDocument)
293 {
294 throw lang::IllegalArgumentException();
295 }
296
297 SwUnoInternalPaM aPam(*pDocument);
298 // this now needs to return TRUE
299 ::sw::XTextRangeToSwPaM(aPam, xTextRange);
300 m_pImpl->InsertRefMark(aPam, dynamic_cast<SwXTextCursor*>(pCursor));
301 m_pImpl->m_bIsDescriptor = false;
302 m_pImpl->m_pDoc = pDocument;
303}
304
305uno::Reference< text::XTextRange > SAL_CALL
306SwXReferenceMark::getAnchor()
307{
308 SolarMutexGuard aGuard;
309
310 if (m_pImpl->IsValid())
311 {
312 SwFormatRefMark const*const pNewMark =
313 m_pImpl->m_pDoc->GetRefMark(m_pImpl->m_sMarkName);
314 if (pNewMark && (pNewMark == m_pImpl->m_pMarkFormat))
315 {
316 SwTextRefMark const*const pTextMark =
317 m_pImpl->m_pMarkFormat->GetTextRefMark();
318 if (pTextMark &&
319 (&pTextMark->GetTextNode().GetNodes() ==
320 &m_pImpl->m_pDoc->GetNodes()))
321 {
322 SwTextNode const& rTextNode = pTextMark->GetTextNode();
323 const std::unique_ptr<SwPaM> pPam( (pTextMark->End())
324 ? new SwPaM( rTextNode, *pTextMark->End(),
325 rTextNode, pTextMark->GetStart())
326 : new SwPaM( rTextNode, pTextMark->GetStart()) );
327
328 return SwXTextRange::CreateXTextRange(
329 *m_pImpl->m_pDoc, *pPam->Start(), pPam->End());
330 }
331 }
332 }
333 return nullptr;
334}
335
336void SAL_CALL SwXReferenceMark::dispose()
337{
338 SolarMutexGuard aGuard;
339 if (m_pImpl->IsValid())
340 {
341 SwFormatRefMark const*const pNewMark =
342 m_pImpl->m_pDoc->GetRefMark(m_pImpl->m_sMarkName);
343 if (pNewMark && (pNewMark == m_pImpl->m_pMarkFormat))
344 {
345 SwTextRefMark const*const pTextMark =
346 m_pImpl->m_pMarkFormat->GetTextRefMark();
347 if (pTextMark &&
348 (&pTextMark->GetTextNode().GetNodes() ==
349 &m_pImpl->m_pDoc->GetNodes()))
350 {
351 SwTextNode const& rTextNode = pTextMark->GetTextNode();
352 const sal_Int32 nStt = pTextMark->GetStart();
353 const sal_Int32 nEnd = pTextMark->End()
354 ? *pTextMark->End()
355 : nStt + 1;
356
357 SwPaM aPam( rTextNode, nStt, rTextNode, nEnd );
358 m_pImpl->m_pDoc->getIDocumentContentOperations().DeleteAndJoin( aPam );
359 }
360 }
361 }
362 else if (m_pImpl->m_bIsDescriptor)
363 {
364 m_pImpl->Invalidate();
365 }
366}
367
368void SAL_CALL SwXReferenceMark::addEventListener(
369 const uno::Reference< lang::XEventListener > & xListener)
370{
371 // no need to lock here as m_pImpl is const and container threadsafe
372 m_pImpl->m_EventListeners.addInterface(xListener);
373}
374
375void SAL_CALL SwXReferenceMark::removeEventListener(
376 const uno::Reference< lang::XEventListener > & xListener)
377{
378 // no need to lock here as m_pImpl is const and container threadsafe
379 m_pImpl->m_EventListeners.removeInterface(xListener);
380}
381
382OUString SAL_CALL SwXReferenceMark::getName()
383{
384 SolarMutexGuard aGuard;
385 if (!m_pImpl->IsValid() ||
386 !m_pImpl->m_pDoc->GetRefMark(m_pImpl->m_sMarkName))
387 {
388 throw uno::RuntimeException();
389 }
390 return m_pImpl->m_sMarkName;
391}
392
393void SAL_CALL SwXReferenceMark::setName(const OUString& rName)
394{
395 SolarMutexGuard aGuard;
396 if (m_pImpl->m_bIsDescriptor)
397 {
398 m_pImpl->m_sMarkName = rName;
399 }
400 else
401 {
402 if (!m_pImpl->IsValid()
403 || !m_pImpl->m_pDoc->GetRefMark(m_pImpl->m_sMarkName)
404 || m_pImpl->m_pDoc->GetRefMark(rName))
405 {
406 throw uno::RuntimeException();
407 }
408 SwFormatRefMark const*const pCurMark =
409 m_pImpl->m_pDoc->GetRefMark(m_pImpl->m_sMarkName);
410 if ((rName != m_pImpl->m_sMarkName)
411 && pCurMark && (pCurMark == m_pImpl->m_pMarkFormat))
412 {
413 const UnoActionContext aCont(m_pImpl->m_pDoc);
414 SwTextRefMark const*const pTextMark =
415 m_pImpl->m_pMarkFormat->GetTextRefMark();
416 if (pTextMark &&
417 (&pTextMark->GetTextNode().GetNodes() ==
418 &m_pImpl->m_pDoc->GetNodes()))
419 {
420 SwTextNode const& rTextNode = pTextMark->GetTextNode();
421 const sal_Int32 nStt = pTextMark->GetStart();
422 const sal_Int32 nEnd = pTextMark->End()
423 ? *pTextMark->End()
424 : nStt + 1;
425
426 SwPaM aPam( rTextNode, nStt, rTextNode, nEnd );
427 // deletes the m_pImpl->m_pDoc member in the SwXReferenceMark!
428 m_pImpl->m_pDoc->getIDocumentContentOperations().DeleteAndJoin( aPam );
429 // The aPam will keep the correct and functional doc though
430
431 m_pImpl->m_sMarkName = rName;
432 //create a new one
433 m_pImpl->InsertRefMark( aPam, nullptr );
434 m_pImpl->m_pDoc = &aPam.GetDoc();
435 }
436 }
437 }
438}
439
440uno::Reference< beans::XPropertySetInfo > SAL_CALL
441SwXReferenceMark::getPropertySetInfo()
442{
443 SolarMutexGuard g;
444
445 static uno::Reference< beans::XPropertySetInfo > xRef =
446 aSwMapProvider.GetPropertySet(PROPERTY_MAP_PARAGRAPH_EXTENSIONS24)
447 ->getPropertySetInfo();
448 return xRef;
449}
450
451void SAL_CALL SwXReferenceMark::setPropertyValue(
452 const OUString& /*rPropertyName*/, const uno::Any& /*rValue*/ )
453{
454 throw lang::IllegalArgumentException();
455}
456
457uno::Any SAL_CALL
458SwXReferenceMark::getPropertyValue(const OUString& rPropertyName)
459{
460 // does not seem to need SolarMutex
461 uno::Any aRet;
462 if (! ::sw::GetDefaultTextContentValue(aRet, rPropertyName))
463 {
464 throw beans::UnknownPropertyException(rPropertyName);
465 }
466 return aRet;
467}
468
469void SAL_CALL SwXReferenceMark::addPropertyChangeListener(
470 const OUString& /*rPropertyName*/,
471 const uno::Reference< beans::XPropertyChangeListener >& /*xListener*/)
472{
473 OSL_FAIL("SwXReferenceMark::addPropertyChangeListener(): not implemented")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/unocore/unorefmk.cxx"
":" "473" ": "), "%s", "SwXReferenceMark::addPropertyChangeListener(): not implemented"
); } } while (false)
;
474}
475
476void SAL_CALL SwXReferenceMark::removePropertyChangeListener(
477 const OUString& /*rPropertyName*/,
478 const uno::Reference< beans::XPropertyChangeListener >& /*xListener*/)
479{
480 OSL_FAIL("SwXReferenceMark::removePropertyChangeListener(): not implemented")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/unocore/unorefmk.cxx"
":" "480" ": "), "%s", "SwXReferenceMark::removePropertyChangeListener(): not implemented"
); } } while (false)
;
481}
482
483void SAL_CALL SwXReferenceMark::addVetoableChangeListener(
484 const OUString& /*rPropertyName*/,
485 const uno::Reference< beans::XVetoableChangeListener >& /*xListener*/)
486{
487 OSL_FAIL("SwXReferenceMark::addVetoableChangeListener(): not implemented")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/unocore/unorefmk.cxx"
":" "487" ": "), "%s", "SwXReferenceMark::addVetoableChangeListener(): not implemented"
); } } while (false)
;
488}
489
490void SAL_CALL SwXReferenceMark::removeVetoableChangeListener(
491 const OUString& /*rPropertyName*/,
492 const uno::Reference< beans::XVetoableChangeListener >& /*xListener*/)
493{
494 OSL_FAIL("SwXReferenceMark::removeVetoableChangeListener(): not implemented")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/unocore/unorefmk.cxx"
":" "494" ": "), "%s", "SwXReferenceMark::removeVetoableChangeListener(): not implemented"
); } } while (false)
;
495}
496
497namespace {
498
499class SwXMetaText : public cppu::OWeakObject, public SwXText
500{
501private:
502 SwXMeta & m_rMeta;
503
504 virtual void PrepareForAttach(uno::Reference< text::XTextRange > & xRange,
505 const SwPaM & rPam) override;
506
507 virtual bool CheckForOwnMemberMeta(const SwPaM & rPam, const bool bAbsorb) override;
508
509protected:
510 virtual const SwStartNode *GetStartNode() const override;
511 virtual uno::Reference< text::XTextCursor >
512 CreateCursor() override;
513
514public:
515 SwXMetaText(SwDoc & rDoc, SwXMeta & rMeta);
516
517 /// make available for SwXMeta
518 using SwXText::Invalidate;
519
520 // XInterface
521 virtual void SAL_CALL acquire() throw() override { cppu::OWeakObject::acquire(); }
522 virtual void SAL_CALL release() throw() override { cppu::OWeakObject::release(); }
523
524 // XTypeProvider
525 virtual uno::Sequence< sal_Int8 > SAL_CALL
526 getImplementationId() override;
527
528 // XText
529 virtual uno::Reference< text::XTextCursor > SAL_CALL
530 createTextCursor() override;
531 virtual uno::Reference< text::XTextCursor > SAL_CALL
532 createTextCursorByRange(
533 const uno::Reference< text::XTextRange > & xTextPosition) override;
534
535};
536
537}
538
539SwXMetaText::SwXMetaText(SwDoc & rDoc, SwXMeta & rMeta)
540 : SwXText(&rDoc, CursorType::Meta)
541 , m_rMeta(rMeta)
542{
543}
544
545const SwStartNode *SwXMetaText::GetStartNode() const
546{
547 SwXText const * const pParent(
548 dynamic_cast<SwXText*>(m_rMeta.GetParentText().get()));
549 return pParent ? pParent->GetStartNode() : nullptr;
550}
551
552void SwXMetaText::PrepareForAttach( uno::Reference<text::XTextRange> & xRange,
553 const SwPaM & rPam)
554{
555 // create a new cursor to prevent modifying SwXTextRange
556 xRange = static_cast<text::XWordCursor*>(
557 new SwXTextCursor(*GetDoc(), &m_rMeta, CursorType::Meta, *rPam.GetPoint(),
558 (rPam.HasMark()) ? rPam.GetMark() : nullptr));
559}
560
561bool SwXMetaText::CheckForOwnMemberMeta(const SwPaM & rPam, const bool bAbsorb)
562{
563 return m_rMeta.CheckForOwnMemberMeta(rPam, bAbsorb);
564}
565
566uno::Reference< text::XTextCursor > SwXMetaText::CreateCursor()
567{
568 uno::Reference< text::XTextCursor > xRet;
569 if (IsValid())
570 {
571 SwTextNode * pTextNode;
572 sal_Int32 nMetaStart;
573 sal_Int32 nMetaEnd;
574 const bool bSuccess(
575 m_rMeta.SetContentRange(pTextNode, nMetaStart, nMetaEnd) );
576 if (bSuccess)
577 {
578 SwPosition aPos(*pTextNode, nMetaStart);
579 xRet = static_cast<text::XWordCursor*>(
580 new SwXTextCursor(*GetDoc(), &m_rMeta, CursorType::Meta, aPos));
581 }
582 }
583 return xRet;
584}
585
586uno::Sequence<sal_Int8> SAL_CALL
587SwXMetaText::getImplementationId()
588{
589 return css::uno::Sequence<sal_Int8>();
590}
591
592// XText
593uno::Reference< text::XTextCursor > SAL_CALL
594SwXMetaText::createTextCursor()
595{
596 return CreateCursor();
597}
598
599uno::Reference< text::XTextCursor > SAL_CALL
600SwXMetaText::createTextCursorByRange(
601 const uno::Reference<text::XTextRange> & xTextPosition)
602{
603 const uno::Reference<text::XTextCursor> xCursor( CreateCursor() );
604 xCursor->gotoRange(xTextPosition, false);
605 return xCursor;
606}
607
608// the Meta has a cached list of text portions for its contents
609// this list is created by SwXTextPortionEnumeration
610// the Meta listens at the SwTextNode and throws away the cache when it changes
611class SwXMeta::Impl : public SvtListener
612{
613private:
614 ::osl::Mutex m_Mutex; // just for OInterfaceContainerHelper2
615
616public:
617 uno::WeakReference<uno::XInterface> m_wThis;
618 ::comphelper::OInterfaceContainerHelper2 m_EventListeners;
619 std::unique_ptr<const TextRangeList_t> m_pTextPortions;
620 // 3 possible states: not attached, attached, disposed
621 bool m_bIsDisposed;
622 bool m_bIsDescriptor;
623 uno::Reference<text::XText> m_xParentText;
624 rtl::Reference<SwXMetaText> m_xText;
625 sw::Meta* m_pMeta;
626
627 Impl(SwXMeta& rThis, SwDoc& rDoc,
628 ::sw::Meta* const pMeta,
629 uno::Reference<text::XText> const& xParentText,
630 std::unique_ptr<TextRangeList_t const> pPortions)
631 : m_EventListeners(m_Mutex)
632 , m_pTextPortions(std::move(pPortions))
633 , m_bIsDisposed(false)
634 , m_bIsDescriptor(nullptr == pMeta)
635 , m_xParentText(xParentText)
636 , m_xText(new SwXMetaText(rDoc, rThis))
637 , m_pMeta(pMeta)
638 {
639 !m_bIsDescriptor && StartListening(m_pMeta->GetNotifier());
640 }
641
642 inline const ::sw::Meta* GetMeta() const;
643 // only for SwXMetaField!
644 inline const ::sw::MetaField* GetMetaField() const;
645protected:
646 virtual void Notify(const SfxHint& rHint) override;
647
648};
649
650inline const ::sw::Meta* SwXMeta::Impl::GetMeta() const
651{
652 return m_pMeta;
653}
654
655// SwModify
656void SwXMeta::Impl::Notify(const SfxHint& rHint)
657{
658 m_pTextPortions.reset(); // throw away cache (SwTextNode changed)
659 if(rHint.GetId() != SfxHintId::Dying && rHint.GetId() != SfxHintId::Deinitializing)
660 return;
661
662 m_bIsDisposed = true;
663 m_pMeta = nullptr;
664 m_xText->Invalidate();
665 uno::Reference<uno::XInterface> const xThis(m_wThis);
666 if (!xThis.is())
667 { // fdo#72695: if UNO object is already dead, don't revive it with event
668 return;
669 }
670 lang::EventObject const ev(xThis);
671 m_EventListeners.disposeAndClear(ev);
672}
673
674uno::Reference<text::XText> const & SwXMeta::GetParentText() const
675{
676 return m_pImpl->m_xParentText;
677}
678
679SwXMeta::SwXMeta(SwDoc *const pDoc, ::sw::Meta *const pMeta,
680 uno::Reference<text::XText> const& xParentText,
681 std::unique_ptr<TextRangeList_t const> pPortions)
682 : m_pImpl( new SwXMeta::Impl(*this, *pDoc, pMeta, xParentText, std::move(pPortions)) )
683{
684}
685
686SwXMeta::SwXMeta(SwDoc *const pDoc)
687 : m_pImpl( new SwXMeta::Impl(*this, *pDoc, nullptr, nullptr, nullptr) )
688{
689}
690
691SwXMeta::~SwXMeta()
692{
693}
694
695uno::Reference<rdf::XMetadatable>
696SwXMeta::CreateXMeta(SwDoc & rDoc, bool const isField)
697{
698 SwXMeta *const pXMeta(isField
699 ? new SwXMetaField(& rDoc) : new SwXMeta(& rDoc));
700 // this is why the constructor is private: need to acquire pXMeta here
701 uno::Reference<rdf::XMetadatable> const xMeta(pXMeta);
702 // need a permanent Reference to initialize m_wThis
703 pXMeta->m_pImpl->m_wThis = xMeta;
704 return xMeta;
705}
706
707uno::Reference<rdf::XMetadatable>
708SwXMeta::CreateXMeta(::sw::Meta & rMeta,
709 uno::Reference<text::XText> const& i_xParent,
710 std::unique_ptr<TextRangeList_t const> && pPortions)
711{
712 // re-use existing SwXMeta
713 // #i105557#: do not iterate over the registered clients: race condition
714 uno::Reference<rdf::XMetadatable> xMeta(rMeta.GetXMeta());
715 if (xMeta.is())
716 {
717 if (pPortions) // set cache in the XMeta to the given portions
718 {
719 SwXMeta *const pXMeta(
720 comphelper::getUnoTunnelImplementation<SwXMeta>(xMeta));
721 assert(pXMeta)(static_cast <bool> (pXMeta) ? void (0) : __assert_fail
("pXMeta", "/home/maarten/src/libreoffice/core/sw/source/core/unocore/unorefmk.cxx"
, 721, __extension__ __PRETTY_FUNCTION__))
;
722 // NB: the meta must always be created with the complete content
723 // if SwXTextPortionEnumeration is created for a selection,
724 // it must be checked that the Meta is contained in the selection!
725 pXMeta->m_pImpl->m_pTextPortions = std::move(pPortions);
726 // ??? is this necessary?
727 if (pXMeta->m_pImpl->m_xParentText.get() != i_xParent.get())
728 {
729 SAL_WARN("sw.uno", "SwXMeta with different parent?")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "sw.uno")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "SwXMeta with different parent?"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.uno"
), ("/home/maarten/src/libreoffice/core/sw/source/core/unocore/unorefmk.cxx"
":" "729" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "SwXMeta with different parent?"), 0);
} else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "SwXMeta with different parent?"; ::sal::detail::log
( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.uno"), ("/home/maarten/src/libreoffice/core/sw/source/core/unocore/unorefmk.cxx"
":" "729" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "SwXMeta with different parent?") == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.uno"), ("/home/maarten/src/libreoffice/core/sw/source/core/unocore/unorefmk.cxx"
":" "729" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "SwXMeta with different parent?"), 0);
} else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "SwXMeta with different parent?"; ::sal::detail::log
( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.uno"), ("/home/maarten/src/libreoffice/core/sw/source/core/unocore/unorefmk.cxx"
":" "729" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
730 pXMeta->m_pImpl->m_xParentText.set(i_xParent);
731 }
732 }
733 return xMeta;
734 }
735
736 // create new SwXMeta
737 SwTextNode * const pTextNode( rMeta.GetTextNode() );
738 SAL_WARN_IF(!pTextNode, "sw.uno", "CreateXMeta: no text node?")do { if (true && (!pTextNode)) { switch (sal_detail_log_report
(::SAL_DETAIL_LOG_LEVEL_WARN, "sw.uno")) { case SAL_DETAIL_LOG_ACTION_IGNORE
: break; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail
::getResult( ::sal::detail::StreamStart() << "CreateXMeta: no text node?"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.uno"
), ("/home/maarten/src/libreoffice/core/sw/source/core/unocore/unorefmk.cxx"
":" "738" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "CreateXMeta: no text node?"), 0); } else
{ ::std::ostringstream sal_detail_stream; sal_detail_stream <<
"CreateXMeta: no text node?"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw.uno"), ("/home/maarten/src/libreoffice/core/sw/source/core/unocore/unorefmk.cxx"
":" "738" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "CreateXMeta: no text node?") == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.uno"), ("/home/maarten/src/libreoffice/core/sw/source/core/unocore/unorefmk.cxx"
":" "738" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "CreateXMeta: no text node?"), 0); } else
{ ::std::ostringstream sal_detail_stream; sal_detail_stream <<
"CreateXMeta: no text node?"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw.uno"), ("/home/maarten/src/libreoffice/core/sw/source/core/unocore/unorefmk.cxx"
":" "738" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
739 if (!pTextNode) { return nullptr; }
740 uno::Reference<text::XText> xParentText(i_xParent);
741 if (!xParentText.is())
742 {
743 SwTextMeta * const pTextAttr( rMeta.GetTextAttr() );
744 SAL_WARN_IF(!pTextAttr, "sw.uno", "CreateXMeta: no text attr?")do { if (true && (!pTextAttr)) { switch (sal_detail_log_report
(::SAL_DETAIL_LOG_LEVEL_WARN, "sw.uno")) { case SAL_DETAIL_LOG_ACTION_IGNORE
: break; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail
::getResult( ::sal::detail::StreamStart() << "CreateXMeta: no text attr?"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.uno"
), ("/home/maarten/src/libreoffice/core/sw/source/core/unocore/unorefmk.cxx"
":" "744" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "CreateXMeta: no text attr?"), 0); } else
{ ::std::ostringstream sal_detail_stream; sal_detail_stream <<
"CreateXMeta: no text attr?"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw.uno"), ("/home/maarten/src/libreoffice/core/sw/source/core/unocore/unorefmk.cxx"
":" "744" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "CreateXMeta: no text attr?") == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.uno"), ("/home/maarten/src/libreoffice/core/sw/source/core/unocore/unorefmk.cxx"
":" "744" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "CreateXMeta: no text attr?"), 0); } else
{ ::std::ostringstream sal_detail_stream; sal_detail_stream <<
"CreateXMeta: no text attr?"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw.uno"), ("/home/maarten/src/libreoffice/core/sw/source/core/unocore/unorefmk.cxx"
":" "744" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
745 if (!pTextAttr) { return nullptr; }
746 const SwPosition aPos(*pTextNode, pTextAttr->GetStart());
747 xParentText.set( ::sw::CreateParentXText(pTextNode->GetDoc(), aPos) );
748 }
749 if (!xParentText.is()) { return nullptr; }
750 SwXMeta *const pXMeta( (RES_TXTATR_META == rMeta.GetFormatMeta()->Which())
751 ? new SwXMeta (&pTextNode->GetDoc(), &rMeta, xParentText,
752 std::move(pPortions))
753 : new SwXMetaField(&pTextNode->GetDoc(), &rMeta, xParentText,
754 std::move(pPortions)));
755 // this is why the constructor is private: need to acquire pXMeta here
756 xMeta.set(pXMeta);
757 // in order to initialize the weak pointer cache in the core object
758 rMeta.SetXMeta(xMeta);
759 // need a permanent Reference to initialize m_wThis
760 pXMeta->m_pImpl->m_wThis = xMeta;
761 return xMeta;
762}
763
764bool SwXMeta::SetContentRange(
765 SwTextNode *& rpNode, sal_Int32 & rStart, sal_Int32 & rEnd ) const
766{
767 ::sw::Meta const * const pMeta( m_pImpl->GetMeta() );
768 if (pMeta)
769 {
770 SwTextMeta const * const pTextAttr( pMeta->GetTextAttr() );
771 if (pTextAttr)
772 {
773 rpNode = pMeta->GetTextNode();
774 if (rpNode)
775 {
776 // rStart points at the first position _within_ the meta!
777 rStart = pTextAttr->GetStart() + 1;
778 rEnd = *pTextAttr->End();
779 return true;
780 }
781 }
782 }
783 return false;
784}
785
786bool SwXMeta::CheckForOwnMemberMeta(const SwPaM & rPam, const bool bAbsorb)
787{
788 SwTextNode * pTextNode;
789 sal_Int32 nMetaStart;
790 sal_Int32 nMetaEnd;
791 const bool bSuccess( SetContentRange(pTextNode, nMetaStart, nMetaEnd) );
792 OSL_ENSURE(bSuccess, "no pam?")do { if (true && (!(bSuccess))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/unocore/unorefmk.cxx"
":" "792" ": "), "%s", "no pam?"); } } while (false)
;
793 if (!bSuccess)
794 throw lang::DisposedException();
795
796 SwPosition const * const pStartPos( rPam.Start() );
797 if (&pStartPos->nNode.GetNode() != pTextNode)
798 {
799 throw lang::IllegalArgumentException(
800 "trying to insert into a nesting text content, but start "
801 "of text range not in same paragraph as text content",
802 nullptr, 0);
803 }
804 bool bForceExpandHints(false);
805 const sal_Int32 nStartPos(pStartPos->nContent.GetIndex());
806 // not <= but < because nMetaStart is behind dummy char!
807 // not >= but > because == means insert at end!
808 if ((nStartPos < nMetaStart) || (nStartPos > nMetaEnd))
809 {
810 throw lang::IllegalArgumentException(
811 "trying to insert into a nesting text content, but start "
812 "of text range not inside text content",
813 nullptr, 0);
814 }
815 else if (nStartPos == nMetaEnd)
816 {
817 bForceExpandHints = true;
818 }
819 if (rPam.HasMark() && bAbsorb)
820 {
821 SwPosition const * const pEndPos( rPam.End() );
822 if (&pEndPos->nNode.GetNode() != pTextNode)
823 {
824 throw lang::IllegalArgumentException(
825 "trying to insert into a nesting text content, but end "
826 "of text range not in same paragraph as text content",
827 nullptr, 0);
828 }
829 const sal_Int32 nEndPos(pEndPos->nContent.GetIndex());
830 // not <= but < because nMetaStart is behind dummy char!
831 // not >= but > because == means insert at end!
832 if ((nEndPos < nMetaStart) || (nEndPos > nMetaEnd))
833 {
834 throw lang::IllegalArgumentException(
835 "trying to insert into a nesting text content, but end "
836 "of text range not inside text content",
837 nullptr, 0);
838 }
839 else if (nEndPos == nMetaEnd)
840 {
841 bForceExpandHints = true;
842 }
843 }
844 return bForceExpandHints;
845}
846
847namespace
848{
849 class theSwXMetaUnoTunnelId : public rtl::Static< UnoTunnelIdInit, theSwXMetaUnoTunnelId > {};
850}
851
852const uno::Sequence< sal_Int8 > & SwXMeta::getUnoTunnelId()
853{
854 return theSwXMetaUnoTunnelId::get().getSeq();
855}
856
857// XUnoTunnel
858sal_Int64 SAL_CALL
859SwXMeta::getSomething( const uno::Sequence< sal_Int8 > & i_rId )
860{
861 return ::sw::UnoTunnelImpl<SwXMeta>(i_rId, this);
862}
863
864// XServiceInfo
865OUString SAL_CALL
866SwXMeta::getImplementationName()
867{
868 return "SwXMeta";
869}
870
871sal_Bool SAL_CALL
872SwXMeta::supportsService(const OUString& rServiceName)
873{
874 return cppu::supportsService(this, rServiceName);
875}
876
877uno::Sequence< OUString > SAL_CALL
878SwXMeta::getSupportedServiceNames()
879{
880 return {
881 "com.sun.star.text.TextContent",
882 "com.sun.star.text.InContentMetadata"
883 };
884}
885
886// XComponent
887void SAL_CALL
888SwXMeta::addEventListener(
889 uno::Reference< lang::XEventListener> const & xListener )
890{
891 // no need to lock here as m_pImpl is const and container threadsafe
892 m_pImpl->m_EventListeners.addInterface(xListener);
893}
894
895void SAL_CALL
896SwXMeta::removeEventListener(
897 uno::Reference< lang::XEventListener> const & xListener )
898{
899 // no need to lock here as m_pImpl is const and container threadsafe
900 m_pImpl->m_EventListeners.removeInterface(xListener);
901}
902
903void SAL_CALL
904SwXMeta::dispose()
905{
906 SolarMutexGuard g;
907
908 if (m_pImpl->m_bIsDescriptor)
909 {
910 m_pImpl->m_pTextPortions.reset();
911 lang::EventObject const ev(static_cast< ::cppu::OWeakObject&>(*this));
912 m_pImpl->m_EventListeners.disposeAndClear(ev);
913 m_pImpl->m_bIsDisposed = true;
914 m_pImpl->m_xText->Invalidate();
915 }
916 else if (!m_pImpl->m_bIsDisposed)
917 {
918 SwTextNode * pTextNode;
919 sal_Int32 nMetaStart;
920 sal_Int32 nMetaEnd;
921 const bool bSuccess(SetContentRange(pTextNode, nMetaStart, nMetaEnd));
922 OSL_ENSURE(bSuccess, "no pam?")do { if (true && (!(bSuccess))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/unocore/unorefmk.cxx"
":" "922" ": "), "%s", "no pam?"); } } while (false)
;
923 if (bSuccess)
924 {
925 // -1 because of CH_TXTATR
926 SwPaM aPam( *pTextNode, nMetaStart - 1, *pTextNode, nMetaEnd );
927 SwDoc& rDoc( pTextNode->GetDoc() );
928 rDoc.getIDocumentContentOperations().DeleteAndJoin( aPam );
929
930 // removal should call Modify and do the dispose
931 assert(m_pImpl->m_bIsDisposed)(static_cast <bool> (m_pImpl->m_bIsDisposed) ? void (
0) : __assert_fail ("m_pImpl->m_bIsDisposed", "/home/maarten/src/libreoffice/core/sw/source/core/unocore/unorefmk.cxx"
, 931, __extension__ __PRETTY_FUNCTION__))
;
932 }
933 }
934}
935
936void
937SwXMeta::AttachImpl(const uno::Reference< text::XTextRange > & i_xTextRange,
938 const sal_uInt16 i_nWhich)
939{
940 SolarMutexGuard g;
941
942 if (m_pImpl->m_bIsDisposed)
2
Assuming field 'm_bIsDisposed' is false
3
Taking false branch
943 {
944 throw lang::DisposedException();
945 }
946 if (!m_pImpl->m_bIsDescriptor)
4
Assuming field 'm_bIsDescriptor' is true
5
Taking false branch
947 {
948 throw uno::RuntimeException(
949 "SwXMeta::attach(): already attached",
950 static_cast< ::cppu::OWeakObject* >(this));
951 }
952
953 uno::Reference<lang::XUnoTunnel> xRangeTunnel(i_xTextRange, uno::UNO_QUERY);
954 if (!xRangeTunnel.is())
6
Taking false branch
955 {
956 throw lang::IllegalArgumentException(
957 "SwXMeta::attach(): argument is no XUnoTunnel",
958 static_cast< ::cppu::OWeakObject* >(this), 0);
959 }
960 SwXTextRange *const pRange(
961 ::sw::UnoTunnelGetImplementation<SwXTextRange>(xRangeTunnel));
962 OTextCursorHelper *const pCursor( pRange ? nullptr :
7
Assuming 'pRange' is non-null
8
'?' condition is true
963 ::sw::UnoTunnelGetImplementation<OTextCursorHelper>(xRangeTunnel));
964 if (!pRange
8.1
'pRange' is non-null
8.1
'pRange' is non-null
8.1
'pRange' is non-null
8.1
'pRange' is non-null
8.1
'pRange' is non-null
8.1
'pRange' is non-null
&& !pCursor)
965 {
966 throw lang::IllegalArgumentException(
967 "SwXMeta::attach(): argument not supported type",
968 static_cast< ::cppu::OWeakObject* >(this), 0);
969 }
970
971 SwDoc * const pDoc(
972 pRange
8.2
'pRange' is non-null
8.2
'pRange' is non-null
8.2
'pRange' is non-null
8.2
'pRange' is non-null
8.2
'pRange' is non-null
8.2
'pRange' is non-null
? &pRange->GetDoc() : pCursor->GetDoc());
9
'?' condition is true
973 if (!pDoc
9.1
'pDoc' is non-null
9.1
'pDoc' is non-null
9.1
'pDoc' is non-null
9.1
'pDoc' is non-null
9.1
'pDoc' is non-null
9.1
'pDoc' is non-null
)
10
Taking false branch
974 {
975 throw lang::IllegalArgumentException(
976 "SwXMeta::attach(): argument has no SwDoc",
977 static_cast< ::cppu::OWeakObject* >(this), 0);
978 }
979
980 SwUnoInternalPaM aPam(*pDoc);
981 ::sw::XTextRangeToSwPaM(aPam, i_xTextRange);
982
983 UnoActionContext aContext(pDoc);
984
985 SwXTextCursor const*const pTextCursor(
986 dynamic_cast<SwXTextCursor*>(pCursor));
987 const bool bForceExpandHints(pTextCursor
10.1
'pTextCursor' is null
10.1
'pTextCursor' is null
10.1
'pTextCursor' is null
10.1
'pTextCursor' is null
10.1
'pTextCursor' is null
10.1
'pTextCursor' is null
&& pTextCursor->IsAtEndOfMeta());
988 const SetAttrMode nInsertFlags( bForceExpandHints
10.2
'bForceExpandHints' is false
10.2
'bForceExpandHints' is false
10.2
'bForceExpandHints' is false
10.2
'bForceExpandHints' is false
10.2
'bForceExpandHints' is false
10.2
'bForceExpandHints' is false
11
'?' condition is false
989 ? ( SetAttrMode::FORCEHINTEXPAND 990 | SetAttrMode::DONTEXPAND) 991 : SetAttrMode::DONTEXPAND ); 992 993 const std::shared_ptr< ::sw::Meta> pMeta( (RES_TXTATR_META == i_nWhich)
12
'?' condition is true
994 ? std::make_shared< ::sw::Meta>( nullptr )
13
Calling 'make_shared<sw::Meta, nullptr_t>'
31
Returned allocated memory
995 : std::shared_ptr< ::sw::Meta>( 996 pDoc->GetMetaFieldManager().makeMetaField()) ); 997 SwFormatMeta meta(pMeta, i_nWhich); // this is cloned by Insert! 998 const bool bSuccess( pDoc->getIDocumentContentOperations().InsertPoolItem( aPam, meta, nInsertFlags ) ); 999 SwTextAttr * const pTextAttr( pMeta->GetTextAttr() ); 1000 if (!bSuccess)
32
Assuming 'bSuccess' is true
33
Taking false branch
1001 { 1002 throw lang::IllegalArgumentException( 1003 "SwXMeta::attach(): cannot create meta: range invalid?", 1004 static_cast< ::cppu::OWeakObject* >(this), 1); 1005 } 1006 if (!pTextAttr)
34
Assuming 'pTextAttr' is non-null
35
Taking false branch
1007 { 1008 OSL_FAIL("meta inserted, but has no text attribute?")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/unocore/unorefmk.cxx"
":" "1008" ": "), "%s", "meta inserted, but has no text attribute?"
); } } while (false)
; 1009 throw uno::RuntimeException( 1010 "SwXMeta::attach(): cannot create meta", 1011 static_cast< ::cppu::OWeakObject* >(this)); 1012 } 1013 1014 m_pImpl->EndListeningAll(); 1015 m_pImpl->m_pMeta = pMeta.get(); 1016 m_pImpl->StartListening(pMeta->GetNotifier()); 1017 pMeta->SetXMeta(uno::Reference<rdf::XMetadatable>(this)); 1018 1019 m_pImpl->m_xParentText = ::sw::CreateParentXText(*pDoc, *aPam.GetPoint()); 1020 1021 m_pImpl->m_bIsDescriptor = false; 1022}
36
Potential leak of memory pointed to by field '_M_pi'
1023 1024// XTextContent 1025void SAL_CALL 1026SwXMeta::attach(const uno::Reference< text::XTextRange > & i_xTextRange) 1027{ 1028 return SwXMeta::AttachImpl(i_xTextRange, RES_TXTATR_META); 1029} 1030 1031uno::Reference< text::XTextRange > SAL_CALL 1032SwXMeta::getAnchor() 1033{ 1034 SolarMutexGuard g; 1035 1036 if (m_pImpl->m_bIsDisposed) 1037 { 1038 throw lang::DisposedException(); 1039 } 1040 if (m_pImpl->m_bIsDescriptor) 1041 { 1042 throw uno::RuntimeException( 1043 "SwXMeta::getAnchor(): not inserted", 1044 static_cast< ::cppu::OWeakObject* >(this)); 1045 } 1046 1047 SwTextNode * pTextNode; 1048 sal_Int32 nMetaStart; 1049 sal_Int32 nMetaEnd; 1050 const bool bSuccess(SetContentRange(pTextNode, nMetaStart, nMetaEnd)); 1051 OSL_ENSURE(bSuccess, "no pam?")do { if (true && (!(bSuccess))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/unocore/unorefmk.cxx"
":" "1051" ": "), "%s", "no pam?"); } } while (false)
; 1052 if (!bSuccess) 1053 { 1054 throw lang::DisposedException( 1055 "SwXMeta::getAnchor(): not attached", 1056 static_cast< ::cppu::OWeakObject* >(this)); 1057 } 1058 1059 const SwPosition start(*pTextNode, nMetaStart - 1); // -1 due to CH_TXTATR 1060 const SwPosition end(*pTextNode, nMetaEnd); 1061 return SwXTextRange::CreateXTextRange(pTextNode->GetDoc(), start, &end); 1062} 1063 1064// XTextRange 1065uno::Reference< text::XText > SAL_CALL 1066SwXMeta::getText() 1067{ 1068 return this; 1069} 1070 1071uno::Reference< text::XTextRange > SAL_CALL 1072SwXMeta::getStart() 1073{ 1074 SolarMutexGuard g; 1075 return m_pImpl->m_xText->getStart(); 1076} 1077 1078uno::Reference< text::XTextRange > SAL_CALL 1079SwXMeta::getEnd() 1080{ 1081 SolarMutexGuard g; 1082 return m_pImpl->m_xText->getEnd(); 1083} 1084 1085OUString SAL_CALL 1086SwXMeta::getString() 1087{ 1088 SolarMutexGuard g; 1089 return m_pImpl->m_xText->getString(); 1090} 1091 1092void SAL_CALL 1093SwXMeta::setString(const OUString& rString) 1094{ 1095 SolarMutexGuard g; 1096 return m_pImpl->m_xText->setString(rString); 1097} 1098 1099// XSimpleText 1100uno::Reference< text::XTextCursor > SAL_CALL 1101SwXMeta::createTextCursor() 1102{ 1103 SolarMutexGuard g; 1104 return m_pImpl->m_xText->createTextCursor(); 1105} 1106 1107uno::Reference< text::XTextCursor > SAL_CALL 1108SwXMeta::createTextCursorByRange( 1109 const uno::Reference<text::XTextRange> & xTextPosition) 1110{ 1111 SolarMutexGuard g; 1112 return m_pImpl->m_xText->createTextCursorByRange(xTextPosition); 1113} 1114 1115void SAL_CALL 1116SwXMeta::insertString(const uno::Reference<text::XTextRange> & xRange, 1117 const OUString& rString, sal_Bool bAbsorb) 1118{ 1119 SolarMutexGuard g; 1120 return m_pImpl->m_xText->insertString(xRange, rString, bAbsorb); 1121} 1122 1123void SAL_CALL 1124SwXMeta::insertControlCharacter(const uno::Reference<text::XTextRange> & xRange, 1125 sal_Int16 nControlCharacter, sal_Bool bAbsorb) 1126{ 1127 SolarMutexGuard g; 1128 return m_pImpl->m_xText->insertControlCharacter(xRange, nControlCharacter, 1129 bAbsorb); 1130} 1131 1132// XText 1133void SAL_CALL 1134SwXMeta::insertTextContent( const uno::Reference<text::XTextRange> & xRange, 1135 const uno::Reference<text::XTextContent> & xContent, sal_Bool bAbsorb) 1136{ 1137 SolarMutexGuard g; 1138 return m_pImpl->m_xText->insertTextContent(xRange, xContent, bAbsorb); 1139} 1140 1141void SAL_CALL 1142SwXMeta::removeTextContent( 1143 const uno::Reference< text::XTextContent > & xContent) 1144{ 1145 SolarMutexGuard g; 1146 return m_pImpl->m_xText->removeTextContent(xContent); 1147} 1148 1149// XChild 1150uno::Reference< uno::XInterface > SAL_CALL 1151SwXMeta::getParent() 1152{ 1153 SolarMutexGuard g; 1154 SwTextNode * pTextNode; 1155 sal_Int32 nMetaStart; 1156 sal_Int32 nMetaEnd; 1157 bool const bSuccess( SetContentRange(pTextNode, nMetaStart, nMetaEnd) ); 1158 OSL_ENSURE(bSuccess, "no pam?")do { if (true && (!(bSuccess))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/unocore/unorefmk.cxx"
":" "1158" ": "), "%s", "no pam?"); } } while (false)
; 1159 if (!bSuccess) { throw lang::DisposedException(); } 1160 // in order to prevent getting this meta, subtract 1 from nMetaStart; 1161 // so we get the index of the dummy character, and we exclude it 1162 // by calling GetTextAttrAt(_, _, PARENT) in GetNestedTextContent 1163 uno::Reference<text::XTextContent> const xRet( 1164 SwUnoCursorHelper::GetNestedTextContent(*pTextNode, nMetaStart - 1, 1165 true) ); 1166 return xRet; 1167} 1168 1169void SAL_CALL 1170SwXMeta::setParent(uno::Reference< uno::XInterface > const& /*xParent*/) 1171{ 1172 throw lang::NoSupportException("setting parent not supported", *this); 1173} 1174 1175// XElementAccess 1176uno::Type SAL_CALL 1177SwXMeta::getElementType() 1178{ 1179 return cppu::UnoType<text::XTextRange>::get(); 1180} 1181 1182sal_Bool SAL_CALL SwXMeta::hasElements() 1183{ 1184 SolarMutexGuard g; 1185 return m_pImpl->m_pMeta != nullptr; 1186} 1187 1188// XEnumerationAccess 1189uno::Reference< container::XEnumeration > SAL_CALL 1190SwXMeta::createEnumeration() 1191{ 1192 SolarMutexGuard g; 1193 1194 if (m_pImpl->m_bIsDisposed) 1195 { 1196 throw lang::DisposedException(); 1197 } 1198 if (m_pImpl->m_bIsDescriptor) 1199 { 1200 throw uno::RuntimeException( 1201 "createEnumeration(): not inserted", 1202 static_cast< ::cppu::OWeakObject* >(this)); 1203 } 1204 1205 SwTextNode * pTextNode; 1206 sal_Int32 nMetaStart; 1207 sal_Int32 nMetaEnd; 1208 const bool bSuccess(SetContentRange(pTextNode, nMetaStart, nMetaEnd)); 1209 OSL_ENSURE(bSuccess, "no pam?")do { if (true && (!(bSuccess))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/unocore/unorefmk.cxx"
":" "1209" ": "), "%s", "no pam?"); } } while (false)
; 1210 if (!bSuccess) 1211 throw lang::DisposedException(); 1212 1213 SwPaM aPam(*pTextNode, nMetaStart); 1214 1215 if (!m_pImpl->m_pTextPortions) 1216 { 1217 return new SwXTextPortionEnumeration( 1218 aPam, GetParentText(), nMetaStart, nMetaEnd); 1219 } 1220 else // cached! 1221 { 1222 return new SwXTextPortionEnumeration(aPam, *m_pImpl->m_pTextPortions); 1223 } 1224} 1225 1226// MetadatableMixin 1227::sfx2::Metadatable* SwXMeta::GetCoreObject() 1228{ 1229 return const_cast< ::sw::Meta * >(m_pImpl->GetMeta()); 1230} 1231 1232uno::Reference<frame::XModel> SwXMeta::GetModel() 1233{ 1234 ::sw::Meta const * const pMeta( m_pImpl->GetMeta() ); 1235 if (pMeta) 1236 { 1237 SwTextNode const * const pTextNode( pMeta->GetTextNode() ); 1238 if (pTextNode) 1239 { 1240 SwDocShell const * const pShell(pTextNode->GetDoc().GetDocShell()); 1241 return pShell ? pShell->GetModel() : nullptr; 1242 } 1243 } 1244 return nullptr; 1245} 1246 1247inline const ::sw::MetaField* SwXMeta::Impl::GetMetaField() const 1248{ 1249 return dynamic_cast<sw::MetaField*>(m_pMeta); 1250} 1251 1252SwXMetaField::SwXMetaField(SwDoc *const pDoc, ::sw::Meta *const pMeta, 1253 uno::Reference<text::XText> const& xParentText, 1254 std::unique_ptr<TextRangeList_t const> pPortions) 1255 : SwXMetaField_Base(pDoc, pMeta, xParentText, std::move(pPortions)) 1256{ 1257 OSL_ENSURE(dynamic_cast< ::sw::MetaField* >(pMeta),do { if (true && (!(dynamic_cast< ::sw::MetaField*
>(pMeta)))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/unocore/unorefmk.cxx"
":" "1258" ": "), "%s", "SwXMetaField created for wrong hint!"
); } } while (false)
1258 "SwXMetaField created for wrong hint!")do { if (true && (!(dynamic_cast< ::sw::MetaField*
>(pMeta)))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/unocore/unorefmk.cxx"
":" "1258" ": "), "%s", "SwXMetaField created for wrong hint!"
); } } while (false)
; 1259} 1260 1261SwXMetaField::SwXMetaField(SwDoc *const pDoc) 1262 : SwXMetaField_Base(pDoc) 1263{ 1264} 1265 1266SwXMetaField::~SwXMetaField() 1267{ 1268} 1269 1270// XServiceInfo 1271OUString SAL_CALL 1272SwXMetaField::getImplementationName() 1273{ 1274 return "SwXMetaField"; 1275} 1276 1277sal_Bool SAL_CALL 1278SwXMetaField::supportsService(const OUString& rServiceName) 1279{ 1280 return cppu::supportsService(this, rServiceName); 1281} 1282 1283uno::Sequence< OUString > SAL_CALL 1284SwXMetaField::getSupportedServiceNames() 1285{ 1286 return { 1287 "com.sun.star.text.TextContent", 1288 "com.sun.star.text.TextField", 1289 "com.sun.star.text.textfield.MetadataField" 1290 }; 1291} 1292 1293// XComponent 1294void SAL_CALL 1295SwXMetaField::addEventListener( 1296 uno::Reference< lang::XEventListener> const & xListener ) 1297{ 1298 return SwXMeta::addEventListener(xListener); 1299} 1300 1301void SAL_CALL 1302SwXMetaField::removeEventListener( 1303 uno::Reference< lang::XEventListener> const & xListener ) 1304{ 1305 return SwXMeta::removeEventListener(xListener); 1306} 1307 1308void SAL_CALL 1309SwXMetaField::dispose() 1310{ 1311 return SwXMeta::dispose(); 1312} 1313 1314// XTextContent 1315void SAL_CALL 1316SwXMetaField::attach(const uno::Reference< text::XTextRange > & i_xTextRange) 1317{ 1318 return SwXMeta::AttachImpl(i_xTextRange, RES_TXTATR_METAFIELD);
1
Calling 'SwXMeta::AttachImpl'
1319} 1320 1321uno::Reference< text::XTextRange > SAL_CALL 1322SwXMetaField::getAnchor() 1323{ 1324 return SwXMeta::getAnchor(); 1325} 1326 1327// XPropertySet 1328uno::Reference< beans::XPropertySetInfo > SAL_CALL 1329SwXMetaField::getPropertySetInfo() 1330{ 1331 SolarMutexGuard g; 1332 1333 static uno::Reference< beans::XPropertySetInfo > xRef( 1334 aSwMapProvider.GetPropertySet(PROPERTY_MAP_METAFIELD98) 1335 ->getPropertySetInfo() ); 1336 return xRef; 1337} 1338 1339void SAL_CALL 1340SwXMetaField::setPropertyValue( 1341 const OUString& rPropertyName, const uno::Any& rValue) 1342{ 1343 SolarMutexGuard g; 1344 1345 ::sw::MetaField * const pMeta( 1346 const_cast< ::sw::MetaField * >(m_pImpl->GetMetaField()) ); 1347 if (!pMeta) 1348 throw lang::DisposedException(); 1349 1350 if ( rPropertyName == "NumberFormat" ) 1351 { 1352 sal_Int32 nNumberFormat(0); 1353 if (rValue >>= nNumberFormat) 1354 { 1355 pMeta->SetNumberFormat(static_cast<sal_uInt32>(nNumberFormat)); 1356 } 1357 } 1358 else if ( rPropertyName == "IsFixedLanguage" ) 1359 { 1360 bool b(false); 1361 if (rValue >>= b) 1362 { 1363 pMeta->SetIsFixedLanguage(b); 1364 } 1365 } 1366 else 1367 { 1368 throw beans::UnknownPropertyException(rPropertyName); 1369 } 1370} 1371 1372uno::Any SAL_CALL 1373SwXMetaField::getPropertyValue(const OUString& rPropertyName) 1374{ 1375 SolarMutexGuard g; 1376 1377 ::sw::MetaField const * const pMeta( m_pImpl->GetMetaField() ); 1378 if (!pMeta) 1379 throw lang::DisposedException(); 1380 1381 uno::Any any; 1382 1383 if ( rPropertyName == "NumberFormat" ) 1384 { 1385 const OUString text( getPresentation(false) ); 1386 any <<= static_cast<sal_Int32>(pMeta->GetNumberFormat(text)); 1387 } 1388 else if ( rPropertyName == "IsFixedLanguage" ) 1389 { 1390 any <<= pMeta->IsFixedLanguage(); 1391 } 1392 else 1393 { 1394 throw beans::UnknownPropertyException(rPropertyName); 1395 } 1396 1397 return any; 1398} 1399 1400void SAL_CALL 1401SwXMetaField::addPropertyChangeListener( 1402 const OUString& /*rPropertyName*/, 1403 const uno::Reference< beans::XPropertyChangeListener >& /*xListener*/) 1404{ 1405 OSL_FAIL("SwXMetaField::addPropertyChangeListener(): not implemented")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/unocore/unorefmk.cxx"
":" "1405" ": "), "%s", "SwXMetaField::addPropertyChangeListener(): not implemented"
); } } while (false)
; 1406} 1407 1408void SAL_CALL 1409SwXMetaField::removePropertyChangeListener( 1410 const OUString& /*rPropertyName*/, 1411 const uno::Reference< beans::XPropertyChangeListener >& /*xListener*/) 1412{ 1413 OSL_FAIL("SwXMetaField::removePropertyChangeListener(): not implemented")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/unocore/unorefmk.cxx"
":" "1413" ": "), "%s", "SwXMetaField::removePropertyChangeListener(): not implemented"
); } } while (false)
; 1414} 1415 1416void SAL_CALL 1417SwXMetaField::addVetoableChangeListener( 1418 const OUString& /*rPropertyName*/, 1419 const uno::Reference< beans::XVetoableChangeListener >& /*xListener*/) 1420{ 1421 OSL_FAIL("SwXMetaField::addVetoableChangeListener(): not implemented")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/unocore/unorefmk.cxx"
":" "1421" ": "), "%s", "SwXMetaField::addVetoableChangeListener(): not implemented"
); } } while (false)
; 1422} 1423 1424void SAL_CALL 1425SwXMetaField::removeVetoableChangeListener( 1426 const OUString& /*rPropertyName*/, 1427 const uno::Reference< beans::XVetoableChangeListener >& /*xListener*/) 1428{ 1429 OSL_FAIL("SwXMetaField::removeVetoableChangeListener(): not implemented")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/unocore/unorefmk.cxx"
":" "1429" ": "), "%s", "SwXMetaField::removeVetoableChangeListener(): not implemented"
); } } while (false)
; 1430} 1431 1432static uno::Reference<rdf::XURI> const& 1433lcl_getURI(const bool bPrefix) 1434{ 1435 static uno::Reference< uno::XComponentContext > xContext( 1436 ::comphelper::getProcessComponentContext()); 1437 static uno::Reference< rdf::XURI > xOdfPrefix( 1438 rdf::URI::createKnown(xContext, rdf::URIs::ODF_PREFIX), 1439 uno::UNO_SET_THROW); 1440 static uno::Reference< rdf::XURI > xOdfSuffix( 1441 rdf::URI::createKnown(xContext, rdf::URIs::ODF_SUFFIX), 1442 uno::UNO_SET_THROW); 1443 return bPrefix ? xOdfPrefix : xOdfSuffix; 1444} 1445 1446static OUString 1447lcl_getPrefixOrSuffix( 1448 uno::Reference<rdf::XRepository> const & xRepository, 1449 uno::Reference<rdf::XResource> const & xMetaField, 1450 uno::Reference<rdf::XURI> const & xPredicate) 1451{ 1452 const uno::Reference<container::XEnumeration> xEnum( 1453 xRepository->getStatements(xMetaField, xPredicate, nullptr), 1454 uno::UNO_SET_THROW); 1455 while (xEnum->hasMoreElements()) { 1456 rdf::Statement stmt; 1457 if (!(xEnum->nextElement() >>= stmt)) { 1458 throw uno::RuntimeException(); 1459 } 1460 const uno::Reference<rdf::XLiteral> xObject(stmt.Object, 1461 uno::UNO_QUERY); 1462 if (!xObject.is()) continue; 1463 if (xEnum->hasMoreElements()) { 1464 SAL_INFO("sw.uno", "ignoring other odf:Prefix/odf:Suffix statements")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO
, "sw.uno")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "ignoring other odf:Prefix/odf:Suffix statements"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("sw.uno"
), ("/home/maarten/src/libreoffice/core/sw/source/core/unocore/unorefmk.cxx"
":" "1464" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "ignoring other odf:Prefix/odf:Suffix statements"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "ignoring other odf:Prefix/odf:Suffix statements"; ::
sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("sw.uno"), (
"/home/maarten/src/libreoffice/core/sw/source/core/unocore/unorefmk.cxx"
":" "1464" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "ignoring other odf:Prefix/odf:Suffix statements"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("sw.uno"
), ("/home/maarten/src/libreoffice/core/sw/source/core/unocore/unorefmk.cxx"
":" "1464" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "ignoring other odf:Prefix/odf:Suffix statements"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "ignoring other odf:Prefix/odf:Suffix statements"; ::
sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("sw.uno"), (
"/home/maarten/src/libreoffice/core/sw/source/core/unocore/unorefmk.cxx"
":" "1464" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
; 1465 } 1466 return xObject->getValue(); 1467 } 1468 return OUString(); 1469} 1470 1471void 1472getPrefixAndSuffix( 1473 const uno::Reference<frame::XModel>& xModel, 1474 const uno::Reference<rdf::XMetadatable>& xMetaField, 1475 OUString *const o_pPrefix, OUString *const o_pSuffix) 1476{ 1477 try { 1478 const uno::Reference<rdf::XRepositorySupplier> xRS( 1479 xModel, uno::UNO_QUERY_THROW); 1480 const uno::Reference<rdf::XRepository> xRepo( 1481 xRS->getRDFRepository(), uno::UNO_SET_THROW); 1482 const uno::Reference<rdf::XResource> xMeta( 1483 xMetaField, uno::UNO_QUERY_THROW); 1484 if (o_pPrefix) 1485 { 1486 *o_pPrefix = lcl_getPrefixOrSuffix(xRepo, xMeta, lcl_getURI(true)); 1487 } 1488 if (o_pSuffix) 1489 { 1490 *o_pSuffix = lcl_getPrefixOrSuffix(xRepo, xMeta, lcl_getURI(false)); 1491 } 1492 } catch (uno::RuntimeException &) { 1493 throw; 1494 } catch (const uno::Exception &) { 1495 css::uno::Any anyEx = cppu::getCaughtException(); 1496 throw lang::WrappedTargetRuntimeException("getPrefixAndSuffix: exception", nullptr, anyEx); 1497 } 1498} 1499 1500// XTextField 1501OUString SAL_CALL 1502SwXMetaField::getPresentation(sal_Bool bShowCommand) 1503{ 1504 SolarMutexGuard g; 1505 1506 if (bShowCommand) 1507 { 1508//FIXME ? 1509 return OUString(); 1510 } 1511 else 1512 { 1513 // getString should check if this is invalid 1514 const OUString content( getString() ); 1515 OUString prefix; 1516 OUString suffix; 1517 getPrefixAndSuffix(GetModel(), this, &prefix, &suffix); 1518 return prefix + content + suffix; 1519 } 1520} 1521 1522/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

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

1// shared_ptr and weak_ptr implementation -*- C++ -*-
2
3// Copyright (C) 2007-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// GCC Note: Based on files from version 1.32.0 of the Boost library.
26
27// shared_count.hpp
28// Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.
29
30// shared_ptr.hpp
31// Copyright (C) 1998, 1999 Greg Colvin and Beman Dawes.
32// Copyright (C) 2001, 2002, 2003 Peter Dimov
33
34// weak_ptr.hpp
35// Copyright (C) 2001, 2002, 2003 Peter Dimov
36
37// enable_shared_from_this.hpp
38// Copyright (C) 2002 Peter Dimov
39
40// Distributed under the Boost Software License, Version 1.0. (See
41// accompanying file LICENSE_1_0.txt or copy at
42// http://www.boost.org/LICENSE_1_0.txt)
43
44/** @file
45 * This is an internal header file, included by other library headers.
46 * Do not attempt to use it directly. @headername{memory}
47 */
48
49#ifndef _SHARED_PTR_H1
50#define _SHARED_PTR_H1 1
51
52#include <bits/shared_ptr_base.h>
53
54namespace std _GLIBCXX_VISIBILITY(default)__attribute__ ((__visibility__ ("default")))
55{
56_GLIBCXX_BEGIN_NAMESPACE_VERSION
57
58 /**
59 * @addtogroup pointer_abstractions
60 * @{
61 */
62
63 // 20.7.2.2.11 shared_ptr I/O
64
65 /// Write the stored pointer to an ostream.
66 /// @relates shared_ptr
67 template<typename _Ch, typename _Tr, typename _Tp, _Lock_policy _Lp>
68 inline std::basic_ostream<_Ch, _Tr>&
69 operator<<(std::basic_ostream<_Ch, _Tr>& __os,
70 const __shared_ptr<_Tp, _Lp>& __p)
71 {
72 __os << __p.get();
73 return __os;
74 }
75
76 template<typename _Del, typename _Tp, _Lock_policy _Lp>
77 inline _Del*
78 get_deleter(const __shared_ptr<_Tp, _Lp>& __p) noexcept
79 {
80#if __cpp_rtti199711L
81 return static_cast<_Del*>(__p._M_get_deleter(typeid(_Del)));
82#else
83 return 0;
84#endif
85 }
86
87 /// 20.7.2.2.10 shared_ptr get_deleter
88
89 /// If `__p` has a deleter of type `_Del`, return a pointer to it.
90 /// @relates shared_ptr
91 template<typename _Del, typename _Tp>
92 inline _Del*
93 get_deleter(const shared_ptr<_Tp>& __p) noexcept
94 {
95#if __cpp_rtti199711L
96 return static_cast<_Del*>(__p._M_get_deleter(typeid(_Del)));
97#else
98 return 0;
99#endif
100 }
101
102 /**
103 * @brief A smart pointer with reference-counted copy semantics.
104 *
105 * A `shared_ptr` object is either empty or _owns_ a pointer passed
106 * to the constructor. Copies of a `shared_ptr` share ownership of
107 * the same pointer. When the last `shared_ptr` that owns the pointer
108 * is destroyed or reset, the owned pointer is freed (either by `delete`
109 * or by invoking a custom deleter that was passed to the constructor).
110 *
111 * A `shared_ptr` also stores another pointer, which is usually
112 * (but not always) the same pointer as it owns. The stored pointer
113 * can be retrieved by calling the `get()` member function.
114 *
115 * The equality and relational operators for `shared_ptr` only compare
116 * the stored pointer returned by `get()`, not the owned pointer.
117 * To test whether two `shared_ptr` objects share ownership of the same
118 * pointer see `std::shared_ptr::owner_before` and `std::owner_less`.
119 */
120 template<typename _Tp>
121 class shared_ptr : public __shared_ptr<_Tp>
122 {
123 template<typename... _Args>
124 using _Constructible = typename enable_if<
125 is_constructible<__shared_ptr<_Tp>, _Args...>::value
126 >::type;
127
128 template<typename _Arg>
129 using _Assignable = typename enable_if<
130 is_assignable<__shared_ptr<_Tp>&, _Arg>::value, shared_ptr&
131 >::type;
132
133 public:
134
135 /// The type pointed to by the stored pointer, remove_extent_t<_Tp>
136 using element_type = typename __shared_ptr<_Tp>::element_type;
137
138#if __cplusplus201703L >= 201703L
139# define __cpp_lib_shared_ptr_weak_type201606 201606
140 /// The corresponding weak_ptr type for this shared_ptr
141 using weak_type = weak_ptr<_Tp>;
142#endif
143 /**
144 * @brief Construct an empty %shared_ptr.
145 * @post use_count()==0 && get()==0
146 */
147 constexpr shared_ptr() noexcept : __shared_ptr<_Tp>() { }
148
149 shared_ptr(const shared_ptr&) noexcept = default; ///< Copy constructor
150
151 /**
152 * @brief Construct a %shared_ptr that owns the pointer @a __p.
153 * @param __p A pointer that is convertible to element_type*.
154 * @post use_count() == 1 && get() == __p
155 * @throw std::bad_alloc, in which case @c delete @a __p is called.
156 */
157 template<typename _Yp, typename = _Constructible<_Yp*>>
158 explicit
159 shared_ptr(_Yp* __p) : __shared_ptr<_Tp>(__p) { }
160
161 /**
162 * @brief Construct a %shared_ptr that owns the pointer @a __p
163 * and the deleter @a __d.
164 * @param __p A pointer.
165 * @param __d A deleter.
166 * @post use_count() == 1 && get() == __p
167 * @throw std::bad_alloc, in which case @a __d(__p) is called.
168 *
169 * Requirements: _Deleter's copy constructor and destructor must
170 * not throw
171 *
172 * __shared_ptr will release __p by calling __d(__p)
173 */
174 template<typename _Yp, typename _Deleter,
175 typename = _Constructible<_Yp*, _Deleter>>
176 shared_ptr(_Yp* __p, _Deleter __d)
177 : __shared_ptr<_Tp>(__p, std::move(__d)) { }
178
179 /**
180 * @brief Construct a %shared_ptr that owns a null pointer
181 * and the deleter @a __d.
182 * @param __p A null pointer constant.
183 * @param __d A deleter.
184 * @post use_count() == 1 && get() == __p
185 * @throw std::bad_alloc, in which case @a __d(__p) is called.
186 *
187 * Requirements: _Deleter's copy constructor and destructor must
188 * not throw
189 *
190 * The last owner will call __d(__p)
191 */
192 template<typename _Deleter>
193 shared_ptr(nullptr_t __p, _Deleter __d)
194 : __shared_ptr<_Tp>(__p, std::move(__d)) { }
195
196 /**
197 * @brief Construct a %shared_ptr that owns the pointer @a __p
198 * and the deleter @a __d.
199 * @param __p A pointer.
200 * @param __d A deleter.
201 * @param __a An allocator.
202 * @post use_count() == 1 && get() == __p
203 * @throw std::bad_alloc, in which case @a __d(__p) is called.
204 *
205 * Requirements: _Deleter's copy constructor and destructor must
206 * not throw _Alloc's copy constructor and destructor must not
207 * throw.
208 *
209 * __shared_ptr will release __p by calling __d(__p)
210 */
211 template<typename _Yp, typename _Deleter, typename _Alloc,
212 typename = _Constructible<_Yp*, _Deleter, _Alloc>>
213 shared_ptr(_Yp* __p, _Deleter __d, _Alloc __a)
214 : __shared_ptr<_Tp>(__p, std::move(__d), std::move(__a)) { }
215
216 /**
217 * @brief Construct a %shared_ptr that owns a null pointer
218 * and the deleter @a __d.
219 * @param __p A null pointer constant.
220 * @param __d A deleter.
221 * @param __a An allocator.
222 * @post use_count() == 1 && get() == __p
223 * @throw std::bad_alloc, in which case @a __d(__p) is called.
224 *
225 * Requirements: _Deleter's copy constructor and destructor must
226 * not throw _Alloc's copy constructor and destructor must not
227 * throw.
228 *
229 * The last owner will call __d(__p)
230 */
231 template<typename _Deleter, typename _Alloc>
232 shared_ptr(nullptr_t __p, _Deleter __d, _Alloc __a)
233 : __shared_ptr<_Tp>(__p, std::move(__d), std::move(__a)) { }
234
235 // Aliasing constructor
236
237 /**
238 * @brief Constructs a `shared_ptr` instance that stores `__p`
239 * and shares ownership with `__r`.
240 * @param __r A `shared_ptr`.
241 * @param __p A pointer that will remain valid while `*__r` is valid.
242 * @post `get() == __p && use_count() == __r.use_count()`
243 *
244 * This can be used to construct a `shared_ptr` to a sub-object
245 * of an object managed by an existing `shared_ptr`. The complete
246 * object will remain valid while any `shared_ptr` owns it, even
247 * if they don't store a pointer to the complete object.
248 *
249 * @code
250 * shared_ptr<pair<int,int>> pii(new pair<int,int>());
251 * shared_ptr<int> pi(pii, &pii->first);
252 * assert(pii.use_count() == 2);
253 * @endcode
254 */
255 template<typename _Yp>
256 shared_ptr(const shared_ptr<_Yp>& __r, element_type* __p) noexcept
257 : __shared_ptr<_Tp>(__r, __p) { }
258
259#if __cplusplus201703L > 201703L
260 // _GLIBCXX_RESOLVE_LIB_DEFECTS
261 // 2996. Missing rvalue overloads for shared_ptr operations
262 /**
263 * @brief Constructs a `shared_ptr` instance that stores `__p`
264 * and shares ownership with `__r`.
265 * @param __r A `shared_ptr`.
266 * @param __p A pointer that will remain valid while `*__r` is valid.
267 * @post `get() == __p && !__r.use_count() && !__r.get()`
268 *
269 * This can be used to construct a `shared_ptr` to a sub-object
270 * of an object managed by an existing `shared_ptr`. The complete
271 * object will remain valid while any `shared_ptr` owns it, even
272 * if they don't store a pointer to the complete object.
273 *
274 * @code
275 * shared_ptr<pair<int,int>> pii(new pair<int,int>());
276 * shared_ptr<int> pi1(pii, &pii->first);
277 * assert(pii.use_count() == 2);
278 * shared_ptr<int> pi2(std::move(pii), &pii->second);
279 * assert(pii.use_count() == 0);
280 * @endcode
281 */
282 template<typename _Yp>
283 shared_ptr(shared_ptr<_Yp>&& __r, element_type* __p) noexcept
284 : __shared_ptr<_Tp>(std::move(__r), __p) { }
285#endif
286 /**
287 * @brief If @a __r is empty, constructs an empty %shared_ptr;
288 * otherwise construct a %shared_ptr that shares ownership
289 * with @a __r.
290 * @param __r A %shared_ptr.
291 * @post get() == __r.get() && use_count() == __r.use_count()
292 */
293 template<typename _Yp,
294 typename = _Constructible<const shared_ptr<_Yp>&>>
295 shared_ptr(const shared_ptr<_Yp>& __r) noexcept
296 : __shared_ptr<_Tp>(__r) { }
297
298 /**
299 * @brief Move-constructs a %shared_ptr instance from @a __r.
300 * @param __r A %shared_ptr rvalue.
301 * @post *this contains the old value of @a __r, @a __r is empty.
302 */
303 shared_ptr(shared_ptr&& __r) noexcept
304 : __shared_ptr<_Tp>(std::move(__r)) { }
305
306 /**
307 * @brief Move-constructs a %shared_ptr instance from @a __r.
308 * @param __r A %shared_ptr rvalue.
309 * @post *this contains the old value of @a __r, @a __r is empty.
310 */
311 template<typename _Yp, typename = _Constructible<shared_ptr<_Yp>>>
312 shared_ptr(shared_ptr<_Yp>&& __r) noexcept
313 : __shared_ptr<_Tp>(std::move(__r)) { }
314
315 /**
316 * @brief Constructs a %shared_ptr that shares ownership with @a __r
317 * and stores a copy of the pointer stored in @a __r.
318 * @param __r A weak_ptr.
319 * @post use_count() == __r.use_count()
320 * @throw bad_weak_ptr when __r.expired(),
321 * in which case the constructor has no effect.
322 */
323 template<typename _Yp, typename = _Constructible<const weak_ptr<_Yp>&>>
324 explicit shared_ptr(const weak_ptr<_Yp>& __r)
325 : __shared_ptr<_Tp>(__r) { }
326
327#if _GLIBCXX_USE_DEPRECATED1
328#pragma GCC diagnostic push
329#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
330 template<typename _Yp, typename = _Constructible<auto_ptr<_Yp>>>
331 shared_ptr(auto_ptr<_Yp>&& __r);
332#pragma GCC diagnostic pop
333#endif
334
335 // _GLIBCXX_RESOLVE_LIB_DEFECTS
336 // 2399. shared_ptr's constructor from unique_ptr should be constrained
337 template<typename _Yp, typename _Del,
338 typename = _Constructible<unique_ptr<_Yp, _Del>>>
339 shared_ptr(unique_ptr<_Yp, _Del>&& __r)
340 : __shared_ptr<_Tp>(std::move(__r)) { }
341
342#if __cplusplus201703L <= 201402L && _GLIBCXX_USE_DEPRECATED1
343 // This non-standard constructor exists to support conversions that
344 // were possible in C++11 and C++14 but are ill-formed in C++17.
345 // If an exception is thrown this constructor has no effect.
346 template<typename _Yp, typename _Del,
347 _Constructible<unique_ptr<_Yp, _Del>, __sp_array_delete>* = 0>
348 shared_ptr(unique_ptr<_Yp, _Del>&& __r)
349 : __shared_ptr<_Tp>(std::move(__r), __sp_array_delete()) { }
350#endif
351
352 /**
353 * @brief Construct an empty %shared_ptr.
354 * @post use_count() == 0 && get() == nullptr
355 */
356 constexpr shared_ptr(nullptr_t) noexcept : shared_ptr() { }
357
358 shared_ptr& operator=(const shared_ptr&) noexcept = default;
359
360 template<typename _Yp>
361 _Assignable<const shared_ptr<_Yp>&>
362 operator=(const shared_ptr<_Yp>& __r) noexcept
363 {
364 this->__shared_ptr<_Tp>::operator=(__r);
365 return *this;
366 }
367
368#if _GLIBCXX_USE_DEPRECATED1
369#pragma GCC diagnostic push
370#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
371 template<typename _Yp>
372 _Assignable<auto_ptr<_Yp>>
373 operator=(auto_ptr<_Yp>&& __r)
374 {
375 this->__shared_ptr<_Tp>::operator=(std::move(__r));
376 return *this;
377 }
378#pragma GCC diagnostic pop
379#endif
380
381 shared_ptr&
382 operator=(shared_ptr&& __r) noexcept
383 {
384 this->__shared_ptr<_Tp>::operator=(std::move(__r));
385 return *this;
386 }
387
388 template<class _Yp>
389 _Assignable<shared_ptr<_Yp>>
390 operator=(shared_ptr<_Yp>&& __r) noexcept
391 {
392 this->__shared_ptr<_Tp>::operator=(std::move(__r));
393 return *this;
394 }
395
396 template<typename _Yp, typename _Del>
397 _Assignable<unique_ptr<_Yp, _Del>>
398 operator=(unique_ptr<_Yp, _Del>&& __r)
399 {
400 this->__shared_ptr<_Tp>::operator=(std::move(__r));
401 return *this;
402 }
403
404 private:
405 // This constructor is non-standard, it is used by allocate_shared.
406 template<typename _Alloc, typename... _Args>
407 shared_ptr(_Sp_alloc_shared_tag<_Alloc> __tag, _Args&&... __args)
408 : __shared_ptr<_Tp>(__tag, std::forward<_Args>(__args)...)
16
Calling constructor for '__shared_ptr<sw::Meta, __gnu_cxx::_S_atomic>'
28
Returning from constructor for '__shared_ptr<sw::Meta, __gnu_cxx::_S_atomic>'
409 { }
410
411 template<typename _Yp, typename _Alloc, typename... _Args>
412 friend shared_ptr<_Yp>
413 allocate_shared(const _Alloc& __a, _Args&&... __args);
414
415 // This constructor is non-standard, it is used by weak_ptr::lock().
416 shared_ptr(const weak_ptr<_Tp>& __r, std::nothrow_t)
417 : __shared_ptr<_Tp>(__r, std::nothrow) { }
418
419 friend class weak_ptr<_Tp>;
420 };
421
422#if __cpp_deduction_guides201703L >= 201606
423 template<typename _Tp>
424 shared_ptr(weak_ptr<_Tp>) -> shared_ptr<_Tp>;
425 template<typename _Tp, typename _Del>
426 shared_ptr(unique_ptr<_Tp, _Del>) -> shared_ptr<_Tp>;
427#endif
428
429 // 20.7.2.2.7 shared_ptr comparisons
430
431 /// @relates shared_ptr @{
432
433 /// Equality operator for shared_ptr objects, compares the stored pointers
434 template<typename _Tp, typename _Up>
435 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
436 operator==(const shared_ptr<_Tp>& __a, const shared_ptr<_Up>& __b) noexcept
437 { return __a.get() == __b.get(); }
438
439 /// shared_ptr comparison with nullptr
440 template<typename _Tp>
441 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
442 operator==(const shared_ptr<_Tp>& __a, nullptr_t) noexcept
443 { return !__a; }
444
445#ifdef __cpp_lib_three_way_comparison
446 template<typename _Tp, typename _Up>
447 inline strong_ordering
448 operator<=>(const shared_ptr<_Tp>& __a,
449 const shared_ptr<_Up>& __b) noexcept
450 { return compare_three_way()(__a.get(), __b.get()); }
451
452 template<typename _Tp>
453 inline strong_ordering
454 operator<=>(const shared_ptr<_Tp>& __a, nullptr_t) noexcept
455 {
456 using pointer = typename shared_ptr<_Tp>::element_type*;
457 return compare_three_way()(__a.get(), static_cast<pointer>(nullptr));
458 }
459#else
460 /// shared_ptr comparison with nullptr
461 template<typename _Tp>
462 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
463 operator==(nullptr_t, const shared_ptr<_Tp>& __a) noexcept
464 { return !__a; }
465
466 /// Inequality operator for shared_ptr objects, compares the stored pointers
467 template<typename _Tp, typename _Up>
468 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
469 operator!=(const shared_ptr<_Tp>& __a, const shared_ptr<_Up>& __b) noexcept
470 { return __a.get() != __b.get(); }
471
472 /// shared_ptr comparison with nullptr
473 template<typename _Tp>
474 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
475 operator!=(const shared_ptr<_Tp>& __a, nullptr_t) noexcept
476 { return (bool)__a; }
477
478 /// shared_ptr comparison with nullptr
479 template<typename _Tp>
480 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
481 operator!=(nullptr_t, const shared_ptr<_Tp>& __a) noexcept
482 { return (bool)__a; }
483
484 /// Relational operator for shared_ptr objects, compares the stored pointers
485 template<typename _Tp, typename _Up>
486 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
487 operator<(const shared_ptr<_Tp>& __a, const shared_ptr<_Up>& __b) noexcept
488 {
489 using _Tp_elt = typename shared_ptr<_Tp>::element_type;
490 using _Up_elt = typename shared_ptr<_Up>::element_type;
491 using _Vp = typename common_type<_Tp_elt*, _Up_elt*>::type;
492 return less<_Vp>()(__a.get(), __b.get());
493 }
494
495 /// shared_ptr comparison with nullptr
496 template<typename _Tp>
497 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
498 operator<(const shared_ptr<_Tp>& __a, nullptr_t) noexcept
499 {
500 using _Tp_elt = typename shared_ptr<_Tp>::element_type;
501 return less<_Tp_elt*>()(__a.get(), nullptr);
502 }
503
504 /// shared_ptr comparison with nullptr
505 template<typename _Tp>
506 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
507 operator<(nullptr_t, const shared_ptr<_Tp>& __a) noexcept
508 {
509 using _Tp_elt = typename shared_ptr<_Tp>::element_type;
510 return less<_Tp_elt*>()(nullptr, __a.get());
511 }
512
513 /// Relational operator for shared_ptr objects, compares the stored pointers
514 template<typename _Tp, typename _Up>
515 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
516 operator<=(const shared_ptr<_Tp>& __a, const shared_ptr<_Up>& __b) noexcept
517 { return !(__b < __a); }
518
519 /// shared_ptr comparison with nullptr
520 template<typename _Tp>
521 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
522 operator<=(const shared_ptr<_Tp>& __a, nullptr_t) noexcept
523 { return !(nullptr < __a); }
524
525 /// shared_ptr comparison with nullptr
526 template<typename _Tp>
527 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
528 operator<=(nullptr_t, const shared_ptr<_Tp>& __a) noexcept
529 { return !(__a < nullptr); }
530
531 /// Relational operator for shared_ptr objects, compares the stored pointers
532 template<typename _Tp, typename _Up>
533 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
534 operator>(const shared_ptr<_Tp>& __a, const shared_ptr<_Up>& __b) noexcept
535 { return (__b < __a); }
536
537 /// shared_ptr comparison with nullptr
538 template<typename _Tp>
539 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
540 operator>(const shared_ptr<_Tp>& __a, nullptr_t) noexcept
541 { return nullptr < __a; }
542
543 /// shared_ptr comparison with nullptr
544 template<typename _Tp>
545 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
546 operator>(nullptr_t, const shared_ptr<_Tp>& __a) noexcept
547 { return __a < nullptr; }
548
549 /// Relational operator for shared_ptr objects, compares the stored pointers
550 template<typename _Tp, typename _Up>
551 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
552 operator>=(const shared_ptr<_Tp>& __a, const shared_ptr<_Up>& __b) noexcept
553 { return !(__a < __b); }
554
555 /// shared_ptr comparison with nullptr
556 template<typename _Tp>
557 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
558 operator>=(const shared_ptr<_Tp>& __a, nullptr_t) noexcept
559 { return !(__a < nullptr); }
560
561 /// shared_ptr comparison with nullptr
562 template<typename _Tp>
563 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
564 operator>=(nullptr_t, const shared_ptr<_Tp>& __a) noexcept
565 { return !(nullptr < __a); }
566#endif
567
568 // 20.7.2.2.8 shared_ptr specialized algorithms.
569
570 /// Swap overload for shared_ptr
571 template<typename _Tp>
572 inline void
573 swap(shared_ptr<_Tp>& __a, shared_ptr<_Tp>& __b) noexcept
574 { __a.swap(__b); }
575
576 // 20.7.2.2.9 shared_ptr casts.
577
578 /// Convert type of `shared_ptr`, via `static_cast`
579 template<typename _Tp, typename _Up>
580 inline shared_ptr<_Tp>
581 static_pointer_cast(const shared_ptr<_Up>& __r) noexcept
582 {
583 using _Sp = shared_ptr<_Tp>;
584 return _Sp(__r, static_cast<typename _Sp::element_type*>(__r.get()));
585 }
586
587 /// Convert type of `shared_ptr`, via `const_cast`
588 template<typename _Tp, typename _Up>
589 inline shared_ptr<_Tp>
590 const_pointer_cast(const shared_ptr<_Up>& __r) noexcept
591 {
592 using _Sp = shared_ptr<_Tp>;
593 return _Sp(__r, const_cast<typename _Sp::element_type*>(__r.get()));
594 }
595
596 /// Convert type of `shared_ptr`, via `dynamic_cast`
597 template<typename _Tp, typename _Up>
598 inline shared_ptr<_Tp>
599 dynamic_pointer_cast(const shared_ptr<_Up>& __r) noexcept
600 {
601 using _Sp = shared_ptr<_Tp>;
602 if (auto* __p = dynamic_cast<typename _Sp::element_type*>(__r.get()))
603 return _Sp(__r, __p);
604 return _Sp();
605 }
606
607#if __cplusplus201703L >= 201703L
608 /// Convert type of `shared_ptr`, via `reinterpret_cast`
609 template<typename _Tp, typename _Up>
610 inline shared_ptr<_Tp>
611 reinterpret_pointer_cast(const shared_ptr<_Up>& __r) noexcept
612 {
613 using _Sp = shared_ptr<_Tp>;
614 return _Sp(__r, reinterpret_cast<typename _Sp::element_type*>(__r.get()));
615 }
616
617#if __cplusplus201703L > 201703L
618 // _GLIBCXX_RESOLVE_LIB_DEFECTS
619 // 2996. Missing rvalue overloads for shared_ptr operations
620
621 /// Convert type of `shared_ptr` rvalue, via `static_cast`
622 template<typename _Tp, typename _Up>
623 inline shared_ptr<_Tp>
624 static_pointer_cast(shared_ptr<_Up>&& __r) noexcept
625 {
626 using _Sp = shared_ptr<_Tp>;
627 return _Sp(std::move(__r),
628 static_cast<typename _Sp::element_type*>(__r.get()));
629 }
630
631 /// Convert type of `shared_ptr` rvalue, via `const_cast`
632 template<typename _Tp, typename _Up>
633 inline shared_ptr<_Tp>
634 const_pointer_cast(shared_ptr<_Up>&& __r) noexcept
635 {
636 using _Sp = shared_ptr<_Tp>;
637 return _Sp(std::move(__r),
638 const_cast<typename _Sp::element_type*>(__r.get()));
639 }
640
641 /// Convert type of `shared_ptr` rvalue, via `dynamic_cast`
642 template<typename _Tp, typename _Up>
643 inline shared_ptr<_Tp>
644 dynamic_pointer_cast(shared_ptr<_Up>&& __r) noexcept
645 {
646 using _Sp = shared_ptr<_Tp>;
647 if (auto* __p = dynamic_cast<typename _Sp::element_type*>(__r.get()))
648 return _Sp(std::move(__r), __p);
649 return _Sp();
650 }
651
652 /// Convert type of `shared_ptr` rvalue, via `reinterpret_cast`
653 template<typename _Tp, typename _Up>
654 inline shared_ptr<_Tp>
655 reinterpret_pointer_cast(shared_ptr<_Up>&& __r) noexcept
656 {
657 using _Sp = shared_ptr<_Tp>;
658 return _Sp(std::move(__r),
659 reinterpret_cast<typename _Sp::element_type*>(__r.get()));
660 }
661#endif // C++20
662#endif // C++17
663
664 // @}
665
666 /**
667 * @brief A non-owning observer for a pointer owned by a shared_ptr
668 *
669 * A weak_ptr provides a safe alternative to a raw pointer when you want
670 * a non-owning reference to an object that is managed by a shared_ptr.
671 *
672 * Unlike a raw pointer, a weak_ptr can be converted to a new shared_ptr
673 * that shares ownership with every other shared_ptr that already owns
674 * the pointer. In other words you can upgrade from a non-owning "weak"
675 * reference to an owning shared_ptr, without having access to any of
676 * the existing shared_ptr objects.
677 *
678 * Also unlike a raw pointer, a weak_ptr does not become "dangling" after
679 * the object it points to has been destroyed. Instead, a weak_ptr
680 * becomes _expired_ and can no longer be converted to a shared_ptr that
681 * owns the freed pointer, so you cannot accidentally access the pointed-to
682 * object after it has been destroyed.
683 */
684 template<typename _Tp>
685 class weak_ptr : public __weak_ptr<_Tp>
686 {
687 template<typename _Arg>
688 using _Constructible = typename enable_if<
689 is_constructible<__weak_ptr<_Tp>, _Arg>::value
690 >::type;
691
692 template<typename _Arg>
693 using _Assignable = typename enable_if<
694 is_assignable<__weak_ptr<_Tp>&, _Arg>::value, weak_ptr&
695 >::type;
696
697 public:
698 constexpr weak_ptr() noexcept = default;
699
700 template<typename _Yp,
701 typename = _Constructible<const shared_ptr<_Yp>&>>
702 weak_ptr(const shared_ptr<_Yp>& __r) noexcept
703 : __weak_ptr<_Tp>(__r) { }
704
705 weak_ptr(const weak_ptr&) noexcept = default;
706
707 template<typename _Yp, typename = _Constructible<const weak_ptr<_Yp>&>>
708 weak_ptr(const weak_ptr<_Yp>& __r) noexcept
709 : __weak_ptr<_Tp>(__r) { }
710
711 weak_ptr(weak_ptr&&) noexcept = default;
712
713 template<typename _Yp, typename = _Constructible<weak_ptr<_Yp>>>
714 weak_ptr(weak_ptr<_Yp>&& __r) noexcept
715 : __weak_ptr<_Tp>(std::move(__r)) { }
716
717 weak_ptr&
718 operator=(const weak_ptr& __r) noexcept = default;
719
720 template<typename _Yp>
721 _Assignable<const weak_ptr<_Yp>&>
722 operator=(const weak_ptr<_Yp>& __r) noexcept
723 {
724 this->__weak_ptr<_Tp>::operator=(__r);
725 return *this;
726 }
727
728 template<typename _Yp>
729 _Assignable<const shared_ptr<_Yp>&>
730 operator=(const shared_ptr<_Yp>& __r) noexcept
731 {
732 this->__weak_ptr<_Tp>::operator=(__r);
733 return *this;
734 }
735
736 weak_ptr&
737 operator=(weak_ptr&& __r) noexcept = default;
738
739 template<typename _Yp>
740 _Assignable<weak_ptr<_Yp>>
741 operator=(weak_ptr<_Yp>&& __r) noexcept
742 {
743 this->__weak_ptr<_Tp>::operator=(std::move(__r));
744 return *this;
745 }
746
747 shared_ptr<_Tp>
748 lock() const noexcept
749 { return shared_ptr<_Tp>(*this, std::nothrow); }
750 };
751
752#if __cpp_deduction_guides201703L >= 201606
753 template<typename _Tp>
754 weak_ptr(shared_ptr<_Tp>) -> weak_ptr<_Tp>;
755#endif
756
757 // 20.7.2.3.6 weak_ptr specialized algorithms.
758 /// Swap overload for weak_ptr
759 /// @relates weak_ptr
760 template<typename _Tp>
761 inline void
762 swap(weak_ptr<_Tp>& __a, weak_ptr<_Tp>& __b) noexcept
763 { __a.swap(__b); }
764
765
766 /// Primary template owner_less
767 template<typename _Tp = void>
768 struct owner_less;
769
770 /// Void specialization of owner_less compares either shared_ptr or weak_ptr
771 template<>
772 struct owner_less<void> : _Sp_owner_less<void, void>
773 { };
774
775 /// Partial specialization of owner_less for shared_ptr.
776 template<typename _Tp>
777 struct owner_less<shared_ptr<_Tp>>
778 : public _Sp_owner_less<shared_ptr<_Tp>, weak_ptr<_Tp>>
779 { };
780
781 /// Partial specialization of owner_less for weak_ptr.
782 template<typename _Tp>
783 struct owner_less<weak_ptr<_Tp>>
784 : public _Sp_owner_less<weak_ptr<_Tp>, shared_ptr<_Tp>>
785 { };
786
787 /**
788 * @brief Base class allowing use of member function shared_from_this.
789 */
790 template<typename _Tp>
791 class enable_shared_from_this
792 {
793 protected:
794 constexpr enable_shared_from_this() noexcept { }
795
796 enable_shared_from_this(const enable_shared_from_this&) noexcept { }
797
798 enable_shared_from_this&
799 operator=(const enable_shared_from_this&) noexcept
800 { return *this; }
801
802 ~enable_shared_from_this() { }
803
804 public:
805 shared_ptr<_Tp>
806 shared_from_this()
807 { return shared_ptr<_Tp>(this->_M_weak_this); }
808
809 shared_ptr<const _Tp>
810 shared_from_this() const
811 { return shared_ptr<const _Tp>(this->_M_weak_this); }
812
813#if __cplusplus201703L > 201402L || !defined(__STRICT_ANSI__1) // c++1z or gnu++11
814#define __cpp_lib_enable_shared_from_this201603 201603
815 weak_ptr<_Tp>
816 weak_from_this() noexcept
817 { return this->_M_weak_this; }
818
819 weak_ptr<const _Tp>
820 weak_from_this() const noexcept
821 { return this->_M_weak_this; }
822#endif
823
824 private:
825 template<typename _Tp1>
826 void
827 _M_weak_assign(_Tp1* __p, const __shared_count<>& __n) const noexcept
828 { _M_weak_this._M_assign(__p, __n); }
829
830 // Found by ADL when this is an associated class.
831 friend const enable_shared_from_this*
832 __enable_shared_from_this_base(const __shared_count<>&,
833 const enable_shared_from_this* __p)
834 { return __p; }
835
836 template<typename, _Lock_policy>
837 friend class __shared_ptr;
838
839 mutable weak_ptr<_Tp> _M_weak_this;
840 };
841
842 /// @relates shared_ptr @{
843
844 /**
845 * @brief Create an object that is owned by a shared_ptr.
846 * @param __a An allocator.
847 * @param __args Arguments for the @a _Tp object's constructor.
848 * @return A shared_ptr that owns the newly created object.
849 * @throw An exception thrown from @a _Alloc::allocate or from the
850 * constructor of @a _Tp.
851 *
852 * A copy of @a __a will be used to allocate memory for the shared_ptr
853 * and the new object.
854 */
855 template<typename _Tp, typename _Alloc, typename... _Args>
856 inline shared_ptr<_Tp>
857 allocate_shared(const _Alloc& __a, _Args&&... __args)
858 {
859 return shared_ptr<_Tp>(_Sp_alloc_shared_tag<_Alloc>{__a},
15
Calling constructor for 'shared_ptr<sw::Meta>'
29
Returning from constructor for 'shared_ptr<sw::Meta>'
860 std::forward<_Args>(__args)...);
861 }
862
863 /**
864 * @brief Create an object that is owned by a shared_ptr.
865 * @param __args Arguments for the @a _Tp object's constructor.
866 * @return A shared_ptr that owns the newly created object.
867 * @throw std::bad_alloc, or an exception thrown from the
868 * constructor of @a _Tp.
869 */
870 template<typename _Tp, typename... _Args>
871 inline shared_ptr<_Tp>
872 make_shared(_Args&&... __args)
873 {
874 typedef typename std::remove_cv<_Tp>::type _Tp_nc;
875 return std::allocate_shared<_Tp>(std::allocator<_Tp_nc>(),
14
Calling 'allocate_shared<sw::Meta, std::allocator<sw::Meta>, nullptr_t>'
30
Returned allocated memory
876 std::forward<_Args>(__args)...);
877 }
878
879 /// std::hash specialization for shared_ptr.
880 template<typename _Tp>
881 struct hash<shared_ptr<_Tp>>
882 : public __hash_base<size_t, shared_ptr<_Tp>>
883 {
884 size_t
885 operator()(const shared_ptr<_Tp>& __s) const noexcept
886 {
887 return std::hash<typename shared_ptr<_Tp>::element_type*>()(__s.get());
888 }
889 };
890
891 // @} relates shared_ptr
892 // @} group pointer_abstractions
893
894#if __cplusplus201703L >= 201703L
895 namespace __detail::__variant
896 {
897 template<typename> struct _Never_valueless_alt; // see <variant>
898
899 // Provide the strong exception-safety guarantee when emplacing a
900 // shared_ptr into a variant.
901 template<typename _Tp>
902 struct _Never_valueless_alt<std::shared_ptr<_Tp>>
903 : std::true_type
904 { };
905
906 // Provide the strong exception-safety guarantee when emplacing a
907 // weak_ptr into a variant.
908 template<typename _Tp>
909 struct _Never_valueless_alt<std::weak_ptr<_Tp>>
910 : std::true_type
911 { };
912 } // namespace __detail::__variant
913#endif // C++17
914
915_GLIBCXX_END_NAMESPACE_VERSION
916} // namespace
917
918#endif // _SHARED_PTR_H

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

1// shared_ptr and weak_ptr implementation details -*- C++ -*-
2
3// Copyright (C) 2007-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// GCC Note: Based on files from version 1.32.0 of the Boost library.
26
27// shared_count.hpp
28// Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.
29
30// shared_ptr.hpp
31// Copyright (C) 1998, 1999 Greg Colvin and Beman Dawes.
32// Copyright (C) 2001, 2002, 2003 Peter Dimov
33
34// weak_ptr.hpp
35// Copyright (C) 2001, 2002, 2003 Peter Dimov
36
37// enable_shared_from_this.hpp
38// Copyright (C) 2002 Peter Dimov
39
40// Distributed under the Boost Software License, Version 1.0. (See
41// accompanying file LICENSE_1_0.txt or copy at
42// http://www.boost.org/LICENSE_1_0.txt)
43
44/** @file bits/shared_ptr_base.h
45 * This is an internal header file, included by other library headers.
46 * Do not attempt to use it directly. @headername{memory}
47 */
48
49#ifndef _SHARED_PTR_BASE_H1
50#define _SHARED_PTR_BASE_H1 1
51
52#include <typeinfo>
53#include <bits/allocated_ptr.h>
54#include <bits/refwrap.h>
55#include <bits/stl_function.h>
56#include <ext/aligned_buffer.h>
57#if __cplusplus201703L > 201703L
58# include <compare>
59#endif
60
61namespace std _GLIBCXX_VISIBILITY(default)__attribute__ ((__visibility__ ("default")))
62{
63_GLIBCXX_BEGIN_NAMESPACE_VERSION
64
65#if _GLIBCXX_USE_DEPRECATED1
66#pragma GCC diagnostic push
67#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
68 template<typename> class auto_ptr;
69#pragma GCC diagnostic pop
70#endif
71
72 /**
73 * @brief Exception possibly thrown by @c shared_ptr.
74 * @ingroup exceptions
75 */
76 class bad_weak_ptr : public std::exception
77 {
78 public:
79 virtual char const* what() const noexcept;
80
81 virtual ~bad_weak_ptr() noexcept;
82 };
83
84 // Substitute for bad_weak_ptr object in the case of -fno-exceptions.
85 inline void
86 __throw_bad_weak_ptr()
87 { _GLIBCXX_THROW_OR_ABORT(bad_weak_ptr())(throw (bad_weak_ptr())); }
88
89 using __gnu_cxx::_Lock_policy;
90 using __gnu_cxx::__default_lock_policy;
91 using __gnu_cxx::_S_single;
92 using __gnu_cxx::_S_mutex;
93 using __gnu_cxx::_S_atomic;
94
95 // Empty helper class except when the template argument is _S_mutex.
96 template<_Lock_policy _Lp>
97 class _Mutex_base
98 {
99 protected:
100 // The atomic policy uses fully-fenced builtins, single doesn't care.
101 enum { _S_need_barriers = 0 };
102 };
103
104 template<>
105 class _Mutex_base<_S_mutex>
106 : public __gnu_cxx::__mutex
107 {
108 protected:
109 // This policy is used when atomic builtins are not available.
110 // The replacement atomic operations might not have the necessary
111 // memory barriers.
112 enum { _S_need_barriers = 1 };
113 };
114
115 template<_Lock_policy _Lp = __default_lock_policy>
116 class _Sp_counted_base
117 : public _Mutex_base<_Lp>
118 {
119 public:
120 _Sp_counted_base() noexcept
121 : _M_use_count(1), _M_weak_count(1) { }
122
123 virtual
124 ~_Sp_counted_base() noexcept
125 { }
126
127 // Called when _M_use_count drops to zero, to release the resources
128 // managed by *this.
129 virtual void
130 _M_dispose() noexcept = 0;
131
132 // Called when _M_weak_count drops to zero.
133 virtual void
134 _M_destroy() noexcept
135 { delete this; }
136
137 virtual void*
138 _M_get_deleter(const std::type_info&) noexcept = 0;
139
140 void
141 _M_add_ref_copy()
142 { __gnu_cxx::__atomic_add_dispatch(&_M_use_count, 1); }
143
144 void
145 _M_add_ref_lock();
146
147 bool
148 _M_add_ref_lock_nothrow();
149
150 void
151 _M_release() noexcept
152 {
153 // Be race-detector-friendly. For more info see bits/c++config.
154 _GLIBCXX_SYNCHRONIZATION_HAPPENS_BEFORE(&_M_use_count);
155 if (__gnu_cxx::__exchange_and_add_dispatch(&_M_use_count, -1) == 1)
156 {
157 _GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER(&_M_use_count);
158 _M_dispose();
159 // There must be a memory barrier between dispose() and destroy()
160 // to ensure that the effects of dispose() are observed in the
161 // thread that runs destroy().
162 // See http://gcc.gnu.org/ml/libstdc++/2005-11/msg00136.html
163 if (_Mutex_base<_Lp>::_S_need_barriers)
164 {
165 __atomic_thread_fence (__ATOMIC_ACQ_REL4);
166 }
167
168 // Be race-detector-friendly. For more info see bits/c++config.
169 _GLIBCXX_SYNCHRONIZATION_HAPPENS_BEFORE(&_M_weak_count);
170 if (__gnu_cxx::__exchange_and_add_dispatch(&_M_weak_count,
171 -1) == 1)
172 {
173 _GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER(&_M_weak_count);
174 _M_destroy();
175 }
176 }
177 }
178
179 void
180 _M_weak_add_ref() noexcept
181 { __gnu_cxx::__atomic_add_dispatch(&_M_weak_count, 1); }
182
183 void
184 _M_weak_release() noexcept
185 {
186 // Be race-detector-friendly. For more info see bits/c++config.
187 _GLIBCXX_SYNCHRONIZATION_HAPPENS_BEFORE(&_M_weak_count);
188 if (__gnu_cxx::__exchange_and_add_dispatch(&_M_weak_count, -1) == 1)
189 {
190 _GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER(&_M_weak_count);
191 if (_Mutex_base<_Lp>::_S_need_barriers)
192 {
193 // See _M_release(),
194 // destroy() must observe results of dispose()
195 __atomic_thread_fence (__ATOMIC_ACQ_REL4);
196 }
197 _M_destroy();
198 }
199 }
200
201 long
202 _M_get_use_count() const noexcept
203 {
204 // No memory barrier is used here so there is no synchronization
205 // with other threads.
206 return __atomic_load_n(&_M_use_count, __ATOMIC_RELAXED0);
207 }
208
209 private:
210 _Sp_counted_base(_Sp_counted_base const&) = delete;
211 _Sp_counted_base& operator=(_Sp_counted_base const&) = delete;
212
213 _Atomic_word _M_use_count; // #shared
214 _Atomic_word _M_weak_count; // #weak + (#shared != 0)
215 };
216
217 template<>
218 inline void
219 _Sp_counted_base<_S_single>::
220 _M_add_ref_lock()
221 {
222 if (_M_use_count == 0)
223 __throw_bad_weak_ptr();
224 ++_M_use_count;
225 }
226
227 template<>
228 inline void
229 _Sp_counted_base<_S_mutex>::
230 _M_add_ref_lock()
231 {
232 __gnu_cxx::__scoped_lock sentry(*this);
233 if (__gnu_cxx::__exchange_and_add_dispatch(&_M_use_count, 1) == 0)
234 {
235 _M_use_count = 0;
236 __throw_bad_weak_ptr();
237 }
238 }
239
240 template<>
241 inline void
242 _Sp_counted_base<_S_atomic>::
243 _M_add_ref_lock()
244 {
245 // Perform lock-free add-if-not-zero operation.
246 _Atomic_word __count = _M_get_use_count();
247 do
248 {
249 if (__count == 0)
250 __throw_bad_weak_ptr();
251 // Replace the current counter value with the old value + 1, as
252 // long as it's not changed meanwhile.
253 }
254 while (!__atomic_compare_exchange_n(&_M_use_count, &__count, __count + 1,
255 true, __ATOMIC_ACQ_REL4,
256 __ATOMIC_RELAXED0));
257 }
258
259 template<>
260 inline bool
261 _Sp_counted_base<_S_single>::
262 _M_add_ref_lock_nothrow()
263 {
264 if (_M_use_count == 0)
265 return false;
266 ++_M_use_count;
267 return true;
268 }
269
270 template<>
271 inline bool
272 _Sp_counted_base<_S_mutex>::
273 _M_add_ref_lock_nothrow()
274 {
275 __gnu_cxx::__scoped_lock sentry(*this);
276 if (__gnu_cxx::__exchange_and_add_dispatch(&_M_use_count, 1) == 0)
277 {
278 _M_use_count = 0;
279 return false;
280 }
281 return true;
282 }
283
284 template<>
285 inline bool
286 _Sp_counted_base<_S_atomic>::
287 _M_add_ref_lock_nothrow()
288 {
289 // Perform lock-free add-if-not-zero operation.
290 _Atomic_word __count = _M_get_use_count();
291 do
292 {
293 if (__count == 0)
294 return false;
295 // Replace the current counter value with the old value + 1, as
296 // long as it's not changed meanwhile.
297 }
298 while (!__atomic_compare_exchange_n(&_M_use_count, &__count, __count + 1,
299 true, __ATOMIC_ACQ_REL4,
300 __ATOMIC_RELAXED0));
301 return true;
302 }
303
304 template<>
305 inline void
306 _Sp_counted_base<_S_single>::_M_add_ref_copy()
307 { ++_M_use_count; }
308
309 template<>
310 inline void
311 _Sp_counted_base<_S_single>::_M_release() noexcept
312 {
313 if (--_M_use_count == 0)
314 {
315 _M_dispose();
316 if (--_M_weak_count == 0)
317 _M_destroy();
318 }
319 }
320
321 template<>
322 inline void
323 _Sp_counted_base<_S_single>::_M_weak_add_ref() noexcept
324 { ++_M_weak_count; }
325
326 template<>
327 inline void
328 _Sp_counted_base<_S_single>::_M_weak_release() noexcept
329 {
330 if (--_M_weak_count == 0)
331 _M_destroy();
332 }
333
334 template<>
335 inline long
336 _Sp_counted_base<_S_single>::_M_get_use_count() const noexcept
337 { return _M_use_count; }
338
339
340 // Forward declarations.
341 template<typename _Tp, _Lock_policy _Lp = __default_lock_policy>
342 class __shared_ptr;
343
344 template<typename _Tp, _Lock_policy _Lp = __default_lock_policy>
345 class __weak_ptr;
346
347 template<typename _Tp, _Lock_policy _Lp = __default_lock_policy>
348 class __enable_shared_from_this;
349
350 template<typename _Tp>
351 class shared_ptr;
352
353 template<typename _Tp>
354 class weak_ptr;
355
356 template<typename _Tp>
357 struct owner_less;
358
359 template<typename _Tp>
360 class enable_shared_from_this;
361
362 template<_Lock_policy _Lp = __default_lock_policy>
363 class __weak_count;
364
365 template<_Lock_policy _Lp = __default_lock_policy>
366 class __shared_count;
367
368
369 // Counted ptr with no deleter or allocator support
370 template<typename _Ptr, _Lock_policy _Lp>
371 class _Sp_counted_ptr final : public _Sp_counted_base<_Lp>
372 {
373 public:
374 explicit
375 _Sp_counted_ptr(_Ptr __p) noexcept
376 : _M_ptr(__p) { }
377
378 virtual void
379 _M_dispose() noexcept
380 { delete _M_ptr; }
381
382 virtual void
383 _M_destroy() noexcept
384 { delete this; }
385
386 virtual void*
387 _M_get_deleter(const std::type_info&) noexcept
388 { return nullptr; }
389
390 _Sp_counted_ptr(const _Sp_counted_ptr&) = delete;
391 _Sp_counted_ptr& operator=(const _Sp_counted_ptr&) = delete;
392
393 private:
394 _Ptr _M_ptr;
395 };
396
397 template<>
398 inline void
399 _Sp_counted_ptr<nullptr_t, _S_single>::_M_dispose() noexcept { }
400
401 template<>
402 inline void
403 _Sp_counted_ptr<nullptr_t, _S_mutex>::_M_dispose() noexcept { }
404
405 template<>
406 inline void
407 _Sp_counted_ptr<nullptr_t, _S_atomic>::_M_dispose() noexcept { }
408
409 template<int _Nm, typename _Tp,
410 bool __use_ebo = !__is_final(_Tp) && __is_empty(_Tp)>
411 struct _Sp_ebo_helper;
412
413 /// Specialization using EBO.
414 template<int _Nm, typename _Tp>
415 struct _Sp_ebo_helper<_Nm, _Tp, true> : private _Tp
416 {
417 explicit _Sp_ebo_helper(const _Tp& __tp) : _Tp(__tp) { }
418 explicit _Sp_ebo_helper(_Tp&& __tp) : _Tp(std::move(__tp)) { }
419
420 static _Tp&
421 _S_get(_Sp_ebo_helper& __eboh) { return static_cast<_Tp&>(__eboh); }
422 };
423
424 /// Specialization not using EBO.
425 template<int _Nm, typename _Tp>
426 struct _Sp_ebo_helper<_Nm, _Tp, false>
427 {
428 explicit _Sp_ebo_helper(const _Tp& __tp) : _M_tp(__tp) { }
429 explicit _Sp_ebo_helper(_Tp&& __tp) : _M_tp(std::move(__tp)) { }
430
431 static _Tp&
432 _S_get(_Sp_ebo_helper& __eboh)
433 { return __eboh._M_tp; }
434
435 private:
436 _Tp _M_tp;
437 };
438
439 // Support for custom deleter and/or allocator
440 template<typename _Ptr, typename _Deleter, typename _Alloc, _Lock_policy _Lp>
441 class _Sp_counted_deleter final : public _Sp_counted_base<_Lp>
442 {
443 class _Impl : _Sp_ebo_helper<0, _Deleter>, _Sp_ebo_helper<1, _Alloc>
444 {
445 typedef _Sp_ebo_helper<0, _Deleter> _Del_base;
446 typedef _Sp_ebo_helper<1, _Alloc> _Alloc_base;
447
448 public:
449 _Impl(_Ptr __p, _Deleter __d, const _Alloc& __a) noexcept
450 : _M_ptr(__p), _Del_base(std::move(__d)), _Alloc_base(__a)
451 { }
452
453 _Deleter& _M_del() noexcept { return _Del_base::_S_get(*this); }
454 _Alloc& _M_alloc() noexcept { return _Alloc_base::_S_get(*this); }
455
456 _Ptr _M_ptr;
457 };
458
459 public:
460 using __allocator_type = __alloc_rebind<_Alloc, _Sp_counted_deleter>;
461
462 // __d(__p) must not throw.
463 _Sp_counted_deleter(_Ptr __p, _Deleter __d) noexcept
464 : _M_impl(__p, std::move(__d), _Alloc()) { }
465
466 // __d(__p) must not throw.
467 _Sp_counted_deleter(_Ptr __p, _Deleter __d, const _Alloc& __a) noexcept
468 : _M_impl(__p, std::move(__d), __a) { }
469
470 ~_Sp_counted_deleter() noexcept { }
471
472 virtual void
473 _M_dispose() noexcept
474 { _M_impl._M_del()(_M_impl._M_ptr); }
475
476 virtual void
477 _M_destroy() noexcept
478 {
479 __allocator_type __a(_M_impl._M_alloc());
480 __allocated_ptr<__allocator_type> __guard_ptr{ __a, this };
481 this->~_Sp_counted_deleter();
482 }
483
484 virtual void*
485 _M_get_deleter(const std::type_info& __ti) noexcept
486 {
487#if __cpp_rtti199711L
488 // _GLIBCXX_RESOLVE_LIB_DEFECTS
489 // 2400. shared_ptr's get_deleter() should use addressof()
490 return __ti == typeid(_Deleter)
491 ? std::__addressof(_M_impl._M_del())
492 : nullptr;
493#else
494 return nullptr;
495#endif
496 }
497
498 private:
499 _Impl _M_impl;
500 };
501
502 // helpers for make_shared / allocate_shared
503
504 struct _Sp_make_shared_tag
505 {
506 private:
507 template<typename _Tp, typename _Alloc, _Lock_policy _Lp>
508 friend class _Sp_counted_ptr_inplace;
509
510 static const type_info&
511 _S_ti() noexcept _GLIBCXX_VISIBILITY(default)__attribute__ ((__visibility__ ("default")))
512 {
513 alignas(type_info) static constexpr char __tag[sizeof(type_info)] = { };
514 return reinterpret_cast<const type_info&>(__tag);
515 }
516
517 static bool _S_eq(const type_info&) noexcept;
518 };
519
520 template<typename _Alloc>
521 struct _Sp_alloc_shared_tag
522 {
523 const _Alloc& _M_a;
524 };
525
526 template<typename _Tp, typename _Alloc, _Lock_policy _Lp>
527 class _Sp_counted_ptr_inplace final : public _Sp_counted_base<_Lp>
528 {
529 class _Impl : _Sp_ebo_helper<0, _Alloc>
530 {
531 typedef _Sp_ebo_helper<0, _Alloc> _A_base;
532
533 public:
534 explicit _Impl(_Alloc __a) noexcept : _A_base(__a) { }
535
536 _Alloc& _M_alloc() noexcept { return _A_base::_S_get(*this); }
537
538 __gnu_cxx::__aligned_buffer<_Tp> _M_storage;
539 };
540
541 public:
542 using __allocator_type = __alloc_rebind<_Alloc, _Sp_counted_ptr_inplace>;
543
544 // Alloc parameter is not a reference so doesn't alias anything in __args
545 template<typename... _Args>
546 _Sp_counted_ptr_inplace(_Alloc __a, _Args&&... __args)
547 : _M_impl(__a)
548 {
549 // _GLIBCXX_RESOLVE_LIB_DEFECTS
550 // 2070. allocate_shared should use allocator_traits<A>::construct
551 allocator_traits<_Alloc>::construct(__a, _M_ptr(),
552 std::forward<_Args>(__args)...); // might throw
553 }
554
555 ~_Sp_counted_ptr_inplace() noexcept { }
556
557 virtual void
558 _M_dispose() noexcept
559 {
560 allocator_traits<_Alloc>::destroy(_M_impl._M_alloc(), _M_ptr());
561 }
562
563 // Override because the allocator needs to know the dynamic type
564 virtual void
565 _M_destroy() noexcept
566 {
567 __allocator_type __a(_M_impl._M_alloc());
568 __allocated_ptr<__allocator_type> __guard_ptr{ __a, this };
569 this->~_Sp_counted_ptr_inplace();
570 }
571
572 private:
573 friend class __shared_count<_Lp>; // To be able to call _M_ptr().
574
575 // No longer used, but code compiled against old libstdc++ headers
576 // might still call it from __shared_ptr ctor to get the pointer out.
577 virtual void*
578 _M_get_deleter(const std::type_info& __ti) noexcept override
579 {
580 auto __ptr = const_cast<typename remove_cv<_Tp>::type*>(_M_ptr());
581 // Check for the fake type_info first, so we don't try to access it
582 // as a real type_info object. Otherwise, check if it's the real
583 // type_info for this class. With RTTI enabled we can check directly,
584 // or call a library function to do it.
585 if (&__ti == &_Sp_make_shared_tag::_S_ti()
586 ||
587#if __cpp_rtti199711L
588 __ti == typeid(_Sp_make_shared_tag)
589#else
590 _Sp_make_shared_tag::_S_eq(__ti)
591#endif
592 )
593 return __ptr;
594 return nullptr;
595 }
596
597 _Tp* _M_ptr() noexcept { return _M_impl._M_storage._M_ptr(); }
598
599 _Impl _M_impl;
600 };
601
602 // The default deleter for shared_ptr<T[]> and shared_ptr<T[N]>.
603 struct __sp_array_delete
604 {
605 template<typename _Yp>
606 void operator()(_Yp* __p) const { delete[] __p; }
607 };
608
609 template<_Lock_policy _Lp>
610 class __shared_count
611 {
612 template<typename _Tp>
613 struct __not_alloc_shared_tag { using type = void; };
614
615 template<typename _Tp>
616 struct __not_alloc_shared_tag<_Sp_alloc_shared_tag<_Tp>> { };
617
618 public:
619 constexpr __shared_count() noexcept : _M_pi(0)
620 { }
621
622 template<typename _Ptr>
623 explicit
624 __shared_count(_Ptr __p) : _M_pi(0)
625 {
626 __trytry
627 {
628 _M_pi = new _Sp_counted_ptr<_Ptr, _Lp>(__p);
629 }
630 __catch(...)catch(...)
631 {
632 delete __p;
633 __throw_exception_againthrow;
634 }
635 }
636
637 template<typename _Ptr>
638 __shared_count(_Ptr __p, /* is_array = */ false_type)
639 : __shared_count(__p)
640 { }
641
642 template<typename _Ptr>
643 __shared_count(_Ptr __p, /* is_array = */ true_type)
644 : __shared_count(__p, __sp_array_delete{}, allocator<void>())
645 { }
646
647 template<typename _Ptr, typename _Deleter,
648 typename = typename __not_alloc_shared_tag<_Deleter>::type>
649 __shared_count(_Ptr __p, _Deleter __d)
650 : __shared_count(__p, std::move(__d), allocator<void>())
651 { }
652
653 template<typename _Ptr, typename _Deleter, typename _Alloc,
654 typename = typename __not_alloc_shared_tag<_Deleter>::type>
655 __shared_count(_Ptr __p, _Deleter __d, _Alloc __a) : _M_pi(0)
656 {
657 typedef _Sp_counted_deleter<_Ptr, _Deleter, _Alloc, _Lp> _Sp_cd_type;
658 __trytry
659 {
660 typename _Sp_cd_type::__allocator_type __a2(__a);
661 auto __guard = std::__allocate_guarded(__a2);
662 _Sp_cd_type* __mem = __guard.get();
663 ::new (__mem) _Sp_cd_type(__p, std::move(__d), std::move(__a));
664 _M_pi = __mem;
665 __guard = nullptr;
666 }
667 __catch(...)catch(...)
668 {
669 __d(__p); // Call _Deleter on __p.
670 __throw_exception_againthrow;
671 }
672 }
673
674 template<typename _Tp, typename _Alloc, typename... _Args>
675 __shared_count(_Tp*& __p, _Sp_alloc_shared_tag<_Alloc> __a,
676 _Args&&... __args)
677 {
678 typedef _Sp_counted_ptr_inplace<_Tp, _Alloc, _Lp> _Sp_cp_type;
679 typename _Sp_cp_type::__allocator_type __a2(__a._M_a);
680 auto __guard = std::__allocate_guarded(__a2);
18
Calling '__allocate_guarded<std::allocator<std::_Sp_counted_ptr_inplace<sw::Meta, std::allocator<sw::Meta>, __gnu_cxx::_S_atomic>>>'
26
Returned allocated memory
681 _Sp_cp_type* __mem = __guard.get();
682 auto __pi = ::new (__mem)
683 _Sp_cp_type(__a._M_a, std::forward<_Args>(__args)...);
684 __guard = nullptr;
685 _M_pi = __pi;
686 __p = __pi->_M_ptr();
687 }
688
689#if _GLIBCXX_USE_DEPRECATED1
690#pragma GCC diagnostic push
691#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
692 // Special case for auto_ptr<_Tp> to provide the strong guarantee.
693 template<typename _Tp>
694 explicit
695 __shared_count(std::auto_ptr<_Tp>&& __r);
696#pragma GCC diagnostic pop
697#endif
698
699 // Special case for unique_ptr<_Tp,_Del> to provide the strong guarantee.
700 template<typename _Tp, typename _Del>
701 explicit
702 __shared_count(std::unique_ptr<_Tp, _Del>&& __r) : _M_pi(0)
703 {
704 // _GLIBCXX_RESOLVE_LIB_DEFECTS
705 // 2415. Inconsistency between unique_ptr and shared_ptr
706 if (__r.get() == nullptr)
707 return;
708
709 using _Ptr = typename unique_ptr<_Tp, _Del>::pointer;
710 using _Del2 = typename conditional<is_reference<_Del>::value,
711 reference_wrapper<typename remove_reference<_Del>::type>,
712 _Del>::type;
713 using _Sp_cd_type
714 = _Sp_counted_deleter<_Ptr, _Del2, allocator<void>, _Lp>;
715 using _Alloc = allocator<_Sp_cd_type>;
716 using _Alloc_traits = allocator_traits<_Alloc>;
717 _Alloc __a;
718 _Sp_cd_type* __mem = _Alloc_traits::allocate(__a, 1);
719 _Alloc_traits::construct(__a, __mem, __r.release(),
720 __r.get_deleter()); // non-throwing
721 _M_pi = __mem;
722 }
723
724 // Throw bad_weak_ptr when __r._M_get_use_count() == 0.
725 explicit __shared_count(const __weak_count<_Lp>& __r);
726
727 // Does not throw if __r._M_get_use_count() == 0, caller must check.
728 explicit __shared_count(const __weak_count<_Lp>& __r, std::nothrow_t);
729
730 ~__shared_count() noexcept
731 {
732 if (_M_pi != nullptr)
733 _M_pi->_M_release();
734 }
735
736 __shared_count(const __shared_count& __r) noexcept
737 : _M_pi(__r._M_pi)
738 {
739 if (_M_pi != 0)
740 _M_pi->_M_add_ref_copy();
741 }
742
743 __shared_count&
744 operator=(const __shared_count& __r) noexcept
745 {
746 _Sp_counted_base<_Lp>* __tmp = __r._M_pi;
747 if (__tmp != _M_pi)
748 {
749 if (__tmp != 0)
750 __tmp->_M_add_ref_copy();
751 if (_M_pi != 0)
752 _M_pi->_M_release();
753 _M_pi = __tmp;
754 }
755 return *this;
756 }
757
758 void
759 _M_swap(__shared_count& __r) noexcept
760 {
761 _Sp_counted_base<_Lp>* __tmp = __r._M_pi;
762 __r._M_pi = _M_pi;
763 _M_pi = __tmp;
764 }
765
766 long
767 _M_get_use_count() const noexcept
768 { return _M_pi != 0 ? _M_pi->_M_get_use_count() : 0; }
769
770 bool
771 _M_unique() const noexcept
772 { return this->_M_get_use_count() == 1; }
773
774 void*
775 _M_get_deleter(const std::type_info& __ti) const noexcept
776 { return _M_pi ? _M_pi->_M_get_deleter(__ti) : nullptr; }
777
778 bool
779 _M_less(const __shared_count& __rhs) const noexcept
780 { return std::less<_Sp_counted_base<_Lp>*>()(this->_M_pi, __rhs._M_pi); }
781
782 bool
783 _M_less(const __weak_count<_Lp>& __rhs) const noexcept
784 { return std::less<_Sp_counted_base<_Lp>*>()(this->_M_pi, __rhs._M_pi); }
785
786 // Friend function injected into enclosing namespace and found by ADL
787 friend inline bool
788 operator==(const __shared_count& __a, const __shared_count& __b) noexcept
789 { return __a._M_pi == __b._M_pi; }
790
791 private:
792 friend class __weak_count<_Lp>;
793
794 _Sp_counted_base<_Lp>* _M_pi;
795 };
796
797
798 template<_Lock_policy _Lp>
799 class __weak_count
800 {
801 public:
802 constexpr __weak_count() noexcept : _M_pi(nullptr)
803 { }
804
805 __weak_count(const __shared_count<_Lp>& __r) noexcept
806 : _M_pi(__r._M_pi)
807 {
808 if (_M_pi != nullptr)
809 _M_pi->_M_weak_add_ref();
810 }
811
812 __weak_count(const __weak_count& __r) noexcept
813 : _M_pi(__r._M_pi)
814 {
815 if (_M_pi != nullptr)
816 _M_pi->_M_weak_add_ref();
817 }
818
819 __weak_count(__weak_count&& __r) noexcept
820 : _M_pi(__r._M_pi)
821 { __r._M_pi = nullptr; }
822
823 ~__weak_count() noexcept
824 {
825 if (_M_pi != nullptr)
826 _M_pi->_M_weak_release();
827 }
828
829 __weak_count&
830 operator=(const __shared_count<_Lp>& __r) noexcept
831 {
832 _Sp_counted_base<_Lp>* __tmp = __r._M_pi;
833 if (__tmp != nullptr)
834 __tmp->_M_weak_add_ref();
835 if (_M_pi != nullptr)
836 _M_pi->_M_weak_release();
837 _M_pi = __tmp;
838 return *this;
839 }
840
841 __weak_count&
842 operator=(const __weak_count& __r) noexcept
843 {
844 _Sp_counted_base<_Lp>* __tmp = __r._M_pi;
845 if (__tmp != nullptr)
846 __tmp->_M_weak_add_ref();
847 if (_M_pi != nullptr)
848 _M_pi->_M_weak_release();
849 _M_pi = __tmp;
850 return *this;
851 }
852
853 __weak_count&
854 operator=(__weak_count&& __r) noexcept
855 {
856 if (_M_pi != nullptr)
857 _M_pi->_M_weak_release();
858 _M_pi = __r._M_pi;
859 __r._M_pi = nullptr;
860 return *this;
861 }
862
863 void
864 _M_swap(__weak_count& __r) noexcept
865 {
866 _Sp_counted_base<_Lp>* __tmp = __r._M_pi;
867 __r._M_pi = _M_pi;
868 _M_pi = __tmp;
869 }
870
871 long
872 _M_get_use_count() const noexcept
873 { return _M_pi != nullptr ? _M_pi->_M_get_use_count() : 0; }
874
875 bool
876 _M_less(const __weak_count& __rhs) const noexcept
877 { return std::less<_Sp_counted_base<_Lp>*>()(this->_M_pi, __rhs._M_pi); }
878
879 bool
880 _M_less(const __shared_count<_Lp>& __rhs) const noexcept
881 { return std::less<_Sp_counted_base<_Lp>*>()(this->_M_pi, __rhs._M_pi); }
882
883 // Friend function injected into enclosing namespace and found by ADL
884 friend inline bool
885 operator==(const __weak_count& __a, const __weak_count& __b) noexcept
886 { return __a._M_pi == __b._M_pi; }
887
888 private:
889 friend class __shared_count<_Lp>;
890
891 _Sp_counted_base<_Lp>* _M_pi;
892 };
893
894 // Now that __weak_count is defined we can define this constructor:
895 template<_Lock_policy _Lp>
896 inline
897 __shared_count<_Lp>::__shared_count(const __weak_count<_Lp>& __r)
898 : _M_pi(__r._M_pi)
899 {
900 if (_M_pi != nullptr)
901 _M_pi->_M_add_ref_lock();
902 else
903 __throw_bad_weak_ptr();
904 }
905
906 // Now that __weak_count is defined we can define this constructor:
907 template<_Lock_policy _Lp>
908 inline
909 __shared_count<_Lp>::
910 __shared_count(const __weak_count<_Lp>& __r, std::nothrow_t)
911 : _M_pi(__r._M_pi)
912 {
913 if (_M_pi != nullptr)
914 if (!_M_pi->_M_add_ref_lock_nothrow())
915 _M_pi = nullptr;
916 }
917
918#define __cpp_lib_shared_ptr_arrays201611L 201611L
919
920 // Helper traits for shared_ptr of array:
921
922 // A pointer type Y* is said to be compatible with a pointer type T* when
923 // either Y* is convertible to T* or Y is U[N] and T is U cv [].
924 template<typename _Yp_ptr, typename _Tp_ptr>
925 struct __sp_compatible_with
926 : false_type
927 { };
928
929 template<typename _Yp, typename _Tp>
930 struct __sp_compatible_with<_Yp*, _Tp*>
931 : is_convertible<_Yp*, _Tp*>::type
932 { };
933
934 template<typename _Up, size_t _Nm>
935 struct __sp_compatible_with<_Up(*)[_Nm], _Up(*)[]>
936 : true_type
937 { };
938
939 template<typename _Up, size_t _Nm>
940 struct __sp_compatible_with<_Up(*)[_Nm], const _Up(*)[]>
941 : true_type
942 { };
943
944 template<typename _Up, size_t _Nm>
945 struct __sp_compatible_with<_Up(*)[_Nm], volatile _Up(*)[]>
946 : true_type
947 { };
948
949 template<typename _Up, size_t _Nm>
950 struct __sp_compatible_with<_Up(*)[_Nm], const volatile _Up(*)[]>
951 : true_type
952 { };
953
954 // Test conversion from Y(*)[N] to U(*)[N] without forming invalid type Y[N].
955 template<typename _Up, size_t _Nm, typename _Yp, typename = void>
956 struct __sp_is_constructible_arrN
957 : false_type
958 { };
959
960 template<typename _Up, size_t _Nm, typename _Yp>
961 struct __sp_is_constructible_arrN<_Up, _Nm, _Yp, __void_t<_Yp[_Nm]>>
962 : is_convertible<_Yp(*)[_Nm], _Up(*)[_Nm]>::type
963 { };
964
965 // Test conversion from Y(*)[] to U(*)[] without forming invalid type Y[].
966 template<typename _Up, typename _Yp, typename = void>
967 struct __sp_is_constructible_arr
968 : false_type
969 { };
970
971 template<typename _Up, typename _Yp>
972 struct __sp_is_constructible_arr<_Up, _Yp, __void_t<_Yp[]>>
973 : is_convertible<_Yp(*)[], _Up(*)[]>::type
974 { };
975
976 // Trait to check if shared_ptr<T> can be constructed from Y*.
977 template<typename _Tp, typename _Yp>
978 struct __sp_is_constructible;
979
980 // When T is U[N], Y(*)[N] shall be convertible to T*;
981 template<typename _Up, size_t _Nm, typename _Yp>
982 struct __sp_is_constructible<_Up[_Nm], _Yp>
983 : __sp_is_constructible_arrN<_Up, _Nm, _Yp>::type
984 { };
985
986 // when T is U[], Y(*)[] shall be convertible to T*;
987 template<typename _Up, typename _Yp>
988 struct __sp_is_constructible<_Up[], _Yp>
989 : __sp_is_constructible_arr<_Up, _Yp>::type
990 { };
991
992 // otherwise, Y* shall be convertible to T*.
993 template<typename _Tp, typename _Yp>
994 struct __sp_is_constructible
995 : is_convertible<_Yp*, _Tp*>::type
996 { };
997
998
999 // Define operator* and operator-> for shared_ptr<T>.
1000 template<typename _Tp, _Lock_policy _Lp,
1001 bool = is_array<_Tp>::value, bool = is_void<_Tp>::value>
1002 class __shared_ptr_access
1003 {
1004 public:
1005 using element_type = _Tp;
1006
1007 element_type&
1008 operator*() const noexcept
1009 {
1010 __glibcxx_assert(_M_get() != nullptr);
1011 return *_M_get();
1012 }
1013
1014 element_type*
1015 operator->() const noexcept
1016 {
1017 _GLIBCXX_DEBUG_PEDASSERT(_M_get() != nullptr);
1018 return _M_get();
1019 }
1020
1021 private:
1022 element_type*
1023 _M_get() const noexcept
1024 { return static_cast<const __shared_ptr<_Tp, _Lp>*>(this)->get(); }
1025 };
1026
1027 // Define operator-> for shared_ptr<cv void>.
1028 template<typename _Tp, _Lock_policy _Lp>
1029 class __shared_ptr_access<_Tp, _Lp, false, true>
1030 {
1031 public:
1032 using element_type = _Tp;
1033
1034 element_type*
1035 operator->() const noexcept
1036 {
1037 auto __ptr = static_cast<const __shared_ptr<_Tp, _Lp>*>(this)->get();
1038 _GLIBCXX_DEBUG_PEDASSERT(__ptr != nullptr);
1039 return __ptr;
1040 }
1041 };
1042
1043 // Define operator[] for shared_ptr<T[]> and shared_ptr<T[N]>.
1044 template<typename _Tp, _Lock_policy _Lp>
1045 class __shared_ptr_access<_Tp, _Lp, true, false>
1046 {
1047 public:
1048 using element_type = typename remove_extent<_Tp>::type;
1049
1050#if __cplusplus201703L <= 201402L
1051 [[__deprecated__("shared_ptr<T[]>::operator* is absent from C++17")]]
1052 element_type&
1053 operator*() const noexcept
1054 {
1055 __glibcxx_assert(_M_get() != nullptr);
1056 return *_M_get();
1057 }
1058
1059 [[__deprecated__("shared_ptr<T[]>::operator-> is absent from C++17")]]
1060 element_type*
1061 operator->() const noexcept
1062 {
1063 _GLIBCXX_DEBUG_PEDASSERT(_M_get() != nullptr);
1064 return _M_get();
1065 }
1066#endif
1067
1068 element_type&
1069 operator[](ptrdiff_t __i) const
1070 {
1071 __glibcxx_assert(_M_get() != nullptr);
1072 __glibcxx_assert(!extent<_Tp>::value || __i < extent<_Tp>::value);
1073 return _M_get()[__i];
1074 }
1075
1076 private:
1077 element_type*
1078 _M_get() const noexcept
1079 { return static_cast<const __shared_ptr<_Tp, _Lp>*>(this)->get(); }
1080 };
1081
1082 template<typename _Tp, _Lock_policy _Lp>
1083 class __shared_ptr
1084 : public __shared_ptr_access<_Tp, _Lp>
1085 {
1086 public:
1087 using element_type = typename remove_extent<_Tp>::type;
1088
1089 private:
1090 // Constraint for taking ownership of a pointer of type _Yp*:
1091 template<typename _Yp>
1092 using _SafeConv
1093 = typename enable_if<__sp_is_constructible<_Tp, _Yp>::value>::type;
1094
1095 // Constraint for construction from shared_ptr and weak_ptr:
1096 template<typename _Yp, typename _Res = void>
1097 using _Compatible = typename
1098 enable_if<__sp_compatible_with<_Yp*, _Tp*>::value, _Res>::type;
1099
1100 // Constraint for assignment from shared_ptr and weak_ptr:
1101 template<typename _Yp>
1102 using _Assignable = _Compatible<_Yp, __shared_ptr&>;
1103
1104 // Constraint for construction from unique_ptr:
1105 template<typename _Yp, typename _Del, typename _Res = void,
1106 typename _Ptr = typename unique_ptr<_Yp, _Del>::pointer>
1107 using _UniqCompatible = typename enable_if<__and_<
1108 __sp_compatible_with<_Yp*, _Tp*>, is_convertible<_Ptr, element_type*>
1109 >::value, _Res>::type;
1110
1111 // Constraint for assignment from unique_ptr:
1112 template<typename _Yp, typename _Del>
1113 using _UniqAssignable = _UniqCompatible<_Yp, _Del, __shared_ptr&>;
1114
1115 public:
1116
1117#if __cplusplus201703L > 201402L
1118 using weak_type = __weak_ptr<_Tp, _Lp>;
1119#endif
1120
1121 constexpr __shared_ptr() noexcept
1122 : _M_ptr(0), _M_refcount()
1123 { }
1124
1125 template<typename _Yp, typename = _SafeConv<_Yp>>
1126 explicit
1127 __shared_ptr(_Yp* __p)
1128 : _M_ptr(__p), _M_refcount(__p, typename is_array<_Tp>::type())
1129 {
1130 static_assert( !is_void<_Yp>::value, "incomplete type" );
1131 static_assert( sizeof(_Yp) > 0, "incomplete type" );
1132 _M_enable_shared_from_this_with(__p);
1133 }
1134
1135 template<typename _Yp, typename _Deleter, typename = _SafeConv<_Yp>>
1136 __shared_ptr(_Yp* __p, _Deleter __d)
1137 : _M_ptr(__p), _M_refcount(__p, std::move(__d))
1138 {
1139 static_assert(__is_invocable<_Deleter&, _Yp*&>::value,
1140 "deleter expression d(p) is well-formed");
1141 _M_enable_shared_from_this_with(__p);
1142 }
1143
1144 template<typename _Yp, typename _Deleter, typename _Alloc,
1145 typename = _SafeConv<_Yp>>
1146 __shared_ptr(_Yp* __p, _Deleter __d, _Alloc __a)
1147 : _M_ptr(__p), _M_refcount(__p, std::move(__d), std::move(__a))
1148 {
1149 static_assert(__is_invocable<_Deleter&, _Yp*&>::value,
1150 "deleter expression d(p) is well-formed");
1151 _M_enable_shared_from_this_with(__p);
1152 }
1153
1154 template<typename _Deleter>
1155 __shared_ptr(nullptr_t __p, _Deleter __d)
1156 : _M_ptr(0), _M_refcount(__p, std::move(__d))
1157 { }
1158
1159 template<typename _Deleter, typename _Alloc>
1160 __shared_ptr(nullptr_t __p, _Deleter __d, _Alloc __a)
1161 : _M_ptr(0), _M_refcount(__p, std::move(__d), std::move(__a))
1162 { }
1163
1164 // Aliasing constructor
1165 template<typename _Yp>
1166 __shared_ptr(const __shared_ptr<_Yp, _Lp>& __r,
1167 element_type* __p) noexcept
1168 : _M_ptr(__p), _M_refcount(__r._M_refcount) // never throws
1169 { }
1170
1171 // Aliasing constructor
1172 template<typename _Yp>
1173 __shared_ptr(__shared_ptr<_Yp, _Lp>&& __r,
1174 element_type* __p) noexcept
1175 : _M_ptr(__p), _M_refcount()
1176 {
1177 _M_refcount._M_swap(__r._M_refcount);
1178 __r._M_ptr = 0;
1179 }
1180
1181 __shared_ptr(const __shared_ptr&) noexcept = default;
1182 __shared_ptr& operator=(const __shared_ptr&) noexcept = default;
1183 ~__shared_ptr() = default;
1184
1185 template<typename _Yp, typename = _Compatible<_Yp>>
1186 __shared_ptr(const __shared_ptr<_Yp, _Lp>& __r) noexcept
1187 : _M_ptr(__r._M_ptr), _M_refcount(__r._M_refcount)
1188 { }
1189
1190 __shared_ptr(__shared_ptr&& __r) noexcept
1191 : _M_ptr(__r._M_ptr), _M_refcount()
1192 {
1193 _M_refcount._M_swap(__r._M_refcount);
1194 __r._M_ptr = 0;
1195 }
1196
1197 template<typename _Yp, typename = _Compatible<_Yp>>
1198 __shared_ptr(__shared_ptr<_Yp, _Lp>&& __r) noexcept
1199 : _M_ptr(__r._M_ptr), _M_refcount()
1200 {
1201 _M_refcount._M_swap(__r._M_refcount);
1202 __r._M_ptr = 0;
1203 }
1204
1205 template<typename _Yp, typename = _Compatible<_Yp>>
1206 explicit __shared_ptr(const __weak_ptr<_Yp, _Lp>& __r)
1207 : _M_refcount(__r._M_refcount) // may throw
1208 {
1209 // It is now safe to copy __r._M_ptr, as
1210 // _M_refcount(__r._M_refcount) did not throw.
1211 _M_ptr = __r._M_ptr;
1212 }
1213
1214 // If an exception is thrown this constructor has no effect.
1215 template<typename _Yp, typename _Del,
1216 typename = _UniqCompatible<_Yp, _Del>>
1217 __shared_ptr(unique_ptr<_Yp, _Del>&& __r)
1218 : _M_ptr(__r.get()), _M_refcount()
1219 {
1220 auto __raw = __to_address(__r.get());
1221 _M_refcount = __shared_count<_Lp>(std::move(__r));
1222 _M_enable_shared_from_this_with(__raw);
1223 }
1224
1225#if __cplusplus201703L <= 201402L && _GLIBCXX_USE_DEPRECATED1
1226 protected:
1227 // If an exception is thrown this constructor has no effect.
1228 template<typename _Tp1, typename _Del,
1229 typename enable_if<__and_<
1230 __not_<is_array<_Tp>>, is_array<_Tp1>,
1231 is_convertible<typename unique_ptr<_Tp1, _Del>::pointer, _Tp*>
1232 >::value, bool>::type = true>
1233 __shared_ptr(unique_ptr<_Tp1, _Del>&& __r, __sp_array_delete)
1234 : _M_ptr(__r.get()), _M_refcount()
1235 {
1236 auto __raw = __to_address(__r.get());
1237 _M_refcount = __shared_count<_Lp>(std::move(__r));
1238 _M_enable_shared_from_this_with(__raw);
1239 }
1240 public:
1241#endif
1242
1243#if _GLIBCXX_USE_DEPRECATED1
1244#pragma GCC diagnostic push
1245#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
1246 // Postcondition: use_count() == 1 and __r.get() == 0
1247 template<typename _Yp, typename = _Compatible<_Yp>>
1248 __shared_ptr(auto_ptr<_Yp>&& __r);
1249#pragma GCC diagnostic pop
1250#endif
1251
1252 constexpr __shared_ptr(nullptr_t) noexcept : __shared_ptr() { }
1253
1254 template<typename _Yp>
1255 _Assignable<_Yp>
1256 operator=(const __shared_ptr<_Yp, _Lp>& __r) noexcept
1257 {
1258 _M_ptr = __r._M_ptr;
1259 _M_refcount = __r._M_refcount; // __shared_count::op= doesn't throw
1260 return *this;
1261 }
1262
1263#if _GLIBCXX_USE_DEPRECATED1
1264#pragma GCC diagnostic push
1265#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
1266 template<typename _Yp>
1267 _Assignable<_Yp>
1268 operator=(auto_ptr<_Yp>&& __r)
1269 {
1270 __shared_ptr(std::move(__r)).swap(*this);
1271 return *this;
1272 }
1273#pragma GCC diagnostic pop
1274#endif
1275
1276 __shared_ptr&
1277 operator=(__shared_ptr&& __r) noexcept
1278 {
1279 __shared_ptr(std::move(__r)).swap(*this);
1280 return *this;
1281 }
1282
1283 template<class _Yp>
1284 _Assignable<_Yp>
1285 operator=(__shared_ptr<_Yp, _Lp>&& __r) noexcept
1286 {
1287 __shared_ptr(std::move(__r)).swap(*this);
1288 return *this;
1289 }
1290
1291 template<typename _Yp, typename _Del>
1292 _UniqAssignable<_Yp, _Del>
1293 operator=(unique_ptr<_Yp, _Del>&& __r)
1294 {
1295 __shared_ptr(std::move(__r)).swap(*this);
1296 return *this;
1297 }
1298
1299 void
1300 reset() noexcept
1301 { __shared_ptr().swap(*this); }
1302
1303 template<typename _Yp>
1304 _SafeConv<_Yp>
1305 reset(_Yp* __p) // _Yp must be complete.
1306 {
1307 // Catch self-reset errors.
1308 __glibcxx_assert(__p == 0 || __p != _M_ptr);
1309 __shared_ptr(__p).swap(*this);
1310 }
1311
1312 template<typename _Yp, typename _Deleter>
1313 _SafeConv<_Yp>
1314 reset(_Yp* __p, _Deleter __d)
1315 { __shared_ptr(__p, std::move(__d)).swap(*this); }
1316
1317 template<typename _Yp, typename _Deleter, typename _Alloc>
1318 _SafeConv<_Yp>
1319 reset(_Yp* __p, _Deleter __d, _Alloc __a)
1320 { __shared_ptr(__p, std::move(__d), std::move(__a)).swap(*this); }
1321
1322 /// Return the stored pointer.
1323 element_type*
1324 get() const noexcept
1325 { return _M_ptr; }
1326
1327 /// Return true if the stored pointer is not null.
1328 explicit operator bool() const // never throws
1329 { return _M_ptr == 0 ? false : true; }
1330
1331 /// Return true if use_count() == 1.
1332 bool
1333 unique() const noexcept
1334 { return _M_refcount._M_unique(); }
1335
1336 /// If *this owns a pointer, return the number of owners, otherwise zero.
1337 long
1338 use_count() const noexcept
1339 { return _M_refcount._M_get_use_count(); }
1340
1341 /// Exchange both the owned pointer and the stored pointer.
1342 void
1343 swap(__shared_ptr<_Tp, _Lp>& __other) noexcept
1344 {
1345 std::swap(_M_ptr, __other._M_ptr);
1346 _M_refcount._M_swap(__other._M_refcount);
1347 }
1348
1349 /** @brief Define an ordering based on ownership.
1350 *
1351 * This function defines a strict weak ordering between two shared_ptr
1352 * or weak_ptr objects, such that one object is less than the other
1353 * unless they share ownership of the same pointer, or are both empty.
1354 * @{
1355 */
1356 template<typename _Tp1>
1357 bool
1358 owner_before(__shared_ptr<_Tp1, _Lp> const& __rhs) const noexcept
1359 { return _M_refcount._M_less(__rhs._M_refcount); }
1360
1361 template<typename _Tp1>
1362 bool
1363 owner_before(__weak_ptr<_Tp1, _Lp> const& __rhs) const noexcept
1364 { return _M_refcount._M_less(__rhs._M_refcount); }
1365 // @}
1366
1367 protected:
1368 // This constructor is non-standard, it is used by allocate_shared.
1369 template<typename _Alloc, typename... _Args>
1370 __shared_ptr(_Sp_alloc_shared_tag<_Alloc> __tag, _Args&&... __args)
1371 : _M_ptr(), _M_refcount(_M_ptr, __tag, std::forward<_Args>(__args)...)
17
Calling constructor for '__shared_count<__gnu_cxx::_S_atomic>'
27
Returning from constructor for '__shared_count<__gnu_cxx::_S_atomic>'
1372 { _M_enable_shared_from_this_with(_M_ptr); }
1373
1374 template<typename _Tp1, _Lock_policy _Lp1, typename _Alloc,
1375 typename... _Args>
1376 friend __shared_ptr<_Tp1, _Lp1>
1377 __allocate_shared(const _Alloc& __a, _Args&&... __args);
1378
1379 // This constructor is used by __weak_ptr::lock() and
1380 // shared_ptr::shared_ptr(const weak_ptr&, std::nothrow_t).
1381 __shared_ptr(const __weak_ptr<_Tp, _Lp>& __r, std::nothrow_t)
1382 : _M_refcount(__r._M_refcount, std::nothrow)
1383 {
1384 _M_ptr = _M_refcount._M_get_use_count() ? __r._M_ptr : nullptr;
1385 }
1386
1387 friend class __weak_ptr<_Tp, _Lp>;
1388
1389 private:
1390
1391 template<typename _Yp>
1392 using __esft_base_t = decltype(__enable_shared_from_this_base(
1393 std::declval<const __shared_count<_Lp>&>(),
1394 std::declval<_Yp*>()));
1395
1396 // Detect an accessible and unambiguous enable_shared_from_this base.
1397 template<typename _Yp, typename = void>
1398 struct __has_esft_base
1399 : false_type { };
1400
1401 template<typename _Yp>
1402 struct __has_esft_base<_Yp, __void_t<__esft_base_t<_Yp>>>
1403 : __not_<is_array<_Tp>> { }; // No enable shared_from_this for arrays
1404
1405 template<typename _Yp, typename _Yp2 = typename remove_cv<_Yp>::type>
1406 typename enable_if<__has_esft_base<_Yp2>::value>::type
1407 _M_enable_shared_from_this_with(_Yp* __p) noexcept
1408 {
1409 if (auto __base = __enable_shared_from_this_base(_M_refcount, __p))
1410 __base->_M_weak_assign(const_cast<_Yp2*>(__p), _M_refcount);
1411 }
1412
1413 template<typename _Yp, typename _Yp2 = typename remove_cv<_Yp>::type>
1414 typename enable_if<!__has_esft_base<_Yp2>::value>::type
1415 _M_enable_shared_from_this_with(_Yp*) noexcept
1416 { }
1417
1418 void*
1419 _M_get_deleter(const std::type_info& __ti) const noexcept
1420 { return _M_refcount._M_get_deleter(__ti); }
1421
1422 template<typename _Tp1, _Lock_policy _Lp1> friend class __shared_ptr;
1423 template<typename _Tp1, _Lock_policy _Lp1> friend class __weak_ptr;
1424
1425 template<typename _Del, typename _Tp1, _Lock_policy _Lp1>
1426 friend _Del* get_deleter(const __shared_ptr<_Tp1, _Lp1>&) noexcept;
1427
1428 template<typename _Del, typename _Tp1>
1429 friend _Del* get_deleter(const shared_ptr<_Tp1>&) noexcept;
1430
1431 element_type* _M_ptr; // Contained pointer.
1432 __shared_count<_Lp> _M_refcount; // Reference counter.
1433 };
1434
1435
1436 // 20.7.2.2.7 shared_ptr comparisons
1437 template<typename _Tp1, typename _Tp2, _Lock_policy _Lp>
1438 inline bool
1439 operator==(const __shared_ptr<_Tp1, _Lp>& __a,
1440 const __shared_ptr<_Tp2, _Lp>& __b) noexcept
1441 { return __a.get() == __b.get(); }
1442
1443 template<typename _Tp, _Lock_policy _Lp>
1444 inline bool
1445 operator==(const __shared_ptr<_Tp, _Lp>& __a, nullptr_t) noexcept
1446 { return !__a; }
1447
1448#ifdef __cpp_lib_three_way_comparison
1449 template<typename _Tp, typename _Up, _Lock_policy _Lp>
1450 inline strong_ordering
1451 operator<=>(const __shared_ptr<_Tp, _Lp>& __a,
1452 const __shared_ptr<_Up, _Lp>& __b) noexcept
1453 { return compare_three_way()(__a.get(), __b.get()); }
1454
1455 template<typename _Tp, _Lock_policy _Lp>
1456 inline strong_ordering
1457 operator<=>(const __shared_ptr<_Tp, _Lp>& __a, nullptr_t) noexcept
1458 {
1459 using pointer = typename __shared_ptr<_Tp, _Lp>::element_type*;
1460 return compare_three_way()(__a.get(), static_cast<pointer>(nullptr));
1461 }
1462#else
1463 template<typename _Tp, _Lock_policy _Lp>
1464 inline bool
1465 operator==(nullptr_t, const __shared_ptr<_Tp, _Lp>& __a) noexcept
1466 { return !__a; }
1467
1468 template<typename _Tp1, typename _Tp2, _Lock_policy _Lp>
1469 inline bool
1470 operator!=(const __shared_ptr<_Tp1, _Lp>& __a,
1471 const __shared_ptr<_Tp2, _Lp>& __b) noexcept
1472 { return __a.get() != __b.get(); }
1473
1474 template<typename _Tp, _Lock_policy _Lp>
1475 inline bool
1476 operator!=(const __shared_ptr<_Tp, _Lp>& __a, nullptr_t) noexcept
1477 { return (bool)__a; }
1478
1479 template<typename _Tp, _Lock_policy _Lp>
1480 inline bool
1481 operator!=(nullptr_t, const __shared_ptr<_Tp, _Lp>& __a) noexcept
1482 { return (bool)__a; }
1483
1484 template<typename _Tp, typename _Up, _Lock_policy _Lp>
1485 inline bool
1486 operator<(const __shared_ptr<_Tp, _Lp>& __a,
1487 const __shared_ptr<_Up, _Lp>& __b) noexcept
1488 {
1489 using _Tp_elt = typename __shared_ptr<_Tp, _Lp>::element_type;
1490 using _Up_elt = typename __shared_ptr<_Up, _Lp>::element_type;
1491 using _Vp = typename common_type<_Tp_elt*, _Up_elt*>::type;
1492 return less<_Vp>()(__a.get(), __b.get());
1493 }
1494
1495 template<typename _Tp, _Lock_policy _Lp>
1496 inline bool
1497 operator<(const __shared_ptr<_Tp, _Lp>& __a, nullptr_t) noexcept
1498 {
1499 using _Tp_elt = typename __shared_ptr<_Tp, _Lp>::element_type;
1500 return less<_Tp_elt*>()(__a.get(), nullptr);
1501 }
1502
1503 template<typename _Tp, _Lock_policy _Lp>
1504 inline bool
1505 operator<(nullptr_t, const __shared_ptr<_Tp, _Lp>& __a) noexcept
1506 {
1507 using _Tp_elt = typename __shared_ptr<_Tp, _Lp>::element_type;
1508 return less<_Tp_elt*>()(nullptr, __a.get());
1509 }
1510
1511 template<typename _Tp1, typename _Tp2, _Lock_policy _Lp>
1512 inline bool
1513 operator<=(const __shared_ptr<_Tp1, _Lp>& __a,
1514 const __shared_ptr<_Tp2, _Lp>& __b) noexcept
1515 { return !(__b < __a); }
1516
1517 template<typename _Tp, _Lock_policy _Lp>
1518 inline bool
1519 operator<=(const __shared_ptr<_Tp, _Lp>& __a, nullptr_t) noexcept
1520 { return !(nullptr < __a); }
1521
1522 template<typename _Tp, _Lock_policy _Lp>
1523 inline bool
1524 operator<=(nullptr_t, const __shared_ptr<_Tp, _Lp>& __a) noexcept
1525 { return !(__a < nullptr); }
1526
1527 template<typename _Tp1, typename _Tp2, _Lock_policy _Lp>
1528 inline bool
1529 operator>(const __shared_ptr<_Tp1, _Lp>& __a,
1530 const __shared_ptr<_Tp2, _Lp>& __b) noexcept
1531 { return (__b < __a); }
1532
1533 template<typename _Tp, _Lock_policy _Lp>
1534 inline bool
1535 operator>(const __shared_ptr<_Tp, _Lp>& __a, nullptr_t) noexcept
1536 { return nullptr < __a; }
1537
1538 template<typename _Tp, _Lock_policy _Lp>
1539 inline bool
1540 operator>(nullptr_t, const __shared_ptr<_Tp, _Lp>& __a) noexcept
1541 { return __a < nullptr; }
1542
1543 template<typename _Tp1, typename _Tp2, _Lock_policy _Lp>
1544 inline bool
1545 operator>=(const __shared_ptr<_Tp1, _Lp>& __a,
1546 const __shared_ptr<_Tp2, _Lp>& __b) noexcept
1547 { return !(__a < __b); }
1548
1549 template<typename _Tp, _Lock_policy _Lp>
1550 inline bool
1551 operator>=(const __shared_ptr<_Tp, _Lp>& __a, nullptr_t) noexcept
1552 { return !(__a < nullptr); }
1553
1554 template<typename _Tp, _Lock_policy _Lp>
1555 inline bool
1556 operator>=(nullptr_t, const __shared_ptr<_Tp, _Lp>& __a) noexcept
1557 { return !(nullptr < __a); }
1558#endif // three-way comparison
1559
1560 // 20.7.2.2.8 shared_ptr specialized algorithms.
1561 template<typename _Tp, _Lock_policy _Lp>
1562 inline void
1563 swap(__shared_ptr<_Tp, _Lp>& __a, __shared_ptr<_Tp, _Lp>& __b) noexcept
1564 { __a.swap(__b); }
1565
1566 // 20.7.2.2.9 shared_ptr casts
1567
1568 // The seemingly equivalent code:
1569 // shared_ptr<_Tp, _Lp>(static_cast<_Tp*>(__r.get()))
1570 // will eventually result in undefined behaviour, attempting to
1571 // delete the same object twice.
1572 /// static_pointer_cast
1573 template<typename _Tp, typename _Tp1, _Lock_policy _Lp>
1574 inline __shared_ptr<_Tp, _Lp>
1575 static_pointer_cast(const __shared_ptr<_Tp1, _Lp>& __r) noexcept
1576 {
1577 using _Sp = __shared_ptr<_Tp, _Lp>;
1578 return _Sp(__r, static_cast<typename _Sp::element_type*>(__r.get()));
1579 }
1580
1581 // The seemingly equivalent code:
1582 // shared_ptr<_Tp, _Lp>(const_cast<_Tp*>(__r.get()))
1583 // will eventually result in undefined behaviour, attempting to
1584 // delete the same object twice.
1585 /// const_pointer_cast
1586 template<typename _Tp, typename _Tp1, _Lock_policy _Lp>
1587 inline __shared_ptr<_Tp, _Lp>
1588 const_pointer_cast(const __shared_ptr<_Tp1, _Lp>& __r) noexcept
1589 {
1590 using _Sp = __shared_ptr<_Tp, _Lp>;
1591 return _Sp(__r, const_cast<typename _Sp::element_type*>(__r.get()));
1592 }
1593
1594 // The seemingly equivalent code:
1595 // shared_ptr<_Tp, _Lp>(dynamic_cast<_Tp*>(__r.get()))
1596 // will eventually result in undefined behaviour, attempting to
1597 // delete the same object twice.
1598 /// dynamic_pointer_cast
1599 template<typename _Tp, typename _Tp1, _Lock_policy _Lp>
1600 inline __shared_ptr<_Tp, _Lp>
1601 dynamic_pointer_cast(const __shared_ptr<_Tp1, _Lp>& __r) noexcept
1602 {
1603 using _Sp = __shared_ptr<_Tp, _Lp>;
1604 if (auto* __p = dynamic_cast<typename _Sp::element_type*>(__r.get()))
1605 return _Sp(__r, __p);
1606 return _Sp();
1607 }
1608
1609#if __cplusplus201703L > 201402L
1610 template<typename _Tp, typename _Tp1, _Lock_policy _Lp>
1611 inline __shared_ptr<_Tp, _Lp>
1612 reinterpret_pointer_cast(const __shared_ptr<_Tp1, _Lp>& __r) noexcept
1613 {
1614 using _Sp = __shared_ptr<_Tp, _Lp>;
1615 return _Sp(__r, reinterpret_cast<typename _Sp::element_type*>(__r.get()));
1616 }
1617#endif
1618
1619 template<typename _Tp, _Lock_policy _Lp>
1620 class __weak_ptr
1621 {
1622 template<typename _Yp, typename _Res = void>
1623 using _Compatible = typename
1624 enable_if<__sp_compatible_with<_Yp*, _Tp*>::value, _Res>::type;
1625
1626 // Constraint for assignment from shared_ptr and weak_ptr:
1627 template<typename _Yp>
1628 using _Assignable = _Compatible<_Yp, __weak_ptr&>;
1629
1630 public:
1631 using element_type = typename remove_extent<_Tp>::type;
1632
1633 constexpr __weak_ptr() noexcept
1634 : _M_ptr(nullptr), _M_refcount()
1635 { }
1636
1637 __weak_ptr(const __weak_ptr&) noexcept = default;
1638
1639 ~__weak_ptr() = default;
1640
1641 // The "obvious" converting constructor implementation:
1642 //
1643 // template<typename _Tp1>
1644 // __weak_ptr(const __weak_ptr<_Tp1, _Lp>& __r)
1645 // : _M_ptr(__r._M_ptr), _M_refcount(__r._M_refcount) // never throws
1646 // { }
1647 //
1648 // has a serious problem.
1649 //
1650 // __r._M_ptr may already have been invalidated. The _M_ptr(__r._M_ptr)
1651 // conversion may require access to *__r._M_ptr (virtual inheritance).
1652 //
1653 // It is not possible to avoid spurious access violations since
1654 // in multithreaded programs __r._M_ptr may be invalidated at any point.
1655 template<typename _Yp, typename = _Compatible<_Yp>>
1656 __weak_ptr(const __weak_ptr<_Yp, _Lp>& __r) noexcept
1657 : _M_refcount(__r._M_refcount)
1658 { _M_ptr = __r.lock().get(); }
1659
1660 template<typename _Yp, typename = _Compatible<_Yp>>
1661 __weak_ptr(const __shared_ptr<_Yp, _Lp>& __r) noexcept
1662 : _M_ptr(__r._M_ptr), _M_refcount(__r._M_refcount)
1663 { }
1664
1665 __weak_ptr(__weak_ptr&& __r) noexcept
1666 : _M_ptr(__r._M_ptr), _M_refcount(std::move(__r._M_refcount))
1667 { __r._M_ptr = nullptr; }
1668
1669 template<typename _Yp, typename = _Compatible<_Yp>>
1670 __weak_ptr(__weak_ptr<_Yp, _Lp>&& __r) noexcept
1671 : _M_ptr(__r.lock().get()), _M_refcount(std::move(__r._M_refcount))
1672 { __r._M_ptr = nullptr; }
1673
1674 __weak_ptr&
1675 operator=(const __weak_ptr& __r) noexcept = default;
1676
1677 template<typename _Yp>
1678 _Assignable<_Yp>
1679 operator=(const __weak_ptr<_Yp, _Lp>& __r) noexcept
1680 {
1681 _M_ptr = __r.lock().get();
1682 _M_refcount = __r._M_refcount;
1683 return *this;
1684 }
1685
1686 template<typename _Yp>
1687 _Assignable<_Yp>
1688 operator=(const __shared_ptr<_Yp, _Lp>& __r) noexcept
1689 {
1690 _M_ptr = __r._M_ptr;
1691 _M_refcount = __r._M_refcount;
1692 return *this;
1693 }
1694
1695 __weak_ptr&
1696 operator=(__weak_ptr&& __r) noexcept
1697 {
1698 _M_ptr = __r._M_ptr;
1699 _M_refcount = std::move(__r._M_refcount);
1700 __r._M_ptr = nullptr;
1701 return *this;
1702 }
1703
1704 template<typename _Yp>
1705 _Assignable<_Yp>
1706 operator=(__weak_ptr<_Yp, _Lp>&& __r) noexcept
1707 {
1708 _M_ptr = __r.lock().get();
1709 _M_refcount = std::move(__r._M_refcount);
1710 __r._M_ptr = nullptr;
1711 return *this;
1712 }
1713
1714 __shared_ptr<_Tp, _Lp>
1715 lock() const noexcept
1716 { return __shared_ptr<element_type, _Lp>(*this, std::nothrow); }
1717
1718 long
1719 use_count() const noexcept
1720 { return _M_refcount._M_get_use_count(); }
1721
1722 bool
1723 expired() const noexcept
1724 { return _M_refcount._M_get_use_count() == 0; }
1725
1726 template<typename _Tp1>
1727 bool
1728 owner_before(const __shared_ptr<_Tp1, _Lp>& __rhs) const noexcept
1729 { return _M_refcount._M_less(__rhs._M_refcount); }
1730
1731 template<typename _Tp1>
1732 bool
1733 owner_before(const __weak_ptr<_Tp1, _Lp>& __rhs) const noexcept
1734 { return _M_refcount._M_less(__rhs._M_refcount); }
1735
1736 void
1737 reset() noexcept
1738 { __weak_ptr().swap(*this); }
1739
1740 void
1741 swap(__weak_ptr& __s) noexcept
1742 {
1743 std::swap(_M_ptr, __s._M_ptr);
1744 _M_refcount._M_swap(__s._M_refcount);
1745 }
1746
1747 private:
1748 // Used by __enable_shared_from_this.
1749 void
1750 _M_assign(_Tp* __ptr, const __shared_count<_Lp>& __refcount) noexcept
1751 {
1752 if (use_count() == 0)
1753 {
1754 _M_ptr = __ptr;
1755 _M_refcount = __refcount;
1756 }
1757 }
1758
1759 template<typename _Tp1, _Lock_policy _Lp1> friend class __shared_ptr;
1760 template<typename _Tp1, _Lock_policy _Lp1> friend class __weak_ptr;
1761 friend class __enable_shared_from_this<_Tp, _Lp>;
1762 friend class enable_shared_from_this<_Tp>;
1763
1764 element_type* _M_ptr; // Contained pointer.
1765 __weak_count<_Lp> _M_refcount; // Reference counter.
1766 };
1767
1768 // 20.7.2.3.6 weak_ptr specialized algorithms.
1769 template<typename _Tp, _Lock_policy _Lp>
1770 inline void
1771 swap(__weak_ptr<_Tp, _Lp>& __a, __weak_ptr<_Tp, _Lp>& __b) noexcept
1772 { __a.swap(__b); }
1773
1774 template<typename _Tp, typename _Tp1>
1775 struct _Sp_owner_less : public binary_function<_Tp, _Tp, bool>
1776 {
1777 bool
1778 operator()(const _Tp& __lhs, const _Tp& __rhs) const noexcept
1779 { return __lhs.owner_before(__rhs); }
1780
1781 bool
1782 operator()(const _Tp& __lhs, const _Tp1& __rhs) const noexcept
1783 { return __lhs.owner_before(__rhs); }
1784
1785 bool
1786 operator()(const _Tp1& __lhs, const _Tp& __rhs) const noexcept
1787 { return __lhs.owner_before(__rhs); }
1788 };
1789
1790 template<>
1791 struct _Sp_owner_less<void, void>
1792 {
1793 template<typename _Tp, typename _Up>
1794 auto
1795 operator()(const _Tp& __lhs, const _Up& __rhs) const noexcept
1796 -> decltype(__lhs.owner_before(__rhs))
1797 { return __lhs.owner_before(__rhs); }
1798
1799 using is_transparent = void;
1800 };
1801
1802 template<typename _Tp, _Lock_policy _Lp>
1803 struct owner_less<__shared_ptr<_Tp, _Lp>>
1804 : public _Sp_owner_less<__shared_ptr<_Tp, _Lp>, __weak_ptr<_Tp, _Lp>>
1805 { };
1806
1807 template<typename _Tp, _Lock_policy _Lp>
1808 struct owner_less<__weak_ptr<_Tp, _Lp>>
1809 : public _Sp_owner_less<__weak_ptr<_Tp, _Lp>, __shared_ptr<_Tp, _Lp>>
1810 { };
1811
1812
1813 template<typename _Tp, _Lock_policy _Lp>
1814 class __enable_shared_from_this
1815 {
1816 protected:
1817 constexpr __enable_shared_from_this() noexcept { }
1818
1819 __enable_shared_from_this(const __enable_shared_from_this&) noexcept { }
1820
1821 __enable_shared_from_this&
1822 operator=(const __enable_shared_from_this&) noexcept
1823 { return *this; }
1824
1825 ~__enable_shared_from_this() { }
1826
1827 public:
1828 __shared_ptr<_Tp, _Lp>
1829 shared_from_this()
1830 { return __shared_ptr<_Tp, _Lp>(this->_M_weak_this); }
1831
1832 __shared_ptr<const _Tp, _Lp>
1833 shared_from_this() const
1834 { return __shared_ptr<const _Tp, _Lp>(this->_M_weak_this); }
1835
1836#if __cplusplus201703L > 201402L || !defined(__STRICT_ANSI__1) // c++1z or gnu++11
1837 __weak_ptr<_Tp, _Lp>
1838 weak_from_this() noexcept
1839 { return this->_M_weak_this; }
1840
1841 __weak_ptr<const _Tp, _Lp>
1842 weak_from_this() const noexcept
1843 { return this->_M_weak_this; }
1844#endif
1845
1846 private:
1847 template<typename _Tp1>
1848 void
1849 _M_weak_assign(_Tp1* __p, const __shared_count<_Lp>& __n) const noexcept
1850 { _M_weak_this._M_assign(__p, __n); }
1851
1852 friend const __enable_shared_from_this*
1853 __enable_shared_from_this_base(const __shared_count<_Lp>&,
1854 const __enable_shared_from_this* __p)
1855 { return __p; }
1856
1857 template<typename, _Lock_policy>
1858 friend class __shared_ptr;
1859
1860 mutable __weak_ptr<_Tp, _Lp> _M_weak_this;
1861 };
1862
1863 template<typename _Tp, _Lock_policy _Lp = __default_lock_policy,
1864 typename _Alloc, typename... _Args>
1865 inline __shared_ptr<_Tp, _Lp>
1866 __allocate_shared(const _Alloc& __a, _Args&&... __args)
1867 {
1868 return __shared_ptr<_Tp, _Lp>(_Sp_alloc_shared_tag<_Alloc>{__a},
1869 std::forward<_Args>(__args)...);
1870 }
1871
1872 template<typename _Tp, _Lock_policy _Lp = __default_lock_policy,
1873 typename... _Args>
1874 inline __shared_ptr<_Tp, _Lp>
1875 __make_shared(_Args&&... __args)
1876 {
1877 typedef typename std::remove_const<_Tp>::type _Tp_nc;
1878 return std::__allocate_shared<_Tp, _Lp>(std::allocator<_Tp_nc>(),
1879 std::forward<_Args>(__args)...);
1880 }
1881
1882 /// std::hash specialization for __shared_ptr.
1883 template<typename _Tp, _Lock_policy _Lp>
1884 struct hash<__shared_ptr<_Tp, _Lp>>
1885 : public __hash_base<size_t, __shared_ptr<_Tp, _Lp>>
1886 {
1887 size_t
1888 operator()(const __shared_ptr<_Tp, _Lp>& __s) const noexcept
1889 {
1890 return hash<typename __shared_ptr<_Tp, _Lp>::element_type*>()(
1891 __s.get());
1892 }
1893 };
1894
1895_GLIBCXX_END_NAMESPACE_VERSION
1896} // namespace
1897
1898#endif // _SHARED_PTR_BASE_H

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

1// Guarded Allocation -*- C++ -*-
2
3// Copyright (C) 2014-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/allocated_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 _ALLOCATED_PTR_H1
31#define _ALLOCATED_PTR_H1 1
32
33#if __cplusplus201703L < 201103L
34# include <bits/c++0xwarning.h>
35#else
36# include <type_traits>
37# include <bits/ptr_traits.h>
38# include <bits/alloc_traits.h>
39
40namespace std _GLIBCXX_VISIBILITY(default)__attribute__ ((__visibility__ ("default")))
41{
42_GLIBCXX_BEGIN_NAMESPACE_VERSION
43
44 /// Non-standard RAII type for managing pointers obtained from allocators.
45 template<typename _Alloc>
46 struct __allocated_ptr
47 {
48 using pointer = typename allocator_traits<_Alloc>::pointer;
49 using value_type = typename allocator_traits<_Alloc>::value_type;
50
51 /// Take ownership of __ptr
52 __allocated_ptr(_Alloc& __a, pointer __ptr) noexcept
53 : _M_alloc(std::__addressof(__a)), _M_ptr(__ptr)
54 { }
55
56 /// Convert __ptr to allocator's pointer type and take ownership of it
57 template<typename _Ptr,
58 typename _Req = _Require<is_same<_Ptr, value_type*>>>
59 __allocated_ptr(_Alloc& __a, _Ptr __ptr)
60 : _M_alloc(std::__addressof(__a)),
61 _M_ptr(pointer_traits<pointer>::pointer_to(*__ptr))
62 { }
63
64 /// Transfer ownership of the owned pointer
65 __allocated_ptr(__allocated_ptr&& __gd) noexcept
66 : _M_alloc(__gd._M_alloc), _M_ptr(__gd._M_ptr)
67 { __gd._M_ptr = nullptr; }
68
69 /// Deallocate the owned pointer
70 ~__allocated_ptr()
71 {
72 if (_M_ptr != nullptr)
73 std::allocator_traits<_Alloc>::deallocate(*_M_alloc, _M_ptr, 1);
74 }
75
76 /// Release ownership of the owned pointer
77 __allocated_ptr&
78 operator=(std::nullptr_t) noexcept
79 {
80 _M_ptr = nullptr;
81 return *this;
82 }
83
84 /// Get the address that the owned pointer refers to.
85 value_type* get() { return std::__to_address(_M_ptr); }
86
87 private:
88 _Alloc* _M_alloc;
89 pointer _M_ptr;
90 };
91
92 /// Allocate space for a single object using __a
93 template<typename _Alloc>
94 __allocated_ptr<_Alloc>
95 __allocate_guarded(_Alloc& __a)
96 {
97 return { __a, std::allocator_traits<_Alloc>::allocate(__a, 1) };
19
Calling 'allocator_traits::allocate'
25
Returned allocated memory
98 }
99
100_GLIBCXX_END_NAMESPACE_VERSION
101} // namespace std
102
103#endif
104#endif

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

1// Allocator traits -*- C++ -*-
2
3// Copyright (C) 2011-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/alloc_traits.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 _ALLOC_TRAITS_H1
31#define _ALLOC_TRAITS_H1 1
32
33#include <bits/stl_construct.h>
34#include <bits/memoryfwd.h>
35#if __cplusplus201703L >= 201103L
36# include <bits/allocator.h>
37# include <bits/ptr_traits.h>
38# include <ext/numeric_traits.h>
39#endif
40
41namespace std _GLIBCXX_VISIBILITY(default)__attribute__ ((__visibility__ ("default")))
42{
43_GLIBCXX_BEGIN_NAMESPACE_VERSION
44
45#if __cplusplus201703L >= 201103L
46#define __cpp_lib_allocator_traits_is_always_equal201411 201411
47
48 struct __allocator_traits_base
49 {
50 template<typename _Tp, typename _Up, typename = void>
51 struct __rebind : __replace_first_arg<_Tp, _Up> { };
52
53 template<typename _Tp, typename _Up>
54 struct __rebind<_Tp, _Up,
55 __void_t<typename _Tp::template rebind<_Up>::other>>
56 { using type = typename _Tp::template rebind<_Up>::other; };
57
58 protected:
59 template<typename _Tp>
60 using __pointer = typename _Tp::pointer;
61 template<typename _Tp>
62 using __c_pointer = typename _Tp::const_pointer;
63 template<typename _Tp>
64 using __v_pointer = typename _Tp::void_pointer;
65 template<typename _Tp>
66 using __cv_pointer = typename _Tp::const_void_pointer;
67 template<typename _Tp>
68 using __pocca = typename _Tp::propagate_on_container_copy_assignment;
69 template<typename _Tp>
70 using __pocma = typename _Tp::propagate_on_container_move_assignment;
71 template<typename _Tp>
72 using __pocs = typename _Tp::propagate_on_container_swap;
73 template<typename _Tp>
74 using __equal = typename _Tp::is_always_equal;
75 };
76
77 template<typename _Alloc, typename _Up>
78 using __alloc_rebind
79 = typename __allocator_traits_base::template __rebind<_Alloc, _Up>::type;
80
81 /**
82 * @brief Uniform interface to all allocator types.
83 * @ingroup allocators
84 */
85 template<typename _Alloc>
86 struct allocator_traits : __allocator_traits_base
87 {
88 /// The allocator type
89 typedef _Alloc allocator_type;
90 /// The allocated type
91 typedef typename _Alloc::value_type value_type;
92
93 /**
94 * @brief The allocator's pointer type.
95 *
96 * @c Alloc::pointer if that type exists, otherwise @c value_type*
97 */
98 using pointer = __detected_or_t<value_type*, __pointer, _Alloc>;
99
100 private:
101 // Select _Func<_Alloc> or pointer_traits<pointer>::rebind<_Tp>
102 template<template<typename> class _Func, typename _Tp, typename = void>
103 struct _Ptr
104 {
105 using type = typename pointer_traits<pointer>::template rebind<_Tp>;
106 };
107
108 template<template<typename> class _Func, typename _Tp>
109 struct _Ptr<_Func, _Tp, __void_t<_Func<_Alloc>>>
110 {
111 using type = _Func<_Alloc>;
112 };
113
114 // Select _A2::difference_type or pointer_traits<_Ptr>::difference_type
115 template<typename _A2, typename _PtrT, typename = void>
116 struct _Diff
117 { using type = typename pointer_traits<_PtrT>::difference_type; };
118
119 template<typename _A2, typename _PtrT>
120 struct _Diff<_A2, _PtrT, __void_t<typename _A2::difference_type>>
121 { using type = typename _A2::difference_type; };
122
123 // Select _A2::size_type or make_unsigned<_DiffT>::type
124 template<typename _A2, typename _DiffT, typename = void>
125 struct _Size : make_unsigned<_DiffT> { };
126
127 template<typename _A2, typename _DiffT>
128 struct _Size<_A2, _DiffT, __void_t<typename _A2::size_type>>
129 { using type = typename _A2::size_type; };
130
131 public:
132 /**
133 * @brief The allocator's const pointer type.
134 *
135 * @c Alloc::const_pointer if that type exists, otherwise
136 * <tt> pointer_traits<pointer>::rebind<const value_type> </tt>
137 */
138 using const_pointer = typename _Ptr<__c_pointer, const value_type>::type;
139
140 /**
141 * @brief The allocator's void pointer type.
142 *
143 * @c Alloc::void_pointer if that type exists, otherwise
144 * <tt> pointer_traits<pointer>::rebind<void> </tt>
145 */
146 using void_pointer = typename _Ptr<__v_pointer, void>::type;
147
148 /**
149 * @brief The allocator's const void pointer type.
150 *
151 * @c Alloc::const_void_pointer if that type exists, otherwise
152 * <tt> pointer_traits<pointer>::rebind<const void> </tt>
153 */
154 using const_void_pointer = typename _Ptr<__cv_pointer, const void>::type;
155
156 /**
157 * @brief The allocator's difference type
158 *
159 * @c Alloc::difference_type if that type exists, otherwise
160 * <tt> pointer_traits<pointer>::difference_type </tt>
161 */
162 using difference_type = typename _Diff<_Alloc, pointer>::type;
163
164 /**
165 * @brief The allocator's size type
166 *
167 * @c Alloc::size_type if that type exists, otherwise
168 * <tt> make_unsigned<difference_type>::type </tt>
169 */
170 using size_type = typename _Size<_Alloc, difference_type>::type;
171
172 /**
173 * @brief How the allocator is propagated on copy assignment
174 *
175 * @c Alloc::propagate_on_container_copy_assignment if that type exists,
176 * otherwise @c false_type
177 */
178 using propagate_on_container_copy_assignment
179 = __detected_or_t<false_type, __pocca, _Alloc>;
180
181 /**
182 * @brief How the allocator is propagated on move assignment
183 *
184 * @c Alloc::propagate_on_container_move_assignment if that type exists,
185 * otherwise @c false_type
186 */
187 using propagate_on_container_move_assignment
188 = __detected_or_t<false_type, __pocma, _Alloc>;
189
190 /**
191 * @brief How the allocator is propagated on swap
192 *
193 * @c Alloc::propagate_on_container_swap if that type exists,
194 * otherwise @c false_type
195 */
196 using propagate_on_container_swap
197 = __detected_or_t<false_type, __pocs, _Alloc>;
198
199 /**
200 * @brief Whether all instances of the allocator type compare equal.
201 *
202 * @c Alloc::is_always_equal if that type exists,
203 * otherwise @c is_empty<Alloc>::type
204 */
205 using is_always_equal
206 = __detected_or_t<typename is_empty<_Alloc>::type, __equal, _Alloc>;
207
208 template<typename _Tp>
209 using rebind_alloc = __alloc_rebind<_Alloc, _Tp>;
210 template<typename _Tp>
211 using rebind_traits = allocator_traits<rebind_alloc<_Tp>>;
212
213 private:
214 template<typename _Alloc2>
215 static constexpr auto
216 _S_allocate(_Alloc2& __a, size_type __n, const_void_pointer __hint, int)
217 -> decltype(__a.allocate(__n, __hint))
218 { return __a.allocate(__n, __hint); }
219
220 template<typename _Alloc2>
221 static constexpr pointer
222 _S_allocate(_Alloc2& __a, size_type __n, const_void_pointer, ...)
223 { return __a.allocate(__n); }
224
225 template<typename _Tp, typename... _Args>
226 struct __construct_helper
227 {
228 template<typename _Alloc2,
229 typename = decltype(std::declval<_Alloc2*>()->construct(
230 std::declval<_Tp*>(), std::declval<_Args>()...))>
231 static true_type __test(int);
232
233 template<typename>
234 static false_type __test(...);
235
236 using type = decltype(__test<_Alloc>(0));
237 };
238
239 template<typename _Tp, typename... _Args>
240 using __has_construct
241 = typename __construct_helper<_Tp, _Args...>::type;
242
243 template<typename _Tp, typename... _Args>
244 static _GLIBCXX14_CONSTEXPRconstexpr _Require<__has_construct<_Tp, _Args...>>
245 _S_construct(_Alloc& __a, _Tp* __p, _Args&&... __args)
246 noexcept(noexcept(__a.construct(__p, std::forward<_Args>(__args)...)))
247 { __a.construct(__p, std::forward<_Args>(__args)...); }
248
249 template<typename _Tp, typename... _Args>
250 static _GLIBCXX14_CONSTEXPRconstexpr
251 _Require<__and_<__not_<__has_construct<_Tp, _Args...>>,
252 is_constructible<_Tp, _Args...>>>
253 _S_construct(_Alloc&, _Tp* __p, _Args&&... __args)
254 noexcept(std::is_nothrow_constructible<_Tp, _Args...>::value)
255 {
256#if __cplusplus201703L <= 201703L
257 ::new((void*)__p) _Tp(std::forward<_Args>(__args)...);
258#else
259 std::construct_at(__p, std::forward<_Args>(__args)...);
260#endif
261 }
262
263 template<typename _Alloc2, typename _Tp>
264 static _GLIBCXX14_CONSTEXPRconstexpr auto
265 _S_destroy(_Alloc2& __a, _Tp* __p, int)
266 noexcept(noexcept(__a.destroy(__p)))
267 -> decltype(__a.destroy(__p))
268 { __a.destroy(__p); }
269
270 template<typename _Alloc2, typename _Tp>
271 static _GLIBCXX14_CONSTEXPRconstexpr void
272 _S_destroy(_Alloc2&, _Tp* __p, ...)
273 noexcept(std::is_nothrow_destructible<_Tp>::value)
274 { std::_Destroy(__p); }
275
276 template<typename _Alloc2>
277 static constexpr auto
278 _S_max_size(_Alloc2& __a, int)
279 -> decltype(__a.max_size())
280 { return __a.max_size(); }
281
282 template<typename _Alloc2>
283 static constexpr size_type
284 _S_max_size(_Alloc2&, ...)
285 {
286 // _GLIBCXX_RESOLVE_LIB_DEFECTS
287 // 2466. allocator_traits::max_size() default behavior is incorrect
288 return __gnu_cxx::__numeric_traits<size_type>::__max
289 / sizeof(value_type);
290 }
291
292 template<typename _Alloc2>
293 static constexpr auto
294 _S_select(_Alloc2& __a, int)
295 -> decltype(__a.select_on_container_copy_construction())
296 { return __a.select_on_container_copy_construction(); }
297
298 template<typename _Alloc2>
299 static constexpr _Alloc2
300 _S_select(_Alloc2& __a, ...)
301 { return __a; }
302
303 public:
304
305 /**
306 * @brief Allocate memory.
307 * @param __a An allocator.
308 * @param __n The number of objects to allocate space for.
309 *
310 * Calls @c a.allocate(n)
311 */
312 _GLIBCXX_NODISCARD[[__nodiscard__]] static _GLIBCXX20_CONSTEXPR pointer
313 allocate(_Alloc& __a, size_type __n)
314 { return __a.allocate(__n); }
315
316 /**
317 * @brief Allocate memory.
318 * @param __a An allocator.
319 * @param __n The number of objects to allocate space for.
320 * @param __hint Aid to locality.
321 * @return Memory of suitable size and alignment for @a n objects
322 * of type @c value_type
323 *
324 * Returns <tt> a.allocate(n, hint) </tt> if that expression is
325 * well-formed, otherwise returns @c a.allocate(n)
326 */
327 _GLIBCXX_NODISCARD[[__nodiscard__]] static _GLIBCXX20_CONSTEXPR pointer
328 allocate(_Alloc& __a, size_type __n, const_void_pointer __hint)
329 { return _S_allocate(__a, __n, __hint, 0); }
330
331 /**
332 * @brief Deallocate memory.
333 * @param __a An allocator.
334 * @param __p Pointer to the memory to deallocate.
335 * @param __n The number of objects space was allocated for.
336 *
337 * Calls <tt> a.deallocate(p, n) </tt>
338 */
339 static _GLIBCXX20_CONSTEXPR void
340 deallocate(_Alloc& __a, pointer __p, size_type __n)
341 { __a.deallocate(__p, __n); }
342
343 /**
344 * @brief Construct an object of type @a _Tp
345 * @param __a An allocator.
346 * @param __p Pointer to memory of suitable size and alignment for Tp
347 * @param __args Constructor arguments.
348 *
349 * Calls <tt> __a.construct(__p, std::forward<Args>(__args)...) </tt>
350 * if that expression is well-formed, otherwise uses placement-new
351 * to construct an object of type @a _Tp at location @a __p from the
352 * arguments @a __args...
353 */
354 template<typename _Tp, typename... _Args>
355 static _GLIBCXX20_CONSTEXPR auto
356 construct(_Alloc& __a, _Tp* __p, _Args&&... __args)
357 noexcept(noexcept(_S_construct(__a, __p,
358 std::forward<_Args>(__args)...)))
359 -> decltype(_S_construct(__a, __p, std::forward<_Args>(__args)...))
360 { _S_construct(__a, __p, std::forward<_Args>(__args)...); }
361
362 /**
363 * @brief Destroy an object of type @a _Tp
364 * @param __a An allocator.
365 * @param __p Pointer to the object to destroy
366 *
367 * Calls @c __a.destroy(__p) if that expression is well-formed,
368 * otherwise calls @c __p->~_Tp()
369 */
370 template<typename _Tp>
371 static _GLIBCXX20_CONSTEXPR void
372 destroy(_Alloc& __a, _Tp* __p)
373 noexcept(noexcept(_S_destroy(__a, __p, 0)))
374 { _S_destroy(__a, __p, 0); }
375
376 /**
377 * @brief The maximum supported allocation size
378 * @param __a An allocator.
379 * @return @c __a.max_size() or @c numeric_limits<size_type>::max()
380 *
381 * Returns @c __a.max_size() if that expression is well-formed,
382 * otherwise returns @c numeric_limits<size_type>::max()
383 */
384 static _GLIBCXX20_CONSTEXPR size_type
385 max_size(const _Alloc& __a) noexcept
386 { return _S_max_size(__a, 0); }
387
388 /**
389 * @brief Obtain an allocator to use when copying a container.
390 * @param __rhs An allocator.
391 * @return @c __rhs.select_on_container_copy_construction() or @a __rhs
392 *
393 * Returns @c __rhs.select_on_container_copy_construction() if that
394 * expression is well-formed, otherwise returns @a __rhs
395 */
396 static _GLIBCXX20_CONSTEXPR _Alloc
397 select_on_container_copy_construction(const _Alloc& __rhs)
398 { return _S_select(__rhs, 0); }
399 };
400
401#if __cplusplus201703L > 201703L
402# define __cpp_lib_constexpr_dynamic_alloc 201907L
403#endif
404
405 /// Partial specialization for std::allocator.
406 template<typename _Tp>
407 struct allocator_traits<allocator<_Tp>>
408 {
409 /// The allocator type
410 using allocator_type = allocator<_Tp>;
411
412 /// The allocated type
413 using value_type = _Tp;
414
415 /// The allocator's pointer type.
416 using pointer = _Tp*;
417
418 /// The allocator's const pointer type.
419 using const_pointer = const _Tp*;
420
421 /// The allocator's void pointer type.
422 using void_pointer = void*;
423
424 /// The allocator's const void pointer type.
425 using const_void_pointer = const void*;
426
427 /// The allocator's difference type
428 using difference_type = std::ptrdiff_t;
429
430 /// The allocator's size type
431 using size_type = std::size_t;
432
433 /// How the allocator is propagated on copy assignment
434 using propagate_on_container_copy_assignment = false_type;
435
436 /// How the allocator is propagated on move assignment
437 using propagate_on_container_move_assignment = true_type;
438
439 /// How the allocator is propagated on swap
440 using propagate_on_container_swap = false_type;
441
442 /// Whether all instances of the allocator type compare equal.
443 using is_always_equal = true_type;
444
445 template<typename _Up>
446 using rebind_alloc = allocator<_Up>;
447
448 template<typename _Up>
449 using rebind_traits = allocator_traits<allocator<_Up>>;
450
451 /**
452 * @brief Allocate memory.
453 * @param __a An allocator.
454 * @param __n The number of objects to allocate space for.
455 *
456 * Calls @c a.allocate(n)
457 */
458 _GLIBCXX_NODISCARD[[__nodiscard__]] static _GLIBCXX20_CONSTEXPR pointer
459 allocate(allocator_type& __a, size_type __n)
460 { return __a.allocate(__n); }
20
Calling 'new_allocator::allocate'
24
Returned allocated memory
461
462 /**
463 * @brief Allocate memory.
464 * @param __a An allocator.
465 * @param __n The number of objects to allocate space for.
466 * @param __hint Aid to locality.
467 * @return Memory of suitable size and alignment for @a n objects
468 * of type @c value_type
469 *
470 * Returns <tt> a.allocate(n, hint) </tt>
471 */
472 _GLIBCXX_NODISCARD[[__nodiscard__]] static _GLIBCXX20_CONSTEXPR pointer
473 allocate(allocator_type& __a, size_type __n, const_void_pointer __hint)
474 {
475#if __cplusplus201703L <= 201703L
476 return __a.allocate(__n, __hint);
477#else
478 return __a.allocate(__n);
479#endif
480 }
481
482 /**
483 * @brief Deallocate memory.
484 * @param __a An allocator.
485 * @param __p Pointer to the memory to deallocate.
486 * @param __n The number of objects space was allocated for.
487 *
488 * Calls <tt> a.deallocate(p, n) </tt>
489 */
490 static _GLIBCXX20_CONSTEXPR void
491 deallocate(allocator_type& __a, pointer __p, size_type __n)
492 { __a.deallocate(__p, __n); }
493
494 /**
495 * @brief Construct an object of type `_Up`
496 * @param __a An allocator.
497 * @param __p Pointer to memory of suitable size and alignment for
498 * an object of type `_Up`.
499 * @param __args Constructor arguments.
500 *
501 * Calls `__a.construct(__p, std::forward<_Args>(__args)...)`
502 * in C++11, C++14 and C++17. Changed in C++20 to call
503 * `std::construct_at(__p, std::forward<_Args>(__args)...)` instead.
504 */
505 template<typename _Up, typename... _Args>
506 static _GLIBCXX20_CONSTEXPR void
507 construct(allocator_type& __a __attribute__((__unused__)), _Up* __p,
508 _Args&&... __args)
509 noexcept(std::is_nothrow_constructible<_Up, _Args...>::value)
510 {
511#if __cplusplus201703L <= 201703L
512 __a.construct(__p, std::forward<_Args>(__args)...);
513#else
514 std::construct_at(__p, std::forward<_Args>(__args)...);
515#endif
516 }
517
518 /**
519 * @brief Destroy an object of type @a _Up
520 * @param __a An allocator.
521 * @param __p Pointer to the object to destroy
522 *
523 * Calls @c __a.destroy(__p).
524 */
525 template<typename _Up>
526 static _GLIBCXX20_CONSTEXPR void
527 destroy(allocator_type& __a __attribute__((__unused__)), _Up* __p)
528 noexcept(is_nothrow_destructible<_Up>::value)
529 {
530#if __cplusplus201703L <= 201703L
531 __a.destroy(__p);
532#else
533 std::destroy_at(__p);
534#endif
535 }
536
537 /**
538 * @brief The maximum supported allocation size
539 * @param __a An allocator.
540 * @return @c __a.max_size()
541 */
542 static _GLIBCXX20_CONSTEXPR size_type
543 max_size(const allocator_type& __a __attribute__((__unused__))) noexcept
544 {
545#if __cplusplus201703L <= 201703L
546 return __a.max_size();
547#else
548 return size_t(-1) / sizeof(value_type);
549#endif
550 }
551
552 /**
553 * @brief Obtain an allocator to use when copying a container.
554 * @param __rhs An allocator.
555 * @return @c __rhs
556 */
557 static _GLIBCXX20_CONSTEXPR allocator_type
558 select_on_container_copy_construction(const allocator_type& __rhs)
559 { return __rhs; }
560 };
561
562#if __cplusplus201703L < 201703L
563 template<typename _Alloc>
564 inline void
565 __do_alloc_on_copy(_Alloc& __one, const _Alloc& __two, true_type)
566 { __one = __two; }
567
568 template<typename _Alloc>
569 inline void
570 __do_alloc_on_copy(_Alloc&, const _Alloc&, false_type)
571 { }
572#endif
573
574 template<typename _Alloc>
575 _GLIBCXX14_CONSTEXPRconstexpr inline void
576 __alloc_on_copy(_Alloc& __one, const _Alloc& __two)
577 {
578 typedef allocator_traits<_Alloc> __traits;
579 typedef typename __traits::propagate_on_container_copy_assignment __pocca;
580#if __cplusplus201703L >= 201703L
581 if constexpr (__pocca::value)
582 __one = __two;
583#else
584 __do_alloc_on_copy(__one, __two, __pocca());
585#endif
586 }
587
588 template<typename _Alloc>
589 constexpr _Alloc
590 __alloc_on_copy(const _Alloc& __a)
591 {
592 typedef allocator_traits<_Alloc> __traits;
593 return __traits::select_on_container_copy_construction(__a);
594 }
595
596#if __cplusplus201703L < 201703L
597 template<typename _Alloc>
598 inline void __do_alloc_on_move(_Alloc& __one, _Alloc& __two, true_type)
599 { __one = std::move(__two); }
600
601 template<typename _Alloc>
602 inline void __do_alloc_on_move(_Alloc&, _Alloc&, false_type)
603 { }
604#endif
605
606 template<typename _Alloc>
607 _GLIBCXX14_CONSTEXPRconstexpr inline void
608 __alloc_on_move(_Alloc& __one, _Alloc& __two)
609 {
610 typedef allocator_traits<_Alloc> __traits;
611 typedef typename __traits::propagate_on_container_move_assignment __pocma;
612#if __cplusplus201703L >= 201703L
613 if constexpr (__pocma::value)
614 __one = std::move(__two);
615#else
616 __do_alloc_on_move(__one, __two, __pocma());
617#endif
618 }
619
620#if __cplusplus201703L < 201703L
621 template<typename _Alloc>
622 inline void __do_alloc_on_swap(_Alloc& __one, _Alloc& __two, true_type)
623 {
624 using std::swap;
625 swap(__one, __two);
626 }
627
628 template<typename _Alloc>
629 inline void __do_alloc_on_swap(_Alloc&, _Alloc&, false_type)
630 { }
631#endif
632
633 template<typename _Alloc>
634 _GLIBCXX14_CONSTEXPRconstexpr inline void
635 __alloc_on_swap(_Alloc& __one, _Alloc& __two)
636 {
637 typedef allocator_traits<_Alloc> __traits;
638 typedef typename __traits::propagate_on_container_swap __pocs;
639#if __cplusplus201703L >= 201703L
640 if constexpr (__pocs::value)
641 {
642 using std::swap;
643 swap(__one, __two);
644 }
645#else
646 __do_alloc_on_swap(__one, __two, __pocs());
647#endif
648 }
649
650 template<typename _Alloc, typename _Tp,
651 typename _ValueT = __remove_cvref_t<typename _Alloc::value_type>,
652 typename = void>
653 struct __is_alloc_insertable_impl
654 : false_type
655 { };
656
657 template<typename _Alloc, typename _Tp, typename _ValueT>
658 struct __is_alloc_insertable_impl<_Alloc, _Tp, _ValueT,
659 __void_t<decltype(allocator_traits<_Alloc>::construct(
660 std::declval<_Alloc&>(), std::declval<_ValueT*>(),
661 std::declval<_Tp>()))>>
662 : true_type
663 { };
664
665 // true if _Alloc::value_type is CopyInsertable into containers using _Alloc
666 // (might be wrong if _Alloc::construct exists but is not constrained,
667 // i.e. actually trying to use it would still be invalid. Use with caution.)
668 template<typename _Alloc>
669 struct __is_copy_insertable
670 : __is_alloc_insertable_impl<_Alloc,
671 typename _Alloc::value_type const&>::type
672 { };
673
674 // std::allocator<_Tp> just requires CopyConstructible
675 template<typename _Tp>
676 struct __is_copy_insertable<allocator<_Tp>>
677 : is_copy_constructible<_Tp>
678 { };
679
680 // true if _Alloc::value_type is MoveInsertable into containers using _Alloc
681 // (might be wrong if _Alloc::construct exists but is not constrained,
682 // i.e. actually trying to use it would still be invalid. Use with caution.)
683 template<typename _Alloc>
684 struct __is_move_insertable
685 : __is_alloc_insertable_impl<_Alloc, typename _Alloc::value_type>::type
686 { };
687
688 // std::allocator<_Tp> just requires MoveConstructible
689 template<typename _Tp>
690 struct __is_move_insertable<allocator<_Tp>>
691 : is_move_constructible<_Tp>
692 { };
693
694 // Trait to detect Allocator-like types.
695 template<typename _Alloc, typename = void>
696 struct __is_allocator : false_type { };
697
698 template<typename _Alloc>
699 struct __is_allocator<_Alloc,
700 __void_t<typename _Alloc::value_type,
701 decltype(std::declval<_Alloc&>().allocate(size_t{}))>>
702 : true_type { };
703
704 template<typename _Alloc>
705 using _RequireAllocator
706 = typename enable_if<__is_allocator<_Alloc>::value, _Alloc>::type;
707
708 template<typename _Alloc>
709 using _RequireNotAllocator
710 = typename enable_if<!__is_allocator<_Alloc>::value, _Alloc>::type;
711#endif // C++11
712
713 /**
714 * Destroy a range of objects using the supplied allocator. For
715 * non-default allocators we do not optimize away invocation of
716 * destroy() even if _Tp has a trivial destructor.
717 */
718
719 template<typename _ForwardIterator, typename _Allocator>
720 void
721 _Destroy(_ForwardIterator __first, _ForwardIterator __last,
722 _Allocator& __alloc)
723 {
724 for (; __first != __last; ++__first)
725#if __cplusplus201703L < 201103L
726 __alloc.destroy(std::__addressof(*__first));
727#else
728 allocator_traits<_Allocator>::destroy(__alloc,
729 std::__addressof(*__first));
730#endif
731 }
732
733 template<typename _ForwardIterator, typename _Tp>
734 inline void
735 _Destroy(_ForwardIterator __first, _ForwardIterator __last,
736 allocator<_Tp>&)
737 {
738 _Destroy(__first, __last);
739 }
740
741_GLIBCXX_END_NAMESPACE_VERSION
742} // namespace std
743#endif // _ALLOC_TRAITS_H

/usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10/ext/new_allocator.h

1// Allocator that wraps operator new -*- C++ -*-
2
3// Copyright (C) 2001-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 ext/new_allocator.h
26 * This file is a GNU extension to the Standard C++ Library.
27 */
28
29#ifndef _NEW_ALLOCATOR_H1
30#define _NEW_ALLOCATOR_H1 1
31
32#include <bits/c++config.h>
33#include <new>
34#include <bits/functexcept.h>
35#include <bits/move.h>
36#if __cplusplus201703L >= 201103L
37#include <type_traits>
38#endif
39
40namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)__attribute__ ((__visibility__ ("default")))
41{
42_GLIBCXX_BEGIN_NAMESPACE_VERSION
43
44 /**
45 * @brief An allocator that uses global new, as per [20.4].
46 * @ingroup allocators
47 *
48 * This is precisely the allocator defined in the C++ Standard.
49 * - all allocation calls operator new
50 * - all deallocation calls operator delete
51 *
52 * @tparam _Tp Type of allocated object.
53 */
54 template<typename _Tp>
55 class new_allocator
56 {
57 public:
58 typedef _Tp value_type;
59 typedef std::size_t size_type;
60 typedef std::ptrdiff_t difference_type;
61#if __cplusplus201703L <= 201703L
62 typedef _Tp* pointer;
63 typedef const _Tp* const_pointer;
64 typedef _Tp& reference;
65 typedef const _Tp& const_reference;
66
67 template<typename _Tp1>
68 struct rebind
69 { typedef new_allocator<_Tp1> other; };
70#endif
71
72#if __cplusplus201703L >= 201103L
73 // _GLIBCXX_RESOLVE_LIB_DEFECTS
74 // 2103. propagate_on_container_move_assignment
75 typedef std::true_type propagate_on_container_move_assignment;
76#endif
77
78 _GLIBCXX20_CONSTEXPR
79 new_allocator() _GLIBCXX_USE_NOEXCEPTnoexcept { }
80
81 _GLIBCXX20_CONSTEXPR
82 new_allocator(const new_allocator&) _GLIBCXX_USE_NOEXCEPTnoexcept { }
83
84 template<typename _Tp1>
85 _GLIBCXX20_CONSTEXPR
86 new_allocator(const new_allocator<_Tp1>&) _GLIBCXX_USE_NOEXCEPTnoexcept { }
87
88#if __cplusplus201703L <= 201703L
89 ~new_allocator() _GLIBCXX_USE_NOEXCEPTnoexcept { }
90
91 pointer
92 address(reference __x) const _GLIBCXX_NOEXCEPTnoexcept
93 { return std::__addressof(__x); }
94
95 const_pointer
96 address(const_reference __x) const _GLIBCXX_NOEXCEPTnoexcept
97 { return std::__addressof(__x); }
98#endif
99
100 // NB: __n is permitted to be 0. The C++ standard says nothing
101 // about what the return value is when __n == 0.
102 _GLIBCXX_NODISCARD[[__nodiscard__]] _Tp*
103 allocate(size_type __n, const void* = static_cast<const void*>(0))
104 {
105 if (__n > this->_M_max_size())
21
Taking false branch
106 std::__throw_bad_alloc();
107
108#if __cpp_aligned_new201606L
109 if (alignof(_Tp) > __STDCPP_DEFAULT_NEW_ALIGNMENT__16UL)
22
Taking false branch
110 {
111 std::align_val_t __al = std::align_val_t(alignof(_Tp));
112 return static_cast<_Tp*>(::operator new(__n * sizeof(_Tp), __al));
113 }
114#endif
115 return static_cast<_Tp*>(::operator new(__n * sizeof(_Tp)));
23
Memory is allocated
116 }
117
118 // __p is not permitted to be a null pointer.
119 void
120 deallocate(_Tp* __p, size_type __t)
121 {
122#if __cpp_aligned_new201606L
123 if (alignof(_Tp) > __STDCPP_DEFAULT_NEW_ALIGNMENT__16UL)
124 {
125 ::operator delete(__p,
126# if __cpp_sized_deallocation
127 __t * sizeof(_Tp),
128# endif
129 std::align_val_t(alignof(_Tp)));
130 return;
131 }
132#endif
133 ::operator delete(__p
134#if __cpp_sized_deallocation
135 , __t * sizeof(_Tp)
136#endif
137 );
138 }
139
140#if __cplusplus201703L <= 201703L
141 size_type
142 max_size() const _GLIBCXX_USE_NOEXCEPTnoexcept
143 { return _M_max_size(); }
144
145#if __cplusplus201703L >= 201103L
146 template<typename _Up, typename... _Args>
147 void
148 construct(_Up* __p, _Args&&... __args)
149 noexcept(std::is_nothrow_constructible<_Up, _Args...>::value)
150 { ::new((void *)__p) _Up(std::forward<_Args>(__args)...); }
151
152 template<typename _Up>
153 void
154 destroy(_Up* __p)
155 noexcept(std::is_nothrow_destructible<_Up>::value)
156 { __p->~_Up(); }
157#else
158 // _GLIBCXX_RESOLVE_LIB_DEFECTS
159 // 402. wrong new expression in [some_] allocator::construct
160 void
161 construct(pointer __p, const _Tp& __val)
162 { ::new((void *)__p) _Tp(__val); }
163
164 void
165 destroy(pointer __p) { __p->~_Tp(); }
166#endif
167#endif // ! C++20
168
169 template<typename _Up>
170 friend _GLIBCXX20_CONSTEXPR bool
171 operator==(const new_allocator&, const new_allocator<_Up>&)
172 _GLIBCXX_NOTHROWnoexcept
173 { return true; }
174
175#if __cpp_impl_three_way_comparison < 201907L
176 template<typename _Up>
177 friend _GLIBCXX20_CONSTEXPR bool
178 operator!=(const new_allocator&, const new_allocator<_Up>&)
179 _GLIBCXX_NOTHROWnoexcept
180 { return false; }
181#endif
182
183 private:
184 _GLIBCXX_CONSTEXPRconstexpr size_type
185 _M_max_size() const _GLIBCXX_USE_NOEXCEPTnoexcept
186 {
187#if __PTRDIFF_MAX__9223372036854775807L < __SIZE_MAX__18446744073709551615UL
188 return std::size_t(__PTRDIFF_MAX__9223372036854775807L) / sizeof(_Tp);
189#else
190 return std::size_t(-1) / sizeof(_Tp);
191#endif
192 }
193 };
194
195_GLIBCXX_END_NAMESPACE_VERSION
196} // namespace
197
198#endif