Clang Project

clang_source_code/test/CodeGenCXX/constructors.cpp
1// RUN: %clang_cc1 -triple x86_64-apple-darwin10 %s -emit-llvm -o - | FileCheck %s --implicit-check-not=should_not_appear_in_output --check-prefixes=CHECK,NULL-INVALID
2// RUN: %clang_cc1 -triple x86_64-apple-darwin10 %s -emit-llvm -fno-delete-null-pointer-checks -o - | FileCheck %s --implicit-check-not=should_not_appear_in_output --check-prefixes=CHECK,NULL-VALID
3
4struct Member { int x; Member(); Member(int); Member(const Member &); };
5struct VBase { int x; VBase(); VBase(int); VBase(const VBase &); };
6
7struct ValueClass {
8  ValueClass(int x, int y) : x(x), y(y) {}
9  int x;
10  int y;
11}; // subject to ABI trickery
12
13
14
15/* Test basic functionality. */
16struct A {
17  A(struct Undeclared &);
18  A(ValueClass);
19  Member mem;
20};
21
22A::A(struct Undeclared &ref) : mem(0) {}
23
24// Check that delegation works.
25// NULL-INVALID-LABEL: define void @_ZN1AC2ER10Undeclared(%struct.A* %this, %struct.Undeclared* nonnull %ref) unnamed_addr
26// NULL-VALID-LABEL: define void @_ZN1AC2ER10Undeclared(%struct.A* %this, %struct.Undeclared* %ref) unnamed_addr
27// CHECK: call void @_ZN6MemberC1Ei(
28
29// NULL-INVALID-LABEL: define void @_ZN1AC1ER10Undeclared(%struct.A* %this, %struct.Undeclared* nonnull %ref) unnamed_addr
30// NULL-VALID-LABEL: define void @_ZN1AC1ER10Undeclared(%struct.A* %this, %struct.Undeclared* %ref) unnamed_addr
31// CHECK: call void @_ZN1AC2ER10Undeclared(
32
33A::A(ValueClass v) : mem(v.y - v.x) {}
34
35// CHECK-LABEL: define void @_ZN1AC2E10ValueClass(%struct.A* %this, i64 %v.coerce) unnamed_addr
36// CHECK: call void @_ZN6MemberC1Ei(
37
38// CHECK-LABEL: define void @_ZN1AC1E10ValueClass(%struct.A* %this, i64 %v.coerce) unnamed_addr
39// CHECK: call void @_ZN1AC2E10ValueClass(
40
41/* Test that things work for inheritance. */
42struct B : A {
43  B(struct Undeclared &);
44  Member mem;
45};
46
47B::B(struct Undeclared &ref) : A(ref), mem(1) {}
48
49// NULL-INVALID-LABEL: define void @_ZN1BC2ER10Undeclared(%struct.B* %this, %struct.Undeclared* nonnull %ref) unnamed_addr
50// NULL-VALID-LABEL: define void @_ZN1BC2ER10Undeclared(%struct.B* %this, %struct.Undeclared* %ref) unnamed_addr
51// CHECK: call void @_ZN1AC2ER10Undeclared(
52// CHECK: call void @_ZN6MemberC1Ei(
53
54// NULL-INVALID-LABEL: define void @_ZN1BC1ER10Undeclared(%struct.B* %this, %struct.Undeclared* nonnull %ref) unnamed_addr
55// NULL-VALID-LABEL: define void @_ZN1BC1ER10Undeclared(%struct.B* %this, %struct.Undeclared* %ref) unnamed_addr
56// CHECK: call void @_ZN1BC2ER10Undeclared(
57
58
59/* Test that the delegation optimization is disabled for classes with
60   virtual bases (for now).  This is necessary because a vbase
61   initializer could access one of the parameter variables by
62   reference.  That's a solvable problem, but let's not solve it right
63   now. */
64struct C : virtual A {
65  C(int);
66  Member mem;
67};
68C::C(int x) : A(ValueClass(x, x+1)), mem(x * x) {}
69
70// CHECK-LABEL: define void @_ZN1CC2Ei(%struct.C* %this, i8** %vtt, i32 %x) unnamed_addr
71// CHECK: call void @_ZN6MemberC1Ei(
72
73// CHECK-LABEL: define void @_ZN1CC1Ei(%struct.C* %this, i32 %x) unnamed_addr
74// CHECK: call void @_ZN10ValueClassC1Eii(
75// CHECK: call void @_ZN1AC2E10ValueClass(
76// CHECK: call void @_ZN6MemberC1Ei(
77
78
79/* Test that the delegation optimization is disabled for varargs
80   constructors. */
81struct D : A {
82  D(int, ...);
83  Member mem;
84};
85
86D::D(int x, ...) : A(ValueClass(x, x+1)), mem(x*x) {}
87
88// CHECK-LABEL: define void @_ZN1DC2Eiz(%struct.D* %this, i32 %x, ...) unnamed_addr
89// CHECK: call void @_ZN10ValueClassC1Eii(
90// CHECK: call void @_ZN1AC2E10ValueClass(
91// CHECK: call void @_ZN6MemberC1Ei(
92
93// CHECK-LABEL: define void @_ZN1DC1Eiz(%struct.D* %this, i32 %x, ...) unnamed_addr
94// CHECK: call void @_ZN10ValueClassC1Eii(
95// CHECK: call void @_ZN1AC2E10ValueClass(
96// CHECK: call void @_ZN6MemberC1Ei(
97
98// PR6622:  this shouldn't crash
99namespace test0 {
100  struct A {};
101  struct B : virtual A { int x; };
102  struct C : B {};
103  
104  void test(C &in) {
105    C tmp = in;
106  }
107}
108
109namespace test1 {
110  struct A { A(); void *ptr; };
111  struct B { B(); int x; A a[0]; };
112  B::B() {}
113  // CHECK-LABEL:    define void @_ZN5test11BC2Ev(
114  // CHECK:      [[THIS:%.*]] = load [[B:%.*]]*, [[B:%.*]]**
115  // CHECK-NEXT: ret void
116}
117
118// Ensure that we
119// a) emit the ABI-required but useless complete object and deleting destructor
120//    symbols for an abstract class, and 
121// b) do *not* emit references to virtual base destructors for an abstract class
122//
123// Our approach to this is to give these functions a body that simply traps.
124//
125// FIXME: We should ideally not create these symbols at all, but Clang can
126// actually generate references to them in other TUs in some cases, so we can't
127// stop emitting them without breaking ABI. See:
128//
129//   https://github.com/itanium-cxx-abi/cxx-abi/issues/10
130namespace abstract {
131  // Note, the destructor of this class is not instantiated here.
132  template<typename T> struct should_not_appear_in_output {
133    ~should_not_appear_in_output() { int arr[-(int)sizeof(T)]; }
134  };
135
136  struct X { ~X(); };
137
138  struct A : virtual should_not_appear_in_output<int>, X {
139    virtual ~A() = 0;
140  };
141
142  // CHECK-LABEL: define void @_ZN8abstract1AD2Ev(
143  // CHECK: call {{.*}}@_ZN8abstract1XD2Ev(
144  // CHECK: ret
145
146  // CHECK-LABEL: define void @_ZN8abstract1AD1Ev(
147  // CHECK: call {{.*}}@llvm.trap(
148  // CHECK: unreachable
149
150  // CHECK-LABEL: define void @_ZN8abstract1AD0Ev(
151  // CHECK: call {{.*}}@llvm.trap(
152  // CHECK: unreachable
153  A::~A() {}
154
155  struct B : virtual should_not_appear_in_output<int>, X {
156    virtual void f() = 0;
157    ~B();
158  };
159
160  // CHECK-LABEL: define void @_ZN8abstract1BD2Ev(
161  // CHECK: call {{.*}}@_ZN8abstract1XD2Ev(
162  // CHECK: ret
163
164  // CHECK-LABEL: define void @_ZN8abstract1BD1Ev(
165  // CHECK: call {{.*}}@llvm.trap(
166  // CHECK: unreachable
167
168  // CHECK-NOT: @_ZN8abstract1BD0Ev(
169  B::~B() {}
170}
171