Detecting superfluous #includes in C/C++?

116,450

Solution 1

Google's cppclean (links to: download, documentation) can find several categories of C++ problems, and it can now find superfluous #includes.

There's also a Clang-based tool, include-what-you-use, that can do this. include-what-you-use can even suggest forward declarations (so you don't have to #include so much) and optionally clean up your #includes for you.

Current versions of Eclipse CDT also have this functionality built in: going under the Source menu and clicking Organize Includes will alphabetize your #include's, add any headers that Eclipse thinks you're using without directly including them, and comments out any headers that it doesn't think you need. This feature isn't 100% reliable, however.

Solution 2

Also check out include-what-you-use, which solves a similar problem.

Solution 3

The problem with detecting superfluous includes is that it can't be just a type dependency checker. A superfluous include is a file which provides nothing of value to the compilation and does not alter another item which other files depend. There are many ways a header file can alter a compile, say by defining a constant, redefining and/or deleting a used macro, adding a namespace which alters the lookup of a name some way down the line. In order to detect items like the namespace you need much more than a preprocessor, you in fact almost need a full compiler.

Lint is more of a style checker and certainly won't have this full capability.

I think you'll find the only way to detect a superfluous include is to remove, compile and run suites.

Solution 4

I thought that PCLint would do this, but it has been a few years since I've looked at it. You might check it out.

I looked at this blog and the author talked a bit about configuring PCLint to find unused includes. Might be worth a look.

Solution 5

The CScout refactoring browser can detect superfluous include directives in C (unfortunately not C++) code. You can find a description of how it works in this journal article.

Share:
116,450
shoosh
Author by

shoosh

Working as a Software Engineer Millennium projects: https://github.com/shooshx CycleBlob, Lightcycle on a 3d surface using WebGL http://cycleblob.com

Updated on July 08, 2022

