On 8 July 2014 19:33, Zygmunt Ptak <zygmuntptak@xxxxxxxxx> 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.