@@ -116,8 +116,8 @@ static void make_report(symbol *root,FILE *log,char *sourcefile);
116
116
static void reduce_referrers (symbol * root );
117
117
static long max_stacksize (symbol * root ,int * recursion );
118
118
static int testsymbols (symbol * root ,int level ,int testlabs ,int testconst );
119
- static void scanloopvariables (symstate * * loopvars );
120
- static void testloopvariables (symstate * loopvars ,int line );
119
+ static void scanloopvariables (symstate * * loopvars , int dowhile );
120
+ static void testloopvariables (symstate * loopvars ,int dowhile , int line );
121
121
static void destructsymbols (symbol * root ,int level );
122
122
static constvalue * find_constval_byval (constvalue_root * table ,cell val );
123
123
static symbol * fetchlab (char * name );
@@ -5177,7 +5177,7 @@ static int testsymbols(symbol *root,int level,int testlabs,int testconst)
5177
5177
return entry ;
5178
5178
}
5179
5179
5180
- static void scanloopvariables (symstate * * loopvars )
5180
+ static void scanloopvariables (symstate * * loopvars , int dowhile )
5181
5181
{
5182
5182
symbol * start ,* sym ;
5183
5183
int num ;
@@ -5187,9 +5187,10 @@ static void scanloopvariables(symstate **loopvars)
5187
5187
if (sc_status != statWRITE )
5188
5188
return ;
5189
5189
5190
- /* if there's only one active loop entry (the current loop),
5191
- * then there's no enclosing loop and we have an early exit */
5192
- if (wqptr - wqSIZE == wq )
5190
+ /* if there's no enclosing loop (only one active loop entry, which is the
5191
+ * current loop), and the current loop is not 'do-while', then we don't need
5192
+ * to memoize usage flags for local variables, so we have an early exit */
5193
+ if (wqptr - wqSIZE == wq && !dowhile )
5193
5194
return ;
5194
5195
5195
5196
/* skip labels */
@@ -5211,19 +5212,26 @@ static void scanloopvariables(symstate **loopvars)
5211
5212
error (103 ); /* insufficient memory */
5212
5213
5213
5214
for (num = 0 ,sym = start ; sym != NULL ; num ++ ,sym = sym -> next ) {
5214
- /* if the variable already has the uLOOPVAR flag set (from being used
5215
+ /* If the variable already has the uLOOPVAR flag set (from being used
5215
5216
* in an enclosing loop), we have to set the uNOLOOPVAR to exclude it
5216
- * from checks in the current loop */
5217
- if ((sym -> ident == iVARIABLE || sym -> ident == iREFERENCE ) && (sym -> usage & uLOOPVAR )!= 0 ) {
5218
- /* ... but it might be already set from an enclosing loop,
5219
- * so we need to temporarily store it in "loopvars[num]" first */
5220
- (* loopvars )[num ].usage |= (sym -> usage & uNOLOOPVAR );
5221
- sym -> usage |= uNOLOOPVAR ;
5217
+ * from checks in the current loop, ... */
5218
+ if ((sym -> ident == iVARIABLE || sym -> ident == iREFERENCE )
5219
+ && (dowhile || (sym -> usage & uLOOPVAR )!= 0 )) {
5220
+ /* ... but it might be already set from an enclosing loop as well, so we
5221
+ * have to temporarily store it in "loopvars[num]" first. Also, if this is
5222
+ * a 'do-while' loop, we need to memoize and unset the 'uWRITTEN' flag, so
5223
+ * later when analyzing the loop condition (which comes after the loop
5224
+ * body) we'll be able to determine if the variable was modified inside
5225
+ * the loop body by checking if the 'uWRITTEN' flag is set. */
5226
+ (* loopvars )[num ].usage |= (sym -> usage & (uNOLOOPVAR | uWRITTEN ));
5227
+ sym -> usage &= ~uWRITTEN ;
5228
+ if (wqptr - wqSIZE != wq )
5229
+ sym -> usage |= uNOLOOPVAR ;
5222
5230
} /* if */
5223
5231
} /* if */
5224
5232
}
5225
5233
5226
- static void testloopvariables (symstate * loopvars ,int line )
5234
+ static void testloopvariables (symstate * loopvars ,int dowhile , int line )
5227
5235
{
5228
5236
symbol * start ,* sym ;
5229
5237
int num ,warnnum = 0 ;
@@ -5245,7 +5253,8 @@ static void testloopvariables(symstate *loopvars,int line)
5245
5253
warnnum = (pc_numloopvars == 1 ) ? 250 : 251 ;
5246
5254
for (sym = start ; sym != NULL ; sym = sym -> next )
5247
5255
if ((sym -> ident == iVARIABLE || sym -> ident == iREFERENCE )
5248
- && (sym -> usage & (uLOOPVAR | uNOLOOPVAR ))== uLOOPVAR )
5256
+ && (sym -> usage & (uLOOPVAR | uNOLOOPVAR ))== uLOOPVAR
5257
+ && (!dowhile || (sym -> usage & uWRITTEN )== 0 ))
5249
5258
pc_numloopvars -- ;
5250
5259
if (pc_numloopvars == 0 && warnnum == 251 ) {
5251
5260
errorset (sSETPOS ,line );
@@ -5268,7 +5277,7 @@ static void testloopvariables(symstate *loopvars,int line)
5268
5277
} /* if */
5269
5278
sym -> usage &= ~uNOLOOPVAR ;
5270
5279
if (loopvars != NULL )
5271
- sym -> usage |= ( loopvars [num ].usage & uNOLOOPVAR ) ;
5280
+ sym -> usage |= loopvars [num ].usage ;
5272
5281
} /* if */
5273
5282
} /* for */
5274
5283
free (loopvars );
@@ -6039,17 +6048,17 @@ static int dowhile(void)
6039
6048
* tiniest loop, set it below the top of the loop
6040
6049
*/
6041
6050
setline (TRUE);
6042
- scanloopvariables (& loopvars );
6051
+ scanloopvariables (& loopvars ,FALSE );
6043
6052
pc_nestlevel ++ ; /* temporarily increase the "compound statement" nesting level,
6044
6053
* so any assignments made inside the loop control expression
6045
6054
* could be cleaned up later */
6046
- pc_loopcond = TRUE ;
6055
+ pc_loopcond = tWHILE ;
6047
6056
endlessloop = test (wq [wqEXIT ],TEST_DO ,FALSE);/* branch to wq[wqEXIT] if false */
6048
- pc_loopcond = FALSE ;
6057
+ pc_loopcond = 0 ;
6049
6058
pc_nestlevel -- ;
6050
6059
statement (NULL ,FALSE); /* if so, do a statement */
6051
6060
clearassignments (pc_nestlevel + 1 );
6052
- testloopvariables (loopvars ,loopline );
6061
+ testloopvariables (loopvars ,FALSE, loopline );
6053
6062
jumplabel (wq [wqLOOP ]); /* and loop to "while" start */
6054
6063
setlabel (wq [wqEXIT ]); /* exit label */
6055
6064
delwhile (); /* delete queue entry */
@@ -6067,32 +6076,37 @@ static int dowhile(void)
6067
6076
static int dodo (void )
6068
6077
{
6069
6078
int wq [wqSIZE ],top ;
6070
- int save_endlessloop ,retcode ;
6079
+ int save_endlessloop ,save_numloopvars , retcode ;
6071
6080
int loopline = fline ;
6072
6081
symstate * loopvars = NULL ;
6073
6082
6074
6083
save_endlessloop = endlessloop ;
6084
+ save_numloopvars = pc_numloopvars ;
6085
+ pc_numloopvars = 0 ;
6075
6086
addwhile (wq ); /* see "dowhile" for more info */
6076
6087
top = getlabel (); /* make a label first */
6077
6088
setlabel (top ); /* loop label */
6089
+ scanloopvariables (& loopvars ,TRUE);
6078
6090
statement (NULL ,FALSE);
6079
6091
needtoken (tWHILE );
6080
6092
setlabel (wq [wqLOOP ]); /* "continue" always jumps to WQLOOP. */
6081
6093
setline (TRUE);
6082
- scanloopvariables (& loopvars );
6083
6094
pc_nestlevel ++ ; /* temporarily increase the "compound statement" nesting level,
6084
6095
* so any assignments made inside the loop control expression
6085
6096
* could be cleaned up later */
6097
+ pc_loopcond = tDO ;
6086
6098
endlessloop = test (wq [wqEXIT ],TEST_OPT ,FALSE);
6099
+ pc_loopcond = 0 ;
6087
6100
pc_nestlevel -- ;
6088
6101
clearassignments (pc_nestlevel + 1 );
6089
- testloopvariables (loopvars ,loopline );
6102
+ testloopvariables (loopvars ,TRUE, loopline );
6090
6103
jumplabel (top );
6091
6104
setlabel (wq [wqEXIT ]);
6092
6105
delwhile ();
6093
6106
needtoken (tTERM );
6094
6107
6095
6108
retcode = endlessloop ? tENDLESS : tDO ;
6109
+ pc_numloopvars = save_numloopvars ;
6096
6110
endlessloop = save_endlessloop ;
6097
6111
return retcode ;
6098
6112
}
@@ -6144,7 +6158,7 @@ static int dofor(void)
6144
6158
jumplabel (skiplab ); /* skip expression 3 1st time */
6145
6159
setlabel (wq [wqLOOP ]); /* "continue" goes to this label: expr3 */
6146
6160
setline (TRUE);
6147
- scanloopvariables (& loopvars );
6161
+ scanloopvariables (& loopvars ,FALSE );
6148
6162
/* Expressions 2 and 3 are reversed in the generated code: expression 3
6149
6163
* precedes expression 2. When parsing, the code is buffered and marks for
6150
6164
* the start of each expression are insterted in the buffer.
@@ -6159,9 +6173,9 @@ static int dofor(void)
6159
6173
if (matchtoken (';' )) {
6160
6174
endlessloop = 1 ;
6161
6175
} else {
6162
- pc_loopcond = TRUE ;
6176
+ pc_loopcond = tFOR ;
6163
6177
endlessloop = test (wq [wqEXIT ],TEST_PLAIN ,FALSE);/* expression 2 (jump to wq[wqEXIT] if false) */
6164
- pc_loopcond = FALSE ;
6178
+ pc_loopcond = 0 ;
6165
6179
needtoken (';' );
6166
6180
} /* if */
6167
6181
stgmark ((char )(sEXPRSTART + 1 )); /* mark start of 3th expression in stage */
@@ -6174,7 +6188,7 @@ static int dofor(void)
6174
6188
stgset (FALSE); /* stop staging */
6175
6189
statement (NULL ,FALSE);
6176
6190
clearassignments (save_nestlevel + 1 );
6177
- testloopvariables (loopvars ,loopline );
6191
+ testloopvariables (loopvars ,FALSE, loopline );
6178
6192
jumplabel (wq [wqLOOP ]);
6179
6193
setlabel (wq [wqEXIT ]);
6180
6194
delwhile ();
0 commit comments