Re: kcsan -Wmaybe-uninitialized warning in ntfs3

1 view
Skip to first unread message

Arnd Bergmann

unread,
Apr 21, 2026, 6:21:59 AM (9 days ago) Apr 21
to Marco Elver, Konstantin Komarov, Dmitry Vyukov, nt...@lists.linux.dev, linux-...@vger.kernel.org, kasa...@googlegroups.com
On Tue, Apr 21, 2026, at 11:33, Marco Elver wrote:
> On Tue, 21 Apr 2026 at 09:54, Arnd Bergmann <ar...@arndb.de> wrote:
>> What happens here is that copy_from_user() is used in a very
>> normal way to copy a user space structure into a previously
>> uninitialized on-stack buffer. With KCSAN enabled, this passes
>> the pointer to that buffer into __kcsan_check_access(), which
>> takes a 'const volatile void *' pointer. Gcc correctly notices
>> that there is no way to access the data behind this pointer
>> when it hasn't been initialized yet, as both read and write
>> would cause undefined behavior.
>>
>> I'm not sure what a good solution would be to avoid this,
>> but I assume this should be fixed in the kcsan instrumentation.
>> I tried changing that code to pass non-const pointers for
>> any instrument_write variant, which does avoid the warning,
>> but also adds a bit of complexity, see below.
>>
>> Any other ideas?
>
> Indeed, the below is rather complex, and seems unnecessary to me just
> to suppress this warning which not even the whole kernel enables.
>
> How can I reproduce this? GCC version? .config? I can't seem to with
> an x86 defconfig + CONFIG_NTFS3_FS + KCSAN config + GCC on linux-next
> (20260420).

I ran into this during randconfig testing, I have attached a
reproducer .config here, but have not tried to narrow down the
configuration options that are required for triggering it.

The compiler I used is a recent gcc-16.0.1 snapshot, but
the same config produces the warning using earlier compilers
as well, I see this with gcc-12.5 but not with gcc-11.5 or
earlier.

> There's likely a simpler option (attribute or warning suppression
> around these functions) I want to try.

I tried the 'unused' and 'uninitialized' attributes on the
argument without success.

I'm a bit worried that just using __diag_ignore() around the
call would still leave the problem that gcc warns about, in case
the compiler decides that this is undefined behavior and do
something we don't want.

Changing the type of the 'ptr' argument in the internal
__kcsan_check_access() call to 'unsigned long' or perhaps
a non-const pointer should avoid the warning.

Arnd
.config

Marco Elver

unread,
Apr 21, 2026, 7:35:59 AM (9 days ago) Apr 21
to Arnd Bergmann, Konstantin Komarov, Dmitry Vyukov, nt...@lists.linux.dev, linux-...@vger.kernel.org, kasa...@googlegroups.com
The attached .config is a KASAN config, still can't reproduce.

Marco Elver

unread,
Apr 21, 2026, 8:26:54 AM (9 days ago) Apr 21
to Arnd Bergmann, Konstantin Komarov, Dmitry Vyukov, nt...@lists.linux.dev, linux-...@vger.kernel.org, kasa...@googlegroups.com
On Tue, 21 Apr 2026 at 12:21, Arnd Bergmann <ar...@arndb.de> wrote:
>
The warning is "maybe-uninitialized". GCC cannot prove what the called
function does with the argument; if it were to miscompile based on
wild assumptions around what a function does with a const-pointer,
that's a compiler bug.

I think diag_ignore() is the right thing here.

> Changing the type of the 'ptr' argument in the internal
> __kcsan_check_access() call to 'unsigned long' or perhaps
> a non-const pointer should avoid the warning.

non-const doesn't work for read (const) accesses.

I still cannot reproduce it - I've tried various permutations and
compiler versions.

Arnd Bergmann

unread,
Apr 21, 2026, 8:28:46 AM (9 days ago) Apr 21
to Marco Elver, Konstantin Komarov, Dmitry Vyukov, nt...@lists.linux.dev, linux-...@vger.kernel.org, kasa...@googlegroups.com
Odd, this is what I see in the attached file:

CONFIG_ARM64=y
CONFIG_KCSAN=y
CONFIG_KCSAN_SELFTEST=y
CONFIG_KCSAN_EARLY_ENABLE=y
CONFIG_KCSAN_NUM_WATCHPOINTS=64
CONFIG_KCSAN_UDELAY_TASK=80
CONFIG_KCSAN_UDELAY_INTERRUPT=20
# CONFIG_KCSAN_DELAY_RANDOMIZE is not set
CONFIG_KCSAN_SKIP_WATCH=4000
# CONFIG_KCSAN_SKIP_WATCH_RANDOMIZE is not set
CONFIG_KCSAN_INTERRUPT_WATCHER=y
CONFIG_KCSAN_REPORT_ONCE_IN_MS=3000
CONFIG_KCSAN_REPORT_RACE_UNKNOWN_ORIGIN=y
CONFIG_KCSAN_STRICT=y
# CONFIG_KASAN is not set
CONFIG_HAVE_ARCH_KFENCE=y
# CONFIG_KFENCE is not set
# end of Memory Debugging

I forgot to mention that the reproducer was on arm64, if you
tried building for x86, that may have messed up the config.

I've reverted my workaround in the randconfig tree now to see if
I can find a reproducer for x86 as well, in case that is easier.

Arnd

Marco Elver

unread,
Apr 21, 2026, 9:18:48 AM (9 days ago) Apr 21
to Arnd Bergmann, Konstantin Komarov, Dmitry Vyukov, nt...@lists.linux.dev, linux-...@vger.kernel.org, kasa...@googlegroups.com
On Tue, Apr 21, 2026 at 02:28PM +0200, Arnd Bergmann wrote:
> On Tue, Apr 21, 2026, at 13:35, Marco Elver wrote:
> > On Tue, 21 Apr 2026 at 12:21, Arnd Bergmann <ar...@arndb.de> wrote:
> >>
> >> I ran into this during randconfig testing, I have attached a
> >> reproducer .config here, but have not tried to narrow down the
> >> configuration options that are required for triggering it.
> >
> > The attached .config is a KASAN config, still can't reproduce.
>
> Odd, this is what I see in the attached file:

Mea culpa - I added one '.' too many and ended up copying some old
config.

Anyway, I can reproduce this now.

There appear to be 2 options to fix, see patch below:

1. __kcsan_nodiag wrapper to disable warnings for the kcsan_check
helpers. Tested and seems to work in this case.

2. __attribute__((access(none, 1))) per https://gcc.gnu.org/onlinedocs/gcc/Common-Attributes.html:
"The access attribute enables the detection of invalid or unsafe
accesses by functions or their callers, as well as write-only
accesses to objects that are never read from. Such accesses may be
diagnosed by warnings such as -Wstringop-overflow, -Wuninitialized,
-Wunused, and others."

Option #2 seems a lot simpler. While KCSAN does read the accessed
memory, for the purpose of diagnostics hiding this fact from the
compiler is perfectly fine as it's not part of "normal" kernel code.

Preferences?

------ >8 ------


diff --git a/fs/ntfs3/file.c b/fs/ntfs3/file.c
index b041639ab406..088412189f16 100644
--- a/fs/ntfs3/file.c
+++ b/fs/ntfs3/file.c
@@ -73,6 +73,7 @@ static int ntfs_ioctl_fitrim(struct ntfs_sb_info *sbi, unsigned long arg)
if (!bdev_max_discard_sectors(dev))
return -EOPNOTSUPP;

+ kcsan_check_write(&range, sizeof(range));
user_range = (struct fstrim_range __user *)arg;
if (copy_from_user(&range, user_range, sizeof(range)))
return -EFAULT;
diff --git a/include/linux/kcsan-checks.h b/include/linux/kcsan-checks.h
index 92f3843d9ebb..7304512cf2a2 100644
--- a/include/linux/kcsan-checks.h
+++ b/include/linux/kcsan-checks.h
@@ -27,6 +27,14 @@
* to validate access to an address. Never use these in header files!
*/
#ifdef CONFIG_KCSAN
+#define __kcsan_nodiag(...) \
+({ \
+ __diag_push(); \
+ __diag_ignore_all("-Wmaybe-uninitialized", "") \
+ __VA_ARGS__; \
+ __diag_pop() \
+})
+
/**
* __kcsan_check_access - check generic access for races
*
@@ -34,7 +42,7 @@
* @size: size of access
* @type: access type modifier
*/
-void __kcsan_check_access(const volatile void *ptr, size_t size, int type);
+void __kcsan_check_access(const volatile void *ptr, size_t size, int type)/* __attribute__((access (none, 1)))*/;

/*
* See definition of __tsan_atomic_signal_fence() in kernel/kcsan/core.c.
@@ -186,6 +194,8 @@ void kcsan_end_scoped_access(struct kcsan_scoped_access *sa);

#else /* CONFIG_KCSAN */

+#define __kcsan_nodiag(...) ({ __VA_ARGS__; })
+
static inline void __kcsan_check_access(const volatile void *ptr, size_t size,
int type) { }

@@ -273,7 +283,7 @@ static inline void __kcsan_disable_current(void) { }
* @ptr: address of access
* @size: size of access
*/
-#define __kcsan_check_read(ptr, size) __kcsan_check_access(ptr, size, 0)
+#define __kcsan_check_read(ptr, size) __kcsan_nodiag(__kcsan_check_access(ptr, size, 0))

/**
* __kcsan_check_write - check regular write access for races
@@ -282,7 +292,7 @@ static inline void __kcsan_disable_current(void) { }
* @size: size of access
*/
#define __kcsan_check_write(ptr, size) \
- __kcsan_check_access(ptr, size, KCSAN_ACCESS_WRITE)
+ __kcsan_nodiag(__kcsan_check_access(ptr, size, KCSAN_ACCESS_WRITE))

/**
* __kcsan_check_read_write - check regular read-write access for races
@@ -291,7 +301,7 @@ static inline void __kcsan_disable_current(void) { }
* @size: size of access
*/
#define __kcsan_check_read_write(ptr, size) \
- __kcsan_check_access(ptr, size, KCSAN_ACCESS_COMPOUND | KCSAN_ACCESS_WRITE)
+ __kcsan_nodiag(__kcsan_check_access(ptr, size, KCSAN_ACCESS_COMPOUND | KCSAN_ACCESS_WRITE))

/**
* kcsan_check_read - check regular read access for races
@@ -299,7 +309,7 @@ static inline void __kcsan_disable_current(void) { }
* @ptr: address of access
* @size: size of access
*/
-#define kcsan_check_read(ptr, size) kcsan_check_access(ptr, size, 0)
+#define kcsan_check_read(ptr, size) __kcsan_nodiag(kcsan_check_access(ptr, size, 0))

/**
* kcsan_check_write - check regular write access for races
@@ -308,7 +318,7 @@ static inline void __kcsan_disable_current(void) { }
* @size: size of access
*/
#define kcsan_check_write(ptr, size) \
- kcsan_check_access(ptr, size, KCSAN_ACCESS_WRITE)
+ __kcsan_nodiag(kcsan_check_access(ptr, size, KCSAN_ACCESS_WRITE))

/**
* kcsan_check_read_write - check regular read-write access for races
@@ -317,7 +327,7 @@ static inline void __kcsan_disable_current(void) { }
* @size: size of access
*/
#define kcsan_check_read_write(ptr, size) \
- kcsan_check_access(ptr, size, KCSAN_ACCESS_COMPOUND | KCSAN_ACCESS_WRITE)
+ __kcsan_nodiag(kcsan_check_access(ptr, size, KCSAN_ACCESS_COMPOUND | KCSAN_ACCESS_WRITE))

/*
* Check for atomic accesses: if atomic accesses are not ignored, this simply
@@ -329,11 +339,11 @@ static inline void __kcsan_disable_current(void) { }
#define kcsan_check_atomic_read_write(...) do { } while (0)
#else
#define kcsan_check_atomic_read(ptr, size) \
- kcsan_check_access(ptr, size, KCSAN_ACCESS_ATOMIC)
+ __kcsan_nodiag(kcsan_check_access(ptr, size, KCSAN_ACCESS_ATOMIC))
#define kcsan_check_atomic_write(ptr, size) \
- kcsan_check_access(ptr, size, KCSAN_ACCESS_ATOMIC | KCSAN_ACCESS_WRITE)
+ __kcsan_nodiag(kcsan_check_access(ptr, size, KCSAN_ACCESS_ATOMIC | KCSAN_ACCESS_WRITE))
#define kcsan_check_atomic_read_write(ptr, size) \
- kcsan_check_access(ptr, size, KCSAN_ACCESS_ATOMIC | KCSAN_ACCESS_WRITE | KCSAN_ACCESS_COMPOUND)
+ __kcsan_nodiag(kcsan_check_access(ptr, size, KCSAN_ACCESS_ATOMIC | KCSAN_ACCESS_WRITE | KCSAN_ACCESS_COMPOUND))
#endif

/**
@@ -368,7 +378,7 @@ static inline void __kcsan_disable_current(void) { }
* @var: variable to assert on
*/
#define ASSERT_EXCLUSIVE_WRITER(var) \
- __kcsan_check_access(&(var), sizeof(var), KCSAN_ACCESS_ASSERT)
+ __kcsan_nodiag(__kcsan_check_access(&(var), sizeof(var), KCSAN_ACCESS_ASSERT))

/*
* Helper macros for implementation of for ASSERT_EXCLUSIVE_*_SCOPED(). @id is
@@ -380,9 +390,9 @@ static inline void __kcsan_disable_current(void) { }
struct kcsan_scoped_access __kcsan_scoped_name(id, _) \
__kcsan_cleanup_scoped; \
struct kcsan_scoped_access *__kcsan_scoped_name(id, _dummy_p) \
- __maybe_unused = kcsan_begin_scoped_access( \
+ __maybe_unused = __kcsan_nodiag(kcsan_begin_scoped_access( \
&(var), sizeof(var), KCSAN_ACCESS_SCOPED | (type), \
- &__kcsan_scoped_name(id, _))
+ &__kcsan_scoped_name(id, _)))

/**
* ASSERT_EXCLUSIVE_WRITER_SCOPED - assert no concurrent writes to @var in scope
@@ -449,7 +459,7 @@ static inline void __kcsan_disable_current(void) { }
* @var: variable to assert on
*/
#define ASSERT_EXCLUSIVE_ACCESS(var) \
- __kcsan_check_access(&(var), sizeof(var), KCSAN_ACCESS_WRITE | KCSAN_ACCESS_ASSERT)
+ __kcsan_nodiag(__kcsan_check_access(&(var), sizeof(var), KCSAN_ACCESS_WRITE | KCSAN_ACCESS_ASSERT))

/**
* ASSERT_EXCLUSIVE_ACCESS_SCOPED - assert no concurrent accesses to @var in scope
@@ -525,7 +535,7 @@ static inline void __kcsan_disable_current(void) { }
#define ASSERT_EXCLUSIVE_BITS(var, mask) \
do { \
kcsan_set_access_mask(mask); \
- __kcsan_check_access(&(var), sizeof(var), KCSAN_ACCESS_ASSERT);\
+ __kcsan_nodiag(__kcsan_check_access(&(var), sizeof(var), KCSAN_ACCESS_ASSERT));\
kcsan_set_access_mask(0); \
kcsan_atomic_next(1); \
} while (0)

Arnd Bergmann

unread,
Apr 21, 2026, 10:11:51 AM (9 days ago) Apr 21
to Marco Elver, Konstantin Komarov, Dmitry Vyukov, nt...@lists.linux.dev, linux-...@vger.kernel.org, kasa...@googlegroups.com
On Tue, Apr 21, 2026, at 15:18, Marco Elver wrote:
> On Tue, Apr 21, 2026 at 02:28PM +0200, Arnd Bergmann wrote:
>
> There appear to be 2 options to fix, see patch below:
>
> 1. __kcsan_nodiag wrapper to disable warnings for the kcsan_check
> helpers. Tested and seems to work in this case.
>
> 2. __attribute__((access(none, 1))) per
> https://gcc.gnu.org/onlinedocs/gcc/Common-Attributes.html:
> "The access attribute enables the detection of invalid or unsafe
> accesses by functions or their callers, as well as write-only
> accesses to objects that are never read from. Such accesses may be
> diagnosed by warnings such as -Wstringop-overflow, -Wuninitialized,
> -Wunused, and others."
>
> Option #2 seems a lot simpler. While KCSAN does read the accessed
> memory, for the purpose of diagnostics hiding this fact from the
> compiler is perfectly fine as it's not part of "normal" kernel code.
>
> Preferences?

To me, 2 makes more sense. The attribute requires gcc-11 or higher,
so you need to wrap that in a compiler version specific macro,
but since I only saw the warning with gcc-12 and higher, that
should be fine.

I assume that gcc would be allowed to reorder code like

int i = 1;
__kcsan_check_write(&i, sizeof(i));

to defer the initialization until after the check with
the attribute((access(none, 1))) annotation. Is that a
problem for kcsan?

Looking through your change I also see

> diff --git a/fs/ntfs3/file.c b/fs/ntfs3/file.c
> index b041639ab406..088412189f16 100644
> --- a/fs/ntfs3/file.c
> +++ b/fs/ntfs3/file.c
> @@ -73,6 +73,7 @@ static int ntfs_ioctl_fitrim(struct ntfs_sb_info
> *sbi, unsigned long arg)
> if (!bdev_max_discard_sectors(dev))
> return -EOPNOTSUPP;
>
> + kcsan_check_write(&range, sizeof(range));
> user_range = (struct fstrim_range __user *)arg;

This was probably not meant to be there.

> @@ -273,7 +283,7 @@ static inline void __kcsan_disable_current(void) { }
> * @ptr: address of access
> * @size: size of access
> */
> -#define __kcsan_check_read(ptr, size) __kcsan_check_access(ptr, size,
> 0)
> +#define __kcsan_check_read(ptr, size)
> __kcsan_nodiag(__kcsan_check_access(ptr, size, 0))

I don't think we need to do anything about the read and read_write
code paths: if the compiler can see that the data passed here
is uninitialized, warning about this is better than not warning.

The problem I see was specifically for __kcsan_check_write()
with an uninitialized pointer

> @@ -282,7 +292,7 @@ static inline void __kcsan_disable_current(void) { }
> * @size: size of access
> */
> #define __kcsan_check_write(ptr, size)
> \
> - __kcsan_check_access(ptr, size, KCSAN_ACCESS_WRITE)
> + __kcsan_nodiag(__kcsan_check_access(ptr, size, KCSAN_ACCESS_WRITE))

So if we end up using __diag_ignore(), it should be sufficient to
add it here directly, instead of another indirection.

Arnd

Marco Elver

unread,
Apr 21, 2026, 11:26:43 AM (9 days ago) Apr 21
to Arnd Bergmann, Konstantin Komarov, Dmitry Vyukov, nt...@lists.linux.dev, linux-...@vger.kernel.org, kasa...@googlegroups.com
No - kcsan is just looking for races, and in this case there'd
trivially be no race if the stack var couldn't escape (the compiler
instrumentation eliminates such stack accesses).

> Looking through your change I also see
>
> > diff --git a/fs/ntfs3/file.c b/fs/ntfs3/file.c
> > index b041639ab406..088412189f16 100644
> > --- a/fs/ntfs3/file.c
> > +++ b/fs/ntfs3/file.c
> > @@ -73,6 +73,7 @@ static int ntfs_ioctl_fitrim(struct ntfs_sb_info
> > *sbi, unsigned long arg)
> > if (!bdev_max_discard_sectors(dev))
> > return -EOPNOTSUPP;
> >
> > + kcsan_check_write(&range, sizeof(range));
> > user_range = (struct fstrim_range __user *)arg;
>
> This was probably not meant to be there.

Yes, just for testing something else.

> > @@ -273,7 +283,7 @@ static inline void __kcsan_disable_current(void) { }
> > * @ptr: address of access
> > * @size: size of access
> > */
> > -#define __kcsan_check_read(ptr, size) __kcsan_check_access(ptr, size,
> > 0)
> > +#define __kcsan_check_read(ptr, size)
> > __kcsan_nodiag(__kcsan_check_access(ptr, size, 0))
>
> I don't think we need to do anything about the read and read_write
> code paths: if the compiler can see that the data passed here
> is uninitialized, warning about this is better than not warning.
>
> The problem I see was specifically for __kcsan_check_write()
> with an uninitialized pointer
>
> > @@ -282,7 +292,7 @@ static inline void __kcsan_disable_current(void) { }
> > * @size: size of access
> > */
> > #define __kcsan_check_write(ptr, size)
> > \
> > - __kcsan_check_access(ptr, size, KCSAN_ACCESS_WRITE)
> > + __kcsan_nodiag(__kcsan_check_access(ptr, size, KCSAN_ACCESS_WRITE))
>
> So if we end up using __diag_ignore(), it should be sufficient to
> add it here directly, instead of another indirection.

I merged the 2 experiments, but you get the idea.

I think I'll drop the __kcsan_nodiag stuff and just add the access
attribute - but that would go on the __kcsan_check_access function, so
it'd apply to any kind of access (read or write). The GCC docs promise
that the 'access' attribute is only for diagnostics, and should not
affect codegen.

Marco Elver

unread,
Apr 21, 2026, 3:06:49 PM (9 days ago) Apr 21
to Arnd Bergmann, Konstantin Komarov, Dmitry Vyukov, nt...@lists.linux.dev, linux-...@vger.kernel.org, kasa...@googlegroups.com
On Tue, 21 Apr 2026 at 17:26, Marco Elver <el...@google.com> wrote:
[...]
> > To me, 2 makes more sense. The attribute requires gcc-11 or higher,
> > so you need to wrap that in a compiler version specific macro,
> > but since I only saw the warning with gcc-12 and higher, that
> > should be fine.

Kindly test if you can:
https://lore.kernel.org/all/20260421190351....@google.com/

Thanks!

Arnd Bergmann

unread,
Apr 21, 2026, 3:15:51 PM (9 days ago) Apr 21
to Marco Elver, Konstantin Komarov, Dmitry Vyukov, nt...@lists.linux.dev, linux-...@vger.kernel.org, kasa...@googlegroups.com
Applied to my randconfig tree and verified that this fixes the
known warning (only one out of about 200 random configs). I'll
let you know if something comes up by tomorrow.

Both patches

Reviewed-by: Arnd Bergmann <ar...@arndb.de>

Thanks a lot for addressing the warning!

Arnd Bergmann

unread,
Apr 22, 2026, 4:00:49 AM (8 days ago) Apr 22
to Marco Elver, Konstantin Komarov, Dmitry Vyukov, nt...@lists.linux.dev, linux-...@vger.kernel.org, kasa...@googlegroups.com
On Tue, Apr 21, 2026, at 21:12, Arnd Bergmann wrote:
> On Tue, Apr 21, 2026, at 21:06, Marco Elver wrote:
>> On Tue, 21 Apr 2026 at 17:26, Marco Elver <el...@google.com> wrote:
>> [...]
>>> > To me, 2 makes more sense. The attribute requires gcc-11 or higher,
>>> > so you need to wrap that in a compiler version specific macro,
>>> > but since I only saw the warning with gcc-12 and higher, that
>>> > should be fine.
>>
>> Kindly test if you can:
>> https://lore.kernel.org/all/20260421190351....@google.com/
>
> Applied to my randconfig tree and verified that this fixes the
> known warning (only one out of about 200 random configs). I'll
> let you know if something comes up by tomorrow.

Unfortunately, there are new warnings after your patches using
gcc-11. In 500 randconfig builds with that compiler, I saw 7
configurations failing with one of these four messages:

1.

In file included from include/asm-generic/rwonce.h:27,
from ./arch/x86/include/generated/asm/rwonce.h:1,
from include/linux/compiler.h:369,
from include/linux/build_bug.h:5,
from arch/x86/include/asm/current.h:5,
from include/linux/sched.h:12,
from include/linux/mempool.h:8,
from include/linux/bio.h:8,
from drivers/md/dm-bio-record.h:11,
from drivers/md/dm-raid1.c:9:
In function 'instrument_atomic_write',
inlined from 'atomic_set' at include/linux/atomic/atomic-instrumented.h:67:2,
inlined from 'reset_ms_flags' at drivers/md/dm-raid1.c:384:3,
inlined from 'do_recovery' at drivers/md/dm-raid1.c:413:3,
inlined from 'do_mirror' at drivers/md/dm-raid1.c:876:2:
include/linux/kcsan-checks.h:220:28: error: '__kcsan_check_access' expecting 0 bytes in a region of size 0 [-Werror=stringop-overread]
220 | #define kcsan_check_access __kcsan_check_access
| ^
include/linux/kcsan-checks.h:334:9: note: in expansion of macro 'kcsan_check_access'
334 | kcsan_check_access(ptr, size, KCSAN_ACCESS_ATOMIC | KCSAN_ACCESS_WRITE)
| ^~~~~~~~~~~~~~~~~~
include/linux/instrumented.h:98:9: note: in expansion of macro 'kcsan_check_atomic_write'
98 | kcsan_check_atomic_write(v, size);
| ^~~~~~~~~~~~~~~~~~~~~~~~
include/linux/instrumented.h: In function 'do_mirror':
drivers/md/dm-raid1.c:59:27: note: at offset [504, 171798692304] into source object 'ti' of size 8
59 | struct dm_target *ti;
| ^~
In file included from include/asm-generic/rwonce.h:27,
from ./arch/x86/include/generated/asm/rwonce.h:1,
from include/linux/compiler.h:369,
from include/linux/build_bug.h:5,
from arch/x86/include/asm/current.h:5,
from include/linux/sched.h:12,
from include/linux/mempool.h:8,
from include/linux/bio.h:8,
from drivers/md/dm-bio-record.h:11,
from drivers/md/dm-raid1.c:9:
include/linux/kcsan-checks.h:37:6: note: in a call to function '__kcsan_check_access' declared with attribute 'access (none, 1)'
37 | void __kcsan_check_access(const volatile void *ptr, size_t size, int type) __access(none, 1);
| ^~~~~~~~~~~~~~~~~~~~

2.

In file included from include/asm-generic/rwonce.h:27,
from arch/arm64/include/asm/rwonce.h:81,
from include/linux/compiler.h:369,
from include/asm-generic/bug.h:5,
from arch/arm64/include/asm/bug.h:26,
from include/linux/bug.h:5,
from include/linux/random.h:6,
from include/crypto/curve25519.h:10,
from drivers/net/wireguard/messages.h:9,
from drivers/net/wireguard/noise.h:8,
from drivers/net/wireguard/device.h:9,
from drivers/net/wireguard/peer.h:9,
from drivers/net/wireguard/queueing.h:9,
from drivers/net/wireguard/receive.c:6:
In function 'instrument_atomic_read_write',
inlined from 'test_and_set_bit' at include/asm-generic/bitops/instrumented-atomic.h:71:2,
inlined from 'counter_validate' at drivers/net/wireguard/receive.c:325:9,
inlined from 'wg_packet_rx_poll' at drivers/net/wireguard/receive.c:461:7:
include/linux/kcsan-checks.h:220:28: error: '__kcsan_check_access' expecting 0 bytes in a region of size 0 [-Werror=stringop-overread]
220 | #define kcsan_check_access __kcsan_check_access
| ^
include/linux/kcsan-checks.h:336:9: note: in expansion of macro 'kcsan_check_access'
336 | kcsan_check_access(ptr, size, KCSAN_ACCESS_ATOMIC | KCSAN_ACCESS_WRITE | KCSAN_ACCESS_COMPOUND)
| ^~~~~~~~~~~~~~~~~~
include/linux/instrumented.h:113:9: note: in expansion of macro 'kcsan_check_atomic_read_write'
113 | kcsan_check_atomic_read_write(v, size);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from drivers/net/wireguard/device.h:9,
from drivers/net/wireguard/peer.h:9,
from drivers/net/wireguard/queueing.h:9,
from drivers/net/wireguard/receive.c:6:
include/linux/instrumented.h: In function 'wg_packet_rx_poll':
drivers/net/wireguard/noise.h:19:13: note: at offset [80, 1096] into source object 'counter' of size 8
19 | u64 counter;
| ^~~~~~~
In file included from include/asm-generic/rwonce.h:27,
from arch/arm64/include/asm/rwonce.h:81,
from include/linux/compiler.h:369,
from include/asm-generic/bug.h:5,
from arch/arm64/include/asm/bug.h:26,
from include/linux/bug.h:5,
from include/linux/random.h:6,
from include/crypto/curve25519.h:10,
from drivers/net/wireguard/messages.h:9,
from drivers/net/wireguard/noise.h:8,
from drivers/net/wireguard/device.h:9,
from drivers/net/wireguard/peer.h:9,
from drivers/net/wireguard/queueing.h:9,
from drivers/net/wireguard/receive.c:6:
include/linux/kcsan-checks.h:37:6: note: in a call to function '__kcsan_check_access' declared with attribute 'access (none, 1)'
37 | void __kcsan_check_access(const volatile void *ptr, size_t size, int type) __access(none, 1);
| ^~~~~~~~~~~~~~~~~~~~

3.

In file included from include/asm-generic/rwonce.h:27,
from arch/arm64/include/asm/rwonce.h:81,
from include/linux/compiler.h:369,
from include/asm-generic/div64.h:27,
from ./arch/arm64/include/generated/asm/div64.h:1,
from include/linux/math.h:6,
from include/linux/delay.h:12,
from drivers/misc/bcm-vk/bcm_vk_msg.c:6:
In function 'instrument_atomic_write',
inlined from 'atomic_set' at include/linux/atomic/atomic-instrumented.h:67:2,
inlined from 'bcm_vk_get_ctx' at drivers/misc/bcm-vk/bcm_vk_msg.c:250:2,
inlined from 'bcm_vk_open' at drivers/misc/bcm-vk/bcm_vk_msg.c:980:8:
include/linux/kcsan-checks.h:220:28: error: '__kcsan_check_access' expecting 0 bytes in a region of size 0 [-Werror=stringop-overread]
220 | #define kcsan_check_access __kcsan_check_access
| ^
include/linux/kcsan-checks.h:334:9: note: in expansion of macro 'kcsan_check_access'
334 | kcsan_check_access(ptr, size, KCSAN_ACCESS_ATOMIC | KCSAN_ACCESS_WRITE)
| ^~~~~~~~~~~~~~~~~~
include/linux/instrumented.h:98:9: note: in expansion of macro 'kcsan_check_atomic_write'
98 | kcsan_check_atomic_write(v, size);
| ^~~~~~~~~~~~~~~~~~~~~~~~
In file included from drivers/misc/bcm-vk/bcm_vk_msg.c:17:
include/linux/instrumented.h: In function 'bcm_vk_open':
drivers/misc/bcm-vk/bcm_vk.h:359:25: note: at offset [1576, 23200] into source object 'pdev' of size 8
359 | struct pci_dev *pdev;
| ^~~~
In file included from include/asm-generic/rwonce.h:27,
from arch/arm64/include/asm/rwonce.h:81,
from include/linux/compiler.h:369,
from include/asm-generic/div64.h:27,
from ./arch/arm64/include/generated/asm/div64.h:1,
from include/linux/math.h:6,
from include/linux/delay.h:12,
from drivers/misc/bcm-vk/bcm_vk_msg.c:6:
include/linux/kcsan-checks.h:37:6: note: in a call to function '__kcsan_check_access' declared with attribute 'access (none, 1)'
37 | void __kcsan_check_access(const volatile void *ptr, size_t size, int type) __access(none, 1);
| ^~~~~~~~~~~~~~~~~~~~
In function 'instrument_atomic_write',
inlined from 'atomic_set' at include/linux/atomic/atomic-instrumented.h:67:2,
inlined from 'bcm_vk_get_ctx' at drivers/misc/bcm-vk/bcm_vk_msg.c:251:2,
inlined from 'bcm_vk_open' at drivers/misc/bcm-vk/bcm_vk_msg.c:980:8:
include/linux/kcsan-checks.h:220:28: error: '__kcsan_check_access' expecting 0 bytes in a region of size 0 [-Werror=stringop-overread]
220 | #define kcsan_check_access __kcsan_check_access
| ^
include/linux/kcsan-checks.h:334:9: note: in expansion of macro 'kcsan_check_access'
334 | kcsan_check_access(ptr, size, KCSAN_ACCESS_ATOMIC | KCSAN_ACCESS_WRITE)
| ^~~~~~~~~~~~~~~~~~
include/linux/instrumented.h:98:9: note: in expansion of macro 'kcsan_check_atomic_write'
98 | kcsan_check_atomic_write(v, size);
| ^~~~~~~~~~~~~~~~~~~~~~~~
In file included from drivers/misc/bcm-vk/bcm_vk_msg.c:17:
include/linux/instrumented.h: In function 'bcm_vk_open':
drivers/misc/bcm-vk/bcm_vk.h:359:25: note: at offset [1580, 23204] into source object 'pdev' of size 8
359 | struct pci_dev *pdev;
| ^~~~
In file included from include/asm-generic/rwonce.h:27,
from arch/arm64/include/asm/rwonce.h:81,
from include/linux/compiler.h:369,
from include/asm-generic/div64.h:27,
from ./arch/arm64/include/generated/asm/div64.h:1,
from include/linux/math.h:6,
from include/linux/delay.h:12,
from drivers/misc/bcm-vk/bcm_vk_msg.c:6:
include/linux/kcsan-checks.h:37:6: note: in a call to function '__kcsan_check_access' declared with attribute 'access (none, 1)'
37 | void __kcsan_check_access(const volatile void *ptr, size_t size, int type) __access(none, 1);
| ^~~~~~~~~~~~~~~~~~~~

4.

In file included from include/asm-generic/rwonce.h:27,
from ./arch/x86/include/generated/asm/rwonce.h:1,
from include/linux/compiler.h:369,
from include/asm-generic/bug.h:5,
from arch/x86/include/asm/bug.h:193,
from include/linux/bug.h:5,
from include/linux/mmdebug.h:5,
from include/linux/mm.h:7,
from mm/vmscan.c:15:
In function 'instrument_atomic_read_write',
inlined from 'atomic_long_add' at include/linux/atomic/atomic-instrumented.h:3260:2,
inlined from 'node_page_state_add' at include/linux/vmstat.h:172:2,
inlined from '__mod_node_page_state' at include/linux/vmstat.h:331:2,
inlined from 'shrink_active_list' at mm/vmscan.c:2149:2,
inlined from 'shrink_list' at mm/vmscan.c:2220:4,
inlined from 'shrink_lruvec' at mm/vmscan.c:5969:21:
include/linux/kcsan-checks.h:220:28: error: '__kcsan_check_access' expecting 0 bytes in a region of size 0 [-Werror=stringop-overread]
220 | #define kcsan_check_access __kcsan_check_access
| ^
include/linux/kcsan-checks.h:336:9: note: in expansion of macro 'kcsan_check_access'
336 | kcsan_check_access(ptr, size, KCSAN_ACCESS_ATOMIC | KCSAN_ACCESS_WRITE | KCSAN_ACCESS_COMPOUND)
| ^~~~~~~~~~~~~~~~~~
include/linux/instrumented.h:113:9: note: in expansion of macro 'kcsan_check_atomic_read_write'
113 | kcsan_check_atomic_read_write(v, size);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from include/linux/gfp.h:7,
from include/linux/mm.h:8,
from mm/vmscan.c:15:
include/linux/instrumented.h: In function 'shrink_lruvec':
include/linux/mmzone.h:1478:21: note: at offset [10272, 10280] into source object 'node_zones' of size 7264
1478 | struct zone node_zones[MAX_NR_ZONES];
| ^~~~~~~~~~
In file included from include/asm-generic/rwonce.h:27,
from ./arch/x86/include/generated/asm/rwonce.h:1,
from include/linux/compiler.h:369,
from include/asm-generic/bug.h:5,
from arch/x86/include/asm/bug.h:193,
from include/linux/bug.h:5,
from include/linux/mmdebug.h:5,
from include/linux/mm.h:7,
from mm/vmscan.c:15:
include/linux/kcsan-checks.h:37:6: note: in a call to function '__kcsan_check_access' declared with attribute 'access (none, 1)'
37 | void __kcsan_check_access(const volatile void *ptr, size_t size, int type) __access(none, 1);
| ^~~~~~~~~~~~~~~~~~~~
In function 'instrument_atomic_read_write',
inlined from 'atomic_long_add' at include/linux/atomic/atomic-instrumented.h:3260:2,
inlined from 'node_page_state_add' at include/linux/vmstat.h:172:2,
inlined from '__mod_node_page_state' at include/linux/vmstat.h:331:2,
inlined from 'mod_lruvec_state' at include/linux/vmstat.h:536:2,
inlined from 'shrink_inactive_list' at mm/vmscan.c:1987:2,
inlined from 'shrink_list' at mm/vmscan.c:2226:9,
inlined from 'shrink_lruvec' at mm/vmscan.c:5969:21:
include/linux/kcsan-checks.h:220:28: error: '__kcsan_check_access' expecting 0 bytes in a region of size 0 [-Werror=stringop-overread]
220 | #define kcsan_check_access __kcsan_check_access
| ^
include/linux/kcsan-checks.h:336:9: note: in expansion of macro 'kcsan_check_access'
336 | kcsan_check_access(ptr, size, KCSAN_ACCESS_ATOMIC | KCSAN_ACCESS_WRITE | KCSAN_ACCESS_COMPOUND)
| ^~~~~~~~~~~~~~~~~~
include/linux/instrumented.h:113:9: note: in expansion of macro 'kcsan_check_atomic_read_write'
113 | kcsan_check_atomic_read_write(v, size);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from include/linux/gfp.h:7,
from include/linux/mm.h:8,
from mm/vmscan.c:15:
include/linux/instrumented.h: In function 'shrink_lruvec':
include/linux/mmzone.h:1478:21: note: at offset [10624, 10648] into source object 'node_zones' of size 7264
1478 | struct zone node_zones[MAX_NR_ZONES];
| ^~~~~~~~~~
In file included from include/asm-generic/rwonce.h:27,
from ./arch/x86/include/generated/asm/rwonce.h:1,
from include/linux/compiler.h:369,
from include/asm-generic/bug.h:5,
from arch/x86/include/asm/bug.h:193,
from include/linux/bug.h:5,
from include/linux/mmdebug.h:5,
from include/linux/mm.h:7,
from mm/vmscan.c:15:

