diff mbox series

c++: DR 569, DR 1693: fun with semicolons [PR113760]

Message ID 20240213192411.56178-1-polacek@redhat.com
State New
Headers show
Series c++: DR 569, DR 1693: fun with semicolons [PR113760] | expand

Commit Message

Marek Polacek Feb. 13, 2024, 7:24 p.m. UTC
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


base-commit: f4935df217ad89f884f908f39086b322e80123d0

Comments

Jakub Jelinek Feb. 13, 2024, 7:38 p.m. UTC | #1
On Tue, Feb 13, 2024 at 02:24:11PM -0500, Marek Polacek wrote:
> Sadly, I must admit this is looking like GCC 15 material.

If deferred for GCC 15, can't we at least do some minimal
change and just guard the member pedwarn with cxx_dialect < something?
Given that -Wextra-semi isn't on by default nor included in
-Wall -W, I think even accepting this for GCC 14 wouldn't be that
risky.

Jason's decision.

+      /* 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)                                                                                                                                      

If it was a DR, did it apply just to C++14 or changed C++11 as well?

	Jakub
Marek Polacek Feb. 13, 2024, 7:43 p.m. UTC | #2
On Tue, Feb 13, 2024 at 08:38:18PM +0100, Jakub Jelinek wrote:
> On Tue, Feb 13, 2024 at 02:24:11PM -0500, Marek Polacek wrote:
> > Sadly, I must admit this is looking like GCC 15 material.
> 
> If deferred for GCC 15, can't we at least do some minimal
> change and just guard the member pedwarn with cxx_dialect < something?

I could do something like that, but...

> Given that -Wextra-semi isn't on by default nor included in
> -Wall -W, I think even accepting this for GCC 14 wouldn't be that
> risky.

...I also don't think it's that risky but technically, it's not
a regression I think.
 
> Jason's decision.
> 
> +      /* 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)                                                                                                                                      
> 
> If it was a DR, did it apply just to C++14 or changed C++11 as well?

It's got Status: C++14 so I thought that C++11/C++98 had not been
adjusted. 

Marek
Marek Polacek Feb. 13, 2024, 8:38 p.m. UTC | #3
On Tue, Feb 13, 2024 at 02:43:39PM -0500, Marek Polacek wrote:
> On Tue, Feb 13, 2024 at 08:38:18PM +0100, Jakub Jelinek wrote:
> > On Tue, Feb 13, 2024 at 02:24:11PM -0500, Marek Polacek wrote:
> > > Sadly, I must admit this is looking like GCC 15 material.
> > 
> > If deferred for GCC 15, can't we at least do some minimal
> > change and just guard the member pedwarn with cxx_dialect < something?
> 
> I could do something like that, but...
> 
> > Given that -Wextra-semi isn't on by default nor included in
> > -Wall -W, I think even accepting this for GCC 14 wouldn't be that
> > risky.
> 
> ...I also don't think it's that risky but technically, it's not
> a regression I think.
>  
> > Jason's decision.
> > 
> > +      /* 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)                                                                                                                                      
> > 
> > If it was a DR, did it apply just to C++14 or changed C++11 as well?
> 
> It's got Status: C++14 so I thought that C++11/C++98 had not been
> adjusted. 

...but then so was DR 1601 which I implemented in 
https://gcc.gnu.org/git/?p=gcc.git&a=commit;h=e295e3d981355c61b72eca2ee58864958655cc31
and made it apply to C++11 as well.

So I'm starting to lean towards adjusting this patch to
make DR 1693 apply to C++11 as well, but not C++98.  Probably
not a very important distinction in practice though.

Marek
Jason Merrill Feb. 13, 2024, 8:41 p.m. UTC | #4
On 2/13/24 14:43, Marek Polacek wrote:
> On Tue, Feb 13, 2024 at 08:38:18PM +0100, Jakub Jelinek wrote:
>> On Tue, Feb 13, 2024 at 02:24:11PM -0500, Marek Polacek wrote:
>>> Sadly, I must admit this is looking like GCC 15 material.
>>
>> If deferred for GCC 15, can't we at least do some minimal
>> change and just guard the member pedwarn with cxx_dialect < something?
> 
> I could do something like that, but...
> 
>> Given that -Wextra-semi isn't on by default nor included in
>> -Wall -W, I think even accepting this for GCC 14 wouldn't be that
>> risky.
> 
> ...I also don't think it's that risky but technically, it's not
> a regression I think.
>   
>> Jason's decision.
>>
>> +      /* 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)
>>
>> If it was a DR, did it apply just to C++14 or changed C++11 as well?
> 
> It's got Status: C++14 so I thought that C++11/C++98 had not been
> adjusted.

That's just the timeframe it was accepted in; below that it says "moved 
to DR" which usually means it applies to earlier standards, whereas 
"accepted" or "applied to WP" do not.

For 14 let's go with the minimal change Jakub suggests.

Jason
Marek Polacek Feb. 13, 2024, 8:52 p.m. UTC | #5
On Tue, Feb 13, 2024 at 03:41:53PM -0500, Jason Merrill wrote:
> On 2/13/24 14:43, Marek Polacek wrote:
> > On Tue, Feb 13, 2024 at 08:38:18PM +0100, Jakub Jelinek wrote:
> > > On Tue, Feb 13, 2024 at 02:24:11PM -0500, Marek Polacek wrote:
> > > > Sadly, I must admit this is looking like GCC 15 material.
> > > 
> > > If deferred for GCC 15, can't we at least do some minimal
> > > change and just guard the member pedwarn with cxx_dialect < something?
> > 
> > I could do something like that, but...
> > 
> > > Given that -Wextra-semi isn't on by default nor included in
> > > -Wall -W, I think even accepting this for GCC 14 wouldn't be that
> > > risky.
> > 
> > ...I also don't think it's that risky but technically, it's not
> > a regression I think.
> > > Jason's decision.
> > > 
> > > +      /* 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)
> > > 
> > > If it was a DR, did it apply just to C++14 or changed C++11 as well?
> > 
> > It's got Status: C++14 so I thought that C++11/C++98 had not been
> > adjusted.
> 
> That's just the timeframe it was accepted in; below that it says "moved to
> DR" which usually means it applies to earlier standards, whereas "accepted"
> or "applied to WP" do not.
> 
> For 14 let's go with the minimal change Jakub suggests.

Okay.  Do we want to pedwarn about the extra ; here

  struct S {
    int a;;
  };

only in C++98 or C++11 too?

Marek
Jason Merrill Feb. 13, 2024, 10:58 p.m. UTC | #6
On 2/13/24 15:52, Marek Polacek wrote:
> On Tue, Feb 13, 2024 at 03:41:53PM -0500, Jason Merrill wrote:
>> On 2/13/24 14:43, Marek Polacek wrote:
>>> On Tue, Feb 13, 2024 at 08:38:18PM +0100, Jakub Jelinek wrote:
>>>> On Tue, Feb 13, 2024 at 02:24:11PM -0500, Marek Polacek wrote:
>>>>> Sadly, I must admit this is looking like GCC 15 material.
>>>>
>>>> If deferred for GCC 15, can't we at least do some minimal
>>>> change and just guard the member pedwarn with cxx_dialect < something?
>>>
>>> I could do something like that, but...
>>>
>>>> Given that -Wextra-semi isn't on by default nor included in
>>>> -Wall -W, I think even accepting this for GCC 14 wouldn't be that
>>>> risky.
>>>
>>> ...I also don't think it's that risky but technically, it's not
>>> a regression I think.
>>>> Jason's decision.
>>>>
>>>> +      /* 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)
>>>>
>>>> If it was a DR, did it apply just to C++14 or changed C++11 as well?
>>>
>>> It's got Status: C++14 so I thought that C++11/C++98 had not been
>>> adjusted.
>>
>> That's just the timeframe it was accepted in; below that it says "moved to
>> DR" which usually means it applies to earlier standards, whereas "accepted"
>> or "applied to WP" do not.
>>
>> For 14 let's go with the minimal change Jakub suggests.
> 
> Okay.  Do we want to pedwarn about the extra ; here
> 
>    struct S {
>      int a;;
>    };
> 
> only in C++98 or C++11 too?

Only in 98, I think.

Jason
diff mbox series

Patch

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