]> granicus.if.org Git - clang/commitdiff
Module: emit initializers in submodules when importing the parent module.
authorManman Ren <manman.ren@gmail.com>
Fri, 14 Oct 2016 18:55:44 +0000 (18:55 +0000)
committerManman Ren <manman.ren@gmail.com>
Fri, 14 Oct 2016 18:55:44 +0000 (18:55 +0000)
When importing the parent module, module initializers in submodules should
be emitted.

rdar://28740482

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@284263 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/CodeGenModule.cpp
lib/CodeGen/CodeGenModule.h
test/Modules/Inputs/objc-initializer/module.modulemap
test/Modules/objc-initializer.m

index f4628fc0d33ada4ef9405bba9933d3542f245e77..21849590b11c0f5cb590dcebb9062d60c3bd3d99 100644 (file)
@@ -3951,9 +3951,33 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) {
         DI->EmitImportDecl(*Import);
     }
 
-    // Emit the module initializers.
-    for (auto *D : Context.getModuleInitializers(Import->getImportedModule()))
-      EmitTopLevelDecl(D);
+    // Find all of the submodules and emit the module initializers.
+    llvm::SmallPtrSet<clang::Module *, 16> Visited;
+    SmallVector<clang::Module *, 16> Stack;
+    Visited.insert(Import->getImportedModule());
+    Stack.push_back(Import->getImportedModule());
+
+    while (!Stack.empty()) {
+      clang::Module *Mod = Stack.pop_back_val();
+      if (!EmittedModuleInitializers.insert(Mod).second)
+        continue;
+
+      for (auto *D : Context.getModuleInitializers(Mod))
+        EmitTopLevelDecl(D);
+
+      // Visit the submodules of this module.
+      for (clang::Module::submodule_iterator Sub = Mod->submodule_begin(),
+                                             SubEnd = Mod->submodule_end();
+           Sub != SubEnd; ++Sub) {
+        // Skip explicit children; they need to be explicitly imported to emit
+        // the initializers.
+        if ((*Sub)->IsExplicit)
+          continue;
+
+        if (Visited.insert(*Sub).second)
+          Stack.push_back(*Sub);
+      }
+    }
     break;
   }
 
index e896b11a7aed31900ea5ca0ea6152573ed79d51b..7fb2402d34ab3cdd8870bb34f540524f290d79d7 100644 (file)
@@ -420,6 +420,10 @@ private:
   /// \brief The complete set of modules that has been imported.
   llvm::SetVector<clang::Module *> ImportedModules;
 
+  /// \brief The set of modules for which the module initializers
+  /// have been emitted.
+  llvm::SmallPtrSet<clang::Module *, 16> EmittedModuleInitializers;
+
   /// \brief A vector of metadata strings.
   SmallVector<llvm::Metadata *, 16> LinkerOptionsMetadata;
 
index 8fe4c92a1738aff199a6e4e881e9fd96606460ad..bc76ace10654242b58b791356b172c4f7d5eb472 100644 (file)
@@ -1,4 +1,7 @@
 module X {
-  header "X.h"
+  module T {
+    header "X.h"
+    export *
+  }
   export *
 }
index 90cc182471771ac895d411dcb89572a151c707e3..adb7a06a2bf66f8963b63bdda0ee787d67b3bf54 100644 (file)
@@ -1,8 +1,14 @@
 // RUN: rm -rf %t
 // RUN: %clang_cc1 -fmodules-cache-path=%t -fmodules -fimplicit-module-maps -I %S/Inputs/objc-initializer %s -emit-llvm -o - -fobjc-arc | FileCheck %s
+// RUN: %clang_cc1 -fmodules-cache-path=%t -fmodules -fimplicit-module-maps -I %S/Inputs/objc-initializer %s -emit-llvm -o - -fobjc-arc -DIMPORT_TOP | FileCheck %s
 // CHECK: kSimDeviceIOGetInterface = internal constant {{.*}} bitcast
 
+#ifdef IMPORT_TOP
+@import X;
+#else
 #import <X.h>
+#endif
+
 void test2(const NSString*);
 void test() {
   test2(kSimDeviceIOGetInterface);