Skip to content

Commit

Permalink
Merge pull request #3069 from 9rnsr/fix11863
Browse files Browse the repository at this point in the history
[REG2.064] Issue 11863 - std.conv.to!string(int/uint, radix) returns incorrect string
  • Loading branch information
Don Clugston committed Jan 7, 2014
2 parents 044717c + 4c846a2 commit 6090f45
Show file tree
Hide file tree
Showing 5 changed files with 140 additions and 24 deletions.
40 changes: 16 additions & 24 deletions src/glue.c
Expand Up @@ -647,6 +647,20 @@ void FuncDeclaration::toObjFile(int multiobj)
}
}

if (isNested())
{
/* The enclosing function must have its code generated first,
* so defer this code generation until ancestors are completed.
*/
FuncDeclaration *fd = toAliasFunc();
FuncDeclaration *fdp = fd->toParent2()->isFuncDeclaration();
if (fdp && fdp->semanticRun < PASSobj)
{
fdp->deferred.push(fd);
return;
}
}

// start code generation
semanticRun = PASSobj;

Expand Down Expand Up @@ -696,31 +710,9 @@ void FuncDeclaration::toObjFile(int multiobj)

if (isNested())
{

// if (!(config.flags3 & CFG3pic))
// s->Sclass = SCstatic;
//if (!(config.flags3 & CFG3pic))
// s->Sclass = SCstatic;
f->Fflags3 |= Fnested;

/* The enclosing function must have its code generated first,
* so we know things like where its local symbols are stored.
*/
FuncDeclaration *fdp = toAliasFunc()->toParent2()->isFuncDeclaration();
// Bug 8016 - only include the function if it is a template instance
Dsymbol * owner = NULL;
if (fdp)
{
//printf("fdp = %s %s\n", fdp->kind(), fdp->toChars());
owner = fdp->toParent2();
if (owner && fdp->semanticRun == PASSsemantic3done &&
!fdp->isUnitTestDeclaration())
{
/* Can't do unittest's out of order, they are order dependent in that their
* execution is done in lexical order, and some modules (std.datetime *cough*
* *cough*) rely on this.
*/
fdp->toObjFile(multiobj);
}
}
}
else
{
Expand Down
11 changes: 11 additions & 0 deletions test/runnable/imports/std11863bitmanip.d
@@ -0,0 +1,11 @@
module imports.std11863bitmanip;

import imports.std11863format : FormatSpec;

struct BitArray
{
void toString(scope void delegate(const(char)[]) sink,
FormatSpec!char fmt) const
{
}
}
90 changes: 90 additions & 0 deletions test/runnable/imports/std11863conv.d
@@ -0,0 +1,90 @@
module imports.std11863conv;

import imports.std11863format;

template to(T)
{
T to(A...)(A args)
{
return toImpl!T(args);
}
}

T toImpl(T, S)(S value)
{
static if (is(S == int) && is(T == string))
{
// other integral-to-string conversions with default radix
return toImpl!(T, S)(value, 10);
}
else
static assert(0);
}

@trusted pure T toImpl(T, S)(S value, uint radix/*, LetterCase letterCase = LetterCase.upper*/)
{
static assert(is(S == int) && is(T == string));

alias EEType = char/*Unqual!(typeof(T.init[0]))*/;

T toStringRadixConvert(size_t bufLen, uint radix = 0, bool neg = false)(uint runtimeRadix = 0)
{
static if (neg)
ulong div = void, mValue = cast(uint)(-value);
else
uint/*Unsigned!(Unqual!S)*/ div = void, mValue = cast(uint)(value);

size_t index = bufLen;
EEType[bufLen] buffer = void;
char baseChar = /*letterCase == LetterCase.lower ? 'a' : */'A';
char mod = void;

do
{
static if (radix == 0)
{
div = cast(S)(mValue / runtimeRadix );
mod = cast(ubyte)(mValue % runtimeRadix);
mod += mod < 10 ? '0' : baseChar - 10;
}
else static if (radix > 10)
{
div = cast(S)(mValue / radix );
mod = cast(ubyte)(mValue % radix);
mod += mod < 10 ? '0' : baseChar - 10;
}
else
{
div = cast(S)(mValue / radix);
mod = mValue % radix + '0';
}
buffer[--index] = cast(char)mod;
mValue = div;
} while (mValue);

static if (neg)
{
buffer[--index] = '-';
}
return cast(T)buffer[index .. $].dup;
}

//enforce(radix >= 2 && radix <= 36, new ConvException("Radix error"));

switch(radix)
{
case 10:
if (value < 0)
return toStringRadixConvert!(S.sizeof * 3 + 1, 10, true)();
else
return toStringRadixConvert!(S.sizeof * 3, 10)();
//case 16:
// return toStringRadixConvert!(S.sizeof * 2, 16)();
//case 2:
// return toStringRadixConvert!(S.sizeof * 8, 2)();
//case 8:
// return toStringRadixConvert!(S.sizeof * 3, 8)();
default:
assert(0);//return toStringRadixConvert!(S.sizeof * 6)(radix);
}
}
13 changes: 13 additions & 0 deletions test/runnable/imports/std11863format.d
@@ -0,0 +1,13 @@
module imports.std11863format;

import imports.std11863bitmanip;
import imports.std11863conv;

struct FormatSpec(Char)
{
string toString()
{
// text(width)
return to!string(1); // instantiate toImpl!(string, int)
}
}
10 changes: 10 additions & 0 deletions test/runnable/test11863.d
@@ -0,0 +1,10 @@
// COMPILE_SEPARATELY
// EXTRA_SOURCES: imports/std11863conv.d

import imports.std11863conv;

void main()
{
auto s = to!string(15, 10);
assert(s == "15"); // failure
}

0 comments on commit 6090f45

Please sign in to comment.