Bug 439685 compiler warning in callgrind/main.c
[valgrind.git] / coregrind / m_demangle / cplus-dem.c
blob5d6e04d962ee7616f1e61dd0bfe93e2087da1a90
1 /* Demangler for GNU C++
2 Copyright (C) 1989-2022 Free Software Foundation, Inc.
3 Written by James Clark (jjc@jclark.uucp)
4 Rewritten by Fred Fish (fnf@cygnus.com) for ARM and Lucid demangling
5 Modified by Satish Pai (pai@apollo.hp.com) for HP demangling
7 This file is part of the libiberty library.
8 Libiberty is free software; you can redistribute it and/or
9 modify it under the terms of the GNU Library General Public
10 License as published by the Free Software Foundation; either
11 version 2 of the License, or (at your option) any later version.
13 In addition to the permissions in the GNU Library General Public
14 License, the Free Software Foundation gives you unlimited permission
15 to link the compiled version of this file into combinations with other
16 programs, and to distribute those combinations without any restriction
17 coming from the use of this file. (The Library Public License
18 restrictions do apply in other respects; for example, they cover
19 modification of the file, and distribution when not linked into a
20 combined executable.)
22 Libiberty is distributed in the hope that it will be useful,
23 but WITHOUT ANY WARRANTY; without even the implied warranty of
24 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
25 Library General Public License for more details.
27 You should have received a copy of the GNU Library General Public
28 License along with libiberty; see the file COPYING.LIB. If
29 not, write to the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
30 Boston, MA 02110-1301, USA. */
32 /* This file lives in both GCC and libiberty. When making changes, please
33 try not to break either. */
35 #if 0 /* in valgrind */
36 #ifdef HAVE_CONFIG_H
37 #include "config.h"
38 #endif
39 #endif /* ! in valgrind */
41 #if 0 /* in valgrind */
42 #include "safe-ctype.h"
43 #endif /* ! in valgrind */
45 #if 0 /* in valgrind */
46 #include <string.h>
47 #endif /* ! in valgrind */
49 #if 0 /* in valgrind */
50 #ifdef HAVE_STDLIB_H
51 #include <stdlib.h>
52 #else
53 void * malloc ();
54 void * realloc ();
55 #endif
56 #endif /* ! in valgrind */
58 #if 0 /* in valgrind */
59 #include <demangle.h>
60 #undef CURRENT_DEMANGLING_STYLE
61 #define CURRENT_DEMANGLING_STYLE options
62 #endif /* ! in valgrind */
64 #if 0 /* in valgrind */
65 #include "libiberty.h"
66 #endif /* ! in valgrind */
68 #include "vg_libciface.h"
70 #include "ansidecl.h"
71 #include "demangle.h"
72 #include "safe-ctype.h"
74 enum demangling_styles current_demangling_style = auto_demangling;
76 const struct demangler_engine libiberty_demanglers[] =
79 NO_DEMANGLING_STYLE_STRING,
80 no_demangling,
81 "Demangling disabled"
85 AUTO_DEMANGLING_STYLE_STRING,
86 auto_demangling,
87 "Automatic selection based on executable"
91 GNU_V3_DEMANGLING_STYLE_STRING,
92 gnu_v3_demangling,
93 "GNU (g++) V3 (Itanium C++ ABI) style demangling"
97 JAVA_DEMANGLING_STYLE_STRING,
98 java_demangling,
99 "Java style demangling"
103 GNAT_DEMANGLING_STYLE_STRING,
104 gnat_demangling,
105 "GNAT style demangling"
109 DLANG_DEMANGLING_STYLE_STRING,
110 dlang_demangling,
111 "DLANG style demangling"
115 RUST_DEMANGLING_STYLE_STRING,
116 rust_demangling,
117 "Rust style demangling"
121 NULL, unknown_demangling, NULL
125 /* Add a routine to set the demangling style to be sure it is valid and
126 allow for any demangler initialization that maybe necessary. */
128 enum demangling_styles
129 cplus_demangle_set_style (enum demangling_styles style)
131 const struct demangler_engine *demangler = libiberty_demanglers;
133 for (; demangler->demangling_style != unknown_demangling; ++demangler)
134 if (style == demangler->demangling_style)
136 current_demangling_style = style;
137 return current_demangling_style;
140 return unknown_demangling;
143 /* Do string name to style translation */
145 enum demangling_styles
146 cplus_demangle_name_to_style (const char *name)
148 const struct demangler_engine *demangler = libiberty_demanglers;
150 for (; demangler->demangling_style != unknown_demangling; ++demangler)
151 if (strcmp (name, demangler->demangling_style_name) == 0)
152 return demangler->demangling_style;
154 return unknown_demangling;
157 /* char *cplus_demangle (const char *mangled, int options)
159 If MANGLED is a mangled function name produced by GNU C++, then
160 a pointer to a @code{malloc}ed string giving a C++ representation
161 of the name will be returned; otherwise NULL will be returned.
162 It is the caller's responsibility to free the string which
163 is returned.
165 Note that any leading underscores, or other such characters prepended by
166 the compilation system, are presumed to have already been stripped from
167 MANGLED. */
169 char *
170 ML_(cplus_demangle) (const char *mangled, int options)
172 char *ret;
174 if (current_demangling_style == no_demangling)
175 return xstrdup (mangled);
177 if ((options & DMGL_STYLE_MASK) == 0)
178 options |= (int) current_demangling_style & DMGL_STYLE_MASK;
180 /* The Rust demangling is implemented elsewhere.
181 Legacy Rust symbols overlap with GNU_V3, so try Rust first. */
182 if (RUST_DEMANGLING || AUTO_DEMANGLING)
184 ret = rust_demangle (mangled, options);
185 if (ret || RUST_DEMANGLING)
186 return ret;
189 /* The V3 ABI demangling is implemented elsewhere. */
190 if (GNU_V3_DEMANGLING || AUTO_DEMANGLING)
192 ret = cplus_demangle_v3 (mangled, options);
193 if (ret || GNU_V3_DEMANGLING)
194 return ret;
197 if (JAVA_DEMANGLING)
199 ret = java_demangle_v3 (mangled);
200 if (ret)
201 return ret;
204 if (GNAT_DEMANGLING)
205 return ada_demangle (mangled, options);
207 if (DLANG_DEMANGLING)
209 ret = dlang_demangle (mangled, options);
210 if (ret)
211 return ret;
214 return (ret);
217 /* Demangle ada names. The encoding is documented in gcc/ada/exp_dbug.ads. */
219 char *
220 ada_demangle (const char *mangled, int option ATTRIBUTE_UNUSED)
222 int len0;
223 const char* p;
224 char *d;
225 char *demangled = NULL;
227 /* Discard leading _ada_, which is used for library level subprograms. */
228 if (strncmp (mangled, "_ada_", 5) == 0)
229 mangled += 5;
231 /* All ada unit names are lower-case. */
232 if (!ISLOWER (mangled[0]))
233 goto unknown;
235 /* Most of the demangling will trivially remove chars. Operator names
236 may add one char but because they are always preceded by '__' which is
237 replaced by '.', they eventually never expand the size.
238 A few special names such as '___elabs' add a few chars (at most 7), but
239 they occur only once. */
240 len0 = strlen (mangled) + 7 + 1;
241 demangled = XNEWVEC (char, len0);
243 d = demangled;
244 p = mangled;
245 while (1)
247 /* An entity names is expected. */
248 if (ISLOWER (*p))
250 /* An identifier, which is always lower case. */
252 *d++ = *p++;
253 while (ISLOWER(*p) || ISDIGIT (*p)
254 || (p[0] == '_' && (ISLOWER (p[1]) || ISDIGIT (p[1]))));
256 else if (p[0] == 'O')
258 /* An operator name. */
259 static const char * const operators[][2] =
260 {{"Oabs", "abs"}, {"Oand", "and"}, {"Omod", "mod"},
261 {"Onot", "not"}, {"Oor", "or"}, {"Orem", "rem"},
262 {"Oxor", "xor"}, {"Oeq", "="}, {"One", "/="},
263 {"Olt", "<"}, {"Ole", "<="}, {"Ogt", ">"},
264 {"Oge", ">="}, {"Oadd", "+"}, {"Osubtract", "-"},
265 {"Oconcat", "&"}, {"Omultiply", "*"}, {"Odivide", "/"},
266 {"Oexpon", "**"}, {NULL, NULL}};
267 int k;
269 for (k = 0; operators[k][0] != NULL; k++)
271 size_t slen = strlen (operators[k][0]);
272 if (strncmp (p, operators[k][0], slen) == 0)
274 p += slen;
275 slen = strlen (operators[k][1]);
276 *d++ = '"';
277 memcpy (d, operators[k][1], slen);
278 d += slen;
279 *d++ = '"';
280 break;
283 /* Operator not found. */
284 if (operators[k][0] == NULL)
285 goto unknown;
287 else
289 /* Not a GNAT encoding. */
290 goto unknown;
293 /* The name can be directly followed by some uppercase letters. */
294 if (p[0] == 'T' && p[1] == 'K')
296 /* Task stuff. */
297 if (p[2] == 'B' && p[3] == 0)
299 /* Subprogram for task body. */
300 break;
302 else if (p[2] == '_' && p[3] == '_')
304 /* Inner declarations in a task. */
305 p += 4;
306 *d++ = '.';
307 continue;
309 else
310 goto unknown;
312 if (p[0] == 'E' && p[1] == 0)
314 /* Exception name. */
315 goto unknown;
317 if ((p[0] == 'P' || p[0] == 'N') && p[1] == 0)
319 /* Protected type subprogram. */
320 break;
322 if ((*p == 'N' || *p == 'S') && p[1] == 0)
324 /* Enumerated type name table. */
325 goto unknown;
327 if (p[0] == 'X')
329 /* Body nested. */
330 p++;
331 while (p[0] == 'n' || p[0] == 'b')
332 p++;
334 if (p[0] == 'S' && p[1] != 0 && (p[2] == '_' || p[2] == 0))
336 /* Stream operations. */
337 const char *name;
338 switch (p[1])
340 case 'R':
341 name = "'Read";
342 break;
343 case 'W':
344 name = "'Write";
345 break;
346 case 'I':
347 name = "'Input";
348 break;
349 case 'O':
350 name = "'Output";
351 break;
352 default:
353 goto unknown;
355 p += 2;
356 strcpy (d, name);
357 d += strlen (name);
359 else if (p[0] == 'D')
361 /* Controlled type operation. */
362 const char *name;
363 switch (p[1])
365 case 'F':
366 name = ".Finalize";
367 break;
368 case 'A':
369 name = ".Adjust";
370 break;
371 default:
372 goto unknown;
374 strcpy (d, name);
375 d += strlen (name);
376 break;
379 if (p[0] == '_')
381 /* Separator. */
382 if (p[1] == '_')
384 /* Standard separator. Handled first. */
385 p += 2;
387 if (ISDIGIT (*p))
389 /* Overloading number. */
391 p++;
392 while (ISDIGIT (*p) || (p[0] == '_' && ISDIGIT (p[1])));
393 if (*p == 'X')
395 p++;
396 while (p[0] == 'n' || p[0] == 'b')
397 p++;
400 else if (p[0] == '_' && p[1] != '_')
402 /* Special names. */
403 static const char * const special[][2] = {
404 { "_elabb", "'Elab_Body" },
405 { "_elabs", "'Elab_Spec" },
406 { "_size", "'Size" },
407 { "_alignment", "'Alignment" },
408 { "_assign", ".\":=\"" },
409 { NULL, NULL }
411 int k;
413 for (k = 0; special[k][0] != NULL; k++)
415 size_t slen = strlen (special[k][0]);
416 if (strncmp (p, special[k][0], slen) == 0)
418 p += slen;
419 slen = strlen (special[k][1]);
420 memcpy (d, special[k][1], slen);
421 d += slen;
422 break;
425 if (special[k][0] != NULL)
426 break;
427 else
428 goto unknown;
430 else
432 *d++ = '.';
433 continue;
436 else if (p[1] == 'B' || p[1] == 'E')
438 /* Entry Body or barrier Evaluation. */
439 p += 2;
440 while (ISDIGIT (*p))
441 p++;
442 if (p[0] == 's' && p[1] == 0)
443 break;
444 else
445 goto unknown;
447 else
448 goto unknown;
451 if (p[0] == '.' && ISDIGIT (p[1]))
453 /* Nested subprogram. */
454 p += 2;
455 while (ISDIGIT (*p))
456 p++;
458 if (*p == 0)
460 /* End of mangled name. */
461 break;
463 else
464 goto unknown;
466 *d = 0;
467 return demangled;
469 unknown:
470 XDELETEVEC (demangled);
471 len0 = strlen (mangled);
472 demangled = XNEWVEC (char, len0 + 3);
474 if (mangled[0] == '<')
475 strcpy (demangled, mangled);
476 else
477 sprintf (demangled, "<%s>", mangled);
479 return demangled;