Bug 105523 - Wrong warning array subscript [0] is outside array bounds
Summary: Wrong warning array subscript [0] is outside array bounds
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: target (show other bugs)
Version: 12.0
: P3 normal
Target Milestone: 13.3
Assignee: Senthil Kumar Selvaraj
URL:
Keywords: diagnostic
: 107842 (view as bug list)
Depends on:
Blocks: Warray-bounds
  Show dependency treegraph
 
Reported: 2022-05-08 12:12 UTC by Wilhelm M
Modified: 2024-02-12 17:10 UTC (History)
12 users (show)

See Also:
Host:
Target: avr
Build:
Known to work:
Known to fail:
Last reconfirmed: 2022-11-23 00:00:00


Attachments
pr105532.diff: Proposed patch for the AVR backend (689 bytes, patch)
2023-04-24 18:41 UTC, Georg-Johann Lay
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Wilhelm M 2022-05-08 12:12:01 UTC
The following code produces the above mentined wrong warning:

----

#include <stdint.h>

int main() {
    const auto ptr2 = reinterpret_cast<volatile uint8_t*>(0x0030);
    *ptr2 = 0xd8;
}

----

Up to avr-g++-11.3.1 there was no warning in above code.
Comment 1 Andrew Pinski 2022-05-08 19:53:36 UTC
--param=min-pagesize= should be set to 0 for avr as zero is a valid address.
Comment 2 Wilhelm M 2022-05-09 04:00:19 UTC
Setting --param=min-pagesize=0 on the commandline does the trick. But I think this should be set generally for avr target
Comment 3 Wilhelm M 2022-05-09 04:54:02 UTC
This bug is still in version 13.0.0
Comment 4 Wilhelm M 2022-05-09 06:59:55 UTC
The strange thing is, that it depends on how the assignment is written:

#include <avr/io.h>

int main() {
    GPIOR0 = 0x01; // no warning
    
    (*(volatile uint8_t *)(0x001C)) = 0x01; // warning
}

The cpp replaces the GPIOR0 access to essentially the same line as the following line, where the warning occures.
Comment 5 rudi 2022-05-11 11:50:51 UTC
Compiling atf with gcc-12.1.0 for the NXP iMX8 target results in the same error.

CFLAGS=+“ --param=min-pagesize=0” allows the build to complete.

———-

PROJECT=NXP ARCH=arm DEVICE=iMX8 s/build atf
CLEAN      atf
    *      Removing /var/media/DATA/home-rudi/LibreELEC.kernel11/build.LibreELEC-iMX8.arm-11.0-devel/build/atf-2.4 ...
    *      Removing /var/media/DATA/home-rudi/LibreELEC.kernel11/build.LibreELEC-iMX8.arm-11.0-devel/install_pkg/atf-2.4 ...
