Skip to content

Commit 82f8e45

Browse files
committed
[clang][modules] Delay creating IdentifierInfo for names of explicit modules
When using explicit Clang modules, some declarations might unexpectedly become invisible. This is caused by the mechanism that loads PCM files passed via `-fmodule-file=<path>` and creates an `IdentifierInfo` for the module name. The `IdentifierInfo` creation takes place when the `ASTReader` is in a weird state, with modules that are loaded but not yet set up properly. This patch delays the creation of `IdentifierInfo` until the `ASTReader` is done with reading the PCM. Note that the `-fmodule-file=<name>=<path>` form of the argument doesn't suffer from this issue, since it doesn't create `IdentifierInfo` for the module name. Reviewed By: dexonsmith Differential Revision: https://reviews.llvm.org/D111543
1 parent 863531f commit 82f8e45

File tree

5 files changed

+44
-6
lines changed

5 files changed

+44
-6
lines changed

clang/lib/Frontend/CompilerInstance.cpp

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -566,25 +566,28 @@ namespace {
566566
// the files we were handed.
567567
struct ReadModuleNames : ASTReaderListener {
568568
Preprocessor &PP;
569-
llvm::SmallVector<IdentifierInfo*, 8> LoadedModules;
569+
llvm::SmallVector<std::string, 8> LoadedModules;
570570

571571
ReadModuleNames(Preprocessor &PP) : PP(PP) {}
572572

573573
void ReadModuleName(StringRef ModuleName) override {
574-
LoadedModules.push_back(PP.getIdentifierInfo(ModuleName));
574+
// Keep the module name as a string for now. It's not safe to create a new
575+
// IdentifierInfo from an ASTReader callback.
576+
LoadedModules.push_back(ModuleName.str());
575577
}
576578

577579
void registerAll() {
578580
ModuleMap &MM = PP.getHeaderSearchInfo().getModuleMap();
579-
for (auto *II : LoadedModules)
580-
MM.cacheModuleLoad(*II, MM.findModule(II->getName()));
581+
for (const std::string &LoadedModule : LoadedModules)
582+
MM.cacheModuleLoad(*PP.getIdentifierInfo(LoadedModule),
583+
MM.findModule(LoadedModule));
581584
LoadedModules.clear();
582585
}
583586

584587
void markAllUnavailable() {
585-
for (auto *II : LoadedModules) {
588+
for (const std::string &LoadedModule : LoadedModules) {
586589
if (Module *M = PP.getHeaderSearchInfo().getModuleMap().findModule(
587-
II->getName())) {
590+
LoadedModule)) {
588591
M->HasIncompatibleModuleFile = true;
589592

590593
// Mark module as available if the only reason it was unavailable
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
@interface Interface
2+
@end
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
typedef struct __attribute__((objc_bridge(Interface))) Foo *Bar;
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
module InterfaceBridge {
2+
header "InterfaceBridge.h"
3+
}
4+
5+
module Interface {
6+
header "Interface.h"
7+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// RUN: rm -rf %t && mkdir %t
2+
3+
// RUN: %clang_cc1 -fmodules -x objective-c -emit-module -fmodule-name=InterfaceBridge \
4+
// RUN: %S/Inputs/module-name-used-by-objc-bridge/module.modulemap -o %t/InterfaceBridge.pcm
5+
6+
// RUN: %clang_cc1 -fmodules -x objective-c -emit-module -fmodule-name=Interface \
7+
// RUN: %S/Inputs/module-name-used-by-objc-bridge/module.modulemap -o %t/Interface.pcm
8+
9+
// Check that the `-fmodule-file=<name>=<path>` form succeeds:
10+
// RUN: %clang_cc1 -fmodules -fsyntax-only %s -I %S/Inputs/module-name-used-by-objc-bridge \
11+
// RUN: -fmodule-file=InterfaceBridge=%t/InterfaceBridge.pcm -fmodule-file=Interface=%t/Interface.pcm \
12+
// RUN: -fmodule-map-file=%S/Inputs/module-name-used-by-objc-bridge/module.modulemap -verify
13+
14+
// Check that the `-fmodule-file=<path>` form succeeds:
15+
// RUN: %clang_cc1 -fmodules -fsyntax-only %s -I %S/Inputs/module-name-used-by-objc-bridge \
16+
// RUN: -fmodule-file=%t/InterfaceBridge.pcm -fmodule-file=%t/Interface.pcm \
17+
// RUN: -fmodule-map-file=%S/Inputs/module-name-used-by-objc-bridge/module.modulemap -verify
18+
19+
#import "InterfaceBridge.h"
20+
#import "Interface.h"
21+
22+
@interface Interface (User)
23+
@end
24+
25+
// expected-no-diagnostics

0 commit comments

Comments
 (0)