diff options
Diffstat (limited to 'test/CodeGenCXX')
159 files changed, 4431 insertions, 1325 deletions
diff --git a/test/CodeGenCXX/2010-07-23-DeclLoc.cpp b/test/CodeGenCXX/2010-07-23-DeclLoc.cpp index 4c689029b8a8..56c364cb485f 100644 --- a/test/CodeGenCXX/2010-07-23-DeclLoc.cpp +++ b/test/CodeGenCXX/2010-07-23-DeclLoc.cpp @@ -1,7 +1,7 @@ // RUN: %clang_cc1 -emit-llvm -g %s -o - | FileCheck %s // Require the template function declaration refer to the correct filename. // First, locate the function decl in metadata, and pluck out the file handle: -// CHECK: metadata [[filehandle:![0-9]+]], {{[^,]*}}, {{.*extract_dwarf_data_from_header.*extract_dwarf_data_from_header.*extract_dwarf_data_from_header.*[^ ]+", }} +// CHECK: !"0x2e\00extract_dwarf_data_from_header{{[^"]+}}", [[filehandle:![0-9]+]] // Second: Require that filehandle refer to the correct filename: // CHECK: [[filehandle]] = {{.*}}decl_should_be_here.hpp" typedef long unsigned int __darwin_size_t; diff --git a/test/CodeGenCXX/PR20038.cpp b/test/CodeGenCXX/PR20038.cpp index c24685d696b6..0936dfc64904 100644 --- a/test/CodeGenCXX/PR20038.cpp +++ b/test/CodeGenCXX/PR20038.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -triple %itanium_abi_triple -g -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -triple %itanium_abi_triple -g -mllvm -no-discriminators -emit-llvm %s -o - | FileCheck %s struct C { ~C(); @@ -8,9 +8,7 @@ extern bool b; // CHECK: call {{.*}}, !dbg [[DTOR_CALL2_LOC:![0-9]*]] // CHECK: [[FUN1:.*]] = {{.*}}; [ DW_TAG_subprogram ] {{.*}} [def] [fun1] // CHECK: [[FUN2:.*]] = {{.*}}; [ DW_TAG_subprogram ] {{.*}} [def] [fun2] -// CHECK: [[DTOR_CALL1_LOC]] = metadata !{i32 [[@LINE+2]], i32 0, metadata [[FUN1_BLOCK:.*]], null} -// CHECK: [[FUN1_BLOCK]] = metadata !{{{[^,]*}}, {{[^,]*}}, metadata [[FUN1]], +// CHECK: [[DTOR_CALL1_LOC]] = !MDLocation(line: [[@LINE+1]], scope: [[FUN1]]) void fun1() { b && (C(), 1); } -// CHECK: [[DTOR_CALL2_LOC]] = metadata !{i32 [[@LINE+2]], i32 0, metadata [[FUN2_BLOCK1:.*]], null} -// CHECK: [[FUN2_BLOCK1]] = metadata !{{{[^,]*}}, {{[^,]*}}, metadata [[FUN2]], +// CHECK: [[DTOR_CALL2_LOC]] = !MDLocation(line: [[@LINE+1]], scope: [[FUN2]]) bool fun2() { return (C(), b) && 0; } diff --git a/test/CodeGenCXX/align-avx-complete-objects.cpp b/test/CodeGenCXX/align-avx-complete-objects.cpp new file mode 100644 index 000000000000..25f4ef1099ac --- /dev/null +++ b/test/CodeGenCXX/align-avx-complete-objects.cpp @@ -0,0 +1,57 @@ +// RUN: %clang_cc1 -x c++ %s -O0 -triple=x86_64-apple-darwin -target-feature +avx2 -fmax-type-align=16 -emit-llvm -o - -Werror | FileCheck %s +// rdar://16254558 + +typedef float AVX2Float __attribute__((__vector_size__(32))); + + +volatile float TestAlign(void) +{ + volatile AVX2Float *p = new AVX2Float; + *p = *p; + AVX2Float r = *p; + return r[0]; +} + +// CHECK: [[R:%.*]] = alloca <8 x float>, align 32 +// CHECK-NEXT: [[CALL:%.*]] = call noalias 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>** [[P]], align 8 +// CHECK-NEXT: [[TWO:%.*]] = load volatile <8 x float>* [[ONE]], align 16 +// CHECK-NEXT: [[THREE:%.*]] = load <8 x float>** [[P]], align 8 +// CHECK-NEXT: store volatile <8 x float> [[TWO]], <8 x float>* [[THREE]], align 16 +// CHECK-NEXT: [[FOUR:%.*]] = load <8 x float>** [[P]], align 8 +// CHECK-NEXT: [[FIVE:%.*]] = load volatile <8 x float>* [[FOUR]], align 16 +// CHECK-NEXT: store <8 x float> [[FIVE]], <8 x float>* [[R]], align 32 +// CHECK-NEXT: [[SIX:%.*]] = load <8 x float>* [[R]], align 32 +// CHECK-NEXT: [[VECEXT:%.*]] = extractelement <8 x float> [[SIX]], i32 0 +// CHECK-NEXT: ret float [[VECEXT]] + +typedef float AVX2Float_Explicitly_aligned __attribute__((__vector_size__(32))) __attribute__((aligned (32))); + +typedef AVX2Float_Explicitly_aligned AVX2Float_indirect; + +typedef AVX2Float_indirect AVX2Float_use_existing_align; + +volatile float TestAlign2(void) +{ + volatile AVX2Float_use_existing_align *p = new AVX2Float_use_existing_align; + *p = *p; + AVX2Float_use_existing_align r = *p; + return r[0]; +} + +// CHECK: [[R:%.*]] = alloca <8 x float>, align 32 +// CHECK-NEXT: [[CALL:%.*]] = call noalias 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>** [[P]], align 8 +// CHECK-NEXT: [[TWO:%.*]] = load volatile <8 x float>* [[ONE]], align 32 +// CHECK-NEXT: [[THREE:%.*]] = load <8 x float>** [[P]], align 8 +// CHECK-NEXT: store volatile <8 x float> [[TWO]], <8 x float>* [[THREE]], align 32 +// CHECK-NEXT: [[FOUR:%.*]] = load <8 x float>** [[P]], align 8 +// CHECK-NEXT: [[FIVE:%.*]] = load volatile <8 x float>* [[FOUR]], align 32 +// CHECK-NEXT: store <8 x float> [[FIVE]], <8 x float>* [[R]], align 32 +// CHECK-NEXT: [[SIX:%.*]] = load <8 x float>* [[R]], align 32 +// CHECK-NEXT: [[VECEXT:%.*]] = extractelement <8 x float> [[SIX]], i32 0 +// CHECK-NEXT: ret float [[VECEXT]] diff --git a/test/CodeGenCXX/atomicinit.cpp b/test/CodeGenCXX/atomicinit.cpp index f453194468dd..982396e177ab 100644 --- a/test/CodeGenCXX/atomicinit.cpp +++ b/test/CodeGenCXX/atomicinit.cpp @@ -1,9 +1,13 @@ // RUN: %clang_cc1 %s -emit-llvm -O1 -o - -triple=i686-apple-darwin9 -std=c++11 | FileCheck %s -// CHECK-DAG: @_ZN7PR180978constant1aE = global {{.*}} { i16 1, i8 6, i8 undef }, align 4 -// CHECK-DAG: @_ZN7PR180978constant1bE = global {{.*}} { i16 2, i8 6, i8 undef }, align 4 -// CHECK-DAG: @_ZN7PR180978constant1cE = global {{.*}} { i16 3, i8 6, i8 undef }, align 4 -// CHECK-DAG: @_ZN7PR180978constant1yE = global {{.*}} { {{.*}} { i16 4, i8 6, i8 undef }, i32 5 }, align 4 +// CHECK-DAG: @PR22043 = 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 struct A { _Atomic(int) i; diff --git a/test/CodeGenCXX/attr-used.cpp b/test/CodeGenCXX/attr-used.cpp index 861734667357..d2a73f7d33e6 100644 --- a/test/CodeGenCXX/attr-used.cpp +++ b/test/CodeGenCXX/attr-used.cpp @@ -2,16 +2,16 @@ // <rdar://problem/8684363>: clang++ not respecting __attribute__((used)) on destructors struct X0 { - // CHECK: define linkonce_odr {{.*}} @_ZN2X0C1Ev + // CHECK-DAG: define linkonce_odr {{.*}} @_ZN2X0C1Ev __attribute__((used)) X0() {} - // CHECK: define linkonce_odr {{.*}} @_ZN2X0D1Ev + // CHECK-DAG: define linkonce_odr {{.*}} @_ZN2X0D1Ev __attribute__((used)) ~X0() {} }; // PR19743: not emitting __attribute__((used)) inline methods in nested classes. struct X1 { struct Nested { - // CHECK: define linkonce_odr {{.*}} @_ZN2X16Nested1fEv + // CHECK-DAG: define linkonce_odr {{.*}} @_ZN2X16Nested1fEv void __attribute__((used)) f() {} }; }; @@ -22,6 +22,6 @@ struct X2 { void __attribute__((used)) bar() { foo(); } void foo() { } - // CHECK: define linkonce_odr {{.*}} @_ZN2X23barEv - // CHECK: define linkonce_odr {{.*}} @_ZN2X23fooEv + // CHECK-DAG: define linkonce_odr {{.*}} @_ZN2X23barEv + // CHECK-DAG: define linkonce_odr {{.*}} @_ZN2X23fooEv }; diff --git a/test/CodeGenCXX/call-with-static-chain.cpp b/test/CodeGenCXX/call-with-static-chain.cpp new file mode 100644 index 000000000000..7cf929189f2c --- /dev/null +++ b/test/CodeGenCXX/call-with-static-chain.cpp @@ -0,0 +1,39 @@ +// RUN: %clang_cc1 -triple i386-unknown-unknown -emit-llvm -o - %s | FileCheck -check-prefix=CHECK32 %s +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm -o - %s | FileCheck -check-prefix=CHECK64 %s + +struct A { + long x, y; +}; + +struct B { + long x, y, z, w; +}; + +extern "C" { + +int f1(A, A, A, A); +B f2(void); +_Complex float f3(void); +A &f4(); + +} + +void test() { + A a; + + // CHECK32: call i32 bitcast (i32 (%struct.A*, %struct.A*, %struct.A*, %struct.A*)* @f1 to i32 (i8*, %struct.A*, %struct.A*, %struct.A*, %struct.A*)*)(i8* nest bitcast (i32 (%struct.A*, %struct.A*, %struct.A*, %struct.A*)* @f1 to i8*) + // CHECK64: call i32 bitcast (i32 (i64, i64, i64, i64, i64, i64, %struct.A*)* @f1 to i32 (i8*, i64, i64, i64, i64, i64, i64, %struct.A*)*)(i8* nest bitcast (i32 (i64, i64, i64, i64, i64, i64, %struct.A*)* @f1 to i8*) + __builtin_call_with_static_chain(f1(a, a, a, a), f1); + + // CHECK32: call void bitcast (void (%struct.B*)* @f2 to void (%struct.B*, i8*)*)(%struct.B* sret %{{[0-9a-z]+}}, i8* nest bitcast (void (%struct.B*)* @f2 to i8*)) + // CHECK64: call void bitcast (void (%struct.B*)* @f2 to void (%struct.B*, i8*)*)(%struct.B* sret %{{[0-9a-z]+}}, i8* nest bitcast (void (%struct.B*)* @f2 to i8*)) + __builtin_call_with_static_chain(f2(), f2); + + // CHECK32: call i64 bitcast (i64 ()* @f3 to i64 (i8*)*)(i8* nest bitcast (i64 ()* @f3 to i8*)) + // CHECK64: call <2 x float> bitcast (<2 x float> ()* @f3 to <2 x float> (i8*)*)(i8* nest bitcast (<2 x float> ()* @f3 to i8*)) + __builtin_call_with_static_chain(f3(), f3); + + // CHECK32: call dereferenceable(8) %struct.A* bitcast (%struct.A* ()* @f4 to %struct.A* (i8*)*)(i8* nest bitcast (%struct.A* ()* @f4 to i8*)) + // CHECK64: call dereferenceable(16) %struct.A* bitcast (%struct.A* ()* @f4 to %struct.A* (i8*)*)(i8* nest bitcast (%struct.A* ()* @f4 to i8*)) + __builtin_call_with_static_chain(f4(), f4); +} diff --git a/test/CodeGenCXX/catch-undef-behavior.cpp b/test/CodeGenCXX/catch-undef-behavior.cpp index 333855d0ba61..4120d0fead4d 100644 --- a/test/CodeGenCXX/catch-undef-behavior.cpp +++ b/test/CodeGenCXX/catch-undef-behavior.cpp @@ -1,6 +1,6 @@ -// RUN: %clang_cc1 -std=c++11 -fsanitize=signed-integer-overflow,integer-divide-by-zero,float-divide-by-zero,shift,unreachable,return,vla-bound,alignment,null,vptr,object-size,float-cast-overflow,bool,enum,array-bounds,function -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -// RUN: %clang_cc1 -std=c++11 -fsanitize=vptr,address -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s --check-prefix=CHECK-ASAN -// RUN: %clang_cc1 -std=c++11 -fsanitize=vptr -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s --check-prefix=DOWNCAST-NULL +// RUN: %clang_cc1 -std=c++11 -fsanitize=signed-integer-overflow,integer-divide-by-zero,float-divide-by-zero,shift,unreachable,return,vla-bound,alignment,null,vptr,object-size,float-cast-overflow,bool,enum,array-bounds,function -fsanitize-recover=signed-integer-overflow,integer-divide-by-zero,float-divide-by-zero,shift,vla-bound,alignment,null,vptr,object-size,float-cast-overflow,bool,enum,array-bounds,function -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s +// RUN: %clang_cc1 -std=c++11 -fsanitize=vptr,address -fsanitize-recover=vptr,address -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s --check-prefix=CHECK-ASAN +// RUN: %clang_cc1 -std=c++11 -fsanitize=vptr -fsanitize-recover=vptr -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s --check-prefix=DOWNCAST-NULL struct S { double d; @@ -221,11 +221,14 @@ void bad_downcast_pointer(S *p) { void bad_downcast_reference(S &p) { // CHECK: %[[E1:.*]] = icmp ne {{.*}}, null // CHECK-NOT: br i1 + // CHECK: %[[SIZE:.*]] = call i64 @llvm.objectsize.i64.p0i8( // CHECK: %[[E2:.*]] = icmp uge i64 %[[SIZE]], 24 - // CHECK: %[[E12:.*]] = and i1 %[[E1]], %[[E2]] + // CHECK: %[[MISALIGN:.*]] = and i64 %{{.*}}, 7 // CHECK: %[[E3:.*]] = icmp eq i64 %[[MISALIGN]], 0 + + // CHECK: %[[E12:.*]] = and i1 %[[E1]], %[[E2]] // CHECK: %[[E123:.*]] = and i1 %[[E12]], %[[E3]] // CHECK: br i1 %[[E123]], @@ -382,11 +385,11 @@ void downcast_reference(B &b) { // CHECK-NEXT: [[MASKED:%[0-9]*]] = and i64 [[C_INT]], 15 // CHECK-NEXT: [[TEST:%[0-9]*]] = icmp eq i64 [[MASKED]], 0 // AND the alignment test with the objectsize test. - // CHECK-NEXT: [[AND:%[0-9]*]] = and i1 {{.*}}, [[TEST]] + // CHECK: [[AND:%[0-9]*]] = and i1 {{.*}}, [[TEST]] // CHECK-NEXT: br i1 [[AND]] } -// CHECK-LABEL: @_Z22indirect_function_callPFviE({{.*}} prefix <{ i32, i8* }> <{ i32 1413876459, i8* bitcast ({ i8*, i8* }* @_ZTIFvPFviEE to i8*) }> +// CHECK-LABEL: @_Z22indirect_function_callPFviE({{.*}} prologue <{ i32, i8* }> <{ i32 1413876459, i8* bitcast ({ i8*, i8* }* @_ZTIFvPFviEE to i8*) }> void indirect_function_call(void (*p)(int)) { // CHECK: [[PTR:%[0-9]*]] = bitcast void (i32)* {{.*}} to <{ i32, i8* }>* @@ -404,6 +407,40 @@ void indirect_function_call(void (*p)(int)) { p(42); } +namespace UpcastPointerTest { +struct S {}; +struct T : S { double d; }; +struct V : virtual S {}; + +// CHECK-LABEL: upcast_pointer +S* upcast_pointer(T* t) { + // Check for null pointer + // CHECK: %[[NONNULL:.*]] = icmp ne {{.*}}, null + // CHECK: br i1 %[[NONNULL]] + + // Check alignment + // CHECK: %[[MISALIGN:.*]] = and i64 %{{.*}}, 7 + // CHECK: icmp eq i64 %[[MISALIGN]], 0 + + // CHECK: call void @__ubsan_handle_type_mismatch + return t; +} + +V getV(); + +// CHECK-LABEL: upcast_to_vbase +void upcast_to_vbase() { + // No need to check for null here, as we have a temporary here. + + // CHECK-NOT: br i1 + + // CHECK: call i64 @llvm.objectsize + // CHECK: call void @__ubsan_handle_type_mismatch + // CHECK: call void @__ubsan_handle_dynamic_type_cache_miss + const S& s = getV(); +} +} + namespace CopyValueRepresentation { // CHECK-LABEL: define {{.*}} @_ZN23CopyValueRepresentation2S3aSERKS0_ // CHECK-NOT: call {{.*}} @__ubsan_handle_load_invalid_value diff --git a/test/CodeGenCXX/class-layout.cpp b/test/CodeGenCXX/class-layout.cpp index d7d84a86abad..610dbc5feaaf 100644 --- a/test/CodeGenCXX/class-layout.cpp +++ b/test/CodeGenCXX/class-layout.cpp @@ -14,7 +14,7 @@ namespace Test2 { namespace Test3 { // C should have a vtable pointer. - // CHECK: %"struct.Test3::A" = type { i32 (...)**, i32 } + // CHECK: %"struct.Test3::A" = type <{ i32 (...)**, i32, [4 x i8] }> struct A { virtual void f(); int a; } *a; } diff --git a/test/CodeGenCXX/compound-literals.cpp b/test/CodeGenCXX/compound-literals.cpp index f1d88027c4fa..e7710939bd2d 100644 --- a/test/CodeGenCXX/compound-literals.cpp +++ b/test/CodeGenCXX/compound-literals.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -triple armv7-none-eabi -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -std=c++11 -triple armv7-none-eabi -emit-llvm -o - %s | FileCheck %s struct X { X(); @@ -42,3 +42,16 @@ struct Z { int i[3]; }; int *p = (Z){ {1, 2, 3} }.i; // CHECK: define {{.*}}__cxx_global_var_init() // CHECK: store i32* getelementptr inbounds (%struct.Z* @.compoundliteral, i32 0, i32 0, i32 0), i32** @p + + +int *PR21912_1 = (int []){}; +// CHECK-LABEL: define {{.*}}__cxx_global_var_init1() +// CHECK: store i32* getelementptr inbounds ([0 x i32]* @.compoundliteral2, i32 0, i32 0), i32** @PR21912_1 + +union PR21912Ty { + long long l; + double d; +}; +union PR21912Ty *PR21912_2 = (union PR21912Ty[]){{.d = 2.0}, {.l = 3}}; +// CHECK-LABEL: define {{.*}}__cxx_global_var_init3() +// CHECK: store %union.PR21912Ty* getelementptr inbounds ([2 x %union.PR21912Ty]* bitcast (<{ { double }, %union.PR21912Ty }>* @.compoundliteral4 to [2 x %union.PR21912Ty]*), i32 0, i32 0), %union.PR21912Ty** @PR21912_2 diff --git a/test/CodeGenCXX/constructor-destructor-return-this.cpp b/test/CodeGenCXX/constructor-destructor-return-this.cpp index ce6ddd29f644..dcd20fe87d6f 100644 --- a/test/CodeGenCXX/constructor-destructor-return-this.cpp +++ b/test/CodeGenCXX/constructor-destructor-return-this.cpp @@ -10,7 +10,7 @@ class A { public: A(); - ~A(); + virtual ~A(); private: int x_; @@ -19,7 +19,7 @@ private: class B : public A { public: B(int *i); - ~B(); + virtual ~B(); private: int *i_; @@ -44,7 +44,7 @@ B::~B() { } // CHECKIOS5-LABEL: define %class.B* @_ZN1BD1Ev(%class.B* %this) // CHECKMS-LABEL: define x86_thiscallcc %class.B* @"\01??0B@@QAE@PAH@Z"(%class.B* returned %this, i32* %i) -// CHECKMS-LABEL: define x86_thiscallcc void @"\01??1B@@QAE@XZ"(%class.B* %this) +// CHECKMS-LABEL: define x86_thiscallcc void @"\01??1B@@UAE@XZ"(%class.B* %this) class C : public A, public B { public: @@ -61,19 +61,25 @@ C::~C() { } // CHECKGEN-LABEL: define void @_ZN1CC1EPiPc(%class.C* %this, i32* %i, i8* %c) // CHECKGEN-LABEL: define void @_ZN1CD2Ev(%class.C* %this) // CHECKGEN-LABEL: define void @_ZN1CD1Ev(%class.C* %this) +// CHECKGEN-LABEL: define void @_ZThn8_N1CD1Ev(%class.C* %this) // CHECKGEN-LABEL: define void @_ZN1CD0Ev(%class.C* %this) +// CHECKGEN-LABEL: define void @_ZThn8_N1CD0Ev(%class.C* %this) // CHECKARM-LABEL: define %class.C* @_ZN1CC2EPiPc(%class.C* returned %this, i32* %i, i8* %c) // CHECKARM-LABEL: define %class.C* @_ZN1CC1EPiPc(%class.C* returned %this, i32* %i, i8* %c) // CHECKARM-LABEL: define %class.C* @_ZN1CD2Ev(%class.C* returned %this) // CHECKARM-LABEL: define %class.C* @_ZN1CD1Ev(%class.C* returned %this) +// CHECKARM-LABEL: define %class.C* @_ZThn8_N1CD1Ev(%class.C* %this) // CHECKARM-LABEL: define void @_ZN1CD0Ev(%class.C* %this) +// CHECKARM-LABEL: define void @_ZThn8_N1CD0Ev(%class.C* %this) // CHECKIOS5-LABEL: define %class.C* @_ZN1CC2EPiPc(%class.C* %this, i32* %i, i8* %c) // CHECKIOS5-LABEL: define %class.C* @_ZN1CC1EPiPc(%class.C* %this, i32* %i, i8* %c) // CHECKIOS5-LABEL: define %class.C* @_ZN1CD2Ev(%class.C* %this) // CHECKIOS5-LABEL: define %class.C* @_ZN1CD1Ev(%class.C* %this) +// CHECKIOS5-LABEL: define %class.C* @_ZThn8_N1CD1Ev(%class.C* %this) // CHECKIOS5-LABEL: define void @_ZN1CD0Ev(%class.C* %this) +// CHECKIOS5-LABEL: define void @_ZThn8_N1CD0Ev(%class.C* %this) // CHECKMS-LABEL: define x86_thiscallcc %class.C* @"\01??0C@@QAE@PAHPAD@Z"(%class.C* returned %this, i32* %i, i8* %c) // CHECKMS-LABEL: define x86_thiscallcc void @"\01??1C@@UAE@XZ"(%class.C* %this) @@ -103,7 +109,7 @@ D::~D() { } // CHECKIOS5-LABEL: define %class.D* @_ZN1DD1Ev(%class.D* %this) // CHECKMS-LABEL: define x86_thiscallcc %class.D* @"\01??0D@@QAE@XZ"(%class.D* returned %this, i32 %is_most_derived) -// CHECKMS-LABEL: define x86_thiscallcc void @"\01??1D@@QAE@XZ"(%class.D* %this) +// CHECKMS-LABEL: define x86_thiscallcc void @"\01??1D@@UAE@XZ"(%class.D*) class E { public: diff --git a/test/CodeGenCXX/constructor-init.cpp b/test/CodeGenCXX/constructor-init.cpp index a8f483e53ab5..9d029a3696b2 100644 --- a/test/CodeGenCXX/constructor-init.cpp +++ b/test/CodeGenCXX/constructor-init.cpp @@ -94,23 +94,23 @@ namespace InitVTable { }; // CHECK-LABEL: define void @_ZN10InitVTable1BC2Ev(%"struct.InitVTable::B"* %this) unnamed_addr - // CHECK: [[T0:%.*]] = bitcast [[B:%.*]]* [[THIS:%.*]] to i8*** - // CHECK-NEXT: store i8** getelementptr inbounds ([3 x i8*]* @_ZTVN10InitVTable1BE, i64 0, i64 2), i8*** [[T0]] + // CHECK: [[T0:%.*]] = bitcast [[B:%.*]]* [[THIS:%.*]] to i32 (...)*** + // CHECK-NEXT: store i32 (...)** bitcast (i8** getelementptr inbounds ([3 x i8*]* @_ZTVN10InitVTable1BE, i64 0, i64 2) to i32 (...)**), i32 (...)*** [[T0]] // CHECK: [[VTBL:%.*]] = load i32 ([[B]]*)*** {{%.*}} // CHECK-NEXT: [[FNP:%.*]] = getelementptr inbounds i32 ([[B]]*)** [[VTBL]], i64 0 // CHECK-NEXT: [[FN:%.*]] = load i32 ([[B]]*)** [[FNP]] // CHECK-NEXT: [[ARG:%.*]] = call i32 [[FN]]([[B]]* [[THIS]]) // CHECK-NEXT: call void @_ZN10InitVTable1AC2Ei({{.*}}* {{%.*}}, i32 [[ARG]]) - // CHECK-NEXT: [[T0:%.*]] = bitcast [[B]]* [[THIS]] to i8*** - // CHECK-NEXT: store i8** getelementptr inbounds ([3 x i8*]* @_ZTVN10InitVTable1BE, i64 0, i64 2), i8*** [[T0]] + // CHECK-NEXT: [[T0:%.*]] = bitcast [[B]]* [[THIS]] to i32 (...)*** + // CHECK-NEXT: store i32 (...)** bitcast (i8** getelementptr inbounds ([3 x i8*]* @_ZTVN10InitVTable1BE, i64 0, i64 2) to i32 (...)**), i32 (...)*** [[T0]] // CHECK-NEXT: ret void B::B() : A(foo()) {} // CHECK-LABEL: define void @_ZN10InitVTable1BC2Ei(%"struct.InitVTable::B"* %this, i32 %x) unnamed_addr // CHECK: [[ARG:%.*]] = add nsw i32 {{%.*}}, 5 // CHECK-NEXT: call void @_ZN10InitVTable1AC2Ei({{.*}}* {{%.*}}, i32 [[ARG]]) - // CHECK-NEXT: [[T0:%.*]] = bitcast [[B]]* {{%.*}} to i8*** - // CHECK-NEXT: store i8** getelementptr inbounds ([3 x i8*]* @_ZTVN10InitVTable1BE, i64 0, i64 2), i8*** [[T0]] + // CHECK-NEXT: [[T0:%.*]] = bitcast [[B]]* {{%.*}} to i32 (...)*** + // CHECK-NEXT: store i32 (...)** bitcast (i8** getelementptr inbounds ([3 x i8*]* @_ZTVN10InitVTable1BE, i64 0, i64 2) to i32 (...)**), i32 (...)*** [[T0]] // CHECK-NEXT: ret void B::B(int x) : A(x + 5) {} } diff --git a/test/CodeGenCXX/copy-constructor-synthesis-2.cpp b/test/CodeGenCXX/copy-constructor-synthesis-2.cpp index 4bb0fee25e51..8fdc4dff7feb 100644 --- a/test/CodeGenCXX/copy-constructor-synthesis-2.cpp +++ b/test/CodeGenCXX/copy-constructor-synthesis-2.cpp @@ -4,4 +4,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 i8** getelementptr inbounds ([3 x i8*]* @_ZTV1A, i64 0, i64 2) +// CHECK: store i32 (...)** bitcast (i8** getelementptr inbounds ([3 x i8*]* @_ZTV1A, i64 0, i64 2) to i32 (...)**) diff --git a/test/CodeGenCXX/copy-constructor-synthesis.cpp b/test/CodeGenCXX/copy-constructor-synthesis.cpp index 47f8e131d62e..abbb7d05351e 100644 --- a/test/CodeGenCXX/copy-constructor-synthesis.cpp +++ b/test/CodeGenCXX/copy-constructor-synthesis.cpp @@ -148,8 +148,8 @@ void f(B b1) { // CHECK-LABEL: define linkonce_odr void @_ZN12rdar138169401AC2ERKS0_( // CHECK: [[THIS:%.*]] = load [[A]]** -// CHECK-NEXT: [[T0:%.*]] = bitcast [[A]]* [[THIS]] to i8*** -// CHECK-NEXT: store i8** getelementptr inbounds ([4 x i8*]* @_ZTVN12rdar138169401AE, i64 0, i64 2), i8*** [[T0]] +// CHECK-NEXT: [[T0:%.*]] = bitcast [[A]]* [[THIS]] to i32 (...)*** +// CHECK-NEXT: store i32 (...)** bitcast (i8** getelementptr inbounds ([4 x i8*]* @_ZTVN12rdar138169401AE, i64 0, i64 2) to i32 (...)**), i32 (...)*** [[T0]] // CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[A]]* [[THIS]], i32 0, i32 1 // CHECK-NEXT: [[OTHER:%.*]] = load [[A]]** // CHECK-NEXT: [[T2:%.*]] = getelementptr inbounds [[A]]* [[OTHER]], i32 0, i32 1 diff --git a/test/CodeGenCXX/coverage.cpp b/test/CodeGenCXX/coverage.cpp index 88f74098efa8..3931b0c6ffb3 100644 --- a/test/CodeGenCXX/coverage.cpp +++ b/test/CodeGenCXX/coverage.cpp @@ -3,5 +3,5 @@ extern "C" void test_name1() {} void test_name2() {} -// CHECK: metadata !"test_name1", metadata !"test_name1", metadata !"",{{.*}}DW_TAG_subprogram -// CHECK: metadata !"test_name2", metadata !"test_name2", metadata !"_Z10test_name2v",{{.*}}DW_TAG_subprogram +// CHECK: !"0x2e\00test_name1\00test_name1\00\00{{[^,]+}}", {{.*}} DW_TAG_subprogram +// CHECK: !"0x2e\00test_name2\00test_name2\00_Z10test_name2v\00{{[^,]+}}", {{.*}} DW_TAG_subprogram diff --git a/test/CodeGenCXX/crash.cpp b/test/CodeGenCXX/crash.cpp index 073542dd15b0..e1577a3abe37 100644 --- a/test/CodeGenCXX/crash.cpp +++ b/test/CodeGenCXX/crash.cpp @@ -1,4 +1,5 @@ // RUN: %clang_cc1 %s -std=c++11 -emit-llvm-only +// RUN: %clang_cc1 -emit-obj -o %t -gline-tables-only -std=c++11 %s // CHECK that we don't crash. // PR11676's example is ill-formed: @@ -33,3 +34,13 @@ template <class ELFT> void finalizeDefaultAtomValues() { void f() { finalizeDefaultAtomValues<int>(); } } + +namespace PR22096 { +template <class> struct c { + c(); + template <class U> __attribute__((__always_inline__)) c(c<U>) {} +}; +struct { + c<double> v = c<int>(); +} o; +} diff --git a/test/CodeGenCXX/ctor-dtor-alias.cpp b/test/CodeGenCXX/ctor-dtor-alias.cpp index d869a2bfd5d9..bd60cb88bb25 100644 --- a/test/CodeGenCXX/ctor-dtor-alias.cpp +++ b/test/CodeGenCXX/ctor-dtor-alias.cpp @@ -1,20 +1,33 @@ -// RUN: %clang_cc1 %s -triple i686-linux -emit-llvm -o - -mconstructor-aliases -O1 -disable-llvm-optzns | FileCheck %s // RUN: %clang_cc1 %s -triple i686-linux -emit-llvm -o - -mconstructor-aliases | FileCheck --check-prefix=NOOPT %s -// RUN: %clang_cc1 -triple x86_64--netbsd -emit-llvm \ -// RUN: -mconstructor-aliases -O2 %s -o - | FileCheck --check-prefix=CHECK-RAUW %s +// RUN: %clang_cc1 %s -triple i686-linux -emit-llvm -o - -mconstructor-aliases -O1 -disable-llvm-optzns > %t +// RUN: FileCheck --check-prefix=CHECK1 --input-file=%t %s +// RUN: FileCheck --check-prefix=CHECK2 --input-file=%t %s +// 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: FileCheck --check-prefix=CHECK6 --input-file=%t %s + +// RUN: %clang_cc1 %s -triple i686-pc-windows-gnu -emit-llvm -o - -mconstructor-aliases -O1 -disable-llvm-optzns | FileCheck --check-prefix=COFF %s namespace test1 { -// test that we don't produce an alias when the destructor is weak_odr. The -// reason to avoid it that another TU might have no explicit template -// instantiation definition or declaration, causing it to to output only -// one of the destructors as linkonce_odr, producing a different comdat. +// Test that we produce the apropriate comdats when creating aliases to +// weak_odr constructors and destructors. -// CHECK-DAG: define weak_odr void @_ZN5test16foobarIvEC2Ev -// CHECK-DAG: define weak_odr void @_ZN5test16foobarIvEC1Ev +// CHECK1: @_ZN5test16foobarIvEC1Ev = weak_odr alias void {{.*}} @_ZN5test16foobarIvEC2Ev +// CHECK1: @_ZN5test16foobarIvED1Ev = weak_odr alias void (%"struct.test1::foobar"*)* @_ZN5test16foobarIvED2Ev +// CHECK1: define weak_odr void @_ZN5test16foobarIvEC2Ev({{.*}} comdat($_ZN5test16foobarIvEC5Ev) +// CHECK1: define weak_odr void @_ZN5test16foobarIvED2Ev({{.*}} comdat($_ZN5test16foobarIvED5Ev) +// CHECK1: define weak_odr void @_ZN5test16foobarIvED0Ev({{.*}} comdat($_ZN5test16foobarIvED5Ev) +// CHECK1-NOT: comdat -template <typename T> struct foobar { +// COFF doesn't support comdats with arbitrary names (C5/D5). +// COFF-NOT: comdat + +template <typename T> +struct foobar { foobar() {} + virtual ~foobar() {} }; template struct foobar<void>; @@ -24,8 +37,9 @@ namespace test2 { // test that when the destrucor is linkonce_odr we just replace every use of // C1 with C2. -// CHECK-DAG: define linkonce_odr void @_ZN5test26foobarIvEC2Ev( -// CHECK-DAG: call void @_ZN5test26foobarIvEC2Ev +// CHECK1: define internal void @__cxx_global_var_init() +// CHECK1: call void @_ZN5test26foobarIvEC2Ev +// CHECK1: define linkonce_odr void @_ZN5test26foobarIvEC2Ev( void g(); template <typename T> struct foobar { foobar() { g(); } @@ -37,8 +51,9 @@ namespace test3 { // test that instead of an internal alias we just use the other destructor // directly. -// CHECK-DAG: define internal void @_ZN5test312_GLOBAL__N_11AD2Ev( -// CHECK-DAG: call i32 @__cxa_atexit{{.*}}_ZN5test312_GLOBAL__N_11AD2Ev +// CHECK1: define internal void @__cxx_global_var_init1() +// CHECK1: call i32 @__cxa_atexit{{.*}}_ZN5test312_GLOBAL__N_11AD2Ev +// CHECK1: define internal void @_ZN5test312_GLOBAL__N_11AD2Ev( namespace { struct A { ~A() {} @@ -55,13 +70,15 @@ namespace test4 { // guarantee that they will be present in every TU. Instead, we just call // A's destructor directly. - // CHECK-DAG: define linkonce_odr void @_ZN5test41AD2Ev( - // CHECK-DAG: call i32 @__cxa_atexit{{.*}}_ZN5test41AD2Ev + // CHECK1: define internal void @__cxx_global_var_init2() + // CHECK1: call i32 @__cxa_atexit{{.*}}_ZN5test41AD2Ev + // CHECK1: define linkonce_odr void @_ZN5test41AD2Ev( // test that we don't do this optimization at -O0 so that the debugger can // see both destructors. - // NOOPT-DAG: call i32 @__cxa_atexit{{.*}}@_ZN5test41BD2Ev - // NOOPT-DAG: define linkonce_odr void @_ZN5test41BD2Ev + // NOOPT: define internal void @__cxx_global_var_init2() + // NOOPT: call i32 @__cxa_atexit{{.*}}@_ZN5test41BD2Ev + // NOOPT: define linkonce_odr void @_ZN5test41BD2Ev struct A { virtual ~A() {} }; @@ -74,8 +91,9 @@ namespace test4 { namespace test5 { // similar to test4, but with an internal B. - // CHECK-DAG: define linkonce_odr void @_ZN5test51AD2Ev( - // CHECK-DAG: call i32 @__cxa_atexit{{.*}}_ZN5test51AD2Ev + // CHECK2: define internal void @__cxx_global_var_init3() + // CHECK2: call i32 @__cxa_atexit{{.*}}_ZN5test51AD2Ev + // CHECK2: define linkonce_odr void @_ZN5test51AD2Ev( struct A { virtual ~A() {} }; @@ -99,14 +117,15 @@ namespace test6 { }; } B X; - // CHECK-DAG: call i32 @__cxa_atexit({{.*}}@_ZN5test61AD2Ev + // CHECK3: define internal void @__cxx_global_var_init4() + // CHECK3: call i32 @__cxa_atexit({{.*}}@_ZN5test61AD2Ev } namespace test7 { // Test that we don't produce an alias from ~B to ~A<int> (or crash figuring // out if we should). // pr17875. - // CHECK-DAG: define void @_ZN5test71BD2Ev + // CHECK3: define void @_ZN5test71BD2Ev template <typename> struct A { ~A() {} }; @@ -119,8 +138,9 @@ namespace test7 { namespace test8 { // Test that we replace ~zed with ~bar which is an alias to ~foo. - // CHECK-DAG: call i32 @__cxa_atexit({{.*}}@_ZN5test83barD2Ev - // CHECK-DAG: @_ZN5test83barD2Ev = alias {{.*}} @_ZN5test83fooD2Ev + // CHECK4: @_ZN5test83barD2Ev = alias {{.*}} @_ZN5test83fooD2Ev + // CHECK4: define internal void @__cxx_global_var_init5() + // CHECK4: call i32 @__cxa_atexit({{.*}}@_ZN5test83barD2Ev struct foo { ~foo(); }; @@ -144,12 +164,12 @@ struct bar : public foo {}; void zed() { // Test that we produce a call to bar's destructor. We used to call foo's, but // it has a different calling conversion. - // CHECK-DAG: call void @_ZN5test93barD2Ev + // CHECK4: call void @_ZN5test93barD2Ev bar ptr; } } -// CHECK-RAUW: @_ZTV1C = linkonce_odr unnamed_addr constant [4 x i8*] [{{[^@]*}}@_ZTI1C {{[^@]*}}@_ZN1CD2Ev {{[^@]*}}@_ZN1CD0Ev {{[^@]*}}] +// CHECK5: @_ZTV1C = linkonce_odr unnamed_addr constant [4 x i8*] [{{[^@]*}}@_ZTI1C {{[^@]*}}@_ZN1CD2Ev {{[^@]*}}@_ZN1CD0Ev {{[^@]*}}] // r194296 replaced C::~C with B::~B without emitting the later. class A { @@ -177,3 +197,38 @@ void fn1() { new C; } + +namespace test10 { +// Test that if a destructor is in a comdat, we don't try to emit is as an +// alias to a base class destructor. +struct bar { + ~bar(); +}; +bar::~bar() { +} +} // closing the namespace causes ~bar to be sent to CodeGen +namespace test10 { +template <typename T> +struct foo : public bar { + ~foo(); +}; +template <typename T> +foo<T>::~foo() {} +template class foo<int>; +// CHECK5: define weak_odr void @_ZN6test103fooIiED2Ev({{.*}} comdat($_ZN6test103fooIiED5Ev) +} + +namespace test11 { +// Test that when we don't have to worry about COMDATs we produce an alias +// from complate to base and from base to base class base. +struct bar { + ~bar(); +}; +bar::~bar() {} +struct foo : public bar { + ~foo(); +}; +foo::~foo() {} +// CHECK6: @_ZN6test113fooD2Ev = alias {{.*}} @_ZN6test113barD2Ev +// CHECK6: @_ZN6test113fooD1Ev = alias {{.*}} @_ZN6test113fooD2Ev +} diff --git a/test/CodeGenCXX/ctor-globalopt.cpp b/test/CodeGenCXX/ctor-globalopt.cpp new file mode 100644 index 000000000000..672fc9067527 --- /dev/null +++ b/test/CodeGenCXX/ctor-globalopt.cpp @@ -0,0 +1,28 @@ +// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm -o - %s -O1 | FileCheck %s --check-prefix=O1 +// RUN: %clang_cc1 -triple %ms_abi_triple -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple %ms_abi_triple -emit-llvm -o - %s -O1 | FileCheck %s --check-prefix=O1 + +// Check that GlobalOpt can eliminate static constructors for simple implicit +// constructors. This is a targetted integration test to make sure that LLVM's +// optimizers are able to process Clang's IR. GlobalOpt in particular is +// sensitive to the casts we emit. + +// CHECK: @llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] +// CHECK: [{ i32, void ()*, i8* } { i32 65535, void ()* @_GLOBAL__sub_I_ctor_globalopt.cpp, i8* null }] + +// CHECK-LABEL: define internal void @_GLOBAL__sub_I_ctor_globalopt.cpp() +// CHECK: call void @ +// CHECK-NOT: call + +// O1: @llvm.global_ctors = appending global [0 x { i32, void ()*, i8* }] zeroinitializer + +struct A { + virtual void f(); + int a; +}; +struct B : virtual A { + virtual void g(); + int b; +}; +B b; diff --git a/test/CodeGenCXX/cxx11-exception-spec.cpp b/test/CodeGenCXX/cxx11-exception-spec.cpp index 3b1516b92536..3fb5c15c2ab5 100644 --- a/test/CodeGenCXX/cxx11-exception-spec.cpp +++ b/test/CodeGenCXX/cxx11-exception-spec.cpp @@ -22,9 +22,9 @@ template<> void S<short>::f() { h(); } // CHECK: define {{.*}} @_ZN1SIA2_sE1fEv() [[NUW]] template<> void S<short[2]>::f() noexcept { h(); } -// CHECK: define {{.*}} @_Z1fIDsEvv() [[NONE]] { +// CHECK: define {{.*}} @_Z1fIDsEvv() [[NONE]] comdat { template void f<char16_t>(); -// CHECK: define {{.*}} @_Z1fIA2_DsEvv() [[NUW]] { +// CHECK: define {{.*}} @_Z1fIA2_DsEvv() [[NUW]] comdat { template void f<char16_t[2]>(); // CHECK: define {{.*}} @_ZN1SIDsE1fEv() @@ -34,9 +34,9 @@ template void S<char16_t>::f(); template void S<char16_t[2]>::f(); void h() { - // CHECK: define {{.*}} @_Z1fIiEvv() [[NUW]] { + // CHECK: define {{.*}} @_Z1fIiEvv() [[NUW]] comdat { f<int>(); - // CHECK: define {{.*}} @_Z1fIA2_iEvv() [[NONE]] { + // CHECK: define {{.*}} @_Z1fIA2_iEvv() [[NONE]] comdat { f<int[2]>(); // CHECK: define {{.*}} @_ZN1SIiE1fEv() [[NUW]] @@ -45,9 +45,9 @@ void h() { // CHECK-NOT: [[NUW]] S<int[2]>::f(); - // CHECK: define {{.*}} @_Z1fIfEvv() [[NUW]] { + // CHECK: define {{.*}} @_Z1fIfEvv() [[NUW]] comdat { void (*f1)() = &f<float>; - // CHECK: define {{.*}} @_Z1fIdEvv() [[NONE]] { + // CHECK: define {{.*}} @_Z1fIdEvv() [[NONE]] comdat { void (*f2)() = &f<double>; // CHECK: define {{.*}} @_ZN1SIfE1fEv() [[NUW]] @@ -56,9 +56,9 @@ void h() { // CHECK-NOT: [[NUW]] void (*f4)() = &S<double>::f; - // CHECK: define {{.*}} @_Z1fIA4_cEvv() [[NUW]] { + // CHECK: define {{.*}} @_Z1fIA4_cEvv() [[NUW]] comdat { (void)&f<char[4]>; - // CHECK: define {{.*}} @_Z1fIcEvv() [[NONE]] { + // CHECK: define {{.*}} @_Z1fIcEvv() [[NONE]] comdat { (void)&f<char>; // CHECK: define {{.*}} @_ZN1SIA4_cE1fEv() [[NUW]] @@ -122,3 +122,8 @@ void j() { // CHECK: attributes [[NONE]] = { {{.*}} } // CHECK: attributes [[NUW]] = { nounwind{{.*}} } + +namespace PR19190 { +template <class T> struct DWFIterator { virtual void get() throw(int) = 0; }; +void foo(DWFIterator<int> *foo) { foo->get(); } +} diff --git a/test/CodeGenCXX/cxx11-special-members.cpp b/test/CodeGenCXX/cxx11-special-members.cpp index 59461f9e2f4b..037e59a6408f 100644 --- a/test/CodeGenCXX/cxx11-special-members.cpp +++ b/test/CodeGenCXX/cxx11-special-members.cpp @@ -28,5 +28,19 @@ void f2(B &x, B &y) { // CHECK: define {{.*}} @_ZN1BaSEOS_( // CHECK: call {{.*}} @_ZN1AaSERKS_( +// rdar://18309639 { +template<int> struct C { C() = default; }; +struct D { + C<0> c; + D() { } +}; +template struct C<0>; // was asserting +void f3() { + C<0> a; + D b; +} +// CHECK: define {{.*}} @_ZN1CILi0EEC1Ev +// CHECK: define {{.*}} @_ZN1DC1Ev + // CHECK: define {{.*}} @_ZN1BC2EOS_( // CHECK: call {{.*}} @_ZN1AC1ERKS_( diff --git a/test/CodeGenCXX/cxx11-thread-local.cpp b/test/CodeGenCXX/cxx11-thread-local.cpp index a3690b352989..a6f010626cad 100644 --- a/test/CodeGenCXX/cxx11-thread-local.cpp +++ b/test/CodeGenCXX/cxx11-thread-local.cpp @@ -44,9 +44,9 @@ int e = V<int>::m; // CHECK: @llvm.global_ctors = appending global {{.*}} @[[GLOBAL_INIT:[^ ]*]] // CHECK: @_ZTH1a = alias void ()* @__tls_init -// CHECK: @_ZTHL1d = alias internal void ()* @__tls_init +// CHECK: @_ZTHL1d = internal alias void ()* @__tls_init // CHECK: @_ZTHN1U1mE = alias void ()* @__tls_init -// CHECK: @_ZTHN1VIiE1mE = alias linkonce_odr void ()* @__tls_init +// CHECK: @_ZTHN1VIiE1mE = linkonce_odr alias void ()* @__tls_init // Individual variable initialization functions: diff --git a/test/CodeGenCXX/cxx1y-initializer-aggregate.cpp b/test/CodeGenCXX/cxx1y-initializer-aggregate.cpp index 8bdf8633d61e..098a4b945e04 100644 --- a/test/CodeGenCXX/cxx1y-initializer-aggregate.cpp +++ b/test/CodeGenCXX/cxx1y-initializer-aggregate.cpp @@ -36,6 +36,17 @@ B y {}; B z { 1 }; // CHECK: @z = global {{.*}} { i32 1 } +// Brace initialization should initialize the first field even though it is +// unnamed. +union C { + struct { + int C::*memptr; + }; +}; + +C n{}; +// CHECK: @n = global %union.C { %struct.anon { i64 -1 } }, align 8 + // Initialization of 'a': // CHECK: store i32 0, i32* getelementptr inbounds ({{.*}} @a, i32 0, i32 0) diff --git a/test/CodeGenCXX/cxx1y-variable-template-linkage.cpp b/test/CodeGenCXX/cxx1y-variable-template-linkage.cpp new file mode 100644 index 000000000000..8c0b8c22096d --- /dev/null +++ b/test/CodeGenCXX/cxx1y-variable-template-linkage.cpp @@ -0,0 +1,40 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm -std=c++1y -O1 -disable-llvm-optzns %s -o - | FileCheck %s -check-prefix=CHECKA -check-prefix=CHECK +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm -std=c++1y -O1 -disable-llvm-optzns -fcxx-exceptions %s -o - | FileCheck %s -check-prefix=CHECKB -check-prefix=CHECK +// expected-no-diagnostics + +// The variable template specialization x<Foo> generated in each file +// should be 'internal global' and not 'linkonce_odr global'. + +template <typename T> int x = 42; + +// CHECK-DAG: @_Z1xIZL3foovE3FooE = internal global + +// CHECK-DAG: define internal dereferenceable(4) i32* @_ZL3foov( +static int &foo() { + struct Foo { }; + + // CHECK-DAG: ret i32* @_Z1xIZL3foovE3FooE + return x<Foo>; +} + + +#if !__has_feature(cxx_exceptions) // File A +// CHECKA-DAG: define dereferenceable(4) i32* @_Z3barv( +int &bar() { + // CHECKA-DAG: call dereferenceable(4) i32* @_ZL3foov() + return foo(); +} + +#else // File B + +// CHECKB-DAG: declare dereferenceable(4) i32* @_Z3barv( +int &bar(); + +int main() { + // CHECKB-DAG: call dereferenceable(4) i32* @_Z3barv() + // CHECKB-DAG: call dereferenceable(4) i32* @_ZL3foov() + &bar() == &foo() ? throw 0 : (void)0; // Should not throw exception at runtime. +} + +#endif // end of Files A and B + diff --git a/test/CodeGenCXX/cxx1z-fold-expression.cpp b/test/CodeGenCXX/cxx1z-fold-expression.cpp new file mode 100644 index 000000000000..5dac66b497db --- /dev/null +++ b/test/CodeGenCXX/cxx1z-fold-expression.cpp @@ -0,0 +1,45 @@ +// RUN: %clang_cc1 -std=c++1z -triple %itanium_abi_triple -emit-llvm -o - %s | FileCheck %s + +template<int> struct A {}; +template<int ...N> void foldr(A<(N + ...)>); +template<int ...N> void foldl(A<(... + N)>); +template<int ...N> void foldr1(A<(N + ... + 1)>); +template<int ...N> void foldl1(A<(1 + ... + N)>); +void use() { + foldr<1, 2, 3>({}); + foldl<1, 2, 3>({}); + foldr1<1, 2, 3>({}); + foldl1<1, 2, 3>({}); + // CHECK-DAG: @_Z5foldrIJLi1ELi2ELi3EEEv1AIXfrplT_EE( + // CHECK-DAG: @_Z5foldlIJLi1ELi2ELi3EEEv1AIXflplT_EE( + // CHECK-DAG: @_Z6foldr1IJLi1ELi2ELi3EEEv1AIXfRplT_Li1EEE( + // CHECK-DAG: @_Z6foldl1IJLi1ELi2ELi3EEEv1AIXfLplLi1ET_EE( +} + +template<int ...N> using Foldr = A<(N + ...)>; +template<int ...N> using Foldl = A<(... + N)>; +template<int ...N> using Foldr1 = A<(N + ... + 1)>; +template<int ...N> using Foldl1 = A<(1 + ... + N)>; + +template<int ...A> struct Partial { + template<int ...B> void foldr(Foldr<A..., B..., A..., B...>); + template<int ...B> void foldl(Foldl<A..., B..., A..., B...>); + template<int ...B> void foldr1(Foldr1<A..., B..., A..., B...>); + template<int ...B> void foldl1(Foldl1<A..., B..., A..., B...>); +}; +void use(Partial<1, 2> p) { + p.foldr<3, 4>({}); + p.foldl<3, 4>({}); + p.foldr1<3, 4>({}); + p.foldl1<3, 4>({}); + // CHECK-DAG: @_ZN7PartialIJLi1ELi2EEE5foldrIJLi3ELi4EEEEv1AIXplLi1EplLi2EfRplT_plLi1EplLi2EfrplT_EE( + // CHECK-DAG: @_ZN7PartialIJLi1ELi2EEE5foldlIJLi3ELi4EEEEv1AIXfLplplplfLplplLi1ELi2ET_Li1ELi2ET_EE + // CHECK-DAG: @_ZN7PartialIJLi1ELi2EEE6foldr1IJLi3ELi4EEEEv1AIXplLi1EplLi2EfRplT_plLi1EplLi2EfRplT_Li1EEE( + // CHECK-DAG: @_ZN7PartialIJLi1ELi2EEE6foldl1IJLi3ELi4EEEEv1AIXfLplplplfLplplplLi1ELi1ELi2ET_Li1ELi2ET_EE( +} + +extern int n; +template<int ...N> void f() { + (n = ... = N); +} +template void f<>(); diff --git a/test/CodeGenCXX/debug-info-access.cpp b/test/CodeGenCXX/debug-info-access.cpp new file mode 100644 index 000000000000..d6dfd87013dd --- /dev/null +++ b/test/CodeGenCXX/debug-info-access.cpp @@ -0,0 +1,39 @@ +// RUN: %clang_cc1 -emit-llvm -g -triple %itanium_abi_triple %s -o - | FileCheck %s +// Test the various accessibility flags in the debug info. +struct A { + // CHECK-DAG: [ DW_TAG_subprogram ] [line [[@LINE+1]]] [pub_default] + void pub_default(); + // CHECK-DAG: [ DW_TAG_member ] [pub_default_static] [line [[@LINE+1]]{{.*}}offset 0] [static] + static int pub_default_static; +}; + +// CHECK: [ DW_TAG_inheritance ] {{.*}} [public] [from {{.*}}A] +class B : public A { +public: + // CHECK-DAG: [ DW_TAG_subprogram ] [line [[@LINE+1]]] [public] [pub] + void pub(); + // CHECK-DAG: [ DW_TAG_member ] [public_static] [line [[@LINE+1]]{{.*}} [public] [static] + static int public_static; +protected: + // CHECK: [ DW_TAG_subprogram ] [line [[@LINE+1]]] [protected] [prot] + void prot(); +private: + // CHECK: [ DW_TAG_subprogram ] [line [[@LINE+1]]] [priv_default] + void priv_default(); +}; + +union U { + // CHECK-DAG: [ DW_TAG_subprogram ] [line [[@LINE+1]]] [union_pub_default] + void union_pub_default(); +private: + // CHECK-DAG: [ DW_TAG_member ] [union_priv] [line [[@LINE+1]]{{.*}} [private] + int union_priv; +}; + + +// CHECK: {{.*}}\00256\00{{.*}} ; [ DW_TAG_subprogram ] [line [[@LINE+1]]] [def] [free] +void free() {} + +A a; +B b; +U u; diff --git a/test/CodeGenCXX/debug-info-alias.cpp b/test/CodeGenCXX/debug-info-alias.cpp index fb18ac5da006..dd4b00b7de62 100644 --- a/test/CodeGenCXX/debug-info-alias.cpp +++ b/test/CodeGenCXX/debug-info-alias.cpp @@ -13,15 +13,15 @@ bar = foo<T*>; } -// CHECK: metadata [[BINT:![0-9]*]], i32 0, i32 1, {{.*}} ; [ DW_TAG_variable ] [bi] +// CHECK: [[BINT:![0-9]*]], {{[^,]+, [^,]+}}} ; [ DW_TAG_variable ] [bi] // CHECK: [[BINT]] = {{.*}} ; [ DW_TAG_typedef ] [bar<int>] [line 42 x::bar<int> bi; -// CHECK: metadata [[BFLOAT:![0-9]*]], i32 0, i32 1, {{.*}} ; [ DW_TAG_variable ] [bf] +// CHECK: [[BFLOAT:![0-9]*]], {{[^,]+, [^,]+}}} ; [ DW_TAG_variable ] [bf] // CHECK: [[BFLOAT]] = {{.*}} ; [ DW_TAG_typedef ] [bar<float>] [line 42 x::bar<float> bf; using -// CHECK: metadata [[NARF:![0-9]*]], i32 0, i32 1, {{.*}} ; [ DW_TAG_variable ] [n] +// CHECK: [[NARF:![0-9]*]], {{[^,]+, [^,]+}}} ; [ DW_TAG_variable ] [n] # 142 narf // CHECK: [[NARF]] = {{.*}} ; [ DW_TAG_typedef ] [narf] [line 142 = int; diff --git a/test/CodeGenCXX/debug-info-artificial-arg.cpp b/test/CodeGenCXX/debug-info-artificial-arg.cpp index 84f496f54c37..9eb3c6f0e98d 100644 --- a/test/CodeGenCXX/debug-info-artificial-arg.cpp +++ b/test/CodeGenCXX/debug-info-artificial-arg.cpp @@ -22,8 +22,8 @@ int main(int argc, char **argv) { A reallyA (500); } -// CHECK: ![[CLASSTYPE:.*]] = {{.*}}, metadata !"_ZTS1A"} ; [ DW_TAG_class_type ] [A] +// CHECK: ![[CLASSTYPE:.*]] = {{.*}}, !"_ZTS1A"} ; [ DW_TAG_class_type ] [A] // CHECK: ![[ARTARG:.*]] = {{.*}} ; [ DW_TAG_pointer_type ] [line 0, size 64, align 64, offset 0] [artificial] [from _ZTS1A] -// CHECK: metadata !"_ZTS1A", {{.*}} ; [ DW_TAG_subprogram ] [line 12] [A] -// CHECK: metadata [[FUNCTYPE:![0-9]*]], i32 0, null, null, null} ; [ DW_TAG_subroutine_type ] -// CHECK: [[FUNCTYPE]] = metadata !{null, metadata ![[ARTARG]], metadata !{{.*}}, metadata !{{.*}}} +// CHECK: !"_ZTS1A", {{.*}} ; [ DW_TAG_subprogram ] [line 12] [public] [A] +// CHECK: [[FUNCTYPE:![0-9]*]], null, null, null} ; [ DW_TAG_subroutine_type ] +// CHECK: [[FUNCTYPE]] = !{null, ![[ARTARG]], !{{.*}}, !{{.*}}} diff --git a/test/CodeGenCXX/debug-info-class.cpp b/test/CodeGenCXX/debug-info-class.cpp index 34add0432c49..55d56531609f 100644 --- a/test/CodeGenCXX/debug-info-class.cpp +++ b/test/CodeGenCXX/debug-info-class.cpp @@ -94,33 +94,29 @@ int main(int argc, char **argv) { // CHECK: DW_TAG_class_type ] [bar] // CHECK: DW_TAG_union_type ] [baz] // CHECK: DW_TAG_class_type ] [B] {{.*}} [def] -// CHECK: metadata !"_vptr$B", {{.*}}, i32 64, metadata !{{.*}}} ; [ DW_TAG_member ] +// CHECK: !"0xd\00_vptr$B\00{{.*}}\0064", {{.*}} ; [ DW_TAG_member ] -// CHECK: [[C:![0-9]*]] = {{.*}} metadata [[C_MEM:![0-9]*]], i32 0, metadata !"_ZTS1C", null, metadata !"_ZTS1C"} ; [ DW_TAG_structure_type ] [C] {{.*}} [def] -// CHECK: [[C_MEM]] = metadata !{metadata [[C_VPTR:![0-9]*]], metadata [[C_S:![0-9]*]], metadata [[C_DTOR:![0-9]*]]} +// CHECK: [[C:![0-9]*]] = {{.*}} [[C_MEM:![0-9]*]], !"_ZTS1C", null, !"_ZTS1C"} ; [ DW_TAG_structure_type ] [C] {{.*}} [def] +// CHECK: [[C_MEM]] = !{[[C_VPTR:![0-9]*]], [[C_S:![0-9]*]], [[C_DTOR:![0-9]*]]} // CHECK: [[C_VPTR]] = {{.*}} ; [ DW_TAG_member ] [_vptr$C] {{.*}} [artificial] // CHECK: [[C_S]] = {{.*}} ; [ DW_TAG_member ] [s] {{.*}} [static] [from int] // CHECK: [[C_DTOR]] = {{.*}} ; [ DW_TAG_subprogram ] {{.*}} [~C] -// CHECK: null, i32 0, null, null, metadata !"_ZTS1D"} ; [ DW_TAG_structure_type ] [D] {{.*}} [decl] -// CHECK: null, i32 0, null, null, metadata !"_ZTS1E"} ; [ DW_TAG_structure_type ] [E] {{.*}} [decl] -// CHECK: [[F:![0-9]*]] = {{.*}} null, i32 0, null, null, metadata !"_ZTS1F"} ; [ DW_TAG_structure_type ] [F] {{.*}} [decl] +// CHECK: null, null, null, !"_ZTS1D"} ; [ DW_TAG_structure_type ] [D] {{.*}} [decl] +// CHECK: null, null, null, !"_ZTS1E"} ; [ DW_TAG_structure_type ] [E] {{.*}} [decl] +// CHECK: [[F:![0-9]*]] = {{.*}} null, null, null, !"_ZTS1F"} ; [ DW_TAG_structure_type ] [F] {{.*}} [decl] -// CHECK: null, i32 0, null, null, metadata !"_ZTS1G"} ; [ DW_TAG_structure_type ] [G] {{.*}} [decl] -// CHECK: metadata [[G_INNER_MEM:![0-9]*]], i32 0, null, null, metadata !"_ZTSN1G5innerE"} ; [ DW_TAG_structure_type ] [inner] [line 50, {{.*}} [def] -// CHECK: [[G_INNER_MEM]] = metadata !{metadata [[G_INNER_I:![0-9]*]]} +// CHECK: null, null, null, !"_ZTS1G"} ; [ DW_TAG_structure_type ] [G] {{.*}} [decl] +// CHECK: [[G_INNER_MEM:![0-9]*]], null, null, !"_ZTSN1G5innerE"} ; [ DW_TAG_structure_type ] [inner] [line 50, {{.*}} [def] +// CHECK: [[G_INNER_MEM]] = !{[[G_INNER_I:![0-9]*]]} // CHECK: [[G_INNER_I]] = {{.*}} ; [ DW_TAG_member ] [j] {{.*}} [from int] // CHECK: ; [ DW_TAG_structure_type ] [A] // CHECK: HdrSize // CHECK: ; [ DW_TAG_structure_type ] [I] {{.*}} [def] // -// CHECK: metadata !"_ZTS1D", {{.*}}, metadata [[D_FUNC_DECL:![0-9]*]], metadata {{![0-9]*}}, i32 {{[0-9]*}}} ; [ DW_TAG_subprogram ] {{.*}} [def] [func] -// CHECK: [[D_FUNC_DECL]] = {{.*}}, metadata !"_ZTS1D", {{.*}}, i32 0, null, i32 {{[0-9]*}}} ; [ DW_TAG_subprogram ] {{.*}} [func] +// CHECK: !"_ZTS1D", {{.*}}, [[D_FUNC_DECL:![0-9]*]], {{![0-9]*}}} ; [ DW_TAG_subprogram ] {{.*}} [def] [func] +// CHECK: [[D_FUNC_DECL]] = !{!"0x2e\00func\00{{.*}}\000\00{{[0-9]+}}"{{.*}}, !"_ZTS1D", {{.*}}, null} ; [ DW_TAG_subprogram ] {{.*}} [func] -// CHECK: [[F_I_DEF:![0-9]*]] = {{.*}}, metadata [[F_I:![0-9]*]]} ; [ DW_TAG_variable ] [i] - -// CHECK: [[F_I]] = {{.*}}, metadata !"_ZTS1F", {{.*}} ; [ DW_TAG_member ] [i] - -// CHECK: ![[EXCEPTLOC]] = metadata !{i32 84, -// CHECK: ![[RETLOC]] = metadata !{i32 83, +// CHECK: ![[EXCEPTLOC]] = !MDLocation(line: 84, +// CHECK: ![[RETLOC]] = !MDLocation(line: 83, diff --git a/test/CodeGenCXX/debug-info-cxx1y.cpp b/test/CodeGenCXX/debug-info-cxx1y.cpp index 3cb7e45e6985..261f9653461d 100644 --- a/test/CodeGenCXX/debug-info-cxx1y.cpp +++ b/test/CodeGenCXX/debug-info-cxx1y.cpp @@ -1,7 +1,20 @@ -// RUN: not %clang_cc1 -emit-llvm-only -std=c++1y -g %s 2>&1 | FileCheck %s +// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm-only -std=c++14 -emit-llvm -g %s -o - | FileCheck %s + +// CHECK: [[EMPTY:![0-9]*]] = !{} +// CHECK: \00foo\00{{.*}}, [[EMPTY]], {{.*}}} ; [ DW_TAG_structure_type ] +// FIXME: The context of this definition should be the CU/file scope, not the class. +// CHECK: !"_ZTS3foo", [[SUBROUTINE_TYPE:![0-9]*]], {{.*}}, [[FUNC_DECL:![0-9]*]], {{![0-9]*}}} ; [ DW_TAG_subprogram ] {{.*}} [def] [func] +// CHECK: [[SUBROUTINE_TYPE]] = {{.*}}, [[TYPE_LIST:![0-9]*]], +// CHECK: [[TYPE_LIST]] = !{[[INT:![0-9]*]]} +// CHECK: [[INT]] = {{.*}} ; [ DW_TAG_base_type ] [int] +// CHECK: [[FUNC_DECL]] = {{.*}}, !"_ZTS3foo", [[SUBROUTINE_TYPE]], {{.*}}} ; [ DW_TAG_subprogram ] {{.*}} [func] struct foo { - auto func(); // CHECK: error: debug information for auto is not yet supported + static auto func(); }; foo f; + +auto foo::func() { + return 1; +} diff --git a/test/CodeGenCXX/debug-info-decl-nested.cpp b/test/CodeGenCXX/debug-info-decl-nested.cpp index f79a8e9fe32d..95d32c400e18 100644 --- a/test/CodeGenCXX/debug-info-decl-nested.cpp +++ b/test/CodeGenCXX/debug-info-decl-nested.cpp @@ -17,17 +17,18 @@ class OuterClass public: InnerClass(); // Here createContextChain() generates a limited type for OuterClass. } theInnerClass; -// CHECK0: [[DECL:[0-9]+]] = {{.*}} ; [ DW_TAG_subprogram ] [line [[@LINE+1]]] [private] [OuterClass] +// CHECK0: [[DECL:[0-9]+]] = {{.*}} ; [ DW_TAG_subprogram ] [line [[@LINE+1]]] [OuterClass] OuterClass(const Foo *); // line 10 }; OuterClass::InnerClass OuterClass::theInnerClass; // This toplevel decl causes InnerClass to be generated. -// CHECK0: metadata {{.*}}, metadata ![[DECL]], metadata {{.*}}, i32 [[@LINE+1]]} ; [ DW_TAG_subprogram ] [line [[@LINE+1]]] [def] [OuterClass] +// CHECK0: !"0x2e\00OuterClass\00{{.*}}\00[[@LINE+1]]"{{.*}}, ![[DECL]], {{![0-9]+}}} ; [ DW_TAG_subprogram ] [line [[@LINE+1]]] [def] [OuterClass] OuterClass::OuterClass(const Foo *meta) { } // line 13 + class Foo1; class OuterClass1 { @@ -35,8 +36,8 @@ class OuterClass1 public: InnerClass1(); } theInnerClass1; -// CHECK1: [[DECL:[0-9]+]] = {{.*}} ; [ DW_TAG_subprogram ] [line [[@LINE+2]]] [private] [Bar] -// CHECK1: metadata {{.*}}, metadata ![[DECL]], metadata {{.*}}, i32 [[@LINE+4]]} ; [ DW_TAG_subprogram ] [line [[@LINE+4]]] [def] [Bar] +// CHECK1: [[DECL:[0-9]+]] = {{.*}} ; [ DW_TAG_subprogram ] [line [[@LINE+2]]] [Bar] +// CHECK1: !"0x2e\00Bar\00{{.*}}\00[[@LINE+4]]"{{.*}}, ![[DECL]], {{![0-9]+}}} ; [ DW_TAG_subprogram ] [line [[@LINE+4]]] [def] [Bar] void Bar(const Foo1 *); }; OuterClass1::InnerClass1 OuterClass1::theInnerClass1; @@ -53,9 +54,9 @@ class OuterClass2 public: InnerClass2(); } theInnerClass2; -// CHECK2: [[DECL:[0-9]+]] = {{.*}} ; [ DW_TAG_subprogram ] [line [[@LINE+1]]] [private] [~OuterClass2] +// CHECK2: [[DECL:[0-9]+]] = {{.*}} ; [ DW_TAG_subprogram ] [line [[@LINE+1]]] [~OuterClass2] ~OuterClass2(); // line 10 }; OuterClass2::InnerClass2 OuterClass2::theInnerClass2; -// CHECK2: metadata {{.*}}, metadata ![[DECL]], metadata {{.*}}, i32 [[@LINE+1]]} ; [ DW_TAG_subprogram ] [line [[@LINE+1]]] [def] [~OuterClass2] +// CHECK2: !"0x2e\00~OuterClass2\00{{.*}}\00[[@LINE+1]]"{{.*}}, ![[DECL]], {{.*}}} ; [ DW_TAG_subprogram ] [line [[@LINE+1]]] [def] [~OuterClass2] OuterClass2::~OuterClass2() { } diff --git a/test/CodeGenCXX/debug-info-enum-class.cpp b/test/CodeGenCXX/debug-info-enum-class.cpp index f0b97ccd2c8e..28ffce046c09 100644 --- a/test/CodeGenCXX/debug-info-enum-class.cpp +++ b/test/CodeGenCXX/debug-info-enum-class.cpp @@ -29,10 +29,10 @@ namespace PR14029 { namespace test2 { // FIXME: this should just be a declaration under -fno-standalone-debug -// CHECK: metadata !{i32 {{[^,]*}}, {{[^,]*}}, metadata [[TEST2:![0-9]*]], {{.*}}, metadata [[TEST_ENUMS:![0-9]*]], {{[^,]*}}, null, null, metadata !"_ZTSN5test21EE"} ; [ DW_TAG_enumeration_type ] [E] +// CHECK: !"0x4\00{{.*}}", {{[^,]*}}, [[TEST2:![0-9]*]], {{.*}}, [[TEST_ENUMS:![0-9]*]], null, null, !"_ZTSN5test21EE"} ; [ DW_TAG_enumeration_type ] [E] // CHECK: [[TEST2]] = {{.*}} ; [ DW_TAG_namespace ] [test2] -// CHECK: [[TEST_ENUMS]] = metadata !{metadata [[TEST_E:![0-9]*]]} -// CHECK: [[TEST_E]] = {{.*}}, metadata !"e", i64 0} ; [ DW_TAG_enumerator ] [e :: 0] +// CHECK: [[TEST_ENUMS]] = !{[[TEST_E:![0-9]*]]} +// CHECK: [[TEST_E]] = !{!"0x28\00e\000"} ; [ DW_TAG_enumerator ] [e :: 0] enum E : int; void func(E *) { } @@ -41,7 +41,7 @@ enum E : int { e }; namespace test3 { // FIXME: this should just be a declaration under -fno-standalone-debug -// CHECK: metadata !{i32 {{[^,]*}}, {{[^,]*}}, metadata [[TEST3:![0-9]*]], {{.*}}, metadata [[TEST_ENUMS]], {{[^,]*}}, null, null, metadata !"_ZTSN5test31EE"} ; [ DW_TAG_enumeration_type ] [E] +// CHECK: !"0x4\00{{.*}}", {{[^,]*}}, [[TEST3:![0-9]*]], {{.*}}, [[TEST_ENUMS]], null, null, !"_ZTSN5test31EE"} ; [ DW_TAG_enumeration_type ] [E] // CHECK: [[TEST3]] = {{.*}} ; [ DW_TAG_namespace ] [test3] enum E : int { e }; void func(E *) { @@ -49,7 +49,7 @@ void func(E *) { } namespace test4 { -// CHECK: metadata !{i32 {{[^,]*}}, {{[^,]*}}, metadata [[TEST4:![0-9]*]], {{.*}}, metadata [[TEST_ENUMS]], {{[^,]*}}, null, null, metadata !"_ZTSN5test41EE"} ; [ DW_TAG_enumeration_type ] [E] +// CHECK: !"0x4\00{{.*}}", {{[^,]*}}, [[TEST4:![0-9]*]], {{.*}}, [[TEST_ENUMS]], null, null, !"_ZTSN5test41EE"} ; [ DW_TAG_enumeration_type ] [E] // CHECK: [[TEST4]] = {{.*}} ; [ DW_TAG_namespace ] [test4] enum E : int; void f1(E *) { @@ -62,7 +62,7 @@ void f2(E) { // CHECK: ; [ DW_TAG_enumeration_type ] [D] [line 6, size 16, align 16, offset 0] [decl] [from ] namespace test5 { -// CHECK: metadata !{i32 {{[^,]*}}, {{[^,]*}}, metadata [[TEST5:![0-9]*]], {{.*}}, null, {{[^,]*}}, null, null, metadata !"_ZTSN5test51EE"} ; [ DW_TAG_enumeration_type ] [E] +// CHECK: !"0x4\00{{.*}}", {{[^,]*}}, [[TEST5:![0-9]*]], {{.*}}, null, null, null, !"_ZTSN5test51EE"} ; [ DW_TAG_enumeration_type ] [E] // CHECK: [[TEST5]] = {{.*}} ; [ DW_TAG_namespace ] [test5] enum E : int; void f1(E *) { diff --git a/test/CodeGenCXX/debug-info-enum.cpp b/test/CodeGenCXX/debug-info-enum.cpp index 810c3ee7ae9b..954f6f62e497 100644 --- a/test/CodeGenCXX/debug-info-enum.cpp +++ b/test/CodeGenCXX/debug-info-enum.cpp @@ -1,13 +1,13 @@ // RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm -g %s -o - | FileCheck %s -// CHECK: [[ENUMS:![0-9]*]], {{[^,]*}}, {{[^,]*}}, {{[^,]*}}, {{[^,]*}}, {{[^,]*}}} ; [ DW_TAG_compile_unit ] -// CHECK: [[ENUMS]] = metadata !{metadata [[E1:![0-9]*]], metadata [[E2:![0-9]*]], metadata [[E3:![0-9]*]]} +// CHECK: !"0x11\00{{.*}}", {{[^,]*}}, [[ENUMS:![0-9]*]], {{.*}}} ; [ DW_TAG_compile_unit ] +// CHECK: [[ENUMS]] = !{[[E1:![0-9]*]], [[E2:![0-9]*]], [[E3:![0-9]*]]} namespace test1 { -// CHECK: [[E1]] = metadata !{i32 {{[^,]*}}, {{[^,]*}}, metadata [[TEST1:![0-9]*]], {{.*}}, metadata [[TEST1_ENUMS:![0-9]*]], {{[^,]*}}, null, null, metadata !"_ZTSN5test11eE"} ; [ DW_TAG_enumeration_type ] [e] +// CHECK: [[E1]] = !{!"0x4\00{{.*}}", {{[^,]*}}, [[TEST1:![0-9]*]], {{.*}}, [[TEST1_ENUMS:![0-9]*]], null, null, !"_ZTSN5test11eE"} ; [ DW_TAG_enumeration_type ] [e] // CHECK: [[TEST1]] = {{.*}} ; [ DW_TAG_namespace ] [test1] -// CHECK: [[TEST1_ENUMS]] = metadata !{metadata [[TEST1_E:![0-9]*]]} -// CHECK: [[TEST1_E]] = {{.*}}, metadata !"E", i64 0} ; [ DW_TAG_enumerator ] [E :: 0] +// CHECK: [[TEST1_ENUMS]] = !{[[TEST1_E:![0-9]*]]} +// CHECK: [[TEST1_E]] = !{!"0x28\00E\000"} ; [ DW_TAG_enumerator ] [E :: 0] enum e { E }; void foo() { int v = E; @@ -16,7 +16,7 @@ void foo() { namespace test2 { // rdar://8195980 -// CHECK: [[E2]] = metadata !{i32 {{[^,]*}}, {{[^,]*}}, metadata [[TEST2:![0-9]*]], {{.*}}, metadata [[TEST1_ENUMS]], {{[^,]*}}, null, null, metadata !"_ZTSN5test21eE"} ; [ DW_TAG_enumeration_type ] [e] +// CHECK: [[E2]] = !{!"0x4\00{{.*}}", {{[^,]*}}, [[TEST2:![0-9]*]], {{.*}}, [[TEST1_ENUMS]], null, null, !"_ZTSN5test21eE"} ; [ DW_TAG_enumeration_type ] [e] // CHECK: [[TEST2]] = {{.*}} ; [ DW_TAG_namespace ] [test2] enum e { E }; bool func(int i) { @@ -25,10 +25,10 @@ bool func(int i) { } namespace test3 { -// CHECK: [[E3]] = metadata !{i32 {{[^,]*}}, {{[^,]*}}, metadata [[TEST3:![0-9]*]], {{.*}}, metadata [[TEST3_ENUMS:![0-9]*]], {{[^,]*}}, null, null, metadata !"_ZTSN5test31eE"} ; [ DW_TAG_enumeration_type ] [e] +// CHECK: [[E3]] = !{!"0x4\00{{.*}}", {{[^,]*}}, [[TEST3:![0-9]*]], {{.*}}, [[TEST3_ENUMS:![0-9]*]], null, null, !"_ZTSN5test31eE"} ; [ DW_TAG_enumeration_type ] [e] // CHECK: [[TEST3]] = {{.*}} ; [ DW_TAG_namespace ] [test3] -// CHECK: [[TEST3_ENUMS]] = metadata !{metadata [[TEST3_E:![0-9]*]]} -// CHECK: [[TEST3_E]] = {{.*}}, metadata !"E", i64 -1} ; [ DW_TAG_enumerator ] [E :: -1] +// CHECK: [[TEST3_ENUMS]] = !{[[TEST3_E:![0-9]*]]} +// CHECK: [[TEST3_E]] = !{!"0x28\00E\00-1"} ; [ DW_TAG_enumerator ] [E :: -1] enum e { E = -1 }; void func() { e x; diff --git a/test/CodeGenCXX/debug-info-flex-member.cpp b/test/CodeGenCXX/debug-info-flex-member.cpp index 11329aa1e2b9..bc501c016847 100644 --- a/test/CodeGenCXX/debug-info-flex-member.cpp +++ b/test/CodeGenCXX/debug-info-flex-member.cpp @@ -1,6 +1,6 @@ // RUN: %clang_cc1 -emit-llvm -g -triple x86_64-apple-darwin %s -o - | FileCheck %s -// CHECK: metadata !{i32 {{.*}}, i64 0, i64 -1} ; [ DW_TAG_subrange_type ] +// CHECK: !"0x21\000\00-1"} ; [ DW_TAG_subrange_type ] struct StructName { int member[]; diff --git a/test/CodeGenCXX/debug-info-function-context.cpp b/test/CodeGenCXX/debug-info-function-context.cpp index e65d3289f8b1..a6c5a115fc07 100644 --- a/test/CodeGenCXX/debug-info-function-context.cpp +++ b/test/CodeGenCXX/debug-info-function-context.cpp @@ -25,12 +25,12 @@ int global_namespace_variable = 1; // functions that belong to the namespace have it as a context, and the global // function has the file as a context. -// CHECK: metadata !"_ZTS1C", metadata !"member_function"{{.*}} [ DW_TAG_subprogram ] [line 11] [def] [member_function] +// CHECK: !"0x2e\00member_function\00{{.*}}", !{{[0-9]+}}, !"_ZTS1C"{{.*}} [ DW_TAG_subprogram ] [line 11] [def] [member_function] -// CHECK: metadata !"_ZTS1C", metadata !"static_member_function"{{.*}} [ DW_TAG_subprogram ] [line 13] [def] [static_member_function] +// CHECK: !"0x2e\00static_member_function\00{{.*}}", !{{[0-9]+}}, !"_ZTS1C"{{.*}} [ DW_TAG_subprogram ] [line 13] [def] [static_member_function] -// CHECK: metadata [[FILE:![0-9]*]], metadata !"global_function"{{.*}} [ DW_TAG_subprogram ] [line 17] [def] [global_function] +// CHECK: !"0x2e\00global_function\00{{[^,]+}}", !{{[0-9]+}}, [[FILE:![0-9]*]]{{.*}} [ DW_TAG_subprogram ] [line 17] [def] [global_function] // CHECK: [[FILE]] = {{.*}} [ DW_TAG_file_type ] -// CHECK: metadata [[NS:![0-9]*]], metadata !"global_namespace_function"{{.*}} [ DW_TAG_subprogram ] [line 20] [def] [global_namespace_function] +// CHECK: !"0x2e\00global_namespace_function\00{{[^,]+}}", !{{[0-9]+}}, [[NS:![0-9]*]]{{.*}} [ DW_TAG_subprogram ] [line 20] [def] [global_namespace_function] // CHECK: [[NS]] = {{.*}} [ DW_TAG_namespace ] [ns] [line 19] diff --git a/test/CodeGenCXX/debug-info-global.cpp b/test/CodeGenCXX/debug-info-global.cpp index 8dc30c892316..5fc61c7c4d45 100644 --- a/test/CodeGenCXX/debug-info-global.cpp +++ b/test/CodeGenCXX/debug-info-global.cpp @@ -10,10 +10,10 @@ int f1() { return ns::cnst + ns::cnst; } -// CHECK: metadata [[GLOBALS:![0-9]*]], metadata {{![0-9]*}}, metadata !"{{.*}}", i32 {{[0-9]*}}} ; [ DW_TAG_compile_unit ] +// CHECK: !"0x11\00{{.*}}"{{.*}}, [[GLOBALS:![0-9]*]], {{![0-9]*}}} ; [ DW_TAG_compile_unit ] -// CHECK: [[GLOBALS]] = metadata !{metadata [[CNST:![0-9]*]]} +// CHECK: [[GLOBALS]] = !{[[CNST:![0-9]*]]} -// CHECK: [[CNST]] = {{.*}}, metadata [[NS:![0-9]*]], metadata !"cnst", {{.*}}; [ DW_TAG_variable ] [cnst] +// CHECK: [[CNST]] = !{!"0x34\00cnst\00{{.*}}", [[NS:![0-9]*]], {{[^,]+, [^,]+, [^,]+, [^,]+}}} ; [ DW_TAG_variable ] [cnst] // CHECK: [[NS]] = {{.*}}; [ DW_TAG_namespace ] [ns] diff --git a/test/CodeGenCXX/debug-info-globalinit.cpp b/test/CodeGenCXX/debug-info-globalinit.cpp index 30c8bfc680eb..efba958c9ed0 100644 --- a/test/CodeGenCXX/debug-info-globalinit.cpp +++ b/test/CodeGenCXX/debug-info-globalinit.cpp @@ -34,5 +34,5 @@ int main(void) {} // CHECK-NOT: __cxx_global_var_init // CHECK: store i32 %[[C2]], i32* @_ZL1k, align 4, !dbg // -// CHECK: ![[LINE]] = metadata !{i32 13, i32 -// CHECK: ![[LINE2]] = metadata !{i32 15, i32 +// CHECK: ![[LINE]] = !MDLocation(line: 13, +// CHECK: ![[LINE2]] = !MDLocation(line: 15, diff --git a/test/CodeGenCXX/debug-info-line-if.cpp b/test/CodeGenCXX/debug-info-line-if.cpp index e14090f03f98..d0205af92bf4 100644 --- a/test/CodeGenCXX/debug-info-line-if.cpp +++ b/test/CodeGenCXX/debug-info-line-if.cpp @@ -1,20 +1,55 @@ // RUN: %clang_cc1 -g -std=c++11 -S -emit-llvm %s -o - | FileCheck %s // PR19864 +extern int v[2]; +int a = 0, b = 0; int main() { - int v[] = {13, 21, 8, 3, 34, 1, 5, 2}; - int a = 0, b = 0; - for (int x : v) - if (x >= 3) - ++b; // CHECK: add nsw{{.*}}, 1 - else if (x >= 0) - ++a; // CHECK: add nsw{{.*}}, 1 - // The continuation block if the if statement should not share the - // location of the ++a statement. Having it point to the end of - // the condition is not ideal either, but it's less missleading. - - // CHECK: br label - // CHECK: br label - // CHECK: br label {{.*}}, !dbg ![[DBG:.*]] - // CHECK: ![[DBG]] = metadata !{i32 [[@LINE-11]], i32 0, metadata !{{.*}}, null} +#line 100 + for (int x : v) + if (x) + ++b; // CHECK: add nsw{{.*}}, 1 + else + ++a; // CHECK: add nsw{{.*}}, 1 + // The continuation block if the if statement should not share the + // location of the ++a statement. The branch back to the start of the loop + // should be attributed to the loop header line. + // CHECK: br label + // CHECK: br label + // CHECK: br label {{.*}}, !dbg [[DBG1:!.*]] + +#line 200 + while (a) + if (b) + ++b; // CHECK: add nsw{{.*}}, 1 + else + ++a; // CHECK: add nsw{{.*}}, 1 + + // CHECK: br label + // CHECK: br label {{.*}}, !dbg [[DBG2:!.*]] + +#line 300 + for (; a; ) + if (b) + ++b; // CHECK: add nsw{{.*}}, 1 + else + ++a; // CHECK: add nsw{{.*}}, 1 + + // CHECK: br label + // CHECK: br label {{.*}}, !dbg [[DBG3:!.*]] + +#line 400 + int x[] = {1, 2}; + for (int y : x) + if (b) + ++b; // CHECK: add nsw{{.*}}, 1 + else + ++a; // CHECK: add nsw{{.*}}, 1 + + // CHECK: br label + // CHECK: br label {{.*}}, !dbg [[DBG4:!.*]] + + // CHECK: [[DBG1]] = !MDLocation(line: 100, scope: !{{.*}}) + // CHECK: [[DBG2]] = !MDLocation(line: 200, scope: !{{.*}}) + // CHECK: [[DBG3]] = !MDLocation(line: 300, scope: !{{.*}}) + // CHECK: [[DBG4]] = !MDLocation(line: 401, scope: !{{.*}}) } diff --git a/test/CodeGenCXX/debug-info-line.cpp b/test/CodeGenCXX/debug-info-line.cpp new file mode 100644 index 000000000000..a5cc6392b4fc --- /dev/null +++ b/test/CodeGenCXX/debug-info-line.cpp @@ -0,0 +1,187 @@ +// RUN: %clang_cc1 -gline-tables-only -std=c++11 -fexceptions -fcxx-exceptions -S -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -gline-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(); +extern "C" __complex float *complex_sink(); + +// CHECK-LABEL: define +void f1() { +#line 100 + * // The store for the assignment should be attributed to the start of the + // assignment expression here, regardless of the location of subexpressions. + sink() = src(); + // CHECK: store {{.*}}, !dbg [[DBG_F1:!.*]] +} + +struct foo { + int i; + int &j; + __complex float k; + foo(); +}; + +// CHECK-LABEL: define +foo::foo() + : +#line 200 + i // CHECK: store i32 {{.*}} !dbg [[DBG_FOO_VALUE:!.*]] + (src()), + j // CHECK: store i32* {{.*}} !dbg [[DBG_FOO_REF:!.*]] + (src()), + k // CHECK: store float {{.*}} !dbg [[DBG_FOO_COMPLEX:!.*]] + (complex_src()) { +} + +// CHECK-LABEL: define {{.*}}f2{{.*}} +void f2() { +#line 300 + * // CHECK: store float {{.*}} !dbg [[DBG_F2:!.*]] + complex_sink() = complex_src(); +} + +// CHECK-LABEL: define +void f3() { +#line 400 + * // CHECK: store float {{.*}} !dbg [[DBG_F3:!.*]] + complex_sink() += complex_src(); +} + +// CHECK-LABEL: define +void f4() { +#line 500 + auto x // CHECK: store {{.*}} !dbg [[DBG_F4:!.*]] + = src(); +} + +// CHECK-LABEL: define +void f5() { +#line 600 + auto x // CHECK: store float {{.*}} !dbg [[DBG_F5:!.*]] + = complex_src(); +} + +struct agg { int i; }; +agg agg_src(); + +// CHECK-LABEL: define +void f6() { + agg x; +#line 700 + x // CHECK: call void @llvm.memcpy{{.*}} !dbg [[DBG_F6:!.*]] + = agg_src(); +} + +// CHECK-LABEL: define +void f7() { + int *src1(); + int src2(); +#line 800 + int x = ( // CHECK: load {{.*}} !dbg [[DBG_F7:!.*]] + src1())[src2()]; +} + +// CHECK-LABEL: define +void f8() { + int src1[1]; + int src2(); +#line 900 + int x = ( // CHECK: load {{.*}} !dbg [[DBG_F8:!.*]] + src1)[src2()]; +} + +// CHECK-LABEL: define +void f9(int i) { + int src1[1][i]; + int src2(); +#line 1000 + auto x = ( // CHECK: getelementptr {{.*}} !dbg [[DBG_F9:!.*]] + src1)[src2()]; +} + +inline void *operator new(decltype(sizeof(1)), void *p) noexcept { return p; } + +// CHECK-LABEL: define +void f10() { + void *void_src(); + ( // CHECK: icmp {{.*}} !dbg [[DBG_F10_ICMP:.*]] + // CHECK: store {{.*}} !dbg [[DBG_F10_STORE:!.*]] +#line 1100 + new (void_src()) int(src())); +} + +// noexcept just to simplify the codegen a bit +void fn() noexcept(true); + +struct bar { + bar(); + // noexcept(false) to convolute the global dtor + ~bar() noexcept(false); +}; +// global ctor cleanup +// CHECK-LABEL: define +// CHECK: invoke{{ }} +// CHECK: invoke{{ }} +// CHECK: to label {{.*}}, !dbg [[DBG_GLBL_CTOR_B:!.*]] + +// terminate caller +// CHECK-LABEL: define + +// global dtor cleanup +// CHECK-LABEL: define +// CHECK: invoke{{ }} +// CHECK: invoke{{ }} +// CHECK: to label {{.*}}, !dbg [[DBG_GLBL_DTOR_B:!.*]] +#line 1500 +bar b[1] = { // + (fn(), // + bar())}; + +// CHECK-LABEL: define +__complex double f11() { + __complex double f; +// CHECK: store {{.*}} !dbg [[DBG_F11:!.*]] +#line 1200 + return f; +} + +// CHECK-LABEL: define +void f12() { + int f12_1(); + void f12_2(int = f12_1()); +// CHECK: call {{(signext )?}}i32 {{.*}} !dbg [[DBG_F12:!.*]] +#line 1300 + f12_2(); +} + +// CHECK-LABEL: define +void f13() { +// CHECK: call {{.*}} !dbg [[DBG_F13:!.*]] +#define F13_IMPL 1, src() + 1, +#line 1400 + F13_IMPL; +} + +// CHECK: [[DBG_F1]] = !MDLocation(line: 100, +// CHECK: [[DBG_FOO_VALUE]] = !MDLocation(line: 200, +// CHECK: [[DBG_FOO_REF]] = !MDLocation(line: 202, +// CHECK: [[DBG_FOO_COMPLEX]] = !MDLocation(line: 204, +// CHECK: [[DBG_F2]] = !MDLocation(line: 300, +// CHECK: [[DBG_F3]] = !MDLocation(line: 400, +// CHECK: [[DBG_F4]] = !MDLocation(line: 500, +// CHECK: [[DBG_F5]] = !MDLocation(line: 600, +// CHECK: [[DBG_F6]] = !MDLocation(line: 700, +// CHECK: [[DBG_F7]] = !MDLocation(line: 800, +// CHECK: [[DBG_F8]] = !MDLocation(line: 900, +// CHECK: [[DBG_F9]] = !MDLocation(line: 1000, +// CHECK: [[DBG_F10_ICMP]] = !MDLocation(line: 1100, +// CHECK: [[DBG_F10_STORE]] = !MDLocation(line: 1100, +// CHECK: [[DBG_GLBL_CTOR_B]] = !MDLocation(line: 1500, +// CHECK: [[DBG_GLBL_DTOR_B]] = !MDLocation(line: 1500, +// CHECK: [[DBG_F11]] = !MDLocation(line: 1200, +// CHECK: [[DBG_F12]] = !MDLocation(line: 1300, +// CHECK: [[DBG_F13]] = !MDLocation(line: 1400, diff --git a/test/CodeGenCXX/debug-info-method.cpp b/test/CodeGenCXX/debug-info-method.cpp index 49b8dc47855d..bb69a6516507 100644 --- a/test/CodeGenCXX/debug-info-method.cpp +++ b/test/CodeGenCXX/debug-info-method.cpp @@ -1,14 +1,14 @@ // RUN: %clang_cc1 -emit-llvm -triple %itanium_abi_triple -std=c++11 -g %s -o - | FileCheck %s -// CHECK: metadata !"_ZTS1A"} ; [ DW_TAG_class_type ] [A] -// CHECK: metadata !"_ZN1A3fooEiS_3$_0", {{.*}} [protected] +// CHECK: !"_ZTS1A"} ; [ DW_TAG_class_type ] [A] +// CHECK: !"{{.*}}\00_ZN1A3fooEiS_3$_0\00{{.*}}", {{.*}} [protected] // CHECK: ![[THISTYPE:[0-9]+]] = {{.*}} ; [ DW_TAG_pointer_type ] {{.*}} [artificial] [from _ZTS1A] -// CHECK: DW_TAG_ptr_to_member_type -// CHECK: {{.*}}metadata ![[MEMFUNTYPE:[0-9]+]], metadata !{{.*}}} ; [ DW_TAG_ptr_to_member_type ] {{.*}} [from ] -// CHECK: ![[MEMFUNTYPE]] = {{.*}}metadata ![[MEMFUNARGS:[0-9]+]], i32 0, null, null, null} ; [ DW_TAG_subroutine_type ] {{.*}} [from ] -// CHECK: ![[MEMFUNARGS]] = {{.*}}, metadata ![[THISTYPE]], -// CHECK: ""{{.*}}DW_TAG_arg_variable -// CHECK: ""{{.*}}DW_TAG_arg_variable -// CHECK: ""{{.*}}DW_TAG_arg_variable +// CHECK: [ DW_TAG_ptr_to_member_type ] [line {{[0-9]+}}, size {{[1-9][0-9]+}}, align +// CHECK: {{.*}}![[MEMFUNTYPE:[0-9]+]], !{{.*}}} ; [ DW_TAG_ptr_to_member_type ] {{.*}} [from ] +// CHECK: ![[MEMFUNTYPE]] = {{.*}}![[MEMFUNARGS:[0-9]+]], null, null, null} ; [ DW_TAG_subroutine_type ] {{.*}} [from ] +// CHECK: ![[MEMFUNARGS]] = {{.*}}, ![[THISTYPE]], +// CHECK: !"0x101\00\00{{.*}}"{{.*}} DW_TAG_arg_variable +// CHECK: !"0x101\00\00{{.*}}"{{.*}} DW_TAG_arg_variable +// CHECK: !"0x101\00\00{{.*}}"{{.*}} DW_TAG_arg_variable union { int a; float b; diff --git a/test/CodeGenCXX/debug-info-namespace.cpp b/test/CodeGenCXX/debug-info-namespace.cpp index a1284d2d2771..60d508bcb735 100644 --- a/test/CodeGenCXX/debug-info-namespace.cpp +++ b/test/CodeGenCXX/debug-info-namespace.cpp @@ -5,12 +5,16 @@ namespace A { #line 1 "foo.cpp" namespace B { -int i; -void f1() { } +extern int i; +int f1() { return 0; } void f1(int) { } struct foo; struct bar { }; typedef bar baz; +extern int var_decl; +void func_decl(void); +extern int var_fwd; +void func_fwd(void); } } namespace A { @@ -19,7 +23,7 @@ using namespace B; using namespace A; namespace E = A; - +int B::i = f1(); int func(bool b) { if (b) { using namespace A::B; @@ -33,51 +37,65 @@ int func(bool b) { using B::baz; namespace X = A; namespace Y = X; + using B::var_decl; + using B::func_decl; + using B::var_fwd; + using B::func_fwd; return i + X::B::i + Y::B::i; } namespace A { using B::i; +namespace B { +int var_fwd = i; +} } +void B::func_fwd() {} // This should work even if 'i' and 'func' were declarations & not definitions, // but it doesn't yet. -// CHECK: [[CU:![0-9]*]] = {{.*}}[[MODULES:![0-9]*]], metadata !"", i32 1} ; [ DW_TAG_compile_unit ] +// CHECK: [[CU:![0-9]*]] = !{!"0x11\00{{.*}}\001"{{.*}}, [[MODULES:![0-9]*]]} ; [ DW_TAG_compile_unit ] // CHECK: [[FOO:![0-9]*]] {{.*}} ; [ DW_TAG_structure_type ] [foo] [line 5, size 0, align 0, offset 0] [decl] [from ] -// CHECK: [[FOOCPP:![0-9]*]] = metadata !{metadata !"foo.cpp", {{.*}} -// CHECK: [[NS:![0-9]*]] = {{.*}}, metadata [[FILE2:![0-9]*]], metadata [[CTXT:![0-9]*]], {{.*}} ; [ DW_TAG_namespace ] [B] [line 1] -// CHECK: [[CTXT]] = {{.*}}, metadata [[FILE:![0-9]*]], null, {{.*}} ; [ DW_TAG_namespace ] [A] [line 5] +// CHECK: [[FOOCPP:![0-9]*]] = !{!"foo.cpp", {{.*}} +// CHECK: [[NS:![0-9]*]] = !{!"0x39\00B\001", [[FILE2:![0-9]*]], [[CTXT:![0-9]*]]} ; [ DW_TAG_namespace ] [B] [line 1] +// CHECK: [[CTXT]] = !{!"0x39\00A\005", [[FILE:![0-9]*]], null} ; [ DW_TAG_namespace ] [A] [line 5] // CHECK: [[FILE]] {{.*}}debug-info-namespace.cpp" // CHECK: [[BAR:![0-9]*]] {{.*}} ; [ DW_TAG_structure_type ] [bar] [line 6, {{.*}}] [decl] [from ] // CHECK: [[F1:![0-9]*]] {{.*}} ; [ DW_TAG_subprogram ] [line 4] [def] [f1] -// CHECK: [[FUNC:![0-9]*]] {{.*}} ; [ DW_TAG_subprogram ] {{.*}} [def] [func] // CHECK: [[FILE2]]} ; [ DW_TAG_file_type ] [{{.*}}foo.cpp] -// CHECK: [[I:![0-9]*]] = {{.*}}, metadata [[NS]], metadata !"i", {{.*}} ; [ DW_TAG_variable ] [i] -// CHECK: [[MODULES]] = metadata !{metadata [[M1:![0-9]*]], metadata [[M2:![0-9]*]], metadata [[M3:![0-9]*]], metadata [[M4:![0-9]*]], metadata [[M5:![0-9]*]], metadata [[M6:![0-9]*]], metadata [[M7:![0-9]*]], metadata [[M8:![0-9]*]], metadata [[M9:![0-9]*]], metadata [[M10:![0-9]*]], metadata [[M11:![0-9]*]], metadata [[M12:![0-9]*]], metadata [[M13:![0-9]*]]} -// CHECK: [[M1]] = metadata !{i32 {{[0-9]*}}, metadata [[CTXT]], metadata [[NS]], i32 11} ; [ DW_TAG_imported_module ] -// CHECK: [[M2]] = metadata !{i32 {{[0-9]*}}, metadata [[CU]], metadata [[CTXT]], i32 {{[0-9]*}}} ; [ DW_TAG_imported_module ] -// CHECK: [[M3]] = metadata !{i32 {{[0-9]*}}, metadata [[CU]], metadata [[CTXT]], i32 15, metadata !"E"} ; [ DW_TAG_imported_declaration ] -// CHECK: [[M4]] = metadata !{i32 {{[0-9]*}}, metadata [[LEX2:![0-9]*]], metadata [[NS]], i32 19} ; [ DW_TAG_imported_module ] -// CHECK: [[LEX2]] = metadata !{i32 {{[0-9]*}}, metadata [[FILE2]], metadata [[LEX1:![0-9]+]], i32 {{[0-9]*}}, i32 0, i32 {{.*}}} ; [ DW_TAG_lexical_block ] -// CHECK: [[LEX1]] = metadata !{i32 {{[0-9]*}}, metadata [[FILE2]], metadata [[FUNC]], i32 {{[0-9]*}}, i32 0, i32 {{.*}}} ; [ DW_TAG_lexical_block ] -// CHECK: [[M5]] = metadata !{i32 {{[0-9]*}}, metadata [[FUNC]], metadata [[CTXT]], i32 {{[0-9]*}}} ; [ DW_TAG_imported_module ] -// CHECK: [[M6]] = metadata !{i32 {{[0-9]*}}, metadata [[FUNC]], metadata [[FOO:!"_ZTSN1A1B3fooE"]], i32 23} ; [ DW_TAG_imported_declaration ] -// CHECK: [[M7]] = metadata !{i32 {{[0-9]*}}, metadata [[FUNC]], metadata [[BAR:!"_ZTSN1A1B3barE"]], i32 {{[0-9]*}}} ; [ DW_TAG_imported_declaration ] -// CHECK: [[M8]] = metadata !{i32 {{[0-9]*}}, metadata [[FUNC]], metadata [[F1]], i32 {{[0-9]*}}} ; [ DW_TAG_imported_declaration ] -// CHECK: [[M9]] = metadata !{i32 {{[0-9]*}}, metadata [[FUNC]], metadata [[I]], i32 {{[0-9]*}}} ; [ DW_TAG_imported_declaration ] -// CHECK: [[M10]] = metadata !{i32 {{[0-9]*}}, metadata [[FUNC]], metadata [[BAZ:![0-9]*]], i32 {{[0-9]*}}} ; [ DW_TAG_imported_declaration ] -// CHECK: [[BAZ]] = metadata !{i32 {{[0-9]*}}, metadata [[FOOCPP]], metadata [[NS]], {{.*}}, metadata !"_ZTSN1A1B3barE"} ; [ DW_TAG_typedef ] [baz] {{.*}} [from _ZTSN1A1B3barE] -// CHECK: [[M11]] = metadata !{i32 {{[0-9]*}}, metadata [[FUNC]], metadata [[CTXT]], i32 {{[0-9]*}}, metadata !"X"} ; [ DW_TAG_imported_declaration ] -// CHECK: [[M12]] = metadata !{i32 {{[0-9]*}}, metadata [[FUNC]], metadata [[M11]], i32 {{[0-9]*}}, metadata !"Y"} ; [ DW_TAG_imported_declaration ] -// CHECK: [[M13]] = metadata !{i32 {{[0-9]*}}, metadata [[CTXT]], metadata [[I]], i32 {{[0-9]*}}} ; [ DW_TAG_imported_declaration ] +// CHECK: [[FUNC:![0-9]*]] {{.*}} ; [ DW_TAG_subprogram ] {{.*}} [def] [func] +// CHECK: [[FUNC_FWD:![0-9]*]] {{.*}} [ DW_TAG_subprogram ] [line 47] [def] [func_fwd] +// CHECK: [[I:![0-9]*]] = !{!"0x34\00i\00{{.*}}", [[NS]], {{.*}} ; [ DW_TAG_variable ] [i] +// CHECK: [[VAR_FWD:![0-9]*]] = !{!"0x34\00var_fwd\00{{.*}}", [[NS]], {{.*}}} ; [ DW_TAG_variable ] [var_fwd] [line 44] [def] -// CHECK-GMLT: [[CU:![0-9]*]] = {{.*}}[[MODULES:![0-9]*]], metadata !"", i32 2} ; [ DW_TAG_compile_unit ] -// CHECK-GMLT: [[MODULES]] = metadata !{} +// 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]] = !{!"0x3a\0015\00", [[CTXT]], [[NS]]} ; [ DW_TAG_imported_module ] +// CHECK: [[M2]] = !{!"0x3a\00{{[0-9]+}}\00", [[CU]], [[CTXT]]} ; [ DW_TAG_imported_module ] +// CHECK: [[M3]] = !{!"0x8\0019\00E", [[CU]], [[CTXT]]} ; [ DW_TAG_imported_declaration ] +// CHECK: [[M4]] = !{!"0x3a\0023\00", [[LEX2:![0-9]*]], [[NS]]} ; [ DW_TAG_imported_module ] +// CHECK: [[LEX2]] = !{!"0xb\00{{[0-9]*}}\000\00{{.*}}", [[FILE2]], [[LEX1:![0-9]+]]} ; [ DW_TAG_lexical_block ] +// CHECK: [[LEX1]] = !{!"0xb\00{{[0-9]*}}\000\00{{.*}}", [[FILE2]], [[FUNC]]} ; [ DW_TAG_lexical_block ] +// CHECK: [[M5]] = !{!"0x3a\00{{[0-9]+}}\00", [[FUNC]], [[CTXT]]} ; [ DW_TAG_imported_module ] +// CHECK: [[M6]] = !{!"0x8\0027\00", [[FUNC]], [[FOO:!"_ZTSN1A1B3fooE"]]} ; [ DW_TAG_imported_declaration ] +// CHECK: [[M7]] = !{!"0x8\00{{[0-9]+}}\00", [[FUNC]], [[BAR:!"_ZTSN1A1B3barE"]]} ; [ DW_TAG_imported_declaration ] +// CHECK: [[M8]] = !{!"0x8\00{{[0-9]+}}\00", [[FUNC]], [[F1]]} ; [ DW_TAG_imported_declaration ] +// CHECK: [[M9]] = !{!"0x8\00{{[0-9]+}}\00", [[FUNC]], [[I]]} ; [ DW_TAG_imported_declaration ] +// CHECK: [[M10]] = !{!"0x8\00{{[0-9]+}}\00", [[FUNC]], [[BAZ:![0-9]*]]} ; [ DW_TAG_imported_declaration ] +// CHECK: [[BAZ]] = !{!"0x16\00baz\00{{.*}}", [[FOOCPP]], [[NS]], !"_ZTSN1A1B3barE"} ; [ DW_TAG_typedef ] [baz] {{.*}} [from _ZTSN1A1B3barE] +// CHECK: [[M11]] = !{!"0x8\00{{[0-9]+}}\00X", [[FUNC]], [[CTXT]]} ; [ DW_TAG_imported_declaration ] +// CHECK: [[M12]] = !{!"0x8\00{{[0-9]+}}\00Y", [[FUNC]], [[M11]]} ; [ DW_TAG_imported_declaration ] +// CHECK: [[M13]] = !{!"0x8\00{{[0-9]+}}\00", [[FUNC]], [[VAR_DECL:![0-9]*]]} ; [ DW_TAG_imported_declaration ] +// CHECK [[VAR_DECL]] = !{!"0x34\00var_decl\00{{.*}}", [[NS]], {{.*}}} ; [ DW_TAG_variable ] [var_decl] [line 8] +// CHECK: [[M14]] = !{!"0x8\00{{[0-9]+}}\00", [[FUNC]], [[FUNC_DECL:![0-9]*]]} ; [ DW_TAG_imported_declaration ] +// CHECK: [[FUNC_DECL]] = !{!"0x2e\00func_decl\00{{.*}}", [[FOOCPP]], [[NS]], {{.*}}} ; [ DW_TAG_subprogram ] [line 9] [scope 0] [func_decl] +// CHECK: [[M15]] = !{!"0x8\00{{[0-9]+}}\00", [[FUNC]], [[VAR_FWD:![0-9]*]]} ; [ DW_TAG_imported_declaration ] +// CHECK: [[M16]] = !{!"0x8\00{{[0-9]+}}\00", [[FUNC]], [[FUNC_FWD:![0-9]*]]} ; [ DW_TAG_imported_declaration ] +// CHECK: [[M17]] = !{!"0x8\00{{[0-9]+}}\00", [[CTXT]], [[I]]} ; [ DW_TAG_imported_declaration ] +// CHECK-GMLT: [[CU:![0-9]*]] = !{!"0x11\00{{.*}}\002"{{.*}}, [[MODULES:![0-9]*]]} ; [ DW_TAG_compile_unit ] +// CHECK-GMLT: [[MODULES]] = !{} // CHECK-NOLIMIT: ; [ DW_TAG_structure_type ] [bar] [line 6, {{.*}}] [def] [from ] -// FIXME: It is confused on win32 to generate file entry when dosish filename is given. -// REQUIRES: shell // REQUIRES: shell-preserves-root // REQUIRES: dw2 diff --git a/test/CodeGenCXX/debug-info-ptr-to-member-function.cpp b/test/CodeGenCXX/debug-info-ptr-to-member-function.cpp new file mode 100644 index 000000000000..656e6f495880 --- /dev/null +++ b/test/CodeGenCXX/debug-info-ptr-to-member-function.cpp @@ -0,0 +1,10 @@ +// RUN: %clang_cc1 %s -triple x86_64-apple-darwin -g -emit-llvm -o - | FileCheck %s + +struct T { + int method(); +}; + +void foo(int (T::*method)()) {} + +// A pointer to a member function is a pair of function- and this-pointer. +// CHECK: [ DW_TAG_ptr_to_member_type ] {{.*}} size 128 diff --git a/test/CodeGenCXX/debug-info-qualifiers.cpp b/test/CodeGenCXX/debug-info-qualifiers.cpp index c6b935f9039a..2655bd9d726f 100644 --- a/test/CodeGenCXX/debug-info-qualifiers.cpp +++ b/test/CodeGenCXX/debug-info-qualifiers.cpp @@ -2,25 +2,25 @@ // Test (r)value and CVR qualifiers on C++11 non-static member functions. class A { public: - // CHECK: i32 [[@LINE+2]], metadata ![[PLSR:[0-9]+]], {{.*}}[ DW_TAG_subprogram ] [line [[@LINE+2]]] [reference] [l] + // CHECK: !"0x2e\00l\00{{.*}}\00[[@LINE+2]]"{{, [^,]+, [^,]+}}, ![[PLSR:[0-9]+]], {{.*}}[ DW_TAG_subprogram ] [line [[@LINE+2]]] [public] [reference] [l] // CHECK: ![[PLSR]] ={{.*}}[ DW_TAG_subroutine_type ]{{.*}}[reference] void l() const &; - // CHECK: ![[ARGS:[0-9]+]] = metadata !{null, metadata ![[THIS:[0-9]+]]} - // CHECK: ![[THIS]] = {{.*}} metadata ![[CONST_A:.*]]} ; [ DW_TAG_pointer_type ] + // CHECK: ![[ARGS:[0-9]+]] = !{null, ![[THIS:[0-9]+]]} + // CHECK: ![[THIS]] = {{.*}} ![[CONST_A:.*]]} ; [ DW_TAG_pointer_type ] // CHECK: ![[CONST_A]] = {{.*}} [ DW_TAG_const_type ] - // CHECK: i32 [[@LINE+2]], metadata ![[PRSR:[0-9]+]], {{.*}}[ DW_TAG_subprogram ] [line [[@LINE+2]]] [rvalue reference] [r] - // CHECK: ![[PRSR]] ={{.*}}metadata ![[ARGS]], i32 0, null, null, null}{{.*}}[ DW_TAG_subroutine_type ]{{.*}}[rvalue reference] + // CHECK: !"0x2e\00r\00{{.*}}\00[[@LINE+2]]"{{, [^,]+, [^,]+}}, ![[PRSR:[0-9]+]], {{.*}}[ DW_TAG_subprogram ] [line [[@LINE+2]]] [public] [rvalue reference] [r] + // CHECK: ![[PRSR]] ={{.*}}![[ARGS]], null, null, null}{{.*}}[ DW_TAG_subroutine_type ]{{.*}}[rvalue reference] void r() const &&; }; void g() { A a; // The type of pl is "void (A::*)() const &". - // CHECK: metadata ![[PL:[0-9]+]], i32 0, i32 0} ; [ DW_TAG_auto_variable ] [pl] [line [[@LINE+2]]] - // CHECK: metadata ![[PLSR]], metadata !"{{.*}}"} ; [ DW_TAG_ptr_to_member_type ] + // CHECK: ![[PL:[0-9]+]]} ; [ DW_TAG_auto_variable ] [pl] [line [[@LINE+2]]] + // CHECK: ![[PLSR]], !"{{.*}}"} ; [ DW_TAG_ptr_to_member_type ] auto pl = &A::l; - // CHECK: metadata ![[PR:[0-9]+]], i32 0, i32 0} ; [ DW_TAG_auto_variable ] [pr] [line [[@LINE+2]]] - // CHECK: metadata ![[PRSR]], metadata !"{{.*}}"} ; [ DW_TAG_ptr_to_member_type ] + // CHECK: ![[PR:[0-9]+]]} ; [ DW_TAG_auto_variable ] [pr] [line [[@LINE+2]]] + // CHECK: ![[PRSR]], !"{{.*}}"} ; [ DW_TAG_ptr_to_member_type ] auto pr = &A::r; } diff --git a/test/CodeGenCXX/debug-info-rvalue-ref.cpp b/test/CodeGenCXX/debug-info-rvalue-ref.cpp index 142f587fc62d..36e4aa374244 100644 --- a/test/CodeGenCXX/debug-info-rvalue-ref.cpp +++ b/test/CodeGenCXX/debug-info-rvalue-ref.cpp @@ -8,4 +8,4 @@ void foo (int &&i) printf("%d\n", i); } -// CHECK: metadata !{i32 {{.*}}, null, null, null, i32 0, i64 0, i64 0, i64 0, i32 0, metadata !{{.*}}} ; [ DW_TAG_rvalue_reference_type ] +// CHECK: !"0x42\00\000\000\000\000\000", null, null, !{{.*}}} ; [ DW_TAG_rvalue_reference_type ] diff --git a/test/CodeGenCXX/debug-info-scope.cpp b/test/CodeGenCXX/debug-info-scope.cpp index 0447dc04d56b..e66588d699af 100644 --- a/test/CodeGenCXX/debug-info-scope.cpp +++ b/test/CodeGenCXX/debug-info-scope.cpp @@ -1,32 +1,55 @@ -// RUN: %clang_cc1 -g -emit-llvm %s -o -| FileCheck %s +// RUN: %clang_cc1 -g -std=c++11 -emit-llvm %s -o -| FileCheck %s // // Two variables with the same name in subsequent if staments need to be in separate scopes. // // rdar://problem/14024005 -// -int printf(const char*, ...); +int src(); -char *return_char (int input) -{ - if (input%2 == 0) - return "I am even.\n"; - else - return "I am odd.\n"; -} +void f(); -int main2() { -// CHECK: [ DW_TAG_auto_variable ] [ptr] [line [[@LINE+2]]] -// CHECK: metadata !{i32 {{.*}}, metadata !{{.*}}, i32 [[@LINE+1]], {{.*}}} ; [ DW_TAG_lexical_block ] - if (char *ptr = return_char(1)) { - printf ("%s", ptr); - } -// CHECK: [ DW_TAG_auto_variable ] [ptr] [line [[@LINE+2]]] -// CHECK: metadata !{i32 {{.*}}, metadata !{{.*}}, i32 [[@LINE+1]], {{.*}}} ; [ DW_TAG_lexical_block ] - if (char *ptr = return_char(2)) { - printf ("%s", ptr); +void func() { + // CHECK: = !{!"0x100\00{{.*}}", [[IF1:![0-9]*]], {{.*}} ; [ DW_TAG_auto_variable ] [i] [line [[@LINE+2]]] + // CHECK: [[IF1]] = !{!"0xb\00[[@LINE+1]]\00{{.*}}", !{{.*}}} ; [ DW_TAG_lexical_block ] + if (int i = src()) + f(); + + // CHECK: = !{!"0x100\00{{.*}}", [[IF2:![0-9]*]], {{.*}} ; [ DW_TAG_auto_variable ] [i] [line [[@LINE+2]]] + // CHECK: [[IF2]] = !{!"0xb\00[[@LINE+1]]\00{{.*}}", !{{.*}}} ; [ DW_TAG_lexical_block ] + if (int i = src()) { + f(); + } else + f(); + + // CHECK: = !{!"0x100\00{{.*}}", [[FOR:![0-9]*]], {{.*}} ; [ DW_TAG_auto_variable ] [i] [line [[@LINE+2]]] + // CHECK: [[FOR]] = !{!"0xb\00[[@LINE+1]]\00{{.*}}", !{{.*}}} ; [ DW_TAG_lexical_block ] + for (int i = 0; + // CHECK: = !{!"0x100\00{{.*}}", [[FOR_BODY:![0-9]*]], {{.*}} ; [ DW_TAG_auto_variable ] [b] [line [[@LINE+6]]] + // The scope could be located at 'bool b', but LLVM drops line information for + // scopes anyway, so it's not terribly important. + // FIXME: change the debug info schema to not include locations of scopes, + // since they're not used. + // CHECK: [[FOR_BODY]] = !{!"0xb\00[[@LINE-6]]\00{{.*}}", !{{.*}}} ; [ DW_TAG_lexical_block ] + bool b = i != 10; ++i) + f(); + + // CHECK: = !{!"0x100\00{{.*}}", [[FOR:![0-9]*]], {{.*}} ; [ DW_TAG_auto_variable ] [i] [line [[@LINE+2]]] + // CHECK: [[FOR]] = !{!"0xb\00[[@LINE+1]]\00{{.*}}", !{{.*}}} ; [ DW_TAG_lexical_block ] + for (int i = 0; i != 10; ++i) { + // FIXME: Do not include scopes that have only other scopes (and no variables + // or using declarations) as direct children, they just waste + // space/relocations/etc. + // CHECK: [[FOR_LOOP_INCLUDING_COND:!.*]] = !{!"0xb\00[[@LINE-4]]\00{{.*}}", !{{[0-9]+}}, [[FOR]]} ; [ DW_TAG_lexical_block ] + // CHECK: = !{!"0x100\00{{.*}}", [[FOR_COMPOUND:![0-9]*]], {{.*}} ; [ DW_TAG_auto_variable ] [b] [line [[@LINE+2]]] + // CHECK: [[FOR_COMPOUND]] = !{!"0xb\00[[@LINE-6]]\00{{.*}}", !{{[0-9]+}}, [[FOR_LOOP_INCLUDING_COND]]} ; [ DW_TAG_lexical_block ] + bool b = i % 2; } - else printf ("%s", ptr); - return 0; + int x[] = {1, 2}; + // CHECK: = !{!"0x100\00{{.*}}", [[RANGE_FOR:![0-9]*]], {{.*}} ; [ DW_TAG_auto_variable ] [__range] [line 0] + // CHECK: [[RANGE_FOR]] = !{!"0xb\00[[@LINE+1]]\00{{.*}}", !{{.*}}} ; [ DW_TAG_lexical_block ] + for (int i : x) { + // CHECK: = !{!"0x100\00{{.*}}", [[RANGE_FOR_BODY:![0-9]*]], {{.*}} ; [ DW_TAG_auto_variable ] [i] [line [[@LINE-1]]] + // CHECK: [[RANGE_FOR_BODY]] = !{!"0xb\00[[@LINE-2]]\00{{.*}}", !{{[0-9]+}}, [[RANGE_FOR]]} ; [ DW_TAG_lexical_block ] + } } diff --git a/test/CodeGenCXX/debug-info-static-fns.cpp b/test/CodeGenCXX/debug-info-static-fns.cpp index 136261cdbc0d..41b713cc0674 100644 --- a/test/CodeGenCXX/debug-info-static-fns.cpp +++ b/test/CodeGenCXX/debug-info-static-fns.cpp @@ -7,4 +7,4 @@ namespace A { } // Verify that a is present and mangled. -// CHECK: metadata !"_ZN1AL1aEi", {{.*}}, i32 (i32)* @_ZN1AL1aEi, {{.*}} ; [ DW_TAG_subprogram ] [line 4] [local] [def] [a] +// CHECK: !"0x2e\00a\00a\00_ZN1AL1aEi\00{{.*}}", {{.*}}, i32 (i32)* @_ZN1AL1aEi, {{.*}} ; [ DW_TAG_subprogram ] [line 4] [local] [def] [a] diff --git a/test/CodeGenCXX/debug-info-static-member.cpp b/test/CodeGenCXX/debug-info-static-member.cpp index 1ac235c50f8e..18fd6915189a 100644 --- a/test/CodeGenCXX/debug-info-static-member.cpp +++ b/test/CodeGenCXX/debug-info-static-member.cpp @@ -33,15 +33,72 @@ int main() // why the definition of "a" comes before the declarations while // "b" and "c" come after. -// CHECK: metadata !"_ZTS1X"} ; [ DW_TAG_enumeration_type ] [X] -// CHECK: metadata !"_ZTS1C"} ; [ DW_TAG_class_type ] [C] -// CHECK: ![[DECL_A:[0-9]+]] = metadata {{.*}} [ DW_TAG_member ] [a] [line {{.*}}, size 0, align 0, offset 0] [private] [static] -// CHECK: metadata !"const_a", {{.*}}, i1 true} ; [ DW_TAG_member ] [const_a] [line {{.*}}, size 0, align 0, offset 0] [private] [static] -// CHECK: ![[DECL_B:[0-9]+]] {{.*}} metadata !"b", {{.*}} [ DW_TAG_member ] [b] [line {{.*}}, size 0, align 0, offset 0] [protected] [static] -// CHECK: metadata !"const_b", {{.*}}, float 0x{{.*}}} ; [ DW_TAG_member ] [const_b] [line {{.*}}, size 0, align 0, offset 0] [protected] [static] -// CHECK: ![[DECL_C:[0-9]+]] {{.*}} metadata !"c", {{.*}} [ DW_TAG_member ] [c] [line {{.*}}, size 0, align 0, offset 0] [static] -// CHECK: metadata !"const_c", {{.*}} [ DW_TAG_member ] [const_c] [line {{.*}}, size 0, align 0, offset 0] [static] -// CHECK: metadata !"x_a", {{.*}} [ DW_TAG_member ] [x_a] {{.*}} [static] -// CHECK: metadata !"a", {{.*}} @_ZN1C1aE, metadata ![[DECL_A]]} ; [ DW_TAG_variable ] [a] {{.*}} [def] -// CHECK: metadata !"b", {{.*}} @_ZN1C1bE, metadata ![[DECL_B]]} ; [ DW_TAG_variable ] [b] {{.*}} [def] -// CHECK: metadata !"c", {{.*}} @_ZN1C1cE, metadata ![[DECL_C]]} ; [ DW_TAG_variable ] [c] {{.*}} [def] +// CHECK: !"_ZTS1X"} ; [ DW_TAG_enumeration_type ] [X] +// CHECK: !"_ZTS1C"} ; [ DW_TAG_class_type ] [C] +// CHECK: ![[DECL_A:[0-9]+]] = {{.*}} [ DW_TAG_member ] [a] [line {{.*}}, size 0, align 0, offset 0] [static] +// CHECK: !"0xd\00const_a\00{{.*}}", {{.*}}, i1 true} ; [ DW_TAG_member ] [const_a] [line {{.*}}, size 0, align 0, offset 0] [static] +// CHECK: ![[DECL_B:[0-9]+]] = !{!"0xd\00b\00{{.*}}", {{.*}} [ DW_TAG_member ] [b] [line {{.*}}, size 0, align 0, offset 0] [protected] [static] +// CHECK: !"0xd\00const_b\00{{.*}}", {{.*}}, float 0x{{.*}}} ; [ DW_TAG_member ] [const_b] [line {{.*}}, size 0, align 0, offset 0] [protected] [static] +// CHECK: ![[DECL_C:[0-9]+]] = !{!"0xd\00c\00{{.*}}", {{.*}} [ DW_TAG_member ] [c] [line {{.*}}, size 0, align 0, offset 0] [public] [static] +// CHECK: !"0xd\00const_c\00{{.*}}", {{.*}} [ DW_TAG_member ] [const_c] [line {{.*}}, size 0, align 0, offset 0] [public] [static] +// CHECK: !"0xd\00x_a\00{{.*}}", {{.*}} [ DW_TAG_member ] [x_a] {{.*}} [public] [static] + +// CHECK: ; [ DW_TAG_structure_type ] [static_decl_templ<int>] {{.*}} [def] +// CHECK: ; [ DW_TAG_member ] [static_decl_templ_var] + +// CHECK: [[NS_X:![0-9]+]] = {{.*}} ; [ DW_TAG_namespace ] [x] + +// 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. +namespace { +struct anon_static_decl_struct { + static const int anon_static_decl_var = 117; +}; +} + + +// CHECK: ; [ DW_TAG_structure_type ] [anon_static_decl_struct] {{.*}} [def] +// CHECK: ; [ DW_TAG_member ] [anon_static_decl_var] + +int ref() { + return anon_static_decl_struct::anon_static_decl_var; +} + +template<typename T> +struct static_decl_templ { + static const int static_decl_templ_var = 7; +}; + +template<typename T> +const int static_decl_templ<T>::static_decl_templ_var; + +int static_decl_templ_ref() { + return static_decl_templ<int>::static_decl_templ_var; +} + +// CHECK: !"0x34\00a\00{{.*}}", null, {{.*}} @_ZN1C1aE, ![[DECL_A]]} ; [ DW_TAG_variable ] [a] {{.*}} [def] +// CHECK: !"0x34\00b\00{{.*}}", null, {{.*}} @_ZN1C1bE, ![[DECL_B]]} ; [ DW_TAG_variable ] [b] {{.*}} [def] +// CHECK: !"0x34\00c\00{{.*}}", null, {{.*}} @_ZN1C1cE, ![[DECL_C]]} ; [ DW_TAG_variable ] [c] {{.*}} [def] + +// CHECK-NOT: ; [ DW_TAG_variable ] [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 +// definition, we should also correctly emit the constant value (42) into the +// debug info. +struct V { + virtual ~V(); // cause the definition of 'V' to be omitted by no-standalone-debug optimization + static const int const_va = 42; +}; +// CHECK: i32 42} ; [ DW_TAG_member ] [const_va] [line [[@LINE-2]], +const int V::const_va; + +namespace x { +struct y { + static int z; +}; +int y::z; +} + +// CHECK: !"0x34\00z\00{{.*}}", [[NS_X]], {{.*}} ; [ DW_TAG_variable ] [z] {{.*}} [def] diff --git a/test/CodeGenCXX/debug-info-template-explicit-specialization.cpp b/test/CodeGenCXX/debug-info-template-explicit-specialization.cpp index 506c0d535751..461303884b8d 100644 --- a/test/CodeGenCXX/debug-info-template-explicit-specialization.cpp +++ b/test/CodeGenCXX/debug-info-template-explicit-specialization.cpp @@ -91,3 +91,11 @@ struct j { extern template class j<int>; j<int> jj; // CHECK: ; [ DW_TAG_structure_type ] [j<int, int>] + +template <typename T> +struct k { +}; +template <> +struct k<int>; +template struct k<int>; +// CHECK-NOT: ; [ DW_TAG_structure_type ] [k<int>] diff --git a/test/CodeGenCXX/debug-info-template-limit.cpp b/test/CodeGenCXX/debug-info-template-limit.cpp index e1f23ada21ed..8e05c7f1c81d 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 -fno-standalone-debug -triple %itanium_abi_triple -g %s -o - | FileCheck %s // Check that this pointer type is TC<int> -// CHECK: ![[LINE:[0-9]+]] = {{.*}}"TC<int>", {{.*}} metadata !"_ZTS2TCIiE"} ; [ DW_TAG_class_type ] -// CHECK: metadata !"_ZTS2TCIiE"} ; [ DW_TAG_pointer_type ]{{.*}}[from _ZTS2TCIiE] +// CHECK: ![[LINE:[0-9]+]] = !{!"0x2\00TC<int>\00{{.*}}", {{.*}} !"_ZTS2TCIiE"} ; [ DW_TAG_class_type ] +// CHECK: !"_ZTS2TCIiE"} ; [ DW_TAG_pointer_type ]{{.*}}[from _ZTS2TCIiE] template<typename T> class TC { diff --git a/test/CodeGenCXX/debug-info-template-member.cpp b/test/CodeGenCXX/debug-info-template-member.cpp index c9a3d9b9177c..300b6dbaccf6 100644 --- a/test/CodeGenCXX/debug-info-template-member.cpp +++ b/test/CodeGenCXX/debug-info-template-member.cpp @@ -16,29 +16,35 @@ 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 } -// CHECK: [[FOO_MEM:![0-9]*]], i32 0, null, null, metadata !"_ZTS3foo"} ; [ DW_TAG_structure_type ] [foo] -// CHECK: [[FOO_MEM]] = metadata !{metadata [[FOO_FUNC:![0-9]*]]} -// CHECK: [[FOO_FUNC]] = {{.*}}, metadata !"_ZN3foo4funcEN5outerIS_E5innerE", i32 {{[0-9]*}}, metadata [[FOO_FUNC_TYPE:![0-9]*]], {{.*}} ; [ DW_TAG_subprogram ] {{.*}} [func] -// CHECK: [[FOO_FUNC_TYPE]] = {{.*}}, metadata [[FOO_FUNC_PARAMS:![0-9]*]], i32 0, null, null, null} ; [ DW_TAG_subroutine_type ] -// CHECK: [[FOO_FUNC_PARAMS]] = metadata !{null, metadata !{{[0-9]*}}, metadata [[OUTER_FOO_INNER:![0-9]*]]} -// CHECK: [[OUTER_FOO_INNER]] = {{.*}}, null, metadata !"[[OUTER_FOO_INNER_ID:.*]]"} ; [ DW_TAG_structure_type ] [inner] - -// CHECK: metadata [[VIRT_MEM:![0-9]*]], i32 0, metadata !"_ZTS4virtI4elemE", metadata [[VIRT_TEMP_PARAM:![0-9]*]], metadata !"_ZTS4virtI4elemE"} ; [ DW_TAG_structure_type ] [virt<elem>] {{.*}} [def] -// CHECK: [[VIRT_TEMP_PARAM]] = metadata !{metadata [[VIRT_T:![0-9]*]]} -// CHECK: [[VIRT_T]] = {{.*}}, metadata !"T", metadata !"_ZTS4elem", {{.*}} ; [ DW_TAG_template_type_parameter ] - -// CHECK: [[C:![0-9]*]] = {{.*}}, metadata [[C_MEM:![0-9]*]], i32 0, metadata !"_ZTS7MyClass", null, metadata !"_ZTS7MyClass"} ; [ DW_TAG_structure_type ] [MyClass] -// CHECK: [[C_MEM]] = metadata !{metadata [[C_VPTR:![0-9]*]], metadata [[C_ADD:![0-9]*]], metadata [[C_FUNC:![0-9]*]], metadata [[C_CTOR:![0-9]*]]} +// CHECK: [[FOO_MEM:![0-9]*]], null, null, !"_ZTS3foo"} ; [ DW_TAG_structure_type ] [foo] +// CHECK: [[FOO_MEM]] = !{[[FOO_FUNC:![0-9]*]]} +// CHECK: [[FOO_FUNC]] = !{!"0x2e\00func\00func\00_ZN3foo4funcEN5outerIS_E5innerE\00{{.*}}"{{, [^,]+, [^,]+}}, [[FOO_FUNC_TYPE:![0-9]*]], {{.*}} ; [ DW_TAG_subprogram ] {{.*}} [func] +// CHECK: [[FOO_FUNC_TYPE]] = {{.*}}, [[FOO_FUNC_PARAMS:![0-9]*]], null, null, null} ; [ DW_TAG_subroutine_type ] +// CHECK: [[FOO_FUNC_PARAMS]] = !{null, !{{[0-9]*}}, !"[[OUTER_FOO_INNER_ID:.*]]"} +// CHECK: !{{[0-9]*}} = {{.*}}, null, !"[[OUTER_FOO_INNER_ID]]"} ; [ DW_TAG_structure_type ] [inner] + +// CHECK: [[VIRT_MEM:![0-9]*]], !"_ZTS4virtI4elemE", [[VIRT_TEMP_PARAM:![0-9]*]], !"_ZTS4virtI4elemE"} ; [ DW_TAG_structure_type ] [virt<elem>] {{.*}} [def] +// CHECK: [[VIRT_TEMP_PARAM]] = !{[[VIRT_T:![0-9]*]]} +// CHECK: [[VIRT_T]] = !{!"0x2f\00T\000\000"{{, [^,]+}}, !"_ZTS4elem", {{.*}} ; [ DW_TAG_template_type_parameter ] + +// CHECK: [[C:![0-9]*]] = {{.*}}, [[C_MEM:![0-9]*]], !"_ZTS7MyClass", null, !"_ZTS7MyClass"} ; [ DW_TAG_structure_type ] [MyClass] +// CHECK: [[C_MEM]] = !{[[C_VPTR:![0-9]*]], [[C_FUNC:![0-9]*]]} // CHECK: [[C_VPTR]] = {{.*}} ; [ DW_TAG_member ] [_vptr$MyClass] -// CHECK: [[C_ADD]] = {{.*}} ; [ DW_TAG_subprogram ] [line 4] [add<2>] // CHECK: [[C_FUNC]] = {{.*}} ; [ DW_TAG_subprogram ] [line 7] [func] -// CHECK: [[C_CTOR]] = {{.*}} ; [ DW_TAG_subprogram ] [line 0] [MyClass] -// CHECK: [[ELEM:![0-9]*]] = {{.*}}, metadata [[ELEM_MEM:![0-9]*]], i32 0, null, null, metadata !"_ZTS4elem"} ; [ DW_TAG_structure_type ] [elem] {{.*}} [def] -// CHECK: [[ELEM_MEM]] = metadata !{metadata [[ELEM_X:![0-9]*]]} +// CHECK: [[ELEM:![0-9]*]] = {{.*}}, [[ELEM_MEM:![0-9]*]], null, null, !"_ZTS4elem"} ; [ DW_TAG_structure_type ] [elem] {{.*}} [def] +// CHECK: [[ELEM_MEM]] = !{[[ELEM_X:![0-9]*]]} // CHECK: [[ELEM_X]] = {{.*}} ; [ DW_TAG_member ] [x] {{.*}} [static] [from _ZTS4virtI4elemE] +// 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: !"_ZTS7MyClass", {{.*}} ; [ DW_TAG_subprogram ] [line 4] [add<2>] +// CHECK: !"_ZTS7MyClass", {{.*}} ; [ DW_TAG_subprogram ] [line 0] [MyClass] + template<typename T> struct outer { struct inner { @@ -59,7 +65,7 @@ inline void func() { outer<foo>::inner x; -// CHECK: metadata !"[[OUTER_FOO_INNER_ID]]", i32 {{[0-9]*}}, i32 {{[0-9]*}}, %"struct.outer<foo>::inner"* @x, {{.*}} ; [ DW_TAG_variable ] [x] +// CHECK: !"0x34\00{{.*}}", {{.*}}, !"[[OUTER_FOO_INNER_ID]]", %"struct.outer<foo>::inner"* @x, {{.*}} ; [ DW_TAG_variable ] [x] template <typename T> struct virt { diff --git a/test/CodeGenCXX/debug-info-template-partial-specialization.cpp b/test/CodeGenCXX/debug-info-template-partial-specialization.cpp index cce84af4023c..6940c0fd3503 100644 --- a/test/CodeGenCXX/debug-info-template-partial-specialization.cpp +++ b/test/CodeGenCXX/debug-info-template-partial-specialization.cpp @@ -3,7 +3,7 @@ namespace __pointer_type_imp { template <class _Tp, class _Dp, bool > struct __pointer_type1 {}; - // CHECK: metadata ![[PARAMS:[0-9]+]], metadata !"_ZTSN18__pointer_type_imp15__pointer_type1I1C14default_deleteIS1_ELb0EEE"} ; [ DW_TAG_structure_type ] [__pointer_type1<C, default_delete<C>, false>] [line [[@LINE+1]], size 8, align 8, offset 0] [def] [from ] + // CHECK: ![[PARAMS:[0-9]+]], !"_ZTSN18__pointer_type_imp15__pointer_type1I1C14default_deleteIS1_ELb0EEE"} ; [ DW_TAG_structure_type ] [__pointer_type1<C, default_delete<C>, false>] [line [[@LINE+1]], size 8, align 8, offset 0] [def] [from ] template <class _Tp, class _Dp> struct __pointer_type1<_Tp, _Dp, false> { typedef _Tp* type; @@ -14,7 +14,7 @@ struct __pointer_type2 { // Test that the bool template type parameter is emitted. // - // CHECK: ![[PARAMS]] = metadata !{metadata !{{.*}}, metadata !{{.*}}, metadata ![[FALSE:[0-9]+]]} + // CHECK: ![[PARAMS]] = !{!{{.*}}, !{{.*}}, ![[FALSE:[0-9]+]]} // CHECK: ![[FALSE]] = {{.*}} i8 0, {{.*}}} ; [ DW_TAG_template_value_parameter ] typedef typename __pointer_type_imp::__pointer_type1<_Tp, _Dp, false>::type type; }; diff --git a/test/CodeGenCXX/debug-info-template-quals.cpp b/test/CodeGenCXX/debug-info-template-quals.cpp index 740f7bfa5ce5..15c096f5f94e 100644 --- a/test/CodeGenCXX/debug-info-template-quals.cpp +++ b/test/CodeGenCXX/debug-info-template-quals.cpp @@ -16,12 +16,12 @@ void foo (const char *c) { } // CHECK: [[BS:.*]] = {{.*}} ; [ DW_TAG_structure_type ] [basic_string<char>] [line 4, size 8, align 8, offset 0] [def] [from ] -// CHECK: [[TYPE:![0-9]*]] = metadata !{i32 {{.*}}, metadata [[ARGS:.*]], i32 0, null, null, null} ; [ DW_TAG_subroutine_type ] -// CHECK: [[ARGS]] = metadata !{metadata !{{.*}}, metadata !{{.*}}, metadata [[P:![0-9]*]], metadata [[R:.*]]} -// CHECK: [[P]] = {{.*}}, metadata [[CON:![0-9]*]]} ; [ DW_TAG_pointer_type ] [line 0, size 64, align 64, offset 0] [from ] -// CHECK: [[CON]] = {{.*}}, metadata [[CH:![0-9]*]]} ; [ DW_TAG_const_type ] [line 0, size 0, align 0, offset 0] [from char] +// CHECK: [[TYPE:![0-9]*]] = !{!"0x15\00{{.*}}"{{.*}}, [[ARGS:.*]], null, null, null} ; [ DW_TAG_subroutine_type ] +// CHECK: [[ARGS]] = !{!{{.*}}, !{{.*}}, [[P:![0-9]*]], [[R:.*]]} +// CHECK: [[P]] = {{.*}}, [[CON:![0-9]*]]} ; [ DW_TAG_pointer_type ] [line 0, size 64, align 64, offset 0] [from ] +// CHECK: [[CON]] = {{.*}}, [[CH:![0-9]*]]} ; [ DW_TAG_const_type ] [line 0, size 0, align 0, offset 0] [from char] // CHECK: [[CH]] = {{.*}} ; [ DW_TAG_base_type ] [char] [line 0, size 8, align 8, offset 0, enc DW_ATE_signed_char] -// CHECK: [[R]] = {{.*}}, metadata [[CON2:![0-9]*]]} ; [ DW_TAG_reference_type ] [line 0, size 0, align 0, offset 0] [from ] -// CHECK: [[CON2]] = {{.*}}, metadata !"_ZTS12basic_stringIcE"} ; [ DW_TAG_const_type ] [line 0, size 0, align 0, offset 0] [from _ZTS12basic_stringIcE] -// CHECK: {{.*}} metadata [[TYPE]], {{.*}}, metadata !{{[0-9]*}}, metadata !{{[0-9]*}}, i32 8} ; [ DW_TAG_subprogram ] [line 7] [def] [scope 8] [assign] +// CHECK: [[R]] = {{.*}}, [[CON2:![0-9]*]]} ; [ DW_TAG_reference_type ] [line 0, size 0, align 0, offset 0] [from ] +// CHECK: [[CON2]] = {{.*}}, !"_ZTS12basic_stringIcE"} ; [ DW_TAG_const_type ] [line 0, size 0, align 0, offset 0] [from _ZTS12basic_stringIcE] +// CHECK: !"0x2e\00assign\00{{.*}}\008"{{, [^,]+, [^,]+}}, !8, {{.*}} ; [ DW_TAG_subprogram ] [line 7] [def] [scope 8] [assign] diff --git a/test/CodeGenCXX/debug-info-template.cpp b/test/CodeGenCXX/debug-info-template.cpp index d071830eaf67..17b945018387 100644 --- a/test/CodeGenCXX/debug-info-template.cpp +++ b/test/CodeGenCXX/debug-info-template.cpp @@ -1,92 +1,106 @@ // RUN: %clang -S -emit-llvm -target x86_64-unknown_unknown -g %s -o - -std=c++11 | FileCheck %s -// CHECK: {{.*}}, i1 false, metadata !"", i32 0, metadata !{{[0-9]]*}}, metadata [[RETAIN:![0-9]*]], {{.*}} ; [ DW_TAG_compile_unit ] -// CHECK: [[EMPTY:![0-9]*]] = metadata !{} -// CHECK: [[RETAIN]] = metadata !{metadata !{{[0-9]]*}}, metadata [[FOO:![0-9]*]], +// CHECK: !"0x11\00{{.*}}"{{, [^,]+, [^,]+}}, [[RETAIN:![0-9]*]], {{.*}} ; [ DW_TAG_compile_unit ] +// CHECK: [[EMPTY:![0-9]*]] = !{} +// CHECK: [[RETAIN]] = !{!{{[0-9]]*}}, [[FOO:![0-9]*]], -// CHECK: [[TC:![0-9]*]] = {{.*}}, metadata [[TCARGS:![0-9]*]], metadata !"{{.*}}"} ; [ DW_TAG_structure_type ] [TC<unsigned int, 2, &glb, &foo::e, &foo::f, &func, tmpl_impl, 1, 2, 3>] -// CHECK: [[TCARGS]] = metadata !{metadata [[TCARG1:![0-9]*]], metadata [[TCARG2:![0-9]*]], metadata [[TCARG3:![0-9]*]], metadata [[TCARG4:![0-9]*]], metadata [[TCARG5:![0-9]*]], metadata [[TCARG6:![0-9]*]], metadata [[TCARG7:![0-9]*]], metadata [[TCARG8:![0-9]*]]} +// CHECK: [[TC:![0-9]*]] = {{.*}}, [[TCARGS:![0-9]*]], !"{{.*}}"} ; [ DW_TAG_structure_type ] [TC<unsigned int, 2, &glb, &foo::e, &foo::f, &foo::g, 1, 2, 3>] +// CHECK: [[TCARGS]] = !{[[TCARG1:![0-9]*]], [[TCARG2:![0-9]*]], [[TCARG3:![0-9]*]], [[TCARG4:![0-9]*]], [[TCARG5:![0-9]*]], [[TCARG6:![0-9]*]], [[TCARG7:![0-9]*]]} // // We seem to be missing file/line/col info on template value parameters - // metadata supports it but it's not populated. GCC doesn't emit it either, // perhaps we should just drop it from the metadata. // -// CHECK: [[TCARG1]] = {{.*}}metadata !"T", metadata [[UINT:![0-9]*]], {{.*}} ; [ DW_TAG_template_type_parameter ] +// CHECK: [[TCARG1]] = !{!"0x2f\00T\000\000", null, [[UINT:![0-9]*]], null} ; [ DW_TAG_template_type_parameter ] // CHECK: [[UINT:![0-9]*]] = {{.*}} ; [ DW_TAG_base_type ] [unsigned int] -// CHECK: [[TCARG2]] = {{.*}}metadata !"", metadata [[UINT]], i32 2, {{.*}} ; [ DW_TAG_template_value_parameter ] -// CHECK: [[TCARG3]] = {{.*}}metadata !"x", metadata [[INTPTR:![0-9]*]], i32* @glb, {{.*}} ; [ DW_TAG_template_value_parameter ] -// CHECK: [[INTPTR]] = {{.*}}, metadata [[INT:![0-9]*]]} ; [ DW_TAG_pointer_type ] [line 0, size 64, align 64, offset 0] [from int] +// CHECK: [[TCARG2]] = !{!"0x30\00\00{{.*}}", {{[^,]+}}, [[UINT]], i32 2, {{.*}} ; [ DW_TAG_template_value_parameter ] +// CHECK: [[TCARG3]] = !{!"0x30\00x\00{{.*}}", {{[^,]+}}, [[CINTPTR:![0-9]*]], i32* @glb, {{.*}} ; [ DW_TAG_template_value_parameter ] +// CHECK: [[CINTPTR]] = {{.*}}, [[CINT:![0-9]*]]} ; [ DW_TAG_pointer_type ] {{.*}} [from ] +// CHECK: [[CINT]] = {{.*}}, [[INT:![0-9]*]]} ; [ DW_TAG_const_type ] {{.*}} [from int] // CHECK: [[INT]] = {{.*}} ; [ DW_TAG_base_type ] [int] -// CHECK: [[TCARG4]] = {{.*}}metadata !"a", metadata [[MEMINTPTR:![0-9]*]], i64 8, {{.*}} ; [ DW_TAG_template_value_parameter ] -// CHECK: [[MEMINTPTR]] = {{.*}}, metadata !"_ZTS3foo"} ; [ DW_TAG_ptr_to_member_type ] {{.*}}[from int] +// CHECK: [[TCARG4]] = !{!"0x30\00a\00{{.*}}", {{[^,]+}}, [[MEMINTPTR:![0-9]*]], i64 8, {{.*}} ; [ DW_TAG_template_value_parameter ] +// CHECK: [[MEMINTPTR]] = {{.*}}, !"_ZTS3foo"} ; [ DW_TAG_ptr_to_member_type ] {{.*}}[from int] // // 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]] = {{.*}}metadata !"b", metadata [[MEMFUNPTR:![0-9]*]], { i64, i64 } { i64 ptrtoint (void (%struct.foo*)* @_ZN3foo1fEv to i64), i64 0 }, {{.*}} ; [ DW_TAG_template_value_parameter ] -// CHECK: [[MEMFUNPTR]] = {{.*}}, metadata [[FTYPE:![0-9]*]], metadata !"_ZTS3foo"} ; [ DW_TAG_ptr_to_member_type ] -// CHECK: [[FTYPE]] = {{.*}}, metadata [[FARGS:![0-9]*]], i32 0, null, null, null} ; [ DW_TAG_subroutine_type ] -// CHECK: [[FARGS]] = metadata !{null, metadata [[FARG1:![0-9]*]]} +// CHECK: [[TCARG5]] = !{!"0x30\00b\00{{.*}}", {{[^,]+}}, [[MEMFUNPTR:![0-9]*]], { i64, i64 } { i64 ptrtoint (void (%struct.foo*)* @_ZN3foo1fEv to i64), i64 0 }, {{.*}} ; [ DW_TAG_template_value_parameter ] +// CHECK: [[MEMFUNPTR]] = {{.*}}, [[FTYPE:![0-9]*]], !"_ZTS3foo"} ; [ DW_TAG_ptr_to_member_type ] +// CHECK: [[FTYPE]] = {{.*}}, [[FARGS:![0-9]*]], null, null, null} ; [ DW_TAG_subroutine_type ] +// CHECK: [[FARGS]] = !{null, [[FARG1:![0-9]*]]} // CHECK: [[FARG1]] = {{.*}} ; [ DW_TAG_pointer_type ] [line 0, size 64, align 64, offset 0] [artificial] [from _ZTS3foo] // -// CHECK: [[TCARG6]] = {{.*}}metadata !"f", metadata [[FUNPTR:![0-9]*]], void ()* @_Z4funcv, {{.*}} ; [ DW_TAG_template_value_parameter ] -// CHECK: [[FUNPTR]] = {{.*}}, metadata [[FUNTYPE:![0-9]*]]} ; [ DW_TAG_pointer_type ] -// CHECK: [[FUNTYPE]] = {{.*}}, metadata [[FUNARGS:![0-9]*]], i32 0, null, null, null} ; [ DW_TAG_subroutine_type ] -// CHECK: [[FUNARGS]] = metadata !{null} -// CHECK: [[TCARG7]] = {{.*}}metadata !"tmpl", null, metadata !"tmpl_impl", {{.*}} ; [ DW_TAG_GNU_template_template_param ] -// CHECK: [[TCARG8]] = {{.*}}metadata !"Is", null, metadata [[TCARG8_VALS:![0-9]*]], {{.*}} ; [ DW_TAG_GNU_template_parameter_pack ] -// CHECK: [[TCARG8_VALS]] = metadata !{metadata [[TCARG8_1:![0-9]*]], metadata [[TCARG8_2:![0-9]*]], metadata [[TCARG8_3:![0-9]*]]} -// CHECK: [[TCARG8_1]] = {{.*}}metadata !"", metadata [[INT]], i32 1, {{.*}} ; [ DW_TAG_template_value_parameter ] -// CHECK: [[TCARG8_2]] = {{.*}}metadata !"", metadata [[INT]], i32 2, {{.*}} ; [ DW_TAG_template_value_parameter ] -// CHECK: [[TCARG8_3]] = {{.*}}metadata !"", metadata [[INT]], i32 3, {{.*}} ; [ DW_TAG_template_value_parameter ] +// CHECK: [[TCARG6]] = !{!"0x30\00f\00{{.*}}", {{[^,]+}}, [[FUNPTR:![0-9]*]], void ()* @_ZN3foo1gEv, {{.*}} ; [ DW_TAG_template_value_parameter ] +// CHECK: [[FUNPTR]] = {{.*}}, [[FUNTYPE:![0-9]*]]} ; [ DW_TAG_pointer_type ] +// CHECK: [[FUNTYPE]] = {{.*}}, [[FUNARGS:![0-9]*]], null, null, null} ; [ DW_TAG_subroutine_type ] +// CHECK: [[FUNARGS]] = !{null} +// CHECK: [[TCARG7]] = !{!"0x4107\00Is\000\000", null, null, [[TCARG7_VALS:![0-9]*]], null} ; [ DW_TAG_GNU_template_parameter_pack ] +// CHECK: [[TCARG7_VALS]] = !{[[TCARG7_1:![0-9]*]], [[TCARG7_2:![0-9]*]], [[TCARG7_3:![0-9]*]]} +// CHECK: [[TCARG7_1]] = !{!"0x30\00\00{{.*}}", {{[^,]+}}, [[INT]], i32 1, {{.*}} ; [ DW_TAG_template_value_parameter ] +// CHECK: [[TCARG7_2]] = !{!"0x30\00\00{{.*}}", {{[^,]+}}, [[INT]], i32 2, {{.*}} ; [ DW_TAG_template_value_parameter ] +// CHECK: [[TCARG7_3]] = !{!"0x30\00\00{{.*}}", {{[^,]+}}, [[INT]], i32 3, {{.*}} ; [ DW_TAG_template_value_parameter ] // // 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]] = {{.*}}, metadata !"_ZTS3foo"} ; [ DW_TAG_structure_type ] [foo] -// CHECK: metadata !"f", metadata !"_ZN3foo1fEv", i32 {{[0-9]*}}, metadata [[FTYPE:![0-9]*]], +// CHECK: [[FOO]] = {{.*}}, !"_ZTS3foo"} ; [ DW_TAG_structure_type ] [foo] +// CHECK: !"0x2e\00f\00f\00_ZN3foo1fEv\00{{.*}}", [[FTYPE:![0-9]*]], {{.*}} ; [ DW_TAG_subprogram ] // - -// CHECK: metadata !{i32 {{[0-9]*}}, metadata !{{[0-9]*}}, metadata !"_ZTS2TCIjLj2EXadL_Z3glbEEXadL_ZN3foo1eEEEXadL_ZNS0_1fEvEEXadL_Z4funcvEE9tmpl_implJLi1ELi2ELi3EEE", {{.*}}, metadata !"[[TCNESTED:.*]]"} ; [ DW_TAG_structure_type ] [nested] -// CHECK: metadata [[TCNARGS:![0-9]*]], metadata !"[[TCNT:.*]]"} ; [ DW_TAG_structure_type ] [TC<int, -3, nullptr, nullptr, nullptr, nullptr, tmpl_impl>] -// CHECK: [[TCNARGS]] = metadata !{metadata [[TCNARG1:![0-9]*]], metadata [[TCNARG2:![0-9]*]], metadata [[TCNARG3:![0-9]*]], metadata [[TCNARG4:![0-9]*]], metadata [[TCNARG5:![0-9]*]], metadata [[TCNARG6:![0-9]*]], metadata [[TCARG7:![0-9]*]], metadata [[TCNARG8:![0-9]*]]} -// CHECK: [[TCNARG1]] = {{.*}}metadata !"T", metadata [[INT]], {{.*}} ; [ DW_TAG_template_type_parameter ] -// CHECK: [[TCNARG2]] = {{.*}}metadata !"", metadata [[INT]], i32 -3, {{.*}} ; [ DW_TAG_template_value_parameter ] -// CHECK: [[TCNARG3]] = {{.*}}metadata !"x", metadata [[INTPTR]], i8 0, {{.*}} ; [ DW_TAG_template_value_parameter ] +// CHECK: !"0x13\00{{.*}}", !{{[0-9]*}}, !"_ZTS2TCIjLj2EXadL_Z3glbEEXadL_ZN3foo1eEEEXadL_ZNS0_1fEvEEXadL_ZNS0_1gEvEEJLi1ELi2ELi3EEE", {{.*}}, !"[[TCNESTED:.*]]"} ; [ DW_TAG_structure_type ] [nested] +// CHECK: [[TCNARGS:![0-9]*]], !"[[TCNT:.*]]"} ; [ DW_TAG_structure_type ] [TC<int, -3, nullptr, nullptr, nullptr, nullptr>] +// 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]] = !{!"0x2f\00T\000\000", null, [[INT]], null} ; [ DW_TAG_template_type_parameter ] +// CHECK: [[TCNARG2]] = !{!"0x30\00\000\000", null, [[INT]], i32 -3, null} ; [ DW_TAG_template_value_parameter ] +// CHECK: [[TCNARG3]] = !{!"0x30\00x\000\000", null, [[CINTPTR]], i8 0, null} ; [ DW_TAG_template_value_parameter ] // 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]] = {{.*}}metadata !"a", metadata [[MEMINTPTR]], i64 -1, {{.*}} ; [ DW_TAG_template_value_parameter ] +// CHECK: [[TCNARG4]] = !{!"0x30\00a\000\000", null, [[MEMINTPTR]], i64 -1, null} ; [ DW_TAG_template_value_parameter ] // // 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 // naturally from the LLVM CodeGen side once we decide how to handle non-null // member function pointers. For now, it's simpler just to emit the 'i8 0'. // -// CHECK: [[TCNARG5]] = {{.*}}metadata !"b", metadata [[MEMFUNPTR]], i8 0, {{.*}} ; [ DW_TAG_template_value_parameter ] -// CHECK: [[TCNARG6]] = {{.*}}metadata !"f", metadata [[FUNPTR]], i8 0, {{.*}} ; [ DW_TAG_template_value_parameter ] -// CHECK: [[TCNARG8]] = {{.*}}metadata !"Is", null, metadata [[EMPTY]], {{.*}} ; [ DW_TAG_GNU_template_parameter_pack ] - -// CHECK: metadata [[PTOARGS:![0-9]*]], metadata !"{{.*}}"} ; [ DW_TAG_structure_type ] [PaddingAtEndTemplate<&PaddedObj>] -// CHECK: [[PTOARGS]] = metadata !{metadata [[PTOARG1:![0-9]*]]} -// CHECK: [[PTOARG1]] = {{.*}}metadata !"", metadata [[CONST_PADDINGATEND_PTR:![0-9]*]], { i32, i8, [3 x i8] }* @PaddedObj, {{.*}} ; [ DW_TAG_template_value_parameter ] +// CHECK: [[TCNARG5]] = !{!"0x30\00b\000\000", null, [[MEMFUNPTR]], i8 0, null} ; [ DW_TAG_template_value_parameter ] +// CHECK: [[TCNARG6]] = !{!"0x30\00f\000\000", null, [[FUNPTR]], i8 0, null} ; [ DW_TAG_template_value_parameter ] +// CHECK: [[TCNARG7]] = !{!"0x4107\00Is\000\000", null, null, [[EMPTY]], null} ; [ DW_TAG_GNU_template_parameter_pack ] + +// FIXME: these parameters should probably be rendered as 'glb' rather than +// '&glb', since they're references, not pointers. +// CHECK: [[NNARGS:![0-9]*]], !"[[NNT:.*]]"} ; [ DW_TAG_structure_type ] [NN<tmpl_impl, &glb, &glb>] +// CHECK: [[NNARGS]] = !{[[NNARG1:![0-9]*]], [[NNARG2:![0-9]*]], [[NNARG3:![0-9]*]]} +// CHECK: [[NNARG1]] = !{!"0x4106\00tmpl\000\000", null, null, !"tmpl_impl", null} ; [ DW_TAG_GNU_template_template_param ] +// CHECK: [[NNARG2]] = !{!"0x30\00lvr\00{{.*}}", {{[^,]+}}, [[INTLVR:![0-9]*]], i32* @glb, {{.*}} ; [ DW_TAG_template_value_parameter ] +// CHECK: [[INTLVR]] = {{.*}}, [[INT]]} ; [ DW_TAG_reference_type ] {{.*}} [from int] +// CHECK: [[NNARG3]] = !{!"0x30\00rvr\00{{.*}}", {{[^,]+}}, [[INTRVR:![0-9]*]], i32* @glb, {{.*}} ; [ DW_TAG_template_value_parameter ] +// CHECK: [[INTRVR]] = {{.*}}, [[INT]]} ; [ DW_TAG_rvalue_reference_type ] {{.*}} [from int] + +// CHECK: [[PTOARGS:![0-9]*]], !"{{.*}}"} ; [ DW_TAG_structure_type ] [PaddingAtEndTemplate<&PaddedObj>] +// CHECK: [[PTOARGS]] = !{[[PTOARG1:![0-9]*]]} +// CHECK: [[PTOARG1]] = !{!"0x30\00\000\000", null, [[CONST_PADDINGATEND_PTR:![0-9]*]], %struct.PaddingAtEnd* @PaddedObj, null} ; [ DW_TAG_template_value_parameter ] // CHECK: [[CONST_PADDINGATEND_PTR]] = {{.*}} ; [ DW_TAG_pointer_type ] [line 0, size 64, align 64, offset 0] [from _ZTS12PaddingAtEnd] -// CHECK: metadata !"[[TCNESTED]]", i32 0, i32 1, %"struct.TC<unsigned int, 2, &glb, &foo::e, &foo::f, &func, tmpl_impl, 1, 2, 3>::nested"* @tci, null} ; [ DW_TAG_variable ] [tci] +// CHECK: !"[[TCNESTED]]", %"struct.TC<unsigned int, 2, &glb, &foo::e, &foo::f, &foo::g, 1, 2, 3>::nested"* @tci, null} ; [ DW_TAG_variable ] [tci] -// CHECK: metadata !"[[TCNT]]", i32 0, i32 1, %struct.TC* @tcn, null} ; [ DW_TAG_variable ] [tcn] +// CHECK: !"[[TCNT]]", %struct.TC* @tcn, null} ; [ DW_TAG_variable ] [tcn] + +// CHECK: !"[[NNT]]", %struct.NN* @nn, null} ; [ DW_TAG_variable ] [nn] struct foo { char pad[8]; // make the member pointer to 'e' a bit more interesting (nonzero) int e; void f(); + static void g(); }; -template<typename T, T, int *x, int foo::*a, void (foo::*b)(), void (*f)(), template<typename> class tmpl, int ...Is> +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 { }; @@ -95,12 +109,18 @@ struct TC { 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 { }; -TC<unsigned, 2, &glb, &foo::e, &foo::f, &func, tmpl_impl, 1, 2, 3>::nested tci; -TC<int, -3, nullptr, nullptr, nullptr, nullptr, tmpl_impl> tcn; +template <template <typename> class tmpl, int &lvr, int &&rvr> +struct NN { +}; + +NN<tmpl_impl, glb, glb> nn; struct PaddingAtEnd { int i; @@ -109,7 +129,7 @@ struct PaddingAtEnd { PaddingAtEnd PaddedObj = {}; -template <const PaddingAtEnd *> +template <PaddingAtEnd *> struct PaddingAtEndTemplate { }; diff --git a/test/CodeGenCXX/debug-info-thunk.cpp b/test/CodeGenCXX/debug-info-thunk.cpp index 1d6f1a77b49a..9f187901f7ec 100644 --- a/test/CodeGenCXX/debug-info-thunk.cpp +++ b/test/CodeGenCXX/debug-info-thunk.cpp @@ -14,4 +14,4 @@ struct C : A, B { void C::f() { } -// CHECK: metadata !"_ZThn{{4|8}}_N1C1fEv", i32 15, {{.*}} ; [ DW_TAG_subprogram ] [line 15] [def]{{$}} +// CHECK: !"0x2e\00\00\00_ZThn{{[48]}}_N1C1fEv\0015\00{{.*}}", {{.*}} ; [ DW_TAG_subprogram ] [line 15] [def]{{$}} diff --git a/test/CodeGenCXX/debug-info-union-template.cpp b/test/CodeGenCXX/debug-info-union-template.cpp index 570520d03d9e..aa66e3f9de1a 100644 --- a/test/CodeGenCXX/debug-info-union-template.cpp +++ b/test/CodeGenCXX/debug-info-union-template.cpp @@ -10,6 +10,6 @@ namespace PR15637 { Value<float> f; } -// CHECK: {{.*}}, metadata !"Value<float>", {{.*}}, null, metadata [[TTPARAM:.*]], metadata !"_ZTSN7PR156375ValueIfEE"} ; [ DW_TAG_union_type ] [Value<float>] -// CHECK: [[TTPARAM]] = metadata !{metadata [[PARAMS:.*]]} -// CHECK: [[PARAMS]] = metadata !{{{.*}}metadata !"T",{{.*}}} ; [ DW_TAG_template_type_parameter ] +// CHECK: !"0x17\00Value<float>\00{{.*}}", {{.*}}, [[TTPARAM:![0-9]+]], !"_ZTSN7PR156375ValueIfEE"} ; [ DW_TAG_union_type ] [Value<float>] +// CHECK: [[TTPARAM]] = !{[[PARAMS:.*]]} +// CHECK: [[PARAMS]] = !{!"0x2f\00T\000\000", {{.*}} ; [ DW_TAG_template_type_parameter ] diff --git a/test/CodeGenCXX/debug-info-uuid.cpp b/test/CodeGenCXX/debug-info-uuid.cpp index 6137400de07c..b7e532ba2b31 100644 --- a/test/CodeGenCXX/debug-info-uuid.cpp +++ b/test/CodeGenCXX/debug-info-uuid.cpp @@ -1,14 +1,20 @@ // RUN: %clang_cc1 -emit-llvm -fms-extensions -triple=x86_64-pc-win32 -g %s -o - -std=c++11 | FileCheck %s -// RUN: not %clang_cc1 -emit-llvm -fms-extensions -triple=x86_64-unknown-unknown -g %s -o - -std=c++11 2>&1 | FileCheck %s --check-prefix=CHECK-ITANIUM +// RUN: %clang_cc1 -emit-llvm -fms-extensions -triple=x86_64-unknown-unknown -g %s -o - -std=c++11 2>&1 | FileCheck %s --check-prefix=CHECK-ITANIUM -// CHECK: metadata [[TGIARGS:![0-9]*]], null} ; [ DW_TAG_structure_type ] [tmpl_guid<&__uuidof(uuid)>] -// CHECK: [[TGIARGS]] = metadata !{metadata [[TGIARG1:![0-9]*]]} -// CHECK: [[TGIARG1]] = {{.*}}metadata !"", metadata [[CONST_GUID_PTR:![0-9]*]], { i32, i16, i16, [8 x i8] }* @_GUID_12345678_1234_1234_1234_1234567890ab, {{.*}} ; [ DW_TAG_template_value_parameter ] -// CHECK: [[CONST_GUID_PTR]] = {{.*}}, metadata [[CONST_GUID:![0-9]*]]} ; [ DW_TAG_pointer_type ] [line 0, size 64, align 64, offset 0] [from ] -// CHECK: [[CONST_GUID]] = {{.*}}, metadata [[GUID:![0-9]*]]} ; [ DW_TAG_const_type ] [line 0, size 0, align 0, offset 0] [from _GUID] +// CHECK: [[TGIARGS:![0-9]*]], null} ; [ DW_TAG_structure_type ] [tmpl_guid<&__uuidof(uuid)>] +// CHECK: [[TGIARGS]] = !{[[TGIARG1:![0-9]*]]} +// CHECK: [[TGIARG1]] = !{!"0x30\00\00{{.*}}", {{[^,]+}}, [[CONST_GUID_PTR:![0-9]*]], { i32, i16, i16, [8 x i8] }* @_GUID_12345678_1234_1234_1234_1234567890ab, {{.*}} ; [ DW_TAG_template_value_parameter ] +// CHECK: [[CONST_GUID_PTR]] = {{.*}}, [[CONST_GUID:![0-9]*]]} ; [ DW_TAG_pointer_type ] [line 0, size 64, align 64, offset 0] [from ] +// CHECK: [[CONST_GUID]] = {{.*}}, [[GUID:![0-9]*]]} ; [ DW_TAG_const_type ] [line 0, size 0, align 0, offset 0] [from _GUID] // CHECK: [[GUID]] = {{.*}} ; [ DW_TAG_structure_type ] [_GUID] -// CHECK-ITANIUM: error: cannot yet mangle expression type CXXUuidofExpr +// CHECK: [[TGI2ARGS:![0-9]*]], null} ; [ DW_TAG_structure_type ] [tmpl_guid2<__uuidof(uuid)>] +// CHECK: [[TGI2ARGS]] = !{[[TGI2ARG1:![0-9]*]]} +// CHECK: [[TGI2ARG1]] = !{!"0x30\00\00{{.*}}", {{[^,]+}}, [[CONST_GUID_REF:![0-9]*]], { i32, i16, i16, [8 x i8] }* @_GUID_12345678_1234_1234_1234_1234567890ab, {{.*}} ; [ DW_TAG_template_value_parameter ] +// CHECK: [[CONST_GUID_REF]] = {{.*}}, [[CONST_GUID:![0-9]*]]} ; [ DW_TAG_reference_type ] [line 0, size 0, align 0, offset 0] [from ] + +// CHECK-ITANIUM: !"_ZTS9tmpl_guidIXadu8__uuidoft4uuidEE"} ; [ DW_TAG_structure_type ] [tmpl_guid<&__uuidof(uuid)>] +// CHECK-ITANIUM: !"_ZTS10tmpl_guid2IXu8__uuidoft4uuidEE"} ; [ DW_TAG_structure_type ] [tmpl_guid2<__uuidof(uuid)>] struct _GUID; template <const _GUID *> @@ -17,3 +23,7 @@ struct tmpl_guid { struct __declspec(uuid("{12345678-1234-1234-1234-1234567890ab}")) uuid; tmpl_guid<&__uuidof(uuid)> tgi; + +template <const _GUID &> +struct tmpl_guid2 {}; +tmpl_guid2<__uuidof(uuid)> tgi2; diff --git a/test/CodeGenCXX/debug-info-varargs.cpp b/test/CodeGenCXX/debug-info-varargs.cpp index cc92477dbb92..25e8f350b055 100644 --- a/test/CodeGenCXX/debug-info-varargs.cpp +++ b/test/CodeGenCXX/debug-info-varargs.cpp @@ -2,21 +2,21 @@ struct A { - // CHECK-DAG: ", i32 [[@LINE+1]], metadata ![[ATY:[0-9]+]]{{.*}}[ DW_TAG_subprogram ]{{.*}}[a] + // CHECK-DAG: !"0x2e\00a\00a\00_ZN1A1aEiz\00[[@LINE+1]]\00{{[^,]*}}"{{, [^,]+, [^,]+}}, ![[ATY:[0-9]+]]{{.*}}[ DW_TAG_subprogram ]{{.*}}[a] void a(int c, ...) {} - // CHECK: ![[ATY]] ={{.*}} metadata ![[AARGS:[0-9]+]], i32 0, null, null, null} ; [ DW_TAG_subroutine_type ] - // CHECK: ![[AARGS]] = {{.*}} metadata ![[UNSPEC:[0-9]+]]} - // CHECK: ![[UNSPEC]] = {{.*}} [ DW_TAG_unspecified_parameters ] + // CHECK: ![[ATY]] ={{.*}} ![[AARGS:[0-9]+]], null, null, null} ; [ DW_TAG_subroutine_type ] + // 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: ", i32 [[@LINE+1]], metadata ![[BTY:[0-9]+]]{{.*}}[ DW_TAG_subprogram ]{{.*}}[b] + // CHECK: !"0x2e\00b\00b\00_Z1biz\00[[@LINE+1]]\00{{[^,]*}}"{{, [^,]+, [^,]+}}, ![[BTY:[0-9]+]]{{.*}}[ DW_TAG_subprogram ]{{.*}}[b] void b(int c, ...) { - // CHECK: ![[BTY]] ={{.*}} metadata ![[BARGS:[0-9]+]], i32 0, null, null, null} ; [ DW_TAG_subroutine_type ] - // CHECK: ![[BARGS]] = {{.*}} metadata ![[UNSPEC:[0-9]+]]} + // CHECK: ![[BTY]] ={{.*}} ![[BARGS:[0-9]+]], null, null, null} ; [ DW_TAG_subroutine_type ] + // CHECK: ![[BARGS]] = !{null, !{{[0-9]+}}, null} A a; - // CHECK: metadata ![[PST:[0-9]+]], i32 0, i32 0} ; [ DW_TAG_auto_variable ] [fptr] [line [[@LINE+1]]] + // CHECK: !"0x100\00fptr\00[[@LINE+1]]\000"{{, [^,]+, [^,]+}}, ![[PST:[0-9]+]]} ; [ DW_TAG_auto_variable ] [fptr] [line [[@LINE+1]]] void (*fptr)(int, ...) = b; - // CHECK: ![[PST]] ={{.*}} metadata ![[BTY]]} ; [ DW_TAG_pointer_type ] + // CHECK: ![[PST]] ={{.*}} ![[BTY]]} ; [ DW_TAG_pointer_type ] } diff --git a/test/CodeGenCXX/debug-info-wchar.cpp b/test/CodeGenCXX/debug-info-wchar.cpp index 6f5384966b99..5b5fdccce14e 100644 --- a/test/CodeGenCXX/debug-info-wchar.cpp +++ b/test/CodeGenCXX/debug-info-wchar.cpp @@ -1,5 +1,5 @@ // RUN: %clang_cc1 -emit-llvm -g %s -o -| FileCheck %s void foo() { -// CHECK: metadata !"wchar_t", +// CHECK: !"0x24\00wchar_t\00{{.*}}", null, null} ; [ DW_TAG_base_type ] [wchar_t] const wchar_t w = L'x'; } diff --git a/test/CodeGenCXX/debug-info-windows-dtor.cpp b/test/CodeGenCXX/debug-info-windows-dtor.cpp new file mode 100644 index 000000000000..a94f2b06ee72 --- /dev/null +++ b/test/CodeGenCXX/debug-info-windows-dtor.cpp @@ -0,0 +1,22 @@ +// RUN: %clang_cc1 -triple i386-unknown-windows-msvc -std=c++11 -emit-llvm -gline-tables-only %s -o - | FileCheck %s + +struct A { + virtual ~A() {} +}; + +struct B { + virtual ~B() {} +}; + +template<typename T> +struct AB: A, B { +}; + +template struct AB<int>; + +// CHECK-LABEL: define {{.*}}@"\01??_E?$AB@H@@W3AEPAXI@Z" +// CHECK: call {{.*}}@"\01??_G?$AB@H@@UAEPAXI@Z"({{.*}}) #{{[0-9]*}}, !dbg [[THUNK_LOC:![0-9]*]] +// CHECK-LABEL: define + +// CHECK: [[THUNK_VEC_DEL_DTOR:![0-9]*]] = {{.*}} @"\01??_E?$AB@H@@W3AEPAXI@Z", {{.*}}; [ DW_TAG_subprogram ] +// CHECK: [[THUNK_LOC]] = !MDLocation(line: 15, scope: [[THUNK_VEC_DEL_DTOR]]) diff --git a/test/CodeGenCXX/debug-info-zero-length-arrays.cpp b/test/CodeGenCXX/debug-info-zero-length-arrays.cpp index 101796509da3..f1ba636729bc 100644 --- a/test/CodeGenCXX/debug-info-zero-length-arrays.cpp +++ b/test/CodeGenCXX/debug-info-zero-length-arrays.cpp @@ -6,7 +6,7 @@ class A { }; A a; -// CHECK: metadata [[ARRAY_TYPE:![0-9]*]]} ; [ DW_TAG_member ] [x] -// CHECK: metadata [[ELEM_TYPE:![0-9]*]], i32 0, null, null, null} ; [ DW_TAG_array_type ] [line 0, size 0, align 32, offset 0] [from int] -// CHECK: [[ELEM_TYPE]] = metadata !{metadata [[SUBRANGE:.*]]} -// CHECK: [[SUBRANGE]] = metadata !{i32 786465, i64 0, i64 -1} ; [ DW_TAG_subrange_type ] [unbounded] +// CHECK: [[ARRAY_TYPE:![0-9]*]]} ; [ DW_TAG_member ] [x] +// CHECK: !"0x1\00\000\000\0032\000\000\000", null, null, {{![0-9]+}}, [[ELEM_TYPE:![0-9]+]], null, null, null} ; [ DW_TAG_array_type ] [line 0, size 0, align 32, offset 0] [from int] +// CHECK: [[ELEM_TYPE]] = !{[[SUBRANGE:.*]]} +// CHECK: [[SUBRANGE]] = !{!"0x21\000\00-1"} ; [ DW_TAG_subrange_type ] [unbounded] diff --git a/test/CodeGenCXX/debug-info.cpp b/test/CodeGenCXX/debug-info.cpp index 7c89dfc04ce1..f4d1f00137d6 100644 --- a/test/CodeGenCXX/debug-info.cpp +++ b/test/CodeGenCXX/debug-info.cpp @@ -1,4 +1,6 @@ // RUN: %clang_cc1 -triple x86_64-none-linux-gnu -emit-llvm -g %s -o - | FileCheck %s +// RUN: %clang_cc1 -triple i686-pc-windows-msvc -emit-llvm -g %s -o - | FileCheck %s --check-prefix=MSVC + template<typename T> struct Identity { typedef T Type; }; @@ -43,14 +45,25 @@ namespace VirtualDtor { } namespace VirtualBase { - struct A { }; - struct B : virtual A { }; + struct A { int a; }; + struct B : virtual A { int b; }; void f() { B b; } } +// MSVC: [[VBASE_B:![0-9]+]] = distinct !{!"0x13\00B\00{{[0-9]+}}\0096\0032\000\000\000", {{.*}}, null, [[VBASE_B_DEF:![0-9]+]], {{.*}}} ; [ DW_TAG_structure_type ] [B] [line 49, size 96, align 32, offset 0] [def] [from ] +// 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]] = !{!"0x1c\00\000\000\000\004\0032", null, [[VBASE_B]], !{{[0-9]*}}} ; [ DW_TAG_inheritance ] [line 0, size 0, align 0, offset 4] [from A] + +// CHECK: !"0x13\00B\00{{[0-9]+}}\00128\0064\000\000\000", {{.*}}, null, [[VBASE_B_DEF:![0-9]+]], {{.*}}} ; [ DW_TAG_structure_type ] [B] [line 49, size 128, align 64, offset 0] [def] [from ] +// 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]] = !{!"0x1c\00\000\000\000\0024\0032", null, !"_ZTSN11VirtualBase1BE", !"_ZTSN11VirtualBase1AE"} ; [ DW_TAG_inheritance ] [line 0, size 0, align 0, offset 24] [from _ZTSN11VirtualBase1AE] namespace b5249287 { template <typename T> class A { struct B; @@ -72,15 +85,15 @@ foo func(foo f) { return f; // reference 'f' for now because otherwise we hit another bug } -// CHECK: metadata !{i32 {{[0-9]*}}, metadata !{{[0-9]*}}, metadata [[PR14763:![0-9]*]], {{.*}}, metadata !"[[FOO:.*]]"} ; [ DW_TAG_structure_type ] [foo] +// CHECK: !"0x13\00{{.*}}", !{{[0-9]*}}, [[PR14763:![0-9]*]], {{.*}}, !"[[FOO:.*]]"} ; [ DW_TAG_structure_type ] [foo] // CHECK: [[PR14763]] = {{.*}} ; [ DW_TAG_namespace ] [pr14763] // CHECK: [[INCTYPE:![0-9]*]] = {{.*}} ; [ DW_TAG_structure_type ] [incomplete]{{.*}} [decl] -// CHECK: metadata [[A_MEM:![0-9]*]], i32 0, null, null, metadata !"_ZTSN7pr162141aE"} ; [ DW_TAG_structure_type ] [a] -// CHECK: [[A_MEM]] = metadata !{metadata [[A_I:![0-9]*]]} +// CHECK: [[A_MEM:![0-9]*]], null, null, !"_ZTSN7pr162141aE"} ; [ DW_TAG_structure_type ] [a] +// CHECK: [[A_MEM]] = !{[[A_I:![0-9]*]]} // CHECK: [[A_I]] = {{.*}} ; [ DW_TAG_member ] [i] {{.*}} [from int] // CHECK: ; [ DW_TAG_structure_type ] [b] {{.*}}[decl] -// CHECK: [[FUNC:![0-9]*]] = {{.*}} metadata !"_ZN7pr147634funcENS_3fooE", i32 {{[0-9]*}}, metadata [[FUNC_TYPE:![0-9]*]], {{.*}} ; [ DW_TAG_subprogram ] {{.*}} [def] [func] +// CHECK: [[FUNC:![0-9]*]] = !{!"0x2e\00func\00func\00_ZN7pr147634funcENS_3fooE\00{{.*}}"{{, [^,]+, [^,]+}}, [[FUNC_TYPE:![0-9]*]], {{.*}} ; [ DW_TAG_subprogram ] {{.*}} [def] [func] } void foo() { @@ -93,13 +106,13 @@ void foo() { namespace pr9608 { // also pr9600 struct incomplete; incomplete (*x)[3]; -// CHECK: metadata [[INCARRAYPTR:![0-9]*]], i32 0, i32 1, [3 x i8]** @_ZN6pr96081xE, null} ; [ DW_TAG_variable ] [x] -// CHECK: [[INCARRAYPTR]] = {{.*}}metadata [[INCARRAY:![0-9]*]]} ; [ DW_TAG_pointer_type ] -// CHECK: [[INCARRAY]] = {{.*}}metadata !"_ZTSN6pr960810incompleteE", metadata {{![0-9]*}}, i32 0, null, null, null} ; [ DW_TAG_array_type ] [line 0, size 0, align 0, offset 0] [from _ZTSN6pr960810incompleteE] +// CHECK: [[INCARRAYPTR:![0-9]*]], [3 x i8]** @_ZN6pr96081xE, null} ; [ DW_TAG_variable ] [x] +// CHECK: [[INCARRAYPTR]] = {{.*}}[[INCARRAY:![0-9]*]]} ; [ DW_TAG_pointer_type ] +// CHECK: [[INCARRAY]] = !{!"0x1\00\000\000\000\000\000\000", null, null, !"_ZTSN6pr960810incompleteE", {{![0-9]+}}, null, null, null} ; [ DW_TAG_array_type ] [line 0, size 0, align 0, offset 0] [from _ZTSN6pr960810incompleteE] } // For some reason function arguments ended up down here -// CHECK: = metadata !{i32 {{[0-9]*}}, metadata [[FUNC]], {{.*}}, metadata !"[[FOO]]", i32 8192, i32 0} ; [ DW_TAG_arg_variable ] [f] +// CHECK: = !{!"0x101\00f\00{{.*}}\008192", [[FUNC]], {{![0-9]+}}, !"[[FOO]]"} ; [ DW_TAG_arg_variable ] [f] // CHECK: ; [ DW_TAG_auto_variable ] [c] diff --git a/test/CodeGenCXX/debug-lambda-expressions.cpp b/test/CodeGenCXX/debug-lambda-expressions.cpp index 0b087360f9d5..feafcff064c8 100644 --- a/test/CodeGenCXX/debug-lambda-expressions.cpp +++ b/test/CodeGenCXX/debug-lambda-expressions.cpp @@ -30,38 +30,38 @@ int d(int x) { D y[10]; return [x,y] { return y[x].x; }(); } // CHECK: [[D_FUNC:.*]] = {{.*}} [ DW_TAG_subprogram ] [line [[D_LINE:.*]]] [def] [d] // Back to D. -- 24 -// CHECK: [[LAM_D:.*]] = {{.*}}, metadata [[D_FUNC]], {{.*}}, metadata [[LAM_D_ARGS:.*]], i32 0, null, null, null} ; [ DW_TAG_class_type ] [line [[D_LINE]], -// CHECK: [[LAM_D_ARGS]] = metadata !{metadata [[CAP_D_X:.*]], metadata [[CAP_D_Y:.*]], metadata [[CON_LAM_D:.*]]} -// CHECK: [[CAP_D_X]] = {{.*}}, metadata [[LAM_D]], {{.*}} [ DW_TAG_member ] [x] [line [[D_LINE]], -// CHECK: [[CAP_D_Y]] = {{.*}}, metadata [[LAM_D]], {{.*}} [ DW_TAG_member ] [y] [line [[D_LINE]], -// CHECK: [[CON_LAM_D]] = {{.*}}, metadata [[LAM_D]], {{.*}} [ DW_TAG_subprogram ] [line [[D_LINE]]] [operator()] +// CHECK: [[LAM_D:.*]] = {{.*}}, [[D_FUNC]], {{.*}}, [[LAM_D_ARGS:.*]], null, null, null} ; [ DW_TAG_class_type ] [line [[D_LINE]], +// CHECK: [[LAM_D_ARGS]] = !{[[CAP_D_X:.*]], [[CAP_D_Y:.*]], [[CON_LAM_D:.*]]} +// CHECK: [[CAP_D_X]] = {{.*}}, [[LAM_D]], {{.*}} [ DW_TAG_member ] [x] [line [[D_LINE]], +// CHECK: [[CAP_D_Y]] = {{.*}}, [[LAM_D]], {{.*}} [ DW_TAG_member ] [y] [line [[D_LINE]], +// CHECK: [[CON_LAM_D]] = {{.*}}, [[LAM_D]], {{.*}} [ DW_TAG_subprogram ] [line [[D_LINE]]] [public] [operator()] // Back to C. -- 55 -// CHECK: [[LAM_C:.*]] = {{.*}}, metadata [[C_FUNC]], {{.*}}, metadata [[LAM_C_ARGS:.*]], i32 0, null, null, null} ; [ DW_TAG_class_type ] [line [[C_LINE]], -// CHECK: [[LAM_C_ARGS]] = metadata !{metadata [[CAP_C:.*]], metadata [[CON_LAM_C:.*]]} +// CHECK: [[LAM_C:.*]] = {{.*}}, [[C_FUNC]], {{.*}}, [[LAM_C_ARGS:.*]], null, null, null} ; [ DW_TAG_class_type ] [line [[C_LINE]], +// CHECK: [[LAM_C_ARGS]] = !{[[CAP_C:.*]], [[CON_LAM_C:.*]]} // Ignoring the member type for now. -// CHECK: [[CAP_C]] = {{.*}}, metadata [[LAM_C]], {{.*}}} ; [ DW_TAG_member ] [x] [line [[C_LINE]], -// CHECK: [[CON_LAM_C]] = {{.*}}, metadata [[LAM_C]], {{.*}} [ DW_TAG_subprogram ] [line [[C_LINE]]] [operator()] +// CHECK: [[CAP_C]] = {{.*}}, [[LAM_C]], {{.*}}} ; [ DW_TAG_member ] [x] [line [[C_LINE]], +// CHECK: [[CON_LAM_C]] = {{.*}}, [[LAM_C]], {{.*}} [ DW_TAG_subprogram ] [line [[C_LINE]]] [public] [operator()] // Back to B. -- 67 -// CHECK: [[LAM_B:.*]] = {{.*}}, metadata [[B_FUNC]], {{.*}}, metadata [[LAM_B_ARGS:.*]], i32 0, null, null, null} ; [ DW_TAG_class_type ] [line [[B_LINE]], -// CHECK: [[LAM_B_ARGS]] = metadata !{metadata [[CAP_B:.*]], metadata [[CON_LAM_B:.*]]} -// CHECK: [[CAP_B]] = {{.*}}, metadata [[LAM_B]], {{.*}}} ; [ DW_TAG_member ] [x] [line [[B_LINE]], -// CHECK: [[CON_LAM_B]] = {{.*}}, metadata [[LAM_B]], {{.*}} [ DW_TAG_subprogram ] [line [[B_LINE]]] [operator()] +// CHECK: [[LAM_B:.*]] = {{.*}}, [[B_FUNC]], {{.*}}, [[LAM_B_ARGS:.*]], null, null, null} ; [ DW_TAG_class_type ] [line [[B_LINE]], +// CHECK: [[LAM_B_ARGS]] = !{[[CAP_B:.*]], [[CON_LAM_B:.*]]} +// CHECK: [[CAP_B]] = {{.*}}, [[LAM_B]], {{.*}}} ; [ DW_TAG_member ] [x] [line [[B_LINE]], +// CHECK: [[CON_LAM_B]] = {{.*}}, [[LAM_B]], {{.*}} [ DW_TAG_subprogram ] [line [[B_LINE]]] [public] [operator()] // Back to A. -- 78 -// CHECK: [[LAM_A:.*]] = {{.*}}, metadata [[A_FUNC]], {{.*}}, metadata [[LAM_A_ARGS:.*]], i32 0, null, null, null} ; [ DW_TAG_class_type ] [line [[A_LINE]], -// CHECK: [[LAM_A_ARGS]] = metadata !{metadata [[CON_LAM_A:.*]]} -// CHECK: [[CON_LAM_A]] = {{.*}}, metadata [[LAM_A]], {{.*}} [ DW_TAG_subprogram ] [line [[A_LINE]]] [operator()] +// CHECK: [[LAM_A:.*]] = {{.*}}, [[A_FUNC]], {{.*}}, [[LAM_A_ARGS:.*]], null, null, null} ; [ DW_TAG_class_type ] [line [[A_LINE]], +// CHECK: [[LAM_A_ARGS]] = !{[[CON_LAM_A:.*]]} +// CHECK: [[CON_LAM_A]] = {{.*}}, [[LAM_A]], {{.*}} [ DW_TAG_subprogram ] [line [[A_LINE]]] [public] [operator()] // CVAR: -// CHECK: {{.*}} metadata [[CVAR_T:![0-9]*]], {{.*}} ; [ DW_TAG_variable ] [cvar] [line [[CVAR_LINE:[0-9]*]]] -// CHECK: [[CVAR_T]] = {{.*}}, metadata ![[CVAR_ARGS:.*]], i32 0, null, null, null} ; [ DW_TAG_class_type ] [line [[CVAR_LINE]], -// CHECK: [[CVAR_ARGS]] = metadata !{metadata !{{.*}}} +// CHECK: {{.*}} [[CVAR_T:![0-9]*]], {{.*}} ; [ DW_TAG_variable ] [cvar] [line [[CVAR_LINE:[0-9]*]]] +// CHECK: [[CVAR_T]] = {{.*}}, ![[CVAR_ARGS:.*]], null, null, null} ; [ DW_TAG_class_type ] [line [[CVAR_LINE]], +// CHECK: [[CVAR_ARGS]] = !{!{{.*}}} // VAR: -// CHECK: {{.*}} metadata [[VAR_T:![0-9]*]], {{.*}} ; [ DW_TAG_variable ] [var] [line [[VAR_LINE:[0-9]*]]] -// CHECK: [[VAR_T]] = {{.*}}, metadata [[VAR_ARGS:![0-9]*]], i32 0, null, null, null} ; [ DW_TAG_class_type ] [line [[VAR_LINE]], -// CHECK: [[VAR_ARGS]] = metadata !{metadata !{{.*}}} +// CHECK: {{.*}} [[VAR_T:![0-9]*]], {{.*}} ; [ DW_TAG_variable ] [var] [line [[VAR_LINE:[0-9]*]]] +// CHECK: [[VAR_T]] = {{.*}}, [[VAR_ARGS:![0-9]*]], null, null, null} ; [ DW_TAG_class_type ] [line [[VAR_LINE]], +// CHECK: [[VAR_ARGS]] = !{!{{.*}}} diff --git a/test/CodeGenCXX/debug-lambda-this.cpp b/test/CodeGenCXX/debug-lambda-this.cpp index e7155e76a1cc..87a317db5e16 100644 --- a/test/CodeGenCXX/debug-lambda-this.cpp +++ b/test/CodeGenCXX/debug-lambda-this.cpp @@ -12,4 +12,4 @@ int D::d(int x) { }(); } -// CHECK: {{.*}} [ DW_TAG_member ] [this] [line 11, size 64, align 64, offset 0] [private] [from ] +// CHECK: {{.*}} [ DW_TAG_member ] [this] [line 11, size 64, align 64, offset 0] [from ] diff --git a/test/CodeGenCXX/destructor-debug-info.cpp b/test/CodeGenCXX/destructor-debug-info.cpp index f2e2a39bd6b6..a8abfded2c22 100644 --- a/test/CodeGenCXX/destructor-debug-info.cpp +++ b/test/CodeGenCXX/destructor-debug-info.cpp @@ -19,4 +19,4 @@ void foo() { } } // Check there is a line number entry for line 19 where b1 is destructed. -// CHECK: i32 19, i32 0, metadata +// CHECK: !MDLocation(line: 19, diff --git a/test/CodeGenCXX/destructors.cpp b/test/CodeGenCXX/destructors.cpp index 5c430480bc28..bc9a683be5d4 100644 --- a/test/CodeGenCXX/destructors.cpp +++ b/test/CodeGenCXX/destructors.cpp @@ -1,21 +1,13 @@ -// RUN: %clang_cc1 %s -triple x86_64-apple-darwin10 -emit-llvm -o - -mconstructor-aliases -fcxx-exceptions -fexceptions -O1 -disable-llvm-optzns | FileCheck %s - -// CHECK-DAG: @_ZN5test01AD1Ev = alias {{.*}} @_ZN5test01AD2Ev -// CHECK-DAG: @_ZN5test11MD2Ev = alias {{.*}} @_ZN5test11AD2Ev -// CHECK-DAG: @_ZN5test11ND2Ev = alias {{.*}} @_ZN5test11AD2Ev -// CHECK-DAG: @_ZN5test11OD2Ev = alias {{.*}} @_ZN5test11AD2Ev -// CHECK-DAG: @_ZN5test11SD2Ev = alias bitcast {{.*}} @_ZN5test11AD2Ev - -// WIN32-DAG: @_ZN5test01AD1Ev = alias {{.*}} @_ZN5test01AD2Ev -// WIN32-DAG: @_ZN5test11MD2Ev = alias {{.*}} @_ZN5test11AD2Ev -// WIN32-DAG: @_ZN5test11ND2Ev = alias {{.*}} @_ZN5test11AD2Ev -// WIN32-DAG: @_ZN5test11OD2Ev = alias {{.*}} @_ZN5test11AD2Ev -// WIN32-DAG: @_ZN5test11SD2Ev = alias bitcast {{.*}} @_ZN5test11AD2Ev - +// RUN: %clang_cc1 %s -triple x86_64-apple-darwin10 -emit-llvm -o - -mconstructor-aliases -fcxx-exceptions -fexceptions -O1 -disable-llvm-optzns > %t +// RUN: FileCheck --check-prefix=CHECK1 --input-file=%t %s +// RUN: FileCheck --check-prefix=CHECK2 --input-file=%t %s +// 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 struct A { int a; - + ~A(); }; @@ -29,7 +21,7 @@ B::~B() { } // Field with non-trivial destructor struct C { A a; - + ~C(); }; @@ -43,11 +35,11 @@ namespace PR7526 { struct allocator_derived : allocator { }; - // CHECK-LABEL: define void @_ZN6PR75263fooEv() - // CHECK: call void {{.*}} @_ZN6PR75269allocatorD2Ev + // CHECK1-LABEL: define void @_ZN6PR75263fooEv() + // CHECK1: call void {{.*}} @_ZN6PR75269allocatorD2Ev - // CHECK-LABEL: define void @_ZN6PR75269allocatorD2Ev(%"struct.PR7526::allocator"* %this) unnamed_addr - // CHECK: call void @__cxa_call_unexpected + // CHECK1-LABEL: define void @_ZN6PR75269allocatorD2Ev(%"struct.PR7526::allocator"* %this) unnamed_addr + // CHECK1: call void @__cxa_call_unexpected allocator::~allocator() throw() { foo(); } void foo() { @@ -68,12 +60,12 @@ namespace PR5529 { struct A { ~A(); }; - + A::~A() { } struct B : A { virtual ~B(); }; - + B::~B() {} } @@ -96,11 +88,12 @@ namespace test0 { // complete destructor alias tested above -// CHECK-LABEL: define void @_ZN5test01AD2Ev(%"struct.test0::A"* %this) unnamed_addr -// CHECK: invoke void @_ZN5test06MemberD1Ev -// CHECK: unwind label [[MEM_UNWIND:%[a-zA-Z0-9.]+]] -// CHECK: invoke void @_ZN5test04BaseD2Ev -// CHECK: unwind label [[BASE_UNWIND:%[a-zA-Z0-9.]+]] +// CHECK2-LABEL: @_ZN5test01AD1Ev = alias {{.*}} @_ZN5test01AD2Ev +// CHECK2-LABEL: define void @_ZN5test01AD2Ev(%"struct.test0::A"* %this) unnamed_addr +// CHECK2: invoke void @_ZN5test06MemberD1Ev +// CHECK2: unwind label [[MEM_UNWIND:%[a-zA-Z0-9.]+]] +// CHECK2: invoke void @_ZN5test04BaseD2Ev +// CHECK2: unwind label [[BASE_UNWIND:%[a-zA-Z0-9.]+]] struct B : Base, virtual VBase { Member M; @@ -109,19 +102,19 @@ namespace test0 { B::~B() try { } catch (int i) {} // It will suppress the delegation optimization here, though. -// CHECK-LABEL: define void @_ZN5test01BD2Ev(%"struct.test0::B"* %this, i8** %vtt) unnamed_addr -// CHECK: invoke void @_ZN5test06MemberD1Ev -// CHECK: unwind label [[MEM_UNWIND:%[a-zA-Z0-9.]+]] -// CHECK: invoke void @_ZN5test04BaseD2Ev -// CHECK: unwind label [[BASE_UNWIND:%[a-zA-Z0-9.]+]] - -// CHECK-LABEL: define void @_ZN5test01BD1Ev(%"struct.test0::B"* %this) unnamed_addr -// CHECK: invoke void @_ZN5test06MemberD1Ev -// CHECK: unwind label [[MEM_UNWIND:%[a-zA-Z0-9.]+]] -// CHECK: invoke void @_ZN5test04BaseD2Ev -// CHECK: unwind label [[BASE_UNWIND:%[a-zA-Z0-9.]+]] -// CHECK: invoke void @_ZN5test05VBaseD2Ev -// CHECK: unwind label [[VBASE_UNWIND:%[a-zA-Z0-9.]+]] +// CHECK2-LABEL: define void @_ZN5test01BD2Ev(%"struct.test0::B"* %this, i8** %vtt) unnamed_addr +// CHECK2: invoke void @_ZN5test06MemberD1Ev +// CHECK2: unwind label [[MEM_UNWIND:%[a-zA-Z0-9.]+]] +// CHECK2: invoke void @_ZN5test04BaseD2Ev +// CHECK2: unwind label [[BASE_UNWIND:%[a-zA-Z0-9.]+]] + +// CHECK2-LABEL: define void @_ZN5test01BD1Ev(%"struct.test0::B"* %this) unnamed_addr +// CHECK2: invoke void @_ZN5test06MemberD1Ev +// CHECK2: unwind label [[MEM_UNWIND:%[a-zA-Z0-9.]+]] +// CHECK2: invoke void @_ZN5test04BaseD2Ev +// CHECK2: unwind label [[BASE_UNWIND:%[a-zA-Z0-9.]+]] +// CHECK2: invoke void @_ZN5test05VBaseD2Ev +// CHECK2: unwind label [[VBASE_UNWIND:%[a-zA-Z0-9.]+]] } // Test base-class aliasing. @@ -136,33 +129,37 @@ namespace test1 { A::~A() { delete m; } struct M : A { ~M(); }; - M::~M() {} // alias tested above + M::~M() {} + // CHECK3: @_ZN5test11MD2Ev = alias {{.*}} @_ZN5test11AD2Ev struct N : A, Empty { ~N(); }; - N::~N() {} // alias tested above + N::~N() {} + // CHECK3: @_ZN5test11ND2Ev = alias {{.*}} @_ZN5test11AD2Ev struct O : Empty, A { ~O(); }; - O::~O() {} // alias tested above + O::~O() {} + // CHECK3: @_ZN5test11OD2Ev = alias {{.*}} @_ZN5test11AD2Ev struct P : NonEmpty, A { ~P(); }; - P::~P() {} // CHECK-LABEL: define void @_ZN5test11PD2Ev(%"struct.test1::P"* %this) unnamed_addr + P::~P() {} // CHECK3-LABEL: define void @_ZN5test11PD2Ev(%"struct.test1::P"* %this) unnamed_addr struct Q : A, B { ~Q(); }; - Q::~Q() {} // CHECK-LABEL: define void @_ZN5test11QD2Ev(%"struct.test1::Q"* %this) unnamed_addr + Q::~Q() {} // CHECK3-LABEL: define void @_ZN5test11QD2Ev(%"struct.test1::Q"* %this) unnamed_addr struct R : A { ~R(); }; - R::~R() { A a; } // CHECK-LABEL: define void @_ZN5test11RD2Ev(%"struct.test1::R"* %this) unnamed_addr + R::~R() { A a; } // CHECK3-LABEL: define void @_ZN5test11RD2Ev(%"struct.test1::R"* %this) unnamed_addr struct S : A { ~S(); int x; }; - S::~S() {} // alias tested above + S::~S() {} + // CHECK4: @_ZN5test11SD2Ev = alias bitcast {{.*}} @_ZN5test11AD2Ev struct T : A { ~T(); B x; }; - T::~T() {} // CHECK-LABEL: define void @_ZN5test11TD2Ev(%"struct.test1::T"* %this) unnamed_addr + T::~T() {} // CHECK4-LABEL: define void @_ZN5test11TD2Ev(%"struct.test1::T"* %this) unnamed_addr // The VTT parameter prevents this. We could still make this work // for calling conventions that are safe against extra parameters. struct U : A, virtual B { ~U(); }; - U::~U() {} // CHECK-LABEL: define void @_ZN5test11UD2Ev(%"struct.test1::U"* %this, i8** %vtt) unnamed_addr + U::~U() {} // CHECK4-LABEL: define void @_ZN5test11UD2Ev(%"struct.test1::U"* %this, i8** %vtt) unnamed_addr } // PR6471 @@ -171,8 +168,8 @@ namespace test2 { struct B : A { ~B(); }; B::~B() {} - // CHECK-LABEL: define void @_ZN5test21BD2Ev(%"struct.test2::B"* %this) unnamed_addr - // CHECK: call void @_ZN5test21AD2Ev + // CHECK4-LABEL: define void @_ZN5test21BD2Ev(%"struct.test2::B"* %this) unnamed_addr + // CHECK4: call void @_ZN5test21AD2Ev } // PR7142 @@ -187,14 +184,63 @@ namespace test3 { void test() { new D; // Force emission of D's vtable } + + // CHECK4-LABEL: define internal void @_ZN5test312_GLOBAL__N_11DD0Ev(%"struct.test3::(anonymous namespace)::D"* %this) unnamed_addr + // CHECK4: invoke void {{.*}} @_ZN5test312_GLOBAL__N_11CD2Ev + // CHECK4: call void @_ZdlPv({{.*}}) [[NUW:#[0-9]+]] + // CHECK4: ret void + // CHECK4: landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) + // CHECK4-NEXT: cleanup + // CHECK4: call void @_ZdlPv({{.*}}) [[NUW]] + // CHECK4: resume { i8*, i32 } + + // CHECK4-LABEL: define internal void @_ZThn8_N5test312_GLOBAL__N_11DD1Ev( + // CHECK4: getelementptr inbounds i8* {{.*}}, i64 -8 + // CHECK4: call void {{.*}} @_ZN5test312_GLOBAL__N_11CD2Ev + // CHECK4: ret void + + // CHECK4-LABEL: define internal void @_ZThn8_N5test312_GLOBAL__N_11DD0Ev( + // CHECK4: getelementptr inbounds i8* {{.*}}, i64 -8 + // CHECK4: call void @_ZN5test312_GLOBAL__N_11DD0Ev( + // CHECK4: ret void + + // CHECK4-LABEL: declare void @_ZN5test31BD2Ev( + // CHECK4-LABEL: declare void @_ZN5test31AD2Ev( + + // CHECK4-LABEL: define internal void @_ZN5test312_GLOBAL__N_11CD2Ev(%"struct.test3::(anonymous namespace)::C"* %this) unnamed_addr + // CHECK4: invoke void @_ZN5test31BD2Ev( + // CHECK4: call void @_ZN5test31AD2Ev( + // CHECK4: ret void + + + // CHECK4-LABEL: define internal void @_ZN5test312_GLOBAL__N_11CD0Ev(%"struct.test3::(anonymous namespace)::C"* %this) unnamed_addr + // CHECK4: invoke void @_ZN5test312_GLOBAL__N_11CD2Ev( + // CHECK4: call void @_ZdlPv({{.*}}) [[NUW]] + // CHECK4: ret void + // CHECK4: landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) + // CHECK4-NEXT: cleanup + // CHECK4: call void @_ZdlPv({{.*}}) [[NUW]] + // CHECK4: resume { i8*, i32 } + + // CHECK4-LABEL: define internal void @_ZThn8_N5test312_GLOBAL__N_11CD1Ev( + // CHECK4: getelementptr inbounds i8* {{.*}}, i64 -8 + // CHECK4: call void @_ZN5test312_GLOBAL__N_11CD2Ev( + // CHECK4: ret void + + // CHECK4-LABEL: define internal void @_ZThn8_N5test312_GLOBAL__N_11CD0Ev( + // CHECK4: getelementptr inbounds i8* {{.*}}, i64 -8 + // CHECK4: call void @_ZN5test312_GLOBAL__N_11CD0Ev( + // CHECK4: ret void + + // CHECK4: attributes [[NUW]] = {{[{].*}} nounwind {{.*[}]}} } namespace test4 { struct A { ~A(); }; - // CHECK-LABEL: define void @_ZN5test43fooEv() - // CHECK: call void @_ZN5test41AD1Ev - // CHECK: ret void + // CHECK5-LABEL: define void @_ZN5test43fooEv() + // CHECK5: call void @_ZN5test41AD1Ev + // CHECK5: ret void void foo() { { A a; @@ -205,20 +251,20 @@ namespace test4 { return; } - // CHECK-LABEL: define void @_ZN5test43barEi( - // CHECK: [[X:%.*]] = alloca i32 - // CHECK-NEXT: [[A:%.*]] = alloca - // CHECK: br label - // CHECK: [[TMP:%.*]] = load i32* [[X]] - // CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[TMP]], 0 - // CHECK-NEXT: br i1 - // CHECK: call void @_ZN5test41AD1Ev( - // CHECK: br label - // CHECK: [[TMP:%.*]] = load i32* [[X]] - // CHECK: [[TMP2:%.*]] = add nsw i32 [[TMP]], -1 - // CHECK: store i32 [[TMP2]], i32* [[X]] - // CHECK: br label - // CHECK: ret void + // CHECK5-LABEL: define void @_ZN5test43barEi( + // CHECK5: [[X:%.*]] = alloca i32 + // CHECK5-NEXT: [[A:%.*]] = alloca + // CHECK5: br label + // CHECK5: [[TMP:%.*]] = load i32* [[X]] + // CHECK5-NEXT: [[CMP:%.*]] = icmp ne i32 [[TMP]], 0 + // CHECK5-NEXT: br i1 + // CHECK5: call void @_ZN5test41AD1Ev( + // CHECK5: br label + // CHECK5: [[TMP:%.*]] = load i32* [[X]] + // CHECK5: [[TMP2:%.*]] = add nsw i32 [[TMP]], -1 + // CHECK5: store i32 [[TMP2]], i32* [[X]] + // CHECK5: br label + // CHECK5: ret void void bar(int x) { for (A a; x; ) { x--; @@ -230,27 +276,27 @@ namespace test4 { namespace test5 { struct A { ~A(); }; - // CHECK-LABEL: define void @_ZN5test53fooEv() - // CHECK: [[ELEMS:%.*]] = alloca [5 x [[A:%.*]]], align - // CHECK-NEXT: [[EXN:%.*]] = alloca i8* - // CHECK-NEXT: [[SEL:%.*]] = alloca i32 - // CHECK-NEXT: [[BEGIN:%.*]] = getelementptr inbounds [5 x [[A]]]* [[ELEMS]], i32 0, i32 0 - // CHECK-NEXT: [[END:%.*]] = getelementptr inbounds [[A]]* [[BEGIN]], i64 5 - // CHECK-NEXT: br label - // CHECK: [[POST:%.*]] = phi [[A]]* [ [[END]], {{%.*}} ], [ [[ELT:%.*]], {{%.*}} ] - // CHECK-NEXT: [[ELT]] = getelementptr inbounds [[A]]* [[POST]], i64 -1 - // CHECK-NEXT: invoke void @_ZN5test51AD1Ev([[A]]* [[ELT]]) - // CHECK: [[T0:%.*]] = icmp eq [[A]]* [[ELT]], [[BEGIN]] - // CHECK-NEXT: br i1 [[T0]], - // CHECK: ret void + // CHECK5-LABEL: define void @_ZN5test53fooEv() + // CHECK5: [[ELEMS:%.*]] = alloca [5 x [[A:%.*]]], align + // CHECK5-NEXT: [[EXN:%.*]] = alloca i8* + // CHECK5-NEXT: [[SEL:%.*]] = alloca i32 + // CHECK5-NEXT: [[BEGIN:%.*]] = getelementptr inbounds [5 x [[A]]]* [[ELEMS]], i32 0, i32 0 + // CHECK5-NEXT: [[END:%.*]] = getelementptr inbounds [[A]]* [[BEGIN]], i64 5 + // CHECK5-NEXT: br label + // CHECK5: [[POST:%.*]] = phi [[A]]* [ [[END]], {{%.*}} ], [ [[ELT:%.*]], {{%.*}} ] + // CHECK5-NEXT: [[ELT]] = getelementptr inbounds [[A]]* [[POST]], i64 -1 + // CHECK5-NEXT: invoke void @_ZN5test51AD1Ev([[A]]* [[ELT]]) + // CHECK5: [[T0:%.*]] = icmp eq [[A]]* [[ELT]], [[BEGIN]] + // CHECK5-NEXT: br i1 [[T0]], + // CHECK5: ret void // lpad - // CHECK: [[EMPTY:%.*]] = icmp eq [[A]]* [[BEGIN]], [[ELT]] - // CHECK-NEXT: br i1 [[EMPTY]] - // CHECK: [[AFTER:%.*]] = phi [[A]]* [ [[ELT]], {{%.*}} ], [ [[CUR:%.*]], {{%.*}} ] - // CHECK-NEXT: [[CUR:%.*]] = getelementptr inbounds [[A]]* [[AFTER]], i64 -1 - // CHECK-NEXT: invoke void @_ZN5test51AD1Ev([[A]]* [[CUR]]) - // CHECK: [[DONE:%.*]] = icmp eq [[A]]* [[CUR]], [[BEGIN]] - // CHECK-NEXT: br i1 [[DONE]], + // CHECK5: [[EMPTY:%.*]] = icmp eq [[A]]* [[BEGIN]], [[ELT]] + // CHECK5-NEXT: br i1 [[EMPTY]] + // CHECK5: [[AFTER:%.*]] = phi [[A]]* [ [[ELT]], {{%.*}} ], [ [[CUR:%.*]], {{%.*}} ] + // CHECK5-NEXT: [[CUR:%.*]] = getelementptr inbounds [[A]]* [[AFTER]], i64 -1 + // CHECK5-NEXT: invoke void @_ZN5test51AD1Ev([[A]]* [[CUR]]) + // CHECK5: [[DONE:%.*]] = icmp eq [[A]]* [[CUR]], [[BEGIN]] + // CHECK5-NEXT: br i1 [[DONE]], void foo() { A elems[5]; } @@ -269,37 +315,37 @@ namespace test6 { }; C::C() { opaque(); } - // CHECK-LABEL: define void @_ZN5test61CC1Ev(%"struct.test6::C"* %this) unnamed_addr - // CHECK: call void @_ZN5test61BILj2EEC2Ev - // CHECK: invoke void @_ZN5test61BILj3EEC2Ev - // CHECK: invoke void @_ZN5test61BILj0EEC2Ev - // CHECK: invoke void @_ZN5test61BILj1EEC2Ev - // CHECK: invoke void @_ZN5test66opaqueEv - // CHECK: ret void + // CHECK5-LABEL: define void @_ZN5test61CC1Ev(%"struct.test6::C"* %this) unnamed_addr + // CHECK5: call void @_ZN5test61BILj2EEC2Ev + // CHECK5: invoke void @_ZN5test61BILj3EEC2Ev + // CHECK5: invoke void @_ZN5test61BILj0EEC2Ev + // CHECK5: invoke void @_ZN5test61BILj1EEC2Ev + // CHECK5: invoke void @_ZN5test66opaqueEv + // CHECK5: ret void // FIXME: way too much EH cleanup code follows C::~C() { opaque(); } - // CHECK-LABEL: define void @_ZN5test61CD2Ev(%"struct.test6::C"* %this, i8** %vtt) unnamed_addr - // CHECK: invoke void @_ZN5test66opaqueEv - // CHECK: invoke void @_ZN5test61AD1Ev - // CHECK: invoke void @_ZN5test61AD1Ev - // CHECK: invoke void @_ZN5test61AD1Ev - // CHECK: invoke void @_ZN5test61BILj1EED2Ev - // CHECK: call void @_ZN5test61BILj0EED2Ev - // CHECK: ret void - // CHECK: invoke void @_ZN5test61AD1Ev - // CHECK: invoke void @_ZN5test61AD1Ev - // CHECK: invoke void @_ZN5test61AD1Ev - // CHECK: invoke void @_ZN5test61BILj1EED2Ev - // CHECK: invoke void @_ZN5test61BILj0EED2Ev - - // CHECK-LABEL: define void @_ZN5test61CD1Ev(%"struct.test6::C"* %this) unnamed_addr - // CHECK: invoke void @_ZN5test61CD2Ev - // CHECK: invoke void @_ZN5test61BILj3EED2Ev - // CHECK: call void @_ZN5test61BILj2EED2Ev - // CHECK: ret void - // CHECK: invoke void @_ZN5test61BILj3EED2Ev - // CHECK: invoke void @_ZN5test61BILj2EED2Ev + // CHECK5-LABEL: define void @_ZN5test61CD2Ev(%"struct.test6::C"* %this, i8** %vtt) unnamed_addr + // CHECK5: invoke void @_ZN5test66opaqueEv + // CHECK5: invoke void @_ZN5test61AD1Ev + // CHECK5: invoke void @_ZN5test61AD1Ev + // CHECK5: invoke void @_ZN5test61AD1Ev + // CHECK5: invoke void @_ZN5test61BILj1EED2Ev + // CHECK5: call void @_ZN5test61BILj0EED2Ev + // CHECK5: ret void + // CHECK5: invoke void @_ZN5test61AD1Ev + // CHECK5: invoke void @_ZN5test61AD1Ev + // CHECK5: invoke void @_ZN5test61AD1Ev + // CHECK5: invoke void @_ZN5test61BILj1EED2Ev + // CHECK5: invoke void @_ZN5test61BILj0EED2Ev + + // CHECK5-LABEL: define void @_ZN5test61CD1Ev(%"struct.test6::C"* %this) unnamed_addr + // CHECK5: invoke void @_ZN5test61CD2Ev + // CHECK5: invoke void @_ZN5test61BILj3EED2Ev + // CHECK5: call void @_ZN5test61BILj2EED2Ev + // CHECK5: ret void + // CHECK5: invoke void @_ZN5test61BILj3EED2Ev + // CHECK5: invoke void @_ZN5test61BILj2EED2Ev } // PR 9197 @@ -315,9 +361,9 @@ namespace test7 { }; // Verify that this doesn't get emitted as an alias - // CHECK-LABEL: define void @_ZN5test71BD2Ev( - // CHECK: invoke void @_ZN5test71DD1Ev( - // CHECK: call void @_ZN5test71AD2Ev( + // CHECK5-LABEL: define void @_ZN5test71BD2Ev( + // CHECK5: invoke void @_ZN5test71DD1Ev( + // CHECK5: call void @_ZN5test71AD2Ev( B::~B() {} } @@ -335,16 +381,16 @@ namespace test8 { l: die(); } - // CHECK-LABEL: define void @_ZN5test84testEv() - // CHECK: [[X:%.*]] = alloca [[A:%.*]], align 1 - // CHECK-NEXT: [[Y:%.*]] = alloca [[A:%.*]], align 1 - // CHECK: call void @_ZN5test81AC1Ev([[A]]* [[X]]) - // CHECK-NEXT: br label - // CHECK: invoke void @_ZN5test81AC1Ev([[A]]* [[Y]]) - // CHECK: invoke void @_ZN5test81AD1Ev([[A]]* [[Y]]) - // CHECK-NOT: switch - // CHECK: invoke void @_ZN5test83dieEv() - // CHECK: unreachable + // CHECK5-LABEL: define void @_ZN5test84testEv() + // CHECK5: [[X:%.*]] = alloca [[A:%.*]], align 1 + // CHECK5-NEXT: [[Y:%.*]] = alloca [[A:%.*]], align 1 + // CHECK5: call void @_ZN5test81AC1Ev([[A]]* [[X]]) + // CHECK5-NEXT: br label + // CHECK5: invoke void @_ZN5test81AC1Ev([[A]]* [[Y]]) + // CHECK5: invoke void @_ZN5test81AD1Ev([[A]]* [[Y]]) + // CHECK5-NOT: switch + // CHECK5: invoke void @_ZN5test83dieEv() + // CHECK5: unreachable } // PR12710 @@ -359,8 +405,8 @@ namespace test9 { f1<int>(); f2(); } - // CHECK: call void @_ZN5test97ArgTypeD1Ev(%"struct.test9::ArgType"* % - // CHECK: call void @_ZN5test92f2Ev() + // CHECK5: call void @_ZN5test97ArgTypeD1Ev(%"struct.test9::ArgType"* % + // CHECK5: call void @_ZN5test92f2Ev() } namespace test10 { @@ -371,60 +417,10 @@ namespace test10 { }; template <class DataType> class opt : public Option {}; template class opt<int>; - // CHECK-LABEL: define zeroext i1 @_ZN6test1016handleOccurrenceEv( + // CHECK5-LABEL: define zeroext i1 @_ZN6test1016handleOccurrenceEv( bool handleOccurrence() { - // CHECK: call void @_ZN6test106OptionD2Ev( + // CHECK5: call void @_ZN6test106OptionD2Ev( Option x; return true; } } - -// Checks from test3: - - // CHECK-LABEL: define internal void @_ZN5test312_GLOBAL__N_11DD0Ev(%"struct.test3::(anonymous namespace)::D"* %this) unnamed_addr - // CHECK: invoke void {{.*}} @_ZN5test312_GLOBAL__N_11CD2Ev - // CHECK: call void @_ZdlPv({{.*}}) [[NUW:#[0-9]+]] - // CHECK: ret void - // CHECK: landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) - // CHECK-NEXT: cleanup - // CHECK: call void @_ZdlPv({{.*}}) [[NUW]] - // CHECK: resume { i8*, i32 } - - // CHECK-LABEL: define internal void @_ZThn8_N5test312_GLOBAL__N_11DD1Ev( - // CHECK: getelementptr inbounds i8* {{.*}}, i64 -8 - // CHECK: call void {{.*}} @_ZN5test312_GLOBAL__N_11CD2Ev - // CHECK: ret void - - // CHECK-LABEL: define internal void @_ZThn8_N5test312_GLOBAL__N_11DD0Ev( - // CHECK: getelementptr inbounds i8* {{.*}}, i64 -8 - // CHECK: call void @_ZN5test312_GLOBAL__N_11DD0Ev( - // CHECK: ret void - - // CHECK-LABEL: define internal void @_ZThn8_N5test312_GLOBAL__N_11CD1Ev( - // CHECK: getelementptr inbounds i8* {{.*}}, i64 -8 - // CHECK: call void @_ZN5test312_GLOBAL__N_11CD2Ev( - // CHECK: ret void - - // CHECK-LABEL: define internal void @_ZN5test312_GLOBAL__N_11CD2Ev(%"struct.test3::(anonymous namespace)::C"* %this) unnamed_addr - // CHECK: invoke void @_ZN5test31BD2Ev( - // CHECK: call void @_ZN5test31AD2Ev( - // CHECK: ret void - - // CHECK: declare void @_ZN5test31BD2Ev( - // CHECK: declare void @_ZN5test31AD2Ev( - - // CHECK-LABEL: define internal void @_ZN5test312_GLOBAL__N_11CD0Ev(%"struct.test3::(anonymous namespace)::C"* %this) unnamed_addr - // CHECK: invoke void @_ZN5test312_GLOBAL__N_11CD2Ev( - // CHECK: call void @_ZdlPv({{.*}}) [[NUW]] - // CHECK: ret void - // CHECK: landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) - // CHECK-NEXT: cleanup - // CHECK: call void @_ZdlPv({{.*}}) [[NUW]] - // CHECK: resume { i8*, i32 } - - // CHECK-LABEL: define internal void @_ZThn8_N5test312_GLOBAL__N_11CD0Ev( - // CHECK: getelementptr inbounds i8* {{.*}}, i64 -8 - // CHECK: call void @_ZN5test312_GLOBAL__N_11CD0Ev( - // CHECK: ret void - - // CHECK: attributes [[NUW]] = {{[{].*}} nounwind {{.*[}]}} diff --git a/test/CodeGenCXX/devirtualize-virtual-function-calls-final.cpp b/test/CodeGenCXX/devirtualize-virtual-function-calls-final.cpp index 11026e8df3e7..193ee5f80406 100644 --- a/test/CodeGenCXX/devirtualize-virtual-function-calls-final.cpp +++ b/test/CodeGenCXX/devirtualize-virtual-function-calls-final.cpp @@ -53,26 +53,32 @@ namespace Test3 { namespace Test4 { struct A { virtual void f(); + virtual int operator-(); }; struct B final : A { virtual void f(); + virtual int operator-(); }; // CHECK-LABEL: define void @_ZN5Test41fEPNS_1BE void f(B* d) { // CHECK: call void @_ZN5Test41B1fEv static_cast<A*>(d)->f(); + // CHECK: call i32 @_ZN5Test41BngEv + -static_cast<A&>(*d); } } namespace Test5 { struct A { virtual void f(); + virtual int operator-(); }; struct B : A { virtual void f(); + virtual int operator-(); }; struct C final : B { @@ -87,6 +93,15 @@ namespace Test5 { // CHECK-NEXT: call void %[[FUNC]] static_cast<A*>(d)->f(); } + // CHECK-LABEL: define void @_ZN5Test53fopEPNS_1CE + void fop(C* d) { + // FIXME: It should be possible to devirtualize this case, but that is + // not implemented yet. + // CHECK: getelementptr + // CHECK-NEXT: %[[FUNC:.*]] = load + // CHECK-NEXT: call i32 %[[FUNC]] + -static_cast<A&>(*d); + } } namespace Test6 { @@ -165,6 +180,9 @@ namespace Test9 { virtual A *f() { return 0; } + virtual A *operator-() { + return 0; + } }; struct RC final : public RA { virtual C *f() { @@ -173,15 +191,37 @@ namespace Test9 { x->b = 2; return x; } + virtual C *operator-() { + C *x = new C(); + x->a = 1; + x->b = 2; + return x; + } }; // CHECK: define {{.*}} @_ZN5Test91fEPNS_2RCE A *f(RC *x) { // FIXME: It should be possible to devirtualize this case, but that is // not implemented yet. - // CHECK: getelementptr - // CHECK-NEXT: %[[FUNC:.*]] = load - // CHECK-NEXT: bitcast + // CHECK: load + // CHECK: bitcast + // CHECK: [[F_PTR_RA:%.+]] = bitcast + // CHECK: [[VTABLE:%.+]] = load {{.+}} [[F_PTR_RA]] + // CHECK: [[VFN:%.+]] = getelementptr inbounds {{.+}} [[VTABLE]], i{{[0-9]+}} 0 + // CHECK-NEXT: %[[FUNC:.*]] = load {{.+}} [[VFN]] // CHECK-NEXT: = call {{.*}} %[[FUNC]] return static_cast<RA*>(x)->f(); } + // CHECK: define {{.*}} @_ZN5Test93fopEPNS_2RCE + A *fop(RC *x) { + // FIXME: It should be possible to devirtualize this case, but that is + // not implemented yet. + // CHECK: load + // CHECK: bitcast + // CHECK: [[F_PTR_RA:%.+]] = bitcast + // CHECK: [[VTABLE:%.+]] = load {{.+}} [[F_PTR_RA]] + // CHECK: [[VFN:%.+]] = getelementptr inbounds {{.+}} [[VTABLE]], i{{[0-9]+}} 1 + // CHECK-NEXT: %[[FUNC:.*]] = load {{.+}} [[VFN]] + // CHECK-NEXT: = call {{.*}} %[[FUNC]] + return -static_cast<RA&>(*x); + } } diff --git a/test/CodeGenCXX/dllexport-alias.cpp b/test/CodeGenCXX/dllexport-alias.cpp new file mode 100644 index 000000000000..479595d05751 --- /dev/null +++ b/test/CodeGenCXX/dllexport-alias.cpp @@ -0,0 +1,18 @@ +// RUN: %clang_cc1 -triple x86_64-windows-gnu -mconstructor-aliases %s -S -emit-llvm -o - | FileCheck %s + +// This test assumes that the C1 constructor will be aliased to the C2 +// constructor, and the D1 destructor to the D2. It then checks that the aliases +// are dllexport'ed. + +class __declspec(dllexport) A { +public: + A(); + ~A(); +}; + +A::A() {} + +A::~A() {} + +// CHECK: @_ZN1AC1Ev = dllexport alias void (%class.A*)* @_ZN1AC2Ev +// CHECK: @_ZN1AD1Ev = dllexport alias void (%class.A*)* @_ZN1AD2Ev diff --git a/test/CodeGenCXX/dllexport-members.cpp b/test/CodeGenCXX/dllexport-members.cpp index d913c09ec7be..5b2af1e04bd7 100644 --- a/test/CodeGenCXX/dllexport-members.cpp +++ b/test/CodeGenCXX/dllexport-members.cpp @@ -110,9 +110,9 @@ public: // MSC-DAG: @"\01?StaticField@ExportMembers@@2HA" = dllexport global i32 1, align 4 // MSC-DAG: @"\01?StaticConstField@ExportMembers@@2HB" = dllexport constant i32 1, align 4 - // MSC-DAG: @"\01?StaticConstFieldEqualInit@ExportMembers@@2HB" = weak_odr dllexport constant i32 1, align 4 - // MSC-DAG: @"\01?StaticConstFieldBraceInit@ExportMembers@@2HB" = weak_odr dllexport constant i32 1, align 4 - // MSC-DAG: @"\01?ConstexprField@ExportMembers@@2HB" = weak_odr dllexport constant i32 1, align 4 + // MSC-DAG: @"\01?StaticConstFieldEqualInit@ExportMembers@@2HB" = weak_odr dllexport constant i32 1, comdat, align 4 + // MSC-DAG: @"\01?StaticConstFieldBraceInit@ExportMembers@@2HB" = weak_odr dllexport constant i32 1, comdat, align 4 + // MSC-DAG: @"\01?ConstexprField@ExportMembers@@2HB" = weak_odr dllexport constant i32 1, comdat, align 4 // GNU-DAG: @_ZN13ExportMembers11StaticFieldE = dllexport global i32 1, align 4 // GNU-DAG: @_ZN13ExportMembers16StaticConstFieldE = dllexport constant i32 1, align 4 // GNU-DAG: @_ZN13ExportMembers25StaticConstFieldEqualInitE = dllexport constant i32 1, align 4 @@ -233,9 +233,9 @@ public: // MSC-DAG: @"\01?StaticField@Nested@ExportMembers@@2HA" = dllexport global i32 1, align 4 // MSC-DAG: @"\01?StaticConstField@Nested@ExportMembers@@2HB" = dllexport constant i32 1, align 4 - // MSC-DAG: @"\01?StaticConstFieldEqualInit@Nested@ExportMembers@@2HB" = weak_odr dllexport constant i32 1, align 4 - // MSC-DAG: @"\01?StaticConstFieldBraceInit@Nested@ExportMembers@@2HB" = weak_odr dllexport constant i32 1, align 4 - // MSC-DAG: @"\01?ConstexprField@Nested@ExportMembers@@2HB" = weak_odr dllexport constant i32 1, align 4 + // MSC-DAG: @"\01?StaticConstFieldEqualInit@Nested@ExportMembers@@2HB" = weak_odr dllexport constant i32 1, comdat, align 4 + // MSC-DAG: @"\01?StaticConstFieldBraceInit@Nested@ExportMembers@@2HB" = weak_odr dllexport constant i32 1, comdat, align 4 + // MSC-DAG: @"\01?ConstexprField@Nested@ExportMembers@@2HB" = weak_odr dllexport constant i32 1, comdat, align 4 // GNU-DAG: @_ZN13ExportMembers6Nested11StaticFieldE = dllexport global i32 1, align 4 // GNU-DAG: @_ZN13ExportMembers6Nested16StaticConstFieldE = dllexport constant i32 1, align 4 // GNU-DAG: @_ZN13ExportMembers6Nested25StaticConstFieldEqualInitE = dllexport constant i32 1, align 4 @@ -599,21 +599,21 @@ template<typename T> const int MemVarTmpl::StaticVar; template<typename T> const int MemVarTmpl::ExportedStaticVar; // Export implicit instantiation of an exported member variable template. -// MSC-DAG: @"\01??$ExportedStaticVar@UImplicitInst_Exported@@@MemVarTmpl@@2HB" = weak_odr dllexport constant i32 1, align 4 -// GNU-DAG: @_ZN10MemVarTmpl17ExportedStaticVarI21ImplicitInst_ExportedEE = weak_odr dllexport constant i32 1, align 4 +// MSC-DAG: @"\01??$ExportedStaticVar@UImplicitInst_Exported@@@MemVarTmpl@@2HB" = weak_odr dllexport constant i32 1, comdat, align 4 +// GNU-DAG: @_ZN10MemVarTmpl17ExportedStaticVarI21ImplicitInst_ExportedEE = weak_odr dllexport constant i32 1, comdat, align 4 int useMemVarTmpl() { return MemVarTmpl::ExportedStaticVar<ImplicitInst_Exported>; } // Export explicit instantiation declaration of an exported member variable // template. -// MSC-DAG: @"\01??$ExportedStaticVar@UExplicitDecl_Exported@@@MemVarTmpl@@2HB" = weak_odr dllexport constant i32 1, align 4 -// GNU-DAG: @_ZN10MemVarTmpl17ExportedStaticVarI21ExplicitDecl_ExportedEE = weak_odr dllexport constant i32 1, align 4 +// MSC-DAG: @"\01??$ExportedStaticVar@UExplicitDecl_Exported@@@MemVarTmpl@@2HB" = weak_odr dllexport constant i32 1, comdat, align 4 +// GNU-DAG: @_ZN10MemVarTmpl17ExportedStaticVarI21ExplicitDecl_ExportedEE = weak_odr dllexport constant i32 1, comdat, align 4 extern template const int MemVarTmpl::ExportedStaticVar<ExplicitDecl_Exported>; template const int MemVarTmpl::ExportedStaticVar<ExplicitDecl_Exported>; // Export explicit instantiation definition of an exported member variable // template. -// MSC-DAG: @"\01??$ExportedStaticVar@UExplicitInst_Exported@@@MemVarTmpl@@2HB" = weak_odr dllexport constant i32 1, align 4 -// GNU-DAG: @_ZN10MemVarTmpl17ExportedStaticVarI21ExplicitInst_ExportedEE = weak_odr dllexport constant i32 1, align 4 +// MSC-DAG: @"\01??$ExportedStaticVar@UExplicitInst_Exported@@@MemVarTmpl@@2HB" = weak_odr dllexport constant i32 1, comdat, align 4 +// GNU-DAG: @_ZN10MemVarTmpl17ExportedStaticVarI21ExplicitInst_ExportedEE = weak_odr dllexport constant i32 1, comdat, align 4 template const int MemVarTmpl::ExportedStaticVar<ExplicitInst_Exported>; // Export specialization of an exported member variable template. @@ -630,15 +630,15 @@ template<> const int MemVarTmpl::ExportedStaticVar<ExplicitSpec_NotExported> = 1 // Export explicit instantiation declaration of a non-exported member variable // template. -// MSC-DAG: @"\01??$StaticVar@UExplicitDecl_Exported@@@MemVarTmpl@@2HB" = weak_odr dllexport constant i32 1, align 4 -// GNU-DAG: @_ZN10MemVarTmpl9StaticVarI21ExplicitDecl_ExportedEE = weak_odr dllexport constant i32 1, align 4 +// MSC-DAG: @"\01??$StaticVar@UExplicitDecl_Exported@@@MemVarTmpl@@2HB" = weak_odr dllexport constant i32 1, comdat, align 4 +// GNU-DAG: @_ZN10MemVarTmpl9StaticVarI21ExplicitDecl_ExportedEE = weak_odr dllexport constant i32 1, comdat, align 4 extern template __declspec(dllexport) const int MemVarTmpl::StaticVar<ExplicitDecl_Exported>; template __declspec(dllexport) const int MemVarTmpl::StaticVar<ExplicitDecl_Exported>; // Export explicit instantiation definition of a non-exported member variable // template. -// MSC-DAG: @"\01??$StaticVar@UExplicitInst_Exported@@@MemVarTmpl@@2HB" = weak_odr dllexport constant i32 1, align 4 -// GNU-DAG: @_ZN10MemVarTmpl9StaticVarI21ExplicitInst_ExportedEE = weak_odr dllexport constant i32 1, align 4 +// MSC-DAG: @"\01??$StaticVar@UExplicitInst_Exported@@@MemVarTmpl@@2HB" = weak_odr dllexport constant i32 1, comdat, align 4 +// GNU-DAG: @_ZN10MemVarTmpl9StaticVarI21ExplicitInst_ExportedEE = weak_odr dllexport constant i32 1, comdat, align 4 template __declspec(dllexport) const int MemVarTmpl::StaticVar<ExplicitInst_Exported>; // Export specialization of a non-exported member variable template. diff --git a/test/CodeGenCXX/dllexport.cpp b/test/CodeGenCXX/dllexport.cpp index 5097abf0c094..93bd1f5fe99c 100644 --- a/test/CodeGenCXX/dllexport.cpp +++ b/test/CodeGenCXX/dllexport.cpp @@ -1,9 +1,7 @@ -// RUN: %clang_cc1 -triple i686-windows-msvc -emit-llvm -std=c++1y -O0 -o - %s | FileCheck --check-prefix=MSC --check-prefix=M32 %s -// RUN: %clang_cc1 -triple x86_64-windows-msvc -emit-llvm -std=c++1y -O0 -o - %s | FileCheck --check-prefix=MSC --check-prefix=M64 %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 - -// RUN: %clang_cc1 -triple i686-pc-win32 -O1 -mconstructor-aliases -std=c++1y -emit-llvm -o - %s | FileCheck %s --check-prefix=MSC --check-prefix=M32 +// RUN: %clang_cc1 -triple i686-windows-msvc -emit-llvm -std=c++1y -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 -O0 -o - %s -w | FileCheck --check-prefix=MSC --check-prefix=M64 %s +// RUN: %clang_cc1 -triple i686-windows-gnu -emit-llvm -std=c++1y -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 -O0 -o - %s -w | FileCheck --check-prefix=GNU --check-prefix=G64 %s // Helper structs to make templates more expressive. struct ImplicitInst_Exported {}; @@ -77,8 +75,8 @@ namespace ns { __declspec(dllexport) int ExternalGlobal; } __declspec(dllexport) auto ExternalAutoTypeGlobal = External(); int f(); -// MSC-DAG: @"\01?x@?0??nonInlineStaticLocalsFunc@@YAHXZ@4HA" = internal {{(unnamed_addr )*}}global i32 0 -// MSC-DAG: @"\01?$S1@?0??nonInlineStaticLocalsFunc@@YAHXZ@4IA" = internal {{(unnamed_addr )*}}global i32 0 +// MSC-DAG: @"\01?x@?1??nonInlineStaticLocalsFunc@@YAHXZ@4HA" = internal {{(unnamed_addr )*}}global i32 0 +// MSC-DAG: @"\01?$S1@?1??nonInlineStaticLocalsFunc@@YAHXZ@4IA" = internal {{(unnamed_addr )*}}global i32 0 int __declspec(dllexport) nonInlineStaticLocalsFunc() { static int x = f(); return x++; @@ -112,43 +110,43 @@ template<typename T> __declspec(dllexport) int VarTmplImplicitDef; USEVAR(VarTmplImplicitDef<ImplicitInst_Exported>) // Export definition. -// MSC-DAG: @"\01??$VarTmplInit1@UExplicitInst_Exported@@@@3HA" = weak_odr dllexport global i32 1, align 4 -// GNU-DAG: @_Z12VarTmplInit1I21ExplicitInst_ExportedE = weak_odr dllexport global i32 1, align 4 +// MSC-DAG: @"\01??$VarTmplInit1@UExplicitInst_Exported@@@@3HA" = weak_odr dllexport global i32 1, comdat, align 4 +// GNU-DAG: @_Z12VarTmplInit1I21ExplicitInst_ExportedE = weak_odr dllexport global i32 1, comdat, align 4 template<typename T> __declspec(dllexport) int VarTmplInit1 = 1; INSTVAR(VarTmplInit1<ExplicitInst_Exported>) -// MSC-DAG: @"\01??$VarTmplInit2@UExplicitInst_Exported@@@@3HA" = weak_odr dllexport global i32 1, align 4 -// GNU-DAG: @_Z12VarTmplInit2I21ExplicitInst_ExportedE = weak_odr dllexport global i32 1, align 4 +// MSC-DAG: @"\01??$VarTmplInit2@UExplicitInst_Exported@@@@3HA" = weak_odr dllexport global i32 1, comdat, align 4 +// GNU-DAG: @_Z12VarTmplInit2I21ExplicitInst_ExportedE = weak_odr dllexport global i32 1, comdat, align 4 template<typename T> int __declspec(dllexport) VarTmplInit2 = 1; INSTVAR(VarTmplInit2<ExplicitInst_Exported>) // Declare, then export definition. -// MSC-DAG: @"\01??$VarTmplDeclInit@UExplicitInst_Exported@@@@3HA" = weak_odr dllexport global i32 1, align 4 -// GNU-DAG: @_Z15VarTmplDeclInitI21ExplicitInst_ExportedE = weak_odr dllexport global i32 1, align 4 +// MSC-DAG: @"\01??$VarTmplDeclInit@UExplicitInst_Exported@@@@3HA" = weak_odr dllexport global i32 1, comdat, align 4 +// GNU-DAG: @_Z15VarTmplDeclInitI21ExplicitInst_ExportedE = weak_odr dllexport global i32 1, comdat, align 4 template<typename T> __declspec(dllexport) extern int VarTmplDeclInit; template<typename T> int VarTmplDeclInit = 1; INSTVAR(VarTmplDeclInit<ExplicitInst_Exported>) // Redeclarations -// MSC-DAG: @"\01??$VarTmplRedecl1@UExplicitInst_Exported@@@@3HA" = weak_odr dllexport global i32 1, align 4 -// GNU-DAG: @_Z14VarTmplRedecl1I21ExplicitInst_ExportedE = weak_odr dllexport global i32 1, align 4 +// MSC-DAG: @"\01??$VarTmplRedecl1@UExplicitInst_Exported@@@@3HA" = weak_odr dllexport global i32 1, comdat, align 4 +// GNU-DAG: @_Z14VarTmplRedecl1I21ExplicitInst_ExportedE = weak_odr dllexport global i32 1, comdat, align 4 template<typename T> __declspec(dllexport) extern int VarTmplRedecl1; template<typename T> __declspec(dllexport) int VarTmplRedecl1 = 1; INSTVAR(VarTmplRedecl1<ExplicitInst_Exported>) -// MSC-DAG: @"\01??$VarTmplRedecl2@UExplicitInst_Exported@@@@3HA" = weak_odr dllexport global i32 1, align 4 -// GNU-DAG: @_Z14VarTmplRedecl2I21ExplicitInst_ExportedE = weak_odr dllexport global i32 1, align 4 +// MSC-DAG: @"\01??$VarTmplRedecl2@UExplicitInst_Exported@@@@3HA" = weak_odr dllexport global i32 1, comdat, align 4 +// GNU-DAG: @_Z14VarTmplRedecl2I21ExplicitInst_ExportedE = weak_odr dllexport global i32 1, comdat, align 4 template<typename T> __declspec(dllexport) extern int VarTmplRedecl2; template<typename T> int VarTmplRedecl2 = 1; INSTVAR(VarTmplRedecl2<ExplicitInst_Exported>) -// MSC-DAG: @"\01??$ExternalVarTmpl@UExplicitInst_Exported@@@ns@@3HA" = weak_odr dllexport global i32 1, align 4 -// GNU-DAG: @_ZN2ns15ExternalVarTmplI21ExplicitInst_ExportedEE = weak_odr dllexport global i32 1, align 4 +// MSC-DAG: @"\01??$ExternalVarTmpl@UExplicitInst_Exported@@@ns@@3HA" = weak_odr dllexport global i32 1, comdat, align 4 +// GNU-DAG: @_ZN2ns15ExternalVarTmplI21ExplicitInst_ExportedEE = weak_odr dllexport global i32 1, comdat, align 4 namespace ns { template<typename T> __declspec(dllexport) int ExternalVarTmpl = 1; } INSTVAR(ns::ExternalVarTmpl<ExplicitInst_Exported>) -// MSC-DAG: @"\01??$ExternalAutoTypeVarTmpl@UExplicitInst_Exported@@@@3UExternal@@A" = weak_odr dllexport global %struct.External zeroinitializer, align 4 -// GNU-DAG: @_Z23ExternalAutoTypeVarTmplI21ExplicitInst_ExportedE = weak_odr dllexport global %struct.External zeroinitializer, align 4 +// MSC-DAG: @"\01??$ExternalAutoTypeVarTmpl@UExplicitInst_Exported@@@@3UExternal@@A" = weak_odr dllexport global %struct.External zeroinitializer, comdat, align 4 +// GNU-DAG: @_Z23ExternalAutoTypeVarTmplI21ExplicitInst_ExportedE = weak_odr dllexport global %struct.External zeroinitializer, comdat, align 4 template<typename T> __declspec(dllexport) auto ExternalAutoTypeVarTmpl = External(); template External ExternalAutoTypeVarTmpl<ExplicitInst_Exported>; @@ -157,19 +155,19 @@ template<typename T> int VarTmpl = 1; template<typename T> __declspec(dllexport) int ExportedVarTmpl = 1; // Export implicit instantiation of an exported variable template. -// MSC-DAG: @"\01??$ExportedVarTmpl@UImplicitInst_Exported@@@@3HA" = weak_odr dllexport global i32 1, align 4 -// GNU-DAG: @_Z15ExportedVarTmplI21ImplicitInst_ExportedE = weak_odr dllexport global i32 1, align 4 +// MSC-DAG: @"\01??$ExportedVarTmpl@UImplicitInst_Exported@@@@3HA" = weak_odr dllexport global i32 1, comdat, align 4 +// GNU-DAG: @_Z15ExportedVarTmplI21ImplicitInst_ExportedE = weak_odr dllexport global i32 1, comdat, align 4 USEVAR(ExportedVarTmpl<ImplicitInst_Exported>) // Export explicit instantiation declaration of an exported variable template. -// MSC-DAG: @"\01??$ExportedVarTmpl@UImplicitInst_Exported@@@@3HA" = weak_odr dllexport global i32 1, align 4 -// GNU-DAG: @_Z15ExportedVarTmplI21ExplicitDecl_ExportedE = weak_odr dllexport global i32 1, align 4 +// MSC-DAG: @"\01??$ExportedVarTmpl@UImplicitInst_Exported@@@@3HA" = weak_odr dllexport global i32 1, comdat, align 4 +// GNU-DAG: @_Z15ExportedVarTmplI21ExplicitDecl_ExportedE = weak_odr dllexport global i32 1, comdat, align 4 extern template int ExportedVarTmpl<ExplicitDecl_Exported>; template int ExportedVarTmpl<ExplicitDecl_Exported>; // Export explicit instantiation definition of an exported variable template. -// MSC-DAG: @"\01??$ExportedVarTmpl@UImplicitInst_Exported@@@@3HA" = weak_odr dllexport global i32 1, align 4 -// GNU-DAG: @_Z15ExportedVarTmplI21ExplicitInst_ExportedE = weak_odr dllexport global i32 1, align 4 +// MSC-DAG: @"\01??$ExportedVarTmpl@UImplicitInst_Exported@@@@3HA" = weak_odr dllexport global i32 1, comdat, align 4 +// GNU-DAG: @_Z15ExportedVarTmplI21ExplicitInst_ExportedE = weak_odr dllexport global i32 1, comdat, align 4 template __declspec(dllexport) int ExportedVarTmpl<ExplicitInst_Exported>; // Export specialization of an exported variable template. @@ -189,14 +187,14 @@ template<> int ExportedVarTmpl<ExplicitSpec_NotExported>; // Export explicit instantiation declaration of a non-exported variable template. -// MSC-DAG: @"\01??$VarTmpl@UExplicitDecl_Exported@@@@3HA" = weak_odr dllexport global i32 1, align 4 -// GNU-DAG: @_Z7VarTmplI21ExplicitDecl_ExportedE = weak_odr dllexport global i32 1, align 4 +// MSC-DAG: @"\01??$VarTmpl@UExplicitDecl_Exported@@@@3HA" = weak_odr dllexport global i32 1, comdat, align 4 +// GNU-DAG: @_Z7VarTmplI21ExplicitDecl_ExportedE = weak_odr dllexport global i32 1, comdat, align 4 extern template __declspec(dllexport) int VarTmpl<ExplicitDecl_Exported>; template __declspec(dllexport) int VarTmpl<ExplicitDecl_Exported>; // Export explicit instantiation definition of a non-exported variable template. -// MSC-DAG: @"\01??$VarTmpl@UExplicitInst_Exported@@@@3HA" = weak_odr dllexport global i32 1, align 4 -// GNU-DAG: @_Z7VarTmplI21ExplicitInst_ExportedE = weak_odr dllexport global i32 1, align 4 +// MSC-DAG: @"\01??$VarTmpl@UExplicitInst_Exported@@@@3HA" = weak_odr dllexport global i32 1, comdat, align 4 +// GNU-DAG: @_Z7VarTmplI21ExplicitInst_ExportedE = weak_odr dllexport global i32 1, comdat, align 4 template __declspec(dllexport) int VarTmpl<ExplicitInst_Exported>; // Export specialization of a non-exported variable template. @@ -509,11 +507,9 @@ USEVAR(T::b) int T::c; template <typename T> struct __declspec(dllexport) U { void foo() {} }; -// The U<int> specialization below must cause the following to be emitted: -// M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?foo@?$U@H@@QAEXXZ" -// M32-DAG: define weak_odr dllexport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.U* @"\01??4?$U@H@@QAEAAU0@ABU0@@Z" struct __declspec(dllexport) V : public U<int> { }; - +// U<int>'s assignment operator is emitted. +// M32-DAG: define weak_odr dllexport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.U* @"\01??4?$U@H@@QAEAAU0@ABU0@@Z" struct __declspec(dllexport) W { virtual void foo() {} }; // Default ctor: @@ -521,7 +517,7 @@ struct __declspec(dllexport) W { virtual void foo() {} }; // Copy ctor: // M32-DAG: define weak_odr dllexport x86_thiscallcc %struct.W* @"\01??0W@@QAE@ABU0@@Z" // vftable: -// M32-DAG: [[W_VTABLE:@.*]] = private unnamed_addr constant [2 x i8*] [i8* bitcast (%rtti.CompleteObjectLocator* @"\01??_R4W@@6B@" to i8*), i8* bitcast (void (%struct.W*)* @"\01?foo@W@@UAEXXZ" to i8*)], comdat $"\01??_7W@@6B@" +// M32-DAG: [[W_VTABLE:@.*]] = private unnamed_addr constant [2 x i8*] [i8* bitcast (%rtti.CompleteObjectLocator* @"\01??_R4W@@6B@" to i8*), i8* bitcast (void (%struct.W*)* @"\01?foo@W@@UAEXXZ" to i8*)], comdat($"\01??_7W@@6B@") // M32-DAG: @"\01??_7W@@6B@" = dllexport unnamed_addr alias getelementptr inbounds ([2 x i8*]* [[W_VTABLE]], i32 0, i32 1) // G32-DAG: @_ZTV1W = weak_odr dllexport unnamed_addr constant [3 x i8*] [i8* null, i8* bitcast ({ i8*, i8* }* @_ZTI1W to i8*), i8* bitcast (void (%struct.W*)* @_ZN1W3fooEv to i8*)] @@ -538,19 +534,20 @@ struct __declspec(dllexport) Y { struct __declspec(dllexport) Z { virtual ~Z() {} }; // The scalar deleting dtor does not get exported: -// M32-DAG: define linkonce_odr x86_thiscallcc void @"\01??_GZ@@UAEPAXI@Z" +// M32-DAG: define linkonce_odr x86_thiscallcc i8* @"\01??_GZ@@UAEPAXI@Z" // The user-defined dtor does get exported: // M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01??1Z@@UAE@XZ" -namespace DontUseDtorAlias { +namespace UseDtorAlias { struct __declspec(dllexport) A { ~A(); }; struct __declspec(dllexport) B : A { ~B(); }; A::~A() { } B::~B() { } - // Emit a real definition of B's constructor; don't alias it to A's. - // M32-DAG: define dllexport x86_thiscallcc void @"\01??1B@DontUseDtorAlias@@QAE@XZ" + // Emit a alias definition of B's constructor. + // M32-DAG: @"\01??1B@UseDtorAlias@@QAE@XZ" = dllexport alias {{.*}} @"\01??1A@UseDtorAlias@@QAE@XZ" + } struct __declspec(dllexport) DefaultedCtorsDtors { @@ -581,106 +578,155 @@ USEMEMFUNC(PartiallySpecializedClassTemplate<void*>, f); // M32-DAG: define linkonce_odr x86_thiscallcc void @"\01?f@?$PartiallySpecializedClassTemplate@PAX@@QAEXXZ" // G32-DAG: define weak_odr dllexport x86_thiscallcc void @_ZN33PartiallySpecializedClassTemplateIPvE1fEv +// Attributes on explicit specializations are honored. template <typename T> struct ExplicitlySpecializedClassTemplate {}; template <> struct __declspec(dllexport) ExplicitlySpecializedClassTemplate<void*> { void f() {} }; USEMEMFUNC(ExplicitlySpecializedClassTemplate<void*>, f); // M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?f@?$ExplicitlySpecializedClassTemplate@PAX@@QAEXXZ" // G32-DAG: define weak_odr dllexport x86_thiscallcc void @_ZN34ExplicitlySpecializedClassTemplateIPvE1fEv +// MS inherits DLL attributes to partial specializations. +template <typename T> struct __declspec(dllexport) PartiallySpecializedExportedClassTemplate {}; +template <typename T> struct PartiallySpecializedExportedClassTemplate<T*> { void f() {} }; +USEMEMFUNC(PartiallySpecializedExportedClassTemplate<void*>, f); +// M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?f@?$PartiallySpecializedExportedClassTemplate@PAX@@QAEXXZ" +// G32-DAG: define linkonce_odr x86_thiscallcc void @_ZN41PartiallySpecializedExportedClassTemplateIPvE1fEv + +// MS ignores DLL attributes on partial specializations; inheritance still works though. +template <typename T> struct __declspec(dllexport) PartiallySpecializedExportedClassTemplate2 {}; +template <typename T> struct __declspec(dllimport) PartiallySpecializedExportedClassTemplate2<T*> { void f(); }; +template <typename T> void PartiallySpecializedExportedClassTemplate2<T*>::f() {} +USEMEMFUNC(PartiallySpecializedExportedClassTemplate2<void*>, f); +// M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?f@?$PartiallySpecializedExportedClassTemplate2@PAX@@QAEXXZ" +// G32-DAG: declare dllimport x86_thiscallcc void @_ZN42PartiallySpecializedExportedClassTemplate2IPvE1fEv + +// Attributes on the instantiation take precedence over attributes on the template. +template <typename T> struct __declspec(dllimport) ExplicitlyInstantiatedWithDifferentAttr { void f() {} }; +template struct __declspec(dllexport) ExplicitlyInstantiatedWithDifferentAttr<int>; +USEMEMFUNC(ExplicitlyInstantiatedWithDifferentAttr<int>, f); +// M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?f@?$ExplicitlyInstantiatedWithDifferentAttr@H@@QAEXXZ" + +// Don't create weak dllexport aliases. (PR21373) +struct NonExportedBaseClass { + virtual ~NonExportedBaseClass(); +}; +NonExportedBaseClass::~NonExportedBaseClass() {} + +struct __declspec(dllexport) ExportedDerivedClass : NonExportedBaseClass {}; +// M32-DAG: weak_odr dllexport x86_thiscallcc void @"\01??1ExportedDerivedClass@@UAE@XZ" + +// Do not assert about generating code for constexpr functions twice during explicit instantiation (PR21718). +template <typename T> struct ExplicitInstConstexprMembers { + // Copy assignment operator + // M32-DAG: define weak_odr dllexport x86_thiscallcc dereferenceable(1) %struct.ExplicitInstConstexprMembers* @"\01??4?$ExplicitInstConstexprMembers@X@@QAEAAU0@ABU0@@Z" + + constexpr 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" + + constexpr int f() const { return 42; } + // M32-DAG: define weak_odr dllexport x86_thiscallcc i32 @"\01?f@?$ExplicitInstConstexprMembers@X@@QBEHXZ" +}; +template struct __declspec(dllexport) ExplicitInstConstexprMembers<void>; + //===----------------------------------------------------------------------===// // Classes with template base classes //===----------------------------------------------------------------------===// template <typename T> struct ClassTemplate { void func() {} }; template <typename T> struct __declspec(dllexport) ExportedClassTemplate { void func() {} }; -template <typename T> struct __declspec(dllimport) ImportedClassTemplate { void func() {} }; +template <typename T> struct __declspec(dllimport) ImportedClassTemplate { void func(); }; +template <typename T> void ImportedClassTemplate<T>::func() {} template <typename T> struct ExplicitlySpecializedTemplate { void func() {} }; template <> struct ExplicitlySpecializedTemplate<int> { void func() {} }; template <typename T> struct ExplicitlyExportSpecializedTemplate { void func() {} }; template <> struct __declspec(dllexport) ExplicitlyExportSpecializedTemplate<int> { void func() {} }; -template <typename T> struct ExplicitlyImportSpecializedTemplate { void func() {} }; -template <> struct __declspec(dllimport) ExplicitlyImportSpecializedTemplate<int> { void func() {} }; +template <typename T> struct ExplicitlyImportSpecializedTemplate { void func(); }; +template <> struct __declspec(dllimport) ExplicitlyImportSpecializedTemplate<int> { void func(); }; template <typename T> struct ExplicitlyInstantiatedTemplate { void func() {} }; template struct ExplicitlyInstantiatedTemplate<int>; template <typename T> struct ExplicitlyExportInstantiatedTemplate { void func() {} }; template struct __declspec(dllexport) ExplicitlyExportInstantiatedTemplate<int>; -template <typename T> struct ExplicitlyImportInstantiatedTemplate { void func() {} }; +template <typename T> struct ExplicitlyImportInstantiatedTemplate { void func(); }; template struct __declspec(dllimport) ExplicitlyImportInstantiatedTemplate<int>; // MS: ClassTemplate<int> gets exported. struct __declspec(dllexport) DerivedFromTemplate : public ClassTemplate<int> {}; -USEMEMFUNC(ClassTemplate<int>, func) +USEMEMFUNC(DerivedFromTemplate, func) // M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?func@?$ClassTemplate@H@@QAEXXZ" // G32-DAG: define linkonce_odr x86_thiscallcc void @_ZN13ClassTemplateIiE4funcEv // ExportedTemplate is explicitly exported. struct __declspec(dllexport) DerivedFromExportedTemplate : public ExportedClassTemplate<int> {}; +USEMEMFUNC(DerivedFromExportedTemplate, func) // M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?func@?$ExportedClassTemplate@H@@QAEXXZ" // G32-DAG: define weak_odr dllexport x86_thiscallcc void @_ZN21ExportedClassTemplateIiE4funcEv // ImportedClassTemplate is explicitly imported. struct __declspec(dllexport) DerivedFromImportedTemplate : public ImportedClassTemplate<int> {}; -USEMEMFUNC(ImportedClassTemplate<int>, func) +USEMEMFUNC(DerivedFromImportedTemplate, func) // M32-DAG: {{declare|define available_externally}} dllimport x86_thiscallcc void @"\01?func@?$ImportedClassTemplate@H@@QAEXXZ" // G32-DAG: declare dllimport x86_thiscallcc void @_ZN21ImportedClassTemplateIiE4funcEv // Base class already instantiated without dll attribute. struct DerivedFromTemplateD : public ClassTemplate<double> {}; struct __declspec(dllexport) DerivedFromTemplateD2 : public ClassTemplate<double> {}; -USEMEMFUNC(ClassTemplate<double>, func) +USEMEMFUNC(DerivedFromTemplateD2, func) // M32-DAG: define linkonce_odr x86_thiscallcc void @"\01?func@?$ClassTemplate@N@@QAEXXZ" // G32-DAG: define linkonce_odr x86_thiscallcc void @_ZN13ClassTemplateIdE4funcEv // MS: Base class already instantiated with different dll attribute. struct __declspec(dllimport) DerivedFromTemplateB : public ClassTemplate<bool> {}; struct __declspec(dllexport) DerivedFromTemplateB2 : public ClassTemplate<bool> {}; -USEMEMFUNC(ClassTemplate<bool>, func) +USEMEMFUNC(DerivedFromTemplateB2, func) // M32-DAG: {{declare|define available_externally}} dllimport x86_thiscallcc void @"\01?func@?$ClassTemplate@_N@@QAEXXZ" // G32-DAG: define linkonce_odr x86_thiscallcc void @_ZN13ClassTemplateIbE4funcEv // Base class already specialized without dll attribute. struct __declspec(dllexport) DerivedFromExplicitlySpecializedTemplate : public ExplicitlySpecializedTemplate<int> {}; -USEMEMFUNC(ExplicitlySpecializedTemplate<int>, func) +USEMEMFUNC(DerivedFromExplicitlySpecializedTemplate, func) // M32-DAG: define linkonce_odr x86_thiscallcc void @"\01?func@?$ExplicitlySpecializedTemplate@H@@QAEXXZ" // G32-DAG: define linkonce_odr x86_thiscallcc void @_ZN29ExplicitlySpecializedTemplateIiE4funcEv // Base class alredy specialized with export attribute. struct __declspec(dllexport) DerivedFromExplicitlyExportSpecializedTemplate : public ExplicitlyExportSpecializedTemplate<int> {}; -USEMEMFUNC(ExplicitlyExportSpecializedTemplate<int>, func) +USEMEMFUNC(DerivedFromExplicitlyExportSpecializedTemplate, func) // M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?func@?$ExplicitlyExportSpecializedTemplate@H@@QAEXXZ" // G32-DAG: define weak_odr dllexport x86_thiscallcc void @_ZN35ExplicitlyExportSpecializedTemplateIiE4funcEv // Base class already specialized with import attribute. struct __declspec(dllexport) DerivedFromExplicitlyImportSpecializedTemplate : public ExplicitlyImportSpecializedTemplate<int> {}; -USEMEMFUNC(ExplicitlyImportSpecializedTemplate<int>, func) -// M32-DAG: {{declare|define available_externally}} dllimport x86_thiscallcc void @"\01?func@?$ExplicitlyImportSpecializedTemplate@H@@QAEXXZ" -// G32-DAG: {{declare|define available_externally}} dllimport x86_thiscallcc void @_ZN35ExplicitlyImportSpecializedTemplateIiE4funcEv +USEMEMFUNC(DerivedFromExplicitlyImportSpecializedTemplate, func) +// M32-DAG: declare dllimport x86_thiscallcc void @"\01?func@?$ExplicitlyImportSpecializedTemplate@H@@QAEXXZ" +// G32-DAG: declare dllimport x86_thiscallcc void @_ZN35ExplicitlyImportSpecializedTemplateIiE4funcEv // Base class already instantiated without dll attribute. struct __declspec(dllexport) DerivedFromExplicitlyInstantiatedTemplate : public ExplicitlyInstantiatedTemplate<int> {}; -USEMEMFUNC(ExplicitlyInstantiatedTemplate<int>, func) +USEMEMFUNC(DerivedFromExplicitlyInstantiatedTemplate, func) // M32-DAG: define weak_odr x86_thiscallcc void @"\01?func@?$ExplicitlyInstantiatedTemplate@H@@QAEXXZ" // G32-DAG: define weak_odr x86_thiscallcc void @_ZN30ExplicitlyInstantiatedTemplateIiE4funcEv // Base class already instantiated with export attribute. struct __declspec(dllexport) DerivedFromExplicitlyExportInstantiatedTemplate : public ExplicitlyExportInstantiatedTemplate<int> {}; -USEMEMFUNC(ExplicitlyExportInstantiatedTemplate<int>, func) +USEMEMFUNC(DerivedFromExplicitlyExportInstantiatedTemplate, func) // M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?func@?$ExplicitlyExportInstantiatedTemplate@H@@QAEXXZ" // G32-DAG: define weak_odr dllexport x86_thiscallcc void @_ZN36ExplicitlyExportInstantiatedTemplateIiE4funcEv // Base class already instantiated with import attribute. struct __declspec(dllexport) DerivedFromExplicitlyImportInstantiatedTemplate : public ExplicitlyImportInstantiatedTemplate<int> {}; -USEMEMFUNC(ExplicitlyImportInstantiatedTemplate<int>, func) -// M32-DAG: {{declare|define available_externally}} dllimport x86_thiscallcc void @"\01?func@?$ExplicitlyImportInstantiatedTemplate@H@@QAEXXZ" -// G32-DAG: {{declare|define available_externally}} dllimport x86_thiscallcc void @_ZN36ExplicitlyImportInstantiatedTemplateIiE4funcEv +USEMEMFUNC(DerivedFromExplicitlyImportInstantiatedTemplate, func) +// M32-DAG: declare dllimport x86_thiscallcc void @"\01?func@?$ExplicitlyImportInstantiatedTemplate@H@@QAEXXZ" +// G32-DAG: declare dllimport x86_thiscallcc void @_ZN36ExplicitlyImportInstantiatedTemplateIiE4funcEv // MS: A dll attribute propagates through multiple levels of instantiation. template <typename T> struct TopClass { void func() {} }; template <typename T> struct MiddleClass : public TopClass<T> { }; struct __declspec(dllexport) BottomClass : public MiddleClass<int> { }; -USEMEMFUNC(TopClass<int>, func) +USEMEMFUNC(BottomClass, func) // M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?func@?$TopClass@H@@QAEXXZ" // G32-DAG: define linkonce_odr x86_thiscallcc void @_ZN8TopClassIiE4funcEv diff --git a/test/CodeGenCXX/dllimport-members.cpp b/test/CodeGenCXX/dllimport-members.cpp index 6656b92b0022..e88b7e97c3e7 100644 --- a/test/CodeGenCXX/dllimport-members.cpp +++ b/test/CodeGenCXX/dllimport-members.cpp @@ -63,64 +63,64 @@ 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: 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*) - // M64-DAG: declare dllimport void @"\01?normalInclass@ImportMembers@@QEAAXXZ"(%struct.ImportMembers*) - // M32-DAG: declare dllimport x86_thiscallcc void @"\01?normalInlineDef@ImportMembers@@QAEXXZ"(%struct.ImportMembers*) - // M64-DAG: declare dllimport void @"\01?normalInlineDef@ImportMembers@@QEAAXXZ"(%struct.ImportMembers*) - // M32-DAG: declare dllimport x86_thiscallcc void @"\01?normalInlineDecl@ImportMembers@@QAEXXZ"(%struct.ImportMembers*) - // M64-DAG: declare dllimport void @"\01?normalInlineDecl@ImportMembers@@QEAAXXZ"(%struct.ImportMembers*) - // G32-DAG: define x86_thiscallcc void @_ZN13ImportMembers9normalDefEv(%struct.ImportMembers* %this) - // G64-DAG: define void @_ZN13ImportMembers9normalDefEv(%struct.ImportMembers* %this) - // G32-DAG: declare dllimport x86_thiscallcc void @_ZN13ImportMembers10normalDeclEv(%struct.ImportMembers*) - // G64-DAG: declare dllimport void @_ZN13ImportMembers10normalDeclEv(%struct.ImportMembers*) - // G32-DAG: declare dllimport x86_thiscallcc void @_ZN13ImportMembers13normalInclassEv(%struct.ImportMembers*) - // G64-DAG: declare dllimport void @_ZN13ImportMembers13normalInclassEv(%struct.ImportMembers*) - // G32-DAG: declare dllimport x86_thiscallcc void @_ZN13ImportMembers15normalInlineDefEv(%struct.ImportMembers*) - // G64-DAG: declare dllimport void @_ZN13ImportMembers15normalInlineDefEv(%struct.ImportMembers*) - // G32-DAG: declare dllimport x86_thiscallcc void @_ZN13ImportMembers16normalInlineDeclEv(%struct.ImportMembers*) - // G64-DAG: declare dllimport void @_ZN13ImportMembers16normalInlineDeclEv(%struct.ImportMembers*) + // 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: 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*) + // M64-DAG: declare dllimport void @"\01?normalInclass@ImportMembers@@QEAAXXZ"(%struct.ImportMembers*) + // M32-DAG: declare dllimport x86_thiscallcc void @"\01?normalInlineDef@ImportMembers@@QAEXXZ"(%struct.ImportMembers*) + // M64-DAG: declare dllimport void @"\01?normalInlineDef@ImportMembers@@QEAAXXZ"(%struct.ImportMembers*) + // M32-DAG: declare dllimport x86_thiscallcc void @"\01?normalInlineDecl@ImportMembers@@QAEXXZ"(%struct.ImportMembers*) + // M64-DAG: declare dllimport void @"\01?normalInlineDecl@ImportMembers@@QEAAXXZ"(%struct.ImportMembers*) + // G32-DAG: define x86_thiscallcc void @_ZN13ImportMembers9normalDefEv(%struct.ImportMembers* %this) + // G64-DAG: define void @_ZN13ImportMembers9normalDefEv(%struct.ImportMembers* %this) + // G32-DAG: declare dllimport x86_thiscallcc void @_ZN13ImportMembers10normalDeclEv(%struct.ImportMembers*) + // G64-DAG: declare dllimport void @_ZN13ImportMembers10normalDeclEv(%struct.ImportMembers*) + // G32-DAG: define linkonce_odr x86_thiscallcc void @_ZN13ImportMembers13normalInclassEv(%struct.ImportMembers* %this) + // G64-DAG: define linkonce_odr void @_ZN13ImportMembers13normalInclassEv(%struct.ImportMembers* %this) + // G32-DAG: define linkonce_odr x86_thiscallcc void @_ZN13ImportMembers15normalInlineDefEv(%struct.ImportMembers* %this) + // G64-DAG: define linkonce_odr void @_ZN13ImportMembers15normalInlineDefEv(%struct.ImportMembers* %this) + // G32-DAG: define linkonce_odr x86_thiscallcc void @_ZN13ImportMembers16normalInlineDeclEv(%struct.ImportMembers* %this) + // G64-DAG: define linkonce_odr void @_ZN13ImportMembers16normalInlineDeclEv(%struct.ImportMembers* %this) // MO1-DAG: define available_externally dllimport x86_thiscallcc void @"\01?normalInclass@ImportMembers@@QAEXXZ"( // MO1-DAG: define available_externally dllimport x86_thiscallcc void @"\01?normalInlineDef@ImportMembers@@QAEXXZ"( // MO1-DAG: define available_externally dllimport x86_thiscallcc void @"\01?normalInlineDecl@ImportMembers@@QAEXXZ"( - // GO1-DAG: define available_externally dllimport x86_thiscallcc void @_ZN13ImportMembers13normalInclassEv( - // GO1-DAG: define available_externally dllimport x86_thiscallcc void @_ZN13ImportMembers15normalInlineDefEv( - // GO1-DAG: define available_externally dllimport x86_thiscallcc void @_ZN13ImportMembers16normalInlineDeclEv( + // GO1-DAG: define linkonce_odr x86_thiscallcc void @_ZN13ImportMembers13normalInclassEv( + // GO1-DAG: define linkonce_odr x86_thiscallcc void @_ZN13ImportMembers15normalInlineDefEv( + // GO1-DAG: define linkonce_odr x86_thiscallcc void @_ZN13ImportMembers16normalInlineDeclEv( __declspec(dllimport) void normalDef(); // dllimport ignored __declspec(dllimport) void normalDecl(); __declspec(dllimport) void normalInclass() {} __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: 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*) - // M64-DAG: declare dllimport void @"\01?virtualInclass@ImportMembers@@UEAAXXZ"(%struct.ImportMembers*) - // M32-DAG: declare dllimport x86_thiscallcc void @"\01?virtualInlineDef@ImportMembers@@UAEXXZ"(%struct.ImportMembers*) - // M64-DAG: declare dllimport void @"\01?virtualInlineDef@ImportMembers@@UEAAXXZ"(%struct.ImportMembers*) - // M32-DAG: declare dllimport x86_thiscallcc void @"\01?virtualInlineDecl@ImportMembers@@UAEXXZ"(%struct.ImportMembers*) - // M64-DAG: declare dllimport void @"\01?virtualInlineDecl@ImportMembers@@UEAAXXZ"(%struct.ImportMembers*) - // G32-DAG: define x86_thiscallcc void @_ZN13ImportMembers10virtualDefEv(%struct.ImportMembers* %this) - // G64-DAG: define void @_ZN13ImportMembers10virtualDefEv(%struct.ImportMembers* %this) - // G32-DAG: declare dllimport x86_thiscallcc void @_ZN13ImportMembers11virtualDeclEv(%struct.ImportMembers*) - // G64-DAG: declare dllimport void @_ZN13ImportMembers11virtualDeclEv(%struct.ImportMembers*) - // G32-DAG: declare dllimport x86_thiscallcc void @_ZN13ImportMembers14virtualInclassEv(%struct.ImportMembers*) - // G64-DAG: declare dllimport void @_ZN13ImportMembers14virtualInclassEv(%struct.ImportMembers*) - // G32-DAG: declare dllimport x86_thiscallcc void @_ZN13ImportMembers16virtualInlineDefEv(%struct.ImportMembers*) - // G64-DAG: declare dllimport void @_ZN13ImportMembers16virtualInlineDefEv(%struct.ImportMembers*) - // G32-DAG: declare dllimport x86_thiscallcc void @_ZN13ImportMembers17virtualInlineDeclEv(%struct.ImportMembers*) - // G64-DAG: declare dllimport void @_ZN13ImportMembers17virtualInlineDeclEv(%struct.ImportMembers*) + // 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: 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*) + // M64-DAG: declare dllimport void @"\01?virtualInclass@ImportMembers@@UEAAXXZ"(%struct.ImportMembers*) + // M32-DAG: declare dllimport x86_thiscallcc void @"\01?virtualInlineDef@ImportMembers@@UAEXXZ"(%struct.ImportMembers*) + // M64-DAG: declare dllimport void @"\01?virtualInlineDef@ImportMembers@@UEAAXXZ"(%struct.ImportMembers*) + // M32-DAG: declare dllimport x86_thiscallcc void @"\01?virtualInlineDecl@ImportMembers@@UAEXXZ"(%struct.ImportMembers*) + // M64-DAG: declare dllimport void @"\01?virtualInlineDecl@ImportMembers@@UEAAXXZ"(%struct.ImportMembers*) + // G32-DAG: define x86_thiscallcc void @_ZN13ImportMembers10virtualDefEv(%struct.ImportMembers* %this) + // G64-DAG: define void @_ZN13ImportMembers10virtualDefEv(%struct.ImportMembers* %this) + // G32-DAG: declare dllimport x86_thiscallcc void @_ZN13ImportMembers11virtualDeclEv(%struct.ImportMembers*) + // G64-DAG: declare dllimport void @_ZN13ImportMembers11virtualDeclEv(%struct.ImportMembers*) + // G32-DAG: define linkonce_odr x86_thiscallcc void @_ZN13ImportMembers14virtualInclassEv(%struct.ImportMembers* %this) + // G64-DAG: define linkonce_odr void @_ZN13ImportMembers14virtualInclassEv(%struct.ImportMembers* %this) + // G32-DAG: define linkonce_odr x86_thiscallcc void @_ZN13ImportMembers16virtualInlineDefEv(%struct.ImportMembers* %this) + // G64-DAG: define linkonce_odr void @_ZN13ImportMembers16virtualInlineDefEv(%struct.ImportMembers* %this) + // G32-DAG: define linkonce_odr x86_thiscallcc void @_ZN13ImportMembers17virtualInlineDeclEv(%struct.ImportMembers* %this) + // G64-DAG: define linkonce_odr void @_ZN13ImportMembers17virtualInlineDeclEv(%struct.ImportMembers* %this) // MO1-DAG: define available_externally dllimport x86_thiscallcc void @"\01?virtualInclass@ImportMembers@@UAEXXZ"( // MO1-DAG: define available_externally dllimport x86_thiscallcc void @"\01?virtualInlineDef@ImportMembers@@UAEXXZ"( // MO1-DAG: define available_externally dllimport x86_thiscallcc void @"\01?virtualInlineDecl@ImportMembers@@UAEXXZ"( - // GO1-DAG: define available_externally dllimport x86_thiscallcc void @_ZN13ImportMembers14virtualInclassEv( - // GO1-DAG: define available_externally dllimport x86_thiscallcc void @_ZN13ImportMembers16virtualInlineDefEv( - // GO1-DAG: define available_externally dllimport x86_thiscallcc void @_ZN13ImportMembers17virtualInlineDeclEv( + // GO1-DAG: define linkonce_odr x86_thiscallcc void @_ZN13ImportMembers14virtualInclassEv( + // GO1-DAG: define linkonce_odr x86_thiscallcc void @_ZN13ImportMembers16virtualInlineDefEv( + // GO1-DAG: define linkonce_odr x86_thiscallcc void @_ZN13ImportMembers17virtualInlineDeclEv( __declspec(dllimport) virtual void virtualDef(); // dllimport ignored __declspec(dllimport) virtual void virtualDecl(); __declspec(dllimport) virtual void virtualInclass() {} @@ -134,15 +134,15 @@ struct ImportMembers { // MSC-DAG: declare dllimport void @"\01?staticInlineDecl@ImportMembers@@SAXXZ"() // GNU-DAG: define void @_ZN13ImportMembers9staticDefEv() // GNU-DAG: declare dllimport void @_ZN13ImportMembers10staticDeclEv() - // GNU-DAG: declare dllimport void @_ZN13ImportMembers13staticInclassEv() - // GNU-DAG: declare dllimport void @_ZN13ImportMembers15staticInlineDefEv() - // GNU-DAG: declare dllimport void @_ZN13ImportMembers16staticInlineDeclEv() + // GNU-DAG: define linkonce_odr void @_ZN13ImportMembers13staticInclassEv() + // GNU-DAG: define linkonce_odr void @_ZN13ImportMembers15staticInlineDefEv() + // GNU-DAG: define linkonce_odr void @_ZN13ImportMembers16staticInlineDeclEv() // MO1-DAG: define available_externally dllimport void @"\01?staticInclass@ImportMembers@@SAXXZ"() // MO1-DAG: define available_externally dllimport void @"\01?staticInlineDef@ImportMembers@@SAXXZ"() // MO1-DAG: define available_externally dllimport void @"\01?staticInlineDecl@ImportMembers@@SAXXZ"() - // GO1-DAG: define available_externally dllimport void @_ZN13ImportMembers13staticInclassEv() - // GO1-DAG: define available_externally dllimport void @_ZN13ImportMembers15staticInlineDefEv() - // GO1-DAG: define available_externally dllimport void @_ZN13ImportMembers16staticInlineDeclEv() + // GO1-DAG: define linkonce_odr void @_ZN13ImportMembers13staticInclassEv() + // GO1-DAG: define linkonce_odr void @_ZN13ImportMembers15staticInlineDefEv() + // GO1-DAG: define linkonce_odr void @_ZN13ImportMembers16staticInlineDeclEv() __declspec(dllimport) static void staticDef(); // dllimport ignored __declspec(dllimport) static void staticDecl(); __declspec(dllimport) static void staticInclass() {} @@ -235,65 +235,65 @@ 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: 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"*) - // M64-DAG: declare dllimport void @"\01?normalInclass@Nested@ImportMembers@@QEAAXXZ"(%"struct.ImportMembers::Nested"*) - // M32-DAG: declare dllimport x86_thiscallcc void @"\01?normalInlineDef@Nested@ImportMembers@@QAEXXZ"(%"struct.ImportMembers::Nested"*) - // M64-DAG: declare dllimport void @"\01?normalInlineDef@Nested@ImportMembers@@QEAAXXZ"(%"struct.ImportMembers::Nested"*) - // M32-DAG: declare dllimport x86_thiscallcc void @"\01?normalInlineDecl@Nested@ImportMembers@@QAEXXZ"(%"struct.ImportMembers::Nested"*) - // M64-DAG: declare dllimport void @"\01?normalInlineDecl@Nested@ImportMembers@@QEAAXXZ"(%"struct.ImportMembers::Nested"*) - // G32-DAG: define x86_thiscallcc void @_ZN13ImportMembers6Nested9normalDefEv(%"struct.ImportMembers::Nested"* %this) - // G64-DAG: define void @_ZN13ImportMembers6Nested9normalDefEv(%"struct.ImportMembers::Nested"* %this) - // G32-DAG: declare dllimport x86_thiscallcc void @_ZN13ImportMembers6Nested10normalDeclEv(%"struct.ImportMembers::Nested"*) - // G64-DAG: declare dllimport void @_ZN13ImportMembers6Nested10normalDeclEv(%"struct.ImportMembers::Nested"*) - // G32-DAG: declare dllimport x86_thiscallcc void @_ZN13ImportMembers6Nested13normalInclassEv(%"struct.ImportMembers::Nested"*) - // G64-DAG: declare dllimport void @_ZN13ImportMembers6Nested13normalInclassEv(%"struct.ImportMembers::Nested"*) - // G32-DAG: declare dllimport x86_thiscallcc void @_ZN13ImportMembers6Nested15normalInlineDefEv(%"struct.ImportMembers::Nested"*) - // G64-DAG: declare dllimport void @_ZN13ImportMembers6Nested15normalInlineDefEv(%"struct.ImportMembers::Nested"*) - // G32-DAG: declare dllimport x86_thiscallcc void @_ZN13ImportMembers6Nested16normalInlineDeclEv(%"struct.ImportMembers::Nested"*) - // G64-DAG: declare dllimport void @_ZN13ImportMembers6Nested16normalInlineDeclEv(%"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: 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"*) + // M64-DAG: declare dllimport void @"\01?normalInclass@Nested@ImportMembers@@QEAAXXZ"(%"struct.ImportMembers::Nested"*) + // M32-DAG: declare dllimport x86_thiscallcc void @"\01?normalInlineDef@Nested@ImportMembers@@QAEXXZ"(%"struct.ImportMembers::Nested"*) + // M64-DAG: declare dllimport void @"\01?normalInlineDef@Nested@ImportMembers@@QEAAXXZ"(%"struct.ImportMembers::Nested"*) + // M32-DAG: declare dllimport x86_thiscallcc void @"\01?normalInlineDecl@Nested@ImportMembers@@QAEXXZ"(%"struct.ImportMembers::Nested"*) + // M64-DAG: declare dllimport void @"\01?normalInlineDecl@Nested@ImportMembers@@QEAAXXZ"(%"struct.ImportMembers::Nested"*) + // G32-DAG: define x86_thiscallcc void @_ZN13ImportMembers6Nested9normalDefEv(%"struct.ImportMembers::Nested"* %this) + // G64-DAG: define void @_ZN13ImportMembers6Nested9normalDefEv(%"struct.ImportMembers::Nested"* %this) + // G32-DAG: declare dllimport x86_thiscallcc void @_ZN13ImportMembers6Nested10normalDeclEv(%"struct.ImportMembers::Nested"*) + // G64-DAG: declare dllimport void @_ZN13ImportMembers6Nested10normalDeclEv(%"struct.ImportMembers::Nested"*) + // G32-DAG: define linkonce_odr x86_thiscallcc void @_ZN13ImportMembers6Nested13normalInclassEv(%"struct.ImportMembers::Nested"* %this) + // G64-DAG: define linkonce_odr void @_ZN13ImportMembers6Nested13normalInclassEv(%"struct.ImportMembers::Nested"* %this) + // G32-DAG: define linkonce_odr x86_thiscallcc void @_ZN13ImportMembers6Nested15normalInlineDefEv(%"struct.ImportMembers::Nested"* %this) + // G64-DAG: define linkonce_odr void @_ZN13ImportMembers6Nested15normalInlineDefEv(%"struct.ImportMembers::Nested"* %this) + // G32-DAG: define linkonce_odr x86_thiscallcc void @_ZN13ImportMembers6Nested16normalInlineDeclEv(%"struct.ImportMembers::Nested"* %this) + // G64-DAG: define linkonce_odr void @_ZN13ImportMembers6Nested16normalInlineDeclEv(%"struct.ImportMembers::Nested"* %this) // MO1-DAG: define available_externally dllimport x86_thiscallcc void @"\01?normalInclass@Nested@ImportMembers@@QAEXXZ"( // MO1-DAG: define available_externally dllimport x86_thiscallcc void @"\01?normalInlineDef@Nested@ImportMembers@@QAEXXZ"( // MO1-DAG: define available_externally dllimport x86_thiscallcc void @"\01?normalInlineDecl@Nested@ImportMembers@@QAEXXZ"( - // GO1-DAG: define available_externally dllimport x86_thiscallcc void @_ZN13ImportMembers6Nested13normalInclassEv( - // GO1-DAG: define available_externally dllimport x86_thiscallcc void @_ZN13ImportMembers6Nested15normalInlineDefEv( - // GO1-DAG: define available_externally dllimport x86_thiscallcc void @_ZN13ImportMembers6Nested16normalInlineDeclEv( + // GO1-DAG: define linkonce_odr x86_thiscallcc void @_ZN13ImportMembers6Nested13normalInclassEv( + // GO1-DAG: define linkonce_odr x86_thiscallcc void @_ZN13ImportMembers6Nested15normalInlineDefEv( + // GO1-DAG: define linkonce_odr x86_thiscallcc void @_ZN13ImportMembers6Nested16normalInlineDeclEv( __declspec(dllimport) void normalDef(); // dllimport ignored __declspec(dllimport) void normalDecl(); __declspec(dllimport) void normalInclass() {} __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: 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"*) - // M64-DAG: declare dllimport void @"\01?virtualInclass@Nested@ImportMembers@@UEAAXXZ"(%"struct.ImportMembers::Nested"*) - // M32-DAG: declare dllimport x86_thiscallcc void @"\01?virtualInlineDef@Nested@ImportMembers@@UAEXXZ"(%"struct.ImportMembers::Nested"*) - // M64-DAG: declare dllimport void @"\01?virtualInlineDef@Nested@ImportMembers@@UEAAXXZ"(%"struct.ImportMembers::Nested"*) - // M32-DAG: declare dllimport x86_thiscallcc void @"\01?virtualInlineDecl@Nested@ImportMembers@@UAEXXZ"(%"struct.ImportMembers::Nested"*) - // M64-DAG: declare dllimport void @"\01?virtualInlineDecl@Nested@ImportMembers@@UEAAXXZ"(%"struct.ImportMembers::Nested"*) - // G32-DAG: define x86_thiscallcc void @_ZN13ImportMembers6Nested10virtualDefEv(%"struct.ImportMembers::Nested"* %this) - // G64-DAG: define void @_ZN13ImportMembers6Nested10virtualDefEv(%"struct.ImportMembers::Nested"* %this) - // G32-DAG: declare dllimport x86_thiscallcc void @_ZN13ImportMembers6Nested11virtualDeclEv(%"struct.ImportMembers::Nested"*) - // G64-DAG: declare dllimport void @_ZN13ImportMembers6Nested11virtualDeclEv(%"struct.ImportMembers::Nested"*) - // G32-DAG: declare dllimport x86_thiscallcc void @_ZN13ImportMembers6Nested14virtualInclassEv(%"struct.ImportMembers::Nested"*) - // G64-DAG: declare dllimport void @_ZN13ImportMembers6Nested14virtualInclassEv(%"struct.ImportMembers::Nested"*) - // G32-DAG: declare dllimport x86_thiscallcc void @_ZN13ImportMembers6Nested16virtualInlineDefEv(%"struct.ImportMembers::Nested"*) - // G64-DAG: declare dllimport void @_ZN13ImportMembers6Nested16virtualInlineDefEv(%"struct.ImportMembers::Nested"*) - // G32-DAG: declare dllimport x86_thiscallcc void @_ZN13ImportMembers6Nested17virtualInlineDeclEv(%"struct.ImportMembers::Nested"*) - // G64-DAG: declare dllimport void @_ZN13ImportMembers6Nested17virtualInlineDeclEv(%"struct.ImportMembers::Nested"*) + // 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: 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"*) + // M64-DAG: declare dllimport void @"\01?virtualInclass@Nested@ImportMembers@@UEAAXXZ"(%"struct.ImportMembers::Nested"*) + // M32-DAG: declare dllimport x86_thiscallcc void @"\01?virtualInlineDef@Nested@ImportMembers@@UAEXXZ"(%"struct.ImportMembers::Nested"*) + // M64-DAG: declare dllimport void @"\01?virtualInlineDef@Nested@ImportMembers@@UEAAXXZ"(%"struct.ImportMembers::Nested"*) + // M32-DAG: declare dllimport x86_thiscallcc void @"\01?virtualInlineDecl@Nested@ImportMembers@@UAEXXZ"(%"struct.ImportMembers::Nested"*) + // M64-DAG: declare dllimport void @"\01?virtualInlineDecl@Nested@ImportMembers@@UEAAXXZ"(%"struct.ImportMembers::Nested"*) + // G32-DAG: define x86_thiscallcc void @_ZN13ImportMembers6Nested10virtualDefEv(%"struct.ImportMembers::Nested"* %this) + // G64-DAG: define void @_ZN13ImportMembers6Nested10virtualDefEv(%"struct.ImportMembers::Nested"* %this) + // G32-DAG: declare dllimport x86_thiscallcc void @_ZN13ImportMembers6Nested11virtualDeclEv(%"struct.ImportMembers::Nested"*) + // G64-DAG: declare dllimport void @_ZN13ImportMembers6Nested11virtualDeclEv(%"struct.ImportMembers::Nested"*) + // G32-DAG: define linkonce_odr x86_thiscallcc void @_ZN13ImportMembers6Nested14virtualInclassEv(%"struct.ImportMembers::Nested"* %this) + // G64-DAG: define linkonce_odr void @_ZN13ImportMembers6Nested14virtualInclassEv(%"struct.ImportMembers::Nested"* %this) + // G32-DAG: define linkonce_odr x86_thiscallcc void @_ZN13ImportMembers6Nested16virtualInlineDefEv(%"struct.ImportMembers::Nested"* %this) + // G64-DAG: define linkonce_odr void @_ZN13ImportMembers6Nested16virtualInlineDefEv(%"struct.ImportMembers::Nested"* %this) + // G32-DAG: define linkonce_odr x86_thiscallcc void @_ZN13ImportMembers6Nested17virtualInlineDeclEv(%"struct.ImportMembers::Nested"* %this) + // G64-DAG: define linkonce_odr void @_ZN13ImportMembers6Nested17virtualInlineDeclEv(%"struct.ImportMembers::Nested"* %this) // MO1-DAG: define available_externally dllimport x86_thiscallcc void @"\01?virtualInclass@Nested@ImportMembers@@UAEXXZ"( // MO1-DAG: define available_externally dllimport x86_thiscallcc void @"\01?virtualInlineDef@Nested@ImportMembers@@UAEXXZ"( // MO1-DAG: define available_externally dllimport x86_thiscallcc void @"\01?virtualInlineDecl@Nested@ImportMembers@@UAEXXZ"( - // GO1-DAG: define available_externally dllimport x86_thiscallcc void @_ZN13ImportMembers6Nested14virtualInclassEv( - // GO1-DAG: define available_externally dllimport x86_thiscallcc void @_ZN13ImportMembers6Nested16virtualInlineDefEv( - // GO1-DAG: define available_externally dllimport x86_thiscallcc void @_ZN13ImportMembers6Nested17virtualInlineDeclEv( + // GO1-DAG: define linkonce_odr x86_thiscallcc void @_ZN13ImportMembers6Nested14virtualInclassEv( + // GO1-DAG: define linkonce_odr x86_thiscallcc void @_ZN13ImportMembers6Nested16virtualInlineDefEv( + // GO1-DAG: define linkonce_odr x86_thiscallcc void @_ZN13ImportMembers6Nested17virtualInlineDeclEv( __declspec(dllimport) virtual void virtualDef(); // dllimport ignored __declspec(dllimport) virtual void virtualDecl(); __declspec(dllimport) virtual void virtualInclass() {} @@ -307,15 +307,15 @@ struct ImportMembers::Nested { // MSC-DAG: declare dllimport void @"\01?staticInlineDecl@Nested@ImportMembers@@SAXXZ"() // GNU-DAG: define void @_ZN13ImportMembers6Nested9staticDefEv() // GNU-DAG: declare dllimport void @_ZN13ImportMembers6Nested10staticDeclEv() - // GNU-DAG: declare dllimport void @_ZN13ImportMembers6Nested13staticInclassEv() - // GNU-DAG: declare dllimport void @_ZN13ImportMembers6Nested15staticInlineDefEv() - // GNU-DAG: declare dllimport void @_ZN13ImportMembers6Nested16staticInlineDeclEv() + // GNU-DAG: define linkonce_odr void @_ZN13ImportMembers6Nested13staticInclassEv() + // GNU-DAG: define linkonce_odr void @_ZN13ImportMembers6Nested15staticInlineDefEv() + // GNU-DAG: define linkonce_odr void @_ZN13ImportMembers6Nested16staticInlineDeclEv() // MO1-DAG: define available_externally dllimport void @"\01?staticInclass@Nested@ImportMembers@@SAXXZ"() // MO1-DAG: define available_externally dllimport void @"\01?staticInlineDef@Nested@ImportMembers@@SAXXZ"() // MO1-DAG: define available_externally dllimport void @"\01?staticInlineDecl@Nested@ImportMembers@@SAXXZ"() - // GO1-DAG: define available_externally dllimport void @_ZN13ImportMembers6Nested13staticInclassEv() - // GO1-DAG: define available_externally dllimport void @_ZN13ImportMembers6Nested15staticInlineDefEv() - // GO1-DAG: define available_externally dllimport void @_ZN13ImportMembers6Nested16staticInlineDeclEv() + // GO1-DAG: define linkonce_odr void @_ZN13ImportMembers6Nested13staticInclassEv() + // GO1-DAG: define linkonce_odr void @_ZN13ImportMembers6Nested15staticInlineDefEv() + // GO1-DAG: define linkonce_odr void @_ZN13ImportMembers6Nested16staticInlineDeclEv() __declspec(dllimport) static void staticDef(); // dllimport ignored __declspec(dllimport) static void staticDecl(); __declspec(dllimport) static void staticInclass() {} @@ -449,52 +449,52 @@ USESPECIALS(ImportSpecials) // Export inline special member functions. struct ImportInlineSpecials { - // M32-DAG: declare dllimport x86_thiscallcc %struct.ImportInlineSpecials* @"\01??0ImportInlineSpecials@@QAE@XZ"(%struct.ImportInlineSpecials* returned) - // M64-DAG: declare dllimport %struct.ImportInlineSpecials* @"\01??0ImportInlineSpecials@@QEAA@XZ"(%struct.ImportInlineSpecials* returned) - // G32-DAG: declare dllimport x86_thiscallcc void @_ZN20ImportInlineSpecialsC1Ev(%struct.ImportInlineSpecials*) - // G64-DAG: declare dllimport void @_ZN20ImportInlineSpecialsC1Ev(%struct.ImportInlineSpecials*) + // M32-DAG: declare dllimport x86_thiscallcc %struct.ImportInlineSpecials* @"\01??0ImportInlineSpecials@@QAE@XZ"(%struct.ImportInlineSpecials* returned) + // M64-DAG: declare dllimport %struct.ImportInlineSpecials* @"\01??0ImportInlineSpecials@@QEAA@XZ"(%struct.ImportInlineSpecials* returned) + // G32-DAG: define linkonce_odr x86_thiscallcc void @_ZN20ImportInlineSpecialsC1Ev(%struct.ImportInlineSpecials* %this) + // G64-DAG: define linkonce_odr void @_ZN20ImportInlineSpecialsC1Ev(%struct.ImportInlineSpecials* %this) // MO1-DAG: define available_externally dllimport x86_thiscallcc %struct.ImportInlineSpecials* @"\01??0ImportInlineSpecials@@QAE@XZ"( - // GO1-DAG: define available_externally dllimport x86_thiscallcc void @_ZN20ImportInlineSpecialsC1Ev( + // GO1-DAG: define linkonce_odr x86_thiscallcc void @_ZN20ImportInlineSpecialsC1Ev( __declspec(dllimport) ImportInlineSpecials() {} - // M32-DAG: declare dllimport x86_thiscallcc void @"\01??1ImportInlineSpecials@@QAE@XZ"(%struct.ImportInlineSpecials*) - // M64-DAG: declare dllimport void @"\01??1ImportInlineSpecials@@QEAA@XZ"(%struct.ImportInlineSpecials*) - // G32-DAG: declare dllimport x86_thiscallcc void @_ZN20ImportInlineSpecialsD1Ev(%struct.ImportInlineSpecials*) - // G64-DAG: declare dllimport void @_ZN20ImportInlineSpecialsD1Ev(%struct.ImportInlineSpecials*) + // M32-DAG: declare dllimport x86_thiscallcc void @"\01??1ImportInlineSpecials@@QAE@XZ"(%struct.ImportInlineSpecials*) + // M64-DAG: declare dllimport void @"\01??1ImportInlineSpecials@@QEAA@XZ"(%struct.ImportInlineSpecials*) + // G32-DAG: define linkonce_odr x86_thiscallcc void @_ZN20ImportInlineSpecialsD1Ev(%struct.ImportInlineSpecials* %this) + // G64-DAG: define linkonce_odr void @_ZN20ImportInlineSpecialsD1Ev(%struct.ImportInlineSpecials* %this) // MO1-DAG: define available_externally dllimport x86_thiscallcc void @"\01??1ImportInlineSpecials@@QAE@XZ"( - // GO1-DAG: define available_externally dllimport x86_thiscallcc void @_ZN20ImportInlineSpecialsD1Ev( + // GO1-DAG: define linkonce_odr x86_thiscallcc void @_ZN20ImportInlineSpecialsD1Ev( __declspec(dllimport) ~ImportInlineSpecials() {} - // M32-DAG: declare dllimport x86_thiscallcc %struct.ImportInlineSpecials* @"\01??0ImportInlineSpecials@@QAE@ABU0@@Z"(%struct.ImportInlineSpecials* returned, %struct.ImportInlineSpecials* dereferenceable({{[0-9]+}})) - // M64-DAG: declare dllimport %struct.ImportInlineSpecials* @"\01??0ImportInlineSpecials@@QEAA@AEBU0@@Z"(%struct.ImportInlineSpecials* returned, %struct.ImportInlineSpecials* dereferenceable({{[0-9]+}})) - // G32-DAG: declare dllimport x86_thiscallcc void @_ZN20ImportInlineSpecialsC1ERKS_(%struct.ImportInlineSpecials*, %struct.ImportInlineSpecials* dereferenceable({{[0-9]+}})) - // G64-DAG: declare dllimport void @_ZN20ImportInlineSpecialsC1ERKS_(%struct.ImportInlineSpecials*, %struct.ImportInlineSpecials* dereferenceable({{[0-9]+}})) + // M32-DAG: declare dllimport x86_thiscallcc %struct.ImportInlineSpecials* @"\01??0ImportInlineSpecials@@QAE@ABU0@@Z"(%struct.ImportInlineSpecials* returned, %struct.ImportInlineSpecials* dereferenceable({{[0-9]+}})) + // M64-DAG: declare dllimport %struct.ImportInlineSpecials* @"\01??0ImportInlineSpecials@@QEAA@AEBU0@@Z"(%struct.ImportInlineSpecials* returned, %struct.ImportInlineSpecials* dereferenceable({{[0-9]+}})) + // G32-DAG: define linkonce_odr x86_thiscallcc void @_ZN20ImportInlineSpecialsC1ERKS_(%struct.ImportInlineSpecials* %this, %struct.ImportInlineSpecials* dereferenceable({{[0-9]+}})) + // G64-DAG: define linkonce_odr void @_ZN20ImportInlineSpecialsC1ERKS_(%struct.ImportInlineSpecials* %this, %struct.ImportInlineSpecials* dereferenceable({{[0-9]+}})) // MO1-DAG: define available_externally dllimport x86_thiscallcc %struct.ImportInlineSpecials* @"\01??0ImportInlineSpecials@@QAE@ABU0@@Z"( - // GO1-DAG: define available_externally dllimport x86_thiscallcc void @_ZN20ImportInlineSpecialsC1ERKS_( + // GO1-DAG: define linkonce_odr x86_thiscallcc void @_ZN20ImportInlineSpecialsC1ERKS_( __declspec(dllimport) inline ImportInlineSpecials(const ImportInlineSpecials&); - // M32-DAG: declare dllimport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportInlineSpecials* @"\01??4ImportInlineSpecials@@QAEAAU0@ABU0@@Z"(%struct.ImportInlineSpecials*, %struct.ImportInlineSpecials* dereferenceable({{[0-9]+}})) - // M64-DAG: declare dllimport dereferenceable({{[0-9]+}}) %struct.ImportInlineSpecials* @"\01??4ImportInlineSpecials@@QEAAAEAU0@AEBU0@@Z"(%struct.ImportInlineSpecials*, %struct.ImportInlineSpecials* dereferenceable({{[0-9]+}})) - // G32-DAG: declare dllimport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportInlineSpecials* @_ZN20ImportInlineSpecialsaSERKS_(%struct.ImportInlineSpecials*, %struct.ImportInlineSpecials* dereferenceable({{[0-9]+}})) - // G64-DAG: declare dllimport dereferenceable({{[0-9]+}}) %struct.ImportInlineSpecials* @_ZN20ImportInlineSpecialsaSERKS_(%struct.ImportInlineSpecials*, %struct.ImportInlineSpecials* dereferenceable({{[0-9]+}})) + // M32-DAG: declare dllimport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportInlineSpecials* @"\01??4ImportInlineSpecials@@QAEAAU0@ABU0@@Z"(%struct.ImportInlineSpecials*, %struct.ImportInlineSpecials* dereferenceable({{[0-9]+}})) + // M64-DAG: declare dllimport dereferenceable({{[0-9]+}}) %struct.ImportInlineSpecials* @"\01??4ImportInlineSpecials@@QEAAAEAU0@AEBU0@@Z"(%struct.ImportInlineSpecials*, %struct.ImportInlineSpecials* dereferenceable({{[0-9]+}})) + // G32-DAG: define linkonce_odr x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportInlineSpecials* @_ZN20ImportInlineSpecialsaSERKS_(%struct.ImportInlineSpecials* %this, %struct.ImportInlineSpecials* dereferenceable({{[0-9]+}})) + // G64-DAG: define linkonce_odr dereferenceable({{[0-9]+}}) %struct.ImportInlineSpecials* @_ZN20ImportInlineSpecialsaSERKS_(%struct.ImportInlineSpecials* %this, %struct.ImportInlineSpecials* dereferenceable({{[0-9]+}})) // MO1-DAG: define available_externally dllimport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportInlineSpecials* @"\01??4ImportInlineSpecials@@QAEAAU0@ABU0@@Z"( - // GO1-DAG: define available_externally dllimport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportInlineSpecials* @_ZN20ImportInlineSpecialsaSERKS_( + // GO1-DAG: define linkonce_odr x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportInlineSpecials* @_ZN20ImportInlineSpecialsaSERKS_( __declspec(dllimport) ImportInlineSpecials& operator=(const ImportInlineSpecials&); - // M32-DAG: declare dllimport x86_thiscallcc %struct.ImportInlineSpecials* @"\01??0ImportInlineSpecials@@QAE@$$QAU0@@Z"(%struct.ImportInlineSpecials* returned, %struct.ImportInlineSpecials* dereferenceable({{[0-9]+}})) - // M64-DAG: declare dllimport %struct.ImportInlineSpecials* @"\01??0ImportInlineSpecials@@QEAA@$$QEAU0@@Z"(%struct.ImportInlineSpecials* returned, %struct.ImportInlineSpecials* dereferenceable({{[0-9]+}})) - // G32-DAG: declare dllimport x86_thiscallcc void @_ZN20ImportInlineSpecialsC1EOS_(%struct.ImportInlineSpecials*, %struct.ImportInlineSpecials* dereferenceable({{[0-9]+}})) - // G64-DAG: declare dllimport void @_ZN20ImportInlineSpecialsC1EOS_(%struct.ImportInlineSpecials*, %struct.ImportInlineSpecials* dereferenceable({{[0-9]+}})) + // M32-DAG: declare dllimport x86_thiscallcc %struct.ImportInlineSpecials* @"\01??0ImportInlineSpecials@@QAE@$$QAU0@@Z"(%struct.ImportInlineSpecials* returned, %struct.ImportInlineSpecials* dereferenceable({{[0-9]+}})) + // M64-DAG: declare dllimport %struct.ImportInlineSpecials* @"\01??0ImportInlineSpecials@@QEAA@$$QEAU0@@Z"(%struct.ImportInlineSpecials* returned, %struct.ImportInlineSpecials* dereferenceable({{[0-9]+}})) + // G32-DAG: define linkonce_odr x86_thiscallcc void @_ZN20ImportInlineSpecialsC1EOS_(%struct.ImportInlineSpecials* %this, %struct.ImportInlineSpecials* dereferenceable({{[0-9]+}})) + // G64-DAG: define linkonce_odr void @_ZN20ImportInlineSpecialsC1EOS_(%struct.ImportInlineSpecials* %this, %struct.ImportInlineSpecials* dereferenceable({{[0-9]+}})) // MO1-DAG: define available_externally dllimport x86_thiscallcc %struct.ImportInlineSpecials* @"\01??0ImportInlineSpecials@@QAE@$$QAU0@@Z"( - // GO1-DAG: define available_externally dllimport x86_thiscallcc void @_ZN20ImportInlineSpecialsC1EOS_( + // GO1-DAG: define linkonce_odr x86_thiscallcc void @_ZN20ImportInlineSpecialsC1EOS_( __declspec(dllimport) ImportInlineSpecials(ImportInlineSpecials&&) {} - // M32-DAG: declare dllimport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportInlineSpecials* @"\01??4ImportInlineSpecials@@QAEAAU0@$$QAU0@@Z"(%struct.ImportInlineSpecials*, %struct.ImportInlineSpecials* dereferenceable({{[0-9]+}})) - // M64-DAG: declare dllimport dereferenceable({{[0-9]+}}) %struct.ImportInlineSpecials* @"\01??4ImportInlineSpecials@@QEAAAEAU0@$$QEAU0@@Z"(%struct.ImportInlineSpecials*, %struct.ImportInlineSpecials* dereferenceable({{[0-9]+}})) - // G32-DAG: declare dllimport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportInlineSpecials* @_ZN20ImportInlineSpecialsaSEOS_(%struct.ImportInlineSpecials*, %struct.ImportInlineSpecials* dereferenceable({{[0-9]+}})) - // G64-DAG: declare dllimport dereferenceable({{[0-9]+}}) %struct.ImportInlineSpecials* @_ZN20ImportInlineSpecialsaSEOS_(%struct.ImportInlineSpecials*, %struct.ImportInlineSpecials* dereferenceable({{[0-9]+}})) + // M32-DAG: declare dllimport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportInlineSpecials* @"\01??4ImportInlineSpecials@@QAEAAU0@$$QAU0@@Z"(%struct.ImportInlineSpecials*, %struct.ImportInlineSpecials* dereferenceable({{[0-9]+}})) + // M64-DAG: declare dllimport dereferenceable({{[0-9]+}}) %struct.ImportInlineSpecials* @"\01??4ImportInlineSpecials@@QEAAAEAU0@$$QEAU0@@Z"(%struct.ImportInlineSpecials*, %struct.ImportInlineSpecials* dereferenceable({{[0-9]+}})) + // G32-DAG: define linkonce_odr x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportInlineSpecials* @_ZN20ImportInlineSpecialsaSEOS_(%struct.ImportInlineSpecials* %this, %struct.ImportInlineSpecials* dereferenceable({{[0-9]+}})) + // G64-DAG: define linkonce_odr dereferenceable({{[0-9]+}}) %struct.ImportInlineSpecials* @_ZN20ImportInlineSpecialsaSEOS_(%struct.ImportInlineSpecials* %this, %struct.ImportInlineSpecials* dereferenceable({{[0-9]+}})) // MO1-DAG: define available_externally dllimport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportInlineSpecials* @"\01??4ImportInlineSpecials@@QAEAAU0@$$QAU0@@Z"( - // GO1-DAG: define available_externally dllimport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportInlineSpecials* @_ZN20ImportInlineSpecialsaSEOS_( + // GO1-DAG: define linkonce_odr x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportInlineSpecials* @_ZN20ImportInlineSpecialsaSEOS_( __declspec(dllimport) ImportInlineSpecials& operator=(ImportInlineSpecials&&) { return *this; } }; ImportInlineSpecials::ImportInlineSpecials(const ImportInlineSpecials&) {} @@ -504,52 +504,52 @@ USESPECIALS(ImportInlineSpecials) // Import defaulted member functions. struct ImportDefaulted { - // M32-DAG: declare dllimport x86_thiscallcc %struct.ImportDefaulted* @"\01??0ImportDefaulted@@QAE@XZ"(%struct.ImportDefaulted* returned) - // M64-DAG: declare dllimport %struct.ImportDefaulted* @"\01??0ImportDefaulted@@QEAA@XZ"(%struct.ImportDefaulted* returned) - // G32-DAG: declare dllimport x86_thiscallcc void @_ZN15ImportDefaultedC1Ev(%struct.ImportDefaulted*) - // G64-DAG: declare dllimport void @_ZN15ImportDefaultedC1Ev(%struct.ImportDefaulted*) + // M32-DAG: declare dllimport x86_thiscallcc %struct.ImportDefaulted* @"\01??0ImportDefaulted@@QAE@XZ"(%struct.ImportDefaulted* returned) + // M64-DAG: declare dllimport %struct.ImportDefaulted* @"\01??0ImportDefaulted@@QEAA@XZ"(%struct.ImportDefaulted* returned) + // G32-DAG: define linkonce_odr x86_thiscallcc void @_ZN15ImportDefaultedC1Ev(%struct.ImportDefaulted* %this) + // G64-DAG: define linkonce_odr void @_ZN15ImportDefaultedC1Ev(%struct.ImportDefaulted* %this) // MO1-DAG: define available_externally dllimport x86_thiscallcc %struct.ImportDefaulted* @"\01??0ImportDefaulted@@QAE@XZ"(%struct.ImportDefaulted* returned %this) - // GO1-DAG: define available_externally dllimport x86_thiscallcc void @_ZN15ImportDefaultedC1Ev(%struct.ImportDefaulted* %this) + // GO1-DAG: define linkonce_odr x86_thiscallcc void @_ZN15ImportDefaultedC1Ev(%struct.ImportDefaulted* %this) __declspec(dllimport) ImportDefaulted() = default; - // M32-DAG: declare dllimport x86_thiscallcc void @"\01??1ImportDefaulted@@QAE@XZ"(%struct.ImportDefaulted*) - // M64-DAG: declare dllimport void @"\01??1ImportDefaulted@@QEAA@XZ"(%struct.ImportDefaulted*) - // G32-DAG: declare dllimport x86_thiscallcc void @_ZN15ImportDefaultedD1Ev(%struct.ImportDefaulted*) - // G64-DAG: declare dllimport void @_ZN15ImportDefaultedD1Ev(%struct.ImportDefaulted*) + // M32-DAG: declare dllimport x86_thiscallcc void @"\01??1ImportDefaulted@@QAE@XZ"(%struct.ImportDefaulted*) + // M64-DAG: declare dllimport void @"\01??1ImportDefaulted@@QEAA@XZ"(%struct.ImportDefaulted*) + // G32-DAG: define linkonce_odr x86_thiscallcc void @_ZN15ImportDefaultedD1Ev(%struct.ImportDefaulted* %this) + // G64-DAG: define linkonce_odr void @_ZN15ImportDefaultedD1Ev(%struct.ImportDefaulted* %this) // MO1-DAG: define available_externally dllimport x86_thiscallcc void @"\01??1ImportDefaulted@@QAE@XZ"(%struct.ImportDefaulted* %this) - // GO1-DAG: define available_externally dllimport x86_thiscallcc void @_ZN15ImportDefaultedD1Ev(%struct.ImportDefaulted* %this) + // GO1-DAG: define linkonce_odr x86_thiscallcc void @_ZN15ImportDefaultedD1Ev(%struct.ImportDefaulted* %this) __declspec(dllimport) ~ImportDefaulted() = default; - // M32-DAG: declare dllimport x86_thiscallcc %struct.ImportDefaulted* @"\01??0ImportDefaulted@@QAE@ABU0@@Z"(%struct.ImportDefaulted* returned, %struct.ImportDefaulted* dereferenceable({{[0-9]+}})) - // M64-DAG: declare dllimport %struct.ImportDefaulted* @"\01??0ImportDefaulted@@QEAA@AEBU0@@Z"(%struct.ImportDefaulted* returned, %struct.ImportDefaulted* dereferenceable({{[0-9]+}})) - // G32-DAG: declare dllimport x86_thiscallcc void @_ZN15ImportDefaultedC1ERKS_(%struct.ImportDefaulted*, %struct.ImportDefaulted* dereferenceable({{[0-9]+}})) - // G64-DAG: declare dllimport void @_ZN15ImportDefaultedC1ERKS_(%struct.ImportDefaulted*, %struct.ImportDefaulted* dereferenceable({{[0-9]+}})) + // M32-DAG: declare dllimport x86_thiscallcc %struct.ImportDefaulted* @"\01??0ImportDefaulted@@QAE@ABU0@@Z"(%struct.ImportDefaulted* returned, %struct.ImportDefaulted* dereferenceable({{[0-9]+}})) + // M64-DAG: declare dllimport %struct.ImportDefaulted* @"\01??0ImportDefaulted@@QEAA@AEBU0@@Z"(%struct.ImportDefaulted* returned, %struct.ImportDefaulted* dereferenceable({{[0-9]+}})) + // G32-DAG: define linkonce_odr x86_thiscallcc void @_ZN15ImportDefaultedC1ERKS_(%struct.ImportDefaulted* %this, %struct.ImportDefaulted* dereferenceable({{[0-9]+}})) + // G64-DAG: define linkonce_odr void @_ZN15ImportDefaultedC1ERKS_(%struct.ImportDefaulted* %this, %struct.ImportDefaulted* dereferenceable({{[0-9]+}})) // MO1-DAG: define available_externally dllimport x86_thiscallcc %struct.ImportDefaulted* @"\01??0ImportDefaulted@@QAE@ABU0@@Z"(%struct.ImportDefaulted* returned %this, %struct.ImportDefaulted* dereferenceable({{[0-9]+}})) - // GO1-DAG: define available_externally dllimport x86_thiscallcc void @_ZN15ImportDefaultedC1ERKS_(%struct.ImportDefaulted* %this, %struct.ImportDefaulted* dereferenceable({{[0-9]+}})) + // GO1-DAG: define linkonce_odr x86_thiscallcc void @_ZN15ImportDefaultedC1ERKS_(%struct.ImportDefaulted* %this, %struct.ImportDefaulted* dereferenceable({{[0-9]+}})) __declspec(dllimport) ImportDefaulted(const ImportDefaulted&) = default; - // M32-DAG: declare dllimport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportDefaulted* @"\01??4ImportDefaulted@@QAEAAU0@ABU0@@Z"(%struct.ImportDefaulted*, %struct.ImportDefaulted* dereferenceable({{[0-9]+}})) - // M64-DAG: declare dllimport dereferenceable({{[0-9]+}}) %struct.ImportDefaulted* @"\01??4ImportDefaulted@@QEAAAEAU0@AEBU0@@Z"(%struct.ImportDefaulted*, %struct.ImportDefaulted* dereferenceable({{[0-9]+}})) - // G32-DAG: declare dllimport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportDefaulted* @_ZN15ImportDefaultedaSERKS_(%struct.ImportDefaulted*, %struct.ImportDefaulted* dereferenceable({{[0-9]+}})) - // G64-DAG: declare dllimport dereferenceable({{[0-9]+}}) %struct.ImportDefaulted* @_ZN15ImportDefaultedaSERKS_(%struct.ImportDefaulted*, %struct.ImportDefaulted* dereferenceable({{[0-9]+}})) + // M32-DAG: declare dllimport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportDefaulted* @"\01??4ImportDefaulted@@QAEAAU0@ABU0@@Z"(%struct.ImportDefaulted*, %struct.ImportDefaulted* dereferenceable({{[0-9]+}})) + // M64-DAG: declare dllimport dereferenceable({{[0-9]+}}) %struct.ImportDefaulted* @"\01??4ImportDefaulted@@QEAAAEAU0@AEBU0@@Z"(%struct.ImportDefaulted*, %struct.ImportDefaulted* dereferenceable({{[0-9]+}})) + // G32-DAG: define linkonce_odr x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportDefaulted* @_ZN15ImportDefaultedaSERKS_(%struct.ImportDefaulted* %this, %struct.ImportDefaulted* dereferenceable({{[0-9]+}})) + // G64-DAG: define linkonce_odr dereferenceable({{[0-9]+}}) %struct.ImportDefaulted* @_ZN15ImportDefaultedaSERKS_(%struct.ImportDefaulted* %this, %struct.ImportDefaulted* dereferenceable({{[0-9]+}})) // MO1-DAG: define available_externally dllimport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportDefaulted* @"\01??4ImportDefaulted@@QAEAAU0@ABU0@@Z"(%struct.ImportDefaulted* %this, %struct.ImportDefaulted* dereferenceable({{[0-9]+}})) - // GO1-DAG: define available_externally dllimport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportDefaulted* @_ZN15ImportDefaultedaSERKS_(%struct.ImportDefaulted* %this, %struct.ImportDefaulted* dereferenceable({{[0-9]+}})) + // GO1-DAG: define linkonce_odr x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportDefaulted* @_ZN15ImportDefaultedaSERKS_(%struct.ImportDefaulted* %this, %struct.ImportDefaulted* dereferenceable({{[0-9]+}})) __declspec(dllimport) ImportDefaulted& operator=(const ImportDefaulted&) = default; - // M32-DAG: declare dllimport x86_thiscallcc %struct.ImportDefaulted* @"\01??0ImportDefaulted@@QAE@$$QAU0@@Z"(%struct.ImportDefaulted* returned, %struct.ImportDefaulted* dereferenceable({{[0-9]+}})) - // M64-DAG: declare dllimport %struct.ImportDefaulted* @"\01??0ImportDefaulted@@QEAA@$$QEAU0@@Z"(%struct.ImportDefaulted* returned, %struct.ImportDefaulted* dereferenceable({{[0-9]+}})) - // G32-DAG: declare dllimport x86_thiscallcc void @_ZN15ImportDefaultedC1EOS_(%struct.ImportDefaulted*, %struct.ImportDefaulted* dereferenceable({{[0-9]+}})) - // G64-DAG: declare dllimport void @_ZN15ImportDefaultedC1EOS_(%struct.ImportDefaulted*, %struct.ImportDefaulted* dereferenceable({{[0-9]+}})) + // M32-DAG: declare dllimport x86_thiscallcc %struct.ImportDefaulted* @"\01??0ImportDefaulted@@QAE@$$QAU0@@Z"(%struct.ImportDefaulted* returned, %struct.ImportDefaulted* dereferenceable({{[0-9]+}})) + // M64-DAG: declare dllimport %struct.ImportDefaulted* @"\01??0ImportDefaulted@@QEAA@$$QEAU0@@Z"(%struct.ImportDefaulted* returned, %struct.ImportDefaulted* dereferenceable({{[0-9]+}})) + // G32-DAG: define linkonce_odr x86_thiscallcc void @_ZN15ImportDefaultedC1EOS_(%struct.ImportDefaulted* %this, %struct.ImportDefaulted* dereferenceable({{[0-9]+}})) + // G64-DAG: define linkonce_odr void @_ZN15ImportDefaultedC1EOS_(%struct.ImportDefaulted* %this, %struct.ImportDefaulted* dereferenceable({{[0-9]+}})) // MO1-DAG: define available_externally dllimport x86_thiscallcc %struct.ImportDefaulted* @"\01??0ImportDefaulted@@QAE@$$QAU0@@Z"(%struct.ImportDefaulted* returned %this, %struct.ImportDefaulted* dereferenceable({{[0-9]+}})) - // GO1-DAG: define available_externally dllimport x86_thiscallcc void @_ZN15ImportDefaultedC1EOS_(%struct.ImportDefaulted* %this, %struct.ImportDefaulted* dereferenceable({{[0-9]+}})) + // GO1-DAG: define linkonce_odr x86_thiscallcc void @_ZN15ImportDefaultedC1EOS_(%struct.ImportDefaulted* %this, %struct.ImportDefaulted* dereferenceable({{[0-9]+}})) __declspec(dllimport) ImportDefaulted(ImportDefaulted&&) = default; - // M32-DAG: declare dllimport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportDefaulted* @"\01??4ImportDefaulted@@QAEAAU0@$$QAU0@@Z"(%struct.ImportDefaulted*, %struct.ImportDefaulted* dereferenceable({{[0-9]+}})) - // M64-DAG: declare dllimport dereferenceable({{[0-9]+}}) %struct.ImportDefaulted* @"\01??4ImportDefaulted@@QEAAAEAU0@$$QEAU0@@Z"(%struct.ImportDefaulted*, %struct.ImportDefaulted* dereferenceable({{[0-9]+}})) - // G32-DAG: declare dllimport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportDefaulted* @_ZN15ImportDefaultedaSEOS_(%struct.ImportDefaulted*, %struct.ImportDefaulted* dereferenceable({{[0-9]+}})) - // G64-DAG: declare dllimport dereferenceable({{[0-9]+}}) %struct.ImportDefaulted* @_ZN15ImportDefaultedaSEOS_(%struct.ImportDefaulted*, %struct.ImportDefaulted* dereferenceable({{[0-9]+}})) + // M32-DAG: declare dllimport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportDefaulted* @"\01??4ImportDefaulted@@QAEAAU0@$$QAU0@@Z"(%struct.ImportDefaulted*, %struct.ImportDefaulted* dereferenceable({{[0-9]+}})) + // M64-DAG: declare dllimport dereferenceable({{[0-9]+}}) %struct.ImportDefaulted* @"\01??4ImportDefaulted@@QEAAAEAU0@$$QEAU0@@Z"(%struct.ImportDefaulted*, %struct.ImportDefaulted* dereferenceable({{[0-9]+}})) + // G32-DAG: define linkonce_odr x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportDefaulted* @_ZN15ImportDefaultedaSEOS_(%struct.ImportDefaulted* %this, %struct.ImportDefaulted* dereferenceable({{[0-9]+}})) + // G64-DAG: define linkonce_odr dereferenceable({{[0-9]+}}) %struct.ImportDefaulted* @_ZN15ImportDefaultedaSEOS_(%struct.ImportDefaulted* %this, %struct.ImportDefaulted* dereferenceable({{[0-9]+}})) // MO1-DAG: define available_externally dllimport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportDefaulted* @"\01??4ImportDefaulted@@QAEAAU0@$$QAU0@@Z"(%struct.ImportDefaulted* %this, %struct.ImportDefaulted* dereferenceable({{[0-9]+}})) - // GO1-DAG: define available_externally dllimport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportDefaulted* @_ZN15ImportDefaultedaSEOS_(%struct.ImportDefaulted* %this, %struct.ImportDefaulted* dereferenceable({{[0-9]+}})) + // GO1-DAG: define linkonce_odr x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportDefaulted* @_ZN15ImportDefaultedaSEOS_(%struct.ImportDefaulted* %this, %struct.ImportDefaulted* dereferenceable({{[0-9]+}})) __declspec(dllimport) ImportDefaulted& operator=(ImportDefaulted&&) = default; ForceNonTrivial v; // ensure special members are non-trivial @@ -569,28 +569,30 @@ struct ImportDefaultedDefs { __declspec(dllimport) ImportDefaultedDefs& operator=(ImportDefaultedDefs&&); }; +#ifdef MSABI +// For MinGW, the function will not be dllimport, and we cannot add the attribute now. // M32-DAG: declare dllimport x86_thiscallcc %struct.ImportDefaultedDefs* @"\01??0ImportDefaultedDefs@@QAE@XZ"(%struct.ImportDefaultedDefs* returned) // M64-DAG: declare dllimport %struct.ImportDefaultedDefs* @"\01??0ImportDefaultedDefs@@QEAA@XZ"(%struct.ImportDefaultedDefs* returned) -// G32-DAG: declare dllimport x86_thiscallcc void @_ZN19ImportDefaultedDefsC1Ev(%struct.ImportDefaultedDefs*) -// G64-DAG: declare dllimport void @_ZN19ImportDefaultedDefsC1Ev(%struct.ImportDefaultedDefs*) __declspec(dllimport) ImportDefaultedDefs::ImportDefaultedDefs() = default; +#endif +#ifdef MSABI +// For MinGW, the function will not be dllimport, and we cannot add the attribute now. // M32-DAG: declare dllimport x86_thiscallcc void @"\01??1ImportDefaultedDefs@@QAE@XZ"(%struct.ImportDefaultedDefs*) // M64-DAG: declare dllimport void @"\01??1ImportDefaultedDefs@@QEAA@XZ"(%struct.ImportDefaultedDefs*) -// G32-DAG: declare dllimport x86_thiscallcc void @_ZN19ImportDefaultedDefsD1Ev(%struct.ImportDefaultedDefs*) -// G64-DAG: declare dllimport void @_ZN19ImportDefaultedDefsD1Ev(%struct.ImportDefaultedDefs*) __declspec(dllimport) ImportDefaultedDefs::~ImportDefaultedDefs() = default; +#endif -// M32-DAG: declare dllimport x86_thiscallcc %struct.ImportDefaultedDefs* @"\01??0ImportDefaultedDefs@@QAE@ABU0@@Z"(%struct.ImportDefaultedDefs* returned, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}})) -// M64-DAG: declare dllimport %struct.ImportDefaultedDefs* @"\01??0ImportDefaultedDefs@@QEAA@AEBU0@@Z"(%struct.ImportDefaultedDefs* returned, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}})) -// G32-DAG: declare dllimport x86_thiscallcc void @_ZN19ImportDefaultedDefsC1ERKS_(%struct.ImportDefaultedDefs*, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}})) -// G64-DAG: declare dllimport void @_ZN19ImportDefaultedDefsC1ERKS_(%struct.ImportDefaultedDefs*, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}})) +// M32-DAG: declare dllimport x86_thiscallcc %struct.ImportDefaultedDefs* @"\01??0ImportDefaultedDefs@@QAE@ABU0@@Z"(%struct.ImportDefaultedDefs* returned, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}})) +// M64-DAG: declare dllimport %struct.ImportDefaultedDefs* @"\01??0ImportDefaultedDefs@@QEAA@AEBU0@@Z"(%struct.ImportDefaultedDefs* returned, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}})) +// G32-DAG: define linkonce_odr x86_thiscallcc void @_ZN19ImportDefaultedDefsC1ERKS_(%struct.ImportDefaultedDefs* %this, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}})) +// G64-DAG: define linkonce_odr void @_ZN19ImportDefaultedDefsC1ERKS_(%struct.ImportDefaultedDefs* %this, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}})) inline ImportDefaultedDefs::ImportDefaultedDefs(const ImportDefaultedDefs&) = default; -// M32-DAG: declare dllimport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportDefaultedDefs* @"\01??4ImportDefaultedDefs@@QAEAAU0@ABU0@@Z"(%struct.ImportDefaultedDefs*, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}})) -// M64-DAG: declare dllimport dereferenceable({{[0-9]+}}) %struct.ImportDefaultedDefs* @"\01??4ImportDefaultedDefs@@QEAAAEAU0@AEBU0@@Z"(%struct.ImportDefaultedDefs*, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}})) -// G32-DAG: declare dllimport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportDefaultedDefs* @_ZN19ImportDefaultedDefsaSERKS_(%struct.ImportDefaultedDefs*, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}})) -// G64-DAG: declare dllimport dereferenceable({{[0-9]+}}) %struct.ImportDefaultedDefs* @_ZN19ImportDefaultedDefsaSERKS_(%struct.ImportDefaultedDefs*, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}})) +// M32-DAG: declare dllimport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportDefaultedDefs* @"\01??4ImportDefaultedDefs@@QAEAAU0@ABU0@@Z"(%struct.ImportDefaultedDefs*, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}})) +// M64-DAG: declare dllimport dereferenceable({{[0-9]+}}) %struct.ImportDefaultedDefs* @"\01??4ImportDefaultedDefs@@QEAAAEAU0@AEBU0@@Z"(%struct.ImportDefaultedDefs*, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}})) +// G32-DAG: define linkonce_odr x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportDefaultedDefs* @_ZN19ImportDefaultedDefsaSERKS_(%struct.ImportDefaultedDefs* %this, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}})) +// 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]+}})) @@ -655,14 +657,14 @@ struct MemFunTmpl { }; // Import implicit instantiation of an imported member function template. -// M32-DAG: declare dllimport x86_thiscallcc void @"\01??$importedNormal@UImplicitInst_Imported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl*) -// M64-DAG: declare dllimport void @"\01??$importedNormal@UImplicitInst_Imported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl*) -// G32-DAG: declare dllimport x86_thiscallcc void @_ZN10MemFunTmpl14importedNormalI21ImplicitInst_ImportedEEvv(%struct.MemFunTmpl*) -// G64-DAG: declare dllimport void @_ZN10MemFunTmpl14importedNormalI21ImplicitInst_ImportedEEvv(%struct.MemFunTmpl*) +// M32-DAG: declare dllimport x86_thiscallcc void @"\01??$importedNormal@UImplicitInst_Imported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl*) +// M64-DAG: declare dllimport void @"\01??$importedNormal@UImplicitInst_Imported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl*) +// G32-DAG: define linkonce_odr x86_thiscallcc void @_ZN10MemFunTmpl14importedNormalI21ImplicitInst_ImportedEEvv(%struct.MemFunTmpl* %this) +// G64-DAG: define linkonce_odr void @_ZN10MemFunTmpl14importedNormalI21ImplicitInst_ImportedEEvv(%struct.MemFunTmpl* %this) USEMF(MemFunTmpl, importedNormal<ImplicitInst_Imported>) // MSC-DAG: declare dllimport void @"\01??$importedStatic@UImplicitInst_Imported@@@MemFunTmpl@@SAXXZ"() -// GNU-DAG: declare dllimport void @_ZN10MemFunTmpl14importedStaticI21ImplicitInst_ImportedEEvv() +// GNU-DAG: define linkonce_odr void @_ZN10MemFunTmpl14importedStaticI21ImplicitInst_ImportedEEvv() USE(MemFunTmpl::importedStatic<ImplicitInst_Imported>) @@ -670,13 +672,13 @@ USE(MemFunTmpl::importedStatic<ImplicitInst_Imported>) // template. // M32-DAG: declare dllimport x86_thiscallcc void @"\01??$importedNormal@UExplicitDecl_Imported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl*) // M64-DAG: declare dllimport void @"\01??$importedNormal@UExplicitDecl_Imported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl*) -// G32-DAG: declare dllimport x86_thiscallcc void @_ZN10MemFunTmpl14importedNormalI21ExplicitDecl_ImportedEEvv(%struct.MemFunTmpl*) -// G64-DAG: declare dllimport void @_ZN10MemFunTmpl14importedNormalI21ExplicitDecl_ImportedEEvv(%struct.MemFunTmpl*) +// G32-DAG: declare x86_thiscallcc void @_ZN10MemFunTmpl14importedNormalI21ExplicitDecl_ImportedEEvv(%struct.MemFunTmpl*) +// G64-DAG: declare void @_ZN10MemFunTmpl14importedNormalI21ExplicitDecl_ImportedEEvv(%struct.MemFunTmpl*) extern template void MemFunTmpl::importedNormal<ExplicitDecl_Imported>(); USEMF(MemFunTmpl, importedNormal<ExplicitDecl_Imported>) // MSC-DAG: declare dllimport void @"\01??$importedStatic@UExplicitDecl_Imported@@@MemFunTmpl@@SAXXZ"() -// GNU-DAG: declare dllimport void @_ZN10MemFunTmpl14importedStaticI21ExplicitDecl_ImportedEEvv() +// GNU-DAG: declare void @_ZN10MemFunTmpl14importedStaticI21ExplicitDecl_ImportedEEvv() extern template void MemFunTmpl::importedStatic<ExplicitDecl_Imported>(); USE(MemFunTmpl::importedStatic<ExplicitDecl_Imported>) @@ -685,13 +687,13 @@ USE(MemFunTmpl::importedStatic<ExplicitDecl_Imported>) // template. // M32-DAG: declare dllimport x86_thiscallcc void @"\01??$importedNormal@UExplicitInst_Imported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl*) // M64-DAG: declare dllimport void @"\01??$importedNormal@UExplicitInst_Imported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl*) -// G32-DAG: declare dllimport x86_thiscallcc void @_ZN10MemFunTmpl14importedNormalI21ExplicitInst_ImportedEEvv(%struct.MemFunTmpl*) -// G64-DAG: declare dllimport void @_ZN10MemFunTmpl14importedNormalI21ExplicitInst_ImportedEEvv(%struct.MemFunTmpl*) +// G32-DAG: define weak_odr x86_thiscallcc void @_ZN10MemFunTmpl14importedNormalI21ExplicitInst_ImportedEEvv(%struct.MemFunTmpl* %this) +// G64-DAG: define weak_odr void @_ZN10MemFunTmpl14importedNormalI21ExplicitInst_ImportedEEvv(%struct.MemFunTmpl* %this) template void MemFunTmpl::importedNormal<ExplicitInst_Imported>(); USEMF(MemFunTmpl, importedNormal<ExplicitInst_Imported>) // MSC-DAG: declare dllimport void @"\01??$importedStatic@UExplicitInst_Imported@@@MemFunTmpl@@SAXXZ"() -// GNU-DAG: declare dllimport void @_ZN10MemFunTmpl14importedStaticI21ExplicitInst_ImportedEEvv() +// GNU-DAG: define weak_odr void @_ZN10MemFunTmpl14importedStaticI21ExplicitInst_ImportedEEvv() template void MemFunTmpl::importedStatic<ExplicitInst_Imported>(); USE(MemFunTmpl::importedStatic<ExplicitInst_Imported>) @@ -711,10 +713,10 @@ USEMF(MemFunTmpl, importedNormal<ExplicitSpec_Imported>) //USEMF(MemFunTmpl, importedNormal<ExplicitSpec_Def_Imported>) #endif -// M32-DAG: declare dllimport x86_thiscallcc void @"\01??$importedNormal@UExplicitSpec_InlineDef_Imported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl*) -// M64-DAG: declare dllimport void @"\01??$importedNormal@UExplicitSpec_InlineDef_Imported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl*) -// G32-DAG: declare dllimport x86_thiscallcc void @_ZN10MemFunTmpl14importedNormalI31ExplicitSpec_InlineDef_ImportedEEvv(%struct.MemFunTmpl*) -// G64-DAG: declare dllimport void @_ZN10MemFunTmpl14importedNormalI31ExplicitSpec_InlineDef_ImportedEEvv(%struct.MemFunTmpl*) +// M32-DAG: declare dllimport x86_thiscallcc void @"\01??$importedNormal@UExplicitSpec_InlineDef_Imported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl*) +// M64-DAG: declare dllimport void @"\01??$importedNormal@UExplicitSpec_InlineDef_Imported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl*) +// G32-DAG: define linkonce_odr x86_thiscallcc void @_ZN10MemFunTmpl14importedNormalI31ExplicitSpec_InlineDef_ImportedEEvv(%struct.MemFunTmpl* %this) +// G64-DAG: define linkonce_odr void @_ZN10MemFunTmpl14importedNormalI31ExplicitSpec_InlineDef_ImportedEEvv(%struct.MemFunTmpl* %this) template<> __declspec(dllimport) inline void MemFunTmpl::importedNormal<ExplicitSpec_InlineDef_Imported>() {} USEMF(MemFunTmpl, importedNormal<ExplicitSpec_InlineDef_Imported>) @@ -731,7 +733,7 @@ USE(MemFunTmpl::importedStatic<ExplicitSpec_Imported>) #endif // MSC-DAG: declare dllimport void @"\01??$importedStatic@UExplicitSpec_InlineDef_Imported@@@MemFunTmpl@@SAXXZ"() -// GNU-DAG: declare dllimport void @_ZN10MemFunTmpl14importedStaticI31ExplicitSpec_InlineDef_ImportedEEvv() +// GNU-DAG: define linkonce_odr void @_ZN10MemFunTmpl14importedStaticI31ExplicitSpec_InlineDef_ImportedEEvv() template<> __declspec(dllimport) inline void MemFunTmpl::importedStatic<ExplicitSpec_InlineDef_Imported>() {} USE(MemFunTmpl::importedStatic<ExplicitSpec_InlineDef_Imported>) @@ -755,13 +757,13 @@ USE(MemFunTmpl::importedStatic<ExplicitSpec_NotImported>) // template. // M32-DAG: declare dllimport x86_thiscallcc void @"\01??$normalDef@UExplicitDecl_Imported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl*) // M64-DAG: declare dllimport void @"\01??$normalDef@UExplicitDecl_Imported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl*) -// G32-DAG: declare dllimport x86_thiscallcc void @_ZN10MemFunTmpl9normalDefI21ExplicitDecl_ImportedEEvv(%struct.MemFunTmpl*) -// G64-DAG: declare dllimport void @_ZN10MemFunTmpl9normalDefI21ExplicitDecl_ImportedEEvv(%struct.MemFunTmpl*) +// G32-DAG: declare x86_thiscallcc void @_ZN10MemFunTmpl9normalDefI21ExplicitDecl_ImportedEEvv(%struct.MemFunTmpl*) +// G64-DAG: declare void @_ZN10MemFunTmpl9normalDefI21ExplicitDecl_ImportedEEvv(%struct.MemFunTmpl*) extern template __declspec(dllimport) void MemFunTmpl::normalDef<ExplicitDecl_Imported>(); USEMF(MemFunTmpl, normalDef<ExplicitDecl_Imported>) // MSC-DAG: declare dllimport void @"\01??$staticDef@UExplicitDecl_Imported@@@MemFunTmpl@@SAXXZ"() -// GNU-DAG: declare dllimport void @_ZN10MemFunTmpl9staticDefI21ExplicitDecl_ImportedEEvv() +// GNU-DAG: declare void @_ZN10MemFunTmpl9staticDefI21ExplicitDecl_ImportedEEvv() extern template __declspec(dllimport) void MemFunTmpl::staticDef<ExplicitDecl_Imported>(); USE(MemFunTmpl::staticDef<ExplicitDecl_Imported>) @@ -770,13 +772,13 @@ USE(MemFunTmpl::staticDef<ExplicitDecl_Imported>) // template. // M32-DAG: declare dllimport x86_thiscallcc void @"\01??$normalDef@UExplicitInst_Imported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl*) // M64-DAG: declare dllimport void @"\01??$normalDef@UExplicitInst_Imported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl*) -// G32-DAG: declare dllimport x86_thiscallcc void @_ZN10MemFunTmpl9normalDefI21ExplicitInst_ImportedEEvv(%struct.MemFunTmpl*) -// G64-DAG: declare dllimport void @_ZN10MemFunTmpl9normalDefI21ExplicitInst_ImportedEEvv(%struct.MemFunTmpl*) +// G32-DAG: define weak_odr x86_thiscallcc void @_ZN10MemFunTmpl9normalDefI21ExplicitInst_ImportedEEvv(%struct.MemFunTmpl* %this) +// G64-DAG: define weak_odr void @_ZN10MemFunTmpl9normalDefI21ExplicitInst_ImportedEEvv(%struct.MemFunTmpl* %this) template __declspec(dllimport) void MemFunTmpl::normalDef<ExplicitInst_Imported>(); USEMF(MemFunTmpl, normalDef<ExplicitInst_Imported>) // MSC-DAG: declare dllimport void @"\01??$staticDef@UExplicitInst_Imported@@@MemFunTmpl@@SAXXZ"() -// GNU-DAG: declare dllimport void @_ZN10MemFunTmpl9staticDefI21ExplicitInst_ImportedEEvv() +// GNU-DAG: define weak_odr void @_ZN10MemFunTmpl9staticDefI21ExplicitInst_ImportedEEvv() template __declspec(dllimport) void MemFunTmpl::staticDef<ExplicitInst_Imported>(); USE(MemFunTmpl::staticDef<ExplicitInst_Imported>) @@ -796,10 +798,10 @@ USEMF(MemFunTmpl, normalDef<ExplicitSpec_Imported>) //USEMF(MemFunTmpl, normalDef<ExplicitSpec_Def_Imported>) #endif -// M32-DAG: declare dllimport x86_thiscallcc void @"\01??$normalDef@UExplicitSpec_InlineDef_Imported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl*) -// M64-DAG: declare dllimport void @"\01??$normalDef@UExplicitSpec_InlineDef_Imported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl*) -// G32-DAG: declare dllimport x86_thiscallcc void @_ZN10MemFunTmpl9normalDefI31ExplicitSpec_InlineDef_ImportedEEvv(%struct.MemFunTmpl*) -// G64-DAG: declare dllimport void @_ZN10MemFunTmpl9normalDefI31ExplicitSpec_InlineDef_ImportedEEvv(%struct.MemFunTmpl*) +// M32-DAG: declare dllimport x86_thiscallcc void @"\01??$normalDef@UExplicitSpec_InlineDef_Imported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl*) +// M64-DAG: declare dllimport void @"\01??$normalDef@UExplicitSpec_InlineDef_Imported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl*) +// G32-DAG: define linkonce_odr x86_thiscallcc void @_ZN10MemFunTmpl9normalDefI31ExplicitSpec_InlineDef_ImportedEEvv(%struct.MemFunTmpl* %this) +// G64-DAG: define linkonce_odr void @_ZN10MemFunTmpl9normalDefI31ExplicitSpec_InlineDef_ImportedEEvv(%struct.MemFunTmpl* %this) template<> __declspec(dllimport) inline void MemFunTmpl::normalDef<ExplicitSpec_InlineDef_Imported>() {} USEMF(MemFunTmpl, normalDef<ExplicitSpec_InlineDef_Imported>) @@ -816,7 +818,7 @@ USE(MemFunTmpl::staticDef<ExplicitSpec_Imported>) #endif // MSC-DAG: declare dllimport void @"\01??$staticDef@UExplicitSpec_InlineDef_Imported@@@MemFunTmpl@@SAXXZ"() -// GNU-DAG: declare dllimport void @_ZN10MemFunTmpl9staticDefI31ExplicitSpec_InlineDef_ImportedEEvv() +// GNU-DAG: define linkonce_odr void @_ZN10MemFunTmpl9staticDefI31ExplicitSpec_InlineDef_ImportedEEvv() template<> __declspec(dllimport) inline void MemFunTmpl::staticDef<ExplicitSpec_InlineDef_Imported>() {} USE(MemFunTmpl::staticDef<ExplicitSpec_InlineDef_Imported>) diff --git a/test/CodeGenCXX/dllimport-rtti.cpp b/test/CodeGenCXX/dllimport-rtti.cpp index 7ed7dadfe402..b5a5d543d6e2 100644 --- a/test/CodeGenCXX/dllimport-rtti.cpp +++ b/test/CodeGenCXX/dllimport-rtti.cpp @@ -1,13 +1,17 @@ -// RUN: %clang_cc1 -triple i686-windows-msvc -emit-llvm -std=c++1y -O1 -disable-llvm-optzns -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple i686-windows-msvc -emit-llvm -std=c++1y -O1 -disable-llvm-optzns -o - %s | FileCheck %s --check-prefix=MSVC +// RUN: %clang_cc1 -triple i686-windows-gnu -emit-llvm -std=c++1y -O1 -disable-llvm-optzns -o - %s | FileCheck %s --check-prefix=GNU struct __declspec(dllimport) S { - virtual void f(); + virtual void f() {} } s; -// CHECK-DAG: @"\01??_7S@@6B@" = available_externally dllimport -// CHECK-DAG: @"\01??_R0?AUS@@@8" = linkonce_odr -// CHECK-DAG: @"\01??_R1A@?0A@EA@S@@8" = linkonce_odr -// CHECK-DAG: @"\01??_R2S@@8" = linkonce_odr -// CHECK-DAG: @"\01??_R3S@@8" = linkonce_odr +// MSVC-DAG: @"\01??_7S@@6B@" = available_externally dllimport +// 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 +// MSVC-DAG: @"\01??_R3S@@8" = linkonce_odr + +// GNU-DAG: @_ZTV1S = available_externally dllimport +// GNU-DAG: @_ZTI1S = external dllimport struct U : S { } u; diff --git a/test/CodeGenCXX/dllimport.cpp b/test/CodeGenCXX/dllimport.cpp index 59f8f6361619..e5b9f64dcca6 100644 --- a/test/CodeGenCXX/dllimport.cpp +++ b/test/CodeGenCXX/dllimport.cpp @@ -1,13 +1,13 @@ -// RUN: %clang_cc1 -triple i686-windows-msvc -fno-rtti -emit-llvm -std=c++1y -O0 -o - %s -DMSABI | FileCheck --check-prefix=MSC --check-prefix=M32 %s -// RUN: %clang_cc1 -triple x86_64-windows-msvc -fno-rtti -emit-llvm -std=c++1y -O0 -o - %s -DMSABI | FileCheck --check-prefix=MSC --check-prefix=M64 %s -// RUN: %clang_cc1 -triple i686-windows-gnu -fno-rtti -emit-llvm -std=c++1y -O0 -o - %s | FileCheck --check-prefix=GNU --check-prefix=G32 %s -// RUN: %clang_cc1 -triple x86_64-windows-gnu -fno-rtti -emit-llvm -std=c++1y -O0 -o - %s | FileCheck --check-prefix=GNU --check-prefix=G64 %s -// RUN: %clang_cc1 -triple i686-windows-msvc -fno-rtti -emit-llvm -std=c++1y -O1 -o - %s -DMSABI | FileCheck --check-prefix=MO1 %s -// RUN: %clang_cc1 -triple i686-windows-gnu -fno-rtti -emit-llvm -std=c++1y -O1 -o - %s | FileCheck --check-prefix=GO1 %s +// RUN: %clang_cc1 -triple i686-windows-msvc -fno-rtti -emit-llvm -std=c++1y -O0 -o - %s -DMSABI -w | FileCheck --check-prefix=MSC --check-prefix=M32 %s +// RUN: %clang_cc1 -triple x86_64-windows-msvc -fno-rtti -emit-llvm -std=c++1y -O0 -o - %s -DMSABI -w | FileCheck --check-prefix=MSC --check-prefix=M64 %s +// RUN: %clang_cc1 -triple i686-windows-gnu -fno-rtti -emit-llvm -std=c++1y -O0 -o - %s -w | FileCheck --check-prefix=GNU --check-prefix=G32 %s +// RUN: %clang_cc1 -triple x86_64-windows-gnu -fno-rtti -emit-llvm -std=c++1y -O0 -o - %s -w | FileCheck --check-prefix=GNU --check-prefix=G64 %s +// RUN: %clang_cc1 -triple i686-windows-msvc -fno-rtti -emit-llvm -std=c++1y -O1 -o - %s -DMSABI -w | FileCheck --check-prefix=MO1 %s +// RUN: %clang_cc1 -triple i686-windows-gnu -fno-rtti -emit-llvm -std=c++1y -O1 -o - %s -w | FileCheck --check-prefix=GO1 %s // CHECK-NOT doesn't play nice with CHECK-DAG, so use separate run lines. -// RUN: %clang_cc1 -triple i686-windows-msvc -fno-rtti -emit-llvm -std=c++1y -O0 -o - %s -DMSABI | FileCheck --check-prefix=MSC2 %s -// RUN: %clang_cc1 -triple i686-windows-gnu -fno-rtti -emit-llvm -std=c++1y -O0 -o - %s | FileCheck --check-prefix=GNU2 %s +// RUN: %clang_cc1 -triple i686-windows-msvc -fno-rtti -emit-llvm -std=c++1y -O0 -o - %s -DMSABI -w | FileCheck --check-prefix=MSC2 %s +// RUN: %clang_cc1 -triple i686-windows-gnu -fno-rtti -emit-llvm -std=c++1y -O0 -o - %s -w | FileCheck --check-prefix=GNU2 %s // Helper structs to make templates more expressive. struct ImplicitInst_Imported {}; @@ -95,7 +95,7 @@ inline int __declspec(dllimport) inlineStaticLocalsFunc() { USE(inlineStaticLocalsFunc); // The address of a dllimport global cannot be used in constant initialization. -// M32-DAG: @"\01?arr@?0??initializationFunc@@YAPAHXZ@4QBQAHB" = internal global [1 x i32*] zeroinitializer +// M32-DAG: @"\01?arr@?1??initializationFunc@@YAPAHXZ@4QBQAHB" = internal global [1 x i32*] zeroinitializer // GNU-DAG: @_ZZ18initializationFuncvE3arr = internal global [1 x i32*] zeroinitializer int *initializationFunc() { static int *const arr[] = {&ExternGlobalDecl}; @@ -214,36 +214,36 @@ USE(externC) // Import inline function. // MSC-DAG: declare dllimport void @"\01?inlineFunc@@YAXXZ"() -// GNU-DAG: declare dllimport void @_Z10inlineFuncv() +// GNU-DAG: define linkonce_odr void @_Z10inlineFuncv() // MO1-DAG: define available_externally dllimport void @"\01?inlineFunc@@YAXXZ"() -// GO1-DAG: define available_externally dllimport void @_Z10inlineFuncv() +// GO1-DAG: define linkonce_odr void @_Z10inlineFuncv() __declspec(dllimport) inline void inlineFunc() {} USE(inlineFunc) // MSC-DAG: declare dllimport void @"\01?inlineDecl@@YAXXZ"() -// GNU-DAG: declare dllimport void @_Z10inlineDeclv() +// GNU-DAG: define linkonce_odr void @_Z10inlineDeclv() // MO1-DAG: define available_externally dllimport void @"\01?inlineDecl@@YAXXZ"() -// GO1-DAG: define available_externally dllimport void @_Z10inlineDeclv() +// GO1-DAG: define linkonce_odr void @_Z10inlineDeclv() __declspec(dllimport) inline void inlineDecl(); void inlineDecl() {} USE(inlineDecl) // MSC-DAG: declare dllimport void @"\01?inlineDef@@YAXXZ"() -// GNU-DAG: declare dllimport void @_Z9inlineDefv() +// GNU-DAG: define linkonce_odr void @_Z9inlineDefv() // MO1-DAG: define available_externally dllimport void @"\01?inlineDef@@YAXXZ"() -// GO1-DAG: define available_externally dllimport void @_Z9inlineDefv() +// GO1-DAG: define linkonce_odr void @_Z9inlineDefv() __declspec(dllimport) void inlineDef(); inline void inlineDef() {} USE(inlineDef) // inline attributes // MSC-DAG: declare dllimport void @"\01?noinline@@YAXXZ"() -// GNU-DAG: declare dllimport void @_Z8noinlinev() +// GNU-DAG: define linkonce_odr void @_Z8noinlinev() __declspec(dllimport) __attribute__((noinline)) inline void noinline() {} USE(noinline) // MSC2-NOT: @"\01?alwaysInline@@YAXXZ"() -// GNU2-NOT: @_Z12alwaysInlinev() +// GNU-DAG: define linkonce_odr void @_Z12alwaysInlinev() {{.*}} comdat { __declspec(dllimport) __attribute__((always_inline)) inline void alwaysInline() {} USE(alwaysInline) @@ -276,6 +276,11 @@ USE(redecl3) // GNU-DAG: declare void @_Z7friend2v() // MSC-DAG: define void @"\01?friend3@@YAXXZ"() // GNU-DAG: define void @_Z7friend3v() +// MSC-DAG: declare void @"\01?friend4@@YAXXZ"() +// GNU-DAG: declare void @_Z7friend4v() +// MSC-DAG: declare dllimport void @"\01?friend5@@YAXXZ"() +// GNU-DAG: declare dllimport void @_Z7friend5v() + struct FuncFriend { friend __declspec(dllimport) void friend1(); friend __declspec(dllimport) void friend2(); @@ -284,9 +289,18 @@ struct FuncFriend { __declspec(dllimport) void friend1(); void friend2(); // dllimport ignored void friend3() {} // dllimport ignored + +__declspec(dllimport) void friend4(); +__declspec(dllimport) void friend5(); +struct FuncFriendRedecl { + friend void friend4(); // dllimport ignored + friend void ::friend5(); +}; USE(friend1) USE(friend2) USE(friend3) +USE(friend4) +USE(friend5) // Implicit declarations can be redeclared with dllimport. // MSC-DAG: declare dllimport noalias i8* @"\01??2@{{YAPAXI|YAPEAX_K}}@Z"( @@ -315,31 +329,31 @@ USE(funcTmplDecl<ImplicitInst_Imported>) // Import inline function template. // MSC-DAG: declare dllimport void @"\01??$inlineFuncTmpl1@UImplicitInst_Imported@@@@YAXXZ"() -// GNU-DAG: declare dllimport void @_Z15inlineFuncTmpl1I21ImplicitInst_ImportedEvv() +// GNU-DAG: define linkonce_odr void @_Z15inlineFuncTmpl1I21ImplicitInst_ImportedEvv() // MO1-DAG: define available_externally dllimport void @"\01??$inlineFuncTmpl1@UImplicitInst_Imported@@@@YAXXZ"() -// GO1-DAG: define available_externally dllimport void @_Z15inlineFuncTmpl1I21ImplicitInst_ImportedEvv() +// GO1-DAG: define linkonce_odr void @_Z15inlineFuncTmpl1I21ImplicitInst_ImportedEvv() template<typename T> __declspec(dllimport) inline void inlineFuncTmpl1() {} USE(inlineFuncTmpl1<ImplicitInst_Imported>) // MSC-DAG: declare dllimport void @"\01??$inlineFuncTmpl2@UImplicitInst_Imported@@@@YAXXZ"() -// GNU-DAG: declare dllimport void @_Z15inlineFuncTmpl2I21ImplicitInst_ImportedEvv() +// GNU-DAG: define linkonce_odr void @_Z15inlineFuncTmpl2I21ImplicitInst_ImportedEvv() // MO1-DAG: define available_externally dllimport void @"\01??$inlineFuncTmpl2@UImplicitInst_Imported@@@@YAXXZ"() -// GO1-DAG: define available_externally dllimport void @_Z15inlineFuncTmpl2I21ImplicitInst_ImportedEvv() +// GO1-DAG: define linkonce_odr void @_Z15inlineFuncTmpl2I21ImplicitInst_ImportedEvv() template<typename T> inline void __attribute__((dllimport)) inlineFuncTmpl2() {} USE(inlineFuncTmpl2<ImplicitInst_Imported>) // MSC-DAG: declare dllimport void @"\01??$inlineFuncTmplDecl@UImplicitInst_Imported@@@@YAXXZ"() -// GNU-DAG: declare dllimport void @_Z18inlineFuncTmplDeclI21ImplicitInst_ImportedEvv() +// GNU-DAG: define linkonce_odr void @_Z18inlineFuncTmplDeclI21ImplicitInst_ImportedEvv() // MO1-DAG: define available_externally dllimport void @"\01??$inlineFuncTmplDecl@UImplicitInst_Imported@@@@YAXXZ"() -// GO1-DAG: define available_externally dllimport void @_Z18inlineFuncTmplDeclI21ImplicitInst_ImportedEvv() +// GO1-DAG: define linkonce_odr void @_Z18inlineFuncTmplDeclI21ImplicitInst_ImportedEvv() template<typename T> __declspec(dllimport) inline void inlineFuncTmplDecl(); template<typename T> void inlineFuncTmplDecl() {} USE(inlineFuncTmplDecl<ImplicitInst_Imported>) // MSC-DAG: declare dllimport void @"\01??$inlineFuncTmplDef@UImplicitInst_Imported@@@@YAXXZ"() -// GNU-DAG: declare dllimport void @_Z17inlineFuncTmplDefI21ImplicitInst_ImportedEvv() +// GNU-DAG: define linkonce_odr void @_Z17inlineFuncTmplDefI21ImplicitInst_ImportedEvv() // MO1-DAG: define available_externally dllimport void @"\01??$inlineFuncTmplDef@UImplicitInst_Imported@@@@YAXXZ"() -// GO1-DAG: define available_externally dllimport void @_Z17inlineFuncTmplDefI21ImplicitInst_ImportedEvv() +// GO1-DAG: define linkonce_odr void @_Z17inlineFuncTmplDefI21ImplicitInst_ImportedEvv() template<typename T> __declspec(dllimport) void inlineFuncTmplDef(); template<typename T> inline void inlineFuncTmplDef() {} USE(inlineFuncTmplDef<ImplicitInst_Imported>) @@ -373,7 +387,7 @@ USE(funcTmplRedecl3<ImplicitInst_NotImported>) // MSC-DAG: define linkonce_odr void @"\01??$funcTmplFriend3@UImplicitInst_NotImported@@@@YAXXZ"() // GNU-DAG: define linkonce_odr void @_Z15funcTmplFriend3I24ImplicitInst_NotImportedEvv() // MSC-DAG: declare dllimport void @"\01??$funcTmplFriend4@UImplicitInst_Imported@@@@YAXXZ"() -// GNU-DAG: declare dllimport void @_Z15funcTmplFriend4I21ImplicitInst_ImportedEvv() +// GNU-DAG: define linkonce_odr void @_Z15funcTmplFriend4I21ImplicitInst_ImportedEvv() struct FuncTmplFriend { template<typename T> friend __declspec(dllimport) void funcTmplFriend1(); template<typename T> friend __declspec(dllimport) void funcTmplFriend2(); @@ -406,24 +420,24 @@ template<typename T> __declspec(dllimport) inline void importedFuncTmpl() {} USE(importedFuncTmplDecl<ImplicitInst_Imported>) // MSC-DAG: declare dllimport void @"\01??$importedFuncTmpl@UImplicitInst_Imported@@@@YAXXZ"() -// GNU-DAG: declare dllimport void @_Z16importedFuncTmplI21ImplicitInst_ImportedEvv() +// GNU-DAG: define linkonce_odr void @_Z16importedFuncTmplI21ImplicitInst_ImportedEvv() // MO1-DAG: define available_externally dllimport void @"\01??$importedFuncTmpl@UImplicitInst_Imported@@@@YAXXZ"() -// GO1-DAG: define available_externally dllimport void @_Z16importedFuncTmplI21ImplicitInst_ImportedEvv() +// GO1-DAG: define linkonce_odr void @_Z16importedFuncTmplI21ImplicitInst_ImportedEvv() USE(importedFuncTmpl<ImplicitInst_Imported>) // Import explicit instantiation declaration of an imported function template. // MSC-DAG: declare dllimport void @"\01??$importedFuncTmpl@UExplicitDecl_Imported@@@@YAXXZ"() -// GNU-DAG: declare dllimport void @_Z16importedFuncTmplI21ExplicitDecl_ImportedEvv() +// GNU-DAG: declare void @_Z16importedFuncTmplI21ExplicitDecl_ImportedEvv() // MO1-DAG: define available_externally dllimport void @"\01??$importedFuncTmpl@UExplicitDecl_Imported@@@@YAXXZ"() -// GO1-DAG: define available_externally dllimport void @_Z16importedFuncTmplI21ExplicitDecl_ImportedEvv() +// GO1-DAG: define available_externally void @_Z16importedFuncTmplI21ExplicitDecl_ImportedEvv() extern template void importedFuncTmpl<ExplicitDecl_Imported>(); USE(importedFuncTmpl<ExplicitDecl_Imported>) // Import explicit instantiation definition of an imported function template. // MSC-DAG: declare dllimport void @"\01??$importedFuncTmpl@UExplicitInst_Imported@@@@YAXXZ"() -// GNU-DAG: declare dllimport void @_Z16importedFuncTmplI21ExplicitInst_ImportedEvv() +// GNU-DAG: define weak_odr void @_Z16importedFuncTmplI21ExplicitInst_ImportedEvv() // MO1-DAG: define available_externally dllimport void @"\01??$importedFuncTmpl@UExplicitInst_Imported@@@@YAXXZ"() -// GO1-DAG: define available_externally dllimport void @_Z16importedFuncTmplI21ExplicitInst_ImportedEvv() +// GO1-DAG: define weak_odr void @_Z16importedFuncTmplI21ExplicitInst_ImportedEvv() template void importedFuncTmpl<ExplicitInst_Imported>(); USE(importedFuncTmpl<ExplicitInst_Imported>) @@ -442,9 +456,9 @@ USE(importedFuncTmplDecl<ExplicitSpec_Imported>) #endif // MSC-DAG: declare dllimport void @"\01??$importedFuncTmplDecl@UExplicitSpec_InlineDef_Imported@@@@YAXXZ"() -// GNU-DAG: declare dllimport void @_Z20importedFuncTmplDeclI31ExplicitSpec_InlineDef_ImportedEvv() +// GNU-DAG: define linkonce_odr void @_Z20importedFuncTmplDeclI31ExplicitSpec_InlineDef_ImportedEvv() // MO1-DAG: define available_externally dllimport void @"\01??$importedFuncTmplDecl@UExplicitSpec_InlineDef_Imported@@@@YAXXZ"() -// GO1-DAG: define available_externally dllimport void @_Z20importedFuncTmplDeclI31ExplicitSpec_InlineDef_ImportedEvv() +// GO1-DAG: define linkonce_odr void @_Z20importedFuncTmplDeclI31ExplicitSpec_InlineDef_ImportedEvv() template<> __declspec(dllimport) inline void importedFuncTmplDecl<ExplicitSpec_InlineDef_Imported>() {} USE(importedFuncTmplDecl<ExplicitSpec_InlineDef_Imported>) @@ -462,9 +476,9 @@ USE(importedFuncTmpl<ExplicitSpec_Imported>) #endif // MSC-DAG: declare dllimport void @"\01??$importedFuncTmpl@UExplicitSpec_InlineDef_Imported@@@@YAXXZ"() -// GNU-DAG: declare dllimport void @_Z16importedFuncTmplI31ExplicitSpec_InlineDef_ImportedEvv() +// GNU-DAG: define linkonce_odr void @_Z16importedFuncTmplI31ExplicitSpec_InlineDef_ImportedEvv() // MO1-DAG: define available_externally dllimport void @"\01??$importedFuncTmpl@UExplicitSpec_InlineDef_Imported@@@@YAXXZ"() -// GO1-DAG: define available_externally dllimport void @_Z16importedFuncTmplI31ExplicitSpec_InlineDef_ImportedEvv() +// GO1-DAG: define linkonce_odr void @_Z16importedFuncTmplI31ExplicitSpec_InlineDef_ImportedEvv() template<> __declspec(dllimport) inline void importedFuncTmpl<ExplicitSpec_InlineDef_Imported>() {} USE(importedFuncTmpl<ExplicitSpec_InlineDef_Imported>) @@ -481,9 +495,9 @@ USE(importedFuncTmpl<ExplicitSpec_NotImported>) // MSC-DAG: declare dllimport void @"\01??$funcTmpl@UExplicitDecl_Imported@@@@YAXXZ"() // MSC-DAG: declare dllimport void @"\01??$inlineFuncTmpl@UExplicitDecl_Imported@@@@YAXXZ"() // GNU-DAG: declare dllimport void @_Z8funcTmplI21ExplicitDecl_ImportedEvv() -// GNU-DAG: declare dllimport void @_Z14inlineFuncTmplI21ExplicitDecl_ImportedEvv() +// GNU-DAG: declare void @_Z14inlineFuncTmplI21ExplicitDecl_ImportedEvv() // MO1-DAG: define available_externally dllimport void @"\01??$inlineFuncTmpl@UExplicitDecl_Imported@@@@YAXXZ"() -// GO1-DAG: define available_externally dllimport void @_Z14inlineFuncTmplI21ExplicitDecl_ImportedEvv() +// GO1-DAG: define available_externally void @_Z14inlineFuncTmplI21ExplicitDecl_ImportedEvv() extern template __declspec(dllimport) void funcTmpl<ExplicitDecl_Imported>(); extern template __declspec(dllimport) void inlineFuncTmpl<ExplicitDecl_Imported>(); USE(funcTmpl<ExplicitDecl_Imported>) @@ -494,11 +508,11 @@ USE(inlineFuncTmpl<ExplicitDecl_Imported>) // MSC-DAG: declare dllimport void @"\01??$funcTmpl@UExplicitInst_Imported@@@@YAXXZ"() // MSC-DAG: declare dllimport void @"\01??$inlineFuncTmpl@UExplicitInst_Imported@@@@YAXXZ"() // GNU-DAG: declare dllimport void @_Z8funcTmplI21ExplicitInst_ImportedEvv() -// GNU-DAG: declare dllimport void @_Z14inlineFuncTmplI21ExplicitInst_ImportedEvv() +// GNU-DAG: define weak_odr void @_Z14inlineFuncTmplI21ExplicitInst_ImportedEvv() // MO1-DAG: define available_externally dllimport void @"\01??$funcTmpl@UExplicitInst_Imported@@@@YAXXZ"() // MO1-DAG: define available_externally dllimport void @"\01??$inlineFuncTmpl@UExplicitInst_Imported@@@@YAXXZ"() // GO1-DAG: define available_externally dllimport void @_Z8funcTmplI21ExplicitInst_ImportedEvv() -// GO1-DAG: define available_externally dllimport void @_Z14inlineFuncTmplI21ExplicitInst_ImportedEvv() +// GO1-DAG: define weak_odr void @_Z14inlineFuncTmplI21ExplicitInst_ImportedEvv() template __declspec(dllimport) void funcTmpl<ExplicitInst_Imported>(); template __declspec(dllimport) void inlineFuncTmpl<ExplicitInst_Imported>(); USE(funcTmpl<ExplicitInst_Imported>) @@ -519,9 +533,9 @@ USE(funcTmpl<ExplicitSpec_Imported>) #endif // MSC-DAG: declare dllimport void @"\01??$funcTmpl@UExplicitSpec_InlineDef_Imported@@@@YAXXZ"() -// GNU-DAG: declare dllimport void @_Z8funcTmplI31ExplicitSpec_InlineDef_ImportedEvv() +// GNU-DAG: define linkonce_odr void @_Z8funcTmplI31ExplicitSpec_InlineDef_ImportedEvv() // MO1-DAG: define available_externally dllimport void @"\01??$funcTmpl@UExplicitSpec_InlineDef_Imported@@@@YAXXZ"() -// GO1-DAG: define available_externally dllimport void @_Z8funcTmplI31ExplicitSpec_InlineDef_ImportedEvv() +// GO1-DAG: define linkonce_odr void @_Z8funcTmplI31ExplicitSpec_InlineDef_ImportedEvv() template<> __declspec(dllimport) inline void funcTmpl<ExplicitSpec_InlineDef_Imported>() {} USE(funcTmpl<ExplicitSpec_InlineDef_Imported>) @@ -658,18 +672,56 @@ namespace PR19933 { // MSC-DAG: @"\01?y@?$D@$0CK@@PR19933@@2HA" = available_externally dllimport global i32 0 } +namespace PR21355 { + struct __declspec(dllimport) S { + virtual ~S(); + }; + S::~S() {} + + // S::~S is a key function, so we would ordinarily emit a strong definition for + // the vtable. However, S is imported, so the vtable should be too. + + // GNU-DAG: @_ZTVN7PR213551SE = available_externally dllimport unnamed_addr constant [4 x i8*] +} + +namespace PR21366 { + struct __declspec(dllimport) S { + void outOfLineMethod(); + void inlineMethod() {} + inline void anotherInlineMethod(); + void outOfClassInlineMethod(); + }; + void S::anotherInlineMethod() {} + inline void S::outOfClassInlineMethod() {} +} + // MS ignores DLL attributes on partial specializations. template <typename T> struct PartiallySpecializedClassTemplate {}; -template <typename T> struct __declspec(dllimport) PartiallySpecializedClassTemplate<T*> { void f() {} }; +template <typename T> struct __declspec(dllimport) PartiallySpecializedClassTemplate<T*> { void f(); }; USEMEMFUNC(PartiallySpecializedClassTemplate<void*>, f); -// M32-DAG: define linkonce_odr x86_thiscallcc void @"\01?f@?$PartiallySpecializedClassTemplate@PAX@@QAEXXZ" -// G32-DAG: {{declare|define available_externally}} dllimport x86_thiscallcc void @_ZN33PartiallySpecializedClassTemplateIPvE1fEv +// M32-DAG: declare x86_thiscallcc void @"\01?f@?$PartiallySpecializedClassTemplate@PAX@@QAEXXZ" +// G32-DAG: declare dllimport x86_thiscallcc void @_ZN33PartiallySpecializedClassTemplateIPvE1fEv +// Attributes on explicit specializations are honored. template <typename T> struct ExplicitlySpecializedClassTemplate {}; -template <> struct __declspec(dllimport) ExplicitlySpecializedClassTemplate<void*> { void f() {} }; +template <> struct __declspec(dllimport) ExplicitlySpecializedClassTemplate<void*> { void f(); }; USEMEMFUNC(ExplicitlySpecializedClassTemplate<void*>, f); -// M32-DAG: {{declare|define available_externally}} dllimport x86_thiscallcc void @"\01?f@?$ExplicitlySpecializedClassTemplate@PAX@@QAEXXZ" -// G32-DAG: {{declare|define available_externally}} dllimport x86_thiscallcc void @_ZN34ExplicitlySpecializedClassTemplateIPvE1fEv +// M32-DAG: declare dllimport x86_thiscallcc void @"\01?f@?$ExplicitlySpecializedClassTemplate@PAX@@QAEXXZ" +// G32-DAG: declare dllimport x86_thiscallcc void @_ZN34ExplicitlySpecializedClassTemplateIPvE1fEv + +// MS inherits DLL attributes to partial specializations. +template <typename T> struct __declspec(dllimport) PartiallySpecializedImportedClassTemplate {}; +template <typename T> struct PartiallySpecializedImportedClassTemplate<T*> { void f() {} }; +USEMEMFUNC(PartiallySpecializedImportedClassTemplate<void*>, f); +// M32-DAG: {{declare|define available_externally}} dllimport x86_thiscallcc void @"\01?f@?$PartiallySpecializedImportedClassTemplate@PAX@@QAEXXZ" +// G32-DAG: define linkonce_odr x86_thiscallcc void @_ZN41PartiallySpecializedImportedClassTemplateIPvE1fEv + +// Attributes on the instantiation take precedence over attributes on the template. +template <typename T> struct __declspec(dllexport) ExplicitlyInstantiatedWithDifferentAttr { void f() {} }; +template struct __declspec(dllimport) ExplicitlyInstantiatedWithDifferentAttr<int>; +USEMEMFUNC(ExplicitlyInstantiatedWithDifferentAttr<int>, f); +// M32-DAG: {{declare|define available_externally}} dllimport x86_thiscallcc void @"\01?f@?$ExplicitlyInstantiatedWithDifferentAttr@H@@QAEXXZ" + //===----------------------------------------------------------------------===// // Classes with template base classes @@ -677,20 +729,20 @@ USEMEMFUNC(ExplicitlySpecializedClassTemplate<void*>, f); template <typename T> struct ClassTemplate { void func() {} }; template <typename T> struct __declspec(dllexport) ExportedClassTemplate { void func() {} }; -template <typename T> struct __declspec(dllimport) ImportedClassTemplate { void func() {} }; +template <typename T> struct __declspec(dllimport) ImportedClassTemplate { void func(); }; template <typename T> struct ExplicitlySpecializedTemplate { void func() {} }; template <> struct ExplicitlySpecializedTemplate<int> { void func() {} }; template <typename T> struct ExplicitlyExportSpecializedTemplate { void func() {} }; template <> struct __declspec(dllexport) ExplicitlyExportSpecializedTemplate<int> { void func() {} }; template <typename T> struct ExplicitlyImportSpecializedTemplate { void func() {} }; -template <> struct __declspec(dllimport) ExplicitlyImportSpecializedTemplate<int> { void func() {} }; +template <> struct __declspec(dllimport) ExplicitlyImportSpecializedTemplate<int> { void func(); }; template <typename T> struct ExplicitlyInstantiatedTemplate { void func() {} }; template struct ExplicitlyInstantiatedTemplate<int>; template <typename T> struct ExplicitlyExportInstantiatedTemplate { void func() {} }; template struct __declspec(dllexport) ExplicitlyExportInstantiatedTemplate<int>; -template <typename T> struct ExplicitlyImportInstantiatedTemplate { void func() {} }; +template <typename T> struct ExplicitlyImportInstantiatedTemplate { void func(); }; template struct __declspec(dllimport) ExplicitlyImportInstantiatedTemplate<int>; @@ -703,7 +755,7 @@ USEMEMFUNC(ClassTemplate<int>, func) // ImportedTemplate is explicitly imported. struct __declspec(dllimport) DerivedFromImportedTemplate : public ImportedClassTemplate<int> {}; USEMEMFUNC(ImportedClassTemplate<int>, func) -// M32-DAG: {{declare|define available_externally}} dllimport x86_thiscallcc void @"\01?func@?$ImportedClassTemplate@H@@QAEXXZ" +// M32-DAG: declare dllimport x86_thiscallcc void @"\01?func@?$ImportedClassTemplate@H@@QAEXXZ" // G32-DAG: declare dllimport x86_thiscallcc void @_ZN21ImportedClassTemplateIiE4funcEv // ExportedTemplate is explicitly exported. @@ -741,8 +793,8 @@ USEMEMFUNC(ExplicitlyExportSpecializedTemplate<int>, func) // Base class already specialized with import attribute. struct __declspec(dllimport) DerivedFromExplicitlyImportSpecializedTemplate : public ExplicitlyImportSpecializedTemplate<int> {}; USEMEMFUNC(ExplicitlyImportSpecializedTemplate<int>, func) -// M32-DAG: {{declare|define available_externally}} dllimport x86_thiscallcc void @"\01?func@?$ExplicitlyImportSpecializedTemplate@H@@QAEXXZ" -// G32-DAG: {{declare|define available_externally}} dllimport x86_thiscallcc void @_ZN35ExplicitlyImportSpecializedTemplateIiE4funcEv +// M32-DAG: declare dllimport x86_thiscallcc void @"\01?func@?$ExplicitlyImportSpecializedTemplate@H@@QAEXXZ" +// G32-DAG: declare dllimport x86_thiscallcc void @_ZN35ExplicitlyImportSpecializedTemplateIiE4funcEv // Base class already instantiated without dll attribute. struct __declspec(dllimport) DerivedFromExplicitlyInstantiatedTemplate : public ExplicitlyInstantiatedTemplate<int> {}; @@ -759,8 +811,8 @@ USEMEMFUNC(ExplicitlyExportInstantiatedTemplate<int>, func) // Base class already instantiated with import attribute. struct __declspec(dllimport) DerivedFromExplicitlyImportInstantiatedTemplate : public ExplicitlyImportInstantiatedTemplate<int> {}; USEMEMFUNC(ExplicitlyImportInstantiatedTemplate<int>, func) -// M32-DAG: {{declare|define available_externally}} dllimport x86_thiscallcc void @"\01?func@?$ExplicitlyImportInstantiatedTemplate@H@@QAEXXZ" -// G32-DAG: {{declare|define available_externally}} dllimport x86_thiscallcc void @_ZN36ExplicitlyImportInstantiatedTemplateIiE4funcEv +// M32-DAG: declare dllimport x86_thiscallcc void @"\01?func@?$ExplicitlyImportInstantiatedTemplate@H@@QAEXXZ" +// G32-DAG: declare dllimport x86_thiscallcc void @_ZN36ExplicitlyImportInstantiatedTemplateIiE4funcEv // MS: A dll attribute propagates through multiple levels of instantiation. template <typename T> struct TopClass { void func() {} }; diff --git a/test/CodeGenCXX/duplicate-mangled-name.cpp b/test/CodeGenCXX/duplicate-mangled-name.cpp index 65bfa22ac621..e57012e8c414 100644 --- a/test/CodeGenCXX/duplicate-mangled-name.cpp +++ b/test/CodeGenCXX/duplicate-mangled-name.cpp @@ -4,7 +4,7 @@ class MyClass { static void meth(); }; -void MyClass::meth() { } +void MyClass::meth() { } // expected-note {{previous}} extern "C" { void _ZN7MyClass4methEv() { } // expected-error {{definition with same mangled name as another definition}} } diff --git a/test/CodeGenCXX/explicit-instantiation.cpp b/test/CodeGenCXX/explicit-instantiation.cpp index 5bd06784cfab..6076444c25b0 100644 --- a/test/CodeGenCXX/explicit-instantiation.cpp +++ b/test/CodeGenCXX/explicit-instantiation.cpp @@ -90,6 +90,19 @@ namespace LateInstantiation { // CHECK-OPT: define available_externally i32 @_ZN17LateInstantiation1fIiEEiv( } +namespace PR21718 { +// The linkage of a used constexpr member function can change from linkonce_odr +// to weak_odr after explicit instantiation without errors about defining the +// same function twice. +template <typename T> +struct S { +// CHECK-LABEL: define weak_odr i32 @_ZN7PR217181SIiE1fEv + __attribute__((used)) constexpr int f() { return 0; } +}; +int g() { return S<int>().f(); } +template struct S<int>; +} + // 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 fefb216ea1c0..7852644d2b74 100644 --- a/test/CodeGenCXX/extern-c.cpp +++ b/test/CodeGenCXX/extern-c.cpp @@ -59,10 +59,10 @@ extern "C" { // CHECK-NOT: @unused // CHECK-NOT: @duplicate_internal - // CHECK: @internal_var = alias internal i32* @_Z12internal_var + // CHECK: @internal_var = internal alias i32* @_Z12internal_var // CHECK-NOT: @unused // CHECK-NOT: @duplicate_internal - // CHECK: @internal_fn = alias internal i32 ()* @_Z11internal_fnv + // CHECK: @internal_fn = internal alias i32 ()* @_Z11internal_fnv // CHECK-NOT: @unused // CHECK-NOT: @duplicate_internal } diff --git a/test/CodeGenCXX/field-access-debug-info.cpp b/test/CodeGenCXX/field-access-debug-info.cpp index aed4ee5f3a77..2b5b53dcbd84 100644 --- a/test/CodeGenCXX/field-access-debug-info.cpp +++ b/test/CodeGenCXX/field-access-debug-info.cpp @@ -1,7 +1,7 @@ // RUN: %clang -g -S -emit-llvm %s -o - | FileCheck %s -// CHECK: [ DW_TAG_member ] [p] [{{[^]]*}}] [from int] -// CHECK: [ DW_TAG_member ] [pr] [{{[^]]*}}] [private] [from int] +// CHECK: [ DW_TAG_member ] [p] [{{[^]]*}}] [public] [from int] +// CHECK: [ DW_TAG_member ] [pr] [{{[^]]*}}] [from int] class A { public: diff --git a/test/CodeGenCXX/funcsig.cpp b/test/CodeGenCXX/funcsig.cpp index 684a796c1905..2a6e641aec9c 100644 --- a/test/CodeGenCXX/funcsig.cpp +++ b/test/CodeGenCXX/funcsig.cpp @@ -8,7 +8,7 @@ extern "C" int printf(const char *, ...); void freeFunc(int *, char) { printf("__FUNCSIG__ %s\n\n", __FUNCSIG__); } -// CHECK: private unnamed_addr constant [{{.*}} x i8] c"void __cdecl freeFunc(int *, char)\00" +// CHECK: @"\01??_C@_0CD@KLGMNNL@void?5__cdecl?5freeFunc?$CIint?5?$CK?0?5cha@" = linkonce_odr unnamed_addr constant [{{.*}} x i8] c"void __cdecl freeFunc(int *, char)\00" struct TopLevelClass { void topLevelMethod(int *, char); @@ -16,7 +16,7 @@ struct TopLevelClass { void TopLevelClass::topLevelMethod(int *, char) { printf("__FUNCSIG__ %s\n\n", __FUNCSIG__); } -// CHECK: private unnamed_addr constant [{{.*}} x i8] c"void __thiscall TopLevelClass::topLevelMethod(int *, char)\00" +// CHECK: @"\01??_C@_0DL@OBHNMDP@void?5__thiscall?5TopLevelClass?3?3t@" = linkonce_odr unnamed_addr constant [{{.*}} x i8] c"void __thiscall TopLevelClass::topLevelMethod(int *, char)\00" namespace NS { struct NamespacedClass { @@ -25,5 +25,5 @@ struct NamespacedClass { void NamespacedClass::namespacedMethod(int *, char) { printf("__FUNCSIG__ %s\n\n", __FUNCSIG__); } -// CHECK: private unnamed_addr constant [{{.*}} x i8] c"void __thiscall NS::NamespacedClass::namespacedMethod(int *, char)\00" +// CHECK: @"\01??_C@_0ED@PFDKIEBA@void?5__thiscall?5NS?3?3NamespacedCl@" = linkonce_odr unnamed_addr constant [{{.*}} x i8] c"void __thiscall NS::NamespacedClass::namespacedMethod(int *, char)\00" } diff --git a/test/CodeGenCXX/function-template-specialization.cpp b/test/CodeGenCXX/function-template-specialization.cpp index eb099df14d00..7728f3dc7462 100644 --- a/test/CodeGenCXX/function-template-specialization.cpp +++ b/test/CodeGenCXX/function-template-specialization.cpp @@ -1,4 +1,8 @@ // RUN: %clang_cc1 -emit-llvm -triple %itanium_abi_triple %s -o - | FileCheck %s + +// CHECK-DAG: _ZZN7PR219047GetDataIiEERKibE1i = internal global i32 4 +// CHECK-DAG: _ZZN7PR219047GetDataIiEERKibE1i_0 = internal global i32 2 + template<typename T, typename U> T* next(T* ptr, const U& diff); @@ -24,3 +28,18 @@ void test2(int *iptr, double *dptr, int diff) { // CHECK: _Z4nextIdiEPT_S1_RKT0_ dptr = next(dptr, diff); } + +namespace PR21904 { +template <typename> +const int &GetData(bool); + +template <> +const int &GetData<int>(bool b) { + static int i = 4; + if (b) { + static int i = 2; + return i; + } + return i; +} +} diff --git a/test/CodeGenCXX/globalinit-loc.cpp b/test/CodeGenCXX/globalinit-loc.cpp index eb39aec94d48..583f9c75fa53 100644 --- a/test/CodeGenCXX/globalinit-loc.cpp +++ b/test/CodeGenCXX/globalinit-loc.cpp @@ -6,8 +6,8 @@ // // CHECK: define internal void @_GLOBAL__sub_I_globalinit_loc.cpp // CHECK: !dbg ![[DBG:.*]] -// CHECK: "_GLOBAL__sub_I_globalinit_loc.cpp", i32 0, {{.*}}, i32 0} ; [ DW_TAG_subprogram ] [line 0] [local] [def] -// CHECK: ![[DBG]] = metadata !{i32 0, i32 0, +// CHECK: !"0x2e\00\00\00_GLOBAL__sub_I_globalinit_loc.cpp\000\00{{.*}}\000", {{.*}} ; [ DW_TAG_subprogram ] [line 0] [local] [def] +// CHECK: ![[DBG]] = !MDLocation(line: 0, # 99 "someheader.h" class A { public: diff --git a/test/CodeGenCXX/homogeneous-aggregates.cpp b/test/CodeGenCXX/homogeneous-aggregates.cpp new file mode 100644 index 000000000000..94813f357884 --- /dev/null +++ b/test/CodeGenCXX/homogeneous-aggregates.cpp @@ -0,0 +1,106 @@ +// RUN: %clang_cc1 -triple powerpc64le-unknown-linux-gnu -emit-llvm -o - %s | FileCheck %s --check-prefix=PPC +// RUN: %clang_cc1 -mfloat-abi hard -triple armv7-unknown-linux-gnueabi -emit-llvm -o - %s | FileCheck %s --check-prefix=ARM32 +// RUN: %clang_cc1 -mfloat-abi hard -triple aarch64-unknown-linux-gnu -emit-llvm -o - %s | FileCheck %s --check-prefix=ARM64 +// RUN: %clang_cc1 -mfloat-abi hard -triple x86_64-unknown-windows-gnu -emit-llvm -o - %s | FileCheck %s --check-prefix=X64 + +#if defined(__x86_64__) +#define CC __attribute__((vectorcall)) +#else +#define CC +#endif + +// Test that C++ classes are correctly classified as homogeneous aggregates. + +struct Base1 { + int x; +}; +struct Base2 { + double x; +}; +struct Base3 { + double x; +}; +struct D1 : Base1 { // non-homogeneous aggregate + double y, z; +}; +struct D2 : Base2 { // homogeneous aggregate + double y, z; +}; +struct D3 : Base1, Base2 { // non-homogeneous aggregate + double y, z; +}; +struct D4 : Base2, Base3 { // homogeneous aggregate + double y, z; +}; + +struct I1 : Base2 {}; +struct I2 : Base2 {}; +struct I3 : Base2 {}; +struct D5 : I1, I2, I3 {}; // homogeneous aggregate + +// PPC: define void @_Z7func_D12D1(%struct.D1* noalias sret %agg.result, [3 x i64] %x.coerce) +// ARM32: define arm_aapcs_vfpcc void @_Z7func_D12D1(%struct.D1* noalias sret %agg.result, [3 x i64] %x.coerce) +// ARM64: define void @_Z7func_D12D1(%struct.D1* noalias sret %agg.result, %struct.D1* %x) +// X64: define x86_vectorcallcc void @"\01_Z7func_D12D1@@24"(%struct.D1* noalias sret %agg.result, %struct.D1* %x) +D1 CC func_D1(D1 x) { return x; } + +// PPC: define [3 x double] @_Z7func_D22D2([3 x double] %x.coerce) +// ARM32: define arm_aapcs_vfpcc %struct.D2 @_Z7func_D22D2(%struct.D2 %x.coerce) +// ARM64: define %struct.D2 @_Z7func_D22D2([3 x double] %x.coerce) +// X64: define x86_vectorcallcc %struct.D2 @"\01_Z7func_D22D2@@24"(double %x.0, double %x.1, double %x.2) +D2 CC func_D2(D2 x) { return x; } + +// PPC: define void @_Z7func_D32D3(%struct.D3* noalias sret %agg.result, [4 x i64] %x.coerce) +// ARM32: define arm_aapcs_vfpcc void @_Z7func_D32D3(%struct.D3* noalias sret %agg.result, [4 x i64] %x.coerce) +// ARM64: define void @_Z7func_D32D3(%struct.D3* noalias sret %agg.result, %struct.D3* %x) +D3 CC func_D3(D3 x) { return x; } + +// PPC: define [4 x double] @_Z7func_D42D4([4 x double] %x.coerce) +// ARM32: define arm_aapcs_vfpcc %struct.D4 @_Z7func_D42D4(%struct.D4 %x.coerce) +// ARM64: define %struct.D4 @_Z7func_D42D4([4 x double] %x.coerce) +D4 CC func_D4(D4 x) { return x; } + +D5 CC func_D5(D5 x) { return x; } +// PPC: define [3 x double] @_Z7func_D52D5([3 x double] %x.coerce) +// ARM32: define arm_aapcs_vfpcc %struct.D5 @_Z7func_D52D5(%struct.D5 %x.coerce) + +// The C++ multiple inheritance expansion case is a little more complicated, so +// do some extra checking. +// +// ARM64-LABEL: define %struct.D5 @_Z7func_D52D5([3 x double] %x.coerce) +// ARM64: bitcast %struct.D5* %{{.*}} to [3 x double]* +// ARM64: store [3 x double] %x.coerce, [3 x double]* + +void call_D5(D5 *p) { + func_D5(*p); +} + +// Check the call site. +// +// ARM64-LABEL: define void @_Z7call_D5P2D5(%struct.D5* %p) +// ARM64: load [3 x double]* +// ARM64: call %struct.D5 @_Z7func_D52D5([3 x double] %{{.*}}) + +struct Empty { }; +struct Float1 { float x; }; +struct Float2 { float y; }; +struct HVAWithEmptyBase : Float1, Empty, Float2 { float z; }; + +// PPC: define void @_Z15with_empty_base16HVAWithEmptyBase([3 x float] %a.coerce) +// ARM64: define void @_Z15with_empty_base16HVAWithEmptyBase([3 x float] %a.coerce) +// ARM32: define arm_aapcs_vfpcc void @_Z15with_empty_base16HVAWithEmptyBase(%struct.HVAWithEmptyBase %a.coerce) +void CC with_empty_base(HVAWithEmptyBase a) {} + +// FIXME: MSVC doesn't consider this an HVA becuase of the empty base. +// X64: define x86_vectorcallcc void @"\01_Z15with_empty_base16HVAWithEmptyBase@@16"(float %a.0, float %a.1, float %a.2) + +struct HVAWithEmptyBitField : Float1, Float2 { + int : 0; // Takes no space. + float z; +}; + +// PPC: define void @_Z19with_empty_bitfield20HVAWithEmptyBitField([3 x float] %a.coerce) +// ARM64: define void @_Z19with_empty_bitfield20HVAWithEmptyBitField([3 x float] %a.coerce) +// ARM32: define arm_aapcs_vfpcc void @_Z19with_empty_bitfield20HVAWithEmptyBitField(%struct.HVAWithEmptyBitField %a.coerce) +// X64: define x86_vectorcallcc void @"\01_Z19with_empty_bitfield20HVAWithEmptyBitField@@16"(float %a.0, float %a.1, float %a.2) +void CC with_empty_bitfield(HVAWithEmptyBitField a) {} diff --git a/test/CodeGenCXX/lambda-expressions.cpp b/test/CodeGenCXX/lambda-expressions.cpp index 2f9a4f2d4f55..49b9efbdaba2 100644 --- a/test/CodeGenCXX/lambda-expressions.cpp +++ b/test/CodeGenCXX/lambda-expressions.cpp @@ -81,7 +81,7 @@ int g() { }; // PR14773 -// CHECK: [[ARRVAL:%[0-9a-zA-Z]*]] = load i32* getelementptr inbounds ([0 x i32]* bitcast (<{}>* @_ZZ14staticarrayrefvE5array to [0 x i32]*), i32 0, i64 0), align 4 +// CHECK: [[ARRVAL:%[0-9a-zA-Z]*]] = load i32* getelementptr inbounds ([0 x i32]* @_ZZ14staticarrayrefvE5array, i32 0, i64 0), align 4 // CHECK-NEXT: store i32 [[ARRVAL]] void staticarrayref(){ static int array[] = {}; @@ -91,9 +91,17 @@ void staticarrayref(){ }(); } -// CHECK: define internal void @"_ZZ1hvEN3$_88__invokeEv"(%struct.A* noalias sret %agg.result) {{.*}} { +// CHECK-LABEL: define internal i32* @"_ZZ11PR22071_funvENK3$_8clEv" +// CHECK: ret i32* @PR22071_var +int PR22071_var; +int *PR22071_fun() { + constexpr int &y = PR22071_var; + return [&] { return &y; }(); +} + +// CHECK: define internal void @"_ZZ1hvEN3$_98__invokeEv"(%struct.A* noalias sret %agg.result) {{.*}} { // CHECK-NOT: = -// CHECK: call void @"_ZZ1hvENK3$_8clEv"(%struct.A* sret %agg.result, +// CHECK: call void @"_ZZ1hvENK3$_9clEv"(%struct.A* sret %agg.result, // CHECK-NEXT: ret void struct A { ~A(); }; void h() { diff --git a/test/CodeGenCXX/linetable-cleanup.cpp b/test/CodeGenCXX/linetable-cleanup.cpp index ce7f2c674ba5..3a6aa88d9464 100644 --- a/test/CodeGenCXX/linetable-cleanup.cpp +++ b/test/CodeGenCXX/linetable-cleanup.cpp @@ -24,15 +24,15 @@ int foo() C c; c.i = 42; // This breakpoint should be at/before the cleanup code. - // CHECK: ![[CLEANUP]] = metadata !{i32 [[@LINE+1]], i32 0, metadata !{{.*}}, null} + // CHECK: ![[CLEANUP]] = !MDLocation(line: [[@LINE+1]], scope: !{{.*}}) return 0; - // CHECK: ![[RET]] = metadata !{i32 [[@LINE+1]], i32 0, metadata !{{.*}}, null} + // CHECK: ![[RET]] = !MDLocation(line: [[@LINE+1]], scope: !{{.*}}) } void bar() { if (!foo()) - // CHECK: {{.*}} = metadata !{i32 [[@LINE+1]], i32 0, metadata !{{.*}}, null} + // CHECK: {{.*}} = !MDLocation(line: [[@LINE+1]], scope: !{{.*}}) return; if (foo()) { @@ -40,21 +40,21 @@ void bar() c.i = foo(); } // Clang creates only a single ret instruction. Make sure it is at a useful line. - // CHECK: ![[RETBAR]] = metadata !{i32 [[@LINE+1]], i32 0, metadata !{{.*}}, null} + // CHECK: ![[RETBAR]] = !MDLocation(line: [[@LINE+1]], scope: !{{.*}}) } void baz() { if (!foo()) - // CHECK: ![[SCOPE1:.*]] = metadata !{{{.*}}, i32 [[@LINE-1]], {{.*}}} ; [ DW_TAG_lexical_block ] - // CHECK: {{.*}} = metadata !{i32 [[@LINE+1]], i32 0, metadata ![[SCOPE1]], null} + // CHECK: ![[SCOPE1:.*]] = !{!"0xb\00[[@LINE-1]]\00{{.*}}", {{.*}} ; [ DW_TAG_lexical_block ] + // CHECK: {{.*}} = !MDLocation(line: [[@LINE+1]], scope: ![[SCOPE1]]) return; if (foo()) { // no cleanup - // CHECK: {{.*}} = metadata !{i32 [[@LINE+2]], i32 0, metadata ![[SCOPE2:.*]], null} - // CHECK: ![[SCOPE2]] = metadata !{{{.*}}, i32 [[@LINE-3]], {{.*}}} ; [ DW_TAG_lexical_block ] + // CHECK: {{.*}} = !MDLocation(line: [[@LINE+2]], scope: ![[SCOPE2:.*]]) + // CHECK: ![[SCOPE2]] = !{!"0xb\00[[@LINE-3]]\00{{.*}}", {{.*}} ; [ DW_TAG_lexical_block ] return; } - // CHECK: ![[RETBAZ]] = metadata !{i32 [[@LINE+1]], i32 0, metadata !{{.*}}, null} + // CHECK: ![[RETBAZ]] = !MDLocation(line: [[@LINE+1]], scope: !{{.*}}) } diff --git a/test/CodeGenCXX/linetable-eh.cpp b/test/CodeGenCXX/linetable-eh.cpp index 14a5067cf3ea..6d9b3a968ca6 100644 --- a/test/CodeGenCXX/linetable-eh.cpp +++ b/test/CodeGenCXX/linetable-eh.cpp @@ -4,18 +4,18 @@ // entries for the code that triggered it. // CHECK: call void @llvm.dbg.declare -// CHECK: call void @llvm.dbg.declare(metadata !{{{.*}}}, metadata ![[CURRENT_ADDR:.*]]), !dbg ![[DBG1:.*]] +// CHECK: call void @llvm.dbg.declare(metadata {{.*}}, metadata ![[CURRENT_ADDR:.*]], metadata !{{.*}}), !dbg ![[DBG1:.*]] // CHECK: unwind label %{{.*}}, !dbg ![[DBG1]] // CHECK: store i64 %{{.*}}, i64* %current_address, align 8, !dbg ![[DBG4:.*]] -// CHECK-NEXT: call void @llvm.dbg.declare(metadata !{{{.*}}}, metadata ![[FOUND_IT:.*]]), !dbg ![[DBG2:.*]] +// CHECK-NEXT: call void @llvm.dbg.declare(metadata {{.*}}, metadata ![[FOUND_IT:.*]], metadata !{{.*}}), !dbg ![[DBG2:.*]] // CHECK: = landingpad // CHECK-NEXT: cleanup, !dbg ![[DBG3:.*]] // CHECK-DAG: ![[CURRENT_ADDR]] = {{.*}} [current_address] // CHECK-DAG: ![[FOUND_IT]] = {{.*}} [found_it] -// CHECK-DAG: ![[DBG1]] = metadata !{i32 256, -// CHECK-DAG: ![[DBG2]] = metadata !{i32 257, -// CHECK-DAG: ![[DBG3]] = metadata !{i32 268, -// CHECK-DAG: ![[DBG4]] = metadata !{i32 256, +// CHECK-DAG: ![[DBG1]] = !MDLocation(line: 256, +// CHECK-DAG: ![[DBG2]] = !MDLocation(line: 257, +// CHECK-DAG: ![[DBG3]] = !MDLocation(line: 268, +// CHECK-DAG: ![[DBG4]] = !MDLocation(line: 256, typedef unsigned long long uint64_t; template<class _Tp> class shared_ptr { public: diff --git a/test/CodeGenCXX/linetable-fnbegin.cpp b/test/CodeGenCXX/linetable-fnbegin.cpp index ce46306fed0d..b0a03f7c2067 100644 --- a/test/CodeGenCXX/linetable-fnbegin.cpp +++ b/test/CodeGenCXX/linetable-fnbegin.cpp @@ -4,10 +4,10 @@ // CHECK: define{{.*}}bar // CHECK-NOT: define // CHECK: ret {{.*}}, !dbg [[DBG:.*]] -// CHECK: [[HPP:.*]] = metadata !{metadata !"./template.hpp", -// CHECK: [[SP:.*]] = metadata !{i32 786478, metadata [[HPP]],{{.*}}[ DW_TAG_subprogram ] [line 22] [def] [bar] +// CHECK: [[HPP:.*]] = !{!"./template.hpp", +// CHECK: [[SP:.*]] = !{!"0x2e\00{{.*}}", [[HPP]],{{.*}}[ DW_TAG_subprogram ] [line 22] [def] [bar] // We shouldn't need a lexical block for this function. -// CHECK: [[DBG]] = metadata !{i32 23, i32 0, metadata [[SP]], null} +// CHECK: [[DBG]] = !MDLocation(line: 23, scope: [[SP]]) # 1 "./template.h" 1 diff --git a/test/CodeGenCXX/lpad-linetable.cpp b/test/CodeGenCXX/lpad-linetable.cpp index dba2ad63b2dd..c81191b9fedd 100644 --- a/test/CodeGenCXX/lpad-linetable.cpp +++ b/test/CodeGenCXX/lpad-linetable.cpp @@ -4,7 +4,7 @@ // CHECK: ret i32 // CHECK: landingpad {{.*}} // CHECK-NEXT: !dbg ![[LPAD:[0-9]+]] -// CHECK: ![[LPAD]] = metadata !{i32 24, i32 0, metadata !{{.*}}, null} +// CHECK: ![[LPAD]] = !MDLocation(line: 24, scope: !{{.*}}) # 1 "/usr/include/c++/4.2.1/vector" 1 3 typedef long unsigned int __darwin_size_t; diff --git a/test/CodeGenCXX/mangle-exprs.cpp b/test/CodeGenCXX/mangle-exprs.cpp index e935f51a46b2..ee7f24466b00 100644 --- a/test/CodeGenCXX/mangle-exprs.cpp +++ b/test/CodeGenCXX/mangle-exprs.cpp @@ -56,6 +56,18 @@ namespace Casts { void static_(typename enable_if< O <= static_cast<unsigned>(4) >::type* = 0) { } + template <unsigned O, typename T> + void reinterpret_(typename enable_if<O <= sizeof(reinterpret_cast<T *>(0))>::type * = 0) { + } + + template <typename T, T *p> + void const_(typename enable_if<0 <= sizeof(const_cast<T *>(p))>::type * = 0) { + } + + template <typename T, T *p> + void dynamic_(typename enable_if<0 <= sizeof(dynamic_cast<T *>(p))>::type * = 0) { + } + template< typename T > void auto_(decltype(new auto(T()))) { } @@ -64,11 +76,12 @@ namespace Casts { void scalar_(decltype(T(), int())) { } - // FIXME: Test const_cast, reinterpret_cast, dynamic_cast, which are - // a bit harder to use in template arguments. template <unsigned N> struct T {}; template <int N> T<N> f() { return T<N>(); } + + extern int i; + extern struct S {} s; // CHECK-LABEL: define weak_odr void @_ZN5Casts8implicitILj4EEEvPN9enable_ifIXleT_Li4EEvE4typeE template void implicit<4>(void*); @@ -76,8 +89,14 @@ namespace Casts { template void cstyle<4>(void*); // CHECK-LABEL: define weak_odr void @_ZN5Casts10functionalILj4EEEvPN9enable_ifIXleT_cvjLi4EEvE4typeE template void functional<4>(void*); - // CHECK-LABEL: define weak_odr void @_ZN5Casts7static_ILj4EEEvPN9enable_ifIXleT_cvjLi4EEvE4typeE + // CHECK-LABEL: define weak_odr void @_ZN5Casts7static_ILj4EEEvPN9enable_ifIXleT_scjLi4EEvE4typeE template void static_<4>(void*); + // CHECK-LABEL: define weak_odr void @_ZN5Casts12reinterpret_ILj4EiEEvPN9enable_ifIXleT_szrcPT0_Li0EEvE4typeE + template void reinterpret_<4, int>(void*); + // CHECK-LABEL: define weak_odr void @_ZN5Casts6const_IiXadL_ZNS_1iEEEEEvPN9enable_ifIXleLi0EszccPT_T0_EvE4typeE + template void const_<int, &i>(void*); + // CHECK-LABEL: define weak_odr void @_ZN5Casts8dynamic_INS_1SEXadL_ZNS_1sEEEEEvPN9enable_ifIXleLi0EszdcPT_T0_EvE4typeE + template void dynamic_<struct S, &s>(void*); // CHECK-LABEL: define weak_odr void @_ZN5Casts1fILi6EEENS_1TIXT_EEEv template T<6> f<6>(); @@ -198,3 +217,79 @@ namespace test5 { template void a<int>(decltype(noexcept(int()))); // CHECK: void @_ZN5test51aIiEEvDTnxcvT__EE( } + +namespace test6 { + struct X { + int i; + }; + + struct Y { + union { + int i; + }; + }; + + struct Z { + union { + X ua; + Y ub; + }; + + struct { + X s; + }; + + union { + union { + struct { + struct { + X uuss; + }; + }; + }; + }; + }; + + Z z, *zp; + + template<typename T> + void f1(decltype(T(z.ua.i))) {} + template void f1<int>(int); + // CHECK-LABEL: define weak_odr void @_ZN5test62f1IiEEvDTcvT_dtdtL_ZNS_1zEE2ua1iE + + template<typename T> + void f2(decltype(T(z.ub.i))) {} + template void f2<int>(int); + // CHECK-LABEL: define weak_odr void @_ZN5test62f2IiEEvDTcvT_dtdtL_ZNS_1zEE2ub1iE + + template<typename T> + void f3(decltype(T(z.s.i))) {} + template void f3<int>(int); + // CHECK-LABEL: define weak_odr void @_ZN5test62f3IiEEvDTcvT_dtdtL_ZNS_1zEE1s1iE + + template<typename T> + void f4(decltype(T(z.uuss.i))) {} + template void f4<int>(int); + // CHECK-LABEL: define weak_odr void @_ZN5test62f4IiEEvDTcvT_dtdtL_ZNS_1zEE4uuss1iE + + template<typename T> + void f5(decltype(T(zp->ua.i))) {} + template void f5<int>(int); + // CHECK-LABEL: define weak_odr void @_ZN5test62f5IiEEvDTcvT_dtptL_ZNS_2zpEE2ua1iE + + template<typename T> + void f6(decltype(T(zp->ub.i))) {} + template void f6<int>(int); + // CHECK-LABEL: define weak_odr void @_ZN5test62f6IiEEvDTcvT_dtptL_ZNS_2zpEE2ub1iE + + template<typename T> + void f7(decltype(T(zp->s.i))) {} + template void f7<int>(int); + // CHECK-LABEL: define weak_odr void @_ZN5test62f7IiEEvDTcvT_dtptL_ZNS_2zpEE1s1iE + + template<typename T> + void f8(decltype(T(zp->uuss.i))) {} + template void f8<int>(int); + // CHECK-LABEL: define weak_odr void @_ZN5test62f8IiEEvDTcvT_dtptL_ZNS_2zpEE4uuss1iE +} + diff --git a/test/CodeGenCXX/mangle-literal-suffix.cpp b/test/CodeGenCXX/mangle-literal-suffix.cpp new file mode 100644 index 000000000000..ab557d5a1bfa --- /dev/null +++ b/test/CodeGenCXX/mangle-literal-suffix.cpp @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 -triple mips-none-none -emit-llvm -o - %s | FileCheck %s + +template <class T> void g3(char (&buffer)[sizeof(T() + 5.0)]) {} +template void g3<int>(char (&)[sizeof(double)]); +// CHECK: _Z2g3IiEvRAszplcvT__ELd4014000000000000E_c + +template <class T> void g4(char (&buffer)[sizeof(T() + 5.0L)]) {} +template void g4<int>(char (&)[sizeof(long double)]); +// CHECK: _Z2g4IiEvRAszplcvT__ELe4014000000000000E_c + +template <class T> void g5(char (&buffer)[sizeof(T() + 5)]) {} +template void g5<int>(char (&)[sizeof(int)]); +// CHECK: _Z2g5IiEvRAszplcvT__ELi5E_c + +template <class T> void g6(char (&buffer)[sizeof(T() + 5L)]) {} +template void g6<int>(char (&)[sizeof(long int)]); +// CHECK: _Z2g6IiEvRAszplcvT__ELl5E_c diff --git a/test/CodeGenCXX/mangle-local-anonymous-unions.cpp b/test/CodeGenCXX/mangle-local-anonymous-unions.cpp new file mode 100644 index 000000000000..9187c1a5a27a --- /dev/null +++ b/test/CodeGenCXX/mangle-local-anonymous-unions.cpp @@ -0,0 +1,42 @@ +// RUN: %clang_cc1 %s -emit-llvm -triple %itanium_abi_triple -o - | FileCheck %s + +// CHECK-DAG: @_ZZ2f0vE1a +// CHECK-DAG: @_ZZ2f0vE1c +// CHECK-DAG: @_ZZ2f0vE1e_0 +inline int f0() { + static union { + int a; + long int b; + }; + + static union { + int c; + double d; + }; + + if (0) { + static union { + int e; + int f; + }; + } + static union { + int e; + int f; + }; + + return a+c; +} + +inline void nop() { + static union { + union { + }; + }; +} + +int f1 (int a, int c) { + nop(); + return a+c+f0(); +} + diff --git a/test/CodeGenCXX/mangle-ms-cxx11.cpp b/test/CodeGenCXX/mangle-ms-cxx11.cpp index 373d2b7b957f..fe7121ef24dc 100644 --- a/test/CodeGenCXX/mangle-ms-cxx11.cpp +++ b/test/CodeGenCXX/mangle-ms-cxx11.cpp @@ -1,8 +1,67 @@ // RUN: %clang_cc1 -std=c++11 -fms-extensions -emit-llvm %s -o - -triple=i386-pc-win32 | FileCheck %s +namespace FTypeWithQuals { +template <typename T> +struct S {}; + +using A = int () const; +S<A> a; +// CHECK-DAG: @"\01?a@FTypeWithQuals@@3U?$S@$$A8@@BAHXZ@1@A" + +using B = int () volatile; +S<B> b; +// CHECK-DAG: @"\01?b@FTypeWithQuals@@3U?$S@$$A8@@CAHXZ@1@A" + +using C = int () __restrict; +S<C> c; +// CHECK-DAG: @"\01?c@FTypeWithQuals@@3U?$S@$$A8@@IAAHXZ@1@A" + +using D = int () const &; +S<D> d; +// CHECK-DAG: @"\01?d@FTypeWithQuals@@3U?$S@$$A8@@GBAHXZ@1@A" + +using E = int () volatile &; +S<E> e; +// CHECK-DAG: @"\01?e@FTypeWithQuals@@3U?$S@$$A8@@GCAHXZ@1@A" + +using F = int () __restrict &; +S<F> f; +// CHECK-DAG: @"\01?f@FTypeWithQuals@@3U?$S@$$A8@@IGAAHXZ@1@A" + +using G = int () const &&; +S<G> g; +// CHECK-DAG: @"\01?g@FTypeWithQuals@@3U?$S@$$A8@@HBAHXZ@1@A" + +using H = int () volatile &&; +S<H> h; +// CHECK-DAG: @"\01?h@FTypeWithQuals@@3U?$S@$$A8@@HCAHXZ@1@A" + +using I = int () __restrict &&; +S<I> i; +// CHECK-DAG: @"\01?i@FTypeWithQuals@@3U?$S@$$A8@@IHAAHXZ@1@A" + +using J = int (); +S<J> j; +// CHECK-DAG: @"\01?j@FTypeWithQuals@@3U?$S@$$A6AHXZ@1@A" + +using K = int () &; +S<K> k; +// CHECK-DAG: @"\01?k@FTypeWithQuals@@3U?$S@$$A8@@GAAHXZ@1@A" + +using L = int () &&; +S<L> l; +// CHECK-DAG: @"\01?l@FTypeWithQuals@@3U?$S@$$A8@@HAAHXZ@1@A" +} + // CHECK: "\01?DeducedType@@3HA" auto DeducedType = 30; +// CHECK-DAG: @"\01?Char16Var@@3_SA" +char16_t Char16Var; + +// CHECK-DAG: @"\01?Char32Var@@3_UA" +char32_t Char32Var; + // CHECK: "\01?LRef@@YAXAAH@Z" void LRef(int& a) { } @@ -98,7 +157,7 @@ namespace PR18022 { struct { } a; decltype(a) fun(decltype(a) x, decltype(a)) { return x; } -// CHECK-DAG: ?fun@PR18022@@YA?AU<unnamed-type-a>@1@U21@0@Z +// CHECK-DAG: @"\01?fun@PR18022@@YA?AU<unnamed-type-a>@1@U21@0@Z" } @@ -106,17 +165,32 @@ 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: ?lambda@?1??define_lambda@@YAHXZ@4V<lambda_1>@@A +// CHECK-DAG: @"\01?lambda@?1??define_lambda@@YAHXZ@4V<lambda_1>@?1@YAHXZ@A" // Next, we have the "operator()" for "<lambda_1>" which is inside of // "define_lambda". -// CHECK-DAG: ??R<lambda_1>@?define_lambda@@YAHXZ@QBEHXZ +// CHECK-DAG: @"\01??R<lambda_1>@?define_lambda@@YAHXZ@QBEHXZ" // Finally, we have the local which is inside of "<lambda_1>" which is inside of // "define_lambda". Hooray. -// CHECK-DAG: ?local@?2???R<lambda_1>@?define_lambda@@YAHXZ@QBEHXZ@4HA +// CHECK-DAG: @"\01?local@?2???R<lambda_1>@?define_lambda@@YAHXZ@QBEHXZ@4HA" return lambda(); } +template <typename T> +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" +} + +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" +} + int call_lambda() { + call_with_lambda_arg1(); + call_with_lambda_arg2(); return define_lambda(); } @@ -139,3 +213,29 @@ void templ_fun_with_pack() {} template void templ_fun_with_pack<>(); // CHECK-DAG: @"\01??$templ_fun_with_pack@$S@@YAXXZ" + +template <typename...> +void templ_fun_with_ty_pack() {} + +template void templ_fun_with_ty_pack<>(); +// CHECK-DAG: @"\01??$templ_fun_with_ty_pack@$$V@@YAXXZ" + +template <template <class> class...> +void templ_fun_with_templ_templ_pack() {} + +template void templ_fun_with_templ_templ_pack<>(); +// CHECK-DAG: @"\01??$templ_fun_with_templ_templ_pack@$$V@@YAXXZ" + +namespace PR20047 { +template <typename T> +struct A {}; + +template <typename T> +using AliasA = A<T>; + +template <template <typename> class> +void f() {} + +template void f<AliasA>(); +// CHECK-DAG: @"\01??$f@$$YAliasA@PR20047@@@PR20047@@YAXXZ" +} diff --git a/test/CodeGenCXX/mangle-ms-cxx14.cpp b/test/CodeGenCXX/mangle-ms-cxx14.cpp index 03995611d252..c06efe2edee9 100644 --- a/test/CodeGenCXX/mangle-ms-cxx14.cpp +++ b/test/CodeGenCXX/mangle-ms-cxx14.cpp @@ -13,7 +13,7 @@ auto FunctionWithLocalType() { return LocalType{}; } -// CHECK: "\01?ValueFromFunctionWithLocalType@@3ULocalType@?0??FunctionWithLocalType@@YA?A?<auto>@@XZ@A" +// CHECK: "\01?ValueFromFunctionWithLocalType@@3ULocalType@?1??FunctionWithLocalType@@YA?A?<auto>@@XZ@A" auto ValueFromFunctionWithLocalType = FunctionWithLocalType(); // CHECK: "\01??R<lambda_0>@@QBE?A?<auto>@@XZ" @@ -22,7 +22,7 @@ auto LambdaWithLocalType = [] { return LocalType{}; }; -// CHECK: "\01?ValueFromLambdaWithLocalType@@3ULocalType@?0???R<lambda_0>@@QBE?A?<auto>@@XZ@A" +// CHECK: "\01?ValueFromLambdaWithLocalType@@3ULocalType@?1???R<lambda_0>@@QBE?A?<auto>@@XZ@A" auto ValueFromLambdaWithLocalType = LambdaWithLocalType(); template <typename T> diff --git a/test/CodeGenCXX/mangle-ms-string-literals.cpp b/test/CodeGenCXX/mangle-ms-string-literals.cpp index a77a04f71e0a..e5ebc086e148 100644 --- a/test/CodeGenCXX/mangle-ms-string-literals.cpp +++ b/test/CodeGenCXX/mangle-ms-string-literals.cpp @@ -719,3 +719,9 @@ const wchar_t *LongWideString = L"012345678901234567890123456789ABCDEF"; // CHECK: @"\01??_C@_1EK@KFPEBLPK@?$AA0?$AA1?$AA2?$AA3?$AA4?$AA5?$AA6?$AA7?$AA8?$AA9?$AA0?$AA1?$AA2?$AA3?$AA4?$AA5?$AA6?$AA7?$AA8?$AA9?$AA0?$AA1?$AA2?$AA3?$AA4?$AA5?$AA6?$AA7?$AA8?$AA9?$AAA?$AAB@" const wchar_t *UnicodeLiteral = L"\ud7ff"; // CHECK: @"\01??_C@_13IIHIAFKH@?W?$PP?$AA?$AA@" +const char *U8Literal = u8"hi"; +// CHECK: @"\01??_C@_02PCEFGMJL@hi?$AA@" +const char16_t *U16Literal = u"hi"; +// CHECK: @"\01??_C@_05OMLEGLOC@h?$AAi?$AA?$AA?$AA@" +const char32_t *U32Literal = U"hi"; +// CHECK: @"\01??_C@_0M@GFNAJIPG@h?$AA?$AA?$AAi?$AA?$AA?$AA?$AA?$AA?$AA?$AA@" diff --git a/test/CodeGenCXX/mangle-ms-templates.cpp b/test/CodeGenCXX/mangle-ms-templates.cpp index 31fda2046c4b..46ab251af14f 100644 --- a/test/CodeGenCXX/mangle-ms-templates.cpp +++ b/test/CodeGenCXX/mangle-ms-templates.cpp @@ -24,6 +24,12 @@ class IntTemplate { IntTemplate() {} }; +template<unsigned param> +class UnsignedIntTemplate { +public: + UnsignedIntTemplate() {} +}; + template<long long param> class LongLongTemplate { public: @@ -133,6 +139,10 @@ void template_mangling() { IntTemplate<-11> neg_11; // CHECK: call {{.*}} @"\01??0?$IntTemplate@$0?L@@@QAE@XZ" // X64: call {{.*}} @"\01??0?$IntTemplate@$0?L@@@QEAA@XZ" + + UnsignedIntTemplate<4294967295> ffffffff; +// CHECK: call {{.*}} @"\01??0?$UnsignedIntTemplate@$0PPPPPPPP@@@QAE@XZ" +// X64: call {{.*}} @"\01??0?$UnsignedIntTemplate@$0PPPPPPPP@@@QEAA@XZ" LongLongTemplate<-9223372036854775807LL-1LL> int64_min; // CHECK: call {{.*}} @"\01??0?$LongLongTemplate@$0?IAAAAAAAAAAAAAAA@@@QAE@XZ" diff --git a/test/CodeGenCXX/mangle-ms.cpp b/test/CodeGenCXX/mangle-ms.cpp index 3285c98546ec..662278b3034f 100644 --- a/test/CodeGenCXX/mangle-ms.cpp +++ b/test/CodeGenCXX/mangle-ms.cpp @@ -117,6 +117,19 @@ const volatile char foo2::*k; int (foo2::*l)(int); // CHECK-DAG: @"\01?l@@3P8foo@@AEHH@ZQ1@" +// Ensure typedef CV qualifiers are mangled correctly +typedef const int cInt; +typedef volatile int vInt; +typedef const volatile int cvInt; + +extern cInt g_cInt = 1; +vInt g_vInt = 2; +cvInt g_cvInt = 3; + +// CHECK-DAG: @"\01?g_cInt@@3HB" +// CHECK-DAG: @"\01?g_vInt@@3HC" +// CHECK-DAG: @"\01?g_cvInt@@3HD" + // Static functions are mangled, too. // Also make sure calling conventions, arglists, and throw specs work. static void __stdcall alpha(float a, double b) throw() {} @@ -365,3 +378,5 @@ void TypedefNewDelete::operator delete[](void *) { } // CHECK-DAG: ??3TypedefNewDelete@@SAXPAX@Z // CHECK-DAG: ??_VTypedefNewDelete@@SAXPAX@Z +void __vectorcall vector_func() { } +// CHECK-DAG: @"\01?vector_func@@YQXXZ" diff --git a/test/CodeGenCXX/mangle.cpp b/test/CodeGenCXX/mangle.cpp index 9bdac7f17289..9af0d9da9976 100644 --- a/test/CodeGenCXX/mangle.cpp +++ b/test/CodeGenCXX/mangle.cpp @@ -991,3 +991,25 @@ namespace test48 { template void f<S>(S::u *); // CHECK-LABEL: define weak_odr void @_ZN6test481fINS_1SEEEvPTuNT_1uE(%"union.test48::S::u"*) } + +namespace test49 { + template <int> + struct S {}; + + template <template <int> class T> + T<3> fin(T<3>); + + auto v = fin<S>; + // CHECK-LABEL: declare void @_ZN6test493finINS_1SEEET_ILi3EES3_() +} + +namespace test50 { + template <int> + struct S {}; + + template <template <int> class T> + T<3> fin(T<4>); + + auto v = fin<S>; + // CHECK-LABEL: declare void @_ZN6test503finINS_1SEEET_ILi3EES2_ILi4EE() +} diff --git a/test/CodeGenCXX/merge-functions.cpp b/test/CodeGenCXX/merge-functions.cpp new file mode 100644 index 000000000000..2137f19c409c --- /dev/null +++ b/test/CodeGenCXX/merge-functions.cpp @@ -0,0 +1,14 @@ +// REQUIRES: x86-registered-target +// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -O1 -fmerge-functions -emit-llvm -o - -x c++ < %s | FileCheck %s + +// Basic functionality test. Function merging doesn't kick in on functions that +// are too simple. + +struct A { + virtual int f(int x, int *p) { return x ? *p : 1; } + virtual int g(int x, int *p) { return x ? *p : 1; } +} a; + +// CHECK: define {{.*}} @_ZN1A1gEiPi +// CHECK-NEXT: tail call i32 @_ZN1A1fEiPi +// CHECK-NEXT: ret diff --git a/test/CodeGenCXX/microsoft-abi-byval-sret.cpp b/test/CodeGenCXX/microsoft-abi-byval-sret.cpp index 985b1ce62e92..a34a2455c36f 100644 --- a/test/CodeGenCXX/microsoft-abi-byval-sret.cpp +++ b/test/CodeGenCXX/microsoft-abi-byval-sret.cpp @@ -5,25 +5,66 @@ struct A { A(const A &o) : a(o.a) {} ~A() {} int a; +}; + +struct B { A foo(A o); + A __cdecl bar(A o); + A __stdcall baz(A o); + A __fastcall qux(A o); }; -A A::foo(A x) { - A y(*this); - y.a += x.a; - return y; +A B::foo(A x) { + return x; } -// CHECK-LABEL: define x86_thiscallcc %struct.A* @"\01?foo@A@@QAE?AU1@U1@@Z" -// CHECK: (%struct.A* %this, <{ %struct.A*, %struct.A }>* inalloca) +// CHECK-LABEL: define x86_thiscallcc %struct.A* @"\01?foo@B@@QAE?AUA@@U2@@Z" +// CHECK: (%struct.B* %this, <{ %struct.A*, %struct.A }>* inalloca) // CHECK: getelementptr inbounds <{ %struct.A*, %struct.A }>* %{{.*}}, i32 0, i32 0 // CHECK: load %struct.A** // CHECK: ret %struct.A* +A B::bar(A x) { + return x; +} + +// CHECK-LABEL: define %struct.A* @"\01?bar@B@@QAA?AUA@@U2@@Z" +// CHECK: (<{ %struct.B*, %struct.A*, %struct.A }>* inalloca) +// CHECK: getelementptr inbounds <{ %struct.B*, %struct.A*, %struct.A }>* %{{.*}}, i32 0, i32 1 +// CHECK: load %struct.A** +// CHECK: ret %struct.A* + +A B::baz(A x) { + return x; +} + +// CHECK-LABEL: define x86_stdcallcc %struct.A* @"\01?baz@B@@QAG?AUA@@U2@@Z" +// CHECK: (<{ %struct.B*, %struct.A*, %struct.A }>* inalloca) +// CHECK: getelementptr inbounds <{ %struct.B*, %struct.A*, %struct.A }>* %{{.*}}, i32 0, i32 1 +// CHECK: load %struct.A** +// CHECK: ret %struct.A* + +A B::qux(A x) { + return x; +} + +// CHECK-LABEL: define x86_fastcallcc void @"\01?qux@B@@QAI?AUA@@U2@@Z" +// CHECK: (%struct.B* inreg %this, %struct.A* inreg noalias sret %agg.result, <{ %struct.A }>* inalloca) +// CHECK: ret void + int main() { - A x; - A y = x.foo(x); + B b; + A a = b.foo(A()); + a = b.bar(a); + a = b.baz(a); + a = b.qux(a); } -// CHECK: call x86_thiscallcc %struct.A* @"\01?foo@A@@QAE?AU1@U1@@Z" -// CHECK: (%struct.A* %{{[^,]*}}, <{ %struct.A*, %struct.A }>* inalloca %{{[^,]*}}) +// CHECK: call x86_thiscallcc %struct.A* @"\01?foo@B@@QAE?AUA@@U2@@Z" +// CHECK: (%struct.B* %{{[^,]*}}, <{ %struct.A*, %struct.A }>* inalloca %{{[^,]*}}) +// CHECK: call %struct.A* @"\01?bar@B@@QAA?AUA@@U2@@Z" +// CHECK: (<{ %struct.B*, %struct.A*, %struct.A }>* inalloca %{{[^,]*}}) +// CHECK: call x86_stdcallcc %struct.A* @"\01?baz@B@@QAG?AUA@@U2@@Z" +// CHECK: (<{ %struct.B*, %struct.A*, %struct.A }>* inalloca %{{[^,]*}}) +// CHECK: call x86_fastcallcc void @"\01?qux@B@@QAI?AUA@@U2@@Z" +// CHECK: (%struct.B* inreg %{{[^,]*}}, %struct.A* inreg sret %{{.*}}, <{ %struct.A }>* inalloca %{{[^,]*}}) diff --git a/test/CodeGenCXX/microsoft-abi-byval-thunks.cpp b/test/CodeGenCXX/microsoft-abi-byval-thunks.cpp new file mode 100644 index 000000000000..9bcfb9c184e5 --- /dev/null +++ b/test/CodeGenCXX/microsoft-abi-byval-thunks.cpp @@ -0,0 +1,113 @@ +// RUN: %clang_cc1 %s -fno-rtti -triple=i686-pc-win32 -emit-llvm -o - | FileCheck --check-prefix=CHECK32 %s +// RUN: %clang_cc1 %s -fno-rtti -triple=x86_64-pc-win32 -emit-llvm -o - | FileCheck --check-prefix=CHECK64 %s + +namespace byval_thunk { +struct Agg { + Agg(); + Agg(const Agg &); + ~Agg(); + int x; +}; + +struct A { virtual void foo(Agg x); }; +struct B { virtual void foo(Agg x); }; +struct C : A, B { C(); virtual void foo(Agg x); }; +C::C() {} // force emission + +// CHECK32-LABEL: define linkonce_odr x86_thiscallcc void @"\01?foo@C@byval_thunk@@W3AEXUAgg@2@@Z" +// CHECK32: (%"struct.byval_thunk::C"* %this, <{ %"struct.byval_thunk::Agg" }>* inalloca) +// CHECK32: getelementptr i8* %{{.*}}, i32 -4 +// CHECK32: musttail call x86_thiscallcc void @"\01?foo@C@byval_thunk@@UAEXUAgg@2@@Z" +// CHECK32: (%"struct.byval_thunk::C"* %{{.*}}, <{ %"struct.byval_thunk::Agg" }>* inalloca %0) +// CHECK32-NEXT: ret void + +// CHECK64-LABEL: define linkonce_odr void @"\01?foo@C@byval_thunk@@W7EAAXUAgg@2@@Z" +// CHECK64: (%"struct.byval_thunk::C"* %this, %"struct.byval_thunk::Agg"* %x) +// CHECK64: getelementptr i8* %{{.*}}, i32 -8 +// CHECK64: call void @"\01?foo@C@byval_thunk@@UEAAXUAgg@2@@Z" +// CHECK64: (%"struct.byval_thunk::C"* %{{.*}}, %"struct.byval_thunk::Agg"* %x) +// CHECK64-NOT: call +// CHECK64: ret void +} + +namespace stdcall_thunk { +struct Agg { + Agg(); + Agg(const Agg &); + ~Agg(); + int x; +}; + +struct A { virtual void __stdcall foo(Agg x); }; +struct B { virtual void __stdcall foo(Agg x); }; +struct C : A, B { C(); virtual void __stdcall foo(Agg x); }; +C::C() {} // force emission + +// CHECK32-LABEL: define linkonce_odr x86_stdcallcc void @"\01?foo@C@stdcall_thunk@@W3AGXUAgg@2@@Z" +// CHECK32: (<{ %"struct.stdcall_thunk::C"*, %"struct.stdcall_thunk::Agg" }>* inalloca) +// CHECK32: %[[this_slot:[^ ]*]] = getelementptr inbounds <{ %"struct.stdcall_thunk::C"*, %"struct.stdcall_thunk::Agg" }>* %0, i32 0, i32 0 +// CHECK32: load %"struct.stdcall_thunk::C"** %[[this_slot]] +// CHECK32: getelementptr i8* %{{.*}}, i32 -4 +// CHECK32: store %"struct.stdcall_thunk::C"* %{{.*}}, %"struct.stdcall_thunk::C"** %[[this_slot]] +// CHECK32: musttail call x86_stdcallcc void @"\01?foo@C@stdcall_thunk@@UAGXUAgg@2@@Z" +// CHECK32: (<{ %"struct.stdcall_thunk::C"*, %"struct.stdcall_thunk::Agg" }>* inalloca %0) +// CHECK32-NEXT: ret void + +// CHECK64-LABEL: define linkonce_odr void @"\01?foo@C@stdcall_thunk@@W7EAAXUAgg@2@@Z" +// CHECK64: (%"struct.stdcall_thunk::C"* %this, %"struct.stdcall_thunk::Agg"* %x) +// CHECK64: getelementptr i8* %{{.*}}, i32 -8 +// CHECK64: call void @"\01?foo@C@stdcall_thunk@@UEAAXUAgg@2@@Z" +// CHECK64: (%"struct.stdcall_thunk::C"* %{{.*}}, %"struct.stdcall_thunk::Agg"* %x) +// CHECK64-NOT: call +// CHECK64: ret void +} + +namespace sret_thunk { +struct Agg { + Agg(); + Agg(const Agg &); + ~Agg(); + int x; +}; + +struct A { virtual Agg __cdecl foo(Agg x); }; +struct B { virtual Agg __cdecl foo(Agg x); }; +struct C : A, B { C(); virtual Agg __cdecl foo(Agg x); }; +C::C() {} // force emission + +// CHECK32-LABEL: define linkonce_odr %"struct.sret_thunk::Agg"* @"\01?foo@C@sret_thunk@@W3AA?AUAgg@2@U32@@Z" +// CHECK32: (<{ %"struct.sret_thunk::C"*, %"struct.sret_thunk::Agg"*, %"struct.sret_thunk::Agg" }>* inalloca) +// CHECK32: %[[this_slot:[^ ]*]] = getelementptr inbounds <{ %"struct.sret_thunk::C"*, %"struct.sret_thunk::Agg"*, %"struct.sret_thunk::Agg" }>* %0, i32 0, i32 0 +// CHECK32: load %"struct.sret_thunk::C"** %[[this_slot]] +// CHECK32: getelementptr i8* %{{.*}}, i32 -4 +// CHECK32: store %"struct.sret_thunk::C"* %{{.*}}, %"struct.sret_thunk::C"** %[[this_slot]] +// CHECK32: %[[rv:[^ ]*]] = musttail call %"struct.sret_thunk::Agg"* @"\01?foo@C@sret_thunk@@UAA?AUAgg@2@U32@@Z" +// CHECK32: (<{ %"struct.sret_thunk::C"*, %"struct.sret_thunk::Agg"*, %"struct.sret_thunk::Agg" }>* inalloca %0) +// CHECK32-NEXT: ret %"struct.sret_thunk::Agg"* %[[rv]] + +// CHECK64-LABEL: define linkonce_odr void @"\01?foo@C@sret_thunk@@W7EAA?AUAgg@2@U32@@Z" +// CHECK64: (%"struct.sret_thunk::C"* %this, %"struct.sret_thunk::Agg"* noalias sret %agg.result, %"struct.sret_thunk::Agg"* %x) +// CHECK64: getelementptr i8* %{{.*}}, i32 -8 +// CHECK64: call void @"\01?foo@C@sret_thunk@@UEAA?AUAgg@2@U32@@Z" +// CHECK64: (%"struct.sret_thunk::C"* %{{.*}}, %"struct.sret_thunk::Agg"* sret %agg.result, %"struct.sret_thunk::Agg"* %x) +// CHECK64-NOT: call +// CHECK64: ret void +} + +#if 0 +// FIXME: When we extend LLVM IR to allow forwarding of varargs through musttail +// calls, use this test. +namespace variadic_thunk { +struct Agg { + Agg(); + Agg(const Agg &); + ~Agg(); + int x; +}; + +struct A { virtual void foo(Agg x, ...); }; +struct B { virtual void foo(Agg x, ...); }; +struct C : A, B { C(); virtual void foo(Agg x, ...); }; +C::C() {} // force emission +} +#endif diff --git a/test/CodeGenCXX/microsoft-abi-dynamic-cast.cpp b/test/CodeGenCXX/microsoft-abi-dynamic-cast.cpp index 225407b7fa9c..f2e9da7cca1f 100644 --- a/test/CodeGenCXX/microsoft-abi-dynamic-cast.cpp +++ b/test/CodeGenCXX/microsoft-abi-dynamic-cast.cpp @@ -20,11 +20,10 @@ T* test1(V* x) { return &dynamic_cast<T&>(*x); } T* test2(A* x) { return &dynamic_cast<T&>(*x); } // CHECK-LABEL: define %struct.T* @"\01?test2@@YAPAUT@@PAUA@@@Z"(%struct.A* %x) // CHECK: [[CAST:%.*]] = bitcast %struct.A* %x to i8* -// CHECK-NEXT: [[BITCAST:%.*]] = bitcast %struct.A* %x to i8** -// CHECK-NEXT: [[VBTBL:%.*]] = load i8** [[BITCAST]], align 4 -// CHECK-NEXT: [[VBOFFP:%.*]] = getelementptr inbounds i8* [[VBTBL]], i32 4 -// CHECK-NEXT: [[VBOFFPCAST:%.*]] = bitcast i8* [[VBOFFP]] to i32* -// CHECK-NEXT: [[VBOFFS:%.*]] = load i32* [[VBOFFPCAST]], align 4 +// CHECK-NEXT: [[VBPTRPTR:%.*]] = getelementptr inbounds %struct.A* %x, i32 0, i32 0 +// CHECK-NEXT: [[VBTBL:%.*]] = load i32** [[VBPTRPTR]], align 4 +// CHECK-NEXT: [[VBOFFP:%.*]] = getelementptr inbounds i32* [[VBTBL]], i32 1 +// CHECK-NEXT: [[VBOFFS:%.*]] = load i32* [[VBOFFP]], align 4 // CHECK-NEXT: [[ADJ:%.*]] = getelementptr inbounds i8* [[CAST]], i32 [[VBOFFS]] // 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 1) // CHECK-NEXT: [[RET:%.*]] = bitcast i8* [[CALL]] to %struct.T* @@ -34,11 +33,10 @@ T* test3(B* x) { return &dynamic_cast<T&>(*x); } // CHECK-LABEL: define %struct.T* @"\01?test3@@YAPAUT@@PAUB@@@Z"(%struct.B* %x) // CHECK: [[VOIDP:%.*]] = getelementptr inbounds %struct.B* %x, i32 0, i32 0, i32 0 // CHECK-NEXT: [[VBPTR:%.*]] = getelementptr inbounds i8* [[VOIDP]], i32 4 -// CHECK-NEXT: [[BITCAST:%.*]] = bitcast i8* [[VBPTR:%.*]] to i8** -// CHECK-NEXT: [[VBTBL:%.*]] = load i8** [[BITCAST]], align 4 -// CHECK-NEXT: [[VBOFFP:%.*]] = getelementptr inbounds i8* [[VBTBL]], i32 4 -// CHECK-NEXT: [[VBOFFPCAST:%.*]] = bitcast i8* [[VBOFFP]] to i32* -// CHECK-NEXT: [[VBOFFS:%.*]] = load i32* [[VBOFFPCAST]], align 4 +// CHECK-NEXT: [[VBPTRPTR:%.*]] = bitcast i8* [[VBPTR:%.*]] to i32** +// CHECK-NEXT: [[VBTBL:%.*]] = load i32** [[VBPTRPTR]], align 4 +// CHECK-NEXT: [[VBOFFP:%.*]] = getelementptr inbounds i32* [[VBTBL]], i32 1 +// CHECK-NEXT: [[VBOFFS:%.*]] = load i32* [[VBOFFP]], align 4 // CHECK-NEXT: [[DELTA:%.*]] = add nsw i32 [[VBOFFS]], 4 // CHECK-NEXT: [[ADJ:%.*]] = getelementptr inbounds i8* [[VOIDP]], i32 [[DELTA]] // 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 1) @@ -57,11 +55,10 @@ T* test5(A* x) { return dynamic_cast<T*>(x); } // CHECK: [[CHECK:%.*]] = icmp eq %struct.A* %x, null // CHECK-NEXT: br i1 [[CHECK]] // CHECK: [[VOIDP:%.*]] = bitcast %struct.A* %x to i8* -// CHECK-NEXT: [[BITCAST:%.*]] = bitcast %struct.A* %x to i8** -// CHECK-NEXT: [[VBTBL:%.*]] = load i8** [[BITCAST]], align 4 -// CHECK-NEXT: [[VBOFFP:%.*]] = getelementptr inbounds i8* [[VBTBL]], i32 4 -// CHECK-NEXT: [[VBOFFPCAST:%.*]] = bitcast i8* [[VBOFFP]] to i32* -// CHECK-NEXT: [[VBOFFS:%.*]] = load i32* [[VBOFFPCAST:%.*]], align 4 +// CHECK-NEXT: [[VBPTRPTR:%.*]] = getelementptr inbounds %struct.A* %x, i32 0, i32 0 +// CHECK-NEXT: [[VBTBL:%.*]] = load i32** [[VBPTRPTR]], align 4 +// CHECK-NEXT: [[VBOFFP:%.*]] = getelementptr inbounds i32* [[VBTBL]], i32 1 +// CHECK-NEXT: [[VBOFFS:%.*]] = load i32* [[VBOFFP]], align 4 // CHECK-NEXT: [[ADJ:%.*]] = getelementptr inbounds i8* [[VOIDP]], i32 [[VBOFFS]] // 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* @@ -75,11 +72,10 @@ T* test6(B* x) { return dynamic_cast<T*>(x); } // CHECK-NEXT: br i1 [[CHECK]] // CHECK: [[CAST:%.*]] = getelementptr inbounds %struct.B* %x, i32 0, i32 0, i32 0 // CHECK-NEXT: [[VBPTR:%.*]] = getelementptr inbounds i8* [[CAST]], i32 4 -// CHECK-NEXT: [[BITCAST:%.*]] = bitcast i8* [[VBPTR]] to i8** -// CHECK-NEXT: [[VBTBL:%.*]] = load i8** [[BITCAST]], align 4 -// CHECK-NEXT: [[VBOFFP:%.*]] = getelementptr inbounds i8* [[VBTBL]], i32 4 -// CHECK-NEXT: [[VBOFFPCAST:%.*]] = bitcast i8* [[VBOFFP]] to i32* -// CHECK-NEXT: [[VBOFFS:%.*]] = load i32* [[VBOFFPCAST:%.*]], align 4 +// CHECK-NEXT: [[VBPTRPTR:%.*]] = bitcast i8* [[VBPTR]] to i32** +// CHECK-NEXT: [[VBTBL:%.*]] = load i32** [[VBPTRPTR]], align 4 +// CHECK-NEXT: [[VBOFFP:%.*]] = getelementptr inbounds i32* [[VBTBL]], i32 1 +// CHECK-NEXT: [[VBOFFS:%.*]] = load i32* [[VBOFFP]], align 4 // CHECK-NEXT: [[DELTA:%.*]] = add nsw i32 [[VBOFFS]], 4 // CHECK-NEXT: [[ADJ:%.*]] = getelementptr inbounds i8* [[CAST]], i32 [[DELTA]] // 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) @@ -99,11 +95,10 @@ void* test8(A* x) { return dynamic_cast<void*>(x); } // CHECK: [[CHECK:%.*]] = icmp eq %struct.A* %x, null // CHECK-NEXT: br i1 [[CHECK]] // CHECK: [[VOIDP:%.*]] = bitcast %struct.A* %x to i8* -// CHECK-NEXT: [[BITCAST:%.*]] = bitcast %struct.A* %x to i8** -// CHECK-NEXT: [[VBTBL:%.*]] = load i8** [[BITCAST]], align 4 -// CHECK-NEXT: [[VBOFFP:%.*]] = getelementptr inbounds i8* [[VBTBL]], i32 4 -// CHECK-NEXT: [[VBOFFPCAST:%.*]] = bitcast i8* [[VBOFFP]] to i32* -// CHECK-NEXT: [[VBOFFS:%.*]] = load i32* [[VBOFFPCAST:%.*]], align 4 +// CHECK-NEXT: [[VBPTRPTR:%.*]] = getelementptr inbounds %struct.A* %x, i32 0, i32 0 +// CHECK-NEXT: [[VBTBL:%.*]] = load i32** [[VBPTRPTR]], align 4 +// CHECK-NEXT: [[VBOFFP:%.*]] = getelementptr inbounds i32* [[VBTBL]], i32 1 +// CHECK-NEXT: [[VBOFFS:%.*]] = load i32* [[VBOFFP]], align 4 // CHECK-NEXT: [[ADJ:%.*]] = getelementptr inbounds i8* [[VOIDP]], i32 [[VBOFFS]] // CHECK-NEXT: [[RES:%.*]] = tail call i8* @__RTCastToVoid(i8* [[ADJ]]) // CHECK-NEXT: br label @@ -116,11 +111,10 @@ void* test9(B* x) { return dynamic_cast<void*>(x); } // CHECK-NEXT: br i1 [[CHECK]] // CHECK: [[CAST:%.*]] = getelementptr inbounds %struct.B* %x, i32 0, i32 0, i32 0 // CHECK-NEXT: [[VBPTR:%.*]] = getelementptr inbounds i8* [[CAST]], i32 4 -// CHECK-NEXT: [[BITCAST:%.*]] = bitcast i8* [[VBPTR]] to i8** -// CHECK-NEXT: [[VBTBL:%.*]] = load i8** [[BITCAST]], align 4 -// CHECK-NEXT: [[VBOFFP:%.*]] = getelementptr inbounds i8* [[VBTBL]], i32 4 -// CHECK-NEXT: [[VBOFFPCAST:%.*]] = bitcast i8* [[VBOFFP]] to i32* -// CHECK-NEXT: [[VBOFFS:%.*]] = load i32* [[VBOFFPCAST:%.*]], align 4 +// CHECK-NEXT: [[VBPTRPTR:%.*]] = bitcast i8* [[VBPTR]] to i32** +// CHECK-NEXT: [[VBTBL:%.*]] = load i32** [[VBPTRPTR]], align 4 +// CHECK-NEXT: [[VBOFFP:%.*]] = getelementptr inbounds i32* [[VBTBL]], i32 1 +// CHECK-NEXT: [[VBOFFS:%.*]] = load i32* [[VBOFFP]], align 4 // CHECK-NEXT: [[DELTA:%.*]] = add nsw i32 [[VBOFFS]], 4 // CHECK-NEXT: [[ADJ:%.*]] = getelementptr inbounds i8* [[CAST]], i32 [[DELTA]] // CHECK-NEXT: [[CALL:%.*]] = tail call i8* @__RTCastToVoid(i8* [[ADJ]]) diff --git a/test/CodeGenCXX/microsoft-abi-member-pointers.cpp b/test/CodeGenCXX/microsoft-abi-member-pointers.cpp index 18e8c827eebe..719cb70679f4 100755 --- a/test/CodeGenCXX/microsoft-abi-member-pointers.cpp +++ b/test/CodeGenCXX/microsoft-abi-member-pointers.cpp @@ -1,9 +1,29 @@ -// RUN: %clang_cc1 -std=c++11 -fno-rtti -emit-llvm %s -o - -triple=i386-pc-win32 -fms-extensions | FileCheck %s -// RUN: %clang_cc1 -std=c++11 -fno-rtti -emit-llvm %s -o - -triple=x86_64-pc-win32 -fms-extensions | FileCheck %s -check-prefix=X64 -// RUN: %clang_cc1 -std=c++11 -fno-rtti -emit-llvm %s -o - -triple=i386-pc-win32 -DINCOMPLETE_VIRTUAL -fms-extensions -verify -// RUN: %clang_cc1 -std=c++11 -fno-rtti -emit-llvm %s -o - -triple=i386-pc-win32 -DINCOMPLETE_VIRTUAL -DMEMFUN -fms-extensions -verify -// FIXME: Test x86_64 member pointers when codegen no longer asserts on records -// with virtual bases. +// RUN: %clang_cc1 -std=c++11 -Wno-uninitialized -fno-rtti -emit-llvm %s -o - -triple=i386-pc-win32 -fms-extensions | FileCheck %s +// RUN: %clang_cc1 -std=c++11 -Wno-uninitialized -fno-rtti -emit-llvm %s -o - -triple=x86_64-pc-win32 -fms-extensions | FileCheck %s -check-prefix=X64 +// 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 + +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 + +struct B; +int B::*&b = b; +// CHECK: @"\01?b@PR20947@@3AAPQB@1@HA" = global %[[opaque1]]* null, align 4 +} + +namespace PR20017 { +template <typename T> +struct A { + int T::*m_fn1() { return nullptr; } +}; +struct B; +auto a = &A<B>::m_fn1; +// CHECK-DAG: @"\01?a@PR20017@@3P8?$A@UB@PR20017@@@1@AEPQB@1@HXZQ21@" = global i8* bitcast ({ i32, i32, i32 } ({{.*}}*)* @"\01?m_fn1@?$A@UB@PR20017@@@PR20017@@QAEPQB@2@HXZ" to i8*), align 4 +} #ifndef INCOMPLETE_VIRTUAL struct B1 { @@ -265,11 +285,11 @@ int loadDataMemberPointerVirtual(Virtual *o, int Virtual::*memptr) { // CHECK: %[[memptr1:.*]] = extractvalue { i32, i32 } %[[memptr:.*]], 1 // CHECK: %[[v6:.*]] = bitcast %{{.*}}* %[[o]] to i8* // CHECK: %[[vbptr:.*]] = getelementptr inbounds i8* %[[v6]], i32 0 -// CHECK: %[[vbptr_a:.*]] = bitcast i8* %[[vbptr]] to i8** -// CHECK: %[[vbtable:.*]] = load i8** %[[vbptr_a:.*]] -// CHECK: %[[v7:.*]] = getelementptr inbounds i8* %[[vbtable]], i32 %[[memptr1]] -// CHECK: %[[v8:.*]] = bitcast i8* %[[v7]] to i32* -// CHECK: %[[vbase_offs:.*]] = load i32* %[[v8]] +// CHECK: %[[vbptr_a:.*]] = bitcast i8* %[[vbptr]] to i32** +// CHECK: %[[vbtable:.*]] = load i32** %[[vbptr_a:.*]] +// CHECK: %[[memptr1_shr:.*]] = ashr exact i32 %[[memptr1]], 2 +// CHECK: %[[v7:.*]] = getelementptr inbounds i32* %[[vbtable]], i32 %[[memptr1_shr]] +// CHECK: %[[vbase_offs:.*]] = load i32* %[[v7]] // CHECK: %[[v10:.*]] = getelementptr inbounds i8* %[[vbptr]], i32 %[[vbase_offs]] // CHECK: %[[offset:.*]] = getelementptr inbounds i8* %[[v10]], i32 %[[memptr0]] // CHECK: %[[v11:.*]] = bitcast i8* %[[offset]] to i32* @@ -299,11 +319,11 @@ int loadDataMemberPointerUnspecified(Unspecified *o, int Unspecified::*memptr) { // // CHECK: [[vadjust]] // CHECK: %[[vbptr:.*]] = getelementptr inbounds i8* %[[base]], i32 %[[memptr1]] -// CHECK: %[[vbptr_a:.*]] = bitcast i8* %[[vbptr]] to i8** -// CHECK: %[[vbtable:.*]] = load i8** %[[vbptr_a:.*]] -// CHECK: %[[v7:.*]] = getelementptr inbounds i8* %[[vbtable]], i32 %[[memptr2]] -// CHECK: %[[v8:.*]] = bitcast i8* %[[v7]] to i32* -// CHECK: %[[vbase_offs:.*]] = load i32* %[[v8]] +// CHECK: %[[vbptr_a:.*]] = bitcast i8* %[[vbptr]] to i32** +// CHECK: %[[vbtable:.*]] = load i32** %[[vbptr_a:.*]] +// CHECK: %[[memptr2_shr:.*]] = ashr exact i32 %[[memptr2]], 2 +// CHECK: %[[v7:.*]] = getelementptr inbounds i32* %[[vbtable]], i32 %[[memptr2_shr]] +// CHECK: %[[vbase_offs:.*]] = load i32* %[[v7]] // CHECK: %[[base_adj:.*]] = getelementptr inbounds i8* %[[vbptr]], i32 %[[vbase_offs]] // // CHECK: [[skip]] @@ -350,11 +370,11 @@ void callMemberPointerVirtualBase(Virtual *o, void (Virtual::*memptr)()) { // CHECK: %[[memptr1:.*]] = extractvalue { i8*, i32, i32 } %{{.*}}, 1 // CHECK: %[[memptr2:.*]] = extractvalue { i8*, i32, i32 } %{{.*}}, 2 // CHECK: %[[vbptr:.*]] = getelementptr inbounds i8* %{{.*}}, i32 0 -// CHECK: %[[vbptr_a:.*]] = bitcast i8* %[[vbptr]] to i8** -// CHECK: %[[vbtable:.*]] = load i8** %[[vbptr_a:.*]] -// CHECK: %[[v7:.*]] = getelementptr inbounds i8* %[[vbtable]], i32 %[[memptr2]] -// CHECK: %[[v8:.*]] = bitcast i8* %[[v7]] to i32* -// CHECK: %[[vbase_offs:.*]] = load i32* %[[v8]] +// CHECK: %[[vbptr_a:.*]] = bitcast i8* %[[vbptr]] to i32** +// CHECK: %[[vbtable:.*]] = load i32** %[[vbptr_a:.*]] +// CHECK: %[[memptr2_shr:.*]] = ashr exact i32 %[[memptr2]], 2 +// CHECK: %[[v7:.*]] = getelementptr inbounds i32* %[[vbtable]], i32 %[[memptr2_shr]] +// CHECK: %[[vbase_offs:.*]] = load i32* %[[v7]] // CHECK: %[[v10:.*]] = getelementptr inbounds i8* %[[vbptr]], i32 %[[vbase_offs]] // CHECK: %[[this_adjusted:.*]] = getelementptr inbounds i8* %[[v10]], i32 %[[memptr1]] // CHECK: %[[fptr:.*]] = bitcast i8* %[[memptr0]] to void ({{.*}}) @@ -595,15 +615,15 @@ void (C::*getmp())() { return &C::g; } // CHECK-LABEL: define i64 @"\01?getmp@Test4@@YAP8C@1@AEXXZXZ"() -// CHECK: store { i8*, i32 } { i8* bitcast (void (i8*)* @"\01??_9C@Test4@@$BA@AE" to i8*), i32 4 }, { i8*, i32 }* %{{.*}} +// CHECK: store { i8*, i32 } { i8* bitcast (void (%"struct.Test4::C"*, ...)* @"\01??_9C@Test4@@$BA@AE" to i8*), i32 4 }, { i8*, i32 }* %{{.*}} // -// CHECK-LABEL: define linkonce_odr x86_thiscallcc void @"\01??_9C@Test4@@$BA@AE"(i8*) +// CHECK-LABEL: define linkonce_odr x86_thiscallcc void @"\01??_9C@Test4@@$BA@AE"(%"struct.Test4::C"* %this, ...) // CHECK-NOT: getelementptr -// CHECK: load void (i8*)*** %{{.*}} -// CHECK: getelementptr inbounds void (i8*)** %{{.*}}, i64 0 +// CHECK: load void (%"struct.Test4::C"*, ...)*** %{{.*}} +// CHECK: getelementptr inbounds void (%"struct.Test4::C"*, ...)** %{{.*}}, i64 0 // CHECK-NOT: getelementptr -// CHECK: call x86_thiscallcc void % +// CHECK: musttail call x86_thiscallcc void (%"struct.Test4::C"*, ...)* % } @@ -630,6 +650,34 @@ void test() { void (B::*a)() = &B::f; } // CHECK: store i8* bitcast (void (%"struct.pr20007_kw::A"*)* @"\01?f@A@pr20007_kw@@QAEXXZ" to i8*) } +namespace pr20007_pragma { +struct A { + void f(); + void f(int); +}; +struct B : public A {}; +void test() { (void)(void (B::*)()) &B::f; } +#pragma pointers_to_members(full_generality, virtual_inheritance) +static_assert(sizeof(int B::*) == 4, ""); +static_assert(sizeof(int A::*) == 4, ""); +#pragma pointers_to_members(best_case) +// CHECK-LABEL: define void @"\01?test@pr20007_pragma@@YAXXZ" +} + +namespace pr20007_pragma2 { +struct A { +}; +struct B : public A { + void f(); +}; +void test() { (void)&B::f; } +#pragma pointers_to_members(full_generality, virtual_inheritance) +static_assert(sizeof(int B::*) == 4, ""); +static_assert(sizeof(int A::*) == 12, ""); +#pragma pointers_to_members(best_case) +// CHECK-LABEL: define void @"\01?test@pr20007_pragma2@@YAXXZ" +} + namespace pr19987 { template <typename T> struct S { diff --git a/test/CodeGenCXX/microsoft-abi-multiple-nonvirtual-inheritance.cpp b/test/CodeGenCXX/microsoft-abi-multiple-nonvirtual-inheritance.cpp index b1c1482eff6f..b5293e0d7989 100644 --- a/test/CodeGenCXX/microsoft-abi-multiple-nonvirtual-inheritance.cpp +++ b/test/CodeGenCXX/microsoft-abi-multiple-nonvirtual-inheritance.cpp @@ -150,35 +150,35 @@ void emit_ctors() { Left l; // CHECK: define {{.*}} @"\01??0Left@@QAE@XZ" // CHECK-NOT: getelementptr - // CHECK: store [1 x i8*]* @"\01??_7Left@@6B@" + // CHECK: store i32 (...)** bitcast ([1 x i8*]* @"\01??_7Left@@6B@" to i32 (...)**) // CHECK: ret Right r; // CHECK: define {{.*}} @"\01??0Right@@QAE@XZ" // CHECK-NOT: getelementptr - // CHECK: store [1 x i8*]* @"\01??_7Right@@6B@" + // CHECK: store i32 (...)** bitcast ([1 x i8*]* @"\01??_7Right@@6B@" to i32 (...)**) // CHECK: ret ChildOverride co; // CHECK: define {{.*}} @"\01??0ChildOverride@@QAE@XZ" // CHECK: %[[THIS:.*]] = load %struct.ChildOverride** - // CHECK: %[[VFPTR:.*]] = bitcast %struct.ChildOverride* %[[THIS]] to [1 x i8*]** - // CHECK: store [1 x i8*]* @"\01??_7ChildOverride@@6BLeft@@@", [1 x i8*]** %[[VFPTR]] + // CHECK: %[[VFPTR:.*]] = bitcast %struct.ChildOverride* %[[THIS]] to i32 (...)*** + // CHECK: store i32 (...)** bitcast ([1 x i8*]* @"\01??_7ChildOverride@@6BLeft@@@" to i32 (...)**), i32 (...)*** %[[VFPTR]] // CHECK: %[[THIS_i8:.*]] = bitcast %struct.ChildOverride* %[[THIS]] to i8* // CHECK: %[[VFPTR_i8:.*]] = getelementptr inbounds i8* %[[THIS_i8]], i32 4 - // CHECK: %[[VFPTR:.*]] = bitcast i8* %[[VFPTR_i8]] to [1 x i8*]** - // CHECK: store [1 x i8*]* @"\01??_7ChildOverride@@6BRight@@@", [1 x i8*]** %[[VFPTR]] + // CHECK: %[[VFPTR:.*]] = bitcast i8* %[[VFPTR_i8]] to i32 (...)*** + // CHECK: store i32 (...)** bitcast ([1 x i8*]* @"\01??_7ChildOverride@@6BRight@@@" to i32 (...)**), i32 (...)*** %[[VFPTR]] // CHECK: ret GrandchildOverride gc; // CHECK: define {{.*}} @"\01??0GrandchildOverride@@QAE@XZ" // CHECK: %[[THIS:.*]] = load %struct.GrandchildOverride** - // CHECK: %[[VFPTR:.*]] = bitcast %struct.GrandchildOverride* %[[THIS]] to [1 x i8*]** - // CHECK: store [1 x i8*]* @"\01??_7GrandchildOverride@@6BLeft@@@", [1 x i8*]** %[[VFPTR]] + // CHECK: %[[VFPTR:.*]] = bitcast %struct.GrandchildOverride* %[[THIS]] to i32 (...)*** + // CHECK: store i32 (...)** bitcast ([1 x i8*]* @"\01??_7GrandchildOverride@@6BLeft@@@" to i32 (...)**), i32 (...)*** %[[VFPTR]] // CHECK: %[[THIS_i8:.*]] = bitcast %struct.GrandchildOverride* %[[THIS]] to i8* // CHECK: %[[VFPTR_i8:.*]] = getelementptr inbounds i8* %[[THIS_i8]], i32 4 - // CHECK: %[[VFPTR:.*]] = bitcast i8* %[[VFPTR_i8]] to [1 x i8*]** - // CHECK: store [1 x i8*]* @"\01??_7GrandchildOverride@@6BRight@@@", [1 x i8*]** %[[VFPTR]] + // CHECK: %[[VFPTR:.*]] = bitcast i8* %[[VFPTR_i8]] to i32 (...)*** + // CHECK: store i32 (...)** bitcast ([1 x i8*]* @"\01??_7GrandchildOverride@@6BRight@@@" to i32 (...)**), i32 (...)*** %[[VFPTR]] // CHECK: ret } diff --git a/test/CodeGenCXX/microsoft-abi-nontrivial-covariant-thunk.cpp b/test/CodeGenCXX/microsoft-abi-nontrivial-covariant-thunk.cpp index d305dd83271f..cb8b5224d65b 100644 --- a/test/CodeGenCXX/microsoft-abi-nontrivial-covariant-thunk.cpp +++ b/test/CodeGenCXX/microsoft-abi-nontrivial-covariant-thunk.cpp @@ -18,7 +18,7 @@ struct B { struct C : A, B { C(); int c; - virtual C *clone(A); // expected-error {{cannot compile this non-trivial argument copy for thunk yet}} + virtual C *clone(A); // expected-error {{cannot compile this non-trivial argument copy for return-adjusting thunk yet}} }; B::B() {} // force emission C::C() {} // force emission diff --git a/test/CodeGenCXX/microsoft-abi-static-initializers.cpp b/test/CodeGenCXX/microsoft-abi-static-initializers.cpp index 5f74c54c1c45..76d7e9e19192 100644 --- a/test/CodeGenCXX/microsoft-abi-static-initializers.cpp +++ b/test/CodeGenCXX/microsoft-abi-static-initializers.cpp @@ -1,9 +1,12 @@ // RUN: %clang_cc1 -fms-extensions -emit-llvm %s -o - -mconstructor-aliases -triple=i386-pc-win32 | FileCheck %s -// CHECK: @llvm.global_ctors = appending global [2 x { i32, void ()*, i8* }] -// CHECK: [{ i32, void ()*, i8* } { i32 65535, void ()* @"\01??__Efoo@?$B@H@@2VA@@A@YAXXZ", -// CHECK: i8* bitcast (%class.A* @"\01?foo@?$B@H@@2VA@@A" to i8*) }, -// CHECK: { i32, void ()*, i8* } { i32 65535, void ()* @_GLOBAL__sub_I_microsoft_abi_static_initializers.cpp, i8* null }] +// CHECK: @llvm.global_ctors = appending global [5 x { i32, void ()*, i8* }] [ +// CHECK: { i32, void ()*, i8* } { i32 65535, void ()* @"\01??__Eselectany1@@YAXXZ", i8* getelementptr inbounds (%struct.S* @"\01?selectany1@@3US@@A", i32 0, i32 0) }, +// CHECK: { i32, void ()*, i8* } { i32 65535, void ()* @"\01??__Eselectany2@@YAXXZ", i8* getelementptr inbounds (%struct.S* @"\01?selectany2@@3US@@A", i32 0, i32 0) }, +// CHECK: { i32, void ()*, i8* } { i32 65535, void ()* @"\01??__Es@?$ExportedTemplate@H@@2US@@A@YAXXZ", i8* getelementptr inbounds (%struct.S* @"\01?s@?$ExportedTemplate@H@@2US@@A", i32 0, i32 0) }, +// CHECK: { i32, void ()*, i8* } { i32 65535, void ()* @"\01??__Efoo@?$B@H@@2VA@@A@YAXXZ", i8* bitcast (%class.A* @"\01?foo@?$B@H@@2VA@@A" to i8*) }, +// CHECK: { i32, void ()*, i8* } { i32 65535, void ()* @_GLOBAL__sub_I_microsoft_abi_static_initializers.cpp, i8* null } +// CHECK: ] struct S { S(); @@ -21,8 +24,8 @@ S s; // CHECK: call x86_thiscallcc void @"\01??1S@@QAE@XZ" // CHECK: ret void -// These globals should use distinct guard variables, and not different bits of -// the same global. +// These globals should have initializers comdat associative with the global. +// See @llvm.global_ctors above. __declspec(selectany) S selectany1; __declspec(selectany) S selectany2; // CHECK: define linkonce_odr void @"\01??__Eselectany1@@YAXXZ"() @@ -34,12 +37,23 @@ __declspec(selectany) S selectany2; // CHECK: call x86_thiscallcc %struct.S* @"\01??0S@@QAE@XZ" // CHECK: ret void +// The implicitly instantiated static data member should have initializer +// comdat associative with the global. +template <typename T> struct __declspec(dllexport) ExportedTemplate { + static S s; +}; +template <typename T> S ExportedTemplate<T>::s; +void useExportedTemplate(ExportedTemplate<int> x) { + (void)x.s; +} + void StaticLocal() { static S TheS; } + // CHECK-LABEL: define void @"\01?StaticLocal@@YAXXZ"() -// CHECK: load i32* @"\01?$S1@?0??StaticLocal@@YAXXZ@4IA" -// CHECK: store i32 {{.*}}, i32* @"\01?$S1@?0??StaticLocal@@YAXXZ@4IA" +// CHECK: load i32* @"\01?$S1@?1??StaticLocal@@YAXXZ@4IA" +// CHECK: store i32 {{.*}}, i32* @"\01?$S1@?1??StaticLocal@@YAXXZ@4IA" // CHECK: ret void MultipleStatics() { @@ -80,7 +94,7 @@ void MultipleStatics() { static S S35; } // CHECK-LABEL: define void @"\01?MultipleStatics@@YAXXZ"() -// CHECK: load i32* @"\01?$S1@?0??MultipleStatics@@YAXXZ@4IA" +// CHECK: load i32* @"\01?$S1@?1??MultipleStatics@@YAXXZ@4IA" // CHECK: and i32 {{.*}}, 1 // CHECK: and i32 {{.*}}, 2 // CHECK: and i32 {{.*}}, 4 @@ -88,7 +102,7 @@ void MultipleStatics() { // CHECK: and i32 {{.*}}, 16 // ... // CHECK: and i32 {{.*}}, -2147483648 -// CHECK: load i32* @"\01?$S1@?0??MultipleStatics@@YAXXZ@4IA1" +// CHECK: load i32* @"\01?$S1@?1??MultipleStatics@@YAXXZ@4IA1" // CHECK: and i32 {{.*}}, 1 // CHECK: and i32 {{.*}}, 2 // CHECK: and i32 {{.*}}, 4 diff --git a/test/CodeGenCXX/microsoft-abi-structors-delayed-template.cpp b/test/CodeGenCXX/microsoft-abi-structors-delayed-template.cpp new file mode 100644 index 000000000000..f9e188033ca4 --- /dev/null +++ b/test/CodeGenCXX/microsoft-abi-structors-delayed-template.cpp @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -emit-llvm -fdelayed-template-parsing -std=c++11 -o - -triple=i386-pc-win32 %s > %t +// RUN: FileCheck %s < %t + +// PR20671 +namespace vtable_referenced_from_template { +struct ImplicitCtor { + virtual ~ImplicitCtor(); +}; +template <class T> void foo(T t) { new ImplicitCtor; } +void bar() { foo(0); } +// CHECK: store {{.*}} @"\01??_7ImplicitCtor@vtable_referenced_from_template@@6B@" +} diff --git a/test/CodeGenCXX/microsoft-abi-structors.cpp b/test/CodeGenCXX/microsoft-abi-structors.cpp index 7d3992b9940b..01d72e0aed57 100644 --- a/test/CodeGenCXX/microsoft-abi-structors.cpp +++ b/test/CodeGenCXX/microsoft-abi-structors.cpp @@ -46,8 +46,9 @@ B::B() { struct C { virtual ~C() { -// DTORS: define linkonce_odr x86_thiscallcc void @"\01??_GC@basic@@UAEPAXI@Z"(%"struct.basic::C"* %this, i32 %should_call_delete) +// DTORS: define linkonce_odr x86_thiscallcc i8* @"\01??_GC@basic@@UAEPAXI@Z"(%"struct.basic::C"* %this, i32 %should_call_delete) // DTORS: store i32 %should_call_delete, i32* %[[SHOULD_DELETE_VAR:[0-9a-z._]+]], align 4 +// DTORS: store i8* %{{.*}}, i8** %[[RETVAL:[0-9a-z._]+]] // DTORS: %[[SHOULD_DELETE_VALUE:[0-9a-z._]+]] = load i32* %[[SHOULD_DELETE_VAR]] // DTORS: call x86_thiscallcc void @"\01??1C@basic@@UAE@XZ"(%"struct.basic::C"* %[[THIS:[0-9a-z]+]]) // DTORS-NEXT: %[[CONDITION:[0-9]+]] = icmp eq i32 %[[SHOULD_DELETE_VALUE]], 0 @@ -59,7 +60,8 @@ struct C { // DTORS-NEXT: br label %[[CONTINUE_LABEL]] // // DTORS: [[CONTINUE_LABEL]] -// DTORS-NEXT: ret void +// DTORS-NEXT: %[[RET:.*]] = load i8** %[[RETVAL]] +// DTORS-NEXT: ret i8* %[[RET]] // Check that we do the mangling correctly on x64. // DTORS-X64: @"\01??_GC@basic@@UEAAPEAXI@Z" @@ -73,19 +75,19 @@ void C::foo() {} void check_vftable_offset() { C c; // The vftable pointer should point at the beginning of the vftable. -// CHECK: [[THIS_PTR:%[0-9]+]] = bitcast %"struct.basic::C"* {{.*}} to [2 x i8*]** -// CHECK: store [2 x i8*]* @"\01??_7C@basic@@6B@", [2 x i8*]** [[THIS_PTR]] +// CHECK: [[THIS_PTR:%[0-9]+]] = bitcast %"struct.basic::C"* {{.*}} to i32 (...)*** +// CHECK: store i32 (...)** bitcast ([2 x i8*]* @"\01??_7C@basic@@6B@" to i32 (...)**), i32 (...)*** [[THIS_PTR]] } void call_complete_dtor(C *obj_ptr) { // CHECK: define void @"\01?call_complete_dtor@basic@@YAXPAUC@1@@Z"(%"struct.basic::C"* %obj_ptr) obj_ptr->~C(); // CHECK: %[[OBJ_PTR_VALUE:.*]] = load %"struct.basic::C"** %{{.*}}, align 4 -// CHECK-NEXT: %[[PVTABLE:.*]] = bitcast %"struct.basic::C"* %[[OBJ_PTR_VALUE]] to void (%"struct.basic::C"*, i32)*** -// CHECK-NEXT: %[[VTABLE:.*]] = load void (%"struct.basic::C"*, i32)*** %[[PVTABLE]] -// CHECK-NEXT: %[[PVDTOR:.*]] = getelementptr inbounds void (%"struct.basic::C"*, i32)** %[[VTABLE]], i64 0 -// CHECK-NEXT: %[[VDTOR:.*]] = load void (%"struct.basic::C"*, i32)** %[[PVDTOR]] -// CHECK-NEXT: call x86_thiscallcc void %[[VDTOR]](%"struct.basic::C"* %[[OBJ_PTR_VALUE]], i32 0) +// CHECK-NEXT: %[[PVTABLE:.*]] = bitcast %"struct.basic::C"* %[[OBJ_PTR_VALUE]] to i8* (%"struct.basic::C"*, i32)*** +// CHECK-NEXT: %[[VTABLE:.*]] = load i8* (%"struct.basic::C"*, i32)*** %[[PVTABLE]] +// CHECK-NEXT: %[[PVDTOR:.*]] = getelementptr inbounds i8* (%"struct.basic::C"*, i32)** %[[VTABLE]], i64 0 +// CHECK-NEXT: %[[VDTOR:.*]] = load i8* (%"struct.basic::C"*, i32)** %[[PVDTOR]] +// CHECK-NEXT: call x86_thiscallcc i8* %[[VDTOR]](%"struct.basic::C"* %[[OBJ_PTR_VALUE]], i32 0) // CHECK-NEXT: ret void } @@ -96,11 +98,27 @@ void call_deleting_dtor(C *obj_ptr) { // CHECK: br i1 {{.*}}, label %[[DELETE_NULL:.*]], label %[[DELETE_NOTNULL:.*]] // CHECK: [[DELETE_NOTNULL]] -// CHECK-NEXT: %[[PVTABLE:.*]] = bitcast %"struct.basic::C"* %[[OBJ_PTR_VALUE]] to void (%"struct.basic::C"*, i32)*** -// CHECK-NEXT: %[[VTABLE:.*]] = load void (%"struct.basic::C"*, i32)*** %[[PVTABLE]] -// CHECK-NEXT: %[[PVDTOR:.*]] = getelementptr inbounds void (%"struct.basic::C"*, i32)** %[[VTABLE]], i64 0 -// CHECK-NEXT: %[[VDTOR:.*]] = load void (%"struct.basic::C"*, i32)** %[[PVDTOR]] -// CHECK-NEXT: call x86_thiscallcc void %[[VDTOR]](%"struct.basic::C"* %[[OBJ_PTR_VALUE]], i32 1) +// CHECK-NEXT: %[[PVTABLE:.*]] = bitcast %"struct.basic::C"* %[[OBJ_PTR_VALUE]] to i8* (%"struct.basic::C"*, i32)*** +// CHECK-NEXT: %[[VTABLE:.*]] = load i8* (%"struct.basic::C"*, i32)*** %[[PVTABLE]] +// CHECK-NEXT: %[[PVDTOR:.*]] = getelementptr inbounds i8* (%"struct.basic::C"*, i32)** %[[VTABLE]], i64 0 +// CHECK-NEXT: %[[VDTOR:.*]] = load i8* (%"struct.basic::C"*, i32)** %[[PVDTOR]] +// CHECK-NEXT: call x86_thiscallcc i8* %[[VDTOR]](%"struct.basic::C"* %[[OBJ_PTR_VALUE]], i32 1) +// CHECK: ret void +} + +void call_deleting_dtor_and_global_delete(C *obj_ptr) { +// CHECK: define void @"\01?call_deleting_dtor_and_global_delete@basic@@YAXPAUC@1@@Z"(%"struct.basic::C"* %obj_ptr) + ::delete obj_ptr; +// CHECK: %[[OBJ_PTR_VALUE:.*]] = load %"struct.basic::C"** %{{.*}}, align 4 +// CHECK: br i1 {{.*}}, label %[[DELETE_NULL:.*]], label %[[DELETE_NOTNULL:.*]] + +// CHECK: [[DELETE_NOTNULL]] +// CHECK-NEXT: %[[PVTABLE:.*]] = bitcast %"struct.basic::C"* %[[OBJ_PTR_VALUE]] to i8* (%"struct.basic::C"*, i32)*** +// CHECK-NEXT: %[[VTABLE:.*]] = load i8* (%"struct.basic::C"*, i32)*** %[[PVTABLE]] +// CHECK-NEXT: %[[PVDTOR:.*]] = getelementptr inbounds i8* (%"struct.basic::C"*, i32)** %[[VTABLE]], i64 0 +// CHECK-NEXT: %[[VDTOR:.*]] = load i8* (%"struct.basic::C"*, i32)** %[[PVDTOR]] +// CHECK-NEXT: %[[CALL:.*]] = call x86_thiscallcc i8* %[[VDTOR]](%"struct.basic::C"* %[[OBJ_PTR_VALUE]], i32 0) +// CHECK-NEXT: call void @"\01??3@YAXPAX@Z"(i8* %[[CALL]]) // CHECK: ret void } @@ -153,13 +171,13 @@ C::~C() { void foo() { C c; } -// DTORS2-LABEL: define linkonce_odr x86_thiscallcc void @"\01??_EC@dtor_in_second_nvbase@@W3AEPAXI@Z" +// DTORS2-LABEL: define linkonce_odr x86_thiscallcc i8* @"\01??_EC@dtor_in_second_nvbase@@W3AEPAXI@Z" // DTORS2: (%"struct.dtor_in_second_nvbase::C"* %this, i32 %should_call_delete) // Do an adjustment from B* to C*. // DTORS2: getelementptr i8* %{{.*}}, i32 -4 // DTORS2: bitcast i8* %{{.*}} to %"struct.dtor_in_second_nvbase::C"* -// DTORS2: call x86_thiscallcc void @"\01??_GC@dtor_in_second_nvbase@@UAEPAXI@Z" -// DTORS2: ret void +// DTORS2: %[[CALL:.*]] = call x86_thiscallcc i8* @"\01??_GC@dtor_in_second_nvbase@@UAEPAXI@Z" +// DTORS2: ret i8* %[[CALL]] } @@ -229,8 +247,8 @@ C::C() { // CHECK: [[INIT_VBASES]] // CHECK-NEXT: %[[this_i8:.*]] = bitcast %"struct.constructors::C"* %{{.*}} to i8* // CHECK-NEXT: %[[vbptr_off:.*]] = getelementptr inbounds i8* %[[this_i8]], i64 0 - // CHECK-NEXT: %[[vbptr:.*]] = bitcast i8* %[[vbptr_off]] to [2 x i32]** - // CHECK-NEXT: store [2 x i32]* @"\01??_8C@constructors@@7B@", [2 x i32]** %[[vbptr]] + // CHECK-NEXT: %[[vbptr:.*]] = bitcast i8* %[[vbptr_off]] to i32** + // CHECK-NEXT: store i32* getelementptr inbounds ([2 x i32]* @"\01??_8C@constructors@@7B@", i32 0, i32 0), i32** %[[vbptr]] // CHECK-NEXT: bitcast %"struct.constructors::C"* %{{.*}} to i8* // CHECK-NEXT: getelementptr inbounds i8* %{{.*}}, i64 4 // CHECK-NEXT: bitcast i8* %{{.*}} to %"struct.constructors::A"* @@ -264,8 +282,8 @@ D::D() { // CHECK: [[INIT_VBASES]] // CHECK-NEXT: %[[this_i8:.*]] = bitcast %"struct.constructors::D"* %{{.*}} to i8* // CHECK-NEXT: %[[vbptr_off:.*]] = getelementptr inbounds i8* %[[this_i8]], i64 0 - // CHECK-NEXT: %[[vbptr:.*]] = bitcast i8* %[[vbptr_off]] to [2 x i32]** - // CHECK-NEXT: store [2 x i32]* @"\01??_8D@constructors@@7B@", [2 x i32]** %[[vbptr]] + // CHECK-NEXT: %[[vbptr:.*]] = bitcast i8* %[[vbptr_off]] to i32** + // CHECK-NEXT: store i32* getelementptr inbounds ([2 x i32]* @"\01??_8D@constructors@@7B@", i32 0, i32 0), i32** %[[vbptr]] // CHECK-NEXT: bitcast %"struct.constructors::D"* %{{.*}} to i8* // CHECK-NEXT: getelementptr inbounds i8* %{{.*}}, i64 4 // CHECK-NEXT: bitcast i8* %{{.*}} to %"struct.constructors::A"* @@ -291,11 +309,11 @@ E::E() { // CHECK: [[INIT_VBASES]] // CHECK-NEXT: %[[this_i8:.*]] = bitcast %"struct.constructors::E"* %{{.*}} to i8* // CHECK-NEXT: %[[offs:.*]] = getelementptr inbounds i8* %[[this_i8]], i64 0 - // CHECK-NEXT: %[[vbptr_E:.*]] = bitcast i8* %[[offs]] to [3 x i32]** - // CHECK-NEXT: store [3 x i32]* @"\01??_8E@constructors@@7B01@@", [3 x i32]** %[[vbptr_E]] + // CHECK-NEXT: %[[vbptr_E:.*]] = bitcast i8* %[[offs]] to i32** + // CHECK-NEXT: store i32* getelementptr inbounds ([3 x i32]* @"\01??_8E@constructors@@7B01@@", i32 0, i32 0), i32** %[[vbptr_E]] // CHECK-NEXT: %[[offs:.*]] = getelementptr inbounds i8* %[[this_i8]], i64 4 - // CHECK-NEXT: %[[vbptr_C:.*]] = bitcast i8* %[[offs]] to [2 x i32]** - // CHECK-NEXT: store [2 x i32]* @"\01??_8E@constructors@@7BC@1@@", [2 x i32]** %[[vbptr_C]] + // CHECK-NEXT: %[[vbptr_C:.*]] = bitcast i8* %[[offs]] to i32** + // CHECK-NEXT: store i32* getelementptr inbounds ([2 x i32]* @"\01??_8E@constructors@@7BC@1@@", i32 0, i32 0), i32** %[[vbptr_C]] // CHECK-NEXT: bitcast %"struct.constructors::E"* %{{.*}} to i8* // CHECK-NEXT: getelementptr inbounds i8* %{{.*}}, i64 4 // CHECK-NEXT: bitcast i8* %{{.*}} to %"struct.constructors::A"* @@ -436,7 +454,7 @@ struct A { void *getA() { return (void*)new A(); } -// CHECK: define internal x86_thiscallcc void @"\01??_GA@?A@@UAEPAXI@Z" +// CHECK: define internal x86_thiscallcc i8* @"\01??_GA@?A@@UAEPAXI@Z" // CHECK: (%"struct.(anonymous namespace)::A"* %this, i32 %should_call_delete) // CHECK: define internal x86_thiscallcc void @"\01??1A@?A@@UAE@XZ" // CHECK: (%"struct.(anonymous namespace)::A"* %this) diff --git a/test/CodeGenCXX/microsoft-abi-thunks.cpp b/test/CodeGenCXX/microsoft-abi-thunks.cpp index c755b300067d..843bc89b0d0d 100644 --- a/test/CodeGenCXX/microsoft-abi-thunks.cpp +++ b/test/CodeGenCXX/microsoft-abi-thunks.cpp @@ -61,10 +61,10 @@ struct C : A, B { C::C() {} // Emits vftable and forces thunk generation. -// CODEGEN-LABEL: define linkonce_odr x86_thiscallcc void @"\01??_EC@@W3AEPAXI@Z"(%struct.C* %this, i32 %should_call_delete) +// CODEGEN-LABEL: define linkonce_odr x86_thiscallcc i8* @"\01??_EC@@W3AEPAXI@Z"(%struct.C* %this, i32 %should_call_delete) // CODEGEN: getelementptr i8* {{.*}}, i32 -4 // FIXME: should actually call _EC, not _GC. -// CODEGEN: call x86_thiscallcc void @"\01??_GC@@UAEPAXI@Z" +// CODEGEN: call x86_thiscallcc i8* @"\01??_GC@@UAEPAXI@Z" // CODEGEN: ret // CODEGEN-LABEL: define linkonce_odr x86_thiscallcc void @"\01?public_f@C@@W3AEXXZ"(%struct.C* @@ -128,10 +128,9 @@ I::I() {} // Emits vftable and forces thunk generation. // CODEGEN: %[[ORIG_RET:.*]] = call x86_thiscallcc %struct.F* @"\01?goo@I@@UAEPAUF@@XZ" // CODEGEN: %[[ORIG_RET_i8:.*]] = bitcast %struct.F* %[[ORIG_RET]] to i8* // CODEGEN: %[[VBPTR_i8:.*]] = getelementptr inbounds i8* %[[ORIG_RET_i8]], i32 4 -// CODEGEN: %[[VBPTR:.*]] = bitcast i8* %[[VBPTR_i8]] to i8** -// CODEGEN: %[[VBTABLE:.*]] = load i8** %[[VBPTR]] -// CODEGEN: %[[VBASE_OFFSET_PTR_i8:.*]] = getelementptr inbounds i8* %[[VBTABLE]], i32 8 -// CODEGEN: %[[VBASE_OFFSET_PTR:.*]] = bitcast i8* %[[VBASE_OFFSET_PTR_i8]] to i32* +// CODEGEN: %[[VBPTR:.*]] = bitcast i8* %[[VBPTR_i8]] to i32** +// CODEGEN: %[[VBTABLE:.*]] = load i32** %[[VBPTR]] +// CODEGEN: %[[VBASE_OFFSET_PTR:.*]] = getelementptr inbounds i32* %[[VBTABLE]], i32 2 // CODEGEN: %[[VBASE_OFFSET:.*]] = load i32* %[[VBASE_OFFSET_PTR]] // CODEGEN: %[[RES_i8:.*]] = getelementptr inbounds i8* %[[VBPTR_i8]], i32 %[[VBASE_OFFSET]] // CODEGEN: %[[RES:.*]] = bitcast i8* %[[RES_i8]] to %struct.F* diff --git a/test/CodeGenCXX/microsoft-abi-typeid.cpp b/test/CodeGenCXX/microsoft-abi-typeid.cpp index 4ee004d51d21..1beb2118126a 100644 --- a/test/CodeGenCXX/microsoft-abi-typeid.cpp +++ b/test/CodeGenCXX/microsoft-abi-typeid.cpp @@ -31,11 +31,10 @@ const std::type_info* test3_typeid() { return &typeid(*fn()); } // CHECK: tail call i8* @__RTtypeid(i8* null) // CHECK-NEXT: unreachable // CHECK: [[THIS:%.*]] = bitcast %struct.A* [[CALL]] to i8* -// CHECK-NEXT: [[VBTBLP:%.*]] = bitcast %struct.A* [[CALL]] to i8** -// CHECK-NEXT: [[VBTBL:%.*]] = load i8** [[VBTBLP]], align 4 -// CHECK-NEXT: [[VBSLOT:%.*]] = getelementptr inbounds i8* [[VBTBL]], i32 4 -// CHECK-NEXT: [[VBITCST:%.*]] = bitcast i8* [[VBSLOT]] to i32* -// CHECK-NEXT: [[VBASE_OFFS:%.*]] = load i32* [[VBITCST]], align 4 +// CHECK-NEXT: [[VBTBLP:%.*]] = getelementptr inbounds %struct.A* [[CALL]], i32 0, i32 0 +// CHECK-NEXT: [[VBTBL:%.*]] = load i32** [[VBTBLP]], align 4 +// CHECK-NEXT: [[VBSLOT:%.*]] = getelementptr inbounds i32* [[VBTBL]], i32 1 +// CHECK-NEXT: [[VBASE_OFFS:%.*]] = load i32* [[VBSLOT]], align 4 // CHECK-NEXT: [[ADJ:%.*]] = getelementptr inbounds i8* [[THIS]], i32 [[VBASE_OFFS]] // CHECK-NEXT: [[RT:%.*]] = tail call i8* @__RTtypeid(i8* [[ADJ]]) // CHECK-NEXT: [[RET:%.*]] = bitcast i8* [[RT]] to %struct.type_info* diff --git a/test/CodeGenCXX/microsoft-abi-vftables.cpp b/test/CodeGenCXX/microsoft-abi-vftables.cpp index 825aba010f12..14bd6c388b01 100644 --- a/test/CodeGenCXX/microsoft-abi-vftables.cpp +++ b/test/CodeGenCXX/microsoft-abi-vftables.cpp @@ -9,7 +9,7 @@ struct S { virtual ~S(); } s; -// RTTI-DAG: [[VTABLE_S:@.*]] = private unnamed_addr constant [2 x i8*] [i8* bitcast ({{.*}} @"\01??_R4S@@6B@" to i8*), i8* bitcast ({{.*}} @"\01??_GS@@UAEPAXI@Z" to i8*)], comdat $"\01??_7S@@6B@" +// RTTI-DAG: [[VTABLE_S:@.*]] = private unnamed_addr constant [2 x i8*] [i8* bitcast ({{.*}} @"\01??_R4S@@6B@" to i8*), i8* bitcast ({{.*}} @"\01??_GS@@UAEPAXI@Z" to i8*)], comdat($"\01??_7S@@6B@") // RTTI-DAG: @"\01??_7S@@6B@" = unnamed_addr alias getelementptr inbounds ([2 x i8*]* [[VTABLE_S]], i32 0, i32 1) // NO-RTTI-DAG: @"\01??_7S@@6B@" = linkonce_odr unnamed_addr constant [1 x i8*] [i8* bitcast ({{.*}} @"\01??_GS@@UAEPAXI@Z" to i8*)] @@ -26,7 +26,7 @@ struct __declspec(dllexport) V { virtual ~V(); } v; -// RTTI-DAG: [[VTABLE_V:@.*]] = private unnamed_addr constant [2 x i8*] [i8* bitcast ({{.*}} @"\01??_R4V@@6B@" to i8*), i8* bitcast ({{.*}} @"\01??_GV@@UAEPAXI@Z" to i8*)], comdat $"\01??_7V@@6B@" +// RTTI-DAG: [[VTABLE_V:@.*]] = private unnamed_addr constant [2 x i8*] [i8* bitcast ({{.*}} @"\01??_R4V@@6B@" to i8*), i8* bitcast ({{.*}} @"\01??_GV@@UAEPAXI@Z" to i8*)], comdat($"\01??_7V@@6B@") // RTTI-DAG: @"\01??_7V@@6B@" = dllexport unnamed_addr alias getelementptr inbounds ([2 x i8*]* [[VTABLE_V]], i32 0, i32 1) // NO-RTTI-DAG: @"\01??_7V@@6B@" = weak_odr dllexport unnamed_addr constant [1 x i8*] [i8* bitcast ({{.*}} @"\01??_GV@@UAEPAXI@Z" to i8*)] @@ -36,7 +36,7 @@ struct 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*)], comdat $"\01??_7W@?A@@6B@" -// RTTI-DAG: @"\01??_7W@?A@@6B@" = unnamed_addr alias internal getelementptr inbounds ([2 x i8*]* @1, i32 0, i32 1) +// 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*)], comdat($"\01??_7W@?A@@6B@") +// RTTI-DAG: @"\01??_7W@?A@@6B@" = internal unnamed_addr alias getelementptr inbounds ([2 x i8*]* @1, i32 0, i32 1) // NO-RTTI-DAG: @"\01??_7W@?A@@6B@" = internal unnamed_addr constant [1 x i8*] [i8* bitcast ({{.*}} @"\01??_GW@?A@@UAEPAXI@Z" to i8*)] diff --git a/test/CodeGenCXX/microsoft-abi-virtual-inheritance-vtordisps.cpp b/test/CodeGenCXX/microsoft-abi-virtual-inheritance-vtordisps.cpp index a6fcdea749ab..26eb01205cf6 100644 --- a/test/CodeGenCXX/microsoft-abi-virtual-inheritance-vtordisps.cpp +++ b/test/CodeGenCXX/microsoft-abi-virtual-inheritance-vtordisps.cpp @@ -72,10 +72,9 @@ G::G() {} // Forces vftable emission. // CHECK: %[[VTORDISP_NEG:.*]] = sub i32 0, %[[VTORDISP]] // CHECK: %[[VTORDISP_ADJUSTED_i8:.*]] = getelementptr i8* %[[ECX_i8]], i32 %[[VTORDISP_NEG]] // CHECK: %[[VBPTR_i8:.*]] = getelementptr inbounds i8* %[[VTORDISP_ADJUSTED_i8]], i32 -16 -// CHECK: %[[VBPTR:.*]] = bitcast i8* %[[VBPTR_i8]] to i8** -// CHECK: %[[VBTABLE:.*]] = load i8** %[[VBPTR]] -// CHECK: %[[VBOFFSET_PTR_i8:.*]] = getelementptr inbounds i8* %[[VBTABLE]], i32 12 -// CHECK: %[[VBOFFSET_PTR:.*]] = bitcast i8* %[[VBOFFSET_PTR_i8]] to i32* +// CHECK: %[[VBPTR:.*]] = bitcast i8* %[[VBPTR_i8]] to i32** +// CHECK: %[[VBTABLE:.*]] = load i32** %[[VBPTR]] +// CHECK: %[[VBOFFSET_PTR:.*]] = getelementptr inbounds i32* %[[VBTABLE]], i32 3 // CHECK: %[[VBASE_OFFSET:.*]] = load i32* %[[VBOFFSET_PTR]] // CHECK: %[[VBASE:.*]] = getelementptr inbounds i8* %[[VBPTR_i8]], i32 %[[VBASE_OFFSET]] // CHECK: %[[ARG_i8:.*]] = getelementptr i8* %[[VBASE]], i32 8 diff --git a/test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp b/test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp index 2f0fffee696f..7a00a731f5fa 100644 --- a/test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp +++ b/test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp @@ -32,8 +32,8 @@ B::B() { // ... // CHECK: %[[THIS_i8:.*]] = bitcast %struct.B* %[[THIS]] to i8* // CHECK: %[[VFPTR_i8:.*]] = getelementptr inbounds i8* %[[THIS_i8]], i32 %{{.*}} - // CHECK: %[[VFPTR:.*]] = bitcast i8* %[[VFPTR_i8]] to [3 x i8*]** - // CHECK: store [3 x i8*]* @"\01??_7B@@6B@", [3 x i8*]** %[[VFPTR]] + // CHECK: %[[VFPTR:.*]] = bitcast i8* %[[VFPTR_i8]] to i32 (...)*** + // CHECK: store i32 (...)** bitcast ([3 x i8*]* @"\01??_7B@@6B@" to i32 (...)**), i32 (...)*** %[[VFPTR]] // Initialize vtorDisp: // CHECK: %[[THIS_i8:.*]] = bitcast %struct.B* %[[THIS]] to i8* @@ -65,8 +65,8 @@ B::~B() { // ... // CHECK: %[[THIS_i8:.*]] = bitcast %struct.B* %[[THIS]] to i8* // CHECK: %[[VFPTR_i8:.*]] = getelementptr inbounds i8* %[[THIS_i8]], i32 %{{.*}} - // CHECK: %[[VFPTR:.*]] = bitcast i8* %[[VFPTR_i8]] to [3 x i8*]** - // CHECK: store [3 x i8*]* @"\01??_7B@@6B@", [3 x i8*]** %[[VFPTR]] + // CHECK: %[[VFPTR:.*]] = bitcast i8* %[[VFPTR_i8]] to i32 (...)*** + // CHECK: store i32 (...)** bitcast ([3 x i8*]* @"\01??_7B@@6B@" to i32 (...)**), i32 (...)*** %[[VFPTR]] // Initialize vtorDisp: // CHECK: %[[THIS_i8:.*]] = bitcast %struct.B* %[[THIS]] to i8* @@ -96,7 +96,7 @@ B::~B() { // CHECK2: call x86_thiscallcc void @"\01??1VBase@@UAE@XZ"(%struct.VBase* %[[VBASE]]) // CHECK2: ret - // CHECK2-LABEL: define linkonce_odr x86_thiscallcc void @"\01??_GB@@UAEPAXI@Z" + // CHECK2-LABEL: define linkonce_odr x86_thiscallcc i8* @"\01??_GB@@UAEPAXI@Z" // CHECK2: %[[THIS_PARAM_i8:.*]] = bitcast %struct.B* {{.*}} to i8* // CHECK2: %[[THIS_i8:.*]] = getelementptr inbounds i8* %[[THIS_PARAM_i8:.*]], i32 -8 // CHECK2: %[[THIS:.*]] = bitcast i8* %[[THIS_i8]] to %struct.B* @@ -122,10 +122,9 @@ void B::foo() { // CHECK: %[[THIS:.*]] = load %struct.B** %[[THIS_ADDR]] // CHECK: %[[THIS8:.*]] = bitcast %struct.B* %[[THIS]] to i8* // CHECK: %[[VBPTR:.*]] = getelementptr inbounds i8* %[[THIS8]], i32 0 -// CHECK: %[[VBPTR8:.*]] = bitcast i8* %[[VBPTR]] to i8** -// CHECK: %[[VBTABLE:.*]] = load i8** %[[VBPTR8]] -// CHECK: %[[VBENTRY8:.*]] = getelementptr inbounds i8* %[[VBTABLE]], i32 4 -// CHECK: %[[VBENTRY:.*]] = bitcast i8* %[[VBENTRY8]] to i32* +// CHECK: %[[VBPTR8:.*]] = bitcast i8* %[[VBPTR]] to i32** +// CHECK: %[[VBTABLE:.*]] = load i32** %[[VBPTR8]] +// CHECK: %[[VBENTRY:.*]] = getelementptr inbounds i32* %[[VBTABLE]], i32 1 // CHECK: %[[VBOFFSET32:.*]] = load i32* %[[VBENTRY]] // CHECK: %[[VBOFFSET:.*]] = add nsw i32 0, %[[VBOFFSET32]] // CHECK: %[[THIS8:.*]] = bitcast %struct.B* %[[THIS]] to i8* @@ -147,10 +146,9 @@ void call_vbase_bar(B *obj) { // // CHECK: %[[OBJ_i8:.*]] = bitcast %struct.B* %[[OBJ]] to i8* // CHECK: %[[VBPTR:.*]] = getelementptr inbounds i8* %[[OBJ_i8]], i32 0 -// CHECK: %[[VBPTR8:.*]] = bitcast i8* %[[VBPTR]] to i8** -// CHECK: %[[VBTABLE:.*]] = load i8** %[[VBPTR8]] -// CHECK: %[[VBENTRY8:.*]] = getelementptr inbounds i8* %[[VBTABLE]], i32 4 -// CHECK: %[[VBENTRY:.*]] = bitcast i8* %[[VBENTRY8]] to i32* +// CHECK: %[[VBPTR8:.*]] = bitcast i8* %[[VBPTR]] to i32** +// CHECK: %[[VBTABLE:.*]] = load i32** %[[VBPTR8]] +// CHECK: %[[VBENTRY:.*]] = getelementptr inbounds i32* %[[VBTABLE]], i32 1 // CHECK: %[[VBOFFSET32:.*]] = load i32* %[[VBENTRY]] // CHECK: %[[VBOFFSET:.*]] = add nsw i32 0, %[[VBOFFSET32]] // CHECK: %[[VBASE_i8:.*]] = getelementptr inbounds i8* %[[OBJ_i8]], i32 %[[VBOFFSET]] @@ -161,10 +159,9 @@ void call_vbase_bar(B *obj) { // // CHECK: %[[OBJ_i8:.*]] = bitcast %struct.B* %[[OBJ]] to i8* // CHECK: %[[VBPTR:.*]] = getelementptr inbounds i8* %[[OBJ_i8]], i32 0 -// CHECK: %[[VBPTR8:.*]] = bitcast i8* %[[VBPTR]] to i8** -// CHECK: %[[VBTABLE:.*]] = load i8** %[[VBPTR8]] -// CHECK: %[[VBENTRY8:.*]] = getelementptr inbounds i8* %[[VBTABLE]], i32 4 -// CHECK: %[[VBENTRY:.*]] = bitcast i8* %[[VBENTRY8]] to i32* +// CHECK: %[[VBPTR8:.*]] = bitcast i8* %[[VBPTR]] to i32** +// CHECK: %[[VBTABLE:.*]] = load i32** %[[VBPTR8]] +// CHECK: %[[VBENTRY:.*]] = getelementptr inbounds i32* %[[VBTABLE]], i32 1 // CHECK: %[[VBOFFSET32:.*]] = load i32* %[[VBENTRY]] // CHECK: %[[VBOFFSET:.*]] = add nsw i32 0, %[[VBOFFSET32]] // CHECK: %[[VBASE:.*]] = getelementptr inbounds i8* %[[OBJ_i8]], i32 %[[VBOFFSET]] @@ -181,30 +178,28 @@ void delete_B(B *obj) { delete obj; // CHECK: %[[OBJ_i8:.*]] = bitcast %struct.B* %[[OBJ]] to i8* // CHECK: %[[VBPTR:.*]] = getelementptr inbounds i8* %[[OBJ_i8]], i32 0 -// CHECK: %[[VBPTR8:.*]] = bitcast i8* %[[VBPTR]] to i8** -// CHECK: %[[VBTABLE:.*]] = load i8** %[[VBPTR8]] -// CHECK: %[[VBENTRY8:.*]] = getelementptr inbounds i8* %[[VBTABLE]], i32 4 -// CHECK: %[[VBENTRY:.*]] = bitcast i8* %[[VBENTRY8]] to i32* +// CHECK: %[[VBPTR8:.*]] = bitcast i8* %[[VBPTR]] to i32** +// CHECK: %[[VBTABLE:.*]] = load i32** %[[VBPTR8]] +// CHECK: %[[VBENTRY:.*]] = getelementptr inbounds i32* %[[VBTABLE]], i32 1 // CHECK: %[[VBOFFSET32:.*]] = load i32* %[[VBENTRY]] // CHECK: %[[VBOFFSET:.*]] = add nsw i32 0, %[[VBOFFSET32]] // CHECK: %[[VBASE_i8:.*]] = getelementptr inbounds i8* %[[OBJ_i8]], i32 %[[VBOFFSET]] -// CHECK: %[[VFPTR:.*]] = bitcast i8* %[[VBASE_i8]] to void (%struct.B*, i32)*** -// CHECK: %[[VFTABLE:.*]] = load void (%struct.B*, i32)*** %[[VFPTR]] -// CHECK: %[[VFUN:.*]] = getelementptr inbounds void (%struct.B*, i32)** %[[VFTABLE]], i64 0 -// CHECK: %[[VFUN_VALUE:.*]] = load void (%struct.B*, i32)** %[[VFUN]] +// CHECK: %[[VFPTR:.*]] = bitcast i8* %[[VBASE_i8]] to i8* (%struct.B*, i32)*** +// CHECK: %[[VFTABLE:.*]] = load i8* (%struct.B*, i32)*** %[[VFPTR]] +// CHECK: %[[VFUN:.*]] = getelementptr inbounds i8* (%struct.B*, i32)** %[[VFTABLE]], i64 0 +// CHECK: %[[VFUN_VALUE:.*]] = load i8* (%struct.B*, i32)** %[[VFUN]] // // CHECK: %[[OBJ_i8:.*]] = bitcast %struct.B* %[[OBJ]] to i8* // CHECK: %[[VBPTR:.*]] = getelementptr inbounds i8* %[[OBJ_i8]], i32 0 -// CHECK: %[[VBPTR8:.*]] = bitcast i8* %[[VBPTR]] to i8** -// CHECK: %[[VBTABLE:.*]] = load i8** %[[VBPTR8]] -// CHECK: %[[VBENTRY8:.*]] = getelementptr inbounds i8* %[[VBTABLE]], i32 4 -// CHECK: %[[VBENTRY:.*]] = bitcast i8* %[[VBENTRY8]] to i32* +// CHECK: %[[VBPTR8:.*]] = bitcast i8* %[[VBPTR]] to i32** +// CHECK: %[[VBTABLE:.*]] = load i32** %[[VBPTR8]] +// CHECK: %[[VBENTRY:.*]] = getelementptr inbounds i32* %[[VBTABLE]], i32 1 // CHECK: %[[VBOFFSET32:.*]] = load i32* %[[VBENTRY]] // CHECK: %[[VBOFFSET:.*]] = add nsw i32 0, %[[VBOFFSET32]] // CHECK: %[[VBASE_i8:.*]] = getelementptr inbounds i8* %[[OBJ_i8]], i32 %[[VBOFFSET]] // CHECK: %[[VBASE:.*]] = bitcast i8* %[[VBASE_i8]] to %struct.B* // -// CHECK: call x86_thiscallcc void %[[VFUN_VALUE]](%struct.B* %[[VBASE]], i32 1) +// CHECK: call x86_thiscallcc i8* %[[VFUN_VALUE]](%struct.B* %[[VBASE]], i32 1) // CHECK: ret void } @@ -250,9 +245,9 @@ struct D : virtual A, virtual B, virtual C { D::D() { // CHECK-LABEL: define x86_thiscallcc %"struct.multiple_vbases::D"* @"\01??0D@multiple_vbases@@QAE@XZ" // Just make sure we emit 3 vtordisps after initializing vfptrs. - // CHECK: store [1 x i8*]* @"\01??_7D@multiple_vbases@@6BA@1@@", [1 x i8*]** %{{.*}} - // CHECK: store [1 x i8*]* @"\01??_7D@multiple_vbases@@6BB@1@@", [1 x i8*]** %{{.*}} - // CHECK: store [1 x i8*]* @"\01??_7D@multiple_vbases@@6BC@1@@", [1 x i8*]** %{{.*}} + // CHECK: store i32 (...)** bitcast ([1 x i8*]* @"\01??_7D@multiple_vbases@@6BA@1@@" to i32 (...)**), i32 (...)*** %{{.*}} + // CHECK: store i32 (...)** bitcast ([1 x i8*]* @"\01??_7D@multiple_vbases@@6BB@1@@" to i32 (...)**), i32 (...)*** %{{.*}} + // CHECK: store i32 (...)** bitcast ([1 x i8*]* @"\01??_7D@multiple_vbases@@6BC@1@@" to i32 (...)**), i32 (...)*** %{{.*}} // ... // CHECK: store i32 %{{.*}}, i32* %{{.*}} // CHECK: store i32 %{{.*}}, i32* %{{.*}} @@ -401,8 +396,8 @@ C::~C() { // In this case "this" points to the most derived class, so no GEPs needed. // CHECK-NOT: getelementptr // CHECK-NOT: bitcast - // CHECK: %[[VFPTR_i8:.*]] = bitcast %"struct.test4::C"* %{{.*}} to [1 x i8*]** - // CHECK: store [1 x i8*]* @"\01??_7C@test4@@6BB@1@@", [1 x i8*]** %[[VFPTR_i8]] + // CHECK: %[[VFPTR_i8:.*]] = bitcast %"struct.test4::C"* %{{.*}} to i32 (...)*** + // CHECK: store i32 (...)** bitcast ([1 x i8*]* @"\01??_7C@test4@@6BB@1@@" to i32 (...)**), i32 (...)*** %[[VFPTR_i8]] foo(this); // CHECK: ret @@ -412,11 +407,11 @@ void destroy(C *obj) { // CHECK-LABEL: define void @"\01?destroy@test4@@YAXPAUC@1@@Z"(%"struct.test4::C"* %obj) delete obj; - // CHECK: %[[VPTR:.*]] = bitcast %"struct.test4::C"* %[[OBJ:.*]] to void (%"struct.test4::C"*, i32)*** - // CHECK: %[[VFTABLE:.*]] = load void (%"struct.test4::C"*, i32)*** %[[VPTR]] - // CHECK: %[[VFTENTRY:.*]] = getelementptr inbounds void (%"struct.test4::C"*, i32)** %[[VFTABLE]], i64 0 - // CHECK: %[[VFUN:.*]] = load void (%"struct.test4::C"*, i32)** %[[VFTENTRY]] - // CHECK: call x86_thiscallcc void %[[VFUN]](%"struct.test4::C"* %[[OBJ]], i32 1) + // CHECK: %[[VPTR:.*]] = bitcast %"struct.test4::C"* %[[OBJ:.*]] to i8* (%"struct.test4::C"*, i32)*** + // CHECK: %[[VFTABLE:.*]] = load i8* (%"struct.test4::C"*, i32)*** %[[VPTR]] + // CHECK: %[[VFTENTRY:.*]] = getelementptr inbounds i8* (%"struct.test4::C"*, i32)** %[[VFTABLE]], i64 0 + // CHECK: %[[VFUN:.*]] = load i8* (%"struct.test4::C"*, i32)** %[[VFTENTRY]] + // CHECK: call x86_thiscallcc i8* %[[VFUN]](%"struct.test4::C"* %[[OBJ]], i32 1) // CHECK: ret } @@ -436,8 +431,8 @@ E::~E() { // In this case "this" points to the most derived class, so no GEPs needed. // CHECK-NOT: getelementptr // CHECK-NOT: bitcast - // CHECK: %[[VFPTR_i8:.*]] = bitcast %"struct.test4::E"* %{{.*}} to [1 x i8*]** - // CHECK: store [1 x i8*]* @"\01??_7E@test4@@6BD@1@@", [1 x i8*]** %[[VFPTR_i8]] + // CHECK: %[[VFPTR_i8:.*]] = bitcast %"struct.test4::E"* %{{.*}} to i32 (...)*** + // CHECK: store i32 (...)** bitcast ([1 x i8*]* @"\01??_7E@test4@@6BD@1@@" to i32 (...)**), i32 (...)*** %[[VFPTR_i8]] foo(this); } @@ -447,15 +442,15 @@ void destroy(E *obj) { // CHECK-NOT: getelementptr // CHECK: %[[OBJ_i8:.*]] = bitcast %"struct.test4::E"* %[[OBJ:.*]] to i8* // CHECK: %[[B_i8:.*]] = getelementptr inbounds i8* %[[OBJ_i8]], i32 4 - // CHECK: %[[VPTR:.*]] = bitcast i8* %[[B_i8]] to void (%"struct.test4::E"*, i32)*** - // CHECK: %[[VFTABLE:.*]] = load void (%"struct.test4::E"*, i32)*** %[[VPTR]] - // CHECK: %[[VFTENTRY:.*]] = getelementptr inbounds void (%"struct.test4::E"*, i32)** %[[VFTABLE]], i64 0 - // CHECK: %[[VFUN:.*]] = load void (%"struct.test4::E"*, i32)** %[[VFTENTRY]] + // CHECK: %[[VPTR:.*]] = bitcast i8* %[[B_i8]] to i8* (%"struct.test4::E"*, i32)*** + // CHECK: %[[VFTABLE:.*]] = load i8* (%"struct.test4::E"*, i32)*** %[[VPTR]] + // CHECK: %[[VFTENTRY:.*]] = getelementptr inbounds i8* (%"struct.test4::E"*, i32)** %[[VFTABLE]], i64 0 + // CHECK: %[[VFUN:.*]] = load i8* (%"struct.test4::E"*, i32)** %[[VFTENTRY]] // CHECK: %[[OBJ_i8:.*]] = bitcast %"struct.test4::E"* %[[OBJ]] to i8* // CHECK: %[[B_i8:.*]] = getelementptr inbounds i8* %[[OBJ_i8]], i32 4 // FIXME: in fact, the call should take i8* and the bitcast is redundant. // CHECK: %[[B_as_E:.*]] = bitcast i8* %[[B_i8]] to %"struct.test4::E"* - // CHECK: call x86_thiscallcc void %[[VFUN]](%"struct.test4::E"* %[[B_as_E]], i32 1) + // CHECK: call x86_thiscallcc i8* %[[VFUN]](%"struct.test4::E"* %[[B_as_E]], i32 1) delete obj; } diff --git a/test/CodeGenCXX/microsoft-abi-virtual-member-pointers.cpp b/test/CodeGenCXX/microsoft-abi-virtual-member-pointers.cpp index 974953c01444..b5db7c7881b5 100644 --- a/test/CodeGenCXX/microsoft-abi-virtual-member-pointers.cpp +++ b/test/CodeGenCXX/microsoft-abi-virtual-member-pointers.cpp @@ -45,92 +45,95 @@ void f() { // CHECK32-LABEL: define void @"\01?f@@YAXXZ"() -// CHECK32: store i8* bitcast (void (%struct.C*)* @"\01??_9C@@$BA@AE" to i8*), i8** %ptr -// CHECK32: store i8* bitcast (i32 (%struct.C*, i32, double)* @"\01??_9C@@$B3AE" to i8*), i8** %ptr2 -// CHECK32: store i8* bitcast (void (%struct.C*, %struct.S*, i32)* @"\01??_9C@@$B7AE" to i8*), i8** %ptr3 -// CHECK32: store i8* bitcast (void (%"struct.(anonymous namespace)::D"*)* @"\01??_9D@?A@@$BA@AE" to i8*), i8** %ptr4 +// CHECK32: store i8* bitcast (void (%struct.C*, ...)* @"\01??_9C@@$BA@AE" to i8*), i8** %ptr +// CHECK32: store i8* bitcast (void (%struct.C*, ...)* @"\01??_9C@@$B3AE" to i8*), i8** %ptr2 +// CHECK32: store i8* bitcast (void (%struct.C*, ...)* @"\01??_9C@@$B7AE" to i8*), i8** %ptr3 +// CHECK32: store i8* bitcast (void (%"struct.(anonymous namespace)::D"*, ...)* @"\01??_9D@?A@@$BA@AE" to i8*), i8** %ptr4 // CHECK32: } // // CHECK64-LABEL: define void @"\01?f@@YAXXZ"() -// CHECK64: store i8* bitcast (void (%struct.C*)* @"\01??_9C@@$BA@AA" to i8*), i8** %ptr -// CHECK64: store i8* bitcast (i32 (%struct.C*, i32, double)* @"\01??_9C@@$B7AA" to i8*), i8** %ptr2 -// CHECK64: store i8* bitcast (void (%struct.C*, %struct.S*, i32)* @"\01??_9C@@$BBA@AA" to i8*), i8** %ptr3 -// CHECK64: store i8* bitcast (void (%"struct.(anonymous namespace)::D"*)* @"\01??_9D@?A@@$BA@AA" to i8*), i8** %ptr +// CHECK64: store i8* bitcast (void (%struct.C*, ...)* @"\01??_9C@@$BA@AA" to i8*), i8** %ptr +// CHECK64: store i8* bitcast (void (%struct.C*, ...)* @"\01??_9C@@$B7AA" to i8*), i8** %ptr2 +// CHECK64: store i8* bitcast (void (%struct.C*, ...)* @"\01??_9C@@$BBA@AA" to i8*), i8** %ptr3 +// CHECK64: store i8* bitcast (void (%"struct.(anonymous namespace)::D"*, ...)* @"\01??_9D@?A@@$BA@AA" to i8*), i8** %ptr // CHECK64: } } // Thunk for calling the 1st virtual function in C with no parameters. -// CHECK32-LABEL: define linkonce_odr x86_thiscallcc void @"\01??_9C@@$BA@AE"(%struct.C* %this) unnamed_addr -// CHECK32: [[VPTR:%.*]] = getelementptr inbounds void (%struct.C*)** %{{.*}}, i64 0 -// CHECK32: [[CALLEE:%.*]] = load void (%struct.C*)** [[VPTR]] -// CHECK32: musttail call x86_thiscallcc void [[CALLEE]](%struct.C* %{{.*}}) -// CHECK32: ret void +// CHECK32-LABEL: define linkonce_odr x86_thiscallcc void @"\01??_9C@@$BA@AE"(%struct.C* %this, ...) +// CHECK32-NOT: unnamed_addr +// CHECK32: [[VPTR:%.*]] = getelementptr inbounds void (%struct.C*, ...)** %{{.*}}, i64 0 +// CHECK32: [[CALLEE:%.*]] = load void (%struct.C*, ...)** [[VPTR]] +// CHECK32: musttail call x86_thiscallcc void (%struct.C*, ...)* [[CALLEE]](%struct.C* %{{.*}}, ...) +// CHECK32-NEXT: ret void // CHECK32: } // -// CHECK64-LABEL: define linkonce_odr void @"\01??_9C@@$BA@AA"(%struct.C* %this) unnamed_addr -// CHECK64: [[VPTR:%.*]] = getelementptr inbounds void (%struct.C*)** %{{.*}}, i64 0 -// CHECK64: [[CALLEE:%.*]] = load void (%struct.C*)** [[VPTR]] -// CHECK64: musttail call void [[CALLEE]](%struct.C* %{{.*}}) -// CHECK64: ret void +// CHECK64-LABEL: define linkonce_odr void @"\01??_9C@@$BA@AA"(%struct.C* %this, ...) +// CHECK64-NOT: unnamed_addr +// CHECK64: [[VPTR:%.*]] = getelementptr inbounds void (%struct.C*, ...)** %{{.*}}, i64 0 +// CHECK64: [[CALLEE:%.*]] = load void (%struct.C*, ...)** [[VPTR]] +// CHECK64: musttail call void (%struct.C*, ...)* [[CALLEE]](%struct.C* %{{.*}}, ...) +// CHECK64-NEXT: ret void // CHECK64: } // Thunk for calling the 2nd virtual function in C, taking int and double as parameters, returning int. -// CHECK32-LABEL: define linkonce_odr x86_thiscallcc i32 @"\01??_9C@@$B3AE"(%struct.C* %this, i32, double) unnamed_addr -// CHECK32: [[VPTR:%.*]] = getelementptr inbounds i32 (%struct.C*, i32, double)** %{{.*}}, i64 1 -// CHECK32: [[CALLEE:%.*]] = load i32 (%struct.C*, i32, double)** [[VPTR]] -// CHECK32: [[CALL:%.*]] = musttail call x86_thiscallcc i32 [[CALLEE]](%struct.C* %{{.*}}, i32 %{{.*}}, double %{{.*}}) -// CHECK32: ret i32 [[CALL]] +// CHECK32-LABEL: define linkonce_odr x86_thiscallcc void @"\01??_9C@@$B3AE"(%struct.C* %this, ...) +// CHECK32: [[VPTR:%.*]] = getelementptr inbounds void (%struct.C*, ...)** %{{.*}}, i64 1 +// CHECK32: [[CALLEE:%.*]] = load void (%struct.C*, ...)** [[VPTR]] +// CHECK32: musttail call x86_thiscallcc void (%struct.C*, ...)* [[CALLEE]](%struct.C* %{{.*}}, ...) +// CHECK32-NEXT: ret void // CHECK32: } // -// CHECK64-LABEL: define linkonce_odr i32 @"\01??_9C@@$B7AA"(%struct.C* %this, i32, double) unnamed_addr -// CHECK64: [[VPTR:%.*]] = getelementptr inbounds i32 (%struct.C*, i32, double)** %{{.*}}, i64 1 -// CHECK64: [[CALLEE:%.*]] = load i32 (%struct.C*, i32, double)** [[VPTR]] -// CHECK64: [[CALL:%.*]] = musttail call i32 [[CALLEE]](%struct.C* %{{.*}}, i32 %{{.*}}, double %{{.*}}) -// CHECK64: ret i32 [[CALL]] +// CHECK64-LABEL: define linkonce_odr void @"\01??_9C@@$B7AA"(%struct.C* %this, ...) +// CHECK64: [[VPTR:%.*]] = getelementptr inbounds void (%struct.C*, ...)** %{{.*}}, i64 1 +// CHECK64: [[CALLEE:%.*]] = load void (%struct.C*, ...)** [[VPTR]] +// CHECK64: musttail call void (%struct.C*, ...)* [[CALLEE]](%struct.C* %{{.*}}, ...) +// CHECK64-NEXT: ret void // CHECK64: } // Thunk for calling the 3rd virtual function in C, taking an int parameter, returning a struct. -// CHECK32-LABEL: define linkonce_odr x86_thiscallcc void @"\01??_9C@@$B7AE"(%struct.C* %this, %struct.S* noalias sret %agg.result, i32) unnamed_addr -// CHECK32: [[VPTR:%.*]] = getelementptr inbounds void (%struct.C*, %struct.S*, i32)** %{{.*}}, i64 2 -// CHECK32: [[CALLEE:%.*]] = load void (%struct.C*, %struct.S*, i32)** [[VPTR]] -// CHECK32: musttail call x86_thiscallcc void [[CALLEE]](%struct.C* %{{.*}}, %struct.S* sret %agg.result, i32 %{{.*}}) -// CHECK32: ret void +// CHECK32-LABEL: define linkonce_odr x86_thiscallcc void @"\01??_9C@@$B7AE"(%struct.C* %this, ...) +// CHECK32: [[VPTR:%.*]] = getelementptr inbounds void (%struct.C*, ...)** %{{.*}}, i64 2 +// CHECK32: [[CALLEE:%.*]] = load void (%struct.C*, ...)** [[VPTR]] +// CHECK32: musttail call x86_thiscallcc void (%struct.C*, ...)* [[CALLEE]](%struct.C* %{{.*}}, ...) +// CHECK32-NEXT: ret void // CHECK32: } // -// CHECK64-LABEL: define linkonce_odr void @"\01??_9C@@$BBA@AA"(%struct.C* %this, %struct.S* noalias sret %agg.result, i32) unnamed_addr -// CHECK64: [[VPTR:%.*]] = getelementptr inbounds void (%struct.C*, %struct.S*, i32)** %{{.*}}, i64 2 -// CHECK64: [[CALLEE:%.*]] = load void (%struct.C*, %struct.S*, i32)** [[VPTR]] -// CHECK64: musttail call void [[CALLEE]](%struct.C* %{{.*}}, %struct.S* sret %agg.result, i32 %{{.*}}) -// CHECK64: ret void +// CHECK64-LABEL: define linkonce_odr void @"\01??_9C@@$BBA@AA"(%struct.C* %this, ...) +// CHECK64: [[VPTR:%.*]] = getelementptr inbounds void (%struct.C*, ...)** %{{.*}}, i64 2 +// CHECK64: [[CALLEE:%.*]] = load void (%struct.C*, ...)** [[VPTR]] +// CHECK64: musttail call void (%struct.C*, ...)* [[CALLEE]](%struct.C* %{{.*}}, ...) +// CHECK64-NEXT: ret void // CHECK64: } // Thunk for calling the virtual function in internal class D. -// CHECK32-LABEL: define internal x86_thiscallcc void @"\01??_9D@?A@@$BA@AE"(%"struct.(anonymous namespace)::D"* %this) unnamed_addr -// CHECK32: [[VPTR:%.*]] = getelementptr inbounds void (%"struct.(anonymous namespace)::D"*)** %{{.*}}, i64 0 -// CHECK32: [[CALLEE:%.*]] = load void (%"struct.(anonymous namespace)::D"*)** [[VPTR]] -// CHECK32: musttail call x86_thiscallcc void [[CALLEE]](%"struct.(anonymous namespace)::D"* %{{.*}}) -// CHECK32: ret void +// CHECK32-LABEL: define internal x86_thiscallcc void @"\01??_9D@?A@@$BA@AE"(%"struct.(anonymous namespace)::D"* %this, ...) +// CHECK32: [[VPTR:%.*]] = getelementptr inbounds void (%"struct.(anonymous namespace)::D"*, ...)** %{{.*}}, i64 0 +// CHECK32: [[CALLEE:%.*]] = load void (%"struct.(anonymous namespace)::D"*, ...)** [[VPTR]] +// CHECK32: musttail call x86_thiscallcc void (%"struct.(anonymous namespace)::D"*, ...)* [[CALLEE]](%"struct.(anonymous namespace)::D"* %{{.*}}, ...) +// CHECK32-NEXT: ret void // CHECK32: } // -// CHECK64-LABEL: define internal void @"\01??_9D@?A@@$BA@AA"(%"struct.(anonymous namespace)::D"* %this) unnamed_addr -// CHECK64: [[VPTR:%.*]] = getelementptr inbounds void (%"struct.(anonymous namespace)::D"*)** %{{.*}}, i64 0 -// CHECK64: [[CALLEE:%.*]] = load void (%"struct.(anonymous namespace)::D"*)** [[VPTR]] -// CHECK64: musttail call void [[CALLEE]](%"struct.(anonymous namespace)::D"* %{{.*}}) -// CHECK64: ret void +// CHECK64-LABEL: define internal void @"\01??_9D@?A@@$BA@AA"(%"struct.(anonymous namespace)::D"* %this, ...) +// CHECK64: [[VPTR:%.*]] = getelementptr inbounds void (%"struct.(anonymous namespace)::D"*, ...)** %{{.*}}, i64 0 +// CHECK64: [[CALLEE:%.*]] = load void (%"struct.(anonymous namespace)::D"*, ...)** [[VPTR]] +// CHECK64: musttail call void (%"struct.(anonymous namespace)::D"*, ...)* [[CALLEE]](%"struct.(anonymous namespace)::D"* %{{.*}}, ...) +// CHECK64-NEXT: ret void // CHECK64: } -// Thunk for calling the fourth virtual function in C, taking a struct parameter and returning a struct. -// CHECK32-LABEL: define linkonce_odr x86_thiscallcc %struct.S* @"\01??_9C@@$BM@AE"(%struct.C* %this, <{ %struct.S*, %struct.U }>* inalloca) unnamed_addr -// CHECK32: [[VPTR:%.*]] = getelementptr inbounds %struct.S* (%struct.C*, <{ %struct.S*, %struct.U }>*)** %{{.*}}, i64 3 -// CHECK32: [[CALLEE:%.*]] = load %struct.S* (%struct.C*, <{ %struct.S*, %struct.U }>*)** [[VPTR]] -// CHECK32: [[CALL:%.*]] = musttail call x86_thiscallcc %struct.S* [[CALLEE]](%struct.C* %this, <{ %struct.S*, %struct.U }>* inalloca %{{.*}}) -// CHECK32: ret %struct.S* [[CALL]] +// Thunk for calling the fourth virtual function in C, taking a struct parameter +// and returning a struct. +// CHECK32-LABEL: define linkonce_odr x86_thiscallcc void @"\01??_9C@@$BM@AE"(%struct.C* %this, ...) +// CHECK32: [[VPTR:%.*]] = getelementptr inbounds void (%struct.C*, ...)** %{{.*}}, i64 3 +// CHECK32: [[CALLEE:%.*]] = load void (%struct.C*, ...)** [[VPTR]] +// CHECK32: musttail call x86_thiscallcc void (%struct.C*, ...)* [[CALLEE]](%struct.C* %{{.*}}, ...) +// CHECK32-NEXT: ret void // CHECK32: } // -// CHECK64-LABEL: define linkonce_odr void @"\01??_9C@@$BBI@AA"(%struct.C* %this, %struct.S* noalias sret %agg.result, %struct.U*) unnamed_addr -// CHECK64: [[VPTR:%.*]] = getelementptr inbounds void (%struct.C*, %struct.S*, %struct.U*)** %{{.*}}, i64 3 -// CHECK64: [[CALLEE:%.*]] = load void (%struct.C*, %struct.S*, %struct.U*)** [[VPTR]] -// CHECK64: musttail call void [[CALLEE]](%struct.C* %this, %struct.S* sret %agg.result, %struct.U* %{{.*}}) +// CHECK64-LABEL: define linkonce_odr void @"\01??_9C@@$BBI@AA"(%struct.C* %this, ...) +// CHECK64: [[VPTR:%.*]] = getelementptr inbounds void (%struct.C*, ...)** %{{.*}}, i64 3 +// CHECK64: [[CALLEE:%.*]] = load void (%struct.C*, ...)** [[VPTR]] +// CHECK64: musttail call void (%struct.C*, ...)* [[CALLEE]](%struct.C* %{{.*}}, ...) // CHECK64: ret void // CHECK64: } diff --git a/test/CodeGenCXX/microsoft-abi-vmemptr-conflicts.cpp b/test/CodeGenCXX/microsoft-abi-vmemptr-conflicts.cpp new file mode 100644 index 000000000000..35ff4f3bebef --- /dev/null +++ b/test/CodeGenCXX/microsoft-abi-vmemptr-conflicts.cpp @@ -0,0 +1,101 @@ +// RUN: %clang_cc1 -fno-rtti -emit-llvm -triple=i386-pc-win32 %s -o - | FileCheck %s + +// In each test case, we have two member pointers whose thunks have the same +// vtable offset and same mangling, but their prototypes conflict. The +// arguments and return type may differ. Therefore, we have to bitcast the +// function prototype. Unfortunately, if the return types differ, LLVM's +// optimizers can get upset. + +namespace num_params { +struct A { virtual void a(int); }; +struct B { virtual void b(int, int); }; +struct C : A, B { + virtual void a(int); + virtual void b(int, int); +}; +void f(C *c) { + (c->*(&C::a))(0); + (c->*(&C::b))(0, 0); +} +} + +// CHECK-LABEL: define void @"\01?f@num_params@@YAXPAUC@1@@Z"(%"struct.num_params::C"* %c) +// CHECK: call x86_thiscallcc void bitcast (void (%"struct.num_params::C"*, ...)* @"\01??_9C@num_params@@$BA@AE" to void (%"struct.num_params::C"*, i32)*)(%"struct.num_params::C"* %{{.*}}, i32 0) +// CHECK: call x86_thiscallcc void bitcast (void (%"struct.num_params::C"*, ...)* @"\01??_9C@num_params@@$BA@AE" to void (%"struct.num_params::C"*, i32, i32)*)(%"struct.num_params::C"* %{{.*}}, i32 0, i32 0) + +// CHECK-LABEL: define linkonce_odr x86_thiscallcc void @"\01??_9C@num_params@@$BA@AE"(%"struct.num_params::C"* %this, ...) +// CHECK: musttail call x86_thiscallcc void (%"struct.num_params::C"*, ...)* %{{.*}}(%"struct.num_params::C"* %{{.*}}, ...) +// CHECK-NEXT: ret void + +namespace i64_return { +struct A { virtual int a(); }; +struct B { virtual long long b(); }; +struct C : A, B { + virtual int a(); + virtual long long b(); +}; +long long f(C *c) { + int x = (c->*(&C::a))(); + long long y = (c->*(&C::b))(); + return x + y; +} +} + +// CHECK-LABEL: define i64 @"\01?f@i64_return@@YA_JPAUC@1@@Z"(%"struct.i64_return::C"* %c) +// CHECK: call x86_thiscallcc i32 bitcast (void (%"struct.i64_return::C"*, ...)* @"\01??_9C@i64_return@@$BA@AE" to i32 (%"struct.i64_return::C"*)*)(%"struct.i64_return::C"* %{{.*}}) +// CHECK: call x86_thiscallcc i64 bitcast (void (%"struct.i64_return::C"*, ...)* @"\01??_9C@i64_return@@$BA@AE" to i64 (%"struct.i64_return::C"*)*)(%"struct.i64_return::C"* %{{.*}}) + +// CHECK-LABEL: define linkonce_odr x86_thiscallcc void @"\01??_9C@i64_return@@$BA@AE"(%"struct.i64_return::C"* %this, ...) +// CHECK: musttail call x86_thiscallcc void (%"struct.i64_return::C"*, ...)* %{{.*}}(%"struct.i64_return::C"* %{{.*}}, ...) +// CHECK-NEXT: ret void + +namespace sret { +struct Big { int big[32]; }; +struct A { virtual int a(); }; +struct B { virtual Big b(); }; +struct C : A, B { + virtual int a(); + virtual Big b(); +}; +void f(C *c) { + (c->*(&C::a))(); + Big b((c->*(&C::b))()); +} +} + +// CHECK-LABEL: define void @"\01?f@sret@@YAXPAUC@1@@Z"(%"struct.sret::C"* %c) +// CHECK: call x86_thiscallcc i32 bitcast (void (%"struct.sret::C"*, ...)* @"\01??_9C@sret@@$BA@AE" to i32 (%"struct.sret::C"*)*)(%"struct.sret::C"* %{{.*}}) +// CHECK: call x86_thiscallcc void bitcast (void (%"struct.sret::C"*, ...)* @"\01??_9C@sret@@$BA@AE" to void (%"struct.sret::C"*, %"struct.sret::Big"*)*)(%"struct.sret::C"* %{{.*}}, %"struct.sret::Big"* sret %{{.*}}) + +// CHECK-LABEL: define linkonce_odr x86_thiscallcc void @"\01??_9C@sret@@$BA@AE"(%"struct.sret::C"* %this, ...) +// CHECK: musttail call x86_thiscallcc void (%"struct.sret::C"*, ...)* %{{.*}}(%"struct.sret::C"* %{{.*}}, ...) +// CHECK-NEXT: ret void + +namespace cdecl_inalloca { +// Fairly evil, since now we end up doing an inalloca-style call through a +// thunk that doesn't use inalloca. Hopefully the stacks line up? +struct Big { + Big(); + ~Big(); + int big[32]; +}; +struct A { virtual void __cdecl a(); }; +struct B { virtual void __cdecl b(Big); }; +struct C : A, B { + virtual void __cdecl a(); + virtual void __cdecl b(Big); +}; +void f(C *c) { + Big b; + (c->*(&C::a))(); + ((c->*(&C::b))(b)); +} +} + +// CHECK-LABEL: define void @"\01?f@cdecl_inalloca@@YAXPAUC@1@@Z"(%"struct.cdecl_inalloca::C"* %c) +// CHECK: call void bitcast (void (%"struct.cdecl_inalloca::C"*, ...)* @"\01??_9C@cdecl_inalloca@@$BA@AE" to void (%"struct.cdecl_inalloca::C"*)*)(%"struct.cdecl_inalloca::C"* %{{.*}}) +// CHECK: call void bitcast (void (%"struct.cdecl_inalloca::C"*, ...)* @"\01??_9C@cdecl_inalloca@@$BA@AE" to void (<{ %"struct.cdecl_inalloca::C"*, %"struct.cdecl_inalloca::Big" }>*)*)(<{ %"struct.cdecl_inalloca::C"*, %"struct.cdecl_inalloca::Big" }>* inalloca %{{.*}}) + +// CHECK-LABEL: define linkonce_odr void @"\01??_9C@cdecl_inalloca@@$BA@AE"(%"struct.cdecl_inalloca::C"* %this, ...) +// CHECK: musttail call void (%"struct.cdecl_inalloca::C"*, ...)* %{{.*}}(%"struct.cdecl_inalloca::C"* %{{.*}}, ...) +// CHECK-NEXT: ret void diff --git a/test/CodeGenCXX/microsoft-abi-vmemptr-fastcall.cpp b/test/CodeGenCXX/microsoft-abi-vmemptr-fastcall.cpp new file mode 100644 index 000000000000..6d42b8504abf --- /dev/null +++ b/test/CodeGenCXX/microsoft-abi-vmemptr-fastcall.cpp @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 -fms-extensions -triple i686-pc-windows-msvc %s -emit-llvm-only -verify + +// We reject this because LLVM doesn't forward the second regparm through the +// thunk. + +struct A { + virtual void __fastcall f(int a, int b); // expected-error {{cannot compile this pointer to fastcall virtual member function yet}} +}; +void (__fastcall A::*doit())(int, int) { + return &A::f; +} diff --git a/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance-return-adjustment.cpp b/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance-return-adjustment.cpp index 2d0bf6362296..232c0d9c4dd8 100644 --- a/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance-return-adjustment.cpp +++ b/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance-return-adjustment.cpp @@ -295,3 +295,70 @@ struct X : E { void build_vftable(X *obj) { obj->foo(); } } + +namespace test7 { +struct A { + virtual A *f() = 0; +}; +struct B { + virtual void g(); +}; +struct C : B, A { + virtual void g(); + virtual C *f() = 0; + // CHECK-LABEL: VFTable for 'test7::B' in 'test7::C' (1 entry). + // CHECK-NEXT: 0 | void test7::C::g() + + // CHECK-LABEL: VFTable for 'test7::A' in 'test7::C' (2 entries). + // CHECK-NEXT: 0 | test7::C *test7::C::f() [pure] + // CHECK-NEXT: 1 | test7::C *test7::C::f() [pure] + + // No return adjusting thunks needed for pure virtual methods. + // CHECK-NOT: Thunks for 'test7::C *test7::C::f()' +}; + +void build_vftable(C *obj) { obj->g(); } +} + +namespace pr20444 { +struct A { + virtual A* f(); +}; +struct B { + virtual B* f(); +}; +struct C : A, B { + virtual C* f(); + // CHECK-LABEL: VFTable for 'pr20444::A' in 'pr20444::C' (1 entry). + // CHECK-NEXT: 0 | pr20444::C *pr20444::C::f() + + // CHECK-LABEL: VFTable for 'pr20444::B' in 'pr20444::C' (2 entries). + // CHECK-NEXT: 0 | pr20444::C *pr20444::C::f() + // CHECK-NEXT: [return adjustment (to type 'struct pr20444::B *'): 4 non-virtual] + // CHECK-NEXT: [this adjustment: -4 non-virtual] + // CHECK-NEXT: 1 | pr20444::C *pr20444::C::f() + // CHECK-NEXT: [return adjustment (to type 'struct pr20444::C *'): 0 non-virtual] + // CHECK-NEXT: [this adjustment: -4 non-virtual] +}; + +void build_vftable(C *obj) { obj->f(); } + +struct D : C { + virtual D* f(); + // CHECK-LABEL: VFTable for 'pr20444::A' in 'pr20444::C' in 'pr20444::D' (1 entry). + // CHECK-NEXT: 0 | pr20444::D *pr20444::D::f() + + // CHECK-LABEL: VFTable for 'pr20444::B' in 'pr20444::C' in 'pr20444::D' (3 entries). + // CHECK-NEXT: 0 | pr20444::D *pr20444::D::f() + // CHECK-NEXT: [return adjustment (to type 'struct pr20444::B *'): 4 non-virtual] + // CHECK-NEXT: [this adjustment: -4 non-virtual] + // CHECK-NEXT: 1 | pr20444::D *pr20444::D::f() + // CHECK-NEXT: [return adjustment (to type 'struct pr20444::C *'): 0 non-virtual] + // CHECK-NEXT: [this adjustment: -4 non-virtual] + // CHECK-NEXT: 2 | pr20444::D *pr20444::D::f() + // CHECK-NEXT: [return adjustment (to type 'struct pr20444::D *'): 0 non-virtual] + // CHECK-NEXT: [this adjustment: -4 non-virtual] +}; + +void build_vftable(D *obj) { obj->f(); } +} diff --git a/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance-this-adjustment.cpp b/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance-this-adjustment.cpp index 957980aa95ec..d71f40a5ecc6 100644 --- a/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance-this-adjustment.cpp +++ b/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance-this-adjustment.cpp @@ -1,6 +1,6 @@ // RUN: %clang_cc1 %s -fno-rtti -triple=i386-pc-win32 -emit-llvm -o %t.ll -fdump-vtable-layouts >%t // RUN: FileCheck %s < %t -// RUN: FileCheck --check-prefix=MANGLING %s < %t.ll +// RUN: FileCheck --check-prefix=BITCODE %s < %t.ll namespace test1 { struct A { @@ -29,8 +29,8 @@ struct X : A, B { // CHECK-LABEL: VFTable indices for 'test1::X' (1 entry). // CHECK-NEXT: 0 | void test1::X::g() - // MANGLING-DAG: @"\01??_7X@test1@@6BA@1@@" - // MANGLING-DAG: @"\01??_7X@test1@@6BB@1@@" + // BITCODE-DAG: @"\01??_7X@test1@@6BA@1@@" + // BITCODE-DAG: @"\01??_7X@test1@@6BB@1@@" virtual void g(); } x; @@ -71,9 +71,9 @@ struct X : A, B, C { // CHECK-NEXT: via vfptr at offset 4 // CHECK-NEXT: 0 | void test2::X::g() - // MANGLING-DAG: @"\01??_7X@test2@@6BA@1@@" - // MANGLING-DAG: @"\01??_7X@test2@@6BB@1@@" - // MANGLING-DAG: @"\01??_7X@test2@@6BC@1@@" + // BITCODE-DAG: @"\01??_7X@test2@@6BA@1@@" + // BITCODE-DAG: @"\01??_7X@test2@@6BB@1@@" + // BITCODE-DAG: @"\01??_7X@test2@@6BC@1@@" virtual void g(); } x; @@ -138,3 +138,42 @@ struct X: C, D { void build_vftable(X *obj) { obj->g(); } } + +namespace test4 { +struct A { + virtual void foo(); +}; +struct B { + virtual int filler(); + virtual int operator-(); + virtual int bar(); +}; +struct C : public A, public B { + virtual int filler(); + virtual int operator-(); + virtual int bar(); +}; + +// BITCODE-LABEL: define {{.*}}\01?ffun@test4@@YAXAAUC@1@@Z +void ffun(C &c) { + // BITCODE: load + // BITCODE: bitcast + // BITCODE: bitcast + // BITCODE: [[THIS1:%.+]] = bitcast %"struct.test4::C"* {{.*}} to i8* + // BITCODE: [[THIS2:%.+]] = getelementptr inbounds i8* [[THIS1]], i32 4 + // BITCODE-NEXT: call x86_thiscallcc {{.*}}(i8* [[THIS2]]) + c.bar(); +} + +// BITCODE-LABEL: define {{.*}}\01?fop@test4@@YAXAAUC@1@@Z +void fop(C &c) { + // BITCODE: load + // BITCODE: bitcast + // BITCODE: bitcast + // BITCODE: [[THIS1:%.+]] = bitcast %"struct.test4::C"* {{.*}} to i8* + // BITCODE: [[THIS2:%.+]] = getelementptr inbounds i8* [[THIS1]], i32 4 + // BITCODE-NEXT: call x86_thiscallcc {{.*}}(i8* [[THIS2]]) + -c; +} + +} diff --git a/test/CodeGenCXX/microsoft-abi-vtables-return-thunks.cpp b/test/CodeGenCXX/microsoft-abi-vtables-return-thunks.cpp index a4a21106c685..072cb956035f 100644 --- a/test/CodeGenCXX/microsoft-abi-vtables-return-thunks.cpp +++ b/test/CodeGenCXX/microsoft-abi-vtables-return-thunks.cpp @@ -104,3 +104,27 @@ K::K() {} // GLOBALS-LABEL: @"\01??_7K@test2@@6B@" = linkonce_odr unnamed_addr constant [3 x i8*] } + +namespace pr20479 { +struct A { + virtual A *f(); +}; + +struct B : virtual A { + virtual B *f(); +}; + +struct C : virtual A, B { +// VFTABLES-LABEL: VFTable for 'pr20479::A' in 'pr20479::B' in 'pr20479::C' (2 entries). +// VFTABLES-NEXT: 0 | pr20479::B *pr20479::B::f() +// VFTABLES-NEXT: [return adjustment (to type 'struct pr20479::A *'): vbase #1, 0 non-virtual] +// VFTABLES-NEXT: 1 | pr20479::B *pr20479::B::f() + C(); +}; + +C::C() {} + +// GLOBALS-LABEL: @"\01??_7C@pr20479@@6B@" = linkonce_odr unnamed_addr constant [2 x i8*] +// GLOBALS: @"\01?f@B@pr20479@@QAEPAUA@2@XZ" +// GLOBALS: @"\01?f@B@pr20479@@UAEPAU12@XZ" +} diff --git a/test/CodeGenCXX/microsoft-abi-vtables-single-inheritance.cpp b/test/CodeGenCXX/microsoft-abi-vtables-single-inheritance.cpp index d453f5c55aed..baed35145f98 100644 --- a/test/CodeGenCXX/microsoft-abi-vtables-single-inheritance.cpp +++ b/test/CodeGenCXX/microsoft-abi-vtables-single-inheritance.cpp @@ -289,3 +289,13 @@ struct R : Q { R r; void use(R *obj) { obj->foo(42l); } + +struct S { + // CHECK-LABEL: VFTable for 'S' (1 entry). + // CHECK-NEXT: 0 | void S::f() [deleted] + virtual void f() = delete; + S(); + // EMITS-VFTABLE-DAG: @"\01??_7S@@6B@" = linkonce_odr unnamed_addr constant [1 x i8*] [i8* bitcast (void ()* @_purecall to i8*)] +}; + +S::S() {} diff --git a/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance-vtordisps.cpp b/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance-vtordisps.cpp index f63808a89873..1f6d4202154a 100644 --- a/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance-vtordisps.cpp +++ b/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance-vtordisps.cpp @@ -32,8 +32,8 @@ struct V4 : Z, V1, V2 { void use_somewhere_else(void*); namespace simple { -// In case of a single-layer virtual inheritance, the "this" adjustment is done -// staically: +// In case of a single-layer virtual inheritance, the "this" adjustment for a +// virtual method is done staically: // struct A { // virtual void f(); // Expects "(A*)this" in ECX // }; @@ -48,9 +48,9 @@ namespace simple { // current class layout and the most derived class layout are different. // This is done using vtordisp thunks. // -// A simple vtordisp{A,B} thunk for Method@Class is something like: -// sub ecx, [ecx+A] // apply the vtordisp adjustment -// sub ecx, B // apply the subobject adjustment, if needed. +// A simple vtordisp{x,y} thunk for Method@Class is something like: +// sub ecx, [ecx+x] // apply the vtordisp adjustment +// sub ecx, y // apply the subobject adjustment, if needed. // jmp Method@Class struct A : virtual V1 { @@ -227,12 +227,12 @@ namespace extended { // In this case, we should use the extended form of vtordisp thunks, called // vtordispex thunks. // -// vtordispex{A,B,C,D} thunk for Method@Class is something like: -// sub ecx, [ecx+C] // apply the vtordisp adjustment -// sub ecx, A // jump to the vbtable of the most derived class +// vtordispex{x,y,z,w} thunk for Method@Class is something like: +// sub ecx, [ecx+z] // apply the vtordisp adjustment +// sub ecx, x // jump to the vbptr of the most derived class // mov eax, [ecx] // load the vbtable address -// add ecx, [eax+B] // lookup the final overrider's vbase offset -// add ecx, D // apphy the subobject offset if needed +// add ecx, [eax+y] // lookup the final overrider's vbase offset +// add ecx, w // apphy the subobject offset if needed // jmp Method@Class struct A : virtual simple::A { diff --git a/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance.cpp b/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance.cpp index 4ce4e9c2e17e..65d6a9d90e6d 100644 --- a/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance.cpp +++ b/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fno-rtti -emit-llvm -o %t.ll -fdump-vtable-layouts %s -triple=i386-pc-win32 >%t +// RUN: %clang_cc1 -std=c++11 -fms-extensions -fno-rtti -emit-llvm -o %t.ll -fdump-vtable-layouts %s -triple=i386-pc-win32 >%t // RUN: FileCheck %s < %t // RUN: FileCheck --check-prefix=MANGLING %s < %t.ll @@ -764,3 +764,46 @@ struct W : B, Y { W::W() {} } + +namespace Test13 { +struct A { + virtual void f(); +}; +struct __declspec(dllexport) B : virtual A { + virtual void f() = 0; + // MANGLING-DAG: @"\01??_7B@Test13@@6B@" = weak_odr dllexport unnamed_addr constant [1 x i8*] [i8* bitcast (void ()* @_purecall to i8*)] +}; +} + +namespace pr21031_1 { +// This ordering of base specifiers regressed in r202425. +struct A { virtual void f(void); }; +struct B : virtual A { virtual void g(void); }; +struct C : virtual A, B { C(); }; +C::C() {} + +// CHECK-LABEL: VFTable for 'pr21031_1::A' in 'pr21031_1::B' in 'pr21031_1::C' (1 entry) +// CHECK-NEXT: 0 | void pr21031_1::A::f() + +// CHECK-LABEL: VFTable for 'pr21031_1::B' in 'pr21031_1::C' (1 entry) +// CHECK-NEXT: 0 | void pr21031_1::B::g() + +// MANGLING-DAG: @"\01??_7C@pr21031_1@@6BB@1@@" = {{.*}} constant [1 x i8*] +// MANGLING-DAG: @"\01??_7C@pr21031_1@@6B@" = {{.*}} constant [1 x i8*] +} + +namespace pr21031_2 { +struct A { virtual void f(void); }; +struct B : virtual A { virtual void g(void); }; +struct C : B, virtual A { C(); }; +C::C() {} + +// CHECK-LABEL: VFTable for 'pr21031_2::B' in 'pr21031_2::C' (1 entry) +// CHECK-NEXT: 0 | void pr21031_2::B::g() + +// CHECK-LABEL: VFTable for 'pr21031_2::A' in 'pr21031_2::B' in 'pr21031_2::C' (1 entry) +// CHECK-NEXT: 0 | void pr21031_2::A::f() + +// MANGLING-DAG: @"\01??_7C@pr21031_2@@6BA@1@@" = {{.*}} constant [1 x i8*] +// MANGLING-DAG: @"\01??_7C@pr21031_2@@6BB@1@@" = {{.*}} constant [1 x i8*] +} diff --git a/test/CodeGenCXX/microsoft-interface.cpp b/test/CodeGenCXX/microsoft-interface.cpp index c030d1d0b3b5..ec558a408178 100644 --- a/test/CodeGenCXX/microsoft-interface.cpp +++ b/test/CodeGenCXX/microsoft-interface.cpp @@ -34,7 +34,7 @@ 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 i8** getelementptr inbounds ([3 x i8*]* @_ZTV1S, i64 0, i64 2), i8*** %{{[.0-9A-Z_a-z]+}} +// CHECK: store i32 (...)** bitcast (i8** getelementptr inbounds ([3 x i8*]* @_ZTV1S, i64 0, i64 2) to i32 (...)**), i32 (...)*** %{{[.0-9A-Z_a-z]+}} // CHECK-LABEL: define linkonce_odr x86_thiscallcc void @_ZN1IC2Ev(%__interface.I* %this) -// CHECK: store i8** getelementptr inbounds ([3 x i8*]* @_ZTV1I, i64 0, i64 2), i8*** %{{[.0-9A-Z_a-z]+}} +// CHECK: store i32 (...)** bitcast (i8** getelementptr inbounds ([3 x i8*]* @_ZTV1I, i64 0, i64 2) to i32 (...)**), i32 (...)*** %{{[.0-9A-Z_a-z]+}} diff --git a/test/CodeGenCXX/microsoft-no-rtti-data.cpp b/test/CodeGenCXX/microsoft-no-rtti-data.cpp index d4002c28b1a2..fded4c91e4f1 100644 --- a/test/CodeGenCXX/microsoft-no-rtti-data.cpp +++ b/test/CodeGenCXX/microsoft-no-rtti-data.cpp @@ -1,6 +1,7 @@ // RUN: %clang_cc1 %s -fno-rtti-data -triple=i386-pc-win32 -o - -emit-llvm | FileCheck %s // vftable shouldn't have RTTI data in it. +// CHECK-NOT: @"\01??_R4S@@6B@" // CHECK: @"\01??_7S@@6B@" = linkonce_odr unnamed_addr constant [1 x i8*] [i8* bitcast ({{.*}} @"\01??_GS@@UAEPAXI@Z" to i8*)] struct type_info; diff --git a/test/CodeGenCXX/microsoft-uuidof-mangling.cpp b/test/CodeGenCXX/microsoft-uuidof-mangling.cpp new file mode 100644 index 000000000000..9019aa8c9217 --- /dev/null +++ b/test/CodeGenCXX/microsoft-uuidof-mangling.cpp @@ -0,0 +1,48 @@ +// RUN: %clang_cc1 -emit-llvm %s -o - -triple x86_64-unknown-unknown -fms-extensions | FileCheck %s +// rdar://17784718 + +typedef struct _GUID +{ + unsigned int Data1; + unsigned short Data2; + unsigned short Data3; + unsigned char Data4[ 8 ]; +} GUID; + + +template < typename T, const GUID & T_iid = __uuidof(T)> +class UUIDTest +{ +public: + UUIDTest() { } +}; + +struct __declspec(uuid("EAFA1952-66F8-438B-8FBA-AF1BBAE42191")) TestStruct +{ + int foo; +}; + +template <class T> void test_uuidofType(void *arg[sizeof(__uuidof(T))] = 0) {} + +template <class T> void test_uuidofExpr(void *arg[sizeof(__uuidof(T::member))] = 0) {} + +struct HasMember { typedef TestStruct member; }; + +int main(int argc, const char * argv[]) +{ + + UUIDTest<TestStruct> uuidof_test; + test_uuidofType<TestStruct>(); + test_uuidofExpr<HasMember>(); + return 0; +} + +// CHECK: define i32 @main +// CHECK: call void @_ZN8UUIDTestI10TestStructXu8__uuidoftS0_EEC1Ev +// CHECK: call void @_Z15test_uuidofTypeI10TestStructEvPPv(i8** null) +// CHECK: call void @_Z15test_uuidofExprI9HasMemberEvPPv(i8** null) + +// CHECK: define linkonce_odr void @_ZN8UUIDTestI10TestStructXu8__uuidoftS0_EEC1Ev +// CHECK: define linkonce_odr void @_Z15test_uuidofTypeI10TestStructEvPPv +// CHECK: define linkonce_odr void @_Z15test_uuidofExprI9HasMemberEvPPv +// CHECK: define linkonce_odr void @_ZN8UUIDTestI10TestStructXu8__uuidoftS0_EEC2Ev diff --git a/test/CodeGenCXX/mingw-w64-seh-exceptions.cpp b/test/CodeGenCXX/mingw-w64-seh-exceptions.cpp new file mode 100644 index 000000000000..bacddb2936f4 --- /dev/null +++ b/test/CodeGenCXX/mingw-w64-seh-exceptions.cpp @@ -0,0 +1,24 @@ +// RUN: %clang_cc1 %s -fexceptions -emit-llvm -triple x86_64-w64-windows-gnu -o - | FileCheck %s --check-prefix=X64 +// RUN: %clang_cc1 %s -fexceptions -emit-llvm -triple i686-w64-windows-gnu -o - | FileCheck %s --check-prefix=X86 + +extern "C" void foo(); +extern "C" void bar(); + +struct Cleanup { + ~Cleanup() { + bar(); + } +}; + +extern "C" void test() { + Cleanup x; + foo(); +} + +// X64: define void @test() +// X64: invoke void @foo() +// X64: landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_seh0 to i8*) + +// X86: define void @test() +// X86: invoke void @foo() +// X86: landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) diff --git a/test/CodeGenCXX/ms-inline-asm-return.cpp b/test/CodeGenCXX/ms-inline-asm-return.cpp new file mode 100644 index 000000000000..26fc426e5fc2 --- /dev/null +++ b/test/CodeGenCXX/ms-inline-asm-return.cpp @@ -0,0 +1,100 @@ +// REQUIRES: x86-registered-target +// RUN: %clang_cc1 %s -triple i686-pc-windows-msvc -emit-llvm -o - -fasm-blocks | FileCheck %s + +// Check that we take EAX or EAX:EDX and return it from these functions for MSVC +// compatibility. + +extern "C" { + +long long f_i64() { + __asm { + mov eax, 1 + mov edx, 1 + } +} +// CHECK-LABEL: define i64 @f_i64() +// CHECK: %[[r:[^ ]*]] = call i64 asm sideeffect inteldialect "mov eax, $$1\0A\09mov edx, $$1", "=A,~{eax},{{.*}}" +// CHECK: ret i64 %[[r]] + +int f_i32() { + __asm { + mov eax, 1 + mov edx, 1 + } +} +// CHECK-LABEL: define i32 @f_i32() +// CHECK: %[[r:[^ ]*]] = call i32 asm sideeffect inteldialect "mov eax, $$1\0A\09mov edx, $$1", "={eax},~{eax},{{.*}}" +// CHECK: ret i32 %[[r]] + +short f_i16() { + __asm { + mov eax, 1 + mov edx, 1 + } +} +// CHECK-LABEL: define signext i16 @f_i16() +// CHECK: %[[r:[^ ]*]] = call i32 asm sideeffect inteldialect "mov eax, $$1\0A\09mov edx, $$1", "={eax},~{eax},{{.*}}" +// CHECK: %[[r_i16:[^ ]*]] = trunc i32 %[[r]] to i16 +// CHECK: ret i16 %[[r_i16]] + +char f_i8() { + __asm { + mov eax, 1 + mov edx, 1 + } +} +// CHECK-LABEL: define signext i8 @f_i8() +// CHECK: %[[r:[^ ]*]] = call i32 asm sideeffect inteldialect "mov eax, $$1\0A\09mov edx, $$1", "={eax},~{eax},{{.*}}" +// CHECK: %[[r_i8:[^ ]*]] = trunc i32 %[[r]] to i8 +// CHECK: ret i8 %[[r_i8]] + +bool f_i1() { + __asm { + mov eax, 1 + mov edx, 1 + } +} +// CHECK-LABEL: define zeroext i1 @f_i1() +// CHECK: %[[r:[^ ]*]] = call i32 asm sideeffect inteldialect "mov eax, $$1\0A\09mov edx, $$1", "={eax},~{eax},{{.*}}" +// CHECK: %[[r_i8:[^ ]*]] = trunc i32 %[[r]] to i8 +// CHECK: store i8 %[[r_i8]], i8* %{{.*}} +// CHECK: %[[r_i1:[^ ]*]] = load i1* %{{.*}} +// CHECK: ret i1 %[[r_i1]] + +struct FourChars { + char a, b, c, d; +}; +FourChars f_s4() { + __asm { + mov eax, 0x01010101 + } +} +// CHECK-LABEL: define i32 @f_s4() +// CHECK: %[[r:[^ ]*]] = call i32 asm sideeffect inteldialect "mov eax, $$0x01010101", "={eax},~{eax},{{.*}}" +// CHECK: store i32 %[[r]], i32* %{{.*}} +// CHECK: %[[r_i32:[^ ]*]] = load i32* %{{.*}} +// CHECK: ret i32 %[[r_i32]] + +struct EightChars { + char a, b, c, d, e, f, g, h; +}; +EightChars f_s8() { + __asm { + mov eax, 0x01010101 + mov edx, 0x01010101 + } +} +// CHECK-LABEL: define i64 @f_s8() +// CHECK: %[[r:[^ ]*]] = call i64 asm sideeffect inteldialect "mov eax, $$0x01010101\0A\09mov edx, $$0x01010101", "=A,~{eax},{{.*}}" +// CHECK: store i64 %[[r]], i64* %{{.*}} +// CHECK: %[[r_i64:[^ ]*]] = load i64* %{{.*}} +// CHECK: ret i64 %[[r_i64]] + +} // extern "C" + +int main() { + __asm xor eax, eax +} +// CHECK-LABEL: define i32 @main() +// CHECK: %[[r:[^ ]*]] = call i32 asm sideeffect inteldialect "xor eax, eax", "={eax},{{.*}}" +// CHECK: ret i32 %[[r]] diff --git a/test/CodeGenCXX/ms-integer-static-data-members-exported.cpp b/test/CodeGenCXX/ms-integer-static-data-members-exported.cpp index 3f868f36ff66..78bb3a2b1afa 100644 --- a/test/CodeGenCXX/ms-integer-static-data-members-exported.cpp +++ b/test/CodeGenCXX/ms-integer-static-data-members-exported.cpp @@ -17,6 +17,6 @@ struct __declspec(dllexport) S { }; }; -// CHECK: @"\01?x@S@@2FB" = weak_odr dllexport constant i16 42, align 2 -// CHECK: @"\01?y@S@@2W4Enum@@B" = weak_odr dllexport constant i32 2, align 4 +// CHECK: @"\01?x@S@@2FB" = weak_odr dllexport constant i16 42, comdat, align 2 +// CHECK: @"\01?y@S@@2W4Enum@@B" = weak_odr dllexport constant i32 2, comdat, align 4 // CHECK-NOT: NonExported diff --git a/test/CodeGenCXX/ms-integer-static-data-members.cpp b/test/CodeGenCXX/ms-integer-static-data-members.cpp index b02b679d71a1..4965f7319187 100644 --- a/test/CodeGenCXX/ms-integer-static-data-members.cpp +++ b/test/CodeGenCXX/ms-integer-static-data-members.cpp @@ -26,7 +26,7 @@ const int S::x = 5; // Inline initialization. -// CHECK-INLINE: @"\01?x@S@@2HB" = linkonce_odr constant i32 5, align 4 +// CHECK-INLINE: @"\01?x@S@@2HB" = linkonce_odr constant i32 5, comdat, align 4 // Out-of-line initialization. // CHECK-OUTOFLINE: @"\01?x@S@@2HB" = constant i32 5, align 4 diff --git a/test/CodeGenCXX/ms-thread_local.cpp b/test/CodeGenCXX/ms-thread_local.cpp new file mode 100644 index 000000000000..c29473fd6fca --- /dev/null +++ b/test/CodeGenCXX/ms-thread_local.cpp @@ -0,0 +1,28 @@ +// RUN: %clang_cc1 %s -std=c++1y -triple=i686-pc-win32 -emit-llvm -o - | FileCheck %s + +struct A { + A(); + ~A(); +}; + +// CHECK-DAG: $"\01??$a@X@@3UA@@A" = comdat any +// CHECK-DAG: @"\01??$a@X@@3UA@@A" = linkonce_odr thread_local global %struct.A zeroinitializer, comdat, align 1 +// CHECK-DAG: @"\01??__E?$a@X@@YAXXZ$initializer$" = internal constant void ()* @"\01??__E?$a@X@@YAXXZ", section ".CRT$XDU", comdat($"\01??$a@X@@3UA@@A") +template <typename T> +thread_local A a = A(); + +// CHECK-DAG: @"\01?b@@3UA@@A" = thread_local global %struct.A zeroinitializer, align 1 +// CHECK-DAG: @"__tls_init$initializer$" = internal constant void ()* @__tls_init, section ".CRT$XDU" +thread_local A b; + +// CHECK-LABEL: define internal void @__tls_init() +// CHECK: call void @"\01??__Eb@@YAXXZ" + +thread_local A &c = b; +thread_local A &d = c; + +A f() { + (void)a<void>; + (void)b; + return c; +} diff --git a/test/CodeGenCXX/nrvo-noreturn.cc b/test/CodeGenCXX/nrvo-noreturn.cpp index a8259cab5f30..a8259cab5f30 100644 --- a/test/CodeGenCXX/nrvo-noreturn.cc +++ b/test/CodeGenCXX/nrvo-noreturn.cpp diff --git a/test/CodeGenCXX/optnone-def-decl.cpp b/test/CodeGenCXX/optnone-def-decl.cpp new file mode 100644 index 000000000000..ab6eb3f32e11 --- /dev/null +++ b/test/CodeGenCXX/optnone-def-decl.cpp @@ -0,0 +1,94 @@ +// RUN: %clang_cc1 %s -triple %itanium_abi_triple -fms-extensions -emit-llvm -o - | FileCheck %s + +// Test optnone on both function declarations and function definitions. +// Verify also that we don't generate invalid IR functions with +// both alwaysinline and noinline. (optnone implies noinline and wins +// over alwaysinline, in all cases.) + +// Test optnone on extern declaration only. +extern int decl_only(int a) __attribute__((optnone)); + +// This function should be marked 'optnone'. +int decl_only(int a) { + return a + a + a + a; +} + +// CHECK: define {{.*}} @_Z9decl_onlyi({{.*}}) [[OPTNONE:#[0-9]+]] + +// Test optnone on definition but not extern declaration. +extern int def_only(int a); + +__attribute__((optnone)) +int def_only(int a) { + return a + a + a + a; +} + +// Function def_only is a optnone function and therefore it should not be +// inlined inside 'user_of_def_only'. +int user_of_def_only() { + return def_only(5); +} + +// CHECK: define {{.*}} @_Z8def_onlyi({{.*}}) [[OPTNONE]] +// CHECK: define {{.*}} @_Z16user_of_def_onlyv() [[NORMAL:#[0-9]+]] + +// Test optnone on both definition and declaration. +extern int def_and_decl(int a) __attribute__((optnone)); + +__attribute__((optnone)) +int def_and_decl(int a) { + return a + a + a + a; +} + +// CHECK: define {{.*}} @_Z12def_and_decli({{.*}}) [[OPTNONE]] + +// Check that optnone wins over always_inline. + +// Test optnone on definition and always_inline on declaration. +extern int always_inline_function(int a) __attribute__((always_inline)); + +__attribute__((optnone)) +extern int always_inline_function(int a) { + return a + a + a + a; +} +// CHECK: define {{.*}} @_Z22always_inline_functioni({{.*}}) [[OPTNONE]] + +int user_of_always_inline_function() { + return always_inline_function(4); +} + +// CHECK: define {{.*}} @_Z30user_of_always_inline_functionv() [[NORMAL]] + +// Test optnone on declaration and always_inline on definition. +extern int optnone_function(int a) __attribute__((optnone)); + +__attribute__((always_inline)) +int optnone_function(int a) { + return a + a + a + a; +} +// CHECK: define {{.*}} @_Z16optnone_functioni({{.*}}) [[OPTNONE]] + +int user_of_optnone_function() { + return optnone_function(4); +} + +// CHECK: define {{.*}} @_Z24user_of_optnone_functionv() [[NORMAL]] + +// Test the combination of optnone with forceinline (optnone wins). +extern __forceinline int forceinline_optnone_function(int a, int b); + +__attribute__((optnone)) +extern int forceinline_optnone_function(int a, int b) { + return a + b; +} + +int user_of_forceinline_optnone_function() { + return forceinline_optnone_function(4,5); +} + +// CHECK: @_Z36user_of_forceinline_optnone_functionv() [[NORMAL]] +// CHECK: @_Z28forceinline_optnone_functionii({{.*}}) [[OPTNONE]] + +// CHECK: attributes [[OPTNONE]] = { noinline nounwind optnone {{.*}} } +// CHECK: attributes [[NORMAL]] = { nounwind {{.*}} } + diff --git a/test/CodeGenCXX/pod-member-memcpys.cpp b/test/CodeGenCXX/pod-member-memcpys.cpp index 31d774c5345e..a3ee990bf319 100644 --- a/test/CodeGenCXX/pod-member-memcpys.cpp +++ b/test/CodeGenCXX/pod-member-memcpys.cpp @@ -67,6 +67,13 @@ struct BitfieldMember2 { NonPOD np; }; +struct BitfieldMember3 { + virtual void f(); + int : 8; + int x : 1; + int y; +}; + struct InnerClassMember { struct { int a, b, c, d; @@ -174,6 +181,7 @@ CALL_AO(PackedMembers) CALL_CC(PackedMembers) CALL_CC(BitfieldMember2) +CALL_CC(BitfieldMember3) CALL_CC(ReferenceMember) CALL_CC(InnerClassMember) CALL_CC(BitfieldMember) @@ -243,6 +251,11 @@ CALL_CC(Basic) // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 16, i32 8{{.*}}) // CHECK: ret void +// BitfieldMember3 copy-constructor: +// CHECK-LABEL: define linkonce_odr void @_ZN15BitfieldMember3C2ERKS_(%struct.BitfieldMember3* %this, %struct.BitfieldMember3* dereferenceable({{[0-9]+}})) +// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 8, i32 8, i1 false) +// CHECK: ret void + // BitfieldMember2 copy-constructor: // CHECK-2-LABEL: define linkonce_odr void @_ZN15BitfieldMember2C2ERKS_(%struct.BitfieldMember2* %this, %struct.BitfieldMember2* dereferenceable({{[0-9]+}})) // CHECK-2: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 16, i32 4, i1 false) diff --git a/test/CodeGenCXX/pointers-to-data-members.cpp b/test/CodeGenCXX/pointers-to-data-members.cpp index 745cf18fce21..0b99fea8fc57 100644 --- a/test/CodeGenCXX/pointers-to-data-members.cpp +++ b/test/CodeGenCXX/pointers-to-data-members.cpp @@ -55,7 +55,7 @@ namespace ZeroInit { }; struct C : A, B { int j; }; - // CHECK-GLOBAL: @_ZN8ZeroInit1cE = global {{%.*}} { %"struct.ZeroInit::A" { i64 -1, i32 0 }, %"struct.ZeroInit::B" { [10 x %"struct.ZeroInit::A"] [%"struct.ZeroInit::A" { i64 -1, i32 0 }, %"struct.ZeroInit::A" { i64 -1, i32 0 }, %"struct.ZeroInit::A" { i64 -1, i32 0 }, %"struct.ZeroInit::A" { i64 -1, i32 0 }, %"struct.ZeroInit::A" { i64 -1, i32 0 }, %"struct.ZeroInit::A" { i64 -1, i32 0 }, %"struct.ZeroInit::A" { i64 -1, i32 0 }, %"struct.ZeroInit::A" { i64 -1, i32 0 }, %"struct.ZeroInit::A" { i64 -1, i32 0 }, %"struct.ZeroInit::A" { i64 -1, i32 0 }], i8 0, i64 -1 }, i32 0 }, align 8 + // CHECK-GLOBAL: @_ZN8ZeroInit1cE = global {{%.*}} <{ %"struct.ZeroInit::A" { i64 -1, i32 0 }, %"struct.ZeroInit::B" { [10 x %"struct.ZeroInit::A"] [%"struct.ZeroInit::A" { i64 -1, i32 0 }, %"struct.ZeroInit::A" { i64 -1, i32 0 }, %"struct.ZeroInit::A" { i64 -1, i32 0 }, %"struct.ZeroInit::A" { i64 -1, i32 0 }, %"struct.ZeroInit::A" { i64 -1, i32 0 }, %"struct.ZeroInit::A" { i64 -1, i32 0 }, %"struct.ZeroInit::A" { i64 -1, i32 0 }, %"struct.ZeroInit::A" { i64 -1, i32 0 }, %"struct.ZeroInit::A" { i64 -1, i32 0 }, %"struct.ZeroInit::A" { i64 -1, i32 0 }], i8 0, i64 -1 }, i32 0, [4 x i8] zeroinitializer }>, align 8 C c; } @@ -255,4 +255,26 @@ namespace PR13097 { // CHECK: call void @_ZN7PR130971XC1ERKS0_ } +namespace PR21089 { +struct A { + bool : 1; + int A::*x; + bool y; + A(); +}; +struct B : A { +}; +B b; +// CHECK-GLOBAL: @_ZN7PR210891bE = global %"struct.PR21089::B" { %"struct.PR21089::A.base" <{ i8 0, [7 x i8] zeroinitializer, i64 -1, i8 0 }>, [7 x i8] zeroinitializer }, align 8 +} + +namespace PR21282 { +union U { + int U::*x; + long y[2]; +}; +U u; +// CHECK-GLOBAL: @_ZN7PR212821uE = global %"union.PR21282::U" { i64 -1, [8 x i8] zeroinitializer }, align 8 +} + // CHECK-O3: attributes [[NUW]] = { nounwind readnone{{.*}} } diff --git a/test/CodeGenCXX/pr12251.cpp b/test/CodeGenCXX/pr12251.cpp index bb1c82dc8153..5b1ef9a31d24 100644 --- a/test/CodeGenCXX/pr12251.cpp +++ b/test/CodeGenCXX/pr12251.cpp @@ -18,14 +18,14 @@ e1 g1(e1 *x) { return *x; } // CHECK-LABEL: define i32 @_Z2g1P2e1 -// CHECK: load i32* %x, align 4, !range [[RANGE_i32_0_1:![^ ]*]] +// CHECK: ret i32 0 enum e2 { e2_a = 0 }; e2 g2(e2 *x) { return *x; } // CHECK-LABEL: define i32 @_Z2g2P2e2 -// CHECK: load i32* %x, align 4, !range [[RANGE_i32_0_1]] +// CHECK: ret i32 0 enum e3 { e3_a = 16 }; e3 g3(e3 *x) { @@ -136,11 +136,10 @@ e16 g16(e16 *x) { // CHECK: ret -// CHECK: [[RANGE_i8_0_2]] = metadata !{i8 0, i8 2} -// CHECK: [[RANGE_i32_0_1]] = metadata !{i32 0, i32 1} -// CHECK: [[RANGE_i32_0_32]] = metadata !{i32 0, i32 32} -// CHECK: [[RANGE_i32_m16_16]] = metadata !{i32 -16, i32 16} -// CHECK: [[RANGE_i32_m32_32]] = metadata !{i32 -32, i32 32} -// CHECK: [[RANGE_i32_m1_1]] = metadata !{i32 -1, i32 1} -// CHECK: [[RANGE_i32_m64_64]] = metadata !{i32 -64, i32 64} -// CHECK: [[RANGE_i64_0_2pow33]] = metadata !{i64 0, i64 8589934592} +// CHECK: [[RANGE_i8_0_2]] = !{i8 0, i8 2} +// CHECK: [[RANGE_i32_0_32]] = !{i32 0, i32 32} +// CHECK: [[RANGE_i32_m16_16]] = !{i32 -16, i32 16} +// CHECK: [[RANGE_i32_m32_32]] = !{i32 -32, i32 32} +// CHECK: [[RANGE_i32_m1_1]] = !{i32 -1, i32 1} +// CHECK: [[RANGE_i32_m64_64]] = !{i32 -64, i32 64} +// CHECK: [[RANGE_i64_0_2pow33]] = !{i64 0, i64 8589934592} diff --git a/test/CodeGenCXX/pr18635.cpp b/test/CodeGenCXX/pr18635.cpp new file mode 100644 index 000000000000..94b5e4599956 --- /dev/null +++ b/test/CodeGenCXX/pr18635.cpp @@ -0,0 +1,22 @@ +// RUN: %clang_cc1 -emit-llvm -std=c++11 -triple x86_64-pc-linux-gnu -o- %s | FileCheck %s + +// Global @x: +// CHECK: [[X_GLOBAL:@[^ ]+]]{{.*}}thread_local global + +// returned somewhere in TLS wrapper: +// CHECK: ret{{.*}}[[X_GLOBAL]] + +template <typename T> class unique_ptr { + template <typename F, typename S> struct pair { + F first; + S second; + }; + pair<T *, int> data; +public: + constexpr unique_ptr() noexcept : data() {} + explicit unique_ptr(T *p) noexcept : data() {} +}; + +thread_local unique_ptr<int> x; +int main() { x = unique_ptr<int>(new int(5)); } + diff --git a/test/CodeGenCXX/pr18962.cpp b/test/CodeGenCXX/pr18962.cpp index ab537b4928e3..9e6ef169cd10 100644 --- a/test/CodeGenCXX/pr18962.cpp +++ b/test/CodeGenCXX/pr18962.cpp @@ -26,7 +26,7 @@ fn2(C *) { // We end up using an opaque type for 'append' to avoid circular references. // CHECK: %class.A = type { {}* } -// CHECK: %class.C = type { %class.D*, %class.B } +// CHECK: %class.C = type <{ %class.D*, %class.B, [3 x i8] }> // CHECK: %class.D = type { %class.C.base, [3 x i8] } // CHECK: %class.C.base = type <{ %class.D*, %class.B }> // CHECK: %class.B = type { i8 } diff --git a/test/CodeGenCXX/pr20719.cpp b/test/CodeGenCXX/pr20719.cpp new file mode 100644 index 000000000000..208d11135847 --- /dev/null +++ b/test/CodeGenCXX/pr20719.cpp @@ -0,0 +1,35 @@ +// RUN: %clang_cc1 -triple i686-windows-msvc -emit-llvm -std=c++11 -o - %s | FileCheck %s + +// 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" + +template <typename> +struct H { + H() {} +}; + +template <typename Fx> +int K_void(const Fx &) { + H<Fx> callee; + return 0; +} +template <typename Fx> +int K_int(const Fx &) { + H<Fx> callee; + return 0; +} + +struct pair { + pair(int, int); +}; + +struct E1; + +template <typename> +void lep() { + pair x(K_void([] {}), K_int([] {})); +} + +auto z = lep<void>; diff --git a/test/CodeGenCXX/pr20897.cpp b/test/CodeGenCXX/pr20897.cpp new file mode 100644 index 000000000000..49d669bd7eab --- /dev/null +++ b/test/CodeGenCXX/pr20897.cpp @@ -0,0 +1,33 @@ +// RUN: %clang_cc1 -triple i686-windows-msvc -emit-llvm -std=c++1y -O0 -o - %s | FileCheck %s +struct Base {}; + +// __declspec(dllexport) causes us to export the implicit constructor. +struct __declspec(dllexport) Derived : virtual Base { +// CHECK-LABEL: define weak_odr dllexport x86_thiscallcc %struct.Derived* @"\01??0Derived@@QAE@ABU0@@Z" +// CHECK: %[[this:.*]] = load %struct.Derived** {{.*}} +// CHECK-NEXT: store %struct.Derived* %[[this]], %struct.Derived** %[[retval:.*]] +// CHECK: %[[dest_a_gep:.*]] = getelementptr inbounds %struct.Derived* %[[this]], i32 0, i32 1 +// CHECK-NEXT: %[[src_load:.*]] = load %struct.Derived** {{.*}} +// CHECK-NEXT: %[[src_a_gep:.*]] = getelementptr inbounds %struct.Derived* %[[src_load:.*]], i32 0, i32 1 +// CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* %[[dest_a_gep]], i8* %[[src_a_gep]], i64 1, i32 4, i1 false) +// CHECK-NEXT: %[[dest_this:.*]] = load %struct.Derived** %[[retval]] +// CHECK-NEXT: ret %struct.Derived* %[[dest_this]] + bool a : 1; + bool b : 1; +}; + +// __declspec(dllexport) causes us to export the implicit copy constructor. +struct __declspec(dllexport) Derived2 : virtual Base { +// CHECK-LABEL: define weak_odr dllexport x86_thiscallcc %struct.Derived2* @"\01??0Derived2@@QAE@ABU0@@Z" +// CHECK: %[[this:.*]] = load %struct.Derived2** {{.*}} +// CHECK-NEXT: store %struct.Derived2* %[[this]], %struct.Derived2** %[[retval:.*]] +// CHECK: %[[dest_a_gep:.*]] = getelementptr inbounds %struct.Derived2* %[[this]], i32 0, i32 1 +// CHECK-NEXT: %[[src_load:.*]] = load %struct.Derived2** {{.*}} +// CHECK-NEXT: %[[src_a_gep:.*]] = getelementptr inbounds %struct.Derived2* %[[src_load:.*]], i32 0, i32 1 +// CHECK-NEXT: %[[dest_a_bitcast:.*]] = bitcast [1 x i32]* %[[dest_a_gep]] to i8* +// CHECK-NEXT: %[[src_a_bitcast:.*]] = bitcast [1 x i32]* %[[src_a_gep]] to i8* +// CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* %[[dest_a_bitcast]], i8* %[[src_a_bitcast]], i32 4, i32 4, i1 false) +// CHECK-NEXT: %[[dest_this:.*]] = load %struct.Derived2** %[[retval]] +// CHECK-NEXT: ret %struct.Derived2* %[[dest_this]] + int Array[1]; +}; diff --git a/test/CodeGenCXX/pr21989.cpp b/test/CodeGenCXX/pr21989.cpp new file mode 100644 index 000000000000..0b9bccbe925b --- /dev/null +++ b/test/CodeGenCXX/pr21989.cpp @@ -0,0 +1,9 @@ +// REQUIRES: asserts +// RUN: not %clang_cc1 -emit-llvm -triple %itanium_abi_triple -o - %s 2>&1 | FileCheck %s + +struct { + void __attribute__((used)) f() {} +}; +// CHECK: 2 errors generated. + +// Emit the errors, but don't assert. diff --git a/test/CodeGenCXX/pragma-init_seg.cpp b/test/CodeGenCXX/pragma-init_seg.cpp index 3f9ff217e6b6..cc4d01875309 100644 --- a/test/CodeGenCXX/pragma-init_seg.cpp +++ b/test/CodeGenCXX/pragma-init_seg.cpp @@ -35,24 +35,24 @@ int x = f(); namespace selectany_init { int __declspec(selectany) x = f(); -// CHECK: @"\01?x@selectany_init@@3HA" = weak_odr global i32 0, comdat $"\01?x@selectany_init@@3HA", align 4 -// CHECK: @__cxx_init_fn_ptr3 = private constant void ()* @"\01??__Ex@selectany_init@@YAXXZ", section ".asdf", comdat $"\01?x@selectany_init@@3HA" +// CHECK: @"\01?x@selectany_init@@3HA" = weak_odr global i32 0, comdat, align 4 +// CHECK: @__cxx_init_fn_ptr3 = private constant void ()* @"\01??__Ex@selectany_init@@YAXXZ", section ".asdf", comdat($"\01?x@selectany_init@@3HA") } namespace explicit_template_instantiation { template <typename T> struct A { static const int x; }; template <typename T> const int A<T>::x = f(); template struct A<int>; -// CHECK: @"\01?x@?$A@H@explicit_template_instantiation@@2HB" = weak_odr global i32 0, comdat $"\01?x@?$A@H@explicit_template_instantiation@@2HB", align 4 -// CHECK: @__cxx_init_fn_ptr4 = private constant void ()* @"\01??__Ex@?$A@H@explicit_template_instantiation@@2HB@YAXXZ", section ".asdf", comdat $"\01?x@?$A@H@explicit_template_instantiation@@2HB" +// CHECK: @"\01?x@?$A@H@explicit_template_instantiation@@2HB" = weak_odr global i32 0, comdat, align 4 +// CHECK: @__cxx_init_fn_ptr4 = private constant void ()* @"\01??__Ex@?$A@H@explicit_template_instantiation@@2HB@YAXXZ", section ".asdf", comdat($"\01?x@?$A@H@explicit_template_instantiation@@2HB") } namespace implicit_template_instantiation { template <typename T> struct A { static const int x; }; template <typename T> const int A<T>::x = f(); int g() { return A<int>::x; } -// CHECK: @"\01?x@?$A@H@implicit_template_instantiation@@2HB" = linkonce_odr global i32 0, comdat $"\01?x@?$A@H@implicit_template_instantiation@@2HB", align 4 -// CHECK: @__cxx_init_fn_ptr5 = private constant void ()* @"\01??__Ex@?$A@H@implicit_template_instantiation@@2HB@YAXXZ", section ".asdf", comdat $"\01?x@?$A@H@implicit_template_instantiation@@2HB" +// CHECK: @"\01?x@?$A@H@implicit_template_instantiation@@2HB" = linkonce_odr global i32 0, comdat, align 4 +// CHECK: @__cxx_init_fn_ptr5 = private constant void ()* @"\01??__Ex@?$A@H@implicit_template_instantiation@@2HB@YAXXZ", section ".asdf", comdat($"\01?x@?$A@H@implicit_template_instantiation@@2HB") } // ... and here's where we emitted user level ctors. diff --git a/test/CodeGenCXX/predefined-expr-cxx14.cpp b/test/CodeGenCXX/predefined-expr-cxx14.cpp new file mode 100644 index 000000000000..1f035757dea9 --- /dev/null +++ b/test/CodeGenCXX/predefined-expr-cxx14.cpp @@ -0,0 +1,105 @@ +// RUN: %clang_cc1 -std=c++14 %s -triple %itanium_abi_triple -fblocks -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 -x c++ -std=c++14 -triple %itanium_abi_triple -fblocks -emit-pch -o %t %s +// RUN: %clang_cc1 -x c++ -triple %itanium_abi_triple -std=c++14 -fblocks -include-pch %t %s -emit-llvm -o - | FileCheck %s + +#ifndef HEADER +#define HEADER + +// CHECK-DAG: @__func__._ZN13ClassTemplateIiE21classTemplateFunctionERi = private unnamed_addr constant [22 x i8] c"classTemplateFunction\00" +// CHECK-DAG: @__PRETTY_FUNCTION__._ZN13ClassTemplateIiE21classTemplateFunctionERi = private unnamed_addr constant [69 x i8] c"const auto &ClassTemplate<int>::classTemplateFunction(T &) [T = int]\00" + +// CHECK-DAG: @__func__._ZN24ClassInTopLevelNamespace16functionTemplateIiEERDaRT_ = private unnamed_addr constant [17 x i8] c"functionTemplate\00" +// CHECK-DAG: @__PRETTY_FUNCTION__._ZN24ClassInTopLevelNamespace16functionTemplateIiEERDaRT_ = private unnamed_addr constant [64 x i8] c"auto &ClassInTopLevelNamespace::functionTemplate(T &) [T = int]\00" + +// CHECK-DAG: @__func__._ZN24ClassInTopLevelNamespace16variadicFunctionEPiz = private unnamed_addr constant [17 x i8] c"variadicFunction\00" +// CHECK-DAG: @__PRETTY_FUNCTION__._ZN24ClassInTopLevelNamespace16variadicFunctionEPiz = private unnamed_addr constant [70 x i8] c"decltype(auto) ClassInTopLevelNamespace::variadicFunction(int *, ...)\00" + +// CHECK-DAG: @__func__._ZN24ClassInTopLevelNamespace25topLevelNamespaceFunctionEv = private unnamed_addr constant [26 x i8] c"topLevelNamespaceFunction\00" +// CHECK-DAG: @__PRETTY_FUNCTION__._ZN24ClassInTopLevelNamespace25topLevelNamespaceFunctionEv = private unnamed_addr constant [60 x i8] c"auto *ClassInTopLevelNamespace::topLevelNamespaceFunction()\00" + +// CHECK-DAG: @__func__.___ZN16ClassBlockConstrD2Ev_block_invoke = private unnamed_addr constant [41 x i8] c"___ZN16ClassBlockConstrD2Ev_block_invoke\00" +// CHECK-DAG: @__func__.___ZN16ClassBlockConstrC2Ev_block_invoke = private unnamed_addr constant [41 x i8] c"___ZN16ClassBlockConstrC2Ev_block_invoke\00" + +int printf(const char * _Format, ...); + +class ClassInTopLevelNamespace { +public: + auto *topLevelNamespaceFunction() { + printf("__func__ %s\n", __func__); + printf("__FUNCTION__ %s\n", __FUNCTION__); + printf("__PRETTY_FUNCTION__ %s\n\n", __PRETTY_FUNCTION__); + return static_cast<int *>(nullptr); + } + + decltype(auto) variadicFunction(int *a, ...) { + printf("__func__ %s\n", __func__); + printf("__FUNCTION__ %s\n", __FUNCTION__); + printf("__PRETTY_FUNCTION__ %s\n\n", __PRETTY_FUNCTION__); + return a; + } + + template<typename T> + auto &functionTemplate(T &t) { + printf("__func__ %s\n", __func__); + printf("__FUNCTION__ %s\n", __FUNCTION__); + printf("__PRETTY_FUNCTION__ %s\n\n", __PRETTY_FUNCTION__); + return t; + } +}; + +template<typename T> +class ClassTemplate { +public: + const auto &classTemplateFunction(T &t) { + printf("__func__ %s\n", __func__); + printf("__FUNCTION__ %s\n", __FUNCTION__); + printf("__PRETTY_FUNCTION__ %s\n\n", __PRETTY_FUNCTION__); + return t; + } +}; + +struct ClassBlockConstr { + const char *s; + ClassBlockConstr() { + const char * (^b)() = ^() { + return __func__; + }; + s = b(); + } + ~ClassBlockConstr() { + const char * (^b)() = ^() { + return __func__; + }; + s = b(); + } +}; + +template <class T> +class FuncTemplate { + const char *Func; + +public: + FuncTemplate() : Func(__func__) {} + const char *getFunc() const { return Func; } +}; + +int +main() { + int a; + ClassInTopLevelNamespace topLevelNamespace; + ClassBlockConstr classBlockConstr; + topLevelNamespace.topLevelNamespaceFunction(); + topLevelNamespace.variadicFunction(&a); + topLevelNamespace.functionTemplate(a); + + ClassTemplate<int> t; + t.classTemplateFunction(a); + return 0; +} +#else +void Foo() { + FuncTemplate<int> FTi; + (void)FTi.getFunc(); +} +#endif + diff --git a/test/CodeGenCXX/predefined-expr.cpp b/test/CodeGenCXX/predefined-expr.cpp index f901467c4f4b..6bdc2cec4be8 100644 --- a/test/CodeGenCXX/predefined-expr.cpp +++ b/test/CodeGenCXX/predefined-expr.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -std=c++11 %s -triple %itanium_abi_triple -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 -std=c++11 -fblocks %s -triple %itanium_abi_triple -emit-llvm -o - | FileCheck %s // CHECK: private unnamed_addr constant [15 x i8] c"externFunction\00" // CHECK: private unnamed_addr constant [26 x i8] c"void NS::externFunction()\00" @@ -537,3 +537,33 @@ int main() { return 0; } + +// rdar://19065361 +class XXX { + XXX(); + ~XXX(); +}; + +void XXLog(const char *functionName) { } + +typedef void (^notify_handler_t)(int token); + +typedef void (^dispatch_block_t)(void); + +void notify_register_dispatch(notify_handler_t handler); + +void _dispatch_once(dispatch_block_t block); + +XXX::XXX() +{ + _dispatch_once(^{ notify_register_dispatch( ^(int token) { XXLog(__FUNCTION__); }); + }); +} +// CHECK: define internal void @___ZN3XXXC2Ev_block_invoke_ + +XXX::~XXX() +{ + _dispatch_once(^{ notify_register_dispatch( ^(int token) { XXLog(__FUNCTION__); }); + }); +} +// CHECK: define internal void @___ZN3XXXD2Ev_block_invoke_ diff --git a/test/CodeGenCXX/runtimecc.cpp b/test/CodeGenCXX/runtimecc.cpp index 20448838f919..ad6dc85c360d 100644 --- a/test/CodeGenCXX/runtimecc.cpp +++ b/test/CodeGenCXX/runtimecc.cpp @@ -20,33 +20,33 @@ namespace test0 { }; A global; -// CHECK-LABEL: define internal arm_aapcscc void @__cxx_global_var_init() -// CHECK: call arm_aapcscc [[A]]* @_ZN5test01AC1Ev([[A]]* @_ZN5test06globalE) -// CHECK-NEXT: call arm_aapcscc i32 @__cxa_atexit(void (i8*)* bitcast ([[A]]* ([[A]]*)* @_ZN5test01AD1Ev to void (i8*)*), i8* bitcast ([[A]]* @_ZN5test06globalE to i8*), i8* @__dso_handle) [[NOUNWIND:#[0-9]+]] +// CHECK-LABEL: define internal void @__cxx_global_var_init() +// CHECK: call [[A]]* @_ZN5test01AC1Ev([[A]]* @_ZN5test06globalE) +// CHECK-NEXT: call i32 @__cxa_atexit(void (i8*)* bitcast ([[A]]* ([[A]]*)* @_ZN5test01AD1Ev to void (i8*)*), i8* bitcast ([[A]]* @_ZN5test06globalE to i8*), i8* @__dso_handle) [[NOUNWIND:#[0-9]+]] // CHECK-NEXT: ret void } -// CHECK: declare arm_aapcscc i32 @__cxa_atexit(void (i8*)*, i8*, i8*) [[NOUNWIND]] +// CHECK: declare i32 @__cxa_atexit(void (i8*)*, i8*, i8*) [[NOUNWIND]] namespace test1 { void test() { throw 0; } -// CHECK-LABEL: define arm_aapcscc void @_ZN5test14testEv() -// CHECK: [[T0:%.*]] = call arm_aapcscc i8* @__cxa_allocate_exception(i32 4) [[NOUNWIND]] +// CHECK-LABEL: define void @_ZN5test14testEv() +// CHECK: [[T0:%.*]] = call i8* @__cxa_allocate_exception(i32 4) [[NOUNWIND]] // CHECK-NEXT: [[T1:%.*]] = bitcast i8* [[T0]] to i32* // CHECK-NEXT: store i32 0, i32* [[T1]] -// CHECK-NEXT: call arm_aapcscc void @__cxa_throw(i8* [[T0]], i8* bitcast (i8** @_ZTIi to i8*), i8* null) [[NORETURN:#[0-9]+]] +// CHECK-NEXT: call void @__cxa_throw(i8* [[T0]], i8* bitcast (i8** @_ZTIi to i8*), i8* null) [[NORETURN:#[0-9]+]] // CHECK-NEXT: unreachable } -// CHECK: declare arm_aapcscc i8* @__cxa_allocate_exception(i32) +// CHECK: declare i8* @__cxa_allocate_exception(i32) -// CHECK: declare arm_aapcscc void @__cxa_throw(i8*, i8*, i8*) +// CHECK: declare void @__cxa_throw(i8*, i8*, i8*) -// CHECK-LABEL: define internal arm_aapcscc void @_GLOBAL__sub_I_runtimecc.cpp() -// CHECK: call arm_aapcscc void @__cxx_global_var_init() +// CHECK-LABEL: define internal void @_GLOBAL__sub_I_runtimecc.cpp() +// CHECK: call void @__cxx_global_var_init() // CHECK: attributes [[NOUNWIND]] = { nounwind } diff --git a/test/CodeGenCXX/sections.cpp b/test/CodeGenCXX/sections.cpp new file mode 100644 index 000000000000..f84f9d939c0b --- /dev/null +++ b/test/CodeGenCXX/sections.cpp @@ -0,0 +1,72 @@ +// RUN: %clang_cc1 -emit-llvm -triple i686-pc-win32 -fms-extensions -o - %s | FileCheck %s + +extern "C" { + +#pragma const_seg(".my_const") +#pragma bss_seg(".my_bss") +int D = 1; +#pragma data_seg(".data") +int a = 1; +#pragma data_seg(push, label, ".data2") +extern const int b; +const int b = 1; +const char* s = "my string!"; +#pragma data_seg(push, ".my_seg") +int c = 1; +#pragma data_seg(pop, label) +int d = 1; +int e; +#pragma bss_seg(".c") +int f; +void g(void){} +#pragma code_seg(".my_code") +void h(void){} +#pragma bss_seg() +int i; +#pragma bss_seg(".bss1") +#pragma bss_seg(push, test, ".bss2") +#pragma bss_seg() +#pragma bss_seg() +int TEST1; +#pragma bss_seg(pop) +int TEST2; + +#pragma section("read_flag_section", read) +// Even though they are not declared const, these become constant since they are +// in a read-only section. +__declspec(allocate("read_flag_section")) int unreferenced = 0; +extern __declspec(allocate("read_flag_section")) int referenced = 42; +int *user() { return &referenced; } + +#pragma section("no_section_attributes") +// A pragma section with no section attributes is read/write. +__declspec(allocate("no_section_attributes")) int implicitly_read_write = 42; + +#pragma section("long_section", long) +// Pragma section ignores "long". +__declspec(allocate("long_section")) long long_var = 42; + +#pragma section("short_section", short) +// Pragma section ignores "short". +__declspec(allocate("short_section")) short short_var = 42; +} + +//CHECK: @D = global i32 1 +//CHECK: @a = global i32 1, section ".data" +//CHECK: @b = constant i32 1, section ".my_const" +//CHECK: @[[MYSTR:.*]] = {{.*}} unnamed_addr constant [11 x i8] c"my string!\00" +//CHECK: @s = global i8* getelementptr inbounds ([11 x i8]* @[[MYSTR]], i32 0, i32 0), section ".data2" +//CHECK: @c = global i32 1, section ".my_seg" +//CHECK: @d = global i32 1, section ".data" +//CHECK: @e = global i32 0, section ".my_bss" +//CHECK: @f = global i32 0, section ".c" +//CHECK: @i = global i32 0 +//CHECK: @TEST1 = global i32 0 +//CHECK: @TEST2 = global i32 0, section ".bss1" +//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" +//CHECK: @long_var = global i32 42, section "long_section" +//CHECK: @short_var = global i16 42, section "short_section" +//CHECK: define void @g() +//CHECK: define void @h() {{.*}} section ".my_code" diff --git a/test/CodeGenCXX/skip-vtable-pointer-initialization.cpp b/test/CodeGenCXX/skip-vtable-pointer-initialization.cpp index 29926b91b795..6b500751d5d4 100644 --- a/test/CodeGenCXX/skip-vtable-pointer-initialization.cpp +++ b/test/CodeGenCXX/skip-vtable-pointer-initialization.cpp @@ -11,7 +11,7 @@ struct A { }; // CHECK-LABEL: define void @_ZN5Test11AD2Ev -// CHECK-NOT: store i8** getelementptr inbounds ([3 x i8*]* @_ZTVN5Test11AE, i64 0, i64 2), i8*** +// CHECK-NOT: store i32 (...)** bitcast (i8** getelementptr inbounds ([3 x i8*]* @_ZTVN5Test11AE, i64 0, i64 2) to i32 (...)**), i32 (...)*** A::~A() { } @@ -27,7 +27,7 @@ struct A { }; // CHECK-LABEL: define void @_ZN5Test21AD2Ev -// CHECK: store i8** getelementptr inbounds ([3 x i8*]* @_ZTVN5Test21AE, i64 0, i64 2), i8*** +// CHECK: store i32 (...)** bitcast (i8** getelementptr inbounds ([3 x i8*]* @_ZTVN5Test21AE, i64 0, i64 2) to i32 (...)**), i32 (...)*** A::~A() { f(); } @@ -50,7 +50,7 @@ struct A { }; // CHECK-LABEL: define void @_ZN5Test31AD2Ev -// CHECK-NOT: store i8** getelementptr inbounds ([3 x i8*]* @_ZTVN5Test31AE, i64 0, i64 2), i8*** +// CHECK-NOT: store i32 (...)** bitcast (i8** getelementptr inbounds ([3 x i8*]* @_ZTVN5Test31AE, i64 0, i64 2) to i32 (...)**), i32 (...)*** A::~A() { } @@ -76,7 +76,7 @@ struct A { }; // CHECK-LABEL: define void @_ZN5Test41AD2Ev -// CHECK: store i8** getelementptr inbounds ([3 x i8*]* @_ZTVN5Test41AE, i64 0, i64 2), i8*** +// CHECK: store i32 (...)** bitcast (i8** getelementptr inbounds ([3 x i8*]* @_ZTVN5Test41AE, i64 0, i64 2) to i32 (...)**), i32 (...)*** A::~A() { } @@ -100,7 +100,7 @@ struct A { }; // CHECK-LABEL: define void @_ZN5Test51AD2Ev -// CHECK: store i8** getelementptr inbounds ([3 x i8*]* @_ZTVN5Test51AE, i64 0, i64 2), i8*** +// CHECK: store i32 (...)** bitcast (i8** getelementptr inbounds ([3 x i8*]* @_ZTVN5Test51AE, i64 0, i64 2) to i32 (...)**), i32 (...)*** A::~A() { } @@ -128,7 +128,7 @@ struct A { }; // CHECK-LABEL: define void @_ZN5Test61AD2Ev -// CHECK: store i8** getelementptr inbounds ([3 x i8*]* @_ZTVN5Test61AE, i64 0, i64 2), i8*** +// CHECK: store i32 (...)** bitcast (i8** getelementptr inbounds ([3 x i8*]* @_ZTVN5Test61AE, i64 0, i64 2) to i32 (...)**), i32 (...)*** A::~A() { } @@ -154,7 +154,7 @@ struct A { }; // CHECK-LABEL: define void @_ZN5Test71AD2Ev -// CHECK: store i8** getelementptr inbounds ([3 x i8*]* @_ZTVN5Test71AE, i64 0, i64 2), i8*** +// CHECK: store i32 (...)** bitcast (i8** getelementptr inbounds ([3 x i8*]* @_ZTVN5Test71AE, i64 0, i64 2) to i32 (...)**), i32 (...)*** A::~A() { } @@ -180,7 +180,7 @@ struct A { }; // CHECK-LABEL: define void @_ZN5Test81AD2Ev -// CHECK: store i8** getelementptr inbounds ([3 x i8*]* @_ZTVN5Test81AE, i64 0, i64 2), i8*** +// CHECK: store i32 (...)** bitcast (i8** getelementptr inbounds ([3 x i8*]* @_ZTVN5Test81AE, i64 0, i64 2) to i32 (...)**), i32 (...)*** A::~A() { } diff --git a/test/CodeGenCXX/split-stacks.cpp b/test/CodeGenCXX/split-stacks.cpp index 3e120344d6b6..76e1b79b8f1a 100644 --- a/test/CodeGenCXX/split-stacks.cpp +++ b/test/CodeGenCXX/split-stacks.cpp @@ -18,7 +18,7 @@ int nosplit() { // CHECK-SEGSTK: define i32 @_Z3foov() [[SS:#[0-9]+]] { // CHECK-SEGSTK: define i32 @_Z7nosplitv() [[NSS1:#[0-9]+]] { -// CHECK-SEGSTK: define linkonce_odr i32 @_Z8tnosplitIiEiv() [[NSS2:#[0-9]+]] { +// CHECK-SEGSTK: define linkonce_odr i32 @_Z8tnosplitIiEiv() [[NSS2:#[0-9]+]] comdat { // CHECK-SEGSTK-NOT: [[NSS1]] = { {{.*}} "split-stack" {{.*}} } // CHECK-SEGSTK-NOT: [[NSS2]] = { {{.*}} "split-stack" {{.*}} } // CHECK-SEGSTK: [[SS]] = { {{.*}} "split-stack" {{.*}} } @@ -27,7 +27,7 @@ int nosplit() { // CHECK-NOSEGSTK: define i32 @_Z3foov() [[NSS0:#[0-9]+]] { // CHECK-NOSEGSTK: define i32 @_Z7nosplitv() [[NSS1:#[0-9]+]] { -// CHECK-NOSEGSTK: define linkonce_odr i32 @_Z8tnosplitIiEiv() [[NSS2:#[0-9]+]] { +// CHECK-NOSEGSTK: define linkonce_odr i32 @_Z8tnosplitIiEiv() [[NSS2:#[0-9]+]] comdat { // CHECK-NOSEGSTK-NOT: [[NSS1]] = { {{.*}} "split-stack" {{.*}} } // CHECK-NOSEGSTK-NOT: [[NSS2]] = { {{.*}} "split-stack" {{.*}} } // CHECK-NOSEGSTK-NOT: [[NSS3]] = { {{.*}} "split-stack" {{.*}} } diff --git a/test/CodeGenCXX/static-data-member.cpp b/test/CodeGenCXX/static-data-member.cpp index eea979494843..d41ac8fb3542 100644 --- a/test/CodeGenCXX/static-data-member.cpp +++ b/test/CodeGenCXX/static-data-member.cpp @@ -1,9 +1,13 @@ -// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm -o - %s | \ +// RUN: FileCheck --check-prefix=MACHO %s // CHECK: @_ZN5test11A1aE = constant i32 10, align 4 // CHECK: @_ZN5test212_GLOBAL__N_11AIiE1xE = internal global i32 0, align 4 -// CHECK: @_ZN5test31AIiE1xE = weak_odr global i32 0, align 4 -// CHECK: @_ZGVN5test31AIiE1xE = weak_odr global i64 0 +// CHECK: @_ZN5test31AIiE1xE = weak_odr global i32 0, comdat, align 4 +// CHECK: @_ZGVN5test31AIiE1xE = weak_odr global i64 0, comdat($_ZN5test31AIiE1xE) +// MACHO: @_ZGVN5test31AIiE1xE = weak_odr global i64 0 +// MACHO-NOT: comdat // CHECK: _ZN5test51U2k0E = global i32 0 // CHECK: _ZN5test51U2k1E = global i32 0 @@ -60,7 +64,9 @@ namespace test3 { template <class T> int A<T>::x = foo(); template struct A<int>; - // CHECK-LABEL: define internal void @__cxx_global_var_init1() + // CHECK-LABEL: define internal void @__cxx_global_var_init1() {{.*}} comdat($_ZN5test31AIiE1xE) + // MACHO-LABEL: define internal void @__cxx_global_var_init1() + // MACHO-NOT: comdat // CHECK: [[GUARDBYTE:%.*]] = load i8* bitcast (i64* @_ZGVN5test31AIiE1xE to i8*) // CHECK-NEXT: [[UNINITIALIZED:%.*]] = icmp eq i8 [[GUARDBYTE]], 0 // CHECK-NEXT: br i1 [[UNINITIALIZED]] diff --git a/test/CodeGenCXX/static-init.cpp b/test/CodeGenCXX/static-init.cpp index d23ead47f385..66ff5b3fbabd 100644 --- a/test/CodeGenCXX/static-init.cpp +++ b/test/CodeGenCXX/static-init.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 %s -triple=x86_64-pc-linuxs -emit-llvm -o - | FileCheck %s // CHECK: @_ZZ1hvE1i = internal global i32 0, align 4 // CHECK: @base_req = global [4 x i8] c"foo\00", align 1 @@ -6,8 +6,9 @@ // CHECK: @_ZZN5test31BC1EvE1u = internal global { i8, [3 x i8] } { i8 97, [3 x i8] undef }, align 4 // CHECK: @_ZZN5test1L6getvarEiE3var = internal constant [4 x i32] [i32 1, i32 0, i32 2, i32 4], align 16 -// CHECK: @_ZZ2h2vE1i = linkonce_odr global i32 0 -// CHECK: @_ZGVZ2h2vE1i = linkonce_odr global i64 0 + +// CHECK: @_ZZ2h2vE1i = linkonce_odr global i32 0, comdat, align +// CHECK: @_ZGVZ2h2vE1i = linkonce_odr global i64 0, comdat{{$}} struct A { A(); @@ -34,6 +35,7 @@ void h() { static const int i = a(); } +// CHECK: define linkonce_odr void @_Z2h2v() {{.*}} comdat { inline void h2() { static int i = a(); } diff --git a/test/CodeGenCXX/static-local-in-local-class.cpp b/test/CodeGenCXX/static-local-in-local-class.cpp index ebf560ab9805..729b9376ae48 100644 --- a/test/CodeGenCXX/static-local-in-local-class.cpp +++ b/test/CodeGenCXX/static-local-in-local-class.cpp @@ -1,6 +1,13 @@ -// RUN: %clang_cc1 -emit-llvm -o %t %s -// PR6769 +// RUN: %clang_cc1 -triple x86_64-linux -fblocks -emit-llvm -o - %s -std=c++1y | FileCheck %s +// CHECK: @"_ZZNK3$_2clEvE1x" = internal global i32 42 +// CHECK: @_ZZ18static_local_labelPvE1q = linkonce_odr global i8* blockaddress(@_Z18static_local_labelPv, %{{.*}}) +// CHECK: @_ZZZL20block_deduced_returnvEUb_E1n = internal global i32 42 +// CHECK: @_ZZL14deduced_returnvE1n = internal global i32 42 +// CHECK: @"_ZZZNK17pr18020_constexpr3$_1clEvENKUlvE_clEvE2l2" = +// CHECK: internal global i32* @"_ZZNK17pr18020_constexpr3$_1clEvE2l1" + +namespace pr6769 { struct X { static void f(); }; @@ -19,8 +26,9 @@ void X::f() { } (void)i; } +} -// pr7101 +namespace pr7101 { void foo() { static int n = 0; struct Helper { @@ -30,4 +38,123 @@ void foo() { }; Helper::Execute(); } +} + +// These tests all break the assumption that the static var decl has to be +// emitted before use of the var decl. This happens because we defer emission +// of variables with internal linkage and no initialization side effects, such +// as 'x'. Then we hit operator()() in 'f', and emit the callee before we emit +// the arguments, so we emit the innermost function first. + +namespace pr18020_lambda { +// Referring to l1 before emitting it used to crash. +auto x = []() { + static int l1 = 0; + return [] { return l1; }; +}; +int f() { return x()(); } +} + +// CHECK-LABEL: define internal i32 @"_ZZNK14pr18020_lambda3$_0clEvENKUlvE_clEv" +// CHECK: load i32* @"_ZZNK14pr18020_lambda3$_0clEvE2l1" + +namespace pr18020_constexpr { +// Taking the address of l1 in a constant expression used to crash. +auto x = []() { + static int l1 = 0; + return [] { + static int *l2 = &l1; + return *l2; + }; +}; +int f() { return x()(); } +} + +// CHECK-LABEL: define internal i32 @"_ZZNK17pr18020_constexpr3$_1clEvENKUlvE_clEv" +// CHECK: load i32** @"_ZZZNK17pr18020_constexpr3$_1clEvENKUlvE_clEvE2l2" + +// Lambda-less reduction that references l1 before emitting it. This didn't +// crash if you put it in a namespace. +struct pr18020_class { + auto operator()() { + static int l1 = 0; + struct U { + int operator()() { return l1; } + }; + return U(); + } +}; +static pr18020_class x; +int pr18020_f() { return x()(); } + +// CHECK-LABEL: define linkonce_odr i32 @_ZZN13pr18020_classclEvEN1UclEv +// CHECK: load i32* @_ZZN13pr18020_classclEvE2l1 + +// In this test case, the function containing the static local will not be +// emitted because it is unneeded. However, the operator call of the inner class +// is called, and the static local is referenced and must be emitted. +static auto deduced_return() { + static int n = 42; + struct S { int *operator()() { return &n; } }; + return S(); +} +extern "C" int call_deduced_return_operator() { + return *decltype(deduced_return())()(); +} + +// CHECK-LABEL: define i32 @call_deduced_return_operator() +// CHECK: call i32* @_ZZL14deduced_returnvEN1SclEv( +// CHECK: load i32* % +// CHECK: ret i32 % + +// CHECK-LABEL: define internal i32* @_ZZL14deduced_returnvEN1SclEv(%struct.S* %this) +// CHECK: ret i32* @_ZZL14deduced_returnvE1n + +static auto block_deduced_return() { + auto (^b)() = ^() { + static int n = 42; + struct S { int *operator()() { return &n; } }; + return S(); + }; + return b(); +} +extern "C" int call_block_deduced_return() { + return *decltype(block_deduced_return())()(); +} + +// CHECK-LABEL: define i32 @call_block_deduced_return() +// CHECK: call i32* @_ZZZL20block_deduced_returnvEUb_EN1SclEv( +// CHECK: load i32* % +// CHECK: ret i32 % + +// CHECK-LABEL: define internal i32* @_ZZZL20block_deduced_returnvEUb_EN1SclEv(%struct.S.6* %this) #0 align 2 { +// CHECK: ret i32* @_ZZZL20block_deduced_returnvEUb_E1n + +inline auto static_local_label(void *p) { + if (p) + goto *p; + static void *q = &&label; + struct S { static void *get() { return q; } }; + return S(); +label: + __builtin_abort(); +} +void *global_label = decltype(static_local_label(0))::get(); + +// CHECK-LABEL: define linkonce_odr i8* @_ZZ18static_local_labelPvEN1S3getEv() +// CHECK: %[[lbl:[^ ]*]] = load i8** @_ZZ18static_local_labelPvE1q +// CHECK: ret i8* %[[lbl]] + +auto global_lambda = []() { + static int x = 42; + struct S { static int *get() { return &x; } }; + return S(); +}; +extern "C" int use_global_lambda() { + return *decltype(global_lambda())::get(); +} +// CHECK-LABEL: define i32 @use_global_lambda() +// CHECK: call i32* @"_ZZNK3$_2clEvEN1S3getEv"() +// CHECK-LABEL: define internal i32* @"_ZZNK3$_2clEvEN1S3getEv"() +// CHECK: ret i32* @"_ZZNK3$_2clEvE1x" diff --git a/test/CodeGenCXX/static-member-variable-explicit-specialization.cpp b/test/CodeGenCXX/static-member-variable-explicit-specialization.cpp index 98c09b84797d..20b409cbf996 100644 --- a/test/CodeGenCXX/static-member-variable-explicit-specialization.cpp +++ b/test/CodeGenCXX/static-member-variable-explicit-specialization.cpp @@ -1,25 +1,42 @@ -// RUN: %clang_cc1 %s -std=c++1y -triple=x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s -// CHECK: ; ModuleID +// RUN: %clang_cc1 %s -std=c++1y -triple=x86_64-pc-linux -emit-llvm -o - | FileCheck --check-prefix=ELF --check-prefix=ALL %s +// RUN: %clang_cc1 %s -std=c++1y -triple=x86_64-apple-darwin -emit-llvm -o - | FileCheck --check-prefix=MACHO --check-prefix=ALL %s + +// ALL: ; ModuleID extern "C" int foo(); template<typename T> struct A { static int a; }; template<typename T> int A<T>::a = foo(); -// CHECK-NOT: @_ZN1AIcE1aE +// ALLK-NOT: @_ZN1AIcE1aE template<> int A<char>::a; -// CHECK: @_ZN1AIbE1aE = global i32 10 +// ALL: @_ZN1AIbE1aE = global i32 10 template<> int A<bool>::a = 10; -// CHECK: @llvm.global_ctors = appending global [7 x { i32, void ()*, i8* }] -// CHECK: [{ i32, void ()*, i8* } { i32 65535, void ()* @[[unordered1:[^,]*]], i8* bitcast (i32* @_ZN1AIsE1aE to i8*) }, -// CHECK: { i32, void ()*, i8* } { i32 65535, void ()* @[[unordered2:[^,]*]], i8* bitcast (i16* @_Z1xIsE to i8*) }, -// CHECK: { i32, void ()*, i8* } { i32 65535, void ()* @[[unordered3:[^,]*]], i8* bitcast (i32* @_ZN2ns1aIiE1iE to i8*) }, -// CHECK: { i32, void ()*, i8* } { i32 65535, void ()* @[[unordered4:[^,]*]], i8* bitcast (i32* @_ZN2ns1b1iIiEE to i8*) }, -// CHECK: { i32, void ()*, i8* } { i32 65535, void ()* @[[unordered5:[^,]*]], i8* bitcast (i32* @_ZN1AIvE1aE to i8*) }, -// CHECK: { i32, void ()*, i8* } { i32 65535, void ()* @[[unordered6:[^,]*]], i8* @_Z1xIcE }, -// CHECK: { i32, void ()*, i8* } { i32 65535, void ()* @_GLOBAL__sub_I_static_member_variable_explicit_specialization.cpp, i8* null }] +// ALL: @llvm.global_ctors = appending global [8 x { i32, void ()*, i8* }] + +// ELF: [{ i32, void ()*, i8* } { i32 65535, void ()* @[[unordered1:[^,]*]], i8* bitcast (i32* @_ZN1AIsE1aE to i8*) }, +// MACHO: [{ i32, void ()*, i8* } { i32 65535, void ()* @[[unordered1:[^,]*]], i8* null }, + +// ELF: { i32, void ()*, i8* } { i32 65535, void ()* @[[unordered2:[^,]*]], i8* bitcast (i16* @_Z1xIsE to i8*) }, +// MACHO: { i32, void ()*, i8* } { i32 65535, void ()* @[[unordered2:[^,]*]], i8* null }, + +// ELF: { i32, void ()*, i8* } { i32 65535, void ()* @[[unordered3:[^,]*]], i8* bitcast (i32* @_ZN2ns1aIiE1iE to i8*) }, +// MACHO: { i32, void ()*, i8* } { i32 65535, void ()* @[[unordered3:[^,]*]], i8* null }, + +// ELF: { i32, void ()*, i8* } { i32 65535, void ()* @[[unordered4:[^,]*]], i8* bitcast (i32* @_ZN2ns1b1iIiEE to i8*) }, +// MACHO: { i32, void ()*, i8* } { i32 65535, void ()* @[[unordered4:[^,]*]], i8* null }, + +// ELF: { i32, void ()*, i8* } { i32 65535, void ()* @[[unordered5:[^,]*]], i8* bitcast (i32* @_ZN1AIvE1aE to i8*) }, +// MACHO: { i32, void ()*, i8* } { i32 65535, void ()* @[[unordered5:[^,]*]], i8* null }, + +// ELF: { i32, void ()*, i8* } { i32 65535, void ()* @[[unordered6:[^,]*]], i8* @_Z1xIcE }, +// MACHO: { i32, void ()*, i8* } { i32 65535, void ()* @[[unordered6:[^,]*]], i8* null }, + +// ALL: { i32, void ()*, i8* } { i32 65535, void ()* @[[unordered7:[^,]*]], i8* null }, + +// ALL: { i32, void ()*, i8* } { i32 65535, void ()* @_GLOBAL__sub_I_static_member_variable_explicit_specialization.cpp, i8* null }] template int A<short>::a; // Unordered int b = foo(); @@ -52,45 +69,57 @@ struct b { template<typename T> T b::i = foo(); template int b::i<int>; } -// CHECK: define internal void @[[unordered1]] -// CHECK: call i32 @foo() -// CHECK: store {{.*}} @_ZN1AIsE1aE -// CHECK: ret - -// CHECK: define internal void @[[unordered2]] -// CHECK: call i32 @foo() -// CHECK: store {{.*}} @_Z1xIsE -// CHECK: ret - -// CHECK: define internal void @[[unordered3]] -// CHECK: call i32 @foo() -// CHECK: store {{.*}} @_ZN2ns1aIiE1iE -// CHECK: ret - -// CHECK: define internal void @[[unordered4]] -// CHECK: call i32 @foo() -// CHECK: store {{.*}} @_ZN2ns1b1iIiEE -// CHECK: ret - -// CHECK: define internal void @[[unordered5]] -// CHECK: call i32 @foo() -// CHECK: store {{.*}} @_ZN1AIvE1aE -// CHECK: ret - -// CHECK: define internal void @[[unordered6]] -// CHECK: call i32 @foo() -// CHECK: store {{.*}} @_Z1xIcE -// CHECK: ret - -// CHECK: define internal void @_GLOBAL__sub_I_static_member_variable_explicit_specialization.cpp() + +namespace { +template<typename T> struct Internal { static int a; }; +template<typename T> int Internal<T>::a = foo(); +} +int *use_internal_a = &Internal<int>::a; + +// ALL: define internal void @[[unordered1]]( +// ALL: call i32 @foo() +// ALL: store {{.*}} @_ZN1AIsE1aE +// ALL: ret + +// ALL: define internal void @[[unordered2]]( +// ALL: call i32 @foo() +// ALL: store {{.*}} @_Z1xIsE +// ALL: ret + +// ALL: define internal void @[[unordered3]]( +// ALL: call i32 @foo() +// ALL: store {{.*}} @_ZN2ns1aIiE1iE +// ALL: ret + +// ALL: define internal void @[[unordered4]]( +// ALL: call i32 @foo() +// ALL: store {{.*}} @_ZN2ns1b1iIiEE +// ALL: ret + +// ALL: define internal void @[[unordered5]]( +// ALL: call i32 @foo() +// ALL: store {{.*}} @_ZN1AIvE1aE +// ALL: ret + +// ALL: define internal void @[[unordered6]]( +// ALL: call i32 @foo() +// ALL: store {{.*}} @_Z1xIcE +// ALL: ret + +// ALL: define internal void @[[unordered7]]( +// ALL: call i32 @foo() +// ALL: store {{.*}} @_ZN12_GLOBAL__N_18InternalIiE1aE +// ALL: ret + +// ALL: define internal void @_GLOBAL__sub_I_static_member_variable_explicit_specialization.cpp() // We call unique stubs for every ordered dynamic initializer in the TU. -// CHECK: call -// CHECK: call -// CHECK: call -// CHECK: call -// CHECK: call -// CHECK: call -// CHECK: call -// CHECK: call -// CHECK-NOT: call -// CHECK: ret +// ALL: call +// ALL: call +// ALL: call +// ALL: call +// ALL: call +// ALL: call +// ALL: call +// ALL: call +// ALL-NOT: call +// ALL: ret diff --git a/test/CodeGenCXX/temporaries.cpp b/test/CodeGenCXX/temporaries.cpp index 7f5c7af03865..89677cb1e4e9 100644 --- a/test/CodeGenCXX/temporaries.cpp +++ b/test/CodeGenCXX/temporaries.cpp @@ -42,6 +42,13 @@ namespace PR20227 { // CHECK: @_ZGRN7PR202271cE_ = private global } +namespace BraceInit { + typedef const int &CIR; + CIR x = CIR{3}; + // CHECK: @_ZGRN9BraceInit1xE_ = private constant i32 3 + // CHECK: @_ZN9BraceInit1xE = constant i32* @_ZGRN9BraceInit1xE_ +} + struct A { A(); ~A(); diff --git a/test/CodeGenCXX/try-catch.cpp b/test/CodeGenCXX/try-catch.cpp index 89f229fee375..b50214ecdb97 100644 --- a/test/CodeGenCXX/try-catch.cpp +++ b/test/CodeGenCXX/try-catch.cpp @@ -11,3 +11,11 @@ void f() { } catch (const X x) { } } + +void h() { + try { + throw "ABC"; + // CHECK: @_ZTIPKc to i8 + } catch (char const(&)[4]) { + } +} diff --git a/test/CodeGenCXX/unknown-anytype.cpp b/test/CodeGenCXX/unknown-anytype.cpp index aacb8493ef3c..e6f887bea083 100644 --- a/test/CodeGenCXX/unknown-anytype.cpp +++ b/test/CodeGenCXX/unknown-anytype.cpp @@ -115,3 +115,11 @@ extern "C" __unknown_anytype test10_any(...); void test10() { (void) test10_any(), (void) test10_any(); } + +extern "C" __unknown_anytype malloc(...); +void test11() { + void *s = (void*)malloc(12); + // COMMON: call i8* (i32, ...)* @malloc(i32 12) + void *d = (void*)malloc(435); + // COMMON: call i8* (i32, ...)* @malloc(i32 435) +} diff --git a/test/CodeGenCXX/vararg-non-pod-ms-compat.cpp b/test/CodeGenCXX/vararg-non-pod-ms-compat.cpp new file mode 100644 index 000000000000..668fadf7b589 --- /dev/null +++ b/test/CodeGenCXX/vararg-non-pod-ms-compat.cpp @@ -0,0 +1,28 @@ +// RUN: %clang_cc1 -Wno-error=non-pod-varargs -triple i686-pc-win32 -fms-compatibility -emit-llvm -o - %s | FileCheck %s -check-prefix=X86 -check-prefix=CHECK +// RUN: %clang_cc1 -Wno-error=non-pod-varargs -triple x86_64-pc-win32 -fms-compatibility -emit-llvm -o - %s | FileCheck %s -check-prefix=X64 -check-prefix=CHECK + +struct X { + X(); + ~X(); + int data; +}; + +void vararg(...); + +void test(X x) { + // CHECK-LABEL: define void @"\01?test@@YAXUX@@@Z" + + // X86: %[[argmem:[^ ]*]] = alloca inalloca <{ %struct.X }> + // X86: call void (<{ %struct.X }>*, ...)* bitcast (void (...)* @"\01?vararg@@YAXZZ" to void (<{ %struct.X }>*, ...)*)(<{ %struct.X }>* inalloca %[[argmem]]) + + // X64: alloca %struct.X + + // X64: %[[agg:[^ ]*]] = alloca %struct.X + // X64: %[[valptr:[^ ]*]] = getelementptr %struct.X* %[[agg]], i32 0, i32 0 + // X64: %[[val:[^ ]*]] = load i32* %[[valptr]] + // X64: call void (...)* @"\01?vararg@@YAXZZ"(i32 %[[val]]) + + // CHECK-NOT: llvm.trap + vararg(x); + // CHECK: ret void +} diff --git a/test/CodeGenCXX/virtual-base-cast.cpp b/test/CodeGenCXX/virtual-base-cast.cpp index 6a4894b63b70..0dcf319d7dc2 100644 --- a/test/CodeGenCXX/virtual-base-cast.cpp +++ b/test/CodeGenCXX/virtual-base-cast.cpp @@ -20,11 +20,10 @@ A* a() { return x; } // MSVC: @"\01?a@@YAPAUA@@XZ"() [[NUW:#[0-9]+]] { // MSVC: %[[vbptr_off:.*]] = getelementptr inbounds i8* {{.*}}, i32 0 -// MSVC: %[[vbptr:.*]] = bitcast i8* %[[vbptr_off]] to i8** -// MSVC: %[[vbtable:.*]] = load i8** %[[vbptr]] -// MSVC: %[[entry:.*]] = getelementptr inbounds i8* {{.*}}, i32 4 -// MSVC: %[[entry_i32:.*]] = bitcast i8* %[[entry]] to i32* -// MSVC: %[[offset:.*]] = load i32* %[[entry_i32]] +// MSVC: %[[vbptr:.*]] = bitcast i8* %[[vbptr_off]] to i32** +// MSVC: %[[vbtable:.*]] = load i32** %[[vbptr]] +// MSVC: %[[entry:.*]] = getelementptr inbounds i32* {{.*}}, i32 1 +// MSVC: %[[offset:.*]] = load i32* %[[entry]] // MSVC: add nsw i32 0, %[[offset]] // MSVC: } @@ -38,11 +37,10 @@ B* b() { return x; } // Same as 'a' except we use a different vbtable offset. // MSVC: @"\01?b@@YAPAUB@@XZ"() [[NUW:#[0-9]+]] { // MSVC: %[[vbptr_off:.*]] = getelementptr inbounds i8* {{.*}}, i32 0 -// MSVC: %[[vbptr:.*]] = bitcast i8* %[[vbptr_off]] to i8** -// MSVC: %[[vbtable:.*]] = load i8** %[[vbptr]] -// MSVC: %[[entry:.*]] = getelementptr inbounds i8* {{.*}}, i32 8 -// MSVC: %[[entry_i32:.*]] = bitcast i8* %[[entry]] to i32* -// MSVC: %[[offset:.*]] = load i32* %[[entry_i32]] +// MSVC: %[[vbptr:.*]] = bitcast i8* %[[vbptr_off]] to i32** +// MSVC: %[[vbtable:.*]] = load i32** %[[vbptr]] +// MSVC: %[[entry:.*]] = getelementptr inbounds i32* {{.*}}, i32 2 +// MSVC: %[[offset:.*]] = load i32* %[[entry]] // MSVC: add nsw i32 0, %[[offset]] // MSVC: } @@ -58,11 +56,10 @@ BB* c() { return x; } // Same as 'a' except we use a different vbtable offset. // MSVC: @"\01?c@@YAPAUBB@@XZ"() [[NUW:#[0-9]+]] { // MSVC: %[[vbptr_off:.*]] = getelementptr inbounds i8* {{.*}}, i32 0 -// MSVC: %[[vbptr:.*]] = bitcast i8* %[[vbptr_off]] to i8** -// MSVC: %[[vbtable:.*]] = load i8** %[[vbptr]] -// MSVC: %[[entry:.*]] = getelementptr inbounds i8* {{.*}}, i32 16 -// MSVC: %[[entry_i32:.*]] = bitcast i8* %[[entry]] to i32* -// MSVC: %[[offset:.*]] = load i32* %[[entry_i32]] +// MSVC: %[[vbptr:.*]] = bitcast i8* %[[vbptr_off]] to i32** +// MSVC: %[[vbtable:.*]] = load i32** %[[vbptr]] +// MSVC: %[[entry:.*]] = getelementptr inbounds i32* {{.*}}, i32 4 +// MSVC: %[[offset:.*]] = load i32* %[[entry]] // MSVC: add nsw i32 0, %[[offset]] // MSVC: } @@ -78,11 +75,10 @@ BB* d() { return y; } // final add. // MSVC: @"\01?d@@YAPAUBB@@XZ"() [[NUW:#[0-9]+]] { // MSVC: %[[vbptr_off:.*]] = getelementptr inbounds i8* {{.*}}, i32 4 -// MSVC: %[[vbptr:.*]] = bitcast i8* %[[vbptr_off]] to i8** -// MSVC: %[[vbtable:.*]] = load i8** %[[vbptr]] -// MSVC: %[[entry:.*]] = getelementptr inbounds i8* {{.*}}, i32 16 -// MSVC: %[[entry_i32:.*]] = bitcast i8* %[[entry]] to i32* -// MSVC: %[[offset:.*]] = load i32* %[[entry_i32]] +// MSVC: %[[vbptr:.*]] = bitcast i8* %[[vbptr_off]] to i32** +// MSVC: %[[vbtable:.*]] = load i32** %[[vbptr]] +// MSVC: %[[entry:.*]] = getelementptr inbounds i32* {{.*}}, i32 4 +// MSVC: %[[offset:.*]] = load i32* %[[entry]] // MSVC: add nsw i32 4, %[[offset]] // MSVC: } diff --git a/test/CodeGenCXX/virtual-destructor-calls.cpp b/test/CodeGenCXX/virtual-destructor-calls.cpp index 3e7fa8293af8..f0e3dc58b641 100644 --- a/test/CodeGenCXX/virtual-destructor-calls.cpp +++ b/test/CodeGenCXX/virtual-destructor-calls.cpp @@ -17,8 +17,8 @@ struct B : A { // CHECK: @_ZN1BD1Ev = alias {{.*}} @_ZN1BD2Ev // (aliases from C) -// CHECK: @_ZN1CD1Ev = alias {{.*}} @_ZN1CD2Ev // CHECK: @_ZN1CD2Ev = alias bitcast {{.*}} @_ZN1BD2Ev +// CHECK: @_ZN1CD1Ev = alias {{.*}} @_ZN1CD2Ev // Base dtor: actually calls A's base dtor. // CHECK-LABEL: define void @_ZN1BD2Ev(%struct.B* %this) unnamed_addr diff --git a/test/CodeGenCXX/virtual-operator-call.cpp b/test/CodeGenCXX/virtual-operator-call.cpp index 72d49c230093..727c8e140fd8 100644 --- a/test/CodeGenCXX/virtual-operator-call.cpp +++ b/test/CodeGenCXX/virtual-operator-call.cpp @@ -1,10 +1,13 @@ // RUN: %clang_cc1 %s -triple i386-unknown-unknown -emit-llvm -o - | FileCheck %s struct A { - virtual int operator-() = 0; + virtual int operator-(); }; -void f(A *a) { +void f(A a, A *ap) { + // CHECK: call i32 @_ZN1AngEv(%struct.A* %a) + -a; + // CHECK: call i32 % - -*a; + -*ap; } diff --git a/test/CodeGenCXX/vla-lambda-capturing.cpp b/test/CodeGenCXX/vla-lambda-capturing.cpp new file mode 100644 index 000000000000..e8fd0a1fd3ab --- /dev/null +++ b/test/CodeGenCXX/vla-lambda-capturing.cpp @@ -0,0 +1,171 @@ +// RUN: %clang_cc1 %s -std=c++11 -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 %s -std=c++11 -emit-pch -o %t +// RUN: %clang_cc1 %s -std=c++11 -include-pch %t -emit-llvm -o - | FileCheck %s + +#ifndef HEADER +#define HEADER + +typedef __INTPTR_TYPE__ intptr_t; + +// CHECK-DAG: [[CAP_TYPE1:%.+]] = type { [[INTPTR_T:i.+]], [[INTPTR_T]]*, [[INTPTR_T]]* } +// CHECK-DAG: [[CAP_TYPE2:%.+]] = type { [[INTPTR_T]], [[INTPTR_T]]* } +// CHECK-DAG: [[CAP_TYPE3:%.+]] = type { [[INTPTR_T]]*, [[INTPTR_T]], [[INTPTR_T]], [[INTPTR_T]]*, [[INTPTR_T]]* } +// CHECK-DAG: [[CAP_TYPE4:%.+]] = type { [[INTPTR_T]]*, [[INTPTR_T]], [[INTPTR_T]]*, [[INTPTR_T]], [[INTPTR_T]]* } + +// CHECK: define void [[G:@.+]]( +// CHECK: [[N_ADDR:%.+]] = alloca [[INTPTR_T]] +// CHECK: store [[INTPTR_T]] %{{.+}}, [[INTPTR_T]]* [[N_ADDR]] +// CHECK: [[N_VAL:%.+]] = load [[INTPTR_T]]* [[N_ADDR]] +// CHECK: [[CAP_EXPR_REF:%.+]] = getelementptr inbounds [[CAP_TYPE1]]* [[CAP_ARG:%.+]], i{{.+}} 0, i{{.+}} 0 +// CHECK: store [[INTPTR_T]] [[N_VAL]], [[INTPTR_T]]* [[CAP_EXPR_REF]] +// CHECK: [[CAP_BUFFER_ADDR:%.+]] = getelementptr inbounds [[CAP_TYPE1]]* [[CAP_ARG]], i{{.+}} 0, i{{.+}} 1 +// CHECK: store [[INTPTR_T]]* %{{.+}}, [[INTPTR_T]]** [[CAP_BUFFER_ADDR]] +// CHECK: [[CAP_N_REF:%.+]] = getelementptr inbounds [[CAP_TYPE1]]* [[CAP_ARG:%.+]], i{{.+}} 0, i{{.+}} 2 +// CHECK: store [[INTPTR_T]]* [[N_ADDR]], [[INTPTR_T]]** [[CAP_N_REF]] +// CHECK: call void [[G_LAMBDA:@.+]]([[CAP_TYPE1]]* [[CAP_ARG]]) +// CHECK: ret void +void g(intptr_t n) { + intptr_t buffer[n]; + [&buffer, &n]() { + __typeof(buffer) x; + }(); +} + +// CHECK: void [[G_LAMBDA]]([[CAP_TYPE1]]* +// CHECK: [[THIS:%.+]] = load [[CAP_TYPE1]]** +// CHECK: [[N_ADDR:%.+]] = getelementptr inbounds [[CAP_TYPE1]]* [[THIS]], i{{.+}} 0, i{{.+}} 0 +// CHECK: [[N:%.+]] = load [[INTPTR_T]]* [[N_ADDR]] +// CHECK: [[BUFFER_ADDR:%.+]] = getelementptr inbounds [[CAP_TYPE1]]* [[THIS]], i{{.+}} 0, i{{.+}} 1 +// CHECK: [[BUFFER:%.+]] = load [[INTPTR_T]]** [[BUFFER_ADDR]] +// CHECK: call i{{.+}}* @llvm.stacksave() +// CHECK: alloca [[INTPTR_T]], [[INTPTR_T]] [[N]] +// CHECK: call void @llvm.stackrestore( +// CHECK: ret void + +template <typename T> +void f(T n, T m) { + intptr_t buffer[n + m]; + [&buffer]() { + __typeof(buffer) x; + }(); +} + +template <typename T> +intptr_t getSize(T); + +template <typename T> +void b(intptr_t n, T arg) { + typedef intptr_t ArrTy[getSize(arg)]; + ArrTy buffer2; + ArrTy buffer1[n + arg]; + intptr_t a; + [&]() { + n = sizeof(buffer1[n]); + [&](){ + n = sizeof(buffer2); + n = sizeof(buffer1); + }(); + }(); +} + +// CHECK-LABEL: @main +int main() { + // CHECK: call void [[G]]([[INTPTR_T]] [[INTPTR_T_ATTR:(signext )?]]1) + g((intptr_t)1); + // CHECK: call void [[F_INT:@.+]]([[INTPTR_T]] [[INTPTR_T_ATTR]]1, [[INTPTR_T]] [[INTPTR_T_ATTR]]2) + f((intptr_t)1, (intptr_t)2); + // CHECK: call void [[B_INT:@.+]]([[INTPTR_T]] [[INTPTR_T_ATTR]]12, [[INTPTR_T]] [[INTPTR_T_ATTR]]13) + b((intptr_t)12, (intptr_t)13); + // CHECK: ret i32 0 + return 0; +} + +// CHECK: void [[F_INT]]([[INTPTR_T]] +// CHECK: [[SIZE:%.+]] = add +// CHECK: call i{{.+}}* @llvm.stacksave() +// CHECK: [[BUFFER_ADDR:%.+]] = alloca [[INTPTR_T]], [[INTPTR_T]] [[SIZE]] +// CHECK: [[CAP_SIZE_REF:%.+]] = getelementptr inbounds [[CAP_TYPE2]]* [[CAP_ARG:%.+]], i{{.+}} 0, i{{.+}} 0 +// CHECK: store [[INTPTR_T]] [[SIZE]], [[INTPTR_T]]* [[CAP_SIZE_REF]] +// CHECK: [[CAP_BUFFER_ADDR_REF:%.+]] = getelementptr inbounds [[CAP_TYPE2]]* [[CAP_ARG]], i{{.+}} 0, i{{.+}} 1 +// CHECK: store [[INTPTR_T]]* [[BUFFER_ADDR]], [[INTPTR_T]]** [[CAP_BUFFER_ADDR_REF]] +// CHECK: call void [[F_INT_LAMBDA:@.+]]([[CAP_TYPE2]]* [[CAP_ARG]]) +// CHECK: call void @llvm.stackrestore( +// CHECK: ret void +// CHECK: void [[B_INT]]([[INTPTR_T]] +// CHECK: [[SIZE1:%.+]] = call [[INTPTR_T]] +// CHECK: call i{{.+}}* @llvm.stacksave() +// CHECK: [[BUFFER2_ADDR:%.+]] = alloca [[INTPTR_T]], [[INTPTR_T]] [[SIZE1]] +// CHECK: [[SIZE2:%.+]] = add +// CHECK: [[BUFFER1_ADDR:%.+]] = alloca [[INTPTR_T]], [[INTPTR_T]] +// CHECK: [[CAP_N_ADDR_REF:%.+]] = getelementptr inbounds [[CAP_TYPE3]]* [[CAP_ARG:%.+]], i{{.+}} 0, i{{.+}} 0 +// CHECK: store [[INTPTR_T]]* {{%.+}}, [[INTPTR_T]]** [[CAP_N_ADDR_REF]] +// CHECK: [[CAP_SIZE2_REF:%.+]] = getelementptr inbounds [[CAP_TYPE3]]* [[CAP_ARG]], i{{.+}} 0, i{{.+}} 1 +// CHECK: store i{{[0-9]+}} [[SIZE2]], i{{[0-9]+}}* [[CAP_SIZE2_REF]] +// CHECK: [[CAP_SIZE1_REF:%.+]] = getelementptr inbounds [[CAP_TYPE3]]* [[CAP_ARG]], i{{.+}} 0, i{{.+}} 2 +// CHECK: store i{{[0-9]+}} [[SIZE1]], i{{[0-9]+}}* [[CAP_SIZE1_REF]] +// CHECK: [[CAP_BUFFER1_ADDR_REF:%.+]] = getelementptr inbounds [[CAP_TYPE3]]* [[CAP_ARG]], i{{.+}} 0, i{{.+}} 3 +// CHECK: store [[INTPTR_T]]* [[BUFFER1_ADDR]], [[INTPTR_T]]** [[CAP_BUFFER1_ADDR_REF]] +// CHECK: [[CAP_BUFFER2_ADDR_REF:%.+]] = getelementptr inbounds [[CAP_TYPE3]]* [[CAP_ARG]], i{{.+}} 0, i{{.+}} 4 +// CHECK: store [[INTPTR_T]]* [[BUFFER2_ADDR]], [[INTPTR_T]]** [[CAP_BUFFER2_ADDR_REF]] +// CHECK: call void [[B_INT_LAMBDA:@.+]]([[CAP_TYPE3]]* [[CAP_ARG]]) +// CHECK: call void @llvm.stackrestore( +// CHECK: ret void + +// CHECK: define {{.*}} void [[B_INT_LAMBDA]]([[CAP_TYPE3]]* +// CHECK: [[SIZE2_REF:%.+]] = getelementptr inbounds [[CAP_TYPE3]]* [[THIS:%.+]], i{{[0-9]+}} 0, i{{[0-9]+}} 1 +// CHECK: [[SIZE2:%.+]] = load i{{[0-9]+}}* [[SIZE2_REF]] +// CHECK: [[SIZE1_REF:%.+]] = getelementptr inbounds [[CAP_TYPE3]]* [[THIS]], i{{[0-9]+}} 0, i{{[0-9]+}} 2 +// CHECK: [[SIZE1:%.+]] = load i{{[0-9]+}}* [[SIZE1_REF]] +// CHECK: [[N_ADDR_REF:%.+]] = getelementptr inbounds [[CAP_TYPE3]]* [[THIS]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 +// CHECK: [[N_ADDR:%.+]] = load [[INTPTR_T]]** [[N_ADDR_REF]] +// CHECK: [[N:%.+]] = load [[INTPTR_T]]* [[N_ADDR]] +// CHECK: [[BUFFER1_ADDR_REF:%.+]] = getelementptr inbounds [[CAP_TYPE3]]* [[THIS]], i{{[0-9]+}} 0, i{{[0-9]+}} 3 +// CHECK: [[BUFFER1_ADDR:%.+]] = load [[INTPTR_T]]** [[BUFFER1_ADDR_REF]] +// CHECK: [[ELEM_OFFSET:%.+]] = mul {{.*}} i{{[0-9]+}} [[N]], [[SIZE1]] +// CHECK: [[ELEM_ADDR:%.+]] = getelementptr inbounds [[INTPTR_T]]* [[BUFFER1_ADDR]], i{{[0-9]+}} [[ELEM_OFFSET]] +// CHECK: [[SIZEOF:%.+]] = mul {{.*}} i{{[0-9]+}} {{[0-9]+}}, [[SIZE1]] +// CHECK: [[N_ADDR_REF:%.+]] = getelementptr inbounds [[CAP_TYPE3]]* [[THIS]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 +// CHECK: [[N_ADDR:%.+]] = load [[INTPTR_T]]** [[N_ADDR_REF]] +// CHECK: store [[INTPTR_T]] {{%.+}}, [[INTPTR_T]]* [[N_ADDR]] +// CHECK: [[N_ADDR_REF:%.+]] = getelementptr inbounds [[CAP_TYPE4]]* [[CAP:%.+]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 +// CHECK: [[N_ADDR_REF_ORIG:%.+]] = getelementptr inbounds [[CAP_TYPE3]]* [[THIS]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 +// CHECK: [[N_ADDR_ORIG:%.+]] = load [[INTPTR_T]]** [[N_ADDR_REF_ORIG]] +// CHECK: store [[INTPTR_T]]* [[N_ADDR_ORIG]], [[INTPTR_T]]** [[N_ADDR_REF]] +// CHECK: [[SIZE1_REF:%.+]] = getelementptr inbounds [[CAP_TYPE4]]* [[CAP]], i{{[0-9]+}} 0, i{{[0-9]+}} 1 +// CHECK: store i{{[0-9]+}} [[SIZE1]], i{{[0-9]+}}* [[SIZE1_REF]] +// CHECK: [[BUFFER2_ADDR_REF:%.+]] = getelementptr inbounds [[CAP_TYPE4]]* [[CAP]], i{{[0-9]+}} 0, i{{[0-9]+}} 2 +// CHECK: [[BUFFER2_ADDR_REF_ORIG:%.+]] = getelementptr inbounds [[CAP_TYPE3]]* [[THIS]], i{{[0-9]+}} 0, i{{[0-9]+}} 4 +// CHECK: [[BUFFER2_ADDR_ORIG:%.+]] = load [[INTPTR_T]]** [[BUFFER2_ADDR_REF_ORIG]] +// CHECK: store [[INTPTR_T]]* [[BUFFER2_ADDR_ORIG]], [[INTPTR_T]]** [[BUFFER2_ADDR_REF]] +// CHECK: [[SIZE2_REF:%.+]] = getelementptr inbounds [[CAP_TYPE4]]* [[CAP]], i{{[0-9]+}} 0, i{{[0-9]+}} 3 +// CHECK: store i{{[0-9]+}} [[SIZE2]], i{{[0-9]+}}* [[SIZE2_REF]] +// CHECK: [[BUFFER1_ADDR_REF:%.+]] = getelementptr inbounds [[CAP_TYPE4]]* [[CAP]], i{{[0-9]+}} 0, i{{[0-9]+}} 4 +// CHECK: [[BUFFER1_ADDR_REF_ORIG:%.+]] = getelementptr inbounds [[CAP_TYPE3]]* [[THIS]], i{{[0-9]+}} 0, i{{[0-9]+}} 3 +// CHECK: [[BUFFER1_ADDR_ORIG:%.+]] = load [[INTPTR_T]]** [[BUFFER1_ADDR_REF_ORIG]] +// CHECK: store [[INTPTR_T]]* [[BUFFER1_ADDR_ORIG]], [[INTPTR_T]]** [[BUFFER1_ADDR_REF]] +// CHECK: call void [[B_INT_LAMBDA_LAMBDA:@.+]]([[CAP_TYPE4]]* [[CAP]]) +// CHECK: ret void + +// CHECK: define {{.*}} void [[B_INT_LAMBDA_LAMBDA]]([[CAP_TYPE4]]* +// CHECK: [[SIZE1_REF:%.+]] = getelementptr inbounds [[CAP_TYPE4]]* [[THIS:%.+]], i{{[0-9]+}} 0, i{{[0-9]+}} 1 +// CHECK: [[SIZE1:%.+]] = load i{{[0-9]+}}* [[SIZE1_REF]] +// CHECK: [[SIZE2_REF:%.+]] = getelementptr inbounds [[CAP_TYPE4]]* [[THIS]], i{{[0-9]+}} 0, i{{[0-9]+}} 3 +// CHECK: [[SIZE2:%.+]] = load i{{[0-9]+}}* [[SIZE2_REF]] +// CHECK: [[BUFFER2_ADDR_REF:%.+]] = getelementptr inbounds [[CAP_TYPE4]]* [[THIS]], i{{[0-9]+}} 0, i{{[0-9]+}} 2 +// CHECK: [[BUFFER2_ADDR:%.+]] = load [[INTPTR_T]]** [[BUFFER2_ADDR_REF]] +// CHECK: [[SIZEOF_BUFFER2:%.+]] = mul {{.*}} i{{[0-9]+}} {{[0-9]+}}, [[SIZE1]] +// CHECK: [[BUFFER1_ADDR_REF:%.+]] = getelementptr inbounds [[CAP_TYPE4]]* [[THIS]], i{{[0-9]+}} 0, i{{[0-9]+}} 4 +// CHECK: [[BUFFER1_ADDR:%.+]] = load [[INTPTR_T]]** [[BUFFER1_ADDR_REF]] +// CHECK: [[MUL:%.+]] = mul {{.*}} i{{[0-9]+}} [[SIZE2]], [[SIZE1]] +// CHECK: mul {{.*}} i{{[0-9]+}} {{[0-9]+}}, [[MUL]] +// CHECK: ret void + +// CHECK: void [[F_INT_LAMBDA]]([[CAP_TYPE2]]* +// CHECK: [[THIS:%.+]] = load [[CAP_TYPE2]]** +// CHECK: [[SIZE_REF:%.+]] = getelementptr inbounds [[CAP_TYPE2]]* [[THIS]], i{{.+}} 0, i{{.+}} 0 +// CHECK: [[SIZE:%.+]] = load [[INTPTR_T]]* [[SIZE_REF]] +// CHECK: call i{{.+}}* @llvm.stacksave() +// CHECK: alloca [[INTPTR_T]], [[INTPTR_T]] [[SIZE]] +// CHECK: call void @llvm.stackrestore( +// CHECK: ret void +#endif diff --git a/test/CodeGenCXX/vlt_to_reference.cpp b/test/CodeGenCXX/vlt_to_reference.cpp new file mode 100644 index 000000000000..49d7f1aa975f --- /dev/null +++ b/test/CodeGenCXX/vlt_to_reference.cpp @@ -0,0 +1,22 @@ +// RUN: %clang_cc1 %s -emit-llvm -o - | FileCheck %s + +// CHECK-LABEL: @main + +struct dyn_array { + int size; + int data[]; +}; + +int foo(dyn_array **&d) { + return (*d)->data[1]; +} + +int main() +{ + dyn_array **d; + return foo(d); + + // CHECK: call {{.+}} @{{.+}}foo{{.+}}( + // CHECK: ret i{{[0-9]+}} +} + diff --git a/test/CodeGenCXX/vtable-align.cpp b/test/CodeGenCXX/vtable-align.cpp new file mode 100644 index 000000000000..f1f10c07df2d --- /dev/null +++ b/test/CodeGenCXX/vtable-align.cpp @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 %s -triple=i386-apple-darwin10 -emit-llvm -o - | FileCheck %s -check-prefix=CHECK-32 +// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s -check-prefix=CHECK-64 + +struct A { + virtual void f(); + virtual void g(); + virtual void h(); +}; + +void A::f() {} + +// CHECK-32: @_ZTV1A = unnamed_addr constant [5 x i8*] [i8* null, i8* bitcast ({ i8*, i8* }* @_ZTI1A to i8*), i8* bitcast (void (%struct.A*)* @_ZN1A1fEv to i8*), i8* bitcast (void (%struct.A*)* @_ZN1A1gEv to i8*), i8* bitcast (void (%struct.A*)* @_ZN1A1hEv to i8*)], align 4 + +// CHECK-64: @_ZTV1A = unnamed_addr constant [5 x i8*] [i8* null, i8* bitcast ({ i8*, i8* }* @_ZTI1A to i8*), i8* bitcast (void (%struct.A*)* @_ZN1A1fEv to i8*), i8* bitcast (void (%struct.A*)* @_ZN1A1gEv to i8*), i8* bitcast (void (%struct.A*)* @_ZN1A1hEv to i8*)], align 8 diff --git a/test/CodeGenCXX/vtable-holder-self-reference.cpp b/test/CodeGenCXX/vtable-holder-self-reference.cpp new file mode 100644 index 000000000000..05e6d71bae9c --- /dev/null +++ b/test/CodeGenCXX/vtable-holder-self-reference.cpp @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 -emit-llvm -gdwarf-2 -x c++ -o - %s | FileCheck %s +// +// PR21941: crasher for self-referencing DW_TAG_structure_type node. If we get +// rid of self-referenceing structure_types (PR21902), then it should be safe +// to just kill this test. +// +// CHECK: ![[SELF:[0-9]+]] = distinct !{!"0x13\00B\00{{[^"]*}}", {{[^,]+}}, {{[^,]+}}, {{[^,]+}}, {{[^,]+}}, ![[SELF]], {{[^}]+}}} ; [ DW_TAG_structure_type ] [B] + +void foo() { + struct V { + int vi; + }; + struct B : virtual V {}; + B b; +} diff --git a/test/CodeGenCXX/vtable-pointer-initialization.cpp b/test/CodeGenCXX/vtable-pointer-initialization.cpp index 85e08d8f0f9b..835760d165c0 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 i8** getelementptr inbounds ([3 x i8*]* @_ZTV1A, i64 0, i64 2) +// CHECK: store i32 (...)** bitcast (i8** getelementptr inbounds ([3 x i8*]* @_ZTV1A, i64 0, i64 2) to i32 (...)**) // CHECK: call void @_ZN5FieldC1Ev( // CHECK: ret void A::A() { } // CHECK-LABEL: define void @_ZN1AD2Ev(%struct.A* %this) unnamed_addr -// CHECK: store i8** getelementptr inbounds ([3 x i8*]* @_ZTV1A, i64 0, i64 2) +// CHECK: store i32 (...)** bitcast (i8** getelementptr inbounds ([3 x i8*]* @_ZTV1A, i64 0, i64 2) to i32 (...)**) // CHECK: call void @_ZN5FieldD1Ev( // CHECK: call void @_ZN4BaseD2Ev( // CHECK: ret void @@ -45,13 +45,13 @@ void f() { B b; } // CHECK: call void @_ZN1BC2Ev( // CHECK-LABEL: define linkonce_odr void @_ZN1BD1Ev(%struct.B* %this) unnamed_addr -// CHECK: store i8** getelementptr inbounds ([3 x i8*]* @_ZTV1B, i64 0, i64 2) +// CHECK: store i32 (...)** bitcast (i8** getelementptr inbounds ([3 x i8*]* @_ZTV1B, i64 0, i64 2) to i32 (...)**) // CHECK: call void @_ZN5FieldD1Ev( // CHECK: call void @_ZN4BaseD2Ev( // CHECK: ret void // CHECK-LABEL: define linkonce_odr void @_ZN1BC2Ev(%struct.B* %this) unnamed_addr // CHECK: call void @_ZN4BaseC2Ev( -// CHECK: store i8** getelementptr inbounds ([3 x i8*]* @_ZTV1B, i64 0, i64 2) +// CHECK: store i32 (...)** bitcast (i8** getelementptr inbounds ([3 x i8*]* @_ZTV1B, i64 0, i64 2) to i32 (...)**) // CHECK: call void @_ZN5FieldC1Ev // CHECK: ret void diff --git a/test/CodeGenCXX/x86_64-arguments-nacl-x32.cpp b/test/CodeGenCXX/x86_64-arguments-nacl-x32.cpp new file mode 100644 index 000000000000..bb9bd888b20f --- /dev/null +++ b/test/CodeGenCXX/x86_64-arguments-nacl-x32.cpp @@ -0,0 +1,44 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-nacl -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple=x86_64-unknown-linux-gnux32 -emit-llvm -o - %s | FileCheck %s + +struct test_struct {}; +typedef int test_struct::* test_struct_mdp; +typedef int (test_struct::*test_struct_mfp)(); + +// CHECK-LABEL: define i32 @{{.*}}f_mdp{{.*}}(i32 %a) +test_struct_mdp f_mdp(test_struct_mdp a) { return a; } + +// CHECK-LABEL: define {{.*}} @{{.*}}f_mfp{{.*}}(i64 %a.coerce) +test_struct_mfp f_mfp(test_struct_mfp a) { return a; } + +// A struct with <= 12 bytes before a member data pointer should still +// be allowed in registers, since the member data pointer is only 4 bytes. +// CHECK-LABEL: define void @{{.*}}f_struct_with_mdp{{.*}}(i64 %a.coerce0, i64 %a.coerce1) +struct struct_with_mdp { char *a; char *b; char *c; test_struct_mdp d; }; +void f_struct_with_mdp(struct_with_mdp a) { (void)a; } + +struct struct_with_mdp_too_much { + char *a; char *b; char *c; char *d; test_struct_mdp e; +}; +// CHECK-LABEL: define void @{{.*}}f_struct_with_mdp_too_much{{.*}}({{.*}} byval {{.*}} %a) +void f_struct_with_mdp_too_much(struct_with_mdp_too_much a) { + (void)a; +} + +// A struct with <= 8 bytes before a member function pointer should still +// be allowed in registers, since the member function pointer is only 8 bytes. +// CHECK-LABEL: define void @{{.*}}f_struct_with_mfp_0{{.*}}(i64 %a.coerce0, i32 %a.coerce1) +struct struct_with_mfp_0 { char *a; test_struct_mfp b; }; +void f_struct_with_mfp_0(struct_with_mfp_0 a) { (void)a; } + +// CHECK-LABEL: define void @{{.*}}f_struct_with_mfp_1{{.*}}(i64 %a.coerce0, i64 %a.coerce1) +struct struct_with_mfp_1 { char *a; char *b; test_struct_mfp c; }; +void f_struct_with_mfp_1(struct_with_mfp_1 a) { (void)a; } + +// CHECK-LABEL: define void @{{.*}}f_struct_with_mfp_too_much{{.*}}({{.*}} byval {{.*}} %a, i32 %x) +struct struct_with_mfp_too_much { + char *a; char *b; char *c; test_struct_mfp d; +}; +void f_struct_with_mfp_too_much(struct_with_mfp_too_much a, int x) { + (void)a; +} diff --git a/test/CodeGenCXX/x86_64-arguments.cpp b/test/CodeGenCXX/x86_64-arguments.cpp index 2172e0810d75..815ef6111a9a 100644 --- a/test/CodeGenCXX/x86_64-arguments.cpp +++ b/test/CodeGenCXX/x86_64-arguments.cpp @@ -32,6 +32,21 @@ typedef int (s4::*s4_mfp)(); s4_mdp f4_0(s4_mdp a) { return a; } s4_mfp f4_1(s4_mfp a) { return a; } +// A struct with <= one eightbyte before a member data pointer should still +// be allowed in registers. +// CHECK-LABEL: define void @{{.*}}f_struct_with_mdp{{.*}}(i8* %a.coerce0, i64 %a.coerce1) +struct struct_with_mdp { char *a; s4_mdp b; }; +void f_struct_with_mdp(struct_with_mdp a) { (void)a; } + +// A struct with anything before a member function will be too big and +// goes in memory. +// CHECK-LABEL: define void @{{.*}}f_struct_with_mfp_0{{.*}}(%struct{{.*}} byval align 8 %a) +struct struct_with_mfp_0 { char a; s4_mfp b; }; +void f_struct_with_mfp_0(struct_with_mfp_0 a) { (void)a; } + +// CHECK-LABEL: define void @{{.*}}f_struct_with_mfp_1{{.*}}(%struct{{.*}} byval align 8 %a) +struct struct_with_mfp_1 { void *a; s4_mfp b; }; +void f_struct_with_mfp_1(struct_with_mfp_1 a) { (void)a; } namespace PR7523 { struct StringRef { |