├── go.mod ├── README.md ├── .gitignore ├── ast_test.go ├── LICENSE ├── rust_expected_test.go ├── c++filt.go ├── expected_test.go ├── testdata ├── rust-demangle-expected ├── rust.test └── demangle-expected ├── rust.go └── demangle_test.go /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/ianlancetaylor/demangle 2 | 3 | go 1.12 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # github.com/ianlancetaylor/demangle 2 | 3 | A Go package that can be used to demangle C++ and Rust symbol names. 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | *.a 3 | *.so 4 | ._* 5 | .nfs.* 6 | a.out 7 | *~ 8 | *.orig 9 | *.rej 10 | *.exe 11 | .*.swp 12 | core 13 | demangle.test 14 | -------------------------------------------------------------------------------- /ast_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package demangle 6 | 7 | import ( 8 | "fmt" 9 | "testing" 10 | ) 11 | 12 | func TestASTToString(t *testing.T) { 13 | var tests = []struct { 14 | input AST 15 | want string 16 | formatted string 17 | }{ 18 | { 19 | &Qualified{Scope: &Name{Name: "s"}, Name: &Name{Name: "C"}}, 20 | "s::C", 21 | `Qualified: 22 | Scope: s 23 | Name: C`, 24 | }, 25 | { 26 | &Typed{Name: &Name{Name: "v"}, Type: &BuiltinType{"int"}}, 27 | "int v", 28 | `Typed: 29 | Name: v 30 | Type: BuiltinType: int`, 31 | }, 32 | } 33 | 34 | for i, test := range tests { 35 | if got := ASTToString(test.input); got != test.want { 36 | t.Errorf("ASTToString of test %d == %s, want %s", i, test.input, test.want) 37 | } 38 | if got := fmt.Sprintf("%#v", test.input); got != test.formatted { 39 | t.Errorf("Formatted test %d == %s, want %s", i, got, test.formatted) 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015 The Go Authors. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are 5 | met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above 10 | copyright notice, this list of conditions and the following disclaimer 11 | in the documentation and/or other materials provided with the 12 | distribution. 13 | * Neither the name of Google Inc. nor the names of its 14 | contributors may be used to endorse or promote products derived from 15 | this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /rust_expected_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package demangle 6 | 7 | import ( 8 | "bufio" 9 | "fmt" 10 | "os" 11 | "strings" 12 | "testing" 13 | ) 14 | 15 | const rustFilename = "testdata/rust-demangle-expected" 16 | 17 | // TestRustExpected is like TestExpected, but for Rust demangling. 18 | // We ignore all test inputs that do not start with _R. 19 | func TestRustExpected(t *testing.T) { 20 | t.Parallel() 21 | f, err := os.Open(rustFilename) 22 | if err != nil { 23 | t.Fatal(err) 24 | } 25 | scanner := bufio.NewScanner(f) 26 | lineno := 1 27 | for { 28 | format, got := getOptLine(t, scanner, &lineno) 29 | if !got { 30 | break 31 | } 32 | report := lineno 33 | input := getLine(t, scanner, &lineno) 34 | expect := getLine(t, scanner, &lineno) 35 | 36 | skip := false 37 | if len(format) > 0 && format[0] == '-' { 38 | for _, arg := range strings.Fields(format) { 39 | switch arg { 40 | case "--format=gnu-v3": 41 | skip = true 42 | case "--format=auto": 43 | case "--format=rust": 44 | default: 45 | t.Errorf("%s:%d: unrecognized argument %s", rustFilename, report, arg) 46 | } 47 | } 48 | } 49 | 50 | if skip { 51 | continue 52 | } 53 | 54 | oneRustTest(t, report, input, expect) 55 | } 56 | if err := scanner.Err(); err != nil { 57 | t.Error(err) 58 | } 59 | } 60 | 61 | // oneRustTest tests one entry from rust-demangle-expected. 62 | func oneRustTest(t *testing.T, report int, input, expect string) { 63 | if *verbose { 64 | fmt.Println(input) 65 | } 66 | 67 | s, err := ToString(input) 68 | if err != nil { 69 | if err != ErrNotMangledName { 70 | if input == expect { 71 | return 72 | } 73 | t.Errorf("%s:%d: %v", rustFilename, report, err) 74 | return 75 | } 76 | s = input 77 | } 78 | 79 | if s != expect { 80 | t.Errorf("%s:%d: got %q, want %q", rustFilename, report, s, expect) 81 | } 82 | } 83 | 84 | const rustCheckFilename = "testdata/rust.test" 85 | 86 | func TestRustCheck(t *testing.T) { 87 | t.Parallel() 88 | f, err := os.Open(rustCheckFilename) 89 | if err != nil { 90 | t.Fatal(err) 91 | } 92 | scanner := bufio.NewScanner(f) 93 | lineno := 1 94 | for scanner.Scan() { 95 | report := lineno 96 | line := strings.TrimSpace(scanner.Text()) 97 | lineno++ 98 | if !strings.HasPrefix(line, "CHECK: ") { 99 | continue 100 | } 101 | want := strings.TrimPrefix(line, "CHECK: ") 102 | if !scanner.Scan() { 103 | t.Fatalf("%s:%d: unexpected EOF", rustCheckFilename, report) 104 | } 105 | lineno++ 106 | input := strings.TrimSpace(scanner.Text()) 107 | 108 | got, err := ToString(input) 109 | if err != nil { 110 | if want != input { 111 | t.Errorf("%s:%d: %v", rustCheckFilename, report, err) 112 | } 113 | } else if got != want { 114 | t.Errorf("%s:%d: got %q, want %q", rustCheckFilename, report, got, want) 115 | } 116 | } 117 | if err := scanner.Err(); err != nil { 118 | t.Error(err) 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /c++filt.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | //go:build ignore 6 | // +build ignore 7 | 8 | // This is a program that works like the GNU c++filt program. 9 | // It's here for testing purposes and as an example. 10 | 11 | package main 12 | 13 | import ( 14 | "bufio" 15 | "flag" 16 | "fmt" 17 | "io" 18 | "os" 19 | "strings" 20 | "unicode" 21 | 22 | "github.com/ianlancetaylor/demangle" 23 | ) 24 | 25 | func flagUsage() { 26 | usage(os.Stderr, 2) 27 | } 28 | 29 | func usage(w io.Writer, status int) { 30 | fmt.Fprintf(w, "Usage: %s [options] [mangled names]\n", os.Args[0]) 31 | flag.CommandLine.SetOutput(w) 32 | flag.PrintDefaults() 33 | fmt.Fprintln(w, `Demangled names are displayed to stdout 34 | If a name cannot be demangled it is just echoed to stdout. 35 | If no names are provided on the command line, stdin is read.`) 36 | os.Exit(status) 37 | } 38 | 39 | var stripUnderscore = flag.Bool("_", false, "Ignore first leading underscore") 40 | var noParams = flag.Bool("p", false, "Do not display function argument types") 41 | var noVerbose = flag.Bool("i", false, "Do not show implementation details (if any)") 42 | var help = flag.Bool("h", false, "Display help information") 43 | var debug = flag.Bool("d", false, "Display debugging information for strings on command line") 44 | var llvm = flag.Bool("llvm", false, "Demangle strings in LLVM style") 45 | 46 | // Unimplemented c++filt flags: 47 | // -n (opposite of -_) 48 | // -t (demangle types) 49 | // -s (set demangling style) 50 | // -V (print version information) 51 | 52 | // Characters considered to be part of a symbol. 53 | const symbolChars = "_$." 54 | 55 | func main() { 56 | flag.Usage = func() { usage(os.Stderr, 1) } 57 | flag.Parse() 58 | 59 | if *help { 60 | usage(os.Stdout, 0) 61 | } 62 | 63 | out := bufio.NewWriter(os.Stdout) 64 | 65 | if flag.NArg() > 0 { 66 | for _, f := range flag.Args() { 67 | if *debug { 68 | a, err := demangle.ToAST(f, options()...) 69 | if err != nil { 70 | fmt.Fprintf(os.Stderr, "%s: %v\n", f, err) 71 | } else { 72 | fmt.Fprintf(out, "%#v\n", a) 73 | } 74 | } else { 75 | doDemangle(out, f) 76 | } 77 | out.WriteByte('\n') 78 | } 79 | if err := out.Flush(); err != nil { 80 | fmt.Fprintln(os.Stderr, err) 81 | os.Exit(2) 82 | } 83 | return 84 | } 85 | 86 | scanner := bufio.NewScanner(bufio.NewReader(os.Stdin)) 87 | for scanner.Scan() { 88 | line := scanner.Text() 89 | start := -1 90 | for i, c := range line { 91 | if unicode.IsLetter(c) || unicode.IsNumber(c) || strings.ContainsRune(symbolChars, c) { 92 | if start < 0 { 93 | start = i 94 | } 95 | } else { 96 | if start >= 0 { 97 | doDemangle(out, line[start:i]) 98 | } 99 | out.WriteRune(c) 100 | start = -1 101 | } 102 | } 103 | if start >= 0 { 104 | doDemangle(out, line[start:]) 105 | start = -1 106 | } 107 | out.WriteByte('\n') 108 | if err := out.Flush(); err != nil { 109 | fmt.Fprintln(os.Stderr, err) 110 | os.Exit(2) 111 | } 112 | } 113 | } 114 | 115 | // Demangle a string just as the GNU c++filt program does. 116 | func doDemangle(out *bufio.Writer, name string) { 117 | skip := 0 118 | if name[0] == '.' || name[0] == '$' { 119 | skip++ 120 | } 121 | if *stripUnderscore && name[skip] == '_' { 122 | skip++ 123 | } 124 | result := demangle.Filter(name[skip:], options()...) 125 | if result == name[skip:] { 126 | out.WriteString(name) 127 | } else { 128 | if name[0] == '.' { 129 | out.WriteByte('.') 130 | } 131 | out.WriteString(result) 132 | } 133 | } 134 | 135 | // options returns the demangling options to use based on the command 136 | // line flags. 137 | func options() []demangle.Option { 138 | var options []demangle.Option 139 | if *noParams { 140 | options = append(options, demangle.NoParams) 141 | } 142 | if !*noVerbose { 143 | options = append(options, demangle.Verbose) 144 | } 145 | if *llvm { 146 | options = append(options, demangle.LLVMStyle) 147 | } 148 | return options 149 | } 150 | -------------------------------------------------------------------------------- /expected_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package demangle 6 | 7 | import ( 8 | "bufio" 9 | "flag" 10 | "fmt" 11 | "os" 12 | "strings" 13 | "testing" 14 | ) 15 | 16 | var verbose = flag.Bool("verbose", false, "print each demangle-expected symbol") 17 | 18 | const filename = "testdata/demangle-expected" 19 | 20 | // exceptions is a list of exceptions from demangle-expected that we do 21 | // not handle the same as the standard demangler. We keep a list of 22 | // exceptions so that we can use an exact copy of the file. 23 | var exceptions = map[string]bool{ 24 | // These exceptions are all based on different handling of a 25 | // substitution that refers to a template parameter. 26 | // The standard demangler seems to have a bug in which 27 | // template it uses when a reference or rvalue-reference 28 | // refers to a substitution that resolves to a template parameter. 29 | "_ZN3mdr16in_cached_threadIRZNK4cudr6GPUSet17parallel_for_eachIZN5tns3d20shape_representation7compute7GPUImpl7executeERKNS_1AINS_7ptr_refIKjEELl3ELl3ENS_8c_strideILl1ELl0EEEEERKNS8_INS9_IjEELl4ELl1ESD_EEEUliRKNS1_7ContextERNS7_5StateEE_JSt6vectorISO_SaISO_EEEEEvOT_DpRT0_EUlSP_E_JSt17reference_wrapperISO_EEEENS_12ScopedFutureIDTclfp_spcl7forwardISW_Efp0_EEEEESV_DpOSW_": true, 30 | "_ZNSt9_Any_data9_M_accessIPZN3sel8Selector6SetObjI3FooJPKcMS4_FviEEEEvRT_DpT0_EUlvE_EESA_v": true, 31 | "_ZNSt9_Any_data9_M_accessIPZN13ThreadManager7newTaskIRSt5_BindIFSt7_Mem_fnIM5DiaryFivEEPS5_EEIEEESt6futureINSt9result_ofIFT_DpT0_EE4typeEEOSF_DpOSG_EUlvE_EERSF_v": true, 32 | "_ZNSt9_Any_data9_M_accessIPZN6cereal18polymorphic_detail15getInputBindingINS1_16JSONInputArchiveEEENS1_6detail15InputBindingMapIT_E11SerializersERS7_jEUlPvRSt10unique_ptrIvNS5_12EmptyDeleterIvEEEE0_EESA_v": true, 33 | "_ZNSt9_Any_data9_M_accessIPZ4postISt8functionIFvvEEEvOT_EUlvE_EERS5_v": true, 34 | "_ZNSt9_Any_data9_M_accessIPZN13ThreadManager10futureTaskISt5_BindIFSt7_Mem_fnIM6RunnerFvvEEPS5_EEEEvOT_EUlvE_EERSC_v": true, 35 | 36 | // The standard demangler appears to mishandle the argument here, 37 | // treating it as a lamdba auto when I think it ought to be a 38 | // template argument. 39 | "_Z7forwardIZ3FoovEUlPA5_T_E1_EOS0_RS0_": true, 40 | 41 | // These exceptions are because we handle recursion differently, 42 | // and permit some cases that the standard demangler blocks. 43 | "_Z1KMMMMMMMMMMMMMMMA_xooooooooooooooo": true, 44 | "_ZdvMMMMMMMMMMMMMrrrrA_DTdvfp_fp_Eededilfdfdfdfd": true, 45 | "_Z1MA_aMMMMA_MMA_MMMMMMMMSt1MS_o11T0000000000t2M0oooozoooo": true, 46 | 47 | // The standard demangler mishandles an inheriting constructor, 48 | // getting confused when it picks up the last name. 49 | "_ZN1DCI11BEi": true, 50 | } 51 | 52 | // For simplicity, this test reads an exact copy of 53 | // libiberty/testsuite/demangle-expected from GCC. See that file for 54 | // the syntax. We ignore all tests that are not --format=gnu-v3 or 55 | // --format=auto with a string starting with _Z. 56 | func TestExpected(t *testing.T) { 57 | t.Parallel() 58 | f, err := os.Open(filename) 59 | if err != nil { 60 | t.Fatal(err) 61 | } 62 | scanner := bufio.NewScanner(f) 63 | lineno := 1 64 | for { 65 | format, got := getOptLine(t, scanner, &lineno) 66 | if !got { 67 | break 68 | } 69 | report := lineno 70 | input := getLine(t, scanner, &lineno) 71 | expect := getLine(t, scanner, &lineno) 72 | 73 | testNoParams := false 74 | skip := false 75 | if len(format) > 0 && format[0] == '-' { 76 | for _, arg := range strings.Fields(format) { 77 | switch arg { 78 | case "--format=gnu-v3": 79 | case "--format=auto": 80 | if !strings.HasPrefix(input, "_Z") { 81 | skip = true 82 | } 83 | case "--no-params": 84 | testNoParams = true 85 | case "--ret-postfix", "--ret-drop": 86 | skip = true 87 | case "--is-v3-ctor", "--is-v3-dtor": 88 | skip = true 89 | default: 90 | if !strings.HasPrefix(arg, "--format=") { 91 | t.Errorf("%s:%d: unrecognized argument %s", filename, report, arg) 92 | } 93 | skip = true 94 | } 95 | } 96 | } 97 | 98 | // The libiberty testsuite passes DMGL_TYPES to 99 | // demangle type names, but that doesn't seem useful 100 | // and we don't support it. 101 | if !strings.HasPrefix(input, "_Z") && !strings.HasPrefix(input, "_GLOBAL_") { 102 | skip = true 103 | } 104 | 105 | var expectNoParams string 106 | if testNoParams { 107 | expectNoParams = getLine(t, scanner, &lineno) 108 | } 109 | 110 | if skip { 111 | continue 112 | } 113 | 114 | oneTest(t, report, input, expect, true) 115 | if testNoParams { 116 | oneTest(t, report, input, expectNoParams, false) 117 | } 118 | } 119 | if err := scanner.Err(); err != nil { 120 | t.Error(err) 121 | } 122 | } 123 | 124 | // oneTest tests one entry from demangle-expected. 125 | func oneTest(t *testing.T, report int, input, expect string, params bool) { 126 | if *verbose { 127 | fmt.Println(input) 128 | } 129 | 130 | exception := exceptions[input] 131 | 132 | var s string 133 | var err error 134 | if params { 135 | s, err = ToString(input) 136 | } else { 137 | s, err = ToString(input, NoParams) 138 | } 139 | if err != nil { 140 | if exception { 141 | t.Logf("%s:%d: ignore expected difference: got %q, want %q", filename, report, err, expect) 142 | return 143 | } 144 | 145 | if err != ErrNotMangledName { 146 | if input == expect { 147 | return 148 | } 149 | t.Errorf("%s:%d: %v", filename, report, err) 150 | return 151 | } 152 | s = input 153 | } 154 | 155 | if s != expect { 156 | if exception { 157 | t.Logf("%s:%d: ignore expected difference: got %q, want %q", filename, report, s, expect) 158 | } else { 159 | var a AST 160 | if params { 161 | a, err = ToAST(input) 162 | } else { 163 | a, err = ToAST(input, NoParams) 164 | } 165 | if err != nil { 166 | t.Logf("ToAST error: %v", err) 167 | } else { 168 | t.Logf("\n%#v", a) 169 | } 170 | t.Errorf("%s:%d: params: %t: got %q, want %q", filename, report, params, s, expect) 171 | } 172 | } else if exception && params { 173 | t.Errorf("%s:%d: unexpected success (input listed in exceptions)", filename, report) 174 | } 175 | } 176 | 177 | // getLine reads a line from demangle-expected. 178 | func getLine(t *testing.T, scanner *bufio.Scanner, lineno *int) string { 179 | s, got := getOptLine(t, scanner, lineno) 180 | if !got { 181 | t.Fatalf("%s:%d: unexpected EOF", filename, *lineno) 182 | } 183 | return s 184 | } 185 | 186 | // getOptLine reads an optional line from demangle-expected, returning 187 | // false at EOF. It skips comment lines and updates *lineno. 188 | func getOptLine(t *testing.T, scanner *bufio.Scanner, lineno *int) (string, bool) { 189 | for { 190 | if !scanner.Scan() { 191 | return "", false 192 | } 193 | *lineno++ 194 | line := scanner.Text() 195 | if !strings.HasPrefix(line, "#") { 196 | return line, true 197 | } 198 | } 199 | } 200 | -------------------------------------------------------------------------------- /testdata/rust-demangle-expected: -------------------------------------------------------------------------------- 1 | # This file holds test cases for the Rust demangler. 2 | # Each test case looks like this: 3 | # options 4 | # input to be demangled 5 | # expected output 6 | # 7 | # See demangle-expected for documentation of supported options. 8 | # 9 | # A line starting with `#' is ignored. 10 | # However, blank lines in this file are NOT ignored. 11 | # 12 | ############ 13 | # 14 | # Coverage Tests (legacy) 15 | # 16 | # 17 | # Demangles as rust symbol. 18 | --format=rust 19 | _ZN4main4main17he714a2e23ed7db23E 20 | main::main 21 | # Also demangles as c++ gnu v3 mangled symbol. But with extra Rust hash. 22 | --format=gnu-v3 23 | _ZN4main4main17he714a2e23ed7db23E 24 | main::main::he714a2e23ed7db23 25 | # But auto should demangle fully gnu-v3 -> rust -> demangled, not partially. 26 | --format=auto 27 | _ZN4main4main17he714a2e23ed7db23E 28 | main::main 29 | # Hash is exactly 16 hex chars. Not more. 30 | --format=auto 31 | _ZN4main4main18h1e714a2e23ed7db23E 32 | main::main::h1e714a2e23ed7db23 33 | # Not less. 34 | --format=auto 35 | _ZN4main4main16h714a2e23ed7db23E 36 | main::main::h714a2e23ed7db23 37 | # And not non-hex. 38 | --format=auto 39 | _ZN4main4main17he714a2e23ed7db2gE 40 | main::main::he714a2e23ed7db2g 41 | # $XX$ substitutions should not contain just numbers. 42 | --format=auto 43 | _ZN4main4$99$17he714a2e23ed7db23E 44 | main::$99$ 45 | # _ at start of path should be removed. 46 | # ".." translates to "::" "$GT$" to ">" and "$LT$" to "<". 47 | --format=rust 48 | _ZN71_$LT$Test$u20$$u2b$$u20$$u27$static$u20$as$u20$foo..Bar$LT$Test$GT$$GT$3bar17h930b740aa94f1d3aE 49 | >::bar 50 | # 51 | --format=rust 52 | _ZN54_$LT$I$u20$as$u20$core..iter..traits..IntoIterator$GT$9into_iter17h8581507801fb8615E 53 | ::into_iter 54 | # 55 | --format=rust 56 | _ZN10parse_tsan4main17hdbbfdf1c6a7e27d9E 57 | parse_tsan::main 58 | # 59 | --format=rust 60 | _ZN65_$LT$std..env..Args$u20$as$u20$core..iter..iterator..Iterator$GT$4next17h420a7c8d0c7eef40E 61 | ::next 62 | # 63 | --format=rust 64 | _ZN4core3str9from_utf817hdcea28871313776dE 65 | core::str::from_utf8 66 | # 67 | --format=rust 68 | _ZN4core3mem7size_of17h18bde9bb8c22e2cfE 69 | core::mem::size_of 70 | # 71 | --format=rust 72 | _ZN5alloc4heap8allocate17hd55c03e6cb81d924E 73 | alloc::heap::allocate 74 | # 75 | --format=rust 76 | _ZN4core3ptr8null_mut17h736cce09ca0ac11aE 77 | core::ptr::null_mut 78 | # 79 | --format=rust 80 | _ZN4core3ptr31_$LT$impl$u20$$BP$mut$u20$T$GT$7is_null17h7f9de798bc3f0879E 81 | core::ptr::::is_null 82 | # 83 | --format=rust 84 | _ZN40_$LT$alloc..raw_vec..RawVec$LT$T$GT$$GT$6double17h4166e2b47539e1ffE 85 | >::double 86 | # 87 | --format=rust 88 | _ZN39_$LT$collections..vec..Vec$LT$T$GT$$GT$4push17hd4b6b23c1b88141aE 89 | >::push 90 | # 91 | --format=rust 92 | _ZN70_$LT$collections..vec..Vec$LT$T$GT$$u20$as$u20$core..ops..DerefMut$GT$9deref_mut17hf299b860dc5a831cE 93 | as core::ops::DerefMut>::deref_mut 94 | # 95 | --format=rust 96 | _ZN63_$LT$core..ptr..Unique$LT$T$GT$$u20$as$u20$core..ops..Deref$GT$5deref17hc784b4a166cb5e5cE 97 | as core::ops::Deref>::deref 98 | # 99 | --format=rust 100 | _ZN40_$LT$alloc..raw_vec..RawVec$LT$T$GT$$GT$3ptr17h7570b6e9070b693bE 101 | >::ptr 102 | # 103 | --format=rust 104 | _ZN4core3ptr31_$LT$impl$u20$$BP$mut$u20$T$GT$7is_null17h0f3228f343444ac8E 105 | core::ptr::::is_null 106 | # 107 | --format=rust 108 | _ZN53_$LT$$u5b$T$u5d$$u20$as$u20$core..slice..SliceExt$GT$10as_mut_ptr17h153241df1c7d1666E 109 | <[T] as core::slice::SliceExt>::as_mut_ptr 110 | # 111 | --format=rust 112 | _ZN11collections5slice29_$LT$impl$u20$$u5b$T$u5d$$GT$10as_mut_ptr17hf12a6d0409938c96E 113 | collections::slice::::as_mut_ptr 114 | # 115 | --format=rust 116 | _ZN4core3ptr5write17h651fe53ec860e780E 117 | core::ptr::write 118 | # 119 | --format=rust 120 | _ZN65_$LT$std..env..Args$u20$as$u20$core..iter..iterator..Iterator$GT$4next17h420a7c8d0c7eef40E 121 | ::next 122 | # 123 | --format=rust 124 | _ZN54_$LT$I$u20$as$u20$core..iter..traits..IntoIterator$GT$9into_iter17he06cb713aae5b465E 125 | ::into_iter 126 | # 127 | --format=rust 128 | _ZN71_$LT$collections..vec..IntoIter$LT$T$GT$$u20$as$u20$core..ops..Drop$GT$4drop17hf7f23304ebe62eedE 129 | as core::ops::Drop>::drop 130 | # 131 | --format=rust 132 | _ZN86_$LT$collections..vec..IntoIter$LT$T$GT$$u20$as$u20$core..iter..iterator..Iterator$GT$4next17h04b3fbf148c39713E 133 | as core::iter::iterator::Iterator>::next 134 | # 135 | --format=rust 136 | _ZN75_$LT$$RF$$u27$a$u20$mut$u20$I$u20$as$u20$core..iter..iterator..Iterator$GT$4next17ha050492063e0fd20E 137 | <&'a mut I as core::iter::iterator::Iterator>::next 138 | # Different hashes are OK, they are just stripped. 139 | --format=rust 140 | _ZN13drop_contents17hfe3c0a68c8ad1c74E 141 | drop_contents 142 | # 143 | --format=rust 144 | _ZN13drop_contents17h48cb59bef15bb555E 145 | drop_contents 146 | # 147 | --format=rust 148 | _ZN4core3mem7size_of17h900b33157bf58f26E 149 | core::mem::size_of 150 | # 151 | --format=rust 152 | _ZN67_$LT$alloc..raw_vec..RawVec$LT$T$GT$$u20$as$u20$core..ops..Drop$GT$4drop17h96a5cf6e94807905E 153 | as core::ops::Drop>::drop 154 | # 155 | --format=rust 156 | _ZN68_$LT$core..nonzero..NonZero$LT$T$GT$$u20$as$u20$core..ops..Deref$GT$5deref17hc49056f882aa46dbE 157 | as core::ops::Deref>::deref 158 | # 159 | --format=rust 160 | _ZN63_$LT$core..ptr..Unique$LT$T$GT$$u20$as$u20$core..ops..Deref$GT$5deref17h19f2ad4920655e85E 161 | as core::ops::Deref>::deref 162 | # 163 | --format=rust 164 | _ZN11issue_609253foo37Foo$LT$issue_60925..llv$u6d$..Foo$GT$3foo17h059a991a004536adE 165 | issue_60925::foo::Foo::foo 166 | --format=rust 167 | _ZN4core3ops8function6FnOnce40call_once$u7b$$u7b$vtable.shim$u7d$$u7d$17h000b1ad6c4f30bd6E 168 | core::ops::function::FnOnce::call_once{{vtable.shim}} 169 | # 170 | ############ 171 | # 172 | # Coverage Tests (v0) 173 | # 174 | # 175 | # Crate with a leading digit. 176 | --format=rust 177 | _RNvC6_123foo3bar 178 | 123foo::bar 179 | # UTF-8 identifiers. 180 | --format=rust 181 | _RNqCs4fqI2P2rA04_11utf8_identsu30____7hkackfecea1cbdathfdh9hlq6y 182 | utf8_idents::საჭმელად_გემრიელი_სადილი 183 | # Closure path elements. 184 | --format=rust 185 | _RNCNCNgCs6DXkGYLi8lr_2cc5spawn00B5_ 186 | cc::spawn::{closure#0}::{closure#0} 187 | # 188 | --format=rust 189 | _RNCINkXs25_NgCsbmNqQUJIY6D_4core5sliceINyB9_4IterhENuNgNoBb_4iter8iterator8Iterator9rpositionNCNgNpB9_6memchr7memrchrs_0E0Bb_ 190 | as core::iter::iterator::Iterator>::rposition::::{closure#0} 191 | # dyn Trait ("trait object") types. 192 | --format=rust 193 | _RINbNbCskIICzLVDPPb_5alloc5alloc8box_freeDINbNiB4_5boxed5FnBoxuEp6OutputuEL_ECs1iopQbuBiw2_3std 194 | alloc::alloc::box_free::> 195 | # Types with const generics parameters. 196 | --format=rust 197 | _RNvMC0INtC8arrayvec8ArrayVechKj7b_E3new 198 | >::new 199 | # 200 | --format=rust 201 | _RMCs4fqI2P2rA04_13const_genericINtB0_8UnsignedKhb_E 202 | > 203 | # 204 | --format=rust 205 | _RMCs4fqI2P2rA04_13const_genericINtB0_6SignedKs98_E 206 | > 207 | # 208 | --format=rust 209 | _RMCs4fqI2P2rA04_13const_genericINtB0_6SignedKanb_E 210 | > 211 | # 212 | --format=rust 213 | _RMCs4fqI2P2rA04_13const_genericINtB0_4BoolKb0_E 214 | > 215 | # 216 | --format=rust 217 | _RMCs4fqI2P2rA04_13const_genericINtB0_4BoolKb1_E 218 | > 219 | # 220 | --format=rust 221 | _RMCs4fqI2P2rA04_13const_genericINtB0_4CharKc76_E 222 | > 223 | # 224 | --format=rust 225 | _RMCs4fqI2P2rA04_13const_genericINtB0_4CharKca_E 226 | > 227 | # 228 | --format=rust 229 | _RMCs4fqI2P2rA04_13const_genericINtB0_4CharKc2202_E 230 | > 231 | # 232 | --format=rust 233 | _RNvNvMCs4fqI2P2rA04_13const_genericINtB4_3FooKpE3foo3FOO 234 | >::foo::FOO 235 | # 236 | # All of the tests above but in auto mode instead: 237 | # 238 | # Crate with a leading digit. 239 | --format=auto 240 | _RNvC6_123foo3bar 241 | 123foo::bar 242 | # UTF-8 identifiers. 243 | --format=auto 244 | _RNqCs4fqI2P2rA04_11utf8_identsu30____7hkackfecea1cbdathfdh9hlq6y 245 | utf8_idents::საჭმელად_გემრიელი_სადილი 246 | # Closure path elements. 247 | --format=auto 248 | _RNCNCNgCs6DXkGYLi8lr_2cc5spawn00B5_ 249 | cc::spawn::{closure#0}::{closure#0} 250 | # 251 | --format=auto 252 | _RNCINkXs25_NgCsbmNqQUJIY6D_4core5sliceINyB9_4IterhENuNgNoBb_4iter8iterator8Iterator9rpositionNCNgNpB9_6memchr7memrchrs_0E0Bb_ 253 | as core::iter::iterator::Iterator>::rposition::::{closure#0} 254 | # dyn Trait ("trait object") types. 255 | --format=auto 256 | _RINbNbCskIICzLVDPPb_5alloc5alloc8box_freeDINbNiB4_5boxed5FnBoxuEp6OutputuEL_ECs1iopQbuBiw2_3std 257 | alloc::alloc::box_free::> 258 | # Types with const generics parameters. 259 | --format=auto 260 | _RNvMC0INtC8arrayvec8ArrayVechKj7b_E3new 261 | >::new 262 | # 263 | --format=auto 264 | _RMCs4fqI2P2rA04_13const_genericINtB0_8UnsignedKhb_E 265 | > 266 | # 267 | --format=auto 268 | _RMCs4fqI2P2rA04_13const_genericINtB0_6SignedKs98_E 269 | > 270 | # 271 | --format=auto 272 | _RMCs4fqI2P2rA04_13const_genericINtB0_6SignedKanb_E 273 | > 274 | # 275 | --format=auto 276 | _RMCs4fqI2P2rA04_13const_genericINtB0_4BoolKb0_E 277 | > 278 | # 279 | --format=auto 280 | _RMCs4fqI2P2rA04_13const_genericINtB0_4BoolKb1_E 281 | > 282 | # 283 | --format=auto 284 | _RMCs4fqI2P2rA04_13const_genericINtB0_4CharKc76_E 285 | > 286 | # 287 | --format=auto 288 | _RMCs4fqI2P2rA04_13const_genericINtB0_4CharKca_E 289 | > 290 | # 291 | --format=auto 292 | _RMCs4fqI2P2rA04_13const_genericINtB0_4CharKc2202_E 293 | > 294 | # 295 | --format=auto 296 | _RNvNvMCs4fqI2P2rA04_13const_genericINtB4_3FooKpE3foo3FOO 297 | >::foo::FOO 298 | -------------------------------------------------------------------------------- /testdata/rust.test: -------------------------------------------------------------------------------- 1 | RUN: llvm-cxxfilt -n < %s | FileCheck --match-full-lines %s 2 | 3 | CHECK: a::main 4 | _RNvC1a4main 5 | 6 | CHECK: hello::rust 7 | _RNvCshGpAVYOtgW1_5hello4rust 8 | 9 | CHECK: a::b::c 10 | _RNvNvC1a1b1c 11 | 12 | ; Instantiating crate 13 | 14 | CHECK: crate 15 | _RC5crateC3foo 16 | 17 | ; Closure namespace 18 | 19 | CHECK: crate::{closure#0} 20 | _RNCC5crate0 21 | 22 | CHECK: crate::{closure#1} 23 | _RNCC5crates_0 24 | 25 | CHECK: crate::{closure:foo#0} 26 | _RNCC5crate3foo 27 | 28 | CHECK: crate::{closure:foo#1} 29 | _RNCC5crates_3foo 30 | 31 | ; Shim namespace 32 | 33 | CHECK: crate::{shim:reify#0} 34 | _RNSC5crate5reify 35 | 36 | ; Unrecognized special namespace 37 | 38 | CHECK: crate::{Z:ident#10} 39 | _RNZC5crates8_5ident 40 | 41 | ; Inherent impl 42 | 43 | CHECK: <_> 44 | _RMC5cratep 45 | 46 | CHECK: <_> 47 | _RMs_C5cratep 48 | 49 | ; Trait impl 50 | 51 | CHECK: <_ as Clone> 52 | _RXC5cratepC5Clone 53 | 54 | CHECK: <_ as Clone> 55 | _RXs_C5cratepC5Clone 56 | 57 | ; Trait definition 58 | 59 | CHECK: <_ as Ord> 60 | _RYpC3Ord 61 | 62 | ; Generic type arguments 63 | 64 | CHECK: generic::<_> 65 | _RIC7genericpE 66 | 67 | CHECK: generic::<_, _> 68 | _RIC7genericppE 69 | 70 | CHECK: generic::<_, _, _> 71 | _RIC7genericpppE 72 | 73 | ; Generic const arguments 74 | 75 | CHECK: generic_const::<_> 76 | _RIC13generic_constKpE 77 | 78 | ; Generic lifetime arguments 79 | 80 | CHECK: generic_lifetime::<'_> 81 | _RIC16generic_lifetimeL_E 82 | 83 | ; Invalid lifetime index. 84 | 85 | CHECK: _RIC16generic_lifetimeL0_E 86 | _RIC16generic_lifetimeL0_E 87 | 88 | ; Basic types 89 | 90 | CHECK: basic:: 91 | _RIC5basicaE 92 | 93 | CHECK: basic:: 94 | _RIC5basicbE 95 | 96 | CHECK: basic:: 97 | _RIC5basiccE 98 | 99 | CHECK: basic:: 100 | _RIC5basicdE 101 | 102 | CHECK: basic:: 103 | _RIC5basiceE 104 | 105 | CHECK: basic:: 106 | _RIC5basicfE 107 | 108 | CHECK: basic:: 109 | _RIC5basichE 110 | 111 | CHECK: basic:: 112 | _RIC5basiciE 113 | 114 | CHECK: basic:: 115 | _RIC5basicjE 116 | 117 | CHECK: basic:: 118 | _RIC5basiclE 119 | 120 | CHECK: basic:: 121 | _RIC5basicmE 122 | 123 | CHECK: basic:: 124 | _RIC5basicnE 125 | 126 | CHECK: basic:: 127 | _RIC5basicoE 128 | 129 | CHECK: basic::<_> 130 | _RIC5basicpE 131 | 132 | CHECK: basic:: 133 | _RIC5basicsE 134 | 135 | CHECK: basic:: 136 | _RIC5basictE 137 | 138 | CHECK: basic::<()> 139 | _RIC5basicuE 140 | 141 | CHECK: basic::<...> 142 | _RIC5basicvE 143 | 144 | CHECK: basic:: 145 | _RIC5basicxE 146 | 147 | CHECK: basic:: 148 | _RIC5basicyE 149 | 150 | CHECK: basic:: 151 | _RIC5basiczE 152 | 153 | ; Named types. Test possible paths productions. 154 | 155 | CHECK: named:: 156 | _RIC5namedC4nameE 157 | 158 | CHECK: named::<<_>> 159 | _RIC5namedMC5cratepE 160 | 161 | CHECK: named::<<_ as Name>> 162 | _RIC5namedXC5cratepC4NameE 163 | 164 | CHECK: named::<<_ as Name>> 165 | _RIC5namedYpC4NameE 166 | 167 | CHECK: named:: 168 | _RIC5namedNvC4name4NameE 169 | 170 | CHECK: named::> 171 | _RIC5namedIC4NameEE 172 | 173 | ; Types 174 | 175 | CHECK: types::<[u8; 0]> 176 | _RIC5typesAhj0_E 177 | 178 | CHECK: types::<[_]> 179 | _RIC5typesSpE 180 | 181 | CHECK: types::<()> 182 | _RIC5typesTEE 183 | 184 | CHECK: types::<(_,)> 185 | _RIC5typesTpEE 186 | 187 | CHECK: types::<(_, _)> 188 | _RIC5typesTppEE 189 | 190 | CHECK: types::<(_, _, _)> 191 | _RIC5typesTpppEE 192 | 193 | CHECK: types::<&_> 194 | _RIC5typesRpE 195 | 196 | CHECK: types::<&_> 197 | _RIC5typesRL_pE 198 | 199 | CHECK: types::<&mut _> 200 | _RIC5typesQpE 201 | 202 | CHECK: types::<&mut _> 203 | _RIC5typesQL_pE 204 | 205 | CHECK: types::<*const _> 206 | _RIC5typesPpE 207 | 208 | CHECK: types::<*mut _> 209 | _RIC5typesOpE 210 | 211 | ; Function signatures 212 | 213 | CHECK: function:: 214 | _RIC8functionFEuE 215 | 216 | CHECK: function:: _> 217 | _RIC8functionFEpE 218 | 219 | CHECK: function:: 220 | _RIC8functionFpEuE 221 | 222 | CHECK: function:: 223 | _RIC8functionFppEuE 224 | 225 | CHECK: function:: 226 | _RIC8functionFpppEuE 227 | 228 | CHECK: function:: 229 | _RIC8functionFUEuE 230 | 231 | CHECK: function:: 232 | _RIC8functionFKCEuE 233 | 234 | CHECK: function:: 235 | _RIC8functionFK5cdeclEuE 236 | 237 | CHECK: function:: 238 | _RIC8functionFUK21C_cmse_nonsecure_callEuE 239 | 240 | ; Trait objects 241 | 242 | CHECK: trait:: 243 | _RIC5traitDEL_E 244 | 245 | CHECK: trait:: > 246 | _RIC5traitDG_EL_E 247 | 248 | CHECK: trait:: fn(dyn for<'b> + 'a)> 249 | _RIC5traitFG_DG_EL0_EuE 250 | 251 | CHECK: trait:: 252 | _RIC5traitDC7DisplayEL_E 253 | 254 | CHECK: trait:: 255 | _RIC5traitDC7DisplayC4SendC4SyncEL_E 256 | 257 | CHECK: trait:: Display> 258 | _RIC5traitDG_C7DisplayEL_E 259 | 260 | CHECK: trait::> 261 | _RIC5traitDIC12IntoIteratorpEp4ItempEL_E 262 | 263 | CHECK: trait::> 264 | _RIC5traitDC12IntoIteratorp4ItempEL_E 265 | 266 | CHECK: trait::> 267 | _RIC5traitDC12IntoIteratorp4Itempp8IntoIterpEL_E 268 | 269 | ; Invalid trait object, missing lifetime. 270 | 271 | CHECK: _RIC5traitDEE 272 | _RIC5traitDEE 273 | 274 | ; Binders 275 | 276 | CHECK: binders:: fn(&'a _)> 277 | _RIC7bindersFG_RL0_pEuE 278 | 279 | CHECK: binders:: fn(&'a mut _)> 280 | _RIC7bindersFG_QL0_pEuE 281 | 282 | CHECK: binders:: fn(&'a _, &'b _)> 283 | _RIC7bindersFG0_RL1_pRL0_pEuE 284 | 285 | CHECK: binders:: fn() -> for<'c, 'd> fn(&'a _, &'d _)> 286 | _RIC7bindersFG0_EFG0_RL3_pRL0_pEuE 287 | 288 | CHECK: binders:: fn(&'a &'b &'c &'d &'e &'f &'g &'h &'i &'j &'k &'l &'m &'n &'o &'p &'q &'r &'s &'t &'u &'v &'w &'x &'y &'z &'z1 &'z2 &'z3 &'z4 ())> 289 | _RIC7bindersFGs_RLt_RLs_RLr_RLq_RLp_RLo_RLn_RLm_RLl_RLk_RLj_RLi_RLh_RLg_RLf_RLe_RLd_RLc_RLb_RLa_RL9_RL8_RL7_RL6_RL5_RL4_RL3_RL2_RL1_RL0_uEuE 290 | 291 | ; Invalid binder. Too many bound lifetimes. 292 | 293 | CHECK: _RIC7bindersFGFF_EuE 294 | _RIC7bindersFGFF_EuE 295 | 296 | ; Integer constants. Test value demangling. 297 | 298 | CHECK: integer::<0> 299 | _RIC7integerKi0_E 300 | 301 | CHECK: integer::<1> 302 | _RIC7integerKi1_E 303 | 304 | CHECK: integer::<-1> 305 | _RIC7integerKin1_E 306 | 307 | CHECK: integer::<-15> 308 | _RIC7integerKinf_E 309 | 310 | CHECK: integer::<-16> 311 | _RIC7integerKin10_E 312 | 313 | CHECK: integer::<18446744073709551615> 314 | _RIC7integerKoffffffffffffffff_E 315 | 316 | CHECK: integer::<0x10000000000000000> 317 | _RIC7integerKo10000000000000000_E 318 | 319 | CHECK: integer::<-0x123456789abcdef01> 320 | _RIC7integerKnn123456789abcdef01_E 321 | 322 | ; Invalid integer constant without any digits: 323 | 324 | CHECK: _RIC7integerKi_E 325 | _RIC7integerKi_E 326 | 327 | ; Invalid integer constants with insignificant leading zeros: 328 | 329 | CHECK: _RIC7integerKi00_E 330 | _RIC7integerKi00_E 331 | 332 | CHECK: _RIC7integerKi01_E 333 | _RIC7integerKi01_E 334 | 335 | ; Integer constants. Test all integer types. 336 | 337 | CHECK: i8::<0> 338 | _RIC2i8Ka0_E 339 | 340 | CHECK: u8::<0> 341 | _RIC2u8Kh0_E 342 | 343 | CHECK: isize::<0> 344 | _RIC5isizeKi0_E 345 | 346 | CHECK: usize::<0> 347 | _RIC5usizeKj0_E 348 | 349 | CHECK: i32::<0> 350 | _RIC3i32Kl0_E 351 | 352 | CHECK: u32::<0> 353 | _RIC3u32Km0_E 354 | 355 | CHECK: i128::<0> 356 | _RIC4i128Kn0_E 357 | 358 | CHECK: u128::<0> 359 | _RIC4u128Ko0_E 360 | 361 | CHECK: i16::<0> 362 | _RIC3i16Ks0_E 363 | 364 | CHECK: u16::<0> 365 | _RIC3u16Kt0_E 366 | 367 | CHECK: i64::<0> 368 | _RIC3i64Kx0_E 369 | 370 | CHECK: u64::<0> 371 | _RIC3u64Ky0_E 372 | 373 | ; Bool constants 374 | 375 | CHECK: bool:: 376 | _RIC4boolKb0_E 377 | 378 | CHECK: bool:: 379 | _RIC4boolKb1_E 380 | 381 | ; Invalid bool constants 382 | 383 | CHECK: _RIC4boolKb2_E 384 | _RIC4boolKb2_E 385 | 386 | CHECK: _RIC4boolKbn0_E 387 | _RIC4boolKbn0_E 388 | 389 | ; Char constants 390 | 391 | CHECK: char::<'a'> 392 | _RIC4charKc61_E 393 | 394 | CHECK: char::<'"'> 395 | _RIC4charKc22_E 396 | 397 | CHECK: char::<'\t'> 398 | _RIC4charKc9_E 399 | 400 | CHECK: char::<'\r'> 401 | _RIC4charKcd_E 402 | 403 | CHECK: char::<'\n'> 404 | _RIC4charKca_E 405 | 406 | CHECK: char::<'\\'> 407 | _RIC4charKc5c_E 408 | 409 | CHECK: char::<'\''> 410 | _RIC4charKc27_E 411 | 412 | CHECK: char::<'\u{1f40d}'> 413 | _RIC4charKc1f40d_E 414 | 415 | CHECK: char::<'\u{10ffff}'> 416 | _RIC4charKc10ffff_E 417 | 418 | ; Invalid char constants 419 | 420 | CHECK: _RIC4charKc1234567_E 421 | _RIC4charKc1234567_E 422 | 423 | ; Backreferences 424 | 425 | CHECK: backref:: 426 | _RIC7backrefNvB0_5identE 427 | 428 | CHECK: backref::<(), ()> 429 | _RIC7backrefuB9_E 430 | 431 | CHECK: backref::<7, 7> 432 | _RIC7backrefKi7_KBa_E 433 | 434 | ; Invalid backreferences 435 | 436 | CHECK: _RB_ 437 | _RB_ 438 | 439 | CHECK: _RB5_ 440 | _RB5_ 441 | 442 | CHECK: _RNvB_1a 443 | _RNvB_1a 444 | 445 | CHECK: _RIC7backrefSB9_E 446 | _RIC7backrefSB9_E 447 | 448 | CHECK: _RIC7backrefKBa_E 449 | _RIC7backrefKBa_E 450 | 451 | ; Dot suffix 452 | 453 | CHECK: dot (.llvm.1234) 454 | _RC3dot.llvm.1234 455 | 456 | CHECK: dot (.llvm.6789) 457 | _RC3dotC5crate.llvm.6789 458 | 459 | ; Invalid mangled characters 460 | 461 | CHECK: _RNvC2a.1c 462 | _RNvC2a.1c 463 | 464 | CHECK: _RNvC2a$1c 465 | _RNvC2a$1c 466 | 467 | ; Invalid namespace (not in [a-zA-Z]). 468 | 469 | CHECK: _RN_C5crate4main 470 | _RN_C5crate4main 471 | 472 | ; Invalid identifier length (UINT64_MAX + 3, which happens to be ok after a wraparound). 473 | 474 | CHECK: _RNvC2ab18446744073709551618xy 475 | _RNvC2ab18446744073709551618xy 476 | 477 | ; Mangling scheme includes an optional encoding version. When present it would 478 | ; indicate an encoding we don't support yet. Check that it is rejected: 479 | 480 | CHECK: _R0NvC1a4main 481 | _R0NvC1a4main 482 | 483 | ; Early EOF 484 | 485 | CHECK: _RNv 486 | _RNv 487 | 488 | CHECK: _RNvC 489 | _RNvC 490 | 491 | CHECK: _RNvC1a5main 492 | _RNvC1a5main 493 | 494 | CHECK: _RNvC1a20abc 495 | _RNvC1a20abc 496 | -------------------------------------------------------------------------------- /rust.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package demangle 6 | 7 | import ( 8 | "fmt" 9 | "math" 10 | "math/bits" 11 | "strings" 12 | "unicode/utf8" 13 | ) 14 | 15 | // rustToString demangles a Rust symbol. 16 | func rustToString(name string, options []Option) (ret string, err error) { 17 | if !strings.HasPrefix(name, "_R") { 18 | return "", ErrNotMangledName 19 | } 20 | 21 | // When the demangling routines encounter an error, they panic 22 | // with a value of type demangleErr. 23 | defer func() { 24 | if r := recover(); r != nil { 25 | if de, ok := r.(demangleErr); ok { 26 | ret = "" 27 | err = de 28 | return 29 | } 30 | panic(r) 31 | } 32 | }() 33 | 34 | suffix := "" 35 | dot := strings.Index(name, ".") 36 | if dot >= 0 { 37 | suffix = name[dot:] 38 | name = name[:dot] 39 | } 40 | 41 | name = name[2:] 42 | rst := &rustState{orig: name, str: name} 43 | rst.symbolName() 44 | 45 | if len(rst.str) > 0 { 46 | rst.fail("unparsed characters at end of mangled name") 47 | } 48 | 49 | if suffix != "" { 50 | rst.skip = false 51 | rst.writeString(" (") 52 | rst.writeString(suffix) 53 | rst.writeByte(')') 54 | } 55 | 56 | return rst.buf.String(), nil 57 | } 58 | 59 | // A rustState holds the current state of demangling a Rust string. 60 | type rustState struct { 61 | orig string // the original string being demangled 62 | str string // remainder of string to demangle 63 | off int // offset of str within original string 64 | buf strings.Builder // demangled string being built 65 | skip bool // don't print, just skip 66 | lifetimes int64 // number of bound lifetimes 67 | last byte // last byte written to buffer 68 | } 69 | 70 | // fail panics with demangleErr, to be caught in rustToString. 71 | func (rst *rustState) fail(err string) { 72 | panic(demangleErr{err: err, off: rst.off}) 73 | } 74 | 75 | // advance advances the current string offset. 76 | func (rst *rustState) advance(add int) { 77 | if len(rst.str) < add { 78 | panic("internal error") 79 | } 80 | rst.str = rst.str[add:] 81 | rst.off += add 82 | } 83 | 84 | // checkChar requires that the next character in the string be c, 85 | // and advances past it. 86 | func (rst *rustState) checkChar(c byte) { 87 | if len(rst.str) == 0 || rst.str[0] != c { 88 | rst.fail("expected " + string(c)) 89 | } 90 | rst.advance(1) 91 | } 92 | 93 | // writeByte writes a byte to the buffer. 94 | func (rst *rustState) writeByte(c byte) { 95 | if rst.skip { 96 | return 97 | } 98 | rst.last = c 99 | rst.buf.WriteByte(c) 100 | } 101 | 102 | // writeString writes a string to the buffer. 103 | func (rst *rustState) writeString(s string) { 104 | if rst.skip { 105 | return 106 | } 107 | if len(s) > 0 { 108 | rst.last = s[len(s)-1] 109 | rst.buf.WriteString(s) 110 | } 111 | } 112 | 113 | // = "_R" [] [] 114 | // = 115 | // 116 | // We've already skipped the "_R". 117 | func (rst *rustState) symbolName() { 118 | if len(rst.str) < 1 { 119 | rst.fail("expected symbol-name") 120 | } 121 | 122 | if isDigit(rst.str[0]) { 123 | rst.fail("unsupported Rust encoding version") 124 | } 125 | 126 | rst.path(true) 127 | 128 | if len(rst.str) > 0 { 129 | rst.skip = true 130 | rst.path(false) 131 | } 132 | } 133 | 134 | // = "C" // crate root 135 | // | "M" // (inherent impl) 136 | // | "X" // (trait impl) 137 | // | "Y" // (trait definition) 138 | // | "N" // ...::ident (nested path) 139 | // | "I" {} "E" // ... (generic args) 140 | // | 141 | // = "C" // closure 142 | // | "S" // shim 143 | // | // other special namespaces 144 | // | // internal namespaces 145 | // 146 | // needsSeparator is true if we need to write out :: for a generic; 147 | // it is passed as false if we are in the middle of a type. 148 | func (rst *rustState) path(needsSeparator bool) { 149 | if len(rst.str) < 1 { 150 | rst.fail("expected path") 151 | } 152 | switch c := rst.str[0]; c { 153 | case 'C': 154 | rst.advance(1) 155 | _, ident := rst.identifier() 156 | rst.writeString(ident) 157 | case 'M', 'X': 158 | rst.advance(1) 159 | rst.implPath() 160 | rst.writeByte('<') 161 | rst.demangleType() 162 | if c == 'X' { 163 | rst.writeString(" as ") 164 | rst.path(false) 165 | } 166 | rst.writeByte('>') 167 | case 'Y': 168 | rst.advance(1) 169 | rst.writeByte('<') 170 | rst.demangleType() 171 | rst.writeString(" as ") 172 | rst.path(false) 173 | rst.writeByte('>') 174 | case 'N': 175 | rst.advance(1) 176 | 177 | if len(rst.str) < 1 { 178 | rst.fail("expected namespace") 179 | } 180 | ns := rst.str[0] 181 | switch { 182 | case ns >= 'a' && ns <= 'z': 183 | case ns >= 'A' && ns <= 'Z': 184 | default: 185 | rst.fail("invalid namespace character") 186 | } 187 | rst.advance(1) 188 | 189 | rst.path(needsSeparator) 190 | 191 | dis, ident := rst.identifier() 192 | 193 | if ns >= 'A' && ns <= 'Z' { 194 | rst.writeString("::{") 195 | switch ns { 196 | case 'C': 197 | rst.writeString("closure") 198 | case 'S': 199 | rst.writeString("shim") 200 | default: 201 | rst.writeByte(ns) 202 | } 203 | if len(ident) > 0 { 204 | rst.writeByte(':') 205 | rst.writeString(ident) 206 | } 207 | if !rst.skip { 208 | fmt.Fprintf(&rst.buf, "#%d}", dis) 209 | rst.last = '}' 210 | } 211 | } else { 212 | rst.writeString("::") 213 | rst.writeString(ident) 214 | } 215 | case 'I': 216 | rst.advance(1) 217 | rst.path(needsSeparator) 218 | if needsSeparator { 219 | rst.writeString("::") 220 | } 221 | rst.writeByte('<') 222 | first := true 223 | for len(rst.str) > 0 && rst.str[0] != 'E' { 224 | if first { 225 | first = false 226 | } else { 227 | rst.writeString(", ") 228 | } 229 | rst.genericArg() 230 | } 231 | rst.writeByte('>') 232 | rst.checkChar('E') 233 | case 'B': 234 | rst.backref(func() { rst.path(needsSeparator) }) 235 | default: 236 | rst.fail("unrecognized letter in path") 237 | } 238 | } 239 | 240 | // = [] 241 | func (rst *rustState) implPath() { 242 | // This path is not part of the demangled string. 243 | hold := rst.skip 244 | rst.skip = true 245 | defer func() { 246 | rst.skip = hold 247 | }() 248 | 249 | rst.disambiguator() 250 | rst.path(false) 251 | } 252 | 253 | // = [] 254 | // Returns the disambiguator and the identifier. 255 | func (rst *rustState) identifier() (int64, string) { 256 | dis := rst.disambiguator() 257 | ident := rst.undisambiguatedIdentifier() 258 | return dis, ident 259 | } 260 | 261 | // = "s" 262 | // This is optional. 263 | func (rst *rustState) disambiguator() int64 { 264 | if len(rst.str) == 0 || rst.str[0] != 's' { 265 | return 0 266 | } 267 | rst.advance(1) 268 | return rst.base62Number() + 1 269 | } 270 | 271 | // = ["u"] ["_"] 272 | func (rst *rustState) undisambiguatedIdentifier() string { 273 | punycode := false 274 | if len(rst.str) > 0 && rst.str[0] == 'u' { 275 | rst.advance(1) 276 | punycode = true 277 | } 278 | 279 | val := rst.decimalNumber() 280 | 281 | if len(rst.str) > 0 && rst.str[0] == '_' { 282 | rst.advance(1) 283 | } 284 | 285 | if len(rst.str) < val { 286 | rst.fail("not enough characters for identifier") 287 | } 288 | id := rst.str[:val] 289 | rst.advance(val) 290 | 291 | for i := 0; i < len(id); i++ { 292 | c := id[i] 293 | switch { 294 | case c >= '0' && c <= '9': 295 | case c >= 'A' && c <= 'Z': 296 | case c >= 'a' && c <= 'z': 297 | case c == '_': 298 | default: 299 | rst.fail("invalid character in identifier") 300 | } 301 | } 302 | 303 | if punycode { 304 | id = rst.expandPunycode(id) 305 | } 306 | 307 | return id 308 | } 309 | 310 | // expandPunycode decodes the Rust version of punycode. 311 | // This algorithm is taken from RFC 3492 section 6.2. 312 | func (rst *rustState) expandPunycode(s string) string { 313 | const ( 314 | base = 36 315 | tmin = 1 316 | tmax = 26 317 | skew = 38 318 | damp = 700 319 | initialBias = 72 320 | initialN = 128 321 | ) 322 | 323 | idx := strings.LastIndex(s, "_") 324 | if idx < 0 { 325 | rst.fail("missing underscore in punycode string") 326 | } 327 | 328 | output := []rune(s[:idx]) 329 | encoding := s[idx+1:] 330 | 331 | i := 0 332 | n := initialN 333 | bias := initialBias 334 | 335 | pos := 0 336 | for pos < len(encoding) { 337 | oldI := i 338 | w := 1 339 | for k := base; ; k += base { 340 | if pos == len(encoding) { 341 | rst.fail("unterminated punycode") 342 | } 343 | 344 | var digit byte 345 | d := encoding[pos] 346 | pos++ 347 | switch { 348 | case '0' <= d && d <= '9': 349 | digit = d - '0' + 26 350 | case 'A' <= d && d <= 'Z': 351 | digit = d - 'A' 352 | case 'a' <= d && d <= 'z': 353 | digit = d - 'a' 354 | default: 355 | rst.fail("invalid punycode digit") 356 | } 357 | 358 | i += int(digit) * w 359 | if i < 0 { 360 | rst.fail("punycode number overflow") 361 | } 362 | 363 | var t int 364 | if k <= bias { 365 | t = tmin 366 | } else if k > bias+tmax { 367 | t = tmax 368 | } else { 369 | t = k - bias 370 | } 371 | 372 | if int(digit) < t { 373 | break 374 | } 375 | 376 | if w >= math.MaxInt32/base { 377 | rst.fail("punycode number overflow") 378 | } 379 | w *= base - t 380 | } 381 | 382 | delta := i - oldI 383 | numPoints := len(output) + 1 384 | firstTime := oldI == 0 385 | if firstTime { 386 | delta /= damp 387 | } else { 388 | delta /= 2 389 | } 390 | delta += delta / numPoints 391 | k := 0 392 | for delta > ((base-tmin)*tmax)/2 { 393 | delta /= base - tmin 394 | k += base 395 | } 396 | bias = k + ((base-tmin+1)*delta)/(delta+skew) 397 | 398 | n += i / (len(output) + 1) 399 | if n > utf8.MaxRune { 400 | rst.fail("punycode rune overflow") 401 | } 402 | i %= len(output) + 1 403 | output = append(output, 0) 404 | copy(output[i+1:], output[i:]) 405 | output[i] = rune(n) 406 | i++ 407 | } 408 | 409 | return string(output) 410 | } 411 | 412 | // = 413 | // | 414 | // | "K" // forward-compat for const generics 415 | // = "L" 416 | func (rst *rustState) genericArg() { 417 | if len(rst.str) < 1 { 418 | rst.fail("expected generic-arg") 419 | } 420 | if rst.str[0] == 'L' { 421 | rst.advance(1) 422 | rst.writeLifetime(rst.base62Number()) 423 | } else if rst.str[0] == 'K' { 424 | rst.advance(1) 425 | rst.demangleConst() 426 | } else { 427 | rst.demangleType() 428 | } 429 | } 430 | 431 | // = "G" 432 | // This is optional. 433 | func (rst *rustState) binder() { 434 | if len(rst.str) < 1 || rst.str[0] != 'G' { 435 | return 436 | } 437 | rst.advance(1) 438 | 439 | binderLifetimes := rst.base62Number() + 1 440 | 441 | // Every bound lifetime should be referenced later. 442 | if binderLifetimes >= int64(len(rst.str))-rst.lifetimes { 443 | rst.fail("binder lifetimes overflow") 444 | } 445 | 446 | rst.writeString("for<") 447 | for i := int64(0); i < binderLifetimes; i++ { 448 | if i > 0 { 449 | rst.writeString(", ") 450 | } 451 | rst.lifetimes++ 452 | rst.writeLifetime(1) 453 | } 454 | rst.writeString("> ") 455 | } 456 | 457 | // = 458 | // | // named type 459 | // | "A" // [T; N] 460 | // | "S" // [T] 461 | // | "T" {} "E" // (T1, T2, T3, ...) 462 | // | "R" [] // &T 463 | // | "Q" [] // &mut T 464 | // | "P" // *const T 465 | // | "O" // *mut T 466 | // | "F" // fn(...) -> ... 467 | // | "D" // dyn Trait + Send + 'a 468 | // | 469 | func (rst *rustState) demangleType() { 470 | if len(rst.str) < 1 { 471 | rst.fail("expected type") 472 | } 473 | c := rst.str[0] 474 | if c >= 'a' && c <= 'z' { 475 | rst.basicType() 476 | return 477 | } 478 | switch c { 479 | case 'C', 'M', 'X', 'Y', 'N', 'I': 480 | rst.path(false) 481 | case 'A', 'S': 482 | rst.advance(1) 483 | rst.writeByte('[') 484 | rst.demangleType() 485 | if c == 'A' { 486 | rst.writeString("; ") 487 | rst.demangleConst() 488 | } 489 | rst.writeByte(']') 490 | case 'T': 491 | rst.advance(1) 492 | rst.writeByte('(') 493 | c := 0 494 | for len(rst.str) > 0 && rst.str[0] != 'E' { 495 | if c > 0 { 496 | rst.writeString(", ") 497 | } 498 | c++ 499 | rst.demangleType() 500 | } 501 | if c == 1 { 502 | rst.writeByte(',') 503 | } 504 | rst.writeByte(')') 505 | rst.checkChar('E') 506 | case 'R', 'Q': 507 | rst.advance(1) 508 | rst.writeByte('&') 509 | if len(rst.str) > 0 && rst.str[0] == 'L' { 510 | rst.advance(1) 511 | if lifetime := rst.base62Number(); lifetime > 0 { 512 | rst.writeLifetime(lifetime) 513 | rst.writeByte(' ') 514 | } 515 | } 516 | if c == 'Q' { 517 | rst.writeString("mut ") 518 | } 519 | rst.demangleType() 520 | case 'P': 521 | rst.advance(1) 522 | rst.writeString("*const ") 523 | rst.demangleType() 524 | case 'O': 525 | rst.advance(1) 526 | rst.writeString("*mut ") 527 | rst.demangleType() 528 | case 'F': 529 | rst.advance(1) 530 | hold := rst.lifetimes 531 | rst.fnSig() 532 | rst.lifetimes = hold 533 | case 'D': 534 | rst.advance(1) 535 | hold := rst.lifetimes 536 | rst.dynBounds() 537 | rst.lifetimes = hold 538 | if len(rst.str) == 0 || rst.str[0] != 'L' { 539 | rst.fail("expected L") 540 | } 541 | rst.advance(1) 542 | if lifetime := rst.base62Number(); lifetime > 0 { 543 | if rst.last != ' ' { 544 | rst.writeByte(' ') 545 | } 546 | rst.writeString("+ ") 547 | rst.writeLifetime(lifetime) 548 | } 549 | case 'B': 550 | rst.backref(rst.demangleType) 551 | default: 552 | rst.fail("unrecognized character in type") 553 | } 554 | } 555 | 556 | var rustBasicTypes = map[byte]string{ 557 | 'a': "i8", 558 | 'b': "bool", 559 | 'c': "char", 560 | 'd': "f64", 561 | 'e': "str", 562 | 'f': "f32", 563 | 'h': "u8", 564 | 'i': "isize", 565 | 'j': "usize", 566 | 'l': "i32", 567 | 'm': "u32", 568 | 'n': "i128", 569 | 'o': "u128", 570 | 'p': "_", 571 | 's': "i16", 572 | 't': "u16", 573 | 'u': "()", 574 | 'v': "...", 575 | 'x': "i64", 576 | 'y': "u64", 577 | 'z': "!", 578 | } 579 | 580 | // 581 | func (rst *rustState) basicType() { 582 | if len(rst.str) < 1 { 583 | rst.fail("expected basic type") 584 | } 585 | str, ok := rustBasicTypes[rst.str[0]] 586 | if !ok { 587 | rst.fail("unrecognized basic type character") 588 | } 589 | rst.advance(1) 590 | rst.writeString(str) 591 | } 592 | 593 | // = [] ["U"] ["K" ] {} "E" 594 | // = "C" 595 | // | 596 | func (rst *rustState) fnSig() { 597 | rst.binder() 598 | if len(rst.str) > 0 && rst.str[0] == 'U' { 599 | rst.advance(1) 600 | rst.writeString("unsafe ") 601 | } 602 | if len(rst.str) > 0 && rst.str[0] == 'K' { 603 | rst.advance(1) 604 | if len(rst.str) > 0 && rst.str[0] == 'C' { 605 | rst.advance(1) 606 | rst.writeString(`extern "C" `) 607 | } else { 608 | rst.writeString(`extern "`) 609 | id := rst.undisambiguatedIdentifier() 610 | id = strings.ReplaceAll(id, "_", "-") 611 | rst.writeString(id) 612 | rst.writeString(`" `) 613 | } 614 | } 615 | rst.writeString("fn(") 616 | first := true 617 | for len(rst.str) > 0 && rst.str[0] != 'E' { 618 | if first { 619 | first = false 620 | } else { 621 | rst.writeString(", ") 622 | } 623 | rst.demangleType() 624 | } 625 | rst.checkChar('E') 626 | rst.writeByte(')') 627 | if len(rst.str) > 0 && rst.str[0] == 'u' { 628 | rst.advance(1) 629 | } else { 630 | rst.writeString(" -> ") 631 | rst.demangleType() 632 | } 633 | } 634 | 635 | // = [] {} "E" 636 | func (rst *rustState) dynBounds() { 637 | rst.writeString("dyn ") 638 | rst.binder() 639 | first := true 640 | for len(rst.str) > 0 && rst.str[0] != 'E' { 641 | if first { 642 | first = false 643 | } else { 644 | rst.writeString(" + ") 645 | } 646 | rst.dynTrait() 647 | } 648 | rst.checkChar('E') 649 | } 650 | 651 | // = {} 652 | // = "p" 653 | func (rst *rustState) dynTrait() { 654 | started := rst.pathStartGenerics() 655 | for len(rst.str) > 0 && rst.str[0] == 'p' { 656 | rst.advance(1) 657 | if started { 658 | rst.writeString(", ") 659 | } else { 660 | rst.writeByte('<') 661 | started = true 662 | } 663 | rst.writeString(rst.undisambiguatedIdentifier()) 664 | rst.writeString(" = ") 665 | rst.demangleType() 666 | } 667 | if started { 668 | rst.writeByte('>') 669 | } 670 | } 671 | 672 | // pathStartGenerics is like path but if it sees an I to start generic 673 | // arguments it won't close them. It reports whether it started generics. 674 | func (rst *rustState) pathStartGenerics() bool { 675 | if len(rst.str) < 1 { 676 | rst.fail("expected path") 677 | } 678 | switch rst.str[0] { 679 | case 'I': 680 | rst.advance(1) 681 | rst.path(false) 682 | rst.writeByte('<') 683 | first := true 684 | for len(rst.str) > 0 && rst.str[0] != 'E' { 685 | if first { 686 | first = false 687 | } else { 688 | rst.writeString(", ") 689 | } 690 | rst.genericArg() 691 | } 692 | rst.checkChar('E') 693 | return true 694 | case 'B': 695 | var started bool 696 | rst.backref(func() { started = rst.pathStartGenerics() }) 697 | return started 698 | default: 699 | rst.path(false) 700 | return false 701 | } 702 | } 703 | 704 | // writeLifetime writes out a lifetime binding. 705 | func (rst *rustState) writeLifetime(lifetime int64) { 706 | rst.writeByte('\'') 707 | if lifetime == 0 { 708 | rst.writeByte('_') 709 | return 710 | } 711 | depth := rst.lifetimes - lifetime 712 | if depth < 0 { 713 | rst.fail("invalid lifetime") 714 | } else if depth < 26 { 715 | rst.writeByte('a' + byte(depth)) 716 | } else { 717 | rst.writeByte('z') 718 | if !rst.skip { 719 | fmt.Fprintf(&rst.buf, "%d", depth-26+1) 720 | rst.last = '0' 721 | } 722 | } 723 | } 724 | 725 | // = 726 | // | "p" // placeholder, shown as _ 727 | // | 728 | // = ["n"] {} "_" 729 | func (rst *rustState) demangleConst() { 730 | if len(rst.str) < 1 { 731 | rst.fail("expected constant") 732 | } 733 | 734 | if rst.str[0] == 'B' { 735 | rst.backref(rst.demangleConst) 736 | return 737 | } 738 | 739 | if rst.str[0] == 'p' { 740 | rst.advance(1) 741 | rst.writeByte('_') 742 | return 743 | } 744 | 745 | typ := rst.str[0] 746 | 747 | const ( 748 | invalid = iota 749 | signedInt 750 | unsignedInt 751 | boolean 752 | character 753 | ) 754 | 755 | var kind int 756 | switch typ { 757 | case 'a', 's', 'l', 'x', 'n', 'i': 758 | kind = signedInt 759 | case 'h', 't', 'm', 'y', 'o', 'j': 760 | kind = unsignedInt 761 | case 'b': 762 | kind = boolean 763 | case 'c': 764 | kind = character 765 | default: 766 | rst.fail("unrecognized constant type") 767 | } 768 | 769 | rst.advance(1) 770 | 771 | if kind == signedInt && len(rst.str) > 0 && rst.str[0] == 'n' { 772 | rst.advance(1) 773 | rst.writeByte('-') 774 | } 775 | 776 | start := rst.str 777 | digits := 0 778 | val := uint64(0) 779 | digitLoop: 780 | for len(rst.str) > 0 { 781 | c := rst.str[0] 782 | var digit uint64 783 | switch { 784 | case c >= '0' && c <= '9': 785 | digit = uint64(c - '0') 786 | case c >= 'a' && c <= 'f': 787 | digit = uint64(c - 'a' + 10) 788 | case c == '_': 789 | rst.advance(1) 790 | break digitLoop 791 | default: 792 | rst.fail("expected hex digit or _") 793 | } 794 | rst.advance(1) 795 | if val == 0 && digit == 0 && (len(rst.str) == 0 || rst.str[0] != '_') { 796 | rst.fail("invalid leading 0 in constant") 797 | } 798 | val *= 16 799 | val += digit 800 | digits++ 801 | } 802 | 803 | if digits == 0 { 804 | rst.fail("expected constant") 805 | } 806 | 807 | switch kind { 808 | case signedInt, unsignedInt: 809 | if digits > 16 { 810 | // Value too big, just write out the string. 811 | rst.writeString("0x") 812 | rst.writeString(start[:digits]) 813 | } else { 814 | if !rst.skip { 815 | fmt.Fprintf(&rst.buf, "%d", val) 816 | rst.last = '0' 817 | } 818 | } 819 | case boolean: 820 | if digits > 1 { 821 | rst.fail("boolean value too large") 822 | } else if val == 0 { 823 | rst.writeString("false") 824 | } else if val == 1 { 825 | rst.writeString("true") 826 | } else { 827 | rst.fail("invalid boolean value") 828 | } 829 | case character: 830 | if digits > 6 { 831 | rst.fail("character value too large") 832 | } 833 | rst.writeByte('\'') 834 | if val == '\t' { 835 | rst.writeString(`\t`) 836 | } else if val == '\r' { 837 | rst.writeString(`\r`) 838 | } else if val == '\n' { 839 | rst.writeString(`\n`) 840 | } else if val == '\\' { 841 | rst.writeString(`\\`) 842 | } else if val == '\'' { 843 | rst.writeString(`\'`) 844 | } else if val >= ' ' && val <= '~' { 845 | // printable ASCII character 846 | rst.writeByte(byte(val)) 847 | } else { 848 | if !rst.skip { 849 | fmt.Fprintf(&rst.buf, `\u{%x}`, val) 850 | rst.last = '}' 851 | } 852 | } 853 | rst.writeByte('\'') 854 | default: 855 | panic("internal error") 856 | } 857 | } 858 | 859 | // = {<0-9a-zA-Z>} "_" 860 | func (rst *rustState) base62Number() int64 { 861 | if len(rst.str) > 0 && rst.str[0] == '_' { 862 | rst.advance(1) 863 | return 0 864 | } 865 | val := int64(0) 866 | for len(rst.str) > 0 { 867 | c := rst.str[0] 868 | rst.advance(1) 869 | if c == '_' { 870 | return val + 1 871 | } 872 | val *= 62 873 | if c >= '0' && c <= '9' { 874 | val += int64(c - '0') 875 | } else if c >= 'a' && c <= 'z' { 876 | val += int64(c - 'a' + 10) 877 | } else if c >= 'A' && c <= 'Z' { 878 | val += int64(c - 'A' + 36) 879 | } else { 880 | rst.fail("invalid digit in base 62 number") 881 | } 882 | } 883 | rst.fail("expected _ after base 62 number") 884 | return 0 885 | } 886 | 887 | // = "B" 888 | func (rst *rustState) backref(demangle func()) { 889 | backoff := rst.off 890 | 891 | rst.checkChar('B') 892 | idx64 := rst.base62Number() 893 | 894 | if rst.skip { 895 | return 896 | } 897 | 898 | idx := int(idx64) 899 | if int64(idx) != idx64 { 900 | rst.fail("backref index overflow") 901 | } 902 | if idx < 0 || idx >= backoff { 903 | rst.fail("invalid backref index") 904 | } 905 | 906 | holdStr := rst.str 907 | holdOff := rst.off 908 | rst.str = rst.orig[idx:backoff] 909 | rst.off = idx 910 | defer func() { 911 | rst.str = holdStr 912 | rst.off = holdOff 913 | }() 914 | 915 | demangle() 916 | } 917 | 918 | func (rst *rustState) decimalNumber() int { 919 | if len(rst.str) == 0 { 920 | rst.fail("expected number") 921 | } 922 | 923 | val := 0 924 | for len(rst.str) > 0 && isDigit(rst.str[0]) { 925 | add := int(rst.str[0] - '0') 926 | if val >= math.MaxInt32/10-add { 927 | rst.fail("decimal number overflow") 928 | } 929 | val *= 10 930 | val += add 931 | rst.advance(1) 932 | } 933 | return val 934 | } 935 | 936 | // oldRustToString demangles a Rust symbol using the old demangling. 937 | // The second result reports whether this is a valid Rust mangled name. 938 | func oldRustToString(name string, options []Option) (string, bool) { 939 | // We know that the string starts with _ZN. 940 | name = name[3:] 941 | 942 | hexDigit := func(c byte) (byte, bool) { 943 | switch { 944 | case c >= '0' && c <= '9': 945 | return c - '0', true 946 | case c >= 'a' && c <= 'f': 947 | return c - 'a' + 10, true 948 | default: 949 | return 0, false 950 | } 951 | } 952 | 953 | // We know that the strings end with "17h" followed by 16 characters 954 | // followed by "E". We check that the 16 characters are all hex digits. 955 | // Also the hex digits must contain at least 5 distinct digits. 956 | seen := uint16(0) 957 | for i := len(name) - 17; i < len(name)-1; i++ { 958 | digit, ok := hexDigit(name[i]) 959 | if !ok { 960 | return "", false 961 | } 962 | seen |= 1 << digit 963 | } 964 | if bits.OnesCount16(seen) < 5 { 965 | return "", false 966 | } 967 | name = name[:len(name)-20] 968 | 969 | // The name is a sequence of length-preceded identifiers. 970 | var sb strings.Builder 971 | for len(name) > 0 { 972 | if !isDigit(name[0]) { 973 | return "", false 974 | } 975 | 976 | val := 0 977 | for len(name) > 0 && isDigit(name[0]) { 978 | add := int(name[0] - '0') 979 | if val >= math.MaxInt32/10-add { 980 | return "", false 981 | } 982 | val *= 10 983 | val += add 984 | name = name[1:] 985 | } 986 | 987 | // An optional trailing underscore can separate the 988 | // length from the identifier. 989 | if len(name) > 0 && name[0] == '_' { 990 | name = name[1:] 991 | val-- 992 | } 993 | 994 | if len(name) < val { 995 | return "", false 996 | } 997 | 998 | id := name[:val] 999 | name = name[val:] 1000 | 1001 | if sb.Len() > 0 { 1002 | sb.WriteString("::") 1003 | } 1004 | 1005 | // Ignore leading underscores preceding escape sequences. 1006 | if strings.HasPrefix(id, "_$") { 1007 | id = id[1:] 1008 | } 1009 | 1010 | // The identifier can have escape sequences. 1011 | escape: 1012 | for len(id) > 0 { 1013 | switch c := id[0]; c { 1014 | case '$': 1015 | codes := map[string]byte{ 1016 | "SP": '@', 1017 | "BP": '*', 1018 | "RF": '&', 1019 | "LT": '<', 1020 | "GT": '>', 1021 | "LP": '(', 1022 | "RP": ')', 1023 | } 1024 | 1025 | valid := true 1026 | if len(id) > 2 && id[1] == 'C' && id[2] == '$' { 1027 | sb.WriteByte(',') 1028 | id = id[3:] 1029 | } else if len(id) > 4 && id[1] == 'u' && id[4] == '$' { 1030 | dig1, ok1 := hexDigit(id[2]) 1031 | dig2, ok2 := hexDigit(id[3]) 1032 | val := (dig1 << 4) | dig2 1033 | if !ok1 || !ok2 || dig1 > 7 || val < ' ' { 1034 | valid = false 1035 | } else { 1036 | sb.WriteByte(val) 1037 | id = id[5:] 1038 | } 1039 | } else if len(id) > 3 && id[3] == '$' { 1040 | if code, ok := codes[id[1:3]]; !ok { 1041 | valid = false 1042 | } else { 1043 | sb.WriteByte(code) 1044 | id = id[4:] 1045 | } 1046 | } else { 1047 | valid = false 1048 | } 1049 | if !valid { 1050 | sb.WriteString(id) 1051 | break escape 1052 | } 1053 | case '.': 1054 | if strings.HasPrefix(id, "..") { 1055 | sb.WriteString("::") 1056 | id = id[2:] 1057 | } else { 1058 | sb.WriteByte(c) 1059 | id = id[1:] 1060 | } 1061 | default: 1062 | sb.WriteByte(c) 1063 | id = id[1:] 1064 | } 1065 | } 1066 | } 1067 | 1068 | return sb.String(), true 1069 | } 1070 | -------------------------------------------------------------------------------- /demangle_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package demangle 6 | 7 | import ( 8 | "strconv" 9 | "strings" 10 | "testing" 11 | ) 12 | 13 | // Check test cases discovered after the code passed the tests in 14 | // demangle-expected (which are tested by TestExpected). Some of this 15 | // are cases where we differ from the standard demangler, some we are 16 | // the same but we weren't initially. 17 | func TestDemangler(t *testing.T) { 18 | var tests = []struct { 19 | input string 20 | want string 21 | wantNoParams string 22 | wantNoTemplateParams string 23 | wantMinimal string 24 | }{ 25 | { 26 | "_ZNSaIcEC1ERKS_", 27 | "std::allocator::allocator(std::allocator const&)", 28 | "std::allocator::allocator", 29 | "std::allocator::allocator(std::allocator const&)", 30 | "std::allocator::allocator", 31 | }, 32 | { 33 | "_ZN9__gnu_cxx13stdio_filebufIcSt11char_traitsIcEEC1EP8_IO_FILESt13_Ios_Openmodem", 34 | "__gnu_cxx::stdio_filebuf >::stdio_filebuf(_IO_FILE*, std::_Ios_Openmode, unsigned long)", 35 | "__gnu_cxx::stdio_filebuf >::stdio_filebuf", 36 | "__gnu_cxx::stdio_filebuf::stdio_filebuf(_IO_FILE*, std::_Ios_Openmode, unsigned long)", 37 | "__gnu_cxx::stdio_filebuf::stdio_filebuf", 38 | }, 39 | { 40 | "_ZN1n1CcvNS_1DIT_EEI1EEEv", 41 | "n::C::operator n::D()", 42 | "n::C::operator n::D", 43 | "n::C::operator n::D()", 44 | "n::C::operator n::D", 45 | }, 46 | { 47 | "_Z1CIvPN1D1E1FIdJEEEdEPN1GILb0ET_T0_T1_E1HEPFS6_S7_S8_EN1H1I1JIS7_E1KENSG_IS8_E1KE", 48 | "G*, double>::H* C*, double>(void (*)(D::E::F*, double), H::I::J*>::K, H::I::J::K)", 49 | "C*, double>", 50 | "G::H* C(void (*)(D::E::F*, double), H::I::J::K, H::I::J::K)", 51 | "C", 52 | }, 53 | { 54 | "_ZZNK1CI1DIcSt1EIcESaIcEEJEE1FEvE1F", 55 | "C, std::allocator > >::F() const::F", 56 | "C, std::allocator > >::F() const::F", 57 | "C::F() const::F", 58 | "C::F() const::F", 59 | }, 60 | { 61 | "_ZN1CI1DSt1EIK1FN1G1HEEE1I1JIJRKS6_EEEvDpOT_", 62 | "void C >::I::J const&>(std::E const&)", 63 | "C >::I::J const&>", 64 | "void C::I::J(std::E const&)", 65 | "C::I::J", 66 | }, 67 | { 68 | "_ZN1C1D1E1FIJEEEvi1GDpT_", 69 | "void C::D::E::F<>(int, G)", 70 | "C::D::E::F<>", 71 | "void C::D::E::F(int, G)", 72 | "C::D::E::F", 73 | }, 74 | { 75 | "_ZN1CILj50ELb1EE1DEv", 76 | "C<50u, true>::D()", 77 | "C<50u, true>::D", 78 | "C::D()", 79 | "C::D", 80 | }, 81 | { 82 | "_ZN1CUt_C2Ev", 83 | "C::{unnamed type#1}::{unnamed type#1}()", 84 | "C::{unnamed type#1}::{unnamed type#1}", 85 | "C::{unnamed type#1}::{unnamed type#1}()", 86 | "C::{unnamed type#1}::{unnamed type#1}", 87 | }, 88 | { 89 | "_ZN1C12_GLOBAL__N_11DINS_1EEEEN1F1GIDTadcldtcvT__E1HEEEERKS5_NS_1I1JE", 90 | "F::G C::(anonymous namespace)::D(C::E const&, C::I::J)", 91 | "C::(anonymous namespace)::D", 92 | "F::G C::(anonymous namespace)::D(C::E const&, C::I::J)", 93 | "C::(anonymous namespace)::D", 94 | }, 95 | { 96 | "_ZN1CI1DE1EIJiRiRPKcRA1_S4_S8_bS6_S3_RjRPKN1F1GERPKN1H1IEEEEvDpOT_", 97 | "void C::E(int&&, int&, char const*&, char const (&) [1], char const (&) [1], bool&&, char const*&, int&, unsigned int&, F::G const*&, H::I const*&)", 98 | "C::E", 99 | "void C::E(int&&, int&, char const*&, char const (&) [1], char const (&) [1], bool&&, char const*&, int&, unsigned int&, F::G const*&, H::I const*&)", 100 | "C::E", 101 | }, 102 | { 103 | "_ZN1C12_GLOBAL__N_11DIFbPKNS_1EEEEEvPNS_1FERKT_", 104 | "void C::(anonymous namespace)::D(C::F*, bool (&)(C::E const*) const)", 105 | "C::(anonymous namespace)::D", 106 | "void C::(anonymous namespace)::D(C::F*, bool (&)(C::E const*) const)", 107 | "C::(anonymous namespace)::D", 108 | }, 109 | { 110 | "_ZN1C1D1EIJRFviSt1FIFvRKN1G1H1IEEERKSt6vectorINS_1JESaISB_EEERiS9_EvEENS0_1K1LIJDpNSt1MIT_E1NEEEEDpOSM_", 111 | "C::D::K::L, std::vector > const&)>::N, std::M::N, std::M >::N> C::D::E, std::vector > const&), int&, std::F, void>(void (&)(int, std::F, std::vector > const&), int&, std::F&&)", 112 | "C::D::E, std::vector > const&), int&, std::F, void>", 113 | "C::D::K::L C::D::E(void (&)(int, std::F, std::vector const&), int&, std::F&&)", 114 | "C::D::E", 115 | }, 116 | { 117 | "_ZN1C1D1E1FcvNS_1GIT_EEI1HEEv", 118 | "C::D::E::F::operator C::G()", 119 | "C::D::E::F::operator C::G", 120 | "C::D::E::F::operator C::G()", 121 | "C::D::E::F::operator C::G", 122 | }, 123 | { 124 | "_ZN9__gnu_cxx17__normal_iteratorIPK1EIN1F1G1HEESt6vectorIS5_SaIS5_EEEC2IPS5_EERKNS0_IT_NS_11__enable_ifIXsr3std10__are_sameISE_SD_EE7__valueESA_E1IEEE", 125 | "__gnu_cxx::__normal_iterator const*, std::vector, std::allocator > > >::__normal_iterator*>(__gnu_cxx::__normal_iterator*, __gnu_cxx::__enable_if*, E*>::__value, std::vector, std::allocator > > >::I> const&)", 126 | "__gnu_cxx::__normal_iterator const*, std::vector, std::allocator > > >::__normal_iterator*>", 127 | "__gnu_cxx::__normal_iterator::__normal_iterator(__gnu_cxx::__normal_iterator const&)", 128 | "__gnu_cxx::__normal_iterator::__normal_iterator", 129 | }, 130 | { 131 | "_ZNKSt1CIM1DKFjvEEclIJEvEEjPKS0_DpOT_", 132 | "unsigned int std::C::operator()(D const*) const", 133 | "std::C::operator()", 134 | "unsigned int std::C::operator()(D const*) const", 135 | "std::C::operator()", 136 | }, 137 | { 138 | "_ZNSt10_HashtableI12basic_stringIcSt11char_traitsIcESaIcEESt4pairIKS4_N1C1D1EEESaISA_ENSt8__detail10_Select1stESt8equal_toIS4_ESt4hashIS4_ENSC_18_Mod_range_hashingENSC_20_Default_ranged_hashENSC_20_Prime_rehash_policyENSC_17_Hashtable_traitsILb1ELb0ELb1EEEE9_M_assignIZNSN_C1ERKSN_EUlPKNSC_10_Hash_nodeISA_Lb1EEEE_EEvSQ_RKT_", 139 | "void std::_Hashtable, std::allocator >, std::pair, std::allocator > const, C::D::E>, std::allocator, std::allocator > const, C::D::E> >, std::__detail::_Select1st, std::equal_to, std::allocator > >, std::hash, std::allocator > >, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits >::_M_assign, std::allocator >, std::pair, std::allocator > const, C::D::E>, std::allocator, std::allocator > const, C::D::E> >, std::__detail::_Select1st, std::equal_to, std::allocator > >, std::hash, std::allocator > >, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits >::_Hashtable(std::_Hashtable, std::allocator >, std::pair, std::allocator > const, C::D::E>, std::allocator, std::allocator > const, C::D::E> >, std::__detail::_Select1st, std::equal_to, std::allocator > >, std::hash, std::allocator > >, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits > const&)::{lambda(std::__detail::_Hash_node, std::allocator > const, C::D::E>, true> const*)#1}>(std::_Hashtable, std::allocator >, std::pair, std::allocator > const, C::D::E>, std::allocator, std::allocator > const, C::D::E> >, std::__detail::_Select1st, std::equal_to, std::allocator > >, std::hash, std::allocator > >, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits > const&, std::_Hashtable, std::allocator >, std::pair, std::allocator > const, C::D::E>, std::allocator, std::allocator > const, C::D::E> >, std::__detail::_Select1st, std::equal_to, std::allocator > >, std::hash, std::allocator > >, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits >::_Hashtable(std::_Hashtable, std::allocator >, std::pair, std::allocator > const, C::D::E>, std::allocator, std::allocator > const, C::D::E> >, std::__detail::_Select1st, std::equal_to, std::allocator > >, std::hash, std::allocator > >, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits > const&)::{lambda(std::__detail::_Hash_node, std::allocator > const, C::D::E>, true> const*)#1} const&)", 140 | "std::_Hashtable, std::allocator >, std::pair, std::allocator > const, C::D::E>, std::allocator, std::allocator > const, C::D::E> >, std::__detail::_Select1st, std::equal_to, std::allocator > >, std::hash, std::allocator > >, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits >::_M_assign, std::allocator >, std::pair, std::allocator > const, C::D::E>, std::allocator, std::allocator > const, C::D::E> >, std::__detail::_Select1st, std::equal_to, std::allocator > >, std::hash, std::allocator > >, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits >::_Hashtable(std::_Hashtable, std::allocator >, std::pair, std::allocator > const, C::D::E>, std::allocator, std::allocator > const, C::D::E> >, std::__detail::_Select1st, std::equal_to, std::allocator > >, std::hash, std::allocator > >, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits > const&)::{lambda(std::__detail::_Hash_node, std::allocator > const, C::D::E>, true> const*)#1}>", 141 | "void std::_Hashtable::_M_assign(std::_Hashtable const&, std::_Hashtable::_Hashtable(std::_Hashtable const&)::{lambda(std::__detail::_Hash_node const*)#1} const&)", 142 | "std::_Hashtable::_M_assign", 143 | }, 144 | { 145 | "_ZSt3maxIVdERKT_S3_S3_", 146 | "double const volatile& std::max(double const volatile&, double const volatile&)", 147 | "std::max", 148 | "double const volatile& std::max(double const volatile&, double const volatile&)", 149 | "std::max", 150 | }, 151 | { 152 | "_ZZN1C1D1E1F1G1HEvENUlvE_C2EOS4_", 153 | "C::D::E::F::G::H()::{lambda()#1}::{lambda()#1}({lambda()#1}&&)", 154 | "C::D::E::F::G::H()::{lambda()#1}::{lambda()#1}", 155 | "C::D::E::F::G::H()::{lambda()#1}::{lambda()#1}({lambda()#1}&&)", 156 | "C::D::E::F::G::H()::{lambda()#1}::{lambda()#1}", 157 | }, 158 | { 159 | "_ZThn8_NK1C1D1EEv", 160 | "non-virtual thunk to C::D::E() const", 161 | "non-virtual thunk to C::D::E() const", 162 | "non-virtual thunk to C::D::E() const", 163 | "non-virtual thunk to C::D::E() const", 164 | }, 165 | { 166 | "_ZTv0_n96_NK1C1D1E1FEv", 167 | "virtual thunk to C::D::E::F() const", 168 | "virtual thunk to C::D::E::F() const", 169 | "virtual thunk to C::D::E::F() const", 170 | "virtual thunk to C::D::E::F() const", 171 | }, 172 | { 173 | "_ZTCSt9strstream16_So", 174 | "construction vtable for std::ostream-in-std::strstream", 175 | "construction vtable for std::ostream-in-std::strstream", 176 | "construction vtable for std::ostream-in-std::strstream", 177 | "construction vtable for std::ostream-in-std::strstream", 178 | }, 179 | { 180 | "_ZGVZZN1C1D1EEvENK3$_0clEvE1F", 181 | "guard variable for C::D::E()::$_0::operator()() const::F", 182 | "guard variable for C::D::E()::$_0::operator()() const::F", 183 | "guard variable for C::D::E()::$_0::operator()() const::F", 184 | "guard variable for C::D::E()::$_0::operator()() const::F", 185 | }, 186 | { 187 | "_Z1fICiEvT_", 188 | "void f(int _Complex)", 189 | "f", 190 | "void f(int _Complex)", 191 | "f", 192 | }, 193 | { 194 | "_GLOBAL__D__Z2fnv", 195 | "global destructors keyed to fn()", 196 | "global destructors keyed to fn()", 197 | "global destructors keyed to fn()", 198 | "global destructors keyed to fn()", 199 | }, 200 | { 201 | "_Z1fIXadL_Z1hvEEEvv", 202 | "void f<&h>()", 203 | "f<&h>", 204 | "void f()", 205 | "f", 206 | }, 207 | { 208 | "_Z1CIP1DEiRK1EPT_N1F1GIS5_Xaasr1HIS5_E1IntsrSA_1JEE1KE", 209 | "int C(E const&, D**, F::G::I&&(!H::J)>::K)", 210 | "C", 211 | "int C(E const&, D**, F::G::K)", 212 | "C", 213 | }, 214 | { 215 | "_ZNO1A1B1C1DIZN1E1F1GINS3_1HE1IEEvMNS3_1JEFvP1LPKT_PT0_P1KESD_SA_SF_SH_EUlvE_Lb0EEcvPSB_ISG_vvEEv", 216 | "A::B::C::D(void (E::J::*)(L*, E::H const*, I*, K*), E::H const*, L*, I*, K*)::{lambda()#1}, false>::operator K*() &&", 217 | "A::B::C::D(void (E::J::*)(L*, E::H const*, I*, K*), E::H const*, L*, I*, K*)::{lambda()#1}, false>::operator K*", 218 | "A::B::C::D::operator K*() &&", 219 | "A::B::C::D::operator K*", 220 | }, 221 | { 222 | "_ZNSt1AIFSt1BImjEjEZN1C1DI1EEENSt1FIXeqsr1G1H1IIDTadsrT_onclEEE1JLi2EEvE1KEPKcSC_OS7_EUljE_E1KERKSt1Lj", 223 | "std::A (unsigned int), C::D(char const*, G::H::I, G&&)::{lambda(unsigned int)#1}>::K(std::L const&, unsigned int)", 224 | "std::A (unsigned int), C::D(char const*, G::H::I, G&&)::{lambda(unsigned int)#1}>::K", 225 | "std::A::K(std::L const&, unsigned int)", 226 | "std::A::K", 227 | }, 228 | { 229 | "_ZNSt1A1BIiNS_1CIiEEE1DIPiEENS_1EIXaasr1FIT_EE1Gsr1HIiNS_1IIS7_E1JEEE1KEvE1LES7_S7_", 230 | "std::A::E::G&&H::J>::K, void>::L std::A::B >::D(F, F)", 231 | "std::A::B >::D", 232 | "std::A::E::L std::A::B::D(F, F)", 233 | "std::A::B::D", 234 | }, 235 | { 236 | "_ZNO1A1B1C1DIJOZZN1E1F1GINS4_1HINS4_1IINS4_1JEEEEEJNS4_1KEEEEN1L1MINS4_1OINT_1PEEEEERKSt6vectorIN1Q1RESaISL_EERKN3gtl1S1TIN1U1VEEERKNS4_1W1XERKNS4_1YERKNSQ_1ZINS4_1aEEEPSt13unordered_mapISL_NSK_9UniquePtrINS4_1bINS0_1cIJS9_NS7_INST_1dEEEEEENS4_1fEEEEENSC_1g1hIvEESt8equal_toISL_ESaISt4pairIKSL_S1J_EEEDpRKT0_ENKUlSL_mmS1G_E_clESL_mmS1G_EUlS9_E_OZZNS5_ISA_JSB_EEESI_SP_SX_S11_S14_S19_S1U_S1Y_ENKS1Z_clESL_mmS1G_EUlS1F_E0_EEclIJRS9_EEEDTclcl1iIXsrNS1_1jISt5tupleIJNS1_1kIS21_EENS29_IS23_EEEEJDpT_EEE1lEEcl1mIS2C_EEEspcl1mIS2D_EEEEDpOS2D_", 237 | "decltype (((i >, E::F::K>(std::vector > const&, gtl::S::T const&, E::F::W::X const&, E::F::Y const&, gtl::Z const&, std::unordered_map, E::F::I >, E::F::f> >, L::g::h, std::equal_to, std::allocator, E::F::I >, E::F::f> > > > >*, E::F::K const&)::{lambda(Q::R, unsigned long, unsigned long, A::B::c, E::F::I >)#1}::operator()(Q::R, unsigned long, unsigned long, A::B::c, E::F::I >) const::{lambda(E::F::I)#1}&&>, A::B::C::k >, E::F::K>(std::vector > const&, gtl::S::T const&, E::F::W::X const&, E::F::Y const&, gtl::Z const&, std::unordered_map, E::F::I >, E::F::f> >, L::g::h, std::equal_to, std::allocator, E::F::I >, E::F::f> > > > >*, E::F::K const&)::{lambda(Q::R, unsigned long, unsigned long, A::B::c, E::F::I >)#1}::operator()(Q::R, unsigned long, unsigned long, A::B::c, E::F::I >) const::{lambda(E::F::I)#2}&&> >, E::F::I&>::l>)((m >, E::F::K>(std::vector > const&, gtl::S::T const&, E::F::W::X const&, E::F::Y const&, gtl::Z const&, std::unordered_map, E::F::I >, E::F::f> >, L::g::h, std::equal_to, std::allocator, E::F::I >, E::F::f> > > > >*, E::F::K const&)::{lambda(Q::R, unsigned long, unsigned long, A::B::c, E::F::I >)#1}::operator()(Q::R, unsigned long, unsigned long, A::B::c, E::F::I >) const::{lambda(E::F::I)#1}&&>, A::B::C::k >, E::F::K>(std::vector > const&, gtl::S::T const&, E::F::W::X const&, E::F::Y const&, gtl::Z const&, std::unordered_map, E::F::I >, E::F::f> >, L::g::h, std::equal_to, std::allocator, E::F::I >, E::F::f> > > > >*, E::F::K const&)::{lambda(Q::R, unsigned long, unsigned long, A::B::c, E::F::I >)#1}::operator()(Q::R, unsigned long, unsigned long, A::B::c, E::F::I >) const::{lambda(E::F::I)#2}&&> > >)()))((m&>)())) A::B::C::D >, E::F::K>(std::vector > const&, gtl::S::T const&, E::F::W::X const&, E::F::Y const&, gtl::Z const&, std::unordered_map, E::F::I >, E::F::f> >, L::g::h, std::equal_to, std::allocator, E::F::I >, E::F::f> > > > >*, E::F::K const&)::{lambda(Q::R, unsigned long, unsigned long, A::B::c, E::F::I >)#1}::operator()(Q::R, unsigned long, unsigned long, A::B::c, E::F::I >) const::{lambda(E::F::I)#1}&&, E::F::G >, E::F::K>(std::vector > const&, gtl::S::T const&, E::F::W::X const&, E::F::Y const&, gtl::Z const&, std::unordered_map, E::F::I >, E::F::f> >, L::g::h, std::equal_to, std::allocator, E::F::I >, E::F::f> > > > >*, E::F::K const&)::{lambda(Q::R, unsigned long, unsigned long, A::B::c, E::F::I >)#1}::operator()(Q::R, unsigned long, unsigned long, A::B::c, E::F::I >) const::{lambda(E::F::I)#2}&&>::operator()&>(E::F::I&) &&", 238 | "A::B::C::D >, E::F::K>(std::vector > const&, gtl::S::T const&, E::F::W::X const&, E::F::Y const&, gtl::Z const&, std::unordered_map, E::F::I >, E::F::f> >, L::g::h, std::equal_to, std::allocator, E::F::I >, E::F::f> > > > >*, E::F::K const&)::{lambda(Q::R, unsigned long, unsigned long, A::B::c, E::F::I >)#1}::operator()(Q::R, unsigned long, unsigned long, A::B::c, E::F::I >) const::{lambda(E::F::I)#1}&&, E::F::G >, E::F::K>(std::vector > const&, gtl::S::T const&, E::F::W::X const&, E::F::Y const&, gtl::Z const&, std::unordered_map, E::F::I >, E::F::f> >, L::g::h, std::equal_to, std::allocator, E::F::I >, E::F::f> > > > >*, E::F::K const&)::{lambda(Q::R, unsigned long, unsigned long, A::B::c, E::F::I >)#1}::operator()(Q::R, unsigned long, unsigned long, A::B::c, E::F::I >) const::{lambda(E::F::I)#2}&&>::operator()&>", 239 | "decltype (((i)((m)()))((m)())) A::B::C::D::operator()(E::F::I&) &&", 240 | "A::B::C::D::operator()", 241 | }, 242 | { 243 | "_ZcvAna_eE_e", 244 | "operator long double [new long double]", 245 | "operator long double [new long double]", 246 | "operator long double [new long double]", 247 | "operator long double [new long double]", 248 | }, 249 | { 250 | "_ZZ1irFeeEES_S_", 251 | "i(() restrict)::long double (long double)(() restrict) restrict", 252 | "i(long double (long double) restrict)::long double (long double)", 253 | "i(() restrict)::long double (long double)(() restrict) restrict", 254 | "i(long double (long double) restrict)::long double (long double)", 255 | }, 256 | { 257 | "_Z1_VFaeEZS_S_ES_", 258 | "_((() volatile) volatile, signed char (long double)(() volatile) volatile::(() volatile) volatile)", 259 | "_", 260 | "_((() volatile) volatile, signed char (long double)(() volatile) volatile::(() volatile) volatile)", 261 | "_", 262 | }, 263 | { 264 | "_ZdsrFliEZS_GS_EcvS_", 265 | "operator.*(( ( _Imaginary)( _Imaginary) restrict) restrict, long (int)( ( _Imaginary)( _Imaginary) restrict) restrict::operator ( ( _Imaginary)( _Imaginary) restrict) restrict)", 266 | "operator.*", 267 | "operator.*(( ( _Imaginary)( _Imaginary) restrict) restrict, long (int)( ( _Imaginary)( _Imaginary) restrict) restrict::operator ( ( _Imaginary)( _Imaginary) restrict) restrict)", 268 | "operator.*", 269 | }, 270 | { 271 | "_ZZN1A1B1CIfEEvPNS_1DERKNS_1EEiS6_T_S7_S7_RKNSt3__u1FIFS7_iiEEEbbPiENKUlZNS1_IfEEvS3_S6_iS6_S7_S7_S7_SD_bbSE_E1GSF_E_clESF_SF_", 272 | "A::B::C(A::D*, A::E const&, int, A::E const&, float, float, float, std::__u::F const&, bool, bool, int*)::{lambda(A::B::C(A::D*, A::E const&, int, A::E const&, float, float, float, std::__u::F const&, bool, bool, int*)::G, A::B::C(A::D*, A::E const&, int, A::E const&, float, float, float, std::__u::F const&, bool, bool, int*)::G)#1}::operator()(A::B::C(A::D*, A::E const&, int, A::E const&, float, float, float, std::__u::F const&, bool, bool, int*)::G, A::B::C(A::D*, A::E const&, int, A::E const&, float, float, float, std::__u::F const&, bool, bool, int*)::G) const", 273 | "A::B::C(A::D*, A::E const&, int, A::E const&, float, float, float, std::__u::F const&, bool, bool, int*)::{lambda(A::B::C(A::D*, A::E const&, int, A::E const&, float, float, float, std::__u::F const&, bool, bool, int*)::G, A::B::C(A::D*, A::E const&, int, A::E const&, float, float, float, std::__u::F const&, bool, bool, int*)::G)#1}::operator()", 274 | "A::B::C(A::D*, A::E const&, int, A::E const&, float, float, float, std::__u::F const&, bool, bool, int*)::{lambda(A::B::C(A::D*, A::E const&, int, A::E const&, float, float, float, std::__u::F const&, bool, bool, int*)::G, A::B::C(A::D*, A::E const&, int, A::E const&, float, float, float, std::__u::F const&, bool, bool, int*)::G)#1}::operator()(A::B::C(A::D*, A::E const&, int, A::E const&, float, float, float, std::__u::F const&, bool, bool, int*)::G, A::B::C(A::D*, A::E const&, int, A::E const&, float, float, float, std::__u::F const&, bool, bool, int*)::G) const", 275 | "A::B::C(A::D*, A::E const&, int, A::E const&, float, float, float, std::__u::F const&, bool, bool, int*)::{lambda(A::B::C(A::D*, A::E const&, int, A::E const&, float, float, float, std::__u::F const&, bool, bool, int*)::G, A::B::C(A::D*, A::E const&, int, A::E const&, float, float, float, std::__u::F const&, bool, bool, int*)::G)#1}::operator()", 276 | }, 277 | { 278 | "_ZN1A1B1CIJLNS_1DE131067ELS2_4EEEC2EUa9enable_ifIXclL_ZNS0_1EIJLS2_131067ELS2_4EEEEbNSt1F1GIcNS5_1HIcEEEEEfL0p_EEEPKc", 279 | "A::B::C<(A::D)131067, (A::D)4>::C(char const*) [enable_if:bool A::B::E<(A::D)131067, (A::D)4>(std::F::G >)({parm#1})]", 280 | "A::B::C<(A::D)131067, (A::D)4>::C", 281 | "A::B::C::C(char const*) [enable_if:bool A::B::E(std::F::G)({parm#1})]", 282 | "A::B::C::C", 283 | }, 284 | { 285 | "_ZNK1A1B1C1DINS0_1EIKZNK1F1G1HIJNS4_1IINSt1J1KIcNS8_1LIcEENS8_1MIcEEEEEENS4_1NIixEEEE1OEvEUlRT_E_EERKNS8_1PIJNS4_1QISF_EENSP_ISH_EEEEEEclILm0EEEDTcldtclL_ZNS8_1RIRKSN_EEDTclsr3std1SE1TISJ_ELi0EEEvEEonclIXT_EEcl1UIXT_EEclL_ZNSX_ISU_EES10_vEEEEEv", 286 | "decltype (((decltype (std::S::T, std::J::M > >, F::N >::O() const::{lambda(auto:1&)#1} const> const&>(0)) std::J::R, std::J::M > >, F::N >::O() const::{lambda(auto:1&)#1} const> const&>()()).(operator()<0ul>))((U<0ul>)(std std::J::R, std::J::M > > >, F::Q > > const&>()()))) A::B::C::D, std::J::M > >, F::N >::O() const::{lambda(auto:1&)#1} const>, std::J::P, std::J::M > > >, F::Q > > const&>::operator()<0ul>() const", 287 | "A::B::C::D, std::J::M > >, F::N >::O() const::{lambda(auto:1&)#1} const>, std::J::P, std::J::M > > >, F::Q > > const&>::operator()<0ul>", 288 | "decltype (((decltype (std::S::T(0)) std::J::R()()).(operator()))((U)(std std::J::R()()))) A::B::C::D::operator()() const", 289 | "A::B::C::D::operator()", 290 | }, 291 | { 292 | "_ZN1A1B1CIKZN1D1E1FIJNS2_1GINSt1H1IIcNS6_1JIcEENS6_1KIcEEEEiEENS5_IixEEEE1LEvEUlRT_E_EC2EPSJ_", 293 | "A::B::C, std::H::K >, int>, D::G >::L()::{lambda(auto:1&)#1} const>::C(D::E::F, std::H::K >, int>, D::G >::L()::{lambda(auto:1&)#1} const*)", 294 | "A::B::C, std::H::K >, int>, D::G >::L()::{lambda(auto:1&)#1} const>::C", 295 | "A::B::C::C(D::E::F::L()::{lambda(auto:1&)#1} const*)", 296 | "A::B::C::C", 297 | }, 298 | { 299 | "_ZN1A1B1CILb0EvOZN1D1E1FINS3_1GENS3_1HENS3_1IEE1JEvEUlvE0_JEEET0_PNS0_1KEDpDTcp1KIT2_EcvNSt1L1MIbXsr1NE1OISE_EEEE_EEE", 300 | "void A::B::C::J()::{lambda()#2}&&>(A::B::K*)", 301 | "A::B::C::J()::{lambda()#2}&&>", 302 | "void A::B::C(A::B::K*)", 303 | "A::B::C", 304 | }, 305 | { 306 | "_ZN1A1BIJNS_1C1DIJNS_1EENS_1FEEEEENSt1G1HIcNS6_1IIcEENS6_1JIcEEEEEEDTcl1KINS1_1KIsr1LIT0_EE1NJNS1_1MIJDpT_EE1NEEE1N1NEEcldtfp_1OEfp0_EERKNS_1PISE_EEPKc", 307 | "decltype ((K, std::G::J > > restrict>::N >::N>::N::N>)(({parm#1}.O)(), {parm#2})) A::B, std::G::H, std::G::J > >(A::P const&, char const*)", 308 | "A::B, std::G::H, std::G::J > >", 309 | "decltype ((K)(({parm#1}.O)(), {parm#2})) A::B(A::P const&, char const*)", 310 | "A::B", 311 | }, 312 | { 313 | "_ZNSt1A1B1CIZN1D1E1F1GIZNS3_1H1IEixxE1JEENS_1KIFDTclclsr3stdE7declvalIT_EEEEvEEEPN1L1MENS_1OIcNS_1PIcEEEES9_EUlvE_FN1Q1RINS_1SIJNSD_1T1U1VENS6_1WEEEEEEvEEclEv", 314 | "std::A::B::C(L::M*, std::A::O >, std)::{lambda()#1}, Q::R())()) ()>())()) ()>::T::U::V, D::E::H::W> > ()>::operator()()", 315 | "std::A::B::C(L::M*, std::A::O >, std)::{lambda()#1}, Q::R())()) ()>())()) ()>::T::U::V, D::E::H::W> > ()>::operator()", 316 | "std::A::B::C::operator()()", 317 | "std::A::B::C::operator()", 318 | }, 319 | { 320 | "_ZNSt1A1B1CIFN1D1EIN1F1G1HEEERKNS5_1IEEE1JINS0_1KIZN1L1MINS2_1NIS8_S6_EENS5_12_GLOBAL__N_11OES8_S6_EEN1P1QINS_1RINSH_IT1_T2_EENS_1SISQ_EEEEEENS_1TIKT_EENSF_1UET0_EUlSA_E_SB_EEEES7_PKNS0_1VESA_", 321 | "D::E std::A::B::C (F::G::I const&)>::J, F::G::(anonymous namespace)::O, F::G::I, F::G::H>(std::A::T const>, L::U, F::G::(anonymous namespace)::O)::{lambda(F::G::I const&)#1}, D::E (F::G::I const&)> >(std::A::B::V const*, F::G::I const&)", 322 | "std::A::B::C (F::G::I const&)>::J, F::G::(anonymous namespace)::O, F::G::I, F::G::H>(std::A::T const>, L::U, F::G::(anonymous namespace)::O)::{lambda(F::G::I const&)#1}, D::E (F::G::I const&)> >", 323 | "D::E std::A::B::C::J(std::A::B::V const*, F::G::I const&)", 324 | "std::A::B::C::J", 325 | }, 326 | } 327 | 328 | for _, test := range tests { 329 | if got, err := ToString(test.input); err != nil { 330 | t.Errorf("demangling %s: unexpected error %v", test.input, err) 331 | } else if got != test.want { 332 | t.Errorf("demangling %s: got %s, want %s", test.input, got, test.want) 333 | } 334 | 335 | if got, err := ToString(test.input, NoParams); err != nil { 336 | t.Errorf("demangling NoParams %s: unexpected error %v", test.input, err) 337 | } else if got != test.wantNoParams { 338 | t.Errorf("demangling NoParams %s: got %s, want %s", test.input, got, test.wantNoParams) 339 | } 340 | 341 | if got, err := ToString(test.input, NoTemplateParams); err != nil { 342 | t.Errorf("demangling NoTemplateParams %s: unexpected error %v", test.input, err) 343 | } else if got != test.wantNoTemplateParams { 344 | t.Errorf("demangling NoTemplateParams %s: got %s, want %s", test.input, got, test.wantNoTemplateParams) 345 | } 346 | 347 | if got, err := ToString(test.input, NoParams, NoTemplateParams); err != nil { 348 | t.Errorf("demangling NoTemplateParams %s: unexpected error %v", test.input, err) 349 | } else if got != test.wantMinimal { 350 | t.Errorf("demangling Minimal %s: got %s, want %s", test.input, got, test.wantMinimal) 351 | } 352 | 353 | // Test Filter also. 354 | if got := Filter(test.input); got != test.want { 355 | t.Errorf("Filter(%s) == %s, want %s", test.input, got, test.want) 356 | } 357 | } 358 | } 359 | 360 | // Test for some failure cases. 361 | func TestFailure(t *testing.T) { 362 | var tests = []struct { 363 | input string 364 | error string 365 | off int 366 | }{ 367 | { 368 | "_Z1FE", 369 | "unparsed characters at end of mangled name", 370 | 4, 371 | }, 372 | { 373 | "_Z1FQ", 374 | "unrecognized type code", 375 | 4, 376 | }, 377 | { 378 | "_ZZSaIL0D", 379 | "expected positive number", 380 | 8, 381 | }, 382 | { 383 | "_ZNKE", 384 | "expected prefix", 385 | 4, 386 | }, 387 | { 388 | "_ZcvT_", 389 | "not in scope of template", 390 | 6, 391 | }, 392 | { 393 | "_Z1AIXsZ1_EE", 394 | "missing argument pack", 395 | 8, 396 | }, 397 | { 398 | "_Z1gIEDTclspilE", 399 | "expected expression", 400 | 15, 401 | }, 402 | { 403 | "_ZNcvZN1ET_IEE", 404 | "after local name", 405 | 14, 406 | }, 407 | { 408 | "_Zv00", 409 | "expected positive number", 410 | 5, 411 | }, 412 | { 413 | "_ZcvT_B2T0", 414 | "template parameter not in scope", 415 | 10, 416 | }, 417 | { 418 | "_ZStcvT_", 419 | "template parameter not in scope", 420 | 8, 421 | }, 422 | { 423 | "_Z1aIeEU1RT_ZcvS1_", 424 | "expected E after local name", 425 | 18, 426 | }, 427 | { 428 | "_ZNcvT_oRIEE", 429 | "template index out of range", 430 | 11, 431 | }, 432 | { 433 | "_ZNcvT_D0IIEE", 434 | "expected prefix", 435 | 13, 436 | }, 437 | { 438 | "_ZcvT_IAoncvT__eE", 439 | "template parameter not in scope", 440 | 17, 441 | }, 442 | } 443 | 444 | for _, test := range tests { 445 | got, err := ToString(test.input) 446 | if err == nil { 447 | t.Errorf("unexpected success for %s: %s", test.input, got) 448 | } else if !strings.Contains(err.Error(), test.error) { 449 | t.Errorf("unexpected error for %s: %v", test.input, err) 450 | } else { 451 | s := err.Error() 452 | i := strings.LastIndex(s, " at ") 453 | if i < 0 { 454 | t.Errorf("missing offset in error for %s: %v", test.input, err) 455 | } else { 456 | off, oerr := strconv.Atoi(s[i+4:]) 457 | if oerr != nil { 458 | t.Errorf("can't parse offset (%s) for %s: %v", s[i+4:], test.input, err) 459 | } else if off != test.off { 460 | t.Errorf("unexpected offset for %s: got %d, want %d", test.input, off, test.off) 461 | } 462 | } 463 | } 464 | 465 | if got := Filter(test.input); got != test.input { 466 | t.Errorf("Filter(%s) == %s, want %s", test.input, got, test.input) 467 | } 468 | } 469 | } 470 | -------------------------------------------------------------------------------- /testdata/demangle-expected: -------------------------------------------------------------------------------- 1 | # This file holds test cases for the demangler. 2 | # Each test case looks like this: 3 | # options 4 | # input to be demangled 5 | # expected output 6 | # 7 | # Supported options: 8 | # --format= Sets the demangling style. 9 | # --no-params There are two lines of expected output; the first 10 | # is with DMGL_PARAMS, the second is without it. 11 | # --is-v3-ctor Calls is_gnu_v3_mangled_ctor on input; expected 12 | # output is an integer representing ctor_kind. 13 | # --is-v3-dtor Likewise, but for dtors. 14 | # --ret-postfix Passes the DMGL_RET_POSTFIX option 15 | # 16 | # For compatibility, just in case it matters, the options line may be 17 | # empty, to mean --format=auto. If it doesn't start with --, then it 18 | # may contain only a format name. 19 | # 20 | # A line starting with `#' is ignored. 21 | # However, blank lines in this file are NOT ignored. 22 | # 23 | # 24 | # Tests integer overflow problem PR70492 25 | 26 | __vt_90000000000cafebabe 27 | __vt_90000000000cafebabe 28 | # 29 | # Tests write access violation PR70498 30 | 31 | _Z80800000000000000000000 32 | _Z80800000000000000000000 33 | # 34 | # Tests write access violation PR70926 35 | 36 | 0__Ot2m02R5T0000500000 37 | 0__Ot2m02R5T0000500000 38 | # 39 | 40 | 0__GT50000000000_ 41 | 0__GT50000000000_ 42 | # 43 | 44 | __t2m05B500000000000000000_ 45 | __t2m05B500000000000000000_ 46 | ## 47 | ## Tests stack overflow PR71696 48 | # 49 | #__10%0__S4_0T0T0 50 | #%0<>::%0(%0<>) 51 | # Could crash 52 | 53 | _ 54 | _ 55 | # Could crash 56 | 57 | _vt 58 | _vt 59 | # Could crash 60 | 61 | _$_1Acitz 62 | _$_1Acitz 63 | # Could crash 64 | 65 | _$_H1R 66 | _$_H1R 67 | # Could crash 68 | 69 | _Q8ccQ4M2e. 70 | _Q8ccQ4M2e. 71 | # Could crash 72 | 73 | _ZmmAtl 74 | _ZmmAtl 75 | # Could crash 76 | --no-params 77 | _ZZaSFvOEES_ 78 | _ZZaSFvOEES_ 79 | _ZZaSFvOEES_ 80 | # Could crash 81 | 82 | _ZZeqFvOEES_z 83 | _ZZeqFvOEES_z 84 | # 85 | # demangler/80513 Test for bogus characters after __thunk_ 86 | 87 | __thunk_16a_$_1x 88 | __thunk_16a_$_1x 89 | # 90 | # demangler/80513 Test for overflow in consume_count 91 | 92 | __thunk_4294967297__$_1x 93 | __thunk_4294967297__$_1x 94 | # 95 | --format=gnu-v3 --no-params 96 | _Z3fo5n 97 | fo5(__int128) 98 | fo5 99 | # 100 | --format=gnu-v3 --no-params 101 | _Z3fo5o 102 | fo5(unsigned __int128) 103 | fo5 104 | # 105 | --format=java 106 | _ZN4java3awt10ScrollPane7addImplEPNS0_9ComponentEPNS_4lang6ObjectEi 107 | java.awt.ScrollPane.addImpl(java.awt.Component, java.lang.Object, int) 108 | # 109 | --format=java 110 | _ZN4java3awt4geom15AffineTransform9getMatrixEP6JArrayIdE 111 | java.awt.geom.AffineTransform.getMatrix(double[]) 112 | # 113 | --format=java 114 | _ZN23Mangle$Inner$InnerInner3fooEP6JArrayIPS0_IiEEdPS0_IPS0_IPS0_IPS0_IPN4java4lang6StringEEEEEPS0_IPS0_IPN6MangleEEE 115 | Mangle$Inner$InnerInner.foo(int[][], double, java.lang.String[][][][], Mangle[][]) 116 | # 117 | --format=java 118 | _ZN6JArray1tEP6JArrayIPS_E 119 | JArray.t(JArray[]) 120 | # 121 | --format=java 122 | _ZN4Prim1iEibcdfwPN4java4lang6StringEsx 123 | Prim.i(int, boolean, byte, double, float, char, java.lang.String, short, long) 124 | # 125 | --format=java 126 | _ZN4java4util14Map__U24_Entry11class__U24_E 127 | java.util.Map$Entry.class$ 128 | # 129 | --format=java 130 | _ZN3org7eclipse3cdt5debug8internal4core5model9CVariable6sizeof$Ev 131 | org.eclipse.cdt.debug.internal.core.model.CVariable.sizeof() 132 | # 133 | --format=auto --no-params 134 | _Utf58_0_1__1_2147483647__2147483648 135 | _Utf58_0_1__1_2147483647__2147483648 136 | _Utf58_0_1__1_2147483647__2147483648 137 | # 138 | --format=gnu-v3 --no-params 139 | St9bad_alloc 140 | std::bad_alloc 141 | std::bad_alloc 142 | # 143 | --format=gnu-v3 --no-params 144 | _ZN1f1fE 145 | f::f 146 | f::f 147 | # 148 | --format=gnu-v3 --no-params 149 | _Z1fv 150 | f() 151 | f 152 | # 153 | --format=gnu-v3 --no-params 154 | _Z1fi 155 | f(int) 156 | f 157 | # 158 | --format=gnu-v3 --no-params 159 | _Z3foo3bar 160 | foo(bar) 161 | foo 162 | # 163 | --format=gnu-v3 --no-params 164 | _Zrm1XS_ 165 | operator%(X, X) 166 | operator% 167 | # 168 | --format=gnu-v3 --no-params 169 | _ZplR1XS0_ 170 | operator+(X&, X&) 171 | operator+ 172 | # 173 | --format=gnu-v3 --no-params 174 | _ZlsRK1XS1_ 175 | operator<<(X const&, X const&) 176 | operator<< 177 | # 178 | --format=gnu-v3 --no-params 179 | _ZN3FooIA4_iE3barE 180 | Foo::bar 181 | Foo::bar 182 | # 183 | --format=gnu-v3 --no-params 184 | _Z1fIiEvi 185 | void f(int) 186 | f 187 | # 188 | --format=gnu-v3 --no-params 189 | _Z5firstI3DuoEvS0_ 190 | void first(Duo) 191 | first 192 | # 193 | --format=gnu-v3 --no-params 194 | _Z5firstI3DuoEvT_ 195 | void first(Duo) 196 | first 197 | # 198 | --format=gnu-v3 --no-params 199 | _Z3fooIiFvdEiEvv 200 | void foo() 201 | foo 202 | # 203 | --format=gnu-v3 --no-params 204 | _Z1fIFvvEEvv 205 | void f() 206 | f 207 | # 208 | --format=gnu-v3 --no-params 209 | _ZN1N1fE 210 | N::f 211 | N::f 212 | # 213 | --format=gnu-v3 --no-params 214 | _ZN6System5Sound4beepEv 215 | System::Sound::beep() 216 | System::Sound::beep 217 | # 218 | --format=gnu-v3 --no-params 219 | _ZN5Arena5levelE 220 | Arena::level 221 | Arena::level 222 | # 223 | --format=gnu-v3 --no-params 224 | _ZN5StackIiiE5levelE 225 | Stack::level 226 | Stack::level 227 | # 228 | --format=gnu-v3 --no-params 229 | _Z1fI1XEvPVN1AIT_E1TE 230 | void f(A::T volatile*) 231 | f 232 | # 233 | --format=gnu-v3 --no-params 234 | _ZngILi42EEvN1AIXplT_Li2EEE1TE 235 | void operator-<42>(A<(42)+(2)>::T) 236 | operator-<42> 237 | # 238 | --format=gnu-v3 --no-params 239 | _Z4makeI7FactoryiET_IT0_Ev 240 | Factory make() 241 | make 242 | # 243 | --format=gnu-v3 --no-params 244 | _Z4makeI7FactoryiET_IT0_Ev 245 | Factory make() 246 | make 247 | # 248 | --format=gnu-v3 --no-params 249 | _Z3foo5Hello5WorldS0_S_ 250 | foo(Hello, World, World, Hello) 251 | foo 252 | # 253 | --format=gnu-v3 --no-params 254 | _Z3fooPM2ABi 255 | foo(int AB::**) 256 | foo 257 | # 258 | --format=gnu-v3 --no-params 259 | _ZlsRSoRKSs 260 | operator<<(std::ostream&, std::string const&) 261 | operator<< 262 | # 263 | --format=gnu-v3 --no-params 264 | _ZTI7a_class 265 | typeinfo for a_class 266 | typeinfo for a_class 267 | # 268 | --format=gnu-v3 --no-params 269 | U4_farrVKPi 270 | int* const volatile restrict _far 271 | int* const volatile restrict _far 272 | # 273 | --format=gnu-v3 --no-params 274 | _Z3fooILi2EEvRAplT_Li1E_i 275 | void foo<2>(int (&) [(2)+(1)]) 276 | foo<2> 277 | # 278 | --format=gnu-v3 --no-params 279 | _Z3fooILi2EEvOAplT_Li1E_i 280 | void foo<2>(int (&&) [(2)+(1)]) 281 | foo<2> 282 | # 283 | --format=gnu-v3 --no-params 284 | _Z1fM1AKFvvE 285 | f(void (A::*)() const) 286 | f 287 | # 288 | --format=gnu-v3 --no-params 289 | _Z3fooc 290 | foo(char) 291 | foo 292 | # 293 | --format=gnu-v3 --no-params 294 | _Z2f0u8char16_t 295 | f0(char16_t) 296 | f0 297 | # 298 | --format=gnu-v3 --no-params 299 | _Z2f0Pu8char16_t 300 | f0(char16_t*) 301 | f0 302 | # 303 | --format=gnu-v3 --no-params 304 | _Z2f0u8char32_t 305 | f0(char32_t) 306 | f0 307 | # 308 | --format=gnu-v3 --no-params 309 | _Z2f0Pu8char32_t 310 | f0(char32_t*) 311 | f0 312 | # 313 | --format=gnu-v3 --no-params 314 | 2CBIL_Z3foocEE 315 | CB 316 | CB 317 | # 318 | --format=gnu-v3 --no-params 319 | 2CBIL_Z7IsEmptyEE 320 | CB 321 | CB 322 | # 323 | --format=gnu-v3 --no-params 324 | _ZZN1N1fEiE1p 325 | N::f(int)::p 326 | N::f(int)::p 327 | # 328 | --format=gnu-v3 --no-params 329 | _ZZN1N1fEiEs 330 | N::f(int)::string literal 331 | N::f(int)::string literal 332 | # 333 | --format=gnu-v3 --no-params 334 | _Z1fPFvvEM1SFvvE 335 | f(void (*)(), void (S::*)()) 336 | f 337 | # 338 | --format=gnu-v3 --no-params 339 | _ZN1N1TIiiE2mfES0_IddE 340 | N::T::mf(N::T) 341 | N::T::mf 342 | # 343 | --format=gnu-v3 --no-params 344 | _ZSt5state 345 | std::state 346 | std::state 347 | # 348 | --format=gnu-v3 --no-params 349 | _ZNSt3_In4wardE 350 | std::_In::ward 351 | std::_In::ward 352 | # 353 | --format=gnu-v3 --no-params 354 | _Z1fKPFiiE 355 | f(int (* const)(int)) 356 | f 357 | # 358 | --format=gnu-v3 --no-params 359 | _Z1fAszL_ZZNK1N1A1fEvE3foo_0E_i 360 | f(int [sizeof (N::A::f() const::foo)]) 361 | f 362 | # 363 | --format=gnu-v3 --no-params 364 | _Z1fA37_iPS_ 365 | f(int [37], int (*) [37]) 366 | f 367 | # 368 | --format=gnu-v3 --no-params 369 | _Z1fM1AFivEPS0_ 370 | f(int (A::*)(), int (*)()) 371 | f 372 | # 373 | --format=gnu-v3 --no-params 374 | _Z1fPFPA1_ivE 375 | f(int (*(*)()) [1]) 376 | f 377 | # 378 | --format=gnu-v3 --no-params 379 | _Z1fPKM1AFivE 380 | f(int (A::* const*)()) 381 | f 382 | # 383 | --format=gnu-v3 --no-params 384 | _Z1jM1AFivEPS1_ 385 | j(int (A::*)(), int (A::**)()) 386 | j 387 | # 388 | --format=gnu-v3 --no-params 389 | _Z1sPA37_iPS0_ 390 | s(int (*) [37], int (**) [37]) 391 | s 392 | # 393 | --format=gnu-v3 --no-params 394 | _Z3fooA30_A_i 395 | foo(int [30][]) 396 | foo 397 | # 398 | --format=gnu-v3 --no-params 399 | _Z3kooPA28_A30_i 400 | koo(int (*) [28][30]) 401 | koo 402 | # 403 | --format=gnu-v3 --no-params 404 | _ZlsRKU3fooU4bart1XS0_ 405 | operator<<(X bart foo const&, X bart) 406 | operator<< 407 | # 408 | --format=gnu-v3 --no-params 409 | _ZlsRKU3fooU4bart1XS2_ 410 | operator<<(X bart foo const&, X bart foo const) 411 | operator<< 412 | # 413 | --format=gnu-v3 --no-params 414 | _Z1fM1AKFivE 415 | f(int (A::*)() const) 416 | f 417 | # 418 | --format=gnu-v3 --no-params 419 | _Z3absILi11EEvv 420 | void abs<11>() 421 | abs<11> 422 | # 423 | --format=gnu-v3 --no-params 424 | _ZN1AIfEcvT_IiEEv 425 | A::operator int() 426 | A::operator int 427 | # 428 | --format=gnu-v3 --no-params 429 | _ZN12libcw_app_ct10add_optionIS_EEvMT_FvPKcES3_cS3_S3_ 430 | void libcw_app_ct::add_option(void (libcw_app_ct::*)(char const*), char const*, char, char const*, char const*) 431 | libcw_app_ct::add_option 432 | # 433 | --format=gnu-v3 --no-params 434 | _ZGVN5libcw24_GLOBAL__N_cbll.cc0ZhUKa23compiler_bug_workaroundISt6vectorINS_13omanip_id_tctINS_5debug32memblk_types_manipulator_data_ctEEESaIS6_EEE3idsE 435 | guard variable for libcw::(anonymous namespace)::compiler_bug_workaround, std::allocator > > >::ids 436 | guard variable for libcw::(anonymous namespace)::compiler_bug_workaround, std::allocator > > >::ids 437 | # 438 | --format=gnu-v3 --no-params 439 | _ZN5libcw5debug13cwprint_usingINS_9_private_12GlobalObjectEEENS0_17cwprint_using_tctIT_EERKS5_MS5_KFvRSt7ostreamE 440 | libcw::debug::cwprint_using_tct libcw::debug::cwprint_using(libcw::_private_::GlobalObject const&, void (libcw::_private_::GlobalObject::*)(std::ostream&) const) 441 | libcw::debug::cwprint_using 442 | # 443 | --format=gnu-v3 --no-params 444 | _ZNKSt14priority_queueIP27timer_event_request_base_ctSt5dequeIS1_SaIS1_EE13timer_greaterE3topEv 445 | std::priority_queue >, timer_greater>::top() const 446 | std::priority_queue >, timer_greater>::top 447 | # 448 | --format=gnu-v3 --no-params 449 | _ZNKSt15_Deque_iteratorIP15memory_block_stRKS1_PS2_EeqERKS5_ 450 | std::_Deque_iterator::operator==(std::_Deque_iterator const&) const 451 | std::_Deque_iterator::operator== 452 | # 453 | --format=gnu-v3 --no-params 454 | _ZNKSt17__normal_iteratorIPK6optionSt6vectorIS0_SaIS0_EEEmiERKS6_ 455 | std::__normal_iterator