diff --git a/source/ast/expressions/Operator.cpp b/source/ast/expressions/Operator.cpp index 84dc8b42d..a2df26e1f 100644 --- a/source/ast/expressions/Operator.cpp +++ b/source/ast/expressions/Operator.cpp @@ -482,6 +482,7 @@ bool OpInfo::isShortCircuit(BinaryOperator op) { } } +// LCOV_EXCL_START std::string_view OpInfo::getText(BinaryOperator op) { switch (op) { case BinaryOperator::Add: @@ -591,5 +592,6 @@ int OpInfo::getPrecedence(BinaryOperator op) { } SLANG_UNREACHABLE; } +// LCOV_EXCL_STOP } // namespace slang::ast diff --git a/source/ast/expressions/OperatorExpressions.cpp b/source/ast/expressions/OperatorExpressions.cpp index 4ba710a88..28ba08e18 100644 --- a/source/ast/expressions/OperatorExpressions.cpp +++ b/source/ast/expressions/OperatorExpressions.cpp @@ -206,9 +206,7 @@ bool Expression::bindMembershipExpressions(const ASTContext& context, TokenKind else selfDetermined(context, expr); - if (expr->bad()) - return false; - + SLANG_ASSERT(!expr->bad()); results[index++] = expr; } @@ -384,9 +382,6 @@ ConstantValue UnaryExpression::evalImpl(EvalContext& context) const { // Handle operations that require an lvalue up front. if (OpInfo::isLValue(op)) { LValue lvalue = operand().evalLValue(context); - if (!lvalue) - return nullptr; - ConstantValue cv = lvalue.load(); if (!cv) return nullptr; @@ -404,7 +399,7 @@ ConstantValue UnaryExpression::evalImpl(EvalContext& context) const { OP(Postincrement, v + 1); OP(Postdecrement, v - 1); default: - break; + SLANG_UNREACHABLE; } #undef OP } @@ -421,7 +416,7 @@ ConstantValue UnaryExpression::evalImpl(EvalContext& context) const { OP(Postincrement, v + 1); OP(Postdecrement, v - 1); default: - break; + SLANG_UNREACHABLE; } #undef OP } @@ -438,7 +433,7 @@ ConstantValue UnaryExpression::evalImpl(EvalContext& context) const { OP(Postincrement, v + 1); OP(Postdecrement, v - 1); default: - break; + SLANG_UNREACHABLE; } #undef OP } diff --git a/tests/regression/all.sv b/tests/regression/all.sv index 0d8b3e41b..4019ff41a 100644 --- a/tests/regression/all.sv +++ b/tests/regression/all.sv @@ -122,6 +122,8 @@ macromodule m3; if (instr matches (tagged Jmp .j) &&& j matches (tagged JmpC '{cc:.c,addr:.a})) begin pc = c[0] & a[0]; + pc = instr matches (tagged Jmp .j) &&& + j matches (tagged JmpC '{cc:.c,addr:.a}) ? c[0] & a[0] : 0; end else begin end @@ -457,3 +459,26 @@ class C3; b: cross y, x; endgroup endclass + +module m9; + logic [3:0] a = {4 {1'b1}}; +endmodule + +module m10; + byte stream[$]; + class Packet; + rand int header; + rand int len; + rand byte payload[]; + int crc; + constraint G { len > 1; payload.size == len ; } + function void post_randomize; crc = payload.sum; endfunction + endclass + + initial begin + byte q[$]; + automatic Packet p = new; + {<< byte{ p.header, p.len, p.payload with [0 +: p.len], p.crc }} = stream; + stream = stream[ $bits(p) / 8 : $ ]; + end +endmodule diff --git a/tests/unittests/ast/ExpressionTests.cpp b/tests/unittests/ast/ExpressionTests.cpp index 101e1733f..af2e9a2ed 100644 --- a/tests/unittests/ast/ExpressionTests.cpp +++ b/tests/unittests/ast/ExpressionTests.cpp @@ -3823,3 +3823,94 @@ endmodule ast::EvalContext eval_ctx(ast::ASTContext(compilation.getRoot(), ast::LookupLocation::max)); CHECK(var.getInitializer()->eval(eval_ctx).getBitstreamWidth() == 4); } + +TEST_CASE("Value range where implicit strings not allowed") { + auto tree = SyntaxTree::fromText(R"( +int i = "a" inside { [1:2] }; +)"); + + Compilation compilation; + compilation.addSyntaxTree(tree); + NO_COMPILATION_ERRORS; +} + +TEST_CASE("LValue required for prefix unary operators") { + auto tree = SyntaxTree::fromText(R"( +module m; + initial begin + ++(1 + 1); + (1 + 1)++; + end +endmodule +)"); + + Compilation compilation; + compilation.addSyntaxTree(tree); + + auto& diags = compilation.getAllDiagnostics(); + REQUIRE(diags.size() == 2); + CHECK(diags[0].code == diag::ExpressionNotAssignable); + CHECK(diags[1].code == diag::ExpressionNotAssignable); +} + +TEST_CASE("More operator eval tests") { + auto tree = SyntaxTree::fromText(R"( +parameter p = foo(); + +function automatic bit foo; + shortreal a = 1.0; + int b = 3; + string s; + event ev; + union { int i; shortreal r; } u, v; + + assert(++a == shortreal'(2.0)); + assert(a++ == shortreal'(2.0)); + --a; + assert(a-- == shortreal'(2.0)); + assert(+b == 3); + assert(^4'b1000 == 1); + assert(~&4'b1111 == 0); + assert(~|4'b0000 == 1); + assert(~^4'b1000 == 0); + assert(+a == shortreal'(1.0)); + assert(-a == shortreal'(-1.0)); + assert((!a) == 0); + assert((!s) == 1); + assert(a === shortreal'(1.0)); + assert(!(a !== shortreal'(1.0))); + assert(a && 1); + assert(a || 0); + assert(0 || b); + assert(0 || 1.0); + assert(1 -> a); + assert(1.0 <-> a); + assert(a <-> 1.0); + assert(1.0 && 1.0); + assert(0.0 || 1.0); + assert(3 % 2 == 1); + assert(3 !== 2); + assert(3'b1x0 !=? 3'b111); + assert(1 <-> 1); + assert(s === ""); + assert(s !== "asdf"); + assert(ev === null); + assert(!(ev != null)); + assert(!(ev !== null)); + + assert(u === v); + u.i = 1; + v.r = 1.0; + assert(u != v); + assert(u !== v); +endfunction +)"); + + Compilation compilation; + compilation.addSyntaxTree(tree); + + auto diags = compilation.getAllDiagnostics().filter({diag::FloatBoolConv, diag::IntBoolConv}); + if (!diags.empty()) { + FAIL_CHECK(report(diags)); + } +} diff --git a/tests/unittests/ast/WarningTests.cpp b/tests/unittests/ast/WarningTests.cpp index cf3c283c2..9a3a32a9c 100644 --- a/tests/unittests/ast/WarningTests.cpp +++ b/tests/unittests/ast/WarningTests.cpp @@ -743,6 +743,7 @@ module m; logic signed [1:0] l = (2'd3:2'd1:-3); logic signed m = (2'd1 == 2'd1); logic signed [1:0] n = 2'd1 << 1; + logic signed [1:0] o = +2'd3; endmodule )"); @@ -750,10 +751,11 @@ endmodule compilation.addSyntaxTree(tree); auto& diags = compilation.getAllDiagnostics(); - REQUIRE(diags.size() == 3); - CHECK(diags[0].code == diag::SignConversion); - CHECK(diags[0].code == diag::SignConversion); + REQUIRE(diags.size() == 4); CHECK(diags[0].code == diag::SignConversion); + CHECK(diags[1].code == diag::SignConversion); + CHECK(diags[2].code == diag::SignConversion); + CHECK(diags[3].code == diag::SignConversion); } TEST_CASE("Edge of multibit type") { diff --git a/tests/unittests/parsing/VisitorTests.cpp b/tests/unittests/parsing/VisitorTests.cpp index 4dfae7ca8..04e17a856 100644 --- a/tests/unittests/parsing/VisitorTests.cpp +++ b/tests/unittests/parsing/VisitorTests.cpp @@ -747,5 +747,5 @@ TEST_CASE("Visit all file") { v.visitDefault(elem); })); - CHECK(count == 1488); + CHECK(count == 1606); }