diff mbox series

[bpf-next] libbpf: hashmap.h update to fix build issues using LLVM14

Message ID 20221110223240.1350810-1-eddyz87@gmail.com (mailing list archive)
State Accepted
Commit 42597aa372f5d2f26f209c5db36b1cd098b27147
Delegated to: BPF
Headers show
Series [bpf-next] libbpf: hashmap.h update to fix build issues using LLVM14 | expand

Checks

Context Check Description
netdev/tree_selection success Clearly marked for bpf-next
netdev/fixes_present success Fixes tag not required for -next series
netdev/subject_prefix success Link
netdev/cover_letter success Single patches do not need cover letters
netdev/patch_count success Link
netdev/header_inline success No static functions without inline keyword in header files
netdev/build_32bit success Errors and warnings before: 0 this patch: 0
netdev/cc_maintainers warning 18 maintainers not CCed: sdf@google.com mark.rutland@arm.com kpsingh@kernel.org song@kernel.org alexander.shishkin@linux.intel.com haoluo@google.com peterz@infradead.org ndesaulniers@google.com mingo@redhat.com trix@redhat.com john.fastabend@gmail.com jolsa@kernel.org martin.lau@linux.dev nathan@kernel.org namhyung@kernel.org linux-perf-users@vger.kernel.org llvm@lists.linux.dev acme@kernel.org
netdev/build_clang success Errors and warnings before: 0 this patch: 0
netdev/module_param success Was 0 now: 0
netdev/verify_signedoff success Signed-off-by tag matches author and committer
netdev/check_selftest success No net selftest shell script
netdev/verify_fixes success No Fixes tag
netdev/build_allmodconfig_warn success Errors and warnings before: 0 this patch: 0
netdev/checkpatch warning WARNING: line length of 89 exceeds 80 columns
netdev/kdoc success Errors and warnings before: 0 this patch: 0
netdev/source_inline success Was 0 now: 0
bpf/vmtest-bpf-next-PR fail PR summary
bpf/vmtest-bpf-next-VM_Test-11 success Logs for test_maps on s390x with gcc
bpf/vmtest-bpf-next-VM_Test-21 success Logs for test_progs_no_alu32 on s390x with gcc
bpf/vmtest-bpf-next-VM_Test-36 success Logs for test_verifier on s390x with gcc
bpf/vmtest-bpf-next-VM_Test-16 success Logs for test_progs on s390x with gcc
bpf/vmtest-bpf-next-VM_Test-26 success Logs for test_progs_no_alu32_parallel on s390x with gcc
bpf/vmtest-bpf-next-VM_Test-31 success Logs for test_progs_parallel on s390x with gcc
bpf/vmtest-bpf-next-VM_Test-4 success Logs for build for s390x with gcc
bpf/vmtest-bpf-next-VM_Test-9 success Logs for test_maps on aarch64 with gcc
bpf/vmtest-bpf-next-VM_Test-10 success Logs for test_maps on aarch64 with llvm-16
bpf/vmtest-bpf-next-VM_Test-12 success Logs for test_maps on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-13 success Logs for test_maps on x86_64 with llvm-16
bpf/vmtest-bpf-next-VM_Test-14 success Logs for test_progs on aarch64 with gcc
bpf/vmtest-bpf-next-VM_Test-15 success Logs for test_progs on aarch64 with llvm-16
bpf/vmtest-bpf-next-VM_Test-17 success Logs for test_progs on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-18 fail Logs for test_progs on x86_64 with llvm-16
bpf/vmtest-bpf-next-VM_Test-19 success Logs for test_progs_no_alu32 on aarch64 with gcc
bpf/vmtest-bpf-next-VM_Test-20 success Logs for test_progs_no_alu32 on aarch64 with llvm-16
bpf/vmtest-bpf-next-VM_Test-22 success Logs for test_progs_no_alu32 on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-23 success Logs for test_progs_no_alu32 on x86_64 with llvm-16
bpf/vmtest-bpf-next-VM_Test-24 success Logs for test_progs_no_alu32_parallel on aarch64 with gcc
bpf/vmtest-bpf-next-VM_Test-25 success Logs for test_progs_no_alu32_parallel on aarch64 with llvm-16
bpf/vmtest-bpf-next-VM_Test-27 success Logs for test_progs_no_alu32_parallel on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-28 success Logs for test_progs_no_alu32_parallel on x86_64 with llvm-16
bpf/vmtest-bpf-next-VM_Test-29 success Logs for test_progs_parallel on aarch64 with gcc
bpf/vmtest-bpf-next-VM_Test-30 success Logs for test_progs_parallel on aarch64 with llvm-16
bpf/vmtest-bpf-next-VM_Test-32 success Logs for test_progs_parallel on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-33 success Logs for test_progs_parallel on x86_64 with llvm-16
bpf/vmtest-bpf-next-VM_Test-34 success Logs for test_verifier on aarch64 with gcc
bpf/vmtest-bpf-next-VM_Test-35 success Logs for test_verifier on aarch64 with llvm-16
bpf/vmtest-bpf-next-VM_Test-37 success Logs for test_verifier on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-38 success Logs for test_verifier on x86_64 with llvm-16
bpf/vmtest-bpf-next-VM_Test-1 success Logs for ShellCheck
bpf/vmtest-bpf-next-VM_Test-2 success Logs for build for aarch64 with gcc
bpf/vmtest-bpf-next-VM_Test-3 success Logs for build for aarch64 with llvm-16
bpf/vmtest-bpf-next-VM_Test-5 success Logs for build for x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-6 success Logs for build for x86_64 with llvm-16
bpf/vmtest-bpf-next-VM_Test-7 success Logs for llvm-toolchain
bpf/vmtest-bpf-next-VM_Test-8 success Logs for set-matrix

