16

The standard seems to imply that there is no restriction on the number of definitions of a variable if it is not odr-used (§3.2/3):

Every program shall contain exactly one definition of every non-inline function or variable that is odr-used in that program; no diagnostic required.

It does say that any variable can't be defined multiple times within a translation unit (§3.2/1):

No translation unit shall contain more than one definition of any variable, function, class type, enumeration type, or template.

But I can't find a restriction for non-odr-used variables across the entire program. So why can't I compile something like the following:

// other.cpp
int x;

// main.cpp
int x;
int main() {}

Compiling and linking these files with g++ 4.6.3, I get a linker error for multiple definition of 'x'. To be honest, I expect this, but since x is not odr-used anywhere (as far as I can tell), I can't see how the standard restricts this. Or is it undefined behaviour?

Joseph Mansfield
  • 108,238
  • 20
  • 242
  • 324

4 Answers4

11

Your program violates the linkage rules. C++11 §3.5[basic.link]/9 states:

Two names that are the same and that are declared in different scopes shall denote the same variable, function, type, enumerator, template or namespace if

  • both names have external linkage or else both names have internal linkage and are declared in the same translation unit; and

  • both names refer to members of the same namespace or to members, not by inheritance, of the same class; and

  • when both names denote functions, the parameter-type-lists of the functions are identical; and

  • when both names denote function templates, the signatures are the same.

