Sadly, I must admit this is looking like GCC 15 material.

Bootstrapped/regtested on x86_64-pc-linux-gnu.

-- >8 --
Prompted by c++/113760, I started looking into a bogus "extra ;"
warning in C++14.  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 implements DR 1693, which allows superfluous semicolons in
class definitions since C++14:

  struct S {
    int a;
    ; // pedwarn in C++98 + C++11
  };

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/semicolon-fixits.C: Use -Wextra-semi instead of -Wpedantic.
        * g++.dg/warn/pedantic2.C: Adjust dg-warning.
        * g++.old-deja/g++.jason/parse11.C: Adjust dg-error.
        * 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 | 29 ++++++
 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  | 18 ++++
 gcc/testsuite/g++.dg/diagnostic/semicolon7.C  | 18 ++++
 gcc/testsuite/g++.dg/diagnostic/semicolon8.C  | 11 +++
 gcc/testsuite/g++.dg/diagnostic/semicolon9.C  | 11 +++
 gcc/testsuite/g++.dg/semicolon-fixits.C       |  2 +-
 gcc/testsuite/g++.dg/warn/pedantic2.C         |  4 +-
 .../g++.old-deja/g++.jason/parse11.C          |  4 +-
 23 files changed, 472 insertions(+), 23 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 b7a4a1a68e3..1ff0c939e95 100644
--- a/gcc/c-family/c.opt
+++ b/gcc/c-family/c.opt
@@ -723,7 +723,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 f0c8f9c4005..a0071ab3ef5 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -15321,6 +15321,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 (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");
+      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++11 and below.  DR 1693 added "empty-declaration" to the
+        syntax for "member-declaration".  */
+      else if (pedantic && cxx_dialect < cxx14)
+       pedwarn (&richloc, OPT_Wextra_semi,
+                "extra %<;%> inside a struct only allowed in C++14");
+      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
@@ -15396,11 +15451,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,
@@ -27992,19 +28047,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 C++14 / 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);
+         // ??? Should we check !in_system_header_at in maybe_warn_extra_semi?
          if (!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
        {
@@ -28398,11 +28461,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 0de184f6241..12c6fb96052 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -4766,7 +4766,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++14 (therefore is a pedwarn in C++98 and C++11):
+
+@smallexample
+struct S @{
+  int a;
+  ;
+@};
+@end smallexample
 
 @opindex Winaccessible-base
 @opindex Wno-inaccessible-base
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..998499b8e1f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/diagnostic/semicolon16.C
@@ -0,0 +1,29 @@
+// 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" }
+
+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/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..d3f66f15fff
--- /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++11_down } }
+
+struct S {
+  void baz () = delete;
+  void qux () = delete;
+  ;                          // { dg-warning "extra .;. inside a struct" "" { 
target c++11_down } }
+  void corge () = delete;
+  ;                          // { dg-warning "extra .;. inside a struct" "" { 
target c++11_down } }
+  ;                          // { dg-warning "extra .;. inside a struct" "" { 
target c++11_down } }
+  int s;
+  ;                          // { dg-warning "extra .;. inside a struct" "" { 
target c++11_down } }
+};
diff --git a/gcc/testsuite/g++.dg/diagnostic/semicolon3.C 
b/gcc/testsuite/g++.dg/diagnostic/semicolon3.C
new file mode 100644
index 00000000000..ca471cca35a
--- /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++11_down } }
+
+struct S {
+  void baz () = delete;
+  void qux () = delete;
+  ;                          // { dg-error "extra .;. inside a struct" "" { 
target c++11_down } }
+  void corge () = delete;
+  ;                          // { dg-error "extra .;. inside a struct" "" { 
target c++11_down } }
+  ;                          // { dg-error "extra .;. inside a struct" "" { 
target c++11_down } }
+  int s;
+  ;                          // { dg-error "extra .;. inside a struct" "" { 
target c++11_down } }
+};
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..0607ab0d0a5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/diagnostic/semicolon6.C
@@ -0,0 +1,18 @@
+// 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" }
+
+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/semicolon7.C 
b/gcc/testsuite/g++.dg/diagnostic/semicolon7.C
new file mode 100644
index 00000000000..e5407bf2f2f
--- /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++11_down } }
+
+struct S {
+  void baz () = delete;
+  void qux () = delete;
+  ;                          // { dg-warning "extra .;. inside a struct" "" { 
target c++11_down } }
+  void corge () = delete;
+  ;                          // { dg-warning "extra .;. inside a struct" "" { 
target c++11_down } }
+  ;                          // { dg-warning "extra .;. inside a struct" "" { 
target c++11_down } }
+  int s;
+  ;                          // { dg-warning "extra .;. inside a struct" "" { 
target c++11_down } }
+};
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 { };
diff --git a/gcc/testsuite/g++.dg/semicolon-fixits.C 
b/gcc/testsuite/g++.dg/semicolon-fixits.C
index a9cc783b172..88738d46f2c 100644
--- a/gcc/testsuite/g++.dg/semicolon-fixits.C
+++ b/gcc/testsuite/g++.dg/semicolon-fixits.C
@@ -1,4 +1,4 @@
-/* { dg-options "-fdiagnostics-show-caret -Wpedantic" } */
+/* { dg-options "-fdiagnostics-show-caret -Wextra-semi" } */
 
 /* Struct with extra semicolon.  */
 struct s1 { int i;; }; /* { dg-warning "19: extra .;." } */
diff --git a/gcc/testsuite/g++.dg/warn/pedantic2.C 
b/gcc/testsuite/g++.dg/warn/pedantic2.C
index 6c834162c1b..51b4c93a5c8 100644
--- a/gcc/testsuite/g++.dg/warn/pedantic2.C
+++ b/gcc/testsuite/g++.dg/warn/pedantic2.C
@@ -5,6 +5,6 @@ class foo
   foo() {};
   void bar() {};
 
-  foo(int) {};;  // { dg-warning "extra" }
-  void bar(int) {};;  // { dg-warning "extra" }
+  foo(int) {};;  // { dg-warning "extra" "" { target c++11_down } }
+  void bar(int) {};;  // { dg-warning "extra" "" { target c++11_down } }
 };
diff --git a/gcc/testsuite/g++.old-deja/g++.jason/parse11.C 
b/gcc/testsuite/g++.old-deja/g++.jason/parse11.C
index 40864c108ba..b1d8f6eceee 100644
--- a/gcc/testsuite/g++.old-deja/g++.jason/parse11.C
+++ b/gcc/testsuite/g++.old-deja/g++.jason/parse11.C
@@ -3,7 +3,7 @@
 
 class aClass 
 { 
-  ; // { dg-error "" } missing declaration
+  ; // { dg-error "extra" "" { target c++11_down } } missing declaration
 private: 
-  ; // { dg-error "" } missing declaration
+  ; // { dg-error "extra" "" { target c++11_down } } missing declaration
 }; 

base-commit: f4935df217ad89f884f908f39086b322e80123d0
-- 
2.43.0

Reply via email to