comparison 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
comparison
equal deleted inserted replaced
134:4251f96733f4 135:af1bebfd96a4
33 import dmd.WANT; 33 import dmd.WANT;
34 import dmd.VarExp; 34 import dmd.VarExp;
35 import dmd.VarDeclaration; 35 import dmd.VarDeclaration;
36 import dmd.GlobalExpressions; 36 import dmd.GlobalExpressions;
37 import dmd.BE; 37 import dmd.BE;
38 import dmd.Global;
38 39
39 import dmd.codegen.Util; 40 import dmd.codegen.Util;
40 41
41 import dmd.backend.Blockx; 42 import dmd.backend.Blockx;
42 import dmd.backend.elem; 43 import dmd.backend.elem;
171 } 172 }
172 173
173 if (fd.returnLabel && tbret.ty != TY.Tvoid) { 174 if (fd.returnLabel && tbret.ty != TY.Tvoid) {
174 ; 175 ;
175 } else if (fd.inferRetType) { 176 } else if (fd.inferRetType) {
176 if (fd.type.nextOf()) { 177 auto tf = cast(TypeFunction)fd.type;
177 if (!exp.type.equals(fd.type.nextOf())) 178 assert(tf.ty == TY.Tfunction);
178 error("mismatched function return type inference of %s and %s", exp.type.toChars(), fd.type.nextOf().toChars()); 179 Type tfret = tf.nextOf();
180 if (tfret)
181 {
182 if (!exp.type.equals(tfret))
183 error("mismatched function return type inference of %s and %s", exp.type.toChars(), tfret.toChars());
184 /* The "refness" is determined by the first return statement,
185 * not all of them. This means:
186 * return 3; return x; // ok, x can be a value
187 * return x; return 3; // error, 3 is not an lvalue
188 */
179 } 189 }
180 else 190 else
181 { 191 {
182 (cast(TypeFunction)fd.type).next = exp.type; 192 if (tf.isref)
183 fd.type = fd.type.semantic(loc, sc); 193 { /* Determine "refness" of function return:
194 * if it's an lvalue, return by ref, else return by value
195 */
196 if (exp.isLvalue())
197 {
198 /* Return by ref
199 * (but first ensure it doesn't fail the "check for
200 * escaping reference" test)
201 */
202 uint errors = global.errors;
203 global.gag++;
204 exp.checkEscapeRef();
205 global.gag--;
206 if (errors != global.errors)
207 { tf.isref = false; // return by value
208 global.errors = errors;
209 }
210 }
211 else
212 tf.isref = false; // return by value
213 }
214 tf.next = exp.type;
215 fd.type = tf.semantic(loc, sc);
216
184 if (!fd.tintro) 217 if (!fd.tintro)
185 { 218 {
186 tret = fd.type.nextOf(); 219 tret = fd.type.nextOf();
187 tbret = tret.toBasetype(); 220 tbret = tret.toBasetype();
188 } 221 }
288 if (tbret.isMutable()) 321 if (tbret.isMutable())
289 exp = exp.modifiableLvalue(sc, exp); 322 exp = exp.modifiableLvalue(sc, exp);
290 else 323 else
291 exp = exp.toLvalue(sc, exp); 324 exp = exp.toLvalue(sc, exp);
292 325
293 if (exp.op == TOK.TOKvar) 326 exp.checkEscapeRef();
294 { 327 }
295 VarExp ve = cast(VarExp)exp; 328 else
296 VarDeclaration v = ve.var.isVarDeclaration(); 329 {
297 if (v && !v.isDataseg() && !(v.storage_class & (STC.STCref | STC.STCout))) { 330 //exp.dump(0);
298 error("escaping reference to local variable %s", v.toChars()); 331 //exp.print();
299 } 332 exp.checkEscape();
300 } 333 }
301 }
302
303 //exp.dump(0);
304 //exp.print();
305 exp.checkEscape();
306 } 334 }
307 335
308 /* BUG: need to issue an error on: 336 /* BUG: need to issue an error on:
309 * this 337 * this
310 * { if (x) return; 338 * { if (x) return;