1 // RUN: %clang_cc1 %s -std=c++98 -triple %itanium_abi_triple -emit-llvm -o - | FileCheck %s
2 // RUN: %clang_cc1 %s -std=c++98 -triple %itanium_abi_triple -emit-llvm -o - -DPROTOTYPE | FileCheck --check-prefix=CHECK-PROTOTYPE %s
3 // RUN: %clang_cc1 %s -std=c++98 -triple %itanium_abi_triple -emit-llvm -o - -DINSTANTIATE | FileCheck --check-prefix=CHECK-INSTANTIATE %s
4 // RUN: %clang_cc1 %s -std=c++98 -triple %itanium_abi_triple -emit-llvm -o - -DPROTOTYPE -DINSTANTIATE | FileCheck --check-prefix=CHECK-PROTOTYPE-INSTANTIATE %s
5 // RUN: %clang_cc1 %s -DREDEFINE -verify
6 // RUN: %clang_cc1 %s -DPROTOTYPE -DREDEFINE -verify
7 // PR8007: friend function not instantiated, reordered version.
8 // Corresponds to http://gcc.gnu.org/bugzilla/show_bug.cgi?id=38392
9 
10 // CHECK: define linkonce_odr{{.*}}_ZlsR11std_ostreamRK8StreamerI3FooE
11 // CHECK-PROTOTYPE: define linkonce_odr{{.*}}_ZlsR11std_ostreamRK8StreamerI3FooE
12 // CHECK-INSTANTIATE: define linkonce_odr{{.*}}_ZlsR11std_ostreamRK8StreamerI3FooE
13 // CHECK-PROTOTYPE-INSTANTIATE: define linkonce_odr{{.*}}_ZlsR11std_ostreamRK8StreamerI3FooE
14 
15 struct std_ostream
16 {
17   int dummy;
18 };
19 
20 std_ostream cout;
21 
22 template <typename STRUCT_TYPE>
23 struct Streamer;
24 
25 typedef struct Foo {} Foo;
26 
27 inline std_ostream& operator << (std_ostream&, const Streamer<Foo>&);
28 
test(const Streamer<Foo> & foo)29 void test(const Streamer<Foo>& foo)
30 {
31     cout << foo;
32 }
33 
34 template <typename STRUCT_TYPE>
35 struct Streamer
36 {
operator <<(std_ostream & o,const Streamer & f)37     friend std_ostream& operator << (std_ostream& o, const Streamer& f) // expected-error{{redefinition of 'operator<<'}}
38         {
39             Streamer s(f);
40             s(o);
41             return o;
42         }
43 
StreamerStreamer44     Streamer(const STRUCT_TYPE& s) : s(s) {}
45 
46     const STRUCT_TYPE& s;
47     void operator () (std_ostream&) const;
48 };
49 
50 #ifdef PROTOTYPE
51 std_ostream& operator << (std_ostream&, const Streamer<Foo>&);
52 #endif
53 
54 #ifdef INSTANTIATE
55 template struct Streamer<Foo>;
56 #endif
57 
58 #ifdef REDEFINE
operator <<(std_ostream & o,const Streamer<Foo> &)59 std_ostream& operator << (std_ostream& o, const Streamer<Foo>&) // expected-note{{is here}}
60 {
61   return o;
62 }
63 #endif
64 
65 #ifndef INSTANTIATE
66 template <>
operator ()(std_ostream & o) const67 void Streamer<Foo>::operator () (std_ostream& o) const // expected-note{{requested here}}
68 {
69 }
70 #endif
71 
main(void)72 int main(void)
73 {
74     Foo foo;
75     test(foo);
76 }
77 
78