Recently, I was asked the question:
“Is gdc 4.3 really stable enough to be the default gdc?“
As the gdc meta-package in Debian Squeeze and Ubuntu Lucid has been updated to now depend on gdc-4.3 instead of gdc-4.1. And by just playing around with D for a few days the kind fella who asked me that discovered two bugs. So it seems to him that gdc-4.3 is far from being as mature as gdc-4.1 …
I decided to look into this by running dstress against the most recent build. For those of you who don’t know, dstress is a testing suite for D to ensure that the compiler correctly compiles (or in some cases, must not compile) a collection of about 7000+ files with 32 different compiler flag combinations without dying unintentionally, ie: via assertion or a segmentation fault.
From that huge list, I got a total of 10 internal compiler errors produced.
Here is a beautified list of internal errors that I got from the report. This first list consists of GDC back-end errors only, as they will be specific to GDC. Unlike the front-end errors, which will most likely be present in DMD and possibly LDC too.
Update: Some good development has gone into GDC since writing this post, so I’m crossing off each issue as it gets resolved.
________________________________________________________________
Internal Compiler Error 1:
Code?
public struct Color
{
double red = 0;
double green = 0;
double blue = 0;
static Color opCall()
{
Color instance;
return instance;
}
Color opAdd(real right){ return Color(); }
void opAddAssign(real right){ *this = *this + right; }
}
Error?
opAddAssign_A.d: In member function ‘opAddAssign’:
opAddAssign_A.d:13: internal compiler error: in decl_ultimate_origin, at dwarf2out.c:5139
Reproducable?
Only via:
gdc -g -O3 -c opAddAssign_A.d
gdc -g -O2 -frelease -c opAddAssign_A.d
gdc -g -Os -frelease -c opAddAssign_A.d
gdmd -g -O -inline -c opAddAssign_A.d
gdmd -g -O -release -c opAddAssign_A.d
Variants?
Not known.
Workaround?
In all cases, include the compiler option “-fno-inline” to workaround the bug.
Bug seen in gdc-4.1?
No.
________________________________________________________________
Internal Compiler Error 2:
Code?
template thunk(alias fn)
{
static void thunk(int* arg)
{
fn(arg);
}
}
int main()
{
int x = 1;
void inner(int* arg)
{
if(!(arg !is &x))
assert(0);
}
thunk!(inner)(&x);
return 0;
}
Error?
bug_tree_inline_1902_B.d: In function ‘thunk’:
bug_tree_inline_1902_B.d:5: internal compiler error: in estimate_num_insns_1, at tree-inline.c:2494
Reproducable?
Always.
Variants?
Seen also in compiler error 3 and 4, but not known just how related they are.
Workaround?
Using “void thunk” instead of “static void thunk”.
Bug seen in gdc-4.1?
Yes.
________________________________________________________________
Internal Compiler Error 3:
Code?
int main()
{
void foo() {}
void function() bar = function void()
{
foo();
};
return 0;
}
Error(s)?
bug_e2ir_299_A.d: In function ‘__funcliteral1’:
bug_e2ir_299_A.d:6: internal compiler error: in estimate_num_insns_1, at tree-inline.c:2494
Reproducable?
Always.
Variants?
Seen also in compiler error 2 and 4, but not known just how related they are.
Workaround?
Is apparently not supposed to be compilable. (comes under nocompile).
Bug seen in gdc-4.1?
Yes.
________________________________________________________________
Internal Compiler Error 4:
Code?
struct A (alias F)
{
int f() { return F(); }
}
void main()
{
int f() { return 0; }
A!(f) a;
}
Error?
template_struct_01_A.d: In member function ‘f’:
template_struct_01_A.d:5: internal compiler error: in estimate_num_insns_1, at tree-inline.c:2494
Reproducable?
Always.
Variants?
Seen also in compiler error 2 and 3, but not known just how related they are.
Workaround?
None.
Bug seen in gdc-4.1?
Yes.
________________________________________________________________
Internal Compiler Error 5:
Code?
class Outer
{
this()
{
Inner i = new Inner();
}
class Inner
{
Strct str;
}
}
struct Strct
{
int i;
}
int main()
{
Outer o = new Outer();
return 0;
}
Error?
forward_reference_17_A.d: In member function ‘_ctor’:
forward_reference_17_A.d:5: internal compiler error: Segmentation fault
Reproducable?
Always
Variants?
Not known.
Workaround?
Declare the struct before the class.
Bug seen in gdc-4.1?
Yes
________________________________________________________________
Internal Compiler Error 6:
Code?
bool nextis(void delegate() dgpositive = {})
{
return true;
}
bool looping(lazy bool condition)
{
return true;
}
int main()
{
looping(nextis());
return 0;
}
Error?
lazy_02_A.d: In member function ‘__dgliteral2’:
lazy_02_A.d:2: internal compiler error: in getFrameForSymbol, at d/d-codegen.cc:2541
Reproducable?
Always.
Variants?
Anything that uses the following as an argument.
void delegate() foo = {}
Workaround?
None.
Bug seen in gdc-4.1?
Yes.
________________________________________________________________
Internal Compiler Error 7:
Code?
int status;
template T(alias a)
{
int dummy;
}
class C
{
mixin T!(
() {
status++;
}
) mixed;
}
int main()
{
C c = new C();
c.mixed.a();
if(status != 1)
{
assert(0);
}
return 0;
}
Error?
mixin_23_A.d:11: Error: delegate mixin_23_A.C.__dgliteral1 literals cannot be class members
cc1d: internal compiler error: Segmentation fault
Reproducable?
Always.
Variants?
Also seen when using:
mixin T!( delegate() { status++; } ) mixed;
And:
mixin T!( { status++; } ) mixed;
Workaround?
Using function() works around the problem, but probably not correct due to semantic differences.
mixin T!( function(){ status++; } ) mixed;
Bug seen in gdc-4.1?
No.
________________________________________________________________
In this second list are DMD frontend compiler errors, they aren’t necessarily the fault of GDC’s, and they may well be present in LDC too.
Internal Compiler Error 8:
Code?
char[] testHelper(A ...)()
{
char[] result;
foreach(t; a)
{
result ~= "int " ~ t ~ ";\n";
}
return result;
}
int main()
{
mixin( testHelper!( "hello", "world" )() );
return 0;
}
Error?
cc1d: ../../src/gcc/d/dmd/template.c:811: MATCH TemplateDeclaration::deduceFunctionTemplateMatch(Loc, Objects*, Expression*, Expressions*, Objects*): Assertion `i dim' failed.
cc1d: internal compiler error: Aborted
Reproducable?
Always.
Variants?
Not known.
Workaround?
Code is not supposed to be compilable. (comes under nocompile).
Bug seen in gdc-4.1?
No.
________________________________________________________________
Internal Compiler Error 9:
Code?
void[10] array;
Error?
Error: integral constant must be scalar type, not void
cc1d: ../../src/gcc/d/dmd/todt.c:85: dt_t* createTsarrayDt(dt_t*, Type*): Assertion `tsa->size(0) % eoa_size == 0' failed.
cc1d: internal compiler error: Aborted
Reproducable?
Always.
Variants?
Not known.
Workaround?
Code is not supposed to be compilable. (comes under nocompile).
Bug seen in gdc-4.1?
Yes.
________________________________________________________________
Internal Compiler Error 10:
Code?
int main()
{
auto arr = [4:"vier", 0:"null", 2:"zwei"];
if(3 != arr.length)
{
assert(0);
}
char[][] master_e = ["vier", "null", "zwei"];
int[] master_i = [4, 0, 2];
foreach(index, element; arr)
{
bool found = false;
foreach(pos, i; master_i)
{
if(index == i && element == master_e[pos])
{
master_i = master_i[0 .. pos] ~ master_i[pos+1 .. $];
master_e = master_e[0 .. pos] ~ master_e[pos+1 .. $];
found = true;
break;
}
}
if(!found)
{
assert(0);
}
}
if(master_i.length)
{
assert(0);
}
return 0;
}
Error?
associative_array_23_B.d:3: Error: cannot infer type from this array initializer
cc1d: ../../src/gcc/d/dmd/init.c:437: virtual Expression* ArrayInitializer::toExpression(): Assertion `j < edim' failed.
cc1d: internal compiler error: Aborted
Reproducable?
Always.
Variants?
Not known.
Workaround?
None.
Bug seen in gdc-4.1?
No.
________________________________________________________________
So, as far as the dstress testing goes, there are currently 4 regressions – 2 of which are not the fault of gdc – and 6 inherited bugs in gdc-4.3 when compared to gdc-4.1.
So, back to your original question, is gdc 4.3 really stable enough to be the default gdc? Thanks to your help in identifying two underlying problems in the Debianised version, yes, I believe it is!
Despite some outstanding quirks, and the odd ICE or two in this post that would be cool to plumb down and fix. I think we are heading in for a strong release – if and when the GDC upstream developers ever get round to it. In the meantime, I will continue maintaining the Debian and Ubuntu packages, and will love to hear more of your dedicated support and patience in testing.
Got any other show-stopping bugs? Please report! :-)