Skip to content

Commit f16d416

Browse files
authored
Reject duplicate match_kind declarations (#5656)
Signed-off-by: aeron-gh <agab0323@gmail.com>
1 parent d7b2576 commit f16d416

30 files changed

Lines changed: 163 additions & 87 deletions

frontends/p4/toP4/toP4.cpp

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -152,8 +152,9 @@ bool ToP4::preorder(const IR::P4Program *program) {
152152
for (auto a : program->objects) {
153153
// Check where this declaration originates
154154
auto sourceFileOpt = ifSystemFile(a);
155-
// Errors can come from multiple files
156-
if (!a->is<IR::Type_Error>() && sourceFileOpt.has_value()) {
155+
// Errors and match_kinds can come from multiple files
156+
if (!a->is<IR::Type_Error>() && !a->is<IR::Declaration_MatchKind>() &&
157+
sourceFileOpt.has_value()) {
157158
/* FIXME -- when including a user header file (sourceFile !=
158159
* mainFile), do we want to emit an #include of it or not? Probably
159160
* not when translating from P4-14, as that would create a P4-16
@@ -692,10 +693,19 @@ bool ToP4::preorder(const IR::Type_Error *d) {
692693

693694
bool ToP4::preorder(const IR::Declaration_MatchKind *d) {
694695
dump(1);
696+
697+
const auto userMatchKinds = d->getDeclarations()
698+
->where([this](const IR::IDeclaration *e) {
699+
// only print if not from a system file
700+
return !ifSystemFile(e->getNode()).has_value();
701+
})
702+
->toVector();
703+
if (userMatchKinds.empty()) return false;
704+
695705
builder.append("match_kind ");
696706
builder.blockStart();
697707
bool first = true;
698-
for (auto a : *d->getDeclarations()) {
708+
for (auto a : userMatchKinds) {
699709
if (!first) builder.append(",\n");
700710
dump(1, a->getNode(), 1);
701711
first = false;

frontends/parsers/p4/p4parser.ypp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -315,8 +315,9 @@ using namespace P4;
315315
parserDeclaration controlDeclaration enumDeclaration
316316
typedefDeclaration packageTypeDeclaration typeDeclaration
317317
%type<IR::Type_Error*> errorDeclaration
318+
%type<IR::Declaration_MatchKind*> matchKindDeclaration
318319
%type<IR::Node*> fragment
319-
%type<IR::Node*> declaration externDeclaration matchKindDeclaration
320+
%type<IR::Node*> declaration externDeclaration
320321
%type<IR::Type_Parser*> parserTypeDeclaration
321322
%type<IR::Type_Control*> controlTypeDeclaration
322323
%type<IR::IndexedVector<IR::Declaration>> parserLocalElements controlLocalDeclarations
@@ -493,7 +494,7 @@ declaration
493494
| controlDeclaration { $$ = $1; }
494495
| instantiation { $$ = $1; }
495496
| errorDeclaration { $$ = driver.onReadErrorDeclaration($1) ? $1 : nullptr; }
496-
| matchKindDeclaration { $$ = $1; }
497+
| matchKindDeclaration { $$ = driver.onReadMatchKindDeclaration($1) ? $1 : nullptr; }
497498
| functionDeclaration { $$ = $1; }
498499
;
499500

frontends/parsers/parserDriver.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -306,6 +306,15 @@ bool P4ParserDriver::onReadErrorDeclaration(IR::Type_Error *error) {
306306
return false;
307307
}
308308

309+
bool P4ParserDriver::onReadMatchKindDeclaration(IR::Declaration_MatchKind *matchKind) {
310+
if (allMatchKinds == nullptr) {
311+
allMatchKinds = matchKind;
312+
return true;
313+
}
314+
allMatchKinds->members.append(matchKind->members);
315+
return false;
316+
}
317+
309318
} // namespace P4
310319

311320
namespace P4::V1 {

frontends/parsers/parserDriver.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,11 @@ class P4ParserDriver final : public AbstractParserDriver {
183183
// been combined into a previous one (and should be elided)
184184
bool onReadErrorDeclaration(IR::Type_Error *error);
185185

186+
/// Notify that the parser parsed a P4 `match_kind` declaration.
187+
// @return true if this is the first match_kind declaration, false if it has
188+
// been combined into a previous one (and should be elided)
189+
bool onReadMatchKindDeclaration(IR::Declaration_MatchKind *matchKind);
190+
186191
////////////////////////////////////////////////////////////////////////////
187192
// Shared state manipulated directly by the lexer and parser.
188193
////////////////////////////////////////////////////////////////////////////
@@ -217,6 +222,11 @@ class P4ParserDriver final : public AbstractParserDriver {
217222
/// lazily created the first time we see an `error` declaration. (This node
218223
/// is present in @declarations as well.)
219224
IR::Type_Error *allErrors = nullptr;
225+
226+
/// All P4 `match_kind` declarations are merged together in the node, which
227+
/// is lazily created the first time we see a `match_kind` declaration. (This
228+
/// node is present in @declarations as well.)
229+
IR::Declaration_MatchKind *allMatchKinds = nullptr;
220230
};
221231

222232
} // namespace P4

testdata/p4_16_errors/issue5085.p4

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// It is an error to declare the same match_kind identifier multiple times,
2+
// even when the duplicates appear in separate match_kind declarations.
3+
// See https://github.com/p4lang/p4c/issues/5085
4+
5+
match_kind {
6+
foo,
7+
bar
8+
}
9+
10+
match_kind {
11+
foo
12+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
issue5085.p4(11): [--Werror=duplicate] error: foo: Duplicates declaration foo
2+
foo
3+
^^^
4+
issue5085.p4(6)
5+
foo,
6+
^^^
7+
[--Werror=overlimit] error: 1 errors encountered, aborting compilation
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// User-defined match_kind identifiers spread across several declarations are
2+
// merged into a single match_kind node. ToP4 prints them together in one block
3+
// after the core.p4 include, dropping the match_kinds already defined there.
4+
// See https://github.com/p4lang/p4c/issues/5085
5+
6+
#include <core.p4>
7+
8+
match_kind {
9+
first_kind,
10+
second_kind
11+
}
12+
13+
match_kind {
14+
third_kind
15+
}

testdata/p4_16_samples/pipe.p4

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,6 @@
77

88
#include <core.p4>
99

10-
match_kind {
11-
ternary,
12-
exact
13-
}
14-
1510
typedef bit<9> BParamType;
1611
struct TArg1 {
1712
bit<9> field1;

testdata/p4_16_samples_outputs/dash/dash-pipeline-pna-dpdk-first.p4

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,11 @@ error {
44
InvalidIPv4Header
55
}
66
#include <core.p4>
7+
8+
match_kind {
9+
list,
10+
range_list
11+
}
712
#include <pna.p4>
813

914
typedef bit<48> EthernetAddress;
@@ -483,11 +488,6 @@ action tunnel_decap(inout headers_t hdr, inout metadata_t meta) {
483488
hdr.u0_udp.setInvalid();
484489
meta.tunnel_pointer = 16w0;
485490
}
486-
match_kind {
487-
list,
488-
range_list
489-
}
490-
491491
control acl(inout headers_t hdr, inout metadata_t meta) {
492492
action permit() {
493493
}

testdata/p4_16_samples_outputs/dash/dash-pipeline-pna-dpdk-frontend.p4

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,11 @@ error {
44
InvalidIPv4Header
55
}
66
#include <core.p4>
7+
8+
match_kind {
9+
list,
10+
range_list
11+
}
712
#include <pna.p4>
813

914
typedef bit<48> EthernetAddress;
@@ -313,11 +318,6 @@ control dash_deparser(packet_out packet, in headers_t hdr, in metadata_t meta, i
313318
}
314319
}
315320

316-
match_kind {
317-
list,
318-
range_list
319-
}
320-
321321
control dash_ingress(inout headers_t hdr, inout metadata_t meta, in pna_main_input_metadata_t istd, inout pna_main_output_metadata_t ostd) {
322322
@name("dash_ingress.meta") metadata_t meta_0;
323323
@name("dash_ingress.meta") metadata_t meta_5;

0 commit comments

Comments
 (0)