Showing with 59 additions and 6 deletions.
  1. +28 −6 src/inline.d
  2. +31 −0 test/runnable/inline.d
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;
if (e.e1.op == TOKvar)
{
Expand Down Expand Up @@ -1736,10 +1758,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 @@ -1855,7 +1877,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
31 changes: 31 additions & 0 deletions test/runnable/inline.d
Original file line number Diff line number Diff line change
Expand Up @@ -915,6 +915,36 @@ struct ProtoPackage15253
}
}

/**********************************/
// 15296

static int x15296;

struct S15296
{
// Can be expanded only as statements.
void bar(size_t , size_t )
{
for (size_t w = 0; w < 2; w++) { ++x15296; }
}

pragma(inline, true)
void foo(size_t a, size_t b)
{
bar(a, b);
}
}

void test15296()
{
S15296 s;

// CallExp at the top of ExpStatement
x15296 = 0;
s.foo(0, 0);
assert(x15296 == 2);
}

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

int main()
Expand Down Expand Up @@ -947,6 +977,7 @@ int main()
test9785();
test9785_2();
test15207();
test15296();

printf("Success\n");
return 0;
Expand Down