Make functions returning a struct indirectly evaluate the returned struct
directly into the sret pointer. This is an optimization in C, but is required
for correctness in C++ for classes with a non-trivial copy constructor.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@90526 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/CodeGen/CodeGenFunction.cpp b/lib/CodeGen/CodeGenFunction.cpp
index 1e952f9..88f02a9 100644
--- a/lib/CodeGen/CodeGenFunction.cpp
+++ b/lib/CodeGen/CodeGenFunction.cpp
@@ -179,9 +179,6 @@
     AllocaInsertPt->setName("allocapt");
 
   ReturnBlock = createBasicBlock("return");
-  ReturnValue = 0;
-  if (!RetTy->isVoidType())
-    ReturnValue = CreateTempAlloca(ConvertType(RetTy), "retval");
 
   Builder.SetInsertPoint(EntryBB);
 
@@ -204,6 +201,19 @@
 
   // FIXME: Leaked.
   CurFnInfo = &CGM.getTypes().getFunctionInfo(FnRetTy, Args);
+
+  if (RetTy->isVoidType()) {
+    // Void type; nothing to return.
+    ReturnValue = 0;
+  } else if (CurFnInfo->getReturnInfo().getKind() == ABIArgInfo::Indirect &&
+             hasAggregateLLVMType(CurFnInfo->getReturnType())) {
+    // Indirect aggregate return; emit returned value directly into sret slot.
+    // This reduces code size, and is also affects correctness in C++.
+    ReturnValue = CurFn->arg_begin();
+  } else {
+    ReturnValue = CreateTempAlloca(ConvertType(RetTy), "retval");
+  }
+
   EmitFunctionProlog(*CurFnInfo, CurFn, Args);
 
   // If any of the arguments have a variably modified type, make sure to