When we reach the end of a #include of a header of a local submodule that we
authorRichard Smith <richard-llvm@metafoo.co.uk>
Thu, 1 Sep 2016 20:15:25 +0000 (20:15 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Thu, 1 Sep 2016 20:15:25 +0000 (20:15 +0000)
textually included, create an ImportDecl just as we would if we reached a
#include of any other modular header. This is necessary in order to correctly
determine the set of variables to initialize for an imported module.

This should hopefully make the modules selfhost buildbot green again.

llvm-svn: 280409

clang/include/clang/Sema/Sema.h
clang/lib/Sema/SemaDecl.cpp
clang/test/Modules/global-init.cpp [new file with mode: 0644]
clang/tools/libclang/CXIndexDataConsumer.cpp

index b6c7b400f5b0ca38cf022721a68f024dedf33462..dfe9e36b432770cdb3a9d7000344286408e14296 100644 (file)
@@ -1884,6 +1884,7 @@ public:
   /// \brief The parser has processed a module import translated from a
   /// #include or similar preprocessing directive.
   void ActOnModuleInclude(SourceLocation DirectiveLoc, Module *Mod);
+  void BuildModuleInclude(SourceLocation DirectiveLoc, Module *Mod);
 
   /// \brief The parsed has entered a submodule.
   void ActOnModuleBegin(SourceLocation DirectiveLoc, Module *Mod);
index 8b148af8cce382849d7f9ba90bf9488a6cd5e8fa..2a514ab1bd26c010787ec64fce2be8b5b633282a 100644 (file)
@@ -15312,7 +15312,10 @@ DeclResult Sema::ActOnModuleImport(SourceLocation StartLoc,
 
 void Sema::ActOnModuleInclude(SourceLocation DirectiveLoc, Module *Mod) {
   checkModuleImportContext(*this, Mod, DirectiveLoc, CurContext, true);
+  BuildModuleInclude(DirectiveLoc, Mod);
+}
 
+void Sema::BuildModuleInclude(SourceLocation DirectiveLoc, Module *Mod) {
   // Determine whether we're in the #include buffer for a module. The #includes
   // in that buffer do not qualify as module imports; they're just an
   // implementation detail of us building the module.
@@ -15352,20 +15355,27 @@ void Sema::ActOnModuleBegin(SourceLocation DirectiveLoc, Module *Mod) {
   VisibleModules.setVisible(Mod, DirectiveLoc);
 }
 
-void Sema::ActOnModuleEnd(SourceLocation DirectiveLoc, Module *Mod) {
-  checkModuleImportContext(*this, Mod, DirectiveLoc, CurContext);
+void Sema::ActOnModuleEnd(SourceLocation EofLoc, Module *Mod) {
+  checkModuleImportContext(*this, Mod, EofLoc, CurContext);
 
   if (getLangOpts().ModulesLocalVisibility) {
-    assert(!ModuleScopes.empty() && ModuleScopes.back().Module == Mod &&
-           "left the wrong module scope");
     VisibleModules = std::move(ModuleScopes.back().OuterVisibleModules);
-    ModuleScopes.pop_back();
-
-    VisibleModules.setVisible(Mod, DirectiveLoc);
     // Leaving a module hides namespace names, so our visible namespace cache
     // is now out of date.
     VisibleNamespaceCache.clear();
   }
+
+  assert(!ModuleScopes.empty() && ModuleScopes.back().Module == Mod &&
+         "left the wrong module scope");
+  ModuleScopes.pop_back();
+
+  // We got to the end of processing a #include of a local module. Create an
+  // ImportDecl as we would for an imported module.
+  FileID File = getSourceManager().getFileID(EofLoc);
+  assert(File != getSourceManager().getMainFileID() &&
+         "end of submodule in main source file");
+  SourceLocation DirectiveLoc = getSourceManager().getIncludeLoc(File);
+  BuildModuleInclude(DirectiveLoc, Mod);
 }
 
 void Sema::createImplicitModuleImportForErrorRecovery(SourceLocation Loc,
diff --git a/clang/test/Modules/global-init.cpp b/clang/test/Modules/global-init.cpp
new file mode 100644 (file)
index 0000000..fb42464
--- /dev/null
@@ -0,0 +1,19 @@
+// RUN: rm -rf %t
+// RUN: mkdir %t
+//
+// RUN: echo '#pragma once' > %t/a.h
+// RUN: echo 'struct A { A() {} int f() const; } const a;' >> %t/a.h
+//
+// RUN: echo '#include "a.h"' > %t/b.h
+//
+// RUN: echo 'module M { module b { header "b.h" export * } module a { header "a.h" export * } }' > %t/map
+//
+// RUN: %clang_cc1 -fmodules -fmodules-cache-path=%t -fmodule-map-file=%t/map -I%t %s -emit-llvm -o - -triple %itanium_abi_triple | FileCheck %s
+
+#include "b.h"
+
+// CHECK: @_ZL1a = internal global
+// CHECK: call {{.*}} @_ZN1AC1Ev({{.*}}@_ZL1a
+// CHECK: call {{.*}} @_ZNK1A1fEv({{.*}}@_ZL1a
+// CHECK: store {{.*}} @x
+int x = a.f();
index 59fa92bb21e25d7887c588b550df23c812297a49..74d8f2415c63a2d602133c1e041132cddb550d5a 100644 (file)
@@ -478,6 +478,14 @@ void CXIndexDataConsumer::importedModule(const ImportDecl *ImportD) {
   if (!Mod)
     return;
 
+  // If the imported module is part of the top-level module that we're
+  // indexing, it doesn't correspond to an imported AST file.
+  // FIXME: This assumes that AST files and top-level modules directly
+  // correspond, which is unlikely to remain true forever.
+  if (Module *SrcMod = ImportD->getImportedOwningModule())
+    if (SrcMod->getTopLevelModule() == Mod->getTopLevelModule())
+      return;
+
   CXIdxImportedASTFileInfo Info = {
                                     static_cast<CXFile>(
                                     const_cast<FileEntry *>(Mod->getASTFile())),