7 сентября 2009 г.

Предупреждения GCC ч.2

Наткнулся тут в тексте статьи на Хабре:
...посмотрим внимательно на вывод компилятора при максимально включенных предупреждениях

$ g++ -W -Wall test.cpp

К самой статье это отношения не имеет, но хочется заметить, что заблуждение насчет максимально включенных предупреждений компилятора встречается довольно часто — -Wall и -Wextra (-W) это еще не все предупреждения. К сожалению, путаница по большей части возникает из-за разработчиков GCC. Начать с того, что имя опции -Wall само по себе вводит в заблуждение, так они еще добавляют или удаляют предупреждения от версии к версии, или вообще меняют их смысл, чем лично меня иногда просто ставят в тупик. Но надо отдать им должное — компилятор все-таки развивается, и сейчас с помощью предупреждений можно узнать гораздо больше, чем в более ранних версиях.

Например, в последней версии GCC (4.4) есть полезные предупреждения, которые нужно включать самостоятельно:
  • -Wcast-qual
    Предупреждает о преобразованиях типа "из const char * в char *".
  • -Wconversion
    Предупреждает, если при преобразовании типов может произойти потеря данных. Например, при преобразовании из long в short.
  • -Wredundant-decls
    Предупреждает об повторном объявлении чего-нибудь в той же области видимости, даже если это ни на что не влияет.
  • -Wshadow
    Предупреждает, если объявление переменной перекрывает объявленную ранее переменную с таким же именем.
  • -Wsign-conversion
    Предупреждает, если результат выражения может изменить знак. Например, при преобразовании из int в unsigned int.
  • -Wunreachable-code
    Предупреждает, если какой-то фрагмент кода никогда не будет выполнен. Например, если перед этим фрагментом стоит return. Этот флаг специально не был включен в группу -Wall для того, чтобы можно было разделять сборки debug и release.

И еще некоторые другие:
  • -Wcast-align
  • -Wformat-nonliteral
  • -Wformat-security
  • -Wformat-y2k
  • -Winit-self
  • -Wlogical-op
  • -Wmissing-format-attribute
  • -Wmissing-include-dirs
  • -Woverlength-strings

9 комментариев:

  1. Небольшое дополнение
    gcc -c -Q -Wall --help=warnings

    ОтветитьУдалить
  2. Я ещё пользуюсь
    -Wlogical-op
    -Wabi
    -Wctor-dtor-privacy
    -Wnon-virtual-dtor
    -Wstrict-null-sentinel
    -Woverloaded-virtual
    -Wpointer-arith
    -Wswitch-enum
    -Wswitch-default
    -Wold-style-cast

    Кроме последних трёх они срабатывают крайне редко, но пусть будут.

    А когда скучно и нечего делать можно включить -Weffc++ :)
    Что касается -Wunreachable-code то он часто ругается на вполне себе reachable-code и доверия к нему у меня нет.

    ОтветитьУдалить
  3. 2 Alexander: Спасибо, про флаг -Q я не знал. Очень полезно. И познавательно :)

    2 Игорь Говоров: Странно насчет -Wunreachable-code -- мне ни разу не попадались ошибочные предупреждения. Если у Вас есть пример -- приведите его, плз. Было бы интересно попробовать с разными версиями компилятора.

    ОтветитьУдалить
  4. Сделать синтетический пример на ложное срабатывание на скорую руку лень, может быть позже.
    Но показать что он любит заваливать вывод бесполезными сообщениями довольно просто (нельзя не <pre> ни <code>? Досадно ):
    $ cat unreach.cpp
    #include <cstdlib>
    #include <string>
    #include <iostream>

    struct MyStruct
    {
    std::string a;
    };

    int main(int /*argc*/, char** /*argv*/)
    {
    MyStruct s;
    std::cout << s.a << std::endl;
    return (EXIT_SUCCESS);
    }

    $g++ -Wall -Wextra -Wunreachable-code unreach.cpp
    unreach.cpp: In constructor ‘MyStruct::MyStruct()’:
    unreach.cpp:6: warning: will never be executed

    Ну вот зачем мне этот Warning про сгенерированный компилятором код?

    ОтветитьУдалить
  5. Да, действительно. Причем версия g++-4.4 лезет еще дальше - в дебри STL. Зачем - непонятно.

    Значит, будут исправлять.

    ОтветитьУдалить
  6. Да, забыл написать:
    gcc version 4.3.2 [gcc-4_3-branch revision 141291] (SUSE Linux)

    Поставил сейчас -Wunreachable-code на один из проектов, почитал. Ругается на вот такой кусок кода:
    const QString dir = QFileDialog::getExistingDirectory(0, QString(),QString(""));

    У QString все операторы и конструкторы определены, значит дело не в генерируемом коде.
    Если убрать "const QString dir = " и оставить только вызов функции то никаких предупреждений не показывается.
    В чём дело пока не разобрался, может поковыряю вечером.

    ОтветитьУдалить
  7. Ну, вот в Вашем предыдущем примере предупреждение исправляется, если определить конструктор MyStruct и в нем что-нибудь присвоить а, например a="". Но только какой в этом смысл?

    Думаю, это действительно баг. На сайте gcc уже есть сообщения, что слишком много предупреждений при использовании STL и gcc-4.4.

    ОтветитьУдалить
  8. 2 Alexander: Попробовал -Q на версии 4.1 -- не работает. Похоже, эта фича только в 4.3 появилась. На более ранних версиях -Q имеет какой-то другой смысл, насколько я понял. Хотя, могу и ошибаться.

    ОтветитьУдалить
  9. Сорри, кажется, я недопонял документацию.

    В 4.3 появилась фича --help=... Хотя я был уверен, что в ранних версиях такое тоже можно делать.

    ОтветитьУдалить