If you want to debug preprocessor-generated code, -gdwarf-4 -g3 usually does the trick with GCC and Clang. If it doesn&#x27;t, you can just gcc -E it and run it through clang-format or something, and compile and debug the expanded version. It&#x27;s really not a big deal. You can have a Makefile rule to do this automatically, for example <a href="https:&#x2F;&#x2F;github.com&#x2F;alpha123&#x2F;yu&#x2F;blob&#x2F;master&#x2F;Makefile#L70-L103" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;alpha123&#x2F;yu&#x2F;blob&#x2F;master&#x2F;Makefile#L70-L103</a><p>Saying the C preprocessor can &quot;inject bugs&quot; and make code that &quot;can&#x27;t be easily traced&quot; is deceptive and wrong. It is, for all intents and purposes, a solved problem. That Makefile rule could be 3x shorter if I didn&#x27;t go for some extra niceties like not expanding system headers. (As usual, 20% of the result takes 80% of the work). The preprocessor doesn&#x27;t &quot;inject bugs&quot; anyway, unless you write very careless macros. Modern C, with things like __typeof, _Generic, and GCC&#x2F;Clang&#x27;s statement expressions means your macros can be totally safe against overwriting variables, double-evaluation, type errors, and more. You can, of course, still do silly things, but C isn&#x27;t about protecting the programmer anyway, and that&#x27;s totally fine if you&#x27;re prepared for it.<p>Perhaps in C++ the preprocessor is ‘pure evil’, but in C it&#x27;s a very useful part of the language.