Mercurial > projects > ddmd
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: