Как включить (буквально) ВСЕ предупреждения GCC?

194

Я хотел бы включить - буквально - ВСЕ предупреждения, которые имеет GCC. (Вы думаете, это будет легко ...)

  • Вы могли бы подумать, что -Wallможно сделать, но нет! Все еще нужно -Wextra.

  • Вы могли бы подумать, что -Wextraможно сделать, но нет! Не все перечисленные здесь предупреждения (например, -Wshadow) включены этим. И я до сих пор не знаю, является ли этот список всеобъемлющим.

Как мне сказать GCC включить (нет, если, и, или но!) Все предупреждения, которые он имеет?

user541686
источник
27
@Arafangion: я не понимаю, что «неясно» в этом вопросе - да, я хотел бы включить все предупреждения, которые применимы к моему коду, независимо от того, насколько педантичны. Что касается причины, это очень просто: я нашел некоторые предупреждения, которые не включаются -Wall или -Wextra, полезными, и поэтому я хочу попробовать остальные, чтобы посмотреть, смогу ли я улучшить свой код. Это так просто.
user541686
12
@JoachimPileborg: «Что вы хотите, чтобы компилятор предупреждал?» Потенциальные ошибки и / или плохой стиль? Я имею в виду, что если бы я знал все точные предупреждения, то я бы просто включил их вручную, не нужно ставить вопрос. Если ответ действительно «вы должны посмотреть на исходный код, чтобы найти их все», то, пожалуйста, опубликуйте его как ответ!
user541686
56
Clang 3.1 предлагает -Weverything.
Александр Хамес
5
@Arafangion Ну, вопрос помечен C ++, так что ... :)
Какой-то программист чувак
5
@JoachimPileborg И теперь есть (наконец) автоматизированный способ извлечения предупреждений из источника: github.com/barro/compiler-warnings
Кайл Стрэнд,

Ответы:

130

Ты не можешь

Руководство по GCC 4.4.0 является исчерпывающим только для этой версии, но в нем перечислены все возможные предупреждения для 4.4.0. Они не все на странице, на которую вы ссылаетесь, например, некоторые языковые опции находятся на страницах для опций C ++ или Obj-C. Чтобы найти их все, вам лучше посмотреть обзор вариантов

Включение всего включает в себя то, -Wdouble-promotionчто относится только к процессорам с 32-разрядным модулем с плавающей запятой одинарной точности, который реализуется floatаппаратно, но эмулируется doubleпрограммно. Делать расчеты так, как doubleбы использовать программную эмуляцию и быть медленнее. Это актуально для некоторых встроенных процессоров, но совершенно не актуально для современных настольных процессоров с аппаратной поддержкой 64-битной плавающей запятой.

Другое предупреждение, которое обычно бесполезно, - -Wtraditionalэто предупреждение об идеально правильно сформированном коде, который имеет другое значение (или не работает) в традиционных C, например "string " "concatenation", или определениях функций ISO C! Вы действительно заботитесь о совместимости с 30-летними компиляторами? Вы действительно хотите предупреждение для записи int inc(int i) { return i+1; }?

Я думаю, что -Weffc++это слишком шумно, чтобы быть полезным, оно основано на устаревшей первой редакции Effective C ++ и предупреждает о конструкциях, которые совершенно допустимы в C ++ (и для которых руководящие принципы изменились в более поздних выпусках книги). Я не хочу быть предупредил, что я не инициализировал std::stringчлен в своем конструкторе; у него есть конструктор по умолчанию, который делает именно то, что я хочу, почему я должен писать, m_str()чтобы вызвать его? Эти -Weffc++предупреждения , которые были бы полезны слишком сложны для компилятора , чтобы обнаружить точно (давая ложные негативы), и те, которые не является полезными, например, инициализация всех членов в явном виде, просто производят слишком много шума, что дает ложные срабатывания.

Люк Дантон привел отличный пример бесполезных предупреждений, -Waggregate-returnкоторые почти наверняка не имеют смысла для кода C ++.

то есть вы действительно не хотите всех предупреждений, вы просто думаете, что хотите.

Просмотрите руководство, прочитайте о них, решите, какие из них вы можете включить, попробуйте их. Чтение руководства вашего компилятора это хорошая вещь ТМ в любом случае, принимая короткую стрижку и включение предупреждений вы не понимаете, не очень хорошая идея, особенно если это , чтобы избежать необходимости RTFM.

Любой, кто просто включает все , вероятно, либо делает это, потому что он не имеет ни малейшего понятия, потому что или босс с заостренными волосами сказал «никаких предупреждений»