Commit Message

Eduard Zingerman Nov. 10, 2022, 10:32 p.m. UTC
A fix for the LLVM compilation error while building bpftool.
Replaces the expression:

  _Static_assert((p) == NULL || ...)

by expression:

  _Static_assert((__builtin_constant_p((p)) ? (p) == NULL : 0) || ...)

When "p" is not a constant the former is not considered to be a
constant expression by LLVM 14.

The error was introduced in the following patch-set: [1].
The error was reported here: [2].

Reported-by: kernel test robot <lkp@intel.com>
Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>

[1] https://lore.kernel.org/bpf/20221109142611.879983-1-eddyz87@gmail.com/
[2] https://lore.kernel.org/all/202211110355.BcGcbZxP-lkp@intel.com/
---
 tools/lib/bpf/hashmap.h   | 3 ++-
 tools/perf/util/hashmap.h | 3 ++-
 2 files changed, 4 insertions(+), 2 deletions(-)

Comments

Stanislav Fomichev Nov. 11, 2022, 1:25 a.m. UTC | #1
On 11/11, Eduard Zingerman wrote:
> A fix for the LLVM compilation error while building bpftool.
> Replaces the expression:

>    _Static_assert((p) == NULL || ...)

> by expression:

>    _Static_assert((__builtin_constant_p((p)) ? (p) == NULL : 0) || ...)

IIUC, when __builtin_constant_p(p) returns false, we just ignore the NULL  
check?
Do we have cases like that? If no, maybe it's safer to fail?

s/(p) == NULL : 0/(p) == NULL : 1/ ?

> When "p" is not a constant the former is not considered to be a
> constant expression by LLVM 14.

> The error was introduced in the following patch-set: [1].
> The error was reported here: [2].

> Reported-by: kernel test robot <lkp@intel.com>
> Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>

> [1] https://lore.kernel.org/bpf/20221109142611.879983-1-eddyz87@gmail.com/
> [2] https://lore.kernel.org/all/202211110355.BcGcbZxP-lkp@intel.com/
> ---
>   tools/lib/bpf/hashmap.h   | 3 ++-
>   tools/perf/util/hashmap.h | 3 ++-
>   2 files changed, 4 insertions(+), 2 deletions(-)

> diff --git a/tools/lib/bpf/hashmap.h b/tools/lib/bpf/hashmap.h
> index 3fe647477bad..0a5bf1937a7c 100644
> --- a/tools/lib/bpf/hashmap.h
> +++ b/tools/lib/bpf/hashmap.h
> @@ -123,7 +123,8 @@ enum hashmap_insert_strategy {
>   };

>   #define hashmap_cast_ptr(p) ({								\
> -	_Static_assert((p) == NULL || sizeof(*(p)) == sizeof(long),			\
> +	_Static_assert((__builtin_constant_p((p)) ? (p) == NULL : 0) ||			\
> +				sizeof(*(p)) == sizeof(long),				\
>   		       #p " pointee should be a long-sized integer or a pointer");	\
>   	(long *)(p);									\
>   })
> diff --git a/tools/perf/util/hashmap.h b/tools/perf/util/hashmap.h
> index 3fe647477bad..0a5bf1937a7c 100644
> --- a/tools/perf/util/hashmap.h
> +++ b/tools/perf/util/hashmap.h
> @@ -123,7 +123,8 @@ enum hashmap_insert_strategy {
>   };

>   #define hashmap_cast_ptr(p) ({								\
> -	_Static_assert((p) == NULL || sizeof(*(p)) == sizeof(long),			\
> +	_Static_assert((__builtin_constant_p((p)) ? (p) == NULL : 0) ||			\
> +				sizeof(*(p)) == sizeof(long),				\
>   		       #p " pointee should be a long-sized integer or a pointer");	\
>   	(long *)(p);									\
>   })
> --
> 2.34.1
Stanislav Fomichev Nov. 11, 2022, 1:34 a.m. UTC | #2
On 11/10, Stanislav Fomichev wrote:
> On 11/11, Eduard Zingerman wrote:
> > A fix for the LLVM compilation error while building bpftool.
> > Replaces the expression:
> >
> >   _Static_assert((p) == NULL || ...)
> >
> > by expression:
> >
> >   _Static_assert((__builtin_constant_p((p)) ? (p) == NULL : 0) || ...)

> IIUC, when __builtin_constant_p(p) returns false, we just ignore the NULL  
> check?
> Do we have cases like that? If no, maybe it's safer to fail?

> s/(p) == NULL : 0/(p) == NULL : 1/ ?

I'm probably missing something, can you pls clarify? So the error is as
follows:

