diff --git a/frontends/p4/typeChecking/typeCheckStmt.cpp b/frontends/p4/typeChecking/typeCheckStmt.cpp index 7b03593c27..66e250b95e 100644 --- a/frontends/p4/typeChecking/typeCheckStmt.cpp +++ b/frontends/p4/typeChecking/typeCheckStmt.cpp @@ -48,6 +48,14 @@ const IR::Node *TypeInferenceBase::postorder(const IR::SwitchStatement *stat) { } } else { // switch (expression) + if (!(type->is() || type->is() || + type->is() || type->is() || + type->is())) { + typeError("%1%: switch expression cannot be of type %2%", stat->expression, + type->toString()); + return stat; + } + Comparison comp; comp.left = stat->expression; diff --git a/testdata/p4_16_errors/issue5120.p4 b/testdata/p4_16_errors/issue5120.p4 new file mode 100644 index 0000000000..32fba70f32 --- /dev/null +++ b/testdata/p4_16_errors/issue5120.p4 @@ -0,0 +1,43 @@ +@command_line("--preferSwitch") + +extern void __e(in bit<28> arg); +extern void __e2(in bit<28> arg); + +control C() { + action bar(bool a, bool b) { + bit<28> x; bit<28> y; + switch (a) { + b: { + __e(x); + } + default: { + if (b) { + __e2(y); + } + } + } + } + + action baz() { + bar(true, false); + } + + action foo() { + baz(); + + } + + table t { + actions = { foo; } + default_action = foo; + } + + apply { + t.apply(); + } +} + +control proto(); +package top(proto p); + +top(C()) main; diff --git a/testdata/p4_16_errors/issue5313_type_variable.p4 b/testdata/p4_16_errors/issue5313_type_variable.p4 new file mode 100644 index 0000000000..c6792731a0 --- /dev/null +++ b/testdata/p4_16_errors/issue5313_type_variable.p4 @@ -0,0 +1,32 @@ +@command_line("--preferSwitch") + +// Generic helper over a type variable T. +// The switch is written in terms of T; T is instantiated later. +void bar_generic(T v, out bit<8> y) { + switch (v) { + 0b01: { y = 1; } + 0b10: { y = 2; } + default: { y = 0; } + } +} + +control C(out bit<8> y) { + action foo() { + // Here T is instantiated as bit<2>, so switch(v) is on bit<2>. + bar_generic>(1, y); + } + + table t { + actions = { foo; } + default_action = foo; + } + + apply { + t.apply(); + } +} + +control proto(out bit<8> y); +package top(proto p); + +top(C()) main; diff --git a/testdata/p4_16_errors/issue5313_typealiass.p4 b/testdata/p4_16_errors/issue5313_typealiass.p4 new file mode 100644 index 0000000000..fa1b2c361e --- /dev/null +++ b/testdata/p4_16_errors/issue5313_typealiass.p4 @@ -0,0 +1,32 @@ +@command_line("--preferSwitch") + +type bit<2> TwoBitsAlias; + +void bar(bit<2> x, out bit<8> y) { + TwoBitsAlias a = (TwoBitsAlias)x; + switch (a) { + 0b01: { y = 4; } + 0b10: { y = 5; } + default: { y = y; } + } +} + +control C(out bit<8> y) { + action foo() { + bar(1, y); + } + + table t { + actions = { foo; } + default_action = foo; + } + + apply { + t.apply(); + } +} + +control proto(out bit<8> y); +package top(proto p); + +top(C()) main; diff --git a/testdata/p4_16_errors_outputs/issue5120.p4 b/testdata/p4_16_errors_outputs/issue5120.p4 new file mode 100644 index 0000000000..719f8ac58c --- /dev/null +++ b/testdata/p4_16_errors_outputs/issue5120.p4 @@ -0,0 +1,37 @@ +@command_line("--preferSwitch") extern void __e(in bit<28> arg); +extern void __e2(in bit<28> arg); +control C() { + action bar(bool a, bool b) { + bit<28> x; + bit<28> y; + switch (a) { + b: { + __e(x); + } + default: { + if (b) { + __e2(y); + } + } + } + } + action baz() { + bar(true, false); + } + action foo() { + baz(); + } + table t { + actions = { + foo; + } + default_action = foo; + } + apply { + t.apply(); + } +} + +control proto(); +package top(proto p); +top(C()) main; diff --git a/testdata/p4_16_errors_outputs/issue5120.p4-stderr b/testdata/p4_16_errors_outputs/issue5120.p4-stderr new file mode 100644 index 0000000000..4d4b6318fe --- /dev/null +++ b/testdata/p4_16_errors_outputs/issue5120.p4-stderr @@ -0,0 +1,3 @@ +issue5120.p4(9): [--Werror=type-error] error: a: switch expression cannot be of type bool + switch (a) { + ^ diff --git a/testdata/p4_16_errors_outputs/issue5313_type_variable.p4 b/testdata/p4_16_errors_outputs/issue5313_type_variable.p4 new file mode 100644 index 0000000000..1a4467434d --- /dev/null +++ b/testdata/p4_16_errors_outputs/issue5313_type_variable.p4 @@ -0,0 +1,31 @@ +@command_line("--preferSwitch") void bar_generic(T v, out bit<8> y) { + switch (v) { + 0b1: { + y = 1; + } + 0b10: { + y = 2; + } + default: { + y = 0; + } + } +} +control C(out bit<8> y) { + action foo() { + bar_generic>(1, y); + } + table t { + actions = { + foo; + } + default_action = foo; + } + apply { + t.apply(); + } +} + +control proto(out bit<8> y); +package top(proto p); +top(C()) main; diff --git a/testdata/p4_16_errors_outputs/issue5313_type_variable.p4-stderr b/testdata/p4_16_errors_outputs/issue5313_type_variable.p4-stderr new file mode 100644 index 0000000000..18434554a6 --- /dev/null +++ b/testdata/p4_16_errors_outputs/issue5313_type_variable.p4-stderr @@ -0,0 +1,3 @@ +issue5313_type_variable.p4(6): [--Werror=type-error] error: v: switch expression cannot be of type T + switch (v) { + ^ diff --git a/testdata/p4_16_errors_outputs/issue5313_typealiass.p4 b/testdata/p4_16_errors_outputs/issue5313_typealiass.p4 new file mode 100644 index 0000000000..618f939705 --- /dev/null +++ b/testdata/p4_16_errors_outputs/issue5313_typealiass.p4 @@ -0,0 +1,33 @@ +@command_line("--preferSwitch") type bit<2> TwoBitsAlias; +void bar(bit<2> x, out bit<8> y) { + TwoBitsAlias a = (TwoBitsAlias)x; + switch (a) { + 0b1: { + y = 4; + } + 0b10: { + y = 5; + } + default: { + y = y; + } + } +} +control C(out bit<8> y) { + action foo() { + bar(1, y); + } + table t { + actions = { + foo; + } + default_action = foo; + } + apply { + t.apply(); + } +} + +control proto(out bit<8> y); +package top(proto p); +top(C()) main; diff --git a/testdata/p4_16_errors_outputs/issue5313_typealiass.p4-stderr b/testdata/p4_16_errors_outputs/issue5313_typealiass.p4-stderr new file mode 100644 index 0000000000..1329a8ec73 --- /dev/null +++ b/testdata/p4_16_errors_outputs/issue5313_typealiass.p4-stderr @@ -0,0 +1,3 @@ +issue5313_typealiass.p4(7): [--Werror=type-error] error: a: switch expression cannot be of type TwoBitsAlias + switch (a) { + ^ diff --git a/testdata/p4_16_errors_outputs/stmt-switch-on-unsupported-type.p4-stderr b/testdata/p4_16_errors_outputs/stmt-switch-on-unsupported-type.p4-stderr index e3182dd62c..be1fcf5ff3 100644 --- a/testdata/p4_16_errors_outputs/stmt-switch-on-unsupported-type.p4-stderr +++ b/testdata/p4_16_errors_outputs/stmt-switch-on-unsupported-type.p4-stderr @@ -1,6 +1,6 @@ stmt-switch-on-unsupported-type.p4(3): [--Wwarn=unused] warning: control 'ctrl' is unused control ctrl()() { ^^^^ -stmt-switch-on-unsupported-type.p4(5): [--Werror=type-error] error: ...: could not find default value +stmt-switch-on-unsupported-type.p4(5): [--Werror=type-error] error: ...: switch expression cannot be of type ANYTYPE switch (...) { } ^^^ diff --git a/testdata/p4_16_samples/issue5313.p4 b/testdata/p4_16_samples/issue5313.p4 new file mode 100644 index 0000000000..88610c2ed9 --- /dev/null +++ b/testdata/p4_16_samples/issue5313.p4 @@ -0,0 +1,28 @@ +@command_line("--preferSwitch") + +void bar(bit<2> x, out bit<8> y) { + switch (x) { + 0b01: { y = 2; } + 0b10: { y = 3; } + } +} + +control C(out bit<8> y) { + action foo() { + bar(1, y); + } + + table t { + actions = { foo; } + default_action = foo; + } + + apply { + t.apply(); + } +} + +control proto(out bit<8> y); +package top(proto p); + +top(C()) main; diff --git a/testdata/p4_16_samples/issue5313_aliass.p4 b/testdata/p4_16_samples/issue5313_aliass.p4 new file mode 100644 index 0000000000..984bdecc12 --- /dev/null +++ b/testdata/p4_16_samples/issue5313_aliass.p4 @@ -0,0 +1,30 @@ +@command_line("--preferSwitch") + +typedef bit<2> TwoBits; + +void bar(TwoBits x, out bit<8> y) { + switch (x) { + 0b01: { y = 2; } + 0b10: { y = 3; } + } +} + +control C(out bit<8> y) { + action foo() { + bar(1, y); + } + + table t { + actions = { foo; } + default_action = foo; + } + + apply { + t.apply(); + } +} + +control proto(out bit<8> y); +package top(proto p); + +top(C()) main; diff --git a/testdata/p4_16_samples_outputs/issue5313-first.p4 b/testdata/p4_16_samples_outputs/issue5313-first.p4 new file mode 100644 index 0000000000..3bcd772b0a --- /dev/null +++ b/testdata/p4_16_samples_outputs/issue5313-first.p4 @@ -0,0 +1,28 @@ +@command_line("--preferSwitch") void bar(bit<2> x, out bit<8> y) { + switch (x) { + 2w0b1: { + y = 8w2; + } + 2w0b10: { + y = 8w3; + } + } +} +control C(out bit<8> y) { + action foo() { + bar(2w1, y); + } + table t { + actions = { + foo(); + } + default_action = foo(); + } + apply { + t.apply(); + } +} + +control proto(out bit<8> y); +package top(proto p); +top(C()) main; diff --git a/testdata/p4_16_samples_outputs/issue5313-frontend.p4 b/testdata/p4_16_samples_outputs/issue5313-frontend.p4 new file mode 100644 index 0000000000..6a74e42b49 --- /dev/null +++ b/testdata/p4_16_samples_outputs/issue5313-frontend.p4 @@ -0,0 +1,27 @@ +control C(out bit<8> y) { + @name("C.y_0") bit<8> y_1; + @name("C.foo") action foo() { + switch (2w1) { + 2w0b1: { + y_1 = 8w2; + } + 2w0b10: { + y_1 = 8w3; + } + } + y = y_1; + } + @name("C.t") table t_0 { + actions = { + foo(); + } + default_action = foo(); + } + apply { + t_0.apply(); + } +} + +control proto(out bit<8> y); +package top(proto p); +top(C()) main; diff --git a/testdata/p4_16_samples_outputs/issue5313-midend.p4 b/testdata/p4_16_samples_outputs/issue5313-midend.p4 new file mode 100644 index 0000000000..6a74e42b49 --- /dev/null +++ b/testdata/p4_16_samples_outputs/issue5313-midend.p4 @@ -0,0 +1,27 @@ +control C(out bit<8> y) { + @name("C.y_0") bit<8> y_1; + @name("C.foo") action foo() { + switch (2w1) { + 2w0b1: { + y_1 = 8w2; + } + 2w0b10: { + y_1 = 8w3; + } + } + y = y_1; + } + @name("C.t") table t_0 { + actions = { + foo(); + } + default_action = foo(); + } + apply { + t_0.apply(); + } +} + +control proto(out bit<8> y); +package top(proto p); +top(C()) main; diff --git a/testdata/p4_16_samples_outputs/issue5313.p4 b/testdata/p4_16_samples_outputs/issue5313.p4 new file mode 100644 index 0000000000..11bdf8fc5c --- /dev/null +++ b/testdata/p4_16_samples_outputs/issue5313.p4 @@ -0,0 +1,28 @@ +@command_line("--preferSwitch") void bar(bit<2> x, out bit<8> y) { + switch (x) { + 0b1: { + y = 2; + } + 0b10: { + y = 3; + } + } +} +control C(out bit<8> y) { + action foo() { + bar(1, y); + } + table t { + actions = { + foo; + } + default_action = foo; + } + apply { + t.apply(); + } +} + +control proto(out bit<8> y); +package top(proto p); +top(C()) main; diff --git a/testdata/p4_16_samples_outputs/issue5313.p4-stderr b/testdata/p4_16_samples_outputs/issue5313.p4-stderr new file mode 100644 index 0000000000..e87d5aafeb --- /dev/null +++ b/testdata/p4_16_samples_outputs/issue5313.p4-stderr @@ -0,0 +1,7 @@ +issue5313.p4(3): [--Wwarn=uninitialized-out-param] warning: out parameter 'y' may be uninitialized when 'bar' terminates +void bar(bit<2> x, out bit<8> y) { + ^ +issue5313.p4(3) +void bar(bit<2> x, out bit<8> y) { + ^^^ +[--Wwarn=uninitialized-use] warning: y_0 may be uninitialized diff --git a/testdata/p4_16_samples_outputs/issue5313_aliass-first.p4 b/testdata/p4_16_samples_outputs/issue5313_aliass-first.p4 new file mode 100644 index 0000000000..8f274c4446 --- /dev/null +++ b/testdata/p4_16_samples_outputs/issue5313_aliass-first.p4 @@ -0,0 +1,29 @@ +@command_line("--preferSwitch") typedef bit<2> TwoBits; +void bar(TwoBits x, out bit<8> y) { + switch (x) { + 2w0b1: { + y = 8w2; + } + 2w0b10: { + y = 8w3; + } + } +} +control C(out bit<8> y) { + action foo() { + bar(2w1, y); + } + table t { + actions = { + foo(); + } + default_action = foo(); + } + apply { + t.apply(); + } +} + +control proto(out bit<8> y); +package top(proto p); +top(C()) main; diff --git a/testdata/p4_16_samples_outputs/issue5313_aliass-frontend.p4 b/testdata/p4_16_samples_outputs/issue5313_aliass-frontend.p4 new file mode 100644 index 0000000000..6a74e42b49 --- /dev/null +++ b/testdata/p4_16_samples_outputs/issue5313_aliass-frontend.p4 @@ -0,0 +1,27 @@ +control C(out bit<8> y) { + @name("C.y_0") bit<8> y_1; + @name("C.foo") action foo() { + switch (2w1) { + 2w0b1: { + y_1 = 8w2; + } + 2w0b10: { + y_1 = 8w3; + } + } + y = y_1; + } + @name("C.t") table t_0 { + actions = { + foo(); + } + default_action = foo(); + } + apply { + t_0.apply(); + } +} + +control proto(out bit<8> y); +package top(proto p); +top(C()) main; diff --git a/testdata/p4_16_samples_outputs/issue5313_aliass-midend.p4 b/testdata/p4_16_samples_outputs/issue5313_aliass-midend.p4 new file mode 100644 index 0000000000..6a74e42b49 --- /dev/null +++ b/testdata/p4_16_samples_outputs/issue5313_aliass-midend.p4 @@ -0,0 +1,27 @@ +control C(out bit<8> y) { + @name("C.y_0") bit<8> y_1; + @name("C.foo") action foo() { + switch (2w1) { + 2w0b1: { + y_1 = 8w2; + } + 2w0b10: { + y_1 = 8w3; + } + } + y = y_1; + } + @name("C.t") table t_0 { + actions = { + foo(); + } + default_action = foo(); + } + apply { + t_0.apply(); + } +} + +control proto(out bit<8> y); +package top(proto p); +top(C()) main; diff --git a/testdata/p4_16_samples_outputs/issue5313_aliass.p4 b/testdata/p4_16_samples_outputs/issue5313_aliass.p4 new file mode 100644 index 0000000000..70e3ebb0b2 --- /dev/null +++ b/testdata/p4_16_samples_outputs/issue5313_aliass.p4 @@ -0,0 +1,29 @@ +@command_line("--preferSwitch") typedef bit<2> TwoBits; +void bar(TwoBits x, out bit<8> y) { + switch (x) { + 0b1: { + y = 2; + } + 0b10: { + y = 3; + } + } +} +control C(out bit<8> y) { + action foo() { + bar(1, y); + } + table t { + actions = { + foo; + } + default_action = foo; + } + apply { + t.apply(); + } +} + +control proto(out bit<8> y); +package top(proto p); +top(C()) main; diff --git a/testdata/p4_16_samples_outputs/issue5313_aliass.p4-stderr b/testdata/p4_16_samples_outputs/issue5313_aliass.p4-stderr new file mode 100644 index 0000000000..9950c86088 --- /dev/null +++ b/testdata/p4_16_samples_outputs/issue5313_aliass.p4-stderr @@ -0,0 +1,7 @@ +issue5313_aliass.p4(5): [--Wwarn=uninitialized-out-param] warning: out parameter 'y' may be uninitialized when 'bar' terminates +void bar(TwoBits x, out bit<8> y) { + ^ +issue5313_aliass.p4(5) +void bar(TwoBits x, out bit<8> y) { + ^^^ +[--Wwarn=uninitialized-use] warning: y_0 may be uninitialized