From 08c903292732cc6a1377f28359a6a5ce723b58da Mon Sep 17 00:00:00 2001 From: Artur Bieniek Date: Tue, 22 Sep 2026 17:36:20 +0200 Subject: [PATCH] Fix internal error when task without CFunc is left in the tree (#8437) Signed-off-by: Artur Bieniek --- src/V3Task.cpp | 12 ++++++++++++ test_regress/t/t_dpi_argtype_bad.v | 2 ++ test_regress/t/t_dpi_dup_bad.out | 7 +++++++ test_regress/t/t_dpi_dup_bad.v | 13 +++++++++++++ 4 files changed, 34 insertions(+) diff --git a/src/V3Task.cpp b/src/V3Task.cpp index a089d3942..631d4a6db 100644 --- a/src/V3Task.cpp +++ b/src/V3Task.cpp @@ -1629,6 +1629,18 @@ class TaskVisitor final : public VNVisitor { // Includes handling AstMethodCall, AstNew UASSERT_OBJ(nodep->taskp(), nodep, "Unlinked?"); iterateIntoFTask(nodep->taskp()); // First, do hierarchical funcs + if (m_statep->ftaskNoInline(nodep->taskp()) && !m_statep->ftaskCFuncp(nodep->taskp())) { + // An earlier error (e.g. a DPI import declared twice with conflicting + // signatures) prevented creating the function, so remove the call + UASSERT_OBJ(V3Error::errorCount(), nodep, "No non-inline task, but no error issued"); + if (VN_IS(nodep->backp(), StmtExpr)) { + VL_DO_DANGLING(pushDeletep(nodep->unlinkFrBack()), nodep); + } else { + nodep->replaceWith(new AstConst{nodep->fileline(), AstConst::BitFalseErroring{}}); + VL_DO_DANGLING(pushDeletep(nodep), nodep); + } + return; + } UINFO(4, " FTask REF " << nodep); UINFOTREE(9, nodep, "", "inlfunc"); UASSERT_OBJ(m_scopep, nodep, "func ref not under scope"); diff --git a/test_regress/t/t_dpi_argtype_bad.v b/test_regress/t/t_dpi_argtype_bad.v index f0afe58e8..e9ba8616d 100644 --- a/test_regress/t/t_dpi_argtype_bad.v +++ b/test_regress/t/t_dpi_argtype_bad.v @@ -14,7 +14,9 @@ module t; } foo_t; import "DPI-C" task dpix_twice(foo_t arg); + foo_t f; initial begin + dpix_twice(f); $stop; end endmodule diff --git a/test_regress/t/t_dpi_dup_bad.out b/test_regress/t/t_dpi_dup_bad.out index f901051f6..aad0c185b 100644 --- a/test_regress/t/t_dpi_dup_bad.out +++ b/test_regress/t/t_dpi_dup_bad.out @@ -6,4 +6,11 @@ 12 | import "DPI-C" dpii_fa_bit = function int oth_f_int1(input int i); | ^~~~~~~~~~ ... See the manual at https://verilator.org/verilator_doc.html?v=latest for more assistance. +%Error: t/t_dpi_dup_bad.v:19:47: Duplicate declaration of DPI function with different signature: 'dpii_fa_void' + 19 | import "DPI-C" dpii_fa_void = function void oth_f_void2( + | ^~~~~~~~~~~ + : ... New signature: void dpii_fa_void (int, int) + t/t_dpi_dup_bad.v:18:47: ... Original signature: void dpii_fa_void (int) + 18 | import "DPI-C" dpii_fa_void = function void oth_f_void1(input int i); + | ^~~~~~~~~~~ %Error: Exiting due to diff --git a/test_regress/t/t_dpi_dup_bad.v b/test_regress/t/t_dpi_dup_bad.v index e55ff9959..c515bc715 100644 --- a/test_regress/t/t_dpi_dup_bad.v +++ b/test_regress/t/t_dpi_dup_bad.v @@ -14,7 +14,20 @@ module t; input int i, input int bad); + // Same, but void so the call sits in statement position + import "DPI-C" dpii_fa_void = function void oth_f_void1(input int i); + import "DPI-C" dpii_fa_void = function void oth_f_void2( + input int i, + input int bad); + + int o1; + int o2; + initial begin + o1 = oth_f_int1(1); + o2 = oth_f_int2(1, 2); + oth_f_void1(1); + oth_f_void2(1, 2); $stop; end