6

I'm trying to find unused functions in my codebase by using GCC's -Wunused-function flag.

As I would expect, compiling the below code with gcc -Wall -Wunused-function main.cpp prints an unused variable warning:

warning: unused variable ‘x’ [-Wunused-variable]

However, the compiler doesn't give an unused-function warning. What do I have to do to make GCC notice the unused function foo()?

// main.cpp

void foo(){ } //should (but doesn't) trigger 'unused function' warning

int main (int argc, char **argv){
    int x; //correctly triggers 'unused variable' warning
    return 0;
}

Remember, I do want unused function warnings. This is not a "how do I get rid of warnings" question.

solvingPuzzles
  • 8,541
  • 16
  • 69
  • 112

3 Answers3

16

A non-static function is never considered "unused" because its symbol is exported and available to be used by other compilation units, which is something that gcc can't detect. -Wunused-functions is only documented to warn about static functions that are declared but not called.

hobbs
  • 223,387
  • 19
  • 210
  • 288
  • As [we've seen before](http://stackoverflow.com/questions/558122/what-is-a-static-function), there are bunch of different ways to define "static function." What are some examples of situations where `-Wunused-functions` would notice an unused function? – solvingPuzzles Nov 05 '12 at 00:19
  • @solvingPuzzles if you take the code example in your question and change `void foo` to `static void foo`, it will warn. – hobbs Nov 05 '12 at 00:45
  • 1
    "static function" in this case means "function with internal linkage". – caf Nov 05 '12 at 02:43
7

from the gcc documentation:

-Wunused-function: Warn whenever a static function is declared but not defined or a non-inline static function is unused. This warning is enabled by -Wall.

As you can see, you've defined and declared a non-static function. Also your function isn't being inlined(for which you need to use -O3 optimization).

I am not sure what you're asking for exists in gcc, as of yet. :-) But its open source.. maybe you can implement it?

Aniket Inge
  • 25,375
  • 5
  • 50
  • 78
  • 1
    Ah, that's what I was afraid of. I think there are tools out there, but as you said, I could also roll my own. A quick and dirty script could just (1) make a list of functions in the `.cpp` files, and (2) check how many times each function is referenced. If a function name only appears once in the codebase, it's probably unused (barring 'library' types of situations). – solvingPuzzles Nov 05 '12 at 00:14
  • @solvingPuzzles precisely. Once or maybe twice. Check for if the function name(and parameters) follows '{'. If it does, that function is defined. Then check how many times it appears. If it appears once only, then its only defined, not used. – Aniket Inge Nov 05 '12 at 00:25
  • @solvingPuzzles that way you can avoid the library function problems – Aniket Inge Nov 05 '12 at 00:26
  • 2
    This is not right. The reason that no warning is given is because the function has external linkage, not internal linkage ("static"). The quoted text means that: functions with external linkage are never warned about; of static functions, you will get a warning if either it's not defined at all, or it's both unused and not declared `inline`. If you declare the function as `static void foo() {}` you should recieve the warning. – caf Nov 05 '12 at 02:41
5

You can find unused non-static functions using linker optimisation.

I compiled your main.cpp with

gcc -ffunction-sections -fdata-sections -Wl,--gc-sections -Wl,--print-gc-sections main.cpp

And the output

/usr/bin/ld: Removing unused section '.text._Z3foov' in file '/tmp/cc9IJvbH.o'

Shows that foo() is unused and the linker could remove it.

John Slade
  • 12,246
  • 2
  • 25
  • 20
  • Another benefit of this is that it will not complain about "undefined reference to `bar`" if `foo()` calls `bar()`, but nobody calls `foo()`. Ever since finding out about this option I've been puzzled as to why it is not the default. If a function is never called, why should it make its way into the executable? – M.M May 20 '14 at 10:17
  • The main issue with making this the default is that `-ffunction-sections` can cause problems if it is always used for compilation. From the GCC manual: "Only use these options when there are significant benefits from doing so. When you specify these options, the assembler and linker will create larger object and executable files and will also be slower. You will not be able to use gprof on all systems if you specify this option and you may have problems with debugging if you specify both this option and -g." – John Slade May 20 '14 at 10:39
  • In my experience, although object files are larger, executable files are smaller, in fact that's why I use the options. (This is with all debugging info stripped out). Perhaps it just worked out that way for my situation , and not general situations. Anyway though - I mean in a more general sense : linkers ought to have the capability to exclude dead code without having to be prompted, and without making any tradeoffs except for time taken to perform the link. – M.M May 20 '14 at 10:42