-73d8e2fecb9e73422464b4cbf71f2b2967c9a75d
+955b8b36f8bbacc59745b44cdf48ef1ddeb01bcd
The first line of this file holds the git revision number of the last
merge done from the dlang/dmd repository.
result = pue->exp();
}
- void visit(AndAndExp *e)
+ void visit(LogicalExp *e)
{
// Check for an insidePointer expression, evaluate it if so
interpretFourPointerRelation(pue, e);
return;
int res;
- if (result->isBool(false))
- res = 0;
- else if (isTrueBool(result))
+ const bool andand = e->op == TOKandand;
+ if (andand ? result->isBool(false) : isTrueBool(result))
+ res = !andand;
+ else if (andand ? isTrueBool(result) : result->isBool(false))
{
UnionExp ue2;
result = interpret(&ue2, e->e2, istate);
res = 1;
else
{
- result->error("%s does not evaluate to a boolean", result->toChars());
+ result->error("`%s` does not evaluate to a boolean", result->toChars());
result = CTFEExp::cantexp;
return;
}
}
else
{
- result->error("%s cannot be interpreted as a boolean", result->toChars());
- result = CTFEExp::cantexp;
- return;
- }
- if (goal != ctfeNeedNothing)
- {
- new(pue) IntegerExp(e->loc, res, e->type);
- result = pue->exp();
- }
- }
-
- void visit(OrOrExp *e)
- {
- // Check for an insidePointer expression, evaluate it if so
- interpretFourPointerRelation(pue, e);
- if (result)
- return;
-
- result = interpret(e->e1, istate);
- if (exceptionOrCant(result))
- return;
-
- int res;
- if (isTrueBool(result))
- res = 1;
- else if (result->isBool(false))
- {
- UnionExp ue2;
- result = interpret(&ue2, e->e2, istate);
- if (exceptionOrCant(result))
- return;
- if (result->op == TOKvoidexp)
- {
- assert(e->type->ty == Tvoid);
- result = NULL;
- return;
- }
- if (result->isBool(false))
- res = 0;
- else if (isTrueBool(result))
- res = 1;
- else
- {
- result->error("%s cannot be interpreted as a boolean", result->toChars());
- result = CTFEExp::cantexp;
- return;
- }
- }
- else
- {
- result->error("%s cannot be interpreted as a boolean", result->toChars());
+ result->error("`%s` cannot be interpreted as a boolean", result->toChars());
result = CTFEExp::cantexp;
return;
}
// edtor => (__gate || edtor)
assert(tmp->edtor);
Expression *e = tmp->edtor;
- e = new OrOrExp(e->loc, new VarExp(e->loc, gate), e);
+ e = new LogicalExp(e->loc, TOKoror, new VarExp(e->loc, gate), e);
tmp->edtor = semantic(e, sc);
//printf("edtor: %s\n", tmp->edtor->toChars());
}
/************************************************************/
-OrOrExp::OrOrExp(Loc loc, Expression *e1, Expression *e2)
- : BinExp(loc, TOKoror, sizeof(OrOrExp), e1, e2)
+LogicalExp::LogicalExp(Loc loc, TOK op, Expression *e1, Expression *e2)
+ : BinExp(loc, op, sizeof(LogicalExp), e1, e2)
{
}
-Expression *OrOrExp::toBoolean(Scope *sc)
-{
- Expression *ex2 = e2->toBoolean(sc);
- if (ex2->op == TOKerror)
- return ex2;
- e2 = ex2;
- return this;
-}
-
-/************************************************************/
-
-AndAndExp::AndAndExp(Loc loc, Expression *e1, Expression *e2)
- : BinExp(loc, TOKandand, sizeof(AndAndExp), e1, e2)
-{
-}
-
-Expression *AndAndExp::toBoolean(Scope *sc)
+Expression *LogicalExp::toBoolean(Scope *sc)
{
Expression *ex2 = e2->toBoolean(sc);
if (ex2->op == TOKerror)
//printf("\t++v = %s, v->edtor = %s\n", v->toChars(), v->edtor->toChars());
Expression *ve = new VarExp(vcond->loc, vcond);
if (isThen)
- v->edtor = new AndAndExp(v->edtor->loc, ve, v->edtor);
+ v->edtor = new LogicalExp(v->edtor->loc, TOKandand, ve, v->edtor);
else
- v->edtor = new OrOrExp(v->edtor->loc, ve, v->edtor);
+ v->edtor = new LogicalExp(v->edtor->loc, TOKoror, ve, v->edtor);
v->edtor = semantic(v->edtor, sc);
//printf("\t--v = %s, v->edtor = %s\n", v->toChars(), v->edtor->toChars());
}
void accept(Visitor *v) { v->visit(this); }
};
-class OrOrExp : public BinExp
+class LogicalExp : public BinExp
{
public:
- OrOrExp(Loc loc, Expression *e1, Expression *e2);
- Expression *toBoolean(Scope *sc);
- void accept(Visitor *v) { v->visit(this); }
-};
-
-class AndAndExp : public BinExp
-{
-public:
- AndAndExp(Loc loc, Expression *e1, Expression *e2);
+ LogicalExp(Loc loc, TOK op, Expression *e1, Expression *e2);
Expression *toBoolean(Scope *sc);
void accept(Visitor *v) { v->visit(this); }
};
result = exp;
}
- void visit(OrOrExp *exp)
+ void visit(LogicalExp *exp)
{
if (exp->type)
{
setNoderefOperands(exp);
- // same as for AndAnd
Expression *e1x = semantic(exp->e1, sc);
// for static alias this: https://issues.dlang.org/show_bug.cgi?id=17684
/* If in static if, don't evaluate e2 if we don't have to.
*/
e1x = e1x->optimize(WANTvalue);
- if (e1x->isBool(true))
+ if (e1x->isBool(exp->op == TOKoror))
{
- result = new IntegerExp(exp->loc, 1, Type::tbool);
- return;
- }
- }
-
- Expression *e2x = semantic(exp->e2, sc);
- sc->mergeCallSuper(exp->loc, cs1);
-
- // for static alias this: https://issues.dlang.org/show_bug.cgi?id=17684
- if (e2x->op == TOKtype)
- e2x = resolveAliasThis(sc, e2x);
-
- e2x = resolveProperties(sc, e2x);
-
- bool f1 = checkNonAssignmentArrayOp(e1x);
- bool f2 = checkNonAssignmentArrayOp(e2x);
- if (f1 || f2)
- return setError();
-
- // Unless the right operand is 'void', the expression is converted to 'bool'.
- if (e2x->type->ty != Tvoid)
- e2x = e2x->toBoolean(sc);
-
- if (e2x->op == TOKtype || e2x->op == TOKscope)
- {
- exp->error("%s is not an expression", exp->e2->toChars());
- return setError();
- }
- if (e1x->op == TOKerror)
- {
- result = e1x;
- return;
- }
- if (e2x->op == TOKerror)
- {
- result = e2x;
- return;
- }
-
- // The result type is 'bool', unless the right operand has type 'void'.
- if (e2x->type->ty == Tvoid)
- exp->type = Type::tvoid;
- else
- exp->type = Type::tbool;
-
- exp->e1 = e1x;
- exp->e2 = e2x;
- result = exp;
- }
-
- void visit(AndAndExp *exp)
- {
- if (exp->type)
- {
- result = exp;
- return;
- }
-
- setNoderefOperands(exp);
-
- // same as for OrOr
- Expression *e1x = semantic(exp->e1, sc);
-
- // for static alias this: https://issues.dlang.org/show_bug.cgi?id=17684
- if (e1x->op == TOKtype)
- e1x = resolveAliasThis(sc, e1x);
-
- e1x = resolveProperties(sc, e1x);
- e1x = e1x->toBoolean(sc);
- unsigned cs1 = sc->callSuper;
-
- if (sc->flags & SCOPEcondition)
- {
- /* If in static if, don't evaluate e2 if we don't have to.
- */
- e1x = e1x->optimize(WANTvalue);
- if (e1x->isBool(false))
- {
- result = new IntegerExp(exp->loc, 0, Type::tbool);
+ result = new IntegerExp(exp->loc, exp->op == TOKoror, Type::tbool);
return;
}
}
if (!result)
result = eeq;
else if (e->op == TOKequal)
- result = new AndAndExp(e->loc, result, eeq);
+ result = new LogicalExp(e->loc, TOKandand, result, eeq);
else
- result = new OrOrExp(e->loc, result, eeq);
+ result = new LogicalExp(e->loc, TOKoror, result, eeq);
}
assert(result);
}
//printf("-SliceExp::optimize() %s\n", ret->toChars());
}
- void visit(AndAndExp *e)
+ void visit(LogicalExp *e)
{
- //printf("AndAndExp::optimize(%d) %s\n", result, e->toChars());
+ //printf("LogicalExp::optimize(%d) %s\n", result, e->toChars());
if (expOptimize(e->e1, WANTvalue))
return;
-
- if (e->e1->isBool(false))
- {
- // Replace with (e1, false)
- ret = new IntegerExp(e->loc, 0, Type::tbool);
- ret = Expression::combine(e->e1, ret);
- if (e->type->toBasetype()->ty == Tvoid)
- {
- ret = new CastExp(e->loc, ret, Type::tvoid);
- ret->type = e->type;
- }
- return;
- }
-
- if (expOptimize(e->e2, WANTvalue))
- return;
-
- if (e->e1->isConst())
- {
- if (e->e2->isConst())
- {
- bool n1 = e->e1->isBool(true);
- bool n2 = e->e2->isBool(true);
- ret = new IntegerExp(e->loc, n1 && n2, e->type);
- }
- else if (e->e1->isBool(true))
- {
- if (e->type->toBasetype()->ty == Tvoid)
- ret = e->e2;
- else
- {
- ret = new CastExp(e->loc, e->e2, e->type);
- ret->type = e->type;
- }
- }
- }
- }
-
- void visit(OrOrExp *e)
- {
- //printf("OrOrExp::optimize(%d) %s\n", result, e->toChars());
- if (expOptimize(e->e1, WANTvalue))
- return;
-
- if (e->e1->isBool(true))
+ const bool oror = e->op == TOKoror;
+ if (e->e1->isBool(oror))
{
- // Replace with (e1, true)
- ret = new IntegerExp(e->loc, 1, Type::tbool);
+ // Replace with (e1, oror)
+ ret = new IntegerExp(e->loc, oror, Type::tbool);
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 = ret->optimize(result);
return;
}
{
bool n1 = e->e1->isBool(true);
bool n2 = e->e2->isBool(true);
- ret = new IntegerExp(e->loc, n1 || n2, e->type);
+ ret = new IntegerExp(e->loc, oror ? (n1 || n2) : (n1 && n2), e->type);
}
- else if (e->e1->isBool(false))
+ else if (e->e1->isBool(!oror))
{
if (e->type->toBasetype()->ty == Tvoid)
ret = e->e2;
{
nextToken();
e2 = parseOrExp();
- e = new AndAndExp(loc, e, e2);
+ e = new LogicalExp(loc, TOKandand, e, e2);
}
return e;
}
{
nextToken();
e2 = parseAndAndExp();
- e = new OrOrExp(loc, e, e2);
+ e = new LogicalExp(loc, TOKoror, e, e2);
}
return e;
}
return true;
case TOKandand:
- {
- AndAndExp *aae = (AndAndExp *)e;
- return discardValue(aae->e2);
- }
-
case TOKoror:
{
- OrOrExp *ooe = (OrOrExp *)e;
- return discardValue(ooe->e2);
+ LogicalExp *aae = (LogicalExp *)e;
+ return discardValue(aae->e2);
}
case TOKquestion:
bool evalStaticCondition(Scope *sc, Expression *exp, Expression *e, bool &errors)
{
- if (e->op == TOKandand)
+ if (e->op == TOKandand || e->op == TOKoror)
{
- AndAndExp *aae = (AndAndExp *)e;
+ LogicalExp *aae = (LogicalExp *)e;
bool result = evalStaticCondition(sc, exp, aae->e1, errors);
- if (errors || !result)
- return false;
- result = evalStaticCondition(sc, exp, aae->e2, errors);
- return !errors && result;
- }
-
- if (e->op == TOKoror)
- {
- OrOrExp *ooe = (OrOrExp *)e;
- bool result = evalStaticCondition(sc, exp, ooe->e1, errors);
if (errors)
return false;
- if (result)
- return true;
- result = evalStaticCondition(sc, exp, ooe->e2, errors);
+ if (e->op == TOKandand)
+ {
+ if (!result)
+ return false;
+ }
+ else
+ {
+ if (result)
+ return true;
+ }
+ result = evalStaticCondition(sc, exp, aae->e2, errors);
return !errors && result;
}
class AndExp;
class OrExp;
class XorExp;
-class OrOrExp;
-class AndAndExp;
+class LogicalExp;
class CmpExp;
class InExp;
class RemoveExp;
virtual void visit(AndExp *e) { visit((BinExp *)e); }
virtual void visit(OrExp *e) { visit((BinExp *)e); }
virtual void visit(XorExp *e) { visit((BinExp *)e); }
- virtual void visit(OrOrExp *e) { visit((BinExp *)e); }
- virtual void visit(AndAndExp *e) { visit((BinExp *)e); }
+ virtual void visit(LogicalExp *e) { visit((BinExp *)e); }
virtual void visit(CmpExp *e) { visit((BinExp *)e); }
virtual void visit(InExp *e) { visit((BinExp *)e); }
virtual void visit(RemoveExp *e) { visit((BinExp *)e); }
this->result_ = d_convert (build_ctype (e->type), result);
}
- /* Build an `and if' expression. If the right operand expression is void,
- then the resulting type is void. Otherwise the result is bool. */
+ /* Build a logical `and if' or `or if' expression. If the right operand
+ expression is void, then the resulting type is void. Otherwise the
+ result is bool. */
- void visit (AndAndExp *e)
+ void visit (LogicalExp *e)
{
+ tree_code code = (e->op == TOKandand) ? TRUTH_ANDIF_EXPR : TRUTH_ORIF_EXPR;
+
if (e->e2->type->toBasetype ()->ty != Tvoid)
{
tree t1 = build_expr (e->e1);
t2 = convert_for_condition (t2, e->e2->type);
this->result_ = d_convert (build_ctype (e->type),
- build_boolop (TRUTH_ANDIF_EXPR, t1, t2));
+ build_boolop (code, t1, t2));
}
else
{
tree t1 = convert_for_condition (build_expr (e->e1), e->e1->type);
tree t2 = build_expr_dtor (e->e2);
- this->result_ = build_condition (build_ctype (e->type),
- t1, t2, void_node);
- }
- }
-
- /* Build an `or if' expression. If the right operand expression is void,
- then the resulting type is void. Otherwise the result is bool. */
-
- void visit (OrOrExp *e)
- {
- if (e->e2->type->toBasetype ()->ty != Tvoid)
- {
- tree t1 = convert_for_condition (build_expr (e->e1), e->e1->type);
- tree t2 = convert_for_condition (build_expr (e->e2), e->e2->type);
-
- this->result_ = d_convert (build_ctype (e->type),
- build_boolop (TRUTH_ORIF_EXPR, t1, t2));
- }
- else
- {
- tree t1 = convert_for_condition (build_expr (e->e1), e->e1->type);
- tree t2 = build_expr_dtor (e->e2);
- tree cond = build1 (TRUTH_NOT_EXPR, d_bool_type, t1);
+ /* Invert condition for logical or if expression. */
+ if (e->op == TOKoror)
+ t1 = build1 (TRUTH_NOT_EXPR, d_bool_type, t1);
this->result_ = build_condition (build_ctype (e->type),
- cond, t2, void_node);
+ t1, t2, void_node);
}
}