Как я могу избавиться от устаревших предупреждений в устаревших функциях в GCC?

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

Это разумное мышление, и оно отражено в реализациях, которые я вижу в GCC 4.2 (1) и Clang 4.0 (2) в OS X, а также в Clang 3.0 (3) в Ubuntu.

  • (1): i686-apple-darwin11-llvm-g ++ - 4.2 (GCC) 4.2.1 (на основе сборки 5658 Apple Inc.) (сборка LLVM 2336.11.00)
  • (2): Apple clang версии 4.0 (теги / Apple / clang-421.0.57) (на основе LLVM 3.1svn)
  • (3): Ubuntu clang версии 3.0-6ubuntu3 (теги / RELEASE_30 / final) (на основе LLVM 3.0)

Однако, когда я компилирую с GCC 4.6 (4) в Ubuntu, я получаю предупреждения об устаревших для всех вызовов устаревших функций, независимо от контекста. Это регресс функциональности? Могу ли я использовать параметры компилятора для получения другого поведения?

  • (4): g ++ (Ubuntu / Linaro 4.6.3-1ubuntu5) 4.6.3

Пример программы:

int __attribute__((deprecated)) a() {
    return 10;
}

int __attribute__((deprecated)) b() {
    return a() * 2; //< I want to get rid of warnings from this line
}

int main() {
    return b(); //< I expect a warning on this line only
}

Вывод из GCC 4.2 (да, я получаю одно и то же предупреждение дважды. Но меня это не волнует):

main.cpp: In function ‘int main()’:
main.cpp:10: warning: ‘b’ is deprecated (declared at main.cpp:5)
main.cpp:10: warning: ‘b’ is deprecated (declared at main.cpp:5)

Вывод из GCC 4.6:

main.cpp: In function 'int b()':
main.cpp:6:9: warning: 'int a()' is deprecated (declared at main.cpp:1) [-Wdeprecated-declarations]
main.cpp:6:11: warning: 'int a()' is deprecated (declared at main.cpp:1) [-Wdeprecated-declarations]
main.cpp: In function 'int main()':
main.cpp:10:9: warning: 'int b()' is deprecated (declared at main.cpp:5) [-Wdeprecated-declarations]
main.cpp:10:11: warning: 'int b()' is deprecated (declared at main.cpp:5) [-Wdeprecated-declarations]

Как я могу убедить GCC 4.6 в том, что он должен давать тот же результат, что и GCC 4.2?


person Magnus Hoff    schedule 19.11.2012    source источник
comment
Вполне возможно, что это никогда не работало с FSF GCC, что поведение 4.2, которое вы видите, является патчем Apple для GCC. А у вас где-нибудь установлен FSF GCC 4.2, чтобы проверить?   -  person    schedule 19.11.2012
comment
@hvd Вы правы. Я бы хотел увидеть этот тест, но у меня под рукой нет 4.2: /   -  person Magnus Hoff    schedule 19.11.2012


Ответы (4)


Поведение, которое вы видите в GCC 4.2, вызвано патчем Apple для GCC. FSF GCC 4.2.4 предупреждает об использовании a. Конкретный бит, который есть у Apple GCC, а у FSF GCC нет:

--- a/gcc/toplev.c
+++ b/gcc/toplev.c
@@ -902,6 +902,9 @@ warn_deprecated_use (tree node)
   if (node == 0 || !warn_deprecated_decl)
     return;

+  if (current_function_decl && TREE_DEPRECATED (current_function_decl))
+    return;
+
   if (DECL_P (node))
     {
       expanded_location xloc = expand_location (DECL_SOURCE_LOCATION (node));

(Доступно под GPLv2 или новее)

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

person Community    schedule 19.11.2012
comment
Аккуратный! Это неплохой ответ. Думаю, я собираюсь сделать это по просьбе функции. Где ты нашел разницу? - person Magnus Hoff; 20.11.2012
comment
Загрузите исходные коды FSF, загрузите исходные коды Apple, распакуйте оба рядом, запустите рекурсивную проверку, найдите устаревшие в результатах и ​​надейтесь, что результатов не так много :) - person ; 20.11.2012
comment
Хе-хе, понял. Придется запланировать для этого время ... :) Спасибо! - person Magnus Hoff; 20.11.2012
comment
@MagnusHoff Просто любопытно, подавали ли вы когда-нибудь запрос на эту функцию. Ссылка будет очень удобным дополнением к этому ответу. - person David Z; 03.04.2020
comment
@DavidZ, извини, нет. Это быстро стало для меня неактуальным, поэтому у меня никогда не было на это времени. - person Magnus Hoff; 03.04.2020

-Wno-deprecated удалит все устаревшие предупреждения

person doron    schedule 19.11.2012
comment
OP просит не об этом. - person OmnipotentEntity; 19.11.2012
comment
@OmnipotentEntity, почему бы и нет? Вы компилируете устаревший код с -Wno-deprecated, а новый - без. - person Lol4t0; 19.11.2012
comment
Ваше утверждение, несомненно, верно, но я спрашиваю не об этом. Мне действительно нужны предупреждения об устаревании, которые выдает GCC 4.2. - person Magnus Hoff; 19.11.2012
comment
Обратите внимание, что в GCC 9.3.0 -Wno-deprecated проигрывает -Wextra, а, например, побеждает подопция -Wno-deprecated-copy: gem5.atlassian.net/browse/GEM5-365 - person Ciro Santilli 新疆再教育营六四事件ۍ 23.07.2020

gcc 4.6 добавил диагностические прагмы, которые помогут решить эту проблему:

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
int __attribute__((deprecated)) b() {
   return a() * 2; //< I want to get rid of warnings from this line
}
#pragma GCC diagnostic pop

Примечание: это работает только в gcc 4.6 и выше. push и pop - это расширения 4.6. В gcc 4.5 #pragma GCC diagnostic push и pop будут игнорироваться (с предупреждениями). Что не будет проигнорировано, так это #pragma GCC diagnostic ignored "-Wdeprecated-declarations", но теперь это действует до конца файла.

person David Hammen    schedule 19.11.2012
comment
+1 - Это действительно хорошее решение для тех, кто не хочет или не может патчить GCC. - person Riot; 30.06.2013

Я столкнулся с той же проблемой. Подошло следующее решение.

typedef OLD_A_NOT_TO_BE_USED a __attribute__((deprecated));

int OLD_A_NOT_TO_BE_USED () {
    return 10;
}

int __attribute__((deprecated)) b() {
    return OLD_A_NOT_TO_BE_USED () * 2; //< I want to get rid of warnings from this line
}

int main() {
    return b(); //< I expect a warning on this line only
}

Поэтому я просто переименовал свой класс в класс OLD_A_NOT_TO_BE_USED. Я получаю предупреждение только при возврате b (); и если кто-то использовал a, он все равно получит предупреждение об устаревании.

person wincrasher    schedule 27.01.2015