diff options
Diffstat (limited to 'test/CodeGenCXX')
51 files changed, 849 insertions, 103 deletions
diff --git a/test/CodeGenCXX/atomic-dllexport.cpp b/test/CodeGenCXX/atomic-dllexport.cpp new file mode 100644 index 000000000000..ae1422243160 --- /dev/null +++ b/test/CodeGenCXX/atomic-dllexport.cpp @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 -triple i686-windows-msvc -emit-llvm -std=c++11 -fms-extensions -O0 -o - %s | FileCheck --check-prefix=M32 %s +// RUN: %clang_cc1 -triple x86_64-windows-msvc -emit-llvm -std=c++11 -fms-extensions -O0 -o - %s | FileCheck --check-prefix=M64 %s + +struct __declspec(dllexport) SomeStruct { + // Copy assignment operator should be produced, and exported: + // M32: define weak_odr dllexport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.SomeStruct* @"\01??4SomeStruct@@QAEAAU0@ABU0@@Z" + // M64: define weak_odr dllexport dereferenceable({{[0-9]+}}) %struct.SomeStruct* @"\01??4SomeStruct@@QEAAAEAU0@AEBU0@@Z" + _Atomic(int) mData; +}; diff --git a/test/CodeGenCXX/cfi-ms-rtti.cpp b/test/CodeGenCXX/cfi-ms-rtti.cpp index fbebad4b1b8d..328297d85c12 100644 --- a/test/CodeGenCXX/cfi-ms-rtti.cpp +++ b/test/CodeGenCXX/cfi-ms-rtti.cpp @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -flto -emit-llvm -o - -triple=x86_64-pc-win32 %s -fsanitize=cfi-vcall | FileCheck --check-prefix=RTTI %s -// RUN: %clang_cc1 -flto -emit-llvm -o - -triple=x86_64-pc-win32 %s -fsanitize=cfi-vcall -fno-rtti-data | FileCheck --check-prefix=NO-RTTI %s +// RUN: %clang_cc1 -flto -flto-unit -emit-llvm -o - -triple=x86_64-pc-win32 %s -fsanitize=cfi-vcall | FileCheck --check-prefix=RTTI %s +// RUN: %clang_cc1 -flto -flto-unit -emit-llvm -o - -triple=x86_64-pc-win32 %s -fsanitize=cfi-vcall -fno-rtti-data | FileCheck --check-prefix=NO-RTTI %s struct A { A(); diff --git a/test/CodeGenCXX/constructors.cpp b/test/CodeGenCXX/constructors.cpp index ecbe5bb45b63..a89814038340 100644 --- a/test/CodeGenCXX/constructors.cpp +++ b/test/CodeGenCXX/constructors.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -triple x86_64-apple-darwin10 %s -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 %s -emit-llvm -o - | FileCheck %s --implicit-check-not=should_not_appear_in_output struct Member { int x; Member(); Member(int); Member(const Member &); }; struct VBase { int x; VBase(); VBase(int); VBase(const VBase &); }; @@ -109,3 +109,57 @@ namespace test1 { // CHECK: [[THIS:%.*]] = load [[B:%.*]]*, [[B:%.*]]** // CHECK-NEXT: ret void } + +// Ensure that we +// a) emit the ABI-required but useless complete object and deleting destructor +// symbols for an abstract class, and +// b) do *not* emit references to virtual base destructors for an abstract class +// +// Our approach to this is to give these functions a body that simply traps. +// +// FIXME: We should ideally not create these symbols at all, but Clang can +// actually generate references to them in other TUs in some cases, so we can't +// stop emitting them without breaking ABI. See: +// +// https://github.com/itanium-cxx-abi/cxx-abi/issues/10 +namespace abstract { + // Note, the destructor of this class is not instantiated here. + template<typename T> struct should_not_appear_in_output { + ~should_not_appear_in_output() { int arr[-(int)sizeof(T)]; } + }; + + struct X { ~X(); }; + + struct A : virtual should_not_appear_in_output<int>, X { + virtual ~A() = 0; + }; + + // CHECK-LABEL: define void @_ZN8abstract1AD2Ev( + // CHECK: call {{.*}}@_ZN8abstract1XD2Ev( + // CHECK: ret + + // CHECK-LABEL: define void @_ZN8abstract1AD1Ev( + // CHECK: call {{.*}}@llvm.trap( + // CHECK: unreachable + + // CHECK-LABEL: define void @_ZN8abstract1AD0Ev( + // CHECK: call {{.*}}@llvm.trap( + // CHECK: unreachable + A::~A() {} + + struct B : virtual should_not_appear_in_output<int>, X { + virtual void f() = 0; + ~B(); + }; + + // CHECK-LABEL: define void @_ZN8abstract1BD2Ev( + // CHECK: call {{.*}}@_ZN8abstract1XD2Ev( + // CHECK: ret + + // CHECK-LABEL: define void @_ZN8abstract1BD1Ev( + // CHECK: call {{.*}}@llvm.trap( + // CHECK: unreachable + + // CHECK-NOT: @_ZN8abstract1BD0Ev( + B::~B() {} +} diff --git a/test/CodeGenCXX/cxx11-initializer-aggregate.cpp b/test/CodeGenCXX/cxx11-initializer-aggregate.cpp index be4fd73e6c21..8bf35966f5b9 100644 --- a/test/CodeGenCXX/cxx11-initializer-aggregate.cpp +++ b/test/CodeGenCXX/cxx11-initializer-aggregate.cpp @@ -2,7 +2,16 @@ struct A { int a, b; int f(); }; -// CHECK: define {{.*}}@_Z3fn1i( +namespace NonAggregateCopyInAggregateInit { // PR32044 + struct A { constexpr A(int n) : x(n), y() {} int x, y; } extern a; + // CHECK-DAG: @_ZN31NonAggregateCopyInAggregateInit1bE = global %{{.*}} { %[[A:.*]]* @_ZN31NonAggregateCopyInAggregateInit1aE } + struct B { A &p; } b{{a}}; + // CHECK-DAG: @_ZGRN31NonAggregateCopyInAggregateInit1cE_ = internal global %[[A]] { i32 1, i32 0 } + // CHECK-DAG: @_ZN31NonAggregateCopyInAggregateInit1cE = global %{{.*}} { %{{.*}}* @_ZGRN31NonAggregateCopyInAggregateInit1cE_ } + struct C { A &&p; } c{{1}}; +} + +// CHECK-LABEL: define {{.*}}@_Z3fn1i( int fn1(int x) { // CHECK: %[[INITLIST:.*]] = alloca %struct.A // CHECK: %[[A:.*]] = getelementptr inbounds %struct.A, %struct.A* %[[INITLIST]], i32 0, i32 0 @@ -15,7 +24,7 @@ int fn1(int x) { struct B { int &r; int &f() { return r; } }; -// CHECK: define {{.*}}@_Z3fn2Ri( +// CHECK-LABEL: define {{.*}}@_Z3fn2Ri( int &fn2(int &v) { // CHECK: %[[INITLIST2:.*]] = alloca %struct.B, align 8 // CHECK: %[[R:.*]] = getelementptr inbounds %struct.B, %struct.B* %[[INITLIST2:.*]], i32 0, i32 0 @@ -24,7 +33,7 @@ int &fn2(int &v) { return B{v}.f(); } -// CHECK: define {{.*}}@__cxx_global_var_init( +// CHECK-LABEL: define {{.*}}@__cxx_global_var_init( // // CHECK: call {{.*}}@_ZN14NonTrivialInit1AC1Ev( // CHECK: getelementptr inbounds {{.*}}, i64 1 diff --git a/test/CodeGenCXX/debug-info-class-optzns.cpp b/test/CodeGenCXX/debug-info-class-optzns.cpp new file mode 100644 index 000000000000..d58510b7155a --- /dev/null +++ b/test/CodeGenCXX/debug-info-class-optzns.cpp @@ -0,0 +1,26 @@ +// RUN: %clang_cc1 -triple x86_64-unknown_unknown -emit-llvm -debug-info-kind=limited %s -O1 -o - | FileCheck %s + +// Ensure class definitions are not emitted to debug info just because the +// vtable is emitted for optimization purposes (as available_externally). The +// class definition debug info should only go where the vtable is actually +// emitted into the object file. + +// CHECK: @_ZTV3foo = available_externally + +// Verify that this doesn't involve querying for the vtable of types that aren't +// dynamic (that would cause an assertion in the case below) + +// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "bar<int>" +template <typename> struct bar {}; +extern template struct bar<int>; +bar<int> *p1; +bar<int> a; + +// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "foo" +// CHECK-SAME: DIFlagFwdDecl + +struct foo { + virtual void f(); +}; + +foo f; diff --git a/test/CodeGenCXX/debug-info-inheriting-constructor.cpp b/test/CodeGenCXX/debug-info-inheriting-constructor.cpp new file mode 100644 index 000000000000..e3708e2080f0 --- /dev/null +++ b/test/CodeGenCXX/debug-info-inheriting-constructor.cpp @@ -0,0 +1,25 @@ +// RUN: %clang_cc1 -debug-info-kind=standalone -std=c++11 -triple x86_64-darwin -emit-llvm -o - %s | FileCheck %s + +struct A { + A(int, ...); +}; +struct B : A { + using A::A; +}; + +A::A(int i, ...) {} +// CHECK: define void @{{.*}}foo +// CHECK-NOT ret void +// CHECK: call void @llvm.dbg.declare +// CHECK-NOT ret void +// CHECK: call void @llvm.dbg.declare(metadata %{{.*}}** %{{[^,]+}}, +// CHECK-SAME: metadata ![[THIS:[0-9]+]], metadata !{{[0-9]+}}), !dbg ![[LOC:[0-9]+]] +// CHECK: ret void, !dbg ![[NOINL:[0-9]+]] +// CHECK: ![[FOO:.*]] = distinct !DISubprogram(name: "foo" +// CHECK-DAG: ![[A:.*]] = distinct !DISubprogram(name: "A", linkageName: "_ZN1BCI11AEiz" +void foo() { +// CHECK-DAG: ![[LOC]] = !DILocation(line: 0, scope: ![[A]], inlinedAt: ![[INL:[0-9]+]]) +// CHECK-DAG: ![[INL]] = !DILocation(line: [[@LINE+1]], scope: ![[FOO]]) + B b(0); +// CHECK: ![[NOINL]] = !DILocation(line: [[@LINE+1]], scope: !{{[0-9]+}}) +} diff --git a/test/CodeGenCXX/debug-info-ms-dtor-thunks.cpp b/test/CodeGenCXX/debug-info-ms-dtor-thunks.cpp new file mode 100644 index 000000000000..f876267eb5d6 --- /dev/null +++ b/test/CodeGenCXX/debug-info-ms-dtor-thunks.cpp @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 -triple i686--windows -emit-llvm -debug-info-kind=line-tables-only -x c++ %s -fms-extensions -o - | FileCheck %s + +struct __declspec(dllexport) S { virtual ~S(); }; +struct __declspec(dllexport) T { virtual ~T(); }; +struct __declspec(dllexport) U : S, T { virtual ~U(); }; + +// CHECK-LABEL: define {{.*}} @"\01??_GS@@UAEPAXI@Z" +// CHECK: call x86_thiscallcc void @"\01??_DS@@QAEXXZ"(%struct.S* %this1){{.*}}!dbg !{{[0-9]+}} + +// CHECK-LABEL: define {{.*}} @"\01??_GT@@UAEPAXI@Z" +// CHECK: call x86_thiscallcc void @"\01??_DT@@QAEXXZ"(%struct.T* %this1){{.*}}!dbg !{{[0-9]+}} + +// CHECK-LABEL: define {{.*}} @"\01??_GU@@UAEPAXI@Z" +// CHECK: call x86_thiscallcc void @"\01??_DU@@QAEXXZ"(%struct.U* %this1){{.*}}!dbg !{{[0-9]+}} diff --git a/test/CodeGenCXX/debug-info-template-deduction-guide.cpp b/test/CodeGenCXX/debug-info-template-deduction-guide.cpp new file mode 100644 index 000000000000..26eb2156e627 --- /dev/null +++ b/test/CodeGenCXX/debug-info-template-deduction-guide.cpp @@ -0,0 +1,17 @@ +// RUN: %clang -S -emit-llvm -target x86_64-unknown_unknown -g %s -o - -std=c++1z | FileCheck %s + +// Verify that we don't crash when emitting debug information for objects +// created from a deduced template specialization. + +template <class T> +struct S { + S(T) {} +}; + +// CHECK: !DIGlobalVariable(name: "s1" +// CHECK-SAME: type: [[TYPE_NUM:![0-9]+]] +// CHECK: !DIGlobalVariable(name: "s2" +// CHECK-SAME: type: [[TYPE_NUM]] +// CHECK: [[TYPE_NUM]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "S<int>", +S s1(42); +S<int> s2(42); diff --git a/test/CodeGenCXX/debug-info-use-after-free.cpp b/test/CodeGenCXX/debug-info-use-after-free.cpp index f87763b9050d..100124889734 100644 --- a/test/CodeGenCXX/debug-info-use-after-free.cpp +++ b/test/CodeGenCXX/debug-info-use-after-free.cpp @@ -1,4 +1,6 @@ // RUN: %clang_cc1 -debug-info-kind=limited -triple %itanium_abi_triple -emit-llvm-only %s +// RUN: %clang_cc1 -debug-info-kind=limited -triple %itanium_abi_triple -emit-llvm-only -std=c++98 %s +// RUN: %clang_cc1 -debug-info-kind=limited -triple %itanium_abi_triple -emit-llvm-only -std=c++11 %s // Check that we don't crash. // PR12305, PR12315 @@ -233,6 +235,7 @@ template < class > class scoped_ptr { namespace { class AAA { +protected: virtual ~ AAA () { }}; diff --git a/test/CodeGenCXX/destructors.cpp b/test/CodeGenCXX/destructors.cpp index b082908b2c94..180e82de9fff 100644 --- a/test/CodeGenCXX/destructors.cpp +++ b/test/CodeGenCXX/destructors.cpp @@ -309,7 +309,7 @@ namespace test5 { // CHECK5v03-NEXT: [[EXN:%.*]] = alloca i8* // CHECK5v03-NEXT: [[SEL:%.*]] = alloca i32 // CHECK5-NEXT: [[PELEMS:%.*]] = bitcast [5 x [[A]]]* [[ELEMS]] to i8* - // CHECK5-NEXT: call void @llvm.lifetime.start(i64 5, i8* [[PELEMS]]) + // CHECK5-NEXT: call void @llvm.lifetime.start.p0i8(i64 5, i8* [[PELEMS]]) // CHECK5-NEXT: [[BEGIN:%.*]] = getelementptr inbounds [5 x [[A]]], [5 x [[A]]]* [[ELEMS]], i32 0, i32 0 // CHECK5-NEXT: [[END:%.*]] = getelementptr inbounds [[A]], [[A]]* [[BEGIN]], i64 5 // CHECK5-NEXT: br label @@ -484,29 +484,29 @@ namespace test11 { // CHECK6: {{^}}invoke.cont // CHECK6: call void @_ZN6test112S1D1Ev(%"struct.test11::S1"* [[T1]]) // CHECK6: [[BC1:%[a-z0-9]+]] = bitcast %"struct.test11::S1"* [[T1]] to i8* -// CHECK6: call void @llvm.lifetime.end(i64 32, i8* [[BC1]]) +// CHECK6: call void @llvm.lifetime.end.p0i8(i64 32, i8* [[BC1]]) // CHECK6: {{^}}lpad // CHECK6: call void @_ZN6test112S1D1Ev(%"struct.test11::S1"* [[T1]]) // CHECK6: [[BC2:%[a-z0-9]+]] = bitcast %"struct.test11::S1"* [[T1]] to i8* -// CHECK6: call void @llvm.lifetime.end(i64 32, i8* [[BC2]]) +// CHECK6: call void @llvm.lifetime.end.p0i8(i64 32, i8* [[BC2]]) // CHECK6: {{^}}invoke.cont // CHECK6: call void @_ZN6test112S1D1Ev(%"struct.test11::S1"* [[T2]]) // CHECK6: [[BC3:%[a-z0-9]+]] = bitcast %"struct.test11::S1"* [[T2]] to i8* -// CHECK6: call void @llvm.lifetime.end(i64 32, i8* [[BC3]]) +// CHECK6: call void @llvm.lifetime.end.p0i8(i64 32, i8* [[BC3]]) // CHECK6: {{^}}lpad // CHECK6: call void @_ZN6test112S1D1Ev(%"struct.test11::S1"* [[T2]]) // CHECK6: [[BC4:%[a-z0-9]+]] = bitcast %"struct.test11::S1"* [[T2]] to i8* -// CHECK6: call void @llvm.lifetime.end(i64 32, i8* [[BC4]]) +// CHECK6: call void @llvm.lifetime.end.p0i8(i64 32, i8* [[BC4]]) // CHECK6: {{^}}invoke.cont // CHECK6: call void @_ZN6test112S1D1Ev(%"struct.test11::S1"* [[T3]]) // CHECK6: [[BC5:%[a-z0-9]+]] = bitcast %"struct.test11::S1"* [[T3]] to i8* -// CHECK6: call void @llvm.lifetime.end(i64 32, i8* [[BC5]]) +// CHECK6: call void @llvm.lifetime.end.p0i8(i64 32, i8* [[BC5]]) // CHECK6: {{^}}lpad // CHECK6: call void @_ZN6test112S1D1Ev(%"struct.test11::S1"* [[T3]]) // CHECK6: [[BC6:%[a-z0-9]+]] = bitcast %"struct.test11::S1"* [[T3]] to i8* -// CHECK6: call void @llvm.lifetime.end(i64 32, i8* [[BC6]]) +// CHECK6: call void @llvm.lifetime.end.p0i8(i64 32, i8* [[BC6]]) struct S1 { ~S1(); diff --git a/test/CodeGenCXX/dllexport.cpp b/test/CodeGenCXX/dllexport.cpp index 33e524cc9b01..bdef2eb06e69 100644 --- a/test/CodeGenCXX/dllexport.cpp +++ b/test/CodeGenCXX/dllexport.cpp @@ -108,8 +108,8 @@ inline int __declspec(dllexport) inlineStaticLocalsFunc() { template<typename T> __declspec(dllexport) int VarTmplDef; INSTVAR(VarTmplDef<ExplicitInst_Exported>) -// MSC-DAG: @"\01??$VarTmplImplicitDef@UImplicitInst_Exported@@@@3HA" = external dllexport global -// GNU-DAG: @_Z18VarTmplImplicitDefI21ImplicitInst_ExportedE = external dllexport global +// MSC-DAG: @"\01??$VarTmplImplicitDef@UImplicitInst_Exported@@@@3HA" = external global +// GNU-DAG: @_Z18VarTmplImplicitDefI21ImplicitInst_ExportedE = external global template<typename T> __declspec(dllexport) int VarTmplImplicitDef; USEVAR(VarTmplImplicitDef<ImplicitInst_Exported>) @@ -528,7 +528,7 @@ struct __declspec(dllexport) T { // M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?a@T@@QAEXXZ" static int b; - // M32-DAG: @"\01?b@T@@2HA" = external dllexport global i32 + // M32-DAG: @"\01?b@T@@2HA" = external global i32 static int c; // M32-DAG: @"\01?c@T@@2HA" = dllexport global i32 0, align 4 diff --git a/test/CodeGenCXX/dllimport.cpp b/test/CodeGenCXX/dllimport.cpp index 4ec14b72109f..372a96ba2efe 100644 --- a/test/CodeGenCXX/dllimport.cpp +++ b/test/CodeGenCXX/dllimport.cpp @@ -26,6 +26,7 @@ struct ExplicitSpec_NotImported {}; #define USEVARTYPE(type, var) type UNIQ(use)() { return var; } #define USEVAR(var) USEVARTYPE(int, var) #define USE(func) void UNIQ(use)() { func(); } +#define USE1(func) void UNIQ(use)() { func(nullptr); } #define USEMEMFUNC(class, func) void (class::*UNIQ(use)())() { return &class::func; } #define USESTATICMEMFUNC(class, func) void (*UNIQ(use)())() { return &class::func; } #define USECLASS(class) void UNIQ(USE)() { class x; } @@ -316,10 +317,13 @@ namespace ns { __declspec(dllimport) void externalFunc(); } USE(ns::externalFunc) // A dllimport function referencing non-imported vars or functions must not be available_externally. + __declspec(dllimport) int ImportedVar; int NonImportedVar; __declspec(dllimport) int ImportedFunc(); int NonImportedFunc(); +struct ClassWithNonImportedMethod { int f(); }; + __declspec(dllimport) inline int ReferencingImportedVar() { return ImportedVar; } // MO1-DAG: define available_externally dllimport i32 @"\01?ReferencingImportedVar@@YAHXZ" __declspec(dllimport) inline int ReferencingNonImportedVar() { return NonImportedVar; } @@ -328,10 +332,16 @@ __declspec(dllimport) inline int ReferencingImportedFunc() { return ImportedFunc // MO1-DAG: define available_externally dllimport i32 @"\01?ReferencingImportedFunc@@YAHXZ" __declspec(dllimport) inline int ReferencingNonImportedFunc() { return NonImportedFunc(); } // MO1-DAG: declare dllimport i32 @"\01?ReferencingNonImportedFunc@@YAHXZ"() +__declspec(dllimport) inline int ReferencingNonImportedMethod(ClassWithNonImportedMethod *x) { return x->f(); } +// MO1-DAG: declare dllimport i32 @"\01?ReferencingNonImportedMethod +__declspec(dllimport) inline int ReferencingClassMemberPtr(int (ClassWithNonImportedMethod::*p)(), ClassWithNonImportedMethod *x) { return (x->*p)(); } +// MO1-DAG: define available_externally dllimport i32 @"\01?ReferencingClassMemberPtr@@YAHP8ClassWithNonImportedMethod@@AEHXZPAU1@@Z" USE(ReferencingImportedVar) USE(ReferencingNonImportedVar) USE(ReferencingImportedFunc) USE(ReferencingNonImportedFunc) +USE1(ReferencingNonImportedMethod) +void UNIQ(use)() { ReferencingClassMemberPtr(&ClassWithNonImportedMethod::f, nullptr); } // References to operator new and delete count too, despite not being DeclRefExprs. __declspec(dllimport) inline int *ReferencingNonImportedNew() { return new int[2]; } // MO1-DAG: declare dllimport i32* @"\01?ReferencingNonImportedNew@@YAPAHXZ" @@ -348,7 +358,7 @@ __declspec(dllimport) inline int *ReferencingImportedDelete() { delete (int*)nul USE(ReferencingImportedNew) USE(ReferencingImportedDelete) struct ClassWithDtor { ~ClassWithDtor() {} }; -struct __declspec(dllimport) ClassWithNonDllImportField { ClassWithDtor t; }; +struct __declspec(dllimport) ClassWithNonDllImportField { using X = ClassWithDtor; X t[2]; }; struct __declspec(dllimport) ClassWithNonDllImportBase : public ClassWithDtor { }; USECLASS(ClassWithNonDllImportField); USECLASS(ClassWithNonDllImportBase); @@ -358,6 +368,13 @@ struct ClassWithCtor { ClassWithCtor() {} }; struct __declspec(dllimport) ClassWithNonDllImportFieldWithCtor { ClassWithCtor t; }; USECLASS(ClassWithNonDllImportFieldWithCtor); // MO1-DAG: declare dllimport x86_thiscallcc %struct.ClassWithNonDllImportFieldWithCtor* @"\01??0ClassWithNonDllImportFieldWithCtor@@QAE@XZ"(%struct.ClassWithNonDllImportFieldWithCtor* returned) +struct ClassWithImplicitDtor { __declspec(dllimport) ClassWithImplicitDtor(); ClassWithDtor member; }; +__declspec(dllimport) inline void ReferencingDtorThroughDefinition() { ClassWithImplicitDtor x; }; +USE(ReferencingDtorThroughDefinition) +// MO1-DAG: declare dllimport void @"\01?ReferencingDtorThroughDefinition@@YAXXZ"() +__declspec(dllimport) inline void ReferencingDtorThroughTemporary() { ClassWithImplicitDtor(); }; +USE(ReferencingDtorThroughTemporary) +// MO1-DAG: declare dllimport void @"\01?ReferencingDtorThroughTemporary@@YAXXZ"() // A dllimport function with a TLS variable must not be available_externally. __declspec(dllimport) inline void FunctionWithTLSVar() { static __thread int x = 42; } @@ -395,17 +412,17 @@ USE(inlineFuncTmpl1<ImplicitInst_Imported>) template<typename T> inline void __attribute__((dllimport)) inlineFuncTmpl2() {} USE(inlineFuncTmpl2<ImplicitInst_Imported>) -// MSC-DAG: declare dllimport void @"\01??$inlineFuncTmplDecl@UImplicitInst_Imported@@@@YAXXZ"() +// MSC-DAG: define linkonce_odr void @"\01??$inlineFuncTmplDecl@UImplicitInst_Imported@@@@YAXXZ"() // GNU-DAG: define linkonce_odr void @_Z18inlineFuncTmplDeclI21ImplicitInst_ImportedEvv() -// MO1-DAG: define available_externally dllimport void @"\01??$inlineFuncTmplDecl@UImplicitInst_Imported@@@@YAXXZ"() +// MO1-DAG: define linkonce_odr void @"\01??$inlineFuncTmplDecl@UImplicitInst_Imported@@@@YAXXZ"() // 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"() +// MSC-DAG: define linkonce_odr void @"\01??$inlineFuncTmplDef@UImplicitInst_Imported@@@@YAXXZ"() // GNU-DAG: define linkonce_odr void @_Z17inlineFuncTmplDefI21ImplicitInst_ImportedEvv() -// MO1-DAG: define available_externally dllimport void @"\01??$inlineFuncTmplDef@UImplicitInst_Imported@@@@YAXXZ"() +// MO1-DAG: define linkonce_odr void @"\01??$inlineFuncTmplDef@UImplicitInst_Imported@@@@YAXXZ"() // GO1-DAG: define linkonce_odr void @_Z17inlineFuncTmplDefI21ImplicitInst_ImportedEvv() template<typename T> __declspec(dllimport) void inlineFuncTmplDef(); template<typename T> inline void inlineFuncTmplDef() {} @@ -439,7 +456,7 @@ USE(funcTmplRedecl3<ImplicitInst_NotImported>) // GNU-DAG: declare void @_Z15funcTmplFriend2I24ImplicitInst_NotImportedEvv() // 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"() +// MSC-DAG: define linkonce_odr void @"\01??$funcTmplFriend4@UImplicitInst_Imported@@@@YAXXZ"() // GNU-DAG: define linkonce_odr void @_Z15funcTmplFriend4I21ImplicitInst_ImportedEvv() struct FuncTmplFriend { template<typename T> friend __declspec(dllimport) void funcTmplFriend1(); diff --git a/test/CodeGenCXX/dynamic-cast-hint.cpp b/test/CodeGenCXX/dynamic-cast-hint.cpp index 27b76e07ffee..f88d39d3113c 100644 --- a/test/CodeGenCXX/dynamic-cast-hint.cpp +++ b/test/CodeGenCXX/dynamic-cast-hint.cpp @@ -1,7 +1,9 @@ // RUN: %clang_cc1 -triple x86_64-apple-darwin12 -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin12 -emit-llvm -std=c++98 -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin12 -emit-llvm -std=c++11 -o - %s | FileCheck %s -class A { virtual ~A() {} }; -class B { virtual ~B() {} }; +class A { protected: virtual ~A() {} }; +class B { protected: virtual ~B() {} }; class C : A { char x; }; class D : public A { short y; }; diff --git a/test/CodeGenCXX/exceptions-cxx-new.cpp b/test/CodeGenCXX/exceptions-cxx-new.cpp index 3329aea32ef2..9836da8e540b 100644 --- a/test/CodeGenCXX/exceptions-cxx-new.cpp +++ b/test/CodeGenCXX/exceptions-cxx-new.cpp @@ -55,12 +55,12 @@ void test_cleanup() { // CHECK: to label %[[LEAVE_FUNC:.*]] unwind label %[[CLEANUP:.*]] // CHECK: [[LEAVE_FUNC]] -// CHECK: call x86_thiscallcc void @"\01??_DCleanup@@QAE@XZ"( +// CHECK: call x86_thiscallcc void @"\01??_DCleanup@@QAEXXZ"( // CHECK: ret void // CHECK: [[CLEANUP]] // CHECK: %[[CLEANUPPAD:.*]] = cleanuppad within none [] -// CHECK: call x86_thiscallcc void @"\01??_DCleanup@@QAE@XZ"( +// CHECK: call x86_thiscallcc void @"\01??_DCleanup@@QAEXXZ"( // CHECK: cleanupret from %[[CLEANUPPAD]] unwind to caller diff --git a/test/CodeGenCXX/exceptions-seh.cpp b/test/CodeGenCXX/exceptions-seh.cpp index 7a11a1e50582..4f7eacd66720 100644 --- a/test/CodeGenCXX/exceptions-seh.cpp +++ b/test/CodeGenCXX/exceptions-seh.cpp @@ -118,7 +118,7 @@ void use_inline() { use_seh_in_inline_func(); } -// CHECK-LABEL: define linkonce_odr void @use_seh_in_inline_func() #{{[0-9]+}} comdat +// CHECK-LABEL: define linkonce_odr void @use_seh_in_inline_func() #{{[0-9]+}} // CHECK-SAME: personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*) // CHECK: invoke void @might_throw() // @@ -134,12 +134,12 @@ void use_inline() { // CHECK: %[[fp:[^ ]*]] = call i8* @llvm.localaddress() // CHECK: call void @"\01?fin$0@0@use_seh_in_inline_func@@"(i8 1, i8* %[[fp]]) -// CHECK-LABEL: define internal i32 @"\01?filt$0@0@use_seh_in_inline_func@@"(i8* %exception_pointers, i8* %frame_pointer) #{{[0-9]+}} comdat($use_seh_in_inline_func) +// CHECK-LABEL: define internal i32 @"\01?filt$0@0@use_seh_in_inline_func@@"(i8* %exception_pointers, i8* %frame_pointer) #{{[0-9]+}} // CHECK: icmp eq i32 %{{.*}}, 424242 // CHECK: zext i1 %{{.*}} to i32 // CHECK: ret i32 -// CHECK-LABEL: define internal void @"\01?fin$0@0@use_seh_in_inline_func@@"(i8 %abnormal_termination, i8* %frame_pointer) #{{[0-9]+}} comdat($use_seh_in_inline_func) +// CHECK-LABEL: define internal void @"\01?fin$0@0@use_seh_in_inline_func@@"(i8 %abnormal_termination, i8* %frame_pointer) #{{[0-9]+}} // CHECK: store i32 1234, i32* @my_unique_global // CHECK: attributes #[[NOINLINE]] = { {{.*noinline.*}} } diff --git a/test/CodeGenCXX/explicit-instantiation.cpp b/test/CodeGenCXX/explicit-instantiation.cpp index fb5711878764..85857fb6fb8c 100644 --- a/test/CodeGenCXX/explicit-instantiation.cpp +++ b/test/CodeGenCXX/explicit-instantiation.cpp @@ -5,6 +5,9 @@ // This check logically is attached to 'template int S<int>::i;' below. // CHECK: @_ZN1SIiE1iE = weak_odr global i32 +// This check is logically attached to 'template int ExportedStaticLocal::f<int>()' below. +// CHECK-OPT: @_ZZN19ExportedStaticLocal1fIiEEvvE1i = linkonce_odr global + template<typename T, typename U, typename Result> struct plus { Result operator()(const T& t, const U& u) const; @@ -153,3 +156,17 @@ template <typename T> void S<T>::f() {} template <typename T> void S<T>::g() {} template <typename T> int S<T>::i; template <typename T> void S<T>::S2::h() {} + +namespace ExportedStaticLocal { +void sink(int&); +template <typename T> +inline void f() { + static int i; + sink(i); +} +// See the check line at the top of the file. +extern template void f<int>(); +void use() { + f<int>(); +} +} diff --git a/test/CodeGenCXX/float128-declarations.cpp b/test/CodeGenCXX/float128-declarations.cpp index e1604a61cac7..f1db8f41c608 100644 --- a/test/CodeGenCXX/float128-declarations.cpp +++ b/test/CodeGenCXX/float128-declarations.cpp @@ -8,6 +8,10 @@ // RUN: %s -o - | FileCheck %s -check-prefix=CHECK-X86 // RUN: %clang_cc1 -emit-llvm -triple systemz-unknown-linux-gnu -std=c++11 \ // RUN: %s -o - | FileCheck %s -check-prefix=CHECK-SYSZ +// RUN: %clang_cc1 -emit-llvm -triple i686-pc-openbsd -std=c++11 \ +// RUN: %s -o - | FileCheck %s -check-prefix=CHECK-X86 +// RUN: %clang_cc1 -emit-llvm -triple amd64-pc-openbsd -std=c++11 \ +// RUN: %s -o - | FileCheck %s -check-prefix=CHECK-X86 // /* Various contexts where type __float128 can appear. The different check prefixes are due to different mangling on X86 and different calling diff --git a/test/CodeGenCXX/global-init.cpp b/test/CodeGenCXX/global-init.cpp index 291b43cac0a0..f96e6032ff58 100644 --- a/test/CodeGenCXX/global-init.cpp +++ b/test/CodeGenCXX/global-init.cpp @@ -15,7 +15,7 @@ struct C { void *field; }; struct D { ~D(); }; -// CHECK: @__dso_handle = external global i8 +// CHECK: @__dso_handle = external hidden global i8 // CHECK: @c = global %struct.C zeroinitializer, align 8 // PR6205: The casts should not require global initializers diff --git a/test/CodeGenCXX/implicit-exception-spec.cpp b/test/CodeGenCXX/implicit-exception-spec.cpp new file mode 100644 index 000000000000..cf363bd685ad --- /dev/null +++ b/test/CodeGenCXX/implicit-exception-spec.cpp @@ -0,0 +1,22 @@ +// RUN: %clang_cc1 %s -triple=x86_64-linux-gnu -emit-llvm -std=c++11 -o - -fcxx-exceptions -fexceptions | FileCheck -check-prefix=CHECK %s + +struct A { + A(); + A(const A&); + A(A&&); +}; +struct B : virtual A { + virtual void f() = 0; +}; +struct C : B { + void f(); +}; + +// CHECK-DAG: define {{.*}} @_ZN1BC2Ev({{.*}} #[[NOUNWIND:[0-9]*]] +C c1; +// CHECK-DAG: define {{.*}} @_ZN1BC2ERKS_({{.*}} #[[NOUNWIND]] +C c2(c1); +// CHECK-DAG: define {{.*}} @_ZN1BC2EOS_({{.*}} #[[NOUNWIND]] +C c3(static_cast<C&&>(c1)); + +// CHECK-DAG: #[[NOUNWIND]] = {{{.*}} nounwind diff --git a/test/CodeGenCXX/inheriting-constructor.cpp b/test/CodeGenCXX/inheriting-constructor.cpp index a3adf70ebb18..1be59b9305d3 100644 --- a/test/CodeGenCXX/inheriting-constructor.cpp +++ b/test/CodeGenCXX/inheriting-constructor.cpp @@ -137,7 +137,7 @@ namespace inalloca_nonvirt { // WIN32: call {{.*}} @"\01??0A@inalloca_nonvirt@@QAE@UQ@@H0$$QAU2@@Z"(%{{[^,]*}}, <{{.*}}>* inalloca %[[ARGMEM]]) // WIN32: call void @llvm.stackrestore( // WIN32: call {{.*}} @"\01??0Z@@QAE@XZ"( - // WIN32: call {{.*}} @"\01??_DQ@@QAE@XZ"( + // WIN32: call {{.*}} @"\01??_DQ@@QAEXXZ"( // On Win64, the Q arguments would be destroyed in the callee. We don't yet // support that in the non-inlined case, so we force inlining. @@ -150,7 +150,7 @@ namespace inalloca_nonvirt { // WIN64: call {{.*}} @"\01??0Z@@QEAA@XZ"( // WIN64: call {{.*}} @"\01??0A@inalloca_nonvirt@@QEAA@UQ@@H0$$QEAU2@@Z"(%{{.*}}, %{{.*}}* %[[ARG1]], i32 2, %{{.*}}* %[[ARG3]], %{{.*}} %[[TMP]]) // WIN64: call {{.*}} @"\01??0Z@@QEAA@XZ"( - // WIN64: call void @"\01??_DQ@@QEAA@XZ"({{.*}}* %[[TMP]]) + // WIN64: call void @"\01??_DQ@@QEAAXXZ"({{.*}}* %[[TMP]]) struct C : B { using B::B; }; C c(1, 2, 3, 4); @@ -173,7 +173,7 @@ namespace inalloca_nonvirt { // WIN32: call {{.*}} @"\01??0A@inalloca_nonvirt@@QAE@UQ@@H0$$QAU2@@Z"(%{{[^,]*}}, <{{.*}}>* inalloca %[[ARGMEM]]) // WIN32: call void @llvm.stackrestore( // WIN32: call {{.*}} @"\01??0Z@@QAE@XZ"( - // WIN32: call {{.*}} @"\01??_DQ@@QAE@XZ"( + // WIN32: call {{.*}} @"\01??_DQ@@QAEXXZ"( // On Win64, the Q arguments would be destroyed in the callee. We don't yet // support that in the non-inlined case, so we force inlining. @@ -186,7 +186,7 @@ namespace inalloca_nonvirt { // WIN64: call {{.*}} @"\01??0Z@@QEAA@XZ"( // WIN64: call {{.*}} @"\01??0A@inalloca_nonvirt@@QEAA@UQ@@H0$$QEAU2@@Z"(%{{.*}}, %{{.*}}* %[[ARG1]], i32 2, %{{.*}}* %[[ARG3]], %{{.*}} %[[TMP]]) // WIN64: call {{.*}} @"\01??0Z@@QEAA@XZ"( - // WIN64: call void @"\01??_DQ@@QEAA@XZ"({{.*}}* %[[TMP]]) + // WIN64: call void @"\01??_DQ@@QEAAXXZ"({{.*}}* %[[TMP]]) } namespace inalloca_virt { @@ -224,7 +224,7 @@ namespace inalloca_virt { // destroy the parameters, but that's not actually possible. // WIN32: call {{.*}} @"\01??0Z@@QAE@XZ"( // WIN32: call {{.*}} @"\01??0Z@@QAE@XZ"( - // WIN32: call {{.*}} @"\01??_DQ@@QAE@XZ"( + // WIN32: call {{.*}} @"\01??_DQ@@QAEXXZ"( // On Win64, the Q arguments would be destroyed in the callee. We don't yet // support that in the non-inlined case, so we force inlining. @@ -239,7 +239,7 @@ namespace inalloca_virt { // WIN64: br // WIN64: call {{.*}} @"\01??0Z@@QEAA@XZ"( // WIN64: call {{.*}} @"\01??0Z@@QEAA@XZ"( - // WIN64: call void @"\01??_DQ@@QEAA@XZ"({{.*}}* %[[TMP]]) + // WIN64: call void @"\01??_DQ@@QEAAXXZ"({{.*}}* %[[TMP]]) struct C : B { using B::B; }; C c(1, 2, 3, 4); @@ -281,7 +281,7 @@ namespace inalloca_virt { // // WIN32: call {{.*}} @"\01??0Z@@QAE@XZ"( // WIN32: call {{.*}} @"\01??0Z@@QAE@XZ"( - // WIN32: call {{.*}} @"\01??_DQ@@QAE@XZ"( + // WIN32: call {{.*}} @"\01??_DQ@@QAEXXZ"( // On Win64, the Q arguments would be destroyed in the callee. We don't yet // support that in the non-inlined case, so we force inlining. @@ -301,7 +301,7 @@ namespace inalloca_virt { // WIN64: br // WIN64: call {{.*}} @"\01??0Z@@QEAA@XZ"( // WIN64: call {{.*}} @"\01??0Z@@QEAA@XZ"( - // WIN64: call void @"\01??_DQ@@QEAA@XZ"({{.*}}* %[[TMP]]) + // WIN64: call void @"\01??_DQ@@QEAAXXZ"({{.*}}* %[[TMP]]) } namespace inline_nonvirt { diff --git a/test/CodeGenCXX/initializer-list-ctor-order.cpp b/test/CodeGenCXX/initializer-list-ctor-order.cpp new file mode 100644 index 000000000000..390fe4f5c304 --- /dev/null +++ b/test/CodeGenCXX/initializer-list-ctor-order.cpp @@ -0,0 +1,29 @@ +// RUN: %clang_cc1 -std=c++11 %s -emit-llvm -o - -triple i686-linux-gnu | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-ITANIUM +// RUN: %clang_cc1 -std=c++11 %s -emit-llvm -o - -triple i686-windows | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-MS + +extern "C" { +int f(); +int g(); +} + +struct A { + A(int, int); +}; + + +void foo() { + A a{f(), g()}; +} +// CHECK-ITANIUM-LABEL: define void @_Z3foov +// CHECK-MS-LABEL: define void @"\01?foo@@YAXXZ" +// CHECK: call i32 @f() +// CHECK: call i32 @g() + +struct B : A { + B(); +}; +B::B() : A{f(), g()} {} +// CHECK-ITANIUM-LABEL: define void @_ZN1BC2Ev +// CHECK-MS-LABEL: define x86_thiscallcc %struct.B* @"\01??0B@@QAE@XZ" +// CHECK: call i32 @f() +// CHECK: call i32 @g() diff --git a/test/CodeGenCXX/linetable-cleanup.cpp b/test/CodeGenCXX/linetable-cleanup.cpp index fbef05e53267..748f056918b9 100644 --- a/test/CodeGenCXX/linetable-cleanup.cpp +++ b/test/CodeGenCXX/linetable-cleanup.cpp @@ -1,10 +1,12 @@ // RUN: %clang_cc1 -emit-llvm -debug-info-kind=limited -triple x86_64-apple-darwin10 %s -o - | FileCheck %s +// RUN: %clang_cc1 -emit-llvm -debug-info-kind=limited -triple x86_64-apple-darwin10 -std=c++98 %s -o - | FileCheck %s +// RUN: %clang_cc1 -emit-llvm -debug-info-kind=limited -triple x86_64-apple-darwin10 -std=c++11 %s -o - | FileCheck %s // Check the line numbers for cleanup code with EH in combination with // simple return expressions. // CHECK: define {{.*}}foo -// CHECK: call void @_ZN1CD1Ev(%class.C* {{.*}}), !dbg ![[RET:[0-9]+]] +// CHECK: call void @_ZN1CD1Ev(%class.C* {{.*}}){{( #[0-9])?}}, !dbg ![[RET:[0-9]+]] // CHECK: ret i32 0, !dbg ![[RET]] // CHECK: define {{.*}}bar diff --git a/test/CodeGenCXX/lpad-linetable.cpp b/test/CodeGenCXX/lpad-linetable.cpp index 69236693c9c2..9b429bc2a223 100644 --- a/test/CodeGenCXX/lpad-linetable.cpp +++ b/test/CodeGenCXX/lpad-linetable.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -emit-llvm -debug-info-kind=limited -triple x86_64-apple-darwin10 %s -o - | FileCheck %s +// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -emit-llvm -debug-info-kind=limited -triple x86_64-apple-darwin10 -std=c++98 %s -o - | FileCheck %s // The landing pad should have the line number of the closing brace of the function. // rdar://problem/13888152 // CHECK: ret i32 diff --git a/test/CodeGenCXX/mangle-unnamed.cpp b/test/CodeGenCXX/mangle-unnamed.cpp index 43b7bd79537d..c90f47b26e70 100644 --- a/test/CodeGenCXX/mangle-unnamed.cpp +++ b/test/CodeGenCXX/mangle-unnamed.cpp @@ -48,6 +48,7 @@ int f5() { return a; } +#if __cplusplus <= 199711L int f6() { static union { union { @@ -56,9 +57,10 @@ int f6() { int b; }; - // CHECK: _ZZ2f6vE1b + // CXX98: _ZZ2f6vE1b return b; } +#endif int f7() { static union { diff --git a/test/CodeGenCXX/mangle.cpp b/test/CodeGenCXX/mangle.cpp index 3a94071294d3..91fe6aeef298 100644 --- a/test/CodeGenCXX/mangle.cpp +++ b/test/CodeGenCXX/mangle.cpp @@ -1125,3 +1125,15 @@ namespace test57 { // CHECK-LABEL: @_ZN6test571fILi0EEEvDTplcldtL_ZNS_1xEE1fIXLi0EEEET_E template void f<0>(int); } + +namespace test58 { + struct State { + bool m_fn1(); + } a; + template <class T> struct identity { typedef T type; }; + struct A { + template <typename T> A(T, bool (identity<T>::type::*)()); + }; + // CHECK-LABEL: @_ZN6test581AC1INS_5StateEEET_MNS_8identityIS3_E4typeEFbvE + void fn1() { A(a, &State::m_fn1); } +} diff --git a/test/CodeGenCXX/microsoft-abi-dynamic-cast.cpp b/test/CodeGenCXX/microsoft-abi-dynamic-cast.cpp index f03cd6c5632b..f3e43079c3eb 100644 --- a/test/CodeGenCXX/microsoft-abi-dynamic-cast.cpp +++ b/test/CodeGenCXX/microsoft-abi-dynamic-cast.cpp @@ -138,6 +138,6 @@ S3 *f(S2 &s) { // CHECK: [[CALL:%.*]] = invoke i8* @__RTDynamicCast // CHECK: [[BC:%.*]] = bitcast i8* [[CALL]] to %"struct.PR25606::S3"* -// CHECK: call x86_thiscallcc void @"\01??_DCleanup@PR25606@@QAE@XZ"( +// CHECK: call x86_thiscallcc void @"\01??_DCleanup@PR25606@@QAEXXZ"( // CHECK: ret %"struct.PR25606::S3"* [[BC]] } diff --git a/test/CodeGenCXX/microsoft-abi-eh-cleanups.cpp b/test/CodeGenCXX/microsoft-abi-eh-cleanups.cpp index 79ac1e12173b..96b4fa3478a2 100644 --- a/test/CodeGenCXX/microsoft-abi-eh-cleanups.cpp +++ b/test/CodeGenCXX/microsoft-abi-eh-cleanups.cpp @@ -259,14 +259,14 @@ void f() { // WIN32-LIFETIME-LABEL: define void @"\01?f@lifetime_marker@@YAXXZ"() // WIN32-LIFETIME: %[[c:.*]] = alloca %"struct.lifetime_marker::C" // WIN32-LIFETIME: %[[bc0:.*]] = bitcast %"struct.lifetime_marker::C"* %c to i8* -// WIN32-LIFETIME: call void @llvm.lifetime.start(i64 1, i8* %[[bc0]]) +// WIN32-LIFETIME: call void @llvm.lifetime.start.p0i8(i64 1, i8* %[[bc0]]) // WIN32-LIFETIME: invoke void @"\01?g@lifetime_marker@@YAXXZ"() // WIN32-LIFETIME-NEXT: to label %[[cont:[^ ]*]] unwind label %[[lpad0:[^ ]*]] // // WIN32-LIFETIME: [[cont]] // WIN32-LIFETIME: call x86_thiscallcc void @"\01??1C@lifetime_marker@@QAE@XZ"({{.*}}) // WIN32-LIFETIME: %[[bc1:.*]] = bitcast %"struct.lifetime_marker::C"* %[[c]] to i8* -// WIN32-LIFETIME: call void @llvm.lifetime.end(i64 1, i8* %[[bc1]]) +// WIN32-LIFETIME: call void @llvm.lifetime.end.p0i8(i64 1, i8* %[[bc1]]) // // WIN32-LIFETIME: [[lpad0]] // WIN32-LIFETIME-NEXT: cleanuppad @@ -276,7 +276,7 @@ void f() { // WIN32-LIFETIME: [[lpad1]] // WIN32-LIFETIME-NEXT: cleanuppad // WIN32-LIFETIME: %[[bc2:.*]] = bitcast %"struct.lifetime_marker::C"* %[[c]] to i8* -// WIN32-LIFETIME: call void @llvm.lifetime.end(i64 1, i8* %[[bc2]]) +// WIN32-LIFETIME: call void @llvm.lifetime.end.p0i8(i64 1, i8* %[[bc2]]) } struct class_2 { diff --git a/test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp b/test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp index 7eea41c8712e..eaae3493ccdc 100644 --- a/test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp +++ b/test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp @@ -64,6 +64,10 @@ struct BigWithDtor { int a, b, c, d, e, f; }; +struct BaseNoByval : Small { + int bb; +}; + // WIN32: declare void @"{{.*take_bools_and_chars.*}}" // WIN32: (<{ i8, [3 x i8], i8, [3 x i8], %struct.SmallWithDtor, // WIN32: i8, [3 x i8], i8, [3 x i8], i32, i8, [3 x i8] }>* inalloca) @@ -127,6 +131,12 @@ void medium_arg(Medium s) {} // WIN64: define void @"\01?medium_arg@@YAXUMedium@@@Z"(i64 %s.coerce) // WOA: define arm_aapcs_vfpcc void @"\01?medium_arg@@YAXUMedium@@@Z"([2 x i32] %s.coerce) +void base_no_byval_arg(BaseNoByval s) {} +// LINUX-LABEL: define void @_Z17base_no_byval_arg11BaseNoByval(%struct.BaseNoByval* byval align 4 %s) +// WIN32: define void @"\01?base_no_byval_arg@@YAXUBaseNoByval@@@Z"(i32 %s.0, i32 %s.1) +// WIN64: define void @"\01?base_no_byval_arg@@YAXUBaseNoByval@@@Z"(i64 %s.coerce) +// WOA: define arm_aapcs_vfpcc void @"\01?base_no_byval_arg@@YAXUBaseNoByval@@@Z"([2 x i32] %s.coerce) + void small_arg_with_ctor(SmallWithCtor s) {} // LINUX-LABEL: define void @_Z19small_arg_with_ctor13SmallWithCtor(%struct.SmallWithCtor* byval align 4 %s) // WIN32: define void @"\01?small_arg_with_ctor@@YAXUSmallWithCtor@@@Z"(i32 %s.0) diff --git a/test/CodeGenCXX/microsoft-abi-structors.cpp b/test/CodeGenCXX/microsoft-abi-structors.cpp index 6397eeb7313f..4de6c3346611 100644 --- a/test/CodeGenCXX/microsoft-abi-structors.cpp +++ b/test/CodeGenCXX/microsoft-abi-structors.cpp @@ -207,7 +207,7 @@ F::~F() { void foo() { F f; } -// DTORS3-LABEL: define linkonce_odr x86_thiscallcc void @"\01??_DF@test2@@UAE@XZ"({{.*}} {{.*}} comdat +// DTORS3-LABEL: define linkonce_odr x86_thiscallcc void @"\01??_DF@test2@@QAEXXZ"({{.*}} {{.*}} comdat // Do an adjustment from C* to F*. // DTORS3: getelementptr i8, i8* %{{.*}}, i32 20 // DTORS3: bitcast i8* %{{.*}} to %"struct.test2::F"* @@ -361,12 +361,12 @@ struct D : B, C { ~D(); }; void call_vbase_complete(D *d) { d->~D(); // CHECK: define void @"\01?call_vbase_complete@dtors@@YAXPAUD@1@@Z" -// CHECK: call x86_thiscallcc void @"\01??_DD@dtors@@QAE@XZ"(%"struct.dtors::D"* %{{[^,]+}}) +// CHECK: call x86_thiscallcc void @"\01??_DD@dtors@@QAEXXZ"(%"struct.dtors::D"* %{{[^,]+}}) // CHECK: ret } // The complete dtor should call the base dtors for D and the vbase A (once). -// CHECK: define linkonce_odr x86_thiscallcc void @"\01??_DD@dtors@@QAE@XZ"({{.*}}) {{.*}} comdat +// CHECK: define linkonce_odr x86_thiscallcc void @"\01??_DD@dtors@@QAEXXZ"({{.*}}) {{.*}} comdat // CHECK-NOT: call // CHECK: call x86_thiscallcc void @"\01??1D@dtors@@QAE@XZ" // CHECK-NOT: call @@ -377,7 +377,7 @@ void call_vbase_complete(D *d) { void destroy_d_complete() { D d; // CHECK: define void @"\01?destroy_d_complete@dtors@@YAXXZ" -// CHECK: call x86_thiscallcc void @"\01??_DD@dtors@@QAE@XZ"(%"struct.dtors::D"* %{{[^,]+}}) +// CHECK: call x86_thiscallcc void @"\01??_DD@dtors@@QAEXXZ"(%"struct.dtors::D"* %{{[^,]+}}) // CHECK: ret } @@ -387,7 +387,7 @@ void destroy_d_complete() { void call_nv_deleting_dtor(D *d) { delete d; // CHECK: define void @"\01?call_nv_deleting_dtor@dtors@@YAXPAUD@1@@Z" -// CHECK: call x86_thiscallcc void @"\01??_DD@dtors@@QAE@XZ"(%"struct.dtors::D"* %{{[^,]+}}) +// CHECK: call x86_thiscallcc void @"\01??_DD@dtors@@QAEXXZ"(%"struct.dtors::D"* %{{[^,]+}}) // CHECK: call void @"\01??3@YAXPAX@Z" // CHECK: ret } diff --git a/test/CodeGenCXX/microsoft-abi-throw.cpp b/test/CodeGenCXX/microsoft-abi-throw.cpp index 7c2e2a8f901e..51076f841611 100644 --- a/test/CodeGenCXX/microsoft-abi-throw.cpp +++ b/test/CodeGenCXX/microsoft-abi-throw.cpp @@ -12,7 +12,7 @@ // CHECK-DAG: @"\01??_R0?AUV@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"\01??_7type_info@@6B@", i8* null, [8 x i8] c".?AUV@@\00" }, comdat // CHECK-DAG: @"_CT??_R0?AUV@@@81044" = linkonce_odr unnamed_addr constant %eh.CatchableType { i32 0, i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUV@@@8" to i8*), i32 0, i32 4, i32 4, i32 1, i8* null }, section ".xdata", comdat // CHECK-DAG: @"_CTA5?AUY@@" = linkonce_odr unnamed_addr constant %eh.CatchableTypeArray.5 { i32 5, [5 x %eh.CatchableType*] [%eh.CatchableType* @"_CT??_R0?AUY@@@8??0Y@@QAE@ABU0@@Z8", %eh.CatchableType* @"_CT??_R0?AUZ@@@81", %eh.CatchableType* @"_CT??_R0?AUW@@@8??0W@@QAE@ABU0@@Z44", %eh.CatchableType* @"_CT??_R0?AUM@@@818", %eh.CatchableType* @"_CT??_R0?AUV@@@81044"] }, section ".xdata", comdat -// CHECK-DAG: @"_TI5?AUY@@" = linkonce_odr unnamed_addr constant %eh.ThrowInfo { i32 0, i8* bitcast (void (%struct.Y*)* @"\01??_DY@@QAE@XZ" to i8*), i8* null, i8* bitcast (%eh.CatchableTypeArray.5* @"_CTA5?AUY@@" to i8*) }, section ".xdata", comdat +// CHECK-DAG: @"_TI5?AUY@@" = linkonce_odr unnamed_addr constant %eh.ThrowInfo { i32 0, i8* bitcast (void (%struct.Y*)* @"\01??_DY@@QAEXXZ" to i8*), i8* null, i8* bitcast (%eh.CatchableTypeArray.5* @"_CTA5?AUY@@" to i8*) }, section ".xdata", comdat // CHECK-DAG: @"_CT??_R0?AUDefault@@@8??_ODefault@@QAEXAAU0@@Z1" = linkonce_odr unnamed_addr constant %eh.CatchableType { i32 0, i8* bitcast (%rtti.TypeDescriptor13* @"\01??_R0?AUDefault@@@8" to i8*), i32 0, i32 -1, i32 0, i32 1, i8* bitcast (void (%struct.Default*, %struct.Default*)* @"\01??_ODefault@@QAEXAAU0@@Z" to i8*) }, section ".xdata", comdat // CHECK-DAG: @"_CT??_R0?AUVariadic@@@8??_OVariadic@@QAEXAAU0@@Z1" = linkonce_odr unnamed_addr constant %eh.CatchableType { i32 0, i8* bitcast (%rtti.TypeDescriptor14* @"\01??_R0?AUVariadic@@@8" to i8*), i32 0, i32 -1, i32 0, i32 1, i8* bitcast (void (%struct.Variadic*, %struct.Variadic*)* @"\01??_OVariadic@@QAEXAAU0@@Z" to i8*) }, section ".xdata", comdat // CHECK-DAG: @"_CT??_R0?AUTemplateWithDefault@@@8??$?_OH@TemplateWithDefault@@QAEXAAU0@@Z1" = linkonce_odr unnamed_addr constant %eh.CatchableType { i32 0, i8* bitcast (%rtti.TypeDescriptor25* @"\01??_R0?AUTemplateWithDefault@@@8" to i8*), i32 0, i32 -1, i32 0, i32 1, i8* bitcast (void (%struct.TemplateWithDefault*, %struct.TemplateWithDefault*)* @"\01??$?_OH@TemplateWithDefault@@QAEXAAU0@@Z" to i8*) }, section ".xdata", comdat diff --git a/test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp b/test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp index 416aefa6b715..20ecaf431650 100644 --- a/test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp +++ b/test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp @@ -84,7 +84,7 @@ B::~B() { // CHECK: ret - // CHECK2-LABEL: define linkonce_odr x86_thiscallcc void @"\01??_DB@@UAE@XZ"(%struct.B* + // CHECK2-LABEL: define linkonce_odr x86_thiscallcc void @"\01??_DB@@QAEXXZ"(%struct.B* // CHECK2: %[[THIS:.*]] = load %struct.B*, %struct.B** {{.*}} // CHECK2: %[[THIS_i8:.*]] = bitcast %struct.B* %[[THIS]] to i8* // CHECK2: %[[B_i8:.*]] = getelementptr i8, i8* %[[THIS_i8]], i32 8 @@ -102,7 +102,7 @@ B::~B() { // CHECK2: %[[THIS:.*]] = bitcast i8* %[[THIS_i8]] to %struct.B* // CHECK2: store %struct.B* %[[THIS]], %struct.B** %[[THIS_ADDR:.*]], align 4 // CHECK2: %[[THIS:.*]] = load %struct.B*, %struct.B** %[[THIS_ADDR]] - // CHECK2: call x86_thiscallcc void @"\01??_DB@@UAE@XZ"(%struct.B* %[[THIS]]) + // CHECK2: call x86_thiscallcc void @"\01??_DB@@QAEXXZ"(%struct.B* %[[THIS]]) // ... // CHECK2: ret } @@ -208,7 +208,7 @@ void call_complete_dtor() { B b; // CHECK: call x86_thiscallcc %struct.B* @"\01??0B@@QAE@XZ"(%struct.B* %[[B:.*]], i32 1) // CHECK-NOT: getelementptr - // CHECK: call x86_thiscallcc void @"\01??_DB@@UAE@XZ"(%struct.B* %[[B]]) + // CHECK: call x86_thiscallcc void @"\01??_DB@@QAEXXZ"(%struct.B* %[[B]]) // CHECK: ret } diff --git a/test/CodeGenCXX/modules-ts.cppm b/test/CodeGenCXX/modules-ts.cppm index da3bcb2174a7..90f6b5319eb6 100644 --- a/test/CodeGenCXX/modules-ts.cppm +++ b/test/CodeGenCXX/modules-ts.cppm @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fmodules-ts -std=c++1z -triple=x86_64-linux-gnu -emit-module-interface %s -o %t.pcm +// RUN: %clang_cc1 -fmodules-ts -std=c++1z -triple=x86_64-linux-gnu -fmodules-codegen -emit-module-interface %s -o %t.pcm // RUN: %clang_cc1 -fmodules-ts -std=c++1z -triple=x86_64-linux-gnu %t.pcm -emit-llvm -o - | FileCheck %s module FooBar; @@ -8,6 +8,9 @@ export { int f() { return 0; } } +// CHECK-LABEL: define weak_odr void @_Z2f2v( +inline void f2() { } + // FIXME: Emit global variables and their initializers with this TU. // Emit an initialization function that other TUs can call, with guard variable. diff --git a/test/CodeGenCXX/new-array-init.cpp b/test/CodeGenCXX/new-array-init.cpp index 0429ae770bc8..ccc218e2b2dc 100644 --- a/test/CodeGenCXX/new-array-init.cpp +++ b/test/CodeGenCXX/new-array-init.cpp @@ -1,4 +1,5 @@ // RUN: %clang_cc1 -std=c++11 -triple i386-unknown-unknown %s -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 -std=c++11 -triple i386-unknown-unknown %s -emit-llvm -fsanitize=signed-integer-overflow -o - | FileCheck --check-prefix=SIO %s // CHECK: @[[ABC4:.*]] = {{.*}} constant [4 x i8] c"abc\00" // CHECK: @[[ABC15:.*]] = {{.*}} constant [15 x i8] c"abc\00\00\00\00 @@ -116,3 +117,9 @@ void aggr_sufficient(int n) { struct Aggr { int a, b; }; new Aggr[n] { 1, 2, 3 }; } + +// SIO-LABEL: define void @_Z14constexpr_testv +void constexpr_test() { + // SIO: call i8* @_Zna{{.}}(i32 4) + new int[0+1]{0}; +} diff --git a/test/CodeGenCXX/no-lto-unit.cpp b/test/CodeGenCXX/no-lto-unit.cpp new file mode 100644 index 000000000000..24b8fd01546a --- /dev/null +++ b/test/CodeGenCXX/no-lto-unit.cpp @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -flto=thin -triple x86_64-unknown-linux -fvisibility hidden -emit-llvm-bc -o %t %s +// RUN: llvm-dis -o - %t | FileCheck %s +// RUN: %clang_cc1 -flto=thin -flto-unit -fno-lto-unit -triple x86_64-unknown-linux -fvisibility hidden -emit-llvm-bc -o %t %s +// RUN: llvm-dis -o - %t | FileCheck %s + +// CHECK-NOT: !type +class A { + virtual void f() {} +}; + +A *f() { + return new A; +} diff --git a/test/CodeGenCXX/nrvo.cpp b/test/CodeGenCXX/nrvo.cpp index d02206abae50..0f359b9c9000 100644 --- a/test/CodeGenCXX/nrvo.cpp +++ b/test/CodeGenCXX/nrvo.cpp @@ -182,11 +182,11 @@ X test6() { return a; // CHECK: [[A:%.*]] = alloca [[X:%.*]], align 8 // CHECK-NEXT: [[PTR:%.*]] = getelementptr inbounds %class.X, %class.X* [[A]], i32 0, i32 0 - // CHECK-NEXT: call void @llvm.lifetime.start(i64 1, i8* nonnull [[PTR]]) + // CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 1, i8* nonnull [[PTR]]) // CHECK-NEXT: call {{.*}} @_ZN1XC1Ev([[X]]* nonnull [[A]]) // CHECK-NEXT: call {{.*}} @_ZN1XC1ERKS_([[X]]* {{%.*}}, [[X]]* nonnull dereferenceable({{[0-9]+}}) [[A]]) // CHECK-NEXT: call {{.*}} @_ZN1XD1Ev([[X]]* nonnull [[A]]) - // CHECK-NEXT: call void @llvm.lifetime.end(i64 1, i8* nonnull [[PTR]]) + // CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull [[PTR]]) // CHECK-NEXT: ret void } diff --git a/test/CodeGenCXX/optnone-class-members.cpp b/test/CodeGenCXX/optnone-class-members.cpp index 70e3ee76e60a..b1d2f7b559d9 100644 --- a/test/CodeGenCXX/optnone-class-members.cpp +++ b/test/CodeGenCXX/optnone-class-members.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 < %s -triple %itanium_abi_triple -fms-extensions -O2 -disable-llvm-optzns -emit-llvm -x c++ | FileCheck %s +// RUN: %clang_cc1 < %s -triple %itanium_abi_triple -fms-extensions -O2 -disable-llvm-passes -emit-llvm -x c++ | FileCheck %s // Test attribute 'optnone' on methods: // -- member functions; diff --git a/test/CodeGenCXX/optnone-def-decl.cpp b/test/CodeGenCXX/optnone-def-decl.cpp index 4008bbe685f3..6e4e510b9bf6 100644 --- a/test/CodeGenCXX/optnone-def-decl.cpp +++ b/test/CodeGenCXX/optnone-def-decl.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 %s -triple %itanium_abi_triple -fms-extensions -O2 -disable-llvm-optzns -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 %s -triple %itanium_abi_triple -fms-extensions -O2 -disable-llvm-passes -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 diff --git a/test/CodeGenCXX/reference-init.cpp b/test/CodeGenCXX/reference-init.cpp index 3a3eaeee78f6..ba7b282028cf 100644 --- a/test/CodeGenCXX/reference-init.cpp +++ b/test/CodeGenCXX/reference-init.cpp @@ -1,4 +1,6 @@ -// RUN: %clang_cc1 -emit-llvm-only -triple %itanium_abi_triple -verify %s +// RUN: %clang_cc1 -triple %itanium_abi_triple -verify %s +// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm %s -o - -std=c++98 | FileCheck %s --check-prefix=CHECK-CXX98 +// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm %s -o - -std=c++11 | FileCheck %s --check-prefix=CHECK-CXX11 // expected-no-diagnostics struct XPTParamDescriptor {}; @@ -23,3 +25,12 @@ Foo& ignoreSetMutex = *(new Foo); // Binding to a bit-field that requires a temporary. struct { int bitfield : 3; } s = { 3 }; const int &s2 = s.bitfield; + +// In C++98, this forms a reference to itself. In C++11 onwards, this performs +// copy-construction. +struct SelfReference { SelfReference &r; }; +extern SelfReference self_reference_1; +SelfReference self_reference_2 = {self_reference_1}; +// CHECK-CXX98: @self_reference_2 = global %[[SELF_REF:.*]] { %[[SELF_REF]]* @self_reference_1 } +// CHECK-CXX11: @self_reference_2 = global %[[SELF_REF:.*]] zeroinitializer +// CHECK-CXX11: call {{.*}}memcpy{{.*}} @self_reference_2 {{.*}} @self_reference_1 diff --git a/test/CodeGenCXX/regcall.cpp b/test/CodeGenCXX/regcall.cpp index 0cc6ad009324..0ff6fdf12a58 100644 --- a/test/CodeGenCXX/regcall.cpp +++ b/test/CodeGenCXX/regcall.cpp @@ -47,8 +47,8 @@ public: // CHECK-LIN-DAG: define linkonce_odr x86_regcallcc void @_ZN10test_classD2Ev // CHECK-LIN-DAG: define linkonce_odr x86_regcallcc void @_ZN10test_classD1Ev // Windows ignores calling convention on constructor/destructors. - // CHECK-WIN64-DAG: define linkonce_odr void @"\01??_Dtest_class@@QEAA@XZ" - // CHECK-WIN32-DAG: define linkonce_odr x86_thiscallcc void @"\01??_Dtest_class@@QAE@XZ" + // CHECK-WIN64-DAG: define linkonce_odr void @"\01??_Dtest_class@@QEAAXXZ" + // CHECK-WIN32-DAG: define linkonce_odr x86_thiscallcc void @"\01??_Dtest_class@@QAEXXZ" test_class& __regcall operator+=(const test_class&){ return *this; diff --git a/test/CodeGenCXX/static-init.cpp b/test/CodeGenCXX/static-init.cpp index bb974948a059..925ddec1ad06 100644 --- a/test/CodeGenCXX/static-init.cpp +++ b/test/CodeGenCXX/static-init.cpp @@ -1,4 +1,5 @@ -// RUN: %clang_cc1 %s -triple=x86_64-pc-linuxs -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 %s -triple=x86_64-pc-linuxs -emit-llvm -std=c++98 -o - | FileCheck -check-prefix=CHECK -check-prefix=CHECK98 %s +// RUN: %clang_cc1 %s -triple=x86_64-pc-linuxs -emit-llvm -std=c++11 -o - | FileCheck -check-prefix=CHECK -check-prefix=CHECK11 %s // CHECK: @_ZZ1hvE1i = internal global i32 0, align 4 // CHECK: @base_req = global [4 x i8] c"foo\00", align 1 @@ -9,7 +10,8 @@ // CHECK: @_ZZ2h2vE1i = linkonce_odr global i32 0, comdat, align 4 // CHECK: @_ZGVZ2h2vE1i = linkonce_odr global i64 0, comdat, align 8{{$}} // CHECK: @_ZZN5test1L6getvarEiE3var = internal constant [4 x i32] [i32 1, i32 0, i32 2, i32 4], align 16 -// CHECK: @_ZZN5test414useStaticLocalEvE3obj = linkonce_odr global %"struct.test4::HasVTable" zeroinitializer, comdat, align 8 +// CHECK98: @_ZZN5test414useStaticLocalEvE3obj = linkonce_odr global %"struct.test4::HasVTable" zeroinitializer, comdat, align 8 +// CHECK11: @_ZZN5test414useStaticLocalEvE3obj = linkonce_odr global { i8** } { i8** getelementptr inbounds ({ [3 x i8*] }, { [3 x i8*] }* @_ZTVN5test49HasVTableE, i32 0, inrange i32 0, i32 2) }, comdat, align 8 struct A { A(); @@ -169,5 +171,5 @@ void useit() { useStaticLocal(); } // CHECK: define linkonce_odr dereferenceable(8) %"struct.test4::HasVTable"* @_ZN5test414useStaticLocalEv() -// CHECK: ret %"struct.test4::HasVTable"* @_ZZN5test414useStaticLocalEvE3obj +// CHECK: ret %"struct.test4::HasVTable"*{{.*}} @_ZZN5test414useStaticLocalEvE3obj } diff --git a/test/CodeGenCXX/stmtexpr.cpp b/test/CodeGenCXX/stmtexpr.cpp index 7bf19bbfb46d..5885a1663e63 100644 --- a/test/CodeGenCXX/stmtexpr.cpp +++ b/test/CodeGenCXX/stmtexpr.cpp @@ -80,3 +80,85 @@ int foo5(bool b) { y = ({ A a(1); if (b) goto G; a.i; }); G: return y; } + +// When we emit a full expression with cleanups that contains branches out of +// the full expression, the result of the inner expression (the call to +// call_with_cleanups in this case) may not dominate the fallthrough destination +// of the shared cleanup block. +// +// In this case the CFG will be a sequence of two diamonds, but the only +// dynamically possible execution paths are both left hand branches and both +// right hand branches. The first diamond LHS will call bar, and the second +// diamond LHS will assign the result to v, but the call to bar does not +// dominate the assignment. +int bar(A, int); +extern "C" int cleanup_exit_scalar(bool b) { + int v = bar(A(1), ({ if (b) return 42; 13; })); + return v; +} + +// CHECK-LABEL: define{{.*}} i32 @cleanup_exit_scalar({{.*}}) +// CHECK: call {{.*}} @_ZN1AC1Ei +// Spill after bar. +// CHECK: %[[v:[^ ]*]] = call{{.*}} i32 @_Z3bar1Ai({{.*}}) +// CHECK-NEXT: store i32 %[[v]], i32* %[[tmp:[^, ]*]] +// Do cleanup. +// CHECK: call {{.*}} @_ZN1AD1Ev +// CHECK: switch +// Reload before v assignment. +// CHECK: %[[v:[^ ]*]] = load i32, i32* %[[tmp]] +// CHECK-NEXT: store i32 %[[v]], i32* %v + +// No need to spill when the expression result is a constant, constants don't +// have dominance problems. +extern "C" int cleanup_exit_scalar_constant(bool b) { + int v = (A(1), (void)({ if (b) return 42; 0; }), 13); + return v; +} + +// CHECK-LABEL: define{{.*}} i32 @cleanup_exit_scalar_constant({{.*}}) +// CHECK: store i32 13, i32* %v + +// Check for the same bug for lvalue expression evaluation kind. +// FIXME: What about non-reference lvalues, like bitfield lvalues and vector +// lvalues? +int &getref(); +extern "C" int cleanup_exit_lvalue(bool cond) { + int &r = (A(1), ({ if (cond) return 0; (void)0; }), getref()); + return r; +} +// CHECK-LABEL: define{{.*}} i32 @cleanup_exit_lvalue({{.*}}) +// CHECK: call {{.*}} @_ZN1AC1Ei +// Spill after bar. +// CHECK: %[[v:[^ ]*]] = call dereferenceable(4) i32* @_Z6getrefv({{.*}}) +// CHECK-NEXT: store i32* %[[v]], i32** %[[tmp:[^, ]*]] +// Do cleanup. +// CHECK: call {{.*}} @_ZN1AD1Ev +// CHECK: switch +// Reload before v assignment. +// CHECK: %[[v:[^ ]*]] = load i32*, i32** %[[tmp]] +// CHECK-NEXT: store i32* %[[v]], i32** %r + + +// We handle ExprWithCleanups for complex evaluation type separately, and it had +// the same bug. +_Complex float bar_complex(A, int); +extern "C" int cleanup_exit_complex(bool b) { + _Complex float v = bar_complex(A(1), ({ if (b) return 42; 13; })); + return v; +} + +// CHECK-LABEL: define{{.*}} i32 @cleanup_exit_complex({{.*}}) +// CHECK: call {{.*}} @_ZN1AC1Ei +// Spill after bar. +// CHECK: call {{.*}} @_Z11bar_complex1Ai({{.*}}) +// CHECK: store float %{{.*}}, float* %[[tmp1:[^, ]*]] +// CHECK: store float %{{.*}}, float* %[[tmp2:[^, ]*]] +// Do cleanup. +// CHECK: call {{.*}} @_ZN1AD1Ev +// CHECK: switch +// Reload before v assignment. +// CHECK: %[[v1:[^ ]*]] = load float, float* %[[tmp1]] +// CHECK: %[[v2:[^ ]*]] = load float, float* %[[tmp2]] +// CHECK: store float %[[v1]], float* %v.realp +// CHECK: store float %[[v2]], float* %v.imagp diff --git a/test/CodeGenCXX/template-instantiation.cpp b/test/CodeGenCXX/template-instantiation.cpp index 3d0ce234371f..098f18dc479f 100644 --- a/test/CodeGenCXX/template-instantiation.cpp +++ b/test/CodeGenCXX/template-instantiation.cpp @@ -1,21 +1,22 @@ -// RUN: %clang_cc1 %s -O1 -disable-llvm-passes -triple=x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s - -// CHECK: @_ZN7PR100011xE = global -// CHECK-NOT: @_ZN7PR100014kBarE = external global i32 -// -// CHECK-NOT: @_ZTVN5test118stdio_sync_filebufIwEE = constant -// CHECK-NOT: _ZTVN5test315basic_fstreamXXIcEE -// CHECK-NOT: @_ZTVN5test018stdio_sync_filebufIA1_iEE -// CHECK-NOT: @_ZTVN5test018stdio_sync_filebufIA2_iEE -// CHECK: @_ZTVN5test018stdio_sync_filebufIA3_iEE = weak_odr unnamed_addr constant - -// CHECK: @_ZN7PR100011SIiE3arrE = linkonce_odr global [3 x i32] -// CHECK-NOT: @_ZN7PR100011SIiE3arr2E = linkonce_odr global [3 x i32]A - -// CHECK: @_ZTVN5test018stdio_sync_filebufIA4_iEE = linkonce_odr unnamed_addr constant - -// CHECK-NOT: _ZTVN5test31SIiEE -// CHECK-NOT: _ZTSN5test31SIiEE +// RUN: %clang_cc1 %s -O1 -disable-llvm-passes -triple=x86_64-apple-darwin10 -std=c++11 -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 %s -O1 -disable-llvm-passes -triple=x86_64-apple-darwin10 -std=c++11 -emit-llvm -o - | FileCheck %s --check-prefix=CHECK2 + +// Instantiation order varies on different C++ dialects (IE, between C++98 and C++11). +// CHECK-DAG: @_ZN7PR100011xE = global +// CHECK-DAG: @_ZTVN5test018stdio_sync_filebufIA3_iEE = weak_odr unnamed_addr constant +// CHECK-DAG: @_ZN7PR100011SIiE3arrE = linkonce_odr global [3 x i32] +// CHECK-DAG: @_ZTVN5test018stdio_sync_filebufIA4_iEE = linkonce_odr unnamed_addr constant + +// Negative checks go under prefix "CHECK2" to avoid interference with CHECK and CHECK-DAG. +// CHECK2-NOT: @_ZN7PR100014kBarE = external global i32 +// CHECK2-NOT: @_ZTVN5test118stdio_sync_filebufIwEE = constant +// CHECK2-NOT: _ZTVN5test315basic_fstreamXXIcEE +// CHECK2-NOT: @_ZTVN5test018stdio_sync_filebufIA1_iEE +// CHECK2-NOT: @_ZTVN5test018stdio_sync_filebufIA2_iEE +// CHECK2-NOT: @_ZN7PR100011SIiE3arr2E = linkonce_odr global [3 x i32]A + +// CHECK2-NOT: _ZTVN5test31SIiEE +// CHECK2-NOT: _ZTSN5test31SIiEE // CHECK-LABEL: define linkonce_odr void @_ZN5test21CIiEC1Ev(%"class.test2::C"* %this) unnamed_addr // CHECK-LABEL: define linkonce_odr void @_ZN5test21CIiE6foobarIdEEvT_( @@ -152,7 +153,7 @@ class B { void f () {} }; // Should not instantiate class B since it is introduced in namespace scope. -// CHECK-NOT: _ZN6PR85051AILi0EE1B1fEv +// CHECK2-NOT: _ZN6PR85051AILi0EE1B1fEv template class A<0>; } diff --git a/test/CodeGenCXX/type-metadata-thinlto.cpp b/test/CodeGenCXX/type-metadata-thinlto.cpp new file mode 100644 index 000000000000..2a586fc4c37c --- /dev/null +++ b/test/CodeGenCXX/type-metadata-thinlto.cpp @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 -flto=thin -flto-unit -triple x86_64-unknown-linux -fvisibility hidden -emit-llvm-bc -o %t %s +// RUN: llvm-modextract -o - -n 1 %t | llvm-dis | FileCheck %s + +// CHECK: @_ZTV1A = linkonce_odr +class A { + virtual void f() {} +}; + +A *f() { + return new A; +} diff --git a/test/CodeGenCXX/type-metadata.cpp b/test/CodeGenCXX/type-metadata.cpp index 076b1fdf1808..6821e3624093 100644 --- a/test/CodeGenCXX/type-metadata.cpp +++ b/test/CodeGenCXX/type-metadata.cpp @@ -1,16 +1,16 @@ // Tests for the cfi-vcall feature: -// RUN: %clang_cc1 -flto -triple x86_64-unknown-linux -fvisibility hidden -fsanitize=cfi-vcall -fsanitize-trap=cfi-vcall -emit-llvm -o - %s | FileCheck --check-prefix=CFI --check-prefix=CFI-NVT --check-prefix=ITANIUM --check-prefix=TT-ITANIUM --check-prefix=NDIAG %s -// RUN: %clang_cc1 -flto -triple x86_64-unknown-linux -fvisibility hidden -fsanitize=cfi-vcall -emit-llvm -o - %s | FileCheck --check-prefix=CFI --check-prefix=CFI-NVT --check-prefix=ITANIUM --check-prefix=TT-ITANIUM --check-prefix=ITANIUM-DIAG --check-prefix=DIAG --check-prefix=DIAG-ABORT %s -// RUN: %clang_cc1 -flto -triple x86_64-unknown-linux -fvisibility hidden -fsanitize=cfi-vcall -fsanitize-recover=cfi-vcall -emit-llvm -o - %s | FileCheck --check-prefix=CFI --check-prefix=CFI-NVT --check-prefix=ITANIUM --check-prefix=TT-ITANIUM --check-prefix=ITANIUM-DIAG --check-prefix=DIAG --check-prefix=DIAG-RECOVER %s -// RUN: %clang_cc1 -flto -triple x86_64-pc-windows-msvc -fsanitize=cfi-vcall -fsanitize-trap=cfi-vcall -emit-llvm -o - %s | FileCheck --check-prefix=CFI --check-prefix=CFI-NVT --check-prefix=MS --check-prefix=TT-MS --check-prefix=NDIAG %s +// RUN: %clang_cc1 -flto -flto-unit -triple x86_64-unknown-linux -fvisibility hidden -fsanitize=cfi-vcall -fsanitize-trap=cfi-vcall -emit-llvm -o - %s | FileCheck --check-prefix=CFI --check-prefix=CFI-NVT --check-prefix=ITANIUM --check-prefix=TT-ITANIUM --check-prefix=NDIAG %s +// RUN: %clang_cc1 -flto -flto-unit -triple x86_64-unknown-linux -fvisibility hidden -fsanitize=cfi-vcall -emit-llvm -o - %s | FileCheck --check-prefix=CFI --check-prefix=CFI-NVT --check-prefix=ITANIUM --check-prefix=TT-ITANIUM --check-prefix=ITANIUM-DIAG --check-prefix=DIAG --check-prefix=DIAG-ABORT %s +// RUN: %clang_cc1 -flto -flto-unit -triple x86_64-unknown-linux -fvisibility hidden -fsanitize=cfi-vcall -fsanitize-recover=cfi-vcall -emit-llvm -o - %s | FileCheck --check-prefix=CFI --check-prefix=CFI-NVT --check-prefix=ITANIUM --check-prefix=TT-ITANIUM --check-prefix=ITANIUM-DIAG --check-prefix=DIAG --check-prefix=DIAG-RECOVER %s +// RUN: %clang_cc1 -flto -flto-unit -triple x86_64-pc-windows-msvc -fsanitize=cfi-vcall -fsanitize-trap=cfi-vcall -emit-llvm -o - %s | FileCheck --check-prefix=CFI --check-prefix=CFI-NVT --check-prefix=MS --check-prefix=TT-MS --check-prefix=NDIAG %s // Tests for the whole-program-vtables feature: -// RUN: %clang_cc1 -flto -triple x86_64-unknown-linux -fvisibility hidden -fwhole-program-vtables -emit-llvm -o - %s | FileCheck --check-prefix=VTABLE-OPT --check-prefix=ITANIUM --check-prefix=TT-ITANIUM %s -// RUN: %clang_cc1 -flto -triple x86_64-pc-windows-msvc -fwhole-program-vtables -emit-llvm -o - %s | FileCheck --check-prefix=VTABLE-OPT --check-prefix=MS --check-prefix=TT-MS %s +// RUN: %clang_cc1 -flto -flto-unit -triple x86_64-unknown-linux -fvisibility hidden -fwhole-program-vtables -emit-llvm -o - %s | FileCheck --check-prefix=VTABLE-OPT --check-prefix=ITANIUM --check-prefix=TT-ITANIUM %s +// RUN: %clang_cc1 -flto -flto-unit -triple x86_64-pc-windows-msvc -fwhole-program-vtables -emit-llvm -o - %s | FileCheck --check-prefix=VTABLE-OPT --check-prefix=MS --check-prefix=TT-MS %s // Tests for cfi + whole-program-vtables: -// RUN: %clang_cc1 -flto -triple x86_64-unknown-linux -fvisibility hidden -fsanitize=cfi-vcall -fsanitize-trap=cfi-vcall -fwhole-program-vtables -emit-llvm -o - %s | FileCheck --check-prefix=CFI --check-prefix=CFI-VT --check-prefix=ITANIUM --check-prefix=TC-ITANIUM %s -// RUN: %clang_cc1 -flto -triple x86_64-pc-windows-msvc -fsanitize=cfi-vcall -fsanitize-trap=cfi-vcall -fwhole-program-vtables -emit-llvm -o - %s | FileCheck --check-prefix=CFI --check-prefix=CFI-VT --check-prefix=MS --check-prefix=TC-MS %s +// RUN: %clang_cc1 -flto -flto-unit -triple x86_64-unknown-linux -fvisibility hidden -fsanitize=cfi-vcall -fsanitize-trap=cfi-vcall -fwhole-program-vtables -emit-llvm -o - %s | FileCheck --check-prefix=CFI --check-prefix=CFI-VT --check-prefix=ITANIUM --check-prefix=TC-ITANIUM %s +// RUN: %clang_cc1 -flto -flto-unit -triple x86_64-pc-windows-msvc -fsanitize=cfi-vcall -fsanitize-trap=cfi-vcall -fwhole-program-vtables -emit-llvm -o - %s | FileCheck --check-prefix=CFI --check-prefix=CFI-VT --check-prefix=MS --check-prefix=TC-MS %s // ITANIUM: @_ZTV1A = {{[^!]*}}, !type [[A16:![0-9]+]] // ITANIUM-DIAG-SAME: !type [[ALL16:![0-9]+]] diff --git a/test/CodeGenCXX/ubsan-bitfields.cpp b/test/CodeGenCXX/ubsan-bitfields.cpp new file mode 100644 index 000000000000..5595db013db0 --- /dev/null +++ b/test/CodeGenCXX/ubsan-bitfields.cpp @@ -0,0 +1,34 @@ +// RUN: %clang_cc1 -std=c++11 -triple x86_64-apple-darwin10 -emit-llvm -o - %s -fsanitize=bool,enum | FileCheck %s + +enum E { + a = 1, + b = 2, + c = 3 +}; + +struct S { + E e1 : 10; +}; + +// CHECK-LABEL: define i32 @_Z4loadP1S +E load(S *s) { + // CHECK: [[LOAD:%.*]] = load i16, i16* {{.*}} + // CHECK: [[CLEAR:%.*]] = and i16 [[LOAD]], 1023 + // CHECK: [[CAST:%.*]] = zext i16 [[CLEAR]] to i32 + // CHECK: icmp ule i32 [[CAST]], 3, !nosanitize + // CHECK: call void @__ubsan_handle_load_invalid_value + return s->e1; +} + +struct Bool { + bool b1 : 1; + bool b2 : 7; + bool b3 : 16; +}; + +// CHECK-LABEL: define zeroext i1 @_Z13load_cpp_boolP4Bool +bool load_cpp_bool(Bool *b) { + // CHECK-NOT: call void @__ubsan_handle_load_invalid_value + // CHECK-NOT: !nosanitize + return b->b1 || b->b2 || b->b3; +} diff --git a/test/CodeGenCXX/ubsan-global-alignment.cpp b/test/CodeGenCXX/ubsan-global-alignment.cpp new file mode 100644 index 000000000000..67fcfd469a96 --- /dev/null +++ b/test/CodeGenCXX/ubsan-global-alignment.cpp @@ -0,0 +1,29 @@ +// RUN: %clang_cc1 -std=c++11 -triple x86_64-apple-darwin10 -emit-llvm -o - %s -fsanitize=alignment | FileCheck %s + +struct S { + int I; +}; + +extern S g_S; +extern S array_S[]; + +// CHECK-LABEL: define i32 @_Z18load_extern_global +int load_extern_global() { + // FIXME: The IR builder constant-folds the alignment check away to 'true' + // here, so we never call the diagnostic. This is PR32630. + // CHECK-NOT: ptrtoint i32* {{.*}} to i32, !nosanitize + // CHECK: [[I:%.*]] = load i32, i32* getelementptr inbounds (%struct.S, %struct.S* @g_S, i32 0, i32 0), align 4 + // CHECK-NEXT: ret i32 [[I]] + return g_S.I; +} + +// CHECK-LABEL: define i32 @_Z22load_from_extern_array +int load_from_extern_array(int I) { + // CHECK: [[I:%.*]] = getelementptr inbounds %struct.S, %struct.S* {{.*}}, i32 0, i32 0 + // CHECK-NEXT: [[PTRTOINT:%.*]] = ptrtoint i32* [[I]] to i64, !nosanitize + // CHECK-NEXT: [[AND:%.*]] = and i64 [[PTRTOINT]], 3, !nosanitize + // CHECK-NEXT: [[ICMP:%.*]] = icmp eq i64 [[AND]], 0, !nosanitize + // CHECK-NEXT: br i1 [[ICMP]] + // CHECK: call void @__ubsan_handle_type_mismatch + return array_S[I].I; +} diff --git a/test/CodeGenCXX/ubsan-suppress-checks.cpp b/test/CodeGenCXX/ubsan-suppress-checks.cpp new file mode 100644 index 000000000000..8ec94556c136 --- /dev/null +++ b/test/CodeGenCXX/ubsan-suppress-checks.cpp @@ -0,0 +1,221 @@ +// RUN: %clang_cc1 -std=c++11 -triple x86_64-apple-darwin10 -emit-llvm -o - %s -fsanitize=alignment | FileCheck %s --check-prefixes=CHECK,ALIGN +// RUN: %clang_cc1 -std=c++11 -triple x86_64-apple-darwin10 -emit-llvm -o - %s -fsanitize=null | FileCheck %s --check-prefixes=CHECK,NULL +// RUN: %clang_cc1 -std=c++11 -triple x86_64-apple-darwin10 -emit-llvm -o - %s -fsanitize=alignment,null -DCHECK_LAMBDA | FileCheck %s --check-prefixes=LAMBDA + +struct A { + int foo; + + // CHECK-LABEL: define linkonce_odr void @_ZN1A10do_nothingEv + void do_nothing() { + // ALIGN: %[[THISINT1:[0-9]+]] = ptrtoint %struct.A* %{{.*}} to i64, !nosanitize + // ALIGN: and i64 %[[THISINT1]], 3, !nosanitize + // NULL: icmp ne %struct.A* %[[THIS1:[a-z0-9]+]], null, !nosanitize + // NULL: ptrtoint %struct.A* %[[THIS1]] to i64, !nosanitize + // CHECK: call void @__ubsan_handle_type_mismatch + // CHECK-NOT: call void @__ubsan_handle_type_mismatch + // CHECK: ret void + } + +#ifdef CHECK_LAMBDA + // LAMBDA-LABEL: define linkonce_odr void @_ZN1A22do_nothing_with_lambdaEv + void do_nothing_with_lambda() { + // LAMBDA: icmp ne %struct.A* %[[THIS2:[a-z0-9]+]], null, !nosanitize + // LAMBDA: %[[THISINT2:[0-9]+]] = ptrtoint %struct.A* %[[THIS2]] to i64, !nosanitize + // LAMBDA: and i64 %[[THISINT2]], 3, !nosanitize + // LAMBDA: call void @__ubsan_handle_type_mismatch + + auto f = [&] { + foo = 0; + }; + f(); + + // LAMBDA: icmp ne %class.anon* %[[FUNCVAR:.*]], null, !nosanitize + // LAMBDA: %[[LAMBDAINT:[0-9]+]] = ptrtoint %class.anon* %[[FUNCVAR]] to i64, !nosanitize + // LAMBDA: and i64 %[[LAMBDAINT]], 7, !nosanitize + // LAMBDA: call void @__ubsan_handle_type_mismatch + + // LAMBDA-NOT: call void @__ubsan_handle_type_mismatch + // LAMBDA: ret void + } + +// Check the IR for the lambda: +// +// LAMBDA-LABEL: define linkonce_odr void @_ZZN1A22do_nothing_with_lambdaEvENKUlvE_clEv +// LAMBDA: call void @__ubsan_handle_type_mismatch +// LAMBDA-NOT: call void @__ubsan_handle_type_mismatch +// LAMBDA: ret void +#endif + + // CHECK-LABEL: define linkonce_odr i32 @_ZN1A11load_memberEv + int load_member() { + // ALIGN: %[[THISINT3:[0-9]+]] = ptrtoint %struct.A* %{{.*}} to i64, !nosanitize + // ALIGN: and i64 %[[THISINT3]], 3, !nosanitize + // NULL: icmp ne %struct.A* %[[THIS3:[a-z0-9]+]], null, !nosanitize + // NULL: ptrtoint %struct.A* %[[THIS3]] to i64, !nosanitize + // CHECK: call void @__ubsan_handle_type_mismatch + // CHECK-NOT: call void @__ubsan_handle_type_mismatch + return foo; + // CHECK: ret i32 + } + + // CHECK-LABEL: define linkonce_odr i32 @_ZN1A11call_methodEv + int call_method() { + // ALIGN: %[[THISINT4:[0-9]+]] = ptrtoint %struct.A* %{{.*}} to i64, !nosanitize + // ALIGN: and i64 %[[THISINT4]], 3, !nosanitize + // NULL: icmp ne %struct.A* %[[THIS4:[a-z0-9]+]], null, !nosanitize + // NULL: ptrtoint %struct.A* %[[THIS4]] to i64, !nosanitize + // CHECK: call void @__ubsan_handle_type_mismatch + // CHECK-NOT: call void @__ubsan_handle_type_mismatch + return load_member(); + // CHECK: ret i32 + } + + // CHECK-LABEL: define linkonce_odr void @_ZN1A15assign_member_1Ev + void assign_member_1() { + // ALIGN: %[[THISINT5:[0-9]+]] = ptrtoint %struct.A* %{{.*}} to i64, !nosanitize + // ALIGN: and i64 %[[THISINT5]], 3, !nosanitize + // NULL: icmp ne %struct.A* %[[THIS5:[a-z0-9]+]], null, !nosanitize + // NULL: ptrtoint %struct.A* %[[THIS5]] to i64, !nosanitize + // CHECK: call void @__ubsan_handle_type_mismatch + // CHECK-NOT: call void @__ubsan_handle_type_mismatch + foo = 0; + // CHECK: ret void + } + + // CHECK-LABEL: define linkonce_odr void @_ZN1A15assign_member_2Ev + void assign_member_2() { + // ALIGN: %[[THISINT6:[0-9]+]] = ptrtoint %struct.A* %{{.*}} to i64, !nosanitize + // ALIGN: and i64 %[[THISINT6]], 3, !nosanitize + // NULL: icmp ne %struct.A* %[[THIS6:[a-z0-9]+]], null, !nosanitize + // NULL: ptrtoint %struct.A* %[[THIS6]] to i64, !nosanitize + // CHECK: call void @__ubsan_handle_type_mismatch + // CHECK-NOT: call void @__ubsan_handle_type_mismatch + (__extension__ (this))->foo = 0; + // CHECK: ret void + } + + // CHECK-LABEL: define linkonce_odr void @_ZNK1A15assign_member_3Ev + void assign_member_3() const { + // ALIGN: %[[THISINT7:[0-9]+]] = ptrtoint %struct.A* %{{.*}} to i64, !nosanitize + // ALIGN: and i64 %[[THISINT7]], 3, !nosanitize + // NULL: icmp ne %struct.A* %[[THIS7:[a-z0-9]+]], null, !nosanitize + // NULL: ptrtoint %struct.A* %[[THIS7]] to i64, !nosanitize + // CHECK: call void @__ubsan_handle_type_mismatch + // CHECK-NOT: call void @__ubsan_handle_type_mismatch + const_cast<A *>(this)->foo = 0; + // CHECK: ret void + } + + // CHECK-LABEL: define linkonce_odr i32 @_ZN1A22call_through_referenceERS_ + static int call_through_reference(A &a) { + // ALIGN: %[[OBJINT:[0-9]+]] = ptrtoint %struct.A* %{{.*}} to i64, !nosanitize + // ALIGN: and i64 %[[OBJINT]], 3, !nosanitize + // ALIGN: call void @__ubsan_handle_type_mismatch + // NULL-NOT: call void @__ubsan_handle_type_mismatch + return a.load_member(); + // CHECK: ret i32 + } + + // CHECK-LABEL: define linkonce_odr i32 @_ZN1A20call_through_pointerEPS_ + static int call_through_pointer(A *a) { + // CHECK: call void @__ubsan_handle_type_mismatch + return a->load_member(); + // CHECK: ret i32 + } +}; + +struct B { + operator A*() const { return nullptr; } + + // CHECK-LABEL: define linkonce_odr i32 @_ZN1B11load_memberEv + static int load_member() { + // Check &b before converting it to an A*. + // CHECK: call void @__ubsan_handle_type_mismatch + // + // Check the result of the conversion before using it. + // NULL: call void @__ubsan_handle_type_mismatch + // + // CHECK-NOT: call void @__ubsan_handle_type_mismatch + B b; + return static_cast<A *>(b)->load_member(); + // CHECK: ret i32 + } +}; + +struct Base { + int foo; + + virtual int load_member_1() = 0; +}; + +struct Derived : public Base { + int bar; + + // CHECK-LABEL: define linkonce_odr i32 @_ZN7Derived13load_member_2Ev + int load_member_2() { + // ALIGN: %[[THISINT8:[0-9]+]] = ptrtoint %struct.Derived* %{{.*}} to i64, !nosanitize + // ALIGN: and i64 %[[THISINT8]], 7, !nosanitize + // ALIGN: call void @__ubsan_handle_type_mismatch + // NULL: icmp ne %struct.Derived* %[[THIS8:[a-z0-9]+]], null, !nosanitize + // NULL: ptrtoint %struct.Derived* %[[THIS8]] to i64, !nosanitize + // CHECK: call void @__ubsan_handle_type_mismatch + // + // Check the result of the cast before using it. + // CHECK: call void @__ubsan_handle_type_mismatch + // + // CHECK-NOT: call void @__ubsan_handle_type_mismatch + return dynamic_cast<Base *>(this)->load_member_1(); + // CHECK: ret i32 + } + + // CHECK-LABEL: define linkonce_odr i32 @_ZN7Derived13load_member_3Ev + int load_member_3() { + // ALIGN: %[[THISINT9:[0-9]+]] = ptrtoint %struct.Derived* %{{.*}} to i64, !nosanitize + // ALIGN: and i64 %[[THISINT9]], 7, !nosanitize + // ALIGN: call void @__ubsan_handle_type_mismatch + // ALIGN: call void @__ubsan_handle_type_mismatch + // NULL: icmp ne %struct.Derived* %[[THIS9:[a-z0-9]+]], null, !nosanitize + // NULL: ptrtoint %struct.Derived* %[[THIS9]] to i64, !nosanitize + // CHECK: call void @__ubsan_handle_type_mismatch + // CHECK-NOT: call void @__ubsan_handle_type_mismatch + return reinterpret_cast<Derived *>(static_cast<Base *>(this))->foo; + // CHECK: ret i32 + } + + // CHECK-LABEL: define linkonce_odr i32 @_ZN7Derived13load_member_1Ev + int load_member_1() override { + // ALIGN: %[[THISINT10:[0-9]+]] = ptrtoint %struct.Derived* %{{.*}} to i64, !nosanitize + // ALIGN: and i64 %[[THISINT10]], 7, !nosanitize + // ALIGN: call void @__ubsan_handle_type_mismatch + // NULL: icmp ne %struct.Derived* %[[THIS10:[a-z0-9]+]], null, !nosanitize + // NULL: ptrtoint %struct.Derived* %[[THIS10]] to i64, !nosanitize + // CHECK: call void @__ubsan_handle_type_mismatch + // CHECK-NOT: call void @__ubsan_handle_type_mismatch + return foo + bar; + // CHECK: ret i32 + } +}; + +void force_irgen() { + A *a; + a->do_nothing(); +#ifdef CHECK_LAMBDA + a->do_nothing_with_lambda(); +#endif + a->load_member(); + a->call_method(); + a->assign_member_1(); + a->assign_member_2(); + a->assign_member_3(); + A::call_through_reference(*a); + A::call_through_pointer(a); + + B::load_member(); + + Base *b = new Derived; + b->load_member_1(); + + Derived *d; + d->load_member_2(); + d->load_member_3(); +} diff --git a/test/CodeGenCXX/ubsan-type-checks.cpp b/test/CodeGenCXX/ubsan-type-checks.cpp new file mode 100644 index 000000000000..786d049dfb56 --- /dev/null +++ b/test/CodeGenCXX/ubsan-type-checks.cpp @@ -0,0 +1,36 @@ +// RUN: %clang_cc1 -std=c++11 -triple x86_64-apple-darwin10 -emit-llvm -o - %s -fsanitize=alignment | FileCheck %s -check-prefixes=ALIGN,COMMON +// RUN: %clang_cc1 -std=c++11 -triple x86_64-apple-darwin10 -emit-llvm -o - %s -fsanitize=null | FileCheck %s -check-prefixes=NULL,COMMON +// RUN: %clang_cc1 -std=c++11 -triple x86_64-apple-darwin10 -emit-llvm -o - %s -fsanitize=object-size | FileCheck %s -check-prefixes=OBJSIZE,COMMON + +struct A { + // COMMON-LABEL: define linkonce_odr void @_ZN1A10do_nothingEv + void do_nothing() { + // ALIGN-NOT: ptrtoint %struct.A* %{{.*}} to i64, !nosanitize + + // NULL: icmp ne %struct.A* %{{.*}}, null, !nosanitize + + // OBJSIZE-NOT: call i64 @llvm.objectsize + } +}; + +struct B { + int x; + + // COMMON-LABEL: define linkonce_odr void @_ZN1B10do_nothingEv + void do_nothing() { + // ALIGN: ptrtoint %struct.B* %{{.*}} to i64, !nosanitize + // ALIGN: and i64 %{{.*}}, 3, !nosanitize + + // NULL: icmp ne %struct.B* %{{.*}}, null, !nosanitize + + // OBJSIZE-NOT: call i64 @llvm.objectsize + } +}; + +void force_irgen() { + A a; + a.do_nothing(); + + B b; + b.do_nothing(); +} diff --git a/test/CodeGenCXX/unaligned.cpp b/test/CodeGenCXX/unaligned.cpp new file mode 100644 index 000000000000..95549d3339f0 --- /dev/null +++ b/test/CodeGenCXX/unaligned.cpp @@ -0,0 +1,6 @@ +// RUN: %clang_cc1 -x c++ -std=c++11 -triple x86_64-unknown-linux-gnu -fms-extensions -emit-llvm < %s | FileCheck %s + +int foo() { + // CHECK: ret i32 1 + return alignof(__unaligned int); +} diff --git a/test/CodeGenCXX/volatile-1.cpp b/test/CodeGenCXX/volatile-1.cpp index f32e4288b897..75fb0d26f413 100644 --- a/test/CodeGenCXX/volatile-1.cpp +++ b/test/CodeGenCXX/volatile-1.cpp @@ -1,4 +1,5 @@ -// RUN: %clang_cc1 -Wno-unused-value -triple %itanium_abi_triple -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -Wno-unused-value -triple %itanium_abi_triple -emit-llvm %s -std=c++98 -o - | FileCheck %s +// RUN: %clang_cc1 -Wno-unused-value -triple %itanium_abi_triple -emit-llvm %s -std=c++11 -o - | FileCheck -check-prefix=CHECK -check-prefix=CHECK11 %s // CHECK: @i = global [[INT:i[0-9]+]] 0 volatile int i, j, k; @@ -22,18 +23,22 @@ void test() { asm("nop"); // CHECK: call void asm - // should not load + // should not load in C++98 i; + // CHECK11-NEXT: load volatile [[INT]], [[INT]]* @i (float)(ci); // CHECK-NEXT: load volatile [[INT]], [[INT]]* getelementptr inbounds ([[CINT]], [[CINT]]* @ci, i32 0, i32 0) // CHECK-NEXT: load volatile [[INT]], [[INT]]* getelementptr inbounds ([[CINT]], [[CINT]]* @ci, i32 0, i32 1) // CHECK-NEXT: sitofp [[INT]] - // These are not uses in C++: + // These are not uses in C++98: // [expr.static.cast]p6: // The lvalue-to-rvalue . . . conversions are not applied to the expression. (void)ci; + // CHECK11-NEXT: load volatile [[INT]], [[INT]]* getelementptr inbounds ([[CINT]], [[CINT]]* @ci, i32 0, i32 0) + // CHECK11-NEXT: load volatile [[INT]], [[INT]]* getelementptr inbounds ([[CINT]], [[CINT]]* @ci, i32 0, i32 1) + (void)a; (void)(ci=ci); @@ -126,7 +131,8 @@ void test() { // CHECK-NEXT: load volatile // CHECK-NEXT: sitofp - (void)i; + (void)i; // This is now a load in C++11 + // CHECK11-NEXT: load volatile i=i; // CHECK-NEXT: load volatile @@ -155,13 +161,15 @@ void test() { // CHECK-NEXT: br label // CHECK: phi - (void)(i,(i=i)); + (void)(i,(i=i)); // first i is also a load in C++11 + // CHECK11-NEXT: load volatile // CHECK-NEXT: load volatile // CHECK-NEXT: store volatile - i=i,k; + i=i,k; // k is also a load in C++11 // CHECK-NEXT: load volatile [[INT]], [[INT]]* @i // CHECK-NEXT: store volatile {{.*}}, [[INT]]* @i + // CHECK11-NEXT: load volatile [[INT]], [[INT]]* @k (i=j,k=j); // CHECK-NEXT: load volatile [[INT]], [[INT]]* @j @@ -169,11 +177,14 @@ void test() { // CHECK-NEXT: load volatile [[INT]], [[INT]]* @j // CHECK-NEXT: store volatile {{.*}}, [[INT]]* @k - (i=j,k); + (i=j,k); // k is also a load in C++11 // CHECK-NEXT: load volatile [[INT]], [[INT]]* @j // CHECK-NEXT: store volatile {{.*}}, [[INT]]* @i + // CHECK11-NEXT: load volatile [[INT]], [[INT]]* @k - (i,j); + (i,j); // i and j both are loads in C++11 + // CHECK11-NEXT: load volatile [[INT]], [[INT]]* @i + // CHECK11-NEXT: load volatile [[INT]], [[INT]]* @j // Extra load in C++. i=c=k; @@ -190,7 +201,9 @@ void test() { // CHECK-NEXT: add nsw [[INT]] // CHECK-NEXT: store volatile - ci; + ci; // ci is a load in C++11 + // CHECK11-NEXT: load volatile {{.*}} @ci, i32 0, i32 0 + // CHECK11-NEXT: load volatile {{.*}} @ci, i32 0, i32 1 asm("nop"); // CHECK-NEXT: call void asm @@ -338,8 +351,9 @@ void test() { // CHECK-NEXT: load volatile // CHECK-NEXT: add - (i,j)=k; + (i,j)=k; // i is also a load in C++11 // CHECK-NEXT: load volatile [[INT]], [[INT]]* @k + // CHECK11-NEXT: load volatile [[INT]], [[INT]]* @i // CHECK-NEXT: store volatile {{.*}}, [[INT]]* @j (j=k,i)=i; diff --git a/test/CodeGenCXX/volatile.cpp b/test/CodeGenCXX/volatile.cpp index ea7429f291c9..9c0271b21dfe 100644 --- a/test/CodeGenCXX/volatile.cpp +++ b/test/CodeGenCXX/volatile.cpp @@ -1,4 +1,5 @@ -// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -emit-llvm -std=c++98 -o - | FileCheck %s +// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -emit-llvm -std=c++11 -o - | FileCheck -check-prefix=CHECK -check-prefix=CHECK11 %s // Check that IR gen doesn't try to do an lvalue-to-rvalue conversion // on a volatile reference result. rdar://problem/8338198 @@ -27,6 +28,7 @@ namespace test1 { // CHECK-LABEL: define void @_ZN5test14testEv() void test() { // CHECK: [[TMP:%.*]] = load i32*, i32** @_ZN5test11xE, align 8 + // CHECK11-NEXT: {{%.*}} = load volatile i32, i32* [[TMP]], align 4 // CHECK-NEXT: ret void *x; } |