Skip to content

Commit

Permalink
When errors happen do not bug-check; fixes p4lang#2290
Browse files Browse the repository at this point in the history
  • Loading branch information
Mihai Budiu committed Apr 7, 2020
1 parent 90c7d7d commit 7abd726
Show file tree
Hide file tree
Showing 5 changed files with 142 additions and 9 deletions.
24 changes: 16 additions & 8 deletions frontends/p4/typeChecking/typeChecker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -569,7 +569,7 @@ const IR::Type* TypeInference::canonicalize(const IR::Type* type) {
(void)result->apply(*tc);
return result;
} else {
BUG("Unexpected type %1%", dbp(type));
BUG_CHECK(::errorCount(), "Unexpected type %1%", dbp(type));
}

// If we reach this point some type error must have occurred, because
Expand Down Expand Up @@ -1367,20 +1367,27 @@ const IR::Node* TypeInference::postorder(IR::Type_Stack* type) {
return type;
}

void TypeInference::validateFields(const IR::Type* type,
/// Validate the fields of a struct type using the supplied checker.
/// The checker returns "false" when a field is invalid.
/// Return true on success
bool TypeInference::validateFields(const IR::Type* type,
std::function<bool(const IR::Type*)> checker) const {
if (type == nullptr)
return;
return false;
BUG_CHECK(type->is<IR::Type_StructLike>(), "%1%; expected a Struct-like", type);
auto strct = type->to<IR::Type_StructLike>();
bool err = false;
for (auto field : strct->fields) {
auto ftype = getType(field);
if (ftype == nullptr)
return;
if (!checker(ftype))
return false;
if (!checker(ftype)) {
typeError("Field %1% of %2% cannot have type %3%",
field, type->toString(), field->type);
err = true;
}
}
return !err;
}

const IR::Node* TypeInference::postorder(IR::StructField* field) {
Expand All @@ -1404,7 +1411,8 @@ const IR::Node* TypeInference::postorder(IR::Type_Header* type) {
// Experimental feature - see Issue 383.
(t->is<IR::Type_Struct>() && onlyBitsOrBitStructs(t)) ||
t->is<IR::Type_SerEnum>() || t->is<IR::Type_Boolean>(); };
validateFields(canon, validator);
if (!validateFields(canon, validator))
return type;

const IR::StructField* varbit = nullptr;
for (auto field : type->fields) {
Expand Down Expand Up @@ -1435,14 +1443,14 @@ const IR::Node* TypeInference::postorder(IR::Type_Struct* type) {
t->is<IR::Type_Boolean>() || t->is<IR::Type_Stack>() ||
t->is<IR::Type_Varbits>() || t->is<IR::Type_ActionEnum>() ||
t->is<IR::Type_Tuple>() || t->is<IR::Type_SerEnum>(); };
validateFields(canon, validator);
(void)validateFields(canon, validator);
return type;
}

const IR::Node* TypeInference::postorder(IR::Type_HeaderUnion *type) {
auto canon = setTypeType(type);
auto validator = [] (const IR::Type* t) { return t->is<IR::Type_Header>(); };
validateFields(canon, validator);
(void)validateFields(canon, validator);
return type;
}

Expand Down
2 changes: 1 addition & 1 deletion frontends/p4/typeChecking/typeChecker.h
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ class TypeInference : public Transform {
void checkCorelibMethods(const ExternMethod* em) const;
void checkEmitType(const IR::Expression* emit, const IR::Type* type) const;
bool containsHeader(const IR::Type* canonType);
void validateFields(const IR::Type* type,
bool validateFields(const IR::Type* type,
std::function<bool(const IR::Type*)> checker) const;
const IR::Node* binaryBool(const IR::Operation_Binary* op);
const IR::Node* binaryArith(const IR::Operation_Binary* op);
Expand Down
53 changes: 53 additions & 0 deletions testdata/p4_16_errors/issue2290.p4
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
#include <core.p4>
#include <v1model.p4>

header ethernet_t {
bit<48> dst_addr;
bit<48> src_addr;
bit<16> eth_type;
}


header simple_header {
bit<8> a;
}

header nested_header {
simple_header s;
}

struct Headers {
ethernet_t eth_hdr;
nested_header n;
}

struct Meta {
}


parser p(packet_in pkt, out Headers hdr, inout Meta m, inout standard_metadata_t sm) {
state start {
transition parse_hdrs;
}
state parse_hdrs {
pkt.extract(hdr.eth_hdr);
transition accept;
}
}

control ingress(inout Headers h, inout Meta m, inout standard_metadata_t sm) {

apply {

}
}

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);} }

V1Switch(p(), vrfy(), ingress(), egress(), update(), deparser()) main;
63 changes: 63 additions & 0 deletions testdata/p4_16_errors_outputs/issue2290.p4
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
#include <core.p4>
#include <v1model.p4>

header ethernet_t {
bit<48> dst_addr;
bit<48> src_addr;
bit<16> eth_type;
}

header simple_header {
bit<8> a;
}

header nested_header {
simple_header s;
}

struct Headers {
ethernet_t eth_hdr;
nested_header n;
}

struct Meta {
}

parser p(packet_in pkt, out Headers hdr, inout Meta m, inout standard_metadata_t sm) {
state start {
transition parse_hdrs;
}
state parse_hdrs {
pkt.extract(hdr.eth_hdr);
transition accept;
}
}

control ingress(inout Headers h, inout Meta m, inout standard_metadata_t sm) {
apply {
}
}

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);
}
}

V1Switch(p(), vrfy(), ingress(), egress(), update(), deparser()) main;

9 changes: 9 additions & 0 deletions testdata/p4_16_errors_outputs/issue2290.p4-stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
issue2290.p4(16): [--Werror=type-error] error: Field s of header nested_header cannot have type header simple_header
simple_header s;
^
issue2290.p4(11)
header simple_header {
^^^^^^^^^^^^^
issue2290.p4(53): [--Werror=type-error] error: p: cannot evaluate to a compile-time constant
V1Switch(p(), vrfy(), ingress(), egress(), update(), deparser()) main;
^^^

0 comments on commit 7abd726

Please sign in to comment.