I’m not seeing this issue at all when testing with clang 4.0.1 and 6.0.0 (slightly out of date trunk), but the issue (if it exists in a different version) isn’t that function pointers are bad. That dead code should be removed in an early analysis passes of LLVM so there’s no chance of calling it later on.
FWIW, I think it’s with some versions. I see it with Clang 3.9.1:
> clang --version
clang version 3.9.1-4ubuntu3~16.04.1 (tags/RELEASE_391/rc2)
Thread model: posix
400520: eb ee jmp 400510 <_ZL8EraseAllv>
400522: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1)
400529: 00 00 00
40052c: 0f 1f 40 00 nopl 0x0(%rax)
400510: bf a4 05 40 00 mov $0x4005a4,%edi
400515: e9 b6 fe ff ff jmpq 4003d0 <system@plt>
40051a: 66 0f 1f 44 00 00 nopw 0x0(%rax,%rax,1)
and I just grabbed the build of Clang 5.0.0-svn312333-1~exp1 and see it there too.
Calling that an “optimization” is hilarious. The standard says that it does not specify what happens on a null call and the LLVM compiler writers have made the nutty determination that they can then assume there is no UB in the code.
Actually given all the extra work they have put into static warnings and UBSan….
Actually they are doing the right thing.
Admittedly In several places I believe the standards committee should just have had the balls to define a behaviour… which is one of the things I like about D.
One of the weird thing about the standard is that the committee says that non-portable code is a core part of C
And then it goes and tosses non-portable code into UB.
Even though I work with C in my day job, I always thought it’s nothing short of fucking bonkers that compiler writers are so focused on synthetic benchmarks that we have somehow come to accept, that of course this makes sense when it so clearly doesn’t.