v1.2.1
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 0b39ba8..fd35e5b 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,5 +1,5 @@
-cmake_minimum_required(VERSION 3.1.0 FATAL_ERROR)
-project(demumble C CXX)
+cmake_minimum_required(VERSION 3.2.0 FATAL_ERROR)
+project(demumble CXX)
if (UNIX)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -fno-exceptions -fno-rtti")
@@ -20,6 +20,7 @@
if (WIN32)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /Zc:inline /EHs-c- /GR-")
+ add_definitions(-D_CRT_SECURE_NO_WARNINGS) # The LLVM build sets this.
# This is apparently the simplest way to statically link the CRT in CMake:
string(TOUPPER "${CMAKE_BUILD_TYPE}" build)
diff --git a/README.md b/README.md
index 1e6a773..4e1af91 100644
--- a/README.md
+++ b/README.md
@@ -62,12 +62,17 @@
$ c++filt '??2@YAPEAX_K@Z'
??2@YAPEAX_K@Z
-demumble also has a flag to make it print only things that look like symbols.
-For example, print demangled names of all functions defined in a bitcode file:
+Optionally print _only_ demangled things: For example, print demangled names of
+all functions defined in a bitcode file:
$ grep '^define' bitcode-win.ll | demumble -m | head -1
unsigned int __cdecl v8::RoundUpToPowerOfTwo32(unsigned int)
+Optionally print both mangled and demangled names:
+
+ $ echo _ZN3fooC1Ev _ZN3fooC2Ev | ./demumble -b
+ "foo::foo()" (_ZN3fooC1Ev) "foo::foo()" (_ZN3fooC2Ev)
+
## Build instructions
Use cmake to build: `cmake -G Ninja && ninja`
diff --git a/RELEASING b/RELEASING
index f1e0840..61b2017 100644
--- a/RELEASING
+++ b/RELEASING
@@ -1,6 +1,6 @@
Push new release branch:
-1. Make sure branches 'master' and 'release' are synced up locally
-2. update src/demumble.cc with new version (with ".git"), then
+1. make sure branches 'master' and 'release' are synced up locally
+2. update demumble.cc with new version (with ".git"), then
git commit -am 'mark this 1.0.0.git'
3. git checkout release; git merge master
4. fix version number in src/version.cc (it will likely conflict in the above)
@@ -9,5 +9,5 @@
git tag v1.0.0; git push --tags
# Push the 1.0.0.git change on master too:
git checkout master; git push origin master
-6. Add binaries to https://github.com/nico/demumble/releases
- Build them with `-DCMAKE_BUILD_TYPE=Release`, strip after building.
+6. add binaries to https://github.com/nico/demumble/releases
+ build them with `./dist.py`
diff --git a/demumble.cc b/demumble.cc
index 9f37890..0f182ab 100644
--- a/demumble.cc
+++ b/demumble.cc
@@ -6,9 +6,9 @@
#include "llvm/Demangle/Demangle.h"
-const char kDemumbleVersion[] = "1.2.0";
+const char kDemumbleVersion[] = "1.2.1";
-static void print_help(FILE* out) {
+static int print_help(FILE* out) {
fprintf(out,
"usage: demumble [options] [symbols...]\n"
"\n"
@@ -19,17 +19,11 @@
" -m only print mangled names that were demangled, omit other output\n"
" -u use unbuffered output\n"
" --version print demumble version (\"%s\")\n", kDemumbleVersion);
-}
-
-static bool starts_with(const char* s, const char* prefix) {
- return strncmp(s, prefix, strlen(prefix)) == 0;
+ return out == stdout ? 0 : 1;
}
static void print_demangled(const char* format, const char* s) {
- const char* cxa_in = s;
- if (starts_with(s, "__Z") || starts_with(s, "____Z"))
- cxa_in += 1;
- if (char* itanium = llvm::itaniumDemangle(cxa_in, NULL, NULL, NULL)) {
+ if (char* itanium = llvm::itaniumDemangle(s, NULL, NULL, NULL)) {
printf(format, itanium, s);
free(itanium);
} else if (char* ms = llvm::microsoftDemangle(s, NULL, NULL, NULL)) {
@@ -64,15 +58,8 @@
enum { kPrintAll, kPrintMatching } print_mode = kPrintAll;
const char* print_format = "%s";
while (argc > 1 && argv[1][0] == '-') {
- if (strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "--help") == 0) {
- print_help(stdout);
- return 0;
- } else if (strcmp(argv[1], "-b") == 0) {
- print_format = "\"%s\" (%s)";
- } else if (strcmp(argv[1], "-m") == 0) {
- print_mode = kPrintMatching;
- } else if (strcmp(argv[1], "-u") == 0) {
- setbuf(stdout, NULL);
+ if (strcmp(argv[1], "--help") == 0) {
+ return print_help(stdout);
} else if (strcmp(argv[1], "--version") == 0) {
printf("%s\n", kDemumbleVersion);
return 0;
@@ -80,10 +67,21 @@
--argc;
++argv;
break;
+ } else if (argv[1][0] == '-' && argv[1][1] != '-') {
+ for (int i = 1; i < strlen(argv[1]); ++i)
+ switch (argv[1][i]) {
+ case 'b': print_format = "\"%s\" (%s)"; break;
+ case 'h': return print_help(stdout);
+ case 'm': print_mode = kPrintMatching; break;
+ case 'u': setbuf(stdout, NULL); break;
+ default:
+ fprintf(stderr, "demumble: unrecognized option `%c' in `%s'\n",
+ argv[1][i], argv[1]);
+ return print_help(stderr);
+ }
} else {
fprintf(stderr, "demumble: unrecognized option `%s'\n", argv[1]);
- print_help(stderr);
- return 1;
+ return print_help(stderr);
}
--argc;
++argv;
diff --git a/demumble_test.py b/demumble_test.py
index 7df0ae9..3b35aed 100755
--- a/demumble_test.py
+++ b/demumble_test.py
@@ -23,6 +23,7 @@
'.invocation function for block in blocksNRVO()\n'),
('demumble -m < .____Z10blocksNRVOv_block_invoke',
'invocation function for block in blocksNRVO()\n'),
+ ('demumble _ZN2zx7channelD4Ev', 'zx::channel::~channel()\n'),
('demumble -- -b', '-b\n'),
('demumble -- -m', '-m\n'),
('demumble -- -h', '-h\n'),
@@ -32,6 +33,10 @@
('demumble -b hello', 'hello\n'),
('demumble -b _Z1fv', '"f()" (_Z1fv)\n'),
('demumble -b < _Z1fv', '"f()" (_Z1fv)\n'),
+ ('demumble -bm < _Z1fv!foo_bar', '"f()" (_Z1fv)\n'),
+ ('demumble -mb < _Z1fv!foo_bar', '"f()" (_Z1fv)\n'),
+ ('demumble --foo < bar', re.compile(".*unrecognized option `--foo'.*")),
+ ('demumble -bx < bar', re.compile(".*unrecognized option `x' in `-bx'.*")),
]
status = 0
@@ -46,7 +51,7 @@
out = p.communicate(input='\n'.join(cmd[cmd.index('<') + 1:]) + '\n')[0]
else:
out = subprocess.check_output(cmd, universal_newlines=True)
- if (out != t[1] if isinstance(t[1], str) else t[1].match(out, re.M)):
+ if (out != t[1] if isinstance(t[1], str) else not t[1].match(out)):
print("`%s`: Expected '%s', got '%s'" % (t[0], t[1], out))
status = 1
print("passed" if status == 0 else "failed")
diff --git a/dist.py b/dist.py
new file mode 100755
index 0000000..c9a953e
--- /dev/null
+++ b/dist.py
@@ -0,0 +1,127 @@
+#!/usr/bin/env python
+
+# Builds demumble for Mac, Linux, Windows. Must run on a Mac.
+# Needs a chromium checkout at ~/src/chrome/src that was synced with
+# target_os=['win'] to get the Windows toolchain. You must run
+# `build/linux/sysroot_scripts/install-sysroot.py --arch amd64` once to
+# get the linux toolchain.
+
+# Also needs a GN build of llvm at ~/src/llvm-project/out/gn for llvm-strip
+# for stripping the Linux binary.
+
+# Doesn't run tests, so make sure to run `./demumble_test.py` on all 3 platforms
+# before running this script.
+
+# After this script finishes successfully, the cwd will contain
+# demumble-mac.zip, demumble-linux.zip, demumble-windows.zip which each contain
+# a demumble binary built for that OS, ready for releasing (assuming the script
+# was run on the release branch).
+
+# https://gitlab.kitware.com/cmake/community/wikis/doc/cmake/CrossCompiling has
+# some documentation on cross builds with cmake.
+
+import contextlib
+import json
+import glob
+import os
+import subprocess
+import sys
+
+crsrc = os.path.join(os.path.expanduser('~'), 'src/chrome/src')
+if len(sys.argv) > 1:
+ crsrc = os.path.abspath(sys.argv[1])
+clangcl = crsrc + '/third_party/llvm-build/Release+Asserts/bin/clang-cl'
+clangxx = crsrc + '/third_party/llvm-build/Release+Asserts/bin/clang++'
+lldlink = crsrc + '/third_party/llvm-build/Release+Asserts/bin/lld-link'
+
+linux_strip = os.path.join(os.path.expanduser('~'),
+ 'src/llvm-project/out/gn/bin/llvm-strip')
+
+cmake = '/Applications/CMake.app/Contents/bin/cmake'
+call_cmake = [cmake, '-GNinja', '..', '-DCMAKE_BUILD_TYPE=Release']
+
+
+@contextlib.contextmanager
+def buildir(newdir):
+ """Creates newdir if it doesn't exist yet and temporarily sets cwd to it."""
+ newdir = os.path.join(os.path.dirname(__file__), newdir)
+ if not os.path.isdir(newdir):
+ os.mkdir(newdir) # Intentionally not deleted.
+ prevdir = os.getcwd()
+ os.chdir(newdir)
+ try:
+ yield
+ finally:
+ os.chdir(prevdir)
+
+subprocess.check_call(['rm', '-rf', 'buildlinux', 'buildmac', 'buildwin'])
+devnull = open(os.devnull,"w")
+
+# Linux.
+linux_sysroot = crsrc + '/build/linux/debian_jessie_amd64-sysroot'
+cflags = [ '--sysroot', linux_sysroot, '--target=x86_64-linux-gnu', ]
+ldflags = ['-fuse-ld=lld'] + cflags
+with buildir('buildlinux'):
+ print 'building linux'
+ subprocess.check_call(call_cmake + [
+ '-DCMAKE_CXX_COMPILER=' + clangxx,
+ '-DCMAKE_CXX_FLAGS=' + ' '.join(cflags),
+ '-DCMAKE_EXE_LINKER_FLAGS=' + ' '.join(ldflags),
+ '-DCMAKE_SYSTEM_NAME=Linux',
+ ], stdout=devnull)
+ subprocess.check_call(['ninja', 'demumble'])
+ # FIXME: https://chromium-review.googlesource.com/c/chromium/src/+/1214943
+ # has a way to build eu-strip on macOS, which is arguably a smaller dep
+ # than llvm-strip.
+ subprocess.check_call([linux_strip, 'demumble'])
+ subprocess.check_call(['zip', '-q9', 'demumble-linux.zip', 'demumble'])
+ subprocess.check_call(['mv', 'demumble-linux.zip', '..'])
+
+# Mac.
+with buildir('buildmac'):
+ print 'building mac'
+ subprocess.check_call(call_cmake + [
+ '-DCMAKE_CXX_COMPILER=' + clangxx,
+ ], stdout=devnull)
+ subprocess.check_call(['ninja', 'demumble'])
+ subprocess.check_call(['strip', 'demumble'])
+ subprocess.check_call(['zip', '-q9', 'demumble-mac.zip', 'demumble'])
+ subprocess.check_call(['mv', 'demumble-mac.zip', '..'])
+
+# Win.
+win_sysroot = glob.glob(
+ crsrc + '/third_party/depot_tools/win_toolchain/vs_files/*')[0]
+win_bindir = win_sysroot + '/win_sdk/bin'
+# This json file looks like http://codepad.org/kmfgf0UL
+winenv = json.load(open(win_bindir + '/SetEnv.x64.json'))['env']
+for k in ['INCLUDE', 'LIB']:
+ winenv[k] = [os.path.join(*([win_bindir] + e)) for e in winenv[k]]
+win_include = ['-imsvc' + i for i in winenv['INCLUDE']]
+win_lib = ['/libpath:' + i for i in winenv['LIB']]
+cflags = ['--target=x86_64-pc-windows'] + win_include
+with buildir('buildwin'):
+ print 'building windows'
+ subprocess.check_call(call_cmake + [
+ '-DCMAKE_CXX_COMPILER=' + clangcl,
+ '-DCMAKE_CXX_FLAGS=' + ' '.join(cflags),
+ # Without /manifest:no, cmake creates a default manifest file -- and
+ # explicitly calls mt.exe (which we don't have in a cross build).
+ # This also removes a dependency on rc.exe -- without this we'd also
+ # have to set CMAKE_TRY_COMPILE_TARGET_TYPE=STATIC_LIBRARY.
+ '-DCMAKE_EXE_LINKER_FLAGS=' + ' '.join(['/manifest:no'] + win_lib),
+ '-DCMAKE_LINKER=' + lldlink,
+ '-DCMAKE_SYSTEM_NAME=Windows',
+ ], stdout=devnull)
+ subprocess.check_call(['ninja', 'demumble'])
+ # No stripping on Windows.
+ subprocess.check_call(['zip', '-q9', 'demumble-win.zip', 'demumble.exe'])
+ subprocess.check_call(['mv', 'demumble-win.zip', '..'])
+
+# Copy over mac binary and run tests.
+print 'running tests (on mac)'
+subprocess.check_call(['cp', 'buildmac/demumble', '.'])
+subprocess.check_call(['./demumble_test.py'])
+
+# Show zip files.
+subprocess.check_call('ls -hl *.zip', shell=True)
+subprocess.check_call(['./demumble', '--version'])
diff --git a/third_party/llvm/LICENSE.txt b/third_party/llvm/LICENSE.txt
index 57a8005..fa6ac54 100644
--- a/third_party/llvm/LICENSE.txt
+++ b/third_party/llvm/LICENSE.txt
@@ -1,10 +1,245 @@
==============================================================================
-LLVM Release License
+The LLVM Project is under the Apache License v2.0 with LLVM Exceptions:
+==============================================================================
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+
+---- LLVM Exceptions to the Apache 2.0 License ----
+
+As an exception, if, as a result of your compiling your source code, portions
+of this Software are embedded into an Object form of such source code, you
+may redistribute such embedded portions in such Object form without complying
+with the conditions of Sections 4(a), 4(b) and 4(d) of the License.
+
+In addition, if you combine or link compiled forms of this Software with
+software that is licensed under the GPLv2 ("Combined Software") and if a
+court of competent jurisdiction determines that the patent provision (Section
+3), the indemnity provision (Section 9) or other Section of the License
+conflicts with the conditions of the GPLv2, you may retroactively and
+prospectively choose to deem waived or otherwise exclude such Section(s) of
+the License, but only in their entirety and only with respect to the Combined
+Software.
+
+==============================================================================
+Software from third parties included in the LLVM Project:
+==============================================================================
+The LLVM Project contains third party software which is under different license
+terms. All such code will be identified clearly using at least one of two
+mechanisms:
+1) It will be in a separate directory tree with its own `LICENSE.txt` or
+ `LICENSE` file at the top containing the specific license and restrictions
+ which apply to that software, or
+2) It will contain specific license and restriction terms at the top of every
+ file.
+
+==============================================================================
+Legacy LLVM License (https://llvm.org/docs/DeveloperPolicy.html#legacy):
==============================================================================
University of Illinois/NCSA
Open Source License
-Copyright (c) 2003-2018 University of Illinois at Urbana-Champaign.
+Copyright (c) 2003-2019 University of Illinois at Urbana-Champaign.
All rights reserved.
Developed by:
@@ -41,3 +276,4 @@
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE
SOFTWARE.
+
diff --git a/third_party/llvm/include/llvm/Demangle/Demangle.h b/third_party/llvm/include/llvm/Demangle/Demangle.h
index b9b4d15..6fea7ef 100644
--- a/third_party/llvm/include/llvm/Demangle/Demangle.h
+++ b/third_party/llvm/include/llvm/Demangle/Demangle.h
@@ -1,9 +1,8 @@
//===--- Demangle.h ---------------------------------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
@@ -11,6 +10,7 @@
#define LLVM_DEMANGLE_DEMANGLE_H
#include <cstddef>
+#include <string>
namespace llvm {
/// This is a llvm local version of __cxa_demangle. Other than the name and
@@ -31,16 +31,18 @@
char *itaniumDemangle(const char *mangled_name, char *buf, size_t *n,
int *status);
-/// Calls the callback \c Callback with \c Ctx as an argument whenever a type is
-/// encountered. Returns true if \c MangledName couldn't be parsed.
-bool itaniumFindTypesInMangledName(const char *MangledName, void *Ctx,
- void (*Callback)(void *, const char *));
-
enum MSDemangleFlags { MSDF_None = 0, MSDF_DumpBackrefs = 1 << 0 };
char *microsoftDemangle(const char *mangled_name, char *buf, size_t *n,
int *status, MSDemangleFlags Flags = MSDF_None);
+/// Attempt to demangle a string using different demangling schemes.
+/// The function uses heuristics to determine which demangling scheme to use.
+/// \param MangledName - reference to string to demangle.
+/// \returns - the demangled string, or a copy of the input string if no
+/// demangling occurred.
+std::string demangle(const std::string &MangledName);
+
/// "Partial" demangler. This supports demangling a string into an AST
/// (typically an intermediate stage in itaniumDemangle) and querying certain
/// properties or partially printing the demangled name.
diff --git a/third_party/llvm/include/llvm/Demangle/DemangleConfig.h b/third_party/llvm/include/llvm/Demangle/DemangleConfig.h
new file mode 100644
index 0000000..73f89d3
--- /dev/null
+++ b/third_party/llvm/include/llvm/Demangle/DemangleConfig.h
@@ -0,0 +1,99 @@
+//===--- DemangleConfig.h ---------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains a variety of feature test macros copied from
+// include/llvm/Support/Compiler.h so that LLVMDemangle does not need to take
+// a dependency on LLVMSupport.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEMANGLE_COMPILER_H
+#define LLVM_DEMANGLE_COMPILER_H
+
+#ifdef _MSC_VER
+// snprintf is implemented in VS 2015
+#if _MSC_VER < 1900
+#define snprintf _snprintf_s
+#endif
+#endif
+
+#ifndef __has_feature
+#define __has_feature(x) 0
+#endif
+
+#ifndef __has_cpp_attribute
+#define __has_cpp_attribute(x) 0
+#endif
+
+#ifndef __has_attribute
+#define __has_attribute(x) 0
+#endif
+
+#ifndef __has_builtin
+#define __has_builtin(x) 0
+#endif
+
+#ifndef DEMANGLE_GNUC_PREREQ
+#if defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__)
+#define DEMANGLE_GNUC_PREREQ(maj, min, patch) \
+ ((__GNUC__ << 20) + (__GNUC_MINOR__ << 10) + __GNUC_PATCHLEVEL__ >= \
+ ((maj) << 20) + ((min) << 10) + (patch))
+#elif defined(__GNUC__) && defined(__GNUC_MINOR__)
+#define DEMANGLE_GNUC_PREREQ(maj, min, patch) \
+ ((__GNUC__ << 20) + (__GNUC_MINOR__ << 10) >= ((maj) << 20) + ((min) << 10))
+#else
+#define DEMANGLE_GNUC_PREREQ(maj, min, patch) 0
+#endif
+#endif
+
+#if __has_attribute(used) || DEMANGLE_GNUC_PREREQ(3, 1, 0)
+#define DEMANGLE_ATTRIBUTE_USED __attribute__((__used__))
+#else
+#define DEMANGLE_ATTRIBUTE_USED
+#endif
+
+#if __has_builtin(__builtin_unreachable) || DEMANGLE_GNUC_PREREQ(4, 5, 0)
+#define DEMANGLE_UNREACHABLE __builtin_unreachable()
+#elif defined(_MSC_VER)
+#define DEMANGLE_UNREACHABLE __assume(false)
+#else
+#define DEMANGLE_UNREACHABLE
+#endif
+
+#if __has_attribute(noinline) || DEMANGLE_GNUC_PREREQ(3, 4, 0)
+#define DEMANGLE_ATTRIBUTE_NOINLINE __attribute__((noinline))
+#elif defined(_MSC_VER)
+#define DEMANGLE_ATTRIBUTE_NOINLINE __declspec(noinline)
+#else
+#define DEMANGLE_ATTRIBUTE_NOINLINE
+#endif
+
+#if !defined(NDEBUG)
+#define DEMANGLE_DUMP_METHOD DEMANGLE_ATTRIBUTE_NOINLINE DEMANGLE_ATTRIBUTE_USED
+#else
+#define DEMANGLE_DUMP_METHOD DEMANGLE_ATTRIBUTE_NOINLINE
+#endif
+
+#if __cplusplus > 201402L && __has_cpp_attribute(fallthrough)
+#define DEMANGLE_FALLTHROUGH [[fallthrough]]
+#elif __has_cpp_attribute(gnu::fallthrough)
+#define DEMANGLE_FALLTHROUGH [[gnu::fallthrough]]
+#elif !__cplusplus
+// Workaround for llvm.org/PR23435, since clang 3.6 and below emit a spurious
+// error when __has_cpp_attribute is given a scoped attribute in C mode.
+#define DEMANGLE_FALLTHROUGH
+#elif __has_cpp_attribute(clang::fallthrough)
+#define DEMANGLE_FALLTHROUGH [[clang::fallthrough]]
+#else
+#define DEMANGLE_FALLTHROUGH
+#endif
+
+#define DEMANGLE_NAMESPACE_BEGIN namespace llvm { namespace itanium_demangle {
+#define DEMANGLE_NAMESPACE_END } }
+
+#endif
diff --git a/third_party/llvm/include/llvm/Demangle/ItaniumDemangle.h b/third_party/llvm/include/llvm/Demangle/ItaniumDemangle.h
index c5619a1..ad1034f 100644
--- a/third_party/llvm/include/llvm/Demangle/ItaniumDemangle.h
+++ b/third_party/llvm/include/llvm/Demangle/ItaniumDemangle.h
@@ -1,23 +1,26 @@
//===------------------------- ItaniumDemangle.h ----------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
+//===----------------------------------------------------------------------===//
+//
+// Generic itanium demangler library. This file has two byte-per-byte identical
+// copies in the source tree, one in libcxxabi, and the other in llvm.
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_DEMANGLE_ITANIUMDEMANGLE_H
-#define LLVM_DEMANGLE_ITANIUMDEMANGLE_H
+#ifndef DEMANGLE_ITANIUMDEMANGLE_H
+#define DEMANGLE_ITANIUMDEMANGLE_H
// FIXME: (possibly) incomplete list of features that clang mangles that this
// file does not yet support:
// - C++ modules TS
-#include "llvm/Demangle/Compiler.h"
-#include "llvm/Demangle/StringView.h"
-#include "llvm/Demangle/Utility.h"
-
+#include "DemangleConfig.h"
+#include "StringView.h"
+#include "Utility.h"
#include <cassert>
#include <cctype>
#include <cstdio>
@@ -86,6 +89,7 @@
X(InitListExpr) \
X(FoldExpr) \
X(ThrowExpr) \
+ X(UUIDOfExpr) \
X(BoolExpr) \
X(IntegerCastExpr) \
X(IntegerLiteral) \
@@ -95,8 +99,8 @@
X(BracedExpr) \
X(BracedRangeExpr)
-namespace llvm {
-namespace itanium_demangle {
+DEMANGLE_NAMESPACE_BEGIN
+
// Base class of all AST nodes. The AST is built by the parser, then is
// traversed by the printLeft/Right functions to produce a demangled string.
class Node {
@@ -194,7 +198,7 @@
virtual ~Node() = default;
#ifndef NDEBUG
- LLVM_DUMP_METHOD void dump() const;
+ DEMANGLE_DUMP_METHOD void dump() const;
#endif
};
@@ -1278,7 +1282,7 @@
case SpecialSubKind::iostream:
return StringView("basic_iostream");
}
- LLVM_BUILTIN_UNREACHABLE;
+ DEMANGLE_UNREACHABLE;
}
void printLeft(OutputStream &S) const override {
@@ -1330,7 +1334,7 @@
case SpecialSubKind::iostream:
return StringView("iostream");
}
- LLVM_BUILTIN_UNREACHABLE;
+ DEMANGLE_UNREACHABLE;
}
void printLeft(OutputStream &S) const override {
@@ -1870,6 +1874,21 @@
}
};
+// MSVC __uuidof extension, generated by clang in -fms-extensions mode.
+class UUIDOfExpr : public Node {
+ Node *Operand;
+public:
+ UUIDOfExpr(Node *Operand_) : Node(KUUIDOfExpr), Operand(Operand_) {}
+
+ template<typename Fn> void match(Fn F) const { F(Operand); }
+
+ void printLeft(OutputStream &S) const override {
+ S << "__uuidof(";
+ Operand->print(S);
+ S << ")";
+ }
+};
+
class BoolExpr : public Node {
bool Value;
@@ -2157,9 +2176,6 @@
// conversion operator's type, and are resolved in the enclosing <encoding>.
PODSmallVector<ForwardTemplateReference *, 4> ForwardTemplateRefs;
- void (*TypeCallback)(void *, const char *) = nullptr;
- void *TypeCallbackContext = nullptr;
-
bool TryToParseTemplateArgs = true;
bool PermitForwardTemplateReferences = false;
bool ParsingLambdaParams = false;
@@ -2479,6 +2495,12 @@
return nullptr;
return make<ClosureTypeName>(Params, Count);
}
+ if (consumeIf("Ub")) {
+ (void)parseNumber();
+ if (!consumeIf('_'))
+ return nullptr;
+ return make<NameType>("'block-literal'");
+ }
return nullptr;
}
@@ -2788,11 +2810,13 @@
// <ctor-dtor-name> ::= C1 # complete object constructor
// ::= C2 # base object constructor
// ::= C3 # complete object allocating constructor
-// extension ::= C5 # ?
+// extension ::= C4 # gcc old-style "[unified]" constructor
+// extension ::= C5 # the COMDAT used for ctors
// ::= D0 # deleting destructor
// ::= D1 # complete object destructor
// ::= D2 # base object destructor
-// extension ::= D5 # ?
+// extension ::= D4 # gcc old-style "[unified]" destructor
+// extension ::= D5 # the COMDAT used for dtors
template <typename Derived, typename Alloc>
Node *
AbstractManglingParser<Derived, Alloc>::parseCtorDtorName(Node *&SoFar,
@@ -2815,7 +2839,8 @@
if (consumeIf('C')) {
bool IsInherited = consumeIf('I');
- if (look() != '1' && look() != '2' && look() != '3' && look() != '5')
+ if (look() != '1' && look() != '2' && look() != '3' && look() != '4' &&
+ look() != '5')
return nullptr;
int Variant = look() - '0';
++First;
@@ -2824,15 +2849,15 @@
if (getDerived().parseName(State) == nullptr)
return nullptr;
}
- return make<CtorDtorName>(SoFar, false, Variant);
+ return make<CtorDtorName>(SoFar, /*IsDtor=*/false, Variant);
}
- if (look() == 'D' &&
- (look(1) == '0' || look(1) == '1' || look(1) == '2' || look(1) == '5')) {
+ if (look() == 'D' && (look(1) == '0' || look(1) == '1' || look(1) == '2' ||
+ look(1) == '4' || look(1) == '5')) {
int Variant = look(1) - '0';
First += 2;
if (State) State->CtorDtorConversion = true;
- return make<CtorDtorName>(SoFar, true, Variant);
+ return make<CtorDtorName>(SoFar, /*IsDtor=*/true, Variant);
}
return nullptr;
@@ -3453,9 +3478,6 @@
Node *AbstractManglingParser<Derived, Alloc>::parseType() {
Node *Result = nullptr;
- if (TypeCallback != nullptr)
- TypeCallback(TypeCallbackContext, First);
-
switch (look()) {
// ::= <qualified-type>
case 'r':
@@ -3473,7 +3495,7 @@
Result = getDerived().parseFunctionType();
break;
}
- LLVM_FALLTHROUGH;
+ DEMANGLE_FALLTHROUGH;
}
case 'U': {
Result = getDerived().parseQualifiedType();
@@ -3570,7 +3592,11 @@
StringView Res = parseBareSourceName();
if (Res.empty())
return nullptr;
- return make<NameType>(Res);
+ // Typically, <builtin-type>s are not considered substitution candidates,
+ // but the exception to that exception is vendor extended types (Itanium C++
+ // ABI 5.9.1).
+ Result = make<NameType>(Res);
+ break;
}
case 'D':
switch (look(1)) {
@@ -3760,7 +3786,7 @@
// substitution table.
return Sub;
}
- LLVM_FALLTHROUGH;
+ DEMANGLE_FALLTHROUGH;
}
// ::= <class-enum-type>
default: {
@@ -4639,6 +4665,21 @@
case '9':
return getDerived().parseUnresolvedName();
}
+
+ if (consumeIf("u8__uuidoft")) {
+ Node *Ty = getDerived().parseType();
+ if (!Ty)
+ return nullptr;
+ return make<UUIDOfExpr>(Ty);
+ }
+
+ if (consumeIf("u8__uuidofz")) {
+ Node *Ex = getDerived().parseExpr();
+ if (!Ex)
+ return nullptr;
+ return make<UUIDOfExpr>(Ex);
+ }
+
return nullptr;
}
@@ -5145,7 +5186,7 @@
// extension ::= ___Z <encoding> _block_invoke_<decimal-digit>+
template <typename Derived, typename Alloc>
Node *AbstractManglingParser<Derived, Alloc>::parse() {
- if (consumeIf("_Z")) {
+ if (consumeIf("_Z") || consumeIf("__Z")) {
Node *Encoding = getDerived().parseEncoding();
if (Encoding == nullptr)
return nullptr;
@@ -5158,7 +5199,7 @@
return Encoding;
}
- if (consumeIf("___Z")) {
+ if (consumeIf("___Z") || consumeIf("____Z")) {
Node *Encoding = getDerived().parseEncoding();
if (Encoding == nullptr || !consumeIf("_block_invoke"))
return nullptr;
@@ -5184,7 +5225,6 @@
Alloc>::AbstractManglingParser;
};
-} // namespace itanium_demangle
-} // namespace llvm
+DEMANGLE_NAMESPACE_END
-#endif // LLVM_DEMANGLE_ITANIUMDEMANGLE_H
+#endif // DEMANGLE_ITANIUMDEMANGLE_H
diff --git a/third_party/llvm/include/llvm/Demangle/MicrosoftDemangle.h b/third_party/llvm/include/llvm/Demangle/MicrosoftDemangle.h
index b186758..382e794 100644
--- a/third_party/llvm/include/llvm/Demangle/MicrosoftDemangle.h
+++ b/third_party/llvm/include/llvm/Demangle/MicrosoftDemangle.h
@@ -1,16 +1,15 @@
//===------------------------- MicrosoftDemangle.h --------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_DEMANGLE_MICROSOFT_DEMANGLE_H
#define LLVM_DEMANGLE_MICROSOFT_DEMANGLE_H
-#include "llvm/Demangle/Compiler.h"
+#include "llvm/Demangle/DemangleConfig.h"
#include "llvm/Demangle/MicrosoftDemangleNodes.h"
#include "llvm/Demangle/StringView.h"
#include "llvm/Demangle/Utility.h"
@@ -56,24 +55,21 @@
}
}
- char *allocUnalignedBuffer(size_t Length) {
- uint8_t *Buf = Head->Buf + Head->Used;
+ char *allocUnalignedBuffer(size_t Size) {
+ assert(Head && Head->Buf);
- Head->Used += Length;
- if (Head->Used > Head->Capacity) {
- // It's possible we need a buffer which is larger than our default unit
- // size, so we need to be careful to add a node with capacity that is at
- // least as large as what we need.
- addNode(std::max(AllocUnit, Length));
- Head->Used = Length;
- Buf = Head->Buf;
- }
+ uint8_t *P = Head->Buf + Head->Used;
- return reinterpret_cast<char *>(Buf);
+ Head->Used += Size;
+ if (Head->Used <= Head->Capacity)
+ return reinterpret_cast<char *>(P);
+
+ addNode(std::max(AllocUnit, Size));
+ Head->Used = Size;
+ return reinterpret_cast<char *>(Head->Buf);
}
template <typename T, typename... Args> T *allocArray(size_t Count) {
-
size_t Size = Count * sizeof(T);
assert(Head && Head->Buf);
@@ -84,17 +80,16 @@
size_t Adjustment = AlignedP - P;
Head->Used += Size + Adjustment;
- if (Head->Used < Head->Capacity)
+ if (Head->Used <= Head->Capacity)
return new (PP) T[Count]();
- addNode(AllocUnit);
+ addNode(std::max(AllocUnit, Size));
Head->Used = Size;
return new (Head->Buf) T[Count]();
}
template <typename T, typename... Args> T *alloc(Args &&... ConstructorArgs) {
-
- size_t Size = sizeof(T);
+ constexpr size_t Size = sizeof(T);
assert(Head && Head->Buf);
size_t P = (size_t)Head->Buf + Head->Used;
@@ -104,9 +99,10 @@
size_t Adjustment = AlignedP - P;
Head->Used += Size + Adjustment;
- if (Head->Used < Head->Capacity)
+ if (Head->Used <= Head->Capacity)
return new (PP) T(std::forward<Args>(ConstructorArgs)...);
+ static_assert(Size < AllocUnit, "");
addNode(AllocUnit);
Head->Used = Size;
return new (Head->Buf) T(std::forward<Args>(ConstructorArgs)...);
@@ -160,6 +156,8 @@
private:
SymbolNode *demangleEncodedSymbol(StringView &MangledName,
QualifiedNameNode *QN);
+ SymbolNode *demangleDeclarator(StringView &MangledName);
+ SymbolNode *demangleMD5Name(StringView &MangledName);
VariableSymbolNode *demangleVariableEncoding(StringView &MangledName,
StorageClass SC);
@@ -179,8 +177,9 @@
ArrayTypeNode *demangleArrayType(StringView &MangledName);
+ NodeArrayNode *demangleFunctionParameterList(StringView &MangledName,
+ bool &IsVariadic);
NodeArrayNode *demangleTemplateParameterList(StringView &MangledName);
- NodeArrayNode *demangleFunctionParameterList(StringView &MangledName);
std::pair<uint64_t, bool> demangleNumber(StringView &MangledName);
uint64_t demangleUnsigned(StringView &MangledName);
@@ -207,6 +206,8 @@
NamedIdentifierNode *demangleBackRefName(StringView &MangledName);
IdentifierNode *demangleTemplateInstantiationName(StringView &MangledName,
NameBackrefBehavior NBB);
+ IntrinsicFunctionKind
+ translateIntrinsicFunctionCode(char CH, FunctionIdentifierCodeGroup Group);
IdentifierNode *demangleFunctionIdentifierCode(StringView &MangledName);
IdentifierNode *
demangleFunctionIdentifierCode(StringView &MangledName,
@@ -223,7 +224,7 @@
demangleSpecialTableSymbolNode(StringView &MangledName,
SpecialIntrinsicKind SIK);
LocalStaticGuardVariableNode *
- demangleLocalStaticGuard(StringView &MangledName);
+ demangleLocalStaticGuard(StringView &MangledName, bool IsThread);
VariableSymbolNode *demangleUntypedVariable(ArenaAllocator &Arena,
StringView &MangledName,
StringView VariableName);
@@ -245,7 +246,7 @@
FuncClass demangleFunctionClass(StringView &MangledName);
CallingConv demangleCallingConvention(StringView &MangledName);
StorageClass demangleVariableStorageClass(StringView &MangledName);
- void demangleThrowSpecification(StringView &MangledName);
+ bool demangleThrowSpecification(StringView &MangledName);
wchar_t demangleWcharLiteral(StringView &MangledName);
uint8_t demangleCharLiteral(StringView &MangledName);
diff --git a/third_party/llvm/include/llvm/Demangle/MicrosoftDemangleNodes.h b/third_party/llvm/include/llvm/Demangle/MicrosoftDemangleNodes.h
index 1d0b66a..da9d9d5 100644
--- a/third_party/llvm/include/llvm/Demangle/MicrosoftDemangleNodes.h
+++ b/third_party/llvm/include/llvm/Demangle/MicrosoftDemangleNodes.h
@@ -1,11 +1,30 @@
+//===- MicrosoftDemangleNodes.h ---------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the AST nodes used in the MSVC demangler.
+//
+//===----------------------------------------------------------------------===//
+
#ifndef LLVM_SUPPORT_MICROSOFTDEMANGLENODES_H
#define LLVM_SUPPORT_MICROSOFTDEMANGLENODES_H
-#include "llvm/Demangle/Compiler.h"
+#include "llvm/Demangle/DemangleConfig.h"
#include "llvm/Demangle/StringView.h"
#include <array>
+namespace llvm {
+namespace itanium_demangle {
class OutputStream;
+}
+}
+
+using llvm::itanium_demangle::OutputStream;
+using llvm::itanium_demangle::StringView;
namespace llvm {
namespace ms_demangle {
@@ -53,6 +72,7 @@
enum OutputFlags {
OF_Default = 0,
OF_NoCallingConvention = 1,
+ OF_NoTagSpecifier = 2,
};
// Types
@@ -62,6 +82,7 @@
Char,
Schar,
Uchar,
+ Char8,
Char16,
Char32,
Short,
@@ -150,8 +171,8 @@
VectorCopyCtorIter, // ?__G vector copy constructor iterator
VectorVbaseCopyCtorIter, // ?__H vector vbase copy constructor iterator
ManVectorVbaseCopyCtorIter, // ?__I managed vector vbase copy constructor
- CoAwait, // ?__L co_await
- Spaceship, // operator<=>
+ CoAwait, // ?__L operator co_await
+ Spaceship, // ?__M operator<=>
MaxIntrinsic
};
@@ -235,6 +256,8 @@
virtual void output(OutputStream &OS, OutputFlags Flags) const = 0;
+ std::string toString(OutputFlags Flags = OF_Default) const;
+
private:
NodeKind Kind;
};
@@ -320,6 +343,9 @@
// Function parameters
NodeArrayNode *Params = nullptr;
+
+ // True if the function type is noexcept.
+ bool IsNoexcept = false;
};
struct IdentifierNode : public Node {
@@ -383,6 +409,7 @@
void output(OutputStream &OS, OutputFlags Flags) const override;
+ bool IsThread = false;
uint32_t ScopeIndex = 0;
};
@@ -488,7 +515,7 @@
void output(OutputStream &OS, OutputFlags Flags, StringView Separator) const;
- Node **Nodes = 0;
+ Node **Nodes = nullptr;
size_t Count = 0;
};
@@ -596,4 +623,4 @@
} // namespace ms_demangle
} // namespace llvm
-#endif
\ No newline at end of file
+#endif
diff --git a/third_party/llvm/include/llvm/Demangle/StringView.h b/third_party/llvm/include/llvm/Demangle/StringView.h
index a89deda..ceb6c79 100644
--- a/third_party/llvm/include/llvm/Demangle/StringView.h
+++ b/third_party/llvm/include/llvm/Demangle/StringView.h
@@ -1,22 +1,25 @@
//===--- StringView.h -------------------------------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+//===----------------------------------------------------------------------===//
//
+// FIXME: Use std::string_view instead when we support C++17.
//
-// This file contains a limited version of LLVM's StringView class. It is
-// copied here so that LLVMDemangle need not take a dependency on LLVMSupport.
//===----------------------------------------------------------------------===//
-#ifndef LLVM_DEMANGLE_STRINGVIEW_H
-#define LLVM_DEMANGLE_STRINGVIEW_H
+#ifndef DEMANGLE_STRINGVIEW_H
+#define DEMANGLE_STRINGVIEW_H
+#include "DemangleConfig.h"
#include <algorithm>
#include <cassert>
#include <cstring>
+DEMANGLE_NAMESPACE_BEGIN
+
class StringView {
const char *First;
const char *Last;
@@ -43,7 +46,7 @@
if (FindBegin < size()) {
// Just forward to memchr, which is faster than a hand-rolled loop.
if (const void *P = ::memchr(First + FindBegin, C, size() - FindBegin))
- return static_cast<const char *>(P) - First;
+ return size_t(static_cast<const char *>(P) - First);
}
return npos;
}
@@ -118,4 +121,6 @@
std::equal(LHS.begin(), LHS.end(), RHS.begin());
}
+DEMANGLE_NAMESPACE_END
+
#endif
diff --git a/third_party/llvm/include/llvm/Demangle/Utility.h b/third_party/llvm/include/llvm/Demangle/Utility.h
index 1d1601c..ec23859 100644
--- a/third_party/llvm/include/llvm/Demangle/Utility.h
+++ b/third_party/llvm/include/llvm/Demangle/Utility.h
@@ -1,25 +1,27 @@
//===--- Utility.h ----------------------------------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+//===----------------------------------------------------------------------===//
//
+// Provide some utility classes for use in the demangler(s).
//
-// This file contains several utility classes used by the demangle library.
//===----------------------------------------------------------------------===//
-#ifndef LLVM_DEMANGLE_UTILITY_H
-#define LLVM_DEMANGLE_UTILITY_H
+#ifndef DEMANGLE_UTILITY_H
+#define DEMANGLE_UTILITY_H
#include "StringView.h"
-
#include <cstdint>
#include <cstdlib>
#include <cstring>
#include <iterator>
#include <limits>
+DEMANGLE_NAMESPACE_BEGIN
+
// Stream that AST nodes write their string representation into after the AST
// has been parsed.
class OutputStream {
@@ -184,4 +186,6 @@
return true;
}
+DEMANGLE_NAMESPACE_END
+
#endif
diff --git a/third_party/llvm/lib/Demangle/Demangle.cpp b/third_party/llvm/lib/Demangle/Demangle.cpp
new file mode 100644
index 0000000..5f92153
--- /dev/null
+++ b/third_party/llvm/lib/Demangle/Demangle.cpp
@@ -0,0 +1,36 @@
+//===-- Demangle.cpp - Common demangling functions ------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file This file contains definitions of common demangling functions.
+///
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Demangle/Demangle.h"
+#include <cstdlib>
+
+static bool isItaniumEncoding(const std::string &MangledName) {
+ size_t Pos = MangledName.find_first_not_of('_');
+ // A valid Itanium encoding requires 1-4 leading underscores, followed by 'Z'.
+ return Pos > 0 && Pos <= 4 && MangledName[Pos] == 'Z';
+}
+
+std::string llvm::demangle(const std::string &MangledName) {
+ char *Demangled;
+ if (isItaniumEncoding(MangledName))
+ Demangled = itaniumDemangle(MangledName.c_str(), nullptr, nullptr, nullptr);
+ else
+ Demangled =
+ microsoftDemangle(MangledName.c_str(), nullptr, nullptr, nullptr);
+
+ if (!Demangled)
+ return MangledName;
+
+ std::string Ret = Demangled;
+ free(Demangled);
+ return Ret;
+}
diff --git a/third_party/llvm/lib/Demangle/ItaniumDemangle.cpp b/third_party/llvm/lib/Demangle/ItaniumDemangle.cpp
index e3bd3b8..5c99c70 100644
--- a/third_party/llvm/lib/Demangle/ItaniumDemangle.cpp
+++ b/third_party/llvm/lib/Demangle/ItaniumDemangle.cpp
@@ -1,9 +1,8 @@
//===------------------------- ItaniumDemangle.cpp ------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
@@ -356,15 +355,6 @@
return InternalStatus == demangle_success ? Buf : nullptr;
}
-bool llvm::itaniumFindTypesInMangledName(const char *MangledName, void *Ctx,
- void (*Callback)(void *,
- const char *)) {
- Demangler Parser(MangledName, MangledName + std::strlen(MangledName));
- Parser.TypeCallback = Callback;
- Parser.TypeCallbackContext = Ctx;
- return Parser.parse() == nullptr;
-}
-
ItaniumPartialDemangler::ItaniumPartialDemangler()
: RootNode(nullptr), Context(new Demangler{nullptr, nullptr}) {}
diff --git a/third_party/llvm/lib/Demangle/MicrosoftDemangle.cpp b/third_party/llvm/lib/Demangle/MicrosoftDemangle.cpp
index 4a45bfa..bf7d776 100644
--- a/third_party/llvm/lib/Demangle/MicrosoftDemangle.cpp
+++ b/third_party/llvm/lib/Demangle/MicrosoftDemangle.cpp
@@ -1,9 +1,8 @@
//===- MicrosoftDemangle.cpp ----------------------------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
@@ -18,7 +17,7 @@
#include "llvm/Demangle/Demangle.h"
#include "llvm/Demangle/MicrosoftDemangleNodes.h"
-#include "llvm/Demangle/Compiler.h"
+#include "llvm/Demangle/DemangleConfig.h"
#include "llvm/Demangle/StringView.h"
#include "llvm/Demangle/Utility.h"
@@ -40,7 +39,8 @@
NodeList *Next = nullptr;
};
-static bool isMemberPointer(StringView MangledName) {
+static bool isMemberPointer(StringView MangledName, bool &Error) {
+ Error = false;
switch (MangledName.popFront()) {
case '$':
// This is probably an rvalue reference (e.g. $$Q), and you cannot have an
@@ -58,13 +58,18 @@
// what.
break;
default:
- assert(false && "Ty is not a pointer type!");
+ // isMemberPointer() is called only if isPointerType() returns true,
+ // and it rejects other prefixes.
+ DEMANGLE_UNREACHABLE;
}
// If it starts with a number, then 6 indicates a non-member function
// pointer, and 8 indicates a member function pointer.
if (startsWithDigit(MangledName)) {
- assert(MangledName[0] == '6' || MangledName[0] == '8');
+ if (MangledName[0] != '6' && MangledName[0] != '8') {
+ Error = true;
+ return false;
+ }
return (MangledName[0] == '8');
}
@@ -74,7 +79,10 @@
MangledName.consumeFront('I'); // restrict
MangledName.consumeFront('F'); // unaligned
- assert(!MangledName.empty());
+ if (MangledName.empty()) {
+ Error = true;
+ return false;
+ }
// The next value should be either ABCD (non-member) or QRST (member).
switch (MangledName.front()) {
@@ -89,9 +97,9 @@
case 'T':
return true;
default:
- assert(false);
+ Error = true;
+ return false;
}
- return false;
}
static SpecialIntrinsicKind
@@ -134,8 +142,6 @@
static bool startsWithLocalScopePattern(StringView S) {
if (!S.consumeFront('?'))
return false;
- if (S.size() < 2)
- return false;
size_t End = S.find('?');
if (End == StringView::npos)
@@ -232,10 +238,10 @@
case 'S':
return std::make_pair(Qualifiers(Q_Const | Q_Volatile),
PointerAffinity::Pointer);
- default:
- assert(false && "Ty is not a pointer type!");
}
- return std::make_pair(Q_None, PointerAffinity::Pointer);
+ // This function is only called if isPointerType() returns true,
+ // and it only returns true for the six cases listed above.
+ DEMANGLE_UNREACHABLE;
}
StringView Demangler::copyString(StringView Borrowed) {
@@ -263,12 +269,16 @@
NI->Name = "`RTTI Complete Object Locator'";
break;
default:
- LLVM_BUILTIN_UNREACHABLE;
+ DEMANGLE_UNREACHABLE;
}
QualifiedNameNode *QN = demangleNameScopeChain(MangledName, NI);
SpecialTableSymbolNode *STSN = Arena.alloc<SpecialTableSymbolNode>();
STSN->Name = QN;
bool IsMember = false;
+ if (MangledName.empty()) {
+ Error = true;
+ return nullptr;
+ }
char Front = MangledName.popFront();
if (Front != '6' && Front != '7') {
Error = true;
@@ -282,9 +292,10 @@
}
LocalStaticGuardVariableNode *
-Demangler::demangleLocalStaticGuard(StringView &MangledName) {
+Demangler::demangleLocalStaticGuard(StringView &MangledName, bool IsThread) {
LocalStaticGuardIdentifierNode *LSGI =
Arena.alloc<LocalStaticGuardIdentifierNode>();
+ LSGI->IsThread = IsThread;
QualifiedNameNode *QN = demangleNameScopeChain(MangledName, LSGI);
LocalStaticGuardVariableNode *LSGVN =
Arena.alloc<LocalStaticGuardVariableNode>();
@@ -377,11 +388,11 @@
if (MangledName.consumeFront('?'))
IsKnownStaticDataMember = true;
- QualifiedNameNode *QN = demangleFullyQualifiedSymbolName(MangledName);
+ SymbolNode *Symbol = demangleDeclarator(MangledName);
+ if (Error)
+ return nullptr;
- SymbolNode *Symbol = demangleEncodedSymbol(MangledName, QN);
FunctionSymbolNode *FSN = nullptr;
- Symbol->Name = QN;
if (Symbol->kind() == NodeKind::VariableSymbol) {
DSIN->Variable = static_cast<VariableSymbolNode *>(Symbol);
@@ -399,7 +410,8 @@
}
FSN = demangleFunctionEncoding(MangledName);
- FSN->Name = synthesizeQualifiedName(Arena, DSIN);
+ if (FSN)
+ FSN->Name = synthesizeQualifiedName(Arena, DSIN);
} else {
if (IsKnownStaticDataMember) {
// This was supposed to be a static data member, but we got a function.
@@ -417,10 +429,10 @@
SymbolNode *Demangler::demangleSpecialIntrinsic(StringView &MangledName) {
SpecialIntrinsicKind SIK = consumeSpecialIntrinsicKind(MangledName);
- if (SIK == SpecialIntrinsicKind::None)
- return nullptr;
switch (SIK) {
+ case SpecialIntrinsicKind::None:
+ return nullptr;
case SpecialIntrinsicKind::StringLiteralSymbol:
return demangleStringLiteral(MangledName);
case SpecialIntrinsicKind::Vftable:
@@ -431,7 +443,9 @@
case SpecialIntrinsicKind::VcallThunk:
return demangleVcallThunkNode(MangledName);
case SpecialIntrinsicKind::LocalStaticGuard:
- return demangleLocalStaticGuard(MangledName);
+ return demangleLocalStaticGuard(MangledName, /*IsThread=*/false);
+ case SpecialIntrinsicKind::LocalStaticThreadGuard:
+ return demangleLocalStaticGuard(MangledName, /*IsThread=*/true);
case SpecialIntrinsicKind::RttiTypeDescriptor: {
TypeNode *T = demangleType(MangledName, QualifierMangleMode::Result);
if (Error)
@@ -451,11 +465,16 @@
case SpecialIntrinsicKind::RttiBaseClassDescriptor:
return demangleRttiBaseClassDescriptorNode(Arena, MangledName);
case SpecialIntrinsicKind::DynamicInitializer:
- return demangleInitFiniStub(MangledName, false);
+ return demangleInitFiniStub(MangledName, /*IsDestructor=*/false);
case SpecialIntrinsicKind::DynamicAtexitDestructor:
- return demangleInitFiniStub(MangledName, true);
- default:
+ return demangleInitFiniStub(MangledName, /*IsDestructor=*/true);
+ case SpecialIntrinsicKind::Typeof:
+ case SpecialIntrinsicKind::UdtReturning:
+ // It's unclear which tools produces these manglings, so demangling
+ // support is not (yet?) implemented.
break;
+ case SpecialIntrinsicKind::Unknown:
+ DEMANGLE_UNREACHABLE; // Never returned by consumeSpecialIntrinsicKind.
}
Error = true;
return nullptr;
@@ -465,11 +484,15 @@
Demangler::demangleFunctionIdentifierCode(StringView &MangledName) {
assert(MangledName.startsWith('?'));
MangledName = MangledName.dropFront();
+ if (MangledName.empty()) {
+ Error = true;
+ return nullptr;
+ }
if (MangledName.consumeFront("__"))
return demangleFunctionIdentifierCode(
MangledName, FunctionIdentifierCodeGroup::DoubleUnder);
- else if (MangledName.consumeFront("_"))
+ if (MangledName.consumeFront("_"))
return demangleFunctionIdentifierCode(MangledName,
FunctionIdentifierCodeGroup::Under);
return demangleFunctionIdentifierCode(MangledName,
@@ -495,16 +518,22 @@
Demangler::demangleLiteralOperatorIdentifier(StringView &MangledName) {
LiteralOperatorIdentifierNode *N =
Arena.alloc<LiteralOperatorIdentifierNode>();
- N->Name = demangleSimpleString(MangledName, false);
+ N->Name = demangleSimpleString(MangledName, /*Memorize=*/false);
return N;
}
-static IntrinsicFunctionKind
-translateIntrinsicFunctionCode(char CH, FunctionIdentifierCodeGroup Group) {
+IntrinsicFunctionKind
+Demangler::translateIntrinsicFunctionCode(char CH,
+ FunctionIdentifierCodeGroup Group) {
+ using IFK = IntrinsicFunctionKind;
+ if (!(CH >= '0' && CH <= '9') && !(CH >= 'A' && CH <= 'Z')) {
+ Error = true;
+ return IFK::None;
+ }
+
// Not all ? identifiers are intrinsics *functions*. This function only maps
// operator codes for the special functions, all others are handled elsewhere,
// hence the IFK::None entries in the table.
- using IFK = IntrinsicFunctionKind;
static IFK Basic[36] = {
IFK::None, // ?0 # Foo::Foo()
IFK::None, // ?1 # Foo::~Foo()
@@ -604,8 +633,8 @@
// iter
IFK::None, // ?__J local static thread guard
IFK::None, // ?__K operator ""_name
- IFK::CoAwait, // ?__L co_await
- IFK::None, // ?__M <unused>
+ IFK::CoAwait, // ?__L operator co_await
+ IFK::Spaceship, // ?__M operator<=>
IFK::None, // ?__N <unused>
IFK::None, // ?__O <unused>
IFK::None, // ?__P <unused>
@@ -630,12 +659,16 @@
case FunctionIdentifierCodeGroup::DoubleUnder:
return DoubleUnder[Index];
}
- LLVM_BUILTIN_UNREACHABLE;
+ DEMANGLE_UNREACHABLE;
}
IdentifierNode *
Demangler::demangleFunctionIdentifierCode(StringView &MangledName,
FunctionIdentifierCodeGroup Group) {
+ if (MangledName.empty()) {
+ Error = true;
+ return nullptr;
+ }
switch (Group) {
case FunctionIdentifierCodeGroup::Basic:
switch (char CH = MangledName.popFront()) {
@@ -648,7 +681,6 @@
return Arena.alloc<IntrinsicFunctionIdentifierNode>(
translateIntrinsicFunctionCode(CH, Group));
}
- break;
case FunctionIdentifierCodeGroup::Under:
return Arena.alloc<IntrinsicFunctionIdentifierNode>(
translateIntrinsicFunctionCode(MangledName.popFront(), Group));
@@ -661,13 +693,17 @@
translateIntrinsicFunctionCode(CH, Group));
}
}
- // No Mangling Yet: Spaceship, // operator<=>
- return nullptr;
+ DEMANGLE_UNREACHABLE;
}
SymbolNode *Demangler::demangleEncodedSymbol(StringView &MangledName,
QualifiedNameNode *Name) {
+ if (MangledName.empty()) {
+ Error = true;
+ return nullptr;
+ }
+
// Read a variable.
switch (MangledName.front()) {
case '0':
@@ -678,8 +714,6 @@
StorageClass SC = demangleVariableStorageClass(MangledName);
return demangleVariableEncoding(MangledName, SC);
}
- case '8':
- return nullptr;
}
FunctionSymbolNode *FSN = demangleFunctionEncoding(MangledName);
@@ -687,23 +721,74 @@
if (UQN->kind() == NodeKind::ConversionOperatorIdentifier) {
ConversionOperatorIdentifierNode *COIN =
static_cast<ConversionOperatorIdentifierNode *>(UQN);
- COIN->TargetType = FSN->Signature->ReturnType;
+ if (FSN)
+ COIN->TargetType = FSN->Signature->ReturnType;
}
return FSN;
}
+SymbolNode *Demangler::demangleDeclarator(StringView &MangledName) {
+ // What follows is a main symbol name. This may include namespaces or class
+ // back references.
+ QualifiedNameNode *QN = demangleFullyQualifiedSymbolName(MangledName);
+ if (Error)
+ return nullptr;
+
+ SymbolNode *Symbol = demangleEncodedSymbol(MangledName, QN);
+ if (Error)
+ return nullptr;
+ Symbol->Name = QN;
+
+ IdentifierNode *UQN = QN->getUnqualifiedIdentifier();
+ if (UQN->kind() == NodeKind::ConversionOperatorIdentifier) {
+ ConversionOperatorIdentifierNode *COIN =
+ static_cast<ConversionOperatorIdentifierNode *>(UQN);
+ if (!COIN->TargetType) {
+ Error = true;
+ return nullptr;
+ }
+ }
+ return Symbol;
+}
+
+SymbolNode *Demangler::demangleMD5Name(StringView &MangledName) {
+ assert(MangledName.startsWith("??@"));
+ // This is an MD5 mangled name. We can't demangle it, just return the
+ // mangled name.
+ // An MD5 mangled name is ??@ followed by 32 characters and a terminating @.
+ size_t MD5Last = MangledName.find('@', strlen("??@"));
+ if (MD5Last == StringView::npos) {
+ Error = true;
+ return nullptr;
+ }
+ const char *Start = MangledName.begin();
+ MangledName = MangledName.dropFront(MD5Last + 1);
+
+ // There are two additional special cases for MD5 names:
+ // 1. For complete object locators where the object name is long enough
+ // for the object to have an MD5 name, the complete object locator is
+ // called ??@...@??_R4@ (with a trailing "??_R4@" instead of the usual
+ // leading "??_R4". This is handled here.
+ // 2. For catchable types, in versions of MSVC before 2015 (<1900) or after
+ // 2017.2 (>= 1914), the catchable type mangling is _CT??@...@??@...@8
+ // instead of_CT??@...@8 with just one MD5 name. Since we don't yet
+ // demangle catchable types anywhere, this isn't handled for MD5 names
+ // either.
+ MangledName.consumeFront("??_R4@");
+
+ StringView MD5(Start, MangledName.begin());
+ SymbolNode *S = Arena.alloc<SymbolNode>(NodeKind::Md5Symbol);
+ S->Name = synthesizeQualifiedName(Arena, MD5);
+
+ return S;
+}
+
// Parser entry point.
SymbolNode *Demangler::parse(StringView &MangledName) {
- // We can't demangle MD5 names, just output them as-is.
- // Also, MSVC-style mangled symbols must start with '?'.
- if (MangledName.startsWith("??@")) {
- // This is an MD5 mangled name. We can't demangle it, just return the
- // mangled name.
- SymbolNode *S = Arena.alloc<SymbolNode>(NodeKind::Md5Symbol);
- S->Name = synthesizeQualifiedName(Arena, MangledName);
- return S;
- }
+ if (MangledName.startsWith("??@"))
+ return demangleMD5Name(MangledName);
+ // MSVC-style mangled symbols must start with '?'.
if (!MangledName.startsWith('?')) {
Error = true;
return nullptr;
@@ -716,21 +801,7 @@
if (SymbolNode *SI = demangleSpecialIntrinsic(MangledName))
return SI;
- // What follows is a main symbol name. This may include namespaces or class
- // back references.
- QualifiedNameNode *QN = demangleFullyQualifiedSymbolName(MangledName);
- if (Error)
- return nullptr;
-
- SymbolNode *Symbol = demangleEncodedSymbol(MangledName, QN);
- if (Symbol) {
- Symbol->Name = QN;
- }
-
- if (Error)
- return nullptr;
-
- return Symbol;
+ return demangleDeclarator(MangledName);
}
TagTypeNode *Demangler::parseTagUniqueName(StringView &MangledName) {
@@ -757,6 +828,9 @@
VSN->Type = demangleType(MangledName, QualifierMangleMode::Drop);
VSN->SC = SC;
+ if (Error)
+ return nullptr;
+
// <variable-type> ::= <type> <cvr-qualifiers>
// ::= <type> <pointee-cvr-qualifiers> # pointers, references
switch (VSN->Type->kind()) {
@@ -795,7 +869,7 @@
// <number> ::= [?] <non-negative integer>
//
// <non-negative integer> ::= <decimal digit> # when 1 <= Number <= 10
-// ::= <hex digit>+ @ # when Numbrer == 0 or >= 10
+// ::= <hex digit>+ @ # when Number == 0 or >= 10
//
// <hex-digit> ::= [A-P] # A = 0, B = 1, ...
std::pair<uint64_t, bool> Demangler::demangleNumber(StringView &MangledName) {
@@ -904,8 +978,18 @@
if (Error)
return nullptr;
- if (NBB & NBB_Template)
+ if (NBB & NBB_Template) {
+ // NBB_Template is only set for types and non-leaf names ("a::" in "a::b").
+ // Structors and conversion operators only makes sense in a leaf name, so
+ // reject them in NBB_Template contexts.
+ if (Identifier->kind() == NodeKind::ConversionOperatorIdentifier ||
+ Identifier->kind() == NodeKind::StructorIdentifier) {
+ Error = true;
+ return nullptr;
+ }
+
memorizeIdentifier(Identifier);
+ }
return Identifier;
}
@@ -929,6 +1013,7 @@
}
uint8_t Demangler::demangleCharLiteral(StringView &MangledName) {
+ assert(!MangledName.empty());
if (!MangledName.startsWith('?'))
return MangledName.popFront();
@@ -986,7 +1071,7 @@
uint8_t C1, C2;
C1 = demangleCharLiteral(MangledName);
- if (Error)
+ if (Error || MangledName.empty())
goto WCharLiteralError;
C2 = demangleCharLiteral(MangledName);
if (Error)
@@ -1005,10 +1090,8 @@
}
static void outputHex(OutputStream &OS, unsigned C) {
- if (C == 0) {
- OS << "\\x00";
- return;
- }
+ assert (C != 0);
+
// It's easier to do the math if we can work from right to left, but we need
// to print the numbers from left to right. So render this into a temporary
// buffer first, then output the temporary buffer. Each byte is of the form
@@ -1017,23 +1100,26 @@
char TempBuffer[17];
::memset(TempBuffer, 0, sizeof(TempBuffer));
- constexpr int MaxPos = 15;
+ constexpr int MaxPos = sizeof(TempBuffer) - 1;
- int Pos = MaxPos - 1;
+ int Pos = MaxPos - 1; // TempBuffer[MaxPos] is the terminating \0.
while (C != 0) {
for (int I = 0; I < 2; ++I) {
writeHexDigit(&TempBuffer[Pos--], C % 16);
C /= 16;
}
- TempBuffer[Pos--] = 'x';
- TempBuffer[Pos--] = '\\';
- assert(Pos >= 0);
}
+ TempBuffer[Pos--] = 'x';
+ assert(Pos >= 0);
+ TempBuffer[Pos--] = '\\';
OS << StringView(&TempBuffer[Pos + 1]);
}
static void outputEscapedChar(OutputStream &OS, unsigned C) {
switch (C) {
+ case '\0': // nul
+ OS << "\\0";
+ return;
case '\'': // single quote
OS << "\\\'";
return;
@@ -1098,8 +1184,11 @@
return Result;
}
+// A mangled (non-wide) string literal stores the total length of the string it
+// refers to (passed in NumBytes), and it contains up to 32 bytes of actual text
+// (passed in StringBytes, NumChars).
static unsigned guessCharByteSize(const uint8_t *StringBytes, unsigned NumChars,
- unsigned NumBytes) {
+ uint64_t NumBytes) {
assert(NumBytes > 0);
// If the number of bytes is odd, this is guaranteed to be a char string.
@@ -1111,7 +1200,7 @@
// 2-byte, or 4-byte null terminator.
if (NumBytes < 32) {
unsigned TrailingNulls = countTrailingNullBytes(StringBytes, NumChars);
- if (TrailingNulls >= 4)
+ if (TrailingNulls >= 4 && NumBytes % 4 == 0)
return 4;
if (TrailingNulls >= 2)
return 2;
@@ -1125,7 +1214,7 @@
// perfect and is biased towards languages that have ascii alphabets, but this
// was always going to be best effort since the encoding is lossy.
unsigned Nulls = countEmbeddedNulls(StringBytes, NumChars);
- if (Nulls >= 2 * NumChars / 3)
+ if (Nulls >= 2 * NumChars / 3 && NumBytes % 4 == 0)
return 4;
if (Nulls >= NumChars / 3)
return 2;
@@ -1176,6 +1265,11 @@
EncodedStringLiteralNode *Result = Arena.alloc<EncodedStringLiteralNode>();
+ // Must happen before the first `goto StringLiteralError`.
+ if (!initializeOutputStream(nullptr, nullptr, OS, 1024))
+ // FIXME: Propagate out-of-memory as an error?
+ std::terminate();
+
// Prefix indicating the beginning of a string literal
if (!MangledName.consumeFront("@_"))
goto StringLiteralError;
@@ -1186,7 +1280,7 @@
switch (MangledName.popFront()) {
case '1':
IsWcharT = true;
- LLVM_FALLTHROUGH;
+ DEMANGLE_FALLTHROUGH;
case '0':
break;
default:
@@ -1195,7 +1289,7 @@
// Encoded Length
std::tie(StringByteSize, IsNegative) = demangleNumber(MangledName);
- if (Error || IsNegative)
+ if (Error || IsNegative || StringByteSize < (IsWcharT ? 2 : 1))
goto StringLiteralError;
// CRC 32 (always 8 characters plus a terminator)
@@ -1207,16 +1301,14 @@
if (MangledName.empty())
goto StringLiteralError;
- if (!initializeOutputStream(nullptr, nullptr, OS, 1024))
- // FIXME: Propagate out-of-memory as an error?
- std::terminate();
if (IsWcharT) {
Result->Char = CharKind::Wchar;
if (StringByteSize > 64)
Result->IsTruncated = true;
while (!MangledName.consumeFront('@')) {
- assert(StringByteSize >= 2);
+ if (MangledName.size() < 2)
+ goto StringLiteralError;
wchar_t W = demangleWcharLiteral(MangledName);
if (StringByteSize != 2 || Result->IsTruncated)
outputEscapedChar(OS, W);
@@ -1232,7 +1324,8 @@
unsigned BytesDecoded = 0;
while (!MangledName.consumeFront('@')) {
- assert(StringByteSize >= 1);
+ if (MangledName.size() < 1 || BytesDecoded >= MaxStringByteLength)
+ goto StringLiteralError;
StringBytes[BytesDecoded++] = demangleCharLiteral(MangledName);
}
@@ -1253,7 +1346,7 @@
Result->Char = CharKind::Char32;
break;
default:
- LLVM_BUILTIN_UNREACHABLE;
+ DEMANGLE_UNREACHABLE;
}
const unsigned NumChars = BytesDecoded / CharBytes;
for (unsigned CharIndex = 0; CharIndex < NumChars; ++CharIndex) {
@@ -1272,15 +1365,20 @@
StringLiteralError:
Error = true;
+ std::free(OS.getBuffer());
return nullptr;
}
+// Returns MangledName's prefix before the first '@', or an error if
+// MangledName contains no '@' or the prefix has length 0.
StringView Demangler::demangleSimpleString(StringView &MangledName,
bool Memorize) {
StringView S;
for (size_t i = 0; i < MangledName.size(); ++i) {
if (MangledName[i] != '@')
continue;
+ if (i == 0)
+ break;
S = MangledName.substr(0, i);
MangledName = MangledName.dropFront(i + 1);
@@ -1317,8 +1415,10 @@
NamedIdentifierNode *Identifier = Arena.alloc<NamedIdentifierNode>();
MangledName.consumeFront('?');
- auto Number = demangleNumber(MangledName);
- assert(!Number.second);
+ uint64_t Number = 0;
+ bool IsNegative = false;
+ std::tie(Number, IsNegative) = demangleNumber(MangledName);
+ assert(!IsNegative);
// One ? to terminate the number
MangledName.consumeFront('?');
@@ -1336,7 +1436,7 @@
OS << '`';
Scope->output(OS, OF_Default);
OS << '\'';
- OS << "::`" << Number.first << "'";
+ OS << "::`" << Number << "'";
OS << '\0';
char *Result = OS.getBuffer();
Identifier->Name = copyString(Result);
@@ -1347,7 +1447,8 @@
// Parses a type name in the form of A@B@C@@ which represents C::B::A.
QualifiedNameNode *
Demangler::demangleFullyQualifiedTypeName(StringView &MangledName) {
- IdentifierNode *Identifier = demangleUnqualifiedTypeName(MangledName, true);
+ IdentifierNode *Identifier =
+ demangleUnqualifiedTypeName(MangledName, /*Memorize=*/true);
if (Error)
return nullptr;
assert(Identifier);
@@ -1379,9 +1480,12 @@
return nullptr;
if (Identifier->kind() == NodeKind::StructorIdentifier) {
+ if (QN->Components->Count < 2) {
+ Error = true;
+ return nullptr;
+ }
StructorIdentifierNode *SIN =
static_cast<StructorIdentifierNode *>(Identifier);
- assert(QN->Components->Count >= 2);
Node *ClassNode = QN->Components->Nodes[QN->Components->Count - 2];
SIN->Class = static_cast<IdentifierNode *>(ClassNode);
}
@@ -1413,7 +1517,7 @@
return demangleTemplateInstantiationName(MangledName, NBB);
if (MangledName.startsWith('?'))
return demangleFunctionIdentifierCode(MangledName);
- return demangleSimpleName(MangledName, (NBB & NBB_Simple) != 0);
+ return demangleSimpleName(MangledName, /*Memorize=*/(NBB & NBB_Simple) != 0);
}
IdentifierNode *Demangler::demangleNameScopePiece(StringView &MangledName) {
@@ -1429,7 +1533,7 @@
if (startsWithLocalScopePattern(MangledName))
return demangleLocallyScopedNamePiece(MangledName);
- return demangleSimpleName(MangledName, true);
+ return demangleSimpleName(MangledName, /*Memorize=*/true);
}
static NodeArrayNode *nodeListToNodeArray(ArenaAllocator &Arena, NodeList *Head,
@@ -1487,11 +1591,11 @@
case 'C':
return FuncClass(FC_Private | FC_Static);
case 'D':
- return FuncClass(FC_Private | FC_Static);
+ return FuncClass(FC_Private | FC_Static | FC_Far);
case 'E':
return FuncClass(FC_Private | FC_Virtual);
case 'F':
- return FuncClass(FC_Private | FC_Virtual);
+ return FuncClass(FC_Private | FC_Virtual | FC_Far);
case 'G':
return FuncClass(FC_Private | FC_StaticThisAdjust);
case 'H':
@@ -1536,7 +1640,8 @@
FuncClass VFlag = FC_VirtualThisAdjust;
if (MangledName.consumeFront('R'))
VFlag = FuncClass(VFlag | FC_VirtualThisAdjustEx);
-
+ if (MangledName.empty())
+ break;
switch (MangledName.popFront()) {
case '0':
return FuncClass(FC_Private | FC_Virtual | VFlag);
@@ -1559,6 +1664,11 @@
}
CallingConv Demangler::demangleCallingConvention(StringView &MangledName) {
+ if (MangledName.empty()) {
+ Error = true;
+ return CallingConv::None;
+ }
+
switch (MangledName.popFront()) {
case 'A':
case 'B':
@@ -1589,7 +1699,7 @@
}
StorageClass Demangler::demangleVariableStorageClass(StringView &MangledName) {
- assert(std::isdigit(MangledName.front()));
+ assert(MangledName.front() >= '0' && MangledName.front() <= '4');
switch (MangledName.popFront()) {
case '0':
@@ -1603,12 +1713,15 @@
case '4':
return StorageClass::FunctionLocalStatic;
}
- Error = true;
- return StorageClass::None;
+ DEMANGLE_UNREACHABLE;
}
std::pair<Qualifiers, bool>
Demangler::demangleQualifiers(StringView &MangledName) {
+ if (MangledName.empty()) {
+ Error = true;
+ return std::make_pair(Q_None, false);
+ }
switch (MangledName.popFront()) {
// Member qualifiers
@@ -1647,14 +1760,21 @@
std::tie(Quals, IsMember) = demangleQualifiers(MangledName);
}
+ if (MangledName.empty()) {
+ Error = true;
+ return nullptr;
+ }
+
TypeNode *Ty = nullptr;
if (isTagType(MangledName))
Ty = demangleClassType(MangledName);
else if (isPointerType(MangledName)) {
- if (isMemberPointer(MangledName))
+ if (isMemberPointer(MangledName, Error))
Ty = demangleMemberPointerType(MangledName);
- else
+ else if (!Error)
Ty = demanglePointerType(MangledName);
+ else
+ return nullptr;
} else if (isArrayType(MangledName))
Ty = demangleArrayType(MangledName);
else if (isFunctionType(MangledName)) {
@@ -1669,19 +1789,22 @@
Ty = demangleCustomType(MangledName);
} else {
Ty = demanglePrimitiveType(MangledName);
- if (!Ty || Error)
- return Ty;
}
+ if (!Ty || Error)
+ return Ty;
Ty->Quals = Qualifiers(Ty->Quals | Quals);
return Ty;
}
-void Demangler::demangleThrowSpecification(StringView &MangledName) {
+bool Demangler::demangleThrowSpecification(StringView &MangledName) {
+ if (MangledName.consumeFront("_E"))
+ return true;
if (MangledName.consumeFront('Z'))
- return;
+ return false;
Error = true;
+ return false;
}
FunctionSignatureNode *Demangler::demangleFunctionType(StringView &MangledName,
@@ -1703,9 +1826,9 @@
if (!IsStructor)
FTy->ReturnType = demangleType(MangledName, QualifierMangleMode::Result);
- FTy->Params = demangleFunctionParameterList(MangledName);
+ FTy->Params = demangleFunctionParameterList(MangledName, FTy->IsVariadic);
- demangleThrowSpecification(MangledName);
+ FTy->IsNoexcept = demangleThrowSpecification(MangledName);
return FTy;
}
@@ -1716,6 +1839,11 @@
if (MangledName.consumeFront("$$J0"))
ExtraFlags = FC_ExternC;
+ if (MangledName.empty()) {
+ Error = true;
+ return nullptr;
+ }
+
FuncClass FC = demangleFunctionClass(MangledName);
FC = FuncClass(ExtraFlags | FC);
@@ -1743,6 +1871,10 @@
bool HasThisQuals = !(FC & (FC_Global | FC_Static));
FSN = demangleFunctionType(MangledName, HasThisQuals);
}
+
+ if (Error)
+ return nullptr;
+
if (TTN) {
*static_cast<FunctionSignatureNode *>(TTN) = *FSN;
FSN = TTN;
@@ -1759,7 +1891,7 @@
MangledName.popFront();
CustomTypeNode *CTN = Arena.alloc<CustomTypeNode>();
- CTN->Identifier = demangleUnqualifiedTypeName(MangledName, true);
+ CTN->Identifier = demangleUnqualifiedTypeName(MangledName, /*Memorize=*/true);
if (!MangledName.consumeFront('@'))
Error = true;
if (Error)
@@ -1813,6 +1945,8 @@
return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Uint64);
case 'W':
return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Wchar);
+ case 'Q':
+ return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Char8);
case 'S':
return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Char16);
case 'U':
@@ -1839,7 +1973,7 @@
TT = Arena.alloc<TagTypeNode>(TagKind::Class);
break;
case 'W':
- if (MangledName.popFront() != '4') {
+ if (!MangledName.consumeFront('4')) {
Error = true;
return nullptr;
}
@@ -1883,6 +2017,8 @@
Qualifiers ExtQuals = demanglePointerExtQualifiers(MangledName);
Pointer->Quals = Qualifiers(Pointer->Quals | ExtQuals);
+ // isMemberPointer() only returns true if there is at least one character
+ // after the qualifiers.
if (MangledName.consumeFront("8")) {
Pointer->ClassParent = demangleFullyQualifiedTypeName(MangledName);
Pointer->Pointee = demangleFunctionType(MangledName, true);
@@ -1890,11 +2026,12 @@
Qualifiers PointeeQuals = Q_None;
bool IsMember = false;
std::tie(PointeeQuals, IsMember) = demangleQualifiers(MangledName);
- assert(IsMember);
+ assert(IsMember || Error);
Pointer->ClassParent = demangleFullyQualifiedTypeName(MangledName);
Pointer->Pointee = demangleType(MangledName, QualifierMangleMode::Drop);
- Pointer->Pointee->Quals = PointeeQuals;
+ if (Pointer->Pointee)
+ Pointer->Pointee->Quals = PointeeQuals;
}
return Pointer;
@@ -1931,7 +2068,7 @@
for (uint64_t I = 0; I < Rank; ++I) {
uint64_t D = 0;
std::tie(D, IsNegative) = demangleNumber(MangledName);
- if (IsNegative) {
+ if (Error || IsNegative) {
Error = true;
return nullptr;
}
@@ -1956,12 +2093,12 @@
return ATy;
}
-// Reads a function or a template parameters.
-NodeArrayNode *
-Demangler::demangleFunctionParameterList(StringView &MangledName) {
+// Reads a function's parameters.
+NodeArrayNode *Demangler::demangleFunctionParameterList(StringView &MangledName,
+ bool &IsVariadic) {
// Empty parameter list.
if (MangledName.consumeFront('X'))
- return {};
+ return nullptr;
NodeList *Head = Arena.alloc<NodeList>();
NodeList **Current = &Head;
@@ -1974,7 +2111,7 @@
size_t N = MangledName[0] - '0';
if (N >= Backrefs.FunctionParamCount) {
Error = true;
- return {};
+ return nullptr;
}
MangledName = MangledName.dropFront();
@@ -1988,6 +2125,8 @@
*Current = Arena.alloc<NodeList>();
TypeNode *TN = demangleType(MangledName, QualifierMangleMode::Drop);
+ if (!TN || Error)
+ return nullptr;
(*Current)->N = TN;
@@ -2003,7 +2142,7 @@
}
if (Error)
- return {};
+ return nullptr;
NodeArrayNode *NA = nodeListToNodeArray(Arena, Head, Count);
// A non-empty parameter list is terminated by either 'Z' (variadic) parameter
@@ -2013,13 +2152,11 @@
return NA;
if (MangledName.consumeFront('Z')) {
- // This is a variadic parameter list. We probably need a variadic node to
- // append to the end.
+ IsVariadic = true;
return NA;
}
- Error = true;
- return {};
+ DEMANGLE_UNREACHABLE;
}
NodeArrayNode *
@@ -2028,7 +2165,7 @@
NodeList **Current = &Head;
size_t Count = 0;
- while (!Error && !MangledName.startsWith('@')) {
+ while (!MangledName.startsWith('@')) {
if (MangledName.consumeFront("$S") || MangledName.consumeFront("$$V") ||
MangledName.consumeFront("$$$V") || MangledName.consumeFront("$$Z")) {
// parameter pack separator
@@ -2061,12 +2198,16 @@
MangledName = MangledName.dropFront();
// 1 - single inheritance <name>
// H - multiple inheritance <name> <number>
- // I - virtual inheritance <name> <number> <number> <number>
+ // I - virtual inheritance <name> <number> <number>
// J - unspecified inheritance <name> <number> <number> <number>
char InheritanceSpecifier = MangledName.popFront();
SymbolNode *S = nullptr;
if (MangledName.startsWith('?')) {
S = parse(MangledName);
+ if (Error || !S->Name) {
+ Error = true;
+ return nullptr;
+ }
memorizeIdentifier(S->Name->getUnqualifiedIdentifier());
}
@@ -2074,20 +2215,19 @@
case 'J':
TPRN->ThunkOffsets[TPRN->ThunkOffsetCount++] =
demangleSigned(MangledName);
- LLVM_FALLTHROUGH;
+ DEMANGLE_FALLTHROUGH;
case 'I':
TPRN->ThunkOffsets[TPRN->ThunkOffsetCount++] =
demangleSigned(MangledName);
- LLVM_FALLTHROUGH;
+ DEMANGLE_FALLTHROUGH;
case 'H':
TPRN->ThunkOffsets[TPRN->ThunkOffsetCount++] =
demangleSigned(MangledName);
- LLVM_FALLTHROUGH;
+ DEMANGLE_FALLTHROUGH;
case '1':
break;
default:
- Error = true;
- break;
+ DEMANGLE_UNREACHABLE;
}
TPRN->Affinity = PointerAffinity::Pointer;
TPRN->Symbol = S;
@@ -2108,18 +2248,15 @@
case 'G':
TPRN->ThunkOffsets[TPRN->ThunkOffsetCount++] =
demangleSigned(MangledName);
- LLVM_FALLTHROUGH;
+ DEMANGLE_FALLTHROUGH;
case 'F':
TPRN->ThunkOffsets[TPRN->ThunkOffsetCount++] =
demangleSigned(MangledName);
TPRN->ThunkOffsets[TPRN->ThunkOffsetCount++] =
demangleSigned(MangledName);
- LLVM_FALLTHROUGH;
- case '0':
break;
default:
- Error = true;
- break;
+ DEMANGLE_UNREACHABLE;
}
TPRN->IsMemberPointer = true;
@@ -2139,15 +2276,14 @@
Current = &TP.Next;
}
- if (Error)
- return nullptr;
+ // The loop above returns nullptr on Error.
+ assert(!Error);
// Template parameter lists cannot be variadic, so it can only be terminated
- // by @.
- if (MangledName.consumeFront('@'))
- return nodeListToNodeArray(Arena, Head, Count);
- Error = true;
- return nullptr;
+ // by @ (as opposed to 'Z' in the function parameter case).
+ assert(MangledName.startsWith('@')); // The above loop exits only on '@'.
+ MangledName.consumeFront('@');
+ return nodeListToNodeArray(Arena, Head, Count);
}
void Demangler::dumpBackReferences() {
diff --git a/third_party/llvm/lib/Demangle/MicrosoftDemangleNodes.cpp b/third_party/llvm/lib/Demangle/MicrosoftDemangleNodes.cpp
index c57f0cf..63ca475 100644
--- a/third_party/llvm/lib/Demangle/MicrosoftDemangleNodes.cpp
+++ b/third_party/llvm/lib/Demangle/MicrosoftDemangleNodes.cpp
@@ -1,9 +1,8 @@
//===- MicrosoftDemangle.cpp ----------------------------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
@@ -12,9 +11,10 @@
//===----------------------------------------------------------------------===//
#include "llvm/Demangle/MicrosoftDemangleNodes.h"
-#include "llvm/Demangle/Compiler.h"
+#include "llvm/Demangle/DemangleConfig.h"
#include "llvm/Demangle/Utility.h"
#include <cctype>
+#include <string>
using namespace llvm;
using namespace ms_demangle;
@@ -34,21 +34,20 @@
OS << " ";
}
-static bool outputSingleQualifier(OutputStream &OS, Qualifiers Q) {
+static void outputSingleQualifier(OutputStream &OS, Qualifiers Q) {
switch (Q) {
case Q_Const:
OS << "const";
- return true;
+ break;
case Q_Volatile:
OS << "volatile";
- return true;
+ break;
case Q_Restrict:
OS << "__restrict";
- return true;
+ break;
default:
break;
}
- return false;
}
static bool outputQualifierIfPresent(OutputStream &OS, Qualifiers Q,
@@ -113,6 +112,14 @@
}
}
+std::string Node::toString(OutputFlags Flags) const {
+ OutputStream OS;
+ initializeOutputStream(nullptr, nullptr, OS, 1024);
+ this->output(OS, Flags);
+ OS << '\0';
+ return {OS.getBuffer()};
+}
+
void TypeNode::outputQuals(bool SpaceBefore, bool SpaceAfter) const {}
void PrimitiveTypeNode::outputPre(OutputStream &OS, OutputFlags Flags) const {
@@ -122,6 +129,7 @@
OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Char, "char");
OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Schar, "signed char");
OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Uchar, "unsigned char");
+ OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Char8, "char8_t");
OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Char16, "char16_t");
OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Char32, "char32_t");
OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Short, "short");
@@ -329,8 +337,9 @@
"`vector vbase copy constructor iterator'");
OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, ManVectorVbaseCopyCtorIter,
"`managed vector vbase copy constructor iterator'");
- OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, CoAwait, "co_await");
- OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Spaceship, "operator <=>");
+ OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, CoAwait,
+ "operator co_await");
+ OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Spaceship, "operator<=>");
case IntrinsicFunctionKind::MaxIntrinsic:
case IntrinsicFunctionKind::None:
break;
@@ -340,7 +349,10 @@
void LocalStaticGuardIdentifierNode::output(OutputStream &OS,
OutputFlags Flags) const {
- OS << "`local static guard'";
+ if (IsThread)
+ OS << "`local static thread guard'";
+ else
+ OS << "`local static guard'";
if (ScopeIndex > 0)
OS << "{" << ScopeIndex << "}";
}
@@ -402,6 +414,12 @@
Params->output(OS, Flags);
else
OS << "void";
+
+ if (IsVariadic) {
+ if (OS.back() != '(')
+ OS << ", ";
+ OS << "...";
+ }
OS << ")";
}
@@ -414,6 +432,9 @@
if (Quals & Q_Unaligned)
OS << " __unaligned";
+ if (IsNoexcept)
+ OS << " noexcept";
+
if (RefQualifier == FunctionRefQualifier::Reference)
OS << " &";
else if (RefQualifier == FunctionRefQualifier::RValueReference)
@@ -501,13 +522,15 @@
}
void TagTypeNode::outputPre(OutputStream &OS, OutputFlags Flags) const {
- switch (Tag) {
- OUTPUT_ENUM_CLASS_VALUE(TagKind, Class, "class");
- OUTPUT_ENUM_CLASS_VALUE(TagKind, Struct, "struct");
- OUTPUT_ENUM_CLASS_VALUE(TagKind, Union, "union");
- OUTPUT_ENUM_CLASS_VALUE(TagKind, Enum, "enum");
+ if (!(Flags & OF_NoTagSpecifier)) {
+ switch (Tag) {
+ OUTPUT_ENUM_CLASS_VALUE(TagKind, Class, "class");
+ OUTPUT_ENUM_CLASS_VALUE(TagKind, Struct, "struct");
+ OUTPUT_ENUM_CLASS_VALUE(TagKind, Union, "union");
+ OUTPUT_ENUM_CLASS_VALUE(TagKind, Enum, "enum");
+ }
+ OS << " ";
}
- OS << " ";
QualifiedName->output(OS, Flags);
outputQualifiers(OS, Quals, true, false);
}