Message ID | ZkOXizZQssE8-see@redhat.com |
---|---|
State | New |
Headers | show |
Series | [v2] c++: DR 569, DR 1693: fun with semicolons [PR113760] | expand |
On 5/14/24 12:55, Marek Polacek wrote: > On Thu, May 09, 2024 at 12:44:52PM -0400, Jason Merrill wrote: >> On 5/9/24 12:16, Marek Polacek wrote: >>> +static void >>> +maybe_warn_extra_semi (location_t loc, extra_semi_kind kind) >>> +{ >>> + /* -Wno-extra-semi suppresses all. */ >>> + if (warn_extra_semi == 0) >>> + return; >>> + >>> + gcc_rich_location richloc (loc); >>> + richloc.add_fixit_remove (); >>> + >>> + switch (kind) >>> + { >>> + case extra_semi_kind::decl: >>> + if (warn_extra_semi > 0) >>> + warning_at (&richloc, OPT_Wextra_semi, >>> + "extra %<;%> outside of a function"); >>> + /* If -Wextra-semi wasn't specified, warn only when -pedantic is in >>> + effect in C++98. DR 569 says that spurious semicolons at namespace >>> + scope should be allowed. */ >>> + else if (pedantic && cxx_dialect < cxx11) >>> + pedwarn (&richloc, OPT_Wextra_semi, >>> + "extra %<;%> outside of a function only allowed in C++11"); >> >> Shouldn't the pedwarn case come first? > > Yes, I suppose we want both > -Wpedantic -std=c++98 > -Wpedantic -std=c++98 -Wextra-semi > to give pedwarns. Fixed. > >>> + break; >>> + >>> + case extra_semi_kind::member: >>> + if (warn_extra_semi > 0) >>> + warning_at (&richloc, OPT_Wextra_semi, "extra %<;%> inside a struct"); >>> + /* If -Wextra-semi wasn't specified, warn only when -pedantic is in >>> + effect in C++98. DR 1693 added "empty-declaration" to the syntax for >>> + "member-declaration". */ >>> + else if (pedantic && cxx_dialect < cxx11) >>> + pedwarn (&richloc, OPT_Wextra_semi, >>> + "extra %<;%> inside a struct only allowed in C++11"); >> >> And here. > > Fixed too. > >>> + break; >>> + >>> + case extra_semi_kind::in_class_fn_def: >>> + /* A single semicolon is valid after a member function definition >>> + so this is just a warning. */ >>> + if (warn_extra_semi > 0) >>> + warning_at (&richloc, OPT_Wextra_semi, >>> + "extra %<;%> after in-class function definition"); >>> + break; >>> + >>> + default: >>> + gcc_unreachable (); >>> + } >>> +} >>> + >>> /* Declarations [gram.dcl.dcl] */ >>> /* Parse an optional declaration-sequence. TOP_LEVEL is true, if this >>> @@ -15430,11 +15485,11 @@ cp_parser_declaration (cp_parser* parser, tree prefix_attrs) >>> if (token1->type == CPP_SEMICOLON) >>> { >>> - cp_lexer_consume_token (parser->lexer); >>> + location_t semicolon_loc >>> + = cp_lexer_consume_token (parser->lexer)->location; >>> /* A declaration consisting of a single semicolon is invalid >>> - * before C++11. Allow it unless we're being pedantic. */ >>> - if (cxx_dialect < cxx11) >>> - pedwarn (input_location, OPT_Wpedantic, "extra %<;%>"); >>> + before C++11. Allow it unless we're being pedantic. */ >>> + maybe_warn_extra_semi (semicolon_loc, extra_semi_kind::decl); >>> return; >>> } >>> else if (cp_lexer_nth_token_is (parser->lexer, >>> @@ -28121,19 +28176,27 @@ cp_parser_member_declaration (cp_parser* parser) >>> struct S { ; }; >>> - [class.mem] >>> + [class.mem] used to say >>> Each member-declaration shall declare at least one member >>> - name of the class. */ >>> + name of the class. >>> + >>> + but since DR 1693: >>> + >>> + A member-declaration does not declare new members of the class >>> + if it is >>> + -- [...] >>> + -- an empty-declaration. >>> + For any other member-declaration, each declared entity that is not >>> + an unnamed bit-field is a member of the class, and each such >>> + member-declaration shall either declare at least one member name of >>> + the class or declare at least one unnamed bit-field. */ >>> if (!decl_specifiers.any_specifiers_p) >>> { >>> cp_token *token = cp_lexer_peek_token (parser->lexer); >>> - if (cxx_dialect < cxx11 && !in_system_header_at (token->location)) >>> - { >>> - gcc_rich_location richloc (token->location); >>> - richloc.add_fixit_remove (); >>> - pedwarn (&richloc, OPT_Wpedantic, "extra %<;%>"); >>> - } >>> + // ??? Should we check !in_system_header_at in maybe_warn_extra_semi? >> >> The system header check seems to date back to PR 12479. Apparently it has >> not ever proved necessary for the other cases. >> >> Furthermore, all pedwarns are now ignored in system headers unless >> -Wsystem-headers is specified, in which case it would seem useful to report >> this. >> >> So, my inclination is to drop the system header check entirely at this >> point. > > Done. > > Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk? OK. > -- >8 -- > Prompted by c++/113760, I started looking into a bogus "extra ;" > warning in C++11. It quickly turned out that if I want to fix > this for good, the fix will not be so small. > > This patch touches on DR 569, an extra ; at namespace scope should > be allowed since C++11: > > struct S { > }; > ; // pedwarn in C++98 > > It also touches on DR 1693, which allows superfluous semicolons in > class definitions since C++11: > > struct S { > int a; > ; // pedwarn in C++98 > }; > > Note that a single semicolon is valid after a member function definition: > > struct S { > void foo () {}; // only warns with -Wextra-semi > }; > > There's a new function maybe_warn_extra_semi to handle all of the above > in a single place. So now they all get a fix-it hint. > > -Wextra-semi turns on all "extra ;" diagnostics. Currently, options > like -Wc++11-compat or -Wc++11-extensions are not considered. > > DR 1693 > PR c++/113760 > DR 569 > > gcc/c-family/ChangeLog: > > * c.opt (Wextra-semi): Initialize to -1. > > gcc/cp/ChangeLog: > > * parser.cc (extra_semi_kind): New. > (maybe_warn_extra_semi): New. > (cp_parser_declaration): Call maybe_warn_extra_semi. > (cp_parser_member_declaration): Likewise. > > gcc/ChangeLog: > > * doc/invoke.texi: Update -Wextra-semi documentation. > > gcc/testsuite/ChangeLog: > > * g++.dg/diagnostic/semicolon1.C: New test. > * g++.dg/diagnostic/semicolon10.C: New test. > * g++.dg/diagnostic/semicolon11.C: New test. > * g++.dg/diagnostic/semicolon12.C: New test. > * g++.dg/diagnostic/semicolon13.C: New test. > * g++.dg/diagnostic/semicolon14.C: New test. > * g++.dg/diagnostic/semicolon15.C: New test. > * g++.dg/diagnostic/semicolon16.C: New test. > * g++.dg/diagnostic/semicolon17.C: New test. > * g++.dg/diagnostic/semicolon2.C: New test. > * g++.dg/diagnostic/semicolon3.C: New test. > * g++.dg/diagnostic/semicolon4.C: New test. > * g++.dg/diagnostic/semicolon5.C: New test. > * g++.dg/diagnostic/semicolon6.C: New test. > * g++.dg/diagnostic/semicolon7.C: New test. > * g++.dg/diagnostic/semicolon8.C: New test. > * g++.dg/diagnostic/semicolon9.C: New test. > --- > gcc/c-family/c.opt | 2 +- > gcc/cp/parser.cc | 92 +++++++++++++++---- > gcc/doc/invoke.texi | 29 +++++- > gcc/testsuite/g++.dg/diagnostic/semicolon1.C | 18 ++++ > gcc/testsuite/g++.dg/diagnostic/semicolon10.C | 11 +++ > gcc/testsuite/g++.dg/diagnostic/semicolon11.C | 29 ++++++ > gcc/testsuite/g++.dg/diagnostic/semicolon12.C | 29 ++++++ > gcc/testsuite/g++.dg/diagnostic/semicolon13.C | 29 ++++++ > gcc/testsuite/g++.dg/diagnostic/semicolon14.C | 29 ++++++ > gcc/testsuite/g++.dg/diagnostic/semicolon15.C | 29 ++++++ > gcc/testsuite/g++.dg/diagnostic/semicolon16.C | 38 ++++++++ > gcc/testsuite/g++.dg/diagnostic/semicolon17.C | 29 ++++++ > gcc/testsuite/g++.dg/diagnostic/semicolon2.C | 18 ++++ > gcc/testsuite/g++.dg/diagnostic/semicolon3.C | 18 ++++ > gcc/testsuite/g++.dg/diagnostic/semicolon4.C | 18 ++++ > gcc/testsuite/g++.dg/diagnostic/semicolon5.C | 18 ++++ > gcc/testsuite/g++.dg/diagnostic/semicolon6.C | 23 +++++ > gcc/testsuite/g++.dg/diagnostic/semicolon7.C | 18 ++++ > gcc/testsuite/g++.dg/diagnostic/semicolon8.C | 11 +++ > gcc/testsuite/g++.dg/diagnostic/semicolon9.C | 11 +++ > 20 files changed, 480 insertions(+), 19 deletions(-) > create mode 100644 gcc/testsuite/g++.dg/diagnostic/semicolon1.C > create mode 100644 gcc/testsuite/g++.dg/diagnostic/semicolon10.C > create mode 100644 gcc/testsuite/g++.dg/diagnostic/semicolon11.C > create mode 100644 gcc/testsuite/g++.dg/diagnostic/semicolon12.C > create mode 100644 gcc/testsuite/g++.dg/diagnostic/semicolon13.C > create mode 100644 gcc/testsuite/g++.dg/diagnostic/semicolon14.C > create mode 100644 gcc/testsuite/g++.dg/diagnostic/semicolon15.C > create mode 100644 gcc/testsuite/g++.dg/diagnostic/semicolon16.C > create mode 100644 gcc/testsuite/g++.dg/diagnostic/semicolon17.C > create mode 100644 gcc/testsuite/g++.dg/diagnostic/semicolon2.C > create mode 100644 gcc/testsuite/g++.dg/diagnostic/semicolon3.C > create mode 100644 gcc/testsuite/g++.dg/diagnostic/semicolon4.C > create mode 100644 gcc/testsuite/g++.dg/diagnostic/semicolon5.C > create mode 100644 gcc/testsuite/g++.dg/diagnostic/semicolon6.C > create mode 100644 gcc/testsuite/g++.dg/diagnostic/semicolon7.C > create mode 100644 gcc/testsuite/g++.dg/diagnostic/semicolon8.C > create mode 100644 gcc/testsuite/g++.dg/diagnostic/semicolon9.C > > diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt > index 403abc1f26e..fb34c3b7031 100644 > --- a/gcc/c-family/c.opt > +++ b/gcc/c-family/c.opt > @@ -727,7 +727,7 @@ C ObjC C++ ObjC++ Warning > ; in common.opt > > Wextra-semi > -C++ ObjC++ Var(warn_extra_semi) Warning > +C++ ObjC++ Var(warn_extra_semi) Init(-1) Warning > Warn about semicolon after in-class function definition. > > Wflex-array-member-not-at-end > diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc > index 7306ce9a8a8..476ddc0d63a 100644 > --- a/gcc/cp/parser.cc > +++ b/gcc/cp/parser.cc > @@ -15331,6 +15331,61 @@ cp_parser_module_export (cp_parser *parser) > module_kind = mk; > } > > +/* Used for maybe_warn_extra_semi. */ > + > +enum class extra_semi_kind { decl, member, in_class_fn_def }; > + > +/* Warn about an extra semicolon. KIND says in which context the extra > + semicolon occurs. */ > + > +static void > +maybe_warn_extra_semi (location_t loc, extra_semi_kind kind) > +{ > + /* -Wno-extra-semi suppresses all. */ > + if (warn_extra_semi == 0) > + return; > + > + gcc_rich_location richloc (loc); > + richloc.add_fixit_remove (); > + > + switch (kind) > + { > + case extra_semi_kind::decl: > + /* If -Wextra-semi wasn't specified, warn only when -pedantic is in > + effect in C++98. DR 569 says that spurious semicolons at namespace > + scope should be allowed. */ > + if (pedantic && cxx_dialect < cxx11) > + pedwarn (&richloc, OPT_Wextra_semi, > + "extra %<;%> outside of a function only allowed in C++11"); > + else if (warn_extra_semi > 0) > + warning_at (&richloc, OPT_Wextra_semi, > + "extra %<;%> outside of a function"); > + break; > + > + case extra_semi_kind::member: > + /* If -Wextra-semi wasn't specified, warn only when -pedantic is in > + effect in C++98. DR 1693 added "empty-declaration" to the syntax for > + "member-declaration". */ > + if (pedantic && cxx_dialect < cxx11) > + pedwarn (&richloc, OPT_Wextra_semi, > + "extra %<;%> inside a struct only allowed in C++11"); > + else if (warn_extra_semi > 0) > + warning_at (&richloc, OPT_Wextra_semi, "extra %<;%> inside a struct"); > + break; > + > + case extra_semi_kind::in_class_fn_def: > + /* A single semicolon is valid after a member function definition > + so this is just a warning. */ > + if (warn_extra_semi > 0) > + warning_at (&richloc, OPT_Wextra_semi, > + "extra %<;%> after in-class function definition"); > + break; > + > + default: > + gcc_unreachable (); > + } > +} > + > /* Declarations [gram.dcl.dcl] */ > > /* Parse an optional declaration-sequence. TOP_LEVEL is true, if this > @@ -15430,11 +15485,11 @@ cp_parser_declaration (cp_parser* parser, tree prefix_attrs) > > if (token1->type == CPP_SEMICOLON) > { > - cp_lexer_consume_token (parser->lexer); > + location_t semicolon_loc > + = cp_lexer_consume_token (parser->lexer)->location; > /* A declaration consisting of a single semicolon is invalid > - * before C++11. Allow it unless we're being pedantic. */ > - if (cxx_dialect < cxx11) > - pedwarn (input_location, OPT_Wpedantic, "extra %<;%>"); > + before C++11. Allow it unless we're being pedantic. */ > + maybe_warn_extra_semi (semicolon_loc, extra_semi_kind::decl); > return; > } > else if (cp_lexer_nth_token_is (parser->lexer, > @@ -28121,19 +28176,25 @@ cp_parser_member_declaration (cp_parser* parser) > > struct S { ; }; > > - [class.mem] > + [class.mem] used to say > > Each member-declaration shall declare at least one member > - name of the class. */ > + name of the class. > + > + but since DR 1693: > + > + A member-declaration does not declare new members of the class > + if it is > + -- [...] > + -- an empty-declaration. > + For any other member-declaration, each declared entity that is not > + an unnamed bit-field is a member of the class, and each such > + member-declaration shall either declare at least one member name of > + the class or declare at least one unnamed bit-field. */ > if (!decl_specifiers.any_specifiers_p) > { > cp_token *token = cp_lexer_peek_token (parser->lexer); > - if (cxx_dialect < cxx11 && !in_system_header_at (token->location)) > - { > - gcc_rich_location richloc (token->location); > - richloc.add_fixit_remove (); > - pedwarn (&richloc, OPT_Wpedantic, "extra %<;%>"); > - } > + maybe_warn_extra_semi (token->location, extra_semi_kind::member); > } > else > { > @@ -28564,11 +28625,8 @@ cp_parser_member_declaration (cp_parser* parser) > { > location_t semicolon_loc > = cp_lexer_consume_token (parser->lexer)->location; > - gcc_rich_location richloc (semicolon_loc); > - richloc.add_fixit_remove (); > - warning_at (&richloc, OPT_Wextra_semi, > - "extra %<;%> after in-class " > - "function definition"); > + maybe_warn_extra_semi (semicolon_loc, > + extra_semi_kind::in_class_fn_def); > } > goto out; > } > diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi > index ddcd5213f06..cedc1a28c83 100644 > --- a/gcc/doc/invoke.texi > +++ b/gcc/doc/invoke.texi > @@ -4780,7 +4780,34 @@ undefined behavior at runtime. This warning is enabled by default. > @opindex Wextra-semi > @opindex Wno-extra-semi > @item -Wextra-semi @r{(C++, Objective-C++ only)} > -Warn about redundant semicolons after in-class function definitions. > +Warn about redundant semicolons. There are various contexts in which an extra > +semicolon can occur. One is a semicolon after in-class function definitions, > +which is valid in all C++ dialects (and is never a pedwarn): > + > +@smallexample > +struct S @{ > + void foo () @{@}; > +@}; > +@end smallexample > + > +Another is an extra semicolon at namespace scope, which has been allowed > +since C++11 (therefore is a pedwarn in C++98): > + > +@smallexample > +struct S @{ > +@}; > +; > +@end smallexample > + > +And yet another is an extra semicolon in class definitions, which has been > +allowed since C++11 (therefore is a pedwarn in C++98): > + > +@smallexample > +struct S @{ > + int a; > + ; > +@}; > +@end smallexample > > @opindex Wno-global-module > @opindex Wglobal-module > diff --git a/gcc/testsuite/g++.dg/diagnostic/semicolon1.C b/gcc/testsuite/g++.dg/diagnostic/semicolon1.C > new file mode 100644 > index 00000000000..8219d488f4d > --- /dev/null > +++ b/gcc/testsuite/g++.dg/diagnostic/semicolon1.C > @@ -0,0 +1,18 @@ > +// DR 1693, Superfluous semicolons in class definitions > +// PR c++/113760 > +// { dg-do compile } > +// { dg-options "" } > +// { dg-prune-output "only available with" } > + > +struct X { ; }; > + > +struct S { > + void baz () = delete; > + void qux () = delete; > + ; > + void corge () = delete; > + ; > + ; > + int s; > + ; > +}; > diff --git a/gcc/testsuite/g++.dg/diagnostic/semicolon10.C b/gcc/testsuite/g++.dg/diagnostic/semicolon10.C > new file mode 100644 > index 00000000000..4753f557453 > --- /dev/null > +++ b/gcc/testsuite/g++.dg/diagnostic/semicolon10.C > @@ -0,0 +1,11 @@ > +// PR c++/113760 > +// { dg-do compile } > +// { dg-options "-Wextra-semi" } > + > +struct S { > + void f1 () {} > + // A single semicolon is valid after a member function definition. > + void f2 () {}; // { dg-warning "extra .;. after in-class function definition" } > + void f3 () const; > +}; > +void S::f3 () const { }; // { dg-warning "extra .;. outside of a function" } > diff --git a/gcc/testsuite/g++.dg/diagnostic/semicolon11.C b/gcc/testsuite/g++.dg/diagnostic/semicolon11.C > new file mode 100644 > index 00000000000..65df5e9abe6 > --- /dev/null > +++ b/gcc/testsuite/g++.dg/diagnostic/semicolon11.C > @@ -0,0 +1,29 @@ > +// DR 569, Spurious semicolons at namespace scope should be allowed > +// PR c++/113760 > +// { dg-options "-pedantic-errors" } > + > +// C++11 allows extra semicolons at namespace scope. > +struct S { > + void foo(); > +}; > +; // { dg-error "extra .;. outside of a function" "" { target c++98_only } } > + > +void S::foo () { > +}; // { dg-error "extra .;. outside of a function" "" { target c++98_only } } > +; // { dg-error "extra .;. outside of a function" "" { target c++98_only } } > + > +namespace N { > +}; // { dg-error "extra .;. outside of a function" "" { target c++98_only } } > +; // { dg-error "extra .;. outside of a function" "" { target c++98_only } } > + > +void f(); > +; // { dg-error "extra .;. outside of a function" "" { target c++98_only } } > + > +void > +f () > +{ > +}; // { dg-error "extra .;. outside of a function" "" { target c++98_only } } > +; // { dg-error "extra .;. outside of a function" "" { target c++98_only } } > + > +int x; > +; // { dg-error "extra .;. outside of a function" "" { target c++98_only } } > diff --git a/gcc/testsuite/g++.dg/diagnostic/semicolon12.C b/gcc/testsuite/g++.dg/diagnostic/semicolon12.C > new file mode 100644 > index 00000000000..f3e79f80bf0 > --- /dev/null > +++ b/gcc/testsuite/g++.dg/diagnostic/semicolon12.C > @@ -0,0 +1,29 @@ > +// DR 569, Spurious semicolons at namespace scope should be allowed > +// PR c++/113760 > +// { dg-options "" } > + > +// C++11 allows extra semicolons at namespace scope. > +struct S { > + void foo(); > +}; > +; > + > +void S::foo () { > +}; > +; > + > +namespace N { > +}; > +; > + > +void f(); > +; > + > +void > +f () > +{ > +}; > +; > + > +int x; > +; > diff --git a/gcc/testsuite/g++.dg/diagnostic/semicolon13.C b/gcc/testsuite/g++.dg/diagnostic/semicolon13.C > new file mode 100644 > index 00000000000..c7a41202347 > --- /dev/null > +++ b/gcc/testsuite/g++.dg/diagnostic/semicolon13.C > @@ -0,0 +1,29 @@ > +// DR 569, Spurious semicolons at namespace scope should be allowed > +// PR c++/113760 > +// { dg-options "-Wpedantic" } > + > +// C++11 allows extra semicolons at namespace scope. > +struct S { > + void foo(); > +}; > +; // { dg-warning "extra .;. outside of a function" "" { target c++98_only } } > + > +void S::foo () { > +}; // { dg-warning "extra .;. outside of a function" "" { target c++98_only } } > +; // { dg-warning "extra .;. outside of a function" "" { target c++98_only } } > + > +namespace N { > +}; // { dg-warning "extra .;. outside of a function" "" { target c++98_only } } > +; // { dg-warning "extra .;. outside of a function" "" { target c++98_only } } > + > +void f(); > +; // { dg-warning "extra .;. outside of a function" "" { target c++98_only } } > + > +void > +f () > +{ > +}; // { dg-warning "extra .;. outside of a function" "" { target c++98_only } } > +; // { dg-warning "extra .;. outside of a function" "" { target c++98_only } } > + > +int x; > +; // { dg-warning "extra .;. outside of a function" "" { target c++98_only } } > diff --git a/gcc/testsuite/g++.dg/diagnostic/semicolon14.C b/gcc/testsuite/g++.dg/diagnostic/semicolon14.C > new file mode 100644 > index 00000000000..ac2b985f3a3 > --- /dev/null > +++ b/gcc/testsuite/g++.dg/diagnostic/semicolon14.C > @@ -0,0 +1,29 @@ > +// DR 569, Spurious semicolons at namespace scope should be allowed > +// PR c++/113760 > +// { dg-options "-pedantic-errors -Wno-extra-semi" } > + > +// C++11 allows extra semicolons at namespace scope. > +struct S { > + void foo(); > +}; > +; > + > +void S::foo () { > +}; > +; > + > +namespace N { > +}; > +; > + > +void f(); > +; > + > +void > +f () > +{ > +}; > +; > + > +int x; > +; > diff --git a/gcc/testsuite/g++.dg/diagnostic/semicolon15.C b/gcc/testsuite/g++.dg/diagnostic/semicolon15.C > new file mode 100644 > index 00000000000..84b90e4ea35 > --- /dev/null > +++ b/gcc/testsuite/g++.dg/diagnostic/semicolon15.C > @@ -0,0 +1,29 @@ > +// DR 569, Spurious semicolons at namespace scope should be allowed > +// PR c++/113760 > +// { dg-options "-Wextra-semi" } > + > +// C++11 allows extra semicolons at namespace scope. > +struct S { > + void foo(); > +}; > +; // { dg-warning "extra .;. outside of a function" } > + > +void S::foo () { > +}; // { dg-warning "extra .;. outside of a function" } > +; // { dg-warning "extra .;. outside of a function" } > + > +namespace N { > +}; // { dg-warning "extra .;. outside of a function" } > +; // { dg-warning "extra .;. outside of a function" } > + > +void f(); > +; // { dg-warning "extra .;. outside of a function" } > + > +void > +f () > +{ > +}; // { dg-warning "extra .;. outside of a function" } > +; // { dg-warning "extra .;. outside of a function" } > + > +int x; > +; // { dg-warning "extra .;. outside of a function" } > diff --git a/gcc/testsuite/g++.dg/diagnostic/semicolon16.C b/gcc/testsuite/g++.dg/diagnostic/semicolon16.C > new file mode 100644 > index 00000000000..26259cae552 > --- /dev/null > +++ b/gcc/testsuite/g++.dg/diagnostic/semicolon16.C > @@ -0,0 +1,38 @@ > +// DR 569, Spurious semicolons at namespace scope should be allowed > +// PR c++/113760 > +// { dg-options "-Wextra-semi -pedantic-errors" } > + > +// C++11 allows extra semicolons at namespace scope. > +struct S { > + void foo(); > +}; > +; // { dg-warning "extra .;. outside of a function" "" { target c++11 } } > + // { dg-error "extra .;. outside of a function" "" { target c++98_only } .-1 } > + > +void S::foo () { > +}; // { dg-warning "extra .;. outside of a function" "" { target c++11 } } > + // { dg-error "extra .;. outside of a function" "" { target c++98_only } .-1 } > +; // { dg-warning "extra .;. outside of a function" "" { target c++11 } } > + // { dg-error "extra .;. outside of a function" "" { target c++98_only } .-1 } > + > +namespace N { > +}; // { dg-warning "extra .;. outside of a function" "" { target c++11 } } > + // { dg-error "extra .;. outside of a function" "" { target c++98_only } .-1 } > +; // { dg-warning "extra .;. outside of a function" "" { target c++11 } } > + // { dg-error "extra .;. outside of a function" "" { target c++98_only } .-1 } > + > +void f(); > +; // { dg-warning "extra .;. outside of a function" "" { target c++11 } } > + // { dg-error "extra .;. outside of a function" "" { target c++98_only } .-1 } > + > +void > +f () > +{ > +}; // { dg-warning "extra .;. outside of a function" "" { target c++11 } } > + // { dg-error "extra .;. outside of a function" "" { target c++98_only } .-1 } > +; // { dg-warning "extra .;. outside of a function" "" { target c++11 } } > + // { dg-error "extra .;. outside of a function" "" { target c++98_only } .-1 } > + > +int x; > +; // { dg-warning "extra .;. outside of a function" "" { target c++11 } } > + // { dg-error "extra .;. outside of a function" "" { target c++98_only } .-1 } > diff --git a/gcc/testsuite/g++.dg/diagnostic/semicolon17.C b/gcc/testsuite/g++.dg/diagnostic/semicolon17.C > new file mode 100644 > index 00000000000..0b8d3f006e5 > --- /dev/null > +++ b/gcc/testsuite/g++.dg/diagnostic/semicolon17.C > @@ -0,0 +1,29 @@ > +// DR 569, Spurious semicolons at namespace scope should be allowed > +// PR c++/113760 > +// { dg-options "-pedantic-errors -Wno-error=extra-semi" } > + > +// C++11 allows extra semicolons at namespace scope. > +struct S { > + void foo(); > +}; > +; // { dg-warning "extra .;. outside of a function" "" { target c++98_only } } > + > +void S::foo () { > +}; // { dg-warning "extra .;. outside of a function" "" { target c++98_only } } > +; // { dg-warning "extra .;. outside of a function" "" { target c++98_only } } > + > +namespace N { > +}; // { dg-warning "extra .;. outside of a function" "" { target c++98_only } } > +; // { dg-warning "extra .;. outside of a function" "" { target c++98_only } } > + > +void f(); > +; // { dg-warning "extra .;. outside of a function" "" { target c++98_only } } > + > +void > +f () > +{ > +}; // { dg-warning "extra .;. outside of a function" "" { target c++98_only } } > +; // { dg-warning "extra .;. outside of a function" "" { target c++98_only } } > + > +int x; > +; // { dg-warning "extra .;. outside of a function" "" { target c++98_only } } > diff --git a/gcc/testsuite/g++.dg/diagnostic/semicolon2.C b/gcc/testsuite/g++.dg/diagnostic/semicolon2.C > new file mode 100644 > index 00000000000..1cfddf17e9d > --- /dev/null > +++ b/gcc/testsuite/g++.dg/diagnostic/semicolon2.C > @@ -0,0 +1,18 @@ > +// DR 1693, Superfluous semicolons in class definitions > +// PR c++/113760 > +// { dg-do compile } > +// { dg-options "-Wpedantic" } > +// { dg-prune-output "only available with" } > + > +struct X { ; }; // { dg-warning "extra .;. inside a struct" "" { target c++98_only } } > + > +struct S { > + void baz () = delete; > + void qux () = delete; > + ; // { dg-warning "extra .;. inside a struct" "" { target c++98_only } } > + void corge () = delete; > + ; // { dg-warning "extra .;. inside a struct" "" { target c++98_only } } > + ; // { dg-warning "extra .;. inside a struct" "" { target c++98_only } } > + int s; > + ; // { dg-warning "extra .;. inside a struct" "" { target c++98_only } } > +}; > diff --git a/gcc/testsuite/g++.dg/diagnostic/semicolon3.C b/gcc/testsuite/g++.dg/diagnostic/semicolon3.C > new file mode 100644 > index 00000000000..265b655a8fb > --- /dev/null > +++ b/gcc/testsuite/g++.dg/diagnostic/semicolon3.C > @@ -0,0 +1,18 @@ > +// DR 1693, Superfluous semicolons in class definitions > +// PR c++/113760 > +// { dg-do compile } > +// { dg-options "-pedantic-errors" } > +// { dg-prune-output "only available with" } > + > +struct X { ; }; // { dg-error "extra .;. inside a struct" "" { target c++98_only } } > + > +struct S { > + void baz () = delete; > + void qux () = delete; > + ; // { dg-error "extra .;. inside a struct" "" { target c++98_only } } > + void corge () = delete; > + ; // { dg-error "extra .;. inside a struct" "" { target c++98_only } } > + ; // { dg-error "extra .;. inside a struct" "" { target c++98_only } } > + int s; > + ; // { dg-error "extra .;. inside a struct" "" { target c++98_only } } > +}; > diff --git a/gcc/testsuite/g++.dg/diagnostic/semicolon4.C b/gcc/testsuite/g++.dg/diagnostic/semicolon4.C > new file mode 100644 > index 00000000000..22f7a539aed > --- /dev/null > +++ b/gcc/testsuite/g++.dg/diagnostic/semicolon4.C > @@ -0,0 +1,18 @@ > +// DR 1693, Superfluous semicolons in class definitions > +// PR c++/113760 > +// { dg-do compile } > +// { dg-options "-pedantic-errors -Wno-extra-semi" } > +// { dg-prune-output "only available with" } > + > +struct X { ; }; > + > +struct S { > + void baz () = delete; > + void qux () = delete; > + ; > + void corge () = delete; > + ; > + ; > + int s; > + ; > +}; > diff --git a/gcc/testsuite/g++.dg/diagnostic/semicolon5.C b/gcc/testsuite/g++.dg/diagnostic/semicolon5.C > new file mode 100644 > index 00000000000..41b7bfa2ed8 > --- /dev/null > +++ b/gcc/testsuite/g++.dg/diagnostic/semicolon5.C > @@ -0,0 +1,18 @@ > +// DR 1693, Superfluous semicolons in class definitions > +// PR c++/113760 > +// { dg-do compile } > +// { dg-options "-Wextra-semi" } > +// { dg-prune-output "only available with" } > + > +struct X { ; }; // { dg-warning "extra .;. inside a struct" } > + > +struct S { > + void baz () = delete; > + void qux () = delete; > + ; // { dg-warning "extra .;. inside a struct" } > + void corge () = delete; > + ; // { dg-warning "extra .;. inside a struct" } > + ; // { dg-warning "extra .;. inside a struct" } > + int s; > + ; // { dg-warning "extra .;. inside a struct" } > +}; > diff --git a/gcc/testsuite/g++.dg/diagnostic/semicolon6.C b/gcc/testsuite/g++.dg/diagnostic/semicolon6.C > new file mode 100644 > index 00000000000..0c92a1e9523 > --- /dev/null > +++ b/gcc/testsuite/g++.dg/diagnostic/semicolon6.C > @@ -0,0 +1,23 @@ > +// DR 1693, Superfluous semicolons in class definitions > +// PR c++/113760 > +// { dg-do compile } > +// { dg-options "-Wextra-semi -pedantic-errors" } > +// { dg-prune-output "only available with" } > + > +struct X { ; }; // { dg-warning "extra .;. inside a struct" "" { target c++11 } } > + // { dg-error "extra .;. inside a struct" "" { target c++98_only } .-1 } > + > +struct S { > + void baz () = delete; > + void qux () = delete; > + ; // { dg-warning "extra .;. inside a struct" "" { target c++11 } } > + // { dg-error "extra .;. inside a struct" "" { target c++98_only } .-1 } > + void corge () = delete; > + ; // { dg-warning "extra .;. inside a struct" "" { target c++11 } } > + // { dg-error "extra .;. inside a struct" "" { target c++98_only } .-1 } > + ; // { dg-warning "extra .;. inside a struct" "" { target c++11 } } > + // { dg-error "extra .;. inside a struct" "" { target c++98_only } .-1 } > + int s; > + ; // { dg-warning "extra .;. inside a struct" "" { target c++11 } } > + // { dg-error "extra .;. inside a struct" "" { target c++98_only } .-1 } > +}; > diff --git a/gcc/testsuite/g++.dg/diagnostic/semicolon7.C b/gcc/testsuite/g++.dg/diagnostic/semicolon7.C > new file mode 100644 > index 00000000000..aca4f49785d > --- /dev/null > +++ b/gcc/testsuite/g++.dg/diagnostic/semicolon7.C > @@ -0,0 +1,18 @@ > +// DR 1693, Superfluous semicolons in class definitions > +// PR c++/113760 > +// { dg-do compile } > +// { dg-options "-pedantic-errors -Wno-error=extra-semi" } > +// { dg-prune-output "only available with" } > + > +struct X { ; }; // { dg-warning "extra .;. inside a struct" "" { target c++98_only } } > + > +struct S { > + void baz () = delete; > + void qux () = delete; > + ; // { dg-warning "extra .;. inside a struct" "" { target c++98_only } } > + void corge () = delete; > + ; // { dg-warning "extra .;. inside a struct" "" { target c++98_only } } > + ; // { dg-warning "extra .;. inside a struct" "" { target c++98_only } } > + int s; > + ; // { dg-warning "extra .;. inside a struct" "" { target c++98_only } } > +}; > diff --git a/gcc/testsuite/g++.dg/diagnostic/semicolon8.C b/gcc/testsuite/g++.dg/diagnostic/semicolon8.C > new file mode 100644 > index 00000000000..1b0de384dbf > --- /dev/null > +++ b/gcc/testsuite/g++.dg/diagnostic/semicolon8.C > @@ -0,0 +1,11 @@ > +// PR c++/113760 > +// { dg-do compile } > +// { dg-options "-pedantic-errors" } > + > +struct S { > + void f1 () {} > + // A single semicolon is valid after a member function definition. > + void f2 () {}; > + void f3 () const; > +}; > +void S::f3 () const { }; // { dg-error "extra .;. outside of a function" "" { target c++98_only } } > diff --git a/gcc/testsuite/g++.dg/diagnostic/semicolon9.C b/gcc/testsuite/g++.dg/diagnostic/semicolon9.C > new file mode 100644 > index 00000000000..f90539d3bd7 > --- /dev/null > +++ b/gcc/testsuite/g++.dg/diagnostic/semicolon9.C > @@ -0,0 +1,11 @@ > +// PR c++/113760 > +// { dg-do compile } > +// { dg-options "-pedantic-errors -Wno-extra-semi" } > + > +struct S { > + void f1 () {} > + // A single semicolon is valid after a member function definition. > + void f2 () {}; > + void f3 () const; > +}; > +void S::f3 () const { }; > > base-commit: 54ba8d44bbd703bca6984700b4d6f978890097e2
diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt index 403abc1f26e..fb34c3b7031 100644 --- a/gcc/c-family/c.opt +++ b/gcc/c-family/c.opt @@ -727,7 +727,7 @@ C ObjC C++ ObjC++ Warning ; in common.opt Wextra-semi -C++ ObjC++ Var(warn_extra_semi) Warning +C++ ObjC++ Var(warn_extra_semi) Init(-1) Warning Warn about semicolon after in-class function definition. Wflex-array-member-not-at-end diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc index 7306ce9a8a8..476ddc0d63a 100644 --- a/gcc/cp/parser.cc +++ b/gcc/cp/parser.cc @@ -15331,6 +15331,61 @@ cp_parser_module_export (cp_parser *parser) module_kind = mk; } +/* Used for maybe_warn_extra_semi. */ + +enum class extra_semi_kind { decl, member, in_class_fn_def }; + +/* Warn about an extra semicolon. KIND says in which context the extra + semicolon occurs. */ + +static void +maybe_warn_extra_semi (location_t loc, extra_semi_kind kind) +{ + /* -Wno-extra-semi suppresses all. */ + if (warn_extra_semi == 0) + return; + + gcc_rich_location richloc (loc); + richloc.add_fixit_remove (); + + switch (kind) + { + case extra_semi_kind::decl: + /* If -Wextra-semi wasn't specified, warn only when -pedantic is in + effect in C++98. DR 569 says that spurious semicolons at namespace + scope should be allowed. */ + if (pedantic && cxx_dialect < cxx11) + pedwarn (&richloc, OPT_Wextra_semi, + "extra %<;%> outside of a function only allowed in C++11"); + else if (warn_extra_semi > 0) + warning_at (&richloc, OPT_Wextra_semi, + "extra %<;%> outside of a function"); + break; + + case extra_semi_kind::member: + /* If -Wextra-semi wasn't specified, warn only when -pedantic is in + effect in C++98. DR 1693 added "empty-declaration" to the syntax for + "member-declaration". */ + if (pedantic && cxx_dialect < cxx11) + pedwarn (&richloc, OPT_Wextra_semi, + "extra %<;%> inside a struct only allowed in C++11"); + else if (warn_extra_semi > 0) + warning_at (&richloc, OPT_Wextra_semi, "extra %<;%> inside a struct"); + break; + + case extra_semi_kind::in_class_fn_def: + /* A single semicolon is valid after a member function definition + so this is just a warning. */ + if (warn_extra_semi > 0) + warning_at (&richloc, OPT_Wextra_semi, + "extra %<;%> after in-class function definition"); + break; + + default: + gcc_unreachable (); + } +} + /* Declarations [gram.dcl.dcl] */ /* Parse an optional declaration-sequence. TOP_LEVEL is true, if this @@ -15430,11 +15485,11 @@ cp_parser_declaration (cp_parser* parser, tree prefix_attrs) if (token1->type == CPP_SEMICOLON) { - cp_lexer_consume_token (parser->lexer); + location_t semicolon_loc + = cp_lexer_consume_token (parser->lexer)->location; /* A declaration consisting of a single semicolon is invalid - * before C++11. Allow it unless we're being pedantic. */ - if (cxx_dialect < cxx11) - pedwarn (input_location, OPT_Wpedantic, "extra %<;%>"); + before C++11. Allow it unless we're being pedantic. */ + maybe_warn_extra_semi (semicolon_loc, extra_semi_kind::decl); return; } else if (cp_lexer_nth_token_is (parser->lexer, @@ -28121,19 +28176,25 @@ cp_parser_member_declaration (cp_parser* parser) struct S { ; }; - [class.mem] + [class.mem] used to say Each member-declaration shall declare at least one member - name of the class. */ + name of the class. + + but since DR 1693: + + A member-declaration does not declare new members of the class + if it is + -- [...] + -- an empty-declaration. + For any other member-declaration, each declared entity that is not + an unnamed bit-field is a member of the class, and each such + member-declaration shall either declare at least one member name of + the class or declare at least one unnamed bit-field. */ if (!decl_specifiers.any_specifiers_p) { cp_token *token = cp_lexer_peek_token (parser->lexer); - if (cxx_dialect < cxx11 && !in_system_header_at (token->location)) - { - gcc_rich_location richloc (token->location); - richloc.add_fixit_remove (); - pedwarn (&richloc, OPT_Wpedantic, "extra %<;%>"); - } + maybe_warn_extra_semi (token->location, extra_semi_kind::member); } else { @@ -28564,11 +28625,8 @@ cp_parser_member_declaration (cp_parser* parser) { location_t semicolon_loc = cp_lexer_consume_token (parser->lexer)->location; - gcc_rich_location richloc (semicolon_loc); - richloc.add_fixit_remove (); - warning_at (&richloc, OPT_Wextra_semi, - "extra %<;%> after in-class " - "function definition"); + maybe_warn_extra_semi (semicolon_loc, + extra_semi_kind::in_class_fn_def); } goto out; } diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index ddcd5213f06..cedc1a28c83 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -4780,7 +4780,34 @@ undefined behavior at runtime. This warning is enabled by default. @opindex Wextra-semi @opindex Wno-extra-semi @item -Wextra-semi @r{(C++, Objective-C++ only)} -Warn about redundant semicolons after in-class function definitions. +Warn about redundant semicolons. There are various contexts in which an extra +semicolon can occur. One is a semicolon after in-class function definitions, +which is valid in all C++ dialects (and is never a pedwarn): + +@smallexample +struct S @{ + void foo () @{@}; +@}; +@end smallexample + +Another is an extra semicolon at namespace scope, which has been allowed +since C++11 (therefore is a pedwarn in C++98): + +@smallexample +struct S @{ +@}; +; +@end smallexample + +And yet another is an extra semicolon in class definitions, which has been +allowed since C++11 (therefore is a pedwarn in C++98): + +@smallexample +struct S @{ + int a; + ; +@}; +@end smallexample @opindex Wno-global-module @opindex Wglobal-module diff --git a/gcc/testsuite/g++.dg/diagnostic/semicolon1.C b/gcc/testsuite/g++.dg/diagnostic/semicolon1.C new file mode 100644 index 00000000000..8219d488f4d --- /dev/null +++ b/gcc/testsuite/g++.dg/diagnostic/semicolon1.C @@ -0,0 +1,18 @@ +// DR 1693, Superfluous semicolons in class definitions +// PR c++/113760 +// { dg-do compile } +// { dg-options "" } +// { dg-prune-output "only available with" } + +struct X { ; }; + +struct S { + void baz () = delete; + void qux () = delete; + ; + void corge () = delete; + ; + ; + int s; + ; +}; diff --git a/gcc/testsuite/g++.dg/diagnostic/semicolon10.C b/gcc/testsuite/g++.dg/diagnostic/semicolon10.C new file mode 100644 index 00000000000..4753f557453 --- /dev/null +++ b/gcc/testsuite/g++.dg/diagnostic/semicolon10.C @@ -0,0 +1,11 @@ +// PR c++/113760 +// { dg-do compile } +// { dg-options "-Wextra-semi" } + +struct S { + void f1 () {} + // A single semicolon is valid after a member function definition. + void f2 () {}; // { dg-warning "extra .;. after in-class function definition" } + void f3 () const; +}; +void S::f3 () const { }; // { dg-warning "extra .;. outside of a function" } diff --git a/gcc/testsuite/g++.dg/diagnostic/semicolon11.C b/gcc/testsuite/g++.dg/diagnostic/semicolon11.C new file mode 100644 index 00000000000..65df5e9abe6 --- /dev/null +++ b/gcc/testsuite/g++.dg/diagnostic/semicolon11.C @@ -0,0 +1,29 @@ +// DR 569, Spurious semicolons at namespace scope should be allowed +// PR c++/113760 +// { dg-options "-pedantic-errors" } + +// C++11 allows extra semicolons at namespace scope. +struct S { + void foo(); +}; +; // { dg-error "extra .;. outside of a function" "" { target c++98_only } } + +void S::foo () { +}; // { dg-error "extra .;. outside of a function" "" { target c++98_only } } +; // { dg-error "extra .;. outside of a function" "" { target c++98_only } } + +namespace N { +}; // { dg-error "extra .;. outside of a function" "" { target c++98_only } } +; // { dg-error "extra .;. outside of a function" "" { target c++98_only } } + +void f(); +; // { dg-error "extra .;. outside of a function" "" { target c++98_only } } + +void +f () +{ +}; // { dg-error "extra .;. outside of a function" "" { target c++98_only } } +; // { dg-error "extra .;. outside of a function" "" { target c++98_only } } + +int x; +; // { dg-error "extra .;. outside of a function" "" { target c++98_only } } diff --git a/gcc/testsuite/g++.dg/diagnostic/semicolon12.C b/gcc/testsuite/g++.dg/diagnostic/semicolon12.C new file mode 100644 index 00000000000..f3e79f80bf0 --- /dev/null +++ b/gcc/testsuite/g++.dg/diagnostic/semicolon12.C @@ -0,0 +1,29 @@ +// DR 569, Spurious semicolons at namespace scope should be allowed +// PR c++/113760 +// { dg-options "" } + +// C++11 allows extra semicolons at namespace scope. +struct S { + void foo(); +}; +; + +void S::foo () { +}; +; + +namespace N { +}; +; + +void f(); +; + +void +f () +{ +}; +; + +int x; +; diff --git a/gcc/testsuite/g++.dg/diagnostic/semicolon13.C b/gcc/testsuite/g++.dg/diagnostic/semicolon13.C new file mode 100644 index 00000000000..c7a41202347 --- /dev/null +++ b/gcc/testsuite/g++.dg/diagnostic/semicolon13.C @@ -0,0 +1,29 @@ +// DR 569, Spurious semicolons at namespace scope should be allowed +// PR c++/113760 +// { dg-options "-Wpedantic" } + +// C++11 allows extra semicolons at namespace scope. +struct S { + void foo(); +}; +; // { dg-warning "extra .;. outside of a function" "" { target c++98_only } } + +void S::foo () { +}; // { dg-warning "extra .;. outside of a function" "" { target c++98_only } } +; // { dg-warning "extra .;. outside of a function" "" { target c++98_only } } + +namespace N { +}; // { dg-warning "extra .;. outside of a function" "" { target c++98_only } } +; // { dg-warning "extra .;. outside of a function" "" { target c++98_only } } + +void f(); +; // { dg-warning "extra .;. outside of a function" "" { target c++98_only } } + +void +f () +{ +}; // { dg-warning "extra .;. outside of a function" "" { target c++98_only } } +; // { dg-warning "extra .;. outside of a function" "" { target c++98_only } } + +int x; +; // { dg-warning "extra .;. outside of a function" "" { target c++98_only } } diff --git a/gcc/testsuite/g++.dg/diagnostic/semicolon14.C b/gcc/testsuite/g++.dg/diagnostic/semicolon14.C new file mode 100644 index 00000000000..ac2b985f3a3 --- /dev/null +++ b/gcc/testsuite/g++.dg/diagnostic/semicolon14.C @@ -0,0 +1,29 @@ +// DR 569, Spurious semicolons at namespace scope should be allowed +// PR c++/113760 +// { dg-options "-pedantic-errors -Wno-extra-semi" } + +// C++11 allows extra semicolons at namespace scope. +struct S { + void foo(); +}; +; + +void S::foo () { +}; +; + +namespace N { +}; +; + +void f(); +; + +void +f () +{ +}; +; + +int x; +; diff --git a/gcc/testsuite/g++.dg/diagnostic/semicolon15.C b/gcc/testsuite/g++.dg/diagnostic/semicolon15.C new file mode 100644 index 00000000000..84b90e4ea35 --- /dev/null +++ b/gcc/testsuite/g++.dg/diagnostic/semicolon15.C @@ -0,0 +1,29 @@ +// DR 569, Spurious semicolons at namespace scope should be allowed +// PR c++/113760 +// { dg-options "-Wextra-semi" } + +// C++11 allows extra semicolons at namespace scope. +struct S { + void foo(); +}; +; // { dg-warning "extra .;. outside of a function" } + +void S::foo () { +}; // { dg-warning "extra .;. outside of a function" } +; // { dg-warning "extra .;. outside of a function" } + +namespace N { +}; // { dg-warning "extra .;. outside of a function" } +; // { dg-warning "extra .;. outside of a function" } + +void f(); +; // { dg-warning "extra .;. outside of a function" } + +void +f () +{ +}; // { dg-warning "extra .;. outside of a function" } +; // { dg-warning "extra .;. outside of a function" } + +int x; +; // { dg-warning "extra .;. outside of a function" } diff --git a/gcc/testsuite/g++.dg/diagnostic/semicolon16.C b/gcc/testsuite/g++.dg/diagnostic/semicolon16.C new file mode 100644 index 00000000000..26259cae552 --- /dev/null +++ b/gcc/testsuite/g++.dg/diagnostic/semicolon16.C @@ -0,0 +1,38 @@ +// DR 569, Spurious semicolons at namespace scope should be allowed +// PR c++/113760 +// { dg-options "-Wextra-semi -pedantic-errors" } + +// C++11 allows extra semicolons at namespace scope. +struct S { + void foo(); +}; +; // { dg-warning "extra .;. outside of a function" "" { target c++11 } } + // { dg-error "extra .;. outside of a function" "" { target c++98_only } .-1 } + +void S::foo () { +}; // { dg-warning "extra .;. outside of a function" "" { target c++11 } } + // { dg-error "extra .;. outside of a function" "" { target c++98_only } .-1 } +; // { dg-warning "extra .;. outside of a function" "" { target c++11 } } + // { dg-error "extra .;. outside of a function" "" { target c++98_only } .-1 } + +namespace N { +}; // { dg-warning "extra .;. outside of a function" "" { target c++11 } } + // { dg-error "extra .;. outside of a function" "" { target c++98_only } .-1 } +; // { dg-warning "extra .;. outside of a function" "" { target c++11 } } + // { dg-error "extra .;. outside of a function" "" { target c++98_only } .-1 } + +void f(); +; // { dg-warning "extra .;. outside of a function" "" { target c++11 } } + // { dg-error "extra .;. outside of a function" "" { target c++98_only } .-1 } + +void +f () +{ +}; // { dg-warning "extra .;. outside of a function" "" { target c++11 } } + // { dg-error "extra .;. outside of a function" "" { target c++98_only } .-1 } +; // { dg-warning "extra .;. outside of a function" "" { target c++11 } } + // { dg-error "extra .;. outside of a function" "" { target c++98_only } .-1 } + +int x; +; // { dg-warning "extra .;. outside of a function" "" { target c++11 } } + // { dg-error "extra .;. outside of a function" "" { target c++98_only } .-1 } diff --git a/gcc/testsuite/g++.dg/diagnostic/semicolon17.C b/gcc/testsuite/g++.dg/diagnostic/semicolon17.C new file mode 100644 index 00000000000..0b8d3f006e5 --- /dev/null +++ b/gcc/testsuite/g++.dg/diagnostic/semicolon17.C @@ -0,0 +1,29 @@ +// DR 569, Spurious semicolons at namespace scope should be allowed +// PR c++/113760 +// { dg-options "-pedantic-errors -Wno-error=extra-semi" } + +// C++11 allows extra semicolons at namespace scope. +struct S { + void foo(); +}; +; // { dg-warning "extra .;. outside of a function" "" { target c++98_only } } + +void S::foo () { +}; // { dg-warning "extra .;. outside of a function" "" { target c++98_only } } +; // { dg-warning "extra .;. outside of a function" "" { target c++98_only } } + +namespace N { +}; // { dg-warning "extra .;. outside of a function" "" { target c++98_only } } +; // { dg-warning "extra .;. outside of a function" "" { target c++98_only } } + +void f(); +; // { dg-warning "extra .;. outside of a function" "" { target c++98_only } } + +void +f () +{ +}; // { dg-warning "extra .;. outside of a function" "" { target c++98_only } } +; // { dg-warning "extra .;. outside of a function" "" { target c++98_only } } + +int x; +; // { dg-warning "extra .;. outside of a function" "" { target c++98_only } } diff --git a/gcc/testsuite/g++.dg/diagnostic/semicolon2.C b/gcc/testsuite/g++.dg/diagnostic/semicolon2.C new file mode 100644 index 00000000000..1cfddf17e9d --- /dev/null +++ b/gcc/testsuite/g++.dg/diagnostic/semicolon2.C @@ -0,0 +1,18 @@ +// DR 1693, Superfluous semicolons in class definitions +// PR c++/113760 +// { dg-do compile } +// { dg-options "-Wpedantic" } +// { dg-prune-output "only available with" } + +struct X { ; }; // { dg-warning "extra .;. inside a struct" "" { target c++98_only } } + +struct S { + void baz () = delete; + void qux () = delete; + ; // { dg-warning "extra .;. inside a struct" "" { target c++98_only } } + void corge () = delete; + ; // { dg-warning "extra .;. inside a struct" "" { target c++98_only } } + ; // { dg-warning "extra .;. inside a struct" "" { target c++98_only } } + int s; + ; // { dg-warning "extra .;. inside a struct" "" { target c++98_only } } +}; diff --git a/gcc/testsuite/g++.dg/diagnostic/semicolon3.C b/gcc/testsuite/g++.dg/diagnostic/semicolon3.C new file mode 100644 index 00000000000..265b655a8fb --- /dev/null +++ b/gcc/testsuite/g++.dg/diagnostic/semicolon3.C @@ -0,0 +1,18 @@ +// DR 1693, Superfluous semicolons in class definitions +// PR c++/113760 +// { dg-do compile } +// { dg-options "-pedantic-errors" } +// { dg-prune-output "only available with" } + +struct X { ; }; // { dg-error "extra .;. inside a struct" "" { target c++98_only } } + +struct S { + void baz () = delete; + void qux () = delete; + ; // { dg-error "extra .;. inside a struct" "" { target c++98_only } } + void corge () = delete; + ; // { dg-error "extra .;. inside a struct" "" { target c++98_only } } + ; // { dg-error "extra .;. inside a struct" "" { target c++98_only } } + int s; + ; // { dg-error "extra .;. inside a struct" "" { target c++98_only } } +}; diff --git a/gcc/testsuite/g++.dg/diagnostic/semicolon4.C b/gcc/testsuite/g++.dg/diagnostic/semicolon4.C new file mode 100644 index 00000000000..22f7a539aed --- /dev/null +++ b/gcc/testsuite/g++.dg/diagnostic/semicolon4.C @@ -0,0 +1,18 @@ +// DR 1693, Superfluous semicolons in class definitions +// PR c++/113760 +// { dg-do compile } +// { dg-options "-pedantic-errors -Wno-extra-semi" } +// { dg-prune-output "only available with" } + +struct X { ; }; + +struct S { + void baz () = delete; + void qux () = delete; + ; + void corge () = delete; + ; + ; + int s; + ; +}; diff --git a/gcc/testsuite/g++.dg/diagnostic/semicolon5.C b/gcc/testsuite/g++.dg/diagnostic/semicolon5.C new file mode 100644 index 00000000000..41b7bfa2ed8 --- /dev/null +++ b/gcc/testsuite/g++.dg/diagnostic/semicolon5.C @@ -0,0 +1,18 @@ +// DR 1693, Superfluous semicolons in class definitions +// PR c++/113760 +// { dg-do compile } +// { dg-options "-Wextra-semi" } +// { dg-prune-output "only available with" } + +struct X { ; }; // { dg-warning "extra .;. inside a struct" } + +struct S { + void baz () = delete; + void qux () = delete; + ; // { dg-warning "extra .;. inside a struct" } + void corge () = delete; + ; // { dg-warning "extra .;. inside a struct" } + ; // { dg-warning "extra .;. inside a struct" } + int s; + ; // { dg-warning "extra .;. inside a struct" } +}; diff --git a/gcc/testsuite/g++.dg/diagnostic/semicolon6.C b/gcc/testsuite/g++.dg/diagnostic/semicolon6.C new file mode 100644 index 00000000000..0c92a1e9523 --- /dev/null +++ b/gcc/testsuite/g++.dg/diagnostic/semicolon6.C @@ -0,0 +1,23 @@ +// DR 1693, Superfluous semicolons in class definitions +// PR c++/113760 +// { dg-do compile } +// { dg-options "-Wextra-semi -pedantic-errors" } +// { dg-prune-output "only available with" } + +struct X { ; }; // { dg-warning "extra .;. inside a struct" "" { target c++11 } } + // { dg-error "extra .;. inside a struct" "" { target c++98_only } .-1 } + +struct S { + void baz () = delete; + void qux () = delete; + ; // { dg-warning "extra .;. inside a struct" "" { target c++11 } } + // { dg-error "extra .;. inside a struct" "" { target c++98_only } .-1 } + void corge () = delete; + ; // { dg-warning "extra .;. inside a struct" "" { target c++11 } } + // { dg-error "extra .;. inside a struct" "" { target c++98_only } .-1 } + ; // { dg-warning "extra .;. inside a struct" "" { target c++11 } } + // { dg-error "extra .;. inside a struct" "" { target c++98_only } .-1 } + int s; + ; // { dg-warning "extra .;. inside a struct" "" { target c++11 } } + // { dg-error "extra .;. inside a struct" "" { target c++98_only } .-1 } +}; diff --git a/gcc/testsuite/g++.dg/diagnostic/semicolon7.C b/gcc/testsuite/g++.dg/diagnostic/semicolon7.C new file mode 100644 index 00000000000..aca4f49785d --- /dev/null +++ b/gcc/testsuite/g++.dg/diagnostic/semicolon7.C @@ -0,0 +1,18 @@ +// DR 1693, Superfluous semicolons in class definitions +// PR c++/113760 +// { dg-do compile } +// { dg-options "-pedantic-errors -Wno-error=extra-semi" } +// { dg-prune-output "only available with" } + +struct X { ; }; // { dg-warning "extra .;. inside a struct" "" { target c++98_only } } + +struct S { + void baz () = delete; + void qux () = delete; + ; // { dg-warning "extra .;. inside a struct" "" { target c++98_only } } + void corge () = delete; + ; // { dg-warning "extra .;. inside a struct" "" { target c++98_only } } + ; // { dg-warning "extra .;. inside a struct" "" { target c++98_only } } + int s; + ; // { dg-warning "extra .;. inside a struct" "" { target c++98_only } } +}; diff --git a/gcc/testsuite/g++.dg/diagnostic/semicolon8.C b/gcc/testsuite/g++.dg/diagnostic/semicolon8.C new file mode 100644 index 00000000000..1b0de384dbf --- /dev/null +++ b/gcc/testsuite/g++.dg/diagnostic/semicolon8.C @@ -0,0 +1,11 @@ +// PR c++/113760 +// { dg-do compile } +// { dg-options "-pedantic-errors" } + +struct S { + void f1 () {} + // A single semicolon is valid after a member function definition. + void f2 () {}; + void f3 () const; +}; +void S::f3 () const { }; // { dg-error "extra .;. outside of a function" "" { target c++98_only } } diff --git a/gcc/testsuite/g++.dg/diagnostic/semicolon9.C b/gcc/testsuite/g++.dg/diagnostic/semicolon9.C new file mode 100644 index 00000000000..f90539d3bd7 --- /dev/null +++ b/gcc/testsuite/g++.dg/diagnostic/semicolon9.C @@ -0,0 +1,11 @@ +// PR c++/113760 +// { dg-do compile } +// { dg-options "-pedantic-errors -Wno-extra-semi" } + +struct S { + void f1 () {} + // A single semicolon is valid after a member function definition. + void f2 () {}; + void f3 () const; +}; +void S::f3 () const { };