Bug Summary

File:build/llvm-toolchain-snapshot-16~++20220904122748+c444af1c20b3/lldb/source/Core/Debugger.cpp
Warning:line 952, column 5
Potential leak of memory pointed to by 'file_sp._M_refcount._M_pi'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name Debugger.cpp -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 -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -ffunction-sections -fdata-sections -fcoverage-compilation-dir=/build/llvm-toolchain-snapshot-16~++20220904122748+c444af1c20b3/build-llvm/tools/clang/stage2-bins -resource-dir /usr/lib/llvm-16/lib/clang/16.0.0 -isystem /usr/include/libxml2 -D HAVE_ROUND -D _DEBUG -D _GNU_SOURCE -D __STDC_CONSTANT_MACROS -D __STDC_FORMAT_MACROS -D __STDC_LIMIT_MACROS -I tools/lldb/source/Core -I /build/llvm-toolchain-snapshot-16~++20220904122748+c444af1c20b3/lldb/source/Core -I /build/llvm-toolchain-snapshot-16~++20220904122748+c444af1c20b3/lldb/include -I tools/lldb/include -I include -I /build/llvm-toolchain-snapshot-16~++20220904122748+c444af1c20b3/llvm/include -I /usr/include/python3.9 -I /build/llvm-toolchain-snapshot-16~++20220904122748+c444af1c20b3/clang/include -I tools/lldb/../clang/include -I /build/llvm-toolchain-snapshot-16~++20220904122748+c444af1c20b3/lldb/source -I tools/lldb/source -D _FORTIFY_SOURCE=2 -D NDEBUG -U NDEBUG -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/x86_64-linux-gnu/c++/10 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/backward -internal-isystem /usr/lib/llvm-16/lib/clang/16.0.0/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -fmacro-prefix-map=/build/llvm-toolchain-snapshot-16~++20220904122748+c444af1c20b3/build-llvm/tools/clang/stage2-bins=build-llvm/tools/clang/stage2-bins -fmacro-prefix-map=/build/llvm-toolchain-snapshot-16~++20220904122748+c444af1c20b3/= -fcoverage-prefix-map=/build/llvm-toolchain-snapshot-16~++20220904122748+c444af1c20b3/build-llvm/tools/clang/stage2-bins=build-llvm/tools/clang/stage2-bins -fcoverage-prefix-map=/build/llvm-toolchain-snapshot-16~++20220904122748+c444af1c20b3/= -O2 -Wno-unused-command-line-argument -Wno-unused-parameter -Wwrite-strings -Wno-missing-field-initializers -Wno-long-long -Wno-maybe-uninitialized -Wno-class-memaccess -Wno-redundant-move -Wno-pessimizing-move -Wno-noexcept-type -Wno-comment -Wno-misleading-indentation -Wno-deprecated-declarations -Wno-unknown-pragmas -Wno-strict-aliasing -Wno-stringop-truncation -std=c++17 -fdeprecated-macro -fdebug-compilation-dir=/build/llvm-toolchain-snapshot-16~++20220904122748+c444af1c20b3/build-llvm/tools/clang/stage2-bins -fdebug-prefix-map=/build/llvm-toolchain-snapshot-16~++20220904122748+c444af1c20b3/build-llvm/tools/clang/stage2-bins=build-llvm/tools/clang/stage2-bins -fdebug-prefix-map=/build/llvm-toolchain-snapshot-16~++20220904122748+c444af1c20b3/= -ferror-limit 19 -fvisibility-inlines-hidden -stack-protector 2 -fgnuc-version=4.2.1 -fcolor-diagnostics -vectorize-loops -vectorize-slp -analyzer-output=html -analyzer-config stable-report-filename=true -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2022-09-04-125545-48738-1 -x c++ /build/llvm-toolchain-snapshot-16~++20220904122748+c444af1c20b3/lldb/source/Core/Debugger.cpp

/build/llvm-toolchain-snapshot-16~++20220904122748+c444af1c20b3/lldb/source/Core/Debugger.cpp

1//===-- Debugger.cpp ------------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "lldb/Core/Debugger.h"
10
11#include "lldb/Breakpoint/Breakpoint.h"
12#include "lldb/Core/DebuggerEvents.h"
13#include "lldb/Core/FormatEntity.h"
14#include "lldb/Core/Mangled.h"
15#include "lldb/Core/ModuleList.h"
16#include "lldb/Core/ModuleSpec.h"
17#include "lldb/Core/PluginManager.h"
18#include "lldb/Core/StreamAsynchronousIO.h"
19#include "lldb/Core/StreamFile.h"
20#include "lldb/DataFormatters/DataVisualization.h"
21#include "lldb/Expression/REPL.h"
22#include "lldb/Host/File.h"
23#include "lldb/Host/FileSystem.h"
24#include "lldb/Host/HostInfo.h"
25#include "lldb/Host/Terminal.h"
26#include "lldb/Host/ThreadLauncher.h"
27#include "lldb/Interpreter/CommandInterpreter.h"
28#include "lldb/Interpreter/CommandReturnObject.h"
29#include "lldb/Interpreter/OptionValue.h"
30#include "lldb/Interpreter/OptionValueLanguage.h"
31#include "lldb/Interpreter/OptionValueProperties.h"
32#include "lldb/Interpreter/OptionValueSInt64.h"
33#include "lldb/Interpreter/OptionValueString.h"
34#include "lldb/Interpreter/Property.h"
35#include "lldb/Interpreter/ScriptInterpreter.h"
36#include "lldb/Symbol/Function.h"
37#include "lldb/Symbol/Symbol.h"
38#include "lldb/Symbol/SymbolContext.h"
39#include "lldb/Target/Language.h"
40#include "lldb/Target/Process.h"
41#include "lldb/Target/StructuredDataPlugin.h"
42#include "lldb/Target/Target.h"
43#include "lldb/Target/TargetList.h"
44#include "lldb/Target/Thread.h"
45#include "lldb/Target/ThreadList.h"
46#include "lldb/Utility/AnsiTerminal.h"
47#include "lldb/Utility/Event.h"
48#include "lldb/Utility/LLDBLog.h"
49#include "lldb/Utility/Listener.h"
50#include "lldb/Utility/Log.h"
51#include "lldb/Utility/Reproducer.h"
52#include "lldb/Utility/ReproducerProvider.h"
53#include "lldb/Utility/State.h"
54#include "lldb/Utility/Stream.h"
55#include "lldb/Utility/StreamString.h"
56
57#if defined(_WIN32)
58#include "lldb/Host/windows/PosixApi.h"
59#include "lldb/Host/windows/windows.h"
60#endif
61
62#include "llvm/ADT/None.h"
63#include "llvm/ADT/STLExtras.h"
64#include "llvm/ADT/StringRef.h"
65#include "llvm/ADT/iterator.h"
66#include "llvm/Support/DynamicLibrary.h"
67#include "llvm/Support/FileSystem.h"
68#include "llvm/Support/Process.h"
69#include "llvm/Support/ThreadPool.h"
70#include "llvm/Support/Threading.h"
71#include "llvm/Support/raw_ostream.h"
72
73#include <cstdio>
74#include <cstdlib>
75#include <cstring>
76#include <list>
77#include <memory>
78#include <mutex>
79#include <set>
80#include <string>
81#include <system_error>
82
83// Includes for pipe()
84#if defined(_WIN32)
85#include <fcntl.h>
86#include <io.h>
87#else
88#include <unistd.h>
89#endif
90
91namespace lldb_private {
92class Address;
93}
94
95using namespace lldb;
96using namespace lldb_private;
97
98static lldb::user_id_t g_unique_id = 1;
99static size_t g_debugger_event_thread_stack_bytes = 8 * 1024 * 1024;
100
101#pragma mark Static Functions
102
103typedef std::vector<DebuggerSP> DebuggerList;
104static std::recursive_mutex *g_debugger_list_mutex_ptr =
105 nullptr; // NOTE: intentional leak to avoid issues with C++ destructor chain
106static DebuggerList *g_debugger_list_ptr =
107 nullptr; // NOTE: intentional leak to avoid issues with C++ destructor chain
108static llvm::ThreadPool *g_thread_pool = nullptr;
109
110static constexpr OptionEnumValueElement g_show_disassembly_enum_values[] = {
111 {
112 Debugger::eStopDisassemblyTypeNever,
113 "never",
114 "Never show disassembly when displaying a stop context.",
115 },
116 {
117 Debugger::eStopDisassemblyTypeNoDebugInfo,
118 "no-debuginfo",
119 "Show disassembly when there is no debug information.",
120 },
121 {
122 Debugger::eStopDisassemblyTypeNoSource,
123 "no-source",
124 "Show disassembly when there is no source information, or the source "
125 "file "
126 "is missing when displaying a stop context.",
127 },
128 {
129 Debugger::eStopDisassemblyTypeAlways,
130 "always",
131 "Always show disassembly when displaying a stop context.",
132 },
133};
134
135static constexpr OptionEnumValueElement g_language_enumerators[] = {
136 {
137 eScriptLanguageNone,
138 "none",
139 "Disable scripting languages.",
140 },
141 {
142 eScriptLanguagePython,
143 "python",
144 "Select python as the default scripting language.",
145 },
146 {
147 eScriptLanguageDefault,
148 "default",
149 "Select the lldb default as the default scripting language.",
150 },
151};
152
153static constexpr OptionEnumValueElement s_stop_show_column_values[] = {
154 {
155 eStopShowColumnAnsiOrCaret,
156 "ansi-or-caret",
157 "Highlight the stop column with ANSI terminal codes when color/ANSI "
158 "mode is enabled; otherwise, fall back to using a text-only caret (^) "
159 "as if \"caret-only\" mode was selected.",
160 },
161 {
162 eStopShowColumnAnsi,
163 "ansi",
164 "Highlight the stop column with ANSI terminal codes when running LLDB "
165 "with color/ANSI enabled.",
166 },
167 {
168 eStopShowColumnCaret,
169 "caret",
170 "Highlight the stop column with a caret character (^) underneath the "
171 "stop column. This method introduces a new line in source listings "
172 "that display thread stop locations.",
173 },
174 {
175 eStopShowColumnNone,
176 "none",
177 "Do not highlight the stop column.",
178 },
179};
180
181#define LLDB_PROPERTIES_debugger
182#include "CoreProperties.inc"
183
184enum {
185#define LLDB_PROPERTIES_debugger
186#include "CorePropertiesEnum.inc"
187};
188
189LoadPluginCallbackType Debugger::g_load_plugin_callback = nullptr;
190
191Status Debugger::SetPropertyValue(const ExecutionContext *exe_ctx,
192 VarSetOperationType op,
193 llvm::StringRef property_path,
194 llvm::StringRef value) {
195 bool is_load_script =
196 (property_path == "target.load-script-from-symbol-file");
197 // These properties might change how we visualize data.
198 bool invalidate_data_vis = (property_path == "escape-non-printables");
199 invalidate_data_vis |=
200 (property_path == "target.max-zero-padding-in-float-format");
201 if (invalidate_data_vis) {
202 DataVisualization::ForceUpdate();
203 }
204
205 TargetSP target_sp;
206 LoadScriptFromSymFile load_script_old_value = eLoadScriptFromSymFileFalse;
207 if (is_load_script && exe_ctx->GetTargetSP()) {
208 target_sp = exe_ctx->GetTargetSP();
209 load_script_old_value =
210 target_sp->TargetProperties::GetLoadScriptFromSymbolFile();
211 }
212 Status error(Properties::SetPropertyValue(exe_ctx, op, property_path, value));
213 if (error.Success()) {
214 // FIXME it would be nice to have "on-change" callbacks for properties
215 if (property_path == g_debugger_properties[ePropertyPrompt].name) {
216 llvm::StringRef new_prompt = GetPrompt();
217 std::string str = lldb_private::ansi::FormatAnsiTerminalCodes(
218 new_prompt, GetUseColor());
219 if (str.length())
220 new_prompt = str;
221 GetCommandInterpreter().UpdatePrompt(new_prompt);
222 auto bytes = std::make_unique<EventDataBytes>(new_prompt);
223 auto prompt_change_event_sp = std::make_shared<Event>(
224 CommandInterpreter::eBroadcastBitResetPrompt, bytes.release());
225 GetCommandInterpreter().BroadcastEvent(prompt_change_event_sp);
226 } else if (property_path == g_debugger_properties[ePropertyUseColor].name) {
227 // use-color changed. Ping the prompt so it can reset the ansi terminal
228 // codes.
229 SetPrompt(GetPrompt());
230 } else if (property_path == g_debugger_properties[ePropertyUseSourceCache].name) {
231 // use-source-cache changed. Wipe out the cache contents if it was disabled.
232 if (!GetUseSourceCache()) {
233 m_source_file_cache.Clear();
234 }
235 } else if (is_load_script && target_sp &&
236 load_script_old_value == eLoadScriptFromSymFileWarn) {
237 if (target_sp->TargetProperties::GetLoadScriptFromSymbolFile() ==
238 eLoadScriptFromSymFileTrue) {
239 std::list<Status> errors;
240 StreamString feedback_stream;
241 if (!target_sp->LoadScriptingResources(errors, &feedback_stream)) {
242 Stream &s = GetErrorStream();
243 for (auto error : errors) {
244 s.Printf("%s\n", error.AsCString());
245 }
246 if (feedback_stream.GetSize())
247 s.PutCString(feedback_stream.GetString());
248 }
249 }
250 }
251 }
252 return error;
253}
254
255bool Debugger::GetAutoConfirm() const {
256 const uint32_t idx = ePropertyAutoConfirm;
257 return m_collection_sp->GetPropertyAtIndexAsBoolean(
258 nullptr, idx, g_debugger_properties[idx].default_uint_value != 0);
259}
260
261const FormatEntity::Entry *Debugger::GetDisassemblyFormat() const {
262 const uint32_t idx = ePropertyDisassemblyFormat;
263 return m_collection_sp->GetPropertyAtIndexAsFormatEntity(nullptr, idx);
264}
265
266const FormatEntity::Entry *Debugger::GetFrameFormat() const {
267 const uint32_t idx = ePropertyFrameFormat;
268 return m_collection_sp->GetPropertyAtIndexAsFormatEntity(nullptr, idx);
269}
270
271const FormatEntity::Entry *Debugger::GetFrameFormatUnique() const {
272 const uint32_t idx = ePropertyFrameFormatUnique;
273 return m_collection_sp->GetPropertyAtIndexAsFormatEntity(nullptr, idx);
274}
275
276uint32_t Debugger::GetStopDisassemblyMaxSize() const {
277 const uint32_t idx = ePropertyStopDisassemblyMaxSize;
278 return m_collection_sp->GetPropertyAtIndexAsUInt64(
279 nullptr, idx, g_debugger_properties[idx].default_uint_value);
280}
281
282bool Debugger::GetNotifyVoid() const {
283 const uint32_t idx = ePropertyNotiftVoid;
284 return m_collection_sp->GetPropertyAtIndexAsBoolean(
285 nullptr, idx, g_debugger_properties[idx].default_uint_value != 0);
286}
287
288llvm::StringRef Debugger::GetPrompt() const {
289 const uint32_t idx = ePropertyPrompt;
290 return m_collection_sp->GetPropertyAtIndexAsString(
291 nullptr, idx, g_debugger_properties[idx].default_cstr_value);
292}
293
294void Debugger::SetPrompt(llvm::StringRef p) {
295 const uint32_t idx = ePropertyPrompt;
296 m_collection_sp->SetPropertyAtIndexAsString(nullptr, idx, p);
297 llvm::StringRef new_prompt = GetPrompt();
298 std::string str =
299 lldb_private::ansi::FormatAnsiTerminalCodes(new_prompt, GetUseColor());
300 if (str.length())
301 new_prompt = str;
302 GetCommandInterpreter().UpdatePrompt(new_prompt);
303}
304
305llvm::StringRef Debugger::GetReproducerPath() const {
306 auto &r = repro::Reproducer::Instance();
307 return r.GetReproducerPath().GetPathAsConstString().AsCString();
308}
309
310const FormatEntity::Entry *Debugger::GetThreadFormat() const {
311 const uint32_t idx = ePropertyThreadFormat;
312 return m_collection_sp->GetPropertyAtIndexAsFormatEntity(nullptr, idx);
313}
314
315const FormatEntity::Entry *Debugger::GetThreadStopFormat() const {
316 const uint32_t idx = ePropertyThreadStopFormat;
317 return m_collection_sp->GetPropertyAtIndexAsFormatEntity(nullptr, idx);
318}
319
320lldb::ScriptLanguage Debugger::GetScriptLanguage() const {
321 const uint32_t idx = ePropertyScriptLanguage;
322 return (lldb::ScriptLanguage)m_collection_sp->GetPropertyAtIndexAsEnumeration(
323 nullptr, idx, g_debugger_properties[idx].default_uint_value);
324}
325
326bool Debugger::SetScriptLanguage(lldb::ScriptLanguage script_lang) {
327 const uint32_t idx = ePropertyScriptLanguage;
328 return m_collection_sp->SetPropertyAtIndexAsEnumeration(nullptr, idx,
329 script_lang);
330}
331
332lldb::LanguageType Debugger::GetREPLLanguage() const {
333 const uint32_t idx = ePropertyREPLLanguage;
334 OptionValueLanguage *value =
335 m_collection_sp->GetPropertyAtIndexAsOptionValueLanguage(nullptr, idx);
336 if (value)
337 return value->GetCurrentValue();
338 return LanguageType();
339}
340
341bool Debugger::SetREPLLanguage(lldb::LanguageType repl_lang) {
342 const uint32_t idx = ePropertyREPLLanguage;
343 return m_collection_sp->SetPropertyAtIndexAsLanguage(nullptr, idx, repl_lang);
344}
345
346uint32_t Debugger::GetTerminalWidth() const {
347 const uint32_t idx = ePropertyTerminalWidth;
348 return m_collection_sp->GetPropertyAtIndexAsSInt64(
349 nullptr, idx, g_debugger_properties[idx].default_uint_value);
350}
351
352bool Debugger::SetTerminalWidth(uint32_t term_width) {
353 if (auto handler_sp = m_io_handler_stack.Top())
354 handler_sp->TerminalSizeChanged();
355
356 const uint32_t idx = ePropertyTerminalWidth;
357 return m_collection_sp->SetPropertyAtIndexAsSInt64(nullptr, idx, term_width);
358}
359
360bool Debugger::GetUseExternalEditor() const {
361 const uint32_t idx = ePropertyUseExternalEditor;
362 return m_collection_sp->GetPropertyAtIndexAsBoolean(
363 nullptr, idx, g_debugger_properties[idx].default_uint_value != 0);
364}
365
366bool Debugger::SetUseExternalEditor(bool b) {
367 const uint32_t idx = ePropertyUseExternalEditor;
368 return m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, b);
369}
370
371bool Debugger::GetUseColor() const {
372 const uint32_t idx = ePropertyUseColor;
373 return m_collection_sp->GetPropertyAtIndexAsBoolean(
374 nullptr, idx, g_debugger_properties[idx].default_uint_value != 0);
375}
376
377bool Debugger::SetUseColor(bool b) {
378 const uint32_t idx = ePropertyUseColor;
379 bool ret = m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, b);
380 SetPrompt(GetPrompt());
381 return ret;
382}
383
384bool Debugger::GetShowProgress() const {
385 const uint32_t idx = ePropertyShowProgress;
386 return m_collection_sp->GetPropertyAtIndexAsBoolean(
387 nullptr, idx, g_debugger_properties[idx].default_uint_value != 0);
388}
389
390bool Debugger::SetShowProgress(bool show_progress) {
391 const uint32_t idx = ePropertyShowProgress;
392 return m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx,
393 show_progress);
394}
395
396llvm::StringRef Debugger::GetShowProgressAnsiPrefix() const {
397 const uint32_t idx = ePropertyShowProgressAnsiPrefix;
398 return m_collection_sp->GetPropertyAtIndexAsString(nullptr, idx, "");
399}
400
401llvm::StringRef Debugger::GetShowProgressAnsiSuffix() const {
402 const uint32_t idx = ePropertyShowProgressAnsiSuffix;
403 return m_collection_sp->GetPropertyAtIndexAsString(nullptr, idx, "");
404}
405
406bool Debugger::GetUseAutosuggestion() const {
407 const uint32_t idx = ePropertyShowAutosuggestion;
408 return m_collection_sp->GetPropertyAtIndexAsBoolean(
409 nullptr, idx, g_debugger_properties[idx].default_uint_value != 0);
410}
411
412llvm::StringRef Debugger::GetAutosuggestionAnsiPrefix() const {
413 const uint32_t idx = ePropertyShowAutosuggestionAnsiPrefix;
414 return m_collection_sp->GetPropertyAtIndexAsString(nullptr, idx, "");
415}
416
417llvm::StringRef Debugger::GetAutosuggestionAnsiSuffix() const {
418 const uint32_t idx = ePropertyShowAutosuggestionAnsiSuffix;
419 return m_collection_sp->GetPropertyAtIndexAsString(nullptr, idx, "");
420}
421
422bool Debugger::GetUseSourceCache() const {
423 const uint32_t idx = ePropertyUseSourceCache;
424 return m_collection_sp->GetPropertyAtIndexAsBoolean(
425 nullptr, idx, g_debugger_properties[idx].default_uint_value != 0);
426}
427
428bool Debugger::SetUseSourceCache(bool b) {
429 const uint32_t idx = ePropertyUseSourceCache;
430 bool ret = m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, b);
431 if (!ret) {
432 m_source_file_cache.Clear();
433 }
434 return ret;
435}
436bool Debugger::GetHighlightSource() const {
437 const uint32_t idx = ePropertyHighlightSource;
438 return m_collection_sp->GetPropertyAtIndexAsBoolean(
439 nullptr, idx, g_debugger_properties[idx].default_uint_value);
440}
441
442StopShowColumn Debugger::GetStopShowColumn() const {
443 const uint32_t idx = ePropertyStopShowColumn;
444 return (lldb::StopShowColumn)m_collection_sp->GetPropertyAtIndexAsEnumeration(
445 nullptr, idx, g_debugger_properties[idx].default_uint_value);
446}
447
448llvm::StringRef Debugger::GetStopShowColumnAnsiPrefix() const {
449 const uint32_t idx = ePropertyStopShowColumnAnsiPrefix;
450 return m_collection_sp->GetPropertyAtIndexAsString(nullptr, idx, "");
451}
452
453llvm::StringRef Debugger::GetStopShowColumnAnsiSuffix() const {
454 const uint32_t idx = ePropertyStopShowColumnAnsiSuffix;
455 return m_collection_sp->GetPropertyAtIndexAsString(nullptr, idx, "");
456}
457
458llvm::StringRef Debugger::GetStopShowLineMarkerAnsiPrefix() const {
459 const uint32_t idx = ePropertyStopShowLineMarkerAnsiPrefix;
460 return m_collection_sp->GetPropertyAtIndexAsString(nullptr, idx, "");
461}
462
463llvm::StringRef Debugger::GetStopShowLineMarkerAnsiSuffix() const {
464 const uint32_t idx = ePropertyStopShowLineMarkerAnsiSuffix;
465 return m_collection_sp->GetPropertyAtIndexAsString(nullptr, idx, "");
466}
467
468uint32_t Debugger::GetStopSourceLineCount(bool before) const {
469 const uint32_t idx =
470 before ? ePropertyStopLineCountBefore : ePropertyStopLineCountAfter;
471 return m_collection_sp->GetPropertyAtIndexAsSInt64(
472 nullptr, idx, g_debugger_properties[idx].default_uint_value);
473}
474
475Debugger::StopDisassemblyType Debugger::GetStopDisassemblyDisplay() const {
476 const uint32_t idx = ePropertyStopDisassemblyDisplay;
477 return (Debugger::StopDisassemblyType)
478 m_collection_sp->GetPropertyAtIndexAsEnumeration(
479 nullptr, idx, g_debugger_properties[idx].default_uint_value);
480}
481
482uint32_t Debugger::GetDisassemblyLineCount() const {
483 const uint32_t idx = ePropertyStopDisassemblyCount;
484 return m_collection_sp->GetPropertyAtIndexAsSInt64(
485 nullptr, idx, g_debugger_properties[idx].default_uint_value);
486}
487
488bool Debugger::GetAutoOneLineSummaries() const {
489 const uint32_t idx = ePropertyAutoOneLineSummaries;
490 return m_collection_sp->GetPropertyAtIndexAsBoolean(nullptr, idx, true);
491}
492
493bool Debugger::GetEscapeNonPrintables() const {
494 const uint32_t idx = ePropertyEscapeNonPrintables;
495 return m_collection_sp->GetPropertyAtIndexAsBoolean(nullptr, idx, true);
496}
497
498bool Debugger::GetAutoIndent() const {
499 const uint32_t idx = ePropertyAutoIndent;
500 return m_collection_sp->GetPropertyAtIndexAsBoolean(nullptr, idx, true);
501}
502
503bool Debugger::SetAutoIndent(bool b) {
504 const uint32_t idx = ePropertyAutoIndent;
505 return m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, b);
506}
507
508bool Debugger::GetPrintDecls() const {
509 const uint32_t idx = ePropertyPrintDecls;
510 return m_collection_sp->GetPropertyAtIndexAsBoolean(nullptr, idx, true);
511}
512
513bool Debugger::SetPrintDecls(bool b) {
514 const uint32_t idx = ePropertyPrintDecls;
515 return m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, b);
516}
517
518uint32_t Debugger::GetTabSize() const {
519 const uint32_t idx = ePropertyTabSize;
520 return m_collection_sp->GetPropertyAtIndexAsUInt64(
521 nullptr, idx, g_debugger_properties[idx].default_uint_value);
522}
523
524bool Debugger::SetTabSize(uint32_t tab_size) {
525 const uint32_t idx = ePropertyTabSize;
526 return m_collection_sp->SetPropertyAtIndexAsUInt64(nullptr, idx, tab_size);
527}
528
529#pragma mark Debugger
530
531// const DebuggerPropertiesSP &
532// Debugger::GetSettings() const
533//{
534// return m_properties_sp;
535//}
536//
537
538void Debugger::Initialize(LoadPluginCallbackType load_plugin_callback) {
539 assert(g_debugger_list_ptr == nullptr &&(static_cast <bool> (g_debugger_list_ptr == nullptr &&
"Debugger::Initialize called more than once!") ? void (0) : __assert_fail
("g_debugger_list_ptr == nullptr && \"Debugger::Initialize called more than once!\""
, "lldb/source/Core/Debugger.cpp", 540, __extension__ __PRETTY_FUNCTION__
))
540 "Debugger::Initialize called more than once!")(static_cast <bool> (g_debugger_list_ptr == nullptr &&
"Debugger::Initialize called more than once!") ? void (0) : __assert_fail
("g_debugger_list_ptr == nullptr && \"Debugger::Initialize called more than once!\""
, "lldb/source/Core/Debugger.cpp", 540, __extension__ __PRETTY_FUNCTION__
))
;
541 g_debugger_list_mutex_ptr = new std::recursive_mutex();
542 g_debugger_list_ptr = new DebuggerList();
543 g_thread_pool = new llvm::ThreadPool(llvm::optimal_concurrency());
544 g_load_plugin_callback = load_plugin_callback;
545}
546
547void Debugger::Terminate() {
548 assert(g_debugger_list_ptr &&(static_cast <bool> (g_debugger_list_ptr && "Debugger::Terminate called without a matching Debugger::Initialize!"
) ? void (0) : __assert_fail ("g_debugger_list_ptr && \"Debugger::Terminate called without a matching Debugger::Initialize!\""
, "lldb/source/Core/Debugger.cpp", 549, __extension__ __PRETTY_FUNCTION__
))
549 "Debugger::Terminate called without a matching Debugger::Initialize!")(static_cast <bool> (g_debugger_list_ptr && "Debugger::Terminate called without a matching Debugger::Initialize!"
) ? void (0) : __assert_fail ("g_debugger_list_ptr && \"Debugger::Terminate called without a matching Debugger::Initialize!\""
, "lldb/source/Core/Debugger.cpp", 549, __extension__ __PRETTY_FUNCTION__
))
;
550
551 if (g_thread_pool) {
552 // The destructor will wait for all the threads to complete.
553 delete g_thread_pool;
554 }
555
556 if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {
557 // Clear our global list of debugger objects
558 {
559 std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);
560 for (const auto &debugger : *g_debugger_list_ptr)
561 debugger->Clear();
562 g_debugger_list_ptr->clear();
563 }
564 }
565}
566
567void Debugger::SettingsInitialize() { Target::SettingsInitialize(); }
568
569void Debugger::SettingsTerminate() { Target::SettingsTerminate(); }
570
571bool Debugger::LoadPlugin(const FileSpec &spec, Status &error) {
572 if (g_load_plugin_callback) {
573 llvm::sys::DynamicLibrary dynlib =
574 g_load_plugin_callback(shared_from_this(), spec, error);
575 if (dynlib.isValid()) {
576 m_loaded_plugins.push_back(dynlib);
577 return true;
578 }
579 } else {
580 // The g_load_plugin_callback is registered in SBDebugger::Initialize() and
581 // if the public API layer isn't available (code is linking against all of
582 // the internal LLDB static libraries), then we can't load plugins
583 error.SetErrorString("Public API layer is not available");
584 }
585 return false;
586}
587
588static FileSystem::EnumerateDirectoryResult
589LoadPluginCallback(void *baton, llvm::sys::fs::file_type ft,
590 llvm::StringRef path) {
591 Status error;
592
593 static ConstString g_dylibext(".dylib");
594 static ConstString g_solibext(".so");
595
596 if (!baton)
597 return FileSystem::eEnumerateDirectoryResultQuit;
598
599 Debugger *debugger = (Debugger *)baton;
600
601 namespace fs = llvm::sys::fs;
602 // If we have a regular file, a symbolic link or unknown file type, try and
603 // process the file. We must handle unknown as sometimes the directory
604 // enumeration might be enumerating a file system that doesn't have correct
605 // file type information.
606 if (ft == fs::file_type::regular_file || ft == fs::file_type::symlink_file ||
607 ft == fs::file_type::type_unknown) {
608 FileSpec plugin_file_spec(path);
609 FileSystem::Instance().Resolve(plugin_file_spec);
610
611 if (plugin_file_spec.GetFileNameExtension() != g_dylibext &&
612 plugin_file_spec.GetFileNameExtension() != g_solibext) {
613 return FileSystem::eEnumerateDirectoryResultNext;
614 }
615
616 Status plugin_load_error;
617 debugger->LoadPlugin(plugin_file_spec, plugin_load_error);
618
619 return FileSystem::eEnumerateDirectoryResultNext;
620 } else if (ft == fs::file_type::directory_file ||
621 ft == fs::file_type::symlink_file ||
622 ft == fs::file_type::type_unknown) {
623 // Try and recurse into anything that a directory or symbolic link. We must
624 // also do this for unknown as sometimes the directory enumeration might be
625 // enumerating a file system that doesn't have correct file type
626 // information.
627 return FileSystem::eEnumerateDirectoryResultEnter;
628 }
629
630 return FileSystem::eEnumerateDirectoryResultNext;
631}
632
633void Debugger::InstanceInitialize() {
634 const bool find_directories = true;
635 const bool find_files = true;
636 const bool find_other = true;
637 char dir_path[PATH_MAX4096];
638 if (FileSpec dir_spec = HostInfo::GetSystemPluginDir()) {
639 if (FileSystem::Instance().Exists(dir_spec) &&
640 dir_spec.GetPath(dir_path, sizeof(dir_path))) {
641 FileSystem::Instance().EnumerateDirectory(dir_path, find_directories,
642 find_files, find_other,
643 LoadPluginCallback, this);
644 }
645 }
646
647 if (FileSpec dir_spec = HostInfo::GetUserPluginDir()) {
648 if (FileSystem::Instance().Exists(dir_spec) &&
649 dir_spec.GetPath(dir_path, sizeof(dir_path))) {
650 FileSystem::Instance().EnumerateDirectory(dir_path, find_directories,
651 find_files, find_other,
652 LoadPluginCallback, this);
653 }
654 }
655
656 PluginManager::DebuggerInitialize(*this);
657}
658
659DebuggerSP Debugger::CreateInstance(lldb::LogOutputCallback log_callback,
660 void *baton) {
661 DebuggerSP debugger_sp(new Debugger(log_callback, baton));
662 if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {
663 std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);
664 g_debugger_list_ptr->push_back(debugger_sp);
665 }
666 debugger_sp->InstanceInitialize();
667 return debugger_sp;
668}
669
670void Debugger::Destroy(DebuggerSP &debugger_sp) {
671 if (!debugger_sp)
672 return;
673
674 CommandInterpreter &cmd_interpreter = debugger_sp->GetCommandInterpreter();
675
676 if (cmd_interpreter.GetSaveSessionOnQuit()) {
677 CommandReturnObject result(debugger_sp->GetUseColor());
678 cmd_interpreter.SaveTranscript(result);
679 if (result.Succeeded())
680 (*debugger_sp->GetAsyncOutputStream()) << result.GetOutputData() << '\n';
681 else
682 (*debugger_sp->GetAsyncErrorStream()) << result.GetErrorData() << '\n';
683 }
684
685 debugger_sp->Clear();
686
687 if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {
688 std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);
689 DebuggerList::iterator pos, end = g_debugger_list_ptr->end();
690 for (pos = g_debugger_list_ptr->begin(); pos != end; ++pos) {
691 if ((*pos).get() == debugger_sp.get()) {
692 g_debugger_list_ptr->erase(pos);
693 return;
694 }
695 }
696 }
697}
698
699DebuggerSP Debugger::FindDebuggerWithInstanceName(ConstString instance_name) {
700 DebuggerSP debugger_sp;
701 if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {
702 std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);
703 DebuggerList::iterator pos, end = g_debugger_list_ptr->end();
704 for (pos = g_debugger_list_ptr->begin(); pos != end; ++pos) {
705 if ((*pos)->m_instance_name == instance_name) {
706 debugger_sp = *pos;
707 break;
708 }
709 }
710 }
711 return debugger_sp;
712}
713
714TargetSP Debugger::FindTargetWithProcessID(lldb::pid_t pid) {
715 TargetSP target_sp;
716 if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {
717 std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);
718 DebuggerList::iterator pos, end = g_debugger_list_ptr->end();
719 for (pos = g_debugger_list_ptr->begin(); pos != end; ++pos) {
720 target_sp = (*pos)->GetTargetList().FindTargetWithProcessID(pid);
721 if (target_sp)
722 break;
723 }
724 }
725 return target_sp;
726}
727
728TargetSP Debugger::FindTargetWithProcess(Process *process) {
729 TargetSP target_sp;
730 if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {
731 std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);
732 DebuggerList::iterator pos, end = g_debugger_list_ptr->end();
733 for (pos = g_debugger_list_ptr->begin(); pos != end; ++pos) {
734 target_sp = (*pos)->GetTargetList().FindTargetWithProcess(process);
735 if (target_sp)
736 break;
737 }
738 }
739 return target_sp;
740}
741
742ConstString Debugger::GetStaticBroadcasterClass() {
743 static ConstString class_name("lldb.debugger");
744 return class_name;
745}
746
747Debugger::Debugger(lldb::LogOutputCallback log_callback, void *baton)
748 : UserID(g_unique_id++),
749 Properties(std::make_shared<OptionValueProperties>()),
750 m_input_file_sp(std::make_shared<NativeFile>(stdinstdin, false)),
751 m_output_stream_sp(std::make_shared<StreamFile>(stdoutstdout, false)),
752 m_error_stream_sp(std::make_shared<StreamFile>(stderrstderr, false)),
753 m_input_recorder(nullptr),
754 m_broadcaster_manager_sp(BroadcasterManager::MakeBroadcasterManager()),
755 m_terminal_state(), m_target_list(*this), m_platform_list(),
756 m_listener_sp(Listener::MakeListener("lldb.Debugger")),
757 m_source_manager_up(), m_source_file_cache(),
758 m_command_interpreter_up(
759 std::make_unique<CommandInterpreter>(*this, false)),
760 m_io_handler_stack(), m_instance_name(), m_loaded_plugins(),
761 m_event_handler_thread(), m_io_handler_thread(),
762 m_sync_broadcaster(nullptr, "lldb.debugger.sync"),
763 m_broadcaster(m_broadcaster_manager_sp,
764 GetStaticBroadcasterClass().AsCString()),
765 m_forward_listener_sp(), m_clear_once() {
766 m_instance_name.SetString(llvm::formatv("debugger_{0}", GetID()).str());
767 if (log_callback)
768 m_callback_handler_sp =
769 std::make_shared<CallbackLogHandler>(log_callback, baton);
770 m_command_interpreter_up->Initialize();
771 // Always add our default platform to the platform list
772 PlatformSP default_platform_sp(Platform::GetHostPlatform());
773 assert(default_platform_sp)(static_cast <bool> (default_platform_sp) ? void (0) : __assert_fail
("default_platform_sp", "lldb/source/Core/Debugger.cpp", 773
, __extension__ __PRETTY_FUNCTION__))
;
774 m_platform_list.Append(default_platform_sp, true);
775
776 // Create the dummy target.
777 {
778 ArchSpec arch(Target::GetDefaultArchitecture());
779 if (!arch.IsValid())
780 arch = HostInfo::GetArchitecture();
781 assert(arch.IsValid() && "No valid default or host archspec")(static_cast <bool> (arch.IsValid() && "No valid default or host archspec"
) ? void (0) : __assert_fail ("arch.IsValid() && \"No valid default or host archspec\""
, "lldb/source/Core/Debugger.cpp", 781, __extension__ __PRETTY_FUNCTION__
))
;
782 const bool is_dummy_target = true;
783 m_dummy_target_sp.reset(
784 new Target(*this, arch, default_platform_sp, is_dummy_target));
785 }
786 assert(m_dummy_target_sp.get() && "Couldn't construct dummy target?")(static_cast <bool> (m_dummy_target_sp.get() &&
"Couldn't construct dummy target?") ? void (0) : __assert_fail
("m_dummy_target_sp.get() && \"Couldn't construct dummy target?\""
, "lldb/source/Core/Debugger.cpp", 786, __extension__ __PRETTY_FUNCTION__
))
;
787
788 m_collection_sp->Initialize(g_debugger_properties);
789 m_collection_sp->AppendProperty(
790 ConstString("target"),
791 ConstString("Settings specify to debugging targets."), true,
792 Target::GetGlobalProperties().GetValueProperties());
793 m_collection_sp->AppendProperty(
794 ConstString("platform"), ConstString("Platform settings."), true,
795 Platform::GetGlobalPlatformProperties().GetValueProperties());
796 m_collection_sp->AppendProperty(
797 ConstString("symbols"), ConstString("Symbol lookup and cache settings."),
798 true, ModuleList::GetGlobalModuleListProperties().GetValueProperties());
799 if (m_command_interpreter_up) {
800 m_collection_sp->AppendProperty(
801 ConstString("interpreter"),
802 ConstString("Settings specify to the debugger's command interpreter."),
803 true, m_command_interpreter_up->GetValueProperties());
804 }
805 OptionValueSInt64 *term_width =
806 m_collection_sp->GetPropertyAtIndexAsOptionValueSInt64(
807 nullptr, ePropertyTerminalWidth);
808 term_width->SetMinimumValue(10);
809 term_width->SetMaximumValue(1024);
810
811 // Turn off use-color if this is a dumb terminal.
812 const char *term = getenv("TERM");
813 if (term && !strcmp(term, "dumb"))
814 SetUseColor(false);
815 // Turn off use-color if we don't write to a terminal with color support.
816 if (!GetOutputFile().GetIsTerminalWithColors())
817 SetUseColor(false);
818
819#if defined(_WIN32) && defined(ENABLE_VIRTUAL_TERMINAL_PROCESSING)
820 // Enabling use of ANSI color codes because LLDB is using them to highlight
821 // text.
822 llvm::sys::Process::UseANSIEscapeCodes(true);
823#endif
824}
825
826Debugger::~Debugger() { Clear(); }
827
828void Debugger::Clear() {
829 // Make sure we call this function only once. With the C++ global destructor
830 // chain having a list of debuggers and with code that can be running on
831 // other threads, we need to ensure this doesn't happen multiple times.
832 //
833 // The following functions call Debugger::Clear():
834 // Debugger::~Debugger();
835 // static void Debugger::Destroy(lldb::DebuggerSP &debugger_sp);
836 // static void Debugger::Terminate();
837 llvm::call_once(m_clear_once, [this]() {
838 ClearIOHandlers();
839 StopIOHandlerThread();
840 StopEventHandlerThread();
841 m_listener_sp->Clear();
842 for (TargetSP target_sp : m_target_list.Targets()) {
843 if (target_sp) {
844 if (ProcessSP process_sp = target_sp->GetProcessSP())
845 process_sp->Finalize();
846 target_sp->Destroy();
847 }
848 }
849 m_broadcaster_manager_sp->Clear();
850
851 // Close the input file _before_ we close the input read communications
852 // class as it does NOT own the input file, our m_input_file does.
853 m_terminal_state.Clear();
854 GetInputFile().Close();
855
856 m_command_interpreter_up->Clear();
857 });
858}
859
860bool Debugger::GetCloseInputOnEOF() const {
861 // return m_input_comm.GetCloseOnEOF();
862 return false;
863}
864
865void Debugger::SetCloseInputOnEOF(bool b) {
866 // m_input_comm.SetCloseOnEOF(b);
867}
868
869bool Debugger::GetAsyncExecution() {
870 return !m_command_interpreter_up->GetSynchronous();
871}
872
873void Debugger::SetAsyncExecution(bool async_execution) {
874 m_command_interpreter_up->SetSynchronous(!async_execution);
875}
876
877repro::DataRecorder *Debugger::GetInputRecorder() { return m_input_recorder; }
878
879static inline int OpenPipe(int fds[2], std::size_t size) {
880#ifdef _WIN32
881 return _pipe(fds, size, O_BINARY);
882#else
883 (void)size;
884 return pipe(fds);
885#endif
886}
887
888Status Debugger::SetInputString(const char *data) {
889 Status result;
890 enum PIPES { READ, WRITE }; // Indexes for the read and write fds
891 int fds[2] = {-1, -1};
892
893 if (data == nullptr) {
1
Assuming the condition is false
2
Taking false branch
894 result.SetErrorString("String data is null");
895 return result;
896 }
897
898 size_t size = strlen(data);
899 if (size == 0) {
3
Assuming 'size' is not equal to 0
4
Taking false branch
900 result.SetErrorString("String data is empty");
901 return result;
902 }
903
904 if (OpenPipe(fds, size) != 0) {
5
Assuming the condition is false
6
Taking false branch
905 result.SetErrorString(
906 "can't create pipe file descriptors for LLDB commands");
907 return result;
908 }
909
910 int r = write(fds[WRITE], data, size);
911 (void)r;
912 // Close the write end of the pipe, so that the command interpreter will exit
913 // when it consumes all the data.
914 llvm::sys::Process::SafelyCloseFileDescriptor(fds[WRITE]);
915
916 // Open the read file descriptor as a FILE * that we can return as an input
917 // handle.
918 FILE *commands_file = fdopen(fds[READ], "rb");
919 if (commands_file == nullptr) {
7
Assuming the condition is false
8
Taking false branch
920 result.SetErrorStringWithFormat("fdopen(%i, \"rb\") failed (errno = %i) "
921 "when trying to open LLDB commands pipe",
922 fds[READ], errno(*__errno_location ()));
923 llvm::sys::Process::SafelyCloseFileDescriptor(fds[READ]);
924 return result;
925 }
926
927 return SetInputFile(
9
Calling 'Debugger::SetInputFile'
928 (FileSP)std::make_shared<NativeFile>(commands_file, true));
929}
930
931Status Debugger::SetInputFile(FileSP file_sp) {
932 Status error;
933 repro::DataRecorder *recorder = nullptr;
934 if (repro::Generator *g = repro::Reproducer::Instance().GetGenerator())
10
Assuming 'g' is null
11
Taking false branch
935 recorder = g->GetOrCreate<repro::CommandProvider>().GetNewRecorder();
936
937 static std::unique_ptr<repro::MultiLoader<repro::CommandProvider>> loader =
938 repro::MultiLoader<repro::CommandProvider>::Create(
939 repro::Reproducer::Instance().GetLoader());
940 if (loader) {
12
Taking true branch
941 llvm::Optional<std::string> nextfile = loader->GetNextFile();
942 FILE *fh = nextfile ? FileSystem::Instance().Fopen(nextfile->c_str(), "r")
13
'?' condition is true
943 : nullptr;
944 // FIXME Jonas Devlieghere: shouldn't this error be propagated out to the
945 // reproducer somehow if fh is NULL?
946 if (fh) {
14
Assuming 'fh' is non-null
15
Taking true branch
947 file_sp = std::make_shared<NativeFile>(fh, true);
16
Calling 'make_shared<lldb_private::NativeFile, _IO_FILE *&, bool>'
34
Returned allocated memory
948 }
949 }
950
951 if (!file_sp || !file_sp->IsValid()) {
35
Taking true branch
952 error.SetErrorString("invalid file");
36
Potential leak of memory pointed to by 'file_sp._M_refcount._M_pi'
953 return error;
954 }
955
956 SetInputFile(file_sp, recorder);
957 return error;
958}
959
960void Debugger::SetInputFile(FileSP file_sp, repro::DataRecorder *recorder) {
961 assert(file_sp && file_sp->IsValid())(static_cast <bool> (file_sp && file_sp->IsValid
()) ? void (0) : __assert_fail ("file_sp && file_sp->IsValid()"
, "lldb/source/Core/Debugger.cpp", 961, __extension__ __PRETTY_FUNCTION__
))
;
962 m_input_recorder = recorder;
963 m_input_file_sp = std::move(file_sp);
964 // Save away the terminal state if that is relevant, so that we can restore
965 // it in RestoreInputState.
966 SaveInputTerminalState();
967}
968
969void Debugger::SetOutputFile(FileSP file_sp) {
970 assert(file_sp && file_sp->IsValid())(static_cast <bool> (file_sp && file_sp->IsValid
()) ? void (0) : __assert_fail ("file_sp && file_sp->IsValid()"
, "lldb/source/Core/Debugger.cpp", 970, __extension__ __PRETTY_FUNCTION__
))
;
971 m_output_stream_sp = std::make_shared<StreamFile>(file_sp);
972}
973
974void Debugger::SetErrorFile(FileSP file_sp) {
975 assert(file_sp && file_sp->IsValid())(static_cast <bool> (file_sp && file_sp->IsValid
()) ? void (0) : __assert_fail ("file_sp && file_sp->IsValid()"
, "lldb/source/Core/Debugger.cpp", 975, __extension__ __PRETTY_FUNCTION__
))
;
976 m_error_stream_sp = std::make_shared<StreamFile>(file_sp);
977}
978
979void Debugger::SaveInputTerminalState() {
980 int fd = GetInputFile().GetDescriptor();
981 if (fd != File::kInvalidDescriptor)
982 m_terminal_state.Save(fd, true);
983}
984
985void Debugger::RestoreInputTerminalState() { m_terminal_state.Restore(); }
986
987ExecutionContext Debugger::GetSelectedExecutionContext() {
988 bool adopt_selected = true;
989 ExecutionContextRef exe_ctx_ref(GetSelectedTarget().get(), adopt_selected);
990 return ExecutionContext(exe_ctx_ref);
991}
992
993void Debugger::DispatchInputInterrupt() {
994 std::lock_guard<std::recursive_mutex> guard(m_io_handler_stack.GetMutex());
995 IOHandlerSP reader_sp(m_io_handler_stack.Top());
996 if (reader_sp)
997 reader_sp->Interrupt();
998}
999
1000void Debugger::DispatchInputEndOfFile() {
1001 std::lock_guard<std::recursive_mutex> guard(m_io_handler_stack.GetMutex());
1002 IOHandlerSP reader_sp(m_io_handler_stack.Top());
1003 if (reader_sp)
1004 reader_sp->GotEOF();
1005}
1006
1007void Debugger::ClearIOHandlers() {
1008 // The bottom input reader should be the main debugger input reader. We do
1009 // not want to close that one here.
1010 std::lock_guard<std::recursive_mutex> guard(m_io_handler_stack.GetMutex());
1011 while (m_io_handler_stack.GetSize() > 1) {
1012 IOHandlerSP reader_sp(m_io_handler_stack.Top());
1013 if (reader_sp)
1014 PopIOHandler(reader_sp);
1015 }
1016}
1017
1018void Debugger::RunIOHandlers() {
1019 IOHandlerSP reader_sp = m_io_handler_stack.Top();
1020 while (true) {
1021 if (!reader_sp)
1022 break;
1023
1024 reader_sp->Run();
1025 {
1026 std::lock_guard<std::recursive_mutex> guard(
1027 m_io_handler_synchronous_mutex);
1028
1029 // Remove all input readers that are done from the top of the stack
1030 while (true) {
1031 IOHandlerSP top_reader_sp = m_io_handler_stack.Top();
1032 if (top_reader_sp && top_reader_sp->GetIsDone())
1033 PopIOHandler(top_reader_sp);
1034 else
1035 break;
1036 }
1037 reader_sp = m_io_handler_stack.Top();
1038 }
1039 }
1040 ClearIOHandlers();
1041}
1042
1043void Debugger::RunIOHandlerSync(const IOHandlerSP &reader_sp) {
1044 std::lock_guard<std::recursive_mutex> guard(m_io_handler_synchronous_mutex);
1045
1046 PushIOHandler(reader_sp);
1047 IOHandlerSP top_reader_sp = reader_sp;
1048
1049 while (top_reader_sp) {
1050 if (!top_reader_sp)
1051 break;
1052
1053 top_reader_sp->Run();
1054
1055 // Don't unwind past the starting point.
1056 if (top_reader_sp.get() == reader_sp.get()) {
1057 if (PopIOHandler(reader_sp))
1058 break;
1059 }
1060
1061 // If we pushed new IO handlers, pop them if they're done or restart the
1062 // loop to run them if they're not.
1063 while (true) {
1064 top_reader_sp = m_io_handler_stack.Top();
1065 if (top_reader_sp && top_reader_sp->GetIsDone()) {
1066 PopIOHandler(top_reader_sp);
1067 // Don't unwind past the starting point.
1068 if (top_reader_sp.get() == reader_sp.get())
1069 return;
1070 } else {
1071 break;
1072 }
1073 }
1074 }
1075}
1076
1077bool Debugger::IsTopIOHandler(const lldb::IOHandlerSP &reader_sp) {
1078 return m_io_handler_stack.IsTop(reader_sp);
1079}
1080
1081bool Debugger::CheckTopIOHandlerTypes(IOHandler::Type top_type,
1082 IOHandler::Type second_top_type) {
1083 return m_io_handler_stack.CheckTopIOHandlerTypes(top_type, second_top_type);
1084}
1085
1086void Debugger::PrintAsync(const char *s, size_t len, bool is_stdout) {
1087 bool printed = m_io_handler_stack.PrintAsync(s, len, is_stdout);
1088 if (!printed) {
1089 lldb::StreamFileSP stream =
1090 is_stdout ? m_output_stream_sp : m_error_stream_sp;
1091 stream->Write(s, len);
1092 }
1093}
1094
1095ConstString Debugger::GetTopIOHandlerControlSequence(char ch) {
1096 return m_io_handler_stack.GetTopIOHandlerControlSequence(ch);
1097}
1098
1099const char *Debugger::GetIOHandlerCommandPrefix() {
1100 return m_io_handler_stack.GetTopIOHandlerCommandPrefix();
1101}
1102
1103const char *Debugger::GetIOHandlerHelpPrologue() {
1104 return m_io_handler_stack.GetTopIOHandlerHelpPrologue();
1105}
1106
1107bool Debugger::RemoveIOHandler(const IOHandlerSP &reader_sp) {
1108 return PopIOHandler(reader_sp);
1109}
1110
1111void Debugger::RunIOHandlerAsync(const IOHandlerSP &reader_sp,
1112 bool cancel_top_handler) {
1113 PushIOHandler(reader_sp, cancel_top_handler);
1114}
1115
1116void Debugger::AdoptTopIOHandlerFilesIfInvalid(FileSP &in, StreamFileSP &out,
1117 StreamFileSP &err) {
1118 // Before an IOHandler runs, it must have in/out/err streams. This function
1119 // is called when one ore more of the streams are nullptr. We use the top
1120 // input reader's in/out/err streams, or fall back to the debugger file
1121 // handles, or we fall back onto stdin/stdout/stderr as a last resort.
1122
1123 std::lock_guard<std::recursive_mutex> guard(m_io_handler_stack.GetMutex());
1124 IOHandlerSP top_reader_sp(m_io_handler_stack.Top());
1125 // If no STDIN has been set, then set it appropriately
1126 if (!in || !in->IsValid()) {
1127 if (top_reader_sp)
1128 in = top_reader_sp->GetInputFileSP();
1129 else
1130 in = GetInputFileSP();
1131 // If there is nothing, use stdin
1132 if (!in)
1133 in = std::make_shared<NativeFile>(stdinstdin, false);
1134 }
1135 // If no STDOUT has been set, then set it appropriately
1136 if (!out || !out->GetFile().IsValid()) {
1137 if (top_reader_sp)
1138 out = top_reader_sp->GetOutputStreamFileSP();
1139 else
1140 out = GetOutputStreamSP();
1141 // If there is nothing, use stdout
1142 if (!out)
1143 out = std::make_shared<StreamFile>(stdoutstdout, false);
1144 }
1145 // If no STDERR has been set, then set it appropriately
1146 if (!err || !err->GetFile().IsValid()) {
1147 if (top_reader_sp)
1148 err = top_reader_sp->GetErrorStreamFileSP();
1149 else
1150 err = GetErrorStreamSP();
1151 // If there is nothing, use stderr
1152 if (!err)
1153 err = std::make_shared<StreamFile>(stderrstderr, false);
1154 }
1155}
1156
1157void Debugger::PushIOHandler(const IOHandlerSP &reader_sp,
1158 bool cancel_top_handler) {
1159 if (!reader_sp)
1160 return;
1161
1162 std::lock_guard<std::recursive_mutex> guard(m_io_handler_stack.GetMutex());
1163
1164 // Get the current top input reader...
1165 IOHandlerSP top_reader_sp(m_io_handler_stack.Top());
1166
1167 // Don't push the same IO handler twice...
1168 if (reader_sp == top_reader_sp)
1169 return;
1170
1171 // Push our new input reader
1172 m_io_handler_stack.Push(reader_sp);
1173 reader_sp->Activate();
1174
1175 // Interrupt the top input reader to it will exit its Run() function and let
1176 // this new input reader take over
1177 if (top_reader_sp) {
1178 top_reader_sp->Deactivate();
1179 if (cancel_top_handler)
1180 top_reader_sp->Cancel();
1181 }
1182}
1183
1184bool Debugger::PopIOHandler(const IOHandlerSP &pop_reader_sp) {
1185 if (!pop_reader_sp)
1186 return false;
1187
1188 std::lock_guard<std::recursive_mutex> guard(m_io_handler_stack.GetMutex());
1189
1190 // The reader on the stop of the stack is done, so let the next read on the
1191 // stack refresh its prompt and if there is one...
1192 if (m_io_handler_stack.IsEmpty())
1193 return false;
1194
1195 IOHandlerSP reader_sp(m_io_handler_stack.Top());
1196
1197 if (pop_reader_sp != reader_sp)
1198 return false;
1199
1200 reader_sp->Deactivate();
1201 reader_sp->Cancel();
1202 m_io_handler_stack.Pop();
1203
1204 reader_sp = m_io_handler_stack.Top();
1205 if (reader_sp)
1206 reader_sp->Activate();
1207
1208 return true;
1209}
1210
1211StreamSP Debugger::GetAsyncOutputStream() {
1212 return std::make_shared<StreamAsynchronousIO>(*this, true, GetUseColor());
1213}
1214
1215StreamSP Debugger::GetAsyncErrorStream() {
1216 return std::make_shared<StreamAsynchronousIO>(*this, false, GetUseColor());
1217}
1218
1219size_t Debugger::GetNumDebuggers() {
1220 if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {
1221 std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);
1222 return g_debugger_list_ptr->size();
1223 }
1224 return 0;
1225}
1226
1227lldb::DebuggerSP Debugger::GetDebuggerAtIndex(size_t index) {
1228 DebuggerSP debugger_sp;
1229
1230 if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {
1231 std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);
1232 if (index < g_debugger_list_ptr->size())
1233 debugger_sp = g_debugger_list_ptr->at(index);
1234 }
1235
1236 return debugger_sp;
1237}
1238
1239DebuggerSP Debugger::FindDebuggerWithID(lldb::user_id_t id) {
1240 DebuggerSP debugger_sp;
1241
1242 if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {
1243 std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);
1244 DebuggerList::iterator pos, end = g_debugger_list_ptr->end();
1245 for (pos = g_debugger_list_ptr->begin(); pos != end; ++pos) {
1246 if ((*pos)->GetID() == id) {
1247 debugger_sp = *pos;
1248 break;
1249 }
1250 }
1251 }
1252 return debugger_sp;
1253}
1254
1255bool Debugger::FormatDisassemblerAddress(const FormatEntity::Entry *format,
1256 const SymbolContext *sc,
1257 const SymbolContext *prev_sc,
1258 const ExecutionContext *exe_ctx,
1259 const Address *addr, Stream &s) {
1260 FormatEntity::Entry format_entry;
1261
1262 if (format == nullptr) {
1263 if (exe_ctx != nullptr && exe_ctx->HasTargetScope())
1264 format = exe_ctx->GetTargetRef().GetDebugger().GetDisassemblyFormat();
1265 if (format == nullptr) {
1266 FormatEntity::Parse("${addr}: ", format_entry);
1267 format = &format_entry;
1268 }
1269 }
1270 bool function_changed = false;
1271 bool initial_function = false;
1272 if (prev_sc && (prev_sc->function || prev_sc->symbol)) {
1273 if (sc && (sc->function || sc->symbol)) {
1274 if (prev_sc->symbol && sc->symbol) {
1275 if (!sc->symbol->Compare(prev_sc->symbol->GetName(),
1276 prev_sc->symbol->GetType())) {
1277 function_changed = true;
1278 }
1279 } else if (prev_sc->function && sc->function) {
1280 if (prev_sc->function->GetMangled() != sc->function->GetMangled()) {
1281 function_changed = true;
1282 }
1283 }
1284 }
1285 }
1286 // The first context on a list of instructions will have a prev_sc that has
1287 // no Function or Symbol -- if SymbolContext had an IsValid() method, it
1288 // would return false. But we do get a prev_sc pointer.
1289 if ((sc && (sc->function || sc->symbol)) && prev_sc &&
1290 (prev_sc->function == nullptr && prev_sc->symbol == nullptr)) {
1291 initial_function = true;
1292 }
1293 return FormatEntity::Format(*format, s, sc, exe_ctx, addr, nullptr,
1294 function_changed, initial_function);
1295}
1296
1297void Debugger::SetLoggingCallback(lldb::LogOutputCallback log_callback,
1298 void *baton) {
1299 // For simplicity's sake, I am not going to deal with how to close down any
1300 // open logging streams, I just redirect everything from here on out to the
1301 // callback.
1302 m_callback_handler_sp =
1303 std::make_shared<CallbackLogHandler>(log_callback, baton);
1304}
1305
1306static void PrivateReportProgress(Debugger &debugger, uint64_t progress_id,
1307 const std::string &message,
1308 uint64_t completed, uint64_t total,
1309 bool is_debugger_specific) {
1310 // Only deliver progress events if we have any progress listeners.
1311 const uint32_t event_type = Debugger::eBroadcastBitProgress;
1312 if (!debugger.GetBroadcaster().EventTypeHasListeners(event_type))
1313 return;
1314 EventSP event_sp(new Event(
1315 event_type, new ProgressEventData(progress_id, message, completed, total,
1316 is_debugger_specific)));
1317 debugger.GetBroadcaster().BroadcastEvent(event_sp);
1318}
1319
1320void Debugger::ReportProgress(uint64_t progress_id, const std::string &message,
1321 uint64_t completed, uint64_t total,
1322 llvm::Optional<lldb::user_id_t> debugger_id) {
1323 // Check if this progress is for a specific debugger.
1324 if (debugger_id) {
1325 // It is debugger specific, grab it and deliver the event if the debugger
1326 // still exists.
1327 DebuggerSP debugger_sp = FindDebuggerWithID(*debugger_id);
1328 if (debugger_sp)
1329 PrivateReportProgress(*debugger_sp, progress_id, message, completed,
1330 total, /*is_debugger_specific*/ true);
1331 return;
1332 }
1333 // The progress event is not debugger specific, iterate over all debuggers
1334 // and deliver a progress event to each one.
1335 if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {
1336 std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);
1337 DebuggerList::iterator pos, end = g_debugger_list_ptr->end();
1338 for (pos = g_debugger_list_ptr->begin(); pos != end; ++pos)
1339 PrivateReportProgress(*(*pos), progress_id, message, completed, total,
1340 /*is_debugger_specific*/ false);
1341 }
1342}
1343
1344static void PrivateReportDiagnostic(Debugger &debugger,
1345 DiagnosticEventData::Type type,
1346 std::string message,
1347 bool debugger_specific) {
1348 uint32_t event_type = 0;
1349 switch (type) {
1350 case DiagnosticEventData::Type::Warning:
1351 event_type = Debugger::eBroadcastBitWarning;
1352 break;
1353 case DiagnosticEventData::Type::Error:
1354 event_type = Debugger::eBroadcastBitError;
1355 break;
1356 }
1357
1358 Broadcaster &broadcaster = debugger.GetBroadcaster();
1359 if (!broadcaster.EventTypeHasListeners(event_type)) {
1360 // Diagnostics are too important to drop. If nobody is listening, print the
1361 // diagnostic directly to the debugger's error stream.
1362 DiagnosticEventData event_data(type, std::move(message), debugger_specific);
1363 StreamSP stream = debugger.GetAsyncErrorStream();
1364 event_data.Dump(stream.get());
1365 return;
1366 }
1367 EventSP event_sp = std::make_shared<Event>(
1368 event_type,
1369 new DiagnosticEventData(type, std::move(message), debugger_specific));
1370 broadcaster.BroadcastEvent(event_sp);
1371}
1372
1373void Debugger::ReportDiagnosticImpl(DiagnosticEventData::Type type,
1374 std::string message,
1375 llvm::Optional<lldb::user_id_t> debugger_id,
1376 std::once_flag *once) {
1377 auto ReportDiagnosticLambda = [&]() {
1378 // Check if this progress is for a specific debugger.
1379 if (debugger_id) {
1380 // It is debugger specific, grab it and deliver the event if the debugger
1381 // still exists.
1382 DebuggerSP debugger_sp = FindDebuggerWithID(*debugger_id);
1383 if (debugger_sp)
1384 PrivateReportDiagnostic(*debugger_sp, type, std::move(message), true);
1385 return;
1386 }
1387 // The progress event is not debugger specific, iterate over all debuggers
1388 // and deliver a progress event to each one.
1389 if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {
1390 std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);
1391 for (const auto &debugger : *g_debugger_list_ptr)
1392 PrivateReportDiagnostic(*debugger, type, message, false);
1393 }
1394 };
1395
1396 if (once)
1397 std::call_once(*once, ReportDiagnosticLambda);
1398 else
1399 ReportDiagnosticLambda();
1400}
1401
1402void Debugger::ReportWarning(std::string message,
1403 llvm::Optional<lldb::user_id_t> debugger_id,
1404 std::once_flag *once) {
1405 ReportDiagnosticImpl(DiagnosticEventData::Type::Warning, std::move(message),
1406 debugger_id, once);
1407}
1408
1409void Debugger::ReportError(std::string message,
1410 llvm::Optional<lldb::user_id_t> debugger_id,
1411 std::once_flag *once) {
1412
1413 ReportDiagnosticImpl(DiagnosticEventData::Type::Error, std::move(message),
1414 debugger_id, once);
1415}
1416
1417void Debugger::ReportSymbolChange(const ModuleSpec &module_spec) {
1418 if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {
1419 std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);
1420 for (DebuggerSP debugger_sp : *g_debugger_list_ptr) {
1421 EventSP event_sp = std::make_shared<Event>(
1422 Debugger::eBroadcastSymbolChange,
1423 new SymbolChangeEventData(debugger_sp, module_spec));
1424 debugger_sp->GetBroadcaster().BroadcastEvent(event_sp);
1425 }
1426 }
1427}
1428
1429static std::shared_ptr<LogHandler>
1430CreateLogHandler(LogHandlerKind log_handler_kind, int fd, bool should_close,
1431 size_t buffer_size) {
1432 switch (log_handler_kind) {
1433 case eLogHandlerStream:
1434 return std::make_shared<StreamLogHandler>(fd, should_close, buffer_size);
1435 case eLogHandlerCircular:
1436 return std::make_shared<RotatingLogHandler>(buffer_size);
1437 case eLogHandlerSystem:
1438 return std::make_shared<SystemLogHandler>();
1439 case eLogHandlerCallback:
1440 return {};
1441 }
1442 return {};
1443}
1444
1445bool Debugger::EnableLog(llvm::StringRef channel,
1446 llvm::ArrayRef<const char *> categories,
1447 llvm::StringRef log_file, uint32_t log_options,
1448 size_t buffer_size, LogHandlerKind log_handler_kind,
1449 llvm::raw_ostream &error_stream) {
1450
1451 std::shared_ptr<LogHandler> log_handler_sp;
1452 if (m_callback_handler_sp) {
1453 log_handler_sp = m_callback_handler_sp;
1454 // For now when using the callback mode you always get thread & timestamp.
1455 log_options |=
1456 LLDB_LOG_OPTION_PREPEND_TIMESTAMP(1u << 4) | LLDB_LOG_OPTION_PREPEND_THREAD_NAME(1U << 6);
1457 } else if (log_file.empty()) {
1458 log_handler_sp =
1459 CreateLogHandler(log_handler_kind, GetOutputFile().GetDescriptor(),
1460 /*should_close=*/false, buffer_size);
1461 } else {
1462 auto pos = m_stream_handlers.find(log_file);
1463 if (pos != m_stream_handlers.end())
1464 log_handler_sp = pos->second.lock();
1465 if (!log_handler_sp) {
1466 File::OpenOptions flags =
1467 File::eOpenOptionWriteOnly | File::eOpenOptionCanCreate;
1468 if (log_options & LLDB_LOG_OPTION_APPEND(1U << 8))
1469 flags |= File::eOpenOptionAppend;
1470 else
1471 flags |= File::eOpenOptionTruncate;
1472 llvm::Expected<FileUP> file = FileSystem::Instance().Open(
1473 FileSpec(log_file), flags, lldb::eFilePermissionsFileDefault, false);
1474 if (!file) {
1475 error_stream << "Unable to open log file '" << log_file
1476 << "': " << llvm::toString(file.takeError()) << "\n";
1477 return false;
1478 }
1479
1480 log_handler_sp =
1481 CreateLogHandler(log_handler_kind, (*file)->GetDescriptor(),
1482 /*should_close=*/true, buffer_size);
1483 m_stream_handlers[log_file] = log_handler_sp;
1484 }
1485 }
1486 assert(log_handler_sp)(static_cast <bool> (log_handler_sp) ? void (0) : __assert_fail
("log_handler_sp", "lldb/source/Core/Debugger.cpp", 1486, __extension__
__PRETTY_FUNCTION__))
;
1487
1488 if (log_options == 0)
1489 log_options = LLDB_LOG_OPTION_PREPEND_THREAD_NAME(1U << 6);
1490
1491 return Log::EnableLogChannel(log_handler_sp, log_options, channel, categories,
1492 error_stream);
1493}
1494
1495ScriptInterpreter *
1496Debugger::GetScriptInterpreter(bool can_create,
1497 llvm::Optional<lldb::ScriptLanguage> language) {
1498 std::lock_guard<std::recursive_mutex> locker(m_script_interpreter_mutex);
1499 lldb::ScriptLanguage script_language =
1500 language ? *language : GetScriptLanguage();
1501
1502 if (!m_script_interpreters[script_language]) {
1503 if (!can_create)
1504 return nullptr;
1505 m_script_interpreters[script_language] =
1506 PluginManager::GetScriptInterpreterForLanguage(script_language, *this);
1507 }
1508
1509 return m_script_interpreters[script_language].get();
1510}
1511
1512SourceManager &Debugger::GetSourceManager() {
1513 if (!m_source_manager_up)
1514 m_source_manager_up = std::make_unique<SourceManager>(shared_from_this());
1515 return *m_source_manager_up;
1516}
1517
1518// This function handles events that were broadcast by the process.
1519void Debugger::HandleBreakpointEvent(const EventSP &event_sp) {
1520 using namespace lldb;
1521 const uint32_t event_type =
1522 Breakpoint::BreakpointEventData::GetBreakpointEventTypeFromEvent(
1523 event_sp);
1524
1525 // if (event_type & eBreakpointEventTypeAdded
1526 // || event_type & eBreakpointEventTypeRemoved
1527 // || event_type & eBreakpointEventTypeEnabled
1528 // || event_type & eBreakpointEventTypeDisabled
1529 // || event_type & eBreakpointEventTypeCommandChanged
1530 // || event_type & eBreakpointEventTypeConditionChanged
1531 // || event_type & eBreakpointEventTypeIgnoreChanged
1532 // || event_type & eBreakpointEventTypeLocationsResolved)
1533 // {
1534 // // Don't do anything about these events, since the breakpoint
1535 // commands already echo these actions.
1536 // }
1537 //
1538 if (event_type & eBreakpointEventTypeLocationsAdded) {
1539 uint32_t num_new_locations =
1540 Breakpoint::BreakpointEventData::GetNumBreakpointLocationsFromEvent(
1541 event_sp);
1542 if (num_new_locations > 0) {
1543 BreakpointSP breakpoint =
1544 Breakpoint::BreakpointEventData::GetBreakpointFromEvent(event_sp);
1545 StreamSP output_sp(GetAsyncOutputStream());
1546 if (output_sp) {
1547 output_sp->Printf("%d location%s added to breakpoint %d\n",
1548 num_new_locations, num_new_locations == 1 ? "" : "s",
1549 breakpoint->GetID());
1550 output_sp->Flush();
1551 }
1552 }
1553 }
1554 // else if (event_type & eBreakpointEventTypeLocationsRemoved)
1555 // {
1556 // // These locations just get disabled, not sure it is worth spamming
1557 // folks about this on the command line.
1558 // }
1559 // else if (event_type & eBreakpointEventTypeLocationsResolved)
1560 // {
1561 // // This might be an interesting thing to note, but I'm going to
1562 // leave it quiet for now, it just looked noisy.
1563 // }
1564}
1565
1566void Debugger::FlushProcessOutput(Process &process, bool flush_stdout,
1567 bool flush_stderr) {
1568 const auto &flush = [&](Stream &stream,
1569 size_t (Process::*get)(char *, size_t, Status &)) {
1570 Status error;
1571 size_t len;
1572 char buffer[1024];
1573 while ((len = (process.*get)(buffer, sizeof(buffer), error)) > 0)
1574 stream.Write(buffer, len);
1575 stream.Flush();
1576 };
1577
1578 std::lock_guard<std::mutex> guard(m_output_flush_mutex);
1579 if (flush_stdout)
1580 flush(*GetAsyncOutputStream(), &Process::GetSTDOUT);
1581 if (flush_stderr)
1582 flush(*GetAsyncErrorStream(), &Process::GetSTDERR);
1583}
1584
1585// This function handles events that were broadcast by the process.
1586void Debugger::HandleProcessEvent(const EventSP &event_sp) {
1587 using namespace lldb;
1588 const uint32_t event_type = event_sp->GetType();
1589 ProcessSP process_sp =
1590 (event_type == Process::eBroadcastBitStructuredData)
1591 ? EventDataStructuredData::GetProcessFromEvent(event_sp.get())
1592 : Process::ProcessEventData::GetProcessFromEvent(event_sp.get());
1593
1594 StreamSP output_stream_sp = GetAsyncOutputStream();
1595 StreamSP error_stream_sp = GetAsyncErrorStream();
1596 const bool gui_enabled = IsForwardingEvents();
1597
1598 if (!gui_enabled) {
1599 bool pop_process_io_handler = false;
1600 assert(process_sp)(static_cast <bool> (process_sp) ? void (0) : __assert_fail
("process_sp", "lldb/source/Core/Debugger.cpp", 1600, __extension__
__PRETTY_FUNCTION__))
;
1601
1602 bool state_is_stopped = false;
1603 const bool got_state_changed =
1604 (event_type & Process::eBroadcastBitStateChanged) != 0;
1605 const bool got_stdout = (event_type & Process::eBroadcastBitSTDOUT) != 0;
1606 const bool got_stderr = (event_type & Process::eBroadcastBitSTDERR) != 0;
1607 const bool got_structured_data =
1608 (event_type & Process::eBroadcastBitStructuredData) != 0;
1609
1610 if (got_state_changed) {
1611 StateType event_state =
1612 Process::ProcessEventData::GetStateFromEvent(event_sp.get());
1613 state_is_stopped = StateIsStoppedState(event_state, false);
1614 }
1615
1616 // Display running state changes first before any STDIO
1617 if (got_state_changed && !state_is_stopped) {
1618 Process::HandleProcessStateChangedEvent(event_sp, output_stream_sp.get(),
1619 pop_process_io_handler);
1620 }
1621
1622 // Now display STDOUT and STDERR
1623 FlushProcessOutput(*process_sp, got_stdout || got_state_changed,
1624 got_stderr || got_state_changed);
1625
1626 // Give structured data events an opportunity to display.
1627 if (got_structured_data) {
1628 StructuredDataPluginSP plugin_sp =
1629 EventDataStructuredData::GetPluginFromEvent(event_sp.get());
1630 if (plugin_sp) {
1631 auto structured_data_sp =
1632 EventDataStructuredData::GetObjectFromEvent(event_sp.get());
1633 if (output_stream_sp) {
1634 StreamString content_stream;
1635 Status error =
1636 plugin_sp->GetDescription(structured_data_sp, content_stream);
1637 if (error.Success()) {
1638 if (!content_stream.GetString().empty()) {
1639 // Add newline.
1640 content_stream.PutChar('\n');
1641 content_stream.Flush();
1642
1643 // Print it.
1644 output_stream_sp->PutCString(content_stream.GetString());
1645 }
1646 } else {
1647 error_stream_sp->Format("Failed to print structured "
1648 "data with plugin {0}: {1}",
1649 plugin_sp->GetPluginName(), error);
1650 }
1651 }
1652 }
1653 }
1654
1655 // Now display any stopped state changes after any STDIO
1656 if (got_state_changed && state_is_stopped) {
1657 Process::HandleProcessStateChangedEvent(event_sp, output_stream_sp.get(),
1658 pop_process_io_handler);
1659 }
1660
1661 output_stream_sp->Flush();
1662 error_stream_sp->Flush();
1663
1664 if (pop_process_io_handler)
1665 process_sp->PopProcessIOHandler();
1666 }
1667}
1668
1669void Debugger::HandleThreadEvent(const EventSP &event_sp) {
1670 // At present the only thread event we handle is the Frame Changed event, and
1671 // all we do for that is just reprint the thread status for that thread.
1672 using namespace lldb;
1673 const uint32_t event_type = event_sp->GetType();
1674 const bool stop_format = true;
1675 if (event_type == Thread::eBroadcastBitStackChanged ||
1676 event_type == Thread::eBroadcastBitThreadSelected) {
1677 ThreadSP thread_sp(
1678 Thread::ThreadEventData::GetThreadFromEvent(event_sp.get()));
1679 if (thread_sp) {
1680 thread_sp->GetStatus(*GetAsyncOutputStream(), 0, 1, 1, stop_format);
1681 }
1682 }
1683}
1684
1685bool Debugger::IsForwardingEvents() { return (bool)m_forward_listener_sp; }
1686
1687void Debugger::EnableForwardEvents(const ListenerSP &listener_sp) {
1688 m_forward_listener_sp = listener_sp;
1689}
1690
1691void Debugger::CancelForwardEvents(const ListenerSP &listener_sp) {
1692 m_forward_listener_sp.reset();
1693}
1694
1695lldb::thread_result_t Debugger::DefaultEventHandler() {
1696 ListenerSP listener_sp(GetListener());
1697 ConstString broadcaster_class_target(Target::GetStaticBroadcasterClass());
1698 ConstString broadcaster_class_process(Process::GetStaticBroadcasterClass());
1699 ConstString broadcaster_class_thread(Thread::GetStaticBroadcasterClass());
1700 BroadcastEventSpec target_event_spec(broadcaster_class_target,
1701 Target::eBroadcastBitBreakpointChanged);
1702
1703 BroadcastEventSpec process_event_spec(
1704 broadcaster_class_process,
1705 Process::eBroadcastBitStateChanged | Process::eBroadcastBitSTDOUT |
1706 Process::eBroadcastBitSTDERR | Process::eBroadcastBitStructuredData);
1707
1708 BroadcastEventSpec thread_event_spec(broadcaster_class_thread,
1709 Thread::eBroadcastBitStackChanged |
1710 Thread::eBroadcastBitThreadSelected);
1711
1712 listener_sp->StartListeningForEventSpec(m_broadcaster_manager_sp,
1713 target_event_spec);
1714 listener_sp->StartListeningForEventSpec(m_broadcaster_manager_sp,
1715 process_event_spec);
1716 listener_sp->StartListeningForEventSpec(m_broadcaster_manager_sp,
1717 thread_event_spec);
1718 listener_sp->StartListeningForEvents(
1719 m_command_interpreter_up.get(),
1720 CommandInterpreter::eBroadcastBitQuitCommandReceived |
1721 CommandInterpreter::eBroadcastBitAsynchronousOutputData |
1722 CommandInterpreter::eBroadcastBitAsynchronousErrorData);
1723
1724 listener_sp->StartListeningForEvents(
1725 &m_broadcaster, eBroadcastBitProgress | eBroadcastBitWarning |
1726 eBroadcastBitError | eBroadcastSymbolChange);
1727
1728 // Let the thread that spawned us know that we have started up and that we
1729 // are now listening to all required events so no events get missed
1730 m_sync_broadcaster.BroadcastEvent(eBroadcastBitEventThreadIsListening);
1731
1732 bool done = false;
1733 while (!done) {
1734 EventSP event_sp;
1735 if (listener_sp->GetEvent(event_sp, llvm::None)) {
1736 if (event_sp) {
1737 Broadcaster *broadcaster = event_sp->GetBroadcaster();
1738 if (broadcaster) {
1739 uint32_t event_type = event_sp->GetType();
1740 ConstString broadcaster_class(broadcaster->GetBroadcasterClass());
1741 if (broadcaster_class == broadcaster_class_process) {
1742 HandleProcessEvent(event_sp);
1743 } else if (broadcaster_class == broadcaster_class_target) {
1744 if (Breakpoint::BreakpointEventData::GetEventDataFromEvent(
1745 event_sp.get())) {
1746 HandleBreakpointEvent(event_sp);
1747 }
1748 } else if (broadcaster_class == broadcaster_class_thread) {
1749 HandleThreadEvent(event_sp);
1750 } else if (broadcaster == m_command_interpreter_up.get()) {
1751 if (event_type &
1752 CommandInterpreter::eBroadcastBitQuitCommandReceived) {
1753 done = true;
1754 } else if (event_type &
1755 CommandInterpreter::eBroadcastBitAsynchronousErrorData) {
1756 const char *data = static_cast<const char *>(
1757 EventDataBytes::GetBytesFromEvent(event_sp.get()));
1758 if (data && data[0]) {
1759 StreamSP error_sp(GetAsyncErrorStream());
1760 if (error_sp) {
1761 error_sp->PutCString(data);
1762 error_sp->Flush();
1763 }
1764 }
1765 } else if (event_type & CommandInterpreter::
1766 eBroadcastBitAsynchronousOutputData) {
1767 const char *data = static_cast<const char *>(
1768 EventDataBytes::GetBytesFromEvent(event_sp.get()));
1769 if (data && data[0]) {
1770 StreamSP output_sp(GetAsyncOutputStream());
1771 if (output_sp) {
1772 output_sp->PutCString(data);
1773 output_sp->Flush();
1774 }
1775 }
1776 }
1777 } else if (broadcaster == &m_broadcaster) {
1778 if (event_type & Debugger::eBroadcastBitProgress)
1779 HandleProgressEvent(event_sp);
1780 else if (event_type & Debugger::eBroadcastBitWarning)
1781 HandleDiagnosticEvent(event_sp);
1782 else if (event_type & Debugger::eBroadcastBitError)
1783 HandleDiagnosticEvent(event_sp);
1784 }
1785 }
1786
1787 if (m_forward_listener_sp)
1788 m_forward_listener_sp->AddEvent(event_sp);
1789 }
1790 }
1791 }
1792 return {};
1793}
1794
1795bool Debugger::StartEventHandlerThread() {
1796 if (!m_event_handler_thread.IsJoinable()) {
1797 // We must synchronize with the DefaultEventHandler() thread to ensure it
1798 // is up and running and listening to events before we return from this
1799 // function. We do this by listening to events for the
1800 // eBroadcastBitEventThreadIsListening from the m_sync_broadcaster
1801 ConstString full_name("lldb.debugger.event-handler");
1802 ListenerSP listener_sp(Listener::MakeListener(full_name.AsCString()));
1803 listener_sp->StartListeningForEvents(&m_sync_broadcaster,
1804 eBroadcastBitEventThreadIsListening);
1805
1806 llvm::StringRef thread_name =
1807 full_name.GetLength() < llvm::get_max_thread_name_length()
1808 ? full_name.GetStringRef()
1809 : "dbg.evt-handler";
1810
1811 // Use larger 8MB stack for this thread
1812 llvm::Expected<HostThread> event_handler_thread =
1813 ThreadLauncher::LaunchThread(
1814 thread_name, [this] { return DefaultEventHandler(); },
1815 g_debugger_event_thread_stack_bytes);
1816
1817 if (event_handler_thread) {
1818 m_event_handler_thread = *event_handler_thread;
1819 } else {
1820 LLDB_LOG(GetLog(LLDBLog::Host), "failed to launch host thread: {}",do { ::lldb_private::Log *log_private = (GetLog(LLDBLog::Host
)); if (log_private) log_private->Format("lldb/source/Core/Debugger.cpp"
, __func__, "failed to launch host thread: {}", llvm::toString
(event_handler_thread.takeError())); } while (0)
1821 llvm::toString(event_handler_thread.takeError()))do { ::lldb_private::Log *log_private = (GetLog(LLDBLog::Host
)); if (log_private) log_private->Format("lldb/source/Core/Debugger.cpp"
, __func__, "failed to launch host thread: {}", llvm::toString
(event_handler_thread.takeError())); } while (0)
;
1822 }
1823
1824 // Make sure DefaultEventHandler() is running and listening to events
1825 // before we return from this function. We are only listening for events of
1826 // type eBroadcastBitEventThreadIsListening so we don't need to check the
1827 // event, we just need to wait an infinite amount of time for it (nullptr
1828 // timeout as the first parameter)
1829 lldb::EventSP event_sp;
1830 listener_sp->GetEvent(event_sp, llvm::None);
1831 }
1832 return m_event_handler_thread.IsJoinable();
1833}
1834
1835void Debugger::StopEventHandlerThread() {
1836 if (m_event_handler_thread.IsJoinable()) {
1837 GetCommandInterpreter().BroadcastEvent(
1838 CommandInterpreter::eBroadcastBitQuitCommandReceived);
1839 m_event_handler_thread.Join(nullptr);
1840 }
1841}
1842
1843lldb::thread_result_t Debugger::IOHandlerThread() {
1844 RunIOHandlers();
1845 StopEventHandlerThread();
1846 return {};
1847}
1848
1849void Debugger::HandleProgressEvent(const lldb::EventSP &event_sp) {
1850 auto *data = ProgressEventData::GetEventDataFromEvent(event_sp.get());
1851 if (!data)
1852 return;
1853
1854 // Do some bookkeeping for the current event, regardless of whether we're
1855 // going to show the progress.
1856 const uint64_t id = data->GetID();
1857 if (m_current_event_id) {
1858 Log *log = GetLog(LLDBLog::Events);
1859 if (log && log->GetVerbose()) {
1860 StreamString log_stream;
1861 log_stream.AsRawOstream()
1862 << static_cast<void *>(this) << " Debugger(" << GetID()
1863 << ")::HandleProgressEvent( m_current_event_id = "
1864 << *m_current_event_id << ", data = { ";
1865 data->Dump(&log_stream);
1866 log_stream << " } )";
1867 log->PutString(log_stream.GetString());
1868 }
1869 if (id != *m_current_event_id)
1870 return;
1871 if (data->GetCompleted() == data->GetTotal())
1872 m_current_event_id.reset();
1873 } else {
1874 m_current_event_id = id;
1875 }
1876
1877 // Decide whether we actually are going to show the progress. This decision
1878 // can change between iterations so check it inside the loop.
1879 if (!GetShowProgress())
1880 return;
1881
1882 // Determine whether the current output file is an interactive terminal with
1883 // color support. We assume that if we support ANSI escape codes we support
1884 // vt100 escape codes.
1885 File &file = GetOutputFile();
1886 if (!file.GetIsInteractive() || !file.GetIsTerminalWithColors())
1887 return;
1888
1889 StreamSP output = GetAsyncOutputStream();
1890
1891 // Print over previous line, if any.
1892 output->Printf("\r");
1893
1894 if (data->GetCompleted() == data->GetTotal()) {
1895 // Clear the current line.
1896 output->Printf("\x1B[2K");
1897 output->Flush();
1898 return;
1899 }
1900
1901 // Trim the progress message if it exceeds the window's width and print it.
1902 std::string message = data->GetMessage();
1903 if (data->IsFinite())
1904 message = llvm::formatv("[{0}/{1}] {2}", data->GetCompleted(),
1905 data->GetTotal(), message)
1906 .str();
1907
1908 // Trim the progress message if it exceeds the window's width and print it.
1909 const uint32_t term_width = GetTerminalWidth();
1910 const uint32_t ellipsis = 3;
1911 if (message.size() + ellipsis >= term_width)
1912 message = message.substr(0, term_width - ellipsis);
1913
1914 const bool use_color = GetUseColor();
1915 llvm::StringRef ansi_prefix = GetShowProgressAnsiPrefix();
1916 if (!ansi_prefix.empty())
1917 output->Printf(
1918 "%s", ansi::FormatAnsiTerminalCodes(ansi_prefix, use_color).c_str());
1919
1920 output->Printf("%s...", message.c_str());
1921
1922 llvm::StringRef ansi_suffix = GetShowProgressAnsiSuffix();
1923 if (!ansi_suffix.empty())
1924 output->Printf(
1925 "%s", ansi::FormatAnsiTerminalCodes(ansi_suffix, use_color).c_str());
1926
1927 // Clear until the end of the line.
1928 output->Printf("\x1B[K\r");
1929
1930 // Flush the output.
1931 output->Flush();
1932}
1933
1934void Debugger::HandleDiagnosticEvent(const lldb::EventSP &event_sp) {
1935 auto *data = DiagnosticEventData::GetEventDataFromEvent(event_sp.get());
1936 if (!data)
1937 return;
1938
1939 StreamSP stream = GetAsyncErrorStream();
1940 data->Dump(stream.get());
1941}
1942
1943bool Debugger::HasIOHandlerThread() { return m_io_handler_thread.IsJoinable(); }
1944
1945bool Debugger::StartIOHandlerThread() {
1946 if (!m_io_handler_thread.IsJoinable()) {
1947 llvm::Expected<HostThread> io_handler_thread = ThreadLauncher::LaunchThread(
1948 "lldb.debugger.io-handler", [this] { return IOHandlerThread(); },
1949 8 * 1024 * 1024); // Use larger 8MB stack for this thread
1950 if (io_handler_thread) {
1951 m_io_handler_thread = *io_handler_thread;
1952 } else {
1953 LLDB_LOG(GetLog(LLDBLog::Host), "failed to launch host thread: {}",do { ::lldb_private::Log *log_private = (GetLog(LLDBLog::Host
)); if (log_private) log_private->Format("lldb/source/Core/Debugger.cpp"
, __func__, "failed to launch host thread: {}", llvm::toString
(io_handler_thread.takeError())); } while (0)
1954 llvm::toString(io_handler_thread.takeError()))do { ::lldb_private::Log *log_private = (GetLog(LLDBLog::Host
)); if (log_private) log_private->Format("lldb/source/Core/Debugger.cpp"
, __func__, "failed to launch host thread: {}", llvm::toString
(io_handler_thread.takeError())); } while (0)
;
1955 }
1956 }
1957 return m_io_handler_thread.IsJoinable();
1958}
1959
1960void Debugger::StopIOHandlerThread() {
1961 if (m_io_handler_thread.IsJoinable()) {
1962 GetInputFile().Close();
1963 m_io_handler_thread.Join(nullptr);
1964 }
1965}
1966
1967void Debugger::JoinIOHandlerThread() {
1968 if (HasIOHandlerThread()) {
1969 thread_result_t result;
1970 m_io_handler_thread.Join(&result);
1971 m_io_handler_thread = LLDB_INVALID_HOST_THREAD((lldb::thread_t)__null);
1972 }
1973}
1974
1975Target &Debugger::GetSelectedOrDummyTarget(bool prefer_dummy) {
1976 if (!prefer_dummy) {
1977 if (TargetSP target = m_target_list.GetSelectedTarget())
1978 return *target;
1979 }
1980 return GetDummyTarget();
1981}
1982
1983Status Debugger::RunREPL(LanguageType language, const char *repl_options) {
1984 Status err;
1985 FileSpec repl_executable;
1986
1987 if (language == eLanguageTypeUnknown)
1988 language = GetREPLLanguage();
1989
1990 if (language == eLanguageTypeUnknown) {
1991 LanguageSet repl_languages = Language::GetLanguagesSupportingREPLs();
1992
1993 if (auto single_lang = repl_languages.GetSingularLanguage()) {
1994 language = *single_lang;
1995 } else if (repl_languages.Empty()) {
1996 err.SetErrorString(
1997 "LLDB isn't configured with REPL support for any languages.");
1998 return err;
1999 } else {
2000 err.SetErrorString(
2001 "Multiple possible REPL languages. Please specify a language.");
2002 return err;
2003 }
2004 }
2005
2006 Target *const target =
2007 nullptr; // passing in an empty target means the REPL must create one
2008
2009 REPLSP repl_sp(REPL::Create(err, language, this, target, repl_options));
2010
2011 if (!err.Success()) {
2012 return err;
2013 }
2014
2015 if (!repl_sp) {
2016 err.SetErrorStringWithFormat("couldn't find a REPL for %s",
2017 Language::GetNameForLanguageType(language));
2018 return err;
2019 }
2020
2021 repl_sp->SetCompilerOptions(repl_options);
2022 repl_sp->RunLoop();
2023
2024 return err;
2025}
2026
2027llvm::ThreadPool &Debugger::GetThreadPool() {
2028 assert(g_thread_pool &&(static_cast <bool> (g_thread_pool && "Debugger::GetThreadPool called before Debugger::Initialize"
) ? void (0) : __assert_fail ("g_thread_pool && \"Debugger::GetThreadPool called before Debugger::Initialize\""
, "lldb/source/Core/Debugger.cpp", 2029, __extension__ __PRETTY_FUNCTION__
))
2029 "Debugger::GetThreadPool called before Debugger::Initialize")(static_cast <bool> (g_thread_pool && "Debugger::GetThreadPool called before Debugger::Initialize"
) ? void (0) : __assert_fail ("g_thread_pool && \"Debugger::GetThreadPool called before Debugger::Initialize\""
, "lldb/source/Core/Debugger.cpp", 2029, __extension__ __PRETTY_FUNCTION__
))
;
2030 return *g_thread_pool;
2031}

/usr/lib/gcc/x86_64-linux-gnu/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)...)
19
Calling constructor for '__shared_ptr<lldb_private::NativeFile, __gnu_cxx::_S_atomic>'
31
Returning from constructor for '__shared_ptr<lldb_private::NativeFile, __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},
18
Calling constructor for 'shared_ptr<lldb_private::NativeFile>'
32
Returning from constructor for 'shared_ptr<lldb_private::NativeFile>'
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>(),
17
Calling 'allocate_shared<lldb_private::NativeFile, std::allocator<lldb_private::NativeFile>, _IO_FILE *&, bool>'
33
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/lib/gcc/x86_64-linux-gnu/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())(__builtin_abort()); }
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 __tryif (true)
627 {
628 _M_pi = new _Sp_counted_ptr<_Ptr, _Lp>(__p);
629 }
630 __catch(...)if (false)
631 {
632 delete __p;
633 __throw_exception_again;
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 __tryif (true)
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(...)if (false)
668 {
669 __d(__p); // Call _Deleter on __p.
670 __throw_exception_again;
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);
21
Calling '__allocate_guarded<std::allocator<std::_Sp_counted_ptr_inplace<lldb_private::NativeFile, std::allocator<lldb_private::NativeFile>, __gnu_cxx::_S_atomic>>>'
29
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)...)
20
Calling constructor for '__shared_count<__gnu_cxx::_S_atomic>'
30
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/lib/gcc/x86_64-linux-gnu/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) };
22
Calling 'allocator_traits::allocate'
28
Returned allocated memory
98 }
99
100_GLIBCXX_END_NAMESPACE_VERSION
101} // namespace std
102
103#endif
104#endif

/usr/lib/gcc/x86_64-linux-gnu/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); }
23
Calling 'new_allocator::allocate'
27
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/lib/gcc/x86_64-linux-gnu/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())
24
Taking false branch
106 std::__throw_bad_alloc();
107
108#if __cpp_aligned_new201606L
109 if (alignof(_Tp) > __STDCPP_DEFAULT_NEW_ALIGNMENT__16UL)
25
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)));
26
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