Skip to content

fromRanges for outgoing calls is incorrect for function declarations #2350

Closed
llvm/llvm-project
#134657
@HampusAdolfsson

Description

@HampusAdolfsson

I've been trying out the new outgoing call functionality and found a bug when requesting outgoing calls on a function declaration.

The fromRanges of an outgoing calls response should list where in the function each outgoing call is made. According to the specification, these implicitly refer to the file we used in the outgoing calls request. However, if the request was made on a function declaration and the function implementation is in a different file, clangd returns fromRanges for the implementation file, and there's no way for the client to know that this is the case.

To exemplify:

/// lib.h
void lib_func();

/// lib.c
#include "lib.h"
void lib_func() { }

/// app.h
void func();
//    ^ request outgoing calls here

/// app.c
#include "app.h"
#include "lib.h"
void func() {
  lib_func();
}

Requesting outgoing calls for func in app.h gives this response:

[
  {
    "fromRanges": [
      {
        "end": {
          "character": 10,
          "line": 3
        },
        "start": {
          "character": 2,
          "line": 3 //<-- NOTE
        }
      }
    ],
    "to": {
      "data": "B95D8C2A26F1DE47",
      "detail": "lib_func",
      "kind": 12,
      "name": "lib_func",
      "range": {
        "end": {
          "character": 13,
          "line": 1
        },
        "start": {
          "character": 5,
          "line": 1
        }
      },
      "selectionRange": {
        "end": {
          "character": 13,
          "line": 1
        },
        "start": {
          "character": 5,
          "line": 1
        }
      },
      "uri": "file:///d:/clangd_outgoing_calls/lib.c"
    }
  }
]

Note that the fromRanges element refers to line 3. A client would interpret
this to refer to app.h line 3, since we made the call from app.h, but that
line doesn't exist. It seems like the range refers to the lib_func call in
app.c, but there's no way for the client to know that.

As far as I can tell, the specification provides no way to handle this except to
omit any fromRanges that are not in the same file (so clangd should return
an empty fromRanges in this case).

System information

Output of clangd --version:

clangd version 20.1.0
Features: windows
Platform: x86_64-pc-windows-msvc

Editor/LSP plugin: I found this while working on an unreleased clangd
integration for a proprietary editor. VS Code doesn't use fromRanges at the
moment, but you can verify the behaviour anyway by enabling verbose logging and
using VS Code's call hierarchy functionality.

Operating system: Windows 11

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions