From patchwork Wed Oct 11 19:32:51 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Malcolm X-Patchwork-Id: 824526 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=gcc.gnu.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=gcc-patches-return-463973-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="pnN9O8m6"; dkim-atps=neutral Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3yC3yv39cRz9t2V for ; Thu, 12 Oct 2017 06:32:22 +1100 (AEDT) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :to:cc:subject:date:message-id; q=dns; s=default; b=EVYIOCWHYsGg gDxE9GSCJv2PeQZSm10TuPulmI0YJblBwfLjr51n6m2XP8gP0JsY17+LlRRy/A6b qyZ9XL+AIsOlY7AZ6q6GJIw8bV8254WI78MXysCxMz5hf5f7NbRpZEgSeuevYfzV D9c1QZJ7QOQosii5f6EhjB9CyPCvweY= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :to:cc:subject:date:message-id; s=default; bh=+FbmodiB7zHC4FHpAn mecU0HA+g=; b=pnN9O8m6Lu824OBoJPcd/tee2QyHOIR75FhWi+UOHDjbMmZqTN TUW1m0apypSy8gCfu4zkYS1ASlF+fkdZ9gBQg4GXQxmYEn/sFiyFTPOvhS9QUX2I KzJqory4qG7AHEIsjEa//oqqUaeoiYRlnJ5wAT+MRCb+gVR0SFedSuG7Y= Received: (qmail 12640 invoked by alias); 11 Oct 2017 19:32:14 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 12628 invoked by uid 89); 11 Oct 2017 19:32:13 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-25.9 required=5.0 tests=BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KAM_LAZY_DOMAIN_SECURITY, RP_MATCHES_RCVD, SPF_HELO_PASS autolearn=ham version=3.3.2 spammy=reminder, improving, stray 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 ESMTP; Wed, 11 Oct 2017 19:32:11 +0000 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 42FABC059B61 for ; Wed, 11 Oct 2017 19:32:10 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 42FABC059B61 Authentication-Results: ext-mx08.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx08.extmail.prod.ext.phx2.redhat.com; spf=fail smtp.mailfrom=dmalcolm@redhat.com Received: from c64.redhat.com (ovpn-112-12.phx2.redhat.com [10.3.112.12]) by smtp.corp.redhat.com (Postfix) with ESMTP id 6FE3B183A4; Wed, 11 Oct 2017 19:32:09 +0000 (UTC) From: David Malcolm To: gcc-patches@gcc.gnu.org Cc: David Malcolm Subject: [PATCH] C: detect more missing semicolons (PR c/7356) Date: Wed, 11 Oct 2017 15:32:51 -0400 Message-Id: <1507750371-60739-1-git-send-email-dmalcolm@redhat.com> X-IsSubscribed: yes [This patch assumes the two patches here: https://gcc.gnu.org/ml/gcc-patches/2017-10/msg00274.html ] c_parser_declaration_or_fndef has logic for parsing what might be either a declaration or a function definition. This patch adds a test to detect cases where a semicolon would have terminated the decls as a declaration, where the token that follows would start a new declaration specifier, and updates the error message accordingly, with a fix-it hint. This addresses PR c/7356, fixing the case of a stray token before a #include which previously gave inscrutable output, and improving e.g.: int i int j; from: t.c:2:1: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'int' int j; ^~~ to: t.c:1:6: error: expected ';' before 'int' int i ^ ; int j; ~~~ The patch also adds a test for PR c/44515 as a baseline. gcc.dg/noncompile/920923-1.c needs a slight update, as the output for the first line changes from: 920923-1.c:2:14: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'unsigned' typedef BYTE unsigned char; /* { dg-error "expected" } */ ^~~~~~~~ to: 920923-1.c:2:13: error: expected ';' before 'unsigned' typedef BYTE unsigned char; /* { dg-error "expected" } */ ^~~~~~~~~ ; 920923-1.c:2:1: warning: useless type name in empty declaration typedef BYTE unsigned char; /* { dg-error "expected" } */ ^~~~~~~ Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu. OK for trunk? Thanks Dave gcc/c/ChangeLog: PR c/7356 * c-parser.c (c_parser_declaration_or_fndef): Detect missing semicolons. gcc/testsuite/ChangeLog: PR c/7356 PR c/44515 * c-c++-common/pr44515.c: New test case. * gcc.dg/pr7356-2.c: New test case. * gcc.dg/pr7356.c: New test case. * gcc.dg/spellcheck-typenames.c: Update the "singed" char "TODO" case to reflect changes to output. * gcc.dg/noncompile/920923-1.c: Add dg-warning to reflect changes to output. --- gcc/c/c-parser.c | 36 +++++++++++++++++++++++++---- gcc/testsuite/c-c++-common/pr44515.c | 14 +++++++++++ gcc/testsuite/gcc.dg/noncompile/920923-1.c | 1 + gcc/testsuite/gcc.dg/pr7356-2.c | 33 ++++++++++++++++++++++++++ gcc/testsuite/gcc.dg/pr7356.c | 17 ++++++++++++++ gcc/testsuite/gcc.dg/spellcheck-typenames.c | 5 ++-- 6 files changed, 99 insertions(+), 7 deletions(-) create mode 100644 gcc/testsuite/c-c++-common/pr44515.c create mode 100644 gcc/testsuite/gcc.dg/pr7356-2.c create mode 100644 gcc/testsuite/gcc.dg/pr7356.c diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c index a5e3ec4..7c3b834 100644 --- a/gcc/c/c-parser.c +++ b/gcc/c/c-parser.c @@ -2241,11 +2241,37 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, } if (!start_function (specs, declarator, all_prefix_attrs)) { - /* This can appear in many cases looking nothing like a - function definition, so we don't give a more specific - error suggesting there was one. */ - c_parser_error (parser, "expected %<=%>, %<,%>, %<;%>, % " - "or %<__attribute__%>"); + /* At this point we've consumed: + declaration-specifiers declarator + and the next token isn't CPP_EQ, CPP_COMMA, CPP_SEMICOLON, + RID_ASM, RID_ATTRIBUTE, or RID_IN, + but the + declaration-specifiers declarator + aren't grokkable as a function definition, so we have + an error. */ + gcc_assert (!c_parser_next_token_is (parser, CPP_SEMICOLON)); + if (c_parser_next_token_starts_declspecs (parser)) + { + /* If we have + declaration-specifiers declarator decl-specs + then assume we have a missing semicolon, which would + give us: + declaration-specifiers declarator decl-specs + ^ + ; + <~~~~~~~~~ declaration ~~~~~~~~~~> + Use c_parser_require to get an error with a fix-it hint. */ + c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>"); + parser->error = false; + } + else + { + /* This can appear in many cases looking nothing like a + function definition, so we don't give a more specific + error suggesting there was one. */ + c_parser_error (parser, "expected %<=%>, %<,%>, %<;%>, % " + "or %<__attribute__%>"); + } if (nested) c_pop_function_context (); break; diff --git a/gcc/testsuite/c-c++-common/pr44515.c b/gcc/testsuite/c-c++-common/pr44515.c new file mode 100644 index 0000000..dbb77509 --- /dev/null +++ b/gcc/testsuite/c-c++-common/pr44515.c @@ -0,0 +1,14 @@ +/* { dg-options "-fdiagnostics-show-caret" } */ + +void bar(void); +void foo(void) +{ + bar() /* { dg-error "expected ';' before '.' token" } */ +} +/* { dg-begin-multiline-output "" } + bar() + ^ + ; + } + ~ + { dg-end-multiline-output "" } */ diff --git a/gcc/testsuite/gcc.dg/noncompile/920923-1.c b/gcc/testsuite/gcc.dg/noncompile/920923-1.c index 1cb140e..006a071 100644 --- a/gcc/testsuite/gcc.dg/noncompile/920923-1.c +++ b/gcc/testsuite/gcc.dg/noncompile/920923-1.c @@ -1,5 +1,6 @@ /* { dg-message "undeclared identifier is reported only once" "reminder for mmu_base" { target *-*-* } 0 } */ typedef BYTE unsigned char; /* { dg-error "expected" } */ +/* { dg-warning "useless type name in empty declaration" "" { target *-*-* } .-1 } */ typedef int item_n; typedef int perm_set; struct PENT { caddr_t v_addr; };/* { dg-error "unknown type name" } */ diff --git a/gcc/testsuite/gcc.dg/pr7356-2.c b/gcc/testsuite/gcc.dg/pr7356-2.c new file mode 100644 index 0000000..ad67975 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr7356-2.c @@ -0,0 +1,33 @@ +/* { dg-options "-fdiagnostics-show-caret" } */ + +int i /* { dg-error "6: expected ';' before 'int'" } */ +int j; +/* { dg-begin-multiline-output "" } + int i + ^ + ; + int j; + ~~~ + { dg-end-multiline-output "" } */ + + +void test (void) +{ + int i /* { dg-error "8: expected ';' before 'int'" } */ + int j; + + /* { dg-begin-multiline-output "" } + int i + ^ + ; + int j; + ~~~ + { dg-end-multiline-output "" } */ +} + +int old_style_params (first, second) + int first; + int second; +{ + return first + second; +} diff --git a/gcc/testsuite/gcc.dg/pr7356.c b/gcc/testsuite/gcc.dg/pr7356.c new file mode 100644 index 0000000..84baf07 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr7356.c @@ -0,0 +1,17 @@ +/* { dg-options "-fdiagnostics-show-caret" } */ + +a /* { dg-line stray_token } */ +#include +#include +#include +int main(int argc, char** argv) +{ + return 0; +} + +/* { dg-error "expected ';' before '.*'" "" { target *-*-* } stray_token } */ +/* { dg-begin-multiline-output "" } + a + ^ + ; + { dg-end-multiline-output "" } */ diff --git a/gcc/testsuite/gcc.dg/spellcheck-typenames.c b/gcc/testsuite/gcc.dg/spellcheck-typenames.c index f3b8102..3717ad8 100644 --- a/gcc/testsuite/gcc.dg/spellcheck-typenames.c +++ b/gcc/testsuite/gcc.dg/spellcheck-typenames.c @@ -100,8 +100,9 @@ baz value; /* { dg-error "1: unknown type name .baz.; use .enum. keyword to refe { dg-end-multiline-output "" } */ /* TODO: it would be better to detect the "singed" vs "signed" typo here. */ -singed char ch; /* { dg-error "8: before .char." } */ +singed char ch; /* { dg-error "7: before .char." } */ /* { dg-begin-multiline-output "" } singed char ch; - ^~~~ + ^~~~~ + ; { dg-end-multiline-output "" } */