<HTML>
<HEAD>
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
<TITLE>
    CWG Issue 341</TITLE>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<STYLE TYPE="text/css">
  INS { text-decoration:none; font-weight:bold; background-color:#A0FFA0 }
  .INS { text-decoration:none; background-color:#D0FFD0 }
  DEL { text-decoration:line-through; background-color:#FFA0A0 }
  .DEL { text-decoration:line-through; background-color: #FFD0D0 }
  @media (prefers-color-scheme: dark) {
    HTML { background-color:#202020; color:#f0f0f0; }
    A { color:#5bc0ff; }
    A:visited { color:#c6a8ff; }
    A:hover, a:focus { color:#afd7ff; }
    INS { background-color:#033a16; color:#aff5b4; }
    .INS { background-color: #033a16; }
    DEL { background-color:#67060c; color:#ffdcd7; }
    .DEL { background-color:#67060c; }
  }
  SPAN.cmnt { font-family:Times; font-style:italic }
</STYLE>
</HEAD>
<BODY>
<P><EM>This is an unofficial snapshot of the ISO/IEC JTC1 SC22 WG21
  Core Issues List revision 118b.
  See http://www.open-std.org/jtc1/sc22/wg21/ for the official
  list.</EM></P>
<P>2025-09-28</P>
<HR>
<A NAME="341"></A><H4>341.
  
<TT>extern "C"</TT> namespace member function versus global variable
</H4>
<B>Section: </B>9.12&#160; [<A href="https://wg21.link/dcl.link">dcl.link</A>]
 &#160;&#160;&#160;

 <B>Status: </B>C++11
 &#160;&#160;&#160;

 <B>Submitter: </B>Steve Adamczyk
 &#160;&#160;&#160;

 <B>Date: </B>1 Mar 2002<BR>


<P>[Voted into the WP at the November, 2010 meeting.]</P>



<P>Here's an interesting case:
<PRE>
  int f;
  namespace N {
    extern "C" void f () {}
  }
</PRE>
As far as I can tell, this is not precluded by the ODR section
(6.3 [<A href="https://wg21.link/basic.def.odr">basic.def.odr</A>])
or the extern "C" section (9.12 [<A href="https://wg21.link/dcl.link">dcl.link</A>]).
However, I believe many compilers
do not do name mangling on variables and (more-or-less by definition)
on extern "C" functions.  That means the variable and the function
in the above end up having the same name at link time.  EDG's front
end, g++, and the Sun compiler all get essentially the same error,
which is a compile-time assembler-level error because of the
duplicate symbols (in other words, they fail to check for this, and the
assembler complains).  MSVC++ 7 links the program without error,
though I'm not sure how it is interpreted.</P>

<P>Do we intend for this case to be valid?  If not, is it a compile time
error (required), or some sort of ODR violation (no diagnostic
required)?  If we do intend for it to be valid, are we forcing
many implementations to break binary compatibility by requiring
them to mangle variable names?</P>

<P>Personally, I favor a compile-time error, and an ODR prohibition on
such things in separate translation units.</P>

<P><B>Notes from the 4/02 meeting:</B></P>

<P>The working group agreed with the proposal.  We feel a diagnostic
should be required for declarations within one translation unit.
We also noted that if the variable in global scope in the above example
were declared static we would still expect an error.</P>

<P>Relevant sections in the
standard are 9.12 [<A href="https://wg21.link/dcl.link#6">dcl.link</A>] paragraph 6 and
6.7 [<A href="https://wg21.link/basic.link#9">basic.link</A>] paragraph 9.  We feel that the definition
should be written such that the entities in conflict are not "the same
entity" but merely not allowed together.</P>

<P><B>Additional note (September, 2004)</B></P>

<P>This problem need not involve a conflict between a function
and a variable; it can also arise with two variable
declarations:</P>

<PRE>
    int x;
    namespace N {
        extern "C" int x;
    }
</PRE>

<P><B>Proposed resolution (March, 2008):</B></P>

<P>Change 9.12 [<A href="https://wg21.link/dcl.link#6">dcl.link</A>] paragraph 6 as follows:</P>

<BLOCKQUOTE>

<P>At most one function with a particular name can have C
language linkage. Two declarations for a function with C language
linkage with the same function name (ignoring the namespace names
that qualify it) that appear in different namespace scopes refer
to the same function. Two declarations for an object with C
language linkage with the same name (ignoring the namespace names
that qualify it) that appear in different namespace scopes refer
to the same object. <INS>A function or object with C linkage shall
not be declared with the same name (6.1 [<A href="https://wg21.link/basic.pre">basic.pre</A>])
as an object or reference declared in global scope,
unless both declarations denote the same object; no diagnostic is
required if the declarations appear in different translation
units.</INS> [<I>Note:</I> <DEL>because of the one definition rule
(6.3 [<A href="https://wg21.link/basic.def.odr">basic.def.odr</A>]), only</DEL> <INS>Only</INS> one definition
for a function or object with C linkage may appear in the program
<INS>(see 6.3 [<A href="https://wg21.link/basic.def.odr">basic.def.odr</A>])</INS>; that <DEL>is,</DEL> <INS>implies
that</INS> such a function or object must not be defined in more
than one namespace scope. For example,</P>

<PRE>
    <INS>int x;</INS>
    namespace A {
      extern "C" int f();
      extern "C" int g() { return 1; }
      extern "C" int h();
      <INS>extern "C" int x();               //<SPAN CLASS="cmnt"> ill-formed: same name as global-scope object </SPAN>x</INS>
    }

    namespace B {
      extern "C" int f();               //<SPAN CLASS="cmnt"> </SPAN>A::f<SPAN CLASS="cmnt"> and </SPAN>B::f<SPAN CLASS="cmnt"> refer</SPAN>
                                        //<SPAN CLASS="cmnt"> to the same function</SPAN>
      extern "C" int g() { return 1; }  //<SPAN CLASS="cmnt"> ill-formed, the function </SPAN>g
                                        //<SPAN CLASS="cmnt"> with C language linkage</SPAN>
                                        //<SPAN CLASS="cmnt"> has two definitions</SPAN>
    }

    int A::f() { return 98; }           //<SPAN CLASS="cmnt"> definition for the function </SPAN>f
                                        //<SPAN CLASS="cmnt"> with C language linkage</SPAN>
    extern "C" int h() { return 97; }
                                        //<SPAN CLASS="cmnt"> definition for the function </SPAN>h
                                        //<SPAN CLASS="cmnt"> with C language linkage</SPAN>
                                        //<SPAN CLASS="cmnt"> </SPAN>A::h<SPAN CLASS="cmnt"> and </SPAN>::h<SPAN CLASS="cmnt"> refer to the same function</SPAN>
</PRE>

<P>&#8212;<I>end note</I>]</P>

</BLOCKQUOTE>

<P><B>Notes from the September, 2008 meeting:</B></P>

<P>It should also be possible to declare references with C name
linkage (although the meaning the first sentence of 9.12 [<A href="https://wg21.link/dcl.link#1">dcl.link</A>] paragraph 1 with respect to the meaning of such a
declaration is not clear), which would mean that the changed
wording should refer to declaring &#8220;the same entity&#8221;
instead of &#8220;the same object.&#8221; The formulation here
would probably benefit from the approach currently envisioned for
issues <A HREF="570.html">570</A> and <A HREF="633.html">633</A>, in which &#8220;variable&#8221; is defined as being
either an object or a reference.</P>

<P><B>Proposed resolution (February, 2010):</B></P>

<P>Change 9.12 [<A href="https://wg21.link/dcl.link#6">dcl.link</A>] paragraph 6 as follows:</P>

<BLOCKQUOTE>

<P>At most one function with a particular name can have C
language linkage. Two declarations for a function with C language
linkage with the same function name (ignoring the namespace names
that qualify it) that appear in different namespace scopes refer
to the same function.  Two declarations for an object <INS>or
reference</INS> with C language linkage with the same name
(ignoring the namespace names that qualify it) that appear in
different namespace scopes refer to the same object <INS>or
reference</INS>. <INS>An entity with C language linkage shall not
be declared with the same name as an entity in global scope,
unless both declarations denote the same object or reference; no
diagnostic is required if the declarations appear in different
translation units.</INS> [<I>Note:</I> <DEL>because of the one
definition rule (6.3 [<A href="https://wg21.link/basic.def.odr">basic.def.odr</A>]), only</DEL>
<INS>Only</INS> one definition for <DEL>a function or
object</DEL> <INS>an entity</INS> with C linkage may appear in
the program <INS>(see 6.3 [<A href="https://wg21.link/basic.def.odr">basic.def.odr</A>])</INS>; that
<DEL>is,</DEL> <INS>implies that</INS> such <DEL>a function or
object</DEL> <INS>an entity</INS> must not be defined in more
than one namespace scope. <INS>&#8212;<I>end note</I>]</INS>
<DEL>For example,</DEL> <INS>[<I>Example:</I></INS>
</P>

<PRE>
<INS>  int x;</INS>
  namespace A {
    extern "C" int f();
    extern "C" int g() { return 1; }
    extern "C" int h();
<INS>    extern "C" int x();               // <SPAN CLASS="cmnt">ill-formed: same name as global-scope object </SPAN>x</INS>
  }

  namespace B {
   extern "C" int f();                // A::f<SPAN CLASS="cmnt"> and </SPAN>B::f<SPAN CLASS="cmnt"> refer</SPAN>
                                      // <SPAN CLASS="cmnt">to the same function</SPAN>
   extern "C" int g() { return 1; }   // <SPAN CLASS="cmnt">ill-formed, the function </SPAN>g
                                      // <SPAN CLASS="cmnt">with C language linkage</SPAN>
                                      // <SPAN CLASS="cmnt">has two definitions</SPAN>
  }

  int A::f() { return 98; }           // <SPAN CLASS="cmnt">definition for the function </SPAN>f
                                      // <SPAN CLASS="cmnt">with C language linkage</SPAN>
  extern "C" int h() { return 97; }
                                      // <SPAN CLASS="cmnt">definition for the function </SPAN>h
                                      // <SPAN CLASS="cmnt">with C language linkage</SPAN>
                                      // A::h<SPAN CLASS="cmnt"> and </SPAN>::h<SPAN CLASS="cmnt"> refer to the same function</SPAN>
</PRE>

<P>&#8212;<I>end <DEL>note</DEL> <INS>example</INS></I>]</P>

</BLOCKQUOTE>

<P><B>Additional note (February, 2010):</B></P>

<P>The proposed wording above does not cover the case where two
different entities with C linkage are declared in different namespaces,
only the case where one of the entities is in global scope.</P>

<P><B>Proposed resolution (August, 2010):</B></P>

<P>Change 9.12 [<A href="https://wg21.link/dcl.link#6">dcl.link</A>] paragraph 6 as follows:</P>

<BLOCKQUOTE>

<P>At most one function with a particular name can have C
language linkage. Two declarations for a function with C
language linkage with the same function name (ignoring the
namespace names that qualify it) that appear in different
namespace scopes refer to the same function.  Two
declarations for <DEL>an object</DEL> <INS>a variable</INS>
with C language linkage with the same name (ignoring the
namespace names that qualify it) that appear in different
namespace scopes refer to the same <DEL>object</DEL>
<INS>variable</INS>. <INS>An entity with C language linkage
shall not be declared with the same name as an entity in
global scope, unless both declarations denote the same
entity; no diagnostic is required if the declarations appear
in different translation units. A variable with C language
linkage shall not be declared with the same name as a
function with C language linkage (ignoring the namespace
names that qualify the respective names); no diagnostic is
required if the declarations appear in different translation
units.</INS> [<I>Note:</I> <DEL>because of the one
definition rule (6.3 [<A href="https://wg21.link/basic.def.odr">basic.def.odr</A>]), only</DEL>
<INS>Only</INS> one definition for <DEL>a function or
object</DEL> <INS>an entity with a given name</INS> with C
<INS>language</INS> linkage may appear in the program
<INS>(see 6.3 [<A href="https://wg21.link/basic.def.odr">basic.def.odr</A>])</INS>; that
<DEL>is,</DEL> <INS>implies</INS> such <DEL>a function or
object</DEL> <INS>an entity</INS> must not be defined in
more than one namespace scope. <INS>&#8212;<I>end
note</I>]</INS> <DEL>For example,</DEL>
<INS>[<I>Example:</I></INS>
</P>

<PRE>
<INS>  int x;</INS>
  namespace A {
    extern "C" int f();
    extern "C" int g() { return 1; }
    extern "C" int h();
<INS>    extern "C" int x();               //<SPAN CLASS="cmnt"> ill-formed: same name as global-scope object </SPAN>x</INS>
  }

  namespace B {
    extern "C" int f();               //<SPAN CLASS="cmnt"> </SPAN>A::f<SPAN CLASS="cmnt"> and </SPAN>B::f<SPAN CLASS="cmnt"> refer</SPAN>
                                      //<SPAN CLASS="cmnt"> to the same function</SPAN>
    extern "C" int g() { return 1; }  //<SPAN CLASS="cmnt"> ill-formed, the function </SPAN>g
                                      //<SPAN CLASS="cmnt"> with C language linkage</SPAN>
                                      //<SPAN CLASS="cmnt"> has two definitions</SPAN>
  }

  int A::f() { return 98; }           //<SPAN CLASS="cmnt"><INS> </INS>definition for the function </SPAN>f
                                      //<SPAN CLASS="cmnt"> with C language linkage</SPAN>
  extern "C" int h() { return 97; }
                                      //<SPAN CLASS="cmnt"> definition for the function </SPAN>h
                                      //<SPAN CLASS="cmnt"> with C language linkage</SPAN>
                                      //<SPAN CLASS="cmnt"> </SPAN>A::h<SPAN CLASS="cmnt"> and </SPAN>::h<SPAN CLASS="cmnt"> refer to the same function</SPAN>
</PRE>

<P>&#8212;<I>end <DEL>note</DEL> <INS>example</INS></I>]</P>

</BLOCKQUOTE>

<P><I>[Note to editor: please consider reformatting the comments in the
example.]</I></P>

<BR><BR>
</BODY>
</HTML>
