aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/c-family/c.opt2
-rw-r--r--gcc/cp/parser.cc92
-rw-r--r--gcc/doc/invoke.texi29
-rw-r--r--gcc/testsuite/g++.dg/diagnostic/semicolon1.C18
-rw-r--r--gcc/testsuite/g++.dg/diagnostic/semicolon10.C11
-rw-r--r--gcc/testsuite/g++.dg/diagnostic/semicolon11.C29
-rw-r--r--gcc/testsuite/g++.dg/diagnostic/semicolon12.C29
-rw-r--r--gcc/testsuite/g++.dg/diagnostic/semicolon13.C29
-rw-r--r--gcc/testsuite/g++.dg/diagnostic/semicolon14.C29
-rw-r--r--gcc/testsuite/g++.dg/diagnostic/semicolon15.C29
-rw-r--r--gcc/testsuite/g++.dg/diagnostic/semicolon16.C38
-rw-r--r--gcc/testsuite/g++.dg/diagnostic/semicolon17.C29
-rw-r--r--gcc/testsuite/g++.dg/diagnostic/semicolon2.C18
-rw-r--r--gcc/testsuite/g++.dg/diagnostic/semicolon3.C18
-rw-r--r--gcc/testsuite/g++.dg/diagnostic/semicolon4.C18
-rw-r--r--gcc/testsuite/g++.dg/diagnostic/semicolon5.C18
-rw-r--r--gcc/testsuite/g++.dg/diagnostic/semicolon6.C23
-rw-r--r--gcc/testsuite/g++.dg/diagnostic/semicolon7.C18
-rw-r--r--gcc/testsuite/g++.dg/diagnostic/semicolon8.C11
-rw-r--r--gcc/testsuite/g++.dg/diagnostic/semicolon9.C11
20 files changed, 480 insertions, 19 deletions
diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
index 403abc1..fb34c3b 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 7306ce9..476ddc0 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 ddcd521..cedc1a2 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 0000000..8219d48
--- /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 0000000..4753f55
--- /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 0000000..65df5e9
--- /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 0000000..f3e79f8
--- /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 0000000..c7a4120
--- /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 0000000..ac2b985
--- /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 0000000..84b90e4
--- /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 0000000..26259ca
--- /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 0000000..0b8d3f0
--- /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 0000000..1cfddf1
--- /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 0000000..265b655
--- /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 0000000..22f7a53
--- /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 0000000..41b7bfa
--- /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 0000000..0c92a1e
--- /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 0000000..aca4f49
--- /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 0000000..1b0de38
--- /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 0000000..f90539d
--- /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 { };