"Worthless" is hyperbole, but what I really mean is "not functioning as intended", unless you do clean builds with high frequency. (There have been periods in my life where I never did clean builds at all, although creeping compiler malfeasance has led to an increase in full rebuilds.)
Here's a scenario: you have a policy of fixing certain warnings ("objectionable"), but not others ("ignorable"), so you don't have warnings-as-errors enabled because of the ignorable warnings.
You have a build containing foo.c, bar.c, and dozens of other files.
- You make changes to foo.c, bar.c, and several other files.
- You build your project,
- You get back a list of warnings in foo.c, bar.c, other files, and maybe an error or two.
- You fix the first few things in foo.c, but because errors cascade, only a few.
- repeat:
- rebuild
- fix first few errors and objectionable warnings, ignore ignorable warnings
- run your program
- passes tests, check in
Whoops! You just checked in a bar.c that has the objectionable warning. Because there were no errors in bar.c, it only got built on the first build, the one where you only fixed the stuff in foo.c. On all builds after that, bar.c hadn't changed, bar.o was newer that bar.c, so nothing else got built.
Unless you (a) process all output warnings from the compiler on every build, or (b) always do a full rebuild with high frequency (e.g. before every check-in), the philosophy of "i know what warnings this code has and they're all unobjectionable" is broken.
If you have multiple people enforcing the objectionable warnings, this is less of an issue since they will catch it when they check out the new bar.c, although they will be annoyed, so this only deeply hurts solo programmers. But it's still got to be annoying in a team environment.
(This is not just theory, I learned this the hard way.)
I prefer to fix all warnings even though I don't use warnings-as-errors. When debugging complex issues it's often useful to be able to run programs even when you get a few warnings, and debugging such systems can be rather irritating. (One work-related huge project had warnings-as-errors and I'm certain debugging was actually slower).
Also, when doing porting or other integration work with large codebases from third parties, not having to fix all warnings before getting things running is useful.
Finally, there's some cases where I've opted to turn certain warnings off rather than fixing them. In a way you could say that in those cases I've opted to ignore certain warnings - so much so that I've told the compiler not to mention about them. Those projects would have worked fine with warnings-as-errors as long as the warning-disabling pragmas worked.