Fiix fault on operations on uninitialized strings (#6520)
Signed-off-by: Artur Bieniek <abieniek@internships.antmicro.com>
This commit is contained in:
parent
01157d414b
commit
16fdd0e93c
|
|
@ -1266,6 +1266,9 @@ class AstExprStmt final : public AstNodeExpr {
|
|||
// resultp is evaluated AFTER the statement(s).
|
||||
// @astgen op1 := stmtsp : List[AstNode]
|
||||
// @astgen op2 := resultp : AstNodeExpr
|
||||
private:
|
||||
bool m_hasResult = true;
|
||||
|
||||
public:
|
||||
AstExprStmt(FileLine* fl, AstNode* stmtsp, AstNodeExpr* resultp)
|
||||
: ASTGEN_SUPER_ExprStmt(fl) {
|
||||
|
|
@ -1283,6 +1286,8 @@ public:
|
|||
return resultp()->isPure();
|
||||
}
|
||||
bool sameNode(const AstNode*) const override { return true; }
|
||||
bool hasResult() { return m_hasResult; }
|
||||
void hasResult(bool flag) { m_hasResult = flag; }
|
||||
};
|
||||
class AstFError final : public AstNodeExpr {
|
||||
// @astgen op1 := filep : AstNode
|
||||
|
|
|
|||
|
|
@ -1227,6 +1227,11 @@ public:
|
|||
// GCC allows compound statements in expressions, but this is not standard.
|
||||
// So we use an immediate-evaluation lambda and comma operator
|
||||
putnbs(nodep, "([&]() {\n");
|
||||
if (!nodep->hasResult()) {
|
||||
iterateAndNextConstNull(nodep->stmtsp());
|
||||
puts("}())");
|
||||
return;
|
||||
}
|
||||
iterateAndNextConstNull(nodep->stmtsp());
|
||||
puts("}(), ");
|
||||
iterateAndNextConstNull(nodep->resultp());
|
||||
|
|
|
|||
|
|
@ -374,6 +374,7 @@ class TaskVisitor final : public VNVisitor {
|
|||
AstScope* m_scopep = nullptr; // Current scope
|
||||
AstNode* m_insStmtp = nullptr; // Where to insert statement
|
||||
bool m_inSensesp = false; // Are we under a senitem?
|
||||
bool m_inNew = false; // Are we under a constructor?
|
||||
int m_modNCalls = 0; // Incrementing func # for making symbols
|
||||
|
||||
// STATE - across all visitors
|
||||
|
|
@ -1476,6 +1477,11 @@ class TaskVisitor final : public VNVisitor {
|
|||
iterateChildren(nodep);
|
||||
UASSERT_OBJ(!m_insStmtp, nodep, "Didn't finish out last statement");
|
||||
}
|
||||
void visit(AstCNew* nodep) override {
|
||||
VL_RESTORER(m_inNew);
|
||||
m_inNew = true;
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
void visit(AstNodeFTaskRef* nodep) override {
|
||||
if (m_inSensesp && !nodep->isPure()) {
|
||||
nodep->v3warn(E_UNSUPPORTED,
|
||||
|
|
@ -1525,10 +1531,33 @@ class TaskVisitor final : public VNVisitor {
|
|||
UASSERT_OBJ(nodep->taskp()->isFunction(), nodep,
|
||||
"funcref-like expression to non-function");
|
||||
AstVarRef* const outrefp = new AstVarRef{nodep->fileline(), outvscp, VAccess::READ};
|
||||
beginp = new AstExprStmt{nodep->fileline(), beginp, outrefp};
|
||||
AstExprStmt* lambdap = new AstExprStmt{nodep->fileline(), beginp, outrefp};
|
||||
|
||||
if (m_inNew) {
|
||||
AstVar* varp = outvscp->varp();
|
||||
varp->funcLocal(true);
|
||||
|
||||
// Create a new var that will be inside the lambda
|
||||
AstVar* newvarp = varp->cloneTree(false);
|
||||
|
||||
// Replace all references so they point to the new var
|
||||
lambdap->stmtsp()->foreachAndNext([varp, newvarp](AstVarRef* refp) {
|
||||
if (refp->varp() == varp) refp->varp(newvarp);
|
||||
});
|
||||
|
||||
// Add variable initialization
|
||||
lambdap->stmtsp()->addHereThisAsNext(newvarp);
|
||||
lambdap->hasResult(false);
|
||||
|
||||
// Add return statement
|
||||
AstCExpr* const exprp = new AstCExpr{nodep->fileline(), varp->name(), 0};
|
||||
exprp->dtypeSetString();
|
||||
lambdap->addStmtsp(new AstCReturn{nodep->fileline(), exprp});
|
||||
}
|
||||
|
||||
// AstExprStmt is currently treated as impure, so clear the cached purity of its
|
||||
// parents
|
||||
nodep->replaceWith(beginp);
|
||||
nodep->replaceWith(lambdap);
|
||||
VL_DO_DANGLING(nodep->deleteTree(), nodep);
|
||||
VIsCached::clearCacheTree();
|
||||
} else { // VN_IS(nodep->backp(), StmtExpr)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,18 @@
|
|||
#!/usr/bin/env python3
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2025 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,28 @@
|
|||
// 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 base;
|
||||
function new(string name);
|
||||
$display(name);
|
||||
if(name == "42") $finish;
|
||||
endfunction
|
||||
|
||||
function string retstr();
|
||||
return $sformatf("%0d", $c("42"));
|
||||
endfunction
|
||||
endclass
|
||||
|
||||
class derived extends base;
|
||||
function new();
|
||||
super.new(retstr());
|
||||
endfunction
|
||||
endclass
|
||||
|
||||
module t;
|
||||
initial begin
|
||||
derived test = new;
|
||||
end
|
||||
endmodule
|
||||
Loading…
Reference in New Issue