@@ -69,7 +69,7 @@ private struct Demangle
6969 size_t pos = 0 ;
7070 size_t len = 0 ;
7171 AddType addType = AddType.yes;
72-
72+ bool mute = false ;
7373
7474 static class ParseException : Exception
7575 {
@@ -173,7 +173,7 @@ private struct Demangle
173173 dst[b] = t;
174174 }
175175
176- if ( val.length )
176+ if ( val.length && ! mute )
177177 {
178178 assert ( contains( dst[0 .. len], val ) );
179179 debug (info) printf( " shifting (%.*s)\n " , cast (int ) val.length, val.ptr );
@@ -193,7 +193,7 @@ private struct Demangle
193193
194194 char [] append ( const (char )[] val )
195195 {
196- if ( val.length )
196+ if ( val.length && ! mute )
197197 {
198198 if ( ! dst.length )
199199 dst.length = minBufSize;
@@ -296,6 +296,13 @@ private struct Demangle
296296 return char .init;
297297 }
298298
299+ char peek ( size_t n )
300+ {
301+ if ( pos + n < buf.length )
302+ return buf[pos + n];
303+ return char .init;
304+ }
305+
299306
300307 void test ( char val )
301308 {
@@ -334,18 +341,34 @@ private struct Demangle
334341 popFront();
335342 }
336343
344+ bool isSymbolNameFront ()
345+ {
346+ char val = front;
347+ if ( isDigit( val ) || val == ' _' )
348+ return true ;
349+ if ( val != ' Q' )
350+ return false ;
351+
352+ // check the back reference encoding after 'Q'
353+ val = peek( 1 );
354+ for ( int n = 2 ; isDigit( val ); n++ )
355+ val = peek( n );
356+ return ( val >= ' A' && val <= ' J' ) || ( val >= ' K' && val <= ' T' ); // length or symbol ref
357+ }
337358
338359 // ////////////////////////////////////////////////////////////////////////
339360 // Parsing Implementation
340361 // ////////////////////////////////////////////////////////////////////////
341362
342363
343364 /*
365+ if term != 0, LastDigit == term + digit-value
366+
344367 Number:
345- Digit
368+ LastDigit
346369 Digit Number
347370 */
348- const (char )[] sliceNumber ()
371+ const (char )[] sliceNumber (char term = 0 )( )
349372 {
350373 debug (trace) printf( " sliceNumber+\n " );
351374 debug (trace) scope (success) printf( " sliceNumber-\n " );
@@ -358,33 +381,45 @@ private struct Demangle
358381 if (t >= ' 0' && t <= ' 9' )
359382 popFront();
360383 else
384+ {
385+ static if ( term )
386+ {
387+ if (t >= term && t <= term + 9 )
388+ popFront();
389+ else
390+ error();
391+ }
361392 return buf[beg .. pos];
393+ }
362394 }
363395 }
364396
365397
366- size_t decodeNumber ()
398+ size_t decodeNumber (char term = 0 )( )
367399 {
368400 debug (trace) printf( " decodeNumber+\n " );
369401 debug (trace) scope (success) printf( " decodeNumber-\n " );
370402
371- return decodeNumber ( sliceNumber() );
403+ return decodeNumber! term ( sliceNumber! term () );
372404 }
373405
374406
375- size_t decodeNumber ( const (char )[] num )
407+ size_t decodeNumber (char term = 0 )( const (char )[] num )
376408 {
377409 debug (trace) printf( " decodeNumber+\n " );
378410 debug (trace) scope (success) printf( " decodeNumber-\n " );
379411
380412 size_t val = 0 ;
381413
382- foreach ( c; num )
414+ foreach ( char c; num )
383415 {
384416 import core.checkedint : mulu, addu;
385417
386418 bool overflow = false ;
387419 val = mulu(val, 10 , overflow);
420+ static if ( term )
421+ if ( c >= term )
422+ c += ' 0' - term;
388423 val = addu(val, c - ' 0' , overflow);
389424 if (overflow)
390425 error();
@@ -492,20 +527,53 @@ private struct Demangle
492527 debug (trace) printf( " parseLName+\n " );
493528 debug (trace) scope (success) printf( " parseLName-\n " );
494529
495- auto n = decodeNumber();
496-
497- if ( ! n || n > buf.length || n > buf.length - pos )
498- error( " LName must be at least 1 character" );
499- if ( ' _' != front && ! isAlpha( front ) )
500- error( " Invalid character in LName" );
501- foreach (char e; buf[pos + 1 .. pos + n] )
530+ if ( front == ' Q' )
531+ {
532+ // back reference to LName
533+ auto refPos = pos;
534+ popFront();
535+ char c = front;
536+ for ( int n = 1 ; isDigit( c ); n++ )
537+ c = peek( n );
538+ bool hasDepth = ( c >= ' K' && c <= ' T' );
539+ size_t depth = 0 ;
540+ if ( hasDepth )
541+ depth = decodeNumber! ' K' ();
542+ else if ( c < ' A' || c > ' J' )
543+ error( " invalid LName back reference" );
544+
545+ size_t n = decodeNumber! ' A' ();
546+ if ( ! mute )
547+ {
548+ auto savePos = pos;
549+ scope (exit) pos = savePos;
550+ pos = refPos - n;
551+ for ( size_t d = 0 ; d < depth; d++ )
552+ {
553+ parseSymbolName();
554+ parseFunctionType( true );
555+ put( ' .' );
556+ }
557+ parseSymbolName();
558+ if (hasDepth)
559+ parseFunctionType( true );
560+ }
561+ }
562+ else
502563 {
503- if ( ' _' != e && ! isAlpha( e ) && ! isDigit( e ) )
564+ auto n = decodeNumber();
565+ if ( ! n || n > buf.length || n > buf.length - pos )
566+ error( " LName must be at least 1 character" );
567+ if ( ' _' != front && ! isAlpha( front ) )
504568 error( " Invalid character in LName" );
569+ foreach (char e; buf[pos + 1 .. pos + n] )
570+ {
571+ if ( ' _' != e && ! isAlpha( e ) && ! isDigit( e ) )
572+ error( " Invalid character in LName" );
573+ }
574+ put( buf[pos .. pos + n] );
575+ pos += n;
505576 }
506-
507- put( buf[pos .. pos + n] );
508- pos += n;
509577 }
510578
511579
@@ -715,6 +783,17 @@ private struct Demangle
715783
716784 switch ( t )
717785 {
786+ case ' Q' : // Type back reference
787+ auto refPos = pos;
788+ popFront();
789+ auto n = decodeNumber! ' a' ();
790+ if ( mute )
791+ return null ;
792+ auto savePos = pos;
793+ scope (exit) pos = savePos;
794+ pos = refPos - n;
795+ auto ret = parseType();
796+ return ret;
718797 case ' O' : // Shared (O Type)
719798 popFront();
720799 put( " shared(" );
@@ -1554,13 +1633,56 @@ private struct Demangle
15541633 len = t;
15551634 }
15561635 }
1636+ goto case ;
1637+ case ' Q' :
15571638 parseLName();
15581639 return ;
15591640 default :
15601641 error();
15611642 }
15621643 }
15631644
1645+ void parseFunctionType ( bool muteReturnType )
1646+ {
1647+ if ( ' M' == front )
1648+ {
1649+ // do not emit "needs this"
1650+ popFront();
1651+ }
1652+ if ( isCallConvention( front ) )
1653+ {
1654+ // try to demangle a function, in case we are pointing to some function local
1655+ auto prevpos = pos;
1656+ auto prevlen = len;
1657+
1658+ // we don't want calling convention and attributes in the qualified name
1659+ parseCallConvention();
1660+ parseFuncAttr();
1661+ len = prevlen;
1662+
1663+ put( ' (' );
1664+ parseFuncArguments();
1665+ put( ' )' );
1666+ if ( ! isSymbolNameFront() ) // voldemort types don't have a return type on the function
1667+ {
1668+ auto funclen = len;
1669+
1670+ bool prevMute = mute;
1671+ scope (exit) mute = prevMute;
1672+ mute = muteReturnType;
1673+ parseType();
1674+
1675+ if ( ! muteReturnType && ! isSymbolNameFront() )
1676+ {
1677+ // not part of a qualified name, so back up
1678+ pos = prevpos;
1679+ len = prevlen;
1680+ }
1681+ else
1682+ len = funclen; // remove return type from qualified name
1683+ }
1684+ }
1685+ }
15641686
15651687 /*
15661688 QualifiedName:
@@ -1579,37 +1701,8 @@ private struct Demangle
15791701 if ( n++ )
15801702 put( ' .' );
15811703 parseSymbolName();
1582-
1583- if ( isCallConvention( front ) )
1584- {
1585- // try to demangle a function, in case we are pointing to some function local
1586- auto prevpos = pos;
1587- auto prevlen = len;
1588-
1589- // we don't want calling convention and attributes in the qualified name
1590- parseCallConvention();
1591- parseFuncAttr();
1592- len = prevlen;
1593-
1594- put( ' (' );
1595- parseFuncArguments();
1596- put( ' )' );
1597- if ( ! isDigit( front ) && front != ' _' ) // voldemort types don't have a return type on the function
1598- {
1599- auto funclen = len;
1600- parseType();
1601-
1602- if ( ! isDigit( front ) && front != ' _' )
1603- {
1604- // not part of a qualified name, so back up
1605- pos = prevpos;
1606- len = prevlen;
1607- }
1608- else
1609- len = funclen; // remove return type from qualified name
1610- }
1611- }
1612- } while ( isDigit ( front ) || front == ' _' );
1704+ parseFunctionType( false );
1705+ } while ( isSymbolNameFront () );
16131706 return dst[beg .. len];
16141707 }
16151708
0 commit comments