Imagine we have this:

```
void f(struct s *);

```

From reading the standard ($6.2.1) I'm kinda confused at what is the scope of tags. First there is this:

> 
> 3. A label name is the only kind of identifier that has function scope. It can be used (in a
>  goto statement) anywhere in the function in which it appears, and is declared implicitly
>  by its syntactic appearance (followed by a : and a statement).
> 4. Every other identifier has scope determined by the placement of its declaration (in a declarator or type specifier). If the declarator or
>  type specifier that declares the identifier appears outside of any
>  block or list of parameters, the identifier has file scope, which
>  terminates at the end of the translation unit. If the declarator or
>  type specifier that declares the identifier appears inside a block or
>  within the list of parameter declarations in a function definition,
>  the identifier has block scope, which terminates at the end of the
>  associated block. **If the declarator or type specifier that declares
>  the identifier appears within the list of parameter declarations in a
>  function prototype (not part of a function definition), the identifier
>  has function prototype scope, which terminates at the end of the
>  function declarator.** If an identifier designates two different
>  entities in the same name space, the scopes might overlap. If so, the
>  scope of one entity (the inner scope) will end strictly before the
>  scope of the other entity (the outer scope). Within the inner scope,
>  the identifier designates the entity declared in the inner scope; the
>  entity declared in the outer scope is hidden (and not visible) within
>  the inner scope.
> 
> 
> 

As identifier properties being early defined as:

> 
> 1. **An identifier can denote** an object; a function; **a tag or a member of a structure**, union, or enumeration; a typedef name; a label name; a
>  macro name; or a macro parameter. The same identifier can denote
>  different entities at different points in the program. A member of an
>  enumeration is called an enumeration constant. Macro names and macro
>  parameters are not considered further here, because prior to the
>  semantic phase of program translation any occurrences of macro names
>  in the source file are replaced by the preprocessing token sequences
>  that constitute their macro definitions.
> 
> 
> 

Which leads me to this conclusion:

As the type specifier `struct s` declares the identifier `s` within "the list of parameter declarations in a function prototype" it has (the identifier `s`) function prototype scope. Which means something like this:

```
void f2()
{ //inside **some** function block after the above declaration
    struct s { int a; } v; //new s identifier being declared

    f(&v); //not compatible types
}

```

But then after this we have:

> 
> 7. **Structure, union, and enumeration tags have scope that begins just after the appearance of the tag in a type specifier that declares the
>  tag.** Each enumeration constant has scope that begins just after the
>  appearance of its defining enumerator in an enumerator list. Any other
>  identifier has scope that begins just after the completion of its
>  declarator.
> 
> 
> 

Which means something entirely different:

```
void f3()
{ //inside **some** function block after the above declaration
    struct s { int a; } v; //completing incomplete type

    f(&v); //ok
}

```

Seems like gcc and clang follows p4 (summered up with this warning of compiling the declaration of `f`):

```
warning: ‘struct s’ declared inside parameter list will not be visible outside of this definition or declaration
void f(struct s *);

```

Similar is the case using clang:

```
warning: declaration of 'struct s' will not be visible outside of this function [-Wvisibility]
void f(struct s *);

```

Anyone care to explain what is the right way to determine the scope of the `s` identifier in the function prototype `f`?

I'm referring to INCITS/ISO/IEC 9899-2011[2012] standard paper; compiling with gcc compiler (and clang) with the following flags:

```
-std=c11 -pedantic

```

Request for a complete piece of code:

Currently (by compiling with GCC and clang) this:

```
void f(struct s {int _;});

struct s g;

```

Will give the following error (by clang):

```
prog.c:1:15: warning: declaration of 'struct s' will not be visible outside of this function [-Wvisibility]
void f(struct s {int _;});
              ^
prog.c:3:10: error: tentative definition has type 'struct s' that is never completed
struct s g; 
         ^
prog.c:3:8: note: forward declaration of 'struct s'
struct s g; 

```

Which by quoting the standard may or may not be the right behavior in the case (conflicting p4 and p7 - or are they? - I don't know).

By p7 `struct s` in the declaration of `g` should refer to the same identifier declared in the function prototype of `f`. And so there shouldn't be any compiler errors caused by defining a variable with incomplete type.

But by p4 `struct s` declared in the function prototype of `f` must have scope which terminates at the end of the function declarator. And so then the declaration of `struct s` in the declaration of `g` should create another identifier `s` (being a tag of incomplete structure and so the error messages).