Флаги для включения подробных и подробных предупреждений g ++

122

Часто, работая с C ниже gcc, я начинаю со следующего набора предупреждающих флагов (с трудом собранных из нескольких источников):

-Wall -Wextra -Wformat-nonliteral -Wcast-align -Wpointer-arith -Wbad-function-cast \
-Wmissing-prototypes -Wstrict-prototypes -Wmissing-declarations -Winline -Wundef \
-Wnested-externs -Wcast-qual -Wshadow -Wwrite-strings -Wno-unused-parameter \
-Wfloat-equal -pedantic -ansi

Я буду собирать (по крайней мере, мои отладочные версии) с этим набором предупреждений и исправлять все, что я могу (обычно все), а затем снимать флаги только в том случае, если они либо не актуальны, либо не исправимы (почти никогда). Иногда я также добавляю, -Werrorесли мне нужно отойти во время компиляции.

Я только начинаю изучать C ++ (да, я на 15 лет отстал от времени), и мне бы хотелось начать с правильного пути.

Мой вопрос: есть ли у кого-нибудь предварительно скомпилированный аналогичный набор полных предупреждений для C ++ g++? (Я знаю, что многие из них будут такими же.)

Sdaz Mac
источник
69
Какие потребности GCC (так как он решил нагло ложь о -Wall) является -Wbloody_everythingфлаг :-)
paxdiablo
Вы можете пометить свой вопрос как ложный, но вы также можете указать последнее изменение в качестве ответа, поскольку вы действительно ответили на свой вопрос. И я был бы рад тогда проголосовать за него :)
ereOn
4
OP и @paxdiablo: GCC постоянно отвергает подобные вещи, но они доступны в Clang через -Weverything. Я читал, что даже разработчики Clang ++ немного обеспокоены тем, что пользователи его включают; очевидно, он был предназначен только для внутреннего использования. Однако это не имеет смысла, потому что включение, -Weverythingвероятно, лучший способ обнаружить потенциально полезные предупреждения, о которых вы раньше не знали.
Кайл Стрэнд
1
OP и @paxdiablo Теперь есть способ выяснить полный список предупреждений для данной версии GCC: github.com/barro/compiler-warnings
Кайл Стрэнд,
1
Возможный дубликат Как включить (буквально) ВСЕ предупреждения GCC?
Чиро Сантилли 郝海东 冠状 病 六四 事件 法轮功

Ответы:

138

Я просмотрел и нашел минимальный набор включений, который должен получать максимальный уровень предупреждений. Затем я удалил из этого списка набор предупреждений, которые, как мне кажется, на самом деле не указывают на то, что происходит что-то плохое, или имеют слишком много ложных срабатываний для использования в реальной сборке. Я прокомментировал, почему все исключенные мной были исключены. Это мой последний набор рекомендуемых предупреждений:

-pedantic -Wall -Wextra -Wcast-align -Wcast-qual -Wctor-dtor-privacy -Wdisabled-optimization -Wformat=2 -Winit-self -Wlogical-op -Wmissing-declarations -Wmissing-include-dirs -Wnoexcept -Wold-style-cast -Woverloaded-virtual -Wredundant-decls -Wshadow -Wsign-conversion -Wsign-promo -Wstrict-null-sentinel -Wstrict-overflow=5 -Wswitch-default -Wundef -Werror -Wno-unused

Имеются сомнительные предупреждения:

  • Я включаю, -Wno-unusedпотому что у меня часто есть переменные, которые я знаю, что буду использовать позже, но для которых еще нет написанных функций. Удаление предупреждений об этом позволяет мне писать в своем предпочтительном стиле, иногда откладывая реализацию вещей. Полезно выключать это время от времени, чтобы убедиться, что ничего не проскочило через щели.

  • -Wdisabled-optimizationпохоже на сильную настройку предпочтений пользователя. Я только что добавил это в свою сборку (только для оптимизированных сборок по понятным причинам), и ничего не получилось, так что это не кажется особо разговорчивым предупреждением, по крайней мере, для того, как я кодирую. Я включаю его (хотя код, который вызывает это предупреждение, не обязательно ошибочен), потому что я верю, что могу работать с моими инструментами, а не против них. Если gcc сообщает мне, что он не может оптимизировать код в соответствии с тем, как я его написал, то мне следует подумать о его переписывании. Я подозреваю, что код, который запускает это предупреждение, в любом случае может выиграть от большей модульности, поэтому, хотя код не является технически неправильным (вероятно), стилистически скорее всего так.

  • -Wfloat-equalпредупреждает о безопасном сравнении равенства (в частности, сравнение с невычисленным значением -1). Пример в моем коде, где я использую это, заключается в том, что у меня есть вектор с плавающей запятой. Я просматриваю этот вектор, и есть некоторые элементы, которые я пока не могу оценить, какими они должны быть, поэтому я установил для них -1.0f (поскольку моя проблема использует только положительные числа, -1 находится вне области). Позже я просматриваю и обновляю значения -1.0f. Его нелегко применить к другому методу работы. Я подозреваю, что у большинства людей этой проблемы нет, и сравнение точного числа с плавающей запятой, вероятно, является ошибкой, поэтому я включаю его в список по умолчанию.

  • -Wold-style-castимеет много ложных срабатываний в коде библиотеки, который я использую. В частности, семейство функций htonl, используемых в сети, а также реализация шифрования Rijndael (AES), которую я использую, имеют приведения в старом стиле, о которых меня предупреждают. Я намерен заменить оба из них, но я не уверен, есть ли в моем коде что-то еще, на что он будет жаловаться. Однако большинству пользователей, вероятно, следует включить его по умолчанию.

  • -Wsign-conversionбыл трудным (и почти не попал в список). Включение его в моем коде генерировало огромное количество предупреждений (более 100). Почти все они были невиновны. Тем не менее, я старался использовать целые числа со знаком там, где я не был уверен, хотя для моей конкретной проблемной области я обычно получал небольшое повышение эффективности с использованием значений без знака из-за большого количества целочисленных делений, которые я делаю. Я пожертвовал этой эффективностью, потому что был обеспокоен случайным преобразованием целого числа со знаком в беззнаковое с последующим делением (что небезопасно, в отличие от сложения, вычитания и умножения). Включение этого предупреждения позволило мне безопасно изменить большинство моих переменных на беззнаковые типы и добавить несколько приведений в некоторых других местах. В настоящее время это немного сложно использовать, потому что предупреждение не так умно. Например, если вы сделаетеunsigned short + (integral constant expression), этот результат неявно повышается до int. Затем он предупреждает о потенциальной проблеме со знаком, если вы присвоите это значение unsignedили unsigned short, даже если это безопасно. Это определенно самое необязательное предупреждение почти для всех пользователей.

  • -Wsign-promo: см -Wsign-conversion.

  • -Wswitch-defaultкажется бессмысленным (вам не всегда нужен вариант по умолчанию, если вы явно перечислили все возможности). Однако включение этого предупреждения может привести к тому, что это, вероятно, хорошая идея. В случаях, когда вы явно хотите игнорировать все, кроме перечисленных возможностей (но возможны другие числа), введитеdefault: break;чтобы сделать это явным. Если вы явно перечисляете все возможности, то включение этого предупреждения поможет убедиться, что вы указали что-то вроде assert (false), чтобы убедиться, что вы действительно охватили все возможные варианты. Это позволяет вам четко указать, в чем состоит ваша проблема, и программно обеспечивает это. Однако вам нужно быть осторожным, просто вставляя везде assert (false). Это лучше, чем ничего не делать со случаем по умолчанию, но, как обычно с assert, он не будет работать в сборках выпуска. Другими словами, вы не можете полагаться на него для проверки чисел, которые вы получаете, скажем, от сетевого подключения или базы данных, над которой у вас нет абсолютного контроля. Исключения или досрочное возвращение - лучший способ справиться с этим (но все же требуется, чтобы у вас был случай по умолчанию!).

  • -Werrorдля меня важен. При компиляции большого количества кода в многопоточной сборке с несколькими целями предупреждение легко пропустить. Превращение предупреждений в ошибки гарантирует, что я их замечу.

Затем есть набор предупреждений, которые не включены в приведенный выше список, потому что я не нашел их полезными. Это предупреждения и мои комментарии о том, почему я не включаю их в список по умолчанию:

Предупреждения, которые отсутствуют:

  • -Wabiне нужен, потому что я не комбинирую двоичные файлы из разных компиляторов. Я все равно пытался скомпилировать с ним, но он не сработал, поэтому он не кажется излишне многословным.

  • -Waggregate-returnэто не то, что я считаю ошибкой. Например, он срабатывает при использовании цикла for на основе диапазона для вектора классов. Оптимизация возвращаемого значения должна позаботиться о любых негативных последствиях этого.

  • -Wconversionтриггеры для этого кода: short n = 0; n += 2;неявное преобразование в int вызывает предупреждение, когда оно затем преобразуется обратно в свой целевой тип.

  • -Weffc++включает предупреждение, если все элементы данных не инициализированы в списке инициализаторов. Во многих случаях я намеренно не делаю этого, поэтому набор предупреждений слишком загроможден, чтобы быть полезным. Тем не менее, полезно время от времени включать и сканировать другие предупреждения (например, не виртуальные деструкторы базовых классов). Это было бы более полезно в качестве набора предупреждений (например, -Wall), а не отдельного предупреждения.

  • -Winlineотсутствует, потому что я не использую ключевое слово inline в целях оптимизации, просто для определения функций, встроенных в заголовки. Меня не волнует, действительно ли оптимизатор встраивает его. Это предупреждение также указывает на то, что не может встроить функцию, объявленную в теле класса (например, пустой виртуальный деструктор).

  • -Winvalid-pch отсутствует, потому что я не использую предварительно скомпилированные заголовки.

  • -Wmissing-format-attributeне используется, потому что я не использую расширения GNU. То же самое для -Wsuggest-attributeи некоторых других

  • Потенциально примечателен своим отсутствием -Wno-long-long, в котором я не нуждаюсь. Я компилирую -std=c++0x( -std=c++11в GCC 4.7), который включает long longцелочисленные типы. Те, кто застрял на C ++ 98 / C ++ 03, могут подумать о добавлении этого исключения из списка предупреждений.

  • -Wnormalized=nfc уже является вариантом по умолчанию и выглядит лучшим.

  • -Wpaddedвремя от времени включается для оптимизации компоновки классов, но не остается включенным, потому что не все классы имеют достаточно элементов для удаления отступов в конце. Теоретически я мог бы получить несколько дополнительных переменных «бесплатно», но это не стоит дополнительных усилий по их поддержанию (если размер моего класса изменится, будет нелегко удалить эти ранее свободные переменные).

  • -Wstack-protector не используется, потому что я не использую -fstack-protector

  • -Wstrict-aliasing=3включен -Wallи является наиболее точным, но похоже, что уровни 1 и 2 дают больше предупреждений. Теоретически более низкий уровень является «более сильным» предупреждением, но это происходит за счет большего количества ложных срабатываний. Мой собственный тестовый код аккуратно скомпилирован на всех трех уровнях.

  • -Wswitch-enumповедение не то, что я хочу. Я не хочу явно обрабатывать каждый оператор switch. Было бы полезно, если бы в языке был какой-то механизм для активации этого в определенных операторах switch (чтобы гарантировать, что будущие изменения в перечислении обрабатываются везде, где они должны быть), но это излишне для параметра «все или ничего».

  • -Wunsafe-loop-optimizationsвызывает слишком много ложных предупреждений. Может быть полезно применять его периодически и вручную проверять результаты. Например, это предупреждение было сгенерировано в моем коде, когда я перебирал все элементы вектора, чтобы применить к ним набор функций (используя цикл for на основе диапазона). Это также предупреждение для конструктора константного массива const std :: string (где это не цикл в пользовательском коде).

  • -Wzero-as-null-pointer-constantи -Wuseless-castявляются предупреждениями только для GCC-4.7, которые я добавлю при переходе на GCC 4.7.

