[PATCH] D135849: [llvm] Return canonical virtual path from `RedirectingFileSystem`

Jan Svoboda via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Fri Jun 30 07:07:18 PDT 2023


jansvoboda11 added a comment.

Module map canonicalization in `clang-scan-deps` causes issues even after D135841 <https://reviews.llvm.org/D135841> landed.

Here's the problematic scenario this patch aims to solve:

- there is a framework `FW` whose headers (but not module maps) are redirected in a VFS overlay file
- there is a TU with `#import <fw/Header.h>` (note the incorrect case of the framework name)
- what follows is how Clang treats the involved file/directory paths:
  - find the incorrectly-cased header through the case-insensitive VFS overlay
  - chop off `Headers/Header.h`
  - call `FileManager::getCanonicalName()` on the `fw.framework` directory
    - `RedirectingFileSystem` calls the underlying FS to get the real path
      - note: this happens since the node is not `RedirectingFileSystem::{FileEntry,DirectoryRemapEntry}`, see the last branch of `RedirectingFileSystem::getRealPath()`
      - the underlying case-sensitive FS doesn't recognize the incorrectly-cased path
    - `FileManager` falls back to just using `Dir.getName()` (`fw.framework`) for that virtual `DirectoryEntry` as the canonical path
  - the `fw.framework/Modules/module.modulemap` file is not in the VFS overlay, and due to the wrong case, the underlying case-sensitive FW doesn't recognize it either
  - no matching module map means `#include <fw/Header.h>` is resolved to textual include
  - that header then includes other headers from the same FW using correct case: `#import <FW/AnotherHeader.h>`
  - the correctly-cased module map is found in the underlying FS and the framework gets compiled into a PCM file
  - at the end of dependency scan, scanner takes the correctly-cased module map path from the PCM file
  - scanner tries to canonicalize the module map path
    - `Modules/module.modulemap` is chopped off and `FileManager::getCanonicalName()` is called on the framework directory
    - `FileManager::getDirectory("FW.framework")` resolves to the same `DirectoryEntry` that `fw.framework` resolved to (VFS overlay is case-insensitive)
    - `FileManager` looks in the cache of canonical names and finds `fw.framework` for that virtual `DirectoryEntry`
    - `FW.framework/Modules/module.modulemap` is canonicalized to `fw.framework/Modules/module.modulemap`
  - scanner asserts that file exists, but it's not in the VFS nor in the underlying case-sensitive FS

This patch fixes this issue by returning the **canonical virtual path** for `fw.framework` at the very beginning. This is achieved by using the as-written spelling from the overlay file.

I can think of two other alternatives to this patch:

- In `ModuleMap::canonicalizeModuleMapPath()`, avoid canonicalization if the new module map path resolves to a different (or no) `FileEntry`.
- In `FileManager`, cache real paths based on the directory name, not the `DirectoryEntry`.

Both of these alternatives are workarounds, whereas the VFS fix seems fairly straightforward.

Note that I plan to add unit tests for this and add `// XFAIL: case-insensitive-filesystem` to the clang-scan-deps test if we get consensus on this approach.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D135849/new/

https://reviews.llvm.org/D135849



More information about the cfe-commits mailing list