8 comments

[ 3.4 ms ] story [ 30.6 ms ] thread
It's interesting, but I hate to think this might have been the response to a junior developer's suggestion to clean up unused functions in a code base.
Really? At our company we ran out of compiler .text space and were shopping for things could remove. It depends ...
Dead code elimination is incredibly important for (statically linked) libraries though, usually you don't use the entire feature set of a library, and you also don't want to have the unused features end up in the executable. Traditionally this was done by building libraries from many tiny object files (e.g. one source- and object-file per function: https://github.com/ifduyue/musl/tree/master/src/stdio) since linkers would only work on 'object file granularity' and libraries are simply a container for object files, but the more recent and more flexible DCE strategies allow the same optimzation without splitting the library source code into hundreds of small files.
(comment deleted)
clang has a -Wunneeded-member-function that is not included in -Wall:

https://clang.llvm.org/docs/DiagnosticsReference.html#wunnee...

“warning: member function A is not needed and will not be emitted”

At least clang and gcc will also warn about unused static functions (included in -Wall though). IMHO that's a good reason to use static-by-default (and also not to split a project into a myriad of tiny source files, since this usually means less functions can be made static). Of course in the end LTO will take care of unused functions project-wide, but you'll not get a warning about stale functions that way.
> An optimizing linker might be able to prove that nobody needs those definitions, and eliminate them — I personally have worked on a linker that did exactly that optimization — but in general your mental model of a linker should be that it won’t do that optimization.

Not by default (for some reason), but the major compiler toolchains will all do it if you pass the right flags:

- Apple: Pass -dead_strip to linker

- Linux/ELF: Pass -Wl,--gc-sections to linker and -ffunction-sections -fdata-sections to compiler

- MSVC: Pass /opt:ref to linker and /Gw /Gy to compiler

(If you're building a dynamic library you also want -fvisibility=hidden on the Unix platforms.)