<!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>P1815R1: Translation-unit-local entities</title>
  <style type="text/css">code{white-space: pre;}</style>
  <style type="text/css">
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; }
code > span.dt { color: #902000; }
code > span.dv { color: #40a070; }
code > span.bn { color: #40a070; }
code > span.fl { color: #40a070; }
code > span.ch { color: #4070a0; }
code > span.st { color: #4070a0; }
code > span.co { color: #60a0b0; font-style: italic; }
code > span.ot { color: #007020; }
code > span.al { color: #ff0000; font-weight: bold; }
code > span.fu { color: #06287e; }
code > span.er { color: #ff0000; font-weight: bold; }
  </style>
  <style type="text/css">
  s, .del { background: #ff8888; }
  u, .ins { background: #88ff88; }
  /* from https://stackoverflow.com/a/32456613 */
  body > blockquote {
      display: list-item;
      list-style-type: "- ";
  }
  pre {
  		margin-left: 1.2em;
  }
  </style>
</head>
<body>
<div id="header">
<h1 class="title">P1815R1: Translation-unit-local entities<!-- -*- c++-md -*- --></h1>
</div>
<p><em>Audience</em>: CWG<br />S. Davis Herring &lt;<script type="text/javascript">
<!--
h='&#108;&#x61;&#110;&#108;&#46;&#x67;&#x6f;&#118;';a='&#64;';n='&#104;&#x65;&#114;&#114;&#x69;&#110;&#x67;';e=n+a+h;
document.write('<a h'+'ref'+'="ma'+'ilto'+':'+e+'">'+e+'<\/'+'a'+'>');
// -->
</script><noscript>&#104;&#x65;&#114;&#114;&#x69;&#110;&#x67;&#32;&#x61;&#116;&#32;&#108;&#x61;&#110;&#108;&#32;&#100;&#x6f;&#116;&#32;&#x67;&#x6f;&#118;</noscript>&gt;<br />Los Alamos National Laboratory<br />November 21, 2019</p>
<h1 id="history">History</h1>
<p>r1:</p>
<ul>
<li>Added example and fixed existing example</li>
<li>Added NB comment reference</li>
<li>Moved deduction guide wording to correct place</li>
<li>Restored basic permission for <code>static</code> in header units</li>
<li>Made more template specializations TU-local</li>
<li>Clarified type specifiers</li>
<li>Clarified TU-locality and usage of anonymous types</li>
</ul>
<h1 id="introduction">Introduction</h1>
<p>This paper is a replacement for <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1498r1.html">P1498R1</a> that includes the wording promised for it and thereby addresses <a href="https://github.com/cplusplus/nbballot/issues/34">US35</a>. While its general principle of forbidding exposure of internal-linkage constructs to other translation units is followed, this paper presents rules that differ for consistency, especially for templates.</p>
<p>The function to which a dependent name refers cannot, of course, be determined merely from the template declaration that contains it. <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1347r1.pdf">P1347R1</a> proposed forbidding such a call that selects an internal-linkage function via overload resolution. Such overload resolution can in general require undesirably extensive analysis of otherwise-local declarations, so P1498R1 goes further and (with a single exception for certain constants) forbids any use of such a name in a context where code generation might occur for another translation unit. (This includes, for example, the return type of a non-template function with more than internal linkage; while it need not be mangled, it is accessible via <code>decltype</code> anywhere the function is.) We can consider such overload sets to be <em>poisoned</em> by their mere inclusion of an unusable candidate. The unusable candidate might be a template; templates whose declarations involve internal entities must themselves be internal to avoid needing to perform template argument deduction for them (even if the resulting specialization might not involve any internal types). (As a reminder, <code>export</code> is irrelevant here because the client translation unit might be in the same module.)</p>
<p>However, ADL considers a set of functions and function templates which itself cannot be known until instantiation. It is therefore impossible to reliably preclude poisoned overload sets by any reasonable restriction on (non-internal) templates.</p>
<p>This paper therefore merely proscribes the external use of internal entities and of poisoned overload sets, and does so for the definition of a template only during instantiation. Even a template that unambiguously calls an internal function can have non-internal linkage so long as the only specializations used in other translation units are those generated by an explicit specialization or instantiation. (Implicit instantiation of a template does not preclude other implicit instantiations and so does not allow usage from other translation units.)</p>
<p>It would of course be possible to discard certain overload resolution candidates before deciding whether an overload set is poisoned. Most simply, any that do not support the number of arguments given in the call could be excluded. More sophisticated analysis might exclude functions or function templates with parameter types not convertible from a (non-dependent) argument type, as well as those whose constraints are known not to be met for any instantiation. Preferring future flexibility and compatibility over invention, this paper simply poisons overload sets unconditionally.</p>
<h1 id="wording">Wording</h1>
<p>Relative to N4835.</p>
<p>Change [basic.lookup.argdep]/5:</p>
<blockquote>
<p>[<em>Example</em>:<br />Translation unit #1:</p>
<pre class="sourceCode cpp"><code class="sourceCode cpp"><span class="kw">export</span> module M;
<span class="kw">namespace</span> R {
  <span class="kw">export</span> <span class="kw">struct</span> X ;
  <span class="kw">export</span> <span class="dt">void</span> f(X);
}
<span class="kw">namespace</span> S {
  <span class="kw">export</span> <span class="dt">void</span> f(X, X);
}</code></pre>
<p>Translation unit #2:</p>
<pre class="sourceCode cpp"><code class="sourceCode cpp"><span class="kw">export</span> module N;
import M;
<span class="kw">export</span> R::X make();
<span class="kw">namespace</span> R { <span class="dt">static</span> <span class="dt">int</span> g(X); }
<span class="kw">export</span> <span class="kw">template</span>&lt;<span class="kw">typename</span> T, <span class="kw">typename</span> U&gt; <span class="dt">void</span> apply(T t, U u) {
  f(t, u);
  g(t);
}</code></pre>
Translation unit #3:
<pre class="cpp">
module Q;
import N;
namespace S {
  struct Z { template<typename T> operator T(); };
}
void test() {
  auto x = make();              // OK, decltype(x) is R::X in module M
  R::f(x);                      // ill-formed: R and R::f are not visible here
  f(x);                         // OK, calls R::f from interface of M
  f(x, S::Z());                 // ill-formed: S::f in module M not considered
                                // even though S is an associated namespace
  apply(x, S::Z());             // <s>OK,</s><u>ill-formed:</u> S::f is visible in instantiation context, <s>and</s><u>but</u>
                                // R::g <s>is visible even though it </s>has internal linkage<u> and cannot be used outside TU #2</u>
}
</pre>

<p>— <em>end example</em>]</p>
</blockquote>
<p>Append paragraphs to [basic.link]:</p>
<div style="background-color: #bfa">
<blockquote>
<p>A declaration <em>D</em> <em>names</em> an entity <em>E</em> if</p>
<ol style="list-style-type: decimal">
<li><em>D</em> contains a <em>lambda-expression</em> whose closure type is <em>E</em>, or</li>
<li><em>E</em> is not a function or function template and <em>D</em> contains an <em>id-expression</em>, <em>type-name</em>, <em>decltype-specifier</em>, <em>placeholder-type-specifier</em>, <em>template-name</em>, or <em>concept-name</em> denoting <em>E</em>, or</li>
<li><em>E</em> is a function or function template that is named by an expression ([basic.def.odr]) appearing in <em>D</em>, or</li>
<li><em>E</em> is a function or function template declared in one translation unit, <em>D</em> appears in another translation unit, and <em>D</em> contains an <em>id-expression</em> or <em>template-name</em> ([dcl.type.class.deduct]) that refers to a set of overloads that contains <em>E</em>.</li>
</ol>
<p>A declaration instantiated for a template specialization ([temp.spec]) appears at the point of instantiation of the specialization ([temp.point]). [<em>Note</em>: Non-dependent names in such a declaration do not refer to a set of overloads ([temp.nondep]). — <em>end note</em>]</p>
</blockquote>
<blockquote>
<p>A declaration is an <em>exposure</em> if it names a TU-local entity (defined below), ignoring</p>
<ol style="list-style-type: decimal">
<li>the <em>function-body</em> for a non-inline function (but not the deduced return type for a (possibly instantiated) definition of a function with a declared return type that uses a placeholder type ([dcl.spec.auto])),</li>
<li>the <em>initializer</em> for a variable (but not the variable’s type),</li>
<li>friend declarations in a class definition, and</li>
<li>any reference to a non-volatile const object with internal or no linkage initialized with a constant expression that is not an odr-use ([basic.def.odr]).</li>
</ol>
</blockquote>
<blockquote>
<p>An entity is <em>TU-local</em> if it is</p>
<ol style="list-style-type: decimal">
<li>a type, function, variable, or template that
<ol style="list-style-type: decimal">
<li>has a name with internal linkage, or</li>
<li>does not have a name with linkage and is declared, or introduced by a <em>lambda-expression</em>, within the definition of a TU-local entity, or</li>
</ol></li>
<li>a type with no name introduced by a <em>defining-type-specifier</em> that is used to declare only TU-local entities, or</li>
<li>a specialization of a TU-local template, or</li>
<li>a specialization of a template with any TU-local template argument, or</li>
<li>a specialization of a template whose (possibly instantiated) declaration is an exposure. [<em>Note</em>: The specialization might have been implicitly or explicitly instantiated. — <em>end note</em>]</li>
</ol>
</blockquote>
<blockquote>
<p>If a (possibly instantiated) declaration of, or a deduction guide for, a non-TU-local entity in a module interface unit ([module.unit]), module partition, or header unit ([module.import]) is an exposure, the program is ill-formed. Such a declaration in any other translation unit is deprecated ([depr.local]).</p>
</blockquote>
<blockquote>
<p>If a (possibly instantiated) declaration that appears in one translation unit names a TU-local entity declared in another translation unit, the program is ill-formed.</p>
</blockquote>
<blockquote>
<p>[<em>Example</em>:<br />Translation unit #1:</p>
<pre class="sourceCode cpp"><code class="sourceCode cpp"><span class="kw">export</span> module A;
<span class="dt">static</span> <span class="dt">void</span> f();
<span class="kw">inline</span> <span class="dt">void</span> it() {f();} <span class="co">// error: is an exposure of f</span>
<span class="dt">static</span> <span class="kw">inline</span> <span class="dt">void</span> its() {f();} <span class="co">// OK</span>
<span class="kw">template</span>&lt;<span class="dt">int</span>&gt; <span class="dt">void</span> g() {its();} <span class="co">// OK</span>
<span class="kw">template</span> <span class="dt">void</span> g&lt;<span class="dv">0</span>&gt;();

<span class="dt">static</span> <span class="dt">auto</span> x=[]{f();};  <span class="co">// OK</span>
<span class="dt">auto</span> x2=x;               <span class="co">// error: the closure type is TU-local</span>
<span class="dt">int</span> y=([]{f();}(),<span class="dv">0</span>);    <span class="co">// error: the closure type is not TU-local</span>
<span class="dt">int</span> y2=(x,<span class="dv">0</span>);            <span class="co">// OK</span>

<span class="kw">namespace</span> N {
  <span class="kw">struct</span> A {};
  <span class="dt">void</span> adl(A);
  <span class="dt">static</span> <span class="dt">void</span> adl(<span class="dt">int</span>);
}
<span class="dt">void</span> adl(<span class="dt">double</span>);

<span class="kw">inline</span> <span class="dt">void</span> h(<span class="dt">auto</span> x) {adl(x);} <span class="co">// OK, but a specialization might be an exposure</span></code></pre>
<p>Translation unit #2:</p>
<pre class="sourceCode cpp"><code class="sourceCode cpp">module A;
<span class="dt">void</span> other() {
  g&lt;<span class="dv">0</span>&gt;();  <span class="co">// OK: specialization is explicitly instantiated</span>
  g&lt;<span class="dv">1</span>&gt;();  <span class="co">// error: instantiation uses TU-local its</span>
  h(N::A{});  <span class="co">// error: overload set contains TU-local N::adl(int)</span>
  h(<span class="dv">0</span>);  <span class="co">// OK: calls adl(double)</span>
}</code></pre>
<p>— <em>end example</em>]</p>
</blockquote>
</div>
<p>Change [dcl.inline]/2:</p>
<blockquote>
<p>A function declaration ([dcl.fct], [class.mfct], [class.friend]) with an <code>inline</code> specifier declares an <em>inline function</em>. The inline specifier indicates to the implementation that inline substitution of the function body at the point of call is to be preferred to the usual function call mechanism. An implementation is not required to perform this inline substitution at the point of call; however, even if this inline substitution is omitted, the other rules for inline functions specified in this subclause shall still be respected. <u>[<em>Note</em>: An inline function can use a name with internal linkage only if it is declared with internal linkage. — <em>end note</em>]</u></p>
</blockquote>
<p>Change [dcl.inline]/7:</p>
<blockquote>
<p>An exported inline function or variable shall be defined in the translation unit containing its exported declaration, outside the <em>private-module-fragment</em> (if any). [<em>Note</em>: <s>There is no restriction on the linkage (or absence thereof) of entities that the function body of an exported inline function can reference.</s> A constexpr function ([dcl.constexpr]) is implicitly inline. — <em>end note</em>]</p>
</blockquote>
<p>Change [dcl.spec.auto]/10:</p>
<blockquote>
<p>An exported function with a declared return type that uses a placeholder type shall be defined in the translation unit containing its exported declaration, outside the <em>private-module-fragment</em> (if any). [<em>Note</em>: T<s>here is no restriction on the linkage of t</s>he deduced return type<u> cannot have a name with internal linkage</u>. — <em>end note</em>]</p>
</blockquote>
<p>Change [module.import]/5:</p>
<blockquote>
<p>[…][<em>Note</em>: A <em>module-import-declaration</em> nominating a <em>header-name</em> is also recognized by the preprocessor, and results in macros defined at the end of phase 4 of translation of the header unit being made visible as described in [cpp.import]. — <em>end note</em>] A declaration of a name with internal linkage is permitted within a header unit despite all declarations being implicitly exported ([module.interface]). <s>If such a declaration declares an entity that is odr-used outside the header unit, or by a template instantiation whose point of instantiation is outside the header unit, the program is ill-formed.</s></p>
</blockquote>
<p>Add a subclause before [depr.impldec]:</p>
<div style="background-color: #bfa">
<blockquote>
<h2>Non-local use of TU-local entities [depr.local]</h2>
<p>A declaration of a non-TU-local entity that is an exposure ([basic.link]) is deprecated. [<em>Note</em>: Such a declaration in an importable translation unit is ill-formed. — <em>end note</em>] [<em>Example</em>:</p>
<pre class="sourceCode cpp"><code class="sourceCode cpp"><span class="kw">namespace</span> {
  <span class="kw">struct</span> A {
    <span class="dt">void</span> f();
  };
}
A h();                      <span class="co">// deprecated: not internal linkage</span>
<span class="kw">inline</span> <span class="dt">void</span> g() {A().f();}  <span class="co">// deprecated: inline and not internal linkage</span></code></pre>
<p>— <em>end example</em>]</p>
</blockquote>
</div>
</body>
</html>
