The wording below also address core issue 1065 "[[hiding]] with [[override]]".
Drafting notes: There is an ambiguity when parsing supposedly unnamed classes: "struct final { ... } * p" might define an unnamed final class, or it might define a class called "final". When resolving any ambiguity towards "identifier", unnamed classes can't ever be "final".
Add a new paragraph after 2.11 lex.name paragraph 1:
(追記) Some identifiers have a special meaning when appearing in a certain context (see table X).Remove section 7.6.4 dcl.attr.final:When referred to in the grammar, these identifiers are used explicitly rather than using the identifier grammar production. Any ambiguity whether a given identifier has a special meaning or not is resolved to interpret the token as a regular identifier. (追記ここまで)
Identifiers with special meaning override final
Remove in 7.6.5 dcl.attr.override:(削除) The attribute-tokenfinal
specifies derivation semantics for a class and overriding semantics for a virtual function. It shall appear at most once in each attribute-list and no attribute-argument-clause shall be present. The attribute may be applied to class definitions and to virtual member functions being declared in a class definition. (削除ここまで)
(削除) If a class B is marked final and a class D is derived from B the program is ill formed. (削除ここまで)
(削除) If a virtual member function f in some class B is marked final and in a class D derived from B a function D::f overrides B::f, the program is ill-formed. (削除ここまで)
(削除) [ Example: ... ] (削除ここまで)
Change the grammar in 9 class and the following sentence:(削除) The attribute-tokenoverride
asserts that a virtual member function overrides a function in a base class. It shall appear at most once in each attribute-list and no attribute-argument-clause shall be present. The attribute may be applied to virtual member functions being declared in a class definition. (削除ここまで)
(削除) If a virtual member function f is marked override and does not override (10.3 class virtual) a member function of a base class the program is ill-formed. (削除ここまで)
(削除) The attribute-tokenhiding
asserts that a class member name hides a name in a base class. It shall appear at most once in each attribute-list and no attribute-argument-clause shall be present. The attribute may be applied to class members being declared in a class definition. (削除ここまで)
(削除) If a class member is markedhiding
and its name does not hide (3.3.10 basic.scope.hiding, 10.2 class.member.lookup) a class member name in a base class the program is ill-formed. (削除ここまで)
(削除) The attribute-tokenbase_check
specifies that overriding and hiding of base members is strictly checked within a class. It shall appear at most once in each attribute-list and no attribute-argument-clause shall be present. The attribute may be applied to a class definition. (削除ここまで)
(削除) In a class definition markedbase_check
, if a virtual member function that is neither implicitly-declared nor a destructor overrides (10.3 class.virtual) a member function of a base class and it is not marked override, the program is ill-formed. Similarly, in such a class definition, if a class member name other than that of an implicitly-declared special member function hides (3.3.10 basic.scope.hiding, 10.2 class.member.lookup) a class member name in a base class and it is not marked hiding, the program is ill-formed. [ Note: a using-declaration makes the potentially hidden name visible, avoiding the need for the hiding attribute. -- end note ] [ Example: ... ] (削除ここまで)
Add a new paragraph after 9 class paragraph 2:class-head:... (追記) A class-virt-specifier-seq shall contain at most one of each class-virt-specifier. (追記ここまで) A class-specifier(削除) class-key attribute-specifieropt identifieropt base-clauseopt class-key attribute-specifieropt nested-name-specifier identifier base-clauseopt class-key attribute-specifieropt nested-name-specifieropt simple-template-id base-clauseopt (削除ここまで)(追記) class-key attribute-specifieropt class-head-name class-virt-specifier-seqopt base-clauseopt class-key attribute-specifieropt base-clauseopt class-head-name: nested-name-specifieropt class-name class-virt-specifier-seq: class-virt-specifier class-virt-specifier-seq class-virt-specifier class-virt-specifier: (追記ここまで) (追記) final explicit (追記ここまで)(削除) where the (削除ここまで)(追記) whose (追記ここまで) class-head omits(削除) the optional identifier (削除ここまで)(追記) the class-head-name (追記ここまで) defines an unnamed class. (追記) [ Note: An unnamed class thus can't befinal
orexplicit
. ] (追記ここまで)
(追記) If a class is marked with the class-virt-specifier
final
and it appears as a
base-type-specifier in a base-clause (10
class.derived), the program is ill-formed. (追記ここまで)
Change 9 class paragraph 10:
If aChange the grammar in 9.2 class.mem:(削除) class-head (削除ここまで)(追記) class-head-name (追記ここまで) contains a nested-name-specifier, the class-specifier shall refer to a class that was previously declared directly in the class or namespace to which the nested-name-specifier refers, or in an element of the inline namespace set (7.3.1 namespace.def) of that namespace (i.e., not merely inherited or introduced by a using-declaration), and the class-specifier shall appear in a namespace enclosing the previous declaration. In such cases, the nested-name-specifier of the(削除) class-head (削除ここまで)(追記) class-head-name (追記ここまで) of the definition shall not begin with a decltype-specifier.
Add two new paragraphs after 9.2 class.mem paragraph 8:member-declarator: declarator (追記) virt-specifier-seqopt (追記ここまで) pure-specifieropt declarator (追記) virt-specifier-seqopt (追記ここまで) brace-or-equal-initializeropt identifieropt attribute-specifieropt (追記) virt-specifier-seqopt (追記ここまで) : constant-expression (追記) virt-specifier-seq: virt-specifier virt-specifier-seq virt-specifier virt-specifier: (追記ここまで) (追記) override final new (追記ここまで) pure-specifier: = 0
(追記) A virt-specifier-seq shall contain at most one of each virt-specifier. The virt-specifiersAdd a new paragraph after 10 class.derived paragraph 8:override
andfinal
shall only appear in the declaration of a virtual member function. (追記ここまで)(追記) If a class member is marked
new
and its name does not hide (3.3.10 basic.scope.hiding, 10.2 class.member.lookup) a class member name in a base class the program is ill-formed. (追記ここまで)
(追記) In a class definition marked with the class-virt-specifierAdd two new paragraphs after 10.3 class.virtual paragraph 3:explicit
, if a virtual member function that is neither implicitly-declared nor a destructor overrides (10.3 class.virtual) a member function of a base class and it is not marked with the virt-specifieroverride
, the program is ill-formed. Similarly, in such a class definition, if a class member name other than that of an implicitly-declared special member function hides (3.3.10 basic.scope.hiding, 10.2 class.member.lookup) a class member name in a base class and it is not markednew
, the program is ill-formed, unless the class member is a member function that overrides the corresponding member in the base class. [ Note: a using-declaration makes the potentially hidden name visible, avoiding the need for thenew
marker. -- end note ] [ Example: (追記ここまで)(追記) class B { virtual void some_func(); virtual void f(int); virtual void h(int); void j(int); void k(); typedef B self; }; class D explicit : public B { void sone_func() override; // error: misspelled name void f(int) override; // OK: f implicitly virtual, overrides B::f virtual void f(long) override; // error: non-matching argument type virtual void f(int) const override; // error: non-matching cv-qualification virtual int f(int) override; // error: non-matching return type virtual void g(long); // OK: new virtual function introduced void h(int); // error: h implicitly virtual, but overriding without marker virtual void h(double); // error: hides B::h without marker virtual void h(char *) new; // OK using B::j; int j(double); // OK: not hiding due to "using" void j(int); // OK, despite `obscuring' B::j(int) virtual int j(void) new; // error: not hiding due to "using" int k; // error: hides B::k without marker int m(int) new; // error: no hiding despite marker typedef D self; // error: hides B::self without marker }; (追記ここまで)(追記) -- end example ] (追記ここまで)
(追記) If a virtual function f in some class B is marked with the virt-specifierfinal
and in a class D derived from B a function D::f overrides B::f, the program is ill-formed. [ Example: (追記ここまで)(追記) struct B { virtual void f() const final; }; struct D : B { void f() const; // error: D::f attempts to override final B::f }; (追記ここまで)(追記) -- end example ] (追記ここまで)(追記) If a virtual function is marked with the virt-specifier
override
and does not override a member function of a base class, the program is ill-formed. [ Example: (追記ここまで)(追記) struct B { virtual void f(int); }; struct D : B { void f(long) override; // error: wrong signature overriding B::f void f(int) override; // ok }; (追記ここまで)(追記) -- end example ] (追記ここまで)