"unreachable code" warning in simple single-line function - c++

I have 220 "unreachable code" warnings in Boost.Variant, class boost::detail::variant::invoke_visitor:
template <typename T>
result_type internal_visit(T& operand, int)
{
return visitor_(operand);
}
.
boost_1_50_0\boost\variant\variant.hpp(859): warning C4702: unreachable code
line return visitor_(operand);.
First of all, how is this possible at all to have unreachable code in this simple single-line function? Which code is unreachable?
I cannot reproduce this warning in a simple case, seems because I don't understand what exactly causes it. The warning appeared after I implemented operator== for classes used in boost::variant.
Environment: VC++ 2010, Boost 1.50
EDIT:
the warning happens only in Release build (optimized), and only if I compare boost::variants. I use boost::variant with primitive and custom types. Custom types implements typical bool operator(CT const& lh, CT const& rh) as free functions.

I had this problem myself in VS 2017. If the compiler determines visitor_(T&) will always throw an exception, the "unreachable" part is the return. If you were to unwrap that into the following:
auto v = visitor_(operand);
return v;
The compiler would call out return v; as unreachable. In my case, I was using a Policy-based class and a NullPolicy threw exceptions. I ended up just removing the exception.
Fun fact: if you have LTCG on, you only get the error during the linking stage, so you don't even know where to start. Turning off LTCG but leaving on optimizations will at least let you narrow it down by making compilation of offending files fail.

Just in case someone else stumbles over the same thing: (I experienced this with MSVS 2017 v15.7.4)
class Widget
{
public:
void bar()
{
foo = 0; // C4702 here
}
void foobar()
{
return; // NOTE direct return here
bar();
}
private:
int foo;
};
This was in old code where someone had "commented out" the entire function foobar() leaving the original code for "future reference". (yes, source control is very hard to use)
Now in release mode the compiler inlined the function bar() which resulted in a C4702: unreachable code warning, but it indicated the first line of function bar() where seemingly nothing was wrong. (actually each line of code after the return; triggered the warning)

Related

How to prevent returning a pointer to a temporary variable?

On a recent bug hunt, I found an issue with returning a pointer to a member of a temporary variable. The offending (simplified) code was:
struct S {
S(int i) : i(i) {}
int i;
int* ptr() { return &i; }
};
int* fun(int i) { return S(i).ptr(); } // temporary S dies but pointer lives on
int main() {
int* p = fun(1);
return *p; // undefined
}
How to prevent this? GCC & Clang have -Waddress-of-temporary and -Wreturn-stack-address but they seem to loose trail because of ptr() acting as a middle man for the dirty deeds. They are only triggered when the pointer is taken directly:
int* fun(int i) { return &S(i).i; } // rightly fails to compile
My project also incorporates cppcheck in continuous integration but it also can't pick it up (raised here).
Which static analysis tool can prevent this class of bugs?
EDIT: GCC does pick it up since version 6.1.0 with -Wreturn-local-addr and (surprisingly) -O2 switched on.
I am a Cppcheck developer.
My project also incorporates cppcheck in continuous integration but it also can't pick it up.
interesting bug. This is the kind of bug that cppcheck wants to warn about. We have some related checks but this slipped through unfortunately.
Not really surprising given the regex nature of cppcheck.
I don't personally understand why some people say cppcheck is a regex tool.
It uses AST, context sensitive valueflow analysis, etc to detect bugs. So does GCC and Clang. Cppcheck is sometimes claimed to be a regex tool but GCC and Clang are not.

catch without try compiling successfully

The following code compiles successfully with g++ version 5.1.0. Notice the catch without a corresponding try in the member function foo::bar(). I was wondering if this syntax was legal and if so what effect it had?
struct foo
{
void bar()
{
}
catch (...)
{
}
};
int main ()
{
foo f;
f.bar();
return 0;
}
Originally seen in Catch block in constructor without try
The example you give,
struct foo
{
void bar()
{
}
catch (...)
{
}
};
… is not valid standard C++.
It might be a g++ language extension.
The catches in the question you linked to look like function catch blocks, except that also that requires a try keyword.
As others were quick to point out, the quoted code is not well-formed C++. It was allowed through due to an oversight in the rewritten C++ parser that's used in recent GCC 4/5/6 branches.
I filed this as GCC Bug/PR c++/71909. As can be seen there, commits have just been made to all 3 branches, to ensure that a function-catch block will only be accepted if a matching function-try block has already been encountered. A 3-day turnaround, that's pretty good :-)
Thanks to Richard for bringing this up!

Using generic operator->* as rvalue

