Fix type_id package scope resolution (#5826)
This commit is contained in:
parent
8e87a99628
commit
b2093b513a
|
@ -50,7 +50,8 @@ protected:
|
|||
|
||||
private:
|
||||
// METHODS
|
||||
const AstNodeDType* skipRefIterp(bool skipConst, bool skipEnum) const VL_MT_STABLE;
|
||||
const AstNodeDType* skipRefIterp(bool skipConst, bool skipEnum,
|
||||
bool assertOn = true) const VL_MT_STABLE;
|
||||
|
||||
protected:
|
||||
// METHODS
|
||||
|
@ -78,6 +79,15 @@ public:
|
|||
return const_cast<AstNodeDType*>(
|
||||
static_cast<const AstNodeDType*>(this)->skipRefIterp(true, true));
|
||||
}
|
||||
// (Slow) Recurse over MemberDType|ParamTypeDType|RefDType|ConstDType|EnumDType to other type,
|
||||
// Returns null if not resolved
|
||||
const AstNodeDType* skipRefOrNullp() const VL_MT_STABLE {
|
||||
return skipRefIterp(true, true, false);
|
||||
}
|
||||
AstNodeDType* skipRefOrNullp() VL_MT_STABLE {
|
||||
return const_cast<AstNodeDType*>(
|
||||
static_cast<const AstNodeDType*>(this)->skipRefIterp(true, true, false));
|
||||
}
|
||||
// (Slow) Recurse over MemberDType|ParamTypeDType|RefDType|EnumDType to ConstDType
|
||||
const AstNodeDType* skipRefToConstp() const { return skipRefIterp(false, true); }
|
||||
AstNodeDType* skipRefToConstp() {
|
||||
|
|
|
@ -829,7 +829,8 @@ AstVar* AstVar::scVarRecurse(AstNode* nodep) {
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
const AstNodeDType* AstNodeDType::skipRefIterp(bool skipConst, bool skipEnum) const VL_MT_STABLE {
|
||||
const AstNodeDType* AstNodeDType::skipRefIterp(bool skipConst, bool skipEnum,
|
||||
bool assertOn) const VL_MT_STABLE {
|
||||
const AstNodeDType* nodep = this;
|
||||
while (true) {
|
||||
if (VL_UNLIKELY(VN_IS(nodep, MemberDType) || VN_IS(nodep, ParamTypeDType)
|
||||
|
@ -840,7 +841,7 @@ const AstNodeDType* AstNodeDType::skipRefIterp(bool skipConst, bool skipEnum) co
|
|||
nodep = subp;
|
||||
continue;
|
||||
} else {
|
||||
nodep->v3fatalSrc(nodep->prettyTypeName() << " not linked to type");
|
||||
if (assertOn) nodep->v3fatalSrc(nodep->prettyTypeName() << " not linked to type");
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
@ -2669,7 +2670,9 @@ AstNodeModule* AstClassOrPackageRef::classOrPackageSkipp() const {
|
|||
AstNode* lastp = nullptr;
|
||||
while (foundp != lastp) {
|
||||
lastp = foundp;
|
||||
if (AstNodeDType* const anodep = VN_CAST(foundp, NodeDType)) foundp = anodep->skipRefp();
|
||||
if (AstNodeDType* const anodep = VN_CAST(foundp, NodeDType)) {
|
||||
foundp = anodep->skipRefOrNullp();
|
||||
}
|
||||
if (AstTypedef* const anodep = VN_CAST(foundp, Typedef)) foundp = anodep->subDTypep();
|
||||
if (AstClassRefDType* const anodep = VN_CAST(foundp, ClassRefDType))
|
||||
foundp = anodep->classp();
|
||||
|
|
|
@ -765,10 +765,15 @@ public:
|
|||
if (!foundp) baddot = dotname;
|
||||
return foundp;
|
||||
}
|
||||
VSymEnt* resolveClassOrPackage(VSymEnt* lookSymp, AstClassOrPackageRef* nodep, bool classOnly,
|
||||
const string& forWhat) {
|
||||
VSymEnt* resolveClassOrPackage(VSymEnt* lookSymp, AstClassOrPackageRef* nodep, bool fallback,
|
||||
bool classOnly, const string& forWhat) {
|
||||
if (nodep->classOrPackageSkipp()) return getNodeSym(nodep->classOrPackageSkipp());
|
||||
VSymEnt* foundp = lookSymp->findIdFallback(nodep->name());
|
||||
VSymEnt* foundp;
|
||||
if (fallback) {
|
||||
foundp = lookSymp->findIdFallback(nodep->name());
|
||||
} else {
|
||||
foundp = lookSymp->findIdFlat(nodep->name());
|
||||
}
|
||||
if (!foundp && v3Global.rootp()->stdPackagep()) { // Look under implied std::
|
||||
foundp = getNodeSym(v3Global.rootp()->stdPackagep())->findIdFlat(nodep->name());
|
||||
}
|
||||
|
@ -1038,12 +1043,8 @@ class LinkDotFindVisitor final : public VNVisitor {
|
|||
}
|
||||
}
|
||||
void visit(AstClassOrPackageRef* nodep) override {
|
||||
if (!nodep->classOrPackageNodep()) {
|
||||
if (nodep->name() == "$unit") {
|
||||
nodep->classOrPackageNodep(v3Global.rootp()->dollarUnitPkgAddp());
|
||||
} else if (nodep->name() == "std") {
|
||||
nodep->classOrPackageNodep(v3Global.rootp()->stdPackagep());
|
||||
}
|
||||
if (!nodep->classOrPackageNodep() && nodep->name() == "$unit") {
|
||||
nodep->classOrPackageNodep(v3Global.rootp()->dollarUnitPkgAddp());
|
||||
}
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
|
@ -1183,7 +1184,7 @@ class LinkDotFindVisitor final : public VNVisitor {
|
|||
= VN_CAST(nodep->classOrPackagep(), ClassOrPackageRef);
|
||||
if (dotp) {
|
||||
AstClassOrPackageRef* const lhsp = VN_AS(dotp->lhsp(), ClassOrPackageRef);
|
||||
m_statep->resolveClassOrPackage(m_curSymp, lhsp, false,
|
||||
m_statep->resolveClassOrPackage(m_curSymp, lhsp, true, false,
|
||||
"External definition :: reference");
|
||||
AstClass* const lhsclassp = VN_CAST(lhsp->classOrPackageSkipp(), Class);
|
||||
if (!lhsclassp) {
|
||||
|
@ -1192,7 +1193,7 @@ class LinkDotFindVisitor final : public VNVisitor {
|
|||
m_curSymp = m_statep->getNodeSym(lhsclassp);
|
||||
upSymp = m_curSymp;
|
||||
AstClassOrPackageRef* const rhsp = VN_AS(dotp->rhsp(), ClassOrPackageRef);
|
||||
m_statep->resolveClassOrPackage(m_curSymp, rhsp, false,
|
||||
m_statep->resolveClassOrPackage(m_curSymp, rhsp, true, false,
|
||||
"External definition :: reference");
|
||||
AstClass* const rhsclassp = VN_CAST(rhsp->classOrPackageSkipp(), Class);
|
||||
if (!rhsclassp) {
|
||||
|
@ -1211,7 +1212,7 @@ class LinkDotFindVisitor final : public VNVisitor {
|
|||
}
|
||||
} else if (cpackagerefp) {
|
||||
if (!cpackagerefp->classOrPackageSkipp()) {
|
||||
m_statep->resolveClassOrPackage(m_curSymp, cpackagerefp, false,
|
||||
m_statep->resolveClassOrPackage(m_curSymp, cpackagerefp, true, false,
|
||||
"External definition :: reference");
|
||||
}
|
||||
AstClass* const classp = VN_CAST(cpackagerefp->classOrPackageSkipp(), Class);
|
||||
|
@ -1338,7 +1339,7 @@ class LinkDotFindVisitor final : public VNVisitor {
|
|||
"Unsupported: extern constraint definition with class-in-class");
|
||||
} else {
|
||||
if (!cpackagerefp->classOrPackageSkipp()) {
|
||||
m_statep->resolveClassOrPackage(m_curSymp, cpackagerefp, false,
|
||||
m_statep->resolveClassOrPackage(m_curSymp, cpackagerefp, true, false,
|
||||
"External definition :: reference");
|
||||
}
|
||||
AstClass* const classp = VN_CAST(cpackagerefp->classOrPackageSkipp(), Class);
|
||||
|
@ -2255,6 +2256,8 @@ class LinkDotResolveVisitor final : public VNVisitor {
|
|||
bool m_insideClassExtParam = false; // Inside a class from m_extendsParam
|
||||
bool m_explicitSuperNew = false; // Hit a "super.new" call inside a "new" function
|
||||
std::map<AstNode*, AstPin*> m_usedPins; // Pin used in this cell, map to duplicate
|
||||
std::map<std::string, AstNodeModule*> m_modulesToRevisit; // Modules to revisit a second time
|
||||
AstNode* m_lastDeferredp = nullptr; // Last node which requested a revisit of its module
|
||||
|
||||
struct DotStates final {
|
||||
DotPosition m_dotPos; // Scope part of dotted resolution
|
||||
|
@ -2500,6 +2503,13 @@ class LinkDotResolveVisitor final : public VNVisitor {
|
|||
symIterateNull(nodep, m_statep->getNodeSym(nodep));
|
||||
}
|
||||
|
||||
// Marks the current module to be revisited after the initial AST iteration
|
||||
void revisitLater(AstNode* deferredNodep) {
|
||||
// Need to revisit entire module to build up all the necessary context
|
||||
m_lastDeferredp = deferredNodep;
|
||||
m_modulesToRevisit.insert(std::make_pair(m_modp->name(), m_modp));
|
||||
}
|
||||
|
||||
void updateVarUse(AstVar* nodep) {
|
||||
// Avoid dotted.PARAM false positive when in a parameter block
|
||||
// that is if ()'ed off by same dotted name as another block
|
||||
|
@ -2744,12 +2754,58 @@ class LinkDotResolveVisitor final : public VNVisitor {
|
|||
}
|
||||
}
|
||||
}
|
||||
} else if (VN_IS(nodep->lhsp(), ClassOrPackageRef)
|
||||
|| (VN_IS(nodep->lhsp(), Dot) && VN_AS(nodep->lhsp(), Dot)->colon())) {
|
||||
} else if (AstClassOrPackageRef* const lhsp
|
||||
= VN_CAST(nodep->lhsp(), ClassOrPackageRef)) {
|
||||
// m_ds.m_dotText communicates the cell prefix between stages
|
||||
m_ds.m_dotPos = DP_PACKAGE;
|
||||
UINFO(8, indent() << "iter.lhs " << m_ds.ascii() << " " << nodep << endl);
|
||||
iterateAndNextNull(lhsp);
|
||||
if (!lhsp->classOrPackageSkipp() && lhsp->name() != "local::") {
|
||||
revisitLater(nodep);
|
||||
m_ds = lastStates;
|
||||
// Resolve function args before bailing
|
||||
if (AstNodeFTaskRef* const ftaskrefp = VN_CAST(nodep->rhsp(), NodeFTaskRef)) {
|
||||
iterateAndNextNull(ftaskrefp->pinsp());
|
||||
}
|
||||
return;
|
||||
}
|
||||
m_ds.m_dotPos = DP_PACKAGE;
|
||||
// nodep->lhsp() may be a new node
|
||||
if (AstClassOrPackageRef* const classOrPackageRefp
|
||||
= VN_CAST(nodep->lhsp(), ClassOrPackageRef)) {
|
||||
if (AstNode* const classOrPackageNodep
|
||||
= classOrPackageRefp->classOrPackageSkipp()) {
|
||||
m_ds.m_dotSymp = m_statep->getNodeSym(classOrPackageNodep);
|
||||
}
|
||||
}
|
||||
UINFO(8, indent() << "iter.ldone " << m_ds.ascii() << " " << nodep << endl);
|
||||
} else if (VN_IS(nodep->lhsp(), Dot) && VN_AS(nodep->lhsp(), Dot)->colon()) {
|
||||
// m_ds.m_dotText communicates the cell prefix between stages
|
||||
UINFO(8, indent() << "iter.lhs " << m_ds.ascii() << " " << nodep << endl);
|
||||
m_ds.m_dotPos = DP_PACKAGE;
|
||||
iterateAndNextNull(nodep->lhsp());
|
||||
// nodep->lhsp() may be a new node
|
||||
if (AstClassOrPackageRef* const crefp
|
||||
= VN_CAST(nodep->lhsp(), ClassOrPackageRef)) {
|
||||
if (!crefp->classOrPackageSkipp()) {
|
||||
revisitLater(nodep);
|
||||
m_ds = lastStates;
|
||||
// Resolve function args before bailing
|
||||
if (AstNodeFTaskRef* const ftaskrefp
|
||||
= VN_CAST(nodep->rhsp(), NodeFTaskRef)) {
|
||||
iterateAndNextNull(ftaskrefp->pinsp());
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (m_lastDeferredp == nodep->lhsp()) {
|
||||
// LHS got deferred, so this node won't be resolved. Defer it too
|
||||
m_ds = lastStates;
|
||||
// Resolve function args before bailing
|
||||
if (AstNodeFTaskRef* const ftaskrefp = VN_CAST(nodep->rhsp(), NodeFTaskRef)) {
|
||||
iterateAndNextNull(ftaskrefp->pinsp());
|
||||
}
|
||||
return;
|
||||
}
|
||||
UINFO(8, indent() << "iter.ldone " << m_ds.ascii() << " " << nodep << endl);
|
||||
} else {
|
||||
m_ds.m_dotPos = DP_FIRST;
|
||||
|
@ -2932,10 +2988,15 @@ class LinkDotResolveVisitor final : public VNVisitor {
|
|||
first = true;
|
||||
} else if (!cpackagerefp->classOrPackageSkipp()) {
|
||||
VSymEnt* const foundp = m_statep->resolveClassOrPackage(
|
||||
m_ds.m_dotSymp, cpackagerefp, false, ":: reference");
|
||||
m_ds.m_dotSymp, cpackagerefp, true, false, ":: reference");
|
||||
if (!foundp) return;
|
||||
classOrPackagep = cpackagerefp->classOrPackageSkipp();
|
||||
m_ds.m_dotSymp = m_statep->getNodeSym(classOrPackagep);
|
||||
if (classOrPackagep) {
|
||||
m_ds.m_dotSymp = m_statep->getNodeSym(classOrPackagep);
|
||||
} else {
|
||||
m_ds = lastStates;
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
classOrPackagep = cpackagerefp->classOrPackageSkipp();
|
||||
UASSERT_OBJ(classOrPackagep, m_ds.m_dotp->lhsp(), "Bad package link");
|
||||
|
@ -3293,12 +3354,15 @@ class LinkDotResolveVisitor final : public VNVisitor {
|
|||
VL_RESTORER(m_pinSymp);
|
||||
|
||||
if (!nodep->classOrPackageSkipp() && nodep->name() != "local::") {
|
||||
m_statep->resolveClassOrPackage(m_ds.m_dotSymp, nodep, false, ":: reference");
|
||||
m_statep->resolveClassOrPackage(m_ds.m_dotSymp, nodep, m_ds.m_dotPos != DP_PACKAGE,
|
||||
false, ":: reference");
|
||||
}
|
||||
|
||||
// ClassRef's have pins, so track
|
||||
if (nodep->classOrPackageSkipp()) {
|
||||
m_pinSymp = m_statep->getNodeSym(nodep->classOrPackageSkipp());
|
||||
} else if (nodep->name() != "local::") {
|
||||
return;
|
||||
}
|
||||
AstClass* const refClassp = VN_CAST(nodep->classOrPackageSkipp(), Class);
|
||||
// Make sure any extends() are properly imported within referenced class
|
||||
|
@ -3608,7 +3672,7 @@ class LinkDotResolveVisitor final : public VNVisitor {
|
|||
first = true;
|
||||
} else if (!cpackagerefp->classOrPackageSkipp()) {
|
||||
VSymEnt* const foundp = m_statep->resolveClassOrPackage(
|
||||
m_ds.m_dotSymp, cpackagerefp, false, ":: reference");
|
||||
m_ds.m_dotSymp, cpackagerefp, true, false, ":: reference");
|
||||
if (foundp) nodep->classOrPackagep(cpackagerefp->classOrPackageSkipp());
|
||||
} else {
|
||||
nodep->classOrPackagep(cpackagerefp->classOrPackageSkipp());
|
||||
|
@ -3968,7 +4032,7 @@ class LinkDotResolveVisitor final : public VNVisitor {
|
|||
iterate(lookNodep);
|
||||
cprp = dotp->rhsp();
|
||||
VSymEnt* const foundp = m_statep->resolveClassOrPackage(
|
||||
lookSymp, lookNodep, false, nodep->verilogKwd());
|
||||
lookSymp, lookNodep, true, false, nodep->verilogKwd());
|
||||
if (!foundp) return;
|
||||
UASSERT_OBJ(lookNodep->classOrPackageSkipp(), nodep, "Bad package link");
|
||||
lookSymp = m_statep->getNodeSym(lookNodep->classOrPackageSkipp());
|
||||
|
@ -3984,7 +4048,7 @@ class LinkDotResolveVisitor final : public VNVisitor {
|
|||
return;
|
||||
}
|
||||
VSymEnt* const foundp = m_statep->resolveClassOrPackage(lookSymp, cpackagerefp, true,
|
||||
nodep->verilogKwd());
|
||||
true, nodep->verilogKwd());
|
||||
if (foundp) {
|
||||
if (AstClass* const classp = VN_CAST(foundp->nodep(), Class)) {
|
||||
AstPin* paramsp = cpackagerefp->paramsp();
|
||||
|
@ -4151,7 +4215,7 @@ class LinkDotResolveVisitor final : public VNVisitor {
|
|||
}
|
||||
if (!cpackagerefp->classOrPackageSkipp()) {
|
||||
VSymEnt* const foundp = m_statep->resolveClassOrPackage(
|
||||
m_ds.m_dotSymp, cpackagerefp, false, "class/package reference");
|
||||
m_ds.m_dotSymp, cpackagerefp, true, false, "class/package reference");
|
||||
if (!foundp) return;
|
||||
}
|
||||
nodep->classOrPackagep(cpackagerefp->classOrPackageSkipp());
|
||||
|
@ -4327,6 +4391,13 @@ public:
|
|||
: m_statep{statep} {
|
||||
UINFO(4, __FUNCTION__ << ": " << endl);
|
||||
iterate(rootp);
|
||||
std::map<std::string, AstNodeModule*> modulesToRevisit = std::move(m_modulesToRevisit);
|
||||
m_lastDeferredp = nullptr;
|
||||
for (auto& p : modulesToRevisit) {
|
||||
AstNodeModule* const modp = p.second;
|
||||
modp->foreach([](AstNode* const nodep) { nodep->user3(false); });
|
||||
iterate(modp);
|
||||
}
|
||||
}
|
||||
~LinkDotResolveVisitor() override = default;
|
||||
};
|
||||
|
|
|
@ -712,7 +712,7 @@ void V3ParseImp::tokenPipelineSym() {
|
|||
} else { // Not found
|
||||
yylval.scp = nullptr;
|
||||
if (token == yaID__CC) {
|
||||
if (!v3Global.opt.bboxUnsup()) {
|
||||
if (!m_afterColonColon & !v3Global.opt.bboxUnsup()) {
|
||||
// IEEE does require this, but we may relax this as UVM breaks it, so allow
|
||||
// bbox for today
|
||||
// We'll get a parser error eventually but might not be obvious
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
#!/usr/bin/env python3
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2024 by Wilson Snyder. 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-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
import vltest_bootstrap
|
||||
|
||||
test.scenarios('simulator')
|
||||
|
||||
test.compile()
|
||||
|
||||
test.execute()
|
||||
|
||||
test.passes()
|
|
@ -0,0 +1,36 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||
// any use, without warranty, 2025 by Antmicro.
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
typedef class Bar;
|
||||
typedef Bar Baz;
|
||||
|
||||
module t;
|
||||
initial begin
|
||||
Bar::Qux::boo(1);
|
||||
Baz::Qux::boo(1);
|
||||
if (!Bar::Qux::finish) $stop;
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
endmodule
|
||||
|
||||
class Foo #(type T);
|
||||
static logic finish = 0;
|
||||
static function void boo(input logic rec);
|
||||
if (rec) Bar::Qux::boo(0);
|
||||
finish = 1;
|
||||
endfunction
|
||||
endclass
|
||||
|
||||
class Goo #(type T);
|
||||
function void goo();
|
||||
T::Qux::boo(1);
|
||||
endfunction
|
||||
endclass
|
||||
|
||||
class Bar;
|
||||
typedef Foo#(Bar) Qux;
|
||||
endclass
|
|
@ -1,7 +1,4 @@
|
|||
%Error: t/t_interface_colon_bad.v:14:7: Package/class for ':: reference' not found: 'iface'
|
||||
14 | iface::func();
|
||||
| ^~~~~
|
||||
%Error: t/t_interface_colon_bad.v:14:14: Can't find definition of task/function: 'func'
|
||||
14 | iface::func();
|
||||
| ^~~~
|
||||
%Error: Exiting due to
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
%Error-PKGNODECL: t/t_package_identifier_bad.v:15:20: Package/class 'Bar' not found, and needs to be predeclared (IEEE 1800-2023 26.3)
|
||||
%Error: t/t_package_identifier_bad.v:15:20: Package/class for ':: reference' not found: 'Bar'
|
||||
15 | int baz = Foo::Bar::baz;
|
||||
| ^~~
|
||||
... For error description see https://verilator.org/warn/PKGNODECL?v=latest
|
||||
%Error: Exiting due to
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
#!/usr/bin/env python3
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2024 by Wilson Snyder. 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-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
import vltest_bootstrap
|
||||
|
||||
test.scenarios('simulator')
|
||||
|
||||
test.compile()
|
||||
|
||||
test.execute()
|
||||
|
||||
test.passes()
|
|
@ -0,0 +1,31 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||
// any use, without warranty, 2025 by Antmicro.
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
class Foo;
|
||||
static function int get(int x);
|
||||
return x;
|
||||
endfunction
|
||||
endclass
|
||||
|
||||
class Bar;
|
||||
static function int get;
|
||||
return 42;
|
||||
endfunction
|
||||
endclass
|
||||
|
||||
class Qux #(type Tfoo, type Tbar);
|
||||
static function int get();
|
||||
return Tfoo::get(Tbar::get());
|
||||
endfunction
|
||||
endclass
|
||||
|
||||
module t;
|
||||
initial begin
|
||||
if (Qux#(Foo, Bar)::get() != 42) $stop;
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
endmodule
|
|
@ -11,6 +11,6 @@ import vltest_bootstrap
|
|||
|
||||
test.scenarios('linter')
|
||||
|
||||
test.lint(verilator_flags2=["-DTEST_DECLARE_STD"], fails=test.vlt_all) # Issue #4705 due to ::
|
||||
test.lint(verilator_flags2=["-DTEST_DECLARE_STD"])
|
||||
|
||||
test.passes()
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
%Error-PKGNODECL: t/t_std_identifier.v:16:20: Package/class 'std' not found, and needs to be predeclared (IEEE 1800-2023 26.3)
|
||||
%Error: t/t_std_identifier.v:16:20: Package/class for ':: reference' not found: 'std'
|
||||
16 | int baz = foo::std::bar;
|
||||
| ^~~
|
||||
... For error description see https://verilator.org/warn/PKGNODECL?v=latest
|
||||
%Error: t/t_std_identifier.v:16:25: Can't find definition of scope/variable/func: 'bar'
|
||||
16 | int baz = foo::std::bar;
|
||||
| ^~~
|
||||
%Error: Exiting due to
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue