-- >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