(I've cited the complete paragraph, for reference. The second two bullets do not apply here.)

In your program, there are two names x, which are the same. They are declared in different scopes (in this case, they are declared in different translation units). Both names have external linkage and both names refer to members of the same namespace (the global namespace).

These two names do not denote the same variable. The declaration int x; defines a variable. Because there are two such definitions in the program, there are two variables in the program. The name "x" in one translation unit denotes one of these variables; the name "x" in the other translation unit denotes the other. Therefore, the program is ill-formed.

James McNellis
  • 348,265
  • 75
  • 913
  • 977
  • 3
    How do you reach the conclusion that the two names `x` do not denote the same variable? – ecatmur Oct 19 '12 at 17:39
  • 1
    @ecatmur: There are two variables because there are two definitions: `int x;` defines a variable with static storage duration. There are two such definitions, therefore there are two variables. If the program were modified as suggested by Luc Danton, there would only be one variable because there would be only one definition (`extern int x;` is not a _definition_ of `x`; it is only a _declaration_). – James McNellis Oct 19 '12 at 17:45
  • If instead of `int x;` the declarations took the form `class y {};` or `namespace z {}` (both definitions), the names `y` and `z` would denote the same type or namespace respectively. How is the variable `x` any different? – ecatmur Oct 19 '12 at 17:57
  • 2
    @ecatmur: §3.2[basic.def.odr]/5 permits that "There can be more than one definition of a class type." If `class y {};` appears in two translation units, then in both translation units, the name `y` denotes _the class named `y`_. There is only one class named `y`. In the case of `namespace z {}`, "the definition of a namespace can be split over several parts of one or more translation units" (§7.3[basic.namespace]/1). The name `z` in both translation units refers to _the namespace named _z_. There is only one namespace named `z`. – James McNellis Oct 19 '12 at 18:09
  • I think that referring to names (and declarations thereof) makes for a bit of a mess -- after all there are plenty of ways a program may introduce the same name separately, in different TUs or not, to refer to just one entity or not. It would perhaps be more interesting to follow how many entities there are, regardless of their name. If there's just one, then we have the OP's question: two definitions, one program, one entity. If there are two, then tentatively we would like to preempt the question by stating that the program is incorrect. – Luc Danton Oct 19 '12 at 18:41
  • As things are, I don't think the relationship between an object and its definition (definitions?) is as obvious as you make it appear. That being said, I don't know how to improve the answer. – Luc Danton Oct 19 '12 at 18:42
  • 3
    For 3.2p6 or 7.3p1 to apply you need to have already decided (via 3.5p9) that the names denote the same entity. (This is critical for inline functions, where overloading comes into play.) 3.5p9 is an instruction to the implementor, not the programmer; it describes how translation units can communicate (2.1p2). Otherwise two definitions in the same translation unit would denote different entities, and 3.2p1 would be meaningless. – ecatmur Oct 19 '12 at 19:42
  • @ecatmur: At this point, I am not sure, and you may be right. – James McNellis Oct 19 '12 at 19:51
  • This answer is clearly incorrect. Counterexample: __TU1__ : `inline void f() {}` __TU2__ `inline f() {}; int main() {}`. By your reasoning this program is ill-formed. [basic.link]/9 applies to it just as it does to the OP, yet it clearly isn't ill-formed. – Andrew Tomazos Sep 12 '13 at 16:59
  • I agree with @ecatmur that this answer looks incorrect. The "shall" appears to have been intended to state a requirement on the implementation and not the program. If we take away the "shall", it becomes more clear what I think the text is meant to say. – Johannes Schaub - litb Sep 12 '13 at 19:57
  • @JohannesSchaub-litb: I think it's even simpler than that. There are entities that have zero, one or multiple definitions in a program. [basic.link] doesn't say anything about how many definitions a given entity may have. For some entities the number of allowed definitions is addressed in [basic.def.odr]. The fact that the definition count of some entities is not addressed in [basic.def.odr] is a standard defect imho. – Andrew Tomazos Sep 12 '13 at 20:31
  • The fix for this defect is to change [basic.def.odr]/6 from "There can be more than one definition of X in a program", to "There shall not be multiple definitions of an entity in a program, unless the entity is X". I haven't had time to write up formal wording and file the defect. The intention is pretty clear from implementation behaviour. – Andrew Tomazos Oct 05 '13 at 15:55
  • Recent edits have clarified that these declare the same `x`; they just do so badly and should be (but are not) disallowed by [basic.def.odr]. – Davis Herring Jul 06 '21 at 14:17
8

You're correct that the standard is at fault in this regard. I have a feeling that this case falls into the gap between 3.2p1 (at most one definition per translation unit, as in your question) and 3.2p6 (which describes how classes, enumerations, inline functions, and various templates can have duplicate definitions across translation units).

For comparison, in C, 6.9p5 requires that (my emphasis):

An external definition is an external declaration that is also a definition of a function (other than an inline definition) or an object. If an identifier declared with external linkage is used in an expression (other than as part of the operand of a sizeof or _Alignof operator whose result is an integer constant), somewhere in the entire program there shall be exactly one external definition for the identifier; otherwise, there shall be no more than one.

ecatmur
  • 152,476
  • 27
  • 293
  • 366
1

If standard does not say anything about definitions of unused variables then you can not imply that there may be multiple:

Undefined behavior may also be expected when this International Standard omits the description of any explicit definition of behavior.

So it may compile and run nicely or may stop during translation with error message or may crash runtime etc.

EDIT: See James McNellis answer the standard indeed actually has rules about it.

Öö Tiib
  • 10,809
  • 25
  • 44
  • The program does not exhibit undefined behavior; it is ill-formed. It violates a diagnosable semantic rule. – James McNellis Oct 19 '12 at 17:06
  • @James yes, it is ill formed, but what i said still holds, if standard omits describing something then it is always not defined what happens, reader may not just imply random thing. – Öö Tiib Oct 19 '12 at 17:19
0

There is no error in compiling that, the error is in its linkage. By default your global variable or functions are public to other files(have extern storage) so at the end when linker want to link your code it see two definition for x and it can't select one of them, so if you do not use x of main.cpp in other.cpp and vice-verse make them static(that means only visible to the file that contain it)

// other.cpp
static int x;

// main.cpp
static int x;
BigBoss
  • 6,904
  • 2
  • 23
  • 38