gcc 5.2 странная ошибка
От: enji  
Дата: 09.11.15 06:36
Оценка: 34 (1)
Собрал тут gcc5.2 arm-none-eabi, начал падать на следующем коде

#define r_char_bits CHAR_BIT
#define r_digits(_Tp, S) (sizeof(_Tp) * r_char_bits - S)

#define r_min_0(_Tp) ((_Tp)0)
#define r_min_1(_Tp) ((_Tp)(-(1LL << (r_digits(_Tp, 1)-1))*2))
#define r_min(_Tp, S) r_min_##S(_Tp)

static const signed char min2 = r_min(signed char, 1); // это компиляется

struct Test {
  static const signed char min2 = r_min(signed char, 1); // а это - нет
};


error: left operand of shift expression '(-2ll << 6u)' is negative
#define r_min_1(_Tp) ((_Tp)(-(1LL << (r_digits(_Tp, 1)-1))*2))

Сыроват еще 5.2? Или я как-то криво собрал? Или тут реально какая-то ошибка в коде?

Кто-нить может проверить у себя на 5.2?

09.11.15 14:17: баги компиляторов — это не "прикладные" вопросы, а коренные. — Кодт
Re: gcc 5.2 странная ошибка
От: Zhendos  
Дата: 09.11.15 07:00
Оценка:
Здравствуйте, enji, Вы писали:

E>Собрал тут gcc5.2 arm-none-eabi, начал падать на следующем коде

E>

E>#define r_char_bits CHAR_BIT
E>#define r_digits(_Tp, S) (sizeof(_Tp) * r_char_bits - S)

E>#define r_min_0(_Tp) ((_Tp)0)
E>#define r_min_1(_Tp) ((_Tp)(-(1LL << (r_digits(_Tp, 1)-1))*2))
E>#define r_min(_Tp, S) r_min_##S(_Tp)

E>static const signed char min2 = r_min(signed char, 1); // это компиляется

E>struct Test {
E>  static const signed char min2 = r_min(signed char, 1); // а это - нет
E>};

E>


E>error: left operand of shift expression '(-2ll << 6u)' is negative

E> #define r_min_1(_Tp) ((_Tp)(-(1LL << (r_digits(_Tp, 1)-1))*2))

E>Сыроват еще 5.2? Или я как-то криво собрал? Или тут реально какая-то ошибка в коде?


E>Кто-нить может проверить у себя на 5.2?


$ g++ --version
g++ (Gentoo 5.2.0 p1.1, pie-0.6.4) 5.2.0

Собрал без ошибок.

У вас там действительно ошибка, сдвиг целого со знаком числа,
определен только если оно больше или равно нулю, т.е. у вас UB в чистом виде,
возможно у вас включен режим предупреждения==ошибки, поэтому и возникает ошибка компиляции?
Re[2]: gcc 5.2 странная ошибка
От: enji  
Дата: 09.11.15 07:02
Оценка:
Здравствуйте, Zhendos, Вы писали:

Z>

Z>$ g++ --version
Z>g++ (Gentoo 5.2.0 p1.1, pie-0.6.4) 5.2.0

Z>Собрал без ошибок.

Z>У вас там действительно ошибка, сдвиг целого со знаком числа,

Z>определен только если оно больше или равно нулю, т.е. у вас UB в чистом виде,
Z>возможно у вас включен режим предупреждения==ошибки, поэтому и возникает ошибка компиляции?

А где тут целое со знаком? -(1 << 6) * 2 вообще то говоря...
Re[3]: gcc 5.2 странная ошибка
От: Zhendos  
Дата: 09.11.15 07:16
Оценка:
Здравствуйте, enji, Вы писали:

E>Здравствуйте, Zhendos, Вы писали:


Z>>

Z>>$ g++ --version
Z>>g++ (Gentoo 5.2.0 p1.1, pie-0.6.4) 5.2.0

Z>>Собрал без ошибок.

Z>>У вас там действительно ошибка, сдвиг целого со знаком числа,

Z>>определен только если оно больше или равно нулю, т.е. у вас UB в чистом виде,
Z>>возможно у вас включен режим предупреждения==ошибки, поэтому и возникает ошибка компиляции?

E>А где тут целое со знаком? -(1 << 6) * 2 вообще то говоря...


В первоначальном сообщении '(-2ll << 6u)', а вот как он это получил фиг знает,
здесь надо смотреть опции компилятора.
Re[4]: gcc 5.2 странная ошибка
От: enji  
Дата: 09.11.15 07:18
Оценка:
Здравствуйте, Zhendos, Вы писали:

E>>А где тут целое со знаком? -(1 << 6) * 2 вообще то говоря...


Z>В первоначальном сообщении '(-2ll << 6u)', а вот как он это получил фиг знает,

Z>здесь надо смотреть опции компилятора.

угу, он в это раскрыл. А вот почему — неясно. Причем если убрать struct, то раскроет нормально
Re: gcc 5.2 странная ошибка
От: watchmaker  
Дата: 09.11.15 08:10
Оценка: 4 (1)
Здравствуйте, enji, Вы писали:


E> #define r_min_1(_Tp) ((_Tp)(-(1LL << (r_digits(_Tp, 1)-1))*2))

Раскрыл бы сразу макросы сам. Зачем всех заставлять через них продираться? Не в макросах же проблема. И заменить выражение на что-нибудь попроще, собрав минимальный пример, навроде такого:
struct Test {
  static const int foo = (1 << sizeof(int))*(-3);
};


E>Сыроват еще 5.2?

Да, похоже на баг.
Причём проблема исчезает если не использовать inline инициализацию, либо если убрать sizeof, либо если использовать старый стандарт. Про последнее как раз понятно, что в C++11 поменялись правила левого сдвига знаковых чисел и там стоит повнимательней на код посмотреть.
Ну либо, обойти проблему, использовав в коде беззнаковый тип для левого операнда — это работает везде одинаково.
Отредактировано 09.11.2015 8:13 watchmaker . Предыдущая версия .
Re[2]: gcc 5.2 странная ошибка
От: enji  
Дата: 09.11.15 08:38
Оценка:
Здравствуйте, watchmaker, Вы писали:

W>Раскрыл бы сразу макросы сам.


Я раскрыл до до -(1ll << 6) * 2 — не падал. Не дошло, что дело в sizeof.

Причем неясно, каким боком тут struct, если просто сделать глобальный static const — все ок.

W>Ну либо, обойти проблему, использовав в коде беззнаковый тип для левого операнда — это работает везде одинаково.


да, заменил на 1ULL — завелось. Спасибо!

Но похоже стоит пока остаться на 4.х ветке, счас попробую собрать 4.9.3
Отредактировано 09.11.2015 8:40 enji . Предыдущая версия .
Re[2]: gcc 5.2 странная ошибка
От: Zhendos  
Дата: 09.11.15 09:26
Оценка:
Здравствуйте, watchmaker, Вы писали:

W>Здравствуйте, enji, Вы писали:



E>> #define r_min_1(_Tp) ((_Tp)(-(1LL << (r_digits(_Tp, 1)-1))*2))

W>Раскрыл бы сразу макросы сам. Зачем всех заставлять через них продираться? Не в макросах же проблема. И заменить выражение на что-нибудь попроще, собрав минимальный пример, навроде такого:
struct Test {
W>  static const int foo = (1 << sizeof(int))*(-3);
W>};


E>>Сыроват еще 5.2?

W>Да, похоже на баг.

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=68252
Re: gcc 5.2 странная ошибка
От: Шахтер Интернет  
Дата: 09.11.15 14:39
Оценка:
Здравствуйте, enji, Вы писали:

E>error: left operand of shift expression '(-2ll << 6u)' is negative

E> #define r_min_1(_Tp) ((_Tp)(-(1LL << (r_digits(_Tp, 1)-1))*2))

Это фича: нельзя в константных выражениях сдвигать знаковые отрицательные значения.
Если я не ошибаюсь, это полностью соответствует последней версии стандарта.
В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.