Skip to content

Call Hierarchy Confuses Identically-Named Functions Across Modules in Multi-TU CMake Projects #878

@yunusemreayhan

Description

@yunusemreayhan

Please describe the problem.

In a multi-module CMake project that generates a single compile_commands.json file, clangd sometimes confuses identically named functions from different modules during call hierarchy lookups. For example, consider a project with two modules (modulex and moduley), each implementing a communication library with a function like init_communication(). When I right-click on a call to init_communication() in modulex's source file and select "Peek Call Hierarchy," the results incorrectly include incoming/outgoing calls to the similarly named function in moduley, even though these are distinct functions in separate translation units (TUs). This leads to misleading navigation and IDE features.

The issue appears tied to the shared compile_commands.json, where each module's source files have their own compile commands (with module-specific include paths), but clangd's indexing or symbol resolution seems to merge or ambiguously resolve these global-scope functions across TUs. I haven't confirmed if "Go to References" exhibits the same behavior, but call hierarchy is definitely affected, making it hard to trace calls within the correct module context.

This is problematic for large projects with reusable modules that share naming conventions (e.g., common utility functions). Regenerating compile_commands.json or restarting clangd doesn't resolve it consistently.

For hints on what information is helpful, see: https://clangd.llvm.org/troubleshooting.html

If you can, provide a minimal chunk of code that shows the problem (either inline, or attach it if larger).

Here's a minimal CMake project structure that reproduces the issue (assuming you build with CMake and generate compile_commands.json via cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=ON):

CMakeLists.txt

cmake_minimum_required(VERSION 3.20)
project(MultiModuleTest)

add_library(modulex STATIC modulex/comm.cpp)
target_include_directories(modulex PUBLIC modulex)

add_library(moduley STATIC moduley/comm.cpp)
target_include_directories(moduley PUBLIC moduley)

add_executable(main main.cpp)
target_link_libraries(main modulex moduley)

modulex/comm.h

#pragma once
void init_communication();  // ModuleX's version

modulex/comm.cpp

#include "comm.h"
#include <iostream>

void init_communication() {
    std::cout << "ModuleX init" << std::endl;  // Distinct implementation
}

moduley/comm.h

#pragma once
void init_communication();  // ModuleY's version (same signature)

moduley/comm.cpp

#include "comm.h"
#include <iostream>

void init_communication() {
    std::cout << "ModuleY init" << std::endl;  // Distinct implementation
}

main.cpp

#include "modulex/comm.h"
#include "moduley/comm.h"

int main() {
    init_communication();  // Call to ModuleX's version (due to include order?)
    return 0;
}

Build the project, open main.cpp in VSCode with clangd, and check the call hierarchy on the init_communication() call—it incorrectly mixes references from both modules. (Note: The ambiguity arises because both functions are global with identical signatures, and clangd doesn't fully disambiguate based on TU-specific includes.)

Logs

[Attach the clangd log from VSCode's Output panel here. To reproduce with more detail, add --log=verbose to clangd's arguments in VSCode settings (e.g., via clangd.arguments in settings.json), then reproduce the call hierarchy peek and attach the full log. The log should show symbol indexing and resolution steps for the functions.]

System information

clangd version 19.1.0
Features: linux+debug
Platform: x86_64-unknown-linux-gnu

clangd extension version:
Installation
Identifier
llvm-vs-code-extensions.vscode-clangd
Version
0.2.0
Last Updated
2025-06-10, 09:23:51
Size
1.37MB

Operating system: [e.g., Linux x86_64, macOS 14.0, Windows 11]

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions