Why is this an issue?
The "noreturn" attribute should be used to indicate that a function does not return to its caller: it may terminate the program, enter an infinite
loop, or throw an exception.
This attribute is typically used for functions that perform critical operations, such as exiting the program or handling an error condition. For
example, the "exit" function is marked with the "noreturn" attribute because it terminates the program and does not return to its caller.
Using this attribute allows the compiler to make some assumptions that can lead to optimizations. However, functions marked with the "noreturn"
attribute should not have a return statement because it leads to undefined behavior and unexpected results.
This rules equally applies to C++11 [[noreturn]]
notation or C11 _Noreturn
keyword notation. It raises an issue when the
attribute is incorrectly used.
How to fix it
There are two opposite approaches to fix this issue: remove the "noreturn" attribute or update the function to never return.
Code examples
Noncompliant code example
int global;
[[noreturn]]
void longRunningTask() {
while (true) {
// ...
if (global == 0) {
return; // Noncompliant: this function should not return.
}
}
}
Compliant solution
There are many ways to address the issue in the previous code snippet. Here are some examples.
It can be updated to never return:
[[noreturn]]
void longRunningTask() {
while (true) {
// ...
}
}
Or the "noreturn" attribute can be removed:
void longRunningTask() {
while (true) {
// ...
if (global == 0) {
return;
}
}
}
Or, in C++, the return statement can be turned into a throw expression:
[[noreturn]]
void longRunningTask() {
while (true) {
// ...
if (global == 0) {
throw std::runtime_error("invalid global state");
}
}
}
Resources
Documentation