Example code:
struct A {}
void foo(bool cond){}
void main()
{
A a;
int i;
assert(a); // type A does not have a boolean value
assert(i || a); // type A does not have a boolean value
assert(0 || a); // OK
if(a) {} // type A does not have a boolean value
if(i || a) {} // type A does not have a boolean value
if(0 || a) {} // type A does not have a boolean value
foo(a); // cannot implicitly convert type A to bool
foo(i || a); // OK
foo(0 || a); // OK
}
The three examples that pass really should be errors.
Regards
Comment #1 by ibuclaw — 2011-03-15T17:53:51Z
Note, this is also the same issue for static arrays and unions.
int[1] arr;
assert(arr); // type int[1u] does not have a boolean value
assert(0 || arr); // OK
union B {}
B b;
assert(b); // type B does not have a boolean value
assert(0 || b); // OK
Regards
Comment #2 by ibuclaw — 2011-04-06T03:22:23Z
Rough fix for 2.052 - will try out trunk later on today.
Regards
--- dmd.orig/cast.c 2011-02-18 01:15:38.000000000 +0000
+++ dmd/cast.c 2011-04-06 11:13:50.536604547 +0100
@@ -144,6 +144,10 @@
type = Type::terror;
}
Expression *e = optimize(WANTvalue | WANTflags);
+ if (t->ty == Tbool)
+ { // See if we can really convert the type to boolean.
+ e->checkToBoolean(NULL);
+ }
if (e->type == t)
return MATCHexact;
if (e != this)
--- dmd.orig/optimize.c 2011-02-18 01:15:38.000000000 +0000
+++ dmd/optimize.c 2011-04-06 10:55:18.075088167 +0100
@@ -990,6 +990,8 @@
e = new IntegerExp(loc, n1 || n2, type);
}
+ else if (! e2->type->checkBoolean())
+ ; // Don't convert e2 to bool if it's type disallows it.
else if (e1->isBool(FALSE))
e = new BoolExp(loc, e2, type);
}
Comment #3 by bugzilla — 2011-04-18T12:25:14Z
The patch seg faults building phobos because the argument to checkToBoolean is NULL.
Comment #4 by bugzilla — 2011-04-18T14:28:14Z
// Suitable for inclusion in test suite
struct A {}
void foo(bool cond){}
void main()
{
A a;
int i;
static assert(!__traits(compiles, assert(a))); // type A does not have a boolean value
static assert(!__traits(compiles, assert(i || a))); // type A does not have a boolean value
static assert(!__traits(compiles, assert(0 || a))); // OK
// if(a) {} // type A does not have a boolean value
// if(i || a) {} // type A does not have a boolean value
// if(0 || a) {} // type A does not have a boolean value
static assert(!__traits(compiles, foo(a))); // cannot implicitly convert type A to bool
static assert(!__traits(compiles, foo(i || a))); // OK
static assert(!__traits(compiles, foo(0 || a))); // OK
}
Comment #5 by ibuclaw — 2011-04-18T14:47:20Z
It can happen with '(1 && cond)' too.
Comment #6 by ibuclaw — 2011-04-18T14:58:27Z
Created attachment 944
issue5735
OK, Scrap the above, this is a check is in a better place - though it can cause duplicate errors to emit for the same line. I'm sure you'll know what's best to do though about that. :)