diff dmd/ReturnStatement.d @ 135:af1bebfd96a4 dmd2037

dmd 2.038
author Eldar Insafutdinov <e.insafutdinov@gmail.com>
date Mon, 13 Sep 2010 22:19:42 +0100
parents e28b18c23469
children a43c65469219
line wrap: on
line diff
--- a/dmd/ReturnStatement.d	Sat Sep 11 13:03:39 2010 +0100
+++ b/dmd/ReturnStatement.d	Mon Sep 13 22:19:42 2010 +0100
@@ -35,6 +35,7 @@
 import dmd.VarDeclaration;
 import dmd.GlobalExpressions;
 import dmd.BE;
+import dmd.Global;
 
 import dmd.codegen.Util;
 
@@ -173,14 +174,46 @@
 			if (fd.returnLabel && tbret.ty != TY.Tvoid) {
 				;
 			} else if (fd.inferRetType) {
-				if (fd.type.nextOf()) {
-					if (!exp.type.equals(fd.type.nextOf()))
-						error("mismatched function return type inference of %s and %s", exp.type.toChars(), fd.type.nextOf().toChars());
+				auto tf = cast(TypeFunction)fd.type;
+	            assert(tf.ty == TY.Tfunction);
+	            Type tfret = tf.nextOf();
+	            if (tfret)
+                {
+   					if (!exp.type.equals(tfret))
+						error("mismatched function return type inference of %s and %s", exp.type.toChars(), tfret.toChars());
+		            /* The "refness" is determined by the first return statement,
+		             * not all of them. This means:
+		             *    return 3; return x;  // ok, x can be a value
+		             *    return x; return 3;  // error, 3 is not an lvalue
+		             */
 				}
 				else
 				{
-					(cast(TypeFunction)fd.type).next = exp.type;
-					fd.type = fd.type.semantic(loc, sc);
+		            if (tf.isref)
+		            {   /* Determine "refness" of function return:
+		                 * if it's an lvalue, return by ref, else return by value
+		                 */
+		                if (exp.isLvalue())
+		                {
+			                /* Return by ref
+			                 * (but first ensure it doesn't fail the "check for
+			                 * escaping reference" test)
+			                 */
+			                uint errors = global.errors;
+			                global.gag++;
+			                exp.checkEscapeRef();
+			                global.gag--;
+			                if (errors != global.errors)
+			                {   tf.isref = false;	// return by value
+			                    global.errors = errors;
+			                }
+		                }
+		                else
+			                tf.isref = false;	// return by value
+		            }
+		            tf.next = exp.type;
+		            fd.type = tf.semantic(loc, sc);
+
 					if (!fd.tintro)
 					{   
 						tret = fd.type.nextOf();
@@ -290,19 +323,14 @@
 				else
 					exp = exp.toLvalue(sc, exp);
 
-				if (exp.op == TOK.TOKvar)
-				{	
-					VarExp ve = cast(VarExp)exp;
-					VarDeclaration v = ve.var.isVarDeclaration();
-					if (v && !v.isDataseg() && !(v.storage_class & (STC.STCref | STC.STCout))) {
-						error("escaping reference to local variable %s", v.toChars());
-					}
-				}
+				exp.checkEscapeRef();
 			}
-
-			//exp.dump(0);
-			//exp.print();
-			exp.checkEscape();
+            else
+            {
+			    //exp.dump(0);
+			    //exp.print();
+			    exp.checkEscape();
+            }
 		}
 
 		/* BUG: need to issue an error on: