cxxfilt 0.1.4 → 0.1.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,5 @@
1
1
  /* Demangler for the D programming language
2
- Copyright (C) 2014-2018 Free Software Foundation, Inc.
2
+ Copyright (C) 2014-2025 Free Software Foundation, Inc.
3
3
  Written by Iain Buclaw (ibuclaw@gdcproject.org)
4
4
 
5
5
  This file is part of the libiberty library.
@@ -31,6 +31,9 @@ If not, see <http://www.gnu.org/licenses/>. */
31
31
  #ifdef HAVE_CONFIG_H
32
32
  #include "config.h"
33
33
  #endif
34
+ #ifdef HAVE_LIMITS_H
35
+ #include <limits.h>
36
+ #endif
34
37
 
35
38
  #include "safe-ctype.h"
36
39
 
@@ -45,6 +48,13 @@ If not, see <http://www.gnu.org/licenses/>. */
45
48
  #include <demangle.h>
46
49
  #include "libiberty.h"
47
50
 
51
+ #ifndef ULONG_MAX
52
+ #define ULONG_MAX (~0UL)
53
+ #endif
54
+ #ifndef UINT_MAX
55
+ #define UINT_MAX (~0U)
56
+ #endif
57
+
48
58
  /* A mini string-handling package */
49
59
 
50
60
  typedef struct string /* Beware: these aren't required to be */
@@ -55,9 +65,9 @@ typedef struct string /* Beware: these aren't required to be */
55
65
  } string;
56
66
 
57
67
  static void
58
- string_need (string *s, int n)
68
+ string_need (string *s, size_t n)
59
69
  {
60
- int tem;
70
+ size_t tem;
61
71
 
62
72
  if (s->b == NULL)
63
73
  {
@@ -68,7 +78,7 @@ string_need (string *s, int n)
68
78
  s->p = s->b = XNEWVEC (char, n);
69
79
  s->e = s->b + n;
70
80
  }
71
- else if (s->e - s->p < n)
81
+ else if ((size_t) (s->e - s->p) < n)
72
82
  {
73
83
  tem = s->p - s->b;
74
84
  n += tem;
@@ -117,14 +127,14 @@ string_setlength (string *s, int n)
117
127
  static void
118
128
  string_append (string *p, const char *s)
119
129
  {
120
- int n = strlen (s);
130
+ size_t n = strlen (s);
121
131
  string_need (p, n);
122
132
  memcpy (p->p, s, n);
123
133
  p->p += n;
124
134
  }
125
135
 
126
136
  static void
127
- string_appendn (string *p, const char *s, int n)
137
+ string_appendn (string *p, const char *s, size_t n)
128
138
  {
129
139
  if (n != 0)
130
140
  {
@@ -135,7 +145,7 @@ string_appendn (string *p, const char *s, int n)
135
145
  }
136
146
 
137
147
  static void
138
- string_prependn (string *p, const char *s, int n)
148
+ string_prependn (string *p, const char *s, size_t n)
139
149
  {
140
150
  char *q;
141
151
 
@@ -160,66 +170,73 @@ string_prepend (string *p, const char *s)
160
170
  }
161
171
  }
162
172
 
163
- /* What kinds of symbol we could be parsing. */
164
- enum dlang_symbol_kinds
173
+ /* Demangle information structure we pass around. */
174
+ struct dlang_info
165
175
  {
166
- /* Top-level symbol, needs it's type checked. */
167
- dlang_top_level,
168
- /* Function symbol, needs it's type checked. */
169
- dlang_function,
170
- /* Strongly typed name, such as for classes, structs and enums. */
171
- dlang_type_name,
172
- /* Template identifier. */
173
- dlang_template_ident,
174
- /* Template symbol parameter. */
175
- dlang_template_param
176
+ /* The string we are demangling. */
177
+ const char *s;
178
+ /* The index of the last back reference. */
179
+ int last_backref;
176
180
  };
177
181
 
182
+ /* Pass as the LEN to dlang_parse_template if symbol length is not known. */
183
+ #define TEMPLATE_LENGTH_UNKNOWN (-1UL)
184
+
178
185
  /* Prototypes for forward referenced functions */
179
- static const char *dlang_function_args (string *, const char *);
186
+ static const char *dlang_function_type (string *, const char *,
187
+ struct dlang_info *);
188
+
189
+ static const char *dlang_function_args (string *, const char *,
190
+ struct dlang_info *);
180
191
 
181
- static const char *dlang_type (string *, const char *);
192
+ static const char *dlang_type (string *, const char *, struct dlang_info *);
182
193
 
183
- static const char *dlang_value (string *, const char *, const char *, char);
194
+ static const char *dlang_value (string *, const char *, const char *, char,
195
+ struct dlang_info *);
184
196
 
185
197
  static const char *dlang_parse_qualified (string *, const char *,
186
- enum dlang_symbol_kinds);
198
+ struct dlang_info *, int);
187
199
 
188
200
  static const char *dlang_parse_mangle (string *, const char *,
189
- enum dlang_symbol_kinds);
201
+ struct dlang_info *);
202
+
203
+ static const char *dlang_parse_tuple (string *, const char *,
204
+ struct dlang_info *);
190
205
 
191
- static const char *dlang_parse_tuple (string *, const char *);
206
+ static const char *dlang_parse_template (string *, const char *,
207
+ struct dlang_info *, unsigned long);
192
208
 
193
- static const char *dlang_parse_template (string *, const char *, long);
209
+ static const char *dlang_lname (string *, const char *, unsigned long);
194
210
 
195
211
 
196
212
  /* Extract the number from MANGLED, and assign the result to RET.
197
- Return the remaining string on success or NULL on failure. */
213
+ Return the remaining string on success or NULL on failure.
214
+ A result larger than UINT_MAX is considered a failure. */
198
215
  static const char *
199
- dlang_number (const char *mangled, long *ret)
216
+ dlang_number (const char *mangled, unsigned long *ret)
200
217
  {
201
218
  /* Return NULL if trying to extract something that isn't a digit. */
202
219
  if (mangled == NULL || !ISDIGIT (*mangled))
203
220
  return NULL;
204
221
 
205
- (*ret) = 0;
222
+ unsigned long val = 0;
206
223
 
207
224
  while (ISDIGIT (*mangled))
208
225
  {
209
- (*ret) *= 10;
226
+ unsigned long digit = mangled[0] - '0';
210
227
 
211
- /* If an overflow occured when multiplying by ten, the result
212
- will not be a multiple of ten. */
213
- if ((*ret % 10) != 0)
228
+ /* Check for overflow. */
229
+ if (val > (UINT_MAX - digit) / 10)
214
230
  return NULL;
215
231
 
216
- (*ret) += mangled[0] - '0';
232
+ val = val * 10 + digit;
217
233
  mangled++;
218
234
  }
219
235
 
220
- if (*mangled == '\0' || *ret < 0)
236
+ if (*mangled == '\0')
221
237
  return NULL;
222
238
 
239
+ *ret = val;
223
240
  return mangled;
224
241
  }
225
242
 
@@ -236,15 +253,15 @@ dlang_hexdigit (const char *mangled, char *ret)
236
253
 
237
254
  c = mangled[0];
238
255
  if (!ISDIGIT (c))
239
- (*ret) = (c - (ISUPPER (c) ? 'A' : 'a') + 10);
256
+ *ret = c - (ISUPPER (c) ? 'A' : 'a') + 10;
240
257
  else
241
- (*ret) = (c - '0');
258
+ *ret = c - '0';
242
259
 
243
260
  c = mangled[1];
244
261
  if (!ISDIGIT (c))
245
- (*ret) = (*ret << 4) | (c - (ISUPPER (c) ? 'A' : 'a') + 10);
262
+ *ret = (*ret << 4) | (c - (ISUPPER (c) ? 'A' : 'a') + 10);
246
263
  else
