tags:

views:

317

answers:

9

I'm trying to remove functions that are not used from a C++ project. Over time it's become bloated and I'm looking to remove functions that aren't used at all.

I have all the projects in a solution file in Visual Studio, but I use cmake so I can generate project files for another IDE if necessary (which is why this isn't tagged with visual-studio).

Does something like this exist? Where it'll analyze the source and tell me which functions are not called. I saw PC-Lint mentioned in a few questions here, but that doesn't seem to do this.

What I really want to do is call "Find all references" on each function and remove the functions not called, but doing this manually would take much too long.

A: 

I suppose the easiest way is to remove a function (or class, variable, anything else you might think is unneeded) and then see if it compiles. If the function is used you will get a compile or link error at some point during the rebuild.

Generally you should remove the definition rather than the declaration, as otherwise with things like overloaded functions and specialised templates it may compile and link to one of the others, not causing an error but changing the programs behaviour. By removing the definition, the compiler still sees the declaration, but the linker will fail to link it.

Items that a declared but not defined wont cause an error if their not used, since the linker will never try to link to them.

Fire Lancer
Fingers crossed it's not loaded dynamically...
Roger Lipscombe
If you know the structure of your project well enough to know the function isn't referenced dynamically (i.e. there is a symbol lookup for the function at runtime) then I think this is your best bet. It's what I do.
Omnifarious
Fingers crossed that it doesn't take 30 minutes to build the project.
Jon Seigel
This doesn't necessarily work, unfortunately, because of overloading. Suppose you have a function `void foo(int)` and a function `void foo(long)`. You can remove either one of them and it will compile and link fine, it just won't do the same thing. If you keep them both declared, though, and remove one definition, Then I *think* you're guaranteed a linker error.
Steve Jessop
While not a bad method of finding removable functions, there are too many files/functions for this to be a manual process. There is little polymorphism and very few templates too. So no need to worry about them.
Joe
+4  A: 

Sounds like you need a code coverage tool. There's a list of them in this wikipedia article.

Phil Nash
Why? No testing code may even exist.
reinierpost
No testing code exists. A code coverage tool won't work because we'd have no idea if we hit every case.
Joe
Code coverage tools do not necessarily require specific test code - some can be run on normal code in a production environment.
anon
+3  A: 

The excellent (and free) Source Monitor static analysis tool, from http://www.campwoodsw.com/ can give you counts of the number of calls to a method, which I think is what you want.

Edit: Seems to be my evening for screwing up. The calls metric does not in fact do what I thought it did. Still, SM is an excellent tool so I hope that bringing it to people's attention has done some good!

anon
I have tried Source Monitor and I think the call statistics for a method is not the number of times this method was called but the number of calls to other methods this method is doing.Please someone correct me if I am wrong.
BlueTrin
Yes, you seem to be correct. Sorry about that - it's not a metric I actually use myself.
anon
+1  A: 

If your code is simple enough static analysis might work. However C++ is very context-sensitive :/. So I personally would not even try to look for a tool in the area. At least not until CLANG is fully compliant with C++ :D

I hope you have unit-tests, I would get visual studio to compile code which generates a runtime profile and then farm the function names's (with a scripting language) from the generated profile. If you have covered all of the use-cases (either manually or with unit-tests) in your application you should be able to identify the least used (or never-used) functions. Then you can use the mark-one eyeball to trim down the source-base.

There is nothing like doing It manually though :D

Hassan Syed
+1  A: 

Visual Studio can generate call graphs, showing 'called-by' for each function. Doxygen will do the same if you don't want to use Visual Studio.

However both these methods will fail to detect a function called through a pointer, but that should normally be easy to check manually.

Clifford
+1 for bringing up the function pointers, although i disagree that it will always be easy to check manually. the only problem i have with the entire concept is that because possible control paths will be exponential in number related to the modules you have actually written, it's probably impossible to remove them with 100% certainty of safety unless ALL of the functions are linked statically.
San Jacinto
I said it would *normally* be easy on the basis that function pointers are not often extensively used within a code base. I meant in terms of effort, not necessarily complexity; I am assuming a certain familiarity with the code; for example if it were your code, you'd probably know whether and where you'd used function pointers!
Clifford
fair enough. i did indeed put words in your mouth there.
San Jacinto
+1  A: 

If you want to know, dynamically, which functions are being used you could get the (vc++) compiler to insert callcap hooks and then use those to dump out usage information.

This could be a useful compliment to static analysis based approaches, since it will see every piece of code that is entered during execution (regardless of how execution arrives there).

See http://msdn.microsoft.com/en-us/library/ms254291%28VS.80%29.aspx for info on call profile hooks in visual studio.

Matt Gordon
+5  A: 

Use __declspec(deprecated) in front of the function declaration you want to get rid of. That will throw up compile warnings if that function is actually used at compile time.

MSN
I didn't know about this, I'll definitely look into this more.
Joe
This is the solution I'm going to end up using so I'll mark this as the answer. It works well for me because _declspec(dllimport deprecated) works. I #define _declspec(dllimport) vs _declspec(dllexport) so I can just modify one place per dll and see what shows up.Everything shows up deprecated at least once because everything has a body. I used python to parse the output from the compiler and make a histogram of how many times each class/function is deprecated. Then I look at the ones with the lowest numbers more closely.
Joe
+1  A: 

I'm pretty sure that mathematically, this can't be done in the general case. If you allow for recursion and function pointers (or first class functions) then you end up in a pretty simple reduction to the Halting Problem.

Granted, this be a case that you never have to deal with, but you should know abut it...

Brian Postow
that's the point i was making in my comment to clifford's answer. you posted the answer, you get the points :).. +1
San Jacinto
A: 

For this need you can use CppDepend , it very useful to detect dependencies inside your C\C++ project.

and you can customize your request using CQL language.

Issam