Я подал несколько отчетов об ошибках / запросов на улучшение в gcc в результате некоторых из этих исследований, поэтому, надеюсь, я смогу в конечном итоге добавить больше предупреждений из списка «не включать» в список «включить» , Этот список включает все предупреждения, упомянутые в этой теме (плюс, я думаю, несколько дополнительных). Многие из предупреждений, явно не упомянутых в этом сообщении, включены как часть другого предупреждения, о котором я упоминаю. Если кто-нибудь заметит какие-либо предупреждения, которые полностью исключены из этого сообщения, дайте мне знать.

edit: Похоже, я пропустил несколько (которые я теперь добавил). На самом деле есть вторая страница http://gcc.gnu.org, которая довольно хорошо скрыта. Общие параметры предупреждения и опция C ++ (прокрутите вниз до нижней части для предупреждения)

Дэвид Стоун
источник
Недавно я отправил запрос на улучшение, основанный на моем исследовании для этого ответа: gcc.gnu.org/bugzilla/show_bug.cgi?id=53313 . Это значительно упростило бы ситуацию с предупреждением, создав уровни предупреждений. В моем предложении предлагаемый мной набор предупреждений составляет примерно -W4, с дополнительным предложением создать -Winf, что будет означать -Weverything-and-I-really-mean-it-this-time
Дэвид Стоун
Запрос на улучшение, из-за которого часть -Wpadded будет добавлена ​​в рекомендуемый список: gcc.gnu.org/bugzilla/show_bug.cgi?id=53514
Дэвид Стоун
Запрос на улучшение, который приведет к добавлению частей -Weffc ++ в рекомендуемый список: gcc.gnu.org/bugzilla/show_bug.cgi?id=16166
Дэвид Стоун,
1
@Predelnik: Это сложнее. -Wswitch-enumпредупреждает, если вы явно не обрабатываете каждое значение перечисления в переключателе, и defaultне считается явным. С другой стороны, -Wswitch-defaultпредупреждает вас, если у вашего коммутатора нет defaultрегистра, даже если вы явно указали все возможные значения.
Дэвид Стоун
2
Кстати - используйте -isystemвместо -I«старого библиотечного кода», чтобы предотвратить все эти ложные срабатывания
galois
39

Ооо, все мои первоначальные поисковые запросы привели к 99% сообщений о том, как подавлять предупреждения (что довольно пугающе), но я только что наткнулся на этот комментарий , в котором есть этот прекрасный набор флагов (некоторые менее актуальны):

Перекрестно проверено:

http://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html

-g -O -Wall -Weffc++ -pedantic  \
-pedantic-errors -Wextra -Waggregate-return -Wcast-align \
-Wcast-qual -Wconversion \
-Wdisabled-optimization \
-Werror -Wfloat-equal -Wformat=2 \
-Wformat-nonliteral -Wformat-security  \
-Wformat-y2k \
-Wimplicit  -Wimport  -Winit-self  -Winline \
-Winvalid-pch   \
-Wlong-long \
-Wmissing-field-initializers -Wmissing-format-attribute   \
-Wmissing-include-dirs -Wmissing-noreturn \
-Wpacked  -Wpadded -Wpointer-arith \
-Wredundant-decls \
-Wshadow -Wstack-protector \
-Wstrict-aliasing=2 -Wswitch-default \
-Wswitch-enum \
-Wunreachable-code -Wunused \
-Wunused-parameter \
-Wvariadic-macros \
-Wwrite-strings

Так что я думаю, что это хорошая отправная точка. Не осознавал, что это обман, но, по крайней мере, это было глубоко похоронено. :-)

