Various prototypes adopted by Clang, GCC for the same function

I would like to report a bug against Clang and GCC for adopting multiple incompatible prototypes for the same function.

Consider the examples below:

$ clang -v
Ubuntu clang version 3.4-1ubuntu3 (tags / RELEASE_34 / final) (based on LLVM 3.4)
Target: x86_64-pc-linux-gnu
...
$ gcc -v
...
gcc version 4.8.2 (Ubuntu 4.8.2-19ubuntu1) 
$ cat t1.c
int f (void);

float f (void);
$ gcc -c t1.c
t1.c: 3: 7: error: conflicting types for 'f'
 float f (void);
       ^
t1.c: 1: 5: note: previous declaration of 'f' was here
 int f (void);
     ^
$ clang -c t1.c
t1.c: 3: 7: error: conflicting types for 'f'
float f (void);
      ^
t1.c: 1: 5: note: previous declaration is here
int f (void);
    ^
1 error generated.

Both GCC and Clang conform to what I will call "expected behavior". However, if the parameter is f

set to enum

or unsigned int

:

$ cat t2.c
typedef enum { m1 } t ;

t f();

unsigned int f();
$ gcc -c t2.c
$ clang -c t.c

      

When the return types in two separate declarations f

are simple enum

and unsigned int

neither GCC nor Clang will issue diagnostics. I would like to report this behavior as a bug. In the C11 standard in clause 6.2.7: 2, two programs t1.c and t2.c above undefined are executed:

6.2.7: 2 All declarations referring to the same object or function must be of a compatible type; otherwise, the behavior is undefined.

However, 6.2.7: 2 is not inside the Restrictions section , so the two compilers are allowed to do what they want with these undefined behaviors, including their silence. Is there any other proposal that would make diagnostics mandatory in a program like t2.c and would it be right to report no diagnostics as a compiler error? Or am I wrong in expecting the enumerated type is incompatible with unsigned int

?

+3


source to share


2 answers


The "expected behavior" for the first example is required by the constraints in C11 (n1570) 6.7 p4:

All declarations in the same scope that refer to the same object or function must specify compatible types.

As pointed out by your answer , enum types can be compatible with unsigned int

what they usually are in the case of Gcc :

Typically, type unsigned int

if there are no negative values ​​in the enumeration, otherwise int

. If specified -fshort-enums

, then if there are negative values, it is the first of signed char

, short

and int

, which can represent all values, otherwise it is the first of unsigned char

, unsigned short

and unsigned int

, which can represent all values.



(I couldn't find a suitable part in the Clang documentation, but I expect it to be the same.)

For the second example, diagnostics are required if and only if the enumeration type is incompatible with unsigned int

. If it is not, the behavior (outside diagnostics) of undefined follows the standard quote in the question.

OT: In C ++, the second code is not valid because enumeration types are themselves incompatible with other integer types.

+2


source


I found the answer as I wrote the last sentence in the above question:

In t2.c. no undefined behavior. Each type listed is compatible with one simple integer type selected by the compiler. In the example t2.c, GCC and Clang have opted unsigned int

for enum

typedef'd compatibility as t

.



6.7.2.2:4 Each enumerated type shall be compatible with char, signed integer type, or unsigned integer type. The choice of type is implementation-defined, 128 but must be able to display the values ​​of all enumeration members [...]

128) An implementation MAY delay the selection of an integer type until all the enumeration constants are visible.

+5


source







All Articles