The compilation process of:
template <typename T> T GetMember(const T STRUCT_T::* member)
{
STRUCT_T* pStruct = GetStruct();
...
// read value
T retVal = pStruct->*member; // compiler assertion here
ReleaseStruct();
return retVal;
}
ends due to compiler assertion when used with a non-basic type T:
Tool internal error:
Internal Error: [Front end]: assertion failed at:
"....\Translator\compiler_core\src\parser\edg\lower_il.c", line 13411
Shocked by the fact that IAR compiler's "lower_il.c" has at least 13,411 lines and non of them is a proper generic operator->*(), I found it even stranger that the following function do compile with a non-basic type T:
template <typename T> void SetMember(T STRUCT_T::* member, const T& value)
{
STRUCT_T* pStruct = GetStruct();
...
// write value
pStruct->*member = value; // no compiler assertion here
ReleaseStruct();
}
I guess the result of the generic operator is OK as lvalue but not as rvalue. Unconsting the parameter didn't help.
Any ideas of cause and solution?
We can tell from edg\lower_il.c that this is the EDG frontend, not a proprietary IAR parser. EDG is well-maintained and well-respected, and you can play with a newer version at http://gcc.godbolt.org/ . (Select ICC from the compiler menu.)
The filename suggests that it's dealing with a lower-level intermediate representation, not building the initial AST. There may be a problem translating the pointer-to-member access to more primitive operations. Or the flag might be appearing on the wrong line. Internal errors aren't always precise. An SSCCE would be better.
IAR service pack 6.70.2 solved the problem.

Are there any scenarios where C4172 Visual C++ warning should not be considered an error?

There's C4172 Visual C++ warning for cases when a function returns an address of a local or temporary or a reference to a local variable.
Something like this:
int& fun()
{
int var;
return var; //C4172
}
Now looks like it is a good idea to use #pragma warning to make Visual C++ treat C4172 as error and break compilation.
Are there any sane scenarios where C4172 is not actually an error?
I'm not sure why anyone would ever want to do this:
int * stackTester()
{
int dummy;
return &dummy;
}
bool stackGoesUp()
{
int dummy;
return stackTester() > &dummy;
}
But generally speaking, you should treat the warning like an error.
It is a level 1 warning, very hard to ignore. But the compiler is following language standards here, invoking UB is not forbidden. And it is a very common bug that too often does come to a good end. The pointed-to stack location stays stable as long as you don't make any function calls.
The best way to deal with this is to always turn warnings into errors. Compile with /WX, "Treat warnings as errors" setting in the IDE. If you then intentionally want to suppress a warning then #pragma warning makes it clear to everybody that something fishy is going on that was thought about and not an accident.
Unused code
class base
{
virtual blah& makeBlah()
}
class red : public base
{
blah& makeBlah() { return blah(); } // there are no red blahs, never called
}
class blue : public base
{
blah& makeBlah() { actual code to make a blah }
}

Can I tell the compiler to consider a control path closed with regards to return value?

Say I have the following function:
Thingy& getThingy(int id)
{
for ( int i = 0; i < something(); ++i )
{
// normal execution guarantees that the Thingy we're looking for exists
if ( thingyArray[i].id == id )
return thingyArray[i];
}
// If we got this far, then something went horribly wrong and we can't recover.
// This function terminates the program.
fatalError("The sky is falling!");
// Execution will never reach this point.
}
Compilers will typically complain at this, saying that "not all control paths return a value". Which is technically true, but the control paths that don't return a value abort the program before the function ends, and are therefore semantically correct. Is there a way to tell the compiler (VS2010 in my case, but I'm curious about others as well) that a certain control path is to be ignored for the purposes of this check, without suppressing the warning completely or returning a nonsensical dummy value at the end of the function?
You can annotate the function fatalError (its declaration) to let the compiler know it will never return.
In C++11, this would be something like:
[[noreturn]] void fatalError(std::string const&);
Pre C++11, you have compiler specific attributes, such as GCC's:
void fatalError(std::string const&) __attribute__((noreturn));
or Visual Studio's:
__declspec(noreturn) void fatalError(std::string const&);
Why don't you throw an exception? That would solve the problem and it would force the calling method to deal with the exception.
If you did manage to haggle the warning out some way or other, you are still left with having to do something with the function that calls getThingy(). What happens when getThingy() fails? How will the caller know? What you have here is an exception (conceptually) and your design should reflect that.
You can use a run time assertion in lieu of your fatalError routine. This would just look like:
Thingy& getThingy(int id)
{
for ( int i = 0; i < something(); ++i )
{
if ( thingyArray[i].id == id )
return thingyArray[i];
}
// Clean up and error condition reporting go here.
assert(false);
}