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 @@
1010#define ____CXXABI_CONFIG_H
1111
1212#if defined(__arm__) && !defined(__USING_SJLJ_EXCEPTIONS__) && \
13 !defined(__ARM_DWARF_EH__)
13 !defined(__ARM_DWARF_EH__) && !defined(__SEH__)
1414#define _LIBCXXABI_ARM_EHABI
1515#endif
1616
......@@ -97,4 +97,10 @@
9797# define _LIBCXXABI_NO_EXCEPTIONS
9898#endif
9999
100#if defined(_WIN32)
101#define _LIBCXXABI_DTOR_FUNC __thiscall
102#else
103#define _LIBCXXABI_DTOR_FUNC
104#endif
105
100106#endif // ____CXXABI_CONFIG_H
lib/libcxxabi/include/cxxabi.h+2-2
......@@ -19,7 +19,7 @@
1919
2020#include <__cxxabi_config.h>
2121
22#define _LIBCPPABI_VERSION 1002
22#define _LIBCPPABI_VERSION 15000
2323#define _LIBCXXABI_NORETURN __attribute__((noreturn))
2424#define _LIBCXXABI_ALWAYS_COLD __attribute__((cold))
2525
......@@ -47,7 +47,7 @@ __cxa_free_exception(void *thrown_exception) throw();
4747// 2.4.3 Throwing the Exception Object
4848extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_NORETURN void
4949__cxa_throw(void *thrown_exception, std::type_info *tinfo,
50 void (*dest)(void *));
50 void (_LIBCXXABI_DTOR_FUNC *dest)(void *));
5151
5252// 2.5.3 Exception Handlers
5353extern _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 @@
1010//===----------------------------------------------------------------------===//
1111
1212#include <exception>
13#include <memory>
1314#include <stdlib.h>
1415#include "abort_message.h"
1516#include "cxxabi.h"
......@@ -20,67 +21,69 @@
2021
2122#if !defined(LIBCXXABI_SILENT_TERMINATE)
2223
23_LIBCPP_SAFE_STATIC
24static const char* cause = "uncaught";
24static constinit 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
2637__attribute__((noreturn))
2738static void demangling_terminate_handler()
2839{
29#ifndef _LIBCXXABI_NO_EXCEPTIONS
30 // If there might be an uncaught exception
3140 using namespace __cxxabiv1;
3241 __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))
3469 {
35 __cxa_exception* exception_header = globals->caughtExceptions;
36 // If there is an uncaught exception
37 if (exception_header)
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 }
70 // Include the what() message from the exception
71 const std::exception* e = static_cast<const std::exception*>(thrown_object);
72 abort_message("terminating due to %s exception of type %s: %s", cause, name.get(), e->what());
7973 }
80#endif
81 // Else just note that we're terminating
74 else
75 {
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{
8284 abort_message("terminating");
8385}
86#endif // !_LIBCXXABI_NO_EXCEPTIONS
8487
8588__attribute__((noreturn))
8689static void demangling_unexpected_handler()
......@@ -91,22 +94,22 @@ static void demangling_unexpected_handler()
9194
9295static constexpr std::terminate_handler default_terminate_handler = demangling_terminate_handler;
9396static constexpr std::terminate_handler default_unexpected_handler = demangling_unexpected_handler;
94#else
97#else // !LIBCXXABI_SILENT_TERMINATE
9598static constexpr std::terminate_handler default_terminate_handler = ::abort;
9699static constexpr std::terminate_handler default_unexpected_handler = std::terminate;
97#endif
100#endif // !LIBCXXABI_SILENT_TERMINATE
98101
99102//
100103// Global variables that hold the pointers to the current handler
101104//
102105_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
105108_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
108111_LIBCXXABI_DATA_VIS
109_LIBCPP_SAFE_STATIC std::new_handler __cxa_new_handler = 0;
112constinit std::new_handler __cxa_new_handler = nullptr;
110113
111114namespace std
112115{
lib/libcxxabi/src/cxa_demangle.cpp+44
......@@ -173,6 +173,50 @@ struct DumpVisitor {
173173 return printStr("TemplateParamKind::Template");
174174 }
175175 }
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
177221 void newLine() {
178222 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
254254exception.
255255*/
256256void
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 *)) {
258258 __cxa_eh_globals *globals = __cxa_get_globals();
259259 __cxa_exception* exception_header = cxa_exception_from_thrown_object(thrown_object);
260260
......@@ -341,10 +341,11 @@ unwinding with _Unwind_Resume.
341341According to ARM EHABI 8.4.1, __cxa_end_cleanup() should not clobber any
342342register, thus we have to write this function in assembly so that we can save
343343{r1, r2, r3}. We don't have to save r0 because it is the return value and the
344first argument to _Unwind_Resume(). In addition, we are saving lr in order to
345align the stack to 16 bytes and lr will be used to identify the caller and its
346frame information. _Unwind_Resume never return and we need to keep the original
347lr so just branch to it.
344first argument to _Unwind_Resume(). The function also saves/restores r4 to
345keep the stack aligned and to provide a temp register. _Unwind_Resume never
346returns and we need to keep the original lr so just branch to it. When
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.
348349*/
349350__attribute__((used)) static _Unwind_Exception *
350351__cxa_end_cleanup_impl()
......@@ -381,15 +382,19 @@ asm(" .pushsection .text.__cxa_end_cleanup,\"ax\",%progbits\n"
381382#if defined(__ARM_FEATURE_BTI_DEFAULT)
382383 " bti\n"
383384#endif
384 " push {r1, r2, r3, lr}\n"
385 " push {r1, r2, r3, r4}\n"
386 " mov r4, lr\n"
385387 " bl __cxa_end_cleanup_impl\n"
386 " pop {r1, r2, r3, r4}\n"
387388 " mov lr, r4\n"
388389#if defined(LIBCXXABI_BAREMETAL)
389390 " 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"
391396#else
392 " b _Unwind_Resume\n"
397 " b _Unwind_Resume\n"
393398#endif
394399 " .popsection");
395400#endif // defined(_LIBCXXABI_ARM_EHABI)
......@@ -439,6 +444,14 @@ __cxa_begin_catch(void* unwind_arg) throw()
439444 (
440445 static_cast<_Unwind_Exception*>(unwind_exception)
441446 );
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
442455 if (native_exception)
443456 {
444457 // 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 {
3434 // in the beginning of the struct, rather than before unwindHeader.
3535 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.
3838 // For binary compatibility it is at the start of this
3939 // struct which is prepended to the object thrown in
4040 // __cxa_allocate_exception.
......@@ -43,7 +43,7 @@ struct _LIBCXXABI_HIDDEN __cxa_exception {
4343
4444 // Manage the exception object itself.
4545 std::type_info *exceptionType;
46 void (*exceptionDestructor)(void *);
46 void (_LIBCXXABI_DTOR_FUNC *exceptionDestructor)(void *);
4747 std::unexpected_handler unexpectedHandler;
4848 std::terminate_handler terminateHandler;
4949
......@@ -63,9 +63,9 @@ struct _LIBCXXABI_HIDDEN __cxa_exception {
6363#endif
6464
6565#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.
6767 // 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.
6969 size_t referenceCount;
7070#endif
7171 _Unwind_Exception unwindHeader;
......@@ -81,7 +81,7 @@ struct _LIBCXXABI_HIDDEN __cxa_dependent_exception {
8181#endif
8282
8383 std::type_info *exceptionType;
84 void (*exceptionDestructor)(void *);
84 void (_LIBCXXABI_DTOR_FUNC *exceptionDestructor)(void *);
8585 std::unexpected_handler unexpectedHandler;
8686 std::terminate_handler terminateHandler;
8787
lib/libcxxabi/src/cxa_guard_impl.h+1-1
......@@ -619,7 +619,7 @@ struct GlobalStatic {
619619 static T instance;
620620};
621621template <class T>
622_LIBCPP_SAFE_STATIC T GlobalStatic<T>::instance = {};
622_LIBCPP_CONSTINIT T GlobalStatic<T>::instance = {};
623623
624624enum class Implementation { NoThreads, GlobalMutex, Futex };
625625
lib/libcxxabi/src/cxa_personality.cpp+21-4
......@@ -22,6 +22,15 @@
2222#include "private_typeinfo.h"
2323#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
2534#if defined(__SEH__) && !defined(__USING_SJLJ_EXCEPTIONS__)
2635#include <windows.h>
2736#include <winnt.h>
......@@ -613,7 +622,7 @@ static void scan_eh_tab(scan_results &results, _Unwind_Action actions,
613622 results.reason = _URC_FATAL_PHASE1_ERROR;
614623 return;
615624 }
616 // Start scan by getting exception table address
625 // Start scan by getting exception table address.
617626 const uint8_t *lsda = (const uint8_t *)_Unwind_GetLanguageSpecificData(context);
618627 if (lsda == 0)
619628 {
......@@ -903,6 +912,8 @@ static _Unwind_Reason_Code __gxx_personality_imp
903912_LIBCXXABI_FUNC_VIS _Unwind_Reason_Code
904913#ifdef __USING_SJLJ_EXCEPTIONS__
905914__gxx_personality_sj0
915#elif defined(__MVS__)
916__zos_cxx_personality_v2
906917#else
907918__gxx_personality_v0
908919#endif
......@@ -1015,7 +1026,7 @@ static _Unwind_Reason_Code continue_unwind(_Unwind_Exception* unwind_exception,
10151026}
10161027
10171028// ARM register names
1018#if !defined(LIBCXXABI_USE_LLVM_UNWINDER)
1029#if !defined(_LIBUNWIND_VERSION)
10191030static const uint32_t REG_UCB = 12; // Register to save _Unwind_Control_Block
10201031#endif
10211032static const uint32_t REG_SP = 13;
......@@ -1050,7 +1061,7 @@ __gxx_personality_v0(_Unwind_State state,
10501061
10511062 bool native_exception = __isOurExceptionClass(unwind_exception);
10521063
1053#if !defined(LIBCXXABI_USE_LLVM_UNWINDER)
1064#if !defined(_LIBUNWIND_VERSION)
10541065 // Copy the address of _Unwind_Control_Block to r12 so that
10551066 // _Unwind_GetLanguageSpecificData() and _Unwind_GetRegionStart() can
10561067 // return correct address.
......@@ -1112,7 +1123,7 @@ __gxx_personality_v0(_Unwind_State state,
11121123 }
11131124
11141125 // 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.
11161127 // Search for a (non-catching) cleanup
11171128 if (is_force_unwinding)
11181129 scan_eh_tab(
......@@ -1296,3 +1307,9 @@ _LIBCXXABI_FUNC_VIS _Unwind_Reason_Code __xlcxx_personality_v1(
12961307} // extern "C"
12971308
12981309} // __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 @@
1616#ifndef DEMANGLE_ITANIUMDEMANGLE_H
1717#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
2319#include "DemangleConfig.h"
2420#include "StringView.h"
2521#include "Utility.h"
......@@ -32,85 +28,6 @@
3228#include <limits>
3329#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
11431DEMANGLE_NAMESPACE_BEGIN
11532
11633template <class T, size_t N> class PODSmallVector {
......@@ -238,37 +155,68 @@ public:
238155class Node {
239156public:
240157 enum Kind : unsigned char {
241#define ENUMERATOR(NodeKind) K ## NodeKind,
242 FOR_EACH_NODE_KIND(ENUMERATOR)
243#undef ENUMERATOR
158#define NODE(NodeKind) K##NodeKind,
159#include "ItaniumNodes.def"
244160 };
245161
246162 /// Three-way bool to track a cached value. Unknown is possible if this node
247163 /// has an unexpanded parameter pack below it that may affect this cache.
248164 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
250191private:
251192 Kind K;
252193
194 Prec Precedence : 6;
195
253196 // FIXME: Make these protected.
254197public:
255198 /// Tracks if this node has a component on its right side, in which case we
256199 /// need to call printRight.
257 Cache RHSComponentCache;
200 Cache RHSComponentCache : 2;
258201
259202 /// Track if this node is a (possibly qualified) array type. This can affect
260203 /// how we format the output string.
261 Cache ArrayCache;
204 Cache ArrayCache : 2;
262205
263206 /// Track if this node is a (possibly qualified) function type. This can
264207 /// affect how we format the output string.
265 Cache FunctionCache;
208 Cache FunctionCache : 2;
266209
267210public:
268 Node(Kind K_, Cache RHSComponentCache_ = Cache::No,
269 Cache ArrayCache_ = Cache::No, Cache FunctionCache_ = Cache::No)
270 : K(K_), RHSComponentCache(RHSComponentCache_), ArrayCache(ArrayCache_),
271 FunctionCache(FunctionCache_) {}
211 Node(Kind K_, Prec Precedence_ = Prec::Primary,
212 Cache RHSComponentCache_ = Cache::No, Cache ArrayCache_ = Cache::No,
213 Cache FunctionCache_ = Cache::No)
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
273221 /// Visit the most-derived object corresponding to this object.
274222 template<typename Fn> void visit(Fn F) const;
......@@ -299,6 +247,8 @@ public:
299247
300248 Kind getKind() const { return K; }
301249
250 Prec getPrecedence() const { return Precedence; }
251
302252 virtual bool hasRHSComponentSlow(OutputBuffer &) const { return false; }
303253 virtual bool hasArraySlow(OutputBuffer &) const { return false; }
304254 virtual bool hasFunctionSlow(OutputBuffer &) const { return false; }
......@@ -307,6 +257,19 @@ public:
307257 // get at a node that actually represents some concrete syntax.
308258 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
310273 void print(OutputBuffer &OB) const {
311274 printLeft(OB);
312275 if (RHSComponentCache != Cache::No)
......@@ -356,7 +319,7 @@ public:
356319 if (!FirstElement)
357320 OB += ", ";
358321 size_t AfterComma = OB.getCurrentPosition();
359 Elements[Idx]->print(OB);
322 Elements[Idx]->printAsOperand(OB, Node::Prec::Comma);
360323
361324 // Elements[Idx] is an empty parameter pack expansion, we should erase the
362325 // comma we just printed.
......@@ -494,7 +457,7 @@ class PostfixQualifiedType final : public Node {
494457 const StringView Postfix;
495458
496459public:
497 PostfixQualifiedType(Node *Ty_, StringView Postfix_)
460 PostfixQualifiedType(const Node *Ty_, StringView Postfix_)
498461 : Node(KPostfixQualifiedType), Ty(Ty_), Postfix(Postfix_) {}
499462
500463 template<typename Fn> void match(Fn F) const { F(Ty, Postfix); }
......@@ -519,6 +482,26 @@ public:
519482 void printLeft(OutputBuffer &OB) const override { OB += Name; }
520483};
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
522505class ElaboratedTypeSpefType : public Node {
523506 StringView Kind;
524507 Node *Child;
......@@ -693,7 +676,7 @@ public:
693676 void printLeft(OutputBuffer &OB) const override {
694677 if (Printing)
695678 return;
696 SwapAndRestore<bool> SavePrinting(Printing, true);
679 ScopedOverride<bool> SavePrinting(Printing, true);
697680 std::pair<ReferenceKind, const Node *> Collapsed = collapse(OB);
698681 if (!Collapsed.second)
699682 return;
......@@ -708,7 +691,7 @@ public:
708691 void printRight(OutputBuffer &OB) const override {
709692 if (Printing)
710693 return;
711 SwapAndRestore<bool> SavePrinting(Printing, true);
694 ScopedOverride<bool> SavePrinting(Printing, true);
712695 std::pair<ReferenceKind, const Node *> Collapsed = collapse(OB);
713696 if (!Collapsed.second)
714697 return;
......@@ -815,9 +798,9 @@ public:
815798 }
816799
817800 void printRight(OutputBuffer &OB) const override {
818 OB += "(";
801 OB.printOpen();
819802 Params.printWithComma(OB);
820 OB += ")";
803 OB.printClose();
821804 Ret->printRight(OB);
822805
823806 if (CVQuals & QualConst)
......@@ -847,9 +830,10 @@ public:
847830 template<typename Fn> void match(Fn F) const { F(E); }
848831
849832 void printLeft(OutputBuffer &OB) const override {
850 OB += "noexcept(";
851 E->print(OB);
852 OB += ")";
833 OB += "noexcept";
834 OB.printOpen();
835 E->printAsOperand(OB);
836 OB.printClose();
853837 }
854838};
855839
......@@ -862,9 +846,10 @@ public:
862846 template<typename Fn> void match(Fn F) const { F(Types); }
863847
864848 void printLeft(OutputBuffer &OB) const override {
865 OB += "throw(";
849 OB += "throw";
850 OB.printOpen();
866851 Types.printWithComma(OB);
867 OB += ')';
852 OB.printClose();
868853 }
869854};
870855
......@@ -910,9 +895,9 @@ public:
910895 }
911896
912897 void printRight(OutputBuffer &OB) const override {
913 OB += "(";
898 OB.printOpen();
914899 Params.printWithComma(OB);
915 OB += ")";
900 OB.printClose();
916901 if (Ret)
917902 Ret->printRight(OB);
918903
......@@ -1001,6 +986,46 @@ struct NestedName : Node {
1001986 }
1002987};
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
10041029struct LocalName : Node {
10051030 Node *Encoding;
10061031 Node *Entity;
......@@ -1042,9 +1067,8 @@ class VectorType final : public Node {
10421067 const Node *Dimension;
10431068
10441069public:
1045 VectorType(const Node *BaseType_, Node *Dimension_)
1046 : Node(KVectorType), BaseType(BaseType_),
1047 Dimension(Dimension_) {}
1070 VectorType(const Node *BaseType_, const Node *Dimension_)
1071 : Node(KVectorType), BaseType(BaseType_), Dimension(Dimension_) {}
10481072
10491073 template<typename Fn> void match(Fn F) const { F(BaseType, Dimension); }
10501074
......@@ -1176,6 +1200,7 @@ public:
11761200 template<typename Fn> void match(Fn F) const { F(Name, Params); }
11771201
11781202 void printLeft(OutputBuffer &OB) const override {
1203 ScopedOverride<unsigned> LT(OB.GtIsGt, 0);
11791204 OB += "template<";
11801205 Params.printWithComma(OB);
11811206 OB += "> typename ";
......@@ -1311,8 +1336,8 @@ public:
13111336
13121337 void printLeft(OutputBuffer &OB) const override {
13131338 constexpr unsigned Max = std::numeric_limits<unsigned>::max();
1314 SwapAndRestore<unsigned> SavePackIdx(OB.CurrentPackIndex, Max);
1315 SwapAndRestore<unsigned> SavePackMax(OB.CurrentPackMax, Max);
1339 ScopedOverride<unsigned> SavePackIdx(OB.CurrentPackIndex, Max);
1340 ScopedOverride<unsigned> SavePackMax(OB.CurrentPackMax, Max);
13161341 size_t StreamPos = OB.getCurrentPosition();
13171342
13181343 // Print the first element in the pack. If Child contains a ParameterPack,
......@@ -1353,10 +1378,9 @@ public:
13531378 NodeArray getParams() { return Params; }
13541379
13551380 void printLeft(OutputBuffer &OB) const override {
1381 ScopedOverride<unsigned> LT(OB.GtIsGt, 0);
13561382 OB += "<";
13571383 Params.printWithComma(OB);
1358 if (OB.back() == '>')
1359 OB += " ";
13601384 OB += ">";
13611385 }
13621386};
......@@ -1402,38 +1426,38 @@ struct ForwardTemplateReference : Node {
14021426 bool hasRHSComponentSlow(OutputBuffer &OB) const override {
14031427 if (Printing)
14041428 return false;
1405 SwapAndRestore<bool> SavePrinting(Printing, true);
1429 ScopedOverride<bool> SavePrinting(Printing, true);
14061430 return Ref->hasRHSComponent(OB);
14071431 }
14081432 bool hasArraySlow(OutputBuffer &OB) const override {
14091433 if (Printing)
14101434 return false;
1411 SwapAndRestore<bool> SavePrinting(Printing, true);
1435 ScopedOverride<bool> SavePrinting(Printing, true);
14121436 return Ref->hasArray(OB);
14131437 }
14141438 bool hasFunctionSlow(OutputBuffer &OB) const override {
14151439 if (Printing)
14161440 return false;
1417 SwapAndRestore<bool> SavePrinting(Printing, true);
1441 ScopedOverride<bool> SavePrinting(Printing, true);
14181442 return Ref->hasFunction(OB);
14191443 }
14201444 const Node *getSyntaxNode(OutputBuffer &OB) const override {
14211445 if (Printing)
14221446 return this;
1423 SwapAndRestore<bool> SavePrinting(Printing, true);
1447 ScopedOverride<bool> SavePrinting(Printing, true);
14241448 return Ref->getSyntaxNode(OB);
14251449 }
14261450
14271451 void printLeft(OutputBuffer &OB) const override {
14281452 if (Printing)
14291453 return;
1430 SwapAndRestore<bool> SavePrinting(Printing, true);
1454 ScopedOverride<bool> SavePrinting(Printing, true);
14311455 Ref->printLeft(OB);
14321456 }
14331457 void printRight(OutputBuffer &OB) const override {
14341458 if (Printing)
14351459 return;
1436 SwapAndRestore<bool> SavePrinting(Printing, true);
1460 ScopedOverride<bool> SavePrinting(Printing, true);
14371461 Ref->printRight(OB);
14381462 }
14391463};
......@@ -1473,21 +1497,6 @@ public:
14731497 }
14741498};
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
14911500enum class SpecialSubKind {
14921501 allocator,
14931502 basic_string,
......@@ -1497,15 +1506,25 @@ enum class SpecialSubKind {
14971506 iostream,
14981507};
14991508
1500class ExpandedSpecialSubstitution final : public Node {
1509class SpecialSubstitution;
1510class ExpandedSpecialSubstitution : public Node {
1511protected:
15011512 SpecialSubKind SSK;
15021513
1514 ExpandedSpecialSubstitution(SpecialSubKind SSK_, Kind K_)
1515 : Node(K_), SSK(SSK_) {}
15031516public:
15041517 ExpandedSpecialSubstitution(SpecialSubKind SSK_)
1505 : Node(KExpandedSpecialSubstitution), SSK(SSK_) {}
1518 : ExpandedSpecialSubstitution(SSK_, KExpandedSpecialSubstitution) {}
1519 inline ExpandedSpecialSubstitution(SpecialSubstitution const *);
15061520
15071521 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
15091528 StringView getBaseName() const override {
15101529 switch (SSK) {
15111530 case SpecialSubKind::allocator:
......@@ -1524,82 +1543,44 @@ public:
15241543 DEMANGLE_UNREACHABLE;
15251544 }
15261545
1546private:
15271547 void printLeft(OutputBuffer &OB) const override {
1528 switch (SSK) {
1529 case SpecialSubKind::allocator:
1530 OB += "std::allocator";
1531 break;
1532 case SpecialSubKind::basic_string:
1533 OB += "std::basic_string";
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 OB << "std::" << getBaseName();
1549 if (isInstantiation()) {
1550 OB << "<char, std::char_traits<char>";
1551 if (SSK == SpecialSubKind::string)
1552 OB << ", std::allocator<char>";
1553 OB << ">";
15481554 }
15491555 }
15501556};
15511557
1552class SpecialSubstitution final : public Node {
1558class SpecialSubstitution final : public ExpandedSpecialSubstitution {
15531559public:
1554 SpecialSubKind SSK;
1555
15561560 SpecialSubstitution(SpecialSubKind SSK_)
1557 : Node(KSpecialSubstitution), SSK(SSK_) {}
1561 : ExpandedSpecialSubstitution(SSK_, KSpecialSubstitution) {}
15581562
15591563 template<typename Fn> void match(Fn F) const { F(SSK); }
15601564
15611565 StringView getBaseName() const override {
1562 switch (SSK) {
1563 case SpecialSubKind::allocator:
1564 return StringView("allocator");
1565 case SpecialSubKind::basic_string:
1566 return StringView("basic_string");
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");
1566 auto SV = ExpandedSpecialSubstitution::getBaseName ();
1567 if (isInstantiation()) {
1568 // The instantiations are typedefs that drop the "basic_" prefix.
1569 assert(SV.startsWith("basic_"));
1570 SV = SV.dropFront(sizeof("basic_") - 1);
15751571 }
1576 DEMANGLE_UNREACHABLE;
1572 return SV;
15771573 }
15781574
15791575 void printLeft(OutputBuffer &OB) const override {
1580 switch (SSK) {
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 }
1576 OB << "std::" << getBaseName();
16001577 }
16011578};
16021579
1580inline ExpandedSpecialSubstitution::ExpandedSpecialSubstitution(
1581 SpecialSubstitution const *SS)
1582 : ExpandedSpecialSubstitution(SS->SSK) {}
1583
16031584class CtorDtorName final : public Node {
16041585 const Node *Basename;
16051586 const bool IsDtor;
......@@ -1665,13 +1646,14 @@ public:
16651646
16661647 void printDeclarator(OutputBuffer &OB) const {
16671648 if (!TemplateParams.empty()) {
1649 ScopedOverride<unsigned> LT(OB.GtIsGt, 0);
16681650 OB += "<";
16691651 TemplateParams.printWithComma(OB);
16701652 OB += ">";
16711653 }
1672 OB += "(";
1654 OB.printOpen();
16731655 Params.printWithComma(OB);
1674 OB += ")";
1656 OB.printClose();
16751657 }
16761658
16771659 void printLeft(OutputBuffer &OB) const override {
......@@ -1691,9 +1673,9 @@ public:
16911673 template<typename Fn> void match(Fn F) const { F(Bindings); }
16921674
16931675 void printLeft(OutputBuffer &OB) const override {
1694 OB += '[';
1676 OB.printOpen('[');
16951677 Bindings.printWithComma(OB);
1696 OB += ']';
1678 OB.printClose(']');
16971679 }
16981680};
16991681
......@@ -1705,28 +1687,31 @@ class BinaryExpr : public Node {
17051687 const Node *RHS;
17061688
17071689public:
1708 BinaryExpr(const Node *LHS_, StringView InfixOperator_, const Node *RHS_)
1709 : Node(KBinaryExpr), LHS(LHS_), InfixOperator(InfixOperator_), RHS(RHS_) {
1710 }
1690 BinaryExpr(const Node *LHS_, StringView InfixOperator_, const Node *RHS_,
1691 Prec Prec_)
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
17141699 void printLeft(OutputBuffer &OB) const override {
1715 // might be a template argument expression, then we need to disambiguate
1716 // with parens.
1717 if (InfixOperator == ">")
1718 OB += "(";
1719
1720 OB += "(";
1721 LHS->print(OB);
1722 OB += ") ";
1700 bool ParenAll = OB.isGtInsideTemplateArgs() &&
1701 (InfixOperator == ">" || InfixOperator == ">>");
1702 if (ParenAll)
1703 OB.printOpen();
1704 // Assignment is right associative, with special LHS precedence.
1705 bool IsAssign = getPrecedence() == Prec::Assign;
1706 LHS->printAsOperand(OB, IsAssign ? Prec::OrIf : getPrecedence(), !IsAssign);
1707 // No space before comma operator
1708 if (!(InfixOperator == ","))
1709 OB += " ";
17231710 OB += InfixOperator;
1724 OB += " (";
1725 RHS->print(OB);
1726 OB += ")";
1727
1728 if (InfixOperator == ">")
1729 OB += ")";
1711 OB += " ";
1712 RHS->printAsOperand(OB, getPrecedence(), IsAssign);
1713 if (ParenAll)
1714 OB.printClose();
17301715 }
17311716};
17321717
......@@ -1735,17 +1720,18 @@ class ArraySubscriptExpr : public Node {
17351720 const Node *Op2;
17361721
17371722public:
1738 ArraySubscriptExpr(const Node *Op1_, const Node *Op2_)
1739 : Node(KArraySubscriptExpr), Op1(Op1_), Op2(Op2_) {}
1723 ArraySubscriptExpr(const Node *Op1_, const Node *Op2_, Prec Prec_)
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
17431730 void printLeft(OutputBuffer &OB) const override {
1744 OB += "(";
1745 Op1->print(OB);
1746 OB += ")[";
1747 Op2->print(OB);
1748 OB += "]";
1731 Op1->printAsOperand(OB, getPrecedence());
1732 OB.printOpen('[');
1733 Op2->printAsOperand(OB);
1734 OB.printClose(']');
17491735 }
17501736};
17511737
......@@ -1754,15 +1740,15 @@ class PostfixExpr : public Node {
17541740 const StringView Operator;
17551741
17561742public:
1757 PostfixExpr(const Node *Child_, StringView Operator_)
1758 : Node(KPostfixExpr), Child(Child_), Operator(Operator_) {}
1743 PostfixExpr(const Node *Child_, StringView Operator_, Prec Prec_)
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
17621750 void printLeft(OutputBuffer &OB) const override {
1763 OB += "(";
1764 Child->print(OB);
1765 OB += ")";
1751 Child->printAsOperand(OB, getPrecedence(), true);
17661752 OB += Operator;
17671753 }
17681754};
......@@ -1773,19 +1759,20 @@ class ConditionalExpr : public Node {
17731759 const Node *Else;
17741760
17751761public:
1776 ConditionalExpr(const Node *Cond_, const Node *Then_, const Node *Else_)
1777 : Node(KConditionalExpr), Cond(Cond_), Then(Then_), Else(Else_) {}
1762 ConditionalExpr(const Node *Cond_, const Node *Then_, const Node *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
17811770 void printLeft(OutputBuffer &OB) const override {
1782 OB += "(";
1783 Cond->print(OB);
1784 OB += ") ? (";
1785 Then->print(OB);
1786 OB += ") : (";
1787 Else->print(OB);
1788 OB += ")";
1771 Cond->printAsOperand(OB, getPrecedence());
1772 OB += " ? ";
1773 Then->printAsOperand(OB);
1774 OB += " : ";
1775 Else->printAsOperand(OB, Prec::Assign, true);
17891776 }
17901777};
17911778
......@@ -1795,15 +1782,17 @@ class MemberExpr : public Node {
17951782 const Node *RHS;
17961783
17971784public:
1798 MemberExpr(const Node *LHS_, StringView Kind_, const Node *RHS_)
1799 : Node(KMemberExpr), LHS(LHS_), Kind(Kind_), RHS(RHS_) {}
1785 MemberExpr(const Node *LHS_, StringView Kind_, const Node *RHS_, Prec Prec_)
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
18031792 void printLeft(OutputBuffer &OB) const override {
1804 LHS->print(OB);
1793 LHS->printAsOperand(OB, getPrecedence(), true);
18051794 OB += Kind;
1806 RHS->print(OB);
1795 RHS->printAsOperand(OB, getPrecedence(), false);
18071796 }
18081797};
18091798
......@@ -1847,15 +1836,19 @@ class EnclosingExpr : public Node {
18471836 const StringView Postfix;
18481837
18491838public:
1850 EnclosingExpr(StringView Prefix_, Node *Infix_, StringView Postfix_)
1851 : Node(KEnclosingExpr), Prefix(Prefix_), Infix(Infix_),
1852 Postfix(Postfix_) {}
1839 EnclosingExpr(StringView Prefix_, const Node *Infix_,
1840 Prec Prec_ = Prec::Primary)
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
18561847 void printLeft(OutputBuffer &OB) const override {
18571848 OB += Prefix;
1849 OB.printOpen();
18581850 Infix->print(OB);
1851 OB.printClose();
18591852 OB += Postfix;
18601853 }
18611854};
......@@ -1867,18 +1860,24 @@ class CastExpr : public Node {
18671860 const Node *From;
18681861
18691862public:
1870 CastExpr(StringView CastKind_, const Node *To_, const Node *From_)
1871 : Node(KCastExpr), CastKind(CastKind_), To(To_), From(From_) {}
1863 CastExpr(StringView CastKind_, const Node *To_, const Node *From_, Prec Prec_)
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
18751870 void printLeft(OutputBuffer &OB) const override {
18761871 OB += CastKind;
1877 OB += "<";
1878 To->printLeft(OB);
1879 OB += ">(";
1880 From->printLeft(OB);
1881 OB += ")";
1872 {
1873 ScopedOverride<unsigned> LT(OB.GtIsGt, 0);
1874 OB += "<";
1875 To->printLeft(OB);
1876 OB += ">";
1877 }
1878 OB.printOpen();
1879 From->printAsOperand(OB);
1880 OB.printClose();
18821881 }
18831882};
18841883
......@@ -1892,10 +1891,11 @@ public:
18921891 template<typename Fn> void match(Fn F) const { F(Pack); }
18931892
18941893 void printLeft(OutputBuffer &OB) const override {
1895 OB += "sizeof...(";
1894 OB += "sizeof...";
1895 OB.printOpen();
18961896 ParameterPackExpansion PPE(Pack);
18971897 PPE.printLeft(OB);
1898 OB += ")";
1898 OB.printClose();
18991899 }
19001900};
19011901
......@@ -1904,16 +1904,18 @@ class CallExpr : public Node {
19041904 NodeArray Args;
19051905
19061906public:
1907 CallExpr(const Node *Callee_, NodeArray Args_)
1908 : Node(KCallExpr), Callee(Callee_), Args(Args_) {}
1907 CallExpr(const Node *Callee_, NodeArray Args_, Prec Prec_)
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
19121914 void printLeft(OutputBuffer &OB) const override {
19131915 Callee->print(OB);
1914 OB += "(";
1916 OB.printOpen();
19151917 Args.printWithComma(OB);
1916 OB += ")";
1918 OB.printClose();
19171919 }
19181920};
19191921
......@@ -1926,31 +1928,31 @@ class NewExpr : public Node {
19261928 bool IsArray; // new[] ?
19271929public:
19281930 NewExpr(NodeArray ExprList_, Node *Type_, NodeArray InitList_, bool IsGlobal_,
1929 bool IsArray_)
1930 : Node(KNewExpr), ExprList(ExprList_), Type(Type_), InitList(InitList_),
1931 IsGlobal(IsGlobal_), IsArray(IsArray_) {}
1931 bool IsArray_, Prec Prec_)
1932 : Node(KNewExpr, Prec_), ExprList(ExprList_), Type(Type_),
1933 InitList(InitList_), IsGlobal(IsGlobal_), IsArray(IsArray_) {}
19321934
19331935 template<typename Fn> void match(Fn F) const {
1934 F(ExprList, Type, InitList, IsGlobal, IsArray);
1936 F(ExprList, Type, InitList, IsGlobal, IsArray, getPrecedence());
19351937 }
19361938
19371939 void printLeft(OutputBuffer &OB) const override {
19381940 if (IsGlobal)
1939 OB += "::operator ";
1941 OB += "::";
19401942 OB += "new";
19411943 if (IsArray)
19421944 OB += "[]";
1943 OB += ' ';
19441945 if (!ExprList.empty()) {
1945 OB += "(";
1946 OB.printOpen();
19461947 ExprList.printWithComma(OB);
1947 OB += ")";
1948 OB.printClose();
19481949 }
1950 OB += " ";
19491951 Type->print(OB);
19501952 if (!InitList.empty()) {
1951 OB += "(";
1953 OB.printOpen();
19521954 InitList.printWithComma(OB);
1953 OB += ")";
1955 OB.printClose();
19541956 }
19551957 }
19561958};
......@@ -1961,17 +1963,21 @@ class DeleteExpr : public Node {
19611963 bool IsArray;
19621964
19631965public:
1964 DeleteExpr(Node *Op_, bool IsGlobal_, bool IsArray_)
1965 : Node(KDeleteExpr), Op(Op_), IsGlobal(IsGlobal_), IsArray(IsArray_) {}
1966 DeleteExpr(Node *Op_, bool IsGlobal_, bool IsArray_, Prec Prec_)
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
19691974 void printLeft(OutputBuffer &OB) const override {
19701975 if (IsGlobal)
19711976 OB += "::";
19721977 OB += "delete";
19731978 if (IsArray)
1974 OB += "[] ";
1979 OB += "[]";
1980 OB += ' ';
19751981 Op->print(OB);
19761982 }
19771983};
......@@ -1981,16 +1987,16 @@ class PrefixExpr : public Node {
19811987 Node *Child;
19821988
19831989public:
1984 PrefixExpr(StringView Prefix_, Node *Child_)
1985 : Node(KPrefixExpr), Prefix(Prefix_), Child(Child_) {}
1990 PrefixExpr(StringView Prefix_, Node *Child_, Prec Prec_)
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
19891997 void printLeft(OutputBuffer &OB) const override {
19901998 OB += Prefix;
1991 OB += "(";
1992 Child->print(OB);
1993 OB += ")";
1999 Child->printAsOperand(OB, getPrecedence());
19942000 }
19952001};
19962002
......@@ -2013,17 +2019,20 @@ class ConversionExpr : public Node {
20132019 NodeArray Expressions;
20142020
20152021public:
2016 ConversionExpr(const Node *Type_, NodeArray Expressions_)
2017 : Node(KConversionExpr), Type(Type_), Expressions(Expressions_) {}
2022 ConversionExpr(const Node *Type_, NodeArray Expressions_, Prec Prec_)
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
20212029 void printLeft(OutputBuffer &OB) const override {
2022 OB += "(";
2030 OB.printOpen();
20232031 Type->print(OB);
2024 OB += ")(";
2032 OB.printClose();
2033 OB.printOpen();
20252034 Expressions.printWithComma(OB);
2026 OB += ")";
2035 OB.printClose();
20272036 }
20282037};
20292038
......@@ -2034,18 +2043,21 @@ class PointerToMemberConversionExpr : public Node {
20342043
20352044public:
20362045 PointerToMemberConversionExpr(const Node *Type_, const Node *SubExpr_,
2037 StringView Offset_)
2038 : Node(KPointerToMemberConversionExpr), Type(Type_), SubExpr(SubExpr_),
2039 Offset(Offset_) {}
2046 StringView Offset_, Prec Prec_)
2047 : Node(KPointerToMemberConversionExpr, Prec_), Type(Type_),
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
20432054 void printLeft(OutputBuffer &OB) const override {
2044 OB += "(";
2055 OB.printOpen();
20452056 Type->print(OB);
2046 OB += ")(";
2057 OB.printClose();
2058 OB.printOpen();
20472059 SubExpr->print(OB);
2048 OB += ")";
2060 OB.printClose();
20492061 }
20502062};
20512063
......@@ -2131,41 +2143,33 @@ public:
21312143
21322144 void printLeft(OutputBuffer &OB) const override {
21332145 auto PrintPack = [&] {
2134 OB += '(';
2146 OB.printOpen();
21352147 ParameterPackExpansion(Pack).print(OB);
2136 OB += ')';
2148 OB.printClose();
21372149 };
21382150
2139 OB += '(';
2140
2141 if (IsLeftFold) {
2142 // init op ... op pack
2143 if (Init != nullptr) {
2144 Init->print(OB);
2145 OB += ' ';
2146 OB += OperatorName;
2147 OB += ' ';
2148 }
2149 // ... op pack
2150 OB += "... ";
2151 OB += OperatorName;
2152 OB += ' ';
2153 PrintPack();
2154 } else { // !IsLeftFold
2155 // pack op ...
2156 PrintPack();
2157 OB += ' ';
2158 OB += OperatorName;
2159 OB += " ...";
2160 // pack op ... op init
2161 if (Init != nullptr) {
2162 OB += ' ';
2163 OB += OperatorName;
2164 OB += ' ';
2165 Init->print(OB);
2166 }
2151 OB.printOpen();
2152 // Either '[init op ]... op pack' or 'pack op ...[ op init]'
2153 // Refactored to '[(init|pack) op ]...[ op (pack|init)]'
2154 // Fold expr operands are cast-expressions
2155 if (!IsLeftFold || Init != nullptr) {
2156 // '(init|pack) op '
2157 if (IsLeftFold)
2158 Init->printAsOperand(OB, Prec::Cast, true);
2159 else
2160 PrintPack();
2161 OB << " " << OperatorName << " ";
2162 }
2163 OB << "...";
2164 if (IsLeftFold || Init != nullptr) {
2165 // ' op (init|pack)'
2166 OB << " " << OperatorName << " ";
2167 if (IsLeftFold)
2168 PrintPack();
2169 else
2170 Init->printAsOperand(OB, Prec::Cast, true);
21672171 }
2168 OB += ')';
2172 OB.printClose();
21692173 }
21702174};
21712175
......@@ -2239,9 +2243,9 @@ public:
22392243 template<typename Fn> void match(Fn F) const { F(Ty, Integer); }
22402244
22412245 void printLeft(OutputBuffer &OB) const override {
2242 OB << "(";
2246 OB.printOpen();
22432247 Ty->print(OB);
2244 OB << ")";
2248 OB.printClose();
22452249
22462250 if (Integer[0] == 'n')
22472251 OB << "-" << Integer.dropFront(1);
......@@ -2262,13 +2266,13 @@ public:
22622266
22632267 void printLeft(OutputBuffer &OB) const override {
22642268 if (Type.size() > 3) {
2265 OB += "(";
2269 OB.printOpen();
22662270 OB += Type;
2267 OB += ")";
2271 OB.printClose();
22682272 }
22692273
22702274 if (Value[0] == 'n') {
2271 OB += "-";
2275 OB += '-';
22722276 OB += Value.dropFront(1);
22732277 } else
22742278 OB += Value;
......@@ -2344,24 +2348,22 @@ using LongDoubleLiteral = FloatLiteralImpl<long double>;
23442348template<typename Fn>
23452349void Node::visit(Fn F) const {
23462350 switch (K) {
2347#define CASE(X) case K ## X: return F(static_cast<const X*>(this));
2348 FOR_EACH_NODE_KIND(CASE)
2349#undef CASE
2351#define NODE(X) \
2352 case K##X: \
2353 return F(static_cast<const X *>(this));
2354#include "ItaniumNodes.def"
23502355 }
23512356 assert(0 && "unknown mangling node kind");
23522357}
23532358
23542359/// Determine the kind of a node from its type.
23552360template<typename NodeT> struct NodeKind;
2356#define SPECIALIZATION(X) \
2357 template<> struct NodeKind<X> { \
2358 static constexpr Node::Kind Kind = Node::K##X; \
2359 static constexpr const char *name() { return #X; } \
2361#define NODE(X) \
2362 template <> struct NodeKind<X> { \
2363 static constexpr Node::Kind Kind = Node::K##X; \
2364 static constexpr const char *name() { return #X; } \
23602365 };
2361FOR_EACH_NODE_KIND(SPECIALIZATION)
2362#undef SPECIALIZATION
2363
2364#undef FOR_EACH_NODE_KIND
2366#include "ItaniumNodes.def"
23652367
23662368template <typename Derived, typename Alloc> struct AbstractManglingParser {
23672369 const char *First;
......@@ -2499,17 +2501,16 @@ template <typename Derived, typename Alloc> struct AbstractManglingParser {
24992501
25002502 /// Parse the <expr> production.
25012503 Node *parseExpr();
2502 Node *parsePrefixExpr(StringView Kind);
2503 Node *parseBinaryExpr(StringView Kind);
2504 Node *parsePrefixExpr(StringView Kind, Node::Prec Prec);
2505 Node *parseBinaryExpr(StringView Kind, Node::Prec Prec);
25042506 Node *parseIntegerLiteral(StringView Lit);
25052507 Node *parseExprPrimary();
25062508 template <class Float> Node *parseFloatingLiteral();
25072509 Node *parseFunctionParam();
2508 Node *parseNewExpr();
25092510 Node *parseConversionExpr();
25102511 Node *parseBracedExpr();
25112512 Node *parseFoldExpr();
2512 Node *parsePointerToMemberConversionExpr();
2513 Node *parsePointerToMemberConversionExpr(Node::Prec Prec);
25132514 Node *parseSubobjectExpr();
25142515
25152516 /// Parse the <type> production.
......@@ -2557,17 +2558,80 @@ template <typename Derived, typename Alloc> struct AbstractManglingParser {
25572558 Node *parseName(NameState *State = nullptr);
25582559 Node *parseLocalName(NameState *State);
25592560 Node *parseOperatorName(NameState *State);
2560 Node *parseUnqualifiedName(NameState *State);
2561 bool parseModuleNameOpt(ModuleName *&Module);
2562 Node *parseUnqualifiedName(NameState *State, Node *Scope, ModuleName *Module);
25612563 Node *parseUnnamedTypeName(NameState *State);
25622564 Node *parseSourceName(NameState *State);
2563 Node *parseUnscopedName(NameState *State);
2565 Node *parseUnscopedName(NameState *State, bool *isSubstName);
25642566 Node *parseNestedName(NameState *State);
25652567 Node *parseCtorDtorName(Node *&SoFar, NameState *State);
25662568
25672569 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
25692633 /// Parse the <unresolved-name> production.
2570 Node *parseUnresolvedName();
2634 Node *parseUnresolvedName(bool Global);
25712635 Node *parseSimpleId();
25722636 Node *parseBaseUnresolvedName();
25732637 Node *parseUnresolvedType();
......@@ -2588,26 +2652,16 @@ const char* parse_discriminator(const char* first, const char* last);
25882652// ::= <substitution>
25892653template <typename Derived, typename Alloc>
25902654Node *AbstractManglingParser<Derived, Alloc>::parseName(NameState *State) {
2591 consumeIf('L'); // extension
2592
25932655 if (look() == 'N')
25942656 return getDerived().parseNestedName(State);
25952657 if (look() == 'Z')
25962658 return getDerived().parseLocalName(State);
25972659
25982660 Node *Result = nullptr;
2599 bool IsSubst = look() == 'S' && look(1) != 't';
2600 if (IsSubst) {
2601 // A substitution must lead to:
2602 // ::= <unscoped-template-name> <template-args>
2603 Result = getDerived().parseSubstitution();
2604 } else {
2605 // An unscoped name can be one of:
2606 // ::= <unscoped-name>
2607 // ::= <unscoped-template-name> <template-args>
2608 Result = getDerived().parseUnscopedName(State);
2609 }
2610 if (Result == nullptr)
2661 bool IsSubst = false;
2662
2663 Result = getDerived().parseUnscopedName(State, &IsSubst);
2664 if (!Result)
26112665 return nullptr;
26122666
26132667 if (look() == 'I') {
......@@ -2667,38 +2721,63 @@ Node *AbstractManglingParser<Derived, Alloc>::parseLocalName(NameState *State) {
26672721
26682722// <unscoped-name> ::= <unqualified-name>
26692723// ::= St <unqualified-name> # ::std::
2670// extension ::= StL<unqualified-name>
2724// [*] extension
26712725template <typename Derived, typename Alloc>
26722726Node *
2673AbstractManglingParser<Derived, Alloc>::parseUnscopedName(NameState *State) {
2674 bool IsStd = consumeIf("St");
2675 if (IsStd)
2676 consumeIf('L');
2727AbstractManglingParser<Derived, Alloc>::parseUnscopedName(NameState *State,
2728 bool *IsSubst) {
26772729
2678 Node *Result = getDerived().parseUnqualifiedName(State);
2679 if (Result == nullptr)
2680 return nullptr;
2681 if (IsStd)
2682 Result = make<StdQualifiedName>(Result);
2730 Node *Std = nullptr;
2731 if (consumeIf("St")) {
2732 Std = make<NameType>("std");
2733 if (Std == nullptr)
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;
26852758}
26862759
2687// <unqualified-name> ::= <operator-name> [abi-tags]
2688// ::= <ctor-dtor-name>
2689// ::= <source-name>
2690// ::= <unnamed-type-name>
2691// ::= DC <source-name>+ E # structured binding declaration
2760// <unqualified-name> ::= [<module-name>] L? <operator-name> [<abi-tags>]
2761// ::= [<module-name>] <ctor-dtor-name> [<abi-tags>]
2762// ::= [<module-name>] L? <source-name> [<abi-tags>]
2763// ::= [<module-name>] L? <unnamed-type-name> [<abi-tags>]
2764// # structured binding declaration
2765// ::= [<module-name>] L? DC <source-name>+ E
26922766template <typename Derived, typename Alloc>
2693Node *
2694AbstractManglingParser<Derived, Alloc>::parseUnqualifiedName(NameState *State) {
2695 // <ctor-dtor-name>s are special-cased in parseNestedName().
2767Node *AbstractManglingParser<Derived, Alloc>::parseUnqualifiedName(
2768 NameState *State, Node *Scope, ModuleName *Module) {
2769 if (getDerived().parseModuleNameOpt(Module))
2770 return nullptr;
2771
2772 consumeIf('L');
2773
26962774 Node *Result;
2697 if (look() == 'U')
2698 Result = getDerived().parseUnnamedTypeName(State);
2699 else if (look() >= '1' && look() <= '9')
2775 if (look() >= '1' && look() <= '9') {
27002776 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
27022781 size_t BindingsBegin = Names.size();
27032782 do {
27042783 Node *Binding = getDerived().parseSourceName(State);
......@@ -2707,13 +2786,46 @@ AbstractManglingParser<Derived, Alloc>::parseUnqualifiedName(NameState *State) {
27072786 Names.push_back(Binding);
27082787 } while (!consumeIf('E'));
27092788 Result = make<StructuredBindingName>(popTrailingNodeArray(BindingsBegin));
2710 } else
2789 } 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 {
27112795 Result = getDerived().parseOperatorName(State);
2796 }
2797
2798 if (Result != nullptr && Module != nullptr)
2799 Result = make<ModuleEntity>(Module, Result);
27122800 if (Result != nullptr)
27132801 Result = getDerived().parseAbiTags(Result);
2802 if (Result != nullptr && Scope != nullptr)
2803 Result = make<NestedName>(Scope, Result);
2804
27142805 return Result;
27152806}
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
27172829// <unnamed-type-name> ::= Ut [<nonnegative number>] _
27182830// ::= <closure-type-name>
27192831//
......@@ -2735,7 +2847,7 @@ AbstractManglingParser<Derived, Alloc>::parseUnnamedTypeName(NameState *State) {
27352847 return make<UnnamedTypeName>(Count);
27362848 }
27372849 if (consumeIf("Ul")) {
2738 SwapAndRestore<size_t> SwapParams(ParsingLambdaParamsAtLevel,
2850 ScopedOverride<size_t> SwapParams(ParsingLambdaParamsAtLevel,
27392851 TemplateParams.size());
27402852 ScopedTemplateParamList LambdaTemplateParams(this);
27412853
......@@ -2813,97 +2925,124 @@ Node *AbstractManglingParser<Derived, Alloc>::parseSourceName(NameState *) {
28132925 return make<NameType>(Name);
28142926}
28152927
2816// <operator-name> ::= aa # &&
2817// ::= ad # & (unary)
2818// ::= an # &
2819// ::= aN # &=
2820// ::= aS # =
2821// ::= cl # ()
2822// ::= cm # ,
2823// ::= co # ~
2824// ::= cv <type> # (cast)
2825// ::= da # delete[]
2826// ::= de # * (unary)
2827// ::= dl # delete
2828// ::= dv # /
2829// ::= dV # /=
2830// ::= eo # ^
2831// ::= eO # ^=
2832// ::= eq # ==
2833// ::= ge # >=
2834// ::= gt # >
2835// ::= ix # []
2836// ::= le # <=
2928// Operator encodings
2929template <typename Derived, typename Alloc>
2930const typename AbstractManglingParser<
2931 Derived, Alloc>::OperatorInfo AbstractManglingParser<Derived,
2932 Alloc>::Ops[] = {
2933 // Keep ordered by encoding
2934 {"aN", OperatorInfo::Binary, false, Node::Prec::Assign, "operator&="},
2935 {"aS", OperatorInfo::Binary, false, Node::Prec::Assign, "operator="},
2936 {"aa", OperatorInfo::Binary, false, Node::Prec::AndIf, "operator&&"},
2937 {"ad", OperatorInfo::Prefix, false, Node::Prec::Unary, "operator&"},
2938 {"an", OperatorInfo::Binary, false, Node::Prec::And, "operator&"},
2939 {"at", OperatorInfo::OfIdOp, /*Type*/ true, Node::Prec::Unary, "alignof "},
2940 {"aw", OperatorInfo::NameOnly, false, Node::Prec::Primary,
2941 "operator co_await"},
2942 {"az", OperatorInfo::OfIdOp, /*Type*/ false, Node::Prec::Unary, "alignof "},
2943 {"cc", OperatorInfo::NamedCast, false, Node::Prec::Postfix, "const_cast"},
2944 {"cl", OperatorInfo::Call, false, Node::Prec::Postfix, "operator()"},
2945 {"cm", OperatorInfo::Binary, false, Node::Prec::Comma, "operator,"},
2946 {"co", OperatorInfo::Prefix, false, Node::Prec::Unary, "operator~"},
2947 {"cv", OperatorInfo::CCast, false, Node::Prec::Cast, "operator"}, // C Cast
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()
28373033// ::= li <source-name> # operator ""
2838// ::= ls # <<
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
3034// ::= v <digit> <source-name> # vendor extended operator
28673035template <typename Derived, typename Alloc>
28683036Node *
28693037AbstractManglingParser<Derived, Alloc>::parseOperatorName(NameState *State) {
2870 switch (look()) {
2871 case 'a':
2872 switch (look(1)) {
2873 case 'a':
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);
3038 if (const auto *Op = parseOperatorEncoding()) {
3039 if (Op->getKind() == OperatorInfo::CCast) {
3040 // ::= cv <type> # (cast)
3041 ScopedOverride<bool> SaveTemplate(TryToParseTemplateArgs, false);
29033042 // If we're parsing an encoding, State != nullptr and the conversion
29043043 // operators' <type> could have a <template-param> that refers to some
29053044 // <template-arg>s further ahead in the mangled name.
2906 SwapAndRestore<bool> SavePermit(PermitForwardTemplateReferences,
3045 ScopedOverride<bool> SavePermit(PermitForwardTemplateReferences,
29073046 PermitForwardTemplateReferences ||
29083047 State != nullptr);
29093048 Node *Ty = getDerived().parseType();
......@@ -2912,185 +3051,29 @@ AbstractManglingParser<Derived, Alloc>::parseOperatorName(NameState *State) {
29123051 if (State) State->CtorDtorConversion = true;
29133052 return make<ConversionOperatorType>(Ty);
29143053 }
2915 }
2916 return nullptr;
2917 case 'd':
2918 switch (look(1)) {
2919 case 'a':
2920 First += 2;
2921 return make<NameType>("operator delete[]");
2922 case 'e':
2923 First += 2;
2924 return make<NameType>("operator*");
2925 case 'l':
2926 First += 2;
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<=");
3054
3055 if (Op->getKind() >= OperatorInfo::Unnameable)
3056 /* Not a nameable operator. */
3057 return nullptr;
3058 if (Op->getKind() == OperatorInfo::Member && !Op->getFlag())
3059 /* Not a nameable MemberExpr */
3060 return nullptr;
3061
3062 return make<NameType>(Op->getName());
3063 }
3064
3065 if (consumeIf("li")) {
29703066 // ::= li <source-name> # operator ""
2971 case 'i': {
2972 First += 2;
2973 Node *SN = getDerived().parseSourceName(State);
2974 if (SN == nullptr)
2975 return nullptr;
2976 return make<LiteralOperator>(SN);
2977 }
2978 case 's':
2979 First += 2;
2980 return make<NameType>("operator<<");
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;
3067 Node *SN = getDerived().parseSourceName(State);
3068 if (SN == nullptr)
3069 return nullptr;
3070 return make<LiteralOperator>(SN);
3071 }
3072
3073 if (consumeIf('v')) {
3074 // ::= v <digit> <source-name> # vendor extended operator
3075 if (look() >= '0' && look() <= '9') {
3076 First++;
30943077 Node *SN = getDerived().parseSourceName(State);
30953078 if (SN == nullptr)
30963079 return nullptr;
......@@ -3098,6 +3081,7 @@ AbstractManglingParser<Derived, Alloc>::parseOperatorName(NameState *State) {
30983081 }
30993082 return nullptr;
31003083 }
3084
31013085 return nullptr;
31023086}
31033087
......@@ -3116,19 +3100,11 @@ Node *
31163100AbstractManglingParser<Derived, Alloc>::parseCtorDtorName(Node *&SoFar,
31173101 NameState *State) {
31183102 if (SoFar->getKind() == Node::KSpecialSubstitution) {
3119 auto SSK = static_cast<SpecialSubstitution *>(SoFar)->SSK;
3120 switch (SSK) {
3121 case SpecialSubKind::string:
3122 case SpecialSubKind::istream:
3123 case SpecialSubKind::ostream:
3124 case SpecialSubKind::iostream:
3125 SoFar = make<ExpandedSpecialSubstitution>(SSK);
3126 if (!SoFar)
3127 return nullptr;
3128 break;
3129 default:
3130 break;
3131 }
3103 // Expand the special substitution.
3104 SoFar = make<ExpandedSpecialSubstitution>(
3105 static_cast<SpecialSubstitution *>(SoFar));
3106 if (!SoFar)
3107 return nullptr;
31323108 }
31333109
31343110 if (consumeIf('C')) {
......@@ -3157,8 +3133,10 @@ AbstractManglingParser<Derived, Alloc>::parseCtorDtorName(Node *&SoFar,
31573133 return nullptr;
31583134}
31593135
3160// <nested-name> ::= N [<CV-Qualifiers>] [<ref-qualifier>] <prefix> <unqualified-name> E
3161// ::= N [<CV-Qualifiers>] [<ref-qualifier>] <template-prefix> <template-args> E
3136// <nested-name> ::= N [<CV-Qualifiers>] [<ref-qualifier>] <prefix>
3137// <unqualified-name> E
3138// ::= N [<CV-Qualifiers>] [<ref-qualifier>] <template-prefix>
3139// <template-args> E
31623140//
31633141// <prefix> ::= <prefix> <unqualified-name>
31643142// ::= <template-prefix> <template-args>
......@@ -3167,7 +3145,7 @@ AbstractManglingParser<Derived, Alloc>::parseCtorDtorName(Node *&SoFar,
31673145// ::= # empty
31683146// ::= <substitution>
31693147// ::= <prefix> <data-member-prefix>
3170// extension ::= L
3148// [*] extension
31713149//
31723150// <data-member-prefix> := <member source-name> [<template-args>] M
31733151//
......@@ -3187,90 +3165,76 @@ AbstractManglingParser<Derived, Alloc>::parseNestedName(NameState *State) {
31873165 if (State) State->ReferenceQualifier = FrefQualRValue;
31883166 } else if (consumeIf('R')) {
31893167 if (State) State->ReferenceQualifier = FrefQualLValue;
3190 } else
3168 } else {
31913169 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;
32063170 }
32073171
3172 Node *SoFar = nullptr;
32083173 while (!consumeIf('E')) {
3209 consumeIf('L'); // extension
3210
3211 // <data-member-prefix> := <member source-name> [<template-args>] M
3212 if (consumeIf('M')) {
3213 if (SoFar == nullptr)
3214 return nullptr;
3215 continue;
3216 }
3174 if (State)
3175 // Only set end-with-template on the case that does that.
3176 State->EndsWithTemplateArgs = false;
32173177
3218 // ::= <template-param>
32193178 if (look() == 'T') {
3220 if (!PushComponent(getDerived().parseTemplateParam()))
3221 return nullptr;
3222 Subs.push_back(SoFar);
3223 continue;
3224 }
3225
3226 // ::= <template-prefix> <template-args>
3227 if (look() == 'I') {
3179 // ::= <template-param>
3180 if (SoFar != nullptr)
3181 return nullptr; // Cannot have a prefix.
3182 SoFar = getDerived().parseTemplateParam();
3183 } else if (look() == 'I') {
3184 // ::= <template-prefix> <template-args>
3185 if (SoFar == nullptr)
3186 return nullptr; // Must have a prefix.
32283187 Node *TA = getDerived().parseTemplateArgs(State != nullptr);
3229 if (TA == nullptr || SoFar == 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()))
3188 if (TA == nullptr)
32423189 return nullptr;
3243 Subs.push_back(SoFar);
3244 continue;
3245 }
3246
3247 // ::= <substitution>
3248 if (look() == 'S' && look(1) != 't') {
3249 Node *S = getDerived().parseSubstitution();
3250 if (!PushComponent(S))
3190 if (SoFar->getKind() == Node::KNameWithTemplateArgs)
3191 // Semantically <template-args> <template-args> cannot be generated by a
3192 // C++ entity. There will always be [something like] a name between
3193 // them.
32513194 return nullptr;
3252 if (SoFar != S)
3253 Subs.push_back(S);
3254 continue;
3255 }
3195 if (State)
3196 State->EndsWithTemplateArgs = true;
3197 SoFar = make<NameWithTemplateArgs>(SoFar, TA);
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>.
3258 if (look() == 'C' || (look() == 'D' && look(1) != 'C')) {
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;
3227 // ::= [<prefix>] <unqualified-name>
3228 SoFar = getDerived().parseUnqualifiedName(State, SoFar, Module);
32683229 }
32693230
3270 // ::= <prefix> <unqualified-name>
3271 if (!PushComponent(getDerived().parseUnqualifiedName(State)))
3231 if (SoFar == nullptr)
32723232 return nullptr;
32733233 Subs.push_back(SoFar);
3234
3235 // No longer used.
3236 // <data-member-prefix> := <member source-name> [<template-args>] M
3237 consumeIf('M');
32743238 }
32753239
32763240 if (SoFar == nullptr || Subs.empty())
......@@ -3365,6 +3329,7 @@ Node *AbstractManglingParser<Derived, Alloc>::parseBaseUnresolvedName() {
33653329// ::= [gs] <base-unresolved-name> # x or (with "gs") ::x
33663330// ::= [gs] sr <unresolved-qualifier-level>+ E <base-unresolved-name>
33673331// # A::x, N::y, A<T>::z; "gs" means leading "::"
3332// [gs] has been parsed by caller.
33683333// ::= sr <unresolved-type> <base-unresolved-name> # T::x / decltype(p)::x
33693334// extension ::= sr <unresolved-type> <template-args> <base-unresolved-name>
33703335// # T::N::x /decltype(p)::N::x
......@@ -3372,7 +3337,7 @@ Node *AbstractManglingParser<Derived, Alloc>::parseBaseUnresolvedName() {
33723337//
33733338// <unresolved-qualifier-level> ::= <simple-id>
33743339template <typename Derived, typename Alloc>
3375Node *AbstractManglingParser<Derived, Alloc>::parseUnresolvedName() {
3340Node *AbstractManglingParser<Derived, Alloc>::parseUnresolvedName(bool Global) {
33763341 Node *SoFar = nullptr;
33773342
33783343 // srN <unresolved-type> [<template-args>] <unresolved-qualifier-level>* E <base-unresolved-name>
......@@ -3406,8 +3371,6 @@ Node *AbstractManglingParser<Derived, Alloc>::parseUnresolvedName() {
34063371 return make<QualifiedName>(SoFar, Base);
34073372 }
34083373
3409 bool Global = consumeIf("gs");
3410
34113374 // [gs] <base-unresolved-name> # x or (with "gs") ::x
34123375 if (!consumeIf("sr")) {
34133376 SoFar = getDerived().parseBaseUnresolvedName();
......@@ -3637,7 +3600,7 @@ Node *AbstractManglingParser<Derived, Alloc>::parseDecltype() {
36373600 return nullptr;
36383601 if (!consumeIf('E'))
36393602 return nullptr;
3640 return make<EnclosingExpr>("decltype(", E, ")");
3603 return make<EnclosingExpr>("decltype", E);
36413604}
36423605
36433606// <array-type> ::= A <positive dimension number> _ <element type>
......@@ -3723,8 +3686,8 @@ Node *AbstractManglingParser<Derived, Alloc>::parseQualifiedType() {
37233686 StringView ProtoSourceName = Qual.dropFront(std::strlen("objcproto"));
37243687 StringView Proto;
37253688 {
3726 SwapAndRestore<const char *> SaveFirst(First, ProtoSourceName.begin()),
3727 SaveLast(Last, ProtoSourceName.end());
3689 ScopedOverride<const char *> SaveFirst(First, ProtoSourceName.begin()),
3690 SaveLast(Last, ProtoSourceName.end());
37283691 Proto = parseBareSourceName();
37293692 }
37303693 if (Proto.empty())
......@@ -3929,6 +3892,22 @@ Node *AbstractManglingParser<Derived, Alloc>::parseType() {
39293892 return nullptr;
39303893 return make<BinaryFPType>(DimensionNumber);
39313894 }
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 }
39323911 // ::= Di # char32_t
39333912 case 'i':
39343913 First += 2;
......@@ -4077,8 +4056,9 @@ Node *AbstractManglingParser<Derived, Alloc>::parseType() {
40774056 // ::= <substitution> # See Compression below
40784057 case 'S': {
40794058 if (look(1) != 't') {
4080 Result = getDerived().parseSubstitution();
4081 if (Result == nullptr)
4059 bool IsSubst = false;
4060 Result = getDerived().parseUnscopedName(nullptr, &IsSubst);
4061 if (!Result)
40824062 return nullptr;
40834063
40844064 // Sub could be either of:
......@@ -4091,12 +4071,14 @@ Node *AbstractManglingParser<Derived, Alloc>::parseType() {
40914071 // If this is followed by some <template-args>, and we're permitted to
40924072 // 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);
40954077 Node *TA = getDerived().parseTemplateArgs();
40964078 if (TA == nullptr)
40974079 return nullptr;
40984080 Result = make<NameWithTemplateArgs>(Result, TA);
4099 } else {
4081 } else if (IsSubst) {
41004082 // If all we parsed was a substitution, don't re-insert into the
41014083 // substitution table.
41024084 return Result;
......@@ -4121,22 +4103,24 @@ Node *AbstractManglingParser<Derived, Alloc>::parseType() {
41214103}
41224104
41234105template <typename Derived, typename Alloc>
4124Node *AbstractManglingParser<Derived, Alloc>::parsePrefixExpr(StringView Kind) {
4106Node *AbstractManglingParser<Derived, Alloc>::parsePrefixExpr(StringView Kind,
4107 Node::Prec Prec) {
41254108 Node *E = getDerived().parseExpr();
41264109 if (E == nullptr)
41274110 return nullptr;
4128 return make<PrefixExpr>(Kind, E);
4111 return make<PrefixExpr>(Kind, E, Prec);
41294112}
41304113
41314114template <typename Derived, typename Alloc>
4132Node *AbstractManglingParser<Derived, Alloc>::parseBinaryExpr(StringView Kind) {
4115Node *AbstractManglingParser<Derived, Alloc>::parseBinaryExpr(StringView Kind,
4116 Node::Prec Prec) {
41334117 Node *LHS = getDerived().parseExpr();
41344118 if (LHS == nullptr)
41354119 return nullptr;
41364120 Node *RHS = getDerived().parseExpr();
41374121 if (RHS == nullptr)
41384122 return nullptr;
4139 return make<BinaryExpr>(LHS, Kind, RHS);
4123 return make<BinaryExpr>(LHS, Kind, RHS, Prec);
41404124}
41414125
41424126template <typename Derived, typename Alloc>
......@@ -4191,43 +4175,6 @@ Node *AbstractManglingParser<Derived, Alloc>::parseFunctionParam() {
41914175 return nullptr;
41924176}
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
42314178// cv <type> <expression> # conversion with one argument
42324179// cv <type> _ <expression>* E # conversion with a different number of arguments
42334180template <typename Derived, typename Alloc>
......@@ -4236,7 +4183,7 @@ Node *AbstractManglingParser<Derived, Alloc>::parseConversionExpr() {
42364183 return nullptr;
42374184 Node *Ty;
42384185 {
4239 SwapAndRestore<bool> SaveTemp(TryToParseTemplateArgs, false);
4186 ScopedOverride<bool> SaveTemp(TryToParseTemplateArgs, false);
42404187 Ty = getDerived().parseType();
42414188 }
42424189
......@@ -4353,7 +4300,7 @@ Node *AbstractManglingParser<Derived, Alloc>::parseExprPrimary() {
43534300 return nullptr;
43544301 }
43554302 case 'D':
4356 if (consumeIf("DnE"))
4303 if (consumeIf("Dn") && (consumeIf('0'), consumeIf('E')))
43574304 return make<NameType>("nullptr");
43584305 return nullptr;
43594306 case 'T':
......@@ -4440,55 +4387,38 @@ Node *AbstractManglingParser<Derived, Alloc>::parseFoldExpr() {
44404387 if (!consumeIf('f'))
44414388 return nullptr;
44424389
4443 char FoldKind = look();
4444 bool IsLeftFold, HasInitializer;
4445 HasInitializer = FoldKind == 'L' || FoldKind == 'R';
4446 if (FoldKind == 'l' || FoldKind == 'L')
4447 IsLeftFold = true;
4448 else if (FoldKind == 'r' || FoldKind == 'R')
4449 IsLeftFold = false;
4450 else
4390 bool IsLeftFold = false, HasInitializer = false;
4391 switch (look()) {
4392 default:
44514393 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 }
44524407 ++First;
44534408
4454 // FIXME: This map is duplicated in parseOperatorName and parseExpr.
4455 StringView OperatorName;
4456 if (consumeIf("aa")) OperatorName = "&&";
4457 else if (consumeIf("an")) OperatorName = "&";
4458 else if (consumeIf("aN")) OperatorName = "&=";
4459 else if (consumeIf("aS")) OperatorName = "=";
4460 else if (consumeIf("cm")) OperatorName = ",";
4461 else if (consumeIf("ds")) OperatorName = ".*";
4462 else if (consumeIf("dv")) OperatorName = "/";
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;
4409 const auto *Op = parseOperatorEncoding();
4410 if (!Op)
4411 return nullptr;
4412 if (!(Op->getKind() == OperatorInfo::Binary
4413 || (Op->getKind() == OperatorInfo::Member
4414 && Op->getName().back() == '*')))
4415 return nullptr;
4416
4417 Node *Pack = getDerived().parseExpr();
44904418 if (Pack == nullptr)
44914419 return nullptr;
4420
4421 Node *Init = nullptr;
44924422 if (HasInitializer) {
44934423 Init = getDerived().parseExpr();
44944424 if (Init == nullptr)
......@@ -4498,14 +4428,16 @@ Node *AbstractManglingParser<Derived, Alloc>::parseFoldExpr() {
44984428 if (IsLeftFold && Init)
44994429 std::swap(Pack, Init);
45004430
4501 return make<FoldExpr>(IsLeftFold, OperatorName, Pack, Init);
4431 return make<FoldExpr>(IsLeftFold, Op->getSymbol(), Pack, Init);
45024432}
45034433
45044434// <expression> ::= mc <parameter type> <expr> [<offset number>] E
45054435//
45064436// Not yet in the spec: https://github.com/itanium-cxx-abi/cxx-abi/issues/47
45074437template <typename Derived, typename Alloc>
4508Node *AbstractManglingParser<Derived, Alloc>::parsePointerToMemberConversionExpr() {
4438Node *
4439AbstractManglingParser<Derived, Alloc>::parsePointerToMemberConversionExpr(
4440 Node::Prec Prec) {
45094441 Node *Ty = getDerived().parseType();
45104442 if (!Ty)
45114443 return nullptr;
......@@ -4515,7 +4447,7 @@ Node *AbstractManglingParser<Derived, Alloc>::parsePointerToMemberConversionExpr
45154447 StringView Offset = getDerived().parseNumber(true);
45164448 if (!consumeIf('E'))
45174449 return nullptr;
4518 return make<PointerToMemberConversionExpr>(Ty, Expr, Offset);
4450 return make<PointerToMemberConversionExpr>(Ty, Expr, Offset, Prec);
45194451}
45204452
45214453// <expression> ::= so <referent type> <expr> [<offset number>] <union-selector>* [p] E
......@@ -4592,316 +4524,127 @@ Node *AbstractManglingParser<Derived, Alloc>::parseSubobjectExpr() {
45924524template <typename Derived, typename Alloc>
45934525Node *AbstractManglingParser<Derived, Alloc>::parseExpr() {
45944526 bool Global = consumeIf("gs");
4595 if (numLeft() < 2)
4596 return nullptr;
45974527
4598 switch (*First) {
4599 case 'L':
4600 return getDerived().parseExprPrimary();
4601 case 'T':
4602 return getDerived().parseTemplateParam();
4603 case 'f': {
4604 // Disambiguate a fold expression from a <function-param>.
4605 if (look(1) == 'p' || (look(1) == 'L' && std::isdigit(look(2))))
4606 return getDerived().parseFunctionParam();
4607 return getDerived().parseFoldExpr();
4608 }
4609 case 'a':
4610 switch (First[1]) {
4611 case 'a':
4612 First += 2;
4613 return getDerived().parseBinaryExpr("&&");
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)
4528 const auto *Op = parseOperatorEncoding();
4529 if (Op) {
4530 auto Sym = Op->getSymbol();
4531 switch (Op->getKind()) {
4532 case OperatorInfo::Binary:
4533 // Binary operator: lhs @ rhs
4534 return getDerived().parseBinaryExpr(Sym, Op->getPrecedence());
4535 case OperatorInfo::Prefix:
4536 // Prefix unary operator: @ expr
4537 return getDerived().parsePrefixExpr(Sym, Op->getPrecedence());
4538 case OperatorInfo::Postfix: {
4539 // Postfix unary operator: expr @
4540 if (consumeIf('_'))
4541 return getDerived().parsePrefixExpr(Sym, Op->getPrecedence());
4542 Node *Ex = getDerived().parseExpr();
4543 if (Ex == nullptr)
46304544 return nullptr;
4631 return make<EnclosingExpr>("alignof (", Ty, ")");
4545 return make<PostfixExpr>(Ex, Sym, Op->getPrecedence());
46324546 }
4633 case 'z': {
4634 First += 2;
4635 Node *Ty = getDerived().parseExpr();
4636 if (Ty == nullptr)
4547 case OperatorInfo::Array: {
4548 // Array Index: lhs [ rhs ]
4549 Node *Base = getDerived().parseExpr();
4550 if (Base == nullptr)
46374551 return nullptr;
4638 return make<EnclosingExpr>("alignof (", Ty, ")");
4639 }
4640 }
4641 return nullptr;
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);
4552 Node *Index = getDerived().parseExpr();
4553 if (Index == nullptr)
4554 return nullptr;
4555 return make<ArraySubscriptExpr>(Base, Index, Op->getPrecedence());
46544556 }
4655 // cl <expression>+ E # call
4656 case 'l': {
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;
4557 case OperatorInfo::Member: {
4558 // Member access lhs @ rhs
47134559 Node *LHS = getDerived().parseExpr();
47144560 if (LHS == nullptr)
47154561 return nullptr;
47164562 Node *RHS = getDerived().parseExpr();
47174563 if (RHS == nullptr)
47184564 return nullptr;
4719 return make<MemberExpr>(LHS, ".*", RHS);
4720 }
4721 case 't': {
4722 First += 2;
4723 Node *LHS = getDerived().parseExpr();
4724 if (LHS == nullptr)
4725 return LHS;
4726 Node *RHS = getDerived().parseExpr();
4727 if (RHS == nullptr)
4728 return nullptr;
4729 return make<MemberExpr>(LHS, ".", RHS);
4730 }
4731 case 'v':
4732 First += 2;
4733 return getDerived().parseBinaryExpr("/");
4734 case 'V':
4735 First += 2;
4736 return getDerived().parseBinaryExpr("/=");
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)
4565 return make<MemberExpr>(LHS, Sym, RHS, Op->getPrecedence());
4566 }
4567 case OperatorInfo::New: {
4568 // New
4569 // # new (expr-list) type [(init)]
4570 // [gs] nw <expression>* _ <type> [pi <expression>*] E
4571 // # new[] (expr-list) type [(init)]
4572 // [gs] na <expression>* _ <type> [pi <expression>*] E
4573 size_t Exprs = Names.size();
4574 while (!consumeIf('_')) {
4575 Node *Ex = getDerived().parseExpr();
4576 if (Ex == nullptr)
4577 return nullptr;
4578 Names.push_back(Ex);
4579 }
4580 NodeArray ExprList = popTrailingNodeArray(Exprs);
4581 Node *Ty = getDerived().parseType();
4582 if (Ty == nullptr)
47684583 return nullptr;
4769 Node *Index = getDerived().parseExpr();
4770 if (Index == nullptr)
4771 return Index;
4772 return make<ArraySubscriptExpr>(Base, Index);
4773 }
4774 case 'l': {
4775 First += 2;
4584 bool HaveInits = consumeIf("pi");
47764585 size_t InitsBegin = Names.size();
47774586 while (!consumeIf('E')) {
4778 Node *E = getDerived().parseBracedExpr();
4779 if (E == nullptr)
4587 if (!HaveInits)
47804588 return nullptr;
4781 Names.push_back(E);
4589 Node *Init = getDerived().parseExpr();
4590 if (Init == nullptr)
4591 return Init;
4592 Names.push_back(Init);
47824593 }
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());
47844597 }
4785 }
4786 return nullptr;
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("--");
4598 case OperatorInfo::Del: {
4599 // Delete
48244600 Node *Ex = getDerived().parseExpr();
48254601 if (Ex == nullptr)
48264602 return nullptr;
4827 return make<PostfixExpr>(Ex, "--");
4828 }
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("|=");
4603 return make<DeleteExpr>(Ex, Global, /*IsArray=*/Op->getFlag(),
4604 Op->getPrecedence());
48654605 }
4866 return nullptr;
4867 case 'p':
4868 switch (First[1]) {
4869 case 'm':
4870 First += 2;
4871 return getDerived().parseBinaryExpr("->*");
4872 case 'l':
4873 First += 2;
4874 return getDerived().parseBinaryExpr("+");
4875 case 'L':
4876 First += 2;
4877 return getDerived().parseBinaryExpr("+=");
4878 case 'p': {
4879 First += 2;
4880 if (consumeIf('_'))
4881 return getDerived().parsePrefixExpr("++");
4882 Node *Ex = getDerived().parseExpr();
4883 if (Ex == nullptr)
4884 return Ex;
4885 return make<PostfixExpr>(Ex, "++");
4606 case OperatorInfo::Call: {
4607 // Function Call
4608 Node *Callee = getDerived().parseExpr();
4609 if (Callee == nullptr)
4610 return nullptr;
4611 size_t ExprsBegin = Names.size();
4612 while (!consumeIf('E')) {
4613 Node *E = getDerived().parseExpr();
4614 if (E == nullptr)
4615 return nullptr;
4616 Names.push_back(E);
4617 }
4618 return make<CallExpr>(Callee, popTrailingNodeArray(ExprsBegin),
4619 Op->getPrecedence());
48864620 }
4887 case 's':
4888 First += 2;
4889 return getDerived().parsePrefixExpr("+");
4890 case 't': {
4891 First += 2;
4892 Node *L = getDerived().parseExpr();
4893 if (L == nullptr)
4621 case OperatorInfo::CCast: {
4622 // C Cast: (type)expr
4623 Node *Ty;
4624 {
4625 ScopedOverride<bool> SaveTemp(TryToParseTemplateArgs, false);
4626 Ty = getDerived().parseType();
4627 }
4628 if (Ty == nullptr)
48944629 return nullptr;
4895 Node *R = getDerived().parseExpr();
4896 if (R == nullptr)
4630
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)
48974643 return nullptr;
4898 return make<MemberExpr>(L, "->", R);
4644 return make<ConversionExpr>(Ty, Exprs, Op->getPrecedence());
48994645 }
4900 }
4901 return nullptr;
4902 case 'q':
4903 if (First[1] == 'u') {
4904 First += 2;
4646 case OperatorInfo::Conditional: {
4647 // Conditional operator: expr ? expr : expr
49054648 Node *Cond = getDerived().parseExpr();
49064649 if (Cond == nullptr)
49074650 return nullptr;
......@@ -4911,147 +4654,120 @@ Node *AbstractManglingParser<Derived, Alloc>::parseExpr() {
49114654 Node *RHS = getDerived().parseExpr();
49124655 if (RHS == nullptr)
49134656 return nullptr;
4914 return make<ConditionalExpr>(Cond, LHS, RHS);
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);
4657 return make<ConditionalExpr>(Cond, LHS, RHS, Op->getPrecedence());
49644658 }
4965 case 'r':
4966 return getDerived().parseUnresolvedName();
4967 case 't': {
4968 First += 2;
4659 case OperatorInfo::NamedCast: {
4660 // Named cast operation, @<type>(expr)
49694661 Node *Ty = getDerived().parseType();
49704662 if (Ty == nullptr)
4971 return Ty;
4972 return make<EnclosingExpr>("sizeof (", Ty, ")");
4973 }
4974 case 'z': {
4975 First += 2;
4663 return nullptr;
49764664 Node *Ex = getDerived().parseExpr();
49774665 if (Ex == nullptr)
4978 return Ex;
4979 return make<EnclosingExpr>("sizeof (", Ex, ")");
4666 return nullptr;
4667 return make<CastExpr>(Sym, Ty, Ex, Op->getPrecedence());
49804668 }
4981 case 'Z':
4982 First += 2;
4983 if (look() == 'T') {
4984 Node *R = getDerived().parseTemplateParam();
4985 if (R == nullptr)
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)
4669 case OperatorInfo::OfIdOp: {
4670 // [sizeof/alignof/typeid] ( <type>|<expr> )
4671 Node *Arg =
4672 Op->getFlag() ? getDerived().parseType() : getDerived().parseExpr();
4673 if (!Arg)
50064674 return nullptr;
5007 return make<EnclosingExpr>("sizeof... (", Pack, ")");
4675 return make<EnclosingExpr>(Sym, Arg, Op->getPrecedence());
50084676 }
4677 case OperatorInfo::NameOnly: {
4678 // Not valid as an expression operand.
4679 return nullptr;
50094680 }
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, ")");
50194681 }
5020 case 'i': {
5021 First += 2;
5022 Node *Ty = getDerived().parseType();
5023 if (Ty == nullptr)
5024 return Ty;
5025 return make<EnclosingExpr>("typeid (", Ty, ")");
4682 DEMANGLE_UNREACHABLE;
4683 }
4684
4685 if (numLeft() < 2)
4686 return nullptr;
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);
50264705 }
5027 case 'l': {
5028 First += 2;
5029 Node *Ty = getDerived().parseType();
5030 if (Ty == nullptr)
4706 return make<InitListExpr>(nullptr, popTrailingNodeArray(InitsBegin));
4707 }
4708 if (consumeIf("mc"))
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)
50314728 return nullptr;
5032 size_t InitsBegin = Names.size();
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));
4729 return make<SizeofParamPackExpr>(R);
50404730 }
5041 case 'r':
5042 First += 2;
5043 return make<NameType>("throw");
5044 case 'w': {
5045 First += 2;
5046 Node *Ex = getDerived().parseExpr();
5047 if (Ex == nullptr)
4731 Node *FP = getDerived().parseFunctionParam();
4732 if (FP == nullptr)
4733 return nullptr;
4734 return make<EnclosingExpr>("sizeof... ", FP);
4735 }
4736 if (consumeIf("sP")) {
4737 size_t ArgsBegin = Names.size();
4738 while (!consumeIf('E')) {
4739 Node *Arg = getDerived().parseTemplateArg();
4740 if (Arg == nullptr)
50484741 return nullptr;
5049 return make<ThrowExpr>(Ex);
4742 Names.push_back(Arg);
50504743 }
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);
50514759 }
5052 return nullptr;
5053 case 'u': {
5054 ++First;
4760 return make<InitListExpr>(Ty, popTrailingNodeArray(InitsBegin));
4761 }
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')) {
50554771 Node *Name = getDerived().parseSourceName(/*NameState=*/nullptr);
50564772 if (!Name)
50574773 return nullptr;
......@@ -5060,45 +4776,36 @@ Node *AbstractManglingParser<Derived, Alloc>::parseExpr() {
50604776 // interpreted as <type> node 'short' or 'ellipsis'. However, neither
50614777 // __uuidof(short) nor __uuidof(...) can actually appear, so there is no
50624778 // actual conflict here.
4779 bool IsUUID = false;
4780 Node *UUID = nullptr;
50634781 if (Name->getBaseName() == "__uuidof") {
5064 if (numLeft() < 2)
5065 return nullptr;
5066 if (*First == 't') {
5067 ++First;
5068 Node *Ty = getDerived().parseType();
5069 if (!Ty)
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));
4782 if (consumeIf('t')) {
4783 UUID = getDerived().parseType();
4784 IsUUID = true;
4785 } else if (consumeIf('z')) {
4786 UUID = getDerived().parseExpr();
4787 IsUUID = true;
50794788 }
50804789 }
50814790 size_t ExprsBegin = Names.size();
5082 while (!consumeIf('E')) {
5083 Node *E = getDerived().parseTemplateArg();
5084 if (E == nullptr)
5085 return E;
5086 Names.push_back(E);
4791 if (IsUUID) {
4792 if (UUID == nullptr)
4793 return nullptr;
4794 Names.push_back(UUID);
4795 } else {
4796 while (!consumeIf('E')) {
4797 Node *E = getDerived().parseTemplateArg();
4798 if (E == nullptr)
4799 return E;
4800 Names.push_back(E);
4801 }
50874802 }
5088 return make<CallExpr>(Name, popTrailingNodeArray(ExprsBegin));
5089 }
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();
4803 return make<CallExpr>(Name, popTrailingNodeArray(ExprsBegin),
4804 Node::Prec::Postfix);
51004805 }
5101 return nullptr;
4806
4807 // Only unresolved names remain.
4808 return getDerived().parseUnresolvedName(Global);
51024809}
51034810
51044811// <call-offset> ::= h <nv-offset> _
......@@ -5131,14 +4838,17 @@ bool AbstractManglingParser<Alloc, Derived>::parseCallOffset() {
51314838// # second call-offset is result adjustment
51324839// ::= T <call-offset> <base encoding>
51334840// # base is the nominal target function of thunk
5134// ::= GV <object name> # Guard variable for one-time initialization
4841// # Guard variable for one-time initialization
4842// ::= GV <object name>
51354843// # No <type>
51364844// ::= TW <object name> # Thread-local wrapper
51374845// ::= TH <object name> # Thread-local initialization
51384846// ::= GR <object name> _ # First temporary
51394847// ::= GR <object name> <seq-id> _ # Subsequent temporaries
5140// extension ::= TC <first type> <number> _ <second type> # construction vtable for second-in-first
4848// # construction vtable for second-in-first
4849// extension ::= TC <first type> <number> _ <second type>
51414850// extension ::= GR <object name> # reference temporary for object
4851// extension ::= GI <module name> # module global initializer
51424852template <typename Derived, typename Alloc>
51434853Node *AbstractManglingParser<Derived, Alloc>::parseSpecialName() {
51444854 switch (look()) {
......@@ -5265,6 +4975,16 @@ Node *AbstractManglingParser<Derived, Alloc>::parseSpecialName() {
52654975 return nullptr;
52664976 return make<SpecialName>("reference temporary for ", Name);
52674977 }
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 }
52684988 }
52694989 }
52704990 return nullptr;
......@@ -5379,7 +5099,7 @@ template <>
53795099struct FloatData<long double>
53805100{
53815101#if defined(__mips__) && defined(__mips_n64) || defined(__aarch64__) || \
5382 defined(__wasm__)
5102 defined(__wasm__) || defined(__riscv)
53835103 static const size_t mangled_size = 32;
53845104#elif defined(__arm__) || defined(__mips__) || defined(__hexagon__)
53855105 static const size_t mangled_size = 16;
......@@ -5444,6 +5164,7 @@ bool AbstractManglingParser<Alloc, Derived>::parseSeqId(size_t *Out) {
54445164// <substitution> ::= Si # ::std::basic_istream<char, std::char_traits<char> >
54455165// <substitution> ::= So # ::std::basic_ostream<char, std::char_traits<char> >
54465166// <substitution> ::= Sd # ::std::basic_iostream<char, std::char_traits<char> >
5167// The St case is handled specially in parseNestedName.
54475168template <typename Derived, typename Alloc>
54485169Node *AbstractManglingParser<Derived, Alloc>::parseSubstitution() {
54495170 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 {
3333 size_t CurrentPosition = 0;
3434 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.
3737 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;
3944 BufferCapacity *= 2;
40 if (BufferCapacity < N + CurrentPosition)
41 BufferCapacity = N + CurrentPosition;
45 if (BufferCapacity < Need)
46 BufferCapacity = Need;
4247 Buffer = static_cast<char *>(std::realloc(Buffer, BufferCapacity));
4348 if (Buffer == nullptr)
4449 std::terminate();
4550 }
4651 }
4752
48 void writeUnsigned(uint64_t N, bool isNeg = false) {
49 // Handle special case...
50 if (N == 0) {
51 *this << '0';
52 return;
53 }
54
53 OutputBuffer &writeUnsigned(uint64_t N, bool isNeg = false) {
5554 std::array<char, 21> Temp;
5655 char *TempPtr = Temp.data() + Temp.size();
5756
58 while (N) {
57 // Output at least one character.
58 do {
5959 *--TempPtr = char('0' + N % 10);
6060 N /= 10;
61 }
61 } while (N);
6262
63 // Add negative sign...
63 // Add negative sign.
6464 if (isNeg)
6565 *--TempPtr = '-';
66 this->operator<<(StringView(TempPtr, Temp.data() + Temp.size()));
66
67 return operator+=(StringView(TempPtr, Temp.data() + Temp.size()));
6768 }
6869
6970public:
7071 OutputBuffer(char *StartBuf, size_t Size)
7172 : Buffer(StartBuf), CurrentPosition(0), BufferCapacity(Size) {}
7273 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
7380 void reset(char *Buffer_, size_t BufferCapacity_) {
7481 CurrentPosition = 0;
7582 Buffer = Buffer_;
......@@ -81,13 +88,27 @@ public:
8188 unsigned CurrentPackIndex = std::numeric_limits<unsigned>::max();
8289 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
84106 OutputBuffer &operator+=(StringView R) {
85 size_t Size = R.size();
86 if (Size == 0)
87 return *this;
88 grow(Size);
89 std::memmove(Buffer + CurrentPosition, R.begin(), Size);
90 CurrentPosition += Size;
107 if (size_t Size = R.size()) {
108 grow(Size);
109 std::memcpy(Buffer + CurrentPosition, R.begin(), Size);
110 CurrentPosition += Size;
111 }
91112 return *this;
92113 }
93114
......@@ -97,9 +118,7 @@ public:
97118 return *this;
98119 }
99120
100 OutputBuffer &operator<<(StringView R) { return (*this += R); }
101
102 OutputBuffer prepend(StringView R) {
121 OutputBuffer &prepend(StringView R) {
103122 size_t Size = R.size();
104123
105124 grow(Size);
......@@ -110,19 +129,16 @@ public:
110129 return *this;
111130 }
112131
132 OutputBuffer &operator<<(StringView R) { return (*this += R); }
133
113134 OutputBuffer &operator<<(char C) { return (*this += C); }
114135
115136 OutputBuffer &operator<<(long long N) {
116 if (N < 0)
117 writeUnsigned(static_cast<unsigned long long>(-N), true);
118 else
119 writeUnsigned(static_cast<unsigned long long>(N));
120 return *this;
137 return writeUnsigned(static_cast<unsigned long long>(std::abs(N)), N < 0);
121138 }
122139
123140 OutputBuffer &operator<<(unsigned long long N) {
124 writeUnsigned(N, false);
125 return *this;
141 return writeUnsigned(N, false);
126142 }
127143
128144 OutputBuffer &operator<<(long N) {
......@@ -155,7 +171,8 @@ public:
155171 void setCurrentPosition(size_t NewPos) { CurrentPosition = NewPos; }
156172
157173 char back() const {
158 return CurrentPosition ? Buffer[CurrentPosition - 1] : '\0';
174 assert(CurrentPosition);
175 return Buffer[CurrentPosition - 1];
159176 }
160177
161178 bool empty() const { return CurrentPosition == 0; }
......@@ -165,35 +182,20 @@ public:
165182 size_t getBufferCapacity() const { return BufferCapacity; }
166183};
167184
168template <class T> class SwapAndRestore {
169 T &Restore;
170 T OriginalValue;
171 bool ShouldRestore = true;
185template <class T> class ScopedOverride {
186 T &Loc;
187 T Original;
172188
173189public:
174 SwapAndRestore(T &Restore_) : SwapAndRestore(Restore_, Restore_) {}
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;
190 ScopedOverride(T &Loc_) : ScopedOverride(Loc_, Loc_) {}
190191
191 Restore = std::move(OriginalValue);
192 ShouldRestore = false;
192 ScopedOverride(T &Loc_, T NewVal) : Loc(Loc_), Original(Loc_) {
193 Loc_ = std::move(NewVal);
193194 }
195 ~ScopedOverride() { Loc = std::move(Original); }
194196
195 SwapAndRestore(const SwapAndRestore &) = delete;
196 SwapAndRestore &operator=(const SwapAndRestore &) = delete;
197 ScopedOverride(const ScopedOverride &) = delete;
198 ScopedOverride &operator=(const ScopedOverride &) = delete;
197199};
198200
199201inline bool initializeOutputBuffer(char *Buf, size_t *N, OutputBuffer &OB,
lib/libcxxabi/src/fallback_malloc.cpp+2-3
......@@ -33,10 +33,9 @@ namespace {
3333
3434// When POSIX threads are not available, make the mutex operations a nop
3535#ifndef _LIBCXXABI_HAS_NO_THREADS
36_LIBCPP_SAFE_STATIC
37static std::__libcpp_mutex_t heap_mutex = _LIBCPP_MUTEX_INITIALIZER;
36static _LIBCPP_CONSTINIT std::__libcpp_mutex_t heap_mutex = _LIBCPP_MUTEX_INITIALIZER;
3837#else
39static void* heap_mutex = 0;
38static _LIBCPP_CONSTINIT void* heap_mutex = 0;
4039#endif
4140
4241class mutexor {
src/libcxx.zig+1-1
......@@ -327,7 +327,7 @@ pub fn buildLibCXXABI(comp: *Compilation) !void {
327327 try cflags.append("-nostdinc++");
328328 try cflags.append("-fstrict-aliasing");
329329 try cflags.append("-funwind-tables");
330 try cflags.append("-std=c++11");
330 try cflags.append("-std=c++20");
331331
332332 c_source_files.appendAssumeCapacity(.{
333333 .src_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{ "libcxxabi", cxxabi_src }),