Некоторые предупреждения важны, а некоторые нет. Вы должны быть разборчивы или вы испортили свою программу. Рассмотрим, например, -Wdouble-promotion. Если вы работаете над встроенной системой, вы можете захотеть этого; если вы работаете в настольной системе, то, вероятно, нет. А ты хочешь -Wtraditional? Я сомневаюсь в этом.

Редактировать: См. Также -Wall-все, чтобы включить все предупреждения, которые закрываются как WONTFIX.

Редактировать 2: в ответ на жалобу DevSolar о том, что make-файлам нужно использовать разные предупреждения в зависимости от версии компилятора, если -Wall -Wextraэто не подходит, то нетрудно использовать CFLAGS для конкретного компилятора и для конкретной версии:

compiler_name := $(notdir $(CC))
ifeq ($(compiler_name),gcc)
compiler_version := $(basename $(shell $(CC) -dumpversion))
endif
ifeq ($(compile_name),clang)
compiler_version := $(shell $(CC) --version | awk 'NR==1{print $$3}')
endif
# ...
wflags.gcc.base := -Wall -Wextra
wflags.gcc.4.7 := -Wzero-as-null-pointer-constant
wflags.gcc.4.8 := $(wflags.gcc.4.7)
wflags.clang.base := -Wall -Wextra
wflags.clang.3.2 := -Weverything
CFLAGS += $(wflags.$(compiler_name).base) $(wflags.$(compiler_name).$(compiler_version))
Джонатан Уэйкли
источник
38
«Пройдите руководство, прочитайте о них, решите, что вы можете включить, попробуйте». Проблема здесь состоит в том, что вы упустили следующие шаги: «Перейдите к руководству для каждой версии компилятора и адаптируйте список предупреждений, потому что они меняются. Сделайте так, чтобы ваши Make-файлы проверяли точную версию компилятора и использовали другой список предупреждений. для каждого из них. " У нас есть уровни оптимизации, поддерживаемые сопровождающим; почему они не могут быть обеспокоены предоставлением одного и того же сервиса для предупреждений?
DevSolar
17
@JonathanWakely: у меня есть свои проекты, и GCC среди них нет. Я указываю на слабость в их продукте. Либо они исправляют это, либо они принимают вину за то, что не сделали этого, но я не могу исправить это для них, OSS, черт побери.
DevSolar
14
@JonathanWakely: «Если ты чего-то хочешь, попроси об этом, не смейся об этом». - Я не обязан участвовать в проекте GCC, чтобы критиковать его, особенно если № 31573 уже помечен как WONTFIX. Это помещает эту тему из «спросить об этом» в стадион «сука об этом».
DevSolar
61
-WeverythingЯ думаю, что это лучшее решение, чем стратегия gcc, не предусматривающая такой опции. Я использую этот флаг с clang, потому что моя философия заключается в том, что я хочу, чтобы все предупреждения были включены по умолчанию (потому что кто-то считал, что это достаточно полезно для добавления в компилятор), и если мне это не нравится, я специально отключаю это предупреждение. Дело в том, что вы не знаете о предупреждениях, которые не срабатывают, но вы знаете о предупреждениях, которые не должны срабатывать, и они легко отключаются.
Дэвид Стоун
17
@JonathanWakely Да, но они ничтожные. Самый простой способ узнать, какие предупреждения могут иметь отношение к вашему коду, - это посмотреть, какие предупреждения вызваны вашим кодом; в этот момент вы можете увидеть соответствующий, реально существующий пример потенциально опасного кода, прежде чем решить, стоит ли отключить предупреждение. Это легко сделать с помощью -Weverythingопции Clang , но невозможно с GCC.
Кайл Стрэнд
71

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

gcc -Q --help=warning

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

gcc -Wall -Wextra -Q --help=warning

Чтобы включить все предупреждения, вы можете использовать некоторые регулярные выражения для извлечения параметров командной строки

gcc -Q --help=warning | sed -e 's/^\s*\(\-\S*\)\s*\[\w*\]/\1 /gp;d' | tr -d '\n'

Для моего текущего GCC это дает:

