Skip to content

Commit

Permalink
fix Issue 19227 - S.init is S.init failing for struct with float member
Browse files Browse the repository at this point in the history
  • Loading branch information
WalterBright committed Dec 13, 2018
1 parent 33bc192 commit e1dce1a
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 8 deletions.
34 changes: 26 additions & 8 deletions src/dmd/ctfeexpr.d
Expand Up @@ -1170,10 +1170,17 @@ private bool isArray(Expression e)
return e.op == TOK.arrayLiteral || e.op == TOK.string_ || e.op == TOK.slice || e.op == TOK.null_;
}

/* For strings, return <0 if e1 < e2, 0 if e1==e2, >0 if e1 > e2.
/*****
* Params:
* loc = source file location
* e1 = left operand
* e2 = right operand
* identity = true for `is` identity comparisons
* Returns:
* For strings, return <0 if e1 < e2, 0 if e1==e2, >0 if e1 > e2.
* For all other types, return 0 if e1 == e2, !=0 if e1 != e2.
*/
private int ctfeRawCmp(const ref Loc loc, Expression e1, Expression e2)
private int ctfeRawCmp(const ref Loc loc, Expression e1, Expression e2, bool identity = false)
{
if (e1.op == TOK.classReference || e2.op == TOK.classReference)
{
Expand Down Expand Up @@ -1254,9 +1261,11 @@ private int ctfeRawCmp(const ref Loc loc, Expression e1, Expression e2)
{
real_t r1 = e1.type.isreal() ? e1.toReal() : e1.toImaginary();
real_t r2 = e1.type.isreal() ? e2.toReal() : e2.toImaginary();
if (identity)
return !RealEquals(r1, r2);
if (CTFloat.isNaN(r1) || CTFloat.isNaN(r2)) // if unordered
{
return 1;
return 1; // they are not equal
}
else
{
Expand All @@ -1265,7 +1274,13 @@ private int ctfeRawCmp(const ref Loc loc, Expression e1, Expression e2)
}
else if (e1.type.iscomplex())
{
return e1.toComplex() != e2.toComplex();
auto c1 = e1.toComplex();
auto c2 = e2.toComplex();
if (identity)
{
return !RealEquals(c1.re, c2.re) && !RealEquals(c1.im, c2.im);
}
return c1 != c2;
}
if (e1.op == TOK.structLiteral && e2.op == TOK.structLiteral)
{
Expand All @@ -1290,7 +1305,7 @@ private int ctfeRawCmp(const ref Loc loc, Expression e1, Expression e2)
continue;
if (!ee1 || !ee2)
return 1;
int cmp = ctfeRawCmp(loc, ee1, ee2);
const int cmp = ctfeRawCmp(loc, ee1, ee2, identity);
if (cmp)
return 1;
}
Expand All @@ -1316,13 +1331,13 @@ private int ctfeRawCmp(const ref Loc loc, Expression e1, Expression e2)
if (used[j])
continue;
Expression k2 = (*es2.keys)[j];
if (ctfeRawCmp(loc, k1, k2))
if (ctfeRawCmp(loc, k1, k2, identity))
continue;
used[j] = true;
v2 = (*es2.values)[j];
break;
}
if (!v2 || ctfeRawCmp(loc, v1, v2))
if (!v2 || ctfeRawCmp(loc, v1, v2, identity))
{
mem.xfree(used);
return 1;
Expand All @@ -1347,6 +1362,7 @@ extern (C++) int ctfeEqual(const ref Loc loc, TOK op, Expression e1, Expression
/// Evaluate is, !is. Resolves slices before comparing. Returns 0 or 1
extern (C++) int ctfeIdentity(const ref Loc loc, TOK op, Expression e1, Expression e2)
{
//printf("ctfeIdentity %s %s\n", e1.toChars(), e2.toChars());
//printf("ctfeIdentity op = '%s', e1 = %s %s, e2 = %s %s\n", Token::toChars(op),
// Token::toChars(e1.op), e1.toChars(), Token::toChars(e2.op), e1.toChars());
int cmp;
Expand Down Expand Up @@ -1375,7 +1391,9 @@ extern (C++) int ctfeIdentity(const ref Loc loc, TOK op, Expression e1, Expressi
cmp = RealEquals(creall(v1), creall(v2)) && RealEquals(cimagl(v1), cimagl(v1));
}
else
cmp = !ctfeRawCmp(loc, e1, e2);
{
cmp = !ctfeRawCmp(loc, e1, e2, true);
}
if (op == TOK.notIdentity || op == TOK.notEqual)
cmp ^= 1;
return cmp;
Expand Down
21 changes: 21 additions & 0 deletions test/compilable/test19227.d
@@ -0,0 +1,21 @@
// https://issues.dlang.org/show_bug.cgi?id=19227

struct S
{
float f;
}

struct T
{
cfloat cf;
}

void main()
{
static assert(S.init is S.init);
static assert(S.init != S.init);

static assert(T.init is T.init);
static assert(T.init != T.init);
}

0 comments on commit e1dce1a

Please sign in to comment.