UNPACK      atf
BUILD      atf (target)
    TOOLCHAIN      manual
  CC      bl31/bl31_context_mgmt.c
  CC      bl31/bl31_main.c
  CC      bl31/interrupt_mgmt.c
  CC      common/runtime_svc.c
  CC      drivers/arm/gic/v3/arm_gicv3_common.c
  CC      drivers/arm/gic/v3/gic-x00.c
  CC      drivers/arm/gic/v3/gicdv3_helpers.c
  CC      drivers/arm/gic/v3/gicrv3_helpers.c
  CC      drivers/arm/gic/v3/gicv3_helpers.c
  CC      drivers/arm/gic/v3/gicv3_main.c
  CC      drivers/arm/tzc/tzc380.c
  CC      drivers/delay_timer/delay_timer.c
  CC      drivers/delay_timer/generic_delay_timer.c
  CC      lib/cpus/errata_report.c
  CC      lib/el3_runtime/aarch64/context_mgmt.c
  CC      lib/el3_runtime/cpu_data_array.c
  CC      lib/extensions/spe/spe.c
  CC      lib/extensions/sve/sve.c
  CC      lib/locks/bakery/bakery_lock_coherent.c
  CC      lib/psci/psci_common.c
  CC      lib/psci/psci_main.c
  CC      lib/psci/psci_mem_protect.c
  CC      lib/psci/psci_off.c
  CC      lib/psci/psci_on.c
  CC      lib/psci/psci_setup.c
  CC      lib/psci/psci_suspend.c
  CC      lib/psci/psci_system_off.c
  CC      lib/xlat_tables/aarch64/xlat_tables.c
  CC      lib/xlat_tables/xlat_tables_common.c
  CC      plat/common/plat_gicv3.c
  CC      plat/common/plat_psci_common.c
  CC      plat/imx/common/imx8_topology.c
  CC      plat/imx/common/imx_sip_handler.c
  CC      plat/imx/common/imx_sip_svc.c
  CC      plat/imx/common/plat_imx8_gic.c
  CC      plat/imx/imx8m/gpc_common.c
  CC      plat/imx/imx8m/imx8m_caam.c
  CC      plat/imx/imx8m/imx8m_psci_common.c
  CC      plat/imx/imx8m/imx8mq/gpc.c
  CC      plat/imx/imx8m/imx8mq/imx8mq_bl31_setup.c
  CC      plat/imx/imx8m/imx8mq/imx8mq_psci.c
  CC      plat/imx/imx8m/imx_aipstz.c
  CC      services/arm_arch_svc/arm_arch_svc_setup.c
  CC      services/std_svc/std_svc_setup.c
  CC      common/bl_common.c
  CC      common/tf_log.c
  CC      drivers/console/multi_console.c
  CC      plat/common/plat_bl_common.c
  CC      plat/common/plat_log_common.c
  CC      plat/common/aarch64/plat_common.c
  CC      lib/compiler-rt/builtins/popcountdi2.c
  CC      lib/compiler-rt/builtins/popcountsi2.c
  AS      bl31/aarch64/bl31_entrypoint.S
  AS      bl31/aarch64/crash_reporting.S
  AS      bl31/aarch64/ea_delegate.S
  AS      bl31/aarch64/runtime_exceptions.S
  AS      lib/cpus/aarch64/cortex_a53.S
  AS      lib/cpus/aarch64/cpu_helpers.S
  AS      lib/cpus/aarch64/dsu_helpers.S
  AS      lib/cpus/aarch64/wa_cve_2017_5715_bpiall.S
  AS      lib/cpus/aarch64/wa_cve_2017_5715_mmu.S
  AS      lib/el3_runtime/aarch64/context.S
  AS      lib/el3_runtime/aarch64/cpu_data.S
  AS      lib/locks/exclusive/aarch64/spinlock.S
  AS      lib/psci/aarch64/psci_helpers.S
  AS      plat/common/aarch64/platform_mp_stack.S
  AS      plat/imx/common/imx8_helpers.S
  AS      plat/imx/common/imx_uart_console.S
  AS      common/aarch64/debug.S
  AS      lib/aarch64/cache_helpers.S
  AS      lib/aarch64/misc_helpers.S
  AS      plat/common/aarch64/platform_helpers.S
  PP      bl31/bl31.ld.S
  CC      lib/libc/abort.c
  CC      lib/libc/assert.c
  CC      lib/libc/exit.c
  CC      lib/libc/memchr.c
  CC      lib/libc/memcmp.c
  CC      lib/libc/memcpy.c
  CC      lib/libc/memmove.c
  CC      lib/libc/memrchr.c
  CC      lib/libc/memset.c
  CC      lib/libc/printf.c
  CC      lib/libc/putchar.c
  CC      lib/libc/puts.c
  CC      lib/libc/snprintf.c
  CC      lib/libc/strchr.c
In file included from plat/imx/imx8m/imx8mq/imx8mq_bl31_setup.c:20:
In function 'mmio_read_8',
    inlined from 'imx8mq_soc_info_init' at plat/imx/imx8m/imx8mq/imx8mq_bl31_setup.c:68:16,
    inlined from 'bl31_platform_setup' at plat/imx/imx8m/imx8mq/imx8mq_bl31_setup.c:193:2:
