Fix V3CUse, do not consider implementations (.cpp) at all (#4386)
This commit is contained in:
parent
6c6f03cf7c
commit
24917a187a
22
src/V3Ast.h
22
src/V3Ast.h
|
|
@ -1183,30 +1183,34 @@ inline std::ostream& operator<<(std::ostream& os, const VNumRange& rhs) {
|
|||
class VUseType final {
|
||||
public:
|
||||
enum en : uint8_t {
|
||||
IMP_INCLUDE, // Implementation (.cpp) needs an include
|
||||
INT_INCLUDE, // Interface (.h) needs an include
|
||||
IMP_FWD_CLASS, // Implementation (.cpp) needs a forward class declaration
|
||||
INT_FWD_CLASS, // Interface (.h) needs a forward class declaration
|
||||
// Enum values are compared with <, so order matters
|
||||
INT_FWD_CLASS = 1 << 0, // Interface (.h) needs a forward class declaration
|
||||
INT_INCLUDE = 1 << 1, // Interface (.h) needs an include
|
||||
};
|
||||
enum en m_e;
|
||||
VUseType()
|
||||
: m_e{IMP_FWD_CLASS} {}
|
||||
: m_e{INT_FWD_CLASS} {}
|
||||
// cppcheck-suppress noExplicitConstructor
|
||||
constexpr VUseType(en _e)
|
||||
: m_e{_e} {}
|
||||
explicit VUseType(int _e)
|
||||
: m_e(static_cast<en>(_e)) {} // Need () or GCC 4.8 false warning
|
||||
bool isInclude() const { return m_e == IMP_INCLUDE || m_e == INT_INCLUDE; }
|
||||
bool isFwdClass() const { return m_e == IMP_FWD_CLASS || m_e == INT_FWD_CLASS; }
|
||||
constexpr operator en() const { return m_e; }
|
||||
bool containsAny(VUseType other) { return m_e & other.m_e; }
|
||||
const char* ascii() const {
|
||||
static const char* const names[] = {"IMP_INC", "INT_INC", "IMP_FWD", "INT_FWD"};
|
||||
return names[m_e];
|
||||
static const char* const names[] = {"INT_FWD", "INT_INC", "INT_FWD_INC"};
|
||||
return names[m_e - 1];
|
||||
}
|
||||
};
|
||||
constexpr bool operator==(const VUseType& lhs, const VUseType& rhs) { return lhs.m_e == rhs.m_e; }
|
||||
constexpr bool operator==(const VUseType& lhs, VUseType::en rhs) { return lhs.m_e == rhs; }
|
||||
constexpr bool operator==(VUseType::en lhs, const VUseType& rhs) { return lhs == rhs.m_e; }
|
||||
constexpr VUseType::en operator|(VUseType::en lhs, VUseType::en rhs) {
|
||||
return VUseType::en((uint8_t)lhs | (uint8_t)rhs);
|
||||
}
|
||||
constexpr VUseType::en operator&(VUseType::en lhs, VUseType::en rhs) {
|
||||
return VUseType::en((uint8_t)lhs & (uint8_t)rhs);
|
||||
}
|
||||
inline std::ostream& operator<<(std::ostream& os, const VUseType& rhs) {
|
||||
return os << rhs.ascii();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,9 +28,11 @@
|
|||
#include "V3CUse.h"
|
||||
|
||||
#include "V3Ast.h"
|
||||
#include "V3FileLine.h"
|
||||
#include "V3Global.h"
|
||||
|
||||
#include <set>
|
||||
#include <map>
|
||||
#include <utility>
|
||||
|
||||
VL_DEFINE_DEBUG_FUNCTIONS;
|
||||
|
||||
|
|
@ -46,54 +48,31 @@ class CUseVisitor final : public VNVisitor {
|
|||
|
||||
// MEMBERS
|
||||
AstNodeModule* const m_modp; // Current module
|
||||
std::set<std::pair<VUseType, std::string>> m_didUse; // What we already used
|
||||
bool m_dtypesImplOnly = false;
|
||||
std::map<std::string, std::pair<FileLine*, VUseType>> m_didUse; // What we already used
|
||||
|
||||
// METHODS
|
||||
void addNewUse(AstNode* nodep, VUseType useType, const string& name) {
|
||||
if (m_dtypesImplOnly
|
||||
&& (useType == VUseType::INT_INCLUDE || useType == VUseType::INT_FWD_CLASS))
|
||||
return;
|
||||
|
||||
if (m_didUse.emplace(useType, name).second) {
|
||||
AstCUse* const newp = new AstCUse{nodep->fileline(), useType, name};
|
||||
m_modp->addStmtsp(newp);
|
||||
UINFO(8, "Insert " << newp << endl);
|
||||
auto e = m_didUse.emplace(name, std::make_pair(nodep->fileline(), useType));
|
||||
if (e.second || ((e.first->second.second & useType) != useType)) {
|
||||
e.first->second.second = e.first->second.second | useType;
|
||||
}
|
||||
}
|
||||
|
||||
// VISITORS
|
||||
void visit(AstClassRefDType* nodep) override {
|
||||
if (nodep->user1()) return; // Process once
|
||||
if (!m_dtypesImplOnly) // We might need to revisit this type for interface
|
||||
nodep->user1(true);
|
||||
addNewUse(nodep, VUseType::INT_FWD_CLASS, nodep->classp()->name());
|
||||
}
|
||||
void visit(AstCFunc* nodep) override {
|
||||
if (nodep->user1SetOnce()) return; // Process once
|
||||
if (nodep->user1SetOnce()) return;
|
||||
iterateAndNextNull(nodep->argsp());
|
||||
|
||||
{
|
||||
VL_RESTORER(m_dtypesImplOnly);
|
||||
m_dtypesImplOnly = true;
|
||||
|
||||
iterateAndNextNull(nodep->initsp());
|
||||
iterateAndNextNull(nodep->stmtsp());
|
||||
iterateAndNextNull(nodep->finalsp());
|
||||
}
|
||||
iterateAndNextNull(nodep->stmtsp());
|
||||
}
|
||||
void visit(AstCCall* nodep) override { return; }
|
||||
void visit(AstCReturn* nodep) override {
|
||||
if (nodep->user1SetOnce()) return; // Process once
|
||||
if (m_dtypesImplOnly) {
|
||||
for (AstNode* exprp = nodep->op1p(); exprp; exprp = exprp->nextp()) {
|
||||
if (exprp->dtypep()) iterate(exprp->dtypep());
|
||||
}
|
||||
} else {
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
UASSERT(!nodep->user1SetOnce(), "Visited same return twice.");
|
||||
iterate(nodep->lhsp()->dtypep());
|
||||
}
|
||||
void visit(AstNodeDType* nodep) override {
|
||||
if (nodep->user1SetOnce()) return; // Process once
|
||||
if (nodep->virtRefDTypep()) iterate(nodep->virtRefDTypep());
|
||||
if (nodep->virtRefDType2p()) iterate(nodep->virtRefDType2p());
|
||||
|
||||
|
|
@ -108,7 +87,7 @@ class CUseVisitor final : public VNVisitor {
|
|||
}
|
||||
void visit(AstNode* nodep) override {
|
||||
if (nodep->user1SetOnce()) return; // Process once
|
||||
if (nodep->dtypep() && !nodep->dtypep()->user1()) iterate(nodep->dtypep());
|
||||
if (nodep->dtypep()) iterate(nodep->dtypep());
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
void visit(AstCell* nodep) override {
|
||||
|
|
@ -123,6 +102,12 @@ public:
|
|||
explicit CUseVisitor(AstNodeModule* modp)
|
||||
: m_modp(modp) {
|
||||
iterate(modp);
|
||||
|
||||
for (auto& used : m_didUse) {
|
||||
AstCUse* const newp = new AstCUse{used.second.first, used.second.second, used.first};
|
||||
m_modp->addStmtsp(newp);
|
||||
UINFO(8, "Insert " << newp << endl);
|
||||
}
|
||||
}
|
||||
~CUseVisitor() override = default;
|
||||
VL_UNCOPYABLE(CUseVisitor);
|
||||
|
|
|
|||
|
|
@ -117,11 +117,12 @@ public:
|
|||
static void forModCUse(const AstNodeModule* modp, VUseType useType, F action) {
|
||||
for (AstNode* itemp = modp->stmtsp(); itemp; itemp = itemp->nextp()) {
|
||||
if (AstCUse* const usep = VN_CAST(itemp, CUse)) {
|
||||
if (usep->useType() == useType) {
|
||||
if (usep->useType().isInclude()) {
|
||||
if (usep->useType().containsAny(useType)) {
|
||||
if (usep->useType().containsAny(VUseType::INT_INCLUDE)) {
|
||||
action("#include \"" + prefixNameProtect(usep) + ".h\"\n");
|
||||
continue; // Forward declaration is not necessary
|
||||
}
|
||||
if (usep->useType().isFwdClass()) {
|
||||
if (usep->useType().containsAny(VUseType::INT_FWD_CLASS)) {
|
||||
action("class " + prefixNameProtect(usep) + ";\n");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -380,11 +380,10 @@ class EmitCHeader final : public EmitCConstInit {
|
|||
std::set<string> cuse_set;
|
||||
auto add_to_cuse_set = [&](string s) { cuse_set.insert(s); };
|
||||
|
||||
forModCUse(modp, VUseType::INT_INCLUDE, add_to_cuse_set);
|
||||
forModCUse(modp, VUseType::INT_FWD_CLASS, add_to_cuse_set);
|
||||
forModCUse(modp, VUseType::INT_FWD_CLASS | VUseType::INT_INCLUDE, add_to_cuse_set);
|
||||
if (const AstClassPackage* const packagep = VN_CAST(modp, ClassPackage)) {
|
||||
forModCUse(packagep->classp(), VUseType::INT_INCLUDE, add_to_cuse_set);
|
||||
forModCUse(packagep->classp(), VUseType::INT_FWD_CLASS, add_to_cuse_set);
|
||||
forModCUse(packagep->classp(), VUseType::INT_INCLUDE | VUseType::INT_FWD_CLASS,
|
||||
add_to_cuse_set);
|
||||
}
|
||||
|
||||
for (const string& s : cuse_set) puts(s);
|
||||
|
|
|
|||
Loading…
Reference in New Issue