Tools to find included headers which are unused?

C++Coding StyleHeader Files

C++ Problem Overview


I know PC-Lint can tell you about headers which are included but not used. Are there any other tools that can do this, preferably on linux?

We have a large codebase that through the last 15 years has seen plenty of functionality move around, but rarely do the leftover #include directives get removed when functionality moves from one implementation file to another, leaving us with a pretty good mess by this point. I can obviously do the painstaking thing of removing all the #include directives and letting the compiler tell me which ones to reinclude, but I'd rather solve the problem in reverse - find the unused ones - rather than rebuilding a list of used ones.

C++ Solutions


Solution 1 - C++

DISCLAIMER: My day job is working for a company that develops static analysis tools.

I would be surprised if most (if not all) static analysis tools did not have some form of header usage check. You could use this wikipedia page to get a list of available tools and then email the companies to ask them.

Some points you might consider when you're evaluating a tool:

For function overloads, you want all headers containing overloads to be visible, not just the header that contains the function that was selected by overload resolution:

// f1.h
void foo (char);

// f2.h
void foo (int);


// bar.cc
#include "f1.h"
#include "f2.h"

int main ()
{
  foo (0);  // Calls 'foo(int)' but all functions were in overload set
}

If you take the brute force approach, first remove all headers and then re-add them until it compiles, if 'f1.h' is added first then the code will compile but the semantics of the program have been changed.

A similar rule applies when you have partial and specializations. It doesn't matter if the specialization is selected or not, you need to make sure that all specializations are visible:

// f1.h
template <typename T>
void foo (T);

// f2.h
template <>
void foo (int);

// bar.cc
#include "f1.h"
#include "f2.h"


int main ()
{
  foo (0);  // Calls specialization 'foo<int>(int)'
}

As for the overload example, the brute force approach may result in a program which still compiles but has different behaviour.

Another related type of analysis that you can look out for is checking if types can be forward declared. Consider the following:

// A.h
class A { };

// foo.h
#include "A.h"
void foo (A const &);

// bar.cc
#include "foo.h"

void bar (A const & a)
{
  foo (a);
}

In the above example, the definition of 'A' is not required, and so the header file 'foo.h' can be changed so that it has a forward declaration only for 'A':

// foo.h
class A;
void foo (A const &);

This kind of check also reduces header dependencies.

Solution 2 - C++

Here's a script that does it:

#!/bin/bash
# prune include files one at a time, recompile, and put them back if it doesn't compile
# arguments are list of files to check
removeinclude() {
    file=$1
    header=$2
    perl -i -p -e 's+([ \t]*#include[ \t][ \t]*[\"\<]'$2'[\"\>])+//REMOVEINCLUDE $1+' $1
}
replaceinclude() {
   file=$1
   perl -i -p -e 's+//REMOVEINCLUDE ++' $1
}

for file in $*
do
    includes=`grep "^[ \t]*#include" $file | awk '{print $2;}' | sed 's/[\"\<\>]//g'`
    echo $includes
    for i in $includes
    do
        touch $file # just to be sure it recompiles
        removeinclude $file $i
        if make -j10 >/dev/null  2>&1;
        then
            grep -v REMOVEINCLUDE $file > tmp && mv tmp $file
            echo removed $i from $file
        else
            replaceinclude $file
            echo $i was needed in $file
        fi
    done
done

Solution 3 - C++

Have a look at Dehydra.

From the website:

> Dehydra is a lightweight, scriptable, general purpose static analysis tool capable of application-specific analyses of C++ code. In the simplest sense, Dehydra can be thought of as a semantic grep tool.

It should be possible to come up with a script that checks for unused #include files.

Solution 4 - C++

Google's cppclean seems to do a decent job of finding unused header files. I just started using it. It produces a few false positives. It will often find unnecessary includes in header files, but what it will not tell you is that you need a forward declaration of the associated class, and the include needs to be moved to the associated source file.

Solution 5 - C++

If you are using Eclipse CDT you can try Includator which is free for beta testers (at the time of this writing) and automatically removes superfluous #includes or adds missing ones.

Disclaimer: I work for the company that develops Includator and have been using it for the past few months. It works quite well for me, so give it a try :-)

Solution 6 - C++

As far as I know, there isn't one (that isn't PC-Lint), which is a shame, and surprising. I've seen the suggestion to do this bit of pseudocode (which is basically automating your "painstaking process":

> for every cpp file
for every header include
comment out the include
compile the cpp file
if( compile_errors )
un-comment out the header
else
remove header include from cpp

Put that in a nightly cron, and it should do the job, keeping the projcet in question free of unused headers (you can always run it manually, obviously, but it'll take a long time to execute). Only problem is when not including a header doesn't generate an error, but still produces code.

Solution 7 - C++

I've done this manually and its worth it in the short (Oh, is it the long term? - It takes a long time) term due to reduced compile time:

  1. Less headers to parse for each cpp file.
  2. Less dependencies - the whole world doesn't need re-compiling after a change to one header.

Its also a recursive process - each header file that stays in needs examining to see if any header files it includes can be removed. Plus sometimes you can substitute forward declarations for header includes.

Then the whole process needs repeating every few months/year to keep on top of leftover headers.

Actually, I'm a bit annoyed with C++ compilers, they should be able to tell you what's not needed - the Microsoft compiler can tell you when a change to a header file can be safely ignored during compilation.

Solution 8 - C++

If someone is interested, I just putted on sourceforge a small Java comand-line tool for doing exactly that. As it is written in Java, it is obviously runable on linux.

The link for the project is https://sourceforge.net/projects/chksem/files/chksem-1.0/

Solution 9 - C++

Most approaches for removing unused includes work better if you first make sure that each your header files compiles on its own. I did this relatively quickly as follows (apologies for typos -- I am typing this at home:

find . -name '*.h' -exec makeIncluder.sh {} \;

where makeIncluder.sh contains:

#!/bin/sh
echo "#include \"$1\"" > $1.cpp

For each file ./subdir/classname.h, this approach creates a file called ./subdir/classname.h.cpp containing the line

#include "./subdir/classname.h"

If your makefile in the . directory compiles all cpp files and contains -I. , then just recompiling will test that every include file can compile on its own. Compile in your favorite IDE with goto-error, and fix the errors.

When you're done, find . -name '*.h.cpp' -exec rm {} \;

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionNick BastinView Question on Stackoverflow
Solution 1 - C++Richard CordenView Answer on Stackoverflow
Solution 2 - C++Andy CView Answer on Stackoverflow
Solution 3 - C++Ton van den HeuvelView Answer on Stackoverflow
Solution 4 - C++ChanceView Answer on Stackoverflow
Solution 5 - C++Mirko StockerView Answer on Stackoverflow
Solution 6 - C++Cinder6View Answer on Stackoverflow
Solution 7 - C++quamranaView Answer on Stackoverflow
Solution 8 - C++ArcticaView Answer on Stackoverflow
Solution 9 - C++John HainsworthView Answer on Stackoverflow