Reputation: 21444
I have the following code:
in file Alfa.h
struct color
{
int r;
int g;
int b;
};
in file Beta.h
#include "Alfa.h"
void foo(struct color);
in file Gamma.h
#include "Alfa.h"
void bar(struct color);
in file main.c
#include "Beta.h"
#include "Gamma.h"
int main(void)
{
return 0;
}
Because I didn't write header guard macros I expected GCC with the following command:
gcc Alfa.h Beta.h Gamma.h main.c -std=c23 -Wall -Wextra -Wpedantic -o prog
to generate the following: error: redefinition of 'struct color'
However it seems that the error is only generated with compiler -std
flag below C23 (i.e. c17, c11 and so on).
Is this a bug or has something is changed?
Upvotes: 6
Views: 103
Reputation: 214770
This appears to have changed as per proposal N3037 Improved Rules for Tag Compatibility, which was voted in with C23.
From the proposal:
Tagged types with the same tag and content are already compatible across translation units but never inside the same translation unit. In the following example, ‘p’ and ‘r’ and also ‘q’ and ‘r’ have compatible types, while ‘p’ and ‘q’ do not have compatible types.
// TU 2 struct foo { int a; } p; void bar(void) { struct foo { int a; } q; } // TU 3 struct foo { int a; } r;
(The above is as per C17 6.2.7.)
Here, it is proposed to 1) make tagged types with the same tag and content compatible inside the same translation unit and to 2) allow redeclaration of the same tagged type.
Details of what exactly was changed in the standard's wording with C23 can be found in the linked pdf.
Upvotes: 7
Reputation: 223795
C 2018 6.7.2.1 8 says:
The presence of a struct-declaration-list in a struct-or-union-specifier declares a new type, within a translation unit.
This sentence does not appear in C 2024, nor do I see anything substantially similar in meaning with different wording. The struct-declaration-list grammar token is the list of declarations of members in a structure or union type. So the assertion that a definition of a structure or union creates a new type was removed.
C 2024 6.7.3.4, about tags, adds this to the corresponding clause in C 2018, 6.7.2.3:
If two declarations of the same type have a member-declaration or enumerator-list, one shall not be nested within the other and both declarations shall fulfill all requirements of compatible types (6.2.7) with the additional requirement that corresponding members of structure or union types shall have the same (and not merely compatible) types.
Nate Eldridge also noted in a comment that C 2024 omits this sentence from C 2018 6.7.2.3 1:
A specific type shall have its content defined at most once.
So it seems there was an intentional change in the standard to allow redefining a structure or union (with effectively the same definition).
Upvotes: 7