Bug 112556 - Null pointer constants with enumeration type are not accepted
Summary: Null pointer constants with enumeration type are not accepted
Status: NEW
Alias: None
Product: gcc
Classification: Unclassified
Component: c (show other bugs)
Version: 14.0
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: rejects-valid
Depends on:
Blocks:
 
Reported: 2023-11-16 01:55 UTC by Halalaluyafail3
Modified: 2024-06-27 18:12 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2024-06-27 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Halalaluyafail3 2023-11-16 01:55:38 UTC
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).
Comment 1 Halalaluyafail3 2023-11-16 05:15:10 UTC
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.
Comment 2 jsm-csl@polyomino.org.uk 2023-11-16 17:38:22 UTC
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).
Comment 3 Andrew Pinski 2024-06-27 18:12:56 UTC
Confirmed a bug by JSM already.