This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [C PATCH] Follow-up fix to the misclassified token problem (PR c/67784)
- From: Marek Polacek <polacek at redhat dot com>
- To: Joseph Myers <joseph at codesourcery dot com>
- Cc: GCC Patches <gcc-patches at gcc dot gnu dot org>
- Date: Tue, 26 Apr 2016 15:06:16 +0200
- Subject: Re: [C PATCH] Follow-up fix to the misclassified token problem (PR c/67784)
- Authentication-results: sourceware.org; auth=none
- References: <20160426112900 dot GF28445 at redhat dot com> <alpine dot DEB dot 2 dot 20 dot 1604261141450 dot 25461 at digraph dot polyomino dot org dot uk>
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 <polacek@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