247
- (*ret) = (*ret << 4) | (c - '0');
264
+ *ret = (*ret << 4) | (c - '0');
248
265
 
249
266
  mangled += 2;
250
267
 
@@ -267,6 +284,178 @@ dlang_call_convention_p (const char *mangled)
267
284
  }
268
285
  }
269
286
 
287
+ /* Extract the back reference position from MANGLED, and assign the result
288
+ to RET. Return the remaining string on success or NULL on failure.
289
+ A result <= 0 is a failure. */
290
+ static const char *
291
+ dlang_decode_backref (const char *mangled, long *ret)
292
+ {
293
+ /* Return NULL if trying to extract something that isn't a digit. */
294
+ if (mangled == NULL || !ISALPHA (*mangled))
295
+ return NULL;
296
+
297
+ /* Any identifier or non-basic type that has been emitted to the mangled
298
+ symbol before will not be emitted again, but is referenced by a special
299
+ sequence encoding the relative position of the original occurrence in the
300
+ mangled symbol name.
301
+
302
+ Numbers in back references are encoded with base 26 by upper case letters
303
+ A-Z for higher digits but lower case letters a-z for the last digit.
304
+
305
+ NumberBackRef:
306
+ [a-z]
307
+ [A-Z] NumberBackRef
308
+ ^
309
+ */
310
+ unsigned long val = 0;
311
+
312
+ while (ISALPHA (*mangled))
313
+ {
314
+ /* Check for overflow. */
315
+ if (val > (ULONG_MAX - 25) / 26)
316
+ break;
317
+
318
+ val *= 26;
319
+
320
+ if (mangled[0] >= 'a' && mangled[0] <= 'z')
321
+ {
322
+ val += mangled[0] - 'a';
323
+ if ((long) val <= 0)
324
+ break;
325
+ *ret = val;
326
+ return mangled + 1;
327
+ }
328
+
329
+ val += mangled[0] - 'A';
330
+ mangled++;
331
+ }
332
+
333
+ return NULL;
334
+ }
335
+
336
+ /* Extract the symbol pointed at by the back reference and assign the result
337
+ to RET. Return the remaining string on success or NULL on failure. */
338
+ static const char *
339
+ dlang_backref (const char *mangled, const char **ret, struct dlang_info *info)
340
+ {
341
+ *ret = NULL;
342
+
343
+ if (mangled == NULL || *mangled != 'Q')
344
+ return NULL;
345
+
346
+ /* Position of 'Q'. */
347
+ const char *qpos = mangled;
348
+ long refpos;
349
+ mangled++;
350
+
351
+ mangled = dlang_decode_backref (mangled, &refpos);
352
+ if (mangled == NULL)
353
+ return NULL;
354
+
355
+ if (refpos > qpos - info->s)
356
+ return NULL;
357
+
358
+ /* Set the position of the back reference. */
359
+ *ret = qpos - refpos;
360
+
361
+ return mangled;
362
+ }
363
+
364
+ /* Demangle a back referenced symbol from MANGLED and append it to DECL.
365
+ Return the remaining string on success or NULL on failure. */
366
+ static const char *
367
+ dlang_symbol_backref (string *decl, const char *mangled,
368
+ struct dlang_info *info)
369
+ {
370
+ /* An identifier back reference always points to a digit 0 to 9.
371
+
372
+ IdentifierBackRef:
373
+ Q NumberBackRef
374
+ ^
375
+ */
376
+ const char *backref;
377
+ unsigned long len;
378
+
379
+ /* Get position of the back reference. */
380
+ mangled = dlang_backref (mangled, &backref, info);
381
+
382
+ /* Must point to a simple identifier. */
383
+ backref = dlang_number (backref, &len);
384
+ if (backref == NULL || strlen(backref) < len)
385
+ return NULL;
386
+
387
+ backref = dlang_lname (decl, backref, len);
388
+ if (backref == NULL)
389
+ return NULL;
390
+
391
+ return mangled;
392
+ }
393
+
394
+ /* Demangle a back referenced type from MANGLED and append it to DECL.
395
+ IS_FUNCTION is 1 if the back referenced type is expected to be a function.
396
+ Return the remaining string on success or NULL on failure. */
397
+ static const char *
398
+ dlang_type_backref (string *decl, const char *mangled, struct dlang_info *info,
399
+ int is_function)
400
+ {
401
+ /* A type back reference always points to a letter.
402
+
403
+ TypeBackRef:
404
+ Q NumberBackRef
405
+ ^
406
+ */
407
+ const char *backref;
408
+
409
+ /* If we appear to be moving backwards through the mangle string, then
410
+ bail as this may be a recursive back reference. */
411
+ if (mangled - info->s >= info->last_backref)
412
+ return NULL;
413
+
414
+ int save_refpos = info->last_backref;
415
+ info->last_backref = mangled - info->s;
416
+
417
+ /* Get position of the back reference. */
418
+ mangled = dlang_backref (mangled, &backref, info);
419
+
420
+ /* Must point to a type. */
421
+ if (is_function)
422
+ backref = dlang_function_type (decl, backref, info);
423
+ else
424
+ backref = dlang_type (decl, backref, info);
425
+
426
+ info->last_backref = save_refpos;
427
+
428
+ if (backref == NULL)
429
+ return NULL;
430
+
431
+ return mangled;
432
+ }
433
+
434
+ /* Extract the beginning of a symbol name from MANGLED and
435
+ return 1 on success or 0 on failure. */
436
+ static int
437
+ dlang_symbol_name_p (const char *mangled, struct dlang_info *info)
438
+ {
439
+ long ret;
440
+ const char *qref = mangled;
441
+
442
+ if (ISDIGIT (*mangled))
443
+ return 1;
444
+
445
+ if (mangled[0] == '_' && mangled[1] == '_'
446
+ && (mangled[2] == 'T' || mangled[2] == 'U'))
447
+ return 1;
448
+
449
+ if (*mangled != 'Q')
450
+ return 0;
451
+
452
+ mangled = dlang_decode_backref (mangled + 1, &ret);
453
+ if (mangled == NULL || ret > qref - info->s)
454
+ return 0;
455
+
456
+ return ISDIGIT (qref[-ret]);
457
+ }
458
+
270
459
  /* Demangle the calling convention from MANGLED and append it to DECL.
271
460
  Return the remaining string on success or NULL on failure. */
272
461
  static const char *
@@ -385,9 +574,11 @@ dlang_attributes (string *decl, const char *mangled)
385
574
  case 'g':
386
575
  case 'h':
387
576
  case 'k':
577
+ case 'n':
388
578
  /* inout parameter is represented as 'Ng'.
389
579
  vector parameter is represented as 'Nh'.
390
- return paramenter is represented as 'Nk'.
580
+ return parameter is represented as 'Nk'.
581
+ typeof(*null) parameter is represented as 'Nn'.
391
582
  If we see this, then we know we're really in the
392
583
  parameter list. Rewind and break. */
393
584
  mangled--;
@@ -404,6 +595,10 @@ dlang_attributes (string *decl, const char *mangled)
404
595
  mangled++;
405
596
  string_append (decl, "scope ");
406
597
  continue;
598
+ case 'm': /* @live */
599
+ mangled++;
600
+ string_append (decl, "@live ");
601
+ continue;
407
602
 
408
603
  default: /* unknown attribute */
409
604
  return NULL;
@@ -414,13 +609,39 @@ dlang_attributes (string *decl, const char *mangled)
414
609
  return mangled;
415
610
  }
416
611
 
