[PATCH] D134461: [Clang] Warn when trying to deferencing void pointers in C

Nathan Chancellor via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Mon Sep 26 08:27:58 PDT 2022


nathanchance added subscribers: nickdesaulniers, nathanchance.
nathanchance added a comment.

This warning is quite noisy for the Linux kernel due to a couple of places where a `void *` is dereferenced as part of compile time checking. My original commentary is available on our GitHub issue tracker (https://github.com/ClangBuiltLinux/linux/issues/1720) but I will summarize it here:

The first major instance of this warning comes from the `__is_constexpr` macro, which is used a lot in common macros do fancy things at compile time (change that added this: https://git.kernel.org/linus/3c8ba0d61d04ced9f8d9ff93977995a9e4e96e91):

  /*
   * This returns a constant expression while determining if an argument is
   * a constant expression, most importantly without evaluating the argument.
   * Glory to Martin Uecker <Martin.Uecker at med.uni-goettingen.de>
   */
  #define __is_constexpr(x) \
  	(sizeof(int) == sizeof(*(8 ? ((void *)((long)(x) * 0l)) : (int *)8)))

Sample warnings:

  In file included from scripts/mod/devicetable-offsets.c:3:
  In file included from ./include/linux/mod_devicetable.h:13:
  In file included from ./include/linux/uuid.h:12:
  In file included from ./include/linux/string.h:253:
  ./include/linux/fortify-string.h:159:10: warning: ISO C does not allow indirection on operand of type 'void *' [-Wvoid-ptr-dereference]
          q_len = strlen(q);
                  ^~~~~~~~~
  ./include/linux/fortify-string.h:131:24: note: expanded from macro 'strlen'
          __builtin_choose_expr(__is_constexpr(__builtin_strlen(p)),      \
                                ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  ./include/linux/const.h:12:25: note: expanded from macro '__is_constexpr'
          (sizeof(int) == sizeof(*(8 ? ((void *)((long)(x) * 0l)) : (int *)8)))
                                 ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  
  In file included from arch/x86/kernel/asm-offsets.c:9:
  In file included from ./include/linux/crypto.h:20:
  In file included from ./include/linux/slab.h:15:
  In file included from ./include/linux/gfp.h:7:
  In file included from ./include/linux/mmzone.h:8:
  In file included from ./include/linux/spinlock.h:55:
  In file included from ./include/linux/preempt.h:78:
  In file included from ./arch/x86/include/asm/preempt.h:7:
  In file included from ./include/linux/thread_info.h:60:
  In file included from ./arch/x86/include/asm/thread_info.h:53:
  In file included from ./arch/x86/include/asm/cpufeature.h:5:
  In file included from ./arch/x86/include/asm/processor.h:22:
  In file included from ./arch/x86/include/asm/msr.h:11:
  In file included from ./arch/x86/include/asm/cpumask.h:5:
  In file included from ./include/linux/cpumask.h:12:
  In file included from ./include/linux/bitmap.h:9:
  ./include/linux/find.h:40:17: warning: ISO C does not allow indirection on operand of type 'void *' [-Wvoid-ptr-dereference]
                  val = *addr & GENMASK(size - 1, offset);
                                ^~~~~~~~~~~~~~~~~~~~~~~~~
  ./include/linux/bits.h:38:3: note: expanded from macro 'GENMASK'
          (GENMASK_INPUT_CHECK(h, l) + __GENMASK(h, l))
           ^~~~~~~~~~~~~~~~~~~~~~~~~
  ./include/linux/bits.h:25:3: note: expanded from macro 'GENMASK_INPUT_CHECK'
                  __is_constexpr((l) > (h)), (l) > (h), 0)))
                  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  ./include/linux/const.h:12:25: note: expanded from macro '__is_constexpr'
          (sizeof(int) == sizeof(*(8 ? ((void *)((long)(x) * 0l)) : (int *)8)))
                                 ^
  ./include/linux/build_bug.h:16:62: note: expanded from macro 'BUILD_BUG_ON_ZERO'
  #define BUILD_BUG_ON_ZERO(e) ((int)(sizeof(struct { int:(-!!(e)); })))
                                                               ^

The second major instance is the type checking in `container_of` when ptr is a `void *` (change that added this: https://git.kernel.org/linus/c7acec713d14c6ce8a20154f9dfda258d6bcad3b):

  /**
   * container_of - cast a member of a structure out to the containing structure
   * @ptr:	the pointer to the member.
   * @type:	the type of the container struct this is embedded in.
   * @member:	the name of the member within the struct.
   *
   */
  #define container_of(ptr, type, member) ({				\
  	void *__mptr = (void *)(ptr);					\
  	static_assert(__same_type(*(ptr), ((type *)0)->member) ||	\
  		      __same_type(*(ptr), void),			\
  		      "pointer type mismatch in container_of()");	\
  	((type *)(__mptr - offsetof(type, member))); })

  #define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b))

Sample warning:

  In file included from sound/soc/sof/core.c:14:
  In file included from ./include/sound/sof.h:14:
  ./include/linux/pci.h:600:9: warning: ISO C does not allow indirection on operand of type 'void *' [-Wvoid-ptr-dereference]
          return container_of(priv, struct pci_host_bridge, private);
                 ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  ./include/linux/container_of.h:20:21: note: expanded from macro 'container_of'
                        __same_type(*(ptr), void),                        \
                        ~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  ./include/linux/compiler_types.h:295:63: note: expanded from macro '__same_type'
  #define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b))
                                                                ^
  ./include/linux/build_bug.h:77:50: note: expanded from macro 'static_assert'
  #define static_assert(expr, ...) __static_assert(expr, ##__VA_ARGS__, #expr)
                                   ~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~
  ./include/linux/build_bug.h:78:56: note: expanded from macro '__static_assert'
  #define __static_assert(expr, msg, ...) _Static_assert(expr, msg)
                                                         ^~~~

I am aware these are quite specialized cases so warning is likely appropriate. If so, we can just disable this warning for the kernel but I figured it was worth a comment in case the diagnostic can be improved in any way.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D134461/new/

https://reviews.llvm.org/D134461



More information about the cfe-commits mailing list