Fix bugzilla issue 24566 - condition that starts with runtime value and uses compile time array does not short circuit

This commit is contained in:
Timon Gehr 2024-06-09 15:41:59 +02:00 committed by The Dlang Bot
parent f56d15b9f0
commit d92734bdac
2 changed files with 60 additions and 10 deletions

View file

@ -1238,18 +1238,21 @@ Expression optimize(Expression e, int result, bool keepLvalue = false)
if (expOptimize(e.e1, WANTvalue))
return;
const oror = e.op == EXP.orOr;
void returnE_e1()
{
ret = e.e1;
if (!e.e1.type.equals(e.type))
{
ret = new CastExp(e.loc, ret, e.type);
ret.type = e.type;
ret = optimize(ret, result, false);
}
}
if (e.e1.toBool().hasValue(oror))
{
// Replace with (e1, oror)
ret = IntegerExp.createBool(oror);
ret = Expression.combine(e.e1, ret);
if (e.type.toBasetype().ty == Tvoid)
{
ret = new CastExp(e.loc, ret, Type.tvoid);
ret.type = e.type;
}
ret = optimize(ret, result, false);
return;
// e_true || e2 -> e_true
// e_false && e2 -> e_false
return returnE_e1();
}
expOptimize(e.e2, WANTvalue);
if (e.e1.isConst())
@ -1263,6 +1266,7 @@ Expression optimize(Expression e, int result, bool keepLvalue = false)
}
else if (e1Opt.hasValue(!oror))
{
if (e.type.toBasetype().ty == Tvoid)
ret = e.e2;
else
@ -1272,6 +1276,29 @@ Expression optimize(Expression e, int result, bool keepLvalue = false)
}
}
}
else if (e.e2.isConst())
{
const e2Opt = e.e2.toBool();
if (e2Opt.hasValue(oror))
{
// e1 || true -> (e1, true)
// e1 && false -> (e1, false)
ret = IntegerExp.createBool(oror);
ret = Expression.combine(e.e1, ret);
if (e.type.toBasetype().ty == Tvoid)
{
ret = new CastExp(e.loc, ret, Type.tvoid);
ret.type = e.type;
}
ret = optimize(ret, result, false);
}
else if (e2Opt.hasValue(!oror))
{
// e1 || false -> e1
// e1 && true -> e1
return returnE_e1();
}
}
}
void visitCmp(CmpExp e)

View file

@ -0,0 +1,23 @@
// https://issues.dlang.org/show_bug.cgi?id=24566
void test24566a()
{
enum a = true;
bool b = true;
enum str = "a";
if (a && str.length > 1 && str[1] == 'a') {}
if (b && str.length > 1 && str[1] == 'a') {}
if (!b && str.length > 1 && str[1] == 'a') {}
if (str.length > 1 && b && str[1] == 'a') {}
}
void test24566b()
{
enum a = false;
bool b = false;
enum str = "a";
if (a || str.length <= 1 || str[1] == 'a') {}
if (b || str.length <= 1 || str[1] == 'a') {}
if (!b || str.length <= 1 || str[1] == 'a') {}
if (str.length <= 1 || b || str[1] == 'a') {}
}