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 <lars@metafoo.de>
This commit is contained in:
parent
aa8f928ffa
commit
d1e0fa7da0
|
|
@ -254,7 +254,8 @@ class PCallTask : public Statement {
|
||||||
NetProc*elaborate_function_(Design*des, NetScope*scope) const;
|
NetProc*elaborate_function_(Design*des, NetScope*scope) const;
|
||||||
NetProc*elaborate_void_function_(Design*des, NetScope*scope,
|
NetProc*elaborate_void_function_(Design*des, NetScope*scope,
|
||||||
NetFuncDef*def) const;
|
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,
|
NetProc*elaborate_build_call_(Design*des, NetScope*scope,
|
||||||
NetScope*task, NetExpr*use_this) const;
|
NetScope*task, NetExpr*use_this) const;
|
||||||
|
|
|
||||||
23
elaborate.cc
23
elaborate.cc
|
|
@ -3850,7 +3850,7 @@ NetProc* PCallTask::elaborate(Design*des, NetScope*scope) const
|
||||||
{
|
{
|
||||||
if (peek_tail_name(path_)[0] == '$') {
|
if (peek_tail_name(path_)[0] == '$') {
|
||||||
if (void_cast_)
|
if (void_cast_)
|
||||||
return elaborate_non_void_function_(des, scope);
|
return elaborate_non_void_function_(des, scope, path_);
|
||||||
else
|
else
|
||||||
return elaborate_sys(des, scope);
|
return elaborate_sys(des, scope);
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -4571,6 +4571,14 @@ NetProc* PCallTask::elaborate_method_(Design*des, NetScope*scope,
|
||||||
<< " method " << task->basename() << endl;
|
<< " 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);
|
NetESignal*use_this = new NetESignal(net);
|
||||||
use_this->set_line(*this);
|
use_this->set_line(*this);
|
||||||
|
|
||||||
|
|
@ -4605,17 +4613,18 @@ bool PCallTask::test_task_calls_ok_(Design*des, const NetScope*scope) const
|
||||||
return true;
|
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.
|
// 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);
|
rval->set_line(*this);
|
||||||
// Generate an assign to nothing.
|
// Generate an assign to nothing.
|
||||||
PAssign*tmp = new PAssign(0, rval);
|
auto tmp = new PAssign(nullptr, rval);
|
||||||
tmp->set_line(*this);
|
tmp->set_line(*this);
|
||||||
if (!void_cast_) {
|
if (!void_cast_) {
|
||||||
cerr << get_fileline() << ": warning: User function '"
|
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.
|
// 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())
|
if (gn_system_verilog() && func->is_void())
|
||||||
return elaborate_void_function_(des, scope, func);
|
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,
|
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) {
|
} else if (task->type() == NetScope::FUNC) {
|
||||||
const NetFuncDef*tmp = task->func_def();
|
const NetFuncDef*tmp = task->func_def();
|
||||||
if (!tmp->is_void())
|
if (!tmp->is_void())
|
||||||
return elaborate_non_void_function_(des, scope);
|
return elaborate_non_void_function_(des, scope, path_);
|
||||||
def = tmp;
|
def = tmp;
|
||||||
|
|
||||||
if (void_cast_) {
|
if (void_cast_) {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue