From d1e0fa7da0e43b3738b30e124fc41d95b8f9da1c Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Thu, 6 Aug 2026 23:13:47 -0700 Subject: [PATCH] Handle inherited non-void function calls as statements The LRM section 13.4.1 permits a non-void function call to be used as a statement and requires a warning when the return value is implicitly discarded. A bare call to an inherited class function currently emits that warning and then aborts. Method lookup finds the inherited function through the implicit `this` receiver. The discarded-result path then rebuilds a `PECallFunction` from the original bare name, losing the receiver and leaving the expression without a type. Pass the resolved method path to the discarded-result path so the rebuilt call remains qualified by `this`. Signed-off-by: Lars-Peter Clausen --- Statement.h | 3 ++- elaborate.cc | 23 ++++++++++++++++------- 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/Statement.h b/Statement.h index 36495b7a7..b1f77678e 100644 --- a/Statement.h +++ b/Statement.h @@ -254,7 +254,8 @@ class PCallTask : public Statement { NetProc*elaborate_function_(Design*des, NetScope*scope) const; NetProc*elaborate_void_function_(Design*des, NetScope*scope, NetFuncDef*def) const; - NetProc *elaborate_non_void_function_(Design *des, NetScope *scope) const; + NetProc *elaborate_non_void_function_(Design *des, NetScope *scope, + const pform_name_t &path) const; NetProc*elaborate_build_call_(Design*des, NetScope*scope, NetScope*task, NetExpr*use_this) const; diff --git a/elaborate.cc b/elaborate.cc index a8cb2e388..fd195c606 100644 --- a/elaborate.cc +++ b/elaborate.cc @@ -3850,7 +3850,7 @@ NetProc* PCallTask::elaborate(Design*des, NetScope*scope) const { if (peek_tail_name(path_)[0] == '$') { if (void_cast_) - return elaborate_non_void_function_(des, scope); + return elaborate_non_void_function_(des, scope, path_); else return elaborate_sys(des, scope); } else { @@ -4571,6 +4571,14 @@ NetProc* PCallTask::elaborate_method_(Design*des, NetScope*scope, << " method " << task->basename() << endl; } + /* Preserve the resolved object path, including an implicit this, + * when rebuilding a non-void function call as an expression. */ + if (task->type() == NetScope::FUNC && + !task->func_def()->is_void()) { + use_path.push_back(name_component_t(method_name)); + return elaborate_non_void_function_(des, scope, use_path); + } + NetESignal*use_this = new NetESignal(net); use_this->set_line(*this); @@ -4605,17 +4613,18 @@ bool PCallTask::test_task_calls_ok_(Design*des, const NetScope*scope) const return true; } -NetProc *PCallTask::elaborate_non_void_function_(Design *des, NetScope *scope) const +NetProc *PCallTask::elaborate_non_void_function_(Design *des, NetScope *scope, + const pform_name_t &path) const { // Generate a function call version of this task call. - PExpr*rval = new PECallFunction(package_, path_, parms_); + auto rval = new PECallFunction(package_, path, parms_); rval->set_line(*this); // Generate an assign to nothing. - PAssign*tmp = new PAssign(0, rval); + auto tmp = new PAssign(nullptr, rval); tmp->set_line(*this); if (!void_cast_) { cerr << get_fileline() << ": warning: User function '" - << peek_tail_name(path_) << "' is being called as a task." << endl; + << peek_tail_name(path) << "' is being called as a task." << endl; } // Elaborate the assignment to a dummy variable. @@ -4634,7 +4643,7 @@ NetProc* PCallTask::elaborate_function_(Design*des, NetScope*scope) const if (gn_system_verilog() && func->is_void()) return elaborate_void_function_(des, scope, func); - return elaborate_non_void_function_(des, scope); + return elaborate_non_void_function_(des, scope, path_); } NetProc* PCallTask::elaborate_void_function_(Design*des, NetScope*scope, @@ -4681,7 +4690,7 @@ NetProc* PCallTask::elaborate_build_call_(Design*des, NetScope*scope, } else if (task->type() == NetScope::FUNC) { const NetFuncDef*tmp = task->func_def(); if (!tmp->is_void()) - return elaborate_non_void_function_(des, scope); + return elaborate_non_void_function_(des, scope, path_); def = tmp; if (void_cast_) {