Skip to content

Commit

Permalink
Fix spurious width warnings for conditional operators within an expli…
Browse files Browse the repository at this point in the history
…cit cast
  • Loading branch information
MikePopoloski committed Jan 30, 2025
1 parent 2e39ffe commit 1908099
Show file tree
Hide file tree
Showing 9 changed files with 41 additions and 16 deletions.
3 changes: 2 additions & 1 deletion include/slang/ast/expressions/LiteralExpressions.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,8 @@ class SLANG_EXPORT UnbasedUnsizedIntegerLiteral : public Expression {
SVInt getValue() const;

ConstantValue evalImpl(EvalContext& context) const;
bool propagateType(const ASTContext& context, const Type& newType, SourceRange opRange);
bool propagateType(const ASTContext& context, const Type& newType, SourceRange opRange,
ConversionKind conversionKind);
std::optional<bitwidth_t> getEffectiveWidthImpl() const;
EffectiveSign getEffectiveSignImpl(bool isForConversion) const;

Expand Down
3 changes: 2 additions & 1 deletion include/slang/ast/expressions/MiscExpressions.h
Original file line number Diff line number Diff line change
Expand Up @@ -306,7 +306,8 @@ class SLANG_EXPORT MinTypMaxExpression : public Expression {
Expression& selected() { return *selected_; }

ConstantValue evalImpl(EvalContext& context) const;
bool propagateType(const ASTContext& context, const Type& newType, SourceRange opRange);
bool propagateType(const ASTContext& context, const Type& newType, SourceRange opRange,
ConversionKind conversionKind);
std::optional<bitwidth_t> getEffectiveWidthImpl() const;
EffectiveSign getEffectiveSignImpl(bool isForConversion) const;

Expand Down
12 changes: 8 additions & 4 deletions include/slang/ast/expressions/OperatorExpressions.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ class SLANG_EXPORT UnaryExpression : public Expression {
Expression& operand() { return *operand_; }

ConstantValue evalImpl(EvalContext& context) const;
bool propagateType(const ASTContext& context, const Type& newType, SourceRange opRange);
bool propagateType(const ASTContext& context, const Type& newType, SourceRange opRange,
ConversionKind conversionKind);
std::optional<bitwidth_t> getEffectiveWidthImpl() const;
EffectiveSign getEffectiveSignImpl(bool isForConversion) const;

Expand Down Expand Up @@ -93,7 +94,8 @@ class SLANG_EXPORT BinaryExpression : public Expression {
Expression& right() { return *right_; }

ConstantValue evalImpl(EvalContext& context) const;
bool propagateType(const ASTContext& context, const Type& newType, SourceRange opRange);
bool propagateType(const ASTContext& context, const Type& newType, SourceRange opRange,
ConversionKind conversionKind);
std::optional<bitwidth_t> getEffectiveWidthImpl() const;
EffectiveSign getEffectiveSignImpl(bool isForConversion) const;

Expand Down Expand Up @@ -158,7 +160,8 @@ class SLANG_EXPORT ConditionalExpression : public Expression {
Expression& right() { return *right_; }

ConstantValue evalImpl(EvalContext& context) const;
bool propagateType(const ASTContext& context, const Type& newType, SourceRange opRange);
bool propagateType(const ASTContext& context, const Type& newType, SourceRange opRange,
ConversionKind conversionKind);
std::optional<bitwidth_t> getEffectiveWidthImpl() const;
EffectiveSign getEffectiveSignImpl(bool isForConversion) const;

Expand Down Expand Up @@ -394,7 +397,8 @@ class SLANG_EXPORT ValueRangeExpression : public Expression {
Expression& right() { return *right_; }

ConstantValue evalImpl(EvalContext& context) const;
bool propagateType(const ASTContext& context, const Type& newType, SourceRange opRange);
bool propagateType(const ASTContext& context, const Type& newType, SourceRange opRange,
ConversionKind conversionKind);

ConstantValue checkInside(EvalContext& context, const ConstantValue& val) const;

Expand Down
4 changes: 2 additions & 2 deletions source/ast/Expression.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ struct Expression::PropagationVisitor {
// check if the conversion should be pushed further down the tree. Otherwise we
// should insert the implicit conversion here.
bool needConversion = !newType.isEquivalent(*expr.type);
if constexpr (requires { expr.propagateType(context, newType, opRange); }) {
if constexpr (requires { expr.propagateType(context, newType, opRange, conversionKind); }) {
if ((newType.isFloating() && expr.type->isFloating()) ||
(newType.isIntegral() && expr.type->isIntegral()) || newType.isString() ||
expr.kind == ExpressionKind::ValueRange) {
Expand All @@ -174,7 +174,7 @@ struct Expression::PropagationVisitor {
updateRange(expr);
}

if (expr.propagateType(context, newType, opRange)) {
if (expr.propagateType(context, newType, opRange, conversionKind)) {
// We propagated the type successfully so we don't need a conversion.
// We should however clear out any constant value that may have been
// stored here, since it may no longer be valid given the new type.
Expand Down
5 changes: 4 additions & 1 deletion source/ast/expressions/ConversionExpression.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,8 @@ static bool actuallyNeededCast(const Type& type, const Expression& operand) {
return actuallyNeededCast(type, operand.as<MinTypMaxExpression>().selected());
case ExpressionKind::ConditionalOp: {
auto& cond = operand.as<ConditionalExpression>();
if (!type.isEquivalent(*cond.left().type) || !type.isEquivalent(*cond.right().type))
return true;
return actuallyNeededCast(type, cond.left()) || actuallyNeededCast(type, cond.right());
}
default:
Expand Down Expand Up @@ -403,7 +405,8 @@ Expression& ConversionExpression::fromSyntax(Compilation& comp, const CastExpres
};

if (type->isMatching(*operand->type) && !isGenvar() && !isDifferentTypedef() &&
((assignmentTarget && assignmentTarget->isMatching(*type)) ||
((assignmentTarget && assignmentTarget->isMatching(*type) &&
operand->kind != ExpressionKind::ConditionalOp) ||
!actuallyNeededCast(*type, *operand))) {
context.addDiag(diag::UselessCast, syntax.apostrophe.location())
<< *operand->type << targetExpr.sourceRange << operand->sourceRange;
Expand Down
2 changes: 1 addition & 1 deletion source/ast/expressions/LiteralExpressions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ Expression& UnbasedUnsizedIntegerLiteral::fromSyntax(Compilation& compilation,
}

bool UnbasedUnsizedIntegerLiteral::propagateType(const ASTContext&, const Type& newType,
SourceRange) {
SourceRange, ConversionKind) {
SLANG_ASSERT(newType.isIntegral());
SLANG_ASSERT(newType.getBitWidth());

Expand Down
2 changes: 1 addition & 1 deletion source/ast/expressions/MiscExpressions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1340,7 +1340,7 @@ Expression& MinTypMaxExpression::fromSyntax(Compilation& compilation,
}

bool MinTypMaxExpression::propagateType(const ASTContext& context, const Type& newType,
SourceRange opRange) {
SourceRange opRange, ConversionKind) {
// Only the selected expression gets a propagated type.
type = &newType;
contextDetermined(context, selected_, this, newType, opRange);
Expand Down
11 changes: 6 additions & 5 deletions source/ast/expressions/OperatorExpressions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -329,7 +329,7 @@ Expression& UnaryExpression::fromSyntax(Compilation& compilation,
}

bool UnaryExpression::propagateType(const ASTContext& context, const Type& newType,
SourceRange propRange) {
SourceRange propRange, ConversionKind) {
switch (op) {
case UnaryOperator::Plus:
case UnaryOperator::Minus:
Expand Down Expand Up @@ -1113,7 +1113,7 @@ void BinaryExpression::analyzeOpTypes(const Type& clt, const Type& crt, const Ty
}

bool BinaryExpression::propagateType(const ASTContext& context, const Type& newType,
SourceRange propRange) {
SourceRange propRange, ConversionKind) {
switch (op) {
case BinaryOperator::Add:
case BinaryOperator::Subtract:
Expand Down Expand Up @@ -1460,7 +1460,7 @@ Expression& ConditionalExpression::fromSyntax(Compilation& comp,
}

bool ConditionalExpression::propagateType(const ASTContext& context, const Type& newType,
SourceRange opRange) {
SourceRange opRange, ConversionKind conversionKind) {
const bool parentTypeEquiv = type->isEquivalent(newType);
type = &newType;

Expand All @@ -1477,7 +1477,8 @@ bool ConditionalExpression::propagateType(const ASTContext& context, const Type&
std::optional<bitwidth_t> otherEffectiveWidth) {
// This is a propagated conversion but we'd like to see width-expand
// warnings anyway so we'll manually do the check conversion check here.
if (!flags.has(ASTFlags::UnevaluatedBranch)) {
if (!flags.has(ASTFlags::UnevaluatedBranch) &&
conversionKind <= ConversionKind::Propagated) {
// If the parent type was already equivalent to what's being propagated,
// then the only conversions we might be doing are "self induced", in the
// sense that one branch is propagating its type to the other side.
Expand Down Expand Up @@ -2423,7 +2424,7 @@ Expression& ValueRangeExpression::fromSyntax(Compilation& comp,
}

bool ValueRangeExpression::propagateType(const ASTContext& context, const Type& newType,
SourceRange opRange) {
SourceRange opRange, ConversionKind) {
contextDetermined(context, left_, this, newType, opRange);
if (rangeKind == ValueRangeKind::Simple)
contextDetermined(context, right_, this, newType, opRange);
Expand Down
15 changes: 15 additions & 0 deletions tests/unittests/ast/WarningTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1358,6 +1358,21 @@ module test2;
c = cond ? d : 0;
end
endmodule
module test3;
localparam int unsigned SIZE = 16;
logic a;
logic [7:0] b, c;
logic [SIZE-1:0] d, e, f, g;
always_comb begin
d = SIZE'( a ? b : c);
e = SIZE'(b);
f = a ? SIZE'(b) : SIZE'(c);
g = SIZE'( (a == 0) ? f : c);
end
endmodule
)");

Compilation compilation;
Expand Down

0 comments on commit 1908099

Please sign in to comment.