Skip to content

[clang-tidy] checker to get rid of raw function pointer usages #171662

@denzor200

Description

@denzor200

Motivation

Many C++ codebases still use C-style function pointers (return_type (*)(parameters)) for callbacks and strategy patterns:

// BAD - Legacy C-style function pointer
void register_callback(void (*callback)(int, void*), void* user_data);

// BAD - Function taking raw function pointer
void process_data(int* array, size_t size, int (*transform)(int));

This approach is inflexible and cannot work with:

  • Lambda expressions with captures;
  • Function objects (functors);
  • std::bind expressions;
  • std::mem_fn expressions.
register_callback([&](int value, void*) { /* lambda with capture */ }, d); // won't be compiled
process_data(arr, n, [](int x) { return x * 2; }); // won't be compiled

Proposed Solution

Add a clang-tidy check that identifies raw function pointer parameters and suggests converting them to more flexible alternatives:

// GOD - converted to std::function
void register_callback(const std::function<void(int)>& callback);

// GOD - converted to template version
template<typename F>
void process_data(int* array, size_t size, F&& transform);

Since the first option can negatively impact performance, it's better to use the second one whenever possible—in static functions and functions declared in A-files. However, the second option can lead to binary bloat, so it shouldn't be used for very large functions.

Special Cases

  1. C API Compatibility
// Should NOT warn when extern "C" or __cdecl specified
extern "C" {
    void take_c_api_callback(void (*callback)(int));  // No warning
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions