On 5/14/24 12:55, Marek Polacek wrote:
On Thu, May 09, 2024 at 12:44:52PM -0400, Jason Merrill wrote:
On 5/9/24 12:16, Marek Polacek wrote:
+static void
+maybe_warn_extra_semi (location_t loc, extra_semi_kind kind)
+{
+  /* -Wno-extra-semi suppresses all.  */
+  if (warn_extra_semi == 0)
+    return;
+
+  gcc_rich_location richloc (loc);
+  richloc.add_fixit_remove ();
+
+  switch (kind)
+    {
+    case extra_semi_kind::decl:
+      if (warn_extra_semi > 0)
+       warning_at (&richloc, OPT_Wextra_semi,
+                   "extra %<;%> outside of a function");
+      /* If -Wextra-semi wasn't specified, warn only when -pedantic is in
+        effect in C++98.  DR 569 says that spurious semicolons at namespace
+        scope should be allowed.  */
+      else if (pedantic && cxx_dialect < cxx11)
+       pedwarn (&richloc, OPT_Wextra_semi,
+                "extra %<;%> outside of a function only allowed in C++11");

Shouldn't the pedwarn case come first?

Yes, I suppose we want both
-Wpedantic -std=c++98
-Wpedantic -std=c++98 -Wextra-semi
to give pedwarns.  Fixed.
+      break;
+
+    case extra_semi_kind::member:
+      if (warn_extra_semi > 0)
+       warning_at (&richloc, OPT_Wextra_semi, "extra %<;%> inside a struct");
+      /* If -Wextra-semi wasn't specified, warn only when -pedantic is in
+        effect in C++98.  DR 1693 added "empty-declaration" to the syntax for
+        "member-declaration".  */
+      else if (pedantic && cxx_dialect < cxx11)
+       pedwarn (&richloc, OPT_Wextra_semi,
+                "extra %<;%> inside a struct only allowed in C++11");

And here.

Fixed too.

+      break;
+
+    case extra_semi_kind::in_class_fn_def:
+      /* A single semicolon is valid after a member function definition
+        so this is just a warning.  */
+      if (warn_extra_semi > 0)
+       warning_at (&richloc, OPT_Wextra_semi,
+                   "extra %<;%> after in-class function definition");
+      break;
+
+    default:
+      gcc_unreachable ();
+    }
+}
+
   /* Declarations [gram.dcl.dcl] */
   /* Parse an optional declaration-sequence.  TOP_LEVEL is true, if this
@@ -15430,11 +15485,11 @@ cp_parser_declaration (cp_parser* parser, tree 
prefix_attrs)
     if (token1->type == CPP_SEMICOLON)
       {
-      cp_lexer_consume_token (parser->lexer);
+      location_t semicolon_loc
+       = cp_lexer_consume_token (parser->lexer)->location;
         /* A declaration consisting of a single semicolon is invalid
-       * before C++11.  Allow it unless we're being pedantic.  */
-      if (cxx_dialect < cxx11)
-       pedwarn (input_location, OPT_Wpedantic, "extra %<;%>");
+        before C++11.  Allow it unless we're being pedantic.  */
+      maybe_warn_extra_semi (semicolon_loc, extra_semi_kind::decl);
         return;
       }
     else if (cp_lexer_nth_token_is (parser->lexer,
@@ -28121,19 +28176,27 @@ cp_parser_member_declaration (cp_parser* parser)
           struct S { ; };
-        [class.mem]
+        [class.mem] used to say
         Each member-declaration shall declare at least one member
-        name of the class.  */
+        name of the class.
+
+        but since DR 1693:
+
+        A member-declaration does not declare new members of the class
+        if it is
+        -- [...]
+        -- an empty-declaration.
+        For any other member-declaration, each declared entity that is not
+        an unnamed bit-field is a member of the class, and each such
+        member-declaration shall either declare at least one member name of
+        the class or declare at least one unnamed bit-field.  */
         if (!decl_specifiers.any_specifiers_p)
        {
          cp_token *token = cp_lexer_peek_token (parser->lexer);
-         if (cxx_dialect < cxx11 && !in_system_header_at (token->location))
-           {
-             gcc_rich_location richloc (token->location);
-             richloc.add_fixit_remove ();
-             pedwarn (&richloc, OPT_Wpedantic, "extra %<;%>");
-           }
+         // ??? Should we check !in_system_header_at in maybe_warn_extra_semi?

The system header check seems to date back to PR 12479.  Apparently it has
not ever proved necessary for the other cases.

Furthermore, all pedwarns are now ignored in system headers unless
-Wsystem-headers is specified, in which case it would seem useful to report
this.

So, my inclination is to drop the system header check entirely at this
point.

Done.

Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?

OK.

-- >8 --
Prompted by c++/113760, I started looking into a bogus "extra ;"
warning in C++11.  It quickly turned out that if I want to fix
this for good, the fix will not be so small.

This patch touches on DR 569, an extra ; at namespace scope should
be allowed since C++11:

   struct S {
   };
   ; // pedwarn in C++98

It also touches on DR 1693, which allows superfluous semicolons in
class definitions since C++11:

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

Note that a single semicolon is valid after a member function definition:

   struct S {
     void foo () {}; // only warns with -Wextra-semi
   };

There's a new function maybe_warn_extra_semi to handle all of the above
in a single place.  So now they all get a fix-it hint.

-Wextra-semi turns on all "extra ;" diagnostics.  Currently, options
like -Wc++11-compat or -Wc++11-extensions are not considered.

        DR 1693
        PR c++/113760
        DR 569

gcc/c-family/ChangeLog:

        * c.opt (Wextra-semi): Initialize to -1.

gcc/cp/ChangeLog:

        * parser.cc (extra_semi_kind): New.
        (maybe_warn_extra_semi): New.
        (cp_parser_declaration): Call maybe_warn_extra_semi.
        (cp_parser_member_declaration): Likewise.

gcc/ChangeLog:

        * doc/invoke.texi: Update -Wextra-semi documentation.

gcc/testsuite/ChangeLog:

        * g++.dg/diagnostic/semicolon1.C: New test.
        * g++.dg/diagnostic/semicolon10.C: New test.
        * g++.dg/diagnostic/semicolon11.C: New test.
        * g++.dg/diagnostic/semicolon12.C: New test.
        * g++.dg/diagnostic/semicolon13.C: New test.
        * g++.dg/diagnostic/semicolon14.C: New test.
        * g++.dg/diagnostic/semicolon15.C: New test.
        * g++.dg/diagnostic/semicolon16.C: New test.
        * g++.dg/diagnostic/semicolon17.C: New test.
        * g++.dg/diagnostic/semicolon2.C: New test.
        * g++.dg/diagnostic/semicolon3.C: New test.
        * g++.dg/diagnostic/semicolon4.C: New test.
        * g++.dg/diagnostic/semicolon5.C: New test.
        * g++.dg/diagnostic/semicolon6.C: New test.
        * g++.dg/diagnostic/semicolon7.C: New test.
        * g++.dg/diagnostic/semicolon8.C: New test.
        * g++.dg/diagnostic/semicolon9.C: New test.
---
  gcc/c-family/c.opt                            |  2 +-
  gcc/cp/parser.cc                              | 92 +++++++++++++++----
  gcc/doc/invoke.texi                           | 29 +++++-
  gcc/testsuite/g++.dg/diagnostic/semicolon1.C  | 18 ++++
  gcc/testsuite/g++.dg/diagnostic/semicolon10.C | 11 +++
  gcc/testsuite/g++.dg/diagnostic/semicolon11.C | 29 ++++++
  gcc/testsuite/g++.dg/diagnostic/semicolon12.C | 29 ++++++
  gcc/testsuite/g++.dg/diagnostic/semicolon13.C | 29 ++++++
  gcc/testsuite/g++.dg/diagnostic/semicolon14.C | 29 ++++++
  gcc/testsuite/g++.dg/diagnostic/semicolon15.C | 29 ++++++
  gcc/testsuite/g++.dg/diagnostic/semicolon16.C | 38 ++++++++
  gcc/testsuite/g++.dg/diagnostic/semicolon17.C | 29 ++++++
  gcc/testsuite/g++.dg/diagnostic/semicolon2.C  | 18 ++++
  gcc/testsuite/g++.dg/diagnostic/semicolon3.C  | 18 ++++
  gcc/testsuite/g++.dg/diagnostic/semicolon4.C  | 18 ++++
  gcc/testsuite/g++.dg/diagnostic/semicolon5.C  | 18 ++++
  gcc/testsuite/g++.dg/diagnostic/semicolon6.C  | 23 +++++
  gcc/testsuite/g++.dg/diagnostic/semicolon7.C  | 18 ++++
  gcc/testsuite/g++.dg/diagnostic/semicolon8.C  | 11 +++
  gcc/testsuite/g++.dg/diagnostic/semicolon9.C  | 11 +++
  20 files changed, 480 insertions(+), 19 deletions(-)
  create mode 100644 gcc/testsuite/g++.dg/diagnostic/semicolon1.C
  create mode 100644 gcc/testsuite/g++.dg/diagnostic/semicolon10.C
  create mode 100644 gcc/testsuite/g++.dg/diagnostic/semicolon11.C
  create mode 100644 gcc/testsuite/g++.dg/diagnostic/semicolon12.C
  create mode 100644 gcc/testsuite/g++.dg/diagnostic/semicolon13.C
  create mode 100644 gcc/testsuite/g++.dg/diagnostic/semicolon14.C
  create mode 100644 gcc/testsuite/g++.dg/diagnostic/semicolon15.C
  create mode 100644 gcc/testsuite/g++.dg/diagnostic/semicolon16.C
  create mode 100644 gcc/testsuite/g++.dg/diagnostic/semicolon17.C
  create mode 100644 gcc/testsuite/g++.dg/diagnostic/semicolon2.C
  create mode 100644 gcc/testsuite/g++.dg/diagnostic/semicolon3.C
  create mode 100644 gcc/testsuite/g++.dg/diagnostic/semicolon4.C
  create mode 100644 gcc/testsuite/g++.dg/diagnostic/semicolon5.C
  create mode 100644 gcc/testsuite/g++.dg/diagnostic/semicolon6.C
  create mode 100644 gcc/testsuite/g++.dg/diagnostic/semicolon7.C
  create mode 100644 gcc/testsuite/g++.dg/diagnostic/semicolon8.C
  create mode 100644 gcc/testsuite/g++.dg/diagnostic/semicolon9.C

diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
index 403abc1f26e..fb34c3b7031 100644
--- a/gcc/c-family/c.opt
+++ b/gcc/c-family/c.opt
@@ -727,7 +727,7 @@ C ObjC C++ ObjC++ Warning
  ; in common.opt
Wextra-semi
-C++ ObjC++ Var(warn_extra_semi) Warning
+C++ ObjC++ Var(warn_extra_semi) Init(-1) Warning
  Warn about semicolon after in-class function definition.
Wflex-array-member-not-at-end
diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index 7306ce9a8a8..476ddc0d63a 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -15331,6 +15331,61 @@ cp_parser_module_export (cp_parser *parser)
    module_kind = mk;
  }
+/* Used for maybe_warn_extra_semi. */
+
+enum class extra_semi_kind { decl, member, in_class_fn_def };
+
+/* Warn about an extra semicolon.  KIND says in which context the extra
+   semicolon occurs.  */
+
+static void
+maybe_warn_extra_semi (location_t loc, extra_semi_kind kind)
+{
+  /* -Wno-extra-semi suppresses all.  */
+  if (warn_extra_semi == 0)
+    return;
+
+  gcc_rich_location richloc (loc);
+  richloc.add_fixit_remove ();
+
+  switch (kind)
+    {
+    case extra_semi_kind::decl:
+      /* If -Wextra-semi wasn't specified, warn only when -pedantic is in
+        effect in C++98.  DR 569 says that spurious semicolons at namespace
+        scope should be allowed.  */
+      if (pedantic && cxx_dialect < cxx11)
+       pedwarn (&richloc, OPT_Wextra_semi,
+                "extra %<;%> outside of a function only allowed in C++11");
+      else if (warn_extra_semi > 0)
+       warning_at (&richloc, OPT_Wextra_semi,
+                   "extra %<;%> outside of a function");
+      break;
+
+    case extra_semi_kind::member:
+      /* If -Wextra-semi wasn't specified, warn only when -pedantic is in
+        effect in C++98.  DR 1693 added "empty-declaration" to the syntax for
+        "member-declaration".  */
+      if (pedantic && cxx_dialect < cxx11)
+       pedwarn (&richloc, OPT_Wextra_semi,
+                "extra %<;%> inside a struct only allowed in C++11");
+      else if (warn_extra_semi > 0)
+       warning_at (&richloc, OPT_Wextra_semi, "extra %<;%> inside a struct");
+      break;
+
+    case extra_semi_kind::in_class_fn_def:
+      /* A single semicolon is valid after a member function definition
+        so this is just a warning.  */
+      if (warn_extra_semi > 0)
+       warning_at (&richloc, OPT_Wextra_semi,
+                   "extra %<;%> after in-class function definition");
+      break;
+
+    default:
+      gcc_unreachable ();
+    }
+}
+
  /* Declarations [gram.dcl.dcl] */
/* Parse an optional declaration-sequence. TOP_LEVEL is true, if this
@@ -15430,11 +15485,11 @@ cp_parser_declaration (cp_parser* parser, tree 
prefix_attrs)
if (token1->type == CPP_SEMICOLON)
      {
-      cp_lexer_consume_token (parser->lexer);
+      location_t semicolon_loc
+       = cp_lexer_consume_token (parser->lexer)->location;
        /* A declaration consisting of a single semicolon is invalid
-       * before C++11.  Allow it unless we're being pedantic.  */
-      if (cxx_dialect < cxx11)
-       pedwarn (input_location, OPT_Wpedantic, "extra %<;%>");
+        before C++11.  Allow it unless we're being pedantic.  */
+      maybe_warn_extra_semi (semicolon_loc, extra_semi_kind::decl);
        return;
      }
    else if (cp_lexer_nth_token_is (parser->lexer,
@@ -28121,19 +28176,25 @@ cp_parser_member_declaration (cp_parser* parser)
struct S { ; }; - [class.mem]
+        [class.mem] used to say
Each member-declaration shall declare at least one member
-        name of the class.  */
+        name of the class.
+
+        but since DR 1693:
+
+        A member-declaration does not declare new members of the class
+        if it is
+        -- [...]
+        -- an empty-declaration.
+        For any other member-declaration, each declared entity that is not
+        an unnamed bit-field is a member of the class, and each such
+        member-declaration shall either declare at least one member name of
+        the class or declare at least one unnamed bit-field.  */
        if (!decl_specifiers.any_specifiers_p)
        {
          cp_token *token = cp_lexer_peek_token (parser->lexer);
-         if (cxx_dialect < cxx11 && !in_system_header_at (token->location))
-           {
-             gcc_rich_location richloc (token->location);
-             richloc.add_fixit_remove ();
-             pedwarn (&richloc, OPT_Wpedantic, "extra %<;%>");
-           }
+         maybe_warn_extra_semi (token->location, extra_semi_kind::member);
        }
        else
        {
@@ -28564,11 +28625,8 @@ cp_parser_member_declaration (cp_parser* parser)
                    {
                      location_t semicolon_loc
                        = cp_lexer_consume_token (parser->lexer)->location;
-                     gcc_rich_location richloc (semicolon_loc);
-                     richloc.add_fixit_remove ();
-                     warning_at (&richloc, OPT_Wextra_semi,
-                                 "extra %<;%> after in-class "
-                                 "function definition");
+                     maybe_warn_extra_semi (semicolon_loc,
+                                            extra_semi_kind::in_class_fn_def);
                    }
                  goto out;
                }
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index ddcd5213f06..cedc1a28c83 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -4780,7 +4780,34 @@ undefined behavior at runtime.  This warning is enabled 
by default.
  @opindex Wextra-semi
  @opindex Wno-extra-semi
  @item -Wextra-semi @r{(C++, Objective-C++ only)}
-Warn about redundant semicolons after in-class function definitions.
+Warn about redundant semicolons.  There are various contexts in which an extra
+semicolon can occur.  One is a semicolon after in-class function definitions,
+which is valid in all C++ dialects (and is never a pedwarn):
+
+@smallexample
+struct S @{
+  void foo () @{@};
+@};
+@end smallexample
+
+Another is an extra semicolon at namespace scope, which has been allowed
+since C++11 (therefore is a pedwarn in C++98):
+
+@smallexample
+struct S @{
+@};
+;
+@end smallexample
+
+And yet another is an extra semicolon in class definitions, which has been
+allowed since C++11 (therefore is a pedwarn in C++98):
+
+@smallexample
+struct S @{
+  int a;
+  ;
+@};
+@end smallexample
@opindex Wno-global-module
  @opindex Wglobal-module
diff --git a/gcc/testsuite/g++.dg/diagnostic/semicolon1.C 
b/gcc/testsuite/g++.dg/diagnostic/semicolon1.C
new file mode 100644
index 00000000000..8219d488f4d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/diagnostic/semicolon1.C
@@ -0,0 +1,18 @@
+// DR 1693, Superfluous semicolons in class definitions
+// PR c++/113760
+// { dg-do compile }
+// { dg-options "" }
+// { dg-prune-output "only available with" }
+
+struct X { ; };
+
+struct S {
+  void baz () = delete;
+  void qux () = delete;
+  ;
+  void corge () = delete;
+  ;
+  ;
+  int s;
+  ;
+};
diff --git a/gcc/testsuite/g++.dg/diagnostic/semicolon10.C 
b/gcc/testsuite/g++.dg/diagnostic/semicolon10.C
new file mode 100644
index 00000000000..4753f557453
--- /dev/null
+++ b/gcc/testsuite/g++.dg/diagnostic/semicolon10.C
@@ -0,0 +1,11 @@
+// PR c++/113760
+// { dg-do compile }
+// { dg-options "-Wextra-semi" }
+
+struct S {
+  void f1 () {}
+  // A single semicolon is valid after a member function definition.
+  void f2 () {}; // { dg-warning "extra .;. after in-class function 
definition" }
+  void f3 () const;
+};
+void S::f3 () const { }; // { dg-warning "extra .;. outside of a function" }
diff --git a/gcc/testsuite/g++.dg/diagnostic/semicolon11.C 
b/gcc/testsuite/g++.dg/diagnostic/semicolon11.C
new file mode 100644
index 00000000000..65df5e9abe6
--- /dev/null
+++ b/gcc/testsuite/g++.dg/diagnostic/semicolon11.C
@@ -0,0 +1,29 @@
+// DR 569, Spurious semicolons at namespace scope should be allowed
+// PR c++/113760
+// { dg-options "-pedantic-errors" }
+
+// C++11 allows extra semicolons at namespace scope.
+struct S {
+  void foo();
+};
+;                      // { dg-error "extra .;. outside of a function" "" { 
target c++98_only } }
+
+void S::foo () {
+};                     // { dg-error "extra .;. outside of a function" "" { 
target c++98_only } }
+;                      // { dg-error "extra .;. outside of a function" "" { 
target c++98_only } }
+
+namespace N {
+};                     // { dg-error "extra .;. outside of a function" "" { 
target c++98_only } }
+;                      // { dg-error "extra .;. outside of a function" "" { 
target c++98_only } }
+
+void f();
+;                      // { dg-error "extra .;. outside of a function" "" { 
target c++98_only } }
+
+void
+f ()
+{
+};                     // { dg-error "extra .;. outside of a function" "" { 
target c++98_only } }
+;                      // { dg-error "extra .;. outside of a function" "" { 
target c++98_only } }
+
+int x;
+;                      // { dg-error "extra .;. outside of a function" "" { 
target c++98_only } }
diff --git a/gcc/testsuite/g++.dg/diagnostic/semicolon12.C 
b/gcc/testsuite/g++.dg/diagnostic/semicolon12.C
new file mode 100644
index 00000000000..f3e79f80bf0
--- /dev/null
+++ b/gcc/testsuite/g++.dg/diagnostic/semicolon12.C
@@ -0,0 +1,29 @@
+// DR 569, Spurious semicolons at namespace scope should be allowed
+// PR c++/113760
+// { dg-options "" }
+
+// C++11 allows extra semicolons at namespace scope.
+struct S {
+  void foo();
+};
+;
+
+void S::foo () {
+};
+;
+
+namespace N {
+};
+;
+
+void f();
+;
+
+void
+f ()
+{
+};
+;
+
+int x;
+;
diff --git a/gcc/testsuite/g++.dg/diagnostic/semicolon13.C 
b/gcc/testsuite/g++.dg/diagnostic/semicolon13.C
new file mode 100644
index 00000000000..c7a41202347
--- /dev/null
+++ b/gcc/testsuite/g++.dg/diagnostic/semicolon13.C
@@ -0,0 +1,29 @@
+// DR 569, Spurious semicolons at namespace scope should be allowed
+// PR c++/113760
+// { dg-options "-Wpedantic" }
+
+// C++11 allows extra semicolons at namespace scope.
+struct S {
+  void foo();
+};
+;                      // { dg-warning "extra .;. outside of a function" "" { 
target c++98_only } }
+
+void S::foo () {
+};                     // { dg-warning "extra .;. outside of a function" "" { 
target c++98_only } }
+;                      // { dg-warning "extra .;. outside of a function" "" { 
target c++98_only } }
+
+namespace N {
+};                     // { dg-warning "extra .;. outside of a function" "" { 
target c++98_only } }
+;                      // { dg-warning "extra .;. outside of a function" "" { 
target c++98_only } }
+
+void f();
+;                      // { dg-warning "extra .;. outside of a function" "" { 
target c++98_only } }
+
+void
+f ()
+{
+};                     // { dg-warning "extra .;. outside of a function" "" { 
target c++98_only } }
+;                      // { dg-warning "extra .;. outside of a function" "" { 
target c++98_only } }
+
+int x;
+;                      // { dg-warning "extra .;. outside of a function" "" { 
target c++98_only } }
diff --git a/gcc/testsuite/g++.dg/diagnostic/semicolon14.C 
b/gcc/testsuite/g++.dg/diagnostic/semicolon14.C
new file mode 100644
index 00000000000..ac2b985f3a3
--- /dev/null
+++ b/gcc/testsuite/g++.dg/diagnostic/semicolon14.C
@@ -0,0 +1,29 @@
+// DR 569, Spurious semicolons at namespace scope should be allowed
+// PR c++/113760
+// { dg-options "-pedantic-errors -Wno-extra-semi" }
+
+// C++11 allows extra semicolons at namespace scope.
+struct S {
+  void foo();
+};
+;
+
+void S::foo () {
+};
+;
+
+namespace N {
+};
+;
+
+void f();
+;
+
+void
+f ()
+{
+};
+;
+
+int x;
+;
diff --git a/gcc/testsuite/g++.dg/diagnostic/semicolon15.C 
b/gcc/testsuite/g++.dg/diagnostic/semicolon15.C
new file mode 100644
index 00000000000..84b90e4ea35
--- /dev/null
+++ b/gcc/testsuite/g++.dg/diagnostic/semicolon15.C
@@ -0,0 +1,29 @@
+// DR 569, Spurious semicolons at namespace scope should be allowed
+// PR c++/113760
+// { dg-options "-Wextra-semi" }
+
+// C++11 allows extra semicolons at namespace scope.
+struct S {
+  void foo();
+};
+;                      // { dg-warning "extra .;. outside of a function" }
+
+void S::foo () {
+};                     // { dg-warning "extra .;. outside of a function" }
+;                      // { dg-warning "extra .;. outside of a function" }
+
+namespace N {
+};                     // { dg-warning "extra .;. outside of a function" }
+;                      // { dg-warning "extra .;. outside of a function" }
+
+void f();
+;                      // { dg-warning "extra .;. outside of a function" }
+
+void
+f ()
+{
+};                     // { dg-warning "extra .;. outside of a function" }
+;                      // { dg-warning "extra .;. outside of a function" }
+
+int x;
+;                      // { dg-warning "extra .;. outside of a function" }
diff --git a/gcc/testsuite/g++.dg/diagnostic/semicolon16.C 
b/gcc/testsuite/g++.dg/diagnostic/semicolon16.C
new file mode 100644
index 00000000000..26259cae552
--- /dev/null
+++ b/gcc/testsuite/g++.dg/diagnostic/semicolon16.C
@@ -0,0 +1,38 @@
+// DR 569, Spurious semicolons at namespace scope should be allowed
+// PR c++/113760
+// { dg-options "-Wextra-semi -pedantic-errors" }
+
+// C++11 allows extra semicolons at namespace scope.
+struct S {
+  void foo();
+};
+;                      // { dg-warning "extra .;. outside of a function" "" { 
target c++11 } }
+                       // { dg-error "extra .;. outside of a function" "" { 
target c++98_only } .-1 }
+
+void S::foo () {
+};                     // { dg-warning "extra .;. outside of a function" "" { 
target c++11 } }
+                       // { dg-error "extra .;. outside of a function" "" { 
target c++98_only } .-1 }
+;                      // { dg-warning "extra .;. outside of a function" "" { 
target c++11 } }
+                       // { dg-error "extra .;. outside of a function" "" { 
target c++98_only } .-1 }
+
+namespace N {
+};                     // { dg-warning "extra .;. outside of a function" "" { 
target c++11 } }
+                       // { dg-error "extra .;. outside of a function" "" { 
target c++98_only } .-1 }
+;                      // { dg-warning "extra .;. outside of a function" "" { 
target c++11 } }
+                       // { dg-error "extra .;. outside of a function" "" { 
target c++98_only } .-1 }
+
+void f();
+;                      // { dg-warning "extra .;. outside of a function" "" { 
target c++11 } }
+                       // { dg-error "extra .;. outside of a function" "" { 
target c++98_only } .-1 }
+
+void
+f ()
+{
+};                     // { dg-warning "extra .;. outside of a function" "" { 
target c++11 } }
+                       // { dg-error "extra .;. outside of a function" "" { 
target c++98_only } .-1 }
+;                      // { dg-warning "extra .;. outside of a function" "" { 
target c++11 } }
+                       // { dg-error "extra .;. outside of a function" "" { 
target c++98_only } .-1 }
+
+int x;
+;                      // { dg-warning "extra .;. outside of a function" "" { 
target c++11 } }
+                       // { dg-error "extra .;. outside of a function" "" { 
target c++98_only } .-1 }
diff --git a/gcc/testsuite/g++.dg/diagnostic/semicolon17.C 
b/gcc/testsuite/g++.dg/diagnostic/semicolon17.C
new file mode 100644
index 00000000000..0b8d3f006e5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/diagnostic/semicolon17.C
@@ -0,0 +1,29 @@
+// DR 569, Spurious semicolons at namespace scope should be allowed
+// PR c++/113760
+// { dg-options "-pedantic-errors -Wno-error=extra-semi" }
+
+// C++11 allows extra semicolons at namespace scope.
+struct S {
+  void foo();
+};
+;                      // { dg-warning "extra .;. outside of a function" "" { 
target c++98_only } }
+
+void S::foo () {
+};                     // { dg-warning "extra .;. outside of a function" "" { 
target c++98_only } }
+;                      // { dg-warning "extra .;. outside of a function" "" { 
target c++98_only } }
+
+namespace N {
+};                     // { dg-warning "extra .;. outside of a function" "" { 
target c++98_only } }
+;                      // { dg-warning "extra .;. outside of a function" "" { 
target c++98_only } }
+
+void f();
+;                      // { dg-warning "extra .;. outside of a function" "" { 
target c++98_only } }
+
+void
+f ()
+{
+};                     // { dg-warning "extra .;. outside of a function" "" { 
target c++98_only } }
+;                      // { dg-warning "extra .;. outside of a function" "" { 
target c++98_only } }
+
+int x;
+;                      // { dg-warning "extra .;. outside of a function" "" { 
target c++98_only } }
diff --git a/gcc/testsuite/g++.dg/diagnostic/semicolon2.C 
b/gcc/testsuite/g++.dg/diagnostic/semicolon2.C
new file mode 100644
index 00000000000..1cfddf17e9d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/diagnostic/semicolon2.C
@@ -0,0 +1,18 @@
+// DR 1693, Superfluous semicolons in class definitions
+// PR c++/113760
+// { dg-do compile }
+// { dg-options "-Wpedantic" }
+// { dg-prune-output "only available with" }
+
+struct X { ; };                      // { dg-warning "extra .;. inside a struct" 
"" { target c++98_only } }
+
+struct S {
+  void baz () = delete;
+  void qux () = delete;
+  ;                          // { dg-warning "extra .;. inside a struct" "" { 
target c++98_only } }
+  void corge () = delete;
+  ;                          // { dg-warning "extra .;. inside a struct" "" { 
target c++98_only } }
+  ;                          // { dg-warning "extra .;. inside a struct" "" { 
target c++98_only } }
+  int s;
+  ;                          // { dg-warning "extra .;. inside a struct" "" { 
target c++98_only } }
+};
diff --git a/gcc/testsuite/g++.dg/diagnostic/semicolon3.C 
b/gcc/testsuite/g++.dg/diagnostic/semicolon3.C
new file mode 100644
index 00000000000..265b655a8fb
--- /dev/null
+++ b/gcc/testsuite/g++.dg/diagnostic/semicolon3.C
@@ -0,0 +1,18 @@
+// DR 1693, Superfluous semicolons in class definitions
+// PR c++/113760
+// { dg-do compile }
+// { dg-options "-pedantic-errors" }
+// { dg-prune-output "only available with" }
+
+struct X { ; };                      // { dg-error "extra .;. inside a struct" 
"" { target c++98_only } }
+
+struct S {
+  void baz () = delete;
+  void qux () = delete;
+  ;                          // { dg-error "extra .;. inside a struct" "" { 
target c++98_only } }
+  void corge () = delete;
+  ;                          // { dg-error "extra .;. inside a struct" "" { 
target c++98_only } }
+  ;                          // { dg-error "extra .;. inside a struct" "" { 
target c++98_only } }
+  int s;
+  ;                          // { dg-error "extra .;. inside a struct" "" { 
target c++98_only } }
+};
diff --git a/gcc/testsuite/g++.dg/diagnostic/semicolon4.C 
b/gcc/testsuite/g++.dg/diagnostic/semicolon4.C
new file mode 100644
index 00000000000..22f7a539aed
--- /dev/null
+++ b/gcc/testsuite/g++.dg/diagnostic/semicolon4.C
@@ -0,0 +1,18 @@
+// DR 1693, Superfluous semicolons in class definitions
+// PR c++/113760
+// { dg-do compile }
+// { dg-options "-pedantic-errors -Wno-extra-semi" }
+// { dg-prune-output "only available with" }
+
+struct X { ; };
+
+struct S {
+  void baz () = delete;
+  void qux () = delete;
+  ;
+  void corge () = delete;
+  ;
+  ;
+  int s;
+  ;
+};
diff --git a/gcc/testsuite/g++.dg/diagnostic/semicolon5.C 
b/gcc/testsuite/g++.dg/diagnostic/semicolon5.C
new file mode 100644
index 00000000000..41b7bfa2ed8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/diagnostic/semicolon5.C
@@ -0,0 +1,18 @@
+// DR 1693, Superfluous semicolons in class definitions
+// PR c++/113760
+// { dg-do compile }
+// { dg-options "-Wextra-semi" }
+// { dg-prune-output "only available with" }
+
+struct X { ; };                      // { dg-warning "extra .;. inside a 
struct" }
+
+struct S {
+  void baz () = delete;
+  void qux () = delete;
+  ;                          // { dg-warning "extra .;. inside a struct" }
+  void corge () = delete;
+  ;                          // { dg-warning "extra .;. inside a struct" }
+  ;                          // { dg-warning "extra .;. inside a struct" }
+  int s;
+  ;                          // { dg-warning "extra .;. inside a struct" }
+};
diff --git a/gcc/testsuite/g++.dg/diagnostic/semicolon6.C 
b/gcc/testsuite/g++.dg/diagnostic/semicolon6.C
new file mode 100644
index 00000000000..0c92a1e9523
--- /dev/null
+++ b/gcc/testsuite/g++.dg/diagnostic/semicolon6.C
@@ -0,0 +1,23 @@
+// DR 1693, Superfluous semicolons in class definitions
+// PR c++/113760
+// { dg-do compile }
+// { dg-options "-Wextra-semi -pedantic-errors" }
+// { dg-prune-output "only available with" }
+
+struct X { ; };                      // { dg-warning "extra .;. inside a struct" 
"" { target c++11 } }
+                             // { dg-error "extra .;. inside a struct" "" { 
target c++98_only } .-1 }
+
+struct S {
+  void baz () = delete;
+  void qux () = delete;
+  ;                          // { dg-warning "extra .;. inside a struct" "" { 
target c++11 } }
+                             // { dg-error "extra .;. inside a struct" "" { 
target c++98_only } .-1 }
+  void corge () = delete;
+  ;                          // { dg-warning "extra .;. inside a struct" "" { 
target c++11 } }
+                             // { dg-error "extra .;. inside a struct" "" { 
target c++98_only } .-1 }
+  ;                          // { dg-warning "extra .;. inside a struct" "" { 
target c++11 } }
+                             // { dg-error "extra .;. inside a struct" "" { 
target c++98_only } .-1 }
+  int s;
+  ;                          // { dg-warning "extra .;. inside a struct" "" { 
target c++11 } }
+                             // { dg-error "extra .;. inside a struct" "" { 
target c++98_only } .-1 }
+};
diff --git a/gcc/testsuite/g++.dg/diagnostic/semicolon7.C 
b/gcc/testsuite/g++.dg/diagnostic/semicolon7.C
new file mode 100644
index 00000000000..aca4f49785d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/diagnostic/semicolon7.C
@@ -0,0 +1,18 @@
+// DR 1693, Superfluous semicolons in class definitions
+// PR c++/113760
+// { dg-do compile }
+// { dg-options "-pedantic-errors -Wno-error=extra-semi" }
+// { dg-prune-output "only available with" }
+
+struct X { ; };                      // { dg-warning "extra .;. inside a struct" 
"" { target c++98_only } }
+
+struct S {
+  void baz () = delete;
+  void qux () = delete;
+  ;                          // { dg-warning "extra .;. inside a struct" "" { 
target c++98_only } }
+  void corge () = delete;
+  ;                          // { dg-warning "extra .;. inside a struct" "" { 
target c++98_only } }
+  ;                          // { dg-warning "extra .;. inside a struct" "" { 
target c++98_only } }
+  int s;
+  ;                          // { dg-warning "extra .;. inside a struct" "" { 
target c++98_only } }
+};
diff --git a/gcc/testsuite/g++.dg/diagnostic/semicolon8.C 
b/gcc/testsuite/g++.dg/diagnostic/semicolon8.C
new file mode 100644
index 00000000000..1b0de384dbf
--- /dev/null
+++ b/gcc/testsuite/g++.dg/diagnostic/semicolon8.C
@@ -0,0 +1,11 @@
+// PR c++/113760
+// { dg-do compile }
+// { dg-options "-pedantic-errors" }
+
+struct S {
+  void f1 () {}
+  // A single semicolon is valid after a member function definition.
+  void f2 () {};
+  void f3 () const;
+};
+void S::f3 () const { }; // { dg-error "extra .;. outside of a function" "" { 
target c++98_only } }
diff --git a/gcc/testsuite/g++.dg/diagnostic/semicolon9.C 
b/gcc/testsuite/g++.dg/diagnostic/semicolon9.C
new file mode 100644
index 00000000000..f90539d3bd7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/diagnostic/semicolon9.C
@@ -0,0 +1,11 @@
+// PR c++/113760
+// { dg-do compile }
+// { dg-options "-pedantic-errors -Wno-extra-semi" }
+
+struct S {
+  void f1 () {}
+  // A single semicolon is valid after a member function definition.
+  void f2 () {};
+  void f3 () const;
+};
+void S::f3 () const { };

base-commit: 54ba8d44bbd703bca6984700b4d6f978890097e2


Reply via email to