whether they have missing header files.
Whether a module's headers happen to be present on the local file system
should make no difference to whether we make its contents visible when
importing another module that re-exports it. If we have an up-to-date
AST file that we can load, that's all that matters.
This fixes the ability to header syntax checking for modular headers in
C++20 mode (or in prior modes where -fmodules-local-submodule-visibility
is enabled but -fmodules is not).
SmallVector<Module *, 16> Exports;
V.M->getExportedModules(Exports);
for (Module *E : Exports) {
- // Don't recurse to unavailable submodules.
- if (E->isAvailable())
+ // Don't import non-importable modules.
+ if (!E->isUnimportable())
VisitModule({E, &V});
}
static bool isBetterKnownHeader(const ModuleMap::KnownHeader &New,
const ModuleMap::KnownHeader &Old) {
// Prefer available modules.
+ // FIXME: Considering whether the module is available rather than merely
+ // importable is non-hermetic and can result in surprising behavior for
+ // prebuilt modules. Consider only checking for importability here.
if (New.getModule()->isAvailable() && !Old.getModule()->isAvailable())
return true;
continue;
}
- if (!Mod->isAvailable()) {
- // Modules that aren't available cannot be made visible.
+ if (Mod->isUnimportable()) {
+ // Modules that aren't importable cannot be made visible.
continue;
}
llvm::SmallVector<Module *, 16> Worklist(1, WritingModule);
while (!Worklist.empty()) {
Module *M = Worklist.pop_back_val();
- if (!M->isAvailable())
+ // We don't care about headers in unimportable submodules.
+ if (M->isUnimportable())
continue;
// Map to disk files where possible, to pick up any missing stat
--- /dev/null
+#include "x.h"
+X a();
--- /dev/null
+#include "a.h"
+#include "b.h"
--- /dev/null
+#include "a.h"
+X b();
--- /dev/null
+module M {
+ module A { header "a.h" export * }
+ module B { header "b.h" export * }
+ module X { header "x.h" header "missing.h" export * }
+ module All { header "all.h" export * }
+}
--- /dev/null
+#ifndef X_H
+#define X_H
+struct X {};
+#endif
--- /dev/null
+// RUN: %clang_cc1 -fmodules-local-submodule-visibility -fimplicit-module-maps -I%S/Inputs/missing-header-local-visibility %s
+// RUN: %clang_cc1 -fmodules-local-submodule-visibility -fimplicit-module-maps -I%S/Inputs/missing-header-local-visibility -x c++-header %S/Inputs/missing-header-local-visibility/all.h
+// RUN: %clang_cc1 -fmodule-name=M -std=c++2a -fimplicit-module-maps -I%S/Inputs/missing-header-local-visibility -x c++-header %s
+// RUN: %clang_cc1 -fmodule-name=M -std=c++2a -fimplicit-module-maps -I%S/Inputs/missing-header-local-visibility -x c++-header %S/Inputs/missing-header-local-visibility/all.h
+
+#include "a.h"
+#include "b.h"