<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  <meta http-equiv="Content-Style-Type" content="text/css" />
  <meta name="generator" content="pandoc" />
  <title></title>
  <style type="text/css">code{white-space: pre;}</style>
  <style type="text/css">
div.sourceCode { overflow-x: auto; }
table.sourceCode, tr.sourceCode, td.lineNumbers, td.sourceCode {
  margin: 0; padding: 0; vertical-align: baseline; border: none; }
table.sourceCode { width: 100%; line-height: 100%; }
td.lineNumbers { text-align: right; padding-right: 4px; padding-left: 4px; color: #aaaaaa; border-right: 1px solid #aaaaaa; }
td.sourceCode { padding-left: 5px; }
code > span.kw { color: #007020; font-weight: bold; } /* Keyword */
code > span.dt { color: #902000; } /* DataType */
code > span.dv { color: #40a070; } /* DecVal */
code > span.bn { color: #40a070; } /* BaseN */
code > span.fl { color: #40a070; } /* Float */
code > span.ch { color: #4070a0; } /* Char */
code > span.st { color: #4070a0; } /* String */
code > span.co { color: #60a0b0; font-style: italic; } /* Comment */
code > span.ot { color: #007020; } /* Other */
code > span.al { color: #ff0000; font-weight: bold; } /* Alert */
code > span.fu { color: #06287e; } /* Function */
code > span.er { color: #ff0000; font-weight: bold; } /* Error */
code > span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
code > span.cn { color: #880000; } /* Constant */
code > span.sc { color: #4070a0; } /* SpecialChar */
code > span.vs { color: #4070a0; } /* VerbatimString */
code > span.ss { color: #bb6688; } /* SpecialString */
code > span.im { } /* Import */
code > span.va { color: #19177c; } /* Variable */
code > span.cf { color: #007020; font-weight: bold; } /* ControlFlow */
code > span.op { color: #666666; } /* Operator */
code > span.bu { } /* BuiltIn */
code > span.ex { } /* Extension */
code > span.pp { color: #bc7a00; } /* Preprocessor */
code > span.at { color: #7d9029; } /* Attribute */
code > span.do { color: #ba2121; font-style: italic; } /* Documentation */
code > span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */
code > span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */
code > span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */
  </style>
</head>
<body>
<h1 id="exhaustive-attribute-for-enums">[[exhaustive]] attribute for enums</h1>
<ul>
<li>Document number: P0375R0</li>
<li>Date: 2016-05-29</li>
<li>Reply-to: David Sankel &lt;david@stellarscience.com&gt;</li>
<li>Audience: Evolution</li>
</ul>
<h2 id="abstract">Abstract</h2>
<p>Can a compiler confidently elide warnings on <code>switch</code> statements that cover all enumerators of an <code>enum</code>? Due the many ways <code>enum</code> is used, it turns out the answer is no. Compiler vendors choose either to be overly pessimistic, and always warn when default labels are missing, or overly optimistic, and omit warnings when they're needed.</p>
<p>The compiler needs a little more information on how a particular <code>enum</code> is intended to be used. This proposal makes that possible. The proposed [[exhaustive]] attribute will result in better compiler warnings and less bugs.</p>
<div class="sourceCode"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span class="kw">enum</span> [[<span class="kw">exhaustive</span>]] color {
  red,
  green,
  blue
};</code></pre></div>
<h2 id="motivation">Motivation</h2>
<p>Given the following enum definition and instance,</p>
<div class="sourceCode"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span class="kw">enum</span> color {
  red,
  green,
  blue
};

color c = <span class="co">/* etc. */</span>;</code></pre></div>
<p>, we would like compilers to emit a warning here,</p>
<div class="sourceCode"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span class="kw">switch</span>(c) {
<span class="kw">case</span> red:
  std::cout &lt;&lt; <span class="st">&quot;red&quot;</span> &lt;&lt; std::endl;
  <span class="kw">break</span>;
<span class="kw">case</span> green:
  std::cout &lt;&lt; <span class="st">&quot;green&quot;</span> &lt;&lt; std::endl;
  <span class="kw">break</span>;

  <span class="co">// Hey, where&#39;s blue?</span>
};</code></pre></div>
<p>, but not here,</p>
<div class="sourceCode"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span class="kw">switch</span>(c) {
<span class="kw">case</span> red:
  std::cout &lt;&lt; <span class="st">&quot;red&quot;</span> &lt;&lt; std::endl;
  <span class="kw">break</span>;
<span class="kw">case</span> green:
  std::cout &lt;&lt; <span class="st">&quot;green&quot;</span> &lt;&lt; std::endl;
  <span class="kw">break</span>;
<span class="kw">case</span> blue:
  std::cout &lt;&lt; <span class="st">&quot;blue&quot;</span> &lt;&lt; std::endl;
  <span class="kw">break</span>;
};

<span class="co">// Perfect, all bases are covered.</span></code></pre></div>
<p>. The latter <code>switch</code> statement is safe in that it handles all the possible enumerators.</p>
<p>Unfortunately, other <code>enum</code> uses prevent the compiler from always knowing when a <code>switch</code> is safe. Consider the following example:</p>
<div class="sourceCode"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span class="kw">enum</span> color_channels
{
  red = <span class="dv">1</span> &lt;&lt; <span class="dv">0</span>,
  green = <span class="dv">1</span> &lt;&lt; <span class="dv">1</span>,
  blue = <span class="dv">1</span> &lt;&lt; <span class="dv">2</span>,
  alpha = <span class="dv">1</span> &lt;&lt; <span class="dv">3</span>
};

color_channels cc = <span class="co">/* etc. */</span>;</code></pre></div>
<p>In this case, the enumeration is intended to be used as any combination of a red, green, blue, and alpha channel. This switch,</p>
<div class="sourceCode"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span class="kw">switch</span>(cc) {
<span class="kw">case</span> red:
  std::cout &lt;&lt; <span class="st">&quot;red&quot;</span> &lt;&lt; std::endl;
  <span class="kw">break</span>;
<span class="kw">case</span> green:
  std::cout &lt;&lt; <span class="st">&quot;green&quot;</span> &lt;&lt; std::endl;
  <span class="kw">break</span>;
<span class="kw">case</span> blue:
  std::cout &lt;&lt; <span class="st">&quot;blue&quot;</span> &lt;&lt; std::endl;
  <span class="kw">break</span>;
<span class="kw">case</span> alpha:
  std::cout &lt;&lt; <span class="st">&quot;alpha&quot;</span> &lt;&lt; std::endl;
  <span class="kw">break</span>;
};</code></pre></div>
<p>, <em>should</em> produce a warning because it fails to handle anything other than <em>only</em> the red, green, or blue channel.</p>
<p>To make matters worse, there is yet another common enumeration pattern:</p>
<div class="sourceCode"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span class="kw">enum</span> color_selections
{
  red,
  green,
  blue,
  hot_pink,
  user_0
};

color_selection cs = <span class="co">/* etc. */</span>;</code></pre></div>
<p>In this case, the intent is that the <code>user_0</code> enumerator marks the beginning of an extension point where an arbitrary number of colors can be specified. The following snippet,</p>
<div class="sourceCode"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span class="kw">switch</span>(cs) {
<span class="kw">case</span> red:
  std::cout &lt;&lt; <span class="st">&quot;red&quot;</span> &lt;&lt; std::endl;
  <span class="kw">break</span>;
<span class="kw">case</span> green:
  std::cout &lt;&lt; <span class="st">&quot;green&quot;</span> &lt;&lt; std::endl;
  <span class="kw">break</span>;
<span class="kw">case</span> blue:
  std::cout &lt;&lt; <span class="st">&quot;blue&quot;</span> &lt;&lt; std::endl;
  <span class="kw">break</span>;
<span class="kw">case</span> hot_pink:
  std::cout &lt;&lt; <span class="st">&quot;hot pink&quot;</span> &lt;&lt; std::endl;
  <span class="kw">break</span>;
<span class="kw">case</span> user0:
  std::cout &lt;&lt; extra_color_names[<span class="dv">0</span>] &lt;&lt; std::endl;
  <span class="kw">break</span>;
};</code></pre></div>
<p>, again <em>should</em> produce a warning since only the 0th user color is handled.</p>
<p>All of <code>color</code>, <code>color_channels</code>, and <code>color_selection</code> are common uses of enumerators, but only the first should elide <code>switch</code> warnings when all the enumerators are handled. Because the compiler cannot consistently divine the intent of the developer, we propose a <code>[[exhaustive]]</code> attribute on enumerations that indicates that the enumerators represent <em>all</em> the valid values for that enumeration.</p>
<div class="sourceCode"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span class="kw">enum</span> [[<span class="kw">exhaustive</span>]] color {
  red,
  green,
  blue
};</code></pre></div>
<h2 id="wording">Wording</h2>
<p><strong>Add new section to [dcl.attr] 7.6:</strong></p>
<p>7.6.9 Exhaustive attribute [dcl.attr.exhaustive]</p>
<ol style="list-style-type: decimal">
<li><p>The <em>attribute-token</em> <code>exhaustive</code> may be applied to the <em>declarator-id</em> in the declaration of an enumeration. It shall appear at most once in each <em>attribute-list</em> and no <em>attributeargument-clause</em> shall be present.</p></li>
<li><p>[ <em>Note:</em> For an enumeration marked <code>exhaustive</code>, implementations are encouraged not to emit a warning on <code>switch</code> statements with cases covering all enumerators of that enum. ― <em>end note</em> ]</p></li>
<li>[ <em>Example:</em>
<pre>
   enum [[exhaustive]] color {
     red,
     green,
     blue
   };</pre>
<p>― <em>end example</em> ]</p></li>
</ol>
<h2 id="conclusion">Conclusion</h2>
<p>The <code>[[exhaustive]]</code> attribute allows developers to clarify the intent of their enumerations in a way fixes a longstanding issue with <code>switch</code> compiler warnings that are either spurious or dangerously absent.</p>
</body>
</html>
