Skip to content

Failed BUILD_BUG_ON in drivers/hwmon/macsmc-hwmon.c with clang-17 and older #2147

@nathanchance

Description

@nathanchance

When building drivers/hwmon/macsmc-hwmon.c (introduced in 6.19-rc1) with clang-17 and older, there is a BUILD_BUG_ON failure from a FIELD_PREP check.

drivers/hwmon/macsmc-hwmon.c:249:10: error: call to '__compiletime_assert_814' declared with 'error' attribute: FIELD_PREP: value too large for the field
  249 |                        FIELD_PREP(FLT_MANT_MASK, val);
      |                        ^
include/linux/bitfield.h:137:3: note: expanded from macro 'FIELD_PREP'
  137 |                 __FIELD_PREP(_mask, _val, "FIELD_PREP: ");              \
      |                 ^
include/linux/bitfield.h:90:3: note: expanded from macro '__FIELD_PREP'
   90 |                 __BF_FIELD_CHECK_MASK(mask, val, pfx);                  \
      |                 ^
include/linux/bitfield.h:69:3: note: expanded from macro '__BF_FIELD_CHECK_MASK'
   69 |                 BUILD_BUG_ON_MSG(__builtin_constant_p(_val) ?           \
      |                 ^
note: (skipping 2 expansions in backtrace; use -fmacro-backtrace-limit=0 to see all)
include/linux/compiler_types.h:618:2: note: expanded from macro '_compiletime_assert'
  618 |         __compiletime_assert(condition, msg, prefix, suffix)
      |         ^
include/linux/compiler_types.h:611:4: note: expanded from macro '__compiletime_assert'
  611 |                         prefix ## suffix();                             \
      |                         ^
<scratch space>:18:1: note: expanded from here
   18 | __compiletime_assert_814
      | ^

The full check is

                BUILD_BUG_ON_MSG(__builtin_constant_p(_val) ?           \
                                 ~((_mask) >> __bf_shf(_mask)) &        \
                                        (0 + (_val)) : 0,               \
                                 _pfx "value too large for the field"); \

in include/linux/bitfield.h.

llvm/llvm-project@e3cf80c is the "fix" in LLVM for this issue according to my bisect but I do not really understand how. Furthermore, this check should not even fire since I don't see how __builtin_constant_p(_val) could even be true for this code.

Hiding val from clang with

diff --git a/drivers/hwmon/macsmc-hwmon.c b/drivers/hwmon/macsmc-hwmon.c
index 1c0bbec7e8eb..1d88e46f202d 100644
--- a/drivers/hwmon/macsmc-hwmon.c
+++ b/drivers/hwmon/macsmc-hwmon.c
@@ -244,6 +244,7 @@ static int macsmc_hwmon_write_f32(struct apple_smc *smc, smc_key key, int value)
                        exp += msb;
                }

+               OPTIMIZER_HIDE_VAR(val);
                fval = FIELD_PREP(FLT_SIGN_MASK, neg) |
                       FIELD_PREP(FLT_EXP_MASK, exp + FLT_EXP_BIAS) |
                       FIELD_PREP(FLT_MANT_MASK, val);

avoids the issue.

Metadata

Metadata

Assignees

No one assigned

    Labels

    [BUG] UntriagedSomething isn't working[BUG] linuxA bug that should be fixed in the mainline kernel.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions