A type without linkage shall not be used as the type of a variable or function with external linkage

139 views
Skip to first unread message

mikhailse...@gmail.com

unread,
Apr 6, 2014, 9:30:38 AM4/6/14
to std-dis...@isocpp.org
I am looking at N3936, 3.5, paragraph 8:

A type without linkage shall not be used as the type of a variable or function with external linkage unless

— the entity has C language linkage (7.5), or

— the entity is declared within an unnamed namespace (7.3.1), or

— the entity is not odr-used (3.2) or is defined in the same translation unit.

But according to 3.2, entities in the unnamed namespace have internal linkage anyway. My understanding is

that the following line should be dropped:

— the entity is declared within an unnamed namespace (7.3.1), or


David Krauss

unread,
Apr 6, 2014, 12:39:21 PM4/6/14
to std-dis...@isocpp.org
The entire rule seems to be redundant with paragraph 10, which requires declarations of an entity to have matching types. If the entity is ODR-used in the TU but not defined, that implies that it must be declared in another TU, which cannot possibly name the correct type.

On one hand, it’s good to clarify when two things interact. On the other, this list of rules may be too subtle. I don’t see how entities of C language linkage are exempted from ¶10, so it’s a little misleading. Things work when you apply the C “compatible type” criteria: the other TU doesn’t name the correct type according to C++, but C is yet able to define the behavior, by giving each TU its own distinct set of user-defined types. However, the C++ spec doesn’t really describe linkage of C with C++ TUs; it only describes extern "C" semantics within C++ programs. So, this rule appears to be correct only as part of a C/C++ interface spec that otherwise does not exist.

I think the first bullet point is thus misguided, the second is redundant since C++11 changed linkage of unnamed namespace members, and the third is redundant with §3.5/10. Everything after “A type without linkage shall not be used…” may be deleted, and probably should. Perhaps something should be done with the examples, I don’t know.

David Krauss

unread,
Apr 6, 2014, 9:47:08 PM4/6/14
to std-dis...@isocpp.org
Actually, §3.5/10 is NDR but ¶8 requires a diagnostic. It would be better for 3.5/10 to mention what conditions require diagnosis, if ever.

Clang appears to provide a diagnosis by setting some kind of internal-linkage flag on an object whose type has internal linkage. In any case, it provides a warning like this:

warning: variable 'q' has internal linkage but is not defined [-Wundefined-internal]

However, if q is declared extern "C++", its name is not hidden from other TUs and the program may successfully compile. To be clear, the warning says q has internal linkage, but aside from the program being ill-formed, it has external linkage.

GCC (4.9) and ICC (13.0.1 on godbolt.org) do not diagnose ¶8. The common ABI does not mangle object names, which hinders diagnosis.

Since common compilers don’t seem to provide a diagnosis, except Clang with a somewhat misleading message, I’ll stick by my suggestion only to modify ¶8 and let all the cases be NDR.

Johannes Schaub

unread,
Apr 8, 2014, 4:10:56 PM4/8/14
to std-dis...@isocpp.org
2014-04-07 3:47 GMT+02:00 David Krauss <pot...@gmail.com>:
> Actually, §3.5/10 is NDR but ¶8 requires a diagnostic. It would be better
> for 3.5/10 to mention what conditions require diagnosis, if ever.
>

That 3.5/10 requires a diagnostic is a little silly for in-TU
declarations of the same entity. So compilers are allowed to not give
a diagnostic for

void f();
int f();

I don't believe that this is good. What case exists for in-TU type
mismatches that is too hard for implementations to diagnose?
Reply all
Reply to author
Forward
0 new messages