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.
// 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());
+}
+
+}