return type;
}
+/* Parse an (optional) class-property-specifier-seq.
+
+ class-property-specifier-seq:
+ class-property-specifier class-property-specifier-seq [opt]
+
+ class-property-specifier:
+ final
+
+ Returns a bitmask representing the class-property-specifiers. */
+
+static cp_virt_specifiers
+cp_parser_class_property_specifier_seq_opt (cp_parser *parser)
+{
+ cp_virt_specifiers virt_specifiers = VIRT_SPEC_UNSPECIFIED;
+
+ while (true)
+ {
+ cp_token *token;
+ cp_virt_specifiers virt_specifier;
+
+ /* Peek at the next token. */
+ token = cp_lexer_peek_token (parser->lexer);
+ /* See if it's a class-property-specifier. */
+ if (token->type != CPP_NAME)
+ break;
+ if (id_equal (token->u.value, "final"))
+ {
+ maybe_warn_cpp0x (CPP0X_OVERRIDE_CONTROLS);
+ virt_specifier = VIRT_SPEC_FINAL;
+ }
+ else if (id_equal (token->u.value, "__final"))
+ virt_specifier = VIRT_SPEC_FINAL;
+ else
+ break;
+
+ if (virt_specifiers & virt_specifier)
+ {
+ gcc_rich_location richloc (token->location);
+ richloc.add_fixit_remove ();
+ error_at (&richloc, "duplicate %qD specifier", token->u.value);
+ cp_lexer_purge_token (parser->lexer);
+ }
+ else
+ {
+ cp_lexer_consume_token (parser->lexer);
+ virt_specifiers |= virt_specifier;
+ }
+ }
+ return virt_specifiers;
+}
+
/* Parse a class-head.
class-head:
pop_deferring_access_checks ();
if (id)
- {
- cp_parser_check_for_invalid_template_id (parser, id,
- class_key,
- type_start_token->location);
- }
- virt_specifiers = cp_parser_virt_specifier_seq_opt (parser);
+ cp_parser_check_for_invalid_template_id (parser, id,
+ class_key,
+ type_start_token->location);
+ virt_specifiers = cp_parser_class_property_specifier_seq_opt (parser);
/* If it's not a `:' or a `{' then we can't really be looking at a
class-head, since a class-head only appears as part of a
/* At this point, we're going ahead with the class-specifier, even
if some other problem occurs. */
cp_parser_commit_to_tentative_parse (parser);
- if (virt_specifiers & VIRT_SPEC_OVERRIDE)
- {
- cp_parser_error (parser,
- "cannot specify %<override%> for a class");
- type = error_mark_node;
- goto out;
- }
/* Issue the error about the overly-qualified name now. */
if (qualified_p)
{
struct D6 : B4<D6> {}; // { dg-error "cannot derive from 'final' base" }
-struct B6 final final {}; // { dg-error "duplicate virt-specifier" }
+struct B6 final final {}; // { dg-error "duplicate 'final' specifier" }
-struct B7 override {}; // { dg-error "cannot specify 'override' for a class" }
+struct B7 override {}; // { dg-error "variable 'B7 override' has initializer but incomplete type" }
namespace N
{
struct B2 final; // { dg-error "redeclaration" }
struct B2 override; // { dg-message "previously declared here" }
struct B2 final {}; // { dg-error "redefinition" }
- struct B2 override {}; // { dg-error "cannot specify 'override' for a class" }
+ struct B2 override {}; // { dg-error "redeclaration of 'main\\\(\\\)::B2 override'" }
B2 override{}; // { dg-error "redeclaration" }
struct foo final {}; // { dg-message "previous definition" }
struct foo final {}; // { dg-error "redefinition" }
--- /dev/null
+// PR c++/120569
+// { dg-do compile }
+// { dg-options "" }
+// { dg-additional-options "-pedantic" { target c++14 } }
+
+namespace U {
+ struct A {};
+ struct A override {}; // { dg-warning "extended initializer lists only available with" "" { target c++98_only } }
+}
+namespace V {
+ template <int N>
+ struct B {};
+ template <int N>
+ struct B<N> override {}; // { dg-warning "extended initializer lists only available with" "" { target c++98_only } }
+} // { dg-warning "variable templates only available with" "" { target c++11_down } .-1 }
+struct C {
+ struct D {};
+ struct D override {}; // { dg-warning "extended initializer lists only available with" "" { target c++98_only } }
+}; // { dg-warning "non-static data member initializers only available with" "" { target c++98_only } .-1 }
+namespace W {
+ struct E { struct F {}; };
+ struct E::F override {}; // { dg-warning "extended initializer lists only available with" "" { target c++98_only } }
+}
+template <int N>
+struct V::B<N> override {}; // { dg-warning "extended initializer lists only available with" "" { target c++98_only } }
+ // { dg-warning "variable templates only available with" "" { target c++11_down } .-1 }