-Wabi -Wabi-tag -Waddress -Waggregate-return -Waggressive-loop-optimizations -Waliasing -Walign-commons -Wampersand -Warray-bounds -Warray-temporaries -Wassign-intercept -Wattributes -Wbad-function-cast -Wbool-сравнить -Wbuiltin-macro-redefined -Wc ++ - compat -Wc ++ 0x-compat -Wc ++ 14-compat -Wc-тип привязки -Wc90-c99-compat -Wc99-c11-compat -Wcast-align--Wcast-qual -Wchar-subscripts -Wcharacter-truncation -Wchkp -Wclobbered -Wcomment -Wcompare-reals -Wconditional-поддерживаемых -Wconversion -Wconversion-extra -Wconversion-null -Wcoverage-mismatch -Wcpp -Wctor-dtor-privacy -Wdate-time -Wlaration -after-Statement -Wdelete-неполный -Wdelete-non-virtual-dtor -Wdeprecated -Wdeprecated-декларации -Wdesignated-init -Wdisabled-оптимизация -Wdiscarded-array-qualifiers -Wdiscarded-квалификаторы -Wdiv-by-zero -Wdouble-promotion -Weffc ++ -Wempty-body-Wendif-метки -Wenum-сравнить -Wextra -Wfloat-equal -Wformat-содержит-nul -Wformat-extra-args -Wformat-nonliteral -Wformat-security -Wformat-подпись -Wformat-y2k -Wformat-zero-length -Wfree -nonheap-объект -Wfunction-elission -Wignored-квалификаторы -Wimplicit -Wimplicit-объявление функции -Wimplicit-int -Wimplicit-интерфейс -Wimplicit-процедура -Wincompatible-указатель-типы -Winherited-variadic-ctor -Winit-self -Winline -Wint-преобразование -Wint -ins-cast -Wintrinsic-shadow -Wintrinsics-std -Winvalid-memory-model -Winvalid-offsetof -Winvalid-pch -Wjump-misses-init -Wline-усечение -Wliteral-суффикс -Wlogical -не-круглые скобки -Wlogical-op -Wlong-long -Wmain -Wmaybe-неинициализированный -Wmemset-transposed-args -Wmissing-фигурные скобки -Wmissing-декларации -Wmissing-field-initializers -Wmissing-include-dirs -Wmissing-параметр-type -Wmissing-прототипы-Wmultichar -Wnarrowing -Wnested-externs -Wnoexcept -Wnon-template-friend -Wnon-virtual-dtor -Wnonnull -Wodr -Wold-style-cast -Wold-style-объявление -Wold-style-description -Wopenmp-simd -Woverflow -Woverlength-strings -Woverloaded-virtual -Woverride-init -Wpacked -Wpacked-bitfield-compat -Wpadded -Wparentheses -Wpedantic -Wpmf-преобразований -Wpointer-arith -Wpointer-sign -Wpointer-to-int-cast -Wpragmas -Wproperty -assign-default -Wprotocol -Wreal-q-constant -Wrealloc-lhs -Wrealloc-lhs-all -Wredundant-decls -Wororder -Wreturn-local-addr -Wreturn-type -Wselector -Wsequence-point -Wshadow -Wshadow-ivar -Wshift-count-отрицательный -Wshift-count-overflow -Wsign-Compare -Wsign-promo -Wsized-deallocation -Wsizeof-массив-аргумент -Wsizeof-указатель-memaccess -Wstack-протектор -Wstrict-null-sentinel -Wstrict-prototypes -Wstrict-селектор матч-Wsuggest-attribute = const -Wsuggest-attribute = формат -Wsuggest-attribute = noreturn -Wsuggest-attribute = чисто -Wsuggest-final-методы -Wsuggest-final-types -Wsuggest-override -Wsurprising -Wswitch -Wswitch-bool -Wswitch -default -Wswitch-enum -Wsync-nand -Wsynth -Wsystem-headers -Wtabs -Wtarget-life -Wtraditional -Wtraditional-преобразование -Wtrampolines -Wtrigraphs -Wtype-limit -Wundeclared-selector -Wundef -Wunderflow -Wuninownized -Wuninownized -Wunsafe-loop-optimizations -Wunsuffixed-float-constants -Wunused -Wunused-but-set-параметр -Wunused-но-набор-переменных -Wunused-фиктивный-аргумент -Wunused-function -Wunused-label -Wunused-local-typedefs -Wunused-macros -Wunused-параметр -Wunused-результат -Wunused-значение -Wunused-переменная -Wuse-без-только -Wuseless-cast -Wvarargs -Wvariadic-macros -Wvector-операция-производительность -Wvirtual-move-assign-Wvla -Wvolatile-register-var -Wwrite-strings -Wzero-as-нулевой указатель-константа -Wzerotrip -frequire-return-оператор

Теперь это можно использовать для вызова GCC, т.е.

gcc $(gcc -Q --help=warning | sed -e 's/^\s*\(\-\S*\)\s*\[\w*\]/\1 /gp;d' | tr -d '\n')

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

