]> granicus.if.org Git - clang/commitdiff
When we enter a module within a linkage specification, switch the linkage
authorRichard Smith <richard-llvm@metafoo.co.uk>
Thu, 18 May 2017 19:34:55 +0000 (19:34 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Thu, 18 May 2017 19:34:55 +0000 (19:34 +0000)
specification and the TU to the new module.

This is necessary to get the module ownership correct for entities that we
temporarily hang off the TranslationUnitDecl, such as template parameters and
function parameters.

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

lib/Sema/SemaDecl.cpp
test/Modules/extern_cxx.cpp [new file with mode: 0644]

index ba1e97b33d6fb00e58ee9bda6168294f92ad45a7..5e937aa699639afffca8b9125c9d07674f73f48d 100644 (file)
@@ -16048,8 +16048,10 @@ void Sema::ActOnModuleBegin(SourceLocation DirectiveLoc, Module *Mod) {
   // FIXME: Consider creating a child DeclContext to hold the entities
   // lexically within the module.
   if (getLangOpts().trackLocalOwningModule()) {
-    cast<Decl>(CurContext)->setHidden(true);
-    cast<Decl>(CurContext)->setLocalOwningModule(Mod);
+    for (auto *DC = CurContext; DC; DC = DC->getLexicalParent()) {
+      cast<Decl>(DC)->setHidden(true);
+      cast<Decl>(DC)->setLocalOwningModule(Mod);
+    }
   }
 }
 
@@ -16082,9 +16084,13 @@ void Sema::ActOnModuleEnd(SourceLocation EomLoc, Module *Mod) {
 
   // Any further declarations are in whatever module we returned to.
   if (getLangOpts().trackLocalOwningModule()) {
-    cast<Decl>(CurContext)->setLocalOwningModule(getCurrentModule());
-    if (!getCurrentModule())
-      cast<Decl>(CurContext)->setHidden(false);
+    // The parser guarantees that this is the same context that we entered
+    // the module within.
+    for (auto *DC = CurContext; DC; DC = DC->getLexicalParent()) {
+      cast<Decl>(DC)->setLocalOwningModule(getCurrentModule());
+      if (!getCurrentModule())
+        cast<Decl>(DC)->setHidden(false);
+    }
   }
 }
 
diff --git a/test/Modules/extern_cxx.cpp b/test/Modules/extern_cxx.cpp
new file mode 100644 (file)
index 0000000..97ec726
--- /dev/null
@@ -0,0 +1,25 @@
+// RUN: %clang_cc1 -x c++-module-map -fmodule-name=A -verify %s -fmodules-local-submodule-visibility
+module A { module B {} module C {} }
+
+#pragma clang module contents
+
+#pragma clang module begin A.B
+extern "C++" {
+  #pragma clang module begin A.C
+  template<typename T> void f(T t);
+  #pragma clang module end
+
+  void g() { f(0); } // ok
+}
+
+extern "C++" {
+  #pragma clang module begin A.C
+  } // expected-error {{extraneous closing brace}}
+  #pragma clang module end
+  
+  #pragma clang module begin A.C
+  extern "C++" { // expected-note {{to match this '{'}}
+  #pragma clang module end // expected-error {{expected '}' at end of module}}
+}
+
+#pragma clang module end