diff --git a/frontends/p4/typeChecking/typeCheckExpr.cpp b/frontends/p4/typeChecking/typeCheckExpr.cpp index 851a5de79bb..b98163273a1 100644 --- a/frontends/p4/typeChecking/typeCheckExpr.cpp +++ b/frontends/p4/typeChecking/typeCheckExpr.cpp @@ -915,6 +915,12 @@ const IR::Node *TypeInferenceBase::shift(const IR::Operation_Binary *expression) // getTypeType should have already taken care of the error message return expression; } + // FIXME: #5100, strip the new-type introduced by `type` keyword for now. According to the spec, + // such code should be rejected, but before #5099 it was accepted, so keep it accepted for now, + // until we discuss what is the right approach here. + if (const auto *rt = rtype->to()) { + rtype = getTypeType(rt->type); + } auto lt = ltype->to(); if (auto cst = expression->right->to()) { if (!cst->fitsInt()) { @@ -945,9 +951,14 @@ const IR::Node *TypeInferenceBase::shift(const IR::Operation_Binary *expression) } } - if (rtype->is() && rtype->to()->isSigned) { + if (const auto *rbits = rtype->to(); rbits && rbits->isSigned) { typeError("%1%: Shift amount must be an unsigned number", expression->right); return expression; + } else if (!rbits && !rtype->is()) { + typeError( + "%1%: The right operand of shifts must be either an expression of type bit or int, " + "but is %2%", + expression->right, rtype); } if (!lt && !ltype->is()) { diff --git a/testdata/p4_16_errors/issue5094-a-bmv2.p4 b/testdata/p4_16_errors/issue5094-a-bmv2.p4 new file mode 100644 index 00000000000..5f74690e1e2 --- /dev/null +++ b/testdata/p4_16_errors/issue5094-a-bmv2.p4 @@ -0,0 +1,38 @@ +/* +Copyright 2013-present Barefoot Networks, Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +#include +#include + +header hdr { + int<32> a; + bit<8> b; + int<64> c; +} + +#include "../p4_16_samples/arith-skeleton.p4" + +control ingress(inout Headers h, inout Meta m, inout standard_metadata_t sm) { + action shift() + { h.h.c = (int<64>)(h.h.a >> "aaaa"); sm.egress_spec = 0; } + table t { + actions = { shift; } + const default_action = shift; + } + apply { t.apply(); } +} + +V1Switch(p(), vrfy(), ingress(), egress(), update(), deparser()) main; diff --git a/testdata/p4_16_errors/issue5094-b-bmv2.p4 b/testdata/p4_16_errors/issue5094-b-bmv2.p4 new file mode 100644 index 00000000000..2e0a5393ba3 --- /dev/null +++ b/testdata/p4_16_errors/issue5094-b-bmv2.p4 @@ -0,0 +1,38 @@ +/* +Copyright 2013-present Barefoot Networks, Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +#include +#include + +header hdr { + int<32> a; + bit<8> b; + int<64> c; +} + +#include "../p4_16_samples/arith-skeleton.p4" + +control ingress(inout Headers h, inout Meta m, inout standard_metadata_t sm) { + action shift() + { h.h.c = (int<64>)(h.h.a << m); sm.egress_spec = 0; } + table t { + actions = { shift; } + const default_action = shift; + } + apply { t.apply(); } +} + +V1Switch(p(), vrfy(), ingress(), egress(), update(), deparser()) main; diff --git a/testdata/p4_16_errors_outputs/issue5094-a-bmv2.p4 b/testdata/p4_16_errors_outputs/issue5094-a-bmv2.p4 new file mode 100644 index 00000000000..10ccc11a64a --- /dev/null +++ b/testdata/p4_16_errors_outputs/issue5094-a-bmv2.p4 @@ -0,0 +1,62 @@ +#include +#define V1MODEL_VERSION 20180101 +#include + +header hdr { + int<32> a; + bit<8> b; + int<64> c; +} + +struct Headers { + hdr h; +} + +struct Meta { +} + +parser p(packet_in b, out Headers h, inout Meta m, inout standard_metadata_t sm) { + state start { + b.extract(h.h); + transition accept; + } +} + +control vrfy(inout Headers h, inout Meta m) { + apply { + } +} + +control update(inout Headers h, inout Meta m) { + apply { + } +} + +control egress(inout Headers h, inout Meta m, inout standard_metadata_t sm) { + apply { + } +} + +control deparser(packet_out b, in Headers h) { + apply { + b.emit(h.h); + } +} + +control ingress(inout Headers h, inout Meta m, inout standard_metadata_t sm) { + action shift() { + h.h.c = (int<64>)(h.h.a >> "aaaa"); + sm.egress_spec = 0; + } + table t { + actions = { + shift; + } + const default_action = shift; + } + apply { + t.apply(); + } +} + +V1Switch(p(), vrfy(), ingress(), egress(), update(), deparser()) main; diff --git a/testdata/p4_16_errors_outputs/issue5094-a-bmv2.p4-stderr b/testdata/p4_16_errors_outputs/issue5094-a-bmv2.p4-stderr new file mode 100644 index 00000000000..9c105735e3d --- /dev/null +++ b/testdata/p4_16_errors_outputs/issue5094-a-bmv2.p4-stderr @@ -0,0 +1,3 @@ +issue5094-a-bmv2.p4(30): [--Werror=type-error] error: "aaaa": The right operand of shifts must be either an expression of type bit or int, but is string + { h.h.c = (int<64>)(h.h.a >> "aaaa"); sm.egress_spec = 0; } + ^ diff --git a/testdata/p4_16_errors_outputs/issue5094-b-bmv2.p4 b/testdata/p4_16_errors_outputs/issue5094-b-bmv2.p4 new file mode 100644 index 00000000000..a9dab6abc76 --- /dev/null +++ b/testdata/p4_16_errors_outputs/issue5094-b-bmv2.p4 @@ -0,0 +1,62 @@ +#include +#define V1MODEL_VERSION 20180101 +#include + +header hdr { + int<32> a; + bit<8> b; + int<64> c; +} + +struct Headers { + hdr h; +} + +struct Meta { +} + +parser p(packet_in b, out Headers h, inout Meta m, inout standard_metadata_t sm) { + state start { + b.extract(h.h); + transition accept; + } +} + +control vrfy(inout Headers h, inout Meta m) { + apply { + } +} + +control update(inout Headers h, inout Meta m) { + apply { + } +} + +control egress(inout Headers h, inout Meta m, inout standard_metadata_t sm) { + apply { + } +} + +control deparser(packet_out b, in Headers h) { + apply { + b.emit(h.h); + } +} + +control ingress(inout Headers h, inout Meta m, inout standard_metadata_t sm) { + action shift() { + h.h.c = (int<64>)(h.h.a << m); + sm.egress_spec = 0; + } + table t { + actions = { + shift; + } + const default_action = shift; + } + apply { + t.apply(); + } +} + +V1Switch(p(), vrfy(), ingress(), egress(), update(), deparser()) main; diff --git a/testdata/p4_16_errors_outputs/issue5094-b-bmv2.p4-stderr b/testdata/p4_16_errors_outputs/issue5094-b-bmv2.p4-stderr new file mode 100644 index 00000000000..d4fc7724193 --- /dev/null +++ b/testdata/p4_16_errors_outputs/issue5094-b-bmv2.p4-stderr @@ -0,0 +1,6 @@ +issue5094-b-bmv2.p4(30): [--Werror=type-error] error: m: The right operand of shifts must be either an expression of type bit or int, but is struct Meta + { h.h.c = (int<64>)(h.h.a << m); sm.egress_spec = 0; } + ^ +arith-skeleton.p4(26) +struct Meta {} + ^^^^