I have legacy C++ code that I'm supposed to remove unused code from. The problem is that the code base is large.
How can I find out which code is never called/never used?
There are two varieties of unused code:
- the local one, that is, in some functions some paths or variables are unused (or used but in no meaningful way, like written but never read)
- the global one: functions that are never called, global objects that are never accessed
For the first kind, a good compiler can help:
-Wunused(GCC, Clang) should warn about unused variables, Clang unused analyzer has even been incremented to warn about variables that are never read (even though used).
-Wunreachable-code(GCC) should warn about local blocks that are never accessed (it happens with early returns or conditions that always evaluate to true)
- there is no option I know of to warn about unused
catchblocks, because the compiler generally cannot prove that no exception will be thrown.
For the second kind, it's much more difficult. Statically it requires whole program analysis, and even though link time optimization may actually remove dead code, in practice the program has been so much transformed at the time it is performed that it is near impossible to convey meaningful information to the user.
There are therefore two approaches:
- The theoretic one is to use a static analyzer. A piece of software that will examine the whole code at once in great detail and find all the flow paths. In practice I don't know any that would work here.
- The pragmatic one is to use an heuristic: use a code coverage tool (in the GNU chain it's
gcov. Note that specific flags should be passed during compilation for it to work properly). You run the code coverage tool with a good set of varied inputs (your unit-tests or non-regression tests), the dead code is necessarily within the unreached code... and so you can start from here.
If you are extremely interested in the subject, and have the time and inclination to actually work out a tool by yourself, I would suggest using the Clang libraries to build such a tool.
- Use the Clang library to get an AST (abstract syntax tree)
- Perform a mark-and-sweep analysis from the entry points onward
Because Clang will parse the code for you, and perform overload resolution, you won't have to deal with the C++ languages rules, and you'll be able to concentrate on the problem at hand.
However this kind of technique cannot identify the virtual overrides that are unused, since they could be called by third-party code you cannot reason about.