Does the C standard consider that there are one or two ‘struct uperms_entry’ types in this header?

In C1, they refer to the same type. C99 §6.2.1 defines the scopes that exist:

2 For each different entity that an identifier designates, the
identifier is visible (i.e., can be used) only within a region of
program text called its scope. Different entities designated by the
same identifier either have different scopes, or are in different name
spaces. There are four kinds of scopes: function, file, block, and
function prototype. (A function prototype is a declaration of a
function that declares the types of its parameters.)

Function scope only applies to labels (as explicitly stated later in the same section). Block scope applies to identifiers declared in blocks – blocks are created by compound-statements, iteration-statements and selection-statements (and not by struct declarations or compound initialisers). Function prototype scope applies to identifiers declared within a function prototype declaration.

None of these apply to your example – all of the mentions of struct uperms_entry in your example are at file scope.

C99 §6.7.2.3 says:

1 All declarations of structure, union, or enumerated types that have
the same scope and use the same tag declare the same type. The type is incomplete until the closing brace of the list defining the content, and complete thereafter.

This is pretty clear, and applies to your case.

Paragraph 8 of that section applies to the first mention of struct uperms_entry:

8 If a type specifier of the form struct-or-union identifier occurs
other than as part of one of the above forms, 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.

So at that point it’s declared as an incomplete type at file scope. Paragraph 6 applies to the second mention of struct uperms_entry:

6 A type specifier of the form struct-or-union
identifieropt { struct-declaration-list }
or enum
identifier { enumerator-list }
or enum identifier { enumerator-list
, }
declares a structure, union, or enumerated type. The list defines
the structure content, union content, or enumeration content. If an
identifier is provided, the type specifier also declares the
identifier to be the tag of that type.

So after the } at the end of that typedef declaration, it’s now a complete type.

The adjunct questions are moot.


1. I believe that this is not the case in C++, however.

Leave a Comment