Add ALWNEVER warning, for always @* that never execute (#6291) (#6303)

This commit is contained in:
Wilson Snyder
2025-08-18 12:00:53 -04:00
committed by GitHub
parent 53c59e7ac7
commit c90f9e53b7
23 changed files with 192 additions and 42 deletions
+30
View File
@@ -168,6 +168,36 @@ private:
}
}
}
void visit(AstAlways* nodep) override {
// As have not optimized SenTrees yet, an 'always .*' will be on first and only SenItem
if (nodep->sentreep() && nodep->sentreep()->sensesp()
&& nodep->sentreep()->sensesp()->isComboStar()) {
const bool noReads = nodep->forall(
[&](const AstNodeVarRef* refp) { return !refp->access().isReadOrRW(); });
if (noReads) {
nodep->v3warn(ALWNEVER, "'always @*' will never execute as expression list is "
"empty (no variables read)\n"
<< nodep->warnMore()
<< "... Suggest use 'always_comb'");
VL_DO_DANGLING(pushDeletep(nodep->unlinkFrBack()), nodep);
return;
}
}
// Iterate will delete ComboStar sentrees, so after above
iterateChildren(nodep);
editDType(nodep);
}
void visit(AstSenTree* nodep) override {
if (nodep->sensesp() && nodep->sensesp()->isComboStar()) {
UASSERT_OBJ(!nodep->sensesp()->nextp(), nodep, "Shouldn't be senitems after .*");
// Make look like standalone always
// (Rest of code assumed this before .* existed)
VL_DO_DANGLING(pushDeletep(nodep->unlinkFrBack()), nodep);
return;
}
iterateChildren(nodep);
editDType(nodep);
}
void visit(AstAttrOf* nodep) override {
switch (nodep->attrType()) {
case VAttrType::FUNC_ARG_PROTO: // FALLTHRU