diff options
| author | Roman Divacky <rdivacky@FreeBSD.org> | 2010-07-13 17:21:42 +0000 |
|---|---|---|
| committer | Roman Divacky <rdivacky@FreeBSD.org> | 2010-07-13 17:21:42 +0000 |
| commit | 4ba675006b5a8edfc48b6a9bd3dcf54a70cc08f2 (patch) | |
| tree | 48b44512b5db8ced345df4a1a56b5065cf2a14d9 /test/CodeGenCXX | |
| parent | d7279c4c177bca357ef96ff1379fd9bc420bfe83 (diff) | |
Notes
Diffstat (limited to 'test/CodeGenCXX')
47 files changed, 1138 insertions, 95 deletions
diff --git a/test/CodeGenCXX/DynArrayInit.cpp b/test/CodeGenCXX/DynArrayInit.cpp new file mode 100644 index 000000000000..4b4c2ecf1d3e --- /dev/null +++ b/test/CodeGenCXX/DynArrayInit.cpp @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -O3 -emit-llvm -o - %s | FileCheck %s +// PR7490 + +// CHECK: define signext i8 @_Z2f0v +// CHECK: ret i8 0 +// CHECK: } +inline void* operator new[](unsigned long, void* __p) { return __p; } +static void f0_a(char *a) { + new (a) char[4](); +} +char f0() { + char a[4]; + f0_a(a); + return a[0] + a[1] + a[2] + a[3]; +} diff --git a/test/CodeGenCXX/alloca-align.cpp b/test/CodeGenCXX/alloca-align.cpp index b70e366f4cfb..99d6ab5845f2 100644 --- a/test/CodeGenCXX/alloca-align.cpp +++ b/test/CodeGenCXX/alloca-align.cpp @@ -18,7 +18,7 @@ extern "C" void f1() { (void) (struct s0) { 0, 0, 0, 0 }; } -// CHECK: define i64 @f2 +// CHECK: define i32 @f2 // CHECK: alloca %struct.s1, align 2 struct s1 { short x; short y; }; extern "C" struct s1 f2(int a, struct s1 *x, struct s1 *y) { diff --git a/test/CodeGenCXX/arm-cc.cpp b/test/CodeGenCXX/arm-cc.cpp new file mode 100644 index 000000000000..6027746b9ae8 --- /dev/null +++ b/test/CodeGenCXX/arm-cc.cpp @@ -0,0 +1,20 @@ +// RUN: %clang_cc1 %s -triple=arm-unknown-linux-gnueabi -target-abi aapcs -emit-llvm -o - | FileCheck %s + +class SMLoc { + const char *Ptr; +public: + SMLoc(); + SMLoc(const SMLoc &RHS); +}; +SMLoc foo(void *p); +void bar(void *x) { + foo(x); +} +void zed(SMLoc x); +void baz() { + SMLoc a; + zed(a); +} + +// CHECK: declare void @_Z3fooPv(%class.SMLoc* sret, i8*) +// CHECK: declare void @_Z3zed5SMLoc(%class.SMLoc*) diff --git a/test/CodeGenCXX/arm.cpp b/test/CodeGenCXX/arm.cpp index 5cca7885b7d7..1d4085ca231d 100644 --- a/test/CodeGenCXX/arm.cpp +++ b/test/CodeGenCXX/arm.cpp @@ -16,5 +16,4 @@ public: bar baz; // CHECK: @_GLOBAL__D_a() -// CHECK: call arm_apcscc void @_ZN3barD1Ev(%class.bar* @baz) - +// CHECK: call void @_ZN3barD1Ev(%class.bar* @baz) diff --git a/test/CodeGenCXX/block-in-ctor-dtor.cpp b/test/CodeGenCXX/block-in-ctor-dtor.cpp new file mode 100644 index 000000000000..e4389a4eeec8 --- /dev/null +++ b/test/CodeGenCXX/block-in-ctor-dtor.cpp @@ -0,0 +1,48 @@ +// RUN: %clang_cc1 %s -fblocks -triple x86_64-apple-darwin -emit-llvm -o - | FileCheck %s + +typedef void (^dispatch_block_t)(void); + +void dispatch_once(dispatch_block_t); + +class Zone { +public: + Zone(); + ~Zone(); +}; + +Zone::Zone() { + dispatch_once(^{}); + dispatch_once(^{}); +} + +Zone::~Zone() { + dispatch_once(^{}); + dispatch_once(^{}); +} + +class X : public virtual Zone { + X(); + ~X(); +}; + +X::X() { + dispatch_once(^{}); + dispatch_once(^{}); +}; + +X::~X() { + dispatch_once(^{}); + dispatch_once(^{}); +}; + + +// CHECK: define internal void @___ZN4ZoneC2Ev_block_invoke_ +// CHECK: define internal void @___ZN4ZoneC2Ev_block_invoke_ +// CHECK: define internal void @___ZN4ZoneD2Ev_block_invoke_ +// CHECK: define internal void @___ZN4ZoneD2Ev_block_invoke_ +// CHECK: define internal void @___ZN1XC1Ev_block_invoke_ +// CHECK: define internal void @___ZN1XC1Ev_block_invoke_ +// CHECK: define internal void @___ZN1XC2Ev_block_invoke_ +// CHECK: define internal void @___ZN1XC2Ev_block_invoke_ +// CHECK: define internal void @___ZN1XD2Ev_block_invoke_ +// CHECK: define internal void @___ZN1XD2Ev_block_invoke_ diff --git a/test/CodeGenCXX/condition.cpp b/test/CodeGenCXX/condition.cpp index f5b43d2ef491..bbc6d2f73b85 100644 --- a/test/CodeGenCXX/condition.cpp +++ b/test/CodeGenCXX/condition.cpp @@ -72,12 +72,10 @@ void switch_destruct(int z) { break; default: - // CHECK: {{sw.default:|:5}} // CHECK: store i32 19 z = 19; break; } - // CHECK: {{sw.epilog:|:6}} // CHECK: call void @_ZN16ConvertibleToIntD1Ev // CHECK: store i32 20 z = 20; @@ -96,66 +94,132 @@ void switch_destruct(int z) { int foo(); +// CHECK: define void @_Z14while_destructi void while_destruct(int z) { - // CHECK: define void @_Z14while_destructi - // CHECK: {{while.cond:|:3}} + // CHECK: [[Z:%.*]] = alloca i32 + // CHECK: [[CLEANUPDEST:%.*]] = alloca i32 while (X x = X()) { // CHECK: call void @_ZN1XC1Ev + // CHECK-NEXT: [[COND:%.*]] = call zeroext i1 @_ZN1XcvbEv + // CHECK-NEXT: br i1 [[COND]] - // CHECK: {{while.body:|:5}} - // CHECK: store i32 21 + // Loop-exit staging block. + // CHECK: store i32 1, i32* [[CLEANUPDEST]] + // CHECK-NEXT: br + + // While body. + // CHECK: store i32 21, i32* [[Z]] + // CHECK: store i32 2, i32* [[CLEANUPDEST]] + // CHECK-NEXT: br z = 21; - // CHECK: {{while.cleanup:|:6}} + // Cleanup. // CHECK: call void @_ZN1XD1Ev + // CHECK-NEXT: [[DEST:%.*]] = load i32* [[CLEANUPDEST]] + // CHECK-NEXT: switch i32 [[DEST]] } - // CHECK: {{while.end|:8}} - // CHECK: store i32 22 + + // CHECK: store i32 22, i32* [[Z]] z = 22; // CHECK: call void @_Z4getXv - // CHECK: call zeroext i1 @_ZN1XcvbEv - // CHECK: call void @_ZN1XD1Ev - // CHECK: br + // CHECK-NEXT: call zeroext i1 @_ZN1XcvbEv + // CHECK-NEXT: call void @_ZN1XD1Ev + // CHECK-NEXT: br while(getX()) { } - // CHECK: store i32 25 + // CHECK: store i32 25, i32* [[Z]] z = 25; // CHECK: ret } +// CHECK: define void @_Z12for_destructi( void for_destruct(int z) { - // CHECK: define void @_Z12for_destruct + // CHECK: [[Z:%.*]] = alloca i32 + // CHECK: [[XDEST:%.*]] = alloca i32 + // CHECK: [[I:%.*]] = alloca i32 // CHECK: call void @_ZN1YC1Ev - for(Y y = Y(); X x = X(); ++z) - // CHECK: {{for.cond:|:4}} + // CHECK-NEXT: br + // -> %for.cond + + for(Y y = Y(); X x = X(); ++z) { + // %for.cond: The loop condition. // CHECK: call void @_ZN1XC1Ev - // CHECK: {{for.body:|:6}} - // CHECK: store i32 23 + // CHECK-NEXT: [[COND:%.*]] = call zeroext i1 @_ZN1XcvbEv( + // CHECK-NEXT: br i1 [[COND]] + // -> %for.body, %for.cond.cleanup + + // %for.cond.cleanup: Exit cleanup staging. + // CHECK: store i32 1, i32* [[XDEST]] + // CHECK-NEXT: br + // -> %cleanup + + // %for.body: + // CHECK: store i32 23, i32* [[Z]] + // CHECK-NEXT: br + // -> %for.inc z = 23; - // CHECK: {{for.inc:|:7}} - // CHECK: br label %{{for.cond.cleanup|10}} - // CHECK: {{for.cond.cleanup:|:10}} + + // %for.inc: + // CHECK: [[TMP:%.*]] = load i32* [[Z]] + // CHECK-NEXT: [[INC:%.*]] = add nsw i32 [[TMP]], 1 + // CHECK-NEXT: store i32 [[INC]], i32* [[Z]] + // CHECK-NEXT: store i32 2, i32* [[XDEST]] + // CHECK-NEXT: br + // -> %cleanup + + // %cleanup: Destroys X. // CHECK: call void @_ZN1XD1Ev - // CHECK: {{for.end:|:12}} - // CHECK: call void @_ZN1YD1Ev + // CHECK-NEXT: [[YDESTTMP:%.*]] = load i32* [[XDEST]] + // CHECK-NEXT: switch i32 [[YDESTTMP]] + // 1 -> %cleanup4, 2 -> %cleanup.cont + + // %cleanup.cont: (eliminable) + // CHECK: br + // -> %for.cond + + // %cleanup4: Destroys Y. + // CHECK: call void @_ZN1YD1Ev( + // CHECK-NEXT: br + // -> %for.end + } + + // %for.end: // CHECK: store i32 24 z = 24; + // CHECK-NEXT: store i32 0, i32* [[I]] + // CHECK-NEXT: br + // -> %for.cond6 + + // %for.cond6: // CHECK: call void @_Z4getXv - // CHECK: call zeroext i1 @_ZN1XcvbEv - // CHECK: call void @_ZN1XD1Ev + // CHECK-NEXT: call zeroext i1 @_ZN1XcvbEv + // CHECK-NEXT: call void @_ZN1XD1Ev + // CHECK-NEXT: br + // -> %for.body10, %for.end16 + + // %for.body10: // CHECK: br + // -> %for.inc11 + + // %for.inc11: // CHECK: call void @_Z4getXv - // CHECK: load - // CHECK: add - // CHECK: call void @_ZN1XD1Ev + // CHECK-NEXT: load i32* [[I]] + // CHECK-NEXT: add + // CHECK-NEXT: store + // CHECK-NEXT: call void @_ZN1XD1Ev + // CHECK-NEXT: br + // -> %for.cond6 int i = 0; for(; getX(); getX(), ++i) { } - z = 26; + + // %for.end16 // CHECK: store i32 26 - // CHECK: ret + z = 26; + + // CHECK-NEXT: ret void } void do_destruct(int z) { diff --git a/test/CodeGenCXX/constructor-convert.cpp b/test/CodeGenCXX/constructor-convert.cpp index 7de07724bf17..338febbe97a9 100644 --- a/test/CodeGenCXX/constructor-convert.cpp +++ b/test/CodeGenCXX/constructor-convert.cpp @@ -1,4 +1,4 @@ -// RUN: %clang -emit-llvm -S -o - %s +// RUN: %clang_cc1 -emit-llvm -o - %s // PR5775 class Twine { diff --git a/test/CodeGenCXX/copy-in-cplus-object.cpp b/test/CodeGenCXX/copy-in-cplus-object.cpp new file mode 100644 index 000000000000..bdfca5e4ee0a --- /dev/null +++ b/test/CodeGenCXX/copy-in-cplus-object.cpp @@ -0,0 +1,28 @@ +// RUN: %clang_cc1 %s -fblocks -triple x86_64-apple-darwin -emit-llvm -o - | FileCheck %s + +struct S { + S(const char *); + ~S(); +}; + +struct TestObject +{ + TestObject(const TestObject& inObj, int def = 100, const S &Silly = "silly"); + TestObject(); + ~TestObject(); + TestObject& operator=(const TestObject& inObj); + int version() const; + +}; + +void testRoutine() { + TestObject one; + int (^V)() = ^{ return one.version(); }; +} + +// CHECK: call void @_ZN10TestObjectC1Ev +// CHECK: call void @_ZN1SC1EPKc +// CHECK: call void @_ZN10TestObjectC1ERKS_iRK1S +// CHECK: call void @_ZN1SD1Ev +// CHECK: call void @_ZN10TestObjectD1Ev +// CHECK: call void @_ZN10TestObjectD1Ev diff --git a/test/CodeGenCXX/cxx-apple-kext.cpp b/test/CodeGenCXX/cxx-apple-kext.cpp index 4ba69069bedd..e9a17277b0bb 100644 --- a/test/CodeGenCXX/cxx-apple-kext.cpp +++ b/test/CodeGenCXX/cxx-apple-kext.cpp @@ -1,6 +1,6 @@ -// RUN: %clang -ccc-host-triple x86_64-apple-darwin10 %s -flto -S -o - |\ +// RUN: %clangxx -ccc-host-triple x86_64-apple-darwin10 %s -flto -S -o - |\ // RUN: FileCheck --check-prefix=CHECK-NO-KEXT %s -// RUN: %clang -ccc-host-triple x86_64-apple-darwin10 %s -fapple-kext -flto -S -o - |\ +// RUN: %clangxx -ccc-host-triple x86_64-apple-darwin10 %s -fapple-kext -flto -S -o - |\ // RUN: FileCheck --check-prefix=CHECK-KEXT %s // CHECK-NO-KEXT-NOT: _GLOBAL__D_a diff --git a/test/CodeGenCXX/default-arg-temps.cpp b/test/CodeGenCXX/default-arg-temps.cpp index e4a06770cd9b..c4419850f12d 100644 --- a/test/CodeGenCXX/default-arg-temps.cpp +++ b/test/CodeGenCXX/default-arg-temps.cpp @@ -44,7 +44,6 @@ class obj{ int a; float b; double d; }; // CHECK: define void @_Z1hv() void h() { // CHECK: call void @llvm.memset.p0i8.i64( - // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64( obj o = obj(); } diff --git a/test/CodeGenCXX/destructors.cpp b/test/CodeGenCXX/destructors.cpp index 1442e3740393..8efaf01f3c60 100644 --- a/test/CodeGenCXX/destructors.cpp +++ b/test/CodeGenCXX/destructors.cpp @@ -32,6 +32,26 @@ struct C { C::~C() { } +namespace PR7526 { + extern void foo(); + struct allocator { + ~allocator() throw(); + }; + + struct allocator_derived : allocator { }; + + // CHECK: define void @_ZN6PR75269allocatorD2Ev + // CHECK: call void @__cxa_call_unexpected + allocator::~allocator() throw() { foo(); } + + // CHECK: define linkonce_odr void @_ZN6PR752617allocator_derivedD1Ev + // CHECK-NOT: call void @__cxa_call_unexpected + // CHECK: } + void foo() { + allocator_derived ad; + } +} + // PR5084 template<typename T> class A1 { @@ -168,15 +188,92 @@ namespace test3 { // Checked at top of file: // @_ZN5test312_GLOBAL__N_11CD1Ev = alias internal {{.*}} @_ZN5test312_GLOBAL__N_11CD2Ev + // More checks at end of file. + +} + +namespace test4 { + struct A { ~A(); }; + + // CHECK: define void @_ZN5test43fooEv() + // CHECK: call void @_ZN5test41AD1Ev + // CHECK: ret void + void foo() { + { + A a; + goto failure; + } + + failure: + return; + } + + // CHECK: define void @_ZN5test43barEi( + // CHECK: [[X:%.*]] = alloca i32 + // CHECK-NEXT: [[A:%.*]] = alloca + // CHECK: br label + // CHECK: [[TMP:%.*]] = load i32* [[X]] + // CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[TMP]], 0 + // CHECK-NEXT: br i1 + // CHECK: call void @_ZN5test41AD1Ev( + // CHECK: br label + // CHECK: [[TMP:%.*]] = load i32* [[X]] + // CHECK: [[TMP2:%.*]] = add nsw i32 [[TMP]], -1 + // CHECK: store i32 [[TMP2]], i32* [[X]] + // CHECK: br label + // CHECK: ret void + void bar(int x) { + for (A a; x; ) { + x--; + } + } +} + +// PR7575 +namespace test5 { + struct A { ~A(); }; + + // This is really unnecessarily verbose; we should be using phis, + // even at -O0. + + // CHECK: define void @_ZN5test53fooEv() + // CHECK: [[ELEMS:%.*]] = alloca [5 x [[A:%.*]]], align + // CHECK-NEXT: [[IVAR:%.*]] = alloca i64 + // CHECK: [[ELEMSARRAY:%.*]] = bitcast [5 x [[A]]]* [[ELEMS]] to [[A]] + // CHECK-NEXT: store i64 5, i64* [[IVAR]] + // CHECK-NEXT: br label + // CHECK: [[I:%.*]] = load i64* [[IVAR]] + // CHECK-NEXT: icmp ne i64 [[I]], 0 + // CHECK-NEXT: br i1 + // CHECK: [[I:%.*]] = load i64* [[IVAR]] + // CHECK-NEXT: [[I2:%.*]] = sub i64 [[I]], 1 + // CHECK-NEXT: getelementptr inbounds [[A]]* [[ELEMSARRAY]], i64 [[I2]] + // CHECK-NEXT: call void @_ZN5test51AD1Ev( + // CHECK-NEXT: br label + // CHECK: [[I:%.*]] = load i64* [[IVAR]] + // CHECK-NEXT: [[I1:%.*]] = sub i64 [[I]], 1 + // CHECK-NEXT: store i64 [[I1]], i64* [[IVAR]] + // CHECK-NEXT: br label + // CHECK: ret void + void foo() { + A elems[5]; + } +} + +// Checks from test3: + // CHECK: define internal void @_ZN5test312_GLOBAL__N_11CD2Ev( // CHECK: call void @_ZN5test31BD2Ev( // CHECK: call void @_ZN5test31AD2Ev( // CHECK: ret void // CHECK: define internal void @_ZN5test312_GLOBAL__N_11DD0Ev( - // CHECK: call void @_ZN5test312_GLOBAL__N_11DD1Ev( - // CHECK: call void @_ZdlPv( + // CHECK: invoke void @_ZN5test312_GLOBAL__N_11DD1Ev( + // CHECK: call void @_ZdlPv({{.*}}) nounwind // CHECK: ret void + // CHECK: call i8* @llvm.eh.exception( + // CHECK: call void @_ZdlPv({{.*}}) nounwind + // CHECK: call void @_Unwind_Resume_or_Rethrow // Checked at top of file: // @_ZN5test312_GLOBAL__N_11DD1Ev = alias internal {{.*}} @_ZN5test312_GLOBAL__N_11DD2Ev @@ -196,9 +293,12 @@ namespace test3 { // CHECK: declare void @_ZN5test31AD2Ev( // CHECK: define internal void @_ZN5test312_GLOBAL__N_11CD0Ev( - // CHECK: call void @_ZN5test312_GLOBAL__N_11CD1Ev( - // CHECK: call void @_ZdlPv( + // CHECK: invoke void @_ZN5test312_GLOBAL__N_11CD1Ev( + // CHECK: call void @_ZdlPv({{.*}}) nounwind // CHECK: ret void + // CHECK: call i8* @llvm.eh.exception() + // CHECK: call void @_ZdlPv({{.*}}) nounwind + // CHECK: call void @_Unwind_Resume_or_Rethrow( // CHECK: define internal void @_ZThn8_N5test312_GLOBAL__N_11CD1Ev( // CHECK: getelementptr inbounds i8* {{.*}}, i64 -8 @@ -209,4 +309,3 @@ namespace test3 { // CHECK: getelementptr inbounds i8* {{.*}}, i64 -8 // CHECK: call void @_ZN5test312_GLOBAL__N_11CD0Ev( // CHECK: ret void -} diff --git a/test/CodeGenCXX/eh.cpp b/test/CodeGenCXX/eh.cpp index f2629d19d902..d03dc9171539 100644 --- a/test/CodeGenCXX/eh.cpp +++ b/test/CodeGenCXX/eh.cpp @@ -38,6 +38,7 @@ void test2() { // CHECK: define void @_Z5test2v() // CHECK: [[FREEVAR:%.*]] = alloca i1 // CHECK-NEXT: [[EXNOBJVAR:%.*]] = alloca i8* +// CHECK-NEXT: [[EXNSLOTVAR:%.*]] = alloca i8* // CHECK-NEXT: store i1 false, i1* [[FREEVAR]] // CHECK-NEXT: [[EXNOBJ:%.*]] = call i8* @__cxa_allocate_exception(i64 16) // CHECK-NEXT: store i8* [[EXNOBJ]], i8** [[EXNOBJVAR]] @@ -104,3 +105,118 @@ namespace test5 { // : [[HANDLER]]: (can't check this in Release-Asserts builds) // CHECK: {{%.*}} = call i32 @llvm.eh.typeid.for(i8* bitcast ({{%.*}}* @_ZTIN5test51AE to i8*)) } + +namespace test6 { + template <class T> struct allocator { + ~allocator() throw() { } + }; + + void foo() { + allocator<int> a; + } +} + +// PR7127 +namespace test7 { +// CHECK: define i32 @_ZN5test73fooEv() + int foo() { +// CHECK: [[FREEEXNOBJ:%.*]] = alloca i1 +// CHECK-NEXT: [[EXNALLOCVAR:%.*]] = alloca i8* +// CHECK-NEXT: [[CAUGHTEXNVAR:%.*]] = alloca i8* +// CHECK-NEXT: [[INTCATCHVAR:%.*]] = alloca i32 +// CHECK-NEXT: store i1 false, i1* [[FREEEXNOBJ]] + try { + try { +// CHECK-NEXT: [[EXNALLOC:%.*]] = call i8* @__cxa_allocate_exception +// CHECK-NEXT: store i8* [[EXNALLOC]], i8** [[EXNALLOCVAR]] +// CHECK-NEXT: store i1 true, i1* [[FREEEXNOBJ]] +// CHECK-NEXT: bitcast i8* [[EXNALLOC]] to i32* +// CHECK-NEXT: store i32 1, i32* +// CHECK-NEXT: store i1 false, i1* [[FREEEXNOBJ]] +// CHECK-NEXT: invoke void @__cxa_throw(i8* [[EXNALLOC]], i8* bitcast (i8** @_ZTIi to i8*), i8* null + throw 1; + } +// This cleanup ends up here for no good reason. It's actually unused. +// CHECK: load i8** [[EXNALLOCVAR]] +// CHECK-NEXT: call void @__cxa_free_exception( + +// CHECK: [[CAUGHTEXN:%.*]] = call i8* @llvm.eh.exception() +// CHECK-NEXT: store i8* [[CAUGHTEXN]], i8** [[CAUGHTEXNVAR]] +// CHECK-NEXT: call i32 (i8*, i8*, ...)* @llvm.eh.selector(i8* [[CAUGHTEXN]], i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*), i8* bitcast (i8** @_ZTIi to i8*), i8* null) +// CHECK-NEXT: call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTIi to i8*)) +// CHECK-NEXT: icmp eq +// CHECK-NEXT: br i1 +// CHECK: load i8** [[CAUGHTEXNVAR]] +// CHECK-NEXT: call i8* @__cxa_begin_catch +// CHECK: invoke void @__cxa_rethrow + catch (int) { + throw; + } + } +// CHECK: [[CAUGHTEXN:%.*]] = call i8* @llvm.eh.exception() +// CHECK-NEXT: store i8* [[CAUGHTEXN]], i8** [[CAUGHTEXNVAR]] +// CHECK-NEXT: call i32 (i8*, i8*, ...)* @llvm.eh.selector(i8* [[CAUGHTEXN]], i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*), i8* null) +// CHECK-NEXT: call void @__cxa_end_catch() +// CHECK-NEXT: br label +// CHECK: load i8** [[CAUGHTEXNVAR]] +// CHECK-NEXT: call i8* @__cxa_begin_catch +// CHECK-NEXT: call void @__cxa_end_catch + catch (...) { + } +// CHECK: ret i32 0 + return 0; + } +} + +// Ordering of destructors in a catch handler. +namespace test8 { + struct A { A(const A&); ~A(); }; + void bar(); + + // CHECK: define void @_ZN5test83fooEv() + void foo() { + try { + // CHECK: invoke void @_ZN5test83barEv() + bar(); + } catch (A a) { + // CHECK: call i8* @__cxa_get_exception_ptr + // CHECK-NEXT: bitcast + // CHECK-NEXT: invoke void @_ZN5test81AC1ERKS0_( + // CHECK: call i8* @__cxa_begin_catch + // CHECK-NEXT: invoke void @_ZN5test81AD1Ev( + + // CHECK: call void @__cxa_end_catch() + // CHECK-NEXT: load + // CHECK-NEXT: switch + + // CHECK: ret void + } + } +} + +// Constructor function-try-block must rethrow on fallthrough. +// rdar://problem/7696603 +namespace test9 { + void opaque(); + + struct A { A(); }; + + // CHECK: define void @_ZN5test91AC1Ev + // CHECK: call void @_ZN5test91AC2Ev + // CHECK-NEXT: ret void + + // CHECK: define void @_ZN5test91AC2Ev( + A::A() try { + // CHECK: invoke void @_ZN5test96opaqueEv() + opaque(); + } catch (int x) { + // CHECK: call i8* @__cxa_begin_catch + // CHECK: invoke void @_ZN5test96opaqueEv() + // CHECK: invoke void @__cxa_rethrow() + opaque(); + } + + // landing pad from first call to invoke + // CHECK: call i8* @llvm.eh.exception + // CHECK: call i32 (i8*, i8*, ...)* @llvm.eh.selector(i8* {{.*}}, i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*), i8* bitcast (i8** @_ZTIi to i8*), i8* null) +} diff --git a/test/CodeGenCXX/global-dtor-no-atexit.cpp b/test/CodeGenCXX/global-dtor-no-atexit.cpp index 81e219989800..1e125e3f7d81 100644 --- a/test/CodeGenCXX/global-dtor-no-atexit.cpp +++ b/test/CodeGenCXX/global-dtor-no-atexit.cpp @@ -1,5 +1,8 @@ // RUN: %clang_cc1 -triple x86_64 %s -fno-use-cxa-atexit -emit-llvm -o - | FileCheck %s +// PR7097 +// RUN: %clang_cc1 -triple x86_64 %s -fno-use-cxa-atexit -mconstructor-aliases -emit-llvm -o - | FileCheck %s + // CHECK: define internal void @_GLOBAL__D_a() // CHECK: call void @_ZN1AD1Ev(%class.A* @b) // CHECK: call void @_ZN1AD1Ev(%class.A* @a) diff --git a/test/CodeGenCXX/global-init-darwin.cpp b/test/CodeGenCXX/global-init-darwin.cpp new file mode 100644 index 000000000000..20c13c6eef77 --- /dev/null +++ b/test/CodeGenCXX/global-init-darwin.cpp @@ -0,0 +1,23 @@ +// RUN: %clang_cc1 -triple=x86_64-apple-darwin10 -emit-llvm %s -o - |FileCheck %s + +struct A { + A(); + ~A(); +}; + +A a; +A as[2]; + +struct B { + B(); + ~B(); + int f(); +}; + +int i = B().f(); + +// CHECK: "__TEXT,__StaticInit,regular,pure_instructions" { +// CHECK: "__TEXT,__StaticInit,regular,pure_instructions" { +// CHECK: "__TEXT,__StaticInit,regular,pure_instructions" { +// CHECK: "__TEXT,__StaticInit,regular,pure_instructions" { +// CHECK: "__TEXT,__StaticInit,regular,pure_instructions" { diff --git a/test/CodeGenCXX/global-init.cpp b/test/CodeGenCXX/global-init.cpp index 7cbd55940b43..8ee087e29d11 100644 --- a/test/CodeGenCXX/global-init.cpp +++ b/test/CodeGenCXX/global-init.cpp @@ -1,4 +1,5 @@ -// RUN: %clang_cc1 -triple=x86_64-apple-darwin10 -emit-llvm %s -o - |FileCheck %s +// RUN: %clang_cc1 -triple=x86_64-apple-darwin10 -emit-llvm -fexceptions %s -o - |FileCheck %s +// RUN: %clang_cc1 -triple=x86_64-apple-darwin10 -emit-llvm %s -o - |FileCheck -check-prefix NOEXC %s struct A { A(); @@ -28,4 +29,7 @@ C c; // CHECK: call i32 @__cxa_atexit(void (i8*)* bitcast (void (%struct.A*)* @_ZN1DD1Ev to void (i8*)*), i8* getelementptr inbounds (%struct.A* @d, i32 0, i32 0), i8* bitcast (i8** @__dso_handle to i8*)) D d; -// CHECK: define internal void @_GLOBAL__I_a() { +// CHECK: define internal void @_GLOBAL__I_a() section "__TEXT,__StaticInit,regular,pure_instructions" { + +// rdar://problem/8090834: this should be nounwind +// CHECK-NOEXC: define internal void @_GLOBAL__I_a() nounwind section "__TEXT,__StaticInit,regular,pure_instructions" { diff --git a/test/CodeGenCXX/incomplete-member-function-pointer.cpp b/test/CodeGenCXX/incomplete-member-function-pointer.cpp new file mode 100644 index 000000000000..b97e44c9172d --- /dev/null +++ b/test/CodeGenCXX/incomplete-member-function-pointer.cpp @@ -0,0 +1,10 @@ +// RUN: %clang_cc1 %s -emit-llvm-only +// PR7040 +struct fake_tuple; +struct connection { + void bar(fake_tuple); +}; +void (connection::*a)(fake_tuple) = &connection::bar; +void f() { + void (connection::*b)(fake_tuple) = &connection::bar; +} diff --git a/test/CodeGenCXX/instantiate-blocks.cpp b/test/CodeGenCXX/instantiate-blocks.cpp new file mode 100644 index 000000000000..c8f897de8200 --- /dev/null +++ b/test/CodeGenCXX/instantiate-blocks.cpp @@ -0,0 +1,33 @@ +// RUN: %clang_cc1 -fblocks -emit-llvm -o - %s +// rdar : // 6182276 + +template <typename T> T foo(T t) +{ + void (^block)(int); + return 1; +} + +int test1(void) +{ + int i = 1; + int b = 2; + i = foo(b); + return 0; +} + +template <typename T, typename T1> void foo(T t, T1 r) +{ + T block_arg; + __block T1 byref_block_arg; + + T1 (^block)(char, T, T1, double) = + ^ T1 (char ch, T arg, T1 arg2, double d1) { byref_block_arg = arg2; + return byref_block_arg + block_arg + arg; }; + + void (^block2)() = ^{}; +} + +void test2(void) +{ + foo(100, 'a'); +} diff --git a/test/CodeGenCXX/internal-linkage.cpp b/test/CodeGenCXX/internal-linkage.cpp index 4263891e57f5..9fdb7274e146 100644 --- a/test/CodeGenCXX/internal-linkage.cpp +++ b/test/CodeGenCXX/internal-linkage.cpp @@ -17,3 +17,40 @@ Anon anon1; // CHECK: @anon2 = internal global X<Anon> anon2; +// rdar: // 8071804 +char const * const xyzzy = "Hello, world!"; +extern char const * const xyzzy; + +char const * const *test1() +{ + // CHECK: @_ZL5xyzzy = internal constant + return &xyzzy; +} + +static char const * const static_xyzzy = "Hello, world!"; +extern char const * const static_xyzzy; + +char const * const *test2() +{ + // CHECK: @_ZL12static_xyzzy = internal constant + return &static_xyzzy; +} + +static char const * static_nonconst_xyzzy = "Hello, world!"; +extern char const * static_nonconst_xyzzy; + +char const * *test3() +{ + // CHECK: @_ZL21static_nonconst_xyzzy = internal global + return &static_nonconst_xyzzy; +} + + +char const * extern_nonconst_xyzzy = "Hello, world!"; +extern char const * extern_nonconst_xyzzy; + +char const * *test4() +{ + // CHECK: @extern_nonconst_xyzzy = global + return &extern_nonconst_xyzzy; +} diff --git a/test/CodeGenCXX/mangle-address-space.cpp b/test/CodeGenCXX/mangle-address-space.cpp new file mode 100644 index 000000000000..fbbcbfa35b58 --- /dev/null +++ b/test/CodeGenCXX/mangle-address-space.cpp @@ -0,0 +1,6 @@ +// RUN: %clang_cc1 -emit-llvm -o - %s | FileCheck %s + +// CHECK: define void @_Z2f0Pc +void f0(char *p) { } +// CHECK: define void @_Z2f0PU3AS1c +void f0(char __attribute__((address_space(1))) *p) { } diff --git a/test/CodeGenCXX/mangle-exprs.cpp b/test/CodeGenCXX/mangle-exprs.cpp index 6f1ca5568ed6..d68425f5a578 100644 --- a/test/CodeGenCXX/mangle-exprs.cpp +++ b/test/CodeGenCXX/mangle-exprs.cpp @@ -39,6 +39,6 @@ namespace Casts { // CHECK: define weak_odr void @_ZN5Casts7static_ILj4EEEvPN9enable_ifIXleT_cvjLi4EEvE4typeE template void static_<4>(void*); - // CHECK: define weak_odr i64 @_ZN5Casts1fILi6EEENS_1TIXT_EEEv + // CHECK: define weak_odr i8 @_ZN5Casts1fILi6EEENS_1TIXT_EEEv template T<6> f<6>(); } diff --git a/test/CodeGenCXX/mangle-ms.cpp b/test/CodeGenCXX/mangle-ms.cpp new file mode 100644 index 000000000000..61f8a595fc4f --- /dev/null +++ b/test/CodeGenCXX/mangle-ms.cpp @@ -0,0 +1,96 @@ +// RUN: %clang_cc1 -fms-extensions -fblocks -emit-llvm %s -o - -cxx-abi microsoft -triple=i386-apple-darwin10 | FileCheck %s + +// CHECK: @"\01?a@@3HA" +// CHECK: @"\01?b@N@@3HA" +// CHECK: @c +// CHECK: @"\01?d@foo@@0FB" +// CHECK: @"\01?e@foo@@1JC" +// CHECK: @"\01?f@foo@@2DD" +// CHECK: @"\01?g@bar@@2HA" +// CHECK: @"\01?h@@3QAHA" +// CHECK: @"\01?i@@3PAY0BE@HA" +// CHECK: @"\01?j@@3P6GHCE@ZA" +// CHECK: @"\01?k@@3PTfoo@@DA" +// CHECK: @"\01?l@@3P8foo@@AAHH@ZA" + +int a; + +namespace N { int b; } + +static int c; +int _c(void) {return c;} +// CHECK: @"\01?_c@@YAHXZ" + +class foo { + static const short d; +protected: + static volatile long e; +public: + static const volatile char f; + int operator+(int a); +}; + +struct bar { + static int g; +}; + +union baz { + int a; + char b; + double c; +}; + +enum quux { + qone, + qtwo, + qthree +}; + +// NOTE: The calling convention is supposed to be __thiscall by default, +// but that needs to be fixed in Sema/AST. +int foo::operator+(int a) {return a;} +// CHECK: @"\01??Hfoo@@QAAHH@Z" + +const short foo::d = 0; +volatile long foo::e; +const volatile char foo::f = 'C'; + +int bar::g; + +extern int * const h = &a; + +int i[10][20]; + +int (__stdcall *j)(signed char, unsigned char); + +const volatile char foo::*k; + +int (foo::*l)(int); + +// Static functions are mangled, too. +// Also make sure calling conventions, arglists, and throw specs work. +static void __stdcall alpha(float a, double b) throw() {} +bool __fastcall beta(long long a, wchar_t b) throw(signed char, unsigned char) { +// CHECK: @"\01?beta@@YI_N_J_W@Z" + alpha(0.f, 0.0); + return false; +} + +// CHECK: @"\01?alpha@@YGXMN@Z" + +// Make sure tag-type mangling works. +void gamma(class foo, struct bar, union baz, enum quux) {} +// CHECK: @"\01?gamma@@YAXVfoo@@Ubar@@Tbaz@@W4quux@@@Z" + +// Make sure pointer/reference-type mangling works. +void delta(int * const a, const long &) {} +// CHECK: @"\01?delta@@YAXQAHABJ@Z" + +// Array mangling. +void epsilon(int a[][10][20]) {} +// CHECK: @"\01?epsilon@@YAXQAY19BE@H@Z" + +// Blocks mangling (Clang extension). +void zeta(int (^)(int, int)) {} +// CHECK: @"\01?zeta@@YAXP_EAHHH@Z@Z" + diff --git a/test/CodeGenCXX/mangle-subst-std.cpp b/test/CodeGenCXX/mangle-subst-std.cpp index 4c15eaac8835..9c1e978294c8 100644 --- a/test/CodeGenCXX/mangle-subst-std.cpp +++ b/test/CodeGenCXX/mangle-subst-std.cpp @@ -99,3 +99,13 @@ void f(not_string) { } void create_streams() { std::basic_iostream<char> bio(17); } + +// Make sure we don't mangle 'std' as 'St' here. +namespace N { + namespace std { + struct A { void f(); }; + + // CHECK: define void @_ZN1N3std1A1fEv + void A::f() { } + } +} diff --git a/test/CodeGenCXX/mangle-subst.cpp b/test/CodeGenCXX/mangle-subst.cpp index bd06869ff7f9..d83a081dd76a 100644 --- a/test/CodeGenCXX/mangle-subst.cpp +++ b/test/CodeGenCXX/mangle-subst.cpp @@ -67,3 +67,16 @@ namespace NS { // CHECK: @_ZN2NS1fERNS_1CE void f(C&) { } } + +namespace Test1 { + +struct A { }; +struct B { }; + +// CHECK: @_ZN5Test11fEMNS_1BEFvvENS_1AES3_ +void f(void (B::*)(), A, A) { } + +// CHECK: @_ZN5Test11fEMNS_1BEFvvENS_1AES3_MS0_FvS3_EMS3_FvvE +void f(void (B::*)(), A, A, void (B::*)(A), void (A::*)()) { } + +} diff --git a/test/CodeGenCXX/mangle-unnamed.cpp b/test/CodeGenCXX/mangle-unnamed.cpp index 4aec7dbf4a76..83b46d69454e 100644 --- a/test/CodeGenCXX/mangle-unnamed.cpp +++ b/test/CodeGenCXX/mangle-unnamed.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -emit-llvm-only -verify %s +// RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-apple-darwin10 | FileCheck %s struct S { virtual ~S() { } @@ -37,3 +37,35 @@ struct A { }; int f4() { return A().a(); } + +int f5() { + static union { + int a; + }; + + // CHECK: _ZZ2f5vE1a + return a; +} + +int f6() { + static union { + union { + int : 1; + }; + int b; + }; + + // CHECK: _ZZ2f6vE1b + return b; +} + +int f7() { + static union { + union { + int b; + } a; + }; + + // CHECK: _ZZ2f7vE1a + return a.b; +} diff --git a/test/CodeGenCXX/mangle.cpp b/test/CodeGenCXX/mangle.cpp index 8f3d35684884..54a4060352e0 100644 --- a/test/CodeGenCXX/mangle.cpp +++ b/test/CodeGenCXX/mangle.cpp @@ -477,3 +477,22 @@ namespace test10 { // CHECK: define weak_odr void @_ZN6test101fILc3EEEvNS_1SIXquLb0ELc97ET_EEE( template void f<(char) 3>(struct S<3>); } + +namespace test11 { + // CHECK: @_ZN6test111fEz + void f(...) { } + + struct A { + void f(...); + }; + + // CHECK: @_ZN6test111A1fEz + void A::f(...) { } +} + +namespace test12 { + + // CHECK: _ZN6test121fENS_1AILt33000EEE + template <unsigned short> struct A { }; + void f(A<33000>) { } +}
\ No newline at end of file diff --git a/test/CodeGenCXX/member-functions.cpp b/test/CodeGenCXX/member-functions.cpp index 087e62c5bb37..b363552a4806 100644 --- a/test/CodeGenCXX/member-functions.cpp +++ b/test/CodeGenCXX/member-functions.cpp @@ -58,6 +58,6 @@ struct T { void test3() { T t1, t2; - // RUN: grep "call i64 @_ZN1TplERKS_" %t + // RUN: grep "call i8 @_ZN1TplERKS_" %t T result = t1 + t2; } diff --git a/test/CodeGenCXX/member-init-assignment.cpp b/test/CodeGenCXX/member-init-assignment.cpp new file mode 100644 index 000000000000..57ab7ebd1f2f --- /dev/null +++ b/test/CodeGenCXX/member-init-assignment.cpp @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 %s -emit-llvm -o - | FileCheck %s +// PR7291 + +struct Foo { + unsigned file_id; + + Foo(unsigned arg); +}; + +Foo::Foo(unsigned arg) : file_id(arg = 42) +{ } + +// CHECK: define void @_ZN3FooC2Ej +// CHECK: [[ARG:%.*]] = alloca i32 +// CHECK: store i32 42, i32* [[ARG]] +// CHECK: store i32 42, i32* %{{.*}} +// CHECK: ret void diff --git a/test/CodeGenCXX/nrvo.cpp b/test/CodeGenCXX/nrvo.cpp index 9ee553673f18..6181f0eee131 100644 --- a/test/CodeGenCXX/nrvo.cpp +++ b/test/CodeGenCXX/nrvo.cpp @@ -1,5 +1,5 @@ // RUN: %clang_cc1 -emit-llvm -O1 -o - %s | FileCheck %s -// RUN: %clang_cc1 -emit-llvm -fexceptions -o - %s | FileCheck --check-prefix=CHECK-EH %s +// RUN: %clang_cc1 -emit-llvm -O1 -fexceptions -o - %s | FileCheck --check-prefix=CHECK-EH %s // Test code generation for the named return value optimization. class X { @@ -13,48 +13,97 @@ public: // CHECK-EH: define void @_Z5test0v X test0() { X x; - // CHECK-NOT: call void @_ZN1XD1Ev - // CHECK: ret void - // CHECK-EH: br label - // CHECK-EH: call void @_ZN1XD1Ev - // CHECK-EH: br label - // CHECK-EH: invoke void @_ZN1XD1Ev - // CHECK-EH: ret void + // CHECK: call void @_ZN1XC1Ev + // CHECK-NEXT: ret void + + // CHECK-EH: call void @_ZN1XC1Ev + // CHECK-EH-NEXT: ret void return x; } // CHECK: define void @_Z5test1b( +// CHECK-EH: define void @_Z5test1b( X test1(bool B) { - // CHECK: call void @_ZN1XC1Ev + // CHECK: tail call void @_ZN1XC1Ev + // CHECK-NEXT: ret void X x; - // CHECK-NOT: call void @_ZN1XD1Ev - // CHECK: ret void if (B) return (x); return x; - // CHECK-EH: invoke void @_ZN1XD1Ev + // CHECK-EH: tail call void @_ZN1XC1Ev + // CHECK-EH-NEXT: ret void } // CHECK: define void @_Z5test2b // CHECK-EH: define void @_Z5test2b X test2(bool B) { - // No NRVO - // CHECK: call void @_ZN1XC1Ev + // No NRVO. + X x; - // CHECK: call void @_ZN1XC1Ev X y; - // CHECK: call void @_ZN1XC1ERKS_ - // CHECK-EH: invoke void @_ZN1XC1ERKS_ if (B) return y; - // CHECK: call void @_ZN1XC1ERKS_ - // CHECK-EH: invoke void @_ZN1XC1ERKS_ return x; + + // CHECK: call void @_ZN1XC1Ev + // CHECK-NEXT: call void @_ZN1XC1Ev + // CHECK: call void @_ZN1XC1ERKS_ + // CHECK: call void @_ZN1XC1ERKS_ // CHECK: call void @_ZN1XD1Ev // CHECK: call void @_ZN1XD1Ev // CHECK: ret void + + // The block ordering in the -fexceptions IR is unfortunate. + + // CHECK-EH: call void @_ZN1XC1Ev + // CHECK-EH-NEXT: invoke void @_ZN1XC1Ev + // -> %invoke.cont1, %lpad + + // %invoke.cont1: + // CHECK-EH: br i1 + // -> %if.then, %if.end + + // %if.then: returning 'x' + // CHECK-EH: invoke void @_ZN1XC1ERKS_ + // -> %cleanup, %lpad5 + + // %invoke.cont: rethrow block for %eh.cleanup. + // This really should be elsewhere in the function. + // CHECK-EH: call void @_Unwind_Resume_or_Rethrow + // CHECK-EH-NEXT: unreachable + + // %lpad: landing pad for ctor of 'y', dtor of 'y' + // CHECK-EH: call i8* @llvm.eh.exception() + // CHECK-EH: call i32 (i8*, i8*, ...)* @llvm.eh.selector + // CHECK-EH-NEXT: br label + // -> %eh.cleanup + + // %invoke.cont2: normal cleanup for 'x' + // CHECK-EH: call void @_ZN1XD1Ev + // CHECK-EH-NEXT: ret void + + // %lpad5: landing pad for return copy ctors, EH cleanup for 'y' + // CHECK-EH: invoke void @_ZN1XD1Ev + // -> %eh.cleanup, %terminate.lpad + + // %if.end: returning 'y' + // CHECK-EH: invoke void @_ZN1XC1ERKS_ + // -> %cleanup, %lpad5 + + // %cleanup: normal cleanup for 'y' // CHECK-EH: invoke void @_ZN1XD1Ev + // -> %invoke.cont2, %lpad + + // %eh.cleanup: EH cleanup for 'x' // CHECK-EH: invoke void @_ZN1XD1Ev + // -> %invoke.cont, %terminate.lpad + + // %terminate.lpad: terminate landing pad. + // CHECK-EH: call i8* @llvm.eh.exception() + // CHECK-EH-NEXT: call i32 (i8*, i8*, ...)* @llvm.eh.selector + // CHECK-EH-NEXT: call void @_ZSt9terminatev() + // CHECK-EH-NEXT: unreachable + } X test3(bool B) { diff --git a/test/CodeGenCXX/pointers-to-data-members.cpp b/test/CodeGenCXX/pointers-to-data-members.cpp index affe1f7d18de..70308c6abc5f 100644 --- a/test/CodeGenCXX/pointers-to-data-members.cpp +++ b/test/CodeGenCXX/pointers-to-data-members.cpp @@ -68,11 +68,11 @@ void f() { // CHECK: store i64 -1, i64* @_ZN5Casts2paE pa = 0; - // CHECK: [[ADJ:%[a-zA-Z0-9\.]+]] = add i64 {{.*}}, 4 + // CHECK: [[ADJ:%[a-zA-Z0-9\.]+]] = add nsw i64 {{.*}}, 4 // CHECK: store i64 [[ADJ]], i64* @_ZN5Casts2pcE pc = pa; - // CHECK: [[ADJ:%[a-zA-Z0-9\.]+]] = sub i64 {{.*}}, 4 + // CHECK: [[ADJ:%[a-zA-Z0-9\.]+]] = sub nsw i64 {{.*}}, 4 // CHECK: store i64 [[ADJ]], i64* @_ZN5Casts2paE pa = static_cast<int A::*>(pc); } @@ -151,3 +151,35 @@ bool check2() { } } + +namespace VirtualBases { + +struct A { + char c; + int A::*i; +}; + +// FIXME: A::i should be initialized to -1 here. +struct B : virtual A { }; +B b; + +// FIXME: A::i should be initialized to -1 here. +struct C : virtual A { int A::*i; }; +C c; + +// FIXME: C::A::i should be initialized to -1 here. +struct D : C { int A::*i; }; +D d; + +} + +namespace Test1 { + +// Don't crash when A contains a bit-field. +struct A { + int A::* a; + int b : 10; +}; +A a; + +} diff --git a/test/CodeGenCXX/reference-in-block-args.cpp b/test/CodeGenCXX/reference-in-block-args.cpp new file mode 100644 index 000000000000..1ff1ae2dc856 --- /dev/null +++ b/test/CodeGenCXX/reference-in-block-args.cpp @@ -0,0 +1,29 @@ +// RUN: %clang_cc1 -fblocks %s -emit-llvm -o %t +// rdar: // 8041962 + +extern "C" int printf(const char*, ...); + +struct ST { + int filler; + int referrer; +}; + +void OUTER_BLOCK(void (^fixer)(ST& ref)) { + ST ref = {2, 100}; + fixer(ref); +} + +void INNER_BLOCK(int (^largeDo) ()) { + printf("%d\n", largeDo()); +} + +void scan() { + OUTER_BLOCK(^(ST &ref) { + INNER_BLOCK(^() { return ref.referrer + ref.filler; }); + }); + +} + +int main() { + scan(); +} diff --git a/test/CodeGenCXX/references.cpp b/test/CodeGenCXX/references.cpp index 6fc610298bd2..d2ad98013553 100644 --- a/test/CodeGenCXX/references.cpp +++ b/test/CodeGenCXX/references.cpp @@ -150,10 +150,9 @@ void f0(s1 a) { s1 b = a; } // PR6024 // CHECK: @_Z2f2v() -// CHECK: alloca -// CHECK: store -// CHECK: load -// CHECK: ret +// CHECK: alloca i32, +// CHECK-NEXT: store +// CHECK-NEXT: ret const int &f2() { return 0; } // Don't constant fold const reference parameters with default arguments to @@ -161,7 +160,7 @@ const int &f2() { return 0; } namespace N1 { const int foo = 1; // CHECK: @_ZN2N14test - int test(const int& arg = foo) { + void test(const int& arg = foo) { // Ensure this array is on the stack where we can set values instead of // being a global constant. // CHECK: %args_array = alloca @@ -225,3 +224,37 @@ namespace N2 { i = 19; } } + +namespace N3 { + +// PR7326 + +struct A { + explicit A(int); + ~A(); +}; + +// CHECK: define internal void @__cxx_global_var_init +// CHECK: call void @_ZN2N31AC1Ei(%"class.N2::X"* @_ZGRN2N35sA123E, i32 123) +// CHECK: call i32 @__cxa_atexit +// CHECK: ret void +const A &sA123 = A(123); +} + +namespace N4 { + +struct A { + A(); + ~A(); +}; + +void f() { + // CHECK: define void @_ZN2N41fEv + // CHECK: call void @_ZN2N41AC1Ev(%"class.N2::X"* @_ZGRZN2N41fEvE2ar) + // CHECK: call i32 @__cxa_atexit + // CHECK: ret void + static const A& ar = A(); + +} +} + diff --git a/test/CodeGenCXX/rtti-layout.cpp b/test/CodeGenCXX/rtti-layout.cpp index 1ad87fbc7ef7..7128c4e4d07b 100644 --- a/test/CodeGenCXX/rtti-layout.cpp +++ b/test/CodeGenCXX/rtti-layout.cpp @@ -93,6 +93,14 @@ struct VMI7 : VMIBase1, VMI5, private VMI6 { }; #define CHECK_BASE_INFO_TYPE(type, index, base) CHECK(to<__vmi_class_type_info>(typeid(type)).__base_info[(index)].__base_type == &typeid(base)) #define CHECK_BASE_INFO_OFFSET_FLAGS(type, index, offset, flags) CHECK(to<__vmi_class_type_info>(typeid(type)).__base_info[(index)].__offset_flags == (((offset) << 8) | (flags))) +struct B { + static int const volatile (*a)[10]; + static int (*b)[10]; + + static int const volatile (B::*c)[10]; + static int (B::*d)[10]; +}; + // CHECK: define i32 @_Z1fv() int f() { // Vectors should be treated as fundamental types. @@ -168,6 +176,12 @@ int f() { CHECK(to<__pbase_type_info>(typeid(Incomplete Incomplete::*)).__flags == (__pbase_type_info::__incomplete_class_mask | __pbase_type_info::__incomplete_mask)); CHECK(to<__pbase_type_info>(typeid(Incomplete A::*)).__flags == (__pbase_type_info::__incomplete_mask)); + // Check that when stripping qualifiers off the pointee type, we correctly handle arrays. + CHECK(to<__pbase_type_info>(typeid(B::a)).__flags == (__pbase_type_info::__const_mask | __pbase_type_info::__volatile_mask)); + CHECK(to<__pbase_type_info>(typeid(B::a)).__pointee == to<__pbase_type_info>(typeid(B::b)).__pointee); + CHECK(to<__pbase_type_info>(typeid(B::c)).__flags == (__pbase_type_info::__const_mask | __pbase_type_info::__volatile_mask)); + CHECK(to<__pbase_type_info>(typeid(B::c)).__pointee == to<__pbase_type_info>(typeid(B::d)).__pointee); + // Success! // CHECK: ret i32 0 return 0; diff --git a/test/CodeGenCXX/rtti-linkage.cpp b/test/CodeGenCXX/rtti-linkage.cpp index 9d85a2c69ba0..f8c1167b53db 100644 --- a/test/CodeGenCXX/rtti-linkage.cpp +++ b/test/CodeGenCXX/rtti-linkage.cpp @@ -14,6 +14,7 @@ // CHECK: _ZTI1A = weak_odr constant // CHECK: _ZTI1B = constant // CHECK: _ZTI1C = internal constant +// CHECK: _ZTIA10_i = weak_odr constant // CHECK: _ZTIFN12_GLOBAL__N_11DEvE = internal constant // CHECK: _ZTIFvN12_GLOBAL__N_11DEE = internal constant // CHECK: _ZTIFvvE = weak_odr @@ -33,6 +34,7 @@ // CHECK: _ZTS1B = constant // CHECK: _ZTS1C = internal constant // CHECK: _ZTS1F = weak_odr constant +// CHECK: _ZTSA10_i = weak_odr constant // CHECK: _ZTSFN12_GLOBAL__N_11DEvE = internal constant // CHECK: _ZTSFvN12_GLOBAL__N_11DEE = internal constant // CHECK: _ZTSFvvE = weak_odr constant @@ -107,3 +109,12 @@ const std::type_info &t2() { return typeid(getD()); } + +namespace Arrays { + struct A { + static const int a[10]; + }; + const std::type_info &f() { + return typeid(A::a); + } +} diff --git a/test/CodeGenCXX/sel-address.mm b/test/CodeGenCXX/sel-address.mm new file mode 100644 index 000000000000..c3db9a7d00e5 --- /dev/null +++ b/test/CodeGenCXX/sel-address.mm @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 %s -verify -emit-llvm -o %t +// pr7390 + +void f(const SEL& v2) {} +void g() { + f(@selector(dealloc)); + + SEL s = @selector(dealloc); + SEL* ps = &s; + + @selector(dealloc) = s; // expected-error {{expression is not assignable}} + + SEL* ps2 = &@selector(dealloc); +} diff --git a/test/CodeGenCXX/static-init.cpp b/test/CodeGenCXX/static-init.cpp index 9ad87df8f0c3..09b398a530a1 100644 --- a/test/CodeGenCXX/static-init.cpp +++ b/test/CodeGenCXX/static-init.cpp @@ -2,7 +2,7 @@ // CHECK: @_ZZ1hvE1i = internal global i32 0, align 4 -// CHECK: @_ZZN5test16getvarEiE3var = internal constant [4 x i32] [i32 1, i32 0, i32 2, i32 4], align 4 +// CHECK: @_ZZN5test16getvarEiE3var = internal constant [4 x i32] [i32 1, i32 0, i32 2, i32 4], align 16 // CHECK: @_ZZ2h2vE1i = linkonce_odr global i32 0 // CHECK: @_ZGVZ2h2vE1i = linkonce_odr global i64 0 diff --git a/test/CodeGenCXX/template-instantiation.cpp b/test/CodeGenCXX/template-instantiation.cpp index 4a3857542d06..cb6c81231641 100644 --- a/test/CodeGenCXX/template-instantiation.cpp +++ b/test/CodeGenCXX/template-instantiation.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 %s -O1 -triple=x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s // CHECK-NOT: @_ZTVN5test118stdio_sync_filebufIwEE = constant // CHECK-NOT: _ZTVN5test315basic_fstreamXXIcEE diff --git a/test/CodeGenCXX/template-static-var-defer.cpp b/test/CodeGenCXX/template-static-var-defer.cpp new file mode 100644 index 000000000000..fe18c21a2927 --- /dev/null +++ b/test/CodeGenCXX/template-static-var-defer.cpp @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -emit-llvm -o - | not grep define +// PR7415 +class X { + template <class Dummy> struct COMTypeInfo { + static const int kIID; + }; + static const int& GetIID() {return COMTypeInfo<int>::kIID;} +}; +template <class Dummy> const int X::COMTypeInfo<Dummy>::kIID = 10; + + + diff --git a/test/CodeGenCXX/temporaries.cpp b/test/CodeGenCXX/temporaries.cpp index eb543cb54552..9a397abfc0cf 100644 --- a/test/CodeGenCXX/temporaries.cpp +++ b/test/CodeGenCXX/temporaries.cpp @@ -320,3 +320,21 @@ namespace UserConvertToValue { f(1); } } + +namespace PR7556 { + struct A { ~A(); }; + struct B { int i; ~B(); }; + struct C { int C::*pm; ~C(); }; + // CHECK: define void @_ZN6PR75563fooEv() + void foo() { + // CHECK: call void @_ZN6PR75561AD1Ev + A(); + // CHECK: call void @llvm.memset.p0i8.i64 + // CHECK: call void @_ZN6PR75561BD1Ev + B(); + // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64 + // CHECK: call void @_ZN6PR75561CD1Ev + C(); + // CHECK-NEXT: ret void + } +} diff --git a/test/CodeGenCXX/threadsafe-statics-exceptions.cpp b/test/CodeGenCXX/threadsafe-statics-exceptions.cpp index 9347cc9616a1..17c10301d4fa 100644 --- a/test/CodeGenCXX/threadsafe-statics-exceptions.cpp +++ b/test/CodeGenCXX/threadsafe-statics-exceptions.cpp @@ -12,15 +12,18 @@ void f() { // CHECK: call i32 @__cxa_guard_acquire(i64* @_ZGVZ1fvE1x) // CHECK: invoke void @_ZN1XC1Ev // CHECK: call void @__cxa_guard_release(i64* @_ZGVZ1fvE1x) - // CHECK: call i32 @__cxa_atexit + // CHECK-NEXT: call i32 @__cxa_atexit // CHECK: br static X x; + + // CHECK: call i8* @__cxa_allocate_exception + // CHECK: invoke void @__cxa_throw + throw Y(); + + // Finally, the landing pad. // CHECK: call i8* @llvm.eh.exception() // CHECK: call i32 (i8*, i8*, ...)* @llvm.eh.selector // CHECK: call void @__cxa_guard_abort(i64* @_ZGVZ1fvE1x) // CHECK: call void @_Unwind_Resume_or_Rethrow // CHECK: unreachable - - // CHECK: call i8* @__cxa_allocate_exception - throw Y(); } diff --git a/test/CodeGenCXX/throw-expression-dtor.cpp b/test/CodeGenCXX/throw-expression-dtor.cpp new file mode 100644 index 000000000000..f87657fdcc01 --- /dev/null +++ b/test/CodeGenCXX/throw-expression-dtor.cpp @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 %s -emit-llvm-only -verify -fexceptions +// PR7281 + +class A { +public: + ~A(); +}; +class B : public A { + void ice_throw(); +}; +void B::ice_throw() { + throw *this; +} diff --git a/test/CodeGenCXX/thunks.cpp b/test/CodeGenCXX/thunks.cpp index 79ca709f470d..1de576128a11 100644 --- a/test/CodeGenCXX/thunks.cpp +++ b/test/CodeGenCXX/thunks.cpp @@ -234,6 +234,18 @@ namespace Test8 { void C::bar(NonPOD var) {} } +// PR7241: Emitting thunks for a method shouldn't require the vtable for +// that class to be emitted. +namespace Test9 { + struct A { virtual ~A() { } }; + struct B : A { virtual void test() const {} }; + struct C : B { C(); ~C(); }; + struct D : C { D() {} }; + void test() { + D d; + } +} + /**** The following has to go at the end of the file ****/ // This is from Test5: diff --git a/test/CodeGenCXX/virtual-base-destructor-call.cpp b/test/CodeGenCXX/virtual-base-destructor-call.cpp index 22c49a089d0d..4618a03b9d3f 100644 --- a/test/CodeGenCXX/virtual-base-destructor-call.cpp +++ b/test/CodeGenCXX/virtual-base-destructor-call.cpp @@ -27,6 +27,11 @@ int main() { // CHECK: call void @_ZN13basic_istreamIcED2Ev // CHECK: } +// basic_istream's base dtor is a no-op. +// CHECK: define linkonce_odr void @_ZN13basic_istreamIcED2Ev +// CHECK-NOT: call +// CHECK: } + // basic_iostream's deleting dtor calls its complete dtor, then // operator delete(). // CHECK: define linkonce_odr void @_ZN14basic_iostreamIcED0Ev @@ -44,9 +49,3 @@ int main() { // CHECK: define linkonce_odr void @_ZN13basic_istreamIcED0Ev // CHECK: call void @_ZN13basic_istreamIcED1Ev // CHECK: call void @_ZdlPv - -// basic_istream's base dtor is a no-op. -// CHECK: define linkonce_odr void @_ZN13basic_istreamIcED2Ev -// CHECK-NOT: call -// CHECK: } - diff --git a/test/CodeGenCXX/virtual-functions-incomplete-types.cpp b/test/CodeGenCXX/virtual-functions-incomplete-types.cpp index 991c2bc7220f..052a0192d665 100644 --- a/test/CodeGenCXX/virtual-functions-incomplete-types.cpp +++ b/test/CodeGenCXX/virtual-functions-incomplete-types.cpp @@ -9,7 +9,7 @@ struct B { void B::f() { } -// CHECK: define i64 @_ZN1D1gEv(%struct.B* %this) +// CHECK: define i32 @_ZN1D1gEv(%struct.B* %this) // CHECK: declare void @_ZN1B1gEv() struct C; diff --git a/test/CodeGenCXX/visibility-hidden-extern-templates.cpp b/test/CodeGenCXX/visibility-hidden-extern-templates.cpp new file mode 100644 index 000000000000..7629b77c2cee --- /dev/null +++ b/test/CodeGenCXX/visibility-hidden-extern-templates.cpp @@ -0,0 +1,26 @@ +// RUN: %clang_cc1 -O1 -emit-llvm -o - -fvisibility hidden %s | FileCheck %s + +template<typename T> +struct X { + void f(); + void g() { } +}; + +template<typename T> void X<T>::f() { } + +extern template struct X<int>; +template struct X<int>; +extern template struct X<char>; + +// <rdar://problem/8109763> +void test_X(X<int> xi, X<char> xc) { + // CHECK: define weak_odr hidden void @_ZN1XIiE1fEv + xi.f(); + // CHECK: define weak_odr hidden void @_ZN1XIiE1gEv + xi.g(); + // CHECK: declare void @_ZN1XIcE1fEv + xc.f(); + // CHECK: define available_externally void @_ZN1XIcE1gEv + xc.g(); +} + diff --git a/test/CodeGenCXX/visibility-inlines-hidden.cpp b/test/CodeGenCXX/visibility-inlines-hidden.cpp new file mode 100644 index 000000000000..bb1574fe9d5f --- /dev/null +++ b/test/CodeGenCXX/visibility-inlines-hidden.cpp @@ -0,0 +1,57 @@ +// RUN: %clang_cc1 -fvisibility-inlines-hidden -emit-llvm -o - %s | FileCheck %s +struct X0 { + void __attribute__((visibility("default"))) f1() { } + void f2() { } + void f3(); + static void f5() { } + virtual void f6() { } +}; + +inline void X0::f3() { } + +template<typename T> +struct X1 { + void __attribute__((visibility("default"))) f1() { } + void f2() { } + void f3(); + void f4(); + static void f5() { } + virtual void f6() { } +}; + +template<typename T> +inline void X1<T>::f3() { } + +template<> +inline void X1<int>::f4() { } + +struct __attribute__((visibility("default"))) X2 { + void f2() { } +}; + +void use(X0 *x0, X1<int> *x1, X2 *x2) { + // CHECK: define linkonce_odr void @_ZN2X02f1Ev + x0->f1(); + // CHECK: define linkonce_odr hidden void @_ZN2X02f2Ev + x0->f2(); + // CHECK: define linkonce_odr hidden void @_ZN2X02f3Ev + x0->f3(); + // CHECK: define linkonce_odr hidden void @_ZN2X02f5Ev + X0::f5(); + // CHECK: define linkonce_odr hidden void @_ZN2X02f6Ev + x0->X0::f6(); + // CHECK: define linkonce_odr void @_ZN2X1IiE2f1Ev + x1->f1(); + // CHECK: define linkonce_odr hidden void @_ZN2X1IiE2f2Ev + x1->f2(); + // CHECK: define linkonce_odr hidden void @_ZN2X1IiE2f3Ev + x1->f3(); + // CHECK: define linkonce_odr hidden void @_ZN2X1IiE2f4Ev + x1->f4(); + // CHECK: define linkonce_odr hidden void @_ZN2X1IiE2f5Ev + X1<int>::f5(); + // CHECK: define linkonce_odr hidden void @_ZN2X1IiE2f6Ev + x1->X1::f6(); + // CHECK: define linkonce_odr hidden void @_ZN2X22f2Ev + x2->f2(); +} diff --git a/test/CodeGenCXX/visibility.cpp b/test/CodeGenCXX/visibility.cpp index 5edd27b8b279..ee3c1795fbb7 100644 --- a/test/CodeGenCXX/visibility.cpp +++ b/test/CodeGenCXX/visibility.cpp @@ -5,7 +5,7 @@ #define DEFAULT __attribute__((visibility("default"))) // CHECK: @_ZN5Test425VariableInHiddenNamespaceE = hidden global i32 10 - +// CHECK: @_ZTVN5Test63fooE = weak_odr hidden constant namespace Test1 { // CHECK: define hidden void @_ZN5Test11fEv void HIDDEN f() { } @@ -64,3 +64,21 @@ namespace Test5 { void g() { } } } + +// <rdar://problem/8091955> +namespace Test6 { + struct HIDDEN foo { + foo() { } + void bonk(); + virtual void bar() = 0; + + virtual void zonk() {} + }; + + struct barc : public foo { + barc(); + virtual void bar(); + }; + + barc::barc() {} +} diff --git a/test/CodeGenCXX/x86_64-arguments.cpp b/test/CodeGenCXX/x86_64-arguments.cpp index 4bc83b85134e..df0c78ad941e 100644 --- a/test/CodeGenCXX/x86_64-arguments.cpp +++ b/test/CodeGenCXX/x86_64-arguments.cpp @@ -1,24 +1,21 @@ // RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm -o - %s | FileCheck %s -// CHECK: [[i64_i64_ty:%.*]] = type { i64, i64 } -// CHECK: [[i64_double_ty:%.*]] = type { i64, double } - // Basic base class test. struct f0_s0 { unsigned a; }; struct f0_s1 : public f0_s0 { void *b; }; -// CHECK: define void @_Z2f05f0_s1([[i64_i64_ty]]) +// CHECK: define void @_Z2f05f0_s1(i64 %a0.coerce0, i8* %a0.coerce1) void f0(f0_s1 a0) { } // Check with two eight-bytes in base class. struct f1_s0 { unsigned a; unsigned b; float c; }; struct f1_s1 : public f1_s0 { float d;}; -// CHECK: define void @_Z2f15f1_s1([[i64_double_ty]]) +// CHECK: define void @_Z2f15f1_s1(i64 %a0.coerce0, double %a0.coerce1) void f1(f1_s1 a0) { } // Check with two eight-bytes in base class and merge. struct f2_s0 { unsigned a; unsigned b; float c; }; struct f2_s1 : public f2_s0 { char d;}; -// CHECK: define void @_Z2f25f2_s1([[i64_i64_ty]]) +// CHECK: define void @_Z2f25f2_s1(i64 %a0.coerce0, i64 %a0.coerce1) void f2(f2_s1 a0) { } // PR5831 @@ -26,10 +23,25 @@ struct s3_0 {}; struct s3_1 { struct s3_0 a; long b; }; void f3(struct s3_1 x) {} -// CHECK: define i64 @_Z4f4_0M2s4i(i64) -// CHECK: define [[i64_i64_ty]] @_Z4f4_1M2s4FivE([[i64_i64_ty]]) +// CHECK: define i64 @_Z4f4_0M2s4i(i64 %a.coerce) +// CHECK: define {{.*}} @_Z4f4_1M2s4FivE(i64 %a.coerce0, i64 %a.coerce1) struct s4 {}; typedef int s4::* s4_mdp; typedef int (s4::*s4_mfp)(); s4_mdp f4_0(s4_mdp a) { return a; } s4_mfp f4_1(s4_mfp a) { return a; } + + +namespace PR7523 { +struct StringRef { + char *a; +}; + +void AddKeyword(StringRef, int x); + +void foo() { + // CHECK: define void @_ZN6PR75233fooEv() + // CHECK: call void @_ZN6PR752310AddKeywordENS_9StringRefEi(i8* {{.*}}, i32 4) + AddKeyword(StringRef(), 4); +} +}
\ No newline at end of file |
