summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Kelebek12023-01-13 21:06:13 +0000
committerGravatar Kelebek12023-01-14 04:43:21 +0000
commit80a55c1663ac600103e3d475c1f72b04e2e76f0f (patch)
treeac18dcb7f4714b3324733724edd449c77356345c
parentMerge pull request #9605 from german77/mouse_mapping (diff)
downloadyuzu-80a55c1663ac600103e3d475c1f72b04e2e76f0f.tar.gz
yuzu-80a55c1663ac600103e3d475c1f72b04e2e76f0f.tar.xz
yuzu-80a55c1663ac600103e3d475c1f72b04e2e76f0f.zip
Add stacktrace symbol demangling
-rw-r--r--LICENSES/LLVM-exception.txt279
-rw-r--r--externals/CMakeLists.txt4
-rw-r--r--externals/demangle/Demangle.h104
-rw-r--r--externals/demangle/DemangleConfig.h93
-rw-r--r--externals/demangle/ItaniumDemangle.cpp588
-rw-r--r--externals/demangle/ItaniumDemangle.h5582
-rw-r--r--externals/demangle/LICENSE.TXT279
-rw-r--r--externals/demangle/StringView.h127
-rw-r--r--externals/demangle/Utility.h192
-rw-r--r--src/common/CMakeLists.txt3
-rw-r--r--src/common/demangle.h33
-rw-r--r--src/core/arm/arm_interface.cpp18
12 files changed, 7287 insertions, 15 deletions
diff --git a/LICENSES/LLVM-exception.txt b/LICENSES/LLVM-exception.txt
new file mode 100644
index 000000000..fa6ac5400
--- /dev/null
+++ b/LICENSES/LLVM-exception.txt
@@ -0,0 +1,279 @@
1==============================================================================
2The LLVM Project is under the Apache License v2.0 with LLVM Exceptions:
3==============================================================================
4
5 Apache License
6 Version 2.0, January 2004
7 http://www.apache.org/licenses/
8
9 TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
10
11 1. Definitions.
12
13 "License" shall mean the terms and conditions for use, reproduction,
14 and distribution as defined by Sections 1 through 9 of this document.
15
16 "Licensor" shall mean the copyright owner or entity authorized by
17 the copyright owner that is granting the License.
18
19 "Legal Entity" shall mean the union of the acting entity and all
20 other entities that control, are controlled by, or are under common
21 control with that entity. For the purposes of this definition,
22 "control" means (i) the power, direct or indirect, to cause the
23 direction or management of such entity, whether by contract or
24 otherwise, or (ii) ownership of fifty percent (50%) or more of the
25 outstanding shares, or (iii) beneficial ownership of such entity.
26
27 "You" (or "Your") shall mean an individual or Legal Entity
28 exercising permissions granted by this License.
29
30 "Source" form shall mean the preferred form for making modifications,
31 including but not limited to software source code, documentation
32 source, and configuration files.
33
34 "Object" form shall mean any form resulting from mechanical
35 transformation or translation of a Source form, including but
36 not limited to compiled object code, generated documentation,
37 and conversions to other media types.
38
39 "Work" shall mean the work of authorship, whether in Source or
40 Object form, made available under the License, as indicated by a
41 copyright notice that is included in or attached to the work
42 (an example is provided in the Appendix below).
43
44 "Derivative Works" shall mean any work, whether in Source or Object
45 form, that is based on (or derived from) the Work and for which the
46 editorial revisions, annotations, elaborations, or other modifications
47 represent, as a whole, an original work of authorship. For the purposes
48 of this License, Derivative Works shall not include works that remain
49 separable from, or merely link (or bind by name) to the interfaces of,
50 the Work and Derivative Works thereof.
51
52 "Contribution" shall mean any work of authorship, including
53 the original version of the Work and any modifications or additions
54 to that Work or Derivative Works thereof, that is intentionally
55 submitted to Licensor for inclusion in the Work by the copyright owner
56 or by an individual or Legal Entity authorized to submit on behalf of
57 the copyright owner. For the purposes of this definition, "submitted"
58 means any form of electronic, verbal, or written communication sent
59 to the Licensor or its representatives, including but not limited to
60 communication on electronic mailing lists, source code control systems,
61 and issue tracking systems that are managed by, or on behalf of, the
62 Licensor for the purpose of discussing and improving the Work, but
63 excluding communication that is conspicuously marked or otherwise
64 designated in writing by the copyright owner as "Not a Contribution."
65
66 "Contributor" shall mean Licensor and any individual or Legal Entity
67 on behalf of whom a Contribution has been received by Licensor and
68 subsequently incorporated within the Work.
69
70 2. Grant of Copyright License. Subject to the terms and conditions of
71 this License, each Contributor hereby grants to You a perpetual,
72 worldwide, non-exclusive, no-charge, royalty-free, irrevocable
73 copyright license to reproduce, prepare Derivative Works of,
74 publicly display, publicly perform, sublicense, and distribute the
75 Work and such Derivative Works in Source or Object form.
76
77 3. Grant of Patent License. Subject to the terms and conditions of
78 this License, each Contributor hereby grants to You a perpetual,
79 worldwide, non-exclusive, no-charge, royalty-free, irrevocable
80 (except as stated in this section) patent license to make, have made,
81 use, offer to sell, sell, import, and otherwise transfer the Work,
82 where such license applies only to those patent claims licensable
83 by such Contributor that are necessarily infringed by their
84 Contribution(s) alone or by combination of their Contribution(s)
85 with the Work to which such Contribution(s) was submitted. If You
86 institute patent litigation against any entity (including a
87 cross-claim or counterclaim in a lawsuit) alleging that the Work
88 or a Contribution incorporated within the Work constitutes direct
89 or contributory patent infringement, then any patent licenses
90 granted to You under this License for that Work shall terminate
91 as of the date such litigation is filed.
92
93 4. Redistribution. You may reproduce and distribute copies of the
94 Work or Derivative Works thereof in any medium, with or without
95 modifications, and in Source or Object form, provided that You
96 meet the following conditions:
97
98 (a) You must give any other recipients of the Work or
99 Derivative Works a copy of this License; and
100
101 (b) You must cause any modified files to carry prominent notices
102 stating that You changed the files; and
103
104 (c) You must retain, in the Source form of any Derivative Works
105 that You distribute, all copyright, patent, trademark, and
106 attribution notices from the Source form of the Work,
107 excluding those notices that do not pertain to any part of
108 the Derivative Works; and
109
110 (d) If the Work includes a "NOTICE" text file as part of its
111 distribution, then any Derivative Works that You distribute must
112 include a readable copy of the attribution notices contained
113 within such NOTICE file, excluding those notices that do not
114 pertain to any part of the Derivative Works, in at least one
115 of the following places: within a NOTICE text file distributed
116 as part of the Derivative Works; within the Source form or
117 documentation, if provided along with the Derivative Works; or,
118 within a display generated by the Derivative Works, if and
119 wherever such third-party notices normally appear. The contents
120 of the NOTICE file are for informational purposes only and
121 do not modify the License. You may add Your own attribution
122 notices within Derivative Works that You distribute, alongside
123 or as an addendum to the NOTICE text from the Work, provided
124 that such additional attribution notices cannot be construed
125 as modifying the License.
126
127 You may add Your own copyright statement to Your modifications and
128 may provide additional or different license terms and conditions
129 for use, reproduction, or distribution of Your modifications, or
130 for any such Derivative Works as a whole, provided Your use,
131 reproduction, and distribution of the Work otherwise complies with
132 the conditions stated in this License.
133
134 5. Submission of Contributions. Unless You explicitly state otherwise,
135 any Contribution intentionally submitted for inclusion in the Work
136 by You to the Licensor shall be under the terms and conditions of
137 this License, without any additional terms or conditions.
138 Notwithstanding the above, nothing herein shall supersede or modify
139 the terms of any separate license agreement you may have executed
140 with Licensor regarding such Contributions.
141
142 6. Trademarks. This License does not grant permission to use the trade
143 names, trademarks, service marks, or product names of the Licensor,
144 except as required for reasonable and customary use in describing the
145 origin of the Work and reproducing the content of the NOTICE file.
146
147 7. Disclaimer of Warranty. Unless required by applicable law or
148 agreed to in writing, Licensor provides the Work (and each
149 Contributor provides its Contributions) on an "AS IS" BASIS,
150 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
151 implied, including, without limitation, any warranties or conditions
152 of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
153 PARTICULAR PURPOSE. You are solely responsible for determining the
154 appropriateness of using or redistributing the Work and assume any
155 risks associated with Your exercise of permissions under this License.
156
157 8. Limitation of Liability. In no event and under no legal theory,
158 whether in tort (including negligence), contract, or otherwise,
159 unless required by applicable law (such as deliberate and grossly
160 negligent acts) or agreed to in writing, shall any Contributor be
161 liable to You for damages, including any direct, indirect, special,
162 incidental, or consequential damages of any character arising as a
163 result of this License or out of the use or inability to use the
164 Work (including but not limited to damages for loss of goodwill,
165 work stoppage, computer failure or malfunction, or any and all
166 other commercial damages or losses), even if such Contributor
167 has been advised of the possibility of such damages.
168
169 9. Accepting Warranty or Additional Liability. While redistributing
170 the Work or Derivative Works thereof, You may choose to offer,
171 and charge a fee for, acceptance of support, warranty, indemnity,
172 or other liability obligations and/or rights consistent with this
173 License. However, in accepting such obligations, You may act only
174 on Your own behalf and on Your sole responsibility, not on behalf
175 of any other Contributor, and only if You agree to indemnify,
176 defend, and hold each Contributor harmless for any liability
177 incurred by, or claims asserted against, such Contributor by reason
178 of your accepting any such warranty or additional liability.
179
180 END OF TERMS AND CONDITIONS
181
182 APPENDIX: How to apply the Apache License to your work.
183
184 To apply the Apache License to your work, attach the following
185 boilerplate notice, with the fields enclosed by brackets "[]"
186 replaced with your own identifying information. (Don't include
187 the brackets!) The text should be enclosed in the appropriate
188 comment syntax for the file format. We also recommend that a
189 file or class name and description of purpose be included on the
190 same "printed page" as the copyright notice for easier
191 identification within third-party archives.
192
193 Copyright [yyyy] [name of copyright owner]
194
195 Licensed under the Apache License, Version 2.0 (the "License");
196 you may not use this file except in compliance with the License.
197 You may obtain a copy of the License at
198
199 http://www.apache.org/licenses/LICENSE-2.0
200
201 Unless required by applicable law or agreed to in writing, software
202 distributed under the License is distributed on an "AS IS" BASIS,
203 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
204 See the License for the specific language governing permissions and
205 limitations under the License.
206
207
208---- LLVM Exceptions to the Apache 2.0 License ----
209
210As an exception, if, as a result of your compiling your source code, portions
211of this Software are embedded into an Object form of such source code, you
212may redistribute such embedded portions in such Object form without complying
213with the conditions of Sections 4(a), 4(b) and 4(d) of the License.
214
215In addition, if you combine or link compiled forms of this Software with
216software that is licensed under the GPLv2 ("Combined Software") and if a
217court of competent jurisdiction determines that the patent provision (Section
2183), the indemnity provision (Section 9) or other Section of the License
219conflicts with the conditions of the GPLv2, you may retroactively and
220prospectively choose to deem waived or otherwise exclude such Section(s) of
221the License, but only in their entirety and only with respect to the Combined
222Software.
223
224==============================================================================
225Software from third parties included in the LLVM Project:
226==============================================================================
227The LLVM Project contains third party software which is under different license
228terms. All such code will be identified clearly using at least one of two
229mechanisms:
2301) It will be in a separate directory tree with its own `LICENSE.txt` or
231 `LICENSE` file at the top containing the specific license and restrictions
232 which apply to that software, or
2332) It will contain specific license and restriction terms at the top of every
234 file.
235
236==============================================================================
237Legacy LLVM License (https://llvm.org/docs/DeveloperPolicy.html#legacy):
238==============================================================================
239University of Illinois/NCSA
240Open Source License
241
242Copyright (c) 2003-2019 University of Illinois at Urbana-Champaign.
243All rights reserved.
244
245Developed by:
246
247 LLVM Team
248
249 University of Illinois at Urbana-Champaign
250
251 http://llvm.org
252
253Permission is hereby granted, free of charge, to any person obtaining a copy of
254this software and associated documentation files (the "Software"), to deal with
255the Software without restriction, including without limitation the rights to
256use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
257of the Software, and to permit persons to whom the Software is furnished to do
258so, subject to the following conditions:
259
260 * Redistributions of source code must retain the above copyright notice,
261 this list of conditions and the following disclaimers.
262
263 * Redistributions in binary form must reproduce the above copyright notice,
264 this list of conditions and the following disclaimers in the
265 documentation and/or other materials provided with the distribution.
266
267 * Neither the names of the LLVM Team, University of Illinois at
268 Urbana-Champaign, nor the names of its contributors may be used to
269 endorse or promote products derived from this Software without specific
270 prior written permission.
271
272THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
273IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
274FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
275CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
276LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
277OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE
278SOFTWARE.
279
diff --git a/externals/CMakeLists.txt b/externals/CMakeLists.txt
index dfd40cba6..89a381587 100644
--- a/externals/CMakeLists.txt
+++ b/externals/CMakeLists.txt
@@ -154,3 +154,7 @@ endif()
154if (YUZU_USE_EXTERNAL_VULKAN_HEADERS) 154if (YUZU_USE_EXTERNAL_VULKAN_HEADERS)
155 add_subdirectory(Vulkan-Headers EXCLUDE_FROM_ALL) 155 add_subdirectory(Vulkan-Headers EXCLUDE_FROM_ALL)
156endif() 156endif()
157
158add_library(demangle STATIC)
159target_include_directories(demangle PUBLIC ./demangle)
160target_sources(demangle PRIVATE demangle/ItaniumDemangle.cpp)
diff --git a/externals/demangle/Demangle.h b/externals/demangle/Demangle.h
new file mode 100644
index 000000000..3b76b49ca
--- /dev/null
+++ b/externals/demangle/Demangle.h
@@ -0,0 +1,104 @@
1//===--- Demangle.h ---------------------------------------------*- 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-FileCopyrightText: Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
6// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7//
8//===----------------------------------------------------------------------===//
9
10#ifndef LLVM_DEMANGLE_DEMANGLE_H
11#define LLVM_DEMANGLE_DEMANGLE_H
12
13#include <cstddef>
14#include <string>
15
16namespace llvm {
17/// This is a llvm local version of __cxa_demangle. Other than the name and
18/// being in the llvm namespace it is identical.
19///
20/// The mangled_name is demangled into buf and returned. If the buffer is not
21/// large enough, realloc is used to expand it.
22///
23/// The *status will be set to a value from the following enumeration
24enum : int {
25 demangle_unknown_error = -4,
26 demangle_invalid_args = -3,
27 demangle_invalid_mangled_name = -2,
28 demangle_memory_alloc_failure = -1,
29 demangle_success = 0,
30};
31
32char *itaniumDemangle(const char *mangled_name, char *buf, size_t *n,
33 int *status);
34
35
36enum MSDemangleFlags {
37 MSDF_None = 0,
38 MSDF_DumpBackrefs = 1 << 0,
39 MSDF_NoAccessSpecifier = 1 << 1,
40 MSDF_NoCallingConvention = 1 << 2,
41 MSDF_NoReturnType = 1 << 3,
42 MSDF_NoMemberType = 1 << 4,
43};
44char *microsoftDemangle(const char *mangled_name, char *buf, size_t *n,
45 int *status, MSDemangleFlags Flags = MSDF_None);
46
47/// "Partial" demangler. This supports demangling a string into an AST
48/// (typically an intermediate stage in itaniumDemangle) and querying certain
49/// properties or partially printing the demangled name.
50struct ItaniumPartialDemangler {
51 ItaniumPartialDemangler();
52
53 ItaniumPartialDemangler(ItaniumPartialDemangler &&Other);
54 ItaniumPartialDemangler &operator=(ItaniumPartialDemangler &&Other);
55
56 /// Demangle into an AST. Subsequent calls to the rest of the member functions
57 /// implicitly operate on the AST this produces.
58 /// \return true on error, false otherwise
59 bool partialDemangle(const char *MangledName);
60
61 /// Just print the entire mangled name into Buf. Buf and N behave like the
62 /// second and third parameters to itaniumDemangle.
63 char *finishDemangle(char *Buf, size_t *N) const;
64
65 /// Get the base name of a function. This doesn't include trailing template
66 /// arguments, ie for "a::b<int>" this function returns "b".
67 char *getFunctionBaseName(char *Buf, size_t *N) const;
68
69 /// Get the context name for a function. For "a::b::c", this function returns
70 /// "a::b".
71 char *getFunctionDeclContextName(char *Buf, size_t *N) const;
72
73 /// Get the entire name of this function.
74 char *getFunctionName(char *Buf, size_t *N) const;
75
76 /// Get the parameters for this function.
77 char *getFunctionParameters(char *Buf, size_t *N) const;
78 char *getFunctionReturnType(char *Buf, size_t *N) const;
79
80 /// If this function has any any cv or reference qualifiers. These imply that
81 /// the function is a non-static member function.
82 bool hasFunctionQualifiers() const;
83
84 /// If this symbol describes a constructor or destructor.
85 bool isCtorOrDtor() const;
86
87 /// If this symbol describes a function.
88 bool isFunction() const;
89
90 /// If this symbol describes a variable.
91 bool isData() const;
92
93 /// If this symbol is a <special-name>. These are generally implicitly
94 /// generated by the implementation, such as vtables and typeinfo names.
95 bool isSpecialName() const;
96
97 ~ItaniumPartialDemangler();
98private:
99 void *RootNode;
100 void *Context;
101};
102} // namespace llvm
103
104#endif
diff --git a/externals/demangle/DemangleConfig.h b/externals/demangle/DemangleConfig.h
new file mode 100644
index 000000000..f155f69fa
--- /dev/null
+++ b/externals/demangle/DemangleConfig.h
@@ -0,0 +1,93 @@
1//===--- DemangleConfig.h ---------------------------------------*- 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-FileCopyrightText: Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
6// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7//
8//===----------------------------------------------------------------------===//
9//
10// This file contains a variety of feature test macros copied from
11// include/llvm/Support/Compiler.h so that LLVMDemangle does not need to take
12// a dependency on LLVMSupport.
13//
14//===----------------------------------------------------------------------===//
15
16#ifndef LLVM_DEMANGLE_COMPILER_H
17#define LLVM_DEMANGLE_COMPILER_H
18
19#ifndef __has_feature
20#define __has_feature(x) 0
21#endif
22
23#ifndef __has_cpp_attribute
24#define __has_cpp_attribute(x) 0
25#endif
26
27#ifndef __has_attribute
28#define __has_attribute(x) 0
29#endif
30
31#ifndef __has_builtin
32#define __has_builtin(x) 0
33#endif
34
35#ifndef DEMANGLE_GNUC_PREREQ
36#if defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__)
37#define DEMANGLE_GNUC_PREREQ(maj, min, patch) \
38 ((__GNUC__ << 20) + (__GNUC_MINOR__ << 10) + __GNUC_PATCHLEVEL__ >= \
39 ((maj) << 20) + ((min) << 10) + (patch))
40#elif defined(__GNUC__) && defined(__GNUC_MINOR__)
41#define DEMANGLE_GNUC_PREREQ(maj, min, patch) \
42 ((__GNUC__ << 20) + (__GNUC_MINOR__ << 10) >= ((maj) << 20) + ((min) << 10))
43#else
44#define DEMANGLE_GNUC_PREREQ(maj, min, patch) 0
45#endif
46#endif
47
48#if __has_attribute(used) || DEMANGLE_GNUC_PREREQ(3, 1, 0)
49#define DEMANGLE_ATTRIBUTE_USED __attribute__((__used__))
50#else
51#define DEMANGLE_ATTRIBUTE_USED
52#endif
53
54#if __has_builtin(__builtin_unreachable) || DEMANGLE_GNUC_PREREQ(4, 5, 0)
55#define DEMANGLE_UNREACHABLE __builtin_unreachable()
56#elif defined(_MSC_VER)
57#define DEMANGLE_UNREACHABLE __assume(false)
58#else
59#define DEMANGLE_UNREACHABLE
60#endif
61
62#if __has_attribute(noinline) || DEMANGLE_GNUC_PREREQ(3, 4, 0)
63#define DEMANGLE_ATTRIBUTE_NOINLINE __attribute__((noinline))
64#elif defined(_MSC_VER)
65#define DEMANGLE_ATTRIBUTE_NOINLINE __declspec(noinline)
66#else
67#define DEMANGLE_ATTRIBUTE_NOINLINE
68#endif
69
70#if !defined(NDEBUG)
71#define DEMANGLE_DUMP_METHOD DEMANGLE_ATTRIBUTE_NOINLINE DEMANGLE_ATTRIBUTE_USED
72#else
73#define DEMANGLE_DUMP_METHOD DEMANGLE_ATTRIBUTE_NOINLINE
74#endif
75
76#if __cplusplus > 201402L && __has_cpp_attribute(fallthrough)
77#define DEMANGLE_FALLTHROUGH [[fallthrough]]
78#elif __has_cpp_attribute(gnu::fallthrough)
79#define DEMANGLE_FALLTHROUGH [[gnu::fallthrough]]
80#elif !__cplusplus
81// Workaround for llvm.org/PR23435, since clang 3.6 and below emit a spurious
82// error when __has_cpp_attribute is given a scoped attribute in C mode.
83#define DEMANGLE_FALLTHROUGH
84#elif __has_cpp_attribute(clang::fallthrough)
85#define DEMANGLE_FALLTHROUGH [[clang::fallthrough]]
86#else
87#define DEMANGLE_FALLTHROUGH
88#endif
89
90#define DEMANGLE_NAMESPACE_BEGIN namespace llvm { namespace itanium_demangle {
91#define DEMANGLE_NAMESPACE_END } }
92
93#endif
diff --git a/externals/demangle/ItaniumDemangle.cpp b/externals/demangle/ItaniumDemangle.cpp
new file mode 100644
index 000000000..3a3cbda18
--- /dev/null
+++ b/externals/demangle/ItaniumDemangle.cpp
@@ -0,0 +1,588 @@
1//===------------------------- ItaniumDemangle.cpp ------------------------===//
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-FileCopyrightText: Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
6// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7//
8//===----------------------------------------------------------------------===//
9
10// FIXME: (possibly) incomplete list of features that clang mangles that this
11// file does not yet support:
12// - C++ modules TS
13
14#include "Demangle.h"
15#include "ItaniumDemangle.h"
16
17#include <cassert>
18#include <cctype>
19#include <cstdio>
20#include <cstdlib>
21#include <cstring>
22#include <functional>
23#include <numeric>
24#include <utility>
25#include <vector>
26
27using namespace llvm;
28using namespace llvm::itanium_demangle;
29
30constexpr const char *itanium_demangle::FloatData<float>::spec;
31constexpr const char *itanium_demangle::FloatData<double>::spec;
32constexpr const char *itanium_demangle::FloatData<long double>::spec;
33
34// <discriminator> := _ <non-negative number> # when number < 10
35// := __ <non-negative number> _ # when number >= 10
36// extension := decimal-digit+ # at the end of string
37const char *itanium_demangle::parse_discriminator(const char *first,
38 const char *last) {
39 // parse but ignore discriminator
40 if (first != last) {
41 if (*first == '_') {
42 const char *t1 = first + 1;
43 if (t1 != last) {
44 if (std::isdigit(*t1))
45 first = t1 + 1;
46 else if (*t1 == '_') {
47 for (++t1; t1 != last && std::isdigit(*t1); ++t1)
48 ;
49 if (t1 != last && *t1 == '_')
50 first = t1 + 1;
51 }
52 }
53 } else if (std::isdigit(*first)) {
54 const char *t1 = first + 1;
55 for (; t1 != last && std::isdigit(*t1); ++t1)
56 ;
57 if (t1 == last)
58 first = last;
59 }
60 }
61 return first;
62}
63
64#ifndef NDEBUG
65namespace {
66struct DumpVisitor {
67 unsigned Depth = 0;
68 bool PendingNewline = false;
69
70 template<typename NodeT> static constexpr bool wantsNewline(const NodeT *) {
71 return true;
72 }
73 static bool wantsNewline(NodeArray A) { return !A.empty(); }
74 static constexpr bool wantsNewline(...) { return false; }
75
76 template<typename ...Ts> static bool anyWantNewline(Ts ...Vs) {
77 for (bool B : {wantsNewline(Vs)...})
78 if (B)
79 return true;
80 return false;
81 }
82
83 void printStr(const char *S) { fprintf(stderr, "%s", S); }
84 void print(StringView SV) {
85 fprintf(stderr, "\"%.*s\"", (int)SV.size(), SV.begin());
86 }
87 void print(const Node *N) {
88 if (N)
89 N->visit(std::ref(*this));
90 else
91 printStr("<null>");
92 }
93 void print(NodeOrString NS) {
94 if (NS.isNode())
95 print(NS.asNode());
96 else if (NS.isString())
97 print(NS.asString());
98 else
99 printStr("NodeOrString()");
100 }
101 void print(NodeArray A) {
102 ++Depth;
103 printStr("{");
104 bool First = true;
105 for (const Node *N : A) {
106 if (First)
107 print(N);
108 else
109 printWithComma(N);
110 First = false;
111 }
112 printStr("}");
113 --Depth;
114 }
115
116 // Overload used when T is exactly 'bool', not merely convertible to 'bool'.
117 void print(bool B) { printStr(B ? "true" : "false"); }
118
119 template <class T>
120 typename std::enable_if<std::is_unsigned<T>::value>::type print(T N) {
121 fprintf(stderr, "%llu", (unsigned long long)N);
122 }
123
124 template <class T>
125 typename std::enable_if<std::is_signed<T>::value>::type print(T N) {
126 fprintf(stderr, "%lld", (long long)N);
127 }
128
129 void print(ReferenceKind RK) {
130 switch (RK) {
131 case ReferenceKind::LValue:
132 return printStr("ReferenceKind::LValue");
133 case ReferenceKind::RValue:
134 return printStr("ReferenceKind::RValue");
135 }
136 }
137 void print(FunctionRefQual RQ) {
138 switch (RQ) {
139 case FunctionRefQual::FrefQualNone:
140 return printStr("FunctionRefQual::FrefQualNone");
141 case FunctionRefQual::FrefQualLValue:
142 return printStr("FunctionRefQual::FrefQualLValue");
143 case FunctionRefQual::FrefQualRValue:
144 return printStr("FunctionRefQual::FrefQualRValue");
145 }
146 }
147 void print(Qualifiers Qs) {
148 if (!Qs) return printStr("QualNone");
149 struct QualName { Qualifiers Q; const char *Name; } Names[] = {
150 {QualConst, "QualConst"},
151 {QualVolatile, "QualVolatile"},
152 {QualRestrict, "QualRestrict"},
153 };
154 for (QualName Name : Names) {
155 if (Qs & Name.Q) {
156 printStr(Name.Name);
157 Qs = Qualifiers(Qs & ~Name.Q);
158 if (Qs) printStr(" | ");
159 }
160 }
161 }
162 void print(SpecialSubKind SSK) {
163 switch (SSK) {
164 case SpecialSubKind::allocator:
165 return printStr("SpecialSubKind::allocator");
166 case SpecialSubKind::basic_string:
167 return printStr("SpecialSubKind::basic_string");
168 case SpecialSubKind::string:
169 return printStr("SpecialSubKind::string");
170 case SpecialSubKind::istream:
171 return printStr("SpecialSubKind::istream");
172 case SpecialSubKind::ostream:
173 return printStr("SpecialSubKind::ostream");
174 case SpecialSubKind::iostream:
175 return printStr("SpecialSubKind::iostream");
176 }
177 }
178 void print(TemplateParamKind TPK) {
179 switch (TPK) {
180 case TemplateParamKind::Type:
181 return printStr("TemplateParamKind::Type");
182 case TemplateParamKind::NonType:
183 return printStr("TemplateParamKind::NonType");
184 case TemplateParamKind::Template:
185 return printStr("TemplateParamKind::Template");
186 }
187 }
188
189 void newLine() {
190 printStr("\n");
191 for (unsigned I = 0; I != Depth; ++I)
192 printStr(" ");
193 PendingNewline = false;
194 }
195
196 template<typename T> void printWithPendingNewline(T V) {
197 print(V);
198 if (wantsNewline(V))
199 PendingNewline = true;
200 }
201
202 template<typename T> void printWithComma(T V) {
203 if (PendingNewline || wantsNewline(V)) {
204 printStr(",");
205 newLine();
206 } else {
207 printStr(", ");
208 }
209
210 printWithPendingNewline(V);
211 }
212
213 struct CtorArgPrinter {
214 DumpVisitor &Visitor;
215
216 template<typename T, typename ...Rest> void operator()(T V, Rest ...Vs) {
217 if (Visitor.anyWantNewline(V, Vs...))
218 Visitor.newLine();
219 Visitor.printWithPendingNewline(V);
220 int PrintInOrder[] = { (Visitor.printWithComma(Vs), 0)..., 0 };
221 (void)PrintInOrder;
222 }
223 };
224
225 template<typename NodeT> void operator()(const NodeT *Node) {
226 Depth += 2;
227 fprintf(stderr, "%s(", itanium_demangle::NodeKind<NodeT>::name());
228 Node->match(CtorArgPrinter{*this});
229 fprintf(stderr, ")");
230 Depth -= 2;
231 }
232
233 void operator()(const ForwardTemplateReference *Node) {
234 Depth += 2;
235 fprintf(stderr, "ForwardTemplateReference(");
236 if (Node->Ref && !Node->Printing) {
237 Node->Printing = true;
238 CtorArgPrinter{*this}(Node->Ref);
239 Node->Printing = false;
240 } else {
241 CtorArgPrinter{*this}(Node->Index);
242 }
243 fprintf(stderr, ")");
244 Depth -= 2;
245 }
246};
247}
248
249void itanium_demangle::Node::dump() const {
250 DumpVisitor V;
251 visit(std::ref(V));
252 V.newLine();
253}
254#endif
255
256namespace {
257class BumpPointerAllocator {
258 struct BlockMeta {
259 BlockMeta* Next;
260 size_t Current;
261 };
262
263 static constexpr size_t AllocSize = 4096;
264 static constexpr size_t UsableAllocSize = AllocSize - sizeof(BlockMeta);
265
266 alignas(long double) char InitialBuffer[AllocSize];
267 BlockMeta* BlockList = nullptr;
268
269 void grow() {
270 char* NewMeta = static_cast<char *>(std::malloc(AllocSize));
271 if (NewMeta == nullptr)
272 std::terminate();
273 BlockList = new (NewMeta) BlockMeta{BlockList, 0};
274 }
275
276 void* allocateMassive(size_t NBytes) {
277 NBytes += sizeof(BlockMeta);
278 BlockMeta* NewMeta = reinterpret_cast<BlockMeta*>(std::malloc(NBytes));
279 if (NewMeta == nullptr)
280 std::terminate();
281 BlockList->Next = new (NewMeta) BlockMeta{BlockList->Next, 0};
282 return static_cast<void*>(NewMeta + 1);
283 }
284
285public:
286 BumpPointerAllocator()
287 : BlockList(new (InitialBuffer) BlockMeta{nullptr, 0}) {}
288
289 void* allocate(size_t N) {
290 N = (N + 15u) & ~15u;
291 if (N + BlockList->Current >= UsableAllocSize) {
292 if (N > UsableAllocSize)
293 return allocateMassive(N);
294 grow();
295 }
296 BlockList->Current += N;
297 return static_cast<void*>(reinterpret_cast<char*>(BlockList + 1) +
298 BlockList->Current - N);
299 }
300
301 void reset() {
302 while (BlockList) {
303 BlockMeta* Tmp = BlockList;
304 BlockList = BlockList->Next;
305 if (reinterpret_cast<char*>(Tmp) != InitialBuffer)
306 std::free(Tmp);
307 }
308 BlockList = new (InitialBuffer) BlockMeta{nullptr, 0};
309 }
310
311 ~BumpPointerAllocator() { reset(); }
312};
313
314class DefaultAllocator {
315 BumpPointerAllocator Alloc;
316
317public:
318 void reset() { Alloc.reset(); }
319
320 template<typename T, typename ...Args> T *makeNode(Args &&...args) {
321 return new (Alloc.allocate(sizeof(T)))
322 T(std::forward<Args>(args)...);
323 }
324
325 void *allocateNodeArray(size_t sz) {
326 return Alloc.allocate(sizeof(Node *) * sz);
327 }
328};
329} // unnamed namespace
330
331//===----------------------------------------------------------------------===//
332// Code beyond this point should not be synchronized with libc++abi.
333//===----------------------------------------------------------------------===//
334
335using Demangler = itanium_demangle::ManglingParser<DefaultAllocator>;
336
337char *llvm::itaniumDemangle(const char *MangledName, char *Buf,
338 size_t *N, int *Status) {
339 if (MangledName == nullptr || (Buf != nullptr && N == nullptr)) {
340 if (Status)
341 *Status = demangle_invalid_args;
342 return nullptr;
343 }
344
345 int InternalStatus = demangle_success;
346 Demangler Parser(MangledName, MangledName + std::strlen(MangledName));
347 OutputStream S;
348
349 Node *AST = Parser.parse();
350
351 if (AST == nullptr)
352 InternalStatus = demangle_invalid_mangled_name;
353 else if (!initializeOutputStream(Buf, N, S, 1024))
354 InternalStatus = demangle_memory_alloc_failure;
355 else {
356 assert(Parser.ForwardTemplateRefs.empty());
357 AST->print(S);
358 S += '\0';
359 if (N != nullptr)
360 *N = S.getCurrentPosition();
361 Buf = S.getBuffer();
362 }
363
364 if (Status)
365 *Status = InternalStatus;
366 return InternalStatus == demangle_success ? Buf : nullptr;
367}
368
369ItaniumPartialDemangler::ItaniumPartialDemangler()
370 : RootNode(nullptr), Context(new Demangler{nullptr, nullptr}) {}
371
372ItaniumPartialDemangler::~ItaniumPartialDemangler() {
373 delete static_cast<Demangler *>(Context);
374}
375
376ItaniumPartialDemangler::ItaniumPartialDemangler(
377 ItaniumPartialDemangler &&Other)
378 : RootNode(Other.RootNode), Context(Other.Context) {
379 Other.Context = Other.RootNode = nullptr;
380}
381
382ItaniumPartialDemangler &ItaniumPartialDemangler::
383operator=(ItaniumPartialDemangler &&Other) {
384 std::swap(RootNode, Other.RootNode);
385 std::swap(Context, Other.Context);
386 return *this;
387}
388
389// Demangle MangledName into an AST, storing it into this->RootNode.
390bool ItaniumPartialDemangler::partialDemangle(const char *MangledName) {
391 Demangler *Parser = static_cast<Demangler *>(Context);
392 size_t Len = std::strlen(MangledName);
393 Parser->reset(MangledName, MangledName + Len);
394 RootNode = Parser->parse();
395 return RootNode == nullptr;
396}
397
398static char *printNode(const Node *RootNode, char *Buf, size_t *N) {
399 OutputStream S;
400 if (!initializeOutputStream(Buf, N, S, 128))
401 return nullptr;
402 RootNode->print(S);
403 S += '\0';
404 if (N != nullptr)
405 *N = S.getCurrentPosition();
406 return S.getBuffer();
407}
408
409char *ItaniumPartialDemangler::getFunctionBaseName(char *Buf, size_t *N) const {
410 if (!isFunction())
411 return nullptr;
412
413 const Node *Name = static_cast<const FunctionEncoding *>(RootNode)->getName();
414
415 while (true) {
416 switch (Name->getKind()) {
417 case Node::KAbiTagAttr:
418 Name = static_cast<const AbiTagAttr *>(Name)->Base;
419 continue;
420 case Node::KStdQualifiedName:
421 Name = static_cast<const StdQualifiedName *>(Name)->Child;
422 continue;
423 case Node::KNestedName:
424 Name = static_cast<const NestedName *>(Name)->Name;
425 continue;
426 case Node::KLocalName:
427 Name = static_cast<const LocalName *>(Name)->Entity;
428 continue;
429 case Node::KNameWithTemplateArgs:
430 Name = static_cast<const NameWithTemplateArgs *>(Name)->Name;
431 continue;
432 default:
433 return printNode(Name, Buf, N);
434 }
435 }
436}
437
438char *ItaniumPartialDemangler::getFunctionDeclContextName(char *Buf,
439 size_t *N) const {
440 if (!isFunction())
441 return nullptr;
442 const Node *Name = static_cast<const FunctionEncoding *>(RootNode)->getName();
443
444 OutputStream S;
445 if (!initializeOutputStream(Buf, N, S, 128))
446 return nullptr;
447
448 KeepGoingLocalFunction:
449 while (true) {
450 if (Name->getKind() == Node::KAbiTagAttr) {
451 Name = static_cast<const AbiTagAttr *>(Name)->Base;
452 continue;
453 }
454 if (Name->getKind() == Node::KNameWithTemplateArgs) {
455 Name = static_cast<const NameWithTemplateArgs *>(Name)->Name;
456 continue;
457 }
458 break;
459 }
460
461 switch (Name->getKind()) {
462 case Node::KStdQualifiedName:
463 S += "std";
464 break;
465 case Node::KNestedName:
466 static_cast<const NestedName *>(Name)->Qual->print(S);
467 break;
468 case Node::KLocalName: {
469 auto *LN = static_cast<const LocalName *>(Name);
470 LN->Encoding->print(S);
471 S += "::";
472 Name = LN->Entity;
473 goto KeepGoingLocalFunction;
474 }
475 default:
476 break;
477 }
478 S += '\0';
479 if (N != nullptr)
480 *N = S.getCurrentPosition();
481 return S.getBuffer();
482}
483
484char *ItaniumPartialDemangler::getFunctionName(char *Buf, size_t *N) const {
485 if (!isFunction())
486 return nullptr;
487 auto *Name = static_cast<FunctionEncoding *>(RootNode)->getName();
488 return printNode(Name, Buf, N);
489}
490
491char *ItaniumPartialDemangler::getFunctionParameters(char *Buf,
492 size_t *N) const {
493 if (!isFunction())
494 return nullptr;
495 NodeArray Params = static_cast<FunctionEncoding *>(RootNode)->getParams();
496
497 OutputStream S;
498 if (!initializeOutputStream(Buf, N, S, 128))
499 return nullptr;
500
501 S += '(';
502 Params.printWithComma(S);
503 S += ')';
504 S += '\0';
505 if (N != nullptr)
506 *N = S.getCurrentPosition();
507 return S.getBuffer();
508}
509
510char *ItaniumPartialDemangler::getFunctionReturnType(
511 char *Buf, size_t *N) const {
512 if (!isFunction())
513 return nullptr;
514
515 OutputStream S;
516 if (!initializeOutputStream(Buf, N, S, 128))
517 return nullptr;
518
519 if (const Node *Ret =
520 static_cast<const FunctionEncoding *>(RootNode)->getReturnType())
521 Ret->print(S);
522
523 S += '\0';
524 if (N != nullptr)
525 *N = S.getCurrentPosition();
526 return S.getBuffer();
527}
528
529char *ItaniumPartialDemangler::finishDemangle(char *Buf, size_t *N) const {
530 assert(RootNode != nullptr && "must call partialDemangle()");
531 return printNode(static_cast<Node *>(RootNode), Buf, N);
532}
533
534bool ItaniumPartialDemangler::hasFunctionQualifiers() const {
535 assert(RootNode != nullptr && "must call partialDemangle()");
536 if (!isFunction())
537 return false;
538 auto *E = static_cast<const FunctionEncoding *>(RootNode);
539 return E->getCVQuals() != QualNone || E->getRefQual() != FrefQualNone;
540}
541
542bool ItaniumPartialDemangler::isCtorOrDtor() const {
543 const Node *N = static_cast<const Node *>(RootNode);
544 while (N) {
545 switch (N->getKind()) {
546 default:
547 return false;
548 case Node::KCtorDtorName:
549 return true;
550
551 case Node::KAbiTagAttr:
552 N = static_cast<const AbiTagAttr *>(N)->Base;
553 break;
554 case Node::KFunctionEncoding:
555 N = static_cast<const FunctionEncoding *>(N)->getName();
556 break;
557 case Node::KLocalName:
558 N = static_cast<const LocalName *>(N)->Entity;
559 break;
560 case Node::KNameWithTemplateArgs:
561 N = static_cast<const NameWithTemplateArgs *>(N)->Name;
562 break;
563 case Node::KNestedName:
564 N = static_cast<const NestedName *>(N)->Name;
565 break;
566 case Node::KStdQualifiedName:
567 N = static_cast<const StdQualifiedName *>(N)->Child;
568 break;
569 }
570 }
571 return false;
572}
573
574bool ItaniumPartialDemangler::isFunction() const {
575 assert(RootNode != nullptr && "must call partialDemangle()");
576 return static_cast<const Node *>(RootNode)->getKind() ==
577 Node::KFunctionEncoding;
578}
579
580bool ItaniumPartialDemangler::isSpecialName() const {
581 assert(RootNode != nullptr && "must call partialDemangle()");
582 auto K = static_cast<const Node *>(RootNode)->getKind();
583 return K == Node::KSpecialName || K == Node::KCtorVtableSpecialName;
584}
585
586bool ItaniumPartialDemangler::isData() const {
587 return !isFunction() && !isSpecialName();
588}
diff --git a/externals/demangle/ItaniumDemangle.h b/externals/demangle/ItaniumDemangle.h
new file mode 100644
index 000000000..44ba428a5
--- /dev/null
+++ b/externals/demangle/ItaniumDemangle.h
@@ -0,0 +1,5582 @@
1//===------------------------- ItaniumDemangle.h ----------------*- 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-FileCopyrightText: Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
6// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7//
8//===----------------------------------------------------------------------===//
9//
10// Generic itanium demangler library. This file has two byte-per-byte identical
11// copies in the source tree, one in libcxxabi, and the other in llvm.
12//
13//===----------------------------------------------------------------------===//
14
15#ifndef DEMANGLE_ITANIUMDEMANGLE_H
16#define DEMANGLE_ITANIUMDEMANGLE_H
17
18// FIXME: (possibly) incomplete list of features that clang mangles that this
19// file does not yet support:
20// - C++ modules TS
21
22#include "DemangleConfig.h"
23#include "StringView.h"
24#include "Utility.h"
25#include <cassert>
26#include <cctype>
27#include <cstdio>
28#include <cstdlib>
29#include <cstring>
30#include <numeric>
31#include <utility>
32
33#define FOR_EACH_NODE_KIND(X) \
34 X(NodeArrayNode) \
35 X(DotSuffix) \
36 X(VendorExtQualType) \
37 X(QualType) \
38 X(ConversionOperatorType) \
39 X(PostfixQualifiedType) \
40 X(ElaboratedTypeSpefType) \
41 X(NameType) \
42 X(AbiTagAttr) \
43 X(EnableIfAttr) \
44 X(ObjCProtoName) \
45 X(PointerType) \
46 X(ReferenceType) \
47 X(PointerToMemberType) \
48 X(ArrayType) \
49 X(FunctionType) \
50 X(NoexceptSpec) \
51 X(DynamicExceptionSpec) \
52 X(FunctionEncoding) \
53 X(LiteralOperator) \
54 X(SpecialName) \
55 X(CtorVtableSpecialName) \
56 X(QualifiedName) \
57 X(NestedName) \
58 X(LocalName) \
59 X(VectorType) \
60 X(PixelVectorType) \
61 X(SyntheticTemplateParamName) \
62 X(TypeTemplateParamDecl) \
63 X(NonTypeTemplateParamDecl) \
64 X(TemplateTemplateParamDecl) \
65 X(TemplateParamPackDecl) \
66 X(ParameterPack) \
67 X(TemplateArgumentPack) \
68 X(ParameterPackExpansion) \
69 X(TemplateArgs) \
70 X(ForwardTemplateReference) \
71 X(NameWithTemplateArgs) \
72 X(GlobalQualifiedName) \
73 X(StdQualifiedName) \
74 X(ExpandedSpecialSubstitution) \
75 X(SpecialSubstitution) \
76 X(CtorDtorName) \
77 X(DtorName) \
78 X(UnnamedTypeName) \
79 X(ClosureTypeName) \
80 X(StructuredBindingName) \
81 X(BinaryExpr) \
82 X(ArraySubscriptExpr) \
83 X(PostfixExpr) \
84 X(ConditionalExpr) \
85 X(MemberExpr) \
86 X(EnclosingExpr) \
87 X(CastExpr) \
88 X(SizeofParamPackExpr) \
89 X(CallExpr) \
90 X(NewExpr) \
91 X(DeleteExpr) \
92 X(PrefixExpr) \
93 X(FunctionParam) \
94 X(ConversionExpr) \
95 X(InitListExpr) \
96 X(FoldExpr) \
97 X(ThrowExpr) \
98 X(UUIDOfExpr) \
99 X(BoolExpr) \
100 X(StringLiteral) \
101 X(LambdaExpr) \
102 X(IntegerCastExpr) \
103 X(IntegerLiteral) \
104 X(FloatLiteral) \
105 X(DoubleLiteral) \
106 X(LongDoubleLiteral) \
107 X(BracedExpr) \
108 X(BracedRangeExpr)
109
110DEMANGLE_NAMESPACE_BEGIN
111
112// Base class of all AST nodes. The AST is built by the parser, then is
113// traversed by the printLeft/Right functions to produce a demangled string.
114class Node {
115public:
116 enum Kind : unsigned char {
117#define ENUMERATOR(NodeKind) K ## NodeKind,
118 FOR_EACH_NODE_KIND(ENUMERATOR)
119#undef ENUMERATOR
120 };
121
122 /// Three-way bool to track a cached value. Unknown is possible if this node
123 /// has an unexpanded parameter pack below it that may affect this cache.
124 enum class Cache : unsigned char { Yes, No, Unknown, };
125
126private:
127 Kind K;
128
129 // FIXME: Make these protected.
130public:
131 /// Tracks if this node has a component on its right side, in which case we
132 /// need to call printRight.
133 Cache RHSComponentCache;
134
135 /// Track if this node is a (possibly qualified) array type. This can affect
136 /// how we format the output string.
137 Cache ArrayCache;
138
139 /// Track if this node is a (possibly qualified) function type. This can
140 /// affect how we format the output string.
141 Cache FunctionCache;
142
143public:
144 Node(Kind K_, Cache RHSComponentCache_ = Cache::No,
145 Cache ArrayCache_ = Cache::No, Cache FunctionCache_ = Cache::No)
146 : K(K_), RHSComponentCache(RHSComponentCache_), ArrayCache(ArrayCache_),
147 FunctionCache(FunctionCache_) {}
148
149 /// Visit the most-derived object corresponding to this object.
150 template<typename Fn> void visit(Fn F) const;
151
152 // The following function is provided by all derived classes:
153 //
154 // Call F with arguments that, when passed to the constructor of this node,
155 // would construct an equivalent node.
156 //template<typename Fn> void match(Fn F) const;
157
158 bool hasRHSComponent(OutputStream &S) const {
159 if (RHSComponentCache != Cache::Unknown)
160 return RHSComponentCache == Cache::Yes;
161 return hasRHSComponentSlow(S);
162 }
163
164 bool hasArray(OutputStream &S) const {
165 if (ArrayCache != Cache::Unknown)
166 return ArrayCache == Cache::Yes;
167 return hasArraySlow(S);
168 }
169
170 bool hasFunction(OutputStream &S) const {
171 if (FunctionCache != Cache::Unknown)
172 return FunctionCache == Cache::Yes;
173 return hasFunctionSlow(S);
174 }
175
176 Kind getKind() const { return K; }
177
178 virtual bool hasRHSComponentSlow(OutputStream &) const { return false; }
179 virtual bool hasArraySlow(OutputStream &) const { return false; }
180 virtual bool hasFunctionSlow(OutputStream &) const { return false; }
181
182 // Dig through "glue" nodes like ParameterPack and ForwardTemplateReference to
183 // get at a node that actually represents some concrete syntax.
184 virtual const Node *getSyntaxNode(OutputStream &) const {
185 return this;
186 }
187
188 void print(OutputStream &S) const {
189 printLeft(S);
190 if (RHSComponentCache != Cache::No)
191 printRight(S);
192 }
193
194 // Print the "left" side of this Node into OutputStream.
195 virtual void printLeft(OutputStream &) const = 0;
196
197 // Print the "right". This distinction is necessary to represent C++ types
198 // that appear on the RHS of their subtype, such as arrays or functions.
199 // Since most types don't have such a component, provide a default
200 // implementation.
201 virtual void printRight(OutputStream &) const {}
202
203 virtual StringView getBaseName() const { return StringView(); }
204
205 // Silence compiler warnings, this dtor will never be called.
206 virtual ~Node() = default;
207
208#ifndef NDEBUG
209 DEMANGLE_DUMP_METHOD void dump() const;
210#endif
211};
212
213class NodeArray {
214 Node **Elements;
215 size_t NumElements;
216
217public:
218 NodeArray() : Elements(nullptr), NumElements(0) {}
219 NodeArray(Node **Elements_, size_t NumElements_)
220 : Elements(Elements_), NumElements(NumElements_) {}
221
222 bool empty() const { return NumElements == 0; }
223 size_t size() const { return NumElements; }
224
225 Node **begin() const { return Elements; }
226 Node **end() const { return Elements + NumElements; }
227
228 Node *operator[](size_t Idx) const { return Elements[Idx]; }
229
230 void printWithComma(OutputStream &S) const {
231 bool FirstElement = true;
232 for (size_t Idx = 0; Idx != NumElements; ++Idx) {
233 size_t BeforeComma = S.getCurrentPosition();
234 if (!FirstElement)
235 S += ", ";
236 size_t AfterComma = S.getCurrentPosition();
237 Elements[Idx]->print(S);
238
239 // Elements[Idx] is an empty parameter pack expansion, we should erase the
240 // comma we just printed.
241 if (AfterComma == S.getCurrentPosition()) {
242 S.setCurrentPosition(BeforeComma);
243 continue;
244 }
245
246 FirstElement = false;
247 }
248 }
249};
250
251struct NodeArrayNode : Node {
252 NodeArray Array;
253 NodeArrayNode(NodeArray Array_) : Node(KNodeArrayNode), Array(Array_) {}
254
255 template<typename Fn> void match(Fn F) const { F(Array); }
256
257 void printLeft(OutputStream &S) const override {
258 Array.printWithComma(S);
259 }
260};
261
262class DotSuffix final : public Node {
263 const Node *Prefix;
264 const StringView Suffix;
265
266public:
267 DotSuffix(const Node *Prefix_, StringView Suffix_)
268 : Node(KDotSuffix), Prefix(Prefix_), Suffix(Suffix_) {}
269
270 template<typename Fn> void match(Fn F) const { F(Prefix, Suffix); }
271
272 void printLeft(OutputStream &s) const override {
273 Prefix->print(s);
274 s += " (";
275 s += Suffix;
276 s += ")";
277 }
278};
279
280class VendorExtQualType final : public Node {
281 const Node *Ty;
282 StringView Ext;
283
284public:
285 VendorExtQualType(const Node *Ty_, StringView Ext_)
286 : Node(KVendorExtQualType), Ty(Ty_), Ext(Ext_) {}
287
288 template<typename Fn> void match(Fn F) const { F(Ty, Ext); }
289
290 void printLeft(OutputStream &S) const override {
291 Ty->print(S);
292 S += " ";
293 S += Ext;
294 }
295};
296
297enum FunctionRefQual : unsigned char {
298 FrefQualNone,
299 FrefQualLValue,
300 FrefQualRValue,
301};
302
303enum Qualifiers {
304 QualNone = 0,
305 QualConst = 0x1,
306 QualVolatile = 0x2,
307 QualRestrict = 0x4,
308};
309
310inline Qualifiers operator|=(Qualifiers &Q1, Qualifiers Q2) {
311 return Q1 = static_cast<Qualifiers>(Q1 | Q2);
312}
313
314class QualType final : public Node {
315protected:
316 const Qualifiers Quals;
317 const Node *Child;
318
319 void printQuals(OutputStream &S) const {
320 if (Quals & QualConst)
321 S += " const";
322 if (Quals & QualVolatile)
323 S += " volatile";
324 if (Quals & QualRestrict)
325 S += " restrict";
326 }
327
328public:
329 QualType(const Node *Child_, Qualifiers Quals_)
330 : Node(KQualType, Child_->RHSComponentCache,
331 Child_->ArrayCache, Child_->FunctionCache),
332 Quals(Quals_), Child(Child_) {}
333
334 template<typename Fn> void match(Fn F) const { F(Child, Quals); }
335
336 bool hasRHSComponentSlow(OutputStream &S) const override {
337 return Child->hasRHSComponent(S);
338 }
339 bool hasArraySlow(OutputStream &S) const override {
340 return Child->hasArray(S);
341 }
342 bool hasFunctionSlow(OutputStream &S) const override {
343 return Child->hasFunction(S);
344 }
345
346 void printLeft(OutputStream &S) const override {
347 Child->printLeft(S);
348 printQuals(S);
349 }
350
351 void printRight(OutputStream &S) const override { Child->printRight(S); }
352};
353
354class ConversionOperatorType final : public Node {
355 const Node *Ty;
356
357public:
358 ConversionOperatorType(const Node *Ty_)
359 : Node(KConversionOperatorType), Ty(Ty_) {}
360
361 template<typename Fn> void match(Fn F) const { F(Ty); }
362
363 void printLeft(OutputStream &S) const override {
364 S += "operator ";
365 Ty->print(S);
366 }
367};
368
369class PostfixQualifiedType final : public Node {
370 const Node *Ty;
371 const StringView Postfix;
372
373public:
374 PostfixQualifiedType(Node *Ty_, StringView Postfix_)
375 : Node(KPostfixQualifiedType), Ty(Ty_), Postfix(Postfix_) {}
376
377 template<typename Fn> void match(Fn F) const { F(Ty, Postfix); }
378
379 void printLeft(OutputStream &s) const override {
380 Ty->printLeft(s);
381 s += Postfix;
382 }
383};
384
385class NameType final : public Node {
386 const StringView Name;
387
388public:
389 NameType(StringView Name_) : Node(KNameType), Name(Name_) {}
390
391 template<typename Fn> void match(Fn F) const { F(Name); }
392
393 StringView getName() const { return Name; }
394 StringView getBaseName() const override { return Name; }
395
396 void printLeft(OutputStream &s) const override { s += Name; }
397};
398
399class ElaboratedTypeSpefType : public Node {
400 StringView Kind;
401 Node *Child;
402public:
403 ElaboratedTypeSpefType(StringView Kind_, Node *Child_)
404 : Node(KElaboratedTypeSpefType), Kind(Kind_), Child(Child_) {}
405
406 template<typename Fn> void match(Fn F) const { F(Kind, Child); }
407
408 void printLeft(OutputStream &S) const override {
409 S += Kind;
410 S += ' ';
411 Child->print(S);
412 }
413};
414
415struct AbiTagAttr : Node {
416 Node *Base;
417 StringView Tag;
418
419 AbiTagAttr(Node* Base_, StringView Tag_)
420 : Node(KAbiTagAttr, Base_->RHSComponentCache,
421 Base_->ArrayCache, Base_->FunctionCache),
422 Base(Base_), Tag(Tag_) {}
423
424 template<typename Fn> void match(Fn F) const { F(Base, Tag); }
425
426 void printLeft(OutputStream &S) const override {
427 Base->printLeft(S);
428 S += "[abi:";
429 S += Tag;
430 S += "]";
431 }
432};
433
434class EnableIfAttr : public Node {
435 NodeArray Conditions;
436public:
437 EnableIfAttr(NodeArray Conditions_)
438 : Node(KEnableIfAttr), Conditions(Conditions_) {}
439
440 template<typename Fn> void match(Fn F) const { F(Conditions); }
441
442 void printLeft(OutputStream &S) const override {
443 S += " [enable_if:";
444 Conditions.printWithComma(S);
445 S += ']';
446 }
447};
448
449class ObjCProtoName : public Node {
450 const Node *Ty;
451 StringView Protocol;
452
453 friend class PointerType;
454
455public:
456 ObjCProtoName(const Node *Ty_, StringView Protocol_)
457 : Node(KObjCProtoName), Ty(Ty_), Protocol(Protocol_) {}
458
459 template<typename Fn> void match(Fn F) const { F(Ty, Protocol); }
460
461 bool isObjCObject() const {
462 return Ty->getKind() == KNameType &&
463 static_cast<const NameType *>(Ty)->getName() == "objc_object";
464 }
465
466 void printLeft(OutputStream &S) const override {
467 Ty->print(S);
468 S += "<";
469 S += Protocol;
470 S += ">";
471 }
472};
473
474class PointerType final : public Node {
475 const Node *Pointee;
476
477public:
478 PointerType(const Node *Pointee_)
479 : Node(KPointerType, Pointee_->RHSComponentCache),
480 Pointee(Pointee_) {}
481
482 template<typename Fn> void match(Fn F) const { F(Pointee); }
483
484 bool hasRHSComponentSlow(OutputStream &S) const override {
485 return Pointee->hasRHSComponent(S);
486 }
487
488 void printLeft(OutputStream &s) const override {
489 // We rewrite objc_object<SomeProtocol>* into id<SomeProtocol>.
490 if (Pointee->getKind() != KObjCProtoName ||
491 !static_cast<const ObjCProtoName *>(Pointee)->isObjCObject()) {
492 Pointee->printLeft(s);
493 if (Pointee->hasArray(s))
494 s += " ";
495 if (Pointee->hasArray(s) || Pointee->hasFunction(s))
496 s += "(";
497 s += "*";
498 } else {
499 const auto *objcProto = static_cast<const ObjCProtoName *>(Pointee);
500 s += "id<";
501 s += objcProto->Protocol;
502 s += ">";
503 }
504 }
505
506 void printRight(OutputStream &s) const override {
507 if (Pointee->getKind() != KObjCProtoName ||
508 !static_cast<const ObjCProtoName *>(Pointee)->isObjCObject()) {
509 if (Pointee->hasArray(s) || Pointee->hasFunction(s))
510 s += ")";
511 Pointee->printRight(s);
512 }
513 }
514};
515
516enum class ReferenceKind {
517 LValue,
518 RValue,
519};
520
521// Represents either a LValue or an RValue reference type.
522class ReferenceType : public Node {
523 const Node *Pointee;
524 ReferenceKind RK;
525
526 mutable bool Printing = false;
527
528 // Dig through any refs to refs, collapsing the ReferenceTypes as we go. The
529 // rule here is rvalue ref to rvalue ref collapses to a rvalue ref, and any
530 // other combination collapses to a lvalue ref.
531 std::pair<ReferenceKind, const Node *> collapse(OutputStream &S) const {
532 auto SoFar = std::make_pair(RK, Pointee);
533 for (;;) {
534 const Node *SN = SoFar.second->getSyntaxNode(S);
535 if (SN->getKind() != KReferenceType)
536 break;
537 auto *RT = static_cast<const ReferenceType *>(SN);
538 SoFar.second = RT->Pointee;
539 SoFar.first = std::min(SoFar.first, RT->RK);
540 }
541 return SoFar;
542 }
543
544public:
545 ReferenceType(const Node *Pointee_, ReferenceKind RK_)
546 : Node(KReferenceType, Pointee_->RHSComponentCache),
547 Pointee(Pointee_), RK(RK_) {}
548
549 template<typename Fn> void match(Fn F) const { F(Pointee, RK); }
550
551 bool hasRHSComponentSlow(OutputStream &S) const override {
552 return Pointee->hasRHSComponent(S);
553 }
554
555 void printLeft(OutputStream &s) const override {
556 if (Printing)
557 return;
558 SwapAndRestore<bool> SavePrinting(Printing, true);
559 std::pair<ReferenceKind, const Node *> Collapsed = collapse(s);
560 Collapsed.second->printLeft(s);
561 if (Collapsed.second->hasArray(s))
562 s += " ";
563 if (Collapsed.second->hasArray(s) || Collapsed.second->hasFunction(s))
564 s += "(";
565
566 s += (Collapsed.first == ReferenceKind::LValue ? "&" : "&&");
567 }
568 void printRight(OutputStream &s) const override {
569 if (Printing)
570 return;
571 SwapAndRestore<bool> SavePrinting(Printing, true);
572 std::pair<ReferenceKind, const Node *> Collapsed = collapse(s);
573 if (Collapsed.second->hasArray(s) || Collapsed.second->hasFunction(s))
574 s += ")";
575 Collapsed.second->printRight(s);
576 }
577};
578
579class PointerToMemberType final : public Node {
580 const Node *ClassType;
581 const Node *MemberType;
582
583public:
584 PointerToMemberType(const Node *ClassType_, const Node *MemberType_)
585 : Node(KPointerToMemberType, MemberType_->RHSComponentCache),
586 ClassType(ClassType_), MemberType(MemberType_) {}
587
588 template<typename Fn> void match(Fn F) const { F(ClassType, MemberType); }
589
590 bool hasRHSComponentSlow(OutputStream &S) const override {
591 return MemberType->hasRHSComponent(S);
592 }
593
594 void printLeft(OutputStream &s) const override {
595 MemberType->printLeft(s);
596 if (MemberType->hasArray(s) || MemberType->hasFunction(s))
597 s += "(";
598 else
599 s += " ";
600 ClassType->print(s);
601 s += "::*";
602 }
603
604 void printRight(OutputStream &s) const override {
605 if (MemberType->hasArray(s) || MemberType->hasFunction(s))
606 s += ")";
607 MemberType->printRight(s);
608 }
609};
610
611class NodeOrString {
612 const void *First;
613 const void *Second;
614
615public:
616 /* implicit */ NodeOrString(StringView Str) {
617 const char *FirstChar = Str.begin();
618 const char *SecondChar = Str.end();
619 if (SecondChar == nullptr) {
620 assert(FirstChar == SecondChar);
621 ++FirstChar, ++SecondChar;
622 }
623 First = static_cast<const void *>(FirstChar);
624 Second = static_cast<const void *>(SecondChar);
625 }
626
627 /* implicit */ NodeOrString(Node *N)
628 : First(static_cast<const void *>(N)), Second(nullptr) {}
629 NodeOrString() : First(nullptr), Second(nullptr) {}
630
631 bool isString() const { return Second && First; }
632 bool isNode() const { return First && !Second; }
633 bool isEmpty() const { return !First && !Second; }
634
635 StringView asString() const {
636 assert(isString());
637 return StringView(static_cast<const char *>(First),
638 static_cast<const char *>(Second));
639 }
640
641 const Node *asNode() const {
642 assert(isNode());
643 return static_cast<const Node *>(First);
644 }
645};
646
647class ArrayType final : public Node {
648 const Node *Base;
649 NodeOrString Dimension;
650
651public:
652 ArrayType(const Node *Base_, NodeOrString Dimension_)
653 : Node(KArrayType,
654 /*RHSComponentCache=*/Cache::Yes,
655 /*ArrayCache=*/Cache::Yes),
656 Base(Base_), Dimension(Dimension_) {}
657
658 template<typename Fn> void match(Fn F) const { F(Base, Dimension); }
659
660 bool hasRHSComponentSlow(OutputStream &) const override { return true; }
661 bool hasArraySlow(OutputStream &) const override { return true; }
662
663 void printLeft(OutputStream &S) const override { Base->printLeft(S); }
664
665 void printRight(OutputStream &S) const override {
666 if (S.back() != ']')
667 S += " ";
668 S += "[";
669 if (Dimension.isString())
670 S += Dimension.asString();
671 else if (Dimension.isNode())
672 Dimension.asNode()->print(S);
673 S += "]";
674 Base->printRight(S);
675 }
676};
677
678class FunctionType final : public Node {
679 const Node *Ret;
680 NodeArray Params;
681 Qualifiers CVQuals;
682 FunctionRefQual RefQual;
683 const Node *ExceptionSpec;
684
685public:
686 FunctionType(const Node *Ret_, NodeArray Params_, Qualifiers CVQuals_,
687 FunctionRefQual RefQual_, const Node *ExceptionSpec_)
688 : Node(KFunctionType,
689 /*RHSComponentCache=*/Cache::Yes, /*ArrayCache=*/Cache::No,
690 /*FunctionCache=*/Cache::Yes),
691 Ret(Ret_), Params(Params_), CVQuals(CVQuals_), RefQual(RefQual_),
692 ExceptionSpec(ExceptionSpec_) {}
693
694 template<typename Fn> void match(Fn F) const {
695 F(Ret, Params, CVQuals, RefQual, ExceptionSpec);
696 }
697
698 bool hasRHSComponentSlow(OutputStream &) const override { return true; }
699 bool hasFunctionSlow(OutputStream &) const override { return true; }
700
701 // Handle C++'s ... quirky decl grammar by using the left & right
702 // distinction. Consider:
703 // int (*f(float))(char) {}
704 // f is a function that takes a float and returns a pointer to a function
705 // that takes a char and returns an int. If we're trying to print f, start
706 // by printing out the return types's left, then print our parameters, then
707 // finally print right of the return type.
708 void printLeft(OutputStream &S) const override {
709 Ret->printLeft(S);
710 S += " ";
711 }
712
713 void printRight(OutputStream &S) const override {
714 S += "(";
715 Params.printWithComma(S);
716 S += ")";
717 Ret->printRight(S);
718
719 if (CVQuals & QualConst)
720 S += " const";
721 if (CVQuals & QualVolatile)
722 S += " volatile";
723 if (CVQuals & QualRestrict)
724 S += " restrict";
725
726 if (RefQual == FrefQualLValue)
727 S += " &";
728 else if (RefQual == FrefQualRValue)
729 S += " &&";
730
731 if (ExceptionSpec != nullptr) {
732 S += ' ';
733 ExceptionSpec->print(S);
734 }
735 }
736};
737
738class NoexceptSpec : public Node {
739 const Node *E;
740public:
741 NoexceptSpec(const Node *E_) : Node(KNoexceptSpec), E(E_) {}
742
743 template<typename Fn> void match(Fn F) const { F(E); }
744
745 void printLeft(OutputStream &S) const override {
746 S += "noexcept(";
747 E->print(S);
748 S += ")";
749 }
750};
751
752class DynamicExceptionSpec : public Node {
753 NodeArray Types;
754public:
755 DynamicExceptionSpec(NodeArray Types_)
756 : Node(KDynamicExceptionSpec), Types(Types_) {}
757
758 template<typename Fn> void match(Fn F) const { F(Types); }
759
760 void printLeft(OutputStream &S) const override {
761 S += "throw(";
762 Types.printWithComma(S);
763 S += ')';
764 }
765};
766
767class FunctionEncoding final : public Node {
768 const Node *Ret;
769 const Node *Name;
770 NodeArray Params;
771 const Node *Attrs;
772 Qualifiers CVQuals;
773 FunctionRefQual RefQual;
774
775public:
776 FunctionEncoding(const Node *Ret_, const Node *Name_, NodeArray Params_,
777 const Node *Attrs_, Qualifiers CVQuals_,
778 FunctionRefQual RefQual_)
779 : Node(KFunctionEncoding,
780 /*RHSComponentCache=*/Cache::Yes, /*ArrayCache=*/Cache::No,
781 /*FunctionCache=*/Cache::Yes),
782 Ret(Ret_), Name(Name_), Params(Params_), Attrs(Attrs_),
783 CVQuals(CVQuals_), RefQual(RefQual_) {}
784
785 template<typename Fn> void match(Fn F) const {
786 F(Ret, Name, Params, Attrs, CVQuals, RefQual);
787 }
788
789 Qualifiers getCVQuals() const { return CVQuals; }
790 FunctionRefQual getRefQual() const { return RefQual; }
791 NodeArray getParams() const { return Params; }
792 const Node *getReturnType() const { return Ret; }
793
794 bool hasRHSComponentSlow(OutputStream &) const override { return true; }
795 bool hasFunctionSlow(OutputStream &) const override { return true; }
796
797 const Node *getName() const { return Name; }
798
799 void printLeft(OutputStream &S) const override {
800 if (Ret) {
801 Ret->printLeft(S);
802 if (!Ret->hasRHSComponent(S))
803 S += " ";
804 }
805 Name->print(S);
806 }
807
808 void printRight(OutputStream &S) const override {
809 S += "(";
810 Params.printWithComma(S);
811 S += ")";
812 if (Ret)
813 Ret->printRight(S);
814
815 if (CVQuals & QualConst)
816 S += " const";
817 if (CVQuals & QualVolatile)
818 S += " volatile";
819 if (CVQuals & QualRestrict)
820 S += " restrict";
821
822 if (RefQual == FrefQualLValue)
823 S += " &";
824 else if (RefQual == FrefQualRValue)
825 S += " &&";
826
827 if (Attrs != nullptr)
828 Attrs->print(S);
829 }
830};
831
832class LiteralOperator : public Node {
833 const Node *OpName;
834
835public:
836 LiteralOperator(const Node *OpName_)
837 : Node(KLiteralOperator), OpName(OpName_) {}
838
839 template<typename Fn> void match(Fn F) const { F(OpName); }
840
841 void printLeft(OutputStream &S) const override {
842 S += "operator\"\" ";
843 OpName->print(S);
844 }
845};
846
847class SpecialName final : public Node {
848 const StringView Special;
849 const Node *Child;
850
851public:
852 SpecialName(StringView Special_, const Node *Child_)
853 : Node(KSpecialName), Special(Special_), Child(Child_) {}
854
855 template<typename Fn> void match(Fn F) const { F(Special, Child); }
856
857 void printLeft(OutputStream &S) const override {
858 S += Special;
859 Child->print(S);
860 }
861};
862
863class CtorVtableSpecialName final : public Node {
864 const Node *FirstType;
865 const Node *SecondType;
866
867public:
868 CtorVtableSpecialName(const Node *FirstType_, const Node *SecondType_)
869 : Node(KCtorVtableSpecialName),
870 FirstType(FirstType_), SecondType(SecondType_) {}
871
872 template<typename Fn> void match(Fn F) const { F(FirstType, SecondType); }
873
874 void printLeft(OutputStream &S) const override {
875 S += "construction vtable for ";
876 FirstType->print(S);
877 S += "-in-";
878 SecondType->print(S);
879 }
880};
881
882struct NestedName : Node {
883 Node *Qual;
884 Node *Name;
885
886 NestedName(Node *Qual_, Node *Name_)
887 : Node(KNestedName), Qual(Qual_), Name(Name_) {}
888
889 template<typename Fn> void match(Fn F) const { F(Qual, Name); }
890
891 StringView getBaseName() const override { return Name->getBaseName(); }
892
893 void printLeft(OutputStream &S) const override {
894 Qual->print(S);
895 S += "::";
896 Name->print(S);
897 }
898};
899
900struct LocalName : Node {
901 Node *Encoding;
902 Node *Entity;
903
904 LocalName(Node *Encoding_, Node *Entity_)
905 : Node(KLocalName), Encoding(Encoding_), Entity(Entity_) {}
906
907 template<typename Fn> void match(Fn F) const { F(Encoding, Entity); }
908
909 void printLeft(OutputStream &S) const override {
910 Encoding->print(S);
911 S += "::";
912 Entity->print(S);
913 }
914};
915
916class QualifiedName final : public Node {
917 // qualifier::name
918 const Node *Qualifier;
919 const Node *Name;
920
921public:
922 QualifiedName(const Node *Qualifier_, const Node *Name_)
923 : Node(KQualifiedName), Qualifier(Qualifier_), Name(Name_) {}
924
925 template<typename Fn> void match(Fn F) const { F(Qualifier, Name); }
926
927 StringView getBaseName() const override { return Name->getBaseName(); }
928
929 void printLeft(OutputStream &S) const override {
930 Qualifier->print(S);
931 S += "::";
932 Name->print(S);
933 }
934};
935
936class VectorType final : public Node {
937 const Node *BaseType;
938 const NodeOrString Dimension;
939
940public:
941 VectorType(const Node *BaseType_, NodeOrString Dimension_)
942 : Node(KVectorType), BaseType(BaseType_),
943 Dimension(Dimension_) {}
944
945 template<typename Fn> void match(Fn F) const { F(BaseType, Dimension); }
946
947 void printLeft(OutputStream &S) const override {
948 BaseType->print(S);
949 S += " vector[";
950 if (Dimension.isNode())
951 Dimension.asNode()->print(S);
952 else if (Dimension.isString())
953 S += Dimension.asString();
954 S += "]";
955 }
956};
957
958class PixelVectorType final : public Node {
959 const NodeOrString Dimension;
960
961public:
962 PixelVectorType(NodeOrString Dimension_)
963 : Node(KPixelVectorType), Dimension(Dimension_) {}
964
965 template<typename Fn> void match(Fn F) const { F(Dimension); }
966
967 void printLeft(OutputStream &S) const override {
968 // FIXME: This should demangle as "vector pixel".
969 S += "pixel vector[";
970 S += Dimension.asString();
971 S += "]";
972 }
973};
974
975enum class TemplateParamKind { Type, NonType, Template };
976
977/// An invented name for a template parameter for which we don't have a
978/// corresponding template argument.
979///
980/// This node is created when parsing the <lambda-sig> for a lambda with
981/// explicit template arguments, which might be referenced in the parameter
982/// types appearing later in the <lambda-sig>.
983class SyntheticTemplateParamName final : public Node {
984 TemplateParamKind Kind;
985 unsigned Index;
986
987public:
988 SyntheticTemplateParamName(TemplateParamKind Kind_, unsigned Index_)
989 : Node(KSyntheticTemplateParamName), Kind(Kind_), Index(Index_) {}
990
991 template<typename Fn> void match(Fn F) const { F(Kind, Index); }
992
993 void printLeft(OutputStream &S) const override {
994 switch (Kind) {
995 case TemplateParamKind::Type:
996 S += "$T";
997 break;
998 case TemplateParamKind::NonType:
999 S += "$N";
1000 break;
1001 case TemplateParamKind::Template:
1002 S += "$TT";
1003 break;
1004 }
1005 if (Index > 0)
1006 S << Index - 1;
1007 }
1008};
1009
1010/// A template type parameter declaration, 'typename T'.
1011class TypeTemplateParamDecl final : public Node {
1012 Node *Name;
1013
1014public:
1015 TypeTemplateParamDecl(Node *Name_)
1016 : Node(KTypeTemplateParamDecl, Cache::Yes), Name(Name_) {}
1017
1018 template<typename Fn> void match(Fn F) const { F(Name); }
1019
1020 void printLeft(OutputStream &S) const override {
1021 S += "typename ";
1022 }
1023
1024 void printRight(OutputStream &S) const override {
1025 Name->print(S);
1026 }
1027};
1028
1029/// A non-type template parameter declaration, 'int N'.
1030class NonTypeTemplateParamDecl final : public Node {
1031 Node *Name;
1032 Node *Type;
1033
1034public:
1035 NonTypeTemplateParamDecl(Node *Name_, Node *Type_)
1036 : Node(KNonTypeTemplateParamDecl, Cache::Yes), Name(Name_), Type(Type_) {}
1037
1038 template<typename Fn> void match(Fn F) const { F(Name, Type); }
1039
1040 void printLeft(OutputStream &S) const override {
1041 Type->printLeft(S);
1042 if (!Type->hasRHSComponent(S))
1043 S += " ";
1044 }
1045
1046 void printRight(OutputStream &S) const override {
1047 Name->print(S);
1048 Type->printRight(S);
1049 }
1050};
1051
1052/// A template template parameter declaration,
1053/// 'template<typename T> typename N'.
1054class TemplateTemplateParamDecl final : public Node {
1055 Node *Name;
1056 NodeArray Params;
1057
1058public:
1059 TemplateTemplateParamDecl(Node *Name_, NodeArray Params_)
1060 : Node(KTemplateTemplateParamDecl, Cache::Yes), Name(Name_),
1061 Params(Params_) {}
1062
1063 template<typename Fn> void match(Fn F) const { F(Name, Params); }
1064
1065 void printLeft(OutputStream &S) const override {
1066 S += "template<";
1067 Params.printWithComma(S);
1068 S += "> typename ";
1069 }
1070
1071 void printRight(OutputStream &S) const override {
1072 Name->print(S);
1073 }
1074};
1075
1076/// A template parameter pack declaration, 'typename ...T'.
1077class TemplateParamPackDecl final : public Node {
1078 Node *Param;
1079
1080public:
1081 TemplateParamPackDecl(Node *Param_)
1082 : Node(KTemplateParamPackDecl, Cache::Yes), Param(Param_) {}
1083
1084 template<typename Fn> void match(Fn F) const { F(Param); }
1085
1086 void printLeft(OutputStream &S) const override {
1087 Param->printLeft(S);
1088 S += "...";
1089 }
1090
1091 void printRight(OutputStream &S) const override {
1092 Param->printRight(S);
1093 }
1094};
1095
1096/// An unexpanded parameter pack (either in the expression or type context). If
1097/// this AST is correct, this node will have a ParameterPackExpansion node above
1098/// it.
1099///
1100/// This node is created when some <template-args> are found that apply to an
1101/// <encoding>, and is stored in the TemplateParams table. In order for this to
1102/// appear in the final AST, it has to referenced via a <template-param> (ie,
1103/// T_).
1104class ParameterPack final : public Node {
1105 NodeArray Data;
1106
1107 // Setup OutputStream for a pack expansion unless we're already expanding one.
1108 void initializePackExpansion(OutputStream &S) const {
1109 if (S.CurrentPackMax == std::numeric_limits<unsigned>::max()) {
1110 S.CurrentPackMax = static_cast<unsigned>(Data.size());
1111 S.CurrentPackIndex = 0;
1112 }
1113 }
1114
1115public:
1116 ParameterPack(NodeArray Data_) : Node(KParameterPack), Data(Data_) {
1117 ArrayCache = FunctionCache = RHSComponentCache = Cache::Unknown;
1118 if (std::all_of(Data.begin(), Data.end(), [](Node* P) {
1119 return P->ArrayCache == Cache::No;
1120 }))
1121 ArrayCache = Cache::No;
1122 if (std::all_of(Data.begin(), Data.end(), [](Node* P) {
1123 return P->FunctionCache == Cache::No;
1124 }))
1125 FunctionCache = Cache::No;
1126 if (std::all_of(Data.begin(), Data.end(), [](Node* P) {
1127 return P->RHSComponentCache == Cache::No;
1128 }))
1129 RHSComponentCache = Cache::No;
1130 }
1131
1132 template<typename Fn> void match(Fn F) const { F(Data); }
1133
1134 bool hasRHSComponentSlow(OutputStream &S) const override {
1135 initializePackExpansion(S);
1136 size_t Idx = S.CurrentPackIndex;
1137 return Idx < Data.size() && Data[Idx]->hasRHSComponent(S);
1138 }
1139 bool hasArraySlow(OutputStream &S) const override {
1140 initializePackExpansion(S);
1141 size_t Idx = S.CurrentPackIndex;
1142 return Idx < Data.size() && Data[Idx]->hasArray(S);
1143 }
1144 bool hasFunctionSlow(OutputStream &S) const override {
1145 initializePackExpansion(S);
1146 size_t Idx = S.CurrentPackIndex;
1147 return Idx < Data.size() && Data[Idx]->hasFunction(S);
1148 }
1149 const Node *getSyntaxNode(OutputStream &S) const override {
1150 initializePackExpansion(S);
1151 size_t Idx = S.CurrentPackIndex;
1152 return Idx < Data.size() ? Data[Idx]->getSyntaxNode(S) : this;
1153 }
1154
1155 void printLeft(OutputStream &S) const override {
1156 initializePackExpansion(S);
1157 size_t Idx = S.CurrentPackIndex;
1158 if (Idx < Data.size())
1159 Data[Idx]->printLeft(S);
1160 }
1161 void printRight(OutputStream &S) const override {
1162 initializePackExpansion(S);
1163 size_t Idx = S.CurrentPackIndex;
1164 if (Idx < Data.size())
1165 Data[Idx]->printRight(S);
1166 }
1167};
1168
1169/// A variadic template argument. This node represents an occurrence of
1170/// J<something>E in some <template-args>. It isn't itself unexpanded, unless
1171/// one of it's Elements is. The parser inserts a ParameterPack into the
1172/// TemplateParams table if the <template-args> this pack belongs to apply to an
1173/// <encoding>.
1174class TemplateArgumentPack final : public Node {
1175 NodeArray Elements;
1176public:
1177 TemplateArgumentPack(NodeArray Elements_)
1178 : Node(KTemplateArgumentPack), Elements(Elements_) {}
1179
1180 template<typename Fn> void match(Fn F) const { F(Elements); }
1181
1182 NodeArray getElements() const { return Elements; }
1183
1184 void printLeft(OutputStream &S) const override {
1185 Elements.printWithComma(S);
1186 }
1187};
1188
1189/// A pack expansion. Below this node, there are some unexpanded ParameterPacks
1190/// which each have Child->ParameterPackSize elements.
1191class ParameterPackExpansion final : public Node {
1192 const Node *Child;
1193
1194public:
1195 ParameterPackExpansion(const Node *Child_)
1196 : Node(KParameterPackExpansion), Child(Child_) {}
1197
1198 template<typename Fn> void match(Fn F) const { F(Child); }
1199
1200 const Node *getChild() const { return Child; }
1201
1202 void printLeft(OutputStream &S) const override {
1203 constexpr unsigned Max = std::numeric_limits<unsigned>::max();
1204 SwapAndRestore<unsigned> SavePackIdx(S.CurrentPackIndex, Max);
1205 SwapAndRestore<unsigned> SavePackMax(S.CurrentPackMax, Max);
1206 size_t StreamPos = S.getCurrentPosition();
1207
1208 // Print the first element in the pack. If Child contains a ParameterPack,
1209 // it will set up S.CurrentPackMax and print the first element.
1210 Child->print(S);
1211
1212 // No ParameterPack was found in Child. This can occur if we've found a pack
1213 // expansion on a <function-param>.
1214 if (S.CurrentPackMax == Max) {
1215 S += "...";
1216 return;
1217 }
1218
1219 // We found a ParameterPack, but it has no elements. Erase whatever we may
1220 // of printed.
1221 if (S.CurrentPackMax == 0) {
1222 S.setCurrentPosition(StreamPos);
1223 return;
1224 }
1225
1226 // Else, iterate through the rest of the elements in the pack.
1227 for (unsigned I = 1, E = S.CurrentPackMax; I < E; ++I) {
1228 S += ", ";
1229 S.CurrentPackIndex = I;
1230 Child->print(S);
1231 }
1232 }
1233};
1234
1235class TemplateArgs final : public Node {
1236 NodeArray Params;
1237
1238public:
1239 TemplateArgs(NodeArray Params_) : Node(KTemplateArgs), Params(Params_) {}
1240
1241 template<typename Fn> void match(Fn F) const { F(Params); }
1242
1243 NodeArray getParams() { return Params; }
1244
1245 void printLeft(OutputStream &S) const override {
1246 S += "<";
1247 Params.printWithComma(S);
1248 if (S.back() == '>')
1249 S += " ";
1250 S += ">";
1251 }
1252};
1253
1254/// A forward-reference to a template argument that was not known at the point
1255/// where the template parameter name was parsed in a mangling.
1256///
1257/// This is created when demangling the name of a specialization of a
1258/// conversion function template:
1259///
1260/// \code
1261/// struct A {
1262/// template<typename T> operator T*();
1263/// };
1264/// \endcode
1265///
1266/// When demangling a specialization of the conversion function template, we
1267/// encounter the name of the template (including the \c T) before we reach
1268/// the template argument list, so we cannot substitute the parameter name
1269/// for the corresponding argument while parsing. Instead, we create a
1270/// \c ForwardTemplateReference node that is resolved after we parse the
1271/// template arguments.
1272struct ForwardTemplateReference : Node {
1273 size_t Index;
1274 Node *Ref = nullptr;
1275
1276 // If we're currently printing this node. It is possible (though invalid) for
1277 // a forward template reference to refer to itself via a substitution. This
1278 // creates a cyclic AST, which will stack overflow printing. To fix this, bail
1279 // out if more than one print* function is active.
1280 mutable bool Printing = false;
1281
1282 ForwardTemplateReference(size_t Index_)
1283 : Node(KForwardTemplateReference, Cache::Unknown, Cache::Unknown,
1284 Cache::Unknown),
1285 Index(Index_) {}
1286
1287 // We don't provide a matcher for these, because the value of the node is
1288 // not determined by its construction parameters, and it generally needs
1289 // special handling.
1290 template<typename Fn> void match(Fn F) const = delete;
1291
1292 bool hasRHSComponentSlow(OutputStream &S) const override {
1293 if (Printing)
1294 return false;
1295 SwapAndRestore<bool> SavePrinting(Printing, true);
1296 return Ref->hasRHSComponent(S);
1297 }
1298 bool hasArraySlow(OutputStream &S) const override {
1299 if (Printing)
1300 return false;
1301 SwapAndRestore<bool> SavePrinting(Printing, true);
1302 return Ref->hasArray(S);
1303 }
1304 bool hasFunctionSlow(OutputStream &S) const override {
1305 if (Printing)
1306 return false;
1307 SwapAndRestore<bool> SavePrinting(Printing, true);
1308 return Ref->hasFunction(S);
1309 }
1310 const Node *getSyntaxNode(OutputStream &S) const override {
1311 if (Printing)
1312 return this;
1313 SwapAndRestore<bool> SavePrinting(Printing, true);
1314 return Ref->getSyntaxNode(S);
1315 }
1316
1317 void printLeft(OutputStream &S) const override {
1318 if (Printing)
1319 return;
1320 SwapAndRestore<bool> SavePrinting(Printing, true);
1321 Ref->printLeft(S);
1322 }
1323 void printRight(OutputStream &S) const override {
1324 if (Printing)
1325 return;
1326 SwapAndRestore<bool> SavePrinting(Printing, true);
1327 Ref->printRight(S);
1328 }
1329};
1330
1331struct NameWithTemplateArgs : Node {
1332 // name<template_args>
1333 Node *Name;
1334 Node *TemplateArgs;
1335
1336 NameWithTemplateArgs(Node *Name_, Node *TemplateArgs_)
1337 : Node(KNameWithTemplateArgs), Name(Name_), TemplateArgs(TemplateArgs_) {}
1338
1339 template<typename Fn> void match(Fn F) const { F(Name, TemplateArgs); }
1340
1341 StringView getBaseName() const override { return Name->getBaseName(); }
1342
1343 void printLeft(OutputStream &S) const override {
1344 Name->print(S);
1345 TemplateArgs->print(S);
1346 }
1347};
1348
1349class GlobalQualifiedName final : public Node {
1350 Node *Child;
1351
1352public:
1353 GlobalQualifiedName(Node* Child_)
1354 : Node(KGlobalQualifiedName), Child(Child_) {}
1355
1356 template<typename Fn> void match(Fn F) const { F(Child); }
1357
1358 StringView getBaseName() const override { return Child->getBaseName(); }
1359
1360 void printLeft(OutputStream &S) const override {
1361 S += "::";
1362 Child->print(S);
1363 }
1364};
1365
1366struct StdQualifiedName : Node {
1367 Node *Child;
1368
1369 StdQualifiedName(Node *Child_) : Node(KStdQualifiedName), Child(Child_) {}
1370
1371 template<typename Fn> void match(Fn F) const { F(Child); }
1372
1373 StringView getBaseName() const override { return Child->getBaseName(); }
1374
1375 void printLeft(OutputStream &S) const override {
1376 S += "std::";
1377 Child->print(S);
1378 }
1379};
1380
1381enum class SpecialSubKind {
1382 allocator,
1383 basic_string,
1384 string,
1385 istream,
1386 ostream,
1387 iostream,
1388};
1389
1390class ExpandedSpecialSubstitution final : public Node {
1391 SpecialSubKind SSK;
1392
1393public:
1394 ExpandedSpecialSubstitution(SpecialSubKind SSK_)
1395 : Node(KExpandedSpecialSubstitution), SSK(SSK_) {}
1396
1397 template<typename Fn> void match(Fn F) const { F(SSK); }
1398
1399 StringView getBaseName() const override {
1400 switch (SSK) {
1401 case SpecialSubKind::allocator:
1402 return StringView("allocator");
1403 case SpecialSubKind::basic_string:
1404 return StringView("basic_string");
1405 case SpecialSubKind::string:
1406 return StringView("basic_string");
1407 case SpecialSubKind::istream:
1408 return StringView("basic_istream");
1409 case SpecialSubKind::ostream:
1410 return StringView("basic_ostream");
1411 case SpecialSubKind::iostream:
1412 return StringView("basic_iostream");
1413 }
1414 DEMANGLE_UNREACHABLE;
1415 }
1416
1417 void printLeft(OutputStream &S) const override {
1418 switch (SSK) {
1419 case SpecialSubKind::allocator:
1420 S += "std::allocator";
1421 break;
1422 case SpecialSubKind::basic_string:
1423 S += "std::basic_string";
1424 break;
1425 case SpecialSubKind::string:
1426 S += "std::basic_string<char, std::char_traits<char>, "
1427 "std::allocator<char> >";
1428 break;
1429 case SpecialSubKind::istream:
1430 S += "std::basic_istream<char, std::char_traits<char> >";
1431 break;
1432 case SpecialSubKind::ostream:
1433 S += "std::basic_ostream<char, std::char_traits<char> >";
1434 break;
1435 case SpecialSubKind::iostream:
1436 S += "std::basic_iostream<char, std::char_traits<char> >";
1437 break;
1438 }
1439 }
1440};
1441
1442class SpecialSubstitution final : public Node {
1443public:
1444 SpecialSubKind SSK;
1445
1446 SpecialSubstitution(SpecialSubKind SSK_)
1447 : Node(KSpecialSubstitution), SSK(SSK_) {}
1448
1449 template<typename Fn> void match(Fn F) const { F(SSK); }
1450
1451 StringView getBaseName() const override {
1452 switch (SSK) {
1453 case SpecialSubKind::allocator:
1454 return StringView("allocator");
1455 case SpecialSubKind::basic_string:
1456 return StringView("basic_string");
1457 case SpecialSubKind::string:
1458 return StringView("string");
1459 case SpecialSubKind::istream:
1460 return StringView("istream");
1461 case SpecialSubKind::ostream:
1462 return StringView("ostream");
1463 case SpecialSubKind::iostream:
1464 return StringView("iostream");
1465 }
1466 DEMANGLE_UNREACHABLE;
1467 }
1468
1469 void printLeft(OutputStream &S) const override {
1470 switch (SSK) {
1471 case SpecialSubKind::allocator:
1472 S += "std::allocator";
1473 break;
1474 case SpecialSubKind::basic_string:
1475 S += "std::basic_string";
1476 break;
1477 case SpecialSubKind::string:
1478 S += "std::string";
1479 break;
1480 case SpecialSubKind::istream:
1481 S += "std::istream";
1482 break;
1483 case SpecialSubKind::ostream:
1484 S += "std::ostream";
1485 break;
1486 case SpecialSubKind::iostream:
1487 S += "std::iostream";
1488 break;
1489 }
1490 }
1491};
1492
1493class CtorDtorName final : public Node {
1494 const Node *Basename;
1495 const bool IsDtor;
1496 const int Variant;
1497
1498public:
1499 CtorDtorName(const Node *Basename_, bool IsDtor_, int Variant_)
1500 : Node(KCtorDtorName), Basename(Basename_), IsDtor(IsDtor_),
1501 Variant(Variant_) {}
1502
1503 template<typename Fn> void match(Fn F) const { F(Basename, IsDtor, Variant); }
1504
1505 void printLeft(OutputStream &S) const override {
1506 if (IsDtor)
1507 S += "~";
1508 S += Basename->getBaseName();
1509 }
1510};
1511
1512class DtorName : public Node {
1513 const Node *Base;
1514
1515public:
1516 DtorName(const Node *Base_) : Node(KDtorName), Base(Base_) {}
1517
1518 template<typename Fn> void match(Fn F) const { F(Base); }
1519
1520 void printLeft(OutputStream &S) const override {
1521 S += "~";
1522 Base->printLeft(S);
1523 }
1524};
1525
1526class UnnamedTypeName : public Node {
1527 const StringView Count;
1528
1529public:
1530 UnnamedTypeName(StringView Count_) : Node(KUnnamedTypeName), Count(Count_) {}
1531
1532 template<typename Fn> void match(Fn F) const { F(Count); }
1533
1534 void printLeft(OutputStream &S) const override {
1535 S += "'unnamed";
1536 S += Count;
1537 S += "\'";
1538 }
1539};
1540
1541class ClosureTypeName : public Node {
1542 NodeArray TemplateParams;
1543 NodeArray Params;
1544 StringView Count;
1545
1546public:
1547 ClosureTypeName(NodeArray TemplateParams_, NodeArray Params_,
1548 StringView Count_)
1549 : Node(KClosureTypeName), TemplateParams(TemplateParams_),
1550 Params(Params_), Count(Count_) {}
1551
1552 template<typename Fn> void match(Fn F) const {
1553 F(TemplateParams, Params, Count);
1554 }
1555
1556 void printDeclarator(OutputStream &S) const {
1557 if (!TemplateParams.empty()) {
1558 S += "<";
1559 TemplateParams.printWithComma(S);
1560 S += ">";
1561 }
1562 S += "(";
1563 Params.printWithComma(S);
1564 S += ")";
1565 }
1566
1567 void printLeft(OutputStream &S) const override {
1568 S += "\'lambda";
1569 S += Count;
1570 S += "\'";
1571 printDeclarator(S);
1572 }
1573};
1574
1575class StructuredBindingName : public Node {
1576 NodeArray Bindings;
1577public:
1578 StructuredBindingName(NodeArray Bindings_)
1579 : Node(KStructuredBindingName), Bindings(Bindings_) {}
1580
1581 template<typename Fn> void match(Fn F) const { F(Bindings); }
1582
1583 void printLeft(OutputStream &S) const override {
1584 S += '[';
1585 Bindings.printWithComma(S);
1586 S += ']';
1587 }
1588};
1589
1590// -- Expression Nodes --
1591
1592class BinaryExpr : public Node {
1593 const Node *LHS;
1594 const StringView InfixOperator;
1595 const Node *RHS;
1596
1597public:
1598 BinaryExpr(const Node *LHS_, StringView InfixOperator_, const Node *RHS_)
1599 : Node(KBinaryExpr), LHS(LHS_), InfixOperator(InfixOperator_), RHS(RHS_) {
1600 }
1601
1602 template<typename Fn> void match(Fn F) const { F(LHS, InfixOperator, RHS); }
1603
1604 void printLeft(OutputStream &S) const override {
1605 // might be a template argument expression, then we need to disambiguate
1606 // with parens.
1607 if (InfixOperator == ">")
1608 S += "(";
1609
1610 S += "(";
1611 LHS->print(S);
1612 S += ") ";
1613 S += InfixOperator;
1614 S += " (";
1615 RHS->print(S);
1616 S += ")";
1617
1618 if (InfixOperator == ">")
1619 S += ")";
1620 }
1621};
1622
1623class ArraySubscriptExpr : public Node {
1624 const Node *Op1;
1625 const Node *Op2;
1626
1627public:
1628 ArraySubscriptExpr(const Node *Op1_, const Node *Op2_)
1629 : Node(KArraySubscriptExpr), Op1(Op1_), Op2(Op2_) {}
1630
1631 template<typename Fn> void match(Fn F) const { F(Op1, Op2); }
1632
1633 void printLeft(OutputStream &S) const override {
1634 S += "(";
1635 Op1->print(S);
1636 S += ")[";
1637 Op2->print(S);
1638 S += "]";
1639 }
1640};
1641
1642class PostfixExpr : public Node {
1643 const Node *Child;
1644 const StringView Operator;
1645
1646public:
1647 PostfixExpr(const Node *Child_, StringView Operator_)
1648 : Node(KPostfixExpr), Child(Child_), Operator(Operator_) {}
1649
1650 template<typename Fn> void match(Fn F) const { F(Child, Operator); }
1651
1652 void printLeft(OutputStream &S) const override {
1653 S += "(";
1654 Child->print(S);
1655 S += ")";
1656 S += Operator;
1657 }
1658};
1659
1660class ConditionalExpr : public Node {
1661 const Node *Cond;
1662 const Node *Then;
1663 const Node *Else;
1664
1665public:
1666 ConditionalExpr(const Node *Cond_, const Node *Then_, const Node *Else_)
1667 : Node(KConditionalExpr), Cond(Cond_), Then(Then_), Else(Else_) {}
1668
1669 template<typename Fn> void match(Fn F) const { F(Cond, Then, Else); }
1670
1671 void printLeft(OutputStream &S) const override {
1672 S += "(";
1673 Cond->print(S);
1674 S += ") ? (";
1675 Then->print(S);
1676 S += ") : (";
1677 Else->print(S);
1678 S += ")";
1679 }
1680};
1681
1682class MemberExpr : public Node {
1683 const Node *LHS;
1684 const StringView Kind;
1685 const Node *RHS;
1686
1687public:
1688 MemberExpr(const Node *LHS_, StringView Kind_, const Node *RHS_)
1689 : Node(KMemberExpr), LHS(LHS_), Kind(Kind_), RHS(RHS_) {}
1690
1691 template<typename Fn> void match(Fn F) const { F(LHS, Kind, RHS); }
1692
1693 void printLeft(OutputStream &S) const override {
1694 LHS->print(S);
1695 S += Kind;
1696 RHS->print(S);
1697 }
1698};
1699
1700class EnclosingExpr : public Node {
1701 const StringView Prefix;
1702 const Node *Infix;
1703 const StringView Postfix;
1704
1705public:
1706 EnclosingExpr(StringView Prefix_, Node *Infix_, StringView Postfix_)
1707 : Node(KEnclosingExpr), Prefix(Prefix_), Infix(Infix_),
1708 Postfix(Postfix_) {}
1709
1710 template<typename Fn> void match(Fn F) const { F(Prefix, Infix, Postfix); }
1711
1712 void printLeft(OutputStream &S) const override {
1713 S += Prefix;
1714 Infix->print(S);
1715 S += Postfix;
1716 }
1717};
1718
1719class CastExpr : public Node {
1720 // cast_kind<to>(from)
1721 const StringView CastKind;
1722 const Node *To;
1723 const Node *From;
1724
1725public:
1726 CastExpr(StringView CastKind_, const Node *To_, const Node *From_)
1727 : Node(KCastExpr), CastKind(CastKind_), To(To_), From(From_) {}
1728
1729 template<typename Fn> void match(Fn F) const { F(CastKind, To, From); }
1730
1731 void printLeft(OutputStream &S) const override {
1732 S += CastKind;
1733 S += "<";
1734 To->printLeft(S);
1735 S += ">(";
1736 From->printLeft(S);
1737 S += ")";
1738 }
1739};
1740
1741class SizeofParamPackExpr : public Node {
1742 const Node *Pack;
1743
1744public:
1745 SizeofParamPackExpr(const Node *Pack_)
1746 : Node(KSizeofParamPackExpr), Pack(Pack_) {}
1747
1748 template<typename Fn> void match(Fn F) const { F(Pack); }
1749
1750 void printLeft(OutputStream &S) const override {
1751 S += "sizeof...(";
1752 ParameterPackExpansion PPE(Pack);
1753 PPE.printLeft(S);
1754 S += ")";
1755 }
1756};
1757
1758class CallExpr : public Node {
1759 const Node *Callee;
1760 NodeArray Args;
1761
1762public:
1763 CallExpr(const Node *Callee_, NodeArray Args_)
1764 : Node(KCallExpr), Callee(Callee_), Args(Args_) {}
1765
1766 template<typename Fn> void match(Fn F) const { F(Callee, Args); }
1767
1768 void printLeft(OutputStream &S) const override {
1769 Callee->print(S);
1770 S += "(";
1771 Args.printWithComma(S);
1772 S += ")";
1773 }
1774};
1775
1776class NewExpr : public Node {
1777 // new (expr_list) type(init_list)
1778 NodeArray ExprList;
1779 Node *Type;
1780 NodeArray InitList;
1781 bool IsGlobal; // ::operator new ?
1782 bool IsArray; // new[] ?
1783public:
1784 NewExpr(NodeArray ExprList_, Node *Type_, NodeArray InitList_, bool IsGlobal_,
1785 bool IsArray_)
1786 : Node(KNewExpr), ExprList(ExprList_), Type(Type_), InitList(InitList_),
1787 IsGlobal(IsGlobal_), IsArray(IsArray_) {}
1788
1789 template<typename Fn> void match(Fn F) const {
1790 F(ExprList, Type, InitList, IsGlobal, IsArray);
1791 }
1792
1793 void printLeft(OutputStream &S) const override {
1794 if (IsGlobal)
1795 S += "::operator ";
1796 S += "new";
1797 if (IsArray)
1798 S += "[]";
1799 S += ' ';
1800 if (!ExprList.empty()) {
1801 S += "(";
1802 ExprList.printWithComma(S);
1803 S += ")";
1804 }
1805 Type->print(S);
1806 if (!InitList.empty()) {
1807 S += "(";
1808 InitList.printWithComma(S);
1809 S += ")";
1810 }
1811
1812 }
1813};
1814
1815class DeleteExpr : public Node {
1816 Node *Op;
1817 bool IsGlobal;
1818 bool IsArray;
1819
1820public:
1821 DeleteExpr(Node *Op_, bool IsGlobal_, bool IsArray_)
1822 : Node(KDeleteExpr), Op(Op_), IsGlobal(IsGlobal_), IsArray(IsArray_) {}
1823
1824 template<typename Fn> void match(Fn F) const { F(Op, IsGlobal, IsArray); }
1825
1826 void printLeft(OutputStream &S) const override {
1827 if (IsGlobal)
1828 S += "::";
1829 S += "delete";
1830 if (IsArray)
1831 S += "[] ";
1832 Op->print(S);
1833 }
1834};
1835
1836class PrefixExpr : public Node {
1837 StringView Prefix;
1838 Node *Child;
1839
1840public:
1841 PrefixExpr(StringView Prefix_, Node *Child_)
1842 : Node(KPrefixExpr), Prefix(Prefix_), Child(Child_) {}
1843
1844 template<typename Fn> void match(Fn F) const { F(Prefix, Child); }
1845
1846 void printLeft(OutputStream &S) const override {
1847 S += Prefix;
1848 S += "(";
1849 Child->print(S);
1850 S += ")";
1851 }
1852};
1853
1854class FunctionParam : public Node {
1855 StringView Number;
1856
1857public:
1858 FunctionParam(StringView Number_) : Node(KFunctionParam), Number(Number_) {}
1859
1860 template<typename Fn> void match(Fn F) const { F(Number); }
1861
1862 void printLeft(OutputStream &S) const override {
1863 S += "fp";
1864 S += Number;
1865 }
1866};
1867
1868class ConversionExpr : public Node {
1869 const Node *Type;
1870 NodeArray Expressions;
1871
1872public:
1873 ConversionExpr(const Node *Type_, NodeArray Expressions_)
1874 : Node(KConversionExpr), Type(Type_), Expressions(Expressions_) {}
1875
1876 template<typename Fn> void match(Fn F) const { F(Type, Expressions); }
1877
1878 void printLeft(OutputStream &S) const override {
1879 S += "(";
1880 Type->print(S);
1881 S += ")(";
1882 Expressions.printWithComma(S);
1883 S += ")";
1884 }
1885};
1886
1887class InitListExpr : public Node {
1888 const Node *Ty;
1889 NodeArray Inits;
1890public:
1891 InitListExpr(const Node *Ty_, NodeArray Inits_)
1892 : Node(KInitListExpr), Ty(Ty_), Inits(Inits_) {}
1893
1894 template<typename Fn> void match(Fn F) const { F(Ty, Inits); }
1895
1896 void printLeft(OutputStream &S) const override {
1897 if (Ty)
1898 Ty->print(S);
1899 S += '{';
1900 Inits.printWithComma(S);
1901 S += '}';
1902 }
1903};
1904
1905class BracedExpr : public Node {
1906 const Node *Elem;
1907 const Node *Init;
1908 bool IsArray;
1909public:
1910 BracedExpr(const Node *Elem_, const Node *Init_, bool IsArray_)
1911 : Node(KBracedExpr), Elem(Elem_), Init(Init_), IsArray(IsArray_) {}
1912
1913 template<typename Fn> void match(Fn F) const { F(Elem, Init, IsArray); }
1914
1915 void printLeft(OutputStream &S) const override {
1916 if (IsArray) {
1917 S += '[';
1918 Elem->print(S);
1919 S += ']';
1920 } else {
1921 S += '.';
1922 Elem->print(S);
1923 }
1924 if (Init->getKind() != KBracedExpr && Init->getKind() != KBracedRangeExpr)
1925 S += " = ";
1926 Init->print(S);
1927 }
1928};
1929
1930class BracedRangeExpr : public Node {
1931 const Node *First;
1932 const Node *Last;
1933 const Node *Init;
1934public:
1935 BracedRangeExpr(const Node *First_, const Node *Last_, const Node *Init_)
1936 : Node(KBracedRangeExpr), First(First_), Last(Last_), Init(Init_) {}
1937
1938 template<typename Fn> void match(Fn F) const { F(First, Last, Init); }
1939
1940 void printLeft(OutputStream &S) const override {
1941 S += '[';
1942 First->print(S);
1943 S += " ... ";
1944 Last->print(S);
1945 S += ']';
1946 if (Init->getKind() != KBracedExpr && Init->getKind() != KBracedRangeExpr)
1947 S += " = ";
1948 Init->print(S);
1949 }
1950};
1951
1952class FoldExpr : public Node {
1953 const Node *Pack, *Init;
1954 StringView OperatorName;
1955 bool IsLeftFold;
1956
1957public:
1958 FoldExpr(bool IsLeftFold_, StringView OperatorName_, const Node *Pack_,
1959 const Node *Init_)
1960 : Node(KFoldExpr), Pack(Pack_), Init(Init_), OperatorName(OperatorName_),
1961 IsLeftFold(IsLeftFold_) {}
1962
1963 template<typename Fn> void match(Fn F) const {
1964 F(IsLeftFold, OperatorName, Pack, Init);
1965 }
1966
1967 void printLeft(OutputStream &S) const override {
1968 auto PrintPack = [&] {
1969 S += '(';
1970 ParameterPackExpansion(Pack).print(S);
1971 S += ')';
1972 };
1973
1974 S += '(';
1975
1976 if (IsLeftFold) {
1977 // init op ... op pack
1978 if (Init != nullptr) {
1979 Init->print(S);
1980 S += ' ';
1981 S += OperatorName;
1982 S += ' ';
1983 }
1984 // ... op pack
1985 S += "... ";
1986 S += OperatorName;
1987 S += ' ';
1988 PrintPack();
1989 } else { // !IsLeftFold
1990 // pack op ...
1991 PrintPack();
1992 S += ' ';
1993 S += OperatorName;
1994 S += " ...";
1995 // pack op ... op init
1996 if (Init != nullptr) {
1997 S += ' ';
1998 S += OperatorName;
1999 S += ' ';
2000 Init->print(S);
2001 }
2002 }
2003 S += ')';
2004 }
2005};
2006
2007class ThrowExpr : public Node {
2008 const Node *Op;
2009
2010public:
2011 ThrowExpr(const Node *Op_) : Node(KThrowExpr), Op(Op_) {}
2012
2013 template<typename Fn> void match(Fn F) const { F(Op); }
2014
2015 void printLeft(OutputStream &S) const override {
2016 S += "throw ";
2017 Op->print(S);
2018 }
2019};
2020
2021// MSVC __uuidof extension, generated by clang in -fms-extensions mode.
2022class UUIDOfExpr : public Node {
2023 Node *Operand;
2024public:
2025 UUIDOfExpr(Node *Operand_) : Node(KUUIDOfExpr), Operand(Operand_) {}
2026
2027 template<typename Fn> void match(Fn F) const { F(Operand); }
2028
2029 void printLeft(OutputStream &S) const override {
2030 S << "__uuidof(";
2031 Operand->print(S);
2032 S << ")";
2033 }
2034};
2035
2036class BoolExpr : public Node {
2037 bool Value;
2038
2039public:
2040 BoolExpr(bool Value_) : Node(KBoolExpr), Value(Value_) {}
2041
2042 template<typename Fn> void match(Fn F) const { F(Value); }
2043
2044 void printLeft(OutputStream &S) const override {
2045 S += Value ? StringView("true") : StringView("false");
2046 }
2047};
2048
2049class StringLiteral : public Node {
2050 const Node *Type;
2051
2052public:
2053 StringLiteral(const Node *Type_) : Node(KStringLiteral), Type(Type_) {}
2054
2055 template<typename Fn> void match(Fn F) const { F(Type); }
2056
2057 void printLeft(OutputStream &S) const override {
2058 S += "\"<";
2059 Type->print(S);
2060 S += ">\"";
2061 }
2062};
2063
2064class LambdaExpr : public Node {
2065 const Node *Type;
2066
2067public:
2068 LambdaExpr(const Node *Type_) : Node(KLambdaExpr), Type(Type_) {}
2069
2070 template<typename Fn> void match(Fn F) const { F(Type); }
2071
2072 void printLeft(OutputStream &S) const override {
2073 S += "[]";
2074 if (Type->getKind() == KClosureTypeName)
2075 static_cast<const ClosureTypeName *>(Type)->printDeclarator(S);
2076 S += "{...}";
2077 }
2078};
2079
2080class IntegerCastExpr : public Node {
2081 // ty(integer)
2082 const Node *Ty;
2083 StringView Integer;
2084
2085public:
2086 IntegerCastExpr(const Node *Ty_, StringView Integer_)
2087 : Node(KIntegerCastExpr), Ty(Ty_), Integer(Integer_) {}
2088
2089 template<typename Fn> void match(Fn F) const { F(Ty, Integer); }
2090
2091 void printLeft(OutputStream &S) const override {
2092 S += "(";
2093 Ty->print(S);
2094 S += ")";
2095 S += Integer;
2096 }
2097};
2098
2099class IntegerLiteral : public Node {
2100 StringView Type;
2101 StringView Value;
2102
2103public:
2104 IntegerLiteral(StringView Type_, StringView Value_)
2105 : Node(KIntegerLiteral), Type(Type_), Value(Value_) {}
2106
2107 template<typename Fn> void match(Fn F) const { F(Type, Value); }
2108
2109 void printLeft(OutputStream &S) const override {
2110 if (Type.size() > 3) {
2111 S += "(";
2112 S += Type;
2113 S += ")";
2114 }
2115
2116 if (Value[0] == 'n') {
2117 S += "-";
2118 S += Value.dropFront(1);
2119 } else
2120 S += Value;
2121
2122 if (Type.size() <= 3)
2123 S += Type;
2124 }
2125};
2126
2127template <class Float> struct FloatData;
2128
2129namespace float_literal_impl {
2130constexpr Node::Kind getFloatLiteralKind(float *) {
2131 return Node::KFloatLiteral;
2132}
2133constexpr Node::Kind getFloatLiteralKind(double *) {
2134 return Node::KDoubleLiteral;
2135}
2136constexpr Node::Kind getFloatLiteralKind(long double *) {
2137 return Node::KLongDoubleLiteral;
2138}
2139}
2140
2141template <class Float> class FloatLiteralImpl : public Node {
2142 const StringView Contents;
2143
2144 static constexpr Kind KindForClass =
2145 float_literal_impl::getFloatLiteralKind((Float *)nullptr);
2146
2147public:
2148 FloatLiteralImpl(StringView Contents_)
2149 : Node(KindForClass), Contents(Contents_) {}
2150
2151 template<typename Fn> void match(Fn F) const { F(Contents); }
2152
2153 void printLeft(OutputStream &s) const override {
2154 const char *first = Contents.begin();
2155 const char *last = Contents.end() + 1;
2156
2157 const size_t N = FloatData<Float>::mangled_size;
2158 if (static_cast<std::size_t>(last - first) > N) {
2159 last = first + N;
2160 union {
2161 Float value;
2162 char buf[sizeof(Float)];
2163 };
2164 const char *t = first;
2165 char *e = buf;
2166 for (; t != last; ++t, ++e) {
2167 unsigned d1 = isdigit(*t) ? static_cast<unsigned>(*t - '0')
2168 : static_cast<unsigned>(*t - 'a' + 10);
2169 ++t;
2170 unsigned d0 = isdigit(*t) ? static_cast<unsigned>(*t - '0')
2171 : static_cast<unsigned>(*t - 'a' + 10);
2172 *e = static_cast<char>((d1 << 4) + d0);
2173 }
2174#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
2175 std::reverse(buf, e);
2176#endif
2177 char num[FloatData<Float>::max_demangled_size] = {0};
2178 int n = snprintf(num, sizeof(num), FloatData<Float>::spec, value);
2179 s += StringView(num, num + n);
2180 }
2181 }
2182};
2183
2184using FloatLiteral = FloatLiteralImpl<float>;
2185using DoubleLiteral = FloatLiteralImpl<double>;
2186using LongDoubleLiteral = FloatLiteralImpl<long double>;
2187
2188/// Visit the node. Calls \c F(P), where \c P is the node cast to the
2189/// appropriate derived class.
2190template<typename Fn>
2191void Node::visit(Fn F) const {
2192 switch (K) {
2193#define CASE(X) case K ## X: return F(static_cast<const X*>(this));
2194 FOR_EACH_NODE_KIND(CASE)
2195#undef CASE
2196 }
2197 assert(0 && "unknown mangling node kind");
2198}
2199
2200/// Determine the kind of a node from its type.
2201template<typename NodeT> struct NodeKind;
2202#define SPECIALIZATION(X) \
2203 template<> struct NodeKind<X> { \
2204 static constexpr Node::Kind Kind = Node::K##X; \
2205 static constexpr const char *name() { return #X; } \
2206 };
2207FOR_EACH_NODE_KIND(SPECIALIZATION)
2208#undef SPECIALIZATION
2209
2210#undef FOR_EACH_NODE_KIND
2211
2212template <class T, size_t N>
2213class PODSmallVector {
2214 static_assert(std::is_pod<T>::value,
2215 "T is required to be a plain old data type");
2216
2217 T* First;
2218 T* Last;
2219 T* Cap;
2220 T Inline[N];
2221
2222 bool isInline() const { return First == Inline; }
2223
2224 void clearInline() {
2225 First = Inline;
2226 Last = Inline;
2227 Cap = Inline + N;
2228 }
2229
2230 void reserve(size_t NewCap) {
2231 size_t S = size();
2232 if (isInline()) {
2233 auto* Tmp = static_cast<T*>(std::malloc(NewCap * sizeof(T)));
2234 if (Tmp == nullptr)
2235 std::terminate();
2236 std::copy(First, Last, Tmp);
2237 First = Tmp;
2238 } else {
2239 First = static_cast<T*>(std::realloc(First, NewCap * sizeof(T)));
2240 if (First == nullptr)
2241 std::terminate();
2242 }
2243 Last = First + S;
2244 Cap = First + NewCap;
2245 }
2246
2247public:
2248 PODSmallVector() : First(Inline), Last(First), Cap(Inline + N) {}
2249
2250 PODSmallVector(const PODSmallVector&) = delete;
2251 PODSmallVector& operator=(const PODSmallVector&) = delete;
2252
2253 PODSmallVector(PODSmallVector&& Other) : PODSmallVector() {
2254 if (Other.isInline()) {
2255 std::copy(Other.begin(), Other.end(), First);
2256 Last = First + Other.size();
2257 Other.clear();
2258 return;
2259 }
2260
2261 First = Other.First;
2262 Last = Other.Last;
2263 Cap = Other.Cap;
2264 Other.clearInline();
2265 }
2266
2267 PODSmallVector& operator=(PODSmallVector&& Other) {
2268 if (Other.isInline()) {
2269 if (!isInline()) {
2270 std::free(First);
2271 clearInline();
2272 }
2273 std::copy(Other.begin(), Other.end(), First);
2274 Last = First + Other.size();
2275 Other.clear();
2276 return *this;
2277 }
2278
2279 if (isInline()) {
2280 First = Other.First;
2281 Last = Other.Last;
2282 Cap = Other.Cap;
2283 Other.clearInline();
2284 return *this;
2285 }
2286
2287 std::swap(First, Other.First);
2288 std::swap(Last, Other.Last);
2289 std::swap(Cap, Other.Cap);
2290 Other.clear();
2291 return *this;
2292 }
2293
2294 void push_back(const T& Elem) {
2295 if (Last == Cap)
2296 reserve(size() * 2);
2297 *Last++ = Elem;
2298 }
2299
2300 void pop_back() {
2301 assert(Last != First && "Popping empty vector!");
2302 --Last;
2303 }
2304
2305 void dropBack(size_t Index) {
2306 assert(Index <= size() && "dropBack() can't expand!");
2307 Last = First + Index;
2308 }
2309
2310 T* begin() { return First; }
2311 T* end() { return Last; }
2312
2313 bool empty() const { return First == Last; }
2314 size_t size() const { return static_cast<size_t>(Last - First); }
2315 T& back() {
2316 assert(Last != First && "Calling back() on empty vector!");
2317 return *(Last - 1);
2318 }
2319 T& operator[](size_t Index) {
2320 assert(Index < size() && "Invalid access!");
2321 return *(begin() + Index);
2322 }
2323 void clear() { Last = First; }
2324
2325 ~PODSmallVector() {
2326 if (!isInline())
2327 std::free(First);
2328 }
2329};
2330
2331template <typename Derived, typename Alloc> struct AbstractManglingParser {
2332 const char *First;
2333 const char *Last;
2334
2335 // Name stack, this is used by the parser to hold temporary names that were
2336 // parsed. The parser collapses multiple names into new nodes to construct
2337 // the AST. Once the parser is finished, names.size() == 1.
2338 PODSmallVector<Node *, 32> Names;
2339
2340 // Substitution table. Itanium supports name substitutions as a means of
2341 // compression. The string "S42_" refers to the 44nd entry (base-36) in this
2342 // table.
2343 PODSmallVector<Node *, 32> Subs;
2344
2345 using TemplateParamList = PODSmallVector<Node *, 8>;
2346
2347 class ScopedTemplateParamList {
2348 AbstractManglingParser *Parser;
2349 size_t OldNumTemplateParamLists;
2350 TemplateParamList Params;
2351
2352 public:
2353 ScopedTemplateParamList(AbstractManglingParser *Parser)
2354 : Parser(Parser),
2355 OldNumTemplateParamLists(Parser->TemplateParams.size()) {
2356 Parser->TemplateParams.push_back(&Params);
2357 }
2358 ~ScopedTemplateParamList() {
2359 assert(Parser->TemplateParams.size() >= OldNumTemplateParamLists);
2360 Parser->TemplateParams.dropBack(OldNumTemplateParamLists);
2361 }
2362 };
2363
2364 // Template parameter table. Like the above, but referenced like "T42_".
2365 // This has a smaller size compared to Subs and Names because it can be
2366 // stored on the stack.
2367 TemplateParamList OuterTemplateParams;
2368
2369 // Lists of template parameters indexed by template parameter depth,
2370 // referenced like "TL2_4_". If nonempty, element 0 is always
2371 // OuterTemplateParams; inner elements are always template parameter lists of
2372 // lambda expressions. For a generic lambda with no explicit template
2373 // parameter list, the corresponding parameter list pointer will be null.
2374 PODSmallVector<TemplateParamList *, 4> TemplateParams;
2375
2376 // Set of unresolved forward <template-param> references. These can occur in a
2377 // conversion operator's type, and are resolved in the enclosing <encoding>.
2378 PODSmallVector<ForwardTemplateReference *, 4> ForwardTemplateRefs;
2379
2380 bool TryToParseTemplateArgs = true;
2381 bool PermitForwardTemplateReferences = false;
2382 size_t ParsingLambdaParamsAtLevel = (size_t)-1;
2383
2384 unsigned NumSyntheticTemplateParameters[3] = {};
2385
2386 Alloc ASTAllocator;
2387
2388 AbstractManglingParser(const char *First_, const char *Last_)
2389 : First(First_), Last(Last_) {}
2390
2391 Derived &getDerived() { return static_cast<Derived &>(*this); }
2392
2393 void reset(const char *First_, const char *Last_) {
2394 First = First_;
2395 Last = Last_;
2396 Names.clear();
2397 Subs.clear();
2398 TemplateParams.clear();
2399 ParsingLambdaParamsAtLevel = (size_t)-1;
2400 TryToParseTemplateArgs = true;
2401 PermitForwardTemplateReferences = false;
2402 for (int I = 0; I != 3; ++I)
2403 NumSyntheticTemplateParameters[I] = 0;
2404 ASTAllocator.reset();
2405 }
2406
2407 template <class T, class... Args> Node *make(Args &&... args) {
2408 return ASTAllocator.template makeNode<T>(std::forward<Args>(args)...);
2409 }
2410
2411 template <class It> NodeArray makeNodeArray(It begin, It end) {
2412 size_t sz = static_cast<size_t>(end - begin);
2413 void *mem = ASTAllocator.allocateNodeArray(sz);
2414 Node **data = new (mem) Node *[sz];
2415 std::copy(begin, end, data);
2416 return NodeArray(data, sz);
2417 }
2418
2419 NodeArray popTrailingNodeArray(size_t FromPosition) {
2420 assert(FromPosition <= Names.size());
2421 NodeArray res =
2422 makeNodeArray(Names.begin() + (long)FromPosition, Names.end());
2423 Names.dropBack(FromPosition);
2424 return res;
2425 }
2426
2427 bool consumeIf(StringView S) {
2428 if (StringView(First, Last).startsWith(S)) {
2429 First += S.size();
2430 return true;
2431 }
2432 return false;
2433 }
2434
2435 bool consumeIf(char C) {
2436 if (First != Last && *First == C) {
2437 ++First;
2438 return true;
2439 }
2440 return false;
2441 }
2442
2443 char consume() { return First != Last ? *First++ : '\0'; }
2444
2445 char look(unsigned Lookahead = 0) {
2446 if (static_cast<size_t>(Last - First) <= Lookahead)
2447 return '\0';
2448 return First[Lookahead];
2449 }
2450
2451 size_t numLeft() const { return static_cast<size_t>(Last - First); }
2452
2453 StringView parseNumber(bool AllowNegative = false);
2454 Qualifiers parseCVQualifiers();
2455 bool parsePositiveInteger(size_t *Out);
2456 StringView parseBareSourceName();
2457
2458 bool parseSeqId(size_t *Out);
2459 Node *parseSubstitution();
2460 Node *parseTemplateParam();
2461 Node *parseTemplateParamDecl();
2462 Node *parseTemplateArgs(bool TagTemplates = false);
2463 Node *parseTemplateArg();
2464
2465 /// Parse the <expr> production.
2466 Node *parseExpr();
2467 Node *parsePrefixExpr(StringView Kind);
2468 Node *parseBinaryExpr(StringView Kind);
2469 Node *parseIntegerLiteral(StringView Lit);
2470 Node *parseExprPrimary();
2471 template <class Float> Node *parseFloatingLiteral();
2472 Node *parseFunctionParam();
2473 Node *parseNewExpr();
2474 Node *parseConversionExpr();
2475 Node *parseBracedExpr();
2476 Node *parseFoldExpr();
2477
2478 /// Parse the <type> production.
2479 Node *parseType();
2480 Node *parseFunctionType();
2481 Node *parseVectorType();
2482 Node *parseDecltype();
2483 Node *parseArrayType();
2484 Node *parsePointerToMemberType();
2485 Node *parseClassEnumType();
2486 Node *parseQualifiedType();
2487
2488 Node *parseEncoding();
2489 bool parseCallOffset();
2490 Node *parseSpecialName();
2491
2492 /// Holds some extra information about a <name> that is being parsed. This
2493 /// information is only pertinent if the <name> refers to an <encoding>.
2494 struct NameState {
2495 bool CtorDtorConversion = false;
2496 bool EndsWithTemplateArgs = false;
2497 Qualifiers CVQualifiers = QualNone;
2498 FunctionRefQual ReferenceQualifier = FrefQualNone;
2499 size_t ForwardTemplateRefsBegin;
2500
2501 NameState(AbstractManglingParser *Enclosing)
2502 : ForwardTemplateRefsBegin(Enclosing->ForwardTemplateRefs.size()) {}
2503 };
2504
2505 bool resolveForwardTemplateRefs(NameState &State) {
2506 size_t I = State.ForwardTemplateRefsBegin;
2507 size_t E = ForwardTemplateRefs.size();
2508 for (; I < E; ++I) {
2509 size_t Idx = ForwardTemplateRefs[I]->Index;
2510 if (TemplateParams.empty() || !TemplateParams[0] ||
2511 Idx >= TemplateParams[0]->size())
2512 return true;
2513 ForwardTemplateRefs[I]->Ref = (*TemplateParams[0])[Idx];
2514 }
2515 ForwardTemplateRefs.dropBack(State.ForwardTemplateRefsBegin);
2516 return false;
2517 }
2518
2519 /// Parse the <name> production>
2520 Node *parseName(NameState *State = nullptr);
2521 Node *parseLocalName(NameState *State);
2522 Node *parseOperatorName(NameState *State);
2523 Node *parseUnqualifiedName(NameState *State);
2524 Node *parseUnnamedTypeName(NameState *State);
2525 Node *parseSourceName(NameState *State);
2526 Node *parseUnscopedName(NameState *State);
2527 Node *parseNestedName(NameState *State);
2528 Node *parseCtorDtorName(Node *&SoFar, NameState *State);
2529
2530 Node *parseAbiTags(Node *N);
2531
2532 /// Parse the <unresolved-name> production.
2533 Node *parseUnresolvedName();
2534 Node *parseSimpleId();
2535 Node *parseBaseUnresolvedName();
2536 Node *parseUnresolvedType();
2537 Node *parseDestructorName();
2538
2539 /// Top-level entry point into the parser.
2540 Node *parse();
2541};
2542
2543const char* parse_discriminator(const char* first, const char* last);
2544
2545// <name> ::= <nested-name> // N
2546// ::= <local-name> # See Scope Encoding below // Z
2547// ::= <unscoped-template-name> <template-args>
2548// ::= <unscoped-name>
2549//
2550// <unscoped-template-name> ::= <unscoped-name>
2551// ::= <substitution>
2552template <typename Derived, typename Alloc>
2553Node *AbstractManglingParser<Derived, Alloc>::parseName(NameState *State) {
2554 consumeIf('L'); // extension
2555
2556 if (look() == 'N')
2557 return getDerived().parseNestedName(State);
2558 if (look() == 'Z')
2559 return getDerived().parseLocalName(State);
2560
2561 // ::= <unscoped-template-name> <template-args>
2562 if (look() == 'S' && look(1) != 't') {
2563 Node *S = getDerived().parseSubstitution();
2564 if (S == nullptr)
2565 return nullptr;
2566 if (look() != 'I')
2567 return nullptr;
2568 Node *TA = getDerived().parseTemplateArgs(State != nullptr);
2569 if (TA == nullptr)
2570 return nullptr;
2571 if (State) State->EndsWithTemplateArgs = true;
2572 return make<NameWithTemplateArgs>(S, TA);
2573 }
2574
2575 Node *N = getDerived().parseUnscopedName(State);
2576 if (N == nullptr)
2577 return nullptr;
2578 // ::= <unscoped-template-name> <template-args>
2579 if (look() == 'I') {
2580 Subs.push_back(N);
2581 Node *TA = getDerived().parseTemplateArgs(State != nullptr);
2582 if (TA == nullptr)
2583 return nullptr;
2584 if (State) State->EndsWithTemplateArgs = true;
2585 return make<NameWithTemplateArgs>(N, TA);
2586 }
2587 // ::= <unscoped-name>
2588 return N;
2589}
2590
2591// <local-name> := Z <function encoding> E <entity name> [<discriminator>]
2592// := Z <function encoding> E s [<discriminator>]
2593// := Z <function encoding> Ed [ <parameter number> ] _ <entity name>
2594template <typename Derived, typename Alloc>
2595Node *AbstractManglingParser<Derived, Alloc>::parseLocalName(NameState *State) {
2596 if (!consumeIf('Z'))
2597 return nullptr;
2598 Node *Encoding = getDerived().parseEncoding();
2599 if (Encoding == nullptr || !consumeIf('E'))
2600 return nullptr;
2601
2602 if (consumeIf('s')) {
2603 First = parse_discriminator(First, Last);
2604 auto *StringLitName = make<NameType>("string literal");
2605 if (!StringLitName)
2606 return nullptr;
2607 return make<LocalName>(Encoding, StringLitName);
2608 }
2609
2610 if (consumeIf('d')) {
2611 parseNumber(true);
2612 if (!consumeIf('_'))
2613 return nullptr;
2614 Node *N = getDerived().parseName(State);
2615 if (N == nullptr)
2616 return nullptr;
2617 return make<LocalName>(Encoding, N);
2618 }
2619
2620 Node *Entity = getDerived().parseName(State);
2621 if (Entity == nullptr)
2622 return nullptr;
2623 First = parse_discriminator(First, Last);
2624 return make<LocalName>(Encoding, Entity);
2625}
2626
2627// <unscoped-name> ::= <unqualified-name>
2628// ::= St <unqualified-name> # ::std::
2629// extension ::= StL<unqualified-name>
2630template <typename Derived, typename Alloc>
2631Node *
2632AbstractManglingParser<Derived, Alloc>::parseUnscopedName(NameState *State) {
2633 if (consumeIf("StL") || consumeIf("St")) {
2634 Node *R = getDerived().parseUnqualifiedName(State);
2635 if (R == nullptr)
2636 return nullptr;
2637 return make<StdQualifiedName>(R);
2638 }
2639 return getDerived().parseUnqualifiedName(State);
2640}
2641
2642// <unqualified-name> ::= <operator-name> [abi-tags]
2643// ::= <ctor-dtor-name>
2644// ::= <source-name>
2645// ::= <unnamed-type-name>
2646// ::= DC <source-name>+ E # structured binding declaration
2647template <typename Derived, typename Alloc>
2648Node *
2649AbstractManglingParser<Derived, Alloc>::parseUnqualifiedName(NameState *State) {
2650 // <ctor-dtor-name>s are special-cased in parseNestedName().
2651 Node *Result;
2652 if (look() == 'U')
2653 Result = getDerived().parseUnnamedTypeName(State);
2654 else if (look() >= '1' && look() <= '9')
2655 Result = getDerived().parseSourceName(State);
2656 else if (consumeIf("DC")) {
2657 size_t BindingsBegin = Names.size();
2658 do {
2659 Node *Binding = getDerived().parseSourceName(State);
2660 if (Binding == nullptr)
2661 return nullptr;
2662 Names.push_back(Binding);
2663 } while (!consumeIf('E'));
2664 Result = make<StructuredBindingName>(popTrailingNodeArray(BindingsBegin));
2665 } else
2666 Result = getDerived().parseOperatorName(State);
2667 if (Result != nullptr)
2668 Result = getDerived().parseAbiTags(Result);
2669 return Result;
2670}
2671
2672// <unnamed-type-name> ::= Ut [<nonnegative number>] _
2673// ::= <closure-type-name>
2674//
2675// <closure-type-name> ::= Ul <lambda-sig> E [ <nonnegative number> ] _
2676//
2677// <lambda-sig> ::= <parameter type>+ # Parameter types or "v" if the lambda has no parameters
2678template <typename Derived, typename Alloc>
2679Node *
2680AbstractManglingParser<Derived, Alloc>::parseUnnamedTypeName(NameState *State) {
2681 // <template-params> refer to the innermost <template-args>. Clear out any
2682 // outer args that we may have inserted into TemplateParams.
2683 if (State != nullptr)
2684 TemplateParams.clear();
2685
2686 if (consumeIf("Ut")) {
2687 StringView Count = parseNumber();
2688 if (!consumeIf('_'))
2689 return nullptr;
2690 return make<UnnamedTypeName>(Count);
2691 }
2692 if (consumeIf("Ul")) {
2693 SwapAndRestore<size_t> SwapParams(ParsingLambdaParamsAtLevel,
2694 TemplateParams.size());
2695 ScopedTemplateParamList LambdaTemplateParams(this);
2696
2697 size_t ParamsBegin = Names.size();
2698 while (look() == 'T' &&
2699 StringView("yptn").find(look(1)) != StringView::npos) {
2700 Node *T = parseTemplateParamDecl();
2701 if (!T)
2702 return nullptr;
2703 Names.push_back(T);
2704 }
2705 NodeArray TempParams = popTrailingNodeArray(ParamsBegin);
2706
2707 // FIXME: If TempParams is empty and none of the function parameters
2708 // includes 'auto', we should remove LambdaTemplateParams from the
2709 // TemplateParams list. Unfortunately, we don't find out whether there are
2710 // any 'auto' parameters until too late in an example such as:
2711 //
2712 // template<typename T> void f(
2713 // decltype([](decltype([]<typename T>(T v) {}),
2714 // auto) {})) {}
2715 // template<typename T> void f(
2716 // decltype([](decltype([]<typename T>(T w) {}),
2717 // int) {})) {}
2718 //
2719 // Here, the type of v is at level 2 but the type of w is at level 1. We
2720 // don't find this out until we encounter the type of the next parameter.
2721 //
2722 // However, compilers can't actually cope with the former example in
2723 // practice, and it's likely to be made ill-formed in future, so we don't
2724 // need to support it here.
2725 //
2726 // If we encounter an 'auto' in the function parameter types, we will
2727 // recreate a template parameter scope for it, but any intervening lambdas
2728 // will be parsed in the 'wrong' template parameter depth.
2729 if (TempParams.empty())
2730 TemplateParams.pop_back();
2731
2732 if (!consumeIf("vE")) {
2733 do {
2734 Node *P = getDerived().parseType();
2735 if (P == nullptr)
2736 return nullptr;
2737 Names.push_back(P);
2738 } while (!consumeIf('E'));
2739 }
2740 NodeArray Params = popTrailingNodeArray(ParamsBegin);
2741
2742 StringView Count = parseNumber();
2743 if (!consumeIf('_'))
2744 return nullptr;
2745 return make<ClosureTypeName>(TempParams, Params, Count);
2746 }
2747 if (consumeIf("Ub")) {
2748 (void)parseNumber();
2749 if (!consumeIf('_'))
2750 return nullptr;
2751 return make<NameType>("'block-literal'");
2752 }
2753 return nullptr;
2754}
2755
2756// <source-name> ::= <positive length number> <identifier>
2757template <typename Derived, typename Alloc>
2758Node *AbstractManglingParser<Derived, Alloc>::parseSourceName(NameState *) {
2759 size_t Length = 0;
2760 if (parsePositiveInteger(&Length))
2761 return nullptr;
2762 if (numLeft() < Length || Length == 0)
2763 return nullptr;
2764 StringView Name(First, First + Length);
2765 First += Length;
2766 if (Name.startsWith("_GLOBAL__N"))
2767 return make<NameType>("(anonymous namespace)");
2768 return make<NameType>(Name);
2769}
2770
2771// <operator-name> ::= aa # &&
2772// ::= ad # & (unary)
2773// ::= an # &
2774// ::= aN # &=
2775// ::= aS # =
2776// ::= cl # ()
2777// ::= cm # ,
2778// ::= co # ~
2779// ::= cv <type> # (cast)
2780// ::= da # delete[]
2781// ::= de # * (unary)
2782// ::= dl # delete
2783// ::= dv # /
2784// ::= dV # /=
2785// ::= eo # ^
2786// ::= eO # ^=
2787// ::= eq # ==
2788// ::= ge # >=
2789// ::= gt # >
2790// ::= ix # []
2791// ::= le # <=
2792// ::= li <source-name> # operator ""
2793// ::= ls # <<
2794// ::= lS # <<=
2795// ::= lt # <
2796// ::= mi # -
2797// ::= mI # -=
2798// ::= ml # *
2799// ::= mL # *=
2800// ::= mm # -- (postfix in <expression> context)
2801// ::= na # new[]
2802// ::= ne # !=
2803// ::= ng # - (unary)
2804// ::= nt # !
2805// ::= nw # new
2806// ::= oo # ||
2807// ::= or # |
2808// ::= oR # |=
2809// ::= pm # ->*
2810// ::= pl # +
2811// ::= pL # +=
2812// ::= pp # ++ (postfix in <expression> context)
2813// ::= ps # + (unary)
2814// ::= pt # ->
2815// ::= qu # ?
2816// ::= rm # %
2817// ::= rM # %=
2818// ::= rs # >>
2819// ::= rS # >>=
2820// ::= ss # <=> C++2a
2821// ::= v <digit> <source-name> # vendor extended operator
2822template <typename Derived, typename Alloc>
2823Node *
2824AbstractManglingParser<Derived, Alloc>::parseOperatorName(NameState *State) {
2825 switch (look()) {
2826 case 'a':
2827 switch (look(1)) {
2828 case 'a':
2829 First += 2;
2830 return make<NameType>("operator&&");
2831 case 'd':
2832 case 'n':
2833 First += 2;
2834 return make<NameType>("operator&");
2835 case 'N':
2836 First += 2;
2837 return make<NameType>("operator&=");
2838 case 'S':
2839 First += 2;
2840 return make<NameType>("operator=");
2841 }
2842 return nullptr;
2843 case 'c':
2844 switch (look(1)) {
2845 case 'l':
2846 First += 2;
2847 return make<NameType>("operator()");
2848 case 'm':
2849 First += 2;
2850 return make<NameType>("operator,");
2851 case 'o':
2852 First += 2;
2853 return make<NameType>("operator~");
2854 // ::= cv <type> # (cast)
2855 case 'v': {
2856 First += 2;
2857 SwapAndRestore<bool> SaveTemplate(TryToParseTemplateArgs, false);
2858 // If we're parsing an encoding, State != nullptr and the conversion
2859 // operators' <type> could have a <template-param> that refers to some
2860 // <template-arg>s further ahead in the mangled name.
2861 SwapAndRestore<bool> SavePermit(PermitForwardTemplateReferences,
2862 PermitForwardTemplateReferences ||
2863 State != nullptr);
2864 Node *Ty = getDerived().parseType();
2865 if (Ty == nullptr)
2866 return nullptr;
2867 if (State) State->CtorDtorConversion = true;
2868 return make<ConversionOperatorType>(Ty);
2869 }
2870 }
2871 return nullptr;
2872 case 'd':
2873 switch (look(1)) {
2874 case 'a':
2875 First += 2;
2876 return make<NameType>("operator delete[]");
2877 case 'e':
2878 First += 2;
2879 return make<NameType>("operator*");
2880 case 'l':
2881 First += 2;
2882 return make<NameType>("operator delete");
2883 case 'v':
2884 First += 2;
2885 return make<NameType>("operator/");
2886 case 'V':
2887 First += 2;
2888 return make<NameType>("operator/=");
2889 }
2890 return nullptr;
2891 case 'e':
2892 switch (look(1)) {
2893 case 'o':
2894 First += 2;
2895 return make<NameType>("operator^");
2896 case 'O':
2897 First += 2;
2898 return make<NameType>("operator^=");
2899 case 'q':
2900 First += 2;
2901 return make<NameType>("operator==");
2902 }
2903 return nullptr;
2904 case 'g':
2905 switch (look(1)) {
2906 case 'e':
2907 First += 2;
2908 return make<NameType>("operator>=");
2909 case 't':
2910 First += 2;
2911 return make<NameType>("operator>");
2912 }
2913 return nullptr;
2914 case 'i':
2915 if (look(1) == 'x') {
2916 First += 2;
2917 return make<NameType>("operator[]");
2918 }
2919 return nullptr;
2920 case 'l':
2921 switch (look(1)) {
2922 case 'e':
2923 First += 2;
2924 return make<NameType>("operator<=");
2925 // ::= li <source-name> # operator ""
2926 case 'i': {
2927 First += 2;
2928 Node *SN = getDerived().parseSourceName(State);
2929 if (SN == nullptr)
2930 return nullptr;
2931 return make<LiteralOperator>(SN);
2932 }
2933 case 's':
2934 First += 2;
2935 return make<NameType>("operator<<");
2936 case 'S':
2937 First += 2;
2938 return make<NameType>("operator<<=");
2939 case 't':
2940 First += 2;
2941 return make<NameType>("operator<");
2942 }
2943 return nullptr;
2944 case 'm':
2945 switch (look(1)) {
2946 case 'i':
2947 First += 2;
2948 return make<NameType>("operator-");
2949 case 'I':
2950 First += 2;
2951 return make<NameType>("operator-=");
2952 case 'l':
2953 First += 2;
2954 return make<NameType>("operator*");
2955 case 'L':
2956 First += 2;
2957 return make<NameType>("operator*=");
2958 case 'm':
2959 First += 2;
2960 return make<NameType>("operator--");
2961 }
2962 return nullptr;
2963 case 'n':
2964 switch (look(1)) {
2965 case 'a':
2966 First += 2;
2967 return make<NameType>("operator new[]");
2968 case 'e':
2969 First += 2;
2970 return make<NameType>("operator!=");
2971 case 'g':
2972 First += 2;
2973 return make<NameType>("operator-");
2974 case 't':
2975 First += 2;
2976 return make<NameType>("operator!");
2977 case 'w':
2978 First += 2;
2979 return make<NameType>("operator new");
2980 }
2981 return nullptr;
2982 case 'o':
2983 switch (look(1)) {
2984 case 'o':
2985 First += 2;
2986 return make<NameType>("operator||");
2987 case 'r':
2988 First += 2;
2989 return make<NameType>("operator|");
2990 case 'R':
2991 First += 2;
2992 return make<NameType>("operator|=");
2993 }
2994 return nullptr;
2995 case 'p':
2996 switch (look(1)) {
2997 case 'm':
2998 First += 2;
2999 return make<NameType>("operator->*");
3000 case 'l':
3001 First += 2;
3002 return make<NameType>("operator+");
3003 case 'L':
3004 First += 2;
3005 return make<NameType>("operator+=");
3006 case 'p':
3007 First += 2;
3008 return make<NameType>("operator++");
3009 case 's':
3010 First += 2;
3011 return make<NameType>("operator+");
3012 case 't':
3013 First += 2;
3014 return make<NameType>("operator->");
3015 }
3016 return nullptr;
3017 case 'q':
3018 if (look(1) == 'u') {
3019 First += 2;
3020 return make<NameType>("operator?");
3021 }
3022 return nullptr;
3023 case 'r':
3024 switch (look(1)) {
3025 case 'm':
3026 First += 2;
3027 return make<NameType>("operator%");
3028 case 'M':
3029 First += 2;
3030 return make<NameType>("operator%=");
3031 case 's':
3032 First += 2;
3033 return make<NameType>("operator>>");
3034 case 'S':
3035 First += 2;
3036 return make<NameType>("operator>>=");
3037 }
3038 return nullptr;
3039 case 's':
3040 if (look(1) == 's') {
3041 First += 2;
3042 return make<NameType>("operator<=>");
3043 }
3044 return nullptr;
3045 // ::= v <digit> <source-name> # vendor extended operator
3046 case 'v':
3047 if (std::isdigit(look(1))) {
3048 First += 2;
3049 Node *SN = getDerived().parseSourceName(State);
3050 if (SN == nullptr)
3051 return nullptr;
3052 return make<ConversionOperatorType>(SN);
3053 }
3054 return nullptr;
3055 }
3056 return nullptr;
3057}
3058
3059// <ctor-dtor-name> ::= C1 # complete object constructor
3060// ::= C2 # base object constructor
3061// ::= C3 # complete object allocating constructor
3062// extension ::= C4 # gcc old-style "[unified]" constructor
3063// extension ::= C5 # the COMDAT used for ctors
3064// ::= D0 # deleting destructor
3065// ::= D1 # complete object destructor
3066// ::= D2 # base object destructor
3067// extension ::= D4 # gcc old-style "[unified]" destructor
3068// extension ::= D5 # the COMDAT used for dtors
3069template <typename Derived, typename Alloc>
3070Node *
3071AbstractManglingParser<Derived, Alloc>::parseCtorDtorName(Node *&SoFar,
3072 NameState *State) {
3073 if (SoFar->getKind() == Node::KSpecialSubstitution) {
3074 auto SSK = static_cast<SpecialSubstitution *>(SoFar)->SSK;
3075 switch (SSK) {
3076 case SpecialSubKind::string:
3077 case SpecialSubKind::istream:
3078 case SpecialSubKind::ostream:
3079 case SpecialSubKind::iostream:
3080 SoFar = make<ExpandedSpecialSubstitution>(SSK);
3081 if (!SoFar)
3082 return nullptr;
3083 break;
3084 default:
3085 break;
3086 }
3087 }
3088
3089 if (consumeIf('C')) {
3090 bool IsInherited = consumeIf('I');
3091 if (look() != '1' && look() != '2' && look() != '3' && look() != '4' &&
3092 look() != '5')
3093 return nullptr;
3094 int Variant = look() - '0';
3095 ++First;
3096 if (State) State->CtorDtorConversion = true;
3097 if (IsInherited) {
3098 if (getDerived().parseName(State) == nullptr)
3099 return nullptr;
3100 }
3101 return make<CtorDtorName>(SoFar, /*IsDtor=*/false, Variant);
3102 }
3103
3104 if (look() == 'D' && (look(1) == '0' || look(1) == '1' || look(1) == '2' ||
3105 look(1) == '4' || look(1) == '5')) {
3106 int Variant = look(1) - '0';
3107 First += 2;
3108 if (State) State->CtorDtorConversion = true;
3109 return make<CtorDtorName>(SoFar, /*IsDtor=*/true, Variant);
3110 }
3111
3112 return nullptr;
3113}
3114
3115// <nested-name> ::= N [<CV-Qualifiers>] [<ref-qualifier>] <prefix> <unqualified-name> E
3116// ::= N [<CV-Qualifiers>] [<ref-qualifier>] <template-prefix> <template-args> E
3117//
3118// <prefix> ::= <prefix> <unqualified-name>
3119// ::= <template-prefix> <template-args>
3120// ::= <template-param>
3121// ::= <decltype>
3122// ::= # empty
3123// ::= <substitution>
3124// ::= <prefix> <data-member-prefix>
3125// extension ::= L
3126//
3127// <data-member-prefix> := <member source-name> [<template-args>] M
3128//
3129// <template-prefix> ::= <prefix> <template unqualified-name>
3130// ::= <template-param>
3131// ::= <substitution>
3132template <typename Derived, typename Alloc>
3133Node *
3134AbstractManglingParser<Derived, Alloc>::parseNestedName(NameState *State) {
3135 if (!consumeIf('N'))
3136 return nullptr;
3137
3138 Qualifiers CVTmp = parseCVQualifiers();
3139 if (State) State->CVQualifiers = CVTmp;
3140
3141 if (consumeIf('O')) {
3142 if (State) State->ReferenceQualifier = FrefQualRValue;
3143 } else if (consumeIf('R')) {
3144 if (State) State->ReferenceQualifier = FrefQualLValue;
3145 } else
3146 if (State) State->ReferenceQualifier = FrefQualNone;
3147
3148 Node *SoFar = nullptr;
3149 auto PushComponent = [&](Node *Comp) {
3150 if (!Comp) return false;
3151 if (SoFar) SoFar = make<NestedName>(SoFar, Comp);
3152 else SoFar = Comp;
3153 if (State) State->EndsWithTemplateArgs = false;
3154 return SoFar != nullptr;
3155 };
3156
3157 if (consumeIf("St")) {
3158 SoFar = make<NameType>("std");
3159 if (!SoFar)
3160 return nullptr;
3161 }
3162
3163 while (!consumeIf('E')) {
3164 consumeIf('L'); // extension
3165
3166 // <data-member-prefix> := <member source-name> [<template-args>] M
3167 if (consumeIf('M')) {
3168 if (SoFar == nullptr)
3169 return nullptr;
3170 continue;
3171 }
3172
3173 // ::= <template-param>
3174 if (look() == 'T') {
3175 if (!PushComponent(getDerived().parseTemplateParam()))
3176 return nullptr;
3177 Subs.push_back(SoFar);
3178 continue;
3179 }
3180
3181 // ::= <template-prefix> <template-args>
3182 if (look() == 'I') {
3183 Node *TA = getDerived().parseTemplateArgs(State != nullptr);
3184 if (TA == nullptr || SoFar == nullptr)
3185 return nullptr;
3186 SoFar = make<NameWithTemplateArgs>(SoFar, TA);
3187 if (!SoFar)
3188 return nullptr;
3189 if (State) State->EndsWithTemplateArgs = true;
3190 Subs.push_back(SoFar);
3191 continue;
3192 }
3193
3194 // ::= <decltype>
3195 if (look() == 'D' && (look(1) == 't' || look(1) == 'T')) {
3196 if (!PushComponent(getDerived().parseDecltype()))
3197 return nullptr;
3198 Subs.push_back(SoFar);
3199 continue;
3200 }
3201
3202 // ::= <substitution>
3203 if (look() == 'S' && look(1) != 't') {
3204 Node *S = getDerived().parseSubstitution();
3205 if (!PushComponent(S))
3206 return nullptr;
3207 if (SoFar != S)
3208 Subs.push_back(S);
3209 continue;
3210 }
3211
3212 // Parse an <unqualified-name> thats actually a <ctor-dtor-name>.
3213 if (look() == 'C' || (look() == 'D' && look(1) != 'C')) {
3214 if (SoFar == nullptr)
3215 return nullptr;
3216 if (!PushComponent(getDerived().parseCtorDtorName(SoFar, State)))
3217 return nullptr;
3218 SoFar = getDerived().parseAbiTags(SoFar);
3219 if (SoFar == nullptr)
3220 return nullptr;
3221 Subs.push_back(SoFar);
3222 continue;
3223 }
3224
3225 // ::= <prefix> <unqualified-name>
3226 if (!PushComponent(getDerived().parseUnqualifiedName(State)))
3227 return nullptr;
3228 Subs.push_back(SoFar);
3229 }
3230
3231 if (SoFar == nullptr || Subs.empty())
3232 return nullptr;
3233
3234 Subs.pop_back();
3235 return SoFar;
3236}
3237
3238// <simple-id> ::= <source-name> [ <template-args> ]
3239template <typename Derived, typename Alloc>
3240Node *AbstractManglingParser<Derived, Alloc>::parseSimpleId() {
3241 Node *SN = getDerived().parseSourceName(/*NameState=*/nullptr);
3242 if (SN == nullptr)
3243 return nullptr;
3244 if (look() == 'I') {
3245 Node *TA = getDerived().parseTemplateArgs();
3246 if (TA == nullptr)
3247 return nullptr;
3248 return make<NameWithTemplateArgs>(SN, TA);
3249 }
3250 return SN;
3251}
3252
3253// <destructor-name> ::= <unresolved-type> # e.g., ~T or ~decltype(f())
3254// ::= <simple-id> # e.g., ~A<2*N>
3255template <typename Derived, typename Alloc>
3256Node *AbstractManglingParser<Derived, Alloc>::parseDestructorName() {
3257 Node *Result;
3258 if (std::isdigit(look()))
3259 Result = getDerived().parseSimpleId();
3260 else
3261 Result = getDerived().parseUnresolvedType();
3262 if (Result == nullptr)
3263 return nullptr;
3264 return make<DtorName>(Result);
3265}
3266
3267// <unresolved-type> ::= <template-param>
3268// ::= <decltype>
3269// ::= <substitution>
3270template <typename Derived, typename Alloc>
3271Node *AbstractManglingParser<Derived, Alloc>::parseUnresolvedType() {
3272 if (look() == 'T') {
3273 Node *TP = getDerived().parseTemplateParam();
3274 if (TP == nullptr)
3275 return nullptr;
3276 Subs.push_back(TP);
3277 return TP;
3278 }
3279 if (look() == 'D') {
3280 Node *DT = getDerived().parseDecltype();
3281 if (DT == nullptr)
3282 return nullptr;
3283 Subs.push_back(DT);
3284 return DT;
3285 }
3286 return getDerived().parseSubstitution();
3287}
3288
3289// <base-unresolved-name> ::= <simple-id> # unresolved name
3290// extension ::= <operator-name> # unresolved operator-function-id
3291// extension ::= <operator-name> <template-args> # unresolved operator template-id
3292// ::= on <operator-name> # unresolved operator-function-id
3293// ::= on <operator-name> <template-args> # unresolved operator template-id
3294// ::= dn <destructor-name> # destructor or pseudo-destructor;
3295// # e.g. ~X or ~X<N-1>
3296template <typename Derived, typename Alloc>
3297Node *AbstractManglingParser<Derived, Alloc>::parseBaseUnresolvedName() {
3298 if (std::isdigit(look()))
3299 return getDerived().parseSimpleId();
3300
3301 if (consumeIf("dn"))
3302 return getDerived().parseDestructorName();
3303
3304 consumeIf("on");
3305
3306 Node *Oper = getDerived().parseOperatorName(/*NameState=*/nullptr);
3307 if (Oper == nullptr)
3308 return nullptr;
3309 if (look() == 'I') {
3310 Node *TA = getDerived().parseTemplateArgs();
3311 if (TA == nullptr)
3312 return nullptr;
3313 return make<NameWithTemplateArgs>(Oper, TA);
3314 }
3315 return Oper;
3316}
3317
3318// <unresolved-name>
3319// extension ::= srN <unresolved-type> [<template-args>] <unresolved-qualifier-level>* E <base-unresolved-name>
3320// ::= [gs] <base-unresolved-name> # x or (with "gs") ::x
3321// ::= [gs] sr <unresolved-qualifier-level>+ E <base-unresolved-name>
3322// # A::x, N::y, A<T>::z; "gs" means leading "::"
3323// ::= sr <unresolved-type> <base-unresolved-name> # T::x / decltype(p)::x
3324// extension ::= sr <unresolved-type> <template-args> <base-unresolved-name>
3325// # T::N::x /decltype(p)::N::x
3326// (ignored) ::= srN <unresolved-type> <unresolved-qualifier-level>+ E <base-unresolved-name>
3327//
3328// <unresolved-qualifier-level> ::= <simple-id>
3329template <typename Derived, typename Alloc>
3330Node *AbstractManglingParser<Derived, Alloc>::parseUnresolvedName() {
3331 Node *SoFar = nullptr;
3332
3333 // srN <unresolved-type> [<template-args>] <unresolved-qualifier-level>* E <base-unresolved-name>
3334 // srN <unresolved-type> <unresolved-qualifier-level>+ E <base-unresolved-name>
3335 if (consumeIf("srN")) {
3336 SoFar = getDerived().parseUnresolvedType();
3337 if (SoFar == nullptr)
3338 return nullptr;
3339
3340 if (look() == 'I') {
3341 Node *TA = getDerived().parseTemplateArgs();
3342 if (TA == nullptr)
3343 return nullptr;
3344 SoFar = make<NameWithTemplateArgs>(SoFar, TA);
3345 if (!SoFar)
3346 return nullptr;
3347 }
3348
3349 while (!consumeIf('E')) {
3350 Node *Qual = getDerived().parseSimpleId();
3351 if (Qual == nullptr)
3352 return nullptr;
3353 SoFar = make<QualifiedName>(SoFar, Qual);
3354 if (!SoFar)
3355 return nullptr;
3356 }
3357
3358 Node *Base = getDerived().parseBaseUnresolvedName();
3359 if (Base == nullptr)
3360 return nullptr;
3361 return make<QualifiedName>(SoFar, Base);
3362 }
3363
3364 bool Global = consumeIf("gs");
3365
3366 // [gs] <base-unresolved-name> # x or (with "gs") ::x
3367 if (!consumeIf("sr")) {
3368 SoFar = getDerived().parseBaseUnresolvedName();
3369 if (SoFar == nullptr)
3370 return nullptr;
3371 if (Global)
3372 SoFar = make<GlobalQualifiedName>(SoFar);
3373 return SoFar;
3374 }
3375
3376 // [gs] sr <unresolved-qualifier-level>+ E <base-unresolved-name>
3377 if (std::isdigit(look())) {
3378 do {
3379 Node *Qual = getDerived().parseSimpleId();
3380 if (Qual == nullptr)
3381 return nullptr;
3382 if (SoFar)
3383 SoFar = make<QualifiedName>(SoFar, Qual);
3384 else if (Global)
3385 SoFar = make<GlobalQualifiedName>(Qual);
3386 else
3387 SoFar = Qual;
3388 if (!SoFar)
3389 return nullptr;
3390 } while (!consumeIf('E'));
3391 }
3392 // sr <unresolved-type> <base-unresolved-name>
3393 // sr <unresolved-type> <template-args> <base-unresolved-name>
3394 else {
3395 SoFar = getDerived().parseUnresolvedType();
3396 if (SoFar == nullptr)
3397 return nullptr;
3398
3399 if (look() == 'I') {
3400 Node *TA = getDerived().parseTemplateArgs();
3401 if (TA == nullptr)
3402 return nullptr;
3403 SoFar = make<NameWithTemplateArgs>(SoFar, TA);
3404 if (!SoFar)
3405 return nullptr;
3406 }
3407 }
3408
3409 assert(SoFar != nullptr);
3410
3411 Node *Base = getDerived().parseBaseUnresolvedName();
3412 if (Base == nullptr)
3413 return nullptr;
3414 return make<QualifiedName>(SoFar, Base);
3415}
3416
3417// <abi-tags> ::= <abi-tag> [<abi-tags>]
3418// <abi-tag> ::= B <source-name>
3419template <typename Derived, typename Alloc>
3420Node *AbstractManglingParser<Derived, Alloc>::parseAbiTags(Node *N) {
3421 while (consumeIf('B')) {
3422 StringView SN = parseBareSourceName();
3423 if (SN.empty())
3424 return nullptr;
3425 N = make<AbiTagAttr>(N, SN);
3426 if (!N)
3427 return nullptr;
3428 }
3429 return N;
3430}
3431
3432// <number> ::= [n] <non-negative decimal integer>
3433template <typename Alloc, typename Derived>
3434StringView
3435AbstractManglingParser<Alloc, Derived>::parseNumber(bool AllowNegative) {
3436 const char *Tmp = First;
3437 if (AllowNegative)
3438 consumeIf('n');
3439 if (numLeft() == 0 || !std::isdigit(*First))
3440 return StringView();
3441 while (numLeft() != 0 && std::isdigit(*First))
3442 ++First;
3443 return StringView(Tmp, First);
3444}
3445
3446// <positive length number> ::= [0-9]*
3447template <typename Alloc, typename Derived>
3448bool AbstractManglingParser<Alloc, Derived>::parsePositiveInteger(size_t *Out) {
3449 *Out = 0;
3450 if (look() < '0' || look() > '9')
3451 return true;
3452 while (look() >= '0' && look() <= '9') {
3453 *Out *= 10;
3454 *Out += static_cast<size_t>(consume() - '0');
3455 }
3456 return false;
3457}
3458
3459template <typename Alloc, typename Derived>
3460StringView AbstractManglingParser<Alloc, Derived>::parseBareSourceName() {
3461 size_t Int = 0;
3462 if (parsePositiveInteger(&Int) || numLeft() < Int)
3463 return StringView();
3464 StringView R(First, First + Int);
3465 First += Int;
3466 return R;
3467}
3468
3469// <function-type> ::= [<CV-qualifiers>] [<exception-spec>] [Dx] F [Y] <bare-function-type> [<ref-qualifier>] E
3470//
3471// <exception-spec> ::= Do # non-throwing exception-specification (e.g., noexcept, throw())
3472// ::= DO <expression> E # computed (instantiation-dependent) noexcept
3473// ::= Dw <type>+ E # dynamic exception specification with instantiation-dependent types
3474//
3475// <ref-qualifier> ::= R # & ref-qualifier
3476// <ref-qualifier> ::= O # && ref-qualifier
3477template <typename Derived, typename Alloc>
3478Node *AbstractManglingParser<Derived, Alloc>::parseFunctionType() {
3479 Qualifiers CVQuals = parseCVQualifiers();
3480
3481 Node *ExceptionSpec = nullptr;
3482 if (consumeIf("Do")) {
3483 ExceptionSpec = make<NameType>("noexcept");
3484 if (!ExceptionSpec)
3485 return nullptr;
3486 } else if (consumeIf("DO")) {
3487 Node *E = getDerived().parseExpr();
3488 if (E == nullptr || !consumeIf('E'))
3489 return nullptr;
3490 ExceptionSpec = make<NoexceptSpec>(E);
3491 if (!ExceptionSpec)
3492 return nullptr;
3493 } else if (consumeIf("Dw")) {
3494 size_t SpecsBegin = Names.size();
3495 while (!consumeIf('E')) {
3496 Node *T = getDerived().parseType();
3497 if (T == nullptr)
3498 return nullptr;
3499 Names.push_back(T);
3500 }
3501 ExceptionSpec =
3502 make<DynamicExceptionSpec>(popTrailingNodeArray(SpecsBegin));
3503 if (!ExceptionSpec)
3504 return nullptr;
3505 }
3506
3507 consumeIf("Dx"); // transaction safe
3508
3509 if (!consumeIf('F'))
3510 return nullptr;
3511 consumeIf('Y'); // extern "C"
3512 Node *ReturnType = getDerived().parseType();
3513 if (ReturnType == nullptr)
3514 return nullptr;
3515
3516 FunctionRefQual ReferenceQualifier = FrefQualNone;
3517 size_t ParamsBegin = Names.size();
3518 while (true) {
3519 if (consumeIf('E'))
3520 break;
3521 if (consumeIf('v'))
3522 continue;
3523 if (consumeIf("RE")) {
3524 ReferenceQualifier = FrefQualLValue;
3525 break;
3526 }
3527 if (consumeIf("OE")) {
3528 ReferenceQualifier = FrefQualRValue;
3529 break;
3530 }
3531 Node *T = getDerived().parseType();
3532 if (T == nullptr)
3533 return nullptr;
3534 Names.push_back(T);
3535 }
3536
3537 NodeArray Params = popTrailingNodeArray(ParamsBegin);
3538 return make<FunctionType>(ReturnType, Params, CVQuals,
3539 ReferenceQualifier, ExceptionSpec);
3540}
3541
3542// extension:
3543// <vector-type> ::= Dv <positive dimension number> _ <extended element type>
3544// ::= Dv [<dimension expression>] _ <element type>
3545// <extended element type> ::= <element type>
3546// ::= p # AltiVec vector pixel
3547template <typename Derived, typename Alloc>
3548Node *AbstractManglingParser<Derived, Alloc>::parseVectorType() {
3549 if (!consumeIf("Dv"))
3550 return nullptr;
3551 if (look() >= '1' && look() <= '9') {
3552 StringView DimensionNumber = parseNumber();
3553 if (!consumeIf('_'))
3554 return nullptr;
3555 if (consumeIf('p'))
3556 return make<PixelVectorType>(DimensionNumber);
3557 Node *ElemType = getDerived().parseType();
3558 if (ElemType == nullptr)
3559 return nullptr;
3560 return make<VectorType>(ElemType, DimensionNumber);
3561 }
3562
3563 if (!consumeIf('_')) {
3564 Node *DimExpr = getDerived().parseExpr();
3565 if (!DimExpr)
3566 return nullptr;
3567 if (!consumeIf('_'))
3568 return nullptr;
3569 Node *ElemType = getDerived().parseType();
3570 if (!ElemType)
3571 return nullptr;
3572 return make<VectorType>(ElemType, DimExpr);
3573 }
3574 Node *ElemType = getDerived().parseType();
3575 if (!ElemType)
3576 return nullptr;
3577 return make<VectorType>(ElemType, StringView());
3578}
3579
3580// <decltype> ::= Dt <expression> E # decltype of an id-expression or class member access (C++0x)
3581// ::= DT <expression> E # decltype of an expression (C++0x)
3582template <typename Derived, typename Alloc>
3583Node *AbstractManglingParser<Derived, Alloc>::parseDecltype() {
3584 if (!consumeIf('D'))
3585 return nullptr;
3586 if (!consumeIf('t') && !consumeIf('T'))
3587 return nullptr;
3588 Node *E = getDerived().parseExpr();
3589 if (E == nullptr)
3590 return nullptr;
3591 if (!consumeIf('E'))
3592 return nullptr;
3593 return make<EnclosingExpr>("decltype(", E, ")");
3594}
3595
3596// <array-type> ::= A <positive dimension number> _ <element type>
3597// ::= A [<dimension expression>] _ <element type>
3598template <typename Derived, typename Alloc>
3599Node *AbstractManglingParser<Derived, Alloc>::parseArrayType() {
3600 if (!consumeIf('A'))
3601 return nullptr;
3602
3603 NodeOrString Dimension;
3604
3605 if (std::isdigit(look())) {
3606 Dimension = parseNumber();
3607 if (!consumeIf('_'))
3608 return nullptr;
3609 } else if (!consumeIf('_')) {
3610 Node *DimExpr = getDerived().parseExpr();
3611 if (DimExpr == nullptr)
3612 return nullptr;
3613 if (!consumeIf('_'))
3614 return nullptr;
3615 Dimension = DimExpr;
3616 }
3617
3618 Node *Ty = getDerived().parseType();
3619 if (Ty == nullptr)
3620 return nullptr;
3621 return make<ArrayType>(Ty, Dimension);
3622}
3623
3624// <pointer-to-member-type> ::= M <class type> <member type>
3625template <typename Derived, typename Alloc>
3626Node *AbstractManglingParser<Derived, Alloc>::parsePointerToMemberType() {
3627 if (!consumeIf('M'))
3628 return nullptr;
3629 Node *ClassType = getDerived().parseType();
3630 if (ClassType == nullptr)
3631 return nullptr;
3632 Node *MemberType = getDerived().parseType();
3633 if (MemberType == nullptr)
3634 return nullptr;
3635 return make<PointerToMemberType>(ClassType, MemberType);
3636}
3637
3638// <class-enum-type> ::= <name> # non-dependent type name, dependent type name, or dependent typename-specifier
3639// ::= Ts <name> # dependent elaborated type specifier using 'struct' or 'class'
3640// ::= Tu <name> # dependent elaborated type specifier using 'union'
3641// ::= Te <name> # dependent elaborated type specifier using 'enum'
3642template <typename Derived, typename Alloc>
3643Node *AbstractManglingParser<Derived, Alloc>::parseClassEnumType() {
3644 StringView ElabSpef;
3645 if (consumeIf("Ts"))
3646 ElabSpef = "struct";
3647 else if (consumeIf("Tu"))
3648 ElabSpef = "union";
3649 else if (consumeIf("Te"))
3650 ElabSpef = "enum";
3651
3652 Node *Name = getDerived().parseName();
3653 if (Name == nullptr)
3654 return nullptr;
3655
3656 if (!ElabSpef.empty())
3657 return make<ElaboratedTypeSpefType>(ElabSpef, Name);
3658
3659 return Name;
3660}
3661
3662// <qualified-type> ::= <qualifiers> <type>
3663// <qualifiers> ::= <extended-qualifier>* <CV-qualifiers>
3664// <extended-qualifier> ::= U <source-name> [<template-args>] # vendor extended type qualifier
3665template <typename Derived, typename Alloc>
3666Node *AbstractManglingParser<Derived, Alloc>::parseQualifiedType() {
3667 if (consumeIf('U')) {
3668 StringView Qual = parseBareSourceName();
3669 if (Qual.empty())
3670 return nullptr;
3671
3672 // FIXME parse the optional <template-args> here!
3673
3674 // extension ::= U <objc-name> <objc-type> # objc-type<identifier>
3675 if (Qual.startsWith("objcproto")) {
3676 StringView ProtoSourceName = Qual.dropFront(std::strlen("objcproto"));
3677 StringView Proto;
3678 {
3679 SwapAndRestore<const char *> SaveFirst(First, ProtoSourceName.begin()),
3680 SaveLast(Last, ProtoSourceName.end());
3681 Proto = parseBareSourceName();
3682 }
3683 if (Proto.empty())
3684 return nullptr;
3685 Node *Child = getDerived().parseQualifiedType();
3686 if (Child == nullptr)
3687 return nullptr;
3688 return make<ObjCProtoName>(Child, Proto);
3689 }
3690
3691 Node *Child = getDerived().parseQualifiedType();
3692 if (Child == nullptr)
3693 return nullptr;
3694 return make<VendorExtQualType>(Child, Qual);
3695 }
3696
3697 Qualifiers Quals = parseCVQualifiers();
3698 Node *Ty = getDerived().parseType();
3699 if (Ty == nullptr)
3700 return nullptr;
3701 if (Quals != QualNone)
3702 Ty = make<QualType>(Ty, Quals);
3703 return Ty;
3704}
3705
3706// <type> ::= <builtin-type>
3707// ::= <qualified-type>
3708// ::= <function-type>
3709// ::= <class-enum-type>
3710// ::= <array-type>
3711// ::= <pointer-to-member-type>
3712// ::= <template-param>
3713// ::= <template-template-param> <template-args>
3714// ::= <decltype>
3715// ::= P <type> # pointer
3716// ::= R <type> # l-value reference
3717// ::= O <type> # r-value reference (C++11)
3718// ::= C <type> # complex pair (C99)
3719// ::= G <type> # imaginary (C99)
3720// ::= <substitution> # See Compression below
3721// extension ::= U <objc-name> <objc-type> # objc-type<identifier>
3722// extension ::= <vector-type> # <vector-type> starts with Dv
3723//
3724// <objc-name> ::= <k0 number> objcproto <k1 number> <identifier> # k0 = 9 + <number of digits in k1> + k1
3725// <objc-type> ::= <source-name> # PU<11+>objcproto 11objc_object<source-name> 11objc_object -> id<source-name>
3726template <typename Derived, typename Alloc>
3727Node *AbstractManglingParser<Derived, Alloc>::parseType() {
3728 Node *Result = nullptr;
3729
3730 switch (look()) {
3731 // ::= <qualified-type>
3732 case 'r':
3733 case 'V':
3734 case 'K': {
3735 unsigned AfterQuals = 0;
3736 if (look(AfterQuals) == 'r') ++AfterQuals;
3737 if (look(AfterQuals) == 'V') ++AfterQuals;
3738 if (look(AfterQuals) == 'K') ++AfterQuals;
3739
3740 if (look(AfterQuals) == 'F' ||
3741 (look(AfterQuals) == 'D' &&
3742 (look(AfterQuals + 1) == 'o' || look(AfterQuals + 1) == 'O' ||
3743 look(AfterQuals + 1) == 'w' || look(AfterQuals + 1) == 'x'))) {
3744 Result = getDerived().parseFunctionType();
3745 break;
3746 }
3747 DEMANGLE_FALLTHROUGH;
3748 }
3749 case 'U': {
3750 Result = getDerived().parseQualifiedType();
3751 break;
3752 }
3753 // <builtin-type> ::= v # void
3754 case 'v':
3755 ++First;
3756 return make<NameType>("void");
3757 // ::= w # wchar_t
3758 case 'w':
3759 ++First;
3760 return make<NameType>("wchar_t");
3761 // ::= b # bool
3762 case 'b':
3763 ++First;
3764 return make<NameType>("bool");
3765 // ::= c # char
3766 case 'c':
3767 ++First;
3768 return make<NameType>("char");
3769 // ::= a # signed char
3770 case 'a':
3771 ++First;
3772 return make<NameType>("signed char");
3773 // ::= h # unsigned char
3774 case 'h':
3775 ++First;
3776 return make<NameType>("unsigned char");
3777 // ::= s # short
3778 case 's':
3779 ++First;
3780 return make<NameType>("short");
3781 // ::= t # unsigned short
3782 case 't':
3783 ++First;
3784 return make<NameType>("unsigned short");
3785 // ::= i # int
3786 case 'i':
3787 ++First;
3788 return make<NameType>("int");
3789 // ::= j # unsigned int
3790 case 'j':
3791 ++First;
3792 return make<NameType>("unsigned int");
3793 // ::= l # long
3794 case 'l':
3795 ++First;
3796 return make<NameType>("long");
3797 // ::= m # unsigned long
3798 case 'm':
3799 ++First;
3800 return make<NameType>("unsigned long");
3801 // ::= x # long long, __int64
3802 case 'x':
3803 ++First;
3804 return make<NameType>("long long");
3805 // ::= y # unsigned long long, __int64
3806 case 'y':
3807 ++First;
3808 return make<NameType>("unsigned long long");
3809 // ::= n # __int128
3810 case 'n':
3811 ++First;
3812 return make<NameType>("__int128");
3813 // ::= o # unsigned __int128
3814 case 'o':
3815 ++First;
3816 return make<NameType>("unsigned __int128");
3817 // ::= f # float
3818 case 'f':
3819 ++First;
3820 return make<NameType>("float");
3821 // ::= d # double
3822 case 'd':
3823 ++First;
3824 return make<NameType>("double");
3825 // ::= e # long double, __float80
3826 case 'e':
3827 ++First;
3828 return make<NameType>("long double");
3829 // ::= g # __float128
3830 case 'g':
3831 ++First;
3832 return make<NameType>("__float128");
3833 // ::= z # ellipsis
3834 case 'z':
3835 ++First;
3836 return make<NameType>("...");
3837
3838 // <builtin-type> ::= u <source-name> # vendor extended type
3839 case 'u': {
3840 ++First;
3841 StringView Res = parseBareSourceName();
3842 if (Res.empty())
3843 return nullptr;
3844 // Typically, <builtin-type>s are not considered substitution candidates,
3845 // but the exception to that exception is vendor extended types (Itanium C++
3846 // ABI 5.9.1).
3847 Result = make<NameType>(Res);
3848 break;
3849 }
3850 case 'D':
3851 switch (look(1)) {
3852 // ::= Dd # IEEE 754r decimal floating point (64 bits)
3853 case 'd':
3854 First += 2;
3855 return make<NameType>("decimal64");
3856 // ::= De # IEEE 754r decimal floating point (128 bits)
3857 case 'e':
3858 First += 2;
3859 return make<NameType>("decimal128");
3860 // ::= Df # IEEE 754r decimal floating point (32 bits)
3861 case 'f':
3862 First += 2;
3863 return make<NameType>("decimal32");
3864 // ::= Dh # IEEE 754r half-precision floating point (16 bits)
3865 case 'h':
3866 First += 2;
3867 return make<NameType>("decimal16");
3868 // ::= Di # char32_t
3869 case 'i':
3870 First += 2;
3871 return make<NameType>("char32_t");
3872 // ::= Ds # char16_t
3873 case 's':
3874 First += 2;
3875 return make<NameType>("char16_t");
3876 // ::= Du # char8_t (C++2a, not yet in the Itanium spec)
3877 case 'u':
3878 First += 2;
3879 return make<NameType>("char8_t");
3880 // ::= Da # auto (in dependent new-expressions)
3881 case 'a':
3882 First += 2;
3883 return make<NameType>("auto");
3884 // ::= Dc # decltype(auto)
3885 case 'c':
3886 First += 2;
3887 return make<NameType>("decltype(auto)");
3888 // ::= Dn # std::nullptr_t (i.e., decltype(nullptr))
3889 case 'n':
3890 First += 2;
3891 return make<NameType>("std::nullptr_t");
3892
3893 // ::= <decltype>
3894 case 't':
3895 case 'T': {
3896 Result = getDerived().parseDecltype();
3897 break;
3898 }
3899 // extension ::= <vector-type> # <vector-type> starts with Dv
3900 case 'v': {
3901 Result = getDerived().parseVectorType();
3902 break;
3903 }
3904 // ::= Dp <type> # pack expansion (C++0x)
3905 case 'p': {
3906 First += 2;
3907 Node *Child = getDerived().parseType();
3908 if (!Child)
3909 return nullptr;
3910 Result = make<ParameterPackExpansion>(Child);
3911 break;
3912 }
3913 // Exception specifier on a function type.
3914 case 'o':
3915 case 'O':
3916 case 'w':
3917 // Transaction safe function type.
3918 case 'x':
3919 Result = getDerived().parseFunctionType();
3920 break;
3921 }
3922 break;
3923 // ::= <function-type>
3924 case 'F': {
3925 Result = getDerived().parseFunctionType();
3926 break;
3927 }
3928 // ::= <array-type>
3929 case 'A': {
3930 Result = getDerived().parseArrayType();
3931 break;
3932 }
3933 // ::= <pointer-to-member-type>
3934 case 'M': {
3935 Result = getDerived().parsePointerToMemberType();
3936 break;
3937 }
3938 // ::= <template-param>
3939 case 'T': {
3940 // This could be an elaborate type specifier on a <class-enum-type>.
3941 if (look(1) == 's' || look(1) == 'u' || look(1) == 'e') {
3942 Result = getDerived().parseClassEnumType();
3943 break;
3944 }
3945
3946 Result = getDerived().parseTemplateParam();
3947 if (Result == nullptr)
3948 return nullptr;
3949
3950 // Result could be either of:
3951 // <type> ::= <template-param>
3952 // <type> ::= <template-template-param> <template-args>
3953 //
3954 // <template-template-param> ::= <template-param>
3955 // ::= <substitution>
3956 //
3957 // If this is followed by some <template-args>, and we're permitted to
3958 // parse them, take the second production.
3959
3960 if (TryToParseTemplateArgs && look() == 'I') {
3961 Node *TA = getDerived().parseTemplateArgs();
3962 if (TA == nullptr)
3963 return nullptr;
3964 Result = make<NameWithTemplateArgs>(Result, TA);
3965 }
3966 break;
3967 }
3968 // ::= P <type> # pointer
3969 case 'P': {
3970 ++First;
3971 Node *Ptr = getDerived().parseType();
3972 if (Ptr == nullptr)
3973 return nullptr;
3974 Result = make<PointerType>(Ptr);
3975 break;
3976 }
3977 // ::= R <type> # l-value reference
3978 case 'R': {
3979 ++First;
3980 Node *Ref = getDerived().parseType();
3981 if (Ref == nullptr)
3982 return nullptr;
3983 Result = make<ReferenceType>(Ref, ReferenceKind::LValue);
3984 break;
3985 }
3986 // ::= O <type> # r-value reference (C++11)
3987 case 'O': {
3988 ++First;
3989 Node *Ref = getDerived().parseType();
3990 if (Ref == nullptr)
3991 return nullptr;
3992 Result = make<ReferenceType>(Ref, ReferenceKind::RValue);
3993 break;
3994 }
3995 // ::= C <type> # complex pair (C99)
3996 case 'C': {
3997 ++First;
3998 Node *P = getDerived().parseType();
3999 if (P == nullptr)
4000 return nullptr;
4001 Result = make<PostfixQualifiedType>(P, " complex");
4002 break;
4003 }
4004 // ::= G <type> # imaginary (C99)
4005 case 'G': {
4006 ++First;
4007 Node *P = getDerived().parseType();
4008 if (P == nullptr)
4009 return P;
4010 Result = make<PostfixQualifiedType>(P, " imaginary");
4011 break;
4012 }
4013 // ::= <substitution> # See Compression below
4014 case 'S': {
4015 if (look(1) && look(1) != 't') {
4016 Node *Sub = getDerived().parseSubstitution();
4017 if (Sub == nullptr)
4018 return nullptr;
4019
4020 // Sub could be either of:
4021 // <type> ::= <substitution>
4022 // <type> ::= <template-template-param> <template-args>
4023 //
4024 // <template-template-param> ::= <template-param>
4025 // ::= <substitution>
4026 //
4027 // If this is followed by some <template-args>, and we're permitted to
4028 // parse them, take the second production.
4029
4030 if (TryToParseTemplateArgs && look() == 'I') {
4031 Node *TA = getDerived().parseTemplateArgs();
4032 if (TA == nullptr)
4033 return nullptr;
4034 Result = make<NameWithTemplateArgs>(Sub, TA);
4035 break;
4036 }
4037
4038 // If all we parsed was a substitution, don't re-insert into the
4039 // substitution table.
4040 return Sub;
4041 }
4042 DEMANGLE_FALLTHROUGH;
4043 }
4044 // ::= <class-enum-type>
4045 default: {
4046 Result = getDerived().parseClassEnumType();
4047 break;
4048 }
4049 }
4050
4051 // If we parsed a type, insert it into the substitution table. Note that all
4052 // <builtin-type>s and <substitution>s have already bailed out, because they
4053 // don't get substitutions.
4054 if (Result != nullptr)
4055 Subs.push_back(Result);
4056 return Result;
4057}
4058
4059template <typename Derived, typename Alloc>
4060Node *AbstractManglingParser<Derived, Alloc>::parsePrefixExpr(StringView Kind) {
4061 Node *E = getDerived().parseExpr();
4062 if (E == nullptr)
4063 return nullptr;
4064 return make<PrefixExpr>(Kind, E);
4065}
4066
4067template <typename Derived, typename Alloc>
4068Node *AbstractManglingParser<Derived, Alloc>::parseBinaryExpr(StringView Kind) {
4069 Node *LHS = getDerived().parseExpr();
4070 if (LHS == nullptr)
4071 return nullptr;
4072 Node *RHS = getDerived().parseExpr();
4073 if (RHS == nullptr)
4074 return nullptr;
4075 return make<BinaryExpr>(LHS, Kind, RHS);
4076}
4077
4078template <typename Derived, typename Alloc>
4079Node *
4080AbstractManglingParser<Derived, Alloc>::parseIntegerLiteral(StringView Lit) {
4081 StringView Tmp = parseNumber(true);
4082 if (!Tmp.empty() && consumeIf('E'))
4083 return make<IntegerLiteral>(Lit, Tmp);
4084 return nullptr;
4085}
4086
4087// <CV-Qualifiers> ::= [r] [V] [K]
4088template <typename Alloc, typename Derived>
4089Qualifiers AbstractManglingParser<Alloc, Derived>::parseCVQualifiers() {
4090 Qualifiers CVR = QualNone;
4091 if (consumeIf('r'))
4092 CVR |= QualRestrict;
4093 if (consumeIf('V'))
4094 CVR |= QualVolatile;
4095 if (consumeIf('K'))
4096 CVR |= QualConst;
4097 return CVR;
4098}
4099
4100// <function-param> ::= fp <top-level CV-Qualifiers> _ # L == 0, first parameter
4101// ::= fp <top-level CV-Qualifiers> <parameter-2 non-negative number> _ # L == 0, second and later parameters
4102// ::= fL <L-1 non-negative number> p <top-level CV-Qualifiers> _ # L > 0, first parameter
4103// ::= fL <L-1 non-negative number> p <top-level CV-Qualifiers> <parameter-2 non-negative number> _ # L > 0, second and later parameters
4104template <typename Derived, typename Alloc>
4105Node *AbstractManglingParser<Derived, Alloc>::parseFunctionParam() {
4106 if (consumeIf("fp")) {
4107 parseCVQualifiers();
4108 StringView Num = parseNumber();
4109 if (!consumeIf('_'))
4110 return nullptr;
4111 return make<FunctionParam>(Num);
4112 }
4113 if (consumeIf("fL")) {
4114 if (parseNumber().empty())
4115 return nullptr;
4116 if (!consumeIf('p'))
4117 return nullptr;
4118 parseCVQualifiers();
4119 StringView Num = parseNumber();
4120 if (!consumeIf('_'))
4121 return nullptr;
4122 return make<FunctionParam>(Num);
4123 }
4124 return nullptr;
4125}
4126
4127// [gs] nw <expression>* _ <type> E # new (expr-list) type
4128// [gs] nw <expression>* _ <type> <initializer> # new (expr-list) type (init)
4129// [gs] na <expression>* _ <type> E # new[] (expr-list) type
4130// [gs] na <expression>* _ <type> <initializer> # new[] (expr-list) type (init)
4131// <initializer> ::= pi <expression>* E # parenthesized initialization
4132template <typename Derived, typename Alloc>
4133Node *AbstractManglingParser<Derived, Alloc>::parseNewExpr() {
4134 bool Global = consumeIf("gs");
4135 bool IsArray = look(1) == 'a';
4136 if (!consumeIf("nw") && !consumeIf("na"))
4137 return nullptr;
4138 size_t Exprs = Names.size();
4139 while (!consumeIf('_')) {
4140 Node *Ex = getDerived().parseExpr();
4141 if (Ex == nullptr)
4142 return nullptr;
4143 Names.push_back(Ex);
4144 }
4145 NodeArray ExprList = popTrailingNodeArray(Exprs);
4146 Node *Ty = getDerived().parseType();
4147 if (Ty == nullptr)
4148 return Ty;
4149 if (consumeIf("pi")) {
4150 size_t InitsBegin = Names.size();
4151 while (!consumeIf('E')) {
4152 Node *Init = getDerived().parseExpr();
4153 if (Init == nullptr)
4154 return Init;
4155 Names.push_back(Init);
4156 }
4157 NodeArray Inits = popTrailingNodeArray(InitsBegin);
4158 return make<NewExpr>(ExprList, Ty, Inits, Global, IsArray);
4159 } else if (!consumeIf('E'))
4160 return nullptr;
4161 return make<NewExpr>(ExprList, Ty, NodeArray(), Global, IsArray);
4162}
4163
4164// cv <type> <expression> # conversion with one argument
4165// cv <type> _ <expression>* E # conversion with a different number of arguments
4166template <typename Derived, typename Alloc>
4167Node *AbstractManglingParser<Derived, Alloc>::parseConversionExpr() {
4168 if (!consumeIf("cv"))
4169 return nullptr;
4170 Node *Ty;
4171 {
4172 SwapAndRestore<bool> SaveTemp(TryToParseTemplateArgs, false);
4173 Ty = getDerived().parseType();
4174 }
4175
4176 if (Ty == nullptr)
4177 return nullptr;
4178
4179 if (consumeIf('_')) {
4180 size_t ExprsBegin = Names.size();
4181 while (!consumeIf('E')) {
4182 Node *E = getDerived().parseExpr();
4183 if (E == nullptr)
4184 return E;
4185 Names.push_back(E);
4186 }
4187 NodeArray Exprs = popTrailingNodeArray(ExprsBegin);
4188 return make<ConversionExpr>(Ty, Exprs);
4189 }
4190
4191 Node *E[1] = {getDerived().parseExpr()};
4192 if (E[0] == nullptr)
4193 return nullptr;
4194 return make<ConversionExpr>(Ty, makeNodeArray(E, E + 1));
4195}
4196
4197// <expr-primary> ::= L <type> <value number> E # integer literal
4198// ::= L <type> <value float> E # floating literal
4199// ::= L <string type> E # string literal
4200// ::= L <nullptr type> E # nullptr literal (i.e., "LDnE")
4201// ::= L <lambda type> E # lambda expression
4202// FIXME: ::= L <type> <real-part float> _ <imag-part float> E # complex floating point literal (C 2000)
4203// ::= L <mangled-name> E # external name
4204template <typename Derived, typename Alloc>
4205Node *AbstractManglingParser<Derived, Alloc>::parseExprPrimary() {
4206 if (!consumeIf('L'))
4207 return nullptr;
4208 switch (look()) {
4209 case 'w':
4210 ++First;
4211 return getDerived().parseIntegerLiteral("wchar_t");
4212 case 'b':
4213 if (consumeIf("b0E"))
4214 return make<BoolExpr>(0);
4215 if (consumeIf("b1E"))
4216 return make<BoolExpr>(1);
4217 return nullptr;
4218 case 'c':
4219 ++First;
4220 return getDerived().parseIntegerLiteral("char");
4221 case 'a':
4222 ++First;
4223 return getDerived().parseIntegerLiteral("signed char");
4224 case 'h':
4225 ++First;
4226 return getDerived().parseIntegerLiteral("unsigned char");
4227 case 's':
4228 ++First;
4229 return getDerived().parseIntegerLiteral("short");
4230 case 't':
4231 ++First;
4232 return getDerived().parseIntegerLiteral("unsigned short");
4233 case 'i':
4234 ++First;
4235 return getDerived().parseIntegerLiteral("");
4236 case 'j':
4237 ++First;
4238 return getDerived().parseIntegerLiteral("u");
4239 case 'l':
4240 ++First;
4241 return getDerived().parseIntegerLiteral("l");
4242 case 'm':
4243 ++First;
4244 return getDerived().parseIntegerLiteral("ul");
4245 case 'x':
4246 ++First;
4247 return getDerived().parseIntegerLiteral("ll");
4248 case 'y':
4249 ++First;
4250 return getDerived().parseIntegerLiteral("ull");
4251 case 'n':
4252 ++First;
4253 return getDerived().parseIntegerLiteral("__int128");
4254 case 'o':
4255 ++First;
4256 return getDerived().parseIntegerLiteral("unsigned __int128");
4257 case 'f':
4258 ++First;
4259 return getDerived().template parseFloatingLiteral<float>();
4260 case 'd':
4261 ++First;
4262 return getDerived().template parseFloatingLiteral<double>();
4263 case 'e':
4264 ++First;
4265 return getDerived().template parseFloatingLiteral<long double>();
4266 case '_':
4267 if (consumeIf("_Z")) {
4268 Node *R = getDerived().parseEncoding();
4269 if (R != nullptr && consumeIf('E'))
4270 return R;
4271 }
4272 return nullptr;
4273 case 'A': {
4274 Node *T = getDerived().parseType();
4275 if (T == nullptr)
4276 return nullptr;
4277 // FIXME: We need to include the string contents in the mangling.
4278 if (consumeIf('E'))
4279 return make<StringLiteral>(T);
4280 return nullptr;
4281 }
4282 case 'D':
4283 if (consumeIf("DnE"))
4284 return make<NameType>("nullptr");
4285 return nullptr;
4286 case 'T':
4287 // Invalid mangled name per
4288 // http://sourcerytools.com/pipermail/cxx-abi-dev/2011-August/002422.html
4289 return nullptr;
4290 case 'U': {
4291 // FIXME: Should we support LUb... for block literals?
4292 if (look(1) != 'l')
4293 return nullptr;
4294 Node *T = parseUnnamedTypeName(nullptr);
4295 if (!T || !consumeIf('E'))
4296 return nullptr;
4297 return make<LambdaExpr>(T);
4298 }
4299 default: {
4300 // might be named type
4301 Node *T = getDerived().parseType();
4302 if (T == nullptr)
4303 return nullptr;
4304 StringView N = parseNumber();
4305 if (N.empty())
4306 return nullptr;
4307 if (!consumeIf('E'))
4308 return nullptr;
4309 return make<IntegerCastExpr>(T, N);
4310 }
4311 }
4312}
4313
4314// <braced-expression> ::= <expression>
4315// ::= di <field source-name> <braced-expression> # .name = expr
4316// ::= dx <index expression> <braced-expression> # [expr] = expr
4317// ::= dX <range begin expression> <range end expression> <braced-expression>
4318template <typename Derived, typename Alloc>
4319Node *AbstractManglingParser<Derived, Alloc>::parseBracedExpr() {
4320 if (look() == 'd') {
4321 switch (look(1)) {
4322 case 'i': {
4323 First += 2;
4324 Node *Field = getDerived().parseSourceName(/*NameState=*/nullptr);
4325 if (Field == nullptr)
4326 return nullptr;
4327 Node *Init = getDerived().parseBracedExpr();
4328 if (Init == nullptr)
4329 return nullptr;
4330 return make<BracedExpr>(Field, Init, /*isArray=*/false);
4331 }
4332 case 'x': {
4333 First += 2;
4334 Node *Index = getDerived().parseExpr();
4335 if (Index == nullptr)
4336 return nullptr;
4337 Node *Init = getDerived().parseBracedExpr();
4338 if (Init == nullptr)
4339 return nullptr;
4340 return make<BracedExpr>(Index, Init, /*isArray=*/true);
4341 }
4342 case 'X': {
4343 First += 2;
4344 Node *RangeBegin = getDerived().parseExpr();
4345 if (RangeBegin == nullptr)
4346 return nullptr;
4347 Node *RangeEnd = getDerived().parseExpr();
4348 if (RangeEnd == nullptr)
4349 return nullptr;
4350 Node *Init = getDerived().parseBracedExpr();
4351 if (Init == nullptr)
4352 return nullptr;
4353 return make<BracedRangeExpr>(RangeBegin, RangeEnd, Init);
4354 }
4355 }
4356 }
4357 return getDerived().parseExpr();
4358}
4359
4360// (not yet in the spec)
4361// <fold-expr> ::= fL <binary-operator-name> <expression> <expression>
4362// ::= fR <binary-operator-name> <expression> <expression>
4363// ::= fl <binary-operator-name> <expression>
4364// ::= fr <binary-operator-name> <expression>
4365template <typename Derived, typename Alloc>
4366Node *AbstractManglingParser<Derived, Alloc>::parseFoldExpr() {
4367 if (!consumeIf('f'))
4368 return nullptr;
4369
4370 char FoldKind = look();
4371 bool IsLeftFold, HasInitializer;
4372 HasInitializer = FoldKind == 'L' || FoldKind == 'R';
4373 if (FoldKind == 'l' || FoldKind == 'L')
4374 IsLeftFold = true;
4375 else if (FoldKind == 'r' || FoldKind == 'R')
4376 IsLeftFold = false;
4377 else
4378 return nullptr;
4379 ++First;
4380
4381 // FIXME: This map is duplicated in parseOperatorName and parseExpr.
4382 StringView OperatorName;
4383 if (consumeIf("aa")) OperatorName = "&&";
4384 else if (consumeIf("an")) OperatorName = "&";
4385 else if (consumeIf("aN")) OperatorName = "&=";
4386 else if (consumeIf("aS")) OperatorName = "=";
4387 else if (consumeIf("cm")) OperatorName = ",";
4388 else if (consumeIf("ds")) OperatorName = ".*";
4389 else if (consumeIf("dv")) OperatorName = "/";
4390 else if (consumeIf("dV")) OperatorName = "/=";
4391 else if (consumeIf("eo")) OperatorName = "^";
4392 else if (consumeIf("eO")) OperatorName = "^=";
4393 else if (consumeIf("eq")) OperatorName = "==";
4394 else if (consumeIf("ge")) OperatorName = ">=";
4395 else if (consumeIf("gt")) OperatorName = ">";
4396 else if (consumeIf("le")) OperatorName = "<=";
4397 else if (consumeIf("ls")) OperatorName = "<<";
4398 else if (consumeIf("lS")) OperatorName = "<<=";
4399 else if (consumeIf("lt")) OperatorName = "<";
4400 else if (consumeIf("mi")) OperatorName = "-";
4401 else if (consumeIf("mI")) OperatorName = "-=";
4402 else if (consumeIf("ml")) OperatorName = "*";
4403 else if (consumeIf("mL")) OperatorName = "*=";
4404 else if (consumeIf("ne")) OperatorName = "!=";
4405 else if (consumeIf("oo")) OperatorName = "||";
4406 else if (consumeIf("or")) OperatorName = "|";
4407 else if (consumeIf("oR")) OperatorName = "|=";
4408 else if (consumeIf("pl")) OperatorName = "+";
4409 else if (consumeIf("pL")) OperatorName = "+=";
4410 else if (consumeIf("rm")) OperatorName = "%";
4411 else if (consumeIf("rM")) OperatorName = "%=";
4412 else if (consumeIf("rs")) OperatorName = ">>";
4413 else if (consumeIf("rS")) OperatorName = ">>=";
4414 else return nullptr;
4415
4416 Node *Pack = getDerived().parseExpr(), *Init = nullptr;
4417 if (Pack == nullptr)
4418 return nullptr;
4419 if (HasInitializer) {
4420 Init = getDerived().parseExpr();
4421 if (Init == nullptr)
4422 return nullptr;
4423 }
4424
4425 if (IsLeftFold && Init)
4426 std::swap(Pack, Init);
4427
4428 return make<FoldExpr>(IsLeftFold, OperatorName, Pack, Init);
4429}
4430
4431// <expression> ::= <unary operator-name> <expression>
4432// ::= <binary operator-name> <expression> <expression>
4433// ::= <ternary operator-name> <expression> <expression> <expression>
4434// ::= cl <expression>+ E # call
4435// ::= cv <type> <expression> # conversion with one argument
4436// ::= cv <type> _ <expression>* E # conversion with a different number of arguments
4437// ::= [gs] nw <expression>* _ <type> E # new (expr-list) type
4438// ::= [gs] nw <expression>* _ <type> <initializer> # new (expr-list) type (init)
4439// ::= [gs] na <expression>* _ <type> E # new[] (expr-list) type
4440// ::= [gs] na <expression>* _ <type> <initializer> # new[] (expr-list) type (init)
4441// ::= [gs] dl <expression> # delete expression
4442// ::= [gs] da <expression> # delete[] expression
4443// ::= pp_ <expression> # prefix ++
4444// ::= mm_ <expression> # prefix --
4445// ::= ti <type> # typeid (type)
4446// ::= te <expression> # typeid (expression)
4447// ::= dc <type> <expression> # dynamic_cast<type> (expression)
4448// ::= sc <type> <expression> # static_cast<type> (expression)
4449// ::= cc <type> <expression> # const_cast<type> (expression)
4450// ::= rc <type> <expression> # reinterpret_cast<type> (expression)
4451// ::= st <type> # sizeof (a type)
4452// ::= sz <expression> # sizeof (an expression)
4453// ::= at <type> # alignof (a type)
4454// ::= az <expression> # alignof (an expression)
4455// ::= nx <expression> # noexcept (expression)
4456// ::= <template-param>
4457// ::= <function-param>
4458// ::= dt <expression> <unresolved-name> # expr.name
4459// ::= pt <expression> <unresolved-name> # expr->name
4460// ::= ds <expression> <expression> # expr.*expr
4461// ::= sZ <template-param> # size of a parameter pack
4462// ::= sZ <function-param> # size of a function parameter pack
4463// ::= sP <template-arg>* E # sizeof...(T), size of a captured template parameter pack from an alias template
4464// ::= sp <expression> # pack expansion
4465// ::= tw <expression> # throw expression
4466// ::= tr # throw with no operand (rethrow)
4467// ::= <unresolved-name> # f(p), N::f(p), ::f(p),
4468// # freestanding dependent name (e.g., T::x),
4469// # objectless nonstatic member reference
4470// ::= fL <binary-operator-name> <expression> <expression>
4471// ::= fR <binary-operator-name> <expression> <expression>
4472// ::= fl <binary-operator-name> <expression>
4473// ::= fr <binary-operator-name> <expression>
4474// ::= <expr-primary>
4475template <typename Derived, typename Alloc>
4476Node *AbstractManglingParser<Derived, Alloc>::parseExpr() {
4477 bool Global = consumeIf("gs");
4478 if (numLeft() < 2)
4479 return nullptr;
4480
4481 switch (*First) {
4482 case 'L':
4483 return getDerived().parseExprPrimary();
4484 case 'T':
4485 return getDerived().parseTemplateParam();
4486 case 'f': {
4487 // Disambiguate a fold expression from a <function-param>.
4488 if (look(1) == 'p' || (look(1) == 'L' && std::isdigit(look(2))))
4489 return getDerived().parseFunctionParam();
4490 return getDerived().parseFoldExpr();
4491 }
4492 case 'a':
4493 switch (First[1]) {
4494 case 'a':
4495 First += 2;
4496 return getDerived().parseBinaryExpr("&&");
4497 case 'd':
4498 First += 2;
4499 return getDerived().parsePrefixExpr("&");
4500 case 'n':
4501 First += 2;
4502 return getDerived().parseBinaryExpr("&");
4503 case 'N':
4504 First += 2;
4505 return getDerived().parseBinaryExpr("&=");
4506 case 'S':
4507 First += 2;
4508 return getDerived().parseBinaryExpr("=");
4509 case 't': {
4510 First += 2;
4511 Node *Ty = getDerived().parseType();
4512 if (Ty == nullptr)
4513 return nullptr;
4514 return make<EnclosingExpr>("alignof (", Ty, ")");
4515 }
4516 case 'z': {
4517 First += 2;
4518 Node *Ty = getDerived().parseExpr();
4519 if (Ty == nullptr)
4520 return nullptr;
4521 return make<EnclosingExpr>("alignof (", Ty, ")");
4522 }
4523 }
4524 return nullptr;
4525 case 'c':
4526 switch (First[1]) {
4527 // cc <type> <expression> # const_cast<type>(expression)
4528 case 'c': {
4529 First += 2;
4530 Node *Ty = getDerived().parseType();
4531 if (Ty == nullptr)
4532 return Ty;
4533 Node *Ex = getDerived().parseExpr();
4534 if (Ex == nullptr)
4535 return Ex;
4536 return make<CastExpr>("const_cast", Ty, Ex);
4537 }
4538 // cl <expression>+ E # call
4539 case 'l': {
4540 First += 2;
4541 Node *Callee = getDerived().parseExpr();
4542 if (Callee == nullptr)
4543 return Callee;
4544 size_t ExprsBegin = Names.size();
4545 while (!consumeIf('E')) {
4546 Node *E = getDerived().parseExpr();
4547 if (E == nullptr)
4548 return E;
4549 Names.push_back(E);
4550 }
4551 return make<CallExpr>(Callee, popTrailingNodeArray(ExprsBegin));
4552 }
4553 case 'm':
4554 First += 2;
4555 return getDerived().parseBinaryExpr(",");
4556 case 'o':
4557 First += 2;
4558 return getDerived().parsePrefixExpr("~");
4559 case 'v':
4560 return getDerived().parseConversionExpr();
4561 }
4562 return nullptr;
4563 case 'd':
4564 switch (First[1]) {
4565 case 'a': {
4566 First += 2;
4567 Node *Ex = getDerived().parseExpr();
4568 if (Ex == nullptr)
4569 return Ex;
4570 return make<DeleteExpr>(Ex, Global, /*is_array=*/true);
4571 }
4572 case 'c': {
4573 First += 2;
4574 Node *T = getDerived().parseType();
4575 if (T == nullptr)
4576 return T;
4577 Node *Ex = getDerived().parseExpr();
4578 if (Ex == nullptr)
4579 return Ex;
4580 return make<CastExpr>("dynamic_cast", T, Ex);
4581 }
4582 case 'e':
4583 First += 2;
4584 return getDerived().parsePrefixExpr("*");
4585 case 'l': {
4586 First += 2;
4587 Node *E = getDerived().parseExpr();
4588 if (E == nullptr)
4589 return E;
4590 return make<DeleteExpr>(E, Global, /*is_array=*/false);
4591 }
4592 case 'n':
4593 return getDerived().parseUnresolvedName();
4594 case 's': {
4595 First += 2;
4596 Node *LHS = getDerived().parseExpr();
4597 if (LHS == nullptr)
4598 return nullptr;
4599 Node *RHS = getDerived().parseExpr();
4600 if (RHS == nullptr)
4601 return nullptr;
4602 return make<MemberExpr>(LHS, ".*", RHS);
4603 }
4604 case 't': {
4605 First += 2;
4606 Node *LHS = getDerived().parseExpr();
4607 if (LHS == nullptr)
4608 return LHS;
4609 Node *RHS = getDerived().parseExpr();
4610 if (RHS == nullptr)
4611 return nullptr;
4612 return make<MemberExpr>(LHS, ".", RHS);
4613 }
4614 case 'v':
4615 First += 2;
4616 return getDerived().parseBinaryExpr("/");
4617 case 'V':
4618 First += 2;
4619 return getDerived().parseBinaryExpr("/=");
4620 }
4621 return nullptr;
4622 case 'e':
4623 switch (First[1]) {
4624 case 'o':
4625 First += 2;
4626 return getDerived().parseBinaryExpr("^");
4627 case 'O':
4628 First += 2;
4629 return getDerived().parseBinaryExpr("^=");
4630 case 'q':
4631 First += 2;
4632 return getDerived().parseBinaryExpr("==");
4633 }
4634 return nullptr;
4635 case 'g':
4636 switch (First[1]) {
4637 case 'e':
4638 First += 2;
4639 return getDerived().parseBinaryExpr(">=");
4640 case 't':
4641 First += 2;
4642 return getDerived().parseBinaryExpr(">");
4643 }
4644 return nullptr;
4645 case 'i':
4646 switch (First[1]) {
4647 case 'x': {
4648 First += 2;
4649 Node *Base = getDerived().parseExpr();
4650 if (Base == nullptr)
4651 return nullptr;
4652 Node *Index = getDerived().parseExpr();
4653 if (Index == nullptr)
4654 return Index;
4655 return make<ArraySubscriptExpr>(Base, Index);
4656 }
4657 case 'l': {
4658 First += 2;
4659 size_t InitsBegin = Names.size();
4660 while (!consumeIf('E')) {
4661 Node *E = getDerived().parseBracedExpr();
4662 if (E == nullptr)
4663 return nullptr;
4664 Names.push_back(E);
4665 }
4666 return make<InitListExpr>(nullptr, popTrailingNodeArray(InitsBegin));
4667 }
4668 }
4669 return nullptr;
4670 case 'l':
4671 switch (First[1]) {
4672 case 'e':
4673 First += 2;
4674 return getDerived().parseBinaryExpr("<=");
4675 case 's':
4676 First += 2;
4677 return getDerived().parseBinaryExpr("<<");
4678 case 'S':
4679 First += 2;
4680 return getDerived().parseBinaryExpr("<<=");
4681 case 't':
4682 First += 2;
4683 return getDerived().parseBinaryExpr("<");
4684 }
4685 return nullptr;
4686 case 'm':
4687 switch (First[1]) {
4688 case 'i':
4689 First += 2;
4690 return getDerived().parseBinaryExpr("-");
4691 case 'I':
4692 First += 2;
4693 return getDerived().parseBinaryExpr("-=");
4694 case 'l':
4695 First += 2;
4696 return getDerived().parseBinaryExpr("*");
4697 case 'L':
4698 First += 2;
4699 return getDerived().parseBinaryExpr("*=");
4700 case 'm':
4701 First += 2;
4702 if (consumeIf('_'))
4703 return getDerived().parsePrefixExpr("--");
4704 Node *Ex = getDerived().parseExpr();
4705 if (Ex == nullptr)
4706 return nullptr;
4707 return make<PostfixExpr>(Ex, "--");
4708 }
4709 return nullptr;
4710 case 'n':
4711 switch (First[1]) {
4712 case 'a':
4713 case 'w':
4714 return getDerived().parseNewExpr();
4715 case 'e':
4716 First += 2;
4717 return getDerived().parseBinaryExpr("!=");
4718 case 'g':
4719 First += 2;
4720 return getDerived().parsePrefixExpr("-");
4721 case 't':
4722 First += 2;
4723 return getDerived().parsePrefixExpr("!");
4724 case 'x':
4725 First += 2;
4726 Node *Ex = getDerived().parseExpr();
4727 if (Ex == nullptr)
4728 return Ex;
4729 return make<EnclosingExpr>("noexcept (", Ex, ")");
4730 }
4731 return nullptr;
4732 case 'o':
4733 switch (First[1]) {
4734 case 'n':
4735 return getDerived().parseUnresolvedName();
4736 case 'o':
4737 First += 2;
4738 return getDerived().parseBinaryExpr("||");
4739 case 'r':
4740 First += 2;
4741 return getDerived().parseBinaryExpr("|");
4742 case 'R':
4743 First += 2;
4744 return getDerived().parseBinaryExpr("|=");
4745 }
4746 return nullptr;
4747 case 'p':
4748 switch (First[1]) {
4749 case 'm':
4750 First += 2;
4751 return getDerived().parseBinaryExpr("->*");
4752 case 'l':
4753 First += 2;
4754 return getDerived().parseBinaryExpr("+");
4755 case 'L':
4756 First += 2;
4757 return getDerived().parseBinaryExpr("+=");
4758 case 'p': {
4759 First += 2;
4760 if (consumeIf('_'))
4761 return getDerived().parsePrefixExpr("++");
4762 Node *Ex = getDerived().parseExpr();
4763 if (Ex == nullptr)
4764 return Ex;
4765 return make<PostfixExpr>(Ex, "++");
4766 }
4767 case 's':
4768 First += 2;
4769 return getDerived().parsePrefixExpr("+");
4770 case 't': {
4771 First += 2;
4772 Node *L = getDerived().parseExpr();
4773 if (L == nullptr)
4774 return nullptr;
4775 Node *R = getDerived().parseExpr();
4776 if (R == nullptr)
4777 return nullptr;
4778 return make<MemberExpr>(L, "->", R);
4779 }
4780 }
4781 return nullptr;
4782 case 'q':
4783 if (First[1] == 'u') {
4784 First += 2;
4785 Node *Cond = getDerived().parseExpr();
4786 if (Cond == nullptr)
4787 return nullptr;
4788 Node *LHS = getDerived().parseExpr();
4789 if (LHS == nullptr)
4790 return nullptr;
4791 Node *RHS = getDerived().parseExpr();
4792 if (RHS == nullptr)
4793 return nullptr;
4794 return make<ConditionalExpr>(Cond, LHS, RHS);
4795 }
4796 return nullptr;
4797 case 'r':
4798 switch (First[1]) {
4799 case 'c': {
4800 First += 2;
4801 Node *T = getDerived().parseType();
4802 if (T == nullptr)
4803 return T;
4804 Node *Ex = getDerived().parseExpr();
4805 if (Ex == nullptr)
4806 return Ex;
4807 return make<CastExpr>("reinterpret_cast", T, Ex);
4808 }
4809 case 'm':
4810 First += 2;
4811 return getDerived().parseBinaryExpr("%");
4812 case 'M':
4813 First += 2;
4814 return getDerived().parseBinaryExpr("%=");
4815 case 's':
4816 First += 2;
4817 return getDerived().parseBinaryExpr(">>");
4818 case 'S':
4819 First += 2;
4820 return getDerived().parseBinaryExpr(">>=");
4821 }
4822 return nullptr;
4823 case 's':
4824 switch (First[1]) {
4825 case 'c': {
4826 First += 2;
4827 Node *T = getDerived().parseType();
4828 if (T == nullptr)
4829 return T;
4830 Node *Ex = getDerived().parseExpr();
4831 if (Ex == nullptr)
4832 return Ex;
4833 return make<CastExpr>("static_cast", T, Ex);
4834 }
4835 case 'p': {
4836 First += 2;
4837 Node *Child = getDerived().parseExpr();
4838 if (Child == nullptr)
4839 return nullptr;
4840 return make<ParameterPackExpansion>(Child);
4841 }
4842 case 'r':
4843 return getDerived().parseUnresolvedName();
4844 case 't': {
4845 First += 2;
4846 Node *Ty = getDerived().parseType();
4847 if (Ty == nullptr)
4848 return Ty;
4849 return make<EnclosingExpr>("sizeof (", Ty, ")");
4850 }
4851 case 'z': {
4852 First += 2;
4853 Node *Ex = getDerived().parseExpr();
4854 if (Ex == nullptr)
4855 return Ex;
4856 return make<EnclosingExpr>("sizeof (", Ex, ")");
4857 }
4858 case 'Z':
4859 First += 2;
4860 if (look() == 'T') {
4861 Node *R = getDerived().parseTemplateParam();
4862 if (R == nullptr)
4863 return nullptr;
4864 return make<SizeofParamPackExpr>(R);
4865 } else if (look() == 'f') {
4866 Node *FP = getDerived().parseFunctionParam();
4867 if (FP == nullptr)
4868 return nullptr;
4869 return make<EnclosingExpr>("sizeof... (", FP, ")");
4870 }
4871 return nullptr;
4872 case 'P': {
4873 First += 2;
4874 size_t ArgsBegin = Names.size();
4875 while (!consumeIf('E')) {
4876 Node *Arg = getDerived().parseTemplateArg();
4877 if (Arg == nullptr)
4878 return nullptr;
4879 Names.push_back(Arg);
4880 }
4881 auto *Pack = make<NodeArrayNode>(popTrailingNodeArray(ArgsBegin));
4882 if (!Pack)
4883 return nullptr;
4884 return make<EnclosingExpr>("sizeof... (", Pack, ")");
4885 }
4886 }
4887 return nullptr;
4888 case 't':
4889 switch (First[1]) {
4890 case 'e': {
4891 First += 2;
4892 Node *Ex = getDerived().parseExpr();
4893 if (Ex == nullptr)
4894 return Ex;
4895 return make<EnclosingExpr>("typeid (", Ex, ")");
4896 }
4897 case 'i': {
4898 First += 2;
4899 Node *Ty = getDerived().parseType();
4900 if (Ty == nullptr)
4901 return Ty;
4902 return make<EnclosingExpr>("typeid (", Ty, ")");
4903 }
4904 case 'l': {
4905 First += 2;
4906 Node *Ty = getDerived().parseType();
4907 if (Ty == nullptr)
4908 return nullptr;
4909 size_t InitsBegin = Names.size();
4910 while (!consumeIf('E')) {
4911 Node *E = getDerived().parseBracedExpr();
4912 if (E == nullptr)
4913 return nullptr;
4914 Names.push_back(E);
4915 }
4916 return make<InitListExpr>(Ty, popTrailingNodeArray(InitsBegin));
4917 }
4918 case 'r':
4919 First += 2;
4920 return make<NameType>("throw");
4921 case 'w': {
4922 First += 2;
4923 Node *Ex = getDerived().parseExpr();
4924 if (Ex == nullptr)
4925 return nullptr;
4926 return make<ThrowExpr>(Ex);
4927 }
4928 }
4929 return nullptr;
4930 case '1':
4931 case '2':
4932 case '3':
4933 case '4':
4934 case '5':
4935 case '6':
4936 case '7':
4937 case '8':
4938 case '9':
4939 return getDerived().parseUnresolvedName();
4940 }
4941
4942 if (consumeIf("u8__uuidoft")) {
4943 Node *Ty = getDerived().parseType();
4944 if (!Ty)
4945 return nullptr;
4946 return make<UUIDOfExpr>(Ty);
4947 }
4948
4949 if (consumeIf("u8__uuidofz")) {
4950 Node *Ex = getDerived().parseExpr();
4951 if (!Ex)
4952 return nullptr;
4953 return make<UUIDOfExpr>(Ex);
4954 }
4955
4956 return nullptr;
4957}
4958
4959// <call-offset> ::= h <nv-offset> _
4960// ::= v <v-offset> _
4961//
4962// <nv-offset> ::= <offset number>
4963// # non-virtual base override
4964//
4965// <v-offset> ::= <offset number> _ <virtual offset number>
4966// # virtual base override, with vcall offset
4967template <typename Alloc, typename Derived>
4968bool AbstractManglingParser<Alloc, Derived>::parseCallOffset() {
4969 // Just scan through the call offset, we never add this information into the
4970 // output.
4971 if (consumeIf('h'))
4972 return parseNumber(true).empty() || !consumeIf('_');
4973 if (consumeIf('v'))
4974 return parseNumber(true).empty() || !consumeIf('_') ||
4975 parseNumber(true).empty() || !consumeIf('_');
4976 return true;
4977}
4978
4979// <special-name> ::= TV <type> # virtual table
4980// ::= TT <type> # VTT structure (construction vtable index)
4981// ::= TI <type> # typeinfo structure
4982// ::= TS <type> # typeinfo name (null-terminated byte string)
4983// ::= Tc <call-offset> <call-offset> <base encoding>
4984// # base is the nominal target function of thunk
4985// # first call-offset is 'this' adjustment
4986// # second call-offset is result adjustment
4987// ::= T <call-offset> <base encoding>
4988// # base is the nominal target function of thunk
4989// ::= GV <object name> # Guard variable for one-time initialization
4990// # No <type>
4991// ::= TW <object name> # Thread-local wrapper
4992// ::= TH <object name> # Thread-local initialization
4993// ::= GR <object name> _ # First temporary
4994// ::= GR <object name> <seq-id> _ # Subsequent temporaries
4995// extension ::= TC <first type> <number> _ <second type> # construction vtable for second-in-first
4996// extension ::= GR <object name> # reference temporary for object
4997template <typename Derived, typename Alloc>
4998Node *AbstractManglingParser<Derived, Alloc>::parseSpecialName() {
4999 switch (look()) {
5000 case 'T':
5001 switch (look(1)) {
5002 // TV <type> # virtual table
5003 case 'V': {
5004 First += 2;
5005 Node *Ty = getDerived().parseType();
5006 if (Ty == nullptr)
5007 return nullptr;
5008 return make<SpecialName>("vtable for ", Ty);
5009 }
5010 // TT <type> # VTT structure (construction vtable index)
5011 case 'T': {
5012 First += 2;
5013 Node *Ty = getDerived().parseType();
5014 if (Ty == nullptr)
5015 return nullptr;
5016 return make<SpecialName>("VTT for ", Ty);
5017 }
5018 // TI <type> # typeinfo structure
5019 case 'I': {
5020 First += 2;
5021 Node *Ty = getDerived().parseType();
5022 if (Ty == nullptr)
5023 return nullptr;
5024 return make<SpecialName>("typeinfo for ", Ty);
5025 }
5026 // TS <type> # typeinfo name (null-terminated byte string)
5027 case 'S': {
5028 First += 2;
5029 Node *Ty = getDerived().parseType();
5030 if (Ty == nullptr)
5031 return nullptr;
5032 return make<SpecialName>("typeinfo name for ", Ty);
5033 }
5034 // Tc <call-offset> <call-offset> <base encoding>
5035 case 'c': {
5036 First += 2;
5037 if (parseCallOffset() || parseCallOffset())
5038 return nullptr;
5039 Node *Encoding = getDerived().parseEncoding();
5040 if (Encoding == nullptr)
5041 return nullptr;
5042 return make<SpecialName>("covariant return thunk to ", Encoding);
5043 }
5044 // extension ::= TC <first type> <number> _ <second type>
5045 // # construction vtable for second-in-first
5046 case 'C': {
5047 First += 2;
5048 Node *FirstType = getDerived().parseType();
5049 if (FirstType == nullptr)
5050 return nullptr;
5051 if (parseNumber(true).empty() || !consumeIf('_'))
5052 return nullptr;
5053 Node *SecondType = getDerived().parseType();
5054 if (SecondType == nullptr)
5055 return nullptr;
5056 return make<CtorVtableSpecialName>(SecondType, FirstType);
5057 }
5058 // TW <object name> # Thread-local wrapper
5059 case 'W': {
5060 First += 2;
5061 Node *Name = getDerived().parseName();
5062 if (Name == nullptr)
5063 return nullptr;
5064 return make<SpecialName>("thread-local wrapper routine for ", Name);
5065 }
5066 // TH <object name> # Thread-local initialization
5067 case 'H': {
5068 First += 2;
5069 Node *Name = getDerived().parseName();
5070 if (Name == nullptr)
5071 return nullptr;
5072 return make<SpecialName>("thread-local initialization routine for ", Name);
5073 }
5074 // T <call-offset> <base encoding>
5075 default: {
5076 ++First;
5077 bool IsVirt = look() == 'v';
5078 if (parseCallOffset())
5079 return nullptr;
5080 Node *BaseEncoding = getDerived().parseEncoding();
5081 if (BaseEncoding == nullptr)
5082 return nullptr;
5083 if (IsVirt)
5084 return make<SpecialName>("virtual thunk to ", BaseEncoding);
5085 else
5086 return make<SpecialName>("non-virtual thunk to ", BaseEncoding);
5087 }
5088 }
5089 case 'G':
5090 switch (look(1)) {
5091 // GV <object name> # Guard variable for one-time initialization
5092 case 'V': {
5093 First += 2;
5094 Node *Name = getDerived().parseName();
5095 if (Name == nullptr)
5096 return nullptr;
5097 return make<SpecialName>("guard variable for ", Name);
5098 }
5099 // GR <object name> # reference temporary for object
5100 // GR <object name> _ # First temporary
5101 // GR <object name> <seq-id> _ # Subsequent temporaries
5102 case 'R': {
5103 First += 2;
5104 Node *Name = getDerived().parseName();
5105 if (Name == nullptr)
5106 return nullptr;
5107 size_t Count;
5108 bool ParsedSeqId = !parseSeqId(&Count);
5109 if (!consumeIf('_') && ParsedSeqId)
5110 return nullptr;
5111 return make<SpecialName>("reference temporary for ", Name);
5112 }
5113 }
5114 }
5115 return nullptr;
5116}
5117
5118// <encoding> ::= <function name> <bare-function-type>
5119// ::= <data name>
5120// ::= <special-name>
5121template <typename Derived, typename Alloc>
5122Node *AbstractManglingParser<Derived, Alloc>::parseEncoding() {
5123 if (look() == 'G' || look() == 'T')
5124 return getDerived().parseSpecialName();
5125
5126 auto IsEndOfEncoding = [&] {
5127 // The set of chars that can potentially follow an <encoding> (none of which
5128 // can start a <type>). Enumerating these allows us to avoid speculative
5129 // parsing.
5130 return numLeft() == 0 || look() == 'E' || look() == '.' || look() == '_';
5131 };
5132
5133 NameState NameInfo(this);
5134 Node *Name = getDerived().parseName(&NameInfo);
5135 if (Name == nullptr)
5136 return nullptr;
5137
5138 if (resolveForwardTemplateRefs(NameInfo))
5139 return nullptr;
5140
5141 if (IsEndOfEncoding())
5142 return Name;
5143
5144 Node *Attrs = nullptr;
5145 if (consumeIf("Ua9enable_ifI")) {
5146 size_t BeforeArgs = Names.size();
5147 while (!consumeIf('E')) {
5148 Node *Arg = getDerived().parseTemplateArg();
5149 if (Arg == nullptr)
5150 return nullptr;
5151 Names.push_back(Arg);
5152 }
5153 Attrs = make<EnableIfAttr>(popTrailingNodeArray(BeforeArgs));
5154 if (!Attrs)
5155 return nullptr;
5156 }
5157
5158 Node *ReturnType = nullptr;
5159 if (!NameInfo.CtorDtorConversion && NameInfo.EndsWithTemplateArgs) {
5160 ReturnType = getDerived().parseType();
5161 if (ReturnType == nullptr)
5162 return nullptr;
5163 }
5164
5165 if (consumeIf('v'))
5166 return make<FunctionEncoding>(ReturnType, Name, NodeArray(),
5167 Attrs, NameInfo.CVQualifiers,
5168 NameInfo.ReferenceQualifier);
5169
5170 size_t ParamsBegin = Names.size();
5171 do {
5172 Node *Ty = getDerived().parseType();
5173 if (Ty == nullptr)
5174 return nullptr;
5175 Names.push_back(Ty);
5176 } while (!IsEndOfEncoding());
5177
5178 return make<FunctionEncoding>(ReturnType, Name,
5179 popTrailingNodeArray(ParamsBegin),
5180 Attrs, NameInfo.CVQualifiers,
5181 NameInfo.ReferenceQualifier);
5182}
5183
5184template <class Float>
5185struct FloatData;
5186
5187template <>
5188struct FloatData<float>
5189{
5190 static const size_t mangled_size = 8;
5191 static const size_t max_demangled_size = 24;
5192 static constexpr const char* spec = "%af";
5193};
5194
5195template <>
5196struct FloatData<double>
5197{
5198 static const size_t mangled_size = 16;
5199 static const size_t max_demangled_size = 32;
5200 static constexpr const char* spec = "%a";
5201};
5202
5203template <>
5204struct FloatData<long double>
5205{
5206#if defined(__mips__) && defined(__mips_n64) || defined(__aarch64__) || \
5207 defined(__wasm__)
5208 static const size_t mangled_size = 32;
5209#elif defined(__arm__) || defined(__mips__) || defined(__hexagon__)
5210 static const size_t mangled_size = 16;
5211#else
5212 static const size_t mangled_size = 20; // May need to be adjusted to 16 or 24 on other platforms
5213#endif
5214 static const size_t max_demangled_size = 40;
5215 static constexpr const char *spec = "%LaL";
5216};
5217
5218template <typename Alloc, typename Derived>
5219template <class Float>
5220Node *AbstractManglingParser<Alloc, Derived>::parseFloatingLiteral() {
5221 const size_t N = FloatData<Float>::mangled_size;
5222 if (numLeft() <= N)
5223 return nullptr;
5224 StringView Data(First, First + N);
5225 for (char C : Data)
5226 if (!std::isxdigit(C))
5227 return nullptr;
5228 First += N;
5229 if (!consumeIf('E'))
5230 return nullptr;
5231 return make<FloatLiteralImpl<Float>>(Data);
5232}
5233
5234// <seq-id> ::= <0-9A-Z>+
5235template <typename Alloc, typename Derived>
5236bool AbstractManglingParser<Alloc, Derived>::parseSeqId(size_t *Out) {
5237 if (!(look() >= '0' && look() <= '9') &&
5238 !(look() >= 'A' && look() <= 'Z'))
5239 return true;
5240
5241 size_t Id = 0;
5242 while (true) {
5243 if (look() >= '0' && look() <= '9') {
5244 Id *= 36;
5245 Id += static_cast<size_t>(look() - '0');
5246 } else if (look() >= 'A' && look() <= 'Z') {
5247 Id *= 36;
5248 Id += static_cast<size_t>(look() - 'A') + 10;
5249 } else {
5250 *Out = Id;
5251 return false;
5252 }
5253 ++First;
5254 }
5255}
5256
5257// <substitution> ::= S <seq-id> _
5258// ::= S_
5259// <substitution> ::= Sa # ::std::allocator
5260// <substitution> ::= Sb # ::std::basic_string
5261// <substitution> ::= Ss # ::std::basic_string < char,
5262// ::std::char_traits<char>,
5263// ::std::allocator<char> >
5264// <substitution> ::= Si # ::std::basic_istream<char, std::char_traits<char> >
5265// <substitution> ::= So # ::std::basic_ostream<char, std::char_traits<char> >
5266// <substitution> ::= Sd # ::std::basic_iostream<char, std::char_traits<char> >
5267template <typename Derived, typename Alloc>
5268Node *AbstractManglingParser<Derived, Alloc>::parseSubstitution() {
5269 if (!consumeIf('S'))
5270 return nullptr;
5271
5272 if (std::islower(look())) {
5273 Node *SpecialSub;
5274 switch (look()) {
5275 case 'a':
5276 ++First;
5277 SpecialSub = make<SpecialSubstitution>(SpecialSubKind::allocator);
5278 break;
5279 case 'b':
5280 ++First;
5281 SpecialSub = make<SpecialSubstitution>(SpecialSubKind::basic_string);
5282 break;
5283 case 's':
5284 ++First;
5285 SpecialSub = make<SpecialSubstitution>(SpecialSubKind::string);
5286 break;
5287 case 'i':
5288 ++First;
5289 SpecialSub = make<SpecialSubstitution>(SpecialSubKind::istream);
5290 break;
5291 case 'o':
5292 ++First;
5293 SpecialSub = make<SpecialSubstitution>(SpecialSubKind::ostream);
5294 break;
5295 case 'd':
5296 ++First;
5297 SpecialSub = make<SpecialSubstitution>(SpecialSubKind::iostream);
5298 break;
5299 default:
5300 return nullptr;
5301 }
5302 if (!SpecialSub)
5303 return nullptr;
5304 // Itanium C++ ABI 5.1.2: If a name that would use a built-in <substitution>
5305 // has ABI tags, the tags are appended to the substitution; the result is a
5306 // substitutable component.
5307 Node *WithTags = getDerived().parseAbiTags(SpecialSub);
5308 if (WithTags != SpecialSub) {
5309 Subs.push_back(WithTags);
5310 SpecialSub = WithTags;
5311 }
5312 return SpecialSub;
5313 }
5314
5315 // ::= S_
5316 if (consumeIf('_')) {
5317 if (Subs.empty())
5318 return nullptr;
5319 return Subs[0];
5320 }
5321
5322 // ::= S <seq-id> _
5323 size_t Index = 0;
5324 if (parseSeqId(&Index))
5325 return nullptr;
5326 ++Index;
5327 if (!consumeIf('_') || Index >= Subs.size())
5328 return nullptr;
5329 return Subs[Index];
5330}
5331
5332// <template-param> ::= T_ # first template parameter
5333// ::= T <parameter-2 non-negative number> _
5334// ::= TL <level-1> __
5335// ::= TL <level-1> _ <parameter-2 non-negative number> _
5336template <typename Derived, typename Alloc>
5337Node *AbstractManglingParser<Derived, Alloc>::parseTemplateParam() {
5338 if (!consumeIf('T'))
5339 return nullptr;
5340
5341 size_t Level = 0;
5342 if (consumeIf('L')) {
5343 if (parsePositiveInteger(&Level))
5344 return nullptr;
5345 ++Level;
5346 if (!consumeIf('_'))
5347 return nullptr;
5348 }
5349
5350 size_t Index = 0;
5351 if (!consumeIf('_')) {
5352 if (parsePositiveInteger(&Index))
5353 return nullptr;
5354 ++Index;
5355 if (!consumeIf('_'))
5356 return nullptr;
5357 }
5358
5359 // If we're in a context where this <template-param> refers to a
5360 // <template-arg> further ahead in the mangled name (currently just conversion
5361 // operator types), then we should only look it up in the right context.
5362 // This can only happen at the outermost level.
5363 if (PermitForwardTemplateReferences && Level == 0) {
5364 Node *ForwardRef = make<ForwardTemplateReference>(Index);
5365 if (!ForwardRef)
5366 return nullptr;
5367 assert(ForwardRef->getKind() == Node::KForwardTemplateReference);
5368 ForwardTemplateRefs.push_back(
5369 static_cast<ForwardTemplateReference *>(ForwardRef));
5370 return ForwardRef;
5371 }
5372
5373 if (Level >= TemplateParams.size() || !TemplateParams[Level] ||
5374 Index >= TemplateParams[Level]->size()) {
5375 // Itanium ABI 5.1.8: In a generic lambda, uses of auto in the parameter
5376 // list are mangled as the corresponding artificial template type parameter.
5377 if (ParsingLambdaParamsAtLevel == Level && Level <= TemplateParams.size()) {
5378 // This will be popped by the ScopedTemplateParamList in
5379 // parseUnnamedTypeName.
5380 if (Level == TemplateParams.size())
5381 TemplateParams.push_back(nullptr);
5382 return make<NameType>("auto");
5383 }
5384
5385 return nullptr;
5386 }
5387
5388 return (*TemplateParams[Level])[Index];
5389}
5390
5391// <template-param-decl> ::= Ty # type parameter
5392// ::= Tn <type> # non-type parameter
5393// ::= Tt <template-param-decl>* E # template parameter
5394// ::= Tp <template-param-decl> # parameter pack
5395template <typename Derived, typename Alloc>
5396Node *AbstractManglingParser<Derived, Alloc>::parseTemplateParamDecl() {
5397 auto InventTemplateParamName = [&](TemplateParamKind Kind) {
5398 unsigned Index = NumSyntheticTemplateParameters[(int)Kind]++;
5399 Node *N = make<SyntheticTemplateParamName>(Kind, Index);
5400 if (N) TemplateParams.back()->push_back(N);
5401 return N;
5402 };
5403
5404 if (consumeIf("Ty")) {
5405 Node *Name = InventTemplateParamName(TemplateParamKind::Type);
5406 if (!Name)
5407 return nullptr;
5408 return make<TypeTemplateParamDecl>(Name);
5409 }
5410
5411 if (consumeIf("Tn")) {
5412 Node *Name = InventTemplateParamName(TemplateParamKind::NonType);
5413 if (!Name)
5414 return nullptr;
5415 Node *Type = parseType();
5416 if (!Type)
5417 return nullptr;
5418 return make<NonTypeTemplateParamDecl>(Name, Type);
5419 }
5420
5421 if (consumeIf("Tt")) {
5422 Node *Name = InventTemplateParamName(TemplateParamKind::Template);
5423 if (!Name)
5424 return nullptr;
5425 size_t ParamsBegin = Names.size();
5426 ScopedTemplateParamList TemplateTemplateParamParams(this);
5427 while (!consumeIf("E")) {
5428 Node *P = parseTemplateParamDecl();
5429 if (!P)
5430 return nullptr;
5431 Names.push_back(P);
5432 }
5433 NodeArray Params = popTrailingNodeArray(ParamsBegin);
5434 return make<TemplateTemplateParamDecl>(Name, Params);
5435 }
5436
5437 if (consumeIf("Tp")) {
5438 Node *P = parseTemplateParamDecl();
5439 if (!P)
5440 return nullptr;
5441 return make<TemplateParamPackDecl>(P);
5442 }
5443
5444 return nullptr;
5445}
5446
5447// <template-arg> ::= <type> # type or template
5448// ::= X <expression> E # expression
5449// ::= <expr-primary> # simple expressions
5450// ::= J <template-arg>* E # argument pack
5451// ::= LZ <encoding> E # extension
5452template <typename Derived, typename Alloc>
5453Node *AbstractManglingParser<Derived, Alloc>::parseTemplateArg() {
5454 switch (look()) {
5455 case 'X': {
5456 ++First;
5457 Node *Arg = getDerived().parseExpr();
5458 if (Arg == nullptr || !consumeIf('E'))
5459 return nullptr;
5460 return Arg;
5461 }
5462 case 'J': {
5463 ++First;
5464 size_t ArgsBegin = Names.size();
5465 while (!consumeIf('E')) {
5466 Node *Arg = getDerived().parseTemplateArg();
5467 if (Arg == nullptr)
5468 return nullptr;
5469 Names.push_back(Arg);
5470 }
5471 NodeArray Args = popTrailingNodeArray(ArgsBegin);
5472 return make<TemplateArgumentPack>(Args);
5473 }
5474 case 'L': {
5475 // ::= LZ <encoding> E # extension
5476 if (look(1) == 'Z') {
5477 First += 2;
5478 Node *Arg = getDerived().parseEncoding();
5479 if (Arg == nullptr || !consumeIf('E'))
5480 return nullptr;
5481 return Arg;
5482 }
5483 // ::= <expr-primary> # simple expressions
5484 return getDerived().parseExprPrimary();
5485 }
5486 default:
5487 return getDerived().parseType();
5488 }
5489}
5490
5491// <template-args> ::= I <template-arg>* E
5492// extension, the abi says <template-arg>+
5493template <typename Derived, typename Alloc>
5494Node *
5495AbstractManglingParser<Derived, Alloc>::parseTemplateArgs(bool TagTemplates) {
5496 if (!consumeIf('I'))
5497 return nullptr;
5498
5499 // <template-params> refer to the innermost <template-args>. Clear out any
5500 // outer args that we may have inserted into TemplateParams.
5501 if (TagTemplates) {
5502 TemplateParams.clear();
5503 TemplateParams.push_back(&OuterTemplateParams);
5504 OuterTemplateParams.clear();
5505 }
5506
5507 size_t ArgsBegin = Names.size();
5508 while (!consumeIf('E')) {
5509 if (TagTemplates) {
5510 auto OldParams = std::move(TemplateParams);
5511 Node *Arg = getDerived().parseTemplateArg();
5512 TemplateParams = std::move(OldParams);
5513 if (Arg == nullptr)
5514 return nullptr;
5515 Names.push_back(Arg);
5516 Node *TableEntry = Arg;
5517 if (Arg->getKind() == Node::KTemplateArgumentPack) {
5518 TableEntry = make<ParameterPack>(
5519 static_cast<TemplateArgumentPack*>(TableEntry)->getElements());
5520 if (!TableEntry)
5521 return nullptr;
5522 }
5523 TemplateParams.back()->push_back(TableEntry);
5524 } else {
5525 Node *Arg = getDerived().parseTemplateArg();
5526 if (Arg == nullptr)
5527 return nullptr;
5528 Names.push_back(Arg);
5529 }
5530 }
5531 return make<TemplateArgs>(popTrailingNodeArray(ArgsBegin));
5532}
5533
5534// <mangled-name> ::= _Z <encoding>
5535// ::= <type>
5536// extension ::= ___Z <encoding> _block_invoke
5537// extension ::= ___Z <encoding> _block_invoke<decimal-digit>+
5538// extension ::= ___Z <encoding> _block_invoke_<decimal-digit>+
5539template <typename Derived, typename Alloc>
5540Node *AbstractManglingParser<Derived, Alloc>::parse() {
5541 if (consumeIf("_Z") || consumeIf("__Z")) {
5542 Node *Encoding = getDerived().parseEncoding();
5543 if (Encoding == nullptr)
5544 return nullptr;
5545 if (look() == '.') {
5546 Encoding = make<DotSuffix>(Encoding, StringView(First, Last));
5547 First = Last;
5548 }
5549 if (numLeft() != 0)
5550 return nullptr;
5551 return Encoding;
5552 }
5553
5554 if (consumeIf("___Z") || consumeIf("____Z")) {
5555 Node *Encoding = getDerived().parseEncoding();
5556 if (Encoding == nullptr || !consumeIf("_block_invoke"))
5557 return nullptr;
5558 bool RequireNumber = consumeIf('_');
5559 if (parseNumber().empty() && RequireNumber)
5560 return nullptr;
5561 if (look() == '.')
5562 First = Last;
5563 if (numLeft() != 0)
5564 return nullptr;
5565 return make<SpecialName>("invocation function for block in ", Encoding);
5566 }
5567
5568 Node *Ty = getDerived().parseType();
5569 if (numLeft() != 0)
5570 return nullptr;
5571 return Ty;
5572}
5573
5574template <typename Alloc>
5575struct ManglingParser : AbstractManglingParser<ManglingParser<Alloc>, Alloc> {
5576 using AbstractManglingParser<ManglingParser<Alloc>,
5577 Alloc>::AbstractManglingParser;
5578};
5579
5580DEMANGLE_NAMESPACE_END
5581
5582#endif // DEMANGLE_ITANIUMDEMANGLE_H
diff --git a/externals/demangle/LICENSE.TXT b/externals/demangle/LICENSE.TXT
new file mode 100644
index 000000000..fa6ac5400
--- /dev/null
+++ b/externals/demangle/LICENSE.TXT
@@ -0,0 +1,279 @@
1==============================================================================
2The LLVM Project is under the Apache License v2.0 with LLVM Exceptions:
3==============================================================================
4
5 Apache License
6 Version 2.0, January 2004
7 http://www.apache.org/licenses/
8
9 TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
10
11 1. Definitions.
12
13 "License" shall mean the terms and conditions for use, reproduction,
14 and distribution as defined by Sections 1 through 9 of this document.
15
16 "Licensor" shall mean the copyright owner or entity authorized by
17 the copyright owner that is granting the License.
18
19 "Legal Entity" shall mean the union of the acting entity and all
20 other entities that control, are controlled by, or are under common
21 control with that entity. For the purposes of this definition,
22 "control" means (i) the power, direct or indirect, to cause the
23 direction or management of such entity, whether by contract or
24 otherwise, or (ii) ownership of fifty percent (50%) or more of the
25 outstanding shares, or (iii) beneficial ownership of such entity.
26
27 "You" (or "Your") shall mean an individual or Legal Entity
28 exercising permissions granted by this License.
29
30 "Source" form shall mean the preferred form for making modifications,
31 including but not limited to software source code, documentation
32 source, and configuration files.
33
34 "Object" form shall mean any form resulting from mechanical
35 transformation or translation of a Source form, including but
36 not limited to compiled object code, generated documentation,
37 and conversions to other media types.
38
39 "Work" shall mean the work of authorship, whether in Source or
40 Object form, made available under the License, as indicated by a
41 copyright notice that is included in or attached to the work
42 (an example is provided in the Appendix below).
43
44 "Derivative Works" shall mean any work, whether in Source or Object
45 form, that is based on (or derived from) the Work and for which the
46 editorial revisions, annotations, elaborations, or other modifications
47 represent, as a whole, an original work of authorship. For the purposes
48 of this License, Derivative Works shall not include works that remain
49 separable from, or merely link (or bind by name) to the interfaces of,
50 the Work and Derivative Works thereof.
51
52 "Contribution" shall mean any work of authorship, including
53 the original version of the Work and any modifications or additions
54 to that Work or Derivative Works thereof, that is intentionally
55 submitted to Licensor for inclusion in the Work by the copyright owner
56 or by an individual or Legal Entity authorized to submit on behalf of
57 the copyright owner. For the purposes of this definition, "submitted"
58 means any form of electronic, verbal, or written communication sent
59 to the Licensor or its representatives, including but not limited to
60 communication on electronic mailing lists, source code control systems,
61 and issue tracking systems that are managed by, or on behalf of, the
62 Licensor for the purpose of discussing and improving the Work, but
63 excluding communication that is conspicuously marked or otherwise
64 designated in writing by the copyright owner as "Not a Contribution."
65
66 "Contributor" shall mean Licensor and any individual or Legal Entity
67 on behalf of whom a Contribution has been received by Licensor and
68 subsequently incorporated within the Work.
69
70 2. Grant of Copyright License. Subject to the terms and conditions of
71 this License, each Contributor hereby grants to You a perpetual,
72 worldwide, non-exclusive, no-charge, royalty-free, irrevocable
73 copyright license to reproduce, prepare Derivative Works of,
74 publicly display, publicly perform, sublicense, and distribute the
75 Work and such Derivative Works in Source or Object form.
76
77 3. Grant of Patent License. Subject to the terms and conditions of
78 this License, each Contributor hereby grants to You a perpetual,
79 worldwide, non-exclusive, no-charge, royalty-free, irrevocable
80 (except as stated in this section) patent license to make, have made,
81 use, offer to sell, sell, import, and otherwise transfer the Work,
82 where such license applies only to those patent claims licensable
83 by such Contributor that are necessarily infringed by their
84 Contribution(s) alone or by combination of their Contribution(s)
85 with the Work to which such Contribution(s) was submitted. If You
86 institute patent litigation against any entity (including a
87 cross-claim or counterclaim in a lawsuit) alleging that the Work
88 or a Contribution incorporated within the Work constitutes direct
89 or contributory patent infringement, then any patent licenses
90 granted to You under this License for that Work shall terminate
91 as of the date such litigation is filed.
92
93 4. Redistribution. You may reproduce and distribute copies of the
94 Work or Derivative Works thereof in any medium, with or without
95 modifications, and in Source or Object form, provided that You
96 meet the following conditions:
97
98 (a) You must give any other recipients of the Work or
99 Derivative Works a copy of this License; and
100
101 (b) You must cause any modified files to carry prominent notices
102 stating that You changed the files; and
103
104 (c) You must retain, in the Source form of any Derivative Works
105 that You distribute, all copyright, patent, trademark, and
106 attribution notices from the Source form of the Work,
107 excluding those notices that do not pertain to any part of
108 the Derivative Works; and
109
110 (d) If the Work includes a "NOTICE" text file as part of its
111 distribution, then any Derivative Works that You distribute must
112 include a readable copy of the attribution notices contained
113 within such NOTICE file, excluding those notices that do not
114 pertain to any part of the Derivative Works, in at least one
115 of the following places: within a NOTICE text file distributed
116 as part of the Derivative Works; within the Source form or
117 documentation, if provided along with the Derivative Works; or,
118 within a display generated by the Derivative Works, if and
119 wherever such third-party notices normally appear. The contents
120 of the NOTICE file are for informational purposes only and
121 do not modify the License. You may add Your own attribution
122 notices within Derivative Works that You distribute, alongside
123 or as an addendum to the NOTICE text from the Work, provided
124 that such additional attribution notices cannot be construed
125 as modifying the License.
126
127 You may add Your own copyright statement to Your modifications and
128 may provide additional or different license terms and conditions
129 for use, reproduction, or distribution of Your modifications, or
130 for any such Derivative Works as a whole, provided Your use,
131 reproduction, and distribution of the Work otherwise complies with
132 the conditions stated in this License.
133
134 5. Submission of Contributions. Unless You explicitly state otherwise,
135 any Contribution intentionally submitted for inclusion in the Work
136 by You to the Licensor shall be under the terms and conditions of
137 this License, without any additional terms or conditions.
138 Notwithstanding the above, nothing herein shall supersede or modify
139 the terms of any separate license agreement you may have executed
140 with Licensor regarding such Contributions.
141
142 6. Trademarks. This License does not grant permission to use the trade
143 names, trademarks, service marks, or product names of the Licensor,
144 except as required for reasonable and customary use in describing the
145 origin of the Work and reproducing the content of the NOTICE file.
146
147 7. Disclaimer of Warranty. Unless required by applicable law or
148 agreed to in writing, Licensor provides the Work (and each
149 Contributor provides its Contributions) on an "AS IS" BASIS,
150 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
151 implied, including, without limitation, any warranties or conditions
152 of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
153 PARTICULAR PURPOSE. You are solely responsible for determining the
154 appropriateness of using or redistributing the Work and assume any
155 risks associated with Your exercise of permissions under this License.
156
157 8. Limitation of Liability. In no event and under no legal theory,
158 whether in tort (including negligence), contract, or otherwise,
159 unless required by applicable law (such as deliberate and grossly
160 negligent acts) or agreed to in writing, shall any Contributor be
161 liable to You for damages, including any direct, indirect, special,
162 incidental, or consequential damages of any character arising as a
163 result of this License or out of the use or inability to use the
164 Work (including but not limited to damages for loss of goodwill,
165 work stoppage, computer failure or malfunction, or any and all
166 other commercial damages or losses), even if such Contributor
167 has been advised of the possibility of such damages.
168
169 9. Accepting Warranty or Additional Liability. While redistributing
170 the Work or Derivative Works thereof, You may choose to offer,
171 and charge a fee for, acceptance of support, warranty, indemnity,
172 or other liability obligations and/or rights consistent with this
173 License. However, in accepting such obligations, You may act only
174 on Your own behalf and on Your sole responsibility, not on behalf
175 of any other Contributor, and only if You agree to indemnify,
176 defend, and hold each Contributor harmless for any liability
177 incurred by, or claims asserted against, such Contributor by reason
178 of your accepting any such warranty or additional liability.
179
180 END OF TERMS AND CONDITIONS
181
182 APPENDIX: How to apply the Apache License to your work.
183
184 To apply the Apache License to your work, attach the following
185 boilerplate notice, with the fields enclosed by brackets "[]"
186 replaced with your own identifying information. (Don't include
187 the brackets!) The text should be enclosed in the appropriate
188 comment syntax for the file format. We also recommend that a
189 file or class name and description of purpose be included on the
190 same "printed page" as the copyright notice for easier
191 identification within third-party archives.
192
193 Copyright [yyyy] [name of copyright owner]
194
195 Licensed under the Apache License, Version 2.0 (the "License");
196 you may not use this file except in compliance with the License.
197 You may obtain a copy of the License at
198
199 http://www.apache.org/licenses/LICENSE-2.0
200
201 Unless required by applicable law or agreed to in writing, software
202 distributed under the License is distributed on an "AS IS" BASIS,
203 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
204 See the License for the specific language governing permissions and
205 limitations under the License.
206
207
208---- LLVM Exceptions to the Apache 2.0 License ----
209
210As an exception, if, as a result of your compiling your source code, portions
211of this Software are embedded into an Object form of such source code, you
212may redistribute such embedded portions in such Object form without complying
213with the conditions of Sections 4(a), 4(b) and 4(d) of the License.
214
215In addition, if you combine or link compiled forms of this Software with
216software that is licensed under the GPLv2 ("Combined Software") and if a
217court of competent jurisdiction determines that the patent provision (Section
2183), the indemnity provision (Section 9) or other Section of the License
219conflicts with the conditions of the GPLv2, you may retroactively and
220prospectively choose to deem waived or otherwise exclude such Section(s) of
221the License, but only in their entirety and only with respect to the Combined
222Software.
223
224==============================================================================
225Software from third parties included in the LLVM Project:
226==============================================================================
227The LLVM Project contains third party software which is under different license
228terms. All such code will be identified clearly using at least one of two
229mechanisms:
2301) It will be in a separate directory tree with its own `LICENSE.txt` or
231 `LICENSE` file at the top containing the specific license and restrictions
232 which apply to that software, or
2332) It will contain specific license and restriction terms at the top of every
234 file.
235
236==============================================================================
237Legacy LLVM License (https://llvm.org/docs/DeveloperPolicy.html#legacy):
238==============================================================================
239University of Illinois/NCSA
240Open Source License
241
242Copyright (c) 2003-2019 University of Illinois at Urbana-Champaign.
243All rights reserved.
244
245Developed by:
246
247 LLVM Team
248
249 University of Illinois at Urbana-Champaign
250
251 http://llvm.org
252
253Permission is hereby granted, free of charge, to any person obtaining a copy of
254this software and associated documentation files (the "Software"), to deal with
255the Software without restriction, including without limitation the rights to
256use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
257of the Software, and to permit persons to whom the Software is furnished to do
258so, subject to the following conditions:
259
260 * Redistributions of source code must retain the above copyright notice,
261 this list of conditions and the following disclaimers.
262
263 * Redistributions in binary form must reproduce the above copyright notice,
264 this list of conditions and the following disclaimers in the
265 documentation and/or other materials provided with the distribution.
266
267 * Neither the names of the LLVM Team, University of Illinois at
268 Urbana-Champaign, nor the names of its contributors may be used to
269 endorse or promote products derived from this Software without specific
270 prior written permission.
271
272THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
273IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
274FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
275CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
276LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
277OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE
278SOFTWARE.
279
diff --git a/externals/demangle/StringView.h b/externals/demangle/StringView.h
new file mode 100644
index 000000000..c9848e46d
--- /dev/null
+++ b/externals/demangle/StringView.h
@@ -0,0 +1,127 @@
1//===--- StringView.h -------------------------------------------*- 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-FileCopyrightText: Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
6// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7//
8//===----------------------------------------------------------------------===//
9//
10// FIXME: Use std::string_view instead when we support C++17.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef DEMANGLE_STRINGVIEW_H
15#define DEMANGLE_STRINGVIEW_H
16
17#include "DemangleConfig.h"
18#include <algorithm>
19#include <cassert>
20#include <cstring>
21
22DEMANGLE_NAMESPACE_BEGIN
23
24class StringView {
25 const char *First;
26 const char *Last;
27
28public:
29 static const size_t npos = ~size_t(0);
30
31 template <size_t N>
32 StringView(const char (&Str)[N]) : First(Str), Last(Str + N - 1) {}
33 StringView(const char *First_, const char *Last_)
34 : First(First_), Last(Last_) {}
35 StringView(const char *First_, size_t Len)
36 : First(First_), Last(First_ + Len) {}
37 StringView(const char *Str) : First(Str), Last(Str + std::strlen(Str)) {}
38 StringView() : First(nullptr), Last(nullptr) {}
39
40 StringView substr(size_t From) const {
41 return StringView(begin() + From, size() - From);
42 }
43
44 size_t find(char C, size_t From = 0) const {
45 size_t FindBegin = std::min(From, size());
46 // Avoid calling memchr with nullptr.
47 if (FindBegin < size()) {
48 // Just forward to memchr, which is faster than a hand-rolled loop.
49 if (const void *P = ::memchr(First + FindBegin, C, size() - FindBegin))
50 return size_t(static_cast<const char *>(P) - First);
51 }
52 return npos;
53 }
54
55 StringView substr(size_t From, size_t To) const {
56 if (To >= size())
57 To = size() - 1;
58 if (From >= size())
59 From = size() - 1;
60 return StringView(First + From, First + To);
61 }
62
63 StringView dropFront(size_t N = 1) const {
64 if (N >= size())
65 N = size();
66 return StringView(First + N, Last);
67 }
68
69 StringView dropBack(size_t N = 1) const {
70 if (N >= size())
71 N = size();
72 return StringView(First, Last - N);
73 }
74
75 char front() const {
76 assert(!empty());
77 return *begin();
78 }
79
80 char back() const {
81 assert(!empty());
82 return *(end() - 1);
83 }
84
85 char popFront() {
86 assert(!empty());
87 return *First++;
88 }
89
90 bool consumeFront(char C) {
91 if (!startsWith(C))
92 return false;
93 *this = dropFront(1);
94 return true;
95 }
96
97 bool consumeFront(StringView S) {
98 if (!startsWith(S))
99 return false;
100 *this = dropFront(S.size());
101 return true;
102 }
103
104 bool startsWith(char C) const { return !empty() && *begin() == C; }
105
106 bool startsWith(StringView Str) const {
107 if (Str.size() > size())
108 return false;
109 return std::equal(Str.begin(), Str.end(), begin());
110 }
111
112 const char &operator[](size_t Idx) const { return *(begin() + Idx); }
113
114 const char *begin() const { return First; }
115 const char *end() const { return Last; }
116 size_t size() const { return static_cast<size_t>(Last - First); }
117 bool empty() const { return First == Last; }
118};
119
120inline bool operator==(const StringView &LHS, const StringView &RHS) {
121 return LHS.size() == RHS.size() &&
122 std::equal(LHS.begin(), LHS.end(), RHS.begin());
123}
124
125DEMANGLE_NAMESPACE_END
126
127#endif
diff --git a/externals/demangle/Utility.h b/externals/demangle/Utility.h
new file mode 100644
index 000000000..d98ad5c0b
--- /dev/null
+++ b/externals/demangle/Utility.h
@@ -0,0 +1,192 @@
1//===--- Utility.h ----------------------------------------------*- 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-FileCopyrightText: Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
6// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7//
8//===----------------------------------------------------------------------===//
9//
10// Provide some utility classes for use in the demangler(s).
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef DEMANGLE_UTILITY_H
15#define DEMANGLE_UTILITY_H
16
17#include "StringView.h"
18#include <cstdint>
19#include <cstdlib>
20#include <cstring>
21#include <iterator>
22#include <limits>
23
24DEMANGLE_NAMESPACE_BEGIN
25
26// Stream that AST nodes write their string representation into after the AST
27// has been parsed.
28class OutputStream {
29 char *Buffer;
30 size_t CurrentPosition;
31 size_t BufferCapacity;
32
33 // Ensure there is at least n more positions in buffer.
34 void grow(size_t N) {
35 if (N + CurrentPosition >= BufferCapacity) {
36 BufferCapacity *= 2;
37 if (BufferCapacity < N + CurrentPosition)
38 BufferCapacity = N + CurrentPosition;
39 Buffer = static_cast<char *>(std::realloc(Buffer, BufferCapacity));
40 if (Buffer == nullptr)
41 std::terminate();
42 }
43 }
44
45 void writeUnsigned(uint64_t N, bool isNeg = false) {
46 // Handle special case...
47 if (N == 0) {
48 *this << '0';
49 return;
50 }
51
52 char Temp[21];
53 char *TempPtr = std::end(Temp);
54
55 while (N) {
56 *--TempPtr = '0' + char(N % 10);
57 N /= 10;
58 }
59
60 // Add negative sign...
61 if (isNeg)
62 *--TempPtr = '-';
63 this->operator<<(StringView(TempPtr, std::end(Temp)));
64 }
65
66public:
67 OutputStream(char *StartBuf, size_t Size)
68 : Buffer(StartBuf), CurrentPosition(0), BufferCapacity(Size) {}
69 OutputStream() = default;
70 void reset(char *Buffer_, size_t BufferCapacity_) {
71 CurrentPosition = 0;
72 Buffer = Buffer_;
73 BufferCapacity = BufferCapacity_;
74 }
75
76 /// If a ParameterPackExpansion (or similar type) is encountered, the offset
77 /// into the pack that we're currently printing.
78 unsigned CurrentPackIndex = std::numeric_limits<unsigned>::max();
79 unsigned CurrentPackMax = std::numeric_limits<unsigned>::max();
80
81 OutputStream &operator+=(StringView R) {
82 size_t Size = R.size();
83 if (Size == 0)
84 return *this;
85 grow(Size);
86 std::memmove(Buffer + CurrentPosition, R.begin(), Size);
87 CurrentPosition += Size;
88 return *this;
89 }
90
91 OutputStream &operator+=(char C) {
92 grow(1);
93 Buffer[CurrentPosition++] = C;
94 return *this;
95 }
96
97 OutputStream &operator<<(StringView R) { return (*this += R); }
98
99 OutputStream &operator<<(char C) { return (*this += C); }
100
101 OutputStream &operator<<(long long N) {
102 if (N < 0)
103 writeUnsigned(static_cast<unsigned long long>(-N), true);
104 else
105 writeUnsigned(static_cast<unsigned long long>(N));
106 return *this;
107 }
108
109 OutputStream &operator<<(unsigned long long N) {
110 writeUnsigned(N, false);
111 return *this;
112 }
113
114 OutputStream &operator<<(long N) {
115 return this->operator<<(static_cast<long long>(N));
116 }
117
118 OutputStream &operator<<(unsigned long N) {
119 return this->operator<<(static_cast<unsigned long long>(N));
120 }
121
122 OutputStream &operator<<(int N) {
123 return this->operator<<(static_cast<long long>(N));
124 }
125
126 OutputStream &operator<<(unsigned int N) {
127 return this->operator<<(static_cast<unsigned long long>(N));
128 }
129
130 size_t getCurrentPosition() const { return CurrentPosition; }
131 void setCurrentPosition(size_t NewPos) { CurrentPosition = NewPos; }
132
133 char back() const {
134 return CurrentPosition ? Buffer[CurrentPosition - 1] : '\0';
135 }
136
137 bool empty() const { return CurrentPosition == 0; }
138
139 char *getBuffer() { return Buffer; }
140 char *getBufferEnd() { return Buffer + CurrentPosition - 1; }
141 size_t getBufferCapacity() { return BufferCapacity; }
142};
143
144template <class T> class SwapAndRestore {
145 T &Restore;
146 T OriginalValue;
147 bool ShouldRestore = true;
148
149public:
150 SwapAndRestore(T &Restore_) : SwapAndRestore(Restore_, Restore_) {}
151
152 SwapAndRestore(T &Restore_, T NewVal)
153 : Restore(Restore_), OriginalValue(Restore) {
154 Restore = std::move(NewVal);
155 }
156 ~SwapAndRestore() {
157 if (ShouldRestore)
158 Restore = std::move(OriginalValue);
159 }
160
161 void shouldRestore(bool ShouldRestore_) { ShouldRestore = ShouldRestore_; }
162
163 void restoreNow(bool Force) {
164 if (!Force && !ShouldRestore)
165 return;
166
167 Restore = std::move(OriginalValue);
168 ShouldRestore = false;
169 }
170
171 SwapAndRestore(const SwapAndRestore &) = delete;
172 SwapAndRestore &operator=(const SwapAndRestore &) = delete;
173};
174
175inline bool initializeOutputStream(char *Buf, size_t *N, OutputStream &S,
176 size_t InitSize) {
177 size_t BufferSize;
178 if (Buf == nullptr) {
179 Buf = static_cast<char *>(std::malloc(InitSize));
180 if (Buf == nullptr)
181 return false;
182 BufferSize = InitSize;
183 } else
184 BufferSize = *N;
185
186 S.reset(Buf, BufferSize);
187 return true;
188}
189
190DEMANGLE_NAMESPACE_END
191
192#endif
diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt
index 45332cf95..57eec57b5 100644
--- a/src/common/CMakeLists.txt
+++ b/src/common/CMakeLists.txt
@@ -38,6 +38,7 @@ add_library(common STATIC
38 common_precompiled_headers.h 38 common_precompiled_headers.h
39 common_types.h 39 common_types.h
40 concepts.h 40 concepts.h
41 demangle.h
41 div_ceil.h 42 div_ceil.h
42 dynamic_library.cpp 43 dynamic_library.cpp
43 dynamic_library.h 44 dynamic_library.h
@@ -175,7 +176,7 @@ endif()
175create_target_directory_groups(common) 176create_target_directory_groups(common)
176 177
177target_link_libraries(common PUBLIC ${Boost_LIBRARIES} fmt::fmt microprofile Threads::Threads) 178target_link_libraries(common PUBLIC ${Boost_LIBRARIES} fmt::fmt microprofile Threads::Threads)
178target_link_libraries(common PRIVATE lz4::lz4 zstd::zstd) 179target_link_libraries(common PRIVATE lz4::lz4 zstd::zstd demangle)
179 180
180if (YUZU_USE_PRECOMPILED_HEADERS) 181if (YUZU_USE_PRECOMPILED_HEADERS)
181 target_precompile_headers(common PRIVATE precompiled_headers.h) 182 target_precompile_headers(common PRIVATE precompiled_headers.h)
diff --git a/src/common/demangle.h b/src/common/demangle.h
new file mode 100644
index 000000000..1c4143629
--- /dev/null
+++ b/src/common/demangle.h
@@ -0,0 +1,33 @@
1// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include <string>
7
8namespace llvm {
9char* itaniumDemangle(const char* mangled_name, char* buf, size_t* n, int* status);
10}
11
12namespace Common {
13std::string DemangleSymbol(const std::string& mangled) {
14 auto is_itanium = [](const std::string& name) -> bool {
15 // A valid Itanium encoding requires 1-4 leading underscores, followed by 'Z'.
16 auto pos = name.find_first_not_of('_');
17 return pos > 0 && pos <= 4 && name[pos] == 'Z';
18 };
19
20 char* demangled = nullptr;
21 if (is_itanium(mangled)) {
22 demangled = llvm::itaniumDemangle(mangled.c_str(), nullptr, nullptr, nullptr);
23 }
24
25 if (!demangled) {
26 return mangled;
27 }
28
29 std::string ret = demangled;
30 std::free(demangled);
31 return ret;
32}
33} // namespace Common \ No newline at end of file
diff --git a/src/core/arm/arm_interface.cpp b/src/core/arm/arm_interface.cpp
index 2df7b0ee8..a34200539 100644
--- a/src/core/arm/arm_interface.cpp
+++ b/src/core/arm/arm_interface.cpp
@@ -7,8 +7,10 @@
7 7
8#include <map> 8#include <map>
9#include <optional> 9#include <optional>
10
10#include "common/bit_field.h" 11#include "common/bit_field.h"
11#include "common/common_types.h" 12#include "common/common_types.h"
13#include "common/demangle.h"
12#include "common/logging/log.h" 14#include "common/logging/log.h"
13#include "core/arm/arm_interface.h" 15#include "core/arm/arm_interface.h"
14#include "core/arm/symbols.h" 16#include "core/arm/symbols.h"
@@ -71,20 +73,8 @@ void ARM_Interface::SymbolicateBacktrace(Core::System& system, std::vector<Backt
71 const auto symbol_set = symbols.find(entry.module); 73 const auto symbol_set = symbols.find(entry.module);
72 if (symbol_set != symbols.end()) { 74 if (symbol_set != symbols.end()) {
73 const auto symbol = Symbols::GetSymbolName(symbol_set->second, entry.offset); 75 const auto symbol = Symbols::GetSymbolName(symbol_set->second, entry.offset);
74 if (symbol.has_value()) { 76 if (symbol) {
75#ifdef _MSC_VER 77 entry.name = Common::DemangleSymbol(*symbol);
76 // TODO(DarkLordZach): Add demangling of symbol names.
77 entry.name = *symbol;
78#else
79 int status{-1};
80 char* demangled{abi::__cxa_demangle(symbol->c_str(), nullptr, nullptr, &status)};
81 if (status == 0 && demangled != nullptr) {
82 entry.name = demangled;
83 std::free(demangled);
84 } else {
85 entry.name = *symbol;
86 }
87#endif
88 } 78 }
89 } 79 }
90 } 80 }