How can I know which parts in the code are never used?
Asked Answered
J

19

320

I have legacy C++ code that I'm supposed to remove unused code from. The problem is that the code base is large.

How can I find out which code is never called/never used?

Joyjoya answered 27/1, 2011 at 7:59 Comment(10)
I think a code query language will give you a better view of your project as a whole. I am not sure about the c++ world but there seems to be cppdepend.com ( this is not free ), which looks decent enough. May be something like this may be available for free. The other thing is, before doing anykind of refactoring, the sane thing to do would be have unit tests if you do not have right now. With unit tests what can you do is have your code coverage tools profile your code which in it self will help to remove the dead code if you can not cover that code.Cyrilla
Of course doing a pattern search of function names to look for function calls can be dangerous because preprocessor macros could fool you.Irrefragable
Looks like this will earn you a "Nice Question" badge in less than one hour from asking the question.Angle
I find similar topic. #229569Helli
@Benoit: Yes, but preprocessor macros are just the tip of the iceberg... C++ name lookup rules are beyond incomprehensible. And that's not even mentioning overloaded operators. Or implicit conversions. a->b = c; quite possibly calls an arbitrary number of different templated overloaded operator->()s. For real.Este
@user63898: Are you more concerned with finding individual lines of pointless/unused code, or entire functions/methods that are no longer called from anywhere? I was thinking the latter, but many answers address just the former.Este
Yup, one of the funny things of C++ is that removing "unused" functions may still alter the result of a program.Capote
I don't know too much about C++, but there might be an IDE tool ala R# that will simply grey out anything that's not called.Inappetence
@MSalters: That's an interesting one... For that to be the case we would have to be talking about which function in an overload set is chosen for a given call, correct? To my knowledge, if there are 2 functions both named f(), and a call to f() unambiguously resolves to the 1st, then it is not possible to make that call resolve to the 2nd just by adding a 3rd function named f() -- the "worst you can do" by adding that 3rd function is to cause the call to become ambiguous and therefore prevent the program from compiling. Would love (= be horrified) to see a counterexample.Este
@j_random_hacker: No, that's too simple. You'd need to have SFINAE overload resolution of g depend on the succesful overload resolution of f. When the overload resolution of f succeeds, you should pick one, and when it fails you should pick (via SFINAE) the other.Capote
S
201

There are two varieties of unused code:

  • the local one, that is, in some functions some paths or variables are unused (or used but in no meaningful way, like written but never read)
  • the global one: functions that are never called, global objects that are never accessed

For the first kind, a good compiler can help:

  • -Wunused (GCC, Clang) should warn about unused variables, Clang unused analyzer has even been incremented to warn about variables that are never read (even though used).
  • -Wunreachable-code (older GCC, removed in 2010) should warn about local blocks that are never accessed (it happens with early returns or conditions that always evaluate to true)
  • there is no option I know of to warn about unused catch blocks, because the compiler generally cannot prove that no exception will be thrown.

For the second kind, it's much more difficult. Statically it requires whole program analysis, and even though link time optimization may actually remove dead code, in practice the program has been so much transformed at the time it is performed that it is near impossible to convey meaningful information to the user.

