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

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

  • Вы думаете, что -Wall может сделать трюк, но нет! Еще нужно -Wextra.

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

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

Ответ 1

Вы не можете.

Руководство для GCC 4.4.0 является исчерпывающим для этой версии, но в нем перечислены все возможные предупреждения для 4.4.0. Они не все на странице, на которую вы ссылаетесь, например, некоторые параметры, относящиеся к языку, находятся на страницах для опций С++ или 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 С++ и предупреждает о конструкциях, которые являются вполне допустимыми С++ (и для которых руководство было изменено в последующих выпусках книги.) я не хочу, чтобы вас предупреждали, что я не инициализировал член std::string в моем конструкторе; у него есть конструктор по умолчанию, который делает именно то, что я хочу, зачем писать m_str() для его вызова? Предупреждения -Weffc++, которые были бы полезны, слишком сложны для того, чтобы компилятор точно определял (давал ложные отрицания), а те, которые не были полезны, например, инициализировали все члены явно, просто вызывают слишком много шума, давая ложные срабатывания.

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

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

Пройдите руководство, прочитайте о них, решите, что вы можете включить, попробуйте их. В любом случае, чтение вашего руководства для компилятора - это Good Thing TM поэтому короткое сокращение и предупреждающие предупреждения, которые вы не понимаете, не очень хорошая идея, особенно если это не нужно для RTFM.

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

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

Изменить: См. также - Настенные все, чтобы включить все предупреждения, которые закрыты как 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))

Ответ 2

Я согласен с предыдущими ответами, что, вероятно, нецелесообразно включать буквально все предупреждения, однако 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 -Вагрегат-возврат -Вагрессивная петля-оптимизация -Waliasing -Walign-Commons -Wampersand -Warray-bounds -Warray-temporaries -Wassign-intercept -Wattributes -Wbad-function -cast -Wbool-сравнить -Wbuiltin-макро-переопределить -W C++ -компат -W C++ 0x-compat -W C++ 14-compat -Wc-тип привязки -Wc90-c99-compat -Wc99- c11-compat -Wcast-align -Wcast-qual -Wchar-subscripts -Wcharacter-truncation -Wchkp -Wclobbered -Wcomment -Сравнить-реалы -Обусловно поддерживается -Wconversion -Wconversion -экстра -Wconversion -null -Wcoverage -mismatch -Wcpp -Wctor-dtor-privacy -Wdate-time -Wdeclaration-after-Statement -Wdelete-неполное -Wdelete-non-virtual-dtor -Wdeprecated -Wdeprecated -декларации -Wdesignated-init -Wdisabled-оптимизация - Wdiscarded-array-qualifiers -Wdiscarded-qualifiers -Wdiv-by-zero -Wdouble-promoing -Weff C++ -Wempty-body -Wendif-tags -Wenum-Compare -Wextra -Wfloat-equal -Wformat-содержит-nul - Wformat-extra-args -Wformat-nonliteral -Wformat-security -Wformat-signatureness -Wformat-y2k -Wformat-zero-length - Wfree-nonheap-object -Wfunction-elvention -Wignored-квалификаторы -Wimplicit -Wimplicit -функция-объявление -Wimplicit -int -Wimplicit -интерфейс -Wimplicit -процедура -Wincompatible-pointer-types -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-not-круглые скобки -Wlogical-op -Wlong-long -Wmain -Wmaybe-неинициализированный -Wmemset-transposed-args -Wmissing-фигурные скобки -Wmissing-декларации -Wmissing-field-initializers -Wmissing-include -dirs -Wmissing-type-type -Wmissing-прототипы -Wmultichar -Warrowing -Wnested-externs -Wnoexcept -Won-template-friend -Wnon-virtual-dtor -Wnonnull -Wodr -Wold-style-cast -Wold- объявление стиля -Wold-style-description -Wopenmp-simd -Woverflow -Wwlelength-strings -Woverloaded-virtual -Woverride-init -Wpacked -Wpacked -bitfield-compat -Wpadded -Wpherheses -Wpedantic -Wpmf-преобразования -Wointer-arith -Wpoin ter-sign -Wpointer-to-int-cast -Wpragmas -Wproperty-assign-default -Wprotocol -Wreal-q-constant -Wrealloc-lhs -Wrealloc-lhs-all -Wredundant-decls -Wreorder -Wreturn-local -addr -Wreturn-type -Wselector -Wsequence-point -Wshadow -Wshadow -ivar -Wshift-count-отрицательный -Wshift-count-overflow -Wsign-сравните -Wsign-promo -Wsized-deallocation -Wsizeof-array- Аргумент -Wsizeof-pointer-memaccess -Wstack-protector -Wstrict-null-sentinel -Wstrict-prototypes -Wstrict-selector-match -Wsuggest-attribute = const -Wsuggest-attribute = формат -Wsuggest-attribute = noreturn -Wsuggest-attribute = pure -Wsuggest-final-method -Wsuggest-final-types -Wsuggest-override -Wsurprising -Wswitch -Wswitch-bool -Wswitch-default -Wswitch-enum -Wsync-nand -Wsynth -Wsystem-headers -Wtabs -Wtarget -lifetime -Wtraditional -Wtraditional -конверсия -Wtrampolines -Wtrigraphs -Wtype-limit -Wundeclared-selector -Wundef -Wunderflow -Wuninitialized -Wunknown-pragmas -Wunsafe-loop-optimizations -Wunsuffixed-float-constants -Wunused -Wunused -но-набор-параметр -Wunused -но-набор-переменная e -Wunused - фиктивный аргумент -Wunused - функция -Wunused - метка -Wunused - локальный типdefs -Wunused - макрос -Wunused - параметр -Wunused - результат -Wunused - значение -Wunused - переменная -Wuse-без-только -Wuseless-cast -Wvarargs -Wvariadic-macros -Wvector-операция-производительность -Wvirtual-move-assign -Wvla -Wvolatile-register-var -Wwrite-strings -Wzero-as-null-указатель -constant -Wzerotrip -frequire-return-Statement

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

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

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

Ответ 3

Просто невозможно запрограммировать все включенные предупреждения (если вы не проигнорируете их, но тогда зачем беспокоиться?). Например, предположим, что вы используете следующий набор флагов: -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 isn’t 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 isn’t a prototype [-Wstrict-prototypes]
 int main() {
     ^

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

Для С++ это возможно (флаг -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

Ответ 4

Кто-то создал набор инструментов для определения полного набора предупреждений для данной версии 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

Ответ 5

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

Я только что написал модуль m4, чтобы воспользоваться этим (также поддерживает clang -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 }'

Ответ 6

От эта страница:

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

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

Ответ 7

И я до сих пор не знаю, полный ли этот список.

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