xref: /llvm-project/clang/test/SemaCXX/linkage2.cpp (revision 83ea47acd7116bf50274534ba9b3bd3035c01da6)
1 // RUN: %clang_cc1 -fsyntax-only -verify -Wno-non-c-typedef-for-linkage -std=gnu++11 %s
2 // RUN: %clang_cc1 -fsyntax-only -verify -Wno-non-c-typedef-for-linkage -Wno-c++11-extensions -Wno-local-type-template-args %s -std=gnu++98
3 // RUN: %clang_cc1 -fsyntax-only -verify -Wno-non-c-typedef-for-linkage -Wno-c++11-extensions -Wno-local-type-template-args -fmodules %s
4 
5 namespace test1 {
6   int x; // expected-note {{previous definition is here}}
7   static int y;
f()8   void f() {} // expected-note {{previous definition is here}}
9 
10   extern "C" {
11     extern int x; // expected-error {{declaration of 'x' has a different language linkage}}
12     extern int y; // OK, has internal linkage, so no language linkage.
13     void f(); // expected-error {{declaration of 'f' has a different language linkage}}
14   }
15 }
16 
17 // This is OK. Both test2_f don't have language linkage since they have
18 // internal linkage.
19 extern "C" {
test2_f()20   static void test2_f() {
21   }
test2_f(int x)22   static void test2_f(int x) {
23   }
24 }
25 
26 namespace test3 {
27   extern "C" {
28     namespace {
29       extern int x2;
30       void f2();
31     }
32   }
33   namespace {
34     int x2;
f2()35     void f2() {}
36   }
37 }
38 
39 namespace test4 {
dummy()40   void dummy() {
41     void Bar();
42     class A {
43       friend void Bar();
44     };
45   }
46 }
47 
48 namespace test5 {
49   static void g();
f()50   void f()
51   {
52     void g();
53   }
54 }
55 
56 // pr14898
57 namespace test6 {
58   template <class _Rp>
59   class __attribute__ ((__visibility__("default"))) shared_future;
60   template <class _Rp>
61   class future {
62     template <class> friend class shared_future;
63     shared_future<_Rp> share();
64   };
65   template <class _Rp> future<_Rp>
66   get_future();
67   template <class _Rp>
68   struct shared_future<_Rp&> {
69     shared_future(future<_Rp&>&& __f);
70   };
f()71   void f() {
72     typedef int T;
73     get_future<int>();
74     typedef int& U;
75     shared_future<int&> f1 = get_future<int&>();
76   }
77 }
78 
79 // This is OK. The variables have internal linkage and therefore no language
80 // linkage.
81 extern "C" {
82   static int test7_x;
83 }
84 extern "C++" {
85   extern int test7_x;
86 }
87 extern "C++" {
88   static int test7_y;
89 }
90 extern "C" {
91   extern int test7_y;
92 }
93 extern "C" { typedef int test7_F(); static test7_F test7_f; }
94 extern "C++" { extern test7_F test7_f; }
95 
96 // FIXME: This should be invalid. The function has no language linkage, but
97 // the function type has, so this is redeclaring the function with a different
98 // type.
99 extern "C++" {
100   static void test8_f();
101 }
102 extern "C" {
103   extern void test8_f();
104 }
105 extern "C" {
106   static void test8_g();
107 }
108 extern "C++" {
109   extern void test8_g();
110 }
111 
112 extern "C" {
113   void __attribute__((overloadable)) test9_f(int c); // expected-note {{previous declaration is here}}
114 }
115 extern "C++" {
116   void __attribute__((overloadable)) test9_f(int c); // expected-error {{declaration of 'test9_f' has a different language linkage}}
117 }
118 
119 extern "C" {
120   void __attribute__((overloadable)) test10_f(int);
121   void __attribute__((overloadable)) test10_f(double);
122 }
123 
124 extern "C" {
test11_f()125   void test11_f() {
126     void  __attribute__((overloadable)) test11_g(int);
127     void  __attribute__((overloadable)) test11_g(double);
128   }
129 }
130 
131 namespace test12 {
132   const int n = 0;
133   extern const int n;
f()134   void f() {
135     extern const int n;
136   }
137 }
138 
139 namespace test13 {
140   static void a(void);
141   extern void a();
a(void)142   static void a(void) {}
143 }
144 
145 namespace test14 {
146   // Anonymous namespace implies internal linkage, so 'static' has no effect.
147   namespace {
148     void a(void);
a(void)149     static void a(void) {}
150   }
151 }
152 
153 namespace test15 {
154   const int a = 5; // expected-note {{previous definition is here}}
155   static const int a; // expected-error {{redefinition of 'a'}}
156 }
157 
158 namespace test16 {
159   extern "C" {
160     class Foo {
161       int x;
162       friend int bar(Foo *y);
163     };
bar(Foo * y)164     int bar(Foo *y) {
165       return y->x;
166     }
167   }
168 }
169 
170 namespace test17 {
171   namespace {
172     struct I {
173     };
174   }
foo()175   template <typename T1, typename T2> void foo() {}
bar()176   template <typename T, T x> void bar() {}
177 #if __cplusplus < 201703L
178   // expected-note@-2 {{candidate function}}
179 #endif
g()180   inline void *g() {
181     struct L {
182     };
183     // foo<L, I>'s linkage should be the merge of UniqueExternalLinkage (or
184     // InternalLinkage in c++11) and VisibleNoLinkage. The correct answer is
185     // NoLinkage in both cases. This means that using foo<L, I> as a template
186     // argument should fail.
187     return reinterpret_cast<void*>(bar<typeof(foo<L, I>), foo<L, I> >);
188 #if __cplusplus < 201703L
189     // expected-error@-2 {{reinterpret_cast cannot resolve overloaded function 'bar' to type 'void *}}
190 #endif
191   }
h()192   void h() {
193     g();
194   }
195 }
196 
197 namespace test18 {
198   template <typename T> struct foo {
ftest18::foo199     template <T *P> static void f() {}
gtest18::foo200     static void *g() { return (void *)f<&x>; }
201     static T x;
202   };
203   template <typename T> T foo<T>::x;
f()204   inline void *f() {
205     struct S {
206     };
207     return foo<S>::g();
208   }
h()209   void *h() { return f(); }
210 }
211 
212 extern "C" void pr16247_foo(int);
213 static void pr16247_foo(double);
pr16247_foo(int)214 void pr16247_foo(int) {}
pr16247_foo(double)215 void pr16247_foo(double) {}
216 
217 namespace PR16247 {
218   extern "C" void pr16247_bar(int);
219   static void pr16247_bar(double);
pr16247_bar(int)220   void pr16247_bar(int) {}
pr16247_bar(double)221   void pr16247_bar(double) {}
222 }
223 namespace PR18964 {
224   unsigned &*foo; //expected-error{{'foo' declared as a pointer to a reference of type}}
225   extern struct {} *foo; // don't assert
226 }
227 
228 namespace typedef_name_for_linkage {
229   template<typename T> struct Use {};
230 
231   struct A { A(); A(const A&); ~A(); };
232 
233   typedef struct {
234     A a;
235   } B;
236 
237   struct C {
238     typedef struct {
239       A a;
240     } D;
241   };
242 
243   typedef struct {
ftypedef_name_for_linkage::__anon86bec12b0808244     void f() { static int n; struct Inner {};}
245   } E;
246 
247   // FIXME: Ideally this would be accepted in all modes. In C++98, we trigger a
248   // linkage calculation to drive the "internal linkage type as template
249   // argument" warning.
250   typedef struct {
ftypedef_name_for_linkage::__anon86bec12b0908251     void f() { struct Inner {}; Use<Inner> ui; }
252   } F;
253 #if __cplusplus < 201103L
254   // expected-error@-4 {{given name for linkage purposes by typedef declaration after its linkage was computed}}
255   // expected-note@-4 {{due to this member}}
256   // expected-note@-4 {{by this typedef}}
257 #endif
258 }
259