diff options
author | Joseph Myers <josmyers@redhat.com> | 2024-11-18 22:24:48 +0000 |
---|---|---|
committer | Joseph Myers <josmyers@redhat.com> | 2024-11-18 22:26:21 +0000 |
commit | 3d525fce70fa0ffa0b22af6e213643e1ceca5ab5 (patch) | |
tree | 15296e6c9acc973d89211c207e3fdcf384ff672b /gcc | |
parent | ea1506adbe7544bb51fc74a0fae3fa6fa0c68661 (diff) | |
download | gcc-3d525fce70fa0ffa0b22af6e213643e1ceca5ab5.zip gcc-3d525fce70fa0ffa0b22af6e213643e1ceca5ab5.tar.gz gcc-3d525fce70fa0ffa0b22af6e213643e1ceca5ab5.tar.bz2 |
c: Allow bool and enum null pointer constants [PR112556]
As reported in bug 112556, GCC wrongly rejects conversion of null
pointer constants with bool or enum type to pointers in
convert_for_assignment (assignment, initialization, argument passing,
return). Fix the code there to allow BOOLEAN_TYPE and ENUMERAL_TYPE;
it already allowed INTEGER_TYPE and BITINT_TYPE.
This bug (together with -std=gnu23 meaning false has type bool rather
than int) has in turn resulted in people thinking they need to fix
code using false as a null pointer constant for C23 compatibility.
While such a usage is certainly questionable, it has nothing to do
with C23 compatibility and the right place for warnings about such
usage is -Wzero-as-null-pointer-constant. I think it would be
appropriate to extend -Wzero-as-null-pointer-constant to cover
BOOLEAN_TYPE, ENUMERAL_TYPE and BITINT_TYPE (in all the various
contexts in which that option generates warnings), though this patch
doesn't do anything about that option.
Bootstrapped with no regressions for x86-64-pc-linux-gnu.
PR c/112556
gcc/c/
* c-typeck.cc (convert_for_assignment): Allow conversion of
ENUMERAL_TYPE and BOOLEAN_TYPE null pointer constants to pointers.
gcc/testsuite/
* gcc.dg/c11-null-pointer-constant-1.c,
gcc.dg/c23-null-pointer-constant-1.c: New tests.
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/c/c-typeck.cc | 2 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/c11-null-pointer-constant-1.c | 55 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/c23-null-pointer-constant-1.c | 120 |
3 files changed, 177 insertions, 0 deletions
diff --git a/gcc/c/c-typeck.cc b/gcc/c/c-typeck.cc index 26ee0eb..a701dd0 100644 --- a/gcc/c/c-typeck.cc +++ b/gcc/c/c-typeck.cc @@ -8457,6 +8457,8 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type, } else if (codel == POINTER_TYPE && (coder == INTEGER_TYPE + || coder == ENUMERAL_TYPE + || coder == BOOLEAN_TYPE || coder == NULLPTR_TYPE || coder == BITINT_TYPE)) { diff --git a/gcc/testsuite/gcc.dg/c11-null-pointer-constant-1.c b/gcc/testsuite/gcc.dg/c11-null-pointer-constant-1.c new file mode 100644 index 0000000..f463a1a --- /dev/null +++ b/gcc/testsuite/gcc.dg/c11-null-pointer-constant-1.c @@ -0,0 +1,55 @@ +/* Test zero with different types as null pointer constant: bug 112556. */ +/* { dg-do compile } */ +/* { dg-options "-std=c11 -pedantic-errors -Wno-pointer-compare" } */ + +enum e { ZERO }; + +void *p1 = 0; +void *p2 = 0LL; +void *p3 = (char) 0; +void *p4 = 0UL; +void *p5 = (_Bool) 0; +void *p6 = (enum e) ZERO; + +void f (void *); + +void * +g (void) +{ + p1 = 0; + p2 = 0LL; + p3 = (char) 0; + p4 = 0UL; + p5 = (_Bool) 0; + p6 = (enum e) ZERO; + f (0); + f (0ULL); + f (0L); + f ((char) 0); + f ((_Bool) 0); + f ((enum e) ZERO); + (1 ? p1 : 0); + (1 ? p1 : 0L); + (1 ? p1 : 0ULL); + (1 ? p1 : (char) 0); + (1 ? p1 : (_Bool) 0); + (1 ? p1 : (enum e) 0); + p1 == 0; + p1 == 0LL; + p1 == 0U; + p1 == (char) 0; + p1 == (_Bool) 0; + p1 == (enum e) 0; + p1 != 0; + p1 != 0LL; + p1 != 0U; + p1 != (char) 0; + p1 != (_Bool) 0; + p1 != (enum e) 0; + return 0; + return 0UL; + return 0LL; + return (char) 0; + return (_Bool) 0; + return (enum e) 0; +} diff --git a/gcc/testsuite/gcc.dg/c23-null-pointer-constant-1.c b/gcc/testsuite/gcc.dg/c23-null-pointer-constant-1.c new file mode 100644 index 0000000..71b66cc --- /dev/null +++ b/gcc/testsuite/gcc.dg/c23-null-pointer-constant-1.c @@ -0,0 +1,120 @@ +/* Test zero with different types as null pointer constant: bug 112556. */ +/* { dg-do compile } */ +/* { dg-options "-std=c23 -pedantic-errors -Wno-pointer-compare" } */ + +enum e { ZERO }; +enum e2 : bool { BZERO }; +enum e3 : long { LZERO }; + +void *p1 = 0; +void *p2 = 0LL; +void *p3 = (char) 0; +void *p4 = 0UL; +void *p5 = (bool) 0; +void *p6 = (enum e) ZERO; +void *p7 = false; +void *p8 = BZERO; +void *p9 = (enum e2) 0; +void *p10 = LZERO; +void *p11 = (enum e3) 0; +#ifdef __BITINT_MAXWIDTH__ +void *p12 = 0wb; +void *p13 = 0uwb; +#endif + +void f (void *); + +void * +g (void) +{ + p1 = 0; + p2 = 0LL; + p3 = (char) 0; + p4 = 0UL; + p5 = (bool) 0; + p6 = (enum e) ZERO; + p7 = false; + p8 = BZERO; + p9 = (enum e2) 0; + p10 = LZERO; + p11 = (enum e3) 0; +#ifdef __BITINT_MAXWIDTH__ + p12 = 0wb; + p13 = 0uwb; +#endif + f (0); + f (0ULL); + f (0L); + f ((char) 0); + f ((bool) 0); + f ((enum e) ZERO); + f (false); + f (BZERO); + f ((enum e2) 0); + f (LZERO); + f ((enum e3) 0); +#ifdef __BITINT_MAXWIDTH__ + f (0wb); + f (0uwb); +#endif + (1 ? p1 : 0); + (1 ? p1 : 0L); + (1 ? p1 : 0ULL); + (1 ? p1 : (char) 0); + (1 ? p1 : (bool) 0); + (1 ? p1 : (enum e) 0); + (1 ? p1 : false); + (1 ? p1 : BZERO); + (1 ? p1 : (enum e2) 0); + (1 ? p1 : LZERO); + (1 ? p1 : (enum e3) 0); +#ifdef __BITINT_MAXWIDTH__ + (1 ? p1 : 0wb); + (1 ? p1 : 0uwb); +#endif + p1 == 0; + p1 == 0LL; + p1 == 0U; + p1 == (char) 0; + p1 == (bool) 0; + p1 == (enum e) 0; + p1 == false; + p1 == BZERO; + p1 == (enum e2) 0; + p1 == LZERO; + p1 == (enum e3) 0; +#ifdef __BITINT_MAXWIDTH__ + p1 == 0wb; + p1 == 0uwb; +#endif + p1 != 0; + p1 != 0LL; + p1 != 0U; + p1 != (char) 0; + p1 != (bool) 0; + p1 != (enum e) 0; + p1 != false; + p1 != BZERO; + p1 != (enum e2) 0; + p1 != LZERO; + p1 != (enum e3) 0; +#ifdef __BITINT_MAXWIDTH__ + p1 != 0wb; + p1 != 0uwb; +#endif + return 0; + return 0UL; + return 0LL; + return (char) 0; + return (bool) 0; + return (enum e) 0; + return false; + return BZERO; + return (enum e2) 0; + return LZERO; + return (enum e3) 0; +#ifdef __BITINT_MAXWIDTH__ + return 0wb; + return 0uwb; +#endif +} |