Bug Summary

File:build/llvm-toolchain-snapshot-16~++20221003111214+1fa2019828ca/llvm/lib/ExecutionEngine/Orc/DebugObjectManagerPlugin.cpp
Warning:line 177, column 9
Potential memory leak

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 DebugObjectManagerPlugin.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~++20221003111214+1fa2019828ca/build-llvm/tools/clang/stage2-bins -resource-dir /usr/lib/llvm-16/lib/clang/16.0.0 -D _DEBUG -D _GNU_SOURCE -D __STDC_CONSTANT_MACROS -D __STDC_FORMAT_MACROS -D __STDC_LIMIT_MACROS -I lib/ExecutionEngine/Orc -I /build/llvm-toolchain-snapshot-16~++20221003111214+1fa2019828ca/llvm/lib/ExecutionEngine/Orc -I include -I /build/llvm-toolchain-snapshot-16~++20221003111214+1fa2019828ca/llvm/include -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~++20221003111214+1fa2019828ca/build-llvm/tools/clang/stage2-bins=build-llvm/tools/clang/stage2-bins -fmacro-prefix-map=/build/llvm-toolchain-snapshot-16~++20221003111214+1fa2019828ca/= -fcoverage-prefix-map=/build/llvm-toolchain-snapshot-16~++20221003111214+1fa2019828ca/build-llvm/tools/clang/stage2-bins=build-llvm/tools/clang/stage2-bins -fcoverage-prefix-map=/build/llvm-toolchain-snapshot-16~++20221003111214+1fa2019828ca/= -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 -std=c++17 -fdeprecated-macro -fdebug-compilation-dir=/build/llvm-toolchain-snapshot-16~++20221003111214+1fa2019828ca/build-llvm/tools/clang/stage2-bins -fdebug-prefix-map=/build/llvm-toolchain-snapshot-16~++20221003111214+1fa2019828ca/build-llvm/tools/clang/stage2-bins=build-llvm/tools/clang/stage2-bins -fdebug-prefix-map=/build/llvm-toolchain-snapshot-16~++20221003111214+1fa2019828ca/= -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-10-03-140002-15933-1 -x c++ /build/llvm-toolchain-snapshot-16~++20221003111214+1fa2019828ca/llvm/lib/ExecutionEngine/Orc/DebugObjectManagerPlugin.cpp

/build/llvm-toolchain-snapshot-16~++20221003111214+1fa2019828ca/llvm/lib/ExecutionEngine/Orc/DebugObjectManagerPlugin.cpp

1//===------- DebugObjectManagerPlugin.cpp - JITLink debug objects ---------===//
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// FIXME: Update Plugin to poke the debug object into a new JITLink section,
10// rather than creating a new allocation.
11//
12//===----------------------------------------------------------------------===//
13
14#include "llvm/ExecutionEngine/Orc/DebugObjectManagerPlugin.h"
15
16#include "llvm/ADT/ArrayRef.h"
17#include "llvm/ADT/StringMap.h"
18#include "llvm/ADT/StringRef.h"
19#include "llvm/BinaryFormat/ELF.h"
20#include "llvm/ExecutionEngine/JITLink/JITLinkDylib.h"
21#include "llvm/ExecutionEngine/JITLink/JITLinkMemoryManager.h"
22#include "llvm/ExecutionEngine/JITSymbol.h"
23#include "llvm/Object/ELFObjectFile.h"
24#include "llvm/Object/ObjectFile.h"
25#include "llvm/Support/Errc.h"
26#include "llvm/Support/MSVCErrorWorkarounds.h"
27#include "llvm/Support/MemoryBuffer.h"
28#include "llvm/Support/Process.h"
29#include "llvm/Support/raw_ostream.h"
30
31#include <set>
32
33#define DEBUG_TYPE"orc" "orc"
34
35using namespace llvm::jitlink;
36using namespace llvm::object;
37
38namespace llvm {
39namespace orc {
40
41class DebugObjectSection {
42public:
43 virtual void setTargetMemoryRange(SectionRange Range) = 0;
44 virtual void dump(raw_ostream &OS, StringRef Name) {}
45 virtual ~DebugObjectSection() = default;
46};
47
48template <typename ELFT>
49class ELFDebugObjectSection : public DebugObjectSection {
50public:
51 // BinaryFormat ELF is not meant as a mutable format. We can only make changes
52 // that don't invalidate the file structure.
53 ELFDebugObjectSection(const typename ELFT::Shdr *Header)
54 : Header(const_cast<typename ELFT::Shdr *>(Header)) {}
55
56 void setTargetMemoryRange(SectionRange Range) override;
57 void dump(raw_ostream &OS, StringRef Name) override;
58
59 Error validateInBounds(StringRef Buffer, const char *Name) const;
60
61private:
62 typename ELFT::Shdr *Header;
63
64 bool isTextOrDataSection() const;
65};
66
67template <typename ELFT>
68void ELFDebugObjectSection<ELFT>::setTargetMemoryRange(SectionRange Range) {
69 // Only patch load-addresses for executable and data sections.
70 if (isTextOrDataSection())
71 Header->sh_addr =
72 static_cast<typename ELFT::uint>(Range.getStart().getValue());
73}
74
75template <typename ELFT>
76bool ELFDebugObjectSection<ELFT>::isTextOrDataSection() const {
77 switch (Header->sh_type) {
78 case ELF::SHT_PROGBITS:
79 case ELF::SHT_X86_64_UNWIND:
80 return Header->sh_flags & (ELF::SHF_EXECINSTR | ELF::SHF_ALLOC);
81 }
82 return false;
83}
84
85template <typename ELFT>
86Error ELFDebugObjectSection<ELFT>::validateInBounds(StringRef Buffer,
87 const char *Name) const {
88 const uint8_t *Start = Buffer.bytes_begin();
89 const uint8_t *End = Buffer.bytes_end();
90 const uint8_t *HeaderPtr = reinterpret_cast<uint8_t *>(Header);
91 if (HeaderPtr < Start || HeaderPtr + sizeof(typename ELFT::Shdr) > End)
92 return make_error<StringError>(
93 formatv("{0} section header at {1:x16} not within bounds of the "
94 "given debug object buffer [{2:x16} - {3:x16}]",
95 Name, &Header->sh_addr, Start, End),
96 inconvertibleErrorCode());
97 if (Header->sh_offset + Header->sh_size > Buffer.size())
98 return make_error<StringError>(
99 formatv("{0} section data [{1:x16} - {2:x16}] not within bounds of "
100 "the given debug object buffer [{3:x16} - {4:x16}]",
101 Name, Start + Header->sh_offset,
102 Start + Header->sh_offset + Header->sh_size, Start, End),
103 inconvertibleErrorCode());
104 return Error::success();
105}
106
107template <typename ELFT>
108void ELFDebugObjectSection<ELFT>::dump(raw_ostream &OS, StringRef Name) {
109 if (auto Addr = static_cast<JITTargetAddress>(Header->sh_addr)) {
110 OS << formatv(" {0:x16} {1}\n", Addr, Name);
111 } else {
112 OS << formatv(" {0}\n", Name);
113 }
114}
115
116enum class Requirement {
117 // Request final target memory load-addresses for all sections.
118 ReportFinalSectionLoadAddresses,
119};
120
121/// The plugin creates a debug object from when JITLink starts processing the
122/// corresponding LinkGraph. It provides access to the pass configuration of
123/// the LinkGraph and calls the finalization function, once the resulting link
124/// artifact was emitted.
125///
126class DebugObject {
127public:
128 DebugObject(JITLinkMemoryManager &MemMgr, const JITLinkDylib *JD,
129 ExecutionSession &ES)
130 : MemMgr(MemMgr), JD(JD), ES(ES) {}
131
132 void set(Requirement Req) { Reqs.insert(Req); }
133 bool has(Requirement Req) const { return Reqs.count(Req) > 0; }
134
135 using FinalizeContinuation = std::function<void(Expected<ExecutorAddrRange>)>;
136
137 void finalizeAsync(FinalizeContinuation OnFinalize);
138
139 virtual ~DebugObject() {
140 if (Alloc) {
141 std::vector<FinalizedAlloc> Allocs;
142 Allocs.push_back(std::move(Alloc));
143 if (Error Err = MemMgr.deallocate(std::move(Allocs)))
144 ES.reportError(std::move(Err));
145 }
146 }
147
148 virtual void reportSectionTargetMemoryRange(StringRef Name,
149 SectionRange TargetMem) {}
150
151protected:
152 using InFlightAlloc = JITLinkMemoryManager::InFlightAlloc;
153 using FinalizedAlloc = JITLinkMemoryManager::FinalizedAlloc;
154
155 virtual Expected<SimpleSegmentAlloc> finalizeWorkingMemory() = 0;
156
157 JITLinkMemoryManager &MemMgr;
158 const JITLinkDylib *JD = nullptr;
159
160private:
161 ExecutionSession &ES;
162 std::set<Requirement> Reqs;
163 FinalizedAlloc Alloc;
164};
165
166// Finalize working memory and take ownership of the resulting allocation. Start
167// copying memory over to the target and pass on the result once we're done.
168// Ownership of the allocation remains with us for the rest of our lifetime.
169void DebugObject::finalizeAsync(FinalizeContinuation OnFinalize) {
170 assert(!Alloc && "Cannot finalize more than once")(static_cast <bool> (!Alloc && "Cannot finalize more than once"
) ? void (0) : __assert_fail ("!Alloc && \"Cannot finalize more than once\""
, "llvm/lib/ExecutionEngine/Orc/DebugObjectManagerPlugin.cpp"
, 170, __extension__ __PRETTY_FUNCTION__))
;
11
'?' condition is true
171
172 if (auto SimpleSegAlloc = finalizeWorkingMemory()) {
12
Taking true branch
173 auto ROSeg = SimpleSegAlloc->getSegInfo(MemProt::Read);
174 ExecutorAddrRange DebugObjRange(ExecutorAddr(ROSeg.Addr),
175 ExecutorAddrDiff(ROSeg.WorkingMem.size()));
176 SimpleSegAlloc->finalize(
177 [this, DebugObjRange,
13
Potential memory leak
178 OnFinalize = std::move(OnFinalize)](Expected<FinalizedAlloc> FA) {
179 if (FA) {
180 Alloc = std::move(*FA);
181 OnFinalize(DebugObjRange);
182 } else
183 OnFinalize(FA.takeError());
184 });
185 } else
186 OnFinalize(SimpleSegAlloc.takeError());
187}
188
189/// The current implementation of ELFDebugObject replicates the approach used in
190/// RuntimeDyld: It patches executable and data section headers in the given
191/// object buffer with load-addresses of their corresponding sections in target
192/// memory.
193///
194class ELFDebugObject : public DebugObject {
195public:
196 static Expected<std::unique_ptr<DebugObject>>
197 Create(MemoryBufferRef Buffer, JITLinkContext &Ctx, ExecutionSession &ES);
198
199 void reportSectionTargetMemoryRange(StringRef Name,
200 SectionRange TargetMem) override;
201
202 StringRef getBuffer() const { return Buffer->getMemBufferRef().getBuffer(); }
203
204protected:
205 Expected<SimpleSegmentAlloc> finalizeWorkingMemory() override;
206
207 template <typename ELFT>
208 Error recordSection(StringRef Name,
209 std::unique_ptr<ELFDebugObjectSection<ELFT>> Section);
210 DebugObjectSection *getSection(StringRef Name);
211
212private:
213 template <typename ELFT>
214 static Expected<std::unique_ptr<ELFDebugObject>>
215 CreateArchType(MemoryBufferRef Buffer, JITLinkMemoryManager &MemMgr,
216 const JITLinkDylib *JD, ExecutionSession &ES);
217
218 static std::unique_ptr<WritableMemoryBuffer>
219 CopyBuffer(MemoryBufferRef Buffer, Error &Err);
220
221 ELFDebugObject(std::unique_ptr<WritableMemoryBuffer> Buffer,
222 JITLinkMemoryManager &MemMgr, const JITLinkDylib *JD,
223 ExecutionSession &ES)
224 : DebugObject(MemMgr, JD, ES), Buffer(std::move(Buffer)) {
225 set(Requirement::ReportFinalSectionLoadAddresses);
226 }
227
228 std::unique_ptr<WritableMemoryBuffer> Buffer;
229 StringMap<std::unique_ptr<DebugObjectSection>> Sections;
230};
231
232static const std::set<StringRef> DwarfSectionNames = {
233#define HANDLE_DWARF_SECTION(ENUM_NAME, ELF_NAME, CMDLINE_NAME, OPTION) \
234 ELF_NAME,
235#include "llvm/BinaryFormat/Dwarf.def"
236#undef HANDLE_DWARF_SECTION
237};
238
239static bool isDwarfSection(StringRef SectionName) {
240 return DwarfSectionNames.count(SectionName) == 1;
241}
242
243std::unique_ptr<WritableMemoryBuffer>
244ELFDebugObject::CopyBuffer(MemoryBufferRef Buffer, Error &Err) {
245 ErrorAsOutParameter _(&Err);
246 size_t Size = Buffer.getBufferSize();
247 StringRef Name = Buffer.getBufferIdentifier();
248 if (auto Copy = WritableMemoryBuffer::getNewUninitMemBuffer(Size, Name)) {
249 memcpy(Copy->getBufferStart(), Buffer.getBufferStart(), Size);
250 return Copy;
251 }
252
253 Err = errorCodeToError(make_error_code(errc::not_enough_memory));
254 return nullptr;
255}
256
257template <typename ELFT>
258Expected<std::unique_ptr<ELFDebugObject>>
259ELFDebugObject::CreateArchType(MemoryBufferRef Buffer,
260 JITLinkMemoryManager &MemMgr,
261 const JITLinkDylib *JD, ExecutionSession &ES) {
262 using SectionHeader = typename ELFT::Shdr;
263
264 Error Err = Error::success();
265 std::unique_ptr<ELFDebugObject> DebugObj(
266 new ELFDebugObject(CopyBuffer(Buffer, Err), MemMgr, JD, ES));
267 if (Err)
268 return std::move(Err);
269
270 Expected<ELFFile<ELFT>> ObjRef = ELFFile<ELFT>::create(DebugObj->getBuffer());
271 if (!ObjRef)
272 return ObjRef.takeError();
273
274 // TODO: Add support for other architectures.
275 uint16_t TargetMachineArch = ObjRef->getHeader().e_machine;
276 if (TargetMachineArch != ELF::EM_X86_64)
277 return nullptr;
278
279 Expected<ArrayRef<SectionHeader>> Sections = ObjRef->sections();
280 if (!Sections)
281 return Sections.takeError();
282
283 bool HasDwarfSection = false;
284 for (const SectionHeader &Header : *Sections) {
285 Expected<StringRef> Name = ObjRef->getSectionName(Header);
286 if (!Name)
287 return Name.takeError();
288 if (Name->empty())
289 continue;
290 HasDwarfSection |= isDwarfSection(*Name);
291
292 auto Wrapped = std::make_unique<ELFDebugObjectSection<ELFT>>(&Header);
293 if (Error Err = DebugObj->recordSection(*Name, std::move(Wrapped)))
294 return std::move(Err);
295 }
296
297 if (!HasDwarfSection) {
298 LLVM_DEBUG(dbgs() << "Aborting debug registration for LinkGraph \""do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("orc")) { dbgs() << "Aborting debug registration for LinkGraph \""
<< DebugObj->Buffer->getBufferIdentifier() <<
"\": input object contains no debug info\n"; } } while (false
)
299 << DebugObj->Buffer->getBufferIdentifier()do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("orc")) { dbgs() << "Aborting debug registration for LinkGraph \""
<< DebugObj->Buffer->getBufferIdentifier() <<
"\": input object contains no debug info\n"; } } while (false
)
300 << "\": input object contains no debug info\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("orc")) { dbgs() << "Aborting debug registration for LinkGraph \""
<< DebugObj->Buffer->getBufferIdentifier() <<
"\": input object contains no debug info\n"; } } while (false
)
;
301 return nullptr;
302 }
303
304 return std::move(DebugObj);
305}
306
307Expected<std::unique_ptr<DebugObject>>
308ELFDebugObject::Create(MemoryBufferRef Buffer, JITLinkContext &Ctx,
309 ExecutionSession &ES) {
310 unsigned char Class, Endian;
311 std::tie(Class, Endian) = getElfArchType(Buffer.getBuffer());
312
313 if (Class == ELF::ELFCLASS32) {
314 if (Endian == ELF::ELFDATA2LSB)
315 return CreateArchType<ELF32LE>(Buffer, Ctx.getMemoryManager(),
316 Ctx.getJITLinkDylib(), ES);
317 if (Endian == ELF::ELFDATA2MSB)
318 return CreateArchType<ELF32BE>(Buffer, Ctx.getMemoryManager(),
319 Ctx.getJITLinkDylib(), ES);
320 return nullptr;
321 }
322 if (Class == ELF::ELFCLASS64) {
323 if (Endian == ELF::ELFDATA2LSB)
324 return CreateArchType<ELF64LE>(Buffer, Ctx.getMemoryManager(),
325 Ctx.getJITLinkDylib(), ES);
326 if (Endian == ELF::ELFDATA2MSB)
327 return CreateArchType<ELF64BE>(Buffer, Ctx.getMemoryManager(),
328 Ctx.getJITLinkDylib(), ES);
329 return nullptr;
330 }
331 return nullptr;
332}
333
334Expected<SimpleSegmentAlloc> ELFDebugObject::finalizeWorkingMemory() {
335 LLVM_DEBUG({do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("orc")) { { dbgs() << "Section load-addresses in debug object for \""
<< Buffer->getBufferIdentifier() << "\":\n"; for
(const auto &KV : Sections) KV.second->dump(dbgs(), KV
.first()); }; } } while (false)
336 dbgs() << "Section load-addresses in debug object for \""do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("orc")) { { dbgs() << "Section load-addresses in debug object for \""
<< Buffer->getBufferIdentifier() << "\":\n"; for
(const auto &KV : Sections) KV.second->dump(dbgs(), KV
.first()); }; } } while (false)
337 << Buffer->getBufferIdentifier() << "\":\n";do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("orc")) { { dbgs() << "Section load-addresses in debug object for \""
<< Buffer->getBufferIdentifier() << "\":\n"; for
(const auto &KV : Sections) KV.second->dump(dbgs(), KV
.first()); }; } } while (false)
338 for (const auto &KV : Sections)do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("orc")) { { dbgs() << "Section load-addresses in debug object for \""
<< Buffer->getBufferIdentifier() << "\":\n"; for
(const auto &KV : Sections) KV.second->dump(dbgs(), KV
.first()); }; } } while (false)
339 KV.second->dump(dbgs(), KV.first());do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("orc")) { { dbgs() << "Section load-addresses in debug object for \""
<< Buffer->getBufferIdentifier() << "\":\n"; for
(const auto &KV : Sections) KV.second->dump(dbgs(), KV
.first()); }; } } while (false)
340 })do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("orc")) { { dbgs() << "Section load-addresses in debug object for \""
<< Buffer->getBufferIdentifier() << "\":\n"; for
(const auto &KV : Sections) KV.second->dump(dbgs(), KV
.first()); }; } } while (false)
;
341
342 // TODO: This works, but what actual alignment requirements do we have?
343 unsigned PageSize = sys::Process::getPageSizeEstimate();
344 size_t Size = Buffer->getBufferSize();
345
346 // Allocate working memory for debug object in read-only segment.
347 auto Alloc = SimpleSegmentAlloc::Create(
348 MemMgr, JD, {{MemProt::Read, {Size, Align(PageSize)}}});
349 if (!Alloc)
350 return Alloc;
351
352 // Initialize working memory with a copy of our object buffer.
353 auto SegInfo = Alloc->getSegInfo(MemProt::Read);
354 memcpy(SegInfo.WorkingMem.data(), Buffer->getBufferStart(), Size);
355 Buffer.reset();
356
357 return Alloc;
358}
359
360void ELFDebugObject::reportSectionTargetMemoryRange(StringRef Name,
361 SectionRange TargetMem) {
362 if (auto *DebugObjSection = getSection(Name))
363 DebugObjSection->setTargetMemoryRange(TargetMem);
364}
365
366template <typename ELFT>
367Error ELFDebugObject::recordSection(
368 StringRef Name, std::unique_ptr<ELFDebugObjectSection<ELFT>> Section) {
369 if (Error Err = Section->validateInBounds(this->getBuffer(), Name.data()))
370 return Err;
371 auto ItInserted = Sections.try_emplace(Name, std::move(Section));
372 if (!ItInserted.second)
373 return make_error<StringError>("Duplicate section",
374 inconvertibleErrorCode());
375 return Error::success();
376}
377
378DebugObjectSection *ELFDebugObject::getSection(StringRef Name) {
379 auto It = Sections.find(Name);
380 return It == Sections.end() ? nullptr : It->second.get();
381}
382
383/// Creates a debug object based on the input object file from
384/// ObjectLinkingLayerJITLinkContext.
385///
386static Expected<std::unique_ptr<DebugObject>>
387createDebugObjectFromBuffer(ExecutionSession &ES, LinkGraph &G,
388 JITLinkContext &Ctx, MemoryBufferRef ObjBuffer) {
389 switch (G.getTargetTriple().getObjectFormat()) {
390 case Triple::ELF:
391 return ELFDebugObject::Create(ObjBuffer, Ctx, ES);
392
393 default:
394 // TODO: Once we add support for other formats, we might want to split this
395 // into multiple files.
396 return nullptr;
397 }
398}
399
400DebugObjectManagerPlugin::DebugObjectManagerPlugin(
401 ExecutionSession &ES, std::unique_ptr<DebugObjectRegistrar> Target)
402 : ES(ES), Target(std::move(Target)) {}
403
404DebugObjectManagerPlugin::~DebugObjectManagerPlugin() = default;
405
406void DebugObjectManagerPlugin::notifyMaterializing(
407 MaterializationResponsibility &MR, LinkGraph &G, JITLinkContext &Ctx,
408 MemoryBufferRef ObjBuffer) {
409 std::lock_guard<std::mutex> Lock(PendingObjsLock);
410 assert(PendingObjs.count(&MR) == 0 &&(static_cast <bool> (PendingObjs.count(&MR) == 0 &&
"Cannot have more than one pending debug object per " "MaterializationResponsibility"
) ? void (0) : __assert_fail ("PendingObjs.count(&MR) == 0 && \"Cannot have more than one pending debug object per \" \"MaterializationResponsibility\""
, "llvm/lib/ExecutionEngine/Orc/DebugObjectManagerPlugin.cpp"
, 412, __extension__ __PRETTY_FUNCTION__))
411 "Cannot have more than one pending debug object per "(static_cast <bool> (PendingObjs.count(&MR) == 0 &&
"Cannot have more than one pending debug object per " "MaterializationResponsibility"
) ? void (0) : __assert_fail ("PendingObjs.count(&MR) == 0 && \"Cannot have more than one pending debug object per \" \"MaterializationResponsibility\""
, "llvm/lib/ExecutionEngine/Orc/DebugObjectManagerPlugin.cpp"
, 412, __extension__ __PRETTY_FUNCTION__))
412 "MaterializationResponsibility")(static_cast <bool> (PendingObjs.count(&MR) == 0 &&
"Cannot have more than one pending debug object per " "MaterializationResponsibility"
) ? void (0) : __assert_fail ("PendingObjs.count(&MR) == 0 && \"Cannot have more than one pending debug object per \" \"MaterializationResponsibility\""
, "llvm/lib/ExecutionEngine/Orc/DebugObjectManagerPlugin.cpp"
, 412, __extension__ __PRETTY_FUNCTION__))
;
413
414 if (auto DebugObj = createDebugObjectFromBuffer(ES, G, Ctx, ObjBuffer)) {
415 // Not all link artifacts allow debugging.
416 if (*DebugObj != nullptr)
417 PendingObjs[&MR] = std::move(*DebugObj);
418 } else {
419 ES.reportError(DebugObj.takeError());
420 }
421}
422
423void DebugObjectManagerPlugin::modifyPassConfig(
424 MaterializationResponsibility &MR, LinkGraph &G,
425 PassConfiguration &PassConfig) {
426 // Not all link artifacts have associated debug objects.
427 std::lock_guard<std::mutex> Lock(PendingObjsLock);
428 auto It = PendingObjs.find(&MR);
429 if (It == PendingObjs.end())
430 return;
431
432 DebugObject &DebugObj = *It->second;
433 if (DebugObj.has(Requirement::ReportFinalSectionLoadAddresses)) {
434 PassConfig.PostAllocationPasses.push_back(
435 [&DebugObj](LinkGraph &Graph) -> Error {
436 for (const Section &GraphSection : Graph.sections())
437 DebugObj.reportSectionTargetMemoryRange(GraphSection.getName(),
438 SectionRange(GraphSection));
439 return Error::success();
440 });
441 }
442}
443
444Error DebugObjectManagerPlugin::notifyEmitted(
445 MaterializationResponsibility &MR) {
446 std::lock_guard<std::mutex> Lock(PendingObjsLock);
447 auto It = PendingObjs.find(&MR);
448 if (It == PendingObjs.end())
1
Taking false branch
449 return Error::success();
450
451 // During finalization the debug object is registered with the target.
452 // Materialization must wait for this process to finish. Otherwise we might
453 // start running code before the debugger processed the corresponding debug
454 // info.
455 std::promise<MSVCPError> FinalizePromise;
456 std::future<MSVCPError> FinalizeErr = FinalizePromise.get_future();
457
458 It->second->finalizeAsync(
10
Calling 'DebugObject::finalizeAsync'
459 [this, &FinalizePromise, &MR](Expected<ExecutorAddrRange> TargetMem) {
2
Calling constructor for 'function<void (llvm::Expected<llvm::orc::ExecutorAddrRange>)>'
9
Returning from constructor for 'function<void (llvm::Expected<llvm::orc::ExecutorAddrRange>)>'
460 // Any failure here will fail materialization.
461 if (!TargetMem) {
462 FinalizePromise.set_value(TargetMem.takeError());
463 return;
464 }
465 if (Error Err = Target->registerDebugObject(*TargetMem)) {
466 FinalizePromise.set_value(std::move(Err));
467 return;
468 }
469
470 // Once our tracking info is updated, notifyEmitted() can return and
471 // finish materialization.
472 FinalizePromise.set_value(MR.withResourceKeyDo([&](ResourceKey K) {
473 assert(PendingObjs.count(&MR) && "We still hold PendingObjsLock")(static_cast <bool> (PendingObjs.count(&MR) &&
"We still hold PendingObjsLock") ? void (0) : __assert_fail (
"PendingObjs.count(&MR) && \"We still hold PendingObjsLock\""
, "llvm/lib/ExecutionEngine/Orc/DebugObjectManagerPlugin.cpp"
, 473, __extension__ __PRETTY_FUNCTION__))
;
474 std::lock_guard<std::mutex> Lock(RegisteredObjsLock);
475 RegisteredObjs[K].push_back(std::move(PendingObjs[&MR]));
476 PendingObjs.erase(&MR);
477 }));
478 });
479
480 return FinalizeErr.get();
481}
482
483Error DebugObjectManagerPlugin::notifyFailed(
484 MaterializationResponsibility &MR) {
485 std::lock_guard<std::mutex> Lock(PendingObjsLock);
486 PendingObjs.erase(&MR);
487 return Error::success();
488}
489
490void DebugObjectManagerPlugin::notifyTransferringResources(ResourceKey DstKey,
491 ResourceKey SrcKey) {
492 // Debug objects are stored by ResourceKey only after registration.
493 // Thus, pending objects don't need to be updated here.
494 std::lock_guard<std::mutex> Lock(RegisteredObjsLock);
495 auto SrcIt = RegisteredObjs.find(SrcKey);
496 if (SrcIt != RegisteredObjs.end()) {
497 // Resources from distinct MaterializationResponsibilitys can get merged
498 // after emission, so we can have multiple debug objects per resource key.
499 for (std::unique_ptr<DebugObject> &DebugObj : SrcIt->second)
500 RegisteredObjs[DstKey].push_back(std::move(DebugObj));
501 RegisteredObjs.erase(SrcIt);
502 }
503}
504
505Error DebugObjectManagerPlugin::notifyRemovingResources(ResourceKey Key) {
506 // Removing the resource for a pending object fails materialization, so they
507 // get cleaned up in the notifyFailed() handler.
508 std::lock_guard<std::mutex> Lock(RegisteredObjsLock);
509 RegisteredObjs.erase(Key);
510
511 // TODO: Implement unregister notifications.
512 return Error::success();
513}
514
515} // namespace orc
516} // namespace llvm

/usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/std_function.h

1// Implementation of std::function -*- C++ -*-
2
3// Copyright (C) 2004-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 include/bits/std_function.h
26 * This is an internal header file, included by other library headers.
27 * Do not attempt to use it directly. @headername{functional}
28 */
29
30#ifndef _GLIBCXX_STD_FUNCTION_H1
31#define _GLIBCXX_STD_FUNCTION_H1 1
32
33#pragma GCC system_header
34
35#if __cplusplus201703L < 201103L
36# include <bits/c++0x_warning.h>
37#else
38
39#if __cpp_rtti199711L
40# include <typeinfo>
41#endif
42#include <bits/stl_function.h>
43#include <bits/invoke.h>
44#include <bits/refwrap.h>
45#include <bits/functexcept.h>
46
47namespace std _GLIBCXX_VISIBILITY(default)__attribute__ ((__visibility__ ("default")))
48{
49_GLIBCXX_BEGIN_NAMESPACE_VERSION
50
51 /**
52 * @brief Exception class thrown when class template function's
53 * operator() is called with an empty target.
54 * @ingroup exceptions
55 */
56 class bad_function_call : public std::exception
57 {
58 public:
59 virtual ~bad_function_call() noexcept;
60
61 const char* what() const noexcept;
62 };
63
64 /**
65 * Trait identifying "location-invariant" types, meaning that the
66 * address of the object (or any of its members) will not escape.
67 * Trivially copyable types are location-invariant and users can
68 * specialize this trait for other types.
69 */
70 template<typename _Tp>
71 struct __is_location_invariant
72 : is_trivially_copyable<_Tp>::type
73 { };
74
75 class _Undefined_class;
76
77 union _Nocopy_types
78 {
79 void* _M_object;
80 const void* _M_const_object;
81 void (*_M_function_pointer)();
82 void (_Undefined_class::*_M_member_pointer)();
83 };
84
85 union [[gnu::may_alias]] _Any_data
86 {
87 void* _M_access() { return &_M_pod_data[0]; }
88 const void* _M_access() const { return &_M_pod_data[0]; }
89
90 template<typename _Tp>
91 _Tp&
92 _M_access()
93 { return *static_cast<_Tp*>(_M_access()); }
94
95 template<typename _Tp>
96 const _Tp&
97 _M_access() const
98 { return *static_cast<const _Tp*>(_M_access()); }
99
100 _Nocopy_types _M_unused;
101 char _M_pod_data[sizeof(_Nocopy_types)];
102 };
103
104 enum _Manager_operation
105 {
106 __get_type_info,
107 __get_functor_ptr,
108 __clone_functor,
109 __destroy_functor
110 };
111
112 template<typename _Signature>
113 class function;
114
115 /// Base class of all polymorphic function object wrappers.
116 class _Function_base
117 {
118 public:
119 static const size_t _M_max_size = sizeof(_Nocopy_types);
120 static const size_t _M_max_align = __alignof__(_Nocopy_types);
121
122 template<typename _Functor>
123 class _Base_manager
124 {
125 protected:
126 static const bool __stored_locally =
127 (__is_location_invariant<_Functor>::value
128 && sizeof(_Functor) <= _M_max_size
129 && __alignof__(_Functor) <= _M_max_align
130 && (_M_max_align % __alignof__(_Functor) == 0));
131
132 typedef integral_constant<bool, __stored_locally> _Local_storage;
133
134 // Retrieve a pointer to the function object
135 static _Functor*
136 _M_get_pointer(const _Any_data& __source)
137 {
138 if _GLIBCXX17_CONSTEXPRconstexpr (__stored_locally)
139 {
140 const _Functor& __f = __source._M_access<_Functor>();
141 return const_cast<_Functor*>(std::__addressof(__f));
142 }
143 else // have stored a pointer
144 return __source._M_access<_Functor*>();
145 }
146
147 // Clone a location-invariant function object that fits within
148 // an _Any_data structure.
149 static void
150 _M_clone(_Any_data& __dest, const _Any_data& __source, true_type)
151 {
152 ::new (__dest._M_access()) _Functor(__source._M_access<_Functor>());
153 }
154
155 // Clone a function object that is not location-invariant or
156 // that cannot fit into an _Any_data structure.
157 static void
158 _M_clone(_Any_data& __dest, const _Any_data& __source, false_type)
159 {
160 __dest._M_access<_Functor*>() =
161 new _Functor(*__source._M_access<const _Functor*>());
162 }
163
164 // Destroying a location-invariant object may still require
165 // destruction.
166 static void
167 _M_destroy(_Any_data& __victim, true_type)
168 {
169 __victim._M_access<_Functor>().~_Functor();
170 }
171
172 // Destroying an object located on the heap.
173 static void
174 _M_destroy(_Any_data& __victim, false_type)
175 {
176 delete __victim._M_access<_Functor*>();
177 }
178
179 public:
180 static bool
181 _M_manager(_Any_data& __dest, const _Any_data& __source,
182 _Manager_operation __op)
183 {
184 switch (__op)
185 {
186#if __cpp_rtti199711L
187 case __get_type_info:
188 __dest._M_access<const type_info*>() = &typeid(_Functor);
189 break;
190#endif
191 case __get_functor_ptr:
192 __dest._M_access<_Functor*>() = _M_get_pointer(__source);
193 break;
194
195 case __clone_functor:
196 _M_clone(__dest, __source, _Local_storage());
197 break;
198
199 case __destroy_functor:
200 _M_destroy(__dest, _Local_storage());
201 break;
202 }
203 return false;
204 }
205
206 static void
207 _M_init_functor(_Any_data& __functor, _Functor&& __f)
208 { _M_init_functor(__functor, std::move(__f), _Local_storage()); }
5
Calling '_Base_manager::_M_init_functor'
7
Returned allocated memory
209
210 template<typename _Signature>
211 static bool
212 _M_not_empty_function(const function<_Signature>& __f)
213 { return static_cast<bool>(__f); }
214
215 template<typename _Tp>
216 static bool
217 _M_not_empty_function(_Tp* __fp)
218 { return __fp != nullptr; }
219
220 template<typename _Class, typename _Tp>
221 static bool
222 _M_not_empty_function(_Tp _Class::* __mp)
223 { return __mp != nullptr; }
224
225 template<typename _Tp>
226 static bool
227 _M_not_empty_function(const _Tp&)
228 { return true; }
229
230 private:
231 static void
232 _M_init_functor(_Any_data& __functor, _Functor&& __f, true_type)
233 { ::new (__functor._M_access()) _Functor(std::move(__f)); }
234
235 static void
236 _M_init_functor(_Any_data& __functor, _Functor&& __f, false_type)
237 { __functor._M_access<_Functor*>() = new _Functor(std::move(__f)); }
6
Memory is allocated
238 };
239
240 _Function_base() : _M_manager(nullptr) { }
241
242 ~_Function_base()
243 {
244 if (_M_manager)
245 _M_manager(_M_functor, _M_functor, __destroy_functor);
246 }
247
248 bool _M_empty() const { return !_M_manager; }
249
250 typedef bool (*_Manager_type)(_Any_data&, const _Any_data&,
251 _Manager_operation);
252
253 _Any_data _M_functor;
254 _Manager_type _M_manager;
255 };
256
257 template<typename _Signature, typename _Functor>
258 class _Function_handler;
259
260 template<typename _Res, typename _Functor, typename... _ArgTypes>
261 class _Function_handler<_Res(_ArgTypes...), _Functor>
262 : public _Function_base::_Base_manager<_Functor>
263 {
264 typedef _Function_base::_Base_manager<_Functor> _Base;
265
266 public:
267 static bool
268 _M_manager(_Any_data& __dest, const _Any_data& __source,
269 _Manager_operation __op)
270 {
271 switch (__op)
272 {
273#if __cpp_rtti199711L
274 case __get_type_info:
275 __dest._M_access<const type_info*>() = &typeid(_Functor);
276 break;
277#endif
278 case __get_functor_ptr:
279 __dest._M_access<_Functor*>() = _Base::_M_get_pointer(__source);
280 break;
281
282 default:
283 _Base::_M_manager(__dest, __source, __op);
284 }
285 return false;
286 }
287
288 static _Res
289 _M_invoke(const _Any_data& __functor, _ArgTypes&&... __args)
290 {
291 return std::__invoke_r<_Res>(*_Base::_M_get_pointer(__functor),
292 std::forward<_ArgTypes>(__args)...);
293 }
294 };
295
296 /**
297 * @brief Primary class template for std::function.
298 * @ingroup functors
299 *
300 * Polymorphic function wrapper.
301 */
302 template<typename _Res, typename... _ArgTypes>
303 class function<_Res(_ArgTypes...)>
304 : public _Maybe_unary_or_binary_function<_Res, _ArgTypes...>,
305 private _Function_base
306 {
307 template<typename _Func,
308 typename _Res2 = __invoke_result<_Func&, _ArgTypes...>>
309 struct _Callable
310 : __is_invocable_impl<_Res2, _Res>::type
311 { };
312
313 // Used so the return type convertibility checks aren't done when
314 // performing overload resolution for copy construction/assignment.
315 template<typename _Tp>
316 struct _Callable<function, _Tp> : false_type { };
317
318 template<typename _Cond, typename _Tp>
319 using _Requires = typename enable_if<_Cond::value, _Tp>::type;
320
321 public:
322 typedef _Res result_type;
323
324 // [3.7.2.1] construct/copy/destroy
325
326 /**
327 * @brief Default construct creates an empty function call wrapper.
328 * @post @c !(bool)*this
329 */
330 function() noexcept
331 : _Function_base() { }
332
333 /**
334 * @brief Creates an empty function call wrapper.
335 * @post @c !(bool)*this
336 */
337 function(nullptr_t) noexcept
338 : _Function_base() { }
339
340 /**
341 * @brief %Function copy constructor.
342 * @param __x A %function object with identical call signature.
343 * @post @c bool(*this) == bool(__x)
344 *
345 * The newly-created %function contains a copy of the target of @a
346 * __x (if it has one).
347 */
348 function(const function& __x);
349
350 /**
351 * @brief %Function move constructor.
352 * @param __x A %function object rvalue with identical call signature.
353 *
354 * The newly-created %function contains the target of @a __x
355 * (if it has one).
356 */
357 function(function&& __x) noexcept : _Function_base()
358 {
359 __x.swap(*this);
360 }
361
362 /**
363 * @brief Builds a %function that targets a copy of the incoming
364 * function object.
365 * @param __f A %function object that is callable with parameters of
366 * type @c T1, @c T2, ..., @c TN and returns a value convertible
367 * to @c Res.
368 *
369 * The newly-created %function object will target a copy of
370 * @a __f. If @a __f is @c reference_wrapper<F>, then this function
371 * object will contain a reference to the function object @c
372 * __f.get(). If @a __f is a NULL function pointer or NULL
373 * pointer-to-member, the newly-created object will be empty.
374 *
375 * If @a __f is a non-NULL function pointer or an object of type @c
376 * reference_wrapper<F>, this function will not throw.
377 */
378 template<typename _Functor,
379 typename = _Requires<__not_<is_same<_Functor, function>>, void>,
380 typename = _Requires<_Callable<_Functor>, void>>
381 function(_Functor);
382
383 /**
384 * @brief %Function assignment operator.
385 * @param __x A %function with identical call signature.
386 * @post @c (bool)*this == (bool)x
387 * @returns @c *this
388 *
389 * The target of @a __x is copied to @c *this. If @a __x has no
390 * target, then @c *this will be empty.
391 *
392 * If @a __x targets a function pointer or a reference to a function
393 * object, then this operation will not throw an %exception.
394 */
395 function&
396 operator=(const function& __x)
397 {
398 function(__x).swap(*this);
399 return *this;
400 }
401
402 /**
403 * @brief %Function move-assignment operator.
404 * @param __x A %function rvalue with identical call signature.
405 * @returns @c *this
406 *
407 * The target of @a __x is moved to @c *this. If @a __x has no
408 * target, then @c *this will be empty.
409 *
410 * If @a __x targets a function pointer or a reference to a function
411 * object, then this operation will not throw an %exception.
412 */
413 function&
414 operator=(function&& __x) noexcept
415 {
416 function(std::move(__x)).swap(*this);
417 return *this;
418 }
419
420 /**
421 * @brief %Function assignment to zero.
422 * @post @c !(bool)*this
423 * @returns @c *this
424 *
425 * The target of @c *this is deallocated, leaving it empty.
426 */
427 function&
428 operator=(nullptr_t) noexcept
429 {
430 if (_M_manager)
431 {
432 _M_manager(_M_functor, _M_functor, __destroy_functor);
433 _M_manager = nullptr;
434 _M_invoker = nullptr;
435 }
436 return *this;
437 }
438
439 /**
440 * @brief %Function assignment to a new target.
441 * @param __f A %function object that is callable with parameters of
442 * type @c T1, @c T2, ..., @c TN and returns a value convertible
443 * to @c Res.
444 * @return @c *this
445 *
446 * This %function object wrapper will target a copy of @a
447 * __f. If @a __f is @c reference_wrapper<F>, then this function
448 * object will contain a reference to the function object @c
449 * __f.get(). If @a __f is a NULL function pointer or NULL
450 * pointer-to-member, @c this object will be empty.
451 *
452 * If @a __f is a non-NULL function pointer or an object of type @c
453 * reference_wrapper<F>, this function will not throw.
454 */
455 template<typename _Functor>
456 _Requires<_Callable<typename decay<_Functor>::type>, function&>
457 operator=(_Functor&& __f)
458 {
459 function(std::forward<_Functor>(__f)).swap(*this);
460 return *this;
461 }
462
463 /// @overload
464 template<typename _Functor>
465 function&
466 operator=(reference_wrapper<_Functor> __f) noexcept
467 {
468 function(__f).swap(*this);
469 return *this;
470 }
471
472 // [3.7.2.2] function modifiers
473
474 /**
475 * @brief Swap the targets of two %function objects.
476 * @param __x A %function with identical call signature.
477 *
478 * Swap the targets of @c this function object and @a __f. This
479 * function will not throw an %exception.
480 */
481 void swap(function& __x) noexcept
482 {
483 std::swap(_M_functor, __x._M_functor);
484 std::swap(_M_manager, __x._M_manager);
485 std::swap(_M_invoker, __x._M_invoker);
486 }
487
488 // [3.7.2.3] function capacity
489
490 /**
491 * @brief Determine if the %function wrapper has a target.
492 *
493 * @return @c true when this %function object contains a target,
494 * or @c false when it is empty.
495 *
496 * This function will not throw an %exception.
497 */
498 explicit operator bool() const noexcept
499 { return !_M_empty(); }
500
501 // [3.7.2.4] function invocation
502
503 /**
504 * @brief Invokes the function targeted by @c *this.
505 * @returns the result of the target.
506 * @throws bad_function_call when @c !(bool)*this
507 *
508 * The function call operator invokes the target function object
509 * stored by @c this.
510 */
511 _Res operator()(_ArgTypes... __args) const;
512
513#if __cpp_rtti199711L
514 // [3.7.2.5] function target access
515 /**
516 * @brief Determine the type of the target of this function object
517 * wrapper.
518 *
519 * @returns the type identifier of the target function object, or
520 * @c typeid(void) if @c !(bool)*this.
521 *
522 * This function will not throw an %exception.
523 */
524 const type_info& target_type() const noexcept;
525
526 /**
527 * @brief Access the stored target function object.
528 *
529 * @return Returns a pointer to the stored target function object,
530 * if @c typeid(_Functor).equals(target_type()); otherwise, a NULL
531 * pointer.
532 *
533 * This function does not throw exceptions.
534 *
535 * @{
536 */
537 template<typename _Functor> _Functor* target() noexcept;
538
539 template<typename _Functor> const _Functor* target() const noexcept;
540 // @}
541#endif
542
543 private:
544 using _Invoker_type = _Res (*)(const _Any_data&, _ArgTypes&&...);
545 _Invoker_type _M_invoker;
546 };
547
548#if __cpp_deduction_guides201703L >= 201606
549 template<typename>
550 struct __function_guide_helper
551 { };
552
553 template<typename _Res, typename _Tp, bool _Nx, typename... _Args>
554 struct __function_guide_helper<
555 _Res (_Tp::*) (_Args...) noexcept(_Nx)
556 >
557 { using type = _Res(_Args...); };
558
559 template<typename _Res, typename _Tp, bool _Nx, typename... _Args>
560 struct __function_guide_helper<
561 _Res (_Tp::*) (_Args...) & noexcept(_Nx)
562 >
563 { using type = _Res(_Args...); };
564
565 template<typename _Res, typename _Tp, bool _Nx, typename... _Args>
566 struct __function_guide_helper<
567 _Res (_Tp::*) (_Args...) const noexcept(_Nx)
568 >
569 { using type = _Res(_Args...); };
570
571 template<typename _Res, typename _Tp, bool _Nx, typename... _Args>
572 struct __function_guide_helper<
573 _Res (_Tp::*) (_Args...) const & noexcept(_Nx)
574 >
575 { using type = _Res(_Args...); };
576
577 template<typename _Res, typename... _ArgTypes>
578 function(_Res(*)(_ArgTypes...)) -> function<_Res(_ArgTypes...)>;
579
580 template<typename _Functor, typename _Signature = typename
581 __function_guide_helper<decltype(&_Functor::operator())>::type>
582 function(_Functor) -> function<_Signature>;
583#endif
584
585 // Out-of-line member definitions.
586 template<typename _Res, typename... _ArgTypes>
587 function<_Res(_ArgTypes...)>::
588 function(const function& __x)
589 : _Function_base()
590 {
591 if (static_cast<bool>(__x))
592 {
593 __x._M_manager(_M_functor, __x._M_functor, __clone_functor);
594 _M_invoker = __x._M_invoker;
595 _M_manager = __x._M_manager;
596 }
597 }
598
599 template<typename _Res, typename... _ArgTypes>
600 template<typename _Functor, typename, typename>
601 function<_Res(_ArgTypes...)>::
602 function(_Functor __f)
603 : _Function_base()
604 {
605 typedef _Function_handler<_Res(_ArgTypes...), _Functor> _My_handler;
606
607 if (_My_handler::_M_not_empty_function(__f))
3
Taking true branch
608 {
609 _My_handler::_M_init_functor(_M_functor, std::move(__f));
4
Calling '_Base_manager::_M_init_functor'
8
Returned allocated memory
610 _M_invoker = &_My_handler::_M_invoke;
611 _M_manager = &_My_handler::_M_manager;
612 }
613 }
614
615 template<typename _Res, typename... _ArgTypes>
616 _Res
617 function<_Res(_ArgTypes...)>::
618 operator()(_ArgTypes... __args) const
619 {
620 if (_M_empty())
621 __throw_bad_function_call();
622 return _M_invoker(_M_functor, std::forward<_ArgTypes>(__args)...);
623 }
624
625#if __cpp_rtti199711L
626 template<typename _Res, typename... _ArgTypes>
627 const type_info&
628 function<_Res(_ArgTypes...)>::
629 target_type() const noexcept
630 {
631 if (_M_manager)
632 {
633 _Any_data __typeinfo_result;
634 _M_manager(__typeinfo_result, _M_functor, __get_type_info);
635 return *__typeinfo_result._M_access<const type_info*>();
636 }
637 else
638 return typeid(void);
639 }
640
641 template<typename _Res, typename... _ArgTypes>
642 template<typename _Functor>
643 _Functor*
644 function<_Res(_ArgTypes...)>::
645 target() noexcept
646 {
647 const function* __const_this = this;
648 const _Functor* __func = __const_this->template target<_Functor>();
649 return const_cast<_Functor*>(__func);
650 }
651
652 template<typename _Res, typename... _ArgTypes>
653 template<typename _Functor>
654 const _Functor*
655 function<_Res(_ArgTypes...)>::
656 target() const noexcept
657 {
658 if (typeid(_Functor) == target_type() && _M_manager)
659 {
660 _Any_data __ptr;
661 _M_manager(__ptr, _M_functor, __get_functor_ptr);
662 return __ptr._M_access<const _Functor*>();
663 }
664 else
665 return nullptr;
666 }
667#endif
668
669 // [20.7.15.2.6] null pointer comparisons
670
671 /**
672 * @brief Compares a polymorphic function object wrapper against 0
673 * (the NULL pointer).
674 * @returns @c true if the wrapper has no target, @c false otherwise
675 *
676 * This function will not throw an %exception.
677 */
678 template<typename _Res, typename... _Args>
679 inline bool
680 operator==(const function<_Res(_Args...)>& __f, nullptr_t) noexcept
681 { return !static_cast<bool>(__f); }
682
683#if __cpp_impl_three_way_comparison < 201907L
684 /// @overload
685 template<typename _Res, typename... _Args>
686 inline bool
687 operator==(nullptr_t, const function<_Res(_Args...)>& __f) noexcept
688 { return !static_cast<bool>(__f); }
689
690 /**
691 * @brief Compares a polymorphic function object wrapper against 0
692 * (the NULL pointer).
693 * @returns @c false if the wrapper has no target, @c true otherwise
694 *
695 * This function will not throw an %exception.
696 */
697 template<typename _Res, typename... _Args>
698 inline bool
699 operator!=(const function<_Res(_Args...)>& __f, nullptr_t) noexcept
700 { return static_cast<bool>(__f); }
701
702 /// @overload
703 template<typename _Res, typename... _Args>
704 inline bool
705 operator!=(nullptr_t, const function<_Res(_Args...)>& __f) noexcept
706 { return static_cast<bool>(__f); }
707#endif
708
709 // [20.7.15.2.7] specialized algorithms
710
711 /**
712 * @brief Swap the targets of two polymorphic function object wrappers.
713 *
714 * This function will not throw an %exception.
715 */
716 // _GLIBCXX_RESOLVE_LIB_DEFECTS
717 // 2062. Effect contradictions w/o no-throw guarantee of std::function swaps
718 template<typename _Res, typename... _Args>
719 inline void
720 swap(function<_Res(_Args...)>& __x, function<_Res(_Args...)>& __y) noexcept
721 { __x.swap(__y); }
722
723#if __cplusplus201703L >= 201703L
724 namespace __detail::__variant
725 {
726 template<typename> struct _Never_valueless_alt; // see <variant>
727
728 // Provide the strong exception-safety guarantee when emplacing a
729 // function into a variant.
730 template<typename _Signature>
731 struct _Never_valueless_alt<std::function<_Signature>>
732 : std::true_type
733 { };
734 } // namespace __detail::__variant
735#endif // C++17
736
737_GLIBCXX_END_NAMESPACE_VERSION
738} // namespace std
739
740#endif // C++11
741#endif // _GLIBCXX_STD_FUNCTION_H