This is the mail archive of the gcc-help@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: c++11 and packed structures, bitwise operation with -Wconversion


On 8 July 2014 19:33, Zygmunt Ptak <zygmuntptak@gmail.com> wrote:
> 2) What is going on third line exactly (for x86_64/i686/avr machine):
>
> /*0:*/ typedef uint8_t u8;
> /*1:*/ static u8 MAIN_DDR;
> /*2:*/ constexpr u8 BV(u8 v) { return static_cast<u8>(1 << v); }
> /*3:*/ inline void setPinAsOut(u8 PIN) { MAIN_DDR |= BV(PIN); }
>
> I want use -Wconversion option, but this option raises warning
> for third line:
>
> warning: conversion to 'u8 {aka unsigned char}' from 'int' may alter its
> value [-Wconversion]
>  inline void setPinAsOut(u8 PIN) { MAIN_DDR |= BV(PIN); }
>
> But types operates on 8 bits, so why compiler uses here bigger type? Or
> maybe it's a bug?

The result of "|" is really converted to int because of promotions,
but -Wconversion has some heuristics to not warn when the conversion
back to a smaller type does not actually alter the value. It seems the
heuristics are not triggering here because of some artifact of how the
C++ FE handles "&=" and "|=". For the equivalent C testcase:

typedef unsigned char u8;
static u8 MAIN_DDR;
u8 BV(u8 v) { return (u8) (1 << v); }
void setPinAsOut(u8 PIN)
{
  MAIN_DDR |= BV(PIN);
  MAIN_DDR = MAIN_DDR | BV(PIN);
  MAIN_DDR &= BV(PIN);
  MAIN_DDR = MAIN_DDR & BV(PIN);
}

gcc -Wconversion does not give any warnings, whereas g++ -Wconversion says:

test.c:6:12: warning: conversion to 'u8 {aka unsigned char}' from
'int' may alter its value [-Wconversion]
   MAIN_DDR |= BV(PIN);
            ^
test.c:8:12: warning: conversion to 'u8 {aka unsigned char}' from
'int' may alter its value [-Wconversion]
   MAIN_DDR &= BV(PIN);
            ^

> This line can be resolved by:
> MAIN_DDR = MAIN_DDR | BV(PIN);
> or by adding static_cast, but IMO it's not good;-/
> The same to & operator, but changing line to:
> MAIN_DDR = MAIN_DDR & BV(PIN);
> doesn't resolve problem.

I does for me with current development version of GCC as shown above.

Anyway, this is either a bug in the C++ FE or a possible enhancement
of the Wconversion heuristics. Please open a bug report:
https://gcc.gnu.org/bugs/

Cheers,

Manuel.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]