Haatschii
источник
10
Боюсь, это не практично. Gcc показал мне предупреждения от std lib.
Валентин Хайниц
13
@ValentinHeinitz Как я уже сказал, я не думаю, что полезно включать буквально все предупреждения, но именно об этом попросил OP. Тем не менее, я думаю, что путем явного удаления некоторых проблемных предупреждений, уже упомянутых в других ответах (например, путем добавления соответствующих -Wno-что угодно в конце вызова), это может иметь практическое применение.
Хаацкий
6
@ValentinHeinitz Вы можете запретить gcc выдавать предупреждения для системных / стандартных / сторонних заголовков, используя -isystemвместо -Iсоответствующих каталогов.
Кайл Стрэнд,
4
Это должен быть принятый ответ, так как это на самом деле и прямо отвечает на вопрос.
TFuto
16

Просто невозможно запрограммировать все включенные предупреждения (если вы не собираетесь их игнорировать, но зачем тогда беспокоиться?). Например, давайте предположим , что вы используете следующий набор флагов: -Wstrict-prototypes -Wtraditional.

Даже если включены два предупреждения, следующая программа будет жаловаться.

/tmp $ cat main.c 
int main(int argc, char **argv) {
    return 0;
}
/tmp $ gcc -Wstrict-prototypes -Wtraditional main.c 
main.c: In function main’:
main.c:1:5: warning: traditional C rejects ISO C style function definitions [-Wtraditional]
 int main(int argc, char **argv) {
     ^

Вы можете подумать: «Ну, тогда я собираюсь использовать прототипы старого стиля». Нет, это не сработает.

/tmp $ cat main.c 
int main(argc, argv)
    int argc;
    char **argv;
{
    return 0;
}
/tmp $ gcc -Wstrict-prototypes -Wtraditional main.c 
main.c:1:5: warning: function declaration isnt a prototype [-Wstrict-prototypes]
 int main(argc, argv)
     ^

И нет, не указывать ни один прототип тоже неправильно, так как компилятор тоже будет жаловаться.

/tmp $ cat main.c 
int main() {
    return 0;
}
/tmp $ gcc -Wstrict-prototypes -Wtraditional main.c 
main.c:1:5: warning: function declaration isnt a prototype [-Wstrict-prototypes]
 int main() {
     ^

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

Для C ++ это возможно ( -Wtraditionalфлаг не существует), и очень простые программы могут быть скомпилированы. Чтобы включить все предупреждения, используйте следующий список предупреждений (возможно, некоторые предупреждения дублированы, потому что я не удосужился отфильтровать включенные предупреждения -Wall).

-Wabi -Wctor-dtor-privacy -Wnon-virtual-dtor -Wreorder -Weffc++ -Wstrict-null-sentinel -Wno-non-template-friend -Wold-style-cast -Woverloaded-virtual -Wno-pmf-conversions -Wsign-promo -Wextra -Wall -Waddress -Waggregate-return -Warray-bounds -Wno-attributes -Wno-builtin-macro-redefined -Wc++0x-compat -Wcast-align -Wcast-qual -Wchar-subscripts -Wclobbered -Wcomment -Wconversion -Wcoverage-mismatch -Wno-deprecated -Wno-deprecated-declarations -Wdisabled-optimization -Wno-div-by-zero -Wempty-body -Wenum-compare -Wno-endif-labels -Wfatal-errors -Wfloat-equal -Wformat -Wformat=2 -Wno-format-contains-nul -Wno-format-extra-args -Wformat-nonliteral -Wformat-security -Wformat-y2k -Wignored-qualifiers -Winit-self -Winline -Wno-int-to-pointer-cast -Wno-invalid-offsetof -Winvalid-pch -Wunsafe-loop-optimizations -Wlogical-op -Wlong-long -Wmain -Wmissing-braces -Wmissing-field-initializers -Wmissing-format-attribute -Wmissing-include-dirs -Wmissing-noreturn -Wno-mudflap -Wno-multichar -Wnonnull -Wno-overflow -Woverlength-strings -Wpacked -Wpacked-bitfield-compat -Wpadded -Wparentheses -Wpointer-arith -Wredundant-decls -Wreturn-type -Wsequence-point -Wshadow -Wsign-compare -Wsign-conversion -Wstack-protector -Wstrict-aliasing=1 -Wstrict-overflow=5 -Wswitch -Wswitch-default -Wswitch-enum -Wsync-nand -Wsystem-headers -Wtrigraphs -Wtype-limits -Wundef -Wuninitialized -Wunknown-pragmas -Wno-pragmas -Wunreachable-code -Wunused -Wunused-function -Wunused-label -Wunused-parameter -Wunused-value -Wunused-variable -Wvariadic-macros -Wvla -Wvolatile-register-var -Wwrite-strings
Конрад Боровски
источник
13
Я никогда не удосужился проверить это до сих пор, но на самом деле это не невозможно ... попробуйтеint main(int, char **); int main(argc, argv) int argc; char **argv; { (void)argc; (void)argv; return 0; }
user541686
2
Даже с этой тривиальной программой я все еще могу получить «предупреждение: использование стека составляет 16 байт [-Wstack-Использование =]" ;-)
Марк
7

Кто-то создал набор инструментов для определения полного набора предупреждений для данной версии GCC или Clang.

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

Похоже, что инструмент анализирует фактический c.optфайл в исходном коде GCC, поэтому его результаты должны быть окончательными.

Хранилище также содержит текстовые файлы со списками предупреждений, созданными для большинства версий GCC и Clang (в настоящее время Clang с 3.2 по 3.7 и GCC с 3.4 по 5.3).

https://github.com/barro/compiler-warnings

Кайл Стрэнд
источник
Это ответ. Используйте список «верхнего уровня» и добавьте все аргументы верхнего уровня (без отступа / вложенности). github.com/Barro/compiler-warnings/blob/master/gcc/…
Jetski S-type
6

Gcc 4.3+ теперь имеет -Q --help = warnings, вы даже можете указать --help = warnings, C, чтобы просто распечатать предупреждения, связанные с C.

Я только что написал модуль m4, чтобы воспользоваться этим (также поддерживает clang's -Weverything), см. Wget_manywarnings.m4

Как использовать это довольно просто, в основном модуль включает каждый флаг предупреждения. И вы удаляете предупреждения по мере необходимости - некоторые действительно очень многословны. Пример: configure.ac

Если вы не используете autotools, вы найдете код для включения всех отключенных предупреждений в модуле m4, который в основном представляет собой вызов gcc, передаваемый через awk:

flags="-Wall -Wextra -Wformat=2 "$(gcc -Wall -Wextra -Wformat=2 -Q --help=warning,C|awk '{ if (($2 == "[disabled]" || $2 == "") && $1!~/=/ && $1~/^-W/&& $1!="-Wall") print $1 }'

rockdaboot
источник
3

С этой страницы :

Обратите внимание, что некоторые флаги предупреждения не подразумеваются -Wall. Некоторые из них предупреждают о конструкциях, которые пользователи обычно не считают сомнительными, но которые иногда вы можете проверить; другие предупреждают о конструкциях, которые в некоторых случаях необходимо или трудно избежать, и не существует простого способа изменить код для подавления предупреждения. Некоторые из них включены, -Wextraно многие из них должны быть включены по отдельности.

Я думаю, вопрос в том, какие ? Возможно, вы могли бы выполнить поиск этой страницы для всех строк, начинающихся с -W, и получить полный список флагов предупреждений. Затем сравните их со списками под -Wallи -Wextra. Существует также -Wpedantic, хотя вы, очевидно, хотите быть еще более педантичным все еще =)

Пэдди
источник
«И я до сих пор не знаю, является ли этот список исчерпывающим» ... да, я, конечно, могу найти эту страницу, но вопрос в том, является ли она исчерпывающей?
user541686 30.07.12
1
Я не знаю ... Возможно, вам придется пролистать исходный код GCC. Вы пытаетесь сделать свою жизнь программиста чрезвычайно сложной или есть веская причина, почему вы хотите видеть каждое мыслимое предупреждение? =)
Пэдди
2
Я хотел бы увидеть диагноз GCC моего кода - я считаю, что это действительно полезно. Но, очевидно, если бы я уже знал обо всех предупреждениях и какие из них полезны (а какие нет), тогда не о чем было бы спрашивать. У меня нет никакого реального способа сказать, если я не попробую их (и, например, я обнаружил, что слежка полезна, поэтому они не бесполезны только потому, что они выключены).
user541686
3

И я до сих пор не знаю, является ли этот список всеобъемлющим.

Возможно, это так, но единственный список, который на 100% исчерпывающий, - это фактический источник для компилятора. Тем не менее, GCC большой ! И я не знаю, все ли параметры командной строки собраны в одном месте или распределены по нескольким исходным файлам. Также обратите внимание, что некоторые предупреждения относятся к препроцессору, некоторые - к фактическому компилятору, а некоторые - к компоновщику (который является совершенно отдельной программой и находится в пакете binutils), поэтому они, скорее всего, распространены.

Какой-то программист чувак
источник
3
В своем ответе я связался со страницей « Сводка параметров» , в которой все параметры объединены в одну страницу. Политики проверки кода GCC не допускают новых опций без документации, поэтому документы должны быть исчерпывающими.
Джонатан Уэйкли