Skip to content

Commit c5c47b4

Browse files
authored
Merge pull request #10086 from benlangmuir/eng/blangmuir/local-submodule-visibility-transitive-import
[stable/20240723][clang][modules] Fix local submodule visibility of macros from transitive import
2 parents 056331f + 0874112 commit c5c47b4

File tree

6 files changed

+85
-16
lines changed

6 files changed

+85
-16
lines changed

clang/include/clang/Basic/Module.h

+5-4
Original file line numberDiff line numberDiff line change
@@ -907,10 +907,11 @@ class VisibleModuleSet {
907907
StringRef Message)>;
908908

909909
/// Make a specific module visible.
910-
void setVisible(Module *M, SourceLocation Loc,
911-
VisibleCallback Vis = [](Module *) {},
912-
ConflictCallback Cb = [](ArrayRef<Module *>, Module *,
913-
StringRef) {});
910+
void setVisible(
911+
Module *M, SourceLocation Loc, bool IncludeExports = true,
912+
VisibleCallback Vis = [](Module *) {},
913+
ConflictCallback Cb = [](ArrayRef<Module *>, Module *, StringRef) {});
914+
914915
private:
915916
/// Import locations for each visible module. Indexed by the module's
916917
/// VisibilityID.

clang/include/clang/Lex/Preprocessor.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -1766,7 +1766,8 @@ class Preprocessor {
17661766
bool LexAfterModuleImport(Token &Result);
17671767
void CollectPpImportSuffix(SmallVectorImpl<Token> &Toks);
17681768

1769-
void makeModuleVisible(Module *M, SourceLocation Loc);
1769+
void makeModuleVisible(Module *M, SourceLocation Loc,
1770+
bool IncludeExports = true);
17701771

17711772
SourceLocation getModuleImportLoc(Module *M) const {
17721773
return CurSubmoduleState->VisibleModules.getImportLoc(M);

clang/lib/Basic/Module.cpp

+10-7
Original file line numberDiff line numberDiff line change
@@ -678,7 +678,8 @@ LLVM_DUMP_METHOD void Module::dump() const {
678678
}
679679

680680
void VisibleModuleSet::setVisible(Module *M, SourceLocation Loc,
681-
VisibleCallback Vis, ConflictCallback Cb) {
681+
bool IncludeExports, VisibleCallback Vis,
682+
ConflictCallback Cb) {
682683
// We can't import a global module fragment so the location can be invalid.
683684
assert((M->isGlobalModule() || Loc.isValid()) &&
684685
"setVisible expects a valid import location");
@@ -704,12 +705,14 @@ void VisibleModuleSet::setVisible(Module *M, SourceLocation Loc,
704705
Vis(V.M);
705706

706707
// Make any exported modules visible.
707-
SmallVector<Module *, 16> Exports;
708-
V.M->getExportedModules(Exports);
709-
for (Module *E : Exports) {
710-
// Don't import non-importable modules.
711-
if (!E->isUnimportable())
712-
VisitModule({E, &V});
708+
if (IncludeExports) {
709+
SmallVector<Module *, 16> Exports;
710+
V.M->getExportedModules(Exports);
711+
for (Module *E : Exports) {
712+
// Don't import non-importable modules.
713+
if (!E->isUnimportable())
714+
VisitModule({E, &V});
715+
}
713716
}
714717

715718
for (auto &C : V.M->Conflicts) {

clang/lib/Lex/PPLexerChange.cpp

+3-2
Original file line numberDiff line numberDiff line change
@@ -759,9 +759,10 @@ void Preprocessor::EnterSubmodule(Module *M, SourceLocation ImportLoc,
759759
// Switch to this submodule as the current submodule.
760760
CurSubmoduleState = &State;
761761

762-
// This module is visible to itself.
762+
// This module is visible to itself, but exports should not be made visible
763+
// until they are imported.
763764
if (FirstTime)
764-
makeModuleVisible(M, ImportLoc);
765+
makeModuleVisible(M, ImportLoc, /*IncludeExports=*/false);
765766
}
766767

767768
bool Preprocessor::needModuleMacros() const {

clang/lib/Lex/Preprocessor.cpp

+3-2
Original file line numberDiff line numberDiff line change
@@ -1336,9 +1336,10 @@ bool Preprocessor::LexAfterModuleImport(Token &Result) {
13361336
return true;
13371337
}
13381338

1339-
void Preprocessor::makeModuleVisible(Module *M, SourceLocation Loc) {
1339+
void Preprocessor::makeModuleVisible(Module *M, SourceLocation Loc,
1340+
bool IncludeExports) {
13401341
CurSubmoduleState->VisibleModules.setVisible(
1341-
M, Loc, [](Module *) {},
1342+
M, Loc, IncludeExports, [](Module *) {},
13421343
[&](ArrayRef<Module *> Path, Module *Conflict, StringRef Message) {
13431344
// FIXME: Include the path in the diagnostic.
13441345
// FIXME: Include the import location for the conflicting module.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
// Checks that macros from transitive imports work with local submodule
2+
// visibility. In the below test, previously a() and d() failed because
3+
// OTHER_MACRO1 and OTHER_MACRO3 were not visible at the use site.
4+
5+
// RUN: rm -rf %t
6+
// RUN: split-file %s %t
7+
// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t \
8+
// RUN: -fmodules-local-submodule-visibility -I%t %t/tu.c -verify
9+
10+
//--- Other1.h
11+
#define OTHER_MACRO1(...)
12+
13+
//--- Other2.h
14+
#define OTHER_MACRO2(...)
15+
16+
//--- Other3.h
17+
#define OTHER_MACRO3(...)
18+
19+
//--- module.modulemap
20+
module Other {
21+
module O1 { header "Other1.h" }
22+
module O2 { header "Other2.h" }
23+
module O3 { header "Other3.h" }
24+
}
25+
26+
//--- Top/A.h
27+
#include "Other1.h"
28+
#define MACRO_A OTHER_MACRO1(x, y)
29+
30+
//--- Top/B.h
31+
#include "Other2.h"
32+
#define MACRO_B OTHER_MACRO2(x, y)
33+
34+
//--- Top/C.h
35+
#include "D.h"
36+
37+
//--- Top/D.h
38+
#include "Other3.h"
39+
#define MACRO_D OTHER_MACRO3(x, y)
40+
41+
//--- Top/Top.h
42+
#include "A.h"
43+
#include "B.h"
44+
#include "C.h"
45+
46+
void a() MACRO_A;
47+
void b() MACRO_B;
48+
void d() MACRO_D;
49+
50+
//--- Top/module.modulemap
51+
module Top {
52+
umbrella header "Top.h"
53+
module A { header "A.h" export * }
54+
module D { header "D.h" export * }
55+
module * { export * }
56+
export *
57+
export Other.O3
58+
}
59+
60+
//--- tu.c
61+
#include "Top/Top.h"
62+
// expected-no-diagnostics

0 commit comments

Comments
 (0)