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.
Unified · Split
| @@ -432,6 +432,7 @@ typedef struct TokenSym { · 431 unmodified lines | |||
| 432 | struct Sym *sym_struct; /* direct pointer to structure */ | 432 | struct Sym *sym_struct; /* direct pointer to structure */ |
| 433 | struct Sym *sym_identifier; /* direct pointer to identifier */ | 433 | struct Sym *sym_identifier; /* direct pointer to identifier */ |
| 434 | int tok; /* token number */ | 434 | int tok; /* token number */ |
| 435 | int cnt; | ||
| 435 | int len; | 436 | int len; |
| 436 | char str[1]; | 437 | char str[1]; |
| 437 | } TokenSym; | 438 | } TokenSym; |
| @@ -4321,6 +4321,41 @@ static Sym * find_field (CType *type, int v, int *cumofs) · 4320 unmodified lines | |||
| 4321 | return s; | 4321 | return s; |
| 4322 | } | 4322 | } |
| 4323 | 4323 | ||
| 4324 | /* | ||
| 4325 | * c = 0: reset symbol counter | ||
| 4326 | * c = 1: increment symbol counter | ||
| 4327 | * c = 2: check symbol counter | ||
| 4328 | */ | ||
| 4329 | |||
| 4330 | static void check_fields (CType *type, int c) | ||
| 4331 | { | ||
| 4332 | Sym *s = type->ref; | ||
| 4333 | int v; | ||
| 4334 | |||
| 4335 | while ((s = s->next) != NULL) { | ||
| 4336 | if ((s->v & SYM_FIELD) && | ||
| 4337 | (s->type.t & VT_BTYPE) == VT_STRUCT && | ||
| 4338 | (s->v & ~SYM_FIELD) >= SYM_FIRST_ANOM) { | ||
| 4339 | check_fields (&s->type, c); | ||
| 4340 | } | ||
| 4341 | v = s->v & ~SYM_FIELD; | ||
| 4342 | if (v < tok_ident) | ||
| 4343 | switch (c) { | ||
| 4344 | case 0: | ||
| 4345 | table_ident[v - TOK_IDENT]->cnt = 0; | ||
| 4346 | break; | ||
| 4347 | case 1: | ||
| 4348 | table_ident[v - TOK_IDENT]->cnt++; | ||
| 4349 | break; | ||
| 4350 | case 2: | ||
| 4351 | if (table_ident[v - TOK_IDENT]->cnt != 1) | ||
| 4352 | tcc_error("duplicate member '%s'", | ||
| 4353 | get_tok_str(v, NULL)); | ||
| 4354 | break; | ||
| 4355 | } | ||
| 4356 | } | ||
| 4357 | } | ||
| 4358 | |||
| 4324 | static void struct_layout(CType *type, AttributeDef *ad) | 4359 | static void struct_layout(CType *type, AttributeDef *ad) |
| 4325 | { | 4360 | { |
| 4326 | int size, align, maxalign, offset, c, bit_pos, bit_size; | 4361 | int size, align, maxalign, offset, c, bit_pos, bit_size; |
| @@ -4774,6 +4809,9 @@ do_decl: · 447 unmodified lines | |||
| 4774 | if (ad.cleanup_func) { | 4809 | if (ad.cleanup_func) { |
| 4775 | tcc_warning("attribute '__cleanup__' ignored on type"); | 4810 | tcc_warning("attribute '__cleanup__' ignored on type"); |
| 4776 | } | 4811 | } |
| 4812 | check_fields(type, 0); | ||
| 4813 | check_fields(type, 1); | ||
| 4814 | check_fields(type, 2); | ||
| 4777 | struct_layout(type, &ad); | 4815 | struct_layout(type, &ad); |
| 4778 | } | 4816 | } |
| 4779 | } | 4817 | } |
| @@ -366,4 +366,21 @@ n[sizeof({3;})]; // crashed in block() due to missing local scope · 365 unmodified lines | |||
| 366 | f(){"12"3;} // second const token killed the value of the first | 366 | f(){"12"3;} // second const token killed the value of the first |
| 367 | 367 | ||
| 368 | /******************************************************************/ | 368 | /******************************************************************/ |
| 369 | #elif defined test_duplicate_member | ||
| 370 | struct S { | ||
| 371 | int a, a; | ||
| 372 | }; | ||
| 373 | #elif defined test_duplicate_member_anon | ||
| 374 | struct S1 { | ||
| 375 | int b; | ||
| 376 | struct { | ||
| 377 | int b; | ||
| 378 | } c; | ||
| 379 | }; | ||
| 380 | struct S2 { | ||
| 381 | int d; | ||
| 382 | struct { | ||
| 383 | int d; | ||
| 384 | }; | ||
| 385 | }; | ||
| 369 | #endif | 386 | #endif |
| @@ -174,3 +174,9 @@ bar : 3 ; 3 · 173 unmodified lines | |||
| 174 | 174 | ||
| 175 | [test_invalid_tokckill] | 175 | [test_invalid_tokckill] |
| 176 | 60_errors_and_warnings.c:366: error: ';' expected (got "3") | 176 | 60_errors_and_warnings.c:366: error: ';' expected (got "3") |
| 177 | |||
| 178 | [test_duplicate_member] | ||
| 179 | 60_errors_and_warnings.c:372: error: duplicate member 'a' | ||
| 180 | |||
| 181 | [test_duplicate_member_anon] | ||
| 182 | 60_errors_and_warnings.c:385: error: duplicate member 'd' | ||