Comments

  • shoosh
    shoosh almost 2 years

    I often find that the headers section of a file get larger and larger all the time but it never gets smaller. Throughout the life of a source file classes may have moved and been refactored and it's very possible that there are quite a few #includes that don't need to be there and anymore. Leaving them there only prolong the compile time and adds unnecessary compilation dependencies. Trying to figure out which are still needed can be quite tedious.

    Is there some kind of tool that can detect superfluous #include directives and suggest which ones I can safely remove?
    Does lint do this maybe?

  • Dominic Rodger
    Dominic Rodger about 15 years
    Be careful of this - say there are two header files which both include a definition of something. You can remove either, but not both. You'll need to be a bit more thorough in your brute force approach.
  • Dominic Rodger
    Dominic Rodger about 15 years
    Maybe this is what you meant, but a script that removes a single include, and leaves the last removed include out if it was successfully removed would do the trick.
  • Graeme Perrow
    Graeme Perrow about 15 years
    Bad idea. If a header file #defines a constant BLAH and another header file checks #ifdef BLAH, removing the first header file may still successfully compile but your behaviour has changed.
  • Gilad Naor
    Gilad Naor about 15 years
    Didn't think about it too much, but you are correct. God is in the details, as they say. I'm not sure leaving the .h file out at each step is sufficient - this is still a Greedy search (capitol G), which doesn't always find the optimal solution. It will give a CORRECT solution, unlike the original.
  • David Thornley
    David Thornley about 15 years
    None of this will be an issue if the include files are laid out well. If you ever need to include file A before file B, you're doing it wrong (and I've worked on projects where they did it wrong).
  • David Thornley
    David Thornley about 15 years
    This also can cause problems with system headers, since different implementations might have different things included in #include <vector>. Even if you stick to one compiler, the headers could change over different versions.
  • JaredPar
    JaredPar about 15 years
    @David, yes but that depends on the years of devs before you doing it correctly. I can say with great certainty that the odds of that happening favor the house, not you :(
  • bk1e
    bk1e about 15 years
    This won't find cases where you're including a header that includes the header that you really need.
  • Harold Bamford
    Harold Bamford about 15 years
    I use PCLint regularly and it does tell me of unused headers. I'm careful to comment out the header #include and re-compile to be sure that the header is truly unused...
  • David Thornley
    David Thornley about 15 years
    Yes, but I generally find out about that when modifying a program, and suddenly I've got a compilation error (if I'm lucky) or an obscure bug. That seems to keep the #include files honest, at least in the long run.
  • David Thornley
    David Thornley about 15 years
    I know exactly what you mean, and my reaction was "Ewwww". I hate code like that.
  • JaredPar
    JaredPar about 15 years
    @Benoit, then you would be ignoring a class of issues that compile but semantically change the meaning of your program. Consider how a #define in one file can alter a #if branch in another. Removing a header can still allow this to compile with different results
  • Tom
    Tom about 15 years
    Lakos's book is great for education -- aside from his outdated observations on compiler technology.
  • Dan
    Dan about 15 years
    I could be wrong here (again - I should try it & post facts, not post on my best recollection...) but I'm pretty sure that PC-Lint / Flexelint will detect if a header influences/alters the compilation in any way. Regular lint, not so sure...
  • Admin
    Admin over 13 years
    too expensive. not a viable tool for the masses.
  • Abhi
    Abhi about 13 years
    IMHO this answer needs a lot more upvotes, as once the kinks are worked out Google's IWYU tool will be the definitive tool for this task.
  • Chance
    Chance over 12 years
    It does now. I just starting using it. See my note here. stackoverflow.com/questions/1301850/…
  • Baptiste Wicht
    Baptiste Wicht over 11 years
    The script finds some includes to remove but it gives also a lots of includes that cannot be removed. It seems that it doesn't support class enum, seems also that it has a bad time with macro and sometimes with namespace.
  • Nick
    Nick almost 11 years
    The cppclean repository is down, you can now get it here: bitbucket.org/robertmassaioli/cppclean (the original site is still useful for some example usage though)
  • PeterSom
    PeterSom over 10 years
    The reason for that is that our bookkeeping department is not able to invoice lesser amounts. If you count the time you might save it is not that unreasonable. Once, we've got the ability to get credit card payments we can lower the price significantly. Another option would be a sponsor for our development efforts. Our financing model requires us to gain profits to finance our research work. I would be happy to sell licenses much cheaper, but can't. May be we will contribute it to CDT and you get it for free, but that I have to finance somehow. I forgot, you can try for free!
  • shoosh
    shoosh about 10 years
    Did I ask for an "always correct" solution? This answer is not very productive for the discussion.
  • Algoman
    Algoman about 10 years
    Well there have been numerous posts discussing problems that such a program would have to deal with. My post gives a conclusive and correct answer to that part of the discussion. And I for one would not like it, if a program told me, I could safely remove an #include and then my code doesn't compile anymore. (or worse - still compiles but does something differently). ANY such program bears this risk.
  • Algoman
    Algoman about 10 years
    Between all the SPECULATION about how hard that would be and how you MIGHT solve one obstacle or another, I gave you the only 100% correct answer. I find it quite impudent to say that this wasn't productive...
  • BenC
    BenC over 9 years
    I updated the link to a maintained cppclean fork: github.com/myint/cppclean
  • BlamKiwi
    BlamKiwi over 9 years
    @Algoman taking a page from compiler design, conservative heuristics mean never having to say sorry.
  • hochl
    hochl about 9 years
    include-what-you-use seems still in development, after a somewhat long hiatus there are news posted to the page (latest entry: 2014/11).
  • Erik Sjölund
    Erik Sjölund almost 9 years
    The project include-what-you-use is still active. 4 June 2015 include-what-you-use 0.4 was released.
  • Andrew Wagner
    Andrew Wagner over 8 years
    sudo apt-get install iwyu
  • Zhe Yang
    Zhe Yang over 8 years
    I remembered that Rice's theorem states "There can't be a program which always can check if a given program solve this superfluous-includes problem". There can be a few programs which solve the superfluous-includes problem.
  • Algoman
    Algoman over 8 years
    If a program doesn't ALWAYS give you the correct answer, then it doesn't "SOLVE" the problem. They can only solve some non-semantic subsets of the problem.
  • Zitrax
    Zitrax almost 8 years
    Note that cppclean seem to find them only in header files, not cpp files, from the doc: "Unnecessary #includes in header files".
  • Mawg says reinstate Monica
    Mawg says reinstate Monica over 7 years
    Seems great - with two cavaets 1) last update Feb 2106 2) Gogole themselves use it only for C++, not C, which the OP requested.
  • bogardon
    bogardon over 7 years
    personally I found @Algoman's input very helpful. makes me realize how hard this problem is.
  • Florian Castellane
    Florian Castellane about 7 years
    this is false. The c++ preprocessor is not Turing complete. stackoverflow.com/a/7508513/2918853
  • Algoman
    Algoman almost 7 years
    Do you understand the reasoning behind that claim? Recursion-depth having an (arbitrarily chosen) limit contradicts turing completeness as much as finite RAM contradicts your PCs turing completeness.
  • Benno Straub
    Benno Straub almost 7 years
    The recursion depth is signigicant however: No real compiler can have actual infinite recursion depth, therefore it is not turing complete making the problem solvable for any existing computer with any existing compiler.
  • Algoman
    Algoman almost 7 years
    By that reasoning, the Halting Problem is solvable, because no real PC has actual infinite RAM. There is no technical necessity for a limit on the recursion depth. That is just a design-decision.
  • Admin
    Admin almost 7 years
    Can you explain a little bit how a user should use it ? The README isn't very clear about what contains the output of the python script.
  • phuclv
    phuclv over 6 years
  • InQusitive
    InQusitive about 6 years
    I am using this, but it is not always 100% correct. Maybe 70% times it gives the correct suggestions.
  • Dan M.
    Dan M. about 6 years
    @Algoman but that means that it's solvable in practice, since the maximum recursion depth needed to compile said program is known. I.e. if the program already compiles, when it doesn't have infinite recursion, and then the include analysis can be run safely (since the complexity of getting the correct includes is not asymptotically higher than compiling the program).
  • Algoman
    Algoman about 6 years
    @DanM. that's complete nonsense. One include may set some preprocessor macro (say only it's include guard) then the next include may do something completely different based on the presence of that macro. Say it now doesn't include stdio, but defines a function named printf, which wipes your harddrive. Still compiles. Totally safe to remove that first include.
  • Algoman
    Algoman about 6 years
    Even if the preprocessor wasn't turing complete, you'd still have to GUARANTEE that the removal of the include absolutely doesn't change the semantic of ANY program that includes your file. Now we're talking about Turing-Degree 2 - that's even infinitely harder than the halting problem.
  • Dan M.
    Dan M. about 6 years
    @Algoman and compiler somehow figures out what printf function to include during the compilation process, so it means that so can a hypothetical include analyzer. Also, there is no need to provide strong "GUARANTEE" that removal of some include won't affect anything down the line (if you have a lib). In fact, there can't be such guarantee because transitive includes is a thing and people often mistakenly rely on them. But in that case it's their bug, not yours. You just document which headers you include exactly and relying on everything else is UB (not part of the public interface).
  • Algoman
    Algoman about 6 years
    Oh yes, there is a need to provide a strong guarantee. Just because you (falsely) believe this didn't affect YOUR use-case only shows how little your understanding of the problem is. You are talking with an expert on this topic here and you are suffering from the Dunning-Kruger effect.
  • wizurd
    wizurd almost 6 years
    Does Eclipse CDT use google's iwyu tool under the hood?
  • Josh Kelley
    Josh Kelley almost 6 years
    @wizurd - I haven't kept up with recent developments in Eclipse CDT, but I don't think so. iwyu is thorough and relatively slow. Eclipse CDT's analysis is fast (interactive) and, when I tested it, less accurate.
  • Hi-Angel
    Hi-Angel over 4 years
    Latest cppclean (0.13) reports lots of unused includes for Konsole sources, yet removing any results in compilation errors. include-what-you-use is a bit better in that regard: it also has lots of false-positives, but at least some of removed includes indeed weren't needed. Btw, worth noting that include-what-you-use is packaged for many GNU/Linux distros, so you don't need to install it from sources (which isn't straightforward btw). The package can go under alternative name iwyu.
  • Gabriel Staples
    Gabriel Staples about 4 years
    Woah, that Eclipse feature built in to it is pretty cool! I never knew that existed. I may add it to my Eclipse doc.