diff --git a/Statement.h b/Statement.h index 50ee2f2fd..613f2d64b 100644 --- a/Statement.h +++ b/Statement.h @@ -226,6 +226,8 @@ class PCallTask : public Statement { bool elaborate_elab(Design*des, NetScope*scope) const; + void void_cast() { void_cast_ = true; } + private: NetProc* elaborate_sys(Design*des, NetScope*scope) const; NetProc* elaborate_usr(Design*des, NetScope*scope) const; @@ -257,6 +259,7 @@ class PCallTask : public Statement { PPackage*package_; pform_name_t path_; std::vector parms_; + bool void_cast_ = false; }; class PCase : public Statement { diff --git a/elaborate.cc b/elaborate.cc index 9d5ef8877..02d782e97 100644 --- a/elaborate.cc +++ b/elaborate.cc @@ -3390,10 +3390,14 @@ NetProc* PCondit::elaborate(Design*des, NetScope*scope) const NetProc* PCallTask::elaborate(Design*des, NetScope*scope) const { - if (peek_tail_name(path_)[0] == '$') - return elaborate_sys(des, scope); - else + if (peek_tail_name(path_)[0] == '$') { + if (void_cast_) + return elaborate_non_void_function_(des, scope); + else + return elaborate_sys(des, scope); + } else { return elaborate_usr(des, scope); + } } /* @@ -3690,8 +3694,10 @@ NetProc* PCallTask::elaborate_method_func_(NetScope*scope, perm_string method_name, const char*sys_task_name) const { - cerr << get_fileline() << ": warning: method function '" - << method_name << "' is being called as a task." << endl; + if (!void_cast_) { + cerr << get_fileline() << ": warning: method function '" + << method_name << "' is being called as a task." << endl; + } // Generate the function. NetESFunc*sys_expr = new NetESFunc(sys_task_name, type, 1); @@ -3906,8 +3912,11 @@ NetProc *PCallTask::elaborate_non_void_function_(Design *des, NetScope *scope) c PAssign*tmp = new PAssign(0, rval); tmp->set_file(get_file()); tmp->set_lineno(get_lineno()); - cerr << get_fileline() << ": warning: User function '" - << peek_tail_name(path_) << "' is being called as a task." << endl; + if (!void_cast_) { + cerr << get_fileline() << ": warning: User function '" + << peek_tail_name(path_) << "' is being called as a task." << endl; + } + // Elaborate the assignment to a dummy variable. return tmp->elaborate(des, scope); } @@ -3962,11 +3971,23 @@ NetProc* PCallTask::elaborate_build_call_(Design*des, NetScope*scope, // that we can catch more errors. test_task_calls_ok_(des, scope); + if (void_cast_) { + cerr << get_fileline() << ": error: void casting user task '" + << peek_tail_name(path_) << "' is not allowed." << endl; + des->errors++; + } + } else if (task->type() == NetScope::FUNC) { NetFuncDef*tmp = task->func_def(); if (!tmp->is_void()) return elaborate_non_void_function_(des, scope); def = tmp; + + if (void_cast_) { + cerr << get_fileline() << ": error: void casting user void function '" + << peek_tail_name(path_) << "' is not allowed." << endl; + des->errors++; + } } /* The caller has checked the parms_ size to make sure it diff --git a/parse.y b/parse.y index 409b359a8..19b1577d8 100644 --- a/parse.y +++ b/parse.y @@ -420,6 +420,8 @@ static void current_function_set_statement(const YYLTYPE&loc, std::vector*wires; + PCallTask *subroutine_call; + PEventStatement*event_statement; Statement*statement; std::vector*statement_list; @@ -685,6 +687,8 @@ static void current_function_set_statement(const YYLTYPE&loc, std::vector analog_statement +%type subroutine_call + %type join_keyword %type spec_polarity @@ -6241,6 +6245,35 @@ spec_notifier { args_after_notifier = 0; delete[]$1; } ; +subroutine_call + : hierarchy_identifier argument_list_parens_opt + { PCallTask*tmp = pform_make_call_task(@1, *$1, *$2); + delete $1; + delete $2; + $$ = tmp; + } + | class_hierarchy_identifier argument_list_parens_opt + { PCallTask*tmp = new PCallTask(*$1, *$2); + FILE_NAME(tmp, @1); + delete $1; + delete $2; + $$ = tmp; + } + | SYSTEM_IDENTIFIER argument_list_parens_opt + { PCallTask*tmp = new PCallTask(lex_strings.make($1), *$2); + FILE_NAME(tmp,@1); + delete[]$1; + delete $2; + $$ = tmp; + } + | hierarchy_identifier '(' error ')' + { yyerror(@3, "error: Syntax error in task arguments."); + listpt; + PCallTask*tmp = pform_make_call_task(@1, *$1, pt); + delete $1; + $$ = tmp; + } + ; statement_item /* This is roughly statement_item in the LRM */ @@ -6592,19 +6625,13 @@ statement_item /* This is roughly statement_item in the LRM */ FILE_NAME(tmp,@1); $$ = tmp; } - | SYSTEM_IDENTIFIER argument_list_parens_opt ';' - { PCallTask*tmp = new PCallTask(lex_strings.make($1), *$2); - FILE_NAME(tmp,@1); - delete[]$1; - delete $2; - $$ = tmp; - } + | K_void '\'' '(' subroutine_call ')' ';' + { $4->void_cast(); + $$ = $4; + } - | hierarchy_identifier argument_list_parens_opt ';' - { PCallTask*tmp = pform_make_call_task(@1, *$1, *$2); - delete $1; - delete $2; - $$ = tmp; + | subroutine_call ';' + { $$ = $1; } | hierarchy_identifier K_with '{' constraint_block_item_list_opt '}' ';' @@ -6622,14 +6649,6 @@ statement_item /* This is roughly statement_item in the LRM */ $$ = tmp; } - | class_hierarchy_identifier argument_list_parens_opt ';' - { PCallTask*tmp = new PCallTask(*$1, *$2); - FILE_NAME(tmp, @1); - delete $1; - delete $2; - $$ = tmp; - } - /* IEEE1800 A.1.8: class_constructor_declaration with a call to parent constructor. Note that the implicit_class_handle must be K_super ("this.new" makes little sense) but that would @@ -6646,14 +6665,6 @@ statement_item /* This is roughly statement_item in the LRM */ delete $1; $$ = tmp; } - | hierarchy_identifier '(' error ')' ';' - { yyerror(@3, "error: Syntax error in task arguments."); - listpt; - PCallTask*tmp = pform_make_call_task(@1, *$1, pt); - delete $1; - $$ = tmp; - } - | error ';' { yyerror(@2, "error: malformed statement"); yyerrok;