2016-07-27 263 views
1

在我的工作場所,我們有noreturn屬性的不同內部名稱。假設它是INTERNAL_DONT_RETURN錯誤:函數聲明'noreturn'不應該返回

我寫一個類的成員函數,我這樣做

INTERNAL_DONT_RETURN void foo() const 
{ 
    if(!*this) 
    { 
     throw CoolException(); 
    } 
    m_call_throw(); 
} 

這m_call_throw()是一個私有類成員std::function<void()>m_call_throw它獲取在類的構造函數的拉姆達填充。這拉姆達什麼也不做,但

m_call_throw([uncoolID]() { throw UncoolException(uncoolID); })

現在兩個,GCC-4.9.3和鐺給了我下面的警告

error: function declared 'noreturn' should not return [-Werror,-Winvalid-noreturn] } ^

我已經諮詢thisthis的問題,但他們沒有解釋上述警告的原因。

1)編譯器是否像here那樣隱式添加return

2)即使當我拋出異常,爲什麼編譯器相信我的函數將返回?

3)noreturn attribute提到

The noreturn keyword does not affect the exceptional path when that applies: a noreturn-marked function may still return to the caller by throwing an exception or calling longjmp.

這是有關我的問題?

+0

請提供一個[MCVE] –

回答

6

但你確實回報!如果if語句爲false,則返回該函數結尾的下降。你可能知道這永遠不會發生,因爲m_call_throw()永遠不會返回(是嗎?),但編譯器顯然不理解這個邏輯。

m_call_throw()標記爲noreturn?如果沒有,請添加它。如果編譯器沒有提到,那麼你可以在函數的末尾添加一個額外的拋出,你知道它永遠不會到達,但應該使警告無效。

0

那是因爲您的foo返回或至少似乎返回

當一個函數noreturn聲明,那麼該函數不能返回:

void Foo() __attribute__((noreturn)); 

void Foo() 
{ 
    // The application will exit, without returning. 
    exit(0); 
} 

int main() 
{ 
    Foo(); 
} 

你知道你的m_call_throw會不回來,但是編譯器不會。

於是明確告訴編譯它並不可能幫助如下:

void Foo() __attribute__((noreturn)); 
void m_call_throw() __attribute__((noreturn)); 

void Foo() 
{ 
    // Ok, no return huh? 
    m_call_throw(); 
} 

現場演示是here

1

編譯器不能證明函數總是會拋出。這不是一個錯誤 - 總會有一些編譯器無法證明的情況。

是否應該警告你是一個有趣的問題。警告你的意思是它有時會報告一個不存在的錯誤;不警告你意味着它有時會錯過一個真正的錯誤。

您可以很容易地使警告非致命,或以多種方式使其沉默。禁用此特定文件,或者在末尾添加對abort的呼叫。每種情況下都有權衡,但這就是生活。

如果你可以從lambda/std :: function切換到普通的成員函數,只要這樣做,並使其成爲noreturn。唉,你不能有noreturn功能類型或noreturnstd::functionnoreturn lambda,這是恕我直言,在語言中的錯誤。

+0

+1,以補充我們不能具有noreturn函數類型或noreturn std ::函數或noreturn lambda – Recker