// RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-apple-darwin10 -mconstructor-aliases -O1 -disable-llvm-optzns | FileCheck %s struct Member { ~Member(); }; struct A { virtual ~A(); }; struct B : A { Member m; virtual ~B(); }; // Complete dtor: just an alias because there are no virtual bases. // CHECK: @_ZN1BD1Ev = alias {{.*}} @_ZN1BD2Ev // (aliases from C) // 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 // CHECK: call void @_ZN6MemberD1Ev // CHECK: call void @_ZN1AD2Ev // Deleting dtor: defers to the complete dtor. // CHECK-LABEL: define void @_ZN1BD0Ev(%struct.B* %this) unnamed_addr // CHECK: call void @_ZN1BD1Ev // CHECK: call void @_ZdlPv B::~B() { } struct C : B { ~C(); }; C::~C() { } // Complete dtor: just an alias (checked above). // Deleting dtor: defers to the complete dtor. // CHECK-LABEL: define void @_ZN1CD0Ev(%struct.C* %this) unnamed_addr // CHECK: call void @_ZN1CD1Ev // CHECK: call void @_ZdlPv // Base dtor: just an alias to B's base dtor. namespace PR12798 { // A qualified call to a base class destructor should not undergo virtual // dispatch. Template instantiation used to lose the qualifier. struct A { virtual ~A(); }; template void f(T *p) { p->A::~A(); } // CHECK: define {{.*}} @_ZN7PR127981fINS_1AEEEvPT_( // CHECK: call void @_ZN7PR127981AD1Ev( template void f(A*); }