411 lines · cpp
1// RUN: %clang_cc1 -no-enable-noundef-analysis %s -triple=thumbv7-apple-ios6.0 -fno-use-cxa-atexit -target-abi apcs-gnu -emit-llvm -std=gnu++98 -o - -fexceptions | FileCheck -check-prefix=CHECK -check-prefix=CHECK98 %s2// RUN: %clang_cc1 -no-enable-noundef-analysis %s -triple=thumbv7-apple-ios6.0 -fno-use-cxa-atexit -target-abi apcs-gnu -emit-llvm -std=gnu++11 -o - -fexceptions | FileCheck -check-prefix=CHECK -check-prefix=CHECK11 %s3 4// CHECK: @_ZZN5test74testEvE1x = internal global i32 0, align 45// CHECK: @_ZGVZN5test74testEvE1x = internal global i32 06// CHECK: @_ZZN5test84testEvE1x = internal global [[TEST8A:.*]] zeroinitializer, align 17// CHECK: @_ZGVZN5test84testEvE1x = internal global i32 08 9typedef typeof(sizeof(int)) size_t;10 11class foo {12public:13 foo();14 virtual ~foo();15};16 17class bar : public foo {18public:19 bar();20};21 22// The global dtor needs the right calling conv with -fno-use-cxa-atexit23bar baz;24 25// PR959326// Make sure atexit(3) is used for global dtors.27 28// CHECK: call ptr @_ZN3barC1Ev(29// CHECK-NEXT: call i32 @atexit(ptr @__dtor_baz)30 31// CHECK-NOT: @_GLOBAL__D_a()32// CHECK-LABEL: define internal void @__dtor_baz()33// CHECK: call ptr @_ZN3barD1Ev(ptr @baz)34 35// Destructors and constructors must return this.36namespace test1 {37 void foo();38 39 struct A {40 A(int i) { foo(); }41 ~A() { foo(); }42 void bar() { foo(); }43 };44 45 // CHECK-LABEL: define{{.*}} void @_ZN5test14testEv()46 void test() {47 // CHECK: [[AV:%.*]] = alloca [[A:%.*]], align 148 // CHECK: call ptr @_ZN5test11AC1Ei(ptr {{[^,]*}} [[AV]], i32 10)49 // CHECK: invoke void @_ZN5test11A3barEv(ptr {{[^,]*}} [[AV]])50 // CHECK: call ptr @_ZN5test11AD1Ev(ptr {{[^,]*}} [[AV]])51 // CHECK: ret void52 A a = 10;53 a.bar();54 }55 56 // CHECK: define linkonce_odr ptr @_ZN5test11AC1Ei(ptr {{[^,]*}} returned {{[^,]*}} %this, i32 %i) unnamed_addr57 // CHECK: [[THIS:%.*]] = alloca ptr, align 458 // CHECK: store ptr {{.*}}, ptr [[THIS]]59 // CHECK: [[THIS1:%.*]] = load ptr, ptr [[THIS]]60 // CHECK: {{%.*}} = call ptr @_ZN5test11AC2Ei(61 // CHECK: ret ptr [[THIS1]]62 63 // CHECK: define linkonce_odr ptr @_ZN5test11AD1Ev(ptr {{[^,]*}} returned {{[^,]*}} %this) unnamed_addr64 // CHECK: [[THIS:%.*]] = alloca ptr, align 465 // CHECK: store ptr {{.*}}, ptr [[THIS]]66 // CHECK: [[THIS1:%.*]] = load ptr, ptr [[THIS]]67 // CHECK: {{%.*}} = call ptr @_ZN5test11AD2Ev(68 // CHECK: ret ptr [[THIS1]]69}70 71// Awkward virtual cases.72namespace test2 {73 void foo();74 75 struct A {76 int x;77 78 A(int);79 virtual ~A() { foo(); }80 };81 82 struct B {83 int y;84 int z;85 86 B(int);87 virtual ~B() { foo(); }88 };89 90 struct C : A, virtual B {91 int q;92 93 C(int i) : A(i), B(i) { foo(); }94 ~C() { foo(); }95 };96 97 void test() {98 C c = 10;99 }100 101 // Tests at eof102}103 104namespace test3 {105 struct A {106 int x;107 ~A();108 };109 110 void a() {111 // CHECK-LABEL: define{{.*}} void @_ZN5test31aEv()112 // CHECK: call noalias nonnull ptr @_Znam(i32 48)113 // CHECK: store i32 4114 // CHECK: store i32 10115 A *x = new A[10];116 }117 118 void b(int n) {119 // CHECK-LABEL: define{{.*}} void @_ZN5test31bEi(120 // CHECK: [[N:%.*]] = load i32, ptr121 // CHECK: @llvm.umul.with.overflow.i32(i32 [[N]], i32 4)122 // CHECK: @llvm.uadd.with.overflow.i32(i32 {{.*}}, i32 8)123 // CHECK: [[OR:%.*]] = or i1124 // CHECK: [[SZ:%.*]] = select i1 [[OR]]125 // CHECK: call noalias nonnull ptr @_Znam(i32 [[SZ]])126 // CHECK: store i32 4127 // CHECK: store i32 [[N]]128 A *x = new A[n];129 }130 131 void c() {132 // CHECK-LABEL: define{{.*}} void @_ZN5test31cEv()133 // CHECK: call noalias nonnull ptr @_Znam(i32 808)134 // CHECK: store i32 4135 // CHECK: store i32 200136 A (*x)[20] = new A[10][20];137 }138 139 void d(int n) {140 // CHECK-LABEL: define{{.*}} void @_ZN5test31dEi(141 // CHECK: [[N:%.*]] = load i32, ptr142 // CHECK: @llvm.umul.with.overflow.i32(i32 [[N]], i32 80)143 // CHECK: [[NE:%.*]] = mul i32 [[N]], 20144 // CHECK: @llvm.uadd.with.overflow.i32(i32 {{.*}}, i32 8)145 // CHECK: [[SZ:%.*]] = select146 // CHECK: call noalias nonnull ptr @_Znam(i32 [[SZ]])147 // CHECK: store i32 4148 // CHECK: store i32 [[NE]]149 A (*x)[20] = new A[n][20];150 }151 152 void e(A *x) {153 // CHECK-LABEL: define{{.*}} void @_ZN5test31eEPNS_1AE(154 // CHECK: icmp eq {{.*}}, null155 // CHECK: getelementptr {{.*}}, i32 -8156 // CHECK: getelementptr {{.*}}, i32 4157 // CHECK: load158 // CHECK98: invoke {{.*}} @_ZN5test31AD1Ev159 // CHECK11: call {{.*}} @_ZN5test31AD1Ev160 // CHECK: call void @_ZdaPv161 delete [] x;162 }163 164 void f(A (*x)[20]) {165 // CHECK-LABEL: define{{.*}} void @_ZN5test31fEPA20_NS_1AE(166 // CHECK: icmp eq {{.*}}, null167 // CHECK: getelementptr {{.*}}, i32 -8168 // CHECK: getelementptr {{.*}}, i32 4169 // CHECK: load170 // CHECK98: invoke {{.*}} @_ZN5test31AD1Ev171 // CHECK11: call {{.*}} @_ZN5test31AD1Ev172 // CHECK: call void @_ZdaPv173 delete [] x;174 }175}176 177namespace test4 {178 struct A {179 int x;180 void operator delete[](void *, size_t sz);181 };182 183 void a() {184 // CHECK-LABEL: define{{.*}} void @_ZN5test41aEv()185 // CHECK: call noalias nonnull ptr @_Znam(i32 48)186 // CHECK: store i32 4187 // CHECK: store i32 10188 A *x = new A[10];189 }190 191 void b(int n) {192 // CHECK-LABEL: define{{.*}} void @_ZN5test41bEi(193 // CHECK: [[N:%.*]] = load i32, ptr194 // CHECK: @llvm.umul.with.overflow.i32(i32 [[N]], i32 4)195 // CHECK: @llvm.uadd.with.overflow.i32(i32 {{.*}}, i32 8)196 // CHECK: [[SZ:%.*]] = select197 // CHECK: call noalias nonnull ptr @_Znam(i32 [[SZ]])198 // CHECK: store i32 4199 // CHECK: store i32 [[N]]200 A *x = new A[n];201 }202 203 void c() {204 // CHECK-LABEL: define{{.*}} void @_ZN5test41cEv()205 // CHECK: call noalias nonnull ptr @_Znam(i32 808)206 // CHECK: store i32 4207 // CHECK: store i32 200208 A (*x)[20] = new A[10][20];209 }210 211 void d(int n) {212 // CHECK-LABEL: define{{.*}} void @_ZN5test41dEi(213 // CHECK: [[N:%.*]] = load i32, ptr214 // CHECK: @llvm.umul.with.overflow.i32(i32 [[N]], i32 80)215 // CHECK: [[NE:%.*]] = mul i32 [[N]], 20216 // CHECK: @llvm.uadd.with.overflow.i32(i32 {{.*}}, i32 8)217 // CHECK: [[SZ:%.*]] = select218 // CHECK: call noalias nonnull ptr @_Znam(i32 [[SZ]])219 // CHECK: store i32 4220 // CHECK: store i32 [[NE]]221 A (*x)[20] = new A[n][20];222 }223 224 void e(A *x) {225 // CHECK-LABEL: define{{.*}} void @_ZN5test41eEPNS_1AE(226 // CHECK: [[ALLOC:%.*]] = getelementptr inbounds {{.*}}, i32 -8227 // CHECK: getelementptr inbounds {{.*}}, i32 4228 // CHECK: [[T0:%.*]] = load i32, ptr229 // CHECK: [[T1:%.*]] = mul i32 4, [[T0]]230 // CHECK: [[T2:%.*]] = add i32 [[T1]], 8231 // CHECK: call void @_ZN5test41AdaEPvm(ptr [[ALLOC]], i32 [[T2]])232 delete [] x;233 }234 235 void f(A (*x)[20]) {236 // CHECK-LABEL: define{{.*}} void @_ZN5test41fEPA20_NS_1AE(237 // CHECK: [[ALLOC:%.*]] = getelementptr inbounds {{.*}}, i32 -8238 // CHECK: getelementptr inbounds {{.*}}, i32 4239 // CHECK: [[T0:%.*]] = load i32, ptr240 // CHECK: [[T1:%.*]] = mul i32 4, [[T0]]241 // CHECK: [[T2:%.*]] = add i32 [[T1]], 8242 // CHECK: call void @_ZN5test41AdaEPvm(ptr [[ALLOC]], i32 [[T2]])243 delete [] x;244 }245}246 247namespace test5 {248 struct A {249 ~A();250 };251 252 // CHECK-LABEL: define{{.*}} void @_ZN5test54testEPNS_1AE253 void test(A *a) {254 // CHECK: [[PTR:%.*]] = alloca ptr, align 4255 // CHECK-NEXT: store ptr {{.*}}, ptr [[PTR]], align 4256 // CHECK-NEXT: [[TMP:%.*]] = load ptr, ptr [[PTR]], align 4257 // CHECK-NEXT: call ptr @_ZN5test51AD1Ev(ptr {{[^,]*}} [[TMP]])258 // CHECK-NEXT: ret void259 a->~A();260 }261}262 263namespace test6 {264 struct A {265 virtual ~A();266 };267 268 // CHECK-LABEL: define{{.*}} void @_ZN5test64testEPNS_1AE269 void test(A *a) {270 // CHECK: [[AVAR:%.*]] = alloca ptr, align 4271 // CHECK-NEXT: store ptr {{.*}}, ptr [[AVAR]], align 4272 // CHECK-NEXT: [[V:%.*]] = load ptr, ptr [[AVAR]], align 4273 // CHECK-NEXT: [[ISNULL:%.*]] = icmp eq ptr [[V]], null274 // CHECK-NEXT: br i1 [[ISNULL]]275 // CHECK: [[T1:%.*]] = load ptr, ptr [[V]]276 // CHECK-NEXT: [[T2:%.*]] = getelementptr inbounds ptr, ptr [[T1]], i64 1277 // CHECK-NEXT: [[T3:%.*]] = load ptr, ptr [[T2]]278 // CHECK-NEXT: call void [[T3]](ptr {{[^,]*}} [[V]])279 // CHECK-NEXT: br label280 // CHECK: ret void281 delete a;282 }283}284 285namespace test7 {286 int foo();287 288 // Static and guard tested at top of file289 290 // CHECK-LABEL: define{{.*}} void @_ZN5test74testEv() {{.*}} personality ptr @__gxx_personality_v0291 void test() {292 // CHECK: [[T0:%.*]] = load atomic i8, ptr @_ZGVZN5test74testEvE1x acquire, align 4293 // CHECK-NEXT: [[T1:%.*]] = and i8 [[T0]], 1294 // CHECK-NEXT: [[T2:%.*]] = icmp eq i8 [[T1]], 0295 // CHECK-NEXT: br i1 [[T2]]296 // -> fallthrough, end297 // CHECK: [[T3:%.*]] = call i32 @__cxa_guard_acquire(ptr @_ZGVZN5test74testEvE1x)298 // CHECK-NEXT: [[T4:%.*]] = icmp ne i32 [[T3]], 0299 // CHECK-NEXT: br i1 [[T4]]300 // -> fallthrough, end301 // CHECK: [[INIT:%.*]] = invoke i32 @_ZN5test73fooEv()302 // CHECK: store i32 [[INIT]], ptr @_ZZN5test74testEvE1x, align 4303 // CHECK-NEXT: call void @__cxa_guard_release(ptr @_ZGVZN5test74testEvE1x)304 // CHECK-NEXT: br label305 // -> end306 // end:307 // CHECK: ret void308 static int x = foo();309 310 // CHECK: landingpad { ptr, i32 }311 // CHECK-NEXT: cleanup312 // CHECK: call void @__cxa_guard_abort(ptr @_ZGVZN5test74testEvE1x)313 // CHECK: resume { ptr, i32 }314 }315}316 317namespace test8 {318 struct A {319 A();320 ~A();321 };322 323 // Static and guard tested at top of file324 325 // CHECK-LABEL: define{{.*}} void @_ZN5test84testEv() {{.*}} personality ptr @__gxx_personality_v0326 void test() {327 // CHECK: [[T0:%.*]] = load atomic i8, ptr @_ZGVZN5test84testEvE1x acquire, align 4328 // CHECK-NEXT: [[T1:%.*]] = and i8 [[T0]], 1329 // CHECK-NEXT: [[T2:%.*]] = icmp eq i8 [[T1]], 0330 // CHECK-NEXT: br i1 [[T2]]331 // -> fallthrough, end332 // CHECK: [[T3:%.*]] = call i32 @__cxa_guard_acquire(ptr @_ZGVZN5test84testEvE1x)333 // CHECK-NEXT: [[T4:%.*]] = icmp ne i32 [[T3]], 0334 // CHECK-NEXT: br i1 [[T4]]335 // -> fallthrough, end336 // CHECK: [[INIT:%.*]] = invoke ptr @_ZN5test81AC1Ev(ptr {{[^,]*}} @_ZZN5test84testEvE1x)337 338 // FIXME: Here we register a global destructor that339 // unconditionally calls the destructor. That's what we've always340 // done for -fno-use-cxa-atexit here, but that's really not341 // semantically correct at all.342 343 // CHECK: call void @__cxa_guard_release(ptr @_ZGVZN5test84testEvE1x)344 // CHECK-NEXT: br label345 // -> end346 // end:347 // CHECK: ret void348 static A x;349 350 // CHECK: landingpad { ptr, i32 }351 // CHECK-NEXT: cleanup352 // CHECK: call void @__cxa_guard_abort(ptr @_ZGVZN5test84testEvE1x)353 // CHECK: resume { ptr, i32 }354 }355}356 357// Use a larger-than-mandated array cookie when allocating an358// array whose type is overaligned.359namespace test9 {360 class __attribute__((aligned(16))) A {361 float data[4];362 public:363 A();364 ~A();365 };366 367 A *testNew(unsigned n) {368 return new A[n];369 }370// CHECK: define{{.*}} ptr @_ZN5test97testNewEj(i32371// CHECK: [[N_VAR:%.*]] = alloca i32, align 4372// CHECK: [[N:%.*]] = load i32, ptr [[N_VAR]], align 4373// CHECK-NEXT: [[T0:%.*]] = call { i32, i1 } @llvm.umul.with.overflow.i32(i32 [[N]], i32 16)374// CHECK-NEXT: [[O0:%.*]] = extractvalue { i32, i1 } [[T0]], 1375// CHECK-NEXT: [[T1:%.*]] = extractvalue { i32, i1 } [[T0]], 0376// CHECK-NEXT: [[T2:%.*]] = call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 [[T1]], i32 16)377// CHECK-NEXT: [[O1:%.*]] = extractvalue { i32, i1 } [[T2]], 1378// CHECK-NEXT: [[OVERFLOW:%.*]] = or i1 [[O0]], [[O1]]379// CHECK-NEXT: [[T3:%.*]] = extractvalue { i32, i1 } [[T2]], 0380// CHECK-NEXT: [[T4:%.*]] = select i1 [[OVERFLOW]], i32 -1, i32 [[T3]]381// CHECK-NEXT: [[ALLOC:%.*]] = call noalias nonnull ptr @_Znam(i32 [[T4]])382// CHECK-NEXT: store i32 16, ptr [[ALLOC]]383// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds i32, ptr [[ALLOC]], i32 1384// CHECK-NEXT: store i32 [[N]], ptr [[T1]]385// CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds i8, ptr [[ALLOC]], i32 16386// Array allocation follows.387 388 void testDelete(A *array) {389 delete[] array;390 }391// CHECK-LABEL: define{{.*}} void @_ZN5test910testDeleteEPNS_1AE(392// CHECK: [[BEGIN:%.*]] = load ptr, ptr393// CHECK-NEXT: [[T0:%.*]] = icmp eq ptr [[BEGIN]], null394// CHECK-NEXT: br i1 [[T0]],395// CHECK: [[ALLOC:%.*]] = getelementptr inbounds i8, ptr [[BEGIN]], i32 -16396// CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds i8, ptr [[ALLOC]], i32 4397// CHECK-NEXT: [[N:%.*]] = load i32, ptr [[T0]]398// CHECK-NEXT: [[END:%.*]] = getelementptr inbounds [[TEST9:%.*]], ptr [[BEGIN]], i32 [[N]]399// CHECK-NEXT: [[T0:%.*]] = icmp eq ptr [[BEGIN]], [[END]]400// CHECK-NEXT: br i1 [[T0]],401// Array deallocation follows.402}403 404 // CHECK: define linkonce_odr ptr @_ZTv0_n12_N5test21CD1Ev(405 // CHECK: call ptr @_ZN5test21CD1Ev(406 // CHECK: ret ptr undef407 408 // CHECK-LABEL: define linkonce_odr void @_ZTv0_n12_N5test21CD0Ev(409 // CHECK: call void @_ZN5test21CD0Ev(410 // CHECK: ret void411