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 必须保守地假设这样的函数可以抛出异常,即使它可以静态地证明它现在看到的版本不能。

作为参考,请参阅此处的错误和补丁http://gcc.gnu.org/bugzilla/show_bug.cgi?id=29323#c7(此后代码发生了一些变化,但开始时是这样的)

一个例子,上面适用:

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

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

所以,这就是“为什么”没有警告的直接原因。以下是我的想法。

然而,C++11 说:

7.1.2 函数说明符 [dcl.fct.spec]

4 内联函数应在使用它的每个翻译单元中定义,并且在每种情况下都应具有完全相同的定义(3.2)。

即对于内联函数,如果确定一个函数不抛出,GCC 可以假设这样一个函数的每个潜在覆盖也不能抛出。

从这个意义上说,GCC 对内联函数过于保守,无论是在原始测试用例中还是在上面未inline注释关键字的示例中,GCC 都应该发出警告,即使在-fpic/-fPIC使用时也是如此。

于 2012-12-03T15:21:25.187 回答