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