Одним из способов реализации предупреждений об устаревании является создание предупреждений о вызовах устаревших функций, если только вы не вызываете из устаревшего контекста. Таким образом, унаследованный код может вызывать унаследованный код без выдачи предупреждений, которые составляют только шум.
Это разумное мышление, и оно отражено в реализациях, которые я вижу в GCC 4.2 (1) и Clang 4.0 (2) в OS X, а также в Clang 3.0 (3) в Ubuntu.
Однако, когда я компилирую с GCC 4.6 (4) в Ubuntu, я получаю устаревшие предупреждения для всех вызовов устаревших функций, независимо от контекста. Это регрессия в функциональности? Есть ли варианты компилятора, которые я могу использовать, чтобы получить другое поведение?
Пример программы:
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?
Поведение, которое вы видите в 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.
В 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"
— но теперь это действует до конца файла.
-Wno-deprecated
удалит все устаревшие предупреждения
Я сталкиваюсь с той же проблемой. Решение, которое пришло, заключается в следующем
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 (); и если кто-то использовал, они все равно получат устаревшее предупреждение.