<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html>
  <head>
    <meta content="text/html;charset=UTF-8" http-equiv="Content-Type">
    <title>Clarifying the status of the &ldquo;C headers&rdquo;</title>
    <style type="text/css">
      html { margin: 0; padding: 0; color: black; background-color: white; }
      body { padding: 2em; font-size: medium; font-family: "DejaVu Serif", serif; line-height: 150%; }
      code { font-family: "DejaVu Sans Mono", monospace; color: #006; }

      h1, h2, h3 { margin: 1.5em 0 .75em 0; line-height: 125%; }

      sup, sub { line-height: 0; }

      div.code { white-space: pre-line; font-family: "DejaVu Sans Mono", monospace;
                 border: thin solid #E0E0E0; background-color: #F8F8F8; padding: 1em;
                 border-radius: 4px; }

      div.strictpre { white-space: pre; }

      div.code em { font-family: "DejaVu Serif", serif; }

      table { border-top: 2px solid black; border-bottom: 2px solid black; border-collapse: collapse; margin: 3em auto; }
      thead th { border-bottom: 2px solid black; }
      th, td { text-align: left; padding: 1ex 1ex 1ex 5em; }
      th:first-child, td:first-child { padding-left: 1ex; }

      tr.new td { background-color: #EFE; }
      td.new:after { content: "new!"; font-family: "DejaVu Sans", sans-serif; font-weight: bold; font-size: xx-small;
                     vertical-align: top; top: -1em; right: -1em; position: relative; float: right; color: #090; }

      .docinfo { float: right }
      .docinfo p { margin: 0; text-align:right; }
      .docinfo address { font-style: normal; }

      .quote { display: inline-block; clear: both; margin-left: 1ex;
               border: thin solid #E0E0E0; background-color: #F8F8F8; padding: 1ex; }

      /*  Use DIV[insert] and DIV[delete] if the entire paragraph is added or removed; otherwise
       *  use DIV[modify] and use INS/DEL elements to mark up individual changes.
       */

      div.insert { border-left: thick solid #0A0; border-right: thick solid #0A0; padding: 0 1em; }
      div.modify { border-left: thick solid #999; border-right: thick solid #999; padding: 0 1em; }
      div.delete { border-left: thick solid #A00; border-right: thick solid #A00; padding: 0 1em; }

      del { color: #A00; text-decoration: line-through; }
      ins { color: #090; }
      ins code, del code { color: inherit; }

      .box { border: thin black solid; padding: 2px; }
    </style>
  </head>
  <body>
    <div class="docinfo">
      <p>ISO/IEC JTC1 SC22 WG21 P2340</p>
      <p>Date: 2021-03-15</p>
      <p>To: LEWG, LWG, SG22</p>
      <address>
        Thomas K&ouml;ppe &lt;<a href="mailto:tkoeppe@google.com">tkoeppe@google.com</a>&gt;<br>
      </address>
    </div>

    <h1>Clarifying the status of the &ldquo;C headers&rdquo;</h1>

    <h2>Abstract</h2>

    <p>We propose to move the specification of &ldquo;[depr.c.headers]
    C headers&rdquo; from Annex D into the main document, and changing
    those headers&rsquo; status from &ldquo;deprecated&rdquo; to an
    explicitly discussed state &ldquo;for foreign-language
    interoperability only&rdquo;.</p>

    <h2>Contents</h2>
    <!-- fgrep -e "<h2 id=" cheaders.html | sed -e 's/.*id="\(.*\)">\(.*\)<\/h2>/<li><a href="#\1">\2<\/a><\/li>/g' -->
    <ol>
      <li><a href="#history">Revision history</a></li>
      <li><a href="#motivation">Motivation</a></li>
      <li><a href="#discussion">Discussion and Feedback</a></li>
      <li><a href="#impact">Impact on the Standard</a></li>
      <li><a href="#wording">Proposed wording</a></li>
    </ol>

    <h2 id="history">Revision history</h2>

    <ul>
      <li>this version: initial version</li>
    </ul>

    <h2 id="motivation">Motivation</h2>

    <p>The C++ standard library includes large parts of the standard library of ISO C: where ISO
    C provides a header <code>&lt;<em>name</em>.h&gt;</code>, C++ provides a header
    <code>&lt;c<em>name</em>&gt;</code> with names declared in namespace <code>std</code>. For
    example, C++&rsquo;s <code>&lt;cstddef&gt;</code> defines a type
    alias <code>std::size_t</code>. Additionally, C++ has always shipped a second set of
    headers, called &ldquo;C headers&rdquo;, which are also of the
    form <code>&lt;<em>name</em>.h&gt;</code>, just like in C &mdash; but note that these are
    simply part of the C++ standard library and thus of C++. These headers define the names in
    the global namespace. (Additionally, either class of headers is optionally allowed to also
    declare names in the respective other namespace. This cannot be portably relied upon,
    however, it does have the effect of making the names in question reserved in the global
    namespace.)</p>

    <p>Ever since C++ has been an ISO standard, the C headers have been
    &ldquo;deprecated&rdquo;, which in ISO parlance means &ldquo;no longer in use&rdquo;,
    &ldquo;discouraged&rdquo;, or &ldquo;subject to future removal&rdquo;. However, this is
    inappropriate: The C headers are a necessary part of the C++ ecosystem. What is missing from
    the status quo is a nuanced discussion of what the headers are and are not for. We will lay
    out these nuanced points now.</p>

    <p>The principal purpose of the C headers is for <em>interoperability with ISO C</em>, and
    with any other systems that use C&rsquo;s de-facto ABI and linkage conventions. For example,
    in C++ the header <code>&lt;stddef.h&gt;</code> does not just define the same names as the
    header of the same name in C, but the names actually mean the same, and this extends to the
    names defined by <code>&lt;cstddef&gt;</code>. For example, a C++ program may include that
    header, declare a function <code>extern "C" void f(std::size_t)</code>, and call that
    function. The function can be defined by a C translation unit, compiled with a C compiler,
    which defines <code>void f(size_t)</code> (after including <code>&lt;stddef.h&gt;</code>).
    This is not explicitly guaranteed to work by either language standard, but is universally
    relied upon by real ecosystems. The existence of &ldquo;C language linkage&rdquo; suggests
    that such interoperation is intended to work.</p>

    <p>Finally, this allows us to articulate the role of the &ldquo;C headers&rdquo; in C++:
    These headers are necessary for polyglot interoperability code, i.e. code that is required
    to be at once valid C++ and also valid C. Typically, such code consists of header files
    which are included from both languages, and functions defined in those headers may be
    defined either in C++ or in C translation units. The headers are <em>not</em> useful in code
    that is <em>only</em> required to be valid C++. Therefore, the C headers should be provided
    by the C++ standard library as a fully-supported, not deprecated part, <em>but</em> they
    should also be discouraged for use in code that is not polyglot interoperability code.</p>

    <p>Within pure C++ code, the use of the &ldquo;proper&rdquo; <code>&lt;c<em>name</em>&gt;</code>
    headers has several advantages:</p>
    <ol>
      <li>Consistency and simplicity: Every C++ standard library name is in
        namespace <code>std</code>.</li>
      <li>Some facilities are only available in a <code>&lt;c<em>name</em>&gt;</code> header:
        special maths functions, <code>std::byte</code>, <code>std::nullptr_t</code>. It would
        be burdensome to add an exception to explain how to get those facilities.</li>
      <li>As a visual aid: It is useful to develop a habit that &ldquo;things in a namespace
        require a header inclusion&rdquo;. Typing &ldquo;<code>std::something</code>&rdquo;
        reminds the author (or reviewer) to check for the relevant header inclusion. By
        comparison, it is easier to miss an unqualified &ldquo;<code>size_t</code>&rdquo; and
        spot a missing header inclusion.</li>
    </ol>
    
    <p>Note that the headers <code>&lt;stdbool.h&gt;</code> and <code>&lt;stdalign.h&gt;</code>
    are entirely trivial and only exist because their ISO C counterpart is necessary in C
    programs. Pure C++ code has no need for these headers, and so there is no
    corresponding <code>&lt;c<em>name</em>&gt;</code> header. Yet the existence of the trivial
    interop <code>&lt;<em>name</em>.h&gt;</code> header is critical.</p>

    <h2 id="discussion">Discussion and Feedback</h2>

    <p>The fate of the &ldquo;C headers&rdquo; has been brought up
    in <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p2139r2.html#3.9">P2139</a>. During
    a telecon discussion, LEWG and that paper&rsquo;s author agreed that the topic should be handled by a
    separate paper, and there was general consensus that the current, deprecated status of the
    headers is wrong. Feedback to a draft of this proposal was generally positive, but included
    three noteworthy arguments that we would like to record here.</p>

    <p>The first argument was that we should take a wider look at C interoperability, and
    perhaps even consider language support for addressing the way in which the &ldquo;C
    names&rdquo; are declared in two namespaces. The author of P2139 has also expressed interest
    in exploring farther-reaching language changes to support interoperability. However, this is
    out of scope for the current proposal, in which we only want to make one small change to
    elevate the headers from their current deprecated status to a place where they are a
    regular, normative feature, explicitly encouraged for polyglot code, and discouraged for
    pure C++ code that never needs to be valid C.</p>

    <p>The second argument from a long-time committee member was that we should not overturn
    existing committee decisions without new information. In this author&rsquo;s opinion,
    however, which seems to resonate with many other committee members, that original decision
    (which goes back to the first standard, C++98) was never quite perfect in the first place,
    and many have since come to regard the deprecated status of the headers as a mistake. From
    observing the situation for several years, we have reached the conclusion that the subject
    has simply been too marginal and irrelevant to motivate action, and we simply want to pick
    up that unfinished business with this proposal.</p>

    <p>The third argument was that C and C++ should look as similar as possible (which would
    speak for using the unqualified names from the &ldquo;C headers&rdquo;). This author does
    not share that opinion, and instead believes that users should develop language fluency for
    each language <em>as appropriate for that language</em>. When writing C++, C++ sensibilities
    should come into play; it is not helpful to C++ code health if C++ code is made to look like
    a different language. The aforementioned connection between reading a namespace
    qualification and remembering to check for header inclusion is a valuable part of C++
    fluency that simply does not apply to C, and it should not be abandoned because of C. When
    writing polyglot C and C++ code, one is addressing <em>two audiences</em> and needs fluency
    in <em>both</em> their languages, rather than hypothetical fluency in one hypothetical
    &ldquo;common subset&rdquo;.</p>

    <p>Finally, we would like to repeat that this proposal is an overall improvement for
    everybody: Currently, the &ldquo;C headers&rdquo; are deprecated for everyone, meaning that
    they are notionally at the risk of future removal from the Standard (which we know will not
    happen). Under this proposal, the headers become normatively encouraged for polyglot code,
    and discouraged for pure C++ code. In light of other proposals in the area of C
    interoperability, it should be appreciated that the proposal makes the headers normatively
    encouraged for code that is intended to be both valid C++ and valid C. Discouragement is
    only given for code that is <em>only</em> C++.</p>

    <h2 id="impact">Impact on the Standard</h2>

    <p>There is no change to the actual content of the Standard. This proposal makes the C
    headers no longer deprecated, so there is no formal threat of future removal. The effective
    discouragement to use the C headers in pure C++ code is now spelled out explicitly as
    normative discouragement.</p>

    <h2 id="wording">Proposed wording</h2>

    <p>Move [depr.c.headers] to Clause [17, support]</p>

    <div class="modify">
      <p><strong><del>D.11</del><ins>17.??</ins> C Headers [<del>depr</del><ins>support</ins>.c.headers]</strong></p>

      <p><strong><del>D.11.1</del><ins>17.??.1</ins> General [<del>depr</del><ins>support</ins>.c.headers.general]</strong></p>

      <p>For compatibility with the C standard library, the C++ standard library provides
      the <em>C headers</em> shown in [Table 149, depr.c.headers].
      <ins>The intended use of these headers is for interoperability only. It is possible that
      C++ source files need to include one of these headers so as to be valid ISO C. Source
      files that are not intended to also be valid ISO C should not use any of the C
      headers.</ins></p>
      <p><ins>[<em>Note</em>: The C headers either have no effect, such as <code>&lt;stdbool.h&gt;</code> and <code>&lt;stdalign.h&gt;</code>,
          or otherwise the corresponding header of the form <code>&lt;c<em>name</em>&gt;</code> provides the same facilities and assuredly defines them in namespace <code>std</code>. &mdash;&nbsp;<em>end note</em>] [<em>Example</em>: The following source file is both valid C++ and valid ISO C. Viewed as C++, it declares a function with C language linkage; viewed as C it simply declares a function (and provides a prototype).</ins></p>
      <div class="code"><ins>#include &lt;stdbool.h&gt; &nbsp; // for "bool" in C, no effect in C++
          #include &lt;stddef.h&gt; &nbsp; &nbsp;// for "size_t"

          #ifdef __cplusplus &nbsp; &nbsp; // see [cpp.predefined]
          extern "C" &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // see [decl.link]
          #endif
          void f(bool b[], size_t n);</ins></div>
      <p><ins>&mdash;&nbsp;<em>end example</em>]</ins>
    </div>

    <p><em>Move the remainder of the subclause as is.</em></p>
    
  </body>
</html>
