Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions compiler/src/dmd/expressionsem.d
Original file line number Diff line number Diff line change
Expand Up @@ -14931,6 +14931,19 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
{
//printf("EqualExp::semantic('%s')\n", exp.toErrMsg());

static Expression floatingNaNConst(Expression e)
{
auto optimized = e.optimize(WANTvalue);
if (!optimized || optimized.isConst() != 1)
return null;

if (optimized.type.isReal())
return CTFloat.isNaN(optimized.toReal()) ? optimized : null;
if (optimized.type.isImaginary())
return CTFloat.isNaN(optimized.toImaginary()) ? optimized : null;
return null;
}

exp.setNoderefOperands();

if (auto e = binSemanticProp(exp, sc))
Expand Down Expand Up @@ -15007,6 +15020,22 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
Type t1 = exp.e1.type.toBasetype();
Type t2 = exp.e2.type.toBasetype();

if (t1.isFloating() && t2.isFloating())
{
auto nan1 = floatingNaNConst(exp.e1);
auto nan2 = floatingNaNConst(exp.e2);
auto nan = nan1 ? nan1 : nan2;
if (nan)
{
const(char)* cmpResult = exp.op == EXP.equal ? "false" : "true";
error(exp.loc, "comparison with `%s` is always %s; use `%s` instead",
nan.toErrMsg(),
cmpResult,
"!is".ptr + (exp.op == EXP.equal));
return setError();
}
}

static bool unifyArrayTypes(Type t1, Type t2, Scope* sc)
{
Type t1n = t1.nextOf().toBasetype();
Expand Down
3 changes: 0 additions & 3 deletions compiler/test/compilable/test19227.d
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,5 @@ struct T
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);
}
23 changes: 23 additions & 0 deletions compiler/test/fail_compilation/fail18531.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
TEST_OUTPUT:
---
fail_compilation/fail18531.d(16): Error: comparison with `float.nan` is always false; use `is` instead
fail_compilation/fail18531.d(18): Error: comparison with `float.nan` is always true; use `!is` instead
fail_compilation/fail18531.d(20): Error: comparison with `float.nan` is always false; use `is` instead
fail_compilation/fail18531.d(22): Error: comparison with `double.nan` is always false; use `is` instead
---
*/

enum myNaN = double.nan;

void main()
{
float a = float.nan;
assert(a == float.nan);
float b = 0.0;
assert(b != float.nan);
float c = float.init;
assert(c == float.init);
assert(a == c);
assert(myNaN == double.nan);
}
19 changes: 12 additions & 7 deletions compiler/test/runnable/constfold.d
Original file line number Diff line number Diff line change
Expand Up @@ -148,13 +148,6 @@ static assert((7.2 != 6.2) == 1);
static assert((7.2 == 7.2) == 1);
static assert((7.2 != 7.2) == 0);

static assert((7.2 == double.nan) == 0);
static assert((7.2 != double.nan) == 1);
static assert((double.nan == double.nan) == 0);
static assert((double.nan != double.nan) == 1);
static assert((double.nan == 7.2) == 0);
static assert((double.nan != 7.2) == 1);

static assert((5 is 5) == 1);
static assert((5 is 4) == 0);
static assert((5 !is 5) == 0);
Expand Down Expand Up @@ -228,6 +221,17 @@ void test3()
assert(signbit(m) != 0);
}

void testNaN()
{
double nan = double.nan;
assert((7.2 == nan) == 0);
assert((7.2 != nan) == 1);
assert((nan == nan) == 0);
assert((nan != nan) == 1);
assert((nan == 7.2) == 0);
assert((nan != 7.2) == 1);
}

/************************************/

struct A4 { char [] a; }
Expand Down Expand Up @@ -587,6 +591,7 @@ int main()
test1();
test2();
test3();
testNaN();
test3697and();
test3697or();
test6077();
Expand Down
54 changes: 25 additions & 29 deletions compiler/test/runnable/nan.d
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,13 @@ import core.stdc.stdio;

enum real er1 = real.nan;
enum real er2 = 1;
static assert(er1 != er2);
static assert(!(er1 == er2));
static assert(!(er1 < er2));
static assert(!(er1 > er2));
static assert(!(er1 >= er2));
static assert(!(er1 <= er2));

enum double ed1 = real.nan;
enum double ed2 = 1;
static assert(ed1 != ed2);
static assert(!(ed1 == ed2));
static assert(!(ed1 < ed2));
static assert(!(ed1 > ed2));
static assert(!(ed1 >= ed2));
Expand Down Expand Up @@ -70,33 +66,33 @@ void test2(T)()

bool test()
{
real r1 = real.nan;
real r2 = 1;
b = (r1 != r2); assert(b);
b = (r1 == r2); assert(!b);
b = (r1 < r2); assert(!b);
b = (r1 > r2); assert(!b);
b = (r1 <= r2); assert(!b);
b = (r1 >= r2); assert(!b);
real r1 = real.nan;
real r2 = 1;
b = (r1 != r2); assert(b);
b = (r1 == r2); assert(!b);
b = (r1 < r2); assert(!b);
b = (r1 > r2); assert(!b);
b = (r1 <= r2); assert(!b);
b = (r1 >= r2); assert(!b);

double d1 = double.nan;
double d2 = 1;
b = (d1 != d2); assert(b);
b = (d1 == d2); assert(!b);
b = (d1 < d2); assert(!b);
b = (d1 > d2); assert(!b);
b = (d1 <= d2); assert(!b);
b = (d1 >= d2); assert(!b);
double d1 = double.nan;
double d2 = 1;
b = (d1 != d2); assert(b);
b = (d1 == d2); assert(!b);
b = (d1 < d2); assert(!b);
b = (d1 > d2); assert(!b);
b = (d1 <= d2); assert(!b);
b = (d1 >= d2); assert(!b);

float f1 = float.nan;
float f2 = 1;
b = (f1 != f2); assert(b);
b = (f1 == f2); assert(!b);
b = (f1 < f2); assert(!b);
b = (f1 > f2); assert(!b);
b = (f1 <= f2); assert(!b);
b = (f1 >= f2); assert(!b);
return true;
float f1 = float.nan;
float f2 = 1;
b = (f1 != f2); assert(b);
b = (f1 == f2); assert(!b);
b = (f1 < f2); assert(!b);
b = (f1 > f2); assert(!b);
b = (f1 <= f2); assert(!b);
b = (f1 >= f2); assert(!b);
return true;
}

void main()
Expand Down
Loading