Fix return of aggregate and return of complex.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@41437 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/CodeGen/CGStmt.cpp b/CodeGen/CGStmt.cpp
index de50d71..014f0aa 100644
--- a/CodeGen/CGStmt.cpp
+++ b/CodeGen/CGStmt.cpp
@@ -270,37 +270,30 @@
 /// if the function returns void, or may be missing one if the function returns
 /// non-void.  Fun stuff :).
 void CodeGenFunction::EmitReturnStmt(const ReturnStmt &S) {
-  RValue RetVal;
-  
   // Emit the result value, even if unused, to evalute the side effects.
   const Expr *RV = S.getRetValue();
-  // FIXME: Handle return of an aggregate!
-  if (RV) 
-    // FIXME: This could be much better for return of aggregate: return inplace.
-    RetVal = EmitAnyExpr(RV);
-  else  // Silence a bogus GCC warning. 
-    RetVal = RValue::get(0);
-  
+
   QualType FnRetTy = CurFuncDecl->getType().getCanonicalType();
   FnRetTy = cast<FunctionType>(FnRetTy)->getResultType();
   
   if (FnRetTy->isVoidType()) {
-    // If the function returns void, emit ret void, and ignore the retval.
+    // If the function returns void, emit ret void.
     Builder.CreateRetVoid();
   } else if (RV == 0) {
-    // "return;" in a function that returns a value.
+    // Handle "return;" in a function that returns a value.
     const llvm::Type *RetTy = CurFn->getFunctionType()->getReturnType();
     if (RetTy == llvm::Type::VoidTy)
       Builder.CreateRetVoid();   // struct return etc.
     else
       Builder.CreateRet(llvm::UndefValue::get(RetTy));
+  } else if (!hasAggregateLLVMType(RV->getType())) {
+    Builder.CreateRet(EmitScalarExpr(RV));
+  } else if (RV->getType()->isComplexType()) {
+    llvm::Value *SRetPtr = CurFn->arg_begin();
+    EmitComplexExprIntoAddr(RV, SRetPtr);
   } else {
-    if (RetVal.isScalar()) {
-      Builder.CreateRet(RetVal.getVal());
-    } else {
-      llvm::Value *SRetPtr = CurFn->arg_begin();
-      EmitStoreThroughLValue(RetVal, LValue::MakeAddr(SRetPtr), FnRetTy);
-    }
+    llvm::Value *SRetPtr = CurFn->arg_begin();
+    EmitAggExpr(RV, SRetPtr, false);
   }
   
   // Emit a block after the branch so that dead code after a return has some