The following code is not accepted in GCC: void*p=(enum{E})E; To make it clear why this code should be accepted, I have provided some references to the current C standard. > An integer constant expression with the value 0, > or such an expression cast to type void *, is called > a null pointer constant. If a null pointer constant is > converted to a pointer type, the resulting pointer, > called a null pointer, is guaranteed to compare unequal > to a pointer to any object or function. Section 6.3.2.3 "Pointers" Paragraph 1 ISO/IEC 9899:2018 > An integer constant expression shall have integer type > and shall only have operands that are integer constants, > enumeration constants, character constants, sizeof > expressions whose results are integer constants, > _Alignof expressions, and floating constants that are > the immediate operands of casts. Cast operators in an > integer constant expression shall only convert arithmetic > types to integer types, except as part of an operand > to the sizeof or _Alignof operator. Section 6.6 "Constant expressions" Paragraph 6 ISO/IEC 9899:2018 > The type char, the signed and unsigned integer types, > and the enumerated types are collectively called > integer types. The integer and real floating types are > collectively called real types. > > Integer and floating types are collectively called > arithmetic types. Each arithmetic type belongs to > one type domain: the real type domain comprises the > real types, the complex type domain comprises the > complex types. Section 6.2.5 "Types" Paragraphs 17 and 18 ISO/IEC 9899:2018 (enum{E})E is an integer constant expression because E is an enumeration constant, and the cast is converting an arithmetic type (int) to an integer type (the enumeration type). This integer constant expression has the value zero, so it is a null pointer constant. This problem seems to be specific to null pointer constants, for example the type int(*)[(enum{A,B})B] is not considered to be a variable length array type (which is correct).
This bug also seems to happen with boolean types: void*p=(_Bool)0; Furthermore, this bug only seems to happen when the type of the null pointer constant is an enumeration or boolean type: void*p1=+(_Bool)0,*p2=+(enum{E})E; No errors are generated for this code.
Yes, this is a bug; null_pointer_constant_p gets this right, but convert_for_assignment fails to handle enumerations and booleans as possible null pointer constants. Other contexts such as comparisons and conditional expressions appear to be OK (through performing integer promotions so that enumerations and booleans can't appear, for example, or through handling all kinds of integer types together).
Confirmed a bug by JSM already.