1// RUN:     %clang_cc1 -std=c++1z -fmodules-ts -emit-module-interface %s -o %t.0.pcm -verify -DTEST=0
2// RUN:     %clang_cc1 -std=c++1z -fmodules-ts -emit-module-interface %s -o %t.1.pcm -verify -DTEST=1
3// RUN:     %clang_cc1 -std=c++1z -fmodules-ts -emit-module-interface %s -fmodule-file=%t.0.pcm -o %t.2.pcm -verify -DTEST=2
4// RUN:     %clang_cc1 -std=c++1z -fmodules-ts -emit-module-interface %s -fmodule-file=%t.0.pcm -o %t.3.pcm -verify -Dfoo=bar -DTEST=3
5
6#if TEST == 0
7// expected-no-diagnostics
8#endif
9
10export module foo;
11#if TEST == 2
12// expected-error@-2 {{redefinition of module 'foo'}}
13// expected-note@modules-ts.cppm:* {{loaded from}}
14#endif
15
16static int m;
17#if TEST == 2
18// expected-error@-2 {{redefinition of '}}
19// expected-note@-3 {{unguarded header; consider using #ifdef guards or #pragma once}}
20// FIXME: We should drop the "header from" in this diagnostic.
21// expected-note-re@modules-ts.cppm:1 {{'{{.*}}modules-ts.cppm' included multiple times, additional include site in header from module 'foo'}}
22#endif
23int n;
24#if TEST == 2
25// expected-error@-2 {{redefinition of '}}
26// expected-note@-3 {{unguarded header; consider using #ifdef guards or #pragma once}}
27// FIXME: We should drop the "header from" in this diagnostic.
28// expected-note-re@modules-ts.cppm:1 {{'{{.*}}modules-ts.cppm' included multiple times, additional include site in header from module 'foo'}}
29#endif
30
31#if TEST == 0
32export {
33  int a;
34  int b;
35  constexpr int *p = &n;
36}
37export int c;
38
39namespace N {
40  export void f() {}
41}
42
43export struct T {} t;
44#elif TEST == 3
45int use_a = a; // expected-error {{declaration of 'a' must be imported from module 'foo' before it is required}}
46// expected-note@-13 {{declaration here is not visible}}
47
48#undef foo
49import foo;
50
51export {} // expected-error {{export declaration cannot be empty}}
52export { // expected-note {{begins here}}
53  ; // expected-warning {{ISO C++20 does not permit an empty declaration to appear in an export block}}
54}
55export { // expected-note {{begins here}}
56  static_assert(true); // expected-warning {{ISO C++20 does not permit a static_assert declaration to appear in an export block}}
57}
58
59int use_b = b;
60int use_n = n; // FIXME: this should not be visible, because it is not exported
61
62extern int n;
63static_assert(&n != p);
64#endif
65
66
67#if TEST == 1
68struct S {
69  export int n; // expected-error {{expected member name or ';'}}
70  export static int n; // expected-error {{expected member name or ';'}}
71};
72#endif
73
74// FIXME: Exports of declarations without external linkage are disallowed.
75// Exports of declarations with non-external-linkage types are disallowed.
76
77// Cannot export within another export. This isn't precisely covered by the
78// language rules right now, but (per personal correspondence between zygoloid
79// and gdr) is the intent.
80#if TEST == 1
81export { // expected-note {{export block begins here}}
82  extern "C++" {
83    namespace NestedExport {
84      export { // expected-error {{appears within another export}}
85        int q;
86      }
87    }
88  }
89}
90#endif
91