web-dev-qa-db-ja.com

GCCは警告を黙らせるために「プラグマGCC診断」を尊重しません

最近、プロジェクトで-Wallを有効にしました。 GCC diagnostic を使用して昇格された警告からの出力を管理できるため、GCCが4.7以上(またはClang)のときに有効になります。それらをソースコードから管理し、notコマンドライン引数で管理します。 (コマンドラインを汚染したり、ライブラリのユーザーに必要なものを再発見したりすることは望んでいません)。

GCC 4.8および5.1では、-Wunused-variable-Wunused-value-Wunused-functionおよび-Wunknown-pragmasのGCC診断ブロックで無効にされた警告をキャッチしています。どちらのGCCも-fopenmpを受け入れ、それに応答して_OPENMPを定義しているため、-Wunknown-pragmasに応答して#prgam omp ...が表示されることはないと確信しています。 is無効、ただしis not不明)。

g++ -DNDEBUG -g2 -O3 -Wall -march=native -pipe -c nbtheory.cpp
nbtheory.cpp:655:0: warning: ignoring #pragma omp parallel [-Wunknown-pragmas]
  #pragma omp parallel
 ^
nbtheory.cpp:656:0: warning: ignoring #pragma omp sections [-Wunknown-pragmas]
   #pragma omp sections
 ^
...

この特定のケースでは、 file nbtheroy.cpp は、その警告の管理に役立つ次のガードを備えています(関連する部分のみが示されていますが、 GitHubリンクからすべてを表示できます) ):

// Defines GCC_DIAGNOSTIC_AWARE if GCC 4.7 or above.
#include <misc.h>
...

#if GCC_DIAGNOSTIC_AWARE
# pragma GCC diagnostic ignored "-Wunknown-pragmas"
#endif

...
Integer ModularRoot(const Integer &a, const Integer &dp, const Integer &dq,
                    const Integer &p, const Integer &q, const Integer &u)
{
    Integer p2, q2;
    #pragma omp parallel
        #pragma omp sections
        {
            #pragma omp section
                p2 = ModularExponentiation((a % p), dp, p);
            #pragma omp section
                q2 = ModularExponentiation((a % q), dq, q);
        }
    return CRT(p2, p, q2, q, u);
}
...

ファイルは*.cpp(事実上the翻訳単位)であるため、次のようになりますしないでください最初に#pragma GCC diagnostic Pushを実行し、最後に#pragma GCC diagnostic popを実行します。 (ただし、インクルードされるヘッダーファイルについてはこれを行います)。 (私たちはそれを試みましたが、助けにはなりませんでした)。

そして、これがGCC_DIAGNOSTIC_AWAREです(from misc.h ):

// Used to suppress some warnings in some header and implementation files.
//   Some platforms, like CentOS and OpenBSD, use old compilers that don't understand -Wno-unknown-pragma.
#define GCC_DIAGNOSTIC_AWARE ((__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7)) || defined(__clang__))

ブロックに#errorを追加するとエラーが発生するため、ガードが機能していることがわかります。また、警備員をコメントアウトして#pragma GCC diagnostic ignored "-Wunknown-pragmas"を呼び出すことは役に立ちません。最後に、それはClangで正常に動作します。

-Wunused-variable-Wunused-value-Wunused-functionなどの他の警告でも発生しています。私本当に重複の可能性があることを示唆しているように、コマンドラインを汚染したくありません。

GCC pragma diagnosticメカニズムを使用して、GCCで-Wallを使用しているときに警告が表示されないようにするにはどうすればよいですか?


関連、それを再現したい場合(そのGNUmakefileベースで、構成やautotoolsは必要ありません):

git clone https://github.com/weidai11/cryptopp.git cryptopp-warn
cd cryptopp-warn
make

[〜#〜] edit [〜#〜]:Clang以外の-Wallを無効にするパッチをチェックインしました。古い動作を再現したい場合は、次のようにします。

git clone https://github.com/weidai11/cryptopp.git cryptopp-warn
cd cryptopp-warn
export CXXFLAGS="-g2 -O3 -DNDEBUG -Wall"
make
26
jww

これは少なくともgccのバグのようです。次のコード:

#pragma GCC diagnostic ignored "-Wunknown-pragmas"
#pragma GCC diagnostic ignored "-Wuninitialized"

int fn(void) {
    #pragma xyzzy
    int x;
    return x;
}

int main (void) {
    return fn();
}

初期化されていないx値を無視しても問題はありませんが、プラグマについて不満があります(uninitializedプラグマがないと、予想どおりxの警告が生成されます)。

コマンドラインオプションを-Wall -Wno-unknown-pragmasに変更すると、問題なく無視されます。翻訳単位全体に適用したいので、特定のケースでは問題ありませんが、#pragmaメソッドから取得できる細かい制御はできません(機能した場合)。


GCCのバグレポートを上げに行きましたが、すでに存在していることがわかりました( #53431 )。

この特定のバグは-Wundefに関係していますが、コメントの1つのスニペットは、プリプロセッサに影響するすべてのバリアントに適用されることを示しています(強調のために少し変更されています)。

C++パーサーlexes(andpreprocesses)は、プラグマを処理する前に実行しますが、Cパーサーはプラグマを認識したとおりに処理します。

cp/parser.c:631のこれらのプラグマalsoを何らかの方法で解析する必要があります。おそらく、cp_parser_initial_pragmaの場合と同様のことを実行できますが、ループ内でプラグマ診断のみを処理できます。確かに、それを正しく行うには、試行錯誤が必要です。試してみたいと思って助けが必要な場合は、ここまたはメーリングリストで質問してください。

これが、-Wuninitializedで同じ問題が発生しない理由を説明しています。これは、前処理の最後にプラグマがアクティブ化された後、コンパイルプロセスの後の段階で検出されるためです。

したがって、よりタイムリーに修正された状態で(3年以上前に発生した)修正を確認したい場合は、GCCのBugzillaサイトを手間をかけて公開してみることをお勧めします。

14
paxdiablo