From the latest C2x (6.9p5) (emphasis added):
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 typeof operator whose result is not a variably modified type, or a sizeof or alignof operator whose result is an integer constant expression), somewhere in the entire program there shall be exactly one external definition for the identifier; otherwise, there shall be no more than one.
Consider this program:
extern int x;
int i = _Generic(x, default: 0);
int main(void)
{
}
As I understand per the quote above somewhere in the entire program there shall be exactly one external definition for the identifier x
. Is that correct? FYI: popular compilers don't complain.
Perhaps 6.9p5 misses _Generic
?
I'm also confused with "otherwise, there shall be no more than one". Hence, extra questions:
- What "otherwise ..." is related to? To "somewhere in the entire program there shall be exactly one external definition for the identifier" OR to "an identifier declared with external linkage is used in an expression (other than ...)"?
- If "otherwise ..." is related to "somewhere in the entire program there shall be exactly one external definition for the identifier", then I interpret the whole quote (6.9p5) as
ext_def_cnt == 1 || ext_def_cnt <= 1
, which is redundant (because it can be folded toext_def_cnt <= 1
). Can someone comment on that?
CodePudding user response:
_Generic
was added to the C standard years after the language about requiring a definition was already established, and failing to add an exception about it to 6.9 5 was an oversight.
Clearly the intent of 6.9 5 is that if a program needs a definition for an object or function, because the object or function is actually used, then there must be a definition. But if the identifier is used in a context where only its type is needed, not the object or function it hypothetically refers to, then no definition is needed.
I'm also confused with "otherwise, there shall be no more than one".
If an object or function is used, there needs to be a definition. This is a logical necessity: There is no way to use a thing that does not exist.
If an object or function is declared but not used, there does not need to be a definition. This allows slack in designing headers or source code generally: You can declare things that might or might not be linked into a program and used, and it will not be an error if they are declared but never used or defined.
CodePudding user response:
Perhaps 6.9p5 misses
_Generic
?
No, "If an identifier declared with external linkage is used in an expression (other than as part of the operand of a typeof
operator whose result is not a variably modified type, or a sizeof
or alignof
operator whose result is an integer constant expression), somewhere in the entire program there shall be exactly one external definition for the identifier; otherwise, there shall be no more than one" - so, no external definition is required if used as an operand of a typeof
operator.
From 6.5.1.1 Generic selection
:
- 3 The controlling expression of a generic selection is not evaluated. If a generic selection has a generic association with a type name that is compatible with the type of the controlling expression, then the result expression of the generic selection is the expression in that generic association. Otherwise, the result expression of the generic selection is the expression in the default generic association.
The variable x
's type, int
, is known and that's all that is used in order to make the correct generic association. x
, being the controlling expression, is never actually evaluated.
If anything is missing, it is in the typeof
and/or _Generic
chapters failing to mention that _Generic
acts as-if using a typeof
operator (unevaluated).