<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml" lang="en-US" xml:lang="en-US"><head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Require a diagnostic for "declaration changes meaning"</title>

<style type="text/css">
body { color: #000000; background-color: #FFFFFF; }
del, .del { text-decoration: line-through; color: #8B0040; }
ins, .ins { text-decoration: underline; color: #005100; }
h1 { text-align: center; }

p.example { margin-left: 2em; }
pre.example { margin-left: 2em; }
div.example { margin-left: 2em; }

code.extract { background-color: #F5F6A2; }
pre.extract { margin-left: 2em; background-color: #F5F6A2;
  border: 1px solid #E1E28E; }

p.function { }
.attribute { margin-left: 2em; }
.attribute dt { float: left; font-style: italic;
  padding-right: 1ex; }
.attribute dd { margin-left: 0em; }

blockquote.std, ul.std { color: #000000; background-color: #F1F1F1;
  border: 1px solid #D1D1D1;
  padding-left: 0.5em; padding-right: 0.5em; }
blockquote.std del, blockquote.std .del, ul.std del, ul.std .del { text-decoration: line-through;
  color: #000000; background-color: #FFEBFF;
  border: 1px solid #ECD7EC; }
blockquote.std ins, blockquote.std .ins, ul.std ins, ul.std .ins { text-decoration: underline;
  color: #000000; background-color: #C8FFC8; }
blockquote.stddel { text-decoration: line-through;
  color: #000000; background-color: #FFEBFF;
  border: 1px solid #ECD7EC;
  padding-left: 0.5em; padding-right: 0.5em; }
blockquote.stdins { text-decoration: none;
  color: #000000; background-color: #C8FFC8;
  border: 1px solid #B3EBB3;
  padding-left: 0.5em; padding-right: 0.5em; }

table { border: 1px solid black; border-spacing: 0px;
  margin-left: auto; margin-right: auto; }
th { text-align: left; vertical-align: top;
  padding-left: 0.8em; border: none; }
td { text-align: left; vertical-align: top;
  padding-left: 0.8em; border: none; }

table.table { border-spacing: 2px; border-collapse: separate; }
.table * th, .table * td { border: 1px solid black; }

table.frontmatter { border: 0; border-spacing: 0px; border-collapse: collapse; margin: 0; width: 619px; }
.frontmatter * td, .frontmatter * th { padding: 0px; }
.frontmatter * th { font-weight: inherit; text-align: left; vertical-align: top; }

ul.dash { list-style-type: none; }
ul.dash li:before { content: '\2014'; margin-left: -1em }

span.highlight { background-color: #7FDFFF }

.nowrap { white-space: nowrap; }
.pre { white-space: pre; }

#xins:checked ~ * ins { display: none; visibility: hidden }
#xdel:checked ~ * del { display: none; visibility: hidden }
</style>

</head>

<body>
<address style="text-align: left;">
Document number: P1697R0<br/>
Date: 2019-06-11<br/>
Project: Programming Language C++<br/>
Audience: Core Working Group<br/>
Reply-to: <a href="mailto:botond@mozilla.com">Botond Ballo</a>
</address>
<hr>
<h1>Require a diagnostic for "declaration changes meaning"</h1>

<ul>
<li><a href="#Abstract">Abstract</a></li>
<li><a href="#Issue_description">Issue Description</a></li>
<li><a href="#Proposed_resolution">Proposed Resolution</a></li>
</ul>

<h2><a name="Abstract">Abstract</a></h2>

<p>This paper proposes to require a diagnostic for (some) violations of [basic.scope.class] p1.2 (where a declaration in a class scope changes the meaning of a name used earlier in that class scope).</p>

<h2><a name="Issue_description">Issue Description</a></h2>

<p>Originally posted in <a href="http://lists.isocpp.org/core/2016/09/0932.php">core/2016/09/0932</a>.</p>

<p>The following code:</p>
<code class="pre">
  struct foo {};

  struct bar {
    foo* m_foo;

    foo* foo() { return m_foo; }
  };
</code>

<p>is ill-formed, due to [basic.scope.class] p1.2: "A name N used in a class S shall refer to the same declaration in its context and when re-evaluated in the completed scope of S. No diagnostic is required for a violation of this rule."</p>

<p>gcc and clang differ on whether they issue a diagnostic for this code. clang does not, but gcc does:</p>

<code class="pre">
  test.cpp:6:30: error: declaration of `foo* bar::foo()' [-fpermissive]
     foo* foo() { return m_foo; }
                              ^

  test.cpp:1:8: error: changes meaning of `foo' from `struct foo' [-fpermissive]
   struct foo {};
          ^
</code>

<p>A number of C++ developers have complained to me about this, and I've been bitten by it myself. Usually it happens in the following way:
<ul>
  <li>You write code like this, which I think is very easy to do accidentally</li>
  <li>You compile locally with clang, which accepts your code</li>
  <li>Later on someone else (or your test automation) running gcc complains that you broke the code with gcc</li>
</ul></p>

<p>It could be argued that this is just a QoI issue with clang, but I'm wondering if there's any good reason for the standard not to require a diagnostic in cases like this.</p>

<p>I've brought this up during informal discussion in June 2016 (Oulu), and several implementers have told me they don't see a problem with requiring a diagnostic in cases like this.</p>

<h2><a name="Proposed_resolution">Proposed Resolution</a></h2>

<div>

<p>The following is a strawman proposed resolution:</p>
<hr>
<p><em>Modify [basic.scope.class] p1.2 as follows:</em></p
><blockquote class="std">
  A name N used in a class S shall refer to the same declaration in its context and when re-evaluated in the completed scope of S. <del>No diagnostic is required for a violation of this rule.</del>
</blockquote></p>
<hr>

<p>I describe this as a strawman resolution because I figure that a blanket requirement for diagnosing all violations of this rule may be a burden to implement. I expect a viable resolution will likely involve identifying a subset of violations of this rule (including at least cases similar to the example above) which are diagnosable without too much implementation burden, and requiring a diagnostic only for that subset. I am hoping for some guidance as to what that subset may be.</p>

</div></body></html>
