Bug 4323 – std.demangle incorrectly handles template floating point numbers
Status
RESOLVED
Resolution
FIXED
Severity
normal
Priority
P2
Component
druntime
Product
D
Version
D1 (retired)
Platform
Other
OS
Mac OS X
Creation time
2010-06-15T11:38:00Z
Last change time
2014-06-06T22:34:28Z
Keywords
patch, wrong-code
Assigned to
nobody
Creator
doob
Comments
Comment #0 by doob — 2010-06-15T11:38:04Z
According to the ABI spec the mangled form of template floating point numbers looks like this:
Value:
e HexFloat
HexFloat:
N HexDigits P Exponent
HexDigits P Exponent
But std.demnalge doesn't seem to handle the exponent, it doesn't handle the 'P'. The unittests that test this are also incorrect. The first one looks like this:
mangled form: _D4test58__T9factorialVde67666666666666860140VG5aa5_68656c6c6fVPvnZ9factorialf
demangled form:
float test.factorial!(double 4.2, char[5] \"hello\"c, void* null).factorial
As far as I can see the mangled form doesn't follow the spec or what dmd produces.
module test;
float factorial (T...) ()
{
return float.init;
}
void main ()
{
factorial!(4.2, "hello", null);
}
Compiling the above code and running the "nm" command on the resulting binary shows that "factorial" with the above given values is mangled as: _D4test57__T9factorialVde8666666666666667PN1VAyaa5_68656c6c6fVPvnZ9factorialFZf
After all the 6s the is a 7 and then a P. In the std.demangle unittest the P is missing, also at the end of the mangled name is a Z which is missing in the unittest.
Comment #1 by kennytm — 2011-05-08T02:14:35Z
With core.demangle it now resolves _D4test57__T9factorialVde8666666666666667PN1VAyaa5_68656c6c6fVPvnZ9factorialFZf into:
float test.factorial!(8.400000, "hello", null).factorial()
The only problem is the floating point number is 2 times bigger than the expected.
Comment #2 by kennytm — 2011-05-08T02:45:28Z
The demangler forgot to put the 'p', making the exponent part totally ignored. Also, using the '%f' format makes floating point number that is extremely small becomes 0.00000. I think '%g' is more suitable.
diff --git a/src/core/demangle.d b/src/core/demangle.d
index 6d37633..b2ab00d 100644
--- a/src/core/demangle.d
+++ b/src/core/demangle.d
@@ -368,6 +368,7 @@ private struct Demangle
next();
}
match( 'P' );
+ tbuf[tlen++] = 'p';
if( 'N' == tok() )
{
tbuf[tlen++] = '-';
@@ -386,7 +387,7 @@ private struct Demangle
tbuf[tlen] = 0;
debug(info) printf( "got (%s)\n", tbuf.ptr );
val = strtold( tbuf.ptr, null );
- tlen = snprintf( tbuf.ptr, tbuf.length, "%Lf", val );
+ tlen = snprintf( tbuf.ptr, tbuf.length, "%Lg", val );
debug(info) printf( "converted (%.*s)\n", cast(int) tlen, tbuf.ptr );
put( tbuf[0 .. tlen] );
}