2

Assume we have the following C code:

void undefined_reference(void);

void bad(void) {
    undefined_reference();
}

int main(void) {}

In function bad we fall into the linker error undefined reference to 'undefined_reference', as expected. This function is not actually used anywhere in the code, though, and as such, for the execution of the program, this undefined reference doesn't matter.

Is it possible to compile this code successfully, such that bad simply gets removed as it is never called (similar to tree-shaking in JavaScript)?

John Bollinger
  • 160,171
  • 8
  • 81
  • 157
Post Self
  • 1,471
  • 2
  • 14
  • 34
  • 2
    There are linkers that strip dead code, in conjunction with compiler support, so it may be possible to compile and link this code successfully with the right tools. But you have not indicated which tools you are using or are interested in. As a matter of theory, yes, this is possible. As a matter of what can be accomplishing using only features specified by the C standard, no, it is not possible to guarantee successful compiling and linking. For a specific answer between those, you need to identify the tools to be used. – Eric Postpischil Jan 30 '23 at 14:51
  • You could also do other weird tricks, such as exporting `undefined_reference` symbol from a linker script. But why? Just delete the dead code. – Eugene Sh. Jan 30 '23 at 14:53
  • Removing the [tree-shaking] tag, since that is associated specifically with ECMAscript, and the question is about C. – John Bollinger Jan 30 '23 at 14:54
  • You could put `bad` into an object file in a library and link the program with the library so that the object file containing `bad` only gets linked in if something needs it. – Ian Abbott Jan 30 '23 at 15:38
  • @IanAbbott Did you mean the `undefined_reference()` ? I guess `bad()` is "fixed" – Eugene Sh. Jan 30 '23 at 15:43
  • @EugeneSh. I *do* mean moving `bad()` into a library. If something outside the library calls `bad()` (perhaps indirectly from some other function in the library) then something will also need to provide an external definition of `undefined_reference()`. – Ian Abbott Jan 30 '23 at 15:48
  • @EugeneSh. Or to be more accurate, if something outside the library *refers* to the `bad()` function (not necessarily *call* it) (perhaps indirectly) then something will also need to define `undefined_reference()`. – Ian Abbott Jan 30 '23 at 15:56

2 Answers2

4

This function is not actually used anywhere in the code!

You know that, I know that, but the compiler doesn't. It deals with one translation unit at a time. It cannot divine out that there are no other translation units.

But main doesn't call anything, so there cannot be other translation units!

There can be code that runs before and after main (in an implementation-defined manner).

OK what about the linker? It sees the whole program!

Not really. Code can be loaded dynamically at run time (also by code that the linker cannot see).

So neither the compiler nor linker even try to find unused function by default.

On some systems it is possible to instruct the compiler and the linker to try and garbage-collect unused code (and assume a whole-program view when doing so), but this is not usually the default mode of operation.

With gcc and gnu ld, you can use these options:

gcc -ffunction-sections -Wl,--gc-sections main.c -o main

Other systems may have different ways of doing this.

n. m. could be an AI
  • 112,515
  • 14
  • 128
  • 243
  • The linker, in most cases, is able to eliminate unused *sections*. I am not sure what is the default here, but it is also able to place each function in a separate section (in fact it is the compiler who can). So with these two abilities it can (and will) eliminate unused functions. – Eugene Sh. Jan 30 '23 at 15:08
  • 1
    @EugeneSh. Added options that enable this behaviour. – n. m. could be an AI Jan 30 '23 at 15:14
1

Many compilers (for example gcc) will compile and link it correctly if you

  1. Enable optimizations
  2. make function bad static. Otherwise, it will have external linkage.

https://godbolt.org/z/KrvfrYYdn

Another way is to add the stump version of this function (and pragma displaying warning)

0___________
  • 60,014
  • 4
  • 34
  • 74