>> btf_dump.c:1546:2: error: static_assert expression is not an integral  
>> constant expression
    hashmap__find(name_map, orig_name, &dup_cnt);
    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    ./hashmap.h:169:35: note: expanded from macro 'hashmap__find'
    hashmap_find((map), (long)(key), hashmap_cast_ptr(value))
    ^~~~~~~~~~~~~~~~~~~~~~~
    ./hashmap.h:126:17: note: expanded from macro 'hashmap_cast_ptr'
    _Static_assert((p) == NULL || sizeof(*(p)) ==  
sizeof(long),                                             
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    btf_dump.c:1546:2: note: cast from 'void *' is not allowed in a constant  
expression
    ./hashmap.h:169:35: note: expanded from macro 'hashmap__find'
    hashmap_find((map), (long)(key), hashmap_cast_ptr(value))

This line in particular:

    btf_dump.c:1546:2: note: cast from 'void *' is not allowed in a constant  
expression

And the code does:

   size_t dup_cnt = 0;
   hashmap__find(name_map, orig_name, &dup_cnt);

So where is that cast from 'void *' is happening? Is it the NULL check  
itself?

Are we simply guarding against the user calling hashmap_cast_ptr with
explicit NULL argument?

> > When "p" is not a constant the former is not considered to be a
> > constant expression by LLVM 14.
> >
> > The error was introduced in the following patch-set: [1].
> > The error was reported here: [2].
> >
> > Reported-by: kernel test robot <lkp@intel.com>
> > Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>
> >
> > [1]  
> https://lore.kernel.org/bpf/20221109142611.879983-1-eddyz87@gmail.com/
> > [2] https://lore.kernel.org/all/202211110355.BcGcbZxP-lkp@intel.com/
> > ---
> >  tools/lib/bpf/hashmap.h   | 3 ++-
> >  tools/perf/util/hashmap.h | 3 ++-
> >  2 files changed, 4 insertions(+), 2 deletions(-)
> >
> > diff --git a/tools/lib/bpf/hashmap.h b/tools/lib/bpf/hashmap.h
> > index 3fe647477bad..0a5bf1937a7c 100644
> > --- a/tools/lib/bpf/hashmap.h
> > +++ b/tools/lib/bpf/hashmap.h
> > @@ -123,7 +123,8 @@ enum hashmap_insert_strategy {
> >  };
> >
> >  #define hashmap_cast_ptr(p) ({								\
> > -	_Static_assert((p) == NULL || sizeof(*(p)) == sizeof(long),			\
> > +	_Static_assert((__builtin_constant_p((p)) ? (p) == NULL : 0) ||			\
> > +				sizeof(*(p)) == sizeof(long),				\
> >  		       #p " pointee should be a long-sized integer or a pointer");	\
> >  	(long *)(p);									\
> >  })
> > diff --git a/tools/perf/util/hashmap.h b/tools/perf/util/hashmap.h
> > index 3fe647477bad..0a5bf1937a7c 100644
> > --- a/tools/perf/util/hashmap.h
> > +++ b/tools/perf/util/hashmap.h
> > @@ -123,7 +123,8 @@ enum hashmap_insert_strategy {
> >  };
> >
> >  #define hashmap_cast_ptr(p) ({								\
> > -	_Static_assert((p) == NULL || sizeof(*(p)) == sizeof(long),			\
> > +	_Static_assert((__builtin_constant_p((p)) ? (p) == NULL : 0) ||			\
> > +				sizeof(*(p)) == sizeof(long),				\
> >  		       #p " pointee should be a long-sized integer or a pointer");	\
> >  	(long *)(p);									\
> >  })
> > --
> > 2.34.1
> >
Eduard Zingerman Nov. 11, 2022, 1:44 a.m. UTC | #3
On Thu, 2022-11-10 at 17:34 -0800, sdf@google.com wrote:
> On 11/10, Stanislav Fomichev wrote:
> > On 11/11, Eduard Zingerman wrote:
> > > A fix for the LLVM compilation error while building bpftool.
> > > Replaces the expression:
> > > 
> > >   _Static_assert((p) == NULL || ...)
> > > 
> > > by expression:
> > > 
> > >   _Static_assert((__builtin_constant_p((p)) ? (p) == NULL : 0) || ...)
> 
> > IIUC, when __builtin_constant_p(p) returns false, we just ignore the NULL  
> > check?
> > Do we have cases like that? If no, maybe it's safer to fail?
> 
> > s/(p) == NULL : 0/(p) == NULL : 1/ ?
> 
> I'm probably missing something, can you pls clarify? So the error is as
> follows:
> 
> > > btf_dump.c:1546:2: error: static_assert expression is not an integral  
> > > constant expression
>     hashmap__find(name_map, orig_name, &dup_cnt);
>     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>     ./hashmap.h:169:35: note: expanded from macro 'hashmap__find'
>     hashmap_find((map), (long)(key), hashmap_cast_ptr(value))
>     ^~~~~~~~~~~~~~~~~~~~~~~
>     ./hashmap.h:126:17: note: expanded from macro 'hashmap_cast_ptr'
>     _Static_assert((p) == NULL || sizeof(*(p)) ==  
> sizeof(long),                                             
> ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>     btf_dump.c:1546:2: note: cast from 'void *' is not allowed in a constant  
> expression
>     ./hashmap.h:169:35: note: expanded from macro 'hashmap__find'
>     hashmap_find((map), (long)(key), hashmap_cast_ptr(value))
> 
> This line in particular:
> 
>     btf_dump.c:1546:2: note: cast from 'void *' is not allowed in a constant  
> expression
> 
> And the code does:
> 
>    size_t dup_cnt = 0;
>    hashmap__find(name_map, orig_name, &dup_cnt);
> 
> So where is that cast from 'void *' is happening? Is it the NULL check  
> itself?
> 
> Are we simply guarding against the user calling hashmap_cast_ptr with
> explicit NULL argument?

In case if (p) is not a constant I want the second part of the || to kick-in.
The complete condition looks as follows:

  _Static_assert((__builtin_constant_p((p)) ? (p) == NULL : 0) || \
			sizeof(*(p)) == sizeof(long), "...error...")

The intent is to check that (p) is either NULL or a pointer to
something of size long. So, if (p) is not a constant the expression
would be equivalent to:

  _Static_assert(0 || sizeof(*(p)) == sizeof(long), "...error...")

I just tried the following:

	struct hashmap *name_map;
	char x; // not a constant, wrong pointer size
	...
	hashmap__find(name_map, orig_name, &x);

And it fails with an error message as intended:

btf_dump.c:1548:2: error: static_assert failed due to requirement '(__builtin_constant_p((&x)) ? (&x) == ((void *)0) : 0) || sizeof (*(&x)) == sizeof(long)' "&x pointee should be a long-sized integer or a pointer"
        hashmap__find(name_map, orig_name, &x);
./hashmap.h:170:35: note: expanded from macro 'hashmap__find'
        hashmap_find((map), (long)(key), hashmap_cast_ptr(value))
./hashmap.h:126:2: note: expanded from macro 'hashmap_cast_ptr'
        _Static_assert((__builtin_constant_p((p)) ? (p) == NULL : 0) ||


> 
> > > When "p" is not a constant the former is not considered to be a
> > > constant expression by LLVM 14.
> > > 
> > > The error was introduced in the following patch-set: [1].
> > > The error was reported here: [2].
> > > 
> > > Reported-by: kernel test robot <lkp@intel.com>
> > > Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>
> > > 
> > > [1]  
> > https://lore.kernel.org/bpf/20221109142611.879983-1-eddyz87@gmail.com/
> > > [2] https://lore.kernel.org/all/202211110355.BcGcbZxP-lkp@intel.com/
> > > ---
> > >  tools/lib/bpf/hashmap.h   | 3 ++-
> > >  tools/perf/util/hashmap.h | 3 ++-
> > >  2 files changed, 4 insertions(+), 2 deletions(-)
> > > 
> > > diff --git a/tools/lib/bpf/hashmap.h b/tools/lib/bpf/hashmap.h
> > > index 3fe647477bad..0a5bf1937a7c 100644
> > > --- a/tools/lib/bpf/hashmap.h
> > > +++ b/tools/lib/bpf/hashmap.h
> > > @@ -123,7 +123,8 @@ enum hashmap_insert_strategy {
> > >  };
> > > 
> > >  #define hashmap_cast_ptr(p) ({								\
> > > -	_Static_assert((p) == NULL || sizeof(*(p)) == sizeof(long),			\
> > > +	_Static_assert((__builtin_constant_p((p)) ? (p) == NULL : 0) ||			\
> > > +				sizeof(*(p)) == sizeof(long),				\
> > >  		       #p " pointee should be a long-sized integer or a pointer");	\
> > >  	(long *)(p);									\
> > >  })
> > > diff --git a/tools/perf/util/hashmap.h b/tools/perf/util/hashmap.h
> > > index 3fe647477bad..0a5bf1937a7c 100644
> > > --- a/tools/perf/util/hashmap.h
> > > +++ b/tools/perf/util/hashmap.h
> > > @@ -123,7 +123,8 @@ enum hashmap_insert_strategy {
> > >  };
> > > 
> > >  #define hashmap_cast_ptr(p) ({								\
> > > -	_Static_assert((p) == NULL || sizeof(*(p)) == sizeof(long),			\
> > > +	_Static_assert((__builtin_constant_p((p)) ? (p) == NULL : 0) ||			\
> > > +				sizeof(*(p)) == sizeof(long),				\
> > >  		       #p " pointee should be a long-sized integer or a pointer");	\
> > >  	(long *)(p);									\
> > >  })
> > > --
> > > 2.34.1
> > >
Eduard Zingerman Nov. 11, 2022, 1:51 a.m. UTC | #4
On Thu, 2022-11-10 at 17:34 -0800, sdf@google.com wrote:
> On 11/10, Stanislav Fomichev wrote:
> > On 11/11, Eduard Zingerman wrote:
> > > A fix for the LLVM compilation error while building bpftool.
> > > Replaces the expression:
> > > 
> > >   _Static_assert((p) == NULL || ...)
> > > 
> > > by expression:
> > > 
> > >   _Static_assert((__builtin_constant_p((p)) ? (p) == NULL : 0) || ...)
> 
> > IIUC, when __builtin_constant_p(p) returns false, we just ignore the NULL  
> > check?
> > Do we have cases like that? If no, maybe it's safer to fail?
> 
> > s/(p) == NULL : 0/(p) == NULL : 1/ ?
> 
> I'm probably missing something, can you pls clarify? So the error is as
> follows:
> 
> > > btf_dump.c:1546:2: error: static_assert expression is not an integral  
> > > constant expression
>     hashmap__find(name_map, orig_name, &dup_cnt);
>     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>     ./hashmap.h:169:35: note: expanded from macro 'hashmap__find'
>     hashmap_find((map), (long)(key), hashmap_cast_ptr(value))
>     ^~~~~~~~~~~~~~~~~~~~~~~
>     ./hashmap.h:126:17: note: expanded from macro 'hashmap_cast_ptr'
>     _Static_assert((p) == NULL || sizeof(*(p)) ==  
> sizeof(long),                                             
> ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>     btf_dump.c:1546:2: note: cast from 'void *' is not allowed in a constant  
> expression
>     ./hashmap.h:169:35: note: expanded from macro 'hashmap__find'
>     hashmap_find((map), (long)(key), hashmap_cast_ptr(value))
> 
> This line in particular:
> 
>     btf_dump.c:1546:2: note: cast from 'void *' is not allowed in a constant  
> expression
> 
> And the code does:
> 
>    size_t dup_cnt = 0;
>    hashmap__find(name_map, orig_name, &dup_cnt);
> 
> So where is that cast from 'void *' is happening? Is it the NULL check  
> itself?

The void * comes from the definition of NULL: ((void*)0).
And, unfortunately, sizeoof(*((void*)0)) == 1, so two conditions
are necessary to allow a typical use-case when some of the pointer
parameters are omitted.

> 
> Are we simply guarding against the user calling hashmap_cast_ptr with
> explicit NULL argument?
> 
> > > When "p" is not a constant the former is not considered to be a
> > > constant expression by LLVM 14.
> > > 
> > > The error was introduced in the following patch-set: [1].
> > > The error was reported here: [2].
> > > 
> > > Reported-by: kernel test robot <lkp@intel.com>
> > > Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>
> > > 
> > > [1]  
> > https://lore.kernel.org/bpf/20221109142611.879983-1-eddyz87@gmail.com/
> > > [2] https://lore.kernel.org/all/202211110355.BcGcbZxP-lkp@intel.com/
> > > ---
> > >  tools/lib/bpf/hashmap.h   | 3 ++-
> > >  tools/perf/util/hashmap.h | 3 ++-
> > >  2 files changed, 4 insertions(+), 2 deletions(-)
> > > 
> > > diff --git a/tools/lib/bpf/hashmap.h b/tools/lib/bpf/hashmap.h
> > > index 3fe647477bad..0a5bf1937a7c 100644
> > > --- a/tools/lib/bpf/hashmap.h
> > > +++ b/tools/lib/bpf/hashmap.h
> > > @@ -123,7 +123,8 @@ enum hashmap_insert_strategy {
> > >  };
> > > 
> > >  #define hashmap_cast_ptr(p) ({								\
> > > -	_Static_assert((p) == NULL || sizeof(*(p)) == sizeof(long),			\
> > > +	_Static_assert((__builtin_constant_p((p)) ? (p) == NULL : 0) ||			\
> > > +				sizeof(*(p)) == sizeof(long),				\
> > >  		       #p " pointee should be a long-sized integer or a pointer");	\
> > >  	(long *)(p);									\
> > >  })
> > > diff --git a/tools/perf/util/hashmap.h b/tools/perf/util/hashmap.h
> > > index 3fe647477bad..0a5bf1937a7c 100644
> > > --- a/tools/perf/util/hashmap.h
> > > +++ b/tools/perf/util/hashmap.h
> > > @@ -123,7 +123,8 @@ enum hashmap_insert_strategy {
> > >  };
> > > 
> > >  #define hashmap_cast_ptr(p) ({								\
> > > -	_Static_assert((p) == NULL || sizeof(*(p)) == sizeof(long),			\
> > > +	_Static_assert((__builtin_constant_p((p)) ? (p) == NULL : 0) ||			\
> > > +				sizeof(*(p)) == sizeof(long),				\
> > >  		       #p " pointee should be a long-sized integer or a pointer");	\
> > >  	(long *)(p);									\
> > >  })
> > > --
> > > 2.34.1
> > >
Stanislav Fomichev Nov. 11, 2022, 5:19 p.m. UTC | #5
On 11/11, Eduard Zingerman wrote:
> On Thu, 2022-11-10 at 17:34 -0800, sdf@google.com wrote:
> > On 11/10, Stanislav Fomichev wrote:
> > > On 11/11, Eduard Zingerman wrote:
> > > > A fix for the LLVM compilation error while building bpftool.
> > > > Replaces the expression:
> > > >
> > > >   _Static_assert((p) == NULL || ...)
> > > >
> > > > by expression:
> > > >
> > > >   _Static_assert((__builtin_constant_p((p)) ? (p) == NULL : 0) | 
> | ...)
> >
> > > IIUC, when __builtin_constant_p(p) returns false, we just ignore the  
> NULL
> > > check?
> > > Do we have cases like that? If no, maybe it's safer to fail?
> >
> > > s/(p) == NULL : 0/(p) == NULL : 1/ ?
> >
> > I'm probably missing something, can you pls clarify? So the error is as
> > follows:
> >
> > > > btf_dump.c:1546:2: error: static_assert expression is not an  
> integral
> > > > constant expression
> >     hashmap__find(name_map, orig_name, &dup_cnt);
> >     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> >     ./hashmap.h:169:35: note: expanded from macro 'hashmap__find'
> >     hashmap_find((map), (long)(key), hashmap_cast_ptr(value))
> >     ^~~~~~~~~~~~~~~~~~~~~~~
> >     ./hashmap.h:126:17: note: expanded from macro 'hashmap_cast_ptr'
> >     _Static_assert((p) == NULL || sizeof(*(p)) ==
> > sizeof(long),
> > ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> >     btf_dump.c:1546:2: note: cast from 'void *' is not allowed in a  
> constant
> > expression
> >     ./hashmap.h:169:35: note: expanded from macro 'hashmap__find'
> >     hashmap_find((map), (long)(key), hashmap_cast_ptr(value))
> >
> > This line in particular:
> >
> >     btf_dump.c:1546:2: note: cast from 'void *' is not allowed in a  
> constant
> > expression
> >
> > And the code does:
> >
> >    size_t dup_cnt = 0;
> >    hashmap__find(name_map, orig_name, &dup_cnt);
> >
> > So where is that cast from 'void *' is happening? Is it the NULL check
> > itself?
> >
> > Are we simply guarding against the user calling hashmap_cast_ptr with
> > explicit NULL argument?

> In case if (p) is not a constant I want the second part of the || to  
> kick-in.
> The complete condition looks as follows:

>    _Static_assert((__builtin_constant_p((p)) ? (p) == NULL : 0) || \
> 			sizeof(*(p)) == sizeof(long), "...error...")

> The intent is to check that (p) is either NULL or a pointer to
> something of size long. So, if (p) is not a constant the expression
> would be equivalent to:

>    _Static_assert(0 || sizeof(*(p)) == sizeof(long), "...error...")

> I just tried the following:

> 	struct hashmap *name_map;
> 	char x; // not a constant, wrong pointer size
> 	...
> 	hashmap__find(name_map, orig_name, &x);

> And it fails with an error message as intended:

> btf_dump.c:1548:2: error: static_assert failed due to  
> requirement '(__builtin_constant_p((&x)) ? (&x) == ((void *)0) : 0) ||  
> sizeof (*(&x)) == sizeof(long)' "&x pointee should be a long-sized  
> integer or a pointer"
>          hashmap__find(name_map, orig_name, &x);
> ./hashmap.h:170:35: note: expanded from macro 'hashmap__find'
>          hashmap_find((map), (long)(key), hashmap_cast_ptr(value))
> ./hashmap.h:126:2: note: expanded from macro 'hashmap_cast_ptr'
>          _Static_assert((__builtin_constant_p((p)) ? (p) == NULL : 0) ||

Awesome, thanks for clarifying!

Acked-by: Stanislav Fomichev <sdf@google.com>

> >
> > > > When "p" is not a constant the former is not considered to be a
> > > > constant expression by LLVM 14.
> > > >
> > > > The error was introduced in the following patch-set: [1].
> > > > The error was reported here: [2].
> > > >
> > > > Reported-by: kernel test robot <lkp@intel.com>
> > > > Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>
> > > >
> > > > [1]
> > > https://lore.kernel.org/bpf/20221109142611.879983-1-eddyz87@gmail.com/
> > > > [2] https://lore.kernel.org/all/202211110355.BcGcbZxP-lkp@intel.com/
> > > > ---
> > > >  tools/lib/bpf/hashmap.h   | 3 ++-
> > > >  tools/perf/util/hashmap.h | 3 ++-
> > > >  2 files changed, 4 insertions(+), 2 deletions(-)
> > > >
> > > > diff --git a/tools/lib/bpf/hashmap.h b/tools/lib/bpf/hashmap.h
> > > > index 3fe647477bad..0a5bf1937a7c 100644
> > > > --- a/tools/lib/bpf/hashmap.h
> > > > +++ b/tools/lib/bpf/hashmap.h
> > > > @@ -123,7 +123,8 @@ enum hashmap_insert_strategy {
> > > >  };
> > > >
> > > >  #define hashmap_cast_ptr(p) ({								\
> > > > -	_Static_assert((p) == NULL || sizeof(*(p)) == sizeof(long),			\
> > > > +	_Static_assert((__builtin_constant_p((p)) ? (p) == NULL : 0) ||			 
> \
> > > > +				sizeof(*(p)) == sizeof(long),				\
> > > >  		       #p " pointee should be a long-sized integer or a  
> pointer");	\
> > > >  	(long *)(p);									\
> > > >  })
> > > > diff --git a/tools/perf/util/hashmap.h b/tools/perf/util/hashmap.h
> > > > index 3fe647477bad..0a5bf1937a7c 100644
> > > > --- a/tools/perf/util/hashmap.h
> > > > +++ b/tools/perf/util/hashmap.h
> > > > @@ -123,7 +123,8 @@ enum hashmap_insert_strategy {
> > > >  };
> > > >
> > > >  #define hashmap_cast_ptr(p) ({								\
> > > > -	_Static_assert((p) == NULL || sizeof(*(p)) == sizeof(long),			\
> > > > +	_Static_assert((__builtin_constant_p((p)) ? (p) == NULL : 0) ||			 
> \
> > > > +				sizeof(*(p)) == sizeof(long),				\
> > > >  		       #p " pointee should be a long-sized integer or a  
> pointer");	\
> > > >  	(long *)(p);									\
> > > >  })
> > > > --
> > > > 2.34.1
> > > >
Andrii Nakryiko Nov. 11, 2022, 6:30 p.m. UTC | #6
On Fri, Nov 11, 2022 at 9:19 AM <sdf@google.com> wrote:
>
> On 11/11, Eduard Zingerman wrote:
> > On Thu, 2022-11-10 at 17:34 -0800, sdf@google.com wrote:
> > > On 11/10, Stanislav Fomichev wrote:
> > > > On 11/11, Eduard Zingerman wrote:
> > > > > A fix for the LLVM compilation error while building bpftool.
> > > > > Replaces the expression:
> > > > >
> > > > >   _Static_assert((p) == NULL || ...)
> > > > >
> > > > > by expression:
> > > > >
> > > > >   _Static_assert((__builtin_constant_p((p)) ? (p) == NULL : 0) |
> > | ...)
> > >
> > > > IIUC, when __builtin_constant_p(p) returns false, we just ignore the
> > NULL
> > > > check?
> > > > Do we have cases like that? If no, maybe it's safer to fail?
> > >
> > > > s/(p) == NULL : 0/(p) == NULL : 1/ ?
> > >
> > > I'm probably missing something, can you pls clarify? So the error is as
> > > follows:
> > >
> > > > > btf_dump.c:1546:2: error: static_assert expression is not an
> > integral
> > > > > constant expression
> > >     hashmap__find(name_map, orig_name, &dup_cnt);
> > >     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> > >     ./hashmap.h:169:35: note: expanded from macro 'hashmap__find'
> > >     hashmap_find((map), (long)(key), hashmap_cast_ptr(value))
> > >     ^~~~~~~~~~~~~~~~~~~~~~~
> > >     ./hashmap.h:126:17: note: expanded from macro 'hashmap_cast_ptr'
> > >     _Static_assert((p) == NULL || sizeof(*(p)) ==
> > > sizeof(long),
> > > ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> > >     btf_dump.c:1546:2: note: cast from 'void *' is not allowed in a
> > constant
> > > expression
> > >     ./hashmap.h:169:35: note: expanded from macro 'hashmap__find'
> > >     hashmap_find((map), (long)(key), hashmap_cast_ptr(value))
> > >
> > > This line in particular:
> > >
> > >     btf_dump.c:1546:2: note: cast from 'void *' is not allowed in a
> > constant
> > > expression
> > >
> > > And the code does:
> > >
> > >    size_t dup_cnt = 0;
> > >    hashmap__find(name_map, orig_name, &dup_cnt);
> > >
> > > So where is that cast from 'void *' is happening? Is it the NULL check
> > > itself?
> > >
> > > Are we simply guarding against the user calling hashmap_cast_ptr with
> > > explicit NULL argument?
>
> > In case if (p) is not a constant I want the second part of the || to
> > kick-in.
> > The complete condition looks as follows:
>
> >    _Static_assert((__builtin_constant_p((p)) ? (p) == NULL : 0) || \
> >                       sizeof(*(p)) == sizeof(long), "...error...")
>
> > The intent is to check that (p) is either NULL or a pointer to
> > something of size long. So, if (p) is not a constant the expression
> > would be equivalent to:
>
> >    _Static_assert(0 || sizeof(*(p)) == sizeof(long), "...error...")
>
> > I just tried the following:
>
> >       struct hashmap *name_map;
> >       char x; // not a constant, wrong pointer size
> >       ...
> >       hashmap__find(name_map, orig_name, &x);
>
> > And it fails with an error message as intended:
>
> > btf_dump.c:1548:2: error: static_assert failed due to
> > requirement '(__builtin_constant_p((&x)) ? (&x) == ((void *)0) : 0) ||
> > sizeof (*(&x)) == sizeof(long)' "&x pointee should be a long-sized
> > integer or a pointer"
> >          hashmap__find(name_map, orig_name, &x);
> > ./hashmap.h:170:35: note: expanded from macro 'hashmap__find'
> >          hashmap_find((map), (long)(key), hashmap_cast_ptr(value))
> > ./hashmap.h:126:2: note: expanded from macro 'hashmap_cast_ptr'
> >          _Static_assert((__builtin_constant_p((p)) ? (p) == NULL : 0) ||
>
> Awesome, thanks for clarifying!
>
> Acked-by: Stanislav Fomichev <sdf@google.com>
>

Added

Fixes: c302378bc157 ("libbpf: Hashmap interface update to allow both
long and void* keys/values")

and moved links to be before Signed-off-by (they should be last).

Pushed to bpf-next, thanks.

> > >
> > > > > When "p" is not a constant the former is not considered to be a
> > > > > constant expression by LLVM 14.
> > > > >
> > > > > The error was introduced in the following patch-set: [1].
> > > > > The error was reported here: [2].
> > > > >
> > > > > Reported-by: kernel test robot <lkp@intel.com>
> > > > > Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>
> > > > >
> > > > > [1]
> > > > https://lore.kernel.org/bpf/20221109142611.879983-1-eddyz87@gmail.com/
> > > > > [2] https://lore.kernel.org/all/202211110355.BcGcbZxP-lkp@intel.com/
> > > > > ---
> > > > >  tools/lib/bpf/hashmap.h   | 3 ++-
> > > > >  tools/perf/util/hashmap.h | 3 ++-
> > > > >  2 files changed, 4 insertions(+), 2 deletions(-)
> > > > >
> > > > > diff --git a/tools/lib/bpf/hashmap.h b/tools/lib/bpf/hashmap.h
> > > > > index 3fe647477bad..0a5bf1937a7c 100644
> > > > > --- a/tools/lib/bpf/hashmap.h
> > > > > +++ b/tools/lib/bpf/hashmap.h
> > > > > @@ -123,7 +123,8 @@ enum hashmap_insert_strategy {
> > > > >  };
> > > > >
> > > > >  #define hashmap_cast_ptr(p) ({                                                         \
> > > > > -       _Static_assert((p) == NULL || sizeof(*(p)) == sizeof(long),                     \
> > > > > +       _Static_assert((__builtin_constant_p((p)) ? (p) == NULL : 0) ||
> > \
> > > > > +                               sizeof(*(p)) == sizeof(long),                           \
> > > > >                        #p " pointee should be a long-sized integer or a
> > pointer");    \
> > > > >         (long *)(p);                                                                    \
> > > > >  })
> > > > > diff --git a/tools/perf/util/hashmap.h b/tools/perf/util/hashmap.h
> > > > > index 3fe647477bad..0a5bf1937a7c 100644
> > > > > --- a/tools/perf/util/hashmap.h
> > > > > +++ b/tools/perf/util/hashmap.h
> > > > > @@ -123,7 +123,8 @@ enum hashmap_insert_strategy {
> > > > >  };
> > > > >
> > > > >  #define hashmap_cast_ptr(p) ({                                                         \
> > > > > -       _Static_assert((p) == NULL || sizeof(*(p)) == sizeof(long),                     \
> > > > > +       _Static_assert((__builtin_constant_p((p)) ? (p) == NULL : 0) ||
> > \
> > > > > +                               sizeof(*(p)) == sizeof(long),                           \
> > > > >                        #p " pointee should be a long-sized integer or a
> > pointer");    \
> > > > >         (long *)(p);                                                                    \
> > > > >  })
> > > > > --
> > > > > 2.34.1
> > > > >
>
patchwork-bot+netdevbpf@kernel.org Nov. 11, 2022, 6:40 p.m. UTC | #7
Hello:

This patch was applied to bpf/bpf-next.git (master)
by Andrii Nakryiko <andrii@kernel.org>:

On Fri, 11 Nov 2022 00:32:40 +0200 you wrote:
> A fix for the LLVM compilation error while building bpftool.
> Replaces the expression:
> 
>   _Static_assert((p) == NULL || ...)
> 
> by expression:
> 
> [...]

Here is the summary with links:
  - [bpf-next] libbpf: hashmap.h update to fix build issues using LLVM14
    https://git.kernel.org/bpf/bpf-next/c/42597aa372f5

You are awesome, thank you!
diff mbox series

Patch

diff --git a/tools/lib/bpf/hashmap.h b/tools/lib/bpf/hashmap.h
index 3fe647477bad..0a5bf1937a7c 100644
--- a/tools/lib/bpf/hashmap.h
+++ b/tools/lib/bpf/hashmap.h
@@ -123,7 +123,8 @@  enum hashmap_insert_strategy {
 };
 
 #define hashmap_cast_ptr(p) ({								\
-	_Static_assert((p) == NULL || sizeof(*(p)) == sizeof(long),			\
+	_Static_assert((__builtin_constant_p((p)) ? (p) == NULL : 0) ||			\
+				sizeof(*(p)) == sizeof(long),				\
 		       #p " pointee should be a long-sized integer or a pointer");	\
 	(long *)(p);									\
 })
diff --git a/tools/perf/util/hashmap.h b/tools/perf/util/hashmap.h
index 3fe647477bad..0a5bf1937a7c 100644
--- a/tools/perf/util/hashmap.h
+++ b/tools/perf/util/hashmap.h
@@ -123,7 +123,8 @@  enum hashmap_insert_strategy {
 };
 
 #define hashmap_cast_ptr(p) ({								\
-	_Static_assert((p) == NULL || sizeof(*(p)) == sizeof(long),			\
+	_Static_assert((__builtin_constant_p((p)) ? (p) == NULL : 0) ||			\
+				sizeof(*(p)) == sizeof(long),				\
 		       #p " pointee should be a long-sized integer or a pointer");	\
 	(long *)(p);									\
 })