diff --git a/src/V3LinkCells.cpp b/src/V3LinkCells.cpp index 48134d037..4393a6955 100644 --- a/src/V3LinkCells.cpp +++ b/src/V3LinkCells.cpp @@ -310,7 +310,8 @@ class LinkCellsVisitor final : public VNVisitor { const string prettyName = AstNode::prettyName(modName); V3Parse parser{v3Global.rootp(), m_filterp}; // true below -> other simulators treat modules in link-found files as library cells - parser.parseFile(nodep->fileline(), prettyName, true, false, m_modp->libname(), ""); + parser.parseFile(nodep->fileline(), prettyName, true, false, m_modp->libname(), "", + modName); V3Error::abortIfErrors(); // We've read new modules, grab new pointers to their names readModNames(); diff --git a/src/V3Parse.h b/src/V3Parse.h index 0ba12d6de..0dd2e2946 100644 --- a/src/V3Parse.h +++ b/src/V3Parse.h @@ -43,7 +43,8 @@ public: // METHODS // Preprocess and read the Verilog file specified into the netlist database void parseFile(FileLine* fileline, const string& modname, bool inLibrary, bool inLibMap, - const string& libname, const string& errmsg) VL_MT_DISABLED; + const string& libname, const string& errmsg, + const std::string& notFoundName = "") VL_MT_DISABLED; // Push preprocessed text to the lexer static void ppPushText(V3ParseImp* impp, const string& text) VL_MT_DISABLED; diff --git a/src/V3ParseImp.cpp b/src/V3ParseImp.cpp index fe14577e9..7cf4e76e6 100644 --- a/src/V3ParseImp.cpp +++ b/src/V3ParseImp.cpp @@ -307,9 +307,12 @@ void V3ParseImp::preprocDumps(std::ostream& os, bool forInputs) { if (forInputs && anyNonVerilog) os << "\n`verilog\n"; } -void V3ParseImp::parseFile(FileLine* fileline, const string& modfilename, bool inLibrary, - bool inLibMap, const string& libname, - const string& errmsg) { // "" for no error, make fake node +void V3ParseImp::parseFile( + FileLine* fileline, const string& modfilename, bool inLibrary, bool inLibMap, + const string& libname, + const string& errmsg, // "" for no error, make fake node + const std::string& notFoundName) { // name for AstNotFoundModule - modfilename will be used if + // notFoundName is empty const string nondirname = V3Os::filenameNonDir(modfilename); const string modname = V3Os::filenameNonDirExt(modfilename); @@ -327,7 +330,8 @@ void V3ParseImp::parseFile(FileLine* fileline, const string& modfilename, bool i if (!ok) { if (errmsg != "") return; // Threw error already // Create fake node for later error reporting - AstNodeModule* const nodep = new AstNotFoundModule{fileline, modname, libname}; + AstNodeModule* const nodep = new AstNotFoundModule{ + fileline, notFoundName.empty() ? modname : notFoundName, libname}; v3Global.rootp()->addModulesp(nodep); return; } @@ -893,8 +897,9 @@ V3Parse::~V3Parse() { // VL_DO_CLEAR(delete m_impp, m_impp = nullptr); } void V3Parse::parseFile(FileLine* fileline, const string& modname, bool inLibrary, bool inLibMap, - const string& libname, const string& errmsg) { - m_impp->parseFile(fileline, modname, inLibrary, inLibMap, libname, errmsg); + const string& libname, const string& errmsg, + const std::string& notFoundName) { + m_impp->parseFile(fileline, modname, inLibrary, inLibMap, libname, errmsg, notFoundName); } void V3Parse::ppPushText(V3ParseImp* impp, const string& text) { if (text != "") impp->ppPushText(text); diff --git a/src/V3ParseImp.h b/src/V3ParseImp.h index e011b36f2..33dd99957 100644 --- a/src/V3ParseImp.h +++ b/src/V3ParseImp.h @@ -303,7 +303,8 @@ public: int tokenToBison() VL_MT_DISABLED; // Pass token to bison void parseFile(FileLine* fileline, const string& modfilename, bool inLibrary, bool inLibMap, - const string& libname, const string& errmsg) VL_MT_DISABLED; + const string& libname, const string& errmsg, + const std::string& notFoundName) VL_MT_DISABLED; void dumpInputsFile() VL_MT_DISABLED; void dumpTokensAhead(int line) VL_MT_DISABLED; static void candidatePli(VSpellCheck* spellerp) VL_MT_DISABLED; diff --git a/test_regress/t/t_missing_module_pruned.py b/test_regress/t/t_missing_module_pruned.py new file mode 100755 index 000000000..a5ea6627e --- /dev/null +++ b/test_regress/t/t_missing_module_pruned.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of either the GNU Lesser General Public License Version 3 +# or the Perl Artistic License Version 2.0. +# SPDX-FileCopyrightText: 2026 Wilson Snyder +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +import vltest_bootstrap + +test.scenarios('linter') + +test.lint() + +test.passes() diff --git a/test_regress/t/t_missing_module_pruned.v b/test_regress/t/t_missing_module_pruned.v new file mode 100644 index 000000000..2039e58f5 --- /dev/null +++ b/test_regress/t/t_missing_module_pruned.v @@ -0,0 +1,11 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain +// SPDX-FileCopyrightText: 2026 Antmicro +// SPDX-License-Identifier: CC0-1.0 + +module t #(parameter bit fail = 0)(); + if (!(!fail)) begin + __VnotExising__Vmodule__abc__ sentinel (); + end +endmodule