Як увімкнути (буквально) ВСІ попередження GCC?


194

Я хотів би включити - буквально - ВСІ попередження, які має GCC. (Ви думаєте, що це буде легко ...)

  • Ви -Wallмогли б подумати, що може зробити трюк, але ні! Ще потрібно -Wextra.

  • Ви -Wextraмогли б подумати, що може зробити трюк, але ні! Не всі перелічені тут попередження (наприклад, -Wshadow) увімкнені цим. І я досі не маю уявлення, чи цей перелік є вичерпним.

Як я можу сказати GCC, щоб увімкнути (ні, якщо є, чи є, але!) Всі попередження, які він має?


27
@Arafangion: Я не розумію, що "незрозуміло" у питанні - так, я хотів би ввімкнути всі попередження, застосовні до мого коду, незалежно від того, наскільки педантичні. Що стосується причини, то вона дуже проста: я виявив деякі застереження, які не вмикаються -Wall або -Wextra, щоб бути корисними, і тому я хочу спробувати решту, щоб побачити, чи можу я поліпшити свій код. Це так просто.
користувач541686

12
@JoachimPileborg: "Про що ви хочете попередити компілятор?" Потенційні помилки та / або поганий стиль? Я маю на увазі, якби я знав усі точні попередження, я б просто ввімкнув їх вручну, не потрібно ставити питання. Якщо відповідь справді "Ви повинні подивитися вихідний код, щоб знайти їх", то будь ласка, опублікуйте це як відповідь!
користувач541686

56
clang 3.1 пропозиції -Weverything.
Олександр Хамез

5
@Arafangion Ну, питання позначено C ++ так ... :)
Якийсь програміст чувак

5
@JoachimPileborg А тепер існує (нарешті) автоматизований спосіб витягнути попередження з джерела: github.com/barro/compiler-warnings
Kyle Strand

Відповіді:


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++це занадто галасливо, щоб бути корисним, воно засноване на застарілому першому виданні Ефективного C ++ та попереджає про конструкції, які є абсолютно дійсними C ++ (і щодо яких вказівки змінені в наступних виданнях книги.) Я не хочу бути попередив, що я не ініціалізував std::stringчлена в своєму конструкторі; у нього є конструктор за замовчуванням, який робить саме те, що я хочу, чому я повинен писати, m_str()щоб називати це? Ці -Weffc++попередження , які були б корисні занадто складні для компілятора , щоб виявити точно (даючи помилкові негативи), і ті, які не є корисними, наприклад, ініціалізація всіх членів в явному вигляді, просто виробляють занадто багато шуму, що дає помилкові спрацьовування.

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

тобто ви насправді не хочете всіх попереджень, ви просто думаєте, що робите.

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

Кожен, хто просто вмикає все , мабуть, або робить це, тому що вони незрозумілі, тому що босий гострий голос сказав "ніяких попереджень".

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

Редагувати: Див. Також -Wall-all, щоб увімкнути всі попередження , закриті як WONTFIX.

Редагувати 2: у відповідь на скаргу DevSolar щодо файлів, що потребують використання різних попереджень, залежно від версії компілятора, якщо -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
"Перегляньте посібник, прочитайте про них, вирішіть, що ви хочете включити, спробуйте." Проблема тут - кроки, які ви залишили: "Перегляньте посібник для кожної версії компілятора та адаптуйте свій список попереджень, оскільки вони змінюються. Зробіть Makefiles перевірити точну версію компілятора та скористайтеся іншим списком попереджень для кожного з них ». Ми підтримуємо підтримувані рівнем оптимізації; чому вони не могли заважати надавати ту саму послугу для попереджень?
DevSolar

17
@JonathanWakely: У мене є свої проекти, і GCC не серед них. Я вказую на слабкість їхнього продукту. Або вони виправляють це, або вони приймають провину за те, що цього не роблять, але мені не доводиться це виправляти за них, прокляті ОСС.
DevSolar

14
@JonathanWakely: "Якщо ви чогось хочете, попросіть, не сукайте цього". - Я не зобов’язаний брати участь у проекті GCC, щоб його критикувати, особливо не, якщо # 31573 вже позначено як WONTFIX. Це ставить цю тему з "запитуй про це" в "сука про неї".
DevSolar

