authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-08-04 18:02:01-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-08-04 18:02:01-07:00
logc0d9578a84c95f66f34729f6c8842a98a995f223
tree64a5d94da2124b2e2e34a9f48028f3321e125efe
parent8278eb88376341420817f15791fe7c1715e04a4f

update libcxxabi to LLVM 15

release/15.x commit 134fd359a5d884f16662a9edd22ab24feeb1498c

14 files changed, 2006 insertions(+), 1422 deletions(-)

lib/libcxxabi/include/__cxxabi_config.h+7-1
...@@ -10,7 +10,7 @@...@@ -10,7 +10,7 @@
10#define ____CXXABI_CONFIG_H10#define ____CXXABI_CONFIG_H
1111
12#if defined(__arm__) && !defined(__USING_SJLJ_EXCEPTIONS__) && \12#if defined(__arm__) && !defined(__USING_SJLJ_EXCEPTIONS__) && \
13 !defined(__ARM_DWARF_EH__)13 !defined(__ARM_DWARF_EH__) && !defined(__SEH__)
14#define _LIBCXXABI_ARM_EHABI14#define _LIBCXXABI_ARM_EHABI
15#endif15#endif
1616
...@@ -97,4 +97,10 @@...@@ -97,4 +97,10 @@
97# define _LIBCXXABI_NO_EXCEPTIONS97# define _LIBCXXABI_NO_EXCEPTIONS
98#endif98#endif
9999
100#if defined(_WIN32)
101#define _LIBCXXABI_DTOR_FUNC __thiscall
102#else
103#define _LIBCXXABI_DTOR_FUNC
104#endif
105
100#endif // ____CXXABI_CONFIG_H106#endif // ____CXXABI_CONFIG_H
lib/libcxxabi/include/cxxabi.h+2-2
...@@ -19,7 +19,7 @@...@@ -19,7 +19,7 @@
1919
20#include <__cxxabi_config.h>20#include <__cxxabi_config.h>
2121
22#define _LIBCPPABI_VERSION 100222#define _LIBCPPABI_VERSION 15000
23#define _LIBCXXABI_NORETURN __attribute__((noreturn))23#define _LIBCXXABI_NORETURN __attribute__((noreturn))
24#define _LIBCXXABI_ALWAYS_COLD __attribute__((cold))24#define _LIBCXXABI_ALWAYS_COLD __attribute__((cold))
2525
...@@ -47,7 +47,7 @@ __cxa_free_exception(void *thrown_exception) throw();...@@ -47,7 +47,7 @@ __cxa_free_exception(void *thrown_exception) throw();
47// 2.4.3 Throwing the Exception Object47// 2.4.3 Throwing the Exception Object
48extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_NORETURN void48extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_NORETURN void
49__cxa_throw(void *thrown_exception, std::type_info *tinfo,49__cxa_throw(void *thrown_exception, std::type_info *tinfo,
50 void (*dest)(void *));50 void (_LIBCXXABI_DTOR_FUNC *dest)(void *));
5151
52// 2.5.3 Exception Handlers52// 2.5.3 Exception Handlers
53extern _LIBCXXABI_FUNC_VIS void *53extern _LIBCXXABI_FUNC_VIS void *
lib/libcxxabi/src/aix_state_tab_eh.inc created+684
...@@ -0,0 +1,684 @@
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// This file implements the personality and helper functions for the state
9// table based EH used by IBM legacy compilers xlC and xlclang++ on AIX.
10//
11//===----------------------------------------------------------------------===//
12
13#include <new>
14#include <stdio.h>
15#include <sys/debug.h>
16
17/*
18 The legacy IBM xlC and xlclang++ compilers use the state table for EH
19 instead of the range table. Destructors, or addresses of the possible catch
20 sites or cleanup code are specified in the state table which is a finite
21 state machine (FSM). Each function that has a state table also has an
22 autolocal state variable. The state variable represents the current state
23 of the function for EH and is found through the traceback table of the
24 function during unwinding, which is located at the end of each function.
25 The FSM is an array of state entries. Each state entry has the following
26 fields:
27
28 * offset/address/pointer - the offset used to locate the object, or the
29 address of a global object, or the address of the next state if it is an
30 old conditional state change entry;
31 * dtor/landing pad - address of the destructor function to invoke,
32 or address of the catch block or cleanup code in the user code to branch to;
33 * element count/action flag - the number of elements or the flag for actions;
34 * element size - if the object is an array this is the size of one element
35 of the array;
36 * flags - flags used to control how fields in the entry are interpreted;
37 * next state - the state to execute next after the action for this state is
38 performed. The value of zero indicates the end of the state for this
39 function.
40
41 The following is the description of 'element count/action flag' field.
42+-----------------------------------------------------------------------------+
43| value | description | action |
44+-------+------------------------+--------------------------------------------+
45| > 1 | object is an array | calls __cxa_vec_cleanup to run dtor for |
46| | | each member of the array |
47+-------+------------------------+--------------------------------------------+
48| 1, 0 | object is a scalar | calls dtor for the object |
49+-------+------------------------+--------------------------------------------+
50| -1 | begin catch | branches to the handler which performes |
51| | | catch-match. If there is no catch that |
52| | | matches the exception it will be rethrown |
53+-------+------------------------+--------------------------------------------+
54| -2 | end catch | ends current catch block and continues |
55| | | attempting to catch the exception |
56+-------+------------------------+--------------------------------------------+
57| -3 | delete the object | calls the delete function of the object |
58+-------+------------------------+--------------------------------------------+
59| -4 | cleanup label | branches to the user code for cleaning up |
60+-------+------------------------+--------------------------------------------+
61*/
62
63namespace __cxxabiv1 {
64
65extern "C" {
66
67// Macros for debugging the state table parsing.
68#ifdef NDEBUG
69# define _LIBCXXABI_TRACE_STATETAB(msg, ...)
70# define _LIBCXXABI_TRACE_STATETAB0(msg)
71# define _LIBCXXABI_TRACE_STATETAB1(msg)
72# define _LIBCXXABI_TRACING_STATETAB 0
73#else
74static bool state_tab_dbg() {
75 static bool checked = false;
76 static bool log = false;
77 if (!checked) {
78 log = (getenv("LIBCXXABI_PRINT_STATTAB") != NULL);
79 checked = true;
80 }
81 return log;
82}
83
84# define _LIBCXXABI_TRACE_STATETAB(msg, ...) \
85 do { \
86 if (state_tab_dbg()) \
87 fprintf(stderr, "libcxxabi: " msg, __VA_ARGS__); \
88 } while (0)
89# define _LIBCXXABI_TRACE_STATETAB0(msg) \
90 do { \
91 if (state_tab_dbg()) \
92 fprintf(stderr, "libcxxabi: " msg); \
93 } while (0)
94# define _LIBCXXABI_TRACE_STATETAB1(msg) \
95 do { \
96 if (state_tab_dbg()) \
97 fprintf(stderr, msg); \
98 } while (0)
99
100# define _LIBCXXABI_TRACING_STATETAB state_tab_dbg()
101#endif // NDEBUG
102
103namespace __state_table_eh {
104
105using destruct_f = void (*)(void*);
106
107// Definition of flags for the state table entry field 'action flag'.
108enum FSMEntryCount : intptr_t { beginCatch = -1, endCatch = -2, deleteObject = -3, cleanupLabel = -4, terminate = -5 };
109
110// Definition of flags for the state table entry field 'flags'.
111enum FSMEntryFlag : int16_t {
112 indirect = 0x100, // Object was thrown from a function where
113 // the return value optimization was used.
114 oldConditionalStateChange = 0x400, // State table entry is an indirect state
115 // change, dereference the address in
116 // offset as int for the target state.
117 // This is deprecated. This indicates
118 // the address is direct. (static local).
119 conditionalStateChange = 0x800, // State table entry is an indirect state
120 // change, dereference the address in
121 // offset as int for the target state.
122 // The temporary is an automatic. State
123 // change is used in cases such as
124 // (b?(T1(),foo()):(T2(),foo())),throw 42;
125 // which causes a conditional state change
126 // so that we know if T1 or T2 need to be
127 // destroyed.
128 thisFlag = 0x01, // The address of the object for the
129 // cleanup action is based on the
130 // StateVariable::thisValue.
131 vBaseFlag = 0x02, // The object is of a virtual base class.
132 globalObj = 0x04 // FSMEntry::address is the address of
133 // a global object.
134};
135
136namespace {
137// The finite state machine to be walked.
138struct FSMEntry {
139 union {
140 // Offset of the object within its stack frame or containing object.
141 intptr_t offset;
142 // Address of a global object.
143 intptr_t address;
144 // Address of the next state if it is an old conditional state change entry.
145 intptr_t nextStatePtr;
146 };
147 union {
148 // Address of the destructor function.
149 void (*destructor)(void*, size_t);
150 // The address of the catch block or cleanup code.
151 void* landingPad;
152 };
153 union {
154 // The flag for actions (when the value is negative).
155 FSMEntryCount actionFlag;
156 // The element count (when the value is positive or zero).
157 size_t elementCount;
158 };
159 size_t elemSize;
160 FSMEntryFlag flags;
161 uint16_t nextState;
162};
163
164struct FSM {
165 uint32_t magic; // Magic number of the state table.
166 int32_t numberOfStates;
167 FSMEntry table[1]; // Actually table[numberOfStates].
168};
169
170// The state variable on the stack.
171struct StateVariable {
172 int32_t state;
173 struct FSM* table;
174 intptr_t thisValue;
175 int32_t ignoreVBasePtrs;
176};
177} // namespace
178
179// State table magic number
180enum FSMMagic : uint32_t {
181 number = 0xbeefdead, // State table generated by xlC compiler.
182 number2 = 0xbeeedead, // State table generated by early version xlC compiler.
183 number3 = 0x1cedbeef // State table generated by xlclang++ compiler.
184};
185
186constexpr uint32_t REG_EXCP_OBJ = 14; // Register to pass the address of the exception
187 // object from the personality to xlclang++
188 // compiled code.
189
190constexpr size_t dtorArgument = 0x02; // Flag to destructor indicating to free
191 // virtual bases, don't delete object.
192
193static void invoke_destructor(FSMEntry* fsmEntry, void* addr) {
194 _LIBCXXABI_TRACE_STATETAB("Destruct object=%p, fsmEntry=%p\n", addr, reinterpret_cast<void*>(fsmEntry));
195 try {
196 if (fsmEntry->elementCount == 1) {
197 _LIBCXXABI_TRACE_STATETAB0("calling scalar destructor\n");
198 (*fsmEntry->destructor)(addr, dtorArgument);
199 _LIBCXXABI_TRACE_STATETAB0("returned from scalar destructor\n");
200 } else {
201 _LIBCXXABI_TRACE_STATETAB0("calling vector destructor\n");
202 __cxa_vec_cleanup(addr, reinterpret_cast<size_t>(fsmEntry->elementCount), fsmEntry->elemSize,
203 reinterpret_cast<destruct_f>(fsmEntry->destructor));
204 _LIBCXXABI_TRACE_STATETAB0("returned from vector destructor\n");
205 }
206 } catch (...) {
207 _LIBCXXABI_TRACE_STATETAB0("Uncaught exception in destructor, terminating\n");
208 std::terminate();
209 }
210}
211
212static void invoke_delete(FSMEntry* fsmEntry, void* addr) {
213 char* objectAddress = *reinterpret_cast<char**>(addr);
214
215 _LIBCXXABI_TRACE_STATETAB("Delete object=%p, fsmEntry=%p\n", reinterpret_cast<void*>(objectAddress),
216 reinterpret_cast<void*>(fsmEntry));
217 try {
218 _LIBCXXABI_TRACE_STATETAB0("..calling delete()\n");
219 // 'destructor' holds a function pointer to delete().
220 (*fsmEntry->destructor)(objectAddress, fsmEntry->elemSize);
221 _LIBCXXABI_TRACE_STATETAB0("..returned from delete()\n");
222 } catch (...) {
223 _LIBCXXABI_TRACE_STATETAB0("Uncaught exception in delete(), terminating\n");
224 std::terminate();
225 }
226}
227
228// Get the frame address of the current function from its traceback table
229// which is at the end of each function.
230static uintptr_t get_frame_addr(_Unwind_Context* context) {
231 int framePointerReg = 1; // default frame pointer == SP.
232 uint32_t* p = reinterpret_cast<uint32_t*>(_Unwind_GetIP(context));
233
234 // Keep looking forward until a word of 0 is found. The traceback
235 // table starts at the following word.
236 while (*p)
237 ++p;
238 tbtable* TBTable = reinterpret_cast<tbtable*>(p + 1);
239
240 p = reinterpret_cast<uint32_t*>(&TBTable->tb_ext);
241
242 // Skip field parminfo if it exists.
243 if (TBTable->tb.fixedparms || TBTable->tb.floatparms)
244 ++p;
245
246 // Skip field tb_offset if it exists.
247 if (TBTable->tb.has_tboff)
248 ++p;
249
250 // Skip field hand_mask if it exists.
251 if (TBTable->tb.int_hndl)
252 ++p;
253
254 // Skip fields ctl_info and ctl_info_disp if they exist.
255 if (TBTable->tb.has_ctl)
256 p += 1 + *p;
257
258 // Skip fields name_len and name if exist.
259 if (TBTable->tb.name_present) {
260 const uint16_t name_len = *reinterpret_cast<uint16_t*>(p);
261 p = reinterpret_cast<uint32_t*>(reinterpret_cast<char*>(p) + name_len + sizeof(uint16_t));
262 }
263
264 if (TBTable->tb.uses_alloca)
265 framePointerReg = *reinterpret_cast<char*>(p);
266
267 return _Unwind_GetGR(context, framePointerReg);
268}
269
270// Calculate the object address from the FSM entry.
271static void* compute_addr_from_table(FSMEntry* fsmEntry, StateVariable* const state, _Unwind_Context* context) {
272 void* addr;
273 if (fsmEntry->flags & FSMEntryFlag::globalObj) {
274 addr = reinterpret_cast<void*>(fsmEntry->address);
275 _LIBCXXABI_TRACE_STATETAB("Address calculation (global obj) addr=fsmEntry->address=%p\n", addr);
276 } else if (fsmEntry->flags & FSMEntryFlag::thisFlag) {
277 addr = reinterpret_cast<void*>(state->thisValue + fsmEntry->offset);
278 _LIBCXXABI_TRACE_STATETAB("Address calculation (this obj) fsmEntry->offset=%ld : "
279 "state->thisValue=%ld addr=(fsmEntry->offset+state->thisValue)=%p\n",
280 fsmEntry->offset, state->thisValue, addr);
281 } else if (fsmEntry->flags & FSMEntryFlag::indirect) {
282 addr = reinterpret_cast<void*>(
283 *reinterpret_cast<char**>(get_frame_addr(context) + static_cast<uintptr_t>(fsmEntry->offset)));
284 _LIBCXXABI_TRACE_STATETAB("Address calculation (indirect obj) addr=%p, fsmEntry->offset=%ld \n",
285 addr, fsmEntry->offset);
286 } else {
287 addr = reinterpret_cast<void*>(get_frame_addr(context) + static_cast<uintptr_t>(fsmEntry->offset));
288 _LIBCXXABI_TRACE_STATETAB("Address calculation. (local obj) addr=fsmEntry->offset=%p\n",
289 addr);
290 }
291 return addr;
292}
293
294static void scan_state_tab(scan_results& results, _Unwind_Action actions, bool native_exception,
295 _Unwind_Exception* unwind_exception, _Unwind_Context* context) {
296 // Initialize results to found nothing but an error.
297 results.ttypeIndex = 0;
298 results.actionRecord = 0;
299 results.languageSpecificData = 0;
300 results.landingPad = 0;
301 results.adjustedPtr = 0;
302 results.reason = _URC_FATAL_PHASE1_ERROR;
303
304 // Check for consistent actions.
305 if (actions & _UA_SEARCH_PHASE) {
306 // Do Phase 1
307 if (actions & (_UA_CLEANUP_PHASE | _UA_HANDLER_FRAME | _UA_FORCE_UNWIND)) {
308 // None of these flags should be set during Phase 1.
309 // Client error
310 results.reason = _URC_FATAL_PHASE1_ERROR;
311 return;
312 }
313 } else if (actions & _UA_CLEANUP_PHASE) {
314 if ((actions & _UA_HANDLER_FRAME) && (actions & _UA_FORCE_UNWIND)) {
315 // _UA_HANDLER_FRAME should only be set if phase 1 found a handler.
316 // If _UA_FORCE_UNWIND is set, phase 1 shouldn't have happened.
317 // Client error
318 results.reason = _URC_FATAL_PHASE2_ERROR;
319 return;
320 }
321 } else {
322 // Neither _UA_SEARCH_PHASE nor _UA_CLEANUP_PHASE is set.
323 // Client error
324 results.reason = _URC_FATAL_PHASE1_ERROR;
325 return;
326 }
327
328 if (_LIBCXXABI_TRACING_STATETAB) {
329 _LIBCXXABI_TRACE_STATETAB1("\n");
330 _LIBCXXABI_TRACE_STATETAB("%s: actions=%d (", __func__, actions);
331
332 if (_UA_SEARCH_PHASE & actions)
333 _LIBCXXABI_TRACE_STATETAB1("_UA_SEARCH_PHASE ");
334 if (_UA_CLEANUP_PHASE & actions)
335 _LIBCXXABI_TRACE_STATETAB1("_UA_CLEANUP_PHASE ");
336 if (_UA_HANDLER_FRAME & actions)
337 _LIBCXXABI_TRACE_STATETAB1("_UA_HANDLER_FRAME ");
338 if (_UA_FORCE_UNWIND & actions)
339 _LIBCXXABI_TRACE_STATETAB1("_UA_FORCE_UNWIND ");
340 _LIBCXXABI_TRACE_STATETAB1(")\n");
341 _LIBCXXABI_TRACE_STATETAB(" unwind_exception=%p context=%p\n", reinterpret_cast<void*>(unwind_exception),
342 reinterpret_cast<void*>(context));
343 }
344
345 // Start scan by getting state table address.
346 StateVariable* const state = reinterpret_cast<StateVariable* const>(_Unwind_GetLanguageSpecificData(context));
347 if (state->state <= 0) {
348 // The state is not correct - give up on this routine.
349 _LIBCXXABI_TRACE_STATETAB("state=%d and is <= 0), continue unwinding\n", state->state);
350 results.reason = _URC_CONTINUE_UNWIND;
351 return;
352 }
353 // Parse the state table.
354 FSM* const fsm = state->table;
355 FSMEntry* currFSMEntry;
356
357 if (fsm->magic != FSMMagic::number && fsm->magic != FSMMagic::number2 && fsm->magic != FSMMagic::number3) {
358 // Something is wrong with the state table we found.
359 if (_UA_SEARCH_PHASE & actions) {
360 _LIBCXXABI_TRACE_STATETAB0("Invalid FSM table, return _URC_FATAL_PHASE1_ERROR\n");
361 results.reason = _URC_FATAL_PHASE1_ERROR;
362 } else if (_UA_CLEANUP_PHASE & actions) {
363 _LIBCXXABI_TRACE_STATETAB0("Invalid FSM table, return _URC_FATAL_PHASE2_ERROR\n");
364 results.reason = _URC_FATAL_PHASE2_ERROR;
365 } else {
366 // We should never get here.
367 _LIBCXXABI_TRACE_STATETAB0("Invalid FSM table + RT Internal error, return _URC_FATAL_PHASE2_ERROR\n");
368 results.reason = _URC_FATAL_PHASE2_ERROR;
369 }
370 return;
371 }
372
373 if (_LIBCXXABI_TRACING_STATETAB) {
374 // Print the state table for debugging purposes.
375 _LIBCXXABI_TRACE_STATETAB("state->state=%d, state->ignoreVBasePtrs=%d\n", state->state, state->ignoreVBasePtrs);
376 _LIBCXXABI_TRACE_STATETAB("fsm->magic=%#x, fsm->numberOfStates=%d\n", fsm->magic, fsm->numberOfStates);
377 // Print out the FSM table.
378 _LIBCXXABI_TRACE_STATETAB0("FSM table:\n");
379 _LIBCXXABI_TRACE_STATETAB("%12s %10s %8s %10s %7s %7s %7s %7s\n", "Entry Addr", "state", "Offset", "DTR/lpad",
380 "count", "el_size", "flags", "next");
381 for (int i = 0; i < fsm->numberOfStates; i++) {
382 currFSMEntry = &fsm->table[i];
383 _LIBCXXABI_TRACE_STATETAB("%12p (%8d) %8ld %10p %7ld "
384 "%7ld %#7x %7d\n",
385 reinterpret_cast<void*>(&currFSMEntry), i + 1, currFSMEntry->offset,
386 reinterpret_cast<void*>(currFSMEntry->destructor),
387 currFSMEntry->elementCount, currFSMEntry->elemSize, currFSMEntry->flags,
388 currFSMEntry->nextState);
389 }
390 }
391
392 if (_UA_SEARCH_PHASE & actions) {
393 // Start walking the state table. Use a local copy of state->state so when
394 // we return from search phase we don't change the state number.
395 int currState = state->state;
396
397 while (currState > 0) {
398 currFSMEntry = &fsm->table[currState - 1];
399 _LIBCXXABI_TRACE_STATETAB("Processing state=%d, flags=0x%hx\n", currState, currFSMEntry->flags);
400
401 if (currFSMEntry->actionFlag == FSMEntryCount::beginCatch) {
402 // Found a catch handler.
403 if (fsm->magic == FSMMagic::number) {
404 _LIBCXXABI_TRACE_STATETAB0("Found a xlC catch handler, return _URC_FATAL_PHASE1_ERROR\n");
405 // xlC catch handlers cannot be entered because they use a
406 // proprietary EH runtime that is not interoperable.
407 results.reason = _URC_FATAL_PHASE1_ERROR;
408 return;
409 }
410 // xlclang++ compiled frames use CXA-abi EH calls and any catch
411 // block will include a catch(...) block so it is safe to assume that
412 // the handler is found without checking the catch match. The
413 // catch(...) block will rethrow the exception if there isn't a
414 // match.
415 _LIBCXXABI_TRACE_STATETAB0("Found a catch handler, return _URC_HANDLER_FOUND\n");
416 results.reason = _URC_HANDLER_FOUND;
417 return;
418 }
419 if (currFSMEntry->actionFlag == FSMEntryCount::terminate) {
420 _LIBCXXABI_TRACE_STATETAB0("Found the terminate state, return _URC_HANDLER_FOUND\n");
421 results.reason = _URC_HANDLER_FOUND;
422 return;
423 }
424 if (currFSMEntry->flags & FSMEntryFlag::oldConditionalStateChange) {
425 // Deprecated conditional expression.
426 currState = *reinterpret_cast<int*>(currFSMEntry->nextStatePtr);
427 _LIBCXXABI_TRACE_STATETAB("Flag: FSMEntryFlag::oldConditionalStateChange, dereference "
428 "currFSMEntry->nextStatePtr(%ld), set state=%d\n",
429 currFSMEntry->nextStatePtr, currState);
430 continue; // We are done this iteration of the loop, since
431 // we changed a state.
432 }
433 if (currFSMEntry->flags & FSMEntryFlag::conditionalStateChange) {
434 void* addr = compute_addr_from_table(currFSMEntry, state, context);
435 currState = *reinterpret_cast<int*>(addr);
436 _LIBCXXABI_TRACE_STATETAB("Flag: FSMEntryFlag::conditionalStateChange, dereference "
437 "addr(%p), set state=%d\n", addr, currState);
438 continue; // We are done this iteration of the loop, since we
439 // changed the state.
440 }
441 // Go to the next state.
442 currState = currFSMEntry->nextState;
443 }
444 _LIBCXXABI_TRACE_STATETAB0("No catch handler found, return _URC_CONTINUE_UNWIND\n");
445 results.reason = _URC_CONTINUE_UNWIND;
446 return;
447 }
448 if (_UA_CLEANUP_PHASE & actions) {
449 // Start walking the state table.
450 while (state->state > 0) {
451 currFSMEntry = &fsm->table[state->state - 1];
452
453 if (currFSMEntry->actionFlag == FSMEntryCount::terminate) {
454 _LIBCXXABI_TRACE_STATETAB0("Reached terminate state. Call terminate.\n");
455 std::terminate();
456 }
457 // Perform action according to the currFSMEntry->actionFlag,
458 // except when flag is FSMEntryFlag::conditionalStateChange or
459 // FSMEntryFlag::oldConditionalStateChange.
460 _LIBCXXABI_TRACE_STATETAB("Processing state=%d, flags=0x%hx\n", state->state, currFSMEntry->flags);
461 if (currFSMEntry->flags & FSMEntryFlag::oldConditionalStateChange) {
462 state->state = *reinterpret_cast<int*>(currFSMEntry->nextStatePtr);
463 _LIBCXXABI_TRACE_STATETAB("Flag: FSMEntryFlag::oldConditionalStateChange, dereference "
464 "currFSMEntry->nextStatePtr(%ld), set state=%d\n",
465 currFSMEntry->nextStatePtr, state->state);
466 continue; // We are done with this iteration of the loop, since we changed a state.
467 }
468 if (currFSMEntry->flags & FSMEntryFlag::conditionalStateChange) {
469 // A conditional state table entry holds the address of a local
470 // that holds the next state.
471 void* addr = compute_addr_from_table(currFSMEntry, state, context);
472 state->state = *reinterpret_cast<int*>(addr);
473 _LIBCXXABI_TRACE_STATETAB("Flag: FSMEntryFlag::conditionalStateChange, dereference "
474 "addr(%p), set state=%d\n", addr, state->state);
475 continue; // We are done with this iteration of the loop, since we changed a state.
476 }
477 if (currFSMEntry->actionFlag == FSMEntryCount::beginCatch || currFSMEntry->actionFlag == FSMEntryCount::endCatch ||
478 currFSMEntry->actionFlag == FSMEntryCount::cleanupLabel) {
479
480 _LIBCXXABI_TRACE_STATETAB(
481 "FSMEntryCount::%s: handler %p/%p, return _URC_HANDLER_FOUND\n",
482 (currFSMEntry->actionFlag == FSMEntryCount::beginCatch
483 ? "beginCatch"
484 : (currFSMEntry->actionFlag == FSMEntryCount::endCatch ? "endCatch" : "cleanupLabel")),
485 currFSMEntry->landingPad, *reinterpret_cast<void**>(currFSMEntry->landingPad));
486
487 state->state = currFSMEntry->nextState;
488 results.landingPad = reinterpret_cast<uintptr_t>(*reinterpret_cast<void**>(currFSMEntry->landingPad));
489 results.reason = _URC_HANDLER_FOUND;
490 return;
491 }
492 if (currFSMEntry->elementCount > 0) {
493 if (currFSMEntry->flags & FSMEntryFlag::vBaseFlag && state->ignoreVBasePtrs) {
494 _LIBCXXABI_TRACE_STATETAB0("Ignoring virtual base dtor.\n");
495 } else {
496 // We need to invoke the virtual base destructor. This must be
497 // a frame from the legacy xlC compiler as the xlclang++ compiler
498 // generates inline cleanup code rather than specifying
499 // the destructor via the state table.
500 void* addr = compute_addr_from_table(currFSMEntry, state, context);
501
502 // An extra indirect to get to the object according to the object
503 // model used by the xlC compiler.
504 addr = reinterpret_cast<void*>(*reinterpret_cast<char**>(addr));
505 _LIBCXXABI_TRACE_STATETAB("Invoke dtor for object=%p\n", addr);
506 invoke_destructor(currFSMEntry, addr);
507 }
508 } else if (currFSMEntry->actionFlag == FSMEntryCount::deleteObject) {
509 void* addr = compute_addr_from_table(currFSMEntry, state, context);
510 if (currFSMEntry->flags & FSMEntryFlag::vBaseFlag) {
511 // We need to invoke the virtual base delete function. This must be
512 // a frame from the legacy xlC compiler as the xlclang++ compiler
513 // generates inline cleanup code rather than specifying
514 // the delete function via the state table.
515
516 // An extra indirect to get to the object according to the object
517 // model used by the xlC compiler.
518 addr = reinterpret_cast<void*>(*reinterpret_cast<char**>(addr));
519 }
520 _LIBCXXABI_TRACE_STATETAB("Delete object at %p\n", addr);
521 invoke_delete(currFSMEntry, addr);
522 } else {
523 _LIBCXXABI_TRACE_STATETAB("Unknown entry in FSM (count=%ld), ignored\n",
524 currFSMEntry->elementCount);
525 } // End of action switching.
526
527 // Go to next state.
528 state->state = currFSMEntry->nextState;
529 }
530 _LIBCXXABI_TRACE_STATETAB0("No catch handler, return _URC_CONTINUE_UNWIND\n");
531 results.reason = _URC_CONTINUE_UNWIND;
532 return;
533 }
534 _LIBCXXABI_TRACE_STATETAB0("No state table entry for this exception, call_terminate()\n");
535 // It is possible that no state table entry specify how to handle
536 // this exception. By spec, terminate it immediately.
537 call_terminate(native_exception, unwind_exception);
538}
539
540// Personality routine for EH using the state table.
541_LIBCXXABI_FUNC_VIS _Unwind_Reason_Code
542__xlcxx_personality_v0(int version, _Unwind_Action actions, uint64_t exceptionClass,
543 _Unwind_Exception* unwind_exception, _Unwind_Context* context) {
544 if (version != 1 || unwind_exception == 0 || context == 0)
545 return _URC_FATAL_PHASE1_ERROR;
546
547 bool native_exception = (exceptionClass & get_vendor_and_language) == (kOurExceptionClass & get_vendor_and_language);
548 scan_results results;
549 scan_state_tab(results, actions, native_exception, unwind_exception, context);
550 if (actions & _UA_SEARCH_PHASE) {
551 // Phase 1 search: All we're looking for in phase 1 is a handler that
552 // halts unwinding
553 return results.reason;
554 }
555 if (actions & _UA_CLEANUP_PHASE) {
556 // Phase 2 cleanup:
557 if (results.reason == _URC_HANDLER_FOUND) {
558 // Jump to the handler.
559 _Unwind_SetGR(context, REG_EXCP_OBJ, reinterpret_cast<uintptr_t>(unwind_exception));
560 _Unwind_SetIP(context, results.landingPad);
561 return _URC_INSTALL_CONTEXT;
562 }
563 // Did not find a handler. Return the results of the scan. Normally
564 // _URC_CONTINUE_UNWIND, but could have been _URC_FATAL_PHASE2_ERROR.
565 return results.reason;
566 }
567 // We were called improperly: neither a phase 1 or phase 2 search.
568 return _URC_FATAL_PHASE1_ERROR;
569}
570} // namespace __state_table_eh
571
572// The following are EH helper functions for xlclang++ compiled code.
573
574// __xlc_catch_matchv2
575// Check whether the thrown object matches the catch handler's exception
576// declaration. If there is a match, the function returns true with adjusted
577// address of the thrown object. Otherwise, returns false.
578_LIBCXXABI_FUNC_VIS bool
579__xlc_catch_matchv2(_Unwind_Exception* exceptionObject, std::type_info* catchTypeInfo, void*& obj) {
580 _LIBCXXABI_TRACE_STATETAB("Entering %s, exceptionObject=%p\n", __func__, reinterpret_cast<void*>(exceptionObject));
581
582 if (!__isOurExceptionClass(exceptionObject)) {
583 _LIBCXXABI_TRACE_STATETAB0("No match, not a C++ exception\n");
584 return false;
585 }
586
587 __cxa_exception* exceptionHeader = 0;
588
589 if (__getExceptionClass(exceptionObject) == kOurDependentExceptionClass) {
590 // Walk to the __cxa_dependent_exception primary exception for the
591 // exception object and its type_info.
592 __cxa_dependent_exception* dependentExceptionHeader =
593 reinterpret_cast<__cxa_dependent_exception*>(exceptionObject + 1) - 1;
594 exceptionHeader = reinterpret_cast<__cxa_exception*>(dependentExceptionHeader->primaryException) - 1;
595 _LIBCXXABI_TRACE_STATETAB("exceptionObject 0x%p is a dependent, primary 0x%p\n",
596 reinterpret_cast<void*>(exceptionObject),
597 reinterpret_cast<void*>(&exceptionHeader->unwindHeader));
598 exceptionObject = &exceptionHeader->unwindHeader;
599 } else {
600 _LIBCXXABI_TRACE_STATETAB("exceptionObject %p is NOT a dependent\n", reinterpret_cast<void*>(exceptionObject));
601 exceptionHeader = reinterpret_cast<__cxa_exception*>(exceptionObject + 1) - 1;
602 }
603
604 void* thrownObject = reinterpret_cast<void*>(exceptionObject + 1);
605 std::type_info* throwTypeInfo = exceptionHeader->exceptionType;
606
607 // Get the type info for the thrown type and this catch clause and
608 // see if the catch caluse can catch that type.
609
610 __cxxabiv1::__shim_type_info* catchType = reinterpret_cast<__cxxabiv1::__shim_type_info*>(catchTypeInfo);
611 __cxxabiv1::__shim_type_info* throwType = reinterpret_cast<__cxxabiv1::__shim_type_info*>(throwTypeInfo);
612 _LIBCXXABI_TRACE_STATETAB("UnwindException=%p, thrownObject=%p, throwTypeInfo=%p(%s), catchTypeInfo=%p(%s)\n",
613 reinterpret_cast<void*>(exceptionObject), thrownObject, reinterpret_cast<void*>(throwType),
614 throwType->name(), reinterpret_cast<void*>(catchType), catchType->name());
615 if (catchType->can_catch(throwType, thrownObject)) {
616 exceptionHeader->adjustedPtr = thrownObject;
617 obj = thrownObject;
618 _LIBCXXABI_TRACE_STATETAB("Match found for thrownObject=%p\n", thrownObject);
619 return true;
620 }
621 _LIBCXXABI_TRACE_STATETAB0("No match\n");
622 return false;
623}
624
625// __xlc_throw_badexception
626// This function is for xlclang++. It allocates and throws a bad_exception.
627// During unwinding for this bad_exception, the previous exception which is
628// not matching the throw spec will be cleaned up. Thus having the same
629// effect as replace the top most exception (which is bad) with a bad_exception.
630_LIBCXXABI_FUNC_VIS void __xlc_throw_badexception() {
631 _LIBCXXABI_TRACE_STATETAB("Entering function: %s\n\n", __func__);
632 void* newexception = new (__cxa_allocate_exception(sizeof(std::bad_exception))) std::bad_exception;
633 __cxa_throw(newexception, const_cast<std::type_info*>(&typeid(std::bad_exception)), 0);
634}
635
636// __xlc_exception_handle
637// This function is for xlclang++. It returns the address of the exception
638// object set in gpr14 by the personality routine for xlclang++ compiled code.
639_LIBCXXABI_FUNC_VIS uintptr_t __xlc_exception_handle() {
640 uintptr_t exceptionObject;
641 asm("mr %0, 14" : "=r"(exceptionObject));
642 return exceptionObject;
643}
644
645// xlclang++ may generate calls to __Deleted_Virtual.
646_LIBCXXABI_FUNC_VIS void __Deleted_Virtual() { abort(); }
647
648// __catchThrownException is called during AIX library initialization and
649// termination to handle exceptions. An implementation is also provided in
650// libC.a(shrcore.o). This implementation is provided for applications that
651// link with -lc++ (the xlclang++ or ibm-clang++ link default.)
652_LIBCXXABI_FUNC_VIS int
653__catchThrownException(void (*cdfunc)(void), // function which may fail
654 void (*cleanup)(void*), // cleanup function
655 void* cleanuparg, // parameter to cleanup function
656 int action) { // control exception throwing and termination
657 enum Action : int { None = 0, Rethrow = 1, Terminate = 2 };
658 if (!cdfunc)
659 return 0;
660 if (action == Action::Rethrow && !cleanup) {
661 // No cleanup and rethrow is effectively no-op.
662 // Avoid the catch handler when possible to allow exceptions generated
663 // from xlC binaries to flow through.
664 (*cdfunc)();
665 return 0;
666 }
667 try {
668 (*cdfunc)();
669 } catch (...) {
670 if (action == Action::Terminate)
671 std::terminate();
672 if (cleanup)
673 (*cleanup)(cleanuparg);
674 if (action == Action::Rethrow)
675 throw;
676 assert(action == Action::None);
677 return -1; // FAILED
678 }
679 return 0;
680}
681
682} // extern "C"
683
684} // __cxxabiv1
lib/libcxxabi/src/cxa_default_handlers.cpp+59-56
...@@ -10,6 +10,7 @@...@@ -10,6 +10,7 @@
10//===----------------------------------------------------------------------===//10//===----------------------------------------------------------------------===//
1111
12#include <exception>12#include <exception>
13#include <memory>
13#include <stdlib.h>14#include <stdlib.h>
14#include "abort_message.h"15#include "abort_message.h"
15#include "cxxabi.h"16#include "cxxabi.h"
...@@ -20,67 +21,69 @@...@@ -20,67 +21,69 @@
2021
21#if !defined(LIBCXXABI_SILENT_TERMINATE)22#if !defined(LIBCXXABI_SILENT_TERMINATE)
2223
23_LIBCPP_SAFE_STATIC24static constinit const char* cause = "uncaught";
24static const char* cause = "uncaught";25
26#ifndef _LIBCXXABI_NO_EXCEPTIONS
27// Demangle the given string, or return the string as-is in case of an error.
28static std::unique_ptr<char const, void (*)(char const*)> demangle(char const* str)
29{
30#if !defined(LIBCXXABI_NON_DEMANGLING_TERMINATE)
31 if (const char* result = __cxxabiv1::__cxa_demangle(str, nullptr, nullptr, nullptr))
32 return {result, [](char const* p) { std::free(const_cast<char*>(p)); }};
33#endif
34 return {str, [](char const*) { /* nothing to free */ }};
35}
2536
26__attribute__((noreturn))37__attribute__((noreturn))
27static void demangling_terminate_handler()38static void demangling_terminate_handler()
28{39{
29#ifndef _LIBCXXABI_NO_EXCEPTIONS
30 // If there might be an uncaught exception
31 using namespace __cxxabiv1;40 using namespace __cxxabiv1;
32 __cxa_eh_globals* globals = __cxa_get_globals_fast();41 __cxa_eh_globals* globals = __cxa_get_globals_fast();
33 if (globals)42
43 // If there is no uncaught exception, just note that we're terminating
44 if (!globals)
45 abort_message("terminating");
46
47 __cxa_exception* exception_header = globals->caughtExceptions;
48 if (!exception_header)
49 abort_message("terminating");
50
51 _Unwind_Exception* unwind_exception =
52 reinterpret_cast<_Unwind_Exception*>(exception_header + 1) - 1;
53
54 // If we're terminating due to a foreign exception
55 if (!__isOurExceptionClass(unwind_exception))
56 abort_message("terminating due to %s foreign exception", cause);
57
58 void* thrown_object =
59 __getExceptionClass(unwind_exception) == kOurDependentExceptionClass ?
60 ((__cxa_dependent_exception*)exception_header)->primaryException :
61 exception_header + 1;
62 const __shim_type_info* thrown_type =
63 static_cast<const __shim_type_info*>(exception_header->exceptionType);
64 auto name = demangle(thrown_type->name());
65 // If the uncaught exception can be caught with std::exception&
66 const __shim_type_info* catch_type =
67 static_cast<const __shim_type_info*>(&typeid(std::exception));
68 if (catch_type->can_catch(thrown_type, thrown_object))
34 {69 {
35 __cxa_exception* exception_header = globals->caughtExceptions;70 // Include the what() message from the exception
36 // If there is an uncaught exception71 const std::exception* e = static_cast<const std::exception*>(thrown_object);
37 if (exception_header)72 abort_message("terminating due to %s exception of type %s: %s", cause, name.get(), e->what());
38 {
39 _Unwind_Exception* unwind_exception =
40 reinterpret_cast<_Unwind_Exception*>(exception_header + 1) - 1;
41 if (__isOurExceptionClass(unwind_exception))
42 {
43 void* thrown_object =
44 __getExceptionClass(unwind_exception) == kOurDependentExceptionClass ?
45 ((__cxa_dependent_exception*)exception_header)->primaryException :
46 exception_header + 1;
47 const __shim_type_info* thrown_type =
48 static_cast<const __shim_type_info*>(exception_header->exceptionType);
49#if !defined(LIBCXXABI_NON_DEMANGLING_TERMINATE)
50 // Try to get demangled name of thrown_type
51 int status;
52 char buf[1024];
53 size_t len = sizeof(buf);
54 const char* name = __cxa_demangle(thrown_type->name(), buf, &len, &status);
55 if (status != 0)
56 name = thrown_type->name();
57#else
58 const char* name = thrown_type->name();
59#endif
60 // If the uncaught exception can be caught with std::exception&
61 const __shim_type_info* catch_type =
62 static_cast<const __shim_type_info*>(&typeid(std::exception));
63 if (catch_type->can_catch(thrown_type, thrown_object))
64 {
65 // Include the what() message from the exception
66 const std::exception* e = static_cast<const std::exception*>(thrown_object);
67 abort_message("terminating with %s exception of type %s: %s",
68 cause, name, e->what());
69 }
70 else
71 // Else just note that we're terminating with an exception
72 abort_message("terminating with %s exception of type %s",
73 cause, name);
74 }
75 else
76 // Else we're terminating with a foreign exception
77 abort_message("terminating with %s foreign exception", cause);
78 }
79 }73 }
80#endif74 else
81 // Else just note that we're terminating75 {
76 // Else just note that we're terminating due to an exception
77 abort_message("terminating due to %s exception of type %s", cause, name.get());
78 }
79}
80#else // !_LIBCXXABI_NO_EXCEPTIONS
81__attribute__((noreturn))
82static void demangling_terminate_handler()
83{
82 abort_message("terminating");84 abort_message("terminating");
83}85}
86#endif // !_LIBCXXABI_NO_EXCEPTIONS
8487
85__attribute__((noreturn))88__attribute__((noreturn))
86static void demangling_unexpected_handler()89static void demangling_unexpected_handler()
...@@ -91,22 +94,22 @@ static void demangling_unexpected_handler()...@@ -91,22 +94,22 @@ static void demangling_unexpected_handler()
9194
92static constexpr std::terminate_handler default_terminate_handler = demangling_terminate_handler;95static constexpr std::terminate_handler default_terminate_handler = demangling_terminate_handler;
93static constexpr std::terminate_handler default_unexpected_handler = demangling_unexpected_handler;96static constexpr std::terminate_handler default_unexpected_handler = demangling_unexpected_handler;
94#else97#else // !LIBCXXABI_SILENT_TERMINATE
95static constexpr std::terminate_handler default_terminate_handler = ::abort;98static constexpr std::terminate_handler default_terminate_handler = ::abort;
96static constexpr std::terminate_handler default_unexpected_handler = std::terminate;99static constexpr std::terminate_handler default_unexpected_handler = std::terminate;
97#endif100#endif // !LIBCXXABI_SILENT_TERMINATE
98101
99//102//
100// Global variables that hold the pointers to the current handler103// Global variables that hold the pointers to the current handler
101//104//
102_LIBCXXABI_DATA_VIS105_LIBCXXABI_DATA_VIS
103_LIBCPP_SAFE_STATIC std::terminate_handler __cxa_terminate_handler = default_terminate_handler;106constinit std::terminate_handler __cxa_terminate_handler = default_terminate_handler;
104107
105_LIBCXXABI_DATA_VIS108_LIBCXXABI_DATA_VIS
106_LIBCPP_SAFE_STATIC std::unexpected_handler __cxa_unexpected_handler = default_unexpected_handler;109constinit std::unexpected_handler __cxa_unexpected_handler = default_unexpected_handler;
107110
108_LIBCXXABI_DATA_VIS111_LIBCXXABI_DATA_VIS
109_LIBCPP_SAFE_STATIC std::new_handler __cxa_new_handler = 0;112constinit std::new_handler __cxa_new_handler = nullptr;
110113
111namespace std114namespace std
112{115{
lib/libcxxabi/src/cxa_demangle.cpp+44
...@@ -173,6 +173,50 @@ struct DumpVisitor {...@@ -173,6 +173,50 @@ struct DumpVisitor {
173 return printStr("TemplateParamKind::Template");173 return printStr("TemplateParamKind::Template");
174 }174 }
175 }175 }
176 void print(Node::Prec P) {
177 switch (P) {
178 case Node::Prec::Primary:
179 return printStr("Node::Prec::Primary");
180 case Node::Prec::Postfix:
181 return printStr("Node::Prec::Postfix");
182 case Node::Prec::Unary:
183 return printStr("Node::Prec::Unary");
184 case Node::Prec::Cast:
185 return printStr("Node::Prec::Cast");
186 case Node::Prec::PtrMem:
187 return printStr("Node::Prec::PtrMem");
188 case Node::Prec::Multiplicative:
189 return printStr("Node::Prec::Multiplicative");
190 case Node::Prec::Additive:
191 return printStr("Node::Prec::Additive");
192 case Node::Prec::Shift:
193 return printStr("Node::Prec::Shift");
194 case Node::Prec::Spaceship:
195 return printStr("Node::Prec::Spaceship");
196 case Node::Prec::Relational:
197 return printStr("Node::Prec::Relational");
198 case Node::Prec::Equality:
199 return printStr("Node::Prec::Equality");
200 case Node::Prec::And:
201 return printStr("Node::Prec::And");
202 case Node::Prec::Xor:
203 return printStr("Node::Prec::Xor");
204 case Node::Prec::Ior:
205 return printStr("Node::Prec::Ior");
206 case Node::Prec::AndIf:
207 return printStr("Node::Prec::AndIf");
208 case Node::Prec::OrIf:
209 return printStr("Node::Prec::OrIf");
210 case Node::Prec::Conditional:
211 return printStr("Node::Prec::Conditional");
212 case Node::Prec::Assign:
213 return printStr("Node::Prec::Assign");
214 case Node::Prec::Comma:
215 return printStr("Node::Prec::Comma");
216 case Node::Prec::Default:
217 return printStr("Node::Prec::Default");
218 }
219 }
176220
177 void newLine() {221 void newLine() {
178 printStr("\n");222 printStr("\n");
lib/libcxxabi/src/cxa_exception.cpp+22-9
...@@ -254,7 +254,7 @@ will call terminate, assuming that there was no handler for the...@@ -254,7 +254,7 @@ will call terminate, assuming that there was no handler for the
254exception.254exception.
255*/255*/
256void256void
257__cxa_throw(void *thrown_object, std::type_info *tinfo, void (*dest)(void *)) {257__cxa_throw(void *thrown_object, std::type_info *tinfo, void (_LIBCXXABI_DTOR_FUNC *dest)(void *)) {
258 __cxa_eh_globals *globals = __cxa_get_globals();258 __cxa_eh_globals *globals = __cxa_get_globals();
259 __cxa_exception* exception_header = cxa_exception_from_thrown_object(thrown_object);259 __cxa_exception* exception_header = cxa_exception_from_thrown_object(thrown_object);
260260
...@@ -341,10 +341,11 @@ unwinding with _Unwind_Resume....@@ -341,10 +341,11 @@ unwinding with _Unwind_Resume.
341According to ARM EHABI 8.4.1, __cxa_end_cleanup() should not clobber any341According to ARM EHABI 8.4.1, __cxa_end_cleanup() should not clobber any
342register, thus we have to write this function in assembly so that we can save342register, thus we have to write this function in assembly so that we can save
343{r1, r2, r3}. We don't have to save r0 because it is the return value and the343{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 lr in order to344first argument to _Unwind_Resume(). The function also saves/restores r4 to
345align the stack to 16 bytes and lr will be used to identify the caller and its345keep the stack aligned and to provide a temp register. _Unwind_Resume never
346frame information. _Unwind_Resume never return and we need to keep the original346returns and we need to keep the original lr so just branch to it. When
347lr so just branch to it.347targeting bare metal, the function also clobbers ip/r12 to hold the address of
348_Unwind_Resume, which may be too far away for an ordinary branch.
348*/349*/
349__attribute__((used)) static _Unwind_Exception *350__attribute__((used)) static _Unwind_Exception *
350__cxa_end_cleanup_impl()351__cxa_end_cleanup_impl()
...@@ -381,15 +382,19 @@ asm(" .pushsection .text.__cxa_end_cleanup,\"ax\",%progbits\n"...@@ -381,15 +382,19 @@ asm(" .pushsection .text.__cxa_end_cleanup,\"ax\",%progbits\n"
381#if defined(__ARM_FEATURE_BTI_DEFAULT)382#if defined(__ARM_FEATURE_BTI_DEFAULT)
382 " bti\n"383 " bti\n"
383#endif384#endif
384 " push {r1, r2, r3, lr}\n"385 " push {r1, r2, r3, r4}\n"
386 " mov r4, lr\n"
385 " bl __cxa_end_cleanup_impl\n"387 " bl __cxa_end_cleanup_impl\n"
386 " pop {r1, r2, r3, r4}\n"
387 " mov lr, r4\n"388 " mov lr, r4\n"
388#if defined(LIBCXXABI_BAREMETAL)389#if defined(LIBCXXABI_BAREMETAL)
389 " ldr r4, =_Unwind_Resume\n"390 " ldr r4, =_Unwind_Resume\n"
390 " bx r4\n"391 " mov ip, r4\n"
392#endif
393 " pop {r1, r2, r3, r4}\n"
394#if defined(LIBCXXABI_BAREMETAL)
395 " bx ip\n"
391#else396#else
392 " b _Unwind_Resume\n"397 " b _Unwind_Resume\n"
393#endif398#endif
394 " .popsection");399 " .popsection");
395#endif // defined(_LIBCXXABI_ARM_EHABI)400#endif // defined(_LIBCXXABI_ARM_EHABI)
...@@ -439,6 +444,14 @@ __cxa_begin_catch(void* unwind_arg) throw()...@@ -439,6 +444,14 @@ __cxa_begin_catch(void* unwind_arg) throw()
439 (444 (
440 static_cast<_Unwind_Exception*>(unwind_exception)445 static_cast<_Unwind_Exception*>(unwind_exception)
441 );446 );
447
448#if defined(__MVS__)
449 // Remove the exception object from the linked list of exceptions that the z/OS unwinder
450 // maintains before adding it to the libc++abi list of caught exceptions.
451 // The libc++abi will manage the lifetime of the exception from this point forward.
452 _UnwindZOS_PopException();
453#endif
454
442 if (native_exception)455 if (native_exception)
443 {456 {
444 // Increment the handler count, removing the flag about being rethrown457 // Increment the handler count, removing the flag about being rethrown
lib/libcxxabi/src/cxa_exception.h+5-5
...@@ -34,7 +34,7 @@ struct _LIBCXXABI_HIDDEN __cxa_exception {...@@ -34,7 +34,7 @@ struct _LIBCXXABI_HIDDEN __cxa_exception {
34 // in the beginning of the struct, rather than before unwindHeader.34 // in the beginning of the struct, rather than before unwindHeader.
35 void *reserve;35 void *reserve;
3636
37 // This is a new field to support C++ 0x exception_ptr.37 // This is a new field to support C++11 exception_ptr.
38 // For binary compatibility it is at the start of this38 // For binary compatibility it is at the start of this
39 // struct which is prepended to the object thrown in39 // struct which is prepended to the object thrown in
40 // __cxa_allocate_exception.40 // __cxa_allocate_exception.
...@@ -43,7 +43,7 @@ struct _LIBCXXABI_HIDDEN __cxa_exception {...@@ -43,7 +43,7 @@ struct _LIBCXXABI_HIDDEN __cxa_exception {
4343
44 // Manage the exception object itself.44 // Manage the exception object itself.
45 std::type_info *exceptionType;45 std::type_info *exceptionType;
46 void (*exceptionDestructor)(void *);46 void (_LIBCXXABI_DTOR_FUNC *exceptionDestructor)(void *);
47 std::unexpected_handler unexpectedHandler;47 std::unexpected_handler unexpectedHandler;
48 std::terminate_handler terminateHandler;48 std::terminate_handler terminateHandler;
4949
...@@ -63,9 +63,9 @@ struct _LIBCXXABI_HIDDEN __cxa_exception {...@@ -63,9 +63,9 @@ struct _LIBCXXABI_HIDDEN __cxa_exception {
63#endif63#endif
6464
65#if !defined(__LP64__) && !defined(_WIN64) && !defined(_LIBCXXABI_ARM_EHABI)65#if !defined(__LP64__) && !defined(_WIN64) && !defined(_LIBCXXABI_ARM_EHABI)
66 // This is a new field to support C++ 0x exception_ptr.66 // This is a new field to support C++11 exception_ptr.
67 // For binary compatibility it is placed where the compiler67 // For binary compatibility it is placed where the compiler
68 // previously adding padded to 64-bit align unwindHeader.68 // previously added padding to 64-bit align unwindHeader.
69 size_t referenceCount;69 size_t referenceCount;
70#endif70#endif
71 _Unwind_Exception unwindHeader;71 _Unwind_Exception unwindHeader;
...@@ -81,7 +81,7 @@ struct _LIBCXXABI_HIDDEN __cxa_dependent_exception {...@@ -81,7 +81,7 @@ struct _LIBCXXABI_HIDDEN __cxa_dependent_exception {
81#endif81#endif
8282
83 std::type_info *exceptionType;83 std::type_info *exceptionType;
84 void (*exceptionDestructor)(void *);84 void (_LIBCXXABI_DTOR_FUNC *exceptionDestructor)(void *);
85 std::unexpected_handler unexpectedHandler;85 std::unexpected_handler unexpectedHandler;
86 std::terminate_handler terminateHandler;86 std::terminate_handler terminateHandler;
8787
lib/libcxxabi/src/cxa_guard_impl.h+1-1
...@@ -619,7 +619,7 @@ struct GlobalStatic {...@@ -619,7 +619,7 @@ struct GlobalStatic {
619 static T instance;619 static T instance;
620};620};
621template <class T>621template <class T>
622_LIBCPP_SAFE_STATIC T GlobalStatic<T>::instance = {};622_LIBCPP_CONSTINIT T GlobalStatic<T>::instance = {};
623623
624enum class Implementation { NoThreads, GlobalMutex, Futex };624enum class Implementation { NoThreads, GlobalMutex, Futex };
625625
lib/libcxxabi/src/cxa_personality.cpp+21-4
...@@ -22,6 +22,15 @@...@@ -22,6 +22,15 @@
22#include "private_typeinfo.h"22#include "private_typeinfo.h"
23#include "unwind.h"23#include "unwind.h"
2424
25// TODO: This is a temporary workaround for libc++abi to recognize that it's being
26// built against LLVM's libunwind. LLVM's libunwind started reporting _LIBUNWIND_VERSION
27// in LLVM 15 -- we can remove this workaround after shipping LLVM 17. Once we remove
28// this workaround, it won't be possible to build libc++abi against libunwind headers
29// from LLVM 14 and before anymore.
30#if defined(____LIBUNWIND_CONFIG_H__) && !defined(_LIBUNWIND_VERSION)
31# define _LIBUNWIND_VERSION
32#endif
33
25#if defined(__SEH__) && !defined(__USING_SJLJ_EXCEPTIONS__)34#if defined(__SEH__) && !defined(__USING_SJLJ_EXCEPTIONS__)
26#include <windows.h>35#include <windows.h>
27#include <winnt.h>36#include <winnt.h>
...@@ -613,7 +622,7 @@ static void scan_eh_tab(scan_results &results, _Unwind_Action actions,...@@ -613,7 +622,7 @@ static void scan_eh_tab(scan_results &results, _Unwind_Action actions,
613 results.reason = _URC_FATAL_PHASE1_ERROR;622 results.reason = _URC_FATAL_PHASE1_ERROR;
614 return;623 return;
615 }624 }
616 // Start scan by getting exception table address625 // Start scan by getting exception table address.
617 const uint8_t *lsda = (const uint8_t *)_Unwind_GetLanguageSpecificData(context);626 const uint8_t *lsda = (const uint8_t *)_Unwind_GetLanguageSpecificData(context);
618 if (lsda == 0)627 if (lsda == 0)
619 {628 {
...@@ -903,6 +912,8 @@ static _Unwind_Reason_Code __gxx_personality_imp...@@ -903,6 +912,8 @@ static _Unwind_Reason_Code __gxx_personality_imp
903_LIBCXXABI_FUNC_VIS _Unwind_Reason_Code912_LIBCXXABI_FUNC_VIS _Unwind_Reason_Code
904#ifdef __USING_SJLJ_EXCEPTIONS__913#ifdef __USING_SJLJ_EXCEPTIONS__
905__gxx_personality_sj0914__gxx_personality_sj0
915#elif defined(__MVS__)
916__zos_cxx_personality_v2
906#else917#else
907__gxx_personality_v0918__gxx_personality_v0
908#endif919#endif
...@@ -1015,7 +1026,7 @@ static _Unwind_Reason_Code continue_unwind(_Unwind_Exception* unwind_exception,...@@ -1015,7 +1026,7 @@ static _Unwind_Reason_Code continue_unwind(_Unwind_Exception* unwind_exception,
1015}1026}
10161027
1017// ARM register names1028// ARM register names
1018#if !defined(LIBCXXABI_USE_LLVM_UNWINDER)1029#if !defined(_LIBUNWIND_VERSION)
1019static const uint32_t REG_UCB = 12; // Register to save _Unwind_Control_Block1030static const uint32_t REG_UCB = 12; // Register to save _Unwind_Control_Block
1020#endif1031#endif
1021static const uint32_t REG_SP = 13;1032static const uint32_t REG_SP = 13;
...@@ -1050,7 +1061,7 @@ __gxx_personality_v0(_Unwind_State state,...@@ -1050,7 +1061,7 @@ __gxx_personality_v0(_Unwind_State state,
10501061
1051 bool native_exception = __isOurExceptionClass(unwind_exception);1062 bool native_exception = __isOurExceptionClass(unwind_exception);
10521063
1053#if !defined(LIBCXXABI_USE_LLVM_UNWINDER)1064#if !defined(_LIBUNWIND_VERSION)
1054 // Copy the address of _Unwind_Control_Block to r12 so that1065 // Copy the address of _Unwind_Control_Block to r12 so that
1055 // _Unwind_GetLanguageSpecificData() and _Unwind_GetRegionStart() can1066 // _Unwind_GetLanguageSpecificData() and _Unwind_GetRegionStart() can
1056 // return correct address.1067 // return correct address.
...@@ -1112,7 +1123,7 @@ __gxx_personality_v0(_Unwind_State state,...@@ -1112,7 +1123,7 @@ __gxx_personality_v0(_Unwind_State state,
1112 }1123 }
11131124
1114 // Either we didn't do a phase 1 search (due to forced unwinding), or1125 // Either we didn't do a phase 1 search (due to forced unwinding), or
1115 // phase 1 reported no catching-handlers.1126 // phase 1 reported no catching-handlers.
1116 // Search for a (non-catching) cleanup1127 // Search for a (non-catching) cleanup
1117 if (is_force_unwinding)1128 if (is_force_unwinding)
1118 scan_eh_tab(1129 scan_eh_tab(
...@@ -1296,3 +1307,9 @@ _LIBCXXABI_FUNC_VIS _Unwind_Reason_Code __xlcxx_personality_v1(...@@ -1296,3 +1307,9 @@ _LIBCXXABI_FUNC_VIS _Unwind_Reason_Code __xlcxx_personality_v1(
1296} // extern "C"1307} // extern "C"
12971308
1298} // __cxxabiv11309} // __cxxabiv1
1310
1311#if defined(_AIX)
1312// Include implementation of the personality and helper functions for the
1313// state table based EH used by IBM legacy compilers xlC and xlclang++ on AIX.
1314# include "aix_state_tab_eh.inc"
1315#endif
lib/libcxxabi/src/demangle/ItaniumDemangle.h+1005-1284
...@@ -16,10 +16,6 @@...@@ -16,10 +16,6 @@
16#ifndef DEMANGLE_ITANIUMDEMANGLE_H16#ifndef DEMANGLE_ITANIUMDEMANGLE_H
17#define DEMANGLE_ITANIUMDEMANGLE_H17#define DEMANGLE_ITANIUMDEMANGLE_H
1818
19// FIXME: (possibly) incomplete list of features that clang mangles that this
20// file does not yet support:
21// - C++ modules TS
22
23#include "DemangleConfig.h"19#include "DemangleConfig.h"
24#include "StringView.h"20#include "StringView.h"
25#include "Utility.h"21#include "Utility.h"
...@@ -32,85 +28,6 @@...@@ -32,85 +28,6 @@
32#include <limits>28#include <limits>
33#include <utility>29#include <utility>
3430
35#define FOR_EACH_NODE_KIND(X) \
36 X(NodeArrayNode) \
37 X(DotSuffix) \
38 X(VendorExtQualType) \
39 X(QualType) \
40 X(ConversionOperatorType) \
41 X(PostfixQualifiedType) \
42 X(ElaboratedTypeSpefType) \
43 X(NameType) \
44 X(AbiTagAttr) \
45 X(EnableIfAttr) \
46 X(ObjCProtoName) \
47 X(PointerType) \
48 X(ReferenceType) \
49 X(PointerToMemberType) \
50 X(ArrayType) \
51 X(FunctionType) \
52 X(NoexceptSpec) \
53 X(DynamicExceptionSpec) \
54 X(FunctionEncoding) \
55 X(LiteralOperator) \
56 X(SpecialName) \
57 X(CtorVtableSpecialName) \
58 X(QualifiedName) \
59 X(NestedName) \
60 X(LocalName) \
61 X(VectorType) \
62 X(PixelVectorType) \
63 X(BinaryFPType) \
64 X(SyntheticTemplateParamName) \
65 X(TypeTemplateParamDecl) \
66 X(NonTypeTemplateParamDecl) \
67 X(TemplateTemplateParamDecl) \
68 X(TemplateParamPackDecl) \
69 X(ParameterPack) \
70 X(TemplateArgumentPack) \
71 X(ParameterPackExpansion) \
72 X(TemplateArgs) \
73 X(ForwardTemplateReference) \
74 X(NameWithTemplateArgs) \
75 X(GlobalQualifiedName) \
76 X(StdQualifiedName) \
77 X(ExpandedSpecialSubstitution) \
78 X(SpecialSubstitution) \
79 X(CtorDtorName) \
80 X(DtorName) \
81 X(UnnamedTypeName) \
82 X(ClosureTypeName) \
83 X(StructuredBindingName) \
84 X(BinaryExpr) \
85 X(ArraySubscriptExpr) \
86 X(PostfixExpr) \
87 X(ConditionalExpr) \
88 X(MemberExpr) \
89 X(SubobjectExpr) \
90 X(EnclosingExpr) \
91 X(CastExpr) \
92 X(SizeofParamPackExpr) \
93 X(CallExpr) \
94 X(NewExpr) \
95 X(DeleteExpr) \
96 X(PrefixExpr) \
97 X(FunctionParam) \
98 X(ConversionExpr) \
99 X(PointerToMemberConversionExpr) \
100 X(InitListExpr) \
101 X(FoldExpr) \
102 X(ThrowExpr) \
103 X(BoolExpr) \
104 X(StringLiteral) \
105 X(LambdaExpr) \
106 X(EnumLiteral) \
107 X(IntegerLiteral) \
108 X(FloatLiteral) \
109 X(DoubleLiteral) \
110 X(LongDoubleLiteral) \
111 X(BracedExpr) \
112 X(BracedRangeExpr)
113
114DEMANGLE_NAMESPACE_BEGIN31DEMANGLE_NAMESPACE_BEGIN
11532
116template <class T, size_t N> class PODSmallVector {33template <class T, size_t N> class PODSmallVector {
...@@ -238,37 +155,68 @@ public:...@@ -238,37 +155,68 @@ public:
238class Node {155class Node {
239public:156public:
240 enum Kind : unsigned char {157 enum Kind : unsigned char {
241#define ENUMERATOR(NodeKind) K ## NodeKind,158#define NODE(NodeKind) K##NodeKind,
242 FOR_EACH_NODE_KIND(ENUMERATOR)159#include "ItaniumNodes.def"
243#undef ENUMERATOR
244 };160 };
245161
246 /// Three-way bool to track a cached value. Unknown is possible if this node162 /// Three-way bool to track a cached value. Unknown is possible if this node
247 /// has an unexpanded parameter pack below it that may affect this cache.163 /// has an unexpanded parameter pack below it that may affect this cache.
248 enum class Cache : unsigned char { Yes, No, Unknown, };164 enum class Cache : unsigned char { Yes, No, Unknown, };
249165
166 /// Operator precedence for expression nodes. Used to determine required
167 /// parens in expression emission.
168 enum class Prec {
169 Primary,
170 Postfix,
171 Unary,
172 Cast,
173 PtrMem,
174 Multiplicative,
175 Additive,
176 Shift,
177 Spaceship,
178 Relational,
179 Equality,
180 And,
181 Xor,
182 Ior,
183 AndIf,
184 OrIf,
185 Conditional,
186 Assign,
187 Comma,
188 Default,
189 };
190
250private:191private:
251 Kind K;192 Kind K;
252193
194 Prec Precedence : 6;
195
253 // FIXME: Make these protected.196 // FIXME: Make these protected.
254public:197public:
255 /// Tracks if this node has a component on its right side, in which case we198 /// Tracks if this node has a component on its right side, in which case we
256 /// need to call printRight.199 /// need to call printRight.
257 Cache RHSComponentCache;200 Cache RHSComponentCache : 2;
258201
259 /// Track if this node is a (possibly qualified) array type. This can affect202 /// Track if this node is a (possibly qualified) array type. This can affect
260 /// how we format the output string.203 /// how we format the output string.
261 Cache ArrayCache;204 Cache ArrayCache : 2;
262205
263 /// Track if this node is a (possibly qualified) function type. This can206 /// Track if this node is a (possibly qualified) function type. This can
264 /// affect how we format the output string.207 /// affect how we format the output string.
265 Cache FunctionCache;208 Cache FunctionCache : 2;
266209
267public:210public:
268 Node(Kind K_, Cache RHSComponentCache_ = Cache::No,211 Node(Kind K_, Prec Precedence_ = Prec::Primary,
269 Cache ArrayCache_ = Cache::No, Cache FunctionCache_ = Cache::No)212 Cache RHSComponentCache_ = Cache::No, Cache ArrayCache_ = Cache::No,
270 : K(K_), RHSComponentCache(RHSComponentCache_), ArrayCache(ArrayCache_),213 Cache FunctionCache_ = Cache::No)
271 FunctionCache(FunctionCache_) {}214 : K(K_), Precedence(Precedence_), RHSComponentCache(RHSComponentCache_),
215 ArrayCache(ArrayCache_), FunctionCache(FunctionCache_) {}
216 Node(Kind K_, Cache RHSComponentCache_, Cache ArrayCache_ = Cache::No,
217 Cache FunctionCache_ = Cache::No)
218 : Node(K_, Prec::Primary, RHSComponentCache_, ArrayCache_,
219 FunctionCache_) {}
272220
273 /// Visit the most-derived object corresponding to this object.221 /// Visit the most-derived object corresponding to this object.
274 template<typename Fn> void visit(Fn F) const;222 template<typename Fn> void visit(Fn F) const;
...@@ -299,6 +247,8 @@ public:...@@ -299,6 +247,8 @@ public:
299247
300 Kind getKind() const { return K; }248 Kind getKind() const { return K; }
301249
250 Prec getPrecedence() const { return Precedence; }
251
302 virtual bool hasRHSComponentSlow(OutputBuffer &) const { return false; }252 virtual bool hasRHSComponentSlow(OutputBuffer &) const { return false; }
303 virtual bool hasArraySlow(OutputBuffer &) const { return false; }253 virtual bool hasArraySlow(OutputBuffer &) const { return false; }
304 virtual bool hasFunctionSlow(OutputBuffer &) const { return false; }254 virtual bool hasFunctionSlow(OutputBuffer &) const { return false; }
...@@ -307,6 +257,19 @@ public:...@@ -307,6 +257,19 @@ public:
307 // get at a node that actually represents some concrete syntax.257 // get at a node that actually represents some concrete syntax.
308 virtual const Node *getSyntaxNode(OutputBuffer &) const { return this; }258 virtual const Node *getSyntaxNode(OutputBuffer &) const { return this; }
309259
260 // Print this node as an expression operand, surrounding it in parentheses if
261 // its precedence is [Strictly] weaker than P.
262 void printAsOperand(OutputBuffer &OB, Prec P = Prec::Default,
263 bool StrictlyWorse = false) const {
264 bool Paren =
265 unsigned(getPrecedence()) >= unsigned(P) + unsigned(StrictlyWorse);
266 if (Paren)
267 OB.printOpen();
268 print(OB);
269 if (Paren)
270 OB.printClose();
271 }
272
310 void print(OutputBuffer &OB) const {273 void print(OutputBuffer &OB) const {
311 printLeft(OB);274 printLeft(OB);
312 if (RHSComponentCache != Cache::No)275 if (RHSComponentCache != Cache::No)
...@@ -356,7 +319,7 @@ public:...@@ -356,7 +319,7 @@ public:
356 if (!FirstElement)319 if (!FirstElement)
357 OB += ", ";320 OB += ", ";
358 size_t AfterComma = OB.getCurrentPosition();321 size_t AfterComma = OB.getCurrentPosition();
359 Elements[Idx]->print(OB);322 Elements[Idx]->printAsOperand(OB, Node::Prec::Comma);
360323
361 // Elements[Idx] is an empty parameter pack expansion, we should erase the324 // Elements[Idx] is an empty parameter pack expansion, we should erase the
362 // comma we just printed.325 // comma we just printed.
...@@ -494,7 +457,7 @@ class PostfixQualifiedType final : public Node {...@@ -494,7 +457,7 @@ class PostfixQualifiedType final : public Node {
494 const StringView Postfix;457 const StringView Postfix;
495458
496public:459public:
497 PostfixQualifiedType(Node *Ty_, StringView Postfix_)460 PostfixQualifiedType(const Node *Ty_, StringView Postfix_)
498 : Node(KPostfixQualifiedType), Ty(Ty_), Postfix(Postfix_) {}461 : Node(KPostfixQualifiedType), Ty(Ty_), Postfix(Postfix_) {}
499462
500 template<typename Fn> void match(Fn F) const { F(Ty, Postfix); }463 template<typename Fn> void match(Fn F) const { F(Ty, Postfix); }
...@@ -519,6 +482,26 @@ public:...@@ -519,6 +482,26 @@ public:
519 void printLeft(OutputBuffer &OB) const override { OB += Name; }482 void printLeft(OutputBuffer &OB) const override { OB += Name; }
520};483};
521484
485class BitIntType final : public Node {
486 const Node *Size;
487 bool Signed;
488
489public:
490 BitIntType(const Node *Size_, bool Signed_)
491 : Node(KBitIntType), Size(Size_), Signed(Signed_) {}
492
493 template <typename Fn> void match(Fn F) const { F(Size, Signed); }
494
495 void printLeft(OutputBuffer &OB) const override {
496 if (!Signed)
497 OB += "unsigned ";
498 OB += "_BitInt";
499 OB.printOpen();
500 Size->printAsOperand(OB);
501 OB.printClose();
502 }
503};
504
522class ElaboratedTypeSpefType : public Node {505class ElaboratedTypeSpefType : public Node {
523 StringView Kind;506 StringView Kind;
524 Node *Child;507 Node *Child;
...@@ -693,7 +676,7 @@ public:...@@ -693,7 +676,7 @@ public:
693 void printLeft(OutputBuffer &OB) const override {676 void printLeft(OutputBuffer &OB) const override {
694 if (Printing)677 if (Printing)
695 return;678 return;
696 SwapAndRestore<bool> SavePrinting(Printing, true);679 ScopedOverride<bool> SavePrinting(Printing, true);
697 std::pair<ReferenceKind, const Node *> Collapsed = collapse(OB);680 std::pair<ReferenceKind, const Node *> Collapsed = collapse(OB);
698 if (!Collapsed.second)681 if (!Collapsed.second)
699 return;682 return;
...@@ -708,7 +691,7 @@ public:...@@ -708,7 +691,7 @@ public:
708 void printRight(OutputBuffer &OB) const override {691 void printRight(OutputBuffer &OB) const override {
709 if (Printing)692 if (Printing)
710 return;693 return;
711 SwapAndRestore<bool> SavePrinting(Printing, true);694 ScopedOverride<bool> SavePrinting(Printing, true);
712 std::pair<ReferenceKind, const Node *> Collapsed = collapse(OB);695 std::pair<ReferenceKind, const Node *> Collapsed = collapse(OB);
713 if (!Collapsed.second)696 if (!Collapsed.second)
714 return;697 return;
...@@ -815,9 +798,9 @@ public:...@@ -815,9 +798,9 @@ public:
815 }798 }
816799
817 void printRight(OutputBuffer &OB) const override {800 void printRight(OutputBuffer &OB) const override {
818 OB += "(";801 OB.printOpen();
819 Params.printWithComma(OB);802 Params.printWithComma(OB);
820 OB += ")";803 OB.printClose();
821 Ret->printRight(OB);804 Ret->printRight(OB);
822805
823 if (CVQuals & QualConst)806 if (CVQuals & QualConst)
...@@ -847,9 +830,10 @@ public:...@@ -847,9 +830,10 @@ public:
847 template<typename Fn> void match(Fn F) const { F(E); }830 template<typename Fn> void match(Fn F) const { F(E); }
848831
849 void printLeft(OutputBuffer &OB) const override {832 void printLeft(OutputBuffer &OB) const override {
850 OB += "noexcept(";833 OB += "noexcept";
851 E->print(OB);834 OB.printOpen();
852 OB += ")";835 E->printAsOperand(OB);
836 OB.printClose();
853 }837 }
854};838};
855839
...@@ -862,9 +846,10 @@ public:...@@ -862,9 +846,10 @@ public:
862 template<typename Fn> void match(Fn F) const { F(Types); }846 template<typename Fn> void match(Fn F) const { F(Types); }
863847
864 void printLeft(OutputBuffer &OB) const override {848 void printLeft(OutputBuffer &OB) const override {
865 OB += "throw(";849 OB += "throw";
850 OB.printOpen();
866 Types.printWithComma(OB);851 Types.printWithComma(OB);
867 OB += ')';852 OB.printClose();
868 }853 }
869};854};
870855
...@@ -910,9 +895,9 @@ public:...@@ -910,9 +895,9 @@ public:
910 }895 }
911896
912 void printRight(OutputBuffer &OB) const override {897 void printRight(OutputBuffer &OB) const override {
913 OB += "(";898 OB.printOpen();
914 Params.printWithComma(OB);899 Params.printWithComma(OB);
915 OB += ")";900 OB.printClose();
916 if (Ret)901 if (Ret)
917 Ret->printRight(OB);902 Ret->printRight(OB);
918903
...@@ -1001,6 +986,46 @@ struct NestedName : Node {...@@ -1001,6 +986,46 @@ struct NestedName : Node {
1001 }986 }
1002};987};
1003988
989struct ModuleName : Node {
990 ModuleName *Parent;
991 Node *Name;
992 bool IsPartition;
993
994 ModuleName(ModuleName *Parent_, Node *Name_, bool IsPartition_ = false)
995 : Node(KModuleName), Parent(Parent_), Name(Name_),
996 IsPartition(IsPartition_) {}
997
998 template <typename Fn> void match(Fn F) const {
999 F(Parent, Name, IsPartition);
1000 }
1001
1002 void printLeft(OutputBuffer &OB) const override {
1003 if (Parent)
1004 Parent->print(OB);
1005 if (Parent || IsPartition)
1006 OB += IsPartition ? ':' : '.';
1007 Name->print(OB);
1008 }
1009};
1010
1011struct ModuleEntity : Node {
1012 ModuleName *Module;
1013 Node *Name;
1014
1015 ModuleEntity(ModuleName *Module_, Node *Name_)
1016 : Node(KModuleEntity), Module(Module_), Name(Name_) {}
1017
1018 template <typename Fn> void match(Fn F) const { F(Module, Name); }
1019
1020 StringView getBaseName() const override { return Name->getBaseName(); }
1021
1022 void printLeft(OutputBuffer &OB) const override {
1023 Name->print(OB);
1024 OB += '@';
1025 Module->print(OB);
1026 }
1027};
1028
1004struct LocalName : Node {1029struct LocalName : Node {
1005 Node *Encoding;1030 Node *Encoding;
1006 Node *Entity;1031 Node *Entity;
...@@ -1042,9 +1067,8 @@ class VectorType final : public Node {...@@ -1042,9 +1067,8 @@ class VectorType final : public Node {
1042 const Node *Dimension;1067 const Node *Dimension;
10431068
1044public:1069public:
1045 VectorType(const Node *BaseType_, Node *Dimension_)1070 VectorType(const Node *BaseType_, const Node *Dimension_)
1046 : Node(KVectorType), BaseType(BaseType_),1071 : Node(KVectorType), BaseType(BaseType_), Dimension(Dimension_) {}
1047 Dimension(Dimension_) {}
10481072
1049 template<typename Fn> void match(Fn F) const { F(BaseType, Dimension); }1073 template<typename Fn> void match(Fn F) const { F(BaseType, Dimension); }
10501074
...@@ -1176,6 +1200,7 @@ public:...@@ -1176,6 +1200,7 @@ public:
1176 template<typename Fn> void match(Fn F) const { F(Name, Params); }1200 template<typename Fn> void match(Fn F) const { F(Name, Params); }
11771201
1178 void printLeft(OutputBuffer &OB) const override {1202 void printLeft(OutputBuffer &OB) const override {
1203 ScopedOverride<unsigned> LT(OB.GtIsGt, 0);
1179 OB += "template<";1204 OB += "template<";
1180 Params.printWithComma(OB);1205 Params.printWithComma(OB);
1181 OB += "> typename ";1206 OB += "> typename ";
...@@ -1311,8 +1336,8 @@ public:...@@ -1311,8 +1336,8 @@ public:
13111336
1312 void printLeft(OutputBuffer &OB) const override {1337 void printLeft(OutputBuffer &OB) const override {
1313 constexpr unsigned Max = std::numeric_limits<unsigned>::max();1338 constexpr unsigned Max = std::numeric_limits<unsigned>::max();
1314 SwapAndRestore<unsigned> SavePackIdx(OB.CurrentPackIndex, Max);1339 ScopedOverride<unsigned> SavePackIdx(OB.CurrentPackIndex, Max);
1315 SwapAndRestore<unsigned> SavePackMax(OB.CurrentPackMax, Max);1340 ScopedOverride<unsigned> SavePackMax(OB.CurrentPackMax, Max);
1316 size_t StreamPos = OB.getCurrentPosition();1341 size_t StreamPos = OB.getCurrentPosition();
13171342
1318 // Print the first element in the pack. If Child contains a ParameterPack,1343 // Print the first element in the pack. If Child contains a ParameterPack,
...@@ -1353,10 +1378,9 @@ public:...@@ -1353,10 +1378,9 @@ public:
1353 NodeArray getParams() { return Params; }1378 NodeArray getParams() { return Params; }
13541379
1355 void printLeft(OutputBuffer &OB) const override {1380 void printLeft(OutputBuffer &OB) const override {
1381 ScopedOverride<unsigned> LT(OB.GtIsGt, 0);
1356 OB += "<";1382 OB += "<";
1357 Params.printWithComma(OB);1383 Params.printWithComma(OB);
1358 if (OB.back() == '>')
1359 OB += " ";
1360 OB += ">";1384 OB += ">";
1361 }1385 }
1362};1386};
...@@ -1402,38 +1426,38 @@ struct ForwardTemplateReference : Node {...@@ -1402,38 +1426,38 @@ struct ForwardTemplateReference : Node {
1402 bool hasRHSComponentSlow(OutputBuffer &OB) const override {1426 bool hasRHSComponentSlow(OutputBuffer &OB) const override {
1403 if (Printing)1427 if (Printing)
1404 return false;1428 return false;
1405 SwapAndRestore<bool> SavePrinting(Printing, true);1429 ScopedOverride<bool> SavePrinting(Printing, true);
1406 return Ref->hasRHSComponent(OB);1430 return Ref->hasRHSComponent(OB);
1407 }1431 }
1408 bool hasArraySlow(OutputBuffer &OB) const override {1432 bool hasArraySlow(OutputBuffer &OB) const override {
1409 if (Printing)1433 if (Printing)
1410 return false;1434 return false;
1411 SwapAndRestore<bool> SavePrinting(Printing, true);1435 ScopedOverride<bool> SavePrinting(Printing, true);
1412 return Ref->hasArray(OB);1436 return Ref->hasArray(OB);
1413 }1437 }
1414 bool hasFunctionSlow(OutputBuffer &OB) const override {1438 bool hasFunctionSlow(OutputBuffer &OB) const override {
1415 if (Printing)1439 if (Printing)
1416 return false;1440 return false;
1417 SwapAndRestore<bool> SavePrinting(Printing, true);1441 ScopedOverride<bool> SavePrinting(Printing, true);
1418 return Ref->hasFunction(OB);1442 return Ref->hasFunction(OB);
1419 }1443 }
1420 const Node *getSyntaxNode(OutputBuffer &OB) const override {1444 const Node *getSyntaxNode(OutputBuffer &OB) const override {
1421 if (Printing)1445 if (Printing)
1422 return this;1446 return this;
1423 SwapAndRestore<bool> SavePrinting(Printing, true);1447 ScopedOverride<bool> SavePrinting(Printing, true);
1424 return Ref->getSyntaxNode(OB);1448 return Ref->getSyntaxNode(OB);
1425 }1449 }
14261450
1427 void printLeft(OutputBuffer &OB) const override {1451 void printLeft(OutputBuffer &OB) const override {
1428 if (Printing)1452 if (Printing)
1429 return;1453 return;
1430 SwapAndRestore<bool> SavePrinting(Printing, true);1454 ScopedOverride<bool> SavePrinting(Printing, true);
1431 Ref->printLeft(OB);1455 Ref->printLeft(OB);
1432 }1456 }
1433 void printRight(OutputBuffer &OB) const override {1457 void printRight(OutputBuffer &OB) const override {
1434 if (Printing)1458 if (Printing)
1435 return;1459 return;
1436 SwapAndRestore<bool> SavePrinting(Printing, true);1460 ScopedOverride<bool> SavePrinting(Printing, true);
1437 Ref->printRight(OB);1461 Ref->printRight(OB);
1438 }1462 }
1439};1463};
...@@ -1473,21 +1497,6 @@ public:...@@ -1473,21 +1497,6 @@ public:
1473 }1497 }
1474};1498};
14751499
1476struct StdQualifiedName : Node {
1477 Node *Child;
1478
1479 StdQualifiedName(Node *Child_) : Node(KStdQualifiedName), Child(Child_) {}
1480
1481 template<typename Fn> void match(Fn F) const { F(Child); }
1482
1483 StringView getBaseName() const override { return Child->getBaseName(); }
1484
1485 void printLeft(OutputBuffer &OB) const override {
1486 OB += "std::";
1487 Child->print(OB);
1488 }
1489};
1490
1491enum class SpecialSubKind {1500enum class SpecialSubKind {
1492 allocator,1501 allocator,
1493 basic_string,1502 basic_string,
...@@ -1497,15 +1506,25 @@ enum class SpecialSubKind {...@@ -1497,15 +1506,25 @@ enum class SpecialSubKind {
1497 iostream,1506 iostream,
1498};1507};
14991508
1500class ExpandedSpecialSubstitution final : public Node {1509class SpecialSubstitution;
1510class ExpandedSpecialSubstitution : public Node {
1511protected:
1501 SpecialSubKind SSK;1512 SpecialSubKind SSK;
15021513
1514 ExpandedSpecialSubstitution(SpecialSubKind SSK_, Kind K_)
1515 : Node(K_), SSK(SSK_) {}
1503public:1516public:
1504 ExpandedSpecialSubstitution(SpecialSubKind SSK_)1517 ExpandedSpecialSubstitution(SpecialSubKind SSK_)
1505 : Node(KExpandedSpecialSubstitution), SSK(SSK_) {}1518 : ExpandedSpecialSubstitution(SSK_, KExpandedSpecialSubstitution) {}
1519 inline ExpandedSpecialSubstitution(SpecialSubstitution const *);
15061520
1507 template<typename Fn> void match(Fn F) const { F(SSK); }1521 template<typename Fn> void match(Fn F) const { F(SSK); }
15081522
1523protected:
1524 bool isInstantiation() const {
1525 return unsigned(SSK) >= unsigned(SpecialSubKind::string);
1526 }
1527
1509 StringView getBaseName() const override {1528 StringView getBaseName() const override {
1510 switch (SSK) {1529 switch (SSK) {
1511 case SpecialSubKind::allocator:1530 case SpecialSubKind::allocator:
...@@ -1524,82 +1543,44 @@ public:...@@ -1524,82 +1543,44 @@ public:
1524 DEMANGLE_UNREACHABLE;1543 DEMANGLE_UNREACHABLE;
1525 }1544 }
15261545
1546private:
1527 void printLeft(OutputBuffer &OB) const override {1547 void printLeft(OutputBuffer &OB) const override {
1528 switch (SSK) {1548 OB << "std::" << getBaseName();
1529 case SpecialSubKind::allocator:1549 if (isInstantiation()) {
1530 OB += "std::allocator";1550 OB << "<char, std::char_traits<char>";
1531 break;1551 if (SSK == SpecialSubKind::string)
1532 case SpecialSubKind::basic_string:1552 OB << ", std::allocator<char>";
1533 OB += "std::basic_string";1553 OB << ">";
1534 break;
1535 case SpecialSubKind::string:
1536 OB += "std::basic_string<char, std::char_traits<char>, "
1537 "std::allocator<char> >";
1538 break;
1539 case SpecialSubKind::istream:
1540 OB += "std::basic_istream<char, std::char_traits<char> >";
1541 break;
1542 case SpecialSubKind::ostream:
1543 OB += "std::basic_ostream<char, std::char_traits<char> >";
1544 break;
1545 case SpecialSubKind::iostream:
1546 OB += "std::basic_iostream<char, std::char_traits<char> >";
1547 break;
1548 }1554 }
1549 }1555 }
1550};1556};
15511557
1552class SpecialSubstitution final : public Node {1558class SpecialSubstitution final : public ExpandedSpecialSubstitution {
1553public:1559public:
1554 SpecialSubKind SSK;
1555
1556 SpecialSubstitution(SpecialSubKind SSK_)1560 SpecialSubstitution(SpecialSubKind SSK_)
1557 : Node(KSpecialSubstitution), SSK(SSK_) {}1561 : ExpandedSpecialSubstitution(SSK_, KSpecialSubstitution) {}
15581562
1559 template<typename Fn> void match(Fn F) const { F(SSK); }1563 template<typename Fn> void match(Fn F) const { F(SSK); }
15601564
1561 StringView getBaseName() const override {1565 StringView getBaseName() const override {
1562 switch (SSK) {1566 auto SV = ExpandedSpecialSubstitution::getBaseName ();
1563 case SpecialSubKind::allocator:1567 if (isInstantiation()) {
1564 return StringView("allocator");1568 // The instantiations are typedefs that drop the "basic_" prefix.
1565 case SpecialSubKind::basic_string:1569 assert(SV.startsWith("basic_"));
1566 return StringView("basic_string");1570 SV = SV.dropFront(sizeof("basic_") - 1);
1567 case SpecialSubKind::string:
1568 return StringView("string");
1569 case SpecialSubKind::istream:
1570 return StringView("istream");
1571 case SpecialSubKind::ostream:
1572 return StringView("ostream");
1573 case SpecialSubKind::iostream:
1574 return StringView("iostream");
1575 }1571 }
1576 DEMANGLE_UNREACHABLE;1572 return SV;
1577 }1573 }
15781574
1579 void printLeft(OutputBuffer &OB) const override {1575 void printLeft(OutputBuffer &OB) const override {
1580 switch (SSK) {1576 OB << "std::" << getBaseName();
1581 case SpecialSubKind::allocator:
1582 OB += "std::allocator";
1583 break;
1584 case SpecialSubKind::basic_string:
1585 OB += "std::basic_string";
1586 break;
1587 case SpecialSubKind::string:
1588 OB += "std::string";
1589 break;
1590 case SpecialSubKind::istream:
1591 OB += "std::istream";
1592 break;
1593 case SpecialSubKind::ostream:
1594 OB += "std::ostream";
1595 break;
1596 case SpecialSubKind::iostream:
1597 OB += "std::iostream";
1598 break;
1599 }
1600 }1577 }
1601};1578};
16021579
1580inline ExpandedSpecialSubstitution::ExpandedSpecialSubstitution(
1581 SpecialSubstitution const *SS)
1582 : ExpandedSpecialSubstitution(SS->SSK) {}
1583
1603class CtorDtorName final : public Node {1584class CtorDtorName final : public Node {
1604 const Node *Basename;1585 const Node *Basename;
1605 const bool IsDtor;1586 const bool IsDtor;
...@@ -1665,13 +1646,14 @@ public:...@@ -1665,13 +1646,14 @@ public:
16651646
1666 void printDeclarator(OutputBuffer &OB) const {1647 void printDeclarator(OutputBuffer &OB) const {
1667 if (!TemplateParams.empty()) {1648 if (!TemplateParams.empty()) {
1649 ScopedOverride<unsigned> LT(OB.GtIsGt, 0);
1668 OB += "<";1650 OB += "<";
1669 TemplateParams.printWithComma(OB);1651 TemplateParams.printWithComma(OB);
1670 OB += ">";1652 OB += ">";
1671 }1653 }
1672 OB += "(";1654 OB.printOpen();
1673 Params.printWithComma(OB);1655 Params.printWithComma(OB);
1674 OB += ")";1656 OB.printClose();
1675 }1657 }
16761658
1677 void printLeft(OutputBuffer &OB) const override {1659 void printLeft(OutputBuffer &OB) const override {
...@@ -1691,9 +1673,9 @@ public:...@@ -1691,9 +1673,9 @@ public:
1691 template<typename Fn> void match(Fn F) const { F(Bindings); }1673 template<typename Fn> void match(Fn F) const { F(Bindings); }
16921674
1693 void printLeft(OutputBuffer &OB) const override {1675 void printLeft(OutputBuffer &OB) const override {
1694 OB += '[';1676 OB.printOpen('[');
1695 Bindings.printWithComma(OB);1677 Bindings.printWithComma(OB);
1696 OB += ']';1678 OB.printClose(']');
1697 }1679 }
1698};1680};
16991681
...@@ -1705,28 +1687,31 @@ class BinaryExpr : public Node {...@@ -1705,28 +1687,31 @@ class BinaryExpr : public Node {
1705 const Node *RHS;1687 const Node *RHS;
17061688
1707public:1689public:
1708 BinaryExpr(const Node *LHS_, StringView InfixOperator_, const Node *RHS_)1690 BinaryExpr(const Node *LHS_, StringView InfixOperator_, const Node *RHS_,
1709 : Node(KBinaryExpr), LHS(LHS_), InfixOperator(InfixOperator_), RHS(RHS_) {1691 Prec Prec_)
1710 }1692 : Node(KBinaryExpr, Prec_), LHS(LHS_), InfixOperator(InfixOperator_),
1693 RHS(RHS_) {}
17111694
1712 template<typename Fn> void match(Fn F) const { F(LHS, InfixOperator, RHS); }1695 template <typename Fn> void match(Fn F) const {
1696 F(LHS, InfixOperator, RHS, getPrecedence());
1697 }
17131698
1714 void printLeft(OutputBuffer &OB) const override {1699 void printLeft(OutputBuffer &OB) const override {
1715 // might be a template argument expression, then we need to disambiguate1700 bool ParenAll = OB.isGtInsideTemplateArgs() &&
1716 // with parens.1701 (InfixOperator == ">" || InfixOperator == ">>");
1717 if (InfixOperator == ">")1702 if (ParenAll)
1718 OB += "(";1703 OB.printOpen();
17191704 // Assignment is right associative, with special LHS precedence.
1720 OB += "(";1705 bool IsAssign = getPrecedence() == Prec::Assign;
1721 LHS->print(OB);1706 LHS->printAsOperand(OB, IsAssign ? Prec::OrIf : getPrecedence(), !IsAssign);
1722 OB += ") ";1707 // No space before comma operator
1708 if (!(InfixOperator == ","))
1709 OB += " ";
1723 OB += InfixOperator;1710 OB += InfixOperator;
1724 OB += " (";1711 OB += " ";
1725 RHS->print(OB);1712 RHS->printAsOperand(OB, getPrecedence(), IsAssign);
1726 OB += ")";1713 if (ParenAll)
17271714 OB.printClose();
1728 if (InfixOperator == ">")
1729 OB += ")";
1730 }1715 }
1731};1716};
17321717
...@@ -1735,17 +1720,18 @@ class ArraySubscriptExpr : public Node {...@@ -1735,17 +1720,18 @@ class ArraySubscriptExpr : public Node {
1735 const Node *Op2;1720 const Node *Op2;
17361721
1737public:1722public:
1738 ArraySubscriptExpr(const Node *Op1_, const Node *Op2_)1723 ArraySubscriptExpr(const Node *Op1_, const Node *Op2_, Prec Prec_)
1739 : Node(KArraySubscriptExpr), Op1(Op1_), Op2(Op2_) {}1724 : Node(KArraySubscriptExpr, Prec_), Op1(Op1_), Op2(Op2_) {}
17401725
1741 template<typename Fn> void match(Fn F) const { F(Op1, Op2); }1726 template <typename Fn> void match(Fn F) const {
1727 F(Op1, Op2, getPrecedence());
1728 }
17421729
1743 void printLeft(OutputBuffer &OB) const override {1730 void printLeft(OutputBuffer &OB) const override {
1744 OB += "(";1731 Op1->printAsOperand(OB, getPrecedence());
1745 Op1->print(OB);1732 OB.printOpen('[');
1746 OB += ")[";1733 Op2->printAsOperand(OB);
1747 Op2->print(OB);1734 OB.printClose(']');
1748 OB += "]";
1749 }1735 }
1750};1736};
17511737
...@@ -1754,15 +1740,15 @@ class PostfixExpr : public Node {...@@ -1754,15 +1740,15 @@ class PostfixExpr : public Node {
1754 const StringView Operator;1740 const StringView Operator;
17551741
1756public:1742public:
1757 PostfixExpr(const Node *Child_, StringView Operator_)1743 PostfixExpr(const Node *Child_, StringView Operator_, Prec Prec_)
1758 : Node(KPostfixExpr), Child(Child_), Operator(Operator_) {}1744 : Node(KPostfixExpr, Prec_), Child(Child_), Operator(Operator_) {}
17591745
1760 template<typename Fn> void match(Fn F) const { F(Child, Operator); }1746 template <typename Fn> void match(Fn F) const {
1747 F(Child, Operator, getPrecedence());
1748 }
17611749
1762 void printLeft(OutputBuffer &OB) const override {1750 void printLeft(OutputBuffer &OB) const override {
1763 OB += "(";1751 Child->printAsOperand(OB, getPrecedence(), true);
1764 Child->print(OB);
1765 OB += ")";
1766 OB += Operator;1752 OB += Operator;
1767 }1753 }
1768};1754};
...@@ -1773,19 +1759,20 @@ class ConditionalExpr : public Node {...@@ -1773,19 +1759,20 @@ class ConditionalExpr : public Node {
1773 const Node *Else;1759 const Node *Else;
17741760
1775public:1761public:
1776 ConditionalExpr(const Node *Cond_, const Node *Then_, const Node *Else_)1762 ConditionalExpr(const Node *Cond_, const Node *Then_, const Node *Else_,
1777 : Node(KConditionalExpr), Cond(Cond_), Then(Then_), Else(Else_) {}1763 Prec Prec_)
1764 : Node(KConditionalExpr, Prec_), Cond(Cond_), Then(Then_), Else(Else_) {}
17781765
1779 template<typename Fn> void match(Fn F) const { F(Cond, Then, Else); }1766 template <typename Fn> void match(Fn F) const {
1767 F(Cond, Then, Else, getPrecedence());
1768 }
17801769
1781 void printLeft(OutputBuffer &OB) const override {1770 void printLeft(OutputBuffer &OB) const override {
1782 OB += "(";1771 Cond->printAsOperand(OB, getPrecedence());
1783 Cond->print(OB);1772 OB += " ? ";
1784 OB += ") ? (";1773 Then->printAsOperand(OB);
1785 Then->print(OB);1774 OB += " : ";
1786 OB += ") : (";1775 Else->printAsOperand(OB, Prec::Assign, true);
1787 Else->print(OB);
1788 OB += ")";
1789 }1776 }
1790};1777};
17911778
...@@ -1795,15 +1782,17 @@ class MemberExpr : public Node {...@@ -1795,15 +1782,17 @@ class MemberExpr : public Node {
1795 const Node *RHS;1782 const Node *RHS;
17961783
1797public:1784public:
1798 MemberExpr(const Node *LHS_, StringView Kind_, const Node *RHS_)1785 MemberExpr(const Node *LHS_, StringView Kind_, const Node *RHS_, Prec Prec_)
1799 : Node(KMemberExpr), LHS(LHS_), Kind(Kind_), RHS(RHS_) {}1786 : Node(KMemberExpr, Prec_), LHS(LHS_), Kind(Kind_), RHS(RHS_) {}
18001787
1801 template<typename Fn> void match(Fn F) const { F(LHS, Kind, RHS); }1788 template <typename Fn> void match(Fn F) const {
1789 F(LHS, Kind, RHS, getPrecedence());
1790 }
18021791
1803 void printLeft(OutputBuffer &OB) const override {1792 void printLeft(OutputBuffer &OB) const override {
1804 LHS->print(OB);1793 LHS->printAsOperand(OB, getPrecedence(), true);
1805 OB += Kind;1794 OB += Kind;
1806 RHS->print(OB);1795 RHS->printAsOperand(OB, getPrecedence(), false);
1807 }1796 }
1808};1797};
18091798
...@@ -1847,15 +1836,19 @@ class EnclosingExpr : public Node {...@@ -1847,15 +1836,19 @@ class EnclosingExpr : public Node {
1847 const StringView Postfix;1836 const StringView Postfix;
18481837
1849public:1838public:
1850 EnclosingExpr(StringView Prefix_, Node *Infix_, StringView Postfix_)1839 EnclosingExpr(StringView Prefix_, const Node *Infix_,
1851 : Node(KEnclosingExpr), Prefix(Prefix_), Infix(Infix_),1840 Prec Prec_ = Prec::Primary)
1852 Postfix(Postfix_) {}1841 : Node(KEnclosingExpr, Prec_), Prefix(Prefix_), Infix(Infix_) {}
18531842
1854 template<typename Fn> void match(Fn F) const { F(Prefix, Infix, Postfix); }1843 template <typename Fn> void match(Fn F) const {
1844 F(Prefix, Infix, getPrecedence());
1845 }
18551846
1856 void printLeft(OutputBuffer &OB) const override {1847 void printLeft(OutputBuffer &OB) const override {
1857 OB += Prefix;1848 OB += Prefix;
1849 OB.printOpen();
1858 Infix->print(OB);1850 Infix->print(OB);
1851 OB.printClose();
1859 OB += Postfix;1852 OB += Postfix;
1860 }1853 }
1861};1854};
...@@ -1867,18 +1860,24 @@ class CastExpr : public Node {...@@ -1867,18 +1860,24 @@ class CastExpr : public Node {
1867 const Node *From;1860 const Node *From;
18681861
1869public:1862public:
1870 CastExpr(StringView CastKind_, const Node *To_, const Node *From_)1863 CastExpr(StringView CastKind_, const Node *To_, const Node *From_, Prec Prec_)
1871 : Node(KCastExpr), CastKind(CastKind_), To(To_), From(From_) {}1864 : Node(KCastExpr, Prec_), CastKind(CastKind_), To(To_), From(From_) {}
18721865
1873 template<typename Fn> void match(Fn F) const { F(CastKind, To, From); }1866 template <typename Fn> void match(Fn F) const {
1867 F(CastKind, To, From, getPrecedence());
1868 }
18741869
1875 void printLeft(OutputBuffer &OB) const override {1870 void printLeft(OutputBuffer &OB) const override {
1876 OB += CastKind;1871 OB += CastKind;
1877 OB += "<";1872 {
1878 To->printLeft(OB);1873 ScopedOverride<unsigned> LT(OB.GtIsGt, 0);
1879 OB += ">(";1874 OB += "<";
1880 From->printLeft(OB);1875 To->printLeft(OB);
1881 OB += ")";1876 OB += ">";
1877 }
1878 OB.printOpen();
1879 From->printAsOperand(OB);
1880 OB.printClose();
1882 }1881 }
1883};1882};
18841883
...@@ -1892,10 +1891,11 @@ public:...@@ -1892,10 +1891,11 @@ public:
1892 template<typename Fn> void match(Fn F) const { F(Pack); }1891 template<typename Fn> void match(Fn F) const { F(Pack); }
18931892
1894 void printLeft(OutputBuffer &OB) const override {1893 void printLeft(OutputBuffer &OB) const override {
1895 OB += "sizeof...(";1894 OB += "sizeof...";
1895 OB.printOpen();
1896 ParameterPackExpansion PPE(Pack);1896 ParameterPackExpansion PPE(Pack);
1897 PPE.printLeft(OB);1897 PPE.printLeft(OB);
1898 OB += ")";1898 OB.printClose();
1899 }1899 }
1900};1900};
19011901
...@@ -1904,16 +1904,18 @@ class CallExpr : public Node {...@@ -1904,16 +1904,18 @@ class CallExpr : public Node {
1904 NodeArray Args;1904 NodeArray Args;
19051905
1906public:1906public:
1907 CallExpr(const Node *Callee_, NodeArray Args_)1907 CallExpr(const Node *Callee_, NodeArray Args_, Prec Prec_)
1908 : Node(KCallExpr), Callee(Callee_), Args(Args_) {}1908 : Node(KCallExpr, Prec_), Callee(Callee_), Args(Args_) {}
19091909
1910 template<typename Fn> void match(Fn F) const { F(Callee, Args); }1910 template <typename Fn> void match(Fn F) const {
1911 F(Callee, Args, getPrecedence());
1912 }
19111913
1912 void printLeft(OutputBuffer &OB) const override {1914 void printLeft(OutputBuffer &OB) const override {
1913 Callee->print(OB);1915 Callee->print(OB);
1914 OB += "(";1916 OB.printOpen();
1915 Args.printWithComma(OB);1917 Args.printWithComma(OB);
1916 OB += ")";1918 OB.printClose();
1917 }1919 }
1918};1920};
19191921
...@@ -1926,31 +1928,31 @@ class NewExpr : public Node {...@@ -1926,31 +1928,31 @@ class NewExpr : public Node {
1926 bool IsArray; // new[] ?1928 bool IsArray; // new[] ?
1927public:1929public:
1928 NewExpr(NodeArray ExprList_, Node *Type_, NodeArray InitList_, bool IsGlobal_,1930 NewExpr(NodeArray ExprList_, Node *Type_, NodeArray InitList_, bool IsGlobal_,
1929 bool IsArray_)1931 bool IsArray_, Prec Prec_)
1930 : Node(KNewExpr), ExprList(ExprList_), Type(Type_), InitList(InitList_),1932 : Node(KNewExpr, Prec_), ExprList(ExprList_), Type(Type_),
1931 IsGlobal(IsGlobal_), IsArray(IsArray_) {}1933 InitList(InitList_), IsGlobal(IsGlobal_), IsArray(IsArray_) {}
19321934
1933 template<typename Fn> void match(Fn F) const {1935 template<typename Fn> void match(Fn F) const {
1934 F(ExprList, Type, InitList, IsGlobal, IsArray);1936 F(ExprList, Type, InitList, IsGlobal, IsArray, getPrecedence());
1935 }1937 }
19361938
1937 void printLeft(OutputBuffer &OB) const override {1939 void printLeft(OutputBuffer &OB) const override {
1938 if (IsGlobal)1940 if (IsGlobal)
1939 OB += "::operator ";1941 OB += "::";
1940 OB += "new";1942 OB += "new";
1941 if (IsArray)1943 if (IsArray)
1942 OB += "[]";1944 OB += "[]";
1943 OB += ' ';
1944 if (!ExprList.empty()) {1945 if (!ExprList.empty()) {
1945 OB += "(";1946 OB.printOpen();
1946 ExprList.printWithComma(OB);1947 ExprList.printWithComma(OB);
1947 OB += ")";1948 OB.printClose();
1948 }1949 }
1950 OB += " ";
1949 Type->print(OB);1951 Type->print(OB);
1950 if (!InitList.empty()) {1952 if (!InitList.empty()) {
1951 OB += "(";1953 OB.printOpen();
1952 InitList.printWithComma(OB);1954 InitList.printWithComma(OB);
1953 OB += ")";1955 OB.printClose();
1954 }1956 }
1955 }1957 }
1956};1958};
...@@ -1961,17 +1963,21 @@ class DeleteExpr : public Node {...@@ -1961,17 +1963,21 @@ class DeleteExpr : public Node {
1961 bool IsArray;1963 bool IsArray;
19621964
1963public:1965public:
1964 DeleteExpr(Node *Op_, bool IsGlobal_, bool IsArray_)1966 DeleteExpr(Node *Op_, bool IsGlobal_, bool IsArray_, Prec Prec_)
1965 : Node(KDeleteExpr), Op(Op_), IsGlobal(IsGlobal_), IsArray(IsArray_) {}1967 : Node(KDeleteExpr, Prec_), Op(Op_), IsGlobal(IsGlobal_),
1968 IsArray(IsArray_) {}
19661969
1967 template<typename Fn> void match(Fn F) const { F(Op, IsGlobal, IsArray); }1970 template <typename Fn> void match(Fn F) const {
1971 F(Op, IsGlobal, IsArray, getPrecedence());
1972 }
19681973
1969 void printLeft(OutputBuffer &OB) const override {1974 void printLeft(OutputBuffer &OB) const override {
1970 if (IsGlobal)1975 if (IsGlobal)
1971 OB += "::";1976 OB += "::";
1972 OB += "delete";1977 OB += "delete";
1973 if (IsArray)1978 if (IsArray)
1974 OB += "[] ";1979 OB += "[]";
1980 OB += ' ';
1975 Op->print(OB);1981 Op->print(OB);
1976 }1982 }
1977};1983};
...@@ -1981,16 +1987,16 @@ class PrefixExpr : public Node {...@@ -1981,16 +1987,16 @@ class PrefixExpr : public Node {
1981 Node *Child;1987 Node *Child;
19821988
1983public:1989public:
1984 PrefixExpr(StringView Prefix_, Node *Child_)1990 PrefixExpr(StringView Prefix_, Node *Child_, Prec Prec_)
1985 : Node(KPrefixExpr), Prefix(Prefix_), Child(Child_) {}1991 : Node(KPrefixExpr, Prec_), Prefix(Prefix_), Child(Child_) {}
19861992
1987 template<typename Fn> void match(Fn F) const { F(Prefix, Child); }1993 template <typename Fn> void match(Fn F) const {
1994 F(Prefix, Child, getPrecedence());
1995 }
19881996
1989 void printLeft(OutputBuffer &OB) const override {1997 void printLeft(OutputBuffer &OB) const override {
1990 OB += Prefix;1998 OB += Prefix;
1991 OB += "(";1999 Child->printAsOperand(OB, getPrecedence());
1992 Child->print(OB);
1993 OB += ")";
1994 }2000 }
1995};2001};
19962002
...@@ -2013,17 +2019,20 @@ class ConversionExpr : public Node {...@@ -2013,17 +2019,20 @@ class ConversionExpr : public Node {
2013 NodeArray Expressions;2019 NodeArray Expressions;
20142020
2015public:2021public:
2016 ConversionExpr(const Node *Type_, NodeArray Expressions_)2022 ConversionExpr(const Node *Type_, NodeArray Expressions_, Prec Prec_)
2017 : Node(KConversionExpr), Type(Type_), Expressions(Expressions_) {}2023 : Node(KConversionExpr, Prec_), Type(Type_), Expressions(Expressions_) {}
20182024
2019 template<typename Fn> void match(Fn F) const { F(Type, Expressions); }2025 template <typename Fn> void match(Fn F) const {
2026 F(Type, Expressions, getPrecedence());
2027 }
20202028
2021 void printLeft(OutputBuffer &OB) const override {2029 void printLeft(OutputBuffer &OB) const override {
2022 OB += "(";2030 OB.printOpen();
2023 Type->print(OB);2031 Type->print(OB);
2024 OB += ")(";2032 OB.printClose();
2033 OB.printOpen();
2025 Expressions.printWithComma(OB);2034 Expressions.printWithComma(OB);
2026 OB += ")";2035 OB.printClose();
2027 }2036 }
2028};2037};
20292038
...@@ -2034,18 +2043,21 @@ class PointerToMemberConversionExpr : public Node {...@@ -2034,18 +2043,21 @@ class PointerToMemberConversionExpr : public Node {
20342043
2035public:2044public:
2036 PointerToMemberConversionExpr(const Node *Type_, const Node *SubExpr_,2045 PointerToMemberConversionExpr(const Node *Type_, const Node *SubExpr_,
2037 StringView Offset_)2046 StringView Offset_, Prec Prec_)
2038 : Node(KPointerToMemberConversionExpr), Type(Type_), SubExpr(SubExpr_),2047 : Node(KPointerToMemberConversionExpr, Prec_), Type(Type_),
2039 Offset(Offset_) {}2048 SubExpr(SubExpr_), Offset(Offset_) {}
20402049
2041 template<typename Fn> void match(Fn F) const { F(Type, SubExpr, Offset); }2050 template <typename Fn> void match(Fn F) const {
2051 F(Type, SubExpr, Offset, getPrecedence());
2052 }
20422053
2043 void printLeft(OutputBuffer &OB) const override {2054 void printLeft(OutputBuffer &OB) const override {
2044 OB += "(";2055 OB.printOpen();
2045 Type->print(OB);2056 Type->print(OB);
2046 OB += ")(";2057 OB.printClose();
2058 OB.printOpen();
2047 SubExpr->print(OB);2059 SubExpr->print(OB);
2048 OB += ")";2060 OB.printClose();
2049 }2061 }
2050};2062};
20512063
...@@ -2131,41 +2143,33 @@ public:...@@ -2131,41 +2143,33 @@ public:
21312143
2132 void printLeft(OutputBuffer &OB) const override {2144 void printLeft(OutputBuffer &OB) const override {
2133 auto PrintPack = [&] {2145 auto PrintPack = [&] {
2134 OB += '(';2146 OB.printOpen();
2135 ParameterPackExpansion(Pack).print(OB);2147 ParameterPackExpansion(Pack).print(OB);
2136 OB += ')';2148 OB.printClose();
2137 };2149 };
21382150
2139 OB += '(';2151 OB.printOpen();
21402152 // Either '[init op ]... op pack' or 'pack op ...[ op init]'
2141 if (IsLeftFold) {2153 // Refactored to '[(init|pack) op ]...[ op (pack|init)]'
2142 // init op ... op pack2154 // Fold expr operands are cast-expressions
2143 if (Init != nullptr) {2155 if (!IsLeftFold || Init != nullptr) {
2144 Init->print(OB);2156 // '(init|pack) op '
2145 OB += ' ';2157 if (IsLeftFold)
2146 OB += OperatorName;2158 Init->printAsOperand(OB, Prec::Cast, true);
2147 OB += ' ';2159 else
2148 }2160 PrintPack();
2149 // ... op pack2161 OB << " " << OperatorName << " ";
2150 OB += "... ";2162 }
2151 OB += OperatorName;2163 OB << "...";
2152 OB += ' ';2164 if (IsLeftFold || Init != nullptr) {
2153 PrintPack();2165 // ' op (init|pack)'
2154 } else { // !IsLeftFold2166 OB << " " << OperatorName << " ";
2155 // pack op ...2167 if (IsLeftFold)
2156 PrintPack();2168 PrintPack();
2157 OB += ' ';2169 else
2158 OB += OperatorName;2170 Init->printAsOperand(OB, Prec::Cast, true);
2159 OB += " ...";
2160 // pack op ... op init
2161 if (Init != nullptr) {
2162 OB += ' ';
2163 OB += OperatorName;
2164 OB += ' ';
2165 Init->print(OB);
2166 }
2167 }2171 }
2168 OB += ')';2172 OB.printClose();
2169 }2173 }
2170};2174};
21712175
...@@ -2239,9 +2243,9 @@ public:...@@ -2239,9 +2243,9 @@ public:
2239 template<typename Fn> void match(Fn F) const { F(Ty, Integer); }2243 template<typename Fn> void match(Fn F) const { F(Ty, Integer); }
22402244
2241 void printLeft(OutputBuffer &OB) const override {2245 void printLeft(OutputBuffer &OB) const override {
2242 OB << "(";2246 OB.printOpen();
2243 Ty->print(OB);2247 Ty->print(OB);
2244 OB << ")";2248 OB.printClose();
22452249
2246 if (Integer[0] == 'n')2250 if (Integer[0] == 'n')
2247 OB << "-" << Integer.dropFront(1);2251 OB << "-" << Integer.dropFront(1);
...@@ -2262,13 +2266,13 @@ public:...@@ -2262,13 +2266,13 @@ public:
22622266
2263 void printLeft(OutputBuffer &OB) const override {2267 void printLeft(OutputBuffer &OB) const override {
2264 if (Type.size() > 3) {2268 if (Type.size() > 3) {
2265 OB += "(";2269 OB.printOpen();
2266 OB += Type;2270 OB += Type;
2267 OB += ")";2271 OB.printClose();
2268 }2272 }
22692273
2270 if (Value[0] == 'n') {2274 if (Value[0] == 'n') {
2271 OB += "-";2275 OB += '-';
2272 OB += Value.dropFront(1);2276 OB += Value.dropFront(1);
2273 } else2277 } else
2274 OB += Value;2278 OB += Value;
...@@ -2344,24 +2348,22 @@ using LongDoubleLiteral = FloatLiteralImpl<long double>;...@@ -2344,24 +2348,22 @@ using LongDoubleLiteral = FloatLiteralImpl<long double>;
2344template<typename Fn>2348template<typename Fn>
2345void Node::visit(Fn F) const {2349void Node::visit(Fn F) const {
2346 switch (K) {2350 switch (K) {
2347#define CASE(X) case K ## X: return F(static_cast<const X*>(this));2351#define NODE(X) \
2348 FOR_EACH_NODE_KIND(CASE)2352 case K##X: \
2349#undef CASE2353 return F(static_cast<const X *>(this));
2354#include "ItaniumNodes.def"
2350 }2355 }
2351 assert(0 && "unknown mangling node kind");2356 assert(0 && "unknown mangling node kind");
2352}2357}
23532358
2354/// Determine the kind of a node from its type.2359/// Determine the kind of a node from its type.
2355template<typename NodeT> struct NodeKind;2360template<typename NodeT> struct NodeKind;
2356#define SPECIALIZATION(X) \2361#define NODE(X) \
2357 template<> struct NodeKind<X> { \2362 template <> struct NodeKind<X> { \
2358 static constexpr Node::Kind Kind = Node::K##X; \2363 static constexpr Node::Kind Kind = Node::K##X; \
2359 static constexpr const char *name() { return #X; } \2364 static constexpr const char *name() { return #X; } \
2360 };2365 };
2361FOR_EACH_NODE_KIND(SPECIALIZATION)2366#include "ItaniumNodes.def"
2362#undef SPECIALIZATION
2363
2364#undef FOR_EACH_NODE_KIND
23652367
2366template <typename Derived, typename Alloc> struct AbstractManglingParser {2368template <typename Derived, typename Alloc> struct AbstractManglingParser {
2367 const char *First;2369 const char *First;
...@@ -2499,17 +2501,16 @@ template <typename Derived, typename Alloc> struct AbstractManglingParser {...@@ -2499,17 +2501,16 @@ template <typename Derived, typename Alloc> struct AbstractManglingParser {
24992501
2500 /// Parse the <expr> production.2502 /// Parse the <expr> production.
2501 Node *parseExpr();2503 Node *parseExpr();
2502 Node *parsePrefixExpr(StringView Kind);2504 Node *parsePrefixExpr(StringView Kind, Node::Prec Prec);
2503 Node *parseBinaryExpr(StringView Kind);2505 Node *parseBinaryExpr(StringView Kind, Node::Prec Prec);
2504 Node *parseIntegerLiteral(StringView Lit);2506 Node *parseIntegerLiteral(StringView Lit);
2505 Node *parseExprPrimary();2507 Node *parseExprPrimary();
2506 template <class Float> Node *parseFloatingLiteral();2508 template <class Float> Node *parseFloatingLiteral();
2507 Node *parseFunctionParam();2509 Node *parseFunctionParam();
2508 Node *parseNewExpr();
2509 Node *parseConversionExpr();2510 Node *parseConversionExpr();
2510 Node *parseBracedExpr();2511 Node *parseBracedExpr();
2511 Node *parseFoldExpr();2512 Node *parseFoldExpr();
2512 Node *parsePointerToMemberConversionExpr();2513 Node *parsePointerToMemberConversionExpr(Node::Prec Prec);
2513 Node *parseSubobjectExpr();2514 Node *parseSubobjectExpr();
25142515
2515 /// Parse the <type> production.2516 /// Parse the <type> production.
...@@ -2557,17 +2558,80 @@ template <typename Derived, typename Alloc> struct AbstractManglingParser {...@@ -2557,17 +2558,80 @@ template <typename Derived, typename Alloc> struct AbstractManglingParser {
2557 Node *parseName(NameState *State = nullptr);2558 Node *parseName(NameState *State = nullptr);
2558 Node *parseLocalName(NameState *State);2559 Node *parseLocalName(NameState *State);
2559 Node *parseOperatorName(NameState *State);2560 Node *parseOperatorName(NameState *State);
2560 Node *parseUnqualifiedName(NameState *State);2561 bool parseModuleNameOpt(ModuleName *&Module);
2562 Node *parseUnqualifiedName(NameState *State, Node *Scope, ModuleName *Module);
2561 Node *parseUnnamedTypeName(NameState *State);2563 Node *parseUnnamedTypeName(NameState *State);
2562 Node *parseSourceName(NameState *State);2564 Node *parseSourceName(NameState *State);
2563 Node *parseUnscopedName(NameState *State);2565 Node *parseUnscopedName(NameState *State, bool *isSubstName);
2564 Node *parseNestedName(NameState *State);2566 Node *parseNestedName(NameState *State);
2565 Node *parseCtorDtorName(Node *&SoFar, NameState *State);2567 Node *parseCtorDtorName(Node *&SoFar, NameState *State);
25662568
2567 Node *parseAbiTags(Node *N);2569 Node *parseAbiTags(Node *N);
25682570
2571 struct OperatorInfo {
2572 enum OIKind : unsigned char {
2573 Prefix, // Prefix unary: @ expr
2574 Postfix, // Postfix unary: expr @
2575 Binary, // Binary: lhs @ rhs
2576 Array, // Array index: lhs [ rhs ]
2577 Member, // Member access: lhs @ rhs
2578 New, // New
2579 Del, // Delete
2580 Call, // Function call: expr (expr*)
2581 CCast, // C cast: (type)expr
2582 Conditional, // Conditional: expr ? expr : expr
2583 NameOnly, // Overload only, not allowed in expression.
2584 // Below do not have operator names
2585 NamedCast, // Named cast, @<type>(expr)
2586 OfIdOp, // alignof, sizeof, typeid
2587
2588 Unnameable = NamedCast,
2589 };
2590 char Enc[2]; // Encoding
2591 OIKind Kind; // Kind of operator
2592 bool Flag : 1; // Entry-specific flag
2593 Node::Prec Prec : 7; // Precedence
2594 const char *Name; // Spelling
2595
2596 public:
2597 constexpr OperatorInfo(const char (&E)[3], OIKind K, bool F, Node::Prec P,
2598 const char *N)
2599 : Enc{E[0], E[1]}, Kind{K}, Flag{F}, Prec{P}, Name{N} {}
2600
2601 public:
2602 bool operator<(const OperatorInfo &Other) const {
2603 return *this < Other.Enc;
2604 }
2605 bool operator<(const char *Peek) const {
2606 return Enc[0] < Peek[0] || (Enc[0] == Peek[0] && Enc[1] < Peek[1]);
2607 }
2608 bool operator==(const char *Peek) const {
2609 return Enc[0] == Peek[0] && Enc[1] == Peek[1];
2610 }
2611 bool operator!=(const char *Peek) const { return !this->operator==(Peek); }
2612
2613 public:
2614 StringView getSymbol() const {
2615 StringView Res = Name;
2616 if (Kind < Unnameable) {
2617 assert(Res.startsWith("operator") &&
2618 "operator name does not start with 'operator'");
2619 Res = Res.dropFront(sizeof("operator") - 1);
2620 Res.consumeFront(' ');
2621 }
2622 return Res;
2623 }
2624 StringView getName() const { return Name; }
2625 OIKind getKind() const { return Kind; }
2626 bool getFlag() const { return Flag; }
2627 Node::Prec getPrecedence() const { return Prec; }
2628 };
2629 static const OperatorInfo Ops[];
2630 static const size_t NumOps;
2631 const OperatorInfo *parseOperatorEncoding();
2632
2569 /// Parse the <unresolved-name> production.2633 /// Parse the <unresolved-name> production.
2570 Node *parseUnresolvedName();2634 Node *parseUnresolvedName(bool Global);
2571 Node *parseSimpleId();2635 Node *parseSimpleId();
2572 Node *parseBaseUnresolvedName();2636 Node *parseBaseUnresolvedName();
2573 Node *parseUnresolvedType();2637 Node *parseUnresolvedType();
...@@ -2588,26 +2652,16 @@ const char* parse_discriminator(const char* first, const char* last);...@@ -2588,26 +2652,16 @@ const char* parse_discriminator(const char* first, const char* last);
2588// ::= <substitution>2652// ::= <substitution>
2589template <typename Derived, typename Alloc>2653template <typename Derived, typename Alloc>
2590Node *AbstractManglingParser<Derived, Alloc>::parseName(NameState *State) {2654Node *AbstractManglingParser<Derived, Alloc>::parseName(NameState *State) {
2591 consumeIf('L'); // extension
2592
2593 if (look() == 'N')2655 if (look() == 'N')
2594 return getDerived().parseNestedName(State);2656 return getDerived().parseNestedName(State);
2595 if (look() == 'Z')2657 if (look() == 'Z')
2596 return getDerived().parseLocalName(State);2658 return getDerived().parseLocalName(State);
25972659
2598 Node *Result = nullptr;2660 Node *Result = nullptr;
2599 bool IsSubst = look() == 'S' && look(1) != 't';2661 bool IsSubst = false;
2600 if (IsSubst) {2662
2601 // A substitution must lead to:2663 Result = getDerived().parseUnscopedName(State, &IsSubst);
2602 // ::= <unscoped-template-name> <template-args>2664 if (!Result)
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);
2609 }
2610 if (Result == nullptr)
2611 return nullptr;2665 return nullptr;
26122666
2613 if (look() == 'I') {2667 if (look() == 'I') {
...@@ -2667,38 +2721,63 @@ Node *AbstractManglingParser<Derived, Alloc>::parseLocalName(NameState *State) {...@@ -2667,38 +2721,63 @@ Node *AbstractManglingParser<Derived, Alloc>::parseLocalName(NameState *State) {
26672721
2668// <unscoped-name> ::= <unqualified-name>2722// <unscoped-name> ::= <unqualified-name>
2669// ::= St <unqualified-name> # ::std::2723// ::= St <unqualified-name> # ::std::
2670// extension ::= StL<unqualified-name>2724// [*] extension
2671template <typename Derived, typename Alloc>2725template <typename Derived, typename Alloc>
2672Node *2726Node *
2673AbstractManglingParser<Derived, Alloc>::parseUnscopedName(NameState *State) {2727AbstractManglingParser<Derived, Alloc>::parseUnscopedName(NameState *State,
2674 bool IsStd = consumeIf("St");2728 bool *IsSubst) {
2675 if (IsStd)
2676 consumeIf('L');
26772729
2678 Node *Result = getDerived().parseUnqualifiedName(State);2730 Node *Std = nullptr;
2679 if (Result == nullptr)2731 if (consumeIf("St")) {
2680 return nullptr;2732 Std = make<NameType>("std");
2681 if (IsStd)2733 if (Std == nullptr)
2682 Result = make<StdQualifiedName>(Result);2734 return nullptr;
2735 }
26832736
2684 return Result;2737 Node *Res = nullptr;
2738 ModuleName *Module = nullptr;
2739 if (look() == 'S') {
2740 Node *S = getDerived().parseSubstitution();
2741 if (!S)
2742 return nullptr;
2743 if (S->getKind() == Node::KModuleName)
2744 Module = static_cast<ModuleName *>(S);
2745 else if (IsSubst && Std == nullptr) {
2746 Res = S;
2747 *IsSubst = true;
2748 } else {
2749 return nullptr;
2750 }
2751 }
2752
2753 if (Res == nullptr || Std != nullptr) {
2754 Res = getDerived().parseUnqualifiedName(State, Std, Module);
2755 }
2756
2757 return Res;
2685}2758}
26862759
2687// <unqualified-name> ::= <operator-name> [abi-tags]2760// <unqualified-name> ::= [<module-name>] L? <operator-name> [<abi-tags>]
2688// ::= <ctor-dtor-name>2761// ::= [<module-name>] <ctor-dtor-name> [<abi-tags>]
2689// ::= <source-name>2762// ::= [<module-name>] L? <source-name> [<abi-tags>]
2690// ::= <unnamed-type-name>2763// ::= [<module-name>] L? <unnamed-type-name> [<abi-tags>]
2691// ::= DC <source-name>+ E # structured binding declaration2764// # structured binding declaration
2765// ::= [<module-name>] L? DC <source-name>+ E
2692template <typename Derived, typename Alloc>2766template <typename Derived, typename Alloc>
2693Node *2767Node *AbstractManglingParser<Derived, Alloc>::parseUnqualifiedName(
2694AbstractManglingParser<Derived, Alloc>::parseUnqualifiedName(NameState *State) {2768 NameState *State, Node *Scope, ModuleName *Module) {
2695 // <ctor-dtor-name>s are special-cased in parseNestedName().2769 if (getDerived().parseModuleNameOpt(Module))
2770 return nullptr;
2771
2772 consumeIf('L');
2773
2696 Node *Result;2774 Node *Result;
2697 if (look() == 'U')2775 if (look() >= '1' && look() <= '9') {
2698 Result = getDerived().parseUnnamedTypeName(State);
2699 else if (look() >= '1' && look() <= '9')
2700 Result = getDerived().parseSourceName(State);2776 Result = getDerived().parseSourceName(State);
2701 else if (consumeIf("DC")) {2777 } else if (look() == 'U') {
2778 Result = getDerived().parseUnnamedTypeName(State);
2779 } else if (consumeIf("DC")) {
2780 // Structured binding
2702 size_t BindingsBegin = Names.size();2781 size_t BindingsBegin = Names.size();
2703 do {2782 do {
2704 Node *Binding = getDerived().parseSourceName(State);2783 Node *Binding = getDerived().parseSourceName(State);
...@@ -2707,13 +2786,46 @@ AbstractManglingParser<Derived, Alloc>::parseUnqualifiedName(NameState *State) {...@@ -2707,13 +2786,46 @@ AbstractManglingParser<Derived, Alloc>::parseUnqualifiedName(NameState *State) {
2707 Names.push_back(Binding);2786 Names.push_back(Binding);
2708 } while (!consumeIf('E'));2787 } while (!consumeIf('E'));
2709 Result = make<StructuredBindingName>(popTrailingNodeArray(BindingsBegin));2788 Result = make<StructuredBindingName>(popTrailingNodeArray(BindingsBegin));
2710 } else2789 } else if (look() == 'C' || look() == 'D') {
2790 // A <ctor-dtor-name>.
2791 if (Scope == nullptr || Module != nullptr)
2792 return nullptr;
2793 Result = getDerived().parseCtorDtorName(Scope, State);
2794 } else {
2711 Result = getDerived().parseOperatorName(State);2795 Result = getDerived().parseOperatorName(State);
2796 }
2797
2798 if (Result != nullptr && Module != nullptr)
2799 Result = make<ModuleEntity>(Module, Result);
2712 if (Result != nullptr)2800 if (Result != nullptr)
2713 Result = getDerived().parseAbiTags(Result);2801 Result = getDerived().parseAbiTags(Result);
2802 if (Result != nullptr && Scope != nullptr)
2803 Result = make<NestedName>(Scope, Result);
2804
2714 return Result;2805 return Result;
2715}2806}
27162807
2808// <module-name> ::= <module-subname>
2809// ::= <module-name> <module-subname>
2810// ::= <substitution> # passed in by caller
2811// <module-subname> ::= W <source-name>
2812// ::= W P <source-name>
2813template <typename Derived, typename Alloc>
2814bool AbstractManglingParser<Derived, Alloc>::parseModuleNameOpt(
2815 ModuleName *&Module) {
2816 while (consumeIf('W')) {
2817 bool IsPartition = consumeIf('P');
2818 Node *Sub = getDerived().parseSourceName(nullptr);
2819 if (!Sub)
2820 return true;
2821 Module =
2822 static_cast<ModuleName *>(make<ModuleName>(Module, Sub, IsPartition));
2823 Subs.push_back(Module);
2824 }
2825
2826 return false;
2827}
2828
2717// <unnamed-type-name> ::= Ut [<nonnegative number>] _2829// <unnamed-type-name> ::= Ut [<nonnegative number>] _
2718// ::= <closure-type-name>2830// ::= <closure-type-name>
2719//2831//
...@@ -2735,7 +2847,7 @@ AbstractManglingParser<Derived, Alloc>::parseUnnamedTypeName(NameState *State) {...@@ -2735,7 +2847,7 @@ AbstractManglingParser<Derived, Alloc>::parseUnnamedTypeName(NameState *State) {
2735 return make<UnnamedTypeName>(Count);2847 return make<UnnamedTypeName>(Count);
2736 }2848 }
2737 if (consumeIf("Ul")) {2849 if (consumeIf("Ul")) {
2738 SwapAndRestore<size_t> SwapParams(ParsingLambdaParamsAtLevel,2850 ScopedOverride<size_t> SwapParams(ParsingLambdaParamsAtLevel,
2739 TemplateParams.size());2851 TemplateParams.size());
2740 ScopedTemplateParamList LambdaTemplateParams(this);2852 ScopedTemplateParamList LambdaTemplateParams(this);
27412853
...@@ -2813,97 +2925,124 @@ Node *AbstractManglingParser<Derived, Alloc>::parseSourceName(NameState *) {...@@ -2813,97 +2925,124 @@ Node *AbstractManglingParser<Derived, Alloc>::parseSourceName(NameState *) {
2813 return make<NameType>(Name);2925 return make<NameType>(Name);
2814}2926}
28152927
2816// <operator-name> ::= aa # &&2928// Operator encodings
2817// ::= ad # & (unary)2929template <typename Derived, typename Alloc>
2818// ::= an # &2930const typename AbstractManglingParser<
2819// ::= aN # &=2931 Derived, Alloc>::OperatorInfo AbstractManglingParser<Derived,
2820// ::= aS # =2932 Alloc>::Ops[] = {
2821// ::= cl # ()2933 // Keep ordered by encoding
2822// ::= cm # ,2934 {"aN", OperatorInfo::Binary, false, Node::Prec::Assign, "operator&="},
2823// ::= co # ~2935 {"aS", OperatorInfo::Binary, false, Node::Prec::Assign, "operator="},
2824// ::= cv <type> # (cast)2936 {"aa", OperatorInfo::Binary, false, Node::Prec::AndIf, "operator&&"},
2825// ::= da # delete[]2937 {"ad", OperatorInfo::Prefix, false, Node::Prec::Unary, "operator&"},
2826// ::= de # * (unary)2938 {"an", OperatorInfo::Binary, false, Node::Prec::And, "operator&"},
2827// ::= dl # delete2939 {"at", OperatorInfo::OfIdOp, /*Type*/ true, Node::Prec::Unary, "alignof "},
2828// ::= dv # /2940 {"aw", OperatorInfo::NameOnly, false, Node::Prec::Primary,
2829// ::= dV # /=2941 "operator co_await"},
2830// ::= eo # ^2942 {"az", OperatorInfo::OfIdOp, /*Type*/ false, Node::Prec::Unary, "alignof "},
2831// ::= eO # ^=2943 {"cc", OperatorInfo::NamedCast, false, Node::Prec::Postfix, "const_cast"},
2832// ::= eq # ==2944 {"cl", OperatorInfo::Call, false, Node::Prec::Postfix, "operator()"},
2833// ::= ge # >=2945 {"cm", OperatorInfo::Binary, false, Node::Prec::Comma, "operator,"},
2834// ::= gt # >2946 {"co", OperatorInfo::Prefix, false, Node::Prec::Unary, "operator~"},
2835// ::= ix # []2947 {"cv", OperatorInfo::CCast, false, Node::Prec::Cast, "operator"}, // C Cast
2836// ::= le # <=2948 {"dV", OperatorInfo::Binary, false, Node::Prec::Assign, "operator/="},
2949 {"da", OperatorInfo::Del, /*Ary*/ true, Node::Prec::Unary,
2950 "operator delete[]"},
2951 {"dc", OperatorInfo::NamedCast, false, Node::Prec::Postfix, "dynamic_cast"},
2952 {"de", OperatorInfo::Prefix, false, Node::Prec::Unary, "operator*"},
2953 {"dl", OperatorInfo::Del, /*Ary*/ false, Node::Prec::Unary,
2954 "operator delete"},
2955 {"ds", OperatorInfo::Member, /*Named*/ false, Node::Prec::PtrMem,
2956 "operator.*"},
2957 {"dt", OperatorInfo::Member, /*Named*/ false, Node::Prec::Postfix,
2958 "operator."},
2959 {"dv", OperatorInfo::Binary, false, Node::Prec::Assign, "operator/"},
2960 {"eO", OperatorInfo::Binary, false, Node::Prec::Assign, "operator^="},
2961 {"eo", OperatorInfo::Binary, false, Node::Prec::Xor, "operator^"},
2962 {"eq", OperatorInfo::Binary, false, Node::Prec::Equality, "operator=="},
2963 {"ge", OperatorInfo::Binary, false, Node::Prec::Relational, "operator>="},
2964 {"gt", OperatorInfo::Binary, false, Node::Prec::Relational, "operator>"},
2965 {"ix", OperatorInfo::Array, false, Node::Prec::Postfix, "operator[]"},
2966 {"lS", OperatorInfo::Binary, false, Node::Prec::Assign, "operator<<="},
2967 {"le", OperatorInfo::Binary, false, Node::Prec::Relational, "operator<="},
2968 {"ls", OperatorInfo::Binary, false, Node::Prec::Shift, "operator<<"},
2969 {"lt", OperatorInfo::Binary, false, Node::Prec::Relational, "operator<"},
2970 {"mI", OperatorInfo::Binary, false, Node::Prec::Assign, "operator-="},
2971 {"mL", OperatorInfo::Binary, false, Node::Prec::Assign, "operator*="},
2972 {"mi", OperatorInfo::Binary, false, Node::Prec::Additive, "operator-"},
2973 {"ml", OperatorInfo::Binary, false, Node::Prec::Multiplicative,
2974 "operator*"},
2975 {"mm", OperatorInfo::Postfix, false, Node::Prec::Postfix, "operator--"},
2976 {"na", OperatorInfo::New, /*Ary*/ true, Node::Prec::Unary,
2977 "operator new[]"},
2978 {"ne", OperatorInfo::Binary, false, Node::Prec::Equality, "operator!="},
2979 {"ng", OperatorInfo::Prefix, false, Node::Prec::Unary, "operator-"},
2980 {"nt", OperatorInfo::Prefix, false, Node::Prec::Unary, "operator!"},
2981 {"nw", OperatorInfo::New, /*Ary*/ false, Node::Prec::Unary, "operator new"},
2982 {"oR", OperatorInfo::Binary, false, Node::Prec::Assign, "operator|="},
2983 {"oo", OperatorInfo::Binary, false, Node::Prec::OrIf, "operator||"},
2984 {"or", OperatorInfo::Binary, false, Node::Prec::Ior, "operator|"},
2985 {"pL", OperatorInfo::Binary, false, Node::Prec::Assign, "operator+="},
2986 {"pl", OperatorInfo::Binary, false, Node::Prec::Additive, "operator+"},
2987 {"pm", OperatorInfo::Member, /*Named*/ false, Node::Prec::PtrMem,
2988 "operator->*"},
2989 {"pp", OperatorInfo::Postfix, false, Node::Prec::Postfix, "operator++"},
2990 {"ps", OperatorInfo::Prefix, false, Node::Prec::Unary, "operator+"},
2991 {"pt", OperatorInfo::Member, /*Named*/ true, Node::Prec::Postfix,
2992 "operator->"},
2993 {"qu", OperatorInfo::Conditional, false, Node::Prec::Conditional,
2994 "operator?"},
2995 {"rM", OperatorInfo::Binary, false, Node::Prec::Assign, "operator%="},
2996 {"rS", OperatorInfo::Binary, false, Node::Prec::Assign, "operator>>="},
2997 {"rc", OperatorInfo::NamedCast, false, Node::Prec::Postfix,
2998 "reinterpret_cast"},
2999 {"rm", OperatorInfo::Binary, false, Node::Prec::Multiplicative,
3000 "operator%"},
3001 {"rs", OperatorInfo::Binary, false, Node::Prec::Shift, "operator>>"},
3002 {"sc", OperatorInfo::NamedCast, false, Node::Prec::Postfix, "static_cast"},
3003 {"ss", OperatorInfo::Binary, false, Node::Prec::Spaceship, "operator<=>"},
3004 {"st", OperatorInfo::OfIdOp, /*Type*/ true, Node::Prec::Unary, "sizeof "},
3005 {"sz", OperatorInfo::OfIdOp, /*Type*/ false, Node::Prec::Unary, "sizeof "},
3006 {"te", OperatorInfo::OfIdOp, /*Type*/ false, Node::Prec::Postfix,
3007 "typeid "},
3008 {"ti", OperatorInfo::OfIdOp, /*Type*/ true, Node::Prec::Postfix, "typeid "},
3009};
3010template <typename Derived, typename Alloc>
3011const size_t AbstractManglingParser<Derived, Alloc>::NumOps = sizeof(Ops) /
3012 sizeof(Ops[0]);
3013
3014// If the next 2 chars are an operator encoding, consume them and return their
3015// OperatorInfo. Otherwise return nullptr.
3016template <typename Derived, typename Alloc>
3017const typename AbstractManglingParser<Derived, Alloc>::OperatorInfo *
3018AbstractManglingParser<Derived, Alloc>::parseOperatorEncoding() {
3019 if (numLeft() < 2)
3020 return nullptr;
3021
3022 auto Op = std::lower_bound(
3023 &Ops[0], &Ops[NumOps], First,
3024 [](const OperatorInfo &Op_, const char *Enc_) { return Op_ < Enc_; });
3025 if (Op == &Ops[NumOps] || *Op != First)
3026 return nullptr;
3027
3028 First += 2;
3029 return Op;
3030}
3031
3032// <operator-name> ::= See parseOperatorEncoding()
2837// ::= li <source-name> # operator ""3033// ::= li <source-name> # operator ""
2838// ::= ls # <<3034// ::= v <digit> <source-name> # vendor extended operator
2839// ::= lS # <<=
2840// ::= lt # <
2841// ::= mi # -
2842// ::= mI # -=
2843// ::= ml # *
2844// ::= mL # *=
2845// ::= mm # -- (postfix in <expression> context)
2846// ::= na # new[]
2847// ::= ne # !=
2848// ::= ng # - (unary)
2849// ::= nt # !
2850// ::= nw # new
2851// ::= oo # ||
2852// ::= or # |
2853// ::= oR # |=
2854// ::= pm # ->*
2855// ::= pl # +
2856// ::= pL # +=
2857// ::= pp # ++ (postfix in <expression> context)
2858// ::= ps # + (unary)
2859// ::= pt # ->
2860// ::= qu # ?
2861// ::= rm # %
2862// ::= rM # %=
2863// ::= rs # >>
2864// ::= rS # >>=
2865// ::= ss # <=> C++2a
2866// ::= v <digit> <source-name> # vendor extended operator
2867template <typename Derived, typename Alloc>3035template <typename Derived, typename Alloc>
2868Node *3036Node *
2869AbstractManglingParser<Derived, Alloc>::parseOperatorName(NameState *State) {3037AbstractManglingParser<Derived, Alloc>::parseOperatorName(NameState *State) {
2870 switch (look()) {3038 if (const auto *Op = parseOperatorEncoding()) {
2871 case 'a':3039 if (Op->getKind() == OperatorInfo::CCast) {
2872 switch (look(1)) {3040 // ::= cv <type> # (cast)
2873 case 'a':3041 ScopedOverride<bool> SaveTemplate(TryToParseTemplateArgs, false);
2874 First += 2;
2875 return make<NameType>("operator&&");
2876 case 'd':
2877 case 'n':
2878 First += 2;
2879 return make<NameType>("operator&");
2880 case 'N':
2881 First += 2;
2882 return make<NameType>("operator&=");
2883 case 'S':
2884 First += 2;
2885 return make<NameType>("operator=");
2886 }
2887 return nullptr;
2888 case 'c':
2889 switch (look(1)) {
2890 case 'l':
2891 First += 2;
2892 return make<NameType>("operator()");
2893 case 'm':
2894 First += 2;
2895 return make<NameType>("operator,");
2896 case 'o':
2897 First += 2;
2898 return make<NameType>("operator~");
2899 // ::= cv <type> # (cast)
2900 case 'v': {
2901 First += 2;
2902 SwapAndRestore<bool> SaveTemplate(TryToParseTemplateArgs, false);
2903 // If we're parsing an encoding, State != nullptr and the conversion3042 // If we're parsing an encoding, State != nullptr and the conversion
2904 // operators' <type> could have a <template-param> that refers to some3043 // operators' <type> could have a <template-param> that refers to some
2905 // <template-arg>s further ahead in the mangled name.3044 // <template-arg>s further ahead in the mangled name.
2906 SwapAndRestore<bool> SavePermit(PermitForwardTemplateReferences,3045 ScopedOverride<bool> SavePermit(PermitForwardTemplateReferences,
2907 PermitForwardTemplateReferences ||3046 PermitForwardTemplateReferences ||
2908 State != nullptr);3047 State != nullptr);
2909 Node *Ty = getDerived().parseType();3048 Node *Ty = getDerived().parseType();
...@@ -2912,185 +3051,29 @@ AbstractManglingParser<Derived, Alloc>::parseOperatorName(NameState *State) {...@@ -2912,185 +3051,29 @@ AbstractManglingParser<Derived, Alloc>::parseOperatorName(NameState *State) {
2912 if (State) State->CtorDtorConversion = true;3051 if (State) State->CtorDtorConversion = true;
2913 return make<ConversionOperatorType>(Ty);3052 return make<ConversionOperatorType>(Ty);
2914 }3053 }
2915 }3054
2916 return nullptr;3055 if (Op->getKind() >= OperatorInfo::Unnameable)
2917 case 'd':3056 /* Not a nameable operator. */
2918 switch (look(1)) {3057 return nullptr;
2919 case 'a':3058 if (Op->getKind() == OperatorInfo::Member && !Op->getFlag())
2920 First += 2;3059 /* Not a nameable MemberExpr */
2921 return make<NameType>("operator delete[]");3060 return nullptr;
2922 case 'e':3061
2923 First += 2;3062 return make<NameType>(Op->getName());
2924 return make<NameType>("operator*");3063 }
2925 case 'l':3064
2926 First += 2;3065 if (consumeIf("li")) {
2927 return make<NameType>("operator delete");
2928 case 'v':
2929 First += 2;
2930 return make<NameType>("operator/");
2931 case 'V':
2932 First += 2;
2933 return make<NameType>("operator/=");
2934 }
2935 return nullptr;
2936 case 'e':
2937 switch (look(1)) {
2938 case 'o':
2939 First += 2;
2940 return make<NameType>("operator^");
2941 case 'O':
2942 First += 2;
2943 return make<NameType>("operator^=");
2944 case 'q':
2945 First += 2;
2946 return make<NameType>("operator==");
2947 }
2948 return nullptr;
2949 case 'g':
2950 switch (look(1)) {
2951 case 'e':
2952 First += 2;
2953 return make<NameType>("operator>=");
2954 case 't':
2955 First += 2;
2956 return make<NameType>("operator>");
2957 }
2958 return nullptr;
2959 case 'i':
2960 if (look(1) == 'x') {
2961 First += 2;
2962 return make<NameType>("operator[]");
2963 }
2964 return nullptr;
2965 case 'l':
2966 switch (look(1)) {
2967 case 'e':
2968 First += 2;
2969 return make<NameType>("operator<=");
2970 // ::= li <source-name> # operator ""3066 // ::= li <source-name> # operator ""
2971 case 'i': {3067 Node *SN = getDerived().parseSourceName(State);
2972 First += 2;3068 if (SN == nullptr)
2973 Node *SN = getDerived().parseSourceName(State);3069 return nullptr;
2974 if (SN == nullptr)3070 return make<LiteralOperator>(SN);
2975 return nullptr;3071 }
2976 return make<LiteralOperator>(SN);3072
2977 }3073 if (consumeIf('v')) {
2978 case 's':3074 // ::= v <digit> <source-name> # vendor extended operator
2979 First += 2;3075 if (look() >= '0' && look() <= '9') {
2980 return make<NameType>("operator<<");3076 First++;
2981 case 'S':
2982 First += 2;
2983 return make<NameType>("operator<<=");
2984 case 't':
2985 First += 2;
2986 return make<NameType>("operator<");
2987 }
2988 return nullptr;
2989 case 'm':
2990 switch (look(1)) {
2991 case 'i':
2992 First += 2;
2993 return make<NameType>("operator-");
2994 case 'I':
2995 First += 2;
2996 return make<NameType>("operator-=");
2997 case 'l':
2998 First += 2;
2999 return make<NameType>("operator*");
3000 case 'L':
3001 First += 2;
3002 return make<NameType>("operator*=");
3003 case 'm':
3004 First += 2;
3005 return make<NameType>("operator--");
3006 }
3007 return nullptr;
3008 case 'n':
3009 switch (look(1)) {
3010 case 'a':
3011 First += 2;
3012 return make<NameType>("operator new[]");
3013 case 'e':
3014 First += 2;
3015 return make<NameType>("operator!=");
3016 case 'g':
3017 First += 2;
3018 return make<NameType>("operator-");
3019 case 't':
3020 First += 2;
3021 return make<NameType>("operator!");
3022 case 'w':
3023 First += 2;
3024 return make<NameType>("operator new");
3025 }
3026 return nullptr;
3027 case 'o':
3028 switch (look(1)) {
3029 case 'o':
3030 First += 2;
3031 return make<NameType>("operator||");
3032 case 'r':
3033 First += 2;
3034 return make<NameType>("operator|");
3035 case 'R':
3036 First += 2;
3037 return make<NameType>("operator|=");
3038 }
3039 return nullptr;
3040 case 'p':
3041 switch (look(1)) {
3042 case 'm':
3043 First += 2;
3044 return make<NameType>("operator->*");
3045 case 'l':
3046 First += 2;
3047 return make<NameType>("operator+");
3048 case 'L':
3049 First += 2;
3050 return make<NameType>("operator+=");
3051 case 'p':
3052 First += 2;
3053 return make<NameType>("operator++");
3054 case 's':
3055 First += 2;
3056 return make<NameType>("operator+");
3057 case 't':
3058 First += 2;
3059 return make<NameType>("operator->");
3060 }
3061 return nullptr;
3062 case 'q':
3063 if (look(1) == 'u') {
3064 First += 2;
3065 return make<NameType>("operator?");
3066 }
3067 return nullptr;
3068 case 'r':
3069 switch (look(1)) {
3070 case 'm':
3071 First += 2;
3072 return make<NameType>("operator%");
3073 case 'M':
3074 First += 2;
3075 return make<NameType>("operator%=");
3076 case 's':
3077 First += 2;
3078 return make<NameType>("operator>>");
3079 case 'S':
3080 First += 2;
3081 return make<NameType>("operator>>=");
3082 }
3083 return nullptr;
3084 case 's':
3085 if (look(1) == 's') {
3086 First += 2;
3087 return make<NameType>("operator<=>");
3088 }
3089 return nullptr;
3090 // ::= v <digit> <source-name> # vendor extended operator
3091 case 'v':
3092 if (std::isdigit(look(1))) {
3093 First += 2;
3094 Node *SN = getDerived().parseSourceName(State);3077 Node *SN = getDerived().parseSourceName(State);
3095 if (SN == nullptr)3078 if (SN == nullptr)
3096 return nullptr;3079 return nullptr;
...@@ -3098,6 +3081,7 @@ AbstractManglingParser<Derived, Alloc>::parseOperatorName(NameState *State) {...@@ -3098,6 +3081,7 @@ AbstractManglingParser<Derived, Alloc>::parseOperatorName(NameState *State) {
3098 }3081 }
3099 return nullptr;3082 return nullptr;
3100 }3083 }
3084
3101 return nullptr;3085 return nullptr;
3102}3086}
31033087
...@@ -3116,19 +3100,11 @@ Node *...@@ -3116,19 +3100,11 @@ Node *
3116AbstractManglingParser<Derived, Alloc>::parseCtorDtorName(Node *&SoFar,3100AbstractManglingParser<Derived, Alloc>::parseCtorDtorName(Node *&SoFar,
3117 NameState *State) {3101 NameState *State) {
3118 if (SoFar->getKind() == Node::KSpecialSubstitution) {3102 if (SoFar->getKind() == Node::KSpecialSubstitution) {
3119 auto SSK = static_cast<SpecialSubstitution *>(SoFar)->SSK;3103 // Expand the special substitution.
3120 switch (SSK) {3104 SoFar = make<ExpandedSpecialSubstitution>(
3121 case SpecialSubKind::string:3105 static_cast<SpecialSubstitution *>(SoFar));
3122 case SpecialSubKind::istream:3106 if (!SoFar)
3123 case SpecialSubKind::ostream:3107 return nullptr;
3124 case SpecialSubKind::iostream:
3125 SoFar = make<ExpandedSpecialSubstitution>(SSK);
3126 if (!SoFar)
3127 return nullptr;
3128 break;
3129 default:
3130 break;
3131 }
3132 }3108 }
31333109
3134 if (consumeIf('C')) {3110 if (consumeIf('C')) {
...@@ -3157,8 +3133,10 @@ AbstractManglingParser<Derived, Alloc>::parseCtorDtorName(Node *&SoFar,...@@ -3157,8 +3133,10 @@ AbstractManglingParser<Derived, Alloc>::parseCtorDtorName(Node *&SoFar,
3157 return nullptr;3133 return nullptr;
3158}3134}
31593135
3160// <nested-name> ::= N [<CV-Qualifiers>] [<ref-qualifier>] <prefix> <unqualified-name> E3136// <nested-name> ::= N [<CV-Qualifiers>] [<ref-qualifier>] <prefix>
3161// ::= N [<CV-Qualifiers>] [<ref-qualifier>] <template-prefix> <template-args> E3137// <unqualified-name> E
3138// ::= N [<CV-Qualifiers>] [<ref-qualifier>] <template-prefix>
3139// <template-args> E
3162//3140//
3163// <prefix> ::= <prefix> <unqualified-name>3141// <prefix> ::= <prefix> <unqualified-name>
3164// ::= <template-prefix> <template-args>3142// ::= <template-prefix> <template-args>
...@@ -3167,7 +3145,7 @@ AbstractManglingParser<Derived, Alloc>::parseCtorDtorName(Node *&SoFar,...@@ -3167,7 +3145,7 @@ AbstractManglingParser<Derived, Alloc>::parseCtorDtorName(Node *&SoFar,
3167// ::= # empty3145// ::= # empty
3168// ::= <substitution>3146// ::= <substitution>
3169// ::= <prefix> <data-member-prefix>3147// ::= <prefix> <data-member-prefix>
3170// extension ::= L3148// [*] extension
3171//3149//
3172// <data-member-prefix> := <member source-name> [<template-args>] M3150// <data-member-prefix> := <member source-name> [<template-args>] M
3173//3151//
...@@ -3187,90 +3165,76 @@ AbstractManglingParser<Derived, Alloc>::parseNestedName(NameState *State) {...@@ -3187,90 +3165,76 @@ AbstractManglingParser<Derived, Alloc>::parseNestedName(NameState *State) {
3187 if (State) State->ReferenceQualifier = FrefQualRValue;3165 if (State) State->ReferenceQualifier = FrefQualRValue;
3188 } else if (consumeIf('R')) {3166 } else if (consumeIf('R')) {
3189 if (State) State->ReferenceQualifier = FrefQualLValue;3167 if (State) State->ReferenceQualifier = FrefQualLValue;
3190 } else3168 } else {
3191 if (State) State->ReferenceQualifier = FrefQualNone;3169 if (State) State->ReferenceQualifier = FrefQualNone;
3192
3193 Node *SoFar = nullptr;
3194 auto PushComponent = [&](Node *Comp) {
3195 if (!Comp) return false;
3196 if (SoFar) SoFar = make<NestedName>(SoFar, Comp);
3197 else SoFar = Comp;
3198 if (State) State->EndsWithTemplateArgs = false;
3199 return SoFar != nullptr;
3200 };
3201
3202 if (consumeIf("St")) {
3203 SoFar = make<NameType>("std");
3204 if (!SoFar)
3205 return nullptr;
3206 }3170 }
32073171
3172 Node *SoFar = nullptr;
3208 while (!consumeIf('E')) {3173 while (!consumeIf('E')) {
3209 consumeIf('L'); // extension3174 if (State)
32103175 // Only set end-with-template on the case that does that.
3211 // <data-member-prefix> := <member source-name> [<template-args>] M3176 State->EndsWithTemplateArgs = false;
3212 if (consumeIf('M')) {
3213 if (SoFar == nullptr)
3214 return nullptr;
3215 continue;
3216 }
32173177
3218 // ::= <template-param>
3219 if (look() == 'T') {3178 if (look() == 'T') {
3220 if (!PushComponent(getDerived().parseTemplateParam()))3179 // ::= <template-param>
3221 return nullptr;3180 if (SoFar != nullptr)
3222 Subs.push_back(SoFar);3181 return nullptr; // Cannot have a prefix.
3223 continue;3182 SoFar = getDerived().parseTemplateParam();
3224 }3183 } else if (look() == 'I') {
32253184 // ::= <template-prefix> <template-args>
3226 // ::= <template-prefix> <template-args>3185 if (SoFar == nullptr)
3227 if (look() == 'I') {3186 return nullptr; // Must have a prefix.
3228 Node *TA = getDerived().parseTemplateArgs(State != nullptr);3187 Node *TA = getDerived().parseTemplateArgs(State != nullptr);
3229 if (TA == nullptr || SoFar == nullptr)3188 if (TA == nullptr)
3230 return nullptr;
3231 SoFar = make<NameWithTemplateArgs>(SoFar, TA);
3232 if (!SoFar)
3233 return nullptr;
3234 if (State) State->EndsWithTemplateArgs = true;
3235 Subs.push_back(SoFar);
3236 continue;
3237 }
3238
3239 // ::= <decltype>
3240 if (look() == 'D' && (look(1) == 't' || look(1) == 'T')) {
3241 if (!PushComponent(getDerived().parseDecltype()))
3242 return nullptr;3189 return nullptr;
3243 Subs.push_back(SoFar);3190 if (SoFar->getKind() == Node::KNameWithTemplateArgs)
3244 continue;3191 // Semantically <template-args> <template-args> cannot be generated by a
3245 }3192 // C++ entity. There will always be [something like] a name between
32463193 // them.
3247 // ::= <substitution>
3248 if (look() == 'S' && look(1) != 't') {
3249 Node *S = getDerived().parseSubstitution();
3250 if (!PushComponent(S))
3251 return nullptr;3194 return nullptr;
3252 if (SoFar != S)3195 if (State)
3253 Subs.push_back(S);3196 State->EndsWithTemplateArgs = true;
3254 continue;3197 SoFar = make<NameWithTemplateArgs>(SoFar, TA);
3255 }3198 } else if (look() == 'D' && (look(1) == 't' || look(1) == 'T')) {
3199 // ::= <decltype>
3200 if (SoFar != nullptr)
3201 return nullptr; // Cannot have a prefix.
3202 SoFar = getDerived().parseDecltype();
3203 } else {
3204 ModuleName *Module = nullptr;
3205
3206 if (look() == 'S') {
3207 // ::= <substitution>
3208 Node *S = nullptr;
3209 if (look(1) == 't') {
3210 First += 2;
3211 S = make<NameType>("std");
3212 } else {
3213 S = getDerived().parseSubstitution();
3214 }
3215 if (!S)
3216 return nullptr;
3217 if (S->getKind() == Node::KModuleName) {
3218 Module = static_cast<ModuleName *>(S);
3219 } else if (SoFar != nullptr) {
3220 return nullptr; // Cannot have a prefix.
3221 } else {
3222 SoFar = S;
3223 continue; // Do not push a new substitution.
3224 }
3225 }
32563226
3257 // Parse an <unqualified-name> thats actually a <ctor-dtor-name>.3227 // ::= [<prefix>] <unqualified-name>
3258 if (look() == 'C' || (look() == 'D' && look(1) != 'C')) {3228 SoFar = getDerived().parseUnqualifiedName(State, SoFar, Module);
3259 if (SoFar == nullptr)
3260 return nullptr;
3261 if (!PushComponent(getDerived().parseCtorDtorName(SoFar, State)))
3262 return nullptr;
3263 SoFar = getDerived().parseAbiTags(SoFar);
3264 if (SoFar == nullptr)
3265 return nullptr;
3266 Subs.push_back(SoFar);
3267 continue;
3268 }3229 }
32693230
3270 // ::= <prefix> <unqualified-name>3231 if (SoFar == nullptr)
3271 if (!PushComponent(getDerived().parseUnqualifiedName(State)))
3272 return nullptr;3232 return nullptr;
3273 Subs.push_back(SoFar);3233 Subs.push_back(SoFar);
3234
3235 // No longer used.
3236 // <data-member-prefix> := <member source-name> [<template-args>] M
3237 consumeIf('M');
3274 }3238 }
32753239
3276 if (SoFar == nullptr || Subs.empty())3240 if (SoFar == nullptr || Subs.empty())
...@@ -3365,6 +3329,7 @@ Node *AbstractManglingParser<Derived, Alloc>::parseBaseUnresolvedName() {...@@ -3365,6 +3329,7 @@ Node *AbstractManglingParser<Derived, Alloc>::parseBaseUnresolvedName() {
3365// ::= [gs] <base-unresolved-name> # x or (with "gs") ::x3329// ::= [gs] <base-unresolved-name> # x or (with "gs") ::x
3366// ::= [gs] sr <unresolved-qualifier-level>+ E <base-unresolved-name>3330// ::= [gs] sr <unresolved-qualifier-level>+ E <base-unresolved-name>
3367// # A::x, N::y, A<T>::z; "gs" means leading "::"3331// # A::x, N::y, A<T>::z; "gs" means leading "::"
3332// [gs] has been parsed by caller.
3368// ::= sr <unresolved-type> <base-unresolved-name> # T::x / decltype(p)::x3333// ::= sr <unresolved-type> <base-unresolved-name> # T::x / decltype(p)::x
3369// extension ::= sr <unresolved-type> <template-args> <base-unresolved-name>3334// extension ::= sr <unresolved-type> <template-args> <base-unresolved-name>
3370// # T::N::x /decltype(p)::N::x3335// # T::N::x /decltype(p)::N::x
...@@ -3372,7 +3337,7 @@ Node *AbstractManglingParser<Derived, Alloc>::parseBaseUnresolvedName() {...@@ -3372,7 +3337,7 @@ Node *AbstractManglingParser<Derived, Alloc>::parseBaseUnresolvedName() {
3372//3337//
3373// <unresolved-qualifier-level> ::= <simple-id>3338// <unresolved-qualifier-level> ::= <simple-id>
3374template <typename Derived, typename Alloc>3339template <typename Derived, typename Alloc>
3375Node *AbstractManglingParser<Derived, Alloc>::parseUnresolvedName() {3340Node *AbstractManglingParser<Derived, Alloc>::parseUnresolvedName(bool Global) {
3376 Node *SoFar = nullptr;3341 Node *SoFar = nullptr;
33773342
3378 // srN <unresolved-type> [<template-args>] <unresolved-qualifier-level>* E <base-unresolved-name>3343 // srN <unresolved-type> [<template-args>] <unresolved-qualifier-level>* E <base-unresolved-name>
...@@ -3406,8 +3371,6 @@ Node *AbstractManglingParser<Derived, Alloc>::parseUnresolvedName() {...@@ -3406,8 +3371,6 @@ Node *AbstractManglingParser<Derived, Alloc>::parseUnresolvedName() {
3406 return make<QualifiedName>(SoFar, Base);3371 return make<QualifiedName>(SoFar, Base);
3407 }3372 }
34083373
3409 bool Global = consumeIf("gs");
3410
3411 // [gs] <base-unresolved-name> # x or (with "gs") ::x3374 // [gs] <base-unresolved-name> # x or (with "gs") ::x
3412 if (!consumeIf("sr")) {3375 if (!consumeIf("sr")) {
3413 SoFar = getDerived().parseBaseUnresolvedName();3376 SoFar = getDerived().parseBaseUnresolvedName();
...@@ -3637,7 +3600,7 @@ Node *AbstractManglingParser<Derived, Alloc>::parseDecltype() {...@@ -3637,7 +3600,7 @@ Node *AbstractManglingParser<Derived, Alloc>::parseDecltype() {
3637 return nullptr;3600 return nullptr;
3638 if (!consumeIf('E'))3601 if (!consumeIf('E'))
3639 return nullptr;3602 return nullptr;
3640 return make<EnclosingExpr>("decltype(", E, ")");3603 return make<EnclosingExpr>("decltype", E);
3641}3604}
36423605
3643// <array-type> ::= A <positive dimension number> _ <element type>3606// <array-type> ::= A <positive dimension number> _ <element type>
...@@ -3723,8 +3686,8 @@ Node *AbstractManglingParser<Derived, Alloc>::parseQualifiedType() {...@@ -3723,8 +3686,8 @@ Node *AbstractManglingParser<Derived, Alloc>::parseQualifiedType() {
3723 StringView ProtoSourceName = Qual.dropFront(std::strlen("objcproto"));3686 StringView ProtoSourceName = Qual.dropFront(std::strlen("objcproto"));
3724 StringView Proto;3687 StringView Proto;
3725 {3688 {
3726 SwapAndRestore<const char *> SaveFirst(First, ProtoSourceName.begin()),3689 ScopedOverride<const char *> SaveFirst(First, ProtoSourceName.begin()),
3727 SaveLast(Last, ProtoSourceName.end());3690 SaveLast(Last, ProtoSourceName.end());
3728 Proto = parseBareSourceName();3691 Proto = parseBareSourceName();
3729 }3692 }
3730 if (Proto.empty())3693 if (Proto.empty())
...@@ -3929,6 +3892,22 @@ Node *AbstractManglingParser<Derived, Alloc>::parseType() {...@@ -3929,6 +3892,22 @@ Node *AbstractManglingParser<Derived, Alloc>::parseType() {
3929 return nullptr;3892 return nullptr;
3930 return make<BinaryFPType>(DimensionNumber);3893 return make<BinaryFPType>(DimensionNumber);
3931 }3894 }
3895 // ::= DB <number> _ # C23 signed _BitInt(N)
3896 // ::= DB <instantiation-dependent expression> _ # C23 signed _BitInt(N)
3897 // ::= DU <number> _ # C23 unsigned _BitInt(N)
3898 // ::= DU <instantiation-dependent expression> _ # C23 unsigned _BitInt(N)
3899 case 'B':
3900 case 'U': {
3901 bool Signed = look(1) == 'B';
3902 First += 2;
3903 Node *Size = std::isdigit(look()) ? make<NameType>(parseNumber())
3904 : getDerived().parseExpr();
3905 if (!Size)
3906 return nullptr;
3907 if (!consumeIf('_'))
3908 return nullptr;
3909 return make<BitIntType>(Size, Signed);
3910 }
3932 // ::= Di # char32_t3911 // ::= Di # char32_t
3933 case 'i':3912 case 'i':
3934 First += 2;3913 First += 2;
...@@ -4077,8 +4056,9 @@ Node *AbstractManglingParser<Derived, Alloc>::parseType() {...@@ -4077,8 +4056,9 @@ Node *AbstractManglingParser<Derived, Alloc>::parseType() {
4077 // ::= <substitution> # See Compression below4056 // ::= <substitution> # See Compression below
4078 case 'S': {4057 case 'S': {
4079 if (look(1) != 't') {4058 if (look(1) != 't') {
4080 Result = getDerived().parseSubstitution();4059 bool IsSubst = false;
4081 if (Result == nullptr)4060 Result = getDerived().parseUnscopedName(nullptr, &IsSubst);
4061 if (!Result)
4082 return nullptr;4062 return nullptr;
40834063
4084 // Sub could be either of:4064 // Sub could be either of:
...@@ -4091,12 +4071,14 @@ Node *AbstractManglingParser<Derived, Alloc>::parseType() {...@@ -4091,12 +4071,14 @@ Node *AbstractManglingParser<Derived, Alloc>::parseType() {
4091 // If this is followed by some <template-args>, and we're permitted to4071 // If this is followed by some <template-args>, and we're permitted to
4092 // parse them, take the second production.4072 // parse them, take the second production.
40934073
4094 if (TryToParseTemplateArgs && look() == 'I') {4074 if (look() == 'I' && (!IsSubst || TryToParseTemplateArgs)) {
4075 if (!IsSubst)
4076 Subs.push_back(Result);
4095 Node *TA = getDerived().parseTemplateArgs();4077 Node *TA = getDerived().parseTemplateArgs();
4096 if (TA == nullptr)4078 if (TA == nullptr)
4097 return nullptr;4079 return nullptr;
4098 Result = make<NameWithTemplateArgs>(Result, TA);4080 Result = make<NameWithTemplateArgs>(Result, TA);
4099 } else {4081 } else if (IsSubst) {
4100 // If all we parsed was a substitution, don't re-insert into the4082 // If all we parsed was a substitution, don't re-insert into the
4101 // substitution table.4083 // substitution table.
4102 return Result;4084 return Result;
...@@ -4121,22 +4103,24 @@ Node *AbstractManglingParser<Derived, Alloc>::parseType() {...@@ -4121,22 +4103,24 @@ Node *AbstractManglingParser<Derived, Alloc>::parseType() {
4121}4103}
41224104
4123template <typename Derived, typename Alloc>4105template <typename Derived, typename Alloc>
4124Node *AbstractManglingParser<Derived, Alloc>::parsePrefixExpr(StringView Kind) {4106Node *AbstractManglingParser<Derived, Alloc>::parsePrefixExpr(StringView Kind,
4107 Node::Prec Prec) {
4125 Node *E = getDerived().parseExpr();4108 Node *E = getDerived().parseExpr();
4126 if (E == nullptr)4109 if (E == nullptr)
4127 return nullptr;4110 return nullptr;
4128 return make<PrefixExpr>(Kind, E);4111 return make<PrefixExpr>(Kind, E, Prec);
4129}4112}
41304113
4131template <typename Derived, typename Alloc>4114template <typename Derived, typename Alloc>
4132Node *AbstractManglingParser<Derived, Alloc>::parseBinaryExpr(StringView Kind) {4115Node *AbstractManglingParser<Derived, Alloc>::parseBinaryExpr(StringView Kind,
4116 Node::Prec Prec) {
4133 Node *LHS = getDerived().parseExpr();4117 Node *LHS = getDerived().parseExpr();
4134 if (LHS == nullptr)4118 if (LHS == nullptr)
4135 return nullptr;4119 return nullptr;
4136 Node *RHS = getDerived().parseExpr();4120 Node *RHS = getDerived().parseExpr();
4137 if (RHS == nullptr)4121 if (RHS == nullptr)
4138 return nullptr;4122 return nullptr;
4139 return make<BinaryExpr>(LHS, Kind, RHS);4123 return make<BinaryExpr>(LHS, Kind, RHS, Prec);
4140}4124}
41414125
4142template <typename Derived, typename Alloc>4126template <typename Derived, typename Alloc>
...@@ -4191,43 +4175,6 @@ Node *AbstractManglingParser<Derived, Alloc>::parseFunctionParam() {...@@ -4191,43 +4175,6 @@ Node *AbstractManglingParser<Derived, Alloc>::parseFunctionParam() {
4191 return nullptr;4175 return nullptr;
4192}4176}
41934177
4194// [gs] nw <expression>* _ <type> E # new (expr-list) type
4195// [gs] nw <expression>* _ <type> <initializer> # new (expr-list) type (init)
4196// [gs] na <expression>* _ <type> E # new[] (expr-list) type
4197// [gs] na <expression>* _ <type> <initializer> # new[] (expr-list) type (init)
4198// <initializer> ::= pi <expression>* E # parenthesized initialization
4199template <typename Derived, typename Alloc>
4200Node *AbstractManglingParser<Derived, Alloc>::parseNewExpr() {
4201 bool Global = consumeIf("gs");
4202 bool IsArray = look(1) == 'a';
4203 if (!consumeIf("nw") && !consumeIf("na"))
4204 return nullptr;
4205 size_t Exprs = Names.size();
4206 while (!consumeIf('_')) {
4207 Node *Ex = getDerived().parseExpr();
4208 if (Ex == nullptr)
4209 return nullptr;
4210 Names.push_back(Ex);
4211 }
4212 NodeArray ExprList = popTrailingNodeArray(Exprs);
4213 Node *Ty = getDerived().parseType();
4214 if (Ty == nullptr)
4215 return Ty;
4216 if (consumeIf("pi")) {
4217 size_t InitsBegin = Names.size();
4218 while (!consumeIf('E')) {
4219 Node *Init = getDerived().parseExpr();
4220 if (Init == nullptr)
4221 return Init;
4222 Names.push_back(Init);
4223 }
4224 NodeArray Inits = popTrailingNodeArray(InitsBegin);
4225 return make<NewExpr>(ExprList, Ty, Inits, Global, IsArray);
4226 } else if (!consumeIf('E'))
4227 return nullptr;
4228 return make<NewExpr>(ExprList, Ty, NodeArray(), Global, IsArray);
4229}
4230
4231// cv <type> <expression> # conversion with one argument4178// cv <type> <expression> # conversion with one argument
4232// cv <type> _ <expression>* E # conversion with a different number of arguments4179// cv <type> _ <expression>* E # conversion with a different number of arguments
4233template <typename Derived, typename Alloc>4180template <typename Derived, typename Alloc>
...@@ -4236,7 +4183,7 @@ Node *AbstractManglingParser<Derived, Alloc>::parseConversionExpr() {...@@ -4236,7 +4183,7 @@ Node *AbstractManglingParser<Derived, Alloc>::parseConversionExpr() {
4236 return nullptr;4183 return nullptr;
4237 Node *Ty;4184 Node *Ty;
4238 {4185 {
4239 SwapAndRestore<bool> SaveTemp(TryToParseTemplateArgs, false);4186 ScopedOverride<bool> SaveTemp(TryToParseTemplateArgs, false);
4240 Ty = getDerived().parseType();4187 Ty = getDerived().parseType();
4241 }4188 }
42424189
...@@ -4353,7 +4300,7 @@ Node *AbstractManglingParser<Derived, Alloc>::parseExprPrimary() {...@@ -4353,7 +4300,7 @@ Node *AbstractManglingParser<Derived, Alloc>::parseExprPrimary() {
4353 return nullptr;4300 return nullptr;
4354 }4301 }
4355 case 'D':4302 case 'D':
4356 if (consumeIf("DnE"))4303 if (consumeIf("Dn") && (consumeIf('0'), consumeIf('E')))
4357 return make<NameType>("nullptr");4304 return make<NameType>("nullptr");
4358 return nullptr;4305 return nullptr;
4359 case 'T':4306 case 'T':
...@@ -4440,55 +4387,38 @@ Node *AbstractManglingParser<Derived, Alloc>::parseFoldExpr() {...@@ -4440,55 +4387,38 @@ Node *AbstractManglingParser<Derived, Alloc>::parseFoldExpr() {
4440 if (!consumeIf('f'))4387 if (!consumeIf('f'))
4441 return nullptr;4388 return nullptr;
44424389
4443 char FoldKind = look();4390 bool IsLeftFold = false, HasInitializer = false;
4444 bool IsLeftFold, HasInitializer;4391 switch (look()) {
4445 HasInitializer = FoldKind == 'L' || FoldKind == 'R';4392 default:
4446 if (FoldKind == 'l' || FoldKind == 'L')
4447 IsLeftFold = true;
4448 else if (FoldKind == 'r' || FoldKind == 'R')
4449 IsLeftFold = false;
4450 else
4451 return nullptr;4393 return nullptr;
4394 case 'L':
4395 IsLeftFold = true;
4396 HasInitializer = true;
4397 break;
4398 case 'R':
4399 HasInitializer = true;
4400 break;
4401 case 'l':
4402 IsLeftFold = true;
4403 break;
4404 case 'r':
4405 break;
4406 }
4452 ++First;4407 ++First;
44534408
4454 // FIXME: This map is duplicated in parseOperatorName and parseExpr.4409 const auto *Op = parseOperatorEncoding();
4455 StringView OperatorName;4410 if (!Op)
4456 if (consumeIf("aa")) OperatorName = "&&";4411 return nullptr;
4457 else if (consumeIf("an")) OperatorName = "&";4412 if (!(Op->getKind() == OperatorInfo::Binary
4458 else if (consumeIf("aN")) OperatorName = "&=";4413 || (Op->getKind() == OperatorInfo::Member
4459 else if (consumeIf("aS")) OperatorName = "=";4414 && Op->getName().back() == '*')))
4460 else if (consumeIf("cm")) OperatorName = ",";4415 return nullptr;
4461 else if (consumeIf("ds")) OperatorName = ".*";4416
4462 else if (consumeIf("dv")) OperatorName = "/";4417 Node *Pack = getDerived().parseExpr();
4463 else if (consumeIf("dV")) OperatorName = "/=";
4464 else if (consumeIf("eo")) OperatorName = "^";
4465 else if (consumeIf("eO")) OperatorName = "^=";
4466 else if (consumeIf("eq")) OperatorName = "==";
4467 else if (consumeIf("ge")) OperatorName = ">=";
4468 else if (consumeIf("gt")) OperatorName = ">";
4469 else if (consumeIf("le")) OperatorName = "<=";
4470 else if (consumeIf("ls")) OperatorName = "<<";
4471 else if (consumeIf("lS")) OperatorName = "<<=";
4472 else if (consumeIf("lt")) OperatorName = "<";
4473 else if (consumeIf("mi")) OperatorName = "-";
4474 else if (consumeIf("mI")) OperatorName = "-=";
4475 else if (consumeIf("ml")) OperatorName = "*";
4476 else if (consumeIf("mL")) OperatorName = "*=";
4477 else if (consumeIf("ne")) OperatorName = "!=";
4478 else if (consumeIf("oo")) OperatorName = "||";
4479 else if (consumeIf("or")) OperatorName = "|";
4480 else if (consumeIf("oR")) OperatorName = "|=";
4481 else if (consumeIf("pl")) OperatorName = "+";
4482 else if (consumeIf("pL")) OperatorName = "+=";
4483 else if (consumeIf("rm")) OperatorName = "%";
4484 else if (consumeIf("rM")) OperatorName = "%=";
4485 else if (consumeIf("rs")) OperatorName = ">>";
4486 else if (consumeIf("rS")) OperatorName = ">>=";
4487 else return nullptr;
4488
4489 Node *Pack = getDerived().parseExpr(), *Init = nullptr;
4490 if (Pack == nullptr)4418 if (Pack == nullptr)
4491 return nullptr;4419 return nullptr;
4420
4421 Node *Init = nullptr;
4492 if (HasInitializer) {4422 if (HasInitializer) {
4493 Init = getDerived().parseExpr();4423 Init = getDerived().parseExpr();
4494 if (Init == nullptr)4424 if (Init == nullptr)
...@@ -4498,14 +4428,16 @@ Node *AbstractManglingParser<Derived, Alloc>::parseFoldExpr() {...@@ -4498,14 +4428,16 @@ Node *AbstractManglingParser<Derived, Alloc>::parseFoldExpr() {
4498 if (IsLeftFold && Init)4428 if (IsLeftFold && Init)
4499 std::swap(Pack, Init);4429 std::swap(Pack, Init);
45004430
4501 return make<FoldExpr>(IsLeftFold, OperatorName, Pack, Init);4431 return make<FoldExpr>(IsLeftFold, Op->getSymbol(), Pack, Init);
4502}4432}
45034433
4504// <expression> ::= mc <parameter type> <expr> [<offset number>] E4434// <expression> ::= mc <parameter type> <expr> [<offset number>] E
4505//4435//
4506// Not yet in the spec: https://github.com/itanium-cxx-abi/cxx-abi/issues/474436// Not yet in the spec: https://github.com/itanium-cxx-abi/cxx-abi/issues/47
4507template <typename Derived, typename Alloc>4437template <typename Derived, typename Alloc>
4508Node *AbstractManglingParser<Derived, Alloc>::parsePointerToMemberConversionExpr() {4438Node *
4439AbstractManglingParser<Derived, Alloc>::parsePointerToMemberConversionExpr(
4440 Node::Prec Prec) {
4509 Node *Ty = getDerived().parseType();4441 Node *Ty = getDerived().parseType();
4510 if (!Ty)4442 if (!Ty)
4511 return nullptr;4443 return nullptr;
...@@ -4515,7 +4447,7 @@ Node *AbstractManglingParser<Derived, Alloc>::parsePointerToMemberConversionExpr...@@ -4515,7 +4447,7 @@ Node *AbstractManglingParser<Derived, Alloc>::parsePointerToMemberConversionExpr
4515 StringView Offset = getDerived().parseNumber(true);4447 StringView Offset = getDerived().parseNumber(true);
4516 if (!consumeIf('E'))4448 if (!consumeIf('E'))
4517 return nullptr;4449 return nullptr;
4518 return make<PointerToMemberConversionExpr>(Ty, Expr, Offset);4450 return make<PointerToMemberConversionExpr>(Ty, Expr, Offset, Prec);
4519}4451}
45204452
4521// <expression> ::= so <referent type> <expr> [<offset number>] <union-selector>* [p] E4453// <expression> ::= so <referent type> <expr> [<offset number>] <union-selector>* [p] E
...@@ -4592,316 +4524,127 @@ Node *AbstractManglingParser<Derived, Alloc>::parseSubobjectExpr() {...@@ -4592,316 +4524,127 @@ Node *AbstractManglingParser<Derived, Alloc>::parseSubobjectExpr() {
4592template <typename Derived, typename Alloc>4524template <typename Derived, typename Alloc>
4593Node *AbstractManglingParser<Derived, Alloc>::parseExpr() {4525Node *AbstractManglingParser<Derived, Alloc>::parseExpr() {
4594 bool Global = consumeIf("gs");4526 bool Global = consumeIf("gs");
4595 if (numLeft() < 2)
4596 return nullptr;
45974527
4598 switch (*First) {4528 const auto *Op = parseOperatorEncoding();
4599 case 'L':4529 if (Op) {
4600 return getDerived().parseExprPrimary();4530 auto Sym = Op->getSymbol();
4601 case 'T':4531 switch (Op->getKind()) {
4602 return getDerived().parseTemplateParam();4532 case OperatorInfo::Binary:
4603 case 'f': {4533 // Binary operator: lhs @ rhs
4604 // Disambiguate a fold expression from a <function-param>.4534 return getDerived().parseBinaryExpr(Sym, Op->getPrecedence());
4605 if (look(1) == 'p' || (look(1) == 'L' && std::isdigit(look(2))))4535 case OperatorInfo::Prefix:
4606 return getDerived().parseFunctionParam();4536 // Prefix unary operator: @ expr
4607 return getDerived().parseFoldExpr();4537 return getDerived().parsePrefixExpr(Sym, Op->getPrecedence());
4608 }4538 case OperatorInfo::Postfix: {
4609 case 'a':4539 // Postfix unary operator: expr @
4610 switch (First[1]) {4540 if (consumeIf('_'))
4611 case 'a':4541 return getDerived().parsePrefixExpr(Sym, Op->getPrecedence());
4612 First += 2;4542 Node *Ex = getDerived().parseExpr();
4613 return getDerived().parseBinaryExpr("&&");4543 if (Ex == nullptr)
4614 case 'd':
4615 First += 2;
4616 return getDerived().parsePrefixExpr("&");
4617 case 'n':
4618 First += 2;
4619 return getDerived().parseBinaryExpr("&");
4620 case 'N':
4621 First += 2;
4622 return getDerived().parseBinaryExpr("&=");
4623 case 'S':
4624 First += 2;
4625 return getDerived().parseBinaryExpr("=");
4626 case 't': {
4627 First += 2;
4628 Node *Ty = getDerived().parseType();
4629 if (Ty == nullptr)
4630 return nullptr;4544 return nullptr;
4631 return make<EnclosingExpr>("alignof (", Ty, ")");4545 return make<PostfixExpr>(Ex, Sym, Op->getPrecedence());
4632 }4546 }
4633 case 'z': {4547 case OperatorInfo::Array: {
4634 First += 2;4548 // Array Index: lhs [ rhs ]
4635 Node *Ty = getDerived().parseExpr();4549 Node *Base = getDerived().parseExpr();
4636 if (Ty == nullptr)4550 if (Base == nullptr)
4637 return nullptr;4551 return nullptr;
4638 return make<EnclosingExpr>("alignof (", Ty, ")");4552 Node *Index = getDerived().parseExpr();
4639 }4553 if (Index == nullptr)
4640 }4554 return nullptr;
4641 return nullptr;4555 return make<ArraySubscriptExpr>(Base, Index, Op->getPrecedence());
4642 case 'c':
4643 switch (First[1]) {
4644 // cc <type> <expression> # const_cast<type>(expression)
4645 case 'c': {
4646 First += 2;
4647 Node *Ty = getDerived().parseType();
4648 if (Ty == nullptr)
4649 return Ty;
4650 Node *Ex = getDerived().parseExpr();
4651 if (Ex == nullptr)
4652 return Ex;
4653 return make<CastExpr>("const_cast", Ty, Ex);
4654 }4556 }
4655 // cl <expression>+ E # call4557 case OperatorInfo::Member: {
4656 case 'l': {4558 // Member access lhs @ rhs
4657 First += 2;
4658 Node *Callee = getDerived().parseExpr();
4659 if (Callee == nullptr)
4660 return Callee;
4661 size_t ExprsBegin = Names.size();
4662 while (!consumeIf('E')) {
4663 Node *E = getDerived().parseExpr();
4664 if (E == nullptr)
4665 return E;
4666 Names.push_back(E);
4667 }
4668 return make<CallExpr>(Callee, popTrailingNodeArray(ExprsBegin));
4669 }
4670 case 'm':
4671 First += 2;
4672 return getDerived().parseBinaryExpr(",");
4673 case 'o':
4674 First += 2;
4675 return getDerived().parsePrefixExpr("~");
4676 case 'v':
4677 return getDerived().parseConversionExpr();
4678 }
4679 return nullptr;
4680 case 'd':
4681 switch (First[1]) {
4682 case 'a': {
4683 First += 2;
4684 Node *Ex = getDerived().parseExpr();
4685 if (Ex == nullptr)
4686 return Ex;
4687 return make<DeleteExpr>(Ex, Global, /*is_array=*/true);
4688 }
4689 case 'c': {
4690 First += 2;
4691 Node *T = getDerived().parseType();
4692 if (T == nullptr)
4693 return T;
4694 Node *Ex = getDerived().parseExpr();
4695 if (Ex == nullptr)
4696 return Ex;
4697 return make<CastExpr>("dynamic_cast", T, Ex);
4698 }
4699 case 'e':
4700 First += 2;
4701 return getDerived().parsePrefixExpr("*");
4702 case 'l': {
4703 First += 2;
4704 Node *E = getDerived().parseExpr();
4705 if (E == nullptr)
4706 return E;
4707 return make<DeleteExpr>(E, Global, /*is_array=*/false);
4708 }
4709 case 'n':
4710 return getDerived().parseUnresolvedName();
4711 case 's': {
4712 First += 2;
4713 Node *LHS = getDerived().parseExpr();4559 Node *LHS = getDerived().parseExpr();
4714 if (LHS == nullptr)4560 if (LHS == nullptr)
4715 return nullptr;4561 return nullptr;
4716 Node *RHS = getDerived().parseExpr();4562 Node *RHS = getDerived().parseExpr();
4717 if (RHS == nullptr)4563 if (RHS == nullptr)
4718 return nullptr;4564 return nullptr;
4719 return make<MemberExpr>(LHS, ".*", RHS);4565 return make<MemberExpr>(LHS, Sym, RHS, Op->getPrecedence());
4720 }4566 }
4721 case 't': {4567 case OperatorInfo::New: {
4722 First += 2;4568 // New
4723 Node *LHS = getDerived().parseExpr();4569 // # new (expr-list) type [(init)]
4724 if (LHS == nullptr)4570 // [gs] nw <expression>* _ <type> [pi <expression>*] E
4725 return LHS;4571 // # new[] (expr-list) type [(init)]
4726 Node *RHS = getDerived().parseExpr();4572 // [gs] na <expression>* _ <type> [pi <expression>*] E
4727 if (RHS == nullptr)4573 size_t Exprs = Names.size();
4728 return nullptr;4574 while (!consumeIf('_')) {
4729 return make<MemberExpr>(LHS, ".", RHS);4575 Node *Ex = getDerived().parseExpr();
4730 }4576 if (Ex == nullptr)
4731 case 'v':4577 return nullptr;
4732 First += 2;4578 Names.push_back(Ex);
4733 return getDerived().parseBinaryExpr("/");4579 }
4734 case 'V':4580 NodeArray ExprList = popTrailingNodeArray(Exprs);
4735 First += 2;4581 Node *Ty = getDerived().parseType();
4736 return getDerived().parseBinaryExpr("/=");4582 if (Ty == nullptr)
4737 }
4738 return nullptr;
4739 case 'e':
4740 switch (First[1]) {
4741 case 'o':
4742 First += 2;
4743 return getDerived().parseBinaryExpr("^");
4744 case 'O':
4745 First += 2;
4746 return getDerived().parseBinaryExpr("^=");
4747 case 'q':
4748 First += 2;
4749 return getDerived().parseBinaryExpr("==");
4750 }
4751 return nullptr;
4752 case 'g':
4753 switch (First[1]) {
4754 case 'e':
4755 First += 2;
4756 return getDerived().parseBinaryExpr(">=");
4757 case 't':
4758 First += 2;
4759 return getDerived().parseBinaryExpr(">");
4760 }
4761 return nullptr;
4762 case 'i':
4763 switch (First[1]) {
4764 case 'x': {
4765 First += 2;
4766 Node *Base = getDerived().parseExpr();
4767 if (Base == nullptr)
4768 return nullptr;4583 return nullptr;
4769 Node *Index = getDerived().parseExpr();4584 bool HaveInits = consumeIf("pi");
4770 if (Index == nullptr)
4771 return Index;
4772 return make<ArraySubscriptExpr>(Base, Index);
4773 }
4774 case 'l': {
4775 First += 2;
4776 size_t InitsBegin = Names.size();4585 size_t InitsBegin = Names.size();
4777 while (!consumeIf('E')) {4586 while (!consumeIf('E')) {
4778 Node *E = getDerived().parseBracedExpr();4587 if (!HaveInits)
4779 if (E == nullptr)
4780 return nullptr;4588 return nullptr;
4781 Names.push_back(E);4589 Node *Init = getDerived().parseExpr();
4590 if (Init == nullptr)
4591 return Init;
4592 Names.push_back(Init);
4782 }4593 }
4783 return make<InitListExpr>(nullptr, popTrailingNodeArray(InitsBegin));4594 NodeArray Inits = popTrailingNodeArray(InitsBegin);
4595 return make<NewExpr>(ExprList, Ty, Inits, Global,
4596 /*IsArray=*/Op->getFlag(), Op->getPrecedence());
4784 }4597 }
4785 }4598 case OperatorInfo::Del: {
4786 return nullptr;4599 // Delete
4787 case 'l':
4788 switch (First[1]) {
4789 case 'e':
4790 First += 2;
4791 return getDerived().parseBinaryExpr("<=");
4792 case 's':
4793 First += 2;
4794 return getDerived().parseBinaryExpr("<<");
4795 case 'S':
4796 First += 2;
4797 return getDerived().parseBinaryExpr("<<=");
4798 case 't':
4799 First += 2;
4800 return getDerived().parseBinaryExpr("<");
4801 }
4802 return nullptr;
4803 case 'm':
4804 switch (First[1]) {
4805 case 'c':
4806 First += 2;
4807 return parsePointerToMemberConversionExpr();
4808 case 'i':
4809 First += 2;
4810 return getDerived().parseBinaryExpr("-");
4811 case 'I':
4812 First += 2;
4813 return getDerived().parseBinaryExpr("-=");
4814 case 'l':
4815 First += 2;
4816 return getDerived().parseBinaryExpr("*");
4817 case 'L':
4818 First += 2;
4819 return getDerived().parseBinaryExpr("*=");
4820 case 'm':
4821 First += 2;
4822 if (consumeIf('_'))
4823 return getDerived().parsePrefixExpr("--");
4824 Node *Ex = getDerived().parseExpr();4600 Node *Ex = getDerived().parseExpr();
4825 if (Ex == nullptr)4601 if (Ex == nullptr)
4826 return nullptr;4602 return nullptr;
4827 return make<PostfixExpr>(Ex, "--");4603 return make<DeleteExpr>(Ex, Global, /*IsArray=*/Op->getFlag(),
4828 }4604 Op->getPrecedence());
4829 return nullptr;
4830 case 'n':
4831 switch (First[1]) {
4832 case 'a':
4833 case 'w':
4834 return getDerived().parseNewExpr();
4835 case 'e':
4836 First += 2;
4837 return getDerived().parseBinaryExpr("!=");
4838 case 'g':
4839 First += 2;
4840 return getDerived().parsePrefixExpr("-");
4841 case 't':
4842 First += 2;
4843 return getDerived().parsePrefixExpr("!");
4844 case 'x':
4845 First += 2;
4846 Node *Ex = getDerived().parseExpr();
4847 if (Ex == nullptr)
4848 return Ex;
4849 return make<EnclosingExpr>("noexcept (", Ex, ")");
4850 }
4851 return nullptr;
4852 case 'o':
4853 switch (First[1]) {
4854 case 'n':
4855 return getDerived().parseUnresolvedName();
4856 case 'o':
4857 First += 2;
4858 return getDerived().parseBinaryExpr("||");
4859 case 'r':
4860 First += 2;
4861 return getDerived().parseBinaryExpr("|");
4862 case 'R':
4863 First += 2;
4864 return getDerived().parseBinaryExpr("|=");
4865 }4605 }
4866 return nullptr;4606 case OperatorInfo::Call: {
4867 case 'p':4607 // Function Call
4868 switch (First[1]) {4608 Node *Callee = getDerived().parseExpr();
4869 case 'm':4609 if (Callee == nullptr)
4870 First += 2;4610 return nullptr;
4871 return getDerived().parseBinaryExpr("->*");4611 size_t ExprsBegin = Names.size();
4872 case 'l':4612 while (!consumeIf('E')) {
4873 First += 2;4613 Node *E = getDerived().parseExpr();
4874 return getDerived().parseBinaryExpr("+");4614 if (E == nullptr)
4875 case 'L':4615 return nullptr;
4876 First += 2;4616 Names.push_back(E);
4877 return getDerived().parseBinaryExpr("+=");4617 }
4878 case 'p': {4618 return make<CallExpr>(Callee, popTrailingNodeArray(ExprsBegin),
4879 First += 2;4619 Op->getPrecedence());
4880 if (consumeIf('_'))
4881 return getDerived().parsePrefixExpr("++");
4882 Node *Ex = getDerived().parseExpr();
4883 if (Ex == nullptr)
4884 return Ex;
4885 return make<PostfixExpr>(Ex, "++");
4886 }4620 }
4887 case 's':4621 case OperatorInfo::CCast: {
4888 First += 2;4622 // C Cast: (type)expr
4889 return getDerived().parsePrefixExpr("+");4623 Node *Ty;
4890 case 't': {4624 {
4891 First += 2;4625 ScopedOverride<bool> SaveTemp(TryToParseTemplateArgs, false);
4892 Node *L = getDerived().parseExpr();4626 Ty = getDerived().parseType();
4893 if (L == nullptr)4627 }
4628 if (Ty == nullptr)
4894 return nullptr;4629 return nullptr;
4895 Node *R = getDerived().parseExpr();4630
4896 if (R == nullptr)4631 size_t ExprsBegin = Names.size();
4632 bool IsMany = consumeIf('_');
4633 while (!consumeIf('E')) {
4634 Node *E = getDerived().parseExpr();
4635 if (E == nullptr)
4636 return E;
4637 Names.push_back(E);
4638 if (!IsMany)
4639 break;
4640 }
4641 NodeArray Exprs = popTrailingNodeArray(ExprsBegin);
4642 if (!IsMany && Exprs.size() != 1)
4897 return nullptr;4643 return nullptr;
4898 return make<MemberExpr>(L, "->", R);4644 return make<ConversionExpr>(Ty, Exprs, Op->getPrecedence());
4899 }4645 }
4900 }4646 case OperatorInfo::Conditional: {
4901 return nullptr;4647 // Conditional operator: expr ? expr : expr
4902 case 'q':
4903 if (First[1] == 'u') {
4904 First += 2;
4905 Node *Cond = getDerived().parseExpr();4648 Node *Cond = getDerived().parseExpr();
4906 if (Cond == nullptr)4649 if (Cond == nullptr)
4907 return nullptr;4650 return nullptr;
...@@ -4911,147 +4654,120 @@ Node *AbstractManglingParser<Derived, Alloc>::parseExpr() {...@@ -4911,147 +4654,120 @@ Node *AbstractManglingParser<Derived, Alloc>::parseExpr() {
4911 Node *RHS = getDerived().parseExpr();4654 Node *RHS = getDerived().parseExpr();
4912 if (RHS == nullptr)4655 if (RHS == nullptr)
4913 return nullptr;4656 return nullptr;
4914 return make<ConditionalExpr>(Cond, LHS, RHS);4657 return make<ConditionalExpr>(Cond, LHS, RHS, Op->getPrecedence());
4915 }
4916 return nullptr;
4917 case 'r':
4918 switch (First[1]) {
4919 case 'c': {
4920 First += 2;
4921 Node *T = getDerived().parseType();
4922 if (T == nullptr)
4923 return T;
4924 Node *Ex = getDerived().parseExpr();
4925 if (Ex == nullptr)
4926 return Ex;
4927 return make<CastExpr>("reinterpret_cast", T, Ex);
4928 }
4929 case 'm':
4930 First += 2;
4931 return getDerived().parseBinaryExpr("%");
4932 case 'M':
4933 First += 2;
4934 return getDerived().parseBinaryExpr("%=");
4935 case 's':
4936 First += 2;
4937 return getDerived().parseBinaryExpr(">>");
4938 case 'S':
4939 First += 2;
4940 return getDerived().parseBinaryExpr(">>=");
4941 }
4942 return nullptr;
4943 case 's':
4944 switch (First[1]) {
4945 case 'c': {
4946 First += 2;
4947 Node *T = getDerived().parseType();
4948 if (T == nullptr)
4949 return T;
4950 Node *Ex = getDerived().parseExpr();
4951 if (Ex == nullptr)
4952 return Ex;
4953 return make<CastExpr>("static_cast", T, Ex);
4954 }
4955 case 'o':
4956 First += 2;
4957 return parseSubobjectExpr();
4958 case 'p': {
4959 First += 2;
4960 Node *Child = getDerived().parseExpr();
4961 if (Child == nullptr)
4962 return nullptr;
4963 return make<ParameterPackExpansion>(Child);
4964 }4658 }
4965 case 'r':4659 case OperatorInfo::NamedCast: {
4966 return getDerived().parseUnresolvedName();4660 // Named cast operation, @<type>(expr)
4967 case 't': {
4968 First += 2;
4969 Node *Ty = getDerived().parseType();4661 Node *Ty = getDerived().parseType();
4970 if (Ty == nullptr)4662 if (Ty == nullptr)
4971 return Ty;4663 return nullptr;
4972 return make<EnclosingExpr>("sizeof (", Ty, ")");
4973 }
4974 case 'z': {
4975 First += 2;
4976 Node *Ex = getDerived().parseExpr();4664 Node *Ex = getDerived().parseExpr();
4977 if (Ex == nullptr)4665 if (Ex == nullptr)
4978 return Ex;4666 return nullptr;
4979 return make<EnclosingExpr>("sizeof (", Ex, ")");4667 return make<CastExpr>(Sym, Ty, Ex, Op->getPrecedence());
4980 }4668 }
4981 case 'Z':4669 case OperatorInfo::OfIdOp: {
4982 First += 2;4670 // [sizeof/alignof/typeid] ( <type>|<expr> )
4983 if (look() == 'T') {4671 Node *Arg =
4984 Node *R = getDerived().parseTemplateParam();4672 Op->getFlag() ? getDerived().parseType() : getDerived().parseExpr();
4985 if (R == nullptr)4673 if (!Arg)
4986 return nullptr;
4987 return make<SizeofParamPackExpr>(R);
4988 } else if (look() == 'f') {
4989 Node *FP = getDerived().parseFunctionParam();
4990 if (FP == nullptr)
4991 return nullptr;
4992 return make<EnclosingExpr>("sizeof... (", FP, ")");
4993 }
4994 return nullptr;
4995 case 'P': {
4996 First += 2;
4997 size_t ArgsBegin = Names.size();
4998 while (!consumeIf('E')) {
4999 Node *Arg = getDerived().parseTemplateArg();
5000 if (Arg == nullptr)
5001 return nullptr;
5002 Names.push_back(Arg);
5003 }
5004 auto *Pack = make<NodeArrayNode>(popTrailingNodeArray(ArgsBegin));
5005 if (!Pack)
5006 return nullptr;4674 return nullptr;
5007 return make<EnclosingExpr>("sizeof... (", Pack, ")");4675 return make<EnclosingExpr>(Sym, Arg, Op->getPrecedence());
5008 }4676 }
4677 case OperatorInfo::NameOnly: {
4678 // Not valid as an expression operand.
4679 return nullptr;
5009 }4680 }
5010 return nullptr;
5011 case 't':
5012 switch (First[1]) {
5013 case 'e': {
5014 First += 2;
5015 Node *Ex = getDerived().parseExpr();
5016 if (Ex == nullptr)
5017 return Ex;
5018 return make<EnclosingExpr>("typeid (", Ex, ")");
5019 }4681 }
5020 case 'i': {4682 DEMANGLE_UNREACHABLE;
5021 First += 2;4683 }
5022 Node *Ty = getDerived().parseType();4684
5023 if (Ty == nullptr)4685 if (numLeft() < 2)
5024 return Ty;4686 return nullptr;
5025 return make<EnclosingExpr>("typeid (", Ty, ")");4687
4688 if (look() == 'L')
4689 return getDerived().parseExprPrimary();
4690 if (look() == 'T')
4691 return getDerived().parseTemplateParam();
4692 if (look() == 'f') {
4693 // Disambiguate a fold expression from a <function-param>.
4694 if (look(1) == 'p' || (look(1) == 'L' && std::isdigit(look(2))))
4695 return getDerived().parseFunctionParam();
4696 return getDerived().parseFoldExpr();
4697 }
4698 if (consumeIf("il")) {
4699 size_t InitsBegin = Names.size();
4700 while (!consumeIf('E')) {
4701 Node *E = getDerived().parseBracedExpr();
4702 if (E == nullptr)
4703 return nullptr;
4704 Names.push_back(E);
5026 }4705 }
5027 case 'l': {4706 return make<InitListExpr>(nullptr, popTrailingNodeArray(InitsBegin));
5028 First += 2;4707 }
5029 Node *Ty = getDerived().parseType();4708 if (consumeIf("mc"))
5030 if (Ty == nullptr)4709 return parsePointerToMemberConversionExpr(Node::Prec::Unary);
4710 if (consumeIf("nx")) {
4711 Node *Ex = getDerived().parseExpr();
4712 if (Ex == nullptr)
4713 return Ex;
4714 return make<EnclosingExpr>("noexcept ", Ex, Node::Prec::Unary);
4715 }
4716 if (consumeIf("so"))
4717 return parseSubobjectExpr();
4718 if (consumeIf("sp")) {
4719 Node *Child = getDerived().parseExpr();
4720 if (Child == nullptr)
4721 return nullptr;
4722 return make<ParameterPackExpansion>(Child);
4723 }
4724 if (consumeIf("sZ")) {
4725 if (look() == 'T') {
4726 Node *R = getDerived().parseTemplateParam();
4727 if (R == nullptr)
5031 return nullptr;4728 return nullptr;
5032 size_t InitsBegin = Names.size();4729 return make<SizeofParamPackExpr>(R);
5033 while (!consumeIf('E')) {
5034 Node *E = getDerived().parseBracedExpr();
5035 if (E == nullptr)
5036 return nullptr;
5037 Names.push_back(E);
5038 }
5039 return make<InitListExpr>(Ty, popTrailingNodeArray(InitsBegin));
5040 }4730 }
5041 case 'r':4731 Node *FP = getDerived().parseFunctionParam();
5042 First += 2;4732 if (FP == nullptr)
5043 return make<NameType>("throw");4733 return nullptr;
5044 case 'w': {4734 return make<EnclosingExpr>("sizeof... ", FP);
5045 First += 2;4735 }
5046 Node *Ex = getDerived().parseExpr();4736 if (consumeIf("sP")) {
5047 if (Ex == nullptr)4737 size_t ArgsBegin = Names.size();
4738 while (!consumeIf('E')) {
4739 Node *Arg = getDerived().parseTemplateArg();
4740 if (Arg == nullptr)
5048 return nullptr;4741 return nullptr;
5049 return make<ThrowExpr>(Ex);4742 Names.push_back(Arg);
5050 }4743 }
4744 auto *Pack = make<NodeArrayNode>(popTrailingNodeArray(ArgsBegin));
4745 if (!Pack)
4746 return nullptr;
4747 return make<EnclosingExpr>("sizeof... ", Pack);
4748 }
4749 if (consumeIf("tl")) {
4750 Node *Ty = getDerived().parseType();
4751 if (Ty == nullptr)
4752 return nullptr;
4753 size_t InitsBegin = Names.size();
4754 while (!consumeIf('E')) {
4755 Node *E = getDerived().parseBracedExpr();
4756 if (E == nullptr)
4757 return nullptr;
4758 Names.push_back(E);
5051 }4759 }
5052 return nullptr;4760 return make<InitListExpr>(Ty, popTrailingNodeArray(InitsBegin));
5053 case 'u': {4761 }
5054 ++First;4762 if (consumeIf("tr"))
4763 return make<NameType>("throw");
4764 if (consumeIf("tw")) {
4765 Node *Ex = getDerived().parseExpr();
4766 if (Ex == nullptr)
4767 return nullptr;
4768 return make<ThrowExpr>(Ex);
4769 }
4770 if (consumeIf('u')) {
5055 Node *Name = getDerived().parseSourceName(/*NameState=*/nullptr);4771 Node *Name = getDerived().parseSourceName(/*NameState=*/nullptr);
5056 if (!Name)4772 if (!Name)
5057 return nullptr;4773 return nullptr;
...@@ -5060,45 +4776,36 @@ Node *AbstractManglingParser<Derived, Alloc>::parseExpr() {...@@ -5060,45 +4776,36 @@ Node *AbstractManglingParser<Derived, Alloc>::parseExpr() {
5060 // interpreted as <type> node 'short' or 'ellipsis'. However, neither4776 // interpreted as <type> node 'short' or 'ellipsis'. However, neither
5061 // __uuidof(short) nor __uuidof(...) can actually appear, so there is no4777 // __uuidof(short) nor __uuidof(...) can actually appear, so there is no
5062 // actual conflict here.4778 // actual conflict here.
4779 bool IsUUID = false;
4780 Node *UUID = nullptr;
5063 if (Name->getBaseName() == "__uuidof") {4781 if (Name->getBaseName() == "__uuidof") {
5064 if (numLeft() < 2)4782 if (consumeIf('t')) {
5065 return nullptr;4783 UUID = getDerived().parseType();
5066 if (*First == 't') {4784 IsUUID = true;
5067 ++First;4785 } else if (consumeIf('z')) {
5068 Node *Ty = getDerived().parseType();4786 UUID = getDerived().parseExpr();
5069 if (!Ty)4787 IsUUID = true;
5070 return nullptr;
5071 return make<CallExpr>(Name, makeNodeArray(&Ty, &Ty + 1));
5072 }
5073 if (*First == 'z') {
5074 ++First;
5075 Node *Ex = getDerived().parseExpr();
5076 if (!Ex)
5077 return nullptr;
5078 return make<CallExpr>(Name, makeNodeArray(&Ex, &Ex + 1));
5079 }4788 }
5080 }4789 }
5081 size_t ExprsBegin = Names.size();4790 size_t ExprsBegin = Names.size();
5082 while (!consumeIf('E')) {4791 if (IsUUID) {
5083 Node *E = getDerived().parseTemplateArg();4792 if (UUID == nullptr)
5084 if (E == nullptr)4793 return nullptr;
5085 return E;4794 Names.push_back(UUID);
5086 Names.push_back(E);4795 } else {
4796 while (!consumeIf('E')) {
4797 Node *E = getDerived().parseTemplateArg();
4798 if (E == nullptr)
4799 return E;
4800 Names.push_back(E);
4801 }
5087 }4802 }
5088 return make<CallExpr>(Name, popTrailingNodeArray(ExprsBegin));4803 return make<CallExpr>(Name, popTrailingNodeArray(ExprsBegin),
5089 }4804 Node::Prec::Postfix);
5090 case '1':
5091 case '2':
5092 case '3':
5093 case '4':
5094 case '5':
5095 case '6':
5096 case '7':
5097 case '8':
5098 case '9':
5099 return getDerived().parseUnresolvedName();
5100 }4805 }
5101 return nullptr;4806
4807 // Only unresolved names remain.
4808 return getDerived().parseUnresolvedName(Global);
5102}4809}
51034810
5104// <call-offset> ::= h <nv-offset> _4811// <call-offset> ::= h <nv-offset> _
...@@ -5131,14 +4838,17 @@ bool AbstractManglingParser<Alloc, Derived>::parseCallOffset() {...@@ -5131,14 +4838,17 @@ bool AbstractManglingParser<Alloc, Derived>::parseCallOffset() {
5131// # second call-offset is result adjustment4838// # second call-offset is result adjustment
5132// ::= T <call-offset> <base encoding>4839// ::= T <call-offset> <base encoding>
5133// # base is the nominal target function of thunk4840// # base is the nominal target function of thunk
5134// ::= GV <object name> # Guard variable for one-time initialization4841// # Guard variable for one-time initialization
4842// ::= GV <object name>
5135// # No <type>4843// # No <type>
5136// ::= TW <object name> # Thread-local wrapper4844// ::= TW <object name> # Thread-local wrapper
5137// ::= TH <object name> # Thread-local initialization4845// ::= TH <object name> # Thread-local initialization
5138// ::= GR <object name> _ # First temporary4846// ::= GR <object name> _ # First temporary
5139// ::= GR <object name> <seq-id> _ # Subsequent temporaries4847// ::= GR <object name> <seq-id> _ # Subsequent temporaries
5140// extension ::= TC <first type> <number> _ <second type> # construction vtable for second-in-first4848// # construction vtable for second-in-first
4849// extension ::= TC <first type> <number> _ <second type>
5141// extension ::= GR <object name> # reference temporary for object4850// extension ::= GR <object name> # reference temporary for object
4851// extension ::= GI <module name> # module global initializer
5142template <typename Derived, typename Alloc>4852template <typename Derived, typename Alloc>
5143Node *AbstractManglingParser<Derived, Alloc>::parseSpecialName() {4853Node *AbstractManglingParser<Derived, Alloc>::parseSpecialName() {
5144 switch (look()) {4854 switch (look()) {
...@@ -5265,6 +4975,16 @@ Node *AbstractManglingParser<Derived, Alloc>::parseSpecialName() {...@@ -5265,6 +4975,16 @@ Node *AbstractManglingParser<Derived, Alloc>::parseSpecialName() {
5265 return nullptr;4975 return nullptr;
5266 return make<SpecialName>("reference temporary for ", Name);4976 return make<SpecialName>("reference temporary for ", Name);
5267 }4977 }
4978 // GI <module-name> v
4979 case 'I': {
4980 First += 2;
4981 ModuleName *Module = nullptr;
4982 if (getDerived().parseModuleNameOpt(Module))
4983 return nullptr;
4984 if (Module == nullptr)
4985 return nullptr;
4986 return make<SpecialName>("initializer for module ", Module);
4987 }
5268 }4988 }
5269 }4989 }
5270 return nullptr;4990 return nullptr;
...@@ -5379,7 +5099,7 @@ template <>...@@ -5379,7 +5099,7 @@ template <>
5379struct FloatData<long double>5099struct FloatData<long double>
5380{5100{
5381#if defined(__mips__) && defined(__mips_n64) || defined(__aarch64__) || \5101#if defined(__mips__) && defined(__mips_n64) || defined(__aarch64__) || \
5382 defined(__wasm__)5102 defined(__wasm__) || defined(__riscv)
5383 static const size_t mangled_size = 32;5103 static const size_t mangled_size = 32;
5384#elif defined(__arm__) || defined(__mips__) || defined(__hexagon__)5104#elif defined(__arm__) || defined(__mips__) || defined(__hexagon__)
5385 static const size_t mangled_size = 16;5105 static const size_t mangled_size = 16;
...@@ -5444,6 +5164,7 @@ bool AbstractManglingParser<Alloc, Derived>::parseSeqId(size_t *Out) {...@@ -5444,6 +5164,7 @@ bool AbstractManglingParser<Alloc, Derived>::parseSeqId(size_t *Out) {
5444// <substitution> ::= Si # ::std::basic_istream<char, std::char_traits<char> >5164// <substitution> ::= Si # ::std::basic_istream<char, std::char_traits<char> >
5445// <substitution> ::= So # ::std::basic_ostream<char, std::char_traits<char> >5165// <substitution> ::= So # ::std::basic_ostream<char, std::char_traits<char> >
5446// <substitution> ::= Sd # ::std::basic_iostream<char, std::char_traits<char> >5166// <substitution> ::= Sd # ::std::basic_iostream<char, std::char_traits<char> >
5167// The St case is handled specially in parseNestedName.
5447template <typename Derived, typename Alloc>5168template <typename Derived, typename Alloc>
5448Node *AbstractManglingParser<Derived, Alloc>::parseSubstitution() {5169Node *AbstractManglingParser<Derived, Alloc>::parseSubstitution() {
5449 if (!consumeIf('S'))5170 if (!consumeIf('S'))
lib/libcxxabi/src/demangle/ItaniumNodes.def created+95
...@@ -0,0 +1,95 @@
1//===------------------------- ItaniumNodes.def ----------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// Define the demangler's node names
10
11#ifndef NODE
12#error Define NODE to handle nodes
13#endif
14
15NODE(NodeArrayNode)
16NODE(DotSuffix)
17NODE(VendorExtQualType)
18NODE(QualType)
19NODE(ConversionOperatorType)
20NODE(PostfixQualifiedType)
21NODE(ElaboratedTypeSpefType)
22NODE(NameType)
23NODE(AbiTagAttr)
24NODE(EnableIfAttr)
25NODE(ObjCProtoName)
26NODE(PointerType)
27NODE(ReferenceType)
28NODE(PointerToMemberType)
29NODE(ArrayType)
30NODE(FunctionType)
31NODE(NoexceptSpec)
32NODE(DynamicExceptionSpec)
33NODE(FunctionEncoding)
34NODE(LiteralOperator)
35NODE(SpecialName)
36NODE(CtorVtableSpecialName)
37NODE(QualifiedName)
38NODE(NestedName)
39NODE(LocalName)
40NODE(ModuleName)
41NODE(ModuleEntity)
42NODE(VectorType)
43NODE(PixelVectorType)
44NODE(BinaryFPType)
45NODE(BitIntType)
46NODE(SyntheticTemplateParamName)
47NODE(TypeTemplateParamDecl)
48NODE(NonTypeTemplateParamDecl)
49NODE(TemplateTemplateParamDecl)
50NODE(TemplateParamPackDecl)
51NODE(ParameterPack)
52NODE(TemplateArgumentPack)
53NODE(ParameterPackExpansion)
54NODE(TemplateArgs)
55NODE(ForwardTemplateReference)
56NODE(NameWithTemplateArgs)
57NODE(GlobalQualifiedName)
58NODE(ExpandedSpecialSubstitution)
59NODE(SpecialSubstitution)
60NODE(CtorDtorName)
61NODE(DtorName)
62NODE(UnnamedTypeName)
63NODE(ClosureTypeName)
64NODE(StructuredBindingName)
65NODE(BinaryExpr)
66NODE(ArraySubscriptExpr)
67NODE(PostfixExpr)
68NODE(ConditionalExpr)
69NODE(MemberExpr)
70NODE(SubobjectExpr)
71NODE(EnclosingExpr)
72NODE(CastExpr)
73NODE(SizeofParamPackExpr)
74NODE(CallExpr)
75NODE(NewExpr)
76NODE(DeleteExpr)
77NODE(PrefixExpr)
78NODE(FunctionParam)
79NODE(ConversionExpr)
80NODE(PointerToMemberConversionExpr)
81NODE(InitListExpr)
82NODE(FoldExpr)
83NODE(ThrowExpr)
84NODE(BoolExpr)
85NODE(StringLiteral)
86NODE(LambdaExpr)
87NODE(EnumLiteral)
88NODE(IntegerLiteral)
89NODE(FloatLiteral)
90NODE(DoubleLiteral)
91NODE(LongDoubleLiteral)
92NODE(BracedExpr)
93NODE(BracedRangeExpr)
94
95#undef NODE
lib/libcxxabi/src/demangle/Utility.h+58-56
...@@ -33,43 +33,50 @@ class OutputBuffer {...@@ -33,43 +33,50 @@ class OutputBuffer {
33 size_t CurrentPosition = 0;33 size_t CurrentPosition = 0;
34 size_t BufferCapacity = 0;34 size_t BufferCapacity = 0;
3535
36 // Ensure there is at least n more positions in buffer.36 // Ensure there are at least N more positions in the buffer.
37 void grow(size_t N) {37 void grow(size_t N) {
38 if (N + CurrentPosition >= BufferCapacity) {38 size_t Need = N + CurrentPosition;
39 if (Need > BufferCapacity) {
40 // Reduce the number of reallocations, with a bit of hysteresis. The
41 // number here is chosen so the first allocation will more-than-likely not
42 // allocate more than 1K.
43 Need += 1024 - 32;
39 BufferCapacity *= 2;44 BufferCapacity *= 2;
40 if (BufferCapacity < N + CurrentPosition)45 if (BufferCapacity < Need)
41 BufferCapacity = N + CurrentPosition;46 BufferCapacity = Need;
42 Buffer = static_cast<char *>(std::realloc(Buffer, BufferCapacity));47 Buffer = static_cast<char *>(std::realloc(Buffer, BufferCapacity));
43 if (Buffer == nullptr)48 if (Buffer == nullptr)
44 std::terminate();49 std::terminate();
45 }50 }
46 }51 }
4752
48 void writeUnsigned(uint64_t N, bool isNeg = false) {53 OutputBuffer &writeUnsigned(uint64_t N, bool isNeg = false) {
49 // Handle special case...
50 if (N == 0) {
51 *this << '0';
52 return;
53 }
54
55 std::array<char, 21> Temp;54 std::array<char, 21> Temp;
56 char *TempPtr = Temp.data() + Temp.size();55 char *TempPtr = Temp.data() + Temp.size();
5756
58 while (N) {57 // Output at least one character.
58 do {
59 *--TempPtr = char('0' + N % 10);59 *--TempPtr = char('0' + N % 10);
60 N /= 10;60 N /= 10;
61 }61 } while (N);
6262
63 // Add negative sign...63 // Add negative sign.
64 if (isNeg)64 if (isNeg)
65 *--TempPtr = '-';65 *--TempPtr = '-';
66 this->operator<<(StringView(TempPtr, Temp.data() + Temp.size()));66
67 return operator+=(StringView(TempPtr, Temp.data() + Temp.size()));
67 }68 }
6869
69public:70public:
70 OutputBuffer(char *StartBuf, size_t Size)71 OutputBuffer(char *StartBuf, size_t Size)
71 : Buffer(StartBuf), CurrentPosition(0), BufferCapacity(Size) {}72 : Buffer(StartBuf), CurrentPosition(0), BufferCapacity(Size) {}
72 OutputBuffer() = default;73 OutputBuffer() = default;
74 // Non-copyable
75 OutputBuffer(const OutputBuffer &) = delete;
76 OutputBuffer &operator=(const OutputBuffer &) = delete;
77
78 operator StringView() const { return StringView(Buffer, CurrentPosition); }
79
73 void reset(char *Buffer_, size_t BufferCapacity_) {80 void reset(char *Buffer_, size_t BufferCapacity_) {
74 CurrentPosition = 0;81 CurrentPosition = 0;
75 Buffer = Buffer_;82 Buffer = Buffer_;
...@@ -81,13 +88,27 @@ public:...@@ -81,13 +88,27 @@ public:
81 unsigned CurrentPackIndex = std::numeric_limits<unsigned>::max();88 unsigned CurrentPackIndex = std::numeric_limits<unsigned>::max();
82 unsigned CurrentPackMax = std::numeric_limits<unsigned>::max();89 unsigned CurrentPackMax = std::numeric_limits<unsigned>::max();
8390
91 /// When zero, we're printing template args and '>' needs to be parenthesized.
92 /// Use a counter so we can simply increment inside parentheses.
93 unsigned GtIsGt = 1;
94
95 bool isGtInsideTemplateArgs() const { return GtIsGt == 0; }
96
97 void printOpen(char Open = '(') {
98 GtIsGt++;
99 *this += Open;
100 }
101 void printClose(char Close = ')') {
102 GtIsGt--;
103 *this += Close;
104 }
105
84 OutputBuffer &operator+=(StringView R) {106 OutputBuffer &operator+=(StringView R) {
85 size_t Size = R.size();107 if (size_t Size = R.size()) {
86 if (Size == 0)108 grow(Size);
87 return *this;109 std::memcpy(Buffer + CurrentPosition, R.begin(), Size);
88 grow(Size);110 CurrentPosition += Size;
89 std::memmove(Buffer + CurrentPosition, R.begin(), Size);111 }
90 CurrentPosition += Size;
91 return *this;112 return *this;
92 }113 }
93114
...@@ -97,9 +118,7 @@ public:...@@ -97,9 +118,7 @@ public:
97 return *this;118 return *this;
98 }119 }
99120
100 OutputBuffer &operator<<(StringView R) { return (*this += R); }121 OutputBuffer &prepend(StringView R) {
101
102 OutputBuffer prepend(StringView R) {
103 size_t Size = R.size();122 size_t Size = R.size();
104123
105 grow(Size);124 grow(Size);
...@@ -110,19 +129,16 @@ public:...@@ -110,19 +129,16 @@ public:
110 return *this;129 return *this;
111 }130 }
112131
132 OutputBuffer &operator<<(StringView R) { return (*this += R); }
133
113 OutputBuffer &operator<<(char C) { return (*this += C); }134 OutputBuffer &operator<<(char C) { return (*this += C); }
114135
115 OutputBuffer &operator<<(long long N) {136 OutputBuffer &operator<<(long long N) {
116 if (N < 0)137 return writeUnsigned(static_cast<unsigned long long>(std::abs(N)), N < 0);
117 writeUnsigned(static_cast<unsigned long long>(-N), true);
118 else
119 writeUnsigned(static_cast<unsigned long long>(N));
120 return *this;
121 }138 }
122139
123 OutputBuffer &operator<<(unsigned long long N) {140 OutputBuffer &operator<<(unsigned long long N) {
124 writeUnsigned(N, false);141 return writeUnsigned(N, false);
125 return *this;
126 }142 }
127143
128 OutputBuffer &operator<<(long N) {144 OutputBuffer &operator<<(long N) {
...@@ -155,7 +171,8 @@ public:...@@ -155,7 +171,8 @@ public:
155 void setCurrentPosition(size_t NewPos) { CurrentPosition = NewPos; }171 void setCurrentPosition(size_t NewPos) { CurrentPosition = NewPos; }
156172
157 char back() const {173 char back() const {
158 return CurrentPosition ? Buffer[CurrentPosition - 1] : '\0';174 assert(CurrentPosition);
175 return Buffer[CurrentPosition - 1];
159 }176 }
160177
161 bool empty() const { return CurrentPosition == 0; }178 bool empty() const { return CurrentPosition == 0; }
...@@ -165,35 +182,20 @@ public:...@@ -165,35 +182,20 @@ public:
165 size_t getBufferCapacity() const { return BufferCapacity; }182 size_t getBufferCapacity() const { return BufferCapacity; }
166};183};
167184
168template <class T> class SwapAndRestore {185template <class T> class ScopedOverride {
169 T &Restore;186 T &Loc;
170 T OriginalValue;187 T Original;
171 bool ShouldRestore = true;
172188
173public:189public:
174 SwapAndRestore(T &Restore_) : SwapAndRestore(Restore_, Restore_) {}190 ScopedOverride(T &Loc_) : ScopedOverride(Loc_, Loc_) {}
175
176 SwapAndRestore(T &Restore_, T NewVal)
177 : Restore(Restore_), OriginalValue(Restore) {
178 Restore = std::move(NewVal);
179 }
180 ~SwapAndRestore() {
181 if (ShouldRestore)
182 Restore = std::move(OriginalValue);
183 }
184
185 void shouldRestore(bool ShouldRestore_) { ShouldRestore = ShouldRestore_; }
186
187 void restoreNow(bool Force) {
188 if (!Force && !ShouldRestore)
189 return;
190191
191 Restore = std::move(OriginalValue);192 ScopedOverride(T &Loc_, T NewVal) : Loc(Loc_), Original(Loc_) {
192 ShouldRestore = false;193 Loc_ = std::move(NewVal);
193 }194 }
195 ~ScopedOverride() { Loc = std::move(Original); }
194196
195 SwapAndRestore(const SwapAndRestore &) = delete;197 ScopedOverride(const ScopedOverride &) = delete;
196 SwapAndRestore &operator=(const SwapAndRestore &) = delete;198 ScopedOverride &operator=(const ScopedOverride &) = delete;
197};199};
198200
199inline bool initializeOutputBuffer(char *Buf, size_t *N, OutputBuffer &OB,201inline bool initializeOutputBuffer(char *Buf, size_t *N, OutputBuffer &OB,
lib/libcxxabi/src/fallback_malloc.cpp+2-3
...@@ -33,10 +33,9 @@ namespace {...@@ -33,10 +33,9 @@ namespace {
3333
34// When POSIX threads are not available, make the mutex operations a nop34// When POSIX threads are not available, make the mutex operations a nop
35#ifndef _LIBCXXABI_HAS_NO_THREADS35#ifndef _LIBCXXABI_HAS_NO_THREADS
36_LIBCPP_SAFE_STATIC36static _LIBCPP_CONSTINIT std::__libcpp_mutex_t heap_mutex = _LIBCPP_MUTEX_INITIALIZER;
37static std::__libcpp_mutex_t heap_mutex = _LIBCPP_MUTEX_INITIALIZER;
38#else37#else
39static void* heap_mutex = 0;38static _LIBCPP_CONSTINIT void* heap_mutex = 0;
40#endif39#endif
4140
42class mutexor {41class mutexor {
src/libcxx.zig+1-1
...@@ -327,7 +327,7 @@ pub fn buildLibCXXABI(comp: *Compilation) !void {...@@ -327,7 +327,7 @@ pub fn buildLibCXXABI(comp: *Compilation) !void {
327 try cflags.append("-nostdinc++");327 try cflags.append("-nostdinc++");
328 try cflags.append("-fstrict-aliasing");328 try cflags.append("-fstrict-aliasing");
329 try cflags.append("-funwind-tables");329 try cflags.append("-funwind-tables");
330 try cflags.append("-std=c++11");330 try cflags.append("-std=c++20");
331331
332 c_source_files.appendAssumeCapacity(.{332 c_source_files.appendAssumeCapacity(.{
333 .src_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{ "libcxxabi", cxxabi_src }),333 .src_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{ "libcxxabi", cxxabi_src }),