This is the mail archive of the
gcc-help@gcc.gnu.org
mailing list for the GCC project.
Re: c++11 and packed structures, bitwise operation with -Wconversion
- From: Manuel López-Ibáñez <lopezibanez at gmail dot com>
- To: Zygmunt Ptak <zygmuntptak at gmail dot com>
- Cc: "gcc-help at gcc dot gnu dot org" <gcc-help at gcc dot gnu dot org>
- Date: Wed, 9 Jul 2014 00:54:59 +0200
- Subject: Re: c++11 and packed structures, bitwise operation with -Wconversion
- Authentication-results: sourceware.org; auth=none
- References: <53BC2B5D dot 1030400 at gmail dot com>
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.