Internals: Improve cppcheck flow and fix up issues (#6311)

Added cppcheck-suppressions.txt in the repo root. You can add new
patterns in there instead of having to parse the XML output.

Also configure to add the -D__GNUC__ preprocessor macro, which makes it
understand UASSERT (it understands the 'noreturn' function attribute).

Added some case by case specific suppressions and fixed up other code,
especially in V3Ast*h and V3Dfg*.h, including code generated by astgen
that had some no-ops that irks cppcheck.

One thing it does not seem to like is `const` class members with default
initializers in the class. It will assume that's always the value, even
if overridden in the constructor. We had few so removed them.

With that a lot of files in `src/` are now clean or only have a handful
of issues. Therefore, I have also deleted cppcheck_filtered, and made it
produce human readable output straight to the terminal.

Regarding cleaning up the reported nits, I kind of got bored after
V3[A-E] so pausing here. Apologies for the merge conflicts.

Tested with cppcheck 2.13.0
This commit is contained in:
Geza Lore 2025-08-19 22:02:10 +01:00 committed by GitHub
parent 636a6b8cd2
commit a0edd4e907
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
44 changed files with 357 additions and 468 deletions

View File

@ -409,36 +409,39 @@ CHECK_H = $(wildcard \
CHECK_YL = $(wildcard \ CHECK_YL = $(wildcard \
$(srcdir)/src/*.y \ $(srcdir)/src/*.y \
$(srcdir)/src/*.l ) $(srcdir)/src/*.l )
CPPCHECK = src/cppcheck_filtered cppcheck CPPCHECK = cppcheck
CPPCHECK_FLAGS = --enable=all --inline-suppr \ CPPCHECK_CACHE = $(srcdir)/src/obj_dbg/cppcheck-cache
--suppress=cstyleCast --suppress=ctunullpointer \ CPPCHECK_FLAGS = --enable=all
--suppress=derefInvalidIteratorRedundantCheck \ CPPCHECK_FLAGS += --inline-suppr
--suppress=nullPointer --suppress=nullPointerRedundantCheck \ CPPCHECK_FLAGS += --suppressions-list=$(srcdir)/src/cppcheck-suppressions.txt
--suppress=templateRecursion \ CPPCHECK_FLAGS += --cppcheck-build-dir=$(CPPCHECK_CACHE)
--suppress=unusedFunction --suppress=unusedScopedObject \ CPPCHECK_FLAGS += -DVL_DEBUG=1 -DVL_CPPCHECK=1 -D__GNUC__=1
--suppress=useInitializationList --suppress=useStlAlgorithm \ CPPCHECK_INC = -I$(srcdir)/include
CPPCHECK_INC += -I$(srcdir)/include/gtkwave
CPPCHECK_INC += -I$(srcdir)/include/vltstd
CPPCHECK_INC += -I$(srcdir)/src/obj_dbg
CPPCHECK_INC += -I$(srcdir)/src
CPPCHECK_FLAGS += --xml $(CPPCHECK_CACHE):
CPPCHECK_DEP = $(subst .cpp,.cppcheck,$(CHECK_CPP)) mkdir -p $@
CPPCHECK_INC = -I$(srcdir)/include -I$(srcdir)/include/gtkwave -I$(srcdir)/include/vltstd -I$(srcdir)/src/obj_dbg -I$(srcdir)/src
cppcheck: cppcheck-1 cppcheck-2 cppcheck-3 cppcheck-4 cppcheck-5 cppcheck-6 cppcheck-7 cppcheck-8 cppcheck: cppcheck-1 cppcheck-2 cppcheck-3 cppcheck-4 cppcheck-5 cppcheck-6 cppcheck-7 cppcheck-8
cppcheck-1: cppcheck-1: | $(CPPCHECK_CACHE)
$(CPPCHECK) $(CPPCHECK_FLAGS) -DVL_DEBUG=1 -DVL_CPPCHECK=1 $(CPPCHECK_INC) $(CPPCHECK1_CPP) $(CPPCHECK) $(CPPCHECK_FLAGS) $(CPPCHECK_INC) $(CPPCHECK1_CPP)
cppcheck-2: cppcheck-2: | $(CPPCHECK_CACHE)
$(CPPCHECK) $(CPPCHECK_FLAGS) -DVL_DEBUG=1 -DVL_CPPCHECK=1 $(CPPCHECK_INC) $(CPPCHECK2_CPP) $(CPPCHECK) $(CPPCHECK_FLAGS) $(CPPCHECK_INC) $(CPPCHECK2_CPP)
cppcheck-3: cppcheck-3: | $(CPPCHECK_CACHE)
$(CPPCHECK) $(CPPCHECK_FLAGS) -DVL_DEBUG=1 -DVL_CPPCHECK=1 $(CPPCHECK_INC) $(CPPCHECK3_CPP) $(CPPCHECK) $(CPPCHECK_FLAGS) $(CPPCHECK_INC) $(CPPCHECK3_CPP)
cppcheck-4: cppcheck-4: | $(CPPCHECK_CACHE)
$(CPPCHECK) $(CPPCHECK_FLAGS) -DVL_DEBUG=1 -DVL_CPPCHECK=1 $(CPPCHECK_INC) $(CPPCHECK4_CPP) $(CPPCHECK) $(CPPCHECK_FLAGS) $(CPPCHECK_INC) $(CPPCHECK4_CPP)
cppcheck-5: cppcheck-5: | $(CPPCHECK_CACHE)
$(CPPCHECK) $(CPPCHECK_FLAGS) -DVL_DEBUG=1 -DVL_CPPCHECK=1 $(CPPCHECK_INC) $(CPPCHECK5_CPP) $(CPPCHECK) $(CPPCHECK_FLAGS) $(CPPCHECK_INC) $(CPPCHECK5_CPP)
cppcheck-6: cppcheck-6: | $(CPPCHECK_CACHE)
$(CPPCHECK) $(CPPCHECK_FLAGS) -DVL_DEBUG=1 -DVL_CPPCHECK=1 $(CPPCHECK_INC) $(CPPCHECK6_CPP) $(CPPCHECK) $(CPPCHECK_FLAGS) $(CPPCHECK_INC) $(CPPCHECK6_CPP)
cppcheck-7: cppcheck-7: | $(CPPCHECK_CACHE)
$(CPPCHECK) $(CPPCHECK_FLAGS) -DVL_DEBUG=1 -DVL_CPPCHECK=1 $(CPPCHECK_INC) $(CPPCHECK7_CPP) $(CPPCHECK) $(CPPCHECK_FLAGS) $(CPPCHECK_INC) $(CPPCHECK7_CPP)
cppcheck-8: cppcheck-8: | $(CPPCHECK_CACHE)
$(CPPCHECK) $(CPPCHECK_FLAGS) -DVL_DEBUG=1 -DVL_CPPCHECK=1 $(CPPCHECK_INC) $(CPPCHECK8_CPP) $(CPPCHECK) $(CPPCHECK_FLAGS) $(CPPCHECK_INC) $(CPPCHECK8_CPP)
CLANGTIDY = clang-tidy CLANGTIDY = clang-tidy
CLANGTIDY_FLAGS = -config='' \ CLANGTIDY_FLAGS = -config='' \
@ -512,7 +515,6 @@ PY_PROGRAMS = \
src/astgen \ src/astgen \
src/bisonpre \ src/bisonpre \
src/config_rev \ src/config_rev \
src/cppcheck_filtered \
src/flexfix \ src/flexfix \
src/vlcovgen \ src/vlcovgen \
src/.gdbinit.py \ src/.gdbinit.py \

View File

@ -52,15 +52,13 @@
// clang and gcc-8.0+ support no_sanitize("string") style attribute // clang and gcc-8.0+ support no_sanitize("string") style attribute
# if defined(__clang__) || (__GNUC__ >= 8) # if defined(__clang__) || (__GNUC__ >= 8)
# define VL_ATTR_NO_SANITIZE_ALIGN __attribute__((no_sanitize("alignment"))) # define VL_ATTR_NO_SANITIZE_ALIGN __attribute__((no_sanitize("alignment")))
#else // The entire undefined sanitizer has to be disabled for older gcc # else // The entire undefined sanitizer has to be disabled for older gcc
# define VL_ATTR_NO_SANITIZE_ALIGN __attribute__((no_sanitize_undefined)) # define VL_ATTR_NO_SANITIZE_ALIGN __attribute__((no_sanitize_undefined))
#endif # endif
# define VL_ATTR_PRINTF(fmtArgNum) __attribute__((format(printf, (fmtArgNum), (fmtArgNum) + 1))) # define VL_ATTR_PRINTF(fmtArgNum) __attribute__((format(printf, (fmtArgNum), (fmtArgNum) + 1)))
# define VL_ATTR_PURE __attribute__((pure)) # define VL_ATTR_PURE __attribute__((pure))
# define VL_ATTR_UNUSED __attribute__((unused)) # define VL_ATTR_UNUSED __attribute__((unused))
#ifndef VL_ATTR_WARN_UNUSED_RESULT
# define VL_ATTR_WARN_UNUSED_RESULT __attribute__((warn_unused_result)) # define VL_ATTR_WARN_UNUSED_RESULT __attribute__((warn_unused_result))
#endif
# if !defined(_WIN32) && !defined(__MINGW32__) # if !defined(_WIN32) && !defined(__MINGW32__)
// All VL_ATTR_WEAK symbols must be marked with the macOS -U linker flag in verilated.mk.in // All VL_ATTR_WEAK symbols must be marked with the macOS -U linker flag in verilated.mk.in
# define VL_ATTR_WEAK __attribute__((weak)) # define VL_ATTR_WEAK __attribute__((weak))

View File

@ -166,7 +166,7 @@ public:
// paths make an assignment. Detected latches are flagged in the variables AstVar // paths make an assignment. Detected latches are flagged in the variables AstVar
void latchCheck(AstNode* nodep, bool latch_expected) { void latchCheck(AstNode* nodep, bool latch_expected) {
bool latch_detected = false; bool latch_detected = false;
for (const auto& vrp : m_outputs) { for (const AstVarRef* const vrp : m_outputs) {
LatchDetectGraphVertex* const vertp = castVertexp(vrp->varp()->user1p()); LatchDetectGraphVertex* const vertp = castVertexp(vrp->varp()->user1p());
vertp->user(true); // Identify the output vertex we are checking paths _to_ vertp->user(true); // Identify the output vertex we are checking paths _to_
if (!latchCheckInternal(castVertexp(vertices().frontp()))) latch_detected = true; if (!latchCheckInternal(castVertexp(vertices().frontp()))) latch_detected = true;

View File

@ -86,7 +86,7 @@ class AssertVisitor final : public VNVisitor {
} }
VL_UNREACHABLE; VL_UNREACHABLE;
} }
string assertDisplayMessage(AstNode* nodep, const string& prefix, const string& message, string assertDisplayMessage(const AstNode* nodep, const string& prefix, const string& message,
VDisplayType severity) { VDisplayType severity) {
if (severity == VDisplayType::DT_ERROR || severity == VDisplayType::DT_FATAL) { if (severity == VDisplayType::DT_ERROR || severity == VDisplayType::DT_FATAL) {
return ("[%0t] "s + prefix + ": " + nodep->fileline()->filebasename() + ":" return ("[%0t] "s + prefix + ": " + nodep->fileline()->filebasename() + ":"
@ -148,7 +148,7 @@ class AssertVisitor final : public VNVisitor {
sampledp->dtypeFrom(nodep); sampledp->dtypeFrom(nodep);
return sampledp; return sampledp;
} }
AstVarRef* newMonitorNumVarRefp(AstNode* nodep, VAccess access) { AstVarRef* newMonitorNumVarRefp(const AstNode* nodep, VAccess access) {
if (!m_monitorNumVarp) { if (!m_monitorNumVarp) {
m_monitorNumVarp = new AstVar{nodep->fileline(), VVarType::MODULETEMP, "__VmonitorNum", m_monitorNumVarp = new AstVar{nodep->fileline(), VVarType::MODULETEMP, "__VmonitorNum",
nodep->findUInt64DType()}; nodep->findUInt64DType()};
@ -158,7 +158,7 @@ class AssertVisitor final : public VNVisitor {
varrefp->classOrPackagep(v3Global.rootp()->dollarUnitPkgAddp()); varrefp->classOrPackagep(v3Global.rootp()->dollarUnitPkgAddp());
return varrefp; return varrefp;
} }
AstVarRef* newMonitorOffVarRefp(AstNode* nodep, VAccess access) { AstVarRef* newMonitorOffVarRefp(const AstNode* nodep, VAccess access) {
if (!m_monitorOffVarp) { if (!m_monitorOffVarp) {
m_monitorOffVarp = new AstVar{nodep->fileline(), VVarType::MODULETEMP, "__VmonitorOff", m_monitorOffVarp = new AstVar{nodep->fileline(), VVarType::MODULETEMP, "__VmonitorOff",
nodep->findBitDType()}; nodep->findBitDType()};
@ -181,7 +181,7 @@ class AssertVisitor final : public VNVisitor {
return newp; return newp;
} }
AstNodeStmt* newFireAssertUnchecked(AstNodeStmt* nodep, const string& message, AstNodeStmt* newFireAssertUnchecked(const AstNodeStmt* nodep, const string& message,
AstNodeExpr* exprsp = nullptr) { AstNodeExpr* exprsp = nullptr) {
// Like newFireAssert() but omits the asserts-on check // Like newFireAssert() but omits the asserts-on check
AstDisplay* const dispp AstDisplay* const dispp
@ -194,7 +194,7 @@ class AssertVisitor final : public VNVisitor {
return bodysp; return bodysp;
} }
AstNodeStmt* newFireAssert(AstNodeStmt* nodep, VAssertDirectiveType directiveType, AstNodeStmt* newFireAssert(const AstNodeStmt* nodep, VAssertDirectiveType directiveType,
VAssertType assertType, const string& message, VAssertType assertType, const string& message,
AstNodeExpr* exprsp = nullptr) { AstNodeExpr* exprsp = nullptr) {
AstNodeStmt* bodysp = newFireAssertUnchecked(nodep, message, exprsp); AstNodeStmt* bodysp = newFireAssertUnchecked(nodep, message, exprsp);

View File

@ -102,7 +102,7 @@ private:
} }
AstPropSpec* substitutePropertyCall(AstPropSpec* nodep) { AstPropSpec* substitutePropertyCall(AstPropSpec* nodep) {
if (AstFuncRef* const funcrefp = VN_CAST(nodep->propp(), FuncRef)) { if (AstFuncRef* const funcrefp = VN_CAST(nodep->propp(), FuncRef)) {
if (AstProperty* const propp = VN_CAST(funcrefp->taskp(), Property)) { if (const AstProperty* const propp = VN_CAST(funcrefp->taskp(), Property)) {
AstPropSpec* propExprp = getPropertyExprp(propp); AstPropSpec* propExprp = getPropertyExprp(propp);
// Substitute inner property call before copying in order to not doing the same for // Substitute inner property call before copying in order to not doing the same for
// each call of outer property call. // each call of outer property call.
@ -183,7 +183,7 @@ private:
m_clockingp->addNextHere(varp->unlinkFrBack()); m_clockingp->addNextHere(varp->unlinkFrBack());
varp->user1p(nodep); varp->user1p(nodep);
if (nodep->direction() == VDirection::OUTPUT) { if (nodep->direction() == VDirection::OUTPUT) {
exprp->foreach([](AstNodeVarRef* varrefp) { exprp->foreach([](const AstNodeVarRef* varrefp) {
// Prevent confusing BLKANDNBLK warnings on clockvars due to generated assignments // Prevent confusing BLKANDNBLK warnings on clockvars due to generated assignments
varrefp->fileline()->warnOff(V3ErrorCode::BLKANDNBLK, true); varrefp->fileline()->warnOff(V3ErrorCode::BLKANDNBLK, true);
}); });
@ -318,7 +318,7 @@ private:
if (nodep->stmtsp()) nodep->addNextHere(nodep->stmtsp()->unlinkFrBackWithNext()); if (nodep->stmtsp()) nodep->addNextHere(nodep->stmtsp()->unlinkFrBackWithNext());
FileLine* const flp = nodep->fileline(); FileLine* const flp = nodep->fileline();
AstNodeExpr* valuep = V3Const::constifyEdit(nodep->lhsp()->unlinkFrBack()); AstNodeExpr* valuep = V3Const::constifyEdit(nodep->lhsp()->unlinkFrBack());
AstConst* const constp = VN_CAST(valuep, Const); const AstConst* const constp = VN_CAST(valuep, Const);
if (constp->isZero()) { if (constp->isZero()) {
nodep->v3warn(E_UNSUPPORTED, "Unsupported: ##0 delays"); nodep->v3warn(E_UNSUPPORTED, "Unsupported: ##0 delays");
VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep); VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);

View File

@ -255,14 +255,13 @@ string AstNode::vpiName(const string& namein) {
// This is slightly different from prettyName, in that when we encounter escaped characters, // This is slightly different from prettyName, in that when we encounter escaped characters,
// we change that identifier to an escaped identifier, wrapping it with '\' and ' ' // we change that identifier to an escaped identifier, wrapping it with '\' and ' '
// as specified in LRM 23.6 // as specified in LRM 23.6
string name = namein; const size_t offset = VString::startsWith(namein, "__SYM__") ? 7 : 0;
if (0 == namein.substr(0, 7).compare("__SYM__")) name = namein.substr(7);
string pretty; string pretty;
pretty.reserve(name.length()); pretty.reserve(namein.length());
bool inEscapedIdent = false; bool inEscapedIdent = false;
int lastIdent = 0; int lastIdent = 0;
for (const char* pos = name.c_str(); *pos;) { for (const char* pos = namein.c_str() + offset; *pos;) {
char specialChar = 0; char specialChar = 0;
if (pos[0] == '-' && pos[1] == '>') { // -> if (pos[0] == '-' && pos[1] == '>') { // ->
specialChar = '.'; specialChar = '.';
@ -280,7 +279,7 @@ string AstNode::vpiName(const string& namein) {
} else if (0 == std::strncmp(pos, "__PVT__", 7)) { } else if (0 == std::strncmp(pos, "__PVT__", 7)) {
pos += 7; pos += 7;
continue; continue;
} else if (pos[0] == '_' && pos[1] == '_' && pos[2] == '0' && std::isxdigit(pos[3]) } else if (0 == std::strncmp(pos, "__0", 3) && std::isxdigit(pos[3])
&& std::isxdigit(pos[4])) { && std::isxdigit(pos[4])) {
char value = 0; char value = 0;
value += 16 value += 16
@ -567,6 +566,7 @@ AstNode* AstNode::unlinkFrBackWithNext(VNRelinker* linkerp) {
AstNode* const oldp = this; AstNode* const oldp = this;
UASSERT_OBJ(oldp->m_backp, oldp, "Node has no back, already unlinked?"); UASSERT_OBJ(oldp->m_backp, oldp, "Node has no back, already unlinked?");
oldp->editCountInc(); oldp->editCountInc();
// cppcheck-suppress shadowFunction
AstNode* const backp = oldp->m_backp; AstNode* const backp = oldp->m_backp;
if (linkerp) { if (linkerp) {
linkerp->m_oldp = oldp; linkerp->m_oldp = oldp;
@ -629,6 +629,7 @@ AstNode* AstNode::unlinkFrBack(VNRelinker* linkerp) {
AstNode* const oldp = this; AstNode* const oldp = this;
UASSERT_OBJ(oldp->m_backp, oldp, "Node has no back, already unlinked?"); UASSERT_OBJ(oldp->m_backp, oldp, "Node has no back, already unlinked?");
oldp->editCountInc(); oldp->editCountInc();
// cppcheck-suppress shadowFunction
AstNode* const backp = oldp->m_backp; AstNode* const backp = oldp->m_backp;
if (linkerp) { if (linkerp) {
linkerp->m_oldp = oldp; linkerp->m_oldp = oldp;
@ -710,6 +711,7 @@ void AstNode::relink(VNRelinker* linkerp) {
cout << endl; cout << endl;
} }
// cppcheck-suppress shadowFunction
AstNode* const backp = linkerp->m_backp; AstNode* const backp = linkerp->m_backp;
debugTreeChange(this, "-relinkNew: ", __LINE__, true); debugTreeChange(this, "-relinkNew: ", __LINE__, true);
debugTreeChange(backp, "-relinkTre: ", __LINE__, true); debugTreeChange(backp, "-relinkTre: ", __LINE__, true);
@ -773,6 +775,7 @@ void AstNode::addHereThisAsNext(AstNode* newp) {
UASSERT_OBJ(this->m_backp, this, "'this' node has no back, already unlinked?"); UASSERT_OBJ(this->m_backp, this, "'this' node has no back, already unlinked?");
UASSERT_OBJ(newp->m_headtailp, newp, "m_headtailp not set on new node"); UASSERT_OBJ(newp->m_headtailp, newp, "m_headtailp not set on new node");
// //
// cppcheck-suppress shadowFunction
AstNode* const backp = this->m_backp; AstNode* const backp = this->m_backp;
AstNode* const newLastp = newp->m_headtailp; AstNode* const newLastp = newp->m_headtailp;
// //
@ -1185,6 +1188,7 @@ void AstNode::checkTreeIter(const AstNode* prevBackp) const VL_MT_STABLE {
break; break;
case VNTypeInfo::OP_LIST: case VNTypeInfo::OP_LIST:
if (const AstNode* const headp = nodep) { if (const AstNode* const headp = nodep) {
// cppcheck-suppress shadowFunction
const AstNode* backp = this; const AstNode* backp = this;
const AstNode* tailp; const AstNode* tailp;
const AstNode* opp = headp; const AstNode* opp = headp;
@ -1457,15 +1461,16 @@ string AstNode::instanceStr() const {
// in case we have some circular reference bug. // in case we have some circular reference bug.
constexpr unsigned maxIterations = 10000; constexpr unsigned maxIterations = 10000;
unsigned iterCount = 0; unsigned iterCount = 0;
for (const AstNode* backp = this; backp; backp = backp->backp(), ++iterCount) { // Walk 'backp' chain
for (const AstNode* currp = this; currp; currp = currp->backp(), ++iterCount) {
if (VL_UNCOVERABLE(iterCount >= maxIterations)) return ""; // LCOV_EXCL_LINE if (VL_UNCOVERABLE(iterCount >= maxIterations)) return ""; // LCOV_EXCL_LINE
// Prefer the enclosing scope, if there is one. This is always under the enclosing module, // Prefer the enclosing scope, if there is one. This is always under the enclosing module,
// so just pick it up when encountered // so just pick it up when encountered
if (const AstScope* const scopep = VN_CAST(backp, Scope)) { if (const AstScope* const scopep = VN_CAST(currp, Scope)) {
return scopep->isTop() ? "" : "... note: In instance " + scopep->prettyNameQ(); return scopep->isTop() ? "" : "... note: In instance " + scopep->prettyNameQ();
} }
// If scopes don't exist, report an example instance of the enclosing module // If scopes don't exist, report an example instance of the enclosing module
if (const AstModule* const modp = VN_CAST(backp, Module)) { if (const AstModule* const modp = VN_CAST(currp, Module)) {
const string instanceName = modp->someInstanceName(); const string instanceName = modp->someInstanceName();
return instanceName.empty() ? "" : "... note: In instance '" + instanceName + "'"; return instanceName.empty() ? "" : "... note: In instance '" + instanceName + "'";
} }
@ -1619,8 +1624,8 @@ static VCastable computeCastableImp(const AstNodeDType* toDtp, const AstNodeDTyp
} else if (VN_IS(toDtp, ClassRefDType) && VN_IS(fromConstp, Const)) { } else if (VN_IS(toDtp, ClassRefDType) && VN_IS(fromConstp, Const)) {
if (fromConstp->isNull()) return VCastable::COMPATIBLE; if (fromConstp->isNull()) return VCastable::COMPATIBLE;
} else if (VN_IS(toDtp, ClassRefDType) && VN_IS(fromDtp, ClassRefDType)) { } else if (VN_IS(toDtp, ClassRefDType) && VN_IS(fromDtp, ClassRefDType)) {
const auto toClassp = VN_AS(toDtp, ClassRefDType)->classp(); const AstClass* const toClassp = VN_AS(toDtp, ClassRefDType)->classp();
const auto fromClassp = VN_AS(fromDtp, ClassRefDType)->classp(); const AstClass* const fromClassp = VN_AS(fromDtp, ClassRefDType)->classp();
const bool downcast = AstClass::isClassExtendedFrom(toClassp, fromClassp); const bool downcast = AstClass::isClassExtendedFrom(toClassp, fromClassp);
const bool upcast = AstClass::isClassExtendedFrom(fromClassp, toClassp); const bool upcast = AstClass::isClassExtendedFrom(fromClassp, toClassp);
if (upcast) { if (upcast) {
@ -1664,7 +1669,7 @@ AstNodeDType* AstNode::getCommonClassTypep(AstNode* node1p, AstNode* node2p) {
while (classDtypep1) { while (classDtypep1) {
const VCastable castable = computeCastable(classDtypep1, node2p->dtypep(), node2p); const VCastable castable = computeCastable(classDtypep1, node2p->dtypep(), node2p);
if (castable == VCastable::COMPATIBLE) return classDtypep1; if (castable == VCastable::COMPATIBLE) return classDtypep1;
AstClassExtends* const extendsp = classDtypep1->classp()->extendsp(); const AstClassExtends* const extendsp = classDtypep1->classp()->extendsp();
classDtypep1 = extendsp ? VN_AS(extendsp->dtypep(), ClassRefDType) : nullptr; classDtypep1 = extendsp ? VN_AS(extendsp->dtypep(), ClassRefDType) : nullptr;
} }
return nullptr; return nullptr;

View File

@ -116,9 +116,8 @@ public:
// Above include has: // Above include has:
// enum en {...}; // enum en {...};
// const char* ascii() const {...}; // const char* ascii() const {...};
enum en m_e; const enum en m_e;
// cppcheck-suppress uninitVar // responsibility of each subclass VNType() = delete;
VNType() = default;
// cppcheck-suppress noExplicitConstructor // cppcheck-suppress noExplicitConstructor
constexpr VNType(en _e) VL_MT_SAFE : m_e{_e} {} constexpr VNType(en _e) VL_MT_SAFE : m_e{_e} {}
explicit VNType(int _e) explicit VNType(int _e)
@ -2138,7 +2137,7 @@ protected:
AstNode(VNType t, FileLine* fl); AstNode(VNType t, FileLine* fl);
virtual AstNode* clone() = 0; // Generally, cloneTree is what you want instead virtual AstNode* clone() = 0; // Generally, cloneTree is what you want instead
virtual void cloneRelink() { cloneRelinkGen(); } virtual void cloneRelink() { cloneRelinkGen(); }
virtual void cloneRelinkGen() = 0; // Generated by 'astgen' virtual void cloneRelinkGen(){}; // Overrides generated by 'astgen'
void cloneRelinkTree(); void cloneRelinkTree();
// METHODS // METHODS
@ -2662,20 +2661,24 @@ public:
// For use via privateAs or the VN_DBG_AS macro only // For use via privateAs or the VN_DBG_AS macro only
template <typename T, typename E> template <typename T, typename E>
static T* unsafePrivateAs(AstNode* nodep) VL_PURE { static T* unsafePrivateAs(AstNode* nodep) VL_PURE {
static_assert(!uselessCast<T, E>(), "Unnecessary VN_AS, node known to have target type."); static_assert(!uselessCast<T, E>(),
static_assert(!impossibleCast<T, E>(), "Unnecessary VN_AS, node cannot be this type."); "Unnecessary VN_DBG_AS, node known to have target type.");
static_assert(!impossibleCast<T, E>(), "Unnecessary VN_DBG_AS, node cannot be this type.");
return reinterpret_cast<T*>(nodep); return reinterpret_cast<T*>(nodep);
} }
template <typename T, typename E> template <typename T, typename E>
static const T* unsafePrivateAs(const AstNode* nodep) VL_PURE { static const T* unsafePrivateAs(const AstNode* nodep) VL_PURE {
static_assert(!uselessCast<T, E>(), "Unnecessary VN_AS, node known to have target type."); static_assert(!uselessCast<T, E>(),
static_assert(!impossibleCast<T, E>(), "Unnecessary VN_AS, node cannot be this type."); "Unnecessary VN_DBG_AS, node known to have target type.");
static_assert(!impossibleCast<T, E>(), "Unnecessary VN_DBG_AS, node cannot be this type.");
return reinterpret_cast<const T*>(nodep); return reinterpret_cast<const T*>(nodep);
} }
// For use via the VN_AS macro only // For use via the VN_AS macro only
template <typename T, typename E> template <typename T, typename E>
static T* privateAs(AstNode* nodep) VL_PURE { static T* privateAs(AstNode* nodep) VL_PURE {
static_assert(!uselessCast<T, E>(), "Unnecessary VN_AS, node known to have target type.");
static_assert(!impossibleCast<T, E>(), "Unnecessary VN_AS, node cannot be this type.");
UASSERT_OBJ(!nodep || privateTypeTest<T>(nodep), nodep, UASSERT_OBJ(!nodep || privateTypeTest<T>(nodep), nodep,
"AstNode is not of expected type, but instead has type '" << nodep->typeName() "AstNode is not of expected type, but instead has type '" << nodep->typeName()
<< "'"); << "'");
@ -2683,6 +2686,8 @@ public:
} }
template <typename T, typename E> template <typename T, typename E>
static const T* privateAs(const AstNode* nodep) VL_PURE { static const T* privateAs(const AstNode* nodep) VL_PURE {
static_assert(!uselessCast<T, E>(), "Unnecessary VN_AS, node known to have target type.");
static_assert(!impossibleCast<T, E>(), "Unnecessary VN_AS, node cannot be this type.");
UASSERT_OBJ(!nodep || privateTypeTest<T>(nodep), nodep, UASSERT_OBJ(!nodep || privateTypeTest<T>(nodep), nodep,
"AstNode is not of expected type, but instead has type '" << nodep->typeName() "AstNode is not of expected type, but instead has type '" << nodep->typeName()
<< "'"); << "'");

View File

@ -94,11 +94,11 @@ AstRange::AstRange(FileLine* fl, const VNumRange& range)
rightp(new AstConst{fl, static_cast<uint32_t>(range.right())}); rightp(new AstConst{fl, static_cast<uint32_t>(range.right())});
} }
int AstRange::leftConst() const VL_MT_STABLE { int AstRange::leftConst() const VL_MT_STABLE {
AstConst* const constp = VN_CAST(leftp(), Const); const AstConst* const constp = VN_CAST(leftp(), Const);
return (constp ? constp->toSInt() : 0); return (constp ? constp->toSInt() : 0);
} }
int AstRange::rightConst() const VL_MT_STABLE { int AstRange::rightConst() const VL_MT_STABLE {
AstConst* const constp = VN_CAST(rightp(), Const); const AstConst* const constp = VN_CAST(rightp(), Const);
return (constp ? constp->toSInt() : 0); return (constp ? constp->toSInt() : 0);
} }
@ -129,7 +129,7 @@ AstPackArrayDType::AstPackArrayDType(FileLine* fl, AstNodeDType* dtp, AstRange*
} }
int AstQueueDType::boundConst() const VL_MT_STABLE { int AstQueueDType::boundConst() const VL_MT_STABLE {
AstConst* const constp = VN_CAST(boundp(), Const); const AstConst* const constp = VN_CAST(boundp(), Const);
return (constp ? constp->toSInt() : 0); return (constp ? constp->toSInt() : 0);
} }
@ -193,7 +193,7 @@ bool AstVarRef::sameNode(const AstVarRef* samep) const {
&& (varp() && samep->varp() && varp()->name() == samep->varp()->name())); && (varp() && samep->varp() && varp()->name() == samep->varp()->name()));
} }
} }
bool AstVarRef::sameNoLvalue(AstVarRef* samep) const { bool AstVarRef::sameNoLvalue(const AstVarRef* samep) const {
if (varScopep()) { if (varScopep()) {
return (varScopep() == samep->varScopep()); return (varScopep() == samep->varScopep());
} else { } else {

View File

@ -792,7 +792,7 @@ public:
private: private:
string m_name; // Name from upper typedef, if any string m_name; // Name from upper typedef, if any
const int m_uniqueNum = 0; const int m_uniqueNum;
TableMap m_tableMap; // Created table for V3Width only to remove duplicates TableMap m_tableMap; // Created table for V3Width only to remove duplicates
public: public:

View File

@ -656,6 +656,7 @@ public:
childDTypep(dtp); childDTypep(dtp);
dtypeFrom(dtp); dtypeFrom(dtp);
} }
// cppcheck-suppress constParameterPointer
AstCast(FileLine* fl, AstNodeExpr* fromp, AstNodeDType* dtp) AstCast(FileLine* fl, AstNodeExpr* fromp, AstNodeDType* dtp)
: ASTGEN_SUPER_Cast(fl) { : ASTGEN_SUPER_Cast(fl) {
this->fromp(fromp); this->fromp(fromp);
@ -791,14 +792,17 @@ class AstConsDynArray final : public AstNodeExpr {
// Construct a queue and return object, '{}. '{lhs}, '{lhs. rhs} // Construct a queue and return object, '{}. '{lhs}, '{lhs. rhs}
// @astgen op1 := lhsp : Optional[AstNode] // @astgen op1 := lhsp : Optional[AstNode]
// @astgen op2 := rhsp : Optional[AstNode] // @astgen op2 := rhsp : Optional[AstNode]
const bool m_lhsIsValue = false; // LHS constructs value inside the queue, not concat const bool m_lhsIsValue; // LHS constructs value inside the queue, not concat
const bool m_rhsIsValue = false; // RHS constructs value inside the queue, not concat const bool m_rhsIsValue; // RHS constructs value inside the queue, not concat
public: public:
explicit AstConsDynArray(FileLine* fl) explicit AstConsDynArray(FileLine* fl)
: ASTGEN_SUPER_ConsDynArray(fl) {} : ASTGEN_SUPER_ConsDynArray(fl)
, m_lhsIsValue{false}
, m_rhsIsValue{false} {}
explicit AstConsDynArray(FileLine* fl, bool lhsIsValue, AstNode* lhsp) explicit AstConsDynArray(FileLine* fl, bool lhsIsValue, AstNode* lhsp)
: ASTGEN_SUPER_ConsDynArray(fl) : ASTGEN_SUPER_ConsDynArray(fl)
, m_lhsIsValue{lhsIsValue} { , m_lhsIsValue{lhsIsValue}
, m_rhsIsValue{false} {
this->lhsp(lhsp); this->lhsp(lhsp);
} }
explicit AstConsDynArray(FileLine* fl, bool lhsIsValue, AstNode* lhsp, bool rhsIsValue, explicit AstConsDynArray(FileLine* fl, bool lhsIsValue, AstNode* lhsp, bool rhsIsValue,
@ -873,14 +877,17 @@ class AstConsQueue final : public AstNodeExpr {
// Construct a queue and return object, '{}. '{lhs}, '{lhs. rhs} // Construct a queue and return object, '{}. '{lhs}, '{lhs. rhs}
// @astgen op1 := lhsp : Optional[AstNode] // @astgen op1 := lhsp : Optional[AstNode]
// @astgen op2 := rhsp : Optional[AstNode] // @astgen op2 := rhsp : Optional[AstNode]
const bool m_lhsIsValue = false; // LHS constructs value inside the queue, not concat const bool m_lhsIsValue; // LHS constructs value inside the queue, not concat
const bool m_rhsIsValue = false; // RHS constructs value inside the queue, not concat const bool m_rhsIsValue; // RHS constructs value inside the queue, not concat
public: public:
explicit AstConsQueue(FileLine* fl) explicit AstConsQueue(FileLine* fl)
: ASTGEN_SUPER_ConsQueue(fl) {} : ASTGEN_SUPER_ConsQueue(fl)
, m_lhsIsValue{false}
, m_rhsIsValue{false} {}
explicit AstConsQueue(FileLine* fl, bool lhsIsValue, AstNode* lhsp) explicit AstConsQueue(FileLine* fl, bool lhsIsValue, AstNode* lhsp)
: ASTGEN_SUPER_ConsQueue(fl) : ASTGEN_SUPER_ConsQueue(fl)
, m_lhsIsValue{lhsIsValue} { , m_lhsIsValue{lhsIsValue}
, m_rhsIsValue{false} {
this->lhsp(lhsp); this->lhsp(lhsp);
} }
explicit AstConsQueue(FileLine* fl, bool lhsIsValue, AstNode* lhsp, bool rhsIsValue, explicit AstConsQueue(FileLine* fl, bool lhsIsValue, AstNode* lhsp, bool rhsIsValue,
@ -1116,6 +1123,8 @@ private:
const int m_srcElementBits; // num bits in rhs (ex 8 if from byte-queue, 1 if from bit-queue) const int m_srcElementBits; // num bits in rhs (ex 8 if from byte-queue, 1 if from bit-queue)
public: public:
// cppcheck-suppress constParameterPointer
// cppcheck-suppress constParameterCallback
AstCvtArrayToArray(FileLine* fl, AstNodeExpr* fromp, AstNodeDType* dtp, bool reverse, AstCvtArrayToArray(FileLine* fl, AstNodeExpr* fromp, AstNodeDType* dtp, bool reverse,
int blockSize, int dstElementBits, int srcElementBits) int blockSize, int dstElementBits, int srcElementBits)
: ASTGEN_SUPER_CvtArrayToArray(fl) : ASTGEN_SUPER_CvtArrayToArray(fl)
@ -1141,6 +1150,8 @@ class AstCvtArrayToPacked final : public AstNodeExpr {
// Cast from dynamic queue data type to packed array // Cast from dynamic queue data type to packed array
// @astgen op1 := fromp : AstNodeExpr // @astgen op1 := fromp : AstNodeExpr
public: public:
// cppcheck-suppress constParameterPointer
// cppcheck-suppress constParameterCallback
AstCvtArrayToPacked(FileLine* fl, AstNodeExpr* fromp, AstNodeDType* dtp) AstCvtArrayToPacked(FileLine* fl, AstNodeExpr* fromp, AstNodeDType* dtp)
: ASTGEN_SUPER_CvtArrayToPacked(fl) { : ASTGEN_SUPER_CvtArrayToPacked(fl) {
this->fromp(fromp); this->fromp(fromp);
@ -1155,6 +1166,8 @@ class AstCvtPackedToArray final : public AstNodeExpr {
// Cast from packed array to dynamic/unpacked queue data type // Cast from packed array to dynamic/unpacked queue data type
// @astgen op1 := fromp : AstNodeExpr // @astgen op1 := fromp : AstNodeExpr
public: public:
// cppcheck-suppress constParameterPointer
// cppcheck-suppress constParameterCallback
AstCvtPackedToArray(FileLine* fl, AstNodeExpr* fromp, AstNodeDType* dtp) AstCvtPackedToArray(FileLine* fl, AstNodeExpr* fromp, AstNodeDType* dtp)
: ASTGEN_SUPER_CvtPackedToArray(fl) { : ASTGEN_SUPER_CvtPackedToArray(fl) {
this->fromp(fromp); this->fromp(fromp);
@ -1169,6 +1182,8 @@ class AstCvtUnpackedToQueue final : public AstNodeExpr {
// Cast from unpacked array to dynamic/unpacked queue data type // Cast from unpacked array to dynamic/unpacked queue data type
// @astgen op1 := fromp : AstNodeExpr // @astgen op1 := fromp : AstNodeExpr
public: public:
// cppcheck-suppress constParameterPointer
// cppcheck-suppress constParameterCallback
AstCvtUnpackedToQueue(FileLine* fl, AstNodeExpr* fromp, AstNodeDType* dtp) AstCvtUnpackedToQueue(FileLine* fl, AstNodeExpr* fromp, AstNodeDType* dtp)
: ASTGEN_SUPER_CvtUnpackedToQueue(fl) { : ASTGEN_SUPER_CvtUnpackedToQueue(fl) {
this->fromp(fromp); this->fromp(fromp);
@ -1604,7 +1619,6 @@ class AstLambdaArgRef final : public AstNodeExpr {
// Lambda argument usage // Lambda argument usage
// These are not AstVarRefs because we need to be able to delete/clone lambdas during // These are not AstVarRefs because we need to be able to delete/clone lambdas during
// optimizations and AstVar's are painful to remove. // optimizations and AstVar's are painful to remove.
ASTGEN_MEMBERS_AstLambdaArgRef;
private: private:
string m_name; // Name of variable string m_name; // Name of variable
@ -1615,6 +1629,7 @@ public:
: ASTGEN_SUPER_LambdaArgRef(fl) : ASTGEN_SUPER_LambdaArgRef(fl)
, m_name{name} , m_name{name}
, m_index{index} {} , m_index{index} {}
ASTGEN_MEMBERS_AstLambdaArgRef;
bool sameNode(const AstNode* /*samep*/) const override { return true; } bool sameNode(const AstNode* /*samep*/) const override { return true; }
string emitVerilog() override { return name(); } string emitVerilog() override { return name(); }
string emitC() override { V3ERROR_NA_RETURN(""); } string emitC() override { V3ERROR_NA_RETURN(""); }
@ -1812,7 +1827,7 @@ class AstRand final : public AstNodeExpr {
// $random/$random(seed) or $urandom/$urandom(seed) // $random/$random(seed) or $urandom/$urandom(seed)
// Return a random number, based upon width() // Return a random number, based upon width()
// @astgen op1 := seedp : Optional[AstNode] // @astgen op1 := seedp : Optional[AstNode]
const bool m_urandom = false; // $urandom vs $random const bool m_urandom; // $urandom vs $random
public: public:
class Reset {}; class Reset {};
AstRand(FileLine* fl, AstNode* seedp, bool urandom) AstRand(FileLine* fl, AstNode* seedp, bool urandom)
@ -1994,7 +2009,7 @@ class AstScopeName final : public AstNodeExpr {
// @astgen op1 := scopeAttrp : List[AstText] // @astgen op1 := scopeAttrp : List[AstText]
// @astgen op2 := scopeEntrp : List[AstText] // @astgen op2 := scopeEntrp : List[AstText]
bool m_dpiExport = false; // Is for dpiExport bool m_dpiExport = false; // Is for dpiExport
const bool m_forFormat = false; // Is for a format %m const bool m_forFormat; // Is for a format %m
string scopeNameFormatter(AstText* scopeTextp) const; string scopeNameFormatter(AstText* scopeTextp) const;
string scopePrettyNameFormatter(AstText* scopeTextp) const; string scopePrettyNameFormatter(AstText* scopeTextp) const;
@ -4211,7 +4226,7 @@ public:
// === AstNodeSel === // === AstNodeSel ===
class AstArraySel final : public AstNodeSel { class AstArraySel final : public AstNodeSel {
void init(AstNode* fromp) { void init(const AstNode* fromp) {
if (fromp && VN_IS(fromp->dtypep()->skipRefp(), NodeArrayDType)) { if (fromp && VN_IS(fromp->dtypep()->skipRefp(), NodeArrayDType)) {
// Strip off array to find what array references // Strip off array to find what array references
dtypeFrom(VN_AS(fromp->dtypep()->skipRefp(), NodeArrayDType)->subDTypep()); dtypeFrom(VN_AS(fromp->dtypep()->skipRefp(), NodeArrayDType)->subDTypep());
@ -4251,7 +4266,7 @@ public:
static AstNode* baseFromp(AstNode* nodep, bool overMembers); static AstNode* baseFromp(AstNode* nodep, bool overMembers);
}; };
class AstAssocSel final : public AstNodeSel { class AstAssocSel final : public AstNodeSel {
void init(AstNode* fromp) { void init(const AstNode* fromp) {
if (fromp && VN_IS(fromp->dtypep()->skipRefp(), AssocArrayDType)) { if (fromp && VN_IS(fromp->dtypep()->skipRefp(), AssocArrayDType)) {
// Strip off array to find what array references // Strip off array to find what array references
dtypeFrom(VN_AS(fromp->dtypep()->skipRefp(), AssocArrayDType)->subDTypep()); dtypeFrom(VN_AS(fromp->dtypep()->skipRefp(), AssocArrayDType)->subDTypep());
@ -4285,7 +4300,7 @@ public:
int instrCount() const override { return widthInstrs(); } int instrCount() const override { return widthInstrs(); }
}; };
class AstWildcardSel final : public AstNodeSel { class AstWildcardSel final : public AstNodeSel {
void init(AstNode* fromp) { void init(const AstNode* fromp) {
if (fromp && VN_IS(fromp->dtypep()->skipRefp(), WildcardArrayDType)) { if (fromp && VN_IS(fromp->dtypep()->skipRefp(), WildcardArrayDType)) {
// Strip off array to find what array references // Strip off array to find what array references
dtypeFrom(VN_AS(fromp->dtypep()->skipRefp(), WildcardArrayDType)->subDTypep()); dtypeFrom(VN_AS(fromp->dtypep()->skipRefp(), WildcardArrayDType)->subDTypep());
@ -4976,6 +4991,8 @@ public:
dtypeSetLogicUnsized(setwidth, minwidth, VSigning::UNSIGNED); dtypeSetLogicUnsized(setwidth, minwidth, VSigning::UNSIGNED);
} }
} }
// cppcheck-suppress constParameterPointer
// cppcheck-suppress constParameterCallback
AstCCast(FileLine* fl, AstNodeExpr* lhsp, AstNode* typeFromp) AstCCast(FileLine* fl, AstNodeExpr* lhsp, AstNode* typeFromp)
: ASTGEN_SUPER_CCast(fl, lhsp) { : ASTGEN_SUPER_CCast(fl, lhsp) {
dtypeFrom(typeFromp); dtypeFrom(typeFromp);
@ -5768,7 +5785,7 @@ public:
const char* broken() const override; const char* broken() const override;
bool sameNode(const AstNode* samep) const override; bool sameNode(const AstNode* samep) const override;
inline bool sameNode(const AstVarRef* samep) const; inline bool sameNode(const AstVarRef* samep) const;
inline bool sameNoLvalue(AstVarRef* samep) const; inline bool sameNoLvalue(const AstVarRef* samep) const;
int instrCount() const override; int instrCount() const override;
string emitVerilog() override { V3ERROR_NA_RETURN(""); } string emitVerilog() override { V3ERROR_NA_RETURN(""); }
string emitC() override { V3ERROR_NA_RETURN(""); } string emitC() override { V3ERROR_NA_RETURN(""); }

View File

@ -784,7 +784,7 @@ class AstClassExtends final : public AstNode {
// @astgen op1 := childDTypep : Optional[AstNodeDType] // @astgen op1 := childDTypep : Optional[AstNodeDType]
// @astgen op2 := classOrPkgsp : Optional[AstNode] // @astgen op2 := classOrPkgsp : Optional[AstNode]
// @astgen op3 := argsp : List[AstNodeExpr] // @astgen op3 := argsp : List[AstNodeExpr]
const bool m_isImplements = false; // class implements const bool m_isImplements; // class implements
bool m_parameterized = false; // has parameters in its statement bool m_parameterized = false; // has parameters in its statement
public: public:
@ -812,8 +812,8 @@ class AstClocking final : public AstNode {
// @astgen op2 := itemsp : List[AstClockingItem] // @astgen op2 := itemsp : List[AstClockingItem]
// @astgen op3 := eventp : Optional[AstVar] // @astgen op3 := eventp : Optional[AstVar]
std::string m_name; // Clocking block name std::string m_name; // Clocking block name
const bool m_isDefault = false; // True if default clocking const bool m_isDefault; // True if default clocking
const bool m_isGlobal = false; // True if global clocking const bool m_isGlobal; // True if global clocking
public: public:
AstClocking(FileLine* fl, const std::string& name, AstSenItem* sensesp, AstClocking(FileLine* fl, const std::string& name, AstSenItem* sensesp,
@ -1531,7 +1531,7 @@ public:
// Create new MODULETEMP variable under this scope // Create new MODULETEMP variable under this scope
AstVarScope* createTemp(const string& name, unsigned width); AstVarScope* createTemp(const string& name, unsigned width);
AstVarScope* createTemp(const string& name, AstNodeDType* dtypep); AstVarScope* createTemp(const string& name, AstNodeDType* dtypep);
AstVarScope* createTempLike(const string& name, AstVarScope* vscp); AstVarScope* createTempLike(const string& name, const AstVarScope* vscp);
}; };
class AstSenItem final : public AstNode { class AstSenItem final : public AstNode {
// Parents: SENTREE // Parents: SENTREE
@ -1961,7 +1961,7 @@ public:
combineType(type); combineType(type);
dtypeSetBitSized(wantwidth, VSigning::UNSIGNED); dtypeSetBitSized(wantwidth, VSigning::UNSIGNED);
} }
AstVar(FileLine* fl, VVarType type, const string& name, AstVar* examplep) AstVar(FileLine* fl, VVarType type, const string& name, const AstVar* examplep)
: ASTGEN_SUPER_Var(fl) : ASTGEN_SUPER_Var(fl)
, m_name{name} , m_name{name}
, m_origName{name} { , m_origName{name} {
@ -2133,7 +2133,7 @@ public:
bool isGParam() const { return varType() == VVarType::GPARAM; } bool isGParam() const { return varType() == VVarType::GPARAM; }
bool isGenVar() const { return varType() == VVarType::GENVAR; } bool isGenVar() const { return varType() == VVarType::GENVAR; }
bool isBitLogic() const { bool isBitLogic() const {
AstBasicDType* bdtypep = basicp(); const AstBasicDType* const bdtypep = basicp();
return bdtypep && bdtypep->isBitLogic(); return bdtypep && bdtypep->isBitLogic();
} }
bool isUsedClock() const VL_MT_SAFE { return m_usedClock; } bool isUsedClock() const VL_MT_SAFE { return m_usedClock; }
@ -2486,7 +2486,7 @@ public:
&& std::is_base_of<AstNode, T_Node>::value, && std::is_base_of<AstNode, T_Node>::value,
"T_Callable 'f' must have a signature compatible with 'void(AstClass*, T_Node*)', " "T_Callable 'f' must have a signature compatible with 'void(AstClass*, T_Node*)', "
"with 'T_Node' being a subtype of 'AstNode'"); "with 'T_Node' being a subtype of 'AstNode'");
if (AstClassExtends* const cextendsp = this->extendsp()) { if (const AstClassExtends* const cextendsp = this->extendsp()) {
cextendsp->classp()->foreachMember(f); cextendsp->classp()->foreachMember(f);
} }
for (AstNode* stmtp = stmtsp(); stmtp; stmtp = stmtp->nextp()) { for (AstNode* stmtp = stmtsp(); stmtp; stmtp = stmtp->nextp()) {
@ -2502,7 +2502,7 @@ public:
&& std::is_base_of<AstNode, T_Node>::value, && std::is_base_of<AstNode, T_Node>::value,
"Predicate 'p' must have a signature compatible with 'bool(const AstClass*, " "Predicate 'p' must have a signature compatible with 'bool(const AstClass*, "
"const T_Node*)', with 'T_Node' being a subtype of 'AstNode'"); "const T_Node*)', with 'T_Node' being a subtype of 'AstNode'");
if (AstClassExtends* const cextendsp = this->extendsp()) { if (const AstClassExtends* const cextendsp = this->extendsp()) {
if (cextendsp->classp()->existsMember(p)) return true; if (cextendsp->classp()->existsMember(p)) return true;
} }
for (AstNode* stmtp = stmtsp(); stmtp; stmtp = stmtp->nextp()) { for (AstNode* stmtp = stmtsp(); stmtp; stmtp = stmtp->nextp()) {
@ -2540,18 +2540,22 @@ public:
}; };
class AstModule final : public AstNodeModule { class AstModule final : public AstNodeModule {
// A module declaration // A module declaration
const bool m_isChecker = false; // Module represents a checker const bool m_isChecker; // Module represents a checker
const bool m_isProgram = false; // Module represents a program const bool m_isProgram; // Module represents a program
public: public:
class Checker {}; // for constructor type-overload selection class Checker {}; // for constructor type-overload selection
class Program {}; // for constructor type-overload selection class Program {}; // for constructor type-overload selection
AstModule(FileLine* fl, const string& name, const string& libname) AstModule(FileLine* fl, const string& name, const string& libname)
: ASTGEN_SUPER_Module(fl, name, libname) {} : ASTGEN_SUPER_Module(fl, name, libname)
, m_isChecker{false}
, m_isProgram{false} {}
AstModule(FileLine* fl, const string& name, const string& libname, Checker) AstModule(FileLine* fl, const string& name, const string& libname, Checker)
: ASTGEN_SUPER_Module(fl, name, libname) : ASTGEN_SUPER_Module(fl, name, libname)
, m_isChecker{true} {} , m_isChecker{true}
, m_isProgram{false} {}
AstModule(FileLine* fl, const string& name, const string& libname, Program) AstModule(FileLine* fl, const string& name, const string& libname, Program)
: ASTGEN_SUPER_Module(fl, name, libname) : ASTGEN_SUPER_Module(fl, name, libname)
, m_isChecker{false}
, m_isProgram{true} {} , m_isProgram{true} {}
ASTGEN_MEMBERS_AstModule; ASTGEN_MEMBERS_AstModule;
string verilogKwd() const override { string verilogKwd() const override {

View File

@ -845,6 +845,7 @@ public:
this->exprp(exprp); this->exprp(exprp);
} }
ASTGEN_MEMBERS_AstStmtExpr; ASTGEN_MEMBERS_AstStmtExpr;
// cppcheck-suppress uselessOverride
bool isPure() override { return exprp()->isPure(); } bool isPure() override { return exprp()->isPure(); }
}; };
class AstStop final : public AstNodeStmt { class AstStop final : public AstNodeStmt {

View File

@ -542,18 +542,16 @@ string AstVar::vlArgType(bool named, bool forReturn, bool forFunc, const string&
string ostatic; string ostatic;
if (isStatic() && namespc.empty()) ostatic = "static "; if (isStatic() && namespc.empty()) ostatic = "static ";
const bool isRef = isDpiOpenArray() asRef = asRef || isDpiOpenArray() || (forFunc && (isWritable() || isRef() || isConstRef()));
|| (forFunc && (isWritable() || this->isRef() || this->isConstRef()))
|| asRef;
if (forFunc && isReadOnly() && isRef) ostatic = ostatic + "const "; if (forFunc && isReadOnly() && asRef) ostatic = ostatic + "const ";
string oname; string oname;
if (named) { if (named) {
if (!namespc.empty()) oname += namespc + "::"; if (!namespc.empty()) oname += namespc + "::";
oname += VIdProtect::protectIf(name(), protect()); oname += VIdProtect::protectIf(name(), protect());
} }
return ostatic + dtypep()->cType(oname, forFunc, isRef); return ostatic + dtypep()->cType(oname, forFunc, asRef);
} }
string AstVar::vlEnumType() const { string AstVar::vlEnumType() const {
@ -687,7 +685,7 @@ string AstVar::cPubArgType(bool named, bool forReturn) const {
if (forReturn) named = false; if (forReturn) named = false;
string arg; string arg;
if (isWide() && isReadOnly()) arg += "const "; if (isWide() && isReadOnly()) arg += "const ";
const bool isRef = !forReturn && (isWritable() || this->isRef() || this->isConstRef()); const bool asRef = !forReturn && (isWritable() || this->isRef() || this->isConstRef());
if (VN_IS(dtypeSkipRefp(), BasicDType) && !dtypeSkipRefp()->isDouble() if (VN_IS(dtypeSkipRefp(), BasicDType) && !dtypeSkipRefp()->isDouble()
&& !dtypeSkipRefp()->isString()) { && !dtypeSkipRefp()->isString()) {
// Backward compatible type declaration // Backward compatible type declaration
@ -708,12 +706,12 @@ string AstVar::cPubArgType(bool named, bool forReturn) const {
arg += " (& " + name(); arg += " (& " + name();
arg += ")[" + cvtToStr(widthWords()) + "]"; arg += ")[" + cvtToStr(widthWords()) + "]";
} else { } else {
if (isRef) arg += "&"; if (asRef) arg += "&";
if (named) arg += " " + name(); if (named) arg += " " + name();
} }
} else { } else {
// Newer internal-compatible types // Newer internal-compatible types
arg += dtypep()->cType((named ? name() : std::string{}), true, isRef); arg += dtypep()->cType((named ? name() : std::string{}), true, asRef);
} }
return arg; return arg;
} }
@ -775,7 +773,7 @@ string AstVar::dpiTmpVarType(const string& varName) const {
class converter final : public dpiTypesToStringConverter { class converter final : public dpiTypesToStringConverter {
const string m_name; const string m_name;
string arraySuffix(const AstVar* varp, size_t n) const { string arraySuffix(const AstVar* varp, size_t n) const {
if (AstUnpackArrayDType* const unpackp if (const AstUnpackArrayDType* const unpackp
= VN_CAST(varp->dtypep()->skipRefp(), UnpackArrayDType)) { = VN_CAST(varp->dtypep()->skipRefp(), UnpackArrayDType)) {
// Convert multi dimensional unpacked array to 1D array // Convert multi dimensional unpacked array to 1D array
if (n == 0) n = 1; if (n == 0) n = 1;
@ -849,13 +847,13 @@ AstVar* AstVar::scVarRecurse(AstNode* nodep) {
} else { } else {
return nullptr; return nullptr;
} }
} else if (AstVarRef* const vrefp = VN_CAST(nodep, VarRef)) { } else if (const AstVarRef* const vrefp = VN_CAST(nodep, VarRef)) {
if (vrefp->varp()->isSc()) { if (vrefp->varp()->isSc()) {
return vrefp->varp(); return vrefp->varp();
} else { } else {
return nullptr; return nullptr;
} }
} else if (AstArraySel* const arraySelp = VN_CAST(nodep, ArraySel)) { } else if (const AstArraySel* const arraySelp = VN_CAST(nodep, ArraySel)) {
if (AstVar* const p = scVarRecurse(arraySelp->fromp())) return p; if (AstVar* const p = scVarRecurse(arraySelp->fromp())) return p;
} }
return nullptr; return nullptr;
@ -1194,7 +1192,7 @@ AstVarScope* AstScope::createTemp(const string& name, AstNodeDType* dtypep) {
return vscp; return vscp;
} }
AstVarScope* AstScope::createTempLike(const string& name, AstVarScope* vscp) { AstVarScope* AstScope::createTempLike(const string& name, const AstVarScope* vscp) {
return createTemp(name, vscp->dtypep()); return createTemp(name, vscp->dtypep());
} }
@ -1568,7 +1566,7 @@ void AstNode::dump(std::ostream& str) const {
} else { } else {
str << " @dt=" << nodeAddr(dtypep()) << "@"; str << " @dt=" << nodeAddr(dtypep()) << "@";
} }
if (AstNodeDType* const dtp = dtypep()) dtp->dumpSmall(str); if (const AstNodeDType* const dtp = dtypep()) dtp->dumpSmall(str);
} else { // V3Broken will throw an error } else { // V3Broken will throw an error
if (dtypep()) str << " %Error-dtype-exp=null,got=" << nodeAddr(dtypep()); if (dtypep()) str << " %Error-dtype-exp=null,got=" << nodeAddr(dtypep());
} }
@ -2217,10 +2215,10 @@ void AstRefDType::dump(std::ostream& str) const {
if (!s_recursing) { // Prevent infinite dump if circular typedefs if (!s_recursing) { // Prevent infinite dump if circular typedefs
s_recursing = true; s_recursing = true;
str << " -> "; str << " -> ";
if (const auto subp = subDTypep()) { if (const AstNodeDType* const subp = subDTypep()) {
if (typedefp()) str << "typedef=" << static_cast<void*>(typedefp()) << " -> "; if (typedefp()) str << "typedef=" << static_cast<void*>(typedefp()) << " -> ";
subp->dump(str); subp->dump(str);
} else if (const auto subp = typedefp()) { } else if (const AstTypedef* const subp = typedefp()) {
subp->dump(str); subp->dump(str);
} }
s_recursing = false; s_recursing = false;
@ -2264,7 +2262,7 @@ string AstNodeUOrStructDType::prettyDTypeName(bool full) const {
void AstNodeDType::dump(std::ostream& str) const { void AstNodeDType::dump(std::ostream& str) const {
this->AstNode::dump(str); this->AstNode::dump(str);
if (generic()) str << " [GENERIC]"; if (generic()) str << " [GENERIC]";
if (AstNodeDType* const dtp = virtRefDTypep()) { if (const AstNodeDType* const dtp = virtRefDTypep()) {
str << " refdt=" << nodeAddr(dtp); str << " refdt=" << nodeAddr(dtp);
dtp->dumpSmall(str); dtp->dumpSmall(str);
} }
@ -2476,7 +2474,7 @@ void AstMTaskBody::dumpJson(std::ostream& str) const {
void AstTypeTable::dump(std::ostream& str) const { void AstTypeTable::dump(std::ostream& str) const {
this->AstNode::dump(str); this->AstNode::dump(str);
for (int i = 0; i < static_cast<int>(VBasicDTypeKwd::_ENUM_MAX); ++i) { for (int i = 0; i < static_cast<int>(VBasicDTypeKwd::_ENUM_MAX); ++i) {
if (AstBasicDType* const subnodep = m_basicps[i]) { if (const AstBasicDType* const subnodep = m_basicps[i]) {
str << '\n'; // Newline from caller, so newline first str << '\n'; // Newline from caller, so newline first
str << "\t\t" << std::setw(8) << VBasicDTypeKwd{i}.ascii(); str << "\t\t" << std::setw(8) << VBasicDTypeKwd{i}.ascii();
str << " -> "; str << " -> ";
@ -2486,7 +2484,7 @@ void AstTypeTable::dump(std::ostream& str) const {
{ {
const DetailedMap& mapr = m_detailedMap; const DetailedMap& mapr = m_detailedMap;
for (const auto& itr : mapr) { for (const auto& itr : mapr) {
AstBasicDType* const dtypep = itr.second; const AstBasicDType* const dtypep = itr.second;
str << '\n'; // Newline from caller, so newline first str << '\n'; // Newline from caller, so newline first
str << "\t\tdetailed -> "; str << "\t\tdetailed -> ";
dtypep->dump(str); dtypep->dump(str);
@ -2591,15 +2589,21 @@ void AstNodeVarRef::dumpJson(std::ostream& str) const {
AstNodeVarRef* AstNodeVarRef::varRefLValueRecurse(AstNode* nodep) { AstNodeVarRef* AstNodeVarRef::varRefLValueRecurse(AstNode* nodep) {
// Given a (possible) lvalue expression, recurse to find the being-set NodeVarRef, else nullptr // Given a (possible) lvalue expression, recurse to find the being-set NodeVarRef, else nullptr
if (AstNodeVarRef* const anodep = VN_CAST(nodep, NodeVarRef)) return anodep; if (AstNodeVarRef* const anodep = VN_CAST(nodep, NodeVarRef)) return anodep;
if (AstNodeSel* const anodep = VN_CAST(nodep, NodeSel)) if (const AstNodeSel* const anodep = VN_CAST(nodep, NodeSel)) {
return varRefLValueRecurse(anodep->fromp()); return varRefLValueRecurse(anodep->fromp());
if (AstSel* const anodep = VN_CAST(nodep, Sel)) return varRefLValueRecurse(anodep->fromp()); }
if (AstArraySel* const anodep = VN_CAST(nodep, ArraySel)) if (const AstSel* const anodep = VN_CAST(nodep, Sel)) {
return varRefLValueRecurse(anodep->fromp()); return varRefLValueRecurse(anodep->fromp());
if (AstMemberSel* const anodep = VN_CAST(nodep, MemberSel)) }
if (const AstArraySel* const anodep = VN_CAST(nodep, ArraySel)) {
return varRefLValueRecurse(anodep->fromp()); return varRefLValueRecurse(anodep->fromp());
if (AstStructSel* const anodep = VN_CAST(nodep, StructSel)) }
if (const AstMemberSel* const anodep = VN_CAST(nodep, MemberSel)) {
return varRefLValueRecurse(anodep->fromp()); return varRefLValueRecurse(anodep->fromp());
}
if (const AstStructSel* const anodep = VN_CAST(nodep, StructSel)) {
return varRefLValueRecurse(anodep->fromp());
}
return nullptr; return nullptr;
} }
@ -2796,9 +2800,12 @@ AstNodeModule* AstClassOrPackageRef::classOrPackageSkipp() const {
if (AstNodeDType* const anodep = VN_CAST(foundp, NodeDType)) { if (AstNodeDType* const anodep = VN_CAST(foundp, NodeDType)) {
foundp = anodep->skipRefOrNullp(); foundp = anodep->skipRefOrNullp();
} }
if (AstTypedef* const anodep = VN_CAST(foundp, Typedef)) foundp = anodep->subDTypep(); if (const AstTypedef* const anodep = VN_CAST(foundp, Typedef)) {
if (AstClassRefDType* const anodep = VN_CAST(foundp, ClassRefDType)) foundp = anodep->subDTypep();
}
if (const AstClassRefDType* const anodep = VN_CAST(foundp, ClassRefDType)) {
foundp = anodep->classp(); foundp = anodep->classp();
}
} }
return VN_CAST(foundp, NodeModule); return VN_CAST(foundp, NodeModule);
} }
@ -3076,7 +3083,7 @@ void AstCAwait::dump(std::ostream& str) const {
} }
void AstCAwait::dumpJson(std::ostream& str) const { dumpJsonGen(str); } void AstCAwait::dumpJson(std::ostream& str) const { dumpJsonGen(str); }
int AstCMethodHard::instrCount() const { int AstCMethodHard::instrCount() const {
if (AstBasicDType* const basicp = fromp()->dtypep()->basicp()) { if (const AstBasicDType* const basicp = fromp()->dtypep()->basicp()) {
// TODO: add a more structured description of library methods, rather than using string // TODO: add a more structured description of library methods, rather than using string
// matching. See issue #3715. // matching. See issue #3715.
if (basicp->isTriggerVec() && m_name == "word") { if (basicp->isTriggerVec() && m_name == "word") {
@ -3165,8 +3172,8 @@ void AstCMethodHard::setPurity() {
if (name() == "atWriteAppend" || name() == "atWriteAppendBack") { if (name() == "atWriteAppend" || name() == "atWriteAppendBack") {
m_pure = false; m_pure = false;
// Treat atWriteAppend as pure if the argument is a loop iterator // Treat atWriteAppend as pure if the argument is a loop iterator
if (AstNodeExpr* const argp = pinsp()) { if (const AstNodeExpr* const argp = pinsp()) {
if (AstVarRef* const varrefp = VN_CAST(argp, VarRef)) { if (const AstVarRef* const varrefp = VN_CAST(argp, VarRef)) {
if (varrefp->varp()->isUsedLoopIdx()) m_pure = true; if (varrefp->varp()->isUsedLoopIdx()) m_pure = true;
} }
} }

View File

@ -455,7 +455,7 @@ AstNode* V3Begin::convertToWhile(AstForeach* nodep) {
lastp->unlinkFrBack(&handle); lastp->unlinkFrBack(&handle);
if (const AstNodeArrayDType* const adtypep = VN_CAST(fromDtp, NodeArrayDType)) { if (const AstNodeArrayDType* const adtypep = VN_CAST(fromDtp, NodeArrayDType)) {
loopp = createForeachLoopRanged(nodep, bodyPointp, varp, adtypep->declRange()); loopp = createForeachLoopRanged(nodep, bodyPointp, varp, adtypep->declRange());
} else if (AstBasicDType* const adtypep = VN_CAST(fromDtp, BasicDType)) { } else if (const AstBasicDType* const adtypep = VN_CAST(fromDtp, BasicDType)) {
if (adtypep->isString()) { if (adtypep->isString()) {
AstConst* const leftp = new AstConst{fl, 0}; AstConst* const leftp = new AstConst{fl, 0};
AstNodeExpr* const rightp = new AstLenN{fl, fromp->cloneTreePure(false)}; AstNodeExpr* const rightp = new AstLenN{fl, fromp->cloneTreePure(false)};

View File

@ -51,7 +51,7 @@ class BranchVisitor final : public VNVisitorConst {
m_likely = false; m_likely = false;
m_unlikely = false; m_unlikely = false;
} }
void checkUnlikely(AstNode* nodep) { void checkUnlikely(const AstNode* nodep) {
if (nodep->isUnlikely()) { if (nodep->isUnlikely()) {
UINFO(4, " UNLIKELY: " << nodep); UINFO(4, " UNLIKELY: " << nodep);
m_unlikely++; m_unlikely++;

View File

@ -43,7 +43,7 @@ class CUseVisitor final : public VNVisitorConst {
std::map<std::string, std::pair<FileLine*, VUseType>> m_didUse; // What we already used std::map<std::string, std::pair<FileLine*, VUseType>> m_didUse; // What we already used
// METHODS // METHODS
void addNewUse(AstNode* nodep, VUseType useType, const string& name) { void addNewUse(const AstNode* nodep, VUseType useType, const string& name) {
auto e = m_didUse.emplace(name, std::make_pair(nodep->fileline(), useType)); auto e = m_didUse.emplace(name, std::make_pair(nodep->fileline(), useType));
if (e.second || ((e.first->second.second & useType) != useType)) { if (e.second || ((e.first->second.second & useType) != useType)) {
e.first->second.second = e.first->second.second | useType; e.first->second.second = e.first->second.second | useType;
@ -73,7 +73,8 @@ class CUseVisitor final : public VNVisitorConst {
if (stypep && stypep->classOrPackagep()) { if (stypep && stypep->classOrPackagep()) {
addNewUse(nodep, VUseType::INT_INCLUDE, stypep->classOrPackagep()->name()); addNewUse(nodep, VUseType::INT_INCLUDE, stypep->classOrPackagep()->name());
iterateChildrenConst(stypep); iterateChildrenConst(stypep);
} else if (AstClassRefDType* const classp = VN_CAST(nodep->skipRefp(), ClassRefDType)) { } else if (const AstClassRefDType* const classp
= VN_CAST(nodep->skipRefp(), ClassRefDType)) {
addNewUse(nodep, VUseType::INT_FWD_CLASS, classp->name()); addNewUse(nodep, VUseType::INT_FWD_CLASS, classp->name());
} }
} }
@ -95,7 +96,7 @@ public:
: m_modp{modp} { : m_modp{modp} {
iterateConst(modp); iterateConst(modp);
for (auto& used : m_didUse) { for (const auto& used : m_didUse) {
AstCUse* const newp = new AstCUse{used.second.first, used.second.second, used.first}; AstCUse* const newp = new AstCUse{used.second.first, used.second.second, used.first};
m_modp->addStmtsp(newp); m_modp->addStmtsp(newp);
UINFO(8, "Insert " << newp); UINFO(8, "Insert " << newp);

View File

@ -216,7 +216,7 @@ class CaseVisitor final : public VNVisitor {
const uint32_t val = numval.toUInt(); const uint32_t val = numval.toUInt();
uint32_t firstOverlap = 0; uint32_t firstOverlap = 0;
AstNode* overlappedCondp = nullptr; const AstNode* overlappedCondp = nullptr;
bool foundHit = false; bool foundHit = false;
for (uint32_t i = 0; i < numCases; ++i) { for (uint32_t i = 0; i < numCases; ++i) {
if ((i & mask) == val) { if ((i & mask) == val) {
@ -307,7 +307,7 @@ class CaseVisitor final : public VNVisitor {
// Not done earlier, as we may now have a nullptr because it's just a ";" NOP branch // Not done earlier, as we may now have a nullptr because it's just a ";" NOP branch
for (uint32_t i = 0; i < numCases; ++i) { for (uint32_t i = 0; i < numCases; ++i) {
if (AstNode* const condp = m_valueItem[i]) { if (AstNode* const condp = m_valueItem[i]) {
AstCaseItem* caseItemp = caseItemMap[condp]; const AstCaseItem* const caseItemp = caseItemMap[condp];
UASSERT(caseItemp, "caseItemp should exist"); UASSERT(caseItemp, "caseItemp should exist");
m_valueItem[i] = caseItemp->stmtsp(); m_valueItem[i] = caseItemp->stmtsp();
} }
@ -325,7 +325,7 @@ class CaseVisitor final : public VNVisitor {
} else { } else {
// Make left and right subtrees // Make left and right subtrees
// cexpr[msb:lsb] == 1 // cexpr[msb:lsb] == 1
AstNode* tree0p = replaceCaseFastRecurse(cexprp, msb - 1, upperValue | 0); AstNode* tree0p = replaceCaseFastRecurse(cexprp, msb - 1, upperValue);
AstNode* tree1p = replaceCaseFastRecurse( AstNode* tree1p = replaceCaseFastRecurse(
cexprp, msb - 1, upperValue | (1UL << static_cast<uint32_t>(msb))); cexprp, msb - 1, upperValue | (1UL << static_cast<uint32_t>(msb)));
@ -548,7 +548,7 @@ class CaseVisitor final : public VNVisitor {
} }
} }
bool neverItem(AstCase* casep, AstConst* itemp) { bool neverItem(const AstCase* casep, const AstConst* itemp) {
// Xs in case or casez are impossible due to two state simulations // Xs in case or casez are impossible due to two state simulations
if (casep->casex()) { if (casep->casex()) {
} else if (casep->casez() || casep->caseInside()) { } else if (casep->casez() || casep->caseInside()) {

View File

@ -69,7 +69,7 @@ class CastVisitor final : public VNVisitor {
ensureLower32Cast(castp); ensureLower32Cast(castp);
nodep->user1(1); // Now must be of known size nodep->user1(1); // Now must be of known size
} }
static int castSize(AstNode* nodep) { static int castSize(const AstNode* nodep) {
if (nodep->isQuad()) { if (nodep->isQuad()) {
return VL_QUADSIZE; return VL_QUADSIZE;
} else if (nodep->width() <= 8) { } else if (nodep->width() <= 8) {

View File

@ -83,7 +83,7 @@ class CfgLiveVariables final : VNVisitorConst {
// Check and return if variable is incompatible // Check and return if variable is incompatible
bool incompatible(Variable* varp) { bool incompatible(Variable* varp) {
if (!isSupportedPackedDType(varp->dtypep())) return true; if (!isSupportedPackedDType(varp->dtypep())) return true;
AstVar* astVarp = nullptr; const AstVar* astVarp = nullptr;
// TODO: remove the useless reinterpret_casts when C++17 'if constexpr' actually works // TODO: remove the useless reinterpret_casts when C++17 'if constexpr' actually works
if VL_CONSTEXPR_CXX17 (T_Scoped) { if VL_CONSTEXPR_CXX17 (T_Scoped) {
astVarp = reinterpret_cast<AstVarScope*>(varp)->varp(); astVarp = reinterpret_cast<AstVarScope*>(varp)->varp();

View File

@ -257,7 +257,7 @@ public:
modp->addStmtsp(nodep); modp->addStmtsp(nodep);
} }
// BFS to mark public typedefs. // BFS to mark public typedefs.
std::set<AstNodeUOrStructDType*> pubStrDtypeps; std::set<const AstNodeUOrStructDType*> pubStrDtypeps;
while (!m_pubStrDtypeps.empty()) { while (!m_pubStrDtypeps.empty()) {
AstNodeUOrStructDType* const dtypep = m_pubStrDtypeps.front(); AstNodeUOrStructDType* const dtypep = m_pubStrDtypeps.front();
m_pubStrDtypeps.pop(); m_pubStrDtypeps.pop();
@ -270,7 +270,8 @@ public:
} }
} }
for (AstTypedef* typedefp : m_typedefps) { for (AstTypedef* typedefp : m_typedefps) {
AstNodeUOrStructDType* const sdtypep = VN_AS(typedefp->dtypep(), NodeUOrStructDType); const AstNodeUOrStructDType* const sdtypep
= VN_AS(typedefp->dtypep(), NodeUOrStructDType);
if (pubStrDtypeps.count(sdtypep)) typedefp->attrPublic(true); if (pubStrDtypeps.count(sdtypep)) typedefp->attrPublic(true);
} }
// Clear package pointer of non-public packed struct / union type, which will never be // Clear package pointer of non-public packed struct / union type, which will never be

View File

@ -51,7 +51,7 @@ class CleanVisitor final : public VNVisitor {
// METHODS // METHODS
// Width resetting // Width resetting
int cppWidth(AstNode* nodep) { int cppWidth(const AstNode* nodep) {
if (nodep->width() <= VL_IDATASIZE) { if (nodep->width() <= VL_IDATASIZE) {
return VL_IDATASIZE; return VL_IDATASIZE;
} else if (nodep->width() <= VL_QUADSIZE) { } else if (nodep->width() <= VL_QUADSIZE) {
@ -101,7 +101,9 @@ class CleanVisitor final : public VNVisitor {
// Store the clean state in the userp on each node // Store the clean state in the userp on each node
void setCleanState(AstNode* nodep, CleanState clean) { nodep->user1(clean); } void setCleanState(AstNode* nodep, CleanState clean) { nodep->user1(clean); }
CleanState getCleanState(AstNode* nodep) { return static_cast<CleanState>(nodep->user1()); } CleanState getCleanState(const AstNode* nodep) {
return static_cast<CleanState>(nodep->user1());
}
bool isClean(AstNode* nodep) { bool isClean(AstNode* nodep) {
const CleanState clstate = getCleanState(nodep); const CleanState clstate = getCleanState(nodep);
if (clstate == CS_CLEAN) return true; if (clstate == CS_CLEAN) return true;

View File

@ -170,8 +170,8 @@ class ConstBitOpTreeVisitor final : public VNVisitorConst {
struct BitPolarityEntry final { // Found bit polarity during iterate() struct BitPolarityEntry final { // Found bit polarity during iterate()
LeafInfo m_info; LeafInfo m_info;
bool m_polarity; bool m_polarity = false;
int m_bit; int m_bit = 0;
BitPolarityEntry(const LeafInfo& info, bool pol, int bit) BitPolarityEntry(const LeafInfo& info, bool pol, int bit)
: m_info{info} : m_info{info}
, m_polarity{pol} , m_polarity{pol}
@ -392,7 +392,7 @@ class ConstBitOpTreeVisitor final : public VNVisitorConst {
#define CONST_BITOP_SET_FAILED(reason, nodep) setFailed(true, reason, nodep, __LINE__) #define CONST_BITOP_SET_FAILED(reason, nodep) setFailed(true, reason, nodep, __LINE__)
bool setFailed(bool fail, const char* reason, AstNode* nodep, int line) { bool setFailed(bool fail, const char* reason, const AstNode* nodep, int line) {
if (fail && !m_failed) { if (fail && !m_failed) {
UINFO(9, "cannot optimize " << m_rootp << " reason:" << reason << " called from line:" UINFO(9, "cannot optimize " << m_rootp << " reason:" << reason << " called from line:"
<< line << " when checking:" << nodep); << line << " when checking:" << nodep);
@ -460,7 +460,7 @@ class ConstBitOpTreeVisitor final : public VNVisitorConst {
} }
void visit(AstShiftR* nodep) override { void visit(AstShiftR* nodep) override {
CONST_BITOP_RETURN_IF(!m_leafp, nodep); CONST_BITOP_RETURN_IF(!m_leafp, nodep);
AstConst* const constp = VN_CAST(nodep->rhsp(), Const); const AstConst* const constp = VN_CAST(nodep->rhsp(), Const);
CONST_BITOP_RETURN_IF(!constp, nodep->rhsp()); CONST_BITOP_RETURN_IF(!constp, nodep->rhsp());
m_lsb += constp->toUInt(); m_lsb += constp->toUInt();
incrOps(nodep, __LINE__); incrOps(nodep, __LINE__);
@ -484,7 +484,7 @@ class ConstBitOpTreeVisitor final : public VNVisitorConst {
} }
void visit(AstWordSel* nodep) override { void visit(AstWordSel* nodep) override {
CONST_BITOP_RETURN_IF(!m_leafp, nodep); CONST_BITOP_RETURN_IF(!m_leafp, nodep);
AstConst* const constp = VN_CAST(nodep->bitp(), Const); const AstConst* const constp = VN_CAST(nodep->bitp(), Const);
CONST_BITOP_RETURN_IF(!constp, nodep->bitp()); CONST_BITOP_RETURN_IF(!constp, nodep->bitp());
UASSERT_OBJ(m_leafp->wordIdx() == -1, nodep, "Unexpected nested WordSel"); UASSERT_OBJ(m_leafp->wordIdx() == -1, nodep, "Unexpected nested WordSel");
m_leafp->wordIdx(constp->toSInt()); m_leafp->wordIdx(constp->toSInt());
@ -796,7 +796,7 @@ public:
if (debug() >= 9) { // LCOV_EXCL_START if (debug() >= 9) { // LCOV_EXCL_START
cout << "- Bitop tree considered:\n"; cout << "- Bitop tree considered:\n";
for (AstNodeExpr* const termp : termps) termp->dumpTree("- Reduced term: "); for (const AstNodeExpr* const termp : termps) termp->dumpTree("- Reduced term: ");
for (const std::pair<AstNodeExpr*, FrozenNodeInfo>& termp : visitor.m_frozenNodes) { for (const std::pair<AstNodeExpr*, FrozenNodeInfo>& termp : visitor.m_frozenNodes) {
termp.first->dumpTree("- Frozen term with lsb " termp.first->dumpTree("- Frozen term with lsb "
+ std::to_string(termp.second.m_lsb) + " polarity " + std::to_string(termp.second.m_lsb) + " polarity "
@ -916,7 +916,6 @@ class ConstVisitor final : public VNVisitor {
// AstEnum::user4 -> bool. Recursing. // AstEnum::user4 -> bool. Recursing.
// STATE // STATE
static constexpr bool m_doShort = true; // Remove expressions that short circuit
bool m_params = false; // If true, propagate parameterized and true numbers only bool m_params = false; // If true, propagate parameterized and true numbers only
bool m_required = false; // If true, must become a constant bool m_required = false; // If true, must become a constant
bool m_wremove = true; // Inside scope, no assignw removal bool m_wremove = true; // Inside scope, no assignw removal
@ -949,12 +948,12 @@ class ConstVisitor final : public VNVisitor {
const V3Number& numc = VN_AS(nodep, Const)->num(); const V3Number& numc = VN_AS(nodep, Const)->num();
return !numc.isNumber() ? numc : V3Number{nodep, nodep->widthMinV(), numc}; return !numc.isNumber() ? numc : V3Number{nodep, nodep->widthMinV(), numc};
} }
V3Number toNumC(AstNode* nodep, V3Number& numv) { V3Number toNumC(AstNode* nodep, const V3Number& numv) {
// Extend V width back to C width for given node // Extend V width back to C width for given node
return !numv.isNumber() ? numv : V3Number{nodep, nodep->width(), numv}; return !numv.isNumber() ? numv : V3Number{nodep, nodep->width(), numv};
} }
bool operandConst(AstNode* nodep) { return VN_IS(nodep, Const); } bool operandConst(const AstNode* nodep) { return VN_IS(nodep, Const); }
bool operandAsvConst(const AstNode* nodep) { bool operandAsvConst(const AstNode* nodep) {
// BIASV(CONST, BIASV(CONST,...)) -> BIASV( BIASV_CONSTED(a,b), ...) // BIASV(CONST, BIASV(CONST,...)) -> BIASV( BIASV_CONSTED(a,b), ...)
const AstNodeBiComAsv* const bnodep = VN_CAST(nodep, NodeBiComAsv); const AstNodeBiComAsv* const bnodep = VN_CAST(nodep, NodeBiComAsv);
@ -1022,8 +1021,9 @@ class ConstVisitor final : public VNVisitor {
UASSERT_OBJ(constp && constp->isOne(), andp->lhsp(), "TRREEOPC must meet this condition"); UASSERT_OBJ(constp && constp->isOne(), andp->lhsp(), "TRREEOPC must meet this condition");
AstNodeExpr* const rhsp = andp->rhsp(); AstNodeExpr* const rhsp = andp->rhsp();
AstCCast* ccastp = nullptr; AstCCast* ccastp = nullptr;
const auto isEqOrNeq const auto isEqOrNeq = [](const AstNode* nodep) -> bool { //
= [](AstNode* nodep) -> bool { return VN_IS(nodep, Eq) || VN_IS(nodep, Neq); }; return VN_IS(nodep, Eq) || VN_IS(nodep, Neq);
};
if (isEqOrNeq(rhsp)) { if (isEqOrNeq(rhsp)) {
ccastp = new AstCCast{andp->fileline(), rhsp->unlinkFrBack(), andp}; ccastp = new AstCCast{andp->fileline(), rhsp->unlinkFrBack(), andp};
} else if (AstCCast* const tmpp = VN_CAST(rhsp, CCast)) { } else if (AstCCast* const tmpp = VN_CAST(rhsp, CCast)) {
@ -1352,8 +1352,8 @@ class ConstVisitor final : public VNVisitor {
return false; return false;
} }
AstNodeExpr* const ap = shiftp->lhsp(); AstNodeExpr* const ap = shiftp->lhsp();
AstConst* const bp = VN_AS(shiftp->rhsp(), Const); const AstConst* const bp = VN_AS(shiftp->rhsp(), Const);
AstConst* const lp = VN_AS(nodep->lsbp(), Const); const AstConst* const lp = VN_AS(nodep->lsbp(), Const);
if (bp->isWide() || bp->num().isFourState() || bp->num().isNegative() || lp->isWide() if (bp->isWide() || bp->num().isFourState() || bp->num().isNegative() || lp->isWide()
|| lp->num().isFourState() || lp->num().isNegative()) { || lp->num().isFourState() || lp->num().isNegative()) {
return false; return false;
@ -1402,7 +1402,7 @@ class ConstVisitor final : public VNVisitor {
// Avoids compiler warning // Avoids compiler warning
const AstExtend* const extendp = VN_CAST(nodep->rhsp(), Extend); const AstExtend* const extendp = VN_CAST(nodep->rhsp(), Extend);
if (!extendp) return false; if (!extendp) return false;
AstNode* const smallerp = extendp->lhsp(); const AstNode* const smallerp = extendp->lhsp();
const int subsize = smallerp->width(); const int subsize = smallerp->width();
const AstConst* const constp = VN_CAST(nodep->lhsp(), Const); const AstConst* const constp = VN_CAST(nodep->lhsp(), Const);
if (!constp) return false; if (!constp) return false;
@ -1459,7 +1459,7 @@ class ConstVisitor final : public VNVisitor {
return false; // Not a transform, so NOP return false; // Not a transform, so NOP
} }
static bool operandsSame(AstNode* node1p, AstNode* node2p) { static bool operandsSame(const AstNode* node1p, const AstNode* node2p) {
// For now we just detect constants & simple vars, though it could be more generic // For now we just detect constants & simple vars, though it could be more generic
if (VN_IS(node1p, Const) && VN_IS(node2p, Const)) return node1p->sameGateTree(node2p); if (VN_IS(node1p, Const) && VN_IS(node2p, Const)) return node1p->sameGateTree(node2p);
if (VN_IS(node1p, VarRef) && VN_IS(node2p, VarRef)) { if (VN_IS(node1p, VarRef) && VN_IS(node2p, VarRef)) {
@ -1469,8 +1469,8 @@ class ConstVisitor final : public VNVisitor {
return node1p->isSame(node2p); return node1p->isSame(node2p);
} }
// Pattern created by coverage-line; avoid compiler tautological-compare warning // Pattern created by coverage-line; avoid compiler tautological-compare warning
if (AstAnd* const and1p = VN_CAST(node1p, And)) { if (const AstAnd* const and1p = VN_CAST(node1p, And)) {
if (AstAnd* const and2p = VN_CAST(node2p, And)) { if (const AstAnd* const and2p = VN_CAST(node2p, And)) {
if (VN_IS(and1p->lhsp(), Const) && VN_IS(and1p->rhsp(), NodeVarRef) if (VN_IS(and1p->lhsp(), Const) && VN_IS(and1p->rhsp(), NodeVarRef)
&& VN_IS(and2p->lhsp(), Const) && VN_IS(and2p->rhsp(), NodeVarRef)) && VN_IS(and2p->lhsp(), Const) && VN_IS(and2p->rhsp(), NodeVarRef))
return node1p->sameGateTree(node2p); return node1p->sameGateTree(node2p);
@ -1535,11 +1535,11 @@ class ConstVisitor final : public VNVisitor {
if (!lselp || !rselp) return false; if (!lselp || !rselp) return false;
// a[a:b] a[b-1:c] are adjacent // a[a:b] a[b-1:c] are adjacent
AstNode* const lfromp = lselp->fromp(); const AstNode* const lfromp = lselp->fromp();
AstNode* const rfromp = rselp->fromp(); const AstNode* const rfromp = rselp->fromp();
if (!lfromp || !rfromp || !lfromp->sameGateTree(rfromp)) return false; if (!lfromp || !rfromp || !lfromp->sameGateTree(rfromp)) return false;
AstConst* const lstart = VN_CAST(lselp->lsbp(), Const); const AstConst* const lstart = VN_CAST(lselp->lsbp(), Const);
AstConst* const rstart = VN_CAST(rselp->lsbp(), Const); const AstConst* const rstart = VN_CAST(rselp->lsbp(), Const);
if (!lstart || !rstart) return false; // too complicated if (!lstart || !rstart) return false; // too complicated
const int rend = (rstart->toSInt() + rselp->widthConst()); const int rend = (rstart->toSInt() + rselp->widthConst());
// a[i:j] a[j-1:k] // a[i:j] a[j-1:k]
@ -2209,11 +2209,11 @@ class ConstVisitor final : public VNVisitor {
if (VN_IS(srcDTypep, QueueDType) || VN_IS(srcDTypep, DynArrayDType)) { if (VN_IS(srcDTypep, QueueDType) || VN_IS(srcDTypep, DynArrayDType)) {
if (VN_IS(dstDTypep, QueueDType) || VN_IS(dstDTypep, DynArrayDType)) { if (VN_IS(dstDTypep, QueueDType) || VN_IS(dstDTypep, DynArrayDType)) {
int srcElementBits = 0; int srcElementBits = 0;
if (AstNodeDType* const elemDtp = srcDTypep->subDTypep()) { if (const AstNodeDType* const elemDtp = srcDTypep->subDTypep()) {
srcElementBits = elemDtp->width(); srcElementBits = elemDtp->width();
} }
int dstElementBits = 0; int dstElementBits = 0;
if (AstNodeDType* const elemDtp = dstDTypep->subDTypep()) { if (const AstNodeDType* const elemDtp = dstDTypep->subDTypep()) {
dstElementBits = elemDtp->width(); dstElementBits = elemDtp->width();
} }
srcp = new AstCvtArrayToArray{ srcp = new AstCvtArrayToArray{
@ -2243,7 +2243,7 @@ class ConstVisitor final : public VNVisitor {
AstNodeExpr* const dstp = VN_AS(streamp, StreamL)->lhsp()->unlinkFrBack(); AstNodeExpr* const dstp = VN_AS(streamp, StreamL)->lhsp()->unlinkFrBack();
AstNodeDType* const dstDTypep = dstp->dtypep()->skipRefp(); AstNodeDType* const dstDTypep = dstp->dtypep()->skipRefp();
AstNodeExpr* const srcp = nodep->rhsp()->unlinkFrBack(); AstNodeExpr* const srcp = nodep->rhsp()->unlinkFrBack();
AstNodeDType* const srcDTypep = srcp->dtypep()->skipRefp(); const AstNodeDType* const srcDTypep = srcp->dtypep()->skipRefp();
const int sWidth = srcp->width(); const int sWidth = srcp->width();
const int dWidth = dstp->width(); const int dWidth = dstp->width();
// Connect the rhs to the stream operator and update its width // Connect the rhs to the stream operator and update its width
@ -2306,7 +2306,7 @@ class ConstVisitor final : public VNVisitor {
} else if (m_doV && VN_IS(nodep->rhsp(), StreamL)) { } else if (m_doV && VN_IS(nodep->rhsp(), StreamL)) {
AstStreamL* streamp = VN_AS(nodep->rhsp(), StreamL); AstStreamL* streamp = VN_AS(nodep->rhsp(), StreamL);
AstNodeExpr* srcp = streamp->lhsp(); AstNodeExpr* srcp = streamp->lhsp();
AstNodeDType* const srcDTypep = srcp->dtypep()->skipRefp(); const AstNodeDType* const srcDTypep = srcp->dtypep()->skipRefp();
AstNodeDType* const dstDTypep = nodep->lhsp()->dtypep()->skipRefp(); AstNodeDType* const dstDTypep = nodep->lhsp()->dtypep()->skipRefp();
if ((VN_IS(srcDTypep, QueueDType) || VN_IS(srcDTypep, DynArrayDType) if ((VN_IS(srcDTypep, QueueDType) || VN_IS(srcDTypep, DynArrayDType)
|| VN_IS(srcDTypep, UnpackArrayDType))) { || VN_IS(srcDTypep, UnpackArrayDType))) {
@ -2330,11 +2330,11 @@ class ConstVisitor final : public VNVisitor {
// streamp->rhsp()->prettyTypeName() << ")"); // streamp->rhsp()->prettyTypeName() << ")");
// } // }
int srcElementBits = 0; int srcElementBits = 0;
if (AstNodeDType* const elemDtp = srcDTypep->subDTypep()) { if (const AstNodeDType* const elemDtp = srcDTypep->subDTypep()) {
srcElementBits = elemDtp->width(); srcElementBits = elemDtp->width();
} }
int dstElementBits = 0; int dstElementBits = 0;
if (AstNodeDType* const elemDtp = dstDTypep->subDTypep()) { if (const AstNodeDType* const elemDtp = dstDTypep->subDTypep()) {
dstElementBits = elemDtp->width(); dstElementBits = elemDtp->width();
} }
streamp->unlinkFrBack(); streamp->unlinkFrBack();
@ -2500,7 +2500,7 @@ class ConstVisitor final : public VNVisitor {
bool matchConcatRand(AstConcat* nodep) { bool matchConcatRand(AstConcat* nodep) {
// CONCAT(RAND, RAND) - created by Chisel code // CONCAT(RAND, RAND) - created by Chisel code
AstRand* const aRandp = VN_CAST(nodep->lhsp(), Rand); AstRand* const aRandp = VN_CAST(nodep->lhsp(), Rand);
AstRand* const bRandp = VN_CAST(nodep->rhsp(), Rand); const AstRand* const bRandp = VN_CAST(nodep->rhsp(), Rand);
if (!aRandp || !bRandp) return false; if (!aRandp || !bRandp) return false;
if (!aRandp->combinable(bRandp)) return false; if (!aRandp->combinable(bRandp)) return false;
UINFO(4, "Concat(Rand,Rand) => Rand: " << nodep); UINFO(4, "Concat(Rand,Rand) => Rand: " << nodep);
@ -2518,15 +2518,15 @@ class ConstVisitor final : public VNVisitor {
VL_DO_DANGLING(pushDeletep(nodep), nodep); VL_DO_DANGLING(pushDeletep(nodep), nodep);
return true; return true;
} }
int operandConcatMove(AstConcat* nodep) { int operandConcatMove(const AstConcat* nodep) {
// CONCAT under concat (See moveConcat) // CONCAT under concat (See moveConcat)
// Return value: true indicates to do it; 2 means move to LHS // Return value: true indicates to do it; 2 means move to LHS
const AstConcat* const abConcp = VN_CAST(nodep->lhsp(), Concat); const AstConcat* const abConcp = VN_CAST(nodep->lhsp(), Concat);
const AstConcat* const bcConcp = VN_CAST(nodep->rhsp(), Concat); const AstConcat* const bcConcp = VN_CAST(nodep->rhsp(), Concat);
if (!abConcp && !bcConcp) return 0; if (!abConcp && !bcConcp) return 0;
if (bcConcp) { if (bcConcp) {
AstNodeExpr* const ap = nodep->lhsp(); const AstNodeExpr* const ap = nodep->lhsp();
AstNodeExpr* const bp = bcConcp->lhsp(); const AstNodeExpr* const bp = bcConcp->lhsp();
// If a+b == 32,64,96 etc, then we want to have a+b together on LHS // If a+b == 32,64,96 etc, then we want to have a+b together on LHS
if (VL_BITBIT_I(ap->width() + bp->width()) == 0) return 2; // Transform 2: to abConc if (VL_BITBIT_I(ap->width() + bp->width()) == 0) return 2; // Transform 2: to abConc
} else { // abConcp } else { // abConcp
@ -2617,7 +2617,7 @@ class ConstVisitor final : public VNVisitor {
// potentially smaller lsb1p's width, but don't insert a redundant AstExtend. // potentially smaller lsb1p's width, but don't insert a redundant AstExtend.
// Note that due to some sloppiness in earlier passes, lsb1p might actually be wider, // Note that due to some sloppiness in earlier passes, lsb1p might actually be wider,
// so extend to the wider type. // so extend to the wider type.
AstNodeExpr* const widep = lsb1p->width() > lsb2p->width() ? lsb1p : lsb2p; const AstNodeExpr* const widep = lsb1p->width() > lsb2p->width() ? lsb1p : lsb2p;
AstNodeExpr* const lhsp = widep->width() > lsb2p->width() AstNodeExpr* const lhsp = widep->width() > lsb2p->width()
? new AstExtend{lsb2p->fileline(), lsb2p} ? new AstExtend{lsb2p->fileline(), lsb2p}
: lsb2p; : lsb2p;
@ -2895,7 +2895,7 @@ class ConstVisitor final : public VNVisitor {
// Not constant propagated (for today) because AstNodeExpr::isOpaque is set // Not constant propagated (for today) because AstNodeExpr::isOpaque is set
// Someday if lower is constant, convert to quoted "string". // Someday if lower is constant, convert to quoted "string".
bool onlySenItemInSenTree(AstSenItem* nodep) { bool onlySenItemInSenTree(const AstSenItem* nodep) {
// Only one if it's not in a list // Only one if it's not in a list
return (!nodep->nextp() && nodep->backp()->nextp() != nodep); return (!nodep->nextp() && nodep->backp()->nextp() != nodep);
} }
@ -2981,8 +2981,8 @@ class ConstVisitor final : public VNVisitor {
if (aCallp->name() < bCallp->name()) return -1; if (aCallp->name() < bCallp->name()) return -1;
if (aCallp->name() > bCallp->name()) return 1; if (aCallp->name() > bCallp->name()) return 1;
if (const int c = cmp(aCallp->fromp(), bCallp->fromp())) return c; if (const int c = cmp(aCallp->fromp(), bCallp->fromp())) return c;
AstNodeExpr* aPinsp = aCallp->pinsp(); const AstNodeExpr* aPinsp = aCallp->pinsp();
AstNodeExpr* bPinsp = bCallp->pinsp(); const AstNodeExpr* bPinsp = bCallp->pinsp();
while (aPinsp && bPinsp) { while (aPinsp && bPinsp) {
if (const int c = cmp(aPinsp, bPinsp)) return c; if (const int c = cmp(aPinsp, bPinsp)) return c;
aPinsp = VN_AS(aPinsp->nextp(), NodeExpr); aPinsp = VN_AS(aPinsp->nextp(), NodeExpr);
@ -2996,8 +2996,8 @@ class ConstVisitor final : public VNVisitor {
public: public:
bool operator()(const AstSenItem* lhsp, const AstSenItem* rhsp) const { bool operator()(const AstSenItem* lhsp, const AstSenItem* rhsp) const {
AstNodeExpr* const lSensp = lhsp->sensp(); const AstNodeExpr* const lSensp = lhsp->sensp();
AstNodeExpr* const rSensp = rhsp->sensp(); const AstNodeExpr* const rSensp = rhsp->sensp();
if (lSensp && rSensp) { if (lSensp && rSensp) {
// If both terms have sensitivity expressions, recursively compare them // If both terms have sensitivity expressions, recursively compare them
if (const int c = cmp(lSensp, rSensp)) return c < 0; if (const int c = cmp(lSensp, rSensp)) return c < 0;
@ -3163,11 +3163,11 @@ class ConstVisitor final : public VNVisitor {
} }
if (streamp) { if (streamp) {
AstNodeExpr* srcp = streamp->lhsp(); AstNodeExpr* srcp = streamp->lhsp();
AstNodeDType* const srcDTypep = srcp->dtypep()->skipRefp(); const AstNodeDType* const srcDTypep = srcp->dtypep()->skipRefp();
AstNodeDType* const dstDTypep = nodep->dtypep()->skipRefp(); AstNodeDType* const dstDTypep = nodep->dtypep()->skipRefp();
if (VN_IS(srcDTypep, QueueDType) && VN_IS(dstDTypep, QueueDType)) { if (VN_IS(srcDTypep, QueueDType) && VN_IS(dstDTypep, QueueDType)) {
int blockSize = 1; int blockSize = 1;
if (AstConst* const constp = VN_CAST(streamp->rhsp(), Const)) { if (const AstConst* const constp = VN_CAST(streamp->rhsp(), Const)) {
blockSize = constp->toSInt(); blockSize = constp->toSInt();
if (VL_UNLIKELY(blockSize <= 0)) { if (VL_UNLIKELY(blockSize <= 0)) {
// Not reachable due to higher level checks when parsing stream // Not reachable due to higher level checks when parsing stream
@ -3184,11 +3184,11 @@ class ConstVisitor final : public VNVisitor {
// streamp->rhsp()->prettyTypeName() << ")"); // streamp->rhsp()->prettyTypeName() << ")");
// } // }
int srcElementBits = 0; int srcElementBits = 0;
if (AstNodeDType* const elemDtp = srcDTypep->subDTypep()) { if (const AstNodeDType* const elemDtp = srcDTypep->subDTypep()) {
srcElementBits = elemDtp->width(); srcElementBits = elemDtp->width();
} }
int dstElementBits = 0; int dstElementBits = 0;
if (AstNodeDType* const elemDtp = dstDTypep->subDTypep()) { if (const AstNodeDType* const elemDtp = dstDTypep->subDTypep()) {
dstElementBits = elemDtp->width(); dstElementBits = elemDtp->width();
} }
streamp->unlinkFrBack(); streamp->unlinkFrBack();
@ -3330,9 +3330,7 @@ class ConstVisitor final : public VNVisitor {
if (!prevp->fmtp() || prevp->fmtp()->nextp() || !nodep->fmtp() || nodep->fmtp()->nextp()) if (!prevp->fmtp() || prevp->fmtp()->nextp() || !nodep->fmtp() || nodep->fmtp()->nextp())
return false; return false;
AstSFormatF* const pformatp = prevp->fmtp(); AstSFormatF* const pformatp = prevp->fmtp();
if (!pformatp) return false;
AstSFormatF* const nformatp = nodep->fmtp(); AstSFormatF* const nformatp = nodep->fmtp();
if (!nformatp) return false;
// We don't merge scopeNames as can have only one and might be different scopes (late in // We don't merge scopeNames as can have only one and might be different scopes (late in
// process) Also rare for real code to print %m multiple times in same message // process) Also rare for real code to print %m multiple times in same message
if (nformatp->scopeNamep() && pformatp->scopeNamep()) return false; if (nformatp->scopeNamep() && pformatp->scopeNamep()) return false;

View File

@ -441,7 +441,7 @@ using V3ControlFileResolver = V3ControlWildcardResolver<V3ControlFile>;
class V3ControlScopeTraceEntry final { class V3ControlScopeTraceEntry final {
public: public:
const string m_scope; // Scope or regexp to match const string m_scope; // Scope or regexp to match
const bool m_on = false; // True to enable message const bool m_on; // True to enable message
int m_levels = 0; // # levels, 0 = all, 1 = only this, ... int m_levels = 0; // # levels, 0 = all, 1 = only this, ...
// CONSTRUCTORS // CONSTRUCTORS
V3ControlScopeTraceEntry(const string& scope, bool on, int levels) V3ControlScopeTraceEntry(const string& scope, bool on, int levels)
@ -757,7 +757,8 @@ void V3Control::applyFTask(AstNodeModule* modulep, AstNodeFTask* ftaskp) {
if (ftp) ftp->apply(ftaskp); if (ftp) ftp->apply(ftaskp);
} }
void V3Control::applyVarAttr(AstNodeModule* modulep, AstNodeFTask* ftaskp, AstVar* varp) { void V3Control::applyVarAttr(const AstNodeModule* modulep, const AstNodeFTask* ftaskp,
AstVar* varp) {
V3ControlVar* vp; V3ControlVar* vp;
V3ControlModule* const modp V3ControlModule* const modp
= V3ControlResolver::s().modules().resolve(modulep->prettyOrigOrName()); = V3ControlResolver::s().modules().resolve(modulep->prettyOrigOrName());
@ -797,7 +798,7 @@ bool V3Control::containsMTaskProfileData() {
return V3ControlResolver::s().containsMTaskProfileData(); return V3ControlResolver::s().containsMTaskProfileData();
} }
bool V3Control::waive(FileLine* filelinep, V3ErrorCode code, const string& message) { bool V3Control::waive(const FileLine* filelinep, V3ErrorCode code, const string& message) {
V3ControlFile* const filep = V3ControlResolver::s().files().resolve(filelinep->filename()); V3ControlFile* const filep = V3ControlResolver::s().files().resolve(filelinep->filename());
if (!filep) return false; if (!filep) return false;
return filep->waive(code, message); return filep->waive(code, message);

View File

@ -51,7 +51,8 @@ public:
static void applyFTask(AstNodeModule* modulep, AstNodeFTask* ftaskp); static void applyFTask(AstNodeModule* modulep, AstNodeFTask* ftaskp);
static void applyIgnores(FileLine* filelinep); static void applyIgnores(FileLine* filelinep);
static void applyModule(AstNodeModule* modulep); static void applyModule(AstNodeModule* modulep);
static void applyVarAttr(AstNodeModule* modulep, AstNodeFTask* ftaskp, AstVar* varp); static void applyVarAttr(const AstNodeModule* modulep, const AstNodeFTask* ftaskp,
AstVar* varp);
static int getHierWorkers(const string& model); static int getHierWorkers(const string& model);
static FileLine* getHierWorkersFileLine(const string& model); static FileLine* getHierWorkersFileLine(const string& model);
@ -64,7 +65,7 @@ public:
static bool containsMTaskProfileData(); static bool containsMTaskProfileData();
static bool waive(FileLine* filelinep, V3ErrorCode code, const string& message); static bool waive(const FileLine* filelinep, V3ErrorCode code, const string& message);
}; };
#endif // Guard #endif // Guard

View File

@ -35,30 +35,30 @@
VL_DEFINE_DEBUG_FUNCTIONS; VL_DEFINE_DEBUG_FUNCTIONS;
class ExprCoverageEligibleVisitor final : public VNVisitor { class ExprCoverageEligibleVisitor final : public VNVisitorConst {
// STATE // STATE
bool m_eligible = true; bool m_eligible = true;
static bool elemDTypeEligible(const AstNodeDType* dtypep) { static bool elemDTypeEligible(const AstNodeDType* dtypep) {
dtypep = dtypep->skipRefp(); dtypep = dtypep->skipRefp();
if (AstNodeDType* const dtp = dtypep->virtRefDTypep()) { if (const AstNodeDType* const dtp = dtypep->virtRefDTypep()) {
if (!elemDTypeEligible(dtp)) return false; if (!elemDTypeEligible(dtp)) return false;
} }
if (AstNodeDType* const dtp = dtypep->virtRefDType2p()) { if (const AstNodeDType* const dtp = dtypep->virtRefDType2p()) {
if (!elemDTypeEligible(dtp)) return false; if (!elemDTypeEligible(dtp)) return false;
} }
return !VN_IS(dtypep, ClassRefDType); return !VN_IS(dtypep, ClassRefDType);
} }
void visit(AstNodeVarRef* nodep) override { void visit(AstNodeVarRef* nodep) override {
AstNodeDType* dtypep = nodep->varp()->dtypep(); const AstNodeDType* const dtypep = nodep->varp()->dtypep();
// Class objects and references not supported for expression coverage // Class objects and references not supported for expression coverage
// because the object may not persist until the point at which // because the object may not persist until the point at which
// coverage data is gathered // coverage data is gathered
// This could be resolved in the future by protecting against dereferrencing // This could be resolved in the future by protecting against dereferrencing
// null pointers when cloning the expression for expression coverage // null pointers when cloning the expression for expression coverage
if (dtypep && elemDTypeEligible(dtypep)) { if (dtypep && elemDTypeEligible(dtypep)) {
iterateChildren(nodep); iterateChildrenConst(nodep);
} else { } else {
m_eligible = false; m_eligible = false;
} }
@ -68,13 +68,13 @@ class ExprCoverageEligibleVisitor final : public VNVisitor {
if (!nodep->isExprCoverageEligible()) { if (!nodep->isExprCoverageEligible()) {
m_eligible = false; m_eligible = false;
} else { } else {
iterateChildren(nodep); iterateChildrenConst(nodep);
} }
} }
public: public:
// CONSTRUCTORS // CONSTRUCTORS
explicit ExprCoverageEligibleVisitor(AstNode* nodep) { iterateChildren(nodep); } explicit ExprCoverageEligibleVisitor(AstNode* nodep) { iterateChildrenConst(nodep); }
~ExprCoverageEligibleVisitor() override = default; ~ExprCoverageEligibleVisitor() override = default;
bool eligible() { return m_eligible; } bool eligible() { return m_eligible; }
@ -162,7 +162,7 @@ class CoverageVisitor final : public VNVisitor {
// METHODS // METHODS
const char* varIgnoreToggle(AstVar* nodep) { const char* varIgnoreToggle(const AstVar* nodep) {
// Return true if this shouldn't be traced // Return true if this shouldn't be traced
// See also similar rule in V3TraceDecl::varIgnoreTrace // See also similar rule in V3TraceDecl::varIgnoreTrace
if (!nodep->isToggleCoverable()) return "Not relevant signal type"; if (!nodep->isToggleCoverable()) return "Not relevant signal type";
@ -203,7 +203,7 @@ class CoverageVisitor final : public VNVisitor {
} }
return incp; return incp;
} }
string traceNameForLine(AstNode* nodep, const string& type) { string traceNameForLine(const AstNode* nodep, const string& type) {
string name = "vlCoverageLineTrace_" + nodep->fileline()->filebasenameNoExt() + "__" string name = "vlCoverageLineTrace_" + nodep->fileline()->filebasenameNoExt() + "__"
+ cvtToStr(nodep->fileline()->lineno()) + "_" + type; + cvtToStr(nodep->fileline()->lineno()) + "_" + type;
if (const uint32_t suffix = m_varnames[name]++) name += "_" + cvtToStr(suffix); if (const uint32_t suffix = m_varnames[name]++) name += "_" + cvtToStr(suffix);
@ -438,7 +438,7 @@ class CoverageVisitor final : public VNVisitor {
if (adtypep->packed()) { if (adtypep->packed()) {
for (AstMemberDType* itemp = adtypep->membersp(); itemp; for (AstMemberDType* itemp = adtypep->membersp(); itemp;
itemp = VN_AS(itemp->nextp(), MemberDType)) { itemp = VN_AS(itemp->nextp(), MemberDType)) {
AstNodeDType* const subtypep = itemp->subDTypep()->skipRefp(); const AstNodeDType* const subtypep = itemp->subDTypep()->skipRefp();
const int index_code = itemp->lsb(); const int index_code = itemp->lsb();
ToggleEnt newent{ ToggleEnt newent{
above.m_comment + "."s + itemp->name(), above.m_comment + "."s + itemp->name(),
@ -855,7 +855,7 @@ class CoverageVisitor final : public VNVisitor {
// not be flagged as redundant or impossible, however the results will // not be flagged as redundant or impossible, however the results will
// still be valid, albeit messier // still be valid, albeit messier
for (CoverTerm& term : l) { for (CoverTerm& term : l) {
if (AstVarRef* const refp = VN_CAST(term.m_exprp, VarRef)) { if (const AstVarRef* const refp = VN_CAST(term.m_exprp, VarRef)) {
varps[term.m_objective].insert(refp->varp()); varps[term.m_objective].insert(refp->varp());
} else { } else {
strs[term.m_objective].insert(term.m_emitV); strs[term.m_objective].insert(term.m_emitV);
@ -865,7 +865,7 @@ class CoverageVisitor final : public VNVisitor {
bool impossible = false; bool impossible = false;
for (CoverTerm& term : r) { for (CoverTerm& term : r) {
bool redundant = false; bool redundant = false;
if (AstNodeVarRef* const refp = VN_CAST(term.m_exprp, NodeVarRef)) { if (const AstNodeVarRef* const refp = VN_CAST(term.m_exprp, NodeVarRef)) {
if (varps[term.m_objective].find(refp->varp()) if (varps[term.m_objective].find(refp->varp())
!= varps[term.m_objective].end()) != varps[term.m_objective].end())
redundant = true; redundant = true;

View File

@ -48,7 +48,7 @@ class CoverageJoinVisitor final : public VNVisitor {
// Note uses user4 // Note uses user4
V3DupFinder dupFinder; // Duplicate code detection V3DupFinder dupFinder; // Duplicate code detection
// Hash all of the original signals we toggle cover // Hash all of the original signals we toggle cover
for (AstCoverToggle* nodep : m_toggleps) dupFinder.insert(nodep->origp()); for (const AstCoverToggle* const nodep : m_toggleps) dupFinder.insert(nodep->origp());
if (dumpLevel() || debug() >= 9) if (dumpLevel() || debug() >= 9)
dupFinder.dumpFile(v3Global.debugFilename("coveragejoin") + ".hash", false); dupFinder.dumpFile(v3Global.debugFilename("coveragejoin") + ".hash", false);
// Find if there are any duplicates // Find if there are any duplicates

View File

@ -334,8 +334,8 @@ class DeadVisitor final : public VNVisitor {
checkAll(typedefp); checkAll(typedefp);
} }
} }
bool shouldDeleteTypedef(AstTypedef* typedefp) { bool shouldDeleteTypedef(const AstTypedef* typedefp) {
if (auto* const structp = VN_CAST(typedefp->subDTypep(), NodeUOrStructDType)) { if (const auto* const structp = VN_CAST(typedefp->subDTypep(), NodeUOrStructDType)) {
if (structp->user1() && !structp->packed()) return false; if (structp->user1() && !structp->packed()) return false;
} }
return m_elimCells && !typedefp->attrPublic(); return m_elimCells && !typedefp->attrPublic();
@ -367,7 +367,7 @@ class DeadVisitor final : public VNVisitor {
} }
} }
} }
bool mightElimVar(AstVar* nodep) const { bool mightElimVar(const AstVar* nodep) const {
if (nodep->isSigPublic()) return false; // Can't elim publics! if (nodep->isSigPublic()) return false; // Can't elim publics!
if (nodep->isIO() || nodep->isClassMember() || nodep->sensIfacep()) return false; if (nodep->isIO() || nodep->isClassMember() || nodep->sensIfacep()) return false;
if (nodep->isTemp() && !nodep->isTrace()) return true; if (nodep->isTemp() && !nodep->isTrace()) return true;

View File

@ -540,7 +540,7 @@ class DelayedVisitor final : public VNVisitor {
} }
// Create a unique temporary variable name // Create a unique temporary variable name
std::string uniqueTmpName(AstScope* scopep, AstVarScope* vscp, VarScopeInfo& vscpInfo) { std::string uniqueTmpName(AstScope* scopep, const AstVarScope* vscp, VarScopeInfo& vscpInfo) {
std::stringstream ss; std::stringstream ss;
ss << "__" << vscp->varp()->shortName() + "__v"; ss << "__" << vscp->varp()->shortName() + "__v";
// If the assignment is in the same scope as the variable, just // If the assignment is in the same scope as the variable, just
@ -900,7 +900,7 @@ class DelayedVisitor final : public VNVisitor {
return dtypep; return dtypep;
}(); }();
if (AstSel* const lSelp = VN_CAST(lhsNodep, Sel)) { if (const AstSel* const lSelp = VN_CAST(lhsNodep, Sel)) {
// This is a partial assignment. // This is a partial assignment.
// Need to create a mask and widen the value to element size. // Need to create a mask and widen the value to element size.
lhsNodep = lSelp->fromp(); lhsNodep = lSelp->fromp();
@ -910,7 +910,7 @@ class DelayedVisitor final : public VNVisitor {
// Create mask value // Create mask value
maskp = [&]() -> AstNodeExpr* { maskp = [&]() -> AstNodeExpr* {
// Constant mask we can compute here // Constant mask we can compute here
if (AstConst* const cLsbp = VN_CAST(sLsbp, Const)) { if (const AstConst* const cLsbp = VN_CAST(sLsbp, Const)) {
AstConst* const cp = new AstConst{flp, AstConst::DTyped{}, eDTypep}; AstConst* const cp = new AstConst{flp, AstConst::DTyped{}, eDTypep};
cp->num().setMask(sWidth, cLsbp->toSInt()); cp->num().setMask(sWidth, cLsbp->toSInt());
return cp; return cp;
@ -927,7 +927,7 @@ class DelayedVisitor final : public VNVisitor {
valuep = [&]() -> AstNodeExpr* { valuep = [&]() -> AstNodeExpr* {
// Constant value with constant select we can compute here // Constant value with constant select we can compute here
if (AstConst* const cValuep = VN_CAST(valuep, Const)) { if (AstConst* const cValuep = VN_CAST(valuep, Const)) {
if (AstConst* const cLsbp = VN_CAST(sLsbp, Const)) { if (const AstConst* const cLsbp = VN_CAST(sLsbp, Const)) {
AstConst* const cp = new AstConst{flp, AstConst::DTyped{}, eDTypep}; AstConst* const cp = new AstConst{flp, AstConst::DTyped{}, eDTypep};
cp->num().setAllBits0(); cp->num().setAllBits0();
cp->num().opSelInto(cValuep->num(), cLsbp->toSInt(), sWidth); cp->num().opSelInto(cValuep->num(), cLsbp->toSInt(), sWidth);
@ -1097,7 +1097,7 @@ class DelayedVisitor final : public VNVisitor {
VL_RESTORER(m_ignoreBlkAndNBlk); VL_RESTORER(m_ignoreBlkAndNBlk);
VL_RESTORER(m_inNonCombLogic); VL_RESTORER(m_inNonCombLogic);
m_activep = nodep; m_activep = nodep;
AstSenTree* const senTreep = nodep->sentreep(); const AstSenTree* const senTreep = nodep->sentreep();
m_ignoreBlkAndNBlk = senTreep->hasStatic() || senTreep->hasInitial(); m_ignoreBlkAndNBlk = senTreep->hasStatic() || senTreep->hasInitial();
m_inNonCombLogic = senTreep->hasClocked(); m_inNonCombLogic = senTreep->hasClocked();
iterateChildren(nodep); iterateChildren(nodep);
@ -1160,7 +1160,7 @@ class DelayedVisitor final : public VNVisitor {
AstNode* newp = new AstCStmt{flp, blockp}; AstNode* newp = new AstCStmt{flp, blockp};
if (nodep->isDelayed()) { if (nodep->isDelayed()) {
AstVarRef* const vrefp = VN_AS(eventp, VarRef); const AstVarRef* const vrefp = VN_AS(eventp, VarRef);
const std::string newvarname = "__Vdly__" + vrefp->varp()->shortName(); const std::string newvarname = "__Vdly__" + vrefp->varp()->shortName();
AstVarScope* const dlyvscp AstVarScope* const dlyvscp
= createTemp(flp, vrefp->varScopep()->scopep(), newvarname, 1); = createTemp(flp, vrefp->varScopep()->scopep(), newvarname, 1);

View File

@ -55,11 +55,11 @@ class DescopeVisitor final : public VNVisitor {
// METHODS // METHODS
static bool modIsSingleton(AstNodeModule* modp) { static bool modIsSingleton(const AstNodeModule* modp) {
// True iff there's exactly one instance of this module in the design (including top). // True iff there's exactly one instance of this module in the design (including top).
if (modp->isTop()) return true; if (modp->isTop()) return true;
int instances = 0; int instances = 0;
for (AstNode* stmtp = modp->stmtsp(); stmtp; stmtp = stmtp->nextp()) { for (const AstNode* stmtp = modp->stmtsp(); stmtp; stmtp = stmtp->nextp()) {
if (VN_IS(stmtp, Scope)) { if (VN_IS(stmtp, Scope)) {
if (++instances > 1) return false; if (++instances > 1) return false;
} }

View File

@ -79,8 +79,8 @@ struct std::hash<std::pair<const DfgVertex*, const DfgVertex*>> final {
class VDfgType final { class VDfgType final {
public: public:
#include "V3Dfg__gen_type_enum.h" // From ./astgen #include "V3Dfg__gen_type_enum.h" // From ./astgen
enum en m_e; const enum en m_e;
VDfgType() = default; VDfgType() = delete;
// cppcheck-suppress noExplicitConstructor // cppcheck-suppress noExplicitConstructor
constexpr VDfgType(en _e) constexpr VDfgType(en _e)
: m_e{_e} {} : m_e{_e} {}

View File

@ -181,8 +181,8 @@ void V3DfgPasses::binToOneHot(DfgGraph& dfg, V3DfgBinToOneHotContext& ctx) {
// Structure to keep track of comparison details // Structure to keep track of comparison details
struct Term final { struct Term final {
DfgVertex* m_vtxp; // Vertex to replace DfgVertex* m_vtxp = nullptr; // Vertex to replace
bool m_inv; // '!=', instead of '==' bool m_inv = false; // '!=', instead of '=='
Term() = default; Term() = default;
Term(DfgVertex* vtxp, bool inv) Term(DfgVertex* vtxp, bool inv)
: m_vtxp{vtxp} : m_vtxp{vtxp}

View File

@ -234,7 +234,9 @@ public:
uint32_t toU32() const { return static_cast<size_t>(num().toUInt()); } uint32_t toU32() const { return static_cast<size_t>(num().toUInt()); }
// cppcheck-suppress duplInheritedMember
bool isZero() const { return num().isEqZero(); } bool isZero() const { return num().isEqZero(); }
// cppcheck-suppress duplInheritedMember
bool isOnes() const { return num().isEqAllOnes(width()); } bool isOnes() const { return num().isEqAllOnes(width()); }
// Does this DfgConst have the given value? Note this is not easy to answer if wider than 32. // Does this DfgConst have the given value? Note this is not easy to answer if wider than 32.

View File

@ -33,14 +33,14 @@ class V3DiagSarifImp final {
// METHODS // METHODS
void calculate() { void calculate() {
for (auto& msgr : m_messages) for (const VErrorMessage& msgr : m_messages)
if (msgr.code().isNamed()) m_codes.emplace(msgr.code()); if (msgr.code().isNamed()) m_codes.emplace(msgr.code());
int i = 0; int i = 0;
for (const auto& code : m_codes) m_codeIndex[code] = i++; for (const V3ErrorCode& code : m_codes) m_codeIndex[code] = i++;
} }
void putRules(V3OutJsonFile& of) const { void putRules(V3OutJsonFile& of) const {
for (const auto& code : m_codes) { for (const V3ErrorCode& code : m_codes) {
of.begin().put("id", code.ascii()).put("helpUri", code.url()).end(); of.begin().put("id", code.ascii()).put("helpUri", code.url()).end();
} }
} }
@ -97,7 +97,7 @@ class V3DiagSarifImp final {
of.begin("message"); of.begin("message");
putText(of, first_clean, first_fmt); putText(of, first_clean, first_fmt);
of.end(); of.end();
if (auto fl = msg.fileline()) { if (const FileLine* const fl = msg.fileline()) {
of.begin("locations", '[').begin(); of.begin("locations", '[').begin();
putLocation(of, fl); putLocation(of, fl);
of.end(); of.end();
@ -175,7 +175,7 @@ public:
.end(); .end();
of.begin("results", '['); of.begin("results", '[');
for (auto& msgr : m_messages) putResult(of, msgr); for (const VErrorMessage& msgr : m_messages) putResult(of, msgr);
of.end(); of.end();
of.end(); // runs ] of.end(); // runs ]

View File

@ -148,8 +148,8 @@ public:
void emitVarAccessors(const AstVar* nodep); void emitVarAccessors(const AstVar* nodep);
template <typename T_Callable> template <typename T_Callable>
static void forModCUse(const AstNodeModule* modp, VUseType useType, T_Callable action) { static void forModCUse(const AstNodeModule* modp, VUseType useType, T_Callable action) {
for (AstNode* itemp = modp->stmtsp(); itemp; itemp = itemp->nextp()) { for (const AstNode* itemp = modp->stmtsp(); itemp; itemp = itemp->nextp()) {
if (AstCUse* const usep = VN_CAST(itemp, CUse)) { if (const AstCUse* const usep = VN_CAST(itemp, CUse)) {
if (usep->useType().containsAny(useType)) { if (usep->useType().containsAny(useType)) {
if (usep->useType().containsAny(VUseType::INT_INCLUDE)) { if (usep->useType().containsAny(VUseType::INT_INCLUDE)) {
action("#include \"" + prefixNameProtect(usep) + ".h\"\n"); action("#include \"" + prefixNameProtect(usep) + ".h\"\n");

View File

@ -33,7 +33,7 @@ class EmitCConstInit VL_NOT_FINAL : public EmitCBaseVisitorConst {
// METHODS // METHODS
uint32_t tabModulus(AstNodeDType* dtypep) { uint32_t tabModulus(const AstNodeDType* dtypep) {
const uint32_t elemBytes = dtypep->widthTotalBytes(); const uint32_t elemBytes = dtypep->widthTotalBytes();
return dtypep->isString() ? 1 // String return dtypep->isString() ? 1 // String
: elemBytes <= 2 ? 8 // CData, SData : elemBytes <= 2 ? 8 // CData, SData

View File

@ -110,7 +110,7 @@ class EmitCConstPool final : public EmitCConstInit {
} }
public: public:
explicit EmitCConstPool(AstConstPool* poolp) { explicit EmitCConstPool(const AstConstPool* poolp) {
emitVars(poolp); emitVars(poolp);
V3Stats::addStatSum("ConstPool, Tables emitted", m_tablesEmitted); V3Stats::addStatSum("ConstPool, Tables emitted", m_tablesEmitted);
V3Stats::addStatSum("ConstPool, Constants emitted", m_constsEmitted); V3Stats::addStatSum("ConstPool, Constants emitted", m_constsEmitted);

View File

@ -175,7 +175,7 @@ public:
// ACCESSORS // ACCESSORS
void splitSizeInc(int count) { m_splitSize += count; } void splitSizeInc(int count) { m_splitSize += count; }
void splitSizeInc(AstNode* nodep) { splitSizeInc(nodep->nodeCount()); } void splitSizeInc(const AstNode* nodep) { splitSizeInc(nodep->nodeCount()); }
void splitSizeReset() { m_splitSize = 0; } void splitSizeReset() { m_splitSize = 0; }
bool splitNeeded() const { bool splitNeeded() const {
return v3Global.opt.outputSplit() && m_splitSize >= v3Global.opt.outputSplit(); return v3Global.opt.outputSplit() && m_splitSize >= v3Global.opt.outputSplit();
@ -189,13 +189,13 @@ public:
char fmtLetter); char fmtLetter);
bool emitSimpleOk(AstNodeExpr* nodep); bool emitSimpleOk(AstNodeExpr* nodep);
void emitIQW(AstNode* nodep) { void emitIQW(const AstNode* nodep) {
// See "Type letters" in verilated.h // See "Type letters" in verilated.h
// Other abbrevs: "C"har, "S"hort, "F"loat, "D"ouble, stri"N"g, "R"=queue, "U"npacked // Other abbrevs: "C"har, "S"hort, "F"loat, "D"ouble, stri"N"g, "R"=queue, "U"npacked
puts(nodep->dtypep()->skipRefp()->charIQWN()); puts(nodep->dtypep()->skipRefp()->charIQWN());
} }
void emitRU(AstNode* nodep) { void emitRU(const AstNode* nodep) {
AstNodeDType* dtp = nodep->dtypep()->skipRefp(); const AstNodeDType* dtp = nodep->dtypep()->skipRefp();
// See "Type letters" in verilated.h // See "Type letters" in verilated.h
if (VN_IS(dtp, UnpackArrayDType)) if (VN_IS(dtp, UnpackArrayDType))
puts("U"); puts("U");
@ -210,7 +210,7 @@ public:
: nodep->isDouble() ? "SD" : nodep->isDouble() ? "SD"
: (nodep->isScQuad() ? "SQ" : "SI")); : (nodep->isScQuad() ? "SQ" : "SI"));
} }
void emitDatap(AstNode* nodep) { void emitDatap(const AstNode* nodep) {
// When passing to a function with va_args the compiler doesn't // When passing to a function with va_args the compiler doesn't
// know need a pointer so when wide, need to look inside VlWide // know need a pointer so when wide, need to look inside VlWide
if (nodep->isWide()) puts(".data()"); if (nodep->isWide()) puts(".data()");
@ -319,7 +319,7 @@ public:
// VISITORS // VISITORS
using EmitCConstInit::visit; using EmitCConstInit::visit;
void visit(AstCFunc* nodep) override { void visit(AstCFunc* const nodep) override {
if (nodep->emptyBody() && !nodep->isLoose()) return; if (nodep->emptyBody() && !nodep->isLoose()) return;
VL_RESTORER(m_useSelfForThis); VL_RESTORER(m_useSelfForThis);
VL_RESTORER(m_cfuncp); VL_RESTORER(m_cfuncp);
@ -339,7 +339,7 @@ public:
if (nodep->isConstructor()) { if (nodep->isConstructor()) {
const AstClass* const classp = VN_CAST(nodep->scopep()->modp(), Class); const AstClass* const classp = VN_CAST(nodep->scopep()->modp(), Class);
if (nodep->isConstructor() && classp && classp->extendsp()) { if (classp && classp->extendsp()) {
puts("\n : "); puts("\n : ");
putConstructorSubinit(classp, nodep); putConstructorSubinit(classp, nodep);
} }

View File

@ -259,7 +259,7 @@ class EmitCHeader final : public EmitCConstInit {
case AttributeType::Width: { case AttributeType::Width: {
if (isArrayType) { if (isArrayType) {
// For arrays, get innermost element width // For arrays, get innermost element width
AstNodeDType* dtype = itemp->dtypep(); const AstNodeDType* dtype = itemp->dtypep();
while (dtype->subDTypep()) dtype = dtype->subDTypep(); while (dtype->subDTypep()) dtype = dtype->subDTypep();
return dtype->width(); return dtype->width();
} }
@ -461,7 +461,7 @@ class EmitCHeader final : public EmitCConstInit {
AstMemberDType* itemp; AstMemberDType* itemp;
AstMemberDType* lastItemp; AstMemberDType* lastItemp;
AstMemberDType* witemp = nullptr; const AstMemberDType* witemp = nullptr;
// LSB is first field in C, so loop backwards // LSB is first field in C, so loop backwards
for (lastItemp = sdtypep->membersp(); lastItemp && lastItemp->nextp(); for (lastItemp = sdtypep->membersp(); lastItemp && lastItemp->nextp();
lastItemp = VN_AS(lastItemp->nextp(), MemberDType)) { lastItemp = VN_AS(lastItemp->nextp(), MemberDType)) {

View File

@ -724,28 +724,28 @@ class EmitCTrace final : EmitCFunc {
&& m_typeSplitSize >= v3Global.opt.outputSplitCTrace(); && m_typeSplitSize >= v3Global.opt.outputSplitCTrace();
} }
bool emitTraceIsScBv(AstTraceInc* nodep) { bool emitTraceIsScBv(const AstTraceInc* nodep) {
const AstVarRef* const varrefp = VN_CAST(nodep->declp()->valuep(), VarRef); const AstVarRef* const varrefp = VN_CAST(nodep->declp()->valuep(), VarRef);
if (!varrefp) return false; if (!varrefp) return false;
AstVar* const varp = varrefp->varp(); const AstVar* const varp = varrefp->varp();
return varp->isSc() && varp->isScBv(); return varp->isSc() && varp->isScBv();
} }
bool emitTraceIsScBigUint(AstTraceInc* nodep) { bool emitTraceIsScBigUint(const AstTraceInc* nodep) {
const AstVarRef* const varrefp = VN_CAST(nodep->declp()->valuep(), VarRef); const AstVarRef* const varrefp = VN_CAST(nodep->declp()->valuep(), VarRef);
if (!varrefp) return false; if (!varrefp) return false;
AstVar* const varp = varrefp->varp(); const AstVar* const varp = varrefp->varp();
return varp->isSc() && varp->isScBigUint(); return varp->isSc() && varp->isScBigUint();
} }
bool emitTraceIsScUint(AstTraceInc* nodep) { bool emitTraceIsScUint(const AstTraceInc* nodep) {
const AstVarRef* const varrefp = VN_CAST(nodep->declp()->valuep(), VarRef); const AstVarRef* const varrefp = VN_CAST(nodep->declp()->valuep(), VarRef);
if (!varrefp) return false; if (!varrefp) return false;
AstVar* const varp = varrefp->varp(); const AstVar* const varp = varrefp->varp();
return varp->isSc() && (varp->isScUint() || varp->isScUintBool()); return varp->isSc() && (varp->isScUint() || varp->isScUintBool());
} }
void emitTraceInitOne(AstTraceDecl* nodep, int enumNum) { void emitTraceInitOne(const AstTraceDecl* nodep, int enumNum) {
if (nodep->dtypep()->basicp()->isDouble()) { if (nodep->dtypep()->basicp()->isDouble()) {
puts("tracep->declDouble("); puts("tracep->declDouble(");
} else if (nodep->isWide()) { } else if (nodep->isWide()) {
@ -906,7 +906,7 @@ class EmitCTrace final : EmitCFunc {
void emitTraceValue(AstTraceInc* nodep, int arrayindex) { void emitTraceValue(AstTraceInc* nodep, int arrayindex) {
if (AstVarRef* const varrefp = VN_CAST(nodep->valuep(), VarRef)) { if (AstVarRef* const varrefp = VN_CAST(nodep->valuep(), VarRef)) {
AstVar* const varp = varrefp->varp(); const AstVar* const varp = varrefp->varp();
if (varp->isEvent()) puts("&"); if (varp->isEvent()) puts("&");
puts("("); puts("(");
if (emitTraceIsScBigUint(nodep)) { if (emitTraceIsScBigUint(nodep)) {

View File

@ -39,7 +39,7 @@ class CMakeEmitter final {
template <typename T_List> template <typename T_List>
static string cmake_list(const T_List& strs) { static string cmake_list(const T_List& strs) {
string s; string s;
for (auto& itr : strs) { for (const std::string& itr : strs) {
if (!s.empty()) s += ' '; if (!s.empty()) s += ' ';
s += '"'; s += '"';
s += V3OutFormatter::quoteNameControls(itr); s += V3OutFormatter::quoteNameControls(itr);
@ -49,7 +49,7 @@ class CMakeEmitter final {
} }
static string cmake_list(const VFileLibList& strs) { static string cmake_list(const VFileLibList& strs) {
string s; string s;
for (auto& itr : strs) { for (const VFileLibName& itr : strs) {
if (!s.empty()) s += ' '; if (!s.empty()) s += ' ';
s += '"'; s += '"';
s += V3OutFormatter::quoteNameControls(itr.filename()); s += V3OutFormatter::quoteNameControls(itr.filename());
@ -191,14 +191,16 @@ class CMakeEmitter final {
*of << "target_link_libraries(${TOP_TARGET_NAME} PRIVATE " << prefix << ")\n"; *of << "target_link_libraries(${TOP_TARGET_NAME} PRIVATE " << prefix << ")\n";
if (!children.empty()) { if (!children.empty()) {
*of << "target_link_libraries(" << prefix << " INTERFACE"; *of << "target_link_libraries(" << prefix << " INTERFACE";
for (const auto& childr : children) *of << " " << (childr)->hierPrefix(); for (const V3HierBlock* const childp : children) {
*of << " " << childp->hierPrefix();
}
*of << ")\n"; *of << ")\n";
} }
*of << "verilate(" << prefix << " PREFIX " << prefix << " TOP_MODULE " *of << "verilate(" << prefix << " PREFIX " << prefix << " TOP_MODULE "
<< hblockp->modp()->name() << " DIRECTORY " << hblockp->modp()->name() << " DIRECTORY "
<< v3Global.opt.makeDir() + "/" + prefix << " SOURCES "; << v3Global.opt.makeDir() + "/" + prefix << " SOURCES ";
for (const auto& childr : children) { for (const V3HierBlock* const childp : children) {
*of << " " << v3Global.opt.makeDir() + "/" + childr->hierWrapperFilename(true); *of << " " << v3Global.opt.makeDir() + "/" + childp->hierWrapperFilename(true);
} }
*of << " "; *of << " ";
const string vFile = hblockp->vFileIfNecessary(); const string vFile = hblockp->vFileIfNecessary();

View File

@ -152,11 +152,11 @@ private:
VL_DEFINE_DEBUG_FUNCTIONS; VL_DEFINE_DEBUG_FUNCTIONS;
// Potentially very slow, intended for debugging // Potentially very slow, intended for debugging
string prettyNumber(const V3Number* nump, AstNodeDType* dtypep) { string prettyNumber(const V3Number* nump, const AstNodeDType* dtypep) {
if (AstRefDType* const refdtypep = VN_CAST(dtypep, RefDType)) { // if (const AstRefDType* const refdtypep = VN_CAST(dtypep, RefDType)) { //
dtypep = refdtypep->skipRefp(); dtypep = refdtypep->skipRefp();
} }
if (AstNodeUOrStructDType* const stp = VN_CAST(dtypep, NodeUOrStructDType)) { if (const AstNodeUOrStructDType* const stp = VN_CAST(dtypep, NodeUOrStructDType)) {
if (stp->packed()) { if (stp->packed()) {
std::ostringstream out; std::ostringstream out;
out << "'{"; out << "'{";
@ -218,13 +218,13 @@ public:
m_whyNotOptimizable = why; m_whyNotOptimizable = why;
std::ostringstream stack; std::ostringstream stack;
for (const auto& callstack : vlstd::reverse_view(m_callStack)) { for (const auto& callstack : vlstd::reverse_view(m_callStack)) {
AstFuncRef* const funcp = callstack->m_funcp; const AstFuncRef* const funcp = callstack->m_funcp;
stack << "\n " << funcp->fileline() << "... Called from '" stack << "\n " << funcp->fileline() << "... Called from '"
<< funcp->prettyName() << "()' with parameters:"; << funcp->prettyName() << "()' with parameters:";
V3TaskConnects* tconnects = callstack->m_tconnects; V3TaskConnects* tconnects = callstack->m_tconnects;
for (V3TaskConnects::iterator conIt = tconnects->begin(); for (V3TaskConnects::iterator conIt = tconnects->begin();
conIt != tconnects->end(); ++conIt) { conIt != tconnects->end(); ++conIt) {
AstVar* const portp = conIt->first; const AstVar* const portp = conIt->first;
AstNodeExpr* const pinp = conIt->second->exprp(); AstNodeExpr* const pinp = conIt->second->exprp();
AstNodeDType* const dtypep = pinp->dtypep(); AstNodeDType* const dtypep = pinp->dtypep();
if (AstConst* const valp = fetchConstNull(pinp)) { if (AstConst* const valp = fetchConstNull(pinp)) {
@ -400,7 +400,7 @@ private:
// True if current node might be jumped over - all visitors must call this up front // True if current node might be jumped over - all visitors must call this up front
bool jumpingOver() const { return m_jumpp; } bool jumpingOver() const { return m_jumpp; }
void assignOutValue(AstNodeAssign* nodep, AstNode* vscp, const AstNodeExpr* valuep) { void assignOutValue(const AstNodeAssign* nodep, AstNode* vscp, const AstNodeExpr* valuep) {
if (VN_IS(nodep, AssignDly)) { if (VN_IS(nodep, AssignDly)) {
// Don't do setValue, as value isn't yet visible to following statements // Don't do setValue, as value isn't yet visible to following statements
newOutValue(vscp, valuep); newOutValue(vscp, valuep);
@ -458,7 +458,7 @@ private:
m_varAux(vscp).usage |= VU_RV; m_varAux(vscp).usage |= VU_RV;
const bool varIsConst = (nodep->varp()->isConst() || nodep->varp()->isParam()) const bool varIsConst = (nodep->varp()->isConst() || nodep->varp()->isParam())
&& nodep->varp()->valuep(); && nodep->varp()->valuep();
AstNodeExpr* const valuep const AstNodeExpr* const valuep
= varIsConst ? fetchValueNull(nodep->varp()->valuep()) : nullptr; = varIsConst ? fetchValueNull(nodep->varp()->valuep()) : nullptr;
// Propagate PARAM constants for constant function analysis // Propagate PARAM constants for constant function analysis
if (varIsConst && valuep) { if (varIsConst && valuep) {
@ -800,9 +800,7 @@ private:
handleAssignArray(nodep, selp, valueFromp); handleAssignArray(nodep, selp, valueFromp);
} else if (AstConcat* const selp = VN_CAST(lhsp, Concat)) { } else if (AstConcat* const selp = VN_CAST(lhsp, Concat)) {
checkNodeInfo(selp); checkNodeInfo(selp);
AstBasicDType* const rhsBasicp if (!VN_IS(selp->rhsp()->dtypep()->skipRefp(), BasicDType)) {
= VN_CAST(selp->rhsp()->dtypep()->skipRefp(), BasicDType);
if (!rhsBasicp) {
clearOptimizable(lhsp, "Assign LHS concat of non-basic type"); clearOptimizable(lhsp, "Assign LHS concat of non-basic type");
return; return;
} }
@ -879,7 +877,7 @@ private:
checkNodeInfo(nodep); checkNodeInfo(nodep);
iterateChildrenConst(nodep); iterateChildrenConst(nodep);
if (AstInitArray* const initp = VN_CAST(fetchValueNull(nodep->fromp()), InitArray)) { if (AstInitArray* const initp = VN_CAST(fetchValueNull(nodep->fromp()), InitArray)) {
AstConst* const indexp = fetchConst(nodep->bitp()); const AstConst* const indexp = fetchConst(nodep->bitp());
const uint32_t offset = indexp->num().toUInt(); const uint32_t offset = indexp->num().toUInt();
AstNodeExpr* const itemp = initp->getIndexDefaultedValuep(offset); AstNodeExpr* const itemp = initp->getIndexDefaultedValuep(offset);
if (!itemp) { if (!itemp) {
@ -904,7 +902,7 @@ private:
iterateChildrenConst(nodep); iterateChildrenConst(nodep);
if (m_checkOnly || !optimizable()) return; if (m_checkOnly || !optimizable()) return;
// Fetch the base constant array // Fetch the base constant array
if (AstInitArray* const initp = VN_CAST(fetchValueNull(nodep->fromp()), InitArray)) { if (const AstInitArray* const initp = VN_CAST(fetchValueNull(nodep->fromp()), InitArray)) {
const VNumRange& sliceRange = nodep->declRange(); const VNumRange& sliceRange = nodep->declRange();
const uint32_t sliceElements = sliceRange.elements(); const uint32_t sliceElements = sliceRange.elements();
const int sliceLo = sliceRange.lo(); const int sliceLo = sliceRange.lo();
@ -962,7 +960,7 @@ private:
for (AstCaseItem* itemp = nodep->itemsp(); itemp; for (AstCaseItem* itemp = nodep->itemsp(); itemp;
itemp = VN_AS(itemp->nextp(), CaseItem)) { itemp = VN_AS(itemp->nextp(), CaseItem)) {
if (hit) break; if (hit) break;
if (!hit && itemp->isDefault()) { if (itemp->isDefault()) {
iterateAndNextConstNull(itemp->stmtsp()); iterateAndNextConstNull(itemp->stmtsp());
hit = true; hit = true;
} }
@ -1250,7 +1248,7 @@ private:
checkNodeInfo(nodep, /*display:*/ true); checkNodeInfo(nodep, /*display:*/ true);
iterateChildrenConst(nodep); iterateChildrenConst(nodep);
if (m_params) { if (m_params) {
AstConst* const textp = fetchConst(nodep->fmtp()); const AstConst* const textp = fetchConst(nodep->fmtp());
switch (nodep->displayType()) { switch (nodep->displayType()) {
case VDisplayType::DT_DISPLAY: // FALLTHRU case VDisplayType::DT_DISPLAY: // FALLTHRU
case VDisplayType::DT_INFO: v3warn(USERINFO, textp->name()); break; case VDisplayType::DT_INFO: v3warn(USERINFO, textp->name()); break;

View File

@ -938,10 +938,11 @@ def write_ast_impl(filename):
emitBlock(" BROKEN_RTN(!m_{name});\n" + emitBlock(" BROKEN_RTN(!m_{name});\n" +
" BROKEN_RTN(!m_{name}->brokeExists());\n", " BROKEN_RTN(!m_{name}->brokeExists());\n",
name=ptr['name']) name=ptr['name'])
if ptr['legals'] != '': legals = ptr['legals'].split('|')
if legals and legals != ["Node"]:
emitBlock(" BROKEN_RTN(m_{name} && !(", name=ptr['name']) emitBlock(" BROKEN_RTN(m_{name} && !(", name=ptr['name'])
eor = "" eor = ""
for legal in ptr['legals'].split('|'): for legal in legals:
# We use privateTypeTest, as VN_IS would assert that we know # We use privateTypeTest, as VN_IS would assert that we know
# the type is correct, but we want to check regardless, # the type is correct, but we want to check regardless,
# to find errors after raw node edits/replacements # to find errors after raw node edits/replacements
@ -956,10 +957,11 @@ def write_ast_impl(filename):
if op is None: if op is None:
continue continue
name, _, _, legals = op name, _, _, legals = op
if legals != '': legals = legals.split('|')
if legals and legals != ["Node"]:
emitBlock(" BROKEN_RTN({name}() && !(", name=name) emitBlock(" BROKEN_RTN({name}() && !(", name=name)
eor = "" eor = ""
for legal in legals.split('|'): for legal in legals:
emitBlock("{eor}privateTypeTest<Ast{legal}>({name}())", emitBlock("{eor}privateTypeTest<Ast{legal}>({name}())",
eor=eor, eor=eor,
name=name, name=name,
@ -978,12 +980,13 @@ def write_ast_impl(filename):
if op is None: if op is None:
continue continue
name, _, _, legals = op name, _, _, legals = op
if legals != '': legals = legals.split('|')
if legals and legals != ["Node"]:
# 'this' is a parent, where oldp replacing newp as op1p, must follow op1p's rules # 'this' is a parent, where oldp replacing newp as op1p, must follow op1p's rules
# Could also be on a list, we don't check for speed reasons and as V3Broken doesn't # Could also be on a list, we don't check for speed reasons and as V3Broken doesn't
emitBlock(" if (oldp == op{i}p() && !(", i=i) emitBlock(" if (oldp == op{i}p() && !(", i=i)
eor = "" eor = ""
for legal in legals.split('|'): for legal in legals:
emitBlock("{eor}privateTypeTest<Ast{legal}>(newp)", emitBlock("{eor}privateTypeTest<Ast{legal}>(newp)",
eor=eor, eor=eor,
name=name, name=name,
@ -994,16 +997,17 @@ def write_ast_impl(filename):
emitBlock(" return false;\n") emitBlock(" return false;\n")
emitBlock("}}\n") emitBlock("}}\n")
emitBlock("void Ast{t}::cloneRelinkGen() {{\n", t=node.name) if node.ptrs:
if node.superClass.name != 'Node': emitBlock("void Ast{t}::cloneRelinkGen() {{\n", t=node.name)
emitBlock(" Ast{base}::cloneRelinkGen();\n", base=node.superClass.name) if node.superClass.name != 'Node':
for ptr in node.ptrs: emitBlock(" Ast{base}::cloneRelinkGen();\n", base=node.superClass.name)
emitBlock( for ptr in node.ptrs:
" if (m_{name} && m_{name}->clonep()) m_{name} = m_{name}->clonep();\n", emitBlock(
name=ptr['name'], " if (m_{name} && m_{name}->clonep()) m_{name} = m_{name}->clonep();\n",
kind=ptr['kind']) name=ptr['name'],
kind=ptr['kind'])
emitBlock("}}\n") emitBlock("}}\n")
emitBlock("void Ast{t}::dumpJsonGen(std::ostream& str) const {{\n", t=node.name) emitBlock("void Ast{t}::dumpJsonGen(std::ostream& str) const {{\n", t=node.name)
if node.superClass.name != 'Node': if node.superClass.name != 'Node':
@ -1067,11 +1071,14 @@ def write_ast_macros(filename):
Ast{t}* addNext(Ast{t}* nodep) {{ return static_cast<Ast{t}*>(AstNode::addNext(this, nodep)); }} Ast{t}* addNext(Ast{t}* nodep) {{ return static_cast<Ast{t}*>(AstNode::addNext(this, nodep)); }}
const char* brokenGen() const override; const char* brokenGen() const override;
bool wouldBreakGen(const AstNode* const oldp, const AstNode* const newp) const override; bool wouldBreakGen(const AstNode* const oldp, const AstNode* const newp) const override;
void cloneRelinkGen() override;
void dumpTreeJsonOpGen(std::ostream& str, const string& indent) const override; void dumpTreeJsonOpGen(std::ostream& str, const string& indent) const override;
void dumpJsonGen(std::ostream& str) const; void dumpJsonGen(std::ostream& str) const;
''', ''',
t=node.name) t=node.name)
if node.ptrs:
emitBlock('''\
void cloneRelinkGen() override;
''')
if node.isLeaf: if node.isLeaf:
emitBlock('''\ emitBlock('''\

View File

@ -0,0 +1,33 @@
// Copyright 2003-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
cstyleCast
ctunullpointer
derefInvalidIteratorRedundantCheck
nullPointer
nullPointerRedundantCheck
templateRecursion
unusedFunction
unusedScopedObject
useInitializationList
useStlAlgorithm
// Seems useless
missingIncludeSystem
// Tedious
unmatchedSuppression
// Not our code
*:include/gtkwave/*
*:include/vltstd/*
// We intentionally redefine AstNode methods to improve type safety
duplInheritedMember:src/V3AstNode*.h
duplInheritedMember:src/obj_*/V3Ast__gen_impl.h
// We intentionally redefine DfgVertex methods to match Ast
duplInheritedMember:src/obj_*/V3Dfg__gen_auto_classes.h
// TODO: fix - maybe?
duplInheritedMember:src/V3File*.h
// They are used after astgen expansion
unusedPrivateFunction:src/V3Const.cpp

View File

@ -1,196 +0,0 @@
#!/usr/bin/env python3
# pylint: disable=C0103,C0114,C0115,C0116,C0209,R0911,R0912,R0915,W0621
######################################################################
import argparse
import os
import re
import sys
SuppressMap = {
# New cpp check error Can suppress with old error
'nullPointerRedundantCheck': 'nullPointer'
}
######################################################################
def process(cppcheck_args):
cmd = " ".join(cppcheck_args) + " 2>&1"
if Args.debug:
print("\t" + cmd)
fh = os.popen(cmd)
errs = False
last_error = ""
for line in fh:
line = line.rstrip()
if Args.debug:
print(">>>" + line)
line = re.sub(r'^\s+', '', line)
# Sometimes tacked at end-of-line
line = re.sub(r'Checking usage of global functions\.+', '', line)
line = re.sub(r' file0="[^"]+"', r'', line)
if re.search(r'^<\?xml version', line):
continue
if re.search(r'^<cppcheck', line):
continue
if re.search(r'^<errors', line):
continue
if re.search(r'^</error>', line):
continue
if re.search(r'^</errors>', line):
continue
if re.search(r'^<results', line):
continue
if re.search(r'^</results>', line):
continue
if re.search(r'^<symbol>', line):
continue
# An earlier id line is more specific
if re.search(r'Cppcheck cannot find all the include files', line):
continue
if re.search(r'^Checking ', line):
continue
if re.search(r'^make.*Entering directory ', line):
continue
if re.search(r'^make.*Leaving directory ', line):
continue
if re.search(r'^\s+$', line):
continue
# Output
if re.search(r'^cppcheck --', line):
if Args.debug:
print(line)
continue
if re.search(r'^\d+/\d+ files checked', line):
print(line)
continue
suppress = False
# --xml-format=2
if re.search(r'<error id', line):
last_error = line
continue
match = re.search(r'<location.* file="([^"]+)"\s+line="(\d+)"', line)
if match:
file = match.group(1)
linenum = int(match.group(2))
match = re.search(r' id="([^"]+)"', last_error)
eid = match.group(1) if match else '?'
if _suppress(file, linenum, eid):
suppress = True
if file == "*":
suppress = True
if not suppress:
print("%s:%s: %s" % (file, linenum, last_error))
suppress = True
if not suppress:
eline = "%Error: cppcheck: " + line
print(eline)
errs = True
if errs:
sys.exit(1)
######################################################################
def _suppress(filename, linenum, eid):
if Args.debug:
print("-Suppression search %s %s %s" % (filename, linenum, eid))
if filename == "*":
return False
# Cleanup for e.g. ../V3AstNode*.h
filename = re.sub(r'^\.\./(.*)', r'src/\1', filename)
# Specific suppressions
if eid == 'asctimeCalled' and re.search(r'gtkwave/', filename):
return True
if eid == 'constParameter' and re.search(r'gtkwave/', filename):
return True
if eid == 'ctuOneDefinitionRuleViolation' and re.search(r'vltstd/', filename):
return True
if eid == 'duplicateConditionalAssign' and re.search(r'gtkwave/', filename):
return True
if eid == 'knownConditionTrueFalse' and re.search(r'gtkwave/', filename):
return True
if eid == 'missingInclude' and re.search(r'systemc.h', filename):
return True
if eid == 'missingInclude' and re.search(r'svdpi.h', filename):
return True
if eid == 'shiftNegativeLHS' and re.search(r'gtkwave/', filename):
return True
if eid == 'shiftTooManyBits' and re.search(r'gtkwave/', filename):
return True
if eid == 'shiftTooManyBitsSigned' and re.search(r'gtkwave/', filename):
return True
if eid == 'nullPointerArithmetic' and re.search(r'gtkwave/', filename):
return True
if eid == 'unmatchedSuppression':
return True
if eid == 'unusedFunction' and re.search(r'verilated_dpi.cpp', filename):
return True
if eid == 'unusedFunction' and re.search(r'verilated_vpi.cpp', filename):
return True
if eid == 'unreachableCode' and re.search(r'V3ParseBison.c', filename):
return True
if eid == 'unreadVariable' and re.search(r'gtkwave/', filename):
return True
if eid == 'uselessAssignmentPtrArg' and re.search(r'gtkwave/', filename):
return True
if eid == 'variableScope' and re.search(r'fstapi.c', filename):
return True
if not os.path.exists(filename):
print("%Warning: " + filename + " does not exist, ignored", file=sys.stderr)
return False
with open(filename, "r", encoding="utf8") as fh:
lineno = 0
for line in fh:
lineno += 1
if (lineno + 1) == linenum:
match = re.search(r'(cppcheck|cppcheck-has-bug|cppverilator)-suppress((\s+\S+)+)',
line)
if match:
for supid in match.group(2).split():
if (supid == eid or (eid in SuppressMap and supid == SuppressMap[eid])):
return True
return False
#######################################################################
#######################################################################
parser = argparse.ArgumentParser(
allow_abbrev=False,
formatter_class=argparse.RawDescriptionHelpFormatter,
description="""cppcheck_filtered passes all arguments to cppcheck, then
filters out unnecessary warnings related to Verilator. Run as:
cd $VERILATOR_ROOT
make -k cppcheck""",
epilog="""Copyright 2014-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""")
parser.add_argument('--debug', action='store_true', help='enable debug')
Args, cppcheck_args = parser.parse_known_args()
process(cppcheck_args)
######################################################################
# Local Variables:
# compile-command: "cd .. ; src/cppcheck_filtered cppcheck --xml --enable=all src/V3Width.cpp"
# End: