public inbox for gcc-cvs@sourceware.org help / color / mirror / Atom feed
From: Jakub Jelinek <jakub@gcc.gnu.org> To: gcc-cvs@gcc.gnu.org Subject: [gcc r13-2889] c++: Improve diagnostics about conflicting specifiers Date: Tue, 27 Sep 2022 06:21:48 +0000 (GMT) [thread overview] Message-ID: <20220927062148.0200E3858D39@sourceware.org> (raw) https://gcc.gnu.org/g:5b86d5dbe47c477daf739b82c3793a70f8cbd96c commit r13-2889-g5b86d5dbe47c477daf739b82c3793a70f8cbd96c Author: Jakub Jelinek <jakub@redhat.com> Date: Tue Sep 27 08:20:05 2022 +0200 c++: Improve diagnostics about conflicting specifiers 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; | ~~~~~~ ^~~~~~ 2022-09-27 Jakub Jelinek <jakub@redhat.com> 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. Diff: --- gcc/cp/decl.cc | 7 +- gcc/cp/parser.cc | 88 +++++++++++++++------- gcc/testsuite/g++.dg/cpp2a/constinit3.C | 2 +- .../g++.dg/diagnostic/conflicting-specifiers-1.C | 2 +- gcc/testsuite/g++.dg/other/mult-stor1.C | 2 +- gcc/testsuite/g++.dg/parse/crash39.C | 2 +- gcc/testsuite/g++.dg/parse/typedef8.C | 10 +-- 7 files changed, 71 insertions(+), 42 deletions(-) diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc index 80467c19254..f4460c911b3 100644 --- a/gcc/cp/decl.cc +++ b/gcc/cp/decl.cc @@ -12095,12 +12095,7 @@ grokdeclarator (const cp_declarator *declarator, } 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; diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc index 3dedd140428..d876a8623b4 100644 --- a/gcc/cp/parser.cc +++ b/gcc/cp/parser.cc @@ -11729,9 +11729,6 @@ cp_parser_lambda_declarator_opt (cp_parser* parser, tree lambda_expr) { 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 %<mutable%>"); } tx_qual = cp_parser_tx_qualifier_opt (parser); @@ -15731,6 +15728,13 @@ cp_parser_decomposition_declaration (cp_parser *parser, 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: @@ -15952,8 +15956,18 @@ cp_parser_decl_specifier_seq (cp_parser* 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, + "%<typedef%> specifier conflicts with %qs", + cp_storage_class_name[decl_specs->storage_class]); + decl_specs->conflicting_specifiers_p = true; + } break; /* storage-class-specifier: @@ -32845,26 +32859,6 @@ cp_parser_set_storage_class (cp_parser *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: @@ -32885,6 +32879,38 @@ cp_parser_set_storage_class (cp_parser *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); @@ -32892,8 +32918,16 @@ cp_parser_set_storage_class (cp_parser *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 %<typedef%>", + ridpointers[keyword]); + decl_specs->conflicting_specifiers_p = true; + } } /* Update the DECL_SPECS to reflect the TYPE_SPEC. If TYPE_DEFINITION_P diff --git a/gcc/testsuite/g++.dg/cpp2a/constinit3.C b/gcc/testsuite/g++.dg/cpp2a/constinit3.C index a29c594657a..ffa61847824 100644 --- a/gcc/testsuite/g++.dg/cpp2a/constinit3.C +++ b/gcc/testsuite/g++.dg/cpp2a/constinit3.C @@ -5,7 +5,7 @@ constinit constinit int v1; // { dg-error "duplicate .constinit." } 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; diff --git a/gcc/testsuite/g++.dg/diagnostic/conflicting-specifiers-1.C b/gcc/testsuite/g++.dg/diagnostic/conflicting-specifiers-1.C index 1a8ac02b77e..89e2ebdebf6 100644 --- a/gcc/testsuite/g++.dg/diagnostic/conflicting-specifiers-1.C +++ b/gcc/testsuite/g++.dg/diagnostic/conflicting-specifiers-1.C @@ -1 +1 @@ -static typedef int i __attribute__((unused)); // { dg-error "1:conflicting specifiers" } +static typedef int i __attribute__((unused)); // { dg-error "8:'typedef' specifier conflicts with 'static'" } diff --git a/gcc/testsuite/g++.dg/other/mult-stor1.C b/gcc/testsuite/g++.dg/other/mult-stor1.C index 1eaec4f14f9..e582b03ee60 100644 --- a/gcc/testsuite/g++.dg/other/mult-stor1.C +++ b/gcc/testsuite/g++.dg/other/mult-stor1.C @@ -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'" } }; diff --git a/gcc/testsuite/g++.dg/parse/crash39.C b/gcc/testsuite/g++.dg/parse/crash39.C index 2f39c10e31d..5d4e02d79ca 100644 --- a/gcc/testsuite/g++.dg/parse/crash39.C +++ b/gcc/testsuite/g++.dg/parse/crash39.C @@ -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'" } diff --git a/gcc/testsuite/g++.dg/parse/typedef8.C b/gcc/testsuite/g++.dg/parse/typedef8.C index 60b8f39ee5e..e21bdb911d9 100644 --- a/gcc/testsuite/g++.dg/parse/typedef8.C +++ b/gcc/testsuite/g++.dg/parse/typedef8.C @@ -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" } }
reply other threads:[~2022-09-27 6:21 UTC|newest] Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=20220927062148.0200E3858D39@sourceware.org \ --to=jakub@gcc.gnu.org \ --cc=gcc-cvs@gcc.gnu.org \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: linkBe sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).