2016-07-27 7 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] } ^

Я уже консультировалась this и this вопрос, но ни один из них не объяснил причина вышеупомянутого предупреждения.

1) Является ли компилятор неявным добавлением return, как описано here?

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-statement является ложным. Вы можете знать, что этого никогда не может случиться, потому что 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. В каждом случае есть компромиссы, но это жизнь.

Если вы можете переключиться с функции лямбда/std :: на нормальную функцию-член, просто сделайте это и сделайте это noreturn. Увы, у вас не может быть типа функции noreturn или noreturnstd::function или noreturn lambda, что является ИМХО ошибкой на этом языке.

+0

+1 для добавления, что мы не можем иметь (пока) тип функции noreturn или noreturn std :: function или noreturn lambda – Recker

Смежные вопросы