authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-07-01 16:36:40-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-07-01 16:39:29-07:00
logaa964bd555bf7d034b5bfea6275d6edddc35cb8c
tree13f5a2b3eb2704f6dfc85f26bbd0bddb07049a42
parentbd680139d084b673d1f56d0e63e01936c4680a91

update libcxxabi to llvm 14.0.6


31 files changed, 1169 insertions(+), 1185 deletions(-)

lib/libcxxabi/include/__cxxabi_config.h+2-2
......@@ -1,4 +1,4 @@
1//===-------------------------- __cxxabi_config.h -------------------------===//
1//===----------------------------------------------------------------------===//
22//
33// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
44// See https://llvm.org/LICENSE.txt for license information.
......@@ -93,7 +93,7 @@
9393# if !__has_feature(cxx_exceptions)
9494# define _LIBCXXABI_NO_EXCEPTIONS
9595# endif
96#elif defined(_LIBCXXABI_COMPILER_GCC) && !__EXCEPTIONS
96#elif defined(_LIBCXXABI_COMPILER_GCC) && !defined(__EXCEPTIONS)
9797# define _LIBCXXABI_NO_EXCEPTIONS
9898#endif
9999
lib/libcxxabi/include/cxxabi.h+1-1
......@@ -1,4 +1,4 @@
1//===--------------------------- cxxabi.h ---------------------------------===//
1//===----------------------------------------------------------------------===//
22//
33// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
44// See https://llvm.org/LICENSE.txt for license information.
lib/libcxxabi/src/abort_message.cpp+1-1
......@@ -1,4 +1,4 @@
1//===------------------------- abort_message.cpp --------------------------===//
1//===----------------------------------------------------------------------===//
22//
33// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
44// See https://llvm.org/LICENSE.txt for license information.
lib/libcxxabi/src/abort_message.h+1-1
......@@ -1,4 +1,4 @@
1//===-------------------------- abort_message.h-----------------------------===//
1//===----------------------------------------------------------------------===//
22//
33// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
44// See https://llvm.org/LICENSE.txt for license information.
lib/libcxxabi/src/cxa_aux_runtime.cpp+1-1
......@@ -1,4 +1,4 @@
1//===------------------------ cxa_aux_runtime.cpp -------------------------===//
1//===----------------------------------------------------------------------===//
22//
33// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
44// See https://llvm.org/LICENSE.txt for license information.
lib/libcxxabi/src/cxa_default_handlers.cpp+13-3
......@@ -1,11 +1,12 @@
1//===------------------------- cxa_default_handlers.cpp -------------------===//
1//===----------------------------------------------------------------------===//
22//
33// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
44// See https://llvm.org/LICENSE.txt for license information.
55// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
66//
77//
8// This file implements the default terminate_handler and unexpected_handler.
8// This file implements the default terminate_handler, unexpected_handler and
9// new_handler.
910//===----------------------------------------------------------------------===//
1011
1112#include <exception>
......@@ -15,7 +16,7 @@
1516#include "cxa_handlers.h"
1617#include "cxa_exception.h"
1718#include "private_typeinfo.h"
18#include "include/atomic_support.h"
19#include "include/atomic_support.h" // from libc++
1920
2021#if !defined(LIBCXXABI_SILENT_TERMINATE)
2122
......@@ -104,6 +105,9 @@ _LIBCPP_SAFE_STATIC std::terminate_handler __cxa_terminate_handler = default_ter
104105_LIBCXXABI_DATA_VIS
105106_LIBCPP_SAFE_STATIC std::unexpected_handler __cxa_unexpected_handler = default_unexpected_handler;
106107
108_LIBCXXABI_DATA_VIS
109_LIBCPP_SAFE_STATIC std::new_handler __cxa_new_handler = 0;
110
107111namespace std
108112{
109113
......@@ -125,4 +129,10 @@ set_terminate(terminate_handler func) noexcept
125129 _AO_Acq_Rel);
126130}
127131
132new_handler
133set_new_handler(new_handler handler) noexcept
134{
135 return __libcpp_atomic_exchange(&__cxa_new_handler, handler, _AO_Acq_Rel);
136}
137
128138}
lib/libcxxabi/src/cxa_demangle.cpp+7-7
......@@ -1,4 +1,4 @@
1//===-------------------------- cxa_demangle.cpp --------------------------===//
1//===----------------------------------------------------------------------===//
22//
33// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
44// See https://llvm.org/LICENSE.txt for license information.
......@@ -342,21 +342,21 @@ __cxa_demangle(const char *MangledName, char *Buf, size_t *N, int *Status) {
342342
343343 int InternalStatus = demangle_success;
344344 Demangler Parser(MangledName, MangledName + std::strlen(MangledName));
345 OutputStream S;
345 OutputBuffer O;
346346
347347 Node *AST = Parser.parse();
348348
349349 if (AST == nullptr)
350350 InternalStatus = demangle_invalid_mangled_name;
351 else if (!initializeOutputStream(Buf, N, S, 1024))
351 else if (!initializeOutputBuffer(Buf, N, O, 1024))
352352 InternalStatus = demangle_memory_alloc_failure;
353353 else {
354354 assert(Parser.ForwardTemplateRefs.empty());
355 AST->print(S);
356 S += '\0';
355 AST->print(O);
356 O += '\0';
357357 if (N != nullptr)
358 *N = S.getCurrentPosition();
359 Buf = S.getBuffer();
358 *N = O.getCurrentPosition();
359 Buf = O.getBuffer();
360360 }
361361
362362 if (Status)
lib/libcxxabi/src/cxa_exception.cpp+19-11
......@@ -1,4 +1,4 @@
1//===------------------------- cxa_exception.cpp --------------------------===//
1//===----------------------------------------------------------------------===//
22//
33// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
44// See https://llvm.org/LICENSE.txt for license information.
......@@ -17,7 +17,7 @@
1717#include "cxa_exception.h"
1818#include "cxa_handlers.h"
1919#include "fallback_malloc.h"
20#include "include/atomic_support.h"
20#include "include/atomic_support.h" // from libc++
2121
2222#if __has_feature(address_sanitizer)
2323#include <sanitizer/asan_interface.h>
......@@ -341,8 +341,10 @@ unwinding with _Unwind_Resume.
341341According to ARM EHABI 8.4.1, __cxa_end_cleanup() should not clobber any
342342register, thus we have to write this function in assembly so that we can save
343343{r1, r2, r3}. We don't have to save r0 because it is the return value and the
344first argument to _Unwind_Resume(). In addition, we are saving r4 in order to
345align the stack to 16 bytes, even though it is a callee-save register.
344first argument to _Unwind_Resume(). In addition, we are saving lr in order to
345align the stack to 16 bytes and lr will be used to identify the caller and its
346frame information. _Unwind_Resume never return and we need to keep the original
347lr so just branch to it.
346348*/
347349__attribute__((used)) static _Unwind_Exception *
348350__cxa_end_cleanup_impl()
......@@ -372,18 +374,24 @@ __cxa_end_cleanup_impl()
372374 return &exception_header->unwindHeader;
373375}
374376
375asm (
376 " .pushsection .text.__cxa_end_cleanup,\"ax\",%progbits\n"
377asm(" .pushsection .text.__cxa_end_cleanup,\"ax\",%progbits\n"
377378 " .globl __cxa_end_cleanup\n"
378379 " .type __cxa_end_cleanup,%function\n"
379380 "__cxa_end_cleanup:\n"
380 " push {r1, r2, r3, r4}\n"
381#if defined(__ARM_FEATURE_BTI_DEFAULT)
382 " bti\n"
383#endif
384 " push {r1, r2, r3, lr}\n"
381385 " bl __cxa_end_cleanup_impl\n"
382386 " pop {r1, r2, r3, r4}\n"
383 " bl _Unwind_Resume\n"
384 " bl abort\n"
385 " .popsection"
386);
387 " mov lr, r4\n"
388#if defined(LIBCXXABI_BAREMETAL)
389 " ldr r4, =_Unwind_Resume\n"
390 " bx r4\n"
391#else
392 " b _Unwind_Resume\n"
393#endif
394 " .popsection");
387395#endif // defined(_LIBCXXABI_ARM_EHABI)
388396
389397/*
lib/libcxxabi/src/cxa_exception.h+1-1
......@@ -1,4 +1,4 @@
1//===------------------------- cxa_exception.h ----------------------------===//
1//===----------------------------------------------------------------------===//
22//
33// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
44// See https://llvm.org/LICENSE.txt for license information.
lib/libcxxabi/src/cxa_exception_storage.cpp+34-36
......@@ -1,4 +1,4 @@
1//===--------------------- cxa_exception_storage.cpp ----------------------===//
1//===----------------------------------------------------------------------===//
22//
33// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
44// See https://llvm.org/LICENSE.txt for license information.
......@@ -21,25 +21,24 @@ extern "C" {
2121 static __cxa_eh_globals eh_globals;
2222 __cxa_eh_globals *__cxa_get_globals() { return &eh_globals; }
2323 __cxa_eh_globals *__cxa_get_globals_fast() { return &eh_globals; }
24 }
25}
24} // extern "C"
25} // namespace __cxxabiv1
2626
2727#elif defined(HAS_THREAD_LOCAL)
2828
2929namespace __cxxabiv1 {
30
3130namespace {
32 __cxa_eh_globals * __globals () {
31 __cxa_eh_globals *__globals() {
3332 static thread_local __cxa_eh_globals eh_globals;
3433 return &eh_globals;
35 }
3634 }
35} // namespace
3736
3837extern "C" {
39 __cxa_eh_globals * __cxa_get_globals () { return __globals (); }
40 __cxa_eh_globals * __cxa_get_globals_fast () { return __globals (); }
41 }
42}
38 __cxa_eh_globals *__cxa_get_globals() { return __globals(); }
39 __cxa_eh_globals *__cxa_get_globals_fast() { return __globals(); }
40} // extern "C"
41} // namespace __cxxabiv1
4342
4443#else
4544
......@@ -59,47 +58,46 @@ namespace {
5958 std::__libcpp_tls_key key_;
6059 std::__libcpp_exec_once_flag flag_ = _LIBCPP_EXEC_ONCE_INITIALIZER;
6160
62 void _LIBCPP_TLS_DESTRUCTOR_CC destruct_ (void *p) {
63 __free_with_fallback ( p );
64 if ( 0 != std::__libcpp_tls_set ( key_, NULL ) )
61 void _LIBCPP_TLS_DESTRUCTOR_CC destruct_(void *p) {
62 __free_with_fallback(p);
63 if (0 != std::__libcpp_tls_set(key_, NULL))
6564 abort_message("cannot zero out thread value for __cxa_get_globals()");
66 }
65 }
6766
68 void construct_ () {
69 if ( 0 != std::__libcpp_tls_create ( &key_, destruct_ ) )
67 void construct_() {
68 if (0 != std::__libcpp_tls_create(&key_, destruct_))
7069 abort_message("cannot create thread specific key for __cxa_get_globals()");
71 }
72}
70 }
71} // namespace
7372
7473extern "C" {
75 __cxa_eh_globals * __cxa_get_globals () {
76 // Try to get the globals for this thread
77 __cxa_eh_globals* retVal = __cxa_get_globals_fast ();
78
79 // If this is the first time we've been asked for these globals, create them
80 if ( NULL == retVal ) {
81 retVal = static_cast<__cxa_eh_globals*>
82 (__calloc_with_fallback (1, sizeof (__cxa_eh_globals)));
83 if ( NULL == retVal )
74 __cxa_eh_globals *__cxa_get_globals() {
75 // Try to get the globals for this thread
76 __cxa_eh_globals *retVal = __cxa_get_globals_fast();
77
78 // If this is the first time we've been asked for these globals, create them
79 if (NULL == retVal) {
80 retVal = static_cast<__cxa_eh_globals*>(
81 __calloc_with_fallback(1, sizeof(__cxa_eh_globals)));
82 if (NULL == retVal)
8483 abort_message("cannot allocate __cxa_eh_globals");
85 if ( 0 != std::__libcpp_tls_set ( key_, retVal ) )
84 if (0 != std::__libcpp_tls_set(key_, retVal))
8685 abort_message("std::__libcpp_tls_set failure in __cxa_get_globals()");
87 }
88 return retVal;
8986 }
87 return retVal;
88 }
9089
9190 // Note that this implementation will reliably return NULL if not
9291 // preceded by a call to __cxa_get_globals(). This is an extension
9392 // to the Itanium ABI and is taken advantage of in several places in
9493 // libc++abi.
95 __cxa_eh_globals * __cxa_get_globals_fast () {
96 // First time through, create the key.
94 __cxa_eh_globals *__cxa_get_globals_fast() {
95 // First time through, create the key.
9796 if (0 != std::__libcpp_execute_once(&flag_, construct_))
9897 abort_message("execute once failure in __cxa_get_globals_fast()");
99// static int init = construct_();
10098 return static_cast<__cxa_eh_globals*>(std::__libcpp_tls_get(key_));
101 }
99 }
100} // extern "C"
101} // namespace __cxxabiv1
102102
103}
104}
105103#endif
lib/libcxxabi/src/cxa_guard.cpp+1-1
......@@ -1,4 +1,4 @@
1//===---------------------------- cxa_guard.cpp ---------------------------===//
1//===----------------------------------------------------------------------===//
22//
33// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
44// See https://llvm.org/LICENSE.txt for license information.
lib/libcxxabi/src/cxa_guard_impl.h+260-182
......@@ -23,9 +23,15 @@
2323 * the thread currently performing initialization is stored in the second word.
2424 *
2525 * Guard Object Layout:
26 * -------------------------------------------------------------------------
27 * |a: guard byte | a+1: init byte | a+2 : unused ... | a+4: thread-id ... |
28 * ------------------------------------------------------------------------
26 * ---------------------------------------------------------------------------
27 * | a+0: guard byte | a+1: init byte | a+2: unused ... | a+4: thread-id ... |
28 * ---------------------------------------------------------------------------
29 *
30 * Note that we don't do what the ABI docs suggest (put a mutex in the guard
31 * object which we acquire in cxa_guard_acquire and release in
32 * cxa_guard_release). Instead we use the init byte to imitate that behaviour,
33 * but without actually holding anything mutex related between aquire and
34 * release/abort.
2935 *
3036 * Access Protocol:
3137 * For each implementation the guard byte is checked and set before accessing
......@@ -38,28 +44,31 @@
3844 */
3945
4046#include "__cxxabi_config.h"
41#include "include/atomic_support.h"
42#include <unistd.h>
47#include "include/atomic_support.h" // from libc++
4348#if defined(__has_include)
44# if __has_include(<sys/syscall.h>)
45# include <sys/syscall.h>
46# endif
49# if __has_include(<sys/syscall.h>)
50# include <sys/syscall.h>
51# endif
52# if __has_include(<unistd.h>)
53# include <unistd.h>
54# endif
4755#endif
4856
57#include <limits.h>
4958#include <stdlib.h>
5059#include <__threading_support>
5160#ifndef _LIBCXXABI_HAS_NO_THREADS
52#if defined(__ELF__) && defined(_LIBCXXABI_LINK_PTHREAD_LIB)
53#pragma comment(lib, "pthread")
54#endif
61# if defined(__ELF__) && defined(_LIBCXXABI_LINK_PTHREAD_LIB)
62# pragma comment(lib, "pthread")
63# endif
5564#endif
5665
5766#if defined(__clang__)
58# pragma clang diagnostic push
59# pragma clang diagnostic ignored "-Wtautological-pointer-compare"
67# pragma clang diagnostic push
68# pragma clang diagnostic ignored "-Wtautological-pointer-compare"
6069#elif defined(__GNUC__)
61# pragma GCC diagnostic push
62# pragma GCC diagnostic ignored "-Waddress"
70# pragma GCC diagnostic push
71# pragma GCC diagnostic ignored "-Waddress"
6372#endif
6473
6574// To make testing possible, this header is included from both cxa_guard.cpp
......@@ -74,20 +83,20 @@
7483// defined when including this file. Only `src/cxa_guard.cpp` should define
7584// the former.
7685#ifdef BUILDING_CXA_GUARD
77# include "abort_message.h"
78# define ABORT_WITH_MESSAGE(...) ::abort_message(__VA_ARGS__)
86# include "abort_message.h"
87# define ABORT_WITH_MESSAGE(...) ::abort_message(__VA_ARGS__)
7988#elif defined(TESTING_CXA_GUARD)
80# define ABORT_WITH_MESSAGE(...) ::abort()
89# define ABORT_WITH_MESSAGE(...) ::abort()
8190#else
82# error "Either BUILDING_CXA_GUARD or TESTING_CXA_GUARD must be defined"
91# error "Either BUILDING_CXA_GUARD or TESTING_CXA_GUARD must be defined"
8392#endif
8493
8594#if __has_feature(thread_sanitizer)
8695extern "C" void __tsan_acquire(void*);
8796extern "C" void __tsan_release(void*);
8897#else
89#define __tsan_acquire(addr) ((void)0)
90#define __tsan_release(addr) ((void)0)
98# define __tsan_acquire(addr) ((void)0)
99# define __tsan_release(addr) ((void)0)
91100#endif
92101
93102namespace __cxxabiv1 {
......@@ -99,7 +108,7 @@ namespace {
99108// Misc Utilities
100109//===----------------------------------------------------------------------===//
101110
102template <class T, T(*Init)()>
111template <class T, T (*Init)()>
103112struct LazyValue {
104113 LazyValue() : is_init(false) {}
105114
......@@ -110,7 +119,8 @@ struct LazyValue {
110119 }
111120 return value;
112121 }
113 private:
122
123private:
114124 T value;
115125 bool is_init = false;
116126};
......@@ -120,25 +130,19 @@ class AtomicInt {
120130public:
121131 using MemoryOrder = std::__libcpp_atomic_order;
122132
123 explicit AtomicInt(IntType *b) : b_(b) {}
133 explicit AtomicInt(IntType* b) : b_(b) {}
124134 AtomicInt(AtomicInt const&) = delete;
125135 AtomicInt& operator=(AtomicInt const&) = delete;
126136
127 IntType load(MemoryOrder ord) {
128 return std::__libcpp_atomic_load(b_, ord);
129 }
130 void store(IntType val, MemoryOrder ord) {
131 std::__libcpp_atomic_store(b_, val, ord);
132 }
133 IntType exchange(IntType new_val, MemoryOrder ord) {
134 return std::__libcpp_atomic_exchange(b_, new_val, ord);
135 }
136 bool compare_exchange(IntType *expected, IntType desired, MemoryOrder ord_success, MemoryOrder ord_failure) {
137 IntType load(MemoryOrder ord) { return std::__libcpp_atomic_load(b_, ord); }
138 void store(IntType val, MemoryOrder ord) { std::__libcpp_atomic_store(b_, val, ord); }
139 IntType exchange(IntType new_val, MemoryOrder ord) { return std::__libcpp_atomic_exchange(b_, new_val, ord); }
140 bool compare_exchange(IntType* expected, IntType desired, MemoryOrder ord_success, MemoryOrder ord_failure) {
137141 return std::__libcpp_atomic_compare_exchange(b_, expected, desired, ord_success, ord_failure);
138142 }
139143
140144private:
141 IntType *b_;
145 IntType* b_;
142146};
143147
144148//===----------------------------------------------------------------------===//
......@@ -148,8 +152,7 @@ private:
148152#if defined(__APPLE__) && defined(_LIBCPP_HAS_THREAD_API_PTHREAD)
149153uint32_t PlatformThreadID() {
150154 static_assert(sizeof(mach_port_t) == sizeof(uint32_t), "");
151 return static_cast<uint32_t>(
152 pthread_mach_thread_np(std::__libcpp_thread_get_current_id()));
155 return static_cast<uint32_t>(pthread_mach_thread_np(std::__libcpp_thread_get_current_id()));
153156}
154157#elif defined(SYS_gettid) && defined(_LIBCPP_HAS_THREAD_API_PTHREAD)
155158uint32_t PlatformThreadID() {
......@@ -160,99 +163,108 @@ uint32_t PlatformThreadID() {
160163constexpr uint32_t (*PlatformThreadID)() = nullptr;
161164#endif
162165
163
164constexpr bool PlatformSupportsThreadID() {
165 return +PlatformThreadID != nullptr;
166}
167
168166//===----------------------------------------------------------------------===//
169// GuardBase
167// GuardByte
170168//===----------------------------------------------------------------------===//
171169
172enum class AcquireResult {
173 INIT_IS_DONE,
174 INIT_IS_PENDING,
175};
176constexpr AcquireResult INIT_IS_DONE = AcquireResult::INIT_IS_DONE;
177constexpr AcquireResult INIT_IS_PENDING = AcquireResult::INIT_IS_PENDING;
178
179170static constexpr uint8_t UNSET = 0;
180171static constexpr uint8_t COMPLETE_BIT = (1 << 0);
181172static constexpr uint8_t PENDING_BIT = (1 << 1);
182173static constexpr uint8_t WAITING_BIT = (1 << 2);
183174
184template <class Derived>
185struct GuardObject {
186 GuardObject() = delete;
187 GuardObject(GuardObject const&) = delete;
188 GuardObject& operator=(GuardObject const&) = delete;
175/// Manages reads and writes to the guard byte.
176struct GuardByte {
177 GuardByte() = delete;
178 GuardByte(GuardByte const&) = delete;
179 GuardByte& operator=(GuardByte const&) = delete;
189180
190 explicit GuardObject(uint32_t* g)
191 : base_address(g), guard_byte_address(reinterpret_cast<uint8_t*>(g)),
192 init_byte_address(reinterpret_cast<uint8_t*>(g) + 1),
193 thread_id_address(nullptr) {}
194
195 explicit GuardObject(uint64_t* g)
196 : base_address(g), guard_byte_address(reinterpret_cast<uint8_t*>(g)),
197 init_byte_address(reinterpret_cast<uint8_t*>(g) + 1),
198 thread_id_address(reinterpret_cast<uint32_t*>(g) + 1) {}
181 explicit GuardByte(uint8_t* const guard_byte_address) : guard_byte(guard_byte_address) {}
199182
200183public:
201 /// Implements __cxa_guard_acquire
202 AcquireResult cxa_guard_acquire() {
203 AtomicInt<uint8_t> guard_byte(guard_byte_address);
204 if (guard_byte.load(std::_AO_Acquire) != UNSET)
205 return INIT_IS_DONE;
206 return derived()->acquire_init_byte();
207 }
208
209 /// Implements __cxa_guard_release
210 void cxa_guard_release() {
211 AtomicInt<uint8_t> guard_byte(guard_byte_address);
212 // Store complete first, so that when release wakes other folks, they see
213 // it as having been completed.
214 guard_byte.store(COMPLETE_BIT, std::_AO_Release);
215 derived()->release_init_byte();
184 /// The guard byte portion of cxa_guard_acquire. Returns true if
185 /// initialization has already been completed.
186 bool acquire() {
187 // if guard_byte is non-zero, we have already completed initialization
188 // (i.e. release has been called)
189 return guard_byte.load(std::_AO_Acquire) != UNSET;
216190 }
217191
218 /// Implements __cxa_guard_abort
219 void cxa_guard_abort() { derived()->abort_init_byte(); }
192 /// The guard byte portion of cxa_guard_release.
193 void release() { guard_byte.store(COMPLETE_BIT, std::_AO_Release); }
220194
221public:
222 /// base_address - the address of the original guard object.
223 void* const base_address;
224 /// The address of the guard byte at offset 0.
225 uint8_t* const guard_byte_address;
226 /// The address of the byte used by the implementation during initialization.
227 uint8_t* const init_byte_address;
228 /// An optional address storing an identifier for the thread performing initialization.
229 /// It's used to detect recursive initialization.
230 uint32_t* const thread_id_address;
195 /// The guard byte portion of cxa_guard_abort.
196 void abort() {} // Nothing to do
231197
232198private:
233 Derived* derived() { return static_cast<Derived*>(this); }
199 AtomicInt<uint8_t> guard_byte;
234200};
235201
202//===----------------------------------------------------------------------===//
203// InitByte Implementations
204//===----------------------------------------------------------------------===//
205//
206// Each initialization byte implementation supports the following methods:
207//
208// InitByte(uint8_t* _init_byte_address, uint32_t* _thread_id_address)
209// Construct the InitByte object, initializing our member variables
210//
211// bool acquire()
212// Called before we start the initialization. Check if someone else has already started, and if
213// not to signal our intent to start it ourselves. We determine the current status from the init
214// byte, which is one of 4 possible values:
215// COMPLETE: Initialization was finished by somebody else. Return true.
216// PENDING: Somebody has started the initialization already, set the WAITING bit,
217// then wait for the init byte to get updated with a new value.
218// (PENDING|WAITING): Somebody has started the initialization already, and we're not the
219// first one waiting. Wait for the init byte to get updated.
220// UNSET: Initialization hasn't successfully completed, and nobody is currently
221// performing the initialization. Set the PENDING bit to indicate our
222// intention to start the initialization, and return false.
223// The return value indicates whether initialization has already been completed.
224//
225// void release()
226// Called after successfully completing the initialization. Update the init byte to reflect
227// that, then if anybody else is waiting, wake them up.
228//
229// void abort()
230// Called after an error is thrown during the initialization. Reset the init byte to UNSET to
231// indicate that we're no longer performing the initialization, then if anybody is waiting, wake
232// them up so they can try performing the initialization.
233//
234
236235//===----------------------------------------------------------------------===//
237236// Single Threaded Implementation
238237//===----------------------------------------------------------------------===//
239238
240struct InitByteNoThreads : GuardObject<InitByteNoThreads> {
241 using GuardObject::GuardObject;
239/// InitByteNoThreads - Doesn't use any inter-thread synchronization when
240/// managing reads and writes to the init byte.
241struct InitByteNoThreads {
242 InitByteNoThreads() = delete;
243 InitByteNoThreads(InitByteNoThreads const&) = delete;
244 InitByteNoThreads& operator=(InitByteNoThreads const&) = delete;
242245
243 AcquireResult acquire_init_byte() {
246 explicit InitByteNoThreads(uint8_t* _init_byte_address, uint32_t*) : init_byte_address(_init_byte_address) {}
247
248 /// The init byte portion of cxa_guard_acquire. Returns true if
249 /// initialization has already been completed.
250 bool acquire() {
244251 if (*init_byte_address == COMPLETE_BIT)
245 return INIT_IS_DONE;
252 return true;
246253 if (*init_byte_address & PENDING_BIT)
247254 ABORT_WITH_MESSAGE("__cxa_guard_acquire detected recursive initialization");
248255 *init_byte_address = PENDING_BIT;
249 return INIT_IS_PENDING;
256 return false;
250257 }
251258
252 void release_init_byte() { *init_byte_address = COMPLETE_BIT; }
253 void abort_init_byte() { *init_byte_address = UNSET; }
254};
259 /// The init byte portion of cxa_guard_release.
260 void release() { *init_byte_address = COMPLETE_BIT; }
261 /// The init byte portion of cxa_guard_abort.
262 void abort() { *init_byte_address = UNSET; }
255263
264private:
265 /// The address of the byte used during initialization.
266 uint8_t* const init_byte_address;
267};
256268
257269//===----------------------------------------------------------------------===//
258270// Global Mutex Implementation
......@@ -280,9 +292,7 @@ struct LibcppCondVar {
280292 LibcppCondVar(LibcppCondVar const&) = delete;
281293 LibcppCondVar& operator=(LibcppCondVar const&) = delete;
282294
283 bool wait(LibcppMutex& mut) {
284 return std::__libcpp_condvar_wait(&cond, &mut.mutex);
285 }
295 bool wait(LibcppMutex& mut) { return std::__libcpp_condvar_wait(&cond, &mut.mutex); }
286296 bool broadcast() { return std::__libcpp_condvar_broadcast(&cond); }
287297
288298private:
......@@ -293,28 +303,25 @@ struct LibcppMutex {};
293303struct LibcppCondVar {};
294304#endif // !defined(_LIBCXXABI_HAS_NO_THREADS)
295305
296
306/// InitByteGlobalMutex - Uses a global mutex and condition variable (common to
307/// all static local variables) to manage reads and writes to the init byte.
297308template <class Mutex, class CondVar, Mutex& global_mutex, CondVar& global_cond,
298309 uint32_t (*GetThreadID)() = PlatformThreadID>
299struct InitByteGlobalMutex
300 : GuardObject<InitByteGlobalMutex<Mutex, CondVar, global_mutex, global_cond,
301 GetThreadID>> {
302
303 using BaseT = typename InitByteGlobalMutex::GuardObject;
304 using BaseT::BaseT;
310struct InitByteGlobalMutex {
305311
306 explicit InitByteGlobalMutex(uint32_t *g)
307 : BaseT(g), has_thread_id_support(false) {}
308 explicit InitByteGlobalMutex(uint64_t *g)
309 : BaseT(g), has_thread_id_support(PlatformSupportsThreadID()) {}
312 explicit InitByteGlobalMutex(uint8_t* _init_byte_address, uint32_t* _thread_id_address)
313 : init_byte_address(_init_byte_address), thread_id_address(_thread_id_address),
314 has_thread_id_support(_thread_id_address != nullptr && GetThreadID != nullptr) {}
310315
311316public:
312 AcquireResult acquire_init_byte() {
317 /// The init byte portion of cxa_guard_acquire. Returns true if
318 /// initialization has already been completed.
319 bool acquire() {
313320 LockGuard g("__cxa_guard_acquire");
314321 // Check for possible recursive initialization.
315322 if (has_thread_id_support && (*init_byte_address & PENDING_BIT)) {
316323 if (*thread_id_address == current_thread_id.get())
317 ABORT_WITH_MESSAGE("__cxa_guard_acquire detected recursive initialization");
324 ABORT_WITH_MESSAGE("__cxa_guard_acquire detected recursive initialization");
318325 }
319326
320327 // Wait until the pending bit is not set.
......@@ -324,16 +331,17 @@ public:
324331 }
325332
326333 if (*init_byte_address == COMPLETE_BIT)
327 return INIT_IS_DONE;
334 return true;
328335
329336 if (has_thread_id_support)
330337 *thread_id_address = current_thread_id.get();
331338
332339 *init_byte_address = PENDING_BIT;
333 return INIT_IS_PENDING;
340 return false;
334341 }
335342
336 void release_init_byte() {
343 /// The init byte portion of cxa_guard_release.
344 void release() {
337345 bool has_waiting;
338346 {
339347 LockGuard g("__cxa_guard_release");
......@@ -347,7 +355,8 @@ public:
347355 }
348356 }
349357
350 void abort_init_byte() {
358 /// The init byte portion of cxa_guard_abort.
359 void abort() {
351360 bool has_waiting;
352361 {
353362 LockGuard g("__cxa_guard_abort");
......@@ -364,8 +373,12 @@ public:
364373 }
365374
366375private:
367 using BaseT::init_byte_address;
368 using BaseT::thread_id_address;
376 /// The address of the byte used during initialization.
377 uint8_t* const init_byte_address;
378 /// An optional address storing an identifier for the thread performing initialization.
379 /// It's used to detect recursive initialization.
380 uint32_t* const thread_id_address;
381
369382 const bool has_thread_id_support;
370383 LazyValue<uint32_t, GetThreadID> current_thread_id;
371384
......@@ -375,8 +388,7 @@ private:
375388 LockGuard(LockGuard const&) = delete;
376389 LockGuard& operator=(LockGuard const&) = delete;
377390
378 explicit LockGuard(const char* calling_func)
379 : calling_func_(calling_func) {
391 explicit LockGuard(const char* calling_func) : calling_func_(calling_func) {
380392 if (global_mutex.lock())
381393 ABORT_WITH_MESSAGE("%s failed to acquire mutex", calling_func_);
382394 }
......@@ -411,50 +423,40 @@ constexpr void (*PlatformFutexWait)(int*, int) = nullptr;
411423constexpr void (*PlatformFutexWake)(int*) = nullptr;
412424#endif
413425
414constexpr bool PlatformSupportsFutex() {
415 return +PlatformFutexWait != nullptr;
416}
426constexpr bool PlatformSupportsFutex() { return +PlatformFutexWait != nullptr; }
417427
418/// InitByteFutex - Manages initialization using atomics and the futex syscall
419/// for waiting and waking.
420template <void (*Wait)(int*, int) = PlatformFutexWait,
421 void (*Wake)(int*) = PlatformFutexWake,
428/// InitByteFutex - Uses a futex to manage reads and writes to the init byte.
429template <void (*Wait)(int*, int) = PlatformFutexWait, void (*Wake)(int*) = PlatformFutexWake,
422430 uint32_t (*GetThreadIDArg)() = PlatformThreadID>
423struct InitByteFutex : GuardObject<InitByteFutex<Wait, Wake, GetThreadIDArg>> {
424 using BaseT = typename InitByteFutex::GuardObject;
425
426 /// ARM Constructor
427 explicit InitByteFutex(uint32_t *g) : BaseT(g),
428 init_byte(this->init_byte_address),
429 has_thread_id_support(this->thread_id_address && GetThreadIDArg),
430 thread_id(this->thread_id_address) {}
431struct InitByteFutex {
431432
432 /// Itanium Constructor
433 explicit InitByteFutex(uint64_t *g) : BaseT(g),
434 init_byte(this->init_byte_address),
435 has_thread_id_support(this->thread_id_address && GetThreadIDArg),
436 thread_id(this->thread_id_address) {}
433 explicit InitByteFutex(uint8_t* _init_byte_address, uint32_t* _thread_id_address)
434 : init_byte(_init_byte_address),
435 has_thread_id_support(_thread_id_address != nullptr && GetThreadIDArg != nullptr),
436 thread_id(_thread_id_address),
437 base_address(reinterpret_cast<int*>(/*_init_byte_address & ~0x3*/ _init_byte_address - 1)) {}
437438
438439public:
439 AcquireResult acquire_init_byte() {
440 /// The init byte portion of cxa_guard_acquire. Returns true if
441 /// initialization has already been completed.
442 bool acquire() {
440443 while (true) {
441444 uint8_t last_val = UNSET;
442 if (init_byte.compare_exchange(&last_val, PENDING_BIT, std::_AO_Acq_Rel,
443 std::_AO_Acquire)) {
445 if (init_byte.compare_exchange(&last_val, PENDING_BIT, std::_AO_Acq_Rel, std::_AO_Acquire)) {
444446 if (has_thread_id_support) {
445447 thread_id.store(current_thread_id.get(), std::_AO_Relaxed);
446448 }
447 return INIT_IS_PENDING;
449 return false;
448450 }
449451
450452 if (last_val == COMPLETE_BIT)
451 return INIT_IS_DONE;
453 return true;
452454
453455 if (last_val & PENDING_BIT) {
454456
455457 // Check for recursive initialization
456458 if (has_thread_id_support && thread_id.load(std::_AO_Relaxed) == current_thread_id.get()) {
457 ABORT_WITH_MESSAGE("__cxa_guard_acquire detected recursive initialization");
459 ABORT_WITH_MESSAGE("__cxa_guard_acquire detected recursive initialization");
458460 }
459461
460462 if ((last_val & WAITING_BIT) == 0) {
......@@ -462,11 +464,10 @@ public:
462464 // (1) another thread finished the whole thing before we got here
463465 // (2) another thread set the waiting bit we were trying to thread
464466 // (3) another thread had an exception and failed to finish
465 if (!init_byte.compare_exchange(&last_val, PENDING_BIT | WAITING_BIT,
466 std::_AO_Acq_Rel, std::_AO_Release)) {
467 if (!init_byte.compare_exchange(&last_val, PENDING_BIT | WAITING_BIT, std::_AO_Acq_Rel, std::_AO_Release)) {
467468 // (1) success, via someone else's work!
468469 if (last_val == COMPLETE_BIT)
469 return INIT_IS_DONE;
470 return true;
470471
471472 // (3) someone else, bailed on doing the work, retry from the start!
472473 if (last_val == UNSET)
......@@ -480,30 +481,30 @@ public:
480481 }
481482 }
482483
483 void release_init_byte() {
484 /// The init byte portion of cxa_guard_release.
485 void release() {
484486 uint8_t old = init_byte.exchange(COMPLETE_BIT, std::_AO_Acq_Rel);
485487 if (old & WAITING_BIT)
486488 wake_all();
487489 }
488490
489 void abort_init_byte() {
491 /// The init byte portion of cxa_guard_abort.
492 void abort() {
490493 if (has_thread_id_support)
491494 thread_id.store(0, std::_AO_Relaxed);
492495
493 uint8_t old = init_byte.exchange(0, std::_AO_Acq_Rel);
496 uint8_t old = init_byte.exchange(UNSET, std::_AO_Acq_Rel);
494497 if (old & WAITING_BIT)
495498 wake_all();
496499 }
497500
498501private:
499502 /// Use the futex to wait on the current guard variable. Futex expects a
500 /// 32-bit 4-byte aligned address as the first argument, so we have to use use
501 /// the base address of the guard variable (not the init byte).
502 void wait_on_initialization() {
503 Wait(static_cast<int*>(this->base_address),
504 expected_value_for_futex(PENDING_BIT | WAITING_BIT));
505 }
506 void wake_all() { Wake(static_cast<int*>(this->base_address)); }
503 /// 32-bit 4-byte aligned address as the first argument, so we use the 4-byte
504 /// aligned address that encompasses the init byte (i.e. the address of the
505 /// raw guard object that was passed to __cxa_guard_acquire/release/abort).
506 void wait_on_initialization() { Wait(base_address, expected_value_for_futex(PENDING_BIT | WAITING_BIT)); }
507 void wake_all() { Wake(base_address); }
507508
508509private:
509510 AtomicInt<uint8_t> init_byte;
......@@ -513,6 +514,10 @@ private:
513514 AtomicInt<uint32_t> thread_id;
514515 LazyValue<uint32_t, GetThreadIDArg> current_thread_id;
515516
517 /// the 4-byte-aligned address that encompasses the init byte (i.e. the
518 /// address of the raw guard object).
519 int* const base_address;
520
516521 /// Create the expected integer value for futex `wait(int* addr, int expected)`.
517522 /// We pass the base address as the first argument, So this function creates
518523 /// an zero-initialized integer with `b` copied at the correct offset.
......@@ -525,6 +530,86 @@ private:
525530 static_assert(Wait != nullptr && Wake != nullptr, "");
526531};
527532
533//===----------------------------------------------------------------------===//
534// GuardObject
535//===----------------------------------------------------------------------===//
536
537enum class AcquireResult {
538 INIT_IS_DONE,
539 INIT_IS_PENDING,
540};
541constexpr AcquireResult INIT_IS_DONE = AcquireResult::INIT_IS_DONE;
542constexpr AcquireResult INIT_IS_PENDING = AcquireResult::INIT_IS_PENDING;
543
544/// Co-ordinates between GuardByte and InitByte.
545template <class InitByteT>
546struct GuardObject {
547 GuardObject() = delete;
548 GuardObject(GuardObject const&) = delete;
549 GuardObject& operator=(GuardObject const&) = delete;
550
551private:
552 GuardByte guard_byte;
553 InitByteT init_byte;
554
555public:
556 /// ARM Constructor
557 explicit GuardObject(uint32_t* raw_guard_object)
558 : guard_byte(reinterpret_cast<uint8_t*>(raw_guard_object)),
559 init_byte(reinterpret_cast<uint8_t*>(raw_guard_object) + 1, nullptr) {}
560
561 /// Itanium Constructor
562 explicit GuardObject(uint64_t* raw_guard_object)
563 : guard_byte(reinterpret_cast<uint8_t*>(raw_guard_object)),
564 init_byte(reinterpret_cast<uint8_t*>(raw_guard_object) + 1, reinterpret_cast<uint32_t*>(raw_guard_object) + 1) {
565 }
566
567 /// Implements __cxa_guard_acquire.
568 AcquireResult cxa_guard_acquire() {
569 // Use short-circuit evaluation to avoid calling init_byte.acquire when
570 // guard_byte.acquire returns true. (i.e. don't call it when we know from
571 // the guard byte that initialization has already been completed)
572 if (guard_byte.acquire() || init_byte.acquire())
573 return INIT_IS_DONE;
574 return INIT_IS_PENDING;
575 }
576
577 /// Implements __cxa_guard_release.
578 void cxa_guard_release() {
579 // Update guard byte first, so if somebody is woken up by init_byte.release
580 // and comes all the way back around to __cxa_guard_acquire again, they see
581 // it as having completed initialization.
582 guard_byte.release();
583 init_byte.release();
584 }
585
586 /// Implements __cxa_guard_abort.
587 void cxa_guard_abort() {
588 guard_byte.abort();
589 init_byte.abort();
590 }
591};
592
593//===----------------------------------------------------------------------===//
594// Convenience Classes
595//===----------------------------------------------------------------------===//
596
597/// NoThreadsGuard - Manages initialization without performing any inter-thread
598/// synchronization.
599using NoThreadsGuard = GuardObject<InitByteNoThreads>;
600
601/// GlobalMutexGuard - Manages initialization using a global mutex and
602/// condition variable.
603template <class Mutex, class CondVar, Mutex& global_mutex, CondVar& global_cond,
604 uint32_t (*GetThreadID)() = PlatformThreadID>
605using GlobalMutexGuard = GuardObject<InitByteGlobalMutex<Mutex, CondVar, global_mutex, global_cond, GetThreadID>>;
606
607/// FutexGuard - Manages initialization using atomics and the futex syscall for
608/// waiting and waking.
609template <void (*Wait)(int*, int) = PlatformFutexWait, void (*Wake)(int*) = PlatformFutexWake,
610 uint32_t (*GetThreadIDArg)() = PlatformThreadID>
611using FutexGuard = GuardObject<InitByteFutex<Wait, Wake, GetThreadIDArg>>;
612
528613//===----------------------------------------------------------------------===//
529614//
530615//===----------------------------------------------------------------------===//
......@@ -536,31 +621,25 @@ struct GlobalStatic {
536621template <class T>
537622_LIBCPP_SAFE_STATIC T GlobalStatic<T>::instance = {};
538623
539enum class Implementation {
540 NoThreads,
541 GlobalLock,
542 Futex
543};
624enum class Implementation { NoThreads, GlobalMutex, Futex };
544625
545626template <Implementation Impl>
546627struct SelectImplementation;
547628
548629template <>
549630struct SelectImplementation<Implementation::NoThreads> {
550 using type = InitByteNoThreads;
631 using type = NoThreadsGuard;
551632};
552633
553634template <>
554struct SelectImplementation<Implementation::GlobalLock> {
555 using type = InitByteGlobalMutex<
556 LibcppMutex, LibcppCondVar, GlobalStatic<LibcppMutex>::instance,
557 GlobalStatic<LibcppCondVar>::instance, PlatformThreadID>;
635struct SelectImplementation<Implementation::GlobalMutex> {
636 using type = GlobalMutexGuard<LibcppMutex, LibcppCondVar, GlobalStatic<LibcppMutex>::instance,
637 GlobalStatic<LibcppCondVar>::instance, PlatformThreadID>;
558638};
559639
560640template <>
561641struct SelectImplementation<Implementation::Futex> {
562 using type =
563 InitByteFutex<PlatformFutexWait, PlatformFutexWake, PlatformThreadID>;
642 using type = FutexGuard<PlatformFutexWait, PlatformFutexWake, PlatformThreadID>;
564643};
565644
566645// TODO(EricWF): We should prefer the futex implementation when available. But
......@@ -571,22 +650,21 @@ constexpr Implementation CurrentImplementation =
571650#elif defined(_LIBCXXABI_USE_FUTEX)
572651 Implementation::Futex;
573652#else
574 Implementation::GlobalLock;
653 Implementation::GlobalMutex;
575654#endif
576655
577static_assert(CurrentImplementation != Implementation::Futex
578 || PlatformSupportsFutex(), "Futex selected but not supported");
656static_assert(CurrentImplementation != Implementation::Futex || PlatformSupportsFutex(),
657 "Futex selected but not supported");
579658
580using SelectedImplementation =
581 SelectImplementation<CurrentImplementation>::type;
659using SelectedImplementation = SelectImplementation<CurrentImplementation>::type;
582660
583661} // end namespace
584662} // end namespace __cxxabiv1
585663
586664#if defined(__clang__)
587# pragma clang diagnostic pop
665# pragma clang diagnostic pop
588666#elif defined(__GNUC__)
589# pragma GCC diagnostic pop
667# pragma GCC diagnostic pop
590668#endif
591669
592670#endif // LIBCXXABI_SRC_INCLUDE_CXA_GUARD_IMPL_H
lib/libcxxabi/src/cxa_handlers.cpp+3-13
......@@ -1,4 +1,4 @@
1//===------------------------- cxa_handlers.cpp ---------------------------===//
1//===----------------------------------------------------------------------===//
22//
33// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
44// See https://llvm.org/LICENSE.txt for license information.
......@@ -6,7 +6,7 @@
66//
77//
88// This file implements the functionality associated with the terminate_handler,
9// unexpected_handler, and new_handler.
9// unexpected_handler, and new_handler.
1010//===----------------------------------------------------------------------===//
1111
1212#include <stdexcept>
......@@ -17,7 +17,7 @@
1717#include "cxa_handlers.h"
1818#include "cxa_exception.h"
1919#include "private_typeinfo.h"
20#include "include/atomic_support.h"
20#include "include/atomic_support.h" // from libc++
2121
2222namespace std
2323{
......@@ -92,16 +92,6 @@ terminate() noexcept
9292 __terminate(get_terminate());
9393}
9494
95extern "C" {
96new_handler __cxa_new_handler = 0;
97}
98
99new_handler
100set_new_handler(new_handler handler) noexcept
101{
102 return __libcpp_atomic_exchange(&__cxa_new_handler, handler, _AO_Acq_Rel);
103}
104
10595new_handler
10696get_new_handler() noexcept
10797{
lib/libcxxabi/src/cxa_handlers.h+1-1
......@@ -1,4 +1,4 @@
1//===------------------------- cxa_handlers.h -----------------------------===//
1//===----------------------------------------------------------------------===//
22//
33// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
44// See https://llvm.org/LICENSE.txt for license information.
lib/libcxxabi/src/cxa_noexception.cpp+1-1
......@@ -1,4 +1,4 @@
1//===------------------------- cxa_exception.cpp --------------------------===//
1//===----------------------------------------------------------------------===//
22//
33// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
44// See https://llvm.org/LICENSE.txt for license information.
lib/libcxxabi/src/cxa_personality.cpp+16-4
......@@ -1,4 +1,4 @@
1//===------------------------- cxa_exception.cpp --------------------------===//
1//===----------------------------------------------------------------------===//
22//
33// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
44// See https://llvm.org/LICENSE.txt for license information.
......@@ -1004,9 +1004,14 @@ extern "C" _Unwind_Reason_Code __gnu_unwind_frame(_Unwind_Exception*,
10041004static _Unwind_Reason_Code continue_unwind(_Unwind_Exception* unwind_exception,
10051005 _Unwind_Context* context)
10061006{
1007 if (__gnu_unwind_frame(unwind_exception, context) != _URC_OK)
1008 return _URC_FAILURE;
1007 switch (__gnu_unwind_frame(unwind_exception, context)) {
1008 case _URC_OK:
10091009 return _URC_CONTINUE_UNWIND;
1010 case _URC_END_OF_STACK:
1011 return _URC_END_OF_STACK;
1012 default:
1013 return _URC_FAILURE;
1014 }
10101015}
10111016
10121017// ARM register names
......@@ -1109,7 +1114,14 @@ __gxx_personality_v0(_Unwind_State state,
11091114 // Either we didn't do a phase 1 search (due to forced unwinding), or
11101115 // phase 1 reported no catching-handlers.
11111116 // Search for a (non-catching) cleanup
1112 scan_eh_tab(results, _UA_CLEANUP_PHASE, native_exception, unwind_exception, context);
1117 if (is_force_unwinding)
1118 scan_eh_tab(
1119 results,
1120 static_cast<_Unwind_Action>(_UA_CLEANUP_PHASE | _UA_FORCE_UNWIND),
1121 native_exception, unwind_exception, context);
1122 else
1123 scan_eh_tab(results, _UA_CLEANUP_PHASE, native_exception,
1124 unwind_exception, context);
11131125 if (results.reason == _URC_HANDLER_FOUND)
11141126 {
11151127 // Found a non-catching handler
lib/libcxxabi/src/cxa_thread_atexit.cpp+1-1
......@@ -1,4 +1,4 @@
1//===----------------------- cxa_thread_atexit.cpp ------------------------===//
1//===----------------------------------------------------------------------===//
22//
33// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
44// See https://llvm.org/LICENSE.txt for license information.
lib/libcxxabi/src/cxa_vector.cpp+1-1
......@@ -1,4 +1,4 @@
1//===-------------------------- cxa_vector.cpp ---------------------------===//
1//===----------------------------------------------------------------------===//
22//
33// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
44// See https://llvm.org/LICENSE.txt for license information.
lib/libcxxabi/src/cxa_virtual.cpp+1-1
......@@ -1,4 +1,4 @@
1//===-------------------------- cxa_virtual.cpp ---------------------------===//
1//===----------------------------------------------------------------------===//
22//
33// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
44// See https://llvm.org/LICENSE.txt for license information.
lib/libcxxabi/src/demangle/ItaniumDemangle.h+740-698
......@@ -6,8 +6,10 @@
66//
77//===----------------------------------------------------------------------===//
88//
9// Generic itanium demangler library. This file has two byte-per-byte identical
10// copies in the source tree, one in libcxxabi, and the other in llvm.
9// Generic itanium demangler library.
10// There are two copies of this file in the source tree. The one under
11// libcxxabi is the original and the one under llvm is the copy. Use
12// cp-to-llvm.sh to update the copy. See README.txt for more details.
1113//
1214//===----------------------------------------------------------------------===//
1315
......@@ -21,12 +23,13 @@
2123#include "DemangleConfig.h"
2224#include "StringView.h"
2325#include "Utility.h"
26#include <algorithm>
2427#include <cassert>
2528#include <cctype>
2629#include <cstdio>
2730#include <cstdlib>
2831#include <cstring>
29#include <numeric>
32#include <limits>
3033#include <utility>
3134
3235#define FOR_EACH_NODE_KIND(X) \
......@@ -57,6 +60,7 @@
5760 X(LocalName) \
5861 X(VectorType) \
5962 X(PixelVectorType) \
63 X(BinaryFPType) \
6064 X(SyntheticTemplateParamName) \
6165 X(TypeTemplateParamDecl) \
6266 X(NonTypeTemplateParamDecl) \
......@@ -109,6 +113,126 @@
109113
110114DEMANGLE_NAMESPACE_BEGIN
111115
116template <class T, size_t N> class PODSmallVector {
117 static_assert(std::is_pod<T>::value,
118 "T is required to be a plain old data type");
119
120 T *First = nullptr;
121 T *Last = nullptr;
122 T *Cap = nullptr;
123 T Inline[N] = {0};
124
125 bool isInline() const { return First == Inline; }
126
127 void clearInline() {
128 First = Inline;
129 Last = Inline;
130 Cap = Inline + N;
131 }
132
133 void reserve(size_t NewCap) {
134 size_t S = size();
135 if (isInline()) {
136 auto *Tmp = static_cast<T *>(std::malloc(NewCap * sizeof(T)));
137 if (Tmp == nullptr)
138 std::terminate();
139 std::copy(First, Last, Tmp);
140 First = Tmp;
141 } else {
142 First = static_cast<T *>(std::realloc(First, NewCap * sizeof(T)));
143 if (First == nullptr)
144 std::terminate();
145 }
146 Last = First + S;
147 Cap = First + NewCap;
148 }
149
150public:
151 PODSmallVector() : First(Inline), Last(First), Cap(Inline + N) {}
152
153 PODSmallVector(const PODSmallVector &) = delete;
154 PODSmallVector &operator=(const PODSmallVector &) = delete;
155
156 PODSmallVector(PODSmallVector &&Other) : PODSmallVector() {
157 if (Other.isInline()) {
158 std::copy(Other.begin(), Other.end(), First);
159 Last = First + Other.size();
160 Other.clear();
161 return;
162 }
163
164 First = Other.First;
165 Last = Other.Last;
166 Cap = Other.Cap;
167 Other.clearInline();
168 }
169
170 PODSmallVector &operator=(PODSmallVector &&Other) {
171 if (Other.isInline()) {
172 if (!isInline()) {
173 std::free(First);
174 clearInline();
175 }
176 std::copy(Other.begin(), Other.end(), First);
177 Last = First + Other.size();
178 Other.clear();
179 return *this;
180 }
181
182 if (isInline()) {
183 First = Other.First;
184 Last = Other.Last;
185 Cap = Other.Cap;
186 Other.clearInline();
187 return *this;
188 }
189
190 std::swap(First, Other.First);
191 std::swap(Last, Other.Last);
192 std::swap(Cap, Other.Cap);
193 Other.clear();
194 return *this;
195 }
196
197 // NOLINTNEXTLINE(readability-identifier-naming)
198 void push_back(const T &Elem) {
199 if (Last == Cap)
200 reserve(size() * 2);
201 *Last++ = Elem;
202 }
203
204 // NOLINTNEXTLINE(readability-identifier-naming)
205 void pop_back() {
206 assert(Last != First && "Popping empty vector!");
207 --Last;
208 }
209
210 void dropBack(size_t Index) {
211 assert(Index <= size() && "dropBack() can't expand!");
212 Last = First + Index;
213 }
214
215 T *begin() { return First; }
216 T *end() { return Last; }
217
218 bool empty() const { return First == Last; }
219 size_t size() const { return static_cast<size_t>(Last - First); }
220 T &back() {
221 assert(Last != First && "Calling back() on empty vector!");
222 return *(Last - 1);
223 }
224 T &operator[](size_t Index) {
225 assert(Index < size() && "Invalid access!");
226 return *(begin() + Index);
227 }
228 void clear() { Last = First; }
229
230 ~PODSmallVector() {
231 if (!isInline())
232 std::free(First);
233 }
234};
235
112236// Base class of all AST nodes. The AST is built by the parser, then is
113237// traversed by the printLeft/Right functions to produce a demangled string.
114238class Node {
......@@ -155,50 +279,48 @@ public:
155279 // would construct an equivalent node.
156280 //template<typename Fn> void match(Fn F) const;
157281
158 bool hasRHSComponent(OutputStream &S) const {
282 bool hasRHSComponent(OutputBuffer &OB) const {
159283 if (RHSComponentCache != Cache::Unknown)
160284 return RHSComponentCache == Cache::Yes;
161 return hasRHSComponentSlow(S);
285 return hasRHSComponentSlow(OB);
162286 }
163287
164 bool hasArray(OutputStream &S) const {
288 bool hasArray(OutputBuffer &OB) const {
165289 if (ArrayCache != Cache::Unknown)
166290 return ArrayCache == Cache::Yes;
167 return hasArraySlow(S);
291 return hasArraySlow(OB);
168292 }
169293
170 bool hasFunction(OutputStream &S) const {
294 bool hasFunction(OutputBuffer &OB) const {
171295 if (FunctionCache != Cache::Unknown)
172296 return FunctionCache == Cache::Yes;
173 return hasFunctionSlow(S);
297 return hasFunctionSlow(OB);
174298 }
175299
176300 Kind getKind() const { return K; }
177301
178 virtual bool hasRHSComponentSlow(OutputStream &) const { return false; }
179 virtual bool hasArraySlow(OutputStream &) const { return false; }
180 virtual bool hasFunctionSlow(OutputStream &) const { return false; }
302 virtual bool hasRHSComponentSlow(OutputBuffer &) const { return false; }
303 virtual bool hasArraySlow(OutputBuffer &) const { return false; }
304 virtual bool hasFunctionSlow(OutputBuffer &) const { return false; }
181305
182306 // Dig through "glue" nodes like ParameterPack and ForwardTemplateReference to
183307 // get at a node that actually represents some concrete syntax.
184 virtual const Node *getSyntaxNode(OutputStream &) const {
185 return this;
186 }
308 virtual const Node *getSyntaxNode(OutputBuffer &) const { return this; }
187309
188 void print(OutputStream &S) const {
189 printLeft(S);
310 void print(OutputBuffer &OB) const {
311 printLeft(OB);
190312 if (RHSComponentCache != Cache::No)
191 printRight(S);
313 printRight(OB);
192314 }
193315
194 // Print the "left" side of this Node into OutputStream.
195 virtual void printLeft(OutputStream &) const = 0;
316 // Print the "left" side of this Node into OutputBuffer.
317 virtual void printLeft(OutputBuffer &) const = 0;
196318
197319 // Print the "right". This distinction is necessary to represent C++ types
198320 // that appear on the RHS of their subtype, such as arrays or functions.
199321 // Since most types don't have such a component, provide a default
200322 // implementation.
201 virtual void printRight(OutputStream &) const {}
323 virtual void printRight(OutputBuffer &) const {}
202324
203325 virtual StringView getBaseName() const { return StringView(); }
204326
......@@ -227,19 +349,19 @@ public:
227349
228350 Node *operator[](size_t Idx) const { return Elements[Idx]; }
229351
230 void printWithComma(OutputStream &S) const {
352 void printWithComma(OutputBuffer &OB) const {
231353 bool FirstElement = true;
232354 for (size_t Idx = 0; Idx != NumElements; ++Idx) {
233 size_t BeforeComma = S.getCurrentPosition();
355 size_t BeforeComma = OB.getCurrentPosition();
234356 if (!FirstElement)
235 S += ", ";
236 size_t AfterComma = S.getCurrentPosition();
237 Elements[Idx]->print(S);
357 OB += ", ";
358 size_t AfterComma = OB.getCurrentPosition();
359 Elements[Idx]->print(OB);
238360
239361 // Elements[Idx] is an empty parameter pack expansion, we should erase the
240362 // comma we just printed.
241 if (AfterComma == S.getCurrentPosition()) {
242 S.setCurrentPosition(BeforeComma);
363 if (AfterComma == OB.getCurrentPosition()) {
364 OB.setCurrentPosition(BeforeComma);
243365 continue;
244366 }
245367
......@@ -254,9 +376,7 @@ struct NodeArrayNode : Node {
254376
255377 template<typename Fn> void match(Fn F) const { F(Array); }
256378
257 void printLeft(OutputStream &S) const override {
258 Array.printWithComma(S);
259 }
379 void printLeft(OutputBuffer &OB) const override { Array.printWithComma(OB); }
260380};
261381
262382class DotSuffix final : public Node {
......@@ -269,11 +389,11 @@ public:
269389
270390 template<typename Fn> void match(Fn F) const { F(Prefix, Suffix); }
271391
272 void printLeft(OutputStream &s) const override {
273 Prefix->print(s);
274 s += " (";
275 s += Suffix;
276 s += ")";
392 void printLeft(OutputBuffer &OB) const override {
393 Prefix->print(OB);
394 OB += " (";
395 OB += Suffix;
396 OB += ")";
277397 }
278398};
279399
......@@ -288,12 +408,12 @@ public:
288408
289409 template <typename Fn> void match(Fn F) const { F(Ty, Ext, TA); }
290410
291 void printLeft(OutputStream &S) const override {
292 Ty->print(S);
293 S += " ";
294 S += Ext;
411 void printLeft(OutputBuffer &OB) const override {
412 Ty->print(OB);
413 OB += " ";
414 OB += Ext;
295415 if (TA != nullptr)
296 TA->print(S);
416 TA->print(OB);
297417 }
298418};
299419
......@@ -319,13 +439,13 @@ protected:
319439 const Qualifiers Quals;
320440 const Node *Child;
321441
322 void printQuals(OutputStream &S) const {
442 void printQuals(OutputBuffer &OB) const {
323443 if (Quals & QualConst)
324 S += " const";
444 OB += " const";
325445 if (Quals & QualVolatile)
326 S += " volatile";
446 OB += " volatile";
327447 if (Quals & QualRestrict)
328 S += " restrict";
448 OB += " restrict";
329449 }
330450
331451public:
......@@ -336,22 +456,22 @@ public:
336456
337457 template<typename Fn> void match(Fn F) const { F(Child, Quals); }
338458
339 bool hasRHSComponentSlow(OutputStream &S) const override {
340 return Child->hasRHSComponent(S);
459 bool hasRHSComponentSlow(OutputBuffer &OB) const override {
460 return Child->hasRHSComponent(OB);
341461 }
342 bool hasArraySlow(OutputStream &S) const override {
343 return Child->hasArray(S);
462 bool hasArraySlow(OutputBuffer &OB) const override {
463 return Child->hasArray(OB);
344464 }
345 bool hasFunctionSlow(OutputStream &S) const override {
346 return Child->hasFunction(S);
465 bool hasFunctionSlow(OutputBuffer &OB) const override {
466 return Child->hasFunction(OB);
347467 }
348468
349 void printLeft(OutputStream &S) const override {
350 Child->printLeft(S);
351 printQuals(S);
469 void printLeft(OutputBuffer &OB) const override {
470 Child->printLeft(OB);
471 printQuals(OB);
352472 }
353473
354 void printRight(OutputStream &S) const override { Child->printRight(S); }
474 void printRight(OutputBuffer &OB) const override { Child->printRight(OB); }
355475};
356476
357477class ConversionOperatorType final : public Node {
......@@ -363,9 +483,9 @@ public:
363483
364484 template<typename Fn> void match(Fn F) const { F(Ty); }
365485
366 void printLeft(OutputStream &S) const override {
367 S += "operator ";
368 Ty->print(S);
486 void printLeft(OutputBuffer &OB) const override {
487 OB += "operator ";
488 Ty->print(OB);
369489 }
370490};
371491
......@@ -379,9 +499,9 @@ public:
379499
380500 template<typename Fn> void match(Fn F) const { F(Ty, Postfix); }
381501
382 void printLeft(OutputStream &s) const override {
383 Ty->printLeft(s);
384 s += Postfix;
502 void printLeft(OutputBuffer &OB) const override {
503 Ty->printLeft(OB);
504 OB += Postfix;
385505 }
386506};
387507
......@@ -396,7 +516,7 @@ public:
396516 StringView getName() const { return Name; }
397517 StringView getBaseName() const override { return Name; }
398518
399 void printLeft(OutputStream &s) const override { s += Name; }
519 void printLeft(OutputBuffer &OB) const override { OB += Name; }
400520};
401521
402522class ElaboratedTypeSpefType : public Node {
......@@ -408,10 +528,10 @@ public:
408528
409529 template<typename Fn> void match(Fn F) const { F(Kind, Child); }
410530
411 void printLeft(OutputStream &S) const override {
412 S += Kind;
413 S += ' ';
414 Child->print(S);
531 void printLeft(OutputBuffer &OB) const override {
532 OB += Kind;
533 OB += ' ';
534 Child->print(OB);
415535 }
416536};
417537
......@@ -426,11 +546,11 @@ struct AbiTagAttr : Node {
426546
427547 template<typename Fn> void match(Fn F) const { F(Base, Tag); }
428548
429 void printLeft(OutputStream &S) const override {
430 Base->printLeft(S);
431 S += "[abi:";
432 S += Tag;
433 S += "]";
549 void printLeft(OutputBuffer &OB) const override {
550 Base->printLeft(OB);
551 OB += "[abi:";
552 OB += Tag;
553 OB += "]";
434554 }
435555};
436556
......@@ -442,10 +562,10 @@ public:
442562
443563 template<typename Fn> void match(Fn F) const { F(Conditions); }
444564
445 void printLeft(OutputStream &S) const override {
446 S += " [enable_if:";
447 Conditions.printWithComma(S);
448 S += ']';
565 void printLeft(OutputBuffer &OB) const override {
566 OB += " [enable_if:";
567 Conditions.printWithComma(OB);
568 OB += ']';
449569 }
450570};
451571
......@@ -466,11 +586,11 @@ public:
466586 static_cast<const NameType *>(Ty)->getName() == "objc_object";
467587 }
468588
469 void printLeft(OutputStream &S) const override {
470 Ty->print(S);
471 S += "<";
472 S += Protocol;
473 S += ">";
589 void printLeft(OutputBuffer &OB) const override {
590 Ty->print(OB);
591 OB += "<";
592 OB += Protocol;
593 OB += ">";
474594 }
475595};
476596
......@@ -484,34 +604,34 @@ public:
484604
485605 template<typename Fn> void match(Fn F) const { F(Pointee); }
486606
487 bool hasRHSComponentSlow(OutputStream &S) const override {
488 return Pointee->hasRHSComponent(S);
607 bool hasRHSComponentSlow(OutputBuffer &OB) const override {
608 return Pointee->hasRHSComponent(OB);
489609 }
490610
491 void printLeft(OutputStream &s) const override {
611 void printLeft(OutputBuffer &OB) const override {
492612 // We rewrite objc_object<SomeProtocol>* into id<SomeProtocol>.
493613 if (Pointee->getKind() != KObjCProtoName ||
494614 !static_cast<const ObjCProtoName *>(Pointee)->isObjCObject()) {
495 Pointee->printLeft(s);
496 if (Pointee->hasArray(s))
497 s += " ";
498 if (Pointee->hasArray(s) || Pointee->hasFunction(s))
499 s += "(";
500 s += "*";
615 Pointee->printLeft(OB);
616 if (Pointee->hasArray(OB))
617 OB += " ";
618 if (Pointee->hasArray(OB) || Pointee->hasFunction(OB))
619 OB += "(";
620 OB += "*";
501621 } else {
502622 const auto *objcProto = static_cast<const ObjCProtoName *>(Pointee);
503 s += "id<";
504 s += objcProto->Protocol;
505 s += ">";
623 OB += "id<";
624 OB += objcProto->Protocol;
625 OB += ">";
506626 }
507627 }
508628
509 void printRight(OutputStream &s) const override {
629 void printRight(OutputBuffer &OB) const override {
510630 if (Pointee->getKind() != KObjCProtoName ||
511631 !static_cast<const ObjCProtoName *>(Pointee)->isObjCObject()) {
512 if (Pointee->hasArray(s) || Pointee->hasFunction(s))
513 s += ")";
514 Pointee->printRight(s);
632 if (Pointee->hasArray(OB) || Pointee->hasFunction(OB))
633 OB += ")";
634 Pointee->printRight(OB);
515635 }
516636 }
517637};
......@@ -531,15 +651,30 @@ class ReferenceType : public Node {
531651 // Dig through any refs to refs, collapsing the ReferenceTypes as we go. The
532652 // rule here is rvalue ref to rvalue ref collapses to a rvalue ref, and any
533653 // other combination collapses to a lvalue ref.
534 std::pair<ReferenceKind, const Node *> collapse(OutputStream &S) const {
654 //
655 // A combination of a TemplateForwardReference and a back-ref Substitution
656 // from an ill-formed string may have created a cycle; use cycle detection to
657 // avoid looping forever.
658 std::pair<ReferenceKind, const Node *> collapse(OutputBuffer &OB) const {
535659 auto SoFar = std::make_pair(RK, Pointee);
660 // Track the chain of nodes for the Floyd's 'tortoise and hare'
661 // cycle-detection algorithm, since getSyntaxNode(S) is impure
662 PODSmallVector<const Node *, 8> Prev;
536663 for (;;) {
537 const Node *SN = SoFar.second->getSyntaxNode(S);
664 const Node *SN = SoFar.second->getSyntaxNode(OB);
538665 if (SN->getKind() != KReferenceType)
539666 break;
540667 auto *RT = static_cast<const ReferenceType *>(SN);
541668 SoFar.second = RT->Pointee;
542669 SoFar.first = std::min(SoFar.first, RT->RK);
670
671 // The middle of Prev is the 'slow' pointer moving at half speed
672 Prev.push_back(SoFar.second);
673 if (Prev.size() > 1 && SoFar.second == Prev[(Prev.size() - 1) / 2]) {
674 // Cycle detected
675 SoFar.second = nullptr;
676 break;
677 }
543678 }
544679 return SoFar;
545680 }
......@@ -551,31 +686,35 @@ public:
551686
552687 template<typename Fn> void match(Fn F) const { F(Pointee, RK); }
553688
554 bool hasRHSComponentSlow(OutputStream &S) const override {
555 return Pointee->hasRHSComponent(S);
689 bool hasRHSComponentSlow(OutputBuffer &OB) const override {
690 return Pointee->hasRHSComponent(OB);
556691 }
557692
558 void printLeft(OutputStream &s) const override {
693 void printLeft(OutputBuffer &OB) const override {
559694 if (Printing)
560695 return;
561696 SwapAndRestore<bool> SavePrinting(Printing, true);
562 std::pair<ReferenceKind, const Node *> Collapsed = collapse(s);
563 Collapsed.second->printLeft(s);
564 if (Collapsed.second->hasArray(s))
565 s += " ";
566 if (Collapsed.second->hasArray(s) || Collapsed.second->hasFunction(s))
567 s += "(";
697 std::pair<ReferenceKind, const Node *> Collapsed = collapse(OB);
698 if (!Collapsed.second)
699 return;
700 Collapsed.second->printLeft(OB);
701 if (Collapsed.second->hasArray(OB))
702 OB += " ";
703 if (Collapsed.second->hasArray(OB) || Collapsed.second->hasFunction(OB))
704 OB += "(";
568705
569 s += (Collapsed.first == ReferenceKind::LValue ? "&" : "&&");
706 OB += (Collapsed.first == ReferenceKind::LValue ? "&" : "&&");
570707 }
571 void printRight(OutputStream &s) const override {
708 void printRight(OutputBuffer &OB) const override {
572709 if (Printing)
573710 return;
574711 SwapAndRestore<bool> SavePrinting(Printing, true);
575 std::pair<ReferenceKind, const Node *> Collapsed = collapse(s);
576 if (Collapsed.second->hasArray(s) || Collapsed.second->hasFunction(s))
577 s += ")";
578 Collapsed.second->printRight(s);
712 std::pair<ReferenceKind, const Node *> Collapsed = collapse(OB);
713 if (!Collapsed.second)
714 return;
715 if (Collapsed.second->hasArray(OB) || Collapsed.second->hasFunction(OB))
716 OB += ")";
717 Collapsed.second->printRight(OB);
579718 }
580719};
581720
......@@ -590,24 +729,24 @@ public:
590729
591730 template<typename Fn> void match(Fn F) const { F(ClassType, MemberType); }
592731
593 bool hasRHSComponentSlow(OutputStream &S) const override {
594 return MemberType->hasRHSComponent(S);
732 bool hasRHSComponentSlow(OutputBuffer &OB) const override {
733 return MemberType->hasRHSComponent(OB);
595734 }
596735
597 void printLeft(OutputStream &s) const override {
598 MemberType->printLeft(s);
599 if (MemberType->hasArray(s) || MemberType->hasFunction(s))
600 s += "(";
736 void printLeft(OutputBuffer &OB) const override {
737 MemberType->printLeft(OB);
738 if (MemberType->hasArray(OB) || MemberType->hasFunction(OB))
739 OB += "(";
601740 else
602 s += " ";
603 ClassType->print(s);
604 s += "::*";
741 OB += " ";
742 ClassType->print(OB);
743 OB += "::*";
605744 }
606745
607 void printRight(OutputStream &s) const override {
608 if (MemberType->hasArray(s) || MemberType->hasFunction(s))
609 s += ")";
610 MemberType->printRight(s);
746 void printRight(OutputBuffer &OB) const override {
747 if (MemberType->hasArray(OB) || MemberType->hasFunction(OB))
748 OB += ")";
749 MemberType->printRight(OB);
611750 }
612751};
613752
......@@ -624,19 +763,19 @@ public:
624763
625764 template<typename Fn> void match(Fn F) const { F(Base, Dimension); }
626765
627 bool hasRHSComponentSlow(OutputStream &) const override { return true; }
628 bool hasArraySlow(OutputStream &) const override { return true; }
766 bool hasRHSComponentSlow(OutputBuffer &) const override { return true; }
767 bool hasArraySlow(OutputBuffer &) const override { return true; }
629768
630 void printLeft(OutputStream &S) const override { Base->printLeft(S); }
769 void printLeft(OutputBuffer &OB) const override { Base->printLeft(OB); }
631770
632 void printRight(OutputStream &S) const override {
633 if (S.back() != ']')
634 S += " ";
635 S += "[";
771 void printRight(OutputBuffer &OB) const override {
772 if (OB.back() != ']')
773 OB += " ";
774 OB += "[";
636775 if (Dimension)
637 Dimension->print(S);
638 S += "]";
639 Base->printRight(S);
776 Dimension->print(OB);
777 OB += "]";
778 Base->printRight(OB);
640779 }
641780};
642781
......@@ -660,8 +799,8 @@ public:
660799 F(Ret, Params, CVQuals, RefQual, ExceptionSpec);
661800 }
662801
663 bool hasRHSComponentSlow(OutputStream &) const override { return true; }
664 bool hasFunctionSlow(OutputStream &) const override { return true; }
802 bool hasRHSComponentSlow(OutputBuffer &) const override { return true; }
803 bool hasFunctionSlow(OutputBuffer &) const override { return true; }
665804
666805 // Handle C++'s ... quirky decl grammar by using the left & right
667806 // distinction. Consider:
......@@ -670,32 +809,32 @@ public:
670809 // that takes a char and returns an int. If we're trying to print f, start
671810 // by printing out the return types's left, then print our parameters, then
672811 // finally print right of the return type.
673 void printLeft(OutputStream &S) const override {
674 Ret->printLeft(S);
675 S += " ";
812 void printLeft(OutputBuffer &OB) const override {
813 Ret->printLeft(OB);
814 OB += " ";
676815 }
677816
678 void printRight(OutputStream &S) const override {
679 S += "(";
680 Params.printWithComma(S);
681 S += ")";
682 Ret->printRight(S);
817 void printRight(OutputBuffer &OB) const override {
818 OB += "(";
819 Params.printWithComma(OB);
820 OB += ")";
821 Ret->printRight(OB);
683822
684823 if (CVQuals & QualConst)
685 S += " const";
824 OB += " const";
686825 if (CVQuals & QualVolatile)
687 S += " volatile";
826 OB += " volatile";
688827 if (CVQuals & QualRestrict)
689 S += " restrict";
828 OB += " restrict";
690829
691830 if (RefQual == FrefQualLValue)
692 S += " &";
831 OB += " &";
693832 else if (RefQual == FrefQualRValue)
694 S += " &&";
833 OB += " &&";
695834
696835 if (ExceptionSpec != nullptr) {
697 S += ' ';
698 ExceptionSpec->print(S);
836 OB += ' ';
837 ExceptionSpec->print(OB);
699838 }
700839 }
701840};
......@@ -707,10 +846,10 @@ public:
707846
708847 template<typename Fn> void match(Fn F) const { F(E); }
709848
710 void printLeft(OutputStream &S) const override {
711 S += "noexcept(";
712 E->print(S);
713 S += ")";
849 void printLeft(OutputBuffer &OB) const override {
850 OB += "noexcept(";
851 E->print(OB);
852 OB += ")";
714853 }
715854};
716855
......@@ -722,10 +861,10 @@ public:
722861
723862 template<typename Fn> void match(Fn F) const { F(Types); }
724863
725 void printLeft(OutputStream &S) const override {
726 S += "throw(";
727 Types.printWithComma(S);
728 S += ')';
864 void printLeft(OutputBuffer &OB) const override {
865 OB += "throw(";
866 Types.printWithComma(OB);
867 OB += ')';
729868 }
730869};
731870
......@@ -756,41 +895,41 @@ public:
756895 NodeArray getParams() const { return Params; }
757896 const Node *getReturnType() const { return Ret; }
758897
759 bool hasRHSComponentSlow(OutputStream &) const override { return true; }
760 bool hasFunctionSlow(OutputStream &) const override { return true; }
898 bool hasRHSComponentSlow(OutputBuffer &) const override { return true; }
899 bool hasFunctionSlow(OutputBuffer &) const override { return true; }
761900
762901 const Node *getName() const { return Name; }
763902
764 void printLeft(OutputStream &S) const override {
903 void printLeft(OutputBuffer &OB) const override {
765904 if (Ret) {
766 Ret->printLeft(S);
767 if (!Ret->hasRHSComponent(S))
768 S += " ";
905 Ret->printLeft(OB);
906 if (!Ret->hasRHSComponent(OB))
907 OB += " ";
769908 }
770 Name->print(S);
909 Name->print(OB);
771910 }
772911
773 void printRight(OutputStream &S) const override {
774 S += "(";
775 Params.printWithComma(S);
776 S += ")";
912 void printRight(OutputBuffer &OB) const override {
913 OB += "(";
914 Params.printWithComma(OB);
915 OB += ")";
777916 if (Ret)
778 Ret->printRight(S);
917 Ret->printRight(OB);
779918
780919 if (CVQuals & QualConst)
781 S += " const";
920 OB += " const";
782921 if (CVQuals & QualVolatile)
783 S += " volatile";
922 OB += " volatile";
784923 if (CVQuals & QualRestrict)
785 S += " restrict";
924 OB += " restrict";
786925
787926 if (RefQual == FrefQualLValue)
788 S += " &";
927 OB += " &";
789928 else if (RefQual == FrefQualRValue)
790 S += " &&";
929 OB += " &&";
791930
792931 if (Attrs != nullptr)
793 Attrs->print(S);
932 Attrs->print(OB);
794933 }
795934};
796935
......@@ -803,9 +942,9 @@ public:
803942
804943 template<typename Fn> void match(Fn F) const { F(OpName); }
805944
806 void printLeft(OutputStream &S) const override {
807 S += "operator\"\" ";
808 OpName->print(S);
945 void printLeft(OutputBuffer &OB) const override {
946 OB += "operator\"\" ";
947 OpName->print(OB);
809948 }
810949};
811950
......@@ -819,9 +958,9 @@ public:
819958
820959 template<typename Fn> void match(Fn F) const { F(Special, Child); }
821960
822 void printLeft(OutputStream &S) const override {
823 S += Special;
824 Child->print(S);
961 void printLeft(OutputBuffer &OB) const override {
962 OB += Special;
963 Child->print(OB);
825964 }
826965};
827966
......@@ -836,11 +975,11 @@ public:
836975
837976 template<typename Fn> void match(Fn F) const { F(FirstType, SecondType); }
838977
839 void printLeft(OutputStream &S) const override {
840 S += "construction vtable for ";
841 FirstType->print(S);
842 S += "-in-";
843 SecondType->print(S);
978 void printLeft(OutputBuffer &OB) const override {
979 OB += "construction vtable for ";
980 FirstType->print(OB);
981 OB += "-in-";
982 SecondType->print(OB);
844983 }
845984};
846985
......@@ -855,10 +994,10 @@ struct NestedName : Node {
855994
856995 StringView getBaseName() const override { return Name->getBaseName(); }
857996
858 void printLeft(OutputStream &S) const override {
859 Qual->print(S);
860 S += "::";
861 Name->print(S);
997 void printLeft(OutputBuffer &OB) const override {
998 Qual->print(OB);
999 OB += "::";
1000 Name->print(OB);
8621001 }
8631002};
8641003
......@@ -871,10 +1010,10 @@ struct LocalName : Node {
8711010
8721011 template<typename Fn> void match(Fn F) const { F(Encoding, Entity); }
8731012
874 void printLeft(OutputStream &S) const override {
875 Encoding->print(S);
876 S += "::";
877 Entity->print(S);
1013 void printLeft(OutputBuffer &OB) const override {
1014 Encoding->print(OB);
1015 OB += "::";
1016 Entity->print(OB);
8781017 }
8791018};
8801019
......@@ -891,10 +1030,10 @@ public:
8911030
8921031 StringView getBaseName() const override { return Name->getBaseName(); }
8931032
894 void printLeft(OutputStream &S) const override {
895 Qualifier->print(S);
896 S += "::";
897 Name->print(S);
1033 void printLeft(OutputBuffer &OB) const override {
1034 Qualifier->print(OB);
1035 OB += "::";
1036 Name->print(OB);
8981037 }
8991038};
9001039
......@@ -909,12 +1048,12 @@ public:
9091048
9101049 template<typename Fn> void match(Fn F) const { F(BaseType, Dimension); }
9111050
912 void printLeft(OutputStream &S) const override {
913 BaseType->print(S);
914 S += " vector[";
1051 void printLeft(OutputBuffer &OB) const override {
1052 BaseType->print(OB);
1053 OB += " vector[";
9151054 if (Dimension)
916 Dimension->print(S);
917 S += "]";
1055 Dimension->print(OB);
1056 OB += "]";
9181057 }
9191058};
9201059
......@@ -927,11 +1066,26 @@ public:
9271066
9281067 template<typename Fn> void match(Fn F) const { F(Dimension); }
9291068
930 void printLeft(OutputStream &S) const override {
1069 void printLeft(OutputBuffer &OB) const override {
9311070 // FIXME: This should demangle as "vector pixel".
932 S += "pixel vector[";
933 Dimension->print(S);
934 S += "]";
1071 OB += "pixel vector[";
1072 Dimension->print(OB);
1073 OB += "]";
1074 }
1075};
1076
1077class BinaryFPType final : public Node {
1078 const Node *Dimension;
1079
1080public:
1081 BinaryFPType(const Node *Dimension_)
1082 : Node(KBinaryFPType), Dimension(Dimension_) {}
1083
1084 template<typename Fn> void match(Fn F) const { F(Dimension); }
1085
1086 void printLeft(OutputBuffer &OB) const override {
1087 OB += "_Float";
1088 Dimension->print(OB);
9351089 }
9361090};
9371091
......@@ -953,20 +1107,20 @@ public:
9531107
9541108 template<typename Fn> void match(Fn F) const { F(Kind, Index); }
9551109
956 void printLeft(OutputStream &S) const override {
1110 void printLeft(OutputBuffer &OB) const override {
9571111 switch (Kind) {
9581112 case TemplateParamKind::Type:
959 S += "$T";
1113 OB += "$T";
9601114 break;
9611115 case TemplateParamKind::NonType:
962 S += "$N";
1116 OB += "$N";
9631117 break;
9641118 case TemplateParamKind::Template:
965 S += "$TT";
1119 OB += "$TT";
9661120 break;
9671121 }
9681122 if (Index > 0)
969 S << Index - 1;
1123 OB << Index - 1;
9701124 }
9711125};
9721126
......@@ -980,13 +1134,9 @@ public:
9801134
9811135 template<typename Fn> void match(Fn F) const { F(Name); }
9821136
983 void printLeft(OutputStream &S) const override {
984 S += "typename ";
985 }
1137 void printLeft(OutputBuffer &OB) const override { OB += "typename "; }
9861138
987 void printRight(OutputStream &S) const override {
988 Name->print(S);
989 }
1139 void printRight(OutputBuffer &OB) const override { Name->print(OB); }
9901140};
9911141
9921142/// A non-type template parameter declaration, 'int N'.
......@@ -1000,15 +1150,15 @@ public:
10001150
10011151 template<typename Fn> void match(Fn F) const { F(Name, Type); }
10021152
1003 void printLeft(OutputStream &S) const override {
1004 Type->printLeft(S);
1005 if (!Type->hasRHSComponent(S))
1006 S += " ";
1153 void printLeft(OutputBuffer &OB) const override {
1154 Type->printLeft(OB);
1155 if (!Type->hasRHSComponent(OB))
1156 OB += " ";
10071157 }
10081158
1009 void printRight(OutputStream &S) const override {
1010 Name->print(S);
1011 Type->printRight(S);
1159 void printRight(OutputBuffer &OB) const override {
1160 Name->print(OB);
1161 Type->printRight(OB);
10121162 }
10131163};
10141164
......@@ -1025,15 +1175,13 @@ public:
10251175
10261176 template<typename Fn> void match(Fn F) const { F(Name, Params); }
10271177
1028 void printLeft(OutputStream &S) const override {
1029 S += "template<";
1030 Params.printWithComma(S);
1031 S += "> typename ";
1178 void printLeft(OutputBuffer &OB) const override {
1179 OB += "template<";
1180 Params.printWithComma(OB);
1181 OB += "> typename ";
10321182 }
10331183
1034 void printRight(OutputStream &S) const override {
1035 Name->print(S);
1036 }
1184 void printRight(OutputBuffer &OB) const override { Name->print(OB); }
10371185};
10381186
10391187/// A template parameter pack declaration, 'typename ...T'.
......@@ -1046,14 +1194,12 @@ public:
10461194
10471195 template<typename Fn> void match(Fn F) const { F(Param); }
10481196
1049 void printLeft(OutputStream &S) const override {
1050 Param->printLeft(S);
1051 S += "...";
1197 void printLeft(OutputBuffer &OB) const override {
1198 Param->printLeft(OB);
1199 OB += "...";
10521200 }
10531201
1054 void printRight(OutputStream &S) const override {
1055 Param->printRight(S);
1056 }
1202 void printRight(OutputBuffer &OB) const override { Param->printRight(OB); }
10571203};
10581204
10591205/// An unexpanded parameter pack (either in the expression or type context). If
......@@ -1067,11 +1213,12 @@ public:
10671213class ParameterPack final : public Node {
10681214 NodeArray Data;
10691215
1070 // Setup OutputStream for a pack expansion unless we're already expanding one.
1071 void initializePackExpansion(OutputStream &S) const {
1072 if (S.CurrentPackMax == std::numeric_limits<unsigned>::max()) {
1073 S.CurrentPackMax = static_cast<unsigned>(Data.size());
1074 S.CurrentPackIndex = 0;
1216 // Setup OutputBuffer for a pack expansion, unless we're already expanding
1217 // one.
1218 void initializePackExpansion(OutputBuffer &OB) const {
1219 if (OB.CurrentPackMax == std::numeric_limits<unsigned>::max()) {
1220 OB.CurrentPackMax = static_cast<unsigned>(Data.size());
1221 OB.CurrentPackIndex = 0;
10751222 }
10761223 }
10771224
......@@ -1094,38 +1241,38 @@ public:
10941241
10951242 template<typename Fn> void match(Fn F) const { F(Data); }
10961243
1097 bool hasRHSComponentSlow(OutputStream &S) const override {
1098 initializePackExpansion(S);
1099 size_t Idx = S.CurrentPackIndex;
1100 return Idx < Data.size() && Data[Idx]->hasRHSComponent(S);
1244 bool hasRHSComponentSlow(OutputBuffer &OB) const override {
1245 initializePackExpansion(OB);
1246 size_t Idx = OB.CurrentPackIndex;
1247 return Idx < Data.size() && Data[Idx]->hasRHSComponent(OB);
11011248 }
1102 bool hasArraySlow(OutputStream &S) const override {
1103 initializePackExpansion(S);
1104 size_t Idx = S.CurrentPackIndex;
1105 return Idx < Data.size() && Data[Idx]->hasArray(S);
1249 bool hasArraySlow(OutputBuffer &OB) const override {
1250 initializePackExpansion(OB);
1251 size_t Idx = OB.CurrentPackIndex;
1252 return Idx < Data.size() && Data[Idx]->hasArray(OB);
11061253 }
1107 bool hasFunctionSlow(OutputStream &S) const override {
1108 initializePackExpansion(S);
1109 size_t Idx = S.CurrentPackIndex;
1110 return Idx < Data.size() && Data[Idx]->hasFunction(S);
1254 bool hasFunctionSlow(OutputBuffer &OB) const override {
1255 initializePackExpansion(OB);
1256 size_t Idx = OB.CurrentPackIndex;
1257 return Idx < Data.size() && Data[Idx]->hasFunction(OB);
11111258 }
1112 const Node *getSyntaxNode(OutputStream &S) const override {
1113 initializePackExpansion(S);
1114 size_t Idx = S.CurrentPackIndex;
1115 return Idx < Data.size() ? Data[Idx]->getSyntaxNode(S) : this;
1259 const Node *getSyntaxNode(OutputBuffer &OB) const override {
1260 initializePackExpansion(OB);
1261 size_t Idx = OB.CurrentPackIndex;
1262 return Idx < Data.size() ? Data[Idx]->getSyntaxNode(OB) : this;
11161263 }
11171264
1118 void printLeft(OutputStream &S) const override {
1119 initializePackExpansion(S);
1120 size_t Idx = S.CurrentPackIndex;
1265 void printLeft(OutputBuffer &OB) const override {
1266 initializePackExpansion(OB);
1267 size_t Idx = OB.CurrentPackIndex;
11211268 if (Idx < Data.size())
1122 Data[Idx]->printLeft(S);
1269 Data[Idx]->printLeft(OB);
11231270 }
1124 void printRight(OutputStream &S) const override {
1125 initializePackExpansion(S);
1126 size_t Idx = S.CurrentPackIndex;
1271 void printRight(OutputBuffer &OB) const override {
1272 initializePackExpansion(OB);
1273 size_t Idx = OB.CurrentPackIndex;
11271274 if (Idx < Data.size())
1128 Data[Idx]->printRight(S);
1275 Data[Idx]->printRight(OB);
11291276 }
11301277};
11311278
......@@ -1144,8 +1291,8 @@ public:
11441291
11451292 NodeArray getElements() const { return Elements; }
11461293
1147 void printLeft(OutputStream &S) const override {
1148 Elements.printWithComma(S);
1294 void printLeft(OutputBuffer &OB) const override {
1295 Elements.printWithComma(OB);
11491296 }
11501297};
11511298
......@@ -1162,35 +1309,35 @@ public:
11621309
11631310 const Node *getChild() const { return Child; }
11641311
1165 void printLeft(OutputStream &S) const override {
1312 void printLeft(OutputBuffer &OB) const override {
11661313 constexpr unsigned Max = std::numeric_limits<unsigned>::max();
1167 SwapAndRestore<unsigned> SavePackIdx(S.CurrentPackIndex, Max);
1168 SwapAndRestore<unsigned> SavePackMax(S.CurrentPackMax, Max);
1169 size_t StreamPos = S.getCurrentPosition();
1314 SwapAndRestore<unsigned> SavePackIdx(OB.CurrentPackIndex, Max);
1315 SwapAndRestore<unsigned> SavePackMax(OB.CurrentPackMax, Max);
1316 size_t StreamPos = OB.getCurrentPosition();
11701317
11711318 // Print the first element in the pack. If Child contains a ParameterPack,
11721319 // it will set up S.CurrentPackMax and print the first element.
1173 Child->print(S);
1320 Child->print(OB);
11741321
11751322 // No ParameterPack was found in Child. This can occur if we've found a pack
11761323 // expansion on a <function-param>.
1177 if (S.CurrentPackMax == Max) {
1178 S += "...";
1324 if (OB.CurrentPackMax == Max) {
1325 OB += "...";
11791326 return;
11801327 }
11811328
11821329 // We found a ParameterPack, but it has no elements. Erase whatever we may
11831330 // of printed.
1184 if (S.CurrentPackMax == 0) {
1185 S.setCurrentPosition(StreamPos);
1331 if (OB.CurrentPackMax == 0) {
1332 OB.setCurrentPosition(StreamPos);
11861333 return;
11871334 }
11881335
11891336 // Else, iterate through the rest of the elements in the pack.
1190 for (unsigned I = 1, E = S.CurrentPackMax; I < E; ++I) {
1191 S += ", ";
1192 S.CurrentPackIndex = I;
1193 Child->print(S);
1337 for (unsigned I = 1, E = OB.CurrentPackMax; I < E; ++I) {
1338 OB += ", ";
1339 OB.CurrentPackIndex = I;
1340 Child->print(OB);
11941341 }
11951342 }
11961343};
......@@ -1205,12 +1352,12 @@ public:
12051352
12061353 NodeArray getParams() { return Params; }
12071354
1208 void printLeft(OutputStream &S) const override {
1209 S += "<";
1210 Params.printWithComma(S);
1211 if (S.back() == '>')
1212 S += " ";
1213 S += ">";
1355 void printLeft(OutputBuffer &OB) const override {
1356 OB += "<";
1357 Params.printWithComma(OB);
1358 if (OB.back() == '>')
1359 OB += " ";
1360 OB += ">";
12141361 }
12151362};
12161363
......@@ -1252,42 +1399,42 @@ struct ForwardTemplateReference : Node {
12521399 // special handling.
12531400 template<typename Fn> void match(Fn F) const = delete;
12541401
1255 bool hasRHSComponentSlow(OutputStream &S) const override {
1402 bool hasRHSComponentSlow(OutputBuffer &OB) const override {
12561403 if (Printing)
12571404 return false;
12581405 SwapAndRestore<bool> SavePrinting(Printing, true);
1259 return Ref->hasRHSComponent(S);
1406 return Ref->hasRHSComponent(OB);
12601407 }
1261 bool hasArraySlow(OutputStream &S) const override {
1408 bool hasArraySlow(OutputBuffer &OB) const override {
12621409 if (Printing)
12631410 return false;
12641411 SwapAndRestore<bool> SavePrinting(Printing, true);
1265 return Ref->hasArray(S);
1412 return Ref->hasArray(OB);
12661413 }
1267 bool hasFunctionSlow(OutputStream &S) const override {
1414 bool hasFunctionSlow(OutputBuffer &OB) const override {
12681415 if (Printing)
12691416 return false;
12701417 SwapAndRestore<bool> SavePrinting(Printing, true);
1271 return Ref->hasFunction(S);
1418 return Ref->hasFunction(OB);
12721419 }
1273 const Node *getSyntaxNode(OutputStream &S) const override {
1420 const Node *getSyntaxNode(OutputBuffer &OB) const override {
12741421 if (Printing)
12751422 return this;
12761423 SwapAndRestore<bool> SavePrinting(Printing, true);
1277 return Ref->getSyntaxNode(S);
1424 return Ref->getSyntaxNode(OB);
12781425 }
12791426
1280 void printLeft(OutputStream &S) const override {
1427 void printLeft(OutputBuffer &OB) const override {
12811428 if (Printing)
12821429 return;
12831430 SwapAndRestore<bool> SavePrinting(Printing, true);
1284 Ref->printLeft(S);
1431 Ref->printLeft(OB);
12851432 }
1286 void printRight(OutputStream &S) const override {
1433 void printRight(OutputBuffer &OB) const override {
12871434 if (Printing)
12881435 return;
12891436 SwapAndRestore<bool> SavePrinting(Printing, true);
1290 Ref->printRight(S);
1437 Ref->printRight(OB);
12911438 }
12921439};
12931440
......@@ -1303,9 +1450,9 @@ struct NameWithTemplateArgs : Node {
13031450
13041451 StringView getBaseName() const override { return Name->getBaseName(); }
13051452
1306 void printLeft(OutputStream &S) const override {
1307 Name->print(S);
1308 TemplateArgs->print(S);
1453 void printLeft(OutputBuffer &OB) const override {
1454 Name->print(OB);
1455 TemplateArgs->print(OB);
13091456 }
13101457};
13111458
......@@ -1320,9 +1467,9 @@ public:
13201467
13211468 StringView getBaseName() const override { return Child->getBaseName(); }
13221469
1323 void printLeft(OutputStream &S) const override {
1324 S += "::";
1325 Child->print(S);
1470 void printLeft(OutputBuffer &OB) const override {
1471 OB += "::";
1472 Child->print(OB);
13261473 }
13271474};
13281475
......@@ -1335,9 +1482,9 @@ struct StdQualifiedName : Node {
13351482
13361483 StringView getBaseName() const override { return Child->getBaseName(); }
13371484
1338 void printLeft(OutputStream &S) const override {
1339 S += "std::";
1340 Child->print(S);
1485 void printLeft(OutputBuffer &OB) const override {
1486 OB += "std::";
1487 Child->print(OB);
13411488 }
13421489};
13431490
......@@ -1377,26 +1524,26 @@ public:
13771524 DEMANGLE_UNREACHABLE;
13781525 }
13791526
1380 void printLeft(OutputStream &S) const override {
1527 void printLeft(OutputBuffer &OB) const override {
13811528 switch (SSK) {
13821529 case SpecialSubKind::allocator:
1383 S += "std::allocator";
1530 OB += "std::allocator";
13841531 break;
13851532 case SpecialSubKind::basic_string:
1386 S += "std::basic_string";
1533 OB += "std::basic_string";
13871534 break;
13881535 case SpecialSubKind::string:
1389 S += "std::basic_string<char, std::char_traits<char>, "
1390 "std::allocator<char> >";
1536 OB += "std::basic_string<char, std::char_traits<char>, "
1537 "std::allocator<char> >";
13911538 break;
13921539 case SpecialSubKind::istream:
1393 S += "std::basic_istream<char, std::char_traits<char> >";
1540 OB += "std::basic_istream<char, std::char_traits<char> >";
13941541 break;
13951542 case SpecialSubKind::ostream:
1396 S += "std::basic_ostream<char, std::char_traits<char> >";
1543 OB += "std::basic_ostream<char, std::char_traits<char> >";
13971544 break;
13981545 case SpecialSubKind::iostream:
1399 S += "std::basic_iostream<char, std::char_traits<char> >";
1546 OB += "std::basic_iostream<char, std::char_traits<char> >";
14001547 break;
14011548 }
14021549 }
......@@ -1429,25 +1576,25 @@ public:
14291576 DEMANGLE_UNREACHABLE;
14301577 }
14311578
1432 void printLeft(OutputStream &S) const override {
1579 void printLeft(OutputBuffer &OB) const override {
14331580 switch (SSK) {
14341581 case SpecialSubKind::allocator:
1435 S += "std::allocator";
1582 OB += "std::allocator";
14361583 break;
14371584 case SpecialSubKind::basic_string:
1438 S += "std::basic_string";
1585 OB += "std::basic_string";
14391586 break;
14401587 case SpecialSubKind::string:
1441 S += "std::string";
1588 OB += "std::string";
14421589 break;
14431590 case SpecialSubKind::istream:
1444 S += "std::istream";
1591 OB += "std::istream";
14451592 break;
14461593 case SpecialSubKind::ostream:
1447 S += "std::ostream";
1594 OB += "std::ostream";
14481595 break;
14491596 case SpecialSubKind::iostream:
1450 S += "std::iostream";
1597 OB += "std::iostream";
14511598 break;
14521599 }
14531600 }
......@@ -1465,10 +1612,10 @@ public:
14651612
14661613 template<typename Fn> void match(Fn F) const { F(Basename, IsDtor, Variant); }
14671614
1468 void printLeft(OutputStream &S) const override {
1615 void printLeft(OutputBuffer &OB) const override {
14691616 if (IsDtor)
1470 S += "~";
1471 S += Basename->getBaseName();
1617 OB += "~";
1618 OB += Basename->getBaseName();
14721619 }
14731620};
14741621
......@@ -1480,9 +1627,9 @@ public:
14801627
14811628 template<typename Fn> void match(Fn F) const { F(Base); }
14821629
1483 void printLeft(OutputStream &S) const override {
1484 S += "~";
1485 Base->printLeft(S);
1630 void printLeft(OutputBuffer &OB) const override {
1631 OB += "~";
1632 Base->printLeft(OB);
14861633 }
14871634};
14881635
......@@ -1494,10 +1641,10 @@ public:
14941641
14951642 template<typename Fn> void match(Fn F) const { F(Count); }
14961643
1497 void printLeft(OutputStream &S) const override {
1498 S += "'unnamed";
1499 S += Count;
1500 S += "\'";
1644 void printLeft(OutputBuffer &OB) const override {
1645 OB += "'unnamed";
1646 OB += Count;
1647 OB += "\'";
15011648 }
15021649};
15031650
......@@ -1516,22 +1663,22 @@ public:
15161663 F(TemplateParams, Params, Count);
15171664 }
15181665
1519 void printDeclarator(OutputStream &S) const {
1666 void printDeclarator(OutputBuffer &OB) const {
15201667 if (!TemplateParams.empty()) {
1521 S += "<";
1522 TemplateParams.printWithComma(S);
1523 S += ">";
1668 OB += "<";
1669 TemplateParams.printWithComma(OB);
1670 OB += ">";
15241671 }
1525 S += "(";
1526 Params.printWithComma(S);
1527 S += ")";
1672 OB += "(";
1673 Params.printWithComma(OB);
1674 OB += ")";
15281675 }
15291676
1530 void printLeft(OutputStream &S) const override {
1531 S += "\'lambda";
1532 S += Count;
1533 S += "\'";
1534 printDeclarator(S);
1677 void printLeft(OutputBuffer &OB) const override {
1678 OB += "\'lambda";
1679 OB += Count;
1680 OB += "\'";
1681 printDeclarator(OB);
15351682 }
15361683};
15371684
......@@ -1543,10 +1690,10 @@ public:
15431690
15441691 template<typename Fn> void match(Fn F) const { F(Bindings); }
15451692
1546 void printLeft(OutputStream &S) const override {
1547 S += '[';
1548 Bindings.printWithComma(S);
1549 S += ']';
1693 void printLeft(OutputBuffer &OB) const override {
1694 OB += '[';
1695 Bindings.printWithComma(OB);
1696 OB += ']';
15501697 }
15511698};
15521699
......@@ -1564,22 +1711,22 @@ public:
15641711
15651712 template<typename Fn> void match(Fn F) const { F(LHS, InfixOperator, RHS); }
15661713
1567 void printLeft(OutputStream &S) const override {
1714 void printLeft(OutputBuffer &OB) const override {
15681715 // might be a template argument expression, then we need to disambiguate
15691716 // with parens.
15701717 if (InfixOperator == ">")
1571 S += "(";
1718 OB += "(";
15721719
1573 S += "(";
1574 LHS->print(S);
1575 S += ") ";
1576 S += InfixOperator;
1577 S += " (";
1578 RHS->print(S);
1579 S += ")";
1720 OB += "(";
1721 LHS->print(OB);
1722 OB += ") ";
1723 OB += InfixOperator;
1724 OB += " (";
1725 RHS->print(OB);
1726 OB += ")";
15801727
15811728 if (InfixOperator == ">")
1582 S += ")";
1729 OB += ")";
15831730 }
15841731};
15851732
......@@ -1593,12 +1740,12 @@ public:
15931740
15941741 template<typename Fn> void match(Fn F) const { F(Op1, Op2); }
15951742
1596 void printLeft(OutputStream &S) const override {
1597 S += "(";
1598 Op1->print(S);
1599 S += ")[";
1600 Op2->print(S);
1601 S += "]";
1743 void printLeft(OutputBuffer &OB) const override {
1744 OB += "(";
1745 Op1->print(OB);
1746 OB += ")[";
1747 Op2->print(OB);
1748 OB += "]";
16021749 }
16031750};
16041751
......@@ -1612,11 +1759,11 @@ public:
16121759
16131760 template<typename Fn> void match(Fn F) const { F(Child, Operator); }
16141761
1615 void printLeft(OutputStream &S) const override {
1616 S += "(";
1617 Child->print(S);
1618 S += ")";
1619 S += Operator;
1762 void printLeft(OutputBuffer &OB) const override {
1763 OB += "(";
1764 Child->print(OB);
1765 OB += ")";
1766 OB += Operator;
16201767 }
16211768};
16221769
......@@ -1631,14 +1778,14 @@ public:
16311778
16321779 template<typename Fn> void match(Fn F) const { F(Cond, Then, Else); }
16331780
1634 void printLeft(OutputStream &S) const override {
1635 S += "(";
1636 Cond->print(S);
1637 S += ") ? (";
1638 Then->print(S);
1639 S += ") : (";
1640 Else->print(S);
1641 S += ")";
1781 void printLeft(OutputBuffer &OB) const override {
1782 OB += "(";
1783 Cond->print(OB);
1784 OB += ") ? (";
1785 Then->print(OB);
1786 OB += ") : (";
1787 Else->print(OB);
1788 OB += ")";
16421789 }
16431790};
16441791
......@@ -1653,10 +1800,10 @@ public:
16531800
16541801 template<typename Fn> void match(Fn F) const { F(LHS, Kind, RHS); }
16551802
1656 void printLeft(OutputStream &S) const override {
1657 LHS->print(S);
1658 S += Kind;
1659 RHS->print(S);
1803 void printLeft(OutputBuffer &OB) const override {
1804 LHS->print(OB);
1805 OB += Kind;
1806 RHS->print(OB);
16601807 }
16611808};
16621809
......@@ -1677,20 +1824,20 @@ public:
16771824 F(Type, SubExpr, Offset, UnionSelectors, OnePastTheEnd);
16781825 }
16791826
1680 void printLeft(OutputStream &S) const override {
1681 SubExpr->print(S);
1682 S += ".<";
1683 Type->print(S);
1684 S += " at offset ";
1827 void printLeft(OutputBuffer &OB) const override {
1828 SubExpr->print(OB);
1829 OB += ".<";
1830 Type->print(OB);
1831 OB += " at offset ";
16851832 if (Offset.empty()) {
1686 S += "0";
1833 OB += "0";
16871834 } else if (Offset[0] == 'n') {
1688 S += "-";
1689 S += Offset.dropFront();
1835 OB += "-";
1836 OB += Offset.dropFront();
16901837 } else {
1691 S += Offset;
1838 OB += Offset;
16921839 }
1693 S += ">";
1840 OB += ">";
16941841 }
16951842};
16961843
......@@ -1706,10 +1853,10 @@ public:
17061853
17071854 template<typename Fn> void match(Fn F) const { F(Prefix, Infix, Postfix); }
17081855
1709 void printLeft(OutputStream &S) const override {
1710 S += Prefix;
1711 Infix->print(S);
1712 S += Postfix;
1856 void printLeft(OutputBuffer &OB) const override {
1857 OB += Prefix;
1858 Infix->print(OB);
1859 OB += Postfix;
17131860 }
17141861};
17151862
......@@ -1725,13 +1872,13 @@ public:
17251872
17261873 template<typename Fn> void match(Fn F) const { F(CastKind, To, From); }
17271874
1728 void printLeft(OutputStream &S) const override {
1729 S += CastKind;
1730 S += "<";
1731 To->printLeft(S);
1732 S += ">(";
1733 From->printLeft(S);
1734 S += ")";
1875 void printLeft(OutputBuffer &OB) const override {
1876 OB += CastKind;
1877 OB += "<";
1878 To->printLeft(OB);
1879 OB += ">(";
1880 From->printLeft(OB);
1881 OB += ")";
17351882 }
17361883};
17371884
......@@ -1744,11 +1891,11 @@ public:
17441891
17451892 template<typename Fn> void match(Fn F) const { F(Pack); }
17461893
1747 void printLeft(OutputStream &S) const override {
1748 S += "sizeof...(";
1894 void printLeft(OutputBuffer &OB) const override {
1895 OB += "sizeof...(";
17491896 ParameterPackExpansion PPE(Pack);
1750 PPE.printLeft(S);
1751 S += ")";
1897 PPE.printLeft(OB);
1898 OB += ")";
17521899 }
17531900};
17541901
......@@ -1762,11 +1909,11 @@ public:
17621909
17631910 template<typename Fn> void match(Fn F) const { F(Callee, Args); }
17641911
1765 void printLeft(OutputStream &S) const override {
1766 Callee->print(S);
1767 S += "(";
1768 Args.printWithComma(S);
1769 S += ")";
1912 void printLeft(OutputBuffer &OB) const override {
1913 Callee->print(OB);
1914 OB += "(";
1915 Args.printWithComma(OB);
1916 OB += ")";
17701917 }
17711918};
17721919
......@@ -1787,25 +1934,24 @@ public:
17871934 F(ExprList, Type, InitList, IsGlobal, IsArray);
17881935 }
17891936
1790 void printLeft(OutputStream &S) const override {
1937 void printLeft(OutputBuffer &OB) const override {
17911938 if (IsGlobal)
1792 S += "::operator ";
1793 S += "new";
1939 OB += "::operator ";
1940 OB += "new";
17941941 if (IsArray)
1795 S += "[]";
1796 S += ' ';
1942 OB += "[]";
1943 OB += ' ';
17971944 if (!ExprList.empty()) {
1798 S += "(";
1799 ExprList.printWithComma(S);
1800 S += ")";
1945 OB += "(";
1946 ExprList.printWithComma(OB);
1947 OB += ")";
18011948 }
1802 Type->print(S);
1949 Type->print(OB);
18031950 if (!InitList.empty()) {
1804 S += "(";
1805 InitList.printWithComma(S);
1806 S += ")";
1951 OB += "(";
1952 InitList.printWithComma(OB);
1953 OB += ")";
18071954 }
1808
18091955 }
18101956};
18111957
......@@ -1820,13 +1966,13 @@ public:
18201966
18211967 template<typename Fn> void match(Fn F) const { F(Op, IsGlobal, IsArray); }
18221968
1823 void printLeft(OutputStream &S) const override {
1969 void printLeft(OutputBuffer &OB) const override {
18241970 if (IsGlobal)
1825 S += "::";
1826 S += "delete";
1971 OB += "::";
1972 OB += "delete";
18271973 if (IsArray)
1828 S += "[] ";
1829 Op->print(S);
1974 OB += "[] ";
1975 Op->print(OB);
18301976 }
18311977};
18321978
......@@ -1840,11 +1986,11 @@ public:
18401986
18411987 template<typename Fn> void match(Fn F) const { F(Prefix, Child); }
18421988
1843 void printLeft(OutputStream &S) const override {
1844 S += Prefix;
1845 S += "(";
1846 Child->print(S);
1847 S += ")";
1989 void printLeft(OutputBuffer &OB) const override {
1990 OB += Prefix;
1991 OB += "(";
1992 Child->print(OB);
1993 OB += ")";
18481994 }
18491995};
18501996
......@@ -1856,9 +2002,9 @@ public:
18562002
18572003 template<typename Fn> void match(Fn F) const { F(Number); }
18582004
1859 void printLeft(OutputStream &S) const override {
1860 S += "fp";
1861 S += Number;
2005 void printLeft(OutputBuffer &OB) const override {
2006 OB += "fp";
2007 OB += Number;
18622008 }
18632009};
18642010
......@@ -1872,12 +2018,12 @@ public:
18722018
18732019 template<typename Fn> void match(Fn F) const { F(Type, Expressions); }
18742020
1875 void printLeft(OutputStream &S) const override {
1876 S += "(";
1877 Type->print(S);
1878 S += ")(";
1879 Expressions.printWithComma(S);
1880 S += ")";
2021 void printLeft(OutputBuffer &OB) const override {
2022 OB += "(";
2023 Type->print(OB);
2024 OB += ")(";
2025 Expressions.printWithComma(OB);
2026 OB += ")";
18812027 }
18822028};
18832029
......@@ -1894,12 +2040,12 @@ public:
18942040
18952041 template<typename Fn> void match(Fn F) const { F(Type, SubExpr, Offset); }
18962042
1897 void printLeft(OutputStream &S) const override {
1898 S += "(";
1899 Type->print(S);
1900 S += ")(";
1901 SubExpr->print(S);
1902 S += ")";
2043 void printLeft(OutputBuffer &OB) const override {
2044 OB += "(";
2045 Type->print(OB);
2046 OB += ")(";
2047 SubExpr->print(OB);
2048 OB += ")";
19032049 }
19042050};
19052051
......@@ -1912,12 +2058,12 @@ public:
19122058
19132059 template<typename Fn> void match(Fn F) const { F(Ty, Inits); }
19142060
1915 void printLeft(OutputStream &S) const override {
2061 void printLeft(OutputBuffer &OB) const override {
19162062 if (Ty)
1917 Ty->print(S);
1918 S += '{';
1919 Inits.printWithComma(S);
1920 S += '}';
2063 Ty->print(OB);
2064 OB += '{';
2065 Inits.printWithComma(OB);
2066 OB += '}';
19212067 }
19222068};
19232069
......@@ -1931,18 +2077,18 @@ public:
19312077
19322078 template<typename Fn> void match(Fn F) const { F(Elem, Init, IsArray); }
19332079
1934 void printLeft(OutputStream &S) const override {
2080 void printLeft(OutputBuffer &OB) const override {
19352081 if (IsArray) {
1936 S += '[';
1937 Elem->print(S);
1938 S += ']';
2082 OB += '[';
2083 Elem->print(OB);
2084 OB += ']';
19392085 } else {
1940 S += '.';
1941 Elem->print(S);
2086 OB += '.';
2087 Elem->print(OB);
19422088 }
19432089 if (Init->getKind() != KBracedExpr && Init->getKind() != KBracedRangeExpr)
1944 S += " = ";
1945 Init->print(S);
2090 OB += " = ";
2091 Init->print(OB);
19462092 }
19472093};
19482094
......@@ -1956,15 +2102,15 @@ public:
19562102
19572103 template<typename Fn> void match(Fn F) const { F(First, Last, Init); }
19582104
1959 void printLeft(OutputStream &S) const override {
1960 S += '[';
1961 First->print(S);
1962 S += " ... ";
1963 Last->print(S);
1964 S += ']';
2105 void printLeft(OutputBuffer &OB) const override {
2106 OB += '[';
2107 First->print(OB);
2108 OB += " ... ";
2109 Last->print(OB);
2110 OB += ']';
19652111 if (Init->getKind() != KBracedExpr && Init->getKind() != KBracedRangeExpr)
1966 S += " = ";
1967 Init->print(S);
2112 OB += " = ";
2113 Init->print(OB);
19682114 }
19692115};
19702116
......@@ -1983,43 +2129,43 @@ public:
19832129 F(IsLeftFold, OperatorName, Pack, Init);
19842130 }
19852131
1986 void printLeft(OutputStream &S) const override {
2132 void printLeft(OutputBuffer &OB) const override {
19872133 auto PrintPack = [&] {
1988 S += '(';
1989 ParameterPackExpansion(Pack).print(S);
1990 S += ')';
2134 OB += '(';
2135 ParameterPackExpansion(Pack).print(OB);
2136 OB += ')';
19912137 };
19922138
1993 S += '(';
2139 OB += '(';
19942140
19952141 if (IsLeftFold) {
19962142 // init op ... op pack
19972143 if (Init != nullptr) {
1998 Init->print(S);
1999 S += ' ';
2000 S += OperatorName;
2001 S += ' ';
2144 Init->print(OB);
2145 OB += ' ';
2146 OB += OperatorName;
2147 OB += ' ';
20022148 }
20032149 // ... op pack
2004 S += "... ";
2005 S += OperatorName;
2006 S += ' ';
2150 OB += "... ";
2151 OB += OperatorName;
2152 OB += ' ';
20072153 PrintPack();
20082154 } else { // !IsLeftFold
20092155 // pack op ...
20102156 PrintPack();
2011 S += ' ';
2012 S += OperatorName;
2013 S += " ...";
2157 OB += ' ';
2158 OB += OperatorName;
2159 OB += " ...";
20142160 // pack op ... op init
20152161 if (Init != nullptr) {
2016 S += ' ';
2017 S += OperatorName;
2018 S += ' ';
2019 Init->print(S);
2162 OB += ' ';
2163 OB += OperatorName;
2164 OB += ' ';
2165 Init->print(OB);
20202166 }
20212167 }
2022 S += ')';
2168 OB += ')';
20232169 }
20242170};
20252171
......@@ -2031,9 +2177,9 @@ public:
20312177
20322178 template<typename Fn> void match(Fn F) const { F(Op); }
20332179
2034 void printLeft(OutputStream &S) const override {
2035 S += "throw ";
2036 Op->print(S);
2180 void printLeft(OutputBuffer &OB) const override {
2181 OB += "throw ";
2182 Op->print(OB);
20372183 }
20382184};
20392185
......@@ -2045,8 +2191,8 @@ public:
20452191
20462192 template<typename Fn> void match(Fn F) const { F(Value); }
20472193
2048 void printLeft(OutputStream &S) const override {
2049 S += Value ? StringView("true") : StringView("false");
2194 void printLeft(OutputBuffer &OB) const override {
2195 OB += Value ? StringView("true") : StringView("false");
20502196 }
20512197};
20522198
......@@ -2058,10 +2204,10 @@ public:
20582204
20592205 template<typename Fn> void match(Fn F) const { F(Type); }
20602206
2061 void printLeft(OutputStream &S) const override {
2062 S += "\"<";
2063 Type->print(S);
2064 S += ">\"";
2207 void printLeft(OutputBuffer &OB) const override {
2208 OB += "\"<";
2209 Type->print(OB);
2210 OB += ">\"";
20652211 }
20662212};
20672213
......@@ -2073,11 +2219,11 @@ public:
20732219
20742220 template<typename Fn> void match(Fn F) const { F(Type); }
20752221
2076 void printLeft(OutputStream &S) const override {
2077 S += "[]";
2222 void printLeft(OutputBuffer &OB) const override {
2223 OB += "[]";
20782224 if (Type->getKind() == KClosureTypeName)
2079 static_cast<const ClosureTypeName *>(Type)->printDeclarator(S);
2080 S += "{...}";
2225 static_cast<const ClosureTypeName *>(Type)->printDeclarator(OB);
2226 OB += "{...}";
20812227 }
20822228};
20832229
......@@ -2092,15 +2238,15 @@ public:
20922238
20932239 template<typename Fn> void match(Fn F) const { F(Ty, Integer); }
20942240
2095 void printLeft(OutputStream &S) const override {
2096 S << "(";
2097 Ty->print(S);
2098 S << ")";
2241 void printLeft(OutputBuffer &OB) const override {
2242 OB << "(";
2243 Ty->print(OB);
2244 OB << ")";
20992245
21002246 if (Integer[0] == 'n')
2101 S << "-" << Integer.dropFront(1);
2247 OB << "-" << Integer.dropFront(1);
21022248 else
2103 S << Integer;
2249 OB << Integer;
21042250 }
21052251};
21062252
......@@ -2114,21 +2260,21 @@ public:
21142260
21152261 template<typename Fn> void match(Fn F) const { F(Type, Value); }
21162262
2117 void printLeft(OutputStream &S) const override {
2263 void printLeft(OutputBuffer &OB) const override {
21182264 if (Type.size() > 3) {
2119 S += "(";
2120 S += Type;
2121 S += ")";
2265 OB += "(";
2266 OB += Type;
2267 OB += ")";
21222268 }
21232269
21242270 if (Value[0] == 'n') {
2125 S += "-";
2126 S += Value.dropFront(1);
2271 OB += "-";
2272 OB += Value.dropFront(1);
21272273 } else
2128 S += Value;
2274 OB += Value;
21292275
21302276 if (Type.size() <= 3)
2131 S += Type;
2277 OB += Type;
21322278 }
21332279};
21342280
......@@ -2158,7 +2304,7 @@ public:
21582304
21592305 template<typename Fn> void match(Fn F) const { F(Contents); }
21602306
2161 void printLeft(OutputStream &s) const override {
2307 void printLeft(OutputBuffer &OB) const override {
21622308 const char *first = Contents.begin();
21632309 const char *last = Contents.end() + 1;
21642310
......@@ -2184,7 +2330,7 @@ public:
21842330#endif
21852331 char num[FloatData<Float>::max_demangled_size] = {0};
21862332 int n = snprintf(num, sizeof(num), FloatData<Float>::spec, value);
2187 s += StringView(num, num + n);
2333 OB += StringView(num, num + n);
21882334 }
21892335 }
21902336};
......@@ -2217,125 +2363,6 @@ FOR_EACH_NODE_KIND(SPECIALIZATION)
22172363
22182364#undef FOR_EACH_NODE_KIND
22192365
2220template <class T, size_t N>
2221class PODSmallVector {
2222 static_assert(std::is_pod<T>::value,
2223 "T is required to be a plain old data type");
2224
2225 T* First = nullptr;
2226 T* Last = nullptr;
2227 T* Cap = nullptr;
2228 T Inline[N] = {0};
2229
2230 bool isInline() const { return First == Inline; }
2231
2232 void clearInline() {
2233 First = Inline;
2234 Last = Inline;
2235 Cap = Inline + N;
2236 }
2237
2238 void reserve(size_t NewCap) {
2239 size_t S = size();
2240 if (isInline()) {
2241 auto* Tmp = static_cast<T*>(std::malloc(NewCap * sizeof(T)));
2242 if (Tmp == nullptr)
2243 std::terminate();
2244 std::copy(First, Last, Tmp);
2245 First = Tmp;
2246 } else {
2247 First = static_cast<T*>(std::realloc(First, NewCap * sizeof(T)));
2248 if (First == nullptr)
2249 std::terminate();
2250 }
2251 Last = First + S;
2252 Cap = First + NewCap;
2253 }
2254
2255public:
2256 PODSmallVector() : First(Inline), Last(First), Cap(Inline + N) {}
2257
2258 PODSmallVector(const PODSmallVector&) = delete;
2259 PODSmallVector& operator=(const PODSmallVector&) = delete;
2260
2261 PODSmallVector(PODSmallVector&& Other) : PODSmallVector() {
2262 if (Other.isInline()) {
2263 std::copy(Other.begin(), Other.end(), First);
2264 Last = First + Other.size();
2265 Other.clear();
2266 return;
2267 }
2268
2269 First = Other.First;
2270 Last = Other.Last;
2271 Cap = Other.Cap;
2272 Other.clearInline();
2273 }
2274
2275 PODSmallVector& operator=(PODSmallVector&& Other) {
2276 if (Other.isInline()) {
2277 if (!isInline()) {
2278 std::free(First);
2279 clearInline();
2280 }
2281 std::copy(Other.begin(), Other.end(), First);
2282 Last = First + Other.size();
2283 Other.clear();
2284 return *this;
2285 }
2286
2287 if (isInline()) {
2288 First = Other.First;
2289 Last = Other.Last;
2290 Cap = Other.Cap;
2291 Other.clearInline();
2292 return *this;
2293 }
2294
2295 std::swap(First, Other.First);
2296 std::swap(Last, Other.Last);
2297 std::swap(Cap, Other.Cap);
2298 Other.clear();
2299 return *this;
2300 }
2301
2302 void push_back(const T& Elem) {
2303 if (Last == Cap)
2304 reserve(size() * 2);
2305 *Last++ = Elem;
2306 }
2307
2308 void pop_back() {
2309 assert(Last != First && "Popping empty vector!");
2310 --Last;
2311 }
2312
2313 void dropBack(size_t Index) {
2314 assert(Index <= size() && "dropBack() can't expand!");
2315 Last = First + Index;
2316 }
2317
2318 T* begin() { return First; }
2319 T* end() { return Last; }
2320
2321 bool empty() const { return First == Last; }
2322 size_t size() const { return static_cast<size_t>(Last - First); }
2323 T& back() {
2324 assert(Last != First && "Calling back() on empty vector!");
2325 return *(Last - 1);
2326 }
2327 T& operator[](size_t Index) {
2328 assert(Index < size() && "Invalid access!");
2329 return *(begin() + Index);
2330 }
2331 void clear() { Last = First; }
2332
2333 ~PODSmallVector() {
2334 if (!isInline())
2335 std::free(First);
2336 }
2337};
2338
23392366template <typename Derived, typename Alloc> struct AbstractManglingParser {
23402367 const char *First;
23412368 const char *Last;
......@@ -2450,7 +2477,7 @@ template <typename Derived, typename Alloc> struct AbstractManglingParser {
24502477
24512478 char consume() { return First != Last ? *First++ : '\0'; }
24522479
2453 char look(unsigned Lookahead = 0) {
2480 char look(unsigned Lookahead = 0) const {
24542481 if (static_cast<size_t>(Last - First) <= Lookahead)
24552482 return '\0';
24562483 return First[Lookahead];
......@@ -2568,34 +2595,38 @@ Node *AbstractManglingParser<Derived, Alloc>::parseName(NameState *State) {
25682595 if (look() == 'Z')
25692596 return getDerived().parseLocalName(State);
25702597
2571 // ::= <unscoped-template-name> <template-args>
2572 if (look() == 'S' && look(1) != 't') {
2573 Node *S = getDerived().parseSubstitution();
2574 if (S == nullptr)
2575 return nullptr;
2576 if (look() != 'I')
2577 return nullptr;
2578 Node *TA = getDerived().parseTemplateArgs(State != nullptr);
2579 if (TA == nullptr)
2580 return nullptr;
2581 if (State) State->EndsWithTemplateArgs = true;
2582 return make<NameWithTemplateArgs>(S, TA);
2598 Node *Result = nullptr;
2599 bool IsSubst = look() == 'S' && look(1) != 't';
2600 if (IsSubst) {
2601 // A substitution must lead to:
2602 // ::= <unscoped-template-name> <template-args>
2603 Result = getDerived().parseSubstitution();
2604 } else {
2605 // An unscoped name can be one of:
2606 // ::= <unscoped-name>
2607 // ::= <unscoped-template-name> <template-args>
2608 Result = getDerived().parseUnscopedName(State);
25832609 }
2584
2585 Node *N = getDerived().parseUnscopedName(State);
2586 if (N == nullptr)
2610 if (Result == nullptr)
25872611 return nullptr;
2588 // ::= <unscoped-template-name> <template-args>
2612
25892613 if (look() == 'I') {
2590 Subs.push_back(N);
2614 // ::= <unscoped-template-name> <template-args>
2615 if (!IsSubst)
2616 // An unscoped-template-name is substitutable.
2617 Subs.push_back(Result);
25912618 Node *TA = getDerived().parseTemplateArgs(State != nullptr);
25922619 if (TA == nullptr)
25932620 return nullptr;
2594 if (State) State->EndsWithTemplateArgs = true;
2595 return make<NameWithTemplateArgs>(N, TA);
2621 if (State)
2622 State->EndsWithTemplateArgs = true;
2623 Result = make<NameWithTemplateArgs>(Result, TA);
2624 } else if (IsSubst) {
2625 // The substitution case must be followed by <template-args>.
2626 return nullptr;
25962627 }
2597 // ::= <unscoped-name>
2598 return N;
2628
2629 return Result;
25992630}
26002631
26012632// <local-name> := Z <function encoding> E <entity name> [<discriminator>]
......@@ -2640,13 +2671,17 @@ Node *AbstractManglingParser<Derived, Alloc>::parseLocalName(NameState *State) {
26402671template <typename Derived, typename Alloc>
26412672Node *
26422673AbstractManglingParser<Derived, Alloc>::parseUnscopedName(NameState *State) {
2643 if (consumeIf("StL") || consumeIf("St")) {
2644 Node *R = getDerived().parseUnqualifiedName(State);
2645 if (R == nullptr)
2646 return nullptr;
2647 return make<StdQualifiedName>(R);
2648 }
2649 return getDerived().parseUnqualifiedName(State);
2674 bool IsStd = consumeIf("St");
2675 if (IsStd)
2676 consumeIf('L');
2677
2678 Node *Result = getDerived().parseUnqualifiedName(State);
2679 if (Result == nullptr)
2680 return nullptr;
2681 if (IsStd)
2682 Result = make<StdQualifiedName>(Result);
2683
2684 return Result;
26502685}
26512686
26522687// <unqualified-name> ::= <operator-name> [abi-tags]
......@@ -3884,6 +3919,16 @@ Node *AbstractManglingParser<Derived, Alloc>::parseType() {
38843919 case 'h':
38853920 First += 2;
38863921 return make<NameType>("half");
3922 // ::= DF <number> _ # ISO/IEC TS 18661 binary floating point (N bits)
3923 case 'F': {
3924 First += 2;
3925 Node *DimensionNumber = make<NameType>(parseNumber());
3926 if (!DimensionNumber)
3927 return nullptr;
3928 if (!consumeIf('_'))
3929 return nullptr;
3930 return make<BinaryFPType>(DimensionNumber);
3931 }
38873932 // ::= Di # char32_t
38883933 case 'i':
38893934 First += 2;
......@@ -4031,9 +4076,9 @@ Node *AbstractManglingParser<Derived, Alloc>::parseType() {
40314076 }
40324077 // ::= <substitution> # See Compression below
40334078 case 'S': {
4034 if (look(1) && look(1) != 't') {
4035 Node *Sub = getDerived().parseSubstitution();
4036 if (Sub == nullptr)
4079 if (look(1) != 't') {
4080 Result = getDerived().parseSubstitution();
4081 if (Result == nullptr)
40374082 return nullptr;
40384083
40394084 // Sub could be either of:
......@@ -4050,13 +4095,13 @@ Node *AbstractManglingParser<Derived, Alloc>::parseType() {
40504095 Node *TA = getDerived().parseTemplateArgs();
40514096 if (TA == nullptr)
40524097 return nullptr;
4053 Result = make<NameWithTemplateArgs>(Sub, TA);
4054 break;
4098 Result = make<NameWithTemplateArgs>(Result, TA);
4099 } else {
4100 // If all we parsed was a substitution, don't re-insert into the
4101 // substitution table.
4102 return Result;
40554103 }
4056
4057 // If all we parsed was a substitution, don't re-insert into the
4058 // substitution table.
4059 return Sub;
4104 break;
40604105 }
40614106 DEMANGLE_FALLTHROUGH;
40624107 }
......@@ -5404,38 +5449,35 @@ Node *AbstractManglingParser<Derived, Alloc>::parseSubstitution() {
54045449 if (!consumeIf('S'))
54055450 return nullptr;
54065451
5407 if (std::islower(look())) {
5408 Node *SpecialSub;
5452 if (look() >= 'a' && look() <= 'z') {
5453 SpecialSubKind Kind;
54095454 switch (look()) {
54105455 case 'a':
5411 ++First;
5412 SpecialSub = make<SpecialSubstitution>(SpecialSubKind::allocator);
5456 Kind = SpecialSubKind::allocator;
54135457 break;
54145458 case 'b':
5415 ++First;
5416 SpecialSub = make<SpecialSubstitution>(SpecialSubKind::basic_string);
5459 Kind = SpecialSubKind::basic_string;
54175460 break;
5418 case 's':
5419 ++First;
5420 SpecialSub = make<SpecialSubstitution>(SpecialSubKind::string);
5461 case 'd':
5462 Kind = SpecialSubKind::iostream;
54215463 break;
54225464 case 'i':
5423 ++First;
5424 SpecialSub = make<SpecialSubstitution>(SpecialSubKind::istream);
5465 Kind = SpecialSubKind::istream;
54255466 break;
54265467 case 'o':
5427 ++First;
5428 SpecialSub = make<SpecialSubstitution>(SpecialSubKind::ostream);
5468 Kind = SpecialSubKind::ostream;
54295469 break;
5430 case 'd':
5431 ++First;
5432 SpecialSub = make<SpecialSubstitution>(SpecialSubKind::iostream);
5470 case 's':
5471 Kind = SpecialSubKind::string;
54335472 break;
54345473 default:
54355474 return nullptr;
54365475 }
5476 ++First;
5477 auto *SpecialSub = make<SpecialSubstitution>(Kind);
54375478 if (!SpecialSub)
54385479 return nullptr;
5480
54395481 // Itanium C++ ABI 5.1.2: If a name that would use a built-in <substitution>
54405482 // has ABI tags, the tags are appended to the substitution; the result is a
54415483 // substitutable component.
lib/libcxxabi/src/demangle/StringView.h+10-7
......@@ -7,6 +7,9 @@
77//===----------------------------------------------------------------------===//
88//
99// FIXME: Use std::string_view instead when we support C++17.
10// There are two copies of this file in the source tree. The one under
11// libcxxabi is the original and the one under llvm is the copy. Use
12// cp-to-llvm.sh to update the copy. See README.txt for more details.
1013//
1114//===----------------------------------------------------------------------===//
1215
......@@ -14,7 +17,6 @@
1417#define DEMANGLE_STRINGVIEW_H
1518
1619#include "DemangleConfig.h"
17#include <algorithm>
1820#include <cassert>
1921#include <cstring>
2022
......@@ -38,15 +40,16 @@ public:
3840
3941 StringView substr(size_t Pos, size_t Len = npos) const {
4042 assert(Pos <= size());
41 return StringView(begin() + Pos, std::min(Len, size() - Pos));
43 if (Len > size() - Pos)
44 Len = size() - Pos;
45 return StringView(begin() + Pos, Len);
4246 }
4347
4448 size_t find(char C, size_t From = 0) const {
45 size_t FindBegin = std::min(From, size());
4649 // Avoid calling memchr with nullptr.
47 if (FindBegin < size()) {
50 if (From < size()) {
4851 // Just forward to memchr, which is faster than a hand-rolled loop.
49 if (const void *P = ::memchr(First + FindBegin, C, size() - FindBegin))
52 if (const void *P = ::memchr(First + From, C, size() - From))
5053 return size_t(static_cast<const char *>(P) - First);
5154 }
5255 return npos;
......@@ -98,7 +101,7 @@ public:
98101 bool startsWith(StringView Str) const {
99102 if (Str.size() > size())
100103 return false;
101 return std::equal(Str.begin(), Str.end(), begin());
104 return std::strncmp(Str.begin(), begin(), Str.size()) == 0;
102105 }
103106
104107 const char &operator[](size_t Idx) const { return *(begin() + Idx); }
......@@ -111,7 +114,7 @@ public:
111114
112115inline bool operator==(const StringView &LHS, const StringView &RHS) {
113116 return LHS.size() == RHS.size() &&
114 std::equal(LHS.begin(), LHS.end(), RHS.begin());
117 std::strncmp(LHS.begin(), RHS.begin(), LHS.size()) == 0;
115118}
116119
117120DEMANGLE_NAMESPACE_END
lib/libcxxabi/src/demangle/Utility.h+45-20
......@@ -6,7 +6,10 @@
66//
77//===----------------------------------------------------------------------===//
88//
9// Provide some utility classes for use in the demangler(s).
9// Provide some utility classes for use in the demangler.
10// There are two copies of this file in the source tree. The one in libcxxabi
11// is the original and the one in llvm is the copy. Use cp-to-llvm.sh to update
12// the copy. See README.txt for more details.
1013//
1114//===----------------------------------------------------------------------===//
1215
......@@ -14,17 +17,18 @@
1417#define DEMANGLE_UTILITY_H
1518
1619#include "StringView.h"
20#include <array>
1721#include <cstdint>
1822#include <cstdlib>
1923#include <cstring>
20#include <iterator>
24#include <exception>
2125#include <limits>
2226
2327DEMANGLE_NAMESPACE_BEGIN
2428
2529// Stream that AST nodes write their string representation into after the AST
2630// has been parsed.
27class OutputStream {
31class OutputBuffer {
2832 char *Buffer = nullptr;
2933 size_t CurrentPosition = 0;
3034 size_t BufferCapacity = 0;
......@@ -48,8 +52,8 @@ class OutputStream {
4852 return;
4953 }
5054
51 char Temp[21];
52 char *TempPtr = std::end(Temp);
55 std::array<char, 21> Temp;
56 char *TempPtr = Temp.data() + Temp.size();
5357
5458 while (N) {
5559 *--TempPtr = char('0' + N % 10);
......@@ -59,13 +63,13 @@ class OutputStream {
5963 // Add negative sign...
6064 if (isNeg)
6165 *--TempPtr = '-';
62 this->operator<<(StringView(TempPtr, std::end(Temp)));
66 this->operator<<(StringView(TempPtr, Temp.data() + Temp.size()));
6367 }
6468
6569public:
66 OutputStream(char *StartBuf, size_t Size)
70 OutputBuffer(char *StartBuf, size_t Size)
6771 : Buffer(StartBuf), CurrentPosition(0), BufferCapacity(Size) {}
68 OutputStream() = default;
72 OutputBuffer() = default;
6973 void reset(char *Buffer_, size_t BufferCapacity_) {
7074 CurrentPosition = 0;
7175 Buffer = Buffer_;
......@@ -77,7 +81,7 @@ public:
7781 unsigned CurrentPackIndex = std::numeric_limits<unsigned>::max();
7882 unsigned CurrentPackMax = std::numeric_limits<unsigned>::max();
7983
80 OutputStream &operator+=(StringView R) {
84 OutputBuffer &operator+=(StringView R) {
8185 size_t Size = R.size();
8286 if (Size == 0)
8387 return *this;
......@@ -87,17 +91,28 @@ public:
8791 return *this;
8892 }
8993
90 OutputStream &operator+=(char C) {
94 OutputBuffer &operator+=(char C) {
9195 grow(1);
9296 Buffer[CurrentPosition++] = C;
9397 return *this;
9498 }
9599
96 OutputStream &operator<<(StringView R) { return (*this += R); }
100 OutputBuffer &operator<<(StringView R) { return (*this += R); }
97101
98 OutputStream &operator<<(char C) { return (*this += C); }
102 OutputBuffer prepend(StringView R) {
103 size_t Size = R.size();
104
105 grow(Size);
106 std::memmove(Buffer + Size, Buffer, CurrentPosition);
107 std::memcpy(Buffer, R.begin(), Size);
108 CurrentPosition += Size;
99109
100 OutputStream &operator<<(long long N) {
110 return *this;
111 }
112
113 OutputBuffer &operator<<(char C) { return (*this += C); }
114
115 OutputBuffer &operator<<(long long N) {
101116 if (N < 0)
102117 writeUnsigned(static_cast<unsigned long long>(-N), true);
103118 else
......@@ -105,27 +120,37 @@ public:
105120 return *this;
106121 }
107122
108 OutputStream &operator<<(unsigned long long N) {
123 OutputBuffer &operator<<(unsigned long long N) {
109124 writeUnsigned(N, false);
110125 return *this;
111126 }
112127
113 OutputStream &operator<<(long N) {
128 OutputBuffer &operator<<(long N) {
114129 return this->operator<<(static_cast<long long>(N));
115130 }
116131
117 OutputStream &operator<<(unsigned long N) {
132 OutputBuffer &operator<<(unsigned long N) {
118133 return this->operator<<(static_cast<unsigned long long>(N));
119134 }
120135
121 OutputStream &operator<<(int N) {
136 OutputBuffer &operator<<(int N) {
122137 return this->operator<<(static_cast<long long>(N));
123138 }
124139
125 OutputStream &operator<<(unsigned int N) {
140 OutputBuffer &operator<<(unsigned int N) {
126141 return this->operator<<(static_cast<unsigned long long>(N));
127142 }
128143
144 void insert(size_t Pos, const char *S, size_t N) {
145 assert(Pos <= CurrentPosition);
146 if (N == 0)
147 return;
148 grow(N);
149 std::memmove(Buffer + Pos + N, Buffer + Pos, CurrentPosition - Pos);
150 std::memcpy(Buffer + Pos, S, N);
151 CurrentPosition += N;
152 }
153
129154 size_t getCurrentPosition() const { return CurrentPosition; }
130155 void setCurrentPosition(size_t NewPos) { CurrentPosition = NewPos; }
131156
......@@ -171,7 +196,7 @@ public:
171196 SwapAndRestore &operator=(const SwapAndRestore &) = delete;
172197};
173198
174inline bool initializeOutputStream(char *Buf, size_t *N, OutputStream &S,
199inline bool initializeOutputBuffer(char *Buf, size_t *N, OutputBuffer &OB,
175200 size_t InitSize) {
176201 size_t BufferSize;
177202 if (Buf == nullptr) {
......@@ -182,7 +207,7 @@ inline bool initializeOutputStream(char *Buf, size_t *N, OutputStream &S,
182207 } else
183208 BufferSize = *N;
184209
185 S.reset(Buf, BufferSize);
210 OB.reset(Buf, BufferSize);
186211 return true;
187212}
188213
lib/libcxxabi/src/fallback_malloc.cpp+1-1
......@@ -1,4 +1,4 @@
1//===------------------------ fallback_malloc.cpp -------------------------===//
1//===----------------------------------------------------------------------===//
22//
33// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
44// See https://llvm.org/LICENSE.txt for license information.
lib/libcxxabi/src/fallback_malloc.h+1-1
......@@ -1,4 +1,4 @@
1//===------------------------- fallback_malloc.h --------------------------===//
1//===----------------------------------------------------------------------===//
22//
33// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
44// See https://llvm.org/LICENSE.txt for license information.
lib/libcxxabi/src/include/atomic_support.h deleted-180
......@@ -1,180 +0,0 @@
1//===----------------------------------------------------------------------===////
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===////
8
9// FIXME: This file is copied from libcxx/src/include/atomic_support.h. Instead
10// of duplicating the file in libc++abi we should require that the libc++
11// sources are available when building libc++abi.
12
13#ifndef ATOMIC_SUPPORT_H
14#define ATOMIC_SUPPORT_H
15
16#include "__config"
17#include "memory" // for __libcpp_relaxed_load
18
19#if defined(__clang__) && __has_builtin(__atomic_load_n) \
20 && __has_builtin(__atomic_store_n) \
21 && __has_builtin(__atomic_add_fetch) \
22 && __has_builtin(__atomic_exchange_n) \
23 && __has_builtin(__atomic_compare_exchange_n) \
24 && defined(__ATOMIC_RELAXED) \
25 && defined(__ATOMIC_CONSUME) \
26 && defined(__ATOMIC_ACQUIRE) \
27 && defined(__ATOMIC_RELEASE) \
28 && defined(__ATOMIC_ACQ_REL) \
29 && defined(__ATOMIC_SEQ_CST)
30# define _LIBCXXABI_HAS_ATOMIC_BUILTINS
31#elif !defined(__clang__) && defined(_GNUC_VER) && _GNUC_VER >= 407
32# define _LIBCXXABI_HAS_ATOMIC_BUILTINS
33#endif
34
35#if !defined(_LIBCXXABI_HAS_ATOMIC_BUILTINS) && !defined(_LIBCXXABI_HAS_NO_THREADS)
36# if defined(_LIBCPP_WARNING)
37 _LIBCPP_WARNING("Building libc++ without __atomic builtins is unsupported")
38# else
39# warning Building libc++ without __atomic builtins is unsupported
40# endif
41#endif
42
43_LIBCPP_BEGIN_NAMESPACE_STD
44
45namespace {
46
47#if defined(_LIBCXXABI_HAS_ATOMIC_BUILTINS) && !defined(_LIBCXXABI_HAS_NO_THREADS)
48
49enum __libcpp_atomic_order {
50 _AO_Relaxed = __ATOMIC_RELAXED,
51 _AO_Consume = __ATOMIC_CONSUME,
52 _AO_Acquire = __ATOMIC_ACQUIRE,
53 _AO_Release = __ATOMIC_RELEASE,
54 _AO_Acq_Rel = __ATOMIC_ACQ_REL,
55 _AO_Seq = __ATOMIC_SEQ_CST
56};
57
58template <class _ValueType, class _FromType>
59inline _LIBCPP_INLINE_VISIBILITY
60void __libcpp_atomic_store(_ValueType* __dest, _FromType __val,
61 int __order = _AO_Seq)
62{
63 __atomic_store_n(__dest, __val, __order);
64}
65
66template <class _ValueType, class _FromType>
67inline _LIBCPP_INLINE_VISIBILITY
68void __libcpp_relaxed_store(_ValueType* __dest, _FromType __val)
69{
70 __atomic_store_n(__dest, __val, _AO_Relaxed);
71}
72
73template <class _ValueType>
74inline _LIBCPP_INLINE_VISIBILITY
75_ValueType __libcpp_atomic_load(_ValueType const* __val,
76 int __order = _AO_Seq)
77{
78 return __atomic_load_n(__val, __order);
79}
80
81template <class _ValueType, class _AddType>
82inline _LIBCPP_INLINE_VISIBILITY
83_ValueType __libcpp_atomic_add(_ValueType* __val, _AddType __a,
84 int __order = _AO_Seq)
85{
86 return __atomic_add_fetch(__val, __a, __order);
87}
88
89template <class _ValueType>
90inline _LIBCPP_INLINE_VISIBILITY
91_ValueType __libcpp_atomic_exchange(_ValueType* __target,
92 _ValueType __value, int __order = _AO_Seq)
93{
94 return __atomic_exchange_n(__target, __value, __order);
95}
96
97template <class _ValueType>
98inline _LIBCPP_INLINE_VISIBILITY
99bool __libcpp_atomic_compare_exchange(_ValueType* __val,
100 _ValueType* __expected, _ValueType __after,
101 int __success_order = _AO_Seq,
102 int __fail_order = _AO_Seq)
103{
104 return __atomic_compare_exchange_n(__val, __expected, __after, true,
105 __success_order, __fail_order);
106}
107
108#else // _LIBCPP_HAS_NO_THREADS
109
110enum __libcpp_atomic_order {
111 _AO_Relaxed,
112 _AO_Consume,
113 _AO_Acquire,
114 _AO_Release,
115 _AO_Acq_Rel,
116 _AO_Seq
117};
118
119template <class _ValueType, class _FromType>
120inline _LIBCPP_INLINE_VISIBILITY
121void __libcpp_atomic_store(_ValueType* __dest, _FromType __val,
122 int = 0)
123{
124 *__dest = __val;
125}
126
127template <class _ValueType, class _FromType>
128inline _LIBCPP_INLINE_VISIBILITY
129void __libcpp_relaxed_store(_ValueType* __dest, _FromType __val)
130{
131 *__dest = __val;
132}
133
134template <class _ValueType>
135inline _LIBCPP_INLINE_VISIBILITY
136_ValueType __libcpp_atomic_load(_ValueType const* __val,
137 int = 0)
138{
139 return *__val;
140}
141
142template <class _ValueType, class _AddType>
143inline _LIBCPP_INLINE_VISIBILITY
144_ValueType __libcpp_atomic_add(_ValueType* __val, _AddType __a,
145 int = 0)
146{
147 return *__val += __a;
148}
149
150template <class _ValueType>
151inline _LIBCPP_INLINE_VISIBILITY
152_ValueType __libcpp_atomic_exchange(_ValueType* __target,
153 _ValueType __value, int = _AO_Seq)
154{
155 _ValueType old = *__target;
156 *__target = __value;
157 return old;
158}
159
160template <class _ValueType>
161inline _LIBCPP_INLINE_VISIBILITY
162bool __libcpp_atomic_compare_exchange(_ValueType* __val,
163 _ValueType* __expected, _ValueType __after,
164 int = 0, int = 0)
165{
166 if (*__val == *__expected) {
167 *__val = __after;
168 return true;
169 }
170 *__expected = *__val;
171 return false;
172}
173
174#endif // _LIBCPP_HAS_NO_THREADS
175
176} // end namespace
177
178_LIBCPP_END_NAMESPACE_STD
179
180#endif // ATOMIC_SUPPORT_H
lib/libcxxabi/src/private_typeinfo.cpp+1-1
......@@ -1,4 +1,4 @@
1//===----------------------- private_typeinfo.cpp -------------------------===//
1//===----------------------------------------------------------------------===//
22//
33// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
44// See https://llvm.org/LICENSE.txt for license information.
lib/libcxxabi/src/private_typeinfo.h+1-1
......@@ -1,4 +1,4 @@
1//===------------------------ private_typeinfo.h --------------------------===//
1//===----------------------------------------------------------------------===//
22//
33// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
44// See https://llvm.org/LICENSE.txt for license information.
lib/libcxxabi/src/stdlib_exception.cpp+1-1
......@@ -1,4 +1,4 @@
1//===---------------------------- exception.cpp ---------------------------===//
1//===----------------------------------------------------------------------===//
22//
33// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
44// See https://llvm.org/LICENSE.txt for license information.
lib/libcxxabi/src/stdlib_new_delete.cpp+1-1
......@@ -1,4 +1,4 @@
1//===--------------------- stdlib_new_delete.cpp --------------------------===//
1//===----------------------------------------------------------------------===//
22//
33// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
44// See https://llvm.org/LICENSE.txt for license information.
lib/libcxxabi/src/stdlib_stdexcept.cpp+2-4
......@@ -1,4 +1,4 @@
1//===------------------------ stdexcept.cpp -------------------------------===//
1//===----------------------------------------------------------------------===//
22//
33// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
44// See https://llvm.org/LICENSE.txt for license information.
......@@ -12,9 +12,7 @@
1212#include <cstring>
1313#include <cstdint>
1414#include <cstddef>
15
16// This includes an implementation file from libc++.
17#include "../../libcxx/src/include/refstring.h"
15#include "include/refstring.h" // from libc++
1816
1917static_assert(sizeof(std::__libcpp_refstring) == sizeof(const char *), "");
2018
lib/libcxxabi/src/stdlib_typeinfo.cpp+1-1
......@@ -1,4 +1,4 @@
1//===----------------------------- typeinfo.cpp ---------------------------===//
1//===----------------------------------------------------------------------===//
22//
33// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
44// See https://llvm.org/LICENSE.txt for license information.