Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

If I don't odr-use a variable, can I have multiple definitions of it across translation units?

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?

like image 820
Joseph Mansfield Avatar asked Oct 19 '12 16:10

Joseph Mansfield


People also ask

What does odr used mean?

10. +1 for the succinct opening sentence: "In plain word, odr-used means something(variable or function) is used in a context where the definition of it must be present."

What is inline variable?

A variable declared inline has the same semantics as a function declared inline: it can be defined, identically, in multiple translation units, must be defined in every translation unit in which it is used, and the behavior of the program is as if there was exactly one variable.

What is inline specifier?

An inline function is one for which the compiler copies the code from the function definition directly into the code of the calling function rather than creating a separate set of instructions in memory.


1 Answers

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.

like image 109
James McNellis Avatar answered Nov 09 '22 10:11

James McNellis