diff options
Diffstat (limited to 'test/CodeGenCXX')
130 files changed, 4187 insertions, 464 deletions
diff --git a/test/CodeGenCXX/PR5050-constructor-conversion.cpp b/test/CodeGenCXX/PR5050-constructor-conversion.cpp index 9103b83..aa75ea4 100644 --- a/test/CodeGenCXX/PR5050-constructor-conversion.cpp +++ b/test/CodeGenCXX/PR5050-constructor-conversion.cpp @@ -13,6 +13,6 @@ A f(const B &b) { // CHECK-LP64: callq __ZN1AC1ERKS_i -// CHECK-LP32: call L__ZN1AC1ERKS_i +// CHECK-LP32: calll L__ZN1AC1ERKS_i diff --git a/test/CodeGenCXX/PR5863-unreachable-block.cpp b/test/CodeGenCXX/PR5863-unreachable-block.cpp index 7709615..4829b52 100644 --- a/test/CodeGenCXX/PR5863-unreachable-block.cpp +++ b/test/CodeGenCXX/PR5863-unreachable-block.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -emit-llvm-only %s +// RUN: %clang_cc1 -fexceptions -emit-llvm-only %s // PR5863 class E { }; diff --git a/test/CodeGenCXX/anonymous-namespaces.cpp b/test/CodeGenCXX/anonymous-namespaces.cpp index 3ec7032..0198ed0 100644 --- a/test/CodeGenCXX/anonymous-namespaces.cpp +++ b/test/CodeGenCXX/anonymous-namespaces.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm %s -o - > %t +// RUN: %clang_cc1 -fexceptions -triple x86_64-apple-darwin10 -emit-llvm %s -o - > %t // RUN: FileCheck %s -check-prefix=1 < %t // RUN: FileCheck %s -check-prefix=2 < %t diff --git a/test/CodeGenCXX/anonymous-union-member-initializer.cpp b/test/CodeGenCXX/anonymous-union-member-initializer.cpp index 9ba3805..d97a2ae 100644 --- a/test/CodeGenCXX/anonymous-union-member-initializer.cpp +++ b/test/CodeGenCXX/anonymous-union-member-initializer.cpp @@ -1,4 +1,18 @@ -// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -o - %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -o - %s | FileCheck %s + +// rdar://8818236 +namespace rdar8818236 { +struct S { + char c2; + union { + char c; + int i; + }; +}; + +// CHECK: @_ZN11rdar88182363fooE = global i64 4 +char S::*foo = &S::c; +} struct A { union { @@ -67,7 +81,7 @@ namespace test3 { }; A::A() : callback(0), callback_value(0) {} - // CHECK: define void @ZN5test31AC2Ev( + // CHECK: define void @_ZN5test31AC2Ev( // CHECK: [[THIS:%.*]] = load // CHECK-NEXT: [[UNION:%.*]] = getelementptr inbounds {{.*}} [[THIS]], i32 0, i32 0 // CHECK-NEXT: [[STRUCT:%.*]] = getelementptr inbounds {{.*}} [[UNION]], i32 0, i32 0 @@ -75,8 +89,8 @@ namespace test3 { // CHECK-NEXT: store void (i8*)* null, void (i8*)** [[CALLBACK]] // CHECK-NEXT: [[UNION:%.*]] = getelementptr inbounds {{.*}} [[THIS]], i32 0, i32 0 // CHECK-NEXT: [[STRUCT:%.*]] = getelementptr inbounds {{.*}} [[UNION]], i32 0, i32 0 - // CHECK-NEXT: [[CVALUE:%.*]] = getelementptr inbounds {{.*}} [[STRUCT]], i32 0, i32 0 - // CHECK-NEXT: store i8* null, void i8** [[CVALUE]] + // CHECK-NEXT: [[CVALUE:%.*]] = getelementptr inbounds {{.*}} [[STRUCT]], i32 0, i32 1 + // CHECK-NEXT: store i8* null, i8** [[CVALUE]] } struct S { @@ -90,3 +104,16 @@ struct S { }; }; } s; + + + //PR8760 + template <typename T>
+ struct Foo {
+ Foo() : ptr(__nullptr) {}
+ union {
+ T *ptr;
+ };
+ };
+ Foo<int> f;
+
+
diff --git a/test/CodeGenCXX/apple-kext-indirect-call-2.C b/test/CodeGenCXX/apple-kext-indirect-call-2.C new file mode 100644 index 0000000..7e25200 --- /dev/null +++ b/test/CodeGenCXX/apple-kext-indirect-call-2.C @@ -0,0 +1,77 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fapple-kext -fno-rtti -emit-llvm -o - %s | FileCheck %s + +// CHECK: @_ZTV1A = unnamed_addr constant [4 x i8*] [i8* null, i8* null, i8* bitcast (i8* (%struct.A*)* @_ZNK1A3abcEv to i8*), i8* null] +// CHECK: @_ZTV4Base = unnamed_addr constant [4 x i8*] [i8* null, i8* null, i8* bitcast (i8* (%struct.A*)* @_ZNK4Base3abcEv to i8*), i8* null] +// CHECK: @_ZTV8Derived2 = unnamed_addr constant [5 x i8*] [i8* null, i8* null, i8* null, i8* bitcast (i8* (%struct.A*)* @_ZNK8Derived23efgEv to i8*), i8* null] +// CHECK: @_ZTV2D2 = unnamed_addr constant [5 x i8*] [i8* null, i8* null, i8* null, i8* bitcast (i8* (%struct.A*)* @_ZNK2D23abcEv to i8*), i8* null] + +struct A { + virtual const char* abc(void) const; +}; + +const char* A::abc(void) const {return "A"; }; + +struct B : virtual A { + virtual void VF(); +}; + +void B::VF() {} + +void FUNC(B* p) { +// CHECK: [[T1:%.*]] = load i8* (%struct.A*)** getelementptr inbounds (i8* (%struct.A*)** bitcast ([4 x i8*]* @_ZTV1A to i8* (%struct.A*)**), i64 2) +// CHECK-NEXT: [[T2:%.*]] = call i8* [[T1]] + const char* c = p->A::abc(); +} + + +// Test2 +struct Base { virtual char* abc(void) const; }; + +char* Base::abc() const { return 0; } + +struct Derived : public Base { +}; + +void FUNC1(Derived* p) { +// CHECK: [[U1:%.*]] = load i8* (%struct.A*)** getelementptr inbounds (i8* (%struct.A*)** bitcast ([4 x i8*]* @_ZTV4Base to i8* (%struct.A*)**), i64 2) +// CHECK-NEXT: [[U2:%.*]] = call i8* [[U1]] + char* c = p->Base::abc(); +} + + +// Test3 +struct Base2 { }; + +struct Derived2 : virtual Base2 { + virtual char* efg(void) const; +}; + +char* Derived2::efg(void) const { return 0; } + +void FUNC2(Derived2* p) { +// CHECK: [[V1:%.*]] = load i8* (%struct.A*)** getelementptr inbounds (i8* (%struct.A*)** bitcast ([5 x i8*]* @_ZTV8Derived2 to i8* (%struct.A*)**), i64 3) +// CHECK-NEXT: [[V2:%.*]] = call i8* [[V1]] + char* c = p->Derived2::efg(); +} + +// Test4 +struct Base3 { }; + +struct D1 : virtual Base3 { +}; + +struct D2 : virtual Base3 { + virtual char *abc(void) const; +}; + +struct Sub : D1, D2 { +}; + +char* D2::abc(void) const { return 0; } + +void FUNC3(Sub* p) { +// CHECK: [[W1:%.*]] = load i8* (%struct.A*)** getelementptr inbounds (i8* (%struct.A*)** bitcast ([5 x i8*]* @_ZTV2D2 to i8* (%struct.A*)**), i64 3) +// CHECK-NEXT: [[W2:%.*]] = call i8* [[W1]] + char* c = p->D2::abc(); +} + diff --git a/test/CodeGenCXX/apple-kext-indirect-call.C b/test/CodeGenCXX/apple-kext-indirect-call.C new file mode 100644 index 0000000..2dbb0b8 --- /dev/null +++ b/test/CodeGenCXX/apple-kext-indirect-call.C @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fapple-kext -emit-llvm -o - %s | FileCheck %s + +struct Base { + virtual void abc(void) const; +}; + +void Base::abc(void) const {} + +void FUNC(Base* p) { + p->Base::abc(); +} + +// CHECK: getelementptr inbounds (void (%struct.Base*)** bitcast ([3 x i8*]* @_ZTV4Base to void (%struct.Base*)**), i64 2) +// CHECK-NOT: call void @_ZNK4Base3abcEv diff --git a/test/CodeGenCXX/apple-kext-indirect-virtual-dtor-call.cpp b/test/CodeGenCXX/apple-kext-indirect-virtual-dtor-call.cpp new file mode 100644 index 0000000..bd275f1 --- /dev/null +++ b/test/CodeGenCXX/apple-kext-indirect-virtual-dtor-call.cpp @@ -0,0 +1,19 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fapple-kext -fno-rtti -emit-llvm -o - %s | FileCheck %s + +// CHECK: define void @_ZN2B1D0Ev +// CHECK: [[T1:%.*]] = load void (%struct.B1*)** getelementptr inbounds (void (%struct.B1*)** bitcast ([5 x i8*]* @_ZTV2B1 to void (%struct.B1*)**), i64 2) +// CHECK-NEXT: call void [[T1]](%struct.B1* [[T2:%.*]]) +// CHECK: define void @_Z6DELETEP2B1 +// CHECK: [[T3:%.*]] = load void (%struct.B1*)** getelementptr inbounds (void (%struct.B1*)** bitcast ([5 x i8*]* @_ZTV2B1 to void (%struct.B1*)**), i64 2) +// CHECK-NEXT: call void [[T3]](%struct.B1* [[T4:%.*]]) + + +struct B1 { + virtual ~B1(); +}; + +B1::~B1() {} + +void DELETE(B1 *pb1) { + pb1->B1::~B1(); +} diff --git a/test/CodeGenCXX/apple-kext-linkage.C b/test/CodeGenCXX/apple-kext-linkage.C new file mode 100644 index 0000000..9df1151 --- /dev/null +++ b/test/CodeGenCXX/apple-kext-linkage.C @@ -0,0 +1,25 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fapple-kext -emit-llvm -o - %s | FileCheck %s + +struct Base { + virtual ~Base(); +} ; + +struct Derived : Base { + void operator delete(void *) { } + Derived(); +}; + +void foo() { + Derived d1; // ok +} + +inline unsigned f(unsigned n) { return n == 0 ? 0 : n + f(n-1); } + +unsigned g(unsigned n) { return f(n); } + + +template <typename X> X ident(X x) { return x; } +int foo(int n) { return ident(n); } + +// CHECK-NOT: define linkonce_odr +// CHECK 5 : define internal diff --git a/test/CodeGenCXX/apple-kext-no-staticinit-section.C b/test/CodeGenCXX/apple-kext-no-staticinit-section.C new file mode 100644 index 0000000..0401d49 --- /dev/null +++ b/test/CodeGenCXX/apple-kext-no-staticinit-section.C @@ -0,0 +1,20 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fapple-kext -fno-rtti -emit-llvm -o - %s | FileCheck %s +// rdar://8825235 +/** +1) Normally, global object construction code ends up in __StaticInit segment of text section + .section __TEXT,__StaticInit,regular,pure_instructions + In kext mode, they end up in the __text segment. +*/ + +class foo { +public: + foo(); + virtual ~foo(); +}; + +foo a; +foo b; +foo c; +foo::~foo() {} + +// CHECK-NOT: __TEXT,__StaticInit,regular,pure_instructions diff --git a/test/CodeGenCXX/arm.cpp b/test/CodeGenCXX/arm.cpp index 44c0aff..672ca01 100644 --- a/test/CodeGenCXX/arm.cpp +++ b/test/CodeGenCXX/arm.cpp @@ -1,5 +1,10 @@ // 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 +// CHECK: @_ZZN5test74testEvE1x = internal global i32 0, align 4 +// CHECK: @_ZGVZN5test74testEvE1x = internal global i32 0 +// CHECK: @_ZZN5test84testEvE1x = internal global [[TEST8A:.*]] zeroinitializer, align 1 +// CHECK: @_ZGVZN5test84testEvE1x = internal global i32 0 + typedef typeof(sizeof(int)) size_t; class foo { @@ -39,7 +44,7 @@ namespace test1 { a.bar(); } - // CHECK: define linkonce_odr [[A]]* @_ZN5test11AC1Ei([[A]]* + // CHECK: define linkonce_odr [[A]]* @_ZN5test11AC1Ei([[A]]* %this, i32 %i) unnamed_addr // CHECK: [[RET:%.*]] = alloca [[A]]*, align 4 // CHECK: [[THIS:%.*]] = alloca [[A]]*, align 4 // CHECK: store [[A]]* {{.*}}, [[A]]** [[THIS]] @@ -49,7 +54,7 @@ namespace test1 { // CHECK: [[THIS2:%.*]] = load [[A]]** [[RET]] // CHECK: ret [[A]]* [[THIS2]] - // CHECK: define linkonce_odr [[A]]* @_ZN5test11AD1Ev([[A]]* + // CHECK: define linkonce_odr [[A]]* @_ZN5test11AD1Ev([[A]]* %this) unnamed_addr // CHECK: [[RET:%.*]] = alloca [[A]]*, align 4 // CHECK: [[THIS:%.*]] = alloca [[A]]*, align 4 // CHECK: store [[A]]* {{.*}}, [[A]]** [[THIS]] @@ -277,6 +282,76 @@ namespace test6 { } } +namespace test7 { + int foo(); + + // Static and guard tested at top of file + + // CHECK: define void @_ZN5test74testEv() + void test() { + // CHECK: [[T0:%.*]] = load i32* @_ZGVZN5test74testEvE1x + // CHECK-NEXT: [[T1:%.*]] = and i32 [[T0]], 1 + // CHECK-NEXT: [[T2:%.*]] = icmp eq i32 [[T1]], 0 + // CHECK-NEXT: br i1 [[T2]] + // -> fallthrough, end + // CHECK: [[T3:%.*]] = call i32 @__cxa_guard_acquire(i32* @_ZGVZN5test74testEvE1x) + // CHECK-NEXT: [[T4:%.*]] = icmp ne i32 [[T3]], 0 + // CHECK-NEXT: br i1 [[T4]] + // -> fallthrough, end + // CHECK: [[INIT:%.*]] = invoke i32 @_ZN5test73fooEv() + // CHECK: store i32 [[INIT]], i32* @_ZZN5test74testEvE1x, align 4 + // CHECK-NEXT: call void @__cxa_guard_release(i32* @_ZGVZN5test74testEvE1x) + // CHECK-NEXT: br label + // -> end + // end: + // CHECK: ret void + static int x = foo(); + + // CHECK: call i8* @llvm.eh.exception() + // CHECK: call void @__cxa_guard_abort(i32* @_ZGVZN5test74testEvE1x) + // CHECK: call void @_Unwind_Resume_or_Rethrow + } +} + +namespace test8 { + struct A { + A(); + ~A(); + }; + + // Static and guard tested at top of file + + // CHECK: define void @_ZN5test84testEv() + void test() { + // CHECK: [[T0:%.*]] = load i32* @_ZGVZN5test84testEvE1x + // CHECK-NEXT: [[T1:%.*]] = and i32 [[T0]], 1 + // CHECK-NEXT: [[T2:%.*]] = icmp eq i32 [[T1]], 0 + // CHECK-NEXT: br i1 [[T2]] + // -> fallthrough, end + // CHECK: [[T3:%.*]] = call i32 @__cxa_guard_acquire(i32* @_ZGVZN5test84testEvE1x) + // CHECK-NEXT: [[T4:%.*]] = icmp ne i32 [[T3]], 0 + // CHECK-NEXT: br i1 [[T4]] + // -> fallthrough, end + // CHECK: [[INIT:%.*]] = invoke [[TEST8A]]* @_ZN5test81AC1Ev([[TEST8A]]* @_ZZN5test84testEvE1x) + + // FIXME: Here we register a global destructor that + // unconditionally calls the destructor. That's what we've always + // done for -fno-use-cxa-atexit here, but that's really not + // semantically correct at all. + + // CHECK: call void @__cxa_guard_release(i32* @_ZGVZN5test84testEvE1x) + // CHECK-NEXT: br label + // -> end + // end: + // CHECK: ret void + static A x; + + // CHECK: call i8* @llvm.eh.exception() + // CHECK: call void @__cxa_guard_abort(i32* @_ZGVZN5test84testEvE1x) + // CHECK: call void @_Unwind_Resume_or_Rethrow + } +} + // CHECK: define linkonce_odr [[C:%.*]]* @_ZTv0_n12_N5test21CD1Ev( // CHECK: call [[C]]* @_ZN5test21CD1Ev( // CHECK: ret [[C]]* undef diff --git a/test/CodeGenCXX/array-construction.cpp b/test/CodeGenCXX/array-construction.cpp index ab46be7..d044ac5 100644 --- a/test/CodeGenCXX/array-construction.cpp +++ b/test/CodeGenCXX/array-construction.cpp @@ -32,5 +32,5 @@ int main() { // CHECK-LP64: callq __ZN4xptoC1Ev -// CHECK-LP32: call L__ZN4xptoC1Ev +// CHECK-LP32: calll L__ZN4xptoC1Ev diff --git a/test/CodeGenCXX/array-operator-delete-call.cpp b/test/CodeGenCXX/array-operator-delete-call.cpp index acb85d2..ad60cf6 100644 --- a/test/CodeGenCXX/array-operator-delete-call.cpp +++ b/test/CodeGenCXX/array-operator-delete-call.cpp @@ -59,5 +59,5 @@ COST c2; // CHECK-LP64: callq __ZdaPv -// CHECK-LP32: call L__ZdaPv +// CHECK-LP32: calll L__ZdaPv diff --git a/test/CodeGenCXX/array-value-initialize.cpp b/test/CodeGenCXX/array-value-initialize.cpp index 8a3d5ff..27607c1 100644 --- a/test/CodeGenCXX/array-value-initialize.cpp +++ b/test/CodeGenCXX/array-value-initialize.cpp @@ -49,4 +49,4 @@ int main() Stuff b = a; return 0; -}
\ No newline at end of file +} diff --git a/test/CodeGenCXX/asm.cpp b/test/CodeGenCXX/asm.cpp new file mode 100644 index 0000000..3b745a7 --- /dev/null +++ b/test/CodeGenCXX/asm.cpp @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck %s + +struct A +{ + ~A(); +}; +int foo(A); + +void bar(A &a) +{ + // CHECK: call void asm + asm("" : : "r"(foo(a)) ); // rdar://8540491 + // CHECK: call void @_ZN1AD1Ev +} diff --git a/test/CodeGenCXX/attr-used.cpp b/test/CodeGenCXX/attr-used.cpp new file mode 100644 index 0000000..26109e7 --- /dev/null +++ b/test/CodeGenCXX/attr-used.cpp @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 -emit-llvm -o - %s | FileCheck %s + +// <rdar://problem/8684363>: clang++ not respecting __attribute__((used)) on destructors +struct X0 { + // CHECK: define linkonce_odr void @_ZN2X0C1Ev + __attribute__((used)) X0() {} + // CHECK: define linkonce_odr void @_ZN2X0D1Ev + __attribute__((used)) ~X0() {} +}; diff --git a/test/CodeGenCXX/attr.cpp b/test/CodeGenCXX/attr.cpp index d689a4f..9e8740e5 100644 --- a/test/CodeGenCXX/attr.cpp +++ b/test/CodeGenCXX/attr.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -emit-llvm -o - %s | FileCheck %s // CHECK: @test2 = alias i32 ()* @_Z5test1v diff --git a/test/CodeGenCXX/block-byref-cxx-objc.cpp b/test/CodeGenCXX/block-byref-cxx-objc.cpp new file mode 100644 index 0000000..a4fbd6c --- /dev/null +++ b/test/CodeGenCXX/block-byref-cxx-objc.cpp @@ -0,0 +1,25 @@ +// RUN: %clang_cc1 %s -emit-llvm -o - -fblocks | FileCheck %s +// rdar://8594790 + +struct A { + int x; + A(const A &); + A(); + ~A(); +}; + +int main() +{ + __block A BYREF_VAR; + ^{ BYREF_VAR.x = 1234; }; + return 0; +} + +// CHECK: define internal void @__Block_byref_object_copy_ +// CHECK: call void @_ZN1AC1ERKS_ +// CHECK: define internal void @__Block_byref_object_dispose_ +// CHECK: call void @_ZN1AD1Ev +// CHECK: define internal void @__copy_helper_block_ +// CHECK: call void @_Block_object_assign +// CHECK: define internal void @__destroy_helper_block_ +// CHECK: call void @_Block_object_dispose diff --git a/test/CodeGenCXX/blocks.cpp b/test/CodeGenCXX/blocks.cpp new file mode 100644 index 0000000..ea174b5 --- /dev/null +++ b/test/CodeGenCXX/blocks.cpp @@ -0,0 +1,57 @@ +// RUN: %clang_cc1 %s -fblocks -triple x86_64-apple-darwin -emit-llvm -o - | FileCheck %s + +namespace test0 { + // CHECK: define void @_ZN5test04testEi( + // CHECK: define internal void @__test_block_invoke_{{.*}}( + // CHECK: define internal void @__block_global_{{.*}}( + void test(int x) { + ^{ ^{ (void) x; }; }; + } +} + +extern void (^out)(); + +namespace test1 { + // Capturing const objects doesn't require a local block. + // CHECK: define void @_ZN5test15test1Ev() + // CHECK: store void ()* bitcast ({{.*}} @__block_literal_global{{.*}} to void ()*), void ()** @out + void test1() { + const int NumHorsemen = 4; + out = ^{ (void) NumHorsemen; }; + } + + // That applies to structs too... + // CHECK: define void @_ZN5test15test2Ev() + // CHECK: store void ()* bitcast ({{.*}} @__block_literal_global{{.*}} to void ()*), void ()** @out + struct loc { double x, y; }; + void test2() { + const loc target = { 5, 6 }; + out = ^{ (void) target; }; + } + + // ...unless they have mutable fields... + // CHECK: define void @_ZN5test15test3Ev() + // CHECK: [[BLOCK:%.*]] = alloca [[BLOCK_T:%.*]], + // CHECK: [[T0:%.*]] = bitcast [[BLOCK_T]]* [[BLOCK]] to void ()* + // CHECK: store void ()* [[T0]], void ()** @out + struct mut { mutable int x; }; + void test3() { + const mut obj = { 5 }; + out = ^{ (void) obj; }; + } + + // ...or non-trivial destructors... + // CHECK: define void @_ZN5test15test4Ev() + // CHECK: [[OBJ:%.*]] = alloca + // CHECK: [[BLOCK:%.*]] = alloca [[BLOCK_T:%.*]], + // CHECK: [[T0:%.*]] = bitcast [[BLOCK_T]]* [[BLOCK]] to void ()* + // CHECK: store void ()* [[T0]], void ()** @out + struct scope { int x; ~scope(); }; + void test4() { + const scope obj = { 5 }; + out = ^{ (void) obj; }; + } + + // ...or non-trivial copy constructors, but it's not clear how to do + // that and still have a constant initializer in '03. +} diff --git a/test/CodeGenCXX/builtins.cpp b/test/CodeGenCXX/builtins.cpp new file mode 100644 index 0000000..0629c31 --- /dev/null +++ b/test/CodeGenCXX/builtins.cpp @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 -emit-llvm -o - %s | FileCheck %s + +// PR8839 +extern "C" char memmove(); + +int main() { + // CHECK: call signext i8 @memmove() + return memmove(); +} diff --git a/test/CodeGenCXX/c99-variable-length-array.cpp b/test/CodeGenCXX/c99-variable-length-array.cpp index 66c14ff..76f99c7 100644 --- a/test/CodeGenCXX/c99-variable-length-array.cpp +++ b/test/CodeGenCXX/c99-variable-length-array.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -o - %s | FileCheck %s struct X { X(); ~X(); diff --git a/test/CodeGenCXX/call-arg-zero-temp.cpp b/test/CodeGenCXX/call-arg-zero-temp.cpp index ed8118e..88e7452 100644 --- a/test/CodeGenCXX/call-arg-zero-temp.cpp +++ b/test/CodeGenCXX/call-arg-zero-temp.cpp @@ -19,4 +19,4 @@ int main() { // CHECK-LP64: callq __Z3foo3obj -// CHECK-LP32: call __Z3foo3obj +// CHECK-LP32: calll __Z3foo3obj diff --git a/test/CodeGenCXX/cast-conversion.cpp b/test/CodeGenCXX/cast-conversion.cpp index 6dc6de6..27e34b9 100644 --- a/test/CodeGenCXX/cast-conversion.cpp +++ b/test/CodeGenCXX/cast-conversion.cpp @@ -24,9 +24,9 @@ int main () { // CHECK-LP64: callq __ZN1AC1Ei // CHECK-LP64: callq __ZN1BC1E1A -// CHECK-LP32: call L__ZN1AC1Ei -// CHECK-LP32: call L__ZN1BC1E1A -// CHECK-LP32: call L__ZN1AC1Ei -// CHECK-LP32: call L__ZN1BC1E1A -// CHECK-LP32: call L__ZN1AC1Ei -// CHECK-LP32: call L__ZN1BC1E1A +// CHECK-LP32: calll L__ZN1AC1Ei +// CHECK-LP32: calll L__ZN1BC1E1A +// CHECK-LP32: calll L__ZN1AC1Ei +// CHECK-LP32: calll L__ZN1BC1E1A +// CHECK-LP32: calll L__ZN1AC1Ei +// CHECK-LP32: calll L__ZN1BC1E1A diff --git a/test/CodeGenCXX/class-layout.cpp b/test/CodeGenCXX/class-layout.cpp index 9303bda..6675b49 100644 --- a/test/CodeGenCXX/class-layout.cpp +++ b/test/CodeGenCXX/class-layout.cpp @@ -1,13 +1,19 @@ -// RUN: %clang_cc1 %s -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 %s -triple x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s // An extra byte should be allocated for an empty class. -// CHECK: %struct.A = type { i8 } -struct A { } a; +namespace Test1 { + // CHECK: %"struct.Test1::A" = type { i8 } + struct A { } *a; +} -// No need to add tail padding here. -// CHECK: %struct.B = type { i8*, i32 } -struct B { void *a; int b; } b; +namespace Test2 { + // No need to add tail padding here. + // CHECK: %"struct.Test2::A" = type { i8*, i32 } + struct A { void *a; int b; } *a; +} -// C should have a vtable pointer. -// CHECK: %struct.C = type { i32 (...)**, i32 } -struct C { virtual void f(); int a; } *c; +namespace Test3 { + // C should have a vtable pointer. + // CHECK: %"struct.Test3::A" = type { i32 (...)**, i32 } + struct A { virtual void f(); int a; } *a; +} diff --git a/test/CodeGenCXX/const-init.cpp b/test/CodeGenCXX/const-init.cpp index 9cfce7a..a8c6f30 100644 --- a/test/CodeGenCXX/const-init.cpp +++ b/test/CodeGenCXX/const-init.cpp @@ -24,3 +24,15 @@ public: // CHECK: @_ZN6PR55812g0E = global %1 { i32 1 } C g0 = { C::e1 }; } + +namespace test2 { + struct A { + static const double d = 1.0; + static const float f = d / 2; + }; + + // CHECK: @_ZN5test22t0E = global double {{1\.0+e\+0+}}, align 8 + // CHECK: @_ZN5test22t1E = global [2 x double] [double {{1\.0+e\+0+}}, double {{5\.0+e-0*}}1], align 16 + double t0 = A::d; + double t1[] = { A::d, A::f }; +} diff --git a/test/CodeGenCXX/constructor-attr.cpp b/test/CodeGenCXX/constructor-attr.cpp new file mode 100644 index 0000000..691795f --- /dev/null +++ b/test/CodeGenCXX/constructor-attr.cpp @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -emit-llvm -o - %s | FileCheck %s + +// CHECK: @llvm.global_ctors + +// PR6521 +void bar(); +struct Foo { + // CHECK: define linkonce_odr void @_ZN3Foo3fooEv + static void foo() __attribute__((constructor)) { + bar(); + } +}; diff --git a/test/CodeGenCXX/constructor-conversion.cpp b/test/CodeGenCXX/constructor-conversion.cpp index f135da5..405bba6 100644 --- a/test/CodeGenCXX/constructor-conversion.cpp +++ b/test/CodeGenCXX/constructor-conversion.cpp @@ -49,6 +49,6 @@ int main() { // CHECK-LP64: callq __ZN1XC1EPKci // CHECK-LP64: callq __ZN1XC1Ev -// CHECK-LP32: call L__ZN1XC1Ei -// CHECK-LP32: call L__ZN1XC1EPKci -// CHECK-LP32: call L__ZN1XC1Ev +// CHECK-LP32: calll L__ZN1XC1Ei +// CHECK-LP32: calll L__ZN1XC1EPKci +// CHECK-LP32: calll L__ZN1XC1Ev diff --git a/test/CodeGenCXX/constructor-convert.cpp b/test/CodeGenCXX/constructor-convert.cpp index 338febb..9122dae 100644 --- a/test/CodeGenCXX/constructor-convert.cpp +++ b/test/CodeGenCXX/constructor-convert.cpp @@ -5,7 +5,7 @@ class Twine { Twine(const char *Str) { } }; -static void error(const Twine &Message); +static void error(const Twine &Message) {} template<typename> struct opt_storage { diff --git a/test/CodeGenCXX/constructor-default-arg.cpp b/test/CodeGenCXX/constructor-default-arg.cpp index ec0b8da..0c08c76 100644 --- a/test/CodeGenCXX/constructor-default-arg.cpp +++ b/test/CodeGenCXX/constructor-default-arg.cpp @@ -34,6 +34,6 @@ int main() { // CHECK-LP64: callq __ZN1XC1ERKS_iii // CHECK-LP64: callq __ZN1XC1ERKS_iii -// CHECK-LP32: call L__ZN1XC1ERKS_iii -// CHECK-LP32: call L__ZN1XC1ERKS_iii -// CHECK-LP32: call L__ZN1XC1ERKS_iii +// CHECK-LP32: calll L__ZN1XC1ERKS_iii +// CHECK-LP32: calll L__ZN1XC1ERKS_iii +// CHECK-LP32: calll L__ZN1XC1ERKS_iii diff --git a/test/CodeGenCXX/constructor-direct-call.cpp b/test/CodeGenCXX/constructor-direct-call.cpp new file mode 100644 index 0000000..75e6f21 --- /dev/null +++ b/test/CodeGenCXX/constructor-direct-call.cpp @@ -0,0 +1,60 @@ +// RUN: %clang_cc1 -triple i686-pc-win32 -fms-extensions -Wmicrosoft %s -emit-llvm -o - | FileCheck %s + +class Test1 { +public: + int a; +}; + +void f1() { + Test1 var; + var.Test1::Test1(); + + // CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* %{{.*}}, i8* %{{.*}}, i32 4, i32 4, i1 false) + var.Test1::Test1(var); +} + +class Test2 { +public: + Test2() { a = 10; b = 10; } + int a; + int b; +}; + +void f2() { + // CHECK: %var = alloca %class.Test2, align 4 + // CHECK-NEXT: call void @_ZN5Test2C1Ev(%class.Test2* %var) + Test2 var; + + // CHECK-NEXT: call void @_ZN5Test2C1Ev(%class.Test2* %var) + var.Test2::Test2(); + + // CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* %{{.*}}, i8* %{{.*}}, i32 8, i32 4, i1 false) + var.Test2::Test2(var); +} + + + + +class Test3 { +public: + Test3() { a = 10; b = 15; c = 20; } + Test3(const Test3& that) { a = that.a; b = that.b; c = that.c; } + int a; + int b; + int c; +}; + +void f3() { + // CHECK: call void @_ZN5Test3C1Ev(%class.Test3* %var) + Test3 var; + + // CHECK-NEXT: call void @_ZN5Test3C1Ev(%class.Test3* %var2) + Test3 var2; + + // CHECK-NEXT: call void @_ZN5Test3C1Ev(%class.Test3* %var) + var.Test3::Test3(); + + // CHECK-NEXT: call void @_ZN5Test3C1ERKS_(%class.Test3* %var, %class.Test3* %var2) + var.Test3::Test3(var2); +} + diff --git a/test/CodeGenCXX/constructor-for-array-members.cpp b/test/CodeGenCXX/constructor-for-array-members.cpp index b981da4..fd6dc6d 100644 --- a/test/CodeGenCXX/constructor-for-array-members.cpp +++ b/test/CodeGenCXX/constructor-for-array-members.cpp @@ -40,4 +40,4 @@ int main() { // CHECK-LP64: callq __ZN1SC1Ev -// CHECK-LP32: call L__ZN1SC1Ev +// CHECK-LP32: calll L__ZN1SC1Ev diff --git a/test/CodeGenCXX/constructor-init.cpp b/test/CodeGenCXX/constructor-init.cpp index 284b8b5..47e3b7b 100644 --- a/test/CodeGenCXX/constructor-init.cpp +++ b/test/CodeGenCXX/constructor-init.cpp @@ -81,6 +81,38 @@ void f() { // CHECK: ret void } +// Make sure we initialize the vtable pointer if it's required by a +// base initializer. +namespace InitVTable { + struct A { A(int); }; + struct B : A { + virtual int foo(); + B(); + B(int); + }; + + // CHECK: define void @_ZN10InitVTable1BC2Ev(%"struct.InitVTable::B"* %this) unnamed_addr + // CHECK: [[T0:%.*]] = bitcast [[B:%.*]]* [[THIS:%.*]] to i8*** + // CHECK-NEXT: store i8** getelementptr inbounds ([3 x i8*]* @_ZTVN10InitVTable1BE, i64 0, i64 2), i8*** [[T0]] + // CHECK: [[VTBL:%.*]] = load i32 ([[B]]*)*** {{%.*}} + // CHECK-NEXT: [[FNP:%.*]] = getelementptr inbounds i32 ([[B]]*)** [[VTBL]], i64 0 + // CHECK-NEXT: [[FN:%.*]] = load i32 ([[B]]*)** [[FNP]] + // CHECK-NEXT: [[ARG:%.*]] = call i32 [[FN]]([[B]]* [[THIS]]) + // CHECK-NEXT: call void @_ZN10InitVTable1AC2Ei({{.*}}* {{%.*}}, i32 [[ARG]]) + // CHECK-NEXT: [[T0:%.*]] = bitcast [[B]]* [[THIS]] to i8*** + // CHECK-NEXT: store i8** getelementptr inbounds ([3 x i8*]* @_ZTVN10InitVTable1BE, i64 0, i64 2), i8*** [[T0]] + // CHECK-NEXT: ret void + B::B() : A(foo()) {} + + // CHECK: define void @_ZN10InitVTable1BC2Ei(%"struct.InitVTable::B"* %this, i32 %x) unnamed_addr + // CHECK: [[ARG:%.*]] = add nsw i32 {{%.*}}, 5 + // CHECK-NEXT: call void @_ZN10InitVTable1AC2Ei({{.*}}* {{%.*}}, i32 [[ARG]]) + // CHECK-NEXT: [[T0:%.*]] = bitcast [[B]]* {{%.*}} to i8*** + // CHECK-NEXT: store i8** getelementptr inbounds ([3 x i8*]* @_ZTVN10InitVTable1BE, i64 0, i64 2), i8*** [[T0]] + // CHECK-NEXT: ret void + B::B(int x) : A(x + 5) {} +} + template<typename T> struct X { X(const X &); @@ -93,7 +125,7 @@ template<typename T> struct X; // Make sure that the instantiated constructor initializes start and // end properly. -// CHECK: define linkonce_odr void @_ZN1XIiEC2ERKS0_ +// CHECK: define linkonce_odr void @_ZN1XIiEC2ERKS0_(%struct.X* %this, %struct.X* %other) unnamed_addr // CHECK: {{store.*null}} // CHECK: {{store.*null}} // CHECK: ret diff --git a/test/CodeGenCXX/constructors.cpp b/test/CodeGenCXX/constructors.cpp index a8dc7fc..75588ce 100644 --- a/test/CodeGenCXX/constructors.cpp +++ b/test/CodeGenCXX/constructors.cpp @@ -21,18 +21,18 @@ struct A { A::A(struct Undeclared &ref) : mem(0) {} // Check that delegation works. -// CHECK: define void @_ZN1AC1ER10Undeclared( +// CHECK: define void @_ZN1AC1ER10Undeclared(%struct.A* %this, %struct.Undeclared* %ref) unnamed_addr // CHECK: call void @_ZN1AC2ER10Undeclared( -// CHECK: define void @_ZN1AC2ER10Undeclared( +// CHECK: define void @_ZN1AC2ER10Undeclared(%struct.A* %this, %struct.Undeclared* %ref) unnamed_addr // CHECK: call void @_ZN6MemberC1Ei( A::A(ValueClass v) : mem(v.y - v.x) {} -// CHECK: define void @_ZN1AC1E10ValueClass( +// CHECK: define void @_ZN1AC1E10ValueClass(%struct.A* %this, i64 %v.coerce) unnamed_addr // CHECK: call void @_ZN1AC2E10ValueClass( -// CHECK: define void @_ZN1AC2E10ValueClass( +// CHECK: define void @_ZN1AC2E10ValueClass(%struct.A* %this, i64 %v.coerce) unnamed_addr // CHECK: call void @_ZN6MemberC1Ei( @@ -44,10 +44,10 @@ struct B : A { B::B(struct Undeclared &ref) : A(ref), mem(1) {} -// CHECK: define void @_ZN1BC1ER10Undeclared( +// CHECK: define void @_ZN1BC1ER10Undeclared(%struct.B* %this, %struct.Undeclared* %ref) unnamed_addr // CHECK: call void @_ZN1BC2ER10Undeclared( -// CHECK: define void @_ZN1BC2ER10Undeclared( +// CHECK: define void @_ZN1BC2ER10Undeclared(%struct.B* %this, %struct.Undeclared* %ref) unnamed_addr // CHECK: call void @_ZN1AC2ER10Undeclared( // CHECK: call void @_ZN6MemberC1Ei( @@ -64,12 +64,12 @@ struct C : virtual A { }; C::C(int x) : A(ValueClass(x, x+1)), mem(x * x) {} -// CHECK: define void @_ZN1CC1Ei( +// CHECK: define void @_ZN1CC1Ei(%struct.C* %this, i32 %x) unnamed_addr // CHECK: call void @_ZN10ValueClassC1Eii( // CHECK: call void @_ZN1AC2E10ValueClass( // CHECK: call void @_ZN6MemberC1Ei( -// CHECK: define void @_ZN1CC2Ei( +// CHECK: define void @_ZN1CC2Ei(%struct.C* %this, i8** %vtt, i32 %x) unnamed_addr // CHECK: call void @_ZN6MemberC1Ei( @@ -83,12 +83,12 @@ struct D : A { D::D(int x, ...) : A(ValueClass(x, x+1)), mem(x*x) {} -// CHECK: define void @_ZN1DC1Eiz( +// CHECK: define void @_ZN1DC1Eiz(%struct.B* %this, i32 %x, ...) unnamed_addr // CHECK: call void @_ZN10ValueClassC1Eii( // CHECK: call void @_ZN1AC2E10ValueClass( // CHECK: call void @_ZN6MemberC1Ei( -// CHECK: define void @_ZN1DC2Eiz( +// CHECK: define void @_ZN1DC2Eiz(%struct.B* %this, i32 %x, ...) unnamed_addr // CHECK: call void @_ZN10ValueClassC1Eii( // CHECK: call void @_ZN1AC2E10ValueClass( // CHECK: call void @_ZN6MemberC1Ei( diff --git a/test/CodeGenCXX/convert-to-fptr.cpp b/test/CodeGenCXX/convert-to-fptr.cpp index dc49401..f895dbc 100644 --- a/test/CodeGenCXX/convert-to-fptr.cpp +++ b/test/CodeGenCXX/convert-to-fptr.cpp @@ -41,6 +41,6 @@ int main() // CHECK-LP64: callq __ZN1AcvPFiiEEv // CHECK-LP64: callq __ZN1BcvRFiiEEv -// CHECK-LP32: call L__ZN1AcvPFiiEEv -// CHECK-LP32: call L__ZN1BcvRFiiEEv +// CHECK-LP32: calll L__ZN1AcvPFiiEEv +// CHECK-LP32: calll L__ZN1BcvRFiiEEv diff --git a/test/CodeGenCXX/copy-constructor-elim-2.cpp b/test/CodeGenCXX/copy-constructor-elim-2.cpp index 73e9b94..4f4a8e9 100644 --- a/test/CodeGenCXX/copy-constructor-elim-2.cpp +++ b/test/CodeGenCXX/copy-constructor-elim-2.cpp @@ -21,7 +21,7 @@ namespace no_elide_base { Derived(const Other &O); }; - // CHECK: define void @_ZN13no_elide_base7DerivedC1ERKNS_5OtherE + // CHECK: define void @_ZN13no_elide_base7DerivedC1ERKNS_5OtherE(%"struct.no_elide_base::Derived"* %this, %"struct.PR8683::A"* %O) unnamed_addr Derived::Derived(const Other &O) // CHECK: call void @_ZNK13no_elide_base5OthercvNS_4BaseEEv // CHECK: call void @_ZN13no_elide_base4BaseC2ERKS0_ @@ -31,3 +31,25 @@ namespace no_elide_base { // CHECK: ret void } } + +// PR8683. + +namespace PR8683 { + +struct A { + A(); + A(const A&); + A& operator=(const A&); +}; + +struct B { + A a; +}; + +void f() { + // Verify that we don't mark the copy constructor in this expression as elidable. + // CHECK: call void @_ZN6PR86831AC1ERKS0_ + A a = (B().a); +} + +} diff --git a/test/CodeGenCXX/copy-constructor-synthesis-2.cpp b/test/CodeGenCXX/copy-constructor-synthesis-2.cpp index 2f7c79b..a556679 100644 --- a/test/CodeGenCXX/copy-constructor-synthesis-2.cpp +++ b/test/CodeGenCXX/copy-constructor-synthesis-2.cpp @@ -3,5 +3,5 @@ struct A { virtual void a(); }; A x(A& y) { return y; } -// CHECK: define linkonce_odr void @_ZN1AC1ERKS_( +// CHECK: define linkonce_odr void @_ZN1AC1ERKS_(%struct.A* %this, %struct.A*) unnamed_addr // CHECK: store i8** getelementptr inbounds ([3 x i8*]* @_ZTV1A, i64 0, i64 2) diff --git a/test/CodeGenCXX/copy-constructor-synthesis.cpp b/test/CodeGenCXX/copy-constructor-synthesis.cpp index 9cafd0a..68f6805 100644 --- a/test/CodeGenCXX/copy-constructor-synthesis.cpp +++ b/test/CodeGenCXX/copy-constructor-synthesis.cpp @@ -21,7 +21,7 @@ struct P { }; -// CHECK: define linkonce_odr void @_ZN1XC1ERKS_ +// CHECK: define linkonce_odr void @_ZN1XC1ERKS_(%struct.X* %this, %struct.X*) unnamed_addr struct X : M, N, P { // ... X() : f1(1.0), d1(2.0), i1(3), name("HELLO"), bf1(0xff), bf2(0xabcd), au_i1(1234), au1_4("MASKED") {} @@ -136,7 +136,7 @@ void f(B b1) { B b2 = b1; } -// CHECK: define linkonce_odr void @_ZN6PR66281BC2ERKS0_ +// CHECK: define linkonce_odr void @_ZN6PR66281BC2ERKS0_(%"struct.PR6628::B"* %this, %"struct.PR6628::B"*) unnamed_addr // CHECK: call void @_ZN6PR66281TC1Ev // CHECK: call void @_ZN6PR66281TC1Ev // CHECK: call void @_ZN6PR66281AC2ERKS0_RKNS_1TES5_ diff --git a/test/CodeGenCXX/cxx-block-objects.cpp b/test/CodeGenCXX/cxx-block-objects.cpp new file mode 100644 index 0000000..b989065 --- /dev/null +++ b/test/CodeGenCXX/cxx-block-objects.cpp @@ -0,0 +1,33 @@ +// RUN: %clang_cc1 %s -fblocks -triple x86_64-apple-darwin -emit-llvm -o - | FileCheck %s +// rdar://8594790 + +extern "C" { +extern "C" void *_Block_copy(const void *aBlock); +extern "C" void _Block_release(const void *aBlock); +} + +class A { +public: + int x; + A(const A &o); + A(); + virtual ~A(); + void hello() const; +}; + +int +main() +{ + A a; + void (^c)(void) = ((__typeof(^{ a.hello(); }))_Block_copy((const void *)(^{ a.hello(); }))); + c(); + _Block_release((const void *)(c)); + return 0; +} + +// CHECK: define internal void @__copy_helper_block_ +// CHECK: call void @_ZN1AC1ERKS_ + + +// CHECK:define internal void @__destroy_helper_block_ +// CHECK: call void @_ZN1AD1Ev diff --git a/test/CodeGenCXX/debug-info-ctor2.cpp b/test/CodeGenCXX/debug-info-ctor2.cpp new file mode 100644 index 0000000..19bd64b --- /dev/null +++ b/test/CodeGenCXX/debug-info-ctor2.cpp @@ -0,0 +1,15 @@ +// RUN: %clang -fverbose-asm -g -S %s -o - | grep AT_explicit + + +class MyClass +{ +public: + explicit MyClass (int i) : + m_i (i) + {} +private: + int m_i; +}; + +MyClass m(1); + diff --git a/test/CodeGenCXX/debug-info-large-constant.cpp b/test/CodeGenCXX/debug-info-large-constant.cpp new file mode 100644 index 0000000..2daa189 --- /dev/null +++ b/test/CodeGenCXX/debug-info-large-constant.cpp @@ -0,0 +1,8 @@ +// RUN: %clang_cc1 -g -triple=x86_64-apple-darwin %s -o /dev/null +// PR 8913 + +typedef __uint128_t word128; +static const word128 m126 = 0xffffffffffffffffULL; +word128 foo() { + return m126; +} diff --git a/test/CodeGenCXX/debug-info-member.cpp b/test/CodeGenCXX/debug-info-member.cpp new file mode 100644 index 0000000..5052a6c --- /dev/null +++ b/test/CodeGenCXX/debug-info-member.cpp @@ -0,0 +1,6 @@ +// RUN: %clang -fverbose-asm -cc1 -g -S %s -o - | grep DW_ACCESS_public +class A { +public: + int x; +}; +A a; diff --git a/test/CodeGenCXX/debug-info-method.cpp b/test/CodeGenCXX/debug-info-method.cpp new file mode 100644 index 0000000..5935727 --- /dev/null +++ b/test/CodeGenCXX/debug-info-method.cpp @@ -0,0 +1,6 @@ +// RUN: %clang -fverbose-asm -cc1 -g -S %s -o - | grep DW_ACCESS_protected +class A { +protected: + int foo(); +}; +A a; diff --git a/test/CodeGenCXX/debug-info-namespace.cpp b/test/CodeGenCXX/debug-info-namespace.cpp new file mode 100644 index 0000000..2e0a96d --- /dev/null +++ b/test/CodeGenCXX/debug-info-namespace.cpp @@ -0,0 +1,12 @@ +// RUN: %clang -g -S %s -o - | FileCheck %s + +// CHECK: TAG_namespace +namespace A { + enum numbers { + ZERO, + ONE + }; +} + +using namespace A; +numbers n; diff --git a/test/CodeGenCXX/debug-info-template.cpp b/test/CodeGenCXX/debug-info-template.cpp index 233090c..0ddfc24 100644 --- a/test/CodeGenCXX/debug-info-template.cpp +++ b/test/CodeGenCXX/debug-info-template.cpp @@ -1,4 +1,8 @@ -// RUN: %clang_cc1 -emit-llvm-only -g -S %s -o - | grep "TC<int>" +// RUN: %clang -emit-llvm -g -S %s -o - | FileCheck %s + +//CHECK: TC<int> +//CHECK: DW_TAG_template_type_parameter + template<typename T> class TC { public: @@ -7,3 +11,12 @@ public: }; TC<int> tci; + +//CHECK: TU<2> +//CHECK: DW_TAG_template_value_parameter +template<unsigned > +class TU { + int b; +}; + +TU<2> u2; diff --git a/test/CodeGenCXX/decl-ref-init.cpp b/test/CodeGenCXX/decl-ref-init.cpp index c215b1b..58fdeda 100644 --- a/test/CodeGenCXX/decl-ref-init.cpp +++ b/test/CodeGenCXX/decl-ref-init.cpp @@ -26,5 +26,5 @@ int main() { // CHECK-LP64: callq __ZN1BcvR1AEv // CHECK-LP64: callq __ZN1BcvR1AEv -// CHECK-LP32: call L__ZN1BcvR1AEv -// CHECK-LP32: call L__ZN1BcvR1AEv +// CHECK-LP32: calll L__ZN1BcvR1AEv +// CHECK-LP32: calll L__ZN1BcvR1AEv diff --git a/test/CodeGenCXX/default-arg-temps.cpp b/test/CodeGenCXX/default-arg-temps.cpp index c441985..3d741d5 100644 --- a/test/CodeGenCXX/default-arg-temps.cpp +++ b/test/CodeGenCXX/default-arg-temps.cpp @@ -61,7 +61,7 @@ namespace test1 { C c; A a; - // CHECK: define linkonce_odr void @_ZN5test11DC2Ev( + // CHECK: define linkonce_odr void @_ZN5test11DC2Ev(%"struct.test1::D"* %this) unnamed_addr // CHECK: call void @_ZN5test11BC1Ev( // CHECK-NEXT: call void @_ZN5test11CC1ERKNS_1BE( // CHECK-NEXT: call void @_ZN5test11BD1Ev( diff --git a/test/CodeGenCXX/default-arguments.cpp b/test/CodeGenCXX/default-arguments.cpp index 2ed1567..6560d35 100644 --- a/test/CodeGenCXX/default-arguments.cpp +++ b/test/CodeGenCXX/default-arguments.cpp @@ -42,10 +42,10 @@ struct C { C(); }; -// CHECK: define void @_ZN1CC1Ev( +// CHECK: define void @_ZN1CC1Ev(%struct.C* %this) unnamed_addr // CHECK: call void @_ZN1CC2Ev( -// CHECK: define void @_ZN1CC2Ev( +// CHECK: define void @_ZN1CC2Ev(%struct.C* %this) unnamed_addr // CHECK: call void @_ZN2A1C1Ev( // CHECK: call void @_ZN2A2C1Ev( // CHECK: call void @_ZN1BC1ERK2A1RK2A2( diff --git a/test/CodeGenCXX/default-constructor-for-members.cpp b/test/CodeGenCXX/default-constructor-for-members.cpp index 1f17746..a97764d 100644 --- a/test/CodeGenCXX/default-constructor-for-members.cpp +++ b/test/CodeGenCXX/default-constructor-for-members.cpp @@ -20,4 +20,4 @@ int main() { // CHECK-LP64: callq __ZN1SC1Ev -// CHECK-LP32: call L__ZN1SC1Ev +// CHECK-LP32: calll L__ZN1SC1Ev diff --git a/test/CodeGenCXX/default-constructor-template-member.cpp b/test/CodeGenCXX/default-constructor-template-member.cpp index e74fb6d..422cc09 100644 --- a/test/CodeGenCXX/default-constructor-template-member.cpp +++ b/test/CodeGenCXX/default-constructor-template-member.cpp @@ -6,5 +6,5 @@ void a() { B b; } // CHECK: call void @_ZN1BC1Ev -// CHECK: define linkonce_odr void @_ZN1BC1Ev +// CHECK: define linkonce_odr void @_ZN1BC1Ev(%struct.B* %this) unnamed_addr // CHECK: call void @_ZN1AIiEC1Ev diff --git a/test/CodeGenCXX/delete-two-arg.cpp b/test/CodeGenCXX/delete-two-arg.cpp index 5358747..b82e9ba 100644 --- a/test/CodeGenCXX/delete-two-arg.cpp +++ b/test/CodeGenCXX/delete-two-arg.cpp @@ -1,6 +1,70 @@ // RUN: %clang_cc1 -triple i686-pc-linux-gnu %s -o - -emit-llvm -verify | FileCheck %s -struct A { void operator delete(void*,__typeof(sizeof(int))); int x; }; -void a(A* x) { delete x; } +typedef __typeof(sizeof(int)) size_t; -// CHECK: call void @_ZN1AdlEPvj(i8* %{{.*}}, i32 4) +namespace test1 { + struct A { void operator delete(void*,size_t); int x; }; + + // CHECK: define void @_ZN5test11aEPNS_1AE( + void a(A *x) { + // CHECK: load + // CHECK-NEXT: icmp eq {{.*}}, null + // CHECK-NEXT: br i1 + // CHECK: call void @_ZN5test11AdlEPvj(i8* %{{.*}}, i32 4) + delete x; + } +} + +// Check that we make cookies for the two-arg delete even when using +// the global allocator and deallocator. +namespace test2 { + struct A { + int x; + void *operator new[](size_t); + void operator delete[](void *, size_t); + }; + + // CHECK: define [[A:%.*]]* @_ZN5test24testEv() + A *test() { + // CHECK: [[NEW:%.*]] = call noalias i8* @_Znaj(i32 44) + // CHECK-NEXT: [[T0:%.*]] = bitcast i8* [[NEW]] to i32* + // CHECK-NEXT: store i32 10, i32* [[T0]] + // CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds i8* [[NEW]], i64 4 + // CHECK-NEXT: [[T2:%.*]] = bitcast i8* [[T1]] to [[A]]* + // CHECK-NEXT: ret [[A]]* [[T2]] + return ::new A[10]; + } + + // CHECK: define void @_ZN5test24testEPNS_1AE( + void test(A *p) { + // CHECK: [[P:%.*]] = alloca [[A]]*, align 4 + // CHECK-NEXT: store [[A]]* {{%.*}}, [[A]]** [[P]], align 4 + // CHECK-NEXT: [[T0:%.*]] = load [[A]]** [[P]], align 4 + // CHECK-NEXT: [[T1:%.*]] = icmp eq [[A]]* [[T0]], null + // CHECK-NEXT: br i1 [[T1]], + // CHECK: [[T2:%.*]] = bitcast [[A]]* [[T0]] to i8* + // CHECK-NEXT: [[T3:%.*]] = getelementptr inbounds i8* [[T2]], i64 -4 + // CHECK-NEXT: [[T4:%.*]] = bitcast i8* [[T3]] to i32* + // CHECK-NEXT: [[T5:%.*]] = load i32* [[T4]] + // CHECK-NEXT: call void @_ZdaPv(i8* [[T3]]) + // CHECK-NEXT: br label + ::delete[] p; + } +} + +// rdar://problem/8913519 +namespace test3 { + struct A { + int x; + void operator delete[](void *, size_t); + }; + struct B : A {}; + + // CHECK: define void @_ZN5test34testEv() + void test() { + // CHECK: call noalias i8* @_Znaj(i32 24) + // CHECK-NEXT: bitcast + // CHECK-NEXT: store i32 5 + (void) new B[5]; + } +} diff --git a/test/CodeGenCXX/delete.cpp b/test/CodeGenCXX/delete.cpp index 1f52a78..ddc7bb8 100644 --- a/test/CodeGenCXX/delete.cpp +++ b/test/CodeGenCXX/delete.cpp @@ -54,7 +54,7 @@ namespace test0 { delete a; } - // CHECK: define linkonce_odr void @_ZN5test01AD1Ev + // CHECK: define linkonce_odr void @_ZN5test01AD1Ev(%class.A* %this) unnamed_addr // CHECK: define linkonce_odr void @_ZN5test01AdlEPv } @@ -105,3 +105,10 @@ namespace test2 { delete [] b; } } + +namespace test3 { + void f(int a[10][20]) { + // CHECK: call void @_ZdaPv(i8* + delete a; + } +} diff --git a/test/CodeGenCXX/derived-to-base-conv.cpp b/test/CodeGenCXX/derived-to-base-conv.cpp index f2835b7..006f264 100644 --- a/test/CodeGenCXX/derived-to-base-conv.cpp +++ b/test/CodeGenCXX/derived-to-base-conv.cpp @@ -78,7 +78,7 @@ void test(Derived bb) // CHECK-LP64: callq __ZN1XcvR1BEv // CHECK-LP64: callq __ZN1AC1ERKS_ -// CHECK-LP32: call L__ZN1XcvR1BEv -// CHECK-LP32: call L__ZN1AC1ERKS_ +// CHECK-LP32: calll L__ZN1XcvR1BEv +// CHECK-LP32: calll L__ZN1AC1ERKS_ diff --git a/test/CodeGenCXX/derived-to-base.cpp b/test/CodeGenCXX/derived-to-base.cpp index e44fdc5..76b79fc 100644 --- a/test/CodeGenCXX/derived-to-base.cpp +++ b/test/CodeGenCXX/derived-to-base.cpp @@ -34,3 +34,14 @@ A *f(B* b) { } +// Don't crash on a derived-to-base conversion of an r-value +// aggregate. +namespace test3 { + struct A {}; + struct B : A {}; + + void foo(A a); + void test() { + foo(B()); + } +} diff --git a/test/CodeGenCXX/derived-to-virtual-base-class-calls-final.cpp b/test/CodeGenCXX/derived-to-virtual-base-class-calls-final.cpp new file mode 100644 index 0000000..e332f40 --- /dev/null +++ b/test/CodeGenCXX/derived-to-virtual-base-class-calls-final.cpp @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 %s -emit-llvm -o - | FileCheck %s + +struct A { int i; }; +struct B { int j; }; +struct C : A, B { int k; }; + +struct D final : virtual C { + D(); + virtual void f(); +}; + +// CHECK: define %struct.B* @_Z1fR1D +B &f(D &d) { + // CHECK-NOT: load i8** + return d; +} diff --git a/test/CodeGenCXX/destructors.cpp b/test/CodeGenCXX/destructors.cpp index 2eba30f..f382413 100644 --- a/test/CodeGenCXX/destructors.cpp +++ b/test/CodeGenCXX/destructors.cpp @@ -40,11 +40,11 @@ namespace PR7526 { struct allocator_derived : allocator { }; - // CHECK: define void @_ZN6PR75269allocatorD2Ev + // CHECK: define void @_ZN6PR75269allocatorD2Ev(%"struct.PR5529::A"* %this) unnamed_addr // CHECK: call void @__cxa_call_unexpected allocator::~allocator() throw() { foo(); } - // CHECK: define linkonce_odr void @_ZN6PR752617allocator_derivedD1Ev + // CHECK: define linkonce_odr void @_ZN6PR752617allocator_derivedD1Ev(%"struct.PR5529::A"* %this) unnamed_addr // CHECK-NOT: call void @__cxa_call_unexpected // CHECK: } void foo() { @@ -93,7 +93,7 @@ namespace test0 { // complete destructor alias tested above -// CHECK: define void @_ZN5test01AD2Ev +// CHECK: define void @_ZN5test01AD2Ev(%"struct.test0::A"* %this) unnamed_addr // CHECK: invoke void @_ZN5test06MemberD1Ev // CHECK: unwind label [[MEM_UNWIND:%[a-zA-Z0-9.]+]] // CHECK: invoke void @_ZN5test04BaseD2Ev @@ -106,7 +106,7 @@ namespace test0 { B::~B() try { } catch (int i) {} // It will suppress the delegation optimization here, though. -// CHECK: define void @_ZN5test01BD1Ev +// CHECK: define void @_ZN5test01BD1Ev(%"struct.test0::B"* %this) unnamed_addr // CHECK: invoke void @_ZN5test06MemberD1Ev // CHECK: unwind label [[MEM_UNWIND:%[a-zA-Z0-9.]+]] // CHECK: invoke void @_ZN5test04BaseD2Ev @@ -114,7 +114,7 @@ namespace test0 { // CHECK: invoke void @_ZN5test05VBaseD2Ev // CHECK: unwind label [[VBASE_UNWIND:%[a-zA-Z0-9.]+]] -// CHECK: define void @_ZN5test01BD2Ev +// CHECK: define void @_ZN5test01BD2Ev(%"struct.test0::B"* %this, i8** %vtt) unnamed_addr // CHECK: invoke void @_ZN5test06MemberD1Ev // CHECK: unwind label [[MEM_UNWIND:%[a-zA-Z0-9.]+]] // CHECK: invoke void @_ZN5test04BaseD2Ev @@ -142,24 +142,24 @@ namespace test1 { O::~O() {} // alias tested above struct P : NonEmpty, A { ~P(); }; - P::~P() {} // CHECK: define void @_ZN5test11PD2Ev + P::~P() {} // CHECK: define void @_ZN5test11PD2Ev(%"struct.test1::P"* %this) unnamed_addr struct Q : A, B { ~Q(); }; - Q::~Q() {} // CHECK: define void @_ZN5test11QD2Ev + Q::~Q() {} // CHECK: define void @_ZN5test11QD2Ev(%"struct.test1::M"* %this) unnamed_addr struct R : A { ~R(); }; - R::~R() { A a; } // CHECK: define void @_ZN5test11RD2Ev + R::~R() { A a; } // CHECK: define void @_ZN5test11RD2Ev(%"struct.test1::M"* %this) unnamed_addr struct S : A { ~S(); int x; }; S::~S() {} // alias tested above struct T : A { ~T(); B x; }; - T::~T() {} // CHECK: define void @_ZN5test11TD2Ev + T::~T() {} // CHECK: define void @_ZN5test11TD2Ev(%"struct.test1::T"* %this) unnamed_addr // The VTT parameter prevents this. We could still make this work // for calling conventions that are safe against extra parameters. struct U : A, virtual B { ~U(); }; - U::~U() {} // CHECK: define void @_ZN5test11UD2Ev + U::~U() {} // CHECK: define void @_ZN5test11UD2Ev(%"struct.test1::U"* %this, i8** %vtt) unnamed_addr } // PR6471 @@ -168,7 +168,7 @@ namespace test2 { struct B : A { ~B(); }; B::~B() {} - // CHECK: define void @_ZN5test21BD2Ev + // CHECK: define void @_ZN5test21BD2Ev(%"struct.test1::M"* %this) unnamed_addr // CHECK: call void @_ZN5test21AD2Ev } @@ -273,7 +273,7 @@ namespace test6 { }; C::C() { opaque(); } - // CHECK: define void @_ZN5test61CC1Ev + // CHECK: define void @_ZN5test61CC1Ev(%"struct.test6::C"* %this) unnamed_addr // CHECK: call void @_ZN5test61BILj2EEC2Ev // CHECK: invoke void @_ZN5test61BILj3EEC2Ev // CHECK: invoke void @_ZN5test61BILj0EEC2Ev @@ -283,7 +283,7 @@ namespace test6 { // FIXME: way too much EH cleanup code follows C::~C() { opaque(); } - // CHECK: define void @_ZN5test61CD1Ev + // CHECK: define void @_ZN5test61CD1Ev(%"struct.test6::C"* %this) unnamed_addr // CHECK: invoke void @_ZN5test61CD2Ev // CHECK: invoke void @_ZN5test61BILj3EED2Ev // CHECK: call void @_ZN5test61BILj2EED2Ev @@ -291,7 +291,7 @@ namespace test6 { // CHECK: invoke void @_ZN5test61BILj3EED2Ev // CHECK: invoke void @_ZN5test61BILj2EED2Ev - // CHECK: define void @_ZN5test61CD2Ev + // CHECK: define void @_ZN5test61CD2Ev(%"struct.test6::C"* %this, i8** %vtt) unnamed_addr // CHECK: invoke void @_ZN5test66opaqueEv // CHECK: invoke void @_ZN5test61AD1Ev // CHECK: invoke void @_ZN5test61AD1Ev @@ -306,9 +306,29 @@ namespace test6 { // CHECK: invoke void @_ZN5test61BILj0EED2Ev } +// PR 9197 +namespace test7 { + struct D { ~D(); }; + + struct A { ~A(); }; + A::~A() { } + + struct B : public A { + ~B(); + D arr[1]; + }; + + // Verify that this doesn't get emitted as an alias + // CHECK: define void @_ZN5test71BD2Ev( + // CHECK: invoke void @_ZN5test71DD1Ev( + // CHECK: call void @_ZN5test71AD2Ev( + B::~B() {} + +} + // Checks from test3: - // CHECK: define internal void @_ZN5test312_GLOBAL__N_11DD0Ev( + // CHECK: define internal void @_ZN5test312_GLOBAL__N_11DD0Ev(%"struct.test3::<anonymous namespace>::D"* %this) unnamed_addr // CHECK: invoke void @_ZN5test312_GLOBAL__N_11DD1Ev( // CHECK: call void @_ZdlPv({{.*}}) nounwind // CHECK: ret void @@ -330,7 +350,7 @@ namespace test6 { // CHECK: call void @_ZN5test312_GLOBAL__N_11DD0Ev( // CHECK: ret void - // CHECK: define internal void @_ZN5test312_GLOBAL__N_11CD2Ev( + // CHECK: define internal void @_ZN5test312_GLOBAL__N_11CD2Ev(%"struct.test3::<anonymous namespace>::C"* %this) unnamed_addr // CHECK: invoke void @_ZN5test31BD2Ev( // CHECK: call void @_ZN5test31AD2Ev( // CHECK: ret void @@ -338,7 +358,7 @@ namespace test6 { // CHECK: declare void @_ZN5test31BD2Ev( // CHECK: declare void @_ZN5test31AD2Ev( - // CHECK: define internal void @_ZN5test312_GLOBAL__N_11CD0Ev( + // CHECK: define internal void @_ZN5test312_GLOBAL__N_11CD0Ev(%"struct.test3::<anonymous namespace>::C"* %this) unnamed_addr // CHECK: invoke void @_ZN5test312_GLOBAL__N_11CD1Ev( // CHECK: call void @_ZdlPv({{.*}}) nounwind // CHECK: ret void diff --git a/test/CodeGenCXX/devirtualize-virtual-function-calls-final.cpp b/test/CodeGenCXX/devirtualize-virtual-function-calls-final.cpp new file mode 100644 index 0000000..3de75ed --- /dev/null +++ b/test/CodeGenCXX/devirtualize-virtual-function-calls-final.cpp @@ -0,0 +1,51 @@ +// RUN: %clang_cc1 %s -emit-llvm -o - | FileCheck %s + +namespace Test1 { + struct A { + virtual int f() final; + }; + + // CHECK: define i32 @_ZN5Test11fEPNS_1AE + int f(A *a) { + // CHECK: call i32 @_ZN5Test11A1fEv + return a->f(); + } +} + +namespace Test2 { + struct A final { + virtual int f(); + }; + + // CHECK: define i32 @_ZN5Test21fEPNS_1AE + int f(A *a) { + // CHECK: call i32 @_ZN5Test21A1fEv + return a->f(); + } +} + +namespace Test3 { + struct A { + virtual int f(); + }; + + struct B final : A { }; + + // CHECK: define i32 @_ZN5Test31fEPNS_1BE + int f(B *b) { + // CHECK: call i32 @_ZN5Test31A1fEv + return b->f(); + } + + // CHECK: define i32 @_ZN5Test31fERNS_1BE + int f(B &b) { + // CHECK: call i32 @_ZN5Test31A1fEv + return b.f(); + } + + // CHECK: define i32 @_ZN5Test31fEPv + int f(void *v) { + // CHECK: call i32 @_ZN5Test31A1fEv + return static_cast<B*>(v)->f(); + } +} diff --git a/test/CodeGenCXX/dyncast.cpp b/test/CodeGenCXX/dyncast.cpp index 723e12b..7fd5899 100644 --- a/test/CodeGenCXX/dyncast.cpp +++ b/test/CodeGenCXX/dyncast.cpp @@ -1,6 +1,5 @@ // RUN: %clang_cc1 -I%S -triple x86_64-apple-darwin -std=c++0x -emit-llvm %s -o %t.ll // RUN: FileCheck -check-prefix LL --input-file=%t.ll %s -// XFAIL: win32 #include <typeinfo> diff --git a/test/CodeGenCXX/eh.cpp b/test/CodeGenCXX/eh.cpp index 0960ec3..5ae65cc 100644 --- a/test/CodeGenCXX/eh.cpp +++ b/test/CodeGenCXX/eh.cpp @@ -10,16 +10,10 @@ void test1() { } // CHECK: define void @_Z5test1v() -// CHECK: [[FREEVAR:%.*]] = alloca i1 -// CHECK-NEXT: [[EXNOBJVAR:%.*]] = alloca i8* -// CHECK-NEXT: store i1 false, i1* [[FREEVAR]] -// CHECK-NEXT: [[EXNOBJ:%.*]] = call i8* @__cxa_allocate_exception(i64 8) -// CHECK-NEXT: store i8* [[EXNOBJ]], i8** [[EXNOBJVAR]] -// CHECK-NEXT: store i1 true, i1* [[FREEVAR]] +// CHECK: [[EXNOBJ:%.*]] = call i8* @__cxa_allocate_exception(i64 8) // CHECK-NEXT: [[EXN:%.*]] = bitcast i8* [[EXNOBJ]] to [[DSTAR:%[^*]*\*]] // CHECK-NEXT: [[EXN2:%.*]] = bitcast [[DSTAR]] [[EXN]] to i8* // CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[EXN2]], i8* bitcast ([[DSTAR]] @d1 to i8*), i64 8, i32 8, i1 false) -// CHECK-NEXT: store i1 false, i1* [[FREEVAR]] // CHECK-NEXT: call void @__cxa_throw(i8* [[EXNOBJ]], i8* bitcast (%0* @_ZTI7test1_D to i8*), i8* null) noreturn // CHECK-NEXT: unreachable @@ -36,20 +30,14 @@ void test2() { } // CHECK: define void @_Z5test2v() -// CHECK: [[FREEVAR:%.*]] = alloca i1 -// CHECK-NEXT: [[EXNOBJVAR:%.*]] = alloca i8* -// CHECK-NEXT: [[EXNSLOTVAR:%.*]] = alloca i8* +// CHECK: [[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]] -// CHECK-NEXT: store i1 true, i1* [[FREEVAR]] // CHECK-NEXT: [[EXN:%.*]] = bitcast i8* [[EXNOBJ]] to [[DSTAR:%[^*]*\*]] // CHECK-NEXT: invoke void @_ZN7test2_DC1ERKS_([[DSTAR]] [[EXN]], [[DSTAR]] @d2) // CHECK-NEXT: to label %[[CONT:.*]] unwind label %{{.*}} // : [[CONT]]: (can't check this in Release-Asserts builds) -// CHECK: store i1 false, i1* [[FREEVAR]] -// CHECK-NEXT: call void @__cxa_throw(i8* [[EXNOBJ]], i8* bitcast (%{{.*}}* @_ZTI7test2_D to i8*), i8* null) noreturn +// CHECK: call void @__cxa_throw(i8* [[EXNOBJ]], i8* bitcast (%{{.*}}* @_ZTI7test2_D to i8*), i8* null) noreturn // CHECK-NEXT: unreachable @@ -64,15 +52,9 @@ void test3() { } // CHECK: define void @_Z5test3v() -// CHECK: [[FREEVAR:%.*]] = alloca i1 -// CHECK-NEXT: [[EXNOBJVAR:%.*]] = alloca i8* -// CHECK-NEXT: store i1 false, i1* [[FREEVAR]] -// CHECK-NEXT: [[EXNOBJ:%.*]] = call i8* @__cxa_allocate_exception(i64 8) -// CHECK-NEXT: store i8* [[EXNOBJ]], i8** [[EXNOBJVAR]] -// CHECK-NEXT: store i1 true, i1* [[FREEVAR]] -// CHECK-NEXT: [[EXN:%.*]] = bitcast i8* [[EXNOBJ]] to [[DSS:%[^*]*\*]]* -// CHECK-NEXT: store [[DSS]] null, [[DSS]]* [[EXN]] -// CHECK-NEXT: store i1 false, i1* [[FREEVAR]] +// CHECK: [[EXNOBJ:%.*]] = call i8* @__cxa_allocate_exception(i64 8) +// CHECK-NEXT: [[EXN:%.*]] = bitcast i8* [[EXNOBJ]] to [[D:%[^*]+]]** +// CHECK-NEXT: store [[D]]* null, [[D]]** [[EXN]] // CHECK-NEXT: call void @__cxa_throw(i8* [[EXNOBJ]], i8* bitcast (%1* @_ZTIPV7test3_D to i8*), i8* null) noreturn // CHECK-NEXT: unreachable @@ -121,20 +103,14 @@ namespace test6 { namespace test7 { // CHECK: define i32 @_ZN5test73fooEv() int foo() { -// CHECK: [[FREEEXNOBJ:%.*]] = alloca i1 -// CHECK-NEXT: [[EXNALLOCVAR:%.*]] = alloca i8* -// CHECK-NEXT: [[CAUGHTEXNVAR:%.*]] = alloca i8* +// CHECK: [[CAUGHTEXNVAR:%.*]] = alloca i8* // CHECK-NEXT: [[INTCATCHVAR:%.*]] = alloca i32 // CHECK-NEXT: [[EHCLEANUPDESTVAR:%.*]] = alloca i32 -// CHECK-NEXT: store i1 false, i1* [[FREEEXNOBJ]] try { try { // CHECK-NEXT: [[EXNALLOC:%.*]] = call i8* @__cxa_allocate_exception -// CHECK-NEXT: store i8* [[EXNALLOC]], i8** [[EXNALLOCVAR]] -// CHECK-NEXT: store i1 true, i1* [[FREEEXNOBJ]] // CHECK-NEXT: bitcast i8* [[EXNALLOC]] to i32* // CHECK-NEXT: store i32 1, i32* -// CHECK-NEXT: store i1 false, i1* [[FREEEXNOBJ]] // CHECK-NEXT: invoke void @__cxa_throw(i8* [[EXNALLOC]], i8* bitcast (i8** @_ZTIi to i8*), i8* null throw 1; } @@ -197,11 +173,11 @@ namespace test9 { struct A { A(); }; - // CHECK: define void @_ZN5test91AC1Ev + // CHECK: define void @_ZN5test91AC1Ev(%"struct.test10::A"* %this) unnamed_addr // CHECK: call void @_ZN5test91AC2Ev // CHECK-NEXT: ret void - // CHECK: define void @_ZN5test91AC2Ev( + // CHECK: define void @_ZN5test91AC2Ev(%"struct.test10::A"* %this) unnamed_addr A::A() try { // CHECK: invoke void @_ZN5test96opaqueEv() opaque(); @@ -414,3 +390,49 @@ namespace test15 { // CHECK: call void @_ZN6test151AD1Ev } } + +namespace test16 { + struct A { A(); ~A(); }; + struct B { int x; B(const A &); ~B(); }; + void foo(); + bool cond(); + + // CHECK: define void @_ZN6test163barEv() + void bar() { + // CHECK: [[EXN_SAVE:%.*]] = alloca i8* + // CHECK-NEXT: [[EXN_ACTIVE:%.*]] = alloca i1 + // CHECK-NEXT: [[TEMP:%.*]] = alloca [[A:%.*]], + // CHECK-NEXT: [[EXNSLOT:%.*]] = alloca i8* + // CHECK-NEXT: [[EHDEST:%.*]] = alloca i32 + // CHECK-NEXT: [[TEMP_ACTIVE:%.*]] = alloca i1 + + cond() ? throw B(A()) : foo(); + + // CHECK-NEXT: [[COND:%.*]] = call zeroext i1 @_ZN6test164condEv() + // CHECK-NEXT: store i1 false, i1* [[EXN_ACTIVE]] + // CHECK-NEXT: store i1 false, i1* [[TEMP_ACTIVE]] + // CHECK-NEXT: br i1 [[COND]], + + // CHECK: [[EXN:%.*]] = call i8* @__cxa_allocate_exception(i64 4) + // CHECK-NEXT: store i8* [[EXN]], i8** [[EXN_SAVE]] + // CHECK-NEXT: store i1 true, i1* [[EXN_ACTIVE]] + // CHECK-NEXT: [[T0:%.*]] = bitcast i8* [[EXN]] to [[B:%.*]]* + // CHECK-NEXT: invoke void @_ZN6test161AC1Ev([[A]]* [[TEMP]]) + // CHECK: store i1 true, i1* [[TEMP_ACTIVE]] + // CHECK-NEXT: invoke void @_ZN6test161BC1ERKNS_1AE([[B]]* [[T0]], [[A]]* [[TEMP]]) + // CHECK: store i1 false, i1* [[EXN_ACTIVE]] + // CHECK-NEXT: invoke void @__cxa_throw(i8* [[EXN]], + + // CHECK: invoke void @_ZN6test163fooEv() + // CHECK: br label + + // CHECK: invoke void @_ZN6test161AD1Ev([[A]]* [[TEMP]]) + // CHECK: ret void + + // CHECK: [[T0:%.*]] = load i1* [[EXN_ACTIVE]] + // CHECK-NEXT: br i1 [[T0]] + // CHECK: [[T1:%.*]] = load i8** [[EXN_SAVE]] + // CHECK-NEXT: call void @__cxa_free_exception(i8* [[T1]]) + // CHECK-NEXT: br label + } +} diff --git a/test/CodeGenCXX/empty-classes.cpp b/test/CodeGenCXX/empty-classes.cpp index 59124e3..1ce1dad 100644 --- a/test/CodeGenCXX/empty-classes.cpp +++ b/test/CodeGenCXX/empty-classes.cpp @@ -53,6 +53,19 @@ int f() { return 0; } +namespace PR8796 { + struct FreeCell { + }; + union ThingOrCell { + FreeCell t; + FreeCell cell; + }; + struct Things { + ThingOrCell things; + }; + Things x; +} + #ifdef HARNESS extern "C" void printf(const char *, ...); diff --git a/test/CodeGenCXX/exceptions-no-rtti.cpp b/test/CodeGenCXX/exceptions-no-rtti.cpp index 66b4c4a..bbbc1b8 100644 --- a/test/CodeGenCXX/exceptions-no-rtti.cpp +++ b/test/CodeGenCXX/exceptions-no-rtti.cpp @@ -1,10 +1,10 @@ // RUN: %clang_cc1 -fno-rtti -fexceptions %s -triple=x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s -// CHECK: @_ZTIN5test11AE = weak_odr constant -// CHECK: @_ZTIN5test11BE = weak_odr constant -// CHECK: @_ZTIN5test11CE = weak_odr constant -// CHECK: @_ZTIN5test11DE = weak_odr constant -// CHECK: @_ZTIPN5test11DE = weak_odr constant {{.*}} @_ZTIN5test11DE +// CHECK: @_ZTIN5test11AE = linkonce_odr unnamed_addr constant +// CHECK: @_ZTIN5test11BE = linkonce_odr unnamed_addr constant +// CHECK: @_ZTIN5test11CE = linkonce_odr unnamed_addr constant +// CHECK: @_ZTIN5test11DE = linkonce_odr unnamed_addr constant +// CHECK: @_ZTIPN5test11DE = linkonce_odr unnamed_addr constant {{.*}} @_ZTIN5test11DE // PR6974: this shouldn't crash namespace test0 { diff --git a/test/CodeGenCXX/exceptions.cpp b/test/CodeGenCXX/exceptions.cpp index 4d8fb80..84d55c8 100644 --- a/test/CodeGenCXX/exceptions.cpp +++ b/test/CodeGenCXX/exceptions.cpp @@ -1,18 +1,295 @@ -// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -emit-llvm -o - -fexceptions +// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -emit-llvm -o - -fexceptions | FileCheck %s -struct allocator { - allocator(); - allocator(const allocator&); - ~allocator(); -}; +typedef typeof(sizeof(0)) size_t; -void f(); -void g(bool b, bool c) { - if (b) { - if (!c) - throw allocator(); +// This just shouldn't crash. +namespace test0 { + struct allocator { + allocator(); + allocator(const allocator&); + ~allocator(); + }; - return; + void f(); + void g(bool b, bool c) { + if (b) { + if (!c) + throw allocator(); + + return; + } + f(); + } +} + +namespace test1 { + struct A { A(int); A(int, int); ~A(); void *p; }; + + A *a() { + // CHECK: define [[A:%.*]]* @_ZN5test11aEv() + // CHECK: [[NEW:%.*]] = call noalias i8* @_Znwm(i64 8) + // CHECK-NEXT: [[CAST:%.*]] = bitcast i8* [[NEW]] to [[A]]* + // CHECK-NEXT: invoke void @_ZN5test11AC1Ei([[A]]* [[CAST]], i32 5) + // CHECK: ret [[A]]* [[CAST]] + // CHECK: call void @_ZdlPv(i8* [[NEW]]) + return new A(5); + } + + A *b() { + // CHECK: define [[A:%.*]]* @_ZN5test11bEv() + // CHECK: [[NEW:%.*]] = call noalias i8* @_Znwm(i64 8) + // CHECK-NEXT: [[CAST:%.*]] = bitcast i8* [[NEW]] to [[A]]* + // CHECK-NEXT: [[FOO:%.*]] = invoke i32 @_ZN5test13fooEv() + // CHECK: invoke void @_ZN5test11AC1Ei([[A]]* [[CAST]], i32 [[FOO]]) + // CHECK: ret [[A]]* [[CAST]] + // CHECK: call void @_ZdlPv(i8* [[NEW]]) + extern int foo(); + return new A(foo()); + } + + struct B { B(); ~B(); operator int(); int x; }; + B makeB(); + + A *c() { + // CHECK: define [[A:%.*]]* @_ZN5test11cEv() + // CHECK: [[ACTIVE:%.*]] = alloca i1 + // CHECK-NEXT: store i1 true, i1* [[ACTIVE]] + // CHECK-NEXT: [[NEW:%.*]] = call noalias i8* @_Znwm(i64 8) + // CHECK-NEXT: [[CAST:%.*]] = bitcast i8* [[NEW]] to [[A]]* + // CHECK-NEXT: invoke void @_ZN5test11BC1Ev([[B:%.*]]* [[T0:%.*]]) + // CHECK: [[T1:%.*]] = getelementptr inbounds [[B]]* [[T0]], i32 0, i32 0 + // CHECK-NEXT: [[T2:%.*]] = load i32* [[T1]], align 4 + // CHECK-NEXT: invoke void @_ZN5test11AC1Ei([[A]]* [[CAST]], i32 [[T2]]) + // CHECK: store i1 false, i1* [[ACTIVE]] + // CHECK-NEXT: invoke void @_ZN5test11BD1Ev([[B]]* [[T0]]) + // CHECK: ret [[A]]* [[CAST]] + // CHECK: [[ISACTIVE:%.*]] = load i1* [[ACTIVE]] + // CHECK-NEXT: br i1 [[ISACTIVE]] + // CHECK: call void @_ZdlPv(i8* [[NEW]]) + return new A(B().x); + } + + A *d() { + // CHECK: define [[A:%.*]]* @_ZN5test11dEv() + // CHECK: [[ACTIVE:%.*]] = alloca i1 + // CHECK-NEXT: store i1 true, i1* [[ACTIVE]] + // CHECK-NEXT: [[NEW:%.*]] = call noalias i8* @_Znwm(i64 8) + // CHECK-NEXT: [[CAST:%.*]] = bitcast i8* [[NEW]] to [[A]]* + // CHECK-NEXT: invoke void @_ZN5test11BC1Ev([[B:%.*]]* [[T0:%.*]]) + // CHECK: [[T1:%.*]] = invoke i32 @_ZN5test11BcviEv([[B]]* [[T0]]) + // CHECK: invoke void @_ZN5test11AC1Ei([[A]]* [[CAST]], i32 [[T1]]) + // CHECK: store i1 false, i1* [[ACTIVE]] + // CHECK-NEXT: invoke void @_ZN5test11BD1Ev([[B]]* [[T0]]) + // CHECK: ret [[A]]* [[CAST]] + // CHECK: [[ISACTIVE:%.*]] = load i1* [[ACTIVE]] + // CHECK-NEXT: br i1 [[ISACTIVE]] + // CHECK: call void @_ZdlPv(i8* [[NEW]]) + return new A(B()); + } + + A *e() { + // CHECK: define [[A:%.*]]* @_ZN5test11eEv() + // CHECK: [[ACTIVE:%.*]] = alloca i1 + // CHECK-NEXT: store i1 true, i1* [[ACTIVE]] + // CHECK-NEXT: [[NEW:%.*]] = call noalias i8* @_Znwm(i64 8) + // CHECK-NEXT: [[CAST:%.*]] = bitcast i8* [[NEW]] to [[A]]* + // CHECK-NEXT: invoke void @_ZN5test11BC1Ev([[B:%.*]]* [[T0:%.*]]) + // CHECK: [[T1:%.*]] = invoke i32 @_ZN5test11BcviEv([[B]]* [[T0]]) + // CHECK: invoke void @_ZN5test11BC1Ev([[B]]* [[T2:%.*]]) + // CHECK: [[T3:%.*]] = invoke i32 @_ZN5test11BcviEv([[B]]* [[T2]]) + // CHECK: invoke void @_ZN5test11AC1Eii([[A]]* [[CAST]], i32 [[T1]], i32 [[T3]]) + // CHECK: store i1 false, i1* [[ACTIVE]] + // CHECK-NEXT: invoke void @_ZN5test11BD1Ev([[B]]* [[T2]]) + // CHECK: invoke void @_ZN5test11BD1Ev([[B]]* [[T0]]) + // CHECK: ret [[A]]* [[CAST]] + // CHECK: [[ISACTIVE:%.*]] = load i1* [[ACTIVE]] + // CHECK-NEXT: br i1 [[ISACTIVE]] + // CHECK: call void @_ZdlPv(i8* [[NEW]]) + return new A(B(), B()); + } + A *f() { + return new A(makeB().x); + } + A *g() { + return new A(makeB()); + } + A *h() { + return new A(makeB(), makeB()); + } + + A *i() { + // CHECK: define [[A:%.*]]* @_ZN5test11iEv() + // CHECK: [[X:%.*]] = alloca [[A]]*, align 8 + // CHECK: [[ACTIVE:%.*]] = alloca i1 + // CHECK: store i1 true, i1* [[ACTIVE]] + // CHECK-NEXT: [[NEW:%.*]] = call noalias i8* @_Znwm(i64 8) + // CHECK-NEXT: [[CAST:%.*]] = bitcast i8* [[NEW]] to [[A]]* + // CHECK-NEXT: invoke void @_ZN5test15makeBEv([[B:%.*]]* sret [[T0:%.*]]) + // CHECK: [[T1:%.*]] = invoke i32 @_ZN5test11BcviEv([[B]]* [[T0]]) + // CHECK: invoke void @_ZN5test11AC1Ei([[A]]* [[CAST]], i32 [[T1]]) + // CHECK: store i1 false, i1* [[ACTIVE]] + // CHECK-NEXT: store [[A]]* [[CAST]], [[A]]** [[X]], align 8 + // CHECK: invoke void @_ZN5test15makeBEv([[B:%.*]]* sret [[T2:%.*]]) + // CHECK: [[RET:%.*]] = load [[A]]** [[X]], align 8 + // CHECK: invoke void @_ZN5test11BD1Ev([[B]]* [[T2]]) + // CHECK: invoke void @_ZN5test11BD1Ev([[B]]* [[T0]]) + // CHECK: ret [[A]]* [[RET]] + // CHECK: [[ISACTIVE:%.*]] = load i1* [[ACTIVE]] + // CHECK-NEXT: br i1 [[ISACTIVE]] + // CHECK: call void @_ZdlPv(i8* [[NEW]]) + A *x; + return (x = new A(makeB()), makeB(), x); + } +} + +namespace test2 { + struct A { + A(int); A(int, int); ~A(); + void *p; + void *operator new(size_t); + void operator delete(void*, size_t); + }; + + A *a() { + // CHECK: define [[A:%.*]]* @_ZN5test21aEv() + // CHECK: [[NEW:%.*]] = call i8* @_ZN5test21AnwEm(i64 8) + // CHECK-NEXT: [[CAST:%.*]] = bitcast i8* [[NEW]] to [[A]]* + // CHECK-NEXT: invoke void @_ZN5test21AC1Ei([[A]]* [[CAST]], i32 5) + // CHECK: ret [[A]]* [[CAST]] + // CHECK: invoke void @_ZN5test21AdlEPvm(i8* [[NEW]], i64 8) + // CHECK: call void @_ZSt9terminatev() + return new A(5); + } +} + +namespace test3 { + struct A { + A(int); A(int, int); A(const A&); ~A(); + void *p; + void *operator new(size_t, void*, double); + void operator delete(void*, void*, double); + }; + + void *foo(); + double bar(); + A makeA(), *makeAPtr(); + + A *a() { + // CHECK: define [[A:%.*]]* @_ZN5test31aEv() + // CHECK: [[FOO:%.*]] = call i8* @_ZN5test33fooEv() + // CHECK: [[BAR:%.*]] = call double @_ZN5test33barEv() + // CHECK: [[NEW:%.*]] = call i8* @_ZN5test31AnwEmPvd(i64 8, i8* [[FOO]], double [[BAR]]) + // CHECK-NEXT: [[CAST:%.*]] = bitcast i8* [[NEW]] to [[A]]* + // CHECK-NEXT: invoke void @_ZN5test31AC1Ei([[A]]* [[CAST]], i32 5) + // CHECK: ret [[A]]* [[CAST]] + // CHECK: invoke void @_ZN5test31AdlEPvS1_d(i8* [[NEW]], i8* [[FOO]], double [[BAR]]) + // CHECK: call void @_ZSt9terminatev() + return new(foo(),bar()) A(5); + } + + // rdar://problem/8439196 + A *b(bool cond) { + + // CHECK: define [[A:%.*]]* @_ZN5test31bEb(i1 zeroext + // CHECK: [[SAVED0:%.*]] = alloca i8* + // CHECK-NEXT: [[SAVED1:%.*]] = alloca i8* + // CHECK-NEXT: [[CLEANUPACTIVE:%.*]] = alloca i1 + // CHECK-NEXT: [[TMP:%.*]] = alloca [[A]], align 8 + // CHECK: [[TMPACTIVE:%.*]] = alloca i1 + // CHECK-NEXT: store i1 false, i1* [[CLEANUPACTIVE]] + + // CHECK: [[COND:%.*]] = trunc i8 {{.*}} to i1 + // CHECK-NEXT: store i1 false, i1* [[TMPACTIVE]] + // CHECK-NEXT: br i1 [[COND]] + return (cond ? + + // CHECK: [[FOO:%.*]] = call i8* @_ZN5test33fooEv() + // CHECK-NEXT: [[NEW:%.*]] = call i8* @_ZN5test31AnwEmPvd(i64 8, i8* [[FOO]], double [[CONST:.*]]) + // CHECK-NEXT: store i8* [[NEW]], i8** [[SAVED0]] + // CHECK-NEXT: store i8* [[FOO]], i8** [[SAVED1]] + // CHECK-NEXT: store i1 true, i1* [[CLEANUPACTIVE]] + // CHECK-NEXT: [[CAST:%.*]] = bitcast i8* [[NEW]] to [[A]]* + // CHECK-NEXT: invoke void @_ZN5test35makeAEv([[A]]* sret [[TMP]]) + // CHECK: store i1 true, i1* [[TMPACTIVE]] + // CHECK-NEXT: invoke void @_ZN5test31AC1ERKS0_([[A]]* [[CAST]], [[A]]* [[TMP]]) + // CHECK: store i1 false, i1* [[CLEANUPACTIVE]] + // CHECK-NEXT: br label + // -> cond.end + new(foo(),10.0) A(makeA()) : + + // CHECK: [[MAKE:%.*]] = invoke [[A]]* @_ZN5test38makeAPtrEv() + // CHECK: br label + // -> cond.end + makeAPtr()); + + // cond.end: + // CHECK: [[RESULT:%.*]] = phi [[A]]* {{.*}}[[CAST]]{{.*}}[[MAKE]] + // CHECK-NEXT: [[ISACTIVE:%.*]] = load i1* [[TMPACTIVE]] + // CHECK-NEXT: br i1 [[ISACTIVE]] + // CHECK: invoke void @_ZN5test31AD1Ev + // CHECK: ret [[A]]* [[RESULT]] + + // in the EH path: + // CHECK: [[ISACTIVE:%.*]] = load i1* [[CLEANUPACTIVE]] + // CHECK-NEXT: br i1 [[ISACTIVE]] + // CHECK: [[V0:%.*]] = load i8** [[SAVED0]] + // CHECK-NEXT: [[V1:%.*]] = load i8** [[SAVED1]] + // CHECK-NEXT: invoke void @_ZN5test31AdlEPvS1_d(i8* [[V0]], i8* [[V1]], double [[CONST]]) + } +} + +namespace test4 { + struct A { + A(int); A(int, int); ~A(); + void *p; + void *operator new(size_t, void*, void*); + void operator delete(void*, size_t, void*, void*); // not a match + }; + + A *a() { + // CHECK: define [[A:%.*]]* @_ZN5test41aEv() + // CHECK: [[FOO:%.*]] = call i8* @_ZN5test43fooEv() + // CHECK-NEXT: [[BAR:%.*]] = call i8* @_ZN5test43barEv() + // CHECK-NEXT: [[NEW:%.*]] = call i8* @_ZN5test41AnwEmPvS1_(i64 8, i8* [[FOO]], i8* [[BAR]]) + // CHECK-NEXT: [[CAST:%.*]] = bitcast i8* [[NEW]] to [[A]]* + // CHECK-NEXT: call void @_ZN5test41AC1Ei([[A]]* [[CAST]], i32 5) + // CHECK-NEXT: ret [[A]]* [[CAST]] + extern void *foo(), *bar(); + + return new(foo(),bar()) A(5); + } +} + +// PR7908 +namespace test5 { + struct T { T(); ~T(); }; + + struct A { + A(const A &x, const T &t = T()); + ~A(); + }; + + void foo(); + + // CHECK: define void @_ZN5test54testEv() + // CHECK: [[EXNSLOT:%.*]] = alloca i8* + // CHECK-NEXT: [[A:%.*]] = alloca [[A_T:%.*]], align 1 + // CHECK-NEXT: [[T:%.*]] = alloca [[T_T:%.*]], align 1 + // CHECK-NEXT: alloca i32 + // CHECK-NEXT: invoke void @_ZN5test53fooEv() + // CHECK: [[EXN:%.*]] = load i8** [[EXNSLOT]] + // CHECK-NEXT: [[ADJ:%.*]] = call i8* @__cxa_get_exception_ptr(i8* [[EXN]]) + // CHECK-NEXT: [[SRC:%.*]] = bitcast i8* [[ADJ]] to [[A_T]]* + // CHECK-NEXT: invoke void @_ZN5test51TC1Ev([[T_T]]* [[T]]) + // CHECK: invoke void @_ZN5test51AC1ERKS0_RKNS_1TE([[A_T]]* [[A]], [[A_T]]* [[SRC]], [[T_T]]* [[T]]) + // CHECK: invoke void @_ZN5test51TD1Ev([[T_T]]* [[T]]) + // CHECK: call i8* @__cxa_begin_catch(i8* [[EXN]]) nounwind + // CHECK-NEXT: invoke void @_ZN5test51AD1Ev([[A_T]]* [[A]]) + // CHECK: call void @__cxa_end_catch() + void test() { + try { + foo(); + } catch (A a) { + } } - f(); } diff --git a/test/CodeGenCXX/friend-redecl.cpp b/test/CodeGenCXX/friend-redecl.cpp new file mode 100644 index 0000000..18292cd --- /dev/null +++ b/test/CodeGenCXX/friend-redecl.cpp @@ -0,0 +1,18 @@ +// RUN: %clang_cc1 -triple i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s +// PR8864 + +struct Foo { + friend bool TryFoo(Foo *f2) { return TryFoo(0, f2); } + +// CHECK: define{{.*}}Z6TryFooP3Foo +// CHECK-NOT: ret +// CHECK: call{{.*}}Z6TryFooiP3Foo +// CHECK: ret + + friend bool TryFoo(int, Foo *f3); +}; +bool TryFoo(Foo *f5); +int main(void) { + Foo f; + TryFoo(&f); +} diff --git a/test/CodeGenCXX/global-init.cpp b/test/CodeGenCXX/global-init.cpp index 6ff9598..6003270 100644 --- a/test/CodeGenCXX/global-init.cpp +++ b/test/CodeGenCXX/global-init.cpp @@ -12,11 +12,17 @@ struct C { void *field; }; struct D { ~D(); }; +// CHECK: @__dso_handle = external unnamed_addr global i8* // 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]* +// PR6205: The casts should not require global initializers +// CHECK: @_ZN6PR59741cE = external global %"struct.PR5974::C" +// CHECK: @_ZN6PR59741aE = global %"struct.PR5974::A"* bitcast (%"struct.PR5974::C"* @_ZN6PR59741cE to %"struct.PR5974::A"*), align 8 +// CHECK: @_ZN6PR59741bE = global %"struct.PR5974::A"* bitcast (i8* getelementptr (%"struct.PR5974::C"* @_ZN6PR59741cE, i32 0, i32 0, i64 4) to %"struct.PR5974::A"*), align 8 + // 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; @@ -64,6 +70,17 @@ namespace test3 { const char *test() { return var; } } +namespace PR5974 { + struct A { int a; }; + struct B { int b; }; + struct C : A, B { int c; }; + + extern C c; + + // These should not require global initializers. + A* a = &c; + B* b = &c; +} // CHECK: define internal void [[TEST1_Z_INIT:@.*]]() // CHECK: load i32* @_ZN5test1L1yE // CHECK-NEXT: xor diff --git a/test/CodeGenCXX/gnu-conditional-scalar-ext.cpp b/test/CodeGenCXX/gnu-conditional-scalar-ext.cpp new file mode 100644 index 0000000..fea8364 --- /dev/null +++ b/test/CodeGenCXX/gnu-conditional-scalar-ext.cpp @@ -0,0 +1,62 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm -o - %s | FileCheck %s +// rdar: // 8353567 +// pr7726 + +extern "C" int printf(...); + +void test0() { +// CHECK: call i32 (...)* @printf({{.*}}, i8* inttoptr (i64 3735928559 to i8*)) + printf("%p\n", (void *)0xdeadbeef ? : (void *)0xaaaaaa); +} + +// rdar://8446940 +namespace radar8446940 { +extern "C" void abort(); + +int main () { + char x[1]; + char *y = x ? : 0; + + if (x != y) + abort(); +} +} + +namespace radar8453812 { +extern "C" void abort(); +_Complex int getComplex(_Complex int val) { + static int count; + if (count++) + abort(); + return val; +} + +_Complex int cmplx() { + _Complex int cond; + _Complex int rhs; + + return getComplex(1+2i) ? : rhs; +} + +// lvalue test +void foo (int& lv) { + ++lv; +} + +int global = 1; + +int &cond() { + static int count; + if (count++) + abort(); + return global; +} + + +int main() { + cmplx(); + int rhs = 10; + foo (cond()? : rhs); + return global-2; +} +} diff --git a/test/CodeGenCXX/goto.cpp b/test/CodeGenCXX/goto.cpp new file mode 100644 index 0000000..938d4e1 --- /dev/null +++ b/test/CodeGenCXX/goto.cpp @@ -0,0 +1,43 @@ +// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -fexceptions -emit-llvm -o - | FileCheck %s + +// Reduced from a crash on boost::interprocess's node_allocator_test.cpp. +namespace test0 { + struct A { A(); ~A(); }; + struct V { V(const A &a = A()); ~V(); }; + + // CHECK: define linkonce_odr i32 @_ZN5test04testILi0EEEii + template<int X> int test(int x) { + // CHECK: [[RET:%.*]] = alloca i32 + // CHECK-NEXT: [[X:%.*]] = alloca i32 + // CHECK-NEXT: [[Y:%.*]] = alloca [[A:%.*]], + // CHECK-NEXT: [[Z:%.*]] = alloca [[A]] + // CHECK-NEXT: [[EXN:%.*]] = alloca i8* + // CHECK-NEXT: alloca i32 + // CHECK-NEXT: [[V:%.*]] = alloca [[V:%.*]]*, + // CHECK-NEXT: [[TMP:%.*]] = alloca [[A]] + // CHECK-NEXT: [[CLEANUPACTIVE:%.*]] = alloca i1 + // CHECK: store i1 true, i1* [[CLEANUPACTIVE]] + // CHECK: call void @_ZN5test01AC1Ev([[A]]* [[Y]]) + // CHECK-NEXT: invoke void @_ZN5test01AC1Ev([[A]]* [[Z]]) + // CHECK: [[NEW:%.*]] = invoke noalias i8* @_Znwm(i64 1) + // CHECK: [[NEWCAST:%.*]] = bitcast i8* [[NEW]] to [[V]]* + // CHECK-NEXT: invoke void @_ZN5test01AC1Ev([[A]]* [[TMP]]) + // CHECK: invoke void @_ZN5test01VC1ERKNS_1AE([[V]]* [[NEWCAST]], [[A]]* [[TMP]]) + // CHECK: store i1 false, i1* [[CLEANUPACTIVE]] + // CHECK-NEXT: invoke void @_ZN5test01AD1Ev([[A]]* [[TMP]]) + A y; + try { + A z; + V *v = new V(); + + if (x) return 1; + } catch (int ex) { + return 1; + } + return 0; + } + + int test() { + return test<0>(5); + } +} diff --git a/test/CodeGenCXX/implicit-copy-constructor.cpp b/test/CodeGenCXX/implicit-copy-constructor.cpp index a343dd1..5008601 100644 --- a/test/CodeGenCXX/implicit-copy-constructor.cpp +++ b/test/CodeGenCXX/implicit-copy-constructor.cpp @@ -40,7 +40,7 @@ void f(D d) { D d2(d); } -// CHECK: define linkonce_odr void @_ZN1DC1ERS_ +// CHECK: define linkonce_odr void @_ZN1DC1ERS_(%struct.D* %this, %struct.D*) unnamed_addr // CHECK: call void @_ZN1AC1Ev // CHECK: call void @_ZN1CC2ERS_1A // CHECK: call void @_ZN1AD1Ev diff --git a/test/CodeGenCXX/inline-functions.cpp b/test/CodeGenCXX/inline-functions.cpp index 8d046a2..69dfe0d 100644 --- a/test/CodeGenCXX/inline-functions.cpp +++ b/test/CodeGenCXX/inline-functions.cpp @@ -21,3 +21,35 @@ void B<char>::f() { } // CHECK: define void @_Z1fv void f() { } + +// <rdar://problem/8740363> +inline void f1(int); + +// CHECK: define linkonce_odr void @_Z2f1i +void f1(int) { } + +void test_f1() { f1(17); } + +// PR8789 +namespace test1 { + template <typename T> class ClassTemplate { + private: + friend void T::func(); + void g() {} + }; + + // CHECK: define linkonce_odr void @_ZN5test11C4funcEv( + + class C { + public: + void func() { + ClassTemplate<C> ct; + ct.g(); + } + }; + + void f() { + C c; + c.func(); + } +} diff --git a/test/CodeGenCXX/internal-linkage.cpp b/test/CodeGenCXX/internal-linkage.cpp index 9fdb727..39bce85 100644 --- a/test/CodeGenCXX/internal-linkage.cpp +++ b/test/CodeGenCXX/internal-linkage.cpp @@ -1,11 +1,11 @@ // RUN: %clang_cc1 -emit-llvm -o - %s | FileCheck %s struct Global { Global(); }; -template<typename T> struct X { X(); }; +template<typename T> struct X { X() {} }; namespace { - struct Anon { Anon(); }; + struct Anon { Anon() {} }; // CHECK: @_ZN12_GLOBAL__N_15anon0E = internal global Global anon0; diff --git a/test/CodeGenCXX/key-function-vtable.cpp b/test/CodeGenCXX/key-function-vtable.cpp index 15c058d..8e474bd 100644 --- a/test/CodeGenCXX/key-function-vtable.cpp +++ b/test/CodeGenCXX/key-function-vtable.cpp @@ -30,6 +30,7 @@ void testf::a() {} namespace { struct testg { virtual void a(); }; } +void testg::a() {} testg *testgvar = new testg; struct X0 { virtual ~X0(); }; @@ -43,9 +44,9 @@ void use_X1(X1 *x1) { x1->f(); } // FIXME: The checks are extremely difficult to get right when the globals // aren't alphabetized -// CHECK: @_ZTV2X1 = weak_odr constant -// CHECK: @_ZTV5testa = constant [3 x i8*] [i8* null -// CHECK: @_ZTV5testc = weak_odr constant [3 x i8*] [i8* null -// CHECK: @_ZTVN12_GLOBAL__N_15testgE = internal constant [3 x i8*] [i8* null -// CHECK: @_ZTV5teste = weak_odr constant [3 x i8*] [i8* null -// CHECK: @_ZTV5testb = weak_odr constant [3 x i8*] [i8* null +// CHECK: @_ZTV2X1 = linkonce_odr unnamed_addr constant +// CHECK: @_ZTV5testa = unnamed_addr constant [3 x i8*] [i8* null +// CHECK: @_ZTV5testc = linkonce_odr unnamed_addr constant [3 x i8*] [i8* null +// CHECK: @_ZTVN12_GLOBAL__N_15testgE = internal unnamed_addr constant [3 x i8*] [i8* null +// CHECK: @_ZTV5teste = linkonce_odr unnamed_addr constant [3 x i8*] [i8* null +// CHECK: @_ZTV5testb = linkonce_odr unnamed_addr constant [3 x i8*] [i8* null diff --git a/test/CodeGenCXX/mangle-abi-examples.cpp b/test/CodeGenCXX/mangle-abi-examples.cpp new file mode 100644 index 0000000..7124078 --- /dev/null +++ b/test/CodeGenCXX/mangle-abi-examples.cpp @@ -0,0 +1,27 @@ +// RUN: %clang_cc1 %s -emit-llvm -o - | FileCheck %s + +// CHECK: @_ZTVZ3foovEN1C1DE = +// CHECK: @_ZTVZN1A3fooEiE1B = +// CHECK: define {{.*}} @_ZZZ3foovEN1C3barEvEN1E3bazEv( + +// Itanium C++ ABI examples. +struct A { + void foo (int) { + struct B { virtual ~B() {} }; + B(); + } +}; +void foo () { + struct C { + struct D { virtual ~D() {} }; + void bar () { + struct E { + void baz() { } + }; + E().baz(); + } + }; + A().foo(0); + C::D(); + C().bar(); +} diff --git a/test/CodeGenCXX/mangle-local-class-vtables.cpp b/test/CodeGenCXX/mangle-local-class-vtables.cpp new file mode 100644 index 0000000..d9d3afe --- /dev/null +++ b/test/CodeGenCXX/mangle-local-class-vtables.cpp @@ -0,0 +1,61 @@ +// RUN: %clang_cc1 %s -emit-llvm -o - | FileCheck %s + +// CHECK: @_ZTVZN1J1KEvE1C = {{.*}} @_ZTIZN1J1KEvE1C {{.*}} @_ZZN1J1KEvENK1C1FEv +// CHECK: @_ZTIZN1J1KEvE1C = {{.*}} @_ZTSZN1J1KEvE1C +// CHECK: @_ZTVZ1GvE1C_1 = {{.*}} @_ZTIZ1GvE1C_1 {{.*}} @_ZZ1GvENK1C1FE_1v +// CHECK: @_ZTIZ1GvE1C_1 = {{.*}} @_ZTSZ1GvE1C_1 +// CHECK: @_ZTVZ1GvE1C_0 = {{.*}} @_ZTIZ1GvE1C_0 {{.*}} @_ZZ1GvENK1C1FE_0v +// CHECK: @_ZTIZ1GvE1C_0 = {{.*}} @_ZTSZ1GvE1C_0 +// CHECK: @_ZTVZ1GvE1C = {{.*}} @_ZTIZ1GvE1C {{.*}} @_ZZ1GvENK1C1FEv +// CHECK: @_ZTIZ1GvE1C = {{.*}} @_ZTSZ1GvE1C + +// CHECK: define {{.*}} @_ZZN1J1KEvEN1CC2Ev( +// CHECK: define {{.*}} @_ZZN1J1KEvENK1C1FEv( +// CHECK: define {{.*}} @_ZZ1GvEN1CC2E_1v( +// CHECK: define {{.*}} @_ZZ1GvENK1C1FE_1v( +// CHECK: define {{.*}} @_ZZ1GvENK1C1HE_1v( +// CHECK: define {{.*}} @_ZZ1GvEN1CC2E_0v( +// CHECK: define {{.*}} @_ZZ1GvENK1C1FE_0v( +// CHECK: define {{.*}} @_ZZ1GvENK1C1GE_0v( +// CHECK: define {{.*}} @_ZZ1GvEN1CC2Ev( +// CHECK: define {{.*}} @_ZZ1GvENK1C1FEv( + +struct I { + virtual void F() const = 0; +}; + +void Go(const I &i); + +void G() { + { + struct C : I { + void F() const {} + }; + Go(C()); + } + { + struct C : I { + void F() const { G(); } + void G() const {} + }; + Go(C()); + } + { + struct C : I { + void F() const { H(); } + void H() const {} + }; + Go(C()); + } +} + +struct J { + void K(); +}; + +void J::K() { + struct C : I { + void F() const {} + }; + Go(C()); +} diff --git a/test/CodeGenCXX/mangle-local-classes-nested.cpp b/test/CodeGenCXX/mangle-local-classes-nested.cpp new file mode 100644 index 0000000..fafa5d4 --- /dev/null +++ b/test/CodeGenCXX/mangle-local-classes-nested.cpp @@ -0,0 +1,81 @@ +// RUN: %clang_cc1 %s -emit-llvm -o - | FileCheck %s + +// CHECK: @_ZTVZZ1HvEN1S1IEvE1S = + +// CHECK: define {{.*}} @_Z2L1v( +// CHECK: define {{.*}} @_ZZ2L1vEN1S2L2Ev( +// CHECK: define {{.*}} @_ZZ2L1vEN1S2L2E_0v( +// CHECK: define {{.*}} @_ZZ1FvEN1S1T1S1T1GEv( +// CHECK: define {{.*}} @_ZZZ2L1vEN1S2L2E_0vEN1S3L3cEv( +// CHECK: define {{.*}} @_ZZZ2L1vEN1S2L2E_0vEN1S3L3dE_0v( +// CHECK: define {{.*}} @_ZZZ2L1vEN1S2L2EvEN1S3L3aEv( +// CHECK: define {{.*}} @_ZZZ2L1vEN1S2L2EvEN1S3L3bE_0v( + +void L1() { + { + struct S { + void L2() { + { + struct S { + void L3a() {} + }; + S().L3a(); + } + { + struct S { + void L3b() {} + }; + S().L3b(); + } + } + }; + S().L2(); + } + { + struct S { + void L2() { + { + struct S { + void L3c() {} + }; + S().L3c(); + } + { + struct S { + void L3d() {} + }; + S().L3d(); + } + } + }; + S().L2(); + } +} + +void F() { + struct S { + struct T { + struct S { + struct T { + void G() {} + }; + }; + }; + }; + S::T::S::T().G(); +} + +struct B { virtual void Foo() = 0; }; +void G(const B &); + +void H() { + struct S { + void I() { + struct S : B { + virtual void Foo() {} + }; + G(S()); + } + }; + S().I(); +} diff --git a/test/CodeGenCXX/mangle-ms.cpp b/test/CodeGenCXX/mangle-ms.cpp index 61f8a59..d8d75b7 100644 --- a/test/CodeGenCXX/mangle-ms.cpp +++ b/test/CodeGenCXX/mangle-ms.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fms-extensions -fblocks -emit-llvm %s -o - -cxx-abi microsoft -triple=i386-apple-darwin10 | FileCheck %s +// RUN: %clang_cc1 -fms-extensions -fblocks -emit-llvm %s -o - -cxx-abi microsoft -triple=i386-pc-win32 | FileCheck %s // CHECK: @"\01?a@@3HA" // CHECK: @"\01?b@N@@3HA" @@ -11,7 +11,7 @@ // CHECK: @"\01?i@@3PAY0BE@HA" // CHECK: @"\01?j@@3P6GHCE@ZA" // CHECK: @"\01?k@@3PTfoo@@DA" -// CHECK: @"\01?l@@3P8foo@@AAHH@ZA" +// CHECK: @"\01?l@@3P8foo@@AEHH@ZA" int a; @@ -46,10 +46,8 @@ enum quux { qthree }; -// NOTE: The calling convention is supposed to be __thiscall by default, -// but that needs to be fixed in Sema/AST. int foo::operator+(int a) {return a;} -// CHECK: @"\01??Hfoo@@QAAHH@Z" +// CHECK: @"\01??Hfoo@@QAEHH@Z" const short foo::d = 0; volatile long foo::e; diff --git a/test/CodeGenCXX/mangle-neon-vectors.cpp b/test/CodeGenCXX/mangle-neon-vectors.cpp new file mode 100644 index 0000000..3723deb --- /dev/null +++ b/test/CodeGenCXX/mangle-neon-vectors.cpp @@ -0,0 +1,32 @@ +// RUN: %clang_cc1 %s -emit-llvm -o - | FileCheck %s + +typedef float float32_t; +typedef signed char poly8_t; +typedef short poly16_t; +typedef unsigned long long uint64_t; + +typedef __attribute__((neon_vector_type(2))) int int32x2_t; +typedef __attribute__((neon_vector_type(4))) int int32x4_t; +typedef __attribute__((neon_vector_type(1))) uint64_t uint64x1_t; +typedef __attribute__((neon_vector_type(2))) uint64_t uint64x2_t; +typedef __attribute__((neon_vector_type(2))) float32_t float32x2_t; +typedef __attribute__((neon_vector_type(4))) float32_t float32x4_t; +typedef __attribute__((neon_polyvector_type(16))) poly8_t poly8x16_t; +typedef __attribute__((neon_polyvector_type(8))) poly16_t poly16x8_t; + +// CHECK: 16__simd64_int32_t +void f1(int32x2_t v) { } +// CHECK: 17__simd128_int32_t +void f2(int32x4_t v) { } +// CHECK: 17__simd64_uint64_t +void f3(uint64x1_t v) { } +// CHECK: 18__simd128_uint64_t +void f4(uint64x2_t v) { } +// CHECK: 18__simd64_float32_t +void f5(float32x2_t v) { } +// CHECK: 19__simd128_float32_t +void f6(float32x4_t v) { } +// CHECK: 17__simd128_poly8_t +void f7(poly8x16_t v) { } +// CHECK: 18__simd128_poly16_t +void f8(poly16x8_t v) { } diff --git a/test/CodeGenCXX/mangle-ref-qualifiers.cpp b/test/CodeGenCXX/mangle-ref-qualifiers.cpp new file mode 100644 index 0000000..b3f37d7 --- /dev/null +++ b/test/CodeGenCXX/mangle-ref-qualifiers.cpp @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -std=c++0x -triple x86_64-apple-darwin10 -emit-llvm -o - %s | FileCheck %s +struct X { + int f() &; + int g() &&; + int h() const &&; +}; + +// CHECK: define i32 @_ZNR1X1fEv +int X::f() & { return 0; } +// CHECK: define i32 @_ZNO1X1gEv +int X::g() && { return 0; } +// CHECK: define i32 @_ZNKO1X1hEv +int X::h() const && { return 0; } + +// CHECK: define void @_Z1fM1XRFivEMS_OFivEMS_KOFivE +void f(int (X::*)() &, int (X::*)() &&, int (X::*)() const&&) { } diff --git a/test/CodeGenCXX/mangle-subst-std.cpp b/test/CodeGenCXX/mangle-subst-std.cpp index 9c1e978..8d79988 100644 --- a/test/CodeGenCXX/mangle-subst-std.cpp +++ b/test/CodeGenCXX/mangle-subst-std.cpp @@ -3,19 +3,19 @@ // Check mangling of Vtables, VTTs, and construction vtables that // involve standard substitutions. -// CHECK: @_ZTVSd = weak_odr constant +// CHECK: @_ZTTSd = linkonce_odr unnamed_addr constant +// CHECK: @_ZTVSd = linkonce_odr unnamed_addr constant // CHECK: @_ZTCSd0_Si = internal constant // CHECK: @_ZTCSd16_So = internal constant -// CHECK: @_ZTTSd = weak_odr constant -// CHECK: @_ZTVSo = weak_odr constant -// CHECK: @_ZTTSo = weak_odr constant -// CHECK: @_ZTVSi = weak_odr constant -// CHECK: @_ZTTSi = weak_odr constant +// CHECK: @_ZTTSo = linkonce_odr unnamed_addr constant +// CHECK: @_ZTVSo = linkonce_odr unnamed_addr constant +// CHECK: @_ZTTSi = linkonce_odr unnamed_addr constant +// CHECK: @_ZTVSi = linkonce_odr unnamed_addr constant namespace std { struct A { A(); }; - // CHECK: define void @_ZNSt1AC1Ev - // CHECK: define void @_ZNSt1AC2Ev + // CHECK: define void @_ZNSt1AC1Ev(%"struct.N::std::A"* %this) unnamed_addr + // CHECK: define void @_ZNSt1AC2Ev(%"struct.N::std::A"* %this) unnamed_addr A::A() { } }; diff --git a/test/CodeGenCXX/mangle-template.cpp b/test/CodeGenCXX/mangle-template.cpp index 6a29944..463f15d 100644 --- a/test/CodeGenCXX/mangle-template.cpp +++ b/test/CodeGenCXX/mangle-template.cpp @@ -82,7 +82,7 @@ namespace test7 { X(U*, typename int_c<(meta<T>::value + meta<U>::value)>::type *) { } }; - // CHECK: define weak_odr void @_ZN5test71XIiEC1IdEEPT_PNS_5int_cIXplL_ZNS_4metaIiE5valueEEsrNS6_IS3_EE5valueEE4typeE + // CHECK: define weak_odr void @_ZN5test71XIiEC1IdEEPT_PNS_5int_cIXplL_ZNS_4metaIiE5valueEEsrNS6_IS3_EE5valueEE4typeE(%"class.test1::T"* %this, double*, float*) unnamed_addr template X<int>::X(double*, float*); } diff --git a/test/CodeGenCXX/mangle-unnamed.cpp b/test/CodeGenCXX/mangle-unnamed.cpp index 83b46d6..53f381c 100644 --- a/test/CodeGenCXX/mangle-unnamed.cpp +++ b/test/CodeGenCXX/mangle-unnamed.cpp @@ -69,3 +69,24 @@ int f7() { // CHECK: _ZZ2f7vE1a return a.b; } + +// This used to cause an assert because the typedef-for-anonymous-tag +// code was trying to claim the enum for the template. +enum { T8 }; +template <class T> struct Test8 { + typedef T type; + Test8(type t) {} // tested later +}; +template <class T> void make_test8(T value) { Test8<T> t(value); } +void test8() { make_test8(T8); } + +// CHECK: define internal void @"_ZNV3$_35test9Ev"( +typedef volatile struct { + void test9() volatile {} +} Test9; +void test9() { + Test9 a; + a.test9(); +} + +// CHECK: define internal void @"_ZN5Test8I3$_2EC1ES0_"( diff --git a/test/CodeGenCXX/mangle-variadic-templates.cpp b/test/CodeGenCXX/mangle-variadic-templates.cpp new file mode 100644 index 0000000..a987b49 --- /dev/null +++ b/test/CodeGenCXX/mangle-variadic-templates.cpp @@ -0,0 +1,67 @@ +// RUN: %clang_cc1 -std=c++0x -emit-llvm -triple=x86_64-apple-darwin9 -o - %s | FileCheck %s + +template<unsigned I, typename ...Types> +struct X { }; + +template<typename T> struct identity { }; +template<typename T> struct add_reference; +template<typename ...Types> struct tuple { }; +template<int ...Values> struct int_tuple { }; +template<template<typename> class ...Templates> struct template_tuple { }; + +// CHECK: define weak_odr void @_Z2f0IJEEv1XIXsZT_EJDpRT_EE +template<typename ...Types> +void f0(X<sizeof...(Types), Types&...>) { } + +template void f0(X<0>); + +// CHECK: define weak_odr void @_Z2f0IJifdEEv1XIXsZT_EJDpRT_EE +template void f0<int, float, double>(X<3, int&, float&, double&>); + +// Mangling for template argument packs +template<typename ...Types> void f1() {} +// CHECK: define weak_odr void @_Z2f1IJEEvv +template void f1<>(); +// CHECK: define weak_odr void @_Z2f1IJiEEvv +template void f1<int>(); +// CHECK: define weak_odr void @_Z2f1IJifEEvv +template void f1<int, float>(); + +// Mangling function parameter packs +template<typename ...Types> void f2(Types...) {} +// CHECK: define weak_odr void @_Z2f2IJEEvDpT_ +template void f2<>(); +// CHECK: define weak_odr void @_Z2f2IJiEEvDpT_ +template void f2<int>(int); +// CHECK: define weak_odr void @_Z2f2IJifEEvDpT_ +template void f2<int, float>(int, float); + +// Mangling non-trivial function parameter packs +template<typename ...Types> void f3(const Types *...) {} +// CHECK: define weak_odr void @_Z2f3IJEEvDpPKT_ +template void f3<>(); +// CHECK: define weak_odr void @_Z2f3IJiEEvDpPKT_ +template void f3<int>(const int*); +// CHECK: define weak_odr void @_Z2f3IJifEEvDpPKT_ +template void f3<int, float>(const int*, const float*); + +// Mangling of type pack expansions in a template argument +template<typename ...Types> tuple<Types...> f4() {} +// CHECK: define weak_odr void @_Z2f4IJifdEE5tupleIJDpT_EEv +template tuple<int, float, double> f4(); + +// Mangling of type pack expansions in a function type +template<typename R, typename ...ArgTypes> identity<R(ArgTypes...)> f5() {} +// CHECK: define weak_odr void @_Z2f5IiJifdEE8identityIFT_DpT0_EEv +template identity<int(int, float, double)> f5(); + +// Mangling of non-type template argument expansions +template<int ...Values> int_tuple<Values...> f6() {} +// CHECK: define weak_odr void @_Z2f6IJLi1ELi2ELi3EEE9int_tupleIJXspT_EEEv +template int_tuple<1, 2, 3> f6(); + +// Mangling of template template argument expansions +template<template<typename> class ...Templates> +template_tuple<Templates...> f7() {} +// CHECK: define weak_odr void @_Z2f7IJ8identity13add_referenceEE14template_tupleIJDpT_EEv +template template_tuple<identity, add_reference> f7(); diff --git a/test/CodeGenCXX/mangle.cpp b/test/CodeGenCXX/mangle.cpp index 55357c7..ec496fe 100644 --- a/test/CodeGenCXX/mangle.cpp +++ b/test/CodeGenCXX/mangle.cpp @@ -624,3 +624,26 @@ namespace test20 { template <class T> void test1(decltype(f<>(T()))) {} template void test1<int>(decltype(f<>(int()))); } + +// rdar:// 8620510 +namespace test21 { + // CHECK: define void @_ZN6test2112vla_arg_funcEiPA_i( + void vla_arg_func(int X, int a[X][X]) {} +} + +namespace test22 { + // CHECK: define void @_ZN6test221fEDn( + void f(decltype(nullptr)) { } +} + +// rdar://problem/8913416 +namespace test23 { + typedef void * const vpc; + + // CHECK: define void @_ZN6test231fERA10_KPv( + void f(vpc (&)[10]) {} + + typedef vpc vpca5[5]; + void f(vpca5 volatile (&)[10]) {} + // CHECK: define void @_ZN6test231fERA10_A5_VKPv( +} diff --git a/test/CodeGenCXX/member-functions.cpp b/test/CodeGenCXX/member-functions.cpp index a60d24a..b95763c 100644 --- a/test/CodeGenCXX/member-functions.cpp +++ b/test/CodeGenCXX/member-functions.cpp @@ -20,9 +20,9 @@ void test1() { struct S { - // RUN: grep "define linkonce_odr void @_ZN1SC1Ev" %t + // RUN: grep "define linkonce_odr void @_ZN1SC1Ev.*unnamed_addr" %t inline S() { } - // RUN: grep "define linkonce_odr void @_ZN1SC1Ev" %t + // RUN: grep "define linkonce_odr void @_ZN1SC1Ev.*unnamed_addr" %t inline ~S() { } diff --git a/test/CodeGenCXX/member-init-assignment.cpp b/test/CodeGenCXX/member-init-assignment.cpp index 57ab7eb..128cb88 100644 --- a/test/CodeGenCXX/member-init-assignment.cpp +++ b/test/CodeGenCXX/member-init-assignment.cpp @@ -10,7 +10,7 @@ struct Foo { Foo::Foo(unsigned arg) : file_id(arg = 42) { } -// CHECK: define void @_ZN3FooC2Ej +// CHECK: define void @_ZN3FooC2Ej(%struct.Foo* %this, i32 %arg) unnamed_addr // CHECK: [[ARG:%.*]] = alloca i32 // CHECK: store i32 42, i32* [[ARG]] // CHECK: store i32 42, i32* %{{.*}} diff --git a/test/CodeGenCXX/member-pointer-type-convert.cpp b/test/CodeGenCXX/member-pointer-type-convert.cpp index 16c1469..2970a2e 100644 --- a/test/CodeGenCXX/member-pointer-type-convert.cpp +++ b/test/CodeGenCXX/member-pointer-type-convert.cpp @@ -6,5 +6,6 @@ struct { const char *name; param_t par; } *ptr; +void test_ptr() { (void) ptr; } // forced use // CHECK: type { i8*, {{i..}} } diff --git a/test/CodeGenCXX/member-templates.cpp b/test/CodeGenCXX/member-templates.cpp index bcf1187..7e4bdca 100644 --- a/test/CodeGenCXX/member-templates.cpp +++ b/test/CodeGenCXX/member-templates.cpp @@ -15,8 +15,8 @@ struct B { template<typename T> B::B(T) {} -// CHECK: define weak_odr void @_ZN1BC1IiEET_(%struct.B* %this, i32) -// CHECK: define weak_odr void @_ZN1BC2IiEET_(%struct.B* %this, i32) +// CHECK: define weak_odr void @_ZN1BC1IiEET_(%struct.B* %this, i32) unnamed_addr +// CHECK: define weak_odr void @_ZN1BC2IiEET_(%struct.B* %this, i32) unnamed_addr template B::B(int); template<typename T> diff --git a/test/CodeGenCXX/nrvo-noreturn.cc b/test/CodeGenCXX/nrvo-noreturn.cc new file mode 100644 index 0000000..a8259ca --- /dev/null +++ b/test/CodeGenCXX/nrvo-noreturn.cc @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 -emit-llvm-only %s +// PR9178 + +void abort() __attribute__((__noreturn__)); +struct CoinModelLink { + CoinModelLink(); + ~CoinModelLink(); +}; +class CoinModel { + CoinModelLink firstInQuadraticColumn(); +}; +CoinModelLink CoinModel::firstInQuadraticColumn() { + abort(); + CoinModelLink x; + return x; +} + diff --git a/test/CodeGenCXX/nrvo.cpp b/test/CodeGenCXX/nrvo.cpp index 8d19b1e..d03b21bac 100644 --- a/test/CodeGenCXX/nrvo.cpp +++ b/test/CodeGenCXX/nrvo.cpp @@ -131,3 +131,18 @@ X test4(bool B) { // CHECK: tail call void @exit(i32 1) exit(1); } + +#ifdef __EXCEPTIONS +// CHECK-EH: define void @_Z5test5 +void may_throw(); +X test5() { + try { + may_throw(); + } catch (X x) { + // CHECK-EH: invoke void @_ZN1XC1ERKS_ + // CHECK-EH: call void @__cxa_end_catch() + // CHECK-EH: ret void + return x; + } +} +#endif diff --git a/test/CodeGenCXX/nullptr.cpp b/test/CodeGenCXX/nullptr.cpp index ab63b43..1ea23ec 100644 --- a/test/CodeGenCXX/nullptr.cpp +++ b/test/CodeGenCXX/nullptr.cpp @@ -1,5 +1,8 @@ -// RUN: %clang_cc1 -std=c++0x -triple x86_64-apple-darwin10 -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -std=c++0x -triple x86_64-apple-darwin10 -I%S -emit-llvm -o - %s | FileCheck %s +#include <typeinfo> + +// CHECK: @_ZTIDn = external constant i8* int* a = nullptr; void f() { @@ -15,3 +18,7 @@ void g() { // CHECK: call i8* @_Z11get_nullptrv() int (X::*pmf)(int) = get_nullptr(); } + +const std::type_info& f2() { + return typeid(nullptr_t); +} diff --git a/test/CodeGenCXX/pointers-to-data-members.cpp b/test/CodeGenCXX/pointers-to-data-members.cpp index 38c7d28..40723a8 100644 --- a/test/CodeGenCXX/pointers-to-data-members.cpp +++ b/test/CodeGenCXX/pointers-to-data-members.cpp @@ -1,40 +1,47 @@ -// RUN: %clang_cc1 %s -emit-llvm -o - -triple=x86_64-apple-darwin10 | FileCheck %s -// RUN: %clang_cc1 %s -emit-llvm -o - -triple=x86_64-apple-darwin10 -O3 | FileCheck --check-prefix=CHECK-O3 %s +// RUN: %clang_cc1 %s -emit-llvm -o %t.ll -triple=x86_64-apple-darwin10 +// RUN: FileCheck %s < %t.ll +// RUN: FileCheck -check-prefix=CHECK-GLOBAL %s < %t.ll +// RUN: %clang_cc1 %s -emit-llvm -o %t-opt.ll -triple=x86_64-apple-darwin10 -O3 +// RUN: FileCheck --check-prefix=CHECK-O3 %s < %t-opt.ll + struct A { int a; int b; }; struct B { int b; }; struct C : B, A { }; // Zero init. namespace ZeroInit { - // CHECK: @_ZN8ZeroInit1aE = global i64 -1 + // CHECK-GLOBAL: @_ZN8ZeroInit1aE = global i64 -1 int A::* a; - // CHECK: @_ZN8ZeroInit2aaE = global [2 x i64] [i64 -1, i64 -1] + // CHECK-GLOBAL: @_ZN8ZeroInit2aaE = global [2 x i64] [i64 -1, i64 -1] int A::* aa[2]; - // CHECK: @_ZN8ZeroInit3aaaE = global [2 x [2 x i64]] {{\[}}[2 x i64] [i64 -1, i64 -1], [2 x i64] [i64 -1, i64 -1]] + // CHECK-GLOBAL: @_ZN8ZeroInit3aaaE = global [2 x [2 x i64]] {{\[}}[2 x i64] [i64 -1, i64 -1], [2 x i64] [i64 -1, i64 -1]] int A::* aaa[2][2]; - // CHECK: @_ZN8ZeroInit1bE = global i64 -1, + // CHECK-GLOBAL: @_ZN8ZeroInit1bE = global i64 -1, int A::* b = 0; - // CHECK: @_ZN8ZeroInit2saE = global %struct.anon { i64 -1 } + // CHECK-GLOBAL: @_ZN8ZeroInit2saE = internal global %struct.anon { i64 -1 } struct { int A::*a; } sa; + void test_sa() { (void) sa; } // force emission - // CHECK: @_ZN8ZeroInit3ssaE = - // CHECK: [2 x i64] [i64 -1, i64 -1] + // CHECK-GLOBAL: @_ZN8ZeroInit3ssaE = internal + // CHECK-GLOBAL: [2 x i64] [i64 -1, i64 -1] struct { int A::*aa[2]; } ssa[2]; + void test_ssa() { (void) ssa; } - // CHECK: @_ZN8ZeroInit2ssE = global %1 { %struct.anon { i64 -1 } } + // CHECK-GLOBAL: @_ZN8ZeroInit2ssE = internal global %1 { %struct.anon { i64 -1 } } struct { struct { int A::*pa; } s; } ss; + void test_ss() { (void) ss; } struct A { int A::*a; @@ -48,13 +55,13 @@ namespace ZeroInit { }; struct C : A, B { int j; }; - // CHECK: @_ZN8ZeroInit1cE = global %"struct.ZeroInit::C" { [16 x i8] c"\FF\FF\FF\FF\FF\FF\FF\FF\00\00\00\00\00\00\00\00", [176 x i8] c"\FF\FF\FF\FF\FF\FF\FF\FF\00\00\00\00\00\00\00\00\FF\FF\FF\FF\FF\FF\FF\FF\00\00\00\00\00\00\00\00\FF\FF\FF\FF\FF\FF\FF\FF\00\00\00\00\00\00\00\00\FF\FF\FF\FF\FF\FF\FF\FF\00\00\00\00\00\00\00\00\FF\FF\FF\FF\FF\FF\FF\FF\00\00\00\00\00\00\00\00\FF\FF\FF\FF\FF\FF\FF\FF\00\00\00\00\00\00\00\00\FF\FF\FF\FF\FF\FF\FF\FF\00\00\00\00\00\00\00\00\FF\FF\FF\FF\FF\FF\FF\FF\00\00\00\00\00\00\00\00\FF\FF\FF\FF\FF\FF\FF\FF\00\00\00\00\00\00\00\00\FF\FF\FF\FF\FF\FF\FF\FF\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\FF\FF\FF\FF\FF\FF\FF\FF", i32 0, [4 x i8] zeroinitializer } + // CHECK-GLOBAL: @_ZN8ZeroInit1cE = global {{%.*}} { [16 x i8] c"\FF\FF\FF\FF\FF\FF\FF\FF\00\00\00\00\00\00\00\00", [176 x i8] c"\FF\FF\FF\FF\FF\FF\FF\FF\00\00\00\00\00\00\00\00\FF\FF\FF\FF\FF\FF\FF\FF\00\00\00\00\00\00\00\00\FF\FF\FF\FF\FF\FF\FF\FF\00\00\00\00\00\00\00\00\FF\FF\FF\FF\FF\FF\FF\FF\00\00\00\00\00\00\00\00\FF\FF\FF\FF\FF\FF\FF\FF\00\00\00\00\00\00\00\00\FF\FF\FF\FF\FF\FF\FF\FF\00\00\00\00\00\00\00\00\FF\FF\FF\FF\FF\FF\FF\FF\00\00\00\00\00\00\00\00\FF\FF\FF\FF\FF\FF\FF\FF\00\00\00\00\00\00\00\00\FF\FF\FF\FF\FF\FF\FF\FF\00\00\00\00\00\00\00\00\FF\FF\FF\FF\FF\FF\FF\FF\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\FF\FF\FF\FF\FF\FF\FF\FF", i32 0, [4 x i8] zeroinitializer } C c; } // PR5674 namespace PR5674 { - // CHECK: @_ZN6PR56742pbE = global i64 4 + // CHECK-GLOBAL: @_ZN6PR56742pbE = global i64 4 int A::*pb = &A::b; } @@ -117,7 +124,7 @@ struct A { A(); }; -// CHECK: define void @_ZN9ValueInit1AC2Ev +// CHECK: define void @_ZN9ValueInit1AC2Ev(%"struct.ValueInit::A"* %this) unnamed_addr // CHECK: store i64 -1, i64* // CHECK: ret void A::A() : a() {} @@ -165,15 +172,15 @@ struct A { int A::*i; }; -// FIXME: A::i should be initialized to -1 here. +// CHECK-GLOBAL: @_ZN12VirtualBases1bE = global {{%.*}} { i32 (...)** null, [16 x i8] c"\00\00\00\00\00\00\00\00\FF\FF\FF\FF\FF\FF\FF\FF" } struct B : virtual A { }; B b; -// FIXME: A::i should be initialized to -1 here. +// CHECK-GLOBAL: @_ZN12VirtualBases1cE = global {{%.*}} { i32 (...)** null, i64 -1, [16 x i8] c"\00\00\00\00\00\00\00\00\FF\FF\FF\FF\FF\FF\FF\FF" } struct C : virtual A { int A::*i; }; C c; -// FIXME: C::A::i should be initialized to -1 here. + // CHECK-GLOBAL: @_ZN12VirtualBases1dE = global {{%.*}} { [16 x i8] c"\00\00\00\00\00\00\00\00\FF\FF\FF\FF\FF\FF\FF\FF", i64 -1, [16 x i8] c"\00\00\00\00\00\00\00\00\FF\FF\FF\FF\FF\FF\FF\FF" } struct D : C { int A::*i; }; D d; @@ -203,3 +210,23 @@ namespace BoolPtrToMember { return x.*member; } } + +namespace PR8507 { + +struct S; +void f(S* p, double S::*pm) { + if (0 < p->*pm) { + } +} + +} + +namespace test4 { + struct A { int A_i; }; + struct B : virtual A { int A::*B_p; }; + struct C : virtual B { int *C_p; }; + struct D : C { int *D_p; }; + + // CHECK-GLOBAL: @_ZN5test41dE = global {{%.*}} { [16 x i8] zeroinitializer, i32* null, [16 x i8] c"\00\00\00\00\00\00\00\00\FF\FF\FF\FF\FF\FF\FF\FF", [4 x i8] zeroinitializer } + D d; +} diff --git a/test/CodeGenCXX/pr9130.cpp b/test/CodeGenCXX/pr9130.cpp new file mode 100644 index 0000000..b28f394 --- /dev/null +++ b/test/CodeGenCXX/pr9130.cpp @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm -o - %s | FileCheck %s + +class nsOggCodecState { + virtual int StartTime() { + return -1; + } +}; +class nsVorbisState : public nsOggCodecState { + virtual ~nsVorbisState(); +}; +nsVorbisState::~nsVorbisState() { +} + +// CHECK: define linkonce_odr i32 @_ZN15nsOggCodecState9StartTimeEv diff --git a/test/CodeGenCXX/pragma-pack.cpp b/test/CodeGenCXX/pragma-pack.cpp new file mode 100644 index 0000000..c0ddb1d --- /dev/null +++ b/test/CodeGenCXX/pragma-pack.cpp @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 %s -triple=i686-apple-darwin10 -emit-llvm -o - | FileCheck %s + +struct Base { + virtual ~Base(); + int x; +}; + +#pragma pack(1) +struct Sub : virtual Base { + char c; +}; + +// CHECK: %struct.Sub = type <{ i32 (...)**, i8, [8 x i8] }> +void f(Sub*) { } diff --git a/test/CodeGenCXX/pragma-visibility.cpp b/test/CodeGenCXX/pragma-visibility.cpp index 05de786..2dc8bcc 100644 --- a/test/CodeGenCXX/pragma-visibility.cpp +++ b/test/CodeGenCXX/pragma-visibility.cpp @@ -63,10 +63,12 @@ namespace n __attribute((visibility("default"))) { #pragma GCC visibility pop } +// We used to test this, but it's insane, so unless it happens in +// headers, we should not support it. 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 + // CHECK disabled: define void @_ZN1n1hEv } diff --git a/test/CodeGenCXX/predefined-expr.cpp b/test/CodeGenCXX/predefined-expr.cpp index f5e5ca9..56270b5 100644 --- a/test/CodeGenCXX/predefined-expr.cpp +++ b/test/CodeGenCXX/predefined-expr.cpp @@ -1,82 +1,82 @@ // RUN: %clang_cc1 %s -emit-llvm -o - | FileCheck %s -// CHECK: private constant [15 x i8] c"externFunction\00" -// CHECK: private constant [26 x i8] c"void NS::externFunction()\00" +// CHECK: private unnamed_addr constant [15 x i8] c"externFunction\00" +// CHECK: private unnamed_addr constant [26 x i8] c"void NS::externFunction()\00" -// CHECK: private constant [22 x i8] c"classTemplateFunction\00" -// CHECK: private constant [60 x i8] c"void NS::ClassTemplate<NS::Base *>::classTemplateFunction()\00" -// CHECK: private constant [53 x i8] c"void NS::ClassTemplate<int>::classTemplateFunction()\00" +// CHECK: private unnamed_addr constant [22 x i8] c"classTemplateFunction\00" +// CHECK: private unnamed_addr constant [60 x i8] c"void NS::ClassTemplate<NS::Base *>::classTemplateFunction()\00" +// CHECK: private unnamed_addr constant [53 x i8] c"void NS::ClassTemplate<int>::classTemplateFunction()\00" -// CHECK: private constant [18 x i8] c"functionTemplate1\00" -// CHECK: private constant [45 x i8] c"void NS::Base::functionTemplate1(NS::Base *)\00" -// CHECK: private constant [38 x i8] c"void NS::Base::functionTemplate1(int)\00" +// CHECK: private unnamed_addr constant [18 x i8] c"functionTemplate1\00" +// CHECK: private unnamed_addr constant [45 x i8] c"void NS::Base::functionTemplate1(NS::Base *)\00" +// CHECK: private unnamed_addr constant [38 x i8] c"void NS::Base::functionTemplate1(int)\00" -// CHECK: private constant [23 x i8] c"anonymousUnionFunction\00" -// CHECK: private constant [83 x i8] c"void NS::ContainerForAnonymousRecords::<anonymous union>::anonymousUnionFunction()\00" +// CHECK: private unnamed_addr constant [23 x i8] c"anonymousUnionFunction\00" +// CHECK: private unnamed_addr constant [83 x i8] c"void NS::ContainerForAnonymousRecords::<anonymous union>::anonymousUnionFunction()\00" -// CHECK: private constant [24 x i8] c"anonymousStructFunction\00" -// CHECK: private constant [85 x i8] c"void NS::ContainerForAnonymousRecords::<anonymous struct>::anonymousStructFunction()\00" +// CHECK: private unnamed_addr constant [24 x i8] c"anonymousStructFunction\00" +// CHECK: private unnamed_addr constant [85 x i8] c"void NS::ContainerForAnonymousRecords::<anonymous struct>::anonymousStructFunction()\00" -// CHECK: private constant [23 x i8] c"anonymousClassFunction\00" -// CHECK: private constant [83 x i8] c"void NS::ContainerForAnonymousRecords::<anonymous class>::anonymousClassFunction()\00" +// CHECK: private unnamed_addr constant [23 x i8] c"anonymousClassFunction\00" +// CHECK: private unnamed_addr constant [83 x i8] c"void NS::ContainerForAnonymousRecords::<anonymous class>::anonymousClassFunction()\00" -// CHECK: private constant [12 x i8] c"~Destructor\00" -// CHECK: private constant [30 x i8] c"NS::Destructor::~Destructor()\00" +// CHECK: private unnamed_addr constant [12 x i8] c"~Destructor\00" +// CHECK: private unnamed_addr constant [30 x i8] c"NS::Destructor::~Destructor()\00" -// CHECK: private constant [12 x i8] c"Constructor\00" -// CHECK: private constant [41 x i8] c"NS::Constructor::Constructor(NS::Base *)\00" -// CHECK: private constant [34 x i8] c"NS::Constructor::Constructor(int)\00" -// CHECK: private constant [31 x i8] c"NS::Constructor::Constructor()\00" +// CHECK: private unnamed_addr constant [12 x i8] c"Constructor\00" +// CHECK: private unnamed_addr constant [41 x i8] c"NS::Constructor::Constructor(NS::Base *)\00" +// CHECK: private unnamed_addr constant [34 x i8] c"NS::Constructor::Constructor(int)\00" +// CHECK: private unnamed_addr constant [31 x i8] c"NS::Constructor::Constructor()\00" -// CHECK: private constant [16 x i8] c"virtualFunction\00" -// CHECK: private constant [44 x i8] c"virtual void NS::Derived::virtualFunction()\00" +// CHECK: private unnamed_addr constant [16 x i8] c"virtualFunction\00" +// CHECK: private unnamed_addr constant [44 x i8] c"virtual void NS::Derived::virtualFunction()\00" -// CHECK: private constant [22 x i8] c"constVolatileFunction\00" -// CHECK: private constant [54 x i8] c"void NS::Base::constVolatileFunction() const volatile\00" +// CHECK: private unnamed_addr constant [22 x i8] c"constVolatileFunction\00" +// CHECK: private unnamed_addr constant [54 x i8] c"void NS::Base::constVolatileFunction() const volatile\00" -// CHECK: private constant [17 x i8] c"volatileFunction\00" -// CHECK: private constant [43 x i8] c"void NS::Base::volatileFunction() volatile\00" +// CHECK: private unnamed_addr constant [17 x i8] c"volatileFunction\00" +// CHECK: private unnamed_addr constant [43 x i8] c"void NS::Base::volatileFunction() volatile\00" -// CHECK: private constant [14 x i8] c"constFunction\00" -// CHECK: private constant [37 x i8] c"void NS::Base::constFunction() const\00" +// CHECK: private unnamed_addr constant [14 x i8] c"constFunction\00" +// CHECK: private unnamed_addr constant [37 x i8] c"void NS::Base::constFunction() const\00" -// CHECK: private constant [26 x i8] c"functionReturingTemplate2\00" -// CHECK: private constant [64 x i8] c"ClassTemplate<NS::Base *> NS::Base::functionReturingTemplate2()\00" +// CHECK: private unnamed_addr constant [26 x i8] c"functionReturingTemplate2\00" +// CHECK: private unnamed_addr constant [64 x i8] c"ClassTemplate<NS::Base *> NS::Base::functionReturingTemplate2()\00" -// CHECK: private constant [26 x i8] c"functionReturingTemplate1\00" -// CHECK: private constant [57 x i8] c"ClassTemplate<int> NS::Base::functionReturingTemplate1()\00" +// CHECK: private unnamed_addr constant [26 x i8] c"functionReturingTemplate1\00" +// CHECK: private unnamed_addr constant [57 x i8] c"ClassTemplate<int> NS::Base::functionReturingTemplate1()\00" -// CHECK: private constant [23 x i8] c"withTemplateParameter2\00" -// CHECK: private constant [65 x i8] c"void NS::Base::withTemplateParameter2(ClassTemplate<NS::Base *>)\00" +// CHECK: private unnamed_addr constant [23 x i8] c"withTemplateParameter2\00" +// CHECK: private unnamed_addr constant [65 x i8] c"void NS::Base::withTemplateParameter2(ClassTemplate<NS::Base *>)\00" -// CHECK: private constant [23 x i8] c"withTemplateParameter1\00" -// CHECK: private constant [58 x i8] c"void NS::Base::withTemplateParameter1(ClassTemplate<int>)\00" +// CHECK: private unnamed_addr constant [23 x i8] c"withTemplateParameter1\00" +// CHECK: private unnamed_addr constant [58 x i8] c"void NS::Base::withTemplateParameter1(ClassTemplate<int>)\00" -// CHECK: private constant [23 x i8] c"functionReturningClass\00" -// CHECK: private constant [45 x i8] c"NS::Base *NS::Base::functionReturningClass()\00" +// CHECK: private unnamed_addr constant [23 x i8] c"functionReturningClass\00" +// CHECK: private unnamed_addr constant [45 x i8] c"NS::Base *NS::Base::functionReturningClass()\00" -// CHECK: private constant [23 x i8] c"functionWithParameters\00" -// CHECK: private constant [64 x i8] c"void NS::Base::functionWithParameters(int, float *, NS::Base *)\00" +// CHECK: private unnamed_addr constant [23 x i8] c"functionWithParameters\00" +// CHECK: private unnamed_addr constant [64 x i8] c"void NS::Base::functionWithParameters(int, float *, NS::Base *)\00" -// CHECK: private constant [17 x i8] c"variadicFunction\00" -// CHECK: private constant [42 x i8] c"void NS::Base::variadicFunction(int, ...)\00" +// CHECK: private unnamed_addr constant [17 x i8] c"variadicFunction\00" +// CHECK: private unnamed_addr constant [42 x i8] c"void NS::Base::variadicFunction(int, ...)\00" -// CHECK: private constant [41 x i8] c"virtual void NS::Base::virtualFunction()\00" +// CHECK: private unnamed_addr constant [41 x i8] c"virtual void NS::Base::virtualFunction()\00" -// CHECK: private constant [15 x i8] c"inlineFunction\00" -// CHECK: private constant [32 x i8] c"void NS::Base::inlineFunction()\00" +// CHECK: private unnamed_addr constant [15 x i8] c"inlineFunction\00" +// CHECK: private unnamed_addr constant [32 x i8] c"void NS::Base::inlineFunction()\00" -// CHECK: private constant [15 x i8] c"staticFunction\00" -// CHECK: private constant [39 x i8] c"static void NS::Base::staticFunction()\00" +// CHECK: private unnamed_addr constant [15 x i8] c"staticFunction\00" +// CHECK: private unnamed_addr constant [39 x i8] c"static void NS::Base::staticFunction()\00" -// CHECK: private constant [26 x i8] c"topLevelNamespaceFunction\00" -// CHECK: private constant [59 x i8] c"void ClassInTopLevelNamespace::topLevelNamespaceFunction()\00" +// CHECK: private unnamed_addr constant [26 x i8] c"topLevelNamespaceFunction\00" +// CHECK: private unnamed_addr constant [59 x i8] c"void ClassInTopLevelNamespace::topLevelNamespaceFunction()\00" -// CHECK: private constant [27 x i8] c"anonymousNamespaceFunction\00" -// CHECK: private constant [84 x i8] c"void <anonymous namespace>::ClassInAnonymousNamespace::anonymousNamespaceFunction()\00" +// CHECK: private unnamed_addr constant [27 x i8] c"anonymousNamespaceFunction\00" +// CHECK: private unnamed_addr constant [84 x i8] c"void <anonymous namespace>::ClassInAnonymousNamespace::anonymousNamespaceFunction()\00" -// CHECK: private constant [19 x i8] c"localClassFunction\00" -// CHECK: private constant [59 x i8] c"void NS::localClass(int)::LocalClass::localClassFunction()\00" +// CHECK: private unnamed_addr constant [19 x i8] c"localClassFunction\00" +// CHECK: private unnamed_addr constant [59 x i8] c"void NS::localClass(int)::LocalClass::localClassFunction()\00" int printf(const char * _Format, ...); diff --git a/test/CodeGenCXX/ptr-to-member-function.cpp b/test/CodeGenCXX/ptr-to-member-function.cpp index e3912fe..89db142 100644 --- a/test/CodeGenCXX/ptr-to-member-function.cpp +++ b/test/CodeGenCXX/ptr-to-member-function.cpp @@ -66,5 +66,5 @@ int main() // CHECK-LP64: callq __ZN1XcvM1BFvvEEv // CHECK-LP64: callq __Z1gM1CFvvE -// CHECK-LP32: call L__ZN1XcvM1BFvvEEv -// CHECK-LP32: call __Z1gM1CFvvE +// CHECK-LP32: calll L__ZN1XcvM1BFvvEEv +// CHECK-LP32: calll __Z1gM1CFvvE diff --git a/test/CodeGenCXX/rtti-fundamental.cpp b/test/CodeGenCXX/rtti-fundamental.cpp index 7f80d99..2495e96 100644 --- a/test/CodeGenCXX/rtti-fundamental.cpp +++ b/test/CodeGenCXX/rtti-fundamental.cpp @@ -14,60 +14,103 @@ namespace __cxxabiv1 { __fundamental_type_info::~__fundamental_type_info() { } } -// 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 +// void +// CHECK: @_ZTIv = unnamed_addr constant +// CHECK: @_ZTIPv = unnamed_addr constant +// CHECK: @_ZTIPKv = unnamed_addr constant + +// std::nullptr_t +// CHECK: @_ZTIDn = unnamed_addr constant +// CHECK: @_ZTIPDn = unnamed_addr constant +// CHECK: @_ZTIPKDn = unnamed_addr constant + +// bool +// CHECK: @_ZTIb = unnamed_addr constant +// CHECK: @_ZTIPb = unnamed_addr constant +// CHECK: @_ZTIPKb = unnamed_addr constant + +// wchar_t +// CHECK: @_ZTIw = unnamed_addr constant +// CHECK: @_ZTIPw = unnamed_addr constant +// CHECK: @_ZTIPKw = unnamed_addr constant + +// char +// CHECK: @_ZTIc = unnamed_addr constant +// CHECK: @_ZTIPc = unnamed_addr constant +// CHECK: @_ZTIPKc = unnamed_addr constant + +// unsigned char +// CHECK: @_ZTIh = unnamed_addr constant +// CHECK: @_ZTIPh = unnamed_addr constant +// CHECK: @_ZTIPKh = unnamed_addr constant + +// signed char +// CHECK: @_ZTIa = unnamed_addr constant +// CHECK: @_ZTIPa = unnamed_addr constant +// CHECK: @_ZTIPKa = unnamed_addr constant + +// short +// CHECK: @_ZTIs = unnamed_addr constant +// CHECK: @_ZTIPs = unnamed_addr constant +// CHECK: @_ZTIPKs = unnamed_addr constant + +// unsigned short +// CHECK: @_ZTIt = unnamed_addr constant +// CHECK: @_ZTIPt = unnamed_addr constant +// CHECK: @_ZTIPKt = unnamed_addr constant + +// int +// CHECK: @_ZTIi = unnamed_addr constant +// CHECK: @_ZTIPi = unnamed_addr constant +// CHECK: @_ZTIPKi = unnamed_addr constant + +// unsigned int +// CHECK: @_ZTIj = unnamed_addr constant +// CHECK: @_ZTIPj = unnamed_addr constant +// CHECK: @_ZTIPKj = unnamed_addr constant + +// long +// CHECK: @_ZTIl = unnamed_addr constant +// CHECK: @_ZTIPl = unnamed_addr constant +// CHECK: @_ZTIPKl = unnamed_addr constant + +// unsigned long +// CHECK: @_ZTIm = unnamed_addr constant +// CHECK: @_ZTIPm = unnamed_addr constant +// CHECK: @_ZTIPKm = unnamed_addr constant + +// long long +// CHECK: @_ZTIx = unnamed_addr constant +// CHECK: @_ZTIPx = unnamed_addr constant +// CHECK: @_ZTIPKx = unnamed_addr constant + +// unsigned long long +// CHECK: @_ZTIy = unnamed_addr constant +// CHECK: @_ZTIPy = unnamed_addr constant +// CHECK: @_ZTIPKy = unnamed_addr constant + +// float +// CHECK: @_ZTIf = unnamed_addr constant +// CHECK: @_ZTIPf = unnamed_addr constant +// CHECK: @_ZTIPKf = unnamed_addr constant + +// double +// CHECK: @_ZTId = unnamed_addr constant +// CHECK: @_ZTIPd = unnamed_addr constant +// CHECK: @_ZTIPKd = unnamed_addr constant + +// long double +// CHECK: @_ZTIe = unnamed_addr constant +// CHECK: @_ZTIPe = unnamed_addr constant +// CHECK: @_ZTIPKe = unnamed_addr constant + +// char16_t +// CHECK: @_ZTIDs = unnamed_addr constant +// CHECK: @_ZTIPDs = unnamed_addr constant +// CHECK: @_ZTIPKDs = unnamed_addr constant + +// char32_t +// CHECK: @_ZTIDi = unnamed_addr constant +// CHECK: @_ZTIPDi = unnamed_addr constant +// CHECK: @_ZTIPKDi = unnamed_addr constant + diff --git a/test/CodeGenCXX/rtti-linkage.cpp b/test/CodeGenCXX/rtti-linkage.cpp index efa336d..42fe435 100644 --- a/test/CodeGenCXX/rtti-linkage.cpp +++ b/test/CodeGenCXX/rtti-linkage.cpp @@ -1,60 +1,60 @@ -// 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 +// RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -fhidden-weak-vtables -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -fvisibility hidden -fhidden-weak-vtables -emit-llvm -o - | FileCheck -check-prefix=CHECK-WITH-HIDDEN %s #include <typeinfo> +// CHECK-WITH-HIDDEN: _ZTSFN12_GLOBAL__N_11DEvE = internal constant +// CHECK-WITH-HIDDEN: @_ZTSPK2T4 = linkonce_odr hidden constant +// CHECK-WITH-HIDDEN: @_ZTS2T4 = linkonce_odr hidden constant +// CHECK-WITH-HIDDEN: @_ZTI2T4 = linkonce_odr hidden unnamed_addr constant +// CHECK-WITH-HIDDEN: @_ZTIPK2T4 = linkonce_odr hidden unnamed_addr constant - -// CHECK: _ZTIN12_GLOBAL__N_11DE to - - - -// CHECK: _ZTI1A = weak_odr hidden constant -// CHECK: _ZTI1B = constant -// CHECK: _ZTI1C = internal 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 hidden constant -// CHECK: _ZTIM1A1C = internal constant -// CHECK: _ZTIM1AP1C = internal constant -// CHECK: _ZTIM1CPS_ = internal constant -// CHECK: _ZTIM1CS_ = internal constant -// CHECK: _ZTIM1Ci = internal constant -// CHECK: _ZTIN12_GLOBAL__N_11DE = internal constant -// CHECK: _ZTIN12_GLOBAL__N_11EE = internal constant -// CHECK: _ZTIP1C = internal constant -// CHECK: _ZTIPFvvE = weak_odr hidden constant -// CHECK: _ZTIPM1Ci = internal constant -// CHECK: _ZTIPN12_GLOBAL__N_11DE = internal constant -// CHECK: _ZTIPP1C = internal constant -// CHECK: _ZTS1A = weak_odr constant -// CHECK: _ZTS1B = constant +// CHECK: _ZTSP1C = internal constant // CHECK: _ZTS1C = internal constant -// CHECK: _ZTS1F = weak_odr constant -// CHECK: _ZTSA10_i = weak_odr constant -// CHECK: _ZTSFN12_GLOBAL__N_11DEvE = internal constant -// CHECK: _ZTSFvN12_GLOBAL__N_11DEE = internal constant -// CHECK: _ZTSFvvE = weak_odr constant +// CHECK: _ZTI1C = internal unnamed_addr constant +// CHECK: _ZTIP1C = internal unnamed_addr constant +// CHECK: _ZTSPP1C = internal constant +// CHECK: _ZTIPP1C = internal unnamed_addr constant +// CHECK: _ZTSM1Ci = internal constant +// CHECK: _ZTIM1Ci = internal unnamed_addr constant +// CHECK: _ZTSPM1Ci = internal constant +// CHECK: _ZTIPM1Ci = internal unnamed_addr constant +// CHECK: _ZTSM1CS_ = internal constant +// CHECK: _ZTIM1CS_ = internal unnamed_addr constant +// CHECK: _ZTSM1CPS_ = internal constant +// CHECK: _ZTIM1CPS_ = internal unnamed_addr constant // CHECK: _ZTSM1A1C = internal constant +// CHECK: _ZTS1A = linkonce_odr constant +// CHECK: _ZTI1A = linkonce_odr hidden unnamed_addr constant +// CHECK: _ZTIM1A1C = internal unnamed_addr constant // CHECK: _ZTSM1AP1C = internal constant -// CHECK: _ZTSM1CPS_ = internal constant -// CHECK: _ZTSM1CS_ = internal constant -// CHECK: _ZTSM1Ci = internal constant +// CHECK: _ZTIM1AP1C = internal unnamed_addr constant // CHECK: _ZTSN12_GLOBAL__N_11DE = internal constant -// CHECK: _ZTSN12_GLOBAL__N_11EE = internal constant -// CHECK: _ZTSP1C = internal constant -// CHECK: _ZTSPFvvE = weak_odr constant -// CHECK: _ZTSPM1Ci = internal constant +// CHECK: _ZTIN12_GLOBAL__N_11DE = internal unnamed_addr constant // CHECK: _ZTSPN12_GLOBAL__N_11DE = internal constant -// CHECK: _ZTSPP1C = internal constant +// CHECK: _ZTIPN12_GLOBAL__N_11DE = internal unnamed_addr constant +// CHECK: _ZTSFN12_GLOBAL__N_11DEvE = internal constant +// CHECK: _ZTIFN12_GLOBAL__N_11DEvE = internal unnamed_addr constant +// CHECK: _ZTSFvN12_GLOBAL__N_11DEE = internal constant +// CHECK: _ZTIFvN12_GLOBAL__N_11DEE = internal unnamed_addr constant +// CHECK: _ZTSPFvvE = linkonce_odr constant +// CHECK: _ZTSFvvE = linkonce_odr constant +// CHECK: _ZTIFvvE = linkonce_odr hidden unnamed_addr constant +// CHECK: _ZTIPFvvE = linkonce_odr hidden unnamed_addr constant +// CHECK: _ZTSN12_GLOBAL__N_11EE = internal constant +// CHECK: _ZTIN12_GLOBAL__N_11EE = internal unnamed_addr constant +// CHECK: _ZTSA10_i = linkonce_odr constant +// CHECK: _ZTIA10_i = linkonce_odr hidden unnamed_addr constant +// CHECK: _ZTI1TILj0EE = linkonce_odr unnamed_addr constant +// CHECK: _ZTI1TILj1EE = weak_odr unnamed_addr constant +// CHECK: _ZTI1TILj2EE = external constant +// CHECK: _ZTS1B = constant +// CHECK: _ZTI1B = unnamed_addr constant +// CHECK: _ZTS1F = linkonce_odr constant -// A has no key function, so its RTTI data should be weak_odr. +// CHECK: _ZTIN12_GLOBAL__N_11DE to + +// A has no key function, so its RTTI data should be linkonce_odr. struct A { }; // B has a key function defined in the translation unit, so the RTTI data should @@ -90,7 +90,7 @@ namespace { }; // F has a key function defined in the translation unit, but it is inline so the RTTI -// data should be emitted with weak_odr linkage. +// data should be emitted with linkonce_odr linkage. struct F { virtual void f(); }; @@ -132,3 +132,9 @@ void t3() { (void) typeid(T<1>); (void) typeid(T<2>); } + +// rdar://problem/8778973 +struct T4 {}; +void t4(const T4 *ptr) { + const void *value = &typeid(ptr); +} diff --git a/test/CodeGenCXX/rtti-visibility.cpp b/test/CodeGenCXX/rtti-visibility.cpp new file mode 100644 index 0000000..40cee06 --- /dev/null +++ b/test/CodeGenCXX/rtti-visibility.cpp @@ -0,0 +1,35 @@ +// RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -emit-llvm -o %t +// RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -fhidden-weak-vtables -emit-llvm -o %t.hidden +// RUN: FileCheck --check-prefix=CHECK-TEST1 %s < %t +// RUN: FileCheck --check-prefix=CHECK-TEST2 %s < %t +// RUN: FileCheck --check-prefix=CHECK-TEST2-HIDDEN %s < %t.hidden + +#include <typeinfo> + +namespace Test1 { + // A is explicitly marked hidden, so all RTTI data should also be marked hidden. + // CHECK-TEST1: @_ZTSN5Test11AE = linkonce_odr hidden constant + // CHECK-TEST1: @_ZTIN5Test11AE = linkonce_odr hidden unnamed_addr constant + // CHECK-TEST1: @_ZTSPN5Test11AE = linkonce_odr hidden constant + // CHECK-TEST1: @_ZTIPN5Test11AE = linkonce_odr hidden unnamed_addr constant + struct __attribute__((visibility("hidden"))) A { }; + + void f() { + (void)typeid(A); + (void)typeid(A *); + } +} + +namespace Test2 { + // A is weak, so its linkage should be linkoce_odr, but not marked hidden. + // CHECK-TEST2: @_ZTSN5Test21AE = linkonce_odr constant + // CHECK-TEST2: @_ZTIN5Test21AE = linkonce_odr unnamed_addr constant + struct A { }; + + // With -fhidden-weak-vtables, the typeinfo for A is marked hidden, but not its name. + // CHECK-TEST2-HIDDEN: _ZTSN5Test21AE = linkonce_odr constant + // CHECK-TEST2-HIDDEN: @_ZTIN5Test21AE = linkonce_odr hidden unnamed_addr constant + void f() { + (void)typeid(A); + } +} diff --git a/test/CodeGenCXX/rvalue-references.cpp b/test/CodeGenCXX/rvalue-references.cpp new file mode 100644 index 0000000..e151723 --- /dev/null +++ b/test/CodeGenCXX/rvalue-references.cpp @@ -0,0 +1,85 @@ +// RUN: %clang_cc1 -std=c++0x -triple x86_64-apple-darwin10 -emit-llvm -o - %s | FileCheck %s + + +struct Spacer { int x; }; +struct A { double array[2]; }; +struct B : Spacer, A { }; + +B &getB(); + +// CHECK: define %struct.A* @_Z4getAv() +// CHECK: call %struct.B* @_Z4getBv() +// CHECK-NEXT: bitcast %struct.B* +// CHECK-NEXT: getelementptr i8* +// CHECK-NEXT: bitcast i8* {{.*}} to %struct.A* +// CHECK-NEXT: ret %struct.A* +A &&getA() { return static_cast<A&&>(getB()); } + +int &getIntLValue(); +int &&getIntXValue(); +int getIntPRValue(); + +// CHECK: define i32* @_Z2f0v() +// CHECK: call i32* @_Z12getIntLValuev() +// CHECK-NEXT: ret i32* +int &&f0() { return static_cast<int&&>(getIntLValue()); } + +// CHECK: define i32* @_Z2f1v() +// CHECK: call i32* @_Z12getIntXValuev() +// CHECK-NEXT: ret i32* +int &&f1() { return static_cast<int&&>(getIntXValue()); } + +// CHECK: define i32* @_Z2f2v +// CHECK: call i32 @_Z13getIntPRValuev() +// CHECK-NEXT: store i32 {{.*}}, i32* +// CHECK-NEXT: ret i32* +int &&f2() { return static_cast<int&&>(getIntPRValue()); } + +bool ok; + +class C +{ + int* state_; + + C(const C&) = delete; + C& operator=(const C&) = delete; +public: + C(int state) : state_(new int(state)) { } + + C(C&& a) { + state_ = a.state_; + a.state_ = 0; + } + + ~C() { + delete state_; + state_ = 0; + } +}; + +C test(); + +// CHECK: define void @_Z15elide_copy_initv +void elide_copy_init() { + ok = false; + // CHECK: call void @_Z4testv + C a = test(); + // CHECK-NEXT: call void @_ZN1CD1Ev + // CHECK-NEXT: ret void +} + +// CHECK: define void @_Z16test_move_returnv +C test_move_return() { + // CHECK: call void @_ZN1CC1Ei + C a1(3); + // CHECK: call void @_ZN1CC1Ei + C a2(4); + if (ok) + // CHECK: call void @_ZN1CC1EOS_ + return a1; + // CHECK: call void @_ZN1CC1EOS_ + return a2; + // CHECK: call void @_ZN1CD1Ev + // CHECK: call void @_ZN1CD1Ev + //CHECK: ret void +} diff --git a/test/CodeGenCXX/specialized-static-data-mem-init.cpp b/test/CodeGenCXX/specialized-static-data-mem-init.cpp new file mode 100644 index 0000000..8f5765b --- /dev/null +++ b/test/CodeGenCXX/specialized-static-data-mem-init.cpp @@ -0,0 +1,29 @@ +// RUN: %clang_cc1 %s -emit-llvm -o - | FileCheck %s +// rdar: // 8562966 +// pr8409 + +// CHECK: @_ZN1CIiE11needs_guardE = weak global +// CHECK: @_ZGVN1CIiE11needs_guardE = weak global + +struct K +{ + K(); + K(const K &); + ~K(); + void PrintNumK(); +}; + +template<typename T> +struct C +{ + void Go() { needs_guard.PrintNumK(); } + static K needs_guard; +}; + +template<typename T> K C<T>::needs_guard; + +void F() +{ + C<int>().Go(); +} + diff --git a/test/CodeGenCXX/static-data-member.cpp b/test/CodeGenCXX/static-data-member.cpp index b3a2af2..64fca2e 100644 --- a/test/CodeGenCXX/static-data-member.cpp +++ b/test/CodeGenCXX/static-data-member.cpp @@ -1,18 +1,66 @@ -// RUN: %clang_cc1 -emit-llvm -o - %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -o - %s | FileCheck %s -// CHECK: @_ZN1A1aE = constant i32 10 +// CHECK: @_ZN5test11A1aE = constant i32 10, align 4 +// CHECK: @_ZN5test212_GLOBAL__N_11AIiE1xE = internal global i32 0, align 4 +// CHECK: @_ZN5test31AIiE1xE = weak global i32 0, align 4 +// CHECK: @_ZGVN5test31AIiE1xE = weak global i64 0 // PR5564. -struct A { - static const int a = 10; -}; +namespace test1 { + struct A { + static const int a = 10; + }; -const int A::a; + const int A::a; -struct S { - static int i; -}; + struct S { + static int i; + }; -void f() { - int a = S::i; + void f() { + int a = S::i; + } +} + +// Test that we don't use guards for initializing template static data +// members with internal linkage. +namespace test2 { + int foo(); + + namespace { + template <class T> struct A { + static int x; + }; + + template <class T> int A<T>::x = foo(); + template struct A<int>; + } + + // CHECK: define internal void @__cxx_global_var_init() + // CHECK: [[TMP:%.*]] = call i32 @_ZN5test23fooEv() + // CHECK-NEXT: store i32 [[TMP]], i32* @_ZN5test212_GLOBAL__N_11AIiE1xE, align 4 + // CHECK-NEXT: ret void +} + +// Test that we don't use threadsafe statics when initializing +// template static data members. +namespace test3 { + int foo(); + + template <class T> struct A { + static int x; + }; + + template <class T> int A<T>::x = foo(); + template struct A<int>; + + // CHECK: define internal void @__cxx_global_var_init1() + // CHECK: [[GUARDBYTE:%.*]] = load i8* bitcast (i64* @_ZGVN5test31AIiE1xE to i8*) + // CHECK-NEXT: [[UNINITIALIZED:%.*]] = icmp eq i8 [[GUARDBYTE]], 0 + // CHECK-NEXT: br i1 [[UNINITIALIZED]] + // CHECK: [[TMP:%.*]] = call i32 @_ZN5test33fooEv() + // CHECK-NEXT: store i32 [[TMP]], i32* @_ZN5test31AIiE1xE, align 4 + // CHECK-NEXT: store i64 1, i64* @_ZGVN5test31AIiE1xE + // CHECK-NEXT: br label + // CHECK: ret void } diff --git a/test/CodeGenCXX/static-init.cpp b/test/CodeGenCXX/static-init.cpp index 09b398a..dd9ed61 100644 --- a/test/CodeGenCXX/static-init.cpp +++ b/test/CodeGenCXX/static-init.cpp @@ -14,8 +14,8 @@ struct A { void f() { // CHECK: call i32 @__cxa_guard_acquire // CHECK: call void @_ZN1AC1Ev - // CHECK: call void @__cxa_guard_release // CHECK: call i32 @__cxa_atexit(void (i8*)* bitcast (void (%struct.A*)* @_ZN1AD1Ev to void (i8*)*), i8* getelementptr inbounds (%struct.A* @_ZZ1fvE1a, i32 0, i32 0), i8* bitcast (i8** @__dso_handle to i8*)) + // CHECK: call void @__cxa_guard_release static A a; } diff --git a/test/CodeGenCXX/stmtexpr.cpp b/test/CodeGenCXX/stmtexpr.cpp new file mode 100644 index 0000000..0828d59 --- /dev/null +++ b/test/CodeGenCXX/stmtexpr.cpp @@ -0,0 +1,75 @@ +// RUN: %clang_cc1 -Wno-unused-value -emit-llvm -o - %s | FileCheck %s +// rdar: //8540501 +extern "C" int printf(...); +extern "C" void abort(); + +struct A +{ + int i; + A (int j) : i(j) {printf("this = %p A(%d)\n", this, j);} + A (const A &j) : i(j.i) {printf("this = %p const A&(%d)\n", this, i);} + A& operator= (const A &j) { i = j.i; abort(); return *this; } + ~A() { printf("this = %p ~A(%d)\n", this, i); } +}; + +struct B +{ + int i; + B (const A& a) { i = a.i; } + B() {printf("this = %p B()\n", this);} + B (const B &j) : i(j.i) {printf("this = %p const B&(%d)\n", this, i);} + ~B() { printf("this = %p ~B(%d)\n", this, i); } +}; + +A foo(int j) +{ + return ({ j ? A(1) : A(0); }); +} + + +void foo2() +{ + A b = ({ A a(1); A a1(2); A a2(3); a1; a2; a; }); + if (b.i != 1) + abort(); + A c = ({ A a(1); A a1(2); A a2(3); a1; a2; a; A a3(4); a2; a3; }); + if (c.i != 4) + abort(); +} + +void foo3() +{ + const A &b = ({ A a(1); a; }); + if (b.i != 1) + abort(); +} + +void foo4() +{ +// CHECK: call void @_ZN1AC1Ei +// CHECK: call void @_ZN1AC1ERKS_ +// CHECK: call void @_ZN1AD1Ev +// CHECK: call void @_ZN1BC1ERK1A +// CHECK: call void @_ZN1AD1Ev + const B &b = ({ A a(1); a; }); + if (b.i != 1) + abort(); +} + +int main() +{ + foo2(); + foo3(); + foo4(); + return foo(1).i-1; +} + +// rdar: // 8600553 +int a[128]; +int* foo5() { +// CHECK-NOT: memcpy + // Check that array-to-pointer conversion occurs in a + // statement-expression. + return (({ a; })); +} + diff --git a/test/CodeGenCXX/template-anonymous-types.cpp b/test/CodeGenCXX/template-anonymous-types.cpp index 5e7a71f..68bdc0c 100644 --- a/test/CodeGenCXX/template-anonymous-types.cpp +++ b/test/CodeGenCXX/template-anonymous-types.cpp @@ -29,9 +29,9 @@ void test() { // // 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) + // CHECK: define internal void @"_ZN1XIN1S3$_1EEC2ES1_"(%struct.X* %this, i32 %t) unnamed_addr // // 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) + // CHECK: define internal void @"_ZN1XIN1S3$_0EEC2ES1_"(%struct.X* %this, i32 %t) unnamed_addr } diff --git a/test/CodeGenCXX/template-dependent-bind-temporary.cpp b/test/CodeGenCXX/template-dependent-bind-temporary.cpp new file mode 100644 index 0000000..cc1ce86 --- /dev/null +++ b/test/CodeGenCXX/template-dependent-bind-temporary.cpp @@ -0,0 +1,24 @@ +// RUN: %clang_cc1 %s -emit-llvm -o - | FileCheck %s +// rdar: //8620524 +// PR7851 +struct string { + string (const string& ); + string (); + ~string(); +}; + +string operator + (char ch, const string&); + +template <class T> +void IntToString(T a) +{ + string result; + T digit; + char((digit < 10 ? '0' : 'a') + digit) + result; +} + +int main() { +// CHECK: define linkonce_odr void @_Z11IntToStringIcEvT_( + IntToString('a'); +} + diff --git a/test/CodeGenCXX/template-inner-struct-visibility-hidden.cpp b/test/CodeGenCXX/template-inner-struct-visibility-hidden.cpp new file mode 100644 index 0000000..ca4446c --- /dev/null +++ b/test/CodeGenCXX/template-inner-struct-visibility-hidden.cpp @@ -0,0 +1,24 @@ +// RUN: %clang_cc1 -fvisibility hidden -emit-llvm -o - %s | FileCheck %s + +// Verify that symbols are hidden. +// CHECK: @_ZN1CIiE5Inner6Inner26StaticE = weak hidden global +// CHECK: define weak_odr hidden void @_ZN1CIiE5Inner1fEv +// CHECK: define weak_odr hidden void @_ZN1CIiE5Inner6Inner21gEv + +template<typename T> +struct C { + struct Inner { + void f(); + struct Inner2 { + void g(); + static int Static; + }; + }; +}; + +template<typename T> void C<T>::Inner::f() { } +template<typename T> void C<T>::Inner::Inner2::g() { } +template<typename T> int C<T>::Inner::Inner2::Static; + +extern template struct C<int>; +template struct C<int>; diff --git a/test/CodeGenCXX/template-instantiation.cpp b/test/CodeGenCXX/template-instantiation.cpp index cb6c812..635e1d2 100644 --- a/test/CodeGenCXX/template-instantiation.cpp +++ b/test/CodeGenCXX/template-instantiation.cpp @@ -2,9 +2,12 @@ // CHECK-NOT: @_ZTVN5test118stdio_sync_filebufIwEE = constant // CHECK-NOT: _ZTVN5test315basic_fstreamXXIcEE -// CHECK: @_ZTVN5test018stdio_sync_filebufIwEE = constant +// CHECK: @_ZTVN5test018stdio_sync_filebufIwEE = unnamed_addr constant -// CHECK: define linkonce_odr void @_ZN5test21CIiEC1Ev( +// CHECK-NOT: _ZTVN5test31SIiEE +// CHECK-NOT: _ZTSN5test31SIiEE + +// CHECK: define linkonce_odr void @_ZN5test21CIiEC1Ev(%"class.test2::C"* nocapture %this) unnamed_addr // CHECK: define linkonce_odr void @_ZN5test21CIiE6foobarIdEEvT_( // CHECK: define available_externally void @_ZN5test21CIiE6zedbarEd( @@ -75,3 +78,47 @@ namespace test3 { // (test at the top). template void basic_fstreamXX<char>::is_open() const; } + +namespace test3 { + template <typename T> + struct S { + virtual void m(); + }; + + template<typename T> + void S<T>::m() { } + + // Should not cause us to produce vtable because template instantiations + // don't have key functions. + template void S<int>::m(); +} + +namespace test4 { + template <class T> struct A { static void foo(); }; + + class B { + template <class T> friend void A<T>::foo(); + B(); + }; + + template <class T> void A<T>::foo() { + B b; + } + + unsigned test() { + A<int>::foo(); + } +} + +namespace PR8505 { +// Hits an assertion due to bogus instantiation of class B. +template <int i> class A { + class B* g; +}; +class B { + void f () {} +}; +// Should not instantiate class B since it is introduced in namespace scope. +// CHECK-NOT: _ZN6PR85051AILi0EE1B1fEv +template class A<0>; +} diff --git a/test/CodeGenCXX/template-linkage.cpp b/test/CodeGenCXX/template-linkage.cpp index 63a5c09..20508c1 100644 --- a/test/CodeGenCXX/template-linkage.cpp +++ b/test/CodeGenCXX/template-linkage.cpp @@ -37,7 +37,7 @@ template<typename T> void X1<T>::blarg() { } extern template struct X0<char>; extern template struct X1<char>; -// CHECK: define linkonce_odr void @_ZN2X1IcED1Ev( +// CHECK: define linkonce_odr void @_ZN2X1IcED1Ev(%struct.X1* %this) unnamed_addr void test_X1() { X1<char> i1c; } diff --git a/test/CodeGenCXX/temporaries.cpp b/test/CodeGenCXX/temporaries.cpp index 9a397ab..348d51e 100644 --- a/test/CodeGenCXX/temporaries.cpp +++ b/test/CodeGenCXX/temporaries.cpp @@ -338,3 +338,188 @@ namespace PR7556 { // CHECK-NEXT: ret void } } + +namespace Elision { + struct A { + A(); A(const A &); ~A(); + void *p; + void foo() const; + }; + + void foo(); + A fooA(); + void takeA(A a); + + // CHECK: define void @_ZN7Elision5test0Ev() + void test0() { + // CHECK: [[I:%.*]] = alloca [[A:%.*]], align 8 + // CHECK-NEXT: [[J:%.*]] = alloca [[A]], align 8 + // CHECK-NEXT: [[T0:%.*]] = alloca [[A]], align 8 + // CHECK-NEXT: [[K:%.*]] = alloca [[A]], align 8 + // CHECK-NEXT: [[T1:%.*]] = alloca [[A]], align 8 + + // CHECK-NEXT: call void @_ZN7Elision3fooEv() + // CHECK-NEXT: call void @_ZN7Elision1AC1Ev([[A]]* [[I]]) + A i = (foo(), A()); + + // CHECK-NEXT: call void @_ZN7Elision4fooAEv([[A]]* sret [[T0]]) + // CHECK-NEXT: call void @_ZN7Elision1AC1Ev([[A]]* [[J]]) + // CHECK-NEXT: call void @_ZN7Elision1AD1Ev([[A]]* [[T0]]) + A j = (fooA(), A()); + + // CHECK-NEXT: call void @_ZN7Elision1AC1Ev([[A]]* [[T1]]) + // CHECK-NEXT: call void @_ZN7Elision4fooAEv([[A]]* sret [[K]]) + // CHECK-NEXT: call void @_ZN7Elision1AD1Ev([[A]]* [[T1]]) + A k = (A(), fooA()); + + // CHECK-NEXT: call void @_ZN7Elision1AD1Ev([[A]]* [[K]]) + // CHECK-NEXT: call void @_ZN7Elision1AD1Ev([[A]]* [[J]]) + // CHECK-NEXT: call void @_ZN7Elision1AD1Ev([[A]]* [[I]]) + } + + + // CHECK: define void @_ZN7Elision5test1EbNS_1AE( + void test1(bool c, A x) { + // CHECK: [[I:%.*]] = alloca [[A]], align 8 + // CHECK-NEXT: [[J:%.*]] = alloca [[A]], align 8 + + // CHECK: call void @_ZN7Elision1AC1Ev([[A]]* [[I]]) + // CHECK: call void @_ZN7Elision1AC1ERKS0_([[A]]* [[I]], [[A]]* [[X:%.*]]) + A i = (c ? A() : x); + + // CHECK: call void @_ZN7Elision1AC1ERKS0_([[A]]* [[J]], [[A]]* [[X]]) + // CHECK: call void @_ZN7Elision1AC1Ev([[A]]* [[J]]) + A j = (c ? x : A()); + + // CHECK: call void @_ZN7Elision1AD1Ev([[A]]* [[J]]) + // CHECK-NEXT: call void @_ZN7Elision1AD1Ev([[A]]* [[I]]) + } + + // CHECK: define void @_ZN7Elision5test2Ev([[A]]* sret + A test2() { + // CHECK: call void @_ZN7Elision3fooEv() + // CHECK-NEXT: call void @_ZN7Elision1AC1Ev([[A]]* [[RET:%.*]]) + // CHECK-NEXT: ret void + return (foo(), A()); + } + + // CHECK: define void @_ZN7Elision5test3EiNS_1AE([[A]]* sret + A test3(int v, A x) { + if (v < 5) + // CHECK: call void @_ZN7Elision1AC1Ev([[A]]* [[RET:%.*]]) + // CHECK: call void @_ZN7Elision1AC1ERKS0_([[A]]* [[RET]], [[A]]* [[X:%.*]]) + return (v < 0 ? A() : x); + else + // CHECK: call void @_ZN7Elision1AC1ERKS0_([[A]]* [[RET]], [[A]]* [[X]]) + // CHECK: call void @_ZN7Elision1AC1Ev([[A]]* [[RET]]) + return (v > 10 ? x : A()); + + // CHECK: ret void + } + + // CHECK: define void @_ZN7Elision5test4Ev() + void test4() { + // CHECK: [[X:%.*]] = alloca [[A]], align 8 + // CHECK-NEXT: [[XS:%.*]] = alloca [2 x [[A]]], align 16 + // CHECK-NEXT: [[I:%.*]] = alloca i64 + + // CHECK-NEXT: call void @_ZN7Elision1AC1Ev([[A]]* [[X]]) + A x; + + // CHECK-NEXT: [[XS0:%.*]] = getelementptr inbounds [2 x [[A]]]* [[XS]], i32 0, i32 0 + // CHECK-NEXT: call void @_ZN7Elision1AC1Ev([[A]]* [[XS0]]) + // CHECK-NEXT: [[XS1:%.*]] = getelementptr inbounds [2 x [[A]]]* [[XS]], i32 0, i32 1 + // CHECK-NEXT: call void @_ZN7Elision1AC1ERKS0_([[A]]* [[XS1]], [[A]]* [[X]]) + // CHECK-NEXT: [[XSB:%.*]] = bitcast [2 x [[A]]]* [[XS]] to [[A]]* + A xs[] = { A(), x }; + + // CHECK-NEXT: store i64 2, i64* [[I]] + // CHECK-NEXT: br label + // CHECK: [[I0:%.*]] = load i64* [[I]] + // CHECK-NEXT: icmp ne i64 [[I0]], 0 + // CHECK-NEXT: br i1 + // CHECK: [[I1:%.*]] = load i64* [[I]] + // CHECK-NEXT: [[I2:%.*]] = sub i64 [[I1]], 1 + // CHECK-NEXT: [[XSI:%.*]] = getelementptr inbounds [[A]]* [[XSB]], i64 [[I2]] + // CHECK-NEXT: call void @_ZN7Elision1AD1Ev([[A]]* [[XSI]]) + // CHECK-NEXT: br label + + // CHECK: call void @_ZN7Elision1AD1Ev([[A]]* [[X]]) + } + + // rdar://problem/8433352 + // CHECK: define void @_ZN7Elision5test5Ev([[A]]* sret + struct B { A a; B(); }; + A test5() { + // CHECK: [[AT0:%.*]] = alloca [[A]], align 8 + // CHECK-NEXT: [[BT0:%.*]] = alloca [[B:%.*]], align 8 + // CHECK-NEXT: [[X:%.*]] = alloca [[A]], align 8 + // CHECK-NEXT: [[BT1:%.*]] = alloca [[B]], align 8 + // CHECK-NEXT: [[BT2:%.*]] = alloca [[B]], align 8 + + // CHECK: call void @_ZN7Elision1BC1Ev([[B]]* [[BT0]]) + // CHECK-NEXT: [[AM:%.*]] = getelementptr inbounds [[B]]* [[BT0]], i32 0, i32 0 + // CHECK-NEXT: call void @_ZN7Elision1AC1ERKS0_([[A]]* [[AT0]], [[A]]* [[AM]]) + // CHECK-NEXT: call void @_ZN7Elision5takeAENS_1AE([[A]]* [[AT0]]) + // CHECK-NEXT: call void @_ZN7Elision1AD1Ev([[A]]* [[AT0]]) + // CHECK-NEXT: call void @_ZN7Elision1BD1Ev([[B]]* [[BT0]]) + takeA(B().a); + + // CHECK-NEXT: call void @_ZN7Elision1BC1Ev([[B]]* [[BT1]]) + // CHECK-NEXT: [[AM:%.*]] = getelementptr inbounds [[B]]* [[BT1]], i32 0, i32 0 + // CHECK-NEXT: call void @_ZN7Elision1AC1ERKS0_([[A]]* [[X]], [[A]]* [[AM]]) + // CHECK-NEXT: call void @_ZN7Elision1BD1Ev([[B]]* [[BT1]]) + A x = B().a; + + // CHECK-NEXT: call void @_ZN7Elision1BC1Ev([[B]]* [[BT2]]) + // CHECK-NEXT: [[AM:%.*]] = getelementptr inbounds [[B]]* [[BT2]], i32 0, i32 0 + // CHECK-NEXT: call void @_ZN7Elision1AC1ERKS0_([[A]]* [[RET:%.*]], [[A]]* [[AM]]) + // CHECK-NEXT: call void @_ZN7Elision1BD1Ev([[B]]* [[BT2]]) + return B().a; + + // CHECK: call void @_ZN7Elision1AD1Ev([[A]]* [[X]]) + } + + // Reduced from webkit. + // CHECK: define void @_ZN7Elision5test6EPKNS_1CE([[C:%.*]]* + struct C { operator A() const; }; + void test6(const C *x) { + // CHECK: [[T0:%.*]] = alloca [[A]], align 8 + // CHECK: [[X:%.*]] = load [[C]]** {{%.*}}, align 8 + // CHECK-NEXT: call void @_ZNK7Elision1CcvNS_1AEEv([[A]]* sret [[T0]], [[C]]* [[X]]) + // CHECK-NEXT: call void @_ZNK7Elision1A3fooEv([[A]]* [[T0]]) + // CHECK-NEXT: call void @_ZN7Elision1AD1Ev([[A]]* [[T0]]) + // CHECK-NEXT: ret void + A(*x).foo(); + } +} + +namespace PR8623 { + struct A { A(int); ~A(); }; + + // CHECK: define void @_ZN6PR86233fooEb( + void foo(bool b) { + // CHECK: [[TMP:%.*]] = alloca [[A:%.*]], align 1 + // CHECK-NEXT: [[LCONS:%.*]] = alloca i1 + // CHECK-NEXT: [[RCONS:%.*]] = alloca i1 + // CHECK: store i1 false, i1* [[LCONS]] + // CHECK-NEXT: store i1 false, i1* [[RCONS]] + // CHECK-NEXT: br i1 + // CHECK: call void @_ZN6PR86231AC1Ei([[A]]* [[TMP]], i32 2) + // CHECK-NEXT: store i1 true, i1* [[LCONS]] + // CHECK-NEXT: br label + // CHECK: call void @_ZN6PR86231AC1Ei([[A]]* [[TMP]], i32 3) + // CHECK-NEXT: store i1 true, i1* [[RCONS]] + // CHECK-NEXT: br label + // CHECK: load i1* [[RCONS]] + // CHECK-NEXT: br i1 + // CHECK: call void @_ZN6PR86231AD1Ev([[A]]* [[TMP]]) + // CHECK-NEXT: br label + // CHECK: load i1* [[LCONS]] + // CHECK-NEXT: br i1 + // CHECK: call void @_ZN6PR86231AD1Ev([[A]]* [[TMP]]) + // CHECK-NEXT: br label + // CHECK: ret void + b ? A(2) : A(3); + } +} diff --git a/test/CodeGenCXX/threadsafe-statics-exceptions.cpp b/test/CodeGenCXX/threadsafe-statics-exceptions.cpp index c91590f..87be572 100644 --- a/test/CodeGenCXX/threadsafe-statics-exceptions.cpp +++ b/test/CodeGenCXX/threadsafe-statics-exceptions.cpp @@ -11,8 +11,8 @@ struct Y { }; void f() { // CHECK: call i32 @__cxa_guard_acquire(i64* @_ZGVZ1fvE1x) // CHECK: invoke void @_ZN1XC1Ev - // CHECK: call void @__cxa_guard_release(i64* @_ZGVZ1fvE1x) - // CHECK-NEXT: call i32 @__cxa_atexit + // CHECK: call i32 @__cxa_atexit + // CHECK-NEXT: call void @__cxa_guard_release(i64* @_ZGVZ1fvE1x) // CHECK: br static X x; diff --git a/test/CodeGenCXX/throw-expressions.cpp b/test/CodeGenCXX/throw-expressions.cpp index 1670e44..1d22ec0 100644 --- a/test/CodeGenCXX/throw-expressions.cpp +++ b/test/CodeGenCXX/throw-expressions.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -emit-llvm-only -verify %s -Wno-unreachable-code +// RUN: %clang_cc1 -fexceptions -emit-llvm-only -verify %s -Wno-unreachable-code int val = 42; int& test1() { @@ -8,3 +8,8 @@ int& test1() { int test2() { return val ? throw val : val; } + +// rdar://problem/8608801 +void test3() { + throw false; +} diff --git a/test/CodeGenCXX/thunks-available-externally.cpp b/test/CodeGenCXX/thunks-available-externally.cpp new file mode 100644 index 0000000..dfdb786 --- /dev/null +++ b/test/CodeGenCXX/thunks-available-externally.cpp @@ -0,0 +1,88 @@ +// RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -emit-llvm -O3 -o - | FileCheck %s + +// Check that we don't assert on this case. +namespace Test1 { + +struct Incomplete; + +struct A { + virtual void f(); + virtual void g(Incomplete); + virtual void h(); + virtual void i(); + int a; +}; + +struct B { + virtual void f(); + virtual void g(Incomplete); + virtual void h(); + virtual void i(); + int b; +}; + +struct C : A, B { + C(); + + virtual void f(); + virtual void g(Incomplete); + virtual void h(); + virtual void i(); +}; + +void C::h() { } + +C::C() { } + +void C::i() { } + +} + +namespace Test2 { + +struct A { + virtual void f(); + int a; +}; + +struct B { + virtual void f(); + int b; +}; + +struct C : A, B { + virtual void f(); +}; + +static void f(B* b) { + b->f(); +} + +// CHECK: define void @_ZN5Test21fEv() +// CHECK: call void @_ZN5Test21C1fEv +// CHECK: ret void +// CHECK: define available_externally void @_ZThn16_N5Test21C1fEv +void f() { + C c; + f(&c); +} + +} + +// Test that we don't assert. +namespace Test3 { + +struct A { + virtual ~A(); + + int a; +}; + +struct B : A { }; +struct C : virtual B { }; + +void f() { + C c; +} + +} diff --git a/test/CodeGenCXX/thunks.cpp b/test/CodeGenCXX/thunks.cpp index ba60385..a74cc05 100644 --- a/test/CodeGenCXX/thunks.cpp +++ b/test/CodeGenCXX/thunks.cpp @@ -88,31 +88,29 @@ void C::f() { } } // Check that the thunk gets internal linkage. -namespace { - -struct A { - virtual void f(); -}; - -struct B { - virtual void f(); -}; - -struct C : A, B { - virtual void c(); - - virtual void f(); -}; +namespace Test4B { + struct A { + virtual void f(); + }; -void C::f() { } + struct B { + virtual void f(); + }; -} + namespace { + struct C : A, B { + virtual void c(); + virtual void f(); + }; + } + void C::c() {} + void C::f() {} -// Force C::f to be used. -void f() { - C c; - - c.f(); + // Force C::f to be used. + void f() { + C c; + c.f(); + } } namespace Test5 { @@ -260,8 +258,27 @@ namespace Test10 { } } +// PR7611 +namespace Test11 { + struct A { virtual A* f(); }; + struct B : virtual A { virtual A* f(); }; + struct C : B { virtual C* f(); }; + C* C::f() { return 0; } + + // The this-adjustment and return-adjustment thunk required when + // C::f appears in a vtable where A is at a nonzero offset from C. + // CHECK: define {{.*}} @_ZTcv0_n24_v0_n32_N6Test111C1fEv( + + // C::f itself. + // CHECK: define {{.*}} @_ZN6Test111C1fEv( + + // The return-adjustment thunk required when C::f appears in a vtable + // where A is at a zero offset from C. + // CHECK: define {{.*}} @_ZTch0_v0_n32_N6Test111C1fEv( +} + /**** The following has to go at the end of the file ****/ // This is from Test5: // CHECK: define linkonce_odr void @_ZTv0_n24_N5Test51B1fEv -// CHECK: define internal void @_ZThn8_N12_GLOBAL__N_11C1fEv( +// CHECK: define internal void @_ZThn8_N6Test4B12_GLOBAL__N_11C1fEv( diff --git a/test/CodeGenCXX/value-init.cpp b/test/CodeGenCXX/value-init.cpp index c4eb1c8..258d692 100644 --- a/test/CodeGenCXX/value-init.cpp +++ b/test/CodeGenCXX/value-init.cpp @@ -133,8 +133,21 @@ namespace zeroinit { X3<int>().f(); } - // CHECK: define linkonce_odr void @_ZN8zeroinit2X3IiEC2Ev + // CHECK: define linkonce_odr void @_ZN8zeroinit2X3IiEC2Ev(%struct.B* %this) unnamed_addr // CHECK: call void @llvm.memset.p0i8.i64 // CHECK-NEXT: call void @_ZN8zeroinit2X2IiEC2Ev // CHECK-NEXT: ret void } + +namespace PR8726 { +class C; +struct S { + const C &c1; + int i; + const C &c2; +}; +void f(const C& c) { + S s = {c, 42, c}; +} + +} diff --git a/test/CodeGenCXX/variadic-templates.cpp b/test/CodeGenCXX/variadic-templates.cpp new file mode 100644 index 0000000..4f3cf1f --- /dev/null +++ b/test/CodeGenCXX/variadic-templates.cpp @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -std=c++0x -triple x86_64-apple-darwin10 -emit-llvm -o - %s | FileCheck %s + +template<typename ...Types> +int get_num_types(Types...) { + return sizeof...(Types); +} + +// CHECK: define weak_odr i32 @_Z13get_num_typesIJifdEEiDpT_ +// CHECK: ret i32 3 +template int get_num_types(int, float, double); + + diff --git a/test/CodeGenCXX/virt-dtor-gen.cpp b/test/CodeGenCXX/virt-dtor-gen.cpp index a4346ba..1a6c583 100644 --- a/test/CodeGenCXX/virt-dtor-gen.cpp +++ b/test/CodeGenCXX/virt-dtor-gen.cpp @@ -7,4 +7,4 @@ class Foo { }; Foo::~Foo() {} -// CHECK: define void @_ZN3FooD0Ev +// CHECK: define void @_ZN3FooD0Ev(%class.Foo* %this) unnamed_addr diff --git a/test/CodeGenCXX/virt-dtor-key.cpp b/test/CodeGenCXX/virt-dtor-key.cpp index 6a58c50..a8fa371 100644 --- a/test/CodeGenCXX/virt-dtor-key.cpp +++ b/test/CodeGenCXX/virt-dtor-key.cpp @@ -1,5 +1,5 @@ // RUN: %clang_cc1 -emit-llvm %s -o - | FileCheck %s -// CHECK: @_ZTI3foo = constant +// CHECK: @_ZTI3foo = unnamed_addr constant class foo { foo(); virtual ~foo(); diff --git a/test/CodeGenCXX/virt-template-vtable.cpp b/test/CodeGenCXX/virt-template-vtable.cpp index d60cfb9..25736fd 100644 --- a/test/CodeGenCXX/virt-template-vtable.cpp +++ b/test/CodeGenCXX/virt-template-vtable.cpp @@ -16,7 +16,7 @@ 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 +// CHECK: @_ZTV1B = linkonce_odr unnamed_addr constant +// CHECK: @_ZTV1AIlE = weak_odr unnamed_addr constant +// CHECK: @_ZTV1AIsE = weak_odr unnamed_addr constant +// CHECK: @_ZTV1AIiE = linkonce_odr unnamed_addr constant diff --git a/test/CodeGenCXX/virtual-base-destructor-call.cpp b/test/CodeGenCXX/virtual-base-destructor-call.cpp index 4618a03..807eaff 100644 --- a/test/CodeGenCXX/virtual-base-destructor-call.cpp +++ b/test/CodeGenCXX/virtual-base-destructor-call.cpp @@ -18,34 +18,34 @@ int main() { // basic_iostream's complete dtor calls its base dtor, then its // virtual base's dtor. -// CHECK: define linkonce_odr void @_ZN14basic_iostreamIcED1Ev +// CHECK: define linkonce_odr void @_ZN14basic_iostreamIcED1Ev(%struct.basic_iostream* %this) unnamed_addr // CHECK: call void @_ZN14basic_iostreamIcED2Ev // CHECK: call void @_ZN9basic_iosD2Ev // basic_iostream's base dtor calls its non-virtual base dtor. -// CHECK: define linkonce_odr void @_ZN14basic_iostreamIcED2Ev +// CHECK: define linkonce_odr void @_ZN14basic_iostreamIcED2Ev(%struct.basic_iostream* %this, i8** %vtt) unnamed_addr // CHECK: call void @_ZN13basic_istreamIcED2Ev // CHECK: } // basic_istream's base dtor is a no-op. -// CHECK: define linkonce_odr void @_ZN13basic_istreamIcED2Ev +// CHECK: define linkonce_odr void @_ZN13basic_istreamIcED2Ev(%struct.basic_istream* %this, i8** %vtt) unnamed_addr // CHECK-NOT: call // CHECK: } // basic_iostream's deleting dtor calls its complete dtor, then // operator delete(). -// CHECK: define linkonce_odr void @_ZN14basic_iostreamIcED0Ev +// CHECK: define linkonce_odr void @_ZN14basic_iostreamIcED0Ev(%struct.basic_iostream* %this) unnamed_addr // CHECK: call void @_ZN14basic_iostreamIcED1Ev // CHECK: call void @_ZdlPv // basic_istream's complete dtor calls the base dtor, // then its virtual base's base dtor. -// CHECK: define linkonce_odr void @_ZN13basic_istreamIcED1Ev +// CHECK: define linkonce_odr void @_ZN13basic_istreamIcED1Ev(%struct.basic_istream* %this) unnamed_addr // CHECK: call void @_ZN13basic_istreamIcED2Ev // CHECK: call void @_ZN9basic_iosD2Ev // basic_istream's deleting dtor calls the complete dtor, then // operator delete(). -// CHECK: define linkonce_odr void @_ZN13basic_istreamIcED0Ev +// CHECK: define linkonce_odr void @_ZN13basic_istreamIcED0Ev(%struct.basic_istream* %this) unnamed_addr // CHECK: call void @_ZN13basic_istreamIcED1Ev // CHECK: call void @_ZdlPv diff --git a/test/CodeGenCXX/virtual-bases.cpp b/test/CodeGenCXX/virtual-bases.cpp index 61de315..cfb4c83 100644 --- a/test/CodeGenCXX/virtual-bases.cpp +++ b/test/CodeGenCXX/virtual-bases.cpp @@ -5,23 +5,23 @@ struct A { }; // CHECK: @_ZN1AC1Ev = alias {{.*}} @_ZN1AC2Ev -// CHECK: define void @_ZN1AC2Ev(%struct.A* %this) +// CHECK: define void @_ZN1AC2Ev(%struct.A* %this) unnamed_addr A::A() { } struct B : virtual A { B(); }; -// CHECK: define void @_ZN1BC1Ev(%struct.B* %this) -// CHECK: define void @_ZN1BC2Ev(%struct.B* %this, i8** %vtt) +// CHECK: define void @_ZN1BC1Ev(%struct.B* %this) unnamed_addr +// CHECK: define void @_ZN1BC2Ev(%struct.B* %this, i8** %vtt) unnamed_addr B::B() { } struct C : virtual A { C(bool); }; -// CHECK: define void @_ZN1CC1Eb(%struct.B* %this, i1 zeroext) -// CHECK: define void @_ZN1CC2Eb(%struct.B* %this, i8** %vtt, i1 zeroext) +// CHECK: define void @_ZN1CC1Eb(%struct.B* %this, i1 zeroext) unnamed_addr +// CHECK: define void @_ZN1CC2Eb(%struct.B* %this, i8** %vtt, i1 zeroext) unnamed_addr C::C(bool) { } // PR6251 @@ -39,7 +39,7 @@ struct D : B, C { D(); }; -// CHECK: define void @_ZN6PR62511DC1Ev +// CHECK: define void @_ZN6PR62511DC1Ev(%"struct.PR6251::D"* %this) unnamed_addr // CHECK: call void @_ZN6PR62511AIcEC2Ev // CHECK-NOT: call void @_ZN6PR62511AIcEC2Ev // CHECK: ret void diff --git a/test/CodeGenCXX/virtual-destructor-calls.cpp b/test/CodeGenCXX/virtual-destructor-calls.cpp index c5b9262..1cc8bcc 100644 --- a/test/CodeGenCXX/virtual-destructor-calls.cpp +++ b/test/CodeGenCXX/virtual-destructor-calls.cpp @@ -21,12 +21,12 @@ struct B : A { // CHECK: @_ZN1CD2Ev = alias bitcast {{.*}} @_ZN1BD2Ev // Deleting dtor: defers to the complete dtor. -// CHECK: define void @_ZN1BD0Ev +// CHECK: define void @_ZN1BD0Ev(%struct.B* %this) unnamed_addr // CHECK: call void @_ZN1BD1Ev // CHECK: call void @_ZdlPv // Base dtor: actually calls A's base dtor. -// CHECK: define void @_ZN1BD2Ev +// CHECK: define void @_ZN1BD2Ev(%struct.B* %this) unnamed_addr // CHECK: call void @_ZN6MemberD1Ev // CHECK: call void @_ZN1AD2Ev @@ -41,7 +41,7 @@ C::~C() { } // Complete dtor: just an alias (checked above). // Deleting dtor: defers to the complete dtor. -// CHECK: define void @_ZN1CD0Ev +// CHECK: define void @_ZN1CD0Ev(%struct.C* %this) unnamed_addr // CHECK: call void @_ZN1CD1Ev // CHECK: call void @_ZdlPv diff --git a/test/CodeGenCXX/visibility-inlines-hidden.cpp b/test/CodeGenCXX/visibility-inlines-hidden.cpp index bb1574f..760879a 100644 --- a/test/CodeGenCXX/visibility-inlines-hidden.cpp +++ b/test/CodeGenCXX/visibility-inlines-hidden.cpp @@ -1,4 +1,9 @@ -// RUN: %clang_cc1 -fvisibility-inlines-hidden -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -fvisibility-inlines-hidden -emit-llvm -o - %s -O2 -disable-llvm-optzns | FileCheck %s + +// The trickery with optimization in the run line is to get IR +// generation to emit available_externally function bodies, but not +// actually inline them (and thus remove the emitted bodies). + struct X0 { void __attribute__((visibility("default"))) f1() { } void f2() { } @@ -29,7 +34,9 @@ struct __attribute__((visibility("default"))) X2 { void f2() { } }; -void use(X0 *x0, X1<int> *x1, X2 *x2) { +extern template struct X1<float>; + +void use(X0 *x0, X1<int> *x1, X2 *x2, X1<float> *x3) { // CHECK: define linkonce_odr void @_ZN2X02f1Ev x0->f1(); // CHECK: define linkonce_odr hidden void @_ZN2X02f2Ev @@ -54,4 +61,39 @@ void use(X0 *x0, X1<int> *x1, X2 *x2) { x1->X1::f6(); // CHECK: define linkonce_odr hidden void @_ZN2X22f2Ev x2->f2(); + // CHECK: define available_externally void @_ZN2X1IfE2f2Ev + x3->f2(); +} + +// rdar://problem/8614470 +namespace test1 { + struct __attribute__((visibility("default"))) A { + inline void foo(); + ~A(); + }; + + void test() { + A a; + a.foo(); + } +// CHECK: declare void @_ZN5test11A3fooEv +// CHECK: declare void @_ZN5test11AD1Ev +} + +// PR8713 +namespace test2 { + struct A {}; + template <class T> class B {}; + typedef B<A> arg; + + namespace ns __attribute__((visibility("default"))) { + template <class T> inline void foo() {} + extern template void foo<arg>(); + } + + void test() { + ns::foo<arg>(); + } + + // CHECK: define available_externally void @_ZN5test22ns3fooINS_1BINS_1AEEEEEvv() } diff --git a/test/CodeGenCXX/visibility.cpp b/test/CodeGenCXX/visibility.cpp index ee3c179..9314650 100644 --- a/test/CodeGenCXX/visibility.cpp +++ b/test/CodeGenCXX/visibility.cpp @@ -1,11 +1,35 @@ // RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -fvisibility hidden -emit-llvm -o - | FileCheck %s -check-prefix=CHECK-HIDDEN #define HIDDEN __attribute__((visibility("hidden"))) #define PROTECTED __attribute__((visibility("protected"))) #define DEFAULT __attribute__((visibility("default"))) // CHECK: @_ZN5Test425VariableInHiddenNamespaceE = hidden global i32 10 -// CHECK: @_ZTVN5Test63fooE = weak_odr hidden constant +// CHECK: @_ZN5Test71aE = hidden global +// CHECK: @_ZN5Test71bE = global +// CHECK: @test9_var = global +// CHECK-HIDDEN: @test9_var = global +// CHECK: @_ZN6Test121A6hiddenE = external hidden global +// CHECK: @_ZN6Test121A7visibleE = external global +// CHECK-HIDDEN: @_ZN6Test121A6hiddenE = external hidden global +// CHECK-HIDDEN: @_ZN6Test121A7visibleE = external global +// CHECK: @_ZN6Test131B1aE = hidden global +// CHECK: @_ZN6Test131C1aE = global +// CHECK-HIDDEN: @_ZN6Test131B1aE = hidden global +// CHECK-HIDDEN: @_ZN6Test131C1aE = global +// CHECK: @_ZN6Test143varE = external global +// CHECK-HIDDEN: @_ZN6Test143varE = external global +// CHECK: @_ZN6Test154TempINS_1AEE5Inner6bufferE = external global [0 x i8] +// CHECK-HIDDEN: @_ZN6Test154TempINS_1AEE5Inner6bufferE = external global [0 x i8] +// CHECK: @_ZZN6Test193fooIiEEvvE1a = linkonce_odr global +// CHECK: @_ZGVZN6Test193fooIiEEvvE1a = linkonce_odr global i64 +// CHECK-HIDDEN: @_ZZN6Test193fooIiEEvvE1a = linkonce_odr hidden global +// CHECK-HIDDEN: @_ZGVZN6Test193fooIiEEvvE1a = linkonce_odr hidden global i64 +// CHECK-HIDDEN: @_ZTTN6Test161AIcEE = external unnamed_addr constant +// CHECK-HIDDEN: @_ZTVN6Test161AIcEE = external unnamed_addr constant +// CHECK: @_ZTVN5Test63fooE = linkonce_odr hidden unnamed_addr constant + namespace Test1 { // CHECK: define hidden void @_ZN5Test11fEv void HIDDEN f() { } @@ -82,3 +106,308 @@ namespace Test6 { barc::barc() {} } + +namespace Test7 { + class HIDDEN A {}; + A a; // top of file + + template <A&> struct Aref { + static void foo() {} + }; + + class B : public A {}; + B b; // top of file + + // CHECK: define linkonce_odr hidden void @_ZN5Test74ArefILZNS_1aEEE3fooEv() + void test() { + Aref<a>::foo(); + } +} + +namespace Test8 { + void foo(); + void bar() {} + // CHECK-HIDDEN: define hidden void @_ZN5Test83barEv() + // CHECK-HIDDEN: declare void @_ZN5Test83fooEv() + + void test() { + foo(); + bar(); + } +} + +// PR8457 +namespace Test9 { + extern "C" { + struct A { int field; }; + void DEFAULT test9_fun(struct A *a) { } + struct A DEFAULT test9_var; // above + } + // CHECK: define void @test9_fun( + // CHECK-HIDDEN: define void @test9_fun( + + void test() { + A a = test9_var; + test9_fun(&a); + } +} + +// PR8478 +namespace Test10 { + struct A; + + DEFAULT class B { + void foo(A*); + }; + + // CHECK: define void @_ZN6Test101B3fooEPNS_1AE( + // CHECK-HIDDEN: define void @_ZN6Test101B3fooEPNS_1AE( + void B::foo(A*) {} +} + +// PR8492 +namespace Test11 { + struct A { + void foo() {} + void DEFAULT bar() {} + }; + + void test() { + A a; + a.foo(); + a.bar(); + } + + // CHECK: define linkonce_odr void @_ZN6Test111A3fooEv( + // CHECK: define linkonce_odr void @_ZN6Test111A3barEv( + // CHECK-HIDDEN: define linkonce_odr hidden void @_ZN6Test111A3fooEv( + // CHECK-HIDDEN: define linkonce_odr void @_ZN6Test111A3barEv( +} + +// Tested at top of file. +namespace Test12 { + struct A { + // This is hidden in all cases: the explicit attribute takes + // priority over -fvisibility on the parent. + static int hidden HIDDEN; + + // This is default in all cases because it's only a declaration. + static int visible; + }; + + void test() { + A::hidden = 0; + A::visible = 0; + } +} + +// Tested at top of file. +namespace Test13 { + struct HIDDEN A {}; + + // Should be hidden in all cases. + struct B { + static A a; + }; + A B::a; + + // Should be default in all cases. + struct DEFAULT C { + static A a; + }; + A C::a; +}; + +// Tested at top of file. +namespace Test14 { + // Neither the visibility of the type nor -fvisibility=hidden should + // apply to declarations. + extern struct A *var; + + struct A *test() { return var; } +} + +// rdar://problem/8613093 +namespace Test15 { + struct A {}; + template <class T> struct Temp { + struct Inner { + static char buffer[0]; + }; + }; + + char *test() { + return Temp<A>::Inner::buffer; + } +} + +namespace Test16 { + struct Base1 { virtual void foo(); }; + struct Base2 : virtual Base1 { virtual void foo(); }; + template <class T> struct A : virtual Base1, Base2 { + virtual void foo(); + }; + extern template struct A<char>; + + void test() { + A<char> a; + a.foo(); + } +} + +namespace Test17 { + struct HIDDEN A { + static void foo(); + static void DEFAULT bar(); + static void HIDDEN baz(); + + struct DEFAULT B { + static void foo(); + static void DEFAULT bar(); + static void HIDDEN baz(); + }; + }; + + void test() { + A::foo(); + A::bar(); + A::baz(); + A::B::foo(); + A::B::bar(); + A::B::baz(); + } + // CHECK: declare hidden void @_ZN6Test171A3fooEv() + // CHECK: declare void @_ZN6Test171A3barEv() + // CHECK: declare hidden void @_ZN6Test171A3bazEv() + // CHECK: declare void @_ZN6Test171A1B3fooEv() + // CHECK: declare void @_ZN6Test171A1B3barEv() + // CHECK: declare hidden void @_ZN6Test171A1B3bazEv() + // CHECK-HIDDEN: declare hidden void @_ZN6Test171A3fooEv() + // CHECK-HIDDEN: declare void @_ZN6Test171A3barEv() + // CHECK-HIDDEN: declare hidden void @_ZN6Test171A3bazEv() + // CHECK-HIDDEN: declare void @_ZN6Test171A1B3fooEv() + // CHECK-HIDDEN: declare void @_ZN6Test171A1B3barEv() + // CHECK-HIDDEN: declare hidden void @_ZN6Test171A1B3bazEv() +} + +namespace Test18 { + template <class T> struct HIDDEN A { + static void foo(); + static void DEFAULT bar(); + static void HIDDEN baz(); + + struct DEFAULT B { + static void foo(); + static void DEFAULT bar(); + static void HIDDEN baz(); + }; + }; + struct HIDDEN H; + + void test() { + A<int>::foo(); + A<int>::bar(); + A<int>::baz(); + A<int>::B::foo(); + A<int>::B::bar(); + A<int>::B::baz(); + A<H>::foo(); + A<H>::bar(); + A<H>::baz(); + A<H>::B::foo(); + A<H>::B::bar(); + A<H>::B::baz(); + } + // CHECK: declare hidden void @_ZN6Test181AIiE3fooEv() + // CHECK: declare void @_ZN6Test181AIiE3barEv() + // CHECK: declare hidden void @_ZN6Test181AIiE3bazEv() + // CHECK: declare void @_ZN6Test181AIiE1B3fooEv() + // CHECK: declare void @_ZN6Test181AIiE1B3barEv() + // CHECK: declare hidden void @_ZN6Test181AIiE1B3bazEv() + // CHECK: declare hidden void @_ZN6Test181AINS_1HEE3fooEv() + // CHECK: declare hidden void @_ZN6Test181AINS_1HEE3barEv() + // CHECK: declare hidden void @_ZN6Test181AINS_1HEE3bazEv() + // CHECK: declare hidden void @_ZN6Test181AINS_1HEE1B3fooEv() + // CHECK: declare hidden void @_ZN6Test181AINS_1HEE1B3barEv() + // CHECK: declare hidden void @_ZN6Test181AINS_1HEE1B3bazEv() + // CHECK-HIDDEN: declare hidden void @_ZN6Test181AIiE3fooEv() + // CHECK-HIDDEN: declare void @_ZN6Test181AIiE3barEv() + // CHECK-HIDDEN: declare hidden void @_ZN6Test181AIiE3bazEv() + // CHECK-HIDDEN: declare void @_ZN6Test181AIiE1B3fooEv() + // CHECK-HIDDEN: declare void @_ZN6Test181AIiE1B3barEv() + // CHECK-HIDDEN: declare hidden void @_ZN6Test181AIiE1B3bazEv() + // CHECK-HIDDEN: declare hidden void @_ZN6Test181AINS_1HEE3fooEv() + // CHECK-HIDDEN: declare hidden void @_ZN6Test181AINS_1HEE3barEv() + // CHECK-HIDDEN: declare hidden void @_ZN6Test181AINS_1HEE3bazEv() + // CHECK-HIDDEN: declare hidden void @_ZN6Test181AINS_1HEE1B3fooEv() + // CHECK-HIDDEN: declare hidden void @_ZN6Test181AINS_1HEE1B3barEv() + // CHECK-HIDDEN: declare hidden void @_ZN6Test181AINS_1HEE1B3bazEv() +} + +namespace Test19 { + struct A { A(); ~A(); }; + + // Tested at top of file. + template <class T> void foo() { + static A a; + } + + void test() { + foo<int>(); + } +} + +// Various things with class template specializations. +namespace Test20 { + template <unsigned> struct HIDDEN A {}; + + // An explicit specialization inherits the explicit visibility of + // the template. + template <> struct A<0> { + static void test0(); + static void test1(); + }; + + // CHECK: define hidden void @_ZN6Test201AILj0EE5test0Ev() + void A<0>::test0() {} + + // CHECK: declare hidden void @_ZN6Test201AILj0EE5test1Ev() + void test1() { + A<0>::test1(); + } + + // ...unless that's explicitly overridden. + template <> struct DEFAULT A<1> { + static void test2(); + static void test3(); + }; + + // CHECK: define void @_ZN6Test201AILj1EE5test2Ev() + void A<1>::test2() {} + + // CHECK: declare void @_ZN6Test201AILj1EE5test3Ev() + void test3() { + A<1>::test3(); + } + + // <rdar://problem/8778497> + // But we should assume that an unknown specialization has the + // explicit visibility settings of the template. + template <class T> struct B { + static void test4() {} + static void test5(); + }; + + // CHECK: define linkonce_odr hidden void @_ZN6Test201BINS_1AILj2EEEE5test4Ev() + void test4() { + B<A<2> >::test4(); + } + + // CHECK: declare void @_ZN6Test201BINS_1AILj2EEEE5test5Ev() + // (but explicit visibility on a template argument doesn't count as + // explicit visibility for the template for purposes of deciding + // whether an external symbol gets visibility) + void test5() { + B<A<2> >::test5(); + } +} diff --git a/test/CodeGenCXX/volatile-1.cpp b/test/CodeGenCXX/volatile-1.cpp new file mode 100644 index 0000000..3ae17bd --- /dev/null +++ b/test/CodeGenCXX/volatile-1.cpp @@ -0,0 +1,352 @@ +// RUN: %clang_cc1 -Wno-unused-value -emit-llvm %s -o - | FileCheck %s + +// CHECK: @i = global [[INT:i[0-9]+]] 0 +volatile int i, j, k; +volatile int ar[5]; +volatile char c; +// CHECK: @ci = global [[CINT:%.*]] zeroinitializer +volatile _Complex int ci; +volatile struct S { +#ifdef __cplusplus + void operator =(volatile struct S&o) volatile; +#endif + int i; +} a, b; + +//void operator =(volatile struct S&o1, volatile struct S&o2) volatile; +int printf(const char *, ...); + + +// CHECK: define void @{{.*}}test +void test() { + + asm("nop"); // CHECK: call void asm + + // should not load + i; + + (float)(ci); + // CHECK-NEXT: volatile load [[INT]]* getelementptr inbounds ([[CINT]]* @ci, i32 0, i32 0) + // CHECK-NEXT: volatile load [[INT]]* getelementptr inbounds ([[CINT]]* @ci, i32 0, i32 1) + // CHECK-NEXT: sitofp [[INT]] + + // These are not uses in C++: + // [expr.static.cast]p6: + // The lvalue-to-rvalue . . . conversions are not applied to the expression. + (void)ci; + (void)a; + + (void)(ci=ci); + // CHECK-NEXT: [[R:%.*]] = volatile load [[INT]]* getelementptr inbounds ([[CINT]]* @ci, i32 0, i32 0) + // CHECK-NEXT: [[I:%.*]] = volatile load [[INT]]* getelementptr inbounds ([[CINT]]* @ci, i32 0, i32 1) + // CHECK-NEXT: volatile store [[INT]] [[R]], [[INT]]* getelementptr inbounds ([[CINT]]* @ci, i32 0, i32 0) + // CHECK-NEXT: volatile store [[INT]] [[I]], [[INT]]* getelementptr inbounds ([[CINT]]* @ci, i32 0, i32 1) + + (void)(i=j); + // CHECK-NEXT: [[T:%.*]] = volatile load [[INT]]* @j + // CHECK-NEXT: volatile store [[INT]] [[T]], [[INT]]* @i + + ci+=ci; + // CHECK-NEXT: [[R1:%.*]] = volatile load [[INT]]* getelementptr inbounds ([[CINT]]* @ci, i32 0, i32 0) + // CHECK-NEXT: [[I1:%.*]] = volatile load [[INT]]* getelementptr inbounds ([[CINT]]* @ci, i32 0, i32 1) + // CHECK-NEXT: [[R2:%.*]] = volatile load [[INT]]* getelementptr inbounds ([[CINT]]* @ci, i32 0, i32 0) + // CHECK-NEXT: [[I2:%.*]] = volatile load [[INT]]* getelementptr inbounds ([[CINT]]* @ci, i32 0, i32 1) + // Not sure why they're ordered this way. + // CHECK-NEXT: [[R:%.*]] = add [[INT]] [[R2]], [[R1]] + // CHECK-NEXT: [[I:%.*]] = add [[INT]] [[I2]], [[I1]] + // CHECK-NEXT: volatile store [[INT]] [[R]], [[INT]]* getelementptr inbounds ([[CINT]]* @ci, i32 0, i32 0) + // CHECK-NEXT: volatile store [[INT]] [[I]], [[INT]]* getelementptr inbounds ([[CINT]]* @ci, i32 0, i32 1) + + // Note that C++ requires an extra volatile load over C from the LHS of the '+'. + (ci += ci) + ci; + // CHECK-NEXT: [[R1:%.*]] = volatile load [[INT]]* getelementptr inbounds ([[CINT]]* @ci, i32 0, i32 0) + // CHECK-NEXT: [[I1:%.*]] = volatile load [[INT]]* getelementptr inbounds ([[CINT]]* @ci, i32 0, i32 1) + // CHECK-NEXT: [[R2:%.*]] = volatile load [[INT]]* getelementptr inbounds ([[CINT]]* @ci, i32 0, i32 0) + // CHECK-NEXT: [[I2:%.*]] = volatile load [[INT]]* getelementptr inbounds ([[CINT]]* @ci, i32 0, i32 1) + // CHECK-NEXT: [[R:%.*]] = add [[INT]] [[R2]], [[R1]] + // CHECK-NEXT: [[I:%.*]] = add [[INT]] [[I2]], [[I1]] + // CHECK-NEXT: volatile store [[INT]] [[R]], [[INT]]* getelementptr inbounds ([[CINT]]* @ci, i32 0, i32 0) + // CHECK-NEXT: volatile store [[INT]] [[I]], [[INT]]* getelementptr inbounds ([[CINT]]* @ci, i32 0, i32 1) + // CHECK-NEXT: [[R1:%.*]] = volatile load [[INT]]* getelementptr inbounds ([[CINT]]* @ci, i32 0, i32 0) + // CHECK-NEXT: [[I1:%.*]] = volatile load [[INT]]* getelementptr inbounds ([[CINT]]* @ci, i32 0, i32 1) + // CHECK-NEXT: [[R2:%.*]] = volatile load [[INT]]* getelementptr inbounds ([[CINT]]* @ci, i32 0, i32 0) + // CHECK-NEXT: [[I2:%.*]] = volatile load [[INT]]* getelementptr inbounds ([[CINT]]* @ci, i32 0, i32 1) + // These additions can be elided. + // CHECK-NEXT: add [[INT]] [[R1]], [[R2]] + // CHECK-NEXT: add [[INT]] [[I1]], [[I2]] + + asm("nop"); // CHECK-NEXT: call void asm + + // Extra volatile load in C++. + (i += j) + k; + // CHECK-NEXT: volatile load + // CHECK-NEXT: volatile load + // CHECK-NEXT: add nsw [[INT]] + // CHECK-NEXT: volatile store + // CHECK-NEXT: volatile load + // CHECK-NEXT: volatile load + // CHECK-NEXT: add nsw [[INT]] + + asm("nop"); // CHECK-NEXT: call void asm + + // Extra volatile load in C++. + (i += j) + 1; + // CHECK-NEXT: volatile load + // CHECK-NEXT: volatile load + // CHECK-NEXT: add nsw [[INT]] + // CHECK-NEXT: volatile store + // CHECK-NEXT: volatile load + // CHECK-NEXT: add nsw [[INT]] + + asm("nop"); // CHECK-NEXT: call void asm + + ci+ci; + // CHECK-NEXT: volatile load + // CHECK-NEXT: volatile load + // CHECK-NEXT: volatile load + // CHECK-NEXT: volatile load + // CHECK-NEXT: add [[INT]] + // CHECK-NEXT: add [[INT]] + + __real i; + + +ci; + // CHECK-NEXT: volatile load + // CHECK-NEXT: volatile load + + asm("nop"); // CHECK-NEXT: call void asm + + (void)(i=i); + // CHECK-NEXT: volatile load + // CHECK-NEXT: volatile store + + (float)(i=i); + // CHECK-NEXT: volatile load + // CHECK-NEXT: volatile store + // CHECK-NEXT: volatile load + // CHECK-NEXT: sitofp + + (void)i; + + i=i; + // CHECK-NEXT: volatile load + // CHECK-NEXT: volatile store + + // Extra volatile load in C++. + i=i=i; + // CHECK-NEXT: volatile load + // CHECK-NEXT: volatile store + // CHECK-NEXT: volatile load + // CHECK-NEXT: volatile store + + (void)__builtin_choose_expr(0, i=i, j=j); + // CHECK-NEXT: volatile load + // CHECK-NEXT: volatile store + + k ? (i=i) : (j=j); + // CHECK-NEXT: volatile load + // CHECK-NEXT: icmp + // CHECK-NEXT: br i1 + // CHECK: volatile load + // CHECK-NEXT: volatile store + // CHECK-NEXT: br label + // CHECK: volatile load + // CHECK-NEXT: volatile store + // CHECK-NEXT: br label + // CHECK: phi + + (void)(i,(i=i)); + // CHECK-NEXT: volatile load + // CHECK-NEXT: volatile store + + i=i,k; + // CHECK-NEXT: volatile load [[INT]]* @i + // CHECK-NEXT: volatile store {{.*}}, [[INT]]* @i + + (i=j,k=j); + // CHECK-NEXT: volatile load [[INT]]* @j + // CHECK-NEXT: volatile store {{.*}}, [[INT]]* @i + // CHECK-NEXT: volatile load [[INT]]* @j + // CHECK-NEXT: volatile store {{.*}}, [[INT]]* @k + + (i=j,k); + // CHECK-NEXT: volatile load [[INT]]* @j + // CHECK-NEXT: volatile store {{.*}}, [[INT]]* @i + + (i,j); + + // Extra load in C++. + i=c=k; + // CHECK-NEXT: volatile load + // CHECK-NEXT: trunc + // CHECK-NEXT: volatile store + // CHECK-NEXT: volatile load + // CHECK-NEXT: sext + // CHECK-NEXT: volatile store + + i+=k; + // CHECK-NEXT: volatile load + // CHECK-NEXT: volatile load + // CHECK-NEXT: add nsw [[INT]] + // CHECK-NEXT: volatile store + + ci; + + asm("nop"); // CHECK-NEXT: call void asm + + (int)ci; + // CHECK-NEXT: volatile load {{.*}} @ci, i32 0, i32 0 + // CHECK-NEXT: volatile load {{.*}} @ci, i32 0, i32 1 + + (bool)ci; + // CHECK-NEXT: volatile load {{.*}} @ci, i32 0, i32 0 + // CHECK-NEXT: volatile load {{.*}} @ci, i32 0, i32 1 + // CHECK-NEXT: icmp ne + // CHECK-NEXT: icmp ne + // CHECK-NEXT: or i1 + + ci=ci; + // CHECK-NEXT: volatile load + // CHECK-NEXT: volatile load + // CHECK-NEXT: volatile store + // CHECK-NEXT: volatile store + + asm("nop"); // CHECK-NEXT: call void asm + + // Extra load in C++. + ci=ci=ci; + // CHECK-NEXT: volatile load + // CHECK-NEXT: volatile load + // CHECK-NEXT: volatile store + // CHECK-NEXT: volatile store + // CHECK-NEXT: volatile load + // CHECK-NEXT: volatile load + // CHECK-NEXT: volatile store + // CHECK-NEXT: volatile store + + __imag ci = __imag ci = __imag ci; + // CHECK-NEXT: [[T:%.*]] = volatile load [[INT]]* getelementptr inbounds ([[CINT]]* @ci, i32 0, i32 1) + // CHECK-NEXT: volatile store [[INT]] [[T]], [[INT]]* getelementptr inbounds ([[CINT]]* @ci, i32 0, i32 1) + // CHECK-NEXT: [[T:%.*]] = volatile load [[INT]]* getelementptr inbounds ([[CINT]]* @ci, i32 0, i32 1) + // CHECK-NEXT: volatile store [[INT]] [[T]], [[INT]]* getelementptr inbounds ([[CINT]]* @ci, i32 0, i32 1) + + __real (i = j); + // CHECK-NEXT: volatile load + // CHECK-NEXT: volatile store + + __imag i; + + // ============================================================ + // FIXME: Test cases we get wrong. + + // A use. We load all of a into a copy of a, then load i. gcc forgets to do + // the assignment. + // (a = a).i; + + // ============================================================ + // Test cases where we intentionally differ from gcc, due to suspected bugs in + // gcc. + + // Not a use. gcc forgets to do the assignment. + // CHECK-NEXT: call + ((a=a),a); + + // Not a use. gcc gets this wrong, it doesn't emit the copy! + // CHECK-NEXT: call + (void)(a=a); + + // Not a use. gcc got this wrong in 4.2 and omitted the side effects + // entirely, but it is fixed in 4.4.0. + __imag (i = j); + // CHECK-NEXT: volatile load + // CHECK-NEXT: volatile store + + // C++ does an extra load here. Note that we have to do full loads. + (float)(ci=ci); + // CHECK-NEXT: volatile load + // CHECK-NEXT: volatile load + // CHECK-NEXT: volatile store + // CHECK-NEXT: volatile store + // CHECK-NEXT: volatile load + // CHECK-NEXT: volatile load + // CHECK-NEXT: sitofp + + // Not a use, bug? gcc treats this as not a use, that's probably a + // bug due to tree folding ignoring volatile. + (int)(ci=ci); + // CHECK-NEXT: volatile load + // CHECK-NEXT: volatile load + // CHECK-NEXT: volatile store + // CHECK-NEXT: volatile store + // CHECK-NEXT: volatile load + // CHECK-NEXT: volatile load + + // A use. + (float)(i=i); + // CHECK-NEXT: volatile load + // CHECK-NEXT: volatile store + // CHECK-NEXT: volatile load + // CHECK-NEXT: sitofp + + // A use. gcc treats this as not a use, that's probably a bug due to tree + // folding ignoring volatile. + (int)(i=i); + // CHECK-NEXT: volatile load + // CHECK-NEXT: volatile store + // CHECK-NEXT: volatile load + + // A use. + -(i=j); + // CHECK-NEXT: volatile load + // CHECK-NEXT: volatile store + // CHECK-NEXT: volatile load + // CHECK-NEXT: sub + + // A use. gcc treats this a not a use, that's probably a bug due to tree + // folding ignoring volatile. + +(i=k); + // CHECK-NEXT: volatile load + // CHECK-NEXT: volatile store + // CHECK-NEXT: volatile load + + // A use. gcc treats this a not a use, that's probably a bug due to tree + // folding ignoring volatile. + __real (ci=ci); + // CHECK-NEXT: volatile load + // CHECK-NEXT: volatile load + // CHECK-NEXT: volatile store + // CHECK-NEXT: volatile store + + // A use. + i + 0; + // CHECK-NEXT: volatile load + // CHECK-NEXT: add + + // A use. + (i=j) + i; + // CHECK-NEXT: volatile load + // CHECK-NEXT: volatile store + // CHECK-NEXT: volatile load + // CHECK-NEXT: volatile load + // CHECK-NEXT: add + + // A use. gcc treats this as not a use, that's probably a bug due to tree + // folding ignoring volatile. + (i=j) + 0; + // CHECK-NEXT: volatile load + // CHECK-NEXT: volatile store + // CHECK-NEXT: volatile load + // CHECK-NEXT: add + + (i,j)=k; + // CHECK-NEXT: volatile load [[INT]]* @k + // CHECK-NEXT: volatile store {{.*}}, [[INT]]* @j + + (j=k,i)=i; + // CHECK-NEXT: volatile load [[INT]]* @i + // CHECK-NEXT: volatile load [[INT]]* @k + // CHECK-NEXT: volatile store {{.*}}, [[INT]]* @j + // CHECK-NEXT: volatile store {{.*}}, [[INT]]* @i + + // CHECK-NEXT: ret void +} diff --git a/test/CodeGenCXX/volatile.cpp b/test/CodeGenCXX/volatile.cpp index 58f433f..6ebb2f1 100644 --- a/test/CodeGenCXX/volatile.cpp +++ b/test/CodeGenCXX/volatile.cpp @@ -27,8 +27,6 @@ namespace test1 { // 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-available-externally.cpp b/test/CodeGenCXX/vtable-available-externally.cpp new file mode 100644 index 0000000..23baac9 --- /dev/null +++ b/test/CodeGenCXX/vtable-available-externally.cpp @@ -0,0 +1,171 @@ +// RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -emit-llvm -O3 -o %t +// RUN: FileCheck --check-prefix=CHECK-TEST1 %s < %t +// RUN: FileCheck --check-prefix=CHECK-TEST2 %s < %t +// RUN: FileCheck --check-prefix=CHECK-TEST5 %s < %t +// RUN: FileCheck --check-prefix=CHECK-TEST7 %s < %t + +#include <typeinfo> + +// Test1::A's key function (f) is not defined in this translation unit, but in +// order to devirtualize calls, we emit the class related data with +// available_externally linkage. + +// CHECK-TEST1: @_ZTVN5Test11AE = available_externally +// CHECK-TEST1: @_ZTSN5Test11AE = available_externally +// CHECK-TEST1: @_ZTIN5Test11AE = available_externally +namespace Test1 { + +struct A { + A(); + virtual void f(); + virtual ~A() { } +}; + +A::A() { } + +void f(A* a) { + a->f(); +}; + +// CHECK: define void @_ZN5Test11gEv +// CHECK: call void @_ZN5Test11A1fEv +void g() { + A a; + f(&a); +} + +} + +// Test2::A's key function (f) is defined in this translation unit, but when +// we're doing codegen for the typeid(A) call, we don't know that yet. +// This tests mainly that the typeinfo and typename constants have their linkage +// updated correctly. + +// CHECK-TEST2: @_ZTSN5Test21AE = constant +// CHECK-TEST2: @_ZTIN5Test21AE = unnamed_addr constant +// CHECK-TEST2: @_ZTVN5Test21AE = unnamed_addr constant +namespace Test2 { + struct A { + virtual void f(); + }; + + const std::type_info &g() { + return typeid(A); + }; + + void A::f() { } +} + +// Test that we don't assert on this test. +namespace Test3 { + +struct A { + virtual void f(); + virtual ~A() { } +}; + +struct B : A { + B(); + virtual void f(); +}; + +B::B() { } + +void g(A* a) { + a->f(); +}; + +} + +// PR9114, test that we don't try to instantiate RefPtr<Node>. +namespace Test4 { + +template <class T> struct RefPtr { + T* p; + ~RefPtr() { + p->deref(); + } +}; + +struct A { + virtual ~A(); +}; + +struct Node; + +struct B : A { + virtual void deref(); + RefPtr<Node> m; +}; + +void f() { + RefPtr<B> b; +} + +} + +// PR9130, test that we emit a definition of A::f. +// CHECK-TEST5: define linkonce_odr void @_ZN5Test51A1fEv +namespace Test5 { + +struct A { + virtual void f() { } +}; + +struct B : A { + virtual ~B(); +}; + +B::~B() { } + +} + +// Check that we don't assert on this test. +namespace Test6 { + +struct A { + virtual ~A(); + int a; +}; + +struct B { + virtual ~B(); + int b; +}; + +struct C : A, B { + C(); +}; + +struct D : C { + virtual void f(); + D(); +}; + +D::D() { } + +} + +namespace Test7 { + +struct c1 {}; +struct c10 : c1{ + virtual void foo (); +}; +struct c11 : c10, c1{ + virtual void f6 (); +}; +struct c28 : virtual c11{ + void f6 (); +}; + +// CHECK-TEST7: define void @_ZN5Test79check_c28Ev +// CHECK-TEST7: call void @_ZN5Test73c282f6Ev +// CHECK-TEST7: ret void +void check_c28 () { + c28 obj; + c11 *ptr = &obj; + ptr->f6 (); +} + +} diff --git a/test/CodeGenCXX/vtable-debug-info.cpp b/test/CodeGenCXX/vtable-debug-info.cpp new file mode 100644 index 0000000..c355406 --- /dev/null +++ b/test/CodeGenCXX/vtable-debug-info.cpp @@ -0,0 +1,318 @@ +// RUN: %clang -c -g %s -o /dev/null +// Radar 8730409 +// XFAIL: win32 + +// FIXME: This test crashes on Windows. +#ifdef _WIN32 + +#error this test must xfail + +#else +class foo { +public: +#define x(a) virtual void v ## a (void) +x(1); +x(2); +x(3); +x(4); +x(5); +x(6); +x(7); +x(8); +x(9); +x(10); +x(11); +x(12); +x(13); +x(14); +x(15); +x(16); +x(17); +x(18); +x(19); +x(20); +x(21); +x(22); +x(23); +x(24); +x(25); +x(26); +x(27); +x(28); +x(29); +x(30); +x(31); +x(32); +x(33); +x(34); +x(35); +x(36); +x(37); +x(38); +x(39); +x(40); +x(41); +x(42); +x(43); +x(44); +x(45); +x(46); +x(47); +x(48); +x(49); +x(50); +x(51); +x(52); +x(53); +x(54); +x(55); +x(56); +x(57); +x(58); +x(59); +x(60); +x(61); +x(62); +x(63); +x(64); +x(65); +x(66); +x(67); +x(68); +x(69); +x(70); +x(71); +x(72); +x(73); +x(74); +x(75); +x(76); +x(77); +x(78); +x(79); +x(80); +x(81); +x(82); +x(83); +x(84); +x(85); +x(86); +x(87); +x(88); +x(89); +x(90); +x(91); +x(92); +x(93); +x(94); +x(95); +x(96); +x(97); +x(98); +x(99); +x(100); +x(101); +x(102); +x(103); +x(104); +x(105); +x(106); +x(107); +x(108); +x(109); +x(110); +x(111); +x(112); +x(113); +x(114); +x(115); +x(116); +x(117); +x(118); +x(119); +x(120); +x(121); +x(122); +x(123); +x(124); +x(125); +x(126); +x(127); +x(128); +x(129); +x(130); +x(131); +x(132); +x(133); +x(134); +x(135); +x(136); +x(137); +x(138); +x(139); +x(140); +x(141); +x(142); +x(143); +x(144); +x(145); +x(146); +x(147); +x(148); +x(149); +x(150); +x(151); +x(152); +x(153); +x(154); +x(155); +x(156); +x(157); +x(158); +x(159); +x(160); +x(161); +x(162); +x(163); +x(164); +x(165); +x(166); +x(167); +x(168); +x(169); +x(170); +x(171); +x(172); +x(173); +x(174); +x(175); +x(176); +x(177); +x(178); +x(179); +x(180); +x(181); +x(182); +x(183); +x(184); +x(185); +x(186); +x(187); +x(188); +x(189); +x(190); +x(191); +x(192); +x(193); +x(194); +x(195); +x(196); +x(197); +x(198); +x(199); +x(200); +x(201); +x(202); +x(203); +x(204); +x(205); +x(206); +x(207); +x(208); +x(209); +x(210); +x(211); +x(212); +x(213); +x(214); +x(215); +x(216); +x(217); +x(218); +x(219); +x(220); +x(221); +x(222); +x(223); +x(224); +x(225); +x(226); +x(227); +x(228); +x(229); +x(230); +x(231); +x(232); +x(233); +x(234); +x(235); +x(236); +x(237); +x(238); +x(239); +x(240); +x(241); +x(242); +x(243); +x(244); +x(245); +x(246); +x(247); +x(248); +x(249); +x(250); +x(251); +x(252); +x(253); +x(254); +x(255); +x(256); +x(257); +x(258); +x(259); +x(260); +x(261); +x(262); +x(263); +x(264); +x(265); +x(266); +x(267); +x(268); +x(269); +x(270); +x(271); +x(272); +x(273); +x(274); +x(275); +x(276); +x(277); +x(278); +x(279); +x(280); +x(281); +x(282); +x(283); +x(284); +x(285); +x(286); +x(287); +x(288); +x(289); +x(290); +x(291); +x(292); +x(293); +x(294); +x(295); +x(296); +x(297); +x(298); +x(299); +x(300); +}; + +foo b; + +#endif diff --git a/test/CodeGenCXX/vtable-key-function.cpp b/test/CodeGenCXX/vtable-key-function.cpp index 97a546f..bf2e679 100644 --- a/test/CodeGenCXX/vtable-key-function.cpp +++ b/test/CodeGenCXX/vtable-key-function.cpp @@ -9,7 +9,7 @@ struct A { // A does not have a key function, so the first constructor we emit should // cause the vtable to be defined (without assertions.) -// CHECK: @_ZTVN6PR56971AE = weak_odr constant +// CHECK: @_ZTVN6PR56971AE = linkonce_odr unnamed_addr constant A::A() { } A::A(int) { } } diff --git a/test/CodeGenCXX/vtable-layout.cpp b/test/CodeGenCXX/vtable-layout.cpp index 60b46fe..1cf8a52 100644 --- a/test/CodeGenCXX/vtable-layout.cpp +++ b/test/CodeGenCXX/vtable-layout.cpp @@ -78,7 +78,7 @@ namespace Test2 { // CHECK-2-NEXT: 5 | Test2::A::~A() [complete] // CHECK-2-NEXT: 6 | Test2::A::~A() [deleting] // CHECK-2-NEXT: 7 | void Test2::A::h() -// CHECK-2-NEXT: 8 | Test2::A &Test2::A::operator=(Test2::A const &) +// CHECK-2-NEXT: 8 | Test2::A &Test2::A::operator=(const Test2::A &) struct A { virtual void f(); virtual void f() const; diff --git a/test/CodeGenCXX/vtable-linkage.cpp b/test/CodeGenCXX/vtable-linkage.cpp index cf988d1..fc14c71 100644 --- a/test/CodeGenCXX/vtable-linkage.cpp +++ b/test/CodeGenCXX/vtable-linkage.cpp @@ -32,7 +32,7 @@ struct B { B::B() { } -struct C { +struct C : virtual B { C(); virtual void f() { } }; @@ -99,92 +99,94 @@ void use_F() { // B has a key function that is not defined in this translation unit so its vtable // has external linkage. -// CHECK-1: @_ZTV1B = external constant +// CHECK-1: @_ZTV1B = external unnamed_addr constant // 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 +// CHECK-2: @_ZTV1C = linkonce_odr unnamed_addr constant +// CHECK-2: @_ZTS1C = linkonce_odr constant +// CHECK-2: @_ZTI1C = linkonce_odr unnamed_addr constant +// CHECK-2: @_ZTT1C = linkonce_odr unnamed_addr constant +// CHECK-2-HIDDEN: @_ZTV1C = linkonce_odr hidden unnamed_addr constant +// CHECK-2-HIDDEN: @_ZTS1C = linkonce_odr constant +// CHECK-2-HIDDEN: @_ZTI1C = linkonce_odr hidden unnamed_addr constant +// CHECK-2-HIDDEN: @_ZTT1C = linkonce_odr hidden unnamed_addr constant // D has a key function that is defined in this translation unit so its vtable is // defined in the translation unit. -// CHECK-3: @_ZTV1D = constant +// CHECK-3: @_ZTV1D = unnamed_addr constant // CHECK-3: @_ZTS1D = constant -// CHECK-3: @_ZTI1D = constant +// CHECK-3: @_ZTI1D = unnamed_addr constant // E<char> is an explicit specialization with a key function defined // in this translation unit, so its vtable should have external // linkage. -// CHECK-4: @_ZTV1EIcE = constant +// CHECK-4: @_ZTV1EIcE = unnamed_addr constant // CHECK-4: @_ZTS1EIcE = constant -// CHECK-4: @_ZTI1EIcE = constant +// CHECK-4: @_ZTI1EIcE = unnamed_addr constant // E<short> is an explicit template instantiation with a key function // defined in this translation unit, so its vtable should have // weak_odr linkage. -// CHECK-5: @_ZTV1EIsE = weak_odr constant +// CHECK-5: @_ZTV1EIsE = weak_odr unnamed_addr constant // CHECK-5: @_ZTS1EIsE = weak_odr constant -// CHECK-5: @_ZTI1EIsE = weak_odr constant -// CHECK-5-HIDDEN: @_ZTV1EIsE = weak_odr constant +// CHECK-5: @_ZTI1EIsE = weak_odr unnamed_addr constant +// CHECK-5-HIDDEN: @_ZTV1EIsE = weak_odr unnamed_addr constant // CHECK-5-HIDDEN: @_ZTS1EIsE = weak_odr constant -// CHECK-5-HIDDEN: @_ZTI1EIsE = weak_odr constant +// CHECK-5-HIDDEN: @_ZTI1EIsE = weak_odr unnamed_addr 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: @_ZTV1FIsE = weak_odr unnamed_addr constant // CHECK-6: @_ZTS1FIsE = weak_odr constant -// CHECK-6: @_ZTI1FIsE = weak_odr constant -// CHECK-6-HIDDEN: @_ZTV1FIsE = weak_odr constant +// CHECK-6: @_ZTI1FIsE = weak_odr unnamed_addr constant +// CHECK-6-HIDDEN: @_ZTV1FIsE = weak_odr unnamed_addr constant // CHECK-6-HIDDEN: @_ZTS1FIsE = weak_odr constant -// CHECK-6-HIDDEN: @_ZTI1FIsE = weak_odr constant +// CHECK-6-HIDDEN: @_ZTI1FIsE = weak_odr unnamed_addr constant // E<long> is an implicit template instantiation with a key function // defined in this translation unit, so its vtable should have -// weak_odr linkage. -// CHECK-7: @_ZTV1EIlE = weak_odr constant -// CHECK-7: @_ZTS1EIlE = weak_odr constant -// CHECK-7: @_ZTI1EIlE = weak_odr constant +// linkonce_odr linkage. +// CHECK-7: @_ZTV1EIlE = linkonce_odr unnamed_addr constant +// CHECK-7: @_ZTS1EIlE = linkonce_odr constant +// CHECK-7: @_ZTI1EIlE = linkonce_odr unnamed_addr constant // F<long> is an implicit template instantiation with no key function, -// so its vtable should have weak_odr linkage. -// CHECK-8: @_ZTV1FIlE = weak_odr constant -// CHECK-8: @_ZTS1FIlE = weak_odr constant -// CHECK-8: @_ZTI1FIlE = weak_odr constant +// so its vtable should have linkonce_odr linkage. +// CHECK-8: @_ZTV1FIlE = linkonce_odr unnamed_addr constant +// CHECK-8: @_ZTS1FIlE = linkonce_odr constant +// CHECK-8: @_ZTI1FIlE = linkonce_odr unnamed_addr constant // F<int> is an explicit template instantiation declaration without a // key function, so its vtable should have external linkage. -// CHECK-9: @_ZTV1FIiE = external constant +// CHECK-9: @_ZTV1FIiE = external unnamed_addr constant // E<int> is an explicit template instantiation declaration. It has a // key function that is not instantiated, so we should only reference // its vtable, not define it. -// CHECK-10: @_ZTV1EIiE = external constant +// CHECK-10: @_ZTV1EIiE = external unnamed_addr constant // The anonymous struct for e has no linkage, so the vtable should have // internal linkage. -// CHECK-11: @"_ZTV3$_0" = internal constant +// CHECK-11: @"_ZTV3$_0" = internal unnamed_addr constant // CHECK-11: @"_ZTS3$_0" = internal constant -// CHECK-11: @"_ZTI3$_0" = internal constant +// CHECK-11: @"_ZTI3$_0" = internal unnamed_addr constant // The A vtable should have internal linkage since it is inside an anonymous // namespace. -// CHECK-12: @_ZTVN12_GLOBAL__N_11AE = internal constant +// CHECK-12: @_ZTVN12_GLOBAL__N_11AE = internal unnamed_addr constant // CHECK-12: @_ZTSN12_GLOBAL__N_11AE = internal constant -// CHECK-12: @_ZTIN12_GLOBAL__N_11AE = internal constant +// CHECK-12: @_ZTIN12_GLOBAL__N_11AE = internal unnamed_addr 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 +// its vtable should have linkonce_odr linkage. +// CHECK-13: @_ZTV1FIcE = linkonce_odr unnamed_addr constant +// CHECK-13: @_ZTS1FIcE = linkonce_odr constant +// CHECK-13: @_ZTI1FIcE = linkonce_odr unnamed_addr constant // RUN: FileCheck --check-prefix=CHECK-G %s < %t // -// CHECK-G: @_ZTV1GIiE = weak_odr constant +// CHECK-G: @_ZTV1GIiE = linkonce_odr unnamed_addr constant template <typename T> class G { public: @@ -197,3 +199,18 @@ void G<int>::f1() {} template <typename T> void G<T>::f0() {} void G_f0() { new G<int>(); } + +// RUN: FileCheck --check-prefix=CHECK-H %s < %t + +// H<int> has a key function without a body but it's a template instantiation +// so its VTable must be emmitted. +// CHECK-H: @_ZTV1HIiE = linkonce_odr unnamed_addr constant +template <typename T> +class H { +public: + virtual ~H(); +}; + +void use_H() { + H<int> h; +} diff --git a/test/CodeGenCXX/vtable-pointer-initialization.cpp b/test/CodeGenCXX/vtable-pointer-initialization.cpp index 75620ab..f629c2d 100644 --- a/test/CodeGenCXX/vtable-pointer-initialization.cpp +++ b/test/CodeGenCXX/vtable-pointer-initialization.cpp @@ -19,14 +19,14 @@ struct A : Base { Field field; }; -// CHECK: define void @_ZN1AC2Ev( +// CHECK: define void @_ZN1AC2Ev(%struct.A* %this) unnamed_addr // CHECK: call void @_ZN4BaseC2Ev( // CHECK: store i8** getelementptr inbounds ([3 x i8*]* @_ZTV1A, i64 0, i64 2) // CHECK: call void @_ZN5FieldC1Ev( // CHECK: ret void A::A() { } -// CHECK: define void @_ZN1AD2Ev( +// CHECK: define void @_ZN1AD2Ev(%struct.A* %this) unnamed_addr // CHECK: store i8** getelementptr inbounds ([3 x i8*]* @_ZTV1A, i64 0, i64 2) // CHECK: call void @_ZN5FieldD1Ev( // CHECK: call void @_ZN4BaseD2Ev( @@ -41,16 +41,16 @@ struct B : Base { void f() { B b; } -// CHECK: define linkonce_odr void @_ZN1BC1Ev( +// CHECK: define linkonce_odr void @_ZN1BC1Ev(%struct.A* %this) unnamed_addr // CHECK: call void @_ZN1BC2Ev( -// CHECK: define linkonce_odr void @_ZN1BD1Ev( +// CHECK: define linkonce_odr void @_ZN1BD1Ev(%struct.A* %this) unnamed_addr // CHECK: store i8** getelementptr inbounds ([3 x i8*]* @_ZTV1B, i64 0, i64 2) // CHECK: call void @_ZN5FieldD1Ev( // CHECK: call void @_ZN4BaseD2Ev( // CHECK: ret void -// CHECK: define linkonce_odr void @_ZN1BC2Ev( +// CHECK: define linkonce_odr void @_ZN1BC2Ev(%struct.A* %this) unnamed_addr // CHECK: call void @_ZN4BaseC2Ev( // CHECK: store i8** getelementptr inbounds ([3 x i8*]* @_ZTV1B, i64 0, i64 2) // CHECK: call void @_ZN5FieldC1Ev diff --git a/test/CodeGenCXX/vtt-layout.cpp b/test/CodeGenCXX/vtt-layout.cpp index 814adf0..ace7b74 100644 --- a/test/CodeGenCXX/vtt-layout.cpp +++ b/test/CodeGenCXX/vtt-layout.cpp @@ -58,7 +58,7 @@ namespace Test4 { D d; } -// 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*)] -// 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*)] +// CHECK: @_ZTTN5Test11BE = unnamed_addr constant [1 x i8*] [i8* bitcast (i8** getelementptr inbounds ([4 x i8*]* @_ZTVN5Test11BE, i64 0, i64 3) to i8*)] +// CHECK: @_ZTTN5Test41DE = linkonce_odr unnamed_addr 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 = linkonce_odr unnamed_addr 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 = linkonce_odr unnamed_addr 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/warn-padded-packed.cpp b/test/CodeGenCXX/warn-padded-packed.cpp new file mode 100644 index 0000000..4203bb3 --- /dev/null +++ b/test/CodeGenCXX/warn-padded-packed.cpp @@ -0,0 +1,76 @@ +// RUN: %clang_cc1 -triple=x86_64-none-none -Wpadded -Wpacked -verify %s -emit-llvm-only + +struct S1 { + char c; + short s; // expected-warning {{padding struct 'S1' with 1 byte to align 's'}} + long l; // expected-warning {{padding struct 'S1' with 4 bytes to align 'l'}} +}; + +struct S2 { // expected-warning {{padding size of 'S2' with 3 bytes to alignment boundary}} + int i; + char c; +}; + +struct S3 { + char c; + int i; +} __attribute__((packed)); + +struct S4 { + int i; // expected-warning {{packed attribute is unnecessary for 'i'}} + char c; +} __attribute__((packed)); + +struct S5 { + char c; + union { + char c; + int i; + } u; // expected-warning {{padding struct 'S5' with 3 bytes to align 'u'}} +}; + +struct S6 { // expected-warning {{padding size of 'S6' with 30 bits to alignment boundary}} + int i : 2; +}; + +struct S7 { // expected-warning {{padding size of 'S7' with 7 bytes to alignment boundary}} + char c; + virtual void m(); +}; + +struct B { + char c; +}; + +struct S8 : B { + int i; // expected-warning {{padding struct 'S8' with 3 bytes to align 'i'}} +}; + +struct S9 { // expected-warning {{packed attribute is unnecessary for 'S9'}} + int x; // expected-warning {{packed attribute is unnecessary for 'x'}} + int y; // expected-warning {{packed attribute is unnecessary for 'y'}} +} __attribute__((packed)); + +struct S10 { // expected-warning {{packed attribute is unnecessary for 'S10'}} + int x; // expected-warning {{packed attribute is unnecessary for 'x'}} + char a,b,c,d; +} __attribute__((packed)); + + +struct S11 { + bool x; + char a,b,c,d; +} __attribute__((packed)); + +struct S12 { + bool b : 1; + char c; // expected-warning {{padding struct 'S12' with 7 bits to align 'c'}} +}; + +struct S13 { // expected-warning {{padding size of 'S13' with 6 bits to alignment boundary}} + char c; + bool b : 10; // expected-warning {{size of bit-field 'b' (10 bits) exceeds the size of its type}} +}; + +// The warnings are emitted when the layout of the structs is computed, so we have to use them. +void f(S1*, S2*, S3*, S4*, S5*, S6*, S7*, S8*, S9*, S10*, S11*, S12*, S13*) { } |