@@ -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
@@ -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;
}
@@ -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
new file mode 100644
@@ -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;
+ ;
+};
new file mode 100644
@@ -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" }
new file mode 100644
@@ -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 } }
new file mode 100644
@@ -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;
+;
new file mode 100644
@@ -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 } }
new file mode 100644
@@ -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;
+;
new file mode 100644
@@ -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" }
new file mode 100644
@@ -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" }
new file mode 100644
@@ -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 } }
new file mode 100644
@@ -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 } }
+};
new file mode 100644
@@ -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 } }
+};
new file mode 100644
@@ -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;
+ ;
+};
new file mode 100644
@@ -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" }
+};
new file mode 100644
@@ -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" }
+};
new file mode 100644
@@ -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 } }
+};
new file mode 100644
@@ -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 } }
new file mode 100644
@@ -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 { };
@@ -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 .;." } */
@@ -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 } }
};
@@ -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
};