Hi all, A codebase I'm working with has decided that poisoning certain standard library functions is necessary, as it explicitly does not use those functions unless absolutely necessary for its own reasons (This was not my decision to make). As such, we've been looking into ways to implement that.
The problem is there's really no way at all to forbid standard library functions. The crucial thing is that this mechanism must have a disable switch for when a callsite must actually call a forbidden function, complicating the whole process. It would be nice to have compiler support to help with this. Something like: #pragma GCC forbidden void *malloc(size_t) // Forbids malloc from being called anywhere #pragma GCC permitted push #pragma GCC permitted void *malloc(size_t) void *ptr = malloc(1); // This callsite must use malloc, bypassing the usual restriction #pragma GCC permitted pop However, I'm guessing this would be a bit complex to implement. There are other ways I have tried as well, such as: #include <cstdlib> namespace permitted { using ::malloc; } inline namespace forbidden { [[deprecated("use os::malloc")]] void *malloc(size_t) throw() = delete; } int main() { void *ptr = malloc(1); // Should raise an error, must call permitted::malloc(1) to avoid free(ptr); } The problem with the above is that the error isn't from the function being deleted or marked as deprecated, it's an ambiguity error that is confusing and doesn't tell the developer why the error is actually happening (Because the function has been forbidden). Additionally, there is no way to disable this system in third party headers included from the testing framework, making it unusable. Given this, could I request some sort of compiler specific "shadow" attribute that can be applied to a namespace? With this attribute, the symbols in this namespace will take precedence over the symbols of the namespace it is in (Including the global namespace, if its parent is in the global namespace) if it is injected into the parent, either because it is inline, unnamed, or because of a using namespace x; declaration. This contrasts with the standard behaviour of raising an ambiguity error when trying to resolve which symbol to use, instead, the symbol from the namespace marked as shadow will always be given precedence. #include <cstdlib> namespace permitted { using ::malloc; } inline namespace [[gnu::shadow]] forbidden { [[deprecated("use os::malloc")]] void *malloc(size_t) throw() = delete; } int main() { void *ptr = malloc(1); // Correct error shown, forbidden::malloc chosen over standard library free(ptr); } Ideally shadow could have another effect on using declarations. Normally, trying to do a using declaration to choose between 2 conflicting symbols will just fail: #include <cstdlib> namespace permitted { using ::malloc; } inline namespace forbidden { [[deprecated("use os::malloc")]] void *malloc(size_t) throw() = delete; } using forbidden::malloc; int main() { void *ptr = malloc(1); free(ptr); } <source>:11:18: error: 'void* forbidden::malloc(size_t)' conflicts with a previous declaration 11 | using forbidden::malloc; | ^~~~~~ Perhaps, if one of those symbols comes from a namespace marked as shadow, the using declaration would instead behave differently, choosing which declaration is used instead of just bringing the declaration into scope: #include <cstdlib> namespace permitted { using ::malloc; } inline namespace [[gnu::shadow]] forbidden { [[deprecated("use os::malloc")]] void *malloc(size_t) throw() = delete; } using forbidden::malloc; // From now on, any calls to malloc use forbidden::malloc using ::malloc; // From now on, any call to malloc go to ::malloc using permitted::malloc; // From now on, any call to malloc goes to permitted::malloc Or alternatively, is there a better way to do this instead of adding custom support to the compiler? The gcc static analyzer doesn't seem to support C++ yet nor does it seem to have a configurable check for whether you are calling a given function, neither does VC for that matter. Maybe this could be an analyzer request instead of a compiler feature request. Either way, I'm open to suggestions. best regards, Julian