Showing with 355 additions and 143 deletions.
  1. +1 −1 src/aggregate.d
  2. +6 −3 src/backend/cgelem.c
  3. +12 −126 src/expression.d
  4. +28 −6 src/inline.d
  5. +189 −7 src/opover.d
  6. +28 −0 test/fail_compilation/fail15292.d
  7. +30 −0 test/runnable/aliasthis.d
  8. +31 −0 test/runnable/inline.d
  9. +30 −0 test/runnable/mars1.d
2 changes: 1 addition & 1 deletion src/aggregate.d
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ public:

override final void semantic3(Scope* sc)
{
//printf("AggregateDeclaration::semantic3(%s) type = %s, errors = %d\n", toChars(), type->toChars(), errors);
//printf("AggregateDeclaration::semantic3(%s) type = %s, errors = %d\n", toChars(), type.toChars(), errors);
if (!members)
return;

Expand Down
9 changes: 6 additions & 3 deletions src/backend/cgelem.c
Original file line number Diff line number Diff line change
Expand Up @@ -3538,9 +3538,11 @@ STATIC elem * eleq(elem *e, goal_t goal)
if (tysize(e1->Ety) == 2 * REGSIZE &&
e1->Eoper == OPvar &&
(e2->Eoper == OPpair || e2->Eoper == OPrpair) &&
goal == GOALnone
goal == GOALnone &&
!el_appears(e2, e1->EV.sp.Vsym)
)
{
//printf("** before:\n"); WReqn(e); printf("\n");
tym_t ty = (REGSIZE == 8) ? TYllong : TYint;
if (tyfloating(e1->Ety) && REGSIZE >= 4)
ty = (REGSIZE == 8) ? TYdouble : TYfloat;
Expand All @@ -3555,8 +3557,8 @@ STATIC elem * eleq(elem *e, goal_t goal)
{
e->E2 = e2->E1;
eb = el_bin(OPeq,ty,eb,e2->E2);
e2->E1 = eb;
e2->E2 = e;
e2->E1 = e;
e2->E2 = eb;
}
else
{
Expand All @@ -3567,6 +3569,7 @@ STATIC elem * eleq(elem *e, goal_t goal)
}

e2->Eoper = OPcomma;
//printf("** after:\n"); WReqn(e2); printf("\n");
return optelem(e2,goal);
}

Expand Down
138 changes: 12 additions & 126 deletions src/expression.d
Original file line number Diff line number Diff line change
Expand Up @@ -2072,27 +2072,6 @@ extern (C++) Expression opAssignToOp(Loc loc, TOK op, Expression e1, Expression
return e;
}

extern (C++) bool needDirectEq(Scope* sc, Type t1, Type t2)
{
assert(t1.ty == Tarray || t1.ty == Tsarray);
assert(t2.ty == Tarray || t2.ty == Tsarray);
Type t1n = t1.nextOf().toBasetype();
Type t2n = t2.nextOf().toBasetype();
if (((t1n.ty == Tchar || t1n.ty == Twchar || t1n.ty == Tdchar) && (t2n.ty == Tchar || t2n.ty == Twchar || t2n.ty == Tdchar)) || (t1n.ty == Tvoid || t2n.ty == Tvoid))
{
return false;
}
if (t1n.constOf() != t2n.constOf())
return true;
Type t = t1n;
while (t.toBasetype().nextOf())
t = t.nextOf().toBasetype();
if (t.ty != Tstruct)
return false;
semanticTypeInfo(sc, t);
return (cast(TypeStruct)t).sym.hasIdentityEquals;
}

/****************************************************************/
extern (C++) Expression extractOpDollarSideEffect(Scope* sc, UnaExp ue)
{
Expand Down Expand Up @@ -14324,10 +14303,12 @@ public:
//printf("EqualExp::semantic('%s')\n", toChars());
if (type)
return this;
if (Expression ex = binSemanticProp(sc))
return ex;

if (auto e = binSemanticProp(sc))
return e;
if (e1.op == TOKtype || e2.op == TOKtype)
return incompatibleTypes();

/* Before checking for operator overloading, check to see if we're
* comparing the addresses of two statics. If so, we can just see
* if they are the same symbol.
Expand All @@ -14347,112 +14328,15 @@ public:
}
}
}
Type t1 = e1.type.toBasetype();
Type t2 = e2.type.toBasetype();
if (t1.ty == Tclass && e2.op == TOKnull || t2.ty == Tclass && e1.op == TOKnull)
{
error("use '%s' instead of '%s' when comparing with null", Token.toChars(op == TOKequal ? TOKidentity : TOKnotidentity), Token.toChars(op));
return new ErrorExp();
}
if ((t1.ty == Tarray || t1.ty == Tsarray) && (t2.ty == Tarray || t2.ty == Tsarray))
{
if (needDirectEq(sc, t1, t2))
{
/* Rewrite as:
* _ArrayEq(e1, e2)
*/
Expression eq = new IdentifierExp(loc, Id._ArrayEq);
Expression e = new CallExp(loc, eq, e1, e2);
if (op == TOKnotequal)
e = new NotExp(loc, e);
e = e.trySemantic(sc); // for better error message
if (!e)
{
error("cannot compare %s and %s", t1.toChars(), t2.toChars());
return new ErrorExp();
}
return e;
}
}
Expression e = op_overload(sc);
if (e)
{
if (e.op == TOKcall && op == TOKnotequal)
{
e = new NotExp(e.loc, e);
e = e.semantic(sc);
}

if (auto e = op_overload(sc))
return e;
}
if (t1.ty == Tpointer || t2.ty == Tpointer)
{
/* Rewrite:
* ptr1 == ptr2
* as:
* ptr1 is ptr2
*/
e = new IdentityExp(op == TOKequal ? TOKidentity : TOKnotidentity, loc, e1, e2);
e = e.semantic(sc);

if (auto e = typeCombine(this, sc))
return e;
}
if (t1.ty == Tstruct && t2.ty == Tstruct)
{
StructDeclaration sd = (cast(TypeStruct)t1).sym;
if (sd == (cast(TypeStruct)t2).sym)
{
if (needOpEquals(sd))
{
this.e1 = new DotIdExp(loc, e1, Id._tupleof);
this.e2 = new DotIdExp(loc, e2, Id._tupleof);
e = this;
}
else
{
e = new IdentityExp(op == TOKequal ? TOKidentity : TOKnotidentity, loc, e1, e2);
}
e = e.semantic(sc);
return e;
}
}
// check tuple equality before typeCombine
if (e1.op == TOKtuple && e2.op == TOKtuple)
{
TupleExp tup1 = cast(TupleExp)e1;
TupleExp tup2 = cast(TupleExp)e2;
size_t dim = tup1.exps.dim;
e = null;
if (dim != tup2.exps.dim)
{
error("mismatched tuple lengths, %d and %d", cast(int)dim, cast(int)tup2.exps.dim);
return new ErrorExp();
}
if (dim == 0)
{
// zero-length tuple comparison should always return true or false.
e = new IntegerExp(loc, (op == TOKequal), Type.tbool);
}
else
{
for (size_t i = 0; i < dim; i++)
{
Expression ex1 = (*tup1.exps)[i];
Expression ex2 = (*tup2.exps)[i];
Expression eeq = new EqualExp(op, loc, ex1, ex2);
if (!e)
e = eeq;
else if (op == TOKequal)
e = new AndAndExp(loc, e, eeq);
else
e = new OrOrExp(loc, e, eeq);
}
}
assert(e);
e = combine(combine(tup1.e0, tup2.e0), e);
return e.semantic(sc);
}
if (Expression ex = typeCombine(this, sc))
return ex;

type = Type.tbool;

// Special handling for array comparisons
if (!arrayTypeCompatible(loc, e1.type, e2.type))
{
Expand All @@ -14465,8 +14349,10 @@ public:
}
if (e1.type.toBasetype().ty == Taarray)
semanticTypeInfo(sc, e1.type.toBasetype());

if (e1.type.toBasetype().ty == Tvector)
return incompatibleTypes();

return this;
}

Expand Down
34 changes: 28 additions & 6 deletions src/inline.d
Original file line number Diff line number Diff line change
Expand Up @@ -1201,13 +1201,33 @@ public:
}
if (s.exp)
{
inlineScan(s.exp); // inline as an expression
/* TODO: It's a problematic inlineScan call. If s.exp is a TOKcall,
* CallExp.inlineScan would try to expand the call as expression.
* If it's impossible, a false "cannot inline function" error
* would be reported.
*/
inlineScan(s.exp); // inline as an expression

/* If there's a TOKcall at the top, then it failed to inline
* as an Expression. Try to inline as a Statement instead.
* Note that inline scanning of s.exp.e1 and s.exp.arguments was already done.
*/
if (s.exp && s.exp.op == TOKcall)
visitCallExp(cast(CallExp)s.exp, null, true);
{
CallExp ce = cast(CallExp)s.exp;

/* Workaround for Bugzilla 15296.
*
* Before the PR#5121, here was inlined a function call only
* when ce.e1.op == TOKvar.
* After the PR, visitCallExp has started to handle TOKdotvar
* and TOKstar. However it was not good for the issue case.
*
* Revive a restriction which was in previous code to avoid regression.
*/
if (ce.e1.op == TOKvar)
visitCallExp(ce, null, true);
}
}
}

Expand Down Expand Up @@ -1478,6 +1498,7 @@ public:

override void visit(CallExp e)
{
//printf("CallExp.inlineScan() %s\n", e.toChars());
inlineScan(e.e1);
arrayInlineScan(e.arguments);
visitCallExp(e, null, false);
Expand All @@ -1493,7 +1514,8 @@ public:
*/
void visitCallExp(CallExp e, Expression eret, bool asStatements)
{
//printf("CallExp.inlineScan() %s\n", e.toChars());
//printf("visitCallExp() %s\n", e.toChars());

FuncDeclaration fd;

void inlineFd()
Expand Down Expand Up @@ -1772,10 +1794,10 @@ bool canInline(FuncDeclaration fd, bool hasthis, bool hdrscan, bool statementsTo
{
int cost;

enum CANINLINE_LOG = 0;
static if (CANINLINE_LOG)
{
printf("FuncDeclaration.canInline(hasthis = %d, statementsToo = %d, '%s')\n", hasthis, statementsToo, fd.toPrettyChars());
printf("FuncDeclaration.canInline(hasthis = %d, statementsToo = %d, '%s')\n",
hasthis, statementsToo, fd.toPrettyChars());
}

if (fd.needThis() && !hasthis)
Expand Down Expand Up @@ -1891,7 +1913,7 @@ bool canInline(FuncDeclaration fd, bool hasthis, bool hdrscan, bool statementsTo
}
static if (CANINLINE_LOG)
{
printf("cost = %d for %s\n", cost, fd.toChars());
printf("\tcost = %d for %s\n", cost, fd.toChars());
}

if (tooCostly(cost))
Expand Down
Loading