views:

289

answers:

3

I've got a largeish codebase that's been around for a while and I'm trying to tidy it up a bit by refactoring it. One thing I'd like to do is find all the headers where I could forward declare members, instead of including the entire header file.

This is a fairly labour intensive process and I'm looking for a tool that could help me figure out which headers have members that could be forward declared.

Is there a compiler setting that could emit a warning or suggestion that the following code could use a forward declaration? I'm using the following compilers icc, gcc, sun studio and HP's aCC

Is there a standalone tool that could do the same job?

#include "Foo.h"
...//more includes

class Bar {
.......
private:
    Foo* m_foo;
};
+2  A: 

I'm not sure you'll find anything that does this out-of-the box, but one option would be to write a script using Python and the pygccxml package that could do some of this analysis for you.

Basically you'd use pygccxml to build an in-memory graph of your source code, then use it to query your classes and functions to find out what they actually need to include to function.

So for example you could ask each class, give me the members that are pointer types: then for each of those pointer types you could work out if a real instance (non pointer) of the class was used in the interface, and if not you could mark it as a candidate for forward declaration.

The downside is that the script would take some time to get right so the cost might outweigh the benefits but it would be an interesting exercise at least. You could post your code to Github if you got something that worked and maybe others would find it useful.

jkp
+1 for mentioning pygccxml: didn't know it and it seems nice!
Francesco
+3  A: 

Anything involving the precise analysis of C++ requires essentially an entire C++ front end somewhere (otherwise you won't get answers, or they'll be wrong, and that works badly when you have "largish" applications). There aren't many practical answers available here.

Already mentioned is GCCXML is a GCC-derived package, so it has the requisite C++ front end. It produces XML, thus it will produce a LOT of output that you'll have to read back in to form "the in memory data structure" suggested in another answer. Its unfortunate that GCCXML builds that memory data structure already, then exports it as XML, and forces you to build it again. Of course, you could just use GCC, which builds the in memory data structure, but then you have to hack GCC to be what you want, and it really, really wants to be a compiler. That means you'll have a fight on your hands to bend it to your will (and explains why GCCXML exists: most people don't want that fight).

Not mentioned is the Edison Design Group C++ (EDG) front end, which builds that in memory data structure directly. It is a front end; you'll have to do all the analysis stuff yourself but your task may be simple enough so that isn't hard.

The last solution I know is mine: C++ FrontEnd for DMS. DMS is foundation for building program analysis, and its C++ FrontEnd is a complete Front end for C++ (e.g., does everything the GCC and Edison front ends do: parsing, tree building, name/type resolution). And you'll have to code your special analysis much the way you would for GCCXML and EDG by walking over the "in memory" datastructures produced by DMS.

What is really different is that DMS could then be used to actually modify your source code by updating those in memory data structures, and regenerate compilable code from those memory structures, including the original comments.

Ira Baxter
+2  A: 

What you could do is call gcc with -MM. This will produce dependency files that Make can read. Instead of having make use them, you could parse them (with perl, or something) to determine which includes are needed and which could be replaced with forward declarations.

curlingdude
@curlingdude: sounds like an interesting idea +1
jkp