I've attached one .config for each of the above, but haven't looked in
too much detail. For the wireguard case, I managed to simplify the
code so gcc doesn't get confused by the pointer arithmetic:

--- a/drivers/net/wireguard/receive.c
+++ b/drivers/net/wireguard/receive.c
@@ -321,9 +321,8 @@ static bool counter_validate(struct noise_replay_counter *counter, u64 their_cou
WRITE_ONCE(counter->counter, their_counter);
}

- index &= (COUNTER_BITS_TOTAL / BITS_PER_LONG) - 1;
- ret = !test_and_set_bit(their_counter & (BITS_PER_LONG - 1),
- &counter->backtrack[index]);
+ ret = !test_and_set_bit(their_counter & (COUNTER_BITS_TOTAL - 1),
+ counter->backtrack);

out:
spin_unlock_bh(&counter->lock);


Arnd
0xD490B040_defconfig
0x83019D90_defconfig
0x82DE0922_defconfig
0xE7F14A61_defconfig

Marco Elver

unread,
Apr 22, 2026, 4:24:20 AM (8 days ago) Apr 22
to Arnd Bergmann, Konstantin Komarov, Dmitry Vyukov, nt...@lists.linux.dev, linux-...@vger.kernel.org, kasa...@googlegroups.com
On Wed, 22 Apr 2026 at 10:00, Arnd Bergmann <ar...@arndb.de> wrote:
>
> On Tue, Apr 21, 2026, at 21:12, Arnd Bergmann wrote:
> > On Tue, Apr 21, 2026, at 21:06, Marco Elver wrote:
> >> On Tue, 21 Apr 2026 at 17:26, Marco Elver <el...@google.com> wrote:
> >> [...]
> >>> > To me, 2 makes more sense. The attribute requires gcc-11 or higher,
> >>> > so you need to wrap that in a compiler version specific macro,
> >>> > but since I only saw the warning with gcc-12 and higher, that
> >>> > should be fine.
> >>
> >> Kindly test if you can:
> >> https://lore.kernel.org/all/20260421190351....@google.com/
> >
> > Applied to my randconfig tree and verified that this fixes the
> > known warning (only one out of about 200 random configs). I'll
> > let you know if something comes up by tomorrow.
>
> Unfortunately, there are new warnings after your patches using
> gcc-11. In 500 randconfig builds with that compiler, I saw 7
> configurations failing with one of these four messages:

Looks like a compiler bug to me; can you check gcc-12+ ? Maybe we need
to allow the __access attribute only for later GCC versions.

Marco Elver

unread,
Apr 22, 2026, 7:35:53 AM (8 days ago) Apr 22
to Arnd Bergmann, Konstantin Komarov, Dmitry Vyukov, nt...@lists.linux.dev, linux-...@vger.kernel.org, kasa...@googlegroups.com
I can also see this warning with later GCC - so I'll give up on the
__attribute__((access)) version and instead suppress warnings.

Marco Elver

unread,
Apr 22, 2026, 7:51:31 AM (8 days ago) Apr 22
to Arnd Bergmann, Konstantin Komarov, Dmitry Vyukov, nt...@lists.linux.dev, linux-...@vger.kernel.org, kasa...@googlegroups.com
The simplest solution I found so far:

diff --git a/include/linux/kcsan-checks.h b/include/linux/kcsan-checks.h
index 92f3843d9ebb..989fd21841ba 100644
--- a/include/linux/kcsan-checks.h
+++ b/include/linux/kcsan-checks.h
@@ -282,7 +282,7 @@ static inline void __kcsan_disable_current(void) { }
* @size: size of access
*/
#define __kcsan_check_write(ptr, size) \
- __kcsan_check_access(ptr, size, KCSAN_ACCESS_WRITE)
+ __kcsan_check_access(absolute_pointer(ptr), size, KCSAN_ACCESS_WRITE)

/**
* __kcsan_check_read_write - check regular read-write access for races
@@ -291,7 +291,7 @@ static inline void __kcsan_disable_current(void) { }
* @size: size of access
*/
#define __kcsan_check_read_write(ptr, size) \
- __kcsan_check_access(ptr, size, KCSAN_ACCESS_COMPOUND | KCSAN_ACCESS_WRITE)
+ __kcsan_check_access(absolute_pointer(ptr), size, KCSAN_ACCESS_COMPOUND | KCSAN_ACCESS_WRITE)

/**
* kcsan_check_read - check regular read access for races
@@ -308,7 +308,7 @@ static inline void __kcsan_disable_current(void) { }
* @size: size of access
*/
#define kcsan_check_write(ptr, size) \
- kcsan_check_access(ptr, size, KCSAN_ACCESS_WRITE)
+ kcsan_check_access(absolute_pointer(ptr), size, KCSAN_ACCESS_WRITE)

/**
* kcsan_check_read_write - check regular read-write access for races
@@ -317,7 +317,7 @@ static inline void __kcsan_disable_current(void) { }
* @size: size of access
*/
#define kcsan_check_read_write(ptr, size) \
- kcsan_check_access(ptr, size, KCSAN_ACCESS_COMPOUND | KCSAN_ACCESS_WRITE)
+ kcsan_check_access(absolute_pointer(ptr), size, KCSAN_ACCESS_COMPOUND | KCSAN_ACCESS_WRITE)

