Author: Jan Svoboda
Date: 2021-10-18T11:50:29+02:00
New Revision: a2d805c020a1658b04ed7e606ee67e234a9d5b56

URL: 
https://github.com/llvm/llvm-project/commit/a2d805c020a1658b04ed7e606ee67e234a9d5b56
DIFF: 
https://github.com/llvm/llvm-project/commit/a2d805c020a1658b04ed7e606ee67e234a9d5b56.diff

LOG: [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

Added: 
    clang/test/Modules/Inputs/module-name-used-by-objc-bridge/Interface.h
    clang/test/Modules/Inputs/module-name-used-by-objc-bridge/InterfaceBridge.h
    clang/test/Modules/Inputs/module-name-used-by-objc-bridge/module.modulemap
    clang/test/Modules/module-name-used-by-objc-bridge.m

Modified: 
    clang/lib/Frontend/CompilerInstance.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/Frontend/CompilerInstance.cpp 
b/clang/lib/Frontend/CompilerInstance.cpp
index 20de9174740ac..a9b9e6516d56f 100644
--- a/clang/lib/Frontend/CompilerInstance.cpp
+++ b/clang/lib/Frontend/CompilerInstance.cpp
@@ -565,25 +565,28 @@ namespace {
 // the files we were handed.
 struct ReadModuleNames : ASTReaderListener {
   Preprocessor &PP;
-  llvm::SmallVector<IdentifierInfo*, 8> LoadedModules;
+  llvm::SmallVector<std::string, 8> LoadedModules;
 
   ReadModuleNames(Preprocessor &PP) : PP(PP) {}
 
   void ReadModuleName(StringRef ModuleName) override {
-    LoadedModules.push_back(PP.getIdentifierInfo(ModuleName));
+    // Keep the module name as a string for now. It's not safe to create a new
+    // IdentifierInfo from an ASTReader callback.
+    LoadedModules.push_back(ModuleName.str());
   }
 
   void registerAll() {
     ModuleMap &MM = PP.getHeaderSearchInfo().getModuleMap();
-    for (auto *II : LoadedModules)
-      MM.cacheModuleLoad(*II, MM.findModule(II->getName()));
+    for (const std::string &LoadedModule : LoadedModules)
+      MM.cacheModuleLoad(*PP.getIdentifierInfo(LoadedModule),
+                         MM.findModule(LoadedModule));
     LoadedModules.clear();
   }
 
   void markAllUnavailable() {
-    for (auto *II : LoadedModules) {
+    for (const std::string &LoadedModule : LoadedModules) {
       if (Module *M = PP.getHeaderSearchInfo().getModuleMap().findModule(
-              II->getName())) {
+              LoadedModule)) {
         M->HasIncompatibleModuleFile = true;
 
         // Mark module as available if the only reason it was unavailable

diff  --git 
a/clang/test/Modules/Inputs/module-name-used-by-objc-bridge/Interface.h 
b/clang/test/Modules/Inputs/module-name-used-by-objc-bridge/Interface.h
new file mode 100644
index 0000000000000..a825c0d25f311
--- /dev/null
+++ b/clang/test/Modules/Inputs/module-name-used-by-objc-bridge/Interface.h
@@ -0,0 +1,2 @@
+@interface Interface
+@end

diff  --git 
a/clang/test/Modules/Inputs/module-name-used-by-objc-bridge/InterfaceBridge.h 
b/clang/test/Modules/Inputs/module-name-used-by-objc-bridge/InterfaceBridge.h
new file mode 100644
index 0000000000000..63f6399a806ce
--- /dev/null
+++ 
b/clang/test/Modules/Inputs/module-name-used-by-objc-bridge/InterfaceBridge.h
@@ -0,0 +1 @@
+typedef struct __attribute__((objc_bridge(Interface))) Foo *Bar;

diff  --git 
a/clang/test/Modules/Inputs/module-name-used-by-objc-bridge/module.modulemap 
b/clang/test/Modules/Inputs/module-name-used-by-objc-bridge/module.modulemap
new file mode 100644
index 0000000000000..a0bd43ff80a56
--- /dev/null
+++ b/clang/test/Modules/Inputs/module-name-used-by-objc-bridge/module.modulemap
@@ -0,0 +1,7 @@
+module InterfaceBridge {
+  header "InterfaceBridge.h"
+}
+
+module Interface {
+  header "Interface.h"
+}

diff  --git a/clang/test/Modules/module-name-used-by-objc-bridge.m 
b/clang/test/Modules/module-name-used-by-objc-bridge.m
new file mode 100644
index 0000000000000..afaa0cb0e4a7d
--- /dev/null
+++ b/clang/test/Modules/module-name-used-by-objc-bridge.m
@@ -0,0 +1,25 @@
+// RUN: rm -rf %t && mkdir %t
+
+// RUN: %clang_cc1 -fmodules -x objective-c -emit-module 
-fmodule-name=InterfaceBridge \
+// RUN:   %S/Inputs/module-name-used-by-objc-bridge/module.modulemap -o 
%t/InterfaceBridge.pcm
+
+// RUN: %clang_cc1 -fmodules -x objective-c -emit-module 
-fmodule-name=Interface \
+// RUN:   %S/Inputs/module-name-used-by-objc-bridge/module.modulemap -o 
%t/Interface.pcm
+
+// Check that the `-fmodule-file=<name>=<path>` form succeeds:
+// RUN: %clang_cc1 -fmodules -fsyntax-only %s -I 
%S/Inputs/module-name-used-by-objc-bridge \
+// RUN:   -fmodule-file=InterfaceBridge=%t/InterfaceBridge.pcm 
-fmodule-file=Interface=%t/Interface.pcm \
+// RUN:   
-fmodule-map-file=%S/Inputs/module-name-used-by-objc-bridge/module.modulemap 
-verify
+
+// Check that the `-fmodule-file=<path>` form succeeds:
+// RUN: %clang_cc1 -fmodules -fsyntax-only %s -I 
%S/Inputs/module-name-used-by-objc-bridge \
+// RUN:   -fmodule-file=%t/InterfaceBridge.pcm -fmodule-file=%t/Interface.pcm \
+// RUN:   
-fmodule-map-file=%S/Inputs/module-name-used-by-objc-bridge/module.modulemap 
-verify
+
+#import "InterfaceBridge.h"
+#import "Interface.h"
+
+@interface Interface (User)
+@end
+
+// expected-no-diagnostics


        
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to