3

Below is some code where the compilers partially detect mismatch between the method declaration (i.e. with 'noexcept' specifier) and the method implementation.

The compilers report a warning for the method "bazExcept()" but fail to report anything for "baz()". But, I'm expecting warning in both cases because "bazSub()" may throw exception & "baz()" explicitly states to not throw exception.

Is that a work in progress (i.e. later compiler versions will trap that case) or something I misunderstood with 'noexcept' usage?

// Tested with C++11 & C++17
// Tested with msvc 19, gcc 9 & clang 9
// Tested using https://godbolt.org/

// Specifier 'noexcept(false)' (same as no specifier) i.e. may throw exceptions.
void bar() noexcept(false) {}

// No specifier 'noexcept' means 'noexcept(false)' i.e. may throw exceptions.
void bazSub() { throw 42; }

// Specifier 'noexcept' means 'noexcept(true)' i.e. do not throw exceptions.
// Note: Compilers do not detect the problem i.e. bazSub may throw exception.
void baz() noexcept { bazSub(); }

// Specifier 'noexcept' means 'noexcept(true)' i.e. must not throw exceptions.
// Note: Compilers generate a warning.
void bazExcept() noexcept { throw 42; }

int main() {return 1;}

Thanks for your help.

  • "*I'm expecting warning in both cases*" Why though? From what I can tell, the warning is not required, so you shouldn't be expecting one. – Nikos C. Mar 05 '20 at 15:31
  • @TheArquitect How does it matter whether `noexcept` is used on a free function or a member function? – walnut Mar 05 '20 at 17:19
  • 1
    @walnut There are two good reasons for the use of noexcept: First, an exception specifier documents the behaviour of the function. If a function is specified as noexcept, it can be safely used in a non-throwing function. Second, it is an optimisation opportunity for the compiler. – TheArchitect Mar 05 '20 at 17:46
  • 1
    @TheArquitect You misunderstood my question. I wanted clarification on what you meant with your first comment. `noexcept` on a free function works the same as on a member function, so I don't understand what your first comment is trying to say. – walnut Mar 05 '20 at 17:57
  • @TheArquitect That's exactly why I try to constantly use the 'noexcept' specifier. – Patrick Hodoul Mar 05 '20 at 19:39

1 Answers1

1

Why compilers fail to detect a 'noexcept' usage mismatch?

Because they are not required to. Compilers act according to the standard.

C++ draft in except#spec-5:

Whenever an exception is thrown and the search for a handler encounters the outermost block of a function with a non-throwing exception specification, the function std​::​terminate is called.

Followed by important note:

An implementation is not permitted to reject an expression merely because, when executed, it throws or might throw an exception from a function with a non-throwing exception specification.

Compilers are not permitted to reject throwing from noexcept function and throwing in a noexcept function just calls std::terminate.

KamilCuk
  • 120,984
  • 8
  • 59
  • 111
  • The runtime behavior is perfectly documented and useful. Having compiler warning support for 'noexcept' is great but limitations decrease its relevance (as it could lead to code inconsistencies). On the other hand, the 'const' specifier (i.e. on a class member function) has a consistent compiler support making its usage extremely valuable. Why is there a compiler support difference between 'noexcept' & 'const' specifiers? – Patrick Hodoul Mar 05 '20 at 19:53
  • Sorry, I do not follow. What is the "compiler support" for `const`? I think that if you implement a warning for throwing in noexcept function for gcc, there's a good chance of merging. – KamilCuk Mar 05 '20 at 19:55
  • I hope that the example below better explains my point: `struct MyStruct { void barSub() {} void bar() const { barSub(); } };` There is a compilation failure on `bar()` implementation because `barSub()` is not `const`. My question is about having the same kind of behavior for `noexcept` with a warning. – Patrick Hodoul Mar 05 '20 at 23:13
  • Well, compilers follow the standard. It's not "compiler support", it's what the standard says. So well, the interpretation could be that the people that create the C++ don't agree with you, they think that such compilation failure is not needed with `noexcept`. You could search for the pull request that introduced `noexcept` keyword in C++ standard, there's a good chance there will be an explanation. – KamilCuk Mar 05 '20 at 23:14
  • You could search the [wg21 mailing list](http://www.open-std.org/jtc1/sc22/wg21/docs/mailings/) for the PR with `noexcept`. – KamilCuk Mar 05 '20 at 23:22