[clang] When loading preamble from AST file, re-export modules in Sema.

This addresses a FIXME in ASTReader.

Modules were already re-exported for Preprocessor, but not for Sema.
The result was that, with -fmodules-local-submodule-visibility, all AST
nodes belonging to a module that was loaded in a premable where not
accesible from the main part of the file and a diagnostic recommending
importing those modules would be generated.

Differential Revision: https://reviews.llvm.org/D86069
This commit is contained in:
Adam Czachorowski 2020-08-14 16:37:34 +02:00
parent 53b9199a5c
commit baeff989b0
5 changed files with 60 additions and 3 deletions

View File

@ -26,7 +26,7 @@ TEST(Modules, TextualIncludeInPreamble) {
void foo() {}
)cpp");
TU.ExtraArgs.push_back("-fmodule-name=M");
TU.ExtraArgs.push_back("-fmodule-map-file=m.modulemap");
TU.ExtraArgs.push_back("-fmodule-map-file=" + testPath("m.modulemap"));
TU.AdditionalFiles["Textual.h"] = "void foo();";
TU.AdditionalFiles["m.modulemap"] = R"modulemap(
module M {
@ -39,6 +39,31 @@ TEST(Modules, TextualIncludeInPreamble) {
TU.index();
}
// Verify that visibility of AST nodes belonging to modules, but loaded from
// preamble PCH, is restored.
TEST(Modules, PreambleBuildVisibility) {
TestTU TU = TestTU::withCode(R"cpp(
#include "module.h"
foo x;
)cpp");
TU.OverlayRealFileSystemForModules = true;
TU.ExtraArgs.push_back("-fmodules");
TU.ExtraArgs.push_back("-fmodules-strict-decluse");
TU.ExtraArgs.push_back("-Xclang");
TU.ExtraArgs.push_back("-fmodules-local-submodule-visibility");
TU.ExtraArgs.push_back("-fmodule-map-file=" + testPath("m.modulemap"));
TU.AdditionalFiles["module.h"] = R"cpp(
typedef int foo;
)cpp";
TU.AdditionalFiles["m.modulemap"] = R"modulemap(
module M {
header "module.h"
}
)modulemap";
EXPECT_TRUE(TU.build().getDiagnostics().empty());
}
} // namespace
} // namespace clangd
} // namespace clang

View File

@ -1912,6 +1912,12 @@ public:
bool isModuleVisible(const Module *M, bool ModulePrivate = false);
// When loading a non-modular PCH files, this is used to restore module
// visibility.
void makeModuleVisible(Module *Mod, SourceLocation ImportLoc) {
VisibleModules.setVisible(Mod, ImportLoc);
}
/// Determine whether a declaration is visible to name lookup.
bool isVisible(const NamedDecl *D) {
return D->isUnconditionallyVisible() || isVisibleSlow(D);

View File

@ -4987,10 +4987,10 @@ void ASTReader::InitializeContext() {
/*ImportLoc=*/Import.ImportLoc);
if (Import.ImportLoc.isValid())
PP.makeModuleVisible(Imported, Import.ImportLoc);
// FIXME: should we tell Sema to make the module visible too?
// This updates visibility for Preprocessor only. For Sema, which can be
// nullptr here, we do the same later, in UpdateSema().
}
}
ImportedModules.clear();
}
void ASTReader::finalizeForWriting() {
@ -7943,6 +7943,15 @@ void ASTReader::UpdateSema() {
SemaObj->FpPragmaStack.CurrentPragmaLocation = FpPragmaCurrentLocation;
}
}
// For non-modular AST files, restore visiblity of modules.
for (auto &Import : ImportedModules) {
if (Import.ImportLoc.isInvalid())
continue;
if (Module *Imported = getSubmodule(Import.ID)) {
SemaObj->makeModuleVisible(Imported, Import.ImportLoc);
}
}
}
IdentifierInfo *ASTReader::get(StringRef Name) {

View File

@ -1 +1,3 @@
void make_foo(void);
typedef int MyType;

View File

@ -0,0 +1,15 @@
// Check that modules included in the preamble remain visible to the rest of the
// file.
// RUN: rm -rf %t.mcp
// RUN: %clang_cc1 -emit-pch -o %t.pch %s -fmodules -fmodule-map-file=%S/Inputs/modules/module.modulemap -fmodules-local-submodule-visibility -fmodules-cache-path=%t.mcp
// RUN: %clang_cc1 -include-pch %t.pch %s -fmodules -fmodule-map-file=%S/Inputs/modules/module.modulemap -fmodules-local-submodule-visibility -fmodules-cache-path=%t.mcp
#ifndef MAIN_FILE
#define MAIN_FILE
// Premable section.
#include "Inputs/modules/Foo.h"
#else
// Main section.
MyType foo;
#endif