1
votes

I'm trying to understand linkage of enumeration constants and could not find a clear answer in the Standard N1570. 6.2.2(p6):

The following identifiers have no linkage: an identifier declared to be anything other than an object or a function; an identifier declared to be a function parameter; a block scope identifier for an object declared without the storage-class specifier extern.

So I need to understand that constants are not objects. Object is defined as 3.15:

region of data storage in the execution environment, the contents of which can represent values

Also 6.2.2(p4) (emphasize mine):

For an identifier declared with the storage-class specifier extern in a scope in which a prior declaration of that identifier is visible,31) if the prior declaration specifies internal or external linkage, the linkage of the identifier at the later declaration is the same as the linkage specified at the prior declaration. If no prior declaration is visible, or if the prior declaration specifies no linkage, then the identifier has external linkage.

Anyway 6.4.4.3(p2):

An identifier declared as an enumeration constant has type int.

Combining all that I don't understand why

enum test {
    a = 1
};

extern int a; //compile-error. UB?

does not compile? I expected a to have external linkage.

LIVE DEMO

Is the behavior well-defined? Can you provide a reference to the Standard explaining that?

3
your question does not make any sense. You just try to have two same symbols in the same compilation unit.0___________
@P__J__ your question does not make any sense Why? I provided the behavior and asked its explanation? Is it well-defined/undifened/unspecified behavior?Some Name
It same as int a; extern int a; why this do not compile. It is exactly the same two same symbols in one compilation unit. It does not have anything in common with the linkage.0___________
Something can have an identifier without being an object. Enumeration constants are in the same category as integer constants 123 and character constants 'A'.Lundin
@SomeName If you do not agree you need to write your own compiler.0___________

3 Answers

3
votes

In 6.2.2 4, the standard intends to discuss linkage only for identifiers of objects and functions, but it fails to make this clear.

Enumeration constants are mere values, not objects or functions, and their identifiers never have any linkage.

Observe the declaration extern int a; declares a as an identifier for an int object. An int object is a different thing from an int value, so an enumeration constant named a cannot be the same thing as an int object named a. So the declaration of extern int a; is invalid even before linkage is considered.

8
votes

An identifier declared as an enumeration constant has type int

that doesn't means it is a variable of type int

but

extern int a;

says there is a variable of type int named a, this is a conflict with the enumeration constant


Why does not enumeration constant have no linkage

for the same reason the constant 123 (also having type int, but whatever) has no linkage too

2
votes

Linkage does not matter here. In the same compilation unit you try to have two same identifiers Imagine if the code compiles:

enum test {
    a = 1
};

extern int a; 


int b = a;   // which `a`? a as the external variable or `a` as a constant? How to decide.

enter image description here