Visual C++では、 #pragma warning (disable: ...)
を使用できます。また、GCCでは ファイルコンパイラフラグごとのオーバーライド を使用できることもわかりました。 「次の行」に対して、またはGCCを使用してコードの領域の周りにプッシュ/ポップセマンティクスでこれを行うにはどうすればよいですか。
このように見えます できます 。追加されたGCCのバージョンを判別することはできませんが、2010年6月より前の時点でした。
次に例を示します。
#pragma GCC diagnostic error "-Wuninitialized"
foo(a); /* error is given for this one */
#pragma GCC diagnostic Push
#pragma GCC diagnostic ignored "-Wuninitialized"
foo(b); /* no diagnostic for this one */
#pragma GCC diagnostic pop
foo(c); /* error is given for this one */
#pragma GCC diagnostic pop
foo(d); /* depends on command line options */
すべてを無効にするために、これは警告を無効にするtemporarilyの例です。
#pragma GCC diagnostic Push
#pragma GCC diagnostic ignored "-Wunused-result"
write(foo, bar, baz);
#pragma GCC diagnostic pop
詳細については、 診断プラグマに関するGCCドキュメント を確認してください。
TL; DR:動作する場合は、__attribute__
などの指定子を避けるか、使用します。それ以外の場合は_Pragma
。
これは私のブログ記事の短いバージョンです GCCとClangでの警告の抑制 。
次のMakefile
を考慮してください
CPPFLAGS:=-std=c11 -W -Wall -pedantic -Werror
.PHONY: all
all: puts
次のputs.c
ソースコードをビルドするため
#include <stdio.h>
int main(int argc, const char *argv[])
{
while (*++argv) puts(*argv);
return 0;
}
argc
が使用されておらず、設定がハードコア(-W -Wall -pedantic -Werror
)であるため、コンパイルされません。
できることは5つあります。
__attribute__
などの宣言指定子を使用します_Pragma
を使用#pragma
を使用最初の試みは、警告を取り除くためにソースコードを改善できるかどうかを確認することです。この場合、argc
は!*argv
(最後の要素の後のNULL
)と冗長であるため、そのためだけにアルゴリズムを変更する必要はありません。
__attribute__
などの宣言指定子を使用する#include <stdio.h>
int main(__attribute__((unused)) int argc, const char *argv[])
{
while (*++argv) puts(*argv);
return 0;
}
運がよければ、標準は_Noreturn
のように、状況に応じた指定子を提供します。
__attribute__
は独自のGCC拡張機能であり(Clangおよびarmcc
などの他のコンパイラーでもサポートされています)、他の多くのコンパイラーでは理解されません。移植可能なコードが必要な場合は、__attribute__((unused))
をマクロ内に配置します。
_Pragma
演算子_Pragma
は、#pragma
の代わりに使用できます。
#include <stdio.h>
_Pragma("GCC diagnostic Push")
_Pragma("GCC diagnostic ignored \"-Wunused-parameter\"")
int main(int argc, const char *argv[])
{
while (*++argv) puts(*argv);
return 0;
}
_Pragma("GCC diagnostic pop") \
_Pragma
演算子の主な利点は、マクロ内に配置できることです。これは、#pragma
ディレクティブでは不可能です。
欠点:宣言ベースではなく行ベースで動作するため、ほぼ戦術的な核です。
_Pragma
演算子はC99で導入されました。
#pragma
ディレクティブ。ソースコードを変更して、コードの領域、通常は関数全体の警告を抑制することができます。
#include <stdio.h>
#pragma GCC diagnostic Push
#pragma GCC diagnostic ignored "-Wunused-parameter"
int main(int argc, const char *argv[])
{
while (*++argc) puts(*argv);
return 0;
}
#pragma GCC diagnostic pop
欠点:宣言ベースではなく行ベースで動作するため、ほぼ戦術的な核です。
同様の構文が clang に存在することに注意してください。
次の行をMakefile
に追加して、puts専用の警告を抑制することができます。
CPPFLAGS:=-std=c11 -W -Wall -pedantic -Werror
.PHONY: all
all: puts
puts.o: CPPFLAGS+=-Wno-unused-parameter
これはおそらく、特定のケースでは望んでいませんが、同様の状況にある他の読み取りに役立つ場合があります。
#define DIAG_STR(s) #s
#define DIAG_JOINSTR(x,y) DIAG_STR(x ## y)
#ifdef _MSC_VER
#define DIAG_DO_PRAGMA(x) __pragma (#x)
#define DIAG_PRAGMA(compiler,x) DIAG_DO_PRAGMA(warning(x))
#else
#define DIAG_DO_PRAGMA(x) _Pragma (#x)
#define DIAG_PRAGMA(compiler,x) DIAG_DO_PRAGMA(compiler diagnostic x)
#endif
#if defined(__clang__)
# define DISABLE_WARNING(gcc_unused,clang_option,msvc_unused) DIAG_PRAGMA(clang,Push) DIAG_PRAGMA(clang,ignored DIAG_JOINSTR(-W,clang_option))
# define ENABLE_WARNING(gcc_unused,clang_option,msvc_unused) DIAG_PRAGMA(clang,pop)
#Elif defined(_MSC_VER)
# define DISABLE_WARNING(gcc_unused,clang_unused,msvc_errorcode) DIAG_PRAGMA(msvc,Push) DIAG_DO_PRAGMA(warning(disable:##msvc_errorcode))
# define ENABLE_WARNING(gcc_unused,clang_unused,msvc_errorcode) DIAG_PRAGMA(msvc,pop)
#Elif defined(__GNUC__)
#if ((__GNUC__ * 100) + __GNUC_MINOR__) >= 406
# define DISABLE_WARNING(gcc_option,clang_unused,msvc_unused) DIAG_PRAGMA(GCC,Push) DIAG_PRAGMA(GCC,ignored DIAG_JOINSTR(-W,gcc_option))
# define ENABLE_WARNING(gcc_option,clang_unused,msvc_unused) DIAG_PRAGMA(GCC,pop)
#else
# define DISABLE_WARNING(gcc_option,clang_unused,msvc_unused) DIAG_PRAGMA(GCC,ignored DIAG_JOINSTR(-W,gcc_option))
# define ENABLE_WARNING(gcc_option,clang_option,msvc_unused) DIAG_PRAGMA(GCC,warning DIAG_JOINSTR(-W,gcc_option))
#endif
#endif
これは、gcc、clang、msvcのトリックを実行するはずです。
以下を使用して呼び出すことができます:
DISABLE_WARNING(unused-variable,unused-variable,42)
[.... some code with warnings in here ....]
ENABLE_WARNING(unused-variable,unused-variable,42)
https://gcc.gnu.org/onlinedocs/cpp/Pragmas.html 、 http://clang.llvm.org/docs/UsersManual.html#controlling-diagnostics-を参照via-pragmas and https://msdn.Microsoft.com/de-DE/library/d9x1s805.aspx 詳細については
これらの種類のプラグマをgccで使用するには、少なくともバージョン4.02が必要です。バージョンに関するmsvcおよびclangについてはわかりません。
GccのPush popプラグマ処理が少し壊れているようです。警告を再度有効にしても、DISABLE_WARNING/ENABLE_WARNINGブロック内にあったブロックの警告が表示されます。 gccの一部のバージョンでは機能しますが、一部のバージョンでは機能しません。
#pragma GCC diagnostic ignored "-Wformat"
「-Wformat」を警告フラグの名前に置き換えます。
私の知る限り、このオプションにプッシュ/ポップセマンティクスを使用する方法はありません。
ROSヘッダーのような外部ライブラリでも同じ問題がありました。より厳密なコンパイルのために、CMakeLists.txtで次のオプションを使用するのが好きです。
set(CMAKE_CXX_FLAGS "-std=c++0x -Wall -Wextra -Wstrict-aliasing -pedantic -Werror -Wunreachable-code ${CMAKE_CXX_FLAGS}")
ただし、これを行うと、外部に含まれるライブラリにもあらゆる種類のペダンティックエラーが発生します。解決策は、外部ライブラリを含める前にすべてのペダンティック警告を無効にして、次のように再度有効にすることです。
//save compiler switches
#pragma GCC diagnostic Push
#pragma GCC diagnostic ignored "-Wpedantic"
//Bad headers with problem goes here
#include <ros/ros.h>
#include <sensor_msgs/LaserScan.h>
//restore compiler switches
#pragma GCC diagnostic pop
警告を黙らせるのではなく、gccスタイルは通常、標準C構成体または__attribute__
拡張を使用して、コンパイラーにユーザーの意図を通知します。たとえば、条件として使用される割り当てに関する警告は、割り当てを括弧で囲むことで抑制されます。つまり、if ((p=malloc(cnt)))
の代わりにif (p=malloc(cnt))
です。未使用の関数引数に関する警告は、覚えていない奇妙な__attribute__
によって、または自己割り当てなどによって抑制できます。しかし、一般に、正しいコードで発生するものに対して警告を生成する警告オプションをグローバルに無効にすることをお勧めします。
IARでこれを行う方法を探しているこのページを見つけた人のために、これを試してください:
#pragma diag_suppress=Pe177
void foo1( void )
{
/* The following line of code would normally provoke diagnostic
message #177-D: variable "x" was declared but never referenced.
Instead, we have suppressed this warning throughout the entire
scope of foo1().
*/
int x;
}
#pragma diag_default=Pe177
http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0472m/chr1359124244797.html を参照してください。
私は質問がGCCについてであることを知っていますが、他のおよび/または複数のコンパイラでこれを行う方法を探している人のために...
Hedley をご覧ください。これは、私が書いたパブリックドメインの単一のC/C++ヘッダーで、lotを実行します君は。この記事の最後に、これらすべてにHedleyを使用する方法について簡単なセクションを示します。
#pragma warning (disable: …)
には、ほとんどのコンパイラで同等のものがあります。
#pragma warning(disable:4996)
#pragma GCC diagnostic ignored "-W…"
ここで、省略記号は警告の名前です。 e.g。、#pragma GCC diagnostic ignored "-Wdeprecated-declarations
。#pragma clang diagnostic ignored "-W…"
。構文は基本的にGCCと同じであり、警告名の多くは同じです(ただし、多くは同じではありません)。#pragma warning(disable:1478 1786)
。diag_suppress
プラグマがあります:#pragma diag_suppress 1215,1444
diag_suppress
プラグマがあります:pragma diag_suppress 1291,1718
error_messages
プラグマがあります。面倒なことに、警告はCとC++コンパイラで異なります。これらは両方とも基本的に同じ警告を無効にします:#pragma error_messages(off,E_DEPRECATED_ATT,E_DEPRECATED_ATT_MESS)
#pragma error_messages(off,symdeprecated,symdeprecated2)
diag_suppress
も使用しますが、構文は異なります。一部の警告番号は同じですが、私は別の警告番号を付けました:#pragma diag_suppress=Pe1444,Pe1215
#pragma warn(disable:2241)
ほとんどのコンパイラーでは、コンパイラーのバージョンを無効にする前に確認することをお勧めします。そうしないと、別の警告がトリガーされてしまいます。たとえば、GCC 7は-Wimplicit-fallthrough
警告のサポートを追加したため、7より前にGCCを気にする場合は、次のようなことを行う必要があります。
#if defined(__GNUC__) && (__GNUC__ >= 7)
# pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
#endif
XL C/C++およびarmclangの新しいバージョンなどのclangおよびclangベースのコンパイラーの場合、コンパイラーが__has_warning()
マクロを使用して特定の警告を認識しているかどうかを確認できます。
#if __has_warning("-Wimplicit-fallthrough")
# pragma clang diagnostic ignored "-Wimplicit-fallthrough"
#endif
もちろん、__has_warning()
マクロが存在するかどうかも確認する必要があります。
#if defined(__has_warning)
# if __has_warning("-Wimplicit-fallthrough")
# pragma clang diagnostic ignored "-Wimplicit-fallthrough"
# endif
#endif
あなたは次のようなことをしたくなるかもしれません
#if !defined(__has_warning)
# define __has_warning(warning)
#endif
したがって、__has_warning
をもう少し簡単に使用できます。 Clangは、マニュアルの__has_builtin()
マクロについても同様のことを提案しています。 これをしないでください。他のコードは__has_warning
をチェックし、存在しない場合はコンパイラーのバージョンをチェックし、__has_warning
を定義するとコードを壊します。これを行う正しい方法は、名前空間にマクロを作成することです。例えば:
#if defined(__has_warning)
# define MY_HAS_WARNING(warning) __has_warning(warning)
#else
# define MY_HAS_WARNING(warning) (0)
#endif
その後、次のようなことができます
#if MY_HAS_WARNING(warning)
# pragma clang diagnostic ignored "-Wimplicit-fallthrough"
#Elif defined(__GNUC__) && (__GNUC__ >= 7)
# pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
#endif
多くのコンパイラは、スタックに警告をプッシュおよびポップする方法もサポートしています。たとえば、これにより、コードの1行のGCCでの警告が無効になり、以前の状態に戻ります。
#pragma GCC diagnostic Push
#pragma GCC diagnostic ignored "-Wdeprecated"
call_deprecated_function();
#pragma GCC diagnostic pop
もちろん、コンパイラー間で構文について多くの合意はありません。
#pragma GCC diagnostic Push
/#pragma GCC diagnostic pop
#pragma clang diagnostic Push
/#pragma diagnostic pop
#pragma warning(Push)
/#pragma warning(pop)
#pragma warning(Push)
/#pragma warning(pop)
#pragma Push
/#pragma pop
#pragma diag_Push
/#pragma diag_pop
#pragma warning(Push)
/#pragma warning(pop)
メモリが機能する場合、GCCの非常に古いバージョン(3.x、IIRCなど)では、Push/popプラグマは関数のoutsideでなければなりませんでした。
ほとんどのコンパイラでは、C99で導入された_Pragma
を使用して、マクロの背後にあるロジックを隠すことができます。非C99モードでも、ほとんどのコンパイラは_Pragma
;をサポートしています。大きな例外はMSVCで、これには独自の__pragma
キーワードと異なる構文があります。標準の_Pragma
は文字列を取りますが、Microsoftのバージョンはそうではありません。
#if defined(_MSC_VER)
# define PRAGMA_FOO __pragma(foo)
#else
# define PRAGMA_FOO _Pragma("foo")
#endif
PRAGMA_FOO
前処理された後、おおよそ同等です
#pragma foo
これによりマクロを作成できるため、次のようなコードを記述できます
MY_DIAGNOSTIC_Push
MY_DIAGNOSTIC_DISABLE_DEPRECATED
call_deprecated_function();
MY_DIAGNOSTIC_POP
そして、マクロ定義のallいバージョンチェックをすべて隠します。
コードをきれいに保ちながら、このようなことを移植可能にする方法の仕組みを理解したので、私のプロジェクトの1つである Hedley の機能を理解しました。大量のドキュメントを掘り下げたり、テストできる限り多くのコンパイラーのバージョンをインストールしたりする代わりに、Hedley(単一のパブリックドメインC/C++ヘッダー)をインクルードして、それを実行できます。例えば:
#include "hedley.h"
HEDLEY_DIAGNOSTIC_Push
HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
call_deprecated();
HEDLEY_DIAGNOSTIC_POP
GCC、clang、ICC、PGI、MSVC、TI、IAR、ODS、Pelles、およびその他の非推奨関数の呼び出しに関する警告を無効にします(Hedleyを更新するときにこの回答を更新することはおそらくありません)。そして、動作することが知られていないコンパイラーでは、マクロは何も前処理されないため、コードはどのコンパイラーでも動作し続けます。もちろん、HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
は、Hedleyが知っている唯一の警告ではなく、すべてのHedleyが実行できる警告を無効にしているわけではありませんが、うまくいけばアイデアが得られます。