https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89299
--- Comment #7 from Andrew Pinski <pinskia at gcc dot gnu.org> --- The issue is we don't do any overload resolution for the function in cleanup attribute; most likely because the attribute was originally added for C. Also in C++ you could just use a wrapper class to do the same thing. take: void cu_char( char** s ) { if ( s && *s ) { free ( *s ); } } void cu_char( int** s ) { if ( s && *s ) { free ( *s ); } } int main() { __attribute__((cleanup(cu_char))) char* s = nullptr; return 0; } For C++ you could something like: #include <cstdlib> template <class T> struct cleanup_class { T a; void (*f)(T*); cleanup_class(void (*f1)(T*)) : a{}, f(f1) { } cleanup_class(T &b, void (*f1)(T*)) : a(b), f(f1) { } cleanup_class(cleanup_class&) = delete; cleanup_class(cleanup_class&&) = delete; ~cleanup_class() { f(&a);} operator T&() { return a; } T &operator =(const T &b) { return a = b;} }; template <typename T> void cu( T** p ) { if ( p && *p ) { free( *p ); } } int main() { cleanup_class<char*> t(cu); t = 0; return 0; } Note this is not the best code, just the quick I wrote up.