From patchwork Thu Sep 10 20:28:21 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Malcolm X-Patchwork-Id: 516429 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org 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 5928C1400A0 for ; Fri, 11 Sep 2015 06:14:32 +1000 (AEST) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b=LAtYCMcT; dkim-atps=neutral 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:in-reply-to:references; q=dns; s= default; b=tr0DVku5988U+z8e2sMFv7khEdCrTY3QXXa6XSFy6hIOG51Dav/pT SHyBBYD9w77rnZjvn9xTmv3oT64NouMoSYSGgEEJym9MH9JQ1PSM5ch9ih6uwwti odw1yhJoYcpv6B+q+Ixu0b3YR7QpdxFuSJ85c5QyJ7mrDXL8NisYpg= 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:in-reply-to:references; s= default; bh=+MWegTtcFEZc7t79h/8UDti9GyQ=; b=LAtYCMcTT97PTZx1MLGM 6mt86ybFgFh2pKuorU011fTeoNbc9J6d2inHSD6LLq9Qd9WUX4ZwGm0DcsbBRnOo mYifdowOzjZW5SBxMGZ2Oj1rhVMs5wTQ6OrXPGL2UGm3dq9Mwi+UVsoi2Hlbv/C9 GRAZ5kMGRyqB7PL6M0U+eKM= Received: (qmail 115556 invoked by alias); 10 Sep 2015 20:12:55 -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 115494 invoked by uid 89); 10 Sep 2015 20:12:55 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-0.4 required=5.0 tests=AWL, BAYES_40, KAM_LAZY_DOMAIN_SECURITY autolearn=no version=3.3.2 X-HELO: eggs.gnu.org Received: from eggs.gnu.org (HELO eggs.gnu.org) (208.118.235.92) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES256-SHA encrypted) ESMTPS; Thu, 10 Sep 2015 20:12:44 +0000 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Za8D1-0003fi-VC for gcc-patches@gcc.gnu.org; Thu, 10 Sep 2015 16:12:42 -0400 Received: from mx1.redhat.com ([209.132.183.28]:38965) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Za8D1-0003fb-Ma for gcc-patches@gcc.gnu.org; Thu, 10 Sep 2015 16:12:39 -0400 Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) by mx1.redhat.com (Postfix) with ESMTPS id 4A0C8A2C0B for ; Thu, 10 Sep 2015 20:12:39 +0000 (UTC) Received: from c64.redhat.com (vpn-239-137.phx2.redhat.com [10.3.239.137]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id t8AKCWaS003473; Thu, 10 Sep 2015 16:12:38 -0400 From: David Malcolm To: gcc-patches@gcc.gnu.org Cc: David Malcolm Subject: [PATCH 10/22] C++ FE: Use token ranges for various diagnostics Date: Thu, 10 Sep 2015 16:28:21 -0400 Message-Id: <1441916913-11547-11-git-send-email-dmalcolm@redhat.com> In-Reply-To: <1441916913-11547-1-git-send-email-dmalcolm@redhat.com> References: <1441916913-11547-1-git-send-email-dmalcolm@redhat.com> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x X-Received-From: 209.132.183.28 X-IsSubscribed: yes Screenshot: https://dmalcolm.fedorapeople.org/gcc/2015-09-09/c++-token-ranges.html gcc/cp/ChangeLog: * parser.c (cp_parser_string_literal): Show ranges of both string literals in the "unsupported concatenation" error. (cp_parser_primary_expression): Use token range rather than location for two errors. (cp_parser_namespace_alias_definition): Likewise for one error. (cp_parser_init_declarator): Likewise. (cp_parser_base_specifier): Likewise for two errors. (cp_parser_std_attribute): Likewise for an error and a warning. (cp_parser_function_definition_after_declarator): Likewise for an error. (cp_parser_explicit_template_declaration): Add "tok_range" param and use it for the errors. (cp_parser_template_declaration_after_export): Pass the range of the "template" token to cp_parser_explicit_template_declaration. gcc/testsuite/ChangeLog: * g++.dg/diagnostic/token-ranges.C: New. --- gcc/cp/parser.c | 45 +++++++---- gcc/testsuite/g++.dg/diagnostic/token-ranges.C | 104 +++++++++++++++++++++++++ 2 files changed, 132 insertions(+), 17 deletions(-) create mode 100644 gcc/testsuite/g++.dg/diagnostic/token-ranges.C diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 7c59c58..17b7de0 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -3734,6 +3734,8 @@ cp_parser_string_literal (cp_parser *parser, bool translate, bool wide_ok, gcc_obstack_init (&str_ob); count = 0; + source_range range_of_prior_literal = tok->range; + do { cp_lexer_consume_token (parser->lexer); @@ -3767,11 +3769,17 @@ cp_parser_string_literal (cp_parser *parser, bool translate, bool wide_ok, if (type == CPP_STRING) type = curr_type; else if (curr_type != CPP_STRING) - error_at (tok->location, - "unsupported non-standard concatenation " - "of string literals"); + { + rich_location rich_loc (tok->range); + rich_loc.add_range (range_of_prior_literal); + error_at_rich_loc (&rich_loc, + "unsupported non-standard concatenation " + "of string literals"); + } } + range_of_prior_literal.m_finish = tok->range.m_finish; + obstack_grow (&str_ob, &str, sizeof (cpp_string)); tok = cp_lexer_peek_token (parser->lexer); @@ -4549,7 +4557,7 @@ cp_parser_primary_expression (cp_parser *parser, cp_lexer_consume_token (parser->lexer); if (parser->local_variables_forbidden_p) { - error_at (token->location, + error_at (token->range, "% may not be used in this context"); return error_mark_node; } @@ -4672,7 +4680,7 @@ cp_parser_primary_expression (cp_parser *parser, && (cp_lexer_peek_nth_token (parser->lexer, 2)->type == CPP_LESS)) { - error_at (token->location, + error_at (token->range, "a template declaration cannot appear at block scope"); cp_parser_skip_to_end_of_block_or_statement (parser); return error_mark_node; @@ -16829,7 +16837,7 @@ cp_parser_namespace_alias_definition (cp_parser* parser) if (!cp_parser_uncommitted_to_tentative_parse_p (parser) && cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE)) { - error_at (token->location, "% definition is not allowed here"); + error_at (token->range, "% definition is not allowed here"); /* Skip the definition. */ cp_lexer_consume_token (parser->lexer); if (cp_parser_skip_to_closing_brace (parser)) @@ -17602,7 +17610,7 @@ cp_parser_init_declarator (cp_parser* parser, "an asm-specification is not allowed " "on a function-definition"); if (attributes) - error_at (attributes_start_token->location, + error_at (attributes_start_token->range, "attributes are not allowed " "on a function-definition"); /* This is a function-definition. */ @@ -22016,10 +22024,10 @@ cp_parser_base_specifier (cp_parser* parser) { token = cp_lexer_peek_token (parser->lexer); if (!processing_template_decl) - error_at (token->location, + error_at (token->range, "keyword % not allowed outside of templates"); else - error_at (token->location, + error_at (token->range, "keyword % not allowed in this context " "(the base class is implicitly a type)"); cp_lexer_consume_token (parser->lexer); @@ -22971,10 +22979,12 @@ cp_parser_std_attribute (cp_parser *parser) { tree attribute, attr_ns = NULL_TREE, attr_id = NULL_TREE, arguments; cp_token *token; + source_range name_range; /* First, parse name of the attribute, a.k.a attribute-token. */ token = cp_lexer_peek_token (parser->lexer); + name_range = token->range; if (token->type == CPP_NAME) attr_id = token->u.value; else if (token->type == CPP_KEYWORD) @@ -23002,7 +23012,7 @@ cp_parser_std_attribute (cp_parser *parser) attr_id = ridpointers[(int) token->keyword]; else { - error_at (token->location, + error_at (token->range, "expected an identifier for the attribute name"); return error_mark_node; } @@ -23021,7 +23031,7 @@ cp_parser_std_attribute (cp_parser *parser) else if (cxx_dialect >= cxx11 && is_attribute_p ("deprecated", attr_id)) { if (cxx_dialect == cxx11) - pedwarn (token->location, OPT_Wpedantic, + pedwarn (name_range, OPT_Wpedantic, "% is a C++14 feature;" " use %"); TREE_PURPOSE (TREE_PURPOSE (attribute)) = get_identifier ("gnu"); @@ -24383,7 +24393,7 @@ cp_parser_function_definition_after_declarator (cp_parser* parser, returned. */ cp_parser_identifier (parser); /* Issue an error message. */ - error_at (token->location, + error_at (token->range, "named return values are no longer supported"); /* Skip tokens until we reach the start of the function body. */ while (true) @@ -24654,11 +24664,11 @@ cp_parser_template_introduction (cp_parser* parser, bool member_p) /* Parse a normal template-declaration following the template keyword. */ static void -cp_parser_explicit_template_declaration (cp_parser* parser, bool member_p) +cp_parser_explicit_template_declaration (cp_parser* parser, bool member_p, + source_range tok_range) { tree parameter_list; bool need_lang_pop; - location_t location = input_location; /* Look for the `<' token. */ if (!cp_parser_require (parser, CPP_LESS, RT_LESS)) @@ -24668,7 +24678,7 @@ cp_parser_explicit_template_declaration (cp_parser* parser, bool member_p) /* 14.5.2.2 [temp.mem] A local class shall not have member templates. */ - error_at (location, + error_at (tok_range, "invalid declaration of member template in local class"); cp_parser_skip_to_end_of_block_or_statement (parser); return; @@ -24678,7 +24688,7 @@ cp_parser_explicit_template_declaration (cp_parser* parser, bool member_p) A template ... shall not have C linkage. */ if (current_lang_name == lang_name_c) { - error_at (location, "template with C linkage"); + error_at (tok_range, "template with C linkage"); /* Give it C++ linkage to avoid confusing other parts of the front end. */ push_lang_context (lang_name_cplusplus); @@ -24737,8 +24747,9 @@ cp_parser_template_declaration_after_export (cp_parser* parser, bool member_p) { if (cp_lexer_next_token_is_keyword (parser->lexer, RID_TEMPLATE)) { + source_range tok_range = cp_lexer_peek_token (parser->lexer)->range; cp_lexer_consume_token (parser->lexer); - cp_parser_explicit_template_declaration (parser, member_p); + cp_parser_explicit_template_declaration (parser, member_p, tok_range); return true; } else if (flag_concepts) diff --git a/gcc/testsuite/g++.dg/diagnostic/token-ranges.C b/gcc/testsuite/g++.dg/diagnostic/token-ranges.C new file mode 100644 index 0000000..bc830ad --- /dev/null +++ b/gcc/testsuite/g++.dg/diagnostic/token-ranges.C @@ -0,0 +1,104 @@ +/* { dg-options "-fdiagnostics-show-caret -std=c++11 -Wpedantic" } */ + +/* Verify that various diagnostics show source code ranges. */ + +/* These ones merely use token ranges; they don't use tree ranges. */ + +void bad_namespace () { + namespace foo { // { dg-error "'namespace' definition is not allowed here" } + } +/* { dg-begin-multiline-output "" } + namespace foo { + ^~~~~~~~~ + { dg-end-multiline-output "" } */ +} + + +void fn_defn_with_attribute () + __attribute__((constructor (0))) // { dg-error "attributes are not allowed on a function-definition" } +{ + /* { dg-begin-multiline-output "" } + __attribute__((constructor (0))) + ^~~~~~~~~~~~~ + { dg-end-multiline-output "" } */ +} + +class foo {}; +class bar : public typename foo // { dg-error "keyword 'typename' not allowed outside of templates" } +{ +}; +/* { dg-begin-multiline-output "" } + class bar : public typename foo + ^~~~~~~~ + { dg-end-multiline-output "" } */ + + +// C++11 attributes + +void bogus_scoped_attribute [[foo::400]] (); // { dg-error "expected an identifier for the attribute name" } +/* { dg-begin-multiline-output "" } + void bogus_scoped_attribute [[foo::400]] (); + ^~~ + { dg-end-multiline-output "" } */ + +void meta_deprecation [[deprecated]] (); // { dg-warning "use 'gnu::deprecated'" } +/* { dg-begin-multiline-output "" } + void meta_deprecation [[deprecated]] (); + ^~~~~~~~~~ + { dg-end-multiline-output "" } */ + + +int foo() return bar {} // { dg-error "named return values are no longer supported" } +/* { dg-begin-multiline-output "" } + int foo() return bar {} + ^~~~~~ + { dg-end-multiline-output "" } */ + +template void foo(T) +{ + struct A + { + template struct B {} // { dg-error "local class" } + +/* { dg-begin-multiline-output "" } + template struct B {} + ^~~~~~~~ + { dg-end-multiline-output "" } */ + }; +} + +extern "C" { template void foo(T); } // { dg-error "C linkage" } +/* { dg-begin-multiline-output "" } + extern "C" { template void foo(T); } + ^~~~~~~~ + { dg-end-multiline-output "" } */ +// TODO: It would be nice to inform the user of the location of the +// relevant extern "C". + +const void *s = u8"a" u"b"; // { dg-error "non-standard concatenation" } +/* { dg-begin-multiline-output "" } + const void *s = u8"a" u"b"; + ~~~~~ ^~~~ + { dg-end-multiline-output "" } */ + +const void *s2 = u"a" u"b" u8"c"; // { dg-error "non-standard concatenation" } +/* { dg-begin-multiline-output "" } + const void *s2 = u"a" u"b" u8"c"; + ~~~~~~~~~~ ^~~~~ + { dg-end-multiline-output "" } */ + + +void default_arg_of_this (void *ptr = this); // { dg-error "'this'" } +/* { dg-begin-multiline-output "" } + void default_arg_of_this (void *ptr = this); + ^~~~ + { dg-end-multiline-output "" } */ + +void template_inside_fn () +{ + int i = template < // { dg-error "cannot appear at block scope" } +/* { dg-begin-multiline-output "" } + int i = template < + ^~~~~~~~ + { dg-end-multiline-output "" } */ +}