include/lib/mmio.h:19:16: error: array subscript 0 is outside array bounds of 'volatile uint8_t[0]' {aka 'volatile unsigned char[]'} [-Werror=array-bounds]
   19 |         return *(volatile uint8_t*)addr;
      |                ^~~~~~~~~~~~~~~~~~~~~~~~
In function 'mmio_read_8',
    inlined from 'imx8mq_soc_info_init' at plat/imx/imx8m/imx8mq/imx8mq_bl31_setup.c:72:16,
    inlined from 'bl31_platform_setup' at plat/imx/imx8m/imx8mq/imx8mq_bl31_setup.c:193:2:
include/lib/mmio.h:19:16: error: array subscript 0 is outside array bounds of 'volatile uint8_t[0]' {aka 'volatile unsigned char[]'} [-Werror=array-bounds]
   19 |         return *(volatile uint8_t*)addr;
      |                ^~~~~~~~~~~~~~~~~~~~~~~~
cc1: all warnings being treated as errors

————
Comment 6 LIU Hao 2022-10-21 05:57:01 UTC
We have been experiencing this on mingw-w64 too. The warning can be caused by

```
void*
teb(void)
  {
    void* self;
    __asm__ ("movq %%gs:%1, %0" : "=r"(self) : "m"(*(void**) 0x30));
    return self;
  }
```

```
<source>:5:52: warning: array subscript 0 is outside array bounds of 'void *[0]' [-Warray-bounds]
    5 |     __asm__ ("movq %%gs:%1, %0" : "=r"(self) : "m"(*(void**) 0x30));
      |   
```

