duplicate member

Check duplicate struct/union member names

tcc.h: Add cnt field in TokenSym

tccgen.c: New function check_fields to find duplicate member names.

This avoids quadratic behavior and can be used for large structs.
This commit is contained in:
herman ten brugge 2020-12-03 07:53:44 +01:00
parent 6f2659c230
commit 170be79a42
4 changed files with 62 additions and 0 deletions

1
tcc.h
View file

@ -432,6 +432,7 @@ typedef struct TokenSym {
struct Sym *sym_struct; /* direct pointer to structure */ struct Sym *sym_struct; /* direct pointer to structure */
struct Sym *sym_identifier; /* direct pointer to identifier */ struct Sym *sym_identifier; /* direct pointer to identifier */
int tok; /* token number */ int tok; /* token number */
int cnt;
int len; int len;
char str[1]; char str[1];
} TokenSym; } TokenSym;

View file

@ -4321,6 +4321,41 @@ static Sym * find_field (CType *type, int v, int *cumofs)
return s; return s;
} }
/*
* c = 0: reset symbol counter
* c = 1: increment symbol counter
* c = 2: check symbol counter
*/
static void check_fields (CType *type, int c)
{
Sym *s = type->ref;
int v;
while ((s = s->next) != NULL) {
if ((s->v & SYM_FIELD) &&
(s->type.t & VT_BTYPE) == VT_STRUCT &&
(s->v & ~SYM_FIELD) >= SYM_FIRST_ANOM) {
check_fields (&s->type, c);
}
v = s->v & ~SYM_FIELD;
if (v < tok_ident)
switch (c) {
case 0:
table_ident[v - TOK_IDENT]->cnt = 0;
break;
case 1:
table_ident[v - TOK_IDENT]->cnt++;
break;
case 2:
if (table_ident[v - TOK_IDENT]->cnt != 1)
tcc_error("duplicate member '%s'",
get_tok_str(v, NULL));
break;
}
}
}
static void struct_layout(CType *type, AttributeDef *ad) static void struct_layout(CType *type, AttributeDef *ad)
{ {
int size, align, maxalign, offset, c, bit_pos, bit_size; int size, align, maxalign, offset, c, bit_pos, bit_size;
@ -4774,6 +4809,9 @@ do_decl:
if (ad.cleanup_func) { if (ad.cleanup_func) {
tcc_warning("attribute '__cleanup__' ignored on type"); tcc_warning("attribute '__cleanup__' ignored on type");
} }
check_fields(type, 0);
check_fields(type, 1);
check_fields(type, 2);
struct_layout(type, &ad); struct_layout(type, &ad);
} }
} }

View file

@ -366,4 +366,21 @@ n[sizeof({3;})]; // crashed in block() due to missing local scope
f(){"12"3;} // second const token killed the value of the first f(){"12"3;} // second const token killed the value of the first
/******************************************************************/ /******************************************************************/
#elif defined test_duplicate_member
struct S {
int a, a;
};
#elif defined test_duplicate_member_anon
struct S1 {
int b;
struct {
int b;
} c;
};
struct S2 {
int d;
struct {
int d;
};
};
#endif #endif

View file

@ -174,3 +174,9 @@ bar : 3 ; 3
[test_invalid_tokckill] [test_invalid_tokckill]
60_errors_and_warnings.c:366: error: ';' expected (got "3") 60_errors_and_warnings.c:366: error: ';' expected (got "3")
[test_duplicate_member]
60_errors_and_warnings.c:372: error: duplicate member 'a'
[test_duplicate_member_anon]
60_errors_and_warnings.c:385: error: duplicate member 'd'