mirror of
https://github.com/verilator/verilator.git
synced 2025-04-05 20:22:41 +00:00
Fix object assignment from conditionals (#4968).
This commit is contained in:
parent
d3b93a1113
commit
0262819c20
1
Changes
1
Changes
@ -31,6 +31,7 @@ Verilator 5.023 devel
|
|||||||
* Fix DFG removing forceable signals (#4942). [Geza Lore]
|
* Fix DFG removing forceable signals (#4942). [Geza Lore]
|
||||||
* Fix null characters in shortened identifiers (#4946). [Abdul Hameed]
|
* Fix null characters in shortened identifiers (#4946). [Abdul Hameed]
|
||||||
* Fix assignment of null into struct member (#4952).
|
* Fix assignment of null into struct member (#4952).
|
||||||
|
* Fix object assignment from conditionals (#4968).
|
||||||
* Fix unpacked structure upper bit cleaning (#4978).
|
* Fix unpacked structure upper bit cleaning (#4978).
|
||||||
|
|
||||||
|
|
||||||
|
@ -1581,26 +1581,26 @@ VCastable AstNode::computeCastable(const AstNodeDType* toDtp, const AstNodeDType
|
|||||||
return castable;
|
return castable;
|
||||||
}
|
}
|
||||||
|
|
||||||
AstNodeDType* AstNode::getCommonClassTypep(AstNode* nodep1, AstNode* nodep2) {
|
AstNodeDType* AstNode::getCommonClassTypep(AstNode* node1p, AstNode* node2p) {
|
||||||
// Return the class type that both nodep1 and nodep2 are castable to.
|
// Return the class type that both node1p and node2p are castable to.
|
||||||
// If both are null, return the type of null constant.
|
// If both are null, return the type of null constant.
|
||||||
// If one is a class and one is null, return AstClassRefDType that points to that class.
|
// If one is a class and one is null, return AstClassRefDType that points to that class.
|
||||||
// If no common class type exists, return nullptr.
|
// If no common class type exists, return nullptr.
|
||||||
|
|
||||||
// First handle cases with null values and when one class is a super class of the other.
|
// First handle cases with null values and when one class is a super class of the other.
|
||||||
if (VN_IS(nodep1, Const)) std::swap(nodep1, nodep2);
|
if (VN_IS(node1p, Const)) std::swap(node1p, node2p);
|
||||||
{
|
{
|
||||||
const VCastable castable = computeCastable(nodep1->dtypep(), nodep2->dtypep(), nodep2);
|
const VCastable castable = computeCastable(node1p->dtypep(), node2p->dtypep(), node2p);
|
||||||
if (castable == VCastable::SAMEISH || castable == VCastable::COMPATIBLE) {
|
if (castable == VCastable::SAMEISH || castable == VCastable::COMPATIBLE) {
|
||||||
return nodep1->dtypep();
|
return node1p->dtypep();
|
||||||
} else if (castable == VCastable::DYNAMIC_CLASS) {
|
} else if (castable == VCastable::DYNAMIC_CLASS) {
|
||||||
return nodep2->dtypep();
|
return node2p->dtypep();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
AstClassRefDType* classDtypep1 = VN_CAST(nodep1->dtypep(), ClassRefDType);
|
AstClassRefDType* classDtypep1 = VN_CAST(node1p->dtypep(), ClassRefDType);
|
||||||
while (classDtypep1) {
|
while (classDtypep1) {
|
||||||
const VCastable castable = computeCastable(classDtypep1, nodep2->dtypep(), nodep2);
|
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();
|
AstClassExtends* const extendsp = classDtypep1->classp()->extendsp();
|
||||||
classDtypep1 = extendsp ? VN_AS(extendsp->dtypep(), ClassRefDType) : nullptr;
|
classDtypep1 = extendsp ? VN_AS(extendsp->dtypep(), ClassRefDType) : nullptr;
|
||||||
|
@ -47,7 +47,7 @@ bool AstNode::isSigned() const VL_MT_STABLE { return dtypep() && dtypep()->isSig
|
|||||||
|
|
||||||
bool AstNode::isClassHandleValue() const {
|
bool AstNode::isClassHandleValue() const {
|
||||||
return (VN_IS(this, Const) && VN_AS(this, Const)->num().isNull())
|
return (VN_IS(this, Const) && VN_AS(this, Const)->num().isNull())
|
||||||
|| VN_IS(dtypep(), ClassRefDType);
|
|| (dtypep() && VN_IS(dtypep()->skipRefp(), ClassRefDType));
|
||||||
}
|
}
|
||||||
bool AstNode::isNull() const { return VN_IS(this, Const) && VN_AS(this, Const)->num().isNull(); }
|
bool AstNode::isNull() const { return VN_IS(this, Const) && VN_AS(this, Const)->num().isNull(); }
|
||||||
bool AstNode::isZero() const {
|
bool AstNode::isZero() const {
|
||||||
|
@ -121,14 +121,14 @@ class CastVisitor final : public VNVisitor {
|
|||||||
// already checked by V3Width and dtypep of a condition operator is a type of their
|
// already checked by V3Width and dtypep of a condition operator is a type of their
|
||||||
// common base class, so both classes can be safely casted.
|
// common base class, so both classes can be safely casted.
|
||||||
const AstClassRefDType* const thenClassDtypep
|
const AstClassRefDType* const thenClassDtypep
|
||||||
= VN_CAST(nodep->thenp()->dtypep(), ClassRefDType);
|
= VN_CAST(nodep->thenp()->dtypep()->skipRefp(), ClassRefDType);
|
||||||
const AstClassRefDType* const elseClassDtypep
|
const AstClassRefDType* const elseClassDtypep
|
||||||
= VN_CAST(nodep->elsep()->dtypep(), ClassRefDType);
|
= VN_CAST(nodep->elsep()->dtypep()->skipRefp(), ClassRefDType);
|
||||||
const bool castRequired = thenClassDtypep && elseClassDtypep
|
const bool castRequired = thenClassDtypep && elseClassDtypep
|
||||||
&& (thenClassDtypep->classp() != elseClassDtypep->classp());
|
&& (thenClassDtypep->classp() != elseClassDtypep->classp());
|
||||||
if (castRequired) {
|
if (castRequired) {
|
||||||
const AstClass* const commonBaseClassp
|
const AstClass* const commonBaseClassp
|
||||||
= VN_AS(nodep->dtypep(), ClassRefDType)->classp();
|
= VN_AS(nodep->dtypep()->skipRefp(), ClassRefDType)->classp();
|
||||||
if (thenClassDtypep->classp() != commonBaseClassp) {
|
if (thenClassDtypep->classp() != commonBaseClassp) {
|
||||||
AstNodeExpr* thenp = nodep->thenp()->unlinkFrBack();
|
AstNodeExpr* thenp = nodep->thenp()->unlinkFrBack();
|
||||||
nodep->thenp(new AstCCast{thenp->fileline(), thenp, nodep});
|
nodep->thenp(new AstCCast{thenp->fileline(), thenp, nodep});
|
||||||
|
@ -30,9 +30,11 @@ class ExtendExtendCls extends ExtendCls;
|
|||||||
endclass
|
endclass
|
||||||
|
|
||||||
module t (/*AUTOARG*/);
|
module t (/*AUTOARG*/);
|
||||||
|
typedef ExtendCls ExtendCls_t;
|
||||||
|
|
||||||
initial begin
|
initial begin
|
||||||
Cls cls1 = null, cls2 = null;
|
Cls cls1 = null, cls2 = null;
|
||||||
ExtendCls ext_cls = null;
|
ExtendCls_t ext_cls = null;
|
||||||
AnotherExtendCls an_ext_cls = null;
|
AnotherExtendCls an_ext_cls = null;
|
||||||
ExtendExtendCls ext_ext_cls = null;
|
ExtendExtendCls ext_ext_cls = null;
|
||||||
int r;
|
int r;
|
||||||
|
Loading…
Reference in New Issue
Block a user