简体   繁体   中英

Is typedef allowed before definition

Minimum code:

// foo.h

typedef struct foo_s foo_t;

struct foo_s {
  foo_t* next;
};

iwyu insists I forward declare struct foo_s before I typedef it to foo_t .

Output:

$ iwyu -c foo.h 

foo.h should add these lines:
struct foo_s;

foo.h should remove these lines:

The full include-list for foo.h:
struct foo_s;
---

This is true across different versions of iwyu , including newer versions with -Xiwyu --no_fwd_decls added.

Is this a mistake in iwyu or does the C standard want me to define the type before the typedef ?

does the C standard want me to define the type before the typedef ?

It does not. The standard verbiage is as follows

6.7.2.3 Tags

7 A declaration of the form

 struct-or-union identifier;

specifies a structure or union type and declares the identifier as a tag of that type.

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 your original pair of declarations has well-defined behavior. The declaration for the structure is implicitly added into the translation unit at the point you define the type alias, and then completed afterward. The fact that the tool does not allow it may be due to a bug, a limitation of the tool, or perhaps an attempt to enforce a particular coding style.


There is one point in favor of the style that the tool may try to enforce, and it has to do with the C notion of scope. Specifically, function parameter list scope. As an example, see this Q&A and refer to this short example

void bar(struct foo);

struct foo {
    char c;
};

void bar(struct foo f) {}

It so happens that the first declaration of bar is declared with a type that is unique to its parameter list. The initial declaration of struct foo is not the same type as the one used in the later function definition. As such, the code will not compile by a conforming C compiler. Declaring the structure on its own line ahead of the first function declaration fixes this problem.

This C11 Draft Standard makes it quite clear that you can 'forward declare' a typedef struct... , by way of an example that is very similar to your code:

6.7.2.3 Tags
...
11 The following alternative formulation uses the typedef mechanism:

 typedef struct tnode TNODE; struct tnode { int count; TNODE *left, *right; }; TNODE s, *sp;

It is a bug. It seems the typedef for a structure is considered the same way as a typedef for an enumeration.

For enumerations you may not use an incomplete type in a typedef definition

From the C Standard (6.7.2.3 Tags)

3 A type specifier of the form

enum identifier 

without an enumerator list shall only appear after the type it specifies is complete.

So for example such a typedef

typedef enum E AnotherE;

enum E { N };

is invalid while this typedef

enum E { N };

typedef enum E AnotherE;

is valid.

For structures you may use an incomplete type in a typedef definition.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM