decl2.c (delete_sanity): Improve diagnostic locations, use cp_expr_loc_or_loc in...
[official-gcc.git] / libiberty / cplus-dem.c
bloba39e2bf2ed46eaaee01a95b363b46a70be31fc9f
1 /* Demangler for GNU C++
2 Copyright (C) 1989-2019 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 #ifdef HAVE_CONFIG_H
36 #include "config.h"
37 #endif
39 #include "safe-ctype.h"
41 #include <string.h>
43 #ifdef HAVE_STDLIB_H
44 #include <stdlib.h>
45 #else
46 void * malloc ();
47 void * realloc ();
48 #endif
50 #include <demangle.h>
51 #undef CURRENT_DEMANGLING_STYLE
52 #define CURRENT_DEMANGLING_STYLE options
54 #include "libiberty.h"
55 #include "rust-demangle.h"
57 enum demangling_styles current_demangling_style = auto_demangling;
59 const struct demangler_engine libiberty_demanglers[] =
62 NO_DEMANGLING_STYLE_STRING,
63 no_demangling,
64 "Demangling disabled"
68 AUTO_DEMANGLING_STYLE_STRING,
69 auto_demangling,
70 "Automatic selection based on executable"
74 GNU_V3_DEMANGLING_STYLE_STRING,
75 gnu_v3_demangling,
76 "GNU (g++) V3 (Itanium C++ ABI) style demangling"
80 JAVA_DEMANGLING_STYLE_STRING,
81 java_demangling,
82 "Java style demangling"
86 GNAT_DEMANGLING_STYLE_STRING,
87 gnat_demangling,
88 "GNAT style demangling"
92 DLANG_DEMANGLING_STYLE_STRING,
93 dlang_demangling,
94 "DLANG style demangling"
98 RUST_DEMANGLING_STYLE_STRING,
99 rust_demangling,
100 "Rust style demangling"
104 NULL, unknown_demangling, NULL
108 /* Add a routine to set the demangling style to be sure it is valid and
109 allow for any demangler initialization that maybe necessary. */
111 enum demangling_styles
112 cplus_demangle_set_style (enum demangling_styles style)
114 const struct demangler_engine *demangler = libiberty_demanglers;
116 for (; demangler->demangling_style != unknown_demangling; ++demangler)
117 if (style == demangler->demangling_style)
119 current_demangling_style = style;
120 return current_demangling_style;
123 return unknown_demangling;
126 /* Do string name to style translation */
128 enum demangling_styles
129 cplus_demangle_name_to_style (const char *name)
131 const struct demangler_engine *demangler = libiberty_demanglers;
133 for (; demangler->demangling_style != unknown_demangling; ++demangler)
134 if (strcmp (name, demangler->demangling_style_name) == 0)
135 return demangler->demangling_style;
137 return unknown_demangling;
140 /* char *cplus_demangle (const char *mangled, int options)
142 If MANGLED is a mangled function name produced by GNU C++, then
143 a pointer to a @code{malloc}ed string giving a C++ representation
144 of the name will be returned; otherwise NULL will be returned.
145 It is the caller's responsibility to free the string which
146 is returned.
148 Note that any leading underscores, or other such characters prepended by
149 the compilation system, are presumed to have already been stripped from
150 MANGLED. */
152 char *
153 cplus_demangle (const char *mangled, int options)
155 char *ret;
157 if (current_demangling_style == no_demangling)
158 return xstrdup (mangled);
160 if ((options & DMGL_STYLE_MASK) == 0)
161 options |= (int) current_demangling_style & DMGL_STYLE_MASK;
163 /* The V3 ABI demangling is implemented elsewhere. */
164 if (GNU_V3_DEMANGLING || RUST_DEMANGLING || AUTO_DEMANGLING)
166 ret = cplus_demangle_v3 (mangled, options);
167 if (GNU_V3_DEMANGLING)
168 return ret;
170 if (ret)
172 /* Rust symbols are GNU_V3 mangled plus some extra subtitutions.
173 The subtitutions are always smaller, so do in place changes. */
174 if (rust_is_mangled (ret))
175 rust_demangle_sym (ret);
176 else if (RUST_DEMANGLING)
178 free (ret);
179 ret = NULL;
183 if (ret || RUST_DEMANGLING)
184 return ret;
187 if (JAVA_DEMANGLING)
189 ret = java_demangle_v3 (mangled);
190 if (ret)
191 return ret;
194 if (GNAT_DEMANGLING)
195 return ada_demangle (mangled, options);
197 if (DLANG_DEMANGLING)
199 ret = dlang_demangle (mangled, options);
200 if (ret)
201 return ret;
204 return (ret);
207 char *
208 rust_demangle (const char *mangled, int options)
210 /* Rust symbols are GNU_V3 mangled plus some extra subtitutions. */
211 char *ret = cplus_demangle_v3 (mangled, options);
213 /* The Rust subtitutions are always smaller, so do in place changes. */
214 if (ret != NULL)
216 if (rust_is_mangled (ret))
217 rust_demangle_sym (ret);
218 else
220 free (ret);
221 ret = NULL;
225 return ret;
228 /* Demangle ada names. The encoding is documented in gcc/ada/exp_dbug.ads. */
230 char *
231 ada_demangle (const char *mangled, int option ATTRIBUTE_UNUSED)
233 int len0;
234 const char* p;
235 char *d;
236 char *demangled = NULL;
238 /* Discard leading _ada_, which is used for library level subprograms. */
239 if (strncmp (mangled, "_ada_", 5) == 0)
240 mangled += 5;
242 /* All ada unit names are lower-case. */
243 if (!ISLOWER (mangled[0]))
244 goto unknown;
246 /* Most of the demangling will trivially remove chars. Operator names
247 may add one char but because they are always preceeded by '__' which is
248 replaced by '.', they eventually never expand the size.
249 A few special names such as '___elabs' add a few chars (at most 7), but
250 they occur only once. */
251 len0 = strlen (mangled) + 7 + 1;
252 demangled = XNEWVEC (char, len0);
254 d = demangled;
255 p = mangled;
256 while (1)
258 /* An entity names is expected. */
259 if (ISLOWER (*p))
261 /* An identifier, which is always lower case. */
263 *d++ = *p++;
264 while (ISLOWER(*p) || ISDIGIT (*p)
265 || (p[0] == '_' && (ISLOWER (p[1]) || ISDIGIT (p[1]))));
267 else if (p[0] == 'O')
269 /* An operator name. */
270 static const char * const operators[][2] =
271 {{"Oabs", "abs"}, {"Oand", "and"}, {"Omod", "mod"},
272 {"Onot", "not"}, {"Oor", "or"}, {"Orem", "rem"},
273 {"Oxor", "xor"}, {"Oeq", "="}, {"One", "/="},
274 {"Olt", "<"}, {"Ole", "<="}, {"Ogt", ">"},
275 {"Oge", ">="}, {"Oadd", "+"}, {"Osubtract", "-"},
276 {"Oconcat", "&"}, {"Omultiply", "*"}, {"Odivide", "/"},
277 {"Oexpon", "**"}, {NULL, NULL}};
278 int k;
280 for (k = 0; operators[k][0] != NULL; k++)
282 size_t slen = strlen (operators[k][0]);
283 if (strncmp (p, operators[k][0], slen) == 0)
285 p += slen;
286 slen = strlen (operators[k][1]);
287 *d++ = '"';
288 memcpy (d, operators[k][1], slen);
289 d += slen;
290 *d++ = '"';
291 break;
294 /* Operator not found. */
295 if (operators[k][0] == NULL)
296 goto unknown;
298 else
300 /* Not a GNAT encoding. */
301 goto unknown;
304 /* The name can be directly followed by some uppercase letters. */
305 if (p[0] == 'T' && p[1] == 'K')
307 /* Task stuff. */
308 if (p[2] == 'B' && p[3] == 0)
310 /* Subprogram for task body. */
311 break;
313 else if (p[2] == '_' && p[3] == '_')
315 /* Inner declarations in a task. */
316 p += 4;
317 *d++ = '.';
318 continue;
320 else
321 goto unknown;
323 if (p[0] == 'E' && p[1] == 0)
325 /* Exception name. */
326 goto unknown;
328 if ((p[0] == 'P' || p[0] == 'N') && p[1] == 0)
330 /* Protected type subprogram. */
331 break;
333 if ((*p == 'N' || *p == 'S') && p[1] == 0)
335 /* Enumerated type name table. */
336 goto unknown;
338 if (p[0] == 'X')
340 /* Body nested. */
341 p++;
342 while (p[0] == 'n' || p[0] == 'b')
343 p++;
345 if (p[0] == 'S' && p[1] != 0 && (p[2] == '_' || p[2] == 0))
347 /* Stream operations. */
348 const char *name;
349 switch (p[1])
351 case 'R':
352 name = "'Read";
353 break;
354 case 'W':
355 name = "'Write";
356 break;
357 case 'I':
358 name = "'Input";
359 break;
360 case 'O':
361 name = "'Output";
362 break;
363 default:
364 goto unknown;
366 p += 2;
367 strcpy (d, name);
368 d += strlen (name);
370 else if (p[0] == 'D')
372 /* Controlled type operation. */
373 const char *name;
374 switch (p[1])
376 case 'F':
377 name = ".Finalize";
378 break;
379 case 'A':
380 name = ".Adjust";
381 break;
382 default:
383 goto unknown;
385 strcpy (d, name);
386 d += strlen (name);
387 break;
390 if (p[0] == '_')
392 /* Separator. */
393 if (p[1] == '_')
395 /* Standard separator. Handled first. */
396 p += 2;
398 if (ISDIGIT (*p))
400 /* Overloading number. */
402 p++;
403 while (ISDIGIT (*p) || (p[0] == '_' && ISDIGIT (p[1])));
404 if (*p == 'X')
406 p++;
407 while (p[0] == 'n' || p[0] == 'b')
408 p++;
411 else if (p[0] == '_' && p[1] != '_')
413 /* Special names. */
414 static const char * const special[][2] = {
415 { "_elabb", "'Elab_Body" },
416 { "_elabs", "'Elab_Spec" },
417 { "_size", "'Size" },
418 { "_alignment", "'Alignment" },
419 { "_assign", ".\":=\"" },
420 { NULL, NULL }
422 int k;
424 for (k = 0; special[k][0] != NULL; k++)
426 size_t slen = strlen (special[k][0]);
427 if (strncmp (p, special[k][0], slen) == 0)
429 p += slen;
430 slen = strlen (special[k][1]);
431 memcpy (d, special[k][1], slen);
432 d += slen;
433 break;
436 if (special[k][0] != NULL)
437 break;
438 else
439 goto unknown;
441 else
443 *d++ = '.';
444 continue;
447 else if (p[1] == 'B' || p[1] == 'E')
449 /* Entry Body or barrier Evaluation. */
450 p += 2;
451 while (ISDIGIT (*p))
452 p++;
453 if (p[0] == 's' && p[1] == 0)
454 break;
455 else
456 goto unknown;
458 else
459 goto unknown;
462 if (p[0] == '.' && ISDIGIT (p[1]))
464 /* Nested subprogram. */
465 p += 2;
466 while (ISDIGIT (*p))
467 p++;
469 if (*p == 0)
471 /* End of mangled name. */
472 break;
474 else
475 goto unknown;
477 *d = 0;
478 return demangled;
480 unknown:
481 XDELETEVEC (demangled);
482 len0 = strlen (mangled);
483 demangled = XNEWVEC (char, len0 + 3);
485 if (mangled[0] == '<')
486 strcpy (demangled, mangled);
487 else
488 sprintf (demangled, "<%s>", mangled);
490 return demangled;