Sdaz Mac
источник
1
Возможно, но это, похоже, меняется между версиями и, вероятно, из-за солнечных пятен и RMS, поэтому излишняя явность, вероятно, не повредит. В любом случае, это хорошая отправная точка.
Sdaz MacSkibbons
3
Из быстрого grep c-opts.c / opts.c 4.5.2 для 'case OPT_W' вам не хватает: строгого переполнения, undef, strict nul sentinel, normalized, multichar, неявного объявления функции, устаревшего, меток endif, comment s , встроенный макрос переопределен, больше чем, больше чем eq, abi. Это безумие, что нет опции командной строки для их перечисления.
Тони Делрой
3
Я думаю, что это еще более безумно, когда -Wallне происходит того, чего можно ожидать. Но спасибо, некоторые из них выглядят очень полезными!
Sdaz MacSkibbons
1
Отключение предупреждений имеет свое место. В конце концов, это «предупреждения». Другая ситуация - когда вы включаете флаг, который включает несколько предупреждений, но вы хотите выбирать его.
Tamás Szelei
1
Как ты умеешь пользоваться -Waggregate-return? Это дает мне предупреждение при каждом использованииbegin/end()
Flamefire
13

Некоторые из них уже включены в -Wallили -Wextra.

Хорошая базовая установка для C:

-std=c99 -pedantic -Wall -Wextra -Wwrite-strings -Werror

и для C ++

-ansi -pedantic -Wall -Wextra -Weffc++

(пропуск -Werrorдля C ++, так как -Weffc++есть некоторые неудобства)

Шимон Тот
источник
10
-Werror может быть отключен для определенных типов предупреждений, например: -Werror -Weffc ++ -Wno-error = effc ++
Роберт Хенсинг,
2
ansi : В режиме C это эквивалентно -std=c89. В режиме C ++ он эквивалентен -std=c++98. то есть, если вы указываете какой-то другой std, не используйтеansi
Шон Брекенридж
2

Пытаться

export CFLAGS="`gcc --help=warnings | grep '\-W' | awk '{print $1 \" \"}' |
sort | uniq` -pedantic -fdiagnostics-show-option -Werror"

Это быстрый и грязный старт, который определенно потребует некоторой настройки; во-первых, даже если вы вызовете компилятор по имени, подходящему для вашего языка (например, g++для C ++), вы получите предупреждения, которые не относятся к этому языку (и компилятор поднимет руки и откажется продолжать, пока вы убрать предупреждение).

Другое дело, что я добавил -Werror, потому что, если вы не исправляете предупреждения, зачем вам их включать? Вы также можете убрать предупреждения из списка. (Например, я почти никогда не использую -Waggregate-returnC ++.)

Некоторые предупреждения ничего не сделают без других параметров, связанных с производительностью ( -Wstack-protector). -fdiagnostics-show-optionи руководство GCC - ваши друзья.

Кстати, некоторые предупреждения являются взаимоисключающими; в частности, используя -Wtraditionalи -Wold-style-definitionвместе с -Werror, не будет компилироваться.

Натан Пол Саймонс
источник
0

В моем Clion's CmakeLists.txt

cmake_minimum_required(VERSION 3.13)
project(cpp17)

set(CMAKE_CXX_STANDARD 17)

set(GCC_COVERAGE_COMPILE_FLAGS "-std=c++17 -Wall -Weffc++ -Wno-error=effc++ -pedantic \
 -Weverything -Wno-c++98-compat -Wno-c++98-compat-pedantic -Wno-newline-eof  \
-pedantic-errors -Wextra -Waggregate-return -Wcast-align \
-Wcast-qual -Wconversion \
-Wdisabled-optimization \
-Werror -Wfloat-equal -Wformat=2 \
-Wformat-nonliteral -Wformat-security  \
-Wformat-y2k \
-Wimplicit  -Wimport  -Winit-self  -Winline -Winvalid-pch   \
-Wlong-long \
-Wmissing-field-initializers -Wmissing-format-attribute   \
-Wmissing-include-dirs -Wmissing-noreturn \
-Wpacked  -Wpadded -Wpointer-arith \
-Wredundant-decls \
-Wshadow -Wstack-protector \
-Wstrict-aliasing=2 -Wswitch-default \
-Wswitch-enum \
-Wunreachable-code -Wunused \
-Wunused-parameter \
-Wvariadic-macros \
-Wwrite-strings")


set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${GCC_COVERAGE_COMPILE_FLAGS}" )

add_executable(cpp17 main.cpp)
ОСШ
источник