Skip to content

Commit 38067c5

Browse files
committed
[C++20] [Modules] [Reduced BMI] Avoid force writing static declarations
within module purview Close #90259 Technically, the static declarations shouldn't be leaked from the module interface, otherwise it is an illegal program according to the spec. So we can get rid of the static declarations from the reduced BMI technically. Then we can close the above issue. However, there are too many `static inline` codes in existing headers. So it will be a pretty big breaking change if we do this globally.
1 parent 9d5411f commit 38067c5

File tree

2 files changed

+78
-2
lines changed

2 files changed

+78
-2
lines changed

clang/lib/Serialization/ASTWriter.cpp

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3205,6 +3205,17 @@ void ASTWriter::WriteType(QualType T) {
32053205
// Declaration Serialization
32063206
//===----------------------------------------------------------------------===//
32073207

3208+
static bool IsInternalDeclFromFileContext(const Decl *D) {
3209+
auto *ND = dyn_cast<NamedDecl>(D);
3210+
if (!ND)
3211+
return false;
3212+
3213+
if (!D->getDeclContext()->getRedeclContext()->isFileContext())
3214+
return false;
3215+
3216+
return ND->getFormalLinkage() == Linkage::Internal;
3217+
}
3218+
32083219
/// Write the block containing all of the declaration IDs
32093220
/// lexically declared within the given DeclContext.
32103221
///
@@ -3225,6 +3236,15 @@ uint64_t ASTWriter::WriteDeclContextLexicalBlock(ASTContext &Context,
32253236
if (DoneWritingDeclsAndTypes && !wasDeclEmitted(D))
32263237
continue;
32273238

3239+
// We don't need to write decls with internal linkage into reduced BMI.
3240+
// If such decls gets emitted due to it get used from inline functions,
3241+
// the program illegal. However, there are too many use of static inline
3242+
// functions in the global module fragment and it will be breaking change
3243+
// to forbid that. So we have to allow to emit such declarations from GMF.
3244+
if (GeneratingReducedBMI && !D->isFromExplicitGlobalModule() &&
3245+
IsInternalDeclFromFileContext(D))
3246+
continue;
3247+
32283248
KindDeclPairs.push_back(D->getKind());
32293249
KindDeclPairs.push_back(GetDeclRef(D).get());
32303250
}
@@ -3886,6 +3906,13 @@ class ASTDeclContextNameLookupTrait {
38863906
!Writer.wasDeclEmitted(DeclForLocalLookup))
38873907
continue;
38883908

3909+
// Try to avoid writing internal decls to reduced BMI.
3910+
// See comments in ASTWriter::WriteDeclContextLexicalBlock for details.
3911+
if (Writer.isGeneratingReducedBMI() &&
3912+
!DeclForLocalLookup->isFromExplicitGlobalModule() &&
3913+
IsInternalDeclFromFileContext(DeclForLocalLookup))
3914+
continue;
3915+
38893916
DeclIDs.push_back(Writer.GetDeclRef(DeclForLocalLookup));
38903917
}
38913918
return std::make_pair(Start, DeclIDs.size());
@@ -4257,6 +4284,12 @@ uint64_t ASTWriter::WriteDeclContextVisibleBlock(ASTContext &Context,
42574284
if (DoneWritingDeclsAndTypes && !wasDeclEmitted(ND))
42584285
continue;
42594286

4287+
// We don't need to force emitting internal decls into reduced BMI.
4288+
// See comments in ASTWriter::WriteDeclContextLexicalBlock for details.
4289+
if (GeneratingReducedBMI && !ND->isFromExplicitGlobalModule() &&
4290+
IsInternalDeclFromFileContext(ND))
4291+
continue;
4292+
42604293
GetDeclRef(ND);
42614294
}
42624295
}
@@ -4917,8 +4950,7 @@ void ASTWriter::PrepareWritingSpecialDecls(Sema &SemaRef) {
49174950
// is ill-formed. However, in practice, there are a lot of projects
49184951
// uses `static inline` in the headers. So we can't get rid of all
49194952
// static entities in reduced BMI now.
4920-
if (auto *ND = dyn_cast<NamedDecl>(D);
4921-
ND && ND->getFormalLinkage() == Linkage::Internal)
4953+
if (IsInternalDeclFromFileContext(D))
49224954
continue;
49234955
}
49244956

clang/test/Modules/pr90259.cppm

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
// RUN: rm -rf %t
2+
// RUN: mkdir -p %t
3+
// RUN: split-file %s %t
4+
//
5+
// RUN: %clang_cc1 -std=c++20 %t/mod1.cppm -emit-reduced-module-interface -o %t/mod-mod1.pcm
6+
// RUN: %clang_cc1 -std=c++20 %t/mod.cppm -fprebuilt-module-path=%t \
7+
// RUN: -emit-reduced-module-interface -o %t/mod.pcm
8+
// RUN: %clang_cc1 -std=c++20 %t/use.cpp -fprebuilt-module-path=%t -verify -fsyntax-only
9+
10+
//--- mod1.cppm
11+
export module mod:mod1;
12+
namespace {
13+
int abc = 43;
14+
}
15+
namespace mod {
16+
static int def = 44;
17+
}
18+
export int f() {
19+
return abc + mod::def;
20+
}
21+
22+
//--- mod.cppm
23+
// expected-no-diagnostics
24+
export module mod;
25+
import :mod1;
26+
27+
namespace {
28+
double abc = 43.0;
29+
}
30+
31+
namespace mod {
32+
static double def = 44.0;
33+
}
34+
35+
export double func() {
36+
return (double)f() + abc + mod::def;
37+
}
38+
39+
//--- use.cpp
40+
// expected-no-diagnostics
41+
import mod;
42+
double use() {
43+
return func();
44+
}

0 commit comments

Comments
 (0)