@@ -205,100 +205,153 @@ public:
205205 result = exp;
206206 }
207207
208- override void visit (CompoundStatement s)
208+ static if (asStatements)
209+ alias StatementsResult = Statements* ;
210+ else
211+ alias StatementsResult = Expression;
212+
213+ static StatementsResult statementsDoInline (Statements* stmts, InlineDoState ids)
209214 {
210- // printf("CompoundStatement.doInlineAs!%s() %d\n", Result.stringof.ptr, s.statements.length);
211215 static if (asStatements)
212216 {
213- auto as = new Statements();
214- as.reserve (s.statements.length);
217+ auto result = new Statements();
218+ result.reserve (stmts.length);
219+ }
220+ else
221+ {
222+ Expression result;
215223 }
216224
217- foreach (i, sx; * s.statements )
225+ foreach (i, sx; * stmts )
218226 {
219227 if (! sx)
220228 continue ;
221- static if (asStatements)
222- {
223- as.push(doInlineAs! Statement(sx, ids));
224- }
225- else
229+
230+ if (auto ifs = sx.isIfStatement())
226231 {
227- /* Specifically allow:
228- * if (condition)
229- * return exp1;
230- * return exp2;
231- */
232- IfStatement ifs;
233- Statement s3;
234- if ((ifs = sx.isIfStatement()) ! is null &&
235- ifs.ifbody &&
236- ifs.ifbody.endsWithReturnStatement() &&
237- ! ifs.elsebody &&
238- i + 1 < s.statements.length &&
239- (s3 = (* s.statements)[i + 1 ]) ! is null &&
240- s3.endsWithReturnStatement()
241- )
232+ assert (! ifs.param);
233+ auto econd = doInlineAs! Expression(ifs.condition, ids);
234+ assert (econd);
235+
236+ ids.foundReturn = false ;
237+ auto ifbody = doInlineAs! Result(ifs.ifbody, ids);
238+ bool ifReturned = ids.foundReturn;
239+
240+ ids.foundReturn = false ;
241+ auto elsebody = doInlineAs! Result(ifs.elsebody, ids);
242+ bool elseReturned = ids.foundReturn;
243+
244+ if (ifReturned != elseReturned)
242245 {
243- /* Rewrite as ?:
246+ /* One branch returns, but the other does not.
247+ * Merge the remaining statements in stmts into
248+ * the branch that does not return, and recurse.
244249 */
245- auto econd = doInlineAs! Expression(ifs.condition, ids);
246- assert (econd);
247- auto e1 = doInlineAs! Expression(ifs.ifbody, ids);
248- assert (ids.foundReturn);
249- auto e2 = doInlineAs! Expression(s3, ids);
250- assert (e2);
251- Expression e = new CondExp(econd.loc, econd, e1, e2);
252- e.type = e1.type;
253- if (e.type.ty == Ttuple)
250+
251+ if (elseReturned)
254252 {
255- e1.type = Type.tvoid;
256- e2.type = Type.tvoid;
257- e.type = Type.tvoid;
253+ /* Rewrite
254+ * if (cond) stmt; else return exp;
255+ * into
256+ * if (!cond) return exp; else stmt;
257+ */
258+ econd = new NotExp(econd.loc, econd);
259+ econd.type = Type.tbool;
260+
261+ auto tmp = ifbody;
262+ ifbody = elsebody;
263+ elsebody = tmp;
258264 }
259- result = Expression.combine(result, e);
265+
266+ if (i < stmts.length - 1 )
267+ {
268+ ids.foundReturn = false ;
269+ scope rem = Statements((* stmts)[i + 1 .. $]);
270+ auto rembody = statementsDoInline(&rem, ids);
271+
272+ static if (asStatements)
273+ {
274+ /* Rewrite
275+ * if (cond) return exp; else stmt1; stmt2;
276+ * into
277+ * if (cond) return exp; else { { stmt1; } stmt2; }
278+ */
279+ auto ss = new ScopeStatement(ifs.loc, elsebody, ifs.endloc);
280+ auto cs = new CompoundStatement(ifs.loc, ss);
281+ cs.statements.append(rembody);
282+ elsebody = cs;
283+ }
284+ else
285+ {
286+ elsebody = Expression.combine(elsebody, rembody);
287+ }
288+ }
289+
290+ ids.foundReturn = true ;
291+
292+ static if (asStatements)
293+ {
294+ auto s = new IfStatement(ifs.loc, ifs.param, econd, ifbody, elsebody, ifs.endloc);
295+ result.push(s);
296+ }
297+ else
298+ {
299+ auto e = buildBranchExp(econd, ifbody, elsebody);
300+ result = Expression.combine(result, e);
301+ }
302+
303+ return result;
304+ }
305+
306+ ids.foundReturn = ifReturned && elseReturned;
307+
308+ static if (asStatements)
309+ {
310+ auto s = new IfStatement(ifs.loc, ifs.param, econd, ifbody, elsebody, ifs.endloc);
311+ result.push(s);
260312 }
261313 else
262314 {
263- ids.foundReturn = false ;
264- auto e = doInlineAs! Expression(sx, ids);
315+ auto e = buildBranchExp(econd, ifbody, elsebody);
265316 result = Expression.combine(result, e);
266317 }
267318 }
319+ else
320+ {
321+ ids.foundReturn = false ;
322+
323+ auto r = doInlineAs! Result(sx, ids);
324+ static if (asStatements)
325+ result.push(r);
326+ else
327+ result = Expression.combine(result, r);
328+ }
268329
269330 if (ids.foundReturn)
270331 break ;
271332 }
272333
334+ return result;
335+ }
336+
337+ override void visit (CompoundStatement s)
338+ {
339+ // printf("CompoundStatement.doInlineAs!%s() %d\n", Result.stringof.ptr, s.statements.length);
340+ auto r = statementsDoInline(s.statements, ids);
273341 static if (asStatements)
274- result = new CompoundStatement(s.loc, as);
342+ result = new CompoundStatement(s.loc, r);
343+ else
344+ result = r;
275345 }
276346
277347 override void visit (UnrolledLoopStatement s)
278348 {
279349 // printf("UnrolledLoopStatement.doInlineAs!%s() %d\n", Result.stringof.ptr, s.statements.length);
350+ auto r = statementsDoInline(s.statements, ids);
280351 static if (asStatements)
281- {
282- auto as = new Statements();
283- as.reserve (s.statements.length);
284- }
285-
286- foreach (sx; * s.statements)
287- {
288- if (! sx)
289- continue ;
290- auto r = doInlineAs! Result(sx, ids);
291- static if (asStatements)
292- as.push(r);
293- else
294- result = Expression.combine(result, r);
295-
296- if (ids.foundReturn)
297- break ;
298- }
299-
300- static if (asStatements)
301- result = new UnrolledLoopStatement(s.loc, as);
352+ result = new UnrolledLoopStatement(s.loc, r);
353+ else
354+ result = r;
302355 }
303356
304357 override void visit (ScopeStatement s)
@@ -317,47 +370,23 @@ public:
317370 auto econd = doInlineAs! Expression(s.condition, ids);
318371 assert (econd);
319372
373+ ids.foundReturn = false ;
320374 auto ifbody = doInlineAs! Result(s.ifbody, ids);
321- bool bodyReturn = ids.foundReturn;
375+ bool ifReturned = ids.foundReturn;
322376
323377 ids.foundReturn = false ;
324378 auto elsebody = doInlineAs! Result(s.elsebody, ids);
379+ bool elseReturned = ids.foundReturn;
380+
381+ // Top-level if statements should have been handled in statementsDoInline().
382+ // Here we're handling nested if statements, which must be symmetrical.
383+ assert (ifReturned == elseReturned);
384+ ids.foundReturn = ifReturned && elseReturned;
325385
326386 static if (asStatements)
327- {
328387 result = new IfStatement(s.loc, s.param, econd, ifbody, elsebody, s.endloc);
329- }
330388 else
331- {
332- alias e1 = ifbody;
333- alias e2 = elsebody;
334- if (e1 && e2)
335- {
336- result = new CondExp(econd.loc, econd, e1, e2);
337- result.type = e1.type;
338- if (result.type.ty == Ttuple)
339- {
340- e1.type = Type.tvoid;
341- e2.type = Type.tvoid;
342- result.type = Type.tvoid;
343- }
344- }
345- else if (e1)
346- {
347- result = new LogicalExp(econd.loc, EXP .andAnd, econd, e1);
348- result.type = Type.tvoid;
349- }
350- else if (e2)
351- {
352- result = new LogicalExp(econd.loc, EXP .orOr, econd, e2);
353- result.type = Type.tvoid;
354- }
355- else
356- {
357- result = econd;
358- }
359- }
360- ids.foundReturn = ids.foundReturn && bodyReturn;
389+ result = buildBranchExp(econd, ifbody, elsebody);
361390 }
362391
363392 override void visit (ReturnStatement s)
@@ -2619,3 +2648,45 @@ private bool expNeedsDtor(Expression exp)
26192648 scope NeedsDtor ct = new NeedsDtor(exp);
26202649 return walkPostorder (exp, ct);
26212650}
2651+
2652+ /* **********************************************************
2653+ * Build an expression with the semantics of
2654+ * if (econd) e1; else e2;
2655+ */
2656+ Expression buildBranchExp (Expression econd, Expression e1, Expression e2)
2657+ {
2658+ if (e1 && e2)
2659+ {
2660+ auto ce = new CondExp(econd.loc, econd, e1, e2);
2661+
2662+ if (e1.type.ty == Tvoid || e2.type.ty == Tvoid)
2663+ ce.type = Type.tvoid;
2664+ else if (e1.type.ty == Tnoreturn)
2665+ ce.type = e2.type;
2666+ else
2667+ ce.type = e1.type;
2668+
2669+ if (ce.type.ty == Ttuple)
2670+ {
2671+ ce.e1.type = Type.tvoid;
2672+ ce.e2.type = Type.tvoid;
2673+ ce.type = Type.tvoid;
2674+ }
2675+
2676+ return ce;
2677+ }
2678+ else if (e1)
2679+ {
2680+ auto le = new LogicalExp(econd.loc, EXP .andAnd, econd, e1);
2681+ le.type = Type.tvoid;
2682+ return le;
2683+ }
2684+ else if (e2)
2685+ {
2686+ auto le = new LogicalExp(econd.loc, EXP .orOr, econd, e2);
2687+ le.type = Type.tvoid;
2688+ return le;
2689+ }
2690+
2691+ return econd;
2692+ }
0 commit comments