Skip to content

Commit 5c7f289

Browse files
committed
[clang][modules] Respect "-fmodule-name=" when serializing included files into a PCH
Clang writes the set of textually included files into AST files, so that importers know to avoid including those files again and instead deserialize their contents from the AST on-demand. Logic for determining the set of included files files only considers headers that are either non-modular or that are modular but with `HeaderFileInfo::isCompilingModuleHeader` set. Logic for computing that bit is different than the one that determines whether to include a header textually with the "-fmodule-name=Mod" option. That can lead to header from module "Mod" being included textually in a PCH, but be omitted in the serialized set of included files. This can then allow such header to be textually included from importer of the PCH, wreaking havoc. This patch fixes that by aligning the logic for computing `HeaderFileInfo::isCompilingModuleHeader` with the logic for deciding whether to include modular header textually. As far as I can tell, this bug has been in Clang for forever. It got accidentally "fixed" by D114095 (that changed the logic for determining the set of included files) and got broken again in D155131 (which is essentially a revert of the former). rdar://113520515 Reviewed By: benlangmuir Differential Revision: https://reviews.llvm.org/D157559 (cherry picked from commit bbdb0c7)
1 parent d95c83a commit 5c7f289

File tree

2 files changed

+34
-1
lines changed

2 files changed

+34
-1
lines changed

clang/lib/Lex/ModuleMap.cpp

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1265,6 +1265,20 @@ void ModuleMap::resolveHeaderDirectives(
12651265
Mod->UnresolvedHeaders.swap(NewHeaders);
12661266
}
12671267

1268+
// FIXME: duplicates code in PPDirectives
1269+
static bool isForModuleBuilding(const Module *M, StringRef CurrentModule,
1270+
StringRef ModuleName) {
1271+
StringRef TopLevelName = M->getTopLevelModuleName();
1272+
1273+
// When building framework Foo, we wanna make sure that Foo *and* Foo_Private
1274+
// are textually included and no modules are built for both.
1275+
if (M->getTopLevelModule()->IsFramework && CurrentModule == ModuleName &&
1276+
!CurrentModule.endswith("_Private") && TopLevelName.endswith("_Private"))
1277+
TopLevelName = TopLevelName.drop_back(8);
1278+
1279+
return TopLevelName == CurrentModule;
1280+
}
1281+
12681282
void ModuleMap::addHeader(Module *Mod, Module::Header Header,
12691283
ModuleHeaderRole Role, bool Imported) {
12701284
KnownHeader KH(Mod, Role);
@@ -1280,7 +1294,7 @@ void ModuleMap::addHeader(Module *Mod, Module::Header Header,
12801294
Mod->Headers[headerRoleToKind(Role)].push_back(Header);
12811295

12821296
bool isCompilingModuleHeader =
1283-
LangOpts.isCompilingModule() && Mod->getTopLevelModule() == SourceModule;
1297+
isForModuleBuilding(Mod, LangOpts.CurrentModule, LangOpts.ModuleName);
12841298
if (!Imported || isCompilingModuleHeader) {
12851299
// When we import HeaderFileInfo, the external source is expected to
12861300
// set the isModuleHeader flag itself.
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// RUN: rm -rf %t
2+
// RUN: split-file %s %t
3+
4+
// This test checks that headers that are part of a module named by
5+
// -fmodule-name= don't get included again if previously included from a PCH.
6+
7+
//--- include/module.modulemap
8+
module Mod { header "Mod.h" }
9+
//--- include/Mod.h
10+
struct Symbol {};
11+
//--- pch.h
12+
#import "Mod.h"
13+
//--- tu.c
14+
#import "Mod.h" // expected-no-diagnostics
15+
16+
// RUN: %clang_cc1 -fmodules -fmodules-cache-path=%t/cache -fimplicit-module-maps -fmodule-name=Mod -I %t/include \
17+
// RUN: -emit-pch -x c-header %t/pch.h -o %t/pch.pch
18+
// RUN: %clang_cc1 -fmodules -fmodules-cache-path=%t/cache -fimplicit-module-maps -fmodule-name=Mod -I %t/include \
19+
// RUN: -fsyntax-only %t/tu.c -include-pch %t/pch.pch -verify

0 commit comments

Comments
 (0)