2012-12-03 19 views
5

tôi có mã tiếp theo:Tại sao g ++ không phát ra cảnh báo noexcept liên quan đến hàm dựng này khi bật `-fpic`?

#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; 
} 

Và với tùy chọn tiếp theo:
-fno-pic -fmessage-length=0 -std=c++0x -Wnoexcept
g ++ ném cảnh báo tiếp theo:

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] 

Nhưng tại sao khi tôi sử dụng -fpic thay vì -fno-picg++ không ném bất kỳ cảnh báo nào?

EDIT:
GCC phiên bản - 4.7.2

+0

Bạn đang sử dụng phiên bản gcc nào để biên dịch? –

+0

@kumar_m_kiran 4.7.2 – Arseniy

Trả lời

5

Cảnh báo không được ban hành trong trường hợp -fpic, bởi vì trình biên dịch giả định rằng các nhà xây dựng A::A() có thể ném.

Khi biên dịch mã PIC, GCC giả định rằng mọi tên chung có thể bị ghi đè bởi các ký hiệu từ các mô-đun khác. Do đó, nếu không có khai báo rõ ràng noexcept, GCC phải thận trọng giả định rằng một hàm như vậy có thể ném ngoại lệ, ngay cả khi nó có thể chứng minh tĩnh rằng phiên bản mà nó đang nhìn thấy bây giờ, không thể.

Để tham khảo, xem lỗi và bản vá đây http://gcc.gnu.org/bugzilla/show_bug.cgi?id=29323#c7 (mã đã thay đổi một chút từ đó, nhưng nó bắt đầu như thế này)

Một ví dụ, nơi ở trên là áp dụng:

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

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

Vì vậy, đây là lý do ngay lập tức "tại sao" không có cảnh báo. Điều gì sau đây là những gì tôi nghĩ về nó.

Tuy nhiên, C++ 11 nói:

7.1.2 Chức năng specifiers [dcl.fct.spec]

4 Một chức năng inline sẽ được xác định trong mỗi đơn vị dịch trong mà nó là odr-sử dụng và phải có định nghĩa giống hệt nhau trong mọi trường hợp (3.2).

tức là đối với các hàm nội tuyến, nếu hàm được xác định không ném, GCC có thể giả định rằng mọi khả năng ghi đè hàm như vậy cũng không thể ném. Trong trường hợp đó, GCC đang quá bảo thủ với các hàm nội tuyến và cả trong trường hợp thử nghiệm ban đầu và trong ví dụ trên với từ khóa inline không được chú trọng, GCC phải đưa ra cảnh báo ngay cả khi sử dụng -fpic/-fPIC.

+0

Xin chào và cảm ơn bạn đã trả lời. Nơi nào bạn nhận được điều này 'Khi biên dịch mã PIC, GCC giả định rằng mỗi tên toàn cầu có thể được ghi đè bởi các biểu tượng từ các mô-đun khác' Tôi có nghĩa là một số cuốn sách/nguồn? Vui lòng cung cấp liên kết. – Arseniy

+0

@Pepelac, nguồn là mã nguồn GCC :) Bằng cách này, hành vi này không phải là độc quyền cho mã PIC, nó cũng giống nhau cho các chức năng yếu và một số trường hợp khác. – chill

+0

Cảm ơn một lần nữa Tôi đã tìm thấy nơi nó được thực hiện trong mã GCC, nhưng tôi nghĩ rằng có lẽ bạn nhận được nó từ một số hướng dẫn sử dụng) – Arseniy

Các vấn đề liên quan