612
+ /* Demangle the function type from MANGLED without the return type.
613
+ The arguments are appended to ARGS, the calling convention is appended
614
+ to CALL and attributes are appended to ATTR. Any of these can be NULL
615
+ to throw the information away. Return the remaining string on success
616
+ or NULL on failure. */
617
+ static const char *
618
+ dlang_function_type_noreturn (string *args, string *call, string *attr,
619
+ const char *mangled, struct dlang_info *info)
620
+ {
621
+ string dump;
622
+ string_init (&dump);
623
+
624
+ /* Skip over calling convention and attributes. */
625
+ mangled = dlang_call_convention (call ? call : &dump, mangled);
626
+ mangled = dlang_attributes (attr ? attr : &dump, mangled);
627
+
628
+ if (args)
629
+ string_append (args, "(");
630
+
631
+ mangled = dlang_function_args (args ? args : &dump, mangled, info);
632
+ if (args)
633
+ string_append (args, ")");
634
+
635
+ string_delete (&dump);
636
+ return mangled;
637
+ }
638
+
417
639
  /* Demangle the function type from MANGLED and append it to DECL.
418
640
  Return the remaining string on success or NULL on failure. */
419
641
  static const char *
420
- dlang_function_type (string *decl, const char *mangled)
642
+ dlang_function_type (string *decl, const char *mangled, struct dlang_info *info)
421
643
  {
422
644
  string attr, args, type;
423
- size_t szattr, szargs, sztype;
424
645
 
425
646
  if (mangled == NULL || *mangled == '\0')
426
647
  return NULL;
@@ -435,27 +656,16 @@ dlang_function_type (string *decl, const char *mangled)
435
656
  string_init (&args);
436
657
  string_init (&type);
437
658
 
438
- /* Function call convention. */
439
- mangled = dlang_call_convention (decl, mangled);
440
-
441
- /* Function attributes. */
442
- mangled = dlang_attributes (&attr, mangled);
443
- szattr = string_length (&attr);
444
-
445
- /* Function arguments. */
446
- mangled = dlang_function_args (&args, mangled);
447
- szargs = string_length (&args);
659
+ mangled = dlang_function_type_noreturn (&args, decl, &attr, mangled, info);
448
660
 
449
661
  /* Function return type. */
450
- mangled = dlang_type (&type, mangled);
451
- sztype = string_length (&type);
662
+ mangled = dlang_type (&type, mangled, info);
452
663
 
453
664
  /* Append to decl in order. */
454
- string_appendn (decl, type.b, sztype);
455
- string_append (decl, "(");
456
- string_appendn (decl, args.b, szargs);
457
- string_append (decl, ") ");
458
- string_appendn (decl, attr.b, szattr);
665
+ string_appendn (decl, type.b, string_length (&type));
666
+ string_appendn (decl, args.b, string_length (&args));
667
+ string_append (decl, " ");
668
+ string_appendn (decl, attr.b, string_length (&attr));
459
669
 
460
670
  string_delete (&attr);
461
671
  string_delete (&args);
@@ -466,7 +676,7 @@ dlang_function_type (string *decl, const char *mangled)
466
676
  /* Demangle the argument list from MANGLED and append it to DECL.
467
677
  Return the remaining string on success or NULL on failure. */
468
678
  static const char *
469
- dlang_function_args (string *decl, const char *mangled)
679
+ dlang_function_args (string *decl, const char *mangled, struct dlang_info *info)
470
680
  {
471
681
  size_t n = 0;
472
682
 
@@ -506,6 +716,15 @@ dlang_function_args (string *decl, const char *mangled)
506
716
 
507
717
  switch (*mangled)
508
718
  {
719
+ case 'I': /* in(T) */
720
+ mangled++;
721
+ string_append (decl, "in ");
722
+ if (*mangled == 'K') /* in ref(T) */
723
+ {
724
+ mangled++;
725
+ string_append (decl, "ref ");
726
+ }
727
+ break;
509
728
  case 'J': /* out(T) */
510
729
  mangled++;
511
730
  string_append (decl, "out ");
@@ -519,7 +738,7 @@ dlang_function_args (string *decl, const char *mangled)
519
738
  string_append (decl, "lazy ");
520
739
  break;
521
740
  }
522
- mangled = dlang_type (decl, mangled);
741
+ mangled = dlang_type (decl, mangled, info);
523
742
  }
524
743
 
525
744
  return mangled;
@@ -528,7 +747,7 @@ dlang_function_args (string *decl, const char *mangled)
528
747
  /* Demangle the type from MANGLED and append it to DECL.
529
748
  Return the remaining string on success or NULL on failure. */
530
749
  static const char *
531
- dlang_type (string *decl, const char *mangled)
750
+ dlang_type (string *decl, const char *mangled, struct dlang_info *info)
532
751
  {
533
752
  if (mangled == NULL || *mangled == '\0')
534
753
  return NULL;
@@ -538,19 +757,19 @@ dlang_type (string *decl, const char *mangled)
538
757
  case 'O': /* shared(T) */
539
758
  mangled++;
540
759
  string_append (decl, "shared(");
541
- mangled = dlang_type (decl, mangled);
760
+ mangled = dlang_type (decl, mangled, info);
542
761
  string_append (decl, ")");
543
762
  return mangled;
544
763
  case 'x': /* const(T) */
545
764
  mangled++;
546
765
  string_append (decl, "const(");
547
- mangled = dlang_type (decl, mangled);
766
+ mangled = dlang_type (decl, mangled, info);
548
767
  string_append (decl, ")");
549
768
  return mangled;
550
769
  case 'y': /* immutable(T) */
551
770
  mangled++;
552
771
  string_append (decl, "immutable(");
553
- mangled = dlang_type (decl, mangled);
772
+ mangled = dlang_type (decl, mangled, info);
554
773
  string_append (decl, ")");
555
774
  return mangled;
556
775
  case 'N':
@@ -559,7 +778,7 @@ dlang_type (string *decl, const char *mangled)
559
778
  {
560
779
  mangled++;
561
780
  string_append (decl, "inout(");
562
- mangled = dlang_type (decl, mangled);
781
+ mangled = dlang_type (decl, mangled, info);
563
782
  string_append (decl, ")");
564
783
  return mangled;
565
784
  }
@@ -567,15 +786,21 @@ dlang_type (string *decl, const char *mangled)
567
786
  {
568
787
  mangled++;
569
788
  string_append (decl, "__vector(");
570
- mangled = dlang_type (decl, mangled);
789
+ mangled = dlang_type (decl, mangled, info);
571
790
  string_append (decl, ")");
572
791
  return mangled;
573
792
  }
793
+ else if (*mangled == 'n') /* typeof(*null) */
794
+ {
795
+ mangled++;
796
+ string_append (decl, "typeof(*null)");
797
+ return mangled;
798
+ }
574
799
  else
575
800
  return NULL;
576
801
  case 'A': /* dynamic array (T[]) */
577
802
  mangled++;
578
- mangled = dlang_type (decl, mangled);
803
+ mangled = dlang_type (decl, mangled, info);
579
804
  string_append (decl, "[]");
580
805
  return mangled;
581
806
  case 'G': /* static array (T[N]) */
@@ -590,7 +815,7 @@ dlang_type (string *decl, const char *mangled)
590
815
  num++;
591
816
  mangled++;
592
817
  }
593
- mangled = dlang_type (decl, mangled);
818
+ mangled = dlang_type (decl, mangled, info);
594
819
  string_append (decl, "[");
595
820
  string_appendn (decl, numptr, num);
596
821
  string_append (decl, "]");
@@ -603,10 +828,10 @@ dlang_type (string *decl, const char *mangled)
603
828
  mangled++;
604
829
 
605
830
  string_init (&type);
606
- mangled = dlang_type (&type, mangled);
831
+ mangled = dlang_type (&type, mangled, info);
607
832
  sztype = string_length (&type);
608
833
 
609
- mangled = dlang_type (decl, mangled);
834
+ mangled = dlang_type (decl, mangled, info);
610
835
  string_append (decl, "[");
611
836
  string_appendn (decl, type.b, sztype);
612
837
  string_append (decl, "]");
@@ -618,7 +843,7 @@ dlang_type (string *decl, const char *mangled)
618
843
  mangled++;
619
844
  if (!dlang_call_convention_p (mangled))
620
845
  {
621
- mangled = dlang_type (decl, mangled);
846
+ mangled = dlang_type (decl, mangled, info);
622
847
  string_append (decl, "*");
623
848
  return mangled;
624
849
  }
@@ -630,16 +855,15 @@ dlang_type (string *decl, const char *mangled)
630
855
  case 'R': /* function T (C++) */
631
856
  case 'Y': /* function T (Objective-C) */
632
857
  /* Function pointer types don't include the trailing asterisk. */
633
- mangled = dlang_function_type (decl, mangled);
858
+ mangled = dlang_function_type (decl, mangled, info);
634
859
  string_append (decl, "function");
635
860
  return mangled;
636
- case 'I': /* ident T */
637
861
  case 'C': /* class T */
638
862
  case 'S': /* struct T */
639
863
  case 'E': /* enum T */
640
864
  case 'T': /* typedef T */
641
865
  mangled++;
642
- return dlang_parse_qualified (decl, mangled, dlang_type_name);
866
+ return dlang_parse_qualified (decl, mangled, info, 0);
643
867
  case 'D': /* delegate T */
644
868
  {
645
869
  string mods;
@@ -650,7 +874,12 @@ dlang_type (string *decl, const char *mangled)
650
874
  mangled = dlang_type_modifiers (&mods, mangled);
651
875
  szmods = string_length (&mods);
652
876
 
653
- mangled = dlang_function_type (decl, mangled);
877
+ /* Back referenced function type. */
878
+ if (mangled && *mangled == 'Q')
879
+ mangled = dlang_type_backref (decl, mangled, info, 1);
880
+ else
881
+ mangled = dlang_function_type (decl, mangled, info);
882
+
654
883
  string_append (decl, "delegate");
655
884
  string_appendn (decl, mods.b, szmods);
656
885
 
@@ -659,12 +888,12 @@ dlang_type (string *decl, const char *mangled)
659
888
  }
660
889
  case 'B': /* tuple T */
661
890
  mangled++;
662
- return dlang_parse_tuple (decl, mangled);
891
+ return dlang_parse_tuple (decl, mangled, info);
663
892
 
664
893
  /* Basic types */
665
894
  case 'n':
666
895
  mangled++;
667
- string_append (decl, "none");
896
+ string_append (decl, "typeof(null)");
668
897
  return mangled;
669
898
  case 'v':
670
899
  mangled++;
@@ -773,6 +1002,10 @@ dlang_type (string *decl, const char *mangled)
773
1002
  }
