@@ -175,6 +175,7 @@ struct DWARFTypePrinter {
175
175
OS << " )]" ;
176
176
}
177
177
}
178
+ EndedWithTemplate = false ;
178
179
}
179
180
180
181
DWARFDie skipQualifiers (DWARFDie D) {
@@ -197,9 +198,12 @@ struct DWARFTypePrinter {
197
198
OS << ' (' ;
198
199
OS << Ptr;
199
200
Word = false ;
201
+ EndedWithTemplate = false ;
200
202
}
201
203
202
- DWARFDie appendUnqualifiedNameBefore (DWARFDie D) {
204
+ DWARFDie
205
+ appendUnqualifiedNameBefore (DWARFDie D,
206
+ std::string *OriginalFullName = nullptr ) {
203
207
Word = true ;
204
208
if (!D) {
205
209
OS << " void" ;
@@ -268,15 +272,54 @@ struct DWARFTypePrinter {
268
272
EndedWithTemplate = false ;
269
273
break ;
270
274
}
271
- default :
275
+ /*
276
+ case DW_TAG_structure_type:
277
+ case DW_TAG_class_type:
278
+ case DW_TAG_enumeration_type:
279
+ case DW_TAG_base_type:
280
+ */
281
+ default : {
272
282
const char *NamePtr = dwarf::toString (D.find (DW_AT_name), nullptr );
273
283
if (!NamePtr) {
274
- appendTypeTagName (D.getTag ());
275
- break ;
284
+ StringRef TagStr = TagString (D.getTag ());
285
+ static constexpr StringRef Prefix = " DW_TAG_" ;
286
+ static constexpr StringRef Suffix = " _type" ;
287
+ if (TagStr.startswith (Prefix) && TagStr.endswith (Suffix))
288
+ OS << TagStr.substr (Prefix.size (),
289
+ TagStr.size () - (Prefix.size () + Suffix.size ()))
290
+ << " " ;
291
+ return Inner;
292
+ }
293
+ Word = true ;
294
+ StringRef Name = NamePtr;
295
+ static constexpr StringRef MangledPrefix = " _STN" ;
296
+ if (Name.startswith (MangledPrefix)) {
297
+ Name = Name.drop_front (MangledPrefix.size ());
298
+ auto Separator = Name.find (' |' );
299
+ assert (Separator != StringRef::npos);
300
+ StringRef BaseName = Name.substr (0 , Separator);
301
+ StringRef TemplateArgs = Name.substr (Separator + 1 );
302
+ if (OriginalFullName)
303
+ *OriginalFullName = (BaseName + TemplateArgs).str ();
304
+ Name = BaseName;
305
+ } else
306
+ EndedWithTemplate = Name.endswith (" >" );
307
+ OS << Name;
308
+ // FIXME: This needs to be a bit more narrow, it would fail to
309
+ // reconstitute a non-operator overload that is a template, like
310
+ // "operator_thing<int>"
311
+ if (!Name.endswith (" >" ) && !Name.startswith (" operator" )) {
312
+ if (appendTemplateParameters (D)) {
313
+ if (EndedWithTemplate)
314
+ OS << ' ' ;
315
+ OS << ' >' ;
316
+ EndedWithTemplate = true ;
317
+ Word = true ;
318
+ }
276
319
}
277
- OS << NamePtr;
278
320
break ;
279
321
}
322
+ }
280
323
return Inner;
281
324
}
282
325
@@ -310,6 +353,13 @@ struct DWARFTypePrinter {
310
353
DW_TAG_ptr_to_member_type);
311
354
break ;
312
355
}
356
+ /*
357
+ case DW_TAG_structure_type:
358
+ case DW_TAG_class_type:
359
+ case DW_TAG_enumeration_type:
360
+ case DW_TAG_base_type:
361
+ case DW_TAG_namespace:
362
+ */
313
363
default :
314
364
break ;
315
365
}
@@ -325,6 +375,170 @@ struct DWARFTypePrinter {
325
375
appendScopes (D.getParent ());
326
376
return appendUnqualifiedNameBefore (D);
327
377
}
378
+ bool appendTemplateParameters (DWARFDie D, bool *FirstParameter = nullptr ) {
379
+ bool FirstParameterValue = true ;
380
+ bool IsTemplate = false ;
381
+ if (!FirstParameter)
382
+ FirstParameter = &FirstParameterValue;
383
+ for (const DWARFDie &C : D) {
384
+ auto Sep = [&] {
385
+ if (*FirstParameter)
386
+ OS << ' <' ;
387
+ else
388
+ OS << " , " ;
389
+ IsTemplate = true ;
390
+ EndedWithTemplate = false ;
391
+ *FirstParameter = false ;
392
+ };
393
+ if (C.getTag () == dwarf::DW_TAG_GNU_template_parameter_pack) {
394
+ IsTemplate = true ;
395
+ appendTemplateParameters (C, FirstParameter);
396
+ }
397
+ if (C.getTag () == dwarf::DW_TAG_template_value_parameter) {
398
+ DWARFDie T = C.getAttributeValueAsReferencedDie (DW_AT_type);
399
+ Sep ();
400
+ if (T.getTag () == DW_TAG_enumeration_type) {
401
+ auto V = C.find (DW_AT_const_value);
402
+ bool FoundEnumerator = false ;
403
+ for (const DWARFDie &Enumerator : T) {
404
+ auto EV = Enumerator.find (DW_AT_const_value);
405
+ if (V && EV &&
406
+ V->getAsSignedConstant () == EV->getAsSignedConstant ()) {
407
+ if (T.find (DW_AT_enum_class)) {
408
+ appendQualifiedName (T);
409
+ OS << " ::" ;
410
+ } else
411
+ appendScopes (T.getParent ());
412
+ OS << Enumerator.getShortName ();
413
+ FoundEnumerator = true ;
414
+ break ;
415
+ }
416
+ }
417
+ if (FoundEnumerator)
418
+ continue ;
419
+ OS << ' (' ;
420
+ appendQualifiedName (T);
421
+ OS << ' )' ;
422
+ OS << to_string (*V->getAsSignedConstant ());
423
+ continue ;
424
+ }
425
+ // /Maybe/ we could do pointer type parameters, looking for the
426
+ // symbol in the ELF symbol table to get back to the variable...
427
+ // but probably not worth it.
428
+ if (T.getTag () == DW_TAG_pointer_type)
429
+ continue ;
430
+ const char *RawName = dwarf::toString (T.find (DW_AT_name), nullptr );
431
+ assert (RawName);
432
+ StringRef Name = RawName;
433
+ auto V = C.find (DW_AT_const_value);
434
+ bool IsQualifiedChar = false ;
435
+ if (Name == " bool" ) {
436
+ OS << (*V->getAsUnsignedConstant () ? " true" : " false" );
437
+ } else if (Name == " short" ) {
438
+ OS << " (short)" ;
439
+ OS << to_string (*V->getAsSignedConstant ());
440
+ } else if (Name == " unsigned short" ) {
441
+ OS << " (unsigned short)" ;
442
+ OS << to_string (*V->getAsSignedConstant ());
443
+ } else if (Name == " int" )
444
+ OS << to_string (*V->getAsSignedConstant ());
445
+ else if (Name == " long" ) {
446
+ OS << to_string (*V->getAsSignedConstant ());
447
+ OS << " L" ;
448
+ } else if (Name == " long long" ) {
449
+ OS << to_string (*V->getAsSignedConstant ());
450
+ OS << " LL" ;
451
+ } else if (Name == " unsigned int" ) {
452
+ OS << to_string (*V->getAsUnsignedConstant ());
453
+ OS << " U" ;
454
+ } else if (Name == " unsigned long" ) {
455
+ OS << to_string (*V->getAsUnsignedConstant ());
456
+ OS << " UL" ;
457
+ } else if (Name == " unsigned long long" ) {
458
+ OS << to_string (*V->getAsUnsignedConstant ());
459
+ OS << " ULL" ;
460
+ } else if (Name == " char" ||
461
+ (IsQualifiedChar =
462
+ (Name == " unsigned char" || Name == " signed char" ))) {
463
+ // FIXME: check T's DW_AT_type to see if it's signed or not (since
464
+ // char signedness is implementation defined).
465
+ auto Val = *V->getAsSignedConstant ();
466
+ // Copied/hacked up from Clang's CharacterLiteral::print - incomplete
467
+ // (doesn't actually support different character types/widths, sign
468
+ // handling's not done, and doesn't correctly test if a character is
469
+ // printable or needs to use a numeric escape sequence instead)
470
+ if (IsQualifiedChar) {
471
+ OS << ' (' ;
472
+ OS << Name;
473
+ OS << ' )' ;
474
+ }
475
+ switch (Val) {
476
+ case ' \\ ' :
477
+ OS << " '\\\\ '" ;
478
+ break ;
479
+ case ' \' ' :
480
+ OS << " '\\ ''" ;
481
+ break ;
482
+ case ' \a ' :
483
+ // TODO: K&R: the meaning of '\\a' is different in traditional C
484
+ OS << " '\\ a'" ;
485
+ break ;
486
+ case ' \b ' :
487
+ OS << " '\\ b'" ;
488
+ break ;
489
+ case ' \f ' :
490
+ OS << " '\\ f'" ;
491
+ break ;
492
+ case ' \n ' :
493
+ OS << " '\\ n'" ;
494
+ break ;
495
+ case ' \r ' :
496
+ OS << " '\\ r'" ;
497
+ break ;
498
+ case ' \t ' :
499
+ OS << " '\\ t'" ;
500
+ break ;
501
+ case ' \v ' :
502
+ OS << " '\\ v'" ;
503
+ break ;
504
+ default :
505
+ if ((Val & ~0xFFu ) == ~0xFFu )
506
+ Val &= 0xFFu ;
507
+ if (Val < 127 && Val >= 32 ) {
508
+ OS << " '" ;
509
+ OS << (char )Val;
510
+ OS << " '" ;
511
+ } else if (Val < 256 )
512
+ OS << to_string (llvm::format (" '\\ x%02x'" , Val));
513
+ else if (Val <= 0xFFFF )
514
+ OS << to_string (llvm::format (" '\\ u%04x'" , Val));
515
+ else
516
+ OS << to_string (llvm::format (" '\\ U%08x'" , Val));
517
+ }
518
+ }
519
+ continue ;
520
+ }
521
+ if (C.getTag () == dwarf::DW_TAG_GNU_template_template_param) {
522
+ const char *RawName =
523
+ dwarf::toString (C.find (DW_AT_GNU_template_name), nullptr );
524
+ assert (RawName);
525
+ StringRef Name = RawName;
526
+ Sep ();
527
+ OS << Name;
528
+ continue ;
529
+ }
530
+ if (C.getTag () != dwarf::DW_TAG_template_type_parameter)
531
+ continue ;
532
+ auto TypeAttr = C.find (DW_AT_type);
533
+ Sep ();
534
+ appendQualifiedName (TypeAttr
535
+ ? C.getAttributeValueAsReferencedDie (*TypeAttr)
536
+ : DWARFDie ());
537
+ }
538
+ if (IsTemplate && *FirstParameter && FirstParameter == &FirstParameterValue)
539
+ OS << ' <' ;
540
+ return IsTemplate;
541
+ }
328
542
void decomposeConstVolatile (DWARFDie &N, DWARFDie &T, DWARFDie &C,
329
543
DWARFDie &V) {
330
544
(N.getTag () == DW_TAG_const_type ? C : V) = N;
@@ -386,10 +600,11 @@ struct DWARFTypePrinter {
386
600
}
387
601
388
602
// / Recursively append the DIE type name when applicable.
389
- void appendUnqualifiedName (const DWARFDie &D) {
603
+ void appendUnqualifiedName (DWARFDie D,
604
+ std::string *OriginalFullName = nullptr ) {
390
605
// FIXME: We should have pretty printers per language. Currently we print
391
606
// everything as if it was C++ and fall back to the TAG type name.
392
- DWARFDie Inner = appendUnqualifiedNameBefore (D);
607
+ DWARFDie Inner = appendUnqualifiedNameBefore (D, OriginalFullName );
393
608
appendUnqualifiedNameAfter (D, Inner);
394
609
}
395
610
@@ -586,6 +801,14 @@ static void dumpAttribute(raw_ostream &OS, const DWARFDie &Die,
586
801
OS << " )\n " ;
587
802
}
588
803
804
+ void DWARFDie::getFullName (raw_string_ostream &OS,
805
+ std::string *OriginalFullName) const {
806
+ const char *NamePtr = getShortName ();
807
+ if (!NamePtr)
808
+ return ;
809
+ DWARFTypePrinter (OS).appendUnqualifiedName (*this , OriginalFullName);
810
+ }
811
+
589
812
bool DWARFDie::isSubprogramDIE () const { return getTag () == DW_TAG_subprogram; }
590
813
591
814
bool DWARFDie::isSubroutineDIE () const {
0 commit comments