@@ -174,7 +174,7 @@ struct selection_sym {
174
174
struct compound_sym {
175
175
bool start = false ;
176
176
compound_statement_node const * compound = {};
177
- enum kind { is_scope, is_true, is_false } kind_ = is_scope;
177
+ enum kind { is_scope, is_true, is_false, is_loop } kind_ = is_scope;
178
178
179
179
compound_sym (
180
180
bool s,
@@ -373,6 +373,7 @@ class sema
373
373
index_t global_token_counter = 1 ;
374
374
375
375
std::vector<selection_statement_node const *> active_selections;
376
+ std::vector<iteration_statement_node const *> active_iterations;
376
377
std::vector<declaration_sym const *> current_declarations;
377
378
378
379
struct declaration_of_t {
@@ -648,10 +649,12 @@ class sema
648
649
else if (sym.kind_ == sym.is_false ) {
649
650
o << " false branch" ;
650
651
}
652
+ else if (sym.kind_ == sym.is_loop ) {
653
+ o << " loop" ;
654
+ }
651
655
else {
652
656
o << " scope" ;
653
657
}
654
-
655
658
}
656
659
657
660
break ;default :
@@ -1164,7 +1167,7 @@ class sema
1164
1167
{
1165
1168
auto name = decl->identifier ->to_string ();
1166
1169
1167
- struct stack_entry {
1170
+ struct selection_stack_entry {
1168
1171
int pos; // start of this selection statement
1169
1172
1170
1173
struct branch {
@@ -1175,17 +1178,34 @@ class sema
1175
1178
};
1176
1179
std::vector<branch> branches;
1177
1180
1178
- stack_entry (int p) : pos{p} { }
1181
+ selection_stack_entry (int p) : pos{p} { }
1179
1182
1180
1183
auto debug_print (std::ostream& o) const -> void
1181
1184
{
1182
- o << " Stack entry: " << pos << " \n " ;
1185
+ o << " Selection stack entry: " << pos << " \n " ;
1183
1186
for (auto const & e : branches) {
1184
1187
o << " ( " << e.start << " , " << e.result << " )\n " ;
1185
1188
}
1186
1189
}
1187
1190
};
1188
- std::vector<stack_entry> selection_stack;
1191
+ std::vector<selection_stack_entry> selection_stack;
1192
+
1193
+ std::vector<source_position> loop_stack; // start of each active loop
1194
+
1195
+
1196
+ auto record_result = [&](token const * t) -> bool {
1197
+ if (!loop_stack.empty ()) {
1198
+ errors.emplace_back (
1199
+ t->position (),
1200
+ " local variable " + name
1201
+ + " cannot be initialized inside a loop"
1202
+ );
1203
+ return false ;
1204
+ }
1205
+ definite_initializations.push_back (t);
1206
+ return true ;
1207
+ };
1208
+
1189
1209
1190
1210
for (
1191
1211
;
@@ -1236,7 +1256,9 @@ class sema
1236
1256
// just return true if it's an assignment to it, else return false
1237
1257
if (std::ssize (selection_stack) == 0 ) {
1238
1258
if (sym.standalone_assignment_to ) {
1239
- definite_initializations.push_back ( sym.identifier );
1259
+ if (!record_result (sym.identifier )) {
1260
+ return false ;
1261
+ }
1240
1262
}
1241
1263
else {
1242
1264
errors.emplace_back (
@@ -1254,7 +1276,9 @@ class sema
1254
1276
// if we weren't an a selection statement
1255
1277
if (std::ssize (selection_stack) == 1 ) {
1256
1278
if (sym.standalone_assignment_to ) {
1257
- definite_initializations.push_back ( sym.identifier );
1279
+ if (!record_result (sym.identifier )) {
1280
+ return false ;
1281
+ }
1258
1282
}
1259
1283
else {
1260
1284
errors.emplace_back (
@@ -1282,7 +1306,9 @@ class sema
1282
1306
// and record this as the result for the current branch
1283
1307
else {
1284
1308
if (sym.standalone_assignment_to ) {
1285
- definite_initializations.push_back ( sym.identifier );
1309
+ if (!record_result (sym.identifier )) {
1310
+ return false ;
1311
+ }
1286
1312
}
1287
1313
else {
1288
1314
errors.emplace_back (
@@ -1390,8 +1416,20 @@ class sema
1390
1416
break ;case symbol::active::compound: {
1391
1417
auto const & sym = std::get<symbol::active::compound>(symbols[pos].sym );
1392
1418
1393
- // If we're in a selection
1394
- if (std::ssize (selection_stack) > 0 ) {
1419
+ // Track loop entries/exits
1420
+ if (sym.kind_ == sym.is_loop )
1421
+ {
1422
+ if (sym.start ) {
1423
+ loop_stack.push_back ( sym.position () );
1424
+ }
1425
+ else {
1426
+ assert (!loop_stack.empty ());
1427
+ loop_stack.pop_back ();
1428
+ }
1429
+ }
1430
+
1431
+ // Else if we're at a selection
1432
+ else if (std::ssize (selection_stack) > 0 ) {
1395
1433
// If this is a compound start with the current selection's depth
1396
1434
// plus one, it's the start of one of the branches of that selection
1397
1435
if (
@@ -2316,6 +2354,7 @@ class sema
2316
2354
2317
2355
auto start (iteration_statement_node const & n, int ) -> void
2318
2356
{
2357
+ active_iterations.push_back (&n);
2319
2358
if (*n.identifier != " for" ) {
2320
2359
symbols.emplace_back ( scope_depth, identifier_sym ( false , n.identifier ) );
2321
2360
}
@@ -2324,6 +2363,7 @@ class sema
2324
2363
auto end (iteration_statement_node const & n, int ) -> void
2325
2364
{
2326
2365
symbols.emplace_back ( scope_depth, identifier_sym ( false , n.identifier , identifier_sym::deactivation ) );
2366
+ active_iterations.pop_back ();
2327
2367
}
2328
2368
2329
2369
auto start (loop_body_tag const & n, int ) -> void
@@ -2688,7 +2728,16 @@ class sema
2688
2728
-> compound_sym::kind
2689
2729
{
2690
2730
auto kind = compound_sym::is_scope;
2691
- if (!active_selections.empty ())
2731
+
2732
+ if (
2733
+ !active_iterations.empty ()
2734
+ && active_iterations.back ()->statements .get () == &n
2735
+ )
2736
+ {
2737
+ kind = compound_sym::is_loop;
2738
+ }
2739
+
2740
+ else if (!active_selections.empty ())
2692
2741
{
2693
2742
assert (active_selections.back ()->true_branch );
2694
2743
if (active_selections.back ()->true_branch .get () == &n)
@@ -2703,6 +2752,7 @@ class sema
2703
2752
kind = compound_sym::is_false;
2704
2753
}
2705
2754
}
2755
+
2706
2756
return kind;
2707
2757
}
2708
2758
0 commit comments