5

次のコードがあります:

#include <exception>
#include <cstdlib>

void g() { throw 1; }
void (*p)() = g;

template <class T>
void f(T) noexcept (noexcept (T())) // warning 1
{
  p();
}

struct A { A() { } };           // warning 2

int main()
{
  try { f(A()); } catch (int) { }
  return 1;
}

次のオプションを使用すると、
-fno-pic -fmessage-length=0 -std=c++0x -Wnoexcept
g++ は次の警告をスロー します。

noexcept03.C:16:6: warning: noexcept-expression evaluates to 'false' because of a call to 'A::A()' [-Wnoexcept]
noexcept03.C:21:12: warning: but 'A::A()' does not throw; perhaps it should be declared 'noexcept' [-Wnoexcept]

しかし、-fpic代わりに使用すると-fno-pic g++警告がスローされないのはなぜですか?

編集:
GCC バージョン - 4.7.2

4

1 に答える 1

5

この場合、コンパイラはコンストラクターがスローできる-fpicと想定しているため、警告は発行されません。A::A()

PIC コードをコンパイルするとき、GCC はすべてのグローバル名が他のモジュールからのシンボルによって上書きされる可能性があると想定します。したがって、明示的なnoexcept宣言がない場合、GCC は保守的に、そのような関数が例外をスローできると想定する必要があります。たとえ、現在表示されているバージョンではスローできないことを静的に証明できたとしてもです。

参考までに、こちらのバグとパッチを参照してください

上記が適用される例:

/* inline */ int f() { return 0; }

int g() noexcept (noexcept(f())) { return f() + 1; }

したがって、これが「なぜ」警告がない直接の理由です。以下は、それについて私が思うことです。

ただし、C++11 は次のように述べています。

7.1.2 関数指定子 [dcl.fct.spec]

4 インライン関数は、それが ODR で使用されるすべての翻訳単位で定義され、すべての場合でまったく同じ定義を持つものとします(3.2)。

つまり、インライン関数の場合、関数がスローされないと判断された場合、GCC は、そのような関数のすべての潜在的なオーバーライドもスローできないと想定できます。

その意味で、GCC はインライン関数に対して過度に保守的であり、元のテスト ケースと上記のinlineキーワードのコメントを外した例の両方で、GCC は が使用されている場合でも警告を発行する必要-fpic/-fPICがあります。

于 2012-12-03T15:21:25.187 に答える