61
-WeverythingЯ вважаю, що найкраще рішення, ніж стратегія gcc не дає такого варіанту. Я використовую цей прапор з клангом, тому що моя філософія полягає в тому, що я хочу, щоб усі попередження були за замовчуванням (тому що хтось вважав, що це досить корисно, щоб додати до компілятора), і якщо мені це не подобається, я вимикаю це попередження спеціально. Справа в тому, що ви не знаєте про попередження, які не спрацьовують, але ви знаєте про попередження, які ви не хочете, щоб зробити це тригером, і вони легко відключаються.
Девід Стоун

17
@JonathanWakely Так, але вони мізерні. Найпростіший спосіб зрозуміти, які попередження можуть бути відповідні вашому коду, - це побачити, які попередження викликаються вашим кодом; в цей момент ви можете побачити відповідний, реальний приклад потенційно небезпечного коду, перш ніж приймати рішення про відключення попередження чи ні. Це легко зробити за допомогою -Weverythingопції Кланг , але зробити це неможливо з 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-оптимізації -Waliasing -Walign-commons -Wampersand -Warray-межа -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-kval -Wchar-підписки -Wcharacter-усічення -Wchkp -Wblobbered -Wcomment -Wcompare-reals -Умовно-підтримувані -Wconversion -Wconversion-extra -Wconversion-null -Wcoverage-невідповідність -Wcpp -Wctor-dtor-privacy -Wdate-time -Wdeclaration -after-statement -Wdelete-incomplete -Wdelete-non-virtual-dtor -Wdeprecated -Wdeprecated -кларації -Wdesignized-init -Wdisabled-optimization -Wdiscarded-array-kvalifiers -Wdiscarded-kvalifiers -Wdiv-by-zero -Wdouble-promotion -Weffc ++ -Wempty-body-Wendif-мітки -Wenum-порівняння -Wextra -Wfloat-рівний -Wformat-містить-нуль -Wformat-extra-args -Wformat-nonliteral -Wformat-security -Wformat-підпис -Wformat-y2k -Wformat-нульова довжина -Wfree -nonheap-object -Wfunction-elimination -Wignored-kvalifiers -Wimplicit -Wimplicit-function-izjave -Wimplicit-int -Wimplicit-interface -Wimplicit-procedure -Wincompatible-pointer-types -Winherited-variadic-ctor -Winit-self -Winline -Wint-convert -Wint-to-pointer-cast -Wintrinsic-shadow -Wintrinsics-std -Winvalid-memory-model -Winvalid-offsetof -Winvalid-pch -Wjump-misses-init -Wline-усікання -Wliteral-суфікс -Wlogical -не-в дужках -Wlogical-op -Wlong-long -Wmain -Wmaybe-uninitialized -Wmemset-transposed-args -Wmissing-брекети -Wmissing-декларації -Wmissing-field-ініціалізатори -Wmissing-include-dirs -Wmissing-type-type -Вітмінг-прототипи-Wmultichar -Wnarrowing -Wnested-externs -Wnoexcept -Wnon-template-friend -Wnon-virtual-dtor -Wnonnull -Wodr -Wold-style-cast -Wold-style-izjave -Wold-style-definition -Wopenmp-simd -Woverflow -Woverlength-string -Woverloaded-virtual -Woverride-init -Wpacked -Wpacked-bitfield-compat -Wpadded -Wparentheses -Wpedantic -Wpmf-converions -Wpointer-arith -Wpointer-sign -Wpointer-to-int-cast -Wpragmas -Wproperty -призначення за замовчуванням -Wprotocol -Wreal-q-константа -Wrealloc-lhs -Wrealloc-lhs-all -Wredundant-decls -Wreorder -Wreturn-local-addr -Wreturn-type -Wselector -Wsequence-point -Wshadow -Wshadow-ivar -Wshift-count-negative -Wshift-count-overflow -Wsign-порівняння -Wsign-promo -Wsized-deallocation -Wsizeof-array-argument -Wsizeof-pointer-memaccess -Wstack-protector -Wstrict-null-sentinel -Wstrict-прототипи -Стримка-селектор-відповідність-Wsuggest-attribute = const -Wsuggest-attribute = format -Wsuggest-attribute = noreturn -Wsuggest-attribute = pure -Wsuggest-final-method -Wsuggest-final-types -Wsuggest-override -Wsurprising -Wswitch -Wswitch-bool -Wswitch -за замовчуванням -Wswitch-enum -Wsync-nand -Wsynth -Wsystem-headers -Wtabs -Wtarget-lifetime -Wtraditional -Wtraditional-convert -Wtrampolines -Wtrigraphs -Wtype-limit -Wundeclared-selector -Wundef -Wunderflow -Wuninitialized -Wuninitig -Оптимізація-контур-переможець -Звірна-контур-константи -Унсуфікс-float-константи -Уніфікована -Вінфункція-параметр -Вінфузована-але-встановлена ​​змінна -Вінфузивна-манекен-аргумент -Запомочена-функція -Унікована-мітка -Зупокоєна-локальна-typedefs -Wunused-macros -Wunused-parameter -Wunused-result -Wunused-value -Wunused-variable -Wuse-without-only -Wuseless-cast -Wvarargs -Wvariadic-macros -Wvector-Operation-performance -Wvirtual-move-assign-Wvla -Wvolatile-register-var -Wwrite-stringings -Wzero-as-null-pointer-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в кінці виклику.


