<html>
<head>
<title>N3206: Override control: Eliminating Attributes</title>

<style type="text/css">
  ins { text-decoration:none; font-weight:bold; background-color:#A0FFA0 }
  del { text-decoration:line-through; background-color:#FFA0A0 }
</style>
</head>

<body>
Jens Maurer, Mark Hall, Ville Voutilainen<br/>
2010-11-12<br/>
N3206=10-0196

<h1>N3206: Override control: Eliminating Attributes</h1>

The Core Working Group discussed the syntax for override control
as related to FCD National Body comments US 44 and CA 3 on 2010-11-10,
2010-11-11, and 2010-11-12.

The author believes the consensus established at that time via a chain
of straw polls was:
<ul>
<li>Remove the attributes [[base_check]], [[final]], [[override]], and
[[hiding]].</li>
<li>Introduce contextual keywords at the end of a member function
declarator for "override" and "final".</li>
<li>Introduce contextual keyword "final" and existing keyword
"explicit" after the identifier in a <em>class-head</em>.
<li>Allow keyword "new" to appear after the declarator of a member
declaration.</li>
</ul>

<p>
The wording below also address core issue 1065 "[[hiding]] with
[[override]]".
<p>
<em>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".</em>
<p>

Add a new paragraph after 2.11 lex.name paragraph 1:
<blockquote>
<ins>Some identifiers have a special meaning when appearing in a
certain context (see table X).
<table align="center" border="1">
<th colspan="2">Identifiers with special meaning</th>
<tr><td>override</td><td>final</td></tr>
</table>

When referred to in the grammar, these identifiers are used explicitly
rather than using the <em>identifier</em> grammar production.  Any
ambiguity whether a given <em>identifier</em> has a special meaning or
not is resolved to interpret the token as a regular
<em>identifier</em>.</ins>
</blockquote>

<!--
Change in 7.3.3 namespace.udecl paragraph 1:
<blockquote>
<pre>
<em>using-declaration:
      using typename<sub>opt</sub> ::<sub>opt</sub> nested-name-specifier unqualified-id <ins>new</ins><sub>opt</sub>;
      using :: unqualified-id <ins>new<sub>opt</sub></ins> ;
</em>
</pre>
...
</blockquote>
-->

Remove section 7.6.4 dcl.attr.final:

<blockquote>
<del>The <em>attribute-token</em> <code>final</code> specifies
derivation semantics
for a class and overriding semantics for a virtual function. It shall
appear at most once in each <em>attribute-list</em> and no
<em>attribute-argument-clause</em> shall be present.  The attribute
may be applied to class definitions and to virtual member functions
being declared in a class definition.</del>
<p>
<del>If a class B is marked final and a class D is derived from B the
program is ill formed.</del>
<p>
<del>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.</del>
<p>
<del>[ Example: ... ]</del>
</blockquote>

Remove in 7.6.5 dcl.attr.override:
<blockquote>
<del>The <em>attribute-token</em> <code>override</code> asserts that a virtual member
function overrides a function in a base class. It shall appear at most
once in each <em>attribute-list</em> and no
<em>attribute-argument-clause</em> shall be present. The attribute may
be applied to virtual member functions being declared in a class
definition.</del>
<p>
<del>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.</del>
<p>
<del>The <em>attribute-token</em> <code>hiding</code> asserts that a class
member name hides a name in a base class. It shall appear at most once
in each <em>attribute-list</em> and no
<em>attribute-argument-clause</em> shall be present.  The attribute
may be applied to class members being declared in a class definition.</del>
<p>
<del>If a class member is marked <code>hiding</code> 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.</del>
<p>
<del>The <em>attribute-token</em> <code>base_check</code> specifies that
overriding and hiding of base members is strictly checked within a
class. It shall appear at most once in each <em>attribute-list</em>
and no <em>attribute-argument-clause</em> shall be present. The
attribute may be applied to a class definition.</del>
<p>
<del>In a class definition marked <code>base_check</code>, 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: ... ]</del>
</blockquote>

Change the grammar in 9 class and the following sentence:
<blockquote>
<pre>
<em>class-head:
       <del>class-key attribute-specifier<sub>opt</sub> identifier<sub>opt</sub> base-clause<sub>opt</sub>
       class-key attribute-specifier<sub>opt</sub> nested-name-specifier identifier base-clause<sub>opt</sub>
       class-key attribute-specifier<sub>opt</sub> nested-name-specifier<sub>opt</sub> simple-template-id base-clause<sub>opt</sub></del>
       <ins>class-key attribute-specifier<sub>opt</sub> class-head-name class-virt-specifier-seq<sub>opt</sub> base-clause<sub>opt</sub>
       class-key attribute-specifier<sub>opt</sub> base-clause<sub>opt</sub>

class-head-name:
       nested-name-specifier<sub>opt</sub> class-name

class-virt-specifier-seq:
       class-virt-specifier
       class-virt-specifier-seq class-virt-specifier

class-virt-specifier:</ins></em>
       <ins>final
       explicit</ins>
</pre>
...

<ins>A class-virt-specifier-seq shall contain at most one of each
class-virt-specifier.</ins>
</pre>
A <em>class-specifier</em> <del>where the</del> <ins>whose</ins> <em>class-head</em> omits
<del>the optional identifier</del> <ins>the <em>class-head-name</em></ins>
defines an unnamed class. <ins>[ Note: An unnamed class thus can't be
<code>final</code> or <code>explicit</code>. ]</ins>
</blockquote>

Add a new paragraph after 9 class paragraph 2:
<blockquote>
<ins>If a class is marked with the <em>class-virt-specifier</em>
<code>final</code> and it appears as a
<em>base-type-specifier</em> in a <em>base-clause</em> (10
class.derived), the program is ill-formed.</ins>
</blockquote>

Change 9 class paragraph 10:
<blockquote>
If a <del><em>class-head</em></del>
<ins><em>class-head-name</em></ins> contains a
<em>nested-name-specifier</em>, the <em>class-specifier</em> shall
refer to a class that was previously declared directly in the class or
namespace to which the <em>nested-name-specifier</em> 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 <em>class-specifier</em> shall appear in a
namespace enclosing the previous declaration. In such cases, the
<em>nested-name-specifier</em> of the <del><em>class-head</em></del>
<ins><em>class-head-name</em></ins> of the definition shall not begin
with a <em>decltype-specifier</em>.
</blockquote>

Change the grammar in 9.2 class.mem:
<blockquote>
<pre>
<em>member-declarator:
    declarator <ins>virt-specifier-seq<sub>opt</sub></ins> pure-specifier<sub>opt</sub>
    declarator <ins>virt-specifier-seq<sub>opt</sub></ins> brace-or-equal-initializer<sub>opt</sub>
    identifier<sub>opt</sub> attribute-specifier<sub>opt</sub> <ins>virt-specifier-seq<sub>opt</sub></ins> : constant-expression

<ins>virt-specifier-seq:
    virt-specifier
    virt-specifier-seq virt-specifier

virt-specifier:</ins></em>
    <ins>override
    final
    new</ins>

<em>pure-specifier:</em>
      = 0
</pre>
</blockquote>

Add two new paragraphs after 9.2 class.mem paragraph 8:
<blockquote>
<ins>A <em>virt-specifier-seq</em> shall contain at most one of each
<em>virt-specifier</em>.
The <em>virt-specifier</em>s <code>override</code> and
<code>final</code> shall only appear in the declaration of a virtual
member function.</ins>
<p>
<ins>If a class member is marked <code>new</code> 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.</ins>
</blockquote>

Add a new paragraph after 10 class.derived paragraph 8:
<blockquote>
<ins>In a class definition marked with the
<em>class-virt-specifier</em> <code>explicit</code>, 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 <em>virt-specifier</em>
<code>override</code>, 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 <code>new</code>, 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 the <code>new</code> marker.
 -- end note ] [ Example:</ins>
<pre>
<ins>
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
};</ins>
</pre>
<ins>-- end example ]</ins>
</blockquote>

Add two new paragraphs after 10.3 class.virtual paragraph 3:
<blockquote>
<ins>If a virtual function f in some class B is marked with the
<em>virt-specifier</em> <code>final</code> and in a class D derived
from B a function D::f overrides B::f, the program is
ill-formed. [ Example:</ins>
<pre>
<ins>struct B {
  virtual void f() const final;
};

struct D : B {
  void f() const;    // error: D::f attempts to override final B::f
};
</ins></pre>
<ins>-- end example ]</ins>
<p>

<ins>If a virtual function is marked with the <em>virt-specifier</em>
<code>override</code> and does not override a member function of a
base class, the program is ill-formed. [ Example:</ins>
<pre>
<ins>struct B {
  virtual void f(int);
};

struct D : B {
  void f(long) override;     // error: wrong signature overriding B::f
  void f(int) override;      // ok
};
</ins></pre>
<ins>-- end example ]</ins>
</blockquote>

</body>
</html>