/*
* Check for atomic accesses: if atomic accesses are not ignored, this simply
@@ -331,9 +331,9 @@ static inline void __kcsan_disable_current(void) { }
#define kcsan_check_atomic_read(ptr, size) \
kcsan_check_access(ptr, size, KCSAN_ACCESS_ATOMIC)
#define kcsan_check_atomic_write(ptr, size) \
- kcsan_check_access(ptr, size, KCSAN_ACCESS_ATOMIC | KCSAN_ACCESS_WRITE)
+ kcsan_check_access(absolute_pointer(ptr), size, KCSAN_ACCESS_ATOMIC | KCSAN_ACCESS_WRITE)
#define kcsan_check_atomic_read_write(ptr, size) \
- kcsan_check_access(ptr, size, KCSAN_ACCESS_ATOMIC | KCSAN_ACCESS_WRITE | KCSAN_ACCESS_COMPOUND)
+ kcsan_check_access(absolute_pointer(ptr), size, KCSAN_ACCESS_ATOMIC | KCSAN_ACCESS_WRITE | KCSAN_ACCESS_COMPOUND)
#endif

/**

Arnd Bergmann

unread,
Apr 22, 2026, 4:57:48 PM (8 days ago) Apr 22
to Marco Elver, Konstantin Komarov, Dmitry Vyukov, nt...@lists.linux.dev, linux-...@vger.kernel.org, kasa...@googlegroups.com
All gcc versions I tried that support kcsan run into some of
the warnings, but the exact set is not always the same.

The stringop-overread warnings are (like -Wmaybe-uninitialized)
a bit unpredictable and depend on the exact optimizations taken
by the compiler, to see exactly which object is passed into
a string operation and what its size is.

I'm guessing that by annotating a function argument as being
not accessed, gcc starts assuming that the object has zero
valid bytes if it cannot deduce the actual length in any
other way.

Arnd

Marco Elver

unread,
Apr 22, 2026, 5:51:01 PM (8 days ago) Apr 22
to Arnd Bergmann, Konstantin Komarov, Dmitry Vyukov, nt...@lists.linux.dev, linux-...@vger.kernel.org, kasa...@googlegroups.com
Thanks for confirming - this is rather unfortunate. I wish a suitable
attribute would exist to suppress this, but I guess that's not yet the
case.

Which means the simplest fix is probably the absolute_pointer() one.

Thanks,
-- Marco

David Laight

unread,
Apr 23, 2026, 4:12:51 AM (7 days ago) Apr 23
to Marco Elver, Arnd Bergmann, Konstantin Komarov, Dmitry Vyukov, nt...@lists.linux.dev, linux-...@vger.kernel.org, kasa...@googlegroups.com
On Wed, 22 Apr 2026 23:50:22 +0200
Marco Elver <el...@google.com> wrote:

> Which means the simplest fix is probably the absolute_pointer() one.

I'm not sure that using absolute_pointer() is right, it is normally used
for special conversions in low level boot code.

Here it might just be best to explicitly use (void *)(long)addr.

David


>
> Thanks,
> -- Marco
>

Marco Elver

unread,
Apr 23, 2026, 7:35:49 AM (7 days ago) Apr 23
to David Laight, Arnd Bergmann, Konstantin Komarov, Dmitry Vyukov, nt...@lists.linux.dev, linux-...@vger.kernel.org, kasa...@googlegroups.com
On Thu, 23 Apr 2026 at 10:12, David Laight <david.lai...@gmail.com> wrote:
> On Wed, 22 Apr 2026 23:50:22 +0200
> Marco Elver <el...@google.com> wrote:
>
> > Which means the simplest fix is probably the absolute_pointer() one.
>
> I'm not sure that using absolute_pointer() is right, it is normally used
> for special conversions in low level boot code.
>
> Here it might just be best to explicitly use (void *)(long)addr.

That didn't work - tried, and warnings still there (GCC seems to see
through it).

So that leaves:
- absolute_pointer()
- __diag_ignore_all wrapper (mentioned elsewhere in thread)

Preferences?

Thanks,
-- Marco

David Laight

unread,
Apr 23, 2026, 9:06:18 AM (7 days ago) Apr 23
to Marco Elver, Arnd Bergmann, Konstantin Komarov, Dmitry Vyukov, nt...@lists.linux.dev, linux-...@vger.kernel.org, kasa...@googlegroups.com
On Thu, 23 Apr 2026 13:35:09 +0200
Marco Elver <el...@google.com> wrote:

> On Thu, 23 Apr 2026 at 10:12, David Laight <david.lai...@gmail.com> wrote:
> > On Wed, 22 Apr 2026 23:50:22 +0200
> > Marco Elver <el...@google.com> wrote:
> >
> > > Which means the simplest fix is probably the absolute_pointer() one.
> >
> > I'm not sure that using absolute_pointer() is right, it is normally used
> > for special conversions in low level boot code.
> >
> > Here it might just be best to explicitly use (void *)(long)addr.
>
> That didn't work - tried, and warnings still there (GCC seems to see
> through it).

The only difference is the extra local - unless the '+ 0' matters.

OPTIMIZE_HIDE_VAR() should work, but is annoying to use in a function call.
You sort of need:
#define OPTIMIZER_HIDE_VAL(x) {( \
auto _x = x; \
asm ("", "+r" (_x)); \
_x; \
)}

(also useful for 'lying' to snprintf())

David

Marco Elver

unread,
Apr 24, 2026, 6:04:34 AM (6 days ago) Apr 24
to David Laight, Arnd Bergmann, Konstantin Komarov, Dmitry Vyukov, nt...@lists.linux.dev, linux-...@vger.kernel.org, kasa...@googlegroups.com
On Thu, 23 Apr 2026 at 15:06, David Laight <david.lai...@gmail.com> wrote:
>
> On Thu, 23 Apr 2026 13:35:09 +0200
> Marco Elver <el...@google.com> wrote:
>
> > On Thu, 23 Apr 2026 at 10:12, David Laight <david.lai...@gmail.com> wrote:
> > > On Wed, 22 Apr 2026 23:50:22 +0200
> > > Marco Elver <el...@google.com> wrote:
> > >
> > > > Which means the simplest fix is probably the absolute_pointer() one.
> > >
> > > I'm not sure that using absolute_pointer() is right, it is normally used
> > > for special conversions in low level boot code.
> > >
> > > Here it might just be best to explicitly use (void *)(long)addr.
> >
> > That didn't work - tried, and warnings still there (GCC seems to see
> > through it).
>
> The only difference is the extra local - unless the '+ 0' matters.
>
> OPTIMIZE_HIDE_VAR() should work, but is annoying to use in a function call.
> You sort of need:
> #define OPTIMIZER_HIDE_VAL(x) {( \
> auto _x = x; \
> asm ("", "+r" (_x)); \
> _x; \
> )}
>
> (also useful for 'lying' to snprintf())

Isn't that effectively what RELOC_HIDE (and absolute_pointer) is
supposed to do? I don't see the need to add another similar macro, we
already have too many horrible macros like this. And in this case it's
not necessarily the optimizer we're trying to hide this wrong, but
from the semantic analyzer that gives us these false positive
diagnostics.
Reply all
Reply to author
Forward
0 new messages