xref: /llvm-project/clang/test/SemaCXX/extern-c.cpp (revision 78abeca1d88593d7f2a27f3c3e140abe77236e7e)
1 // RUN: %clang_cc1 -fsyntax-only -verify %s
2 
3 namespace test1 {
4   extern "C" {
5     void test1_f() {
6       void test1_g(int);
7     }
8   }
9 }
10 int test1_g(int);
11 
12 namespace test2 {
13   extern "C" {
14     void test2_f() {
15       extern int test2_x; // expected-note {{declared with C language linkage here}}
16     }
17   }
18 }
19 float test2_x; // expected-error {{declaration of 'test2_x' in global scope conflicts with declaration with C language linkage}}
20 
21 namespace test3 {
22   extern "C" {
23     void test3_f() {
24       extern int test3_b; // expected-note {{previous declaration is here}}
25     }
26   }
27   extern "C" {
28     float test3_b; // expected-error {{redefinition of 'test3_b' with a different type: 'float' vs 'int'}}
29   }
30 }
31 
32 namespace N {
33   extern "C" {
34     void test4_f() {
35       extern int test4_b; // expected-note {{declared with C language linkage here}}
36     }
37   }
38 }
39 static float test4_b; // expected-error {{declaration of 'test4_b' in global scope conflicts with declaration with C language linkage}}
40 
41 extern "C" {
42   void test4c_f() {
43     extern int test4_c; // expected-note {{previous}}
44   }
45 }
46 static float test4_c; // expected-error {{redefinition of 'test4_c' with a different type: 'float' vs 'int'}}
47 
48 namespace N {
49   extern "C" {
50     void test5_f() {
51       extern int test5_b; // expected-note {{declared with C language linkage here}}
52     }
53   }
54 }
55 extern "C" {
56   static float test5_b; // expected-error {{declaration of 'test5_b' in global scope conflicts with declaration with C language linkage}}
57 }
58 
59 extern "C" {
60   void test5c_f() {
61     extern int test5_c; // expected-note {{previous}}
62   }
63 }
64 extern "C" {
65   static float test5_c; // expected-error {{redefinition of 'test5_c' with a different type: 'float' vs 'int'}}
66 }
67 
68 extern "C" {
69   void f() {
70     extern int test6_b;
71   }
72 }
73 namespace foo {
74   extern "C" {
75     static float test6_b;
76     extern float test6_b;
77   }
78 }
79 
80 namespace extern_ovl {
81   extern "C" {
82     __attribute__((overloadable))
83     void ovl_decl(void); // expected-note {{previous}}
84 
85     __attribute__((overloadable))
86     int ovl_decl(int);
87 
88     __attribute__((overloadable))
89     int ovl_decl(void); // expected-error {{functions that differ only in their return type}}
90   }
91 }
92 
93 namespace linkage {
94   namespace redecl {
95     extern "C" {
96       static void linkage_redecl();
97       static void linkage_redecl(int);
98       void linkage_redecl(); // ok, still not extern "C"
99       void linkage_redecl(int); // ok, still not extern "C"
100       void linkage_redecl(float); // expected-note {{previous}}
101       void linkage_redecl(double); // expected-error {{conflicting types}}
102     }
103   }
104   namespace redecl_2 {
105     extern "C" {
106       void linkage_redecl_2(); // expected-note {{previous}}
107       int linkage_redecl_2(int); // expected-error {{conflicting types}}
108     }
109   }
110   namespace from_outer {
111     void linkage_from_outer_1(); // expected-note {{previous}}
112     void linkage_from_outer_2(); // expected-note {{previous}}
113     extern "C" {
114       void linkage_from_outer_1(int);
115       void linkage_from_outer_1(); // expected-error {{different language linkage}}
116       void linkage_from_outer_2(); // expected-error {{different language linkage}}
117     }
118   }
119   namespace mixed {
120     extern "C" {
121       void linkage_mixed_1();
122       static void linkage_mixed_1(int);
123 
124       static void linkage_mixed_2(int);
125       void linkage_mixed_2();
126     }
127   }
128   namespace across_scopes {
129     namespace X {
130       extern "C" void linkage_across_scopes_f() {
131         void linkage_across_scopes_g(); // expected-note {{previous}}
132       }
133     }
134     namespace Y {
135       extern "C" void linkage_across_scopes_g(int); // expected-error {{conflicting}}
136     }
137   }
138 }
139 
140 int lookup_in_global_f; // expected-note {{here}}
141 namespace lookup_in_global {
142   void lookup_in_global_f();
143   void lookup_in_global_g();
144   extern "C" {
145     void lookup_in_global_f(int); // expected-error {{conflicts with declaration in global scope}}
146     void lookup_in_global_g(int); // expected-note {{here}}
147   }
148 }
149 int lookup_in_global_g; // expected-error {{conflicts with declaration with C language linkage}}
150 
151 namespace N1 {
152   extern "C" int different_kind_1; // expected-note {{here}}
153   extern "C" void different_kind_2(); // expected-note {{here}}
154 }
155 namespace N2 {
156   extern "C" void different_kind_1(); // expected-error {{different kind of symbol}}
157   extern "C" int different_kind_2; // expected-error {{different kind of symbol}}
158 }
159 
160 // We allow all these even though the standard says they are ill-formed.
161 extern "C" {
162   struct stat {};   // expected-warning{{empty struct has size 0 in C, size 1 in C++}}
163   void stat(struct stat);
164 }
165 namespace X {
166   extern "C" {
167     void stat(struct ::stat);
168   }
169 }
170 int stat(int *p);
171 void global_fn_vs_extern_c_var_1();
172 namespace X {
173   extern "C" int global_fn_vs_extern_c_var_1;
174   extern "C" int global_fn_vs_extern_c_var_2;
175 }
176 void global_fn_vs_extern_c_var_2();
177 void global_fn_vs_extern_c_fn_1();
178 namespace X {
179   extern "C" int global_fn_vs_extern_c_fn_1(int);
180   extern "C" int global_fn_vs_extern_c_fn_2(int);
181 }
182 void global_fn_vs_extern_c_fn_2();
183 extern "C" void name_with_using_decl_1(int);
184 namespace using_decl {
185   void name_with_using_decl_1();
186   void name_with_using_decl_2();
187   void name_with_using_decl_3();
188 }
189 using using_decl::name_with_using_decl_1;
190 using using_decl::name_with_using_decl_2;
191 extern "C" void name_with_using_decl_2(int);
192 extern "C" void name_with_using_decl_3(int);
193 using using_decl::name_with_using_decl_3;
194 
195 // We do not allow a global variable and an extern "C" function to have the same
196 // name, because such entities may have the same mangled name.
197 int global_var_vs_extern_c_fn_1; // expected-note {{here}}
198 namespace X {
199   extern "C" void global_var_vs_extern_c_fn_1(); // expected-error {{conflicts with declaration in global scope}}
200   extern "C" void global_var_vs_extern_c_fn_2(); // expected-note {{here}}
201 }
202 int global_var_vs_extern_c_fn_2; // expected-error {{conflicts with declaration with C language linkage}}
203 int global_var_vs_extern_c_var_1; // expected-note {{here}}
204 namespace X {
205   extern "C" double global_var_vs_extern_c_var_1; // expected-error {{conflicts with declaration in global scope}}
206   extern "C" double global_var_vs_extern_c_var_2; // expected-note {{here}}
207 }
208 int global_var_vs_extern_c_var_2; // expected-error {{conflicts with declaration with C language linkage}}
209 
210 template <class T> struct pr5065_n1 {};
211 extern "C" {
212   union pr5065_1 {}; // expected-warning{{empty union has size 0 in C, size 1 in C++}}
213   struct pr5065_2 { int: 0; }; // expected-warning{{struct has size 0 in C, size 1 in C++}}
214   struct pr5065_3 {}; // expected-warning{{empty struct has size 0 in C, size 1 in C++}}
215   struct pr5065_4 { // expected-warning{{empty struct has size 0 in C, size 1 in C++}}
216     struct Inner {}; // expected-warning{{empty struct has size 0 in C, size 1 in C++}}
217   };
218   // These should not warn
219   class pr5065_n3 {};
220   pr5065_n1<int> pr5065_v;
221   struct pr5065_n4 { void m() {} };
222   struct pr5065_n5 : public pr5065_3 {};
223   struct pr5065_n6 : public virtual pr5065_3 {};
224 }
225 struct pr5065_n7 {};
226 
227 namespace tag_hiding {
228   namespace namespace_with_injected_name {
229     class Boo {
230       friend struct ExternCStruct1;
231     };
232     void ExternCStruct4(); // expected-note 2{{candidate}}
233   }
234 
235   class Baz {
236     friend struct ExternCStruct2;
237     friend void ExternCStruct3();
238   };
239 
240   using namespace namespace_with_injected_name;
241 
242   extern "C" {
243     struct ExternCStruct1;
244     struct ExternCStruct2;
245     struct ExternCStruct3;
246     struct ExternCStruct4; // expected-note {{candidate}}
247   }
248   ExternCStruct1 *p1;
249   ExternCStruct2 *p2;
250   ExternCStruct3 *p3;
251   ExternCStruct4 *p4; // expected-error {{ambiguous}}
252 
253   extern "C" {
254     struct ExternCStruct1;
255     struct ExternCStruct2;
256     struct ExternCStruct3;
257     struct ExternCStruct4; // expected-note {{candidate}}
258   }
259   ExternCStruct1 *q1 = p1;
260   ExternCStruct2 *q2 = p2;
261   ExternCStruct3 *q3 = p3;
262   ExternCStruct4 *q4 = p4; // expected-error {{ambiguous}}
263 }
264 
265 namespace PR35697 {
266   typedef struct {} *ReturnStruct;
267   extern "C" ReturnStruct PR35697_f();
268   extern "C" ReturnStruct PR35697_v;
269   ReturnStruct PR35697_f();
270   ReturnStruct PR35697_v;
271 
272   namespace {
273     extern "C" ReturnStruct PR35697_f();
274     extern "C" ReturnStruct PR35697_v;
275     void q() {
276       extern ReturnStruct PR35697_f();
277       extern ReturnStruct PR35697_v;
278     }
279   }
280 }
281 
282 namespace PR46859 {
283   extern "bogus" // expected-error {{unknown linkage language}}
284     template<int> struct X {}; // expected-error {{templates can only be declared in namespace or class scope}}
285 }
286