diff options
Diffstat (limited to 'test/CodeGenCXX')
47 files changed, 1739 insertions, 215 deletions
diff --git a/test/CodeGenCXX/anonymous-namespaces.cpp b/test/CodeGenCXX/anonymous-namespaces.cpp index fb3470c..3ec7032 100644 --- a/test/CodeGenCXX/anonymous-namespaces.cpp +++ b/test/CodeGenCXX/anonymous-namespaces.cpp @@ -1,12 +1,14 @@ -// RUN: %clang_cc1 -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm %s -o - > %t +// RUN: FileCheck %s -check-prefix=1 < %t +// RUN: FileCheck %s -check-prefix=2 < %t int f(); namespace { - // CHECK: @_ZN12_GLOBAL__N_11bE = internal global i32 0 - // CHECK: @_ZN12_GLOBAL__N_1L1cE = internal global i32 0 - // CHECK: @_ZN12_GLOBAL__N_11D1dE = internal global i32 0 - // CHECK: @_ZN12_GLOBAL__N_11aE = internal global i32 0 + // CHECK-1: @_ZN12_GLOBAL__N_11bE = internal global i32 0 + // CHECK-1: @_ZN12_GLOBAL__N_1L1cE = internal global i32 0 + // CHECK-1: @_ZN12_GLOBAL__N_11D1dE = internal global i32 0 + // CHECK-1: @_ZN12_GLOBAL__N_11aE = internal global i32 0 int a = 0; int b = f(); @@ -20,18 +22,18 @@ namespace { int D::d = f(); // Check for generation of a VTT with internal linkage - // CHECK: @_ZTSN12_GLOBAL__N_11X1EE = internal constant + // CHECK-1: @_ZTSN12_GLOBAL__N_11X1EE = internal constant struct X { struct EBase { }; struct E : public virtual EBase { virtual ~E() {} }; }; - // CHECK: define internal i32 @_ZN12_GLOBAL__N_13fooEv() + // CHECK-1: define internal i32 @_ZN12_GLOBAL__N_13fooEv() int foo() { return 32; } - // CHECK: define internal i32 @_ZN12_GLOBAL__N_11A3fooEv() + // CHECK-1: define internal i32 @_ZN12_GLOBAL__N_11A3fooEv() namespace A { int foo() { return 45; @@ -44,3 +46,23 @@ int concrete() { } void test_XE() { throw X::E(); } + +// Miscompile on llvmc plugins. +namespace test2 { + struct A { + template <class T> struct B { + static void foo() {} + }; + }; + namespace { + struct C; + } + + // CHECK-2: define void @_ZN5test24testEv() + // CHECK-2: call void @_ZN5test21A1BINS_12_GLOBAL__N_11CEE3fooEv() + void test() { + A::B<C>::foo(); + } + + // CHECK-2: define internal void @_ZN5test21A1BINS_12_GLOBAL__N_11CEE3fooEv() +} diff --git a/test/CodeGenCXX/anonymous-union-member-initializer.cpp b/test/CodeGenCXX/anonymous-union-member-initializer.cpp index a4da2c0..9ba3805 100644 --- a/test/CodeGenCXX/anonymous-union-member-initializer.cpp +++ b/test/CodeGenCXX/anonymous-union-member-initializer.cpp @@ -78,3 +78,15 @@ namespace test3 { // CHECK-NEXT: [[CVALUE:%.*]] = getelementptr inbounds {{.*}} [[STRUCT]], i32 0, i32 0 // CHECK-NEXT: store i8* null, void i8** [[CVALUE]] } + +struct S { + // CHECK: store i32 42 + // CHECK: store i32 55 + S() : x(42), y(55) {} + union { + struct { + int x; + union { int y; }; + }; + }; +} s; diff --git a/test/CodeGenCXX/arm.cpp b/test/CodeGenCXX/arm.cpp index 1d4085c..44c0aff 100644 --- a/test/CodeGenCXX/arm.cpp +++ b/test/CodeGenCXX/arm.cpp @@ -1,4 +1,6 @@ -// RUN: %clang_cc1 %s -triple=thumbv7-apple-darwin3.0.0-iphoneos -fno-use-cxa-atexit -target-abi apcs-gnu -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 %s -triple=thumbv7-apple-darwin3.0.0-iphoneos -fno-use-cxa-atexit -target-abi apcs-gnu -emit-llvm -o - -fexceptions | FileCheck %s + +typedef typeof(sizeof(int)) size_t; class foo { public: @@ -13,7 +15,275 @@ public: // The global dtor needs the right calling conv with -fno-use-cxa-atexit // rdar://7817590 +// Checked at end of file. bar baz; +// Destructors and constructors must return this. +namespace test1 { + void foo(); + + struct A { + A(int i) { foo(); } + ~A() { foo(); } + void bar() { foo(); } + }; + + // CHECK: define void @_ZN5test14testEv() + void test() { + // CHECK: [[AV:%.*]] = alloca [[A:%.*]], align 1 + // CHECK: call [[A]]* @_ZN5test11AC1Ei([[A]]* [[AV]], i32 10) + // CHECK: invoke void @_ZN5test11A3barEv([[A]]* [[AV]]) + // CHECK: call [[A]]* @_ZN5test11AD1Ev([[A]]* [[AV]]) + // CHECK: ret void + A a = 10; + a.bar(); + } + + // CHECK: define linkonce_odr [[A]]* @_ZN5test11AC1Ei([[A]]* + // CHECK: [[RET:%.*]] = alloca [[A]]*, align 4 + // CHECK: [[THIS:%.*]] = alloca [[A]]*, align 4 + // CHECK: store [[A]]* {{.*}}, [[A]]** [[THIS]] + // CHECK: [[THIS1:%.*]] = load [[A]]** [[THIS]] + // CHECK: store [[A]]* [[THIS1]], [[A]]** [[RET]] + // CHECK: call [[A]]* @_ZN5test11AC2Ei( + // CHECK: [[THIS2:%.*]] = load [[A]]** [[RET]] + // CHECK: ret [[A]]* [[THIS2]] + + // CHECK: define linkonce_odr [[A]]* @_ZN5test11AD1Ev([[A]]* + // CHECK: [[RET:%.*]] = alloca [[A]]*, align 4 + // CHECK: [[THIS:%.*]] = alloca [[A]]*, align 4 + // CHECK: store [[A]]* {{.*}}, [[A]]** [[THIS]] + // CHECK: [[THIS1:%.*]] = load [[A]]** [[THIS]] + // CHECK: store [[A]]* [[THIS1]], [[A]]** [[RET]] + // CHECK: call [[A]]* @_ZN5test11AD2Ev( + // CHECK: [[THIS2:%.*]] = load [[A]]** [[RET]] + // CHECK: ret [[A]]* [[THIS2]] +} + +// Awkward virtual cases. +namespace test2 { + void foo(); + + struct A { + int x; + + A(int); + virtual ~A() { foo(); } + }; + + struct B { + int y; + int z; + + B(int); + virtual ~B() { foo(); } + }; + + struct C : A, virtual B { + int q; + + C(int i) : A(i), B(i) { foo(); } + ~C() { foo(); } + }; + + void test() { + C c = 10; + } + + // Tests at eof +} + +namespace test3 { + struct A { + int x; + ~A(); + }; + + void a() { + // CHECK: define void @_ZN5test31aEv() + // CHECK: call noalias i8* @_Znam(i32 48) + // CHECK: store i32 4 + // CHECK: store i32 10 + A *x = new A[10]; + } + + void b(int n) { + // CHECK: define void @_ZN5test31bEi( + // CHECK: [[N:%.*]] = load i32* + // CHECK: @llvm.umul.with.overflow.i32(i32 [[N]], i32 4) + // CHECK: @llvm.uadd.with.overflow.i32(i32 {{.*}}, i32 8) + // CHECK: [[SZ:%.*]] = select + // CHECK: call noalias i8* @_Znam(i32 [[SZ]]) + // CHECK: store i32 4 + // CHECK: store i32 [[N]] + A *x = new A[n]; + } + + void c() { + // CHECK: define void @_ZN5test31cEv() + // CHECK: call noalias i8* @_Znam(i32 808) + // CHECK: store i32 4 + // CHECK: store i32 200 + A (*x)[20] = new A[10][20]; + } + + void d(int n) { + // CHECK: define void @_ZN5test31dEi( + // CHECK: [[N:%.*]] = load i32* + // CHECK: [[NE:%.*]] = mul i32 [[N]], 20 + // CHECK: @llvm.umul.with.overflow.i32(i32 [[N]], i32 80) + // CHECK: @llvm.uadd.with.overflow.i32(i32 {{.*}}, i32 8) + // CHECK: [[SZ:%.*]] = select + // CHECK: call noalias i8* @_Znam(i32 [[SZ]]) + // CHECK: store i32 4 + // CHECK: store i32 [[NE]] + A (*x)[20] = new A[n][20]; + } + + void e(A *x) { + // CHECK: define void @_ZN5test31eEPNS_1AE( + // CHECK: icmp eq {{.*}}, null + // CHECK: getelementptr {{.*}}, i64 -8 + // CHECK: getelementptr {{.*}}, i64 4 + // CHECK: bitcast {{.*}} to i32* + // CHECK: load + // CHECK: invoke {{.*}} @_ZN5test31AD1Ev + // CHECK: call void @_ZdaPv + delete [] x; + } + + void f(A (*x)[20]) { + // CHECK: define void @_ZN5test31fEPA20_NS_1AE( + // CHECK: icmp eq {{.*}}, null + // CHECK: getelementptr {{.*}}, i64 -8 + // CHECK: getelementptr {{.*}}, i64 4 + // CHECK: bitcast {{.*}} to i32* + // CHECK: load + // CHECK: invoke {{.*}} @_ZN5test31AD1Ev + // CHECK: call void @_ZdaPv + delete [] x; + } +} + +namespace test4 { + struct A { + int x; + void operator delete[](void *, size_t sz); + }; + + void a() { + // CHECK: define void @_ZN5test41aEv() + // CHECK: call noalias i8* @_Znam(i32 48) + // CHECK: store i32 4 + // CHECK: store i32 10 + A *x = new A[10]; + } + + void b(int n) { + // CHECK: define void @_ZN5test41bEi( + // CHECK: [[N:%.*]] = load i32* + // CHECK: @llvm.umul.with.overflow.i32(i32 [[N]], i32 4) + // CHECK: @llvm.uadd.with.overflow.i32(i32 {{.*}}, i32 8) + // CHECK: [[SZ:%.*]] = select + // CHECK: call noalias i8* @_Znam(i32 [[SZ]]) + // CHECK: store i32 4 + // CHECK: store i32 [[N]] + A *x = new A[n]; + } + + void c() { + // CHECK: define void @_ZN5test41cEv() + // CHECK: call noalias i8* @_Znam(i32 808) + // CHECK: store i32 4 + // CHECK: store i32 200 + A (*x)[20] = new A[10][20]; + } + + void d(int n) { + // CHECK: define void @_ZN5test41dEi( + // CHECK: [[N:%.*]] = load i32* + // CHECK: [[NE:%.*]] = mul i32 [[N]], 20 + // CHECK: @llvm.umul.with.overflow.i32(i32 [[N]], i32 80) + // CHECK: @llvm.uadd.with.overflow.i32(i32 {{.*}}, i32 8) + // CHECK: [[SZ:%.*]] = select + // CHECK: call noalias i8* @_Znam(i32 [[SZ]]) + // CHECK: store i32 4 + // CHECK: store i32 [[NE]] + A (*x)[20] = new A[n][20]; + } + + void e(A *x) { + // CHECK: define void @_ZN5test41eEPNS_1AE( + // CHECK: [[ALLOC:%.*]] = getelementptr inbounds {{.*}}, i64 -8 + // CHECK: getelementptr inbounds {{.*}}, i64 4 + // CHECK: bitcast + // CHECK: [[T0:%.*]] = load i32* + // CHECK: [[T1:%.*]] = mul i32 4, [[T0]] + // CHECK: [[T2:%.*]] = add i32 [[T1]], 8 + // CHECK: call void @_ZN5test41AdaEPvm(i8* [[ALLOC]], i32 [[T2]]) + delete [] x; + } + + void f(A (*x)[20]) { + // CHECK: define void @_ZN5test41fEPA20_NS_1AE( + // CHECK: [[ALLOC:%.*]] = getelementptr inbounds {{.*}}, i64 -8 + // CHECK: getelementptr inbounds {{.*}}, i64 4 + // CHECK: bitcast + // CHECK: [[T0:%.*]] = load i32* + // CHECK: [[T1:%.*]] = mul i32 4, [[T0]] + // CHECK: [[T2:%.*]] = add i32 [[T1]], 8 + // CHECK: call void @_ZN5test41AdaEPvm(i8* [[ALLOC]], i32 [[T2]]) + delete [] x; + } +} + +// <rdar://problem/8386802>: don't crash +namespace test5 { + struct A { + ~A(); + }; + + // CHECK: define void @_ZN5test54testEPNS_1AE + void test(A *a) { + // CHECK: [[PTR:%.*]] = alloca [[A:%.*]]*, align 4 + // CHECK-NEXT: store [[A]]* {{.*}}, [[A]]** [[PTR]], align 4 + // CHECK-NEXT: [[TMP:%.*]] = load [[A]]** [[PTR]], align 4 + // CHECK-NEXT: call [[A]]* @_ZN5test51AD1Ev([[A]]* [[TMP]]) + // CHECK-NEXT: ret void + a->~A(); + } +} + +namespace test6 { + struct A { + virtual ~A(); + }; + + // CHECK: define void @_ZN5test64testEPNS_1AE + void test(A *a) { + // CHECK: [[AVAR:%.*]] = alloca [[A:%.*]]*, align 4 + // CHECK-NEXT: store [[A]]* {{.*}}, [[A]]** [[AVAR]], align 4 + // CHECK-NEXT: [[V:%.*]] = load [[A]]** [[AVAR]], align 4 + // CHECK-NEXT: [[ISNULL:%.*]] = icmp eq [[A]]* [[V]], null + // CHECK-NEXT: br i1 [[ISNULL]] + // CHECK: [[T0:%.*]] = bitcast [[A]]* [[V]] to [[A]]* ([[A]]*)*** + // CHECK-NEXT: [[T1:%.*]] = load [[A]]* ([[A]]*)*** [[T0]] + // CHECK-NEXT: [[T2:%.*]] = getelementptr inbounds [[A]]* ([[A]]*)** [[T1]], i64 1 + // CHECK-NEXT: [[T3:%.*]] = load [[A]]* ([[A]]*)** [[T2]] + // CHECK-NEXT: call [[A]]* [[T3]]([[A]]* [[V]]) + // CHECK-NEXT: br label + // CHECK: ret void + delete a; + } +} + + // CHECK: define linkonce_odr [[C:%.*]]* @_ZTv0_n12_N5test21CD1Ev( + // CHECK: call [[C]]* @_ZN5test21CD1Ev( + // CHECK: ret [[C]]* undef + + // CHECK: define linkonce_odr void @_ZTv0_n12_N5test21CD0Ev( + // CHECK: call void @_ZN5test21CD0Ev( + // CHECK: ret void + // CHECK: @_GLOBAL__D_a() -// CHECK: call void @_ZN3barD1Ev(%class.bar* @baz) +// CHECK: call %class.bar* @_ZN3barD1Ev(%class.bar* @baz) diff --git a/test/CodeGenCXX/condition.cpp b/test/CodeGenCXX/condition.cpp index 652e7c8..cc2eaf5 100644 --- a/test/CodeGenCXX/condition.cpp +++ b/test/CodeGenCXX/condition.cpp @@ -105,12 +105,12 @@ void while_destruct(int z) { // CHECK-NEXT: br i1 [[COND]] // Loop-exit staging block. - // CHECK: store i32 1, i32* [[CLEANUPDEST]] + // CHECK: store i32 3, i32* [[CLEANUPDEST]] // CHECK-NEXT: br // While body. // CHECK: store i32 21, i32* [[Z]] - // CHECK: store i32 2, i32* [[CLEANUPDEST]] + // CHECK: store i32 0, i32* [[CLEANUPDEST]] // CHECK-NEXT: br z = 21; @@ -138,7 +138,7 @@ void while_destruct(int z) { // CHECK: define void @_Z12for_destructi( void for_destruct(int z) { // CHECK: [[Z:%.*]] = alloca i32 - // CHECK: [[XDEST:%.*]] = alloca i32 + // CHECK: [[CLEANUPDEST:%.*]] = alloca i32 // CHECK: [[I:%.*]] = alloca i32 // CHECK: call void @_ZN1YC1Ev // CHECK-NEXT: br @@ -152,7 +152,7 @@ void for_destruct(int z) { // -> %for.body, %for.cond.cleanup // %for.cond.cleanup: Exit cleanup staging. - // CHECK: store i32 1, i32* [[XDEST]] + // CHECK: store i32 2, i32* [[CLEANUPDEST]] // CHECK-NEXT: br // -> %cleanup @@ -166,21 +166,21 @@ void for_destruct(int z) { // 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: store i32 0, i32* [[CLEANUPDEST]] // CHECK-NEXT: br // -> %cleanup // %cleanup: Destroys X. // CHECK: call void @_ZN1XD1Ev - // CHECK-NEXT: [[YDESTTMP:%.*]] = load i32* [[XDEST]] + // CHECK-NEXT: [[YDESTTMP:%.*]] = load i32* [[CLEANUPDEST]] // CHECK-NEXT: switch i32 [[YDESTTMP]] - // 1 -> %cleanup4, 2 -> %cleanup.cont + // 0 -> %cleanup.cont, default -> %cleanup1 // %cleanup.cont: (eliminable) // CHECK: br // -> %for.cond - // %cleanup4: Destroys Y. + // %cleanup1: Destroys Y. // CHECK: call void @_ZN1YD1Ev( // CHECK-NEXT: br // -> %for.end diff --git a/test/CodeGenCXX/copy-constructor-elim-2.cpp b/test/CodeGenCXX/copy-constructor-elim-2.cpp index 3a06c10..73e9b94 100644 --- a/test/CodeGenCXX/copy-constructor-elim-2.cpp +++ b/test/CodeGenCXX/copy-constructor-elim-2.cpp @@ -5,3 +5,29 @@ A f() { return A(0); } // CHECK: define void @_Z1fv // CHECK: call void @_ZN1AC1Ei // CHECK-NEXT: ret void + +// Verify that we do not elide copies when constructing a base class. +namespace no_elide_base { + struct Base { + Base(const Base&); + ~Base(); + }; + + struct Other { + operator Base() const; + }; + + struct Derived : public virtual Base { + Derived(const Other &O); + }; + + // CHECK: define void @_ZN13no_elide_base7DerivedC1ERKNS_5OtherE + Derived::Derived(const Other &O) + // CHECK: call void @_ZNK13no_elide_base5OthercvNS_4BaseEEv + // CHECK: call void @_ZN13no_elide_base4BaseC2ERKS0_ + // CHECK: call void @_ZN13no_elide_base4BaseD1Ev + : Base(O) + { + // CHECK: ret void + } +} diff --git a/test/CodeGenCXX/debug-info-byval.cpp b/test/CodeGenCXX/debug-info-byval.cpp new file mode 100644 index 0000000..c99518e --- /dev/null +++ b/test/CodeGenCXX/debug-info-byval.cpp @@ -0,0 +1,31 @@ +// RUN: %clang -g -S %s -o - | FileCheck %s +// Test to check presense of debug info for byval parameter. +// Radar 8350436. +class DAG { +public: + int i; + int j; +}; + +class EVT { +public: + int a; + int b; + int c; +}; + +class VAL { +public: + int x; + int y; +}; +void foo(EVT e); +EVT bar(); + +void get(int *i, unsigned dl, VAL v, VAL *p, unsigned n, EVT missing_arg) { +//CHECK: .ascii "missing_arg" + EVT e = bar(); + if (dl == n) + foo(missing_arg); +} + diff --git a/test/CodeGenCXX/debug-info-class.cpp b/test/CodeGenCXX/debug-info-class.cpp new file mode 100644 index 0000000..151c5f9 --- /dev/null +++ b/test/CodeGenCXX/debug-info-class.cpp @@ -0,0 +1,12 @@ +// RUN: %clang -emit-llvm -g -S %s -o - | grep HdrSize +struct A { + int one; + static const int HdrSize = 52; + int two; + A() { + int x = 1; + } +}; +int main() { + A a; +} diff --git a/test/CodeGenCXX/debug-info-ctor.cpp b/test/CodeGenCXX/debug-info-ctor.cpp new file mode 100644 index 0000000..c31eebe --- /dev/null +++ b/test/CodeGenCXX/debug-info-ctor.cpp @@ -0,0 +1,14 @@ +// RUN: %clang -emit-llvm -g -S %s -o - | FileCheck %s + +struct X { + X(int v); + + int value; +}; + +X::X(int v) { + // CHECK_TEMPORARILY_DISABLED: call void @_ZN1XC2Ei(%struct.X* %this1, i32 %tmp), !dbg + // TEMPORARY CHECK: X + value = v; +} + diff --git a/test/CodeGenCXX/debug-info-enum.cpp b/test/CodeGenCXX/debug-info-enum.cpp new file mode 100644 index 0000000..c08fc35 --- /dev/null +++ b/test/CodeGenCXX/debug-info-enum.cpp @@ -0,0 +1,8 @@ +// RUN: %clang -fverbose-asm -S -g %s -o - | grep DW_TAG_enumeration_type + +int v; +enum index { MAX }; +void foo(void) +{ + v = MAX; +} diff --git a/test/CodeGenCXX/debug-info-friend.cpp b/test/CodeGenCXX/debug-info-friend.cpp new file mode 100644 index 0000000..c50f281 --- /dev/null +++ b/test/CodeGenCXX/debug-info-friend.cpp @@ -0,0 +1,11 @@ +// RUN: %clang -fverbose-asm -S -g %s -o - | grep DW_TAG_friend + +class MyFriend; + +class SomeClass +{ + friend class MyFriend; +}; + +SomeClass sc; + diff --git a/test/CodeGenCXX/debug-info-template.cpp b/test/CodeGenCXX/debug-info-template.cpp new file mode 100644 index 0000000..233090c --- /dev/null +++ b/test/CodeGenCXX/debug-info-template.cpp @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 -emit-llvm-only -g -S %s -o - | grep "TC<int>" +template<typename T> +class TC { +public: + TC(const TC &) {} + TC() {} +}; + +TC<int> tci; diff --git a/test/CodeGenCXX/debug-info.cpp b/test/CodeGenCXX/debug-info.cpp index 6bb9533..71c8603 100644 --- a/test/CodeGenCXX/debug-info.cpp +++ b/test/CodeGenCXX/debug-info.cpp @@ -50,3 +50,8 @@ namespace VirtualBase { B b; } } + +void foo() { + const wchar_t c = L'x'; + wchar_t d = c; +} diff --git a/test/CodeGenCXX/delete.cpp b/test/CodeGenCXX/delete.cpp index 87f8698..1f52a78 100644 --- a/test/CodeGenCXX/delete.cpp +++ b/test/CodeGenCXX/delete.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 %s -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 %s -emit-llvm -o - | FileCheck %s void t1(int *a) { delete a; @@ -57,3 +57,51 @@ namespace test0 { // CHECK: define linkonce_odr void @_ZN5test01AD1Ev // CHECK: define linkonce_odr void @_ZN5test01AdlEPv } + +namespace test1 { + struct A { + int x; + ~A(); + }; + + // CHECK: define void @_ZN5test14testEPA10_A20_NS_1AE( + void test(A (*arr)[10][20]) { + delete [] arr; + // CHECK: icmp eq [10 x [20 x [[S:%.*]]]]* [[PTR:%.*]], null + // CHECK-NEXT: br i1 + + // CHECK: [[ARR:%.*]] = getelementptr inbounds [10 x [20 x [[S]]]]* [[PTR]], i32 0, i32 0, i32 0 + // CHECK-NEXT: bitcast {{.*}} to i8* + // CHECK-NEXT: [[ALLOC:%.*]] = getelementptr inbounds {{.*}}, i64 -8 + // CHECK-NEXT: bitcast i8* [[ALLOC]] to i64* + // CHECK-NEXT: load + // CHECK-NEXT: store i64 {{.*}}, i64* [[IDX:%.*]] + + // CHECK: load i64* [[IDX]] + // CHECK-NEXT: icmp ne {{.*}}, 0 + // CHECK-NEXT: br i1 + + // CHECK: load i64* [[IDX]] + // CHECK-NEXT: [[I:%.*]] = sub i64 {{.*}}, 1 + // CHECK-NEXT: getelementptr inbounds [[S]]* [[ARR]], i64 [[I]] + // CHECK-NEXT: call void @_ZN5test11AD1Ev( + // CHECK-NEXT: br label + + // CHECK: load i64* [[IDX]] + // CHECK-NEXT: sub + // CHECK-NEXT: store {{.*}}, i64* [[IDX]] + // CHECK-NEXT: br label + + // CHECK: call void @_ZdaPv(i8* [[ALLOC]]) + } +} + +namespace test2 { + // CHECK: define void @_ZN5test21fEPb + void f(bool *b) { + // CHECK: call void @_ZdlPv(i8* + delete b; + // CHECK: call void @_ZdaPv(i8* + delete [] b; + } +} diff --git a/test/CodeGenCXX/dependent-type-member-pointer.cpp b/test/CodeGenCXX/dependent-type-member-pointer.cpp new file mode 100644 index 0000000..41bb5e2 --- /dev/null +++ b/test/CodeGenCXX/dependent-type-member-pointer.cpp @@ -0,0 +1,18 @@ +// RUN: %clang_cc1 -emit-llvm-only -verify %s +// PR7736 + +template <class scriptmemberptr> int InitMember(scriptmemberptr); + +template <class> +struct contentmap +{ + static void InitDataMap() + { InitMember(&contentmap::SizeHolder); } + int SizeHolder; +}; + +void ReadFrom( ) +{ + contentmap<int>::InitDataMap(); +} + diff --git a/test/CodeGenCXX/destructors.cpp b/test/CodeGenCXX/destructors.cpp index 8efaf01..2eba30f 100644 --- a/test/CodeGenCXX/destructors.cpp +++ b/test/CodeGenCXX/destructors.cpp @@ -260,12 +260,53 @@ namespace test5 { } } -// Checks from test3: +namespace test6 { + void opaque(); - // CHECK: define internal void @_ZN5test312_GLOBAL__N_11CD2Ev( - // CHECK: call void @_ZN5test31BD2Ev( - // CHECK: call void @_ZN5test31AD2Ev( - // CHECK: ret void + struct A { ~A(); }; + template <unsigned> struct B { B(); ~B(); int _; }; + struct C : B<0>, B<1>, virtual B<2>, virtual B<3> { + A x, y, z; + + C(); + ~C(); + }; + + C::C() { opaque(); } + // CHECK: define void @_ZN5test61CC1Ev + // CHECK: call void @_ZN5test61BILj2EEC2Ev + // CHECK: invoke void @_ZN5test61BILj3EEC2Ev + // CHECK: invoke void @_ZN5test61BILj0EEC2Ev + // CHECK: invoke void @_ZN5test61BILj1EEC2Ev + // CHECK: invoke void @_ZN5test66opaqueEv + // CHECK: ret void + // FIXME: way too much EH cleanup code follows + + C::~C() { opaque(); } + // CHECK: define void @_ZN5test61CD1Ev + // CHECK: invoke void @_ZN5test61CD2Ev + // CHECK: invoke void @_ZN5test61BILj3EED2Ev + // CHECK: call void @_ZN5test61BILj2EED2Ev + // CHECK: ret void + // CHECK: invoke void @_ZN5test61BILj3EED2Ev + // CHECK: invoke void @_ZN5test61BILj2EED2Ev + + // CHECK: define void @_ZN5test61CD2Ev + // CHECK: invoke void @_ZN5test66opaqueEv + // CHECK: invoke void @_ZN5test61AD1Ev + // CHECK: invoke void @_ZN5test61AD1Ev + // CHECK: invoke void @_ZN5test61AD1Ev + // CHECK: invoke void @_ZN5test61BILj1EED2Ev + // CHECK: call void @_ZN5test61BILj0EED2Ev + // CHECK: ret void + // CHECK: invoke void @_ZN5test61AD1Ev + // CHECK: invoke void @_ZN5test61AD1Ev + // CHECK: invoke void @_ZN5test61AD1Ev + // CHECK: invoke void @_ZN5test61BILj1EED2Ev + // CHECK: invoke void @_ZN5test61BILj0EED2Ev +} + +// Checks from test3: // CHECK: define internal void @_ZN5test312_GLOBAL__N_11DD0Ev( // CHECK: invoke void @_ZN5test312_GLOBAL__N_11DD1Ev( @@ -289,6 +330,11 @@ namespace test5 { // CHECK: call void @_ZN5test312_GLOBAL__N_11DD0Ev( // CHECK: ret void + // CHECK: define internal void @_ZN5test312_GLOBAL__N_11CD2Ev( + // CHECK: invoke void @_ZN5test31BD2Ev( + // CHECK: call void @_ZN5test31AD2Ev( + // CHECK: ret void + // CHECK: declare void @_ZN5test31BD2Ev( // CHECK: declare void @_ZN5test31AD2Ev( diff --git a/test/CodeGenCXX/dyncast.cpp b/test/CodeGenCXX/dyncast.cpp index 906d44b..723e12b 100644 --- a/test/CodeGenCXX/dyncast.cpp +++ b/test/CodeGenCXX/dyncast.cpp @@ -86,15 +86,12 @@ void test1() { // CHECK-LL-NEXT: [[tmp:%.*]] = load %class.test1_A** [[bp]] // CHECK-LL-NEXT: [[v4:%.*]] = icmp ne %class.test1_A* [[tmp]], null // CHECK-LL-NEXT: br i1 [[v4]], label %[[v5:.*]], label %[[v9:.*]] -// CHECK-LL: ; <label>:[[v5]] -// CHECK-LL-NEXT: [[v6:%.*]] = bitcast %class.test1_A* [[tmp]] to i8* -// CHECK-LL-NEXT: [[v7:%.*]] = call i8* @__dynamic_cast(i8* [[v6]], i8* bitcast (%0* @_ZTI7test1_B to i8*), i8* bitcast (%1* @_ZTI7test1_D to i8*), i64 -1) ; <i8*> [#uses=1] +// CHECK-LL: [[v6:%.*]] = bitcast %class.test1_A* [[tmp]] to i8* +// CHECK-LL-NEXT: [[v7:%.*]] = call i8* @__dynamic_cast(i8* [[v6]], i8* bitcast (%0* @_ZTI7test1_B to i8*), i8* bitcast (%1* @_ZTI7test1_D to i8*), i64 -1) // CHECK-LL-NEXT: [[v8:%.*]] = bitcast i8* [[v7]] to %class.test1_D* // CHECK-LL-NEXT: br label %[[v10:.*]] -// CHECK-LL: ; <label>:[[v9]] -// CHECK-LL-NEXT: br label %[[v10]] -// CHECK-LL: ; <label>:[[v10]] -// CHECK-LL-NEXT: [[v11:%.*]] = phi %class.test1_D* [ [[v8]], %[[v5]] ], [ null, %[[v9]] ] +// CHECK-LL: br label %[[v10]] +// CHECK-LL: [[v11:%.*]] = phi %class.test1_D* [ [[v8]], %[[v5]] ], [ null, %[[v9]] ] // CHECK-LL-NEXT: store %class.test1_D* [[v11]], %class.test1_D** [[dp]] // CHECK-LL-NEXT: [[tmp4:%.*]] = load %class.test1_D** [[dp]] // CHECK-LL-NEXT: [[cmp:%.*]] = icmp eq %class.test1_D* [[tmp4]], null @@ -109,15 +106,12 @@ void test1() { // CHECK-LL-NEXT: [[tmp6:%.*]] = load %class.test1_A** [[bp]] // CHECK-LL-NEXT: [[v12:%.*]] = icmp ne %class.test1_A* [[tmp6]], null // CHECK-LL-NEXT: br i1 [[v12]], label %[[v13:.*]], label %[[v17:.*]] -// CHECK-LL: ; <label>:[[v13]] -// CHECK-LL-NEXT: [[v14:%.*]] = bitcast %class.test1_A* [[tmp6]] to i8* +// CHECK-LL: [[v14:%.*]] = bitcast %class.test1_A* [[tmp6]] to i8* // CHECK-LL-NEXT: [[v15:%.*]] = call i8* @__dynamic_cast(i8* [[v14]], i8* bitcast ({{.*}} @_ZTI7test1_B to i8*), i8* bitcast ({{.*}} @_ZTI7test1_A to i8*), i64 -1) // CHECK-LL-NEXT: [[v16:%.*]] = bitcast i8* [[v15]] to %class.test1_A* // CHECK-LL-NEXT: br label %[[v18:.*]] -// CHECK-LL: ; <label>:[[v17]] -// CHECK-LL-NEXT: br label %[[v18]] -// CHECK-LL: ; <label>:[[v18]] -// CHECK-LL-NEXT: [[v19:%.*]] = phi %class.test1_A* [ [[v16]], %[[v13]] ], [ null, %[[v17]] ] +// CHECK-LL: br label %[[v18]] +// CHECK-LL: [[v19:%.*]] = phi %class.test1_A* [ [[v16]], %[[v13]] ], [ null, %[[v17]] ] // CHECK-LL-NEXT: store %class.test1_A* [[v19]], %class.test1_A** [[ap]] // CHECK-LL-NEXT: [[tmp7:%.*]] = load %class.test1_A** [[ap]] // CHECK-LL-NEXT: [[cmp8:%.*]] = icmp eq %class.test1_A* [[tmp7]], null @@ -132,15 +126,12 @@ void test1() { // CHECK-LL-NEXT: [[tmp14:%.*]] = load %class.test1_A** [[ap]] // CHECK-LL-NEXT: [[v20:%.*]] = icmp ne %class.test1_A* [[tmp14]], null // CHECK-LL-NEXT: br i1 [[v20]], label %[[v21:.*]], label %[[v25:.*]] -// CHECK-LL: ; <label>:[[v21]] -// CHECK-LL-NEXT: [[v22:%.*]] = bitcast %class.test1_A* [[tmp14]] to i8* +// CHECK-LL: [[v22:%.*]] = bitcast %class.test1_A* [[tmp14]] to i8* // CHECK-LL-NEXT: [[v23:%.*]] = call i8* @__dynamic_cast({{.*}} [[v22]], i8* bitcast ({{.*}} @_ZTI7test1_A to i8*), i8* bitcast ({{.*}} @_ZTI7test1_B to i8*), i64 -1) // CHECK-LL-NEXT: [[v24:%.*]] = bitcast i8* [[v23]] to %class.test1_A* // CHECK-LL-NEXT: br label %[[v26:.*]] -// CHECK-LL: ; <label>:[[v25]] -// CHECK-LL-NEXT: br label %[[v26]] -// CHECK-LL: ; <label>:[[v26]] -// CHECK-LL-NEXT: [[v27:%.*]] = phi %class.test1_A* [ [[v24]], %[[v21]] ], [ null, %[[v25]] ] +// CHECK-LL: br label %[[v26]] +// CHECK-LL: [[v27:%.*]] = phi %class.test1_A* [ [[v24]], %[[v21]] ], [ null, %[[v25]] ] // CHECK-LL-NEXT: store %class.test1_A* [[v27]], %class.test1_A** [[bp]] // CHECK-LL-NEXT: [[tmp15:%.*]] = load %class.test1_A** [[bp]] // CHECK-LL-NEXT: [[cmp16:%.*]] = icmp eq %class.test1_A* [[tmp15]], null @@ -203,15 +194,12 @@ void test1() { // CHECK-LL-NEXT: [[tmp54:%.*]] = load %class.test1_A** [[ap37]] // CHECK-LL-NEXT: [[v34:%.*]] = icmp ne %class.test1_A* [[tmp54]], null // CHECK-LL-NEXT: br i1 [[v34]], label %[[v35:.*]], label %[[v39:.*]] -// CHECK-LL: ; <label>:[[v35]] -// CHECK-LL-NEXT: [[v36:%.*]] = bitcast %class.test1_A* [[tmp54]] to i8* +// CHECK-LL: [[v36:%.*]] = bitcast %class.test1_A* [[tmp54]] to i8* // CHECK-LL-NEXT: [[v37:%.*]] = call i8* @__dynamic_cast(i8* [[v36]], i8* bitcast ({{.*}} @_ZTI7test1_A to i8*), i8* bitcast ({{.*}} @_ZTI7test1_D to i8*), i64 -1) // CHECK-LL-NEXT: [[v38:%.*]] = bitcast i8* [[v37]] to %class.test1_D* // CHECK-LL-NEXT: br label %[[v40:.*]] -// CHECK-LL: ; <label>:[[v39]] -// CHECK-LL-NEXT: br label %[[v40]] -// CHECK-LL: ; <label>:[[v40]] -// CHECK-LL-NEXT: [[v41:%.*]] = phi %class.test1_D* [ [[v38]], %[[v35]] ], [ null, %[[v39]] ] +// CHECK-LL: br label %[[v40]] +// CHECK-LL: [[v41:%.*]] = phi %class.test1_D* [ [[v38]], %[[v35]] ], [ null, %[[v39]] ] // CHECK-LL-NEXT: store %class.test1_D* [[v41]], %class.test1_D** [[dp53]] // CHECK-LL-NEXT: [[tmp55:%.*]] = load %class.test1_D** [[dp53]] // CHECK-LL-NEXT: [[cmp56:%.*]] = icmp eq %class.test1_D* [[tmp55]], null @@ -226,15 +214,12 @@ void test1() { // CHECK-LL-NEXT: [[tmp63:%.*]] = load %class.test1_A** [[ap37]] // CHECK-LL-NEXT: [[v42:%.*]] = icmp ne %class.test1_A* [[tmp63]], null // CHECK-LL-NEXT: br i1 [[v42]], label %[[v43:.*]], label %[[v47:.*]] -// CHECK-LL: ; <label>:[[v43]] -// CHECK-LL-NEXT: [[v44:%.*]] = bitcast %class.test1_A* [[tmp63]] to i8* +// CHECK-LL: [[v44:%.*]] = bitcast %class.test1_A* [[tmp63]] to i8* // CHECK-LL-NEXT: [[v45:%.*]] = call i8* @__dynamic_cast(i8* [[v44]], i8* bitcast ({{.*}} @_ZTI7test1_A to i8*), i8* bitcast ({{.*}} @_ZTI7test1_E to i8*), i64 -1) // CHECK-LL-NEXT: [[v46:%.*]] = bitcast i8* [[v45]] to %class.test1_E* // CHECK-LL-NEXT: br label %[[v48:.*]] -// CHECK-LL: ; <label>:[[v47]] -// CHECK-LL-NEXT: br label %[[v48]] -// CHECK-LL: ; <label>:[[v48]] -// CHECK-LL-NEXT: [[v49:%.*]] = phi %class.test1_E* [ [[v46]], %[[v43]] ], [ null, %[[v47]] ] +// CHECK-LL: br label %[[v48]] +// CHECK-LL: [[v49:%.*]] = phi %class.test1_E* [ [[v46]], %[[v43]] ], [ null, %[[v47]] ] // CHECK-LL-NEXT: store %class.test1_E* [[v49]], %class.test1_E** [[ep1]] // CHECK-LL-NEXT: [[tmp64:%.*]] = load %class.test1_E** [[ep1]] // CHECK-LL-NEXT: [[cmp65:%.*]] = icmp ne %class.test1_E* [[tmp64]], null @@ -269,14 +254,11 @@ void test1() { // CHECK-LL-NEXT: br label %[[ifend85]] // CHECK-LL: [[ifend85]] // CHECK-LL-NEXT: br i1 false, label %[[v50:.*]], label %[[v53:.*]] -// CHECK-LL: ; <label>:[[v50]] -// CHECK-LL-NEXT: [[v51:%.*]] = call i8* @__dynamic_cast(i8* null, i8* bitcast ({{.*}}* @_ZTI7test1_A to i8*), i8* bitcast ({{.*}} @_ZTI7test1_D to i8*), i64 -1) +// CHECK-LL: [[v51:%.*]] = call i8* @__dynamic_cast(i8* null, i8* bitcast ({{.*}}* @_ZTI7test1_A to i8*), i8* bitcast ({{.*}} @_ZTI7test1_D to i8*), i64 -1) // CHECK-LL-NEXT: [[v52:%.*]] = bitcast i8* [[v51]] to %class.test1_D* // CHECK-LL-NEXT: br label %[[v54:.*]] -// CHECK-LL: ; <label>:[[v53]] -// CHECK-LL-NEXT: br label %[[v54]] -// CHECK-LL: ; <label>:[[v54]] -// CHECK-LL-NEXT: [[v55:%.*]] = phi %class.test1_D* [ [[v52]], %[[v50]] ], [ null, %[[v53]] ] +// CHECK-LL: br label %[[v54]] +// CHECK-LL: [[v55:%.*]] = phi %class.test1_D* [ [[v52]], %[[v50]] ], [ null, %[[v53]] ] // CHECK-LL-NEXT: store %class.test1_D* [[v55]], %class.test1_D** [[dp]] // CHECK-LL-NEXT: [[tmp86:%.*]] = load %class.test1_D** [[dp]] // CHECK-LL-NEXT: [[cmp87:%.*]] = icmp eq %class.test1_D* [[tmp86]], null @@ -327,7 +309,7 @@ void test1() { // CHECK-LL: [[ifend113]] // CHECK-LL-NEXT: store %class.test1_E* bitcast (%class.test1_F* @test1_f to %class.test1_E*), %class.test1_E** [[ep]] // CHECK-LL-NEXT: [[tmp118:%.*]] = load %class.test1_E** [[ep]] -// CHECK-LL-NEXT: [[cmp122:%.*]] = icmp eq %class.test1_E* [[tmp118]], bitcast (%class.test1_F* @test1_f to %class.test1_E*) ; <i1> [#uses=1] +// CHECK-LL-NEXT: [[cmp122:%.*]] = icmp eq %class.test1_E* [[tmp118]], bitcast (%class.test1_F* @test1_f to %class.test1_E*) // CHECK-LL-NEXT: br i1 [[cmp122]], label %[[ifthen123:.*]], label %[[ifelse125:.*]] // CHECK-LL: [[ifthen123]] @@ -340,18 +322,15 @@ void test1() { // CHECK-LL-NEXT: [[tmp129:%.*]] = load %class.test1_A** [[ap]] // CHECK-LL-NEXT: [[v64:%.*]] = icmp ne %class.test1_A* [[tmp129]], null // CHECK-LL-NEXT: br i1 [[v64]], label %[[v65:.*]], label %[[v70:.*]] -// CHECK-LL: ; <label>:[[v65]] -// CHECK-LL-NEXT: [[v66:%.*]] = bitcast %class.test1_A* [[tmp129]] to i64** +// CHECK-LL: [[v66:%.*]] = bitcast %class.test1_A* [[tmp129]] to i64** // CHECK-LL-NEXT: [[vtable130:%.*]] = load i64** [[v66]] // CHECK-LL-NEXT: [[v67:%.*]] = getelementptr inbounds i64* [[vtable130]], i64 -2 // CHECK-LL-NEXT: [[offsettotop:%.*]] = load i64* [[v67]] // CHECK-LL-NEXT: [[v68:%.*]] = bitcast %class.test1_A* [[tmp129]] to i8* // CHECK-LL-NEXT: [[v69:%.*]] = getelementptr inbounds i8* [[v68]], i64 [[offsettotop]] // CHECK-LL-NEXT: br label %[[v71:.*]] -// CHECK-LL: ; <label>:[[v70]] -// CHECK-LL-NEXT: br label %[[v71]] -// CHECK-LL: ; <label>:[[v71]] -// CHECK-LL-NEXT: [[v72:%.*]] = phi i8* [ [[v69]], %[[v65]] ], [ null, %[[v70]] ] +// CHECK-LL: br label %[[v71]] +// CHECK-LL: [[v72:%.*]] = phi i8* [ [[v69]], %[[v65]] ], [ null, %[[v70]] ] // CHECK-LL-NEXT: store i8* [[v72]], i8** [[vp]] // CHECK-LL-NEXT: [[tmp131:%.*]] = load i8** [[vp]] // CHECK-LL-NEXT: [[cmp132:%.*]] = icmp eq i8* [[tmp131]], getelementptr inbounds (%class.test1_D* @test1_d, i32 0, i32 0, i32 0) @@ -366,18 +345,15 @@ void test1() { // CHECK-LL-NEXT: [[tmp139:%.*]] = load %class.test1_A** [[ap]] // CHECK-LL-NEXT: [[v73:%.*]] = icmp ne %class.test1_A* [[tmp139]], null // CHECK-LL-NEXT: br i1 [[v73]], label %[[v74:.*]], label %[[v79:.*]] -// CHECK-LL: ; <label>:[[v74]] -// CHECK-LL-NEXT: [[v75:%.*]] = bitcast %class.test1_A* [[tmp139]] to i64** +// CHECK-LL: [[v75:%.*]] = bitcast %class.test1_A* [[tmp139]] to i64** // CHECK-LL-NEXT: [[vtable140:%.*]] = load i64** [[v75]] // CHECK-LL-NEXT: [[v76:%.*]] = getelementptr inbounds i64* [[vtable140]], i64 -2 // CHECK-LL-NEXT: [[offsettotop141:%.*]] = load i64* [[v76]] // CHECK-LL-NEXT: [[v77:%.*]] = bitcast %class.test1_A* [[tmp139]] to i8* // CHECK-LL-NEXT: [[v78:%.*]] = getelementptr inbounds i8* [[v77]], i64 [[offsettotop141]] // CHECK-LL-NEXT: br label %[[v80:.*]] -// CHECK-LL: ; <label>:[[v79]] -// CHECK-LL-NEXT: br label %[[v80]] -// CHECK-LL: ; <label>:[[v80]] -// CHECK-LL-NEXT: [[v81:%.*]] = phi i8* [ [[v78]], %[[v74]] ], [ null, %[[v79]] ] +// CHECK-LL: br label %[[v80]] +// CHECK-LL: [[v81:%.*]] = phi i8* [ [[v78]], %[[v74]] ], [ null, %[[v79]] ] // CHECK-LL-NEXT: store i8* [[v81]], i8** [[cvp]] // CHECK-LL-NEXT: [[tmp142:%.*]] = load i8** [[cvp]] // CHECK-LL-NEXT: [[cmp143:%.*]] = icmp eq i8* [[tmp142]], getelementptr inbounds (%class.test1_D* @test1_d, i32 0, i32 0, i32 0) diff --git a/test/CodeGenCXX/eh.cpp b/test/CodeGenCXX/eh.cpp index 6d79c3e..0960ec3 100644 --- a/test/CodeGenCXX/eh.cpp +++ b/test/CodeGenCXX/eh.cpp @@ -39,6 +39,7 @@ void test2() { // CHECK: [[FREEVAR:%.*]] = alloca i1 // CHECK-NEXT: [[EXNOBJVAR:%.*]] = alloca i8* // CHECK-NEXT: [[EXNSLOTVAR:%.*]] = alloca i8* +// CHECK-NEXT: [[CLEANUPDESTVAR:%.*]] = alloca i32 // CHECK-NEXT: store i1 false, i1* [[FREEVAR]] // CHECK-NEXT: [[EXNOBJ:%.*]] = call i8* @__cxa_allocate_exception(i64 16) // CHECK-NEXT: store i8* [[EXNOBJ]], i8** [[EXNOBJVAR]] @@ -124,6 +125,7 @@ namespace test7 { // CHECK-NEXT: [[EXNALLOCVAR:%.*]] = alloca i8* // CHECK-NEXT: [[CAUGHTEXNVAR:%.*]] = alloca i8* // CHECK-NEXT: [[INTCATCHVAR:%.*]] = alloca i32 +// CHECK-NEXT: [[EHCLEANUPDESTVAR:%.*]] = alloca i32 // CHECK-NEXT: store i1 false, i1* [[FREEEXNOBJ]] try { try { @@ -153,6 +155,7 @@ namespace test7 { // 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: store i32 1, i32* [[EHCLEANUPDESTVAR]] // CHECK-NEXT: call void @__cxa_end_catch() // CHECK-NEXT: br label // CHECK: load i8** [[CAUGHTEXNVAR]] @@ -249,3 +252,165 @@ namespace test10 { // CHECK: call void @_ZN6test101AD1Ev( } } + +// __cxa_begin_catch returns pointers by value, even when catching by reference +// <rdar://problem/8212123> +namespace test11 { + void opaque(); + + // CHECK: define void @_ZN6test113fooEv() + void foo() { + try { + // CHECK: invoke void @_ZN6test116opaqueEv() + opaque(); + } catch (int**&p) { + // CHECK: [[EXN:%.*]] = load i8** + // CHECK-NEXT: call i8* @__cxa_begin_catch(i8* [[EXN]]) nounwind + // CHECK-NEXT: [[ADJ1:%.*]] = getelementptr i8* [[EXN]], i32 32 + // CHECK-NEXT: [[ADJ2:%.*]] = bitcast i8* [[ADJ1]] to i32*** + // CHECK-NEXT: store i32*** [[ADJ2]], i32**** [[P:%.*]] + // CHECK-NEXT: call void @__cxa_end_catch() nounwind + } + } + + struct A {}; + + // CHECK: define void @_ZN6test113barEv() + void bar() { + try { + // CHECK: [[EXNSLOT:%.*]] = alloca i8* + // CHECK-NEXT: [[P:%.*]] = alloca [[A:%.*]]**, + // CHECK-NEXT: [[TMP:%.*]] = alloca [[A]]* + // CHECK-NEXT: invoke void @_ZN6test116opaqueEv() + opaque(); + } catch (A*&p) { + // CHECK: [[EXN:%.*]] = load i8** [[EXNSLOT]] + // CHECK-NEXT: [[ADJ1:%.*]] = call i8* @__cxa_begin_catch(i8* [[EXN]]) nounwind + // CHECK-NEXT: [[ADJ2:%.*]] = bitcast i8* [[ADJ1]] to [[A]]* + // CHECK-NEXT: store [[A]]* [[ADJ2]], [[A]]** [[TMP]] + // CHECK-NEXT: store [[A]]** [[TMP]], [[A]]*** [[P]] + // CHECK-NEXT: call void @__cxa_end_catch() nounwind + } + } +} + +// PR7686 +namespace test12 { + struct A { ~A(); }; + bool opaque(const A&); + + // CHECK: define void @_ZN6test124testEv() + void test() { + // CHECK: [[X:%.*]] = alloca [[A:%.*]], + // CHECK: [[EHCLEANUPDEST:%.*]] = alloca i32 + // CHECK: [[Y:%.*]] = alloca [[A]] + // CHECK: [[Z:%.*]] = alloca [[A]] + // CHECK: [[CLEANUPDEST:%.*]] = alloca i32 + + A x; + // CHECK: invoke zeroext i1 @_ZN6test126opaqueERKNS_1AE( + if (opaque(x)) { + A y; + A z; + + // CHECK: invoke void @_ZN6test121AD1Ev([[A]]* [[Z]]) + // CHECK: invoke void @_ZN6test121AD1Ev([[A]]* [[Y]]) + + // It'd be great if something eliminated this switch. + // CHECK: load i32* [[CLEANUPDEST]] + // CHECK-NEXT: switch i32 + goto success; + } + + success: + bool _ = true; + + // CHECK: call void @_ZN6test121AD1Ev([[A]]* [[X]]) + // CHECK-NEXT: ret void + } +} + +// Reduced from some TableGen code that was causing a self-host crash. +namespace test13 { + struct A { ~A(); }; + + void test0(int x) { + try { + switch (x) { + case 0: + break; + case 1:{ + A a; + break; + } + default: + return; + } + return; + } catch (int x) { + } + return; + } + + void test1(int x) { + A y; + try { + switch (x) { + default: break; + } + } catch (int x) {} + } +} + +// rdar://problem/8231514 +namespace test14 { + struct A { ~A(); }; + struct B { ~B(); }; + + B b(); + void opaque(); + + void foo() { + A a; + try { + B str = b(); + opaque(); + } catch (int x) { + } + } +} + +// rdar://problem/8231514 +// JumpDests shouldn't get confused by scopes that aren't normal cleanups. +namespace test15 { + struct A { ~A(); }; + + bool opaque(int); + + // CHECK: define void @_ZN6test153fooEv() + void foo() { + A a; + + try { + // CHECK: [[X:%.*]] = alloca i32 + // CHECK: store i32 10, i32* [[X]] + // CHECK-NEXT: br label + // -> while.cond + int x = 10; + + while (true) { + // CHECK: load i32* [[X]] + // CHECK-NEXT: [[COND:%.*]] = invoke zeroext i1 @_ZN6test156opaqueEi + // CHECK: br i1 [[COND]] + if (opaque(x)) + // CHECK: br label + break; + + // CHECK: br label + } + // CHECK: br label + } catch (int x) { } + + // CHECK: call void @_ZN6test151AD1Ev + } +} diff --git a/test/CodeGenCXX/exceptions-no-rtti.cpp b/test/CodeGenCXX/exceptions-no-rtti.cpp index c26abb2..66b4c4a 100644 --- a/test/CodeGenCXX/exceptions-no-rtti.cpp +++ b/test/CodeGenCXX/exceptions-no-rtti.cpp @@ -18,9 +18,12 @@ namespace test0 { } namespace test1 { - // These classes have key functions defined out-of-line. - // Under normal circumstances, we wouldn't generate RTTI for them; - // under -fno-rtti, we generate RTTI only when required by EH. + // These classes have key functions defined out-of-line. Under + // normal circumstances, we wouldn't generate RTTI for them; under + // -fno-rtti, we generate RTTI only when required by EH. But + // everything gets hidden visibility because we assume that all + // users are also compiled under -fno-rtti and therefore will be + // emitting RTTI regardless of key function. class A { virtual void foo(); }; class B { virtual void foo(); }; class C { virtual void foo(); }; diff --git a/test/CodeGenCXX/explicit-instantiation.cpp b/test/CodeGenCXX/explicit-instantiation.cpp index 24d1a67..b829585 100644 --- a/test/CodeGenCXX/explicit-instantiation.cpp +++ b/test/CodeGenCXX/explicit-instantiation.cpp @@ -1,5 +1,8 @@ // RUN: %clang_cc1 -emit-llvm -triple i686-pc-linux-gnu -o - %s | FileCheck %s +// This check logically is attached to 'template int S<int>::i;' below. +// CHECK: @_ZN1SIiE1iE = weak global i32 + template<typename T, typename U, typename Result> struct plus { Result operator()(const T& t, const U& u) const; @@ -12,3 +15,31 @@ Result plus<T, U, Result>::operator()(const T& t, const U& u) const { // CHECK: define weak_odr i32 @_ZNK4plusIillEclERKiRKl template struct plus<int, long, long>; + +// Check that we emit definitions from explicit instantiations even when they +// occur prior to the definition itself. +template <typename T> struct S { + void f(); + static void g(); + static int i; + struct S2 { + void h(); + }; +}; + +// CHECK: define weak_odr void @_ZN1SIiE1fEv +template void S<int>::f(); + +// CHECK: define weak_odr void @_ZN1SIiE1gEv +template void S<int>::g(); + +// See the check line at the top of the file. +template int S<int>::i; + +// CHECK: define weak_odr void @_ZN1SIiE2S21hEv +template void S<int>::S2::h(); + +template <typename T> void S<T>::f() {} +template <typename T> void S<T>::g() {} +template <typename T> int S<T>::i; +template <typename T> void S<T>::S2::h() {} diff --git a/test/CodeGenCXX/expr.cpp b/test/CodeGenCXX/expr.cpp index d92cfb4..33e8e63 100644 --- a/test/CodeGenCXX/expr.cpp +++ b/test/CodeGenCXX/expr.cpp @@ -14,3 +14,24 @@ void test1() { // PR5514 int a; void test2() { ++a+=10; } + +// PR7892 +int test3(const char*); +int test3g = test3(__PRETTY_FUNCTION__); + + +// PR7889 +struct test4A { + int j : 2; +}; +int test4() { + test4A a; + (a.j = 2) = 3; +} + +// Incomplete type in conditional operator. +// Check operations on incomplete types. +struct s5; +struct s5 &f5_0(bool cond, struct s5 &a, struct s5 &b) { + return cond ? a : b; +} diff --git a/test/CodeGenCXX/global-init.cpp b/test/CodeGenCXX/global-init.cpp index 8ee087e..6ff9598 100644 --- a/test/CodeGenCXX/global-init.cpp +++ b/test/CodeGenCXX/global-init.cpp @@ -14,6 +14,9 @@ struct D { ~D(); }; // CHECK: @c = global %struct.C zeroinitializer, align 8 +// It's okay if we ever implement the IR-generation optimization to remove this. +// CHECK: @_ZN5test3L3varE = internal constant i8* getelementptr inbounds ([7 x i8]* + // CHECK: call void @_ZN1AC1Ev(%struct.A* @a) // CHECK: call i32 @__cxa_atexit(void (i8*)* bitcast (void (%struct.A*)* @_ZN1AD1Ev to void (i8*)*), i8* getelementptr inbounds (%struct.A* @a, i32 0, i32 0), i8* bitcast (i8** @__dso_handle to i8*)) A a; @@ -29,7 +32,52 @@ 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; +// <rdar://problem/7458115> +namespace test1 { + int f(); + const int x = f(); // This has side-effects and gets emitted immediately. + const int y = x - 1; // This gets deferred. + const int z = ~y; // This also gets deferred, but gets "undeferred" before y. + int test() { return z; } +// CHECK: define i32 @_ZN5test14testEv() + + // All of these initializers end up delayed, so we check them later. +} + +// <rdar://problem/8246444> +namespace test2 { + struct allocator { allocator(); ~allocator(); }; + struct A { A(const allocator &a = allocator()); ~A(); }; + + A a; +// CHECK: call void @_ZN5test29allocatorC1Ev( +// CHECK: invoke void @_ZN5test21AC1ERKNS_9allocatorE( +// CHECK: call void @_ZN5test29allocatorD1Ev( +// CHECK: call i32 @__cxa_atexit({{.*}} @_ZN5test21AD1Ev {{.*}} @_ZN5test21aE +} + +namespace test3 { + // Tested at the beginning of the file. + const char * const var = "string"; + extern const char * const var; + + const char *test() { return var; } +} + +// CHECK: define internal void [[TEST1_Z_INIT:@.*]]() +// CHECK: load i32* @_ZN5test1L1yE +// CHECK-NEXT: xor +// CHECK-NEXT: store i32 {{.*}}, i32* @_ZN5test1L1zE +// CHECK: define internal void [[TEST1_Y_INIT:@.*]]() +// CHECK: load i32* @_ZN5test1L1xE +// CHECK-NEXT: sub +// CHECK-NEXT: store i32 {{.*}}, i32* @_ZN5test1L1yE + +// At the end of the file, we check that y is initialized before z. + // CHECK: define internal void @_GLOBAL__I_a() section "__TEXT,__StaticInit,regular,pure_instructions" { +// CHECK: call void [[TEST1_Y_INIT]] +// CHECK: call void [[TEST1_Z_INIT]] // 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/key-function-vtable.cpp b/test/CodeGenCXX/key-function-vtable.cpp index 1cfeb0c..15c058d 100644 --- a/test/CodeGenCXX/key-function-vtable.cpp +++ b/test/CodeGenCXX/key-function-vtable.cpp @@ -12,11 +12,11 @@ testb *testbvar = new testb; struct testc { virtual void a(); }; inline void testc::a() {} -// Key functions with inline specifier (PR5705) +// Functions with inline specifier are not key functions (PR5705) struct testd { inline virtual void a(); }; void testd::a() {} -// Key functions with inline specifier (PR5705) +// Functions with inline specifier are not key functions (PR5705) struct teste { inline virtual void a(); }; teste *testevar = new teste; diff --git a/test/CodeGenCXX/mangle-exprs.cpp b/test/CodeGenCXX/mangle-exprs.cpp index d68425f..73221718 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 i8 @_ZN5Casts1fILi6EEENS_1TIXT_EEEv + // CHECK: define weak_odr void @_ZN5Casts1fILi6EEENS_1TIXT_EEEv template T<6> f<6>(); } diff --git a/test/CodeGenCXX/mangle.cpp b/test/CodeGenCXX/mangle.cpp index 814a759..55357c7 100644 --- a/test/CodeGenCXX/mangle.cpp +++ b/test/CodeGenCXX/mangle.cpp @@ -507,3 +507,120 @@ namespace test13 { // CHECK: define weak_odr void @_ZN6test133fooINS_1BEEEvRKNS_1AIT_EE( template void foo(const A<B> &a); } + +namespace test14 { + extern "C" { + struct S { + static int a(), x; + }; + // CHECK: define i32 @_ZN6test141S1aEv + // CHECK: load i32* @_ZN6test141S1xE + int S::a() { return S::x; } + } +} + +// rdar://problem/8204122 +namespace test15 { + enum E { e = 3 }; + template <int I> struct S {}; + + template <int I> void f(S<I + e>) {} + + // CHECK: define weak_odr void @_ZN6test151fILi7EEEvNS_1SIXplT_LNS_1EE3EEEE( + template void f<7>(S<7 + e>); +} + +// rdar://problem/8125400. Don't crash. +namespace test16 { + static union {}; + static union { union {}; }; + static union { struct {}; }; + static union { union { union {}; }; }; + static union { union { struct {}; }; }; + static union { struct { union {}; }; }; + static union { struct { struct {}; }; }; +} + +// rdar://problem/8302148 +namespace test17 { + template <int N> struct A {}; + + struct B { + static int foo(void); + }; + + template <class T> A<sizeof(T::foo())> func(void); + + // CHECK: define void @_ZN6test174testEv() + // CHECK: call {{.*}} @_ZN6test174funcINS_1BEEENS_1AIXszclsrT_3fooEEEEv() + void test() { + func<B>(); + } +} + +// PR7891 +namespace test18 { + struct A { + int operator+(); + int operator-(); + int operator*(); + int operator&(); + }; + template <int (A::*)()> struct S {}; + + template <typename T> void f(S<&T::operator+>) {} + template void f<A>(S<&A::operator+>); + + template <typename T> void f(S<&T::operator- >) {} + template void f<A>(S<&A::operator- >); + + template <typename T> void f(S<&T::operator*>) {} + template void f<A>(S<&A::operator*>); + + template <typename T> void f(S<&T::operator&>) {} + template void f<A>(S<&A::operator&>); + + // CHECK: define weak_odr void @_ZN6test181fINS_1AEEEvNS_1SIXadsrT_plEEE + // CHECK: define weak_odr void @_ZN6test181fINS_1AEEEvNS_1SIXadsrT_miEEE + // CHECK: define weak_odr void @_ZN6test181fINS_1AEEEvNS_1SIXadsrT_mlEEE + // CHECK: define weak_odr void @_ZN6test181fINS_1AEEEvNS_1SIXadsrT_anEEE +} + +// rdar://problem/8332117 +namespace test19 { + struct A { + template <typename T> int f(); + int operator+(); + operator int(); + template <typename T> int operator-(); + }; + + template <int (A::*)()> struct S {}; + + template <typename T> void g (S<&T::template f<int> >) {} + template <typename T> void g (S<&T::operator+ >) {} + template <typename T> void g (S<&T::operator int>) {} + template <typename T> void g (S<&T::template operator- <double> >) {} + + // CHECK: define weak_odr void @_ZN6test191gINS_1AEEEvNS_1SIXadsrT_1fIiEEEE( + template void g<A>(S<&A::f<int> >); + // CHECK: define weak_odr void @_ZN6test191gINS_1AEEEvNS_1SIXadsrT_plEEE( + template void g<A>(S<&A::operator+>); + // CHECK: define weak_odr void @_ZN6test191gINS_1AEEEvNS_1SIXadsrT_cviEEE( + template void g<A>(S<&A::operator int>); + // CHECK: define weak_odr void @_ZN6test191gINS_1AEEEvNS_1SIXadsrT_miIdEEEE( + template void g<A>(S<&A::operator-<double> >); +} + +namespace test20 { + template <class T> T *f(const T&); + template <class T> T *f(T*); + + // CHECK: define weak_odr void @_ZN6test205test0IiEEvDTcl1fIPT_ELi0EEE( + template <class T> void test0(decltype(f<T*>(0))) {} + template void test0<int>(decltype(f<int*>(0))); + + // CHECK: define weak_odr void @_ZN6test205test1IiEEvDTcl1fIEcvT__EEE( + template <class T> void test1(decltype(f<>(T()))) {} + template void test1<int>(decltype(f<>(int()))); +} diff --git a/test/CodeGenCXX/member-function-pointers.cpp b/test/CodeGenCXX/member-function-pointers.cpp index e4beee1..78a571e 100644 --- a/test/CodeGenCXX/member-function-pointers.cpp +++ b/test/CodeGenCXX/member-function-pointers.cpp @@ -1,5 +1,6 @@ // RUN: %clang_cc1 %s -emit-llvm -o - -triple=x86_64-apple-darwin9 | FileCheck %s // RUN: %clang_cc1 %s -emit-llvm -o - -triple=i386-apple-darwin9 | FileCheck -check-prefix LP32 %s +// RUN: %clang_cc1 %s -emit-llvm -o - -triple=armv7-unknown-unknown | FileCheck -check-prefix ARM %s struct A { int a; void f(); virtual void vf1(); virtual void vf2(); }; struct B { int b; virtual void g(); }; @@ -28,50 +29,38 @@ void (C::*pc2)() = &C::f; void (A::*pc3)() = &A::vf1; void f() { - // CHECK: store i64 0, i64* getelementptr inbounds (%0* @pa, i32 0, i32 0) - // CHECK: store i64 0, i64* getelementptr inbounds (%0* @pa, i32 0, i32 1) + // CHECK: store %0 zeroinitializer, %0* @pa pa = 0; - // CHECK: volatile store i64 0, i64* getelementptr inbounds (%0* @vpa, i32 0, i32 0) - // CHECK: volatile store i64 0, i64* getelementptr inbounds (%0* @vpa, i32 0, i32 1) + // Is this okay? What are LLVM's volatile semantics for structs? + // CHECK: volatile store %0 zeroinitializer, %0* @vpa vpa = 0; - // CHECK: store i64 {{.*}}, i64* getelementptr inbounds (%0* @pc, i32 0, i32 0) - // CHECK: [[ADJ:%[a-zA-Z0-9\.]+]] = add i64 {{.*}}, 16 - // CHECK: store i64 [[ADJ]], i64* getelementptr inbounds (%0* @pc, i32 0, i32 1) + // CHECK: [[TMP:%.*]] = load %0* @pa, align 8 + // CHECK: [[TMPADJ:%.*]] = extractvalue %0 [[TMP]], 1 + // CHECK: [[ADJ:%.*]] = add nsw i64 [[TMPADJ]], 16 + // CHECK: [[RES:%.*]] = insertvalue %0 [[TMP]], i64 [[ADJ]], 1 + // CHECK: store %0 [[RES]], %0* @pc, align 8 pc = pa; - // CHECK: store i64 {{.*}}, i64* getelementptr inbounds (%0* @pa, i32 0, i32 0) - // CHECK: [[ADJ:%[a-zA-Z0-9\.]+]] = sub i64 {{.*}}, 16 - // CHECK: store i64 [[ADJ]], i64* getelementptr inbounds (%0* @pa, i32 0, i32 1) + // CHECK: [[TMP:%.*]] = load %0* @pc, align 8 + // CHECK: [[TMPADJ:%.*]] = extractvalue %0 [[TMP]], 1 + // CHECK: [[ADJ:%.*]] = sub nsw i64 [[TMPADJ]], 16 + // CHECK: [[RES:%.*]] = insertvalue %0 [[TMP]], i64 [[ADJ]], 1 + // CHECK: store %0 [[RES]], %0* @pa, align 8 pa = static_cast<void (A::*)()>(pc); } void f2() { - // CHECK: [[pa2ptr:%[a-zA-Z0-9\.]+]] = getelementptr inbounds %0* %pa2, i32 0, i32 0 - // CHECK: store i64 ptrtoint (void (%struct.A*)* @_ZN1A1fEv to i64), i64* [[pa2ptr]] - // CHECK: [[pa2adj:%[a-zA-Z0-9\.]+]] = getelementptr inbounds %0* %pa2, i32 0, i32 1 - // CHECK: store i64 0, i64* [[pa2adj]] + // CHECK: store %0 { i64 ptrtoint (void (%struct.A*)* @_ZN1A1fEv to i64), i64 0 } void (A::*pa2)() = &A::f; - // CHECK: [[pa3ptr:%[a-zA-Z0-9\.]+]] = getelementptr inbounds %0* %pa3, i32 0, i32 0 - // CHECK: store i64 1, i64* [[pa3ptr]] - // CHECK: [[pa3adj:%[a-zA-Z0-9\.]+]] = getelementptr inbounds %0* %pa3, i32 0, i32 1 - // CHECK: store i64 0, i64* [[pa3adj]] - // CHECK-LP32: [[pa3ptr:%[a-zA-Z0-9\.]+]] = getelementptr inbounds %0* %pa3, i32 0, i32 0 - // CHECK-LP32: store i32 1, i32* [[pa3ptr]] - // CHECK-LP32: [[pa3adj:%[a-zA-Z0-9\.]+]] = getelementptr inbounds %0* %pa3, i32 0, i32 1 - // CHECK-LP32: store i32 0, i32* [[pa3adj]] + // CHECK: store %0 { i64 1, i64 0 } + // CHECK-LP32: store %0 { i32 1, i32 0 } void (A::*pa3)() = &A::vf1; - // CHECK: [[pa4ptr:%[a-zA-Z0-9\.]+]] = getelementptr inbounds %0* %pa4, i32 0, i32 0 - // CHECK: store i64 9, i64* [[pa4ptr]] - // CHECK: [[pa4adj:%[a-zA-Z0-9\.]+]] = getelementptr inbounds %0* %pa4, i32 0, i32 1 - // CHECK: store i64 0, i64* [[pa4adj]] - // CHECK-LP32: [[pa4ptr:%[a-zA-Z0-9\.]+]] = getelementptr inbounds %0* %pa4, i32 0, i32 0 - // CHECK-LP32: store i32 5, i32* [[pa4ptr]] - // CHECK-LP32: [[pa4adj:%[a-zA-Z0-9\.]+]] = getelementptr inbounds %0* %pa4, i32 0, i32 1 - // CHECK-LP32: store i32 0, i32* [[pa4adj]] + // CHECK: store %0 { i64 9, i64 0 } + // CHECK-LP32: store %0 { i32 5, i32 0 } void (A::*pa4)() = &A::vf2; } @@ -190,3 +179,33 @@ namespace PR7027 { struct X { void test( ); }; void testX() { &X::test; } } + +namespace test7 { + struct A { void foo(); virtual void vfoo(); }; + struct B { void foo(); virtual void vfoo(); }; + struct C : A, B { void foo(); virtual void vfoo(); }; + + // CHECK-ARM: @_ZN5test74ptr0E = global {{.*}} { i32 ptrtoint ({{.*}}* @_ZN5test71A3fooEv to i32), i32 0 } + // CHECK-ARM: @_ZN5test74ptr1E = global {{.*}} { i32 ptrtoint ({{.*}}* @_ZN5test71B3fooEv to i32), i32 8 } + // CHECK-ARM: @_ZN5test74ptr2E = global {{.*}} { i32 ptrtoint ({{.*}}* @_ZN5test71C3fooEv to i32), i32 0 } + // CHECK-ARM: @_ZN5test74ptr3E = global {{.*}} { i32 0, i32 1 } + // CHECK-ARM: @_ZN5test74ptr4E = global {{.*}} { i32 0, i32 9 } + // CHECK-ARM: @_ZN5test74ptr5E = global {{.*}} { i32 0, i32 1 } + void (C::*ptr0)() = &A::foo; + void (C::*ptr1)() = &B::foo; + void (C::*ptr2)() = &C::foo; + void (C::*ptr3)() = &A::vfoo; + void (C::*ptr4)() = &B::vfoo; + void (C::*ptr5)() = &C::vfoo; +} + +namespace test8 { + struct X { }; + typedef int (X::*pmf)(int); + + // CHECK: {{define.*_ZN5test81fEv}} + pmf f() { + // CHECK: {{ret.*zeroinitializer}} + return pmf(); + } +} diff --git a/test/CodeGenCXX/member-functions.cpp b/test/CodeGenCXX/member-functions.cpp index b363552..a60d24a 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 i8 @_ZN1TplERKS_" %t + // RUN: grep "call void @_ZN1TplERKS_" %t T result = t1 + t2; } diff --git a/test/CodeGenCXX/member-qual-debug-info.cpp b/test/CodeGenCXX/member-qual-debug-info.cpp deleted file mode 100644 index c6e0991..0000000 --- a/test/CodeGenCXX/member-qual-debug-info.cpp +++ /dev/null @@ -1,20 +0,0 @@ -// RUN: %clang_cc1 -g -S -masm-verbose -x c++ -o %t %s -// RUN: grep DW_TAG_volatile_type %t | count 3 -// RUN: grep DW_TAG_const_type %t | count 3 -// one for decl, one for def, one for abbrev - -namespace A { - class B { - public: - void dump() const volatile; - }; -} - -int main () { - using namespace A; - B b; - return 0; -} - -void A::B::dump() const volatile{ -} diff --git a/test/CodeGenCXX/new.cpp b/test/CodeGenCXX/new.cpp index 885158f..10a6f7f 100644 --- a/test/CodeGenCXX/new.cpp +++ b/test/CodeGenCXX/new.cpp @@ -73,6 +73,10 @@ void t8(int n) { new U[n]; } +// noalias +// CHECK: declare noalias i8* @_Znam +void *operator new[](size_t); + void t9() { bool b; @@ -90,19 +94,72 @@ A* t10() { return new(1, 2, 3.45, 100) A; } +// CHECK: define void @_Z3t11i struct B { int a; }; -void t11() { +struct Bmemptr { int Bmemptr::* memptr; int a; }; + +void t11(int n) { // CHECK: call noalias i8* @_Znwm // CHECK: call void @llvm.memset.p0i8.i64( B* b = new B(); + + // CHECK: call noalias i8* @_Znam + // CHECK: {{call void.*llvm.memset.p0i8.i64.*i8 0, i64 %}} + B *b2 = new B[n](); + + // CHECK: call noalias i8* @_Znam + // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64 + // CHECK: br + Bmemptr *b_memptr = new Bmemptr[n](); + + // CHECK: ret void } struct Empty { }; // We don't need to initialize an empty class. +// CHECK: define void @_Z3t12v void t12() { - // CHECK: define void @_Z3t12v - // CHECK-NOT: br label - // CHECK: ret void + // CHECK: call noalias i8* @_Znam + // CHECK-NOT: br (void)new Empty[10]; + + // CHECK: call noalias i8* @_Znam + // CHECK-NOT: br + (void)new Empty[10](); + + // CHECK: ret void +} + +// Zero-initialization +// CHECK: define void @_Z3t13i +void t13(int n) { + // CHECK: call noalias i8* @_Znwm + // CHECK: store i32 0, i32* + (void)new int(); + + // CHECK: call noalias i8* @_Znam + // CHECK: {{call void.*llvm.memset.p0i8.i64.*i8 0, i64 %}} + (void)new int[n](); + + // CHECK-NEXT: ret void +} + +struct Alloc{ + int x; + void* operator new[](size_t size); + void operator delete[](void* p); + ~Alloc(); +}; + +void f() { + // CHECK: call i8* @_ZN5AllocnaEm(i64 808) + // CHECK: store i64 200 + // CHECK: call void @_ZN5AllocD1Ev( + // CHECK: call void @_ZN5AllocdaEPv(i8* + delete[] new Alloc[10][20]; + // CHECK: call noalias i8* @_Znwm + // CHECK: call void @_ZdlPv(i8* + delete new bool; + // CHECK: ret void } diff --git a/test/CodeGenCXX/nonconst-init.cpp b/test/CodeGenCXX/nonconst-init.cpp new file mode 100644 index 0000000..21129b9 --- /dev/null +++ b/test/CodeGenCXX/nonconst-init.cpp @@ -0,0 +1,5 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm -o - %s | FileCheck %s + +int a(); +// CHECK: call i32 @_Z1av() +struct x {int x, y : 10;} x = {1, a()}; diff --git a/test/CodeGenCXX/operator-new.cpp b/test/CodeGenCXX/operator-new.cpp index f718fae..db56cda 100644 --- a/test/CodeGenCXX/operator-new.cpp +++ b/test/CodeGenCXX/operator-new.cpp @@ -11,7 +11,19 @@ public: }; void f1() { - // CHECK-SANE: declare noalias i8* @_Znwj( - // CHECK-SANENOT: declare i8* @_Znwj( + // SANE: declare noalias i8* @_Znwj( + // SANENOT: declare i8* @_Znwj( new teste(); } + + +// rdar://5739832 - operator new should check for overflow in multiply. +void *f2(long N) { + return new int[N]; + +// SANE: [[UWO:%.*]] = call {{.*}} @llvm.umul.with.overflow +// SANE-NEXT: [[OVER:%.*]] = extractvalue {{.*}} [[UWO]], 1 +// SANE-NEXT: [[SUM:%.*]] = extractvalue {{.*}} [[UWO]], 0 +// SANE-NEXT: [[RESULT:%.*]] = select i1 [[OVER]], i32 -1, i32 [[SUM]] +// SANE-NEXT: call noalias i8* @_Znaj(i32 [[RESULT]]) +} diff --git a/test/CodeGenCXX/pointers-to-data-members.cpp b/test/CodeGenCXX/pointers-to-data-members.cpp index 70308c6..38c7d28 100644 --- a/test/CodeGenCXX/pointers-to-data-members.cpp +++ b/test/CodeGenCXX/pointers-to-data-members.cpp @@ -65,15 +65,21 @@ int A::*pa; int C::*pc; void f() { - // CHECK: store i64 -1, i64* @_ZN5Casts2paE + // CHECK: store i64 -1, i64* @_ZN5Casts2paE pa = 0; - // CHECK: [[ADJ:%[a-zA-Z0-9\.]+]] = add nsw i64 {{.*}}, 4 - // CHECK: store i64 [[ADJ]], i64* @_ZN5Casts2pcE + // CHECK-NEXT: [[TMP:%.*]] = load i64* @_ZN5Casts2paE, align 8 + // CHECK-NEXT: [[ADJ:%.*]] = add nsw i64 [[TMP]], 4 + // CHECK-NEXT: [[ISNULL:%.*]] = icmp eq i64 [[TMP]], -1 + // CHECK-NEXT: [[RES:%.*]] = select i1 [[ISNULL]], i64 [[TMP]], i64 [[ADJ]] + // CHECK-NEXT: store i64 [[RES]], i64* @_ZN5Casts2pcE pc = pa; - // CHECK: [[ADJ:%[a-zA-Z0-9\.]+]] = sub nsw i64 {{.*}}, 4 - // CHECK: store i64 [[ADJ]], i64* @_ZN5Casts2paE + // CHECK-NEXT: [[TMP:%.*]] = load i64* @_ZN5Casts2pcE, align 8 + // CHECK-NEXT: [[ADJ:%.*]] = sub nsw i64 [[TMP]], 4 + // CHECK-NEXT: [[ISNULL:%.*]] = icmp eq i64 [[TMP]], -1 + // CHECK-NEXT: [[RES:%.*]] = select i1 [[ISNULL]], i64 [[TMP]], i64 [[ADJ]] + // CHECK-NEXT: store i64 [[RES]], i64* @_ZN5Casts2paE pa = static_cast<int A::*>(pc); } @@ -183,3 +189,17 @@ struct A { A a; } + +namespace BoolPtrToMember { + struct X { + bool member; + }; + + // CHECK: define i8* @_ZN15BoolPtrToMember1fERNS_1XEMS0_b + bool &f(X &x, bool X::*member) { + // CHECK: {{bitcast.* to i8\*}} + // CHECK-NEXT: getelementptr inbounds i8* + // CHECK-NEXT: ret i8* + return x.*member; + } +} diff --git a/test/CodeGenCXX/pragma-visibility.cpp b/test/CodeGenCXX/pragma-visibility.cpp new file mode 100644 index 0000000..05de786 --- /dev/null +++ b/test/CodeGenCXX/pragma-visibility.cpp @@ -0,0 +1,72 @@ +// RUN: %clang_cc1 -emit-llvm -o - %s | FileCheck %s + +#pragma GCC visibility push(hidden) +struct x { + static int y; +}; +#pragma GCC visibility pop +int x::y = 10; +// CHECK: @_ZN1x1yE = hidden global + +#pragma GCC visibility push(hidden) +struct __attribute((visibility("default"))) x2 { + static int y; +}; +int x2::y = 10; +// CHECK: @_ZN2x21yE = global +#pragma GCC visibility pop + +#pragma GCC visibility push(hidden) +struct x3 { + static int y; +} __attribute((visibility("default"))); +int x3::y = 10; +// CHECK: @_ZN2x31yE = global +#pragma GCC visibility pop + +#pragma GCC visibility push(hidden) +template<class T> struct x4 { + static int y; +}; +#pragma GCC visibility pop +template<> int x4<int>::y = 10; +// CHECK: @_ZN2x4IiE1yE = hidden global i32 + +#pragma GCC visibility push(hidden) +template<int x> int f() { return x; } +extern "C" int g() { return f<3>(); } +#pragma GCC visibility pop +// CHECK: define hidden i32 @g() +// CHECK: define linkonce_odr hidden i32 @_Z1fILi3EEiv() + +#pragma GCC visibility push(hidden) +template<class T> struct x5 { + void y(); +}; +#pragma GCC visibility pop +template<> void x5<int>::y() {} +// CHECK: define hidden void @_ZN2x5IiE1yEv + +#pragma GCC visibility push(hidden) +namespace n __attribute((visibility("default"))) { + void f() {} + // CHECK: define void @_ZN1n1fEv +} +#pragma GCC visibility pop + +namespace n __attribute((visibility("default"))) { + extern int foofoo; // FIXME: Shouldn't be necessary, but otherwise the pragma + // gets to Sema before the namespace! +#pragma GCC visibility push(hidden) + void g() {} + // CHECK: define hidden void @_ZN1n1gEv +#pragma GCC visibility pop +} + +namespace n __attribute((visibility("hidden"))) { + extern int foofoo; // FIXME: Shouldn't be necessary, but otherwise the pragma + // gets to Sema before the namespace! + #pragma GCC visibility pop + void h() {} + // CHECK: define void @_ZN1n1hEv +} diff --git a/test/CodeGenCXX/reference-cast.cpp b/test/CodeGenCXX/reference-cast.cpp new file mode 100644 index 0000000..585d1db --- /dev/null +++ b/test/CodeGenCXX/reference-cast.cpp @@ -0,0 +1,170 @@ +// RUN: %clang_cc1 -emit-llvm -triple x86_64-apple-darwin10 -o - %s | FileCheck %s + +// PR6024 +extern int i; + +// CHECK: define i32* @_Z16lvalue_noop_castv() nounwind +const int &lvalue_noop_cast() { + if (i == 0) + // CHECK: store i32 17, i32* + return (const int&)17; + else if (i == 1) + // CHECK: store i32 17, i32* + return static_cast<const int&>(17); + // CHECK: store i32 17, i32* + return 17; +} + +// CHECK: define i16* @_Z20lvalue_integral_castv() +const short &lvalue_integral_cast() { + if (i == 0) + // CHECK: store i16 17, i16* + return (const short&)17; + else if (i == 1) + // CHECK: store i16 17, i16* + return static_cast<const short&>(17); + // CHECK: store i16 17, i16* + return 17; +} + +// CHECK: define i16* @_Z29lvalue_floating_integral_castv() +const short &lvalue_floating_integral_cast() { + if (i == 0) + // CHECK: store i16 17, i16* + return (const short&)17.5; + else if (i == 1) + // CHECK: store i16 17, i16* + return static_cast<const short&>(17.5); + // CHECK: store i16 17, i16* + return 17.5; +} + +// CHECK: define float* @_Z29lvalue_integral_floating_castv() +const float &lvalue_integral_floating_cast() { + if (i == 0) + // CHECK: store float 1.700000e+{{0*}}1, float* + return (const float&)17; + else if (i == 1) + // CHECK: store float 1.700000e+{{0*}}1, float* + return static_cast<const float&>(17); + // CHECK: store float 1.700000e+{{0*}}1, float* + return 17; +} + +// CHECK: define float* @_Z20lvalue_floating_castv() +const float &lvalue_floating_cast() { + if (i == 0) + // CHECK: store float 1.700000e+{{0*}}1, float* + return (const float&)17.0; + else if (i == 1) + // CHECK: store float 1.700000e+{{0*}}1, float* + return static_cast<const float&>(17.0); + // CHECK: store float 1.700000e+{{0*}}1, float* + return 17.0; +} + +int get_int(); + +// CHECK: define i8* @_Z24lvalue_integer_bool_castv() +const bool &lvalue_integer_bool_cast() { + if (i == 0) + // CHECK: call i32 @_Z7get_intv() + // CHECK: store i8 + return (const bool&)get_int(); + else if (i == 1) + // CHECK: call i32 @_Z7get_intv() + // CHECK: store i8 + return static_cast<const bool&>(get_int()); + // CHECK: call i32 @_Z7get_intv() + // CHECK: store i8 + return get_int(); +} + +float get_float(); + +// CHECK: define i8* @_Z25lvalue_floating_bool_castv() +const bool &lvalue_floating_bool_cast() { + if (i == 0) + // CHECK: call float @_Z9get_floatv() + // CHECK: fcmp une float + // CHECK: store i8 + return (const bool&)get_float(); + else if (i == 1) + // CHECK: call float @_Z9get_floatv() + // CHECK: fcmp une float + // CHECK: store i8 + return static_cast<const bool&>(get_float()); + // CHECK: call float @_Z9get_floatv() + // CHECK: fcmp une float + // CHECK: store i8 + return get_float(); +} + +struct X { }; +typedef int X::*pm; +typedef int (X::*pmf)(int); + +pm get_pointer_to_member_data(); +pmf get_pointer_to_member_function(); + +// CHECK: define i8* @_Z26lvalue_ptrmem_to_bool_castv() +const bool &lvalue_ptrmem_to_bool_cast() { + if (i == 0) + // CHECK: call i64 @_Z26get_pointer_to_member_datav() + // CHECK: store i8 + // CHECK: store i8* + return (const bool&)get_pointer_to_member_data(); + else if (i == 1) + // CHECK: call i64 @_Z26get_pointer_to_member_datav() + // CHECK: store i8 + // CHECK: store i8* + return static_cast<const bool&>(get_pointer_to_member_data()); + // CHECK: call i64 @_Z26get_pointer_to_member_datav() + // CHECK: store i8 + // CHECK: store i8* + return get_pointer_to_member_data(); +} + +// CHECK: define i8* @_Z27lvalue_ptrmem_to_bool_cast2v +const bool &lvalue_ptrmem_to_bool_cast2() { + if (i == 0) + // CHECK: {{call.*_Z30get_pointer_to_member_functionv}} + // CHECK: store i8 + // CHECK: store i8* + return (const bool&)get_pointer_to_member_function(); + else if (i == 1) + // CHECK: {{call.*_Z30get_pointer_to_member_functionv}} + // CHECK: store i8 + // CHECK: store i8* + return static_cast<const bool&>(get_pointer_to_member_function()); + // CHECK: {{call.*_Z30get_pointer_to_member_functionv}} + // CHECK: store i8 + // CHECK: store i8* + return get_pointer_to_member_function(); +} + +_Complex double get_complex_double(); + +// CHECK: {{define.*_Z2f1v}} +const _Complex float &f1() { + if (i == 0) + // CHECK: {{call.*_Z18get_complex_doublev}} + // CHECK: fptrunc + // CHECK: fptrunc + // CHECK: store float + // CHECK: store float + return (const _Complex float&)get_complex_double(); + else if (i == 1) + // CHECK: {{call.*_Z18get_complex_doublev}} + // CHECK: fptrunc + // CHECK: fptrunc + // CHECK: store float + // CHECK: store float + return static_cast<const _Complex float&>(get_complex_double()); + // CHECK: {{call.*_Z18get_complex_doublev}} + // CHECK: fptrunc + // CHECK: fptrunc + // CHECK: store float + // CHECK: store float + return get_complex_double(); +} diff --git a/test/CodeGenCXX/rtti-fundamental.cpp b/test/CodeGenCXX/rtti-fundamental.cpp index 6826321..7f80d99 100644 --- a/test/CodeGenCXX/rtti-fundamental.cpp +++ b/test/CodeGenCXX/rtti-fundamental.cpp @@ -14,60 +14,60 @@ namespace __cxxabiv1 { __fundamental_type_info::~__fundamental_type_info() { } } -// CHECK: @_ZTIv = weak_odr constant -// CHECK: @_ZTIPv = weak_odr constant -// CHECK: @_ZTIPKv = weak_odr constant -// CHECK: @_ZTIDi = weak_odr constant -// CHECK: @_ZTIPDi = weak_odr constant -// CHECK: @_ZTIPKDi = weak_odr constant -// CHECK: @_ZTIDs = weak_odr constant -// CHECK: @_ZTIPDs = weak_odr constant -// CHECK: @_ZTIPKDs = weak_odr constant -// CHECK: @_ZTIy = weak_odr constant -// CHECK: @_ZTIPy = weak_odr constant -// CHECK: @_ZTIPKy = weak_odr constant -// CHECK: @_ZTIx = weak_odr constant -// CHECK: @_ZTIPx = weak_odr constant -// CHECK: @_ZTIPKx = weak_odr constant -// CHECK: @_ZTIw = weak_odr constant -// CHECK: @_ZTIPw = weak_odr constant -// CHECK: @_ZTIPKw = weak_odr constant -// CHECK: @_ZTIt = weak_odr constant -// CHECK: @_ZTIPt = weak_odr constant -// CHECK: @_ZTIPKt = weak_odr constant -// CHECK: @_ZTIs = weak_odr constant -// CHECK: @_ZTIPs = weak_odr constant -// CHECK: @_ZTIPKs = weak_odr constant -// CHECK: @_ZTIm = weak_odr constant -// CHECK: @_ZTIPm = weak_odr constant -// CHECK: @_ZTIPKm = weak_odr constant -// CHECK: @_ZTIl = weak_odr constant -// CHECK: @_ZTIPl = weak_odr constant -// CHECK: @_ZTIPKl = weak_odr constant -// CHECK: @_ZTIj = weak_odr constant -// CHECK: @_ZTIPj = weak_odr constant -// CHECK: @_ZTIPKj = weak_odr constant -// CHECK: @_ZTIi = weak_odr constant -// CHECK: @_ZTIPi = weak_odr constant -// CHECK: @_ZTIPKi = weak_odr constant -// CHECK: @_ZTIh = weak_odr constant -// CHECK: @_ZTIPh = weak_odr constant -// CHECK: @_ZTIPKh = weak_odr constant -// CHECK: @_ZTIf = weak_odr constant -// CHECK: @_ZTIPf = weak_odr constant -// CHECK: @_ZTIPKf = weak_odr constant -// CHECK: @_ZTIe = weak_odr constant -// CHECK: @_ZTIPe = weak_odr constant -// CHECK: @_ZTIPKe = weak_odr constant -// CHECK: @_ZTId = weak_odr constant -// CHECK: @_ZTIPd = weak_odr constant -// CHECK: @_ZTIPKd = weak_odr constant -// CHECK: @_ZTIc = weak_odr constant -// CHECK: @_ZTIPc = weak_odr constant -// CHECK: @_ZTIPKc = weak_odr constant -// CHECK: @_ZTIb = weak_odr constant -// CHECK: @_ZTIPb = weak_odr constant -// CHECK: @_ZTIPKb = weak_odr constant -// CHECK: @_ZTIa = weak_odr constant -// CHECK: @_ZTIPa = weak_odr constant -// CHECK: @_ZTIPKa = weak_odr constant +// CHECK: @_ZTIv = constant +// CHECK: @_ZTIPv = constant +// CHECK: @_ZTIPKv = constant +// CHECK: @_ZTIDi = constant +// CHECK: @_ZTIPDi = constant +// CHECK: @_ZTIPKDi = constant +// CHECK: @_ZTIDs = constant +// CHECK: @_ZTIPDs = constant +// CHECK: @_ZTIPKDs = constant +// CHECK: @_ZTIy = constant +// CHECK: @_ZTIPy = constant +// CHECK: @_ZTIPKy = constant +// CHECK: @_ZTIx = constant +// CHECK: @_ZTIPx = constant +// CHECK: @_ZTIPKx = constant +// CHECK: @_ZTIw = constant +// CHECK: @_ZTIPw = constant +// CHECK: @_ZTIPKw = constant +// CHECK: @_ZTIt = constant +// CHECK: @_ZTIPt = constant +// CHECK: @_ZTIPKt = constant +// CHECK: @_ZTIs = constant +// CHECK: @_ZTIPs = constant +// CHECK: @_ZTIPKs = constant +// CHECK: @_ZTIm = constant +// CHECK: @_ZTIPm = constant +// CHECK: @_ZTIPKm = constant +// CHECK: @_ZTIl = constant +// CHECK: @_ZTIPl = constant +// CHECK: @_ZTIPKl = constant +// CHECK: @_ZTIj = constant +// CHECK: @_ZTIPj = constant +// CHECK: @_ZTIPKj = constant +// CHECK: @_ZTIi = constant +// CHECK: @_ZTIPi = constant +// CHECK: @_ZTIPKi = constant +// CHECK: @_ZTIh = constant +// CHECK: @_ZTIPh = constant +// CHECK: @_ZTIPKh = constant +// CHECK: @_ZTIf = constant +// CHECK: @_ZTIPf = constant +// CHECK: @_ZTIPKf = constant +// CHECK: @_ZTIe = constant +// CHECK: @_ZTIPe = constant +// CHECK: @_ZTIPKe = constant +// CHECK: @_ZTId = constant +// CHECK: @_ZTIPd = constant +// CHECK: @_ZTIPKd = constant +// CHECK: @_ZTIc = constant +// CHECK: @_ZTIPc = constant +// CHECK: @_ZTIPKc = constant +// CHECK: @_ZTIb = constant +// CHECK: @_ZTIPb = constant +// CHECK: @_ZTIPKb = constant +// CHECK: @_ZTIa = constant +// CHECK: @_ZTIPa = constant +// CHECK: @_ZTIPKa = constant diff --git a/test/CodeGenCXX/rtti-linkage.cpp b/test/CodeGenCXX/rtti-linkage.cpp index f8c1167..efa336d 100644 --- a/test/CodeGenCXX/rtti-linkage.cpp +++ b/test/CodeGenCXX/rtti-linkage.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -emit-llvm -o - | sort | FileCheck %s +// RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -fhidden-weak-vtables -emit-llvm -o - | sort | FileCheck %s // FIXME: Fails on Win32, dunno why. // XFAIL: win32 @@ -11,13 +11,16 @@ -// CHECK: _ZTI1A = weak_odr constant +// CHECK: _ZTI1A = weak_odr hidden constant // CHECK: _ZTI1B = constant // CHECK: _ZTI1C = internal constant -// CHECK: _ZTIA10_i = weak_odr constant +// CHECK: _ZTI1TILj0EE = weak_odr constant +// CHECK: _ZTI1TILj1EE = weak_odr constant +// CHECK: _ZTI1TILj2EE = external constant +// CHECK: _ZTIA10_i = weak_odr hidden constant // CHECK: _ZTIFN12_GLOBAL__N_11DEvE = internal constant // CHECK: _ZTIFvN12_GLOBAL__N_11DEE = internal constant -// CHECK: _ZTIFvvE = weak_odr +// CHECK: _ZTIFvvE = weak_odr hidden constant // CHECK: _ZTIM1A1C = internal constant // CHECK: _ZTIM1AP1C = internal constant // CHECK: _ZTIM1CPS_ = internal constant @@ -26,7 +29,7 @@ // CHECK: _ZTIN12_GLOBAL__N_11DE = internal constant // CHECK: _ZTIN12_GLOBAL__N_11EE = internal constant // CHECK: _ZTIP1C = internal constant -// CHECK: _ZTIPFvvE = weak_odr constant +// CHECK: _ZTIPFvvE = weak_odr hidden constant // CHECK: _ZTIPM1Ci = internal constant // CHECK: _ZTIPN12_GLOBAL__N_11DE = internal constant // CHECK: _ZTIPP1C = internal constant @@ -118,3 +121,14 @@ namespace Arrays { return typeid(A::a); } } + +template <unsigned N> class T { + virtual void anchor() {} +}; +template class T<1>; +template <> class T<2> { virtual void anchor(); }; +void t3() { + (void) typeid(T<0>); + (void) typeid(T<1>); + (void) typeid(T<2>); +} diff --git a/test/CodeGenCXX/static-init-2.cpp b/test/CodeGenCXX/static-init-2.cpp index 7eb4a7d..65ab3bb 100644 --- a/test/CodeGenCXX/static-init-2.cpp +++ b/test/CodeGenCXX/static-init-2.cpp @@ -3,4 +3,4 @@ // Make sure we don't crash generating y; its value is constant, but the // initializer has side effects, so EmitConstantExpr should fail. int x(); -int y = x() && 0; // expected-warning {{use of logical && with constant operand}} +int y = x() && 0; diff --git a/test/CodeGenCXX/template-anonymous-types.cpp b/test/CodeGenCXX/template-anonymous-types.cpp new file mode 100644 index 0000000..5e7a71f --- /dev/null +++ b/test/CodeGenCXX/template-anonymous-types.cpp @@ -0,0 +1,37 @@ +// RUN: %clang_cc1 %s -triple x86_64-unknown-linux-gnu -emit-llvm -o - | FileCheck %s + +struct S { + enum { FOO = 42 }; + enum { BAR = 42 }; +}; + +template <typename T> struct X { + T value; + X(T t) : value(t) {} + int f() { return value; } +}; + +template <typename T> int f(T t) { + X<T> x(t); + return x.f(); +} + +void test() { + // Look for two instantiations, entirely internal to this TU, one for FOO's + // type and one for BAR's. + // CHECK: define internal i32 @"_Z1fIN1S3$_0EEiT_"(i32 %t) + (void)f(S::FOO); + // CHECK: define internal i32 @"_Z1fIN1S3$_1EEiT_"(i32 %t) + (void)f(S::BAR); + + // Now check for the class template instantiations. Annoyingly, they are in + // reverse order. + // + // BAR's instantiation of X: + // CHECK: define internal i32 @"_ZN1XIN1S3$_1EE1fEv"(%struct.X* %this) + // CHECK: define internal void @"_ZN1XIN1S3$_1EEC2ES1_"(%struct.X* %this, i32 %t) + // + // FOO's instantiation of X: + // CHECK: define internal i32 @"_ZN1XIN1S3$_0EE1fEv"(%struct.X* %this) + // CHECK: define internal void @"_ZN1XIN1S3$_0EEC2ES1_"(%struct.X* %this, i32 %t) +} diff --git a/test/CodeGenCXX/threadsafe-statics-exceptions.cpp b/test/CodeGenCXX/threadsafe-statics-exceptions.cpp index 17c1030..c91590f 100644 --- a/test/CodeGenCXX/threadsafe-statics-exceptions.cpp +++ b/test/CodeGenCXX/threadsafe-statics-exceptions.cpp @@ -17,7 +17,7 @@ void f() { static X x; // CHECK: call i8* @__cxa_allocate_exception - // CHECK: invoke void @__cxa_throw + // CHECK: call void @__cxa_throw throw Y(); // Finally, the landing pad. diff --git a/test/CodeGenCXX/thunks.cpp b/test/CodeGenCXX/thunks.cpp index 1de5761..ba60385 100644 --- a/test/CodeGenCXX/thunks.cpp +++ b/test/CodeGenCXX/thunks.cpp @@ -1,4 +1,5 @@ // RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -fhidden-weak-vtables -emit-llvm -o - | FileCheck -check-prefix=HIDDEN %s namespace Test1 { @@ -246,6 +247,19 @@ namespace Test9 { } } +namespace Test10 { + struct A { virtual void foo(); }; + struct B { virtual void foo(); }; + struct C : A, B { void foo() {} }; + + // CHECK-HIDDEN: define linkonce_odr void @_ZN6Test101C3fooEv + // CHECK-HIDDEN: define linkonce_odr hidden void @_ZThn8_N6Test101C3fooEv + + void test() { + C c; + } +} + /**** The following has to go at the end of the file ****/ // This is from Test5: diff --git a/test/CodeGenCXX/uncode-string.cpp b/test/CodeGenCXX/uncode-string.cpp new file mode 100644 index 0000000..e543149 --- /dev/null +++ b/test/CodeGenCXX/uncode-string.cpp @@ -0,0 +1,6 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -o - %s | FileCheck %s +// rdar://8360841 + +wchar_t s[] = L"\u2722"; + +// CHECK: @s = global [8 x i8] c"\22'\00\00\00\00\00\00" diff --git a/test/CodeGenCXX/value-init.cpp b/test/CodeGenCXX/value-init.cpp index 35be159..c4eb1c8 100644 --- a/test/CodeGenCXX/value-init.cpp +++ b/test/CodeGenCXX/value-init.cpp @@ -49,3 +49,92 @@ void test_enum_holder_and_int() { enum_holder_and_int(); // CHECK-NEXT: ret void } + +// PR7834: don't crash. +namespace test1 { + struct A { + int A::*f; + A(); + A(const A&); + A &operator=(const A &); + }; + + struct B { + A base; + }; + + void foo() { + B(); + } +} + +namespace ptrmem { + struct S { + int mem1; + int S::*mem2; + }; + + // CHECK: define i32 @_ZN6ptrmem4testEPNS_1SE + int test(S *s) { + // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64 + // CHECK: getelementptr + // CHECK: ret + return s->*S().mem2; + } +} + +namespace zeroinit { + struct S { int i; }; + + // CHECK: define i32 @_ZN8zeroinit4testEv() + int test() { + // CHECK: call void @llvm.memset.p0i8.i64 + // CHECK: getelementptr + // CHECK: ret i32 + return S().i; + } + + struct X0 { + X0() { } + int x; + }; + + struct X1 : X0 { + int x1; + void f(); + }; + + // CHECK: define void @_ZN8zeroinit9testX0_X1Ev + void testX0_X1() { + // CHECK: call void @llvm.memset.p0i8.i64 + // CHECK-NEXT: call void @_ZN8zeroinit2X1C1Ev + // CHECK-NEXT: call void @_ZN8zeroinit2X11fEv + X1().f(); + } + + template<typename> + struct X2 : X0 { + int x2; + void f(); + }; + + template<typename> + struct X3 : X2<int> { + X3() : X2<int>() { } + }; + + + // CHECK: define void @_ZN8zeroinit9testX0_X3Ev + void testX0_X3() { + // CHECK-NOT: call void @llvm.memset + // CHECK: call void @_ZN8zeroinit2X3IiEC1Ev + // CHECK: call void @_ZN8zeroinit2X2IiE1fEv + // CHECK-NEXT: ret void + X3<int>().f(); + } + + // CHECK: define linkonce_odr void @_ZN8zeroinit2X3IiEC2Ev + // CHECK: call void @llvm.memset.p0i8.i64 + // CHECK-NEXT: call void @_ZN8zeroinit2X2IiEC2Ev + // CHECK-NEXT: ret void +} diff --git a/test/CodeGenCXX/virt-template-vtable.cpp b/test/CodeGenCXX/virt-template-vtable.cpp index b968f38..d60cfb9 100644 --- a/test/CodeGenCXX/virt-template-vtable.cpp +++ b/test/CodeGenCXX/virt-template-vtable.cpp @@ -10,4 +10,13 @@ class B : A<int> { }; B::B() {} +template class A<long>; + +extern template class A<short>; +template class A<short>; + + +// CHECK: @_ZTV1B = weak_odr constant +// CHECK: @_ZTV1AIlE = weak_odr constant +// CHECK: @_ZTV1AIsE = weak_odr constant // CHECK: @_ZTV1AIiE = weak_odr constant diff --git a/test/CodeGenCXX/volatile.cpp b/test/CodeGenCXX/volatile.cpp new file mode 100644 index 0000000..58f433f --- /dev/null +++ b/test/CodeGenCXX/volatile.cpp @@ -0,0 +1,35 @@ +// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s + +// Check that IR gen doesn't try to do an lvalue-to-rvalue conversion +// on a volatile reference result. rdar://problem/8338198 +namespace test0 { + struct A { + A(const A& t); + A& operator=(const A& t); + volatile A& operator=(const volatile A& t) volatile; + }; + + volatile A *array; + + // CHECK: define void @_ZN5test04testENS_1AE( + void test(A t) { + // CHECK: [[ARR:%.*]] = load [[A:%.*]]** @_ZN5test05arrayE, align 8 + // CHECK-NEXT: [[IDX:%.*]] = getelementptr inbounds [[A]]* [[ARR]], i64 0 + // CHECK-NEXT: [[TMP:%.*]] = call [[A]]* @_ZNV5test01AaSERVKS0_([[A]]* [[IDX]], [[A]]* [[T:%.*]]) + // CHECK-NEXT: ret void + array[0] = t; + } +} + +namespace test1 { + volatile int *x; + + // CHECK: define void @_ZN5test14testEv() + void test() { + // CHECK: [[TMP:%.*]] = load i32** @_ZN5test11xE, align 8 + // *** FIXME: no! bad! should not be loaded! *** + // CHECK-NEXT: [[TMP1:%.*]] = volatile load i32* [[TMP]] + // CHECK-NEXT: ret void + *x; + } +} diff --git a/test/CodeGenCXX/vtable-linkage.cpp b/test/CodeGenCXX/vtable-linkage.cpp index b3b6870..cf988d1 100644 --- a/test/CodeGenCXX/vtable-linkage.cpp +++ b/test/CodeGenCXX/vtable-linkage.cpp @@ -1,16 +1,21 @@ // RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -emit-llvm -o %t +// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -fhidden-weak-vtables -emit-llvm -o %t.hidden // RUN: FileCheck --check-prefix=CHECK-1 %s < %t // RUN: FileCheck --check-prefix=CHECK-2 %s < %t +// RUN: FileCheck --check-prefix=CHECK-2-HIDDEN %s < %t.hidden // RUN: FileCheck --check-prefix=CHECK-3 %s < %t // RUN: FileCheck --check-prefix=CHECK-4 %s < %t // RUN: FileCheck --check-prefix=CHECK-5 %s < %t +// RUN: FileCheck --check-prefix=CHECK-5-HIDDEN %s < %t.hidden // RUN: FileCheck --check-prefix=CHECK-6 %s < %t +// RUN: FileCheck --check-prefix=CHECK-6-HIDDEN %s < %t.hidden // RUN: FileCheck --check-prefix=CHECK-7 %s < %t // RUN: FileCheck --check-prefix=CHECK-8 %s < %t // RUN: FileCheck --check-prefix=CHECK-9 %s < %t // RUN: FileCheck --check-prefix=CHECK-10 %s < %t // RUN: FileCheck --check-prefix=CHECK-11 %s < %t // RUN: FileCheck --check-prefix=CHECK-12 %s < %t +// RUN: FileCheck --check-prefix=CHECK-13 %s < %t namespace { struct A { @@ -83,22 +88,27 @@ struct F<char> { template struct F<short>; extern template struct F<int>; -void use_F(F<char> &fc) { +void use_F() { + F<char> fc; + fc.foo(); F<int> fi; fi.foo(); F<long> fl; (void)fl; - fc.foo(); } // B has a key function that is not defined in this translation unit so its vtable // has external linkage. // CHECK-1: @_ZTV1B = external constant -// C has no key function, so its vtable should have weak_odr linkage. +// C has no key function, so its vtable should have weak_odr linkage +// and hidden visibility (rdar://problem/7523229). // CHECK-2: @_ZTV1C = weak_odr constant // CHECK-2: @_ZTS1C = weak_odr constant // CHECK-2: @_ZTI1C = weak_odr constant +// CHECK-2-HIDDEN: @_ZTV1C = weak_odr hidden constant +// CHECK-2-HIDDEN: @_ZTS1C = weak_odr constant +// CHECK-2-HIDDEN: @_ZTI1C = weak_odr hidden constant // D has a key function that is defined in this translation unit so its vtable is // defined in the translation unit. @@ -119,12 +129,18 @@ void use_F(F<char> &fc) { // CHECK-5: @_ZTV1EIsE = weak_odr constant // CHECK-5: @_ZTS1EIsE = weak_odr constant // CHECK-5: @_ZTI1EIsE = weak_odr constant +// CHECK-5-HIDDEN: @_ZTV1EIsE = weak_odr constant +// CHECK-5-HIDDEN: @_ZTS1EIsE = weak_odr constant +// CHECK-5-HIDDEN: @_ZTI1EIsE = weak_odr constant // F<short> is an explicit template instantiation without a key // function, so its vtable should have weak_odr linkage // CHECK-6: @_ZTV1FIsE = weak_odr constant // CHECK-6: @_ZTS1FIsE = weak_odr constant // CHECK-6: @_ZTI1FIsE = weak_odr constant +// CHECK-6-HIDDEN: @_ZTV1FIsE = weak_odr constant +// CHECK-6-HIDDEN: @_ZTS1FIsE = weak_odr constant +// CHECK-6-HIDDEN: @_ZTI1FIsE = weak_odr constant // E<long> is an implicit template instantiation with a key function // defined in this translation unit, so its vtable should have @@ -160,6 +176,12 @@ void use_F(F<char> &fc) { // CHECK-12: @_ZTSN12_GLOBAL__N_11AE = internal constant // CHECK-12: @_ZTIN12_GLOBAL__N_11AE = internal constant +// F<char> is an explicit specialization without a key function, so +// its vtable should have weak_odr linkage. +// CHECK-13: @_ZTV1FIcE = weak_odr constant +// CHECK-13: @_ZTS1FIcE = weak_odr constant +// CHECK-13: @_ZTI1FIcE = weak_odr constant + // RUN: FileCheck --check-prefix=CHECK-G %s < %t // // CHECK-G: @_ZTV1GIiE = weak_odr constant diff --git a/test/CodeGenCXX/vtt-layout.cpp b/test/CodeGenCXX/vtt-layout.cpp index d7d4227..814adf0 100644 --- a/test/CodeGenCXX/vtt-layout.cpp +++ b/test/CodeGenCXX/vtt-layout.cpp @@ -59,6 +59,6 @@ namespace Test4 { } // CHECK: @_ZTTN5Test11BE = constant [1 x i8*] [i8* bitcast (i8** getelementptr inbounds ([4 x i8*]* @_ZTVN5Test11BE, i64 0, i64 3) to i8*)] -// CHECK: @_ZTTN5Test41DE = weak_odr constant [19 x i8*] [i8* bitcast (i8** getelementptr inbounds ([25 x i8*]* @_ZTVN5Test41DE, i64 0, i64 6) to i8*), i8* bitcast (i8** getelementptr inbounds ([11 x i8*]* @_ZTCN5Test41DE0_NS_2C1E, i64 0, i64 4) to i8*), i8* bitcast (i8** getelementptr inbounds ([11 x i8*]* @_ZTCN5Test41DE0_NS_2C1E, i64 0, i64 7) to i8*), i8* bitcast (i8** getelementptr inbounds ([11 x i8*]* @_ZTCN5Test41DE0_NS_2C1E, i64 0, i64 10) to i8*), i8* bitcast (i8** getelementptr inbounds ([19 x i8*]* @_ZTCN5Test41DE16_NS_2C2E, i64 0, i64 7) to i8*), i8* bitcast (i8** getelementptr inbounds ([19 x i8*]* @_ZTCN5Test41DE16_NS_2C2E, i64 0, i64 7) to i8*), i8* bitcast (i8** getelementptr inbounds ([19 x i8*]* @_ZTCN5Test41DE16_NS_2C2E, i64 0, i64 12) to i8*), i8* bitcast (i8** getelementptr inbounds ([19 x i8*]* @_ZTCN5Test41DE16_NS_2C2E, i64 0, i64 15) to i8*), i8* bitcast (i8** getelementptr inbounds ([19 x i8*]* @_ZTCN5Test41DE16_NS_2C2E, i64 0, i64 18) to i8*), i8* bitcast (i8** getelementptr inbounds ([25 x i8*]* @_ZTVN5Test41DE, i64 0, i64 17) to i8*), i8* bitcast (i8** getelementptr inbounds ([25 x i8*]* @_ZTVN5Test41DE, i64 0, i64 20) to i8*), i8* bitcast (i8** getelementptr inbounds ([25 x i8*]* @_ZTVN5Test41DE, i64 0, i64 13) to i8*), i8* bitcast (i8** getelementptr inbounds ([25 x i8*]* @_ZTVN5Test41DE, i64 0, i64 13) to i8*), i8* bitcast (i8** getelementptr inbounds ([25 x i8*]* @_ZTVN5Test41DE, i64 1, i64 0) to i8*), i8* bitcast (i8** getelementptr inbounds ([7 x i8*]* @_ZTCN5Test41DE40_NS_2V1E, i64 0, i64 3) to i8*), i8* bitcast (i8** getelementptr inbounds ([7 x i8*]* @_ZTCN5Test41DE40_NS_2V1E, i64 0, i64 6) to i8*), i8* bitcast (i8** getelementptr inbounds ([11 x i8*]* @_ZTCN5Test41DE72_NS_2V2E, i64 0, i64 4) to i8*), i8* bitcast (i8** getelementptr inbounds ([11 x i8*]* @_ZTCN5Test41DE72_NS_2V2E, i64 0, i64 7) to i8*), i8* bitcast (i8** getelementptr inbounds ([11 x i8*]* @_ZTCN5Test41DE72_NS_2V2E, i64 0, i64 10) to i8*)] ; <[19 x i8*]*> [#uses=4] -// CHECK: @_ZTTN5Test31DE = weak_odr constant [13 x i8*] [i8* bitcast (i8** getelementptr inbounds ([19 x i8*]* @_ZTVN5Test31DE, i64 0, i64 5) to i8*), i8* bitcast (i8** getelementptr inbounds ([7 x i8*]* @_ZTCN5Test31DE0_NS_2C1E, i64 0, i64 3) to i8*), i8* bitcast (i8** getelementptr inbounds ([7 x i8*]* @_ZTCN5Test31DE0_NS_2C1E, i64 0, i64 6) to i8*), i8* bitcast (i8** getelementptr inbounds ([14 x i8*]* @_ZTCN5Test31DE16_NS_2C2E, i64 0, i64 6) to i8*), i8* bitcast (i8** getelementptr inbounds ([14 x i8*]* @_ZTCN5Test31DE16_NS_2C2E, i64 0, i64 6) to i8*), i8* bitcast (i8** getelementptr inbounds ([14 x i8*]* @_ZTCN5Test31DE16_NS_2C2E, i64 0, i64 10) to i8*), i8* bitcast (i8** getelementptr inbounds ([14 x i8*]* @_ZTCN5Test31DE16_NS_2C2E, i64 0, i64 13) to i8*), i8* bitcast (i8** getelementptr inbounds ([19 x i8*]* @_ZTVN5Test31DE, i64 0, i64 15) to i8*), i8* bitcast (i8** getelementptr inbounds ([19 x i8*]* @_ZTVN5Test31DE, i64 0, i64 11) to i8*), i8* bitcast (i8** getelementptr inbounds ([19 x i8*]* @_ZTVN5Test31DE, i64 0, i64 11) to i8*), i8* bitcast (i8** getelementptr inbounds ([19 x i8*]* @_ZTVN5Test31DE, i64 1, i64 0) to i8*), i8* bitcast (i8** getelementptr inbounds ([7 x i8*]* @_ZTCN5Test31DE64_NS_2V2E, i64 0, i64 3) to i8*), i8* bitcast (i8** getelementptr inbounds ([7 x i8*]* @_ZTCN5Test31DE64_NS_2V2E, i64 0, i64 6) to i8*)] ; <[13 x i8*]*> [#uses=3] -// CHECK: @_ZTTN5Test21CE = weak_odr constant [2 x i8*] [i8* bitcast (i8** getelementptr inbounds ([5 x i8*]* @_ZTVN5Test21CE, i64 0, i64 4) to i8*), i8* bitcast (i8** getelementptr inbounds ([5 x i8*]* @_ZTVN5Test21CE, i64 0, i64 4) to i8*)] ; <[2 x i8*]*> [#uses=0] +// CHECK: @_ZTTN5Test41DE = weak_odr constant [19 x i8*] [i8* bitcast (i8** getelementptr inbounds ([25 x i8*]* @_ZTVN5Test41DE, i64 0, i64 6) to i8*), i8* bitcast (i8** getelementptr inbounds ([11 x i8*]* @_ZTCN5Test41DE0_NS_2C1E, i64 0, i64 4) to i8*), i8* bitcast (i8** getelementptr inbounds ([11 x i8*]* @_ZTCN5Test41DE0_NS_2C1E, i64 0, i64 7) to i8*), i8* bitcast (i8** getelementptr inbounds ([11 x i8*]* @_ZTCN5Test41DE0_NS_2C1E, i64 0, i64 10) to i8*), i8* bitcast (i8** getelementptr inbounds ([19 x i8*]* @_ZTCN5Test41DE16_NS_2C2E, i64 0, i64 7) to i8*), i8* bitcast (i8** getelementptr inbounds ([19 x i8*]* @_ZTCN5Test41DE16_NS_2C2E, i64 0, i64 7) to i8*), i8* bitcast (i8** getelementptr inbounds ([19 x i8*]* @_ZTCN5Test41DE16_NS_2C2E, i64 0, i64 12) to i8*), i8* bitcast (i8** getelementptr inbounds ([19 x i8*]* @_ZTCN5Test41DE16_NS_2C2E, i64 0, i64 15) to i8*), i8* bitcast (i8** getelementptr inbounds ([19 x i8*]* @_ZTCN5Test41DE16_NS_2C2E, i64 0, i64 18) to i8*), i8* bitcast (i8** getelementptr inbounds ([25 x i8*]* @_ZTVN5Test41DE, i64 0, i64 17) to i8*), i8* bitcast (i8** getelementptr inbounds ([25 x i8*]* @_ZTVN5Test41DE, i64 0, i64 20) to i8*), i8* bitcast (i8** getelementptr inbounds ([25 x i8*]* @_ZTVN5Test41DE, i64 0, i64 13) to i8*), i8* bitcast (i8** getelementptr inbounds ([25 x i8*]* @_ZTVN5Test41DE, i64 0, i64 13) to i8*), i8* bitcast (i8** getelementptr inbounds ([25 x i8*]* @_ZTVN5Test41DE, i64 1, i64 0) to i8*), i8* bitcast (i8** getelementptr inbounds ([7 x i8*]* @_ZTCN5Test41DE40_NS_2V1E, i64 0, i64 3) to i8*), i8* bitcast (i8** getelementptr inbounds ([7 x i8*]* @_ZTCN5Test41DE40_NS_2V1E, i64 0, i64 6) to i8*), i8* bitcast (i8** getelementptr inbounds ([11 x i8*]* @_ZTCN5Test41DE72_NS_2V2E, i64 0, i64 4) to i8*), i8* bitcast (i8** getelementptr inbounds ([11 x i8*]* @_ZTCN5Test41DE72_NS_2V2E, i64 0, i64 7) to i8*), i8* bitcast (i8** getelementptr inbounds ([11 x i8*]* @_ZTCN5Test41DE72_NS_2V2E, i64 0, i64 10) to i8*)] +// CHECK: @_ZTTN5Test31DE = weak_odr constant [13 x i8*] [i8* bitcast (i8** getelementptr inbounds ([19 x i8*]* @_ZTVN5Test31DE, i64 0, i64 5) to i8*), i8* bitcast (i8** getelementptr inbounds ([7 x i8*]* @_ZTCN5Test31DE0_NS_2C1E, i64 0, i64 3) to i8*), i8* bitcast (i8** getelementptr inbounds ([7 x i8*]* @_ZTCN5Test31DE0_NS_2C1E, i64 0, i64 6) to i8*), i8* bitcast (i8** getelementptr inbounds ([14 x i8*]* @_ZTCN5Test31DE16_NS_2C2E, i64 0, i64 6) to i8*), i8* bitcast (i8** getelementptr inbounds ([14 x i8*]* @_ZTCN5Test31DE16_NS_2C2E, i64 0, i64 6) to i8*), i8* bitcast (i8** getelementptr inbounds ([14 x i8*]* @_ZTCN5Test31DE16_NS_2C2E, i64 0, i64 10) to i8*), i8* bitcast (i8** getelementptr inbounds ([14 x i8*]* @_ZTCN5Test31DE16_NS_2C2E, i64 0, i64 13) to i8*), i8* bitcast (i8** getelementptr inbounds ([19 x i8*]* @_ZTVN5Test31DE, i64 0, i64 15) to i8*), i8* bitcast (i8** getelementptr inbounds ([19 x i8*]* @_ZTVN5Test31DE, i64 0, i64 11) to i8*), i8* bitcast (i8** getelementptr inbounds ([19 x i8*]* @_ZTVN5Test31DE, i64 0, i64 11) to i8*), i8* bitcast (i8** getelementptr inbounds ([19 x i8*]* @_ZTVN5Test31DE, i64 1, i64 0) to i8*), i8* bitcast (i8** getelementptr inbounds ([7 x i8*]* @_ZTCN5Test31DE64_NS_2V2E, i64 0, i64 3) to i8*), i8* bitcast (i8** getelementptr inbounds ([7 x i8*]* @_ZTCN5Test31DE64_NS_2V2E, i64 0, i64 6) to i8*)] +// CHECK: @_ZTTN5Test21CE = weak_odr constant [2 x i8*] [i8* bitcast (i8** getelementptr inbounds ([5 x i8*]* @_ZTVN5Test21CE, i64 0, i64 4) to i8*), i8* bitcast (i8** getelementptr inbounds ([5 x i8*]* @_ZTVN5Test21CE, i64 0, i64 4) to i8*)] diff --git a/test/CodeGenCXX/x86_32-arguments.cpp b/test/CodeGenCXX/x86_32-arguments.cpp index 023b729..e94e2ca 100644 --- a/test/CodeGenCXX/x86_32-arguments.cpp +++ b/test/CodeGenCXX/x86_32-arguments.cpp @@ -89,7 +89,7 @@ struct s5 { s5(); int &x; }; s5 f5() { return s5(); } // CHECK: define i32 @_Z4f6_0M2s6i(i32 %a) -// CHECK: define i64 @_Z4f6_1M2s6FivE(%{{.*}} byval %a) +// CHECK: define i64 @_Z4f6_1M2s6FivE(%{{.*}} byval) // FIXME: It would be nice to avoid byval on the previous case. struct s6 {}; typedef int s6::* s6_mdp; diff --git a/test/CodeGenCXX/x86_64-arguments.cpp b/test/CodeGenCXX/x86_64-arguments.cpp index df0c78a..e731698 100644 --- a/test/CodeGenCXX/x86_64-arguments.cpp +++ b/test/CodeGenCXX/x86_64-arguments.cpp @@ -19,11 +19,12 @@ struct f2_s1 : public f2_s0 { char d;}; void f2(f2_s1 a0) { } // PR5831 +// CHECK: define void @_Z2f34s3_1(i64 %x.coerce) struct s3_0 {}; struct s3_1 { struct s3_0 a; long b; }; void f3(struct s3_1 x) {} -// CHECK: define i64 @_Z4f4_0M2s4i(i64 %a.coerce) +// CHECK: define i64 @_Z4f4_0M2s4i(i64 %a) // CHECK: define {{.*}} @_Z4f4_1M2s4FivE(i64 %a.coerce0, i64 %a.coerce1) struct s4 {}; typedef int s4::* s4_mdp; @@ -44,4 +45,73 @@ void foo() { // CHECK: call void @_ZN6PR752310AddKeywordENS_9StringRefEi(i8* {{.*}}, i32 4) AddKeyword(StringRef(), 4); } -}
\ No newline at end of file +} + +namespace PR7742 { // Also rdar://8250764 + struct s2 { + float a[2]; + }; + + struct c2 : public s2 {}; + + // CHECK: define double @_ZN6PR77423fooEPNS_2c2E(%"struct.PR7742::c2"* %P) + c2 foo(c2 *P) { + } + +} + +namespace PR5179 { + struct B {}; + + struct B1 : B { + int* pa; + }; + + struct B2 : B { + B1 b1; + }; + + // CHECK: define i8* @_ZN6PR51793barENS_2B2E(i32* %b2.coerce) + const void *bar(B2 b2) { + return b2.b1.pa; + } +} + +namespace test5 { + struct Xbase { }; + struct Empty { }; + struct Y; + struct X : public Xbase { + Empty empty; + Y f(); + }; + struct Y : public X { + Empty empty; + }; + X getX(); + int takeY(const Y&, int y); + void g() { + // rdar://8340348 - The temporary for the X object needs to have a defined + // address when passed into X::f as 'this'. + takeY(getX().f(), 42); + } + // CHECK: void @_ZN5test51gEv() + // CHECK: alloca %"struct.test5::Y" + // CHECK: alloca %"struct.test5::X" + // CHECK: alloca %"struct.test5::Y" +} + + +// rdar://8360877 +namespace test6 { + struct outer { + int x; + struct epsilon_matcher {} e; + int f; + }; + + int test(outer x) { + return x.x + x.f; + } + // CHECK: define i32 @_ZN5test64testENS_5outerE(i64 %x.coerce0, i32 %x.coerce1) +} |