There are therefore two approaches:

  • The theoretic one is to use a static analyzer. A piece of software that will examine the whole code at once in great detail and find all the flow paths. In practice I don't know any that would work here.
  • The pragmatic one is to use an heuristic: use a code coverage tool (in the GNU chain it's gcov. Note that specific flags should be passed during compilation for it to work properly). You run the code coverage tool with a good set of varied inputs (your unit-tests or non-regression tests), the dead code is necessarily within the unreached code... and so you can start from here.

If you are extremely interested in the subject, and have the time and inclination to actually work out a tool by yourself, I would suggest using the Clang libraries to build such a tool.

  1. Use the Clang library to get an AST (abstract syntax tree)
  2. Perform a mark-and-sweep analysis from the entry points onward

Because Clang will parse the code for you, and perform overload resolution, you won't have to deal with the C++ languages rules, and you'll be able to concentrate on the problem at hand.

However this kind of technique cannot identify the virtual overrides that are unused, since they could be called by third-party code you cannot reason about.

Soloman answered 27/1, 2011 at 9:25 Comment(9)
Very nice, +1. I like that you distinguish between code that can be statically determined to never run under any circumstances and code that doesn't run in a particular run, but potentially could. The former is the important one I think, and as you say a reachability analysis using the AST of the entire program is the way to get it. (Preventing foo() from being marked as "called" when it appears only in if (0) { foo(); } would be a bonus but requires extra smarts.)Este
@j_random_hacker: perhaps that using the CFG (Control-Flow Graph) would be better now that I think of it (thanks to your example). I know that Clang is keen to remark about tautological comparisons like the one you mentioned and thus using the CFG we might possibly spot dead-code early on.Soloman
@Matthieu: Yeah maybe CFG is what I mean too, instead of AST :) What I mean is: a digraph in which the vertices are functions and there is an edge from function x to function y whenever x could possibly call y. (And with the important property that overloaded functions are all represented by distinct vertices -- sounds like Clang does that for you, phew!)Este
@j_random_hacker: actually the CFG is more complicated than a simple digraph, since it represents all the code to be executed in blocks with links from one block to another based on conditional statements. The main advantage is that it is naturally suited to pruning code that can statically be determined to be dead (it creates unreachable blocks which can be identified), so it would be better to exploit the CFG than the AST to build the digraph you're talking about... I think :)Soloman
@Matthieu: I see, thanks. Also just realised that the AST probably does not represent things like implicit conversions, which you would want to track.Este
@j_random_hacker: actually Clang's AST does, it makes everything explicit (or almost...) because it is meant for working with the code, not merely for compiling it. There's actually a discussion at the moment because apparently there is an issue with initializer lists where such an implicit conversion does not appear in the AST, but I guess it'll be fixed.Soloman
Astrée reports unreachable C code reliably. Not quite sure if they can do C++, too.Cychosz
@RegDwight: it does not seem so, and I don't blame them, parsing C++ is hellish (template nightmare, function overloads). C's grammar is so much nicer in this regard.Soloman
Just for your information, Wunreachable-code has been removed from gcc in January 2010 (probably version 4.4.3) because it was considered broken.Jamaaljamaica
S
42

For the case of unused whole functions (and unused global variables), GCC can actually do most of the work for you provided that you're using GCC and GNU ld.

When compiling the source, use -ffunction-sections and -fdata-sections, then when linking use -Wl,--gc-sections,--print-gc-sections. The linker will now list all the functions that could be removed because they were never called and all the globals that were never referenced.

(Of course, you can also skip the --print-gc-sections part and let the linker remove the functions silently, but keep them in the source.)

Note: this will only find unused complete functions, it won't do anything about dead code within functions. Functions called from dead code in live functions will also be kept around.

Some C++-specific features will also cause problems, in particular:

  • Virtual functions. Without knowing which subclasses exist and which are actually instantiated at run time, you can't know which virtual functions you need to exist in the final program. The linker doesn't have enough information about that so it will have to keep all of them around.
  • Globals with constructors, and their constructors. In general, the linker can't know that the constructor for a global doesn't have side effects, so it must run it. Obviously this means the global itself also needs to be kept.

In both cases, anything used by a virtual function or a global-variable constructor also has to be kept around.

An additional caveat is that if you're building a shared library, the default settings in GCC will export every function in the shared library, causing it to be "used" as far as the linker is concerned. To fix that you need to set the default to hiding symbols instead of exporting (using e.g. -fvisibility=hidden), and then explicitly select the exported functions that you need to export.

