https://gcc.gnu.org/g:0b3eac4b54a52bf206b88743d1e987badc97cff4

commit r15-522-g0b3eac4b54a52bf206b88743d1e987badc97cff4
Author: Marek Polacek <pola...@redhat.com>
Date:   Mon Feb 12 19:36:16 2024 -0500

    c++: DR 569, DR 1693: fun with semicolons [PR113760]
    
    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.

Diff:
---
 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(-)

diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
index 403abc1f26e1..fb34c3b70319 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 7306ce9a8a8b..476ddc0d63ad 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 ddcd5213f06a..cedc1a28c834 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 000000000000..8219d488f4d8
--- /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 000000000000..4753f5574536
--- /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 000000000000..65df5e9abe6d
--- /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 000000000000..f3e79f80bf08
--- /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 000000000000..c7a41202347c
--- /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 000000000000..ac2b985f3a3c
--- /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 000000000000..84b90e4ea35c
--- /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 000000000000..26259cae5523
--- /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 000000000000..0b8d3f006e57
--- /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 000000000000..1cfddf17e9d2
--- /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 000000000000..265b655a8fb9
--- /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 000000000000..22f7a539aedf
--- /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 000000000000..41b7bfa2ed89
--- /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 000000000000..0c92a1e95232
--- /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 000000000000..aca4f49785d5
--- /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 000000000000..1b0de384dbf3
--- /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 000000000000..f90539d3bd77
--- /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 { };

Reply via email to