In a file struct_test.c I write:
static struct x x;
and I compile with GCC (4.8.2, Ubuntu)
gcc -c -O0 struct_test.c
I get the understandable error:
error: storage size of 'x' isn't known
Then I recompile, this time with optimization turned on
gcc -c -O struct_test.c
and the file is compiled without error.
I can kind of understand why turning on optimization removed the error but can someone help me to get the actual compiler option which is instructing gcc to ignore the undefined tag 'x'?
When it appears at file scope, this code:
static struct x x;
declares x
as an object of type struct x
and having internal linkage. The type struct x
need not have previously been declared:
If a type specifier of the form
struct-or-union identifier
occurs other than [in a struct type declaration], and no other declaration of the identifier as a tag is visible, then it declares an incomplete structure or union type, and declares the identifier as the tag of that type.
(C99 6.7.2.3/8)
A structure or union type that is incomplete when first encountered in a translation unit can nevertheless be completed later in that translation unit:
A structure or union type of unknown content [...] is an incomplete type. It is completed, for all declarations of that type, by declaring the same structure or union tag with its defining content later in the same scope.
(C99 6.2.5/22)
C discriminates between "declarations" generally, which specify the type of an object, and "definitions", which both specify the type and cause storage to be reserved. In a given translation unit, declarations that are not definitions may have incomplete type that is never completed within that unit.
Section 6.9.2 of C99 specifies which file-scope object declarations are definitions:
0
.This section also specifies that "If the declaration of an identifier for an object is a tentative definition and has internal linkage, the declared type shall not be an incomplete type." That applies here, but since a type that is incomplete at one point in the translation unit can be completed by a later declaration, it does not inherently invalidate the line of code in question. However, it does invalidate a translation unit containing only that line.
Inasmuch as the code given, taken as a complete translation unit, violates a "shall not" language constraint, it yields undefined behavior. GCC is not obligated to reject the code or produce any kind of diagnostic, though it is permitted to do either or both. As it turns out, regardless of optimization level, gcc
does issue a warning about the code if the -Wall
or -pedantic
flag is turned on. Any way around, gcc
explicitly disclaims being a tool for validating standard compliance of your code.
This particular violation is relatively benign, however. Because the object is never referenced, gcc
can pretend it was never even declared without risking wrong or unintended behavior.
The -fdce
(dead code elimintation) option seems to be one that affects this particular behavior. Oddly, although -fdce
is enough to suppress the error at optimization level O0
, -fno-dce
does not bring it back at higher optimization levels.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With