<table border="1" cellspacing="0" cellpadding="8">
    <tr>
        <th>Issue</th>
        <td>
            <a href=https://github.com/llvm/llvm-project/issues/116877>116877</a>
        </td>
    </tr>

    <tr>
        <th>Summary</th>
        <td>
            clangd: IncludeInserter does not deal with directory symlinks within include directories (and VFS overlay workarounds are variously broken)
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
            new issue
      </td>
    </tr>

    <tr>
      <th>Assignees</th>
      <td>
      </td>
    </tr>

    <tr>
      <th>Reporter</th>
      <td>
          lf-
      </td>
    </tr>
</table>

<pre>
    When using clangd, the auto-include suggestions are broken in a project like the following (which you can clone from https://git.jade.fyi/jade/clangd-bug-repro):

build.sh:
```
clang++ -std=c++20 -Iinclude/ src/foo.cc -c -o src/foo.cc.o
```

Generate a compile_commands.json via bear or so.

Tree:

```
.
├── build.sh
├── compile_commands.json
├── include
│   └── lib2 -> ../lib2
├── lib2
│   ├── bar.hh
│   └── foo.hh
└── src
    ├── foo.cc
    ├── nya.hh
    └── wat.hh
```

`foo.cc`:

```cpp
#include "lib2/foo.hh"
#include "nya.hh"
#include "wat.hh"

void thingy() {
    frob();
    wat();
    lolwut();
}
```

`lib2/foo.hh`:

```
int frob();
```

`lib2/bar.hh`:

```
void showNyanCat();
```

Then open lib2/bar.hh in a new tab to make sure clangd knows about it. Tab-complete a call to `showNyanCat()`, which will not add the header include. By comparison, doing the same for a symbol in, e.g., wat.hh, will successfully add the include.

I have debugged this to find that `HeaderPath::suggestPathToFileForDiagnostics` returns an absolute path for the file in question, which is then promptly rejected downstream by clangd:

https://github.com/llvm/llvm-project/blob/3f156ef4cc333bcf9389addd1e0054b654501d7e/clang-tools-extra/clangd/Headers.cpp#L292-L306

The proximate cause of the absolute paths from `suggestPathToFileForDiagnostics` is that there are no `-I` directories or parents of the file in question that are common prefixes of the canonical file path of the translation unit and the canonical path of the header file. Seemingly the only way to get this to work today is to *make* the canonical path of the header a child of the include directory. However, this requires rearranging source code around what is IMO a clang bug or at least deficiency.

Another alternative (which I have not tried, and which has kind of bad ergonomics since it is busted for newly created files) is generating a header map specifically for clangd since those are special cased in `suggestPathToFileForDiagnostics`. Yet another alternative which *does* work but is absurd is:

.clangd containing `{"CompileFlags": {"Add": ["-I", ".include"], "Remove": ["-I", "../src/include"]}}` and then running clangd in a bwrap that bindmounts `.include/lix = src` (in the actual problem in the field, the problem is that we have includes of the form `lix/libfoo/bar.hh` which need to resolve to `src/libfoo/bar.hh`, so just putting more `../` is not a fix).

I have tried the following VFS overlay:

```yaml
version: 0
roots:
  - name: include/lib2
    type: directory-remap
    external-contents: lib2/
    # plus or minus the following line; same results either way
    # use-external-name: true
```

and then added via `-Xclang -ivfsoverlay -Xclang ./vfsoverlay.yaml`. This compiles fine but the include inserter still refuses to work for presumably the same reason. It appears that the remapping is treated as if it is a symlink rather than as a bind mount, I think. I have not shoved the thing into rr yet.

At this point I've spent enough time debugging and writing this up that I am looking for input on whether this is a completely busted use case or if I have missed something in this adventure.
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJycWNlu6zgS_RrmpSBBpmI7fvBDlva0gZ4F0xezPA0oqWTxhiLVXOzo7wdFSraT-HZ6Bggci3sVT51zZOGcPGjELVs-seXLnQi-M3ar2uyuMs24_WeHGoKT-gC1EvrQMP4MvkMQwZtM6lqFBsGFwwGdl0Y7EBahsuYVNUgNAgZrvmPtQclXjDNbo5Q50YqMP5w6WXcwmgC10FAroxFaa3rovB8cKx8Z3zG-O0iffxcN5u0oGd_RV8Z36URZFQ6ZxcEaxjc0o3hhxfRZBama3HWX5lUx_cXHuALjT4w_QeZ8w8qXOj3yArL9FB_jO3C2ZnzXGpPXNWQ1ZOZdU25urp8-_4QarfAIAmrTD1Lhf2rT90I3Lv_ujIajFFChsGAsOJNfz_1mET8E9WGPefhPnG3u2eZ5-vJQnL_AOQ1fjrx5vq-nzYm6HvjA2TNnj0X6hHn6_Y3pSlYcMlb-BHnO-I4ev97z06gfbHgzIcLmXff_Hpeu_MPsm-MIIHEQAPzucRKG_thYPYrz5tdjbx3gJPzloLeQyVbFtPeq-BHK6mGYWng5FzzjPKY_wb_rGOe3xkxnvd05He7cGT-PRjbgO6kPI-MPjG-ArZ8uwbbWVKmdlVfNJ-FvtCqjTuFjB1u__H4-3sf147SkR6n9rUN9sfgEv68Wj8lwnTn9ZRT6-VOMNzf5RoRtBtTwbq_ExRpP4EUF3kAvXom3LU68Dq_anByIygQP0ufwTVQZsYHCRFxCKZrHVsXnE60KkoXE5SepFGjjQTRN5PsORYN2pogcnsbIMsJKohb-DI0hMaChTvSkDxYEuLGvjAIZR2B-yOMOE2Se0y4u1DU61walxvN28z7XSdlDJ44IDVYkVBFgjoJppaYH4Smsn-M5_yZ8VIvycRI1avhmdlLhztgXKQ7aOC9rx1YFWPTBkuZpEJUzKniEQfguxhC1Tio6EfwWkjxe0kQHoKsarOkHr0awSDKJDTTmpJ23KHqoxll13-Pkkzh2ocpr0xN3quP8L5ukl0CgCKK7sl0sV9je13VZllXdbsqHjWiaZoFFsbyvVsv7ZbFo1mdtzbwxymX45q046y3ju5QqlxM18PIXvuHZL2Wx-oBDiu1N9iR8tQgOwbTJOlynyiW5J1h9ne-YNOFpFYvRaeiIyGxPvY20WHtjJToS0kFY1N7Nu368irQSrUFaZ-gmsJVveJ5QC220rIVKU-O9Tl3eCu2UiMsELT0I3XyYcz18qgBaJodfEXupD2qMXUarEU5iJDQe0J-ReTL2FbxpxAipgfFHKlnGH7_eSEDdSdXMrTPnzvkZc_jZnPCINpk56cDib0FapC_CWqEPVJHOBFtTehrKtQm6gRPlTDrY__mvtAvhAapwoHQLDwqF89BgK2uJuh7f1eCjNnRtIJRHq4WXR7wYwKlAiTa8lRhdpoj7UW8nHLxSqZoWKtEA2oPRppe1Ayd1jSDjoargqH6o9jSe1Ai1RRFbpEJHWiIdHJIXo_jEnK9eDOAGrGVLGVVjXGKixbSB74xLgIvjhIJaOGwIT38IuTn8Gwkln1OQImT8sTF0xsd081WIEYnKBduAdB_qP58OVxvthdTRS68KUkrOn5OD2ylxcCSu5SOkjsemmZ-X9Jzt6ZE_kxbnZ6fL2fJlavw79uaIP55DVi154Pez1_FvVcxVocEGrS-vEEmLqpMVQyrCSuqmN4GKlXJ1cd1KvgErX6KRWhUEF6kThdQ-EPatqRT2MLW2EtX5BeXcN3HGCRPGptUvvGBspB8l35L1bI25lujphjSSbhiw6Iw64iyFMfzPk-gQzsD34DwMwUe49cZijI_yNrFZ1EloaevNLcWKxfDhrekfu1_BHNEqMf7IPoyiV5OFQOtId8pHmGyCNcZf8ASQgRY9vWLAdd5na00-yo9D7D_zR2axF8NlAL5FPKuM8EicS6Mn-3FlVHkJgwqRm3upg_sQl5IaWfmUTIBFF5R3gDJWzEmM7xcKDrPztnMA3gb8HWt0hqNoGmziSxdpx78SjWXy2LoprzA30lVdmvOYV6rmb0Sa07uSIxuBsWSv2VZqh9ajBefJq1hsg8MLtxPFDBRlL6pJC6bAhTM6h70HMQwo7EXyIKZ9oFwRqCdyEw5kOzFgtE1K6lewIubNd2RNqINqDGKRETb30WO_5tfE6zpznMAWDThITXi3MKJ_z-STTA2G3O-e8fUx8qL2gNqEQwde9rPbikRLTG6lTzZPOghT4e9B9KCMeaUeyojUQ_BgNJw6nAKQLkU2e1E1zkRPloJomAAl2zmUXjpiZmd6nMNIq4jmiNoHi_ldsy2bTbkRd7hdrEteLIvVorjrtkXVrktcLNa4rBe4WrdrXiw295v2YcHXdf1wJ7e84PeLxWLDF4tiUeSbxbJYtk2zqQq-rDfI7gvshVQ5GbDc2MOddC7gdrFYPazXd0pUqNw2kSm58dibePPObqNrq8LBsftCSefdZRkvvcLt2Q3CPsFsP6OM5CNeY4NCwUn67lKvMypcbJf6kyMgx8T4A93TFbtEoCbhTz_rHIWVJji6gfgDD-Obu2DV9n-2ozFqx_huSstxy_8bAAD___TnwLo">