11/**
2+ * Global loop optimizations
3+ *
24 * Compiler implementation of the
35 * $(LINK2 http://www.dlang.org, D programming language).
46 *
1012 * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/backend/gloop.d
1113 */
1214
13-
1415module dmd.backend.gloop ;
1516
1617version (SCPP)
@@ -76,6 +77,7 @@ nothrow:
7677 /* ************************
7778 * Reset memory so this allocation can be re-used.
7879 */
80+ @trusted
7981 void reset ()
8082 {
8183 vec_free(Lloop);
@@ -149,7 +151,7 @@ nothrow:
149151 }
150152}
151153
152- @trusted
154+ @system
153155enum FLELIM = cast (Symbol * )- 1 ;
154156
155157struct Iv
@@ -159,6 +161,7 @@ nothrow:
159161 elem ** IVincr; // pointer to parent of IV increment elem
160162 Barray! famlist IVfamily; // variables in this family
161163
164+ @trusted
162165 void reset ()
163166 {
164167 foreach (ref fl; IVfamily)
@@ -2843,6 +2846,9 @@ private void elimbasivs(ref loop l)
28432846 if (! biv.IVfamily.length)
28442847 continue ;
28452848
2849+ if (catchRef(X, l))
2850+ continue ;
2851+
28462852 elem* ref_ = * pref;
28472853
28482854 /* Replace (X) with (X != 0) */
@@ -3135,7 +3141,6 @@ private void elimbasivs(ref loop l)
31353141 } /* for */
31363142}
31373143
3138-
31393144/* **********************
31403145 * Eliminate opeq IVs that are not used outside the loop.
31413146 */
@@ -3343,6 +3348,39 @@ Lf2:
33433348 return false ;
33443349}
33453350
3351+ /* ****************************
3352+ * If loop is in a try block, see if there are references to x in an enclosing
3353+ * try block. This is because the loop may throw and transfer control
3354+ * outside the try block, and that will count as a use of x.
3355+ * Params:
3356+ * x = basic induction variable symbol
3357+ * l = loop x is in
3358+ * Returns:
3359+ * true if x is used outside the try block
3360+ */
3361+ @trusted
3362+ private bool catchRef (Symbol* x, ref loop l)
3363+ {
3364+ block* btry = l.Lhead.Btry;
3365+ if (! btry)
3366+ return false ; // not in a try block
3367+
3368+ foreach (i, b; dfo[])
3369+ {
3370+ if (vec_testbit(b.Bdfoidx, l.Lloop))
3371+ continue ;
3372+ /* this is conservative, just checking if x is used outside the loop.
3373+ * A better check would see if the body of the loop throws, and would
3374+ * check the enclosing catch/finally blocks and their exit blocks.
3375+ * https://issues.dlang.org/show_bug.cgi?22104
3376+ */
3377+ if (vec_testbit(x.Ssymnum, b.Binlv))
3378+ return true ;
3379+ }
3380+
3381+ return false ;
3382+ }
3383+
33463384/* ***********************************
33473385 * Input:
33483386 * x basic IV symbol
0 commit comments