Sulfur answered 1/2, 2011 at 1:7 Comment(4)
Great practical advice. Just getting a list of the functions that are known not to be used anywhere (even if, as you say, this list is not complete) will get a lot of the low-hanging fruit I think.Este
I don't think any of this works for uninstantiated templates.Masculine
It seems hard to produce useful results with this. Especially "inline"-declared functions and methods produce a lot of false positives which are hard to filter out. And it still does not find a completely unused class defined and declared in a .cpp, probably because it never gets compiled into the object file. cppcheck also does not detect that struct though nor does any compiler.Servitor
Sections are not functions.Fannyfanon
H
26

Well if you using g++ you can use this flag -Wunused

According documentation:

Warn whenever a variable is unused aside from its declaration, whenever a function is declared static but never defined, whenever a label is declared but not used, and whenever a statement computes a result that is explicitly not used.

http://docs.freebsd.org/info/gcc/gcc.info.Warning_Options.html

Edit: Here is other useful flag -Wunreachable-code According documentation:

This option is intended to warn when the compiler detects that at least a whole line of source code will never be executed, because some condition is never satisfied or because it is after a procedure that never returns.

Update: I found similar topic Dead code detection in legacy C/C++ project

Helli answered 27/1, 2011 at 8:36 Comment(3)
This won't catch headers that prototype functions that are never called. Or public class methods that don't get called. It can only check if locally scoped variables are used within that scope.Wentz
@Wentz I never used this flag. I'm trying to figure out myself what kind dead codes I can find with it.Helli
-Wunused warns about variables that are declared (or declared and defined in one go) but actually never used. Pretty annoying with scoped guards by the way :p There is an experimental implementation in Clang to have it also warn for non-volatile variables that are written to but never read from (by Ted Kremenek). -Wunreachable-code warns about code within a function that cannot be reached, it can be code located after a throw or return statement or code in a branch that is never taken (which happens in case of tautological comparisons) for example.Soloman
I
18

I think you are looking for a code coverage tool. A code coverage tool will analyze your code as it is running, and it will let you know which lines of code were executed and how many times, as well as which ones were not.

You could try giving this open source code coverage tool a chance: TestCocoon - code coverage tool for C/C++ and C#.

Inappetence answered 27/1, 2011 at 8:27 Comment(13)
The key here is "as it is running" - if your input data doesn't exercise some code path that path will not be recognized as used, will it?Angle
That is correct. Without running the code there is no way to know what lines are not being reached. I wonder how hard it will be to set up some Unit Tests to emulate a few normal runs.Inappetence
No, for some cases it can be proved that code is unreachable, even by a compiler. So there is a way to know what lines are not being reached, without running the program.Sori
@golcarcol "Without running the code there is no way to know". Why? If in code no one calling some function, than there is no need to execute application, to figure it out.Helli
@drhishch I think, that most such unused code must find linker and not compiler.Helli
@Ashot But then that means that you have to do a pattern search on the source itself. You have to manually search each function to see if its being called somewhere. Besides, what about if..else branches, switch cases, loops, etc, there's no way for you to see if ALL of that code is going to be executed unless it happens at run time, hence the Code Coverage tool. It will do that all for you, granted, you have to get it running in the first place.Inappetence
@drhirsch True, the compiler can take care of some of the code that is unreachable, such as functions being declared but not called and some short circuit evaluations, but what about code that depends on user action, or run time variables?Inappetence
@golcarcol I don't think, that compiler enable to find which functions never called. It can know only linker.Helli
@Ashot The compiler has this ability. Before the compiler turns your code into machine code, it parses your code and applies the language rules to make sure that your expressions are correctly written. It also does some optimizations (turning for loops into while loops, etc) and it throws some warnings about your code. The linker then tries to put all of the machine code together (after the compiler has given the green light) and it can throw an error when it does not find the correct libraries to link everything together. cs.bu.edu/teaching/cpp/debugging/errorsInappetence
@golcarcol Ok, let's we have function void func() in a.cpp, which is used in b.cpp. How compiler can check, that func() is used in program? It's linkers job.Helli
@Ashot Touché, you got me there lol. Maybe with a whole integrated IDE you will be able to, but not just the compiler itself. But then I suppose the IDE will do all the linking. However, for just one source, the compiler will be able to do this =PInappetence
@golcarcol: Although I think your approach has merit, it's far from the ideal solution as it too easily gives false positives (identifying "unused" code that could actually be used), so -1.Este
True, it could result in some false positives. However by knowing which lines of code were not executed, the programmer now has a smaller subset of lines to analyze and see if they are actually needed or not.Inappetence
G
16

