diff options
Diffstat (limited to 'test/CodeGenCXX')
163 files changed, 3988 insertions, 938 deletions
diff --git a/test/CodeGenCXX/2009-05-04-PureConstNounwind.cpp b/test/CodeGenCXX/2009-05-04-PureConstNounwind.cpp index 3828388d48ea..dd5fa3e08fc2 100644 --- a/test/CodeGenCXX/2009-05-04-PureConstNounwind.cpp +++ b/test/CodeGenCXX/2009-05-04-PureConstNounwind.cpp @@ -12,10 +12,11 @@ int f(void) { // CHECK: declare i32 @_Z1cv() [[NUW_RN:#[0-9]+]] // CHECK: declare i32 @_Z1pv() [[NUW_RO:#[0-9]+]] -// CHECK: declare i32 @_Z1tv() [[TF]] +// CHECK: declare i32 @_Z1tv() [[TF2:#[0-9]+]] // CHECK: attributes [[TF]] = { {{.*}} } // CHECK: attributes [[NUW_RN]] = { nounwind readnone{{.*}} } // CHECK: attributes [[NUW_RO]] = { nounwind readonly{{.*}} } +// CHECK: attributes [[TF2]] = { {{.*}} } // CHECK: attributes [[NUW_RN_CALL]] = { nounwind readnone } // CHECK: attributes [[NUW_RO_CALL]] = { nounwind readonly } diff --git a/test/CodeGenCXX/Inputs/debug-info-class-limited.cpp b/test/CodeGenCXX/Inputs/debug-info-class-limited.cpp index 17fa456a45d9..34a1cfa00e2c 100644 --- a/test/CodeGenCXX/Inputs/debug-info-class-limited.cpp +++ b/test/CodeGenCXX/Inputs/debug-info-class-limited.cpp @@ -1,5 +1,6 @@ -// CHECK-DAG: !DICompositeType(tag: DW_TAG_structure_type, name: "PR16214",{{.*}} line: [[@LINE+1]],{{.*}} isDefinition: true +// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "PR16214",{{.*}} line: [[@LINE+2]],{{.*}} +// CHECK-NOT: DIFlagFwdDecl struct PR16214 { int i; }; @@ -10,7 +11,8 @@ bar *a; bar b; namespace PR14467 { -// CHECK-DAG: !DICompositeType(tag: DW_TAG_structure_type, name: "foo",{{.*}} line: [[@LINE+1]],{{.*}} isDefinition: true +// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "foo",{{.*}} line: [[@LINE+2]],{{.*}} +// CHECK-NOT: DIFlagFwdDecl struct foo { }; @@ -21,7 +23,7 @@ foo *bar(foo *a) { } namespace test1 { -// CHECK-DAG: !DICompositeType(tag: DW_TAG_structure_type, name: "foo",{{.*}} line: [[@LINE+1]],{{.*}} isDefinition: true +// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "foo",{{.*}} line: [[@LINE+1]],{{.*}} flags: DIFlagFwdDecl struct foo { }; @@ -35,7 +37,8 @@ namespace test2 { // FIXME: if we were a bit fancier, we could realize that the 'foo' type is only // required because of the 'bar' type which is not required at all (or might // only be required to be declared) -// CHECK-DAG: !DICompositeType(tag: DW_TAG_structure_type, name: "foo",{{.*}} line: [[@LINE+1]],{{.*}} isDefinition: true +// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "foo",{{.*}} line: [[@LINE+2]],{{.*}} +// CHECK-NOT: DIFlagFwdDecl struct foo { }; diff --git a/test/CodeGenCXX/PR20038.cpp b/test/CodeGenCXX/PR20038.cpp index 2d7043dcda33..095705f389bf 100644 --- a/test/CodeGenCXX/PR20038.cpp +++ b/test/CodeGenCXX/PR20038.cpp @@ -7,8 +7,8 @@ extern bool b; // CHECK: call {{.*}}, !dbg [[DTOR_CALL1_LOC:![0-9]*]] // CHECK: call {{.*}}, !dbg [[DTOR_CALL2_LOC:![0-9]*]] // CHECK: [[FUN1:.*]] = distinct !DISubprogram(name: "fun1",{{.*}} isDefinition: true -// CHECK: [[FUN2:.*]] = distinct !DISubprogram(name: "fun2",{{.*}} isDefinition: true // CHECK: [[DTOR_CALL1_LOC]] = !DILocation(line: [[@LINE+1]], scope: [[FUN1]]) void fun1() { b && (C(), 1); } +// CHECK: [[FUN2:.*]] = distinct !DISubprogram(name: "fun2",{{.*}} isDefinition: true // CHECK: [[DTOR_CALL2_LOC]] = !DILocation(line: [[@LINE+1]], scope: [[FUN2]]) bool fun2() { return (C(), b) && 0; } diff --git a/test/CodeGenCXX/PR26569.cpp b/test/CodeGenCXX/PR26569.cpp new file mode 100644 index 000000000000..3e2d2ffeba14 --- /dev/null +++ b/test/CodeGenCXX/PR26569.cpp @@ -0,0 +1,20 @@ +// RUN: %clang_cc1 -triple i686-pc-win32 -fms-extensions -emit-llvm -O1 -disable-llvm-optzns %s -o - | FileCheck %s + +class A { + virtual void m_fn1(); +}; +template <typename> +class B : virtual A {}; + +extern template class __declspec(dllimport) B<int>; +class __declspec(dllexport) C : B<int> {}; + +// CHECK-DAG: @[[VTABLE_C:.*]] = private unnamed_addr constant [2 x i8*] [i8* bitcast (%rtti.CompleteObjectLocator* @"\01??_R4C@@6B@" to i8*), i8* bitcast (void (%class.A*)* @"\01?m_fn1@A@@EAEXXZ" to i8*)] +// CHECK-DAG: @[[VTABLE_B:.*]] = private unnamed_addr constant [2 x i8*] [i8* bitcast (%rtti.CompleteObjectLocator* @"\01??_R4?$B@H@@6B@" to i8*), i8* bitcast (void (%class.A*)* @"\01?m_fn1@A@@EAEXXZ" to i8*)], comdat($"\01??_S?$B@H@@6B@") +// CHECK-DAG: @[[VTABLE_A:.*]] = private unnamed_addr constant [2 x i8*] [i8* bitcast (%rtti.CompleteObjectLocator* @"\01??_R4A@@6B@" to i8*), i8* bitcast (void (%class.A*)* @"\01?m_fn1@A@@EAEXXZ" to i8*)], comdat($"\01??_7A@@6B@") + +// CHECK-DAG: @"\01??_7C@@6B@" = dllexport unnamed_addr alias i8*, getelementptr inbounds ([2 x i8*], [2 x i8*]* @[[VTABLE_C]], i32 0, i32 1) +// CHECK-DAG: @"\01??_S?$B@H@@6B@" = unnamed_addr alias i8*, getelementptr inbounds ([2 x i8*], [2 x i8*]* @[[VTABLE_B]], i32 0, i32 1) +// CHECK-DAG: @"\01??_7A@@6B@" = unnamed_addr alias i8*, getelementptr inbounds ([2 x i8*], [2 x i8*]* @[[VTABLE_A]], i32 0, i32 1) + +// CHECK-DAG: @"\01??_8?$B@H@@7B@" = available_externally dllimport unnamed_addr constant [2 x i32] [i32 0, i32 4] diff --git a/test/CodeGenCXX/PR28220.cpp b/test/CodeGenCXX/PR28220.cpp new file mode 100644 index 000000000000..6262c87de206 --- /dev/null +++ b/test/CodeGenCXX/PR28220.cpp @@ -0,0 +1,19 @@ +// RUN: %clang_cc1 %s -triple i686-pc-win32 -fms-extensions -emit-llvm -o - | FileCheck %s + +template <typename> +struct __declspec(dllimport) S { + S(); +}; + +template <typename T> +struct __declspec(dllimport) U { + static S<T> u; +}; + +template <typename T> +S<T> U<T>::u; + +template S<int> U<int>::u; +// CHECK-NOT: define internal void @"\01??__Eu@?$U@H@@2U?$S@H@@A@YAXXZ"( + +S<int> &i = U<int>::u; diff --git a/test/CodeGenCXX/align-avx-complete-objects.cpp b/test/CodeGenCXX/align-avx-complete-objects.cpp index 6ab17f5d656b..ad4a91428d25 100644 --- a/test/CodeGenCXX/align-avx-complete-objects.cpp +++ b/test/CodeGenCXX/align-avx-complete-objects.cpp @@ -13,7 +13,7 @@ volatile float TestAlign(void) } // CHECK: [[R:%.*]] = alloca <8 x float>, align 32 -// CHECK-NEXT: [[CALL:%.*]] = call noalias i8* @_Znwm(i64 32) +// CHECK-NEXT: [[CALL:%.*]] = call i8* @_Znwm(i64 32) // CHECK-NEXT: [[ZERO:%.*]] = bitcast i8* [[CALL]] to <8 x float>* // CHECK-NEXT: store <8 x float>* [[ZERO]], <8 x float>** [[P:%.*]], align 8 // CHECK-NEXT: [[ONE:%.*]] = load <8 x float>*, <8 x float>** [[P]], align 8 @@ -42,7 +42,7 @@ volatile float TestAlign2(void) } // CHECK: [[R:%.*]] = alloca <8 x float>, align 32 -// CHECK-NEXT: [[CALL:%.*]] = call noalias i8* @_Znwm(i64 32) +// CHECK-NEXT: [[CALL:%.*]] = call i8* @_Znwm(i64 32) // CHECK-NEXT: [[ZERO:%.*]] = bitcast i8* [[CALL]] to <8 x float>* // CHECK-NEXT: store <8 x float>* [[ZERO]], <8 x float>** [[P:%.*]], align 8 // CHECK-NEXT: [[ONE:%.*]] = load <8 x float>*, <8 x float>** [[P]], align 8 diff --git a/test/CodeGenCXX/alignment.cpp b/test/CodeGenCXX/alignment.cpp index 2a1fe71f961b..4c44badd21cd 100644 --- a/test/CodeGenCXX/alignment.cpp +++ b/test/CodeGenCXX/alignment.cpp @@ -32,7 +32,7 @@ namespace test0 { // CHECK: [[T2:%.*]] = or i8 [[T1]], [[T0]] // CHECK: store i8 [[T2]], i8* [[FIELD_P]], align 4 b.onebit = int_source(); - + // CHECK: [[B_P:%.*]] = load [[B]]*, [[B]]** // CHECK: [[FIELD_P:%.*]] = bitcast [[B]]* [[B_P]] to i8* // CHECK: [[VALUE:%.*]] = load i8, i8* [[FIELD_P]], align 4 @@ -60,7 +60,7 @@ namespace test0 { // CHECK: [[T2:%.*]] = or i8 [[T1]], [[T0]] // CHECK: store i8 [[T2]], i8* [[FIELD_P]], align 2 c.onebit = int_source(); - + // CHECK: [[C_P:%.*]] = load [[C]]*, [[C]]** // CHECK: [[T0:%.*]] = bitcast [[C]]* [[C_P]] to i8* // CHECK: [[T1:%.*]] = getelementptr inbounds i8, i8* [[T0]], i64 8 diff --git a/test/CodeGenCXX/arm-swiftcall.cpp b/test/CodeGenCXX/arm-swiftcall.cpp new file mode 100644 index 000000000000..535350c808d3 --- /dev/null +++ b/test/CodeGenCXX/arm-swiftcall.cpp @@ -0,0 +1,115 @@ +// RUN: %clang_cc1 -triple armv7-apple-darwin9 -emit-llvm -o - %s -Wno-return-type-c-linkage | FileCheck %s + +// This isn't really testing anything ARM-specific; it's just a convenient +// 32-bit platform. + +#define SWIFTCALL __attribute__((swiftcall)) +#define OUT __attribute__((swift_indirect_result)) +#define ERROR __attribute__((swift_error_result)) +#define CONTEXT __attribute__((swift_context)) + +/*****************************************************************************/ +/********************************** LOWERING *********************************/ +/*****************************************************************************/ + +#define TEST(TYPE) \ + extern "C" SWIFTCALL TYPE return_##TYPE(void) { \ + TYPE result = {}; \ + return result; \ + } \ + extern "C" SWIFTCALL void take_##TYPE(TYPE v) { \ + } \ + extern "C" void test_##TYPE() { \ + take_##TYPE(return_##TYPE()); \ + } + +/*****************************************************************************/ +/*********************************** STRUCTS *********************************/ +/*****************************************************************************/ + +typedef struct { +} struct_empty; +TEST(struct_empty); +// CHECK-LABEL: define {{.*}} @return_struct_empty() +// CHECK: ret void +// CHECK-LABEL: define {{.*}} @take_struct_empty() +// CHECK: ret void + +// This is only properly testable in C++ because it relies on empty structs +// actually taking up space in a structure without requiring any extra data +// to be passed. +typedef struct { + int x; + struct_empty padding[2]; + char c1; + float f0; + float f1; +} struct_1; +TEST(struct_1); +// CHECK-LABEL: define {{.*}} @return_struct_1() +// CHECK: [[RET:%.*]] = alloca [[REC:%.*]], align 4 +// CHECK: @llvm.memset +// CHECK: [[CAST_TMP:%.*]] = bitcast [[REC]]* [[RET]] to [[AGG:{ i32, \[2 x i8\], i8, \[1 x i8\], float, float }]]* +// CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 0 +// CHECK: [[FIRST:%.*]] = load i32, i32* [[T0]], align 4 +// CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 2 +// CHECK: [[SECOND:%.*]] = load i8, i8* [[T0]], align 2 +// CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 4 +// CHECK: [[THIRD:%.*]] = load float, float* [[T0]], align 4 +// CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 5 +// CHECK: [[FOURTH:%.*]] = load float, float* [[T0]], align 4 +// CHECK: [[T0:%.*]] = insertvalue [[UAGG:{ i32, i8, float, float }]] undef, i32 [[FIRST]], 0 +// CHECK: [[T1:%.*]] = insertvalue [[UAGG]] [[T0]], i8 [[SECOND]], 1 +// CHECK: [[T2:%.*]] = insertvalue [[UAGG]] [[T1]], float [[THIRD]], 2 +// CHECK: [[T3:%.*]] = insertvalue [[UAGG]] [[T2]], float [[FOURTH]], 3 +// CHECK: ret [[UAGG]] [[T3]] +// CHECK-LABEL: define {{.*}} @take_struct_1(i32, i8, float, float) +// CHECK: [[V:%.*]] = alloca [[REC]], align 4 +// CHECK: [[CAST_TMP:%.*]] = bitcast [[REC]]* [[V]] to [[AGG]]* +// CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 0 +// CHECK: store i32 %0, i32* [[T0]], align 4 +// CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 2 +// CHECK: store i8 %1, i8* [[T0]], align 2 +// CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 4 +// CHECK: store float %2, float* [[T0]], align 4 +// CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 5 +// CHECK: store float %3, float* [[T0]], align 4 +// CHECK: ret void +// CHECK-LABEL: define void @test_struct_1() +// CHECK: [[TMP:%.*]] = alloca [[REC]], align 4 +// CHECK: [[CALL:%.*]] = call [[SWIFTCC:swiftcc]] [[UAGG]] @return_struct_1() +// CHECK: [[CAST_TMP:%.*]] = bitcast [[REC]]* [[TMP]] to [[AGG]]* +// CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 0 +// CHECK: [[T1:%.*]] = extractvalue [[UAGG]] [[CALL]], 0 +// CHECK: store i32 [[T1]], i32* [[T0]], align 4 +// CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 2 +// CHECK: [[T1:%.*]] = extractvalue [[UAGG]] [[CALL]], 1 +// CHECK: store i8 [[T1]], i8* [[T0]], align 2 +// CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 4 +// CHECK: [[T1:%.*]] = extractvalue [[UAGG]] [[CALL]], 2 +// CHECK: store float [[T1]], float* [[T0]], align 4 +// CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 5 +// CHECK: [[T1:%.*]] = extractvalue [[UAGG]] [[CALL]], 3 +// CHECK: store float [[T1]], float* [[T0]], align 4 +// CHECK: [[CAST_TMP:%.*]] = bitcast [[REC]]* [[TMP]] to [[AGG]]* +// CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 0 +// CHECK: [[FIRST:%.*]] = load i32, i32* [[T0]], align 4 +// CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 2 +// CHECK: [[SECOND:%.*]] = load i8, i8* [[T0]], align 2 +// CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 4 +// CHECK: [[THIRD:%.*]] = load float, float* [[T0]], align 4 +// CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 5 +// CHECK: [[FOURTH:%.*]] = load float, float* [[T0]], align 4 +// CHECK: call [[SWIFTCC]] void @take_struct_1(i32 [[FIRST]], i8 [[SECOND]], float [[THIRD]], float [[FOURTH]]) +// CHECK: ret void + +struct struct_indirect_1 { + int x; + ~struct_indirect_1(); +}; +TEST(struct_indirect_1) + +// CHECK-LABEL: define {{.*}} void @return_struct_indirect_1({{.*}} noalias sret + +// Should not be byval. +// CHECK-LABEL: define {{.*}} void @take_struct_indirect_1({{.*}}*{{( %.*)?}}) diff --git a/test/CodeGenCXX/arm.cpp b/test/CodeGenCXX/arm.cpp index 11ae6b24c26e..d0b896d182da 100644 --- a/test/CodeGenCXX/arm.cpp +++ b/test/CodeGenCXX/arm.cpp @@ -109,7 +109,7 @@ namespace test3 { void a() { // CHECK-LABEL: define void @_ZN5test31aEv() - // CHECK: call noalias i8* @_Znam(i32 48) + // CHECK: call i8* @_Znam(i32 48) // CHECK: store i32 4 // CHECK: store i32 10 A *x = new A[10]; @@ -122,7 +122,7 @@ namespace test3 { // CHECK: @llvm.uadd.with.overflow.i32(i32 {{.*}}, i32 8) // CHECK: [[OR:%.*]] = or i1 // CHECK: [[SZ:%.*]] = select i1 [[OR]] - // CHECK: call noalias i8* @_Znam(i32 [[SZ]]) + // CHECK: call i8* @_Znam(i32 [[SZ]]) // CHECK: store i32 4 // CHECK: store i32 [[N]] A *x = new A[n]; @@ -130,7 +130,7 @@ namespace test3 { void c() { // CHECK-LABEL: define void @_ZN5test31cEv() - // CHECK: call noalias i8* @_Znam(i32 808) + // CHECK: call i8* @_Znam(i32 808) // CHECK: store i32 4 // CHECK: store i32 200 A (*x)[20] = new A[10][20]; @@ -143,7 +143,7 @@ namespace test3 { // CHECK: [[NE:%.*]] = mul i32 [[N]], 20 // CHECK: @llvm.uadd.with.overflow.i32(i32 {{.*}}, i32 8) // CHECK: [[SZ:%.*]] = select - // CHECK: call noalias i8* @_Znam(i32 [[SZ]]) + // CHECK: call i8* @_Znam(i32 [[SZ]]) // CHECK: store i32 4 // CHECK: store i32 [[NE]] A (*x)[20] = new A[n][20]; @@ -182,7 +182,7 @@ namespace test4 { void a() { // CHECK-LABEL: define void @_ZN5test41aEv() - // CHECK: call noalias i8* @_Znam(i32 48) + // CHECK: call i8* @_Znam(i32 48) // CHECK: store i32 4 // CHECK: store i32 10 A *x = new A[10]; @@ -194,7 +194,7 @@ namespace test4 { // CHECK: @llvm.umul.with.overflow.i32(i32 [[N]], i32 4) // CHECK: @llvm.uadd.with.overflow.i32(i32 {{.*}}, i32 8) // CHECK: [[SZ:%.*]] = select - // CHECK: call noalias i8* @_Znam(i32 [[SZ]]) + // CHECK: call i8* @_Znam(i32 [[SZ]]) // CHECK: store i32 4 // CHECK: store i32 [[N]] A *x = new A[n]; @@ -202,7 +202,7 @@ namespace test4 { void c() { // CHECK-LABEL: define void @_ZN5test41cEv() - // CHECK: call noalias i8* @_Znam(i32 808) + // CHECK: call i8* @_Znam(i32 808) // CHECK: store i32 4 // CHECK: store i32 200 A (*x)[20] = new A[10][20]; @@ -215,7 +215,7 @@ namespace test4 { // CHECK: [[NE:%.*]] = mul i32 [[N]], 20 // CHECK: @llvm.uadd.with.overflow.i32(i32 {{.*}}, i32 8) // CHECK: [[SZ:%.*]] = select - // CHECK: call noalias i8* @_Znam(i32 [[SZ]]) + // CHECK: call i8* @_Znam(i32 [[SZ]]) // CHECK: store i32 4 // CHECK: store i32 [[NE]] A (*x)[20] = new A[n][20]; @@ -383,7 +383,7 @@ namespace test9 { // CHECK-NEXT: [[OVERFLOW:%.*]] = or i1 [[O0]], [[O1]] // CHECK-NEXT: [[T3:%.*]] = extractvalue { i32, i1 } [[T2]], 0 // CHECK-NEXT: [[T4:%.*]] = select i1 [[OVERFLOW]], i32 -1, i32 [[T3]] -// CHECK-NEXT: [[ALLOC:%.*]] = call noalias i8* @_Znam(i32 [[T4]]) +// CHECK-NEXT: [[ALLOC:%.*]] = call i8* @_Znam(i32 [[T4]]) // CHECK-NEXT: [[T0:%.*]] = bitcast i8* [[ALLOC]] to i32* // CHECK-NEXT: store i32 16, i32* [[T0]] // CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds i32, i32* [[T0]], i32 1 diff --git a/test/CodeGenCXX/atomicinit.cpp b/test/CodeGenCXX/atomicinit.cpp index 5e5174bd06e4..96f44d52f286 100644 --- a/test/CodeGenCXX/atomicinit.cpp +++ b/test/CodeGenCXX/atomicinit.cpp @@ -1,13 +1,13 @@ // RUN: %clang_cc1 %s -emit-llvm -O1 -o - -triple=i686-apple-darwin9 -std=c++11 | FileCheck %s -// CHECK-DAG: @PR22043 = global i32 0, align 4 +// CHECK-DAG: @PR22043 = local_unnamed_addr global i32 0, align 4 typedef _Atomic(int) AtomicInt; AtomicInt PR22043 = AtomicInt(); -// CHECK-DAG: @_ZN7PR180978constant1aE = global { i16, i8 } { i16 1, i8 6 }, align 4 -// CHECK-DAG: @_ZN7PR180978constant1bE = global { i16, i8 } { i16 2, i8 6 }, align 4 -// CHECK-DAG: @_ZN7PR180978constant1cE = global { i16, i8 } { i16 3, i8 6 }, align 4 -// CHECK-DAG: @_ZN7PR180978constant1yE = global { { i16, i8 }, i32 } { { i16, i8 } { i16 4, i8 6 }, i32 5 }, align 4 +// CHECK-DAG: @_ZN7PR180978constant1aE = local_unnamed_addr global { i16, i8 } { i16 1, i8 6 }, align 4 +// CHECK-DAG: @_ZN7PR180978constant1bE = local_unnamed_addr global { i16, i8 } { i16 2, i8 6 }, align 4 +// CHECK-DAG: @_ZN7PR180978constant1cE = local_unnamed_addr global { i16, i8 } { i16 3, i8 6 }, align 4 +// CHECK-DAG: @_ZN7PR180978constant1yE = local_unnamed_addr global { { i16, i8 }, i32 } { { i16, i8 } { i16 4, i8 6 }, i32 5 }, align 4 struct A { _Atomic(int) i; diff --git a/test/CodeGenCXX/attr-mode-vector-types-tmpl.cpp b/test/CodeGenCXX/attr-mode-vector-types-tmpl.cpp new file mode 100644 index 000000000000..6373cf0b2e0a --- /dev/null +++ b/test/CodeGenCXX/attr-mode-vector-types-tmpl.cpp @@ -0,0 +1,108 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu %s -emit-llvm -o - | FileCheck %s + +template <class T> +void CheckIntScalarTypes() { + // T will be substituted with 'int' and 'enum' types. + + typedef T __attribute__((mode(QI))) T1; + typedef T __attribute__((mode(HI))) T2; + typedef T __attribute__((mode(SI))) T3; + typedef T __attribute__((mode(DI))) T4; + + T1 a1; + T2 a2; + T3 a3; + T4 a4; +} + +template <class T> +void CheckIntVectorTypes() { + // T will be substituted with 'int'. + + typedef int __attribute__((mode(QI))) __attribute__((vector_size(8))) VT_11; + typedef T __attribute__((mode(V8QI))) VT_12; + typedef int __attribute__((mode(SI))) __attribute__((vector_size(16))) VT_21; + typedef T __attribute__((mode(V4SI))) VT_22; + typedef int __attribute__((mode(DI))) __attribute__((vector_size(64))) VT_31; + typedef T __attribute__((mode(V8DI))) VT_32; + + VT_11 v11; + VT_12 v12; + + VT_21 v21; + VT_22 v22; + + VT_31 v31; + VT_32 v32; +} + +template <class T> +void CheckFloatVectorTypes() { + // T will be substituted with 'float'. + + typedef float __attribute__((mode(SF))) __attribute__((vector_size(128))) VT_41; + typedef T __attribute__((mode(V32SF))) VT_42; + typedef float __attribute__((mode(DF))) __attribute__((vector_size(256))) VT_51; + typedef T __attribute__((mode(V32DF))) VT_52; + + VT_41 v41; + VT_42 v42; + + VT_51 v51; + VT_52 v52; +} + +template <class T> +void CheckInstantiationWithModedType() { + T x1; +} + +typedef enum { A1, B1 } EnumTy; +typedef int __attribute__((mode(DI))) Int64Ty1; +typedef enum __attribute__((mode(DI))) { A2 } Int64Ty2; +typedef int __attribute__((mode(V8HI))) IntVecTy1; + +void test() { + + // CHECK: define {{.*}} void @_Z19CheckIntScalarTypesIiEvv() + // CHECK: %{{.+}} = alloca i8 + // CHECK: %{{.+}} = alloca i16 + // CHECK: %{{.+}} = alloca i32 + // CHECK: %{{.+}} = alloca i64 + CheckIntScalarTypes<int>(); + + // CHECK: define {{.*}} void @_Z19CheckIntScalarTypesI6EnumTyEvv() + // CHECK: %{{.+}} = alloca i8 + // CHECK: %{{.+}} = alloca i16 + // CHECK: %{{.+}} = alloca i32 + // CHECK: %{{.+}} = alloca i64 + CheckIntScalarTypes<EnumTy>(); + + // CHECK: define {{.*}} void @_Z19CheckIntVectorTypesIiEvv() + // CHECK: %{{.+}} = alloca <8 x i8> + // CHECK: %{{.+}} = alloca <8 x i8> + // CHECK: %{{.+}} = alloca <4 x i32> + // CHECK: %{{.+}} = alloca <4 x i32> + // CHECK: %{{.+}} = alloca <8 x i64> + // CHECK: %{{.+}} = alloca <8 x i64> + CheckIntVectorTypes<int>(); + + // CHECK: define {{.*}} void @_Z21CheckFloatVectorTypesIfEvv() + // CHECK: %{{.+}} = alloca <32 x float> + // CHECK: %{{.+}} = alloca <32 x float> + // CHECK: %{{.+}} = alloca <32 x double> + // CHECK: %{{.+}} = alloca <32 x double> + CheckFloatVectorTypes<float>(); + + // CHECK: define {{.*}} void @_Z31CheckInstantiationWithModedTypeIlEvv() + // CHECK: [[X1:%.+]] = alloca i64 + CheckInstantiationWithModedType<Int64Ty1>(); + + // CHECK: define {{.*}} void @_Z31CheckInstantiationWithModedTypeI8Int64Ty2Evv() + // CHECK: [[X1]] = alloca i64 + CheckInstantiationWithModedType<Int64Ty2>(); + + // CHECK: define {{.*}} void @_Z31CheckInstantiationWithModedTypeIDv8_sEvv() + // CHECK: [[X1]] = alloca <8 x i16> + CheckInstantiationWithModedType<IntVecTy1>(); +} diff --git a/test/CodeGenCXX/attr-x86-interrupt.cpp b/test/CodeGenCXX/attr-x86-interrupt.cpp new file mode 100644 index 000000000000..500010469035 --- /dev/null +++ b/test/CodeGenCXX/attr-x86-interrupt.cpp @@ -0,0 +1,35 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu %s -emit-llvm -o - | FileCheck %s --check-prefix=X86_64_LINUX +// RUN: %clang_cc1 -triple i386-unknown-linux-gnu %s -emit-llvm -o - | FileCheck %s --check-prefix=X86_LINUX +// RUN: %clang_cc1 -triple x86_64-pc-win32 %s -emit-llvm -o - | FileCheck %s --check-prefix=X86_64_WIN +// RUN: %clang_cc1 -triple i386-pc-win32 %s -emit-llvm -o - | FileCheck %s --check-prefix=X86_WIN +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnux32 %s -emit-llvm -o - | FileCheck %s --check-prefix=X86_64_LINUX + +#ifdef __x86_64__ +typedef __UINT64_TYPE__ uword; +#else +typedef __UINT32_TYPE__ uword; +#endif + +__attribute__((interrupt)) void foo7(int *a, uword b) {} +namespace S { +__attribute__((interrupt)) void foo8(int *a) {} +} +struct St { +static void foo9(int *a) __attribute__((interrupt)) {} +}; +// X86_64_LINUX: @llvm.used = appending global [3 x i8*] [i8* bitcast (void (i32*, i64)* @{{.*}}foo7{{.*}} to i8*), i8* bitcast (void (i32*)* @{{.*}}foo8{{.*}} to i8*), i8* bitcast (void (i32*)* @{{.*}}foo9{{.*}} to i8*)], section "llvm.metadata" +// X86_64_LINUX: define x86_intrcc void @{{.*}}foo7{{.*}}(i32* %{{.+}}, i64 %{{.+}}) +// X86_64_LINUX: define x86_intrcc void @{{.*}}foo8{{.*}}(i32* %{{.+}}) +// X86_64_LINUX: define linkonce_odr x86_intrcc void @{{.*}}foo9{{.*}}(i32* %{{.+}}) +// X86_LINUX: @llvm.used = appending global [3 x i8*] [i8* bitcast (void (i32*, i32)* @{{.*}}foo7{{.*}} to i8*), i8* bitcast (void (i32*)* @{{.*}}foo8{{.*}} to i8*), i8* bitcast (void (i32*)* @{{.*}}foo9{{.*}} to i8*)], section "llvm.metadata" +// X86_LINUX: define x86_intrcc void @{{.*}}foo7{{.*}}(i32* %{{.+}}, i32 %{{.+}}) +// X86_LINUX: define x86_intrcc void @{{.*}}foo8{{.*}}(i32* %{{.+}}) +// X86_LINUX: define linkonce_odr x86_intrcc void @{{.*}}foo9{{.*}}(i32* %{{.+}}) +// X86_64_WIN: @llvm.used = appending global [3 x i8*] [i8* bitcast (void (i32*, i64)* @{{.*}}foo7{{.*}} to i8*), i8* bitcast (void (i32*)* @{{.*}}foo8{{.*}} to i8*), i8* bitcast (void (i32*)* @{{.*}}foo9{{.*}} to i8*)], section "llvm.metadata" +// X86_64_WIN: define x86_intrcc void @{{.*}}foo7{{.*}}(i32* %{{.+}}, i64 %{{.+}}) +// X86_64_WIN: define x86_intrcc void @{{.*}}foo8{{.*}}(i32* %{{.+}}) +// X86_64_WIN: define linkonce_odr x86_intrcc void @{{.*}}foo9{{.*}}(i32* %{{.+}}) +// X86_WIN: @llvm.used = appending global [3 x i8*] [i8* bitcast (void (i32*, i32)* @{{.*}}foo7{{.*}} to i8*), i8* bitcast (void (i32*)* @{{.*}}foo8{{.*}} to i8*), i8* bitcast (void (i32*)* @{{.*}}foo9{{.*}} to i8*)], section "llvm.metadata" +// X86_WIN: define x86_intrcc void @{{.*}}foo7{{.*}}(i32* %{{.+}}, i32 %{{.+}}) +// X86_WIN: define x86_intrcc void @{{.*}}foo8{{.*}}(i32* %{{.+}}) +// X86_WIN: define linkonce_odr x86_intrcc void @{{.*}}foo9{{.*}}(i32* %{{.+}}) diff --git a/test/CodeGenCXX/c-linkage.cpp b/test/CodeGenCXX/c-linkage.cpp index a70a22ef08c7..0f4c3277253f 100644 --- a/test/CodeGenCXX/c-linkage.cpp +++ b/test/CodeGenCXX/c-linkage.cpp @@ -15,10 +15,10 @@ extern "C" { extern "C" { static void test2_f() { } - // CHECK-LABEL: define internal {{.*}}void @_Z7test2_fv + // CHECK-LABEL: define internal {{.*}}void @_ZL7test2_fv static void test2_f(int x) { } - // CHECK-LABEL: define internal {{.*}}void @_Z7test2_fi + // CHECK-LABEL: define internal {{.*}}void @_ZL7test2_fi void test2_use() { test2_f(); test2_f(42); diff --git a/test/CodeGenCXX/cfi-blacklist.cpp b/test/CodeGenCXX/cfi-blacklist.cpp index 32ed05bcc520..af8a10601d29 100644 --- a/test/CodeGenCXX/cfi-blacklist.cpp +++ b/test/CodeGenCXX/cfi-blacklist.cpp @@ -1,9 +1,8 @@ -// RUN: echo "type:attr:uuid" > %t.txt -// RUN: %clang_cc1 -fms-extensions -fsanitize=cfi-vcall -fsanitize-blacklist=%t.txt -emit-llvm -o - %s | FileCheck --check-prefix=CHECK --check-prefix=NOUUID %s +// RUN: %clang_cc1 -triple %itanium_abi_triple -fvisibility hidden -fms-extensions -fsanitize=cfi-vcall -emit-llvm -o - %s | FileCheck --check-prefix=CHECK --check-prefix=NOBL %s // RUN: echo "type:std::*" > %t.txt -// RUN: %clang_cc1 -fms-extensions -fsanitize=cfi-vcall -fsanitize-blacklist=%t.txt -emit-llvm -o - %s | FileCheck --check-prefix=CHECK --check-prefix=NOSTD %s +// RUN: %clang_cc1 -triple %itanium_abi_triple -fvisibility hidden -fms-extensions -fsanitize=cfi-vcall -fsanitize-blacklist=%t.txt -emit-llvm -o - %s | FileCheck --check-prefix=CHECK --check-prefix=NOSTD %s -struct __declspec(uuid("00000000-0000-0000-0000-000000000000")) S1 { +struct S1 { virtual void f(); }; @@ -16,15 +15,15 @@ struct S2 { } // CHECK: define{{.*}}s1f -// NOSTD: llvm.bitset.test -// NOUUID-NOT: llvm.bitset.test +// NOBL: llvm.type.test +// NOSTD: llvm.type.test void s1f(S1 *s1) { s1->f(); } // CHECK: define{{.*}}s2f -// NOSTD-NOT: llvm.bitset.test -// NOUUID: llvm.bitset.test +// NOBL: llvm.type.test +// NOSTD-NOT: llvm.type.test void s2f(std::S2 *s2) { s2->f(); } diff --git a/test/CodeGenCXX/cfi-cast.cpp b/test/CodeGenCXX/cfi-cast.cpp index 0b96cb6506c0..54641b52332b 100644 --- a/test/CodeGenCXX/cfi-cast.cpp +++ b/test/CodeGenCXX/cfi-cast.cpp @@ -1,6 +1,6 @@ -// RUN: %clang_cc1 -triple x86_64-unknown-linux -fsanitize=cfi-derived-cast -fsanitize-trap=cfi-derived-cast -emit-llvm -o - %s | FileCheck -check-prefix=CHECK-DCAST %s -// RUN: %clang_cc1 -triple x86_64-unknown-linux -fsanitize=cfi-unrelated-cast -fsanitize-trap=cfi-unrelated-cast -emit-llvm -o - %s | FileCheck -check-prefix=CHECK-UCAST %s -// RUN: %clang_cc1 -triple x86_64-unknown-linux -fsanitize=cfi-unrelated-cast,cfi-cast-strict -fsanitize-trap=cfi-unrelated-cast,cfi-cast-strict -emit-llvm -o - %s | FileCheck -check-prefix=CHECK-UCAST-STRICT %s +// RUN: %clang_cc1 -triple x86_64-unknown-linux -fvisibility hidden -std=c++11 -fsanitize=cfi-derived-cast -fsanitize-trap=cfi-derived-cast -emit-llvm -o - %s | FileCheck -check-prefix=CHECK-DCAST %s +// RUN: %clang_cc1 -triple x86_64-unknown-linux -fvisibility hidden -std=c++11 -fsanitize=cfi-unrelated-cast -fsanitize-trap=cfi-unrelated-cast -emit-llvm -o - %s | FileCheck -check-prefix=CHECK-UCAST %s +// RUN: %clang_cc1 -triple x86_64-unknown-linux -fvisibility hidden -std=c++11 -fsanitize=cfi-unrelated-cast,cfi-cast-strict -fsanitize-trap=cfi-unrelated-cast,cfi-cast-strict -emit-llvm -o - %s | FileCheck -check-prefix=CHECK-UCAST-STRICT %s // In this test the main thing we are searching for is something like // 'metadata !"1B"' where "1B" is the mangled name of the class we are @@ -8,6 +8,7 @@ struct A { virtual void f(); + int i() const; }; struct B : A { @@ -16,9 +17,9 @@ struct B : A { struct C : A {}; -// CHECK-DCAST-LABEL: define void @_Z3abpP1A +// CHECK-DCAST-LABEL: define hidden void @_Z3abpP1A void abp(A *a) { - // CHECK-DCAST: [[P:%[^ ]*]] = call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"_ZTS1B") + // CHECK-DCAST: [[P:%[^ ]*]] = call i1 @llvm.type.test(i8* {{%[^ ]*}}, metadata !"_ZTS1B") // CHECK-DCAST-NEXT: br i1 [[P]], label %[[CONTBB:[^ ]*]], label %[[TRAPBB:[^ ,]*]] // CHECK-DCAST: [[TRAPBB]] @@ -27,12 +28,12 @@ void abp(A *a) { // CHECK-DCAST: [[CONTBB]] // CHECK-DCAST: ret - static_cast<B*>(a); + (void)static_cast<B*>(a); } -// CHECK-DCAST-LABEL: define void @_Z3abrR1A +// CHECK-DCAST-LABEL: define hidden void @_Z3abrR1A void abr(A &a) { - // CHECK-DCAST: [[P:%[^ ]*]] = call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"_ZTS1B") + // CHECK-DCAST: [[P:%[^ ]*]] = call i1 @llvm.type.test(i8* {{%[^ ]*}}, metadata !"_ZTS1B") // CHECK-DCAST-NEXT: br i1 [[P]], label %[[CONTBB:[^ ]*]], label %[[TRAPBB:[^ ,]*]] // CHECK-DCAST: [[TRAPBB]] @@ -41,12 +42,12 @@ void abr(A &a) { // CHECK-DCAST: [[CONTBB]] // CHECK-DCAST: ret - static_cast<B&>(a); + (void)static_cast<B&>(a); } -// CHECK-DCAST-LABEL: define void @_Z4abrrO1A +// CHECK-DCAST-LABEL: define hidden void @_Z4abrrO1A void abrr(A &&a) { - // CHECK-DCAST: [[P:%[^ ]*]] = call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"_ZTS1B") + // CHECK-DCAST: [[P:%[^ ]*]] = call i1 @llvm.type.test(i8* {{%[^ ]*}}, metadata !"_ZTS1B") // CHECK-DCAST-NEXT: br i1 [[P]], label %[[CONTBB:[^ ]*]], label %[[TRAPBB:[^ ,]*]] // CHECK-DCAST: [[TRAPBB]] @@ -55,12 +56,12 @@ void abrr(A &&a) { // CHECK-DCAST: [[CONTBB]] // CHECK-DCAST: ret - static_cast<B&&>(a); + (void)static_cast<B&&>(a); } -// CHECK-UCAST-LABEL: define void @_Z3vbpPv +// CHECK-UCAST-LABEL: define hidden void @_Z3vbpPv void vbp(void *p) { - // CHECK-UCAST: [[P:%[^ ]*]] = call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"_ZTS1B") + // CHECK-UCAST: [[P:%[^ ]*]] = call i1 @llvm.type.test(i8* {{%[^ ]*}}, metadata !"_ZTS1B") // CHECK-UCAST-NEXT: br i1 [[P]], label %[[CONTBB:[^ ]*]], label %[[TRAPBB:[^ ,]*]] // CHECK-UCAST: [[TRAPBB]] @@ -69,12 +70,12 @@ void vbp(void *p) { // CHECK-UCAST: [[CONTBB]] // CHECK-UCAST: ret - static_cast<B*>(p); + (void)static_cast<B*>(p); } -// CHECK-UCAST-LABEL: define void @_Z3vbrRc +// CHECK-UCAST-LABEL: define hidden void @_Z3vbrRc void vbr(char &r) { - // CHECK-UCAST: [[P:%[^ ]*]] = call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"_ZTS1B") + // CHECK-UCAST: [[P:%[^ ]*]] = call i1 @llvm.type.test(i8* {{%[^ ]*}}, metadata !"_ZTS1B") // CHECK-UCAST-NEXT: br i1 [[P]], label %[[CONTBB:[^ ]*]], label %[[TRAPBB:[^ ,]*]] // CHECK-UCAST: [[TRAPBB]] @@ -83,12 +84,12 @@ void vbr(char &r) { // CHECK-UCAST: [[CONTBB]] // CHECK-UCAST: ret - reinterpret_cast<B&>(r); + (void)reinterpret_cast<B&>(r); } -// CHECK-UCAST-LABEL: define void @_Z4vbrrOc +// CHECK-UCAST-LABEL: define hidden void @_Z4vbrrOc void vbrr(char &&r) { - // CHECK-UCAST: [[P:%[^ ]*]] = call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"_ZTS1B") + // CHECK-UCAST: [[P:%[^ ]*]] = call i1 @llvm.type.test(i8* {{%[^ ]*}}, metadata !"_ZTS1B") // CHECK-UCAST-NEXT: br i1 [[P]], label %[[CONTBB:[^ ]*]], label %[[TRAPBB:[^ ,]*]] // CHECK-UCAST: [[TRAPBB]] @@ -97,29 +98,37 @@ void vbrr(char &&r) { // CHECK-UCAST: [[CONTBB]] // CHECK-UCAST: ret - reinterpret_cast<B&&>(r); + (void)reinterpret_cast<B&&>(r); } -// CHECK-UCAST-LABEL: define void @_Z3vcpPv -// CHECK-UCAST-STRICT-LABEL: define void @_Z3vcpPv +// CHECK-UCAST-LABEL: define hidden void @_Z3vcpPv +// CHECK-UCAST-STRICT-LABEL: define hidden void @_Z3vcpPv void vcp(void *p) { - // CHECK-UCAST: [[P:%[^ ]*]] = call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"_ZTS1A") - // CHECK-UCAST-STRICT: [[P:%[^ ]*]] = call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"_ZTS1C") - static_cast<C*>(p); + // CHECK-UCAST: call i1 @llvm.type.test(i8* {{%[^ ]*}}, metadata !"_ZTS1A") + // CHECK-UCAST-STRICT: call i1 @llvm.type.test(i8* {{%[^ ]*}}, metadata !"_ZTS1C") + (void)static_cast<C*>(p); } -// CHECK-UCAST-LABEL: define void @_Z3bcpP1B -// CHECK-UCAST-STRICT-LABEL: define void @_Z3bcpP1B +// CHECK-UCAST-LABEL: define hidden void @_Z3bcpP1B +// CHECK-UCAST-STRICT-LABEL: define hidden void @_Z3bcpP1B void bcp(B *p) { - // CHECK-UCAST: [[P:%[^ ]*]] = call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"_ZTS1A") - // CHECK-UCAST-STRICT: [[P:%[^ ]*]] = call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"_ZTS1C") - (C *)p; + // CHECK-UCAST: call i1 @llvm.type.test(i8* {{%[^ ]*}}, metadata !"_ZTS1A") + // CHECK-UCAST-STRICT: call i1 @llvm.type.test(i8* {{%[^ ]*}}, metadata !"_ZTS1C") + (void)(C *)p; } -// CHECK-UCAST-LABEL: define void @_Z8bcp_callP1B -// CHECK-UCAST-STRICT-LABEL: define void @_Z8bcp_callP1B +// CHECK-UCAST-LABEL: define hidden void @_Z8bcp_callP1B +// CHECK-UCAST-STRICT-LABEL: define hidden void @_Z8bcp_callP1B void bcp_call(B *p) { - // CHECK-UCAST: [[P:%[^ ]*]] = call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"_ZTS1A") - // CHECK-UCAST-STRICT: [[P:%[^ ]*]] = call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"_ZTS1C") + // CHECK-UCAST: call i1 @llvm.type.test(i8* {{%[^ ]*}}, metadata !"_ZTS1A") + // CHECK-UCAST-STRICT: call i1 @llvm.type.test(i8* {{%[^ ]*}}, metadata !"_ZTS1C") ((C *)p)->f(); } + +// CHECK-UCAST-LABEL: define hidden i32 @_Z6a_callP1A +// CHECK-UCAST-STRICT-LABEL: define hidden i32 @_Z6a_callP1A +int a_call(A *a) { + // CHECK-UCAST-NOT: @llvm.type.test + // CHECK-UCAST-STRICT-NOT: @llvm.type.test + return a->i(); +} diff --git a/test/CodeGenCXX/cfi-cross-dso.cpp b/test/CodeGenCXX/cfi-cross-dso.cpp index fbe6fc83a5c3..d67927d4d2ed 100644 --- a/test/CodeGenCXX/cfi-cross-dso.cpp +++ b/test/CodeGenCXX/cfi-cross-dso.cpp @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -triple x86_64-unknown-linux -fsanitize=cfi-vcall -fsanitize-cfi-cross-dso -emit-llvm -o - %s | FileCheck --check-prefix=CHECK --check-prefix=ITANIUM %s -// RUN: %clang_cc1 -triple x86_64-pc-windows-msvc -fsanitize=cfi-vcall -fsanitize-cfi-cross-dso -emit-llvm -o - %s | FileCheck --check-prefix=CHECK --check-prefix=MS %s +// RUN: %clang_cc1 -flto -triple x86_64-unknown-linux -fsanitize=cfi-vcall -fsanitize-cfi-cross-dso -emit-llvm -o - %s | FileCheck --check-prefix=CHECK --check-prefix=ITANIUM %s +// RUN: %clang_cc1 -flto -triple x86_64-pc-windows-msvc -fsanitize=cfi-vcall -fsanitize-cfi-cross-dso -emit-llvm -o - %s | FileCheck --check-prefix=CHECK --check-prefix=MS %s struct A { A(); @@ -30,12 +30,12 @@ void g() { // CHECK: %[[VT:.*]] = load void (%struct.A*)**, void (%struct.A*)*** // CHECK: %[[VT2:.*]] = bitcast {{.*}}%[[VT]] to i8*, !nosanitize -// ITANIUM: %[[TEST:.*]] = call i1 @llvm.bitset.test(i8* %[[VT2]], metadata !"_ZTS1A"), !nosanitize -// MS: %[[TEST:.*]] = call i1 @llvm.bitset.test(i8* %[[VT2]], metadata !"?AUA@@"), !nosanitize +// ITANIUM: %[[TEST:.*]] = call i1 @llvm.type.test(i8* %[[VT2]], metadata !"_ZTS1A"), !nosanitize +// MS: %[[TEST:.*]] = call i1 @llvm.type.test(i8* %[[VT2]], metadata !"?AUA@@"), !nosanitize // CHECK: br i1 %[[TEST]], label %[[CONT:.*]], label %[[SLOW:.*]], {{.*}} !nosanitize // CHECK: [[SLOW]] -// ITANIUM: call void @__cfi_slowpath(i64 7004155349499253778, i8* %[[VT2]]) {{.*}} !nosanitize -// MS: call void @__cfi_slowpath(i64 -8005289897957287421, i8* %[[VT2]]) {{.*}} !nosanitize +// ITANIUM: call void @__cfi_slowpath_diag(i64 7004155349499253778, i8* %[[VT2]], {{.*}}) {{.*}} !nosanitize +// MS: call void @__cfi_slowpath_diag(i64 -8005289897957287421, i8* %[[VT2]], {{.*}}) {{.*}} !nosanitize // CHECK: br label %[[CONT]], !nosanitize // CHECK: [[CONT]] // CHECK: call void %{{.*}}(%struct.A* %{{.*}}) diff --git a/test/CodeGenCXX/cfi-icall.cpp b/test/CodeGenCXX/cfi-icall.cpp index eceb92a4421c..c3c6ed309cc6 100644 --- a/test/CodeGenCXX/cfi-icall.cpp +++ b/test/CodeGenCXX/cfi-icall.cpp @@ -15,9 +15,12 @@ void f(S *s) { void g() { void (*fp)(S *) = f; - // CHECK: call i1 @llvm.bitset.test(i8* {{.*}}, metadata ![[VOIDS:[0-9]+]]) + // CHECK: call i1 @llvm.type.test(i8* {{.*}}, metadata [[VOIDS:![0-9]+]]) fp(0); } -// ITANIUM: !{![[VOIDS]], void (%"struct.(anonymous namespace)::S"*)* @_ZN12_GLOBAL__N_11fEPNS_1SE, i64 0} -// MS: !{![[VOIDS]], void (%"struct.(anonymous namespace)::S"*)* @"\01?f@?A@@YAXPEAUS@?A@@@Z", i64 0} +// ITANIUM: define internal void @_ZN12_GLOBAL__N_11fEPNS_1SE({{.*}} !type [[TS:![0-9]+]] +// MS: define internal void @"\01?f@?A@@YAXPEAUS@?A@@@Z"({{.*}} !type [[TS:![0-9]+]] + +// CHECK: [[VOIDS]] = distinct !{} +// CHECK: [[TS]] = !{i64 0, [[VOIDS]]} diff --git a/test/CodeGenCXX/cfi-ms-rtti.cpp b/test/CodeGenCXX/cfi-ms-rtti.cpp index b6e9175c865c..fbebad4b1b8d 100644 --- a/test/CodeGenCXX/cfi-ms-rtti.cpp +++ b/test/CodeGenCXX/cfi-ms-rtti.cpp @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -emit-llvm -o - -triple=x86_64-pc-win32 %s -fsanitize=cfi-vcall | FileCheck --check-prefix=RTTI %s -// RUN: %clang_cc1 -emit-llvm -o - -triple=x86_64-pc-win32 %s -fsanitize=cfi-vcall -fno-rtti-data | FileCheck --check-prefix=NO-RTTI %s +// RUN: %clang_cc1 -flto -emit-llvm -o - -triple=x86_64-pc-win32 %s -fsanitize=cfi-vcall | FileCheck --check-prefix=RTTI %s +// RUN: %clang_cc1 -flto -emit-llvm -o - -triple=x86_64-pc-win32 %s -fsanitize=cfi-vcall -fno-rtti-data | FileCheck --check-prefix=NO-RTTI %s struct A { A(); @@ -8,5 +8,5 @@ struct A { A::A() {} -// RTTI: !{!"?AUA@@", [2 x i8*]* {{.*}}, i64 8} -// NO-RTTI: !{!"?AUA@@", [1 x i8*]* {{.*}}, i64 0} +// RTTI: !{i64 8, !"?AUA@@"} +// NO-RTTI: !{i64 0, !"?AUA@@"} diff --git a/test/CodeGenCXX/cfi-nvcall.cpp b/test/CodeGenCXX/cfi-nvcall.cpp index be4d8448a2e0..e968f05600c2 100644 --- a/test/CodeGenCXX/cfi-nvcall.cpp +++ b/test/CodeGenCXX/cfi-nvcall.cpp @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -triple x86_64-unknown-linux -fsanitize=cfi-nvcall -emit-llvm -o - %s | FileCheck %s -// RUN: %clang_cc1 -triple x86_64-unknown-linux -fsanitize=cfi-nvcall,cfi-cast-strict -emit-llvm -o - %s | FileCheck --check-prefix=CHECK-STRICT %s +// RUN: %clang_cc1 -triple x86_64-unknown-linux -fvisibility hidden -fsanitize=cfi-nvcall -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-unknown-linux -fvisibility hidden -fsanitize=cfi-nvcall,cfi-cast-strict -emit-llvm -o - %s | FileCheck --check-prefix=CHECK-STRICT %s struct A { virtual void f(); @@ -17,8 +17,8 @@ struct C : A { // CHECK-LABEL: @bg // CHECK-STRICT-LABEL: @bg extern "C" void bg(B *b) { - // CHECK: call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"_ZTS1B") - // CHECK-STRICT: call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"_ZTS1B") + // CHECK: call i1 @llvm.type.test(i8* {{%[^ ]*}}, metadata !"_ZTS1B") + // CHECK-STRICT: call i1 @llvm.type.test(i8* {{%[^ ]*}}, metadata !"_ZTS1B") b->g(); } @@ -29,7 +29,7 @@ extern "C" void cg(C *c) { // In this case C's layout is the same as its base class, so we allow // c to be of type A in non-strict mode. - // CHECK: call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"_ZTS1A") - // CHECK-STRICT: call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"_ZTS1C") + // CHECK: call i1 @llvm.type.test(i8* {{%[^ ]*}}, metadata !"_ZTS1A") + // CHECK-STRICT: call i1 @llvm.type.test(i8* {{%[^ ]*}}, metadata !"_ZTS1C") c->g(); } diff --git a/test/CodeGenCXX/cfi-speculative-vtable.cpp b/test/CodeGenCXX/cfi-speculative-vtable.cpp new file mode 100644 index 000000000000..490190c4afd7 --- /dev/null +++ b/test/CodeGenCXX/cfi-speculative-vtable.cpp @@ -0,0 +1,14 @@ +// Test that we don't emit a bit set entry for a speculative (available_externally) vtable. +// This does not happen in the Microsoft ABI. +// RUN: %clang_cc1 -triple x86_64-unknown-linux -O1 -fsanitize=cfi-vcall -fsanitize-trap=cfi-vcall -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-unknown-linux -O1 -fsanitize=cfi-vcall -fsanitize-trap=cfi-vcall -fsanitize-cfi-cross-dso -emit-llvm -o - %s | FileCheck %s + +class A { + public: + virtual ~A(); +}; + +A a; + +// CHECK: @_ZTV1A ={{.*}} available_externally +// CHECK-NOT: !{{.*}} = !{!{{.*}}, [4 x i8*]* @_ZTV1A, i64 16} diff --git a/test/CodeGenCXX/cfi-stats.cpp b/test/CodeGenCXX/cfi-stats.cpp new file mode 100644 index 000000000000..6d0dd5b27091 --- /dev/null +++ b/test/CodeGenCXX/cfi-stats.cpp @@ -0,0 +1,51 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-linux -fvisibility hidden -fsanitize=cfi-vcall,cfi-nvcall,cfi-derived-cast,cfi-unrelated-cast,cfi-icall -fsanitize-stats -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-unknown-linux -fvisibility hidden -fsanitize=cfi-vcall,cfi-nvcall,cfi-derived-cast,cfi-unrelated-cast,cfi-icall -fsanitize-trap=cfi-vcall -fwhole-program-vtables -fsanitize-stats -emit-llvm -o - %s | FileCheck %s + +// CHECK: [[STATS:@[^ ]*]] = internal global { i8*, i32, [5 x [2 x i8*]] } { i8* null, i32 5, [5 x [2 x i8*]] +// CHECK: {{\[\[}}2 x i8*] zeroinitializer, +// CHECK: [2 x i8*] [i8* null, i8* inttoptr (i64 2305843009213693952 to i8*)], +// CHECK: [2 x i8*] [i8* null, i8* inttoptr (i64 4611686018427387904 to i8*)], +// CHECK: [2 x i8*] [i8* null, i8* inttoptr (i64 6917529027641081856 to i8*)], +// CHECK: [2 x i8*] [i8* null, i8* inttoptr (i64 -9223372036854775808 to i8*)]] } + +// CHECK: @llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 0, void ()* [[CTOR:@[^ ]*]], i8* null }] + +struct A { + virtual void vf(); + void nvf(); +}; +struct B : A {}; + +// CHECK: @vcall +extern "C" void vcall(A *a) { + // CHECK: call void @__sanitizer_stat_report({{.*}}[[STATS]]{{.*}}i64 0, i32 2, i64 0 + a->vf(); +} + +// CHECK: @nvcall +extern "C" void nvcall(A *a) { + // CHECK: call void @__sanitizer_stat_report({{.*}}[[STATS]]{{.*}}i64 0, i32 2, i64 1 + a->nvf(); +} + +// CHECK: @dcast +extern "C" void dcast(A *a) { + // CHECK: call void @__sanitizer_stat_report({{.*}}[[STATS]]{{.*}}i64 0, i32 2, i64 2 + static_cast<B *>(a); +} + +// CHECK: @ucast +extern "C" void ucast(void *a) { + // CHECK: call void @__sanitizer_stat_report({{.*}}[[STATS]]{{.*}}i64 0, i32 2, i64 3 + reinterpret_cast<A *>(a); +} + +// CHECK: @icall +extern "C" void icall(void (*p)()) { + // CHECK: call void @__sanitizer_stat_report({{.*}}[[STATS]]{{.*}}i64 0, i32 2, i64 4 + p(); +} + +// CHECK: define internal void [[CTOR]]() +// CHECK-NEXT: call void @__sanitizer_stat_init(i8* bitcast ({ i8*, i32, [5 x [2 x i8*]] }* [[STATS]] to i8*)) +// CHECK-NEXT: ret void diff --git a/test/CodeGenCXX/cfi-vcall.cpp b/test/CodeGenCXX/cfi-vcall.cpp deleted file mode 100644 index daa0531e85d6..000000000000 --- a/test/CodeGenCXX/cfi-vcall.cpp +++ /dev/null @@ -1,188 +0,0 @@ -// RUN: %clang_cc1 -triple x86_64-unknown-linux -fsanitize=cfi-vcall -fsanitize-trap=cfi-vcall -emit-llvm -o - %s | FileCheck --check-prefix=CHECK --check-prefix=ITANIUM --check-prefix=NDIAG %s -// RUN: %clang_cc1 -triple x86_64-unknown-linux -fsanitize=cfi-vcall -emit-llvm -o - %s | FileCheck --check-prefix=CHECK --check-prefix=ITANIUM --check-prefix=DIAG --check-prefix=DIAG-ABORT %s -// RUN: %clang_cc1 -triple x86_64-unknown-linux -fsanitize=cfi-vcall -fsanitize-recover=cfi-vcall -emit-llvm -o - %s | FileCheck --check-prefix=CHECK --check-prefix=ITANIUM --check-prefix=DIAG --check-prefix=DIAG-RECOVER %s -// RUN: %clang_cc1 -triple x86_64-pc-windows-msvc -fsanitize=cfi-vcall -fsanitize-trap=cfi-vcall -emit-llvm -o - %s | FileCheck --check-prefix=CHECK --check-prefix=MS --check-prefix=NDIAG %s - -// MS: @[[VTA:[0-9]*]] {{.*}} comdat($"\01??_7A@@6B@") -// MS: @[[VTB:[0-9]*]] {{.*}} comdat($"\01??_7B@@6B0@@") -// MS: @[[VTAinB:[0-9]*]] {{.*}} comdat($"\01??_7B@@6BA@@@") -// MS: @[[VTAinC:[0-9]*]] {{.*}} comdat($"\01??_7C@@6B@") -// MS: @[[VTBinD:[0-9]*]] {{.*}} comdat($"\01??_7D@?A@@6BB@@@") -// MS: @[[VTAinBinD:[0-9]*]] {{.*}} comdat($"\01??_7D@?A@@6BA@@@") -// MS: @[[VTFA:[0-9]*]] {{.*}} comdat($"\01??_7FA@?1??foo@@YAXXZ@6B@") - -struct A { - A(); - virtual void f(); -}; - -struct B : virtual A { - B(); - virtual void g(); - virtual void h(); -}; - -struct C : virtual A { - C(); -}; - -namespace { - -struct D : B, C { - D(); - virtual void f(); - virtual void h(); -}; - -} - -A::A() {} -B::B() {} -C::C() {} -D::D() {} - -void A::f() { -} - -void B::g() { -} - -void D::f() { -} - -void D::h() { -} - -// DIAG: @[[SRC:.*]] = private unnamed_addr constant [{{.*}} x i8] c"{{.*}}cfi-vcall.cpp\00", align 1 -// DIAG: @[[TYPE:.*]] = private unnamed_addr constant { i16, i16, [4 x i8] } { i16 -1, i16 0, [4 x i8] c"'A'\00" } -// DIAG: @[[BADTYPESTATIC:.*]] = private unnamed_addr global { { [{{.*}} x i8]*, i32, i32 }, { i16, i16, [4 x i8] }*, i8 } { { [{{.*}} x i8]*, i32, i32 } { [{{.*}} x i8]* @[[SRC]], i32 [[@LINE+21]], i32 3 }, { i16, i16, [4 x i8] }* @[[TYPE]], i8 0 } - -// ITANIUM: define void @_Z2afP1A -// MS: define void @"\01?af@@YAXPEAUA@@@Z" -void af(A *a) { - // ITANIUM: [[P:%[^ ]*]] = call i1 @llvm.bitset.test(i8* [[VT:%[^ ]*]], metadata !"_ZTS1A") - // MS: [[P:%[^ ]*]] = call i1 @llvm.bitset.test(i8* [[VT:%[^ ]*]], metadata !"?AUA@@") - // CHECK-NEXT: br i1 [[P]], label %[[CONTBB:[^ ,]*]], label %[[TRAPBB:[^ ,]*]] - // CHECK-NEXT: {{^$}} - - // CHECK: [[TRAPBB]] - // NDIAG-NEXT: call void @llvm.trap() - // NDIAG-NEXT: unreachable - // DIAG-NEXT: [[VTINT:%[^ ]*]] = ptrtoint i8* [[VT]] to i64 - // DIAG-ABORT-NEXT: call void @__ubsan_handle_cfi_bad_type_abort(i8* bitcast ({{.*}} @[[BADTYPESTATIC]] to i8*), i64 [[VTINT]]) - // DIAG-ABORT-NEXT: unreachable - // DIAG-RECOVER-NEXT: call void @__ubsan_handle_cfi_bad_type(i8* bitcast ({{.*}} @[[BADTYPESTATIC]] to i8*), i64 [[VTINT]]) - // DIAG-RECOVER-NEXT: br label %[[CONTBB]] - - // CHECK: [[CONTBB]] - // CHECK: call void % - a->f(); -} - -// ITANIUM: define internal void @_Z3df1PN12_GLOBAL__N_11DE -// MS: define internal void @"\01?df1@@YAXPEAUD@?A@@@Z" -void df1(D *d) { - // ITANIUM: {{%[^ ]*}} = call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata ![[DTYPE:[0-9]+]]) - // MS: {{%[^ ]*}} = call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"?AUA@@") - d->f(); -} - -// ITANIUM: define internal void @_Z3dg1PN12_GLOBAL__N_11DE -// MS: define internal void @"\01?dg1@@YAXPEAUD@?A@@@Z" -void dg1(D *d) { - // ITANIUM: {{%[^ ]*}} = call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"_ZTS1B") - // MS: {{%[^ ]*}} = call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"?AUB@@") - d->g(); -} - -// ITANIUM: define internal void @_Z3dh1PN12_GLOBAL__N_11DE -// MS: define internal void @"\01?dh1@@YAXPEAUD@?A@@@Z" -void dh1(D *d) { - // ITANIUM: {{%[^ ]*}} = call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata ![[DTYPE]]) - // MS: {{%[^ ]*}} = call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata ![[DTYPE:[0-9]+]]) - d->h(); -} - -// ITANIUM: define internal void @_Z3df2PN12_GLOBAL__N_11DE -// MS: define internal void @"\01?df2@@YAXPEAUD@?A@@@Z" -__attribute__((no_sanitize("cfi"))) -void df2(D *d) { - // CHECK-NOT: call i1 @llvm.bitset.test - d->f(); -} - -// ITANIUM: define internal void @_Z3df3PN12_GLOBAL__N_11DE -// MS: define internal void @"\01?df3@@YAXPEAUD@?A@@@Z" -__attribute__((no_sanitize("address"))) __attribute__((no_sanitize("cfi-vcall"))) -void df3(D *d) { - // CHECK-NOT: call i1 @llvm.bitset.test - d->f(); -} - -D d; - -void foo() { - df1(&d); - dg1(&d); - dh1(&d); - df2(&d); - df3(&d); - - struct FA : A { - void f() {} - } fa; - af(&fa); -} - -namespace test2 { - -struct A { - virtual void m_fn1(); -}; -struct B { - virtual void m_fn2(); -}; -struct C : B, A {}; -struct D : C { - void m_fn1(); -}; - -// ITANIUM: define void @_ZN5test21fEPNS_1DE -// MS: define void @"\01?f@test2@@YAXPEAUD@1@@Z" -void f(D *d) { - // ITANIUM: {{%[^ ]*}} = call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"_ZTSN5test21DE") - // MS: {{%[^ ]*}} = call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"?AUA@test2@@") - d->m_fn1(); -} - -} - -// Check for the expected number of elements (9 or 15 respectively). -// MS: !llvm.bitsets = !{[[X:[^,]*(,[^,]*){8}]]} -// ITANIUM: !llvm.bitsets = !{[[X:[^,]*(,[^,]*){14}]]} - -// ITANIUM-DAG: !{!"_ZTS1A", [3 x i8*]* @_ZTV1A, i64 16} -// ITANIUM-DAG: !{!"_ZTS1A", [7 x i8*]* @_ZTCN12_GLOBAL__N_11DE0_1B, i64 32} -// ITANIUM-DAG: !{!"_ZTS1B", [7 x i8*]* @_ZTCN12_GLOBAL__N_11DE0_1B, i64 32} -// ITANIUM-DAG: !{!"_ZTS1A", [9 x i8*]* @_ZTCN12_GLOBAL__N_11DE8_1C, i64 64} -// ITANIUM-DAG: !{!"_ZTS1C", [9 x i8*]* @_ZTCN12_GLOBAL__N_11DE8_1C, i64 32} -// ITANIUM-DAG: !{!"_ZTS1A", [12 x i8*]* @_ZTVN12_GLOBAL__N_11DE, i64 32} -// ITANIUM-DAG: !{!"_ZTS1B", [12 x i8*]* @_ZTVN12_GLOBAL__N_11DE, i64 32} -// ITANIUM-DAG: !{!"_ZTS1C", [12 x i8*]* @_ZTVN12_GLOBAL__N_11DE, i64 88} -// ITANIUM-DAG: !{![[DTYPE]], [12 x i8*]* @_ZTVN12_GLOBAL__N_11DE, i64 32} -// ITANIUM-DAG: !{!"_ZTS1A", [7 x i8*]* @_ZTV1B, i64 32} -// ITANIUM-DAG: !{!"_ZTS1B", [7 x i8*]* @_ZTV1B, i64 32} -// ITANIUM-DAG: !{!"_ZTS1A", [5 x i8*]* @_ZTV1C, i64 32} -// ITANIUM-DAG: !{!"_ZTS1C", [5 x i8*]* @_ZTV1C, i64 32} -// ITANIUM-DAG: !{!"_ZTS1A", [3 x i8*]* @_ZTVZ3foovE2FA, i64 16} -// ITANIUM-DAG: !{!{{[0-9]+}}, [3 x i8*]* @_ZTVZ3foovE2FA, i64 16} - -// MS-DAG: !{!"?AUA@@", [2 x i8*]* @[[VTA]], i64 8} -// MS-DAG: !{!"?AUB@@", [3 x i8*]* @[[VTB]], i64 8} -// MS-DAG: !{!"?AUA@@", [2 x i8*]* @[[VTAinB]], i64 8} -// MS-DAG: !{!"?AUA@@", [2 x i8*]* @[[VTAinC]], i64 8} -// MS-DAG: !{!"?AUB@@", [3 x i8*]* @[[VTBinD]], i64 8} -// MS-DAG: !{![[DTYPE]], [3 x i8*]* @[[VTBinD]], i64 8} -// MS-DAG: !{!"?AUA@@", [2 x i8*]* @[[VTAinBinD]], i64 8} -// MS-DAG: !{!"?AUA@@", [2 x i8*]* @[[VTFA]], i64 8} -// MS-DAG: !{!{{[0-9]+}}, [2 x i8*]* @[[VTFA]], i64 8} diff --git a/test/CodeGenCXX/const-init-cxx11.cpp b/test/CodeGenCXX/const-init-cxx11.cpp index 99be265e2126..0c2193fb07f2 100644 --- a/test/CodeGenCXX/const-init-cxx11.cpp +++ b/test/CodeGenCXX/const-init-cxx11.cpp @@ -343,13 +343,13 @@ namespace VirtualMembers { constexpr E() : B(3), c{'b','y','e'} {} char c[3]; }; - // CHECK: @_ZN14VirtualMembers1eE = global { i8**, double, i32, i8**, double, [5 x i8], i16, i8**, double, [5 x i8], [3 x i8] } { i8** getelementptr inbounds ([11 x i8*], [11 x i8*]* @_ZTVN14VirtualMembers1EE, i64 0, i64 2), double 1.000000e+00, i32 64, i8** getelementptr inbounds ([11 x i8*], [11 x i8*]* @_ZTVN14VirtualMembers1EE, i64 0, i64 5), double 2.000000e+00, [5 x i8] c"hello", i16 5, i8** getelementptr inbounds ([11 x i8*], [11 x i8*]* @_ZTVN14VirtualMembers1EE, i64 0, i64 9), double 3.000000e+00, [5 x i8] c"world", [3 x i8] c"bye" } + // CHECK: @_ZN14VirtualMembers1eE = global { i8**, double, i32, i8**, double, [5 x i8], i16, i8**, double, [5 x i8], [3 x i8] } { i8** getelementptr inbounds ([11 x i8*], [11 x i8*]* @_ZTVN14VirtualMembers1EE, i32 0, i32 2), double 1.000000e+00, i32 64, i8** getelementptr inbounds ([11 x i8*], [11 x i8*]* @_ZTVN14VirtualMembers1EE, i32 0, i32 5), double 2.000000e+00, [5 x i8] c"hello", i16 5, i8** getelementptr inbounds ([11 x i8*], [11 x i8*]* @_ZTVN14VirtualMembers1EE, i32 0, i32 9), double 3.000000e+00, [5 x i8] c"world", [3 x i8] c"bye" } E e; struct nsMemoryImpl { virtual void f(); }; - // CHECK: @_ZN14VirtualMembersL13sGlobalMemoryE = internal global { i8** } { i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTVN14VirtualMembers12nsMemoryImplE, i64 0, i64 2) } + // CHECK: @_ZN14VirtualMembersL13sGlobalMemoryE = internal global { i8** } { i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTVN14VirtualMembers12nsMemoryImplE, i32 0, i32 2) } __attribute__((used)) static nsMemoryImpl sGlobalMemory; @@ -360,7 +360,7 @@ namespace VirtualMembers { T t; }; - // CHECK: @_ZN14VirtualMembers1tE = global { i8**, i32 } { i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTVN14VirtualMembers13TemplateClassIiEE, i64 0, i64 2), i32 42 } + // CHECK: @_ZN14VirtualMembers1tE = global { i8**, i32 } { i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTVN14VirtualMembers13TemplateClassIiEE, i32 0, i32 2), i32 42 } TemplateClass<int> t; } diff --git a/test/CodeGenCXX/const-init.cpp b/test/CodeGenCXX/const-init.cpp index deb923a70890..f5c9dae7ba4b 100644 --- a/test/CodeGenCXX/const-init.cpp +++ b/test/CodeGenCXX/const-init.cpp @@ -1,4 +1,6 @@ // RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm -std=c++98 -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm -std=c++11 -o - %s | FileCheck %s // CHECK: @a = global i32 10 int a = 10; @@ -27,8 +29,13 @@ C g0 = { C::e1 }; namespace test2 { struct A { +#if __cplusplus <= 199711L static const double d = 1.0; static const float f = d / 2; +#else + static constexpr double d = 1.0; + static constexpr float f = d / 2; +#endif static int g(); } a; diff --git a/test/CodeGenCXX/constructor-init.cpp b/test/CodeGenCXX/constructor-init.cpp index d7ae220712f8..c78534a218de 100644 --- a/test/CodeGenCXX/constructor-init.cpp +++ b/test/CodeGenCXX/constructor-init.cpp @@ -95,14 +95,14 @@ namespace InitVTable { // CHECK-LABEL: define void @_ZN10InitVTable1BC2Ev(%"struct.InitVTable::B"* %this) unnamed_addr // CHECK: [[T0:%.*]] = bitcast [[B:%.*]]* [[THIS:%.*]] to i32 (...)*** - // CHECK-NEXT: store i32 (...)** bitcast (i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTVN10InitVTable1BE, i64 0, i64 2) to i32 (...)**), i32 (...)*** [[T0]] + // CHECK-NEXT: store i32 (...)** bitcast (i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTVN10InitVTable1BE, i32 0, i32 2) to i32 (...)**), i32 (...)*** [[T0]] // CHECK: [[VTBL:%.*]] = load i32 ([[B]]*)**, i32 ([[B]]*)*** {{%.*}} // CHECK-NEXT: [[FNP:%.*]] = getelementptr inbounds i32 ([[B]]*)*, i32 ([[B]]*)** [[VTBL]], i64 0 // CHECK-NEXT: [[FN:%.*]] = load i32 ([[B]]*)*, 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 i32 (...)*** - // CHECK-NEXT: store i32 (...)** bitcast (i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTVN10InitVTable1BE, i64 0, i64 2) to i32 (...)**), i32 (...)*** [[T0]] + // CHECK-NEXT: store i32 (...)** bitcast (i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTVN10InitVTable1BE, i32 0, i32 2) to i32 (...)**), i32 (...)*** [[T0]] // CHECK-NEXT: ret void B::B() : A(foo()) {} @@ -110,7 +110,7 @@ namespace InitVTable { // CHECK: [[ARG:%.*]] = add nsw i32 {{%.*}}, 5 // CHECK-NEXT: call void @_ZN10InitVTable1AC2Ei({{.*}}* {{%.*}}, i32 [[ARG]]) // CHECK-NEXT: [[T0:%.*]] = bitcast [[B]]* {{%.*}} to i32 (...)*** - // CHECK-NEXT: store i32 (...)** bitcast (i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTVN10InitVTable1BE, i64 0, i64 2) to i32 (...)**), i32 (...)*** [[T0]] + // CHECK-NEXT: store i32 (...)** bitcast (i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTVN10InitVTable1BE, i32 0, i32 2) to i32 (...)**), i32 (...)*** [[T0]] // CHECK-NEXT: ret void B::B(int x) : A(x + 5) {} } diff --git a/test/CodeGenCXX/copy-constructor-elim.cpp b/test/CodeGenCXX/copy-constructor-elim.cpp index d9b28ce30e91..4abe456e4b29 100644 --- a/test/CodeGenCXX/copy-constructor-elim.cpp +++ b/test/CodeGenCXX/copy-constructor-elim.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm -o - %s | FileCheck %s -check-prefix=CHECK +// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm -o - %s | FileCheck %s // RUN: %clang_cc1 -triple %ms_abi_triple -emit-llvm -o - %s | FileCheck %s -check-prefix MS // CHECK-NOT: _ZN1CC1ERK1C // CHECK-NOT: _ZN1SC1ERK1S diff --git a/test/CodeGenCXX/copy-constructor-synthesis-2.cpp b/test/CodeGenCXX/copy-constructor-synthesis-2.cpp index 02feed3208f6..9790ca882c6b 100644 --- a/test/CodeGenCXX/copy-constructor-synthesis-2.cpp +++ b/test/CodeGenCXX/copy-constructor-synthesis-2.cpp @@ -24,4 +24,4 @@ struct A { virtual void a(); }; A x(A& y) { return y; } // CHECK: define linkonce_odr {{.*}} @_ZN1AC1ERKS_(%struct.A* {{.*}}%this, %struct.A* dereferenceable({{[0-9]+}})) unnamed_addr -// CHECK: store i32 (...)** bitcast (i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTV1A, i64 0, i64 2) to i32 (...)**) +// CHECK: store i32 (...)** bitcast (i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTV1A, i32 0, i32 2) to i32 (...)**) diff --git a/test/CodeGenCXX/copy-constructor-synthesis.cpp b/test/CodeGenCXX/copy-constructor-synthesis.cpp index 2f0aa3b3a648..4928c61488e9 100644 --- a/test/CodeGenCXX/copy-constructor-synthesis.cpp +++ b/test/CodeGenCXX/copy-constructor-synthesis.cpp @@ -166,7 +166,7 @@ void f(B b1) { // CHECK-LABEL: define linkonce_odr void @_ZN12rdar138169401AC2ERKS0_( // CHECK: [[THIS:%.*]] = load [[A]]*, [[A]]** // CHECK-NEXT: [[T0:%.*]] = bitcast [[A]]* [[THIS]] to i32 (...)*** -// CHECK-NEXT: store i32 (...)** bitcast (i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @_ZTVN12rdar138169401AE, i64 0, i64 2) to i32 (...)**), i32 (...)*** [[T0]] +// CHECK-NEXT: store i32 (...)** bitcast (i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @_ZTVN12rdar138169401AE, i32 0, i32 2) to i32 (...)**), i32 (...)*** [[T0]] // CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[A]], [[A]]* [[THIS]], i32 0, i32 1 // CHECK-NEXT: [[OTHER:%.*]] = load [[A]]*, [[A]]** // CHECK-NEXT: [[T2:%.*]] = getelementptr inbounds [[A]], [[A]]* [[OTHER]], i32 0, i32 1 diff --git a/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp b/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp index 311edaabb5db..7bab11488ad4 100644 --- a/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp +++ b/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp @@ -249,7 +249,7 @@ haslist2::haslist2() void fn10(int i) { // CHECK-LABEL: define void @_Z4fn10i // CHECK: alloca [3 x i32] - // CHECK: call noalias i8* @_Znw{{[jm]}} + // CHECK: call i8* @_Znw{{[jm]}} // CHECK: store i32 % // CHECK: store i32 2 // CHECK: store i32 3 diff --git a/test/CodeGenCXX/cxx11-exception-spec.cpp b/test/CodeGenCXX/cxx11-exception-spec.cpp index a3dff79fc494..6a3a394e047a 100644 --- a/test/CodeGenCXX/cxx11-exception-spec.cpp +++ b/test/CodeGenCXX/cxx11-exception-spec.cpp @@ -70,37 +70,37 @@ void h() { // CHECK: define {{.*}} @_Z1iv void i() { - // CHECK: declare {{.*}} @_Z1gIiEvv() [[NUW]] + // CHECK: declare {{.*}} @_Z1gIiEvv() [[NUW2:#[0-9]+]] g<int>(); // CHECK: declare {{.*}} @_Z1gIA2_iEvv() // CHECK-NOT: [[NUW]] g<int[2]>(); - // CHECK: declare {{.*}} @_ZN1SIiE1gEv() [[NUW]] + // CHECK: declare {{.*}} @_ZN1SIiE1gEv() [[NUW2]] S<int>::g(); // CHECK: declare {{.*}} @_ZN1SIA2_iE1gEv() // CHECK-NOT: [[NUW]] S<int[2]>::g(); - // CHECK: declare {{.*}} @_Z1gIfEvv() [[NUW]] + // CHECK: declare {{.*}} @_Z1gIfEvv() [[NUW2]] void (*g1)() = &g<float>; // CHECK: declare {{.*}} @_Z1gIdEvv() // CHECK-NOT: [[NUW]] void (*g2)() = &g<double>; - // CHECK: declare {{.*}} @_ZN1SIfE1gEv() [[NUW]] + // CHECK: declare {{.*}} @_ZN1SIfE1gEv() [[NUW2]] void (*g3)() = &S<float>::g; // CHECK: declare {{.*}} @_ZN1SIdE1gEv() // CHECK-NOT: [[NUW]] void (*g4)() = &S<double>::g; - // CHECK: declare {{.*}} @_Z1gIA4_cEvv() [[NUW]] + // CHECK: declare {{.*}} @_Z1gIA4_cEvv() [[NUW2]] (void)&g<char[4]>; // CHECK: declare {{.*}} @_Z1gIcEvv() // CHECK-NOT: [[NUW]] (void)&g<char>; - // CHECK: declare {{.*}} @_ZN1SIA4_cE1gEv() [[NUW]] + // CHECK: declare {{.*}} @_ZN1SIA4_cE1gEv() [[NUW2]] (void)&S<char[4]>::g; // CHECK: declare {{.*}} @_ZN1SIcE1gEv() // CHECK-NOT: [[NUW]] @@ -116,12 +116,15 @@ void j() { // CHECK: declare {{.*}} @_ZN6NestedIiE1fILb1EcEEvv( // CHECK-NOT: [[NUW]] Nested<int>().f<true, char>(); - // CHECK: declare {{.*}} @_ZN6NestedIlE1fILb0ElEEvv({{.*}}) [[NUW]] + // CHECK: declare {{.*}} @_ZN6NestedIlE1fILb0ElEEvv({{.*}}) [[NUW2]] Nested<long>().f<false, long>(); } // CHECK: attributes [[NONE]] = { {{.*}} } // CHECK: attributes [[NUW]] = { nounwind{{.*}} } +// CHECK: attributes [[NUW2]] = { nounwind{{.*}} } + + namespace PR19190 { template <class T> struct DWFIterator { virtual void get() throw(int) = 0; }; diff --git a/test/CodeGenCXX/cxx11-initializer-array-new.cpp b/test/CodeGenCXX/cxx11-initializer-array-new.cpp index c662190ff386..59f96031fc40 100644 --- a/test/CodeGenCXX/cxx11-initializer-array-new.cpp +++ b/test/CodeGenCXX/cxx11-initializer-array-new.cpp @@ -7,7 +7,7 @@ struct S { S(); S(int); ~S(); int n; }; void *p = new S[2][3]{ { 1, 2, 3 }, { 4, 5, 6 } }; // CHECK-LABEL: define -// CHECK: %[[ALLOC:.*]] = call noalias i8* @_Znam(i64 32) +// CHECK: %[[ALLOC:.*]] = call i8* @_Znam(i64 32) // CHECK: %[[COOKIE:.*]] = bitcast i8* %[[ALLOC]] to i64* // CHECK: store i64 6, i64* %[[COOKIE]] // CHECK: %[[START_AS_i8:.*]] = getelementptr inbounds i8, i8* %[[ALLOC]], i64 8 @@ -50,7 +50,7 @@ void *q = new S[n][3]{ { 1, 2, 3 }, { 4, 5, 6 } }; // CHECK: call {{.*}} @llvm.umul.with.overflow.i64(i64 %[[N:.*]], i64 12) // CHECK: %[[ELTS:.*]] = mul i64 %[[N]], 3 // CHECK: call {{.*}} @llvm.uadd.with.overflow.i64(i64 %{{.*}}, i64 8) -// CHECK: %[[ALLOC:.*]] = call noalias i8* @_Znam(i64 %{{.*}}) +// CHECK: %[[ALLOC:.*]] = call i8* @_Znam(i64 %{{.*}}) // // CHECK: %[[COOKIE:.*]] = bitcast i8* %[[ALLOC]] to i64* // CHECK: store i64 %[[ELTS]], i64* %[[COOKIE]] @@ -113,7 +113,7 @@ void *r = new T[n][3]{ { 1, 2, 3 }, { 4, 5, 6 } }; // No cookie. // CHECK-NOT: @llvm.uadd.with.overflow // -// CHECK: %[[ALLOC:.*]] = call noalias i8* @_Znam(i64 %{{.*}}) +// CHECK: %[[ALLOC:.*]] = call i8* @_Znam(i64 %{{.*}}) // // CHECK: %[[START_AS_T:.*]] = bitcast i8* %[[ALLOC]] to %[[T:.*]]* // diff --git a/test/CodeGenCXX/cxx11-thread-local-reference.cpp b/test/CodeGenCXX/cxx11-thread-local-reference.cpp index 8b2ac5eed800..4c1e5a70cbaf 100644 --- a/test/CodeGenCXX/cxx11-thread-local-reference.cpp +++ b/test/CodeGenCXX/cxx11-thread-local-reference.cpp @@ -21,13 +21,16 @@ int &g() { return r; } // DARWIN: call cxx_fast_tlscc i32* @_ZTW1r() // CHECK: ret i32* %{{.*}} -// LINUX: define weak_odr hidden i32* @_ZTW1r() { -// DARWIN: define cxx_fast_tlscc i32* @_ZTW1r() [[ATTR:#[0-9]+]] { -// CHECK: call void @_ZTH1r() +// LINUX: define weak_odr hidden i32* @_ZTW1r() [[ATTR0:#[0-9]+]] { +// DARWIN: define cxx_fast_tlscc i32* @_ZTW1r() [[ATTR1:#[0-9]+]] { +// LINUX: call void @_ZTH1r() +// DARWIN: call cxx_fast_tlscc void @_ZTH1r() // CHECK: load i32*, i32** @r, align 8 // CHECK: ret i32* %{{.*}} -// CHECK-LABEL: define internal void @__tls_init() +// LINUX-LABEL: define internal void @__tls_init() +// DARWIN-LABEL: define internal cxx_fast_tlscc void @__tls_init() // CHECK: call void @[[R_INIT]]() -// DARWIN: attributes [[ATTR]] = { nounwind } +// LINUX: attributes [[ATTR0]] = { {{.*}}"target-features"{{.*}} } +// DARWIN: attributes [[ATTR1]] = { {{.*}}nounwind{{.*}}"target-features"{{.*}} } diff --git a/test/CodeGenCXX/cxx11-thread-local.cpp b/test/CodeGenCXX/cxx11-thread-local.cpp index b5bcc5e23ecd..f465cbdeea84 100644 --- a/test/CodeGenCXX/cxx11-thread-local.cpp +++ b/test/CodeGenCXX/cxx11-thread-local.cpp @@ -122,7 +122,8 @@ int f() { // LINUX-LABEL: define weak_odr hidden i32* @_ZTWN1VIiE1mE() // DARWIN-LABEL: define weak_odr hidden cxx_fast_tlscc i32* @_ZTWN1VIiE1mE() -// CHECK: call void @_ZTHN1VIiE1mE() +// LINUX: call void @_ZTHN1VIiE1mE() +// DARWIN: call cxx_fast_tlscc void @_ZTHN1VIiE1mE() // CHECK: ret i32* @_ZN1VIiE1mE @@ -212,20 +213,25 @@ void set_anon_i() { // LIUNX: define weak_odr hidden i32* @_ZTW1a() { // DARWIN: define cxx_fast_tlscc i32* @_ZTW1a() -// CHECK: call void @_ZTH1a() +// LINUX: call void @_ZTH1a() +// DARWIN: call cxx_fast_tlscc void @_ZTH1a() // CHECK: ret i32* @a // CHECK: } -// LINUX: declare extern_weak void @_ZTH1b() +// LINUX: declare extern_weak void @_ZTH1b() [[ATTR:#[0-9]+]] // LINUX-LABEL: define internal i32* @_ZTWL1d() // DARWIN-LABEL: define internal cxx_fast_tlscc i32* @_ZTWL1d() -// CHECK: call void @_ZTHL1d() +// LINUX: call void @_ZTHL1d() +// DARWIN: call cxx_fast_tlscc void @_ZTHL1d() // CHECK: ret i32* @_ZL1d // LINUX-LABEL: define weak_odr hidden i32* @_ZTWN1U1mE() // DARWIN-LABEL: define cxx_fast_tlscc i32* @_ZTWN1U1mE() -// CHECK: call void @_ZTHN1U1mE() +// LINUX: call void @_ZTHN1U1mE() +// DARWIN: call cxx_fast_tlscc void @_ZTHN1U1mE() // CHECK: ret i32* @_ZN1U1mE + +// LINUX: attributes [[ATTR]] = { {{.+}} } diff --git a/test/CodeGenCXX/cxx1z-constexpr-if.cpp b/test/CodeGenCXX/cxx1z-constexpr-if.cpp new file mode 100644 index 000000000000..80a397f51e9a --- /dev/null +++ b/test/CodeGenCXX/cxx1z-constexpr-if.cpp @@ -0,0 +1,21 @@ +// RUN: %clang_cc1 -std=c++1z %s -emit-llvm -o - | FileCheck %s --implicit-check-not=should_not_be_used + +void should_be_used_1(); +void should_be_used_2(); +void should_not_be_used(); +void f() { + if constexpr (false) + should_not_be_used(); + else + should_be_used_1(); + + if constexpr (true || ({ label: false; })) + should_be_used_2(); + else { + goto foo; +foo: should_not_be_used(); + } +} + +// CHECK: should_be_used_1 +// CHECK: should_be_used_2 diff --git a/test/CodeGenCXX/cxx1z-init-statement.cpp b/test/CodeGenCXX/cxx1z-init-statement.cpp new file mode 100644 index 000000000000..5c05212c7247 --- /dev/null +++ b/test/CodeGenCXX/cxx1z-init-statement.cpp @@ -0,0 +1,70 @@ +// RUN: %clang_cc1 -std=c++1z -triple x86_64-apple-macosx10.7.0 -emit-llvm -o - %s -w | FileCheck %s + +typedef int T; +void f() { + // CHECK: %[[A:.*]] = alloca i32, align 4 + // CHECK-NEXT: store i32 5, i32* %[[A]], align 4 + // CHECK-NEXT: %[[B:.*]] = load i32, i32* %[[A]], align 4 + // CHECK-NEXT %[[C:.*]] = icmp slt i32 %[[B]], 8 + if (int a = 5; a < 8) + ; +} + +void f1() { + // CHECK: %[[A:.*]] = alloca i32, align 4 + // CHECK-NEXT: %[[B:.*]] = alloca i32, align 4 + // CHECK-NEXT: %[[C:.*]] = alloca i32, align 4 + // CHECK-NEXT: store i32 5, i32* %[[B]], align 4 + // CHECK-NEXT: store i32 7, i32* %[[C]], align 4 + if (int a, b = 5; int c = 7) + ; +} + +int f2() { + // CHECK: %[[A:.*]] = alloca i32, align 4 + // CHECK-NEXT: %[[B:.*]] = call i32 @_Z2f2v() + // CHECK-NEXT: store i32 7, i32* %[[A]], align 4 + // CHECK-NEXT: %[[C:.*]] = load i32, i32* %[[A]], align 4 + // CHECK-NEXT: %[[D:.*]] = icmp ne i32 %[[C]], 0 + if (T{f2()}; int c = 7) + ; + return 2; +} + +void g() { + // CHECK: %[[A:.*]] = alloca i32, align 4 + // CHECK-NEXT: store i32 5, i32* %[[A]], align 4 + // CHECK-NEXT: %[[B:.*]] = load i32, i32* %[[A]], align 4 + // CHECK-NEXT: switch i32 %[[B]], label %[[C:.*]] [ + switch (int a = 5; a) { + case 0: + break; + } +} + +void g1() { + // CHECK: %[[A:.*]] = alloca i32, align 4 + // CHECK-NEXT: %[[B:.*]] = alloca i32, align 4 + // CHECK-NEXT: %[[C:.*]] = alloca i32, align 4 + // CHECK-NEXT: store i32 5, i32* %[[B]], align 4 + // CHECK-NEXT: store i32 7, i32* %[[C]], align 4 + // CHECK-NEXT: %[[D:.*]] = load i32, i32* %[[C]], align 4 + // CHECK-NEXT: switch i32 %[[D]], label %[[E:.*]] [ + switch (int a, b = 5; int c = 7) { + case 0: + break; + } +} + +int g2() { + // CHECK: %[[A:.*]] = alloca i32, align 4 + // CHECK-NEXT: %[[B:.*]] = call i32 @_Z2f2v() + // CHECK-NEXT: store i32 7, i32* %[[A]], align 4 + // CHECK-NEXT: %[[C:.*]] = load i32, i32* %[[A]], align 4 + // CHECK-NEXT: switch i32 %[[C]], label %[[E:.*]] [ + switch (T{f2()}; int c = 7) { + case 0: + break; + } + return 2; +} diff --git a/test/CodeGenCXX/cxx1z-initializer-aggregate.cpp b/test/CodeGenCXX/cxx1z-initializer-aggregate.cpp new file mode 100644 index 000000000000..9110e49f93a1 --- /dev/null +++ b/test/CodeGenCXX/cxx1z-initializer-aggregate.cpp @@ -0,0 +1,114 @@ +// RUN: %clang_cc1 -std=c++1z %s -triple x86_64-linux-gnu -fexceptions -fcxx-exceptions -emit-llvm -o - | FileCheck %s + +namespace Constant { + struct A { + int n; + char k; + ~A(); + }; + + struct B { + char k2; + }; + + struct C : B {}; + + struct D : A, C {}; + + C c1 = {}; + C c2 = {1}; + // CHECK: @_ZN8Constant2c1E = global { i8 } zeroinitializer, align 1 + // CHECK: @_ZN8Constant2c2E = global { i8 } { i8 1 }, align 1 + + // Test packing bases into tail padding. + D d1 = {}; + D d2 = {1, 2, 3}; + D d3 = {1}; + // CHECK: @_ZN8Constant2d1E = global { i32, i8, i8 } zeroinitializer, align 4 + // CHECK: @_ZN8Constant2d2E = global { i32, i8, i8 } { i32 1, i8 2, i8 3 }, align 4 + // CHECK: @_ZN8Constant2d3E = global { i32, i8, i8 } { i32 1, i8 0, i8 0 }, align 4 + + // CHECK-LABEL: define {{.*}}global_var_init + // CHECK: call {{.*}} @__cxa_atexit({{.*}} @_ZN8Constant1DD1Ev {{.*}} @_ZN8Constant2d1E + + // CHECK-LABEL: define {{.*}}global_var_init + // CHECK: call {{.*}} @__cxa_atexit({{.*}} @_ZN8Constant1DD1Ev {{.*}} @_ZN8Constant2d2E + + // CHECK-LABEL: define {{.*}}global_var_init + // CHECK: call {{.*}} @__cxa_atexit({{.*}} @_ZN8Constant1DD1Ev {{.*}} @_ZN8Constant2d3E +} + +namespace Dynamic { + struct A { + A(); + A(int); + A(const char*, unsigned); + ~A(); + void *p; + }; + + struct B { + ~B(); + int n = 5; + }; + + struct C { + C(bool = true); + }; + + int f(), g(), h(), i(); + struct D : A, B, C { + int n = f(); + }; + + D d1 = {}; + // CHECK-LABEL: define {{.*}}global_var_init + // CHECK: call void @_ZN7Dynamic1AC2Ev({{.*}} @_ZN7Dynamic2d1E + // CHECK: store i32 5, {{.*}}i8* getelementptr inbounds {{.*}} @_ZN7Dynamic2d1E{{.*}}, i64 8 + // CHECK: invoke void @_ZN7Dynamic1CC2Eb({{.*}} @_ZN7Dynamic2d1E{{.*}}, i1 zeroext true) + // CHECK: unwind label %[[UNWIND:.*]] + // CHECK: invoke i32 @_ZN7Dynamic1fEv() + // CHECK: unwind label %[[UNWIND:.*]] + // CHECK: store i32 {{.*}}, i32* getelementptr {{.*}} @_ZN7Dynamic2d1E, i32 0, i32 2 + // CHECK: call {{.*}} @__cxa_atexit({{.*}} @_ZN7Dynamic1DD1Ev {{.*}} @_ZN7Dynamic2d1E + // CHECK: ret + // + // UNWIND: + // CHECK: call void @_ZN7Dynamic1BD1Ev({{.*}}i8* getelementptr inbounds {{.*}} @_ZN7Dynamic2d1E{{.*}}, i64 8 + // CHECK: call void @_ZN7Dynamic1AD1Ev({{.*}} @_ZN7Dynamic2d1E + + D d2 = {1, 2, false}; + // CHECK-LABEL: define {{.*}}global_var_init + // CHECK: call void @_ZN7Dynamic1AC1Ei({{.*}} @_ZN7Dynamic2d2E{{.*}}, i32 1) + // CHECK: store i32 2, {{.*}}i8* getelementptr inbounds {{.*}}@_ZN7Dynamic2d2E{{.*}}, i64 8 + // CHECK: invoke void @_ZN7Dynamic1CC1Eb({{.*}} @_ZN7Dynamic2d2E{{.*}}, i1 zeroext false) + // CHECK: invoke i32 @_ZN7Dynamic1fEv() + // CHECK: store i32 {{.*}}, i32* getelementptr {{.*}} @_ZN7Dynamic2d2E, i32 0, i32 2 + // CHECK: call {{.*}} @__cxa_atexit({{.*}} @_ZN7Dynamic1DD1Ev {{.*}} @_ZN7Dynamic2d2E + // CHECK: ret void + + D d3 = {g(), h(), {}, i()}; + // CHECK-LABEL: define {{.*}}global_var_init + // CHECK: %[[G_CALL:.*]] = call i32 @_ZN7Dynamic1gEv() + // CHECK: call void @_ZN7Dynamic1AC1Ei({{.*}} @_ZN7Dynamic2d3E{{.*}}, i32 %[[G_CALL]]) + // CHECK: %[[H_CALL:.*]] = invoke i32 @_ZN7Dynamic1hEv() + // CHECK: unwind label %[[DESTROY_A_LPAD:.*]] + // CHECK: store i32 %[[H_CALL]], {{.*}}i8* getelementptr inbounds {{.*}} @_ZN7Dynamic2d3E{{.*}}, i64 8 + // CHECK: invoke void @_ZN7Dynamic1CC2Eb({{.*}} @_ZN7Dynamic2d3E{{.*}}, i1 zeroext true) + // CHECK: unwind label %[[DESTROY_AB_LPAD:.*]] + // CHECK: %[[I_CALL:.*]] = invoke i32 @_ZN7Dynamic1iEv() + // CHECK: unwind label %[[DESTROY_AB_LPAD:.*]] + // CHECK: store i32 %[[I_CALL]], i32* getelementptr {{.*}} @_ZN7Dynamic2d3E, i32 0, i32 2 + // CHECK: call {{.*}} @__cxa_atexit({{.*}} @_ZN7Dynamic1DD1Ev {{.*}} @_ZN7Dynamic2d3E to i8* + // CHECK: ret + // + // DESTROY_A_LPAD: + // CHECK: br label %[[A_CLEANUP:.*]] + // + // DESTROY_B_LPAD: + // CHECK: call void @_ZN7Dynamic1BD1Ev({{.*}}i8* getelementptr inbounds {{.*}} @_ZN7Dynamic2d3E{{.*}}, i64 8 + // CHECK: br label %[[A_CLEANUP:.*]] + // + // A_CLEANUP: + // CHECK: call void @_ZN7Dynamic1AD1Ev({{.*}} @_ZN7Dynamic2d3E +} diff --git a/test/CodeGenCXX/cxx1z-inline-variables.cpp b/test/CodeGenCXX/cxx1z-inline-variables.cpp new file mode 100644 index 000000000000..183709373d12 --- /dev/null +++ b/test/CodeGenCXX/cxx1z-inline-variables.cpp @@ -0,0 +1,83 @@ +// RUN: %clang_cc1 -std=c++1z %s -emit-llvm -o - -triple x86_64-linux-gnu | FileCheck %s + +struct Q { + // CHECK: @_ZN1Q1kE = linkonce_odr constant i32 5, comdat + static constexpr int k = 5; +}; +const int &r = Q::k; + +int f(); + +// const does not imply internal linkage. +// CHECK: @external_inline = linkonce_odr constant i32 5, comdat +inline const int external_inline = 5; +const int &use1 = external_inline; + +// static still does, though. +// CHECK: @_ZL15internal_inline = internal constant i32 5 +static inline const int internal_inline = 5; +const int &use2 = internal_inline; + +int a = f(); +// CHECK: @b = linkonce_odr global i32 0, comdat +// CHECK: @_ZGV1b = linkonce_odr global i64 0, comdat($b) +inline int b = f(); +int c = f(); + +// For compatibility with C++11 and C++14, an out-of-line declaration of a +// static constexpr local variable promotes the variable to weak_odr. +struct compat { + static constexpr int a = 1; + static constexpr int b = 2; + static constexpr int c = 3; + static inline constexpr int d = 4; +}; +const int &compat_use_before_redecl = compat::b; +const int compat::a; +const int compat::b; +const int compat::c; +const int compat::d; +const int &compat_use_after_redecl1 = compat::c; +const int &compat_use_after_redecl2 = compat::d; +// CHECK: @_ZN6compat1bE = weak_odr constant i32 2 +// CHECK: @_ZN6compat1aE = weak_odr constant i32 1 +// CHECK: @_ZN6compat1cE = weak_odr constant i32 3 +// CHECK: @_ZN6compat1dE = linkonce_odr constant i32 4 + +template<typename T> struct X { + static int a; + static inline int b; + static int c; +}; +// CHECK: @_ZN1XIiE1aE = linkonce_odr global i32 10 +// CHECK: @_ZN1XIiE1bE = global i32 20 +// CHECK-NOT: @_ZN1XIiE1cE +template<> inline int X<int>::a = 10; +int &use3 = X<int>::a; +template<> int X<int>::b = 20; +template<> inline int X<int>::c = 30; + +// CHECK-LABEL: define {{.*}}global_var_init +// CHECK: call i32 @_Z1fv + +// CHECK-LABEL: define {{.*}}global_var_init +// CHECK-NOT: comdat +// CHECK-SAME: {{$}} +// CHECK: load atomic {{.*}} acquire +// CHECK: br +// CHECK: __cxa_guard_acquire(i64* @_ZGV1b) +// CHECK: br +// CHECK: call i32 @_Z1fv +// CHECK: __cxa_guard_release(i64* @_ZGV1b) + +// CHECK-LABEL: define {{.*}}global_var_init +// CHECK: call i32 @_Z1fv + +template<typename T> inline int d = f(); +int e = d<int>; + +// CHECK-LABEL: define {{.*}}global_var_init{{.*}}comdat +// CHECK: _ZGV1dIiE +// CHECK-NOT: __cxa_guard_acquire(i64* @_ZGV1b) +// CHECK: call i32 @_Z1fv +// CHECK-NOT: __cxa_guard_release(i64* @_ZGV1b) diff --git a/test/CodeGenCXX/cxx1z-lambda-star-this.cpp b/test/CodeGenCXX/cxx1z-lambda-star-this.cpp new file mode 100644 index 000000000000..a7e4aadbd573 --- /dev/null +++ b/test/CodeGenCXX/cxx1z-lambda-star-this.cpp @@ -0,0 +1,31 @@ +// RUN: %clang_cc1 -std=c++1y -triple i686-pc-windows-msvc -emit-llvm %s -o - | FileCheck %s +//CHECK: %[[A_LAMBDA:.*]] = type { %struct.A } +//CHECK: %[[B_LAMBDA:.*]] = type { %struct.B* } +struct A { + double a = 111; + auto foo() { return [*this] { return a; }; } +}; + +namespace ns1 { +int X = A{}.foo()(); +} //end ns1 + +//CHECK: @"\01?foo@A@@QAE?A?<auto>@@XZ"(%struct.A* %this, %class.anon* noalias sret %[[A_LAMBDA_RETVAL:.*]]) +// get the first object with the closure type, which is of type 'struct.A' +//CHECK: %[[I0:.+]] = getelementptr inbounds %[[A_LAMBDA]], %[[A_LAMBDA]]* %[[A_LAMBDA_RETVAL]], i32 0, i32 0 +//CHECK: %[[I1:.+]] = bitcast %struct.A* %[[I0]] to i8* +//CHECK: %[[I2:.+]] = bitcast %struct.A* %this1 to i8* +// copy the contents ... +//CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* %[[I1]], i8* %[[I2]], i32 8, i32 8, i1 false) + +struct B { + double b = 222; + auto bar() { return [this] { return b; }; }; +}; + +namespace ns2 { +int X = B{}.bar()(); +} +//CHECK: @"\01?bar@B@@QAE?A?<auto>@@XZ"(%struct.B* %this, %class.anon.0* noalias sret %agg.result) +//CHECK: %[[I20:.+]] = getelementptr inbounds %class.anon.0, %class.anon.0* %agg.result, i32 0, i32 0 +//CHECK: store %struct.B* %this1, %struct.B** %[[I20]], align 4 diff --git a/test/CodeGenCXX/debug-info-access.cpp b/test/CodeGenCXX/debug-info-access.cpp index 1699bab96104..41b7f71fcecb 100644 --- a/test/CodeGenCXX/debug-info-access.cpp +++ b/test/CodeGenCXX/debug-info-access.cpp @@ -1,13 +1,16 @@ // RUN: %clang_cc1 -emit-llvm -debug-info-kind=limited -triple %itanium_abi_triple %s -o - | FileCheck %s // Test the various accessibility flags in the debug info. struct A { + // CHECK: ![[A:[0-9]+]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "A", + // CHECK-DAG: !DISubprogram(name: "pub_default",{{.*}} line: [[@LINE+1]],{{.*}} flags: DIFlagPrototyped, void pub_default(); // CHECK-DAG: !DIDerivedType(tag: DW_TAG_member, name: "pub_default_static",{{.*}} line: [[@LINE+1]],{{.*}} flags: DIFlagStaticMember) static int pub_default_static; }; -// CHECK: !DIDerivedType(tag: DW_TAG_inheritance,{{.*}} baseType: !"_ZTS1A",{{.*}} flags: DIFlagPublic) + +// CHECK: !DIDerivedType(tag: DW_TAG_inheritance,{{.*}} baseType: ![[A]],{{.*}} flags: DIFlagPublic) class B : public A { public: // CHECK-DAG: !DISubprogram(name: "pub",{{.*}} line: [[@LINE+1]],{{.*}} flags: DIFlagPublic | DIFlagPrototyped, diff --git a/test/CodeGenCXX/debug-info-anon-union-vars.cpp b/test/CodeGenCXX/debug-info-anon-union-vars.cpp index 5b0370eb749d..b844d429447b 100644 --- a/test/CodeGenCXX/debug-info-anon-union-vars.cpp +++ b/test/CodeGenCXX/debug-info-anon-union-vars.cpp @@ -44,8 +44,8 @@ void instantiate(int x) { buildBytes(x); } -// CHECK: [[FILE:.*]] = !DIFile(filename: "{{.*}}debug-info-anon-union-vars.cpp", -// CHECK: !DIGlobalVariable(name: "c",{{.*}} file: [[FILE]], line: 6,{{.*}} isLocal: true, isDefinition: true +// CHECK: !DIGlobalVariable(name: "c",{{.*}} file: [[FILE:.*]], line: 6,{{.*}} isLocal: true, isDefinition: true +// CHECK: [[FILE]] = !DIFile(filename: "{{.*}}debug-info-anon-union-vars.cpp", // CHECK: !DIGlobalVariable(name: "d",{{.*}} file: [[FILE]], line: 6,{{.*}} isLocal: true, isDefinition: true // CHECK: !DIGlobalVariable(name: "a",{{.*}} file: [[FILE]], line: 6,{{.*}} isLocal: true, isDefinition: true // CHECK: !DIGlobalVariable(name: "b",{{.*}} file: [[FILE]], line: 6,{{.*}} isLocal: true, isDefinition: true @@ -56,7 +56,7 @@ void instantiate(int x) { // CHECK: !DILocalVariable( // CHECK-NOT: name: // CHECK: type: ![[UNION:[0-9]+]] -// CHECK: ![[UNION]] = !DICompositeType(tag: DW_TAG_union_type, +// CHECK: ![[UNION]] = distinct !DICompositeType(tag: DW_TAG_union_type, // CHECK-NOT: name: // CHECK: elements // CHECK: !DIDerivedType(tag: DW_TAG_member, name: "i", scope: ![[UNION]], diff --git a/test/CodeGenCXX/debug-info-artificial-arg.cpp b/test/CodeGenCXX/debug-info-artificial-arg.cpp index c840df672aa0..a0cf131f83e1 100644 --- a/test/CodeGenCXX/debug-info-artificial-arg.cpp +++ b/test/CodeGenCXX/debug-info-artificial-arg.cpp @@ -22,11 +22,10 @@ int main(int argc, char **argv) { A reallyA (500); } -// CHECK: ![[CLASSTYPE:.*]] = !DICompositeType(tag: DW_TAG_class_type, name: "A", +// CHECK: ![[CLASSTYPE:.*]] = distinct !DICompositeType(tag: DW_TAG_class_type, name: "A", // CHECK-SAME: identifier: "_ZTS1A" -// CHECK: ![[ARTARG:.*]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !"_ZTS1A", -// CHECK-SAME: DIFlagArtificial -// CHECK: !DISubprogram(name: "A", scope: !"_ZTS1A" +// CHECK: ![[ARTARG:.*]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[CLASSTYPE]],{{.*}} DIFlagArtificial +// CHECK: !DISubprogram(name: "A", scope: ![[CLASSTYPE]] // CHECK-SAME: line: 12 // CHECK-SAME: DIFlagPublic // CHECK: !DISubroutineType(types: [[FUNCTYPE:![0-9]*]]) diff --git a/test/CodeGenCXX/debug-info-calling-conventions.cpp b/test/CodeGenCXX/debug-info-calling-conventions.cpp new file mode 100644 index 000000000000..51d801e35ef6 --- /dev/null +++ b/test/CodeGenCXX/debug-info-calling-conventions.cpp @@ -0,0 +1,26 @@ +// RUN: %clang_cc1 %s -triple=i686-pc-windows-msvc -debug-info-kind=limited -emit-llvm -o - | FileCheck %s + +struct A { + void thiscallcc(); +}; +void A::thiscallcc() {} + +// CHECK: !DISubprogram(name: "thiscallcc", {{.*}} type: ![[thiscallty:[^,]*]], {{.*}}) +// CHECK: ![[thiscallty]] = !DISubroutineType(cc: DW_CC_BORLAND_thiscall, types: ![[thisargs:[^,)]*]]) +// CHECK: ![[thisargs]] = !{null, ![[thisptrty:[^,}]*]]} +// CHECK: ![[thisptrty]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !{{.*}}, size: 32, align: 32, flags: DIFlagArtificial | DIFlagObjectPointer) + +void cdeclcc() {} +void __fastcall fastcallcc() {} +void __stdcall stdcallcc() {} +void __vectorcall vectorcallcc() {} + +// CHECK: !DISubprogram(name: "cdeclcc", {{.*}} type: ![[cdeclty:[^,]*]], {{.*}}) +// CHECK: ![[cdeclty]] = !DISubroutineType(types: ![[noargs:[^,)]*]]) +// CHECK: ![[noargs]] = !{null} +// CHECK: !DISubprogram(name: "fastcallcc", {{.*}} type: ![[fastcallty:[^,]*]], {{.*}}) +// CHECK: ![[fastcallty]] = !DISubroutineType(cc: DW_CC_BORLAND_msfastcall, types: ![[noargs]]) +// CHECK: !DISubprogram(name: "stdcallcc", {{.*}} type: ![[stdcallty:[^,]*]], {{.*}}) +// CHECK: ![[stdcallty]] = !DISubroutineType(cc: DW_CC_BORLAND_stdcall, types: ![[noargs]]) +// CHECK: !DISubprogram(name: "vectorcallcc", {{.*}} type: ![[vectorcallty:[^,]*]], {{.*}}) +// CHECK: ![[vectorcallty]] = !DISubroutineType(cc: DW_CC_LLVM_vectorcall, types: ![[noargs]]) diff --git a/test/CodeGenCXX/debug-info-class-limited-plugin.test b/test/CodeGenCXX/debug-info-class-limited-plugin.test index 61d258d9ffc4..533c2f6b16c5 100644 --- a/test/CodeGenCXX/debug-info-class-limited-plugin.test +++ b/test/CodeGenCXX/debug-info-class-limited-plugin.test @@ -1,2 +1,2 @@ -RUN: %clang_cc1 -emit-llvm -fno-standalone-debug -g -o - -load %llvmshlibdir/PrintFunctionNames%pluginext -add-plugin print-function-names %S/Inputs/debug-info-class-limited.cpp 2>&1 | FileCheck %S/Inputs/debug-info-class-limited.cpp +RUN: %clang_cc1 -emit-llvm -debug-info-kind=limited -o - -load %llvmshlibdir/PrintFunctionNames%pluginext -add-plugin print-function-names %S/Inputs/debug-info-class-limited.cpp 2>&1 | FileCheck %S/Inputs/debug-info-class-limited.cpp REQUIRES: plugins, examples diff --git a/test/CodeGenCXX/debug-info-class-limited.test b/test/CodeGenCXX/debug-info-class-limited.test index 0b10728f3c97..c2e332866f9f 100644 --- a/test/CodeGenCXX/debug-info-class-limited.test +++ b/test/CodeGenCXX/debug-info-class-limited.test @@ -1 +1 @@ -RUN: %clang_cc1 -emit-llvm -fno-standalone-debug -g %S/Inputs/debug-info-class-limited.cpp -o - | FileCheck %S/Inputs/debug-info-class-limited.cpp +RUN: %clang_cc1 -emit-llvm -debug-info-kind=limited %S/Inputs/debug-info-class-limited.cpp -o - | FileCheck %S/Inputs/debug-info-class-limited.cpp diff --git a/test/CodeGenCXX/debug-info-class.cpp b/test/CodeGenCXX/debug-info-class.cpp index a63efe5d780a..d03c0845dd6b 100644 --- a/test/CodeGenCXX/debug-info-class.cpp +++ b/test/CodeGenCXX/debug-info-class.cpp @@ -83,13 +83,22 @@ int main(int argc, char **argv) { return 0; } -// RUN: %clang -target x86_64-unknown_unknown -emit-llvm -g -S %s -o - | FileCheck %s -// RUN: %clang -target i686-cygwin -emit-llvm -g -S %s -o - | FileCheck %s -// RUN: %clang -target armv7l-unknown-linux-gnueabihf -emit-llvm -g -S %s -o - | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-unknown_unknown -emit-llvm -debug-info-kind=limited -fexceptions %s -o - | FileCheck %s +// RUN: %clang_cc1 -triple i686-cygwin -emit-llvm -debug-info-kind=limited -fexceptions %s -o - | FileCheck %s +// RUN: %clang_cc1 -triple armv7l-unknown-linux-gnueabihf -emit-llvm -debug-info-kind=limited -fexceptions %s -o - | FileCheck %s // CHECK: invoke {{.+}} @_ZN1BD1Ev(%class.B* %b) // CHECK-NEXT: unwind label %{{.+}}, !dbg ![[EXCEPTLOC:.*]] // CHECK: store i32 0, i32* %{{.+}}, !dbg ![[RETLOC:.*]] + +// CHECK: [[F:![0-9]*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "F" +// CHECK-SAME: DIFlagFwdDecl +// CHECK-SAME: identifier: "_ZTS1F" +// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "I" +// CHECK-NOT: DIFlagFwdDecl +// CHECK-SAME: ){{$}} + +// CHECK: ![[INT:[0-9]+]] = !DIBasicType(name: "int" // CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "foo" // CHECK: !DICompositeType(tag: DW_TAG_class_type, name: "bar" // CHECK: !DICompositeType(tag: DW_TAG_union_type, name: "baz" @@ -99,12 +108,10 @@ int main(int argc, char **argv) { // CHECK: !DIDerivedType(tag: DW_TAG_member, name: "_vptr$B", // CHECK-SAME: DIFlagArtificial -// CHECK: ![[INT:[0-9]+]] = !DIBasicType(name: "int" - -// CHECK: [[C:![0-9]*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "C", +// CHECK: [[C:![0-9]*]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "C", // CHECK-NOT: DIFlagFwdDecl // CHECK-SAME: elements: [[C_MEM:![0-9]*]] -// CHECK-SAME: vtableHolder: !"_ZTS1C" +// CHECK-SAME: vtableHolder: [[C]] // CHECK-SAME: identifier: "_ZTS1C" // CHECK: [[C_MEM]] = !{[[C_VPTR:![0-9]*]], [[C_S:![0-9]*]], [[C_DTOR:![0-9]*]]} // CHECK: [[C_VPTR]] = !DIDerivedType(tag: DW_TAG_member, name: "_vptr$C" @@ -114,39 +121,33 @@ int main(int argc, char **argv) { // CHECK-SAME: DIFlagStaticMember // CHECK: [[C_DTOR]] = !DISubprogram(name: "~C" -// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "D" +// CHECK: [[D:![0-9]+]] = !DICompositeType(tag: DW_TAG_structure_type, name: "D" // CHECK-SAME: DIFlagFwdDecl // CHECK-SAME: identifier: "_ZTS1D" // CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "E" // CHECK-SAME: DIFlagFwdDecl // CHECK-SAME: identifier: "_ZTS1E" -// CHECK: [[F:![0-9]*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "F" -// CHECK-SAME: DIFlagFwdDecl -// CHECK-SAME: identifier: "_ZTS1F" -// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "G" -// CHECK-SAME: DIFlagFwdDecl -// CHECK-SAME: identifier: "_ZTS1G" -// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "inner" -// CHECK: line: 50 +// CHECK: !DISubprogram(name: "func",{{.*}} scope: [[D]] +// CHECK-SAME: isDefinition: true +// CHECK-SAME: declaration: [[D_FUNC_DECL:![0-9]*]] +// CHECK: [[D_FUNC_DECL]] = !DISubprogram(name: "func",{{.*}} scope: [[D]] +// CHECK-SAME: isDefinition: false + +// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "inner",{{.*}} line: 50 // CHECK-NOT: DIFlagFwdDecl // CHECK-SAME: elements: [[G_INNER_MEM:![0-9]*]] // CHECK-SAME: identifier: "_ZTSN1G5innerE" + +// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "G" +// CHECK-SAME: DIFlagFwdDecl +// CHECK-SAME: identifier: "_ZTS1G" // CHECK: [[G_INNER_MEM]] = !{[[G_INNER_I:![0-9]*]]} // CHECK: [[G_INNER_I]] = !DIDerivedType(tag: DW_TAG_member, name: "j" // CHECK-SAME: baseType: ![[INT]] // CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "A" // CHECK: !DIDerivedType(tag: DW_TAG_member, name: "HdrSize" -// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "I" -// CHECK-NOT: DIFlagFwdDecl -// CHECK-SAME: ){{$}} // -// CHECK: !DISubprogram(name: "func",{{.*}} scope: !"_ZTS1D" -// CHECK-SAME: isDefinition: true -// CHECK-SAME: declaration: [[D_FUNC_DECL:![0-9]*]] -// CHECK: [[D_FUNC_DECL]] = !DISubprogram(name: "func",{{.*}} scope: !"_ZTS1D" -// CHECK-SAME: isDefinition: false - // CHECK: ![[EXCEPTLOC]] = !DILocation(line: 84, // CHECK: ![[RETLOC]] = !DILocation(line: 83, diff --git a/test/CodeGenCXX/debug-info-codeview-display-name.cpp b/test/CodeGenCXX/debug-info-codeview-display-name.cpp index 1d0300c76c01..b1b5a1e9acb8 100644 --- a/test/CodeGenCXX/debug-info-codeview-display-name.cpp +++ b/test/CodeGenCXX/debug-info-codeview-display-name.cpp @@ -1,14 +1,22 @@ -// RUN: %clang_cc1 -fblocks -debug-info-kind=limited -gcodeview -emit-llvm %s -o - -triple=x86_64-pc-win32 -std=c++98 | \ -// RUN: grep 'DISubprogram' | sed -e 's/.*name: "\([^"]*\)".*/"\1"/' | FileCheck %s +// RUN: %clang_cc1 -fblocks -debug-info-kind=limited -gcodeview -emit-llvm %s \ +// RUN: -o - -triple=x86_64-pc-win32 -std=c++98 | \ +// RUN: grep 'DISubprogram' | sed -e 's/.*name: "\([^"]*\)".*/"\1"/' | \ +// RUN: FileCheck %s --check-prefix=CHECK --check-prefix=UNQUAL +// RUN: %clang_cc1 -fblocks -debug-info-kind=line-tables-only -gcodeview -emit-llvm %s \ +// RUN: -o - -triple=x86_64-pc-win32 -std=c++98 | \ +// RUN: grep 'DISubprogram' | sed -e 's/.*name: "\([^"]*\)".*/"\1"/' | \ +// RUN: FileCheck %s --check-prefix=CHECK --check-prefix=QUAL void freefunc() { } // CHECK-DAG: "freefunc" namespace N { int b() { return 0; } -// CHECK-DAG: "N::b" +// UNQUAL-DAG: "b" +// QUAL-DAG: "N::b" namespace { void func() { } } -// CHECK-DAG: "N::`anonymous namespace'::func +// UNQUAL-DAG: "func" +// QUAL-DAG: "N::`anonymous namespace'::func" } void _c(void) { @@ -19,19 +27,24 @@ void _c(void) { struct foo { int operator+(int); foo(){} -// CHECK-DAG: "foo::foo" +// UNQUAL-DAG: "foo" +// QUAL-DAG: "foo::foo" ~foo(){} -// CHECK-DAG: "foo::~foo" +// UNQUAL-DAG: "~foo" +// QUAL-DAG: "foo::~foo" foo(int i){} -// CHECK-DAG: "foo::foo" +// UNQUAL-DAG: "foo" +// QUAL-DAG: "foo::foo" foo(char *q){} -// CHECK-DAG: "foo::foo" +// UNQUAL-DAG: "foo" +// QUAL-DAG: "foo::foo" static foo* static_method() { return 0; } -// CHECK-DAG: "foo::static_method" +// UNQUAL-DAG: "static_method" +// QUAL-DAG: "foo::static_method" }; @@ -40,7 +53,8 @@ void use_foo() { foo::static_method(); } -// CHECK-DAG: "foo::operator+" +// UNQUAL-DAG: "operator+" +// QUAL-DAG: "foo::operator+" int foo::operator+(int a) { return a; } // PR17371 @@ -60,14 +74,20 @@ void OverloadedNewDelete::operator delete(void *) { } void OverloadedNewDelete::operator delete[](void *) { } int OverloadedNewDelete::operator+(int x) { return x; }; -// CHECK-DAG: "OverloadedNewDelete::operator new" -// CHECK-DAG: "OverloadedNewDelete::operator new[]" -// CHECK-DAG: "OverloadedNewDelete::operator delete" -// CHECK-DAG: "OverloadedNewDelete::operator delete[]" -// CHECK-DAG: "OverloadedNewDelete::operator+" +// UNQUAL-DAG: "operator new" +// UNQUAL-DAG: "operator new[]" +// UNQUAL-DAG: "operator delete" +// UNQUAL-DAG: "operator delete[]" +// UNQUAL-DAG: "operator+" +// QUAL-DAG: "OverloadedNewDelete::operator new" +// QUAL-DAG: "OverloadedNewDelete::operator new[]" +// QUAL-DAG: "OverloadedNewDelete::operator delete" +// QUAL-DAG: "OverloadedNewDelete::operator delete[]" +// QUAL-DAG: "OverloadedNewDelete::operator+" -template <void (*)(void)> + +template <typename T, void (*)(void)> void fn_tmpl() {} -template void fn_tmpl<freefunc>(); -// CHECK-DAG: "fn_tmpl" +template void fn_tmpl<int, freefunc>(); +// CHECK-DAG: "fn_tmpl<int,&freefunc>" diff --git a/test/CodeGenCXX/debug-info-cxx1y.cpp b/test/CodeGenCXX/debug-info-cxx1y.cpp index 37f95959911c..faf29d3ed11b 100644 --- a/test/CodeGenCXX/debug-info-cxx1y.cpp +++ b/test/CodeGenCXX/debug-info-cxx1y.cpp @@ -1,10 +1,10 @@ // RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm-only -std=c++14 -emit-llvm -debug-info-kind=limited %s -o - | FileCheck %s // CHECK: [[EMPTY:![0-9]*]] = !{} -// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "foo", +// CHECK: [[FOO:![0-9]+]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "foo", // CHECK-SAME: elements: [[EMPTY]] // FIXME: The context of this definition should be the CU/file scope, not the class. -// CHECK: !DISubprogram(name: "func", {{.*}} scope: !"_ZTS3foo" +// CHECK: !DISubprogram(name: "func", {{.*}} scope: [[FOO]] // CHECK-SAME: type: [[SUBROUTINE_TYPE:![0-9]*]] // CHECK-SAME: isDefinition: true // CHECK-SAME: declaration: [[FUNC_DECL:![0-9]*]] @@ -12,7 +12,7 @@ // CHECK: [[TYPE_LIST]] = !{[[INT:![0-9]*]]} // CHECK: [[INT]] = !DIBasicType(name: "int" // CHECK: [[FUNC_DECL]] = !DISubprogram(name: "func", -// CHECK-SAME: scope: !"_ZTS3foo" +// CHECK-SAME: scope: [[FOO]] // CHECK-SAME: type: [[SUBROUTINE_TYPE]] // CHECK-SAME: isDefinition: false diff --git a/test/CodeGenCXX/debug-info-enum-class.cpp b/test/CodeGenCXX/debug-info-enum-class.cpp index 71e6e2b2574e..44daf412d3ac 100644 --- a/test/CodeGenCXX/debug-info-enum-class.cpp +++ b/test/CodeGenCXX/debug-info-enum-class.cpp @@ -4,6 +4,7 @@ enum class A { A1=1 }; // underlying type is int by default enum class B: unsigned long { B1=1 }; // underlying type is unsigned long enum C { C1 = 1 }; enum D : short; // enum forward declaration +enum Z : int; A a; B b; C c; @@ -94,12 +95,17 @@ void f2(E) { // CHECK-NOT: offset: // CHECK-SAME: flags: DIFlagFwdDecl +// CHECK: !DICompositeType(tag: DW_TAG_enumeration_type, name: "Z" +// CHECK-NOT: scope: +// CHECK-SAME: flags: DIFlagFwdDecl +void fz() { Z z; } + namespace test5 { +// CHECK: [[TEST5:![0-9]+]] = !DINamespace(name: "test5" // CHECK: !DICompositeType(tag: DW_TAG_enumeration_type, name: "E" -// CHECK-SAME: scope: [[TEST5:![0-9]+]] +// CHECK-SAME: scope: [[TEST5]] // CHECK-SAME: flags: DIFlagFwdDecl // CHECK-SAME: identifier: "_ZTSN5test51EE" -// CHECK: [[TEST5]] = !DINamespace(name: "test5" enum E : int; void f1(E *) { } diff --git a/test/CodeGenCXX/debug-info-function-context.cpp b/test/CodeGenCXX/debug-info-function-context.cpp index 24f9f1bda639..1db62d96d5b6 100644 --- a/test/CodeGenCXX/debug-info-function-context.cpp +++ b/test/CodeGenCXX/debug-info-function-context.cpp @@ -26,11 +26,12 @@ int global_namespace_variable = 1; // function has the file as a context. // CHECK: ![[FILE:[0-9]+]] = !DIFile(filename: "{{.*}}context.cpp", -// CHECK: !DISubprogram(name: "member_function",{{.*}} scope: !"_ZTS1C",{{.*}} isDefinition: true +// CHECK: ![[C:[0-9]+]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "C", +// CHECK: ![[NS:.*]] = !DINamespace(name: "ns" +// CHECK: !DISubprogram(name: "member_function",{{.*}} scope: ![[C]],{{.*}} isDefinition: true -// CHECK: !DISubprogram(name: "static_member_function",{{.*}} scope: !"_ZTS1C",{{.*}} isDefinition: true +// CHECK: !DISubprogram(name: "static_member_function",{{.*}} scope: ![[C]],{{.*}} isDefinition: true // CHECK: !DISubprogram(name: "global_function",{{.*}} scope: ![[FILE]],{{.*}} isDefinition: true -// CHECK: !DISubprogram(name: "global_namespace_function",{{.*}} scope: ![[NS:[0-9]+]],{{.*}} isDefinition: true -// CHECK: ![[NS]] = !DINamespace(name: "ns" +// CHECK: !DISubprogram(name: "global_namespace_function",{{.*}} scope: ![[NS]],{{.*}} isDefinition: true diff --git a/test/CodeGenCXX/debug-info-global.cpp b/test/CodeGenCXX/debug-info-global.cpp index 920db82409bc..795602380d20 100644 --- a/test/CodeGenCXX/debug-info-global.cpp +++ b/test/CodeGenCXX/debug-info-global.cpp @@ -15,7 +15,7 @@ int f1() { // CHECK: [[GLOBALS]] = !{[[CNST:![0-9]*]]} -// CHECK: [[CNST]] = !DIGlobalVariable(name: "cnst", -// CHECK-SAME: scope: [[NS:![0-9]*]] +// CHECK: [[CNST]] = distinct !DIGlobalVariable(name: "cnst", +// CHECK-SAME: scope: [[NS:![0-9]*]] // CHECK: [[NS]] = !DINamespace(name: "ns" diff --git a/test/CodeGenCXX/debug-info-indirect-field-decl.cpp b/test/CodeGenCXX/debug-info-indirect-field-decl.cpp index 19f8d01e1ab6..70b233cac4dc 100644 --- a/test/CodeGenCXX/debug-info-indirect-field-decl.cpp +++ b/test/CodeGenCXX/debug-info-indirect-field-decl.cpp @@ -9,9 +9,10 @@ struct Bar { int i1; // CHECK: ![[INT:[0-9]+]] = !DIBasicType(name: "int" // CHECK: !DIDerivedType(tag: DW_TAG_member, scope: - // CHECK-SAME: line: [[@LINE+3]] - // CHECK-SAME: baseType: !"_ZTSN3BarUt_E" + // CHECK-SAME: line: [[@LINE+4]] + // CHECK-SAME: baseType: ![[UNION:[0-9]+]] // CHECK-SAME: size: 32, align: 32, offset: 32 + // CHECK: ![[UNION]] = distinct !DICompositeType(tag: DW_TAG_union_type,{{.*}} identifier: "_ZTSN3BarUt_E") union { // CHECK: !DIDerivedType(tag: DW_TAG_member, name: "i2", // CHECK-SAME: line: [[@LINE+5]] diff --git a/test/CodeGenCXX/debug-info-limited.cpp b/test/CodeGenCXX/debug-info-limited.cpp index b209e3a850de..4467d20f3de4 100644 --- a/test/CodeGenCXX/debug-info-limited.cpp +++ b/test/CodeGenCXX/debug-info-limited.cpp @@ -1,4 +1,5 @@ // RUN: %clang -flimit-debug-info -emit-llvm -g -S %s -o - | FileCheck %s +// RUN: %clang -flimit-debug-info -emit-llvm -g -S %s -o - | FileCheck --check-prefix=CHECK-C %s // CHECK: !DICompositeType(tag: DW_TAG_class_type, name: "A" // CHECK-NOT: DIFlagFwdDecl @@ -27,8 +28,8 @@ int baz(B *b) { } -// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "C" -// CHECK-SAME: flags: DIFlagFwdDecl +// CHECK-C: !DICompositeType(tag: DW_TAG_structure_type, name: "C" +// CHECK-C-SAME: flags: DIFlagFwdDecl struct C { }; diff --git a/test/CodeGenCXX/debug-info-line-if.cpp b/test/CodeGenCXX/debug-info-line-if.cpp index 29806351c94c..b3f9c32e0911 100644 --- a/test/CodeGenCXX/debug-info-line-if.cpp +++ b/test/CodeGenCXX/debug-info-line-if.cpp @@ -15,7 +15,7 @@ int main() { // CHECK: br label // CHECK: br label - // CHECK: br label {{.*}}, !dbg [[DBG1:!.*]] + // CHECK: br label {{.*}}, !dbg [[DBG1:![0-9]*]], !llvm.loop [[L1:![0-9]*]] #line 200 while (a) @@ -25,7 +25,7 @@ int main() { ++a; // CHECK: add nsw{{.*}}, 1 // CHECK: br label - // CHECK: br label {{.*}}, !dbg [[DBG2:!.*]] + // CHECK: br label {{.*}}, !dbg [[DBG2:![0-9]*]], !llvm.loop [[L2:![0-9]*]] #line 300 for (; a; ) @@ -35,7 +35,7 @@ int main() { ++a; // CHECK: add nsw{{.*}}, 1 // CHECK: br label - // CHECK: br label {{.*}}, !dbg [[DBG3:!.*]] + // CHECK: br label {{.*}}, !dbg [[DBG3:![0-9]*]], !llvm.loop [[L3:![0-9]*]] #line 400 int x[] = {1, 2}; @@ -46,10 +46,22 @@ int main() { ++a; // CHECK: add nsw{{.*}}, 1 // CHECK: br label - // CHECK: br label {{.*}}, !dbg [[DBG4:!.*]] + // CHECK: br label {{.*}}, !dbg [[DBG4:![0-9]*]], !llvm.loop [[L4:![0-9]*]] - // CHECK: [[DBG1]] = !DILocation(line: 100, scope: !{{.*}}) - // CHECK: [[DBG2]] = !DILocation(line: 200, scope: !{{.*}}) - // CHECK: [[DBG3]] = !DILocation(line: 300, scope: !{{.*}}) - // CHECK: [[DBG4]] = !DILocation(line: 401, scope: !{{.*}}) + // CHECK-DAG: [[DBG1]] = !DILocation(line: 100, scope: !{{.*}}) + // CHECK-DAG: [[DBG2]] = !DILocation(line: 200, scope: !{{.*}}) + // CHECK-DAG: [[DBG3]] = !DILocation(line: 300, scope: !{{.*}}) + // CHECK-DAG: [[DBG4]] = !DILocation(line: 401, scope: !{{.*}}) + + // CHECK-DAG: [[L1]] = distinct !{[[L1]], [[LDBG1:![0-9]*]]} + // CHECK-DAG: [[LDBG1]] = !DILocation(line: 100, scope: !{{.*}}) + + // CHECK-DAG: [[L2]] = distinct !{[[L2]], [[LDBG2:![0-9]*]]} + // CHECK-DAG: [[LDBG2]] = !DILocation(line: 200, scope: !{{.*}}) + + // CHECK-DAG: [[L3]] = distinct !{[[L3]], [[LDBG3:![0-9]*]]} + // CHECK-DAG: [[LDBG3]] = !DILocation(line: 300, scope: !{{.*}}) + + // CHECK-DAG: [[L4]] = distinct !{[[L4]], [[LDBG4:![0-9]*]]} + // CHECK-DAG: [[LDBG4]] = !DILocation(line: 401, scope: !{{.*}}) } diff --git a/test/CodeGenCXX/debug-info-line.cpp b/test/CodeGenCXX/debug-info-line.cpp index 9fb6ba8ac70e..11653040109c 100644 --- a/test/CodeGenCXX/debug-info-line.cpp +++ b/test/CodeGenCXX/debug-info-line.cpp @@ -1,8 +1,6 @@ -// RUN: %clang_cc1 -w -debug-info-kind=line-tables-only -std=c++11 -fexceptions -fcxx-exceptions -S -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -w -debug-info-kind=line-tables-only -std=c++11 -fexceptions -fcxx-exceptions -S -emit-llvm %s -o - -triple %itanium_abi_triple | FileCheck %s // RUN: %clang_cc1 -w -debug-info-kind=line-tables-only -std=c++11 -fexceptions -fcxx-exceptions -S -emit-llvm %s -o - -triple i686-linux-gnu | FileCheck %s -// XFAIL: win32 - int &src(); int *sink(); extern "C" __complex float complex_src(); diff --git a/test/CodeGenCXX/debug-info-member-call.cpp b/test/CodeGenCXX/debug-info-member-call.cpp new file mode 100644 index 000000000000..3b5adb8e4b82 --- /dev/null +++ b/test/CodeGenCXX/debug-info-member-call.cpp @@ -0,0 +1,24 @@ +// RUN: %clang_cc1 -triple x86_64-unknown_unknown -emit-llvm -debug-info-kind=standalone -dwarf-column-info %s -o - | FileCheck %s +void ext(); + +struct Bar { + void bar() { ext(); } +}; + +struct Foo { + Bar *b; + + Bar *foo() { return b; } +}; + +void test(Foo *f) { + f->foo()->bar(); +} + +// CHECK-LABEL: @_Z4testP3Foo +// CHECK: call {{.*}} @_ZN3Foo3fooEv{{.*}}, !dbg ![[CALL1LOC:.*]] +// CHECK: call void @_ZN3Bar3barEv{{.*}}, !dbg ![[CALL2LOC:.*]] + +// CHECK: ![[CALL1LOC]] = !DILocation(line: [[LINE:[0-9]+]], column: 6, +// CHECK: ![[CALL2LOC]] = !DILocation(line: [[LINE]], column: 13, + diff --git a/test/CodeGenCXX/debug-info-method.cpp b/test/CodeGenCXX/debug-info-method.cpp index bdd14e0b735d..73d8b928269a 100644 --- a/test/CodeGenCXX/debug-info-method.cpp +++ b/test/CodeGenCXX/debug-info-method.cpp @@ -1,12 +1,12 @@ // RUN: %clang_cc1 -emit-llvm -triple %itanium_abi_triple -std=c++11 -debug-info-kind=limited %s -o - | FileCheck %s -// CHECK: !DICompositeType(tag: DW_TAG_class_type, name: "A",{{.*}} identifier: "_ZTS1A") +// CHECK: ![[A:[0-9]+]] = distinct !DICompositeType(tag: DW_TAG_class_type, name: "A",{{.*}} identifier: "_ZTS1A") // CHECK: !DISubprogram(name: "foo", linkageName: "_ZN1A3fooEiS_3$_0" // CHECK-SAME: DIFlagProtected -// CHECK: ![[THISTYPE:[0-9]+]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !"_ZTS1A" +// CHECK: ![[THISTYPE:[0-9]+]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[A]] // CHECK-SAME: DIFlagArtificial // CHECK: !DIDerivedType(tag: DW_TAG_ptr_to_member_type // CHECK: !DIDerivedType(tag: DW_TAG_ptr_to_member_type, baseType: ![[MEMFUNTYPE:[0-9]+]] -// CHECK: ![[MEMFUNTYPE]] = !DISubroutineType(types: ![[MEMFUNARGS:[0-9]+]]) +// CHECK: ![[MEMFUNTYPE]] = !DISubroutineType({{(cc: DW_CC_BORLAND_thiscall, )?}}types: ![[MEMFUNARGS:[0-9]+]]) // CHECK: ![[MEMFUNARGS]] = {{.*}}, ![[THISTYPE]], // CHECK: !DILocalVariable(name: "this", arg: 1 // CHECK: !DILocalVariable(arg: 2 diff --git a/test/CodeGenCXX/debug-info-ms-abi.cpp b/test/CodeGenCXX/debug-info-ms-abi.cpp new file mode 100644 index 000000000000..a146ce94176e --- /dev/null +++ b/test/CodeGenCXX/debug-info-ms-abi.cpp @@ -0,0 +1,30 @@ +// RUN: %clang_cc1 %s -triple=i686-pc-windows-msvc -debug-info-kind=limited -emit-llvm -o - | FileCheck %s + +// Tests that certain miscellaneous features work in the MS ABI. + +struct Foo { + virtual void f(); + virtual void g(); + virtual void h(); + struct Nested {}; +}; +Foo f; +Foo::Nested n; + +// CHECK: ![[Foo:[^ ]*]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "Foo", +// CHECK-SAME: identifier: ".?AUFoo@@" + +// CHECK: !DISubprogram(name: "f", +// CHECK-SAME: containingType: ![[Foo]], virtuality: DW_VIRTUALITY_virtual, virtualIndex: 0, +// CHECK-SAME: flags: DIFlagPrototyped | DIFlagIntroducedVirtual, + +// CHECK: !DISubprogram(name: "g", +// CHECK-SAME: containingType: ![[Foo]], virtuality: DW_VIRTUALITY_virtual, virtualIndex: 1, +// CHECK-SAME: flags: DIFlagPrototyped | DIFlagIntroducedVirtual, + +// CHECK: !DISubprogram(name: "h", +// CHECK-SAME: containingType: ![[Foo]], virtuality: DW_VIRTUALITY_virtual, virtualIndex: 2, +// CHECK-SAME: flags: DIFlagPrototyped | DIFlagIntroducedVirtual, + +// CHECK: distinct !DICompositeType(tag: DW_TAG_structure_type, name: "Nested", +// CHECK-SAME: identifier: ".?AUNested@Foo@@" diff --git a/test/CodeGenCXX/debug-info-ms-anonymous-tag.cpp b/test/CodeGenCXX/debug-info-ms-anonymous-tag.cpp new file mode 100644 index 000000000000..cef1eb8c5a09 --- /dev/null +++ b/test/CodeGenCXX/debug-info-ms-anonymous-tag.cpp @@ -0,0 +1,20 @@ +// RUN: %clang_cc1 -triple x86_64-pc-win32 -debug-info-kind=limited -gcodeview %s -emit-llvm -o - | FileCheck %s + +typedef struct { +} test1; + +test1 gv1; +// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "test1" + +struct { +} test2; +void *use_test2 = &test2; + +// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "<unnamed-type-test2>" + +typedef struct { +} *test3; +test3 gv3; +void *use_test3 = &gv3; + +// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "<unnamed-type-test3>" diff --git a/test/CodeGenCXX/debug-info-ms-bitfields.cpp b/test/CodeGenCXX/debug-info-ms-bitfields.cpp new file mode 100644 index 000000000000..07d4c0c6c78a --- /dev/null +++ b/test/CodeGenCXX/debug-info-ms-bitfields.cpp @@ -0,0 +1,10 @@ +// RUN: %clang_cc1 -triple x86_64-pc-win32 -debug-info-kind=limited -gcodeview %s -emit-llvm -o - | FileCheck %s + +#pragma pack(1) +struct S { + char : 8; + short : 8; + short x : 8; +} s; + +// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "x", {{.*}}, size: 8, align: 16, offset: 16, flags: DIFlagBitField, extraData: i64 8) diff --git a/test/CodeGenCXX/debug-info-ms-ptr-to-member.cpp b/test/CodeGenCXX/debug-info-ms-ptr-to-member.cpp new file mode 100644 index 000000000000..4b9f2a146896 --- /dev/null +++ b/test/CodeGenCXX/debug-info-ms-ptr-to-member.cpp @@ -0,0 +1,52 @@ +// RUN: %clang_cc1 -triple x86_64-windows -debug-info-kind=limited -gcodeview %s -emit-llvm -o - | FileCheck %s + +// Test member pointer inheritance models. + +struct A { int a; }; +struct B { int b; }; +struct C : A, B { int c; }; +struct D : virtual C { int d; }; +struct E; +int A::*pmd_a; +int C::*pmd_b; +int D::*pmd_c; +int E::*pmd_d; +void (A::*pmf_a)(); +void (C::*pmf_b)(); +void (D::*pmf_c)(); +void (E::*pmf_d)(); + +// Test incomplete MPTs, which don't have inheritance models. + +struct Incomplete; +int Incomplete::**ppmd; +void (Incomplete::**ppmf)(); + +// CHECK: distinct !DIGlobalVariable(name: "pmd_a", {{.*}} type: ![[pmd_a:[^, ]*]], {{.*}}) +// CHECK: ![[pmd_a]] = !DIDerivedType(tag: DW_TAG_ptr_to_member_type, baseType: !{{.*}}, size: 32, flags: DIFlagSingleInheritance, {{.*}}) +// CHECK: distinct !DIGlobalVariable(name: "pmd_b", {{.*}} type: ![[pmd_b:[^, ]*]], {{.*}}) +// CHECK: ![[pmd_b]] = !DIDerivedType(tag: DW_TAG_ptr_to_member_type, baseType: !{{.*}}, size: 32, flags: DIFlagMultipleInheritance, {{.*}}) +// CHECK: distinct !DIGlobalVariable(name: "pmd_c", {{.*}} type: ![[pmd_c:[^, ]*]], {{.*}}) +// CHECK: ![[pmd_c]] = !DIDerivedType(tag: DW_TAG_ptr_to_member_type, baseType: !{{.*}}, size: 64, flags: DIFlagVirtualInheritance, {{.*}}) +// CHECK: distinct !DIGlobalVariable(name: "pmd_d", {{.*}} type: ![[pmd_d:[^, ]*]], {{.*}}) +// CHECK: ![[pmd_d]] = !DIDerivedType(tag: DW_TAG_ptr_to_member_type, baseType: !{{.*}}, size: 96, +// CHECK-NOT: flags: +// CHECK-SAME: ){{$}} + +// CHECK: distinct !DIGlobalVariable(name: "pmf_a", {{.*}} type: ![[pmf_a:[^, ]*]], {{.*}}) +// CHECK: ![[pmf_a]] = !DIDerivedType(tag: DW_TAG_ptr_to_member_type, baseType: !{{.*}}, size: 64, flags: DIFlagSingleInheritance, {{.*}}) +// CHECK: distinct !DIGlobalVariable(name: "pmf_b", {{.*}} type: ![[pmf_b:[^, ]*]], {{.*}}) +// CHECK: ![[pmf_b]] = !DIDerivedType(tag: DW_TAG_ptr_to_member_type, baseType: !{{.*}}, size: 128, flags: DIFlagMultipleInheritance, {{.*}}) +// CHECK: distinct !DIGlobalVariable(name: "pmf_c", {{.*}} type: ![[pmf_c:[^, ]*]], {{.*}}) +// CHECK: ![[pmf_c]] = !DIDerivedType(tag: DW_TAG_ptr_to_member_type, baseType: !{{.*}}, size: 128, flags: DIFlagVirtualInheritance, {{.*}}) +// CHECK: distinct !DIGlobalVariable(name: "pmf_d", {{.*}} type: ![[pmf_d:[^, ]*]], {{.*}}) +// CHECK: ![[pmf_d]] = !DIDerivedType(tag: DW_TAG_ptr_to_member_type, baseType: !{{.*}}, size: 192, +// CHECK-NOT: flags: +// CHECK-SAME: ){{$}} + +// CHECK: distinct !DIGlobalVariable(name: "ppmd", {{.*}} type: ![[ppmd:[^, ]*]], {{.*}}) +// CHECK: ![[ppmd]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[ppmd2:[^ ]*]], size: 64, align: 64) +// CHECK: ![[ppmd2]] = !DIDerivedType(tag: DW_TAG_ptr_to_member_type, baseType: !{{[0-9]*}}, extraData: !{{[0-9]*}}){{$}} +// CHECK: distinct !DIGlobalVariable(name: "ppmf", {{.*}} type: ![[ppmf:[^, ]*]], {{.*}}) +// CHECK: ![[ppmf]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[ppmf2:[^ ]*]], size: 64, align: 64) +// CHECK: ![[ppmf2]] = !DIDerivedType(tag: DW_TAG_ptr_to_member_type, baseType: !{{[0-9]*}}, extraData: !{{[0-9]*}}){{$}} diff --git a/test/CodeGenCXX/debug-info-namespace.cpp b/test/CodeGenCXX/debug-info-namespace.cpp index 4933ae967452..060a5cea636c 100644 --- a/test/CodeGenCXX/debug-info-namespace.cpp +++ b/test/CodeGenCXX/debug-info-namespace.cpp @@ -57,57 +57,57 @@ void B::func_fwd() {} // CHECK: [[CU:![0-9]+]] = distinct !DICompileUnit( // CHECK-SAME: imports: [[MODULES:![0-9]*]] -// CHECK: [[FOO:![0-9]+]] = !DICompositeType(tag: DW_TAG_structure_type, name: "foo", -// CHECK-SAME: line: 5 -// CHECK-SAME: DIFlagFwdDecl -// CHECK: [[FOOCPP:![0-9]+]] = !DIFile(filename: "foo.cpp" -// CHECK: [[NS:![0-9]+]] = !DINamespace(name: "B", scope: [[CTXT:![0-9]+]], file: [[FOOCPP]], line: 1) +// CHECK: [[I:![0-9]+]] = distinct !DIGlobalVariable(name: "i",{{.*}} scope: [[NS:![0-9]+]], +// CHECK: [[NS]] = !DINamespace(name: "B", scope: [[CTXT:![0-9]+]], file: [[FOOCPP:![0-9]+]], line: 1) +// CHECK: [[FOOCPP]] = !DIFile(filename: "foo.cpp" // CHECK: [[CTXT]] = !DINamespace(name: "A", scope: null, file: [[FILE:![0-9]+]], line: 5) // CHECK: [[FILE]] = !DIFile(filename: "{{.*}}debug-info-namespace.cpp", -// CHECK: [[BAR:![0-9]+]] = !DICompositeType(tag: DW_TAG_structure_type, name: "bar", -// CHECK-SAME: line: 6 -// CHECK-SAME: DIFlagFwdDecl -// CHECK: [[F1:![0-9]+]] = distinct !DISubprogram(name: "f1",{{.*}} line: 4 -// CHECK-SAME: isDefinition: true -// CHECK: [[FUNC:![0-9]+]] = distinct !DISubprogram(name: "func",{{.*}} isDefinition: true -// CHECK: [[FUNC_FWD:![0-9]+]] = distinct !DISubprogram(name: "func_fwd",{{.*}} line: 47,{{.*}} isDefinition: true -// CHECK: [[I:![0-9]+]] = !DIGlobalVariable(name: "i",{{.*}} scope: [[NS]], -// CHECK: [[VAR_FWD:![0-9]+]] = !DIGlobalVariable(name: "var_fwd",{{.*}} scope: [[NS]], -// CHECK-SAME: line: 44 -// CHECK-SAME: isDefinition: true - +// CHECK: [[VAR_FWD:![0-9]+]] = distinct !DIGlobalVariable(name: "var_fwd",{{.*}} scope: [[NS]], +// CHECK-SAME: line: 44 +// CHECK-SAME: isDefinition: true // CHECK: [[MODULES]] = !{[[M1:![0-9]+]], [[M2:![0-9]+]], [[M3:![0-9]+]], [[M4:![0-9]+]], [[M5:![0-9]+]], [[M6:![0-9]+]], [[M7:![0-9]+]], [[M8:![0-9]+]], [[M9:![0-9]+]], [[M10:![0-9]+]], [[M11:![0-9]+]], [[M12:![0-9]+]], [[M13:![0-9]+]], [[M14:![0-9]+]], [[M15:![0-9]+]], [[M16:![0-9]+]], [[M17:![0-9]+]]} // CHECK: [[M1]] = !DIImportedEntity(tag: DW_TAG_imported_module, scope: [[CTXT]], entity: [[NS]], line: 15) + // CHECK: [[M2]] = !DIImportedEntity(tag: DW_TAG_imported_module, scope: [[CU]], entity: [[CTXT]], // CHECK: [[M3]] = !DIImportedEntity(tag: DW_TAG_imported_declaration, name: "E", scope: [[CU]], entity: [[CTXT]], line: 19) // CHECK: [[M4]] = !DIImportedEntity(tag: DW_TAG_imported_module, scope: [[LEX2:![0-9]+]], entity: [[NS]], line: 23) // CHECK: [[LEX2]] = distinct !DILexicalBlock(scope: [[LEX1:![0-9]+]], file: [[FOOCPP]], -// CHECK: [[LEX1]] = distinct !DILexicalBlock(scope: [[FUNC]], file: [[FOOCPP]], -// CHECK: [[M5]] = !DIImportedEntity(tag: DW_TAG_imported_module, scope: [[FUNC]], entity: [[CTXT]], -// CHECK: [[M6]] = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: [[FUNC]], entity: [[FOO:!"_ZTSN1A1B3fooE"]], line: 27) -// CHECK: [[M7]] = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: [[FUNC]], entity: [[BAR:!"_ZTSN1A1B3barE"]] -// CHECK: [[M8]] = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: [[FUNC]], entity: [[F1]] +// CHECK: [[LEX1]] = distinct !DILexicalBlock(scope: [[FUNC:![0-9]+]], file: [[FOOCPP]], + +// CHECK: [[FUNC:![0-9]+]] = distinct !DISubprogram(name: "func",{{.*}} isDefinition: true +// CHECK: [[M5]] = !DIImportedEntity(tag: DW_TAG_imported_module, scope: [[FUNC]], entity: [[CTXT:![0-9]+]], +// CHECK: [[M6]] = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: [[FUNC]], entity: [[FOO:![0-9]+]], line: 27) +// CHECK: [[FOO]] = !DICompositeType(tag: DW_TAG_structure_type, name: "foo", +// CHECK-SAME: line: 5 +// CHECK-SAME: DIFlagFwdDecl +// CHECK: [[M7]] = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: [[FUNC]], entity: [[BAR:![0-9]+]] +// CHECK: [[BAR]] = !DICompositeType(tag: DW_TAG_structure_type, name: "bar", +// CHECK-SAME: line: 6 +// CHECK-SAME: DIFlagFwdDecl + +// CHECK: [[M8]] = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: [[FUNC]], entity: [[F1:![0-9]+]] +// CHECK: [[F1:![0-9]+]] = distinct !DISubprogram(name: "f1",{{.*}} line: 4 +// CHECK-SAME: isDefinition: true // CHECK: [[M9]] = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: [[FUNC]], entity: [[I]] // CHECK: [[M10]] = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: [[FUNC]], entity: [[BAZ:![0-9]+]] // CHECK: [[BAZ]] = !DIDerivedType(tag: DW_TAG_typedef, name: "baz", scope: [[NS]], file: [[FOOCPP]], -// CHECK-SAME: baseType: !"_ZTSN1A1B3barE" +// CHECK-SAME: baseType: [[BAR]] // CHECK: [[M11]] = !DIImportedEntity(tag: DW_TAG_imported_declaration, name: "X", scope: [[FUNC]], entity: [[CTXT]] // CHECK: [[M12]] = !DIImportedEntity(tag: DW_TAG_imported_declaration, name: "Y", scope: [[FUNC]], entity: [[M11]] // CHECK: [[M13]] = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: [[FUNC]], entity: [[VAR_DECL:![0-9]+]] -// CHECK: [[VAR_DECL]] = !DIGlobalVariable(name: "var_decl", linkageName: "_ZN1A1B8var_declE", scope: [[NS]],{{.*}} line: 8, +// CHECK: [[VAR_DECL]] = !DIGlobalVariable(name: "var_decl", linkageName: "{{[^"]*var_decl[^"]*}}", scope: [[NS]],{{.*}} line: 8, // CHECK: [[M14]] = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: [[FUNC]], entity: [[FUNC_DECL:![0-9]+]] // CHECK: [[FUNC_DECL]] = !DISubprogram(name: "func_decl", // CHECK-SAME: scope: [[NS]], file: [[FOOCPP]], line: 9 // CHECK: [[M15]] = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: [[FUNC]], entity: [[VAR_FWD:![0-9]+]] // CHECK: [[M16]] = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: [[FUNC]], entity: [[FUNC_FWD:![0-9]+]] +// CHECK: [[FUNC_FWD]] = distinct !DISubprogram(name: "func_fwd",{{.*}} line: 47,{{.*}} isDefinition: true // CHECK: [[M17]] = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: [[CTXT]], entity: [[I]] // CHECK-GMLT: [[CU:![0-9]+]] = distinct !DICompileUnit( -// CHECK-GMLT-SAME: emissionKind: 2, +// CHECK-GMLT-SAME: emissionKind: LineTablesOnly, // CHECK-GMLT-NOT: imports: // CHECK-NOLIMIT: !DICompositeType(tag: DW_TAG_structure_type, name: "bar",{{.*}} line: 6, // CHECK-NOLIMIT-NOT: DIFlagFwdDecl // CHECK-NOLIMIT-SAME: ){{$}} - -// REQUIRES: dw2 diff --git a/test/CodeGenCXX/debug-info-nodebug.cpp b/test/CodeGenCXX/debug-info-nodebug.cpp new file mode 100644 index 000000000000..9f140efaed6f --- /dev/null +++ b/test/CodeGenCXX/debug-info-nodebug.cpp @@ -0,0 +1,55 @@ +// RUN: %clang_cc1 -DSETNODEBUG=0 -emit-llvm -debug-info-kind=limited %s -o - | FileCheck %s --check-prefix=YESINFO +// RUN: %clang_cc1 -DSETNODEBUG=1 -emit-llvm -debug-info-kind=limited %s -o - | FileCheck %s --check-prefix=NOINFO + +#if SETNODEBUG +#define NODEBUG __attribute__((nodebug)) +#else +#define NODEBUG +#endif + +// Const global variable. Use it so it gets emitted. +NODEBUG static const int const_global_int_def = 1; +void func1(int); +void func2() { func1(const_global_int_def); } +// YESINFO-DAG: !DIGlobalVariable(name: "const_global_int_def" +// NOINFO-NOT: !DIGlobalVariable(name: "const_global_int_def" + +// Global variable with a more involved type. +// If the variable has no debug info, the type should not appear either. +struct S1 { + int a; + int b; +}; +NODEBUG S1 global_struct = { 2, 3 }; +// YESINFO-DAG: !DICompositeType({{.*}} name: "S1" +// NOINFO-NOT: !DICompositeType({{.*}} name: "S1" +// YESINFO-DAG: !DIGlobalVariable(name: "global_struct" +// NOINFO-NOT: !DIGlobalVariable(name: "global_struct" + +// Static data members. Const member needs a use. +// Also the class as a whole needs a use, so that we produce debug info for +// the entire class (iterating over the members, demonstrably skipping those +// with 'nodebug'). +struct S2 { + NODEBUG static int static_member; + NODEBUG static const int static_const_member = 4; +}; +int S2::static_member = 5; +void func3() { + S2 junk; + func1(S2::static_const_member); +} +// YESINFO-DAG: !DIGlobalVariable(name: "static_member" +// NOINFO-NOT: !DIGlobalVariable(name: "static_member" +// YESINFO-DAG: !DIDerivedType({{.*}} name: "static_const_member" +// NOINFO-NOT: !DIDerivedType({{.*}} name: "static_const_member" + +// Function-local static and auto variables. +void func4() { + NODEBUG static int static_local = 6; + NODEBUG int normal_local = 7; +} +// YESINFO-DAG: !DIGlobalVariable(name: "static_local" +// NOINFO-NOT: !DIGlobalVariable(name: "static_local" +// YESINFO-DAG: !DILocalVariable(name: "normal_local" +// NOINFO-NOT: !DILocalVariable(name: "normal_local" diff --git a/test/CodeGenCXX/debug-info-ptr-to-member-function.cpp b/test/CodeGenCXX/debug-info-ptr-to-member-function.cpp index cac16b600890..a7e02e481320 100644 --- a/test/CodeGenCXX/debug-info-ptr-to-member-function.cpp +++ b/test/CodeGenCXX/debug-info-ptr-to-member-function.cpp @@ -7,15 +7,15 @@ struct T { void foo(int (T::*method)()) {} -// A pointer to a member function is a pair of function- and this-pointer. -// CHECK: !DIDerivedType(tag: DW_TAG_ptr_to_member_type, -// DARWIN-X64-SAME: size: 128 -// WIN32-X64-SAME: size: 64 - struct Incomplete; int (Incomplete::**bar)(); +// A pointer to a member function is a pair of function- and this-pointer. // CHECK: !DIDerivedType(tag: DW_TAG_ptr_to_member_type, // DARWIN-X64-SAME: size: 128 // WIN32-X64-NOT: size: // CHECK-SAME: extraData: {{.*}}) + +// CHECK: !DIDerivedType(tag: DW_TAG_ptr_to_member_type, +// DARWIN-X64-SAME: size: 128 +// WIN32-X64-SAME: size: 64 diff --git a/test/CodeGenCXX/debug-info-scoped-class.cpp b/test/CodeGenCXX/debug-info-scoped-class.cpp new file mode 100644 index 000000000000..de4aee9a1b44 --- /dev/null +++ b/test/CodeGenCXX/debug-info-scoped-class.cpp @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 -emit-llvm -debug-info-kind=standalone -std=c++11 \ +// RUN: -triple thumbv7-apple-ios %s -o - | FileCheck %s + +// This forward-declared scoped enum will be created while building its own +// declcontext. Make sure it is only emitted once. + +struct A { + enum class Return; + Return f1(); +}; +A::Return* f2() {} + +// CHECK: !DICompositeType(tag: DW_TAG_enumeration_type, name: "Return", +// CHECK-SAME: flags: DIFlagFwdDecl, +// CHECK-NOT: tag: DW_TAG_enumeration_type, name: "Return" diff --git a/test/CodeGenCXX/debug-info-static-member.cpp b/test/CodeGenCXX/debug-info-static-member.cpp index 8e5207d5c30b..ed8ae015cfc3 100644 --- a/test/CodeGenCXX/debug-info-static-member.cpp +++ b/test/CodeGenCXX/debug-info-static-member.cpp @@ -1,4 +1,6 @@ // RUN: %clangxx -target x86_64-unknown-unknown -g %s -emit-llvm -S -o - | FileCheck %s +// RUN: %clangxx -target x86_64-unknown-unknown -g -std=c++98 %s -emit-llvm -S -o - | FileCheck %s +// RUN: %clangxx -target x86_64-unknown-unknown -g -std=c++11 %s -emit-llvm -S -o - | FileCheck %s // PR14471 enum X { @@ -10,7 +12,11 @@ class C const static bool const_a = true; protected: static int b; +#if __cplusplus >= 201103L + constexpr static float const_b = 3.14; +#else const static float const_b = 3.14; +#endif public: static int c; const static int const_c = 18; @@ -18,37 +24,35 @@ public: static X x_a; }; -int C::a = 4; -int C::b = 2; -int C::c = 1; - -int main() -{ - C instance_C; - instance_C.d = 8; - return C::c; -} - // The definition of C::a drives the emission of class C, which is // why the definition of "a" comes before the declarations while // "b" and "c" come after. // CHECK: !DICompositeType(tag: DW_TAG_enumeration_type, name: "X"{{.*}}, identifier: "_ZTS1X") -// CHECK: !DICompositeType(tag: DW_TAG_class_type, name: "C"{{.*}}, identifier: "_ZTS1C") -// -// CHECK: ![[DECL_A:[0-9]+]] = !DIDerivedType(tag: DW_TAG_member, name: "a" +// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "anon_static_decl_struct" +// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "anon_static_decl_var" +// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "static_decl_templ<int>" +// CHECK-NOT: DIFlagFwdDecl +// CHECK-SAME: ){{$}} +// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "static_decl_templ_var" + +// CHECK: !DIGlobalVariable(name: "a", {{.*}}variable: i32* @_ZN1C1aE, declaration: ![[DECL_A:[0-9]+]]) +int C::a = 4; +// CHECK: ![[DECL_A]] = !DIDerivedType(tag: DW_TAG_member, name: "a" // CHECK-NOT: size: // CHECK-NOT: align: // CHECK-NOT: offset: // CHECK-SAME: flags: DIFlagStaticMember) // +// CHECK: !DICompositeType(tag: DW_TAG_class_type, name: "C"{{.*}}, identifier: "_ZTS1C") +// // CHECK: !DIDerivedType(tag: DW_TAG_member, name: "const_a" // CHECK-NOT: size: // CHECK-NOT: align: // CHECK-NOT: offset: // CHECK-SAME: flags: DIFlagStaticMember, // CHECK-SAME: extraData: i1 true) -// + // CHECK: ![[DECL_B:[0-9]+]] = !DIDerivedType(tag: DW_TAG_member, name: "b" // CHECK-NOT: size: // CHECK-NOT: align: @@ -61,7 +65,7 @@ int main() // CHECK-NOT: offset: // CHECK-SAME: flags: DIFlagProtected | DIFlagStaticMember, // CHECK-SAME: extraData: float 0x{{.*}}) -// + // CHECK: ![[DECL_C:[0-9]+]] = !DIDerivedType(tag: DW_TAG_member, name: "c" // CHECK-NOT: size: // CHECK-NOT: align: @@ -78,12 +82,19 @@ int main() // CHECK: !DIDerivedType(tag: DW_TAG_member, name: "x_a" // CHECK-SAME: flags: DIFlagPublic | DIFlagStaticMember) -// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "static_decl_templ<int>" -// CHECK-NOT: DIFlagFwdDecl -// CHECK-SAME: ){{$}} -// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "static_decl_templ_var" +// CHECK: !DIGlobalVariable(name: "b", {{.*}}variable: i32* @_ZN1C1bE, declaration: ![[DECL_B]]) +int C::b = 2; +// CHECK: !DIGlobalVariable(name: "c", {{.*}}variable: i32* @_ZN1C1cE, declaration: ![[DECL_C]]) +int C::c = 1; -// CHECK: [[NS_X:![0-9]+]] = !DINamespace(name: "x" +int main() +{ + C instance_C; + instance_C.d = 8; + return C::c; +} + +// CHECK-NOT: !DIGlobalVariable(name: "anon_static_decl_var" // Test this in an anonymous namespace to ensure the type is retained even when // it doesn't get automatically retained by the string type reference machinery. @@ -94,9 +105,6 @@ struct anon_static_decl_struct { } -// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "anon_static_decl_struct" -// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "anon_static_decl_var" - int ref() { return anon_static_decl_struct::anon_static_decl_var; } @@ -113,12 +121,6 @@ int static_decl_templ_ref() { return static_decl_templ<int>::static_decl_templ_var; } -// CHECK: !DIGlobalVariable(name: "a", {{.*}}variable: i32* @_ZN1C1aE, declaration: ![[DECL_A]]) -// CHECK: !DIGlobalVariable(name: "b", {{.*}}variable: i32* @_ZN1C1bE, declaration: ![[DECL_B]]) -// CHECK: !DIGlobalVariable(name: "c", {{.*}}variable: i32* @_ZN1C1cE, declaration: ![[DECL_C]]) - -// CHECK-NOT: !DIGlobalVariable(name: "anon_static_decl_var" - // Verify that even when a static member declaration is created lazily when // creating the definition, the declaration line is that of the canonical // declaration, not the definition. Also, since we look at the canonical @@ -135,10 +137,10 @@ const int V::const_va; namespace x { struct y { +// CHECK: !DIGlobalVariable(name: "z", +// CHECK-SAME: scope: [[NS_X:![0-9]+]] +// CHECK: [[NS_X]] = !DINamespace(name: "x" static int z; }; int y::z; } - -// CHECK: !DIGlobalVariable(name: "z", -// CHECK-SAME: scope: [[NS_X]] diff --git a/test/CodeGenCXX/debug-info-template-explicit-specialization.cpp b/test/CodeGenCXX/debug-info-template-explicit-specialization.cpp index 04c63ae2ff24..08146c25263b 100644 --- a/test/CodeGenCXX/debug-info-template-explicit-specialization.cpp +++ b/test/CodeGenCXX/debug-info-template-explicit-specialization.cpp @@ -6,6 +6,11 @@ // LINES-ONLY-NOT: !DICompositeType(tag: DW_TAG_structure_type +// "h" is at the top because it's in the compile unit's retainedTypes: list. +// CHECK: DICompositeType(tag: DW_TAG_structure_type, name: "h<int>" +// CHECK-NOT: DIFlagFwdDecl +// CHECK-SAME: ){{$}} + template <typename T> struct a { }; @@ -85,9 +90,6 @@ template <typename T> struct h { }; template class h<int>; -// CHECK: DICompositeType(tag: DW_TAG_structure_type, name: "h<int>" -// CHECK-NOT: DIFlagFwdDecl -// CHECK-SAME: ){{$}} template <typename T> struct i { diff --git a/test/CodeGenCXX/debug-info-template-limit.cpp b/test/CodeGenCXX/debug-info-template-limit.cpp index 5c4ac0cc3e15..172ab94dce62 100644 --- a/test/CodeGenCXX/debug-info-template-limit.cpp +++ b/test/CodeGenCXX/debug-info-template-limit.cpp @@ -1,8 +1,8 @@ // RUN: %clang_cc1 -emit-llvm -debug-info-kind=limited -triple %itanium_abi_triple %s -o - | FileCheck %s // Check that this pointer type is TC<int> -// CHECK: ![[LINE:[0-9]+]] = !DICompositeType(tag: DW_TAG_class_type, name: "TC<int>"{{.*}}, identifier: "_ZTS2TCIiE") -// CHECK: !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !"_ZTS2TCIiE" +// CHECK: ![[LINE:[0-9]+]] = distinct !DICompositeType(tag: DW_TAG_class_type, name: "TC<int>"{{.*}}, identifier: "_ZTS2TCIiE") +// CHECK: !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[LINE]] template<typename T> class TC { diff --git a/test/CodeGenCXX/debug-info-template-member.cpp b/test/CodeGenCXX/debug-info-template-member.cpp index b94ff05df44e..88f024b59abf 100644 --- a/test/CodeGenCXX/debug-info-template-member.cpp +++ b/test/CodeGenCXX/debug-info-template-member.cpp @@ -16,6 +16,12 @@ inline int add3(int x) { return MyClass().add<3>(x); // even though add<3> is ODR used, don't emit it since we don't codegen it } +// The compile unit pulls in the global variables first. +// CHECK: !DIGlobalVariable(name: "x", +// CHECK-SAME: type: ![[OUTER_FOO_INNER_ID:[0-9]+]] +// CHECK-SAME: variable: %"struct.outer<foo>::inner"* @x + +// CHECK: ![[OUTER_FOO_INNER_ID:[0-9]*]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "inner"{{.*}}, identifier: // CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "foo" // CHECK-SAME: elements: [[FOO_MEM:![0-9]*]] // CHECK-SAME: identifier: "_ZTS3foo" @@ -23,42 +29,35 @@ inline int add3(int x) { // CHECK: [[FOO_FUNC]] = !DISubprogram(name: "func", linkageName: "_ZN3foo4funcEN5outerIS_E5innerE", // CHECK-SAME: type: [[FOO_FUNC_TYPE:![0-9]*]] // CHECK: [[FOO_FUNC_TYPE]] = !DISubroutineType(types: [[FOO_FUNC_PARAMS:![0-9]*]]) -// CHECK: [[FOO_FUNC_PARAMS]] = !{null, !{{[0-9]*}}, !"[[OUTER_FOO_INNER_ID:.*]]"} -// CHECK: !{{[0-9]*}} = !DICompositeType(tag: DW_TAG_structure_type, name: "inner"{{.*}}, identifier: "[[OUTER_FOO_INNER_ID]]") - -// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "virt<elem>" -// CHECK-SAME: elements: [[VIRT_MEM:![0-9]*]] -// CHECK-SAME: vtableHolder: !"_ZTS4virtI4elemE" -// CHECK-SAME: templateParams: [[VIRT_TEMP_PARAM:![0-9]*]] -// CHECK-SAME: identifier: "_ZTS4virtI4elemE" -// CHECK: [[VIRT_TEMP_PARAM]] = !{[[VIRT_T:![0-9]*]]} -// CHECK: [[VIRT_T]] = !DITemplateTypeParameter(name: "T", type: !"_ZTS4elem") +// CHECK: [[FOO_FUNC_PARAMS]] = !{null, !{{[0-9]*}}, ![[OUTER_FOO_INNER_ID]]} -// CHECK: [[C:![0-9]*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "MyClass" +// CHECK: [[C:![0-9]*]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "MyClass" // CHECK-SAME: elements: [[C_MEM:![0-9]*]] -// CHECK-SAME: vtableHolder: !"_ZTS7MyClass" +// CHECK-SAME: vtableHolder: [[C]] // CHECK-SAME: identifier: "_ZTS7MyClass") // CHECK: [[C_MEM]] = !{[[C_VPTR:![0-9]*]], [[C_FUNC:![0-9]*]]} // CHECK: [[C_VPTR]] = !DIDerivedType(tag: DW_TAG_member, name: "_vptr$MyClass" // CHECK: [[C_FUNC]] = !DISubprogram(name: "func",{{.*}} line: 7, -// CHECK: [[ELEM:![0-9]*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "elem" +// CHECK: !DISubprogram(name: "add<2>" +// CHECK-SAME: scope: [[C]] +// +// CHECK: [[VIRT_TEMP:![0-9]+]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "virt<elem>" +// CHECK-SAME: elements: [[VIRT_MEM:![0-9]*]] +// CHECK-SAME: vtableHolder: [[VIRT_TEMP]] +// CHECK-SAME: templateParams: [[VIRT_TEMP_PARAM:![0-9]*]] +// CHECK-SAME: identifier: "_ZTS4virtI4elemE" + +// CHECK: [[ELEM:![0-9]+]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "elem" // CHECK-SAME: elements: [[ELEM_MEM:![0-9]*]] // CHECK-SAME: identifier: "_ZTS4elem" // CHECK: [[ELEM_MEM]] = !{[[ELEM_X:![0-9]*]]} -// CHECK: [[ELEM_X]] = !DIDerivedType(tag: DW_TAG_member, name: "x", scope: !"_ZTS4elem" -// CHECK-SAME: baseType: !"_ZTS4virtI4elemE" +// CHECK: [[ELEM_X]] = !DIDerivedType(tag: DW_TAG_member, name: "x", scope: [[ELEM]] +// CHECK-SAME: baseType: [[VIRT_TEMP:![0-9]+]] -// Check that the member function template specialization and implicit special -// members (the default ctor) refer to their class by scope, even though they -// didn't appear in the class's member list (C_MEM). This prevents the functions -// from being added to type units, while still appearing in the type -// declaration/reference in the compile unit. -// CHECK: !DISubprogram(name: "MyClass" -// CHECK-SAME: scope: !"_ZTS7MyClass" -// CHECK: !DISubprogram(name: "add<2>" -// CHECK-SAME: scope: !"_ZTS7MyClass" +// CHECK: [[VIRT_TEMP_PARAM]] = !{[[VIRT_T:![0-9]*]]} +// CHECK: [[VIRT_T]] = !DITemplateTypeParameter(name: "T", type: [[ELEM]]) template<typename T> struct outer { @@ -80,10 +79,6 @@ inline void func() { outer<foo>::inner x; -// CHECK: !DIGlobalVariable(name: "x", -// CHECK-SAME: type: !"[[OUTER_FOO_INNER_ID]]" -// CHECK-SAME: variable: %"struct.outer<foo>::inner"* @x - template <typename T> struct virt { T* values; @@ -98,3 +93,11 @@ inline void f1() { void f2() { virt<elem> d; // emit 'virt<elem>' } + +// Check that the member function template specialization and implicit special +// members (the default ctor) refer to their class by scope, even though they +// didn't appear in the class's member list (C_MEM). This prevents the functions +// from being added to type units, while still appearing in the type +// declaration/reference in the compile unit. +// CHECK: !DISubprogram(name: "MyClass" +// CHECK-SAME: scope: [[C]] diff --git a/test/CodeGenCXX/debug-info-template-quals.cpp b/test/CodeGenCXX/debug-info-template-quals.cpp index 1e8bdb1ad714..7a0d0d4a2755 100644 --- a/test/CodeGenCXX/debug-info-template-quals.cpp +++ b/test/CodeGenCXX/debug-info-template-quals.cpp @@ -15,17 +15,17 @@ void foo (const char *c) { str.assign(c, str); } -// CHECK: [[BS:.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "basic_string<char>" +// CHECK: [[P:![0-9]*]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: [[CON:![0-9]*]] +// CHECK: [[CON]] = !DIDerivedType(tag: DW_TAG_const_type, baseType: [[CH:![0-9]*]] +// CHECK: [[CH]] = !DIBasicType(name: "char", size: 8, align: 8, encoding: DW_ATE_signed_char) +// CHECK: [[BS:.*]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "basic_string<char>" // CHECK-SAME: line: 4 // CHECK-SAME: size: 8, align: 8 // CHECK: [[TYPE:![0-9]*]] = !DISubroutineType(types: [[ARGS:.*]]) -// CHECK: [[ARGS]] = !{!{{.*}}, !{{.*}}, [[P:![0-9]*]], [[R:.*]]} -// CHECK: [[P]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: [[CON:![0-9]*]] -// CHECK: [[CON]] = !DIDerivedType(tag: DW_TAG_const_type, baseType: [[CH:![0-9]*]] -// CHECK: [[CH]] = !DIBasicType(name: "char", size: 8, align: 8, encoding: DW_ATE_signed_char) +// CHECK: [[ARGS]] = !{!{{.*}}, !{{.*}}, [[P]], [[R:.*]]} // CHECK: [[R]] = !DIDerivedType(tag: DW_TAG_reference_type, baseType: [[CON2:![0-9]*]] -// CHECK: [[CON2]] = !DIDerivedType(tag: DW_TAG_const_type, baseType: !"_ZTS12basic_stringIcE" +// CHECK: [[CON2]] = !DIDerivedType(tag: DW_TAG_const_type, baseType: [[BS]] // CHECK: !DISubprogram(name: "assign" // CHECK-SAME: line: 7 // CHECK-SAME: scopeLine: 8 diff --git a/test/CodeGenCXX/debug-info-template.cpp b/test/CodeGenCXX/debug-info-template.cpp index 74adef9a5f7a..d35bb70fa713 100644 --- a/test/CodeGenCXX/debug-info-template.cpp +++ b/test/CodeGenCXX/debug-info-template.cpp @@ -1,73 +1,105 @@ // RUN: %clang -S -emit-llvm -target x86_64-unknown_unknown -g %s -o - -std=c++11 | FileCheck %s // CHECK: !DICompileUnit( -// CHECK-SAME: retainedTypes: [[RETAIN:![0-9]*]] // CHECK: [[EMPTY:![0-9]*]] = !{} -// CHECK: [[RETAIN]] = !{!{{[0-9]]*}}, [[FOO:![0-9]*]], +struct foo { + char pad[8]; // make the member pointer to 'e' a bit more interesting (nonzero) + int e; + void f(); + static void g(); +}; + +typedef int foo::*foo_mem; + +template<typename T, T, const int *x, foo_mem a, void (foo::*b)(), void (*f)(), int ...Is> +struct TC { + struct nested { + }; +}; + +// CHECK: [[INT:![0-9]+]] = !DIBasicType(name: "int" +int glb; +void func(); + +// CHECK: !DIGlobalVariable(name: "tci", +// CHECK-SAME: type: ![[TCNESTED:[0-9]+]] +// CHECK-SAME: variable: %"struct.TC<unsigned int, 2, &glb, &foo::e, &foo::f, &foo::g, 1, 2, 3>::nested"* @tci +// CHECK: ![[TCNESTED]] ={{.*}}!DICompositeType(tag: DW_TAG_structure_type, name: "nested", +// CHECK-SAME: scope: ![[TC:[0-9]+]], -// CHECK: [[TC:![0-9]*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "TC<unsigned int, 2, &glb, &foo::e, &foo::f, &foo::g, 1, 2, 3>" +// CHECK: ![[TC]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "TC<unsigned int, 2, &glb, &foo::e, &foo::f, &foo::g, 1, 2, 3>" // CHECK-SAME: templateParams: [[TCARGS:![0-9]*]] +TC // CHECK: [[TCARGS]] = !{[[TCARG1:![0-9]*]], [[TCARG2:![0-9]*]], [[TCARG3:![0-9]*]], [[TCARG4:![0-9]*]], [[TCARG5:![0-9]*]], [[TCARG6:![0-9]*]], [[TCARG7:![0-9]*]]} -// // CHECK: [[TCARG1]] = !DITemplateTypeParameter(name: "T", type: [[UINT:![0-9]*]]) // CHECK: [[UINT:![0-9]*]] = !DIBasicType(name: "unsigned int" +< unsigned, // CHECK: [[TCARG2]] = !DITemplateValueParameter(type: [[UINT]], value: i32 2) + 2, // CHECK: [[TCARG3]] = !DITemplateValueParameter(name: "x", type: [[CINTPTR:![0-9]*]], value: i32* @glb) // CHECK: [[CINTPTR]] = !DIDerivedType(tag: DW_TAG_pointer_type, {{.*}}baseType: [[CINT:![0-9]+]] -// CHECK: [[CINT]] = !DIDerivedType(tag: DW_TAG_const_type, {{.*}}baseType: [[INT:![0-9]+]] -// CHECK: [[INT]] = !DIBasicType(name: "int" +// CHECK: [[CINT]] = !DIDerivedType(tag: DW_TAG_const_type, {{.*}}baseType: [[INT]] + &glb, // CHECK: [[TCARG4]] = !DITemplateValueParameter(name: "a", type: [[MEMINTPTR:![0-9]*]], value: i64 8) -// CHECK: [[MEMINTPTR]] = !DIDerivedType(tag: DW_TAG_ptr_to_member_type, {{.*}}baseType: [[INT]], {{.*}}extraData: !"_ZTS3foo") +// CHECK: [[MEMINTPTR]] = !DIDerivedType(tag: DW_TAG_ptr_to_member_type, {{.*}}baseType: [[INT]], {{.*}}extraData: ![[FOO:[0-9]+]]) +// +// We could just emit a declaration of 'foo' here, rather than the entire +// definition (same goes for any time we emit a member (function or data) +// pointer type) +// CHECK: [[FOO]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "foo", {{.*}}identifier: "_ZTS3foo") +// CHECK: !DISubprogram(name: "f", linkageName: "_ZN3foo1fEv", {{.*}}type: [[FTYPE:![0-9]*]] // // Currently Clang emits the pointer-to-member-function value, but LLVM doesn't // use it (GCC doesn't emit a value for pointers to member functions either - so // it's not clear what, if any, format would be acceptable to GDB) // -// CHECK: [[TCARG5]] = !DITemplateValueParameter(name: "b", type: [[MEMFUNPTR:![0-9]*]], value: { i64, i64 } { i64 ptrtoint (void (%struct.foo*)* @_ZN3foo1fEv to i64), i64 0 }) -// CHECK: [[MEMFUNPTR]] = !DIDerivedType(tag: DW_TAG_ptr_to_member_type, {{.*}}baseType: [[FTYPE:![0-9]*]], {{.*}}extraData: !"_ZTS3foo") -// CHECK: [[FTYPE]] = !DISubroutineType(types: [[FARGS:![0-9]*]]) +// CHECK: [[FTYPE:![0-9]*]] = !DISubroutineType(types: [[FARGS:![0-9]*]]) // CHECK: [[FARGS]] = !{null, [[FARG1:![0-9]*]]} // CHECK: [[FARG1]] = !DIDerivedType(tag: DW_TAG_pointer_type, -// CHECK-SAME: baseType: !"_ZTS3foo" +// CHECK-SAME: baseType: ![[FOO]] // CHECK-NOT: line: // CHECK-SAME: size: 64, align: 64 // CHECK-NOT: offset: 0 // CHECK-SAME: DIFlagArtificial -// -// CHECK: [[TCARG6]] = !DITemplateValueParameter(name: "f", type: [[FUNPTR:![0-9]*]], value: void ()* @_ZN3foo1gEv) -// CHECK: [[FUNPTR]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: [[FUNTYPE:![0-9]*]] -// CHECK: [[FUNTYPE]] = !DISubroutineType(types: [[FUNARGS:![0-9]*]]) +// CHECK: [[FUNTYPE:![0-9]*]] = !DISubroutineType(types: [[FUNARGS:![0-9]*]]) // CHECK: [[FUNARGS]] = !{null} + &foo::e, +// CHECK: [[TCARG5]] = !DITemplateValueParameter(name: "b", type: [[MEMFUNPTR:![0-9]*]], value: { i64, i64 } { i64 ptrtoint (void (%struct.foo*)* @_ZN3foo1fEv to i64), i64 0 }) +// CHECK: [[MEMFUNPTR]] = !DIDerivedType(tag: DW_TAG_ptr_to_member_type, {{.*}}baseType: [[FTYPE]], {{.*}}extraData: ![[FOO]]) + &foo::f, +// CHECK: [[TCARG6]] = !DITemplateValueParameter(name: "f", type: [[FUNPTR:![0-9]*]], value: void ()* @_ZN3foo1gEv) +// CHECK: [[FUNPTR]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: [[FUNTYPE]] + &foo::g, // CHECK: [[TCARG7]] = !DITemplateValueParameter(tag: DW_TAG_GNU_template_parameter_pack, name: "Is", value: [[TCARG7_VALS:![0-9]*]]) // CHECK: [[TCARG7_VALS]] = !{[[TCARG7_1:![0-9]*]], [[TCARG7_2:![0-9]*]], [[TCARG7_3:![0-9]*]]} // CHECK: [[TCARG7_1]] = !DITemplateValueParameter(type: [[INT]], value: i32 1) + 1, // CHECK: [[TCARG7_2]] = !DITemplateValueParameter(type: [[INT]], value: i32 2) + 2, // CHECK: [[TCARG7_3]] = !DITemplateValueParameter(type: [[INT]], value: i32 3) -// -// We could just emit a declaration of 'foo' here, rather than the entire -// definition (same goes for any time we emit a member (function or data) -// pointer type) -// CHECK: [[FOO]] = !DICompositeType(tag: DW_TAG_structure_type, name: "foo", {{.*}}identifier: "_ZTS3foo") -// CHECK: !DISubprogram(name: "f", linkageName: "_ZN3foo1fEv", {{.*}}type: [[FTYPE:![0-9]*]] -// + 3>::nested tci; -// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "nested", -// CHECK-SAME: scope: !"_ZTS2TCIjLj2EXadL_Z3glbEEXadL_ZN3foo1eEEEXadL_ZNS0_1fEvEEXadL_ZNS0_1gEvEEJLi1ELi2ELi3EEE" -// CHECK-SAME: identifier: "[[TCNESTED:.*]]") -// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "TC<int, -3, nullptr, nullptr, nullptr, nullptr>" +// CHECK: !DIGlobalVariable(name: "tcn" +// CHECK-SAME: type: ![[TCNT:[0-9]+]] +// CHECK-SAME: variable: %struct.TC* @tcn +TC +// CHECK: ![[TCNT]] ={{.*}}!DICompositeType(tag: DW_TAG_structure_type, name: "TC<int, -3, nullptr, nullptr, nullptr, nullptr>" // CHECK-SAME: templateParams: [[TCNARGS:![0-9]*]] -// CHECK-SAME: identifier: "[[TCNT:.*]]") // CHECK: [[TCNARGS]] = !{[[TCNARG1:![0-9]*]], [[TCNARG2:![0-9]*]], [[TCNARG3:![0-9]*]], [[TCNARG4:![0-9]*]], [[TCNARG5:![0-9]*]], [[TCNARG6:![0-9]*]], [[TCNARG7:![0-9]*]]} // CHECK: [[TCNARG1]] = !DITemplateTypeParameter(name: "T", type: [[INT]]) +<int, // CHECK: [[TCNARG2]] = !DITemplateValueParameter(type: [[INT]], value: i32 -3) + -3, // CHECK: [[TCNARG3]] = !DITemplateValueParameter(name: "x", type: [[CINTPTR]], value: i8 0) + nullptr, // The interesting null pointer: -1 for member data pointers (since they are // just an offset in an object, they can be zero and non-null for the first // member) // CHECK: [[TCNARG4]] = !DITemplateValueParameter(name: "a", type: [[MEMINTPTR]], value: i64 -1) + nullptr, // // In some future iteration we could possibly emit the value of a null member // function pointer as '{ i64, i64 } zeroinitializer' as it may be handled @@ -75,69 +107,38 @@ // member function pointers. For now, it's simpler just to emit the 'i8 0'. // // CHECK: [[TCNARG5]] = !DITemplateValueParameter(name: "b", type: [[MEMFUNPTR]], value: i8 0) + nullptr, // CHECK: [[TCNARG6]] = !DITemplateValueParameter(name: "f", type: [[FUNPTR]], value: i8 0) + nullptr // CHECK: [[TCNARG7]] = !DITemplateValueParameter(tag: DW_TAG_GNU_template_parameter_pack, name: "Is", value: [[EMPTY]]) + > tcn; + +template<typename> +struct tmpl_impl { +}; + +template <template <typename> class tmpl, int &lvr, int &&rvr> +struct NN { +}; + +// CHECK: !DIGlobalVariable(name: "nn" +// CHECK-SAME: type: ![[NNT:[0-9]+]] +// CHECK-SAME: variable: %struct.NN* @nn // FIXME: these parameters should probably be rendered as 'glb' rather than // '&glb', since they're references, not pointers. -// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "NN<tmpl_impl, &glb, &glb>", +// CHECK: ![[NNT]] ={{.*}}!DICompositeType(tag: DW_TAG_structure_type, name: "NN<tmpl_impl, &glb, &glb>", // CHECK-SAME: templateParams: [[NNARGS:![0-9]*]] -// CHECK-SAME: identifier: "[[NNT:.*]]") +// CHECK-SAME: identifier: // CHECK: [[NNARGS]] = !{[[NNARG1:![0-9]*]], [[NNARG2:![0-9]*]], [[NNARG3:![0-9]*]]} // CHECK: [[NNARG1]] = !DITemplateValueParameter(tag: DW_TAG_GNU_template_template_param, name: "tmpl", value: !"tmpl_impl") // CHECK: [[NNARG2]] = !DITemplateValueParameter(name: "lvr", type: [[INTLVR:![0-9]*]], value: i32* @glb) // CHECK: [[INTLVR]] = !DIDerivedType(tag: DW_TAG_reference_type, baseType: [[INT]] // CHECK: [[NNARG3]] = !DITemplateValueParameter(name: "rvr", type: [[INTRVR:![0-9]*]], value: i32* @glb) // CHECK: [[INTRVR]] = !DIDerivedType(tag: DW_TAG_rvalue_reference_type, baseType: [[INT]] - -// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "PaddingAtEndTemplate<&PaddedObj>" -// CHECK-SAME: templateParams: [[PTOARGS:![0-9]*]] -// CHECK: [[PTOARGS]] = !{[[PTOARG1:![0-9]*]]} -// CHECK: [[PTOARG1]] = !DITemplateValueParameter(type: [[CONST_PADDINGATEND_PTR:![0-9]*]], value: %struct.PaddingAtEnd* @PaddedObj) -// CHECK: [[CONST_PADDINGATEND_PTR]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !"_ZTS12PaddingAtEnd", size: 64, align: 64) - -// CHECK: !DIGlobalVariable(name: "tci", -// CHECK-SAME: type: !"[[TCNESTED]]" -// CHECK-SAME: variable: %"struct.TC<unsigned int, 2, &glb, &foo::e, &foo::f, &foo::g, 1, 2, 3>::nested"* @tci - -// CHECK: !DIGlobalVariable(name: "tcn" -// CHECK-SAME: type: !"[[TCNT]]" -// CHECK-SAME: variable: %struct.TC* @tcn - -// CHECK: !DIGlobalVariable(name: "nn" -// CHECK-SAME: type: !"[[NNT]]" -// CHECK-SAME: variable: %struct.NN* @nn -struct foo { - char pad[8]; // make the member pointer to 'e' a bit more interesting (nonzero) - int e; - void f(); - static void g(); -}; - -typedef int foo::*foo_mem; - -template<typename T, T, const int *x, foo_mem a, void (foo::*b)(), void (*f)(), int ...Is> -struct TC { - struct nested { - }; -}; - -int glb; -void func(); - -TC<unsigned, 2, &glb, &foo::e, &foo::f, &foo::g, 1, 2, 3>::nested tci; -TC<int, -3, nullptr, nullptr, nullptr, nullptr> tcn; - -template<typename> -struct tmpl_impl { -}; - -template <template <typename> class tmpl, int &lvr, int &&rvr> -struct NN { -}; - NN<tmpl_impl, glb, glb> nn; +// CHECK: ![[PADDINGATEND:[0-9]+]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "PaddingAtEnd", struct PaddingAtEnd { int i; char c; @@ -145,6 +146,11 @@ struct PaddingAtEnd { PaddingAtEnd PaddedObj = {}; +// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "PaddingAtEndTemplate<&PaddedObj>" +// CHECK-SAME: templateParams: [[PTOARGS:![0-9]*]] +// CHECK: [[PTOARGS]] = !{[[PTOARG1:![0-9]*]]} +// CHECK: [[PTOARG1]] = !DITemplateValueParameter(type: [[CONST_PADDINGATEND_PTR:![0-9]*]], value: %struct.PaddingAtEnd* @PaddedObj) +// CHECK: [[CONST_PADDINGATEND_PTR]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[PADDINGATEND]], size: 64, align: 64) template <PaddingAtEnd *> struct PaddingAtEndTemplate { }; diff --git a/test/CodeGenCXX/debug-info-varargs.cpp b/test/CodeGenCXX/debug-info-varargs.cpp index 52bffe6c9285..7afbcd255842 100644 --- a/test/CodeGenCXX/debug-info-varargs.cpp +++ b/test/CodeGenCXX/debug-info-varargs.cpp @@ -2,13 +2,7 @@ struct A { - // CHECK: !DISubprogram(name: "a", linkageName: "_ZN1A1aEiz" - // CHECK-SAME: line: [[@LINE+2]] - // CHECK-SAME: type: ![[ATY:[0-9]+]] void a(int c, ...) {} - // CHECK: ![[ATY]] = !DISubroutineType(types: ![[AARGS:[0-9]+]]) - // We no longer use an explicit unspecified parameter. Instead we use a trailing null to mean the function is variadic. - // CHECK: ![[AARGS]] = !{null, !{{[0-9]+}}, !{{[0-9]+}}, null} }; // CHECK: !DISubprogram(name: "b", linkageName: "_Z1biz" @@ -18,6 +12,14 @@ void b(int c, ...) { // CHECK: ![[BTY]] = !DISubroutineType(types: ![[BARGS:[0-9]+]]) // CHECK: ![[BARGS]] = !{null, !{{[0-9]+}}, null} + // The subprogram "a" comes after "b" because the function comes later. + // CHECK: !DISubprogram(name: "a", linkageName: "_ZN1A1aEiz" + // CHECK-SAME: line: 5, + // CHECK-SAME: type: ![[ATY:[0-9]+]] + // CHECK: ![[ATY]] = !DISubroutineType(types: ![[AARGS:[0-9]+]]) + // We no longer use an explicit unspecified parameter. Instead we use a trailing null to mean the function is variadic. + // CHECK: ![[AARGS]] = !{null, !{{[0-9]+}}, !{{[0-9]+}}, null} + A a; // CHECK: !DILocalVariable(name: "fptr" diff --git a/test/CodeGenCXX/debug-info.cpp b/test/CodeGenCXX/debug-info.cpp index 29ed9e93156d..2e8d5fd5f137 100644 --- a/test/CodeGenCXX/debug-info.cpp +++ b/test/CodeGenCXX/debug-info.cpp @@ -1,5 +1,24 @@ -// RUN: %clang_cc1 -triple x86_64-none-linux-gnu -emit-llvm -debug-info-kind=limited %s -o - | FileCheck %s -// RUN: %clang_cc1 -triple i686-pc-windows-msvc -emit-llvm -debug-info-kind=limited %s -o - | FileCheck %s --check-prefix=MSVC +// RUN: %clang_cc1 -triple x86_64-none-linux-gnu -emit-llvm -debug-info-kind=limited %s -o - | FileCheck %s --check-prefix=CHECK --check-prefix=BOTH +// RUN: %clang_cc1 -triple i686-pc-windows-msvc -emit-llvm -debug-info-kind=limited %s -o - | FileCheck %s --check-prefix=MSVC --check-prefix=BOTH + +// CHECK: define void @_ZN7pr147634funcENS_3fooE +// CHECK: call void @llvm.dbg.declare({{.*}}, metadata ![[F:[0-9]+]], metadata ![[EXPR:[0-9]+]]) + +// !llvm.dbg.cu pulls in globals and their types first. +// CHECK-NOT: !DIGlobalVariable(name: "c" +// CHECK: !DIGlobalVariable(name: "x", linkageName: "_ZN6pr96081xE" +// CHECK-SAME: type: [[INCARRAYPTR:![0-9]*]] +// CHECK-SAME: variable: [3 x i8]** @_ZN6pr96081xE +// CHECK: [[INCARRAYPTR]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: [[INCARRAY:![0-9]+]] +// CHECK: [[INCARRAY]] = !DICompositeType(tag: DW_TAG_array_type +// CHECK-NOT: line: +// CHECK-NOT: size: +// CHECK-NOT: align: +// CHECK-NOT: offset: +// CHECK-SAME: baseType: ![[INCTYPE:[0-9]+]] + +// CHECK: ![[INCTYPE]] = !DICompositeType(tag: DW_TAG_structure_type, name: "incomplete" +// CHECK-SAME: DIFlagFwdDecl template<typename T> struct Identity { typedef T Type; @@ -47,38 +66,27 @@ namespace VirtualDtor { namespace VirtualBase { struct A { int a; }; struct B : virtual A { int b; }; +// BOTH: ![[VBASE_B:[0-9]+]] ={{.*}}!DICompositeType(tag: DW_TAG_structure_type, name: "B",{{.*}} line: [[@LINE-1]], +// MSVC-SAME: size: 96, align: 32 +// CHECK-SAME: size: 128, align: 64, +// BOTH-NOT: offset: +// BOTH-NOT: DIFlagFwdDecl +// BOTH-SAME: elements: [[VBASE_B_DEF:![0-9]+]] +// BOTH: [[VBASE_B_DEF]] = !{[[VBASE_A_IN_B:![0-9]+]], +// +// Look for the vbtable offset of A, which should be 4 for MSVC, 24 otherwise. +// BOTH: [[VBASE_A_IN_B]] = !DIDerivedType(tag: DW_TAG_inheritance, scope: ![[VBASE_B]], +// BOTH-SAME: baseType: ![[VBASE_A:[0-9]+]], +// MSVC-SAME: offset: 4, +// CHECK-SAME: offset: 24, +// +// BOTH: ![[VBASE_A]] ={{.*}}!DICompositeType(tag: DW_TAG_structure_type, name: "A", void f() { B b; } } -// CHECK: define void @_ZN7pr147634funcENS_3fooE -// CHECK: call void @llvm.dbg.declare({{.*}}, metadata ![[F:.*]], metadata ![[EXPR:.*]]) - -// MSVC: [[VBASE_B:![0-9]+]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "B",{{.*}} line: 49 -// MSVC-SAME: size: 96, align: 32 -// MSVC-NOT: offset: -// MSVC-NOT: DIFlagFwdDecl -// MSVC-SAME: elements: [[VBASE_B_DEF:![0-9]+]] -// MSVC: [[VBASE_B_DEF]] = !{[[VBASE_A_IN_B:![0-9]+]], -// -// Look for the vbtable offset of A, which should be 4. -// MSVC: [[VBASE_A_IN_B]] = !DIDerivedType(tag: DW_TAG_inheritance, scope: [[VBASE_B]], -// MSVC-SAME: baseType: !{{[0-9]*}} - -// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "B",{{.*}} line: 49, -// CHECK-SAME: size: 128, align: 64, -// CHECK-NOT: offset: -// CHECK-NOT: DIFlagFwdDecl -// CHECK-SAME: elements: [[VBASE_B_DEF:![^,)]+]] -// CHECK: [[VBASE_B_DEF]] = !{[[VBASE_A_IN_B:![0-9]+]], -// -// Look for the vtable offset offset, which should be -24. -// CHECK: [[VBASE_A_IN_B]] = !DIDerivedType(tag: DW_TAG_inheritance -// CHECK-SAME: scope: !"_ZTSN11VirtualBase1BE" -// CHECK-SAME: baseType: !"_ZTSN11VirtualBase1AE" -// CHECK-SAME: offset: 24, namespace b5249287 { template <typename T> class A { struct B; @@ -91,72 +99,56 @@ class Cls { Cls obj; } +// CHECK: [[FUNC:[0-9]+]] = distinct !DISubprogram(name: "func", linkageName: "_ZN7pr147634funcENS_3fooE" +// CHECK-SAME: type: {{![0-9]+}} +// CHECK-SAME: isDefinition: true + +// CHECK: [[PR14763:![0-9]+]] = !DINamespace(name: "pr14763" namespace pr14763 { struct foo { +// CHECK: ![[FOO:[0-9]+]] ={{.*}}!DICompositeType(tag: DW_TAG_structure_type, name: "foo" +// CHECK-SAME: scope: [[PR14763]] +// CHECK-SAME: identifier: foo(const foo&); }; +// For some reason function arguments ended up down here +// CHECK: ![[F]] = !DILocalVariable(name: "f", arg: 1, scope: ![[FUNC]] +// CHECK-SAME: type: ![[FOO]] +// CHECK: ![[EXPR]] = !DIExpression(DW_OP_deref) foo func(foo f) { return f; // reference 'f' for now because otherwise we hit another bug } -// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "foo" -// CHECK-SAME: scope: [[PR14763:![0-9]+]] -// CHECK-SAME: identifier: "[[FOO:.*]]" -// CHECK: [[PR14763]] = !DINamespace(name: "pr14763" -// CHECK: [[INCTYPE:![0-9]*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "incomplete" -// CHECK-SAME: DIFlagFwdDecl -// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "a" -// CHECK-SAME: elements: [[A_MEM:![0-9]+]] -// CHECK-SAME: identifier: "_ZTSN7pr162141aE" -// CHECK: [[A_MEM]] = !{[[A_I:![0-9]*]]} -// CHECK: [[A_I]] = !DIDerivedType(tag: DW_TAG_member, name: "i" -// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "b" -// CHECK-SAME: DIFlagFwdDecl - -// CHECK: [[FUNC:![0-9]+]] = distinct !DISubprogram(name: "func", linkageName: "_ZN7pr147634funcENS_3fooE" -// CHECK-SAME: type: [[FUNC_TYPE:![0-9]*]] -// CHECK-SAME: isDefinition: true } void foo() { +// CHECK: !DILocalVariable(name: "c" +// CHECK-NOT: arg: +// CHECK-SAME: ) const wchar_t c = L'x'; wchar_t d = c; } -// CHECK-NOT: !DIGlobalVariable(name: "c" - namespace pr9608 { // also pr9600 struct incomplete; incomplete (*x)[3]; -// CHECK: !DIGlobalVariable(name: "x", linkageName: "_ZN6pr96081xE" -// CHECK-SAME: type: [[INCARRAYPTR:![0-9]*]] -// CHECK-SAME: variable: [3 x i8]** @_ZN6pr96081xE -// CHECK: [[INCARRAYPTR]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: [[INCARRAY:![0-9]+]] -// CHECK: [[INCARRAY]] = !DICompositeType(tag: DW_TAG_array_type -// CHECK-NOT: line: -// CHECK-NOT: size: -// CHECK-NOT: align: -// CHECK-NOT: offset: -// CHECK-SAME: baseType: !"_ZTSN6pr960810incompleteE" } -// For some reason function arguments ended up down here -// CHECK: ![[F]] = !DILocalVariable(name: "f", arg: 1, scope: [[FUNC]] -// CHECK-SAME: type: !"[[FOO]]" -// CHECK: ![[EXPR]] = !DIExpression(DW_OP_deref) - -// CHECK: !DILocalVariable(name: "c" -// CHECK-NOT: arg: -// CHECK-SAME: ) - namespace pr16214 { +// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "a" +// CHECK-SAME: elements: [[A_MEM:![0-9]+]] +// CHECK-SAME: identifier: "_ZTSN7pr162141aE" +// CHECK: [[A_MEM]] = !{[[A_I:![0-9]*]]} struct a { +// CHECK: [[A_I]] = !DIDerivedType(tag: DW_TAG_member, name: "i" int i; }; typedef a at; +// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "b" +// CHECK-SAME: DIFlagFwdDecl struct b { }; diff --git a/test/CodeGenCXX/debug-lambda-expressions.cpp b/test/CodeGenCXX/debug-lambda-expressions.cpp index a022fad1b6b9..b01f770bdd97 100644 --- a/test/CodeGenCXX/debug-lambda-expressions.cpp +++ b/test/CodeGenCXX/debug-lambda-expressions.cpp @@ -17,23 +17,31 @@ int d(int x) { D y[10]; return [x,y] { return y[x].x; }(); } // Randomness for file. -- 6 // CHECK: [[FILE:.*]] = !DIFile(filename: "{{.*}}debug-lambda-expressions.cpp", +// CVAR: +// CHECK: !DIGlobalVariable(name: "cvar" +// CHECK-SAME: line: [[CVAR_LINE:[0-9]+]] +// CHECK-SAME: type: ![[CVAR_T:[0-9]+]] +// CHECK: ![[CVAR_T]] = distinct !DICompositeType(tag: DW_TAG_class_type +// CHECK-SAME: line: [[CVAR_LINE]], +// CHECK-SAME: elements: ![[CVAR_ARGS:[0-9]+]] +// CHECK: ![[CVAR_ARGS]] = !{!{{[0-9]+}}} + +// VAR: +// CHECK: !DIGlobalVariable(name: "var" +// CHECK-SAME: line: [[VAR_LINE:[0-9]+]] +// CHECK-SAME: type: ![[VAR_T:[0-9]+]] +// CHECK: ![[VAR_T]] = distinct !DICompositeType(tag: DW_TAG_class_type +// CHECK-SAME: line: [[VAR_LINE]], +// CHECK-SAME: elements: ![[VAR_ARGS:[0-9]+]] +// CHECK: ![[VAR_ARGS]] = !{!{{[0-9]+}}} + // CHECK: ![[INT:[0-9]+]] = !DIBasicType(name: "int" // A: 10 // CHECK: ![[A_FUNC:.*]] = distinct !DISubprogram(name: "a"{{.*}}, line: [[A_LINE:[0-9]+]]{{.*}}, isDefinition: true -// B: 14 -// CHECK: ![[B_FUNC:.*]] = distinct !DISubprogram(name: "b"{{.*}}, line: [[B_LINE:[0-9]+]]{{.*}}, isDefinition: true - -// C: 17 -// CHECK: ![[C_FUNC:.*]] = distinct !DISubprogram(name: "c"{{.*}}, line: [[C_LINE:[0-9]+]]{{.*}}, isDefinition: true - -// D: 18 -// CHECK: ![[D_FUNC:.*]] = distinct !DISubprogram(name: "d"{{.*}}, line: [[D_LINE:[0-9]+]]{{.*}}, isDefinition: true - - // Back to A. -- 78 -// CHECK: ![[LAM_A:.*]] = !DICompositeType(tag: DW_TAG_class_type{{.*}}, scope: ![[A_FUNC]]{{.*}}, line: [[A_LINE]], +// CHECK: ![[LAM_A:.*]] = distinct !DICompositeType(tag: DW_TAG_class_type{{.*}}, scope: ![[A_FUNC]]{{.*}}, line: [[A_LINE]], // CHECK-SAME: elements: ![[LAM_A_ARGS:[0-9]+]] // CHECK: ![[LAM_A_ARGS]] = !{![[CON_LAM_A:[0-9]+]]} // CHECK: ![[CON_LAM_A]] = !DISubprogram(name: "operator()" @@ -41,8 +49,11 @@ int d(int x) { D y[10]; return [x,y] { return y[x].x; }(); } // CHECK-SAME: line: [[A_LINE]] // CHECK-SAME: DIFlagPublic +// B: 14 +// CHECK: ![[B_FUNC:.*]] = distinct !DISubprogram(name: "b"{{.*}}, line: [[B_LINE:[0-9]+]]{{.*}}, isDefinition: true + // Back to B. -- 67 -// CHECK: ![[LAM_B:.*]] = !DICompositeType(tag: DW_TAG_class_type{{.*}}, scope: ![[B_FUNC]]{{.*}}, line: [[B_LINE]], +// CHECK: ![[LAM_B:.*]] = distinct !DICompositeType(tag: DW_TAG_class_type{{.*}}, scope: ![[B_FUNC]]{{.*}}, line: [[B_LINE]], // CHECK-SAME: elements: ![[LAM_B_ARGS:[0-9]+]] // CHECK: ![[LAM_B_ARGS]] = !{![[CAP_B:[0-9]+]], ![[CON_LAM_B:[0-9]+]]} // CHECK: ![[CAP_B]] = !DIDerivedType(tag: DW_TAG_member, name: "x" @@ -54,8 +65,11 @@ int d(int x) { D y[10]; return [x,y] { return y[x].x; }(); } // CHECK-SAME: line: [[B_LINE]] // CHECK-SAME: DIFlagPublic +// C: 17 +// CHECK: ![[C_FUNC:.*]] = distinct !DISubprogram(name: "c"{{.*}}, line: [[C_LINE:[0-9]+]]{{.*}}, isDefinition: true + // Back to C. -- 55 -// CHECK: ![[LAM_C:.*]] = !DICompositeType(tag: DW_TAG_class_type{{.*}}, scope: ![[C_FUNC]]{{.*}}, line: [[C_LINE]], +// CHECK: ![[LAM_C:.*]] = distinct !DICompositeType(tag: DW_TAG_class_type{{.*}}, scope: ![[C_FUNC]]{{.*}}, line: [[C_LINE]], // CHECK-SAME: elements: ![[LAM_C_ARGS:[0-9]+]] // CHECK: ![[LAM_C_ARGS]] = !{![[CAP_C:[0-9]+]], ![[CON_LAM_C:[0-9]+]]} // CHECK: ![[CAP_C]] = !DIDerivedType(tag: DW_TAG_member, name: "x" @@ -68,8 +82,11 @@ int d(int x) { D y[10]; return [x,y] { return y[x].x; }(); } // CHECK-SAME: line: [[C_LINE]] // CHECK-SAME: DIFlagPublic +// D: 18 +// CHECK: ![[D_FUNC:.*]] = distinct !DISubprogram(name: "d"{{.*}}, line: [[D_LINE:[0-9]+]]{{.*}}, isDefinition: true + // Back to D. -- 24 -// CHECK: ![[LAM_D:.*]] = !DICompositeType(tag: DW_TAG_class_type{{.*}}, scope: ![[D_FUNC]]{{.*}}, line: [[D_LINE]], +// CHECK: ![[LAM_D:.*]] = distinct !DICompositeType(tag: DW_TAG_class_type{{.*}}, scope: ![[D_FUNC]]{{.*}}, line: [[D_LINE]], // CHECK-SAME: elements: ![[LAM_D_ARGS:[0-9]+]] // CHECK: ![[LAM_D_ARGS]] = !{![[CAP_D_X:[0-9]+]], ![[CAP_D_Y:[0-9]+]], ![[CON_LAM_D:[0-9]+]]} // CHECK: ![[CAP_D_X]] = !DIDerivedType(tag: DW_TAG_member, name: "x" @@ -82,21 +99,3 @@ int d(int x) { D y[10]; return [x,y] { return y[x].x; }(); } // CHECK-SAME: scope: ![[LAM_D]] // CHECK-SAME: line: [[D_LINE]] // CHECK-SAME: DIFlagPublic - -// CVAR: -// CHECK: !DIGlobalVariable(name: "cvar" -// CHECK-SAME: line: [[CVAR_LINE:[0-9]+]] -// CHECK-SAME: type: ![[CVAR_T:[0-9]+]] -// CHECK: ![[CVAR_T]] = !DICompositeType(tag: DW_TAG_class_type -// CHECK-SAME: line: [[CVAR_LINE]], -// CHECK-SAME: elements: ![[CVAR_ARGS:[0-9]+]] -// CHECK: ![[CVAR_ARGS]] = !{!{{[0-9]+}}} - -// VAR: -// CHECK: !DIGlobalVariable(name: "var" -// CHECK-SAME: line: [[VAR_LINE:[0-9]+]] -// CHECK-SAME: type: ![[VAR_T:[0-9]+]] -// CHECK: ![[VAR_T]] = !DICompositeType(tag: DW_TAG_class_type -// CHECK-SAME: line: [[VAR_LINE]], -// CHECK-SAME: elements: ![[VAR_ARGS:[0-9]+]] -// CHECK: ![[VAR_ARGS]] = !{!{{[0-9]+}}} diff --git a/test/CodeGenCXX/debug-lambda-this.cpp b/test/CodeGenCXX/debug-lambda-this.cpp index 0c413449a3ec..4af3d81983b2 100644 --- a/test/CodeGenCXX/debug-lambda-this.cpp +++ b/test/CodeGenCXX/debug-lambda-this.cpp @@ -12,10 +12,11 @@ int D::d(int x) { }(); } +// CHECK: ![[D:[0-9]+]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "D", +// CHECK: ![[POINTER:.*]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[D]], size: 64, align: 64) // CHECK: !DIDerivedType(tag: DW_TAG_member, name: "this", // CHECK-SAME: line: 11 -// CHECK-SAME: baseType: ![[POINTER:[0-9]+]] +// CHECK-SAME: baseType: ![[POINTER]] // CHECK-SAME: size: 64, align: 64 // CHECK-NOT: offset: 0 // CHECK-SAME: ){{$}} -// CHECK: ![[POINTER]] = !DIDerivedType(tag: DW_TAG_pointer_type diff --git a/test/CodeGenCXX/default_calling_conv.cpp b/test/CodeGenCXX/default_calling_conv.cpp new file mode 100644 index 000000000000..95c214a223d4 --- /dev/null +++ b/test/CodeGenCXX/default_calling_conv.cpp @@ -0,0 +1,34 @@ +// RUN: %clang_cc1 -triple i386-unknown-linux-gnu -fdefault-calling-conv=cdecl -emit-llvm -o - %s | FileCheck %s --check-prefix=CDECL --check-prefix=ALL +// RUN: %clang_cc1 -triple i786-unknown-linux-gnu -target-feature +sse4.2 -fdefault-calling-conv=fastcall -emit-llvm -o - %s | FileCheck %s --check-prefix=FASTCALL --check-prefix=ALL +// RUN: %clang_cc1 -triple i486-unknown-linux-gnu -fdefault-calling-conv=stdcall -emit-llvm -o - %s | FileCheck %s --check-prefix=STDCALL --check-prefix=ALL +// RUN: %clang_cc1 -triple i486-unknown-linux-gnu -mrtd -emit-llvm -o - %s | FileCheck %s --check-prefix=STDCALL --check-prefix=ALL +// RUN: %clang_cc1 -triple i986-unknown-linux-gnu -fdefault-calling-conv=vectorcall -emit-llvm -o - %s | FileCheck %s --check-prefix=VECTORCALL --check-prefix=ALL + +// CDECL: define void @_Z5test1v +// FASTCALL: define x86_fastcallcc void @_Z5test1v +// STDCALL: define x86_stdcallcc void @_Z5test1v +// VECTORCALL: define x86_vectorcallcc void @_Z5test1v +void test1() {} + +// ALL: define void @_Z5test2v +void __attribute__((cdecl)) test2() {} + +// ALL: define x86_fastcallcc void @_Z5test3v +void __attribute__((fastcall)) test3() {} + +// ALL: define x86_stdcallcc void @_Z5test4v +void __attribute__((stdcall)) test4() {} + +// ALL: define x86_vectorcallcc void @_Z5test5v +void __attribute__((vectorcall)) test5() {} + +// ALL: define linkonce_odr void @_ZN1A11test_memberEv +class A { +public: + void test_member() {} +}; + +void test() { + A a; + a.test_member(); +} diff --git a/test/CodeGenCXX/delete-two-arg.cpp b/test/CodeGenCXX/delete-two-arg.cpp index 85275b3eb176..68a6fa6736eb 100644 --- a/test/CodeGenCXX/delete-two-arg.cpp +++ b/test/CodeGenCXX/delete-two-arg.cpp @@ -27,7 +27,7 @@ namespace test2 { // CHECK: define [[A:%.*]]* @_ZN5test24testEv() A *test() { - // CHECK: [[NEW:%.*]] = call noalias i8* @_Znaj(i32 44) + // CHECK: [[NEW:%.*]] = call 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, i8* [[NEW]], i32 4 @@ -63,7 +63,7 @@ namespace test3 { // CHECK-LABEL: define void @_ZN5test34testEv() void test() { - // CHECK: call noalias i8* @_Znaj(i32 24) + // CHECK: call i8* @_Znaj(i32 24) // CHECK-NEXT: bitcast // CHECK-NEXT: store i32 5 (void) new B[5]; diff --git a/test/CodeGenCXX/destructors.cpp b/test/CodeGenCXX/destructors.cpp index 529603142d31..d6aabee58b9e 100644 --- a/test/CodeGenCXX/destructors.cpp +++ b/test/CodeGenCXX/destructors.cpp @@ -4,6 +4,9 @@ // RUN: FileCheck --check-prefix=CHECK3 --input-file=%t %s // RUN: FileCheck --check-prefix=CHECK4 --input-file=%t %s // RUN: FileCheck --check-prefix=CHECK5 --input-file=%t %s +// RUN: %clang_cc1 %s -triple x86_64-apple-darwin10 -emit-llvm -o - -fcxx-exceptions -fexceptions -O1 -disable-llvm-optzns -std=c++11 > %t2 +// RUN: FileCheck --check-prefix=CHECK6 --input-file=%t2 %s +// REQUIRES: asserts struct A { int a; @@ -428,3 +431,64 @@ namespace test10 { return true; } } + +#if __cplusplus >= 201103L +namespace test11 { + +// Check that lifetime.end is emitted in the landing pad. + +// CHECK6-LABEL: define void @_ZN6test1115testLifetimeEndEi( +// CHECK6: entry: +// CHECK6: [[T1:%[a-z0-9]+]] = alloca %"struct.test11::S1" +// CHECK6: [[T2:%[a-z0-9]+]] = alloca %"struct.test11::S1" +// CHECK6: [[T3:%[a-z0-9]+]] = alloca %"struct.test11::S1" + +// CHECK6: {{^}}invoke.cont +// CHECK6: call void @_ZN6test112S1D1Ev(%"struct.test11::S1"* [[T1]]) +// CHECK6: [[BC1:%[a-z0-9]+]] = bitcast %"struct.test11::S1"* [[T1]] to i8* +// CHECK6: call void @llvm.lifetime.end(i64 32, i8* [[BC1]]) +// CHECK6: {{^}}lpad +// CHECK6: call void @_ZN6test112S1D1Ev(%"struct.test11::S1"* [[T1]]) +// CHECK6: [[BC2:%[a-z0-9]+]] = bitcast %"struct.test11::S1"* [[T1]] to i8* +// CHECK6: call void @llvm.lifetime.end(i64 32, i8* [[BC2]]) + +// CHECK6: {{^}}invoke.cont +// CHECK6: call void @_ZN6test112S1D1Ev(%"struct.test11::S1"* [[T2]]) +// CHECK6: [[BC3:%[a-z0-9]+]] = bitcast %"struct.test11::S1"* [[T2]] to i8* +// CHECK6: call void @llvm.lifetime.end(i64 32, i8* [[BC3]]) +// CHECK6: {{^}}lpad +// CHECK6: call void @_ZN6test112S1D1Ev(%"struct.test11::S1"* [[T2]]) +// CHECK6: [[BC4:%[a-z0-9]+]] = bitcast %"struct.test11::S1"* [[T2]] to i8* +// CHECK6: call void @llvm.lifetime.end(i64 32, i8* [[BC4]]) + +// CHECK6: {{^}}invoke.cont +// CHECK6: call void @_ZN6test112S1D1Ev(%"struct.test11::S1"* [[T3]]) +// CHECK6: [[BC5:%[a-z0-9]+]] = bitcast %"struct.test11::S1"* [[T3]] to i8* +// CHECK6: call void @llvm.lifetime.end(i64 32, i8* [[BC5]]) +// CHECK6: {{^}}lpad +// CHECK6: call void @_ZN6test112S1D1Ev(%"struct.test11::S1"* [[T3]]) +// CHECK6: [[BC6:%[a-z0-9]+]] = bitcast %"struct.test11::S1"* [[T3]] to i8* +// CHECK6: call void @llvm.lifetime.end(i64 32, i8* [[BC6]]) + + struct S1 { + ~S1(); + int a[8]; + }; + + void func1(S1 &) noexcept(false); + + void testLifetimeEnd(int n) { + if (n < 10) { + S1 t1; + func1(t1); + } else if (n < 100) { + S1 t2; + func1(t2); + } else if (n < 1000) { + S1 t3; + func1(t3); + } + } + +} +#endif diff --git a/test/CodeGenCXX/discard-name-values.cpp b/test/CodeGenCXX/discard-name-values.cpp new file mode 100644 index 000000000000..49cb7d2fc058 --- /dev/null +++ b/test/CodeGenCXX/discard-name-values.cpp @@ -0,0 +1,10 @@ +// RUN: %clang_cc1 -emit-llvm -triple=armv7-apple-darwin -emit-llvm -std=c++11 %s -o - -O1 | FileCheck %s +// RUN: %clang_cc1 -emit-llvm -triple=armv7-apple-darwin -emit-llvm -std=c++11 %s -o - -O1 -discard-value-names | FileCheck %s --check-prefix=DISCARDVALUE + +int foo(int bar) { + return bar; +} + +// CHECK: ret i32 %bar +// DISCARDVALUE: ret i32 %0 + diff --git a/test/CodeGenCXX/dllexport-members.cpp b/test/CodeGenCXX/dllexport-members.cpp index 76f692dbd301..1c56251328d6 100644 --- a/test/CodeGenCXX/dllexport-members.cpp +++ b/test/CodeGenCXX/dllexport-members.cpp @@ -1,5 +1,7 @@ -// RUN: %clang_cc1 -triple i686-windows-msvc -fms-compatibility -emit-llvm -std=c++1y -O0 -o - %s | FileCheck --check-prefix=MSC --check-prefix=M32 %s -// RUN: %clang_cc1 -triple x86_64-windows-msvc -fms-compatibility -emit-llvm -std=c++1y -O0 -o - %s | FileCheck --check-prefix=MSC --check-prefix=M64 %s +// RUN: %clang_cc1 -triple i686-windows-msvc -fms-compatibility -fms-compatibility-version=18 -emit-llvm -std=c++1y -O0 -o - %s | FileCheck --check-prefix=MSC --check-prefix=M32 %s +// RUN: %clang_cc1 -triple x86_64-windows-msvc -fms-compatibility -fms-compatibility-version=18 -emit-llvm -std=c++1y -O0 -o - %s | FileCheck --check-prefix=MSC --check-prefix=M64 %s +// RUN: %clang_cc1 -triple i686-windows-msvc -fms-compatibility -fms-compatibility-version=19 -emit-llvm -std=c++1y -O0 -o - %s | FileCheck --check-prefix=M32VS2015 %s +// RUN: %clang_cc1 -triple x86_64-windows-msvc -fms-compatibility -fms-compatibility-version=19 -emit-llvm -std=c++1y -O0 -o - %s | FileCheck --check-prefix=M64VS2015 %s // RUN: %clang_cc1 -triple i686-windows-gnu -emit-llvm -std=c++1y -O0 -o - %s | FileCheck --check-prefix=GNU --check-prefix=G32 %s // RUN: %clang_cc1 -triple x86_64-windows-gnu -emit-llvm -std=c++1y -O0 -o - %s | FileCheck --check-prefix=GNU --check-prefix=G64 %s @@ -427,6 +429,32 @@ __declspec(dllexport) ExportDefaultedDefs::ExportDefaultedDefs(ExportDefaultedDe ExportDefaultedDefs& ExportDefaultedDefs::operator=(ExportDefaultedDefs&&) = default; +// Export defaulted member function definitions declared inside class. +struct ExportDefaultedInclassDefs { + __declspec(dllexport) ExportDefaultedInclassDefs() = default; + // M32VS2013-DAG: define weak_odr dllexport x86_thiscallcc %struct.ExportDefaultedInclassDefs* @"\01??0ExportDefaultedInclassDefs@@QAE@XZ"(%struct.ExportDefaultedInclassDefs* returned %this) + // M64VS2013-DAG: define weak_odr dllexport %struct.ExportDefaultedInclassDefs* @"\01??0ExportDefaultedInclassDefs@@QEAA@XZ"(%struct.ExportDefaultedInclassDefs* returned %this) + // M32VS2015-NOT: define weak_odr dllexport x86_thiscallcc %struct.ExportDefaultedInclassDefs* @"\01??0ExportDefaultedInclassDefs@@QAE@XZ"(%struct.ExportDefaultedInclassDefs* returned %this) + // M64VS2015-NOT: define weak_odr dllexport %struct.ExportDefaultedInclassDefs* @"\01??0ExportDefaultedInclassDefs@@QEAA@XZ"(%struct.ExportDefaultedInclassDefs* returned %this) + + __declspec(dllexport) ~ExportDefaultedInclassDefs() = default; + // M32VS2013-DAG: define weak_odr dllexport x86_thiscallcc void @"\01??1ExportDefaultedInclassDefs@@QAE@XZ"(%struct.ExportDefaultedInclassDefs* %this) + // M64VS2013-DAG: define weak_odr dllexport void @"\01??1ExportDefaultedInclassDefs@@QEAA@XZ"(%struct.ExportDefaultedInclassDefs* %this) + // M32VS2015-NOT: define weak_odr dllexport x86_thiscallcc void @"\01??1ExportDefaultedInclassDefs@@QAE@XZ"(%struct.ExportDefaultedInclassDefs* %this) + // M64VS2015-NOT: define weak_odr dllexport void @"\01??1ExportDefaultedInclassDefs@@QEAA@XZ"(%struct.ExportDefaultedInclassDefs* %this) + + __declspec(dllexport) ExportDefaultedInclassDefs(const ExportDefaultedInclassDefs&) = default; + // M32VS2013-DAG: define weak_odr dllexport x86_thiscallcc %struct.ExportDefaultedInclassDefs* @"\01??0ExportDefaultedInclassDefs@@QAE@ABU0@@Z"(%struct.ExportDefaultedInclassDefs* returned %this, %struct.ExportDefaultedInclassDefs* dereferenceable({{[0-9]+}})) + // M64VS2013-DAG: define weak_odr dllexport %struct.ExportDefaultedInclassDefs* @"\01??0ExportDefaultedInclassDefs@@QEAA@AEBU0@@Z"(%struct.ExportDefaultedInclassDefs* returned %this, %struct.ExportDefaultedInclassDefs* dereferenceable({{[0-9]+}})) + // M32VS2015-NOT: define weak_odr dllexport x86_thiscallcc %struct.ExportDefaultedInclassDefs* @"\01??0ExportDefaultedInclassDefs@@QAE@ABU0@@Z"(%struct.ExportDefaultedInclassDefs* returned %this, %struct.ExportDefaultedInclassDefs* dereferenceable({{[0-9]+}})) + // M64VS2015-NOT: define weak_odr dllexport %struct.ExportDefaultedInclassDefs* @"\01??0ExportDefaultedInclassDefs@@QEAA@AEBU0@@Z"(%struct.ExportDefaultedInclassDefs* returned %this, %struct.ExportDefaultedInclassDefs* dereferenceable({{[0-9]+}})) + + __declspec(dllexport) ExportDefaultedInclassDefs& operator=(const ExportDefaultedInclassDefs&) = default; + // M32-DAG: define weak_odr dllexport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ExportDefaultedInclassDefs* @"\01??4ExportDefaultedInclassDefs@@QAEAAU0@ABU0@@Z"(%struct.ExportDefaultedInclassDefs* %this, %struct.ExportDefaultedInclassDefs* dereferenceable({{[0-9]+}})) + // M64-DAG: define weak_odr dllexport dereferenceable({{[0-9]+}}) %struct.ExportDefaultedInclassDefs* @"\01??4ExportDefaultedInclassDefs@@QEAAAEAU0@AEBU0@@Z"(%struct.ExportDefaultedInclassDefs* %this, %struct.ExportDefaultedInclassDefs* dereferenceable({{[0-9]+}})) +}; + + // Export allocation functions. struct ExportAlloc { __declspec(dllexport) void* operator new(__SIZE_TYPE__); diff --git a/test/CodeGenCXX/dllexport-ms-friend.cpp b/test/CodeGenCXX/dllexport-ms-friend.cpp new file mode 100644 index 000000000000..7bcf5905e5e5 --- /dev/null +++ b/test/CodeGenCXX/dllexport-ms-friend.cpp @@ -0,0 +1,22 @@ +// RUN: %clang_cc1 -triple %ms_abi_triple -fms-extensions -emit-llvm -O0 -o - %s | FileCheck %s + +// Friend functions defined in classes are emitted. +// CHECK: define weak_odr dllexport void @"\01?friend1@@YAXXZ"() +struct FuncFriend1 { + friend __declspec(dllexport) void friend1() {} +}; + +// But function templates and functions defined in class templates are not +// emitted. +// CHECK-NOT: friend2 +// CHECK-NOT: friend3 +// CHECK-NOT: friend4 +struct FuncFriend2 { + template<typename> friend __declspec(dllexport) void friend2() {} +}; +template<typename> struct FuncFriend3 { + friend __declspec(dllexport) void friend3() {} + struct Inner { + friend __declspec(dllexport) void friend4() {} + }; +}; diff --git a/test/CodeGenCXX/dllexport-pr26549.cpp b/test/CodeGenCXX/dllexport-pr26549.cpp new file mode 100644 index 000000000000..ceb2e0685ef1 --- /dev/null +++ b/test/CodeGenCXX/dllexport-pr26549.cpp @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 %s -fms-extensions -triple x86_64-windows-msvc -emit-llvm -o - | FileCheck %s + +template <typename> struct MessageT { }; +extern template struct MessageT<int>; + +// CHECK: define weak_odr dllexport {{.*}} %struct.MessageT* @"\01??4?$MessageT@H@@QEAAAEAU0@AEBU0@@Z"( +template struct __declspec(dllexport) MessageT<int>; +// Previously we crashed when this dllexport was the last thing in the file. +// DO NOT ADD MORE TESTS AFTER THIS LINE! diff --git a/test/CodeGenCXX/dllexport.cpp b/test/CodeGenCXX/dllexport.cpp index 1412ad866bd3..7cef7c2d127e 100644 --- a/test/CodeGenCXX/dllexport.cpp +++ b/test/CodeGenCXX/dllexport.cpp @@ -1,5 +1,9 @@ -// RUN: %clang_cc1 -triple i686-windows-msvc -emit-llvm -std=c++1y -fno-threadsafe-statics -fms-extensions -O1 -mconstructor-aliases -disable-llvm-optzns -o - %s -w | FileCheck --check-prefix=MSC --check-prefix=M32 %s -// RUN: %clang_cc1 -triple x86_64-windows-msvc -emit-llvm -std=c++1y -fno-threadsafe-statics -fms-extensions -O0 -o - %s -w | FileCheck --check-prefix=MSC --check-prefix=M64 %s +// RUN: %clang_cc1 -triple i686-windows-msvc -emit-llvm -std=c++1y -fno-threadsafe-statics -fms-extensions -O1 -mconstructor-aliases -disable-llvm-optzns -o - %s -w -fms-compatibility-version=19.00 | FileCheck --check-prefix=MSC --check-prefix=M32 -check-prefix=MSVC2015 -check-prefix=M32MSVC2015 %s +// RUN: %clang_cc1 -triple i686-windows-msvc -emit-llvm -std=c++1y -fno-threadsafe-statics -fms-extensions -O1 -mconstructor-aliases -disable-llvm-optzns -o - %s -w -fms-compatibility-version=18.00 | FileCheck --check-prefix=MSC --check-prefix=M32 -check-prefix=MSVC2013 -check-prefix=M32MSVC2013 %s + +// RUN: %clang_cc1 -triple x86_64-windows-msvc -emit-llvm -std=c++1y -fno-threadsafe-statics -fms-extensions -O0 -o - %s -w -fms-compatibility-version=19.00 | FileCheck --check-prefix=MSC --check-prefix=M64 -check-prefix=MSVC2015 -check-prefix=M64MSVC2015 %s +// RUN: %clang_cc1 -triple x86_64-windows-msvc -emit-llvm -std=c++1y -fno-threadsafe-statics -fms-extensions -O0 -o - %s -w -fms-compatibility-version=18.00 | FileCheck --check-prefix=MSC --check-prefix=M64 -check-prefix=MSVC2013 -check-prefix=M64MSVC2013 %s + // RUN: %clang_cc1 -triple i686-windows-gnu -emit-llvm -std=c++1y -fno-threadsafe-statics -fms-extensions -O0 -o - %s -w | FileCheck --check-prefix=GNU --check-prefix=G32 %s // RUN: %clang_cc1 -triple x86_64-windows-gnu -emit-llvm -std=c++1y -fno-threadsafe-statics -fms-extensions -O0 -o - %s -w | FileCheck --check-prefix=GNU --check-prefix=G64 %s @@ -486,7 +490,7 @@ struct S { struct CtorWithClosure { __declspec(dllexport) CtorWithClosure(...) {} -// M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01??_FCtorWithClosure@@QAEXXZ"({{.*}}) comdat +// M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01??_FCtorWithClosure@@QAEXXZ"({{.*}}) {{#[0-9]+}} comdat // M32-DAG: %[[this_addr:.*]] = alloca %struct.CtorWithClosure*, align 4 // M32-DAG: store %struct.CtorWithClosure* %this, %struct.CtorWithClosure** %[[this_addr]], align 4 // M32-DAG: %[[this:.*]] = load %struct.CtorWithClosure*, %struct.CtorWithClosure** %[[this_addr]] @@ -503,7 +507,7 @@ struct CtorWithClosure { struct __declspec(dllexport) ClassWithClosure { DELETE_IMPLICIT_MEMBERS(ClassWithClosure); ClassWithClosure(...) {} -// M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01??_FClassWithClosure@@QAEXXZ"({{.*}}) comdat +// M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01??_FClassWithClosure@@QAEXXZ"({{.*}}) {{#[0-9]+}} comdat // M32-DAG: %[[this_addr:.*]] = alloca %struct.ClassWithClosure*, align 4 // M32-DAG: store %struct.ClassWithClosure* %this, %struct.ClassWithClosure** %[[this_addr]], align 4 // M32-DAG: %[[this:.*]] = load %struct.ClassWithClosure*, %struct.ClassWithClosure** %[[this_addr]] @@ -520,17 +524,19 @@ struct __declspec(dllexport) NestedOuter { }; }; -// M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01??_FNestedOuter@@QAEXXZ"({{.*}}) comdat -// M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01??_FNestedInner@NestedOuter@@QAEXXZ"({{.*}}) comdat +// M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01??_FNestedOuter@@QAEXXZ"({{.*}}) {{#[0-9]+}} comdat +// M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01??_FNestedInner@NestedOuter@@QAEXXZ"({{.*}}) {{#[0-9]+}} comdat template <typename T> struct SomeTemplate { SomeTemplate(T o = T()) : o(o) {} T o; }; +// MSVC2015-DAG: define weak_odr dllexport {{.+}} @"\01??4?$SomeTemplate@H@@Q{{.+}}@$$Q{{.+}}@@Z" +// MSVC2013-DAG: define weak_odr dllexport {{.+}} @"\01??4?$SomeTemplate@H@@Q{{.+}}0@A{{.+}}0@@Z" struct __declspec(dllexport) InheritFromTemplate : SomeTemplate<int> {}; -// M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01??_F?$SomeTemplate@H@@QAEXXZ"({{.*}}) comdat +// M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01??_F?$SomeTemplate@H@@QAEXXZ"({{.*}}) {{#[0-9]+}} comdat namespace PR23801 { template <typename> @@ -547,7 +553,7 @@ struct __declspec(dllexport) B { } // -// M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01??_FB@PR23801@@QAEXXZ"({{.*}}) comdat +// M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01??_FB@PR23801@@QAEXXZ"({{.*}}) {{#[0-9]+}} comdat struct __declspec(dllexport) T { // Copy assignment operator: @@ -555,7 +561,7 @@ struct __declspec(dllexport) T { // Explicitly defaulted copy constructur: T(const T&) = default; - // M32-DAG: define weak_odr dllexport x86_thiscallcc %struct.T* @"\01??0T@@QAE@ABU0@@Z" + // M32MSVC2013-DAG: define weak_odr dllexport x86_thiscallcc %struct.T* @"\01??0T@@QAE@ABU0@@Z" void a() {} // M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?a@T@@QAEXXZ" @@ -570,6 +576,30 @@ struct __declspec(dllexport) T { USEVAR(T::b) int T::c; +// Export template class with static member variable +// MSC-DAG: @"\01?StaticClassVarExpTmplClass@?$TmplClass@H@@2HA" = weak_odr dllexport global i32 0, comdat, align 4 +// GNU-DAG: @_ZN9TmplClassIiE26StaticClassVarExpTmplClassE = weak_odr dllexport global i32 0, comdat, align 4 +template<typename T> +struct __declspec(dllexport) TmplClass +{ + static T StaticClassVarExpTmplClass; +}; + +template<typename T> +T TmplClass<T>::StaticClassVarExpTmplClass; + +// Export a definition of a template function. +// MSC-DAG: define weak_odr dllexport i32 @"\01??$TypeFunTmpl@H@@YAHH@Z" +// GNU-DAG: define weak_odr dllexport i32 @_Z11TypeFunTmplIiET_S0_ +template<typename T> +T __declspec(dllexport) TypeFunTmpl(T t) { return t + t; } + +// Instantiate the exported template class and the exported template function. +int useExportedTmplStaticAndFun() +{ + return TmplClass<int>::StaticClassVarExpTmplClass + TypeFunTmpl<int>(10); +} + template <typename T> struct __declspec(dllexport) U { void foo() {} }; struct __declspec(dllexport) V : public U<int> { }; // U<int>'s assignment operator is emitted. @@ -592,7 +622,8 @@ struct __declspec(dllexport) X : public virtual W {}; struct __declspec(dllexport) Y { // Move assignment operator: - // M32-DAG: define weak_odr dllexport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.Y* @"\01??4Y@@QAEAAU0@$$QAU0@@Z" + // MSVC2015-DAG: define weak_odr dllexport {{.+}} @"\01??4Y@@Q{{.+}}@$$Q{{.+}}@@Z" + // MSVC2013-DAG: define weak_odr dllexport {{.+}} @"\01??4Y@@Q{{.+}}0@A{{.+}}0@@Z" int x; }; @@ -616,9 +647,34 @@ namespace UseDtorAlias { struct __declspec(dllexport) DefaultedCtorsDtors { DefaultedCtorsDtors() = default; - // M32-DAG: define weak_odr dllexport x86_thiscallcc %struct.DefaultedCtorsDtors* @"\01??0DefaultedCtorsDtors@@QAE@XZ" + // M32MSVC2013-DAG: define weak_odr dllexport x86_thiscallcc %struct.DefaultedCtorsDtors* @"\01??0DefaultedCtorsDtors@@QAE@XZ" ~DefaultedCtorsDtors() = default; - // M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01??1DefaultedCtorsDtors@@QAE@XZ" + // M32MSVC2013-DAG: define weak_odr dllexport x86_thiscallcc void @"\01??1DefaultedCtorsDtors@@QAE@XZ" +}; + +// Export defaulted member function definitions declared inside class. +struct __declspec(dllexport) ExportDefaultedInclassDefs { + ExportDefaultedInclassDefs() = default; + // M32VS2013-DAG: define weak_odr dllexport x86_thiscallcc %struct.ExportDefaultedInclassDefs* @"\01??0ExportDefaultedInclassDefs@@QAE@XZ"(%struct.ExportDefaultedInclassDefs* returned %this) + // M64VS2013-DAG: define weak_odr dllexport %struct.ExportDefaultedInclassDefs* @"\01??0ExportDefaultedInclassDefs@@QEAA@XZ"(%struct.ExportDefaultedInclassDefs* returned %this) + // M32VS2015-NOT: define weak_odr dllexport x86_thiscallcc %struct.ExportDefaultedInclassDefs* @"\01??0ExportDefaultedInclassDefs@@QAE@XZ"(%struct.ExportDefaultedInclassDefs* returned %this) + // M64VS2015-NOT: define weak_odr dllexport %struct.ExportDefaultedInclassDefs* @"\01??0ExportDefaultedInclassDefs@@QEAA@XZ"(%struct.ExportDefaultedInclassDefs* returned %this) + + ~ExportDefaultedInclassDefs() = default; + // M32VS2013-DAG: define weak_odr dllexport x86_thiscallcc void @"\01??1ExportDefaultedInclassDefs@@QAE@XZ"(%struct.ExportDefaultedInclassDefs* %this) + // M64VS2013-DAG: define weak_odr dllexport void @"\01??1ExportDefaultedInclassDefs@@QEAA@XZ"(%struct.ExportDefaultedInclassDefs* %this) + // M32VS2015-NOT: define weak_odr dllexport x86_thiscallcc void @"\01??1ExportDefaultedInclassDefs@@QAE@XZ"(%struct.ExportDefaultedInclassDefs* %this) + // M64VS2015-NOT: define weak_odr dllexport void @"\01??1ExportDefaultedInclassDefs@@QEAA@XZ"(%struct.ExportDefaultedInclassDefs* %this) + + ExportDefaultedInclassDefs(const ExportDefaultedInclassDefs&) = default; + // M32VS2013-DAG: define weak_odr dllexport x86_thiscallcc %struct.ExportDefaultedInclassDefs* @"\01??0ExportDefaultedInclassDefs@@QAE@ABU0@@Z"(%struct.ExportDefaultedInclassDefs* returned %this, %struct.ExportDefaultedInclassDefs* dereferenceable({{[0-9]+}})) + // M64VS2013-DAG: define weak_odr dllexport %struct.ExportDefaultedInclassDefs* @"\01??0ExportDefaultedInclassDefs@@QEAA@AEBU0@@Z"(%struct.ExportDefaultedInclassDefs* returned %this, %struct.ExportDefaultedInclassDefs* dereferenceable({{[0-9]+}})) + // M32VS2015-NOT: define weak_odr dllexport x86_thiscallcc %struct.ExportDefaultedInclassDefs* @"\01??0ExportDefaultedInclassDefs@@QAE@ABU0@@Z"(%struct.ExportDefaultedInclassDefs* returned %this, %struct.ExportDefaultedInclassDefs* dereferenceable({{[0-9]+}})) + // M64VS2015-NOT: define weak_odr dllexport %struct.ExportDefaultedInclassDefs* @"\01??0ExportDefaultedInclassDefs@@QEAA@AEBU0@@Z"(%struct.ExportDefaultedInclassDefs* returned %this, %struct.ExportDefaultedInclassDefs* dereferenceable({{[0-9]+}})) + + ExportDefaultedInclassDefs& operator=(const ExportDefaultedInclassDefs&) = default; + // M32-DAG: define weak_odr dllexport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ExportDefaultedInclassDefs* @"\01??4ExportDefaultedInclassDefs@@QAEAAU0@ABU0@@Z"(%struct.ExportDefaultedInclassDefs* %this, %struct.ExportDefaultedInclassDefs* dereferenceable({{[0-9]+}})) + // M64-DAG: define weak_odr dllexport dereferenceable({{[0-9]+}}) %struct.ExportDefaultedInclassDefs* @"\01??4ExportDefaultedInclassDefs@@QEAAAEAU0@AEBU0@@Z"(%struct.ExportDefaultedInclassDefs* %this, %struct.ExportDefaultedInclassDefs* dereferenceable({{[0-9]+}})) }; namespace ReferencedInlineMethodInNestedClass { @@ -690,7 +746,7 @@ template <typename T> struct ExplicitInstConstexprMembers { // M32-DAG: define weak_odr dllexport x86_thiscallcc %struct.ExplicitInstConstexprMembers* @"\01??0?$ExplicitInstConstexprMembers@X@@QAE@XZ" ExplicitInstConstexprMembers(const ExplicitInstConstexprMembers&) = default; - // M32-DAG: define weak_odr dllexport x86_thiscallcc %struct.ExplicitInstConstexprMembers* @"\01??0?$ExplicitInstConstexprMembers@X@@QAE@ABU0@@Z" + // M32MSVC2013-DAG: define weak_odr dllexport x86_thiscallcc %struct.ExplicitInstConstexprMembers* @"\01??0?$ExplicitInstConstexprMembers@X@@QAE@ABU0@@Z" constexpr int f() const { return 42; } // M32-DAG: define weak_odr dllexport x86_thiscallcc i32 @"\01?f@?$ExplicitInstConstexprMembers@X@@QBEHXZ" @@ -777,6 +833,22 @@ struct __declspec(dllexport) Baz { // M32-DAG: define weak_odr dllexport x86_thiscallcc dereferenceable(1) %"struct.InClassInits::Baz"* @"\01??4Baz@InClassInits@@QAEAAU01@ABU01@@Z" } +// We had an issue where instantiating A would force emission of B's delayed +// exported methods. +namespace pr26490 { +template <typename T> struct A { }; +struct __declspec(dllexport) B { + B(int = 0) {} + A<int> m_fn1() {} +}; +// M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01??_FB@pr26490@@QAEXXZ" +} + +// dllexport trumps dllexport on an explicit instantiation. +template <typename T> struct ExplicitInstantiationTwoAttributes { void f() {} }; +template struct __declspec(dllexport) __declspec(dllimport) ExplicitInstantiationTwoAttributes<int>; +// M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?f@?$ExplicitInstantiationTwoAttributes@H@@QAEXXZ" + //===----------------------------------------------------------------------===// // Classes with template base classes @@ -891,10 +963,26 @@ template struct ExplicitInstantiationDeclTemplateBase<int>; // M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?func@?$ExplicitInstantiationDeclTemplateBase@H@@QAEXXZ" // G32-DAG: define weak_odr x86_thiscallcc void @_ZN37ExplicitInstantiationDeclTemplateBaseIiE4funcEv -template <typename T> struct ExplicitInstantiationDeclTemplateBase2 { void func() {} }; -extern template struct ExplicitInstantiationDeclTemplateBase2<int>; -struct __declspec(dllexport) DerivedFromExplicitInstantiationDeclTemplateBase2 : public ExplicitInstantiationDeclTemplateBase2<int> {}; -template struct __declspec(dllimport) ExplicitInstantiationDeclTemplateBase2<int>; -USEMEMFUNC(ExplicitInstantiationDeclTemplateBase2<int>, func) -// M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?func@?$ExplicitInstantiationDeclTemplateBase2@H@@QAEXXZ" -// G32-DAG: define weak_odr x86_thiscallcc void @_ZN38ExplicitInstantiationDeclTemplateBase2IiE4funcEv +// PR26076 +struct LayerSelectionBound; +template <typename> struct Selection {}; +typedef Selection<LayerSelectionBound> LayerSelection; +struct LayerImpl; +struct __declspec(dllexport) LayerTreeImpl { + struct __declspec(dllexport) ElementLayers { + LayerImpl *main = nullptr; + }; + LayerSelection foo; +}; +// M32-DAG: define weak_odr dllexport x86_thiscallcc %"struct.LayerTreeImpl::ElementLayers"* @"\01??0ElementLayers@LayerTreeImpl@@QAE@XZ" +// M64-DAG: define weak_odr dllexport %"struct.LayerTreeImpl::ElementLayers"* @"\01??0ElementLayers@LayerTreeImpl@@QEAA@XZ" + +class __declspec(dllexport) ACE_Shared_Object { +public: + virtual ~ACE_Shared_Object(); +}; +class __declspec(dllexport) ACE_Service_Object : public ACE_Shared_Object {}; +// Implicit move constructor declaration. +// MSVC2015-DAG: define weak_odr dllexport {{.+}}ACE_Service_Object@@Q{{.+}}@$$Q +// The declarations should not be exported. +// MSVC2013-NOT: define weak_odr dllexport {{.+}}ACE_Service_Object@@Q{{.+}}@$$Q diff --git a/test/CodeGenCXX/dllimport-members.cpp b/test/CodeGenCXX/dllimport-members.cpp index e88b7e97c3e7..1fed1bf0acf1 100644 --- a/test/CodeGenCXX/dllimport-members.cpp +++ b/test/CodeGenCXX/dllimport-members.cpp @@ -63,8 +63,8 @@ struct ForceNonTrivial { struct ImportMembers { struct Nested; - // M32-DAG: define x86_thiscallcc void @"\01?normalDef@ImportMembers@@QAEXXZ"(%struct.ImportMembers* %this) - // M64-DAG: define void @"\01?normalDef@ImportMembers@@QEAAXXZ"(%struct.ImportMembers* %this) + // M32-DAG: define dllexport x86_thiscallcc void @"\01?normalDef@ImportMembers@@QAEXXZ"(%struct.ImportMembers* %this) + // M64-DAG: define dllexport void @"\01?normalDef@ImportMembers@@QEAAXXZ"(%struct.ImportMembers* %this) // M32-DAG: declare dllimport x86_thiscallcc void @"\01?normalDecl@ImportMembers@@QAEXXZ"(%struct.ImportMembers*) // M64-DAG: declare dllimport void @"\01?normalDecl@ImportMembers@@QEAAXXZ"(%struct.ImportMembers*) // M32-DAG: declare dllimport x86_thiscallcc void @"\01?normalInclass@ImportMembers@@QAEXXZ"(%struct.ImportMembers*) @@ -95,8 +95,8 @@ struct ImportMembers { __declspec(dllimport) void normalInlineDef(); __declspec(dllimport) inline void normalInlineDecl(); - // M32-DAG: define x86_thiscallcc void @"\01?virtualDef@ImportMembers@@UAEXXZ"(%struct.ImportMembers* %this) - // M64-DAG: define void @"\01?virtualDef@ImportMembers@@UEAAXXZ"(%struct.ImportMembers* %this) + // M32-DAG: define dllexport x86_thiscallcc void @"\01?virtualDef@ImportMembers@@UAEXXZ"(%struct.ImportMembers* %this) + // M64-DAG: define dllexport void @"\01?virtualDef@ImportMembers@@UEAAXXZ"(%struct.ImportMembers* %this) // M32-DAG: declare dllimport x86_thiscallcc void @"\01?virtualDecl@ImportMembers@@UAEXXZ"(%struct.ImportMembers*) // M64-DAG: declare dllimport void @"\01?virtualDecl@ImportMembers@@UEAAXXZ"(%struct.ImportMembers*) // M32-DAG: declare dllimport x86_thiscallcc void @"\01?virtualInclass@ImportMembers@@UAEXXZ"(%struct.ImportMembers*) @@ -127,7 +127,7 @@ struct ImportMembers { __declspec(dllimport) virtual void virtualInlineDef(); __declspec(dllimport) virtual inline void virtualInlineDecl(); - // MSC-DAG: define void @"\01?staticDef@ImportMembers@@SAXXZ"() + // MSC-DAG: define dllexport void @"\01?staticDef@ImportMembers@@SAXXZ"() // MSC-DAG: declare dllimport void @"\01?staticDecl@ImportMembers@@SAXXZ"() // MSC-DAG: declare dllimport void @"\01?staticInclass@ImportMembers@@SAXXZ"() // MSC-DAG: declare dllimport void @"\01?staticInlineDef@ImportMembers@@SAXXZ"() @@ -235,8 +235,8 @@ USEMV(ImportMembers, ConstexprField) // Import individual members of a nested class. struct ImportMembers::Nested { - // M32-DAG: define x86_thiscallcc void @"\01?normalDef@Nested@ImportMembers@@QAEXXZ"(%"struct.ImportMembers::Nested"* %this) - // M64-DAG: define void @"\01?normalDef@Nested@ImportMembers@@QEAAXXZ"(%"struct.ImportMembers::Nested"* %this) + // M32-DAG: define dllexport x86_thiscallcc void @"\01?normalDef@Nested@ImportMembers@@QAEXXZ"(%"struct.ImportMembers::Nested"* %this) + // M64-DAG: define dllexport void @"\01?normalDef@Nested@ImportMembers@@QEAAXXZ"(%"struct.ImportMembers::Nested"* %this) // M32-DAG: declare dllimport x86_thiscallcc void @"\01?normalDecl@Nested@ImportMembers@@QAEXXZ"(%"struct.ImportMembers::Nested"*) // M64-DAG: declare dllimport void @"\01?normalDecl@Nested@ImportMembers@@QEAAXXZ"(%"struct.ImportMembers::Nested"*) // M32-DAG: declare dllimport x86_thiscallcc void @"\01?normalInclass@Nested@ImportMembers@@QAEXXZ"(%"struct.ImportMembers::Nested"*) @@ -267,8 +267,8 @@ struct ImportMembers::Nested { __declspec(dllimport) void normalInlineDef(); __declspec(dllimport) inline void normalInlineDecl(); - // M32-DAG: define x86_thiscallcc void @"\01?virtualDef@Nested@ImportMembers@@UAEXXZ"(%"struct.ImportMembers::Nested"* %this) - // M64-DAG: define void @"\01?virtualDef@Nested@ImportMembers@@UEAAXXZ"(%"struct.ImportMembers::Nested"* %this) + // M32-DAG: define dllexport x86_thiscallcc void @"\01?virtualDef@Nested@ImportMembers@@UAEXXZ"(%"struct.ImportMembers::Nested"* %this) + // M64-DAG: define dllexport void @"\01?virtualDef@Nested@ImportMembers@@UEAAXXZ"(%"struct.ImportMembers::Nested"* %this) // M32-DAG: declare dllimport x86_thiscallcc void @"\01?virtualDecl@Nested@ImportMembers@@UAEXXZ"(%"struct.ImportMembers::Nested"*) // M64-DAG: declare dllimport void @"\01?virtualDecl@Nested@ImportMembers@@UEAAXXZ"(%"struct.ImportMembers::Nested"*) // M32-DAG: declare dllimport x86_thiscallcc void @"\01?virtualInclass@Nested@ImportMembers@@UAEXXZ"(%"struct.ImportMembers::Nested"*) @@ -300,7 +300,7 @@ struct ImportMembers::Nested { __declspec(dllimport) virtual void virtualInlineDef(); __declspec(dllimport) virtual inline void virtualInlineDecl(); - // MSC-DAG: define void @"\01?staticDef@Nested@ImportMembers@@SAXXZ"() + // MSC-DAG: define dllexport void @"\01?staticDef@Nested@ImportMembers@@SAXXZ"() // MSC-DAG: declare dllimport void @"\01?staticDecl@Nested@ImportMembers@@SAXXZ"() // MSC-DAG: declare dllimport void @"\01?staticInclass@Nested@ImportMembers@@SAXXZ"() // MSC-DAG: declare dllimport void @"\01?staticInlineDef@Nested@ImportMembers@@SAXXZ"() @@ -595,16 +595,16 @@ inline ImportDefaultedDefs::ImportDefaultedDefs(const ImportDefaultedDefs&) = de // G64-DAG: define linkonce_odr dereferenceable({{[0-9]+}}) %struct.ImportDefaultedDefs* @_ZN19ImportDefaultedDefsaSERKS_(%struct.ImportDefaultedDefs* %this, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}})) inline ImportDefaultedDefs& ImportDefaultedDefs::operator=(const ImportDefaultedDefs&) = default; -// M32-DAG: define x86_thiscallcc %struct.ImportDefaultedDefs* @"\01??0ImportDefaultedDefs@@QAE@$$QAU0@@Z"(%struct.ImportDefaultedDefs* returned %this, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}})) -// M64-DAG: define %struct.ImportDefaultedDefs* @"\01??0ImportDefaultedDefs@@QEAA@$$QEAU0@@Z"(%struct.ImportDefaultedDefs* returned %this, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}})) +// M32-DAG: define dllexport x86_thiscallcc %struct.ImportDefaultedDefs* @"\01??0ImportDefaultedDefs@@QAE@$$QAU0@@Z"(%struct.ImportDefaultedDefs* returned %this, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}})) +// M64-DAG: define dllexport %struct.ImportDefaultedDefs* @"\01??0ImportDefaultedDefs@@QEAA@$$QEAU0@@Z"(%struct.ImportDefaultedDefs* returned %this, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}})) // G32-DAG: define x86_thiscallcc void @_ZN19ImportDefaultedDefsC1EOS_(%struct.ImportDefaultedDefs* %this, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}})) // G64-DAG: define void @_ZN19ImportDefaultedDefsC1EOS_(%struct.ImportDefaultedDefs* %this, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}})) // G32-DAG: define x86_thiscallcc void @_ZN19ImportDefaultedDefsC2EOS_(%struct.ImportDefaultedDefs* %this, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}})) // G64-DAG: define void @_ZN19ImportDefaultedDefsC2EOS_(%struct.ImportDefaultedDefs* %this, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}})) ImportDefaultedDefs::ImportDefaultedDefs(ImportDefaultedDefs&&) = default; // dllimport ignored -// M32-DAG: define x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportDefaultedDefs* @"\01??4ImportDefaultedDefs@@QAEAAU0@$$QAU0@@Z"(%struct.ImportDefaultedDefs* %this, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}})) -// M64-DAG: define dereferenceable({{[0-9]+}}) %struct.ImportDefaultedDefs* @"\01??4ImportDefaultedDefs@@QEAAAEAU0@$$QEAU0@@Z"(%struct.ImportDefaultedDefs* %this, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}})) +// M32-DAG: define dllexport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportDefaultedDefs* @"\01??4ImportDefaultedDefs@@QAEAAU0@$$QAU0@@Z"(%struct.ImportDefaultedDefs* %this, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}})) +// M64-DAG: define dllexport dereferenceable({{[0-9]+}}) %struct.ImportDefaultedDefs* @"\01??4ImportDefaultedDefs@@QEAAAEAU0@$$QEAU0@@Z"(%struct.ImportDefaultedDefs* %this, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}})) // G32-DAG: define x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportDefaultedDefs* @_ZN19ImportDefaultedDefsaSEOS_(%struct.ImportDefaultedDefs* %this, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}})) // G64-DAG: define dereferenceable({{[0-9]+}}) %struct.ImportDefaultedDefs* @_ZN19ImportDefaultedDefsaSEOS_(%struct.ImportDefaultedDefs* %this, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}})) ImportDefaultedDefs& ImportDefaultedDefs::operator=(ImportDefaultedDefs&&) = default; // dllimport ignored diff --git a/test/CodeGenCXX/dllimport-rtti.cpp b/test/CodeGenCXX/dllimport-rtti.cpp index 071ce278a5bb..4baee50fcff3 100644 --- a/test/CodeGenCXX/dllimport-rtti.cpp +++ b/test/CodeGenCXX/dllimport-rtti.cpp @@ -4,7 +4,8 @@ struct __declspec(dllimport) S { virtual void f() {} } s; -// MSVC-DAG: @"\01??_7S@@6B@" = available_externally dllimport +// MSVC: [[VF_S:.*]] = private unnamed_addr constant [2 x i8*] +// MSVC-DAG: @"\01??_SS@@6B@" = unnamed_addr alias i8*, getelementptr inbounds ([2 x i8*], [2 x i8*]* [[VF_S]], i32 0, i32 1) // MSVC-DAG: @"\01??_R0?AUS@@@8" = linkonce_odr // MSVC-DAG: @"\01??_R1A@?0A@EA@S@@8" = linkonce_odr // MSVC-DAG: @"\01??_R2S@@8" = linkonce_odr diff --git a/test/CodeGenCXX/dllimport.cpp b/test/CodeGenCXX/dllimport.cpp index b9c850b8b87b..aff240f28769 100644 --- a/test/CodeGenCXX/dllimport.cpp +++ b/test/CodeGenCXX/dllimport.cpp @@ -27,6 +27,7 @@ struct ExplicitSpec_NotImported {}; #define USEVAR(var) USEVARTYPE(int, var) #define USE(func) void UNIQ(use)() { func(); } #define USEMEMFUNC(class, func) void (class::*UNIQ(use)())() { return &class::func; } +#define USESTATICMEMFUNC(class, func) void (*UNIQ(use)())() { return &class::func; } #define USECLASS(class) void UNIQ(USE)() { class x; } #define USECOPYASSIGN(class) class& (class::*UNIQ(use)())(class&) { return &class::operator=; } #define USEMOVEASSIGN(class) class& (class::*UNIQ(use)())(class&&) { return &class::operator=; } @@ -263,7 +264,7 @@ __declspec(dllimport) void redecl2(); void redecl2(); USE(redecl2) -// MSC-DAG: define void @"\01?redecl3@@YAXXZ"() +// MSC-DAG: define dllexport void @"\01?redecl3@@YAXXZ"() // GNU-DAG: define void @_Z7redecl3v() __declspec(dllimport) void redecl3(); void redecl3() {} // dllimport ignored @@ -275,7 +276,7 @@ USE(redecl3) // GNU-DAG: declare dllimport void @_Z7friend1v() // MSC-DAG: declare void @"\01?friend2@@YAXXZ"() // GNU-DAG: declare void @_Z7friend2v() -// MSC-DAG: define void @"\01?friend3@@YAXXZ"() +// MSC-DAG: define dllexport void @"\01?friend3@@YAXXZ"() // GNU-DAG: define void @_Z7friend3v() // MSC-DAG: declare void @"\01?friend4@@YAXXZ"() // GNU-DAG: declare void @_Z7friend4v() @@ -590,6 +591,10 @@ struct __declspec(dllimport) T { void a() {} // MO1-DAG: define available_externally dllimport x86_thiscallcc void @"\01?a@T@@QAEXXZ" + static void StaticMethod(); + // MSC-DAG: declare dllimport void @"\01?StaticMethod@T@@SAXXZ"() + // GNU-DAG: declare dllimport void @_ZN1T12StaticMethodEv() + static int b; // MO1-DAG: @"\01?b@T@@2HA" = external dllimport global i32 @@ -602,6 +607,7 @@ struct __declspec(dllimport) T { // M19-DAG: define available_externally dllimport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.T* @"\01??4T@@QAEAAU0@$$QAU0@@Z" }; USEMEMFUNC(T, a) +USESTATICMEMFUNC(T, StaticMethod) USEVAR(T::b) USECOPYASSIGN(T) USEMOVEASSIGN(T) @@ -614,7 +620,7 @@ USEMEMFUNC(V, foo) struct __declspec(dllimport) W { virtual void foo() {} }; USECLASS(W) // vftable: -// MO1-DAG: @"\01??_7W@@6B@" = available_externally dllimport unnamed_addr constant [1 x i8*] [i8* bitcast (void (%struct.W*)* @"\01?foo@W@@UAEXXZ" to i8*)] +// MO1-DAG: @"\01??_SW@@6B@" = linkonce_odr unnamed_addr constant [1 x i8*] [i8* bitcast (void (%struct.W*)* @"\01?foo@W@@UAEXXZ" to i8*)] // GO1-DAG: @_ZTV1W = available_externally dllimport unnamed_addr constant [3 x i8*] [i8* null, i8* null, i8* bitcast (void (%struct.W*)* @_ZN1W3fooEv to i8*)] struct __declspec(dllimport) KeyFuncClass { @@ -650,7 +656,7 @@ namespace DontUseDtorAlias { namespace Vtordisp { // Don't dllimport the vtordisp. - // MO1-DAG: define linkonce_odr x86_thiscallcc void @"\01?f@?$C@D@Vtordisp@@$4PPPPPPPM@A@AEXXZ" + // MO1-DAG: define linkonce_odr x86_thiscallcc void @"\01?f@?$C@H@Vtordisp@@$4PPPPPPPM@A@AEXXZ" class Base { virtual void f() {} @@ -661,7 +667,7 @@ namespace Vtordisp { C() {} virtual void f() {} }; - template class C<char>; + USECLASS(C<int>); } namespace ClassTemplateStaticDef { @@ -670,7 +676,7 @@ namespace ClassTemplateStaticDef { static int x; }; template <typename T> int S<T>::x; - // MSC-DAG: @"\01?x@?$S@H@ClassTemplateStaticDef@@2HA" = available_externally dllimport global i32 0 + // MSC-DAG: @"\01?x@?$S@H@ClassTemplateStaticDef@@2HA" = external dllimport global i32 int f() { return S<int>::x; } // Partial class template specialization static field: @@ -679,7 +685,7 @@ namespace ClassTemplateStaticDef { static int x; }; template <typename A> int T<A*>::x; - // GNU-DAG: @_ZN22ClassTemplateStaticDef1TIPvE1xE = available_externally dllimport global i32 0 + // GNU-DAG: @_ZN22ClassTemplateStaticDef1TIPvE1xE = external dllimport global i32 int g() { return T<void*>::x; } } @@ -692,26 +698,31 @@ namespace PR19933 { template <typename T> struct A { static NonPOD x; }; template <typename T> NonPOD A<T>::x; template struct __declspec(dllimport) A<int>; - // MSC-DAG: @"\01?x@?$A@H@PR19933@@2UNonPOD@2@A" = available_externally dllimport global %"struct.PR19933::NonPOD" zeroinitializer + USEVARTYPE(NonPOD, A<int>::x); + // MSC-DAG: @"\01?x@?$A@H@PR19933@@2UNonPOD@2@A" = external dllimport global %"struct.PR19933::NonPOD" int f(); template <typename T> struct B { static int x; }; template <typename T> int B<T>::x = f(); template struct __declspec(dllimport) B<int>; - // MSC-DAG: @"\01?x@?$B@H@PR19933@@2HA" = available_externally dllimport global i32 0 + USEVAR(B<int>::x); + // MSC-DAG: @"\01?x@?$B@H@PR19933@@2HA" = external dllimport global i32 constexpr int g() { return 42; } template <typename T> struct C { static int x; }; template <typename T> int C<T>::x = g(); template struct __declspec(dllimport) C<int>; - // MSC-DAG: @"\01?x@?$C@H@PR19933@@2HA" = available_externally dllimport global i32 42 + USEVAR(C<int>::x); + // MSC-DAG: @"\01?x@?$C@H@PR19933@@2HA" = external dllimport global i32 template <int I> struct D { static int x, y; }; template <int I> int D<I>::x = I + 1; template <int I> int D<I>::y = I + f(); template struct __declspec(dllimport) D<42>; - // MSC-DAG: @"\01?x@?$D@$0CK@@PR19933@@2HA" = available_externally dllimport global i32 43 - // MSC-DAG: @"\01?y@?$D@$0CK@@PR19933@@2HA" = available_externally dllimport global i32 0 + USEVAR(D<42>::x); + USEVAR(D<42>::y); + // MSC-DAG: @"\01?x@?$D@$0CK@@PR19933@@2HA" = external dllimport global i32 + // MSC-DAG: @"\01?y@?$D@$0CK@@PR19933@@2HA" = external dllimport global i32 } namespace PR21355 { @@ -737,6 +748,17 @@ namespace PR21366 { inline void S::outOfClassInlineMethod() {} } +namespace PR27319 { + // Make sure we don't assert due to not having checked for operator delete on + // the destructor. + template <typename> struct A { + virtual ~A() = default; + }; + extern template struct __declspec(dllimport) A<int>; + void f() { new A<int>(); } + // MO1-DAG: @"\01??_S?$A@H@PR27319@@6B@" = linkonce_odr unnamed_addr constant [1 x i8*] +} + // MS ignores DLL attributes on partial specializations. template <typename T> struct PartiallySpecializedClassTemplate {}; template <typename T> struct __declspec(dllimport) PartiallySpecializedClassTemplate<T*> { void f(); }; @@ -788,6 +810,36 @@ template struct __declspec(dllimport) PR23770DerivedTemplate<int>; USEMEMFUNC(PR23770BaseTemplate<int>, f); // M32-DAG: declare dllimport x86_thiscallcc void @"\01?f@?$PR23770BaseTemplate@H@@QAEXXZ" +namespace PR27810 { + template <class T> + struct basic_ostream { + struct sentry { + sentry() { } + void foo() { } + }; + }; + template class __declspec(dllimport) basic_ostream<char>; + // The explicit instantiation definition acts as an explicit instantiation + // *declaration*, dllimport is not inherited by the inner class, and no + // functions are emitted unless they are used. + + USEMEMFUNC(basic_ostream<char>::sentry, foo); + // M32-DAG: define linkonce_odr x86_thiscallcc void @"\01?foo@sentry@?$basic_ostream@D@PR27810@@QAEXXZ" + // M32-NOT: ??0sentry@?$basic_ostream@D@PR27810@@QAE@XZ +} + +namespace PR27811 { + template <class T> struct codecvt { + virtual ~codecvt() { } + }; + template class __declspec(dllimport) codecvt<char>; + + // dllimport means this explicit instantiation definition gets treated as a + // declaration. Thus, the vtable should not be marked used, and in fact + // nothing for this class should be emitted at all since it's not used. + // M32-NOT: codecvt +} + //===----------------------------------------------------------------------===// // Classes with template base classes //===----------------------------------------------------------------------===// diff --git a/test/CodeGenCXX/duplicate-mangled-name.cpp b/test/CodeGenCXX/duplicate-mangled-name.cpp index 104bb6eb4d62..8c8f6e0311c3 100644 --- a/test/CodeGenCXX/duplicate-mangled-name.cpp +++ b/test/CodeGenCXX/duplicate-mangled-name.cpp @@ -1,5 +1,7 @@ // RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm-only %s -verify -DTEST1 -// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm-only %s -verify -DTEST2 +// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm-only %s -verify -DTEST2 -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm-only %s -verify -DTEST3 +// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm-only %s -verify -DTEST4 #ifdef TEST1 @@ -14,28 +16,61 @@ extern "C" { #elif TEST2 -// We expect no warnings here, as there is only declaration of _ZN1TD1Ev function, no definitions. +// expected-no-diagnostics + +// We expect no warnings here, as there is only declaration of _ZN1TD1Ev +// function, no definitions. extern "C" void _ZN1TD1Ev(); struct T { ~T() {} }; -void foo() { +// We expect no warnings here, as there is only declaration of _ZN2nm3abcE +// global, no definitions. +extern "C" { + int _ZN2nm3abcE; +} + +namespace nm { + float abc = 2; +} +// CHECK: @_ZN2nm3abcE = global float + +float foo() { _ZN1TD1Ev(); +// CHECK: call void bitcast ({{.*}} (%struct.T*)* @_ZN1TD1Ev to void ()*)() T t; +// CHECK: call {{.*}} @_ZN1TD1Ev(%struct.T* %t) + return _ZN2nm3abcE + nm::abc; } +#elif TEST3 + extern "C" void _ZN2T2D2Ev() {}; // expected-note {{previous definition is here}} struct T2 { ~T2() {} // expected-error {{definition with same mangled name as another definition}} }; -void bar() { +void foo() { _ZN2T2D2Ev(); T2 t; } +#elif TEST4 + +extern "C" { + int _ZN2nm3abcE = 1; // expected-note {{previous definition is here}} +} + +namespace nm { + float abc = 2; // expected-error {{definition with same mangled name as another definition}} +} + +float foo() { + return _ZN2nm3abcE + nm::abc; +} + #else #error Unknwon test diff --git a/test/CodeGenCXX/eh.cpp b/test/CodeGenCXX/eh.cpp index b44e8144bb27..db0576a1baeb 100644 --- a/test/CodeGenCXX/eh.cpp +++ b/test/CodeGenCXX/eh.cpp @@ -448,5 +448,27 @@ namespace test16 { } } +namespace test17 { +class BaseException { +private: + int a[4]; +public: + BaseException() {}; +}; + +class DerivedException: public BaseException { +}; + +int foo() { + throw DerivedException(); + // The alignment passed to memset is 8, not 16, on Darwin. + + // CHECK: [[T0:%.*]] = call i8* @__cxa_allocate_exception(i64 16) + // CHECK-NEXT: [[T1:%.*]] = bitcast i8* [[T0]] to %"class.test17::DerivedException"* + // CHECK-NEXT: [[T2:%.*]] = bitcast %"class.test17::DerivedException"* [[T1]] to i8* + // CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* [[T2]], i8 0, i64 16, i32 8, i1 false) +} +} + // CHECK: attributes [[NUW]] = { nounwind } // CHECK: attributes [[NR]] = { noreturn } diff --git a/test/CodeGenCXX/exceptions-cxx-ehsc.cpp b/test/CodeGenCXX/exceptions-cxx-ehsc.cpp new file mode 100644 index 000000000000..c660d145393a --- /dev/null +++ b/test/CodeGenCXX/exceptions-cxx-ehsc.cpp @@ -0,0 +1,31 @@ +// RUN: %clang_cc1 -emit-llvm %s -o - -triple=i386-pc-win32 -fexceptions -fcxx-exceptions -fexternc-nounwind | FileCheck %s + +namespace test1 { +struct Cleanup { ~Cleanup(); }; +extern "C" void never_throws(); +void may_throw(); + +void caller() { + Cleanup x; + never_throws(); + may_throw(); +} +} +// CHECK-LABEL: define void @"\01?caller@test1@@YAXXZ"( +// CHECK: call void @never_throws( +// CHECK: invoke void @"\01?may_throw@test1@@YAXXZ"( + +namespace test2 { +struct Cleanup { ~Cleanup(); }; +extern "C" void throws_int() throw(int); +void may_throw(); + +void caller() { + Cleanup x; + throws_int(); + may_throw(); +} +} +// CHECK-LABEL: define void @"\01?caller@test2@@YAXXZ"( +// CHECK: invoke void @throws_int( +// CHECK: invoke void @"\01?may_throw@test2@@YAXXZ"( diff --git a/test/CodeGenCXX/exceptions-cxx-new.cpp b/test/CodeGenCXX/exceptions-cxx-new.cpp index 3767f3321c3e..3329aea32ef2 100644 --- a/test/CodeGenCXX/exceptions-cxx-new.cpp +++ b/test/CodeGenCXX/exceptions-cxx-new.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 %s -triple i686-pc-win32 -fms-extensions -fexceptions -fcxx-exceptions -fnew-ms-eh -emit-llvm -o - -std=c++11 | FileCheck %s +// RUN: %clang_cc1 %s -triple i686-pc-win32 -fms-extensions -fexceptions -fcxx-exceptions -emit-llvm -o - -std=c++11 | FileCheck %s int f(int); @@ -72,6 +72,6 @@ void test_cleanup() { // CHECK: ret void // CHECK: [[TERMINATE]] -// CHECK: cleanuppad within none [] -// CHECK-NEXT: call void @"\01?terminate@@YAXXZ"() +// CHECK: %[[CLEANUPPAD:.*]] = cleanuppad within none [] +// CHECK-NEXT: call void @"\01?terminate@@YAXXZ"() {{.*}} [ "funclet"(token %[[CLEANUPPAD]]) ] diff --git a/test/CodeGenCXX/exceptions-seh-filter-captures.cpp b/test/CodeGenCXX/exceptions-seh-filter-captures.cpp index 4e8be72089d5..ab75a87698ab 100644 --- a/test/CodeGenCXX/exceptions-seh-filter-captures.cpp +++ b/test/CodeGenCXX/exceptions-seh-filter-captures.cpp @@ -70,14 +70,14 @@ void test_lambda() { lambda(); } -// CHECK-LABEL: define internal void @"\01??R<lambda_0>@?test_lambda@@YAXXZ@QEBAXXZ"(%class.anon* %this) +// CHECK-LABEL: define internal void @"\01??R<lambda_0>@?0??test_lambda@@YAXXZ@QEBA@XZ"(%class.anon* %this) // CHECK: @llvm.localescape(i32* %[[l2_addr:[^, ]*]]) // CHECK: store i32 42, i32* %[[l2_addr]], align 4 // CHECK: invoke void @might_crash() -// CHECK-LABEL: define internal i32 @"\01?filt$0@0@?R<lambda_0>@?test_lambda@@YAXXZ@"(i8* %exception_pointers, i8* %frame_pointer) -// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.x86.seh.recoverfp(i8* bitcast (void (%class.anon*)* @"\01??R<lambda_0>@?test_lambda@@YAXXZ@QEBAXXZ" to i8*), i8* %frame_pointer) -// CHECK: %[[l2_i8:[^ ]*]] = call i8* @llvm.localrecover(i8* bitcast (void (%class.anon*)* @"\01??R<lambda_0>@?test_lambda@@YAXXZ@QEBAXXZ" to i8*), i8* %[[fp]], i32 0) +// CHECK-LABEL: define internal i32 @"\01?filt$0@0@?R<lambda_0>@?0??test_lambda@@YAXXZ@"(i8* %exception_pointers, i8* %frame_pointer) +// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.x86.seh.recoverfp(i8* bitcast (void (%class.anon*)* @"\01??R<lambda_0>@?0??test_lambda@@YAXXZ@QEBA@XZ" to i8*), i8* %frame_pointer) +// CHECK: %[[l2_i8:[^ ]*]] = call i8* @llvm.localrecover(i8* bitcast (void (%class.anon*)* @"\01??R<lambda_0>@?0??test_lambda@@YAXXZ@QEBA@XZ" to i8*), i8* %[[fp]], i32 0) // CHECK: %[[l2_ptr:[^ ]*]] = bitcast i8* %[[l2_i8]] to i32* // CHECK: %[[l2:[^ ]*]] = load i32, i32* %[[l2_ptr]] // CHECK: call i32 (i32, ...) @basic_filter(i32 %[[l2]]) diff --git a/test/CodeGenCXX/exceptions-seh.cpp b/test/CodeGenCXX/exceptions-seh.cpp index abbe95be3404..589bc2265760 100644 --- a/test/CodeGenCXX/exceptions-seh.cpp +++ b/test/CodeGenCXX/exceptions-seh.cpp @@ -95,7 +95,7 @@ void use_seh_in_lambda() { // NOCXX-NOT: invoke // NOCXX: ret void -// CHECK-LABEL: define internal void @"\01??R<lambda_0>@?use_seh_in_lambda@@YAXXZ@QEBAXXZ"(%class.anon* %this) +// CHECK-LABEL: define internal void @"\01??R<lambda_0>@?0??use_seh_in_lambda@@YAXXZ@QEBA@XZ"(%class.anon* %this) // CXXEH-SAME: personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*) // CHECK: invoke void @might_throw() #[[NOINLINE]] // CHECK: catchpad diff --git a/test/CodeGenCXX/exceptions.cpp b/test/CodeGenCXX/exceptions.cpp index ff76b11350db..86616d1e2c62 100644 --- a/test/CodeGenCXX/exceptions.cpp +++ b/test/CodeGenCXX/exceptions.cpp @@ -30,7 +30,7 @@ namespace test1 { A *a() { // CHECK: define [[A:%.*]]* @_ZN5test11aEv() - // CHECK: [[NEW:%.*]] = call noalias i8* @_Znwm(i64 8) + // CHECK: [[NEW:%.*]] = call 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]] @@ -40,7 +40,7 @@ namespace test1 { A *b() { // CHECK: define [[A:%.*]]* @_ZN5test11bEv() - // CHECK: [[NEW:%.*]] = call noalias i8* @_Znwm(i64 8) + // CHECK: [[NEW:%.*]] = call 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]]) @@ -56,7 +56,7 @@ namespace test1 { A *c() { // CHECK: define [[A:%.*]]* @_ZN5test11cEv() // CHECK: [[ACTIVE:%.*]] = alloca i1 - // CHECK-NEXT: [[NEW:%.*]] = call noalias i8* @_Znwm(i64 8) + // CHECK-NEXT: [[NEW:%.*]] = call i8* @_Znwm(i64 8) // CHECK-NEXT: store i1 true, i1* [[ACTIVE]] // CHECK-NEXT: [[CAST:%.*]] = bitcast i8* [[NEW]] to [[A]]* // CHECK-NEXT: invoke void @_ZN5test11BC1Ev([[B:%.*]]* [[T0:%.*]]) @@ -82,7 +82,7 @@ namespace test1 { A *d() { // CHECK: define [[A:%.*]]* @_ZN5test11dEv() // CHECK: [[ACTIVE:%.*]] = alloca i1 - // CHECK-NEXT: [[NEW:%.*]] = call noalias i8* @_Znwm(i64 8) + // CHECK-NEXT: [[NEW:%.*]] = call i8* @_Znwm(i64 8) // CHECK-NEXT: store i1 true, i1* [[ACTIVE]] // CHECK-NEXT: [[CAST:%.*]] = bitcast i8* [[NEW]] to [[A]]* // CHECK-NEXT: invoke void @_ZN5test11BC1Ev([[B:%.*]]* [[T0:%.*]]) @@ -100,7 +100,7 @@ namespace test1 { A *e() { // CHECK: define [[A:%.*]]* @_ZN5test11eEv() // CHECK: [[ACTIVE:%.*]] = alloca i1 - // CHECK-NEXT: [[NEW:%.*]] = call noalias i8* @_Znwm(i64 8) + // CHECK-NEXT: [[NEW:%.*]] = call i8* @_Znwm(i64 8) // CHECK-NEXT: store i1 true, i1* [[ACTIVE]] // CHECK-NEXT: [[CAST:%.*]] = bitcast i8* [[NEW]] to [[A]]* // CHECK-NEXT: invoke void @_ZN5test11BC1Ev([[B:%.*]]* [[T0:%.*]]) @@ -131,7 +131,7 @@ namespace test1 { // CHECK: define [[A:%.*]]* @_ZN5test11iEv() // CHECK: [[X:%.*]] = alloca [[A]]*, align 8 // CHECK: [[ACTIVE:%.*]] = alloca i1 - // CHECK: [[NEW:%.*]] = call noalias i8* @_Znwm(i64 8) + // CHECK: [[NEW:%.*]] = call i8* @_Znwm(i64 8) // CHECK-NEXT: store i1 true, i1* [[ACTIVE]] // CHECK-NEXT: [[CAST:%.*]] = bitcast i8* [[NEW]] to [[A]]* // CHECK-NEXT: invoke void @_ZN5test15makeBEv([[B:%.*]]* sret [[T0:%.*]]) @@ -422,7 +422,7 @@ namespace test9 { return new A[10]; } // CHECK: define {{%.*}}* @_ZN5test94testEv - // CHECK: [[TEST9_NEW:%.*]] = call noalias i8* @_Znam + // CHECK: [[TEST9_NEW:%.*]] = call i8* @_Znam // CHECK: call void @_ZdaPv(i8* [[TEST9_NEW]]) } diff --git a/test/CodeGenCXX/explicit-instantiation.cpp b/test/CodeGenCXX/explicit-instantiation.cpp index 6076444c25b0..7e00d78e4834 100644 --- a/test/CodeGenCXX/explicit-instantiation.cpp +++ b/test/CodeGenCXX/explicit-instantiation.cpp @@ -1,5 +1,6 @@ // RUN: %clang_cc1 -emit-llvm -triple i686-pc-linux-gnu -std=c++1y -o - %s | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-NO-OPT // RUN: %clang_cc1 -emit-llvm -triple i686-pc-linux-gnu -std=c++1y -O3 -disable-llvm-optzns -o - %s | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-OPT +// RUN: %clang_cc1 -emit-llvm -triple i686-pc-win32 -std=c++1y -o - %s | FileCheck %s --check-prefix=CHECK-MS // This check logically is attached to 'template int S<int>::i;' below. // CHECK: @_ZN1SIiE1iE = weak_odr global i32 @@ -103,6 +104,28 @@ int g() { return S<int>().f(); } template struct S<int>; } +namespace NestedClasses { + // Check how explicit instantiation of an outer class affects the inner class. + template <typename T> struct Outer { + struct Inner { + void f() {} + }; + }; + + // Explicit instantiation definition of Outer causes explicit instantiation + // definition of Inner. + template struct Outer<int>; + // CHECK: define weak_odr void @_ZN13NestedClasses5OuterIiE5Inner1fEv + // CHECK-MS: define weak_odr x86_thiscallcc void @"\01?f@Inner@?$Outer@H@NestedClasses@@QAEXXZ" + + // Explicit instantiation declaration of Outer causes explicit instantiation + // declaration of Inner, but not in MSVC mode. + extern template struct Outer<char>; + auto use = &Outer<char>::Inner::f; + // CHECK: {{declare|define available_externally}} void @_ZN13NestedClasses5OuterIcE5Inner1fEv + // CHECK-MS: define linkonce_odr x86_thiscallcc void @"\01?f@Inner@?$Outer@D@NestedClasses@@QAEXXZ" +} + // Check that we emit definitions from explicit instantiations even when they // occur prior to the definition itself. template <typename T> struct S { diff --git a/test/CodeGenCXX/extern-c.cpp b/test/CodeGenCXX/extern-c.cpp index 5b59a38ba0d7..1046915fcaa2 100644 --- a/test/CodeGenCXX/extern-c.cpp +++ b/test/CodeGenCXX/extern-c.cpp @@ -16,8 +16,23 @@ extern "C" struct d; // CHECK-NOT: should_not_appear extern "C++" int should_not_appear; +// CHECK: @_ZN3foo10extern_cxxE = global +extern "C++" int extern_cxx = 0; + } +// CHECK-NOT: @global_a = global +extern "C" int global_a; + +// CHECK: @global_b = global +extern "C" int global_b = 0; + +// CHECK-NOT: should_not_appear +extern "C++" int should_not_appear; + +// CHECK: @extern_cxx = global +extern "C++" int extern_cxx = 0; + namespace test1 { namespace { struct X {}; @@ -59,10 +74,10 @@ extern "C" { // CHECK-NOT: @unused // CHECK-NOT: @duplicate_internal - // CHECK: @internal_var = internal alias i32, i32* @_Z12internal_var + // CHECK: @internal_var = internal alias i32, i32* @_ZL12internal_var // CHECK-NOT: @unused // CHECK-NOT: @duplicate_internal - // CHECK: @internal_fn = internal alias i32 (), i32 ()* @_Z11internal_fnv + // CHECK: @internal_fn = internal alias i32 (), i32 ()* @_ZL11internal_fnv // CHECK-NOT: @unused // CHECK-NOT: @duplicate_internal } diff --git a/test/CodeGenCXX/float128-declarations.cpp b/test/CodeGenCXX/float128-declarations.cpp new file mode 100644 index 000000000000..e1604a61cac7 --- /dev/null +++ b/test/CodeGenCXX/float128-declarations.cpp @@ -0,0 +1,138 @@ +// RUN: %clang_cc1 -emit-llvm -triple powerpc64-unknown-unknown \ +// RUN: -target-feature +float128 -std=c++11 %s -o - | FileCheck %s +// RUN: %clang_cc1 -emit-llvm -triple powerpc64le-unknown-unknown \ +// RUN: -target-feature +float128 -std=c++11 %s -o - | FileCheck %s +// RUN: %clang_cc1 -emit-llvm -triple i386-unknown-linux-gnu -std=c++11 \ +// RUN: %s -o - | FileCheck %s -check-prefix=CHECK-X86 +// RUN: %clang_cc1 -emit-llvm -triple x86_64-unknown-linux-gnu -std=c++11 \ +// RUN: %s -o - | FileCheck %s -check-prefix=CHECK-X86 +// RUN: %clang_cc1 -emit-llvm -triple systemz-unknown-linux-gnu -std=c++11 \ +// RUN: %s -o - | FileCheck %s -check-prefix=CHECK-SYSZ +// +/* Various contexts where type __float128 can appear. The different check + prefixes are due to different mangling on X86 and different calling + convention on SystemZ. */ + +/* Namespace */ +namespace { + __float128 f1n; + __float128 f2n = 33.q; + __float128 arr1n[10]; + __float128 arr2n[] = { 1.2q, 3.0q, 3.e11q }; + const volatile __float128 func1n(const __float128 &arg) { + return arg + f2n + arr1n[4] - arr2n[1]; + } +} + +/* File */ +__float128 f1f; +__float128 f2f = 32.4q; +static __float128 f3f = f2f; +__float128 arr1f[10]; +__float128 arr2f[] = { -1.2q, -3.0q, -3.e11q }; +__float128 func1f(__float128 arg); + +/* Class */ +class C1 { + __float128 f1c; + static const __float128 f2c; + volatile __float128 f3c; +public: + C1(__float128 arg) : f1c(arg), f3c(arg) { } + __float128 func1c(__float128 arg ) { + return f1c + arg; + } + static __float128 func2c(__float128 arg) { + return arg * C1::f2c; + } +}; + +/* Template */ +template <class C> C func1t(C arg) { return arg * 2.q; } +template <class C> struct S1 { + C mem1; +}; +template <> struct S1<__float128> { + __float128 mem2; +}; + +/* Local */ +int main(void) { + __float128 f1l = 123e220q; + __float128 f2l = -0.q; + __float128 f3l = 1.189731495357231765085759326628007e4932q; + C1 c1(f1l); + S1<__float128> s1 = { 132.q }; + __float128 f4l = func1n(f1l) + func1f(f2l) + c1.func1c(f3l) + c1.func2c(f1l) + + func1t(f1l) + s1.mem2 - f1n + f2n; +#if (__cplusplus >= 201103L) + auto f5l = -1.q, *f6l = &f2l, f7l = func1t(f3l); +#endif + __float128 f8l = f4l++; + __float128 arr1l[] = { -1.q, -0.q, -11.q }; +} +// CHECK-DAG: @_ZN12_GLOBAL__N_13f1nE = internal global fp128 0xL00000000000000000000000000000000 +// CHECK-DAG: @_ZN12_GLOBAL__N_13f2nE = internal global fp128 0xL00000000000000004004080000000000 +// CHECK-DAG: @_ZN12_GLOBAL__N_15arr1nE = internal global [10 x fp128] +// CHECK-DAG: @_ZN12_GLOBAL__N_15arr2nE = internal global [3 x fp128] [fp128 0xL33333333333333333FFF333333333333, fp128 0xL00000000000000004000800000000000, fp128 0xL00000000000000004025176592E00000] +// CHECK-DAG: define internal fp128 @_ZN12_GLOBAL__N_16func1nERKU10__float128(fp128* +// CHECK-DAG: @f1f = global fp128 0xL00000000000000000000000000000000 +// CHECK-DAG: @f2f = global fp128 0xL33333333333333334004033333333333 +// CHECK-DAG: @arr1f = global [10 x fp128] +// CHECK-DAG: @arr2f = global [3 x fp128] [fp128 0xL3333333333333333BFFF333333333333, fp128 0xL0000000000000000C000800000000000, fp128 0xL0000000000000000C025176592E00000] +// CHECK-DAG: declare fp128 @_Z6func1fU10__float128(fp128) +// CHECK-DAG: define linkonce_odr void @_ZN2C1C2EU10__float128(%class.C1* %this, fp128 %arg) +// CHECK-DAG: define linkonce_odr fp128 @_ZN2C16func2cEU10__float128(fp128 %arg) +// CHECK-DAG: define linkonce_odr fp128 @_Z6func1tIU10__float128ET_S0_(fp128 %arg) +// CHECK-DAG: @_ZZ4mainE2s1 = private unnamed_addr constant %struct.S1 { fp128 0xL00000000000000004006080000000000 } +// CHECK-DAG: store fp128 0xLF0AFD0EBFF292DCE42E0B38CDD83F26F, fp128* %f1l, align 16 +// CHECK-DAG: store fp128 0xL00000000000000008000000000000000, fp128* %f2l, align 16 +// CHECK-DAG: store fp128 0xLFFFFFFFFFFFFFFFF7FFEFFFFFFFFFFFF, fp128* %f3l, align 16 +// CHECK-DAG: store fp128 0xL0000000000000000BFFF000000000000, fp128* %f5l, align 16 +// CHECK-DAG: [[F4L:%[a-z0-9]+]] = load fp128, fp128* %f4l +// CHECK-DAG: [[INC:%[a-z0-9]+]] = fadd fp128 [[F4L]], 0xL00000000000000003FFF000000000000 +// CHECK-DAG: store fp128 [[INC]], fp128* %f4l + +// CHECK-X86-DAG: @_ZN12_GLOBAL__N_13f1nE = internal global fp128 0xL00000000000000000000000000000000 +// CHECK-X86-DAG: @_ZN12_GLOBAL__N_13f2nE = internal global fp128 0xL00000000000000004004080000000000 +// CHECK-X86-DAG: @_ZN12_GLOBAL__N_15arr1nE = internal global [10 x fp128] +// CHECK-X86-DAG: @_ZN12_GLOBAL__N_15arr2nE = internal global [3 x fp128] [fp128 0xL33333333333333333FFF333333333333, fp128 0xL00000000000000004000800000000000, fp128 0xL00000000000000004025176592E00000] +// CHECK-X86-DAG: define internal fp128 @_ZN12_GLOBAL__N_16func1nERKg(fp128* +// CHECK-X86-DAG: @f1f = global fp128 0xL00000000000000000000000000000000 +// CHECK-X86-DAG: @f2f = global fp128 0xL33333333333333334004033333333333 +// CHECK-X86-DAG: @arr1f = global [10 x fp128] +// CHECK-X86-DAG: @arr2f = global [3 x fp128] [fp128 0xL3333333333333333BFFF333333333333, fp128 0xL0000000000000000C000800000000000, fp128 0xL0000000000000000C025176592E00000] +// CHECK-X86-DAG: declare fp128 @_Z6func1fg(fp128) +// CHECK-X86-DAG: define linkonce_odr void @_ZN2C1C2Eg(%class.C1* %this, fp128 %arg) +// CHECK-X86-DAG: define linkonce_odr fp128 @_ZN2C16func2cEg(fp128 %arg) +// CHECK-X86-DAG: define linkonce_odr fp128 @_Z6func1tIgET_S0_(fp128 %arg) +// CHECK-X86-DAG: @_ZZ4mainE2s1 = private unnamed_addr constant %struct.S1 { fp128 0xL00000000000000004006080000000000 } +// CHECK-X86-DAG: store fp128 0xLF0AFD0EBFF292DCE42E0B38CDD83F26F, fp128* %f1l, align 16 +// CHECK-X86-DAG: store fp128 0xL00000000000000008000000000000000, fp128* %f2l, align 16 +// CHECK-X86-DAG: store fp128 0xLFFFFFFFFFFFFFFFF7FFEFFFFFFFFFFFF, fp128* %f3l, align 16 +// CHECK-X86-DAG: store fp128 0xL0000000000000000BFFF000000000000, fp128* %f5l, align 16 +// CHECK-X86-DAG: [[F4L:%[a-z0-9]+]] = load fp128, fp128* %f4l +// CHECK-X86-DAG: [[INC:%[a-z0-9]+]] = fadd fp128 [[F4L]], 0xL00000000000000003FFF000000000000 +// CHECK-X86-DAG: store fp128 [[INC]], fp128* %f4l + +// CHECK-SYSZ-DAG: @_ZN12_GLOBAL__N_13f1nE = internal global fp128 0xL00000000000000000000000000000000 +// CHECK-SYSZ-DAG: @_ZN12_GLOBAL__N_13f2nE = internal global fp128 0xL00000000000000004004080000000000 +// CHECK-SYSZ-DAG: @_ZN12_GLOBAL__N_15arr1nE = internal global [10 x fp128] +// CHECK-SYSZ-DAG: @_ZN12_GLOBAL__N_15arr2nE = internal global [3 x fp128] [fp128 0xL33333333333333333FFF333333333333, fp128 0xL00000000000000004000800000000000, fp128 0xL00000000000000004025176592E00000] +// CHECK-SYSZ-DAG: define internal void @_ZN12_GLOBAL__N_16func1nERKU10__float128(fp128* +// CHECK-SYSZ-DAG: @f1f = global fp128 0xL00000000000000000000000000000000 +// CHECK-SYSZ-DAG: @f2f = global fp128 0xL33333333333333334004033333333333 +// CHECK-SYSZ-DAG: @arr1f = global [10 x fp128] +// CHECK-SYSZ-DAG: @arr2f = global [3 x fp128] [fp128 0xL3333333333333333BFFF333333333333, fp128 0xL0000000000000000C000800000000000, fp128 0xL0000000000000000C025176592E00000] +// CHECK-SYSZ-DAG: declare void @_Z6func1fU10__float128(fp128* +// CHECK-SYSZ-DAG: define linkonce_odr void @_ZN2C1C2EU10__float128(%class.C1* %this, fp128* +// CHECK-SYSZ-DAG: define linkonce_odr void @_ZN2C16func2cEU10__float128(fp128* +// CHECK-SYSZ-DAG: define linkonce_odr void @_Z6func1tIU10__float128ET_S0_(fp128* +// CHECK-SYSZ-DAG: @_ZZ4mainE2s1 = private unnamed_addr constant %struct.S1 { fp128 0xL00000000000000004006080000000000 } +// CHECK-SYSZ-DAG: store fp128 0xLF0AFD0EBFF292DCE42E0B38CDD83F26F, fp128* %f1l, align 16 +// CHECK-SYSZ-DAG: store fp128 0xL00000000000000008000000000000000, fp128* %f2l, align 16 +// CHECK-SYSZ-DAG: store fp128 0xLFFFFFFFFFFFFFFFF7FFEFFFFFFFFFFFF, fp128* %f3l, align 16 +// CHECK-SYSZ-DAG: store fp128 0xL0000000000000000BFFF000000000000, fp128* %f5l, align 16 +// CHECK-SYSZ-DAG: [[F4L:%[a-z0-9]+]] = load fp128, fp128* %f4l +// CHECK-SYSZ-DAG: [[INC:%[a-z0-9]+]] = fadd fp128 [[F4L]], 0xL00000000000000003FFF000000000000 +// CHECK-SYSZ-DAG: store fp128 [[INC]], fp128* %f4l diff --git a/test/CodeGenCXX/goto.cpp b/test/CodeGenCXX/goto.cpp index c1a0eeccf811..27bd7affbac9 100644 --- a/test/CodeGenCXX/goto.cpp +++ b/test/CodeGenCXX/goto.cpp @@ -18,7 +18,7 @@ namespace test0 { // CHECK-NEXT: [[CLEANUPACTIVE:%.*]] = alloca i1 // CHECK: call void @_ZN5test01AC1Ev([[A]]* [[Y]]) // CHECK-NEXT: invoke void @_ZN5test01AC1Ev([[A]]* [[Z]]) - // CHECK: [[NEW:%.*]] = invoke noalias i8* @_Znwm(i64 1) + // CHECK: [[NEW:%.*]] = invoke i8* @_Znwm(i64 1) // CHECK: store i1 true, i1* [[CLEANUPACTIVE]] // CHECK: [[NEWCAST:%.*]] = bitcast i8* [[NEW]] to [[V]]* // CHECK-NEXT: invoke void @_ZN5test01AC1Ev([[A]]* [[TMP]]) diff --git a/test/CodeGenCXX/inheriting-constructor.cpp b/test/CodeGenCXX/inheriting-constructor.cpp index 42080a2dafa9..a3adf70ebb18 100644 --- a/test/CodeGenCXX/inheriting-constructor.cpp +++ b/test/CodeGenCXX/inheriting-constructor.cpp @@ -1,4 +1,8 @@ -// RUN: %clang_cc1 -std=c++11 -triple x86_64-apple-darwin10 -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -std=c++11 -triple i386-linux -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK --check-prefix=ITANIUM +// RUN: %clang_cc1 -std=c++11 -triple x86_64-darwin -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK --check-prefix=ITANIUM +// RUN: %clang_cc1 -std=c++11 -triple arm64-ehabi -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK --check-prefix=ITANIUM +// RUN: %clang_cc1 -std=c++11 -triple i386-windows -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK --check-prefix=MSABI --check-prefix=WIN32 +// RUN: %clang_cc1 -std=c++11 -triple x86_64-windows -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK --check-prefix=MSABI --check-prefix=WIN64 // PR12219 struct A { A(int); virtual ~A(); }; @@ -11,18 +15,396 @@ struct C { template<typename T> C(T); }; struct D : C { using C::C; }; D d(123); -// CHECK-LABEL: define void @_ZN1BD2Ev -// CHECK-LABEL: define void @_ZN1BD1Ev -// CHECK-LABEL: define void @_ZN1BD0Ev +// ITANIUM-LABEL: define void @_ZN1BD2Ev +// ITANIUM-LABEL: define void @_ZN1BD1Ev +// ITANIUM-LABEL: define void @_ZN1BD0Ev +// WIN32-LABEL: define {{.*}}void @"\01??1B@@UAE@XZ" +// WIN64-LABEL: define {{.*}}void @"\01??1B@@UEAA@XZ" -// CHECK-LABEL: define linkonce_odr void @_ZN1BC1Ei( -// CHECK: call void @_ZN1BC2Ei( +// ITANIUM-LABEL: define linkonce_odr void @_ZN1BCI11AEi( +// ITANIUM: call void @_ZN1BCI21AEi( -// CHECK-LABEL: define linkonce_odr void @_ZN1DC1IiEET_( -// CHECK: call void @_ZN1DC2IiEET_( +// ITANIUM-LABEL: define linkonce_odr void @_ZN1DCI11CIiEET_( +// ITANIUM: call void @_ZN1DCI21CIiEET_( -// CHECK-LABEL: define linkonce_odr void @_ZN1BC2Ei( -// CHECK: call void @_ZN1AC2Ei( +// WIN32-LABEL: define internal {{.*}} @"\01??0B@@QAE@H@Z"( +// WIN32: call {{.*}} @"\01??0A@@QAE@H@Z"( +// WIN64-LABEL: define internal {{.*}} @"\01??0B@@QEAA@H@Z"( +// WIN64: call {{.*}} @"\01??0A@@QEAA@H@Z"( -// CHECK-LABEL: define linkonce_odr void @_ZN1DC2IiEET_( -// CHECK: call void @_ZN1CC2IiEET_( +// WIN32-LABEL: define internal {{.*}} @"\01??0D@@QAE@H@Z"( +// WIN32: call {{.*}} @"\01??$?0H@C@@QAE@H@Z" +// WIN64-LABEL: define internal {{.*}} @"\01??0D@@QEAA@H@Z"( +// WIN64: call {{.*}} @"\01??$?0H@C@@QEAA@H@Z" + +struct Q { Q(int); Q(const Q&); ~Q(); }; +struct Z { Z(); Z(int); ~Z(); int n; }; + +namespace noninline_nonvirt { + struct A { A(int, Q&&, void *__attribute__((pass_object_size(0)))); int n; }; + struct B : Z, A { Z z; using A::A; }; + B b(1, 2, &b); + // ITANIUM-LABEL: define {{.*}} @__cxx_global_var_init + // ITANIUM: call void @_ZN1QC1Ei({{.*}} %[[TMP:.*]], i32 2) + // ITANIUM: call void @_ZN17noninline_nonvirt1BCI1NS_1AEEiO1QPvU17pass_object_size0({{.*}} @_ZN17noninline_nonvirt1bE, i32 1, {{.*}} %[[TMP]], i8* {{.*}} @_ZN17noninline_nonvirt1bE{{.*}}, i{{32|64}} 12) + // ITANIUM: call void @_ZN1QD1Ev({{.*}} %[[TMP]]) + // ITANIUM: call i32 @__cxa_atexit( + + // Complete object ctor for B delegates to base object ctor. + // ITANIUM-LABEL: define linkonce_odr void @_ZN17noninline_nonvirt1BCI1NS_1AEEiO1QPvU17pass_object_size0( + // ITANIUM: call void @_ZN17noninline_nonvirt1BCI2NS_1AEEiO1QPvU17pass_object_size0({{.*}}, i32 {{.*}}, %{{.*}}* {{.*}}, i8* {{.*}}, i{{32|64}} {{.*}}) + + // In MSABI, we don't have ctor variants. B ctor forwards to A ctor. + // MSABI-LABEL: define internal {{.*}} @"\01??0B@noninline_nonvirt@@Q{{AE|EAA}}@H$$Q{{E?}}AUQ@@P{{E?}}AXW4__pass_object_size0@__clang@@@Z"(%{{.*}}, i32{{.*}}, %{{.*}}, i8*{{.*}}, i{{32|64}}{{.*}}) + // MSABI: call {{.*}} @"\01??0Z@@Q{{AE|EAA}}@XZ"( + // MSABI: call {{.*}} @"\01??0A@noninline_nonvirt@@Q{{AE|EAA}}@H$$Q{{E?}}AUQ@@P{{E?}}AXW4__pass_object_size0@__clang@@@Z"(%{{.*}}, i32{{.*}}, %{{.*}}, i8*{{.*}}, i{{32|64}}{{.*}}) + // MSABI: call {{.*}} @"\01??0Z@@Q{{AE|EAA}}@XZ"( + + struct C : B { using B::B; }; + C c(1, 2, &c); + // Complete object ctor for C delegates. + // ITANIUM-LABEL: define linkonce_odr void @_ZN17noninline_nonvirt1CCI1NS_1AEEiO1QPvU17pass_object_size0( + // ITANIUM: call void @_ZN17noninline_nonvirt1CCI2NS_1AEEiO1QPvU17pass_object_size0({{.*}}, i32 {{.*}}, %{{.*}}* {{.*}}, i8* {{.*}}, i{{32|64}} {{.*}}) + + // MSABI-LABEL: define internal {{.*}} @"\01??0C@noninline_nonvirt@@Q{{AE|EAA}}@H$$Q{{E?}}AUQ@@P{{E?}}AXW4__pass_object_size0@__clang@@@Z"(%{{.*}}, i32{{.*}}, %{{.*}}, i8*{{.*}}, i{{32|64}}{{.*}}) + // MSABI: call {{.*}} @"\01??0B@noninline_nonvirt@@Q{{AE|EAA}}@H$$Q{{E?}}AUQ@@P{{E?}}AXW4__pass_object_size0@__clang@@@Z"(%{{.*}}, i32{{.*}}, %{{.*}}, i8*{{.*}}, i{{32|64}}{{.*}}) +} + +namespace noninline_virt { + struct A { A(int, Q&&, void *__attribute__((pass_object_size(0)))); int n; }; + struct B : Z, virtual A { Z z; using A::A; }; + B b(1, 2, &b); + // Complete object ctor forwards to A ctor then constructs Zs. + // ITANIUM-LABEL: define linkonce_odr void @_ZN14noninline_virt1BCI1NS_1AEEiO1QPvU17pass_object_size0( + // ITANIUM: call void @_ZN14noninline_virt1AC2EiO1QPvU17pass_object_size0({{.*}} %{{.*}}, i32 %{{.*}}, %{{.*}}* {{.*}}, i8* {{.*}}, i{{32|64}} %{{.*}} + // ITANIUM: call void @_ZN1ZC2Ev( + // ITANIUM: store {{.*}} @_ZTVN14noninline_virt1BE + // ITANIUM: call void @_ZN1ZC1Ev( + + // MSABI-LABEL: define internal {{.*}} @"\01??0B@noninline_virt@@Q{{AE|EAA}}@H$$Q{{E?}}AUQ@@P{{E?}}AXW4__pass_object_size0@__clang@@@Z"(%{{.*}}, i32{{.*}}, %{{.*}}, i8*{{.*}}, i{{32|64}}{{.*}}, i32 %{{.*}}) + // MSABI: %[[COMPLETE:.*]] = icmp ne + // MSABI: br i1 %[[COMPLETE]], + // MSABI: call {{.*}} @"\01??0A@noninline_virt@@Q{{AE|EAA}}@H$$Q{{E?}}AUQ@@P{{E?}}AXW4__pass_object_size0@__clang@@@Z"(%{{.*}}, i32{{.*}}, %{{.*}}, i8*{{.*}}, i{{32|64}}{{.*}}) + // MSABI: br + // MSABI: call {{.*}} @"\01??0Z@@Q{{AE|EAA}}@XZ"( + // MSABI: call {{.*}} @"\01??0Z@@Q{{AE|EAA}}@XZ"( + + struct C : B { using B::B; }; + C c(1, 2, &c); + // Complete object ctor forwards to A ctor, then calls B's base inheriting + // constructor, which takes no arguments other than the this pointer and VTT. + // ITANIUM_LABEL: define linkonce_odr void @_ZN14noninline_virt1CCI1NS_1AEEiO1QPvU17pass_object_size0( + // ITANIUM: call void @_ZN14noninline_virt1AC2EiO1QPvU17pass_object_size0({{.*}} %{{.*}}, i32 %{{.*}}, %{{.*}}* {{.*}}, i8* %{{.*}}, i{{32|64}} %{{.*}}) + // ITANIUM: call void @_ZN14noninline_virt1BCI2NS_1AEEiO1QPvU17pass_object_size0(%{{.*}}* %{{.*}}, i8** getelementptr inbounds ([2 x i8*], [2 x i8*]* @_ZTTN14noninline_virt1CE, i64 0, i64 1)) + // ITANIUM: store {{.*}} @_ZTVN14noninline_virt1CE + + // C constructor forwards to B constructor and A constructor. We pass the args + // to both. FIXME: Can we pass undef here instead, for the base object + // constructor call? + // MSABI-LABEL: define internal {{.*}} @"\01??0C@noninline_virt@@Q{{AE|EAA}}@H$$Q{{E?}}AUQ@@P{{E?}}AXW4__pass_object_size0@__clang@@@Z"(%{{.*}}, i32{{.*}}, %{{.*}}, i8*{{.*}}, i{{32|64}}{{.*}}, i32 %{{.*}}) + // MSABI: %[[COMPLETE:.*]] = icmp ne + // MSABI: br i1 %[[COMPLETE]], + // MSABI: call {{.*}} @"\01??0A@noninline_virt@@Q{{AE|EAA}}@H$$Q{{E?}}AUQ@@P{{E?}}AXW4__pass_object_size0@__clang@@@Z"(%{{.*}}, i32{{.*}}, %{{.*}}, i8*{{.*}}, i{{32|64}}{{.*}}) + // MSABI: br + // MSABI: call {{.*}} @"\01??0B@noninline_virt@@Q{{AE|EAA}}@H$$Q{{E?}}AUQ@@P{{E?}}AXW4__pass_object_size0@__clang@@@Z"(%{{.*}}, i32{{.*}}, %{{.*}}, i8*{{.*}}, i{{32|64}}{{.*}}, i32 0) +} + +// For MSABI only, check that inalloca arguments result in inlining. +namespace inalloca_nonvirt { + struct A { A(Q, int, Q, Q&&); int n; }; + struct B : Z, A { Z z; using A::A; }; + B b(1, 2, 3, 4); + // No inlining implied for Itanium. + // ITANIUM-LABEL: define linkonce_odr void @_ZN16inalloca_nonvirt1BCI1NS_1AEE1QiS1_OS1_( + // ITANIUM: call void @_ZN16inalloca_nonvirt1BCI2NS_1AEE1QiS1_OS1_( + + // MSABI-LABEL: define internal void @"\01??__Eb@inalloca_nonvirt@@YAXXZ"( + + // On Win32, the inalloca call can't be forwarded so we force inlining. + // WIN32: %[[TMP:.*]] = alloca + // WIN32: call i8* @llvm.stacksave() + // WIN32: %[[ARGMEM:.*]] = alloca inalloca + // WIN32: call {{.*}} @"\01??0Q@@QAE@H@Z"(%{{.*}}* %[[TMP]], i32 4) + // WIN32: %[[ARG3:.*]] = getelementptr {{.*}} %[[ARGMEM]] + // WIN32: call {{.*}} @"\01??0Q@@QAE@H@Z"({{.*}}* %[[ARG3]], i32 3) + // WIN32: %[[ARG1:.*]] = getelementptr {{.*}} %[[ARGMEM]] + // WIN32: call {{.*}} @"\01??0Q@@QAE@H@Z"({{.*}}* %[[ARG1]], i32 1) + // WIN32: call {{.*}} @"\01??0Z@@QAE@XZ"( + // WIN32: %[[ARG2:.*]] = getelementptr {{.*}} %[[ARGMEM]] + // WIN32: store i32 2, i32* %[[ARG2]] + // WIN32: %[[ARG4:.*]] = getelementptr {{.*}} %[[ARGMEM]] + // WIN32: store {{.*}}* %[[TMP]], {{.*}}** %[[ARG4]] + // WIN32: call {{.*}} @"\01??0A@inalloca_nonvirt@@QAE@UQ@@H0$$QAU2@@Z"(%{{[^,]*}}, <{{.*}}>* inalloca %[[ARGMEM]]) + // WIN32: call void @llvm.stackrestore( + // WIN32: call {{.*}} @"\01??0Z@@QAE@XZ"( + // WIN32: call {{.*}} @"\01??_DQ@@QAE@XZ"( + + // On Win64, the Q arguments would be destroyed in the callee. We don't yet + // support that in the non-inlined case, so we force inlining. + // WIN64: %[[TMP:.*]] = alloca + // WIN64: %[[ARG3:.*]] = alloca + // WIN64: %[[ARG1:.*]] = alloca + // WIN64: call {{.*}} @"\01??0Q@@QEAA@H@Z"({{.*}}* %[[TMP]], i32 4) + // WIN64: call {{.*}} @"\01??0Q@@QEAA@H@Z"({{.*}}* %[[ARG3]], i32 3) + // WIN64: call {{.*}} @"\01??0Q@@QEAA@H@Z"({{.*}}* %[[ARG1]], i32 1) + // WIN64: call {{.*}} @"\01??0Z@@QEAA@XZ"( + // WIN64: call {{.*}} @"\01??0A@inalloca_nonvirt@@QEAA@UQ@@H0$$QEAU2@@Z"(%{{.*}}, %{{.*}}* %[[ARG1]], i32 2, %{{.*}}* %[[ARG3]], %{{.*}} %[[TMP]]) + // WIN64: call {{.*}} @"\01??0Z@@QEAA@XZ"( + // WIN64: call void @"\01??_DQ@@QEAA@XZ"({{.*}}* %[[TMP]]) + + struct C : B { using B::B; }; + C c(1, 2, 3, 4); + // MSABI-LABEL: define internal void @"\01??__Ec@inalloca_nonvirt@@YAXXZ"( + + // On Win32, the inalloca call can't be forwarded so we force inlining. + // WIN32: %[[TMP:.*]] = alloca + // WIN32: call i8* @llvm.stacksave() + // WIN32: %[[ARGMEM:.*]] = alloca inalloca + // WIN32: call {{.*}} @"\01??0Q@@QAE@H@Z"(%{{.*}}* %[[TMP]], i32 4) + // WIN32: %[[ARG3:.*]] = getelementptr {{.*}} %[[ARGMEM]] + // WIN32: call {{.*}} @"\01??0Q@@QAE@H@Z"({{.*}}* %[[ARG3]], i32 3) + // WIN32: %[[ARG1:.*]] = getelementptr {{.*}} %[[ARGMEM]] + // WIN32: call {{.*}} @"\01??0Q@@QAE@H@Z"({{.*}}* %[[ARG1]], i32 1) + // WIN32: call {{.*}} @"\01??0Z@@QAE@XZ"( + // WIN32: %[[ARG2:.*]] = getelementptr {{.*}} %[[ARGMEM]] + // WIN32: store i32 2, i32* %[[ARG2]] + // WIN32: %[[ARG4:.*]] = getelementptr {{.*}} %[[ARGMEM]] + // WIN32: store {{.*}}* %[[TMP]], {{.*}}** %[[ARG4]] + // WIN32: call {{.*}} @"\01??0A@inalloca_nonvirt@@QAE@UQ@@H0$$QAU2@@Z"(%{{[^,]*}}, <{{.*}}>* inalloca %[[ARGMEM]]) + // WIN32: call void @llvm.stackrestore( + // WIN32: call {{.*}} @"\01??0Z@@QAE@XZ"( + // WIN32: call {{.*}} @"\01??_DQ@@QAE@XZ"( + + // On Win64, the Q arguments would be destroyed in the callee. We don't yet + // support that in the non-inlined case, so we force inlining. + // WIN64: %[[TMP:.*]] = alloca + // WIN64: %[[ARG3:.*]] = alloca + // WIN64: %[[ARG1:.*]] = alloca + // WIN64: call {{.*}} @"\01??0Q@@QEAA@H@Z"({{.*}}* %[[TMP]], i32 4) + // WIN64: call {{.*}} @"\01??0Q@@QEAA@H@Z"({{.*}}* %[[ARG3]], i32 3) + // WIN64: call {{.*}} @"\01??0Q@@QEAA@H@Z"({{.*}}* %[[ARG1]], i32 1) + // WIN64: call {{.*}} @"\01??0Z@@QEAA@XZ"( + // WIN64: call {{.*}} @"\01??0A@inalloca_nonvirt@@QEAA@UQ@@H0$$QEAU2@@Z"(%{{.*}}, %{{.*}}* %[[ARG1]], i32 2, %{{.*}}* %[[ARG3]], %{{.*}} %[[TMP]]) + // WIN64: call {{.*}} @"\01??0Z@@QEAA@XZ"( + // WIN64: call void @"\01??_DQ@@QEAA@XZ"({{.*}}* %[[TMP]]) +} + +namespace inalloca_virt { + struct A { A(Q, int, Q, Q&&); int n; }; + struct B : Z, virtual A { Z z; using A::A; }; + B b(1, 2, 3, 4); + + // MSABI-LABEL: define internal void @"\01??__Eb@inalloca_virt@@YAXXZ"( + + // On Win32, the inalloca call can't be forwarded so we force inlining. + // WIN32: %[[TMP:.*]] = alloca + // WIN32: call i8* @llvm.stacksave() + // WIN32: %[[ARGMEM:.*]] = alloca inalloca + // WIN32: call {{.*}} @"\01??0Q@@QAE@H@Z"(%{{.*}}* %[[TMP]], i32 4) + // WIN32: %[[ARG3:.*]] = getelementptr {{.*}} %[[ARGMEM]] + // WIN32: call {{.*}} @"\01??0Q@@QAE@H@Z"({{.*}}* %[[ARG3]], i32 3) + // WIN32: %[[ARG1:.*]] = getelementptr {{.*}} %[[ARGMEM]] + // WIN32: call {{.*}} @"\01??0Q@@QAE@H@Z"({{.*}}* %[[ARG1]], i32 1) + // FIXME: It's dumb to round-trip this though memory and generate a branch. + // WIN32: store i32 1, i32* %[[IS_MOST_DERIVED_ADDR:.*]] + // WIN32: %[[IS_MOST_DERIVED:.*]] = load i32, i32* %[[IS_MOST_DERIVED_ADDR]] + // WIN32: %[[IS_MOST_DERIVED_i1:.*]] = icmp ne i32 %[[IS_MOST_DERIVED]], 0 + // WIN32: br i1 %[[IS_MOST_DERIVED_i1]] + // + // WIN32: store {{.*}} @"\01??_8B@inalloca_virt@@7B@" + // WIN32: %[[ARG2:.*]] = getelementptr {{.*}} %[[ARGMEM]] + // WIN32: store i32 2, i32* %[[ARG2]] + // WIN32: %[[ARG4:.*]] = getelementptr {{.*}} %[[ARGMEM]] + // WIN32: store {{.*}}* %[[TMP]], {{.*}}** %[[ARG4]] + // WIN32: call {{.*}} @"\01??0A@inalloca_virt@@QAE@UQ@@H0$$QAU2@@Z"(%{{[^,]*}}, <{{.*}}>* inalloca %[[ARGMEM]]) + // WIN32: call void @llvm.stackrestore( + // WIN32: br + // + // Note that if we jumped directly to here we would fail to stackrestore and + // destroy the parameters, but that's not actually possible. + // WIN32: call {{.*}} @"\01??0Z@@QAE@XZ"( + // WIN32: call {{.*}} @"\01??0Z@@QAE@XZ"( + // WIN32: call {{.*}} @"\01??_DQ@@QAE@XZ"( + + // On Win64, the Q arguments would be destroyed in the callee. We don't yet + // support that in the non-inlined case, so we force inlining. + // WIN64: %[[TMP:.*]] = alloca + // WIN64: %[[ARG3:.*]] = alloca + // WIN64: %[[ARG1:.*]] = alloca + // WIN64: call {{.*}} @"\01??0Q@@QEAA@H@Z"({{.*}}* %[[TMP]], i32 4) + // WIN64: call {{.*}} @"\01??0Q@@QEAA@H@Z"({{.*}}* %[[ARG3]], i32 3) + // WIN64: call {{.*}} @"\01??0Q@@QEAA@H@Z"({{.*}}* %[[ARG1]], i32 1) + // WIN64: br i1 + // WIN64: call {{.*}} @"\01??0A@inalloca_virt@@QEAA@UQ@@H0$$QEAU2@@Z"(%{{.*}}, %{{.*}}* %[[ARG1]], i32 2, %{{.*}}* %[[ARG3]], %{{.*}} %[[TMP]]) + // WIN64: br + // WIN64: call {{.*}} @"\01??0Z@@QEAA@XZ"( + // WIN64: call {{.*}} @"\01??0Z@@QEAA@XZ"( + // WIN64: call void @"\01??_DQ@@QEAA@XZ"({{.*}}* %[[TMP]]) + + struct C : B { using B::B; }; + C c(1, 2, 3, 4); + // ITANIUM-LABEL: define linkonce_odr void @_ZN13inalloca_virt1CD1Ev( + + // MSABI-LABEL: define internal void @"\01??__Ec@inalloca_virt@@YAXXZ"( + + // On Win32, the inalloca call can't be forwarded so we force inlining. + // WIN32: %[[TMP:.*]] = alloca + // WIN32: call i8* @llvm.stacksave() + // WIN32: %[[ARGMEM:.*]] = alloca inalloca + // WIN32: call {{.*}} @"\01??0Q@@QAE@H@Z"(%{{.*}}* %[[TMP]], i32 4) + // WIN32: %[[ARG3:.*]] = getelementptr {{.*}} %[[ARGMEM]] + // WIN32: call {{.*}} @"\01??0Q@@QAE@H@Z"({{.*}}* %[[ARG3]], i32 3) + // WIN32: %[[ARG1:.*]] = getelementptr {{.*}} %[[ARGMEM]] + // WIN32: call {{.*}} @"\01??0Q@@QAE@H@Z"({{.*}}* %[[ARG1]], i32 1) + // WIN32: store i32 1, i32* %[[IS_MOST_DERIVED_ADDR:.*]] + // WIN32: %[[IS_MOST_DERIVED:.*]] = load i32, i32* %[[IS_MOST_DERIVED_ADDR]] + // WIN32: %[[IS_MOST_DERIVED_i1:.*]] = icmp ne i32 %[[IS_MOST_DERIVED]], 0 + // WIN32: br i1 %[[IS_MOST_DERIVED_i1]] + // + // WIN32: store {{.*}} @"\01??_8C@inalloca_virt@@7B@" + // WIN32: %[[ARG2:.*]] = getelementptr {{.*}} %[[ARGMEM]] + // WIN32: store i32 2, i32* %[[ARG2]] + // WIN32: %[[ARG4:.*]] = getelementptr {{.*}} %[[ARGMEM]] + // WIN32: store {{.*}}* %[[TMP]], {{.*}}** %[[ARG4]] + // WIN32: call {{.*}} @"\01??0A@inalloca_virt@@QAE@UQ@@H0$$QAU2@@Z"(%{{[^,]*}}, <{{.*}}>* inalloca %[[ARGMEM]]) + // WIN32: call void @llvm.stackrestore( + // WIN32: br + // + // WIN32: store i32 0, i32* %[[IS_MOST_DERIVED_ADDR:.*]] + // WIN32: %[[IS_MOST_DERIVED:.*]] = load i32, i32* %[[IS_MOST_DERIVED_ADDR]] + // WIN32: %[[IS_MOST_DERIVED_i1:.*]] = icmp ne i32 %[[IS_MOST_DERIVED]], 0 + // WIN32: br i1 %[[IS_MOST_DERIVED_i1]] + // + // Note: this block is unreachable. + // WIN32: store {{.*}} @"\01??_8B@inalloca_virt@@7B@" + // WIN32: br + // + // WIN32: call {{.*}} @"\01??0Z@@QAE@XZ"( + // WIN32: call {{.*}} @"\01??0Z@@QAE@XZ"( + // WIN32: call {{.*}} @"\01??_DQ@@QAE@XZ"( + + // On Win64, the Q arguments would be destroyed in the callee. We don't yet + // support that in the non-inlined case, so we force inlining. + // WIN64: %[[TMP:.*]] = alloca + // WIN64: %[[ARG3:.*]] = alloca + // WIN64: %[[ARG1:.*]] = alloca + // WIN64: call {{.*}} @"\01??0Q@@QEAA@H@Z"({{.*}}* %[[TMP]], i32 4) + // WIN64: call {{.*}} @"\01??0Q@@QEAA@H@Z"({{.*}}* %[[ARG3]], i32 3) + // WIN64: call {{.*}} @"\01??0Q@@QEAA@H@Z"({{.*}}* %[[ARG1]], i32 1) + // WIN64: br i1 + // WIN64: store {{.*}} @"\01??_8C@inalloca_virt@@7B@" + // WIN64: call {{.*}} @"\01??0A@inalloca_virt@@QEAA@UQ@@H0$$QEAU2@@Z"(%{{.*}}, %{{.*}}* %[[ARG1]], i32 2, %{{.*}}* %[[ARG3]], %{{.*}} %[[TMP]]) + // WIN64: br + // WIN64: br i1 + // (Unreachable block) + // WIN64: store {{.*}} @"\01??_8B@inalloca_virt@@7B@" + // WIN64: br + // WIN64: call {{.*}} @"\01??0Z@@QEAA@XZ"( + // WIN64: call {{.*}} @"\01??0Z@@QEAA@XZ"( + // WIN64: call void @"\01??_DQ@@QEAA@XZ"({{.*}}* %[[TMP]]) +} + +namespace inline_nonvirt { + struct A { A(Q, int, Q, Q&&, ...); int n; }; + struct B : Z, A { Z z; using A::A; }; + B b(1, 2, 3, 4, 5, 6); + // Inlined all the way down to the A ctor. + // ITANIUM-LABEL: define {{.*}} @__cxx_global_var_init + // ITANIUM: call void @_ZN1QC1Ei({{.*}}, i32 1) + // ITANIUM: call void @_ZN1QC1Ei({{.*}}, i32 3) + // ITANIUM: call void @_ZN1QC1Ei({{.*}}, i32 4) + // ITANIUM: %[[Z_BASE:.*]] = bitcast %{{.*}}* %[[THIS:.*]] to + // ITANIUM: call void @_ZN1ZC2Ev( + // ITANIUM: %[[B_CAST:.*]] = bitcast {{.*}} %[[THIS]] + // ITANIUM: %[[A_CAST:.*]] = getelementptr {{.*}} %[[B_CAST]], i{{32|64}} 4 + // ITANIUM: %[[A:.*]] = bitcast {{.*}} %[[A_CAST]] + // ITANIUM: call void ({{.*}}, ...) @_ZN14inline_nonvirt1AC2E1QiS1_OS1_z(%{{.*}}* %[[A]], {{.*}}, i32 2, {{.*}}, {{.*}}, i32 5, i32 6) + // ITANIUM: %[[Z_MEMBER:.*]] = getelementptr {{.*}} %[[THIS]], i32 0, i32 2 + // ITANIUM: call void @_ZN1ZC1Ev({{.*}} %[[Z_MEMBER]]) + // ITANIUM: call void @_ZN1QD1Ev( + // ITANIUM: call void @_ZN1QD1Ev( + // ITANIUM: call void @_ZN1QD1Ev( + + struct C : B { using B::B; }; + C c(1, 2, 3, 4, 5, 6); + // Inlined all the way down to the A ctor. + // ITANIUM-LABEL: define {{.*}} @__cxx_global_var_init + // ITANIUM: call void @_ZN1QC1Ei({{.*}}, i32 1) + // ITANIUM: call void @_ZN1QC1Ei({{.*}}, i32 3) + // ITANIUM: call void @_ZN1QC1Ei({{.*}}, i32 4) + // ITANIUM: %[[Z_BASE:.*]] = bitcast %{{.*}}* %[[THIS:.*]] to + // ITANIUM: call void @_ZN1ZC2Ev( + // ITANIUM: %[[B_CAST:.*]] = bitcast {{.*}} %[[THIS]] + // ITANIUM: %[[A_CAST:.*]] = getelementptr {{.*}} %[[B_CAST]], i{{32|64}} 4 + // ITANIUM: %[[A:.*]] = bitcast {{.*}} %[[A_CAST]] + // ITANIUM: call void ({{.*}}, ...) @_ZN14inline_nonvirt1AC2E1QiS1_OS1_z(%{{.*}}* %[[A]], {{.*}}, i32 2, {{.*}}, {{.*}}, i32 5, i32 6) + // ITANIUM: %[[Z_MEMBER:.*]] = getelementptr {{.*}} %{{.*}}, i32 0, i32 2 + // ITANIUM: call void @_ZN1ZC1Ev({{.*}} %[[Z_MEMBER]]) + // ITANIUM: call void @_ZN1QD1Ev( + // ITANIUM: call void @_ZN1QD1Ev( + // ITANIUM: call void @_ZN1QD1Ev( +} + +namespace inline_virt { + struct A { A(Q, int, Q, Q&&, ...); int n; }; + struct B : Z, virtual A { Z z; using A::A; }; + B b(1, 2, 3, 4, 5, 6); + // Inlined all the way down to the A ctor. + // ITANIUM-LABEL: define {{.*}} @__cxx_global_var_init + // ITANIUM: call void @_ZN1QC1Ei({{.*}}, i32 1) + // ITANIUM: call void @_ZN1QC1Ei({{.*}}, i32 3) + // ITANIUM: call void @_ZN1QC1Ei({{.*}}, i32 4) + // ITANIUM: %[[B_CAST:.*]] = bitcast {{.*}} %[[THIS:.*]] + // ITANIUM: %[[A_CAST:.*]] = getelementptr {{.*}} %[[B_CAST]], i{{32|64}} {{12|16}} + // ITANIUM: %[[A:.*]] = bitcast {{.*}} %[[A_CAST]] + // ITANIUM: call void ({{.*}}, ...) @_ZN11inline_virt1AC2E1QiS1_OS1_z(%{{.*}}* %[[A]], {{.*}}, i32 2, {{.*}}, {{.*}}, i32 5, i32 6) + // ITANIUM: call void @_ZN1ZC2Ev( + // ITANIUM: call void @_ZN1ZC1Ev( + // ITANIUM: call void @_ZN1QD1Ev( + // ITANIUM: call void @_ZN1QD1Ev( + // ITANIUM: call void @_ZN1QD1Ev( + + struct C : B { using B::B; }; + C c(1, 2, 3, 4, 5, 6); + // Inlined all the way down to the A ctor, except that we can just call the + // B base inheriting constructor to construct that portion (it doesn't need + // the forwarded arguments). + // ITANIUM-LABEL: define {{.*}} @__cxx_global_var_init + // ITANIUM: call void @_ZN1QC1Ei({{.*}}, i32 1) + // ITANIUM: call void @_ZN1QC1Ei({{.*}}, i32 3) + // ITANIUM: call void @_ZN1QC1Ei({{.*}}, i32 4) + // ITANIUM: %[[B_CAST:.*]] = bitcast {{.*}} %[[THIS:.*]] + // ITANIUM: %[[A_CAST:.*]] = getelementptr {{.*}} %[[B_CAST]], i{{32|64}} {{12|16}} + // ITANIUM: %[[A:.*]] = bitcast {{.*}} %[[A_CAST]] + // ITANIUM: call void ({{.*}}, ...) @_ZN11inline_virt1AC2E1QiS1_OS1_z(%{{.*}}* %[[A]], {{.*}}, i32 2, {{.*}}, {{.*}}, i32 5, i32 6) + // ITANIUM: call void @_ZN11inline_virt1BCI2NS_1AEE1QiS1_OS1_z({{[^,]*}}, i8** getelementptr inbounds ([2 x i8*], [2 x i8*]* @_ZTTN11inline_virt1CE, i64 0, i64 1)) + // ITANIUM: store {{.*}} @_ZTVN11inline_virt1CE + // ITANIUM: call void @_ZN1QD1Ev( + // ITANIUM: call void @_ZN1QD1Ev( + // ITANIUM: call void @_ZN1QD1Ev( + + // B base object inheriting constructor does not get passed arguments. + // ITANIUM-LABEL: define linkonce_odr void @_ZN11inline_virt1BCI2NS_1AEE1QiS1_OS1_z( + // ITANIUM-NOT: call + // ITANIUM: call void @_ZN1ZC2Ev( + // ITANIUM-NOT: call + // VTT -> vtable + // ITANIUM: store + // ITANIUM-NOT: call + // ITANIUM: call void @_ZN1ZC1Ev( + // ITANIUM-NOT: call + // ITANIUM: } +} + +// ITANIUM-LABEL: define linkonce_odr void @_ZN1BCI21AEi( +// ITANIUM: call void @_ZN1AC2Ei( + +// ITANIUM-LABEL: define linkonce_odr void @_ZN1DCI21CIiEET_( +// ITANIUM: call void @_ZN1CC2IiEET_( + +// ITANIUM-LABEL: define linkonce_odr void @_ZN17noninline_nonvirt1BCI2NS_1AEEiO1QPvU17pass_object_size0( +// ITANIUM: call void @_ZN1ZC2Ev( +// ITANIUM: call void @_ZN17noninline_nonvirt1AC2EiO1QPvU17pass_object_size0( + +// ITANIUM-LABEL: define linkonce_odr void @_ZN17noninline_nonvirt1CCI2NS_1AEEiO1QPvU17pass_object_size0( +// ITANIUM: call void @_ZN17noninline_nonvirt1BCI2NS_1AEEiO1QPvU17pass_object_size0( diff --git a/test/CodeGenCXX/init-invariant.cpp b/test/CodeGenCXX/init-invariant.cpp index 7f348257f263..71eb7dd73492 100644 --- a/test/CodeGenCXX/init-invariant.cpp +++ b/test/CodeGenCXX/init-invariant.cpp @@ -56,5 +56,5 @@ void e() { // CHECK-LABEL: define void @_Z1ev( // CHECK: call void @_ZN1AC1Ev(%struct.A* nonnull @_ZZ1evE1a) -// CHECK: call {{.*}}@llvm.invariant.start(i64 4, i8* nonnull bitcast ({{.*}} @_ZZ1evE1a to i8*)) +// CHECK: call {{.*}}@llvm.invariant.start(i64 4, i8* {{.*}}bitcast ({{.*}} @_ZZ1evE1a to i8*)) // CHECK-NOT: llvm.invariant.end diff --git a/test/CodeGenCXX/inline-hint.cpp b/test/CodeGenCXX/inline-hint.cpp new file mode 100644 index 000000000000..9c14032f9f69 --- /dev/null +++ b/test/CodeGenCXX/inline-hint.cpp @@ -0,0 +1,96 @@ +// RUN: %clang_cc1 %s -std=c++11 -triple=x86_64-linux -finline-functions -emit-llvm -disable-llvm-optzns -o - | FileCheck %s --check-prefix=CHECK --check-prefix=SUITABLE +// RUN: %clang_cc1 %s -std=c++11 -triple=x86_64-linux -finline-hint-functions -emit-llvm -disable-llvm-optzns -o - | FileCheck %s --check-prefix=CHECK --check-prefix=HINTED +// RUN: %clang_cc1 %s -std=c++11 -triple=x86_64-linux -fno-inline -emit-llvm -disable-llvm-optzns -o - | FileCheck %s --check-prefix=CHECK --check-prefix=NOINLINE + +// Force non-trivial implicit constructors/destructors/operators for B by having explicit ones for A +struct A { + A() {} + A(const A&) {} + A& operator=(const A&) { return *this; } + ~A() {} +}; + +struct B { + A member; + int implicitFunction(int a) { return a + a; } + inline int explicitFunction(int a); + int noHintFunction(int a); + __attribute__((optnone)) int optNoneFunction(int a) { return a + a; } + template<int N> int implicitTplFunction(int a) { return N + a; } + template<int N> inline int explicitTplFunction(int a) { return N + a; } + template<int N> int noHintTplFunction(int a); + template<int N> int explicitRedeclTplFunction(int a); +}; + +int B::explicitFunction(int a) { return a + a; } +// CHECK: @_ZN1B14noHintFunctionEi({{.*}}) [[NOHINT_ATTR:#[0-9]+]] +int B::noHintFunction(int a) { return a + a; } + +// CHECK: @_ZN1B19implicitTplFunctionILi0EEEii({{.*}}) [[NOHINT_ATTR]] +template<> int B::implicitTplFunction<0>(int a) { return a + a; } +// CHECK: @_ZN1B19explicitTplFunctionILi0EEEii({{.*}}) [[NOHINT_ATTR]] +template<> int B::explicitTplFunction<0>(int a) { return a + a; } +// CHECK: @_ZN1B17noHintTplFunctionILi0EEEii({{.*}}) [[NOHINT_ATTR]] +template<> int B::noHintTplFunction<0>(int a) { return a + a; } +template<> inline int B::implicitTplFunction<1>(int a) { return a; } +template<> inline int B::explicitTplFunction<1>(int a) { return a; } +template<> inline int B::noHintTplFunction<1>(int a) { return a; } +template<int N> int B::noHintTplFunction(int a) { return N + a; } +template<int N> inline int B::explicitRedeclTplFunction(int a) { return N + a; } + +constexpr int constexprFunction(int a) { return a + a; } + +void foo() +{ +// CHECK: @_ZN1BC1Ev({{.*}}) unnamed_addr [[IMPLICIT_CONSTR_ATTR:#[0-9]+]] + B b1; +// CHECK: @_ZN1BC1ERKS_({{.*}}) unnamed_addr [[IMPLICIT_CONSTR_ATTR]] + B b2(b1); +// CHECK: @_ZN1BaSERKS_({{.*}}) [[IMPLICIT_CONSTR_ATTR]] + b2 = b1; +// CHECK: @_ZN1B16implicitFunctionEi({{.*}}) [[IMPLICIT_ATTR:#[0-9]+]] + b1.implicitFunction(1); +// CHECK: @_ZN1B16explicitFunctionEi({{.*}}) [[EXPLICIT_ATTR:#[0-9]+]] + b1.explicitFunction(2); + b1.noHintFunction(3); +// CHECK: @_ZN1B15optNoneFunctionEi({{.*}}) [[OPTNONE_ATTR:#[0-9]+]] + b1.optNoneFunction(4); +// CHECK: @_Z17constexprFunctioni({{.*}}) [[IMPLICIT_ATTR]] + constexprFunction(5); + b1.implicitTplFunction<0>(6); +// CHECK: @_ZN1B19implicitTplFunctionILi1EEEii({{.*}}) [[EXPLICIT_ATTR]] + b1.implicitTplFunction<1>(7); +// CHECK: @_ZN1B19implicitTplFunctionILi2EEEii({{.*}}) [[IMPLICIT_ATTR]] + b1.implicitTplFunction<2>(8); + b1.explicitTplFunction<0>(9); +// CHECK: @_ZN1B19explicitTplFunctionILi1EEEii({{.*}}) [[EXPLICIT_ATTR]] + b1.explicitTplFunction<1>(10); +// CHECK: @_ZN1B19explicitTplFunctionILi2EEEii({{.*}}) [[EXPLICIT_ATTR]] + b1.explicitTplFunction<2>(11); + b1.noHintTplFunction<0>(12); +// CHECK: @_ZN1B17noHintTplFunctionILi1EEEii({{.*}}) [[EXPLICIT_ATTR]] + b1.noHintTplFunction<1>(13); +// CHECK: @_ZN1B17noHintTplFunctionILi2EEEii({{.*}}) [[NOHINT_ATTR]] + b1.noHintTplFunction<2>(14); +// CHECK: @_ZN1B25explicitRedeclTplFunctionILi2EEEii({{.*}}) [[EXPLICIT_ATTR]] + b1.explicitRedeclTplFunction<2>(15); +// CHECK: @_ZN1BD2Ev({{.*}}) unnamed_addr [[IMPLICIT_CONSTR_ATTR]] +} + +// SUITABLE-NOT: attributes [[NOHINT_ATTR]] = { {{.*}}noinline{{.*}} } +// HINTED-DAG: attributes [[NOHINT_ATTR]] = { noinline{{.*}} } +// NOINLINE-DAG: attributes [[NOHINT_ATTR]] = { noinline{{.*}} } + +// SUITABLE-NOT: attributes [[IMPLICIT_ATTR]] = { {{.*}}noinline{{.*}} } +// HINTED-NOT: attributes [[IMPLICIT_ATTR]] = { {{.*}}noinline{{.*}} } +// NOINLINE-DAG: attributes [[IMPLICIT_ATTR]] = { noinline{{.*}} } + +// SUITABLE-NOT: attributes [[IMPLICIT_CONSTR_ATTR]] = { {{.*}}noinline{{.*}} } +// HINTED-NOT: attributes [[IMPLICIT_ATTR]] = { {{.*}}noinline{{.*}} } +// NOINLINE-DAG: attributes [[IMPLICIT_CONSTR_ATTR]] = { noinline{{.*}} } + +// SUITABLE-NOT: attributes [[EXPLICIT_ATTR]] = { {{.*}}noinline{{.*}} } +// HINTED-NOT: attributes [[IMPLICIT_ATTR]] = { {{.*}}noinline{{.*}} } +// NOINLINE-DAG: attributes [[EXPLICIT_ATTR]] = { noinline{{.*}} } + +// CHECK-DAG: attributes [[OPTNONE_ATTR]] = { noinline{{.*}} } diff --git a/test/CodeGenCXX/lambda-expressions.cpp b/test/CodeGenCXX/lambda-expressions.cpp index 4df44f4c5f7f..f59d360314e4 100644 --- a/test/CodeGenCXX/lambda-expressions.cpp +++ b/test/CodeGenCXX/lambda-expressions.cpp @@ -12,12 +12,16 @@ extern "C" auto cvar = []{}; // CHECK-LABEL: define i32 @_Z9ARBSizeOfi(i32 int ARBSizeOf(int n) { - typedef double (T)[8][n]; - using TT = double [8][n]; + typedef double(T)[8][n]; + using TT = double[8][n]; return [&]() -> int { typedef double(T1)[8][n]; using TT1 = double[8][n]; - return sizeof(T) + sizeof(T1) + sizeof(TT) + sizeof(TT1); + return [&n]() -> int { + typedef double(T2)[8][n]; + using TT2 = double[8][n]; + return sizeof(T) + sizeof(T1) + sizeof(T2) + sizeof(TT) + sizeof(TT1) + sizeof(TT2); + }(); }(); } diff --git a/test/CodeGenCXX/linetable-virtual-variadic.cpp b/test/CodeGenCXX/linetable-virtual-variadic.cpp index 8d1bf47814f8..6f966416867a 100644 --- a/test/CodeGenCXX/linetable-virtual-variadic.cpp +++ b/test/CodeGenCXX/linetable-virtual-variadic.cpp @@ -15,9 +15,5 @@ void Derived::VariadicFunction(...) { } // CHECK-LABEL: define void @_ZT{{.+}}N7Derived16VariadicFunctionEz( // CHECK: ret void, !dbg ![[LOC:[0-9]+]] // -// CHECK: !llvm.dbg.cu = !{![[CU:[0-9]+]]} -// -// CHECK: ![[CU]] = distinct !DICompileUnit({{.*}} subprograms: ![[SPs:[0-9]+]] -// CHECK: ![[SPs]] = !{![[SP]]} // CHECK: ![[SP]] = distinct !DISubprogram(name: "VariadicFunction" // CHECK: ![[LOC]] = !DILocation({{.*}}scope: ![[SP]]) diff --git a/test/CodeGenCXX/lto-visibility-inference.cpp b/test/CodeGenCXX/lto-visibility-inference.cpp new file mode 100644 index 000000000000..8e57ef5e0b89 --- /dev/null +++ b/test/CodeGenCXX/lto-visibility-inference.cpp @@ -0,0 +1,107 @@ +// RUN: %clang_cc1 -flto -triple x86_64-unknown-linux -std=c++11 -fms-extensions -fvisibility hidden -fwhole-program-vtables -emit-llvm -o - %s | FileCheck --check-prefix=ITANIUM %s +// RUN: %clang_cc1 -flto -triple x86_64-pc-windows-msvc -std=c++11 -fms-extensions -fwhole-program-vtables -emit-llvm -o - %s | FileCheck --check-prefix=MS --check-prefix=MS-STD %s +// RUN: %clang_cc1 -flto -triple x86_64-pc-windows-msvc -std=c++11 -fms-extensions -fwhole-program-vtables -flto-visibility-public-std -emit-llvm -o - %s | FileCheck --check-prefix=MS --check-prefix=MS-NOSTD %s + +struct C1 { + virtual void f(); +}; + +struct __attribute__((visibility("default"))) C2 { + virtual void f(); +}; + +struct __declspec(dllexport) C3 { + virtual void f(); +}; + +struct __declspec(dllimport) C4 { + virtual void f(); +}; + +struct [[clang::lto_visibility_public]] C5 { + virtual void f(); +}; + +struct __declspec(uuid("00000000-0000-0000-0000-000000000000")) C6 { + virtual void f(); +}; + +namespace std { + +struct C7 { + virtual void f(); + struct C8 { + virtual void f(); + }; +}; + +} + +extern "C++" { + +namespace stdext { + +struct C9 { + virtual void f(); +}; + +} + +} + +namespace other { + +struct C10 { + virtual void f(); +}; + +} + +namespace { + +struct C11 { + virtual void f(); +}; + +} + +void f(C1 *c1, C2 *c2, C3 *c3, C4 *c4, C5 *c5, C6 *c6, std::C7 *c7, + std::C7::C8 *c8, stdext::C9 *c9, other::C10 *c10) { + // ITANIUM: type.test{{.*}}!"_ZTS2C1" + // MS: type.test{{.*}}!"?AUC1@@" + c1->f(); + // ITANIUM-NOT: type.test{{.*}}!"_ZTS2C2" + // MS: type.test{{.*}}!"?AUC2@@" + c2->f(); + // ITANIUM: type.test{{.*}}!"_ZTS2C3" + // MS-NOT: type.test{{.*}}!"?AUC3@@" + c3->f(); + // ITANIUM: type.test{{.*}}!"_ZTS2C4" + // MS-NOT: type.test{{.*}}!"?AUC4@@" + c4->f(); + // ITANIUM-NOT: type.test{{.*}}!"_ZTS2C5" + // MS-NOT: type.test{{.*}}!"?AUC5@@" + c5->f(); + // ITANIUM-NOT: type.test{{.*}}!"_ZTS2C6" + // MS-NOT: type.test{{.*}}!"?AUC6@@" + c6->f(); + // ITANIUM: type.test{{.*}}!"_ZTSSt2C7" + // MS-STD: type.test{{.*}}!"?AUC7@std@@" + // MS-NOSTD-NOT: type.test{{.*}}!"?AUC7@std@@" + c7->f(); + // ITANIUM: type.test{{.*}}!"_ZTSNSt2C72C8E" + // MS-STD: type.test{{.*}}!"?AUC8@C7@std@@" + // MS-NOSTD-NOT: type.test{{.*}}!"?AUC8@C7@std@@" + c8->f(); + // ITANIUM: type.test{{.*}}!"_ZTSN6stdext2C9E" + // MS-STD: type.test{{.*}}!"?AUC9@stdext@@" + // MS-NOSTD-NOT: type.test{{.*}}!"?AUC9@stdext@@" + c9->f(); + // ITANIUM: type.test{{.*}}!"_ZTSN5other3C10E" + // MS: type.test{{.*}}!"?AUC10@other@@" + c10->f(); + // ITANIUM: type.test{{.*}}!{{[0-9]}} + // MS: type.test{{.*}}!{{[0-9]}} + C11 *c11; + c11->f(); +} diff --git a/test/CodeGenCXX/mangle-abi-tag.cpp b/test/CodeGenCXX/mangle-abi-tag.cpp new file mode 100644 index 000000000000..385a16f26a51 --- /dev/null +++ b/test/CodeGenCXX/mangle-abi-tag.cpp @@ -0,0 +1,205 @@ +// RUN: %clang_cc1 %s -emit-llvm -triple %itanium_abi_triple -std=c++11 -o - | FileCheck %s +// RUN: %clang_cc1 %s -emit-llvm -triple i686-linux-gnu -std=c++11 -o - | FileCheck %s +// RUN: %clang_cc1 %s -emit-llvm -triple x86_64-linux-gnu -std=c++11 -o - | FileCheck %s +// RUN: %clang_cc1 %s -emit-llvm -triple powerpc64le-unknown-linux-gnu -std=c++11 -o - | FileCheck %s + +struct __attribute__((abi_tag("A", "B"))) A { }; + +struct B: A { }; + +template<class T> + +struct C { +}; + +struct D { A* p; }; + +template<class T> +struct __attribute__((abi_tag("C", "D"))) E { +}; + +struct __attribute__((abi_tag("A", "B"))) F { }; + +A a1; +// CHECK-DAG: @_Z2a1B1AB1B = + +__attribute__((abi_tag("C", "D"))) +A a2; +// CHECK-DAG: @_Z2a2B1AB1BB1CB1D = + +B a3; +// CHECK-DAG: @a3 = + +C<A> a4; +// CHECK-DAG: @_Z2a4B1AB1B = + +D a5; +// CHECK-DAG: @a5 = + +E<int> a6; +// CHECK-DAG: @_Z2a6B1CB1D = + +E<A> a7; +// CHECK-DAG: @_Z2a7B1AB1BB1CB1D = + +template<> +struct E<float> { + static float a8; +}; +float E<float>::a8; +// CHECK-DAG: @_ZN1EB1CB1DIfE2a8E = + +template<> +struct E<F> { + static bool a9; +}; +bool E<F>::a9; +// CHECK-DAG: @_ZN1EB1CB1DI1FB1AB1BE2a9E = + +struct __attribute__((abi_tag("A", "B"))) A10 { + virtual ~A10() {} +} a10; +// vtable +// CHECK-DAG: @_ZTV3A10B1AB1B = +// typeinfo +// CHECK-DAG: @_ZTI3A10B1AB1B = + +struct __attribute__((abi_tag("A"))) B11 { + static A10 b; +}; +A10 B11::b; +// B11[abi:A]::b[abi:B] +// CHECK-DAG: @_ZN3B11B1A1bB1BE = + +__attribute__ ((abi_tag("C", "D"))) +void* f1() { + return 0; +} +// CHECK-DAG: define {{.*}} @_Z2f1B1CB1Dv( + +__attribute__ ((abi_tag("C", "D"))) +A* f2() { + return 0; +} +// CHECK-DAG: define {{.*}} @_Z2f2B1AB1BB1CB1Dv( + +B* f3() { + return 0; +} +// CHECK-DAG: define {{.*}} @_Z2f3v( + +C<A>* f4() { + return 0; +} +// CHECK-DAG: define {{.*}} @_Z2f4B1AB1Bv( + +D* f5() { + return 0; +} +// CHECK-DAG: define {{.*}} @_Z2f5v( + +E<char>* f6() { + return 0; +} +// CHECK-DAG: define {{.*}} @_Z2f6B1CB1Dv( + +E<A>* f7() { + return 0; +} +// CHECK-DAG: define {{.*}} @_Z2f7B1AB1BB1CB1Dv( + +void f8(E<A>*) { +} +// CHECK-DAG: define {{.*}} @_Z2f8P1EB1CB1DI1AB1AB1BE( + +inline namespace Names1 __attribute__((__abi_tag__)) { + class C1 {}; +} +C1 f9() { return C1(); } +// CHECK-DAG: @_Z2f9B6Names1v( + +inline namespace Names2 __attribute__((__abi_tag__("Tag1", "Tag2"))) { + class C2 {}; +} +C2 f10() { return C2(); } +// CHECK-DAG: @_Z3f10B4Tag1B4Tag2v( + +void __attribute__((abi_tag("A"))) f11(A) {} +// f11[abi:A](A[abi:A][abi:B]) +// CHECK-DAG: define {{.*}} @_Z3f11B1A1AB1AB1B( + +A f12(A) { return A(); } +// f12(A[abi:A][abi:B]) +// CHECK-DAG: define {{.*}} @_Z3f121AB1AB1B( + +inline void f13() { + struct L { + static E<int>* foo() { + static A10 a; + return 0; + } + }; + L::foo(); +} +void f13_test() { + f13(); +} +// f13()::L::foo[abi:C][abi:D]() +// CHECK-DAG: define linkonce_odr %struct.E* @_ZZ3f13vEN1L3fooB1CB1DEv( + +// f13()::L::foo[abi:C][abi:D]()::a[abi:A][abi:B] +// CHECK-DAG: @_ZZZ3f13vEN1L3fooB1CB1DEvE1aB1AB1B = + +// guard variable for f13()::L::foo[abi:C][abi:D]()::a[abi:A][abi:B] +// CHECK-DAG: @_ZGVZZ3f13vEN1L3fooB1CB1DEvE1aB1AB1B = + +struct __attribute__((abi_tag("TAG"))) A14 { + A14 f14(); +}; +A14 A14::f14() { + return A14(); +} +// A14[abi:TAG]::f14() +// CHECK-DAG: define {{.+}} @_ZN3A14B3TAG3f14Ev( + +template<class T> +T f15() { + return T(); +} +void f15_test() { + f15<A14>(); +} +// A14[abi:TAG] f15<A14[abi:TAG]>() +// CHECK-DAG: define linkonce_odr {{.+}} @_Z3f15I3A14B3TAGET_v( + +template<class T> +A14 f16() { + return A14(); +} +void f16_test() { + f16<int>(); +} +// A14[abi:TAG] f16<int>() +// CHECK-DAG: define linkonce_odr {{.+}} @_Z3f16IiE3A14B3TAGv( + +template<class T> +struct __attribute__((abi_tag("TAG"))) A17 { + A17 operator+(const A17& a) { + return a; + } +}; +void f17_test() { + A17<int> a, b; + a + b; +} +// A17[abi:TAG]<int>::operator+(A17[abi:TAG]<int> const&) +// CHECK-DAG: define linkonce_odr {{.+}} @_ZN3A17B3TAGIiEplERKS0_( + +struct A18 { + operator A() { return A(); } +}; +void f18_test() { + A a = A18(); +} +// A18::operator A[abi:A][abi:B]() but GCC adds the same tags twice! +// CHECK-DAG: define linkonce_odr {{.+}} @_ZN3A18cv1AB1AB1BEv( diff --git a/test/CodeGenCXX/mangle-address-space.cpp b/test/CodeGenCXX/mangle-address-space.cpp index f18480de83de..cd10384594ea 100644 --- a/test/CodeGenCXX/mangle-address-space.cpp +++ b/test/CodeGenCXX/mangle-address-space.cpp @@ -10,3 +10,6 @@ typedef OpaqueType __attribute__((address_space(100))) * OpaqueTypePtr; // CHECK-LABEL: define {{.*}}void @_Z2f0PU5AS10010OpaqueType void f0(OpaqueTypePtr) { } + +// CHECK-LABEL: define {{.*}}void @_Z2f1PU3AS1Kc +void f1(char __attribute__((address_space(1))) const *p) {}
\ No newline at end of file diff --git a/test/CodeGenCXX/mangle-ms-cxx11.cpp b/test/CodeGenCXX/mangle-ms-cxx11.cpp index 999def87fc5e..8e2577b03e26 100644 --- a/test/CodeGenCXX/mangle-ms-cxx11.cpp +++ b/test/CodeGenCXX/mangle-ms-cxx11.cpp @@ -166,14 +166,14 @@ inline int define_lambda() { static auto lambda = [] { static int local; ++local; return local; }; // First, we have the static local variable of type "<lambda_1>" inside of // "define_lambda". -// CHECK-DAG: @"\01?lambda@?1??define_lambda@@YAHXZ@4V<lambda_1>@?1@YAHXZ@A" +// CHECK-DAG: @"\01?lambda@?1??define_lambda@@YAHXZ@4V<lambda_1>@?0??1@YAHXZ@A" // Next, we have the "operator()" for "<lambda_1>" which is inside of // "define_lambda". -// CHECK-DAG: @"\01??R<lambda_1>@?define_lambda@@YAHXZ@QBEHXZ" +// CHECK-DAG: @"\01??R<lambda_1>@?0??define_lambda@@YAHXZ@QBE@XZ" // Finally, we have the local which is inside of "<lambda_1>" which is inside of // "define_lambda". Hooray. -// MSVC2013-DAG: @"\01?local@?2???R<lambda_1>@?define_lambda@@YAHXZ@QBEHXZ@4HA" -// MSVC2015-DAG: @"\01?local@?1???R<lambda_1>@?define_lambda@@YAHXZ@QBEHXZ@4HA" +// MSVC2013-DAG: @"\01?local@?2???R<lambda_1>@?0??define_lambda@@YAHXZ@QBE@XZ@4HA" +// MSVC2015-DAG: @"\01?local@?1???R<lambda_1>@?0??define_lambda@@YAHXZ@QBE@XZ@4HA" return lambda(); } @@ -182,12 +182,12 @@ void use_lambda_arg(T) {} inline void call_with_lambda_arg1() { use_lambda_arg([]{}); - // CHECK-DAG: @"\01??$use_lambda_arg@V<lambda_1>@?call_with_lambda_arg1@@YAXXZ@@@YAXV<lambda_1>@?call_with_lambda_arg1@@YAXXZ@@Z" + // CHECK-DAG: @"\01??$use_lambda_arg@V<lambda_1>@?0??call_with_lambda_arg1@@YAXXZ@@@YAXV<lambda_1>@?0??call_with_lambda_arg1@@YAXXZ@@Z" } inline void call_with_lambda_arg2() { use_lambda_arg([]{}); - // CHECK-DAG: @"\01??$use_lambda_arg@V<lambda_1>@?call_with_lambda_arg2@@YAXXZ@@@YAXV<lambda_1>@?call_with_lambda_arg2@@YAXXZ@@Z" + // CHECK-DAG: @"\01??$use_lambda_arg@V<lambda_1>@?0??call_with_lambda_arg2@@YAXXZ@@@YAXV<lambda_1>@?0??call_with_lambda_arg2@@YAXXZ@@Z" } int call_lambda() { @@ -286,3 +286,35 @@ static union { }; // CHECK-DAG: @"\01??$f@T<unnamed-type-$S1>@PR18204@@@PR18204@@YAHPAT<unnamed-type-$S1>@0@@Z" } + +int PR26105() { + auto add = [](int x) { return ([x](int y) { return x + y; }); }; + return add(3)(4); +} +// CHECK-DAG: @"\01??R<lambda_0>@?0??PR26105@@YAHXZ@QBE@H@Z" +// CHECK-DAG: @"\01??R<lambda_1>@?0???R<lambda_0>@?0??PR26105@@YAHXZ@QBE@H@Z@QBE@H@Z" + +int __unaligned * unaligned_foo1() { return 0; } +int __unaligned * __unaligned * unaligned_foo2() { return 0; } +__unaligned int unaligned_foo3() { return 0; } +void unaligned_foo4(int __unaligned *p1) {} +void unaligned_foo5(int __unaligned * __restrict p1) {} +template <typename T> T unaligned_foo6(T t) { return t; } +void unaligned_foo7() { unaligned_foo6<int *>(0); unaligned_foo6<int __unaligned *>(0); } + +// CHECK-DAG: @"\01?unaligned_foo1@@YAPFAHXZ" +// CHECK-DAG: @"\01?unaligned_foo2@@YAPFAPFAHXZ" +// CHECK-DAG: @"\01?unaligned_foo3@@YAHXZ" +// CHECK-DAG: @"\01?unaligned_foo4@@YAXPFAH@Z" +// CHECK-DAG: @"\01?unaligned_foo5@@YAXPIFAH@Z" +// CHECK-DAG: @"\01??$unaligned_foo6@PAH@@YAPAHPAH@Z" +// CHECK-DAG: @"\01??$unaligned_foo6@PFAH@@YAPFAHPFAH@Z" + +// __unaligned qualifier for function types +struct unaligned_foo8_S { + void unaligned_foo8() volatile __unaligned; +}; +void unaligned_foo8_S::unaligned_foo8() volatile __unaligned {} + +// CHECK-DAG: @"\01?unaligned_foo8@unaligned_foo8_S@@QFCEXXZ" + diff --git a/test/CodeGenCXX/mangle-ms-cxx14.cpp b/test/CodeGenCXX/mangle-ms-cxx14.cpp index 9d30c406c8c7..798a390aeaaa 100644 --- a/test/CodeGenCXX/mangle-ms-cxx14.cpp +++ b/test/CodeGenCXX/mangle-ms-cxx14.cpp @@ -35,12 +35,12 @@ auto TemplateFuncionWithLocalLambda(T) { return LocalLambdaWithLocalType(); } -// MSVC2013-DAG: "\01?ValueFromTemplateFuncionWithLocalLambda@@3ULocalType@?2???R<lambda_1>@??$TemplateFuncionWithLocalLambda@H@@YA?A?<auto>@@H@Z@QBE?A?3@XZ@A" -// MSVC2013-DAG: "\01?ValueFromTemplateFuncionWithLocalLambda@@3ULocalType@?2???R<lambda_1>@??$TemplateFuncionWithLocalLambda@H@@YA?A?<auto>@@H@Z@QBE?A?3@XZ@A" -// MSVC2015-DAG: "\01?ValueFromTemplateFuncionWithLocalLambda@@3ULocalType@?1???R<lambda_1>@??$TemplateFuncionWithLocalLambda@H@@YA?A?<auto>@@H@Z@QBE?A?3@XZ@A" -// MSVC2015-DAG: "\01?ValueFromTemplateFuncionWithLocalLambda@@3ULocalType@?1???R<lambda_1>@??$TemplateFuncionWithLocalLambda@H@@YA?A?<auto>@@H@Z@QBE?A?3@XZ@A" +// MSVC2013-DAG: "\01?ValueFromTemplateFuncionWithLocalLambda@@3ULocalType@?2???R<lambda_1>@?0???$TemplateFuncionWithLocalLambda@H@@YA?A?<auto>@@H@Z@QBE?A?3@XZ@A" +// MSVC2013-DAG: "\01?ValueFromTemplateFuncionWithLocalLambda@@3ULocalType@?2???R<lambda_1>@?0???$TemplateFuncionWithLocalLambda@H@@YA?A?<auto>@@H@Z@QBE?A?3@XZ@A" +// MSVC2015-DAG: "\01?ValueFromTemplateFuncionWithLocalLambda@@3ULocalType@?1???R<lambda_1>@?0???$TemplateFuncionWithLocalLambda@H@@YA?A?<auto>@@H@Z@QBE?A?3@XZ@A" +// MSVC2015-DAG: "\01?ValueFromTemplateFuncionWithLocalLambda@@3ULocalType@?1???R<lambda_1>@?0???$TemplateFuncionWithLocalLambda@H@@YA?A?<auto>@@H@Z@QBE?A?3@XZ@A" // CHECK-DAG: "\01??$TemplateFuncionWithLocalLambda@H@@YA?A?<auto>@@H@Z" -// CHECK-DAG: "\01??R<lambda_1>@??$TemplateFuncionWithLocalLambda@H@@YA?A?<auto>@@H@Z@QBE?A?1@XZ" +// CHECK-DAG: "\01??R<lambda_1>@?0???$TemplateFuncionWithLocalLambda@H@@YA?A?<auto>@@H@Z@QBE?A?1@XZ" auto ValueFromTemplateFuncionWithLocalLambda = TemplateFuncionWithLocalLambda(0); struct S; @@ -55,3 +55,8 @@ struct Foo {}; Foo<&x<int>, &x<int>> Zoo; // CHECK-DAG: "\01?Zoo@@3U?$Foo@$1??$x@H@@3HA$1?1@3HA@@A" + +template <typename T> T unaligned_x; +extern auto test_unaligned() { return unaligned_x<int __unaligned *>; } +// CHECK-DAG: "\01??$unaligned_x@PFAH@@3PFAHA" + diff --git a/test/CodeGenCXX/mangle-ms-md5.cpp b/test/CodeGenCXX/mangle-ms-md5.cpp new file mode 100644 index 000000000000..aef268304832 --- /dev/null +++ b/test/CodeGenCXX/mangle-ms-md5.cpp @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 -emit-llvm -o - -triple i686-pc-win32 %s | FileCheck %s +int xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx; +// CHECK-DAG: @"\01??@bf7ea7b95f260b0b24e7f1e8fc8370ab@" = global i32 0, align 4 + +struct yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy { + yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy(); + virtual void f(); +}; +yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy::yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy() {} +// CHECK-DAG: @"\01??@a6a285da2eea70dba6b578022be61d81@??_R4@" = linkonce_odr constant %rtti.CompleteObjectLocator +// CHECK-DAG: @"\01??@a6a285da2eea70dba6b578022be61d81@" = unnamed_addr alias diff --git a/test/CodeGenCXX/mangle-ms.cpp b/test/CodeGenCXX/mangle-ms.cpp index c82fca49f613..ee0f50e5e2d3 100644 --- a/test/CodeGenCXX/mangle-ms.cpp +++ b/test/CodeGenCXX/mangle-ms.cpp @@ -4,6 +4,11 @@ int a; // CHECK-DAG: @"\01?a@@3HA" +extern "C++" { +static int __attribute__((used)) ignore_transparent_context; +// CHECK-DAG: @ignore_transparent_context +} + namespace N { int b; // CHECK-DAG: @"\01?b@N@@3HA" diff --git a/test/CodeGenCXX/mangle-template.cpp b/test/CodeGenCXX/mangle-template.cpp index 7fa300ae237b..23134693de5c 100644 --- a/test/CodeGenCXX/mangle-template.cpp +++ b/test/CodeGenCXX/mangle-template.cpp @@ -201,3 +201,14 @@ namespace test14 { int call(bool b) { return inl<void>(b); } } + +namespace std { +template <class _Tp, _Tp...> struct integer_sequence {}; +} + +namespace test15 { +template <int N> +__make_integer_seq<std::integer_sequence, int, N> make() {} +template __make_integer_seq<std::integer_sequence, int, 5> make<5>(); +// CHECK: define weak_odr {{.*}} @_ZN6test154makeILi5EEE18__make_integer_seqISt16integer_sequenceiXT_EEv( +} diff --git a/test/CodeGenCXX/mangle.cpp b/test/CodeGenCXX/mangle.cpp index 5012c3b37981..5d757102ed25 100644 --- a/test/CodeGenCXX/mangle.cpp +++ b/test/CodeGenCXX/mangle.cpp @@ -1101,3 +1101,13 @@ struct c { // CHECK-LABEL: @_ZN6test541cC2EPNS0_Ut0_E }; } + +namespace test55 { +enum E { R }; + +template <typename T> +void fn(T, __underlying_type(T)) {} + +template void fn<E>(E, __underlying_type(E)); +// CHECK-LABEL: @_ZN6test552fnINS_1EEEEvT_U3eutS2_ +} diff --git a/test/CodeGenCXX/microsoft-abi-array-cookies.cpp b/test/CodeGenCXX/microsoft-abi-array-cookies.cpp index 75c0621347a5..9ef1879ce5f2 100644 --- a/test/CodeGenCXX/microsoft-abi-array-cookies.cpp +++ b/test/CodeGenCXX/microsoft-abi-array-cookies.cpp @@ -7,7 +7,7 @@ struct ClassWithoutDtor { void check_array_no_cookies() { // CHECK: define void @"\01?check_array_no_cookies@@YAXXZ"() [[NUW:#[0-9]+]] -// CHECK: call noalias i8* @"\01??_U@YAPAXI@Z"(i32 42) +// CHECK: call i8* @"\01??_U@YAPAXI@Z"(i32 42) ClassWithoutDtor *array = new ClassWithoutDtor[42]; // CHECK: call void @"\01??_V@YAXPAX@Z"( @@ -24,7 +24,7 @@ void check_array_cookies_simple() { // CHECK: define {{.*}} @"\01?check_array_cookies_simple@@YAXXZ"() ClassWithDtor *array = new ClassWithDtor[42]; -// CHECK: [[ALLOCATED:%.*]] = call noalias i8* @"\01??_U@YAPAXI@Z"(i32 46) +// CHECK: [[ALLOCATED:%.*]] = call i8* @"\01??_U@YAPAXI@Z"(i32 46) // 46 = 42 + size of cookie (4) // CHECK: [[COOKIE:%.*]] = bitcast i8* [[ALLOCATED]] to i32* // CHECK: store i32 42, i32* [[COOKIE]] @@ -46,7 +46,7 @@ struct __attribute__((aligned(8))) ClassWithAlignment { void check_array_cookies_aligned() { // CHECK: define {{.*}} @"\01?check_array_cookies_aligned@@YAXXZ"() ClassWithAlignment *array = new ClassWithAlignment[42]; -// CHECK: [[ALLOCATED:%.*]] = call noalias i8* @"\01??_U@YAPAXI@Z"(i32 344) +// CHECK: [[ALLOCATED:%.*]] = call i8* @"\01??_U@YAPAXI@Z"(i32 344) // 344 = 42*8 + size of cookie (8, due to alignment) // CHECK: [[COOKIE:%.*]] = bitcast i8* [[ALLOCATED]] to i32* // CHECK: store i32 42, i32* [[COOKIE]] diff --git a/test/CodeGenCXX/microsoft-abi-cdecl-method-sret.cpp b/test/CodeGenCXX/microsoft-abi-cdecl-method-sret.cpp index da58c461dcc0..6da7a50b617e 100644 --- a/test/CodeGenCXX/microsoft-abi-cdecl-method-sret.cpp +++ b/test/CodeGenCXX/microsoft-abi-cdecl-method-sret.cpp @@ -2,10 +2,10 @@ // PR15768 -// A trivial 12 byte struct is returned indirectly. +// A trivial 20 byte struct is returned indirectly and taken as byval. struct S { S(); - int a, b, c; + int a, b, c, d, e; }; struct C { diff --git a/test/CodeGenCXX/microsoft-abi-dynamic-cast.cpp b/test/CodeGenCXX/microsoft-abi-dynamic-cast.cpp index e9eba6ed0b20..f03cd6c5632b 100644 --- a/test/CodeGenCXX/microsoft-abi-dynamic-cast.cpp +++ b/test/CodeGenCXX/microsoft-abi-dynamic-cast.cpp @@ -60,7 +60,7 @@ T* test5(A* x) { return dynamic_cast<T*>(x); } // CHECK-NEXT: [[VBOFFP:%.*]] = getelementptr inbounds i32, i32* [[VBTBL]], i32 1 // CHECK-NEXT: [[VBOFFS:%.*]] = load i32, i32* [[VBOFFP]], align 4 // CHECK-NEXT: [[ADJ:%.*]] = getelementptr inbounds i8, i8* [[VOIDP]], i32 [[VBOFFS]] -// CHECK-NEXT: [[CALL:%.*]] = tail call i8* @__RTDynamicCast(i8* [[ADJ]], i32 [[VBOFFS]], i8* nonnull bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUA@@@8" to i8*), i8* nonnull bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUT@@@8" to i8*), i32 0) +// CHECK-NEXT: [[CALL:%.*]] = tail call i8* @__RTDynamicCast(i8* [[ADJ]], i32 [[VBOFFS]], i8* {{.*}}bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUA@@@8" to i8*), i8* {{.*}}bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUT@@@8" to i8*), i32 0) // CHECK-NEXT: [[RES:%.*]] = bitcast i8* [[CALL]] to %struct.T* // CHECK-NEXT: br label // CHECK: [[RET:%.*]] = phi %struct.T* @@ -78,7 +78,7 @@ T* test6(B* x) { return dynamic_cast<T*>(x); } // CHECK-NEXT: [[VBOFFS:%.*]] = load i32, i32* [[VBOFFP]], align 4 // CHECK-NEXT: [[DELTA:%.*]] = add nsw i32 [[VBOFFS]], 4 // CHECK-NEXT: [[ADJ:%.*]] = getelementptr inbounds i8, i8* [[CAST]], i32 [[DELTA]] -// CHECK-NEXT: [[CALL:%.*]] = tail call i8* @__RTDynamicCast(i8* [[ADJ]], i32 [[DELTA]], i8* nonnull bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUB@@@8" to i8*), i8* nonnull bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUT@@@8" to i8*), i32 0) +// CHECK-NEXT: [[CALL:%.*]] = tail call i8* @__RTDynamicCast(i8* [[ADJ]], i32 [[DELTA]], i8* {{.*}}bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUB@@@8" to i8*), i8* {{.*}}bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUT@@@8" to i8*), i32 0) // CHECK-NEXT: [[RES:%.*]] = bitcast i8* [[CALL]] to %struct.T* // CHECK-NEXT: br label // CHECK: [[RET:%.*]] = phi %struct.T* diff --git a/test/CodeGenCXX/microsoft-abi-eh-catch.cpp b/test/CodeGenCXX/microsoft-abi-eh-catch.cpp index 69ec34754813..ac1321efeae2 100644 --- a/test/CodeGenCXX/microsoft-abi-eh-catch.cpp +++ b/test/CodeGenCXX/microsoft-abi-eh-catch.cpp @@ -1,5 +1,5 @@ // RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o - -triple=x86_64-pc-windows-msvc \ -// RUN: -mconstructor-aliases -fexceptions -fcxx-exceptions -fnew-ms-eh \ +// RUN: -mconstructor-aliases -fexceptions -fcxx-exceptions \ // RUN: -O1 -disable-llvm-optzns \ // RUN: | FileCheck -check-prefix WIN64 %s diff --git a/test/CodeGenCXX/microsoft-abi-eh-cleanups.cpp b/test/CodeGenCXX/microsoft-abi-eh-cleanups.cpp index bf05c693ec0d..004dc45652e4 100644 --- a/test/CodeGenCXX/microsoft-abi-eh-cleanups.cpp +++ b/test/CodeGenCXX/microsoft-abi-eh-cleanups.cpp @@ -1,4 +1,5 @@ -// RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o - -triple=i386-pc-win32 -mconstructor-aliases -fexceptions -fcxx-exceptions -fno-rtti | FileCheck -check-prefix WIN32 %s +// RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o - -triple=i386-pc-win32 -mconstructor-aliases -fexceptions -fcxx-exceptions -fno-rtti | FileCheck -check-prefix WIN32 -check-prefix WIN32-O0 %s +// RUN: %clang_cc1 -std=c++11 -emit-llvm -O3 -disable-llvm-optzns %s -o - -triple=i386-pc-win32 -mconstructor-aliases -fexceptions -fcxx-exceptions -fno-rtti | FileCheck -check-prefix WIN32 -check-prefix WIN32-O3 -check-prefix WIN32-LIFETIME %s struct A { A(); @@ -94,40 +95,78 @@ int HasConditionalDeactivatedCleanups(bool cond) { return (cond ? TakesTwo((TakeRef(A()), A()), (TakeRef(A()), A())) : CouldThrow()); } -// WIN32-LABEL: define i32 @"\01?HasConditionalDeactivatedCleanups@@YAH_N@Z"{{.*}} { -// WIN32: alloca i1 -// WIN32: %[[arg1_cond:.*]] = alloca i1 +// WIN32-O0-LABEL: define i32 @"\01?HasConditionalDeactivatedCleanups@@YAH_N@Z"{{.*}} { +// WIN32-O0: alloca i1 +// WIN32-O0: %[[arg1_cond:.*]] = alloca i1 // Start all four cleanups as deactivated. -// WIN32: store i1 false -// WIN32: store i1 false -// WIN32: store i1 false -// WIN32: store i1 false -// WIN32: br i1 +// WIN32-O0: store i1 false +// WIN32-O0: store i1 false +// WIN32-O0: store i1 false +// WIN32-O0: store i1 false +// WIN32-O0: br i1 // True condition. -// WIN32: call x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ" -// WIN32: store i1 true -// WIN32: invoke void @"\01?TakeRef@@YAXABUA@@@Z" -// WIN32: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ" -// WIN32: store i1 true, i1* %[[arg1_cond]] -// WIN32: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ" -// WIN32: store i1 true -// WIN32: invoke void @"\01?TakeRef@@YAXABUA@@@Z" -// WIN32: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ" -// WIN32: store i1 true -// WIN32: store i1 false, i1* %[[arg1_cond]] -// WIN32: invoke i32 @"\01?TakesTwo@@YAHUA@@0@Z" +// WIN32-O0: call x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ" +// WIN32-O0: store i1 true +// WIN32-O0: invoke void @"\01?TakeRef@@YAXABUA@@@Z" +// WIN32-O0: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ" +// WIN32-O0: store i1 true, i1* %[[arg1_cond]] +// WIN32-O0: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ" +// WIN32-O0: store i1 true +// WIN32-O0: invoke void @"\01?TakeRef@@YAXABUA@@@Z" +// WIN32-O0: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ" +// WIN32-O0: store i1 true +// WIN32-O0: store i1 false, i1* %[[arg1_cond]] +// WIN32-O0: invoke i32 @"\01?TakesTwo@@YAHUA@@0@Z" // False condition. -// WIN32: invoke i32 @"\01?CouldThrow@@YAHXZ"() +// WIN32-O0: invoke i32 @"\01?CouldThrow@@YAHXZ"() // Two normal cleanups for TakeRef args. -// WIN32: call x86_thiscallcc void @"\01??1A@@QAE@XZ"({{.*}}) -// WIN32-NOT: invoke x86_thiscallcc void @"\01??1A@@QAE@XZ" -// WIN32: ret i32 +// WIN32-O0: call x86_thiscallcc void @"\01??1A@@QAE@XZ"({{.*}}) +// WIN32-O0-NOT: invoke x86_thiscallcc void @"\01??1A@@QAE@XZ" +// WIN32-O0: ret i32 // // Somewhere in the landing pad soup, we conditionally destroy arg1. -// WIN32: %[[isactive:.*]] = load i1, i1* %[[arg1_cond]] -// WIN32: br i1 %[[isactive]] -// WIN32: call x86_thiscallcc void @"\01??1A@@QAE@XZ"({{.*}}) -// WIN32: } +// WIN32-O0: %[[isactive:.*]] = load i1, i1* %[[arg1_cond]] +// WIN32-O0: br i1 %[[isactive]] +// WIN32-O0: call x86_thiscallcc void @"\01??1A@@QAE@XZ"({{.*}}) +// WIN32-O0: } + +// WIN32-O3-LABEL: define i32 @"\01?HasConditionalDeactivatedCleanups@@YAH_N@Z"{{.*}} { +// WIN32-O3: alloca i1 +// WIN32-O3: alloca i1 +// WIN32-O3: %[[arg1_cond:.*]] = alloca i1 +// Start all four cleanups as deactivated. +// WIN32-O3: store i1 false +// WIN32-O3: store i1 false +// WIN32-O3: store i1 false +// WIN32-O3: store i1 false +// WIN32-O3: store i1 false +// WIN32-O3: store i1 false +// WIN32-O3: br i1 +// True condition. +// WIN32-O3: call x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ" +// WIN32-O3: store i1 true +// WIN32-O3: invoke void @"\01?TakeRef@@YAXABUA@@@Z" +// WIN32-O3: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ" +// WIN32-O3: store i1 true, i1* %[[arg1_cond]] +// WIN32-O3: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ" +// WIN32-O3: store i1 true +// WIN32-O3: invoke void @"\01?TakeRef@@YAXABUA@@@Z" +// WIN32-O3: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ" +// WIN32-O3: store i1 true +// WIN32-O3: store i1 false, i1* %[[arg1_cond]] +// WIN32-O3: invoke i32 @"\01?TakesTwo@@YAHUA@@0@Z" +// False condition. +// WIN32-O3: invoke i32 @"\01?CouldThrow@@YAHXZ"() +// Two normal cleanups for TakeRef args. +// WIN32-O3: call x86_thiscallcc void @"\01??1A@@QAE@XZ"({{.*}}) +// WIN32-O3-NOT: invoke x86_thiscallcc void @"\01??1A@@QAE@XZ" +// WIN32-O3: ret i32 +// +// Somewhere in the landing pad soup, we conditionally destroy arg1. +// WIN32-O3: %[[isactive:.*]] = load i1, i1* %[[arg1_cond]] +// WIN32-O3: br i1 %[[isactive]] +// WIN32-O3: call x86_thiscallcc void @"\01??1A@@QAE@XZ"({{.*}}) +// WIN32-O3: } namespace crash_on_partial_destroy { struct A { @@ -206,3 +245,36 @@ void f() { // WIN32: cleanuppad // WIN32: call x86_thiscallcc void @"\01??1D@noexcept_false_dtor@@QAE@XZ"(%"struct.noexcept_false_dtor::D"* %{{.*}}) // WIN32: cleanupret + +namespace lifetime_marker { +struct C { + ~C(); +}; +void g(); +void f() { + C c; + g(); +} + +// WIN32-LIFETIME-LABEL: define void @"\01?f@lifetime_marker@@YAXXZ"() +// WIN32-LIFETIME: %[[c:.*]] = alloca %"struct.lifetime_marker::C" +// WIN32-LIFETIME: %[[bc0:.*]] = bitcast %"struct.lifetime_marker::C"* %c to i8* +// WIN32-LIFETIME: call void @llvm.lifetime.start(i64 1, i8* %[[bc0]]) +// WIN32-LIFETIME: invoke void @"\01?g@lifetime_marker@@YAXXZ"() +// WIN32-LIFETIME-NEXT: to label %[[cont:[^ ]*]] unwind label %[[lpad0:[^ ]*]] +// +// WIN32-LIFETIME: [[cont]] +// WIN32-LIFETIME: call x86_thiscallcc void @"\01??1C@lifetime_marker@@QAE@XZ"({{.*}}) +// WIN32-LIFETIME: %[[bc1:.*]] = bitcast %"struct.lifetime_marker::C"* %[[c]] to i8* +// WIN32-LIFETIME: call void @llvm.lifetime.end(i64 1, i8* %[[bc1]]) +// +// WIN32-LIFETIME: [[lpad0]] +// WIN32-LIFETIME-NEXT: cleanuppad +// WIN32-LIFETIME: call x86_thiscallcc void @"\01??1C@lifetime_marker@@QAE@XZ"({{.*}}) +// WIN32-LIFETIME: cleanupret {{.*}} unwind label %[[lpad1:[^ ]*]] +// +// WIN32-LIFETIME: [[lpad1]] +// WIN32-LIFETIME-NEXT: cleanuppad +// WIN32-LIFETIME: %[[bc2:.*]] = bitcast %"struct.lifetime_marker::C"* %[[c]] to i8* +// WIN32-LIFETIME: call void @llvm.lifetime.end(i64 1, i8* %[[bc2]]) +} diff --git a/test/CodeGenCXX/microsoft-abi-eh-terminate.cpp b/test/CodeGenCXX/microsoft-abi-eh-terminate.cpp index 0b8d270e1379..7836dcf32b11 100644 --- a/test/CodeGenCXX/microsoft-abi-eh-terminate.cpp +++ b/test/CodeGenCXX/microsoft-abi-eh-terminate.cpp @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o - -triple=x86_64-pc-windows-msvc -mconstructor-aliases -fexceptions -fcxx-exceptions -fms-compatibility-version=18.00 | FileCheck -check-prefix=MSVC2013 %s -// RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o - -triple=x86_64-pc-windows-msvc -mconstructor-aliases -fexceptions -fcxx-exceptions -fms-compatibility-version=19.00 | FileCheck -check-prefix=MSVC2015 %s +// RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o - -triple=x86_64-pc-windows-msvc -mconstructor-aliases -fexceptions -fcxx-exceptions -fms-compatibility-version=18.00 | FileCheck -check-prefix=MSVC2013 -check-prefix=CHECK %s +// RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o - -triple=x86_64-pc-windows-msvc -mconstructor-aliases -fexceptions -fcxx-exceptions -fms-compatibility-version=19.00 | FileCheck -check-prefix=MSVC2015 -check-prefix=CHECK %s void may_throw(); void never_throws() noexcept(true) { @@ -9,7 +9,8 @@ void never_throws() noexcept(true) { // CHECK-LABEL: define void @"\01?never_throws@@YAXXZ"() // CHECK-SAME: personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) // CHECK: invoke void @"\01?may_throw@@YAXXZ"() -// CHECK: cleanuppad within none [] +// CHECK: %[[cp:.*]] = cleanuppad within none [] // MSVC2013: call void @"\01?terminate@@YAXXZ"() // MSVC2015: call void @__std_terminate() +// CHECK-SAME: [ "funclet"(token %[[cp]]) ] // CHECK-NEXT: unreachable diff --git a/test/CodeGenCXX/microsoft-abi-extern-template.cpp b/test/CodeGenCXX/microsoft-abi-extern-template.cpp new file mode 100644 index 000000000000..de46d5b5c37c --- /dev/null +++ b/test/CodeGenCXX/microsoft-abi-extern-template.cpp @@ -0,0 +1,25 @@ +// RUN: %clang_cc1 -fno-rtti-data -O1 -disable-llvm-optzns %s -emit-llvm -o - -triple x86_64-windows-msvc | FileCheck %s + +// Even though Foo<int> has an extern template declaration, we have to emit our +// own copy the vftable when emitting the available externally constructor. + +// CHECK: @"\01??_7?$Foo@H@@6B@" = linkonce_odr unnamed_addr constant [1 x i8*] [ +// CHECK-SAME: i8* bitcast (i8* (%struct.Foo*, i32)* @"\01??_G?$Foo@H@@UEAAPEAXI@Z" to i8*) +// CHECK-SAME: ], comdat + +// CHECK-LABEL: define %struct.Foo* @"\01?f@@YAPEAU?$Foo@H@@XZ"() +// CHECK: call %struct.Foo* @"\01??0?$Foo@H@@QEAA@XZ"(%struct.Foo* %{{.*}}) + +// CHECK: define available_externally %struct.Foo* @"\01??0?$Foo@H@@QEAA@XZ"(%struct.Foo* returned %this) +// CHECK: store {{.*}} @"\01??_7?$Foo@H@@6B@" + +// CHECK: define linkonce_odr i8* @"\01??_G?$Foo@H@@UEAAPEAXI@Z"(%struct.Foo* %this, i32 %should_call_delete) + +struct Base { + virtual ~Base(); +}; +template <typename T> struct Foo : Base { + Foo() {} +}; +extern template class Foo<int>; +Foo<int> *f() { return new Foo<int>(); } diff --git a/test/CodeGenCXX/microsoft-abi-member-pointers.cpp b/test/CodeGenCXX/microsoft-abi-member-pointers.cpp index fd22c0034203..a3985ba09c02 100755 --- a/test/CodeGenCXX/microsoft-abi-member-pointers.cpp +++ b/test/CodeGenCXX/microsoft-abi-member-pointers.cpp @@ -3,16 +3,29 @@ // RUN: %clang_cc1 -std=c++11 -Wno-uninitialized -fno-rtti -emit-llvm %s -o - -triple=i386-pc-win32 -DINCOMPLETE_VIRTUAL -fms-extensions -verify // RUN: %clang_cc1 -std=c++11 -Wno-uninitialized -fno-rtti -emit-llvm %s -o - -triple=i386-pc-win32 -DINCOMPLETE_VIRTUAL -DMEMFUN -fms-extensions -verify +struct PR26313_Y; +typedef void (PR26313_Y::*PR26313_FUNC)(); +struct PR26313_X { + PR26313_FUNC *ptr; + PR26313_X(); +}; +PR26313_X::PR26313_X() {} +void PR26313_f(PR26313_FUNC *p) { delete p; } + +struct PR26313_Z; +int PR26313_Z::**a = nullptr; +int PR26313_Z::*b = *a; +// CHECK-DAG: @"\01?a@@3PAPQPR26313_Z@@HA" = global %0* null, align 4 +// CHECK-DAG: @"\01?b@@3PQPR26313_Z@@HQ1@" = global { i32, i32, i32 } { i32 0, i32 0, i32 -1 }, align 4 + namespace PR20947 { struct A; int A::**a = nullptr; -// CHECK: %[[opaque0:.*]] = type opaque -// CHECK: %[[opaque1:.*]] = type opaque -// CHECK: @"\01?a@PR20947@@3PAPQA@1@HA" = global %[[opaque0]]* null, align 4 +// CHECK-DAG: @"\01?a@PR20947@@3PAPQA@1@HA" = global %{{.*}}* null, align 4 struct B; int B::*&b = b; -// CHECK: @"\01?b@PR20947@@3AAPQB@1@HA" = global %[[opaque1]]* null, align 4 +// CHECK-DAG: @"\01?b@PR20947@@3AAPQB@1@HA" = global %{{.*}}* null, align 4 } namespace PR20017 { diff --git a/test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp b/test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp index 4c2d8506af70..f7dc52406740 100644 --- a/test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp +++ b/test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp @@ -22,6 +22,16 @@ struct SmallWithCtor { int x; }; +struct Multibyte { + char a, b, c, d; +}; + +struct Packed { + short a; + int b; + short c; +}; + struct SmallWithDtor { SmallWithDtor(); ~SmallWithDtor(); @@ -102,19 +112,30 @@ Big big_return() { return Big(); } void small_arg(Small s) {} // LINUX-LABEL: define void @_Z9small_arg5Small(i32 %s.0) -// WIN32: define void @"\01?small_arg@@YAXUSmall@@@Z"(%struct.Small* byval align 4 %s) +// WIN32: define void @"\01?small_arg@@YAXUSmall@@@Z"(i32 %s.0) // WIN64: define void @"\01?small_arg@@YAXUSmall@@@Z"(i32 %s.coerce) void medium_arg(Medium s) {} // LINUX-LABEL: define void @_Z10medium_arg6Medium(i32 %s.0, i32 %s.1) -// WIN32: define void @"\01?medium_arg@@YAXUMedium@@@Z"(%struct.Medium* byval align 4 %s) +// WIN32: define void @"\01?medium_arg@@YAXUMedium@@@Z"(i32 %s.0, i32 %s.1) // WIN64: define void @"\01?medium_arg@@YAXUMedium@@@Z"(i64 %s.coerce) void small_arg_with_ctor(SmallWithCtor s) {} // LINUX-LABEL: define void @_Z19small_arg_with_ctor13SmallWithCtor(%struct.SmallWithCtor* byval align 4 %s) -// WIN32: define void @"\01?small_arg_with_ctor@@YAXUSmallWithCtor@@@Z"(%struct.SmallWithCtor* byval align 4 %s) +// WIN32: define void @"\01?small_arg_with_ctor@@YAXUSmallWithCtor@@@Z"(i32 %s.0) // WIN64: define void @"\01?small_arg_with_ctor@@YAXUSmallWithCtor@@@Z"(i32 %s.coerce) +// FIXME: We could coerce to a series of i32s here if we wanted to. +void multibyte_arg(Multibyte s) {} +// LINUX-LABEL: define void @_Z13multibyte_arg9Multibyte(%struct.Multibyte* byval align 4 %s) +// WIN32: define void @"\01?multibyte_arg@@YAXUMultibyte@@@Z"(%struct.Multibyte* byval align 4 %s) +// WIN64: define void @"\01?multibyte_arg@@YAXUMultibyte@@@Z"(i32 %s.coerce) + +void packed_arg(Packed s) {} +// LINUX-LABEL: define void @_Z10packed_arg6Packed(%struct.Packed* byval align 4 %s) +// WIN32: define void @"\01?packed_arg@@YAXUPacked@@@Z"(%struct.Packed* byval align 4 %s) +// WIN64: define void @"\01?packed_arg@@YAXUPacked@@@Z"(%struct.Packed* %s) + // Test that dtors are invoked in the callee. void small_arg_with_dtor(SmallWithDtor s) {} // WIN32: define void @"\01?small_arg_with_dtor@@YAXUSmallWithDtor@@@Z"(<{ %struct.SmallWithDtor }>* inalloca) {{.*}} { @@ -196,6 +217,28 @@ void big_arg(Big s) {} // WIN32: define void @"\01?big_arg@@YAXUBig@@@Z"(%struct.Big* byval align 4 %s) // WIN64: define void @"\01?big_arg@@YAXUBig@@@Z"(%struct.Big* %s) +// PR27607: We would attempt to load i32 value out of the reference instead of +// just loading the pointer from the struct during argument expansion. +struct RefField { + RefField(int &x); + int &x; +}; +void takes_ref_field(RefField s) {} +// LINUX-LABEL: define void @_Z15takes_ref_field8RefField(%struct.RefField* byval align 4 %s) +// WIN32: define void @"\01?takes_ref_field@@YAXURefField@@@Z"(i32* %s.0) +// WIN64: define void @"\01?takes_ref_field@@YAXURefField@@@Z"(i64 %s.coerce) + +void pass_ref_field() { + int x; + takes_ref_field(RefField(x)); +} +// LINUX-LABEL: define void @_Z14pass_ref_fieldv() +// LINUX: call void @_Z15takes_ref_field8RefField(%struct.RefField* byval align 4 %{{.*}}) +// WIN32-LABEL: define void @"\01?pass_ref_field@@YAXXZ"() +// WIN32: call void @"\01?takes_ref_field@@YAXURefField@@@Z"(i32* %{{.*}}) +// WIN64-LABEL: define void @"\01?pass_ref_field@@YAXXZ"() +// WIN64: call void @"\01?takes_ref_field@@YAXURefField@@@Z"(i64 %{{.*}}) + class Class { public: Small thiscall_method_small() { return Small(); } @@ -230,12 +273,12 @@ class Class { void thiscall_method_arg(Small s) {} // LINUX: define {{.*}} void @_ZN5Class19thiscall_method_argE5Small(%class.Class* %this, i32 %s.0) - // WIN32: define {{.*}} void @"\01?thiscall_method_arg@Class@@QAEXUSmall@@@Z"(%class.Class* %this, %struct.Small* byval align 4 %s) + // WIN32: define {{.*}} void @"\01?thiscall_method_arg@Class@@QAEXUSmall@@@Z"(%class.Class* %this, i32 %s.0) // WIN64: define linkonce_odr void @"\01?thiscall_method_arg@Class@@QEAAXUSmall@@@Z"(%class.Class* %this, i32 %s.coerce) void thiscall_method_arg(SmallWithCtor s) {} // LINUX: define {{.*}} void @_ZN5Class19thiscall_method_argE13SmallWithCtor(%class.Class* %this, %struct.SmallWithCtor* byval align 4 %s) - // WIN32: define {{.*}} void @"\01?thiscall_method_arg@Class@@QAEXUSmallWithCtor@@@Z"(%class.Class* %this, %struct.SmallWithCtor* byval align 4 %s) + // WIN32: define {{.*}} void @"\01?thiscall_method_arg@Class@@QAEXUSmallWithCtor@@@Z"(%class.Class* %this, i32 %s.0) // WIN64: define linkonce_odr void @"\01?thiscall_method_arg@Class@@QEAAXUSmallWithCtor@@@Z"(%class.Class* %this, i32 %s.coerce) void thiscall_method_arg(Big s) {} diff --git a/test/CodeGenCXX/microsoft-abi-structors.cpp b/test/CodeGenCXX/microsoft-abi-structors.cpp index 3fb97b9a3632..a576f0c3d7e3 100644 --- a/test/CodeGenCXX/microsoft-abi-structors.cpp +++ b/test/CodeGenCXX/microsoft-abi-structors.cpp @@ -7,7 +7,7 @@ // RUN: FileCheck --check-prefix DTORS3 %s < %t // RUN: FileCheck --check-prefix DTORS4 %s < %t // -// RUN: %clang_cc1 -emit-llvm %s -o - -mconstructor-aliases -triple=x86_64-pc-win32 -fno-rtti | FileCheck --check-prefix DTORS-X64 %s +// RUN: %clang_cc1 -emit-llvm %s -o - -mconstructor-aliases -triple=x86_64-pc-win32 -fno-rtti -std=c++11 | FileCheck --check-prefix DTORS-X64 %s namespace basic { @@ -443,6 +443,20 @@ void g() { new MoveOnly(f()); } // CHECK: store {{.*}} @"\01??_7MoveOnly@implicit_copy_vtable@@6B@" } +namespace delegating_ctor { +struct Y {}; +struct X : virtual Y { + X(int); + X(); +}; +X::X(int) : X() {} +} +// CHECK: define x86_thiscallcc %"struct.delegating_ctor::X"* @"\01??0X@delegating_ctor@@QAE@H@Z"( +// CHECK: %[[is_most_derived_addr:.*]] = alloca i32, align 4 +// CHECK: store i32 %is_most_derived, i32* %[[is_most_derived_addr]] +// CHECK: %[[is_most_derived:.*]] = load i32, i32* %[[is_most_derived_addr]] +// CHECK: call x86_thiscallcc {{.*}}* @"\01??0X@delegating_ctor@@QAE@XZ"({{.*}} i32 %[[is_most_derived]]) + // Dtor thunks for classes in anonymous namespaces should be internal, not // linkonce_odr. namespace { @@ -471,4 +485,3 @@ class G { extern void testG() { G g; } - diff --git a/test/CodeGenCXX/microsoft-abi-thread-safe-statics.cpp b/test/CodeGenCXX/microsoft-abi-thread-safe-statics.cpp index 29b434eaf2c5..0202586c8a62 100644 --- a/test/CodeGenCXX/microsoft-abi-thread-safe-statics.cpp +++ b/test/CodeGenCXX/microsoft-abi-thread-safe-statics.cpp @@ -9,12 +9,14 @@ struct S { // CHECK-DAG: @"\01?s@?1??f@@YAAAUS@@XZ@4U2@A" = linkonce_odr thread_local global %struct.S zeroinitializer // CHECK-DAG: @"\01??__J?1??f@@YAAAUS@@XZ@51" = linkonce_odr thread_local global i32 0 // CHECK-DAG: @"\01?s@?1??g@@YAAAUS@@XZ@4U2@A" = linkonce_odr global %struct.S zeroinitializer -// CHECK-DAG: @"\01?$TSS0@?1??g@@YAAAUS@@XZ" = linkonce_odr global i32 0 +// CHECK-DAG: @"\01?$TSS0@?1??g@@YAAAUS@@XZ@4HA" = linkonce_odr global i32 0 // CHECK-DAG: @_Init_thread_epoch = external thread_local global i32, align 4 // CHECK-DAG: @"\01?j@?1??h@@YAAAUS@@_N@Z@4U2@A" = linkonce_odr thread_local global %struct.S zeroinitializer // CHECK-DAG: @"\01??__J?1??h@@YAAAUS@@_N@Z@51" = linkonce_odr thread_local global i32 0 // CHECK-DAG: @"\01?i@?1??h@@YAAAUS@@_N@Z@4U2@A" = linkonce_odr global %struct.S zeroinitializer -// CHECK-DAG: @"\01?$TSS0@?1??h@@YAAAUS@@_N@Z" = linkonce_odr global i32 0 +// CHECK-DAG: @"\01?$TSS0@?1??h@@YAAAUS@@_N@Z@4HA" = linkonce_odr global i32 0 +// CHECK-DAG: @"\01?i@?1??g1@@YAHXZ@4HA" = internal global i32 0, align 4 +// CHECK-DAG: @"\01?$TSS0@?1??g1@@YAHXZ@4HA" = internal global i32 0, align 4 // CHECK-LABEL: define {{.*}} @"\01?f@@YAAAUS@@XZ"() // CHECK-SAME: personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) @@ -51,14 +53,14 @@ extern inline S &f() { // CHECK-LABEL: define {{.*}} @"\01?g@@YAAAUS@@XZ"() extern inline S &g() { static S s; -// CHECK: %[[guard:.*]] = load atomic i32, i32* @"\01?$TSS0@?1??g@@YAAAUS@@XZ" unordered, align 4 +// CHECK: %[[guard:.*]] = load atomic i32, i32* @"\01?$TSS0@?1??g@@YAAAUS@@XZ@4HA" unordered, align 4 // CHECK-NEXT: %[[epoch:.*]] = load i32, i32* @_Init_thread_epoch // CHECK-NEXT: %[[cmp:.*]] = icmp sgt i32 %[[guard]], %[[epoch]] // CHECK-NEXT: br i1 %[[cmp]], label %[[init_attempt:.*]], label %[[init_end:.*]] // // CHECK: [[init_attempt]]: -// CHECK-NEXT: call void @_Init_thread_header(i32* @"\01?$TSS0@?1??g@@YAAAUS@@XZ") -// CHECK-NEXT: %[[guard2:.*]] = load atomic i32, i32* @"\01?$TSS0@?1??g@@YAAAUS@@XZ" unordered, align 4 +// CHECK-NEXT: call void @_Init_thread_header(i32* @"\01?$TSS0@?1??g@@YAAAUS@@XZ@4HA") +// CHECK-NEXT: %[[guard2:.*]] = load atomic i32, i32* @"\01?$TSS0@?1??g@@YAAAUS@@XZ@4HA" unordered, align 4 // CHECK-NEXT: %[[cmp2:.*]] = icmp eq i32 %[[guard2]], -1 // CHECK-NEXT: br i1 %[[cmp2]], label %[[init:.*]], label %[[init_end:.*]] // @@ -68,7 +70,7 @@ extern inline S &g() { // // CHECK: [[invoke_cont]]: // CHECK-NEXT: call i32 @atexit(void ()* @"\01??__Fs@?1??g@@YAAAUS@@XZ@YAXXZ") -// CHECK-NEXT: call void @_Init_thread_footer(i32* @"\01?$TSS0@?1??g@@YAAAUS@@XZ") +// CHECK-NEXT: call void @_Init_thread_footer(i32* @"\01?$TSS0@?1??g@@YAAAUS@@XZ@4HA") // CHECK-NEXT: br label %init.end // // CHECK: [[init_end]]: @@ -76,7 +78,7 @@ extern inline S &g() { // // CHECK: [[lpad]]: // CHECK-NEXT: cleanuppad within none [] -// CHECK: call void @_Init_thread_abort(i32* @"\01?$TSS0@?1??g@@YAAAUS@@XZ") +// CHECK: call void @_Init_thread_abort(i32* @"\01?$TSS0@?1??g@@YAAAUS@@XZ@4HA") // CHECK-NEXT: cleanupret {{.*}} unwind to caller return s; } @@ -86,3 +88,10 @@ extern inline S&h(bool b) { static S i; return b ? j : i; } + +// CHECK-LABEL: define i32 @"\01?g1@@YAHXZ"() +int f1(); +int g1() { + static int i = f1(); + return i; +} diff --git a/test/CodeGenCXX/microsoft-abi-throw.cpp b/test/CodeGenCXX/microsoft-abi-throw.cpp index 080f1a025cd8..7c2e2a8f901e 100644 --- a/test/CodeGenCXX/microsoft-abi-throw.cpp +++ b/test/CodeGenCXX/microsoft-abi-throw.cpp @@ -1,4 +1,5 @@ // RUN: %clang_cc1 -emit-llvm -o - -triple=i386-pc-win32 -std=c++11 %s -fcxx-exceptions -fms-extensions | FileCheck %s +// RUN: %clang_cc1 -emit-llvm -o - -triple=i386-pc-win32 -std=c++11 %s -fcxx-exceptions -fms-extensions -DSTD | FileCheck %s // CHECK-DAG: @"\01??_R0?AUY@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"\01??_7type_info@@6B@", i8* null, [8 x i8] c".?AUY@@\00" }, comdat // CHECK-DAG: @"_CT??_R0?AUY@@@8??0Y@@QAE@ABU0@@Z8" = linkonce_odr unnamed_addr constant %eh.CatchableType { i32 4, i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUY@@@8" to i8*), i32 0, i32 -1, i32 0, i32 8, i8* bitcast (%struct.Y* (%struct.Y*, %struct.Y*, i32)* @"\01??0Y@@QAE@ABU0@@Z" to i8*) }, section ".xdata", comdat @@ -19,6 +20,8 @@ // CHECK-DAG: @"_CT??_R0P6AXXZ@84" = linkonce_odr unnamed_addr constant %eh.CatchableType { i32 1, i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0P6AXXZ@8" to i8*), i32 0, i32 -1, i32 0, i32 4, i8* null }, section ".xdata", comdat // CHECK-DAG: @_CTA1P6AXXZ = linkonce_odr unnamed_addr constant %eh.CatchableTypeArray.1 { i32 1, [1 x %eh.CatchableType*] [%eh.CatchableType* @"_CT??_R0P6AXXZ@84"] }, section ".xdata", comdat // CHECK-DAG: @_TI1P6AXXZ = linkonce_odr unnamed_addr constant %eh.ThrowInfo { i32 0, i8* null, i8* null, i8* bitcast (%eh.CatchableTypeArray.1* @_CTA1P6AXXZ to i8*) }, section ".xdata", comdat +// CHECK-DAG: @_TIU2PAPFAH = linkonce_odr unnamed_addr constant %eh.ThrowInfo { i32 4, i8* null, i8* null, i8* bitcast (%eh.CatchableTypeArray.2* @_CTA2PAPFAH to i8*) }, section ".xdata", comdat +// CHECK-DAG: @_CTA2PAPFAH = linkonce_odr unnamed_addr constant %eh.CatchableTypeArray.2 { i32 2, [2 x %eh.CatchableType*] [%eh.CatchableType* @"_CT??_R0PAPFAH@84", %eh.CatchableType* @"_CT??_R0PAX@84"] }, section ".xdata", comdat struct N { ~N(); }; @@ -43,6 +46,12 @@ void g(const int *const *y) { throw y; } +void h(__unaligned int * __unaligned *y) { + // CHECK-LABEL: @"\01?h@@YAXPFAPFAH@Z" + // CHECK: call void @_CxxThrowException(i8* %{{.*}}, %eh.ThrowInfo* @_TIU2PAPFAH) + throw y; +} + struct Default { Default(Default &, int = 42); }; @@ -97,19 +106,25 @@ void h() { throw nullptr; } +#ifdef STD namespace std { template <typename T> void *__GetExceptionInfo(T); } +#else +template <typename T> +void *__GetExceptionInfo(T); +#endif +using namespace std; void *GetExceptionInfo_test0() { // CHECK-LABEL: @"\01?GetExceptionInfo_test0@@YAPAXXZ" // CHECK: ret i8* bitcast (%eh.ThrowInfo* @_TI1H to i8*) - return std::__GetExceptionInfo(0); + return __GetExceptionInfo(0); } void *GetExceptionInfo_test1() { // CHECK-LABEL: @"\01?GetExceptionInfo_test1@@YAPAXXZ" // CHECK: ret i8* bitcast (%eh.ThrowInfo* @_TI1P6AXXZ to i8*) - return std::__GetExceptionInfo<void (*)()>(&h); + return __GetExceptionInfo<void (*)()>(&h); } diff --git a/test/CodeGenCXX/microsoft-abi-try-throw.cpp b/test/CodeGenCXX/microsoft-abi-try-throw.cpp index 6b1d2bf2a513..bf1834e8594e 100644 --- a/test/CodeGenCXX/microsoft-abi-try-throw.cpp +++ b/test/CodeGenCXX/microsoft-abi-try-throw.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -emit-llvm %s -o - -triple=i386-pc-win32 -mconstructor-aliases -fcxx-exceptions -fexceptions -fno-rtti -DTRY -fnew-ms-eh | FileCheck %s -check-prefix=TRY +// RUN: %clang_cc1 -emit-llvm %s -o - -triple=i386-pc-win32 -mconstructor-aliases -fcxx-exceptions -fexceptions -fno-rtti -DTRY | FileCheck %s -check-prefix=TRY // RUN: %clang_cc1 -emit-llvm %s -o - -triple=i386-pc-win32 -mconstructor-aliases -fcxx-exceptions -fexceptions -fno-rtti -DTHROW | FileCheck %s -check-prefix=THROW // THROW-DAG: @"\01??_R0H@8" = linkonce_odr global %rtti.TypeDescriptor2 { i8** @"\01??_7type_info@@6B@", i8* null, [3 x i8] c".H\00" }, comdat diff --git a/test/CodeGenCXX/microsoft-abi-typeid.cpp b/test/CodeGenCXX/microsoft-abi-typeid.cpp index 60c31ab4706c..d73f8483a713 100644 --- a/test/CodeGenCXX/microsoft-abi-typeid.cpp +++ b/test/CodeGenCXX/microsoft-abi-typeid.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -emit-llvm -O1 -o - -triple=i386-pc-win32 %s | FileCheck %s +// RUN: %clang_cc1 -emit-llvm -O1 -o - -triple=i386-pc-win32 %s -fexceptions -fcxx-exceptions | FileCheck %s struct type_info; namespace std { using ::type_info; } @@ -49,3 +49,22 @@ const std::type_info* test5_typeid() { return &typeid(v); } // CHECK: [[RT:%.*]] = tail call i8* @__RTtypeid(i8* bitcast (%struct.V* @"\01?v@@3UV@@A" to i8*)) // CHECK-NEXT: [[RET:%.*]] = bitcast i8* [[RT]] to %struct.type_info* // CHECK-NEXT: ret %struct.type_info* [[RET]] + +namespace PR26329 { +struct Polymorphic { + virtual ~Polymorphic(); +}; + +void f(const Polymorphic &poly) { + try { + throw; + } catch (...) { + Polymorphic cleanup; + typeid(poly); + } +} +// CHECK-LABEL: define void @"\01?f@PR26329@@YAXABUPolymorphic@1@@Z"( +// CHECK: %[[cs:.*]] = catchswitch within none [label %{{.*}}] unwind to caller +// CHECK: %[[cp:.*]] = catchpad within %[[cs]] [i8* null, i32 64, i8* null] +// CHECK: invoke i8* @__RTtypeid(i8* {{.*}}) [ "funclet"(token %[[cp]]) ] +} diff --git a/test/CodeGenCXX/microsoft-abi-vbtables.cpp b/test/CodeGenCXX/microsoft-abi-vbtables.cpp index 9cce6f8698c8..df0689423872 100644 --- a/test/CodeGenCXX/microsoft-abi-vbtables.cpp +++ b/test/CodeGenCXX/microsoft-abi-vbtables.cpp @@ -537,5 +537,5 @@ template <class> struct B : virtual A { extern template class B<int>; template B<int>::B(); -// CHECK-DAG: @"\01??_8?$B@H@Test30@@7B@" = external unnamed_addr constant [2 x i32]{{$}} +// CHECK-DAG: @"\01??_8?$B@H@Test30@@7B@" = linkonce_odr unnamed_addr constant [2 x i32] [i32 0, i32 4], comdat } diff --git a/test/CodeGenCXX/microsoft-abi-vftables.cpp b/test/CodeGenCXX/microsoft-abi-vftables.cpp index 340675b188d5..0c9b58bbb4d4 100644 --- a/test/CodeGenCXX/microsoft-abi-vftables.cpp +++ b/test/CodeGenCXX/microsoft-abi-vftables.cpp @@ -17,9 +17,10 @@ struct __declspec(dllimport) U { virtual ~U(); } u; -// RTTI-DAG: @"\01??_7U@@6B@" = available_externally dllimport unnamed_addr constant [1 x i8*] [i8* bitcast ({{.*}} @"\01??_GU@@UAEPAXI@Z" to i8*)] +// RTTI-DAG: [[VTABLE_U:@.*]] = private unnamed_addr constant [2 x i8*] [i8* bitcast ({{.*}} @"\01??_R4U@@6B@" to i8*), i8* bitcast ({{.*}} @"\01??_GU@@UAEPAXI@Z" to i8*)] +// RTTI-DAG: @"\01??_SU@@6B@" = unnamed_addr alias i8*, getelementptr inbounds ([2 x i8*], [2 x i8*]* [[VTABLE_U]], i32 0, i32 1) -// NO-RTTI-DAG: @"\01??_7U@@6B@" = available_externally dllimport unnamed_addr constant [1 x i8*] [i8* bitcast ({{.*}} @"\01??_GU@@UAEPAXI@Z" to i8*)] +// NO-RTTI-DAG: @"\01??_SU@@6B@" = linkonce_odr unnamed_addr constant [1 x i8*] [i8* bitcast ({{.*}} @"\01??_GU@@UAEPAXI@Z" to i8*)] struct __declspec(dllexport) V { virtual ~V(); @@ -32,7 +33,7 @@ struct __declspec(dllexport) V { namespace { struct W { - virtual ~W(); + virtual ~W() {} } w; } // RTTI-DAG: [[VTABLE_W:@.*]] = private unnamed_addr constant [2 x i8*] [i8* bitcast ({{.*}} @"\01??_R4W@?A@@6B@" to i8*), i8* bitcast ({{.*}} @"\01??_GW@?A@@UAEPAXI@Z" to i8*)] @@ -48,5 +49,7 @@ template <class> struct Y : virtual X { extern template class Y<int>; template Y<int>::Y(); -// RTTI-DAG: @"\01??_7?$Y@H@@6B@" = external unnamed_addr constant [1 x i8*] -// NO-RTTI-DAG: @"\01??_7?$Y@H@@6B@" = external unnamed_addr constant [1 x i8*] +// RTTI-DAG: [[VTABLE_Y:@.*]] = private unnamed_addr constant [2 x i8*] [i8* bitcast (%rtti.CompleteObjectLocator* @"\01??_R4?$Y@H@@6B@" to i8*), i8* bitcast (i8* (%struct.Y*, i32)* @"\01??_G?$Y@H@@UAEPAXI@Z" to i8*)], comdat($"\01??_7?$Y@H@@6B@") +// RTTI-DAG: @"\01??_7?$Y@H@@6B@" = unnamed_addr alias i8*, getelementptr inbounds ([2 x i8*], [2 x i8*]* [[VTABLE_Y]], i32 0, i32 1) + +// NO-RTTI-DAG: @"\01??_7?$Y@H@@6B@" = linkonce_odr unnamed_addr constant [1 x i8*] [i8* bitcast (i8* (%struct.Y*, i32)* @"\01??_G?$Y@H@@UAEPAXI@Z" to i8*)], comdat diff --git a/test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp b/test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp index 8897a384430c..480ae8cfbbec 100644 --- a/test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp +++ b/test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp @@ -481,3 +481,43 @@ C::C() : B() {} // CHECK: %[[FIELD:.*]] = getelementptr inbounds i8, i8* %[[B_i8]], i32 4 // CHECK: call void @llvm.memset.p0i8.i32(i8* %[[FIELD]], i8 0, i32 4, i32 4, i1 false) } + +namespace pr27621 { +// Devirtualization through a static_cast used to make us compute the 'this' +// adjustment for B::g instead of C::g. When we directly call C::g, 'this' is a +// B*, and the prologue of C::g will adjust it to a C*. +struct A { virtual void f(); }; +struct B { virtual void g(); }; +struct C final : A, B { + virtual void h(); + void g() override; +}; +void callit(C *p) { + static_cast<B*>(p)->g(); +} +// CHECK-LABEL: define void @"\01?callit@pr27621@@YAXPAUC@1@@Z"(%"struct.pr27621::C"* %{{.*}}) +// CHECK: %[[B_i8:.*]] = getelementptr i8, i8* %{{.*}}, i32 4 +// CHECK: call x86_thiscallcc void @"\01?g@C@pr27621@@UAEXXZ"(i8* %[[B_i8]]) +} + +namespace test6 { +class A {}; +class B : virtual A {}; +class C : virtual B { + virtual void m_fn1(); + float field; +}; +class D : C { + D(); +}; +D::D() : C() {} +// CHECK-LABEL: define x86_thiscallcc %"class.test6::D"* @"\01??0D@test6@@AAE@XZ"( +// CHECK: %[[THIS:.*]] = load %"class.test6::D"*, %"class.test6::D"** +// CHECK: br i1 %{{.*}}, label %[[INIT_VBASES:.*]], label %[[SKIP_VBASES:.*]] + +// CHECK: %[[SKIP_VBASES]] +// CHECK: %[[C:.*]] = bitcast %"class.test6::D"* %[[THIS]] to %"class.test6::C"* +// CHECK: %[[C_i8:.*]] = bitcast %"class.test6::C"* %[[C]] to i8* +// CHECK: %[[FIELD:.*]] = getelementptr inbounds i8, i8* %[[C_i8]], i32 8 +// CHECK: call void @llvm.memset.p0i8.i32(i8* %[[FIELD]], i8 0, i32 4, i32 4, i1 false) +} diff --git a/test/CodeGenCXX/microsoft-interface.cpp b/test/CodeGenCXX/microsoft-interface.cpp index a2dfb6926d81..8f4670a6946a 100644 --- a/test/CodeGenCXX/microsoft-interface.cpp +++ b/test/CodeGenCXX/microsoft-interface.cpp @@ -31,10 +31,10 @@ int fn() { // CHECK-LABEL: define linkonce_odr x86_thiscallcc void @_ZN1SC2Ev(%struct.S* %this) // CHECK: call x86_thiscallcc void @_ZN1IC2Ev(%__interface.I* %{{[.0-9A-Z_a-z]+}}) -// CHECK: store i32 (...)** bitcast (i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTV1S, i64 0, i64 2) to i32 (...)**), i32 (...)*** %{{[.0-9A-Z_a-z]+}} +// CHECK: store i32 (...)** bitcast (i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTV1S, i32 0, i32 2) to i32 (...)**), i32 (...)*** %{{[.0-9A-Z_a-z]+}} // CHECK-LABEL: define linkonce_odr x86_thiscallcc void @_ZN1IC2Ev(%__interface.I* %this) -// CHECK: store i32 (...)** bitcast (i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTV1I, i64 0, i64 2) to i32 (...)**), i32 (...)*** %{{[.0-9A-Z_a-z]+}} +// CHECK: store i32 (...)** bitcast (i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTV1I, i32 0, i32 2) to i32 (...)**), i32 (...)*** %{{[.0-9A-Z_a-z]+}} // CHECK-LABEL: define linkonce_odr x86_thiscallcc i32 @_ZN1I4testEv(%__interface.I* %this) // CHECK: ret i32 1 diff --git a/test/CodeGenCXX/microsoft-templ-uuidof.cpp b/test/CodeGenCXX/microsoft-templ-uuidof.cpp index 0ee390863837..74d6069bbacf 100644 --- a/test/CodeGenCXX/microsoft-templ-uuidof.cpp +++ b/test/CodeGenCXX/microsoft-templ-uuidof.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -emit-llvm %s -o - -DDEFINE_GUID -triple=i386-pc-win32 -fms-extensions | FileCheck %s --check-prefix=CHECK +// RUN: %clang_cc1 -emit-llvm %s -o - -DDEFINE_GUID -triple=i386-pc-win32 -fms-extensions | FileCheck %s struct _GUID; diff --git a/test/CodeGenCXX/microsoft-uuidof.cpp b/test/CodeGenCXX/microsoft-uuidof.cpp index 2ac5f1b07999..62e4b880ad46 100644 --- a/test/CodeGenCXX/microsoft-uuidof.cpp +++ b/test/CodeGenCXX/microsoft-uuidof.cpp @@ -1,5 +1,6 @@ // RUN: %clang_cc1 -emit-llvm %s -o - -DDEFINE_GUID -triple=i386-pc-linux -fms-extensions | FileCheck %s --check-prefix=CHECK-DEFINE-GUID // RUN: %clang_cc1 -emit-llvm %s -o - -triple=i386-pc-linux -fms-extensions | FileCheck %s +// RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-pc-linux -fms-extensions | FileCheck %s --check-prefix=CHECK-64 // RUN: %clang_cc1 -emit-llvm %s -o - -DDEFINE_GUID -DWRONG_GUID -triple=i386-pc-linux -fms-extensions | FileCheck %s --check-prefix=CHECK-DEFINE-WRONG-GUID #ifdef DEFINE_GUID @@ -36,6 +37,7 @@ GUID g = __uuidof(S1); // First global use of __uuidof(S1) forces the creation of the global. // CHECK: @_GUID_12345678_1234_1234_1234_1234567890ab = linkonce_odr constant { i32, i16, i16, [8 x i8] } { i32 305419896, i16 4660, i16 4660, [8 x i8] c"\124\124Vx\90\AB" }, comdat // CHECK: @gr = constant %struct._GUID* bitcast ({ i32, i16, i16, [8 x i8] }* @_GUID_12345678_1234_1234_1234_1234567890ab to %struct._GUID*), align 4 +// CHECK-64: @gr = constant %struct._GUID* bitcast ({ i32, i16, i16, [8 x i8] }* @_GUID_12345678_1234_1234_1234_1234567890ab to %struct._GUID*), align 8 const GUID& gr = __uuidof(S1); // CHECK: @gp = global %struct._GUID* bitcast ({ i32, i16, i16, [8 x i8] }* @_GUID_12345678_1234_1234_1234_1234567890ab to %struct._GUID*), align 4 diff --git a/test/CodeGenCXX/mips-size_t-ptrdiff_t.cpp b/test/CodeGenCXX/mips-size_t-ptrdiff_t.cpp index 1ff01820bb1b..5b245a4aaccd 100644 --- a/test/CodeGenCXX/mips-size_t-ptrdiff_t.cpp +++ b/test/CodeGenCXX/mips-size_t-ptrdiff_t.cpp @@ -10,13 +10,13 @@ long *alloc_long() { return rv; } // O32-LABEL: define i32* @_Z10alloc_longv() -// O32: call noalias i8* @_Znwj(i32 signext 4) +// O32: call i8* @_Znwj(i32 signext 4) // N32-LABEL: define i32* @_Z10alloc_longv() -// N32: call noalias i8* @_Znwj(i32 signext 4) +// N32: call i8* @_Znwj(i32 signext 4) // N64-LABEL: define i64* @_Z10alloc_longv() -// N64: call noalias i8* @_Znwm(i64 zeroext 8) +// N64: call i8* @_Znwm(i64 zeroext 8) long *alloc_long_array() { long *rv = new long[2]; @@ -24,13 +24,13 @@ long *alloc_long_array() { } // O32-LABEL: define i32* @_Z16alloc_long_arrayv() -// O32: call noalias i8* @_Znaj(i32 signext 8) +// O32: call i8* @_Znaj(i32 signext 8) // N32-LABEL: define i32* @_Z16alloc_long_arrayv() -// N32: call noalias i8* @_Znaj(i32 signext 8) +// N32: call i8* @_Znaj(i32 signext 8) // N64-LABEL: define i64* @_Z16alloc_long_arrayv() -// N64: call noalias i8* @_Znam(i64 zeroext 16) +// N64: call i8* @_Znam(i64 zeroext 16) #include <stddef.h> diff --git a/test/CodeGenCXX/multi-dim-operator-new.cpp b/test/CodeGenCXX/multi-dim-operator-new.cpp index 7a235e83a78d..0dfcffb6aa40 100644 --- a/test/CodeGenCXX/multi-dim-operator-new.cpp +++ b/test/CodeGenCXX/multi-dim-operator-new.cpp @@ -43,7 +43,7 @@ int main() { return 0; } -// CHECK: call noalias i8* @_Znam -// CHECK: call noalias i8* @_Znam -// CHECK: call noalias i8* @_Znam +// CHECK: call i8* @_Znam +// CHECK: call i8* @_Znam +// CHECK: call i8* @_Znam diff --git a/test/CodeGenCXX/new-alias.cpp b/test/CodeGenCXX/new-alias.cpp index 4afd942e3cdb..b21638abbfb6 100644 --- a/test/CodeGenCXX/new-alias.cpp +++ b/test/CodeGenCXX/new-alias.cpp @@ -9,5 +9,5 @@ extern "C" char *something(long long x) { void *operator new(size_t) __attribute__((alias("something"))); // PR16715: don't assert here. -// CHECK: call noalias i8* @_Znwm(i64 4){{$}} +// CHECK: call i8* @_Znwm(i64 4){{$}} int *pr16715 = new int; diff --git a/test/CodeGenCXX/new-array-init.cpp b/test/CodeGenCXX/new-array-init.cpp index 6b76f471a22b..602f93c34f01 100644 --- a/test/CodeGenCXX/new-array-init.cpp +++ b/test/CodeGenCXX/new-array-init.cpp @@ -14,7 +14,7 @@ void fn(int n) { // CHECK-LABEL: define void @_Z15const_underflowv void const_underflow() { // CHECK-NOT: icmp ult i{{32|64}} %{{[^ ]+}}, 3 - // CHECK: call noalias i8* @_Zna{{.}}(i{{32|64}} -1) + // CHECK: call i8* @_Zna{{.}}(i{{32|64}} -1) new int[2] { 1, 2, 3 }; } @@ -37,7 +37,7 @@ void check_array_value_init() { struct S; new (int S::*[3][4][5]) (); - // CHECK: call noalias i8* @_Zna{{.}}(i{{32 240|64 480}}) + // CHECK: call i8* @_Zna{{.}}(i{{32 240|64 480}}) // CHECK: getelementptr inbounds i{{32|64}}, i{{32|64}}* {{.*}}, i{{32|64}} 60 // CHECK: phi diff --git a/test/CodeGenCXX/new-overflow.cpp b/test/CodeGenCXX/new-overflow.cpp index 9057e049b700..0c4c3c823d19 100644 --- a/test/CodeGenCXX/new-overflow.cpp +++ b/test/CodeGenCXX/new-overflow.cpp @@ -17,7 +17,7 @@ namespace test0 { // CHECK-NEXT: [[T1:%.*]] = extractvalue { i32, i1 } [[T0]], 1 // CHECK-NEXT: [[T2:%.*]] = extractvalue { i32, i1 } [[T0]], 0 // CHECK-NEXT: [[T3:%.*]] = select i1 [[T1]], i32 -1, i32 [[T2]] - // CHECK-NEXT: call noalias i8* @_Znaj(i32 [[T3]]) + // CHECK-NEXT: call i8* @_Znaj(i32 [[T3]]) // CHECK: getelementptr inbounds {{.*}}, i32 [[N]] elt *test(short s) { return new elt[s]; @@ -40,7 +40,7 @@ namespace test1 { // CHECK-NEXT: [[T2:%.*]] = extractvalue { i32, i1 } [[T0]], 0 // CHECK-NEXT: [[T3:%.*]] = mul i32 [[N]], 100 // CHECK-NEXT: [[T4:%.*]] = select i1 [[T1]], i32 -1, i32 [[T2]] - // CHECK-NEXT: call noalias i8* @_Znaj(i32 [[T4]]) + // CHECK-NEXT: call i8* @_Znaj(i32 [[T4]]) // CHECK: getelementptr inbounds {{.*}}, i32 [[T3]] elt *test(short s) { return new elt[s]; @@ -68,7 +68,7 @@ namespace test2 { // CHECK-NEXT: [[T6:%.*]] = or i1 [[T1]], [[T5]] // CHECK-NEXT: [[T7:%.*]] = extractvalue { i32, i1 } [[T4]], 0 // CHECK-NEXT: [[T8:%.*]] = select i1 [[T6]], i32 -1, i32 [[T7]] - // CHECK-NEXT: call noalias i8* @_Znaj(i32 [[T8]]) + // CHECK-NEXT: call i8* @_Znaj(i32 [[T8]]) // CHECK: getelementptr inbounds {{.*}}, i32 [[T3]] elt *test(short s) { return new elt[s]; @@ -87,7 +87,7 @@ namespace test4 { // CHECK: [[N:%.*]] = sext i16 {{%.*}} to i32 // CHECK-NEXT: [[T0:%.*]] = icmp slt i32 [[N]], 0 // CHECK-NEXT: [[T1:%.*]] = select i1 [[T0]], i32 -1, i32 [[N]] - // CHECK-NEXT: call noalias i8* @_Znaj(i32 [[T1]]) + // CHECK-NEXT: call i8* @_Znaj(i32 [[T1]]) // CHECK: getelementptr inbounds {{.*}}, i32 [[N]] elt *test(short s) { return new elt[s]; @@ -106,7 +106,7 @@ namespace test5 { // CHECK: [[N:%.*]] = load i32, i32* // CHECK-NEXT: [[T0:%.*]] = icmp slt i32 [[N]], 0 // CHECK-NEXT: [[T1:%.*]] = select i1 [[T0]], i32 -1, i32 [[N]] - // CHECK-NEXT: call noalias i8* @_Znaj(i32 [[T1]]) + // CHECK-NEXT: call i8* @_Znaj(i32 [[T1]]) // CHECK: getelementptr inbounds {{.*}}, i32 [[N]] elt *test(int s) { return new elt[s]; @@ -128,7 +128,7 @@ namespace test6 { // CHECK-NEXT: [[T1:%.*]] = extractvalue { i32, i1 } [[T0]], 1 // CHECK-NEXT: [[T2:%.*]] = extractvalue { i32, i1 } [[T0]], 0 // CHECK-NEXT: [[T3:%.*]] = select i1 [[T1]], i32 -1, i32 [[T2]] - // CHECK-NEXT: call noalias i8* @_Znaj(i32 [[T3]]) + // CHECK-NEXT: call i8* @_Znaj(i32 [[T3]]) // CHECK: getelementptr inbounds {{.*}}, i32 [[N]] elt *test(unsigned short s) { return new elt[s]; @@ -151,7 +151,7 @@ namespace test7 { // CHECK-NEXT: [[T2:%.*]] = extractvalue { i32, i1 } [[T0]], 0 // CHECK-NEXT: [[T3:%.*]] = mul i32 [[N]], 100 // CHECK-NEXT: [[T4:%.*]] = select i1 [[T1]], i32 -1, i32 [[T2]] - // CHECK-NEXT: call noalias i8* @_Znaj(i32 [[T4]]) + // CHECK-NEXT: call i8* @_Znaj(i32 [[T4]]) // CHECK: getelementptr inbounds {{.*}}, i32 [[T3]] elt *test(unsigned short s) { return new elt[s]; @@ -176,7 +176,7 @@ namespace test8 { // CHECK-NEXT: [[T4:%.*]] = or i1 [[T0]], [[T3]] // CHECK-NEXT: [[T5:%.*]] = extractvalue { i32, i1 } [[T2]], 0 // CHECK-NEXT: [[T6:%.*]] = select i1 [[T4]], i32 -1, i32 [[T5]] - // CHECK-NEXT: call noalias i8* @_Znaj(i32 [[T6]]) + // CHECK-NEXT: call i8* @_Znaj(i32 [[T6]]) // CHECK: getelementptr inbounds {{.*}}, i32 [[T1]] elt *test(long long s) { return new elt[s]; @@ -201,7 +201,7 @@ namespace test9 { // CHECK-NEXT: [[T4:%.*]] = or i1 [[T0]], [[T3]] // CHECK-NEXT: [[T5:%.*]] = extractvalue { i32, i1 } [[T2]], 0 // CHECK-NEXT: [[T6:%.*]] = select i1 [[T4]], i32 -1, i32 [[T5]] - // CHECK-NEXT: call noalias i8* @_Znaj(i32 [[T6]]) + // CHECK-NEXT: call i8* @_Znaj(i32 [[T6]]) // CHECK: getelementptr inbounds {{.*}}, i32 [[T1]] elt *test(unsigned long long s) { return new elt[s]; diff --git a/test/CodeGenCXX/new.cpp b/test/CodeGenCXX/new.cpp index 6d6f70138616..ae2ec1505c5d 100644 --- a/test/CodeGenCXX/new.cpp +++ b/test/CodeGenCXX/new.cpp @@ -127,15 +127,15 @@ struct B { int a; }; struct Bmemptr { int Bmemptr::* memptr; int a; }; void t11(int n) { - // CHECK: call noalias i8* @_Znwm + // CHECK: call i8* @_Znwm // CHECK: call void @llvm.memset.p0i8.i64( B* b = new B(); - // CHECK: call noalias i8* @_Znam + // CHECK: call i8* @_Znam // CHECK: {{call void.*llvm.memset.p0i8.i64.*i8 0, i64 %}} B *b2 = new B[n](); - // CHECK: call noalias i8* @_Znam + // CHECK: call i8* @_Znam // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64 // CHECK: br Bmemptr *b_memptr = new Bmemptr[n](); @@ -148,11 +148,11 @@ struct Empty { }; // We don't need to initialize an empty class. // CHECK-LABEL: define void @_Z3t12v void t12() { - // CHECK: call noalias i8* @_Znam + // CHECK: call i8* @_Znam // CHECK-NOT: br (void)new Empty[10]; - // CHECK: call noalias i8* @_Znam + // CHECK: call i8* @_Znam // CHECK-NOT: br (void)new Empty[10](); @@ -162,11 +162,11 @@ void t12() { // Zero-initialization // CHECK-LABEL: define void @_Z3t13i void t13(int n) { - // CHECK: call noalias i8* @_Znwm + // CHECK: call i8* @_Znwm // CHECK: store i32 0, i32* (void)new int(); - // CHECK: call noalias i8* @_Znam + // CHECK: call i8* @_Znam // CHECK: {{call void.*llvm.memset.p0i8.i64.*i8 0, i64 %}} (void)new int[n](); @@ -186,7 +186,7 @@ void f() { // CHECK: call void @_ZN5AllocD1Ev( // CHECK: call void @_ZN5AllocdaEPv(i8* delete[] new Alloc[10][20]; - // CHECK: call noalias i8* @_Znwm + // CHECK: call i8* @_Znwm // CHECK: call void @_ZdlPv(i8* delete new bool; // CHECK: ret void @@ -274,7 +274,7 @@ namespace PR10197 { // CHECK-LABEL: define weak_odr void @_ZN7PR101971fIiEEvv() template<typename T> void f() { - // CHECK: [[CALL:%.*]] = call noalias i8* @_Znwm + // CHECK: [[CALL:%.*]] = call i8* @_Znwm // CHECK-NEXT: [[CASTED:%.*]] = bitcast i8* [[CALL]] to new T; // CHECK-NEXT: ret void @@ -296,7 +296,7 @@ namespace PR11757 { struct X { X(); X(const X&); }; X* a(X* x) { return new X(X()); } // CHECK: define {{.*}} @_ZN7PR117571aEPNS_1XE - // CHECK: [[CALL:%.*]] = call noalias i8* @_Znwm + // CHECK: [[CALL:%.*]] = call i8* @_Znwm // CHECK-NEXT: [[CASTED:%.*]] = bitcast i8* [[CALL]] to // CHECK-NEXT: call void @_ZN7PR117571XC1Ev({{.*}}* [[CASTED]]) // CHECK-NEXT: ret {{.*}} [[CASTED]] @@ -306,7 +306,7 @@ namespace PR13380 { struct A { A() {} }; struct B : public A { int x; }; // CHECK-LABEL: define i8* @_ZN7PR133801fEv - // CHECK: call noalias i8* @_Znam( + // CHECK: call i8* @_Znam( // CHECK: call void @llvm.memset.p0i8 // CHECK-NEXT: call void @_ZN7PR133801BC1Ev void* f() { return new B[2](); } @@ -320,12 +320,12 @@ namespace N3664 { // CHECK-LABEL: define void @_ZN5N36641fEv void f() { - // CHECK: call noalias i8* @_Znwm(i64 4) [[ATTR_BUILTIN_NEW:#[^ ]*]] + // CHECK: call i8* @_Znwm(i64 4) [[ATTR_BUILTIN_NEW:#[^ ]*]] int *p = new int; // expected-note {{allocated with 'new' here}} // CHECK: call void @_ZdlPv({{.*}}) [[ATTR_BUILTIN_DELETE:#[^ ]*]] delete p; - // CHECK: call noalias i8* @_Znam(i64 12) [[ATTR_BUILTIN_NEW]] + // CHECK: call i8* @_Znam(i64 12) [[ATTR_BUILTIN_NEW]] int *q = new int[3]; // CHECK: call void @_ZdaPv({{.*}}) [[ATTR_BUILTIN_DELETE]] delete[] p; // expected-warning {{'delete[]' applied to a pointer that was allocated with 'new'; did you mean 'delete'?}} @@ -337,19 +337,18 @@ namespace N3664 { (void) new (mpt) int; } - // FIXME: Can we mark this noalias? - // CHECK: declare i8* @_ZnamRKSt9nothrow_t(i64, {{.*}}) [[ATTR_NOBUILTIN_NOUNWIND]] + // CHECK: declare noalias i8* @_ZnamRKSt9nothrow_t(i64, {{.*}}) [[ATTR_NOBUILTIN_NOUNWIND]] // CHECK-LABEL: define void @_ZN5N36641gEv void g() { // It's OK for there to be attributes here, so long as we don't have a // 'builtin' attribute. - // CHECK: call noalias i8* @_Znwm(i64 4){{$}} + // CHECK: call i8* @_Znwm(i64 4){{$}} int *p = (int*)operator new(4); // CHECK: call void @_ZdlPv({{.*}}) [[ATTR_NOUNWIND:#[^ ]*]] operator delete(p); - // CHECK: call noalias i8* @_Znam(i64 12){{$}} + // CHECK: call i8* @_Znam(i64 12){{$}} int *q = (int*)operator new[](12); // CHECK: call void @_ZdaPv({{.*}}) [[ATTR_NOUNWIND]] operator delete [](p); @@ -362,7 +361,7 @@ namespace N3664 { namespace builtins { // CHECK-LABEL: define void @_ZN8builtins1fEv void f() { - // CHECK: call noalias i8* @_Znwm(i64 4) [[ATTR_BUILTIN_NEW]] + // CHECK: call i8* @_Znwm(i64 4) [[ATTR_BUILTIN_NEW]] // CHECK: call void @_ZdlPv({{.*}}) [[ATTR_BUILTIN_DELETE]] __builtin_operator_delete(__builtin_operator_new(4)); } diff --git a/test/CodeGenCXX/operator-new.cpp b/test/CodeGenCXX/operator-new.cpp index db56cda6cdd1..dc1c36d8eadb 100644 --- a/test/CodeGenCXX/operator-new.cpp +++ b/test/CodeGenCXX/operator-new.cpp @@ -16,7 +16,6 @@ void f1() { new teste(); } - // rdar://5739832 - operator new should check for overflow in multiply. void *f2(long N) { return new int[N]; @@ -25,5 +24,8 @@ void *f2(long N) { // SANE-NEXT: [[OVER:%.*]] = extractvalue {{.*}} [[UWO]], 1 // SANE-NEXT: [[SUM:%.*]] = extractvalue {{.*}} [[UWO]], 0 // SANE-NEXT: [[RESULT:%.*]] = select i1 [[OVER]], i32 -1, i32 [[SUM]] -// SANE-NEXT: call noalias i8* @_Znaj(i32 [[RESULT]]) +// SANE-NEXT: call i8* @_Znaj(i32 [[RESULT]]) } + +// SANE: declare noalias i8* @_Znaj( +// SANENOT: declare i8* @_Znaj( diff --git a/test/CodeGenCXX/optnone-and-attributes.cpp b/test/CodeGenCXX/optnone-and-attributes.cpp index 56173b5a3601..870d5e9496f0 100644 --- a/test/CodeGenCXX/optnone-and-attributes.cpp +++ b/test/CodeGenCXX/optnone-and-attributes.cpp @@ -79,4 +79,4 @@ int exported_optnone_func(int a) { // CHECK: attributes [[NORETURN]] = { noinline noreturn {{.*}} optnone // CHECK: attributes [[DLLIMPORT]] = -// CHECK-SAME-NOT: optnone +// CHECK-NOT: optnone diff --git a/test/CodeGenCXX/optnone-class-members.cpp b/test/CodeGenCXX/optnone-class-members.cpp index 147b82196766..751f3dd2bf08 100644 --- a/test/CodeGenCXX/optnone-class-members.cpp +++ b/test/CodeGenCXX/optnone-class-members.cpp @@ -159,6 +159,6 @@ int bar() { // CHECK: attributes [[NORMAL]] = -// CHECK-SAME-NOT: noinline -// CHECK-SAME-NOT: optnone +// CHECK-NOT: noinline +// CHECK-NOT: optnone // CHECK: attributes [[OPTNONE]] = {{.*}} noinline {{.*}} optnone diff --git a/test/CodeGenCXX/optnone-def-decl.cpp b/test/CodeGenCXX/optnone-def-decl.cpp index cb3a67793647..0240189c5089 100644 --- a/test/CodeGenCXX/optnone-def-decl.cpp +++ b/test/CodeGenCXX/optnone-def-decl.cpp @@ -91,5 +91,5 @@ int user_of_forceinline_optnone_function() { // CHECK: attributes [[OPTNONE]] = { noinline nounwind optnone {{.*}} } // CHECK: attributes [[NORMAL]] = -// CHECK-SAME-NOT: noinline -// CHECK-SAME-NOT: optnone +// CHECK-NOT: noinline +// CHECK-NOT: optnone diff --git a/test/CodeGenCXX/optnone-templates.cpp b/test/CodeGenCXX/optnone-templates.cpp index 45a72b3b1766..9f97d832c1e2 100644 --- a/test/CodeGenCXX/optnone-templates.cpp +++ b/test/CodeGenCXX/optnone-templates.cpp @@ -100,5 +100,5 @@ void container3() // CHECK: attributes [[NORMAL]] = -// CHECK-SAME-NOT: optnone +// CHECK-NOT: optnone // CHECK: attributes [[OPTNONE]] = {{.*}} optnone diff --git a/test/CodeGenCXX/pass-object-size.cpp b/test/CodeGenCXX/pass-object-size.cpp index 2c7f9742a8e6..7fd8b599aaa3 100644 --- a/test/CodeGenCXX/pass-object-size.cpp +++ b/test/CodeGenCXX/pass-object-size.cpp @@ -43,3 +43,40 @@ void Test() { (&OvlFoo)(nullptr); } } + +namespace delegate { + struct A { + A(void *const p __attribute__((pass_object_size(0)))); + }; + A::A(void *const p __attribute__((pass_object_size(0)))) {} + // Ensure that we forward the size through a delegating constructor call. + // CHECK: define void @_ZN8delegate1AC1EPvU17pass_object_size0({{[^,]*}}, i8*{{[^,]*}}, i64{{[^,]*}}) + // CHECK: call void @_ZN8delegate1AC2EPvU17pass_object_size0({{[^,]*}}, i8*{{[^,]*}}, i64{{[^,]*}}) +} + +namespace variadic { +// We had an issue where variadic member/operator calls with pass_object_size +// would cause crashes. + +struct AsCtor { + AsCtor(const char *const c __attribute__((pass_object_size(0))), double a, + ...) {} +}; + +struct AsMember { + void bar(const char *const c __attribute__((pass_object_size(0))), double a, + ...) {} + void operator()(const char *const c __attribute__((pass_object_size(0))), + double a, ...) {} +}; + +// CHECK-LABEL: define void @_ZN8variadic4testEv() +void test() { + // CHECK-RE: call{{[^@]+}}@_ZN8variadic6AsCtorC1EPKcU17pass_object_size0dz + AsCtor("a", 1.0); + // CHECK-RE: call{{[^@]+}}@_ZN8variadic8AsMember3barEPKcU17pass_object_size0dz + AsMember{}.bar("a", 1.0); + // CHECK-RE: call{{[^@]+}}@_ZN8variadic8AsMemberclEPKcU17pass_object_size0dz + AsMember{}("a", 1.0); +} +} diff --git a/test/CodeGenCXX/pr20719.cpp b/test/CodeGenCXX/pr20719.cpp index 208d11135847..1c3b21b0b84e 100644 --- a/test/CodeGenCXX/pr20719.cpp +++ b/test/CodeGenCXX/pr20719.cpp @@ -2,8 +2,8 @@ // Make sure that we emit H's constructor twice: once with the first lambda // inside of 'lep' and again with the second lambda inside of 'lep'. -// CHECK-DAG: @"\01??0?$H@V<lambda_1>@??$lep@X@@YAXXZ@@@QAE@XZ" -// CHECK-DAG: @"\01??0?$H@V<lambda_2>@??$lep@X@@YAXXZ@@@QAE@XZ" +// CHECK-DAG: @"\01??0?$H@V<lambda_1>@?0???$lep@X@@YAXXZ@@@QAE@XZ" +// CHECK-DAG: @"\01??0?$H@V<lambda_2>@?0???$lep@X@@YAXXZ@@@QAE@XZ" template <typename> struct H { diff --git a/test/CodeGenCXX/pr27030.cpp b/test/CodeGenCXX/pr27030.cpp new file mode 100644 index 000000000000..5c24051d7a2b --- /dev/null +++ b/test/CodeGenCXX/pr27030.cpp @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -emit-llvm -triple=i386-pc-win32 %s -o - | FileCheck %s +struct A {}; +struct B : A {}; +extern "C" { +extern int B::*a; +void test1() { (int A::*)(a); } +} +// CHECK-LABEL: define void @test1( +// CHECK: %[[load:.*]] = load i32, i32* @a +// CHECK: %[[memptr_cmp:.*]] = icmp ne i32 %[[load]], -1 +// CHECK: br i1 %[[memptr_cmp]] + +// CHECK: %[[adj:.*]] = sub nsw i32 %[[load]], 0 +// CHECK: %[[nv_adj:.*]] = select i1 true, i32 %[[adj]], i32 0 + +// CHECK: %[[memptr_converted:.*]] = phi i32 [ -1, {{.*}} ], [ %[[nv_adj]], {{.*}} ] diff --git a/test/CodeGenCXX/pr28360.cpp b/test/CodeGenCXX/pr28360.cpp new file mode 100644 index 000000000000..5d7e1ae0c1fd --- /dev/null +++ b/test/CodeGenCXX/pr28360.cpp @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 %s -emit-llvm -o - -triple i686-pc-win32 | FileCheck %s +struct A { + void Foo(); + void Foo(int); +}; + +using MpTy = void (A::*)(); + +void Bar(const MpTy &); + +void Baz() { Bar(&A::Foo); } + +// CHECK-LABEL: define void @"\01?Baz@@YAXXZ"( +// CHECK: %[[ref_tmp:.*]] = alloca i8*, align 4 +// CHECK: store i8* bitcast (void (%struct.A*)* @"\01?Foo@A@@QAEXXZ" to i8*), i8** %[[ref_tmp]], align 4 +// CHECK: call void @"\01?Bar@@YAXABQ8A@@AEXXZ@Z"(i8** dereferenceable(4) %[[ref_tmp]]) diff --git a/test/CodeGenCXX/pragma-loop.cpp b/test/CodeGenCXX/pragma-loop.cpp index b85e0b49b9df..e337913646df 100644 --- a/test/CodeGenCXX/pragma-loop.cpp +++ b/test/CodeGenCXX/pragma-loop.cpp @@ -9,6 +9,7 @@ void while_test(int *List, int Length) { #pragma clang loop interleave_count(4) #pragma clang loop vectorize_width(4) #pragma clang loop unroll(full) +#pragma clang loop distribute(enable) while (i < Length) { // CHECK: br label {{.*}}, !llvm.loop ![[LOOP_1:.*]] List[i] = i * 2; @@ -20,7 +21,7 @@ void while_test(int *List, int Length) { void do_test(int *List, int Length) { int i = 0; -#pragma clang loop vectorize_width(8) interleave_count(4) unroll(disable) +#pragma clang loop vectorize_width(8) interleave_count(4) unroll(disable) distribute(disable) do { // CHECK: br i1 {{.*}}, label {{.*}}, label {{.*}}, !llvm.loop ![[LOOP_2:.*]] List[i] = i * 2; @@ -55,7 +56,7 @@ void for_range_test() { // Verify disable pragma clang loop directive generates correct metadata void disable_test(int *List, int Length) { -#pragma clang loop vectorize(disable) unroll(disable) +#pragma clang loop vectorize(disable) unroll(disable) distribute(disable) for (int i = 0; i < Length; i++) { // CHECK: br label {{.*}}, !llvm.loop ![[LOOP_5:.*]] List[i] = i * 2; @@ -157,20 +158,22 @@ void template_test(double *List, int Length) { for_template_constant_expression_test<double, 2, 4, 8>(List, Length); } -// CHECK: ![[LOOP_1]] = distinct !{![[LOOP_1]], ![[WIDTH_4:.*]], ![[INTERLEAVE_4:.*]], ![[INTENABLE_1:.*]], ![[UNROLL_FULL:.*]]} +// CHECK: ![[LOOP_1]] = distinct !{![[LOOP_1]], ![[WIDTH_4:.*]], ![[INTERLEAVE_4:.*]], ![[INTENABLE_1:.*]], ![[UNROLL_FULL:.*]], ![[DISTRIBUTE_ENABLE:.*]]} // CHECK: ![[WIDTH_4]] = !{!"llvm.loop.vectorize.width", i32 4} // CHECK: ![[INTERLEAVE_4]] = !{!"llvm.loop.interleave.count", i32 4} // CHECK: ![[INTENABLE_1]] = !{!"llvm.loop.vectorize.enable", i1 true} // CHECK: ![[UNROLL_FULL]] = !{!"llvm.loop.unroll.full"} -// CHECK: ![[LOOP_2]] = distinct !{![[LOOP_2:.*]], ![[WIDTH_8:.*]], ![[INTERLEAVE_4:.*]], ![[UNROLL_DISABLE:.*]]} +// CHECK: ![[DISTRIBUTE_ENABLE]] = !{!"llvm.loop.distribute.enable", i1 true} +// CHECK: ![[LOOP_2]] = distinct !{![[LOOP_2:.*]], ![[WIDTH_8:.*]], ![[INTERLEAVE_4:.*]], ![[UNROLL_DISABLE:.*]], ![[DISTRIBUTE_DISABLE:.*]]} // CHECK: ![[WIDTH_8]] = !{!"llvm.loop.vectorize.width", i32 8} // CHECK: ![[UNROLL_DISABLE]] = !{!"llvm.loop.unroll.disable"} +// CHECK: ![[DISTRIBUTE_DISABLE]] = !{!"llvm.loop.distribute.enable", i1 false} // CHECK: ![[LOOP_3]] = distinct !{![[LOOP_3]], ![[INTERLEAVE_4:.*]], ![[UNROLL_8:.*]], ![[INTENABLE_1:.*]]} // CHECK: ![[UNROLL_8]] = !{!"llvm.loop.unroll.count", i32 8} // CHECK: ![[LOOP_4]] = distinct !{![[LOOP_4]], ![[WIDTH_2:.*]], ![[INTERLEAVE_2:.*]]} // CHECK: ![[WIDTH_2]] = !{!"llvm.loop.vectorize.width", i32 2} // CHECK: ![[INTERLEAVE_2]] = !{!"llvm.loop.interleave.count", i32 2} -// CHECK: ![[LOOP_5]] = distinct !{![[LOOP_5]], ![[WIDTH_1:.*]], ![[UNROLL_DISABLE:.*]]} +// CHECK: ![[LOOP_5]] = distinct !{![[LOOP_5]], ![[WIDTH_1:.*]], ![[UNROLL_DISABLE:.*]], ![[DISTRIBUTE_DISABLE:.*]]} // CHECK: ![[WIDTH_1]] = !{!"llvm.loop.vectorize.width", i32 1} // CHECK: ![[LOOP_6]] = distinct !{![[LOOP_6]], ![[WIDTH_2:.*]], ![[INTERLEAVE_2:.*]], ![[UNROLL_8:.*]]} // CHECK: ![[LOOP_7]] = distinct !{![[LOOP_7]], ![[WIDTH_5:.*]]} diff --git a/test/CodeGenCXX/rtti-fundamental.cpp b/test/CodeGenCXX/rtti-fundamental.cpp index e70c3aa36597..a0ad80d7c98a 100644 --- a/test/CodeGenCXX/rtti-fundamental.cpp +++ b/test/CodeGenCXX/rtti-fundamental.cpp @@ -89,6 +89,16 @@ namespace __cxxabiv1 { // CHECK: @_ZTIPy = constant // CHECK: @_ZTIPKy = constant +// __int128 +// CHECK: @_ZTIn = constant +// CHECK: @_ZTIPn = constant +// CHECK: @_ZTIPKn = constant + +// unsigned __int128 +// CHECK: @_ZTIo = constant +// CHECK: @_ZTIPo = constant +// CHECK: @_ZTIPKo = constant + // half // CHECK: @_ZTIDh = constant // CHECK: @_ZTIPDh = constant diff --git a/test/CodeGenCXX/sections.cpp b/test/CodeGenCXX/sections.cpp index bec2e2d3d706..c33871a97f56 100644 --- a/test/CodeGenCXX/sections.cpp +++ b/test/CodeGenCXX/sections.cpp @@ -31,6 +31,31 @@ int TEST1; #pragma bss_seg(pop) int TEST2; + +// Check "save-restore" of pragma stacks. +struct Outer { + void f() { + #pragma bss_seg(push, ".bss3") + #pragma code_seg(push, ".my_code1") + #pragma const_seg(push, ".my_const1") + #pragma data_seg(push, ".data3") + struct Inner { + void g() { + #pragma bss_seg(push, ".bss4") + #pragma code_seg(push, ".my_code2") + #pragma const_seg(push, ".my_const2") + #pragma data_seg(push, ".data4") + } + }; + } +}; + +void h2(void) {} // should be in ".my_code" +int TEST3; // should be in ".bss1" +int d2 = 1; // should be in ".data" +extern const int b2; // should be in ".my_const" +const int b2 = 1; + #pragma section("read_flag_section", read) // Even though they are not declared const, these become constant since they are // in a read-only section. @@ -63,6 +88,9 @@ __declspec(allocate("short_section")) short short_var = 42; //CHECK: @i = global i32 0 //CHECK: @TEST1 = global i32 0 //CHECK: @TEST2 = global i32 0, section ".bss1" +//CHECK: @TEST3 = global i32 0, section ".bss1" +//CHECK: @d2 = global i32 1, section ".data" +//CHECK: @b2 = constant i32 1, section ".my_const" //CHECK: @unreferenced = constant i32 0, section "read_flag_section" //CHECK: @referenced = constant i32 42, section "read_flag_section" //CHECK: @implicitly_read_write = global i32 42, section "no_section_attributes" @@ -70,3 +98,4 @@ __declspec(allocate("short_section")) short short_var = 42; //CHECK: @short_var = global i16 42, section "short_section" //CHECK: define void @g() //CHECK: define void @h() {{.*}} section ".my_code" +//CHECK: define void @h2() {{.*}} section ".my_code" diff --git a/test/CodeGenCXX/skip-vtable-pointer-initialization.cpp b/test/CodeGenCXX/skip-vtable-pointer-initialization.cpp index f6f90986e149..4734c02bc52e 100644 --- a/test/CodeGenCXX/skip-vtable-pointer-initialization.cpp +++ b/test/CodeGenCXX/skip-vtable-pointer-initialization.cpp @@ -27,7 +27,7 @@ struct A { }; // CHECK-LABEL: define void @_ZN5Test21AD2Ev -// CHECK: store i32 (...)** bitcast (i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTVN5Test21AE, i64 0, i64 2) to i32 (...)**), i32 (...)*** +// CHECK: store i32 (...)** bitcast (i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTVN5Test21AE, i32 0, i32 2) to i32 (...)**), i32 (...)*** A::~A() { f(); } @@ -50,7 +50,7 @@ struct A { }; // CHECK-LABEL: define void @_ZN5Test31AD2Ev -// CHECK-NOT: store i32 (...)** bitcast (i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTVN5Test31AE, i64 0, i64 2) to i32 (...)**), i32 (...)*** +// CHECK-NOT: store i32 (...)** bitcast (i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTVN5Test31AE, i32 0, i32 2) to i32 (...)**), i32 (...)*** A::~A() { } @@ -76,7 +76,7 @@ struct A { }; // CHECK-LABEL: define void @_ZN5Test41AD2Ev -// CHECK: store i32 (...)** bitcast (i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTVN5Test41AE, i64 0, i64 2) to i32 (...)**), i32 (...)*** +// CHECK: store i32 (...)** bitcast (i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTVN5Test41AE, i32 0, i32 2) to i32 (...)**), i32 (...)*** A::~A() { } @@ -100,7 +100,7 @@ struct A { }; // CHECK-LABEL: define void @_ZN5Test51AD2Ev -// CHECK: store i32 (...)** bitcast (i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTVN5Test51AE, i64 0, i64 2) to i32 (...)**), i32 (...)*** +// CHECK: store i32 (...)** bitcast (i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTVN5Test51AE, i32 0, i32 2) to i32 (...)**), i32 (...)*** A::~A() { } @@ -128,7 +128,7 @@ struct A { }; // CHECK-LABEL: define void @_ZN5Test61AD2Ev -// CHECK: store i32 (...)** bitcast (i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTVN5Test61AE, i64 0, i64 2) to i32 (...)**), i32 (...)*** +// CHECK: store i32 (...)** bitcast (i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTVN5Test61AE, i32 0, i32 2) to i32 (...)**), i32 (...)*** A::~A() { } @@ -154,7 +154,7 @@ struct A { }; // CHECK-LABEL: define void @_ZN5Test71AD2Ev -// CHECK: store i32 (...)** bitcast (i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTVN5Test71AE, i64 0, i64 2) to i32 (...)**), i32 (...)*** +// CHECK: store i32 (...)** bitcast (i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTVN5Test71AE, i32 0, i32 2) to i32 (...)**), i32 (...)*** A::~A() { } @@ -180,7 +180,7 @@ struct A { }; // CHECK-LABEL: define void @_ZN5Test81AD2Ev -// CHECK: store i32 (...)** bitcast (i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTVN5Test81AE, i64 0, i64 2) to i32 (...)**), i32 (...)*** +// CHECK: store i32 (...)** bitcast (i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTVN5Test81AE, i32 0, i32 2) to i32 (...)**), i32 (...)*** A::~A() { } diff --git a/test/CodeGenCXX/stack-reuse.cpp b/test/CodeGenCXX/stack-reuse.cpp index 473a57cda27d..d6340ef2c10b 100644 --- a/test/CodeGenCXX/stack-reuse.cpp +++ b/test/CodeGenCXX/stack-reuse.cpp @@ -1,4 +1,4 @@ -// RUN: %clang -target armv7l-unknown-linux-gnueabihf -S %s -o - -emit-llvm -O1 -disable-llvm-optzns | FileCheck %s +// RUN: %clang_cc1 -triple armv7-unknown-linux-gnueabihf %s -o - -emit-llvm -O1 | FileCheck %s // Stack should be reused when possible, no need to allocate two separate slots // if they have disjoint lifetime. @@ -21,7 +21,7 @@ struct Combiner { S_large a, b; Combiner(S_large); - Combiner f(); + Combiner f(); }; extern S_small foo_small(); diff --git a/test/CodeGenCXX/static-destructor.cpp b/test/CodeGenCXX/static-destructor.cpp new file mode 100644 index 000000000000..0ea84f8da6fa --- /dev/null +++ b/test/CodeGenCXX/static-destructor.cpp @@ -0,0 +1,33 @@ +// RUN: %clang_cc1 %s -triple=x86_64-pc-linux -emit-llvm -o - | FileCheck --check-prefix=X86 %s +// RUN: %clang_cc1 %s -triple=wasm32 -emit-llvm -o - | FileCheck --check-prefix=WASM %s +// RUN: %clang_cc1 %s -triple=armv7-apple-darwin9 -emit-llvm -o - | FileCheck --check-prefix=ARM %s + +// Test that destructors are not passed directly to __cxa_atexit when their +// signatures do not match the type of its first argument. +// e.g. ARM and WebAssembly have destructors that return this instead of void. + + +class Foo { + public: + ~Foo() { + } +}; + +Foo global; + +// X86 destructors have void return, and are registered directly with __cxa_atexit. +// X86: define internal void @__cxx_global_var_init() +// X86: call i32 @__cxa_atexit(void (i8*)* bitcast (void (%class.Foo*)* @_ZN3FooD1Ev to void (i8*)*), i8* getelementptr inbounds (%class.Foo, %class.Foo* @global, i32 0, i32 0), i8* @__dso_handle) + +// ARM destructors return this, but can be registered directly with __cxa_atexit +// because the calling conventions tolerate the mismatch. +// ARM: define internal void @__cxx_global_var_init() +// ARM: call i32 @__cxa_atexit(void (i8*)* bitcast (%class.Foo* (%class.Foo*)* @_ZN3FooD1Ev to void (i8*)*), i8* getelementptr inbounds (%class.Foo, %class.Foo* @global, i32 0, i32 0), i8* @__dso_handle) + +// Wasm destructors return this, and use a wrapper function, which is registered +// with __cxa_atexit. +// WASM: define internal void @__cxx_global_var_init() +// WASM: call i32 @__cxa_atexit(void (i8*)* @__cxx_global_array_dtor, i8* null, i8* @__dso_handle) + +// WASM: define internal void @__cxx_global_array_dtor(i8*) +// WASM: %call = call %class.Foo* @_ZN3FooD1Ev(%class.Foo* @global) diff --git a/test/CodeGenCXX/static-init.cpp b/test/CodeGenCXX/static-init.cpp index 541f6416efd0..bb974948a059 100644 --- a/test/CodeGenCXX/static-init.cpp +++ b/test/CodeGenCXX/static-init.cpp @@ -26,7 +26,7 @@ void f() { } void g() { - // CHECK: call noalias i8* @_Znwm(i64 1) + // CHECK: call i8* @_Znwm(i64 1) // CHECK: call void @_ZN1AC1Ev( static A& a = *new A; } diff --git a/test/CodeGenCXX/strict-vtable-pointers.cpp b/test/CodeGenCXX/strict-vtable-pointers.cpp index ee3919149cab..33f63994d7c0 100644 --- a/test/CodeGenCXX/strict-vtable-pointers.cpp +++ b/test/CodeGenCXX/strict-vtable-pointers.cpp @@ -166,13 +166,13 @@ struct DynamicDerivedMultiple; // CHECK-CTORS: %[[THIS10:.*]] = bitcast %struct.DynamicDerivedMultiple* %[[THIS0]] to i32 (...)*** -// CHECK-CTORS: store {{.*}} @_ZTV22DynamicDerivedMultiple, i64 0, i64 2) {{.*}} %[[THIS10]] +// CHECK-CTORS: store {{.*}} @_ZTV22DynamicDerivedMultiple, i32 0, i32 2) {{.*}} %[[THIS10]] // CHECK-CTORS: %[[THIS11:.*]] = bitcast %struct.DynamicDerivedMultiple* %[[THIS0]] to i8* // CHECK-CTORS: %[[THIS_ADD:.*]] = getelementptr inbounds i8, i8* %[[THIS11]], i64 16 // CHECK-CTORS: %[[THIS12:.*]] = bitcast i8* %[[THIS_ADD]] to i32 (...)*** -// CHECK-CTORS: store {{.*}} @_ZTV22DynamicDerivedMultiple, i64 0, i64 6) {{.*}} %[[THIS12]] +// CHECK-CTORS: store {{.*}} @_ZTV22DynamicDerivedMultiple, i32 0, i32 6) {{.*}} %[[THIS12]] // CHECK-CTORS-LABEL: } struct DynamicFromStatic; diff --git a/test/CodeGenCXX/type-metadata.cpp b/test/CodeGenCXX/type-metadata.cpp new file mode 100644 index 000000000000..076b1fdf1808 --- /dev/null +++ b/test/CodeGenCXX/type-metadata.cpp @@ -0,0 +1,248 @@ +// Tests for the cfi-vcall feature: +// RUN: %clang_cc1 -flto -triple x86_64-unknown-linux -fvisibility hidden -fsanitize=cfi-vcall -fsanitize-trap=cfi-vcall -emit-llvm -o - %s | FileCheck --check-prefix=CFI --check-prefix=CFI-NVT --check-prefix=ITANIUM --check-prefix=TT-ITANIUM --check-prefix=NDIAG %s +// RUN: %clang_cc1 -flto -triple x86_64-unknown-linux -fvisibility hidden -fsanitize=cfi-vcall -emit-llvm -o - %s | FileCheck --check-prefix=CFI --check-prefix=CFI-NVT --check-prefix=ITANIUM --check-prefix=TT-ITANIUM --check-prefix=ITANIUM-DIAG --check-prefix=DIAG --check-prefix=DIAG-ABORT %s +// RUN: %clang_cc1 -flto -triple x86_64-unknown-linux -fvisibility hidden -fsanitize=cfi-vcall -fsanitize-recover=cfi-vcall -emit-llvm -o - %s | FileCheck --check-prefix=CFI --check-prefix=CFI-NVT --check-prefix=ITANIUM --check-prefix=TT-ITANIUM --check-prefix=ITANIUM-DIAG --check-prefix=DIAG --check-prefix=DIAG-RECOVER %s +// RUN: %clang_cc1 -flto -triple x86_64-pc-windows-msvc -fsanitize=cfi-vcall -fsanitize-trap=cfi-vcall -emit-llvm -o - %s | FileCheck --check-prefix=CFI --check-prefix=CFI-NVT --check-prefix=MS --check-prefix=TT-MS --check-prefix=NDIAG %s + +// Tests for the whole-program-vtables feature: +// RUN: %clang_cc1 -flto -triple x86_64-unknown-linux -fvisibility hidden -fwhole-program-vtables -emit-llvm -o - %s | FileCheck --check-prefix=VTABLE-OPT --check-prefix=ITANIUM --check-prefix=TT-ITANIUM %s +// RUN: %clang_cc1 -flto -triple x86_64-pc-windows-msvc -fwhole-program-vtables -emit-llvm -o - %s | FileCheck --check-prefix=VTABLE-OPT --check-prefix=MS --check-prefix=TT-MS %s + +// Tests for cfi + whole-program-vtables: +// RUN: %clang_cc1 -flto -triple x86_64-unknown-linux -fvisibility hidden -fsanitize=cfi-vcall -fsanitize-trap=cfi-vcall -fwhole-program-vtables -emit-llvm -o - %s | FileCheck --check-prefix=CFI --check-prefix=CFI-VT --check-prefix=ITANIUM --check-prefix=TC-ITANIUM %s +// RUN: %clang_cc1 -flto -triple x86_64-pc-windows-msvc -fsanitize=cfi-vcall -fsanitize-trap=cfi-vcall -fwhole-program-vtables -emit-llvm -o - %s | FileCheck --check-prefix=CFI --check-prefix=CFI-VT --check-prefix=MS --check-prefix=TC-MS %s + +// ITANIUM: @_ZTV1A = {{[^!]*}}, !type [[A16:![0-9]+]] +// ITANIUM-DIAG-SAME: !type [[ALL16:![0-9]+]] + +// ITANIUM: @_ZTV1B = {{[^!]*}}, !type [[A32:![0-9]+]] +// ITANIUM-DIAG-SAME: !type [[ALL32:![0-9]+]] +// ITANIUM-SAME: !type [[B32:![0-9]+]] +// ITANIUM-DIAG-SAME: !type [[ALL32]] + +// ITANIUM: @_ZTV1C = {{[^!]*}}, !type [[A32]] +// ITANIUM-DIAG-SAME: !type [[ALL32]] +// ITANIUM-SAME: !type [[C32:![0-9]+]] +// ITANIUM-DIAG-SAME: !type [[ALL32]] + +// DIAG: @[[SRC:.*]] = private unnamed_addr constant [{{.*}} x i8] c"{{.*}}type-metadata.cpp\00", align 1 +// DIAG: @[[TYPE:.*]] = private unnamed_addr constant { i16, i16, [4 x i8] } { i16 -1, i16 0, [4 x i8] c"'A'\00" } +// DIAG: @[[BADTYPESTATIC:.*]] = private unnamed_addr global { i8, { [{{.*}} x i8]*, i32, i32 }, { i16, i16, [4 x i8] }* } { i8 0, { [{{.*}} x i8]*, i32, i32 } { [{{.*}} x i8]* @[[SRC]], i32 123, i32 3 }, { i16, i16, [4 x i8] }* @[[TYPE]] } + +// ITANIUM: @_ZTVN12_GLOBAL__N_11DE = {{[^!]*}}, !type [[A32]] +// ITANIUM-DIAG-SAME: !type [[ALL32]] +// ITANIUM-SAME: !type [[B32]] +// ITANIUM-DIAG-SAME: !type [[ALL32]] +// ITANIUM-SAME: !type [[C88:![0-9]+]] +// ITANIUM-DIAG-SAME: !type [[ALL88:![0-9]+]] +// ITANIUM-SAME: !type [[D32:![0-9]+]] +// ITANIUM-DIAG-SAME: !type [[ALL32]] + +// ITANIUM: @_ZTCN12_GLOBAL__N_11DE0_1B = {{[^!]*}}, !type [[A32]] +// ITANIUM-DIAG-SAME: !type [[ALL32]] +// ITANIUM-SAME: !type [[B32]] +// ITANIUM-DIAG-SAME: !type [[ALL32]] + +// ITANIUM: @_ZTCN12_GLOBAL__N_11DE8_1C = {{[^!]*}}, !type [[A64:![0-9]+]] +// ITANIUM-DIAG-SAME: !type [[ALL64:![0-9]+]] +// ITANIUM-SAME: !type [[C32]] +// ITANIUM-DIAG-SAME: !type [[ALL32]] + +// ITANIUM: @_ZTVZ3foovE2FA = {{[^!]*}}, !type [[A16]] +// ITANIUM-DIAG-SAME: !type [[ALL16]] +// ITANIUM-SAME: !type [[FA16:![0-9]+]] +// ITANIUM-DIAG-SAME: !type [[ALL16]] + +// MS: comdat($"\01??_7A@@6B@"), !type [[A8:![0-9]+]] +// MS: comdat($"\01??_7B@@6B0@@"), !type [[B8:![0-9]+]] +// MS: comdat($"\01??_7B@@6BA@@@"), !type [[A8]] +// MS: comdat($"\01??_7C@@6B@"), !type [[A8]] +// MS: comdat($"\01??_7D@?A@@6BB@@@"), !type [[B8]], !type [[D8:![0-9]+]] +// MS: comdat($"\01??_7D@?A@@6BA@@@"), !type [[A8]] +// MS: comdat($"\01??_7FA@?1??foo@@YAXXZ@6B@"), !type [[A8]], !type [[FA8:![0-9]+]] + +struct A { + A(); + virtual void f(); +}; + +struct B : virtual A { + B(); + virtual void g(); + virtual void h(); +}; + +struct C : virtual A { + C(); +}; + +namespace { + +struct D : B, C { + D(); + virtual void f(); + virtual void h(); +}; + +} + +A::A() {} +B::B() {} +C::C() {} +D::D() {} + +void A::f() { +} + +void B::g() { +} + +void D::f() { +} + +void D::h() { +} + +// ITANIUM: define hidden void @_Z2afP1A +// MS: define void @"\01?af@@YAXPEAUA@@@Z" +void af(A *a) { + // TT-ITANIUM: [[P:%[^ ]*]] = call i1 @llvm.type.test(i8* [[VT:%[^ ]*]], metadata !"_ZTS1A") + // TT-MS: [[P:%[^ ]*]] = call i1 @llvm.type.test(i8* [[VT:%[^ ]*]], metadata !"?AUA@@") + // TC-ITANIUM: [[PAIR:%[^ ]*]] = call { i8*, i1 } @llvm.type.checked.load(i8* {{%[^ ]*}}, i32 0, metadata !"_ZTS1A") + // TC-MS: [[PAIR:%[^ ]*]] = call { i8*, i1 } @llvm.type.checked.load(i8* {{%[^ ]*}}, i32 0, metadata !"?AUA@@") + // CFI-VT: [[P:%[^ ]*]] = extractvalue { i8*, i1 } [[PAIR]], 1 + // DIAG-NEXT: [[VTVALID0:%[^ ]*]] = call i1 @llvm.type.test(i8* [[VT]], metadata !"all-vtables") + // VTABLE-OPT: call void @llvm.assume(i1 [[P]]) + // CFI-NEXT: br i1 [[P]], label %[[CONTBB:[^ ,]*]], label %[[TRAPBB:[^ ,]*]] + // CFI-NEXT: {{^$}} + + // CFI: [[TRAPBB]] + // NDIAG-NEXT: call void @llvm.trap() + // NDIAG-NEXT: unreachable + // DIAG-NEXT: [[VTINT:%[^ ]*]] = ptrtoint i8* [[VT]] to i64 + // DIAG-NEXT: [[VTVALID:%[^ ]*]] = zext i1 [[VTVALID0]] to i64 + // DIAG-ABORT-NEXT: call void @__ubsan_handle_cfi_check_fail_abort(i8* getelementptr inbounds ({{.*}} @[[BADTYPESTATIC]], i32 0, i32 0), i64 [[VTINT]], i64 [[VTVALID]]) + // DIAG-ABORT-NEXT: unreachable + // DIAG-RECOVER-NEXT: call void @__ubsan_handle_cfi_check_fail(i8* getelementptr inbounds ({{.*}} @[[BADTYPESTATIC]], i32 0, i32 0), i64 [[VTINT]], i64 [[VTVALID]]) + // DIAG-RECOVER-NEXT: br label %[[CONTBB]] + + // CFI: [[CONTBB]] + // CFI-NVT: [[PTR:%[^ ]*]] = load + // CFI-VT: [[PTRI8:%[^ ]*]] = extractvalue { i8*, i1 } [[PAIR]], 0 + // CFI-VT: [[PTR:%[^ ]*]] = bitcast i8* [[PTRI8]] to + // CFI: call void [[PTR]] +#line 123 + a->f(); +} + +// ITANIUM: define internal void @_Z3df1PN12_GLOBAL__N_11DE +// MS: define internal void @"\01?df1@@YAXPEAUD@?A@@@Z" +void df1(D *d) { + // TT-ITANIUM: {{%[^ ]*}} = call i1 @llvm.type.test(i8* {{%[^ ]*}}, metadata ![[DTYPE:[0-9]+]]) + // TT-MS: {{%[^ ]*}} = call i1 @llvm.type.test(i8* {{%[^ ]*}}, metadata !"?AUA@@") + // TC-ITANIUM: {{%[^ ]*}} = call { i8*, i1 } @llvm.type.checked.load(i8* {{%[^ ]*}}, i32 0, metadata ![[DTYPE:[0-9]+]]) + // TC-MS: {{%[^ ]*}} = call { i8*, i1 } @llvm.type.checked.load(i8* {{%[^ ]*}}, i32 0, metadata !"?AUA@@") + d->f(); +} + +// ITANIUM: define internal void @_Z3dg1PN12_GLOBAL__N_11DE +// MS: define internal void @"\01?dg1@@YAXPEAUD@?A@@@Z" +void dg1(D *d) { + // TT-ITANIUM: {{%[^ ]*}} = call i1 @llvm.type.test(i8* {{%[^ ]*}}, metadata !"_ZTS1B") + // TT-MS: {{%[^ ]*}} = call i1 @llvm.type.test(i8* {{%[^ ]*}}, metadata !"?AUB@@") + // TC-ITANIUM: {{%[^ ]*}} = call { i8*, i1 } @llvm.type.checked.load(i8* {{%[^ ]*}}, i32 8, metadata !"_ZTS1B") + // TC-MS: {{%[^ ]*}} = call { i8*, i1 } @llvm.type.checked.load(i8* {{%[^ ]*}}, i32 0, metadata !"?AUB@@") + d->g(); +} + +// ITANIUM: define internal void @_Z3dh1PN12_GLOBAL__N_11DE +// MS: define internal void @"\01?dh1@@YAXPEAUD@?A@@@Z" +void dh1(D *d) { + // TT-ITANIUM: {{%[^ ]*}} = call i1 @llvm.type.test(i8* {{%[^ ]*}}, metadata ![[DTYPE]]) + // TT-MS: {{%[^ ]*}} = call i1 @llvm.type.test(i8* {{%[^ ]*}}, metadata ![[DTYPE:[0-9]+]]) + // TC-ITANIUM: {{%[^ ]*}} = call { i8*, i1 } @llvm.type.checked.load(i8* {{%[^ ]*}}, i32 16, metadata ![[DTYPE]]) + // TC-MS: {{%[^ ]*}} = call { i8*, i1 } @llvm.type.checked.load(i8* {{%[^ ]*}}, i32 8, metadata ![[DTYPE:[0-9]+]]) + d->h(); +} + +// ITANIUM: define internal void @_Z3df2PN12_GLOBAL__N_11DE +// MS: define internal void @"\01?df2@@YAXPEAUD@?A@@@Z" +__attribute__((no_sanitize("cfi"))) +void df2(D *d) { + // CFI-NVT-NOT: call i1 @llvm.type.test + // CFI-VT: [[P:%[^ ]*]] = call i1 @llvm.type.test + // CFI-VT: call void @llvm.assume(i1 [[P]]) + d->f(); +} + +// ITANIUM: define internal void @_Z3df3PN12_GLOBAL__N_11DE +// MS: define internal void @"\01?df3@@YAXPEAUD@?A@@@Z" +__attribute__((no_sanitize("address"))) __attribute__((no_sanitize("cfi-vcall"))) +void df3(D *d) { + // CFI-NVT-NOT: call i1 @llvm.type.test + // CFI-VT: [[P:%[^ ]*]] = call i1 @llvm.type.test + // CFI-VT: call void @llvm.assume(i1 [[P]]) + d->f(); +} + +D d; + +void foo() { + df1(&d); + dg1(&d); + dh1(&d); + df2(&d); + df3(&d); + + struct FA : A { + void f() {} + } fa; + af(&fa); +} + +namespace test2 { + +struct A { + virtual void m_fn1(); +}; +struct B { + virtual void m_fn2(); +}; +struct C : B, A {}; +struct D : C { + void m_fn1(); +}; + +// ITANIUM: define hidden void @_ZN5test21fEPNS_1DE +// MS: define void @"\01?f@test2@@YAXPEAUD@1@@Z" +void f(D *d) { + // TT-ITANIUM: {{%[^ ]*}} = call i1 @llvm.type.test(i8* {{%[^ ]*}}, metadata !"_ZTSN5test21DE") + // TT-MS: {{%[^ ]*}} = call i1 @llvm.type.test(i8* {{%[^ ]*}}, metadata !"?AUA@test2@@") + // TC-ITANIUM: {{%[^ ]*}} = call { i8*, i1 } @llvm.type.checked.load(i8* {{%[^ ]*}}, i32 8, metadata !"_ZTSN5test21DE") + // TC-MS: {{%[^ ]*}} = call { i8*, i1 } @llvm.type.checked.load(i8* {{%[^ ]*}}, i32 0, metadata !"?AUA@test2@@") + d->m_fn1(); +} + +} + +// ITANIUM: [[A16]] = !{i64 16, !"_ZTS1A"} +// ITANIUM-DIAG: [[ALL16]] = !{i64 16, !"all-vtables"} +// ITANIUM: [[A32]] = !{i64 32, !"_ZTS1A"} +// ITANIUM-DIAG: [[ALL32]] = !{i64 32, !"all-vtables"} +// ITANIUM: [[B32]] = !{i64 32, !"_ZTS1B"} +// ITANIUM: [[C32]] = !{i64 32, !"_ZTS1C"} +// ITANIUM: [[C88]] = !{i64 88, !"_ZTS1C"} +// ITANIUM-DIAG: [[ALL88]] = !{i64 88, !"all-vtables"} +// ITANIUM: [[D32]] = !{i64 32, [[D_ID:![0-9]+]]} +// ITANIUM: [[D_ID]] = distinct !{} +// ITANIUM: [[A64]] = !{i64 64, !"_ZTS1A"} +// ITANIUM-DIAG: [[ALL64]] = !{i64 64, !"all-vtables"} +// ITANIUM: [[FA16]] = !{i64 16, [[FA_ID:![0-9]+]]} +// ITANIUM: [[FA_ID]] = distinct !{} + +// MS: [[A8]] = !{i64 8, !"?AUA@@"} +// MS: [[B8]] = !{i64 8, !"?AUB@@"} +// MS: [[D8]] = !{i64 8, [[D_ID:![0-9]+]]} +// MS: [[D_ID]] = distinct !{} +// MS: [[FA8]] = !{i64 8, [[FA_ID:![0-9]+]]} +// MS: [[FA_ID]] = distinct !{} diff --git a/test/CodeGenCXX/virtual-base-ctor.cpp b/test/CodeGenCXX/virtual-base-ctor.cpp index 20a88cd37105..8c8c310421dc 100644 --- a/test/CodeGenCXX/virtual-base-ctor.cpp +++ b/test/CodeGenCXX/virtual-base-ctor.cpp @@ -8,4 +8,4 @@ struct A { int a; A() { y = ((size_t)this - (size_t)&x) / sizeof(void*); } }; struct B : virtual A { void* x; }; B x; -// CHECK: @y = global i8 2 +// CHECK: @y = local_unnamed_addr global i8 2 diff --git a/test/CodeGenCXX/virtual-function-attrs.cpp b/test/CodeGenCXX/virtual-function-attrs.cpp new file mode 100644 index 000000000000..3a9a1a28ddf4 --- /dev/null +++ b/test/CodeGenCXX/virtual-function-attrs.cpp @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 %s -triple %itanium_abi_triple -std=c++11 -emit-llvm -o - | FileCheck %s + +class A { + virtual void f(); + virtual void g(); + virtual ~A(); +}; + +void A::f() {} + +// CHECK: define [[CC:(x86_thiscallcc )?]]void @_ZN1A1fEv({{.*}}) unnamed_addr +// CHECK: declare [[CC]]void @_ZN1A1gEv({{.*}}) unnamed_addr +// CHECK: declare {{.*}} @_ZN1AD1Ev({{.*}}) unnamed_addr +// CHECK: declare [[CC]]void @_ZN1AD0Ev({{.*}}) unnamed_addr diff --git a/test/CodeGenCXX/vla-consruct.cpp b/test/CodeGenCXX/vla-consruct.cpp new file mode 100644 index 000000000000..fd8314a5d716 --- /dev/null +++ b/test/CodeGenCXX/vla-consruct.cpp @@ -0,0 +1,139 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fcxx-exceptions -fexceptions -O0 %s -emit-llvm -o - | FileCheck %s + +extern "C" int printf(const char *, ...); + +static int N; +struct S { + S() + __attribute__((nothrow)) { printf("%d: S()\n", ++N); } + ~S() __attribute__((nothrow)) { printf("%d: ~S()\n", N--); } + int n[17]; +}; +// CHECK: [[struct_S:%.+]] = type { [17 x i32] } +void print(int n, int a, int b, int c, int d) { + printf("n=%d\n,sizeof(S)=%d\nsizeof(array_t[0][0])=%d\nsizeof(array_t[0])=%d\nsizeof(array_t)=%d\n", + n, a, b, c, d); + if (n == 2) + throw(n); +} + +void test(int n) { + // CHECK: define void {{.*test.*}}(i32 [[n:%.+]]) # + // CHECK: [[n_addr:%.+]] = alloca + // CHECK-NEXT: [[saved_stack:%.+]] = alloca + // CHECK-NEXT: [[sizeof_S:%.+]] = alloca + // CHECK-NEXT: [[sizeof_array_t_0_0:%.+]] = alloca + // CHECK-NEXT: [[sizeof_array_t_0:%.+]] = alloca + // CHECK-NEXT: [[sizeof_array_t:%.+]] = alloca + // CHECK-NEXT: [[exn_slot:%.+]] = alloca i8* + // CHECK-NEXT: [[ehselector_slot:%.+]] = alloca i32 + // CHECK-NEXT: store i32 [[n]], i32* [[n_addr]] + // CHECK-NEXT: [[t0:%.+]] = load i32, i32* [[n_addr]] + // CHECK-NEXT: [[t1:%.+]] = zext i32 [[t0]] to i64 + // CHECK-NEXT: [[t2:%.+]] = load i32, i32* [[n_addr]] + // CHECK-NEXT: [[add:%.+]] = add nsw i32 [[t2]], 1 + // CHECK-NEXT: [[t3:%.+]] = zext i32 [[add]] to i64 + // CHECK-NEXT: [[t4:%.+]] = call i8* @llvm.stacksave() + // CHECK-NEXT: store i8* [[t4]], i8** [[saved_stack]] + // CHECK-NEXT: [[t5:%.+]] = mul nuw i64 [[t1]], [[t3]] + // CHECK-NEXT: [[vla:%.+]] = alloca [[struct_S]], i64 [[t5]] + // CHECK-NEXT: [[t6:%.+]] = mul nuw i64 [[t1]], [[t3]] + // CHECK-NEXT: [[isempty:%.+]] = icmp eq i64 [[t6]], 0 + // CHECK-NEXT: br i1 [[isempty]], label %[[arrayctor_cont:.+]], label %[[new_ctorloop:.+]] + + S array_t[n][n + 1]; + + // CHECK: [[new_ctorloop]] + // CHECK-NEXT: [[arrayctor_end:%.+]] = getelementptr inbounds [[struct_S]], [[struct_S]]* [[vla]], i64 [[t6]] + // CHECK-NEXT: br label %[[arrayctor_loop:.+]] + + // CHECK: [[arrayctor_loop]] + // CHECK-NEXT: [[arrayctor_cur:%.+]] = phi [[struct_S]]* [ [[vla]], %[[new_ctorloop]] ], [ [[arrayctor_next:%.+]], %[[arrayctor_loop]] ] + // CHECK-NEXT: call void [[ctor:@.+]]([[struct_S]]* [[arrayctor_cur]]) + // CHECK-NEXT: [[arrayctor_next]] = getelementptr inbounds [[struct_S]], [[struct_S]]* [[arrayctor_cur]], i64 1 + // CHECK-NEXT: [[arrayctor_done:%.+]] = icmp eq [[struct_S]]* [[arrayctor_next]], [[arrayctor_end]] + // CHECK-NEXT: br i1 [[arrayctor_done]], label %[[arrayctor_cont]], label %[[arrayctor_loop]] + + int sizeof_S = sizeof(S); + int sizeof_array_t_0_0 = sizeof(array_t[0][0]); + int sizeof_array_t_0 = sizeof(array_t[0]); + int sizeof_array_t = sizeof(array_t); + print(n, sizeof_S, sizeof_array_t_0_0, sizeof_array_t_0, sizeof_array_t); + + // CHECK: [[arrayctor_cont]] + // CHECK-NEXT: store i32 68, i32* [[sizeof_S]] + // CHECK-NEXT: store i32 68, i32* [[sizeof_array_t_0_0]] + // CHECK: [[t8:%.+]] = mul nuw i64 68, [[t3]] + // CHECK-NEXT: [[conv:%.+]] = trunc i64 [[t8]] to i32 + // CHECK-NEXT: store i32 [[conv]], i32* [[sizeof_array_t_0]] + // CHECK-NEXT: [[t9:%.+]] = mul nuw i64 [[t1]], [[t3]] + // CHECK-NEXT: [[t10:%.+]] = mul nuw i64 68, [[t9]] + // CHECK-NEXT: [[conv1:%.+]] = trunc i64 [[t10]] to i32 + // CHECK-NEXT: store i32 [[conv1]], i32* [[sizeof_array_t]] + // CHECK-NEXT: [[t11:%.+]] = load i32, i32* [[n_addr:%.+]] + // CHECK-NEXT: [[t12:%.+]] = load i32, i32* [[sizeof_S]] + // CHECK-NEXT: [[t13:%.+]] = load i32, i32* [[sizeof_array_t_0_0]] + // CHECK-NEXT: [[t14:%.+]] = load i32, i32* [[sizeof_array_t_0]] + // CHECK-NEXT: [[t15:%.+]] = load i32, i32* [[sizeof_array_t]] + // CHECK-NEXT: invoke void @{{.*print.*}}(i32 [[t11]], i32 [[t12]], i32 [[t13]], i32 [[t14]], i32 [[t15]]) + // CHECK-NEXT: to label %[[invoke_cont:.+]] unwind label %[[lpad:.+]] + + // CHECK: [[invoke_cont]] + // CHECK-NEXT: [[t16:%.+]] = mul nuw i64 [[t1]], [[t3]] + // CHECK-NEXT: [[t17:%.+]] = getelementptr inbounds [[struct_S]], [[struct_S]]* [[vla]], i64 [[t16]] + // CHECK-NEXT: [[arraydestroy_isempty:%.+]] = icmp eq [[struct_S]]* [[vla]], [[t17]] + // CHECK-NEXT: br i1 [[arraydestroy_isempty]], label %[[arraydestroy_done2:.+]], label %[[arraydestroy_body:.+]] + + // CHECK: [[arraydestroy_body]] + // CHECK-NEXT: [[arraydestroy_elementPast:%.+]] = phi [[struct_S]]* [ [[t17]], %[[invoke_cont]] ], [ [[arraydestroy_element:%.+]], %[[arraydestroy_body]] ] + // CHECK-NEXT: [[arraydestroy_element]] = getelementptr inbounds [[struct_S]], [[struct_S]]* [[arraydestroy_elementPast]] + // CHECK-NEXT: call void @[[dtor:.+]]([[struct_S]]* [[arraydestroy_element]]) + // CHECK-NEXT: [[arraydestroy_done:%.+]] = icmp eq [[struct_S]]* [[arraydestroy_element]], [[vla]] + // CHECK-NEXT: br i1 [[arraydestroy_done]], label %[[arraydestroy_done2]], label %[[arraydestroy_body]] + + // CHECK: [[arraydestroy_done2]] + // CHECK-NEXT: [[t17:%.+]] = load i8*, i8** [[saved_stack]] + // CHECK-NEXT: call void @llvm.stackrestore(i8* [[t17]]) + // CHECK: ret void + + // CHECK: [[lpad]] + // CHECK-NEXT: [[t19:%.+]] = landingpad { i8*, i32 } + // CHECK: [[t20:%.+]] = extractvalue { i8*, i32 } [[t19]], 0 + // CHECK-NEXT: store i8* [[t20]], i8** [[exn_slot]] + // CHECK-NEXT: [[t21:%.+]] = extractvalue { i8*, i32 } [[t19]], 1 + // CHECK-NEXT: store i32 [[t21]], i32* [[ehselector_slot]] + // CHECK-NEXT: [[t22:%.+]] = mul nuw i64 [[t1]], [[t3]] + // CHECK-NEXT: [[t23:%.+]] = getelementptr inbounds [[struct_S]], [[struct_S]]* [[vla]], i64 [[t22]] + // CHECK-NEXT: [[arraydestroy_isempty3:%.+]] = icmp eq [[struct_S]]* [[vla]], [[t23]] + // CHECK-NEXT: br i1 [[arraydestroy_isempty3]], label %[[arraydestroy_done8:.+]], label %[[arraydestroy_body4:.+]] + + // CHECK: [[arraydestroy_body4]] + // CHECK: [[arraydestroy_elementPast5:%.+]] = phi [[struct_S]]* [ [[t23]], %[[lpad]] ], [ [[arraydestroy_element6:.+]], %[[arraydestroy_body4]] ] + // CHECK-NEXT: [[arraydestroy_element6]] = getelementptr inbounds [[struct_S]], [[struct_S]]* [[arraydestroy_elementPast5]], i64 -1 + // CHECK-NEXT: call void @[[dtor]]([[struct_S]]* [[arraydestroy_element6]]) + // CHECK-NEXT: [[arraydestroy_done7:%.+]] = icmp eq [[struct_S]]* [[arraydestroy_element6]], [[vla]] + // CHECK-NEXT: br i1 [[arraydestroy_done7]], label %[[arraydestroy_done8]], label %[[arraydestroy_body4]] + + // CHECK: [[arraydestroy_done8]] + // CHECK-NEXT: br label %[[eh_resume:.+]] + + // CHECK: [[eh_resume]] + // CHECK-NEXT: [[exn:%.+]] = load i8*, i8** [[exn_slot]] + // CHECK-NEXT: [[sel:%.+]] = load i32, i32* [[ehselector_slot]] + // CHECK-NEXT: [[lpad_val:%.+]] = insertvalue { i8*, i32 } undef, i8* [[exn]], 0 + // CHECK-NEXT: [[lpad_val9:%.+]] = insertvalue { i8*, i32 } [[lpad_val]], i32 [[sel]], 1 + // CHECK-NEXT: resume { i8*, i32 } [[lpad_val9]] +} + +int main() { + try { + test(2); + } catch (int e) { + printf("expeption %d\n", e); + } + try { + test(3); + } catch (int e) { + printf("expeption %d", e); + } +} diff --git a/test/CodeGenCXX/vtable-assume-load.cpp b/test/CodeGenCXX/vtable-assume-load.cpp index 30cfc00ec7ba..819b09d70e3d 100644 --- a/test/CodeGenCXX/vtable-assume-load.cpp +++ b/test/CodeGenCXX/vtable-assume-load.cpp @@ -27,7 +27,7 @@ void g(A *a) { a->foo(); } // CHECK1-LABEL: define void @_ZN5test14fooAEv() // CHECK1: call void @_ZN5test11AC1Ev(%"struct.test1::A"* // CHECK1: %[[VTABLE:.*]] = load i8**, i8*** %{{.*}} -// CHECK1: %[[CMP:.*]] = icmp eq i8** %[[VTABLE]], getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTVN5test11AE, i64 0, i64 2) +// CHECK1: %[[CMP:.*]] = icmp eq i8** %[[VTABLE]], getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTVN5test11AE, i32 0, i32 2) // CHECK1: call void @llvm.assume(i1 %[[CMP]]) // CHECK1-LABEL: } @@ -39,7 +39,7 @@ void fooA() { // CHECK1-LABEL: define void @_ZN5test14fooBEv() // CHECK1: call void @_ZN5test11BC1Ev(%"struct.test1::B"* %{{.*}}) // CHECK1: %[[VTABLE:.*]] = load i8**, i8*** %{{.*}} -// CHECK1: %[[CMP:.*]] = icmp eq i8** %[[VTABLE]], getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTVN5test11BE, i64 0, i64 2) +// CHECK1: %[[CMP:.*]] = icmp eq i8** %[[VTABLE]], getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTVN5test11BE, i32 0, i32 2) // CHECK1: call void @llvm.assume(i1 %[[CMP]]) // CHECK1-LABEL: } @@ -73,14 +73,14 @@ void h(B *b) { b->bar(); } // CHECK2-LABEL: define void @_ZN5test24testEv() // CHECK2: call void @_ZN5test21CC1Ev(%"struct.test2::C"* // CHECK2: %[[VTABLE:.*]] = load i8**, i8*** {{.*}} -// CHECK2: %[[CMP:.*]] = icmp eq i8** %[[VTABLE]], getelementptr inbounds ([6 x i8*], [6 x i8*]* @_ZTVN5test21CE, i64 0, i64 2) +// CHECK2: %[[CMP:.*]] = icmp eq i8** %[[VTABLE]], getelementptr inbounds ([6 x i8*], [6 x i8*]* @_ZTVN5test21CE, i32 0, i32 2) // CHECK2: call void @llvm.assume(i1 %[[CMP]]) // CHECK2: %[[V2:.*]] = bitcast %"struct.test2::C"* %{{.*}} to i8* // CHECK2: %[[ADD_PTR:.*]] = getelementptr inbounds i8, i8* %[[V2]], i64 8 // CHECK2: %[[V3:.*]] = bitcast i8* %[[ADD_PTR]] to i8*** // CHECK2: %[[VTABLE2:.*]] = load i8**, i8*** %[[V3]] -// CHECK2: %[[CMP2:.*]] = icmp eq i8** %[[VTABLE2]], getelementptr inbounds ([6 x i8*], [6 x i8*]* @_ZTVN5test21CE, i64 0, i64 5) +// CHECK2: %[[CMP2:.*]] = icmp eq i8** %[[VTABLE2]], getelementptr inbounds ([6 x i8*], [6 x i8*]* @_ZTVN5test21CE, i32 0, i32 5) // CHECK2: call void @llvm.assume(i1 %[[CMP2]]) // CHECK2: call void @_ZN5test21gEPNS_1AE( @@ -111,7 +111,7 @@ void g(B *a) { a->foo(); } // CHECK3-LABEL: define void @_ZN5test34testEv() // CHECK3: call void @_ZN5test31CC1Ev(%"struct.test3::C"* -// CHECK3: %[[CMP:.*]] = icmp eq i8** %{{.*}}, getelementptr inbounds ([4 x i8*], [4 x i8*]* @_ZTVN5test31CE, i64 0, i64 3) +// CHECK3: %[[CMP:.*]] = icmp eq i8** %{{.*}}, getelementptr inbounds ([4 x i8*], [4 x i8*]* @_ZTVN5test31CE, i32 0, i32 3) // CHECK3: call void @llvm.assume(i1 %[[CMP]]) // CHECK3-LABLEL: } void test() { @@ -140,11 +140,11 @@ void g(C *c) { c->foo(); } // CHECK4-LABEL: define void @_ZN5test44testEv() // CHECK4: call void @_ZN5test41CC1Ev(%"struct.test4::C"* // CHECK4: %[[VTABLE:.*]] = load i8**, i8*** %{{.*}} -// CHECK4: %[[CMP:.*]] = icmp eq i8** %[[VTABLE]], getelementptr inbounds ([5 x i8*], [5 x i8*]* @_ZTVN5test41CE, i64 0, i64 4) +// CHECK4: %[[CMP:.*]] = icmp eq i8** %[[VTABLE]], getelementptr inbounds ([5 x i8*], [5 x i8*]* @_ZTVN5test41CE, i32 0, i32 4) // CHECK4: call void @llvm.assume(i1 %[[CMP]] // CHECK4: %[[VTABLE2:.*]] = load i8**, i8*** %{{.*}} -// CHECK4: %[[CMP2:.*]] = icmp eq i8** %[[VTABLE2]], getelementptr inbounds ([5 x i8*], [5 x i8*]* @_ZTVN5test41CE, i64 0, i64 4) +// CHECK4: %[[CMP2:.*]] = icmp eq i8** %[[VTABLE2]], getelementptr inbounds ([5 x i8*], [5 x i8*]* @_ZTVN5test41CE, i32 0, i32 4) // CHECK4: call void @llvm.assume(i1 %[[CMP2]]) // CHECK4-LABEL: } diff --git a/test/CodeGenCXX/vtable-key-function-arm.cpp b/test/CodeGenCXX/vtable-key-function-arm.cpp index 6f1265b6277d..3d5c3c3865ea 100644 --- a/test/CodeGenCXX/vtable-key-function-arm.cpp +++ b/test/CodeGenCXX/vtable-key-function-arm.cpp @@ -1,9 +1,9 @@ // RUN: %clang_cc1 %s -triple=armv7-unknown-unknown -emit-llvm -o - | FileCheck %s // RUN: %clang_cc1 %s -triple=armv7-unknown-unknown -emit-llvm -o - | FileCheck -check-prefix=CHECK-LATE %s -// The 'a' variants ask for the v-table first. -// The 'b' variants ask for the v-table second. -// The 'c' variants ask for the v-table third. +// The 'a' variants ask for the vtable first. +// The 'b' variants ask for the vtable second. +// The 'c' variants ask for the vtable third. // We do a separate CHECK-LATE pass because the RTTI definition gets // changed after the fact, which causes reordering of the globals. diff --git a/test/CodeGenCXX/vtable-key-function-ios.cpp b/test/CodeGenCXX/vtable-key-function-ios.cpp index d17aa695d2b5..8a3466beda44 100644 --- a/test/CodeGenCXX/vtable-key-function-ios.cpp +++ b/test/CodeGenCXX/vtable-key-function-ios.cpp @@ -4,9 +4,9 @@ // RUN: %clang_cc1 %s -triple=x86_64-pc-windows-gnu -emit-llvm -o - | FileCheck %s // RUN: %clang_cc1 %s -triple=x86_64-pc-windows-gnu -emit-llvm -o - | FileCheck -check-prefix=CHECK-LATE %s -// The 'a' variants ask for the v-table first. -// The 'b' variants ask for the v-table second. -// The 'c' variants ask for the v-table third. +// The 'a' variants ask for the vtable first. +// The 'b' variants ask for the vtable second. +// The 'c' variants ask for the vtable third. // We do a separate CHECK-LATE pass because the RTTI definition gets // changed after the fact, which causes reordering of the globals. diff --git a/test/CodeGenCXX/vtable-linkage.cpp b/test/CodeGenCXX/vtable-linkage.cpp index ff398ffa61dd..0b556d10c3e8 100644 --- a/test/CodeGenCXX/vtable-linkage.cpp +++ b/test/CodeGenCXX/vtable-linkage.cpp @@ -1,6 +1,6 @@ // RUN: %clang_cc1 %s -triple=x86_64-pc-linux -emit-llvm -o %t // RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -disable-llvm-optzns -O3 -emit-llvm -o %t.opt -// RUN: FileCheck --check-prefix=CHECK %s < %t +// RUN: FileCheck %s < %t // RUN: FileCheck --check-prefix=CHECK-OPT %s < %t.opt namespace { diff --git a/test/CodeGenCXX/vtable-pointer-initialization.cpp b/test/CodeGenCXX/vtable-pointer-initialization.cpp index 2854291e2965..130a55cf6218 100644 --- a/test/CodeGenCXX/vtable-pointer-initialization.cpp +++ b/test/CodeGenCXX/vtable-pointer-initialization.cpp @@ -21,13 +21,13 @@ struct A : Base { // CHECK-LABEL: define void @_ZN1AC2Ev(%struct.A* %this) unnamed_addr // CHECK: call void @_ZN4BaseC2Ev( -// CHECK: store i32 (...)** bitcast (i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTV1A, i64 0, i64 2) to i32 (...)**) +// CHECK: store i32 (...)** bitcast (i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTV1A, i32 0, i32 2) to i32 (...)**) // CHECK: call void @_ZN5FieldC1Ev( // CHECK: ret void A::A() { } // CHECK-LABEL: define void @_ZN1AD2Ev(%struct.A* %this) unnamed_addr -// CHECK: store i32 (...)** bitcast (i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTV1A, i64 0, i64 2) to i32 (...)**) +// CHECK: store i32 (...)** bitcast (i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTV1A, i32 0, i32 2) to i32 (...)**) // CHECK: call void @_ZN5FieldD1Ev( // CHECK: call void @_ZN4BaseD2Ev( // CHECK: ret void @@ -49,12 +49,12 @@ void f() { B b; } // CHECK-LABEL: define linkonce_odr void @_ZN1BC2Ev(%struct.B* %this) unnamed_addr // CHECK: call void @_ZN4BaseC2Ev( -// CHECK: store i32 (...)** bitcast (i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTV1B, i64 0, i64 2) to i32 (...)**) +// CHECK: store i32 (...)** bitcast (i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTV1B, i32 0, i32 2) to i32 (...)**) // CHECK: call void @_ZN5FieldC1Ev // CHECK: ret void // CHECK-LABEL: define linkonce_odr void @_ZN1BD2Ev(%struct.B* %this) unnamed_addr -// CHECK: store i32 (...)** bitcast (i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTV1B, i64 0, i64 2) to i32 (...)**) +// CHECK: store i32 (...)** bitcast (i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTV1B, i32 0, i32 2) to i32 (...)**) // CHECK: call void @_ZN5FieldD1Ev( // CHECK: call void @_ZN4BaseD2Ev( // CHECK: ret void diff --git a/test/CodeGenCXX/vtt-layout.cpp b/test/CodeGenCXX/vtt-layout.cpp index 2f441ff7e18a..7ff93dd451c9 100644 --- a/test/CodeGenCXX/vtt-layout.cpp +++ b/test/CodeGenCXX/vtt-layout.cpp @@ -78,9 +78,11 @@ namespace Test6 { } } -// CHECK: @_ZTTN5Test11BE = unnamed_addr constant [1 x i8*] [i8* bitcast (i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @_ZTVN5Test11BE, i64 0, i64 3) to i8*)] +// CHECK: @_ZTTN5Test11BE = unnamed_addr constant [1 x i8*] [i8* bitcast (i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @_ZTVN5Test11BE, i32 0, i32 3) to i8*)] // CHECK: @_ZTVN5Test51AE = unnamed_addr constant [4 x i8*] [i8* null, i8* bitcast ({ i8*, i8* }* @_ZTIN5Test51AE to i8*), i8* bitcast (void ()* @__cxa_pure_virtual to i8*), i8* bitcast (void (%"struct.Test5::A"*)* @_ZN5Test51A6anchorEv to i8*)] // CHECK: @_ZTVN5Test61AE = unnamed_addr constant [4 x i8*] [i8* null, i8* bitcast ({ i8*, i8* }* @_ZTIN5Test61AE to i8*), i8* bitcast (void ()* @__cxa_deleted_virtual to i8*), i8* bitcast (void (%"struct.Test6::A"*)* @_ZN5Test61A6anchorEv to i8*)] -// CHECK: @_ZTTN5Test21CE = linkonce_odr unnamed_addr constant [2 x i8*] [i8* bitcast (i8** getelementptr inbounds ([5 x i8*], [5 x i8*]* @_ZTVN5Test21CE, i64 0, i64 4) to i8*), i8* bitcast (i8** getelementptr inbounds ([5 x i8*], [5 x i8*]* @_ZTVN5Test21CE, i64 0, i64 4) to i8*)] -// CHECK: @_ZTTN5Test31DE = linkonce_odr unnamed_addr constant [13 x i8*] [i8* bitcast (i8** getelementptr inbounds ([19 x i8*], [19 x i8*]* @_ZTVN5Test31DE, i64 0, i64 5) to i8*), i8* bitcast (i8** getelementptr inbounds ([7 x i8*], [7 x i8*]* @_ZTCN5Test31DE0_NS_2C1E, i64 0, i64 3) to i8*), i8* bitcast (i8** getelementptr inbounds ([7 x i8*], [7 x i8*]* @_ZTCN5Test31DE0_NS_2C1E, i64 0, i64 6) to i8*), i8* bitcast (i8** getelementptr inbounds ([14 x i8*], [14 x i8*]* @_ZTCN5Test31DE16_NS_2C2E, i64 0, i64 6) to i8*), i8* bitcast (i8** getelementptr inbounds ([14 x i8*], [14 x i8*]* @_ZTCN5Test31DE16_NS_2C2E, i64 0, i64 6) to i8*), i8* bitcast (i8** getelementptr inbounds ([14 x i8*], [14 x i8*]* @_ZTCN5Test31DE16_NS_2C2E, i64 0, i64 10) to i8*), i8* bitcast (i8** getelementptr inbounds ([14 x i8*], [14 x i8*]* @_ZTCN5Test31DE16_NS_2C2E, i64 0, i64 13) to i8*), i8* bitcast (i8** getelementptr inbounds ([19 x i8*], [19 x i8*]* @_ZTVN5Test31DE, i64 0, i64 15) to i8*), i8* bitcast (i8** getelementptr inbounds ([19 x i8*], [19 x i8*]* @_ZTVN5Test31DE, i64 0, i64 11) to i8*), i8* bitcast (i8** getelementptr inbounds ([19 x i8*], [19 x i8*]* @_ZTVN5Test31DE, i64 0, i64 11) to i8*), i8* bitcast (i8** getelementptr inbounds ([19 x i8*], [19 x i8*]* @_ZTVN5Test31DE, i64 1, i64 0) to i8*), i8* bitcast (i8** getelementptr inbounds ([7 x i8*], [7 x i8*]* @_ZTCN5Test31DE64_NS_2V2E, i64 0, i64 3) to i8*), i8* bitcast (i8** getelementptr inbounds ([7 x i8*], [7 x i8*]* @_ZTCN5Test31DE64_NS_2V2E, i64 0, i64 6) to i8*)] -// CHECK: @_ZTTN5Test41DE = linkonce_odr unnamed_addr constant [19 x i8*] [i8* bitcast (i8** getelementptr inbounds ([25 x i8*], [25 x i8*]* @_ZTVN5Test41DE, i64 0, i64 6) to i8*), i8* bitcast (i8** getelementptr inbounds ([11 x i8*], [11 x i8*]* @_ZTCN5Test41DE0_NS_2C1E, i64 0, i64 4) to i8*), i8* bitcast (i8** getelementptr inbounds ([11 x i8*], [11 x i8*]* @_ZTCN5Test41DE0_NS_2C1E, i64 0, i64 7) to i8*), i8* bitcast (i8** getelementptr inbounds ([11 x i8*], [11 x i8*]* @_ZTCN5Test41DE0_NS_2C1E, i64 0, i64 10) to i8*), i8* bitcast (i8** getelementptr inbounds ([19 x i8*], [19 x i8*]* @_ZTCN5Test41DE16_NS_2C2E, i64 0, i64 7) to i8*), i8* bitcast (i8** getelementptr inbounds ([19 x i8*], [19 x i8*]* @_ZTCN5Test41DE16_NS_2C2E, i64 0, i64 7) to i8*), i8* bitcast (i8** getelementptr inbounds ([19 x i8*], [19 x i8*]* @_ZTCN5Test41DE16_NS_2C2E, i64 0, i64 12) to i8*), i8* bitcast (i8** getelementptr inbounds ([19 x i8*], [19 x i8*]* @_ZTCN5Test41DE16_NS_2C2E, i64 0, i64 15) to i8*), i8* bitcast (i8** getelementptr inbounds ([19 x i8*], [19 x i8*]* @_ZTCN5Test41DE16_NS_2C2E, i64 0, i64 18) to i8*), i8* bitcast (i8** getelementptr inbounds ([25 x i8*], [25 x i8*]* @_ZTVN5Test41DE, i64 0, i64 17) to i8*), i8* bitcast (i8** getelementptr inbounds ([25 x i8*], [25 x i8*]* @_ZTVN5Test41DE, i64 0, i64 20) to i8*), i8* bitcast (i8** getelementptr inbounds ([25 x i8*], [25 x i8*]* @_ZTVN5Test41DE, i64 0, i64 13) to i8*), i8* bitcast (i8** getelementptr inbounds ([25 x i8*], [25 x i8*]* @_ZTVN5Test41DE, i64 0, i64 13) to i8*), i8* bitcast (i8** getelementptr inbounds ([25 x i8*], [25 x i8*]* @_ZTVN5Test41DE, i64 1, i64 0) to i8*), i8* bitcast (i8** getelementptr inbounds ([7 x i8*], [7 x i8*]* @_ZTCN5Test41DE40_NS_2V1E, i64 0, i64 3) to i8*), i8* bitcast (i8** getelementptr inbounds ([7 x i8*], [7 x i8*]* @_ZTCN5Test41DE40_NS_2V1E, i64 0, i64 6) to i8*), i8* bitcast (i8** getelementptr inbounds ([11 x i8*], [11 x i8*]* @_ZTCN5Test41DE72_NS_2V2E, i64 0, i64 4) to i8*), i8* bitcast (i8** getelementptr inbounds ([11 x i8*], [11 x i8*]* @_ZTCN5Test41DE72_NS_2V2E, i64 0, i64 7) to i8*), i8* bitcast (i8** getelementptr inbounds ([11 x i8*], [11 x i8*]* @_ZTCN5Test41DE72_NS_2V2E, i64 0, i64 10) to i8*)] +// CHECK: @_ZTTN5Test21CE = linkonce_odr unnamed_addr constant [2 x i8*] [i8* bitcast (i8** getelementptr inbounds ([5 x i8*], [5 x i8*]* @_ZTVN5Test21CE, i32 0, i32 4) to i8*), i8* bitcast (i8** getelementptr inbounds ([5 x i8*], [5 x i8*]* @_ZTVN5Test21CE, i32 0, i32 4) to i8*)] +// CHECK: @_ZTTN5Test31DE = linkonce_odr unnamed_addr constant [13 x i8*] [i8* bitcast (i8** getelementptr inbounds ([19 x i8*], [19 x i8*]* @_ZTVN5Test31DE, i32 0, i32 5) to i8*), i8* bitcast (i8** getelementptr inbounds ([7 x i8*], [7 x i8*]* @_ZTCN5Test31DE0_NS_2C1E, i32 0, i32 3) to i8*), i8* bitcast (i8** getelementptr inbounds ([7 x i8*], [7 x i8*]* @_ZTCN5Test31DE0_NS_2C1E, i32 0, i32 6) to i8*), i8* bitcast (i8** getelementptr inbounds ([14 x i8*], [14 x i8*]* @_ZTCN5Test31DE16_NS_2C2E, i32 0, i32 6) to i8*), i8* bitcast (i8** getelementptr inbounds ([14 x i8*], [14 x i8*]* @_ZTCN5Test31DE16_NS_2C2E, i32 0, i32 6) to i8*), i8* bitcast (i8** getelementptr inbounds ([14 x i8*], [14 x i8*]* @_ZTCN5Test31DE16_NS_2C2E, i32 0, i32 10) to i8*), i8* bitcast (i8** getelementptr inbounds ([14 x i8*], [14 x i8*]* @_ZTCN5Test31DE16_NS_2C2E, i32 0, i32 13) to i8*), i8* bitcast (i8** getelementptr inbounds ([19 x i8*], [19 x i8*]* @_ZTVN5Test31DE, i32 0, i32 15) to i8*), i8* bitcast (i8** getelementptr inbounds ([19 x i8*], [19 x i8*]* @_ZTVN5Test31DE, i32 0, i32 11) to i8*), i8* bitcast (i8** getelementptr inbounds ([19 x i8*], [19 x i8*]* @_ZTVN5Test31DE, i32 0, i32 11) to i8*), i8* bitcast (i8** getelementptr inbounds ([19 x i8*], [19 x i8*]* @_ZTVN5Test31DE, i64 1, i32 0) to i8*), i8* bitcast (i8** getelementptr inbounds ([7 x i8*], [7 x i8*]* @_ZTCN5Test31DE64_NS_2V2E, i32 0, i32 3) to i8*), i8* bitcast (i8** getelementptr inbounds ([7 x i8*], [7 x i8*]* @_ZTCN5Test31DE64_NS_2V2E, i32 0, i32 6) to i8*)] +// CHECK: @_ZTTN5Test41DE = linkonce_odr unnamed_addr constant [19 x i8*] [i8* bitcast (i8** getelementptr inbounds ([25 x i8*], [25 x i8*]* @_ZTVN5Test41DE, i32 0, i32 6) to i8*), i8* bitcast (i8** getelementptr inbounds ([11 x i8*], [11 x i8*]* @_ZTCN5Test41DE0_NS_2C1E, i32 0, i32 4) to i8*), i8* bitcast (i8** getelementptr inbounds ([11 x i8*], [11 x i8*]* @_ZTCN5Test41DE0_NS_2C1E, i32 0, i32 7) to i8*), i8* bitcast (i8** getelementptr inbounds ([11 x i8*], [11 x i8*]* @_ZTCN5Test41DE0_NS_2C1E, i32 0, i32 10) to i8*), i8* bitcast (i8** getelementptr inbounds ([19 x i8*], [19 x i8*]* @_ZTCN5Test41DE16_NS_2C2E, i32 0, i32 7) to i8*), i8* bitcast (i8** getelementptr inbounds ([19 x i8*], [19 x i8*]* @_ZTCN5Test41DE16_NS_2C2E, i32 0, i32 7) to i8*), i8* bitcast (i8** getelementptr inbounds ([19 x i8*], [19 x i8*]* @_ZTCN5Test41DE16_NS_2C2E, i32 0, i32 12) to i8*), i8* bitcast (i8** getelementptr inbounds ([19 x i8*], [19 x i8*]* @_ZTCN5Test41DE16_NS_2C2E, i32 0, i32 15) to i8*), i8* bitcast (i8** getelementptr inbounds ([19 x i8*], [19 x i8*]* @_ZTCN5Test41DE16_NS_2C2E, i32 0, i32 18) to i8*), i8* bitcast (i8** getelementptr inbounds ([25 x i8*], [25 x i8*]* @_ZTVN5Test41DE, i32 0, i32 17) to i8*), i8* bitcast (i8** getelementptr inbounds ([25 x i8*], [25 x i8*]* @_ZTVN5Test41DE, i32 0, i32 20) to i8*), i8* bitcast (i8** getelementptr inbounds ([25 x i8*], [25 x i8*]* @_ZTVN5Test41DE, i32 0, i32 13) to i8*), i8* bitcast (i8** getelementptr inbounds ([25 x i8*], [25 x i8*]* @_ZTVN5Test41DE, i32 0, i32 13) to i8*), i8* bitcast (i8** getelementptr inbounds ([25 x i8*], [25 x i8*]* @_ZTVN5Test41DE, i64 1, i32 0) to i8*), i8* bitcast (i8** getelementptr inbounds ([7 x i8*], [7 x i8*]* @_ZTCN5Test41DE40_NS_2V1E, i32 0, i32 3) to i8*), i8* bitcast (i8** getelementptr inbounds ([7 x i8*], [7 x i8*]* @_ZTCN5Test41DE40_NS_2V1E, i32 0, i32 6) to i8*), i8* bitcast (i8** getelementptr inbounds ([11 x i8*], [11 x i8*]* @_ZTCN5Test41DE72_NS_2V2E, i32 0, i32 4) to i8*), i8* bitcast (i8** getelementptr inbounds ([11 x i8*], [11 x i8*]* @_ZTCN5Test41DE72_NS_2V2E, i32 0, i32 7) to i8*), i8* bitcast (i8** getelementptr inbounds ([11 x i8*], [11 x i8*]* @_ZTCN5Test41DE72_NS_2V2E, i32 0, i32 10) to i8*)] +// CHECK: declare void @__cxa_pure_virtual() unnamed_addr +// CHECK: declare void @__cxa_deleted_virtual() unnamed_addr |