Я только что обнаружил, что в трекере ошибок GCC есть несколько ошибок, связанных с -Wconversion
.В частности: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=39170
В частности, комментарий #18
(https://gcc.gnu.org/bugzilla/show_bug.cgi?id=39170#c18) приводит пример, почти идентичный моему:
#include <stdint.h>
struct foo
{
unsigned bar: 30;
unsigned fill: 2;
};
struct foo test(uint32_t value)
{
struct foo foo;
foo.bar = (value >> 2) & 0x3fffffffU;
return foo;
}
Поэтому я считаю, что эта проблемаокончательно gcc bug .
Персональный обходной путь
Учитывая ошибку компилятора, мой персональный обходной путь состоял в том, чтобы просто обернуть операцию сдвига вправо в функции static
always_inline
даже если я не особенно доволен этим взломом.
#include <stdint.h>
static __attribute__((always_inline)) inline uintptr_t
rshift(uintptr_t val, uintptr_t bits)
{
return val >> bits;
}
int main() {
struct { unsigned int a:20; } s;
unsigned int val = 0xaabbc000;
s.a = val & 0xfffff; // 1) works
s.a = (rshift(val, 12)) & 0xfffff; // 2) works
}
Обходной путь, предложенный PSkocik
s.a = (unsigned){(val >> 12)} & 0xfffff; // works
Который сейчас мой любимый.