parser: disallow duplicate members

Check each constant as it is recognized to ensure its name does not
duplicate an already-defined constant.

Check each message member as it is recognized to ensure its name
does not duplicate an already-defined member.  Also check its id
value to ensure the same value isn't used more than once.

Check each struct member as it is recognized to ensure its name does
not duplicate an already-defined member.

Signed-off-by: Alex Elder <elder@linaro.org>
Message-Id: <20211001232338.769309-27-elder@linaro.org>
Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
This commit is contained in:
Alex Elder 2021-10-01 18:23:30 -05:00 committed by Bjorn Andersson
parent 83931b750f
commit 72d1687658
5 changed files with 113 additions and 0 deletions

View File

@ -329,6 +329,7 @@ static void qmi_package_parse(void)
static void qmi_const_parse()
{
struct qmi_const *qcm;
struct qmi_const *qc;
struct token num_tok;
struct token id_tok;
@ -338,6 +339,10 @@ static void qmi_const_parse()
token_expect(TOK_NUM, &num_tok);
token_expect(';', NULL);
list_for_each_entry(qcm, &qmi_consts, node)
if (!strcmp(qcm->name, id_tok.str))
yyerror("duplicate constant \"%s\"", qcm->name);
qc = memalloc(sizeof(struct qmi_const));
qc->name = id_tok.str;
qc->value = num_tok.num;
@ -395,6 +400,15 @@ static void qmi_message_parse(enum message_type message_type)
token_expect(TOK_NUM, &num_tok);
token_expect(';', NULL);
list_for_each_entry(qmm, &qm->members, node) {
if (!strcmp(qmm->name, id_tok.str))
yyerror("duplicate message member \"%s\"",
qmm->name);
if (qmm->id == type_tok.num)
yyerror("duplicate message member number %u",
qmm->id);
}
qmm = memalloc(sizeof(struct qmi_message_member));
qmm->name = id_tok.str;
qmm->type = type_tok.num;
@ -439,6 +453,11 @@ static void qmi_struct_parse(void)
token_expect(TOK_ID, &id_tok);
token_expect(';', NULL);
list_for_each_entry(qsm, &qs->members, node)
if (!strcmp(qsm->name, id_tok.str))
yyerror("duplicate struct member \"%s\"",
qsm->name);
qsm = memalloc(sizeof(struct qmi_struct_member));
qsm->name = id_tok.str;
qsm->type = type_tok.num;

21
tests/duplicate_const.qmi Normal file
View File

@ -0,0 +1,21 @@
package test;
const TEST_REQUEST_RESPONSE = 35;
const TEST_REQUEST_RESPONSE = 35;
struct qmi_result {
u16 result;
u16 error;
};
request test_request {
required u8 test_number = 0x12;
} = 0x23;
response test_response {
required qmi_result r = 2;
} = 043;
indication test_indication {
optional u64 value = 0x99;
} = 0x7;

View File

@ -0,0 +1,21 @@
package test;
const TEST_REQUEST_RESPONSE = 35;
struct qmi_result {
u16 result;
u16 error;
};
request test_request {
required u8 test_number = 0x12;
required u16 test_number = 0x11;
} = 0x23;
response test_response {
required qmi_result r = 2;
} = 043;
indication test_indication {
optional u64 value = 0x99;
} = 0x7;

View File

@ -0,0 +1,22 @@
package test;
const TEST_REQUEST_RESPONSE = 35;
const TEST_INDICATION = 07;
struct qmi_result {
u16 result;
u16 error;
};
request test_request {
required u8 test_number = 0x1;
optional u16 test_number2 = 0x1;
} = 0x23;
response test_response {
required qmi_result r = 2;
} = 043;
indication test_indication {
optional u64 value = 0x99;
} = 0x7;

View File

@ -0,0 +1,30 @@
package test;
const TEST_REQUEST_RESPONSE = 35;
const TEST_INDICATION = 07;
struct qmi_result {
u16 result;
u16 error;
};
struct test_struct {
u8 test_u8;
u8 test_u8;
u16 test_u16;
u32 test_u32;
u64 test_u64;
};
request test_request {
optional test_struct foo = 0x1;
required u8 test_number = 0x12;
} = 0x23;
response test_response {
required qmi_result r = 2;
} = 043;
indication test_indication {
optional u64 value = 0x99;
} = 0x7;