[clang] [clang][modules] HeaderSearch::MarkFileModuleHeader creates extra HeaderFileInfo, breaks PCM reuse (PR #89005)

Richard Smith via cfe-commits cfe-commits at lists.llvm.org
Wed Apr 17 13:22:27 PDT 2024


================
@@ -1313,6 +1313,14 @@ OptionalFileEntryRef HeaderSearch::LookupSubframeworkHeader(
 // File Info Management.
 //===----------------------------------------------------------------------===//
 
+static bool
+headerFileInfoModuleBitsMatchRole(const HeaderFileInfo *HFI,
+                                  ModuleMap::ModuleHeaderRole Role) {
+  return (HFI->isModuleHeader == ModuleMap::isModular(Role)) &&
+         (HFI->isTextualModuleHeader ==
+          ((Role & ModuleMap::TextualHeader) != 0));
----------------
zygoloid wrote:

If a file is in multiple modules, we use the logic in [`findModuleForHeader` and `isBetterKnownHeader`](https://github.com/llvm/llvm-project/blob/main/clang/lib/Lex/ModuleMap.cpp#L578) to pick between them when deciding how to handle a `#include`: prefer the declaration from the current module over anything else, prefer available over non-available, public over private, non-textual over textual, and (if we're allowing excluded headers at all) non-excluded over excluded.

If there's still a tie, then yeah, we make an arbitrary decision. (Not non-deterministic -- we prefer the first-loaded module map -- but also not likely to be predictable or useful. But it should generally not matter which one we pick -- the header should have been parsed and interpreted in the same way regardless -- unless different `.pcm`s have different compiler flags, in which case we have an ODR violation.)

The point of `textual header` -- at least in our configuration -- is to mark a header as being intentionally part of a module, so that `[no_undeclared_includes]` / `-fstrict-modules-decluse` can diagnose a `#include` of a file that wasn't a declared dependency. This means that it can be reasonable for a header to be a textual header in one module and a non-textual header in another module -- in particular, that would mean that code with a direct dependency on the first module is permitted to include the header, but that the header is not built as part of building that library. If that compilation is passed a `.pcm` containing the same header as a non-textual header, the desired behavior is that we perform an import for that header (treat it as non-textual for `#include` handling) but use the `textual header` declaration when determining whether the inclusion is permitted.

https://github.com/llvm/llvm-project/pull/89005


More information about the cfe-commits mailing list