From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 57980 invoked by alias); 12 Nov 2015 19:57:32 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Received: (qmail 57963 invoked by uid 89); 12 Nov 2015 19:57:31 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.4 required=5.0 tests=AWL,BAYES_00,RP_MATCHES_RCVD,SPF_HELO_PASS autolearn=ham version=3.3.2 X-HELO: mx1.redhat.com Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES256-GCM-SHA384 encrypted) ESMTPS; Thu, 12 Nov 2015 19:57:30 +0000 Received: from int-mx13.intmail.prod.int.phx2.redhat.com (int-mx13.intmail.prod.int.phx2.redhat.com [10.5.11.26]) by mx1.redhat.com (Postfix) with ESMTPS id 706CC1309; Thu, 12 Nov 2015 19:57:29 +0000 (UTC) Received: from redhat.com (ovpn-204-39.brq.redhat.com [10.40.204.39]) by int-mx13.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id tACJvPT4008119 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO); Thu, 12 Nov 2015 14:57:28 -0500 Date: Thu, 12 Nov 2015 19:57:00 -0000 From: Marek Polacek To: GCC Patches , Joseph Myers Subject: [C PATCH] Fix parsing when using declarations in for loops and typedefs (PR c/67784) Message-ID: <20151112195719.GG3185@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.5.24 (2015-08-30) X-SW-Source: 2015-11/txt/msg01588.txt.bz2 As explained in the PR, the issue here was that we were treating a TYPENAME wrongly as an ID. That happened because we were using information from the wrong scope when parsing a token after an else clause. I.e. in fn1 in the attached testcase we need to examine the token after "if (1);" to see if it's the "else" keyword, but when it's not, we use the scope of the for loop when classifying the token, so we wrongly see "T" as a identifier of a variable. Fixed by examining the token again and reclassifying it. Moreover, we were ICEing in a similar scenario, treating ID as a TYPENAME, as demonstrated in pr67784-2.c. The fix is analogical. Bootstrapped/regtested on x86_64-linux, ok for trunk? 2015-11-12 Marek Polacek PR c/67784 * c-parser.c (c_parser_for_statement): Reclassify the token in a correct scope. * gcc.dg/pr67784-1.c: New test. * gcc.dg/pr67784-2.c: New test. diff --git gcc/c/c-parser.c gcc/c/c-parser.c index 2484b92..8949825 100644 --- gcc/c/c-parser.c +++ gcc/c/c-parser.c @@ -5749,6 +5749,21 @@ c_parser_for_statement (c_parser *parser, bool ivdep) 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); + tree decl = lookup_name (token->value); + if (decl == NULL_TREE) + ; + else if (TREE_CODE (decl) == TYPE_DECL) + token->id_kind = C_ID_TYPENAME; + else if (VAR_P (decl)) + token->id_kind = C_ID_ID; + } + token_indent_info next_tinfo = get_token_indent_info (c_parser_peek_token (parser)); warn_for_misleading_indentation (for_tinfo, body_tinfo, next_tinfo); diff --git gcc/testsuite/gcc.dg/pr67784-1.c gcc/testsuite/gcc.dg/pr67784-1.c index e69de29..d5e85fc 100644 --- gcc/testsuite/gcc.dg/pr67784-1.c +++ gcc/testsuite/gcc.dg/pr67784-1.c @@ -0,0 +1,54 @@ +/* PR c/67784 */ +/* { dg-do compile } */ +/* { dg-options "" } */ + +typedef int T; + +void +fn1 (void) +{ + for (int T;;) + if (1) + ; + T *x; +} + +void +fn2 (void) +{ + for (int T;;) + if (1) + T = 1; + T *x; +} + +void +fn3 (void) +{ + for (int T;;) + if (1) + { + } + T *x; +} + +void +fn4 (void) +{ + for (int T;;) + if (1) +L: + ; + T *x; +} + +void +fn5 (void) +{ + for (int T;;) + if (1) + ; + else + ; + T *x; +} diff --git gcc/testsuite/gcc.dg/pr67784-2.c gcc/testsuite/gcc.dg/pr67784-2.c index e69de29..de3b1c8 100644 --- gcc/testsuite/gcc.dg/pr67784-2.c +++ gcc/testsuite/gcc.dg/pr67784-2.c @@ -0,0 +1,54 @@ +/* PR c/67784 */ +/* { dg-do compile } */ +/* { dg-options "" } */ + +int T; + +void +fn1 (void) +{ + for (typedef int T;;) /* { dg-error "declaration of non-variable" } */ + if (1) + ; + T *x; /* { dg-error "undeclared" } */ +} + +void +fn2 (void) +{ + for (typedef int T;;) /* { dg-error "declaration of non-variable" } */ + if (1) + T = 1; /* { dg-error "expected expression" } */ + T *x; /* { dg-error "undeclared" } */ +} + +void +fn3 (void) +{ + for (typedef int T;;) /* { dg-error "declaration of non-variable" } */ + if (1) + { + } + T *x; /* { dg-error "undeclared" } */ +} + +void +fn4 (void) +{ + for (typedef int T;;) /* { dg-error "declaration of non-variable" } */ + if (1) +L: + ; + T *x; /* { dg-error "undeclared" } */ +} + +void +fn5 (void) +{ + for (typedef int T;;) /* { dg-error "declaration of non-variable" } */ + if (1) + ; + else + ; + T *x; /* { dg-error "undeclared" } */ +} Marek