You only offer emotional arguments ("a blight", "relic from the past", etc.).
Yes, the preprocessor does not work at the same level as the compiler - and that is the good thing about it because it gives you leverage about what the compiler sees and it allows you to guarantee that the logic outside the #ifdefs is untouched by any changes - therefore you get much higher quality/stability.
Your example with the untested feature can be solved by isolating the crazy untested code in its own module, and simply *not enabling that module in the build scripts*.
So you have to have modules for every tiny feature?
And all that bloat and overhead just to satisfy your emotional sense of aesthetics?
So to avoid 2 lines of "ugly" code (#ifdef / #endif) you need to create a module, adapt the build-system, etc. etc.?
And we have not even gone into some "advanced" stuff like
#if defined(TEST_1) && defined(TEST_2)
So easy to do with the preprocessor - how do you do that with modules? Create a third module that contains just the code that is needed when both other modules are included? And hide everything in the build-system so that nobody can find and/or debug it?
And again, why all that overhead when all you get is a program that is slower, uses more RAM and (yes!) is much more difficult to understand and debug?
Ideally, the buld-system should not contain any logic. All the logic should be in the source-code.
And of course your "aesthetics before function" - approach may be acceptable on the PC where all that bloat does not matter much. But it is a absolute no-go in embedded-systems programming. Just two years ago I have worked in a project where we had only 128 KB (yes, that is kilobytes) of RAM. And we had to frequently cut the bloat to stay under that limit.
In that situation you forget about "modules", object-orientation and all that other buzz-words from the ivory-tower pretty fast.
So what do you do when you have a new revision of a circuit board that has a different pin-layout?
Do you throw away everything (several man-months of programming and testing) and create a sophisticated module-system that will create numerous other problems and limitations to satisfy aesthetics?
No: You use the preprocessor to add the new stuff while still avoiding any change for the old, so the old stuff can still be used and tested and (more importantly) you can compare the old with the new.