|  | // RUN: %clang_cc1 -triple x86_64-apple-darwin -std=c++11 -emit-llvm %s -o - | FileCheck %s | 
|  |  | 
|  | struct A { | 
|  | A(const A&); | 
|  | A(); | 
|  | ~A(); | 
|  | }; | 
|  |  | 
|  | struct B : public A { | 
|  | B(); | 
|  | B(const B& Other); | 
|  | ~B(); | 
|  | }; | 
|  |  | 
|  | struct C : public B { | 
|  | C(); | 
|  | C(const C& Other); | 
|  | ~C(); | 
|  | }; | 
|  |  | 
|  | struct X { | 
|  | operator B&(); | 
|  | operator C&(); | 
|  | X(const X&); | 
|  | X(); | 
|  | ~X(); | 
|  | B b; | 
|  | C c; | 
|  | }; | 
|  |  | 
|  | void test0_helper(A); | 
|  | void test0(X x) { | 
|  | test0_helper(x); | 
|  | // CHECK-LABEL:    define{{.*}} void @_Z5test01X( | 
|  | // CHECK-SAME: ptr noundef [[ARG:%.*]]) | 
|  | // CHECK:      [[ARG_ADDR:%.*]] = alloca ptr | 
|  | // CHECK-NEXT: [[TMP:%.*]] = alloca [[A:%.*]], align | 
|  | // CHECK-NEXT: store ptr [[ARG]], ptr [[ARG_ADDR]] | 
|  | // CHECK-NEXT: [[T0:%.*]] = call noundef nonnull align {{[0-9]+}} dereferenceable({{[0-9]+}}) ptr @_ZN1XcvR1BEv( | 
|  | // CHECK-NEXT: call void @_ZN1AC1ERKS_(ptr {{[^,]*}} [[TMP]], ptr noundef nonnull align {{[0-9]+}} dereferenceable({{[0-9]+}}) [[T0]]) | 
|  | // CHECK-NEXT: call void @_Z12test0_helper1A(ptr noundef [[TMP]]) | 
|  | // CHECK-NEXT: call void @_ZN1AD1Ev(ptr {{[^,]*}} [[TMP]]) | 
|  | // CHECK-NEXT: ret void | 
|  | } | 
|  |  | 
|  | struct Base; | 
|  |  | 
|  | struct Root { | 
|  | operator Base&(); | 
|  | }; | 
|  |  | 
|  | struct Derived; | 
|  |  | 
|  | struct Base : Root { | 
|  | Base(const Base &); | 
|  | Base(); | 
|  | operator Derived &(); | 
|  | }; | 
|  |  | 
|  | struct Derived : Base { | 
|  | }; | 
|  |  | 
|  | void test1_helper(Base); | 
|  | void test1(Derived bb) { | 
|  | // CHECK-LABEL:     define{{.*}} void @_Z5test17Derived( | 
|  | // CHECK-NOT: call {{.*}} @_ZN4BasecvR7DerivedEv( | 
|  | // CHECK:     call void @_ZN4BaseC1ERKS_( | 
|  | // CHECK-NOT: call {{.*}} @_ZN4BasecvR7DerivedEv( | 
|  | // CHECK:     call void @_Z12test1_helper4Base( | 
|  | test1_helper(bb); | 
|  | } | 
|  |  | 
|  | // Don't crash after devirtualizing a derived-to-base conversion | 
|  | // to an empty base allocated at offset zero. | 
|  | class Test2a {}; | 
|  | class Test2b final : public virtual Test2a {}; | 
|  | void test2(Test2b &x) { | 
|  | Test2a &y = x; | 
|  | // CHECK-LABEL:    define{{.*}} void @_Z5test2R6Test2b( | 
|  | // CHECK:      [[X:%.*]] = alloca ptr, align 8 | 
|  | // CHECK-NEXT: [[Y:%.*]] = alloca ptr, align 8 | 
|  | // CHECK-NEXT: store ptr {{%.*}}, ptr [[X]], align 8 | 
|  | // CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[X]], align 8 | 
|  | // CHECK-NEXT: store ptr [[T0]], ptr [[Y]], align 8 | 
|  | // CHECK-NEXT: ret void | 
|  | } |