Skip to content

C: a call resolves by exact name onto a static function in another translation unit (4,448 edges on betaflight) #1730

Description

@danusha2345

A static function in C is visible only in its own translation unit, but the exact-name strategy accepts it as the target of a call from any other file. When the caller's file has no same-named definition and another file has a static one, the call resolves onto it.

Reproduction

core.c:

void coreRun(void)
{
    usbGetDescriptor();
}

usb_audio.c:

static void usbGetDescriptor(void)
{
}

codegraph init, then the edges of coreRun:

coreRun --calls--> usb_audio.c::usbGetDescriptor   resolvedBy: exact-match

The real target is whatever core.c links against — a non-static usbGetDescriptor elsewhere, a function pointer, a macro — but never that one. When a same-file static of the same name exists the proximity score in findBestMatch picks it, so the wrong edge appears exactly when the caller's file has no definition, which is the case that matters for cross-file navigation.

Scale

On a 2,109-file betaflight tree, of 42,460 cross-file calls/imports edges resolved by exact-match or fuzzy, 4,448 target a function declared static in a file other than the caller's (10%). A typical run of them:

lib/main/AT32F43x/middlewares/usb_drivers/src/usbd_sdr.c:usbd_get_descriptor
  → lib/main/AT32F43x/middlewares/usbd_class/audio/audio_desc.c:get_device_descriptor      (static)
  → …/audio/audio_desc.c:get_device_configuration                                           (static)
  → …/audio/audio_desc.c:get_device_lang_id                                                 (static)

usbd_sdr.c calls those through a descriptor table of function pointers; audio_desc.c, cdc_desc.c, hid_desc.c, … each define their own static get_device_descriptor, and the matcher hands every call to the first file it ranks.

Relationship to #1719 / #1720

This is the C form of the same defect: a binding that the language makes file-local is admitted as a cross-file candidate. #1720's isSealedModule is deliberately JS/TS-only. In C the signal is per symbol, not per file — the definition's storage class — and the extractor already sees the static specifier on the function_definition, so it could either mark the node (a visibility/isStatic flag) or the resolver could read the definition line as #1720 reads source. Same-file candidates must stay eligible, and a static in a header included by the caller is a genuine same-unit call, which is the one exception to keep in mind.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions