LINUX.ORG.RU

Получить воринг

 ,


0

2

Привет. Вопрос - мелочовка, но хотелось бы уметь. Условно у нас такой код:

int i = 1;
unsigned u = 2;
auto res = i - u + 1LL;

Можно заметить, что результат будет таким: res = long long(unsigned(i-u)+1). Возможно хотелось signed в первом действии, а каст не сделал т.к. не сильно задумывался при написании. Хочется получать предупреждение, когда в выражении более одного действия с участием знакового и беззнакового микса. Компилятор жалуется лишь на сравнение, прогнал через clang-tidy со всеми проверками - нулевой эффект. Кто-нибудь знает способ?

А в целом по вопросу - не очень понятно, почему integer promotion кастит лишь в int, особенно после появления в стандарте long long, по идее нужно кастовать в самый жирный тип. А в до цпп11 почему int, а не long, который может быть больше.

UPDATE:
Свои потребности закрыл вот этой поделкой https://github.com/sfpvk/Wsign-arithmetic

Когда пишешь такой код сразу указывай стандат.
auto до введения вывода типов это storage class, то есть как отсутствие static, extern в этом случае никакого promotion нету, а дефолтный тип когда тип не указан - int

mittorn ★★★★★ ()
% c++ --version
FreeBSD clang version 10.0.1 (git@github.com:llvm/llvm-project.git llvmorg-10.0.1-0-gef32c611aa2)
Target: x86_64-unknown-freebsd12.2
Thread model: posix
InstalledDir: /usr/bin
% c++ -Wsign-conversion 1.cc                                                        
1.cc:4:13: warning: implicit conversion changes signedness: 'int' to 'unsigned int' [-Wsign-conversion]
        auto res = i - u + 1LL;
                   ^ ~
1 warning generated.

?

slovazap ★★★★★ ()
Ответ на: комментарий от mittorn

ок. Не думал, что внесу какую-то неоднозначность с учетом присутствия в контексте цпп11. Лень было писать long long res, сократил.

pavlick ★★ ()
Ответ на: комментарий от pavlick

Конечно не совсем это то, кажется я понимаю почему -Wsign-conversion в -Wall не взяли, она слишком «глупая» и жалуется на любой каст знака. Нужны воринги на касты в сложных выражениях, где количество операндов более двух, там могут быть проблемы. А так запустил компилятор с данной опцией и получил два экран сообщений на всякое вроде vector[int_index]. Полезность проверки в таком виде весьма сомнительна …

Если кто-то знает более адекватное решение, то велком.

pavlick ★★ ()
Последнее исправление: pavlick (всего исправлений: 1)

Костыли это всё, подпорки под кривое. Integer promotion должен быть в long long. А сейчас получается, что любое математическое выражение с целыми типами > int - минное поле. Постоянно прыгать на декларации в либы ради посмотреть тип из get_num()? И вообще хз - изменится ли он в будущем.

Наверное попробую сделать небольшой awk скрипт для парсинга выхлопа -Wsign-conversion и если в выражении нет никаких математических операторов, а лишь какое-нибдуь =, то глушить этот воринг как ненужный.

pavlick ★★ ()
Ответ на: комментарий от pavlick

А сейчас получается, что любая программа на C++ - минное поле.

Не благодари!

anonymous ()
Ответ на: комментарий от pavlick

Я вообще такой код пишу не надеясь на всякие implicit conversion, integer promotion. Считаю что выражение имеет тип первого операнда (если он больше int). Если меньше то придется еще и кастануть.

 
	uint64_t(x) + y; // будет uint64_t
	uint16_t(x) + y; // будет int
	uint16_t(x + y); // так точно будет uint16_t


Итого всегда явно кастуй.

bga_ ★★★ ()
Последнее исправление: bga_ (всего исправлений: 1)
Ответ на: комментарий от bga_

-Wall -Wextra -pedantic

Не, это не помогает.

Я вообще такой код пишу не надеясь на всякие implicit conversion, integer promotion.

А зачем так замораичиваться? Нужно писать кода просто и вообще не думать что там что, а тем более - вдруг тип в некоторой либе изменится:

int res = x + b - c * d;

Можно в нужных местах руками кастовать, да, я для этого и хочу получить адекатные воринги. Но совсем не хочется делать преобразования постоянно и код будет выглядеть как какашка, читать неприятно.

Вообще до цпп20 всё это решить и возможности то не было, когда формат знаковых любой, а конверсия в знаковый с переполнением - implementation defined. Теперь можно, осталось лишь сказать, что promotion делается в long long или unsigned long long, и кодить спокойно без боли и мыслей о типе переменной.

pavlick ★★ ()
Ответ на: комментарий от pavlick

Ну кастовать в самый жирный тип - естественное желание. Только это не путь C++. C++ про производительность. Он не для того чтобы char складывать как __int128.

bga_ ★★★ ()
Ответ на: комментарий от bga_

Так и сейчас не будет как char, один фиг - минимум int. Да я и не думаю что там разница по скорости будет, если в регистр влезает целиком переменная. А если это какой-то МК, то никто не заставляет там делать long long == 2^100500, просто нет ничего больше, хоть один байт пусть будет размером.

pavlick ★★ ()
Ответ на: комментарий от pavlick

Так и сейчас не будет как char, один фиг - минимум int.

Если сложений несколько в каком-нибудь цикле то будет.

AVX и 16 char сложений вместо 4 int сложений…

fsb4000 ★★★★★ ()

Если кому интересно - ГЦЦ умеет прикольную штуку - выводить все воринги/ошибки в JSON через опцию -fdiagnostics-format=json (шланг не умеет). В общем можно stderr перенаправить в файл и получить удобную заготовку для парсинга. Да, может и не часто надо, но вот как раз пригодилось, накостылил небольшой анализатор для анализа и отсеивания предупреждений.

pavlick ★★ ()
Ограничение на отправку комментариев: только для зарегистрированных пользователей