From 4ce0e5a892bcd313fa574898903a1034a4a07fc2 Mon Sep 17 00:00:00 2001 From: Akira Hatanaka Date: Wed, 18 Apr 2018 23:33:15 +0000 Subject: [PATCH] [CodeGen] Do not push a destructor cleanup for a struct that doesn't have a non-trivial destructor. This fixes a bug introduced in r328731 where CodeGen emits calls to synthesized destructors for non-trivial C structs in C++ mode when the struct passed to EmitCallArg doesn't have a non-trivial destructor. Under Microsoft's ABI, ASTContext::isParamDestroyedInCallee currently always returns true, so it's necessary to check whether the struct has a non-trivial destructor before pushing a cleanup in EmitCallArg. This fixes PR37146. llvm-svn: 330304 --- clang/lib/CodeGen/CGCall.cpp | 11 ++++++++-- .../test/CodeGenCXX/microsoft-abi-eh-cleanups.cpp | 24 ++++++++++++++++++++++ 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index 6797a54..27aa69d 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -3541,13 +3541,20 @@ void CodeGenFunction::EmitCallArg(CallArgList &args, const Expr *E, else Slot = CreateAggTemp(type, "agg.tmp"); - Slot.setExternallyDestructed(); + bool DestroyedInCallee = true, NeedsEHCleanup = true; + if (const auto *RD = type->getAsCXXRecordDecl()) + DestroyedInCallee = RD->hasNonTrivialDestructor(); + else + NeedsEHCleanup = needsEHCleanup(type.isDestructedType()); + + if (DestroyedInCallee) + Slot.setExternallyDestructed(); EmitAggExpr(E, Slot); RValue RV = Slot.asRValue(); args.add(RV, type); - if (type->getAsCXXRecordDecl() || needsEHCleanup(type.isDestructedType())) { + if (DestroyedInCallee && NeedsEHCleanup) { // Create a no-op GEP between the placeholder and the cleanup so we can // RAUW it successfully. It also serves as a marker of the first // instruction where the cleanup is active. diff --git a/clang/test/CodeGenCXX/microsoft-abi-eh-cleanups.cpp b/clang/test/CodeGenCXX/microsoft-abi-eh-cleanups.cpp index 116ce09..6682faf 100644 --- a/clang/test/CodeGenCXX/microsoft-abi-eh-cleanups.cpp +++ b/clang/test/CodeGenCXX/microsoft-abi-eh-cleanups.cpp @@ -313,3 +313,27 @@ class_0::class_0() { // WIN32: br label %[[SKIP_VBASE]] // WIN32: [[SKIP_VBASE]] } + +namespace PR37146 { +// Check that IRGen doesn't emit calls to synthesized destructors for +// non-trival C structs. + +// WIN32: define dso_local void @"?test@PR37146@@YAXXZ"() +// WIN32: call void @llvm.memset.p0i8.i32( +// WIN32: call i32 @"?getS@PR37146@@YA?AUS@1@XZ"( +// WIN32: call void @"?func@PR37146@@YAXUS@1@0@Z"( +// WIN32-NEXT: ret void +// WIN32-NEXT: {{^}$}} + +struct S { + int f; +}; + +void func(S, S); +S getS(); + +void test() { + func(getS(), S()); +} + +} -- 2.7.4