From patchwork Mon Sep 19 07:24:22 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Jakub Jelinek X-Patchwork-Id: 1292 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a5d:5044:0:0:0:0:0 with SMTP id h4csp840200wrt; Mon, 19 Sep 2022 00:25:17 -0700 (PDT) X-Google-Smtp-Source: AMsMyM6o80yn+WfmMPE12BcAicirAOZ8vN/v7/LGApJ848ADo2UG9rCbqzXCYX/wbrkXkSS9BwY0 X-Received: by 2002:a17:907:3daa:b0:77a:3e30:bad0 with SMTP id he42-20020a1709073daa00b0077a3e30bad0mr12000264ejc.144.1663572317363; Mon, 19 Sep 2022 00:25:17 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1663572317; cv=none; d=google.com; s=arc-20160816; b=tFBIeqttGBGGKoD3KmKdFxNhQYuTgd24q9nj/eZLw6DxSeBjP+F+I5IBPAwQqs/RsP l3mbFHBSqsuLdFtevevq5i1ojPZux2V0ocsPX+46O8s3+jnWHq/rdnveXXWRLWCFLonJ 4buZLGeTZH1vJ5+LjhKtldfLPRKLL2Bhkg86GXH12R0HMYGRTNCYycDtMOArldJrq/Hd auPFamxehaNXRRp1JJRtQaHgsntdIbpmJWWFAi2tOWMr2qliNBzO/YIzD8WAHGWqF3qa OkyyaVqZJ4AUPza3scSgn0TcqQdhdnscSIqNMiOmDVBJhmt8C57as28eEDWPQ6QHx84X zwMQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:cc:reply-to:from:list-subscribe:list-help :list-post:list-archive:list-unsubscribe:list-id:precedence :content-transfer-encoding:content-disposition:in-reply-to :mime-version:references:message-id:subject:to:date:dmarc-filter :delivered-to:dkim-signature:dkim-filter; bh=CI2zAjXssIs6RZN4RdwnmkyuA07ZjzQ71hYpeMt60OU=; b=i7POQXuA+U2NBnO/wrrr0TdXhxR9iRNu99Sm6mGssybVht6EpQ8VlKArZLuLpWC59d qQFWxHYU/l5m0MVluMo0CE2zDicmgkd5ci4HHikGKKnOGi1QzgLNlpYScfMDluJsioll ZALecGK+TLjoi42XDeZenEHyTyiiFPgEJbYrXjETye+mvbxZMgLWlTxjQslsgIQ3QqDW WJchUTCO+L0m+mmNkTxU3AMOgztwTtLeZYKZQqP8HLyO7BJ2MrHVqN9XlP8+74Prk/9u zFMVaNiBd6Gs4bHGr2b6x03n8xFbGRx8cjb5/z5Juw/VT+pIHZsUm/HCDpUs7yHnDZsq bqiQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gcc.gnu.org header.s=default header.b=mlioxdpW; spf=pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 8.43.85.97 as permitted sender) smtp.mailfrom="gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=gnu.org Received: from sourceware.org (server2.sourceware.org. [8.43.85.97]) by mx.google.com with ESMTPS id qf28-20020a1709077f1c00b0077f4362c957si20784306ejc.702.2022.09.19.00.25.17 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 19 Sep 2022 00:25:17 -0700 (PDT) Received-SPF: pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 8.43.85.97 as permitted sender) client-ip=8.43.85.97; Authentication-Results: mx.google.com; dkim=pass header.i=@gcc.gnu.org header.s=default header.b=mlioxdpW; spf=pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 8.43.85.97 as permitted sender) smtp.mailfrom="gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=gnu.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 0B90B3858C00 for ; Mon, 19 Sep 2022 07:25:16 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 0B90B3858C00 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1663572316; bh=CI2zAjXssIs6RZN4RdwnmkyuA07ZjzQ71hYpeMt60OU=; h=Date:To:Subject:References:In-Reply-To:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc: From; b=mlioxdpWlO6rBmrR775ayaGZpJglqxXFNiJlnuEHJgGfPfeuzetFiHqvzobue2nW9 SCpb4IrSQAybFsTvzSEhbwgvGjZndcuv60sU/2a1LfS9ZB2u0ftFFzcSK5LhA5v35T QKseLOCqOwL1gOT7DFwRdDlvZu5im2q4SpQ6UfEo= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by sourceware.org (Postfix) with ESMTPS id 787FA3858C54 for ; Mon, 19 Sep 2022 07:24:28 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 787FA3858C54 Received: from mimecast-mx02.redhat.com (mx3-rdu2.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-518-KxD29MWcM5WeyzzTd_IJzA-1; Mon, 19 Sep 2022 03:24:26 -0400 X-MC-Unique: KxD29MWcM5WeyzzTd_IJzA-1 Received: from smtp.corp.redhat.com (int-mx10.intmail.prod.int.rdu2.redhat.com [10.11.54.10]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id B263729AB41B for ; Mon, 19 Sep 2022 07:24:26 +0000 (UTC) Received: from tucnak.zalov.cz (unknown [10.39.192.194]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 6EFFA492B04; Mon, 19 Sep 2022 07:24:26 +0000 (UTC) Received: from tucnak.zalov.cz (localhost [127.0.0.1]) by tucnak.zalov.cz (8.17.1/8.17.1) with ESMTPS id 28J7ONjX641233 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NOT); Mon, 19 Sep 2022 09:24:24 +0200 Received: (from jakub@localhost) by tucnak.zalov.cz (8.17.1/8.17.1/Submit) id 28J7ONK8641232; Mon, 19 Sep 2022 09:24:23 +0200 Date: Mon, 19 Sep 2022 09:24:22 +0200 To: Jason Merrill Subject: [PATCH] c++: Improve diagnostics about conflicting specifiers Message-ID: References: <35c635ad-118f-63bd-eb58-cd949286e28d@redhat.com> MIME-Version: 1.0 In-Reply-To: <35c635ad-118f-63bd-eb58-cd949286e28d@redhat.com> X-Scanned-By: MIMEDefang 3.1 on 10.11.54.10 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Disposition: inline X-Spam-Status: No, score=-4.5 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, RCVD_IN_DNSWL_LOW, SPF_HELO_NONE, SPF_NONE, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Jakub Jelinek via Gcc-patches From: Jakub Jelinek Reply-To: Jakub Jelinek Cc: gcc-patches@gcc.gnu.org Errors-To: gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org Sender: "Gcc-patches" X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1744382006463683413?= X-GMAIL-MSGID: =?utf-8?q?1744382006463683413?= Hi! On Sat, Sep 17, 2022 at 01:23:59AM +0200, Jason Merrill wrote: > I wonder why we don't give an error when setting the > conflicting_specifiers_p flag in cp_parser_set_storage_class? We should be > able to give a better diagnostic at that point. I didn't have time to update the whole patch last night, but this part seems to be independent and I've managed to test it. The diagnostics then looks like: a.C:1:9: error: ‘static’ specifier conflicts with ‘typedef’ 1 | typedef static int a; | ~~~~~~~ ^~~~~~ a.C:2:8: error: ‘typedef’ specifier conflicts with ‘static’ 2 | static typedef int b; | ~~~~~~ ^~~~~~~ a.C:3:8: error: duplicate ‘static’ specifier 3 | static static int c; | ~~~~~~ ^~~~~~ a.C:4:8: error: ‘extern’ specifier conflicts with ‘static’ 4 | static extern int d; | ~~~~~~ ^~~~~~ Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? 2022-09-19 Jakub Jelinek gcc/cp/ * parser.cc (cp_parser_lambda_declarator_opt): Don't diagnose conflicting specifiers here. (cp_storage_class_name): New variable. (cp_parser_decl_specifier_seq): When setting conflicting_specifiers_p for the first time, diagnose which exact specifiers conflict. (cp_parser_set_storage_class): Likewise. Move storage_class computation earlier. * decl.cc (grokdeclarator): Don't diagnose conflicting specifiers here, just return error_mark_node. gcc/testsuite/ * g++.dg/diagnostic/conflicting-specifiers-1.C: Adjust expected diagnostics. * g++.dg/parse/typedef8.C: Likewise. * g++.dg/parse/crash39.C: Likewise. * g++.dg/other/mult-stor1.C: Likewise. * g++.dg/cpp2a/constinit3.C: Likewise. Jakub --- gcc/cp/parser.cc.jj 2022-09-16 22:34:28.427708581 +0200 +++ gcc/cp/parser.cc 2022-09-19 09:18:49.561145347 +0200 @@ -11718,9 +11718,6 @@ cp_parser_lambda_declarator_opt (cp_pars { LAMBDA_EXPR_MUTABLE_P (lambda_expr) = 1; quals = TYPE_UNQUALIFIED; - if (lambda_specs.conflicting_specifiers_p) - error_at (lambda_specs.locations[ds_storage_class], - "duplicate %"); } tx_qual = cp_parser_tx_qualifier_opt (parser); @@ -15720,6 +15717,13 @@ cp_parser_decomposition_declaration (cp_ return decl; } +/* Names of storage classes. */ + +static const char *const +cp_storage_class_name[] = { + "", "auto", "register", "static", "extern", "mutable" +}; + /* Parse a decl-specifier-seq. decl-specifier-seq: @@ -15941,8 +15945,18 @@ cp_parser_decl_specifier_seq (cp_parser* may as well commit at this point. */ cp_parser_commit_to_tentative_parse (parser); - if (decl_specs->storage_class != sc_none) - decl_specs->conflicting_specifiers_p = true; + if (decl_specs->storage_class != sc_none) + { + if (decl_specs->conflicting_specifiers_p) + break; + gcc_rich_location richloc (token->location); + location_t oloc = decl_specs->locations[ds_storage_class]; + richloc.add_location_if_nearby (oloc); + error_at (&richloc, + "% specifier conflicts with %qs", + cp_storage_class_name[decl_specs->storage_class]); + decl_specs->conflicting_specifiers_p = true; + } break; /* storage-class-specifier: @@ -32826,26 +32840,6 @@ cp_parser_set_storage_class (cp_parser * { cp_storage_class storage_class; - if (parser->in_unbraced_linkage_specification_p) - { - error_at (token->location, "invalid use of %qD in linkage specification", - ridpointers[keyword]); - return; - } - else if (decl_specs->storage_class != sc_none) - { - decl_specs->conflicting_specifiers_p = true; - return; - } - - if ((keyword == RID_EXTERN || keyword == RID_STATIC) - && decl_spec_seq_has_spec_p (decl_specs, ds_thread) - && decl_specs->gnu_thread_keyword_p) - { - pedwarn (decl_specs->locations[ds_thread], 0, - "%<__thread%> before %qD", ridpointers[keyword]); - } - switch (keyword) { case RID_AUTO: @@ -32866,6 +32860,38 @@ cp_parser_set_storage_class (cp_parser * default: gcc_unreachable (); } + + if (parser->in_unbraced_linkage_specification_p) + { + error_at (token->location, "invalid use of %qD in linkage specification", + ridpointers[keyword]); + return; + } + else if (decl_specs->storage_class != sc_none) + { + if (decl_specs->conflicting_specifiers_p) + return; + gcc_rich_location richloc (token->location); + richloc.add_location_if_nearby (decl_specs->locations[ds_storage_class]); + if (decl_specs->storage_class == storage_class) + error_at (&richloc, "duplicate %qD specifier", ridpointers[keyword]); + else + error_at (&richloc, + "%qD specifier conflicts with %qs", + ridpointers[keyword], + cp_storage_class_name[decl_specs->storage_class]); + decl_specs->conflicting_specifiers_p = true; + return; + } + + if ((keyword == RID_EXTERN || keyword == RID_STATIC) + && decl_spec_seq_has_spec_p (decl_specs, ds_thread) + && decl_specs->gnu_thread_keyword_p) + { + pedwarn (decl_specs->locations[ds_thread], 0, + "%<__thread%> before %qD", ridpointers[keyword]); + } + decl_specs->storage_class = storage_class; set_and_check_decl_spec_loc (decl_specs, ds_storage_class, token); @@ -32873,8 +32899,16 @@ cp_parser_set_storage_class (cp_parser * specifier. If there is a typedef specifier present then set conflicting_specifiers_p which will trigger an error later on in grokdeclarator. */ - if (decl_spec_seq_has_spec_p (decl_specs, ds_typedef)) - decl_specs->conflicting_specifiers_p = true; + if (decl_spec_seq_has_spec_p (decl_specs, ds_typedef) + && !decl_specs->conflicting_specifiers_p) + { + gcc_rich_location richloc (token->location); + richloc.add_location_if_nearby (decl_specs->locations[ds_typedef]); + error_at (&richloc, + "%qD specifier conflicts with %", + ridpointers[keyword]); + decl_specs->conflicting_specifiers_p = true; + } } /* Update the DECL_SPECS to reflect the TYPE_SPEC. If TYPE_DEFINITION_P --- gcc/cp/decl.cc.jj 2022-09-16 22:34:28.420708676 +0200 +++ gcc/cp/decl.cc 2022-09-18 20:15:13.357162931 +0200 @@ -12089,12 +12089,7 @@ grokdeclarator (const cp_declarator *dec } if (declspecs->conflicting_specifiers_p) - { - error_at (min_location (declspecs->locations[ds_typedef], - declspecs->locations[ds_storage_class]), - "conflicting specifiers in declaration of %qs", name); - return error_mark_node; - } + return error_mark_node; /* Extract the basic type from the decl-specifier-seq. */ type = declspecs->type; --- gcc/testsuite/g++.dg/diagnostic/conflicting-specifiers-1.C.jj 2020-01-14 20:02:46.815609354 +0100 +++ gcc/testsuite/g++.dg/diagnostic/conflicting-specifiers-1.C 2022-09-18 20:55:53.928964842 +0200 @@ -1 +1 @@ -static typedef int i __attribute__((unused)); // { dg-error "1:conflicting specifiers" } +static typedef int i __attribute__((unused)); // { dg-error "1:'typedef' specifier conflicts with 'static'" } --- gcc/testsuite/g++.dg/parse/typedef8.C.jj 2020-01-14 20:02:46.921607767 +0100 +++ gcc/testsuite/g++.dg/parse/typedef8.C 2022-09-18 20:55:23.829375095 +0200 @@ -1,11 +1,11 @@ //PR c++ 29024 -typedef static int a; // { dg-error "conflicting" } -typedef register int b; // { dg-error "conflicting" } -typedef extern int c; // { dg-error "conflicting" } -static typedef int a; // { dg-error "conflicting" } +typedef static int a; // { dg-error "'static' specifier conflicts with 'typedef'" } +typedef register int b; // { dg-error "'register' specifier conflicts with 'typedef'" } +typedef extern int c; // { dg-error "'extern' specifier conflicts with 'typedef'" } +static typedef int a; // { dg-error "'typedef' specifier conflicts with 'static'" } void foo() { - typedef auto int bar; // { dg-error "conflicting|two or more data types" } + typedef auto int bar; // { dg-error "'auto' specifier conflicts with 'typedef'|two or more data types" } } --- gcc/testsuite/g++.dg/parse/crash39.C.jj 2020-01-14 20:02:46.911607917 +0100 +++ gcc/testsuite/g++.dg/parse/crash39.C 2022-09-18 20:56:32.004445908 +0200 @@ -1,3 +1,3 @@ // PR c++/31747 -static extern int i; // { dg-error "conflicting specifiers" } +static extern int i; // { dg-error "'extern' specifier conflicts with 'static'" } --- gcc/testsuite/g++.dg/other/mult-stor1.C.jj 2020-01-14 20:02:46.902608051 +0100 +++ gcc/testsuite/g++.dg/other/mult-stor1.C 2022-09-18 20:57:43.635469614 +0200 @@ -4,5 +4,5 @@ struct A { - extern static int i; // { dg-error "conflicting specifiers" } + extern static int i; // { dg-error "'static' specifier conflicts with 'extern'" } }; --- gcc/testsuite/g++.dg/cpp2a/constinit3.C.jj 2020-05-13 21:38:28.356420335 +0200 +++ gcc/testsuite/g++.dg/cpp2a/constinit3.C 2022-09-18 20:57:12.424894986 +0200 @@ -5,7 +5,7 @@ constinit constinit int v1; // { dg-erro constexpr constinit int v2 = 1; // { dg-error "can use at most one of the .constinit. and .constexpr. specifiers" } constinit constexpr int v3 = 1; // { dg-error "an use at most one of the .constinit. and .constexpr. specifiers" } -extern static constinit int v4; // { dg-error "conflicting specifiers" } +extern static constinit int v4; // { dg-error "'static' specifier conflicts with 'extern'" } extern thread_local constinit int v5; extern constinit int v6;