C++ – Enforcing Manual Inclusion of Specific Header Files

ccode-securityprogramming practicesvisual studio

Banned.h is a list of ANSI C functions that Microsoft is trying to persuade programmers to deprecate. I already know how to enforce automatic inclusion of banned.h (such as the answer to Ensuring that headers are explicitly included in CPP file). Unfortunately, that answer has an important drawback.

Forced inclusion in project settings always includes the forced header first. Unfortunately, most of Microsoft's own system header files are not banned.h compliant, and many third party library headers are also not banned.h compliant. Microsoft claims that their usage of the banned APIs are safe, and has no intention of changing this situation. The primary way to use the system headers, then, is to include them before banned.h.

One way to solve this is to make a kind of meta_banned.h, which includes all possible system headers that are used anywhere in your project, as well as all the headers for any non-compliant third-party libraries, prior to including the regular banned.h. This is the first thing I did, but it causes an unfortunate hit to compile time because some of the third-party libraries have extensive headers.

We ended up with a hybrid approach–the meta_banned.h includes some system headers, and then the project settings for certain exceptional CPP files include the third-party headers as part of the force-include settings on that particular file. This works, but it's ugly and painful to maintain. The per-CPP-file forced includes in particular seem ugly.

What I really want is a method to ensure that banned.h is included somewhere in each file, not necessarily at the top. As long as it's included at some point, I consider the file compliant. If it's not included, I want to generate a build error. Any suggestions?

Best Answer

Ok, I would never in a million years do this, but you could do something like this:

Force auto inclusion of this:

// forcebanned.h
#define for "You must include banned.h"

Then add this:

// mybanned.h
#undef for
#include banned.h

But don't do that. Better is to make the inclusion of banned.h a coding standard, and rely on code reviews to catch it.

If you are really insistent on enforcing this technically, you could have a custom build step that grep'd files for "banned.h" prior to compilation, failing the build if the line isn't found. (Or use some static analysis tool that tags deprecated functions.) Doing so as part of the build keeps your code simpler, and more portable.