1 | //RUN: %clang_cc1 %s -emit-llvm -o - -triple=i686-unknown-linux | FileCheck --check-prefix=CHECKGEN %s |
2 | //RUN: %clang_cc1 %s -emit-llvm -o - -triple=thumbv7-apple-ios6.0 -target-abi apcs-gnu | FileCheck --check-prefix=CHECKARM %s |
3 | //RUN: %clang_cc1 %s -emit-llvm -o - -triple=thumbv7-apple-ios5.0 -target-abi apcs-gnu | FileCheck --check-prefix=CHECKIOS5 %s |
4 | //RUN: %clang_cc1 %s -emit-llvm -o - -triple=wasm32-unknown-unknown \ |
5 | //RUN: | FileCheck --check-prefix=CHECKARM %s |
6 | //RUN: %clang_cc1 %s -emit-llvm -o - -triple=i386-pc-win32 -fno-rtti | FileCheck --check-prefix=CHECKMS %s |
7 | // FIXME: these tests crash on the bots when run with -triple=x86_64-pc-win32 |
8 | |
9 | // Make sure we attach the 'returned' attribute to the 'this' parameter of |
10 | // constructors and destructors which return this (and only these cases) |
11 | |
12 | class A { |
13 | public: |
14 | A(); |
15 | virtual ~A(); |
16 | |
17 | private: |
18 | int x_; |
19 | }; |
20 | |
21 | class B : public A { |
22 | public: |
23 | B(int *i); |
24 | virtual ~B(); |
25 | |
26 | private: |
27 | int *i_; |
28 | }; |
29 | |
30 | B::B(int *i) : i_(i) { } |
31 | B::~B() { } |
32 | |
33 | // CHECKGEN-LABEL: define void @_ZN1BC2EPi(%class.B* %this, i32* %i) |
34 | // CHECKGEN-LABEL: define void @_ZN1BC1EPi(%class.B* %this, i32* %i) |
35 | // CHECKGEN-LABEL: define void @_ZN1BD2Ev(%class.B* %this) |
36 | // CHECKGEN-LABEL: define void @_ZN1BD1Ev(%class.B* %this) |
37 | |
38 | // CHECKARM-LABEL: define %class.B* @_ZN1BC2EPi(%class.B* returned %this, i32* %i) |
39 | // CHECKARM-LABEL: define %class.B* @_ZN1BC1EPi(%class.B* returned %this, i32* %i) |
40 | // CHECKARM-LABEL: define %class.B* @_ZN1BD2Ev(%class.B* returned %this) |
41 | // CHECKARM-LABEL: define %class.B* @_ZN1BD1Ev(%class.B* returned %this) |
42 | |
43 | // CHECKIOS5-LABEL: define %class.B* @_ZN1BC2EPi(%class.B* %this, i32* %i) |
44 | // CHECKIOS5-LABEL: define %class.B* @_ZN1BC1EPi(%class.B* %this, i32* %i) |
45 | // CHECKIOS5-LABEL: define %class.B* @_ZN1BD2Ev(%class.B* %this) |
46 | // CHECKIOS5-LABEL: define %class.B* @_ZN1BD1Ev(%class.B* %this) |
47 | |
48 | // CHECKMS-LABEL: define dso_local x86_thiscallcc %class.B* @"??0B@@QAE@PAH@Z"(%class.B* returned %this, i32* %i) |
49 | // CHECKMS-LABEL: define dso_local x86_thiscallcc void @"??1B@@UAE@XZ"(%class.B* %this) |
50 | |
51 | class C : public A, public B { |
52 | public: |
53 | C(int *i, char *c); |
54 | virtual ~C(); |
55 | private: |
56 | char *c_; |
57 | }; |
58 | |
59 | C::C(int *i, char *c) : B(i), c_(c) { } |
60 | C::~C() { } |
61 | |
62 | // CHECKGEN-LABEL: define void @_ZN1CC2EPiPc(%class.C* %this, i32* %i, i8* %c) |
63 | // CHECKGEN-LABEL: define void @_ZN1CC1EPiPc(%class.C* %this, i32* %i, i8* %c) |
64 | // CHECKGEN-LABEL: define void @_ZN1CD2Ev(%class.C* %this) |
65 | // CHECKGEN-LABEL: define void @_ZN1CD1Ev(%class.C* %this) |
66 | // CHECKGEN-LABEL: define void @_ZThn8_N1CD1Ev(%class.C* %this) |
67 | // CHECKGEN-LABEL: define void @_ZN1CD0Ev(%class.C* %this) |
68 | // CHECKGEN-LABEL: define void @_ZThn8_N1CD0Ev(%class.C* %this) |
69 | |
70 | // CHECKARM-LABEL: define %class.C* @_ZN1CC2EPiPc(%class.C* returned %this, i32* %i, i8* %c) |
71 | // CHECKARM-LABEL: define %class.C* @_ZN1CC1EPiPc(%class.C* returned %this, i32* %i, i8* %c) |
72 | // CHECKARM-LABEL: define %class.C* @_ZN1CD2Ev(%class.C* returned %this) |
73 | // CHECKARM-LABEL: define %class.C* @_ZN1CD1Ev(%class.C* returned %this) |
74 | // CHECKARM-LABEL: define %class.C* @_ZThn8_N1CD1Ev(%class.C* %this) |
75 | // CHECKARM-LABEL: define void @_ZN1CD0Ev(%class.C* %this) |
76 | // CHECKARM-LABEL: define void @_ZThn8_N1CD0Ev(%class.C* %this) |
77 | |
78 | // CHECKIOS5-LABEL: define %class.C* @_ZN1CC2EPiPc(%class.C* %this, i32* %i, i8* %c) |
79 | // CHECKIOS5-LABEL: define %class.C* @_ZN1CC1EPiPc(%class.C* %this, i32* %i, i8* %c) |
80 | // CHECKIOS5-LABEL: define %class.C* @_ZN1CD2Ev(%class.C* %this) |
81 | // CHECKIOS5-LABEL: define %class.C* @_ZN1CD1Ev(%class.C* %this) |
82 | // CHECKIOS5-LABEL: define %class.C* @_ZThn8_N1CD1Ev(%class.C* %this) |
83 | // CHECKIOS5-LABEL: define void @_ZN1CD0Ev(%class.C* %this) |
84 | // CHECKIOS5-LABEL: define void @_ZThn8_N1CD0Ev(%class.C* %this) |
85 | |
86 | // CHECKMS-LABEL: define dso_local x86_thiscallcc %class.C* @"??0C@@QAE@PAHPAD@Z"(%class.C* returned %this, i32* %i, i8* %c) |
87 | // CHECKMS-LABEL: define dso_local x86_thiscallcc void @"??1C@@UAE@XZ"(%class.C* %this) |
88 | |
89 | class D : public virtual A { |
90 | public: |
91 | D(); |
92 | ~D(); |
93 | }; |
94 | |
95 | D::D() { } |
96 | D::~D() { } |
97 | |
98 | // CHECKGEN-LABEL: define void @_ZN1DC2Ev(%class.D* %this, i8** %vtt) |
99 | // CHECKGEN-LABEL: define void @_ZN1DC1Ev(%class.D* %this) |
100 | // CHECKGEN-LABEL: define void @_ZN1DD2Ev(%class.D* %this, i8** %vtt) |
101 | // CHECKGEN-LABEL: define void @_ZN1DD1Ev(%class.D* %this) |
102 | |
103 | // CHECKARM-LABEL: define %class.D* @_ZN1DC2Ev(%class.D* returned %this, i8** %vtt) |
104 | // CHECKARM-LABEL: define %class.D* @_ZN1DC1Ev(%class.D* returned %this) |
105 | // CHECKARM-LABEL: define %class.D* @_ZN1DD2Ev(%class.D* returned %this, i8** %vtt) |
106 | // CHECKARM-LABEL: define %class.D* @_ZN1DD1Ev(%class.D* returned %this) |
107 | |
108 | // CHECKIOS5-LABEL: define %class.D* @_ZN1DC2Ev(%class.D* %this, i8** %vtt) |
109 | // CHECKIOS5-LABEL: define %class.D* @_ZN1DC1Ev(%class.D* %this) |
110 | // CHECKIOS5-LABEL: define %class.D* @_ZN1DD2Ev(%class.D* %this, i8** %vtt) |
111 | // CHECKIOS5-LABEL: define %class.D* @_ZN1DD1Ev(%class.D* %this) |
112 | |
113 | // CHECKMS-LABEL: define dso_local x86_thiscallcc %class.D* @"??0D@@QAE@XZ"(%class.D* returned %this, i32 %is_most_derived) |
114 | // CHECKMS-LABEL: define dso_local x86_thiscallcc void @"??1D@@UAE@XZ"(%class.D* %this) |
115 | |
116 | class E { |
117 | public: |
118 | E(); |
119 | virtual ~E(); |
120 | }; |
121 | |
122 | E* gete(); |
123 | |
124 | void test_destructor() { |
125 | const E& e1 = E(); |
126 | E* e2 = gete(); |
127 | e2->~E(); |
128 | } |
129 | |
130 | // CHECKARM-LABEL: define void @_Z15test_destructorv() |
131 | |
132 | // Verify that virtual calls to destructors are not marked with a 'returned' |
133 | // this parameter at the call site... |
134 | // CHECKARM: [[VFN:%.*]] = getelementptr inbounds %class.E* (%class.E*)*, %class.E* (%class.E*)** |
135 | // CHECKARM: [[THUNK:%.*]] = load %class.E* (%class.E*)*, %class.E* (%class.E*)** [[VFN]] |
136 | // CHECKARM: call %class.E* [[THUNK]](%class.E* % |
137 | |
138 | // ...but static calls create declarations with 'returned' this |
139 | // CHECKARM: {{%.*}} = call %class.E* @_ZN1ED1Ev(%class.E* % |
140 | |
141 | // CHECKARM: declare %class.E* @_ZN1ED1Ev(%class.E* returned) |
142 | |