10
Боюся, це не практично. Gcc показав мені попередження від std lib.
Валентин Хайніц

13
@ValentinHeinitz Як я вже говорив, я не думаю, що вигідно включати буквально всі попередження, але це те, про що вимагала ОП. Однак я думаю, що явно усунувши деякі проблемні попередження, про які вже говорилося в інших відповідях (наприклад, додавши відповідне -Wno-що в кінці дзвінка), це може бути корисним для практичного використання.
Haatschii

6
@ValentinHeinitz Ви можете не допустити gcc видавати попередження для заголовків системи / std / сторонніх розробників, використовуючи -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-use =]" ;-)
Марк

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/…
S-type

6

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

Я щойно написав модуль m4, щоб скористатися цим (також підтримує кланг-все), дивіться 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 }'


3

З цієї сторінки :

Зауважте, що деякі попереджувальні прапори не маються на увазі -Wall. Деякі з них попереджають про конструкції, які користувачі зазвичай не вважають сумнівними, але які час від часу ви можете перевірити; інші попереджають про конструкції, які необхідні або важко уникнути в деяких випадках, і немає простого способу зміни коду для придушення попередження. Деякі з них увімкнено функцією, -Wextraале багато з них повинні бути включені індивідуально.

Я здогадуюсь питання, які з них ? Можливо, ви можете зібрати цю сторінку для всіх рядків, що починаються з -W, і отримати повний список попереджувальних прапорів. Потім порівняйте їх зі списками під -Wallта -Wextra. Є також -Wpedantic, хоча ти, очевидно, хочеш бути ще педантичнішим =)


"І я досі не маю уявлення, чи цей список є вичерпним" ... так, я, безумовно, можу зірвати цю сторінку, але питання полягає в тому, чи є всеосяжним?
користувач541686

1
Я не знаю ... Можливо, вам доведеться пролити вихідний код GCC. Ви намагаєтесь зробити ваше життя програмістом надзвичайно важким, чи є вагома причина, чому ви хочете бачити кожне можливе попередження? =)
рисовий

2
Я хотів би побачити діагноз GCC свого коду - я вважаю це дуже корисним. Але очевидно, якби я вже знав про всі попередження та які корисні (а які - ні), то запитати не було б чого. Немає реального способу сказати мені, якщо я не спробую їх (і, наприклад, я знайшов тінь корисною, тож це не так, як вони марні лише тому, що їх вимкнено).
користувач541686

3

І я досі не маю уявлення, чи цей перелік є вичерпним.

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


3
Я відповів на сторінку " Підсумок параметрів" у своїй відповіді, яка об'єднує всі варіанти на одну сторінку. Політики перегляду коду GCC не дозволяють отримати нові параметри без документації, тому документи повинні бути вичерпними.
Джонатан Уейклі
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.