views:

769

answers:

9

I'm refactoring some code in C++, and I want to deprecate some old methods. My current method for finding all of the methods looks like this:

  1. Comment out the original method in the source file in which I'm working.
  2. Try to compile the code.
  3. If a compiler error is found, then make a note comment out the call and try to recompile.
  4. Once the compile has completed successfully, I've found all of the calls.

This totally sucks. I've also tried grepping source for the name of the function calls, but I sometimes run into problems with functions of the same name with different arguments, so my compilation makes the C++ compiler resolve the names for me. I've found this question for C#, but my code base is entirely implemented in C++.

Is there a better way to find all of the callers of a class method or function in C++? I'm using GCC on Unix systems, but cross-platform solutions would be superlative.

+2  A: 

That's pretty much how I do it. If your code is all in once place a "grep" (or find | grep combo) might do the trick too.

One caviat: This method will very often miss instances that are not conditionally compiled into your current configuration. If your code makes use of #ifdefs to support multiple configurations, a thorough person will try to compile with every configuration to catch all instances.

T.E.D.
That's a really good point. Luckily we don't have too many ifdef's in our code, and I don't expect many for this particular refactoring project, but that's another reason why I need a better trick. :)
James Thompson
+24  A: 

GCC allows you to decorate variables, functions, and methods with __attribute__((deprecated)), which will cause a warning on all callsites (unless -Wno-deprecated-declarations is given).

class A {
public:
    A() __attribute__((deprecated)) {}
};
int main() {
    A a;
}
$ g++ test.c
test.cc: In function ‘int main()’:
test.cc:6: warning: ‘A::A()’ is deprecated (declared at test.cc:3)
ephemient
Nice. Since the OQ is using GCC (and no mention of other platforms), this is what I'd do.
T.E.D.
For anyone using visual studio, there is similar functionality with #pragma deprecated(functionname). See http://msdn.microsoft.com/en-us/library/044swk7y.aspx
Eclipse
This is the right answer for me, because I'm refactoring I won't need the attributes to be cross-platform. Good stuff!
James Thompson
One nice thing about GCC's attribute syntax is that it requires double-parens to use; this makes it very easy to `#ifndef __GNUC__ #define __attribute__(x) /* nothing */ #endif` stub out the attributes in other compilers.
ephemient
+4  A: 

I think what you want is to look at a call graph. See this question for some good suggestions on how to do that.

MattK
Thanks for the link! I didn't see that question in my search.
James Thompson
+5  A: 

One option is to run your entire project through a program like Cscope. Which essentially parses the entire source code of your project and builds a database that allows for easy searching of things like all of a function's callers, all references, etc.

I know it works fairly well for C, and they claim it works decently for C++. KScope is a KDE GUI front end for it.

Falaina
Drat. I was hopeful until I read your "they claim it works decently for C++". Based on your post, I thought you were speaking from first hand experience.I am a huge fan of cscope for C code, even big, complex C code, but I've had very mixed results with C++. I guess instead of lamenting I should try to fix cscope, since it's on Sourceforge after all...
Dan
+3  A: 

This plugin for Eclipse might be the right tool: CallGraph View

Velociraptors
+4  A: 

For anyone wanting to do this in Visual Studio under windows....

Visual Assist is really good. It helps a lot with many C++ refactorings, Call graphs, renaming, automatically creating header definitions or generation methods from definitions, etc etc. It's not perfect, nothing like the quality of Java/C# refactoring tools, but really good for C++!!

Keith Nicholas
+6  A: 

Eclipse can do this without any plugins. It can be a useful tool for stuff like this even if you don't want to use it for your day-to-day editor.

  1. Download, install, and run the Eclipse CDT.
  2. Go under File, New, C++ Project. Enter a project name and choose an Empty Makefile project from the Project Type tree view. Uncheck "Use default location" and enter the folder where your project is kept.
  3. Click Next, then click Finish.
  4. Eclipse will automatically start indexing your project. If it really is a Makefile project, and since you're using g++, you can do a full clean then build from within Eclipse (under the Project menu), and it should automatically use your existing makefiles and automatically discover your include directories and other project settings.
  5. Find the prototype of the overloaded function in a source file, right-click on it, choose References, and choose Project. Eclipse will find all references to that function, and only to that particular overload of that function, within your project.

You can also use Eclipse's built-in refactoring support to rename overloaded functions so that they're no longer overloaded. Eclipse is also fully cross-platform; you can use features like its indexer, search references, and refactoring even for projects that are maintained and built in other IDEs.

Josh Kelley
Simul-answered! I defer to your more complete answer and reward you with an upvote :-)
David Citron
+2  A: 

If you let the Eclipse CDT index your source base, then you should be able to view the calling hierarchy for any function and even perform some refactoring.

You can download the Eclipse IDE for C/C++ Developers (hopefully you can find a port for your particular *NIX) and follow their instructions to get going.

David Citron
+2  A: 

In visual studio, right click on the function name and click "Call Browser" > Show Callers graph

Then in the display window there should be a folder called "Calls to function" that contains all the places that call that function, each of which you can double click on to go to them in the code.

DShook