774
1003
  return NULL;
775
1004
 
1005
+ /* Back referenced type. */
1006
+ case 'Q':
1007
+ return dlang_type_backref (decl, mangled, info, 0);
1008
+
776
1009
  default: /* unhandled */
777
1010
  return NULL;
778
1011
  }
@@ -781,152 +1014,146 @@ dlang_type (string *decl, const char *mangled)
781
1014
  /* Extract the identifier from MANGLED and append it to DECL.
782
1015
  Return the remaining string on success or NULL on failure. */
783
1016
  static const char *
784
- dlang_identifier (string *decl, const char *mangled,
785
- enum dlang_symbol_kinds kind)
1017
+ dlang_identifier (string *decl, const char *mangled, struct dlang_info *info)
786
1018
  {
787
- long len;
1019
+ unsigned long len;
1020
+
1021
+ if (mangled == NULL || *mangled == '\0')
1022
+ return NULL;
1023
+
1024
+ if (*mangled == 'Q')
1025
+ return dlang_symbol_backref (decl, mangled, info);
1026
+
1027
+ /* May be a template instance without a length prefix. */
1028
+ if (mangled[0] == '_' && mangled[1] == '_'
1029
+ && (mangled[2] == 'T' || mangled[2] == 'U'))
1030
+ return dlang_parse_template (decl, mangled, info, TEMPLATE_LENGTH_UNKNOWN);
1031
+
788
1032
  const char *endptr = dlang_number (mangled, &len);
789
1033
 
790
1034
  if (endptr == NULL || len == 0)
791
1035
  return NULL;
792
1036
 
793
- /* In template parameter symbols, the first character of the mangled
794
- name can be a digit. This causes ambiguity issues because the
795
- digits of the two numbers are adjacent. */
796
- if (kind == dlang_template_param)
797
- {
798
- long psize = len;
799
- const char *pend;
800
- int saved = string_length (decl);
801
-
802
- /* Work backwards until a match is found. */
803
- for (pend = endptr; endptr != NULL; pend--)
804
- {
805
- mangled = pend;
1037
+ if (strlen (endptr) < len)
1038
+ return NULL;
806
1039
 
807
- /* Reached the beginning of the pointer to the name length,
808
- try parsing the entire symbol. */
809
- if (psize == 0)
810
- {
811
- psize = len;
812
- pend = endptr;
813
- endptr = NULL;
814
- }
1040
+ mangled = endptr;
815
1041
 
816
- /* Check whether template parameter is a function with a valid
817
- return type or an untyped identifier. */
818
- if (ISDIGIT (*mangled))
819
- mangled = dlang_parse_qualified (decl, mangled,
820
- dlang_template_ident);
821
- else if (strncmp (mangled, "_D", 2) == 0)
822
- mangled = dlang_parse_mangle (decl, mangled, dlang_function);
1042
+ /* May be a template instance with a length prefix. */
1043
+ if (len >= 5 && mangled[0] == '_' && mangled[1] == '_'
1044
+ && (mangled[2] == 'T' || mangled[2] == 'U'))
1045
+ return dlang_parse_template (decl, mangled, info, len);
823
1046
 
824
- /* Check for name length mismatch. */
825
- if (mangled && (mangled - pend) == psize)
826
- return mangled;
1047
+ /* There can be multiple different declarations in the same function that have
1048
+ the same mangled name. To make the mangled names unique, a fake parent in
1049
+ the form `__Sddd' is added to the symbol. */
1050
+ if (len >= 4 && mangled[0] == '_' && mangled[1] == '_' && mangled[2] == 'S')
1051
+ {
1052
+ const char *numptr = mangled + 3;
1053
+ while (numptr < (mangled + len) && ISDIGIT (*numptr))
1054
+ numptr++;
827
1055
 
828
- psize /= 10;
829
- string_setlength (decl, saved);
1056
+ if (mangled + len == numptr)
1057
+ {
1058
+ /* Skip over the fake parent. */
1059
+ mangled += len;
1060
+ return dlang_identifier (decl, mangled, info);
830
1061
  }
831
1062
 
832
- /* No match on any combinations. */
833
- return NULL;
1063
+ /* else demangle it as a plain identifier. */
834
1064
  }
835
- else
836
- {
837
- if (strlen (endptr) < (size_t) len)
838
- return NULL;
839
-
840
- mangled = endptr;
841
1065
 
842
- /* May be a template instance. */
843
- if (len >= 5 && mangled[0] == '_' && mangled[1] == '_'
844
- && (mangled[2] == 'T' || mangled[2] == 'U'))
845
- return dlang_parse_template (decl, mangled, len);
1066
+ return dlang_lname (decl, mangled, len);
1067
+ }
846
1068
 
847
- switch (len)
1069
+ /* Extract the plain identifier from MANGLED and prepend/append it to DECL
1070
+ with special treatment for some magic compiler generted symbols.
1071
+ Return the remaining string on success or NULL on failure. */
1072
+ static const char *
1073
+ dlang_lname (string *decl, const char *mangled, unsigned long len)
1074
+ {
1075
+ switch (len)
1076
+ {
1077
+ case 6:
1078
+ if (strncmp (mangled, "__ctor", len) == 0)
848
1079
  {
849
- case 6:
850
- if (strncmp (mangled, "__ctor", len) == 0)
851
- {
852
- /* Constructor symbol for a class/struct. */
853
- string_append (decl, "this");
854
- mangled += len;
855
- return mangled;
856
- }
857
- else if (strncmp (mangled, "__dtor", len) == 0)
858
- {
859
- /* Destructor symbol for a class/struct. */
860
- string_append (decl, "~this");
861
- mangled += len;
862
- return mangled;
863
- }
864
- else if (strncmp (mangled, "__initZ", len+1) == 0)
865
- {
866
- /* The static initialiser for a given symbol. */
867
- string_prepend (decl, "initializer for ");
868
- string_setlength (decl, string_length (decl) - 1);
869
- mangled += len;
870
- return mangled;
871
- }
872
- else if (strncmp (mangled, "__vtblZ", len+1) == 0)
873
- {
874
- /* The vtable symbol for a given class. */
875
- string_prepend (decl, "vtable for ");
876
- string_setlength (decl, string_length (decl) - 1);
877
- mangled += len;
878
- return mangled;
879
- }
880
- break;
881
-
882
- case 7:
883
- if (strncmp (mangled, "__ClassZ", len+1) == 0)
884
- {
885
- /* The classinfo symbol for a given class. */
886
- string_prepend (decl, "ClassInfo for ");
887
- string_setlength (decl, string_length (decl) - 1);
888
- mangled += len;
889
- return mangled;
890
- }
891
- break;
1080
+ /* Constructor symbol for a class/struct. */
1081
+ string_append (decl, "this");
1082
+ mangled += len;
1083
+ return mangled;
1084
+ }
1085
+ else if (strncmp (mangled, "__dtor", len) == 0)
1086
+ {
1087
+ /* Destructor symbol for a class/struct. */
1088
+ string_append (decl, "~this");
1089
+ mangled += len;
1090
+ return mangled;
1091
+ }
1092
+ else if (strncmp (mangled, "__initZ", len + 1) == 0)
1093
+ {
1094
+ /* The static initialiser for a given symbol. */
1095
+ string_prepend (decl, "initializer for ");
1096
+ string_setlength (decl, string_length (decl) - 1);
1097
+ mangled += len;
1098
+ return mangled;
1099
+ }
1100
+ else if (strncmp (mangled, "__vtblZ", len + 1) == 0)
1101
+ {
1102
+ /* The vtable symbol for a given class. */
1103
+ string_prepend (decl, "vtable for ");
1104
+ string_setlength (decl, string_length (decl) - 1);
1105
+ mangled += len;
1106
+ return mangled;
1107
+ }
1108
+ break;
892
1109
 
893
- case 10:
894
- if (strncmp (mangled, "__postblitMFZ", len+3) == 0)
895
- {
896
- /* Postblit symbol for a struct. */
897
- string_append (decl, "this(this)");
898
- mangled += len + 3;
899
- return mangled;
900
- }
901
- break;
1110
+ case 7:
1111
+ if (strncmp (mangled, "__ClassZ", len + 1) == 0)
1112
+ {
1113
+ /* The classinfo symbol for a given class. */
1114
+ string_prepend (decl, "ClassInfo for ");
1115
+ string_setlength (decl, string_length (decl) - 1);
1116
+ mangled += len;
1117
+ return mangled;
1118
+ }
1119
+ break;
902
1120
 
903
- case 11:
904
- if (strncmp (mangled, "__InterfaceZ", len+1) == 0)
905
- {
906
- /* The interface symbol for a given class. */
907
- string_prepend (decl, "Interface for ");
908
- string_setlength (decl, string_length (decl) - 1);
909
- mangled += len;
910
- return mangled;
911
- }
912
- break;
1121
+ case 10:
1122
+ if (strncmp (mangled, "__postblitMFZ", len + 3) == 0)
1123
+ {
1124
+ /* Postblit symbol for a struct. */
1125
+ string_append (decl, "this(this)");
1126
+ mangled += len + 3;
1127
+ return mangled;
1128
+ }
1129
+ break;
913
1130
 
914
- case 12:
915
- if (strncmp (mangled, "__ModuleInfoZ", len+1) == 0)
916
- {
917
- /* The ModuleInfo symbol for a given module. */
918
- string_prepend (decl, "ModuleInfo for ");
919
- string_setlength (decl, string_length (decl) - 1);
920
- mangled += len;
921
- return mangled;
922
- }
923
- break;
1131
+ case 11:
1132
+ if (strncmp (mangled, "__InterfaceZ", len + 1) == 0)
1133
+ {
1134
+ /* The interface symbol for a given class. */
1135
+ string_prepend (decl, "Interface for ");
1136
+ string_setlength (decl, string_length (decl) - 1);
1137
+ mangled += len;
1138
+ return mangled;
924
1139
  }
1140
+ break;
925
1141
 
926
- string_appendn (decl, mangled, len);
927
- mangled += len;
1142
+ case 12:
1143
+ if (strncmp (mangled, "__ModuleInfoZ", len + 1) == 0)
1144
+ {
1145
+ /* The ModuleInfo symbol for a given module. */
1146
+ string_prepend (decl, "ModuleInfo for ");
1147
+ string_setlength (decl, string_length (decl) - 1);
1148
+ mangled += len;
1149
+ return mangled;
1150
+ }
1151
+ break;
928
1152
  }
929
1153
 
1154
+ string_appendn (decl, mangled, len);
1155
+ mangled += len;
1156
+
930
1157
  return mangled;
931
1158
  }
932
1159
 
@@ -939,10 +1166,10 @@ dlang_parse_integer (string *decl, const char *mangled, char type)
939
1166
  if (type == 'a' || type == 'u' || type == 'w')
940
1167
  {
941
1168
  /* Parse character value. */
942
- char value[10];
943
- int pos = 10;
1169
+ char value[20];
1170
+ int pos = sizeof(value);
944
1171
  int width = 0;
945
- long val;
1172
+ unsigned long val;
946
1173
 
947
1174
  mangled = dlang_number (mangled, &val);
948
1175
  if (mangled == NULL)
@@ -991,14 +1218,14 @@ dlang_parse_integer (string *decl, const char *mangled, char type)
991
1218
  for (; width > 0; width--)
992
1219
  value[--pos] = '0';
993
1220
 
994
- string_appendn (decl, &(value[pos]), 10 - pos);
1221
+ string_appendn (decl, &(value[pos]), sizeof(value) - pos);
995
1222
  }
996
1223
  string_append (decl, "'");
997
1224
  }
998
1225
  else if (type == 'b')
999
1226
  {
1000
1227
  /* Parse boolean value. */
1001
- long val;
1228
+ unsigned long val;
1002
1229
 
1003
1230
  mangled = dlang_number (mangled, &val);
1004
1231
  if (mangled == NULL)
@@ -1117,7 +1344,7 @@ static const char *
1117
1344
  dlang_parse_string (string *decl, const char *mangled)
1118
1345
  {
1119
1346
  char type = *mangled;
1120
- long len;
1347
+ unsigned long len;
1121
1348
 
1122
1349
  mangled++;
1123
1350
  mangled = dlang_number (mangled, &len);
@@ -1179,9 +1406,10 @@ dlang_parse_string (string *decl, const char *mangled)
1179
1406
  /* Extract the static array value from MANGLED and append it to DECL.
1180
1407
  Return the remaining string on success or NULL on failure. */
1181
1408
  static const char *
1182
- dlang_parse_arrayliteral (string *decl, const char *mangled)
1409
+ dlang_parse_arrayliteral (string *decl, const char *mangled,
1410
+ struct dlang_info *info)
1183
1411
  {
1184
- long elements;
1412
+ unsigned long elements;
1185
1413
 
1186
1414
  mangled = dlang_number (mangled, &elements);
1187
1415
  if (mangled == NULL)
@@ -1190,7 +1418,10 @@ dlang_parse_arrayliteral (string *decl, const char *mangled)
1190
1418
  string_append (decl, "[");
1191
1419
  while (elements--)
1192
1420
  {
1193
- mangled = dlang_value (decl, mangled, NULL, '\0');
1421
+ mangled = dlang_value (decl, mangled, NULL, '\0', info);
1422
+ if (mangled == NULL)
1423
+ return NULL;
1424
+
1194
1425
  if (elements != 0)
1195
1426
  string_append (decl, ", ");
1196
1427
  }
@@ -1202,9 +1433,10 @@ dlang_parse_arrayliteral (string *decl, const char *mangled)
1202
1433
  /* Extract the associative array value from MANGLED and append it to DECL.
1203
1434
  Return the remaining string on success or NULL on failure. */
1204
1435
  static const char *
1205
- dlang_parse_assocarray (string *decl, const char *mangled)
1436
+ dlang_parse_assocarray (string *decl, const char *mangled,
1437
+ struct dlang_info *info)
1206
1438
  {
1207
- long elements;
1439
+ unsigned long elements;
1208
1440
 
1209
1441
  mangled = dlang_number (mangled, &elements);
1210
1442
  if (mangled == NULL)
@@ -1213,9 +1445,14 @@ dlang_parse_assocarray (string *decl, const char *mangled)
1213
1445
  string_append (decl, "[");
1214
1446
  while (elements--)
1215
1447
  {
1216
- mangled = dlang_value (decl, mangled, NULL, '\0');
1448
+ mangled = dlang_value (decl, mangled, NULL, '\0', info);
1449
+ if (mangled == NULL)
1450
+ return NULL;
1451
+
1217
1452
  string_append (decl, ":");
1218
- mangled = dlang_value (decl, mangled, NULL, '\0');
1453
+ mangled = dlang_value (decl, mangled, NULL, '\0', info);
1454
+ if (mangled == NULL)
1455
+ return NULL;
1219
1456
 
1220
1457
  if (elements != 0)
1221
1458
  string_append (decl, ", ");
@@ -1228,9 +1465,10 @@ dlang_parse_assocarray (string *decl, const char *mangled)
1228
1465
  /* Extract the struct literal value for NAME from MANGLED and append it to DECL.
1229
1466
  Return the remaining string on success or NULL on failure. */
1230
1467
  static const char *
1231
- dlang_parse_structlit (string *decl, const char *mangled, const char *name)
1468
+ dlang_parse_structlit (string *decl, const char *mangled, const char *name,
1469
+ struct dlang_info *info)
1232
1470
  {
1233
- long args;
1471
+ unsigned long args;
1234
1472
 
1235
1473
  mangled = dlang_number (mangled, &args);
1236
1474
  if (mangled == NULL)
@@ -1242,7 +1480,10 @@ dlang_parse_structlit (string *decl, const char *mangled, const char *name)
1242
1480
  string_append (decl, "(");
1243
1481
  while (args--)
1244
1482
  {
1245
- mangled = dlang_value (decl, mangled, NULL, '\0');
1483
+ mangled = dlang_value (decl, mangled, NULL, '\0', info);
1484
+ if (mangled == NULL)
1485
+ return NULL;
1486
+
1246
1487
  if (args != 0)
1247
1488
  string_append (decl, ", ");
1248
1489
  }
@@ -1254,7 +1495,8 @@ dlang_parse_structlit (string *decl, const char *mangled, const char *name)
1254
1495
  /* Extract the value from MANGLED and append it to DECL.
1255
1496
  Return the remaining string on success or NULL on failure. */
1256
1497
  static const char *
1257
- dlang_value (string *decl, const char *mangled, const char *name, char type)
1498
+ dlang_value (string *decl, const char *mangled, const char *name, char type,
1499
+ struct dlang_info *info)
1258
1500
  {
1259
1501
  if (mangled == NULL || *mangled == '\0')
1260
1502
  return NULL;
@@ -1315,15 +1557,24 @@ dlang_value (string *decl, const char *mangled, const char *name, char type)
1315
1557
  case 'A':
1316
1558
  mangled++;
1317
1559
  if (type == 'H')
1318
- mangled = dlang_parse_assocarray (decl, mangled);
1560
+ mangled = dlang_parse_assocarray (decl, mangled, info);
1319
1561
  else
1320
- mangled = dlang_parse_arrayliteral (decl, mangled);
1562
+ mangled = dlang_parse_arrayliteral (decl, mangled, info);
1321
1563
  break;
1322
1564
 
1323
1565
  /* Struct values. */
1324
1566
  case 'S':
1325
1567
  mangled++;
1326
- mangled = dlang_parse_structlit (decl, mangled, name);
1568
+ mangled = dlang_parse_structlit (decl, mangled, name, info);
1569
+ break;
1570
+
1571
+ /* Function literal symbol. */
1572
+ case 'f':
1573
+ mangled++;
1574
+ if (strncmp (mangled, "_D", 2) != 0
1575
+ || !dlang_symbol_name_p (mangled + 2, info))
1576
+ return NULL;
1577
+ mangled = dlang_parse_mangle (decl, mangled, info);
1327
1578
  break;
1328
1579
 
1329
1580
  default:
@@ -1336,22 +1587,22 @@ dlang_value (string *decl, const char *mangled, const char *name, char type)
1336
1587
  /* Extract and demangle the symbol in MANGLED and append it to DECL.
1337
1588
  Returns the remaining signature on success or NULL on failure. */
1338
1589
  static const char *
1339
- dlang_parse_mangle (string *decl, const char *mangled,
1340
- enum dlang_symbol_kinds kind)
1590
+ dlang_parse_mangle (string *decl, const char *mangled, struct dlang_info *info)
1341
1591
  {
1342
1592
  /* A D mangled symbol is comprised of both scope and type information.
1343
1593
 
1344
1594
  MangleName:
1345
1595
  _D QualifiedName Type
1346
- _D QualifiedName M Type
1347
1596
  _D QualifiedName Z
1348
1597
  ^
1349
1598
  The caller should have guaranteed that the start pointer is at the
1350
1599
  above location.
1600
+ Note that type is never a function type, but only the return type of
1601
+ a function or the type of a variable.
1351
1602
  */
1352
1603
  mangled += 2;
1353
1604
 
1354
- mangled = dlang_parse_qualified (decl, mangled, dlang_top_level);
1605
+ mangled = dlang_parse_qualified (decl, mangled, info, 1);
1355
1606
 
1356
1607
  if (mangled != NULL)
1357
1608
  {
@@ -1360,123 +1611,97 @@ dlang_parse_mangle (string *decl, const char *mangled,
1360
1611
  mangled++;
1361
1612
  else
1362
1613
  {
1363
- string mods;
1364
- int saved;
1365
-
1366
- /* Skip over 'this' parameter. */
1367
- if (*mangled == 'M')
1368
- mangled++;
1369
-
1370
- /* Save the type modifiers for appending at the end if needed. */
1371
- string_init (&mods);
1372
- mangled = dlang_type_modifiers (&mods, mangled);
1373
-
1374
- if (mangled && dlang_call_convention_p (mangled))
1375
- {
1376
- /* Skip over calling convention and attributes. */
1377
- saved = string_length (decl);
1378
- mangled = dlang_call_convention (decl, mangled);
1379
- mangled = dlang_attributes (decl, mangled);
1380
- string_setlength (decl, saved);
1381
-
1382
- string_append (decl, "(");
1383
- mangled = dlang_function_args (decl, mangled);
1384
- string_append (decl, ")");
1385
-
1386
- /* Add any const/immutable/shared modifier. */
1387
- string_appendn (decl, mods.b, string_length (&mods));
1388
- }
1614
+ /* Discard the declaration or return type. */
1615
+ string type;
1389
1616
 
1390
- /* Consume the decl type of symbol. */
1391
- saved = string_length (decl);
1392
- mangled = dlang_type (decl, mangled);
1393
- string_setlength (decl, saved);
1394
-
1395
- string_delete (&mods);
1617
+ string_init (&type);
1618
+ mangled = dlang_type (&type, mangled, info);
1619
+ string_delete (&type);
1396
1620
  }
1397
1621
  }
1398
1622
 
1399
- /* Check that the entire symbol was successfully demangled. */
1400
- if (kind == dlang_top_level)
1401
- {
1402
- if (mangled == NULL || *mangled != '\0')
1403
- return NULL;
1404
- }
1405
-
1406
1623
  return mangled;
1407
1624
  }
1408
1625
 
1409
1626
  /* Extract and demangle the qualified symbol in MANGLED and append it to DECL.
1627
+ SUFFIX_MODIFIERS is 1 if we are printing modifiers on this after the symbol.
1410
1628
  Returns the remaining signature on success or NULL on failure. */
1411
1629
  static const char *
1412
1630
  dlang_parse_qualified (string *decl, const char *mangled,
1413
- enum dlang_symbol_kinds kind)
1631
+ struct dlang_info *info, int suffix_modifiers)
1414
1632
  {
1415
1633
  /* Qualified names are identifiers separated by their encoded length.
1416
1634
  Nested functions also encode their argument types without specifying
1417
1635
  what they return.
1418
1636
 
1419
1637
  QualifiedName:
1420
- SymbolName
1421
- SymbolName QualifiedName
1422
- SymbolName TypeFunctionNoReturn QualifiedName
1423
- SymbolName M TypeModifiers TypeFunctionNoReturn QualifiedName
1638
+ SymbolFunctionName
1639
+ SymbolFunctionName QualifiedName
1424
1640
  ^
1641
+
1642
+ SymbolFunctionName:
1643
+ SymbolName
1644
+ SymbolName TypeFunctionNoReturn
1645
+ SymbolName M TypeFunctionNoReturn
1646
+ SymbolName M TypeModifiers TypeFunctionNoReturn
1647
+
1425
1648
  The start pointer should be at the above location.
1426
1649
  */
1427
1650
  size_t n = 0;
1428
1651
  do
1429
1652
  {
1653
+ /* Skip over anonymous symbols. */
1654
+ if (*mangled == '0')
1655
+ {
1656
+ do
1657
+ mangled++;
1658
+ while (*mangled == '0');
1659
+
1660
+ continue;
1661
+ }
1662
+
1430
1663
  if (n++)
1431
1664
  string_append (decl, ".");
1432
1665
 
1433
- /* Skip over anonymous symbols. */
1434
- while (*mangled == '0')
1435
- mangled++;
1436
-
1437
- mangled = dlang_identifier (decl, mangled, kind);
1666
+ mangled = dlang_identifier (decl, mangled, info);
1438
1667
 
1439
1668
  /* Consume the encoded arguments. However if this is not followed by the
1440
- next encoded length, then this is not a continuation of a qualified
1441
- name, in which case we backtrack and return the current unconsumed
1442
- position of the mangled decl. */
1669
+ next encoded length or mangle type, then this is not a continuation of
1670
+ a qualified name, in which case we backtrack and return the current
1671
+ unconsumed position of the mangled decl. */
1443
1672
  if (mangled && (*mangled == 'M' || dlang_call_convention_p (mangled)))
1444
1673
  {
1674
+ string mods;
1445
1675
  const char *start = mangled;
1446
1676
  int saved = string_length (decl);
1447
1677
 
1678
+ /* Save the type modifiers for appending at the end if needed. */
1679
+ string_init (&mods);
1680
+
1448
1681
  /* Skip over 'this' parameter and type modifiers. */
1449
1682
  if (*mangled == 'M')
1450
1683
  {
1451
1684
  mangled++;
1452
- mangled = dlang_type_modifiers (decl, mangled);
1685
+ mangled = dlang_type_modifiers (&mods, mangled);
1453
1686
  string_setlength (decl, saved);
1454
1687
  }
1455
1688
 
1456
- /* The rule we expect to match in the mangled string is:
1457
-
1458
- TypeFunctionNoReturn:
1459
- CallConvention FuncAttrs Arguments ArgClose
1460
-
1461
- The calling convention and function attributes are not included
1462
- in the demangled string. */
1463
- mangled = dlang_call_convention (decl, mangled);
1464
- mangled = dlang_attributes (decl, mangled);
1465
- string_setlength (decl, saved);
1689
+ mangled = dlang_function_type_noreturn (decl, NULL, NULL,
1690
+ mangled, info);
1691
+ if (suffix_modifiers)
1692
+ string_appendn (decl, mods.b, string_length (&mods));
1466
1693
 
1467
- string_append (decl, "(");
1468
- mangled = dlang_function_args (decl, mangled);
1469
- string_append (decl, ")");
1470
-
1471
- if (mangled == NULL || !ISDIGIT (*mangled))
1694
+ if (mangled == NULL || *mangled == '\0')
1472
1695
  {
1473
1696
  /* Did not match the rule we were looking for. */
1474
1697
  mangled = start;
1475
1698
  string_setlength (decl, saved);
1476
1699
  }
1700
+
1701
+ string_delete (&mods);
1477
1702
  }
1478
1703
  }
1479
- while (mangled && ISDIGIT (*mangled));
1704
+ while (mangled && dlang_symbol_name_p (mangled, info));
1480
1705
 
1481
1706
  return mangled;
1482
1707
  }
@@ -1484,9 +1709,9 @@ dlang_parse_qualified (string *decl, const char *mangled,
1484
1709
  /* Demangle the tuple from MANGLED and append it to DECL.
1485
1710
  Return the remaining string on success or NULL on failure. */
1486
1711
  static const char *
1487
- dlang_parse_tuple (string *decl, const char *mangled)
1712
+ dlang_parse_tuple (string *decl, const char *mangled, struct dlang_info *info)
1488
1713
  {
1489
- long elements;
1714
+ unsigned long elements;
1490
1715
 
1491
1716
  mangled = dlang_number (mangled, &elements);
1492
1717
  if (mangled == NULL)
@@ -1496,7 +1721,10 @@ dlang_parse_tuple (string *decl, const char *mangled)
1496
1721
 
1497
1722
  while (elements--)
1498
1723
  {
1499
- mangled = dlang_type (decl, mangled);
1724
+ mangled = dlang_type (decl, mangled, info);
1725
+ if (mangled == NULL)
1726
+ return NULL;
1727
+
1500
1728
  if (elements != 0)
1501
1729
  string_append (decl, ", ");
1502
1730
  }
@@ -1505,10 +1733,71 @@ dlang_parse_tuple (string *decl, const char *mangled)
1505
1733
  return mangled;
1506
1734
  }
1507
1735
 
1736
+ /* Demangle the template symbol parameter from MANGLED and append it to DECL.
1737
+ Return the remaining string on success or NULL on failure. */
1738
+ static const char *
1739
+ dlang_template_symbol_param (string *decl, const char *mangled,
1740
+ struct dlang_info *info)
1741
+ {
1742
+ if (strncmp (mangled, "_D", 2) == 0
1743
+ && dlang_symbol_name_p (mangled + 2, info))
1744
+ return dlang_parse_mangle (decl, mangled, info);
1745
+
1746
+ if (*mangled == 'Q')
1747
+ return dlang_parse_qualified (decl, mangled, info, 0);
1748
+
1749
+ unsigned long len;
1750
+ const char *endptr = dlang_number (mangled, &len);
1751
+
1752
+ if (endptr == NULL || len == 0)
1753
+ return NULL;
1754
+
1755
+ /* In template parameter symbols generated by the frontend up to 2.076,
1756
+ the symbol length is encoded and the first character of the mangled
1757
+ name can be a digit. This causes ambiguity issues because the digits
1758
+ of the two numbers are adjacent. */
1759
+ long psize = len;
1760
+ const char *pend;
1761
+ int saved = string_length (decl);
1762
+
1763
+ /* Work backwards until a match is found. */
1764
+ for (pend = endptr; endptr != NULL; pend--)
1765
+ {
1766
+ mangled = pend;
1767
+
1768
+ /* Reached the beginning of the pointer to the name length,
1769
+ try parsing the entire symbol. */
1770
+ if (psize == 0)
1771
+ {
1772
+ psize = len;
1773
+ pend = endptr;
1774
+ endptr = NULL;
1775
+ }
1776
+
1777
+ /* Check whether template parameter is a function with a valid
1778
+ return type or an untyped identifier. */
1779
+ if (dlang_symbol_name_p (mangled, info))
1780
+ mangled = dlang_parse_qualified (decl, mangled, info, 0);
1781
+ else if (strncmp (mangled, "_D", 2) == 0
1782
+ && dlang_symbol_name_p (mangled + 2, info))
1783
+ mangled = dlang_parse_mangle (decl, mangled, info);
1784
+
1785
+ /* Check for name length mismatch. */
1786
+ if (mangled && (endptr == NULL || (mangled - pend) == psize))
1787
+ return mangled;
1788
+
1789
+ psize /= 10;
1790
+ string_setlength (decl, saved);
1791
+ }
1792
+
1793
+ /* No match on any combinations. */
1794
+ return NULL;
1795
+ }
1796
+
1508
1797
  /* Demangle the argument list from MANGLED and append it to DECL.
1509
1798
  Return the remaining string on success or NULL on failure. */
1510
1799
  static const char *
1511
- dlang_template_args (string *decl, const char *mangled)
1800
+ dlang_template_args (string *decl, const char *mangled, struct dlang_info *info)
1512
1801
  {
1513
1802
  size_t n = 0;
1514
1803
 
@@ -1532,11 +1821,11 @@ dlang_template_args (string *decl, const char *mangled)
1532
1821
  {
1533
1822
  case 'S': /* Symbol parameter. */
1534
1823
  mangled++;
1535
- mangled = dlang_identifier (decl, mangled, dlang_template_param);
1824
+ mangled = dlang_template_symbol_param (decl, mangled, info);
1536
1825
  break;
1537
1826
  case 'T': /* Type parameter. */
1538
1827
  mangled++;
1539
- mangled = dlang_type (decl, mangled);
1828
+ mangled = dlang_type (decl, mangled, info);
1540
1829
  break;
1541
1830
  case 'V': /* Value parameter. */
1542
1831
  {
@@ -1547,18 +1836,41 @@ dlang_template_args (string *decl, const char *mangled)
1547
1836
  mangled++;
1548
1837
  type = *mangled;
1549
1838
 
1839
+ if (type == 'Q')
1840
+ {
1841
+ /* Value type is a back reference, peek at the real type. */
1842
+ const char *backref;
1843
+ if (dlang_backref (mangled, &backref, info) == NULL)
1844
+ return NULL;
1845
+
1846
+ type = *backref;
1847
+ }
1848
+
1550
1849
  /* In the few instances where the type is actually desired in
1551
1850
  the output, it should precede the value from dlang_value. */
1552
1851
  string_init (&name);
1553
- mangled = dlang_type (&name, mangled);
1852
+ mangled = dlang_type (&name, mangled, info);
1554
1853
  string_need (&name, 1);
1555
1854
  *(name.p) = '\0';
1556
1855
 
1557
- mangled = dlang_value (decl, mangled, name.b, type);
1856
+ mangled = dlang_value (decl, mangled, name.b, type, info);
1558
1857
  string_delete (&name);
1559
1858
  break;
1560
1859
  }
1860
+ case 'X': /* Externally mangled parameter. */
1861
+ {
1862
+ unsigned long len;
1863
+ const char *endptr;
1864
+
1865
+ mangled++;
1866
+ endptr = dlang_number (mangled, &len);
1867
+ if (endptr == NULL || strlen (endptr) < len)
1868
+ return NULL;
1561
1869
 
1870
+ string_appendn (decl, endptr, len);
1871
+ mangled = endptr + len;
1872
+ break;
1873
+ }
1562
1874
  default:
1563
1875
  return NULL;
1564
1876
  }
@@ -1568,12 +1880,14 @@ dlang_template_args (string *decl, const char *mangled)
1568
1880
  }
1569
1881
 
1570
1882
  /* Extract and demangle the template symbol in MANGLED, expected to
1571
- be made up of LEN characters, and append it to DECL.
1883
+ be made up of LEN characters (-1 if unknown), and append it to DECL.
1572
1884
  Returns the remaining signature on success or NULL on failure. */
1573
1885
  static const char *
1574
- dlang_parse_template (string *decl, const char *mangled, long len)
1886
+ dlang_parse_template (string *decl, const char *mangled,
1887
+ struct dlang_info *info, unsigned long len)
1575
1888
  {
1576
1889
  const char *start = mangled;
1890
+ string args;
1577
1891
 
1578
1892
  /* Template instance names have the types and values of its parameters
1579
1893
  encoded into it.
@@ -1587,26 +1901,42 @@ dlang_parse_template (string *decl, const char *mangled, long len)
1587
1901
  */
1588
1902
 
1589
1903
  /* Template symbol. */
1590
- if (!ISDIGIT (mangled[3]) || mangled[3] == '0')
1904
+ if (!dlang_symbol_name_p (mangled + 3, info) || mangled[3] == '0')
1591
1905
  return NULL;
1592
1906
 
1593
1907
  mangled += 3;
1594
1908
 
1595
1909
  /* Template identifier. */
1596
- mangled = dlang_identifier (decl, mangled, dlang_template_ident);
1910
+ mangled = dlang_identifier (decl, mangled, info);
1597
1911
 
1598
1912
  /* Template arguments. */
1913
+ string_init (&args);
1914
+ mangled = dlang_template_args (&args, mangled, info);
1915
+
1599
1916
  string_append (decl, "!(");
1600
- mangled = dlang_template_args (decl, mangled);
1917
+ string_appendn (decl, args.b, string_length (&args));
1601
1918
  string_append (decl, ")");
1602
1919
 
1920
+ string_delete (&args);
1921
+
1603
1922
  /* Check for template name length mismatch. */
1604
- if (mangled && (mangled - start) != len)
1923
+ if (len != TEMPLATE_LENGTH_UNKNOWN
1924
+ && mangled
1925
+ && (unsigned long) (mangled - start) != len)
1605
1926
  return NULL;
1606
1927
 
1607
1928
  return mangled;
1608
1929
  }
1609
1930
 
1931
+ /* Initialize the information structure we use to pass around information. */
1932
+ static void
1933
+ dlang_demangle_init_info (const char *mangled, int last_backref,
1934
+ struct dlang_info *info)
1935
+ {
1936
+ info->s = mangled;
1937
+ info->last_backref = last_backref;
1938
+ }
1939
+
1610
1940
  /* Extract and demangle the symbol in MANGLED. Returns the demangled
1611
1941
  signature on success or NULL on failure. */
1612
1942
 
@@ -1630,7 +1960,13 @@ dlang_demangle (const char *mangled, int option ATTRIBUTE_UNUSED)
1630
1960
  }
1631
1961
  else
1632
1962
  {
1633
- if (dlang_parse_mangle (&decl, mangled, dlang_top_level) == NULL)
1963
+ struct dlang_info info;
1964
+
1965
+ dlang_demangle_init_info (mangled, strlen (mangled), &info);
1966
+ mangled = dlang_parse_mangle (&decl, mangled, &info);
1967
+
1968
+ /* Check that the entire symbol was successfully demangled. */
1969
+ if (mangled == NULL || *mangled != '\0')
1634
1970
  string_delete (&decl);
1635
1971
  }
1636
1972