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