I use the clang analyzer to check my C++ code for bugs and errors. I have the following construct:
#include <cstdlib>
#include <iostream>
double
somethingThatMayThrow() throw (std::exception)
{
if( rand() % 2 ) {
throw std::exception();
}
return 5.0;
}
int
main()
{
double value = 2.0;
try {
value = somethingThatMayThrow();
} catch( const std::exception& ) {
std::cout << "oops" << std::endl;
}
double someOtherValue = value + 1.0;
std::cout << someOtherValue << std::endl;
return 0;
}
The analyzer now complains that the initial value of variable value
is never read. However, it is clear that the value is used in the last line if and only if there is an exception in the try block. Is this understanding correct, and am I looking at a bug in the analyzer? Or am I missing something here?
How does the standard define this behavior? What happens to the left hand side of the assignment if the right hand side throws?
The screenshot below shows the actual code that the analyzer complained about, which has the same structure as my example above:
The analyser is wrong. You are right.
The analyser could be right if the code inside the try block can never throw std::exception
s or objects of a type derived from it (e.g. with noexcept
, or with only objects of other types being thrown).
Either way, your interpretation is correct: the assignment will never occur if evaluation of the value-to-be throws. As such, the original value will remain intact.