diff --git a/elaborate.cc b/elaborate.cc index 410e30eff..321375ffc 100644 --- a/elaborate.cc +++ b/elaborate.cc @@ -5613,7 +5613,7 @@ NetProc* PForeach::elaborate_static_array_(Design*des, NetScope*scope, * * - index variable (name1_) (optional) * - initial value (expr1_) (only if name1_ is present) - * - condition expression (cond_) + * - condition expression (cond_) (optional) * - step statement (step_) (optional) * - sub-statement (statement_) * @@ -5693,12 +5693,15 @@ NetProc* PForStatement::elaborate(Design*des, NetScope*scope) const // Elaborate the condition expression. Try to evaluate it too, // in case it is a constant. This is an interesting case // worthy of a warning. - NetExpr*ce = elab_and_eval(des, scope, cond_, -1); - if (!ce) - error_flag = true; - if (dynamic_cast(ce)) { - cerr << get_fileline() << ": warning: condition expression " - "of for-loop is constant." << endl; + NetExpr*ce = nullptr; + if (cond_) { + ce = elab_and_eval(des, scope, cond_, -1); + if (!ce) + error_flag = true; + if (dynamic_cast(ce)) { + cerr << get_fileline() << ": warning: condition expression " + "of for-loop is constant." << endl; + } } // Error recovery - if we failed to elaborate any of the loop diff --git a/parse.y b/parse.y index f7bf42aef..002db27e5 100644 --- a/parse.y +++ b/parse.y @@ -728,7 +728,7 @@ Module::port_t *module_declare_port(const YYLTYPE&loc, char *id, %type timeskew_fullskew_opt_notifier timeskew_fullskew_opt_event_based_flag %type timeskew_fullskew_opt_remain_active_flag -%type assignment_pattern expression expr_mintypmax +%type assignment_pattern expression expression_opt expr_mintypmax %type expr_primary_or_typename expr_primary %type class_new dynamic_array_new %type var_decl_initializer_opt initializer_opt @@ -1754,7 +1754,7 @@ lifetime_opt /* IEEE1800-2005: A.2.1.3 */ /* Loop statements are kinds of statements. */ loop_statement /* IEEE1800-2005: A.6.8 */ - : K_for '(' lpvalue '=' expression ';' expression ';' for_step_opt ')' + : K_for '(' lpvalue '=' expression ';' expression_opt ';' for_step_opt ')' statement_or_null { PForStatement*tmp = new PForStatement($3, $5, $7, $9, $11); FILE_NAME(tmp, @1); @@ -1762,7 +1762,7 @@ loop_statement /* IEEE1800-2005: A.6.8 */ } // The initialization statement is optional. - | K_for '(' ';' expression ';' for_step_opt ')' + | K_for '(' ';' expression_opt ';' for_step_opt ')' statement_or_null { PForStatement*tmp = new PForStatement(nullptr, nullptr, $4, $6, $8); FILE_NAME(tmp, @1); @@ -1773,7 +1773,7 @@ loop_statement /* IEEE1800-2005: A.6.8 */ // statement in a synthetic named block. We can name the block // after the variable that we are creating, that identifier is // safe in the controlling scope. - | K_for '(' K_var_opt data_type IDENTIFIER '=' expression ';' expression ';' for_step_opt ')' + | K_for '(' K_var_opt data_type IDENTIFIER '=' expression ';' expression_opt ';' for_step_opt ')' { static unsigned for_counter = 0; char for_block_name [64]; snprintf(for_block_name, sizeof for_block_name, "$ivl_for_loop%u", for_counter); @@ -1858,7 +1858,7 @@ loop_statement /* IEEE1800-2005: A.6.8 */ /* Error forms for loop statements. */ - | K_for '(' lpvalue '=' expression ';' expression ';' error ')' + | K_for '(' lpvalue '=' expression ';' expression_opt ';' error ')' statement_or_null { $$ = 0; yyerror(@1, "error: Error in for loop step assignment."); @@ -3682,6 +3682,11 @@ expression } ; +expression_opt + : expression { $$ = $1; } + | { $$ = nullptr; } + ; + expr_mintypmax : expression { $$ = $1; } diff --git a/t-dll-api.cc b/t-dll-api.cc index acb0e6935..0e2578bb1 100644 --- a/t-dll-api.cc +++ b/t-dll-api.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2021 Stephen Williams (steve@icarus.com) + * Copyright (c) 2000-2024 Stephen Williams (steve@icarus.com) * Copyright CERN 2013 / Stephen Williams (steve@icarus.com) * Copyright (c) 2016 CERN Michele Castellana (michele.castellana@cern.ch) * @@ -2822,7 +2822,6 @@ extern "C" ivl_expr_t ivl_stmt_cond_expr(ivl_statement_t net) return net->u_.while_.cond_; case IVL_ST_FORLOOP: - assert(net->u_.forloop_.condition); // XXXX return net->u_.forloop_.condition; default: diff --git a/tgt-vvp/vvp_proc_loops.c b/tgt-vvp/vvp_proc_loops.c index a4ca55b7a..7c03b0d9d 100644 --- a/tgt-vvp/vvp_proc_loops.c +++ b/tgt-vvp/vvp_proc_loops.c @@ -121,10 +121,12 @@ int show_stmt_forloop(ivl_statement_t net, ivl_scope_t scope) /* Top of the loop, draw the condition test. */ fprintf(vvp_out, "T_%u.%u ; Top of for-loop\n", thread_count, top_label); - int use_flag = draw_eval_condition(ivl_stmt_cond_expr(net)); - fprintf(vvp_out, " %%jmp/0xz T_%u.%u, %d;\n", - thread_count, out_label, use_flag); - clr_flag(use_flag); + if (ivl_stmt_cond_expr(net)) { + int use_flag = draw_eval_condition(ivl_stmt_cond_expr(net)); + fprintf(vvp_out, " %%jmp/0xz T_%u.%u, %d;\n", + thread_count, out_label, use_flag); + clr_flag(use_flag); + } /* Draw the body of the loop. */ rc += show_statement(ivl_stmt_sub_stmt(net), scope);