The real answer here is: You can never really know for sure.

At least, for nontrivial cases, you can't be sure you've gotten all of it. Consider the following from Wikipedia's article on unreachable code:

double x = sqrt(2);
if (x > 5)
{
  doStuff();
}

As Wikipedia correctly notes, a clever compiler may be able to catch something like this. But consider a modification:

int y;
cin >> y;
double x = sqrt((double)y);

if (x != 0 && x < 1)
{
  doStuff();
}

Will the compiler catch this? Maybe. But to do that, it will need to do more than run sqrt against a constant scalar value. It will have to figure out that (double)y will always be an integer (easy), and then understand the mathematical range of sqrt for the set of integers (hard). A very sophisticated compiler might be able to do this for the sqrt function, or for every function in math.h, or for any fixed-input function whose domain it can figure out. This gets very, very complex, and the complexity is basically limitless. You can keep adding layers of sophistication to your compiler, but there will always be a way to sneak in some code that will be unreachable for any given set of inputs.

And then there are the input sets that simply never get entered. Input that would make no sense in real life, or get blocked by validation logic elsewhere. There's no way for the compiler to know about those.

The end result of this is that while the software tools others have mentioned are extremely useful, you're never going to know for sure that you caught everything unless you go through the code manually afterward. Even then, you'll never be certain that you didn't miss anything.

The only real solution, IMHO, is to be as vigilant as possible, use the automation at your disposal, refactor where you can, and constantly look for ways to improve your code. Of course, it's a good idea to do that anyway.

