On Tue, Apr 26, 2016 at 11:44:52AM +0000, Joseph Myers wrote: > On Tue, 26 Apr 2016, Marek Polacek wrote: > > > This PR was reopened, because the exact same problem with treating a > > TYPENAME > > wrongly as an ID was found when using just if-clause, without an enclosing > > for > > loop. More details: > > <https://gcc.gnu.org/ml/gcc-patches/2015-11/msg01588.html>. > > That fix had a follow-up, because it broke some ObjC code. > > > > To fix this, we need to use the (amended) token reclassification even when > > parsing an if statement. I factored the code into a separate function so > > as to > > not repeat the very same code. > > > > Bootstrapped/regtested on x86_64-linux, ok for trunk? > > I think you need more thorough testcases, to cover the cases where the if > statement with no else forms the body of a switch or while statement, and > the declaration in question appears in the expression of that switch or > while statement, e.g. > > typedef int T; > > switch (sizeof (enum { T })) > if (1) > ; > T x;
Ah, right, that revealed two more places that were missing the c_parser_maybe_reclassify_token call. Bootstrapped/regtested on x86_64-linux, ok for trunk? 2016-04-26 Marek Polacek <pola...@redhat.com> PR c/67784 * c-parser.c (c_parser_maybe_reclassify_token): New function factored out of ... (c_parser_for_statement): ... here. (c_parser_if_statement): Use it. (c_parser_switch_statement): Use it. (c_parser_while_statement): Use it. * gcc.dg/pr67784-3.c: New test. * gcc.dg/pr67784-4.c: New test. * gcc.dg/pr67784-5.c: New test. diff --git gcc/c/c-parser.c gcc/c/c-parser.c index bdd669d..74423a6 100644 --- gcc/c/c-parser.c +++ gcc/c/c-parser.c @@ -5425,6 +5425,43 @@ c_parser_else_body (c_parser *parser, const token_indent_info &else_tinfo, return c_end_compound_stmt (body_loc, block, flag_isoc99); } +/* We might need to reclassify any previously-lexed identifier, e.g. + when we've left a for loop with an if-statement without else in the + body - we might have used a wrong scope for the token. See PR67784. */ + +static void +c_parser_maybe_reclassify_token (c_parser *parser) +{ + if (c_parser_next_token_is (parser, CPP_NAME)) + { + c_token *token = c_parser_peek_token (parser); + + if (token->id_kind != C_ID_CLASSNAME) + { + tree decl = lookup_name (token->value); + + token->id_kind = C_ID_ID; + if (decl) + { + if (TREE_CODE (decl) == TYPE_DECL) + token->id_kind = C_ID_TYPENAME; + } + else if (c_dialect_objc ()) + { + tree objc_interface_decl = objc_is_class_name (token->value); + /* Objective-C class names are in the same namespace as + variables and typedefs, and hence are shadowed by local + declarations. */ + if (objc_interface_decl) + { + token->value = objc_interface_decl; + token->id_kind = C_ID_CLASSNAME; + } + } + } + } +} + /* Parse an if statement (C90 6.6.4, C99 6.8.4). if-statement: @@ -5523,6 +5560,7 @@ c_parser_if_statement (c_parser *parser, bool *if_p, vec<tree> *chain) if (flag_cilkplus && contains_array_notation_expr (if_stmt)) if_stmt = fix_conditional_array_notations (if_stmt); add_stmt (if_stmt); + c_parser_maybe_reclassify_token (parser); } /* Parse a switch statement (C90 6.6.4, C99 6.8.4). @@ -5578,6 +5616,7 @@ c_parser_switch_statement (c_parser *parser) } c_break_label = save_break; add_stmt (c_end_compound_stmt (switch_loc, block, flag_isoc99)); + c_parser_maybe_reclassify_token (parser); } /* Parse a while statement (C90 6.6.5, C99 6.8.5). @@ -5620,6 +5659,7 @@ c_parser_while_statement (c_parser *parser, bool ivdep, bool *if_p) body = c_parser_c99_block_statement (parser, if_p); c_finish_loop (loc, cond, NULL, body, c_break_label, c_cont_label, true); add_stmt (c_end_compound_stmt (loc, block, flag_isoc99)); + c_parser_maybe_reclassify_token (parser); token_indent_info next_tinfo = get_token_indent_info (c_parser_peek_token (parser)); @@ -5916,38 +5956,7 @@ c_parser_for_statement (c_parser *parser, bool ivdep, bool *if_p) else c_finish_loop (loc, cond, incr, body, c_break_label, c_cont_label, true); add_stmt (c_end_compound_stmt (loc, block, flag_isoc99 || c_dialect_objc ())); - - /* We might need to reclassify any previously-lexed identifier, e.g. - when we've left a for loop with an if-statement without else in the - body - we might have used a wrong scope for the token. See PR67784. */ - if (c_parser_next_token_is (parser, CPP_NAME)) - { - c_token *token = c_parser_peek_token (parser); - - if (token->id_kind != C_ID_CLASSNAME) - { - tree decl = lookup_name (token->value); - - token->id_kind = C_ID_ID; - if (decl) - { - if (TREE_CODE (decl) == TYPE_DECL) - token->id_kind = C_ID_TYPENAME; - } - else if (c_dialect_objc ()) - { - tree objc_interface_decl = objc_is_class_name (token->value); - /* Objective-C class names are in the same namespace as - variables and typedefs, and hence are shadowed by local - declarations. */ - if (objc_interface_decl) - { - token->value = objc_interface_decl; - token->id_kind = C_ID_CLASSNAME; - } - } - } - } + c_parser_maybe_reclassify_token (parser); token_indent_info next_tinfo = get_token_indent_info (c_parser_peek_token (parser)); diff --git gcc/testsuite/gcc.dg/pr67784-3.c gcc/testsuite/gcc.dg/pr67784-3.c index e69de29..45e3c44 100644 --- gcc/testsuite/gcc.dg/pr67784-3.c +++ gcc/testsuite/gcc.dg/pr67784-3.c @@ -0,0 +1,50 @@ +/* PR c/67784 */ +/* { dg-do compile } */ +/* { dg-options "" } */ + +typedef int T; + +void +fn1 (void) +{ + if (sizeof (enum { T }) == 0) + ; + T x; +} + +void +fn2 (void) +{ + int i = 0; + if (sizeof (enum { T }) == 0) + i++; + T x; +} + +void +fn3 (void) +{ + if (sizeof (enum { T }) == 0) + { + } + T x; +} + +void +fn4 (void) +{ + if (sizeof (enum { T }) == 0) +L: + ; + T x; +} + +void +fn5 (void) +{ + if (sizeof (enum { T }) == 0) + ; + else + ; + T x; +} diff --git gcc/testsuite/gcc.dg/pr67784-4.c gcc/testsuite/gcc.dg/pr67784-4.c index e69de29..81a43fd 100644 --- gcc/testsuite/gcc.dg/pr67784-4.c +++ gcc/testsuite/gcc.dg/pr67784-4.c @@ -0,0 +1,55 @@ +/* PR c/67784 */ +/* { dg-do compile } */ +/* { dg-options "" } */ + +typedef int T; + +void +fn1 (void) +{ + switch (sizeof (enum { T })) + if (1) + ; + T x; +} + +void +fn2 (void) +{ + int i = 0; + switch (sizeof (enum { T })) + if (1) + i++; + T x; +} + +void +fn3 (void) +{ + switch (sizeof (enum { T })) + if (1) + { + } + T x; +} + +void +fn4 (void) +{ + switch (sizeof (enum { T })) + if (1) +L: + ; + T x; +} + +void +fn5 (void) +{ + switch (sizeof (enum { T })) + if (1) + ; + else + ; + T x; +} diff --git gcc/testsuite/gcc.dg/pr67784-5.c gcc/testsuite/gcc.dg/pr67784-5.c index e69de29..0934ece 100644 --- gcc/testsuite/gcc.dg/pr67784-5.c +++ gcc/testsuite/gcc.dg/pr67784-5.c @@ -0,0 +1,55 @@ +/* PR c/67784 */ +/* { dg-do compile } */ +/* { dg-options "" } */ + +typedef int T; + +void +fn1 (void) +{ + while (sizeof (enum { T })) + if (1) + ; + T x; +} + +void +fn2 (void) +{ + int i = 0; + while (sizeof (enum { T })) + if (1) + i++; + T x; +} + +void +fn3 (void) +{ + while (sizeof (enum { T })) + if (1) + { + } + T x; +} + +void +fn4 (void) +{ + while (sizeof (enum { T })) + if (1) +L: + ; + T x; +} + +void +fn5 (void) +{ + while (sizeof (enum { T })) + if (1) + ; + else + ; + T x; +} Marek