10

I've implemented C++ bindings for some C library. The library API calls can fail, but obviously can't throw anything; and my bindings are, for the purposes of this question, all inline.

Now, the compiler can figure out, for most of my inlined functions/methods, that an exception can't be thrown; for example, suppose I have:

bool foo() { 
    auto result = wrapped_lib_foo(); 
    return some_constexpr_nothrow_cond(result); 
}

should I mark such functions/methods with noexcept?

Notes:

einpoklum
  • 118,144
  • 57
  • 340
  • 684
  • Comments are not for extended discussion; this conversation has been [moved to chat](http://chat.stackoverflow.com/rooms/158969/discussion-on-question-by-einpoklum-add-noexcept-on-otherwise-non-throwing-inlin). – Andy Nov 14 '17 at 13:50

2 Answers2

5

even if wrapped_lib_foo is a extern "C" function, the compiler has no way of knowing that somewhere down the stack wrapped_lib_foo never throws unless you tell it explicitly.

Then there is also that fact that marking the function noexcept explicitly informs your audience that the function does not throw.

So yes noexcept is a good idea.

doron
  • 27,972
  • 12
  • 65
  • 103
  • Well, that's also "true" of a `noexcept` function. It might still throw. But - are you saying that C++ compilers treat extern C funcitons as if they may _throw_ ? – einpoklum Nov 13 '17 at 11:37
  • MSVC has flags to configure this - it can assume C functions can throw. And GCC generates exception-handling information even for pure C code: https://stackoverflow.com/questions/26300819/why-gcc-compiled-c-program-needs-eh-frame-section –  Nov 13 '17 at 12:21
  • 2
    @einpoklum `extern "C"` functions may be defined in C++, and all C++ language features are available then. But even if `extern "C"` functions are defined in C, they may call back into C++ code through a function pointer or another `extern "C"` function. –  Nov 13 '17 at 13:03
  • Re the edit: a `noexcept` function that throws is not a compiler error. – Oktalist Nov 13 '17 at 16:35
4

I think this is good practice to add "noexcept", when you know a function doesn't throw. It is because a C function can throw, if it calls back into C++.

Whether this calling back to C++ and throw is allowed, seems to be compiler dependent. I've checked two compilers:

MSVC: has an option, /EHs, which:

The exception-handling model that catches C++ exceptions only and tells the compiler to assume that functions declared as extern "C" may throw an exception.

So, if this option is specified, then the compiler assumes that a C function can throw.

GCC: here's the documentation of -fexceptions:

Enable exception handling. Generates extra code needed to propagate exceptions. For some targets, this implies GCC generates frame unwind information for all functions, which can produce significant data size overhead, although it does not affect execution. If you do not specify this option, GCC enables it by default for languages like C++ that normally require exception handling, and disables it for languages like C that do not normally require it. However, you may need to enable this option when compiling C code that needs to interoperate properly with exception handlers written in C++. You may also wish to disable this option if you are compiling older C++ programs that don’t use exception handling.

So, this implies that with -fexceptions, GCC compiles C code which can throw. Note, however: when calling a C function, the compiler doesn't know, whether the C code was compiled with -fexceptions, or not. So it has to assume, that it was. So, it seems that GCC must assume, that a C code can throw (the other possible way could be that -fexception would need to be specified for C++ code for telling the compiler that a called C code can throw, but doc of -fexceptions doesn't say anything like this).

Note: for GCC, throwing from a call stack, where a C function is involved, works even without the C code compiled with -fexceptions currently.

geza
  • 28,403
  • 6
  • 61
  • 135
  • 1
    What happens with GCC when you don't specify `-fexceptions` and compile C++ code caling extern C functions, though? – einpoklum Nov 13 '17 at 12:33
  • @einpoklum: in my experience, it works. So the "you may need to enable" part means that you don't need to enable. But it may change in the future. But knowing, how exception handling works with gcc, this would mean ABI change, I think. Note: you would need to use `-fexceptions` for compiling C code, not C++. For C++, exceptions are enabled by default. – geza Nov 13 '17 at 12:41