GCC 11 emits no such warning.
(godbolt: https://gcc.godbolt.org/z/sG7fG9x9j) 


Apparently GCC thinks we are dereferencing `0x30` which is a dangling pointer however that is exactly what we want to do, so GCC shouldn't have warned in this case.
Comment 7 Georg-Johann Lay 2022-11-23 17:49:09 UTC
*** Bug 107842 has been marked as a duplicate of this bug. ***
Comment 8 Andrew Pinski 2022-11-23 17:53:13 UTC
(In reply to LIU Hao from comment #6)
> Apparently GCC thinks we are dereferencing `0x30` which is a dangling
> pointer however that is exactly what we want to do, so GCC shouldn't have
> warned in this case.

That inline-asm is not correct and GCC does not understand segments if you don't use named address space feature.



The original issue is confirmed.
Comment 9 Andrew Pinski 2022-11-23 17:56:27 UTC
(In reply to rudi from comment #5)
> Compiling atf with gcc-12.1.0 for the NXP iMX8 target results in the same
> error.
> 
> CFLAGS=+“ --param=min-pagesize=0” allows the build to complete.

Yes ATF needs to have that addded to their makefile as it is a firmware which has memory at 0. Note this PR is about AVR only as that target always have memory at 0. Most other targets should not set --param=min-pagesize=0 by default (there are a few others); it is up to the firmware software to get set this option to tell GCC there is memory at location 0; because we want to warn about the normal user case. Firmware is a special case and all.
Comment 10 LIU Hao 2022-11-23 18:04:45 UTC
(In reply to Andrew Pinski from comment #8)
> That inline-asm is not correct and GCC does not understand segments if you
> don't use named address space feature.
> 

Named address space is not supported unless a GNU standard is selected.

https://gcc.godbolt.org/z/nbEMz6xMq

```
int
read_gs_30(void)
  {
    return *(int* __seg_gs) 0x30;
  }
```

With `-std=c99`:
```
<source>: In function 'read_gs_30':
<source>:4:18: error: expected ')' before '__seg_gs'
    4 |     return *(int* __seg_gs) 0x30;
      |             ~    ^~~~~~~~~
      |                  )
Compiler returned: 1
```
Comment 11 Andrew Pinski 2022-11-23 18:07:33 UTC
(In reply to LIU Hao from comment #10)
> (In reply to Andrew Pinski from comment #8)
> > That inline-asm is not correct and GCC does not understand segments if you
> > don't use named address space feature.
> > 
> 
> Named address space is not supported unless a GNU standard is selected.

Yes but the inline-asm is just broken. Anyways this is not related to the original issue reported here.
Comment 12 Konrad Rosenbaum 2022-11-23 18:11:31 UTC
It would be super helpful if the AVR target (and all its sub-architectures) could have the min-pagesize=0 option(*) set implicitly. This architecture has ONLY firmware - firmware is not special in that architecture. 
checks.

The first memory mapped page on AVR is actually the register/IO-port file that leads to all the IO devices and "peripherals" that are inside these chips. It's impossible to write any software for AVR without touching this page.

(*) or something else that excludes the register file from range
Comment 13 LIU Hao 2022-11-24 03:35:32 UTC
(In reply to Andrew Pinski from comment #11)
> Yes but the inline-asm is just broken. Anyways this is not related to the
> original issue reported here.

It IS related. GCC should not warn about dereferencing a constant address, no matter for what reason.
Comment 14 Ahmad Fatoum 2022-12-07 06:32:50 UTC
Does param=min-pagesize=0 solely influence warnings or could it now or in the future affect code generation/optimization?

I ask because barebox (https://barebox.org) also has this problem as on i.MX8, where it calls into ROM code, which starts at address 0. After that's done, it maps the NULL page there and normal accesses are unexpected. So if it's just about the warning, I'd prefer hiding pointer value via a compiler barrier where appliable instead of disabling the warning altogether.
Comment 15 William Westfield 2023-01-22 23:44:51 UTC
It seems especially weird that the following AVR program generates the warning for only the "&=" statement.

#include "avr/io.h"

int main(void){
	DDRD &= ~_BV(PD3);
	DDRD |= _BV(PD3);
	return 0;
}
Comment 16 David Crocker 2023-03-31 10:02:00 UTC
This issue is not specific to AVR target. I get the same spurious warning from gcc 12.2 arm-none-eabi when I compile the following code for ARM Cortex M0+ and M4 targets:

const char *bootloaderVersionText = *reinterpret_cast<const char**>(0x20);

I haven't found a workaround other than to use a pragma to disable the warning for that line of code.
Comment 17 Andrew Pinski 2023-03-31 20:32:24 UTC
(In reply to David Crocker from comment #16)
> This issue is not specific to AVR target. I get the same spurious warning
> from gcc 12.2 arm-none-eabi when I compile the following code for ARM Cortex
> M0+ and M4 targets:
> 
> const char *bootloaderVersionText = *reinterpret_cast<const char**>(0x20);
> 
> I haven't found a workaround other than to use a pragma to disable the
> warning for that line of code.

The change in your build would be --param=min-pagesize=0 . I made a mention of this a few times in this bug report on why avr is different from arm here.
Comment 18 David Brown 2023-04-24 15:21:14 UTC
This issue does not appear to be related to any particular backend.

Changing the initial code to remove the volatile :

void m(void) {
     uint8_t * ptr2 = ( uint8_t*)(0x0030);
    *ptr2 = 0xd8;
}

gives a warning in gcc 11 as well - "warning: writing 1 byte into a region of size 0".  (gcc 12 and 13 give the "array subscript [0] is outside array bounds" warning.)


It is standard practice in embedded development to cast an integer value (often a compile-time constant, but not always) to a pointer and use that to access memory-mapped registers or other data at fixed addresses.  Typically the pointers are pointer-to-volatile.  Sometimes the data type in question is a "uintN_t" type, sometimes it is a struct covering a range of registers.  There are other ways to specify fixed addresses, such as using "extern" data that is defined in a linker file or an assembly file - but I have not seen other methods used much in recent decades.

The compiler knows nothing about the size of the region pointed to here.  It is no more appropriate for it to guess the size is 0 than to guess it is 42.  It should either assume the size is one single object of the named type, or an array of unknown size of the named type.  (I'd prefer the first, but the second is also a reasonable choice.)

As an embedded developer, I don't want to have to turn off useful warnings to avoid false positives on common and essential constructs.
Comment 19 Georg-Johann Lay 2023-04-24 18:41:32 UTC
Created attachment 54912 [details]
pr105532.diff: Proposed patch for the AVR backend

Here is a proposed, untested patch.

gcc/
	PR target/105532
	* config/avr/avr.cc (opts.h): Include it.
	(avr_option_override): Set --param_min_pagesize=0.

gcc/testsuite/
	PR target/105532
	* gcc.target/avr/torture/pr105532.c: New test.
Comment 20 David Brown 2023-04-25 07:18:29 UTC
(In reply to Georg-Johann Lay from comment #19)
> Created attachment 54912 [details]
> pr105532.diff: Proposed patch for the AVR backend
> 
> Here is a proposed, untested patch.
> 
> gcc/
> 	PR target/105532
> 	* config/avr/avr.cc (opts.h): Include it.
> 	(avr_option_override): Set --param_min_pagesize=0.
> 
> gcc/testsuite/
> 	PR target/105532
> 	* gcc.target/avr/torture/pr105532.c: New test.

This is not an AVR backend issue - it is much wider than that.  It is perhaps reasonable to test a patch just on the AVR, but this needs to be fixed in the core of gcc.
Comment 21 David Brown 2023-04-25 07:30:13 UTC
(In reply to Andrew Pinski from comment #1)
> --param=min-pagesize= should be set to 0 for avr as zero is a valid address.

Is there any convenient description of "min-pagesize" ?  The user manual is unhelpful: "Minimum page size for warning purposes."  Your comment here suggests it is connected to whether zero is a valid address or not, which does not sound at all related to the issue here.  (But you are correct that for the AVR, and many embedded systems, accessing memory at address zero is valid.)

Testing (on godbolt) shows that setting "--param=min-pagesize=0" does stop this warning triggering.  But this is an issue that affects all systems for which the user might want to convert a fixed value to an address - i.e., all embedded systems, and perhaps device drivers or other low-level code on bigger systems.  Is setting "min-pagesize" to 0 actually a fix, or is it a workaround, and will it have other effects on static warning checks and/or code generation?

A workaround is, of course, helpful - especially since this can be added to peoples CFLAGS list.
Comment 22 LIU Hao 2023-04-25 07:30:46 UTC
Yes, GCC should be told to shut up about dereferencing artificial address values.
Comment 23 David Brown 2023-04-25 07:46:09 UTC
(In reply to LIU Hao from comment #22)
> Yes, GCC should be told to shut up about dereferencing artificial address
> values.

One possibility is to have the warnings disabled whenever you are using a volatile pointer.  After all, "volatile" is an indication that the compiler doesn't know everything, and it has to trust the programmer.
Comment 24 Andrew Pinski 2023-04-25 16:30:29 UTC
(In reply to LIU Hao from comment #22)
> Yes, GCC should be told to shut up about dereferencing artificial address
> values.

NO.
Take:
```
static inline int f(int *a)
{
  return a[10];
}

int g()
{
  return f(0);
}
```
The warning is there for the above case really (and similar ones with struct offsets). Where you originally have a null pointer and have an offset from there; by the time the warning happens, the IR does not know if it was originally from an offset of a null pointer or if the value was written in. The paramater is there to "tune" the heurstic to figure out if it is null pointer deference or if it is some real (HW) address. Maybe -fno-delete-null-pointer-checks should imply --param=min-pagesize=0, though some folks want the warning indepdent of trying to delete null pointer checks.
Comment 25 David Brown 2023-04-25 16:45:20 UTC
(In reply to Andrew Pinski from comment #24)
> (In reply to LIU Hao from comment #22)
> > Yes, GCC should be told to shut up about dereferencing artificial address
> > values.
> 
> NO.
> Take:
> ```
> static inline int f(int *a)
> {
>   return a[10];
> }
> 
> int g()
> {
>   return f(0);
> }
> ```
> The warning is there for the above case really (and similar ones with struct
> offsets). Where you originally have a null pointer and have an offset from
> there; by the time the warning happens, the IR does not know if it was
> originally from an offset of a null pointer or if the value was written in.
> The paramater is there to "tune" the heurstic to figure out if it is null
> pointer deference or if it is some real (HW) address. Maybe
> -fno-delete-null-pointer-checks should imply --param=min-pagesize=0, though
> some folks want the warning indepdent of trying to delete null pointer
> checks.

It is worth noting, I think, that although on a target like the AVR (and most embedded systems without an MMU) the address 0 is a real part of memory, and can really be read and/or written, any code that tries to dereference a 0 pointer is almost always wrong.  I don't want gcc to consider 0 as an acceptable address on these targets - I want it to warn me if it sees a null pointer dereference.  If I really want to target address 0, as I might occasionally do, I'll use a pointer to volatile - /then/ I'd like gcc to believe me without question.

I don't know if every embedded developer feels the same way.  (Georg-Johann could chime in with his opinion.)
Comment 26 Wilhelm M 2023-04-25 16:57:27 UTC
As you can see in my opening bug report, there is no nullptr reference nor dereferencing a pointer with value 0.
Comment 27 Wilhelm M 2023-04-25 16:58:52 UTC
> I don't know if every embedded developer feels the same way.  (Georg-Johann
> could chime in with his opinion.)

Indeed, limiting the warning on volatile-qualified ptr would help.
Comment 28 Andrew Pinski 2023-04-25 17:04:07 UTC
(In reply to Wilhelm M from comment #26)
> As you can see in my opening bug report, there is no nullptr reference nor
> dereferencing a pointer with value 0.

Yes but as I mentioned by the time the warning happens, the IR has lost information if the constant came from a null pointer or from some other constant that the user used. So a heuristic needs to be used and the idea was it would be the lower bytes by default and that the lower bytes would be defined by a "page size" and that is how the naming of the option happened.
Comment 29 Georg-Johann Lay 2023-04-25 19:02:45 UTC
(In reply to David Brown from comment #20)
> This is not an AVR backend issue - it is much wider than that.  It is
> perhaps reasonable to test a patch just on the AVR, but this needs to be
> fixed in the core of gcc.

Ok, just the fact that the issue is sitting there for > 1 year now lead me to the conclusion it's an AVR issue...

On older AVR devices, SFR area starts at 0x20, but on newer devices it starts at 0x0.  There are devices where 0x0 is actually some SFR address like PINB for ATtiny10 just to mention one.

At least for AVR, the warning does not make sense for dereferencing volatile pointers to addresses known at compile time.

But there are also cases for addresses known only at link time, like with AVR attribute __address__ or __io__.

Hence, for any addresses known at link time or earlier (aka. immediates), the warning makes no sense to me, because you cannot allocate them, anyways. (And when you can allocate by means of, say, a memory protection unit, GCC is out of the game.)
Comment 30 Konrad Rosenbaum 2023-04-25 19:07:48 UTC
(In reply to Andrew Pinski from comment #28)
> (In reply to Wilhelm M from comment #26)
> > As you can see in my opening bug report, there is no nullptr reference nor
> > dereferencing a pointer with value 0.
> 
> Yes but as I mentioned by the time the warning happens, the IR has lost
> information if the constant came from a null pointer or from some other
> constant that the user used. So a heuristic needs to be used and the idea
> was it would be the lower bytes by default and that the lower bytes would be
> defined by a "page size" and that is how the naming of the option happened.

To be honest, this sounds like a missing feature or even a design bug: shouldn't the IR be aware of what original address (type) a pointer/array originated from?

If it makes a difference whether I access a[70] or a[700000000] then the heuristic is not very helpful. If a useful option has a completely unintuitive name that is also a problem.

Null pointers usually derive from nullptr, NULL or the integer constant 0. I think it would be worth a flag or two to mark code pathes that transmit real null pointers or offsets to real null pointers. Anything derived from a non-zero integer is something that the programmer bears full responsibility for - if he wants to aim at his foot, let him!

Even if something derives from integer 0 (as opposed to nullptr or NULL), there is a chance that it was something that is intended (on the MCU I'm currently using this is the register that sets the first 8 GPIO pins) - usually "volatile" will be a good indicator of that, because memory mapped registers are always volatile.

A few examples I can think of:


struct MyStruct { int a,b,c; };

auto *nps = (MyStruct*)nullptr; // -> originates from a nullptr, definitely a problem!
auto *npi = &nps->c; // -> still derived from nullptr, still a problem!

MyStruct myvar;
auto *vps = &myvar ; // -> dereferences a real variable, definitely not a problem
auto *vpi = &vps->c; // -> still not a problem

auto *sps = (MyStruct*)0x101; // -> static address, very likely not a problem or at least the programmer's problem, not the compiler's
auto *spi = &sps->c; // same here

auto *xps = (MyStruct*)0x00; // -> static address, but 0x00 -> probably nullptr
auto *xpi = &xps->c; // -> derived from probably nullptr -> probably a problem

struct VMyStruct { volatile int a,b,c; };
auto *yps = (VMyStruct*)0x00; // -> static null address, but has volatile members, may or may not be problematic
auto *ypi = &yps->c; // -> derived from static null address, but access is volatile, it's the programmer's problem, no warning

auto *zps = (VMyStruct*)NULL; // NULL=((void*)0) -> derived from non-volatile pointer to 0, count it like nullptr!

No heuristic at the point of use will be able to properly catch and categorize those. There will have to be some flags that get passed along with the (changing) pointer value.

Even then there should be a way to tell the compiler whether (SomeType*)0 is a null pointer or a pointer to a legitimate memory location. Can pointer values have attributes?

The question that remains is: is this change worth it and might it help to catch other problems?
Comment 31 LIU Hao 2023-04-28 05:17:29 UTC
(In reply to Andrew Pinski from comment #24)
> The warning is there for the above case really (and similar ones with struct
> offsets). Where you originally have a null pointer and have an offset from
> there; by the time the warning happens, the IR does not know if it was
> originally from an offset of a null pointer or if the value was written in.

I understand that completely, but it does not justify the confusion. Something like 'warning: array subscript 0 is outside array bounds of' says nothing about null pointers, and is thus misleading. It is addition of a non-zero offset to a null pointer that the warning really belongs to.
Comment 32 Andrew Pinski 2023-04-28 05:25:00 UTC
(In reply to LIU Hao from comment #31)
> (In reply to Andrew Pinski from comment #24)
> > The warning is there for the above case really (and similar ones with struct
> > offsets). Where you originally have a null pointer and have an offset from
> > there; by the time the warning happens, the IR does not know if it was
> > originally from an offset of a null pointer or if the value was written in.
> 
> I understand that completely, but it does not justify the confusion.
> Something like 'warning: array subscript 0 is outside array bounds of' says
> nothing about null pointers, and is thus misleading. 

Actually since GCC 13, there is an additional note specifically to fix that misleading part:
cc1plus: note: source object is likely at address zero
Comment 33 GCC Commits 2023-06-19 08:23:03 UTC
The master branch has been updated by Senthil Kumar Selvaraj <saaadhu@gcc.gnu.org>:

https://gcc.gnu.org/g:58e1bc2b1c8420773b16452d47932a6ca0d003fb

commit r14-1933-g58e1bc2b1c8420773b16452d47932a6ca0d003fb
Author: Senthil Kumar Selvaraj <saaadhu@gcc.gnu.org>
Date:   Mon Jun 19 12:23:25 2023 +0530

    avr: Fix wrong array bounds warning on SFR access
    
    The warning was raised on accessing SFRs at addresses below the default
    page size, as gcc considers accessing addresses in the first page of
    memory as suspicious. This doesn't apply to an embedded target like the
    avr, where both flash and RAM have zero as a valid address. Zero is also
    a valid address in named address spaces (__memx, flash<n> etc..).
    
    This commit implements TARGET_ADDR_SPACE_ZERO_ADDRESS_VALID for the avr
    target and reports to gcc that zero is a valid address on all
    address spaces. It also disables flag_delete_null_pointer_checks
    based on the target hook, and modifies target-supports.exp to add avr
    to the list of targets that always keep null pointer checks. This fixes
    a bunch of DejaGNU failures that occur otherwise.
    
            PR target/105523
    
    gcc/ChangeLog:
    
            * common/config/avr/avr-common.cc: Remove setting
            of OPT_fdelete_null_pointer_checks.
            * config/avr/avr.cc (avr_option_override): Clear
            flag_delete_null_pointer_checks if zero_address_valid.
            (avr_addr_space_zero_address_valid): New function.
            (TARGET_ADDR_SPACE_ZERO_ADDRESS_VALID): Provide target
            hook.
    
    gcc/testsuite/ChangeLog:
    
            * lib/target-supports.exp
            (check_effective_target_keeps_null_pointer_checks): Add
            avr.
            * gcc.target/avr/pr105523.c: New test.
Comment 34 Georg-Johann Lay 2023-08-01 13:45:55 UTC
@Senthil: Can this PR be closed? Or will it be backported?
Comment 35 Georg-Johann Lay 2023-08-09 18:53:26 UTC
Fixed in v14.
Comment 36 GCC Commits 2024-02-12 17:08:05 UTC
The releases/gcc-13 branch has been updated by Georg-Johann Lay <gjl@gcc.gnu.org>:

https://gcc.gnu.org/g:83e9075ed22c0c5f27328b4be7d8eb9df5c8778b

commit r13-8319-g83e9075ed22c0c5f27328b4be7d8eb9df5c8778b
Author: Senthil Kumar Selvaraj <saaadhu@gcc.gnu.org>
Date:   Mon Jun 19 12:23:25 2023 +0530

    avr: Fix wrong array bounds warning on SFR access
    
    The warning was raised on accessing SFRs at addresses below the default
    page size, as gcc considers accessing addresses in the first page of
    memory as suspicious. This doesn't apply to an embedded target like the
    avr, where both flash and RAM have zero as a valid address. Zero is also
    a valid address in named address spaces (__memx, flash<n> etc..).
    
    This commit implements TARGET_ADDR_SPACE_ZERO_ADDRESS_VALID for the avr
    target and reports to gcc that zero is a valid address on all
    address spaces. It also disables flag_delete_null_pointer_checks
    based on the target hook, and modifies target-supports.exp to add avr
    to the list of targets that always keep null pointer checks. This fixes
    a bunch of DejaGNU failures that occur otherwise.
    
            PR target/105523
    
    gcc/ChangeLog:
    
            * common/config/avr/avr-common.cc: Remove setting
            of OPT_fdelete_null_pointer_checks.
            * config/avr/avr.cc (avr_option_override): Clear
            flag_delete_null_pointer_checks if zero_address_valid.
            (avr_addr_space_zero_address_valid): New function.
            (TARGET_ADDR_SPACE_ZERO_ADDRESS_VALID): Provide target
            hook.
    
    gcc/testsuite/ChangeLog:
    
            * lib/target-supports.exp
            (check_effective_target_keeps_null_pointer_checks): Add
            avr.
            * gcc.target/avr/pr105523.c: New test.
    
    (cherry picked from commit 58e1bc2b1c8420773b16452d47932a6ca0d003fb)
Comment 37 Georg-Johann Lay 2024-02-12 17:10:11 UTC
Back-ported to v13.3