非推奨の警告を実装する1つの方法は、非推奨のコンテキストから呼び出していない限り、非推奨の関数の呼び出しで警告を生成することです。このように、レガシーコードは、ノイズにしかならない警告を生成することなく、レガシーコードを呼び出すことができます。
これは合理的な考え方であり、OS XのGCC 4.2(1)とClang 4.0(2)、UbuntuのClang 3.0(3)で見られる実装に反映されています。
ただし、UbuntuでGCC 4.6(4)を使用してコンパイルすると、コンテキストに関係なく、非推奨の関数のすべての呼び出しに対して非推奨の警告が表示されます。これは機能の後退ですか?他の動作を得るために使用できるコンパイラオプションはありますか?
サンプルプログラム:
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からの出力(はい、同じ警告が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.2と同じ出力が得られることをGCC 4.6に納得させるにはどうすればよいですか?
GCC 4.2で見られる動作は、GCCへのApple固有のパッチが原因です。 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をビルドすることができます。または、これをFSF GCC bugzillaの機能リクエストとして報告することもできます。
-Wno-deprecated
は非推奨の警告をすべて削除します
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"
-しかし、これはファイルの終わりまで有効です。
同じ問題が発生します。解決策は次のとおりです
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()でのみ警告が表示されます。誰かがを使用していた場合でも、非推奨の警告が表示されます。