Grubstake answered 31/1, 2011 at 23:13 Comment(1)
True and do not leave dead code in! If you remove a feature, kill the dead code. Leaving it there "just in case" just causes bloat that (as you've discussed) is hard to find later. Let version control do the hoarding for ya.Checkroom
A
14

I haven't used it myself, but cppcheck, claims to find unused functions. It probably won't solve the complete problem but it might be a start.

Amplify answered 27/1, 2011 at 10:0 Comment(2)
Yes, it is able to find local not referуnced variables and function.Schilt
Yep use cppcheck --enable=unusedFunction --language=c++ . to find these unused functions.Ringleader
H
9

You could try using PC-lint/FlexeLint from Gimple Software. It claims to

find unused macros, typedef's, classes, members, declarations, etc. across the entire project

I've used it for static analysis and found it very good but I have to admit that I have not used it to specifically find dead code.

Hick answered 27/1, 2011 at 10:8 Comment(0)
M
7

My normal approach to finding unused stuff is

  1. make sure the build system handles dependency tracking correctly
  2. set up a second monitor, with a full-screen terminal window, running repeated builds and showing the first screenful of output. watch "make 2>&1" tends to do the trick on Unix.
  3. run a find-and-replace operation on the entire source tree, adding "//? " at the beginning of every line
  4. fix the first error flagged by the compiler, by removing the "//?" in the corresponding lines.
  5. Repeat until there are no errors left.

This is a somewhat lengthy process, but it does give good results.

Malar answered 27/1, 2011 at 12:56 Comment(3)
Has merit, but very labour-intensive. Also you must make sure to uncomment all overloads of a function at the same time -- if there more than one is applicable, uncommenting a less-preferred one might allow compilation to succeed but result in incorrect program behaviour (and an incorrect idea of which functions are used).Este
I only uncomment declarations in the first step (all overloads), and in the next iteration then see which definitions are missing; that way, I can see which overloads are actually used.Malar
@Simon: Interestingly in a comment on the main question, MSalters points out that even the presence/absence of a declaration for a function that is never called can affect which of another 2 functions is found by overload resolution. Admittedly this requires an extremely bizarre and contrived setup, so it's unlikely to be a problem in practice.Este
T
4

Mark as much public functions and variables as private or protected without causing compilation error, while doing this, try to also refactor the code. By making functions private and to some extent protected, you reduced your search area since private functions can only be called from the same class (unless there are stupid macro or other tricks to circumvent access restriction, and if that's the case I'd recommend you find a new job). It is much easier to determine that you don't need a private function since only the class you're currently working on can call this function. This method is easier if your code base have small classes and is loosely coupled. If your code base does not have small classes or have very tight coupling, I suggest cleaning those up first.

Next will be to mark all the remaining public functions and make a call graph to figure out the relationship between the classes. From this tree, try to figure out which part of the branch looks like it can be trimmed.

The advantage of this method is that you can do it on per module basis, so it is easy to keep passing your unittest without having large period of time when you've got broken code base.

Tepefy answered 27/1, 2011 at 15:26 Comment(0)
A
3

I really haven't used any tool that does such a thing... But, as far as I've seen in all the answers, no one has ever said that this problem is uncomputable.

What do I mean by this? That this problem cannot be solved by any algorithm ever on a computer. This theorem (that such an algorithm doesn't exist) is a corollary of Turing's Halting Problem.

All the tools you will use are not algorithms but heuristics (i.e not exact algorithms). They will not give you exactly all the code that's not used.

Adallard answered 27/1, 2011 at 14:44 Comment(2)
I think the OP mainly wants to find functions that aren't called from anywhere, which is certainly not uncomputable -- most modern linkers can do it! It's just a matter of extracting that info with the least amount of pain and drudgery.Este
You're right, I didn't see the last comment to the main question. By the ways, there may be functions referred in code that aren't actually used. That kind of things may not be detected.Adallard
C
3

If you are on Linux, you may want to look into callgrind, a C/C++ program analysis tool that is part of the valgrind suite, which also contains tools that check for memory leaks and other memory errors (which you should be using as well). It analyzes a running instance of your program, and produces data about its call graph, and about the performance costs of nodes on the call graph. It is usually used for performance analysis, but it also produces a call graph for your applications, so you can see what functions are called, as well as their callers.

This is obviously complementary to the static methods mentioned elsewhere on the page, and it will only be helpful for eliminating wholly unused classes, methods, and functions - it well not help find dead code inside methods which are actually called.

Can answered 31/1, 2011 at 22:15 Comment(0)
A
2

One way is use a debugger and the compiler feature of eliminating unused machine code during compilation.

Once some machine code is eliminated the debugger won't let you put a breakpojnt on corresponding line of source code. So you put breakpoints everywhere and start the program and inspect the breakpoints - those which are in "no code loaded for this source" state correspond to eliminated code - either that code is never called or it has been inlined and you have to perform some minimum analysis to find which of those two happened.

At least that's how it works in Visual Studio and I guess other toolsets also can do that.

That's lots of work, but I guess faster than manually analyzing all code.

Angle answered 27/1, 2011 at 8:1 Comment(7)
I think the OP's question is about how to find a smaller, more manageable subset of source code, not so much making sure the compiled binary is efficient.Este
@Este I gave it a though - and turns out code elimination can even be used for tracking back to original source code.Angle
do you have to some specific compiler flags on visual studio to achieve it? and does it work only in release mode or will it work in debug also?Empyrean
What about lines that are used but optimized-out by the compiler?Evermore
@Naveen: In Visual C++ 9 you have to turn optimization on and use /OPT:ICFAngle
@Itamar Katz: They can't be optimized out for no reason - either they are inlined or they are not used. You'll have to perform more analysis to distinguish between the two.Angle
@sharptooth: OK I see what you mean, but it's very labour intensive. I'll +1 if you can think of a way to automate the "try setting a breakpoint" step for all addresses or at least all functions (maybe this can be done in gdb somehow?)Este
S
2

CppDepend is a commercial tool which can detect unused types, methods and fields, and do much more. It is available for Windows and Linux (but currently has no 64-bit support), and comes with a 2-week trial.

Disclaimer: I don't work there, but I own a license for this tool (as well as NDepend, which is a more powerful alternative for .NET code).

For those who are curious, here is an example built-in (customizable) rule for detecting dead methods, written in CQLinq:

// <Name>Potentially dead Methods</Name>
warnif count > 0
// Filter procedure for methods that should'nt be considered as dead
let canMethodBeConsideredAsDeadProc = new Func<IMethod, bool>(
    m => !m.IsPublic &&       // Public methods might be used by client applications of your Projects.
         !m.IsEntryPoint &&            // Main() method is not used by-design.
         !m.IsClassConstructor &&      
         !m.IsVirtual &&               // Only check for non virtual method that are not seen as used in IL.
         !(m.IsConstructor &&          // Don't take account of protected ctor that might be call by a derived ctors.
           m.IsProtected) &&
         !m.IsGeneratedByCompiler
)

// Get methods unused
let methodsUnused = 
   from m in JustMyCode.Methods where 
   m.NbMethodsCallingMe == 0 && 
   canMethodBeConsideredAsDeadProc(m)
   select m

// Dead methods = methods used only by unused methods (recursive)
let deadMethodsMetric = methodsUnused.FillIterative(
   methods => // Unique loop, just to let a chance to build the hashset.
              from o in new[] { new object() }
              // Use a hashet to make Intersect calls much faster!
              let hashset = methods.ToHashSet()
              from m in codeBase.Application.Methods.UsedByAny(methods).Except(methods)
              where canMethodBeConsideredAsDeadProc(m) &&
                    // Select methods called only by methods already considered as dead
                    hashset.Intersect(m.MethodsCallingMe).Count() == m.NbMethodsCallingMe
              select m)

from m in JustMyCode.Methods.Intersect(deadMethodsMetric.DefinitionDomain)
select new { m, m.MethodsCallingMe, depth = deadMethodsMetric[m] }
Samsara answered 5/11, 2012 at 0:0 Comment(1)
Update: 64-bit support for Linux has been added in version 3.1.Samsara
A
1

It depends of the platform you use to create your application.

For example, if you use Visual Studio, you could use a tool like .NET ANTS Profiler which is able to parse and profile your code. This way, you should quickly know which part of your code is actually used. Eclipse also have equivalent plugins.

Otherwise, if you need to know what function of your application is actually used by your end user, and if you can release your application easily, you can use a log file for an audit.

For each main function, you can trace its usage, and after a few days/week just get that log file, and have a look at it.

Anteroom answered 27/1, 2011 at 8:26 Comment(2)
.net ANTS Profiler looks like it's for C# -- are you sure it works for C++ too?Este
@Este : as long as I know, It works with managed code. So .net ANTS will certainly not be able to analyse 'standard' C++ code (i.e. compiled with gcc, ...).Anteroom
D
1

I had a friend ask me this very question today, and I looked around at some promising Clang developments, e.g. ASTMatchers and the Static Analyzer that might have sufficient visibility in the goings-on during compiling to determine the dead code sections, but then I found this:

https://blog.flameeyes.eu/2008/01/today-how-to-identify-unused-exported-functions-and-variables

It's pretty much a complete description of how to use a few GCC flags that are seemingly designed for the purpose of identifying unreferenced symbols!

Destruction answered 11/7, 2013 at 3:43 Comment(2)
The blog link seems to have rotted. Wayback doesn't have it but I did find a Google cache: webcache.googleusercontent.com/…Pau
Thanks for tracking down the content for my dead link! Appreciate it. I think now that it's 10 years later the best way to solve this problem has surely changed.Destruction
M
0

I don't think it can be done automatically.

Even with code coverage tools, you need to provide sufficient input data to run.

May be very complex and high priced static analysis tool such as from Coverity's or LLVM compiler could be help.

But I'm not sure and I would prefer manual code review.

UPDATED

Well.. only removing unused variables, unused functions is not hard though.

UPDATED

After read other answers and comments, I'm more strongly convinced that it can't be done.

You have to know the code to have meaningful code coverage measure, and if you know that much manual editing will be faster than prepare/run/review coverage results.

Maighdlin answered 27/1, 2011 at 8:44 Comment(2)
the wording of your answer is misleading, there is nothing pricy about LLVM... it's free!Soloman
manual editing will not help you with run time variables that pass trough logic branches in your program. What if your code is never meeting a certain criteria and therefore always following the same path?Inappetence
F
0

The GNU linker has a --cref option which produces cross-reference information. You can pass this from the gcc command line via -Wl,--cref.

For instance, suppose that foo.o defines a symbol foo_sym which is also used in bar.o. Then in the output you will see:

foo_sym                            foo.o
                                   bar.o

If foo_sym is confined to foo.o, then you won't see any additional object files; it will be followed by another symbol:

foo_sym                            foo.o
force_flag                         options.o

Now, from this we do not know that foo_sym is not used. It's just a candidate: we know that it's defined in one file, and not used in any others. foo_sym could be defined in foo.o and used there.

So, what you do with this information is

  1. Do some text munging to identify these symbols that are confined to one object file, producing a list of candidates.
  2. Go into the source code, and give each of the candidates internal linkage with static, like it should have.
  3. Recompile the source.
  4. Now, for any of those symbols which are really unused, the compiler will be able to warn, pinpointing them for you; you can delete those.

Of course, I'm ignoring the possibility that some of those symbols are unused on purpose, because they are exported for dynamic linkage (which can be the case even when an executable is linked); that's a more nuanced situation that you have to know about and intelligently deal with.

Fannyfanon answered 24/1, 2022 at 2:24 Comment(0)
C
-2

The general problem of if some function will be called is undecidable. You cannot know in advance in a general way if some function will be called as you won't know if a Turing machine will ever stop. You can get if there's some path (statically) that goes from main() to the function you have written, but that doesn't warrant you it will ever be called. The set of decisions to decide if the function will be called is undecidable, if taken from a general form.

Cohbath answered 12/9, 2014 at 4:22 Comment(5)
True, but presumably what he means is that there are no actual calls to the function in the code, not whether there exist calls that may be unreachable.Pau
@DanielMcLaury, normally, the existence of unreachable calls is due to overestimating the functionality of some module and writing functions that are not used in the application. The general problem of determinine if a reachable function will be or won't be called, is NP-Complete, so I have said not stupid thing. The PO should be given (and give to us) more information than just How can I detect if any Turing machine will call the stop instruction or notCohbath
Other times (believe me, I have just written a tool for that) static unreachability is not the way, as you can have functions that are used as callbacks and so, they are always called through dereferencing their pointers, so there's no way to know (again) if an unreachable function will be finally called or not in the code. But unreachability gives you a starting point.Cohbath
a programmer that never uses git push will make git tests to consider that the push functionality is superfluous in git and can be eliminated. How can we determine if a call to a function will be made in some code. The test to call a function can be so call as to make the problem NP-Complete (you can make it undecidable)Cohbath
Sorry, where I said NP-Complete, I should have said undecidable.Cohbath
P
-3

Well if you using g++ you can use this flag -Wunused

According documentation:

Warn whenever a variable is unused aside from its declaration, whenever a function is declared static but never defined, whenever a label is declared but not used, and whenever a statement computes a result that is explicitly not used.

http://docs.freebsd.org/info/gcc/gcc.info.Warning_Options.html

Edit: Here is other usefull flag -Wunreachable-code According documentation:

This option is intended to warn when the compiler detects that at least a whole line of source code will never be executed, because some condition is never satisfied or because it is after a procedure that never returns.
Polyandrist answered 27/1, 2011 at 10:51 Comment(2)
This exact information has already been mentioned in the currently top-rated answer. Please read existing answers to avoid needless duplication.Este
Now you can earn your Peer Pressure badge!Vaasta

© 2022 - 2024 — McMap. All rights reserved.