]>
Commit | Line | Data |
---|---|---|
34a2b755 JW |
1 | // Methods for Exception Support for -*- C++ -*- |
2 | ||
99dee823 | 3 | // Copyright (C) 2014-2021 Free Software Foundation, Inc. |
34a2b755 JW |
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 | // | |
26 | // ISO C++ 14882: 19.1 Exception classes | |
27 | // | |
28 | ||
a04d5fc9 TR |
29 | // Enable hooks for support for the Transactional Memory TS (N4514). |
30 | #define _GLIBCXX_TM_TS_INTERNAL | |
31 | void | |
32 | _txnal_cow_string_C1_for_exceptions(void* that, const char* s, void* exc); | |
33 | const char* | |
34 | _txnal_cow_string_c_str(const void* that); | |
35 | void | |
36 | _txnal_cow_string_D1(void* that); | |
37 | void | |
38 | _txnal_cow_string_D1_commit(void* that); | |
39 | void* | |
40 | _txnal_logic_error_get_msg(void* e); | |
41 | void* | |
42 | _txnal_runtime_error_get_msg(void* e); | |
43 | ||
34a2b755 JW |
44 | // All exception classes still use the classic COW std::string. |
45 | #define _GLIBCXX_USE_CXX11_ABI 0 | |
46 | #define _GLIBCXX_DEFINE_STDEXCEPT_COPY_OPS 1 | |
47 | #define __cow_string __cow_stringxxx | |
48 | #include <stdexcept> | |
49 | #include <system_error> | |
50 | #undef __cow_string | |
51 | ||
52 | namespace std _GLIBCXX_VISIBILITY(default) | |
53 | { | |
54 | _GLIBCXX_BEGIN_NAMESPACE_VERSION | |
55 | ||
d04dbb8a JW |
56 | // Copy/move constructors and assignment operators defined using COW string. |
57 | // These operations are noexcept even though copying a COW string is not, | |
58 | // but we know that the string member in an exception has not been "leaked" | |
59 | // so copying is a simple reference count increment. | |
891b1d68 JW |
60 | // For the fully dynamic string moves are not noexcept (due to needing to |
61 | // allocate an empty string) so we just define the moves as copies here. | |
34a2b755 JW |
62 | |
63 | logic_error::logic_error(const logic_error& e) noexcept | |
f5a9710a | 64 | : exception(e), _M_msg(e._M_msg) { } |
34a2b755 JW |
65 | |
66 | logic_error& logic_error::operator=(const logic_error& e) noexcept | |
67 | { _M_msg = e._M_msg; return *this; } | |
68 | ||
891b1d68 | 69 | #if _GLIBCXX_FULLY_DYNAMIC_STRING == 0 |
d04dbb8a JW |
70 | logic_error::logic_error(logic_error&& e) noexcept = default; |
71 | ||
72 | logic_error& | |
73 | logic_error::operator=(logic_error&& e) noexcept = default; | |
891b1d68 JW |
74 | #else |
75 | logic_error::logic_error(logic_error&& e) noexcept | |
76 | : exception(e), _M_msg(e._M_msg) { } | |
77 | ||
78 | logic_error& | |
79 | logic_error::operator=(logic_error&& e) noexcept | |
80 | { _M_msg = e._M_msg; return *this; } | |
81 | #endif | |
d04dbb8a | 82 | |
34a2b755 | 83 | runtime_error::runtime_error(const runtime_error& e) noexcept |
f5a9710a | 84 | : exception(e), _M_msg(e._M_msg) { } |
34a2b755 JW |
85 | |
86 | runtime_error& | |
87 | runtime_error::operator=(const runtime_error& e) noexcept | |
88 | { _M_msg = e._M_msg; return *this; } | |
89 | ||
891b1d68 | 90 | #if _GLIBCXX_FULLY_DYNAMIC_STRING == 0 |
d04dbb8a JW |
91 | runtime_error::runtime_error(runtime_error&& e) noexcept = default; |
92 | ||
93 | runtime_error& | |
94 | runtime_error::operator=(runtime_error&& e) noexcept = default; | |
891b1d68 JW |
95 | #else |
96 | runtime_error::runtime_error(runtime_error&& e) noexcept | |
97 | : exception(e), _M_msg(e._M_msg) { } | |
98 | ||
99 | runtime_error& | |
100 | runtime_error::operator=(runtime_error&& e) noexcept | |
101 | { _M_msg = e._M_msg; return *this; } | |
102 | #endif | |
d04dbb8a | 103 | |
34a2b755 JW |
104 | // New C++11 constructors: |
105 | ||
106 | logic_error::logic_error(const char* __arg) | |
107 | : exception(), _M_msg(__arg) { } | |
108 | ||
109 | domain_error::domain_error(const char* __arg) | |
110 | : logic_error(__arg) { } | |
111 | ||
112 | invalid_argument::invalid_argument(const char* __arg) | |
113 | : logic_error(__arg) { } | |
114 | ||
115 | length_error::length_error(const char* __arg) | |
116 | : logic_error(__arg) { } | |
117 | ||
118 | out_of_range::out_of_range(const char* __arg) | |
119 | : logic_error(__arg) { } | |
120 | ||
121 | runtime_error::runtime_error(const char* __arg) | |
122 | : exception(), _M_msg(__arg) { } | |
123 | ||
124 | range_error::range_error(const char* __arg) | |
125 | : runtime_error(__arg) { } | |
126 | ||
127 | overflow_error::overflow_error(const char* __arg) | |
128 | : runtime_error(__arg) { } | |
129 | ||
130 | underflow_error::underflow_error(const char* __arg) | |
131 | : runtime_error(__arg) { } | |
132 | ||
133 | #if _GLIBCXX_USE_DUAL_ABI | |
134 | // Converting constructor from COW std::string to SSO string. | |
135 | __sso_string::__sso_string(const string& s) | |
136 | : __sso_string(s.c_str(), s.length()) { } | |
137 | ||
138 | // Redefine __cow_string so that we can define and export its members | |
139 | // in terms of the COW std::string. | |
140 | struct __cow_string | |
141 | { | |
142 | union { | |
143 | const char* _M_p; | |
144 | char _M_bytes[sizeof(_M_p)]; | |
145 | std::string _M_str; | |
146 | }; | |
147 | ||
148 | __cow_string(); | |
149 | __cow_string(const std::string& s); | |
150 | __cow_string(const char*, size_t n); | |
151 | __cow_string(const __cow_string&) noexcept; | |
152 | __cow_string& operator=(const __cow_string&) noexcept; | |
153 | ~__cow_string(); | |
154 | __cow_string(__cow_string&&) noexcept; | |
155 | __cow_string& operator=(__cow_string&&) noexcept; | |
156 | }; | |
157 | ||
158 | __cow_string::__cow_string() : _M_str() { } | |
159 | ||
160 | __cow_string::__cow_string(const std::string& s) : _M_str(s) { } | |
161 | ||
162 | __cow_string::__cow_string(const char* s, size_t n) : _M_str(s, n) { } | |
163 | ||
164 | __cow_string::__cow_string(const __cow_string& s) noexcept | |
165 | : _M_str(s._M_str) { } | |
166 | ||
167 | __cow_string& | |
168 | __cow_string::operator=(const __cow_string& s) noexcept | |
169 | { | |
170 | _M_str = s._M_str; | |
171 | return *this; | |
172 | } | |
173 | ||
174 | __cow_string::~__cow_string() { _M_str.~basic_string(); } | |
175 | ||
176 | __cow_string::__cow_string(__cow_string&& s) noexcept | |
177 | : _M_str(std::move(s._M_str)) { } | |
178 | ||
179 | __cow_string& | |
180 | __cow_string::operator=(__cow_string&& s) noexcept | |
181 | { | |
182 | _M_str = std::move(s._M_str); | |
183 | return *this; | |
184 | } | |
185 | ||
186 | static_assert(sizeof(__cow_string) == sizeof(std::string), | |
187 | "sizeof(std::string) has changed"); | |
188 | static_assert(alignof(__cow_string) == alignof(std::string), | |
189 | "alignof(std::string) has changed"); | |
190 | #endif | |
191 | ||
192 | // Return error_category::message() as an SSO string | |
193 | __sso_string | |
194 | error_category::_M_message(int i) const | |
195 | { | |
196 | string msg = this->message(i); | |
197 | return {msg.c_str(), msg.length()}; | |
198 | } | |
199 | ||
200 | _GLIBCXX_END_NAMESPACE_VERSION | |
201 | } // namespace | |
a04d5fc9 TR |
202 | |
203 | // Support for the Transactional Memory TS (N4514). | |
204 | // | |
205 | // logic_error and runtime_error both carry a message in the form of a COW | |
206 | // string. This COW string is never made visible to users of the exception | |
207 | // because what() returns a C string. The COW string can be constructed as | |
208 | // either a copy of a COW string of another logic_error/runtime_error, or | |
209 | // using a C string or SSO string; thus, the COW string's _Rep is only | |
210 | // accessed by logic_error operations. We control all txnal clones of those | |
211 | // operations and thus can ensure that _Rep is never accessed transactionally. | |
212 | // Furthermore, _Rep will always have been allocated or deallocated via | |
213 | // global new or delete, so nontransactional writes we do to _Rep cannot | |
214 | // interfere with transactional accesses. | |
9585381a TR |
215 | |
216 | // We depend on having support for referencing functions declared weak that | |
217 | // are not defined by us. Without such support, the exceptions will not be | |
218 | // declared transaction-safe, so we just don't provide transactional clones | |
219 | // in this case. | |
220 | #if _GLIBCXX_USE_WEAK_REF | |
54c67432 | 221 | #ifdef _GLIBCXX_USE_C99_STDINT_TR1 |
9585381a | 222 | |
a04d5fc9 TR |
223 | extern "C" { |
224 | ||
225 | #ifndef _GLIBCXX_MANGLE_SIZE_T | |
226 | #error Mangled name of size_t type not defined. | |
227 | #endif | |
228 | #define CONCAT1(x,y) x##y | |
229 | #define CONCAT(x,y) CONCAT1(x,y) | |
230 | #define _ZGTtnaX CONCAT(_ZGTtna,_GLIBCXX_MANGLE_SIZE_T) | |
231 | ||
232 | #ifdef __i386__ | |
233 | /* Only for 32-bit x86. */ | |
234 | # define ITM_REGPARM __attribute__((regparm(2))) | |
235 | #else | |
236 | # define ITM_REGPARM | |
237 | #endif | |
238 | ||
a04d5fc9 TR |
239 | // Declare all libitm symbols we rely on, but make them weak so that we do |
240 | // not depend on libitm. | |
241 | extern void* _ZGTtnaX (size_t sz) __attribute__((weak)); | |
242 | extern void _ZGTtdlPv (void* ptr) __attribute__((weak)); | |
243 | extern uint8_t _ITM_RU1(const uint8_t *p) | |
244 | ITM_REGPARM __attribute__((weak)); | |
f68963c0 FMA |
245 | extern uint16_t _ITM_RU2(const uint16_t *p) |
246 | ITM_REGPARM __attribute__((weak)); | |
a04d5fc9 TR |
247 | extern uint32_t _ITM_RU4(const uint32_t *p) |
248 | ITM_REGPARM __attribute__((weak)); | |
249 | extern uint64_t _ITM_RU8(const uint64_t *p) | |
250 | ITM_REGPARM __attribute__((weak)); | |
251 | extern void _ITM_memcpyRtWn(void *, const void *, size_t) | |
252 | ITM_REGPARM __attribute__((weak)); | |
253 | extern void _ITM_memcpyRnWt(void *, const void *, size_t) | |
254 | ITM_REGPARM __attribute__((weak)); | |
255 | extern void _ITM_addUserCommitAction(void (*)(void *), uint64_t, void *) | |
256 | ITM_REGPARM __attribute__((weak)); | |
257 | ||
a04d5fc9 TR |
258 | } |
259 | ||
260 | // A transactional version of basic_string::basic_string(const char *s) | |
261 | // that also notifies the TM runtime about allocations belonging to this | |
262 | // exception. | |
263 | void | |
f5460595 JW |
264 | _txnal_cow_string_C1_for_exceptions(void* that, const char* s, |
265 | void *exc __attribute__((unused))) | |
a04d5fc9 TR |
266 | { |
267 | typedef std::basic_string<char> bs_type; | |
268 | bs_type *bs = (bs_type*) that; | |
269 | ||
270 | // First, do a transactional strlen, but including the trailing zero. | |
271 | bs_type::size_type len = 1; | |
272 | for (const char *ss = s; _ITM_RU1((const uint8_t*) ss) != 0; ss++, len++); | |
273 | ||
274 | ||
275 | // Allocate memory for the string and the refcount. We use the | |
276 | // transactional clone of global new[]; if this throws, it will do so in a | |
277 | // transaction-compatible way. | |
278 | // The allocation belongs to this exception, so tell the runtime about it. | |
279 | // TODO Once this is supported, link the following allocation to this | |
280 | // exception: void *prev = _ITM_setAssociatedException(exc); | |
281 | bs_type::_Rep *rep; | |
f5460595 | 282 | __try |
a04d5fc9 TR |
283 | { |
284 | rep = (bs_type::_Rep*) _ZGTtnaX (len + sizeof (bs_type::_Rep)); | |
285 | } | |
f5460595 | 286 | __catch (...) |
a04d5fc9 TR |
287 | { |
288 | // Pop the association with this exception. | |
289 | // TODO Once this is supported, link the following allocation to this | |
290 | // exception: _ITM_setAssociatedException(prev); | |
291 | // We do not need to instrument a rethrow. | |
f5460595 | 292 | __throw_exception_again; |
a04d5fc9 TR |
293 | } |
294 | // Pop the association with this exception. | |
295 | // TODO Once this is supported, link the following allocation to this | |
296 | // exception: _ITM_setAssociatedException(prev); | |
297 | ||
298 | // Now initialize the rest of the string and copy the C string. The memory | |
299 | // will be freshly allocated, so nontransactional accesses are sufficient, | |
300 | // including the writes when copying the string (see above). | |
301 | rep->_M_set_sharable(); | |
302 | rep->_M_length = rep->_M_capacity = len - 1; | |
303 | _ITM_memcpyRtWn(rep->_M_refdata(), s, len); | |
304 | new (&bs->_M_dataplus) bs_type::_Alloc_hider(rep->_M_refdata(), | |
305 | bs_type::allocator_type()); | |
306 | } | |
307 | ||
308 | static void* txnal_read_ptr(void* const * ptr) | |
309 | { | |
310 | static_assert(sizeof(uint64_t) == sizeof(void*) | |
f68963c0 FMA |
311 | || sizeof(uint32_t) == sizeof(void*) |
312 | || sizeof(uint16_t) == sizeof(void*), | |
313 | "Pointers must be 16 bits, 32 bits or 64 bits wide"); | |
a04d5fc9 TR |
314 | #if __UINTPTR_MAX__ == __UINT64_MAX__ |
315 | return (void*)_ITM_RU8((const uint64_t*)ptr); | |
f68963c0 | 316 | #elif __UINTPTR_MAX__ == __UINT32_MAX__ |
a04d5fc9 | 317 | return (void*)_ITM_RU4((const uint32_t*)ptr); |
f68963c0 FMA |
318 | #else |
319 | return (void*)_ITM_RU2((const uint16_t*)ptr); | |
a04d5fc9 TR |
320 | #endif |
321 | } | |
322 | ||
323 | // We must access the data pointer in the COW string transactionally because | |
324 | // another transaction can delete the string and reuse the memory. | |
325 | const char* | |
326 | _txnal_cow_string_c_str(const void* that) | |
327 | { | |
328 | typedef std::basic_string<char> bs_type; | |
329 | const bs_type *bs = (const bs_type*) that; | |
330 | ||
331 | return (const char*) txnal_read_ptr((void**)&bs->_M_dataplus._M_p); | |
332 | } | |
333 | ||
3d73ae6e | 334 | #if _GLIBCXX_USE_DUAL_ABI |
a04d5fc9 TR |
335 | const char* |
336 | _txnal_sso_string_c_str(const void* that) | |
337 | { | |
338 | return (const char*) txnal_read_ptr( | |
339 | (void* const*)const_cast<char* const*>( | |
340 | &((const std::__sso_string*) that)->_M_s._M_p)); | |
341 | } | |
3d73ae6e | 342 | #endif |
a04d5fc9 TR |
343 | |
344 | void | |
345 | _txnal_cow_string_D1_commit(void* data) | |
346 | { | |
347 | typedef std::basic_string<char> bs_type; | |
348 | bs_type::_Rep *rep = (bs_type::_Rep*) data; | |
349 | rep->_M_dispose(bs_type::allocator_type()); | |
350 | } | |
351 | ||
352 | void | |
353 | _txnal_cow_string_D1(void* that) | |
354 | { | |
355 | typedef std::basic_string<char> bs_type; | |
356 | bs_type::_Rep *rep = reinterpret_cast<bs_type::_Rep*>( | |
357 | const_cast<char*>(_txnal_cow_string_c_str(that))) - 1; | |
358 | ||
359 | // The string can be shared, in which case we would need to decrement the | |
360 | // reference count. We cannot undo that because we might lose the string | |
361 | // otherwise. Therefore, we register a commit action that will dispose of | |
362 | // the string's _Rep. | |
363 | enum {_ITM_noTransactionId = 1}; | |
364 | _ITM_addUserCommitAction(_txnal_cow_string_D1_commit, _ITM_noTransactionId, | |
365 | rep); | |
366 | } | |
367 | ||
368 | void* | |
369 | _txnal_logic_error_get_msg(void* e) | |
370 | { | |
371 | std::logic_error* le = (std::logic_error*) e; | |
372 | return &le->_M_msg; | |
373 | } | |
374 | ||
375 | void* | |
376 | _txnal_runtime_error_get_msg(void* e) | |
377 | { | |
378 | std::runtime_error* le = (std::runtime_error*) e; | |
379 | return &le->_M_msg; | |
380 | } | |
381 | ||
382 | // The constructors are only declared transaction-safe if the C++11 ABI is | |
383 | // used for std::string and the exception classes use a COW string internally. | |
384 | // A user must not call these constructors otherwise; if they do, it will | |
385 | // result in undefined behavior, which is in this case not initializing this | |
386 | // string. | |
387 | #if _GLIBCXX_USE_DUAL_ABI | |
3d73ae6e JW |
388 | #define CTORS_FROM_SSOSTRING(NAME, CLASS, BASE) \ |
389 | void \ | |
390 | _ZGTtNSt##NAME##C1ERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE( \ | |
391 | CLASS* that, const std::__sso_string& s) \ | |
392 | { \ | |
393 | CLASS e(""); \ | |
394 | _ITM_memcpyRnWt(that, &e, sizeof(CLASS)); \ | |
395 | /* Get the C string from the SSO string. */ \ | |
396 | _txnal_cow_string_C1_for_exceptions(_txnal_##BASE##_get_msg(that), \ | |
397 | _txnal_sso_string_c_str(&s), that); \ | |
398 | } \ | |
399 | void \ | |
400 | _ZGTtNSt##NAME##C2ERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE( \ | |
401 | CLASS*, const std::__sso_string&) __attribute__((alias \ | |
402 | ("_ZGTtNSt" #NAME \ | |
403 | "C1ERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE"))); | |
a04d5fc9 | 404 | #else |
3d73ae6e | 405 | #define CTORS_FROM_SSOSTRING(NAME, CLASS, BASE) |
a04d5fc9 TR |
406 | #endif |
407 | ||
408 | // This macro defines transaction constructors and destructors for a specific | |
409 | // exception class. NAME is the variable part of the mangled name, CLASS is | |
410 | // the class name, and BASE must be logic_error or runtime_error (which is | |
411 | // then used to call the proper friend function that can return a pointer to | |
412 | // the _M_msg member declared by the given (base) class). | |
413 | #define CTORDTOR(NAME, CLASS, BASE) \ | |
414 | void \ | |
415 | _ZGTtNSt##NAME##C1EPKc (CLASS* that, const char* s) \ | |
416 | { \ | |
417 | /* This will use the singleton _Rep for an empty string and just \ | |
418 | point to it instead of allocating memory. Thus, we can use it as \ | |
419 | source, copy it into the object we are constructing, and then \ | |
420 | construct the COW string in the latter manually. Note that the \ | |
421 | exception classes will not be declared transaction_safe if the \ | |
422 | shared empty _Rep is disabled with --enable-fully-dynamic-string \ | |
423 | (in which case _GLIBCXX_FULLY_DYNAMIC_STRING is nonzero). */ \ | |
424 | CLASS e(""); \ | |
425 | _ITM_memcpyRnWt(that, &e, sizeof(CLASS)); \ | |
426 | _txnal_cow_string_C1_for_exceptions(_txnal_##BASE##_get_msg(that), \ | |
427 | s, that); \ | |
428 | } \ | |
429 | void \ | |
430 | _ZGTtNSt##NAME##C2EPKc (CLASS*, const char*) \ | |
431 | __attribute__((alias ("_ZGTtNSt" #NAME "C1EPKc"))); \ | |
3d73ae6e | 432 | CTORS_FROM_SSOSTRING(NAME, CLASS, BASE) \ |
a04d5fc9 TR |
433 | void \ |
434 | _ZGTtNSt##NAME##D1Ev(CLASS* that) \ | |
435 | { _txnal_cow_string_D1(_txnal_##BASE##_get_msg(that)); } \ | |
436 | void \ | |
437 | _ZGTtNSt##NAME##D2Ev(CLASS*) \ | |
438 | __attribute__((alias ("_ZGTtNSt" #NAME "D1Ev"))); \ | |
439 | void \ | |
440 | _ZGTtNSt##NAME##D0Ev(CLASS* that) \ | |
441 | { \ | |
442 | _ZGTtNSt##NAME##D1Ev(that); \ | |
443 | _ZGTtdlPv(that); \ | |
444 | } | |
445 | ||
446 | // Now create all transactional constructors and destructors, as well as the | |
447 | // two virtual what() functions. | |
448 | extern "C" { | |
449 | ||
450 | CTORDTOR(11logic_error, std::logic_error, logic_error) | |
451 | ||
452 | const char* | |
453 | _ZGTtNKSt11logic_error4whatEv(const std::logic_error* that) | |
454 | { | |
455 | return _txnal_cow_string_c_str(_txnal_logic_error_get_msg( | |
456 | const_cast<std::logic_error*>(that))); | |
457 | } | |
458 | ||
459 | CTORDTOR(12domain_error, std::domain_error, logic_error) | |
460 | CTORDTOR(16invalid_argument, std::invalid_argument, logic_error) | |
461 | CTORDTOR(12length_error, std::length_error, logic_error) | |
462 | CTORDTOR(12out_of_range, std::out_of_range, logic_error) | |
463 | ||
464 | ||
465 | CTORDTOR(13runtime_error, std::runtime_error, runtime_error) | |
466 | ||
467 | const char* | |
468 | _ZGTtNKSt13runtime_error4whatEv(const std::runtime_error* that) | |
469 | { | |
470 | return _txnal_cow_string_c_str(_txnal_runtime_error_get_msg( | |
471 | const_cast<std::runtime_error*>(that))); | |
472 | } | |
473 | ||
474 | CTORDTOR(11range_error, std::range_error, runtime_error) | |
475 | CTORDTOR(14overflow_error, std::overflow_error, runtime_error) | |
476 | CTORDTOR(15underflow_error, std::underflow_error, runtime_error) | |
477 | ||
478 | } | |
9585381a | 479 | |
54c67432 | 480 | #endif // _GLIBCXX_USE_C99_STDINT_TR1 |
9585381a | 481 | #endif // _GLIBCXX_USE_WEAK_REF |