Skip to content

Commit 98004a6

Browse files
Fix typedef/variable name conflict: add declarator_init_start rule to register identifier before parsing initializer
Co-authored-by: michael-schwarz <13812333+michael-schwarz@users.noreply.github.com>
1 parent 3494d12 commit 98004a6

3 files changed

Lines changed: 36 additions & 3 deletions

File tree

src/frontc/cparser.mly

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -388,7 +388,7 @@ let transformOffsetOf (speclist, dtype) member =
388388

389389
%type <Cabs.init_name> init_declarator
390390
%type <Cabs.init_name list> init_declarator_list
391-
%type <Cabs.name> declarator
391+
%type <Cabs.name> declarator declarator_init_start
392392
%type <Cabs.name * expression option> field_decl
393393
%type <(Cabs.name * expression option) list> field_decl_list
394394
%type <string * Cabs.decl_type> direct_decl
@@ -1037,8 +1037,15 @@ init_declarator_attr:
10371037
;
10381038
init_declarator: /* ISO 6.7 */
10391039
declarator { ($1, NO_INIT) }
1040-
| declarator EQ init_expression location
1041-
{ let (n, d, a, l) = $1 in ((n, d, a, joinLoc l $4), $3) }
1040+
| declarator_init_start init_expression location
1041+
{ let (n, d, a, l) = $1 in ((n, d, a, joinLoc l $3), $2) }
1042+
;
1043+
1044+
(* Parses "declarator =" and adds the declared name as a variable identifier
1045+
in the lexer hack, so that in the initializer the name shadows any typedef
1046+
with the same name (C11 6.2.1.7: scope begins after completion of declarator). *)
1047+
declarator_init_start:
1048+
declarator EQ { let (n, _, _, _) = $1 in !Lexerhack.add_identifier n; $1 }
10421049
;
10431050

10441051
decl_spec_list_common: /* ISO 6.7 */

test/small1/typedef_varname.c

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/* Test for typedef and variable name conflict (issue #114).
2+
A variable with the same name as a typedef should shadow it in its initializer,
3+
per C11 6.2.1.7: "Any other identifier has scope that begins just after the
4+
completion of its declarator." */
5+
#include <stdint.h>
6+
#include <stdlib.h>
7+
8+
typedef struct raxNode {
9+
uint32_t iskey:1;
10+
uint32_t isnull:1;
11+
uint32_t iscompr:1;
12+
uint32_t size:29;
13+
unsigned char data[];
14+
} raxNode;
15+
16+
typedef struct rax {
17+
raxNode *head;
18+
uint64_t numele;
19+
uint64_t numnodes;
20+
} rax;
21+
22+
int main() {
23+
rax *rax = malloc(sizeof(*rax)); /* variable rax shadows typedef rax in initializer */
24+
return rax == 0;
25+
}

test/testcil.pl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -471,6 +471,7 @@ sub addToGroup {
471471
addTest("testrun/for1 ");
472472
addTest("testrun/void _GNUCC=1");
473473
addTest("test/voidtypedef ");
474+
addTest("testrun/typedef_varname ");
474475
addTest("testrun/wrongnumargs ");
475476
addBadComment("testrun/wrongnumargs",
476477
"Notbug. Should fail since we don't pad argument lists");

0 commit comments

Comments
 (0)