teemperor created this revision.

In the current local-submodule-visibility mode, as soon as we discover a 
virtual destructor, we declare on demand a global delete operator. However, 
this causes that this delete operator is owned by the submodule which contains 
said virtual destructor. This means that other modules no longer can see the 
global delete operator which is hidden inside another submodule and fail to 
compile.

As an example, see the test case which contains just two classes with virtual 
destructors. The header a.h has a virtual destructor which declares the delete 
operator in module `a`. Module `b` now fails to compile because it can't 
redeclare the delete operator (due to the shared `Sema` instance) but also 
can't see the hidden delete contained in the unimported module `a`.

This patch declares the delete/new operators before we go into the submoules, 
which prevents that a single submodule can own them.


https://reviews.llvm.org/D33366

Files:
  lib/Sema/Sema.cpp
  test/Modules/Inputs/local-submodule-globaldelete/a.h
  test/Modules/Inputs/local-submodule-globaldelete/b.h
  test/Modules/Inputs/local-submodule-globaldelete/module.modulemap
  test/Modules/local-submodule-globaldelete.cpp


Index: test/Modules/local-submodule-globaldelete.cpp
===================================================================
--- /dev/null
+++ test/Modules/local-submodule-globaldelete.cpp
@@ -0,0 +1,14 @@
+// RUN: rm -rf %t
+// RUN: mkdir %t
+// RUN: cp -r %S/Inputs/local-submodule-globaldelete 
%t/local-submodule-globaldelete
+// RUN: cd %t
+// RUN: %clang_cc1 -fmodules -fmodules-local-submodule-visibility -verify 
-fmodules-cache-path=%t  -fimplicit-module-maps -I local-submodule-globaldelete 
%s -H
+
+// expected-no-diagnostics
+
+// This tests that the global delete operator is not by accident assigned
+// to a submodule in local-submodule-visibility mode. This could happen
+// when the operator is created on demand when we discover a virtual destructor
+// inside a module.
+
+#include "a.h"
Index: test/Modules/Inputs/local-submodule-globaldelete/module.modulemap
===================================================================
--- /dev/null
+++ test/Modules/Inputs/local-submodule-globaldelete/module.modulemap
@@ -0,0 +1,4 @@
+module M {
+  module a { header "a.h" export * }
+  module b { header "b.h" export * }
+}
Index: test/Modules/Inputs/local-submodule-globaldelete/b.h
===================================================================
--- /dev/null
+++ test/Modules/Inputs/local-submodule-globaldelete/b.h
@@ -0,0 +1,6 @@
+#ifndef B_H
+#define B_H
+class B {
+  virtual ~B() {};
+};
+#endif
Index: test/Modules/Inputs/local-submodule-globaldelete/a.h
===================================================================
--- /dev/null
+++ test/Modules/Inputs/local-submodule-globaldelete/a.h
@@ -0,0 +1,6 @@
+#ifndef A_H
+#define A_H
+class A {
+  virtual ~A() {};
+};
+#endif
Index: lib/Sema/Sema.cpp
===================================================================
--- lib/Sema/Sema.cpp
+++ lib/Sema/Sema.cpp
@@ -122,6 +122,12 @@
 
   // Initilization of data sharing attributes stack for OpenMP
   InitDataSharingAttributesStack();
+
+  // If we're now in a module, we declare the global new/delete
+  // functions to make sure they don't end up being owned by a certain
+  // submodule (and are therefore always visible to all submodules).
+  if (getLangOpts().ModulesLocalVisibility && 
!getLangOpts().CurrentModule.empty())
+    DeclareGlobalNewDelete();
 }
 
 void Sema::addImplicitTypedef(StringRef Name, QualType T) {


Index: test/Modules/local-submodule-globaldelete.cpp
===================================================================
--- /dev/null
+++ test/Modules/local-submodule-globaldelete.cpp
@@ -0,0 +1,14 @@
+// RUN: rm -rf %t
+// RUN: mkdir %t
+// RUN: cp -r %S/Inputs/local-submodule-globaldelete %t/local-submodule-globaldelete
+// RUN: cd %t
+// RUN: %clang_cc1 -fmodules -fmodules-local-submodule-visibility -verify -fmodules-cache-path=%t  -fimplicit-module-maps -I local-submodule-globaldelete %s -H
+
+// expected-no-diagnostics
+
+// This tests that the global delete operator is not by accident assigned
+// to a submodule in local-submodule-visibility mode. This could happen
+// when the operator is created on demand when we discover a virtual destructor
+// inside a module.
+
+#include "a.h"
Index: test/Modules/Inputs/local-submodule-globaldelete/module.modulemap
===================================================================
--- /dev/null
+++ test/Modules/Inputs/local-submodule-globaldelete/module.modulemap
@@ -0,0 +1,4 @@
+module M {
+  module a { header "a.h" export * }
+  module b { header "b.h" export * }
+}
Index: test/Modules/Inputs/local-submodule-globaldelete/b.h
===================================================================
--- /dev/null
+++ test/Modules/Inputs/local-submodule-globaldelete/b.h
@@ -0,0 +1,6 @@
+#ifndef B_H
+#define B_H
+class B {
+  virtual ~B() {};
+};
+#endif
Index: test/Modules/Inputs/local-submodule-globaldelete/a.h
===================================================================
--- /dev/null
+++ test/Modules/Inputs/local-submodule-globaldelete/a.h
@@ -0,0 +1,6 @@
+#ifndef A_H
+#define A_H
+class A {
+  virtual ~A() {};
+};
+#endif
Index: lib/Sema/Sema.cpp
===================================================================
--- lib/Sema/Sema.cpp
+++ lib/Sema/Sema.cpp
@@ -122,6 +122,12 @@
 
   // Initilization of data sharing attributes stack for OpenMP
   InitDataSharingAttributesStack();
+
+  // If we're now in a module, we declare the global new/delete
+  // functions to make sure they don't end up being owned by a certain
+  // submodule (and are therefore always visible to all submodules).
+  if (getLangOpts().ModulesLocalVisibility && !getLangOpts().CurrentModule.empty())
+    DeclareGlobalNewDelete();
 }
 
 void Sema::addImplicitTypedef(StringRef Name, QualType T) {
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to