Index: clang/lib/CodeGen/CGClass.cpp =================================================================== --- clang/lib/CodeGen/CGClass.cpp +++ clang/lib/CodeGen/CGClass.cpp @@ -2196,6 +2196,7 @@ GlobalDecl GD(Ctor, CtorType); InlinedInheritingConstructorScope Scope(*this, GD); ApplyInlineDebugLocation DebugScope(*this, GD); + RunCleanupsScope RunCleanups(*this); // Save the arguments to be passed to the inherited constructor. CXXInheritedCtorInitExprArgs = Args; Index: clang/test/CodeGenCXX/inheriting-constructor-cleanup.cpp =================================================================== --- /dev/null +++ clang/test/CodeGenCXX/inheriting-constructor-cleanup.cpp @@ -0,0 +1,52 @@ +// RUN: %clang_cc1 -triple x86_64-darwin -std=c++11 -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-darwin -std=c++11 -fcxx-exceptions -fexceptions -emit-llvm -o - %s | FileCheck %s --check-prefix=EXCEPTIONS + +// PR36748 +// rdar://problem/45805151 + +// Classes to verify order of destroying function parameters. +struct S1 { + ~S1(); +}; +struct S2 { + ~S2(); +}; + +struct Base { + // Use variadic args to cause inlining the inherited constructor. + Base(const S1&, const S2&, const char *fmt, ...) {} +}; + +struct NonTrivialDtor { + ~NonTrivialDtor() {} +}; +struct Inheritor : public NonTrivialDtor, public Base { + using Base::Base; +}; + +void f() { + Inheritor(S1(), S2(), "foo"); + // CHECK-LABEL: define void @_Z1fv + // CHECK: %[[TMP1:.*]] = alloca %struct.S1 + // CHECK: %[[TMP2:.*]] = alloca %struct.S2 + // CHECK: call void (%struct.Base*, %struct.S1*, %struct.S2*, i8*, ...) @_ZN4BaseC2ERK2S1RK2S2PKcz(%struct.Base* {{.*}}, %struct.S1* dereferenceable(1) %[[TMP1]], %struct.S2* dereferenceable(1) %[[TMP2]], i8* {{.*}}) + // CHECK-NEXT: call void @_ZN9InheritorD1Ev(%struct.Inheritor* {{.*}}) + // CHECK-NEXT: call void @_ZN2S2D1Ev(%struct.S2* %[[TMP2]]) + // CHECK-NEXT: call void @_ZN2S1D1Ev(%struct.S1* %[[TMP1]]) + + // EXCEPTIONS-LABEL: define void @_Z1fv + // EXCEPTIONS: %[[TMP1:.*]] = alloca %struct.S1 + // EXCEPTIONS: %[[TMP2:.*]] = alloca %struct.S2 + // EXCEPTIONS: invoke void (%struct.Base*, %struct.S1*, %struct.S2*, i8*, ...) @_ZN4BaseC2ERK2S1RK2S2PKcz(%struct.Base* {{.*}}, %struct.S1* dereferenceable(1) %[[TMP1]], %struct.S2* dereferenceable(1) %[[TMP2]], i8* {{.*}}) + // EXCEPTIONS-NEXT: to label %[[CONT:.*]] unwind label %[[LPAD:.*]] + + // EXCEPTIONS: [[CONT]]: + // EXCEPTIONS-NEXT: call void @_ZN9InheritorD1Ev(%struct.Inheritor* {{.*}}) + // EXCEPTIONS-NEXT: call void @_ZN2S2D1Ev(%struct.S2* %[[TMP2]]) + // EXCEPTIONS-NEXT: call void @_ZN2S1D1Ev(%struct.S1* %[[TMP1]]) + + // EXCEPTIONS: [[LPAD]]: + // EXCEPTIONS: call void @_ZN14NonTrivialDtorD2Ev(%struct.NonTrivialDtor* {{.*}}) + // EXCEPTIONS-NEXT: call void @_ZN2S2D1Ev(%struct.S2* %[[TMP2]]) + // EXCEPTIONS-NEXT: call void @_ZN2S1D1Ev(%struct.S1* %[[TMP1]]) +} Index: clang/test/CodeGenObjCXX/inheriting-constructor-cleanup.mm =================================================================== --- /dev/null +++ clang/test/CodeGenObjCXX/inheriting-constructor-cleanup.mm @@ -0,0 +1,33 @@ +// RUN: %clang_cc1 -triple x86_64-darwin -std=c++11 -fobjc-arc -emit-llvm -o - %s | FileCheck %s +// rdar://problem/45805151 + +struct Strong { + __strong id x; +}; + +struct Base { + // Use variadic args to force inlining the inherited constructor. + Base(const Strong &s, ...) {} +}; + +struct NonTrivialDtor { + ~NonTrivialDtor() {} +}; +struct Inheritor : public NonTrivialDtor, public Base { + using Base::Base; +}; + +id g(void); +void f() { + Inheritor({g()}); +} +// CHECK-LABEL: define void @_Z1fv +// CHECK: call void (%struct.Base*, %struct.Strong*, ...) @_ZN4BaseC2ERK6Strongz(%struct.Base* {{.*}}, %struct.Strong* dereferenceable(8) {{.*}}) +// CHECK-NEXT: call void @_ZN9InheritorD1Ev(%struct.Inheritor* {{.*}}) +// CHECK-NEXT: call void @_ZN6StrongD1Ev(%struct.Strong* {{.*}}) + +// CHECK-LABEL: define linkonce_odr void @_ZN6StrongD1Ev(%struct.Strong* {{.*}}) +// CHECK: call void @_ZN6StrongD2Ev(%struct.Strong* {{.*}}) + +// CHECK-LABEL: define linkonce_odr void @_ZN6StrongD2Ev(%struct.Strong* {{.*}}) +// CHECK: call void @objc_storeStrong(i8** {{.*}}, i8* null)