Подтвердить что ты не робот

Как включить предупреждения С++ для побитовых операторов с булевыми аргументами

При работе с довольно большой базой кода С++ и инструментальной связью GCC в Linux я столкнулся с кодом, который выполняет логическую проверку следующим образом:

#include <stdio.h>

int main() {
   bool foo = true;

   if (~foo) {
     // do some expensive operation
     printf("This can be bad...\n");
   }
   return 0;
}

Это выглядит как очевидная ошибка, поскольку оператор ~ представляет бит-мудрый NOT на С++, а не логический NOT, как это было бы, скажем, в MATLAB. Вышеприведенный код всегда будет иметь значение true

К счастью, проблема, вызванная этой ошибкой, не была значительной (это был всего лишь небольшой удар по производительности), но мне стало интересно, как эта ошибка не была обнаружена за такое время.

Поскольку бит-мудрый оператор запускает неявное преобразование из булева в целое, что является продвижением по службе, в нем нет ничего плохого. Тем не менее, мне кажется, что хотя бы что-то вроде clang-tidy должно быть в состоянии выбрать это как логическую ошибку, так как довольно ясно, что в большинстве случаев цель заключается не в применении побитовой операции к bool, но вместо этого логический.

g++, похоже, не заботится об этой проблеме даже при включенном -Wall -Wextra -Wconversion, что разумно, учитывая, что, как я упоминал ранее, это не соответствует стандарту. (Я даже пробовал g++ 6.3, который должен иметь много новых проверок и все равно ничего не получил

Использование clang-tidy со всеми включенными проверками (которые действительно могут быть очень шумными) предупреждает о неявном преобразовании ( "implicit cast bool → " int "), но, похоже, не существует конкретной предупреждение, связанное с применением битовых операторов к булевым файлам.

Написание if-утверждения по-разному как if(~foo == true), в то время как подробный и приводящий к всегда-ложному сценарию, приводит к более значимым ошибкам, которые могут привнести внимание к проблеме, но этого не происходит, когда terser if(~foo).

Существуют ли какие-либо способы/инструменты для проверки таких проблем, которые на 100% правильны для С++, но очень вероятные ошибки?

4b9b3361

Ответ 1

В gcc имеется -Wbool-operation в gcc 7:

Предупреждать о подозрительных операциях над выражениями типа boolean. Например, побитовое отрицание булева, вероятно, является ошибкой в ​​программе. Для C это предупреждение также предупреждает об увеличении или уменьшении булева, что редко имеет смысл. (В С++ декремент boolean всегда недействителен. Приращение логического значения недействительно в С++ 1z и устарело иначе.)

Это предупреждение включено -Wall.

Он предоставляет следующее предупреждение для вашей программы:

prog.cc:6:9: warning: '~' on an expression of type bool [-Wbool-operation]
    if (~foo) {
         ^~~
prog.cc:6:9: note: did you mean to use logical not ('!')?

демонстрация gcc

К сожалению, не похоже, что у clang 5 такая опция. Даже включив (почти все) все возможные предупреждения, перечисленные здесь, мы все еще не получаем ожидаемого предупреждения (Demo) (хотя мы получаем несколько интересных других).

Наконец, для полноты MSVC 19.00.23506 определенно предупреждает (Demo) (кредит @cbuchart для указания этого):

source_file.cpp(8): warning C4804: '~': unsafe use of type 'bool' in operation