diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2019-04-22 22:50:11 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2019-04-22 22:50:11 +0000 |
commit | e181de7f4fe9c75327836e5493c2783bcefc9293 (patch) | |
tree | 014979d3a317a1d57bcb86609e0d1f11c98ebd55 /clang/test | |
parent | 68602ab2f3535291753a6149d1f445c5fd416152 (diff) | |
download | bcm5719-llvm-e181de7f4fe9c75327836e5493c2783bcefc9293.tar.gz bcm5719-llvm-e181de7f4fe9c75327836e5493c2783bcefc9293.zip |
[c++2a] Implement semantic restrictions for 'export' declarations.
llvm-svn: 358932
Diffstat (limited to 'clang/test')
-rw-r--r-- | clang/test/CXX/module/module.interface/Inputs/header.h | 3 | ||||
-rw-r--r-- | clang/test/CXX/module/module.interface/p1.cpp | 8 | ||||
-rw-r--r-- | clang/test/CXX/module/module.interface/p2.cpp | 94 | ||||
-rw-r--r-- | clang/test/CXX/module/module.interface/p3.cpp | 54 | ||||
-rw-r--r-- | clang/test/CXX/module/module.interface/p5.cpp | 89 | ||||
-rw-r--r-- | clang/test/CXX/modules-ts/basic/basic.def.odr/p4/module.cpp | 2 | ||||
-rw-r--r-- | clang/test/CXX/modules-ts/basic/basic.def.odr/p4/module.cppm | 16 | ||||
-rw-r--r-- | clang/test/CXX/modules-ts/basic/basic.def.odr/p4/user.cpp | 2 | ||||
-rw-r--r-- | clang/test/SemaCXX/anonymous-union-export.cpp | 5 | ||||
-rw-r--r-- | clang/test/SemaCXX/modules-ts.cppm | 10 |
10 files changed, 254 insertions, 29 deletions
diff --git a/clang/test/CXX/module/module.interface/Inputs/header.h b/clang/test/CXX/module/module.interface/Inputs/header.h new file mode 100644 index 00000000000..f2e2cbb53c1 --- /dev/null +++ b/clang/test/CXX/module/module.interface/Inputs/header.h @@ -0,0 +1,3 @@ +extern int foo; +namespace bar { extern int baz(); } +static int baz; diff --git a/clang/test/CXX/module/module.interface/p1.cpp b/clang/test/CXX/module/module.interface/p1.cpp index 1eba8175de4..0947b81915e 100644 --- a/clang/test/CXX/module/module.interface/p1.cpp +++ b/clang/test/CXX/module/module.interface/p1.cpp @@ -23,15 +23,15 @@ namespace N { } #ifdef ERRORS -namespace { - export int d1; // FIXME: invalid +namespace { // expected-note 2{{anonymous namespace begins here}} + export int d1; // expected-error {{export declaration appears within anonymous namespace}} namespace X { - export int d2; // FIXME: invalid + export int d2; // expected-error {{export declaration appears within anonymous namespace}} } } export export int e; // expected-error {{within another export declaration}} -export { export int f; } // expected-error {{within another export declaration}} +export { export int f; } // expected-error {{within another export declaration}} expected-note {{export block begins here}} module :private; // expected-note {{private module fragment begins here}} export int priv; // expected-error {{export declaration cannot be used in a private module fragment}} diff --git a/clang/test/CXX/module/module.interface/p2.cpp b/clang/test/CXX/module/module.interface/p2.cpp new file mode 100644 index 00000000000..0a6f8c2aad5 --- /dev/null +++ b/clang/test/CXX/module/module.interface/p2.cpp @@ -0,0 +1,94 @@ +// RUN: rm -rf %t +// RUN: mkdir -p %t +// RUN: %clang_cc1 -std=c++2a -x c++-header %S/Inputs/header.h -emit-header-module -fmodule-name=FIXME -o %t/h.pcm +// RUN: %clang_cc1 -std=c++2a %s -DX_INTERFACE -emit-module-interface -o %t/x.pcm +// RUN: %clang_cc1 -std=c++2a %s -DY_INTERFACE -emit-module-interface -o %t/y.pcm +// RUN: %clang_cc1 -std=c++2a %s -DINTERFACE -fmodule-file=%t/x.pcm -fmodule-file=%t/y.pcm -emit-module-interface -o %t/m.pcm +// RUN: %clang_cc1 -std=c++2a %s -DIMPLEMENTATION -I%S/Inputs -fmodule-file=%t/h.pcm -fmodule-file=%t/m.pcm -verify +// RUN: %clang_cc1 -std=c++2a %s -DUSER -I%S/Inputs -fmodule-file=%t/h.pcm -fmodule-file=%t/m.pcm -verify + +#if defined(X_INTERFACE) +export module X; +export int x; + +#elif defined(Y_INTERFACE) +export module Y; +export int y; + +#elif defined(INTERFACE) +export module p2; +export import X; +import Y; // not exported + +namespace A { + int f(); + export int g(); + int h(); + namespace inner {} +} +export namespace B { + namespace inner {} +} +namespace B { + int f(); +} +namespace C {} +namespace D { int f(); } +export namespace D {} + +#elif defined(IMPLEMENTATION) +module p2; +import "header.h"; + +// Per [basic.scope.namespace]/2.3, exportedness has no impact on visibility +// within the same module. +// +// expected-no-diagnostics + +void use() { + A::f(); + A::g(); + A::h(); + using namespace A::inner; + + using namespace B; + using namespace B::inner; + B::f(); + f(); + + using namespace C; + + D::f(); +} + +int use_header() { return foo + bar::baz(); } + +#elif defined(USER) +import p2; +import "header.h"; + +void use() { + // namespace A is implicitly exported by the export of A::g. + A::f(); // expected-error {{no member named 'f' in namespace 'A'}} + A::g(); + A::h(); // expected-error {{no member named 'h' in namespace 'A'}} + using namespace A::inner; // expected-error {{expected namespace name}} + + // namespace B and B::inner are explicitly exported + using namespace B; + using namespace B::inner; + B::f(); // expected-error {{no member named 'f' in namespace 'B'}} + f(); // expected-error {{undeclared identifier 'f'}} + + // namespace C is not exported + using namespace C; // expected-error {{expected namespace name}} + + // namespace D is exported, but D::f is not + D::f(); // expected-error {{no member named 'f' in namespace 'D'}} +} + +int use_header() { return foo + bar::baz(); } + +#else +#error unknown mode +#endif diff --git a/clang/test/CXX/module/module.interface/p3.cpp b/clang/test/CXX/module/module.interface/p3.cpp new file mode 100644 index 00000000000..89c5e08f546 --- /dev/null +++ b/clang/test/CXX/module/module.interface/p3.cpp @@ -0,0 +1,54 @@ +// RUN: %clang_cc1 -std=c++2a %s -verify -pedantic-errors + +export module p3; + +namespace A { int ns_mem; } + +// An exported declaration shall declare at least one name. +export; // expected-error {{empty declaration cannot be exported}} +export static_assert(true); // expected-error {{static_assert declaration cannot be exported}} +export using namespace A; // expected-error {{ISO C++20 does not permit using directive to be exported}} + +export { // expected-note 3{{export block begins here}} + ; // expected-error {{ISO C++20 does not permit an empty declaration to appear in an export block}} + static_assert(true); // expected-error {{ISO C++20 does not permit a static_assert declaration to appear in an export block}} + using namespace A; // expected-error {{ISO C++20 does not permit using directive to be exported}} +} + +export struct {}; // expected-error {{must be class member}} expected-error {{GNU extension}} +export struct {} struct_; +export union {}; // expected-error {{must be declared 'static'}} +export union {} union_; +export enum {}; // expected-error {{does not declare anything}} +export enum {} enum_; +export enum E : int; +export typedef int; // expected-error {{typedef requires a name}} +export static union {}; // FIXME: this declaration is ill-formed even without the 'export' +export asm(""); // expected-error {{asm declaration cannot be exported}} +export namespace B = A; +export using A::ns_mem; +namespace A { + export using A::ns_mem; +} +export using Int = int; +export extern "C++" {} // expected-error {{ISO C++20 does not permit a declaration that does not introduce any names to be exported}} +export extern "C++" { extern "C" {} } // expected-error {{ISO C++20 does not permit a declaration that does not introduce any names to be exported}} +export extern "C++" { extern "C" int extern_c; } +export { // expected-note {{export block}} + extern "C++" int extern_cxx; + extern "C++" {} // expected-error {{ISO C++20 does not permit a declaration that does not introduce any names to be exported}} +} +export [[]]; // FIXME (bad diagnostic text): expected-error {{empty declaration cannot be exported}} +export [[example::attr]]; // FIXME: expected-error {{empty declaration cannot be exported}} expected-warning {{unknown attribute 'attr'}} + +// [...] shall not declare a name with internal linkage +export static int a; // expected-error {{declaration of 'a' with internal linkage cannot be exported}} +export static int b(); // expected-error {{declaration of 'b' with internal linkage cannot be exported}} +export namespace { int c; } // expected-error {{declaration of 'c' with internal linkage cannot be exported}} +namespace { // expected-note {{here}} + export int d; // expected-error {{export declaration appears within anonymous namespace}} +} +export template<typename> static int e; // FIXME +export template<typename> static int f(); // expected-error {{declaration of 'f' with internal linkage cannot be exported}} +export const int k = 5; +export static union { int n; }; // expected-error {{declaration of 'n' with internal linkage cannot be exported}} diff --git a/clang/test/CXX/module/module.interface/p5.cpp b/clang/test/CXX/module/module.interface/p5.cpp new file mode 100644 index 00000000000..c4299dc04fb --- /dev/null +++ b/clang/test/CXX/module/module.interface/p5.cpp @@ -0,0 +1,89 @@ +// RUN: %clang_cc1 -std=c++2a %s -verify -pedantic-errors + +export module p5; + +int a; +static int sa; // expected-note {{target}} +void b(); +static void sb(); // expected-note {{target}} +struct c {}; +enum d {}; +using e = int; +using f = c; +static union { int sg1, sg2; }; // expected-note {{target}} +namespace NS {} + +template<typename> int ta; +template<typename> static int sta; +template<typename> void tb(); +template<typename> static void stb(); // expected-note {{target}} +template<typename> struct tc {}; +template<typename> using te = int; +template<typename> using tf = c; + +namespace UnnamedNS { + namespace { + int a; // expected-note {{target}} + static int sa; // expected-note {{target}} + void b(); // expected-note {{target}} + static void sb(); // expected-note {{target}} + struct c {}; // expected-note {{target}} + enum d {}; // expected-note {{target}} + using e = int; + using f = c; + static union { int sg1, sg2; }; // expected-note {{target}} + namespace NS {} + + template<typename> int ta; // expected-note {{target}} + template<typename> static int sta; // expected-note {{target}} + template<typename> void tb(); // expected-note {{target}} + template<typename> static void stb(); // expected-note {{target}} + template<typename> struct tc {}; // expected-note {{target}} + template<typename> using te = int; // expected-note {{target}} + template<typename> using tf = c; // expected-note {{target}} + } +} + +export { // expected-note 18{{here}} + using ::a; + using ::sa; // expected-error {{using declaration referring to 'sa' with internal linkage}} + using ::b; + using ::sb; // expected-error {{using declaration referring to 'sb' with internal linkage}} + using ::c; + using ::d; + using ::e; + using ::f; + using ::sg1; // expected-error {{using declaration referring to 'sg1' with internal linkage}} + + using ::ta; + using ::sta; // FIXME {{using declaration referring to 'sta' with internal linkage}} + using ::tb; + using ::stb; // expected-error {{using declaration referring to 'stb' with internal linkage}} + using ::tc; + using ::te; + using ::tf; + namespace NS2 = ::NS; + + namespace UnnamedNS { + using UnnamedNS::a; // expected-error {{internal linkage}} + using UnnamedNS::sa; // expected-error {{internal linkage}} + using UnnamedNS::b; // expected-error {{internal linkage}} + using UnnamedNS::sb; // expected-error {{internal linkage}} + using UnnamedNS::c; // expected-error {{internal linkage}} + using UnnamedNS::d; // expected-error {{internal linkage}} + using UnnamedNS::e; // ok + using UnnamedNS::f; // ok? using-declaration refers to alias-declaration, + // which does not have linkage (even though that then + // refers to a type that has internal linkage) + using UnnamedNS::sg1; // expected-error {{internal linkage}} + + using UnnamedNS::ta; // expected-error {{internal linkage}} + using UnnamedNS::sta; // expected-error {{internal linkage}} + using UnnamedNS::tb; // expected-error {{internal linkage}} + using UnnamedNS::stb; // expected-error {{internal linkage}} + using UnnamedNS::tc; // expected-error {{internal linkage}} + using UnnamedNS::te; // expected-error {{internal linkage}} + using UnnamedNS::tf; // expected-error {{internal linkage}} + namespace NS2 = UnnamedNS::NS; // ok (wording bug?) + } +} diff --git a/clang/test/CXX/modules-ts/basic/basic.def.odr/p4/module.cpp b/clang/test/CXX/modules-ts/basic/basic.def.odr/p4/module.cpp index ad03191363e..6eb5639d302 100644 --- a/clang/test/CXX/modules-ts/basic/basic.def.odr/p4/module.cpp +++ b/clang/test/CXX/modules-ts/basic/basic.def.odr/p4/module.cpp @@ -3,7 +3,6 @@ // CHECK-DAG: @extern_var_exported = external {{(dso_local )?}}global // CHECK-DAG: @inline_var_exported = linkonce_odr {{(dso_local )?}}global -// CHECK-DAG: @_ZW6ModuleE19static_var_exported = available_externally {{(dso_local )?}}global i32 0, // CHECK-DAG: @const_var_exported = available_externally {{(dso_local )?}}constant i32 3, // // CHECK-DAG: @_ZW6ModuleE25extern_var_module_linkage = external {{(dso_local )?}}global @@ -21,7 +20,6 @@ void use() { (void)&extern_var_exported; (void)&inline_var_exported; - (void)&static_var_exported; // FIXME: Should not be exported. (void)&const_var_exported; // FIXME: This symbol should not be visible here. diff --git a/clang/test/CXX/modules-ts/basic/basic.def.odr/p4/module.cppm b/clang/test/CXX/modules-ts/basic/basic.def.odr/p4/module.cppm index 0f2c0db66e9..65861f84bae 100644 --- a/clang/test/CXX/modules-ts/basic/basic.def.odr/p4/module.cppm +++ b/clang/test/CXX/modules-ts/basic/basic.def.odr/p4/module.cppm @@ -11,7 +11,6 @@ // can discard this global and its initializer (if any), and other TUs are not // permitted to run the initializer for this variable. // CHECK-DAG: @inline_var_exported = linkonce_odr {{(dso_local )?}}global -// CHECK-DAG: @_ZW6ModuleE19static_var_exported = {{(dso_local )?}}global // CHECK-DAG: @const_var_exported = {{(dso_local )?}}constant // // CHECK-DAG: @_ZW6ModuleE25extern_var_module_linkage = external {{(dso_local )?}}global @@ -58,32 +57,17 @@ void noninline_global_module() { export module Module; export { - // FIXME: These should be ill-formed: you can't export an internal linkage - // symbol, per [dcl.module.interface]p2. - // CHECK: define {{(dso_local )?}}void {{.*}}@_ZW6ModuleE22unused_static_exportedv - static void unused_static_exported() {} - // CHECK: define {{(dso_local )?}}void {{.*}}@_ZW6ModuleE20used_static_exportedv - static void used_static_exported() {} - inline void unused_inline_exported() {} inline void used_inline_exported() {} extern int extern_var_exported; inline int inline_var_exported; - // FIXME: This should be ill-formed: you can't export an internal linkage - // symbol. - static int static_var_exported; const int const_var_exported = 3; // CHECK: define {{(dso_local )?}}void {{.*}}@_Z18noninline_exportedv void noninline_exported() { - used_static_exported(); - // CHECK: define linkonce_odr {{.*}}@_Z20used_inline_exportedv - used_inline_exported(); - (void)&extern_var_exported; (void)&inline_var_exported; - (void)&static_var_exported; (void)&const_var_exported; } } diff --git a/clang/test/CXX/modules-ts/basic/basic.def.odr/p4/user.cpp b/clang/test/CXX/modules-ts/basic/basic.def.odr/p4/user.cpp index 97c69fa0bbe..d55e0637971 100644 --- a/clang/test/CXX/modules-ts/basic/basic.def.odr/p4/user.cpp +++ b/clang/test/CXX/modules-ts/basic/basic.def.odr/p4/user.cpp @@ -3,7 +3,6 @@ // CHECK-DAG: @extern_var_exported = external {{(dso_local )?}}global // CHECK-DAG: @inline_var_exported = linkonce_odr {{(dso_local )?}}global -// CHECK-DAG: @_ZW6ModuleE19static_var_exported = available_externally {{(dso_local )?}}global i32 0 // CHECK-DAG: @const_var_exported = available_externally {{(dso_local )?}}constant i32 3 import Module; @@ -16,7 +15,6 @@ void use() { (void)&extern_var_exported; (void)&inline_var_exported; - (void)&static_var_exported; (void)&const_var_exported; // Module-linkage declarations are not visible here. diff --git a/clang/test/SemaCXX/anonymous-union-export.cpp b/clang/test/SemaCXX/anonymous-union-export.cpp index 1d83d809f52..689c6b9f17e 100644 --- a/clang/test/SemaCXX/anonymous-union-export.cpp +++ b/clang/test/SemaCXX/anonymous-union-export.cpp @@ -1,6 +1,7 @@ // RUN: %clang_cc1 -std=c++17 -fmodules-ts -emit-obj -verify -o %t.pcm %s export module M; -export { - union { bool a; }; // expected-error{{anonymous unions at namespace or global scope must be declared 'static'}} +export { // expected-note 2{{export block begins here}} + union { bool a; }; // expected-error {{anonymous unions at namespace or global scope must be declared 'static'}} expected-error {{declaration of 'a' with internal linkage cannot be exported}} + static union { bool a; }; // expected-error {{declaration of 'a' with internal linkage cannot be exported}} } diff --git a/clang/test/SemaCXX/modules-ts.cppm b/clang/test/SemaCXX/modules-ts.cppm index c07ee82e313..1081995c586 100644 --- a/clang/test/SemaCXX/modules-ts.cppm +++ b/clang/test/SemaCXX/modules-ts.cppm @@ -49,8 +49,12 @@ int use_a = a; // expected-error {{declaration of 'a' must be imported from modu import foo; export {} // expected-error {{export declaration cannot be empty}} -export { ; } -export { static_assert(true); } +export { // expected-note {{begins here}} + ; // expected-warning {{ISO C++20 does not permit an empty declaration to appear in an export block}} +} +export { // expected-note {{begins here}} + static_assert(true); // expected-warning {{ISO C++20 does not permit a static_assert declaration to appear in an export block}} +} int use_b = b; int use_n = n; // FIXME: this should not be visible, because it is not exported @@ -74,7 +78,7 @@ struct S { // language rules right now, but (per personal correspondence between zygoloid // and gdr) is the intent. #if TEST == 1 -export { +export { // expected-note {{export block begins here}} extern "C++" { namespace NestedExport { export { // expected-error {{appears within another export}} |