Fiix fault on operations on uninitialized strings (#6520)

Signed-off-by: Artur Bieniek <abieniek@internships.antmicro.com>
This commit is contained in:
Artur Bieniek 2025-10-13 13:29:23 +02:00 committed by GitHub
parent 01157d414b
commit 16fdd0e93c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 87 additions and 2 deletions

View File

@ -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

View File

@ -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());

View File

@ -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)

View File

@ -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()

View File

@ -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