Bug Summary

File:build/source/llvm/lib/ExecutionEngine/Orc/COFFPlatform.cpp
Warning:line 419, column 21
Method called on moved-from object 'LoadDynLibrary'

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 COFFPlatform.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/source/build-llvm/tools/clang/stage2-bins -resource-dir /usr/lib/llvm-17/lib/clang/17 -I lib/ExecutionEngine/Orc -I /build/source/llvm/lib/ExecutionEngine/Orc -I include -I /build/source/llvm/include -D _DEBUG -D _GLIBCXX_ASSERTIONS -D _GNU_SOURCE -D _LIBCPP_ENABLE_ASSERTIONS -D __STDC_CONSTANT_MACROS -D __STDC_FORMAT_MACROS -D __STDC_LIMIT_MACROS -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-17/lib/clang/17/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/source/build-llvm/tools/clang/stage2-bins=build-llvm/tools/clang/stage2-bins -fmacro-prefix-map=/build/source/= -fcoverage-prefix-map=/build/source/build-llvm/tools/clang/stage2-bins=build-llvm/tools/clang/stage2-bins -fcoverage-prefix-map=/build/source/= -source-date-epoch 1677842174 -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/source/build-llvm/tools/clang/stage2-bins -fdebug-prefix-map=/build/source/build-llvm/tools/clang/stage2-bins=build-llvm/tools/clang/stage2-bins -fdebug-prefix-map=/build/source/= -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-2023-03-03-140516-16496-1 -x c++ /build/source/llvm/lib/ExecutionEngine/Orc/COFFPlatform.cpp

/build/source/llvm/lib/ExecutionEngine/Orc/COFFPlatform.cpp

1//===------- COFFPlatform.cpp - Utilities for executing COFF in Orc -------===//
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 "llvm/ExecutionEngine/Orc/COFFPlatform.h"
10#include "llvm/ExecutionEngine/Orc/DebugUtils.h"
11#include "llvm/ExecutionEngine/Orc/LookupAndRecordAddrs.h"
12#include "llvm/ExecutionEngine/Orc/ObjectFileInterface.h"
13#include "llvm/ExecutionEngine/Orc/Shared/ObjectFormats.h"
14
15#include "llvm/Object/COFF.h"
16
17#include "llvm/ExecutionEngine/Orc/EPCDynamicLibrarySearchGenerator.h"
18
19#include "llvm/ExecutionEngine/JITLink/x86_64.h"
20
21#define DEBUG_TYPE"orc" "orc"
22
23using namespace llvm;
24using namespace llvm::orc;
25using namespace llvm::orc::shared;
26
27namespace llvm {
28namespace orc {
29namespace shared {
30
31using SPSCOFFJITDylibDepInfo = SPSSequence<SPSExecutorAddr>;
32using SPSCOFFJITDylibDepInfoMap =
33 SPSSequence<SPSTuple<SPSExecutorAddr, SPSCOFFJITDylibDepInfo>>;
34using SPSCOFFObjectSectionsMap =
35 SPSSequence<SPSTuple<SPSString, SPSExecutorAddrRange>>;
36using SPSCOFFRegisterObjectSectionsArgs =
37 SPSArgList<SPSExecutorAddr, SPSCOFFObjectSectionsMap, bool>;
38using SPSCOFFDeregisterObjectSectionsArgs =
39 SPSArgList<SPSExecutorAddr, SPSCOFFObjectSectionsMap>;
40
41} // namespace shared
42} // namespace orc
43} // namespace llvm
44namespace {
45
46class COFFHeaderMaterializationUnit : public MaterializationUnit {
47public:
48 COFFHeaderMaterializationUnit(COFFPlatform &CP,
49 const SymbolStringPtr &HeaderStartSymbol)
50 : MaterializationUnit(createHeaderInterface(CP, HeaderStartSymbol)),
51 CP(CP) {}
52
53 StringRef getName() const override { return "COFFHeaderMU"; }
54
55 void materialize(std::unique_ptr<MaterializationResponsibility> R) override {
56 unsigned PointerSize;
57 support::endianness Endianness;
58 const auto &TT = CP.getExecutionSession().getTargetTriple();
59
60 switch (TT.getArch()) {
61 case Triple::x86_64:
62 PointerSize = 8;
63 Endianness = support::endianness::little;
64 break;
65 default:
66 llvm_unreachable("Unrecognized architecture")::llvm::llvm_unreachable_internal("Unrecognized architecture"
, "llvm/lib/ExecutionEngine/Orc/COFFPlatform.cpp", 66)
;
67 }
68
69 auto G = std::make_unique<jitlink::LinkGraph>(
70 "<COFFHeaderMU>", TT, PointerSize, Endianness,
71 jitlink::getGenericEdgeKindName);
72 auto &HeaderSection = G->createSection("__header", MemProt::Read);
73 auto &HeaderBlock = createHeaderBlock(*G, HeaderSection);
74
75 // Init symbol is __ImageBase symbol.
76 auto &ImageBaseSymbol = G->addDefinedSymbol(
77 HeaderBlock, 0, *R->getInitializerSymbol(), HeaderBlock.getSize(),
78 jitlink::Linkage::Strong, jitlink::Scope::Default, false, true);
79
80 addImageBaseRelocationEdge(HeaderBlock, ImageBaseSymbol);
81
82 CP.getObjectLinkingLayer().emit(std::move(R), std::move(G));
83 }
84
85 void discard(const JITDylib &JD, const SymbolStringPtr &Sym) override {}
86
87private:
88 struct HeaderSymbol {
89 const char *Name;
90 uint64_t Offset;
91 };
92
93 struct NTHeader {
94 support::ulittle32_t PEMagic;
95 object::coff_file_header FileHeader;
96 struct PEHeader {
97 object::pe32plus_header Header;
98 object::data_directory DataDirectory[COFF::NUM_DATA_DIRECTORIES + 1];
99 } OptionalHeader;
100 };
101
102 struct HeaderBlockContent {
103 object::dos_header DOSHeader;
104 COFFHeaderMaterializationUnit::NTHeader NTHeader;
105 };
106
107 static jitlink::Block &createHeaderBlock(jitlink::LinkGraph &G,
108 jitlink::Section &HeaderSection) {
109 HeaderBlockContent Hdr = {};
110
111 // Set up magic
112 Hdr.DOSHeader.Magic[0] = 'M';
113 Hdr.DOSHeader.Magic[1] = 'Z';
114 Hdr.DOSHeader.AddressOfNewExeHeader =
115 offsetof(HeaderBlockContent, NTHeader)__builtin_offsetof(HeaderBlockContent, NTHeader);
116 uint32_t PEMagic = *reinterpret_cast<const uint32_t *>(COFF::PEMagic);
117 Hdr.NTHeader.PEMagic = PEMagic;
118 Hdr.NTHeader.OptionalHeader.Header.Magic = COFF::PE32Header::PE32_PLUS;
119
120 switch (G.getTargetTriple().getArch()) {
121 case Triple::x86_64:
122 Hdr.NTHeader.FileHeader.Machine = COFF::IMAGE_FILE_MACHINE_AMD64;
123 break;
124 default:
125 llvm_unreachable("Unrecognized architecture")::llvm::llvm_unreachable_internal("Unrecognized architecture"
, "llvm/lib/ExecutionEngine/Orc/COFFPlatform.cpp", 125)
;
126 }
127
128 auto HeaderContent = G.allocateContent(
129 ArrayRef<char>(reinterpret_cast<const char *>(&Hdr), sizeof(Hdr)));
130
131 return G.createContentBlock(HeaderSection, HeaderContent, ExecutorAddr(), 8,
132 0);
133 }
134
135 static void addImageBaseRelocationEdge(jitlink::Block &B,
136 jitlink::Symbol &ImageBase) {
137 auto ImageBaseOffset = offsetof(HeaderBlockContent, NTHeader)__builtin_offsetof(HeaderBlockContent, NTHeader) +
138 offsetof(NTHeader, OptionalHeader)__builtin_offsetof(NTHeader, OptionalHeader) +
139 offsetof(object::pe32plus_header, ImageBase)__builtin_offsetof(object::pe32plus_header, ImageBase);
140 B.addEdge(jitlink::x86_64::Pointer64, ImageBaseOffset, ImageBase, 0);
141 }
142
143 static MaterializationUnit::Interface
144 createHeaderInterface(COFFPlatform &MOP,
145 const SymbolStringPtr &HeaderStartSymbol) {
146 SymbolFlagsMap HeaderSymbolFlags;
147
148 HeaderSymbolFlags[HeaderStartSymbol] = JITSymbolFlags::Exported;
149
150 return MaterializationUnit::Interface(std::move(HeaderSymbolFlags),
151 HeaderStartSymbol);
152 }
153
154 COFFPlatform &CP;
155};
156
157} // end anonymous namespace
158
159namespace llvm {
160namespace orc {
161
162Expected<std::unique_ptr<COFFPlatform>>
163COFFPlatform::Create(ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer,
164 JITDylib &PlatformJD, const char *OrcRuntimePath,
165 LoadDynamicLibrary LoadDynLibrary, bool StaticVCRuntime,
166 const char *VCRuntimePath,
167 std::optional<SymbolAliasMap> RuntimeAliases) {
168
169 // If the target is not supported then bail out immediately.
170 if (!supportedTarget(ES.getTargetTriple()))
1
Taking false branch
171 return make_error<StringError>("Unsupported COFFPlatform triple: " +
172 ES.getTargetTriple().str(),
173 inconvertibleErrorCode());
174
175 auto &EPC = ES.getExecutorProcessControl();
176
177 // Create default aliases if the caller didn't supply any.
178 if (!RuntimeAliases)
2
Assuming the condition is false
3
Taking false branch
179 RuntimeAliases = standardPlatformAliases(ES);
180
181 // Define the aliases.
182 if (auto Err = PlatformJD.define(symbolAliases(std::move(*RuntimeAliases))))
4
Taking false branch
183 return std::move(Err);
184
185 auto &HostFuncJD = ES.createBareJITDylib("$<PlatformRuntimeHostFuncJD>");
186
187 // Add JIT-dispatch function support symbols.
188 if (auto Err = HostFuncJD.define(absoluteSymbols(
5
Taking false branch
189 {{ES.intern("__orc_rt_jit_dispatch"),
190 {EPC.getJITDispatchInfo().JITDispatchFunction.getValue(),
191 JITSymbolFlags::Exported}},
192 {ES.intern("__orc_rt_jit_dispatch_ctx"),
193 {EPC.getJITDispatchInfo().JITDispatchContext.getValue(),
194 JITSymbolFlags::Exported}}})))
195 return std::move(Err);
196
197 PlatformJD.addToLinkOrder(HostFuncJD);
198
199 // Create the instance.
200 Error Err = Error::success();
201 auto P = std::unique_ptr<COFFPlatform>(new COFFPlatform(
6
Calling constructor for 'COFFPlatform'
202 ES, ObjLinkingLayer, PlatformJD, OrcRuntimePath,
203 std::move(LoadDynLibrary), StaticVCRuntime, VCRuntimePath, Err));
204 if (Err)
205 return std::move(Err);
206 return std::move(P);
207}
208
209Expected<MemoryBufferRef> COFFPlatform::getPerJDObjectFile() {
210 auto PerJDObj = OrcRuntimeArchive->findSym("__orc_rt_coff_per_jd_marker");
211 if (!PerJDObj)
212 return PerJDObj.takeError();
213
214 if (!*PerJDObj)
215 return make_error<StringError>("Could not find per jd object file",
216 inconvertibleErrorCode());
217
218 auto Buffer = (*PerJDObj)->getAsBinary();
219 if (!Buffer)
220 return Buffer.takeError();
221
222 return (*Buffer)->getMemoryBufferRef();
223}
224
225static void addAliases(ExecutionSession &ES, SymbolAliasMap &Aliases,
226 ArrayRef<std::pair<const char *, const char *>> AL) {
227 for (auto &KV : AL) {
228 auto AliasName = ES.intern(KV.first);
229 assert(!Aliases.count(AliasName) && "Duplicate symbol name in alias map")(static_cast <bool> (!Aliases.count(AliasName) &&
"Duplicate symbol name in alias map") ? void (0) : __assert_fail
("!Aliases.count(AliasName) && \"Duplicate symbol name in alias map\""
, "llvm/lib/ExecutionEngine/Orc/COFFPlatform.cpp", 229, __extension__
__PRETTY_FUNCTION__))
;
230 Aliases[std::move(AliasName)] = {ES.intern(KV.second),
231 JITSymbolFlags::Exported};
232 }
233}
234
235Error COFFPlatform::setupJITDylib(JITDylib &JD) {
236 if (auto Err = JD.define(std::make_unique<COFFHeaderMaterializationUnit>(
237 *this, COFFHeaderStartSymbol)))
238 return Err;
239
240 if (auto Err = ES.lookup({&JD}, COFFHeaderStartSymbol).takeError())
241 return Err;
242
243 // Define the CXX aliases.
244 SymbolAliasMap CXXAliases;
245 addAliases(ES, CXXAliases, requiredCXXAliases());
246 if (auto Err = JD.define(symbolAliases(std::move(CXXAliases))))
247 return Err;
248
249 auto PerJDObj = getPerJDObjectFile();
250 if (!PerJDObj)
251 return PerJDObj.takeError();
252
253 auto I = getObjectFileInterface(ES, *PerJDObj);
254 if (!I)
255 return I.takeError();
256
257 if (auto Err = ObjLinkingLayer.add(
258 JD, MemoryBuffer::getMemBuffer(*PerJDObj, false), std::move(*I)))
259 return Err;
260
261 if (!Bootstrapping) {
262 auto ImportedLibs = StaticVCRuntime
263 ? VCRuntimeBootstrap->loadStaticVCRuntime(JD)
264 : VCRuntimeBootstrap->loadDynamicVCRuntime(JD);
265 if (!ImportedLibs)
266 return ImportedLibs.takeError();
267 for (auto &Lib : *ImportedLibs)
268 if (auto Err = LoadDynLibrary(JD, Lib))
269 return Err;
270 if (StaticVCRuntime)
271 if (auto Err = VCRuntimeBootstrap->initializeStaticVCRuntime(JD))
272 return Err;
273 }
274
275 JD.addGenerator(DLLImportDefinitionGenerator::Create(ES, ObjLinkingLayer));
276 return Error::success();
277}
278
279Error COFFPlatform::teardownJITDylib(JITDylib &JD) {
280 std::lock_guard<std::mutex> Lock(PlatformMutex);
281 auto I = JITDylibToHeaderAddr.find(&JD);
282 if (I != JITDylibToHeaderAddr.end()) {
283 assert(HeaderAddrToJITDylib.count(I->second) &&(static_cast <bool> (HeaderAddrToJITDylib.count(I->second
) && "HeaderAddrToJITDylib missing entry") ? void (0)
: __assert_fail ("HeaderAddrToJITDylib.count(I->second) && \"HeaderAddrToJITDylib missing entry\""
, "llvm/lib/ExecutionEngine/Orc/COFFPlatform.cpp", 284, __extension__
__PRETTY_FUNCTION__))
284 "HeaderAddrToJITDylib missing entry")(static_cast <bool> (HeaderAddrToJITDylib.count(I->second
) && "HeaderAddrToJITDylib missing entry") ? void (0)
: __assert_fail ("HeaderAddrToJITDylib.count(I->second) && \"HeaderAddrToJITDylib missing entry\""
, "llvm/lib/ExecutionEngine/Orc/COFFPlatform.cpp", 284, __extension__
__PRETTY_FUNCTION__))
;
285 HeaderAddrToJITDylib.erase(I->second);
286 JITDylibToHeaderAddr.erase(I);
287 }
288 return Error::success();
289}
290
291Error COFFPlatform::notifyAdding(ResourceTracker &RT,
292 const MaterializationUnit &MU) {
293 auto &JD = RT.getJITDylib();
294 const auto &InitSym = MU.getInitializerSymbol();
295 if (!InitSym)
296 return Error::success();
297
298 RegisteredInitSymbols[&JD].add(InitSym,
299 SymbolLookupFlags::WeaklyReferencedSymbol);
300
301 LLVM_DEBUG({do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("orc")) { { dbgs() << "COFFPlatform: Registered init symbol "
<< *InitSym << " for MU " << MU.getName() <<
"\n"; }; } } while (false)
302 dbgs() << "COFFPlatform: Registered init symbol " << *InitSym << " for MU "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("orc")) { { dbgs() << "COFFPlatform: Registered init symbol "
<< *InitSym << " for MU " << MU.getName() <<
"\n"; }; } } while (false)
303 << MU.getName() << "\n";do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("orc")) { { dbgs() << "COFFPlatform: Registered init symbol "
<< *InitSym << " for MU " << MU.getName() <<
"\n"; }; } } while (false)
304 })do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("orc")) { { dbgs() << "COFFPlatform: Registered init symbol "
<< *InitSym << " for MU " << MU.getName() <<
"\n"; }; } } while (false)
;
305 return Error::success();
306}
307
308Error COFFPlatform::notifyRemoving(ResourceTracker &RT) {
309 llvm_unreachable("Not supported yet")::llvm::llvm_unreachable_internal("Not supported yet", "llvm/lib/ExecutionEngine/Orc/COFFPlatform.cpp"
, 309)
;
310}
311
312SymbolAliasMap COFFPlatform::standardPlatformAliases(ExecutionSession &ES) {
313 SymbolAliasMap Aliases;
314 addAliases(ES, Aliases, standardRuntimeUtilityAliases());
315 return Aliases;
316}
317
318ArrayRef<std::pair<const char *, const char *>>
319COFFPlatform::requiredCXXAliases() {
320 static const std::pair<const char *, const char *> RequiredCXXAliases[] = {
321 {"_CxxThrowException", "__orc_rt_coff_cxx_throw_exception"},
322 {"_onexit", "__orc_rt_coff_onexit_per_jd"},
323 {"atexit", "__orc_rt_coff_atexit_per_jd"}};
324
325 return ArrayRef<std::pair<const char *, const char *>>(RequiredCXXAliases);
326}
327
328ArrayRef<std::pair<const char *, const char *>>
329COFFPlatform::standardRuntimeUtilityAliases() {
330 static const std::pair<const char *, const char *>
331 StandardRuntimeUtilityAliases[] = {
332 {"__orc_rt_run_program", "__orc_rt_coff_run_program"},
333 {"__orc_rt_jit_dlerror", "__orc_rt_coff_jit_dlerror"},
334 {"__orc_rt_jit_dlopen", "__orc_rt_coff_jit_dlopen"},
335 {"__orc_rt_jit_dlclose", "__orc_rt_coff_jit_dlclose"},
336 {"__orc_rt_jit_dlsym", "__orc_rt_coff_jit_dlsym"},
337 {"__orc_rt_log_error", "__orc_rt_log_error_to_stderr"}};
338
339 return ArrayRef<std::pair<const char *, const char *>>(
340 StandardRuntimeUtilityAliases);
341}
342
343bool COFFPlatform::supportedTarget(const Triple &TT) {
344 switch (TT.getArch()) {
345 case Triple::x86_64:
346 return true;
347 default:
348 return false;
349 }
350}
351
352COFFPlatform::COFFPlatform(ExecutionSession &ES,
353 ObjectLinkingLayer &ObjLinkingLayer,
354 JITDylib &PlatformJD, const char *OrcRuntimePath,
355 LoadDynamicLibrary LoadDynLibrary,
356 bool StaticVCRuntime, const char *VCRuntimePath,
357 Error &Err)
358 : ES(ES), ObjLinkingLayer(ObjLinkingLayer),
359 LoadDynLibrary(std::move(LoadDynLibrary)),
7
Object 'LoadDynLibrary' is moved
360 StaticVCRuntime(StaticVCRuntime),
361 COFFHeaderStartSymbol(ES.intern("__ImageBase")) {
362 ErrorAsOutParameter _(&Err);
363
364 // Create a generator for the ORC runtime archive.
365 auto OrcRuntimeArchiveGenerator =
366 StaticLibraryDefinitionGenerator::Load(ObjLinkingLayer, OrcRuntimePath);
367 if (!OrcRuntimeArchiveGenerator) {
8
Taking false branch
368 Err = OrcRuntimeArchiveGenerator.takeError();
369 return;
370 }
371
372 auto ArchiveBuffer = MemoryBuffer::getFile(OrcRuntimePath);
373 if (!ArchiveBuffer) {
9
Taking false branch
374 Err = createFileError(OrcRuntimePath, ArchiveBuffer.getError());
375 return;
376 }
377 OrcRuntimeArchiveBuffer = std::move(*ArchiveBuffer);
378 OrcRuntimeArchive =
379 std::make_unique<object::Archive>(*OrcRuntimeArchiveBuffer, Err);
380 if (Err)
10
Assuming the condition is false
11
Taking false branch
381 return;
382
383 Bootstrapping.store(true);
384 ObjLinkingLayer.addPlugin(std::make_unique<COFFPlatformPlugin>(*this));
385
386 // Load vc runtime
387 auto VCRT =
388 COFFVCRuntimeBootstrapper::Create(ES, ObjLinkingLayer, VCRuntimePath);
389 if (!VCRT) {
12
Taking false branch
390 Err = VCRT.takeError();
391 return;
392 }
393 VCRuntimeBootstrap = std::move(*VCRT);
394
395 for (auto &Lib : (*OrcRuntimeArchiveGenerator)->getImportedDynamicLibraries())
396 DylibsToPreload.insert(Lib);
397
398 auto ImportedLibs =
399 StaticVCRuntime ? VCRuntimeBootstrap->loadStaticVCRuntime(PlatformJD)
13
Assuming 'StaticVCRuntime' is false
14
'?' condition is false
400 : VCRuntimeBootstrap->loadDynamicVCRuntime(PlatformJD);
401 if (!ImportedLibs) {
15
Taking false branch
402 Err = ImportedLibs.takeError();
403 return;
404 }
405
406 for (auto &Lib : *ImportedLibs)
407 DylibsToPreload.insert(Lib);
408
409 PlatformJD.addGenerator(std::move(*OrcRuntimeArchiveGenerator));
410
411 // PlatformJD hasn't been set up by the platform yet (since we're creating
412 // the platform now), so set it up.
413 if (auto E2 = setupJITDylib(PlatformJD)) {
16
Assuming the condition is false
17
Taking false branch
414 Err = std::move(E2);
415 return;
416 }
417
418 for (auto& Lib : DylibsToPreload)
419 if (auto E2 = LoadDynLibrary(PlatformJD, Lib)) {
18
Method called on moved-from object 'LoadDynLibrary'
420 Err = std::move(E2);
421 return;
422 }
423
424 if (StaticVCRuntime)
425 if (auto E2 = VCRuntimeBootstrap->initializeStaticVCRuntime(PlatformJD)) {
426 Err = std::move(E2);
427 return;
428 }
429
430 // Associate wrapper function tags with JIT-side function implementations.
431 if (auto E2 = associateRuntimeSupportFunctions(PlatformJD)) {
432 Err = std::move(E2);
433 return;
434 }
435
436 // Lookup addresses of runtime functions callable by the platform,
437 // call the platform bootstrap function to initialize the platform-state
438 // object in the executor.
439 if (auto E2 = bootstrapCOFFRuntime(PlatformJD)) {
440 Err = std::move(E2);
441 return;
442 }
443
444 Bootstrapping.store(false);
445 JDBootstrapStates.clear();
446}
447
448Expected<COFFPlatform::JITDylibDepMap>
449COFFPlatform::buildJDDepMap(JITDylib &JD) {
450 return ES.runSessionLocked([&]() -> Expected<JITDylibDepMap> {
451 JITDylibDepMap JDDepMap;
452
453 SmallVector<JITDylib *, 16> Worklist({&JD});
454 while (!Worklist.empty()) {
455 auto CurJD = Worklist.back();
456 Worklist.pop_back();
457
458 auto &DM = JDDepMap[CurJD];
459 CurJD->withLinkOrderDo([&](const JITDylibSearchOrder &O) {
460 DM.reserve(O.size());
461 for (auto &KV : O) {
462 if (KV.first == CurJD)
463 continue;
464 {
465 // Bare jitdylibs not known to the platform
466 std::lock_guard<std::mutex> Lock(PlatformMutex);
467 if (!JITDylibToHeaderAddr.count(KV.first)) {
468 LLVM_DEBUG({do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("orc")) { { dbgs() << "JITDylib unregistered to COFFPlatform detected in "
"LinkOrder: " << CurJD->getName() << "\n"; };
} } while (false)
469 dbgs() << "JITDylib unregistered to COFFPlatform detected in "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("orc")) { { dbgs() << "JITDylib unregistered to COFFPlatform detected in "
"LinkOrder: " << CurJD->getName() << "\n"; };
} } while (false)
470 "LinkOrder: "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("orc")) { { dbgs() << "JITDylib unregistered to COFFPlatform detected in "
"LinkOrder: " << CurJD->getName() << "\n"; };
} } while (false)
471 << CurJD->getName() << "\n";do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("orc")) { { dbgs() << "JITDylib unregistered to COFFPlatform detected in "
"LinkOrder: " << CurJD->getName() << "\n"; };
} } while (false)
472 })do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("orc")) { { dbgs() << "JITDylib unregistered to COFFPlatform detected in "
"LinkOrder: " << CurJD->getName() << "\n"; };
} } while (false)
;
473 continue;
474 }
475 }
476 DM.push_back(KV.first);
477 // Push unvisited entry.
478 if (!JDDepMap.count(KV.first)) {
479 Worklist.push_back(KV.first);
480 JDDepMap[KV.first] = {};
481 }
482 }
483 });
484 }
485 return std::move(JDDepMap);
486 });
487}
488
489void COFFPlatform::pushInitializersLoop(PushInitializersSendResultFn SendResult,
490 JITDylibSP JD,
491 JITDylibDepMap &JDDepMap) {
492 SmallVector<JITDylib *, 16> Worklist({JD.get()});
493 DenseSet<JITDylib *> Visited({JD.get()});
494 DenseMap<JITDylib *, SymbolLookupSet> NewInitSymbols;
495 ES.runSessionLocked([&]() {
496 while (!Worklist.empty()) {
497 auto CurJD = Worklist.back();
498 Worklist.pop_back();
499
500 auto RISItr = RegisteredInitSymbols.find(CurJD);
501 if (RISItr != RegisteredInitSymbols.end()) {
502 NewInitSymbols[CurJD] = std::move(RISItr->second);
503 RegisteredInitSymbols.erase(RISItr);
504 }
505
506 for (auto *DepJD : JDDepMap[CurJD])
507 if (!Visited.count(DepJD)) {
508 Worklist.push_back(DepJD);
509 Visited.insert(DepJD);
510 }
511 }
512 });
513
514 // If there are no further init symbols to look up then send the link order
515 // (as a list of header addresses) to the caller.
516 if (NewInitSymbols.empty()) {
517 // Build the dep info map to return.
518 COFFJITDylibDepInfoMap DIM;
519 DIM.reserve(JDDepMap.size());
520 for (auto &KV : JDDepMap) {
521 std::lock_guard<std::mutex> Lock(PlatformMutex);
522 COFFJITDylibDepInfo DepInfo;
523 DepInfo.reserve(KV.second.size());
524 for (auto &Dep : KV.second) {
525 DepInfo.push_back(JITDylibToHeaderAddr[Dep]);
526 }
527 auto H = JITDylibToHeaderAddr[KV.first];
528 DIM.push_back(std::make_pair(H, std::move(DepInfo)));
529 }
530 SendResult(DIM);
531 return;
532 }
533
534 // Otherwise issue a lookup and re-run this phase when it completes.
535 lookupInitSymbolsAsync(
536 [this, SendResult = std::move(SendResult), &JD,
537 JDDepMap = std::move(JDDepMap)](Error Err) mutable {
538 if (Err)
539 SendResult(std::move(Err));
540 else
541 pushInitializersLoop(std::move(SendResult), JD, JDDepMap);
542 },
543 ES, std::move(NewInitSymbols));
544}
545
546void COFFPlatform::rt_pushInitializers(PushInitializersSendResultFn SendResult,
547 ExecutorAddr JDHeaderAddr) {
548 JITDylibSP JD;
549 {
550 std::lock_guard<std::mutex> Lock(PlatformMutex);
551 auto I = HeaderAddrToJITDylib.find(JDHeaderAddr);
552 if (I != HeaderAddrToJITDylib.end())
553 JD = I->second;
554 }
555
556 LLVM_DEBUG({do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("orc")) { { dbgs() << "COFFPlatform::rt_pushInitializers("
<< JDHeaderAddr << ") "; if (JD) dbgs() <<
"pushing initializers for " << JD->getName() <<
"\n"; else dbgs() << "No JITDylib for header address.\n"
; }; } } while (false)
557 dbgs() << "COFFPlatform::rt_pushInitializers(" << JDHeaderAddr << ") ";do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("orc")) { { dbgs() << "COFFPlatform::rt_pushInitializers("
<< JDHeaderAddr << ") "; if (JD) dbgs() <<
"pushing initializers for " << JD->getName() <<
"\n"; else dbgs() << "No JITDylib for header address.\n"
; }; } } while (false)
558 if (JD)do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("orc")) { { dbgs() << "COFFPlatform::rt_pushInitializers("
<< JDHeaderAddr << ") "; if (JD) dbgs() <<
"pushing initializers for " << JD->getName() <<
"\n"; else dbgs() << "No JITDylib for header address.\n"
; }; } } while (false)
559 dbgs() << "pushing initializers for " << JD->getName() << "\n";do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("orc")) { { dbgs() << "COFFPlatform::rt_pushInitializers("
<< JDHeaderAddr << ") "; if (JD) dbgs() <<
"pushing initializers for " << JD->getName() <<
"\n"; else dbgs() << "No JITDylib for header address.\n"
; }; } } while (false)
560 elsedo { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("orc")) { { dbgs() << "COFFPlatform::rt_pushInitializers("
<< JDHeaderAddr << ") "; if (JD) dbgs() <<
"pushing initializers for " << JD->getName() <<
"\n"; else dbgs() << "No JITDylib for header address.\n"
; }; } } while (false)
561 dbgs() << "No JITDylib for header address.\n";do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("orc")) { { dbgs() << "COFFPlatform::rt_pushInitializers("
<< JDHeaderAddr << ") "; if (JD) dbgs() <<
"pushing initializers for " << JD->getName() <<
"\n"; else dbgs() << "No JITDylib for header address.\n"
; }; } } while (false)
562 })do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("orc")) { { dbgs() << "COFFPlatform::rt_pushInitializers("
<< JDHeaderAddr << ") "; if (JD) dbgs() <<
"pushing initializers for " << JD->getName() <<
"\n"; else dbgs() << "No JITDylib for header address.\n"
; }; } } while (false)
;
563
564 if (!JD) {
565 SendResult(
566 make_error<StringError>("No JITDylib with header addr " +
567 formatv("{0:x}", JDHeaderAddr.getValue()),
568 inconvertibleErrorCode()));
569 return;
570 }
571
572 auto JDDepMap = buildJDDepMap(*JD);
573 if (!JDDepMap) {
574 SendResult(JDDepMap.takeError());
575 return;
576 }
577
578 pushInitializersLoop(std::move(SendResult), JD, *JDDepMap);
579}
580
581void COFFPlatform::rt_lookupSymbol(SendSymbolAddressFn SendResult,
582 ExecutorAddr Handle, StringRef SymbolName) {
583 LLVM_DEBUG({do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("orc")) { { dbgs() << "COFFPlatform::rt_lookupSymbol(\""
<< formatv("{0:x}", Handle.getValue()) << "\")\n"
; }; } } while (false)
584 dbgs() << "COFFPlatform::rt_lookupSymbol(\""do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("orc")) { { dbgs() << "COFFPlatform::rt_lookupSymbol(\""
<< formatv("{0:x}", Handle.getValue()) << "\")\n"
; }; } } while (false)
585 << formatv("{0:x}", Handle.getValue()) << "\")\n";do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("orc")) { { dbgs() << "COFFPlatform::rt_lookupSymbol(\""
<< formatv("{0:x}", Handle.getValue()) << "\")\n"
; }; } } while (false)
586 })do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("orc")) { { dbgs() << "COFFPlatform::rt_lookupSymbol(\""
<< formatv("{0:x}", Handle.getValue()) << "\")\n"
; }; } } while (false)
;
587
588 JITDylib *JD = nullptr;
589
590 {
591 std::lock_guard<std::mutex> Lock(PlatformMutex);
592 auto I = HeaderAddrToJITDylib.find(Handle);
593 if (I != HeaderAddrToJITDylib.end())
594 JD = I->second;
595 }
596
597 if (!JD) {
598 LLVM_DEBUG({do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("orc")) { { dbgs() << " No JITDylib for handle " <<
formatv("{0:x}", Handle.getValue()) << "\n"; }; } } while
(false)
599 dbgs() << " No JITDylib for handle "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("orc")) { { dbgs() << " No JITDylib for handle " <<
formatv("{0:x}", Handle.getValue()) << "\n"; }; } } while
(false)
600 << formatv("{0:x}", Handle.getValue()) << "\n";do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("orc")) { { dbgs() << " No JITDylib for handle " <<
formatv("{0:x}", Handle.getValue()) << "\n"; }; } } while
(false)
601 })do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("orc")) { { dbgs() << " No JITDylib for handle " <<
formatv("{0:x}", Handle.getValue()) << "\n"; }; } } while
(false)
;
602 SendResult(make_error<StringError>("No JITDylib associated with handle " +
603 formatv("{0:x}", Handle.getValue()),
604 inconvertibleErrorCode()));
605 return;
606 }
607
608 // Use functor class to work around XL build compiler issue on AIX.
609 class RtLookupNotifyComplete {
610 public:
611 RtLookupNotifyComplete(SendSymbolAddressFn &&SendResult)
612 : SendResult(std::move(SendResult)) {}
613 void operator()(Expected<SymbolMap> Result) {
614 if (Result) {
615 assert(Result->size() == 1 && "Unexpected result map count")(static_cast <bool> (Result->size() == 1 && "Unexpected result map count"
) ? void (0) : __assert_fail ("Result->size() == 1 && \"Unexpected result map count\""
, "llvm/lib/ExecutionEngine/Orc/COFFPlatform.cpp", 615, __extension__
__PRETTY_FUNCTION__))
;
616 SendResult(ExecutorAddr(Result->begin()->second.getAddress()));
617 } else {
618 SendResult(Result.takeError());
619 }
620 }
621
622 private:
623 SendSymbolAddressFn SendResult;
624 };
625
626 ES.lookup(
627 LookupKind::DLSym, {{JD, JITDylibLookupFlags::MatchExportedSymbolsOnly}},
628 SymbolLookupSet(ES.intern(SymbolName)), SymbolState::Ready,
629 RtLookupNotifyComplete(std::move(SendResult)), NoDependenciesToRegister);
630}
631
632Error COFFPlatform::associateRuntimeSupportFunctions(JITDylib &PlatformJD) {
633 ExecutionSession::JITDispatchHandlerAssociationMap WFs;
634
635 using LookupSymbolSPSSig =
636 SPSExpected<SPSExecutorAddr>(SPSExecutorAddr, SPSString);
637 WFs[ES.intern("__orc_rt_coff_symbol_lookup_tag")] =
638 ES.wrapAsyncWithSPS<LookupSymbolSPSSig>(this,
639 &COFFPlatform::rt_lookupSymbol);
640 using PushInitializersSPSSig =
641 SPSExpected<SPSCOFFJITDylibDepInfoMap>(SPSExecutorAddr);
642 WFs[ES.intern("__orc_rt_coff_push_initializers_tag")] =
643 ES.wrapAsyncWithSPS<PushInitializersSPSSig>(
644 this, &COFFPlatform::rt_pushInitializers);
645
646 return ES.registerJITDispatchHandlers(PlatformJD, std::move(WFs));
647}
648
649Error COFFPlatform::runBootstrapInitializers(JDBootstrapState &BState) {
650 llvm::sort(BState.Initializers);
651 if (auto Err =
652 runBootstrapSubsectionInitializers(BState, ".CRT$XIA", ".CRT$XIZ"))
653 return Err;
654
655 if (auto Err = runSymbolIfExists(*BState.JD, "__run_after_c_init"))
656 return Err;
657
658 if (auto Err =
659 runBootstrapSubsectionInitializers(BState, ".CRT$XCA", ".CRT$XCZ"))
660 return Err;
661 return Error::success();
662}
663
664Error COFFPlatform::runBootstrapSubsectionInitializers(JDBootstrapState &BState,
665 StringRef Start,
666 StringRef End) {
667 for (auto &Initializer : BState.Initializers)
668 if (Initializer.first >= Start && Initializer.first <= End &&
669 Initializer.second) {
670 auto Res =
671 ES.getExecutorProcessControl().runAsVoidFunction(Initializer.second);
672 if (!Res)
673 return Res.takeError();
674 }
675 return Error::success();
676}
677
678Error COFFPlatform::bootstrapCOFFRuntime(JITDylib &PlatformJD) {
679 // Lookup of runtime symbols causes the collection of initializers if
680 // it's static linking setting.
681 if (auto Err = lookupAndRecordAddrs(
682 ES, LookupKind::Static, makeJITDylibSearchOrder(&PlatformJD),
683 {
684 {ES.intern("__orc_rt_coff_platform_bootstrap"),
685 &orc_rt_coff_platform_bootstrap},
686 {ES.intern("__orc_rt_coff_platform_shutdown"),
687 &orc_rt_coff_platform_shutdown},
688 {ES.intern("__orc_rt_coff_register_jitdylib"),
689 &orc_rt_coff_register_jitdylib},
690 {ES.intern("__orc_rt_coff_deregister_jitdylib"),
691 &orc_rt_coff_deregister_jitdylib},
692 {ES.intern("__orc_rt_coff_register_object_sections"),
693 &orc_rt_coff_register_object_sections},
694 {ES.intern("__orc_rt_coff_deregister_object_sections"),
695 &orc_rt_coff_deregister_object_sections},
696 }))
697 return Err;
698
699 // Call bootstrap functions
700 if (auto Err = ES.callSPSWrapper<void()>(orc_rt_coff_platform_bootstrap))
701 return Err;
702
703 // Do the pending jitdylib registration actions that we couldn't do
704 // because orc runtime was not linked fully.
705 for (auto KV : JDBootstrapStates) {
706 auto &JDBState = KV.second;
707 if (auto Err = ES.callSPSWrapper<void(SPSString, SPSExecutorAddr)>(
708 orc_rt_coff_register_jitdylib, JDBState.JDName,
709 JDBState.HeaderAddr))
710 return Err;
711
712 for (auto &ObjSectionMap : JDBState.ObjectSectionsMaps)
713 if (auto Err = ES.callSPSWrapper<void(SPSExecutorAddr,
714 SPSCOFFObjectSectionsMap, bool)>(
715 orc_rt_coff_register_object_sections, JDBState.HeaderAddr,
716 ObjSectionMap, false))
717 return Err;
718 }
719
720 // Run static initializers collected in bootstrap stage.
721 for (auto KV : JDBootstrapStates) {
722 auto &JDBState = KV.second;
723 if (auto Err = runBootstrapInitializers(JDBState))
724 return Err;
725 }
726
727 return Error::success();
728}
729
730Error COFFPlatform::runSymbolIfExists(JITDylib &PlatformJD,
731 StringRef SymbolName) {
732 ExecutorAddr jit_function;
733 auto AfterCLookupErr = lookupAndRecordAddrs(
734 ES, LookupKind::Static, makeJITDylibSearchOrder(&PlatformJD),
735 {{ES.intern(SymbolName), &jit_function}});
736 if (!AfterCLookupErr) {
737 auto Res = ES.getExecutorProcessControl().runAsVoidFunction(jit_function);
738 if (!Res)
739 return Res.takeError();
740 return Error::success();
741 }
742 if (!AfterCLookupErr.isA<SymbolsNotFound>())
743 return AfterCLookupErr;
744 consumeError(std::move(AfterCLookupErr));
745 return Error::success();
746}
747
748void COFFPlatform::COFFPlatformPlugin::modifyPassConfig(
749 MaterializationResponsibility &MR, jitlink::LinkGraph &LG,
750 jitlink::PassConfiguration &Config) {
751
752 bool IsBootstrapping = CP.Bootstrapping.load();
753
754 if (auto InitSymbol = MR.getInitializerSymbol()) {
755 if (InitSymbol == CP.COFFHeaderStartSymbol) {
756 Config.PostAllocationPasses.push_back(
757 [this, &MR, IsBootstrapping](jitlink::LinkGraph &G) {
758 return associateJITDylibHeaderSymbol(G, MR, IsBootstrapping);
759 });
760 return;
761 }
762 Config.PrePrunePasses.push_back([this, &MR](jitlink::LinkGraph &G) {
763 return preserveInitializerSections(G, MR);
764 });
765 }
766
767 if (!IsBootstrapping)
768 Config.PostFixupPasses.push_back(
769 [this, &JD = MR.getTargetJITDylib()](jitlink::LinkGraph &G) {
770 return registerObjectPlatformSections(G, JD);
771 });
772 else
773 Config.PostFixupPasses.push_back(
774 [this, &JD = MR.getTargetJITDylib()](jitlink::LinkGraph &G) {
775 return registerObjectPlatformSectionsInBootstrap(G, JD);
776 });
777}
778
779ObjectLinkingLayer::Plugin::SyntheticSymbolDependenciesMap
780COFFPlatform::COFFPlatformPlugin::getSyntheticSymbolDependencies(
781 MaterializationResponsibility &MR) {
782 std::lock_guard<std::mutex> Lock(PluginMutex);
783 auto I = InitSymbolDeps.find(&MR);
784 if (I != InitSymbolDeps.end()) {
785 SyntheticSymbolDependenciesMap Result;
786 Result[MR.getInitializerSymbol()] = std::move(I->second);
787 InitSymbolDeps.erase(&MR);
788 return Result;
789 }
790 return SyntheticSymbolDependenciesMap();
791}
792
793Error COFFPlatform::COFFPlatformPlugin::associateJITDylibHeaderSymbol(
794 jitlink::LinkGraph &G, MaterializationResponsibility &MR,
795 bool IsBootstraping) {
796 auto I = llvm::find_if(G.defined_symbols(), [this](jitlink::Symbol *Sym) {
797 return Sym->getName() == *CP.COFFHeaderStartSymbol;
798 });
799 assert(I != G.defined_symbols().end() && "Missing COFF header start symbol")(static_cast <bool> (I != G.defined_symbols().end() &&
"Missing COFF header start symbol") ? void (0) : __assert_fail
("I != G.defined_symbols().end() && \"Missing COFF header start symbol\""
, "llvm/lib/ExecutionEngine/Orc/COFFPlatform.cpp", 799, __extension__
__PRETTY_FUNCTION__))
;
800
801 auto &JD = MR.getTargetJITDylib();
802 std::lock_guard<std::mutex> Lock(CP.PlatformMutex);
803 auto HeaderAddr = (*I)->getAddress();
804 CP.JITDylibToHeaderAddr[&JD] = HeaderAddr;
805 CP.HeaderAddrToJITDylib[HeaderAddr] = &JD;
806 if (!IsBootstraping) {
807 G.allocActions().push_back(
808 {cantFail(WrapperFunctionCall::Create<
809 SPSArgList<SPSString, SPSExecutorAddr>>(
810 CP.orc_rt_coff_register_jitdylib, JD.getName(), HeaderAddr)),
811 cantFail(WrapperFunctionCall::Create<SPSArgList<SPSExecutorAddr>>(
812 CP.orc_rt_coff_deregister_jitdylib, HeaderAddr))});
813 } else {
814 G.allocActions().push_back(
815 {{},
816 cantFail(WrapperFunctionCall::Create<SPSArgList<SPSExecutorAddr>>(
817 CP.orc_rt_coff_deregister_jitdylib, HeaderAddr))});
818 JDBootstrapState BState;
819 BState.JD = &JD;
820 BState.JDName = JD.getName();
821 BState.HeaderAddr = HeaderAddr;
822 CP.JDBootstrapStates.emplace(&JD, BState);
823 }
824
825 return Error::success();
826}
827
828Error COFFPlatform::COFFPlatformPlugin::registerObjectPlatformSections(
829 jitlink::LinkGraph &G, JITDylib &JD) {
830 COFFObjectSectionsMap ObjSecs;
831 auto HeaderAddr = CP.JITDylibToHeaderAddr[&JD];
832 assert(HeaderAddr && "Must be registered jitdylib")(static_cast <bool> (HeaderAddr && "Must be registered jitdylib"
) ? void (0) : __assert_fail ("HeaderAddr && \"Must be registered jitdylib\""
, "llvm/lib/ExecutionEngine/Orc/COFFPlatform.cpp", 832, __extension__
__PRETTY_FUNCTION__))
;
833 for (auto &S : G.sections()) {
834 jitlink::SectionRange Range(S);
835 if (Range.getSize())
836 ObjSecs.push_back(std::make_pair(S.getName().str(), Range.getRange()));
837 }
838
839 G.allocActions().push_back(
840 {cantFail(WrapperFunctionCall::Create<SPSCOFFRegisterObjectSectionsArgs>(
841 CP.orc_rt_coff_register_object_sections, HeaderAddr, ObjSecs, true)),
842 cantFail(
843 WrapperFunctionCall::Create<SPSCOFFDeregisterObjectSectionsArgs>(
844 CP.orc_rt_coff_deregister_object_sections, HeaderAddr,
845 ObjSecs))});
846
847 return Error::success();
848}
849
850Error COFFPlatform::COFFPlatformPlugin::preserveInitializerSections(
851 jitlink::LinkGraph &G, MaterializationResponsibility &MR) {
852 JITLinkSymbolSet InitSectionSymbols;
853 for (auto &Sec : G.sections())
854 if (isCOFFInitializerSection(Sec.getName()))
855 for (auto *B : Sec.blocks())
856 if (!B->edges_empty())
857 InitSectionSymbols.insert(
858 &G.addAnonymousSymbol(*B, 0, 0, false, true));
859
860 std::lock_guard<std::mutex> Lock(PluginMutex);
861 InitSymbolDeps[&MR] = InitSectionSymbols;
862 return Error::success();
863}
864
865Error COFFPlatform::COFFPlatformPlugin::
866 registerObjectPlatformSectionsInBootstrap(jitlink::LinkGraph &G,
867 JITDylib &JD) {
868 std::lock_guard<std::mutex> Lock(CP.PlatformMutex);
869 auto HeaderAddr = CP.JITDylibToHeaderAddr[&JD];
870 COFFObjectSectionsMap ObjSecs;
871 for (auto &S : G.sections()) {
872 jitlink::SectionRange Range(S);
873 if (Range.getSize())
874 ObjSecs.push_back(std::make_pair(S.getName().str(), Range.getRange()));
875 }
876
877 G.allocActions().push_back(
878 {{},
879 cantFail(
880 WrapperFunctionCall::Create<SPSCOFFDeregisterObjectSectionsArgs>(
881 CP.orc_rt_coff_deregister_object_sections, HeaderAddr,
882 ObjSecs))});
883
884 auto &BState = CP.JDBootstrapStates[&JD];
885 BState.ObjectSectionsMaps.push_back(std::move(ObjSecs));
886
887 // Collect static initializers
888 for (auto &S : G.sections())
889 if (isCOFFInitializerSection(S.getName()))
890 for (auto *B : S.blocks()) {
891 if (B->edges_empty())
892 continue;
893 for (auto &E : B->edges())
894 BState.Initializers.push_back(std::make_pair(
895 S.getName().str(),
896 ExecutorAddr(E.getTarget().getAddress() + E.getAddend())));
897 }
898
899 return Error::success();
900}
901
902} // End namespace orc.
903} // End namespace llvm.

/build/source/llvm/include/llvm/ExecutionEngine/Orc/Core.h

1//===------ Core.h -- Core ORC APIs (Layer, JITDylib, etc.) -----*- C++ -*-===//
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// Contains core ORC APIs.
10//
11//===----------------------------------------------------------------------===//
12
13#ifndef LLVM_EXECUTIONENGINE_ORC_CORE_H
14#define LLVM_EXECUTIONENGINE_ORC_CORE_H
15
16#include "llvm/ADT/BitmaskEnum.h"
17#include "llvm/ADT/DenseSet.h"
18#include "llvm/ADT/FunctionExtras.h"
19#include "llvm/ADT/IntrusiveRefCntPtr.h"
20#include "llvm/ExecutionEngine/JITLink/JITLinkDylib.h"
21#include "llvm/ExecutionEngine/JITSymbol.h"
22#include "llvm/ExecutionEngine/Orc/ExecutorProcessControl.h"
23#include "llvm/ExecutionEngine/Orc/Shared/WrapperFunctionUtils.h"
24#include "llvm/ExecutionEngine/Orc/TaskDispatch.h"
25#include "llvm/Support/Debug.h"
26#include "llvm/Support/ExtensibleRTTI.h"
27
28#include <atomic>
29#include <future>
30#include <memory>
31#include <vector>
32
33namespace llvm {
34namespace orc {
35
36// Forward declare some classes.
37class AsynchronousSymbolQuery;
38class ExecutionSession;
39class MaterializationUnit;
40class MaterializationResponsibility;
41class JITDylib;
42class ResourceTracker;
43class InProgressLookupState;
44
45enum class SymbolState : uint8_t;
46
47using ResourceTrackerSP = IntrusiveRefCntPtr<ResourceTracker>;
48using JITDylibSP = IntrusiveRefCntPtr<JITDylib>;
49
50using ResourceKey = uintptr_t;
51
52/// API to remove / transfer ownership of JIT resources.
53class ResourceTracker : public ThreadSafeRefCountedBase<ResourceTracker> {
54private:
55 friend class ExecutionSession;
56 friend class JITDylib;
57 friend class MaterializationResponsibility;
58
59public:
60 ResourceTracker(const ResourceTracker &) = delete;
61 ResourceTracker &operator=(const ResourceTracker &) = delete;
62 ResourceTracker(ResourceTracker &&) = delete;
63 ResourceTracker &operator=(ResourceTracker &&) = delete;
64
65 ~ResourceTracker();
66
67 /// Return the JITDylib targeted by this tracker.
68 JITDylib &getJITDylib() const {
69 return *reinterpret_cast<JITDylib *>(JDAndFlag.load() &
70 ~static_cast<uintptr_t>(1));
71 }
72
73 /// Runs the given callback under the session lock, passing in the associated
74 /// ResourceKey. This is the safe way to associate resources with trackers.
75 template <typename Func> Error withResourceKeyDo(Func &&F);
76
77 /// Remove all resources associated with this key.
78 Error remove();
79
80 /// Transfer all resources associated with this key to the given
81 /// tracker, which must target the same JITDylib as this one.
82 void transferTo(ResourceTracker &DstRT);
83
84 /// Return true if this tracker has become defunct.
85 bool isDefunct() const { return JDAndFlag.load() & 0x1; }
86
87 /// Returns the key associated with this tracker.
88 /// This method should not be used except for debug logging: there is no
89 /// guarantee that the returned value will remain valid.
90 ResourceKey getKeyUnsafe() const { return reinterpret_cast<uintptr_t>(this); }
91
92private:
93 ResourceTracker(JITDylibSP JD);
94
95 void makeDefunct();
96
97 std::atomic_uintptr_t JDAndFlag;
98};
99
100/// Listens for ResourceTracker operations.
101class ResourceManager {
102public:
103 virtual ~ResourceManager();
104 virtual Error handleRemoveResources(JITDylib &JD, ResourceKey K) = 0;
105 virtual void handleTransferResources(JITDylib &JD, ResourceKey DstK,
106 ResourceKey SrcK) = 0;
107};
108
109/// A set of symbol names (represented by SymbolStringPtrs for
110// efficiency).
111using SymbolNameSet = DenseSet<SymbolStringPtr>;
112
113/// A vector of symbol names.
114using SymbolNameVector = std::vector<SymbolStringPtr>;
115
116/// A map from symbol names (as SymbolStringPtrs) to JITSymbols
117/// (address/flags pairs).
118using SymbolMap = DenseMap<SymbolStringPtr, JITEvaluatedSymbol>;
119
120/// A map from symbol names (as SymbolStringPtrs) to JITSymbolFlags.
121using SymbolFlagsMap = DenseMap<SymbolStringPtr, JITSymbolFlags>;
122
123/// A map from JITDylibs to sets of symbols.
124using SymbolDependenceMap = DenseMap<JITDylib *, SymbolNameSet>;
125
126/// Lookup flags that apply to each dylib in the search order for a lookup.
127///
128/// If MatchHiddenSymbolsOnly is used (the default) for a given dylib, then
129/// only symbols in that Dylib's interface will be searched. If
130/// MatchHiddenSymbols is used then symbols with hidden visibility will match
131/// as well.
132enum class JITDylibLookupFlags { MatchExportedSymbolsOnly, MatchAllSymbols };
133
134/// Lookup flags that apply to each symbol in a lookup.
135///
136/// If RequiredSymbol is used (the default) for a given symbol then that symbol
137/// must be found during the lookup or the lookup will fail returning a
138/// SymbolNotFound error. If WeaklyReferencedSymbol is used and the given
139/// symbol is not found then the query will continue, and no result for the
140/// missing symbol will be present in the result (assuming the rest of the
141/// lookup succeeds).
142enum class SymbolLookupFlags { RequiredSymbol, WeaklyReferencedSymbol };
143
144/// Describes the kind of lookup being performed. The lookup kind is passed to
145/// symbol generators (if they're invoked) to help them determine what
146/// definitions to generate.
147///
148/// Static -- Lookup is being performed as-if at static link time (e.g.
149/// generators representing static archives should pull in new
150/// definitions).
151///
152/// DLSym -- Lookup is being performed as-if at runtime (e.g. generators
153/// representing static archives should not pull in new definitions).
154enum class LookupKind { Static, DLSym };
155
156/// A list of (JITDylib*, JITDylibLookupFlags) pairs to be used as a search
157/// order during symbol lookup.
158using JITDylibSearchOrder =
159 std::vector<std::pair<JITDylib *, JITDylibLookupFlags>>;
160
161/// Convenience function for creating a search order from an ArrayRef of
162/// JITDylib*, all with the same flags.
163inline JITDylibSearchOrder makeJITDylibSearchOrder(
164 ArrayRef<JITDylib *> JDs,
165 JITDylibLookupFlags Flags = JITDylibLookupFlags::MatchExportedSymbolsOnly) {
166 JITDylibSearchOrder O;
167 O.reserve(JDs.size());
168 for (auto *JD : JDs)
169 O.push_back(std::make_pair(JD, Flags));
170 return O;
171}
172
173/// A set of symbols to look up, each associated with a SymbolLookupFlags
174/// value.
175///
176/// This class is backed by a vector and optimized for fast insertion,
177/// deletion and iteration. It does not guarantee a stable order between
178/// operations, and will not automatically detect duplicate elements (they
179/// can be manually checked by calling the validate method).
180class SymbolLookupSet {
181public:
182 using value_type = std::pair<SymbolStringPtr, SymbolLookupFlags>;
183 using UnderlyingVector = std::vector<value_type>;
184 using iterator = UnderlyingVector::iterator;
185 using const_iterator = UnderlyingVector::const_iterator;
186
187 SymbolLookupSet() = default;
188
189 explicit SymbolLookupSet(
190 SymbolStringPtr Name,
191 SymbolLookupFlags Flags = SymbolLookupFlags::RequiredSymbol) {
192 add(std::move(Name), Flags);
193 }
194
195 /// Construct a SymbolLookupSet from an initializer list of SymbolStringPtrs.
196 explicit SymbolLookupSet(
197 std::initializer_list<SymbolStringPtr> Names,
198 SymbolLookupFlags Flags = SymbolLookupFlags::RequiredSymbol) {
199 Symbols.reserve(Names.size());
200 for (const auto &Name : Names)
201 add(std::move(Name), Flags);
202 }
203
204 /// Construct a SymbolLookupSet from a SymbolNameSet with the given
205 /// Flags used for each value.
206 explicit SymbolLookupSet(
207 const SymbolNameSet &Names,
208 SymbolLookupFlags Flags = SymbolLookupFlags::RequiredSymbol) {
209 Symbols.reserve(Names.size());
210 for (const auto &Name : Names)
211 add(Name, Flags);
212 }
213
214 /// Construct a SymbolLookupSet from a vector of symbols with the given Flags
215 /// used for each value.
216 /// If the ArrayRef contains duplicates it is up to the client to remove these
217 /// before using this instance for lookup.
218 explicit SymbolLookupSet(
219 ArrayRef<SymbolStringPtr> Names,
220 SymbolLookupFlags Flags = SymbolLookupFlags::RequiredSymbol) {
221 Symbols.reserve(Names.size());
222 for (const auto &Name : Names)
223 add(Name, Flags);
224 }
225
226 /// Construct a SymbolLookupSet from DenseMap keys.
227 template <typename KeyT>
228 static SymbolLookupSet
229 fromMapKeys(const DenseMap<SymbolStringPtr, KeyT> &M,
230 SymbolLookupFlags Flags = SymbolLookupFlags::RequiredSymbol) {
231 SymbolLookupSet Result;
232 Result.Symbols.reserve(M.size());
233 for (const auto &KV : M)
234 Result.add(KV.first, Flags);
235 return Result;
236 }
237
238 /// Add an element to the set. The client is responsible for checking that
239 /// duplicates are not added.
240 SymbolLookupSet &
241 add(SymbolStringPtr Name,
242 SymbolLookupFlags Flags = SymbolLookupFlags::RequiredSymbol) {
243 Symbols.push_back(std::make_pair(std::move(Name), Flags));
244 return *this;
245 }
246
247 /// Quickly append one lookup set to another.
248 SymbolLookupSet &append(SymbolLookupSet Other) {
249 Symbols.reserve(Symbols.size() + Other.size());
250 for (auto &KV : Other)
251 Symbols.push_back(std::move(KV));
252 return *this;
253 }
254
255 bool empty() const { return Symbols.empty(); }
256 UnderlyingVector::size_type size() const { return Symbols.size(); }
257 iterator begin() { return Symbols.begin(); }
258 iterator end() { return Symbols.end(); }
259 const_iterator begin() const { return Symbols.begin(); }
260 const_iterator end() const { return Symbols.end(); }
261
262 /// Removes the Ith element of the vector, replacing it with the last element.
263 void remove(UnderlyingVector::size_type I) {
264 std::swap(Symbols[I], Symbols.back());
265 Symbols.pop_back();
266 }
267
268 /// Removes the element pointed to by the given iterator. This iterator and
269 /// all subsequent ones (including end()) are invalidated.
270 void remove(iterator I) { remove(I - begin()); }
271
272 /// Removes all elements matching the given predicate, which must be callable
273 /// as bool(const SymbolStringPtr &, SymbolLookupFlags Flags).
274 template <typename PredFn> void remove_if(PredFn &&Pred) {
275 UnderlyingVector::size_type I = 0;
276 while (I != Symbols.size()) {
277 const auto &Name = Symbols[I].first;
278 auto Flags = Symbols[I].second;
279 if (Pred(Name, Flags))
280 remove(I);
281 else
282 ++I;
283 }
284 }
285
286 /// Loop over the elements of this SymbolLookupSet, applying the Body function
287 /// to each one. Body must be callable as
288 /// bool(const SymbolStringPtr &, SymbolLookupFlags).
289 /// If Body returns true then the element just passed in is removed from the
290 /// set. If Body returns false then the element is retained.
291 template <typename BodyFn>
292 auto forEachWithRemoval(BodyFn &&Body) -> std::enable_if_t<
293 std::is_same<decltype(Body(std::declval<const SymbolStringPtr &>(),
294 std::declval<SymbolLookupFlags>())),
295 bool>::value> {
296 UnderlyingVector::size_type I = 0;
297 while (I != Symbols.size()) {
298 const auto &Name = Symbols[I].first;
299 auto Flags = Symbols[I].second;
300 if (Body(Name, Flags))
301 remove(I);
302 else
303 ++I;
304 }
305 }
306
307 /// Loop over the elements of this SymbolLookupSet, applying the Body function
308 /// to each one. Body must be callable as
309 /// Expected<bool>(const SymbolStringPtr &, SymbolLookupFlags).
310 /// If Body returns a failure value, the loop exits immediately. If Body
311 /// returns true then the element just passed in is removed from the set. If
312 /// Body returns false then the element is retained.
313 template <typename BodyFn>
314 auto forEachWithRemoval(BodyFn &&Body) -> std::enable_if_t<
315 std::is_same<decltype(Body(std::declval<const SymbolStringPtr &>(),
316 std::declval<SymbolLookupFlags>())),
317 Expected<bool>>::value,
318 Error> {
319 UnderlyingVector::size_type I = 0;
320 while (I != Symbols.size()) {
321 const auto &Name = Symbols[I].first;
322 auto Flags = Symbols[I].second;
323 auto Remove = Body(Name, Flags);
324 if (!Remove)
325 return Remove.takeError();
326 if (*Remove)
327 remove(I);
328 else
329 ++I;
330 }
331 return Error::success();
332 }
333
334 /// Construct a SymbolNameVector from this instance by dropping the Flags
335 /// values.
336 SymbolNameVector getSymbolNames() const {
337 SymbolNameVector Names;
338 Names.reserve(Symbols.size());
339 for (const auto &KV : Symbols)
340 Names.push_back(KV.first);
341 return Names;
342 }
343
344 /// Sort the lookup set by pointer value. This sort is fast but sensitive to
345 /// allocation order and so should not be used where a consistent order is
346 /// required.
347 void sortByAddress() { llvm::sort(Symbols, llvm::less_first()); }
348
349 /// Sort the lookup set lexicographically. This sort is slow but the order
350 /// is unaffected by allocation order.
351 void sortByName() {
352 llvm::sort(Symbols, [](const value_type &LHS, const value_type &RHS) {
353 return *LHS.first < *RHS.first;
354 });
355 }
356
357 /// Remove any duplicate elements. If a SymbolLookupSet is not duplicate-free
358 /// by construction, this method can be used to turn it into a proper set.
359 void removeDuplicates() {
360 sortByAddress();
361 auto LastI = std::unique(Symbols.begin(), Symbols.end());
362 Symbols.erase(LastI, Symbols.end());
363 }
364
365#ifndef NDEBUG
366 /// Returns true if this set contains any duplicates. This should only be used
367 /// in assertions.
368 bool containsDuplicates() {
369 if (Symbols.size() < 2)
370 return false;
371 sortByAddress();
372 for (UnderlyingVector::size_type I = 1; I != Symbols.size(); ++I)
373 if (Symbols[I].first == Symbols[I - 1].first)
374 return true;
375 return false;
376 }
377#endif
378
379private:
380 UnderlyingVector Symbols;
381};
382
383struct SymbolAliasMapEntry {
384 SymbolAliasMapEntry() = default;
385 SymbolAliasMapEntry(SymbolStringPtr Aliasee, JITSymbolFlags AliasFlags)
386 : Aliasee(std::move(Aliasee)), AliasFlags(AliasFlags) {}
387
388 SymbolStringPtr Aliasee;
389 JITSymbolFlags AliasFlags;
390};
391
392/// A map of Symbols to (Symbol, Flags) pairs.
393using SymbolAliasMap = DenseMap<SymbolStringPtr, SymbolAliasMapEntry>;
394
395/// Callback to notify client that symbols have been resolved.
396using SymbolsResolvedCallback = unique_function<void(Expected<SymbolMap>)>;
397
398/// Callback to register the dependencies for a given query.
399using RegisterDependenciesFunction =
400 std::function<void(const SymbolDependenceMap &)>;
401
402/// This can be used as the value for a RegisterDependenciesFunction if there
403/// are no dependants to register with.
404extern RegisterDependenciesFunction NoDependenciesToRegister;
405
406class ResourceTrackerDefunct : public ErrorInfo<ResourceTrackerDefunct> {
407public:
408 static char ID;
409
410 ResourceTrackerDefunct(ResourceTrackerSP RT);
411 std::error_code convertToErrorCode() const override;
412 void log(raw_ostream &OS) const override;
413
414private:
415 ResourceTrackerSP RT;
416};
417
418/// Used to notify a JITDylib that the given set of symbols failed to
419/// materialize.
420class FailedToMaterialize : public ErrorInfo<FailedToMaterialize> {
421public:
422 static char ID;
423
424 FailedToMaterialize(std::shared_ptr<SymbolStringPool> SSP,
425 std::shared_ptr<SymbolDependenceMap> Symbols);
426 ~FailedToMaterialize();
427 std::error_code convertToErrorCode() const override;
428 void log(raw_ostream &OS) const override;
429 const SymbolDependenceMap &getSymbols() const { return *Symbols; }
430
431private:
432 std::shared_ptr<SymbolStringPool> SSP;
433 std::shared_ptr<SymbolDependenceMap> Symbols;
434};
435
436/// Used to notify clients when symbols can not be found during a lookup.
437class SymbolsNotFound : public ErrorInfo<SymbolsNotFound> {
438public:
439 static char ID;
440
441 SymbolsNotFound(std::shared_ptr<SymbolStringPool> SSP, SymbolNameSet Symbols);
442 SymbolsNotFound(std::shared_ptr<SymbolStringPool> SSP,
443 SymbolNameVector Symbols);
444 std::error_code convertToErrorCode() const override;
445 void log(raw_ostream &OS) const override;
446 std::shared_ptr<SymbolStringPool> getSymbolStringPool() { return SSP; }
447 const SymbolNameVector &getSymbols() const { return Symbols; }
448
449private:
450 std::shared_ptr<SymbolStringPool> SSP;
451 SymbolNameVector Symbols;
452};
453
454/// Used to notify clients that a set of symbols could not be removed.
455class SymbolsCouldNotBeRemoved : public ErrorInfo<SymbolsCouldNotBeRemoved> {
456public:
457 static char ID;
458
459 SymbolsCouldNotBeRemoved(std::shared_ptr<SymbolStringPool> SSP,
460 SymbolNameSet Symbols);
461 std::error_code convertToErrorCode() const override;
462 void log(raw_ostream &OS) const override;
463 std::shared_ptr<SymbolStringPool> getSymbolStringPool() { return SSP; }
464 const SymbolNameSet &getSymbols() const { return Symbols; }
465
466private:
467 std::shared_ptr<SymbolStringPool> SSP;
468 SymbolNameSet Symbols;
469};
470
471/// Errors of this type should be returned if a module fails to include
472/// definitions that are claimed by the module's associated
473/// MaterializationResponsibility. If this error is returned it is indicative of
474/// a broken transformation / compiler / object cache.
475class MissingSymbolDefinitions : public ErrorInfo<MissingSymbolDefinitions> {
476public:
477 static char ID;
478
479 MissingSymbolDefinitions(std::shared_ptr<SymbolStringPool> SSP,
480 std::string ModuleName, SymbolNameVector Symbols)
481 : SSP(std::move(SSP)), ModuleName(std::move(ModuleName)),
482 Symbols(std::move(Symbols)) {}
483 std::error_code convertToErrorCode() const override;
484 void log(raw_ostream &OS) const override;
485 std::shared_ptr<SymbolStringPool> getSymbolStringPool() { return SSP; }
486 const std::string &getModuleName() const { return ModuleName; }
487 const SymbolNameVector &getSymbols() const { return Symbols; }
488private:
489 std::shared_ptr<SymbolStringPool> SSP;
490 std::string ModuleName;
491 SymbolNameVector Symbols;
492};
493
494/// Errors of this type should be returned if a module contains definitions for
495/// symbols that are not claimed by the module's associated
496/// MaterializationResponsibility. If this error is returned it is indicative of
497/// a broken transformation / compiler / object cache.
498class UnexpectedSymbolDefinitions : public ErrorInfo<UnexpectedSymbolDefinitions> {
499public:
500 static char ID;
501
502 UnexpectedSymbolDefinitions(std::shared_ptr<SymbolStringPool> SSP,
503 std::string ModuleName, SymbolNameVector Symbols)
504 : SSP(std::move(SSP)), ModuleName(std::move(ModuleName)),
505 Symbols(std::move(Symbols)) {}
506 std::error_code convertToErrorCode() const override;
507 void log(raw_ostream &OS) const override;
508 std::shared_ptr<SymbolStringPool> getSymbolStringPool() { return SSP; }
509 const std::string &getModuleName() const { return ModuleName; }
510 const SymbolNameVector &getSymbols() const { return Symbols; }
511private:
512 std::shared_ptr<SymbolStringPool> SSP;
513 std::string ModuleName;
514 SymbolNameVector Symbols;
515};
516
517/// Tracks responsibility for materialization, and mediates interactions between
518/// MaterializationUnits and JDs.
519///
520/// An instance of this class is passed to MaterializationUnits when their
521/// materialize method is called. It allows MaterializationUnits to resolve and
522/// emit symbols, or abandon materialization by notifying any unmaterialized
523/// symbols of an error.
524class MaterializationResponsibility {
525 friend class ExecutionSession;
526 friend class JITDylib;
527
528public:
529 MaterializationResponsibility(MaterializationResponsibility &&) = delete;
530 MaterializationResponsibility &
531 operator=(MaterializationResponsibility &&) = delete;
532
533 /// Destruct a MaterializationResponsibility instance. In debug mode
534 /// this asserts that all symbols being tracked have been either
535 /// emitted or notified of an error.
536 ~MaterializationResponsibility();
537
538 /// Runs the given callback under the session lock, passing in the associated
539 /// ResourceKey. This is the safe way to associate resources with trackers.
540 template <typename Func> Error withResourceKeyDo(Func &&F) const {
541 return RT->withResourceKeyDo(std::forward<Func>(F));
542 }
543
544 /// Returns the target JITDylib that these symbols are being materialized
545 /// into.
546 JITDylib &getTargetJITDylib() const { return JD; }
547
548 /// Returns the ExecutionSession for this instance.
549 ExecutionSession &getExecutionSession() const;
550
551 /// Returns the symbol flags map for this responsibility instance.
552 /// Note: The returned flags may have transient flags (Lazy, Materializing)
553 /// set. These should be stripped with JITSymbolFlags::stripTransientFlags
554 /// before using.
555 const SymbolFlagsMap &getSymbols() const { return SymbolFlags; }
556
557 /// Returns the initialization pseudo-symbol, if any. This symbol will also
558 /// be present in the SymbolFlagsMap for this MaterializationResponsibility
559 /// object.
560 const SymbolStringPtr &getInitializerSymbol() const { return InitSymbol; }
561
562 /// Returns the names of any symbols covered by this
563 /// MaterializationResponsibility object that have queries pending. This
564 /// information can be used to return responsibility for unrequested symbols
565 /// back to the JITDylib via the delegate method.
566 SymbolNameSet getRequestedSymbols() const;
567
568 /// Notifies the target JITDylib that the given symbols have been resolved.
569 /// This will update the given symbols' addresses in the JITDylib, and notify
570 /// any pending queries on the given symbols of their resolution. The given
571 /// symbols must be ones covered by this MaterializationResponsibility
572 /// instance. Individual calls to this method may resolve a subset of the
573 /// symbols, but all symbols must have been resolved prior to calling emit.
574 ///
575 /// This method will return an error if any symbols being resolved have been
576 /// moved to the error state due to the failure of a dependency. If this
577 /// method returns an error then clients should log it and call
578 /// failMaterialize. If no dependencies have been registered for the
579 /// symbols covered by this MaterializationResponsibiility then this method
580 /// is guaranteed to return Error::success() and can be wrapped with cantFail.
581 Error notifyResolved(const SymbolMap &Symbols);
582
583 /// Notifies the target JITDylib (and any pending queries on that JITDylib)
584 /// that all symbols covered by this MaterializationResponsibility instance
585 /// have been emitted.
586 ///
587 /// This method will return an error if any symbols being resolved have been
588 /// moved to the error state due to the failure of a dependency. If this
589 /// method returns an error then clients should log it and call
590 /// failMaterialize. If no dependencies have been registered for the
591 /// symbols covered by this MaterializationResponsibiility then this method
592 /// is guaranteed to return Error::success() and can be wrapped with cantFail.
593 Error notifyEmitted();
594
595 /// Attempt to claim responsibility for new definitions. This method can be
596 /// used to claim responsibility for symbols that are added to a
597 /// materialization unit during the compilation process (e.g. literal pool
598 /// symbols). Symbol linkage rules are the same as for symbols that are
599 /// defined up front: duplicate strong definitions will result in errors.
600 /// Duplicate weak definitions will be discarded (in which case they will
601 /// not be added to this responsibility instance).
602 ///
603 /// This method can be used by materialization units that want to add
604 /// additional symbols at materialization time (e.g. stubs, compile
605 /// callbacks, metadata).
606 Error defineMaterializing(SymbolFlagsMap SymbolFlags);
607
608 /// Define the given symbols as non-existent, removing it from the symbol
609 /// table and notifying any pending queries. Queries that lookup up the
610 /// symbol using the SymbolLookupFlags::WeaklyReferencedSymbol flag will
611 /// behave as if the symbol had not been matched in the first place. Queries
612 /// that required this symbol will fail with a missing symbol definition
613 /// error.
614 ///
615 /// This method is intended to support cleanup of special symbols like
616 /// initializer symbols: Queries using
617 /// SymbolLookupFlags::WeaklyReferencedSymbol can be used to trigger their
618 /// emission, and this method can be used to remove them from the JITDylib
619 /// once materialization is complete.
620 void defineNonExistent(ArrayRef<SymbolStringPtr> Symbols);
621
622 /// Notify all not-yet-emitted covered by this MaterializationResponsibility
623 /// instance that an error has occurred.
624 /// This will remove all symbols covered by this MaterializationResponsibilty
625 /// from the target JITDylib, and send an error to any queries waiting on
626 /// these symbols.
627 void failMaterialization();
628
629 /// Transfers responsibility to the given MaterializationUnit for all
630 /// symbols defined by that MaterializationUnit. This allows
631 /// materializers to break up work based on run-time information (e.g.
632 /// by introspecting which symbols have actually been looked up and
633 /// materializing only those).
634 Error replace(std::unique_ptr<MaterializationUnit> MU);
635
636 /// Delegates responsibility for the given symbols to the returned
637 /// materialization responsibility. Useful for breaking up work between
638 /// threads, or different kinds of materialization processes.
639 Expected<std::unique_ptr<MaterializationResponsibility>>
640 delegate(const SymbolNameSet &Symbols);
641
642 void addDependencies(const SymbolStringPtr &Name,
643 const SymbolDependenceMap &Dependencies);
644
645 /// Add dependencies that apply to all symbols covered by this instance.
646 void addDependenciesForAll(const SymbolDependenceMap &Dependencies);
647
648private:
649 /// Create a MaterializationResponsibility for the given JITDylib and
650 /// initial symbols.
651 MaterializationResponsibility(ResourceTrackerSP RT,
652 SymbolFlagsMap SymbolFlags,
653 SymbolStringPtr InitSymbol)
654 : JD(RT->getJITDylib()), RT(std::move(RT)),
655 SymbolFlags(std::move(SymbolFlags)), InitSymbol(std::move(InitSymbol)) {
656 assert(!this->SymbolFlags.empty() && "Materializing nothing?")(static_cast <bool> (!this->SymbolFlags.empty() &&
"Materializing nothing?") ? void (0) : __assert_fail ("!this->SymbolFlags.empty() && \"Materializing nothing?\""
, "llvm/include/llvm/ExecutionEngine/Orc/Core.h", 656, __extension__
__PRETTY_FUNCTION__))
;
657 }
658
659 JITDylib &JD;
660 ResourceTrackerSP RT;
661 SymbolFlagsMap SymbolFlags;
662 SymbolStringPtr InitSymbol;
663};
664
665/// A MaterializationUnit represents a set of symbol definitions that can
666/// be materialized as a group, or individually discarded (when
667/// overriding definitions are encountered).
668///
669/// MaterializationUnits are used when providing lazy definitions of symbols to
670/// JITDylibs. The JITDylib will call materialize when the address of a symbol
671/// is requested via the lookup method. The JITDylib will call discard if a
672/// stronger definition is added or already present.
673class MaterializationUnit {
674 friend class ExecutionSession;
675 friend class JITDylib;
676
677public:
678 static char ID;
679
680 struct Interface {
681 Interface() = default;
682 Interface(SymbolFlagsMap InitalSymbolFlags, SymbolStringPtr InitSymbol)
683 : SymbolFlags(std::move(InitalSymbolFlags)),
684 InitSymbol(std::move(InitSymbol)) {
685 assert((!this->InitSymbol || this->SymbolFlags.count(this->InitSymbol)) &&(static_cast <bool> ((!this->InitSymbol || this->
SymbolFlags.count(this->InitSymbol)) && "If set, InitSymbol should appear in InitialSymbolFlags map"
) ? void (0) : __assert_fail ("(!this->InitSymbol || this->SymbolFlags.count(this->InitSymbol)) && \"If set, InitSymbol should appear in InitialSymbolFlags map\""
, "llvm/include/llvm/ExecutionEngine/Orc/Core.h", 686, __extension__
__PRETTY_FUNCTION__))
686 "If set, InitSymbol should appear in InitialSymbolFlags map")(static_cast <bool> ((!this->InitSymbol || this->
SymbolFlags.count(this->InitSymbol)) && "If set, InitSymbol should appear in InitialSymbolFlags map"
) ? void (0) : __assert_fail ("(!this->InitSymbol || this->SymbolFlags.count(this->InitSymbol)) && \"If set, InitSymbol should appear in InitialSymbolFlags map\""
, "llvm/include/llvm/ExecutionEngine/Orc/Core.h", 686, __extension__
__PRETTY_FUNCTION__))
;
687 }
688
689 SymbolFlagsMap SymbolFlags;
690 SymbolStringPtr InitSymbol;
691 };
692
693 MaterializationUnit(Interface I)
694 : SymbolFlags(std::move(I.SymbolFlags)),
695 InitSymbol(std::move(I.InitSymbol)) {}
696 virtual ~MaterializationUnit() = default;
697
698 /// Return the name of this materialization unit. Useful for debugging
699 /// output.
700 virtual StringRef getName() const = 0;
701
702 /// Return the set of symbols that this source provides.
703 const SymbolFlagsMap &getSymbols() const { return SymbolFlags; }
704
705 /// Returns the initialization symbol for this MaterializationUnit (if any).
706 const SymbolStringPtr &getInitializerSymbol() const { return InitSymbol; }
707
708 /// Implementations of this method should materialize all symbols
709 /// in the materialzation unit, except for those that have been
710 /// previously discarded.
711 virtual void
712 materialize(std::unique_ptr<MaterializationResponsibility> R) = 0;
713
714 /// Called by JITDylibs to notify MaterializationUnits that the given symbol
715 /// has been overridden.
716 void doDiscard(const JITDylib &JD, const SymbolStringPtr &Name) {
717 SymbolFlags.erase(Name);
718 if (InitSymbol == Name) {
719 DEBUG_WITH_TYPE("orc", {do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("orc")) { { dbgs() << "In " << getName() <<
": discarding init symbol \"" << *Name << "\"\n"
; }; } } while (false)
720 dbgs() << "In " << getName() << ": discarding init symbol \""do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("orc")) { { dbgs() << "In " << getName() <<
": discarding init symbol \"" << *Name << "\"\n"
; }; } } while (false)
721 << *Name << "\"\n";do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("orc")) { { dbgs() << "In " << getName() <<
": discarding init symbol \"" << *Name << "\"\n"
; }; } } while (false)
722 })do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("orc")) { { dbgs() << "In " << getName() <<
": discarding init symbol \"" << *Name << "\"\n"
; }; } } while (false)
;
723 InitSymbol = nullptr;
724 }
725 discard(JD, std::move(Name));
726 }
727
728protected:
729 SymbolFlagsMap SymbolFlags;
730 SymbolStringPtr InitSymbol;
731
732private:
733 virtual void anchor();
734
735 /// Implementations of this method should discard the given symbol
736 /// from the source (e.g. if the source is an LLVM IR Module and the
737 /// symbol is a function, delete the function body or mark it available
738 /// externally).
739 virtual void discard(const JITDylib &JD, const SymbolStringPtr &Name) = 0;
740};
741
742/// A MaterializationUnit implementation for pre-existing absolute symbols.
743///
744/// All symbols will be resolved and marked ready as soon as the unit is
745/// materialized.
746class AbsoluteSymbolsMaterializationUnit : public MaterializationUnit {
747public:
748 AbsoluteSymbolsMaterializationUnit(SymbolMap Symbols);
749
750 StringRef getName() const override;
751
752private:
753 void materialize(std::unique_ptr<MaterializationResponsibility> R) override;
754 void discard(const JITDylib &JD, const SymbolStringPtr &Name) override;
755 static MaterializationUnit::Interface extractFlags(const SymbolMap &Symbols);
756
757 SymbolMap Symbols;
758};
759
760/// Create an AbsoluteSymbolsMaterializationUnit with the given symbols.
761/// Useful for inserting absolute symbols into a JITDylib. E.g.:
762/// \code{.cpp}
763/// JITDylib &JD = ...;
764/// SymbolStringPtr Foo = ...;
765/// JITEvaluatedSymbol FooSym = ...;
766/// if (auto Err = JD.define(absoluteSymbols({{Foo, FooSym}})))
767/// return Err;
768/// \endcode
769///
770inline std::unique_ptr<AbsoluteSymbolsMaterializationUnit>
771absoluteSymbols(SymbolMap Symbols) {
772 return std::make_unique<AbsoluteSymbolsMaterializationUnit>(
773 std::move(Symbols));
774}
775
776/// A materialization unit for symbol aliases. Allows existing symbols to be
777/// aliased with alternate flags.
778class ReExportsMaterializationUnit : public MaterializationUnit {
779public:
780 /// SourceJD is allowed to be nullptr, in which case the source JITDylib is
781 /// taken to be whatever JITDylib these definitions are materialized in (and
782 /// MatchNonExported has no effect). This is useful for defining aliases
783 /// within a JITDylib.
784 ///
785 /// Note: Care must be taken that no sets of aliases form a cycle, as such
786 /// a cycle will result in a deadlock when any symbol in the cycle is
787 /// resolved.
788 ReExportsMaterializationUnit(JITDylib *SourceJD,
789 JITDylibLookupFlags SourceJDLookupFlags,
790 SymbolAliasMap Aliases);
791
792 StringRef getName() const override;
793
794private:
795 void materialize(std::unique_ptr<MaterializationResponsibility> R) override;
796 void discard(const JITDylib &JD, const SymbolStringPtr &Name) override;
797 static MaterializationUnit::Interface
798 extractFlags(const SymbolAliasMap &Aliases);
799
800 JITDylib *SourceJD = nullptr;
801 JITDylibLookupFlags SourceJDLookupFlags;
802 SymbolAliasMap Aliases;
803};
804
805/// Create a ReExportsMaterializationUnit with the given aliases.
806/// Useful for defining symbol aliases.: E.g., given a JITDylib JD containing
807/// symbols "foo" and "bar", we can define aliases "baz" (for "foo") and "qux"
808/// (for "bar") with: \code{.cpp}
809/// SymbolStringPtr Baz = ...;
810/// SymbolStringPtr Qux = ...;
811/// if (auto Err = JD.define(symbolAliases({
812/// {Baz, { Foo, JITSymbolFlags::Exported }},
813/// {Qux, { Bar, JITSymbolFlags::Weak }}}))
814/// return Err;
815/// \endcode
816inline std::unique_ptr<ReExportsMaterializationUnit>
817symbolAliases(SymbolAliasMap Aliases) {
818 return std::make_unique<ReExportsMaterializationUnit>(
819 nullptr, JITDylibLookupFlags::MatchAllSymbols, std::move(Aliases));
820}
821
822/// Create a materialization unit for re-exporting symbols from another JITDylib
823/// with alternative names/flags.
824/// SourceJD will be searched using the given JITDylibLookupFlags.
825inline std::unique_ptr<ReExportsMaterializationUnit>
826reexports(JITDylib &SourceJD, SymbolAliasMap Aliases,
827 JITDylibLookupFlags SourceJDLookupFlags =
828 JITDylibLookupFlags::MatchExportedSymbolsOnly) {
829 return std::make_unique<ReExportsMaterializationUnit>(
830 &SourceJD, SourceJDLookupFlags, std::move(Aliases));
831}
832
833/// Build a SymbolAliasMap for the common case where you want to re-export
834/// symbols from another JITDylib with the same linkage/flags.
835Expected<SymbolAliasMap>
836buildSimpleReexportsAliasMap(JITDylib &SourceJD, const SymbolNameSet &Symbols);
837
838/// Represents the state that a symbol has reached during materialization.
839enum class SymbolState : uint8_t {
840 Invalid, /// No symbol should be in this state.
841 NeverSearched, /// Added to the symbol table, never queried.
842 Materializing, /// Queried, materialization begun.
843 Resolved, /// Assigned address, still materializing.
844 Emitted, /// Emitted to memory, but waiting on transitive dependencies.
845 Ready = 0x3f /// Ready and safe for clients to access.
846};
847
848/// A symbol query that returns results via a callback when results are
849/// ready.
850///
851/// makes a callback when all symbols are available.
852class AsynchronousSymbolQuery {
853 friend class ExecutionSession;
854 friend class InProgressFullLookupState;
855 friend class JITDylib;
856 friend class JITSymbolResolverAdapter;
857 friend class MaterializationResponsibility;
858
859public:
860 /// Create a query for the given symbols. The NotifyComplete
861 /// callback will be called once all queried symbols reach the given
862 /// minimum state.
863 AsynchronousSymbolQuery(const SymbolLookupSet &Symbols,
864 SymbolState RequiredState,
865 SymbolsResolvedCallback NotifyComplete);
866
867 /// Notify the query that a requested symbol has reached the required state.
868 void notifySymbolMetRequiredState(const SymbolStringPtr &Name,
869 JITEvaluatedSymbol Sym);
870
871 /// Returns true if all symbols covered by this query have been
872 /// resolved.
873 bool isComplete() const { return OutstandingSymbolsCount == 0; }
874
875
876private:
877 void handleComplete(ExecutionSession &ES);
878
879 SymbolState getRequiredState() { return RequiredState; }
880
881 void addQueryDependence(JITDylib &JD, SymbolStringPtr Name);
882
883 void removeQueryDependence(JITDylib &JD, const SymbolStringPtr &Name);
884
885 void dropSymbol(const SymbolStringPtr &Name);
886
887 void handleFailed(Error Err);
888
889 void detach();
890
891 SymbolsResolvedCallback NotifyComplete;
892 SymbolDependenceMap QueryRegistrations;
893 SymbolMap ResolvedSymbols;
894 size_t OutstandingSymbolsCount;
895 SymbolState RequiredState;
896};
897
898/// Wraps state for a lookup-in-progress.
899/// DefinitionGenerators can optionally take ownership of a LookupState object
900/// to suspend a lookup-in-progress while they search for definitions.
901class LookupState {
902 friend class OrcV2CAPIHelper;
903 friend class ExecutionSession;
904
905public:
906 LookupState();
907 LookupState(LookupState &&);
908 LookupState &operator=(LookupState &&);
909 ~LookupState();
910
911 /// Continue the lookup. This can be called by DefinitionGenerators
912 /// to re-start a captured query-application operation.
913 void continueLookup(Error Err);
914
915private:
916 LookupState(std::unique_ptr<InProgressLookupState> IPLS);
917
918 // For C API.
919 void reset(InProgressLookupState *IPLS);
920
921 std::unique_ptr<InProgressLookupState> IPLS;
922};
923
924/// Definition generators can be attached to JITDylibs to generate new
925/// definitions for otherwise unresolved symbols during lookup.
926class DefinitionGenerator {
927public:
928 virtual ~DefinitionGenerator();
929
930 /// DefinitionGenerators should override this method to insert new
931 /// definitions into the parent JITDylib. K specifies the kind of this
932 /// lookup. JD specifies the target JITDylib being searched, and
933 /// JDLookupFlags specifies whether the search should match against
934 /// hidden symbols. Finally, Symbols describes the set of unresolved
935 /// symbols and their associated lookup flags.
936 virtual Error tryToGenerate(LookupState &LS, LookupKind K, JITDylib &JD,
937 JITDylibLookupFlags JDLookupFlags,
938 const SymbolLookupSet &LookupSet) = 0;
939};
940
941/// Represents a JIT'd dynamic library.
942///
943/// This class aims to mimic the behavior of a regular dylib or shared object,
944/// but without requiring the contained program representations to be compiled
945/// up-front. The JITDylib's content is defined by adding MaterializationUnits,
946/// and contained MaterializationUnits will typically rely on the JITDylib's
947/// links-against order to resolve external references (similar to a regular
948/// dylib).
949///
950/// The JITDylib object is a thin wrapper that references state held by the
951/// ExecutionSession. JITDylibs can be removed, clearing this underlying state
952/// and leaving the JITDylib object in a defunct state. In this state the
953/// JITDylib's name is guaranteed to remain accessible. If the ExecutionSession
954/// is still alive then other operations are callable but will return an Error
955/// or null result (depending on the API). It is illegal to call any operation
956/// other than getName on a JITDylib after the ExecutionSession has been torn
957/// down.
958///
959/// JITDylibs cannot be moved or copied. Their address is stable, and useful as
960/// a key in some JIT data structures.
961class JITDylib : public ThreadSafeRefCountedBase<JITDylib>,
962 public jitlink::JITLinkDylib {
963 friend class AsynchronousSymbolQuery;
964 friend class ExecutionSession;
965 friend class Platform;
966 friend class MaterializationResponsibility;
967public:
968
969 JITDylib(const JITDylib &) = delete;
970 JITDylib &operator=(const JITDylib &) = delete;
971 JITDylib(JITDylib &&) = delete;
972 JITDylib &operator=(JITDylib &&) = delete;
973 ~JITDylib();
974
975 /// Get a reference to the ExecutionSession for this JITDylib.
976 ///
977 /// It is legal to call this method on a defunct JITDylib, however the result
978 /// will only usable if the ExecutionSession is still alive. If this JITDylib
979 /// is held by an error that may have torn down the JIT then the result
980 /// should not be used.
981 ExecutionSession &getExecutionSession() const { return ES; }
982
983 /// Dump current JITDylib state to OS.
984 ///
985 /// It is legal to call this method on a defunct JITDylib.
986 void dump(raw_ostream &OS);
987
988 /// Calls remove on all trackers currently associated with this JITDylib.
989 /// Does not run static deinits.
990 ///
991 /// Note that removal happens outside the session lock, so new code may be
992 /// added concurrently while the clear is underway, and the newly added
993 /// code will *not* be cleared. Adding new code concurrently with a clear
994 /// is usually a bug and should be avoided.
995 ///
996 /// It is illegal to call this method on a defunct JITDylib and the client
997 /// is responsible for ensuring that they do not do so.
998 Error clear();
999
1000 /// Get the default resource tracker for this JITDylib.
1001 ///
1002 /// It is illegal to call this method on a defunct JITDylib and the client
1003 /// is responsible for ensuring that they do not do so.
1004 ResourceTrackerSP getDefaultResourceTracker();
1005
1006 /// Create a resource tracker for this JITDylib.
1007 ///
1008 /// It is illegal to call this method on a defunct JITDylib and the client
1009 /// is responsible for ensuring that they do not do so.
1010 ResourceTrackerSP createResourceTracker();
1011
1012 /// Adds a definition generator to this JITDylib and returns a referenece to
1013 /// it.
1014 ///
1015 /// When JITDylibs are searched during lookup, if no existing definition of
1016 /// a symbol is found, then any generators that have been added are run (in
1017 /// the order that they were added) to potentially generate a definition.
1018 ///
1019 /// It is illegal to call this method on a defunct JITDylib and the client
1020 /// is responsible for ensuring that they do not do so.
1021 template <typename GeneratorT>
1022 GeneratorT &addGenerator(std::unique_ptr<GeneratorT> DefGenerator);
1023
1024 /// Remove a definition generator from this JITDylib.
1025 ///
1026 /// The given generator must exist in this JITDylib's generators list (i.e.
1027 /// have been added and not yet removed).
1028 ///
1029 /// It is illegal to call this method on a defunct JITDylib and the client
1030 /// is responsible for ensuring that they do not do so.
1031 void removeGenerator(DefinitionGenerator &G);
1032
1033 /// Set the link order to be used when fixing up definitions in JITDylib.
1034 /// This will replace the previous link order, and apply to any symbol
1035 /// resolutions made for definitions in this JITDylib after the call to
1036 /// setLinkOrder (even if the definition itself was added before the
1037 /// call).
1038 ///
1039 /// If LinkAgainstThisJITDylibFirst is true (the default) then this JITDylib
1040 /// will add itself to the beginning of the LinkOrder (Clients should not
1041 /// put this JITDylib in the list in this case, to avoid redundant lookups).
1042 ///
1043 /// If LinkAgainstThisJITDylibFirst is false then the link order will be used
1044 /// as-is. The primary motivation for this feature is to support deliberate
1045 /// shadowing of symbols in this JITDylib by a facade JITDylib. For example,
1046 /// the facade may resolve function names to stubs, and the stubs may compile
1047 /// lazily by looking up symbols in this dylib. Adding the facade dylib
1048 /// as the first in the link order (instead of this dylib) ensures that
1049 /// definitions within this dylib resolve to the lazy-compiling stubs,
1050 /// rather than immediately materializing the definitions in this dylib.
1051 ///
1052 /// It is illegal to call this method on a defunct JITDylib and the client
1053 /// is responsible for ensuring that they do not do so.
1054 void setLinkOrder(JITDylibSearchOrder NewSearchOrder,
1055 bool LinkAgainstThisJITDylibFirst = true);
1056
1057 /// Add the given JITDylib to the link order for definitions in this
1058 /// JITDylib.
1059 ///
1060 /// It is illegal to call this method on a defunct JITDylib and the client
1061 /// is responsible for ensuring that they do not do so.
1062 void addToLinkOrder(JITDylib &JD,
1063 JITDylibLookupFlags JDLookupFlags =
1064 JITDylibLookupFlags::MatchExportedSymbolsOnly);
1065
1066 /// Replace OldJD with NewJD in the link order if OldJD is present.
1067 /// Otherwise this operation is a no-op.
1068 ///
1069 /// It is illegal to call this method on a defunct JITDylib and the client
1070 /// is responsible for ensuring that they do not do so.
1071 void replaceInLinkOrder(JITDylib &OldJD, JITDylib &NewJD,
1072 JITDylibLookupFlags JDLookupFlags =
1073 JITDylibLookupFlags::MatchExportedSymbolsOnly);
1074
1075 /// Remove the given JITDylib from the link order for this JITDylib if it is
1076 /// present. Otherwise this operation is a no-op.
1077 ///
1078 /// It is illegal to call this method on a defunct JITDylib and the client
1079 /// is responsible for ensuring that they do not do so.
1080 void removeFromLinkOrder(JITDylib &JD);
1081
1082 /// Do something with the link order (run under the session lock).
1083 ///
1084 /// It is illegal to call this method on a defunct JITDylib and the client
1085 /// is responsible for ensuring that they do not do so.
1086 template <typename Func>
1087 auto withLinkOrderDo(Func &&F)
1088 -> decltype(F(std::declval<const JITDylibSearchOrder &>()));
1089
1090 /// Define all symbols provided by the materialization unit to be part of this
1091 /// JITDylib.
1092 ///
1093 /// If RT is not specified then the default resource tracker will be used.
1094 ///
1095 /// This overload always takes ownership of the MaterializationUnit. If any
1096 /// errors occur, the MaterializationUnit consumed.
1097 ///
1098 /// It is illegal to call this method on a defunct JITDylib and the client
1099 /// is responsible for ensuring that they do not do so.
1100 template <typename MaterializationUnitType>
1101 Error define(std::unique_ptr<MaterializationUnitType> &&MU,
1102 ResourceTrackerSP RT = nullptr);
1103
1104 /// Define all symbols provided by the materialization unit to be part of this
1105 /// JITDylib.
1106 ///
1107 /// This overload only takes ownership of the MaterializationUnit no error is
1108 /// generated. If an error occurs, ownership remains with the caller. This
1109 /// may allow the caller to modify the MaterializationUnit to correct the
1110 /// issue, then re-call define.
1111 ///
1112 /// It is illegal to call this method on a defunct JITDylib and the client
1113 /// is responsible for ensuring that they do not do so.
1114 template <typename MaterializationUnitType>
1115 Error define(std::unique_ptr<MaterializationUnitType> &MU,
1116 ResourceTrackerSP RT = nullptr);
1117
1118 /// Tries to remove the given symbols.
1119 ///
1120 /// If any symbols are not defined in this JITDylib this method will return
1121 /// a SymbolsNotFound error covering the missing symbols.
1122 ///
1123 /// If all symbols are found but some symbols are in the process of being
1124 /// materialized this method will return a SymbolsCouldNotBeRemoved error.
1125 ///
1126 /// On success, all symbols are removed. On failure, the JITDylib state is
1127 /// left unmodified (no symbols are removed).
1128 ///
1129 /// It is illegal to call this method on a defunct JITDylib and the client
1130 /// is responsible for ensuring that they do not do so.
1131 Error remove(const SymbolNameSet &Names);
1132
1133 /// Returns the given JITDylibs and all of their transitive dependencies in
1134 /// DFS order (based on linkage relationships). Each JITDylib will appear
1135 /// only once.
1136 ///
1137 /// If any JITDylib in the order is defunct then this method will return an
1138 /// error, otherwise returns the order.
1139 static Expected<std::vector<JITDylibSP>>
1140 getDFSLinkOrder(ArrayRef<JITDylibSP> JDs);
1141
1142 /// Returns the given JITDylibs and all of their transitive dependencies in
1143 /// reverse DFS order (based on linkage relationships). Each JITDylib will
1144 /// appear only once.
1145 ///
1146 /// If any JITDylib in the order is defunct then this method will return an
1147 /// error, otherwise returns the order.
1148 static Expected<std::vector<JITDylibSP>>
1149 getReverseDFSLinkOrder(ArrayRef<JITDylibSP> JDs);
1150
1151 /// Return this JITDylib and its transitive dependencies in DFS order
1152 /// based on linkage relationships.
1153 ///
1154 /// If any JITDylib in the order is defunct then this method will return an
1155 /// error, otherwise returns the order.
1156 Expected<std::vector<JITDylibSP>> getDFSLinkOrder();
1157
1158 /// Rteurn this JITDylib and its transitive dependencies in reverse DFS order
1159 /// based on linkage relationships.
1160 ///
1161 /// If any JITDylib in the order is defunct then this method will return an
1162 /// error, otherwise returns the order.
1163 Expected<std::vector<JITDylibSP>> getReverseDFSLinkOrder();
1164
1165private:
1166 using AsynchronousSymbolQuerySet =
1167 std::set<std::shared_ptr<AsynchronousSymbolQuery>>;
1168
1169 using AsynchronousSymbolQueryList =
1170 std::vector<std::shared_ptr<AsynchronousSymbolQuery>>;
1171
1172 struct UnmaterializedInfo {
1173 UnmaterializedInfo(std::unique_ptr<MaterializationUnit> MU,
1174 ResourceTracker *RT)
1175 : MU(std::move(MU)), RT(RT) {}
1176
1177 std::unique_ptr<MaterializationUnit> MU;
1178 ResourceTracker *RT;
1179 };
1180
1181 using UnmaterializedInfosMap =
1182 DenseMap<SymbolStringPtr, std::shared_ptr<UnmaterializedInfo>>;
1183
1184 using UnmaterializedInfosList =
1185 std::vector<std::shared_ptr<UnmaterializedInfo>>;
1186
1187 struct MaterializingInfo {
1188 SymbolDependenceMap Dependants;
1189 SymbolDependenceMap UnemittedDependencies;
1190
1191 void addQuery(std::shared_ptr<AsynchronousSymbolQuery> Q);
1192 void removeQuery(const AsynchronousSymbolQuery &Q);
1193 AsynchronousSymbolQueryList takeQueriesMeeting(SymbolState RequiredState);
1194 AsynchronousSymbolQueryList takeAllPendingQueries() {
1195 return std::move(PendingQueries);
1196 }
1197 bool hasQueriesPending() const { return !PendingQueries.empty(); }
1198 const AsynchronousSymbolQueryList &pendingQueries() const {
1199 return PendingQueries;
1200 }
1201 private:
1202 AsynchronousSymbolQueryList PendingQueries;
1203 };
1204
1205 using MaterializingInfosMap = DenseMap<SymbolStringPtr, MaterializingInfo>;
1206
1207 class SymbolTableEntry {
1208 public:
1209 SymbolTableEntry() = default;
1210 SymbolTableEntry(JITSymbolFlags Flags)
1211 : Flags(Flags), State(static_cast<uint8_t>(SymbolState::NeverSearched)),
1212 MaterializerAttached(false), PendingRemoval(false) {}
1213
1214 JITTargetAddress getAddress() const { return Addr; }
1215 JITSymbolFlags getFlags() const { return Flags; }
1216 SymbolState getState() const { return static_cast<SymbolState>(State); }
1217
1218 bool hasMaterializerAttached() const { return MaterializerAttached; }
1219 bool isPendingRemoval() const { return PendingRemoval; }
1220
1221 void setAddress(JITTargetAddress Addr) { this->Addr = Addr; }
1222 void setFlags(JITSymbolFlags Flags) { this->Flags = Flags; }
1223 void setState(SymbolState State) {
1224 assert(static_cast<uint8_t>(State) < (1 << 6) &&(static_cast <bool> (static_cast<uint8_t>(State) <
(1 << 6) && "State does not fit in bitfield") ?
void (0) : __assert_fail ("static_cast<uint8_t>(State) < (1 << 6) && \"State does not fit in bitfield\""
, "llvm/include/llvm/ExecutionEngine/Orc/Core.h", 1225, __extension__
__PRETTY_FUNCTION__))
1225 "State does not fit in bitfield")(static_cast <bool> (static_cast<uint8_t>(State) <
(1 << 6) && "State does not fit in bitfield") ?
void (0) : __assert_fail ("static_cast<uint8_t>(State) < (1 << 6) && \"State does not fit in bitfield\""
, "llvm/include/llvm/ExecutionEngine/Orc/Core.h", 1225, __extension__
__PRETTY_FUNCTION__))
;
1226 this->State = static_cast<uint8_t>(State);
1227 }
1228
1229 void setMaterializerAttached(bool MaterializerAttached) {
1230 this->MaterializerAttached = MaterializerAttached;
1231 }
1232
1233 void setPendingRemoval(bool PendingRemoval) {
1234 this->PendingRemoval = PendingRemoval;
1235 }
1236
1237 JITEvaluatedSymbol getSymbol() const {
1238 return JITEvaluatedSymbol(Addr, Flags);
1239 }
1240
1241 private:
1242 JITTargetAddress Addr = 0;
1243 JITSymbolFlags Flags;
1244 uint8_t State : 6;
1245 uint8_t MaterializerAttached : 1;
1246 uint8_t PendingRemoval : 1;
1247 };
1248
1249 using SymbolTable = DenseMap<SymbolStringPtr, SymbolTableEntry>;
1250
1251 JITDylib(ExecutionSession &ES, std::string Name);
1252
1253 std::pair<AsynchronousSymbolQuerySet, std::shared_ptr<SymbolDependenceMap>>
1254 removeTracker(ResourceTracker &RT);
1255
1256 void transferTracker(ResourceTracker &DstRT, ResourceTracker &SrcRT);
1257
1258 Error defineImpl(MaterializationUnit &MU);
1259
1260 void installMaterializationUnit(std::unique_ptr<MaterializationUnit> MU,
1261 ResourceTracker &RT);
1262
1263 void detachQueryHelper(AsynchronousSymbolQuery &Q,
1264 const SymbolNameSet &QuerySymbols);
1265
1266 void transferEmittedNodeDependencies(MaterializingInfo &DependantMI,
1267 const SymbolStringPtr &DependantName,
1268 MaterializingInfo &EmittedMI);
1269
1270 Expected<SymbolFlagsMap> defineMaterializing(SymbolFlagsMap SymbolFlags);
1271
1272 Error replace(MaterializationResponsibility &FromMR,
1273 std::unique_ptr<MaterializationUnit> MU);
1274
1275 Expected<std::unique_ptr<MaterializationResponsibility>>
1276 delegate(MaterializationResponsibility &FromMR, SymbolFlagsMap SymbolFlags,
1277 SymbolStringPtr InitSymbol);
1278
1279 SymbolNameSet getRequestedSymbols(const SymbolFlagsMap &SymbolFlags) const;
1280
1281 void addDependencies(const SymbolStringPtr &Name,
1282 const SymbolDependenceMap &Dependants);
1283
1284 Error resolve(MaterializationResponsibility &MR, const SymbolMap &Resolved);
1285
1286 Error emit(MaterializationResponsibility &MR, const SymbolFlagsMap &Emitted);
1287
1288 void unlinkMaterializationResponsibility(MaterializationResponsibility &MR);
1289
1290 using FailedSymbolsWorklist =
1291 std::vector<std::pair<JITDylib *, SymbolStringPtr>>;
1292
1293 static std::pair<AsynchronousSymbolQuerySet,
1294 std::shared_ptr<SymbolDependenceMap>>
1295 failSymbols(FailedSymbolsWorklist);
1296
1297 ExecutionSession &ES;
1298 enum { Open, Closing, Closed } State = Open;
1299 std::mutex GeneratorsMutex;
1300 SymbolTable Symbols;
1301 UnmaterializedInfosMap UnmaterializedInfos;
1302 MaterializingInfosMap MaterializingInfos;
1303 std::vector<std::shared_ptr<DefinitionGenerator>> DefGenerators;
1304 JITDylibSearchOrder LinkOrder;
1305 ResourceTrackerSP DefaultTracker;
1306
1307 // Map trackers to sets of symbols tracked.
1308 DenseMap<ResourceTracker *, SymbolNameVector> TrackerSymbols;
1309 DenseMap<ResourceTracker *, DenseSet<MaterializationResponsibility *>>
1310 TrackerMRs;
1311};
1312
1313/// Platforms set up standard symbols and mediate interactions between dynamic
1314/// initializers (e.g. C++ static constructors) and ExecutionSession state.
1315/// Note that Platforms do not automatically run initializers: clients are still
1316/// responsible for doing this.
1317class Platform {
1318public:
1319 virtual ~Platform();
1320
1321 /// This method will be called outside the session lock each time a JITDylib
1322 /// is created (unless it is created with EmptyJITDylib set) to allow the
1323 /// Platform to install any JITDylib specific standard symbols (e.g
1324 /// __dso_handle).
1325 virtual Error setupJITDylib(JITDylib &JD) = 0;
1326
1327 /// This method will be called outside the session lock each time a JITDylib
1328 /// is removed to allow the Platform to remove any JITDylib-specific data.
1329 virtual Error teardownJITDylib(JITDylib &JD) = 0;
1330
1331 /// This method will be called under the ExecutionSession lock each time a
1332 /// MaterializationUnit is added to a JITDylib.
1333 virtual Error notifyAdding(ResourceTracker &RT,
1334 const MaterializationUnit &MU) = 0;
1335
1336 /// This method will be called under the ExecutionSession lock when a
1337 /// ResourceTracker is removed.
1338 virtual Error notifyRemoving(ResourceTracker &RT) = 0;
1339
1340 /// A utility function for looking up initializer symbols. Performs a blocking
1341 /// lookup for the given symbols in each of the given JITDylibs.
1342 ///
1343 /// Note: This function is deprecated and will be removed in the near future.
1344 static Expected<DenseMap<JITDylib *, SymbolMap>>
1345 lookupInitSymbols(ExecutionSession &ES,
1346 const DenseMap<JITDylib *, SymbolLookupSet> &InitSyms);
1347
1348 /// Performs an async lookup for the given symbols in each of the given
1349 /// JITDylibs, calling the given handler once all lookups have completed.
1350 static void
1351 lookupInitSymbolsAsync(unique_function<void(Error)> OnComplete,
1352 ExecutionSession &ES,
1353 const DenseMap<JITDylib *, SymbolLookupSet> &InitSyms);
1354};
1355
1356/// A materialization task.
1357class MaterializationTask : public RTTIExtends<MaterializationTask, Task> {
1358public:
1359 static char ID;
1360
1361 MaterializationTask(std::unique_ptr<MaterializationUnit> MU,
1362 std::unique_ptr<MaterializationResponsibility> MR)
1363 : MU(std::move(MU)), MR(std::move(MR)) {}
1364 void printDescription(raw_ostream &OS) override;
1365 void run() override;
1366
1367private:
1368 std::unique_ptr<MaterializationUnit> MU;
1369 std::unique_ptr<MaterializationResponsibility> MR;
1370};
1371
1372/// An ExecutionSession represents a running JIT program.
1373class ExecutionSession {
1374 friend class InProgressLookupFlagsState;
1375 friend class InProgressFullLookupState;
1376 friend class JITDylib;
1377 friend class LookupState;
1378 friend class MaterializationResponsibility;
1379 friend class ResourceTracker;
1380
1381public:
1382 /// For reporting errors.
1383 using ErrorReporter = std::function<void(Error)>;
1384
1385 /// Send a result to the remote.
1386 using SendResultFunction = unique_function<void(shared::WrapperFunctionResult)>;
1387
1388 /// For dispatching ORC tasks (typically materialization tasks).
1389 using DispatchTaskFunction = unique_function<void(std::unique_ptr<Task> T)>;
1390
1391 /// An asynchronous wrapper-function callable from the executor via
1392 /// jit-dispatch.
1393 using JITDispatchHandlerFunction = unique_function<void(
1394 SendResultFunction SendResult,
1395 const char *ArgData, size_t ArgSize)>;
1396
1397 /// A map associating tag names with asynchronous wrapper function
1398 /// implementations in the JIT.
1399 using JITDispatchHandlerAssociationMap =
1400 DenseMap<SymbolStringPtr, JITDispatchHandlerFunction>;
1401
1402 /// Construct an ExecutionSession with the given ExecutorProcessControl
1403 /// object.
1404 ExecutionSession(std::unique_ptr<ExecutorProcessControl> EPC);
1405
1406 /// Destroy an ExecutionSession. Verifies that endSession was called prior to
1407 /// destruction.
1408 ~ExecutionSession();
1409
1410 /// End the session. Closes all JITDylibs and disconnects from the
1411 /// executor. Clients must call this method before destroying the session.
1412 Error endSession();
1413
1414 /// Get the ExecutorProcessControl object associated with this
1415 /// ExecutionSession.
1416 ExecutorProcessControl &getExecutorProcessControl() { return *EPC; }
1417
1418 /// Return the triple for the executor.
1419 const Triple &getTargetTriple() const { return EPC->getTargetTriple(); }
1420
1421 /// Get the SymbolStringPool for this instance.
1422 std::shared_ptr<SymbolStringPool> getSymbolStringPool() {
1423 return EPC->getSymbolStringPool();
1424 }
1425
1426 /// Add a symbol name to the SymbolStringPool and return a pointer to it.
1427 SymbolStringPtr intern(StringRef SymName) { return EPC->intern(SymName); }
1428
1429 /// Set the Platform for this ExecutionSession.
1430 void setPlatform(std::unique_ptr<Platform> P) { this->P = std::move(P); }
1431
1432 /// Get the Platform for this session.
1433 /// Will return null if no Platform has been set for this ExecutionSession.
1434 Platform *getPlatform() { return P.get(); }
1435
1436 /// Run the given lambda with the session mutex locked.
1437 template <typename Func> decltype(auto) runSessionLocked(Func &&F) {
1438 std::lock_guard<std::recursive_mutex> Lock(SessionMutex);
1439 return F();
1440 }
1441
1442 /// Register the given ResourceManager with this ExecutionSession.
1443 /// Managers will be notified of events in reverse order of registration.
1444 void registerResourceManager(ResourceManager &RM);
1445
1446 /// Deregister the given ResourceManager with this ExecutionSession.
1447 /// Manager must have been previously registered.
1448 void deregisterResourceManager(ResourceManager &RM);
1449
1450 /// Return a pointer to the "name" JITDylib.
1451 /// Ownership of JITDylib remains within Execution Session
1452 JITDylib *getJITDylibByName(StringRef Name);
1453
1454 /// Add a new bare JITDylib to this ExecutionSession.
1455 ///
1456 /// The JITDylib Name is required to be unique. Clients should verify that
1457 /// names are not being re-used (E.g. by calling getJITDylibByName) if names
1458 /// are based on user input.
1459 ///
1460 /// This call does not install any library code or symbols into the newly
1461 /// created JITDylib. The client is responsible for all configuration.
1462 JITDylib &createBareJITDylib(std::string Name);
1463
1464 /// Add a new JITDylib to this ExecutionSession.
1465 ///
1466 /// The JITDylib Name is required to be unique. Clients should verify that
1467 /// names are not being re-used (e.g. by calling getJITDylibByName) if names
1468 /// are based on user input.
1469 ///
1470 /// If a Platform is attached then Platform::setupJITDylib will be called to
1471 /// install standard platform symbols (e.g. standard library interposes).
1472 /// If no Platform is attached this call is equivalent to createBareJITDylib.
1473 Expected<JITDylib &> createJITDylib(std::string Name);
1474
1475 /// Closes the given JITDylib.
1476 ///
1477 /// This method clears all resources held for the JITDylib, puts it in the
1478 /// closed state, and clears all references held by the ExecutionSession and
1479 /// other JITDylibs. No further code can be added to the JITDylib, and the
1480 /// object will be freed once any remaining JITDylibSPs to it are destroyed.
1481 ///
1482 /// This method does *not* run static destructors.
1483 ///
1484 /// This method can only be called once for each JITDylib.
1485 Error removeJITDylib(JITDylib &JD);
1486
1487 /// Set the error reporter function.
1488 ExecutionSession &setErrorReporter(ErrorReporter ReportError) {
1489 this->ReportError = std::move(ReportError);
1490 return *this;
1491 }
1492
1493 /// Report a error for this execution session.
1494 ///
1495 /// Unhandled errors can be sent here to log them.
1496 void reportError(Error Err) { ReportError(std::move(Err)); }
1497
1498 /// Set the task dispatch function.
1499 ExecutionSession &setDispatchTask(DispatchTaskFunction DispatchTask) {
1500 this->DispatchTask = std::move(DispatchTask);
1501 return *this;
1502 }
1503
1504 /// Search the given JITDylibs to find the flags associated with each of the
1505 /// given symbols.
1506 void lookupFlags(LookupKind K, JITDylibSearchOrder SearchOrder,
1507 SymbolLookupSet Symbols,
1508 unique_function<void(Expected<SymbolFlagsMap>)> OnComplete);
1509
1510 /// Blocking version of lookupFlags.
1511 Expected<SymbolFlagsMap> lookupFlags(LookupKind K,
1512 JITDylibSearchOrder SearchOrder,
1513 SymbolLookupSet Symbols);
1514
1515 /// Search the given JITDylibs for the given symbols.
1516 ///
1517 /// SearchOrder lists the JITDylibs to search. For each dylib, the associated
1518 /// boolean indicates whether the search should match against non-exported
1519 /// (hidden visibility) symbols in that dylib (true means match against
1520 /// non-exported symbols, false means do not match).
1521 ///
1522 /// The NotifyComplete callback will be called once all requested symbols
1523 /// reach the required state.
1524 ///
1525 /// If all symbols are found, the RegisterDependencies function will be called
1526 /// while the session lock is held. This gives clients a chance to register
1527 /// dependencies for on the queried symbols for any symbols they are
1528 /// materializing (if a MaterializationResponsibility instance is present,
1529 /// this can be implemented by calling
1530 /// MaterializationResponsibility::addDependencies). If there are no
1531 /// dependenant symbols for this query (e.g. it is being made by a top level
1532 /// client to get an address to call) then the value NoDependenciesToRegister
1533 /// can be used.
1534 void lookup(LookupKind K, const JITDylibSearchOrder &SearchOrder,
1535 SymbolLookupSet Symbols, SymbolState RequiredState,
1536 SymbolsResolvedCallback NotifyComplete,
1537 RegisterDependenciesFunction RegisterDependencies);
1538
1539 /// Blocking version of lookup above. Returns the resolved symbol map.
1540 /// If WaitUntilReady is true (the default), will not return until all
1541 /// requested symbols are ready (or an error occurs). If WaitUntilReady is
1542 /// false, will return as soon as all requested symbols are resolved,
1543 /// or an error occurs. If WaitUntilReady is false and an error occurs
1544 /// after resolution, the function will return a success value, but the
1545 /// error will be reported via reportErrors.
1546 Expected<SymbolMap> lookup(const JITDylibSearchOrder &SearchOrder,
1547 SymbolLookupSet Symbols,
1548 LookupKind K = LookupKind::Static,
1549 SymbolState RequiredState = SymbolState::Ready,
1550 RegisterDependenciesFunction RegisterDependencies =
1551 NoDependenciesToRegister);
1552
1553 /// Convenience version of blocking lookup.
1554 /// Searches each of the JITDylibs in the search order in turn for the given
1555 /// symbol.
1556 Expected<JITEvaluatedSymbol>
1557 lookup(const JITDylibSearchOrder &SearchOrder, SymbolStringPtr Symbol,
1558 SymbolState RequiredState = SymbolState::Ready);
1559
1560 /// Convenience version of blocking lookup.
1561 /// Searches each of the JITDylibs in the search order in turn for the given
1562 /// symbol. The search will not find non-exported symbols.
1563 Expected<JITEvaluatedSymbol>
1564 lookup(ArrayRef<JITDylib *> SearchOrder, SymbolStringPtr Symbol,
1565 SymbolState RequiredState = SymbolState::Ready);
1566
1567 /// Convenience version of blocking lookup.
1568 /// Searches each of the JITDylibs in the search order in turn for the given
1569 /// symbol. The search will not find non-exported symbols.
1570 Expected<JITEvaluatedSymbol>
1571 lookup(ArrayRef<JITDylib *> SearchOrder, StringRef Symbol,
1572 SymbolState RequiredState = SymbolState::Ready);
1573
1574 /// Materialize the given unit.
1575 void dispatchTask(std::unique_ptr<Task> T) {
1576 assert(T && "T must be non-null")(static_cast <bool> (T && "T must be non-null")
? void (0) : __assert_fail ("T && \"T must be non-null\""
, "llvm/include/llvm/ExecutionEngine/Orc/Core.h", 1576, __extension__
__PRETTY_FUNCTION__))
;
1577 DEBUG_WITH_TYPE("orc", dumpDispatchInfo(*T))do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("orc")) { dumpDispatchInfo(*T); } } while (false)
;
1578 DispatchTask(std::move(T));
1579 }
1580
1581 /// Run a wrapper function in the executor.
1582 ///
1583 /// The wrapper function should be callable as:
1584 ///
1585 /// \code{.cpp}
1586 /// CWrapperFunctionResult fn(uint8_t *Data, uint64_t Size);
1587 /// \endcode{.cpp}
1588 ///
1589 /// The given OnComplete function will be called to return the result.
1590 template <typename... ArgTs>
1591 void callWrapperAsync(ArgTs &&... Args) {
1592 EPC->callWrapperAsync(std::forward<ArgTs>(Args)...);
1593 }
1594
1595 /// Run a wrapper function in the executor. The wrapper function should be
1596 /// callable as:
1597 ///
1598 /// \code{.cpp}
1599 /// CWrapperFunctionResult fn(uint8_t *Data, uint64_t Size);
1600 /// \endcode{.cpp}
1601 shared::WrapperFunctionResult callWrapper(ExecutorAddr WrapperFnAddr,
1602 ArrayRef<char> ArgBuffer) {
1603 return EPC->callWrapper(WrapperFnAddr, ArgBuffer);
1604 }
1605
1606 /// Run a wrapper function using SPS to serialize the arguments and
1607 /// deserialize the results.
1608 template <typename SPSSignature, typename SendResultT, typename... ArgTs>
1609 void callSPSWrapperAsync(ExecutorAddr WrapperFnAddr, SendResultT &&SendResult,
1610 const ArgTs &...Args) {
1611 EPC->callSPSWrapperAsync<SPSSignature, SendResultT, ArgTs...>(
1612 WrapperFnAddr, std::forward<SendResultT>(SendResult), Args...);
1613 }
1614
1615 /// Run a wrapper function using SPS to serialize the arguments and
1616 /// deserialize the results.
1617 ///
1618 /// If SPSSignature is a non-void function signature then the second argument
1619 /// (the first in the Args list) should be a reference to a return value.
1620 template <typename SPSSignature, typename... WrapperCallArgTs>
1621 Error callSPSWrapper(ExecutorAddr WrapperFnAddr,
1622 WrapperCallArgTs &&...WrapperCallArgs) {
1623 return EPC->callSPSWrapper<SPSSignature, WrapperCallArgTs...>(
1624 WrapperFnAddr, std::forward<WrapperCallArgTs>(WrapperCallArgs)...);
1625 }
1626
1627 /// Wrap a handler that takes concrete argument types (and a sender for a
1628 /// concrete return type) to produce an AsyncHandlerWrapperFunction. Uses SPS
1629 /// to unpack the arguments and pack the result.
1630 ///
1631 /// This function is intended to support easy construction of
1632 /// AsyncHandlerWrapperFunctions that can be associated with a tag
1633 /// (using registerJITDispatchHandler) and called from the executor.
1634 template <typename SPSSignature, typename HandlerT>
1635 static JITDispatchHandlerFunction wrapAsyncWithSPS(HandlerT &&H) {
1636 return [H = std::forward<HandlerT>(H)](
1637 SendResultFunction SendResult,
1638 const char *ArgData, size_t ArgSize) mutable {
1639 shared::WrapperFunction<SPSSignature>::handleAsync(ArgData, ArgSize, H,
1640 std::move(SendResult));
1641 };
1642 }
1643
1644 /// Wrap a class method that takes concrete argument types (and a sender for
1645 /// a concrete return type) to produce an AsyncHandlerWrapperFunction. Uses
1646 /// SPS to unpack teh arguments and pack the result.
1647 ///
1648 /// This function is intended to support easy construction of
1649 /// AsyncHandlerWrapperFunctions that can be associated with a tag
1650 /// (using registerJITDispatchHandler) and called from the executor.
1651 template <typename SPSSignature, typename ClassT, typename... MethodArgTs>
1652 static JITDispatchHandlerFunction
1653 wrapAsyncWithSPS(ClassT *Instance, void (ClassT::*Method)(MethodArgTs...)) {
1654 return wrapAsyncWithSPS<SPSSignature>(
1655 [Instance, Method](MethodArgTs &&...MethodArgs) {
1656 (Instance->*Method)(std::forward<MethodArgTs>(MethodArgs)...);
1657 });
1658 }
1659
1660 /// For each tag symbol name, associate the corresponding
1661 /// AsyncHandlerWrapperFunction with the address of that symbol. The
1662 /// handler becomes callable from the executor using the ORC runtime
1663 /// __orc_rt_jit_dispatch function and the given tag.
1664 ///
1665 /// Tag symbols will be looked up in JD using LookupKind::Static,
1666 /// JITDylibLookupFlags::MatchAllSymbols (hidden tags will be found), and
1667 /// LookupFlags::WeaklyReferencedSymbol. Missing tag definitions will not
1668 /// cause an error, the handler will simply be dropped.
1669 Error registerJITDispatchHandlers(JITDylib &JD,
1670 JITDispatchHandlerAssociationMap WFs);
1671
1672 /// Run a registered jit-side wrapper function.
1673 /// This should be called by the ExecutorProcessControl instance in response
1674 /// to incoming jit-dispatch requests from the executor.
1675 void
1676 runJITDispatchHandler(SendResultFunction SendResult,
1677 JITTargetAddress HandlerFnTagAddr,
1678 ArrayRef<char> ArgBuffer);
1679
1680 /// Dump the state of all the JITDylibs in this session.
1681 void dump(raw_ostream &OS);
1682
1683private:
1684 static void logErrorsToStdErr(Error Err) {
1685 logAllUnhandledErrors(std::move(Err), errs(), "JIT session error: ");
1686 }
1687
1688 static void runOnCurrentThread(std::unique_ptr<Task> T) { T->run(); }
1689
1690 void dispatchOutstandingMUs();
1691
1692 static std::unique_ptr<MaterializationResponsibility>
1693 createMaterializationResponsibility(ResourceTracker &RT,
1694 SymbolFlagsMap Symbols,
1695 SymbolStringPtr InitSymbol) {
1696 auto &JD = RT.getJITDylib();
1697 std::unique_ptr<MaterializationResponsibility> MR(
1698 new MaterializationResponsibility(&RT, std::move(Symbols),
1699 std::move(InitSymbol)));
1700 JD.TrackerMRs[&RT].insert(MR.get());
1701 return MR;
1702 }
1703
1704 Error removeResourceTracker(ResourceTracker &RT);
1705 void transferResourceTracker(ResourceTracker &DstRT, ResourceTracker &SrcRT);
1706 void destroyResourceTracker(ResourceTracker &RT);
1707
1708 // State machine functions for query application..
1709
1710 /// IL_updateCandidatesFor is called to remove already-defined symbols that
1711 /// match a given query from the set of candidate symbols to generate
1712 /// definitions for (no need to generate a definition if one already exists).
1713 Error IL_updateCandidatesFor(JITDylib &JD, JITDylibLookupFlags JDLookupFlags,
1714 SymbolLookupSet &Candidates,
1715 SymbolLookupSet *NonCandidates);
1716
1717 /// OL_applyQueryPhase1 is an optionally re-startable loop for triggering
1718 /// definition generation. It is called when a lookup is performed, and again
1719 /// each time that LookupState::continueLookup is called.
1720 void OL_applyQueryPhase1(std::unique_ptr<InProgressLookupState> IPLS,
1721 Error Err);
1722
1723 /// OL_completeLookup is run once phase 1 successfully completes for a lookup
1724 /// call. It attempts to attach the symbol to all symbol table entries and
1725 /// collect all MaterializationUnits to dispatch. If this method fails then
1726 /// all MaterializationUnits will be left un-materialized.
1727 void OL_completeLookup(std::unique_ptr<InProgressLookupState> IPLS,
1728 std::shared_ptr<AsynchronousSymbolQuery> Q,
1729 RegisterDependenciesFunction RegisterDependencies);
1730
1731 /// OL_completeLookupFlags is run once phase 1 successfully completes for a
1732 /// lookupFlags call.
1733 void OL_completeLookupFlags(
1734 std::unique_ptr<InProgressLookupState> IPLS,
1735 unique_function<void(Expected<SymbolFlagsMap>)> OnComplete);
1736
1737 // State machine functions for MaterializationResponsibility.
1738 void OL_destroyMaterializationResponsibility(
1739 MaterializationResponsibility &MR);
1740 SymbolNameSet OL_getRequestedSymbols(const MaterializationResponsibility &MR);
1741 Error OL_notifyResolved(MaterializationResponsibility &MR,
1742 const SymbolMap &Symbols);
1743 Error OL_notifyEmitted(MaterializationResponsibility &MR);
1744 Error OL_defineMaterializing(MaterializationResponsibility &MR,
1745 SymbolFlagsMap SymbolFlags);
1746 void OL_notifyFailed(MaterializationResponsibility &MR);
1747 Error OL_replace(MaterializationResponsibility &MR,
1748 std::unique_ptr<MaterializationUnit> MU);
1749 Expected<std::unique_ptr<MaterializationResponsibility>>
1750 OL_delegate(MaterializationResponsibility &MR, const SymbolNameSet &Symbols);
1751 void OL_addDependencies(MaterializationResponsibility &MR,
1752 const SymbolStringPtr &Name,
1753 const SymbolDependenceMap &Dependencies);
1754 void OL_addDependenciesForAll(MaterializationResponsibility &MR,
1755 const SymbolDependenceMap &Dependencies);
1756
1757#ifndef NDEBUG
1758 void dumpDispatchInfo(Task &T);
1759#endif // NDEBUG
1760
1761 mutable std::recursive_mutex SessionMutex;
1762 bool SessionOpen = true;
1763 std::unique_ptr<ExecutorProcessControl> EPC;
1764 std::unique_ptr<Platform> P;
1765 ErrorReporter ReportError = logErrorsToStdErr;
1766 DispatchTaskFunction DispatchTask = runOnCurrentThread;
1767
1768 std::vector<ResourceManager *> ResourceManagers;
1769
1770 std::vector<JITDylibSP> JDs;
1771
1772 // FIXME: Remove this (and runOutstandingMUs) once the linking layer works
1773 // with callbacks from asynchronous queries.
1774 mutable std::recursive_mutex OutstandingMUsMutex;
1775 std::vector<std::pair<std::unique_ptr<MaterializationUnit>,
1776 std::unique_ptr<MaterializationResponsibility>>>
1777 OutstandingMUs;
1778
1779 mutable std::mutex JITDispatchHandlersMutex;
1780 DenseMap<JITTargetAddress, std::shared_ptr<JITDispatchHandlerFunction>>
1781 JITDispatchHandlers;
1782};
1783
1784template <typename Func> Error ResourceTracker::withResourceKeyDo(Func &&F) {
1785 return getJITDylib().getExecutionSession().runSessionLocked([&]() -> Error {
1786 if (isDefunct())
1787 return make_error<ResourceTrackerDefunct>(this);
1788 F(getKeyUnsafe());
1789 return Error::success();
1790 });
1791}
1792
1793inline ExecutionSession &
1794MaterializationResponsibility::getExecutionSession() const {
1795 return JD.getExecutionSession();
1796}
1797
1798template <typename GeneratorT>
1799GeneratorT &JITDylib::addGenerator(std::unique_ptr<GeneratorT> DefGenerator) {
1800 auto &G = *DefGenerator;
1801 ES.runSessionLocked([&] {
1802 assert(State == Open && "Cannot add generator to closed JITDylib")(static_cast <bool> (State == Open && "Cannot add generator to closed JITDylib"
) ? void (0) : __assert_fail ("State == Open && \"Cannot add generator to closed JITDylib\""
, "llvm/include/llvm/ExecutionEngine/Orc/Core.h", 1802, __extension__
__PRETTY_FUNCTION__))
;
1803 DefGenerators.push_back(std::move(DefGenerator));
1804 });
1805 return G;
1806}
1807
1808template <typename Func>
1809auto JITDylib::withLinkOrderDo(Func &&F)
1810 -> decltype(F(std::declval<const JITDylibSearchOrder &>())) {
1811 assert(State == Open && "Cannot use link order of closed JITDylib")(static_cast <bool> (State == Open && "Cannot use link order of closed JITDylib"
) ? void (0) : __assert_fail ("State == Open && \"Cannot use link order of closed JITDylib\""
, "llvm/include/llvm/ExecutionEngine/Orc/Core.h", 1811, __extension__
__PRETTY_FUNCTION__))
;
1812 return ES.runSessionLocked([&]() { return F(LinkOrder); });
1813}
1814
1815template <typename MaterializationUnitType>
1816Error JITDylib::define(std::unique_ptr<MaterializationUnitType> &&MU,
1817 ResourceTrackerSP RT) {
1818 assert(MU && "Can not define with a null MU")(static_cast <bool> (MU && "Can not define with a null MU"
) ? void (0) : __assert_fail ("MU && \"Can not define with a null MU\""
, "llvm/include/llvm/ExecutionEngine/Orc/Core.h", 1818, __extension__
__PRETTY_FUNCTION__))
;
1819
1820 if (MU->getSymbols().empty()) {
1821 // Empty MUs are allowable but pathological, so issue a warning.
1822 DEBUG_WITH_TYPE("orc", {do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("orc")) { { dbgs() << "Warning: Discarding empty MU " <<
MU->getName() << " for " << getName() <<
"\n"; }; } } while (false)
1823 dbgs() << "Warning: Discarding empty MU " << MU->getName() << " for "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("orc")) { { dbgs() << "Warning: Discarding empty MU " <<
MU->getName() << " for " << getName() <<
"\n"; }; } } while (false)
1824 << getName() << "\n";do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("orc")) { { dbgs() << "Warning: Discarding empty MU " <<
MU->getName() << " for " << getName() <<
"\n"; }; } } while (false)
1825 })do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("orc")) { { dbgs() << "Warning: Discarding empty MU " <<
MU->getName() << " for " << getName() <<
"\n"; }; } } while (false)
;
1826 return Error::success();
1827 } else
1828 DEBUG_WITH_TYPE("orc", {do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("orc")) { { dbgs() << "Defining MU " << MU->getName
() << " for " << getName() << " (tracker: "
; if (RT == getDefaultResourceTracker()) dbgs() << "default)"
; else if (RT) dbgs() << RT.get() << ")\n"; else dbgs
() << "0x0, default will be used)\n"; }; } } while (false
)
1829 dbgs() << "Defining MU " << MU->getName() << " for " << getName()do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("orc")) { { dbgs() << "Defining MU " << MU->getName
() << " for " << getName() << " (tracker: "
; if (RT == getDefaultResourceTracker()) dbgs() << "default)"
; else if (RT) dbgs() << RT.get() << ")\n"; else dbgs
() << "0x0, default will be used)\n"; }; } } while (false
)
1830 << " (tracker: ";do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("orc")) { { dbgs() << "Defining MU " << MU->getName
() << " for " << getName() << " (tracker: "
; if (RT == getDefaultResourceTracker()) dbgs() << "default)"
; else if (RT) dbgs() << RT.get() << ")\n"; else dbgs
() << "0x0, default will be used)\n"; }; } } while (false
)
1831 if (RT == getDefaultResourceTracker())do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("orc")) { { dbgs() << "Defining MU " << MU->getName
() << " for " << getName() << " (tracker: "
; if (RT == getDefaultResourceTracker()) dbgs() << "default)"
; else if (RT) dbgs() << RT.get() << ")\n"; else dbgs
() << "0x0, default will be used)\n"; }; } } while (false
)
1832 dbgs() << "default)";do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("orc")) { { dbgs() << "Defining MU " << MU->getName
() << " for " << getName() << " (tracker: "
; if (RT == getDefaultResourceTracker()) dbgs() << "default)"
; else if (RT) dbgs() << RT.get() << ")\n"; else dbgs
() << "0x0, default will be used)\n"; }; } } while (false
)
1833 else if (RT)do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("orc")) { { dbgs() << "Defining MU " << MU->getName
() << " for " << getName() << " (tracker: "
; if (RT == getDefaultResourceTracker()) dbgs() << "default)"
; else if (RT) dbgs() << RT.get() << ")\n"; else dbgs
() << "0x0, default will be used)\n"; }; } } while (false
)
1834 dbgs() << RT.get() << ")\n";do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("orc")) { { dbgs() << "Defining MU " << MU->getName
() << " for " << getName() << " (tracker: "
; if (RT == getDefaultResourceTracker()) dbgs() << "default)"
; else if (RT) dbgs() << RT.get() << ")\n"; else dbgs
() << "0x0, default will be used)\n"; }; } } while (false
)
1835 elsedo { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("orc")) { { dbgs() << "Defining MU " << MU->getName
() << " for " << getName() << " (tracker: "
; if (RT == getDefaultResourceTracker()) dbgs() << "default)"
; else if (RT) dbgs() << RT.get() << ")\n"; else dbgs
() << "0x0, default will be used)\n"; }; } } while (false
)
1836 dbgs() << "0x0, default will be used)\n";do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("orc")) { { dbgs() << "Defining MU " << MU->getName
() << " for " << getName() << " (tracker: "
; if (RT == getDefaultResourceTracker()) dbgs() << "default)"
; else if (RT) dbgs() << RT.get() << ")\n"; else dbgs
() << "0x0, default will be used)\n"; }; } } while (false
)
1837 })do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("orc")) { { dbgs() << "Defining MU " << MU->getName
() << " for " << getName() << " (tracker: "
; if (RT == getDefaultResourceTracker()) dbgs() << "default)"
; else if (RT) dbgs() << RT.get() << ")\n"; else dbgs
() << "0x0, default will be used)\n"; }; } } while (false
)
;
1838
1839 return ES.runSessionLocked([&, this]() -> Error {
1840 assert(State == Open && "JD is defunct")(static_cast <bool> (State == Open && "JD is defunct"
) ? void (0) : __assert_fail ("State == Open && \"JD is defunct\""
, "llvm/include/llvm/ExecutionEngine/Orc/Core.h", 1840, __extension__
__PRETTY_FUNCTION__))
;
1841
1842 if (auto Err = defineImpl(*MU))
1843 return Err;
1844
1845 if (!RT)
1846 RT = getDefaultResourceTracker();
1847
1848 if (auto *P = ES.getPlatform()) {
1849 if (auto Err = P->notifyAdding(*RT, *MU))
1850 return Err;
1851 }
1852
1853 installMaterializationUnit(std::move(MU), *RT);
1854 return Error::success();
1855 });
1856}
1857
1858template <typename MaterializationUnitType>
1859Error JITDylib::define(std::unique_ptr<MaterializationUnitType> &MU,
1860 ResourceTrackerSP RT) {
1861 assert(MU && "Can not define with a null MU")(static_cast <bool> (MU && "Can not define with a null MU"
) ? void (0) : __assert_fail ("MU && \"Can not define with a null MU\""
, "llvm/include/llvm/ExecutionEngine/Orc/Core.h", 1861, __extension__
__PRETTY_FUNCTION__))
;
1862
1863 if (MU->getSymbols().empty()) {
1864 // Empty MUs are allowable but pathological, so issue a warning.
1865 DEBUG_WITH_TYPE("orc", {do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("orc")) { { dbgs() << "Warning: Discarding empty MU " <<
MU->getName() << getName() << "\n"; }; } } while
(false)
1866 dbgs() << "Warning: Discarding empty MU " << MU->getName() << getName()do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("orc")) { { dbgs() << "Warning: Discarding empty MU " <<
MU->getName() << getName() << "\n"; }; } } while
(false)
1867 << "\n";do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("orc")) { { dbgs() << "Warning: Discarding empty MU " <<
MU->getName() << getName() << "\n"; }; } } while
(false)
1868 })do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("orc")) { { dbgs() << "Warning: Discarding empty MU " <<
MU->getName() << getName() << "\n"; }; } } while
(false)
;
1869 return Error::success();
1870 } else
1871 DEBUG_WITH_TYPE("orc", {do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("orc")) { { dbgs() << "Defining MU " << MU->getName
() << " for " << getName() << " (tracker: "
; if (RT == getDefaultResourceTracker()) dbgs() << "default)"
; else if (RT) dbgs() << RT.get() << ")\n"; else dbgs
() << "0x0, default will be used)\n"; }; } } while (false
)
1872 dbgs() << "Defining MU " << MU->getName() << " for " << getName()do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("orc")) { { dbgs() << "Defining MU " << MU->getName
() << " for " << getName() << " (tracker: "
; if (RT == getDefaultResourceTracker()) dbgs() << "default)"
; else if (RT) dbgs() << RT.get() << ")\n"; else dbgs
() << "0x0, default will be used)\n"; }; } } while (false
)
1873 << " (tracker: ";do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("orc")) { { dbgs() << "Defining MU " << MU->getName
() << " for " << getName() << " (tracker: "
; if (RT == getDefaultResourceTracker()) dbgs() << "default)"
; else if (RT) dbgs() << RT.get() << ")\n"; else dbgs
() << "0x0, default will be used)\n"; }; } } while (false
)
1874 if (RT == getDefaultResourceTracker())do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("orc")) { { dbgs() << "Defining MU " << MU->getName
() << " for " << getName() << " (tracker: "
; if (RT == getDefaultResourceTracker()) dbgs() << "default)"
; else if (RT) dbgs() << RT.get() << ")\n"; else dbgs
() << "0x0, default will be used)\n"; }; } } while (false
)
1875 dbgs() << "default)";do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("orc")) { { dbgs() << "Defining MU " << MU->getName
() << " for " << getName() << " (tracker: "
; if (RT == getDefaultResourceTracker()) dbgs() << "default)"
; else if (RT) dbgs() << RT.get() << ")\n"; else dbgs
() << "0x0, default will be used)\n"; }; } } while (false
)
1876 else if (RT)do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("orc")) { { dbgs() << "Defining MU " << MU->getName
() << " for " << getName() << " (tracker: "
; if (RT == getDefaultResourceTracker()) dbgs() << "default)"
; else if (RT) dbgs() << RT.get() << ")\n"; else dbgs
() << "0x0, default will be used)\n"; }; } } while (false
)
1877 dbgs() << RT.get() << ")\n";do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("orc")) { { dbgs() << "Defining MU " << MU->getName
() << " for " << getName() << " (tracker: "
; if (RT == getDefaultResourceTracker()) dbgs() << "default)"
; else if (RT) dbgs() << RT.get() << ")\n"; else dbgs
() << "0x0, default will be used)\n"; }; } } while (false
)
1878 elsedo { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("orc")) { { dbgs() << "Defining MU " << MU->getName
() << " for " << getName() << " (tracker: "
; if (RT == getDefaultResourceTracker()) dbgs() << "default)"
; else if (RT) dbgs() << RT.get() << ")\n"; else dbgs
() << "0x0, default will be used)\n"; }; } } while (false
)
1879 dbgs() << "0x0, default will be used)\n";do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("orc")) { { dbgs() << "Defining MU " << MU->getName
() << " for " << getName() << " (tracker: "
; if (RT == getDefaultResourceTracker()) dbgs() << "default)"
; else if (RT) dbgs() << RT.get() << ")\n"; else dbgs
() << "0x0, default will be used)\n"; }; } } while (false
)
1880 })do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("orc")) { { dbgs() << "Defining MU " << MU->getName
() << " for " << getName() << " (tracker: "
; if (RT == getDefaultResourceTracker()) dbgs() << "default)"
; else if (RT) dbgs() << RT.get() << ")\n"; else dbgs
() << "0x0, default will be used)\n"; }; } } while (false
)
;
1881
1882 return ES.runSessionLocked([&, this]() -> Error {
1883 assert(State == Open && "JD is defunct")(static_cast <bool> (State == Open && "JD is defunct"
) ? void (0) : __assert_fail ("State == Open && \"JD is defunct\""
, "llvm/include/llvm/ExecutionEngine/Orc/Core.h", 1883, __extension__
__PRETTY_FUNCTION__))
;
1884
1885 if (auto Err = defineImpl(*MU))
1886 return Err;
1887
1888 if (!RT)
1889 RT = getDefaultResourceTracker();
1890
1891 if (auto *P = ES.getPlatform()) {
1892 if (auto Err = P->notifyAdding(*RT, *MU))
1893 return Err;
1894 }
1895
1896 installMaterializationUnit(std::move(MU), *RT);
1897 return Error::success();
1898 });
1899}
1900
1901/// ReexportsGenerator can be used with JITDylib::addGenerator to automatically
1902/// re-export a subset of the source JITDylib's symbols in the target.
1903class ReexportsGenerator : public DefinitionGenerator {
1904public:
1905 using SymbolPredicate = std::function<bool(SymbolStringPtr)>;
1906
1907 /// Create a reexports generator. If an Allow predicate is passed, only
1908 /// symbols for which the predicate returns true will be reexported. If no
1909 /// Allow predicate is passed, all symbols will be exported.
1910 ReexportsGenerator(JITDylib &SourceJD,
1911 JITDylibLookupFlags SourceJDLookupFlags,
1912 SymbolPredicate Allow = SymbolPredicate());
1913
1914 Error tryToGenerate(LookupState &LS, LookupKind K, JITDylib &JD,
1915 JITDylibLookupFlags JDLookupFlags,
1916 const SymbolLookupSet &LookupSet) override;
1917
1918private:
1919 JITDylib &SourceJD;
1920 JITDylibLookupFlags SourceJDLookupFlags;
1921 SymbolPredicate Allow;
1922};
1923
1924// --------------- IMPLEMENTATION --------------
1925// Implementations for inline functions/methods.
1926// ---------------------------------------------
1927
1928inline MaterializationResponsibility::~MaterializationResponsibility() {
1929 getExecutionSession().OL_destroyMaterializationResponsibility(*this);
1930}
1931
1932inline SymbolNameSet MaterializationResponsibility::getRequestedSymbols() const {
1933 return getExecutionSession().OL_getRequestedSymbols(*this);
1934}
1935
1936inline Error MaterializationResponsibility::notifyResolved(
1937 const SymbolMap &Symbols) {
1938 return getExecutionSession().OL_notifyResolved(*this, Symbols);
1939}
1940
1941inline Error MaterializationResponsibility::notifyEmitted() {
1942 return getExecutionSession().OL_notifyEmitted(*this);
1943}
1944
1945inline Error MaterializationResponsibility::defineMaterializing(
1946 SymbolFlagsMap SymbolFlags) {
1947 return getExecutionSession().OL_defineMaterializing(*this,
1948 std::move(SymbolFlags));
1949}
1950
1951inline void MaterializationResponsibility::failMaterialization() {
1952 getExecutionSession().OL_notifyFailed(*this);
1953}
1954
1955inline Error MaterializationResponsibility::replace(
1956 std::unique_ptr<MaterializationUnit> MU) {
1957 return getExecutionSession().OL_replace(*this, std::move(MU));
1958}
1959
1960inline Expected<std::unique_ptr<MaterializationResponsibility>>
1961MaterializationResponsibility::delegate(const SymbolNameSet &Symbols) {
1962 return getExecutionSession().OL_delegate(*this, Symbols);
1963}
1964
1965inline void MaterializationResponsibility::addDependencies(
1966 const SymbolStringPtr &Name, const SymbolDependenceMap &Dependencies) {
1967 getExecutionSession().OL_addDependencies(*this, Name, Dependencies);
1968}
1969
1970inline void MaterializationResponsibility::addDependenciesForAll(
1971 const SymbolDependenceMap &Dependencies) {
1972 getExecutionSession().OL_addDependenciesForAll(*this, Dependencies);
1973}
1974
1975} // End namespace orc
1976} // End namespace llvm
1977
1978#endif // LLVM_EXECUTIONENGINE_ORC_CORE_H

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

1// Components for manipulating sequences of characters -*- C++ -*-
2
3// Copyright (C) 1997-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/basic_string.h
26 * This is an internal header file, included by other library headers.
27 * Do not attempt to use it directly. @headername{string}
28 */
29
30//
31// ISO C++ 14882: 21 Strings library
32//
33
34#ifndef _BASIC_STRING_H1
35#define _BASIC_STRING_H1 1
36
37#pragma GCC system_header
38
39#include <ext/atomicity.h>
40#include <ext/alloc_traits.h>
41#include <debug/debug.h>
42
43#if __cplusplus201703L >= 201103L
44#include <initializer_list>
45#endif
46
47#if __cplusplus201703L >= 201703L
48# include <string_view>
49#endif
50
51
52namespace std _GLIBCXX_VISIBILITY(default)__attribute__ ((__visibility__ ("default")))
53{
54_GLIBCXX_BEGIN_NAMESPACE_VERSION
55
56#if _GLIBCXX_USE_CXX11_ABI1
57_GLIBCXX_BEGIN_NAMESPACE_CXX11namespace __cxx11 {
58 /**
59 * @class basic_string basic_string.h <string>
60 * @brief Managing sequences of characters and character-like objects.
61 *
62 * @ingroup strings
63 * @ingroup sequences
64 *
65 * @tparam _CharT Type of character
66 * @tparam _Traits Traits for character type, defaults to
67 * char_traits<_CharT>.
68 * @tparam _Alloc Allocator type, defaults to allocator<_CharT>.
69 *
70 * Meets the requirements of a <a href="tables.html#65">container</a>, a
71 * <a href="tables.html#66">reversible container</a>, and a
72 * <a href="tables.html#67">sequence</a>. Of the
73 * <a href="tables.html#68">optional sequence requirements</a>, only
74 * @c push_back, @c at, and @c %array access are supported.
75 */
76 template<typename _CharT, typename _Traits, typename _Alloc>
77 class basic_string
78 {
79 typedef typename __gnu_cxx::__alloc_traits<_Alloc>::template
80 rebind<_CharT>::other _Char_alloc_type;
81 typedef __gnu_cxx::__alloc_traits<_Char_alloc_type> _Alloc_traits;
82
83 // Types:
84 public:
85 typedef _Traits traits_type;
86 typedef typename _Traits::char_type value_type;
87 typedef _Char_alloc_type allocator_type;
88 typedef typename _Alloc_traits::size_type size_type;
89 typedef typename _Alloc_traits::difference_type difference_type;
90 typedef typename _Alloc_traits::reference reference;
91 typedef typename _Alloc_traits::const_reference const_reference;
92 typedef typename _Alloc_traits::pointer pointer;
93 typedef typename _Alloc_traits::const_pointer const_pointer;
94 typedef __gnu_cxx::__normal_iterator<pointer, basic_string> iterator;
95 typedef __gnu_cxx::__normal_iterator<const_pointer, basic_string>
96 const_iterator;
97 typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
98 typedef std::reverse_iterator<iterator> reverse_iterator;
99
100 /// Value returned by various member functions when they fail.
101 static const size_type npos = static_cast<size_type>(-1);
102
103 protected:
104 // type used for positions in insert, erase etc.
105#if __cplusplus201703L < 201103L
106 typedef iterator __const_iterator;
107#else
108 typedef const_iterator __const_iterator;
109#endif
110
111 private:
112#if __cplusplus201703L >= 201703L
113 // A helper type for avoiding boiler-plate.
114 typedef basic_string_view<_CharT, _Traits> __sv_type;
115
116 template<typename _Tp, typename _Res>
117 using _If_sv = enable_if_t<
118 __and_<is_convertible<const _Tp&, __sv_type>,
119 __not_<is_convertible<const _Tp*, const basic_string*>>,
120 __not_<is_convertible<const _Tp&, const _CharT*>>>::value,
121 _Res>;
122
123 // Allows an implicit conversion to __sv_type.
124 static __sv_type
125 _S_to_string_view(__sv_type __svt) noexcept
126 { return __svt; }
127
128 // Wraps a string_view by explicit conversion and thus
129 // allows to add an internal constructor that does not
130 // participate in overload resolution when a string_view
131 // is provided.
132 struct __sv_wrapper
133 {
134 explicit __sv_wrapper(__sv_type __sv) noexcept : _M_sv(__sv) { }
135 __sv_type _M_sv;
136 };
137
138 /**
139 * @brief Only internally used: Construct string from a string view
140 * wrapper.
141 * @param __svw string view wrapper.
142 * @param __a Allocator to use.
143 */
144 explicit
145 basic_string(__sv_wrapper __svw, const _Alloc& __a)
146 : basic_string(__svw._M_sv.data(), __svw._M_sv.size(), __a) { }
147#endif
148
149 // Use empty-base optimization: http://www.cantrip.org/emptyopt.html
150 struct _Alloc_hider : allocator_type // TODO check __is_final
151 {
152#if __cplusplus201703L < 201103L
153 _Alloc_hider(pointer __dat, const _Alloc& __a = _Alloc())
154 : allocator_type(__a), _M_p(__dat) { }
155#else
156 _Alloc_hider(pointer __dat, const _Alloc& __a)
157 : allocator_type(__a), _M_p(__dat) { }
158
159 _Alloc_hider(pointer __dat, _Alloc&& __a = _Alloc())
160 : allocator_type(std::move(__a)), _M_p(__dat) { }
161#endif
162
163 pointer _M_p; // The actual data.
164 };
165
166 _Alloc_hider _M_dataplus;
167 size_type _M_string_length;
168
169 enum { _S_local_capacity = 15 / sizeof(_CharT) };
170
171 union
172 {
173 _CharT _M_local_buf[_S_local_capacity + 1];
174 size_type _M_allocated_capacity;
175 };
176
177 void
178 _M_data(pointer __p)
179 { _M_dataplus._M_p = __p; }
180
181 void
182 _M_length(size_type __length)
183 { _M_string_length = __length; }
184
185 pointer
186 _M_data() const
187 { return _M_dataplus._M_p; }
188
189 pointer
190 _M_local_data()
191 {
192#if __cplusplus201703L >= 201103L
193 return std::pointer_traits<pointer>::pointer_to(*_M_local_buf);
194#else
195 return pointer(_M_local_buf);
196#endif
197 }
198
199 const_pointer
200 _M_local_data() const
201 {
202#if __cplusplus201703L >= 201103L
203 return std::pointer_traits<const_pointer>::pointer_to(*_M_local_buf);
204#else
205 return const_pointer(_M_local_buf);
206#endif
207 }
208
209 void
210 _M_capacity(size_type __capacity)
211 { _M_allocated_capacity = __capacity; }
212
213 void
214 _M_set_length(size_type __n)
215 {
216 _M_length(__n);
217 traits_type::assign(_M_data()[__n], _CharT());
218 }
219
220 bool
221 _M_is_local() const
222 { return _M_data() == _M_local_data(); }
223
224 // Create & Destroy
225 pointer
226 _M_create(size_type&, size_type);
227
228 void
229 _M_dispose()
230 {
231 if (!_M_is_local())
232 _M_destroy(_M_allocated_capacity);
233 }
234
235 void
236 _M_destroy(size_type __size) throw()
237 { _Alloc_traits::deallocate(_M_get_allocator(), _M_data(), __size + 1); }
238
239 // _M_construct_aux is used to implement the 21.3.1 para 15 which
240 // requires special behaviour if _InIterator is an integral type
241 template<typename _InIterator>
242 void
243 _M_construct_aux(_InIterator __beg, _InIterator __end,
244 std::__false_type)
245 {
246 typedef typename iterator_traits<_InIterator>::iterator_category _Tag;
247 _M_construct(__beg, __end, _Tag());
248 }
249
250 // _GLIBCXX_RESOLVE_LIB_DEFECTS
251 // 438. Ambiguity in the "do the right thing" clause
252 template<typename _Integer>
253 void
254 _M_construct_aux(_Integer __beg, _Integer __end, std::__true_type)
255 { _M_construct_aux_2(static_cast<size_type>(__beg), __end); }
256
257 void
258 _M_construct_aux_2(size_type __req, _CharT __c)
259 { _M_construct(__req, __c); }
260
261 template<typename _InIterator>
262 void
263 _M_construct(_InIterator __beg, _InIterator __end)
264 {
265 typedef typename std::__is_integer<_InIterator>::__type _Integral;
266 _M_construct_aux(__beg, __end, _Integral());
267 }
268
269 // For Input Iterators, used in istreambuf_iterators, etc.
270 template<typename _InIterator>
271 void
272 _M_construct(_InIterator __beg, _InIterator __end,
273 std::input_iterator_tag);
274
275 // For forward_iterators up to random_access_iterators, used for
276 // string::iterator, _CharT*, etc.
277 template<typename _FwdIterator>
278 void
279 _M_construct(_FwdIterator __beg, _FwdIterator __end,
280 std::forward_iterator_tag);
281
282 void
283 _M_construct(size_type __req, _CharT __c);
284
285 allocator_type&
286 _M_get_allocator()
287 { return _M_dataplus; }
288
289 const allocator_type&
290 _M_get_allocator() const
291 { return _M_dataplus; }
292
293 private:
294
295#ifdef _GLIBCXX_DISAMBIGUATE_REPLACE_INST
296 // The explicit instantiations in misc-inst.cc require this due to
297 // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=64063
298 template<typename _Tp, bool _Requires =
299 !__are_same<_Tp, _CharT*>::__value
300 && !__are_same<_Tp, const _CharT*>::__value
301 && !__are_same<_Tp, iterator>::__value
302 && !__are_same<_Tp, const_iterator>::__value>
303 struct __enable_if_not_native_iterator
304 { typedef basic_string& __type; };
305 template<typename _Tp>
306 struct __enable_if_not_native_iterator<_Tp, false> { };
307#endif
308
309 size_type
310 _M_check(size_type __pos, const char* __s) const
311 {
312 if (__pos > this->size())
313 __throw_out_of_range_fmt(__N("%s: __pos (which is %zu) > "("%s: __pos (which is %zu) > " "this->size() (which is %zu)"
)
314 "this->size() (which is %zu)")("%s: __pos (which is %zu) > " "this->size() (which is %zu)"
)
,
315 __s, __pos, this->size());
316 return __pos;
317 }
318
319 void
320 _M_check_length(size_type __n1, size_type __n2, const char* __s) const
321 {
322 if (this->max_size() - (this->size() - __n1) < __n2)
323 __throw_length_error(__N(__s)(__s));
324 }
325
326
327 // NB: _M_limit doesn't check for a bad __pos value.
328 size_type
329 _M_limit(size_type __pos, size_type __off) const _GLIBCXX_NOEXCEPTnoexcept
330 {
331 const bool __testoff = __off < this->size() - __pos;
332 return __testoff ? __off : this->size() - __pos;
333 }
334
335 // True if _Rep and source do not overlap.
336 bool
337 _M_disjunct(const _CharT* __s) const _GLIBCXX_NOEXCEPTnoexcept
338 {
339 return (less<const _CharT*>()(__s, _M_data())
340 || less<const _CharT*>()(_M_data() + this->size(), __s));
341 }
342
343 // When __n = 1 way faster than the general multichar
344 // traits_type::copy/move/assign.
345 static void
346 _S_copy(_CharT* __d, const _CharT* __s, size_type __n)
347 {
348 if (__n == 1)
349 traits_type::assign(*__d, *__s);
350 else
351 traits_type::copy(__d, __s, __n);
352 }
353
354 static void
355 _S_move(_CharT* __d, const _CharT* __s, size_type __n)
356 {
357 if (__n == 1)
358 traits_type::assign(*__d, *__s);
359 else
360 traits_type::move(__d, __s, __n);
361 }
362
363 static void
364 _S_assign(_CharT* __d, size_type __n, _CharT __c)
365 {
366 if (__n == 1)
367 traits_type::assign(*__d, __c);
368 else
369 traits_type::assign(__d, __n, __c);
370 }
371
372 // _S_copy_chars is a separate template to permit specialization
373 // to optimize for the common case of pointers as iterators.
374 template<class _Iterator>
375 static void
376 _S_copy_chars(_CharT* __p, _Iterator __k1, _Iterator __k2)
377 {
378 for (; __k1 != __k2; ++__k1, (void)++__p)
379 traits_type::assign(*__p, *__k1); // These types are off.
380 }
381
382 static void
383 _S_copy_chars(_CharT* __p, iterator __k1, iterator __k2) _GLIBCXX_NOEXCEPTnoexcept
384 { _S_copy_chars(__p, __k1.base(), __k2.base()); }
385
386 static void
387 _S_copy_chars(_CharT* __p, const_iterator __k1, const_iterator __k2)
388 _GLIBCXX_NOEXCEPTnoexcept
389 { _S_copy_chars(__p, __k1.base(), __k2.base()); }
390
391 static void
392 _S_copy_chars(_CharT* __p, _CharT* __k1, _CharT* __k2) _GLIBCXX_NOEXCEPTnoexcept
393 { _S_copy(__p, __k1, __k2 - __k1); }
394
395 static void
396 _S_copy_chars(_CharT* __p, const _CharT* __k1, const _CharT* __k2)
397 _GLIBCXX_NOEXCEPTnoexcept
398 { _S_copy(__p, __k1, __k2 - __k1); }
399
400 static int
401 _S_compare(size_type __n1, size_type __n2) _GLIBCXX_NOEXCEPTnoexcept
402 {
403 const difference_type __d = difference_type(__n1 - __n2);
404
405 if (__d > __gnu_cxx::__numeric_traits<int>::__max)
406 return __gnu_cxx::__numeric_traits<int>::__max;
407 else if (__d < __gnu_cxx::__numeric_traits<int>::__min)
408 return __gnu_cxx::__numeric_traits<int>::__min;
409 else
410 return int(__d);
411 }
412
413 void
414 _M_assign(const basic_string&);
415
416 void
417 _M_mutate(size_type __pos, size_type __len1, const _CharT* __s,
418 size_type __len2);
419
420 void
421 _M_erase(size_type __pos, size_type __n);
422
423 public:
424 // Construct/copy/destroy:
425 // NB: We overload ctors in some cases instead of using default
426 // arguments, per 17.4.4.4 para. 2 item 2.
427
428 /**
429 * @brief Default constructor creates an empty string.
430 */
431 basic_string()
432 _GLIBCXX_NOEXCEPT_IF(is_nothrow_default_constructible<_Alloc>::value)noexcept(is_nothrow_default_constructible<_Alloc>::value
)
433 : _M_dataplus(_M_local_data())
434 { _M_set_length(0); }
435
436 /**
437 * @brief Construct an empty string using allocator @a a.
438 */
439 explicit
440 basic_string(const _Alloc& __a) _GLIBCXX_NOEXCEPTnoexcept
441 : _M_dataplus(_M_local_data(), __a)
442 { _M_set_length(0); }
443
444 /**
445 * @brief Construct string with copy of value of @a __str.
446 * @param __str Source string.
447 */
448 basic_string(const basic_string& __str)
449 : _M_dataplus(_M_local_data(),
450 _Alloc_traits::_S_select_on_copy(__str._M_get_allocator()))
451 { _M_construct(__str._M_data(), __str._M_data() + __str.length()); }
452
453 // _GLIBCXX_RESOLVE_LIB_DEFECTS
454 // 2583. no way to supply an allocator for basic_string(str, pos)
455 /**
456 * @brief Construct string as copy of a substring.
457 * @param __str Source string.
458 * @param __pos Index of first character to copy from.
459 * @param __a Allocator to use.
460 */
461 basic_string(const basic_string& __str, size_type __pos,
462 const _Alloc& __a = _Alloc())
463 : _M_dataplus(_M_local_data(), __a)
464 {
465 const _CharT* __start = __str._M_data()
466 + __str._M_check(__pos, "basic_string::basic_string");
467 _M_construct(__start, __start + __str._M_limit(__pos, npos));
468 }
469
470 /**
471 * @brief Construct string as copy of a substring.
472 * @param __str Source string.
473 * @param __pos Index of first character to copy from.
474 * @param __n Number of characters to copy.
475 */
476 basic_string(const basic_string& __str, size_type __pos,
477 size_type __n)
478 : _M_dataplus(_M_local_data())
479 {
480 const _CharT* __start = __str._M_data()
481 + __str._M_check(__pos, "basic_string::basic_string");
482 _M_construct(__start, __start + __str._M_limit(__pos, __n));
483 }
484
485 /**
486 * @brief Construct string as copy of a substring.
487 * @param __str Source string.
488 * @param __pos Index of first character to copy from.
489 * @param __n Number of characters to copy.
490 * @param __a Allocator to use.
491 */
492 basic_string(const basic_string& __str, size_type __pos,
493 size_type __n, const _Alloc& __a)
494 : _M_dataplus(_M_local_data(), __a)
495 {
496 const _CharT* __start
497 = __str._M_data() + __str._M_check(__pos, "string::string");
498 _M_construct(__start, __start + __str._M_limit(__pos, __n));
499 }
500
501 /**
502 * @brief Construct string initialized by a character %array.
503 * @param __s Source character %array.
504 * @param __n Number of characters to copy.
505 * @param __a Allocator to use (default is default allocator).
506 *
507 * NB: @a __s must have at least @a __n characters, &apos;\\0&apos;
508 * has no special meaning.
509 */
510 basic_string(const _CharT* __s, size_type __n,
511 const _Alloc& __a = _Alloc())
512 : _M_dataplus(_M_local_data(), __a)
513 { _M_construct(__s, __s + __n); }
514
515 /**
516 * @brief Construct string as copy of a C string.
517 * @param __s Source C string.
518 * @param __a Allocator to use (default is default allocator).
519 */
520#if __cpp_deduction_guides201703L && ! defined _GLIBCXX_DEFINING_STRING_INSTANTIATIONS
521 // _GLIBCXX_RESOLVE_LIB_DEFECTS
522 // 3076. basic_string CTAD ambiguity
523 template<typename = _RequireAllocator<_Alloc>>
524#endif
525 basic_string(const _CharT* __s, const _Alloc& __a = _Alloc())
526 : _M_dataplus(_M_local_data(), __a)
527 { _M_construct(__s, __s ? __s + traits_type::length(__s) : __s+npos); }
528
529 /**
530 * @brief Construct string as multiple characters.
531 * @param __n Number of characters.
532 * @param __c Character to use.
533 * @param __a Allocator to use (default is default allocator).
534 */
535#if __cpp_deduction_guides201703L && ! defined _GLIBCXX_DEFINING_STRING_INSTANTIATIONS
536 // _GLIBCXX_RESOLVE_LIB_DEFECTS
537 // 3076. basic_string CTAD ambiguity
538 template<typename = _RequireAllocator<_Alloc>>
539#endif
540 basic_string(size_type __n, _CharT __c, const _Alloc& __a = _Alloc())
541 : _M_dataplus(_M_local_data(), __a)
542 { _M_construct(__n, __c); }
543
544#if __cplusplus201703L >= 201103L
545 /**
546 * @brief Move construct string.
547 * @param __str Source string.
548 *
549 * The newly-created string contains the exact contents of @a __str.
550 * @a __str is a valid, but unspecified string.
551 **/
552 basic_string(basic_string&& __str) noexcept
553 : _M_dataplus(_M_local_data(), std::move(__str._M_get_allocator()))
554 {
555 if (__str._M_is_local())
556 {
557 traits_type::copy(_M_local_buf, __str._M_local_buf,
558 _S_local_capacity + 1);
559 }
560 else
561 {
562 _M_data(__str._M_data());
563 _M_capacity(__str._M_allocated_capacity);
564 }
565
566 // Must use _M_length() here not _M_set_length() because
567 // basic_stringbuf relies on writing into unallocated capacity so
568 // we mess up the contents if we put a '\0' in the string.
569 _M_length(__str.length());
570 __str._M_data(__str._M_local_data());
571 __str._M_set_length(0);
572 }
573
574 /**
575 * @brief Construct string from an initializer %list.
576 * @param __l std::initializer_list of characters.
577 * @param __a Allocator to use (default is default allocator).
578 */
579 basic_string(initializer_list<_CharT> __l, const _Alloc& __a = _Alloc())
580 : _M_dataplus(_M_local_data(), __a)
581 { _M_construct(__l.begin(), __l.end()); }
582
583 basic_string(const basic_string& __str, const _Alloc& __a)
584 : _M_dataplus(_M_local_data(), __a)
585 { _M_construct(__str.begin(), __str.end()); }
586
587 basic_string(basic_string&& __str, const _Alloc& __a)
588 noexcept(_Alloc_traits::_S_always_equal())
589 : _M_dataplus(_M_local_data(), __a)
590 {
591 if (__str._M_is_local())
592 {
593 traits_type::copy(_M_local_buf, __str._M_local_buf,
594 _S_local_capacity + 1);
595 _M_length(__str.length());
596 __str._M_set_length(0);
597 }
598 else if (_Alloc_traits::_S_always_equal()
599 || __str.get_allocator() == __a)
600 {
601 _M_data(__str._M_data());
602 _M_length(__str.length());
603 _M_capacity(__str._M_allocated_capacity);
604 __str._M_data(__str._M_local_buf);
605 __str._M_set_length(0);
606 }
607 else
608 _M_construct(__str.begin(), __str.end());
609 }
610
611#endif // C++11
612
613 /**
614 * @brief Construct string as copy of a range.
615 * @param __beg Start of range.
616 * @param __end End of range.
617 * @param __a Allocator to use (default is default allocator).
618 */
619#if __cplusplus201703L >= 201103L
620 template<typename _InputIterator,
621 typename = std::_RequireInputIter<_InputIterator>>
622#else
623 template<typename _InputIterator>
624#endif
625 basic_string(_InputIterator __beg, _InputIterator __end,
626 const _Alloc& __a = _Alloc())
627 : _M_dataplus(_M_local_data(), __a)
628 { _M_construct(__beg, __end); }
629
630#if __cplusplus201703L >= 201703L
631 /**
632 * @brief Construct string from a substring of a string_view.
633 * @param __t Source object convertible to string view.
634 * @param __pos The index of the first character to copy from __t.
635 * @param __n The number of characters to copy from __t.
636 * @param __a Allocator to use.
637 */
638 template<typename _Tp, typename = _If_sv<_Tp, void>>
639 basic_string(const _Tp& __t, size_type __pos, size_type __n,
640 const _Alloc& __a = _Alloc())
641 : basic_string(_S_to_string_view(__t).substr(__pos, __n), __a) { }
642
643 /**
644 * @brief Construct string from a string_view.
645 * @param __t Source object convertible to string view.
646 * @param __a Allocator to use (default is default allocator).
647 */
648 template<typename _Tp, typename = _If_sv<_Tp, void>>
649 explicit
650 basic_string(const _Tp& __t, const _Alloc& __a = _Alloc())
651 : basic_string(__sv_wrapper(_S_to_string_view(__t)), __a) { }
652#endif // C++17
653
654 /**
655 * @brief Destroy the string instance.
656 */
657 ~basic_string()
658 { _M_dispose(); }
659
660 /**
661 * @brief Assign the value of @a str to this string.
662 * @param __str Source string.
663 */
664 basic_string&
665 operator=(const basic_string& __str)
666 {
667 return this->assign(__str);
668 }
669
670 /**
671 * @brief Copy contents of @a s into this string.
672 * @param __s Source null-terminated string.
673 */
674 basic_string&
675 operator=(const _CharT* __s)
676 { return this->assign(__s); }
677
678 /**
679 * @brief Set value to string of length 1.
680 * @param __c Source character.
681 *
682 * Assigning to a character makes this string length 1 and
683 * (*this)[0] == @a c.
684 */
685 basic_string&
686 operator=(_CharT __c)
687 {
688 this->assign(1, __c);
689 return *this;
690 }
691
692#if __cplusplus201703L >= 201103L
693 /**
694 * @brief Move assign the value of @a str to this string.
695 * @param __str Source string.
696 *
697 * The contents of @a str are moved into this string (without copying).
698 * @a str is a valid, but unspecified string.
699 **/
700 // _GLIBCXX_RESOLVE_LIB_DEFECTS
701 // 2063. Contradictory requirements for string move assignment
702 basic_string&
703 operator=(basic_string&& __str)
704 noexcept(_Alloc_traits::_S_nothrow_move())
705 {
706 if (!_M_is_local() && _Alloc_traits::_S_propagate_on_move_assign()
707 && !_Alloc_traits::_S_always_equal()
708 && _M_get_allocator() != __str._M_get_allocator())
709 {
710 // Destroy existing storage before replacing allocator.
711 _M_destroy(_M_allocated_capacity);
712 _M_data(_M_local_data());
713 _M_set_length(0);
714 }
715 // Replace allocator if POCMA is true.
716 std::__alloc_on_move(_M_get_allocator(), __str._M_get_allocator());
717
718 if (__str._M_is_local())
719 {
720 // We've always got room for a short string, just copy it.
721 if (__str.size())
722 this->_S_copy(_M_data(), __str._M_data(), __str.size());
723 _M_set_length(__str.size());
724 }
725 else if (_Alloc_traits::_S_propagate_on_move_assign()
726 || _Alloc_traits::_S_always_equal()
727 || _M_get_allocator() == __str._M_get_allocator())
728 {
729 // Just move the allocated pointer, our allocator can free it.
730 pointer __data = nullptr;
731 size_type __capacity;
732 if (!_M_is_local())
733 {
734 if (_Alloc_traits::_S_always_equal())
735 {
736 // __str can reuse our existing storage.
737 __data = _M_data();
738 __capacity = _M_allocated_capacity;
739 }
740 else // __str can't use it, so free it.
741 _M_destroy(_M_allocated_capacity);
742 }
743
744 _M_data(__str._M_data());
745 _M_length(__str.length());
746 _M_capacity(__str._M_allocated_capacity);
747 if (__data)
748 {
749 __str._M_data(__data);
750 __str._M_capacity(__capacity);
751 }
752 else
753 __str._M_data(__str._M_local_buf);
754 }
755 else // Need to do a deep copy
756 assign(__str);
757 __str.clear();
758 return *this;
759 }
760
761 /**
762 * @brief Set value to string constructed from initializer %list.
763 * @param __l std::initializer_list.
764 */
765 basic_string&
766 operator=(initializer_list<_CharT> __l)
767 {
768 this->assign(__l.begin(), __l.size());
769 return *this;
770 }
771#endif // C++11
772
773#if __cplusplus201703L >= 201703L
774 /**
775 * @brief Set value to string constructed from a string_view.
776 * @param __svt An object convertible to string_view.
777 */
778 template<typename _Tp>
779 _If_sv<_Tp, basic_string&>
780 operator=(const _Tp& __svt)
781 { return this->assign(__svt); }
782
783 /**
784 * @brief Convert to a string_view.
785 * @return A string_view.
786 */
787 operator __sv_type() const noexcept
788 { return __sv_type(data(), size()); }
789#endif // C++17
790
791 // Iterators:
792 /**
793 * Returns a read/write iterator that points to the first character in
794 * the %string.
795 */
796 iterator
797 begin() _GLIBCXX_NOEXCEPTnoexcept
798 { return iterator(_M_data()); }
799
800 /**
801 * Returns a read-only (constant) iterator that points to the first
802 * character in the %string.
803 */
804 const_iterator
805 begin() const _GLIBCXX_NOEXCEPTnoexcept
806 { return const_iterator(_M_data()); }
807
808 /**
809 * Returns a read/write iterator that points one past the last
810 * character in the %string.
811 */
812 iterator
813 end() _GLIBCXX_NOEXCEPTnoexcept
814 { return iterator(_M_data() + this->size()); }
815
816 /**
817 * Returns a read-only (constant) iterator that points one past the
818 * last character in the %string.
819 */
820 const_iterator
821 end() const _GLIBCXX_NOEXCEPTnoexcept
822 { return const_iterator(_M_data() + this->size()); }
823
824 /**
825 * Returns a read/write reverse iterator that points to the last
826 * character in the %string. Iteration is done in reverse element
827 * order.
828 */
829 reverse_iterator
830 rbegin() _GLIBCXX_NOEXCEPTnoexcept
831 { return reverse_iterator(this->end()); }
832
833 /**
834 * Returns a read-only (constant) reverse iterator that points
835 * to the last character in the %string. Iteration is done in
836 * reverse element order.
837 */
838 const_reverse_iterator
839 rbegin() const _GLIBCXX_NOEXCEPTnoexcept
840 { return const_reverse_iterator(this->end()); }
841
842 /**
843 * Returns a read/write reverse iterator that points to one before the
844 * first character in the %string. Iteration is done in reverse
845 * element order.
846 */
847 reverse_iterator
848 rend() _GLIBCXX_NOEXCEPTnoexcept
849 { return reverse_iterator(this->begin()); }
850
851 /**
852 * Returns a read-only (constant) reverse iterator that points
853 * to one before the first character in the %string. Iteration
854 * is done in reverse element order.
855 */
856 const_reverse_iterator
857 rend() const _GLIBCXX_NOEXCEPTnoexcept
858 { return const_reverse_iterator(this->begin()); }
859
860#if __cplusplus201703L >= 201103L
861 /**
862 * Returns a read-only (constant) iterator that points to the first
863 * character in the %string.
864 */
865 const_iterator
866 cbegin() const noexcept
867 { return const_iterator(this->_M_data()); }
868
869 /**
870 * Returns a read-only (constant) iterator that points one past the
871 * last character in the %string.
872 */
873 const_iterator
874 cend() const noexcept
875 { return const_iterator(this->_M_data() + this->size()); }
876
877 /**
878 * Returns a read-only (constant) reverse iterator that points
879 * to the last character in the %string. Iteration is done in
880 * reverse element order.
881 */
882 const_reverse_iterator
883 crbegin() const noexcept
884 { return const_reverse_iterator(this->end()); }
885
886 /**
887 * Returns a read-only (constant) reverse iterator that points
888 * to one before the first character in the %string. Iteration
889 * is done in reverse element order.
890 */
891 const_reverse_iterator
892 crend() const noexcept
893 { return const_reverse_iterator(this->begin()); }
894#endif
895
896 public:
897 // Capacity:
898 /// Returns the number of characters in the string, not including any
899 /// null-termination.
900 size_type
901 size() const _GLIBCXX_NOEXCEPTnoexcept
902 { return _M_string_length; }
903
904 /// Returns the number of characters in the string, not including any
905 /// null-termination.
906 size_type
907 length() const _GLIBCXX_NOEXCEPTnoexcept
908 { return _M_string_length; }
909
910 /// Returns the size() of the largest possible %string.
911 size_type
912 max_size() const _GLIBCXX_NOEXCEPTnoexcept
913 { return (_Alloc_traits::max_size(_M_get_allocator()) - 1) / 2; }
914
915 /**
916 * @brief Resizes the %string to the specified number of characters.
917 * @param __n Number of characters the %string should contain.
918 * @param __c Character to fill any new elements.
919 *
920 * This function will %resize the %string to the specified
921 * number of characters. If the number is smaller than the
922 * %string's current size the %string is truncated, otherwise
923 * the %string is extended and new elements are %set to @a __c.
924 */
925 void
926 resize(size_type __n, _CharT __c);
927
928 /**
929 * @brief Resizes the %string to the specified number of characters.
930 * @param __n Number of characters the %string should contain.
931 *
932 * This function will resize the %string to the specified length. If
933 * the new size is smaller than the %string's current size the %string
934 * is truncated, otherwise the %string is extended and new characters
935 * are default-constructed. For basic types such as char, this means
936 * setting them to 0.
937 */
938 void
939 resize(size_type __n)
940 { this->resize(__n, _CharT()); }
941
942#if __cplusplus201703L >= 201103L
943 /// A non-binding request to reduce capacity() to size().
944 void
945 shrink_to_fit() noexcept
946 {
947#if __cpp_exceptions
948 if (capacity() > size())
949 {
950 try
951 { reserve(0); }
952 catch(...)
953 { }
954 }
955#endif
956 }
957#endif
958
959 /**
960 * Returns the total number of characters that the %string can hold
961 * before needing to allocate more memory.
962 */
963 size_type
964 capacity() const _GLIBCXX_NOEXCEPTnoexcept
965 {
966 return _M_is_local() ? size_type(_S_local_capacity)
967 : _M_allocated_capacity;
968 }
969
970 /**
971 * @brief Attempt to preallocate enough memory for specified number of
972 * characters.
973 * @param __res_arg Number of characters required.
974 * @throw std::length_error If @a __res_arg exceeds @c max_size().
975 *
976 * This function attempts to reserve enough memory for the
977 * %string to hold the specified number of characters. If the
978 * number requested is more than max_size(), length_error is
979 * thrown.
980 *
981 * The advantage of this function is that if optimal code is a
982 * necessity and the user can determine the string length that will be
983 * required, the user can reserve the memory in %advance, and thus
984 * prevent a possible reallocation of memory and copying of %string
985 * data.
986 */
987 void
988 reserve(size_type __res_arg = 0);
989
990 /**
991 * Erases the string, making it empty.
992 */
993 void
994 clear() _GLIBCXX_NOEXCEPTnoexcept
995 { _M_set_length(0); }
996
997 /**
998 * Returns true if the %string is empty. Equivalent to
999 * <code>*this == ""</code>.
1000 */
1001 _GLIBCXX_NODISCARD[[__nodiscard__]] bool
1002 empty() const _GLIBCXX_NOEXCEPTnoexcept
1003 { return this->size() == 0; }
1004
1005 // Element access:
1006 /**
1007 * @brief Subscript access to the data contained in the %string.
1008 * @param __pos The index of the character to access.
1009 * @return Read-only (constant) reference to the character.
1010 *
1011 * This operator allows for easy, array-style, data access.
1012 * Note that data access with this operator is unchecked and
1013 * out_of_range lookups are not defined. (For checked lookups
1014 * see at().)
1015 */
1016 const_reference
1017 operator[] (size_type __pos) const _GLIBCXX_NOEXCEPTnoexcept
1018 {
1019 __glibcxx_assert(__pos <= size())do { if (! (__pos <= size())) std::__replacement_assert("/usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/basic_string.h"
, 1019, __PRETTY_FUNCTION__, "__pos <= size()"); } while (
false)
;
1020 return _M_data()[__pos];
1021 }
1022
1023 /**
1024 * @brief Subscript access to the data contained in the %string.
1025 * @param __pos The index of the character to access.
1026 * @return Read/write reference to the character.
1027 *
1028 * This operator allows for easy, array-style, data access.
1029 * Note that data access with this operator is unchecked and
1030 * out_of_range lookups are not defined. (For checked lookups
1031 * see at().)
1032 */
1033 reference
1034 operator[](size_type __pos)
1035 {
1036 // Allow pos == size() both in C++98 mode, as v3 extension,
1037 // and in C++11 mode.
1038 __glibcxx_assert(__pos <= size())do { if (! (__pos <= size())) std::__replacement_assert("/usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/basic_string.h"
, 1038, __PRETTY_FUNCTION__, "__pos <= size()"); } while (
false)
;
1039 // In pedantic mode be strict in C++98 mode.
1040 _GLIBCXX_DEBUG_PEDASSERT(__cplusplus >= 201103L || __pos < size());
1041 return _M_data()[__pos];
1042 }
1043
1044 /**
1045 * @brief Provides access to the data contained in the %string.
1046 * @param __n The index of the character to access.
1047 * @return Read-only (const) reference to the character.
1048 * @throw std::out_of_range If @a n is an invalid index.
1049 *
1050 * This function provides for safer data access. The parameter is
1051 * first checked that it is in the range of the string. The function
1052 * throws out_of_range if the check fails.
1053 */
1054 const_reference
1055 at(size_type __n) const
1056 {
1057 if (__n >= this->size())
1058 __throw_out_of_range_fmt(__N("basic_string::at: __n "("basic_string::at: __n " "(which is %zu) >= this->size() "
"(which is %zu)")
1059 "(which is %zu) >= this->size() "("basic_string::at: __n " "(which is %zu) >= this->size() "
"(which is %zu)")
1060 "(which is %zu)")("basic_string::at: __n " "(which is %zu) >= this->size() "
"(which is %zu)")
,
1061 __n, this->size());
1062 return _M_data()[__n];
1063 }
1064
1065 /**
1066 * @brief Provides access to the data contained in the %string.
1067 * @param __n The index of the character to access.
1068 * @return Read/write reference to the character.
1069 * @throw std::out_of_range If @a n is an invalid index.
1070 *
1071 * This function provides for safer data access. The parameter is
1072 * first checked that it is in the range of the string. The function
1073 * throws out_of_range if the check fails.
1074 */
1075 reference
1076 at(size_type __n)
1077 {
1078 if (__n >= size())
1079 __throw_out_of_range_fmt(__N("basic_string::at: __n "("basic_string::at: __n " "(which is %zu) >= this->size() "
"(which is %zu)")
1080 "(which is %zu) >= this->size() "("basic_string::at: __n " "(which is %zu) >= this->size() "
"(which is %zu)")
1081 "(which is %zu)")("basic_string::at: __n " "(which is %zu) >= this->size() "
"(which is %zu)")
,
1082 __n, this->size());
1083 return _M_data()[__n];
1084 }
1085
1086#if __cplusplus201703L >= 201103L
1087 /**
1088 * Returns a read/write reference to the data at the first
1089 * element of the %string.
1090 */
1091 reference
1092 front() noexcept
1093 {
1094 __glibcxx_assert(!empty())do { if (! (!empty())) std::__replacement_assert("/usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/basic_string.h"
, 1094, __PRETTY_FUNCTION__, "!empty()"); } while (false)
;
1095 return operator[](0);
1096 }
1097
1098 /**
1099 * Returns a read-only (constant) reference to the data at the first
1100 * element of the %string.
1101 */
1102 const_reference
1103 front() const noexcept
1104 {
1105 __glibcxx_assert(!empty())do { if (! (!empty())) std::__replacement_assert("/usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/basic_string.h"
, 1105, __PRETTY_FUNCTION__, "!empty()"); } while (false)
;
1106 return operator[](0);
1107 }
1108
1109 /**
1110 * Returns a read/write reference to the data at the last
1111 * element of the %string.
1112 */
1113 reference
1114 back() noexcept
1115 {
1116 __glibcxx_assert(!empty())do { if (! (!empty())) std::__replacement_assert("/usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/basic_string.h"
, 1116, __PRETTY_FUNCTION__, "!empty()"); } while (false)
;
1117 return operator[](this->size() - 1);
1118 }
1119
1120 /**
1121 * Returns a read-only (constant) reference to the data at the
1122 * last element of the %string.
1123 */
1124 const_reference
1125 back() const noexcept
1126 {
1127 __glibcxx_assert(!empty())do { if (! (!empty())) std::__replacement_assert("/usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/basic_string.h"
, 1127, __PRETTY_FUNCTION__, "!empty()"); } while (false)
;
1128 return operator[](this->size() - 1);
1129 }
1130#endif
1131
1132 // Modifiers:
1133 /**
1134 * @brief Append a string to this string.
1135 * @param __str The string to append.
1136 * @return Reference to this string.
1137 */
1138 basic_string&
1139 operator+=(const basic_string& __str)
1140 { return this->append(__str); }
1141
1142 /**
1143 * @brief Append a C string.
1144 * @param __s The C string to append.
1145 * @return Reference to this string.
1146 */
1147 basic_string&
1148 operator+=(const _CharT* __s)
1149 { return this->append(__s); }
1150
1151 /**
1152 * @brief Append a character.
1153 * @param __c The character to append.
1154 * @return Reference to this string.
1155 */
1156 basic_string&
1157 operator+=(_CharT __c)
1158 {
1159 this->push_back(__c);
1160 return *this;
1161 }
1162
1163#if __cplusplus201703L >= 201103L
1164 /**
1165 * @brief Append an initializer_list of characters.
1166 * @param __l The initializer_list of characters to be appended.
1167 * @return Reference to this string.
1168 */
1169 basic_string&
1170 operator+=(initializer_list<_CharT> __l)
1171 { return this->append(__l.begin(), __l.size()); }
1172#endif // C++11
1173
1174#if __cplusplus201703L >= 201703L
1175 /**
1176 * @brief Append a string_view.
1177 * @param __svt An object convertible to string_view to be appended.
1178 * @return Reference to this string.
1179 */
1180 template<typename _Tp>
1181 _If_sv<_Tp, basic_string&>
1182 operator+=(const _Tp& __svt)
1183 { return this->append(__svt); }
1184#endif // C++17
1185
1186 /**
1187 * @brief Append a string to this string.
1188 * @param __str The string to append.
1189 * @return Reference to this string.
1190 */
1191 basic_string&
1192 append(const basic_string& __str)
1193 { return _M_append(__str._M_data(), __str.size()); }
1194
1195 /**
1196 * @brief Append a substring.
1197 * @param __str The string to append.
1198 * @param __pos Index of the first character of str to append.
1199 * @param __n The number of characters to append.
1200 * @return Reference to this string.
1201 * @throw std::out_of_range if @a __pos is not a valid index.
1202 *
1203 * This function appends @a __n characters from @a __str
1204 * starting at @a __pos to this string. If @a __n is is larger
1205 * than the number of available characters in @a __str, the
1206 * remainder of @a __str is appended.
1207 */
1208 basic_string&
1209 append(const basic_string& __str, size_type __pos, size_type __n = npos)
1210 { return _M_append(__str._M_data()
1211 + __str._M_check(__pos, "basic_string::append"),
1212 __str._M_limit(__pos, __n)); }
1213
1214 /**
1215 * @brief Append a C substring.
1216 * @param __s The C string to append.
1217 * @param __n The number of characters to append.
1218 * @return Reference to this string.
1219 */
1220 basic_string&
1221 append(const _CharT* __s, size_type __n)
1222 {
1223 __glibcxx_requires_string_len(__s, __n);
1224 _M_check_length(size_type(0), __n, "basic_string::append");
1225 return _M_append(__s, __n);
1226 }
1227
1228 /**
1229 * @brief Append a C string.
1230 * @param __s The C string to append.
1231 * @return Reference to this string.
1232 */
1233 basic_string&
1234 append(const _CharT* __s)
1235 {
1236 __glibcxx_requires_string(__s);
1237 const size_type __n = traits_type::length(__s);
1238 _M_check_length(size_type(0), __n, "basic_string::append");
1239 return _M_append(__s, __n);
1240 }
1241
1242 /**
1243 * @brief Append multiple characters.
1244 * @param __n The number of characters to append.
1245 * @param __c The character to use.
1246 * @return Reference to this string.
1247 *
1248 * Appends __n copies of __c to this string.
1249 */
1250 basic_string&
1251 append(size_type __n, _CharT __c)
1252 { return _M_replace_aux(this->size(), size_type(0), __n, __c); }
1253
1254#if __cplusplus201703L >= 201103L
1255 /**
1256 * @brief Append an initializer_list of characters.
1257 * @param __l The initializer_list of characters to append.
1258 * @return Reference to this string.
1259 */
1260 basic_string&
1261 append(initializer_list<_CharT> __l)
1262 { return this->append(__l.begin(), __l.size()); }
1263#endif // C++11
1264
1265 /**
1266 * @brief Append a range of characters.
1267 * @param __first Iterator referencing the first character to append.
1268 * @param __last Iterator marking the end of the range.
1269 * @return Reference to this string.
1270 *
1271 * Appends characters in the range [__first,__last) to this string.
1272 */
1273#if __cplusplus201703L >= 201103L
1274 template<class _InputIterator,
1275 typename = std::_RequireInputIter<_InputIterator>>
1276#else
1277 template<class _InputIterator>
1278#endif
1279 basic_string&
1280 append(_InputIterator __first, _InputIterator __last)
1281 { return this->replace(end(), end(), __first, __last); }
1282
1283#if __cplusplus201703L >= 201703L
1284 /**
1285 * @brief Append a string_view.
1286 * @param __svt An object convertible to string_view to be appended.
1287 * @return Reference to this string.
1288 */
1289 template<typename _Tp>
1290 _If_sv<_Tp, basic_string&>
1291 append(const _Tp& __svt)
1292 {
1293 __sv_type __sv = __svt;
1294 return this->append(__sv.data(), __sv.size());
1295 }
1296
1297 /**
1298 * @brief Append a range of characters from a string_view.
1299 * @param __svt An object convertible to string_view to be appended from.
1300 * @param __pos The position in the string_view to append from.
1301 * @param __n The number of characters to append from the string_view.
1302 * @return Reference to this string.
1303 */
1304 template<typename _Tp>
1305 _If_sv<_Tp, basic_string&>
1306 append(const _Tp& __svt, size_type __pos, size_type __n = npos)
1307 {
1308 __sv_type __sv = __svt;
1309 return _M_append(__sv.data()
1310 + std::__sv_check(__sv.size(), __pos, "basic_string::append"),
1311 std::__sv_limit(__sv.size(), __pos, __n));
1312 }
1313#endif // C++17
1314
1315 /**
1316 * @brief Append a single character.
1317 * @param __c Character to append.
1318 */
1319 void
1320 push_back(_CharT __c)
1321 {
1322 const size_type __size = this->size();
1323 if (__size + 1 > this->capacity())
1324 this->_M_mutate(__size, size_type(0), 0, size_type(1));
1325 traits_type::assign(this->_M_data()[__size], __c);
1326 this->_M_set_length(__size + 1);
1327 }
1328
1329 /**
1330 * @brief Set value to contents of another string.
1331 * @param __str Source string to use.
1332 * @return Reference to this string.
1333 */
1334 basic_string&
1335 assign(const basic_string& __str)
1336 {
1337#if __cplusplus201703L >= 201103L
1338 if (_Alloc_traits::_S_propagate_on_copy_assign())
1339 {
1340 if (!_Alloc_traits::_S_always_equal() && !_M_is_local()
1341 && _M_get_allocator() != __str._M_get_allocator())
1342 {
1343 // Propagating allocator cannot free existing storage so must
1344 // deallocate it before replacing current allocator.
1345 if (__str.size() <= _S_local_capacity)
1346 {
1347 _M_destroy(_M_allocated_capacity);
1348 _M_data(_M_local_data());
1349 _M_set_length(0);
1350 }
1351 else
1352 {
1353 const auto __len = __str.size();
1354 auto __alloc = __str._M_get_allocator();
1355 // If this allocation throws there are no effects:
1356 auto __ptr = _Alloc_traits::allocate(__alloc, __len + 1);
1357 _M_destroy(_M_allocated_capacity);
1358 _M_data(__ptr);
1359 _M_capacity(__len);
1360 _M_set_length(__len);
1361 }
1362 }
1363 std::__alloc_on_copy(_M_get_allocator(), __str._M_get_allocator());
1364 }
1365#endif
1366 this->_M_assign(__str);
1367 return *this;
1368 }
1369
1370#if __cplusplus201703L >= 201103L
1371 /**
1372 * @brief Set value to contents of another string.
1373 * @param __str Source string to use.
1374 * @return Reference to this string.
1375 *
1376 * This function sets this string to the exact contents of @a __str.
1377 * @a __str is a valid, but unspecified string.
1378 */
1379 basic_string&
1380 assign(basic_string&& __str)
1381 noexcept(_Alloc_traits::_S_nothrow_move())
1382 {
1383 // _GLIBCXX_RESOLVE_LIB_DEFECTS
1384 // 2063. Contradictory requirements for string move assignment
1385 return *this = std::move(__str);
1386 }
1387#endif // C++11
1388
1389 /**
1390 * @brief Set value to a substring of a string.
1391 * @param __str The string to use.
1392 * @param __pos Index of the first character of str.
1393 * @param __n Number of characters to use.
1394 * @return Reference to this string.
1395 * @throw std::out_of_range if @a pos is not a valid index.
1396 *
1397 * This function sets this string to the substring of @a __str
1398 * consisting of @a __n characters at @a __pos. If @a __n is
1399 * is larger than the number of available characters in @a
1400 * __str, the remainder of @a __str is used.
1401 */
1402 basic_string&
1403 assign(const basic_string& __str, size_type __pos, size_type __n = npos)
1404 { return _M_replace(size_type(0), this->size(), __str._M_data()
1405 + __str._M_check(__pos, "basic_string::assign"),
1406 __str._M_limit(__pos, __n)); }
1407
1408 /**
1409 * @brief Set value to a C substring.
1410 * @param __s The C string to use.
1411 * @param __n Number of characters to use.
1412 * @return Reference to this string.
1413 *
1414 * This function sets the value of this string to the first @a __n
1415 * characters of @a __s. If @a __n is is larger than the number of
1416 * available characters in @a __s, the remainder of @a __s is used.
1417 */
1418 basic_string&
1419 assign(const _CharT* __s, size_type __n)
1420 {
1421 __glibcxx_requires_string_len(__s, __n);
1422 return _M_replace(size_type(0), this->size(), __s, __n);
1423 }
1424
1425 /**
1426 * @brief Set value to contents of a C string.
1427 * @param __s The C string to use.
1428 * @return Reference to this string.
1429 *
1430 * This function sets the value of this string to the value of @a __s.
1431 * The data is copied, so there is no dependence on @a __s once the
1432 * function returns.
1433 */
1434 basic_string&
1435 assign(const _CharT* __s)
1436 {
1437 __glibcxx_requires_string(__s);
1438 return _M_replace(size_type(0), this->size(), __s,
1439 traits_type::length(__s));
1440 }
1441
1442 /**
1443 * @brief Set value to multiple characters.
1444 * @param __n Length of the resulting string.
1445 * @param __c The character to use.
1446 * @return Reference to this string.
1447 *
1448 * This function sets the value of this string to @a __n copies of
1449 * character @a __c.
1450 */
1451 basic_string&
1452 assign(size_type __n, _CharT __c)
1453 { return _M_replace_aux(size_type(0), this->size(), __n, __c); }
1454
1455 /**
1456 * @brief Set value to a range of characters.
1457 * @param __first Iterator referencing the first character to append.
1458 * @param __last Iterator marking the end of the range.
1459 * @return Reference to this string.
1460 *
1461 * Sets value of string to characters in the range [__first,__last).
1462 */
1463#if __cplusplus201703L >= 201103L
1464 template<class _InputIterator,
1465 typename = std::_RequireInputIter<_InputIterator>>
1466#else
1467 template<class _InputIterator>
1468#endif
1469 basic_string&
1470 assign(_InputIterator __first, _InputIterator __last)
1471 { return this->replace(begin(), end(), __first, __last); }
1472
1473#if __cplusplus201703L >= 201103L
1474 /**
1475 * @brief Set value to an initializer_list of characters.
1476 * @param __l The initializer_list of characters to assign.
1477 * @return Reference to this string.
1478 */
1479 basic_string&
1480 assign(initializer_list<_CharT> __l)
1481 { return this->assign(__l.begin(), __l.size()); }
1482#endif // C++11
1483
1484#if __cplusplus201703L >= 201703L
1485 /**
1486 * @brief Set value from a string_view.
1487 * @param __svt The source object convertible to string_view.
1488 * @return Reference to this string.
1489 */
1490 template<typename _Tp>
1491 _If_sv<_Tp, basic_string&>
1492 assign(const _Tp& __svt)
1493 {
1494 __sv_type __sv = __svt;
1495 return this->assign(__sv.data(), __sv.size());
1496 }
1497
1498 /**
1499 * @brief Set value from a range of characters in a string_view.
1500 * @param __svt The source object convertible to string_view.
1501 * @param __pos The position in the string_view to assign from.
1502 * @param __n The number of characters to assign.
1503 * @return Reference to this string.
1504 */
1505 template<typename _Tp>
1506 _If_sv<_Tp, basic_string&>
1507 assign(const _Tp& __svt, size_type __pos, size_type __n = npos)
1508 {
1509 __sv_type __sv = __svt;
1510 return _M_replace(size_type(0), this->size(),
1511 __sv.data()
1512 + std::__sv_check(__sv.size(), __pos, "basic_string::assign"),
1513 std::__sv_limit(__sv.size(), __pos, __n));
1514 }
1515#endif // C++17
1516
1517#if __cplusplus201703L >= 201103L
1518 /**
1519 * @brief Insert multiple characters.
1520 * @param __p Const_iterator referencing location in string to
1521 * insert at.
1522 * @param __n Number of characters to insert
1523 * @param __c The character to insert.
1524 * @return Iterator referencing the first inserted char.
1525 * @throw std::length_error If new length exceeds @c max_size().
1526 *
1527 * Inserts @a __n copies of character @a __c starting at the
1528 * position referenced by iterator @a __p. If adding
1529 * characters causes the length to exceed max_size(),
1530 * length_error is thrown. The value of the string doesn't
1531 * change if an error is thrown.
1532 */
1533 iterator
1534 insert(const_iterator __p, size_type __n, _CharT __c)
1535 {
1536 _GLIBCXX_DEBUG_PEDASSERT(__p >= begin() && __p <= end());
1537 const size_type __pos = __p - begin();
1538 this->replace(__p, __p, __n, __c);
1539 return iterator(this->_M_data() + __pos);
1540 }
1541#else
1542 /**
1543 * @brief Insert multiple characters.
1544 * @param __p Iterator referencing location in string to insert at.
1545 * @param __n Number of characters to insert
1546 * @param __c The character to insert.
1547 * @throw std::length_error If new length exceeds @c max_size().
1548 *
1549 * Inserts @a __n copies of character @a __c starting at the
1550 * position referenced by iterator @a __p. If adding
1551 * characters causes the length to exceed max_size(),
1552 * length_error is thrown. The value of the string doesn't
1553 * change if an error is thrown.
1554 */
1555 void
1556 insert(iterator __p, size_type __n, _CharT __c)
1557 { this->replace(__p, __p, __n, __c); }
1558#endif
1559
1560#if __cplusplus201703L >= 201103L
1561 /**
1562 * @brief Insert a range of characters.
1563 * @param __p Const_iterator referencing location in string to
1564 * insert at.
1565 * @param __beg Start of range.
1566 * @param __end End of range.
1567 * @return Iterator referencing the first inserted char.
1568 * @throw std::length_error If new length exceeds @c max_size().
1569 *
1570 * Inserts characters in range [beg,end). If adding characters
1571 * causes the length to exceed max_size(), length_error is
1572 * thrown. The value of the string doesn't change if an error
1573 * is thrown.
1574 */
1575 template<class _InputIterator,
1576 typename = std::_RequireInputIter<_InputIterator>>
1577 iterator
1578 insert(const_iterator __p, _InputIterator __beg, _InputIterator __end)
1579 {
1580 _GLIBCXX_DEBUG_PEDASSERT(__p >= begin() && __p <= end());
1581 const size_type __pos = __p - begin();
1582 this->replace(__p, __p, __beg, __end);
1583 return iterator(this->_M_data() + __pos);
1584 }
1585#else
1586 /**
1587 * @brief Insert a range of characters.
1588 * @param __p Iterator referencing location in string to insert at.
1589 * @param __beg Start of range.
1590 * @param __end End of range.
1591 * @throw std::length_error If new length exceeds @c max_size().
1592 *
1593 * Inserts characters in range [__beg,__end). If adding
1594 * characters causes the length to exceed max_size(),
1595 * length_error is thrown. The value of the string doesn't
1596 * change if an error is thrown.
1597 */
1598 template<class _InputIterator>
1599 void
1600 insert(iterator __p, _InputIterator __beg, _InputIterator __end)
1601 { this->replace(__p, __p, __beg, __end); }
1602#endif
1603
1604#if __cplusplus201703L >= 201103L
1605 /**
1606 * @brief Insert an initializer_list of characters.
1607 * @param __p Iterator referencing location in string to insert at.
1608 * @param __l The initializer_list of characters to insert.
1609 * @throw std::length_error If new length exceeds @c max_size().
1610 */
1611 iterator
1612 insert(const_iterator __p, initializer_list<_CharT> __l)
1613 { return this->insert(__p, __l.begin(), __l.end()); }
1614
1615#ifdef _GLIBCXX_DEFINING_STRING_INSTANTIATIONS
1616 // See PR libstdc++/83328
1617 void
1618 insert(iterator __p, initializer_list<_CharT> __l)
1619 {
1620 _GLIBCXX_DEBUG_PEDASSERT(__p >= begin() && __p <= end());
1621 this->insert(__p - begin(), __l.begin(), __l.size());
1622 }
1623#endif
1624#endif // C++11
1625
1626 /**
1627 * @brief Insert value of a string.
1628 * @param __pos1 Position in string to insert at.
1629 * @param __str The string to insert.
1630 * @return Reference to this string.
1631 * @throw std::length_error If new length exceeds @c max_size().
1632 *
1633 * Inserts value of @a __str starting at @a __pos1. If adding
1634 * characters causes the length to exceed max_size(),
1635 * length_error is thrown. The value of the string doesn't
1636 * change if an error is thrown.
1637 */
1638 basic_string&
1639 insert(size_type __pos1, const basic_string& __str)
1640 { return this->replace(__pos1, size_type(0),
1641 __str._M_data(), __str.size()); }
1642
1643 /**
1644 * @brief Insert a substring.
1645 * @param __pos1 Position in string to insert at.
1646 * @param __str The string to insert.
1647 * @param __pos2 Start of characters in str to insert.
1648 * @param __n Number of characters to insert.
1649 * @return Reference to this string.
1650 * @throw std::length_error If new length exceeds @c max_size().
1651 * @throw std::out_of_range If @a pos1 > size() or
1652 * @a __pos2 > @a str.size().
1653 *
1654 * Starting at @a pos1, insert @a __n character of @a __str
1655 * beginning with @a __pos2. If adding characters causes the
1656 * length to exceed max_size(), length_error is thrown. If @a
1657 * __pos1 is beyond the end of this string or @a __pos2 is
1658 * beyond the end of @a __str, out_of_range is thrown. The
1659 * value of the string doesn't change if an error is thrown.
1660 */
1661 basic_string&
1662 insert(size_type __pos1, const basic_string& __str,
1663 size_type __pos2, size_type __n = npos)
1664 { return this->replace(__pos1, size_type(0), __str._M_data()
1665 + __str._M_check(__pos2, "basic_string::insert"),
1666 __str._M_limit(__pos2, __n)); }
1667
1668 /**
1669 * @brief Insert a C substring.
1670 * @param __pos Position in string to insert at.
1671 * @param __s The C string to insert.
1672 * @param __n The number of characters to insert.
1673 * @return Reference to this string.
1674 * @throw std::length_error If new length exceeds @c max_size().
1675 * @throw std::out_of_range If @a __pos is beyond the end of this
1676 * string.
1677 *
1678 * Inserts the first @a __n characters of @a __s starting at @a
1679 * __pos. If adding characters causes the length to exceed
1680 * max_size(), length_error is thrown. If @a __pos is beyond
1681 * end(), out_of_range is thrown. The value of the string
1682 * doesn't change if an error is thrown.
1683 */
1684 basic_string&
1685 insert(size_type __pos, const _CharT* __s, size_type __n)
1686 { return this->replace(__pos, size_type(0), __s, __n); }
1687
1688 /**
1689 * @brief Insert a C string.
1690 * @param __pos Position in string to insert at.
1691 * @param __s The C string to insert.
1692 * @return Reference to this string.
1693 * @throw std::length_error If new length exceeds @c max_size().
1694 * @throw std::out_of_range If @a pos is beyond the end of this
1695 * string.
1696 *
1697 * Inserts the first @a n characters of @a __s starting at @a __pos. If
1698 * adding characters causes the length to exceed max_size(),
1699 * length_error is thrown. If @a __pos is beyond end(), out_of_range is
1700 * thrown. The value of the string doesn't change if an error is
1701 * thrown.
1702 */
1703 basic_string&
1704 insert(size_type __pos, const _CharT* __s)
1705 {
1706 __glibcxx_requires_string(__s);
1707 return this->replace(__pos, size_type(0), __s,
1708 traits_type::length(__s));
1709 }
1710
1711 /**
1712 * @brief Insert multiple characters.
1713 * @param __pos Index in string to insert at.
1714 * @param __n Number of characters to insert
1715 * @param __c The character to insert.
1716 * @return Reference to this string.
1717 * @throw std::length_error If new length exceeds @c max_size().
1718 * @throw std::out_of_range If @a __pos is beyond the end of this
1719 * string.
1720 *
1721 * Inserts @a __n copies of character @a __c starting at index
1722 * @a __pos. If adding characters causes the length to exceed
1723 * max_size(), length_error is thrown. If @a __pos > length(),
1724 * out_of_range is thrown. The value of the string doesn't
1725 * change if an error is thrown.
1726 */
1727 basic_string&
1728 insert(size_type __pos, size_type __n, _CharT __c)
1729 { return _M_replace_aux(_M_check(__pos, "basic_string::insert"),
1730 size_type(0), __n, __c); }
1731
1732 /**
1733 * @brief Insert one character.
1734 * @param __p Iterator referencing position in string to insert at.
1735 * @param __c The character to insert.
1736 * @return Iterator referencing newly inserted char.
1737 * @throw std::length_error If new length exceeds @c max_size().
1738 *
1739 * Inserts character @a __c at position referenced by @a __p.
1740 * If adding character causes the length to exceed max_size(),
1741 * length_error is thrown. If @a __p is beyond end of string,
1742 * out_of_range is thrown. The value of the string doesn't
1743 * change if an error is thrown.
1744 */
1745 iterator
1746 insert(__const_iterator __p, _CharT __c)
1747 {
1748 _GLIBCXX_DEBUG_PEDASSERT(__p >= begin() && __p <= end());
1749 const size_type __pos = __p - begin();
1750 _M_replace_aux(__pos, size_type(0), size_type(1), __c);
1751 return iterator(_M_data() + __pos);
1752 }
1753
1754#if __cplusplus201703L >= 201703L
1755 /**
1756 * @brief Insert a string_view.
1757 * @param __pos Position in string to insert at.
1758 * @param __svt The object convertible to string_view to insert.
1759 * @return Reference to this string.
1760 */
1761 template<typename _Tp>
1762 _If_sv<_Tp, basic_string&>
1763 insert(size_type __pos, const _Tp& __svt)
1764 {
1765 __sv_type __sv = __svt;
1766 return this->insert(__pos, __sv.data(), __sv.size());
1767 }
1768
1769 /**
1770 * @brief Insert a string_view.
1771 * @param __pos1 Position in string to insert at.
1772 * @param __svt The object convertible to string_view to insert from.
1773 * @param __pos2 Start of characters in str to insert.
1774 * @param __n The number of characters to insert.
1775 * @return Reference to this string.
1776 */
1777 template<typename _Tp>
1778 _If_sv<_Tp, basic_string&>
1779 insert(size_type __pos1, const _Tp& __svt,
1780 size_type __pos2, size_type __n = npos)
1781 {
1782 __sv_type __sv = __svt;
1783 return this->replace(__pos1, size_type(0),
1784 __sv.data()
1785 + std::__sv_check(__sv.size(), __pos2, "basic_string::insert"),
1786 std::__sv_limit(__sv.size(), __pos2, __n));
1787 }
1788#endif // C++17
1789
1790 /**
1791 * @brief Remove characters.
1792 * @param __pos Index of first character to remove (default 0).
1793 * @param __n Number of characters to remove (default remainder).
1794 * @return Reference to this string.
1795 * @throw std::out_of_range If @a pos is beyond the end of this
1796 * string.
1797 *
1798 * Removes @a __n characters from this string starting at @a
1799 * __pos. The length of the string is reduced by @a __n. If
1800 * there are < @a __n characters to remove, the remainder of
1801 * the string is truncated. If @a __p is beyond end of string,
1802 * out_of_range is thrown. The value of the string doesn't
1803 * change if an error is thrown.
1804 */
1805 basic_string&
1806 erase(size_type __pos = 0, size_type __n = npos)
1807 {
1808 _M_check(__pos, "basic_string::erase");
1809 if (__n == npos)
1810 this->_M_set_length(__pos);
1811 else if (__n != 0)
1812 this->_M_erase(__pos, _M_limit(__pos, __n));
1813 return *this;
1814 }
1815
1816 /**
1817 * @brief Remove one character.
1818 * @param __position Iterator referencing the character to remove.
1819 * @return iterator referencing same location after removal.
1820 *
1821 * Removes the character at @a __position from this string. The value
1822 * of the string doesn't change if an error is thrown.
1823 */
1824 iterator
1825 erase(__const_iterator __position)
1826 {
1827 _GLIBCXX_DEBUG_PEDASSERT(__position >= begin()
1828 && __position < end());
1829 const size_type __pos = __position - begin();
1830 this->_M_erase(__pos, size_type(1));
1831 return iterator(_M_data() + __pos);
1832 }
1833
1834 /**
1835 * @brief Remove a range of characters.
1836 * @param __first Iterator referencing the first character to remove.
1837 * @param __last Iterator referencing the end of the range.
1838 * @return Iterator referencing location of first after removal.
1839 *
1840 * Removes the characters in the range [first,last) from this string.
1841 * The value of the string doesn't change if an error is thrown.
1842 */
1843 iterator
1844 erase(__const_iterator __first, __const_iterator __last)
1845 {
1846 _GLIBCXX_DEBUG_PEDASSERT(__first >= begin() && __first <= __last
1847 && __last <= end());
1848 const size_type __pos = __first - begin();
1849 if (__last == end())
1850 this->_M_set_length(__pos);
1851 else
1852 this->_M_erase(__pos, __last - __first);
1853 return iterator(this->_M_data() + __pos);
1854 }
1855
1856#if __cplusplus201703L >= 201103L
1857 /**
1858 * @brief Remove the last character.
1859 *
1860 * The string must be non-empty.
1861 */
1862 void
1863 pop_back() noexcept
1864 {
1865 __glibcxx_assert(!empty())do { if (! (!empty())) std::__replacement_assert("/usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/basic_string.h"
, 1865, __PRETTY_FUNCTION__, "!empty()"); } while (false)
;
1866 _M_erase(size() - 1, 1);
1867 }
1868#endif // C++11
1869
1870 /**
1871 * @brief Replace characters with value from another string.
1872 * @param __pos Index of first character to replace.
1873 * @param __n Number of characters to be replaced.
1874 * @param __str String to insert.
1875 * @return Reference to this string.
1876 * @throw std::out_of_range If @a pos is beyond the end of this
1877 * string.
1878 * @throw std::length_error If new length exceeds @c max_size().
1879 *
1880 * Removes the characters in the range [__pos,__pos+__n) from
1881 * this string. In place, the value of @a __str is inserted.
1882 * If @a __pos is beyond end of string, out_of_range is thrown.
1883 * If the length of the result exceeds max_size(), length_error
1884 * is thrown. The value of the string doesn't change if an
1885 * error is thrown.
1886 */
1887 basic_string&
1888 replace(size_type __pos, size_type __n, const basic_string& __str)
1889 { return this->replace(__pos, __n, __str._M_data(), __str.size()); }
1890
1891 /**
1892 * @brief Replace characters with value from another string.
1893 * @param __pos1 Index of first character to replace.
1894 * @param __n1 Number of characters to be replaced.
1895 * @param __str String to insert.
1896 * @param __pos2 Index of first character of str to use.
1897 * @param __n2 Number of characters from str to use.
1898 * @return Reference to this string.
1899 * @throw std::out_of_range If @a __pos1 > size() or @a __pos2 >
1900 * __str.size().
1901 * @throw std::length_error If new length exceeds @c max_size().
1902 *
1903 * Removes the characters in the range [__pos1,__pos1 + n) from this
1904 * string. In place, the value of @a __str is inserted. If @a __pos is
1905 * beyond end of string, out_of_range is thrown. If the length of the
1906 * result exceeds max_size(), length_error is thrown. The value of the
1907 * string doesn't change if an error is thrown.
1908 */
1909 basic_string&
1910 replace(size_type __pos1, size_type __n1, const basic_string& __str,
1911 size_type __pos2, size_type __n2 = npos)
1912 { return this->replace(__pos1, __n1, __str._M_data()
1913 + __str._M_check(__pos2, "basic_string::replace"),
1914 __str._M_limit(__pos2, __n2)); }
1915
1916 /**
1917 * @brief Replace characters with value of a C substring.
1918 * @param __pos Index of first character to replace.
1919 * @param __n1 Number of characters to be replaced.
1920 * @param __s C string to insert.
1921 * @param __n2 Number of characters from @a s to use.
1922 * @return Reference to this string.
1923 * @throw std::out_of_range If @a pos1 > size().
1924 * @throw std::length_error If new length exceeds @c max_size().
1925 *
1926 * Removes the characters in the range [__pos,__pos + __n1)
1927 * from this string. In place, the first @a __n2 characters of
1928 * @a __s are inserted, or all of @a __s if @a __n2 is too large. If
1929 * @a __pos is beyond end of string, out_of_range is thrown. If
1930 * the length of result exceeds max_size(), length_error is
1931 * thrown. The value of the string doesn't change if an error
1932 * is thrown.
1933 */
1934 basic_string&
1935 replace(size_type __pos, size_type __n1, const _CharT* __s,
1936 size_type __n2)
1937 {
1938 __glibcxx_requires_string_len(__s, __n2);
1939 return _M_replace(_M_check(__pos, "basic_string::replace"),
1940 _M_limit(__pos, __n1), __s, __n2);
1941 }
1942
1943 /**
1944 * @brief Replace characters with value of a C string.
1945 * @param __pos Index of first character to replace.
1946 * @param __n1 Number of characters to be replaced.
1947 * @param __s C string to insert.
1948 * @return Reference to this string.
1949 * @throw std::out_of_range If @a pos > size().
1950 * @throw std::length_error If new length exceeds @c max_size().
1951 *
1952 * Removes the characters in the range [__pos,__pos + __n1)
1953 * from this string. In place, the characters of @a __s are
1954 * inserted. If @a __pos is beyond end of string, out_of_range
1955 * is thrown. If the length of result exceeds max_size(),
1956 * length_error is thrown. The value of the string doesn't
1957 * change if an error is thrown.
1958 */
1959 basic_string&
1960 replace(size_type __pos, size_type __n1, const _CharT* __s)
1961 {
1962 __glibcxx_requires_string(__s);
1963 return this->replace(__pos, __n1, __s, traits_type::length(__s));
1964 }
1965
1966 /**
1967 * @brief Replace characters with multiple characters.
1968 * @param __pos Index of first character to replace.
1969 * @param __n1 Number of characters to be replaced.
1970 * @param __n2 Number of characters to insert.
1971 * @param __c Character to insert.
1972 * @return Reference to this string.
1973 * @throw std::out_of_range If @a __pos > size().
1974 * @throw std::length_error If new length exceeds @c max_size().
1975 *
1976 * Removes the characters in the range [pos,pos + n1) from this
1977 * string. In place, @a __n2 copies of @a __c are inserted.
1978 * If @a __pos is beyond end of string, out_of_range is thrown.
1979 * If the length of result exceeds max_size(), length_error is
1980 * thrown. The value of the string doesn't change if an error
1981 * is thrown.
1982 */
1983 basic_string&
1984 replace(size_type __pos, size_type __n1, size_type __n2, _CharT __c)
1985 { return _M_replace_aux(_M_check(__pos, "basic_string::replace"),
1986 _M_limit(__pos, __n1), __n2, __c); }
1987
1988 /**
1989 * @brief Replace range of characters with string.
1990 * @param __i1 Iterator referencing start of range to replace.
1991 * @param __i2 Iterator referencing end of range to replace.
1992 * @param __str String value to insert.
1993 * @return Reference to this string.
1994 * @throw std::length_error If new length exceeds @c max_size().
1995 *
1996 * Removes the characters in the range [__i1,__i2). In place,
1997 * the value of @a __str is inserted. If the length of result
1998 * exceeds max_size(), length_error is thrown. The value of
1999 * the string doesn't change if an error is thrown.
2000 */
2001 basic_string&
2002 replace(__const_iterator __i1, __const_iterator __i2,
2003 const basic_string& __str)
2004 { return this->replace(__i1, __i2, __str._M_data(), __str.size()); }
2005
2006 /**
2007 * @brief Replace range of characters with C substring.
2008 * @param __i1 Iterator referencing start of range to replace.
2009 * @param __i2 Iterator referencing end of range to replace.
2010 * @param __s C string value to insert.
2011 * @param __n Number of characters from s to insert.
2012 * @return Reference to this string.
2013 * @throw std::length_error If new length exceeds @c max_size().
2014 *
2015 * Removes the characters in the range [__i1,__i2). In place,
2016 * the first @a __n characters of @a __s are inserted. If the
2017 * length of result exceeds max_size(), length_error is thrown.
2018 * The value of the string doesn't change if an error is
2019 * thrown.
2020 */
2021 basic_string&
2022 replace(__const_iterator __i1, __const_iterator __i2,
2023 const _CharT* __s, size_type __n)
2024 {
2025 _GLIBCXX_DEBUG_PEDASSERT(begin() <= __i1 && __i1 <= __i2
2026 && __i2 <= end());
2027 return this->replace(__i1 - begin(), __i2 - __i1, __s, __n);
2028 }
2029
2030 /**
2031 * @brief Replace range of characters with C string.
2032 * @param __i1 Iterator referencing start of range to replace.
2033 * @param __i2 Iterator referencing end of range to replace.
2034 * @param __s C string value to insert.
2035 * @return Reference to this string.
2036 * @throw std::length_error If new length exceeds @c max_size().
2037 *
2038 * Removes the characters in the range [__i1,__i2). In place,
2039 * the characters of @a __s are inserted. If the length of
2040 * result exceeds max_size(), length_error is thrown. The
2041 * value of the string doesn't change if an error is thrown.
2042 */
2043 basic_string&
2044 replace(__const_iterator __i1, __const_iterator __i2, const _CharT* __s)
2045 {
2046 __glibcxx_requires_string(__s);
2047 return this->replace(__i1, __i2, __s, traits_type::length(__s));
2048 }
2049
2050 /**
2051 * @brief Replace range of characters with multiple characters
2052 * @param __i1 Iterator referencing start of range to replace.
2053 * @param __i2 Iterator referencing end of range to replace.
2054 * @param __n Number of characters to insert.
2055 * @param __c Character to insert.
2056 * @return Reference to this string.
2057 * @throw std::length_error If new length exceeds @c max_size().
2058 *
2059 * Removes the characters in the range [__i1,__i2). In place,
2060 * @a __n copies of @a __c are inserted. If the length of
2061 * result exceeds max_size(), length_error is thrown. The
2062 * value of the string doesn't change if an error is thrown.
2063 */
2064 basic_string&
2065 replace(__const_iterator __i1, __const_iterator __i2, size_type __n,
2066 _CharT __c)
2067 {
2068 _GLIBCXX_DEBUG_PEDASSERT(begin() <= __i1 && __i1 <= __i2
2069 && __i2 <= end());
2070 return _M_replace_aux(__i1 - begin(), __i2 - __i1, __n, __c);
2071 }
2072
2073 /**
2074 * @brief Replace range of characters with range.
2075 * @param __i1 Iterator referencing start of range to replace.
2076 * @param __i2 Iterator referencing end of range to replace.
2077 * @param __k1 Iterator referencing start of range to insert.
2078 * @param __k2 Iterator referencing end of range to insert.
2079 * @return Reference to this string.
2080 * @throw std::length_error If new length exceeds @c max_size().
2081 *
2082 * Removes the characters in the range [__i1,__i2). In place,
2083 * characters in the range [__k1,__k2) are inserted. If the
2084 * length of result exceeds max_size(), length_error is thrown.
2085 * The value of the string doesn't change if an error is
2086 * thrown.
2087 */
2088#if __cplusplus201703L >= 201103L
2089 template<class _InputIterator,
2090 typename = std::_RequireInputIter<_InputIterator>>
2091 basic_string&
2092 replace(const_iterator __i1, const_iterator __i2,
2093 _InputIterator __k1, _InputIterator __k2)
2094 {
2095 _GLIBCXX_DEBUG_PEDASSERT(begin() <= __i1 && __i1 <= __i2
2096 && __i2 <= end());
2097 __glibcxx_requires_valid_range(__k1, __k2);
2098 return this->_M_replace_dispatch(__i1, __i2, __k1, __k2,
2099 std::__false_type());
2100 }
2101#else
2102 template<class _InputIterator>
2103#ifdef _GLIBCXX_DISAMBIGUATE_REPLACE_INST
2104 typename __enable_if_not_native_iterator<_InputIterator>::__type
2105#else
2106 basic_string&
2107#endif
2108 replace(iterator __i1, iterator __i2,
2109 _InputIterator __k1, _InputIterator __k2)
2110 {
2111 _GLIBCXX_DEBUG_PEDASSERT(begin() <= __i1 && __i1 <= __i2
2112 && __i2 <= end());
2113 __glibcxx_requires_valid_range(__k1, __k2);
2114 typedef typename std::__is_integer<_InputIterator>::__type _Integral;
2115 return _M_replace_dispatch(__i1, __i2, __k1, __k2, _Integral());
2116 }
2117#endif
2118
2119 // Specializations for the common case of pointer and iterator:
2120 // useful to avoid the overhead of temporary buffering in _M_replace.
2121 basic_string&
2122 replace(__const_iterator __i1, __const_iterator __i2,
2123 _CharT* __k1, _CharT* __k2)
2124 {
2125 _GLIBCXX_DEBUG_PEDASSERT(begin() <= __i1 && __i1 <= __i2
2126 && __i2 <= end());
2127 __glibcxx_requires_valid_range(__k1, __k2);
2128 return this->replace(__i1 - begin(), __i2 - __i1,
2129 __k1, __k2 - __k1);
2130 }
2131
2132 basic_string&
2133 replace(__const_iterator __i1, __const_iterator __i2,
2134 const _CharT* __k1, const _CharT* __k2)
2135 {
2136 _GLIBCXX_DEBUG_PEDASSERT(begin() <= __i1 && __i1 <= __i2
2137 && __i2 <= end());
2138 __glibcxx_requires_valid_range(__k1, __k2);
2139 return this->replace(__i1 - begin(), __i2 - __i1,
2140 __k1, __k2 - __k1);
2141 }
2142
2143 basic_string&
2144 replace(__const_iterator __i1, __const_iterator __i2,
2145 iterator __k1, iterator __k2)
2146 {
2147 _GLIBCXX_DEBUG_PEDASSERT(begin() <= __i1 && __i1 <= __i2
2148 && __i2 <= end());
2149 __glibcxx_requires_valid_range(__k1, __k2);
2150 return this->replace(__i1 - begin(), __i2 - __i1,
2151 __k1.base(), __k2 - __k1);
2152 }
2153
2154 basic_string&
2155 replace(__const_iterator __i1, __const_iterator __i2,
2156 const_iterator __k1, const_iterator __k2)
2157 {
2158 _GLIBCXX_DEBUG_PEDASSERT(begin() <= __i1 && __i1 <= __i2
2159 && __i2 <= end());
2160 __glibcxx_requires_valid_range(__k1, __k2);
2161 return this->replace(__i1 - begin(), __i2 - __i1,
2162 __k1.base(), __k2 - __k1);
2163 }
2164
2165#if __cplusplus201703L >= 201103L
2166 /**
2167 * @brief Replace range of characters with initializer_list.
2168 * @param __i1 Iterator referencing start of range to replace.
2169 * @param __i2 Iterator referencing end of range to replace.
2170 * @param __l The initializer_list of characters to insert.
2171 * @return Reference to this string.
2172 * @throw std::length_error If new length exceeds @c max_size().
2173 *
2174 * Removes the characters in the range [__i1,__i2). In place,
2175 * characters in the range [__k1,__k2) are inserted. If the
2176 * length of result exceeds max_size(), length_error is thrown.
2177 * The value of the string doesn't change if an error is
2178 * thrown.
2179 */
2180 basic_string& replace(const_iterator __i1, const_iterator __i2,
2181 initializer_list<_CharT> __l)
2182 { return this->replace(__i1, __i2, __l.begin(), __l.size()); }
2183#endif // C++11
2184
2185#if __cplusplus201703L >= 201703L
2186 /**
2187 * @brief Replace range of characters with string_view.
2188 * @param __pos The position to replace at.
2189 * @param __n The number of characters to replace.
2190 * @param __svt The object convertible to string_view to insert.
2191 * @return Reference to this string.
2192 */
2193 template<typename _Tp>
2194 _If_sv<_Tp, basic_string&>
2195 replace(size_type __pos, size_type __n, const _Tp& __svt)
2196 {
2197 __sv_type __sv = __svt;
2198 return this->replace(__pos, __n, __sv.data(), __sv.size());
2199 }
2200
2201 /**
2202 * @brief Replace range of characters with string_view.
2203 * @param __pos1 The position to replace at.
2204 * @param __n1 The number of characters to replace.
2205 * @param __svt The object convertible to string_view to insert from.
2206 * @param __pos2 The position in the string_view to insert from.
2207 * @param __n2 The number of characters to insert.
2208 * @return Reference to this string.
2209 */
2210 template<typename _Tp>
2211 _If_sv<_Tp, basic_string&>
2212 replace(size_type __pos1, size_type __n1, const _Tp& __svt,
2213 size_type __pos2, size_type __n2 = npos)
2214 {
2215 __sv_type __sv = __svt;
2216 return this->replace(__pos1, __n1,
2217 __sv.data()
2218 + std::__sv_check(__sv.size(), __pos2, "basic_string::replace"),
2219 std::__sv_limit(__sv.size(), __pos2, __n2));
2220 }
2221
2222 /**
2223 * @brief Replace range of characters with string_view.
2224 * @param __i1 An iterator referencing the start position
2225 to replace at.
2226 * @param __i2 An iterator referencing the end position
2227 for the replace.
2228 * @param __svt The object convertible to string_view to insert from.
2229 * @return Reference to this string.
2230 */
2231 template<typename _Tp>
2232 _If_sv<_Tp, basic_string&>
2233 replace(const_iterator __i1, const_iterator __i2, const _Tp& __svt)
2234 {
2235 __sv_type __sv = __svt;
2236 return this->replace(__i1 - begin(), __i2 - __i1, __sv);
2237 }
2238#endif // C++17
2239
2240 private:
2241 template<class _Integer>
2242 basic_string&
2243 _M_replace_dispatch(const_iterator __i1, const_iterator __i2,
2244 _Integer __n, _Integer __val, __true_type)
2245 { return _M_replace_aux(__i1 - begin(), __i2 - __i1, __n, __val); }
2246
2247 template<class _InputIterator>
2248 basic_string&
2249 _M_replace_dispatch(const_iterator __i1, const_iterator __i2,
2250 _InputIterator __k1, _InputIterator __k2,
2251 __false_type);
2252
2253 basic_string&
2254 _M_replace_aux(size_type __pos1, size_type __n1, size_type __n2,
2255 _CharT __c);
2256
2257 basic_string&
2258 _M_replace(size_type __pos, size_type __len1, const _CharT* __s,
2259 const size_type __len2);
2260
2261 basic_string&
2262 _M_append(const _CharT* __s, size_type __n);
2263
2264 public:
2265
2266 /**
2267 * @brief Copy substring into C string.
2268 * @param __s C string to copy value into.
2269 * @param __n Number of characters to copy.
2270 * @param __pos Index of first character to copy.
2271 * @return Number of characters actually copied
2272 * @throw std::out_of_range If __pos > size().
2273 *
2274 * Copies up to @a __n characters starting at @a __pos into the
2275 * C string @a __s. If @a __pos is %greater than size(),
2276 * out_of_range is thrown.
2277 */
2278 size_type
2279 copy(_CharT* __s, size_type __n, size_type __pos = 0) const;
2280
2281 /**
2282 * @brief Swap contents with another string.
2283 * @param __s String to swap with.
2284 *
2285 * Exchanges the contents of this string with that of @a __s in constant
2286 * time.
2287 */
2288 void
2289 swap(basic_string& __s) _GLIBCXX_NOEXCEPTnoexcept;
2290
2291 // String operations:
2292 /**
2293 * @brief Return const pointer to null-terminated contents.
2294 *
2295 * This is a handle to internal data. Do not modify or dire things may
2296 * happen.
2297 */
2298 const _CharT*
2299 c_str() const _GLIBCXX_NOEXCEPTnoexcept
2300 { return _M_data(); }
2301
2302 /**
2303 * @brief Return const pointer to contents.
2304 *
2305 * This is a pointer to internal data. It is undefined to modify
2306 * the contents through the returned pointer. To get a pointer that
2307 * allows modifying the contents use @c &str[0] instead,
2308 * (or in C++17 the non-const @c str.data() overload).
2309 */
2310 const _CharT*
2311 data() const _GLIBCXX_NOEXCEPTnoexcept
2312 { return _M_data(); }
2313
2314#if __cplusplus201703L >= 201703L
2315 /**
2316 * @brief Return non-const pointer to contents.
2317 *
2318 * This is a pointer to the character sequence held by the string.
2319 * Modifying the characters in the sequence is allowed.
2320 */
2321 _CharT*
2322 data() noexcept
2323 { return _M_data(); }
2324#endif
2325
2326 /**
2327 * @brief Return copy of allocator used to construct this string.
2328 */
2329 allocator_type
2330 get_allocator() const _GLIBCXX_NOEXCEPTnoexcept
2331 { return _M_get_allocator(); }
2332
2333 /**
2334 * @brief Find position of a C substring.
2335 * @param __s C string to locate.
2336 * @param __pos Index of character to search from.
2337 * @param __n Number of characters from @a s to search for.
2338 * @return Index of start of first occurrence.
2339 *
2340 * Starting from @a __pos, searches forward for the first @a
2341 * __n characters in @a __s within this string. If found,
2342 * returns the index where it begins. If not found, returns
2343 * npos.
2344 */
2345 size_type
2346 find(const _CharT* __s, size_type __pos, size_type __n) const
2347 _GLIBCXX_NOEXCEPTnoexcept;
2348
2349 /**
2350 * @brief Find position of a string.
2351 * @param __str String to locate.
2352 * @param __pos Index of character to search from (default 0).
2353 * @return Index of start of first occurrence.
2354 *
2355 * Starting from @a __pos, searches forward for value of @a __str within
2356 * this string. If found, returns the index where it begins. If not
2357 * found, returns npos.
2358 */
2359 size_type
2360 find(const basic_string& __str, size_type __pos = 0) const
2361 _GLIBCXX_NOEXCEPTnoexcept
2362 { return this->find(__str.data(), __pos, __str.size()); }
2363
2364#if __cplusplus201703L >= 201703L
2365 /**
2366 * @brief Find position of a string_view.
2367 * @param __svt The object convertible to string_view to locate.
2368 * @param __pos Index of character to search from (default 0).
2369 * @return Index of start of first occurrence.
2370 */
2371 template<typename _Tp>
2372 _If_sv<_Tp, size_type>
2373 find(const _Tp& __svt, size_type __pos = 0) const
2374 noexcept(is_same<_Tp, __sv_type>::value)
2375 {
2376 __sv_type __sv = __svt;
2377 return this->find(__sv.data(), __pos, __sv.size());
2378 }
2379#endif // C++17
2380
2381 /**
2382 * @brief Find position of a C string.
2383 * @param __s C string to locate.
2384 * @param __pos Index of character to search from (default 0).
2385 * @return Index of start of first occurrence.
2386 *
2387 * Starting from @a __pos, searches forward for the value of @a
2388 * __s within this string. If found, returns the index where
2389 * it begins. If not found, returns npos.
2390 */
2391 size_type
2392 find(const _CharT* __s, size_type __pos = 0) const _GLIBCXX_NOEXCEPTnoexcept
2393 {
2394 __glibcxx_requires_string(__s);
2395 return this->find(__s, __pos, traits_type::length(__s));
2396 }
2397
2398 /**
2399 * @brief Find position of a character.
2400 * @param __c Character to locate.
2401 * @param __pos Index of character to search from (default 0).
2402 * @return Index of first occurrence.
2403 *
2404 * Starting from @a __pos, searches forward for @a __c within
2405 * this string. If found, returns the index where it was
2406 * found. If not found, returns npos.
2407 */
2408 size_type
2409 find(_CharT __c, size_type __pos = 0) const _GLIBCXX_NOEXCEPTnoexcept;
2410
2411 /**
2412 * @brief Find last position of a string.
2413 * @param __str String to locate.
2414 * @param __pos Index of character to search back from (default end).
2415 * @return Index of start of last occurrence.
2416 *
2417 * Starting from @a __pos, searches backward for value of @a
2418 * __str within this string. If found, returns the index where
2419 * it begins. If not found, returns npos.
2420 */
2421 size_type
2422 rfind(const basic_string& __str, size_type __pos = npos) const
2423 _GLIBCXX_NOEXCEPTnoexcept
2424 { return this->rfind(__str.data(), __pos, __str.size()); }
2425
2426#if __cplusplus201703L >= 201703L
2427 /**
2428 * @brief Find last position of a string_view.
2429 * @param __svt The object convertible to string_view to locate.
2430 * @param __pos Index of character to search back from (default end).
2431 * @return Index of start of last occurrence.
2432 */
2433 template<typename _Tp>
2434 _If_sv<_Tp, size_type>
2435 rfind(const _Tp& __svt, size_type __pos = npos) const
2436 noexcept(is_same<_Tp, __sv_type>::value)
2437 {
2438 __sv_type __sv = __svt;
2439 return this->rfind(__sv.data(), __pos, __sv.size());
2440 }
2441#endif // C++17
2442
2443 /**
2444 * @brief Find last position of a C substring.
2445 * @param __s C string to locate.
2446 * @param __pos Index of character to search back from.
2447 * @param __n Number of characters from s to search for.
2448 * @return Index of start of last occurrence.
2449 *
2450 * Starting from @a __pos, searches backward for the first @a
2451 * __n characters in @a __s within this string. If found,
2452 * returns the index where it begins. If not found, returns
2453 * npos.
2454 */
2455 size_type
2456 rfind(const _CharT* __s, size_type __pos, size_type __n) const
2457 _GLIBCXX_NOEXCEPTnoexcept;
2458
2459 /**
2460 * @brief Find last position of a C string.
2461 * @param __s C string to locate.
2462 * @param __pos Index of character to start search at (default end).
2463 * @return Index of start of last occurrence.
2464 *
2465 * Starting from @a __pos, searches backward for the value of
2466 * @a __s within this string. If found, returns the index
2467 * where it begins. If not found, returns npos.
2468 */
2469 size_type
2470 rfind(const _CharT* __s, size_type __pos = npos) const
2471 {
2472 __glibcxx_requires_string(__s);
2473 return this->rfind(__s, __pos, traits_type::length(__s));
2474 }
2475
2476 /**
2477 * @brief Find last position of a character.
2478 * @param __c Character to locate.
2479 * @param __pos Index of character to search back from (default end).
2480 * @return Index of last occurrence.
2481 *
2482 * Starting from @a __pos, searches backward for @a __c within
2483 * this string. If found, returns the index where it was
2484 * found. If not found, returns npos.
2485 */
2486 size_type
2487 rfind(_CharT __c, size_type __pos = npos) const _GLIBCXX_NOEXCEPTnoexcept;
2488
2489 /**
2490 * @brief Find position of a character of string.
2491 * @param __str String containing characters to locate.
2492 * @param __pos Index of character to search from (default 0).
2493 * @return Index of first occurrence.
2494 *
2495 * Starting from @a __pos, searches forward for one of the
2496 * characters of @a __str within this string. If found,
2497 * returns the index where it was found. If not found, returns
2498 * npos.
2499 */
2500 size_type
2501 find_first_of(const basic_string& __str, size_type __pos = 0) const
2502 _GLIBCXX_NOEXCEPTnoexcept
2503 { return this->find_first_of(__str.data(), __pos, __str.size()); }
2504
2505#if __cplusplus201703L >= 201703L
2506 /**
2507 * @brief Find position of a character of a string_view.
2508 * @param __svt An object convertible to string_view containing
2509 * characters to locate.
2510 * @param __pos Index of character to search from (default 0).
2511 * @return Index of first occurrence.
2512 */
2513 template<typename _Tp>
2514 _If_sv<_Tp, size_type>
2515 find_first_of(const _Tp& __svt, size_type __pos = 0) const
2516 noexcept(is_same<_Tp, __sv_type>::value)
2517 {
2518 __sv_type __sv = __svt;
2519 return this->find_first_of(__sv.data(), __pos, __sv.size());
2520 }
2521#endif // C++17
2522
2523 /**
2524 * @brief Find position of a character of C substring.
2525 * @param __s String containing characters to locate.
2526 * @param __pos Index of character to search from.
2527 * @param __n Number of characters from s to search for.
2528 * @return Index of first occurrence.
2529 *
2530 * Starting from @a __pos, searches forward for one of the
2531 * first @a __n characters of @a __s within this string. If
2532 * found, returns the index where it was found. If not found,
2533 * returns npos.
2534 */
2535 size_type
2536 find_first_of(const _CharT* __s, size_type __pos, size_type __n) const
2537 _GLIBCXX_NOEXCEPTnoexcept;
2538
2539 /**
2540 * @brief Find position of a character of C string.
2541 * @param __s String containing characters to locate.
2542 * @param __pos Index of character to search from (default 0).
2543 * @return Index of first occurrence.
2544 *
2545 * Starting from @a __pos, searches forward for one of the
2546 * characters of @a __s within this string. If found, returns
2547 * the index where it was found. If not found, returns npos.
2548 */
2549 size_type
2550 find_first_of(const _CharT* __s, size_type __pos = 0) const
2551 _GLIBCXX_NOEXCEPTnoexcept
2552 {
2553 __glibcxx_requires_string(__s);
2554 return this->find_first_of(__s, __pos, traits_type::length(__s));
2555 }
2556
2557 /**
2558 * @brief Find position of a character.
2559 * @param __c Character to locate.
2560 * @param __pos Index of character to search from (default 0).
2561 * @return Index of first occurrence.
2562 *
2563 * Starting from @a __pos, searches forward for the character
2564 * @a __c within this string. If found, returns the index
2565 * where it was found. If not found, returns npos.
2566 *
2567 * Note: equivalent to find(__c, __pos).
2568 */
2569 size_type
2570 find_first_of(_CharT __c, size_type __pos = 0) const _GLIBCXX_NOEXCEPTnoexcept
2571 { return this->find(__c, __pos); }
2572
2573 /**
2574 * @brief Find last position of a character of string.
2575 * @param __str String containing characters to locate.
2576 * @param __pos Index of character to search back from (default end).
2577 * @return Index of last occurrence.
2578 *
2579 * Starting from @a __pos, searches backward for one of the
2580 * characters of @a __str within this string. If found,
2581 * returns the index where it was found. If not found, returns
2582 * npos.
2583 */
2584 size_type
2585 find_last_of(const basic_string& __str, size_type __pos = npos) const
2586 _GLIBCXX_NOEXCEPTnoexcept
2587 { return this->find_last_of(__str.data(), __pos, __str.size()); }
2588
2589#if __cplusplus201703L >= 201703L
2590 /**
2591 * @brief Find last position of a character of string.
2592 * @param __svt An object convertible to string_view containing
2593 * characters to locate.
2594 * @param __pos Index of character to search back from (default end).
2595 * @return Index of last occurrence.
2596 */
2597 template<typename _Tp>
2598 _If_sv<_Tp, size_type>
2599 find_last_of(const _Tp& __svt, size_type __pos = npos) const
2600 noexcept(is_same<_Tp, __sv_type>::value)
2601 {
2602 __sv_type __sv = __svt;
2603 return this->find_last_of(__sv.data(), __pos, __sv.size());
2604 }
2605#endif // C++17
2606
2607 /**
2608 * @brief Find last position of a character of C substring.
2609 * @param __s C string containing characters to locate.
2610 * @param __pos Index of character to search back from.
2611 * @param __n Number of characters from s to search for.
2612 * @return Index of last occurrence.
2613 *
2614 * Starting from @a __pos, searches backward for one of the
2615 * first @a __n characters of @a __s within this string. If
2616 * found, returns the index where it was found. If not found,
2617 * returns npos.
2618 */
2619 size_type
2620 find_last_of(const _CharT* __s, size_type __pos, size_type __n) const
2621 _GLIBCXX_NOEXCEPTnoexcept;
2622
2623 /**
2624 * @brief Find last position of a character of C string.
2625 * @param __s C string containing characters to locate.
2626 * @param __pos Index of character to search back from (default end).
2627 * @return Index of last occurrence.
2628 *
2629 * Starting from @a __pos, searches backward for one of the
2630 * characters of @a __s within this string. If found, returns
2631 * the index where it was found. If not found, returns npos.
2632 */
2633 size_type
2634 find_last_of(const _CharT* __s, size_type __pos = npos) const
2635 _GLIBCXX_NOEXCEPTnoexcept
2636 {
2637 __glibcxx_requires_string(__s);
2638 return this->find_last_of(__s, __pos, traits_type::length(__s));
2639 }
2640
2641 /**
2642 * @brief Find last position of a character.
2643 * @param __c Character to locate.
2644 * @param __pos Index of character to search back from (default end).
2645 * @return Index of last occurrence.
2646 *
2647 * Starting from @a __pos, searches backward for @a __c within
2648 * this string. If found, returns the index where it was
2649 * found. If not found, returns npos.
2650 *
2651 * Note: equivalent to rfind(__c, __pos).
2652 */
2653 size_type
2654 find_last_of(_CharT __c, size_type __pos = npos) const _GLIBCXX_NOEXCEPTnoexcept
2655 { return this->rfind(__c, __pos); }
2656
2657 /**
2658 * @brief Find position of a character not in string.
2659 * @param __str String containing characters to avoid.
2660 * @param __pos Index of character to search from (default 0).
2661 * @return Index of first occurrence.
2662 *
2663 * Starting from @a __pos, searches forward for a character not contained
2664 * in @a __str within this string. If found, returns the index where it
2665 * was found. If not found, returns npos.
2666 */
2667 size_type
2668 find_first_not_of(const basic_string& __str, size_type __pos = 0) const
2669 _GLIBCXX_NOEXCEPTnoexcept
2670 { return this->find_first_not_of(__str.data(), __pos, __str.size()); }
2671
2672#if __cplusplus201703L >= 201703L
2673 /**
2674 * @brief Find position of a character not in a string_view.
2675 * @param __svt A object convertible to string_view containing
2676 * characters to avoid.
2677 * @param __pos Index of character to search from (default 0).
2678 * @return Index of first occurrence.
2679 */
2680 template<typename _Tp>
2681 _If_sv<_Tp, size_type>
2682 find_first_not_of(const _Tp& __svt, size_type __pos = 0) const
2683 noexcept(is_same<_Tp, __sv_type>::value)
2684 {
2685 __sv_type __sv = __svt;
2686 return this->find_first_not_of(__sv.data(), __pos, __sv.size());
2687 }
2688#endif // C++17
2689
2690 /**
2691 * @brief Find position of a character not in C substring.
2692 * @param __s C string containing characters to avoid.
2693 * @param __pos Index of character to search from.
2694 * @param __n Number of characters from __s to consider.
2695 * @return Index of first occurrence.
2696 *
2697 * Starting from @a __pos, searches forward for a character not
2698 * contained in the first @a __n characters of @a __s within
2699 * this string. If found, returns the index where it was
2700 * found. If not found, returns npos.
2701 */
2702 size_type
2703 find_first_not_of(const _CharT* __s, size_type __pos,
2704 size_type __n) const _GLIBCXX_NOEXCEPTnoexcept;
2705
2706 /**
2707 * @brief Find position of a character not in C string.
2708 * @param __s C string containing characters to avoid.
2709 * @param __pos Index of character to search from (default 0).
2710 * @return Index of first occurrence.
2711 *
2712 * Starting from @a __pos, searches forward for a character not
2713 * contained in @a __s within this string. If found, returns
2714 * the index where it was found. If not found, returns npos.
2715 */
2716 size_type
2717 find_first_not_of(const _CharT* __s, size_type __pos = 0) const
2718 _GLIBCXX_NOEXCEPTnoexcept
2719 {
2720 __glibcxx_requires_string(__s);
2721 return this->find_first_not_of(__s, __pos, traits_type::length(__s));
2722 }
2723
2724 /**
2725 * @brief Find position of a different character.
2726 * @param __c Character to avoid.
2727 * @param __pos Index of character to search from (default 0).
2728 * @return Index of first occurrence.
2729 *
2730 * Starting from @a __pos, searches forward for a character
2731 * other than @a __c within this string. If found, returns the
2732 * index where it was found. If not found, returns npos.
2733 */
2734 size_type
2735 find_first_not_of(_CharT __c, size_type __pos = 0) const
2736 _GLIBCXX_NOEXCEPTnoexcept;
2737
2738 /**
2739 * @brief Find last position of a character not in string.
2740 * @param __str String containing characters to avoid.
2741 * @param __pos Index of character to search back from (default end).
2742 * @return Index of last occurrence.
2743 *
2744 * Starting from @a __pos, searches backward for a character
2745 * not contained in @a __str within this string. If found,
2746 * returns the index where it was found. If not found, returns
2747 * npos.
2748 */
2749 size_type
2750 find_last_not_of(const basic_string& __str, size_type __pos = npos) const
2751 _GLIBCXX_NOEXCEPTnoexcept
2752 { return this->find_last_not_of(__str.data(), __pos, __str.size()); }
2753
2754#if __cplusplus201703L >= 201703L
2755 /**
2756 * @brief Find last position of a character not in a string_view.
2757 * @param __svt An object convertible to string_view containing
2758 * characters to avoid.
2759 * @param __pos Index of character to search back from (default end).
2760 * @return Index of last occurrence.
2761 */
2762 template<typename _Tp>
2763 _If_sv<_Tp, size_type>
2764 find_last_not_of(const _Tp& __svt, size_type __pos = npos) const
2765 noexcept(is_same<_Tp, __sv_type>::value)
2766 {
2767 __sv_type __sv = __svt;
2768 return this->find_last_not_of(__sv.data(), __pos, __sv.size());
2769 }
2770#endif // C++17
2771
2772 /**
2773 * @brief Find last position of a character not in C substring.
2774 * @param __s C string containing characters to avoid.
2775 * @param __pos Index of character to search back from.
2776 * @param __n Number of characters from s to consider.
2777 * @return Index of last occurrence.
2778 *
2779 * Starting from @a __pos, searches backward for a character not
2780 * contained in the first @a __n characters of @a __s within this string.
2781 * If found, returns the index where it was found. If not found,
2782 * returns npos.
2783 */
2784 size_type
2785 find_last_not_of(const _CharT* __s, size_type __pos,
2786 size_type __n) const _GLIBCXX_NOEXCEPTnoexcept;
2787 /**
2788 * @brief Find last position of a character not in C string.
2789 * @param __s C string containing characters to avoid.
2790 * @param __pos Index of character to search back from (default end).
2791 * @return Index of last occurrence.
2792 *
2793 * Starting from @a __pos, searches backward for a character
2794 * not contained in @a __s within this string. If found,
2795 * returns the index where it was found. If not found, returns
2796 * npos.
2797 */
2798 size_type
2799 find_last_not_of(const _CharT* __s, size_type __pos = npos) const
2800 _GLIBCXX_NOEXCEPTnoexcept
2801 {
2802 __glibcxx_requires_string(__s);
2803 return this->find_last_not_of(__s, __pos, traits_type::length(__s));
2804 }
2805
2806 /**
2807 * @brief Find last position of a different character.
2808 * @param __c Character to avoid.
2809 * @param __pos Index of character to search back from (default end).
2810 * @return Index of last occurrence.
2811 *
2812 * Starting from @a __pos, searches backward for a character other than
2813 * @a __c within this string. If found, returns the index where it was
2814 * found. If not found, returns npos.
2815 */
2816 size_type
2817 find_last_not_of(_CharT __c, size_type __pos = npos) const
2818 _GLIBCXX_NOEXCEPTnoexcept;
2819
2820 /**
2821 * @brief Get a substring.
2822 * @param __pos Index of first character (default 0).
2823 * @param __n Number of characters in substring (default remainder).
2824 * @return The new string.
2825 * @throw std::out_of_range If __pos > size().
2826 *
2827 * Construct and return a new string using the @a __n
2828 * characters starting at @a __pos. If the string is too
2829 * short, use the remainder of the characters. If @a __pos is
2830 * beyond the end of the string, out_of_range is thrown.
2831 */
2832 basic_string
2833 substr(size_type __pos = 0, size_type __n = npos) const
2834 { return basic_string(*this,
2835 _M_check(__pos, "basic_string::substr"), __n); }
2836
2837 /**
2838 * @brief Compare to a string.
2839 * @param __str String to compare against.
2840 * @return Integer < 0, 0, or > 0.
2841 *
2842 * Returns an integer < 0 if this string is ordered before @a
2843 * __str, 0 if their values are equivalent, or > 0 if this
2844 * string is ordered after @a __str. Determines the effective
2845 * length rlen of the strings to compare as the smallest of
2846 * size() and str.size(). The function then compares the two
2847 * strings by calling traits::compare(data(), str.data(),rlen).
2848 * If the result of the comparison is nonzero returns it,
2849 * otherwise the shorter one is ordered first.
2850 */
2851 int
2852 compare(const basic_string& __str) const
2853 {
2854 const size_type __size = this->size();
2855 const size_type __osize = __str.size();
2856 const size_type __len = std::min(__size, __osize);
2857
2858 int __r = traits_type::compare(_M_data(), __str.data(), __len);
2859 if (!__r)
2860 __r = _S_compare(__size, __osize);
2861 return __r;
2862 }
2863
2864#if __cplusplus201703L >= 201703L
2865 /**
2866 * @brief Compare to a string_view.
2867 * @param __svt An object convertible to string_view to compare against.
2868 * @return Integer < 0, 0, or > 0.
2869 */
2870 template<typename _Tp>
2871 _If_sv<_Tp, int>
2872 compare(const _Tp& __svt) const
2873 noexcept(is_same<_Tp, __sv_type>::value)
2874 {
2875 __sv_type __sv = __svt;
2876 const size_type __size = this->size();
2877 const size_type __osize = __sv.size();
2878 const size_type __len = std::min(__size, __osize);
2879
2880 int __r = traits_type::compare(_M_data(), __sv.data(), __len);
2881 if (!__r)
2882 __r = _S_compare(__size, __osize);
2883 return __r;
2884 }
2885
2886 /**
2887 * @brief Compare to a string_view.
2888 * @param __pos A position in the string to start comparing from.
2889 * @param __n The number of characters to compare.
2890 * @param __svt An object convertible to string_view to compare
2891 * against.
2892 * @return Integer < 0, 0, or > 0.
2893 */
2894 template<typename _Tp>
2895 _If_sv<_Tp, int>
2896 compare(size_type __pos, size_type __n, const _Tp& __svt) const
2897 noexcept(is_same<_Tp, __sv_type>::value)
2898 {
2899 __sv_type __sv = __svt;
2900 return __sv_type(*this).substr(__pos, __n).compare(__sv);
2901 }
2902
2903 /**
2904 * @brief Compare to a string_view.
2905 * @param __pos1 A position in the string to start comparing from.
2906 * @param __n1 The number of characters to compare.
2907 * @param __svt An object convertible to string_view to compare
2908 * against.
2909 * @param __pos2 A position in the string_view to start comparing from.
2910 * @param __n2 The number of characters to compare.
2911 * @return Integer < 0, 0, or > 0.
2912 */
2913 template<typename _Tp>
2914 _If_sv<_Tp, int>
2915 compare(size_type __pos1, size_type __n1, const _Tp& __svt,
2916 size_type __pos2, size_type __n2 = npos) const
2917 noexcept(is_same<_Tp, __sv_type>::value)
2918 {
2919 __sv_type __sv = __svt;
2920 return __sv_type(*this)
2921 .substr(__pos1, __n1).compare(__sv.substr(__pos2, __n2));
2922 }
2923#endif // C++17
2924
2925 /**
2926 * @brief Compare substring to a string.
2927 * @param __pos Index of first character of substring.
2928 * @param __n Number of characters in substring.
2929 * @param __str String to compare against.
2930 * @return Integer < 0, 0, or > 0.
2931 *
2932 * Form the substring of this string from the @a __n characters
2933 * starting at @a __pos. Returns an integer < 0 if the
2934 * substring is ordered before @a __str, 0 if their values are
2935 * equivalent, or > 0 if the substring is ordered after @a
2936 * __str. Determines the effective length rlen of the strings
2937 * to compare as the smallest of the length of the substring
2938 * and @a __str.size(). The function then compares the two
2939 * strings by calling
2940 * traits::compare(substring.data(),str.data(),rlen). If the
2941 * result of the comparison is nonzero returns it, otherwise
2942 * the shorter one is ordered first.
2943 */
2944 int
2945 compare(size_type __pos, size_type __n, const basic_string& __str) const;
2946
2947 /**
2948 * @brief Compare substring to a substring.
2949 * @param __pos1 Index of first character of substring.
2950 * @param __n1 Number of characters in substring.
2951 * @param __str String to compare against.
2952 * @param __pos2 Index of first character of substring of str.
2953 * @param __n2 Number of characters in substring of str.
2954 * @return Integer < 0, 0, or > 0.
2955 *
2956 * Form the substring of this string from the @a __n1
2957 * characters starting at @a __pos1. Form the substring of @a
2958 * __str from the @a __n2 characters starting at @a __pos2.
2959 * Returns an integer < 0 if this substring is ordered before
2960 * the substring of @a __str, 0 if their values are equivalent,
2961 * or > 0 if this substring is ordered after the substring of
2962 * @a __str. Determines the effective length rlen of the
2963 * strings to compare as the smallest of the lengths of the
2964 * substrings. The function then compares the two strings by
2965 * calling
2966 * traits::compare(substring.data(),str.substr(pos2,n2).data(),rlen).
2967 * If the result of the comparison is nonzero returns it,
2968 * otherwise the shorter one is ordered first.
2969 */
2970 int
2971 compare(size_type __pos1, size_type __n1, const basic_string& __str,
2972 size_type __pos2, size_type __n2 = npos) const;
2973
2974 /**
2975 * @brief Compare to a C string.
2976 * @param __s C string to compare against.
2977 * @return Integer < 0, 0, or > 0.
2978 *
2979 * Returns an integer < 0 if this string is ordered before @a __s, 0 if
2980 * their values are equivalent, or > 0 if this string is ordered after
2981 * @a __s. Determines the effective length rlen of the strings to
2982 * compare as the smallest of size() and the length of a string
2983 * constructed from @a __s. The function then compares the two strings
2984 * by calling traits::compare(data(),s,rlen). If the result of the
2985 * comparison is nonzero returns it, otherwise the shorter one is
2986 * ordered first.
2987 */
2988 int
2989 compare(const _CharT* __s) const _GLIBCXX_NOEXCEPTnoexcept;
2990
2991 // _GLIBCXX_RESOLVE_LIB_DEFECTS
2992 // 5 String::compare specification questionable
2993 /**
2994 * @brief Compare substring to a C string.
2995 * @param __pos Index of first character of substring.
2996 * @param __n1 Number of characters in substring.
2997 * @param __s C string to compare against.
2998 * @return Integer < 0, 0, or > 0.
2999 *
3000 * Form the substring of this string from the @a __n1
3001 * characters starting at @a pos. Returns an integer < 0 if
3002 * the substring is ordered before @a __s, 0 if their values
3003 * are equivalent, or > 0 if the substring is ordered after @a
3004 * __s. Determines the effective length rlen of the strings to
3005 * compare as the smallest of the length of the substring and
3006 * the length of a string constructed from @a __s. The
3007 * function then compares the two string by calling
3008 * traits::compare(substring.data(),__s,rlen). If the result of
3009 * the comparison is nonzero returns it, otherwise the shorter
3010 * one is ordered first.
3011 */
3012 int
3013 compare(size_type __pos, size_type __n1, const _CharT* __s) const;
3014
3015 /**
3016 * @brief Compare substring against a character %array.
3017 * @param __pos Index of first character of substring.
3018 * @param __n1 Number of characters in substring.
3019 * @param __s character %array to compare against.
3020 * @param __n2 Number of characters of s.
3021 * @return Integer < 0, 0, or > 0.
3022 *
3023 * Form the substring of this string from the @a __n1
3024 * characters starting at @a __pos. Form a string from the
3025 * first @a __n2 characters of @a __s. Returns an integer < 0
3026 * if this substring is ordered before the string from @a __s,
3027 * 0 if their values are equivalent, or > 0 if this substring
3028 * is ordered after the string from @a __s. Determines the
3029 * effective length rlen of the strings to compare as the
3030 * smallest of the length of the substring and @a __n2. The
3031 * function then compares the two strings by calling
3032 * traits::compare(substring.data(),s,rlen). If the result of
3033 * the comparison is nonzero returns it, otherwise the shorter
3034 * one is ordered first.
3035 *
3036 * NB: s must have at least n2 characters, &apos;\\0&apos; has
3037 * no special meaning.
3038 */
3039 int
3040 compare(size_type __pos, size_type __n1, const _CharT* __s,
3041 size_type __n2) const;
3042
3043#if __cplusplus201703L > 201703L
3044 bool
3045 starts_with(basic_string_view<_CharT, _Traits> __x) const noexcept
3046 { return __sv_type(this->data(), this->size()).starts_with(__x); }
3047
3048 bool
3049 starts_with(_CharT __x) const noexcept
3050 { return __sv_type(this->data(), this->size()).starts_with(__x); }
3051
3052 bool
3053 starts_with(const _CharT* __x) const noexcept
3054 { return __sv_type(this->data(), this->size()).starts_with(__x); }
3055
3056 bool
3057 ends_with(basic_string_view<_CharT, _Traits> __x) const noexcept
3058 { return __sv_type(this->data(), this->size()).ends_with(__x); }
3059
3060 bool
3061 ends_with(_CharT __x) const noexcept
3062 { return __sv_type(this->data(), this->size()).ends_with(__x); }
3063
3064 bool
3065 ends_with(const _CharT* __x) const noexcept
3066 { return __sv_type(this->data(), this->size()).ends_with(__x); }
3067#endif // C++20
3068
3069 // Allow basic_stringbuf::__xfer_bufptrs to call _M_length:
3070 template<typename, typename, typename> friend class basic_stringbuf;
3071 };
3072_GLIBCXX_END_NAMESPACE_CXX11}
3073#else // !_GLIBCXX_USE_CXX11_ABI
3074 // Reference-counted COW string implentation
3075
3076 /**
3077 * @class basic_string basic_string.h <string>
3078 * @brief Managing sequences of characters and character-like objects.
3079 *
3080 * @ingroup strings
3081 * @ingroup sequences
3082 *
3083 * @tparam _CharT Type of character
3084 * @tparam _Traits Traits for character type, defaults to
3085 * char_traits<_CharT>.
3086 * @tparam _Alloc Allocator type, defaults to allocator<_CharT>.
3087 *
3088 * Meets the requirements of a <a href="tables.html#65">container</a>, a
3089 * <a href="tables.html#66">reversible container</a>, and a
3090 * <a href="tables.html#67">sequence</a>. Of the
3091 * <a href="tables.html#68">optional sequence requirements</a>, only
3092 * @c push_back, @c at, and @c %array access are supported.
3093 *
3094 * @doctodo
3095 *
3096 *
3097 * Documentation? What's that?
3098 * Nathan Myers <ncm@cantrip.org>.
3099 *
3100 * A string looks like this:
3101 *
3102 * @code
3103 * [_Rep]
3104 * _M_length
3105 * [basic_string<char_type>] _M_capacity
3106 * _M_dataplus _M_refcount
3107 * _M_p ----------------> unnamed array of char_type
3108 * @endcode
3109 *
3110 * Where the _M_p points to the first character in the string, and
3111 * you cast it to a pointer-to-_Rep and subtract 1 to get a
3112 * pointer to the header.
3113 *
3114 * This approach has the enormous advantage that a string object
3115 * requires only one allocation. All the ugliness is confined
3116 * within a single %pair of inline functions, which each compile to
3117 * a single @a add instruction: _Rep::_M_data(), and
3118 * string::_M_rep(); and the allocation function which gets a
3119 * block of raw bytes and with room enough and constructs a _Rep
3120 * object at the front.
3121 *
3122 * The reason you want _M_data pointing to the character %array and
3123 * not the _Rep is so that the debugger can see the string
3124 * contents. (Probably we should add a non-inline member to get
3125 * the _Rep for the debugger to use, so users can check the actual
3126 * string length.)
3127 *
3128 * Note that the _Rep object is a POD so that you can have a
3129 * static <em>empty string</em> _Rep object already @a constructed before
3130 * static constructors have run. The reference-count encoding is
3131 * chosen so that a 0 indicates one reference, so you never try to
3132 * destroy the empty-string _Rep object.
3133 *
3134 * All but the last paragraph is considered pretty conventional
3135 * for a C++ string implementation.
3136 */
3137 // 21.3 Template class basic_string
3138 template<typename _CharT, typename _Traits, typename _Alloc>
3139 class basic_string
3140 {
3141 typedef typename __gnu_cxx::__alloc_traits<_Alloc>::template
3142 rebind<_CharT>::other _CharT_alloc_type;
3143 typedef __gnu_cxx::__alloc_traits<_CharT_alloc_type> _CharT_alloc_traits;
3144
3145 // Types:
3146 public:
3147 typedef _Traits traits_type;
3148 typedef typename _Traits::char_type value_type;
3149 typedef _Alloc allocator_type;
3150 typedef typename _CharT_alloc_type::size_type size_type;
3151 typedef typename _CharT_alloc_type::difference_type difference_type;
3152#if __cplusplus201703L < 201103L
3153 typedef typename _CharT_alloc_type::reference reference;
3154 typedef typename _CharT_alloc_type::const_reference const_reference;
3155#else
3156 typedef value_type& reference;
3157 typedef const value_type& const_reference;
3158#endif
3159 typedef typename _CharT_alloc_traits::pointer pointer;
3160 typedef typename _CharT_alloc_traits::const_pointer const_pointer;
3161 typedef __gnu_cxx::__normal_iterator<pointer, basic_string> iterator;
3162 typedef __gnu_cxx::__normal_iterator<const_pointer, basic_string>
3163 const_iterator;
3164 typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
3165 typedef std::reverse_iterator<iterator> reverse_iterator;
3166
3167 protected:
3168 // type used for positions in insert, erase etc.
3169 typedef iterator __const_iterator;
3170
3171 private:
3172 // _Rep: string representation
3173 // Invariants:
3174 // 1. String really contains _M_length + 1 characters: due to 21.3.4
3175 // must be kept null-terminated.
3176 // 2. _M_capacity >= _M_length
3177 // Allocated memory is always (_M_capacity + 1) * sizeof(_CharT).
3178 // 3. _M_refcount has three states:
3179 // -1: leaked, one reference, no ref-copies allowed, non-const.
3180 // 0: one reference, non-const.
3181 // n>0: n + 1 references, operations require a lock, const.
3182 // 4. All fields==0 is an empty string, given the extra storage
3183 // beyond-the-end for a null terminator; thus, the shared
3184 // empty string representation needs no constructor.
3185
3186 struct _Rep_base
3187 {
3188 size_type _M_length;
3189 size_type _M_capacity;
3190 _Atomic_word _M_refcount;
3191 };
3192
3193 struct _Rep : _Rep_base
3194 {
3195 // Types:
3196 typedef typename __gnu_cxx::__alloc_traits<_Alloc>::template
3197 rebind<char>::other _Raw_bytes_alloc;
3198
3199 // (Public) Data members:
3200
3201 // The maximum number of individual char_type elements of an
3202 // individual string is determined by _S_max_size. This is the
3203 // value that will be returned by max_size(). (Whereas npos
3204 // is the maximum number of bytes the allocator can allocate.)
3205 // If one was to divvy up the theoretical largest size string,
3206 // with a terminating character and m _CharT elements, it'd
3207 // look like this:
3208 // npos = sizeof(_Rep) + (m * sizeof(_CharT)) + sizeof(_CharT)
3209 // Solving for m:
3210 // m = ((npos - sizeof(_Rep))/sizeof(CharT)) - 1
3211 // In addition, this implementation quarters this amount.
3212 static const size_type _S_max_size;
3213 static const _CharT _S_terminal;
3214
3215 // The following storage is init'd to 0 by the linker, resulting
3216 // (carefully) in an empty string with one reference.
3217 static size_type _S_empty_rep_storage[];
3218
3219 static _Rep&
3220 _S_empty_rep() _GLIBCXX_NOEXCEPTnoexcept
3221 {
3222 // NB: Mild hack to avoid strict-aliasing warnings. Note that
3223 // _S_empty_rep_storage is never modified and the punning should
3224 // be reasonably safe in this case.
3225 void* __p = reinterpret_cast<void*>(&_S_empty_rep_storage);
3226 return *reinterpret_cast<_Rep*>(__p);
3227 }
3228
3229 bool
3230 _M_is_leaked() const _GLIBCXX_NOEXCEPTnoexcept
3231 {
3232#if defined(__GTHREADS1)
3233 // _M_refcount is mutated concurrently by _M_refcopy/_M_dispose,
3234 // so we need to use an atomic load. However, _M_is_leaked
3235 // predicate does not change concurrently (i.e. the string is either
3236 // leaked or not), so a relaxed load is enough.
3237 return __atomic_load_n(&this->_M_refcount, __ATOMIC_RELAXED0) < 0;
3238#else
3239 return this->_M_refcount < 0;
3240#endif
3241 }
3242
3243 bool
3244 _M_is_shared() const _GLIBCXX_NOEXCEPTnoexcept
3245 {
3246#if defined(__GTHREADS1)
3247 // _M_refcount is mutated concurrently by _M_refcopy/_M_dispose,
3248 // so we need to use an atomic load. Another thread can drop last
3249 // but one reference concurrently with this check, so we need this
3250 // load to be acquire to synchronize with release fetch_and_add in
3251 // _M_dispose.
3252 return __atomic_load_n(&this->_M_refcount, __ATOMIC_ACQUIRE2) > 0;
3253#else
3254 return this->_M_refcount > 0;
3255#endif
3256 }
3257
3258 void
3259 _M_set_leaked() _GLIBCXX_NOEXCEPTnoexcept
3260 { this->_M_refcount = -1; }
3261
3262 void
3263 _M_set_sharable() _GLIBCXX_NOEXCEPTnoexcept
3264 { this->_M_refcount = 0; }
3265
3266 void
3267 _M_set_length_and_sharable(size_type __n) _GLIBCXX_NOEXCEPTnoexcept
3268 {
3269#if _GLIBCXX_FULLY_DYNAMIC_STRING0 == 0
3270 if (__builtin_expect(this != &_S_empty_rep(), false))
3271#endif
3272 {
3273 this->_M_set_sharable(); // One reference.
3274 this->_M_length = __n;
3275 traits_type::assign(this->_M_refdata()[__n], _S_terminal);
3276 // grrr. (per 21.3.4)
3277 // You cannot leave those LWG people alone for a second.
3278 }
3279 }
3280
3281 _CharT*
3282 _M_refdata() throw()
3283 { return reinterpret_cast<_CharT*>(this + 1); }
3284
3285 _CharT*
3286 _M_grab(const _Alloc& __alloc1, const _Alloc& __alloc2)
3287 {
3288 return (!_M_is_leaked() && __alloc1 == __alloc2)
3289 ? _M_refcopy() : _M_clone(__alloc1);
3290 }
3291
3292 // Create & Destroy
3293 static _Rep*
3294 _S_create(size_type, size_type, const _Alloc&);
3295
3296 void
3297 _M_dispose(const _Alloc& __a) _GLIBCXX_NOEXCEPTnoexcept
3298 {
3299#if _GLIBCXX_FULLY_DYNAMIC_STRING0 == 0
3300 if (__builtin_expect(this != &_S_empty_rep(), false))
3301#endif
3302 {
3303 // Be race-detector-friendly. For more info see bits/c++config.
3304 _GLIBCXX_SYNCHRONIZATION_HAPPENS_BEFORE(&this->_M_refcount);
3305 // Decrement of _M_refcount is acq_rel, because:
3306 // - all but last decrements need to release to synchronize with
3307 // the last decrement that will delete the object.
3308 // - the last decrement needs to acquire to synchronize with
3309 // all the previous decrements.
3310 // - last but one decrement needs to release to synchronize with
3311 // the acquire load in _M_is_shared that will conclude that
3312 // the object is not shared anymore.
3313 if (__gnu_cxx::__exchange_and_add_dispatch(&this->_M_refcount,
3314 -1) <= 0)
3315 {
3316 _GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER(&this->_M_refcount);
3317 _M_destroy(__a);
3318 }
3319 }
3320 } // XXX MT
3321
3322 void
3323 _M_destroy(const _Alloc&) throw();
3324
3325 _CharT*
3326 _M_refcopy() throw()
3327 {
3328#if _GLIBCXX_FULLY_DYNAMIC_STRING0 == 0
3329 if (__builtin_expect(this != &_S_empty_rep(), false))
3330#endif
3331 __gnu_cxx::__atomic_add_dispatch(&this->_M_refcount, 1);
3332 return _M_refdata();
3333 } // XXX MT
3334
3335 _CharT*
3336 _M_clone(const _Alloc&, size_type __res = 0);
3337 };
3338
3339 // Use empty-base optimization: http://www.cantrip.org/emptyopt.html
3340 struct _Alloc_hider : _Alloc
3341 {
3342 _Alloc_hider(_CharT* __dat, const _Alloc& __a) _GLIBCXX_NOEXCEPTnoexcept
3343 : _Alloc(__a), _M_p(__dat) { }
3344
3345 _CharT* _M_p; // The actual data.
3346 };
3347
3348 public:
3349 // Data Members (public):
3350 // NB: This is an unsigned type, and thus represents the maximum
3351 // size that the allocator can hold.
3352 /// Value returned by various member functions when they fail.
3353 static const size_type npos = static_cast<size_type>(-1);
3354
3355 private:
3356 // Data Members (private):
3357 mutable _Alloc_hider _M_dataplus;
3358
3359 _CharT*
3360 _M_data() const _GLIBCXX_NOEXCEPTnoexcept
3361 { return _M_dataplus._M_p; }
3362
3363 _CharT*
3364 _M_data(_CharT* __p) _GLIBCXX_NOEXCEPTnoexcept
3365 { return (_M_dataplus._M_p = __p); }
3366
3367 _Rep*
3368 _M_rep() const _GLIBCXX_NOEXCEPTnoexcept
3369 { return &((reinterpret_cast<_Rep*> (_M_data()))[-1]); }
3370
3371 // For the internal use we have functions similar to `begin'/`end'
3372 // but they do not call _M_leak.
3373 iterator
3374 _M_ibegin() const _GLIBCXX_NOEXCEPTnoexcept
3375 { return iterator(_M_data()); }
3376
3377 iterator
3378 _M_iend() const _GLIBCXX_NOEXCEPTnoexcept
3379 { return iterator(_M_data() + this->size()); }
3380
3381 void
3382 _M_leak() // for use in begin() & non-const op[]
3383 {
3384 if (!_M_rep()->_M_is_leaked())
3385 _M_leak_hard();
3386 }
3387
3388 size_type
3389 _M_check(size_type __pos, const char* __s) const
3390 {
3391 if (__pos > this->size())
3392 __throw_out_of_range_fmt(__N("%s: __pos (which is %zu) > "("%s: __pos (which is %zu) > " "this->size() (which is %zu)"
)
3393 "this->size() (which is %zu)")("%s: __pos (which is %zu) > " "this->size() (which is %zu)"
)
,
3394 __s, __pos, this->size());
3395 return __pos;
3396 }
3397
3398 void
3399 _M_check_length(size_type __n1, size_type __n2, const char* __s) const
3400 {
3401 if (this->max_size() - (this->size() - __n1) < __n2)
3402 __throw_length_error(__N(__s)(__s));
3403 }
3404
3405 // NB: _M_limit doesn't check for a bad __pos value.
3406 size_type
3407 _M_limit(size_type __pos, size_type __off) const _GLIBCXX_NOEXCEPTnoexcept
3408 {
3409 const bool __testoff = __off < this->size() - __pos;
3410 return __testoff ? __off : this->size() - __pos;
3411 }
3412
3413 // True if _Rep and source do not overlap.
3414 bool
3415 _M_disjunct(const _CharT* __s) const _GLIBCXX_NOEXCEPTnoexcept
3416 {
3417 return (less<const _CharT*>()(__s, _M_data())
3418 || less<const _CharT*>()(_M_data() + this->size(), __s));
3419 }
3420
3421 // When __n = 1 way faster than the general multichar
3422 // traits_type::copy/move/assign.
3423 static void
3424 _M_copy(_CharT* __d, const _CharT* __s, size_type __n) _GLIBCXX_NOEXCEPTnoexcept
3425 {
3426 if (__n == 1)
3427 traits_type::assign(*__d, *__s);
3428 else
3429 traits_type::copy(__d, __s, __n);
3430 }
3431
3432 static void
3433 _M_move(_CharT* __d, const _CharT* __s, size_type __n) _GLIBCXX_NOEXCEPTnoexcept
3434 {
3435 if (__n == 1)
3436 traits_type::assign(*__d, *__s);
3437 else
3438 traits_type::move(__d, __s, __n);
3439 }
3440
3441 static void
3442 _M_assign(_CharT* __d, size_type __n, _CharT __c) _GLIBCXX_NOEXCEPTnoexcept
3443 {
3444 if (__n == 1)
3445 traits_type::assign(*__d, __c);
3446 else
3447 traits_type::assign(__d, __n, __c);
3448 }
3449
3450 // _S_copy_chars is a separate template to permit specialization
3451 // to optimize for the common case of pointers as iterators.
3452 template<class _Iterator>
3453 static void
3454 _S_copy_chars(_CharT* __p, _Iterator __k1, _Iterator __k2)
3455 {
3456 for (; __k1 != __k2; ++__k1, (void)++__p)
3457 traits_type::assign(*__p, *__k1); // These types are off.
3458 }
3459
3460 static void
3461 _S_copy_chars(_CharT* __p, iterator __k1, iterator __k2) _GLIBCXX_NOEXCEPTnoexcept
3462 { _S_copy_chars(__p, __k1.base(), __k2.base()); }
3463
3464 static void
3465 _S_copy_chars(_CharT* __p, const_iterator __k1, const_iterator __k2)
3466 _GLIBCXX_NOEXCEPTnoexcept
3467 { _S_copy_chars(__p, __k1.base(), __k2.base()); }
3468
3469 static void
3470 _S_copy_chars(_CharT* __p, _CharT* __k1, _CharT* __k2) _GLIBCXX_NOEXCEPTnoexcept
3471 { _M_copy(__p, __k1, __k2 - __k1); }
3472
3473 static void
3474 _S_copy_chars(_CharT* __p, const _CharT* __k1, const _CharT* __k2)
3475 _GLIBCXX_NOEXCEPTnoexcept
3476 { _M_copy(__p, __k1, __k2 - __k1); }
3477
3478 static int
3479 _S_compare(size_type __n1, size_type __n2) _GLIBCXX_NOEXCEPTnoexcept
3480 {
3481 const difference_type __d = difference_type(__n1 - __n2);
3482
3483 if (__d > __gnu_cxx::__numeric_traits<int>::__max)
3484 return __gnu_cxx::__numeric_traits<int>::__max;
3485 else if (__d < __gnu_cxx::__numeric_traits<int>::__min)
3486 return __gnu_cxx::__numeric_traits<int>::__min;
3487 else
3488 return int(__d);
3489 }
3490
3491 void
3492 _M_mutate(size_type __pos, size_type __len1, size_type __len2);
3493
3494 void
3495 _M_leak_hard();
3496
3497 static _Rep&
3498 _S_empty_rep() _GLIBCXX_NOEXCEPTnoexcept
3499 { return _Rep::_S_empty_rep(); }
3500
3501#if __cplusplus201703L >= 201703L
3502 // A helper type for avoiding boiler-plate.
3503 typedef basic_string_view<_CharT, _Traits> __sv_type;
3504
3505 template<typename _Tp, typename _Res>
3506 using _If_sv = enable_if_t<
3507 __and_<is_convertible<const _Tp&, __sv_type>,
3508 __not_<is_convertible<const _Tp*, const basic_string*>>,
3509 __not_<is_convertible<const _Tp&, const _CharT*>>>::value,
3510 _Res>;
3511
3512 // Allows an implicit conversion to __sv_type.
3513 static __sv_type
3514 _S_to_string_view(__sv_type __svt) noexcept
3515 { return __svt; }
3516
3517 // Wraps a string_view by explicit conversion and thus
3518 // allows to add an internal constructor that does not
3519 // participate in overload resolution when a string_view
3520 // is provided.
3521 struct __sv_wrapper
3522 {
3523 explicit __sv_wrapper(__sv_type __sv) noexcept : _M_sv(__sv) { }
3524 __sv_type _M_sv;
3525 };
3526
3527 /**
3528 * @brief Only internally used: Construct string from a string view
3529 * wrapper.
3530 * @param __svw string view wrapper.
3531 * @param __a Allocator to use.
3532 */
3533 explicit
3534 basic_string(__sv_wrapper __svw, const _Alloc& __a)
3535 : basic_string(__svw._M_sv.data(), __svw._M_sv.size(), __a) { }
3536#endif
3537
3538 public:
3539 // Construct/copy/destroy:
3540 // NB: We overload ctors in some cases instead of using default
3541 // arguments, per 17.4.4.4 para. 2 item 2.
3542
3543 /**
3544 * @brief Default constructor creates an empty string.
3545 */
3546 basic_string()
3547#if _GLIBCXX_FULLY_DYNAMIC_STRING0 == 0
3548 _GLIBCXX_NOEXCEPTnoexcept
3549 : _M_dataplus(_S_empty_rep()._M_refdata(), _Alloc())
3550#else
3551 : _M_dataplus(_S_construct(size_type(), _CharT(), _Alloc()), _Alloc())
3552#endif
3553 { }
3554
3555 /**
3556 * @brief Construct an empty string using allocator @a a.
3557 */
3558 explicit
3559 basic_string(const _Alloc& __a);
3560
3561 // NB: per LWG issue 42, semantics different from IS:
3562 /**
3563 * @brief Construct string with copy of value of @a str.
3564 * @param __str Source string.
3565 */
3566 basic_string(const basic_string& __str);
3567
3568 // _GLIBCXX_RESOLVE_LIB_DEFECTS
3569 // 2583. no way to supply an allocator for basic_string(str, pos)
3570 /**
3571 * @brief Construct string as copy of a substring.
3572 * @param __str Source string.
3573 * @param __pos Index of first character to copy from.
3574 * @param __a Allocator to use.
3575 */
3576 basic_string(const basic_string& __str, size_type __pos,
3577 const _Alloc& __a = _Alloc());
3578
3579 /**
3580 * @brief Construct string as copy of a substring.
3581 * @param __str Source string.
3582 * @param __pos Index of first character to copy from.
3583 * @param __n Number of characters to copy.
3584 */
3585 basic_string(const basic_string& __str, size_type __pos,
3586 size_type __n);
3587 /**
3588 * @brief Construct string as copy of a substring.
3589 * @param __str Source string.
3590 * @param __pos Index of first character to copy from.
3591 * @param __n Number of characters to copy.
3592 * @param __a Allocator to use.
3593 */
3594 basic_string(const basic_string& __str, size_type __pos,
3595 size_type __n, const _Alloc& __a);
3596
3597 /**
3598 * @brief Construct string initialized by a character %array.
3599 * @param __s Source character %array.
3600 * @param __n Number of characters to copy.
3601 * @param __a Allocator to use (default is default allocator).
3602 *
3603 * NB: @a __s must have at least @a __n characters, &apos;\\0&apos;
3604 * has no special meaning.
3605 */
3606 basic_string(const _CharT* __s, size_type __n,
3607 const _Alloc& __a = _Alloc());
3608
3609 /**
3610 * @brief Construct string as copy of a C string.
3611 * @param __s Source C string.
3612 * @param __a Allocator to use (default is default allocator).
3613 */
3614#if __cpp_deduction_guides201703L && ! defined _GLIBCXX_DEFINING_STRING_INSTANTIATIONS
3615 // _GLIBCXX_RESOLVE_LIB_DEFECTS
3616 // 3076. basic_string CTAD ambiguity
3617 template<typename = _RequireAllocator<_Alloc>>
3618#endif
3619 basic_string(const _CharT* __s, const _Alloc& __a = _Alloc())
3620 : _M_dataplus(_S_construct(__s, __s ? __s + traits_type::length(__s) :
3621 __s + npos, __a), __a)
3622 { }
3623
3624 /**
3625 * @brief Construct string as multiple characters.
3626 * @param __n Number of characters.
3627 * @param __c Character to use.
3628 * @param __a Allocator to use (default is default allocator).
3629 */
3630 basic_string(size_type __n, _CharT __c, const _Alloc& __a = _Alloc());
3631
3632#if __cplusplus201703L >= 201103L
3633 /**
3634 * @brief Move construct string.
3635 * @param __str Source string.
3636 *
3637 * The newly-created string contains the exact contents of @a __str.
3638 * @a __str is a valid, but unspecified string.
3639 **/
3640 basic_string(basic_string&& __str)
3641#if _GLIBCXX_FULLY_DYNAMIC_STRING0 == 0
3642 noexcept // FIXME C++11: should always be noexcept.
3643#endif
3644 : _M_dataplus(std::move(__str._M_dataplus))
3645 {
3646#if _GLIBCXX_FULLY_DYNAMIC_STRING0 == 0
3647 __str._M_data(_S_empty_rep()._M_refdata());
3648#else
3649 __str._M_data(_S_construct(size_type(), _CharT(), get_allocator()));
3650#endif
3651 }
3652
3653 /**
3654 * @brief Construct string from an initializer %list.
3655 * @param __l std::initializer_list of characters.
3656 * @param __a Allocator to use (default is default allocator).
3657 */
3658 basic_string(initializer_list<_CharT> __l, const _Alloc& __a = _Alloc());
3659
3660 basic_string(const basic_string& __str, const _Alloc& __a)
3661 : _M_dataplus(__str._M_rep()->_M_grab(__a, __str.get_allocator()), __a)
3662 { }
3663
3664 basic_string(basic_string&& __str, const _Alloc& __a)
3665 : _M_dataplus(__str._M_data(), __a)
3666 {
3667 if (__a == __str.get_allocator())
3668 {
3669#if _GLIBCXX_FULLY_DYNAMIC_STRING0 == 0
3670 __str._M_data(_S_empty_rep()._M_refdata());
3671#else
3672 __str._M_data(_S_construct(size_type(), _CharT(), __a));
3673#endif
3674 }
3675 else
3676 _M_dataplus._M_p = _S_construct(__str.begin(), __str.end(), __a);
3677 }
3678#endif // C++11
3679
3680 /**
3681 * @brief Construct string as copy of a range.
3682 * @param __beg Start of range.
3683 * @param __end End of range.
3684 * @param __a Allocator to use (default is default allocator).
3685 */
3686 template<class _InputIterator>
3687 basic_string(_InputIterator __beg, _InputIterator __end,
3688 const _Alloc& __a = _Alloc());
3689
3690#if __cplusplus201703L >= 201703L
3691 /**
3692 * @brief Construct string from a substring of a string_view.
3693 * @param __t Source object convertible to string view.
3694 * @param __pos The index of the first character to copy from __t.
3695 * @param __n The number of characters to copy from __t.
3696 * @param __a Allocator to use.
3697 */
3698 template<typename _Tp, typename = _If_sv<_Tp, void>>
3699 basic_string(const _Tp& __t, size_type __pos, size_type __n,
3700 const _Alloc& __a = _Alloc())
3701 : basic_string(_S_to_string_view(__t).substr(__pos, __n), __a) { }
3702
3703 /**
3704 * @brief Construct string from a string_view.
3705 * @param __t Source object convertible to string view.
3706 * @param __a Allocator to use (default is default allocator).
3707 */
3708 template<typename _Tp, typename = _If_sv<_Tp, void>>
3709 explicit
3710 basic_string(const _Tp& __t, const _Alloc& __a = _Alloc())
3711 : basic_string(__sv_wrapper(_S_to_string_view(__t)), __a) { }
3712#endif // C++17
3713
3714 /**
3715 * @brief Destroy the string instance.
3716 */
3717 ~basic_string() _GLIBCXX_NOEXCEPTnoexcept
3718 { _M_rep()->_M_dispose(this->get_allocator()); }
3719
3720 /**
3721 * @brief Assign the value of @a str to this string.
3722 * @param __str Source string.
3723 */
3724 basic_string&
3725 operator=(const basic_string& __str)
3726 { return this->assign(__str); }
3727
3728 /**
3729 * @brief Copy contents of @a s into this string.
3730 * @param __s Source null-terminated string.
3731 */
3732 basic_string&
3733 operator=(const _CharT* __s)
3734 { return this->assign(__s); }
3735
3736 /**
3737 * @brief Set value to string of length 1.
3738 * @param __c Source character.
3739 *
3740 * Assigning to a character makes this string length 1 and
3741 * (*this)[0] == @a c.
3742 */
3743 basic_string&
3744 operator=(_CharT __c)
3745 {
3746 this->assign(1, __c);
3747 return *this;
3748 }
3749
3750#if __cplusplus201703L >= 201103L
3751 /**
3752 * @brief Move assign the value of @a str to this string.
3753 * @param __str Source string.
3754 *
3755 * The contents of @a str are moved into this string (without copying).
3756 * @a str is a valid, but unspecified string.
3757 **/
3758 basic_string&
3759 operator=(basic_string&& __str)
3760 _GLIBCXX_NOEXCEPT_IF(allocator_traits<_Alloc>::is_always_equal::value)noexcept(allocator_traits<_Alloc>::is_always_equal::value
)
3761 {
3762 // NB: DR 1204.
3763 this->swap(__str);
3764 return *this;
3765 }
3766
3767 /**
3768 * @brief Set value to string constructed from initializer %list.
3769 * @param __l std::initializer_list.
3770 */
3771 basic_string&
3772 operator=(initializer_list<_CharT> __l)
3773 {
3774 this->assign(__l.begin(), __l.size());
3775 return *this;
3776 }
3777#endif // C++11
3778
3779#if __cplusplus201703L >= 201703L
3780 /**
3781 * @brief Set value to string constructed from a string_view.
3782 * @param __svt An object convertible to string_view.
3783 */
3784 template<typename _Tp>
3785 _If_sv<_Tp, basic_string&>
3786 operator=(const _Tp& __svt)
3787 { return this->assign(__svt); }
3788
3789 /**
3790 * @brief Convert to a string_view.
3791 * @return A string_view.
3792 */
3793 operator __sv_type() const noexcept
3794 { return __sv_type(data(), size()); }
3795#endif // C++17
3796
3797 // Iterators:
3798 /**
3799 * Returns a read/write iterator that points to the first character in
3800 * the %string. Unshares the string.
3801 */
3802 iterator
3803 begin() // FIXME C++11: should be noexcept.
3804 {
3805 _M_leak();
3806 return iterator(_M_data());
3807 }
3808
3809 /**
3810 * Returns a read-only (constant) iterator that points to the first
3811 * character in the %string.
3812 */
3813 const_iterator
3814 begin() const _GLIBCXX_NOEXCEPTnoexcept
3815 { return const_iterator(_M_data()); }
3816
3817 /**
3818 * Returns a read/write iterator that points one past the last
3819 * character in the %string. Unshares the string.
3820 */
3821 iterator
3822 end() // FIXME C++11: should be noexcept.
3823 {
3824 _M_leak();
3825 return iterator(_M_data() + this->size());
3826 }
3827
3828 /**
3829 * Returns a read-only (constant) iterator that points one past the
3830 * last character in the %string.
3831 */
3832 const_iterator
3833 end() const _GLIBCXX_NOEXCEPTnoexcept
3834 { return const_iterator(_M_data() + this->size()); }
3835
3836 /**
3837 * Returns a read/write reverse iterator that points to the last
3838 * character in the %string. Iteration is done in reverse element
3839 * order. Unshares the string.
3840 */
3841 reverse_iterator
3842 rbegin() // FIXME C++11: should be noexcept.
3843 { return reverse_iterator(this->end()); }
3844
3845 /**
3846 * Returns a read-only (constant) reverse iterator that points
3847 * to the last character in the %string. Iteration is done in
3848 * reverse element order.
3849 */
3850 const_reverse_iterator
3851 rbegin() const _GLIBCXX_NOEXCEPTnoexcept
3852 { return const_reverse_iterator(this->end()); }
3853
3854 /**
3855 * Returns a read/write reverse iterator that points to one before the
3856 * first character in the %string. Iteration is done in reverse
3857 * element order. Unshares the string.
3858 */
3859 reverse_iterator
3860 rend() // FIXME C++11: should be noexcept.
3861 { return reverse_iterator(this->begin()); }
3862
3863 /**
3864 * Returns a read-only (constant) reverse iterator that points
3865 * to one before the first character in the %string. Iteration
3866 * is done in reverse element order.
3867 */
3868 const_reverse_iterator
3869 rend() const _GLIBCXX_NOEXCEPTnoexcept
3870 { return const_reverse_iterator(this->begin()); }
3871
3872#if __cplusplus201703L >= 201103L
3873 /**
3874 * Returns a read-only (constant) iterator that points to the first
3875 * character in the %string.
3876 */
3877 const_iterator
3878 cbegin() const noexcept
3879 { return const_iterator(this->_M_data()); }
3880
3881 /**
3882 * Returns a read-only (constant) iterator that points one past the
3883 * last character in the %string.
3884 */
3885 const_iterator
3886 cend() const noexcept
3887 { return const_iterator(this->_M_data() + this->size()); }
3888
3889 /**
3890 * Returns a read-only (constant) reverse iterator that points
3891 * to the last character in the %string. Iteration is done in
3892 * reverse element order.
3893 */
3894 const_reverse_iterator
3895 crbegin() const noexcept
3896 { return const_reverse_iterator(this->end()); }
3897
3898 /**
3899 * Returns a read-only (constant) reverse iterator that points
3900 * to one before the first character in the %string. Iteration
3901 * is done in reverse element order.
3902 */
3903 const_reverse_iterator
3904 crend() const noexcept
3905 { return const_reverse_iterator(this->begin()); }
3906#endif
3907
3908 public:
3909 // Capacity:
3910 /// Returns the number of characters in the string, not including any
3911 /// null-termination.
3912 size_type
3913 size() const _GLIBCXX_NOEXCEPTnoexcept
3914 { return _M_rep()->_M_length; }
3915
3916 /// Returns the number of characters in the string, not including any
3917 /// null-termination.
3918 size_type
3919 length() const _GLIBCXX_NOEXCEPTnoexcept
3920 { return _M_rep()->_M_length; }
3921
3922 /// Returns the size() of the largest possible %string.
3923 size_type
3924 max_size() const _GLIBCXX_NOEXCEPTnoexcept
3925 { return _Rep::_S_max_size; }
3926
3927 /**
3928 * @brief Resizes the %string to the specified number of characters.
3929 * @param __n Number of characters the %string should contain.
3930 * @param __c Character to fill any new elements.
3931 *
3932 * This function will %resize the %string to the specified
3933 * number of characters. If the number is smaller than the
3934 * %string's current size the %string is truncated, otherwise
3935 * the %string is extended and new elements are %set to @a __c.
3936 */
3937 void
3938 resize(size_type __n, _CharT __c);
3939
3940 /**
3941 * @brief Resizes the %string to the specified number of characters.
3942 * @param __n Number of characters the %string should contain.
3943 *
3944 * This function will resize the %string to the specified length. If
3945 * the new size is smaller than the %string's current size the %string
3946 * is truncated, otherwise the %string is extended and new characters
3947 * are default-constructed. For basic types such as char, this means
3948 * setting them to 0.
3949 */
3950 void
3951 resize(size_type __n)
3952 { this->resize(__n, _CharT()); }
3953
3954#if __cplusplus201703L >= 201103L
3955 /// A non-binding request to reduce capacity() to size().
3956 void
3957 shrink_to_fit() _GLIBCXX_NOEXCEPTnoexcept
3958 {
3959#if __cpp_exceptions
3960 if (capacity() > size())
3961 {
3962 try
3963 { reserve(0); }
3964 catch(...)
3965 { }
3966 }
3967#endif
3968 }
3969#endif
3970
3971 /**
3972 * Returns the total number of characters that the %string can hold
3973 * before needing to allocate more memory.
3974 */
3975 size_type
3976 capacity() const _GLIBCXX_NOEXCEPTnoexcept
3977 { return _M_rep()->_M_capacity; }
3978
3979 /**
3980 * @brief Attempt to preallocate enough memory for specified number of
3981 * characters.
3982 * @param __res_arg Number of characters required.
3983 * @throw std::length_error If @a __res_arg exceeds @c max_size().
3984 *
3985 * This function attempts to reserve enough memory for the
3986 * %string to hold the specified number of characters. If the
3987 * number requested is more than max_size(), length_error is
3988 * thrown.
3989 *
3990 * The advantage of this function is that if optimal code is a
3991 * necessity and the user can determine the string length that will be
3992 * required, the user can reserve the memory in %advance, and thus
3993 * prevent a possible reallocation of memory and copying of %string
3994 * data.
3995 */
3996 void
3997 reserve(size_type __res_arg = 0);
3998
3999 /**
4000 * Erases the string, making it empty.
4001 */
4002#if _GLIBCXX_FULLY_DYNAMIC_STRING0 == 0
4003 void
4004 clear() _GLIBCXX_NOEXCEPTnoexcept
4005 {
4006 if (_M_rep()->_M_is_shared())
4007 {
4008 _M_rep()->_M_dispose(this->get_allocator());
4009 _M_data(_S_empty_rep()._M_refdata());
4010 }
4011 else
4012 _M_rep()->_M_set_length_and_sharable(0);
4013 }
4014#else
4015 // PR 56166: this should not throw.
4016 void
4017 clear()
4018 { _M_mutate(0, this->size(), 0); }
4019#endif
4020
4021 /**
4022 * Returns true if the %string is empty. Equivalent to
4023 * <code>*this == ""</code>.
4024 */
4025 _GLIBCXX_NODISCARD[[__nodiscard__]] bool
4026 empty() const _GLIBCXX_NOEXCEPTnoexcept
4027 { return this->size() == 0; }
4028
4029 // Element access:
4030 /**
4031 * @brief Subscript access to the data contained in the %string.
4032 * @param __pos The index of the character to access.
4033 * @return Read-only (constant) reference to the character.
4034 *
4035 * This operator allows for easy, array-style, data access.
4036 * Note that data access with this operator is unchecked and
4037 * out_of_range lookups are not defined. (For checked lookups
4038 * see at().)
4039 */
4040 const_reference
4041 operator[] (size_type __pos) const _GLIBCXX_NOEXCEPTnoexcept
4042 {
4043 __glibcxx_assert(__pos <= size())do { if (! (__pos <= size())) std::__replacement_assert("/usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/basic_string.h"
, 4043, __PRETTY_FUNCTION__, "__pos <= size()"); } while (
false)
;
4044 return _M_data()[__pos];
4045 }
4046
4047 /**
4048 * @brief Subscript access to the data contained in the %string.
4049 * @param __pos The index of the character to access.
4050 * @return Read/write reference to the character.
4051 *
4052 * This operator allows for easy, array-style, data access.
4053 * Note that data access with this operator is unchecked and
4054 * out_of_range lookups are not defined. (For checked lookups
4055 * see at().) Unshares the string.
4056 */
4057 reference
4058 operator[](size_type __pos)
4059 {
4060 // Allow pos == size() both in C++98 mode, as v3 extension,
4061 // and in C++11 mode.
4062 __glibcxx_assert(__pos <= size())do { if (! (__pos <= size())) std::__replacement_assert("/usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/basic_string.h"
, 4062, __PRETTY_FUNCTION__, "__pos <= size()"); } while (
false)
;
4063 // In pedantic mode be strict in C++98 mode.
4064 _GLIBCXX_DEBUG_PEDASSERT(__cplusplus >= 201103L || __pos < size());
4065 _M_leak();
4066 return _M_data()[__pos];
4067 }
4068
4069 /**
4070 * @brief Provides access to the data contained in the %string.
4071 * @param __n The index of the character to access.
4072 * @return Read-only (const) reference to the character.
4073 * @throw std::out_of_range If @a n is an invalid index.
4074 *
4075 * This function provides for safer data access. The parameter is
4076 * first checked that it is in the range of the string. The function
4077 * throws out_of_range if the check fails.
4078 */
4079 const_reference
4080 at(size_type __n) const
4081 {
4082 if (__n >= this->size())
4083 __throw_out_of_range_fmt(__N("basic_string::at: __n "("basic_string::at: __n " "(which is %zu) >= this->size() "
"(which is %zu)")
4084 "(which is %zu) >= this->size() "("basic_string::at: __n " "(which is %zu) >= this->size() "
"(which is %zu)")
4085 "(which is %zu)")("basic_string::at: __n " "(which is %zu) >= this->size() "
"(which is %zu)")
,
4086 __n, this->size());
4087 return _M_data()[__n];
4088 }
4089
4090 /**
4091 * @brief Provides access to the data contained in the %string.
4092 * @param __n The index of the character to access.
4093 * @return Read/write reference to the character.
4094 * @throw std::out_of_range If @a n is an invalid index.
4095 *
4096 * This function provides for safer data access. The parameter is
4097 * first checked that it is in the range of the string. The function
4098 * throws out_of_range if the check fails. Success results in
4099 * unsharing the string.
4100 */
4101 reference
4102 at(size_type __n)
4103 {
4104 if (__n >= size())
4105 __throw_out_of_range_fmt(__N("basic_string::at: __n "("basic_string::at: __n " "(which is %zu) >= this->size() "
"(which is %zu)")
4106 "(which is %zu) >= this->size() "("basic_string::at: __n " "(which is %zu) >= this->size() "
"(which is %zu)")
4107 "(which is %zu)")("basic_string::at: __n " "(which is %zu) >= this->size() "
"(which is %zu)")
,
4108 __n, this->size());
4109 _M_leak();
4110 return _M_data()[__n];
4111 }
4112
4113#if __cplusplus201703L >= 201103L
4114 /**
4115 * Returns a read/write reference to the data at the first
4116 * element of the %string.
4117 */
4118 reference
4119 front()
4120 {
4121 __glibcxx_assert(!empty())do { if (! (!empty())) std::__replacement_assert("/usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/basic_string.h"
, 4121, __PRETTY_FUNCTION__, "!empty()"); } while (false)
;
4122 return operator[](0);
4123 }
4124
4125 /**
4126 * Returns a read-only (constant) reference to the data at the first
4127 * element of the %string.
4128 */
4129 const_reference
4130 front() const noexcept
4131 {
4132 __glibcxx_assert(!empty())do { if (! (!empty())) std::__replacement_assert("/usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/basic_string.h"
, 4132, __PRETTY_FUNCTION__, "!empty()"); } while (false)
;
4133 return operator[](0);
4134 }
4135
4136 /**
4137 * Returns a read/write reference to the data at the last
4138 * element of the %string.
4139 */
4140 reference
4141 back()
4142 {
4143 __glibcxx_assert(!empty())do { if (! (!empty())) std::__replacement_assert("/usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/basic_string.h"
, 4143, __PRETTY_FUNCTION__, "!empty()"); } while (false)
;
4144 return operator[](this->size() - 1);
4145 }
4146
4147 /**
4148 * Returns a read-only (constant) reference to the data at the
4149 * last element of the %string.
4150 */
4151 const_reference
4152 back() const noexcept
4153 {
4154 __glibcxx_assert(!empty())do { if (! (!empty())) std::__replacement_assert("/usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/basic_string.h"
, 4154, __PRETTY_FUNCTION__, "!empty()"); } while (false)
;
4155 return operator[](this->size() - 1);
4156 }
4157#endif
4158
4159 // Modifiers:
4160 /**
4161 * @brief Append a string to this string.
4162 * @param __str The string to append.
4163 * @return Reference to this string.
4164 */
4165 basic_string&
4166 operator+=(const basic_string& __str)
4167 { return this->append(__str); }
4168
4169 /**
4170 * @brief Append a C string.
4171 * @param __s The C string to append.
4172 * @return Reference to this string.
4173 */
4174 basic_string&
4175 operator+=(const _CharT* __s)
4176 { return this->append(__s); }
4177
4178 /**
4179 * @brief Append a character.
4180 * @param __c The character to append.
4181 * @return Reference to this string.
4182 */
4183 basic_string&
4184 operator+=(_CharT __c)
4185 {
4186 this->push_back(__c);
4187 return *this;
4188 }
4189
4190#if __cplusplus201703L >= 201103L
4191 /**
4192 * @brief Append an initializer_list of characters.
4193 * @param __l The initializer_list of characters to be appended.
4194 * @return Reference to this string.
4195 */
4196 basic_string&
4197 operator+=(initializer_list<_CharT> __l)
4198 { return this->append(__l.begin(), __l.size()); }
4199#endif // C++11
4200
4201#if __cplusplus201703L >= 201703L
4202 /**
4203 * @brief Append a string_view.
4204 * @param __svt The object convertible to string_view to be appended.
4205 * @return Reference to this string.
4206 */
4207 template<typename _Tp>
4208 _If_sv<_Tp, basic_string&>
4209 operator+=(const _Tp& __svt)
4210 { return this->append(__svt); }
4211#endif // C++17
4212
4213 /**
4214 * @brief Append a string to this string.
4215 * @param __str The string to append.
4216 * @return Reference to this string.
4217 */
4218 basic_string&
4219 append(const basic_string& __str);
4220
4221 /**
4222 * @brief Append a substring.
4223 * @param __str The string to append.
4224 * @param __pos Index of the first character of str to append.
4225 * @param __n The number of characters to append.
4226 * @return Reference to this string.
4227 * @throw std::out_of_range if @a __pos is not a valid index.
4228 *
4229 * This function appends @a __n characters from @a __str
4230 * starting at @a __pos to this string. If @a __n is is larger
4231 * than the number of available characters in @a __str, the
4232 * remainder of @a __str is appended.
4233 */
4234 basic_string&
4235 append(const basic_string& __str, size_type __pos, size_type __n = npos);
4236
4237 /**
4238 * @brief Append a C substring.
4239 * @param __s The C string to append.
4240 * @param __n The number of characters to append.
4241 * @return Reference to this string.
4242 */
4243 basic_string&
4244 append(const _CharT* __s, size_type __n);
4245
4246 /**
4247 * @brief Append a C string.
4248 * @param __s The C string to append.
4249 * @return Reference to this string.
4250 */
4251 basic_string&
4252 append(const _CharT* __s)
4253 {
4254 __glibcxx_requires_string(__s);
4255 return this->append(__s, traits_type::length(__s));
4256 }
4257
4258 /**
4259 * @brief Append multiple characters.
4260 * @param __n The number of characters to append.
4261 * @param __c The character to use.
4262 * @return Reference to this string.
4263 *
4264 * Appends __n copies of __c to this string.
4265 */
4266 basic_string&
4267 append(size_type __n, _CharT __c);
4268
4269#if __cplusplus201703L >= 201103L
4270 /**
4271 * @brief Append an initializer_list of characters.
4272 * @param __l The initializer_list of characters to append.
4273 * @return Reference to this string.
4274 */
4275 basic_string&
4276 append(initializer_list<_CharT> __l)
4277 { return this->append(__l.begin(), __l.size()); }
4278#endif // C++11
4279
4280 /**
4281 * @brief Append a range of characters.
4282 * @param __first Iterator referencing the first character to append.
4283 * @param __last Iterator marking the end of the range.
4284 * @return Reference to this string.
4285 *
4286 * Appends characters in the range [__first,__last) to this string.
4287 */
4288 template<class _InputIterator>
4289 basic_string&
4290 append(_InputIterator __first, _InputIterator __last)
4291 { return this->replace(_M_iend(), _M_iend(), __first, __last); }
4292
4293#if __cplusplus201703L >= 201703L
4294 /**
4295 * @brief Append a string_view.
4296 * @param __svt The object convertible to string_view to be appended.
4297 * @return Reference to this string.
4298 */
4299 template<typename _Tp>
4300 _If_sv<_Tp, basic_string&>
4301 append(const _Tp& __svt)
4302 {
4303 __sv_type __sv = __svt;
4304 return this->append(__sv.data(), __sv.size());
4305 }
4306
4307 /**
4308 * @brief Append a range of characters from a string_view.
4309 * @param __svt The object convertible to string_view to be appended
4310 * from.
4311 * @param __pos The position in the string_view to append from.
4312 * @param __n The number of characters to append from the string_view.
4313 * @return Reference to this string.
4314 */
4315 template<typename _Tp>
4316 _If_sv<_Tp, basic_string&>
4317 append(const _Tp& __svt, size_type __pos, size_type __n = npos)
4318 {
4319 __sv_type __sv = __svt;
4320 return append(__sv.data()
4321 + std::__sv_check(__sv.size(), __pos, "basic_string::append"),
4322 std::__sv_limit(__sv.size(), __pos, __n));
4323 }
4324#endif // C++17
4325
4326 /**
4327 * @brief Append a single character.
4328 * @param __c Character to append.
4329 */
4330 void
4331 push_back(_CharT __c)
4332 {
4333 const size_type __len = 1 + this->size();
4334 if (__len > this->capacity() || _M_rep()->_M_is_shared())
4335 this->reserve(__len);
4336 traits_type::assign(_M_data()[this->size()], __c);
4337 _M_rep()->_M_set_length_and_sharable(__len);
4338 }
4339
4340 /**
4341 * @brief Set value to contents of another string.
4342 * @param __str Source string to use.
4343 * @return Reference to this string.
4344 */
4345 basic_string&
4346 assign(const basic_string& __str);
4347
4348#if __cplusplus201703L >= 201103L
4349 /**
4350 * @brief Set value to contents of another string.
4351 * @param __str Source string to use.
4352 * @return Reference to this string.
4353 *
4354 * This function sets this string to the exact contents of @a __str.
4355 * @a __str is a valid, but unspecified string.
4356 */
4357 basic_string&
4358 assign(basic_string&& __str)
4359 noexcept(allocator_traits<_Alloc>::is_always_equal::value)
4360 {
4361 this->swap(__str);
4362 return *this;
4363 }
4364#endif // C++11
4365
4366 /**
4367 * @brief Set value to a substring of a string.
4368 * @param __str The string to use.
4369 * @param __pos Index of the first character of str.
4370 * @param __n Number of characters to use.
4371 * @return Reference to this string.
4372 * @throw std::out_of_range if @a pos is not a valid index.
4373 *
4374 * This function sets this string to the substring of @a __str
4375 * consisting of @a __n characters at @a __pos. If @a __n is
4376 * is larger than the number of available characters in @a
4377 * __str, the remainder of @a __str is used.
4378 */
4379 basic_string&
4380 assign(const basic_string& __str, size_type __pos, size_type __n = npos)
4381 { return this->assign(__str._M_data()
4382 + __str._M_check(__pos, "basic_string::assign"),
4383 __str._M_limit(__pos, __n)); }
4384
4385 /**
4386 * @brief Set value to a C substring.
4387 * @param __s The C string to use.
4388 * @param __n Number of characters to use.
4389 * @return Reference to this string.
4390 *
4391 * This function sets the value of this string to the first @a __n
4392 * characters of @a __s. If @a __n is is larger than the number of
4393 * available characters in @a __s, the remainder of @a __s is used.
4394 */
4395 basic_string&
4396 assign(const _CharT* __s, size_type __n);
4397
4398 /**
4399 * @brief Set value to contents of a C string.
4400 * @param __s The C string to use.
4401 * @return Reference to this string.
4402 *
4403 * This function sets the value of this string to the value of @a __s.
4404 * The data is copied, so there is no dependence on @a __s once the
4405 * function returns.
4406 */
4407 basic_string&
4408 assign(const _CharT* __s)
4409 {
4410 __glibcxx_requires_string(__s);
4411 return this->assign(__s, traits_type::length(__s));
4412 }
4413
4414 /**
4415 * @brief Set value to multiple characters.
4416 * @param __n Length of the resulting string.
4417 * @param __c The character to use.
4418 * @return Reference to this string.
4419 *
4420 * This function sets the value of this string to @a __n copies of
4421 * character @a __c.
4422 */
4423 basic_string&
4424 assign(size_type __n, _CharT __c)
4425 { return _M_replace_aux(size_type(0), this->size(), __n, __c); }
4426
4427 /**
4428 * @brief Set value to a range of characters.
4429 * @param __first Iterator referencing the first character to append.
4430 * @param __last Iterator marking the end of the range.
4431 * @return Reference to this string.
4432 *
4433 * Sets value of string to characters in the range [__first,__last).
4434 */
4435 template<class _InputIterator>
4436 basic_string&
4437 assign(_InputIterator __first, _InputIterator __last)
4438 { return this->replace(_M_ibegin(), _M_iend(), __first, __last); }
4439
4440#if __cplusplus201703L >= 201103L
4441 /**
4442 * @brief Set value to an initializer_list of characters.
4443 * @param __l The initializer_list of characters to assign.
4444 * @return Reference to this string.
4445 */
4446 basic_string&
4447 assign(initializer_list<_CharT> __l)
4448 { return this->assign(__l.begin(), __l.size()); }
4449#endif // C++11
4450
4451#if __cplusplus201703L >= 201703L
4452 /**
4453 * @brief Set value from a string_view.
4454 * @param __svt The source object convertible to string_view.
4455 * @return Reference to this string.
4456 */
4457 template<typename _Tp>
4458 _If_sv<_Tp, basic_string&>
4459 assign(const _Tp& __svt)
4460 {
4461 __sv_type __sv = __svt;
4462 return this->assign(__sv.data(), __sv.size());
4463 }
4464
4465 /**
4466 * @brief Set value from a range of characters in a string_view.
4467 * @param __svt The source object convertible to string_view.
4468 * @param __pos The position in the string_view to assign from.
4469 * @param __n The number of characters to assign.
4470 * @return Reference to this string.
4471 */
4472 template<typename _Tp>
4473 _If_sv<_Tp, basic_string&>
4474 assign(const _Tp& __svt, size_type __pos, size_type __n = npos)
4475 {
4476 __sv_type __sv = __svt;
4477 return assign(__sv.data()
4478 + std::__sv_check(__sv.size(), __pos, "basic_string::assign"),
4479 std::__sv_limit(__sv.size(), __pos, __n));
4480 }
4481#endif // C++17
4482
4483 /**
4484 * @brief Insert multiple characters.
4485 * @param __p Iterator referencing location in string to insert at.
4486 * @param __n Number of characters to insert
4487 * @param __c The character to insert.
4488 * @throw std::length_error If new length exceeds @c max_size().
4489 *
4490 * Inserts @a __n copies of character @a __c starting at the
4491 * position referenced by iterator @a __p. If adding
4492 * characters causes the length to exceed max_size(),
4493 * length_error is thrown. The value of the string doesn't
4494 * change if an error is thrown.
4495 */
4496 void
4497 insert(iterator __p, size_type __n, _CharT __c)
4498 { this->replace(__p, __p, __n, __c); }
4499
4500 /**
4501 * @brief Insert a range of characters.
4502 * @param __p Iterator referencing location in string to insert at.
4503 * @param __beg Start of range.
4504 * @param __end End of range.
4505 * @throw std::length_error If new length exceeds @c max_size().
4506 *
4507 * Inserts characters in range [__beg,__end). If adding
4508 * characters causes the length to exceed max_size(),
4509 * length_error is thrown. The value of the string doesn't
4510 * change if an error is thrown.
4511 */
4512 template<class _InputIterator>
4513 void
4514 insert(iterator __p, _InputIterator __beg, _InputIterator __end)
4515 { this->replace(__p, __p, __beg, __end); }
4516
4517#if __cplusplus201703L >= 201103L
4518 /**
4519 * @brief Insert an initializer_list of characters.
4520 * @param __p Iterator referencing location in string to insert at.
4521 * @param __l The initializer_list of characters to insert.
4522 * @throw std::length_error If new length exceeds @c max_size().
4523 */
4524 void
4525 insert(iterator __p, initializer_list<_CharT> __l)
4526 {
4527 _GLIBCXX_DEBUG_PEDASSERT(__p >= _M_ibegin() && __p <= _M_iend());
4528 this->insert(__p - _M_ibegin(), __l.begin(), __l.size());
4529 }
4530#endif // C++11
4531
4532 /**
4533 * @brief Insert value of a string.
4534 * @param __pos1 Position in string to insert at.
4535 * @param __str The string to insert.
4536 * @return Reference to this string.
4537 * @throw std::length_error If new length exceeds @c max_size().
4538 *
4539 * Inserts value of @a __str starting at @a __pos1. If adding
4540 * characters causes the length to exceed max_size(),
4541 * length_error is thrown. The value of the string doesn't
4542 * change if an error is thrown.
4543 */
4544 basic_string&
4545 insert(size_type __pos1, const basic_string& __str)
4546 { return this->insert(__pos1, __str, size_type(0), __str.size()); }
4547
4548 /**
4549 * @brief Insert a substring.
4550 * @param __pos1 Position in string to insert at.
4551 * @param __str The string to insert.
4552 * @param __pos2 Start of characters in str to insert.
4553 * @param __n Number of characters to insert.
4554 * @return Reference to this string.
4555 * @throw std::length_error If new length exceeds @c max_size().
4556 * @throw std::out_of_range If @a pos1 > size() or
4557 * @a __pos2 > @a str.size().
4558 *
4559 * Starting at @a pos1, insert @a __n character of @a __str
4560 * beginning with @a __pos2. If adding characters causes the
4561 * length to exceed max_size(), length_error is thrown. If @a
4562 * __pos1 is beyond the end of this string or @a __pos2 is
4563 * beyond the end of @a __str, out_of_range is thrown. The
4564 * value of the string doesn't change if an error is thrown.
4565 */
4566 basic_string&
4567 insert(size_type __pos1, const basic_string& __str,
4568 size_type __pos2, size_type __n = npos)
4569 { return this->insert(__pos1, __str._M_data()
4570 + __str._M_check(__pos2, "basic_string::insert"),
4571 __str._M_limit(__pos2, __n)); }
4572
4573 /**
4574 * @brief Insert a C substring.
4575 * @param __pos Position in string to insert at.
4576 * @param __s The C string to insert.
4577 * @param __n The number of characters to insert.
4578 * @return Reference to this string.
4579 * @throw std::length_error If new length exceeds @c max_size().
4580 * @throw std::out_of_range If @a __pos is beyond the end of this
4581 * string.
4582 *
4583 * Inserts the first @a __n characters of @a __s starting at @a
4584 * __pos. If adding characters causes the length to exceed
4585 * max_size(), length_error is thrown. If @a __pos is beyond
4586 * end(), out_of_range is thrown. The value of the string
4587 * doesn't change if an error is thrown.
4588 */
4589 basic_string&
4590 insert(size_type __pos, const _CharT* __s, size_type __n);
4591
4592 /**
4593 * @brief Insert a C string.
4594 * @param __pos Position in string to insert at.
4595 * @param __s The C string to insert.
4596 * @return Reference to this string.
4597 * @throw std::length_error If new length exceeds @c max_size().
4598 * @throw std::out_of_range If @a pos is beyond the end of this
4599 * string.
4600 *
4601 * Inserts the first @a n characters of @a __s starting at @a __pos. If
4602 * adding characters causes the length to exceed max_size(),
4603 * length_error is thrown. If @a __pos is beyond end(), out_of_range is
4604 * thrown. The value of the string doesn't change if an error is
4605 * thrown.
4606 */
4607 basic_string&
4608 insert(size_type __pos, const _CharT* __s)
4609 {
4610 __glibcxx_requires_string(__s);
4611 return this->insert(__pos, __s, traits_type::length(__s));
4612 }
4613
4614 /**
4615 * @brief Insert multiple characters.
4616 * @param __pos Index in string to insert at.
4617 * @param __n Number of characters to insert
4618 * @param __c The character to insert.
4619 * @return Reference to this string.
4620 * @throw std::length_error If new length exceeds @c max_size().
4621 * @throw std::out_of_range If @a __pos is beyond the end of this
4622 * string.
4623 *
4624 * Inserts @a __n copies of character @a __c starting at index
4625 * @a __pos. If adding characters causes the length to exceed
4626 * max_size(), length_error is thrown. If @a __pos > length(),
4627 * out_of_range is thrown. The value of the string doesn't
4628 * change if an error is thrown.
4629 */
4630 basic_string&
4631 insert(size_type __pos, size_type __n, _CharT __c)
4632 { return _M_replace_aux(_M_check(__pos, "basic_string::insert"),
4633 size_type(0), __n, __c); }
4634
4635 /**
4636 * @brief Insert one character.
4637 * @param __p Iterator referencing position in string to insert at.
4638 * @param __c The character to insert.
4639 * @return Iterator referencing newly inserted char.
4640 * @throw std::length_error If new length exceeds @c max_size().
4641 *
4642 * Inserts character @a __c at position referenced by @a __p.
4643 * If adding character causes the length to exceed max_size(),
4644 * length_error is thrown. If @a __p is beyond end of string,
4645 * out_of_range is thrown. The value of the string doesn't
4646 * change if an error is thrown.
4647 */
4648 iterator
4649 insert(iterator __p, _CharT __c)
4650 {
4651 _GLIBCXX_DEBUG_PEDASSERT(__p >= _M_ibegin() && __p <= _M_iend());
4652 const size_type __pos = __p - _M_ibegin();
4653 _M_replace_aux(__pos, size_type(0), size_type(1), __c);
4654 _M_rep()->_M_set_leaked();
4655 return iterator(_M_data() + __pos);
4656 }
4657
4658#if __cplusplus201703L >= 201703L
4659 /**
4660 * @brief Insert a string_view.
4661 * @param __pos Position in string to insert at.
4662 * @param __svt The object convertible to string_view to insert.
4663 * @return Reference to this string.
4664 */
4665 template<typename _Tp>
4666 _If_sv<_Tp, basic_string&>
4667 insert(size_type __pos, const _Tp& __svt)
4668 {
4669 __sv_type __sv = __svt;
4670 return this->insert(__pos, __sv.data(), __sv.size());
4671 }
4672
4673 /**
4674 * @brief Insert a string_view.
4675 * @param __pos Position in string to insert at.
4676 * @param __svt The object convertible to string_view to insert from.
4677 * @param __pos Position in string_view to insert
4678 * from.
4679 * @param __n The number of characters to insert.
4680 * @return Reference to this string.
4681 */
4682 template<typename _Tp>
4683 _If_sv<_Tp, basic_string&>
4684 insert(size_type __pos1, const _Tp& __svt,
4685 size_type __pos2, size_type __n = npos)
4686 {
4687 __sv_type __sv = __svt;
4688 return this->replace(__pos1, size_type(0), __sv.data()
4689 + std::__sv_check(__sv.size(), __pos2, "basic_string::insert"),
4690 std::__sv_limit(__sv.size(), __pos2, __n));
4691 }
4692#endif // C++17
4693
4694 /**
4695 * @brief Remove characters.
4696 * @param __pos Index of first character to remove (default 0).
4697 * @param __n Number of characters to remove (default remainder).
4698 * @return Reference to this string.
4699 * @throw std::out_of_range If @a pos is beyond the end of this
4700 * string.
4701 *
4702 * Removes @a __n characters from this string starting at @a
4703 * __pos. The length of the string is reduced by @a __n. If
4704 * there are < @a __n characters to remove, the remainder of
4705 * the string is truncated. If @a __p is beyond end of string,
4706 * out_of_range is thrown. The value of the string doesn't
4707 * change if an error is thrown.
4708 */
4709 basic_string&
4710 erase(size_type __pos = 0, size_type __n = npos)
4711 {
4712 _M_mutate(_M_check(__pos, "basic_string::erase"),
4713 _M_limit(__pos, __n), size_type(0));
4714 return *this;
4715 }
4716
4717 /**
4718 * @brief Remove one character.
4719 * @param __position Iterator referencing the character to remove.
4720 * @return iterator referencing same location after removal.
4721 *
4722 * Removes the character at @a __position from this string. The value
4723 * of the string doesn't change if an error is thrown.
4724 */
4725 iterator
4726 erase(iterator __position)
4727 {
4728 _GLIBCXX_DEBUG_PEDASSERT(__position >= _M_ibegin()
4729 && __position < _M_iend());
4730 const size_type __pos = __position - _M_ibegin();
4731 _M_mutate(__pos, size_type(1), size_type(0));
4732 _M_rep()->_M_set_leaked();
4733 return iterator(_M_data() + __pos);
4734 }
4735
4736 /**
4737 * @brief Remove a range of characters.
4738 * @param __first Iterator referencing the first character to remove.
4739 * @param __last Iterator referencing the end of the range.
4740 * @return Iterator referencing location of first after removal.
4741 *
4742 * Removes the characters in the range [first,last) from this string.
4743 * The value of the string doesn't change if an error is thrown.
4744 */
4745 iterator
4746 erase(iterator __first, iterator __last);
4747
4748#if __cplusplus201703L >= 201103L
4749 /**
4750 * @brief Remove the last character.
4751 *
4752 * The string must be non-empty.
4753 */
4754 void
4755 pop_back() // FIXME C++11: should be noexcept.
4756 {
4757 __glibcxx_assert(!empty())do { if (! (!empty())) std::__replacement_assert("/usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/basic_string.h"
, 4757, __PRETTY_FUNCTION__, "!empty()"); } while (false)
;
4758 erase(size() - 1, 1);
4759 }
4760#endif // C++11
4761
4762 /**
4763 * @brief Replace characters with value from another string.
4764 * @param __pos Index of first character to replace.
4765 * @param __n Number of characters to be replaced.
4766 * @param __str String to insert.
4767 * @return Reference to this string.
4768 * @throw std::out_of_range If @a pos is beyond the end of this
4769 * string.
4770 * @throw std::length_error If new length exceeds @c max_size().
4771 *
4772 * Removes the characters in the range [__pos,__pos+__n) from
4773 * this string. In place, the value of @a __str is inserted.
4774 * If @a __pos is beyond end of string, out_of_range is thrown.
4775 * If the length of the result exceeds max_size(), length_error
4776 * is thrown. The value of the string doesn't change if an
4777 * error is thrown.
4778 */
4779 basic_string&
4780 replace(size_type __pos, size_type __n, const basic_string& __str)
4781 { return this->replace(__pos, __n, __str._M_data(), __str.size()); }
4782
4783 /**
4784 * @brief Replace characters with value from another string.
4785 * @param __pos1 Index of first character to replace.
4786 * @param __n1 Number of characters to be replaced.
4787 * @param __str String to insert.
4788 * @param __pos2 Index of first character of str to use.
4789 * @param __n2 Number of characters from str to use.
4790 * @return Reference to this string.
4791 * @throw std::out_of_range If @a __pos1 > size() or @a __pos2 >
4792 * __str.size().
4793 * @throw std::length_error If new length exceeds @c max_size().
4794 *
4795 * Removes the characters in the range [__pos1,__pos1 + n) from this
4796 * string. In place, the value of @a __str is inserted. If @a __pos is
4797 * beyond end of string, out_of_range is thrown. If the length of the
4798 * result exceeds max_size(), length_error is thrown. The value of the
4799 * string doesn't change if an error is thrown.
4800 */
4801 basic_string&
4802 replace(size_type __pos1, size_type __n1, const basic_string& __str,
4803 size_type __pos2, size_type __n2 = npos)
4804 { return this->replace(__pos1, __n1, __str._M_data()
4805 + __str._M_check(__pos2, "basic_string::replace"),
4806 __str._M_limit(__pos2, __n2)); }
4807
4808 /**
4809 * @brief Replace characters with value of a C substring.
4810 * @param __pos Index of first character to replace.
4811 * @param __n1 Number of characters to be replaced.
4812 * @param __s C string to insert.
4813 * @param __n2 Number of characters from @a s to use.
4814 * @return Reference to this string.
4815 * @throw std::out_of_range If @a pos1 > size().
4816 * @throw std::length_error If new length exceeds @c max_size().
4817 *
4818 * Removes the characters in the range [__pos,__pos + __n1)
4819 * from this string. In place, the first @a __n2 characters of
4820 * @a __s are inserted, or all of @a __s if @a __n2 is too large. If
4821 * @a __pos is beyond end of string, out_of_range is thrown. If
4822 * the length of result exceeds max_size(), length_error is
4823 * thrown. The value of the string doesn't change if an error
4824 * is thrown.
4825 */
4826 basic_string&
4827 replace(size_type __pos, size_type __n1, const _CharT* __s,
4828 size_type __n2);
4829
4830 /**
4831 * @brief Replace characters with value of a C string.
4832 * @param __pos Index of first character to replace.
4833 * @param __n1 Number of characters to be replaced.
4834 * @param __s C string to insert.
4835 * @return Reference to this string.
4836 * @throw std::out_of_range If @a pos > size().
4837 * @throw std::length_error If new length exceeds @c max_size().
4838 *
4839 * Removes the characters in the range [__pos,__pos + __n1)
4840 * from this string. In place, the characters of @a __s are
4841 * inserted. If @a __pos is beyond end of string, out_of_range
4842 * is thrown. If the length of result exceeds max_size(),
4843 * length_error is thrown. The value of the string doesn't
4844 * change if an error is thrown.
4845 */
4846 basic_string&
4847 replace(size_type __pos, size_type __n1, const _CharT* __s)
4848 {
4849 __glibcxx_requires_string(__s);
4850 return this->replace(__pos, __n1, __s, traits_type::length(__s));
4851 }
4852
4853 /**
4854 * @brief Replace characters with multiple characters.
4855 * @param __pos Index of first character to replace.
4856 * @param __n1 Number of characters to be replaced.
4857 * @param __n2 Number of characters to insert.
4858 * @param __c Character to insert.
4859 * @return Reference to this string.
4860 * @throw std::out_of_range If @a __pos > size().
4861 * @throw std::length_error If new length exceeds @c max_size().
4862 *
4863 * Removes the characters in the range [pos,pos + n1) from this
4864 * string. In place, @a __n2 copies of @a __c are inserted.
4865 * If @a __pos is beyond end of string, out_of_range is thrown.
4866 * If the length of result exceeds max_size(), length_error is
4867 * thrown. The value of the string doesn't change if an error
4868 * is thrown.
4869 */
4870 basic_string&
4871 replace(size_type __pos, size_type __n1, size_type __n2, _CharT __c)
4872 { return _M_replace_aux(_M_check(__pos, "basic_string::replace"),
4873 _M_limit(__pos, __n1), __n2, __c); }
4874
4875 /**
4876 * @brief Replace range of characters with string.
4877 * @param __i1 Iterator referencing start of range to replace.
4878 * @param __i2 Iterator referencing end of range to replace.
4879 * @param __str String value to insert.
4880 * @return Reference to this string.
4881 * @throw std::length_error If new length exceeds @c max_size().
4882 *
4883 * Removes the characters in the range [__i1,__i2). In place,
4884 * the value of @a __str is inserted. If the length of result
4885 * exceeds max_size(), length_error is thrown. The value of
4886 * the string doesn't change if an error is thrown.
4887 */
4888 basic_string&
4889 replace(iterator __i1, iterator __i2, const basic_string& __str)
4890 { return this->replace(__i1, __i2, __str._M_data(), __str.size()); }
4891
4892 /**
4893 * @brief Replace range of characters with C substring.
4894 * @param __i1 Iterator referencing start of range to replace.
4895 * @param __i2 Iterator referencing end of range to replace.
4896 * @param __s C string value to insert.
4897 * @param __n Number of characters from s to insert.
4898 * @return Reference to this string.
4899 * @throw std::length_error If new length exceeds @c max_size().
4900 *
4901 * Removes the characters in the range [__i1,__i2). In place,
4902 * the first @a __n characters of @a __s are inserted. If the
4903 * length of result exceeds max_size(), length_error is thrown.
4904 * The value of the string doesn't change if an error is
4905 * thrown.
4906 */
4907 basic_string&
4908 replace(iterator __i1, iterator __i2, const _CharT* __s, size_type __n)
4909 {
4910 _GLIBCXX_DEBUG_PEDASSERT(_M_ibegin() <= __i1 && __i1 <= __i2
4911 && __i2 <= _M_iend());
4912 return this->replace(__i1 - _M_ibegin(), __i2 - __i1, __s, __n);
4913 }
4914
4915 /**
4916 * @brief Replace range of characters with C string.
4917 * @param __i1 Iterator referencing start of range to replace.
4918 * @param __i2 Iterator referencing end of range to replace.
4919 * @param __s C string value to insert.
4920 * @return Reference to this string.
4921 * @throw std::length_error If new length exceeds @c max_size().
4922 *
4923 * Removes the characters in the range [__i1,__i2). In place,
4924 * the characters of @a __s are inserted. If the length of
4925 * result exceeds max_size(), length_error is thrown. The
4926 * value of the string doesn't change if an error is thrown.
4927 */
4928 basic_string&
4929 replace(iterator __i1, iterator __i2, const _CharT* __s)
4930 {
4931 __glibcxx_requires_string(__s);
4932 return this->replace(__i1, __i2, __s, traits_type::length(__s));
4933 }
4934
4935 /**
4936 * @brief Replace range of characters with multiple characters
4937 * @param __i1 Iterator referencing start of range to replace.
4938 * @param __i2 Iterator referencing end of range to replace.
4939 * @param __n Number of characters to insert.
4940 * @param __c Character to insert.
4941 * @return Reference to this string.
4942 * @throw std::length_error If new length exceeds @c max_size().
4943 *
4944 * Removes the characters in the range [__i1,__i2). In place,
4945 * @a __n copies of @a __c are inserted. If the length of
4946 * result exceeds max_size(), length_error is thrown. The
4947 * value of the string doesn't change if an error is thrown.
4948 */
4949 basic_string&
4950 replace(iterator __i1, iterator __i2, size_type __n, _CharT __c)
4951 {
4952 _GLIBCXX_DEBUG_PEDASSERT(_M_ibegin() <= __i1 && __i1 <= __i2
4953 && __i2 <= _M_iend());
4954 return _M_replace_aux(__i1 - _M_ibegin(), __i2 - __i1, __n, __c);
4955 }
4956
4957 /**
4958 * @brief Replace range of characters with range.
4959 * @param __i1 Iterator referencing start of range to replace.
4960 * @param __i2 Iterator referencing end of range to replace.
4961 * @param __k1 Iterator referencing start of range to insert.
4962 * @param __k2 Iterator referencing end of range to insert.
4963 * @return Reference to this string.
4964 * @throw std::length_error If new length exceeds @c max_size().
4965 *
4966 * Removes the characters in the range [__i1,__i2). In place,
4967 * characters in the range [__k1,__k2) are inserted. If the
4968 * length of result exceeds max_size(), length_error is thrown.
4969 * The value of the string doesn't change if an error is
4970 * thrown.
4971 */
4972 template<class _InputIterator>
4973 basic_string&
4974 replace(iterator __i1, iterator __i2,
4975 _InputIterator __k1, _InputIterator __k2)
4976 {
4977 _GLIBCXX_DEBUG_PEDASSERT(_M_ibegin() <= __i1 && __i1 <= __i2
4978 && __i2 <= _M_iend());
4979 __glibcxx_requires_valid_range(__k1, __k2);
4980 typedef typename std::__is_integer<_InputIterator>::__type _Integral;
4981 return _M_replace_dispatch(__i1, __i2, __k1, __k2, _Integral());
4982 }
4983
4984 // Specializations for the common case of pointer and iterator:
4985 // useful to avoid the overhead of temporary buffering in _M_replace.
4986 basic_string&
4987 replace(iterator __i1, iterator __i2, _CharT* __k1, _CharT* __k2)
4988 {
4989 _GLIBCXX_DEBUG_PEDASSERT(_M_ibegin() <= __i1 && __i1 <= __i2
4990 && __i2 <= _M_iend());
4991 __glibcxx_requires_valid_range(__k1, __k2);
4992 return this->replace(__i1 - _M_ibegin(), __i2 - __i1,
4993 __k1, __k2 - __k1);
4994 }
4995
4996 basic_string&
4997 replace(iterator __i1, iterator __i2,
4998 const _CharT* __k1, const _CharT* __k2)
4999 {
5000 _GLIBCXX_DEBUG_PEDASSERT(_M_ibegin() <= __i1 && __i1 <= __i2
5001 && __i2 <= _M_iend());
5002 __glibcxx_requires_valid_range(__k1, __k2);
5003 return this->replace(__i1 - _M_ibegin(), __i2 - __i1,
5004 __k1, __k2 - __k1);
5005 }
5006
5007 basic_string&
5008 replace(iterator __i1, iterator __i2, iterator __k1, iterator __k2)
5009 {
5010 _GLIBCXX_DEBUG_PEDASSERT(_M_ibegin() <= __i1 && __i1 <= __i2
5011 && __i2 <= _M_iend());
5012 __glibcxx_requires_valid_range(__k1, __k2);
5013 return this->replace(__i1 - _M_ibegin(), __i2 - __i1,
5014 __k1.base(), __k2 - __k1);
5015 }
5016
5017 basic_string&
5018 replace(iterator __i1, iterator __i2,
5019 const_iterator __k1, const_iterator __k2)
5020 {
5021 _GLIBCXX_DEBUG_PEDASSERT(_M_ibegin() <= __i1 && __i1 <= __i2
5022 && __i2 <= _M_iend());
5023 __glibcxx_requires_valid_range(__k1, __k2);
5024 return this->replace(__i1 - _M_ibegin(), __i2 - __i1,
5025 __k1.base(), __k2 - __k1);
5026 }
5027
5028#if __cplusplus201703L >= 201103L
5029 /**
5030 * @brief Replace range of characters with initializer_list.
5031 * @param __i1 Iterator referencing start of range to replace.
5032 * @param __i2 Iterator referencing end of range to replace.
5033 * @param __l The initializer_list of characters to insert.
5034 * @return Reference to this string.
5035 * @throw std::length_error If new length exceeds @c max_size().
5036 *
5037 * Removes the characters in the range [__i1,__i2). In place,
5038 * characters in the range [__k1,__k2) are inserted. If the
5039 * length of result exceeds max_size(), length_error is thrown.
5040 * The value of the string doesn't change if an error is
5041 * thrown.
5042 */
5043 basic_string& replace(iterator __i1, iterator __i2,
5044 initializer_list<_CharT> __l)
5045 { return this->replace(__i1, __i2, __l.begin(), __l.end()); }
5046#endif // C++11
5047
5048#if __cplusplus201703L >= 201703L
5049 /**
5050 * @brief Replace range of characters with string_view.
5051 * @param __pos The position to replace at.
5052 * @param __n The number of characters to replace.
5053 * @param __svt The object convertible to string_view to insert.
5054 * @return Reference to this string.
5055 */
5056 template<typename _Tp>
5057 _If_sv<_Tp, basic_string&>
5058 replace(size_type __pos, size_type __n, const _Tp& __svt)
5059 {
5060 __sv_type __sv = __svt;
5061 return this->replace(__pos, __n, __sv.data(), __sv.size());
5062 }
5063
5064 /**
5065 * @brief Replace range of characters with string_view.
5066 * @param __pos1 The position to replace at.
5067 * @param __n1 The number of characters to replace.
5068 * @param __svt The object convertible to string_view to insert from.
5069 * @param __pos2 The position in the string_view to insert from.
5070 * @param __n2 The number of characters to insert.
5071 * @return Reference to this string.
5072 */
5073 template<typename _Tp>
5074 _If_sv<_Tp, basic_string&>
5075 replace(size_type __pos1, size_type __n1, const _Tp& __svt,
5076 size_type __pos2, size_type __n2 = npos)
5077 {
5078 __sv_type __sv = __svt;
5079 return this->replace(__pos1, __n1,
5080 __sv.data()
5081 + std::__sv_check(__sv.size(), __pos2, "basic_string::replace"),
5082 std::__sv_limit(__sv.size(), __pos2, __n2));
5083 }
5084
5085 /**
5086 * @brief Replace range of characters with string_view.
5087 * @param __i1 An iterator referencing the start position
5088 to replace at.
5089 * @param __i2 An iterator referencing the end position
5090 for the replace.
5091 * @param __svt The object convertible to string_view to insert from.
5092 * @return Reference to this string.
5093 */
5094 template<typename _Tp>
5095 _If_sv<_Tp, basic_string&>
5096 replace(const_iterator __i1, const_iterator __i2, const _Tp& __svt)
5097 {
5098 __sv_type __sv = __svt;
5099 return this->replace(__i1 - begin(), __i2 - __i1, __sv);
5100 }
5101#endif // C++17
5102
5103 private:
5104 template<class _Integer>
5105 basic_string&
5106 _M_replace_dispatch(iterator __i1, iterator __i2, _Integer __n,
5107 _Integer __val, __true_type)
5108 { return _M_replace_aux(__i1 - _M_ibegin(), __i2 - __i1, __n, __val); }
5109
5110 template<class _InputIterator>
5111 basic_string&
5112 _M_replace_dispatch(iterator __i1, iterator __i2, _InputIterator __k1,
5113 _InputIterator __k2, __false_type);
5114
5115 basic_string&
5116 _M_replace_aux(size_type __pos1, size_type __n1, size_type __n2,
5117 _CharT __c);
5118
5119 basic_string&
5120 _M_replace_safe(size_type __pos1, size_type __n1, const _CharT* __s,
5121 size_type __n2);
5122
5123 // _S_construct_aux is used to implement the 21.3.1 para 15 which
5124 // requires special behaviour if _InIter is an integral type
5125 template<class _InIterator>
5126 static _CharT*
5127 _S_construct_aux(_InIterator __beg, _InIterator __end,
5128 const _Alloc& __a, __false_type)
5129 {
5130 typedef typename iterator_traits<_InIterator>::iterator_category _Tag;
5131 return _S_construct(__beg, __end, __a, _Tag());
5132 }
5133
5134 // _GLIBCXX_RESOLVE_LIB_DEFECTS
5135 // 438. Ambiguity in the "do the right thing" clause
5136 template<class _Integer>
5137 static _CharT*
5138 _S_construct_aux(_Integer __beg, _Integer __end,
5139 const _Alloc& __a, __true_type)
5140 { return _S_construct_aux_2(static_cast<size_type>(__beg),
5141 __end, __a); }
5142
5143 static _CharT*
5144 _S_construct_aux_2(size_type __req, _CharT __c, const _Alloc& __a)
5145 { return _S_construct(__req, __c, __a); }
5146
5147 template<class _InIterator>
5148 static _CharT*
5149 _S_construct(_InIterator __beg, _InIterator __end, const _Alloc& __a)
5150 {
5151 typedef typename std::__is_integer<_InIterator>::__type _Integral;
5152 return _S_construct_aux(__beg, __end, __a, _Integral());
5153 }
5154
5155 // For Input Iterators, used in istreambuf_iterators, etc.
5156 template<class _InIterator>
5157 static _CharT*
5158 _S_construct(_InIterator __beg, _InIterator __end, const _Alloc& __a,
5159 input_iterator_tag);
5160
5161 // For forward_iterators up to random_access_iterators, used for
5162 // string::iterator, _CharT*, etc.
5163 template<class _FwdIterator>
5164 static _CharT*
5165 _S_construct(_FwdIterator __beg, _FwdIterator __end, const _Alloc& __a,
5166 forward_iterator_tag);
5167
5168 static _CharT*
5169 _S_construct(size_type __req, _CharT __c, const _Alloc& __a);
5170
5171 public:
5172
5173 /**
5174 * @brief Copy substring into C string.
5175 * @param __s C string to copy value into.
5176 * @param __n Number of characters to copy.
5177 * @param __pos Index of first character to copy.
5178 * @return Number of characters actually copied
5179 * @throw std::out_of_range If __pos > size().
5180 *
5181 * Copies up to @a __n characters starting at @a __pos into the
5182 * C string @a __s. If @a __pos is %greater than size(),
5183 * out_of_range is thrown.
5184 */
5185 size_type
5186 copy(_CharT* __s, size_type __n, size_type __pos = 0) const;
5187
5188 /**
5189 * @brief Swap contents with another string.
5190 * @param __s String to swap with.
5191 *
5192 * Exchanges the contents of this string with that of @a __s in constant
5193 * time.
5194 */
5195 void
5196 swap(basic_string& __s)
5197 _GLIBCXX_NOEXCEPT_IF(allocator_traits<_Alloc>::is_always_equal::value)noexcept(allocator_traits<_Alloc>::is_always_equal::value
)
;
5198
5199 // String operations:
5200 /**
5201 * @brief Return const pointer to null-terminated contents.
5202 *
5203 * This is a handle to internal data. Do not modify or dire things may
5204 * happen.
5205 */
5206 const _CharT*
5207 c_str() const _GLIBCXX_NOEXCEPTnoexcept
5208 { return _M_data(); }
5209
5210 /**
5211 * @brief Return const pointer to contents.
5212 *
5213 * This is a pointer to internal data. It is undefined to modify
5214 * the contents through the returned pointer. To get a pointer that
5215 * allows modifying the contents use @c &str[0] instead,
5216 * (or in C++17 the non-const @c str.data() overload).
5217 */
5218 const _CharT*
5219 data() const _GLIBCXX_NOEXCEPTnoexcept
5220 { return _M_data(); }
5221
5222#if __cplusplus201703L >= 201703L
5223 /**
5224 * @brief Return non-const pointer to contents.
5225 *
5226 * This is a pointer to the character sequence held by the string.
5227 * Modifying the characters in the sequence is allowed.
5228 */
5229 _CharT*
5230 data() noexcept
5231 {
5232 _M_leak();
5233 return _M_data();
5234 }
5235#endif
5236
5237 /**
5238 * @brief Return copy of allocator used to construct this string.
5239 */
5240 allocator_type
5241 get_allocator() const _GLIBCXX_NOEXCEPTnoexcept
5242 { return _M_dataplus; }
5243
5244 /**
5245 * @brief Find position of a C substring.
5246 * @param __s C string to locate.
5247 * @param __pos Index of character to search from.
5248 * @param __n Number of characters from @a s to search for.
5249 * @return Index of start of first occurrence.
5250 *
5251 * Starting from @a __pos, searches forward for the first @a
5252 * __n characters in @a __s within this string. If found,
5253 * returns the index where it begins. If not found, returns
5254 * npos.
5255 */
5256 size_type
5257 find(const _CharT* __s, size_type __pos, size_type __n) const
5258 _GLIBCXX_NOEXCEPTnoexcept;
5259
5260 /**
5261 * @brief Find position of a string.
5262 * @param __str String to locate.
5263 * @param __pos Index of character to search from (default 0).
5264 * @return Index of start of first occurrence.
5265 *
5266 * Starting from @a __pos, searches forward for value of @a __str within
5267 * this string. If found, returns the index where it begins. If not
5268 * found, returns npos.
5269 */
5270 size_type
5271 find(const basic_string& __str, size_type __pos = 0) const
5272 _GLIBCXX_NOEXCEPTnoexcept
5273 { return this->find(__str.data(), __pos, __str.size()); }
5274
5275 /**
5276 * @brief Find position of a C string.
5277 * @param __s C string to locate.
5278 * @param __pos Index of character to search from (default 0).
5279 * @return Index of start of first occurrence.
5280 *
5281 * Starting from @a __pos, searches forward for the value of @a
5282 * __s within this string. If found, returns the index where
5283 * it begins. If not found, returns npos.
5284 */
5285 size_type
5286 find(const _CharT* __s, size_type __pos = 0) const _GLIBCXX_NOEXCEPTnoexcept
5287 {
5288 __glibcxx_requires_string(__s);
5289 return this->find(__s, __pos, traits_type::length(__s));
5290 }
5291
5292 /**
5293 * @brief Find position of a character.
5294 * @param __c Character to locate.
5295 * @param __pos Index of character to search from (default 0).
5296 * @return Index of first occurrence.
5297 *
5298 * Starting from @a __pos, searches forward for @a __c within
5299 * this string. If found, returns the index where it was
5300 * found. If not found, returns npos.
5301 */
5302 size_type
5303 find(_CharT __c, size_type __pos = 0) const _GLIBCXX_NOEXCEPTnoexcept;
5304
5305#if __cplusplus201703L >= 201703L
5306 /**
5307 * @brief Find position of a string_view.
5308 * @param __svt The object convertible to string_view to locate.
5309 * @param __pos Index of character to search from (default 0).
5310 * @return Index of start of first occurrence.
5311 */
5312 template<typename _Tp>
5313 _If_sv<_Tp, size_type>
5314 find(const _Tp& __svt, size_type __pos = 0) const
5315 noexcept(is_same<_Tp, __sv_type>::value)
5316 {
5317 __sv_type __sv = __svt;
5318 return this->find(__sv.data(), __pos, __sv.size());
5319 }
5320#endif // C++17
5321
5322 /**
5323 * @brief Find last position of a string.
5324 * @param __str String to locate.
5325 * @param __pos Index of character to search back from (default end).
5326 * @return Index of start of last occurrence.
5327 *
5328 * Starting from @a __pos, searches backward for value of @a
5329 * __str within this string. If found, returns the index where
5330 * it begins. If not found, returns npos.
5331 */
5332 size_type
5333 rfind(const basic_string& __str, size_type __pos = npos) const
5334 _GLIBCXX_NOEXCEPTnoexcept
5335 { return this->rfind(__str.data(), __pos, __str.size()); }
5336
5337 /**
5338 * @brief Find last position of a C substring.
5339 * @param __s C string to locate.
5340 * @param __pos Index of character to search back from.
5341 * @param __n Number of characters from s to search for.
5342 * @return Index of start of last occurrence.
5343 *
5344 * Starting from @a __pos, searches backward for the first @a
5345 * __n characters in @a __s within this string. If found,
5346 * returns the index where it begins. If not found, returns
5347 * npos.
5348 */
5349 size_type
5350 rfind(const _CharT* __s, size_type __pos, size_type __n) const
5351 _GLIBCXX_NOEXCEPTnoexcept;
5352
5353 /**
5354 * @brief Find last position of a C string.
5355 * @param __s C string to locate.
5356 * @param __pos Index of character to start search at (default end).
5357 * @return Index of start of last occurrence.
5358 *
5359 * Starting from @a __pos, searches backward for the value of
5360 * @a __s within this string. If found, returns the index
5361 * where it begins. If not found, returns npos.
5362 */
5363 size_type
5364 rfind(const _CharT* __s, size_type __pos = npos) const _GLIBCXX_NOEXCEPTnoexcept
5365 {
5366 __glibcxx_requires_string(__s);
5367 return this->rfind(__s, __pos, traits_type::length(__s));
5368 }
5369
5370 /**
5371 * @brief Find last position of a character.
5372 * @param __c Character to locate.
5373 * @param __pos Index of character to search back from (default end).
5374 * @return Index of last occurrence.
5375 *
5376 * Starting from @a __pos, searches backward for @a __c within
5377 * this string. If found, returns the index where it was
5378 * found. If not found, returns npos.
5379 */
5380 size_type
5381 rfind(_CharT __c, size_type __pos = npos) const _GLIBCXX_NOEXCEPTnoexcept;
5382
5383#if __cplusplus201703L >= 201703L
5384 /**
5385 * @brief Find last position of a string_view.
5386 * @param __svt The object convertible to string_view to locate.
5387 * @param __pos Index of character to search back from (default end).
5388 * @return Index of start of last occurrence.
5389 */
5390 template<typename _Tp>
5391 _If_sv<_Tp, size_type>
5392 rfind(const _Tp& __svt, size_type __pos = npos) const
5393 noexcept(is_same<_Tp, __sv_type>::value)
5394 {
5395 __sv_type __sv = __svt;
5396 return this->rfind(__sv.data(), __pos, __sv.size());
5397 }
5398#endif // C++17
5399
5400 /**
5401 * @brief Find position of a character of string.
5402 * @param __str String containing characters to locate.
5403 * @param __pos Index of character to search from (default 0).
5404 * @return Index of first occurrence.
5405 *
5406 * Starting from @a __pos, searches forward for one of the
5407 * characters of @a __str within this string. If found,
5408 * returns the index where it was found. If not found, returns
5409 * npos.
5410 */
5411 size_type
5412 find_first_of(const basic_string& __str, size_type __pos = 0) const
5413 _GLIBCXX_NOEXCEPTnoexcept
5414 { return this->find_first_of(__str.data(), __pos, __str.size()); }
5415
5416 /**
5417 * @brief Find position of a character of C substring.
5418 * @param __s String containing characters to locate.
5419 * @param __pos Index of character to search from.
5420 * @param __n Number of characters from s to search for.
5421 * @return Index of first occurrence.
5422 *
5423 * Starting from @a __pos, searches forward for one of the
5424 * first @a __n characters of @a __s within this string. If
5425 * found, returns the index where it was found. If not found,
5426 * returns npos.
5427 */
5428 size_type
5429 find_first_of(const _CharT* __s, size_type __pos, size_type __n) const
5430 _GLIBCXX_NOEXCEPTnoexcept;
5431
5432 /**
5433 * @brief Find position of a character of C string.
5434 * @param __s String containing characters to locate.
5435 * @param __pos Index of character to search from (default 0).
5436 * @return Index of first occurrence.
5437 *
5438 * Starting from @a __pos, searches forward for one of the
5439 * characters of @a __s within this string. If found, returns
5440 * the index where it was found. If not found, returns npos.
5441 */
5442 size_type
5443 find_first_of(const _CharT* __s, size_type __pos = 0) const
5444 _GLIBCXX_NOEXCEPTnoexcept
5445 {
5446 __glibcxx_requires_string(__s);
5447 return this->find_first_of(__s, __pos, traits_type::length(__s));
5448 }
5449
5450 /**
5451 * @brief Find position of a character.
5452 * @param __c Character to locate.
5453 * @param __pos Index of character to search from (default 0).
5454 * @return Index of first occurrence.
5455 *
5456 * Starting from @a __pos, searches forward for the character
5457 * @a __c within this string. If found, returns the index
5458 * where it was found. If not found, returns npos.
5459 *
5460 * Note: equivalent to find(__c, __pos).
5461 */
5462 size_type
5463 find_first_of(_CharT __c, size_type __pos = 0) const _GLIBCXX_NOEXCEPTnoexcept
5464 { return this->find(__c, __pos); }
5465
5466#if __cplusplus201703L >= 201703L
5467 /**
5468 * @brief Find position of a character of a string_view.
5469 * @param __svt An object convertible to string_view containing
5470 * characters to locate.
5471 * @param __pos Index of character to search from (default 0).
5472 * @return Index of first occurrence.
5473 */
5474 template<typename _Tp>
5475 _If_sv<_Tp, size_type>
5476 find_first_of(const _Tp& __svt, size_type __pos = 0) const
5477 noexcept(is_same<_Tp, __sv_type>::value)
5478 {
5479 __sv_type __sv = __svt;
5480 return this->find_first_of(__sv.data(), __pos, __sv.size());
5481 }
5482#endif // C++17
5483
5484 /**
5485 * @brief Find last position of a character of string.
5486 * @param __str String containing characters to locate.
5487 * @param __pos Index of character to search back from (default end).
5488 * @return Index of last occurrence.
5489 *
5490 * Starting from @a __pos, searches backward for one of the
5491 * characters of @a __str within this string. If found,
5492 * returns the index where it was found. If not found, returns
5493 * npos.
5494 */
5495 size_type
5496 find_last_of(const basic_string& __str, size_type __pos = npos) const
5497 _GLIBCXX_NOEXCEPTnoexcept
5498 { return this->find_last_of(__str.data(), __pos, __str.size()); }
5499
5500 /**
5501 * @brief Find last position of a character of C substring.
5502 * @param __s C string containing characters to locate.
5503 * @param __pos Index of character to search back from.
5504 * @param __n Number of characters from s to search for.
5505 * @return Index of last occurrence.
5506 *
5507 * Starting from @a __pos, searches backward for one of the
5508 * first @a __n characters of @a __s within this string. If
5509 * found, returns the index where it was found. If not found,
5510 * returns npos.
5511 */
5512 size_type
5513 find_last_of(const _CharT* __s, size_type __pos, size_type __n) const
5514 _GLIBCXX_NOEXCEPTnoexcept;
5515
5516 /**
5517 * @brief Find last position of a character of C string.
5518 * @param __s C string containing characters to locate.
5519 * @param __pos Index of character to search back from (default end).
5520 * @return Index of last occurrence.
5521 *
5522 * Starting from @a __pos, searches backward for one of the
5523 * characters of @a __s within this string. If found, returns
5524 * the index where it was found. If not found, returns npos.
5525 */
5526 size_type
5527 find_last_of(const _CharT* __s, size_type __pos = npos) const
5528 _GLIBCXX_NOEXCEPTnoexcept
5529 {
5530 __glibcxx_requires_string(__s);
5531 return this->find_last_of(__s, __pos, traits_type::length(__s));
5532 }
5533
5534 /**
5535 * @brief Find last position of a character.
5536 * @param __c Character to locate.
5537 * @param __pos Index of character to search back from (default end).
5538 * @return Index of last occurrence.
5539 *
5540 * Starting from @a __pos, searches backward for @a __c within
5541 * this string. If found, returns the index where it was
5542 * found. If not found, returns npos.
5543 *
5544 * Note: equivalent to rfind(__c, __pos).
5545 */
5546 size_type
5547 find_last_of(_CharT __c, size_type __pos = npos) const _GLIBCXX_NOEXCEPTnoexcept
5548 { return this->rfind(__c, __pos); }
5549
5550#if __cplusplus201703L >= 201703L
5551 /**
5552 * @brief Find last position of a character of string.
5553 * @param __svt An object convertible to string_view containing
5554 * characters to locate.
5555 * @param __pos Index of character to search back from (default end).
5556 * @return Index of last occurrence.
5557 */
5558 template<typename _Tp>
5559 _If_sv<_Tp, size_type>
5560 find_last_of(const _Tp& __svt, size_type __pos = npos) const
5561 noexcept(is_same<_Tp, __sv_type>::value)
5562 {
5563 __sv_type __sv = __svt;
5564 return this->find_last_of(__sv.data(), __pos, __sv.size());
5565 }
5566#endif // C++17
5567
5568 /**
5569 * @brief Find position of a character not in string.
5570 * @param __str String containing characters to avoid.
5571 * @param __pos Index of character to search from (default 0).
5572 * @return Index of first occurrence.
5573 *
5574 * Starting from @a __pos, searches forward for a character not contained
5575 * in @a __str within this string. If found, returns the index where it
5576 * was found. If not found, returns npos.
5577 */
5578 size_type
5579 find_first_not_of(const basic_string& __str, size_type __pos = 0) const
5580 _GLIBCXX_NOEXCEPTnoexcept
5581 { return this->find_first_not_of(__str.data(), __pos, __str.size()); }
5582
5583 /**
5584 * @brief Find position of a character not in C substring.
5585 * @param __s C string containing characters to avoid.
5586 * @param __pos Index of character to search from.
5587 * @param __n Number of characters from __s to consider.
5588 * @return Index of first occurrence.
5589 *
5590 * Starting from @a __pos, searches forward for a character not
5591 * contained in the first @a __n characters of @a __s within
5592 * this string. If found, returns the index where it was
5593 * found. If not found, returns npos.
5594 */
5595 size_type
5596 find_first_not_of(const _CharT* __s, size_type __pos,
5597 size_type __n) const _GLIBCXX_NOEXCEPTnoexcept;
5598
5599 /**
5600 * @brief Find position of a character not in C string.
5601 * @param __s C string containing characters to avoid.
5602 * @param __pos Index of character to search from (default 0).
5603 * @return Index of first occurrence.
5604 *
5605 * Starting from @a __pos, searches forward for a character not
5606 * contained in @a __s within this string. If found, returns
5607 * the index where it was found. If not found, returns npos.
5608 */
5609 size_type
5610 find_first_not_of(const _CharT* __s, size_type __pos = 0) const
5611 _GLIBCXX_NOEXCEPTnoexcept
5612 {
5613 __glibcxx_requires_string(__s);
5614 return this->find_first_not_of(__s, __pos, traits_type::length(__s));
5615 }
5616
5617 /**
5618 * @brief Find position of a different character.
5619 * @param __c Character to avoid.
5620 * @param __pos Index of character to search from (default 0).
5621 * @return Index of first occurrence.
5622 *
5623 * Starting from @a __pos, searches forward for a character
5624 * other than @a __c within this string. If found, returns the
5625 * index where it was found. If not found, returns npos.
5626 */
5627 size_type
5628 find_first_not_of(_CharT __c, size_type __pos = 0) const
5629 _GLIBCXX_NOEXCEPTnoexcept;
5630
5631#if __cplusplus201703L >= 201703L
5632 /**
5633 * @brief Find position of a character not in a string_view.
5634 * @param __svt An object convertible to string_view containing
5635 * characters to avoid.
5636 * @param __pos Index of character to search from (default 0).
5637 * @return Index of first occurrence.
5638 */
5639 template<typename _Tp>
5640 _If_sv<_Tp, size_type>
5641 find_first_not_of(const _Tp& __svt, size_type __pos = 0) const
5642 noexcept(is_same<_Tp, __sv_type>::value)
5643 {
5644 __sv_type __sv = __svt;
5645 return this->find_first_not_of(__sv.data(), __pos, __sv.size());
5646 }
5647#endif // C++17
5648
5649 /**
5650 * @brief Find last position of a character not in string.
5651 * @param __str String containing characters to avoid.
5652 * @param __pos Index of character to search back from (default end).
5653 * @return Index of last occurrence.
5654 *
5655 * Starting from @a __pos, searches backward for a character
5656 * not contained in @a __str within this string. If found,
5657 * returns the index where it was found. If not found, returns
5658 * npos.
5659 */
5660 size_type
5661 find_last_not_of(const basic_string& __str, size_type __pos = npos) const
5662 _GLIBCXX_NOEXCEPTnoexcept
5663 { return this->find_last_not_of(__str.data(), __pos, __str.size()); }
5664
5665 /**
5666 * @brief Find last position of a character not in C substring.
5667 * @param __s C string containing characters to avoid.
5668 * @param __pos Index of character to search back from.
5669 * @param __n Number of characters from s to consider.
5670 * @return Index of last occurrence.
5671 *
5672 * Starting from @a __pos, searches backward for a character not
5673 * contained in the first @a __n characters of @a __s within this string.
5674 * If found, returns the index where it was found. If not found,
5675 * returns npos.
5676 */
5677 size_type
5678 find_last_not_of(const _CharT* __s, size_type __pos,
5679 size_type __n) const _GLIBCXX_NOEXCEPTnoexcept;
5680 /**
5681 * @brief Find last position of a character not in C string.
5682 * @param __s C string containing characters to avoid.
5683 * @param __pos Index of character to search back from (default end).
5684 * @return Index of last occurrence.
5685 *
5686 * Starting from @a __pos, searches backward for a character
5687 * not contained in @a __s within this string. If found,
5688 * returns the index where it was found. If not found, returns
5689 * npos.
5690 */
5691 size_type
5692 find_last_not_of(const _CharT* __s, size_type __pos = npos) const
5693 _GLIBCXX_NOEXCEPTnoexcept
5694 {
5695 __glibcxx_requires_string(__s);
5696 return this->find_last_not_of(__s, __pos, traits_type::length(__s));
5697 }
5698
5699 /**
5700 * @brief Find last position of a different character.
5701 * @param __c Character to avoid.
5702 * @param __pos Index of character to search back from (default end).
5703 * @return Index of last occurrence.
5704 *
5705 * Starting from @a __pos, searches backward for a character other than
5706 * @a __c within this string. If found, returns the index where it was
5707 * found. If not found, returns npos.
5708 */
5709 size_type
5710 find_last_not_of(_CharT __c, size_type __pos = npos) const
5711 _GLIBCXX_NOEXCEPTnoexcept;
5712
5713#if __cplusplus201703L >= 201703L
5714 /**
5715 * @brief Find last position of a character not in a string_view.
5716 * @param __svt An object convertible to string_view containing
5717 * characters to avoid.
5718 * @param __pos Index of character to search back from (default end).
5719 * @return Index of last occurrence.
5720 */
5721 template<typename _Tp>
5722 _If_sv<_Tp, size_type>
5723 find_last_not_of(const _Tp& __svt, size_type __pos = npos) const
5724 noexcept(is_same<_Tp, __sv_type>::value)
5725 {
5726 __sv_type __sv = __svt;
5727 return this->find_last_not_of(__sv.data(), __pos, __sv.size());
5728 }
5729#endif // C++17
5730
5731 /**
5732 * @brief Get a substring.
5733 * @param __pos Index of first character (default 0).
5734 * @param __n Number of characters in substring (default remainder).
5735 * @return The new string.
5736 * @throw std::out_of_range If __pos > size().
5737 *
5738 * Construct and return a new string using the @a __n
5739 * characters starting at @a __pos. If the string is too
5740 * short, use the remainder of the characters. If @a __pos is
5741 * beyond the end of the string, out_of_range is thrown.
5742 */
5743 basic_string
5744 substr(size_type __pos = 0, size_type __n = npos) const
5745 { return basic_string(*this,
5746 _M_check(__pos, "basic_string::substr"), __n); }
5747
5748 /**
5749 * @brief Compare to a string.
5750 * @param __str String to compare against.
5751 * @return Integer < 0, 0, or > 0.
5752 *
5753 * Returns an integer < 0 if this string is ordered before @a
5754 * __str, 0 if their values are equivalent, or > 0 if this
5755 * string is ordered after @a __str. Determines the effective
5756 * length rlen of the strings to compare as the smallest of
5757 * size() and str.size(). The function then compares the two
5758 * strings by calling traits::compare(data(), str.data(),rlen).
5759 * If the result of the comparison is nonzero returns it,
5760 * otherwise the shorter one is ordered first.
5761 */
5762 int
5763 compare(const basic_string& __str) const
5764 {
5765 const size_type __size = this->size();
5766 const size_type __osize = __str.size();
5767 const size_type __len = std::min(__size, __osize);
5768
5769 int __r = traits_type::compare(_M_data(), __str.data(), __len);
5770 if (!__r)
5771 __r = _S_compare(__size, __osize);
5772 return __r;
5773 }
5774
5775#if __cplusplus201703L >= 201703L
5776 /**
5777 * @brief Compare to a string_view.
5778 * @param __svt An object convertible to string_view to compare against.
5779 * @return Integer < 0, 0, or > 0.
5780 */
5781 template<typename _Tp>
5782 _If_sv<_Tp, int>
5783 compare(const _Tp& __svt) const
5784 noexcept(is_same<_Tp, __sv_type>::value)
5785 {
5786 __sv_type __sv = __svt;
5787 const size_type __size = this->size();
5788 const size_type __osize = __sv.size();
5789 const size_type __len = std::min(__size, __osize);
5790
5791 int __r = traits_type::compare(_M_data(), __sv.data(), __len);
5792 if (!__r)
5793 __r = _S_compare(__size, __osize);
5794 return __r;
5795 }
5796
5797 /**
5798 * @brief Compare to a string_view.
5799 * @param __pos A position in the string to start comparing from.
5800 * @param __n The number of characters to compare.
5801 * @param __svt An object convertible to string_view to compare
5802 * against.
5803 * @return Integer < 0, 0, or > 0.
5804 */
5805 template<typename _Tp>
5806 _If_sv<_Tp, int>
5807 compare(size_type __pos, size_type __n, const _Tp& __svt) const
5808 noexcept(is_same<_Tp, __sv_type>::value)
5809 {
5810 __sv_type __sv = __svt;
5811 return __sv_type(*this).substr(__pos, __n).compare(__sv);
5812 }
5813
5814 /**
5815 * @brief Compare to a string_view.
5816 * @param __pos1 A position in the string to start comparing from.
5817 * @param __n1 The number of characters to compare.
5818 * @param __svt An object convertible to string_view to compare
5819 * against.
5820 * @param __pos2 A position in the string_view to start comparing from.
5821 * @param __n2 The number of characters to compare.
5822 * @return Integer < 0, 0, or > 0.
5823 */
5824 template<typename _Tp>
5825 _If_sv<_Tp, int>
5826 compare(size_type __pos1, size_type __n1, const _Tp& __svt,
5827 size_type __pos2, size_type __n2 = npos) const
5828 noexcept(is_same<_Tp, __sv_type>::value)
5829 {
5830 __sv_type __sv = __svt;
5831 return __sv_type(*this)
5832 .substr(__pos1, __n1).compare(__sv.substr(__pos2, __n2));
5833 }
5834#endif // C++17
5835
5836 /**
5837 * @brief Compare substring to a string.
5838 * @param __pos Index of first character of substring.
5839 * @param __n Number of characters in substring.
5840 * @param __str String to compare against.
5841 * @return Integer < 0, 0, or > 0.
5842 *
5843 * Form the substring of this string from the @a __n characters
5844 * starting at @a __pos. Returns an integer < 0 if the
5845 * substring is ordered before @a __str, 0 if their values are
5846 * equivalent, or > 0 if the substring is ordered after @a
5847 * __str. Determines the effective length rlen of the strings
5848 * to compare as the smallest of the length of the substring
5849 * and @a __str.size(). The function then compares the two
5850 * strings by calling
5851 * traits::compare(substring.data(),str.data(),rlen). If the
5852 * result of the comparison is nonzero returns it, otherwise
5853 * the shorter one is ordered first.
5854 */
5855 int
5856 compare(size_type __pos, size_type __n, const basic_string& __str) const;
5857
5858 /**
5859 * @brief Compare substring to a substring.
5860 * @param __pos1 Index of first character of substring.
5861 * @param __n1 Number of characters in substring.
5862 * @param __str String to compare against.
5863 * @param __pos2 Index of first character of substring of str.
5864 * @param __n2 Number of characters in substring of str.
5865 * @return Integer < 0, 0, or > 0.
5866 *
5867 * Form the substring of this string from the @a __n1
5868 * characters starting at @a __pos1. Form the substring of @a
5869 * __str from the @a __n2 characters starting at @a __pos2.
5870 * Returns an integer < 0 if this substring is ordered before
5871 * the substring of @a __str, 0 if their values are equivalent,
5872 * or > 0 if this substring is ordered after the substring of
5873 * @a __str. Determines the effective length rlen of the
5874 * strings to compare as the smallest of the lengths of the
5875 * substrings. The function then compares the two strings by
5876 * calling
5877 * traits::compare(substring.data(),str.substr(pos2,n2).data(),rlen).
5878 * If the result of the comparison is nonzero returns it,
5879 * otherwise the shorter one is ordered first.
5880 */
5881 int
5882 compare(size_type __pos1, size_type __n1, const basic_string& __str,
5883 size_type __pos2, size_type __n2 = npos) const;
5884
5885 /**
5886 * @brief Compare to a C string.
5887 * @param __s C string to compare against.
5888 * @return Integer < 0, 0, or > 0.
5889 *
5890 * Returns an integer < 0 if this string is ordered before @a __s, 0 if
5891 * their values are equivalent, or > 0 if this string is ordered after
5892 * @a __s. Determines the effective length rlen of the strings to
5893 * compare as the smallest of size() and the length of a string
5894 * constructed from @a __s. The function then compares the two strings
5895 * by calling traits::compare(data(),s,rlen). If the result of the
5896 * comparison is nonzero returns it, otherwise the shorter one is
5897 * ordered first.
5898 */
5899 int
5900 compare(const _CharT* __s) const _GLIBCXX_NOEXCEPTnoexcept;
5901
5902 // _GLIBCXX_RESOLVE_LIB_DEFECTS
5903 // 5 String::compare specification questionable
5904 /**
5905 * @brief Compare substring to a C string.
5906 * @param __pos Index of first character of substring.
5907 * @param __n1 Number of characters in substring.
5908 * @param __s C string to compare against.
5909 * @return Integer < 0, 0, or > 0.
5910 *
5911 * Form the substring of this string from the @a __n1
5912 * characters starting at @a pos. Returns an integer < 0 if
5913 * the substring is ordered before @a __s, 0 if their values
5914 * are equivalent, or > 0 if the substring is ordered after @a
5915 * __s. Determines the effective length rlen of the strings to
5916 * compare as the smallest of the length of the substring and
5917 * the length of a string constructed from @a __s. The
5918 * function then compares the two string by calling
5919 * traits::compare(substring.data(),__s,rlen). If the result of
5920 * the comparison is nonzero returns it, otherwise the shorter
5921 * one is ordered first.
5922 */
5923 int
5924 compare(size_type __pos, size_type __n1, const _CharT* __s) const;
5925
5926 /**
5927 * @brief Compare substring against a character %array.
5928 * @param __pos Index of first character of substring.
5929 * @param __n1 Number of characters in substring.
5930 * @param __s character %array to compare against.
5931 * @param __n2 Number of characters of s.
5932 * @return Integer < 0, 0, or > 0.
5933 *
5934 * Form the substring of this string from the @a __n1
5935 * characters starting at @a __pos. Form a string from the
5936 * first @a __n2 characters of @a __s. Returns an integer < 0
5937 * if this substring is ordered before the string from @a __s,
5938 * 0 if their values are equivalent, or > 0 if this substring
5939 * is ordered after the string from @a __s. Determines the
5940 * effective length rlen of the strings to compare as the
5941 * smallest of the length of the substring and @a __n2. The
5942 * function then compares the two strings by calling
5943 * traits::compare(substring.data(),s,rlen). If the result of
5944 * the comparison is nonzero returns it, otherwise the shorter
5945 * one is ordered first.
5946 *
5947 * NB: s must have at least n2 characters, &apos;\\0&apos; has
5948 * no special meaning.
5949 */
5950 int
5951 compare(size_type __pos, size_type __n1, const _CharT* __s,
5952 size_type __n2) const;
5953
5954#if __cplusplus201703L > 201703L
5955 bool
5956 starts_with(basic_string_view<_CharT, _Traits> __x) const noexcept
5957 { return __sv_type(this->data(), this->size()).starts_with(__x); }
5958
5959 bool
5960 starts_with(_CharT __x) const noexcept
5961 { return __sv_type(this->data(), this->size()).starts_with(__x); }
5962
5963 bool
5964 starts_with(const _CharT* __x) const noexcept
5965 { return __sv_type(this->data(), this->size()).starts_with(__x); }
5966
5967 bool
5968 ends_with(basic_string_view<_CharT, _Traits> __x) const noexcept
5969 { return __sv_type(this->data(), this->size()).ends_with(__x); }
5970
5971 bool
5972 ends_with(_CharT __x) const noexcept
5973 { return __sv_type(this->data(), this->size()).ends_with(__x); }
5974
5975 bool
5976 ends_with(const _CharT* __x) const noexcept
5977 { return __sv_type(this->data(), this->size()).ends_with(__x); }
5978#endif // C++20
5979
5980# ifdef _GLIBCXX_TM_TS_INTERNAL
5981 friend void
5982 ::_txnal_cow_string_C1_for_exceptions(void* that, const char* s,
5983 void* exc);
5984 friend const char*
5985 ::_txnal_cow_string_c_str(const void *that);
5986 friend void
5987 ::_txnal_cow_string_D1(void *that);
5988 friend void
5989 ::_txnal_cow_string_D1_commit(void *that);
5990# endif
5991 };
5992#endif // !_GLIBCXX_USE_CXX11_ABI
5993
5994#if __cpp_deduction_guides201703L >= 201606
5995_GLIBCXX_BEGIN_NAMESPACE_CXX11namespace __cxx11 {
5996 template<typename _InputIterator, typename _CharT
5997 = typename iterator_traits<_InputIterator>::value_type,
5998 typename _Allocator = allocator<_CharT>,
5999 typename = _RequireInputIter<_InputIterator>,
6000 typename = _RequireAllocator<_Allocator>>
6001 basic_string(_InputIterator, _InputIterator, _Allocator = _Allocator())
6002 -> basic_string<_CharT, char_traits<_CharT>, _Allocator>;
6003
6004 // _GLIBCXX_RESOLVE_LIB_DEFECTS
6005 // 3075. basic_string needs deduction guides from basic_string_view
6006 template<typename _CharT, typename _Traits,
6007 typename _Allocator = allocator<_CharT>,
6008 typename = _RequireAllocator<_Allocator>>
6009 basic_string(basic_string_view<_CharT, _Traits>, const _Allocator& = _Allocator())
6010 -> basic_string<_CharT, _Traits, _Allocator>;
6011
6012 template<typename _CharT, typename _Traits,
6013 typename _Allocator = allocator<_CharT>,
6014 typename = _RequireAllocator<_Allocator>>
6015 basic_string(basic_string_view<_CharT, _Traits>,
6016 typename basic_string<_CharT, _Traits, _Allocator>::size_type,
6017 typename basic_string<_CharT, _Traits, _Allocator>::size_type,
6018 const _Allocator& = _Allocator())
6019 -> basic_string<_CharT, _Traits, _Allocator>;
6020_GLIBCXX_END_NAMESPACE_CXX11}
6021#endif
6022
6023 // operator+
6024 /**
6025 * @brief Concatenate two strings.
6026 * @param __lhs First string.
6027 * @param __rhs Last string.
6028 * @return New string with value of @a __lhs followed by @a __rhs.
6029 */
6030 template<typename _CharT, typename _Traits, typename _Alloc>
6031 basic_string<_CharT, _Traits, _Alloc>
6032 operator+(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
6033 const basic_string<_CharT, _Traits, _Alloc>& __rhs)
6034 {
6035 basic_string<_CharT, _Traits, _Alloc> __str(__lhs);
6036 __str.append(__rhs);
6037 return __str;
6038 }
6039
6040 /**
6041 * @brief Concatenate C string and string.
6042 * @param __lhs First string.
6043 * @param __rhs Last string.
6044 * @return New string with value of @a __lhs followed by @a __rhs.
6045 */
6046 template<typename _CharT, typename _Traits, typename _Alloc>
6047 basic_string<_CharT,_Traits,_Alloc>
6048 operator+(const _CharT* __lhs,
6049 const basic_string<_CharT,_Traits,_Alloc>& __rhs);
6050
6051 /**
6052 * @brief Concatenate character and string.
6053 * @param __lhs First string.
6054 * @param __rhs Last string.
6055 * @return New string with @a __lhs followed by @a __rhs.
6056 */
6057 template<typename _CharT, typename _Traits, typename _Alloc>
6058 basic_string<_CharT,_Traits,_Alloc>
6059 operator+(_CharT __lhs, const basic_string<_CharT,_Traits,_Alloc>& __rhs);
6060
6061 /**
6062 * @brief Concatenate string and C string.
6063 * @param __lhs First string.
6064 * @param __rhs Last string.
6065 * @return New string with @a __lhs followed by @a __rhs.
6066 */
6067 template<typename _CharT, typename _Traits, typename _Alloc>
6068 inline basic_string<_CharT, _Traits, _Alloc>
6069 operator+(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
6070 const _CharT* __rhs)
6071 {
6072 basic_string<_CharT, _Traits, _Alloc> __str(__lhs);
6073 __str.append(__rhs);
6074 return __str;
6075 }
6076
6077 /**
6078 * @brief Concatenate string and character.
6079 * @param __lhs First string.
6080 * @param __rhs Last string.
6081 * @return New string with @a __lhs followed by @a __rhs.
6082 */
6083 template<typename _CharT, typename _Traits, typename _Alloc>
6084 inline basic_string<_CharT, _Traits, _Alloc>
6085 operator+(const basic_string<_CharT, _Traits, _Alloc>& __lhs, _CharT __rhs)
6086 {
6087 typedef basic_string<_CharT, _Traits, _Alloc> __string_type;
6088 typedef typename __string_type::size_type __size_type;
6089 __string_type __str(__lhs);
6090 __str.append(__size_type(1), __rhs);
6091 return __str;
6092 }
6093
6094#if __cplusplus201703L >= 201103L
6095 template<typename _CharT, typename _Traits, typename _Alloc>
6096 inline basic_string<_CharT, _Traits, _Alloc>
6097 operator+(basic_string<_CharT, _Traits, _Alloc>&& __lhs,
6098 const basic_string<_CharT, _Traits, _Alloc>& __rhs)
6099 { return std::move(__lhs.append(__rhs)); }
6100
6101 template<typename _CharT, typename _Traits, typename _Alloc>
6102 inline basic_string<_CharT, _Traits, _Alloc>
6103 operator+(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
6104 basic_string<_CharT, _Traits, _Alloc>&& __rhs)
6105 { return std::move(__rhs.insert(0, __lhs)); }
6106
6107 template<typename _CharT, typename _Traits, typename _Alloc>
6108 inline basic_string<_CharT, _Traits, _Alloc>
6109 operator+(basic_string<_CharT, _Traits, _Alloc>&& __lhs,
6110 basic_string<_CharT, _Traits, _Alloc>&& __rhs)
6111 {
6112#if _GLIBCXX_USE_CXX11_ABI1
6113 using _Alloc_traits = allocator_traits<_Alloc>;
6114 bool __use_rhs = false;
6115 if _GLIBCXX17_CONSTEXPRconstexpr (typename _Alloc_traits::is_always_equal{})
6116 __use_rhs = true;
6117 else if (__lhs.get_allocator() == __rhs.get_allocator())
6118 __use_rhs = true;
6119 if (__use_rhs)
6120#endif
6121 {
6122 const auto __size = __lhs.size() + __rhs.size();
6123 if (__size > __lhs.capacity() && __size <= __rhs.capacity())
6124 return std::move(__rhs.insert(0, __lhs));
6125 }
6126 return std::move(__lhs.append(__rhs));
6127 }
6128
6129 template<typename _CharT, typename _Traits, typename _Alloc>
6130 inline basic_string<_CharT, _Traits, _Alloc>
6131 operator+(const _CharT* __lhs,
6132 basic_string<_CharT, _Traits, _Alloc>&& __rhs)
6133 { return std::move(__rhs.insert(0, __lhs)); }
6134
6135 template<typename _CharT, typename _Traits, typename _Alloc>
6136 inline basic_string<_CharT, _Traits, _Alloc>
6137 operator+(_CharT __lhs,
6138 basic_string<_CharT, _Traits, _Alloc>&& __rhs)
6139 { return std::move(__rhs.insert(0, 1, __lhs)); }
6140
6141 template<typename _CharT, typename _Traits, typename _Alloc>
6142 inline basic_string<_CharT, _Traits, _Alloc>
6143 operator+(basic_string<_CharT, _Traits, _Alloc>&& __lhs,
6144 const _CharT* __rhs)
6145 { return std::move(__lhs.append(__rhs)); }
6146
6147 template<typename _CharT, typename _Traits, typename _Alloc>
6148 inline basic_string<_CharT, _Traits, _Alloc>
6149 operator+(basic_string<_CharT, _Traits, _Alloc>&& __lhs,
6150 _CharT __rhs)
6151 { return std::move(__lhs.append(1, __rhs)); }
6152#endif
6153
6154 // operator ==
6155 /**
6156 * @brief Test equivalence of two strings.
6157 * @param __lhs First string.
6158 * @param __rhs Second string.
6159 * @return True if @a __lhs.compare(@a __rhs) == 0. False otherwise.
6160 */
6161 template<typename _CharT, typename _Traits, typename _Alloc>
6162 inline bool
6163 operator==(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
6164 const basic_string<_CharT, _Traits, _Alloc>& __rhs)
6165 _GLIBCXX_NOEXCEPTnoexcept
6166 { return __lhs.compare(__rhs) == 0; }
6167
6168 template<typename _CharT>
6169 inline
6170 typename __gnu_cxx::__enable_if<__is_char<_CharT>::__value, bool>::__type
6171 operator==(const basic_string<_CharT>& __lhs,
6172 const basic_string<_CharT>& __rhs) _GLIBCXX_NOEXCEPTnoexcept
6173 { return (__lhs.size() == __rhs.size()
6174 && !std::char_traits<_CharT>::compare(__lhs.data(), __rhs.data(),
6175 __lhs.size())); }
6176
6177 /**
6178 * @brief Test equivalence of string and C string.
6179 * @param __lhs String.
6180 * @param __rhs C string.
6181 * @return True if @a __lhs.compare(@a __rhs) == 0. False otherwise.
6182 */
6183 template<typename _CharT, typename _Traits, typename _Alloc>
6184 inline bool
6185 operator==(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
6186 const _CharT* __rhs)
6187 { return __lhs.compare(__rhs) == 0; }
6188
6189#if __cpp_lib_three_way_comparison
6190 /**
6191 * @brief Three-way comparison of a string and a C string.
6192 * @param __lhs A string.
6193 * @param __rhs A null-terminated string.
6194 * @return A value indicating whether `__lhs` is less than, equal to,
6195 * greater than, or incomparable with `__rhs`.
6196 */
6197 template<typename _CharT, typename _Traits, typename _Alloc>
6198 inline auto
6199 operator<=>(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
6200 const basic_string<_CharT, _Traits, _Alloc>& __rhs) noexcept
6201 -> decltype(__detail::__char_traits_cmp_cat<_Traits>(0))
6202 { return __detail::__char_traits_cmp_cat<_Traits>(__lhs.compare(__rhs)); }
6203
6204 /**
6205 * @brief Three-way comparison of a string and a C string.
6206 * @param __lhs A string.
6207 * @param __rhs A null-terminated string.
6208 * @return A value indicating whether `__lhs` is less than, equal to,
6209 * greater than, or incomparable with `__rhs`.
6210 */
6211 template<typename _CharT, typename _Traits, typename _Alloc>
6212 inline auto
6213 operator<=>(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
6214 const _CharT* __rhs) noexcept
6215 -> decltype(__detail::__char_traits_cmp_cat<_Traits>(0))
6216 { return __detail::__char_traits_cmp_cat<_Traits>(__lhs.compare(__rhs)); }
6217#else
6218 /**
6219 * @brief Test equivalence of C string and string.
6220 * @param __lhs C string.
6221 * @param __rhs String.
6222 * @return True if @a __rhs.compare(@a __lhs) == 0. False otherwise.
6223 */
6224 template<typename _CharT, typename _Traits, typename _Alloc>
6225 inline bool
6226 operator==(const _CharT* __lhs,
6227 const basic_string<_CharT, _Traits, _Alloc>& __rhs)
6228 { return __rhs.compare(__lhs) == 0; }
6229
6230 // operator !=
6231 /**
6232 * @brief Test difference of two strings.
6233 * @param __lhs First string.
6234 * @param __rhs Second string.
6235 * @return True if @a __lhs.compare(@a __rhs) != 0. False otherwise.
6236 */
6237 template<typename _CharT, typename _Traits, typename _Alloc>
6238 inline bool
6239 operator!=(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
6240 const basic_string<_CharT, _Traits, _Alloc>& __rhs)
6241 _GLIBCXX_NOEXCEPTnoexcept
6242 { return !(__lhs == __rhs); }
6243
6244 /**
6245 * @brief Test difference of C string and string.
6246 * @param __lhs C string.
6247 * @param __rhs String.
6248 * @return True if @a __rhs.compare(@a __lhs) != 0. False otherwise.
6249 */
6250 template<typename _CharT, typename _Traits, typename _Alloc>
6251 inline bool
6252 operator!=(const _CharT* __lhs,
6253 const basic_string<_CharT, _Traits, _Alloc>& __rhs)
6254 { return !(__lhs == __rhs); }
6255
6256 /**
6257 * @brief Test difference of string and C string.
6258 * @param __lhs String.
6259 * @param __rhs C string.
6260 * @return True if @a __lhs.compare(@a __rhs) != 0. False otherwise.
6261 */
6262 template<typename _CharT, typename _Traits, typename _Alloc>
6263 inline bool
6264 operator!=(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
6265 const _CharT* __rhs)
6266 { return !(__lhs == __rhs); }
6267
6268 // operator <
6269 /**
6270 * @brief Test if string precedes string.
6271 * @param __lhs First string.
6272 * @param __rhs Second string.
6273 * @return True if @a __lhs precedes @a __rhs. False otherwise.
6274 */
6275 template<typename _CharT, typename _Traits, typename _Alloc>
6276 inline bool
6277 operator<(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
6278 const basic_string<_CharT, _Traits, _Alloc>& __rhs)
6279 _GLIBCXX_NOEXCEPTnoexcept
6280 { return __lhs.compare(__rhs) < 0; }
6281
6282 /**
6283 * @brief Test if string precedes C string.
6284 * @param __lhs String.
6285 * @param __rhs C string.
6286 * @return True if @a __lhs precedes @a __rhs. False otherwise.
6287 */
6288 template<typename _CharT, typename _Traits, typename _Alloc>
6289 inline bool
6290 operator<(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
6291 const _CharT* __rhs)
6292 { return __lhs.compare(__rhs) < 0; }
6293
6294 /**
6295 * @brief Test if C string precedes string.
6296 * @param __lhs C string.
6297 * @param __rhs String.
6298 * @return True if @a __lhs precedes @a __rhs. False otherwise.
6299 */
6300 template<typename _CharT, typename _Traits, typename _Alloc>
6301 inline bool
6302 operator<(const _CharT* __lhs,
6303 const basic_string<_CharT, _Traits, _Alloc>& __rhs)
6304 { return __rhs.compare(__lhs) > 0; }
6305
6306 // operator >
6307 /**
6308 * @brief Test if string follows string.
6309 * @param __lhs First string.
6310 * @param __rhs Second string.
6311 * @return True if @a __lhs follows @a __rhs. False otherwise.
6312 */
6313 template<typename _CharT, typename _Traits, typename _Alloc>
6314 inline bool
6315 operator>(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
6316 const basic_string<_CharT, _Traits, _Alloc>& __rhs)
6317 _GLIBCXX_NOEXCEPTnoexcept
6318 { return __lhs.compare(__rhs) > 0; }
6319
6320 /**
6321 * @brief Test if string follows C string.
6322 * @param __lhs String.
6323 * @param __rhs C string.
6324 * @return True if @a __lhs follows @a __rhs. False otherwise.
6325 */
6326 template<typename _CharT, typename _Traits, typename _Alloc>
6327 inline bool
6328 operator>(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
6329 const _CharT* __rhs)
6330 { return __lhs.compare(__rhs) > 0; }
6331
6332 /**
6333 * @brief Test if C string follows string.
6334 * @param __lhs C string.
6335 * @param __rhs String.
6336 * @return True if @a __lhs follows @a __rhs. False otherwise.
6337 */
6338 template<typename _CharT, typename _Traits, typename _Alloc>
6339 inline bool
6340 operator>(const _CharT* __lhs,
6341 const basic_string<_CharT, _Traits, _Alloc>& __rhs)
6342 { return __rhs.compare(__lhs) < 0; }
6343
6344 // operator <=
6345 /**
6346 * @brief Test if string doesn't follow string.
6347 * @param __lhs First string.
6348 * @param __rhs Second string.
6349 * @return True if @a __lhs doesn't follow @a __rhs. False otherwise.
6350 */
6351 template<typename _CharT, typename _Traits, typename _Alloc>
6352 inline bool
6353 operator<=(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
6354 const basic_string<_CharT, _Traits, _Alloc>& __rhs)
6355 _GLIBCXX_NOEXCEPTnoexcept
6356 { return __lhs.compare(__rhs) <= 0; }
6357
6358 /**
6359 * @brief Test if string doesn't follow C string.
6360 * @param __lhs String.
6361 * @param __rhs C string.
6362 * @return True if @a __lhs doesn't follow @a __rhs. False otherwise.
6363 */
6364 template<typename _CharT, typename _Traits, typename _Alloc>
6365 inline bool
6366 operator<=(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
6367 const _CharT* __rhs)
6368 { return __lhs.compare(__rhs) <= 0; }
6369
6370 /**
6371 * @brief Test if C string doesn't follow string.
6372 * @param __lhs C string.
6373 * @param __rhs String.
6374 * @return True if @a __lhs doesn't follow @a __rhs. False otherwise.
6375 */
6376 template<typename _CharT, typename _Traits, typename _Alloc>
6377 inline bool
6378 operator<=(const _CharT* __lhs,
6379 const basic_string<_CharT, _Traits, _Alloc>& __rhs)
6380 { return __rhs.compare(__lhs) >= 0; }
6381
6382 // operator >=
6383 /**
6384 * @brief Test if string doesn't precede string.
6385 * @param __lhs First string.
6386 * @param __rhs Second string.
6387 * @return True if @a __lhs doesn't precede @a __rhs. False otherwise.
6388 */
6389 template<typename _CharT, typename _Traits, typename _Alloc>
6390 inline bool
6391 operator>=(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
6392 const basic_string<_CharT, _Traits, _Alloc>& __rhs)
6393 _GLIBCXX_NOEXCEPTnoexcept
6394 { return __lhs.compare(__rhs) >= 0; }
6395
6396 /**
6397 * @brief Test if string doesn't precede C string.
6398 * @param __lhs String.
6399 * @param __rhs C string.
6400 * @return True if @a __lhs doesn't precede @a __rhs. False otherwise.
6401 */
6402 template<typename _CharT, typename _Traits, typename _Alloc>
6403 inline bool
6404 operator>=(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
6405 const _CharT* __rhs)
6406 { return __lhs.compare(__rhs) >= 0; }
6407
6408 /**
6409 * @brief Test if C string doesn't precede string.
6410 * @param __lhs C string.
6411 * @param __rhs String.
6412 * @return True if @a __lhs doesn't precede @a __rhs. False otherwise.
6413 */
6414 template<typename _CharT, typename _Traits, typename _Alloc>
6415 inline bool
6416 operator>=(const _CharT* __lhs,
6417 const basic_string<_CharT, _Traits, _Alloc>& __rhs)
6418 { return __rhs.compare(__lhs) <= 0; }
6419#endif // three-way comparison
6420
6421 /**
6422 * @brief Swap contents of two strings.
6423 * @param __lhs First string.
6424 * @param __rhs Second string.
6425 *
6426 * Exchanges the contents of @a __lhs and @a __rhs in constant time.
6427 */
6428 template<typename _CharT, typename _Traits, typename _Alloc>
6429 inline void
6430 swap(basic_string<_CharT, _Traits, _Alloc>& __lhs,
6431 basic_string<_CharT, _Traits, _Alloc>& __rhs)
6432 _GLIBCXX_NOEXCEPT_IF(noexcept(__lhs.swap(__rhs)))noexcept(noexcept(__lhs.swap(__rhs)))
6433 { __lhs.swap(__rhs); }
6434
6435
6436 /**
6437 * @brief Read stream into a string.
6438 * @param __is Input stream.
6439 * @param __str Buffer to store into.
6440 * @return Reference to the input stream.
6441 *
6442 * Stores characters from @a __is into @a __str until whitespace is
6443 * found, the end of the stream is encountered, or str.max_size()
6444 * is reached. If is.width() is non-zero, that is the limit on the
6445 * number of characters stored into @a __str. Any previous
6446 * contents of @a __str are erased.
6447 */
6448 template<typename _CharT, typename _Traits, typename _Alloc>
6449 basic_istream<_CharT, _Traits>&
6450 operator>>(basic_istream<_CharT, _Traits>& __is,
6451 basic_string<_CharT, _Traits, _Alloc>& __str);
6452
6453 template<>
6454 basic_istream<char>&
6455 operator>>(basic_istream<char>& __is, basic_string<char>& __str);
6456
6457 /**
6458 * @brief Write string to a stream.
6459 * @param __os Output stream.
6460 * @param __str String to write out.
6461 * @return Reference to the output stream.
6462 *
6463 * Output characters of @a __str into os following the same rules as for
6464 * writing a C string.
6465 */
6466 template<typename _CharT, typename _Traits, typename _Alloc>
6467 inline basic_ostream<_CharT, _Traits>&
6468 operator<<(basic_ostream<_CharT, _Traits>& __os,
6469 const basic_string<_CharT, _Traits, _Alloc>& __str)
6470 {
6471 // _GLIBCXX_RESOLVE_LIB_DEFECTS
6472 // 586. string inserter not a formatted function
6473 return __ostream_insert(__os, __str.data(), __str.size());
6474 }
6475
6476 /**
6477 * @brief Read a line from stream into a string.
6478 * @param __is Input stream.
6479 * @param __str Buffer to store into.
6480 * @param __delim Character marking end of line.
6481 * @return Reference to the input stream.
6482 *
6483 * Stores characters from @a __is into @a __str until @a __delim is
6484 * found, the end of the stream is encountered, or str.max_size()
6485 * is reached. Any previous contents of @a __str are erased. If
6486 * @a __delim is encountered, it is extracted but not stored into
6487 * @a __str.
6488 */
6489 template<typename _CharT, typename _Traits, typename _Alloc>
6490 basic_istream<_CharT, _Traits>&
6491 getline(basic_istream<_CharT, _Traits>& __is,
6492 basic_string<_CharT, _Traits, _Alloc>& __str, _CharT __delim);
6493
6494 /**
6495 * @brief Read a line from stream into a string.
6496 * @param __is Input stream.
6497 * @param __str Buffer to store into.
6498 * @return Reference to the input stream.
6499 *
6500 * Stores characters from is into @a __str until &apos;\n&apos; is
6501 * found, the end of the stream is encountered, or str.max_size()
6502 * is reached. Any previous contents of @a __str are erased. If
6503 * end of line is encountered, it is extracted but not stored into
6504 * @a __str.
6505 */
6506 template<typename _CharT, typename _Traits, typename _Alloc>
6507 inline basic_istream<_CharT, _Traits>&
6508 getline(basic_istream<_CharT, _Traits>& __is,
6509 basic_string<_CharT, _Traits, _Alloc>& __str)
6510 { return std::getline(__is, __str, __is.widen('\n')); }
6511
6512#if __cplusplus201703L >= 201103L
6513 /// Read a line from an rvalue stream into a string.
6514 template<typename _CharT, typename _Traits, typename _Alloc>
6515 inline basic_istream<_CharT, _Traits>&
6516 getline(basic_istream<_CharT, _Traits>&& __is,
6517 basic_string<_CharT, _Traits, _Alloc>& __str, _CharT __delim)
6518 { return std::getline(__is, __str, __delim); }
6519
6520 /// Read a line from an rvalue stream into a string.
6521 template<typename _CharT, typename _Traits, typename _Alloc>
6522 inline basic_istream<_CharT, _Traits>&
6523 getline(basic_istream<_CharT, _Traits>&& __is,
6524 basic_string<_CharT, _Traits, _Alloc>& __str)
6525 { return std::getline(__is, __str); }
6526#endif
6527
6528 template<>
6529 basic_istream<char>&
6530 getline(basic_istream<char>& __in, basic_string<char>& __str,
6531 char __delim);
6532
6533#ifdef _GLIBCXX_USE_WCHAR_T1
6534 template<>
6535 basic_istream<wchar_t>&
6536 getline(basic_istream<wchar_t>& __in, basic_string<wchar_t>& __str,
6537 wchar_t __delim);
6538#endif
6539
6540_GLIBCXX_END_NAMESPACE_VERSION
6541} // namespace
6542
6543#if __cplusplus201703L >= 201103L
6544
6545#include <ext/string_conversions.h>
6546#include <bits/charconv.h>
6547
6548namespace std _GLIBCXX_VISIBILITY(default)__attribute__ ((__visibility__ ("default")))
6549{
6550_GLIBCXX_BEGIN_NAMESPACE_VERSION
6551_GLIBCXX_BEGIN_NAMESPACE_CXX11namespace __cxx11 {
6552
6553#if _GLIBCXX_USE_C99_STDLIB1
6554 // 21.4 Numeric Conversions [string.conversions].
6555 inline int
6556 stoi(const string& __str, size_t* __idx = 0, int __base = 10)
6557 { return __gnu_cxx::__stoa<long, int>(&std::strtol, "stoi", __str.c_str(),
6558 __idx, __base); }
6559
6560 inline long
6561 stol(const string& __str, size_t* __idx = 0, int __base = 10)
6562 { return __gnu_cxx::__stoa(&std::strtol, "stol", __str.c_str(),
6563 __idx, __base); }
6564
6565 inline unsigned long
6566 stoul(const string& __str, size_t* __idx = 0, int __base = 10)
6567 { return __gnu_cxx::__stoa(&std::strtoul, "stoul", __str.c_str(),
6568 __idx, __base); }
6569
6570 inline long long
6571 stoll(const string& __str, size_t* __idx = 0, int __base = 10)
6572 { return __gnu_cxx::__stoa(&std::strtoll, "stoll", __str.c_str(),
6573 __idx, __base); }
6574
6575 inline unsigned long long
6576 stoull(const string& __str, size_t* __idx = 0, int __base = 10)
6577 { return __gnu_cxx::__stoa(&std::strtoull, "stoull", __str.c_str(),
6578 __idx, __base); }
6579
6580 // NB: strtof vs strtod.
6581 inline float
6582 stof(const string& __str, size_t* __idx = 0)
6583 { return __gnu_cxx::__stoa(&std::strtof, "stof", __str.c_str(), __idx); }
6584
6585 inline double
6586 stod(const string& __str, size_t* __idx = 0)
6587 { return __gnu_cxx::__stoa(&std::strtod, "stod", __str.c_str(), __idx); }
6588
6589 inline long double
6590 stold(const string& __str, size_t* __idx = 0)
6591 { return __gnu_cxx::__stoa(&std::strtold, "stold", __str.c_str(), __idx); }
6592#endif // _GLIBCXX_USE_C99_STDLIB
6593
6594 // DR 1261. Insufficent overloads for to_string / to_wstring
6595
6596 inline string
6597 to_string(int __val)
6598 {
6599 const bool __neg = __val < 0;
6600 const unsigned __uval = __neg ? (unsigned)~__val + 1u : __val;
6601 const auto __len = __detail::__to_chars_len(__uval);
6602 string __str(__neg + __len, '-');
6603 __detail::__to_chars_10_impl(&__str[__neg], __len, __uval);
6604 return __str;
6605 }
6606
6607 inline string
6608 to_string(unsigned __val)
6609 {
6610 string __str(__detail::__to_chars_len(__val), '\0');
6611 __detail::__to_chars_10_impl(&__str[0], __str.size(), __val);
6612 return __str;
6613 }
6614
6615 inline string
6616 to_string(long __val)
6617 {
6618 const bool __neg = __val < 0;
6619 const unsigned long __uval = __neg ? (unsigned long)~__val + 1ul : __val;
6620 const auto __len = __detail::__to_chars_len(__uval);
6621 string __str(__neg + __len, '-');
6622 __detail::__to_chars_10_impl(&__str[__neg], __len, __uval);
6623 return __str;
6624 }
6625
6626 inline string
6627 to_string(unsigned long __val)
6628 {
6629 string __str(__detail::__to_chars_len(__val), '\0');
6630 __detail::__to_chars_10_impl(&__str[0], __str.size(), __val);
6631 return __str;
6632 }
6633
6634 inline string
6635 to_string(long long __val)
6636 {
6637 const bool __neg = __val < 0;
6638 const unsigned long long __uval
6639 = __neg ? (unsigned long long)~__val + 1ull : __val;
6640 const auto __len = __detail::__to_chars_len(__uval);
6641 string __str(__neg + __len, '-');
6642 __detail::__to_chars_10_impl(&__str[__neg], __len, __uval);
6643 return __str;
6644 }
6645
6646 inline string
6647 to_string(unsigned long long __val)
6648 {
6649 string __str(__detail::__to_chars_len(__val), '\0');
6650 __detail::__to_chars_10_impl(&__str[0], __str.size(), __val);
6651 return __str;
6652 }
6653
6654#if _GLIBCXX_USE_C99_STDIO1
6655 // NB: (v)snprintf vs sprintf.
6656
6657 inline string
6658 to_string(float __val)
6659 {
6660 const int __n =
6661 __gnu_cxx::__numeric_traits<float>::__max_exponent10 + 20;
6662 return __gnu_cxx::__to_xstring<string>(&std::vsnprintf, __n,
6663 "%f", __val);
6664 }
6665
6666 inline string
6667 to_string(double __val)
6668 {
6669 const int __n =
6670 __gnu_cxx::__numeric_traits<double>::__max_exponent10 + 20;
6671 return __gnu_cxx::__to_xstring<string>(&std::vsnprintf, __n,
6672 "%f", __val);
6673 }
6674
6675 inline string
6676 to_string(long double __val)
6677 {
6678 const int __n =
6679 __gnu_cxx::__numeric_traits<long double>::__max_exponent10 + 20;
6680 return __gnu_cxx::__to_xstring<string>(&std::vsnprintf, __n,
6681 "%Lf", __val);
6682 }
6683#endif // _GLIBCXX_USE_C99_STDIO
6684
6685#if defined(_GLIBCXX_USE_WCHAR_T1) && _GLIBCXX_USE_C99_WCHAR1
6686 inline int
6687 stoi(const wstring& __str, size_t* __idx = 0, int __base = 10)
6688 { return __gnu_cxx::__stoa<long, int>(&std::wcstol, "stoi", __str.c_str(),
6689 __idx, __base); }
6690
6691 inline long
6692 stol(const wstring& __str, size_t* __idx = 0, int __base = 10)
6693 { return __gnu_cxx::__stoa(&std::wcstol, "stol", __str.c_str(),
6694 __idx, __base); }
6695
6696 inline unsigned long
6697 stoul(const wstring& __str, size_t* __idx = 0, int __base = 10)
6698 { return __gnu_cxx::__stoa(&std::wcstoul, "stoul", __str.c_str(),
6699 __idx, __base); }
6700
6701 inline long long
6702 stoll(const wstring& __str, size_t* __idx = 0, int __base = 10)
6703 { return __gnu_cxx::__stoa(&std::wcstoll, "stoll", __str.c_str(),
6704 __idx, __base); }
6705
6706 inline unsigned long long
6707 stoull(const wstring& __str, size_t* __idx = 0, int __base = 10)
6708 { return __gnu_cxx::__stoa(&std::wcstoull, "stoull", __str.c_str(),
6709 __idx, __base); }
6710
6711 // NB: wcstof vs wcstod.
6712 inline float
6713 stof(const wstring& __str, size_t* __idx = 0)
6714 { return __gnu_cxx::__stoa(&std::wcstof, "stof", __str.c_str(), __idx); }
6715
6716 inline double
6717 stod(const wstring& __str, size_t* __idx = 0)
6718 { return __gnu_cxx::__stoa(&std::wcstod, "stod", __str.c_str(), __idx); }
6719
6720 inline long double
6721 stold(const wstring& __str, size_t* __idx = 0)
6722 { return __gnu_cxx::__stoa(&std::wcstold, "stold", __str.c_str(), __idx); }
6723
6724#ifndef _GLIBCXX_HAVE_BROKEN_VSWPRINTF
6725 // DR 1261.
6726 inline wstring
6727 to_wstring(int __val)
6728 { return __gnu_cxx::__to_xstring<wstring>(&std::vswprintf, 4 * sizeof(int),
6729 L"%d", __val); }
6730
6731 inline wstring
6732 to_wstring(unsigned __val)
6733 { return __gnu_cxx::__to_xstring<wstring>(&std::vswprintf,
6734 4 * sizeof(unsigned),
6735 L"%u", __val); }
6736
6737 inline wstring
6738 to_wstring(long __val)
6739 { return __gnu_cxx::__to_xstring<wstring>(&std::vswprintf, 4 * sizeof(long),
6740 L"%ld", __val); }
6741
6742 inline wstring
6743 to_wstring(unsigned long __val)
6744 { return __gnu_cxx::__to_xstring<wstring>(&std::vswprintf,
6745 4 * sizeof(unsigned long),
6746 L"%lu", __val); }
6747
6748 inline wstring
6749 to_wstring(long long __val)
6750 { return __gnu_cxx::__to_xstring<wstring>(&std::vswprintf,
6751 4 * sizeof(long long),
6752 L"%lld", __val); }
6753
6754 inline wstring
6755 to_wstring(unsigned long long __val)
6756 { return __gnu_cxx::__to_xstring<wstring>(&std::vswprintf,
6757 4 * sizeof(unsigned long long),
6758 L"%llu", __val); }
6759
6760 inline wstring
6761 to_wstring(float __val)
6762 {
6763 const int __n =
6764 __gnu_cxx::__numeric_traits<float>::__max_exponent10 + 20;
6765 return __gnu_cxx::__to_xstring<wstring>(&std::vswprintf, __n,
6766 L"%f", __val);
6767 }
6768
6769 inline wstring
6770 to_wstring(double __val)
6771 {
6772 const int __n =
6773 __gnu_cxx::__numeric_traits<double>::__max_exponent10 + 20;
6774 return __gnu_cxx::__to_xstring<wstring>(&std::vswprintf, __n,
6775 L"%f", __val);
6776 }
6777
6778 inline wstring
6779 to_wstring(long double __val)
6780 {
6781 const int __n =
6782 __gnu_cxx::__numeric_traits<long double>::__max_exponent10 + 20;
6783 return __gnu_cxx::__to_xstring<wstring>(&std::vswprintf, __n,
6784 L"%Lf", __val);
6785 }
6786#endif // _GLIBCXX_HAVE_BROKEN_VSWPRINTF
6787#endif // _GLIBCXX_USE_WCHAR_T && _GLIBCXX_USE_C99_WCHAR
6788
6789_GLIBCXX_END_NAMESPACE_CXX11}
6790_GLIBCXX_END_NAMESPACE_VERSION
6791} // namespace
6792
6793#endif /* C++11 */
6794
6795#if __cplusplus201703L >= 201103L
6796
6797#include <bits/functional_hash.h>
6798
6799namespace std _GLIBCXX_VISIBILITY(default)__attribute__ ((__visibility__ ("default")))
6800{
6801_GLIBCXX_BEGIN_NAMESPACE_VERSION
6802
6803 // DR 1182.
6804
6805#ifndef _GLIBCXX_COMPATIBILITY_CXX0X
6806 /// std::hash specialization for string.
6807 template<>
6808 struct hash<string>
6809 : public __hash_base<size_t, string>
6810 {
6811 size_t
6812 operator()(const string& __s) const noexcept
6813 { return std::_Hash_impl::hash(__s.data(), __s.length()); }
6814 };
6815
6816 template<>
6817 struct __is_fast_hash<hash<string>> : std::false_type
6818 { };
6819
6820#ifdef _GLIBCXX_USE_WCHAR_T1
6821 /// std::hash specialization for wstring.
6822 template<>
6823 struct hash<wstring>
6824 : public __hash_base<size_t, wstring>
6825 {
6826 size_t
6827 operator()(const wstring& __s) const noexcept
6828 { return std::_Hash_impl::hash(__s.data(),
6829 __s.length() * sizeof(wchar_t)); }
6830 };
6831
6832 template<>
6833 struct __is_fast_hash<hash<wstring>> : std::false_type
6834 { };
6835#endif
6836#endif /* _GLIBCXX_COMPATIBILITY_CXX0X */
6837
6838#ifdef _GLIBCXX_USE_CHAR8_T
6839 /// std::hash specialization for u8string.
6840 template<>
6841 struct hash<u8string>
6842 : public __hash_base<size_t, u8string>
6843 {
6844 size_t
6845 operator()(const u8string& __s) const noexcept
6846 { return std::_Hash_impl::hash(__s.data(),
6847 __s.length() * sizeof(char8_t)); }
6848 };
6849
6850 template<>
6851 struct __is_fast_hash<hash<u8string>> : std::false_type
6852 { };
6853#endif
6854
6855 /// std::hash specialization for u16string.
6856 template<>
6857 struct hash<u16string>
6858 : public __hash_base<size_t, u16string>
6859 {
6860 size_t
6861 operator()(const u16string& __s) const noexcept
6862 { return std::_Hash_impl::hash(__s.data(),
6863 __s.length() * sizeof(char16_t)); }
6864 };
6865
6866 template<>
6867 struct __is_fast_hash<hash<u16string>> : std::false_type
6868 { };
6869
6870 /// std::hash specialization for u32string.
6871 template<>
6872 struct hash<u32string>
6873 : public __hash_base<size_t, u32string>
6874 {
6875 size_t
6876 operator()(const u32string& __s) const noexcept
6877 { return std::_Hash_impl::hash(__s.data(),
6878 __s.length() * sizeof(char32_t)); }
6879 };
6880
6881 template<>
6882 struct __is_fast_hash<hash<u32string>> : std::false_type
6883 { };
6884
6885#if __cplusplus201703L >= 201402L
6886
6887#define __cpp_lib_string_udls201304 201304
6888
6889 inline namespace literals
6890 {
6891 inline namespace string_literals
6892 {
6893#pragma GCC diagnostic push
6894#pragma GCC diagnostic ignored "-Wliteral-suffix"
6895 _GLIBCXX_DEFAULT_ABI_TAG__attribute ((__abi_tag__ ("cxx11")))
6896 inline basic_string<char>
6897 operator""s(const char* __str, size_t __len)
6898 { return basic_string<char>{__str, __len}; }
6899
6900#ifdef _GLIBCXX_USE_WCHAR_T1
6901 _GLIBCXX_DEFAULT_ABI_TAG__attribute ((__abi_tag__ ("cxx11")))
6902 inline basic_string<wchar_t>
6903 operator""s(const wchar_t* __str, size_t __len)
6904 { return basic_string<wchar_t>{__str, __len}; }
6905#endif
6906
6907#ifdef _GLIBCXX_USE_CHAR8_T
6908 _GLIBCXX_DEFAULT_ABI_TAG__attribute ((__abi_tag__ ("cxx11")))
6909 inline basic_string<char8_t>
6910 operator""s(const char8_t* __str, size_t __len)
6911 { return basic_string<char8_t>{__str, __len}; }
6912#endif
6913
6914 _GLIBCXX_DEFAULT_ABI_TAG__attribute ((__abi_tag__ ("cxx11")))
6915 inline basic_string<char16_t>
6916 operator""s(const char16_t* __str, size_t __len)
6917 { return basic_string<char16_t>{__str, __len}; }
6918
6919 _GLIBCXX_DEFAULT_ABI_TAG__attribute ((__abi_tag__ ("cxx11")))
6920 inline basic_string<char32_t>
6921 operator""s(const char32_t* __str, size_t __len)
6922 { return basic_string<char32_t>{__str, __len}; }
6923
6924#pragma GCC diagnostic pop
6925 } // inline namespace string_literals
6926 } // inline namespace literals
6927
6928#if __cplusplus201703L >= 201703L
6929 namespace __detail::__variant
6930 {
6931 template<typename> struct _Never_valueless_alt; // see <variant>
6932
6933 // Provide the strong exception-safety guarantee when emplacing a
6934 // basic_string into a variant, but only if moving the string cannot throw.
6935 template<typename _Tp, typename _Traits, typename _Alloc>
6936 struct _Never_valueless_alt<std::basic_string<_Tp, _Traits, _Alloc>>
6937 : __and_<
6938 is_nothrow_move_constructible<std::basic_string<_Tp, _Traits, _Alloc>>,
6939 is_nothrow_move_assignable<std::basic_string<_Tp, _Traits, _Alloc>>
6940 >::type
6941 { };
6942 } // namespace __detail::__variant
6943#endif // C++17
6944#endif // C++14
6945
6946_GLIBCXX_END_NAMESPACE_VERSION
6947} // namespace std
6948
6949#endif // C++11
6950
6951#endif /* _BASIC_STRING_H */