diff --git a/gcc/d/d-codegen.cc b/gcc/d/d-codegen.cc
index 95dc8b6327ef99d46c77c359459c7e4e31b21498..dc528164aaffd6e001eb2268a7c252a3193cb61c 100644
--- a/gcc/d/d-codegen.cc
+++ b/gcc/d/d-codegen.cc
@@ -2270,10 +2270,17 @@ d_build_call (TypeFunction *tf, tree callable, tree object,
 	      Type *t = arg->type->toBasetype ();
 	      StructDeclaration *sd = t->baseElemOf ()->isTypeStruct ()->sym;
 
-	      /* Nested structs also have ADDRESSABLE set, but if the type has
-		 neither a copy constructor nor a destructor available, then we
-		 need to take care of copying its value before passing it.  */
-	      if (arg->op == EXP::structLiteral || (!sd->postblit && !sd->dtor))
+	      /* Need to take care of copying its value before passing the
+		 argument in the following scenarios:
+		 - The argument is a literal expression; a CONSTRUCTOR can't
+		 have its address taken.
+		 - The type has neither a copy constructor nor a destructor
+		 available; nested structs also have ADDRESSABLE set.
+		 - The ABI of the function expects the callee to destroy its
+		 arguments; when the caller is handles destruction, then `targ'
+		 has already been made into a temporary. */
+	      if (arg->op == EXP::structLiteral || (!sd->postblit && !sd->dtor)
+		  || target.isCalleeDestroyingArgs (tf))
 		targ = force_target_expr (targ);
 
 	      targ = convert (build_reference_type (TREE_TYPE (targ)),
diff --git a/gcc/d/decl.cc b/gcc/d/decl.cc
index d2e84d3ba619504f769d8765a9fe746b19579615..827495b3e3036e39cb0572a576087384bb8d17d6 100644
--- a/gcc/d/decl.cc
+++ b/gcc/d/decl.cc
@@ -863,10 +863,28 @@ public:
 	    /* Maybe put variable on list of things needing destruction.  */
 	    if (d->needsScopeDtor ())
 	      {
+		/* Rewrite: `decl = exp' => TARGET_EXPR(decl, exp, dtor).  */
 		vec_safe_push (d_function_chain->vars_in_scope, decl);
+
 		/* Force a TARGET_EXPR to add the corresponding cleanup.  */
-		exp = force_target_expr (compound_expr (exp, decl));
-		TARGET_EXPR_CLEANUP (exp) = build_expr (d->edtor);
+		if (TREE_CODE (exp) != TARGET_EXPR)
+		  {
+		    if (VOID_TYPE_P (TREE_TYPE (exp)))
+		      exp = compound_expr (exp, decl);
+
+		    exp = force_target_expr (exp);
+		  }
+
+		TARGET_EXPR_CLEANUP (exp)
+		  = compound_expr (TARGET_EXPR_CLEANUP (exp),
+				   build_expr (d->edtor));
+
+		/* The decl is really an alias for the TARGET_EXPR slot.  */
+		SET_DECL_VALUE_EXPR (decl, TARGET_EXPR_SLOT (exp));
+		DECL_HAS_VALUE_EXPR_P (decl) = 1;
+		/* This tells the gimplifier not to emit a clobber for the decl
+		   as its lifetime ends when the slot gets cleaned up.  */
+		TREE_ADDRESSABLE (decl) = 0;
 	      }
 
 	    add_stmt (exp);
diff --git a/gcc/testsuite/gdc.dg/torture/pr113758.d b/gcc/testsuite/gdc.dg/torture/pr113758.d
new file mode 100644
index 0000000000000000000000000000000000000000..dc53883a8dea5fb572f8704fe78a4b4a3d334822
--- /dev/null
+++ b/gcc/testsuite/gdc.dg/torture/pr113758.d
@@ -0,0 +1,19 @@
+// { dg-do run }
+// { dg-skip-if "needs gcc/config.d" { ! d_runtime } }
+struct S113758
+{
+    int field;
+    ~this() { field = 0; }
+}
+
+void main()
+{
+    auto var = S113758(1);
+    f113758d(var);
+    assert(var.field == 1);
+    f113758cxx(var);
+    assert(var.field == 1);
+}
+
+extern (D)   void f113758d(S113758 arg) { }
+extern (C++) void f113758cxx(S113758 arg) { }