annotate dmd2/statement.c @ 847:356e65836fb5

Merged DMD 2.021 frontend. Removed generated files from dmd/dmd2 dirs.
author Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
date Sat, 13 Dec 2008 16:14:37 +0100
parents f08e0ff8d28c
children 03d7c4aac654
rev   line source
tomas@758 1
tomas@758 2 // Compiler implementation of the D programming language
tomas@758 3 // Copyright (c) 1999-2008 by Digital Mars
tomas@758 4 // All Rights Reserved
tomas@758 5 // written by Walter Bright
tomas@758 6 // http://www.digitalmars.com
tomas@758 7 // License for redistribution is by either the Artistic License
tomas@758 8 // in artistic.txt, or the GNU General Public License in gnu.txt.
tomas@758 9 // See the included readme.txt for details.
tomas@758 10
tomas@758 11 #include <stdio.h>
tomas@758 12 #include <stdlib.h>
tomas@758 13 #include <assert.h>
tomas@758 14
tomas@758 15 #include "mem.h"
tomas@758 16
tomas@758 17 #include "statement.h"
tomas@758 18 #include "expression.h"
tomas@758 19 #include "cond.h"
tomas@758 20 #include "init.h"
tomas@758 21 #include "staticassert.h"
tomas@758 22 #include "mtype.h"
tomas@758 23 #include "scope.h"
tomas@758 24 #include "declaration.h"
tomas@758 25 #include "aggregate.h"
tomas@758 26 #include "id.h"
tomas@758 27 #include "hdrgen.h"
tomas@758 28 #include "parse.h"
tomas@758 29 #include "template.h"
tomas@758 30
tomas@758 31 /******************************** Statement ***************************/
tomas@758 32
tomas@758 33 Statement::Statement(Loc loc)
tomas@758 34 : loc(loc)
tomas@758 35 {
tomas@758 36 #ifdef _DH
tomas@758 37 // If this is an in{} contract scope statement (skip for determining
tomas@758 38 // inlineStatus of a function body for header content)
tomas@758 39 incontract = 0;
tomas@758 40 #endif
tomas@758 41 }
tomas@758 42
tomas@758 43 Statement *Statement::syntaxCopy()
tomas@758 44 {
tomas@758 45 assert(0);
tomas@758 46 return NULL;
tomas@758 47 }
tomas@758 48
tomas@758 49 void Statement::print()
tomas@758 50 {
tomas@758 51 fprintf(stdmsg, "%s\n", toChars());
tomas@758 52 fflush(stdmsg);
tomas@758 53 }
tomas@758 54
tomas@758 55 char *Statement::toChars()
tomas@758 56 { OutBuffer *buf;
tomas@758 57 HdrGenState hgs;
tomas@758 58
tomas@758 59 buf = new OutBuffer();
tomas@758 60 toCBuffer(buf, &hgs);
tomas@758 61 return buf->toChars();
tomas@758 62 }
tomas@758 63
tomas@758 64 void Statement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
tomas@758 65 {
tomas@758 66 buf->printf("Statement::toCBuffer()");
tomas@758 67 buf->writenl();
tomas@758 68 }
tomas@758 69
tomas@758 70 Statement *Statement::semantic(Scope *sc)
tomas@758 71 {
tomas@758 72 return this;
tomas@758 73 }
tomas@758 74
tomas@758 75 // Same as semantic(), but do create a new scope
tomas@758 76
tomas@758 77 Statement *Statement::semanticScope(Scope *sc, Statement *sbreak, Statement *scontinue)
tomas@758 78 { Scope *scd;
tomas@758 79 Statement *s;
tomas@758 80
tomas@758 81 scd = sc->push();
tomas@758 82 if (sbreak)
tomas@758 83 scd->sbreak = sbreak;
tomas@758 84 if (scontinue)
tomas@758 85 scd->scontinue = scontinue;
tomas@758 86 s = semantic(scd);
tomas@758 87 scd->pop();
tomas@758 88 return s;
tomas@758 89 }
tomas@758 90
tomas@758 91 void Statement::error(const char *format, ...)
tomas@758 92 {
tomas@758 93 va_list ap;
tomas@758 94 va_start(ap, format);
tomas@758 95 ::verror(loc, format, ap);
tomas@758 96 va_end( ap );
tomas@758 97 }
tomas@758 98
tomas@758 99 int Statement::hasBreak()
tomas@758 100 {
tomas@758 101 //printf("Statement::hasBreak()\n");
tomas@758 102 return FALSE;
tomas@758 103 }
tomas@758 104
tomas@758 105 int Statement::hasContinue()
tomas@758 106 {
tomas@758 107 return FALSE;
tomas@758 108 }
tomas@758 109
tomas@758 110 // TRUE if statement uses exception handling
tomas@758 111
tomas@758 112 int Statement::usesEH()
tomas@758 113 {
tomas@758 114 return FALSE;
tomas@758 115 }
tomas@758 116
tomas@758 117 /* Only valid after semantic analysis
tomas@758 118 */
tomas@758 119 int Statement::blockExit()
tomas@758 120 {
tomas@758 121 printf("Statement::blockExit(%p)\n", this);
tomas@758 122 printf("%s\n", toChars());
tomas@758 123 assert(0);
tomas@758 124 return BEany;
tomas@758 125 }
tomas@758 126
tomas@758 127 // TRUE if statement may fall off the end without a throw or return
tomas@758 128
tomas@758 129 int Statement::fallOffEnd()
tomas@758 130 {
tomas@758 131 return TRUE;
tomas@758 132 }
tomas@758 133
tomas@758 134 // TRUE if statement 'comes from' somewhere else, like a goto
tomas@758 135
tomas@758 136 int Statement::comeFrom()
tomas@758 137 {
tomas@758 138 //printf("Statement::comeFrom()\n");
tomas@758 139 return FALSE;
tomas@758 140 }
tomas@758 141
tomas@758 142 /****************************************
tomas@758 143 * If this statement has code that needs to run in a finally clause
tomas@758 144 * at the end of the current scope, return that code in the form of
tomas@758 145 * a Statement.
tomas@758 146 * Output:
tomas@758 147 * *sentry code executed upon entry to the scope
tomas@758 148 * *sexception code executed upon exit from the scope via exception
tomas@758 149 * *sfinally code executed in finally block
tomas@758 150 */
tomas@758 151
tomas@758 152 void Statement::scopeCode(Scope *sc, Statement **sentry, Statement **sexception, Statement **sfinally)
tomas@758 153 {
tomas@758 154 //printf("Statement::scopeCode()\n");
tomas@758 155 //print();
tomas@758 156 *sentry = NULL;
tomas@758 157 *sexception = NULL;
tomas@758 158 *sfinally = NULL;
tomas@758 159 }
tomas@758 160
tomas@758 161 /*********************************
tomas@758 162 * Flatten out the scope by presenting the statement
tomas@758 163 * as an array of statements.
tomas@758 164 * Returns NULL if no flattening necessary.
tomas@758 165 */
tomas@758 166
tomas@758 167 Statements *Statement::flatten(Scope *sc)
tomas@758 168 {
tomas@758 169 return NULL;
tomas@758 170 }
tomas@758 171
tomas@758 172
tomas@758 173 /******************************** ExpStatement ***************************/
tomas@758 174
tomas@758 175 ExpStatement::ExpStatement(Loc loc, Expression *exp)
tomas@758 176 : Statement(loc)
tomas@758 177 {
tomas@758 178 this->exp = exp;
tomas@758 179 }
tomas@758 180
tomas@758 181 Statement *ExpStatement::syntaxCopy()
tomas@758 182 {
tomas@758 183 Expression *e = exp ? exp->syntaxCopy() : NULL;
tomas@758 184 ExpStatement *es = new ExpStatement(loc, e);
tomas@758 185 return es;
tomas@758 186 }
tomas@758 187
tomas@758 188 void ExpStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
tomas@758 189 {
tomas@758 190 if (exp)
tomas@758 191 exp->toCBuffer(buf, hgs);
tomas@758 192 buf->writeByte(';');
tomas@758 193 if (!hgs->FLinit.init)
tomas@758 194 buf->writenl();
tomas@758 195 }
tomas@758 196
tomas@758 197 Statement *ExpStatement::semantic(Scope *sc)
tomas@758 198 {
tomas@758 199 if (exp)
tomas@758 200 {
tomas@758 201 //printf("ExpStatement::semantic() %s\n", exp->toChars());
tomas@758 202 exp = exp->semantic(sc);
tomas@758 203 exp = resolveProperties(sc, exp);
tomas@758 204 exp->checkSideEffect(0);
tomas@758 205 exp = exp->optimize(0);
tomas@758 206 if (exp->op == TOKdeclaration && !isDeclarationStatement())
tomas@758 207 { Statement *s = new DeclarationStatement(loc, exp);
tomas@758 208 return s;
tomas@758 209 }
tomas@758 210 //exp = exp->optimize(isDeclarationStatement() ? WANTvalue : 0);
tomas@758 211 }
tomas@758 212 return this;
tomas@758 213 }
tomas@758 214
tomas@758 215 int ExpStatement::blockExit()
tomas@758 216 { int result = BEfallthru;
tomas@758 217
tomas@758 218 if (exp)
tomas@758 219 {
tomas@758 220 if (exp->op == TOKhalt)
tomas@758 221 return BEhalt;
tomas@758 222 if (exp->op == TOKassert)
tomas@758 223 { AssertExp *a = (AssertExp *)exp;
tomas@758 224
tomas@758 225 if (a->e1->isBool(FALSE)) // if it's an assert(0)
tomas@758 226 return BEhalt;
tomas@758 227 }
tomas@758 228 if (exp->canThrow())
tomas@758 229 result |= BEthrow;
tomas@758 230 }
tomas@758 231 return result;
tomas@758 232 }
tomas@758 233
tomas@758 234 int ExpStatement::fallOffEnd()
tomas@758 235 {
tomas@758 236 if (exp)
tomas@758 237 {
tomas@758 238 if (exp->op == TOKassert)
tomas@758 239 { AssertExp *a = (AssertExp *)exp;
tomas@758 240
tomas@758 241 if (a->e1->isBool(FALSE)) // if it's an assert(0)
tomas@758 242 return FALSE;
tomas@758 243 }
tomas@758 244 else if (exp->op == TOKhalt)
tomas@758 245 return FALSE;
tomas@758 246 }
tomas@758 247 return TRUE;
tomas@758 248 }
tomas@758 249
tomas@758 250 /******************************** CompileStatement ***************************/
tomas@758 251
tomas@758 252 CompileStatement::CompileStatement(Loc loc, Expression *exp)
tomas@758 253 : Statement(loc)
tomas@758 254 {
tomas@758 255 this->exp = exp;
tomas@758 256 }
tomas@758 257
tomas@758 258 Statement *CompileStatement::syntaxCopy()
tomas@758 259 {
tomas@758 260 Expression *e = exp->syntaxCopy();
tomas@758 261 CompileStatement *es = new CompileStatement(loc, e);
tomas@758 262 return es;
tomas@758 263 }
tomas@758 264
tomas@758 265 void CompileStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
tomas@758 266 {
tomas@758 267 buf->writestring("mixin(");
tomas@758 268 exp->toCBuffer(buf, hgs);
tomas@758 269 buf->writestring(");");
tomas@758 270 if (!hgs->FLinit.init)
tomas@758 271 buf->writenl();
tomas@758 272 }
tomas@758 273
tomas@758 274 Statements *CompileStatement::flatten(Scope *sc)
tomas@758 275 {
tomas@758 276 //printf("CompileStatement::flatten() %s\n", exp->toChars());
tomas@758 277 exp = exp->semantic(sc);
tomas@758 278 exp = resolveProperties(sc, exp);
tomas@758 279 exp = exp->optimize(WANTvalue | WANTinterpret);
tomas@758 280 if (exp->op != TOKstring)
tomas@758 281 { error("argument to mixin must be a string, not (%s)", exp->toChars());
tomas@758 282 return NULL;
tomas@758 283 }
tomas@758 284 StringExp *se = (StringExp *)exp;
tomas@758 285 se = se->toUTF8(sc);
tomas@758 286 Parser p(sc->module, (unsigned char *)se->string, se->len, 0);
tomas@758 287 p.loc = loc;
tomas@758 288 p.nextToken();
tomas@758 289
tomas@758 290 Statements *a = new Statements();
tomas@758 291 while (p.token.value != TOKeof)
tomas@758 292 {
tomas@758 293 Statement *s = p.parseStatement(PSsemi | PScurlyscope);
tomas@758 294 a->push(s);
tomas@758 295 }
tomas@758 296 return a;
tomas@758 297 }
tomas@758 298
tomas@758 299 Statement *CompileStatement::semantic(Scope *sc)
tomas@758 300 {
tomas@758 301 //printf("CompileStatement::semantic() %s\n", exp->toChars());
tomas@758 302 Statements *a = flatten(sc);
tomas@758 303 if (!a)
tomas@758 304 return NULL;
tomas@758 305 Statement *s = new CompoundStatement(loc, a);
tomas@758 306 return s->semantic(sc);
tomas@758 307 }
tomas@758 308
tomas@758 309
tomas@758 310 /******************************** DeclarationStatement ***************************/
tomas@758 311
tomas@758 312 DeclarationStatement::DeclarationStatement(Loc loc, Dsymbol *declaration)
tomas@758 313 : ExpStatement(loc, new DeclarationExp(loc, declaration))
tomas@758 314 {
tomas@758 315 }
tomas@758 316
tomas@758 317 DeclarationStatement::DeclarationStatement(Loc loc, Expression *exp)
tomas@758 318 : ExpStatement(loc, exp)
tomas@758 319 {
tomas@758 320 }
tomas@758 321
tomas@758 322 Statement *DeclarationStatement::syntaxCopy()
tomas@758 323 {
tomas@758 324 DeclarationStatement *ds = new DeclarationStatement(loc, exp->syntaxCopy());
tomas@758 325 return ds;
tomas@758 326 }
tomas@758 327
tomas@758 328 void DeclarationStatement::scopeCode(Scope *sc, Statement **sentry, Statement **sexception, Statement **sfinally)
tomas@758 329 {
tomas@758 330 //printf("DeclarationStatement::scopeCode()\n");
tomas@758 331 //print();
tomas@758 332
tomas@758 333 *sentry = NULL;
tomas@758 334 *sexception = NULL;
tomas@758 335 *sfinally = NULL;
tomas@758 336
tomas@758 337 if (exp)
tomas@758 338 {
tomas@758 339 if (exp->op == TOKdeclaration)
tomas@758 340 {
tomas@758 341 DeclarationExp *de = (DeclarationExp *)(exp);
tomas@758 342 VarDeclaration *v = de->declaration->isVarDeclaration();
tomas@758 343 if (v)
tomas@758 344 { Expression *e;
tomas@758 345
tomas@758 346 e = v->callAutoDtor(sc);
tomas@758 347 if (e)
tomas@758 348 {
tomas@758 349 //printf("dtor is: "); e->print();
tomas@758 350 *sfinally = new ExpStatement(loc, e);
tomas@758 351 }
tomas@758 352 }
tomas@758 353 }
tomas@758 354 }
tomas@758 355 }
tomas@758 356
tomas@758 357 void DeclarationStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
tomas@758 358 {
tomas@758 359 exp->toCBuffer(buf, hgs);
tomas@758 360 }
tomas@758 361
tomas@758 362
tomas@758 363 /******************************** CompoundStatement ***************************/
tomas@758 364
tomas@758 365 CompoundStatement::CompoundStatement(Loc loc, Statements *s)
tomas@758 366 : Statement(loc)
tomas@758 367 {
tomas@758 368 statements = s;
tomas@758 369 }
tomas@758 370
tomas@758 371 CompoundStatement::CompoundStatement(Loc loc, Statement *s1, Statement *s2)
tomas@758 372 : Statement(loc)
tomas@758 373 {
tomas@758 374 statements = new Statements();
tomas@758 375 statements->reserve(2);
tomas@758 376 statements->push(s1);
tomas@758 377 statements->push(s2);
tomas@758 378 }
tomas@758 379
tomas@758 380 Statement *CompoundStatement::syntaxCopy()
tomas@758 381 {
tomas@758 382 Statements *a = new Statements();
tomas@758 383 a->setDim(statements->dim);
tomas@758 384 for (size_t i = 0; i < statements->dim; i++)
tomas@758 385 { Statement *s = (Statement *)statements->data[i];
tomas@758 386 if (s)
tomas@758 387 s = s->syntaxCopy();
tomas@758 388 a->data[i] = s;
tomas@758 389 }
tomas@758 390 CompoundStatement *cs = new CompoundStatement(loc, a);
tomas@758 391 return cs;
tomas@758 392 }
tomas@758 393
tomas@758 394
tomas@758 395 Statement *CompoundStatement::semantic(Scope *sc)
tomas@758 396 { Statement *s;
tomas@758 397
tomas@758 398 //printf("CompoundStatement::semantic(this = %p, sc = %p)\n", this, sc);
tomas@758 399
tomas@758 400 for (size_t i = 0; i < statements->dim; )
tomas@758 401 {
tomas@758 402 s = (Statement *) statements->data[i];
tomas@758 403 if (s)
tomas@758 404 { Statements *a = s->flatten(sc);
tomas@758 405
tomas@758 406 if (a)
tomas@758 407 {
tomas@758 408 statements->remove(i);
tomas@758 409 statements->insert(i, a);
tomas@758 410 continue;
tomas@758 411 }
tomas@758 412 s = s->semantic(sc);
tomas@758 413 statements->data[i] = s;
tomas@758 414 if (s)
tomas@758 415 {
tomas@758 416 Statement *sentry;
tomas@758 417 Statement *sexception;
tomas@758 418 Statement *sfinally;
tomas@758 419
tomas@758 420 s->scopeCode(sc, &sentry, &sexception, &sfinally);
tomas@758 421 if (sentry)
tomas@758 422 {
tomas@758 423 sentry = sentry->semantic(sc);
tomas@758 424 statements->data[i] = sentry;
tomas@758 425 }
tomas@758 426 if (sexception)
tomas@758 427 {
tomas@758 428 if (i + 1 == statements->dim && !sfinally)
tomas@758 429 {
tomas@758 430 #if 1
tomas@758 431 sexception = sexception->semantic(sc);
tomas@758 432 #else
tomas@758 433 statements->push(sexception);
tomas@758 434 if (sfinally)
tomas@758 435 // Assume sexception does not throw
tomas@758 436 statements->push(sfinally);
tomas@758 437 #endif
tomas@758 438 }
tomas@758 439 else
tomas@758 440 {
tomas@758 441 /* Rewrite:
tomas@758 442 * s; s1; s2;
tomas@758 443 * As:
tomas@758 444 * s;
tomas@758 445 * try { s1; s2; }
tomas@758 446 * catch (Object __o)
tomas@758 447 * { sexception; throw __o; }
tomas@758 448 */
tomas@758 449 Statement *body;
tomas@758 450 Statements *a = new Statements();
tomas@758 451
tomas@758 452 for (int j = i + 1; j < statements->dim; j++)
tomas@758 453 {
tomas@758 454 a->push(statements->data[j]);
tomas@758 455 }
tomas@758 456 body = new CompoundStatement(0, a);
tomas@758 457 body = new ScopeStatement(0, body);
tomas@758 458
tomas@758 459 Identifier *id = Lexer::uniqueId("__o");
tomas@758 460
tomas@758 461 Statement *handler = new ThrowStatement(0, new IdentifierExp(0, id));
tomas@758 462 handler = new CompoundStatement(0, sexception, handler);
tomas@758 463
tomas@758 464 Array *catches = new Array();
tomas@758 465 Catch *ctch = new Catch(0, NULL, id, handler);
tomas@758 466 catches->push(ctch);
tomas@758 467 s = new TryCatchStatement(0, body, catches);
tomas@758 468
tomas@758 469 if (sfinally)
tomas@758 470 s = new TryFinallyStatement(0, s, sfinally);
tomas@758 471 s = s->semantic(sc);
tomas@758 472 statements->setDim(i + 1);
tomas@758 473 statements->push(s);
tomas@758 474 break;
tomas@758 475 }
tomas@758 476 }
tomas@758 477 else if (sfinally)
tomas@758 478 {
tomas@758 479 if (0 && i + 1 == statements->dim)
tomas@758 480 {
tomas@758 481 statements->push(sfinally);
tomas@758 482 }
tomas@758 483 else
tomas@758 484 {
tomas@758 485 /* Rewrite:
tomas@758 486 * s; s1; s2;
tomas@758 487 * As:
tomas@758 488 * s; try { s1; s2; } finally { sfinally; }
tomas@758 489 */
tomas@758 490 Statement *body;
tomas@758 491 Statements *a = new Statements();
tomas@758 492
tomas@758 493 for (int j = i + 1; j < statements->dim; j++)
tomas@758 494 {
tomas@758 495 a->push(statements->data[j]);
tomas@758 496 }
tomas@758 497 body = new CompoundStatement(0, a);
tomas@758 498 s = new TryFinallyStatement(0, body, sfinally);
tomas@758 499 s = s->semantic(sc);
tomas@758 500 statements->setDim(i + 1);
tomas@758 501 statements->push(s);
tomas@758 502 break;
tomas@758 503 }
tomas@758 504 }
tomas@758 505 }
tomas@758 506 }
tomas@758 507 i++;
tomas@758 508 }
tomas@758 509 if (statements->dim == 1 && !isAsmBlockStatement())
tomas@758 510 {
tomas@758 511 return (Statement *)statements->data[0];
tomas@758 512 }
tomas@758 513 return this;
tomas@758 514 }
tomas@758 515
tomas@758 516 Statements *CompoundStatement::flatten(Scope *sc)
tomas@758 517 {
tomas@758 518 return statements;
tomas@758 519 }
tomas@758 520
tomas@758 521 ReturnStatement *CompoundStatement::isReturnStatement()
tomas@758 522 {
tomas@758 523 ReturnStatement *rs = NULL;
tomas@758 524
tomas@758 525 for (int i = 0; i < statements->dim; i++)
tomas@758 526 { Statement *s = (Statement *) statements->data[i];
tomas@758 527 if (s)
tomas@758 528 {
tomas@758 529 rs = s->isReturnStatement();
tomas@758 530 if (rs)
tomas@758 531 break;
tomas@758 532 }
tomas@758 533 }
tomas@758 534 return rs;
tomas@758 535 }
tomas@758 536
tomas@758 537 void CompoundStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
tomas@758 538 {
tomas@758 539 for (int i = 0; i < statements->dim; i++)
tomas@758 540 { Statement *s = (Statement *) statements->data[i];
tomas@758 541 if (s)
tomas@758 542 s->toCBuffer(buf, hgs);
tomas@758 543 }
tomas@758 544 }
tomas@758 545
tomas@758 546 int CompoundStatement::usesEH()
tomas@758 547 {
tomas@758 548 for (int i = 0; i < statements->dim; i++)
tomas@758 549 { Statement *s = (Statement *) statements->data[i];
tomas@758 550 if (s && s->usesEH())
tomas@758 551 return TRUE;
tomas@758 552 }
tomas@758 553 return FALSE;
tomas@758 554 }
tomas@758 555
tomas@758 556 int CompoundStatement::blockExit()
tomas@758 557 {
tomas@758 558 //printf("CompoundStatement::blockExit(%p) %d\n", this, statements->dim);
tomas@758 559 int result = BEfallthru;
tomas@758 560 for (size_t i = 0; i < statements->dim; i++)
tomas@758 561 { Statement *s = (Statement *) statements->data[i];
tomas@758 562 if (s)
tomas@758 563 {
tomas@758 564 //printf("result = x%x\n", result);
tomas@758 565 //printf("%s\n", s->toChars());
tomas@758 566 if (!(result & BEfallthru) && !s->comeFrom())
tomas@758 567 {
tomas@758 568 if (global.params.warnings)
tomas@758 569 { fprintf(stdmsg, "warning - ");
tomas@758 570 s->error("statement is not reachable");
tomas@758 571 }
tomas@758 572 }
tomas@758 573
tomas@758 574 result &= ~BEfallthru;
tomas@758 575 result |= s->blockExit();
tomas@758 576 }
tomas@758 577 }
tomas@758 578 return result;
tomas@758 579 }
tomas@758 580
tomas@758 581 int CompoundStatement::fallOffEnd()
tomas@758 582 { int falloff = TRUE;
tomas@758 583
tomas@758 584 //printf("CompoundStatement::fallOffEnd() %s\n", toChars());
tomas@758 585 for (int i = 0; i < statements->dim; i++)
tomas@758 586 { Statement *s = (Statement *)statements->data[i];
tomas@758 587
tomas@758 588 if (!s)
tomas@758 589 continue;
tomas@758 590
tomas@758 591 #if 0
tomas@758 592 if (!falloff && global.params.warnings && !s->comeFrom())
tomas@758 593 {
tomas@758 594 warning("%s: statement is not reachable", s->loc.toChars());
tomas@758 595 }
tomas@758 596 #endif
tomas@758 597 falloff = s->fallOffEnd();
tomas@758 598 }
tomas@758 599 return falloff;
tomas@758 600 }
tomas@758 601
tomas@758 602 int CompoundStatement::comeFrom()
tomas@758 603 { int comefrom = FALSE;
tomas@758 604
tomas@758 605 //printf("CompoundStatement::comeFrom()\n");
tomas@758 606 for (int i = 0; i < statements->dim; i++)
tomas@758 607 { Statement *s = (Statement *)statements->data[i];
tomas@758 608
tomas@758 609 if (!s)
tomas@758 610 continue;
tomas@758 611
tomas@758 612 comefrom |= s->comeFrom();
tomas@758 613 }
tomas@758 614 return comefrom;
tomas@758 615 }
tomas@758 616
tomas@758 617
tomas@758 618 /**************************** UnrolledLoopStatement ***************************/
tomas@758 619
tomas@758 620 UnrolledLoopStatement::UnrolledLoopStatement(Loc loc, Statements *s)
tomas@758 621 : Statement(loc)
tomas@758 622 {
tomas@758 623 statements = s;
tomas@758 624 enclosinghandler = NULL;
tomas@758 625 }
tomas@758 626
tomas@758 627 Statement *UnrolledLoopStatement::syntaxCopy()
tomas@758 628 {
tomas@758 629 Statements *a = new Statements();
tomas@758 630 a->setDim(statements->dim);
tomas@758 631 for (size_t i = 0; i < statements->dim; i++)
tomas@758 632 { Statement *s = (Statement *)statements->data[i];
tomas@758 633 if (s)
tomas@758 634 s = s->syntaxCopy();
tomas@758 635 a->data[i] = s;
tomas@758 636 }
tomas@758 637 UnrolledLoopStatement *cs = new UnrolledLoopStatement(loc, a);
tomas@758 638 return cs;
tomas@758 639 }
tomas@758 640
tomas@758 641
tomas@758 642 Statement *UnrolledLoopStatement::semantic(Scope *sc)
tomas@758 643 {
tomas@758 644 //printf("UnrolledLoopStatement::semantic(this = %p, sc = %p)\n", this, sc);
tomas@758 645
tomas@758 646 enclosinghandler = sc->tfOfTry;
tomas@758 647
tomas@758 648 sc->noctor++;
tomas@758 649 Scope *scd = sc->push();
tomas@758 650 scd->sbreak = this;
tomas@758 651 scd->scontinue = this;
tomas@758 652
tomas@758 653 for (size_t i = 0; i < statements->dim; i++)
tomas@758 654 {
tomas@758 655 Statement *s = (Statement *) statements->data[i];
tomas@758 656 if (s)
tomas@758 657 {
tomas@758 658 s = s->semantic(scd);
tomas@758 659 statements->data[i] = s;
tomas@758 660 }
tomas@758 661 }
tomas@758 662
tomas@758 663 scd->pop();
tomas@758 664 sc->noctor--;
tomas@758 665 return this;
tomas@758 666 }
tomas@758 667
tomas@758 668 void UnrolledLoopStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
tomas@758 669 {
tomas@758 670 buf->writestring("unrolled {");
tomas@758 671 buf->writenl();
tomas@758 672
tomas@758 673 for (size_t i = 0; i < statements->dim; i++)
tomas@758 674 { Statement *s;
tomas@758 675
tomas@758 676 s = (Statement *) statements->data[i];
tomas@758 677 if (s)
tomas@758 678 s->toCBuffer(buf, hgs);
tomas@758 679 }
tomas@758 680
tomas@758 681 buf->writeByte('}');
tomas@758 682 buf->writenl();
tomas@758 683 }
tomas@758 684
tomas@758 685 int UnrolledLoopStatement::hasBreak()
tomas@758 686 {
tomas@758 687 return TRUE;
tomas@758 688 }
tomas@758 689
tomas@758 690 int UnrolledLoopStatement::hasContinue()
tomas@758 691 {
tomas@758 692 return TRUE;
tomas@758 693 }
tomas@758 694
tomas@758 695 int UnrolledLoopStatement::usesEH()
tomas@758 696 {
tomas@758 697 for (size_t i = 0; i < statements->dim; i++)
tomas@758 698 { Statement *s = (Statement *) statements->data[i];
tomas@758 699 if (s && s->usesEH())
tomas@758 700 return TRUE;
tomas@758 701 }
tomas@758 702 return FALSE;
tomas@758 703 }
tomas@758 704
tomas@758 705 int UnrolledLoopStatement::blockExit()
tomas@758 706 {
tomas@758 707 int result = BEfallthru;
tomas@758 708 for (size_t i = 0; i < statements->dim; i++)
tomas@758 709 { Statement *s = (Statement *) statements->data[i];
tomas@758 710 if (s)
tomas@758 711 {
tomas@758 712 int r = s->blockExit();
tomas@758 713 result |= r & ~(BEbreak | BEcontinue);
tomas@758 714 }
tomas@758 715 }
tomas@758 716 return result;
tomas@758 717 }
tomas@758 718
tomas@758 719 int UnrolledLoopStatement::fallOffEnd()
tomas@758 720 {
tomas@758 721 //printf("UnrolledLoopStatement::fallOffEnd()\n");
tomas@758 722 for (size_t i = 0; i < statements->dim; i++)
tomas@758 723 { Statement *s = (Statement *)statements->data[i];
tomas@758 724
tomas@758 725 if (s)
tomas@758 726 s->fallOffEnd();
tomas@758 727 }
tomas@758 728 return TRUE;
tomas@758 729 }
tomas@758 730
tomas@758 731 int UnrolledLoopStatement::comeFrom()
tomas@758 732 { int comefrom = FALSE;
tomas@758 733
tomas@758 734 //printf("UnrolledLoopStatement::comeFrom()\n");
tomas@758 735 for (size_t i = 0; i < statements->dim; i++)
tomas@758 736 { Statement *s = (Statement *)statements->data[i];
tomas@758 737
tomas@758 738 if (!s)
tomas@758 739 continue;
tomas@758 740
tomas@758 741 comefrom |= s->comeFrom();
tomas@758 742 }
tomas@758 743 return comefrom;
tomas@758 744 }
tomas@758 745
tomas@758 746
tomas@758 747 /******************************** ScopeStatement ***************************/
tomas@758 748
tomas@758 749 ScopeStatement::ScopeStatement(Loc loc, Statement *s)
tomas@758 750 : Statement(loc)
tomas@758 751 {
tomas@758 752 this->statement = s;
tomas@758 753 }
tomas@758 754
tomas@758 755 Statement *ScopeStatement::syntaxCopy()
tomas@758 756 {
tomas@758 757 Statement *s;
tomas@758 758
tomas@758 759 s = statement ? statement->syntaxCopy() : NULL;
tomas@758 760 s = new ScopeStatement(loc, s);
tomas@758 761 return s;
tomas@758 762 }
tomas@758 763
tomas@758 764
tomas@758 765 Statement *ScopeStatement::semantic(Scope *sc)
tomas@758 766 { ScopeDsymbol *sym;
tomas@758 767
tomas@758 768 //printf("ScopeStatement::semantic(sc = %p)\n", sc);
tomas@758 769 if (statement)
tomas@758 770 { Statements *a;
tomas@758 771
tomas@758 772 sym = new ScopeDsymbol();
tomas@758 773 sym->parent = sc->scopesym;
tomas@758 774 sc = sc->push(sym);
tomas@758 775
tomas@758 776 a = statement->flatten(sc);
tomas@758 777 if (a)
tomas@758 778 {
tomas@758 779 statement = new CompoundStatement(loc, a);
tomas@758 780 }
tomas@758 781
tomas@758 782 statement = statement->semantic(sc);
tomas@758 783 if (statement)
tomas@758 784 {
tomas@758 785 Statement *sentry;
tomas@758 786 Statement *sexception;
tomas@758 787 Statement *sfinally;
tomas@758 788
tomas@758 789 statement->scopeCode(sc, &sentry, &sexception, &sfinally);
tomas@758 790 if (sfinally)
tomas@758 791 {
tomas@758 792 //printf("adding sfinally\n");
tomas@758 793 statement = new CompoundStatement(loc, statement, sfinally);
tomas@758 794 }
tomas@758 795 }
tomas@758 796
tomas@758 797 sc->pop();
tomas@758 798 }
tomas@758 799 return this;
tomas@758 800 }
tomas@758 801
tomas@758 802 int ScopeStatement::hasBreak()
tomas@758 803 {
tomas@758 804 //printf("ScopeStatement::hasBreak() %s\n", toChars());
tomas@758 805 return statement ? statement->hasBreak() : FALSE;
tomas@758 806 }
tomas@758 807
tomas@758 808 int ScopeStatement::hasContinue()
tomas@758 809 {
tomas@758 810 return statement ? statement->hasContinue() : FALSE;
tomas@758 811 }
tomas@758 812
tomas@758 813 int ScopeStatement::usesEH()
tomas@758 814 {
tomas@758 815 return statement ? statement->usesEH() : FALSE;
tomas@758 816 }
tomas@758 817
tomas@758 818 int ScopeStatement::blockExit()
tomas@758 819 {
tomas@758 820 //printf("ScopeStatement::blockExit(%p)\n", statement);
tomas@758 821 return statement ? statement->blockExit() : BEfallthru;
tomas@758 822 }
tomas@758 823
tomas@758 824 int ScopeStatement::fallOffEnd()
tomas@758 825 {
tomas@758 826 return statement ? statement->fallOffEnd() : TRUE;
tomas@758 827 }
tomas@758 828
tomas@758 829 int ScopeStatement::comeFrom()
tomas@758 830 {
tomas@758 831 //printf("ScopeStatement::comeFrom()\n");
tomas@758 832 return statement ? statement->comeFrom() : FALSE;
tomas@758 833 }
tomas@758 834
tomas@758 835 void ScopeStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
tomas@758 836 {
tomas@758 837 buf->writeByte('{');
tomas@758 838 buf->writenl();
tomas@758 839
tomas@758 840 if (statement)
tomas@758 841 statement->toCBuffer(buf, hgs);
tomas@758 842
tomas@758 843 buf->writeByte('}');
tomas@758 844 buf->writenl();
tomas@758 845 }
tomas@758 846
tomas@758 847 /******************************** WhileStatement ***************************/
tomas@758 848
tomas@758 849 WhileStatement::WhileStatement(Loc loc, Expression *c, Statement *b)
tomas@758 850 : Statement(loc)
tomas@758 851 {
tomas@758 852 condition = c;
tomas@758 853 body = b;
tomas@758 854 enclosinghandler = NULL;
tomas@758 855 }
tomas@758 856
tomas@758 857 Statement *WhileStatement::syntaxCopy()
tomas@758 858 {
tomas@758 859 WhileStatement *s = new WhileStatement(loc, condition->syntaxCopy(), body ? body->syntaxCopy() : NULL);
tomas@758 860 return s;
tomas@758 861 }
tomas@758 862
tomas@758 863
tomas@758 864 Statement *WhileStatement::semantic(Scope *sc)
tomas@758 865 {
tomas@758 866 #if 0
tomas@758 867 if (condition->op == TOKmatch)
tomas@758 868 {
tomas@758 869 /* Rewrite while (condition) body as:
tomas@758 870 * if (condition)
tomas@758 871 * do
tomas@758 872 * body
tomas@758 873 * while ((_match = _match.opNext), _match);
tomas@758 874 */
tomas@758 875
tomas@758 876 Expression *ew = new IdentifierExp(0, Id::_match);
tomas@758 877 ew = new DotIdExp(0, ew, Id::next);
tomas@758 878 ew = new AssignExp(0, new IdentifierExp(0, Id::_match), ew);
tomas@758 879 ////ew = new EqualExp(TOKnotequal, 0, ew, new NullExp(0));
tomas@758 880 Expression *ev = new IdentifierExp(0, Id::_match);
tomas@758 881 //ev = new CastExp(0, ev, Type::tvoidptr);
tomas@758 882 ew = new CommaExp(0, ew, ev);
tomas@758 883 Statement *sw = new DoStatement(loc, body, ew);
tomas@758 884 Statement *si = new IfStatement(loc, condition, sw, NULL);
tomas@758 885 return si->semantic(sc);
tomas@758 886 }
tomas@758 887 #endif
tomas@758 888
tomas@758 889 enclosinghandler = sc->tfOfTry;
tomas@758 890
tomas@758 891 condition = condition->semantic(sc);
tomas@758 892 condition = resolveProperties(sc, condition);
tomas@758 893 condition = condition->optimize(WANTvalue);
tomas@758 894 condition = condition->checkToBoolean();
tomas@758 895
tomas@758 896 sc->noctor++;
tomas@758 897
tomas@758 898 Scope *scd = sc->push();
tomas@758 899 scd->sbreak = this;
tomas@758 900 scd->scontinue = this;
tomas@758 901 if (body)
tomas@758 902 body = body->semantic(scd);
tomas@758 903 scd->pop();
tomas@758 904
tomas@758 905 sc->noctor--;
tomas@758 906
tomas@758 907 return this;
tomas@758 908 }
tomas@758 909
tomas@758 910 int WhileStatement::hasBreak()
tomas@758 911 {
tomas@758 912 return TRUE;
tomas@758 913 }
tomas@758 914
tomas@758 915 int WhileStatement::hasContinue()
tomas@758 916 {
tomas@758 917 return TRUE;
tomas@758 918 }
tomas@758 919
tomas@758 920 int WhileStatement::usesEH()
tomas@758 921 {
tomas@758 922 return body ? body->usesEH() : 0;
tomas@758 923 }
tomas@758 924
tomas@758 925 int WhileStatement::blockExit()
tomas@758 926 {
tomas@758 927 //printf("WhileStatement::blockExit(%p)\n", this);
tomas@758 928
tomas@758 929 int result = BEnone;
tomas@758 930 if (condition->canThrow())
tomas@758 931 result |= BEthrow;
tomas@758 932 if (condition->isBool(TRUE))
tomas@758 933 {
tomas@758 934 if (body)
tomas@758 935 { result |= body->blockExit();
tomas@758 936 if (result & BEbreak)
tomas@758 937 result |= BEfallthru;
tomas@758 938 }
tomas@758 939 }
tomas@758 940 else if (condition->isBool(FALSE))
tomas@758 941 {
tomas@758 942 result |= BEfallthru;
tomas@758 943 }
tomas@758 944 else
tomas@758 945 {
tomas@758 946 if (body)
tomas@758 947 result |= body->blockExit();
tomas@758 948 result |= BEfallthru;
tomas@758 949 }
tomas@758 950 result &= ~(BEbreak | BEcontinue);
tomas@758 951 return result;
tomas@758 952 }
tomas@758 953
tomas@758 954 int WhileStatement::fallOffEnd()
tomas@758 955 {
tomas@758 956 if (body)
tomas@758 957 body->fallOffEnd();
tomas@758 958 return TRUE;
tomas@758 959 }
tomas@758 960
tomas@758 961 int WhileStatement::comeFrom()
tomas@758 962 {
tomas@758 963 if (body)
tomas@758 964 return body->comeFrom();
tomas@758 965 return FALSE;
tomas@758 966 }
tomas@758 967
tomas@758 968 void WhileStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
tomas@758 969 {
tomas@758 970 buf->writestring("while (");
tomas@758 971 condition->toCBuffer(buf, hgs);
tomas@758 972 buf->writebyte(')');
tomas@758 973 buf->writenl();
tomas@758 974 if (body)
tomas@758 975 body->toCBuffer(buf, hgs);
tomas@758 976 }
tomas@758 977
tomas@758 978 /******************************** DoStatement ***************************/
tomas@758 979
tomas@758 980 DoStatement::DoStatement(Loc loc, Statement *b, Expression *c)
tomas@758 981 : Statement(loc)
tomas@758 982 {
tomas@758 983 body = b;
tomas@758 984 condition = c;
tomas@758 985 enclosinghandler = NULL;
tomas@758 986 }
tomas@758 987
tomas@758 988 Statement *DoStatement::syntaxCopy()
tomas@758 989 {
tomas@758 990 DoStatement *s = new DoStatement(loc, body ? body->syntaxCopy() : NULL, condition->syntaxCopy());
tomas@758 991 return s;
tomas@758 992 }
tomas@758 993
tomas@758 994
tomas@758 995 Statement *DoStatement::semantic(Scope *sc)
tomas@758 996 {
tomas@758 997 enclosinghandler = sc->tfOfTry;
tomas@758 998
tomas@758 999 sc->noctor++;
tomas@758 1000 if (body)
tomas@758 1001 body = body->semanticScope(sc, this, this);
tomas@758 1002 sc->noctor--;
tomas@758 1003 condition = condition->semantic(sc);
tomas@758 1004 condition = resolveProperties(sc, condition);
tomas@758 1005 condition = condition->optimize(WANTvalue);
tomas@758 1006
tomas@758 1007 condition = condition->checkToBoolean();
tomas@758 1008
tomas@758 1009 return this;
tomas@758 1010 }
tomas@758 1011
tomas@758 1012 int DoStatement::hasBreak()
tomas@758 1013 {
tomas@758 1014 return TRUE;
tomas@758 1015 }
tomas@758 1016
tomas@758 1017 int DoStatement::hasContinue()
tomas@758 1018 {
tomas@758 1019 return TRUE;
tomas@758 1020 }
tomas@758 1021
tomas@758 1022 int DoStatement::usesEH()
tomas@758 1023 {
tomas@758 1024 return body ? body->usesEH() : 0;
tomas@758 1025 }
tomas@758 1026
tomas@758 1027 int DoStatement::blockExit()
tomas@758 1028 { int result;
tomas@758 1029
tomas@758 1030 if (body)
tomas@758 1031 { result = body->blockExit();
tomas@758 1032 if (result == BEbreak)
tomas@758 1033 return BEfallthru;
tomas@758 1034 if (result & BEcontinue)
tomas@758 1035 result |= BEfallthru;
tomas@758 1036 }
tomas@758 1037 else
tomas@758 1038 result = BEfallthru;
tomas@758 1039 if (result & BEfallthru)
tomas@758 1040 { if (condition->canThrow())
tomas@758 1041 result |= BEthrow;
tomas@758 1042 if (!(result & BEbreak) && condition->isBool(TRUE))
tomas@758 1043 result &= ~BEfallthru;
tomas@758 1044 }
tomas@758 1045 result &= ~(BEbreak | BEcontinue);
tomas@758 1046 return result;
tomas@758 1047 }
tomas@758 1048
tomas@758 1049 int DoStatement::fallOffEnd()
tomas@758 1050 {
tomas@758 1051 if (body)
tomas@758 1052 body->fallOffEnd();
tomas@758 1053 return TRUE;
tomas@758 1054 }
tomas@758 1055
tomas@758 1056 int DoStatement::comeFrom()
tomas@758 1057 {
tomas@758 1058 if (body)
tomas@758 1059 return body->comeFrom();
tomas@758 1060 return FALSE;
tomas@758 1061 }
tomas@758 1062
tomas@758 1063 void DoStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
tomas@758 1064 {
tomas@758 1065 buf->writestring("do");
tomas@758 1066 buf->writenl();
tomas@758 1067 if (body)
tomas@758 1068 body->toCBuffer(buf, hgs);
tomas@758 1069 buf->writestring("while (");
tomas@758 1070 condition->toCBuffer(buf, hgs);
tomas@758 1071 buf->writebyte(')');
tomas@758 1072 }
tomas@758 1073
tomas@758 1074 /******************************** ForStatement ***************************/
tomas@758 1075
tomas@758 1076 ForStatement::ForStatement(Loc loc, Statement *init, Expression *condition, Expression *increment, Statement *body)
tomas@758 1077 : Statement(loc)
tomas@758 1078 {
tomas@758 1079 this->init = init;
tomas@758 1080 this->condition = condition;
tomas@758 1081 this->increment = increment;
tomas@758 1082 this->body = body;
tomas@758 1083 this->enclosinghandler = NULL;
tomas@758 1084 }
tomas@758 1085
tomas@758 1086 Statement *ForStatement::syntaxCopy()
tomas@758 1087 {
tomas@758 1088 Statement *i = NULL;
tomas@758 1089 if (init)
tomas@758 1090 i = init->syntaxCopy();
tomas@758 1091 Expression *c = NULL;
tomas@758 1092 if (condition)
tomas@758 1093 c = condition->syntaxCopy();
tomas@758 1094 Expression *inc = NULL;
tomas@758 1095 if (increment)
tomas@758 1096 inc = increment->syntaxCopy();
tomas@758 1097 ForStatement *s = new ForStatement(loc, i, c, inc, body->syntaxCopy());
tomas@758 1098 return s;
tomas@758 1099 }
tomas@758 1100
tomas@758 1101 Statement *ForStatement::semantic(Scope *sc)
tomas@758 1102 {
tomas@758 1103 enclosinghandler = sc->tfOfTry;
tomas@758 1104
tomas@758 1105 ScopeDsymbol *sym = new ScopeDsymbol();
tomas@758 1106 sym->parent = sc->scopesym;
tomas@758 1107 sc = sc->push(sym);
tomas@758 1108 if (init)
tomas@758 1109 init = init->semantic(sc);
tomas@758 1110 sc->noctor++;
tomas@758 1111 if (condition)
tomas@758 1112 {
tomas@758 1113 condition = condition->semantic(sc);
tomas@758 1114 condition = resolveProperties(sc, condition);
tomas@758 1115 condition = condition->optimize(WANTvalue);
tomas@758 1116 condition = condition->checkToBoolean();
tomas@758 1117 }
tomas@758 1118 if (increment)
tomas@847 1119 { increment = increment->semantic(sc);
tomas@847 1120 increment = resolveProperties(sc, increment);
tomas@847 1121 }
tomas@758 1122
tomas@758 1123 sc->sbreak = this;
tomas@758 1124 sc->scontinue = this;
tomas@758 1125 body = body->semantic(sc);
tomas@758 1126 sc->noctor--;
tomas@758 1127
tomas@758 1128 sc->pop();
tomas@758 1129 return this;
tomas@758 1130 }
tomas@758 1131
tomas@758 1132 void ForStatement::scopeCode(Scope *sc, Statement **sentry, Statement **sexception, Statement **sfinally)
tomas@758 1133 {
tomas@758 1134 //printf("ForStatement::scopeCode()\n");
tomas@758 1135 //print();
tomas@758 1136 if (init)
tomas@758 1137 init->scopeCode(sc, sentry, sexception, sfinally);
tomas@758 1138 else
tomas@758 1139 Statement::scopeCode(sc, sentry, sexception, sfinally);
tomas@758 1140 }
tomas@758 1141
tomas@758 1142 int ForStatement::hasBreak()
tomas@758 1143 {
tomas@758 1144 //printf("ForStatement::hasBreak()\n");
tomas@758 1145 return TRUE;
tomas@758 1146 }
tomas@758 1147
tomas@758 1148 int ForStatement::hasContinue()
tomas@758 1149 {
tomas@758 1150 return TRUE;
tomas@758 1151 }
tomas@758 1152
tomas@758 1153 int ForStatement::usesEH()
tomas@758 1154 {
tomas@758 1155 return (init && init->usesEH()) || body->usesEH();
tomas@758 1156 }
tomas@758 1157
tomas@758 1158 int ForStatement::blockExit()
tomas@758 1159 { int result = BEfallthru;
tomas@758 1160
tomas@758 1161 if (init)
tomas@758 1162 { result = init->blockExit();
tomas@758 1163 if (!(result & BEfallthru))
tomas@758 1164 return result;
tomas@758 1165 }
tomas@758 1166 if (condition)
tomas@758 1167 { if (condition->canThrow())
tomas@758 1168 result |= BEthrow;
tomas@758 1169 }
tomas@758 1170 else
tomas@758 1171 result &= ~BEfallthru; // the body must do the exiting
tomas@758 1172 if (body)
tomas@758 1173 { int r = body->blockExit();
tomas@758 1174 if (r & BEbreak)
tomas@758 1175 result |= BEfallthru;
tomas@758 1176 result |= r & ~(BEbreak | BEcontinue);
tomas@758 1177 }
tomas@758 1178 if (increment && increment->canThrow())
tomas@758 1179 result |= BEthrow;
tomas@758 1180 return result;
tomas@758 1181 }
tomas@758 1182
tomas@758 1183 int ForStatement::fallOffEnd()
tomas@758 1184 {
tomas@758 1185 if (body)
tomas@758 1186 body->fallOffEnd();
tomas@758 1187 return TRUE;
tomas@758 1188 }
tomas@758 1189
tomas@758 1190 int ForStatement::comeFrom()
tomas@758 1191 {
tomas@758 1192 //printf("ForStatement::comeFrom()\n");
tomas@758 1193 if (body)
tomas@758 1194 { int result = body->comeFrom();
tomas@758 1195 //printf("result = %d\n", result);
tomas@758 1196 return result;
tomas@758 1197 }
tomas@758 1198 return FALSE;
tomas@758 1199 }
tomas@758 1200
tomas@758 1201 void ForStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
tomas@758 1202 {
tomas@758 1203 buf->writestring("for (");
tomas@758 1204 if (init)
tomas@758 1205 {
tomas@758 1206 hgs->FLinit.init++;
tomas@758 1207 hgs->FLinit.decl = 0;
tomas@758 1208 init->toCBuffer(buf, hgs);
tomas@758 1209 if (hgs->FLinit.decl > 0)
tomas@758 1210 buf->writebyte(';');
tomas@758 1211 hgs->FLinit.decl = 0;
tomas@758 1212 hgs->FLinit.init--;
tomas@758 1213 }
tomas@758 1214 else
tomas@758 1215 buf->writebyte(';');
tomas@758 1216 if (condition)
tomas@758 1217 { buf->writebyte(' ');
tomas@758 1218 condition->toCBuffer(buf, hgs);
tomas@758 1219 }
tomas@758 1220 buf->writebyte(';');
tomas@758 1221 if (increment)
tomas@758 1222 { buf->writebyte(' ');
tomas@758 1223 increment->toCBuffer(buf, hgs);
tomas@758 1224 }
tomas@758 1225 buf->writebyte(')');
tomas@758 1226 buf->writenl();
tomas@758 1227 buf->writebyte('{');
tomas@758 1228 buf->writenl();
tomas@758 1229 body->toCBuffer(buf, hgs);
tomas@758 1230 buf->writebyte('}');
tomas@758 1231 buf->writenl();
tomas@758 1232 }
tomas@758 1233
tomas@758 1234 /******************************** ForeachStatement ***************************/
tomas@758 1235
tomas@758 1236 ForeachStatement::ForeachStatement(Loc loc, enum TOK op, Arguments *arguments,
tomas@758 1237 Expression *aggr, Statement *body)
tomas@758 1238 : Statement(loc)
tomas@758 1239 {
tomas@758 1240 this->op = op;
tomas@758 1241 this->arguments = arguments;
tomas@758 1242 this->aggr = aggr;
tomas@758 1243 this->body = body;
tomas@758 1244 this->enclosinghandler = NULL;
tomas@758 1245
tomas@758 1246 this->key = NULL;
tomas@758 1247 this->value = NULL;
tomas@758 1248
tomas@758 1249 this->func = NULL;
tomas@758 1250 }
tomas@758 1251
tomas@758 1252 Statement *ForeachStatement::syntaxCopy()
tomas@758 1253 {
tomas@758 1254 Arguments *args = Argument::arraySyntaxCopy(arguments);
tomas@758 1255 Expression *exp = aggr->syntaxCopy();
tomas@758 1256 ForeachStatement *s = new ForeachStatement(loc, op, args, exp,
tomas@758 1257 body ? body->syntaxCopy() : NULL);
tomas@758 1258 return s;
tomas@758 1259 }
tomas@758 1260
tomas@758 1261 Statement *ForeachStatement::semantic(Scope *sc)
tomas@758 1262 {
tomas@758 1263 //printf("ForeachStatement::semantic() %p\n", this);
tomas@758 1264 ScopeDsymbol *sym;
tomas@758 1265 Statement *s = this;
tomas@847 1266 size_t dim = arguments->dim;
tomas@758 1267 TypeAArray *taa = NULL;
tomas@758 1268
tomas@758 1269 Type *tn = NULL;
tomas@758 1270 Type *tnv = NULL;
tomas@758 1271
tomas@758 1272 enclosinghandler = sc->tfOfTry;
tomas@758 1273
tomas@758 1274 func = sc->func;
tomas@758 1275 if (func->fes)
tomas@758 1276 func = func->fes->func;
tomas@758 1277
tomas@758 1278 aggr = aggr->semantic(sc);
tomas@758 1279 aggr = resolveProperties(sc, aggr);
tomas@758 1280 aggr = aggr->optimize(WANTvalue);
tomas@758 1281 if (!aggr->type)
tomas@758 1282 {
tomas@758 1283 error("invalid foreach aggregate %s", aggr->toChars());
tomas@758 1284 return this;
tomas@758 1285 }
tomas@758 1286
tomas@758 1287 inferApplyArgTypes(op, arguments, aggr);
tomas@758 1288
tomas@758 1289 /* Check for inference errors
tomas@758 1290 */
tomas@758 1291 if (dim != arguments->dim)
tomas@758 1292 {
tomas@758 1293 //printf("dim = %d, arguments->dim = %d\n", dim, arguments->dim);
tomas@758 1294 error("cannot uniquely infer foreach argument types");
tomas@758 1295 return this;
tomas@758 1296 }
tomas@758 1297
tomas@758 1298 Type *tab = aggr->type->toBasetype();
tomas@758 1299
tomas@758 1300 if (tab->ty == Ttuple) // don't generate new scope for tuple loops
tomas@758 1301 {
tomas@758 1302 if (dim < 1 || dim > 2)
tomas@758 1303 {
tomas@758 1304 error("only one (value) or two (key,value) arguments for tuple foreach");
tomas@758 1305 return s;
tomas@758 1306 }
tomas@758 1307
tomas@758 1308 TypeTuple *tuple = (TypeTuple *)tab;
tomas@758 1309 Statements *statements = new Statements();
tomas@758 1310 //printf("aggr: op = %d, %s\n", aggr->op, aggr->toChars());
tomas@758 1311 size_t n;
tomas@758 1312 TupleExp *te = NULL;
tomas@758 1313 if (aggr->op == TOKtuple) // expression tuple
tomas@758 1314 { te = (TupleExp *)aggr;
tomas@758 1315 n = te->exps->dim;
tomas@758 1316 }
tomas@758 1317 else if (aggr->op == TOKtype) // type tuple
tomas@758 1318 {
tomas@758 1319 n = Argument::dim(tuple->arguments);
tomas@758 1320 }
tomas@758 1321 else
tomas@758 1322 assert(0);
tomas@758 1323 for (size_t j = 0; j < n; j++)
tomas@758 1324 { size_t k = (op == TOKforeach) ? j : n - 1 - j;
tomas@758 1325 Expression *e;
tomas@758 1326 Type *t;
tomas@758 1327 if (te)
tomas@758 1328 e = (Expression *)te->exps->data[k];
tomas@758 1329 else
tomas@758 1330 t = Argument::getNth(tuple->arguments, k)->type;
tomas@758 1331 Argument *arg = (Argument *)arguments->data[0];
tomas@758 1332 Statements *st = new Statements();
tomas@758 1333
tomas@758 1334 if (dim == 2)
tomas@758 1335 { // Declare key
tomas@758 1336 if (arg->storageClass & (STCout | STCref | STClazy))
tomas@758 1337 error("no storage class for key %s", arg->ident->toChars());
tomas@758 1338 TY keyty = arg->type->ty;
tomas@758 1339 if (global.params.is64bit)
tomas@758 1340 {
tomas@758 1341 if (keyty != Tint32 && keyty != Tuns32 && keyty != Tint64 && keyty != Tuns64)
tomas@758 1342 {
tomas@758 1343 error("foreach: key type must be int, uint, long or ulong, not %s", key->type->toChars());
tomas@758 1344 }
tomas@758 1345 }
tomas@758 1346 else if (keyty != Tint32 && keyty != Tuns32)
tomas@758 1347 {
tomas@758 1348 error("foreach: key type must be int or uint, not %s", key->type->toChars());
tomas@758 1349 }
tomas@758 1350 Initializer *ie = new ExpInitializer(0, new IntegerExp(k));
tomas@758 1351 VarDeclaration *var = new VarDeclaration(loc, arg->type, arg->ident, ie);
tomas@758 1352 var->storage_class |= STCmanifest;
tomas@758 1353 DeclarationExp *de = new DeclarationExp(loc, var);
tomas@758 1354 st->push(new ExpStatement(loc, de));
tomas@758 1355 arg = (Argument *)arguments->data[1]; // value
tomas@758 1356 }
tomas@758 1357 // Declare value
tomas@758 1358 if (arg->storageClass & (STCout | STCref | STClazy))
tomas@758 1359 error("no storage class for value %s", arg->ident->toChars());
tomas@758 1360 Dsymbol *var;
tomas@758 1361 if (te)
tomas@758 1362 { Type *tb = e->type->toBasetype();
tomas@758 1363 if ((tb->ty == Tfunction || tb->ty == Tsarray) && e->op == TOKvar)
tomas@758 1364 { VarExp *ve = (VarExp *)e;
tomas@758 1365 var = new AliasDeclaration(loc, arg->ident, ve->var);
tomas@758 1366 }
tomas@758 1367 else
tomas@758 1368 {
tomas@758 1369 arg->type = e->type;
tomas@758 1370 Initializer *ie = new ExpInitializer(0, e);
tomas@758 1371 VarDeclaration *v = new VarDeclaration(loc, arg->type, arg->ident, ie);
tomas@758 1372 if (e->isConst())
tomas@758 1373 v->storage_class |= STCconst;
tomas@758 1374 var = v;
tomas@758 1375 }
tomas@758 1376 }
tomas@758 1377 else
tomas@758 1378 {
tomas@758 1379 var = new AliasDeclaration(loc, arg->ident, t);
tomas@758 1380 }
tomas@758 1381 DeclarationExp *de = new DeclarationExp(loc, var);
tomas@758 1382 st->push(new ExpStatement(loc, de));
tomas@758 1383
tomas@758 1384 st->push(body->syntaxCopy());
tomas@758 1385 s = new CompoundStatement(loc, st);
tomas@758 1386 s = new ScopeStatement(loc, s);
tomas@758 1387 statements->push(s);
tomas@758 1388 }
tomas@758 1389
tomas@758 1390 s = new UnrolledLoopStatement(loc, statements);
tomas@758 1391 s = s->semantic(sc);
tomas@758 1392 return s;
tomas@758 1393 }
tomas@758 1394
tomas@758 1395 sym = new ScopeDsymbol();
tomas@758 1396 sym->parent = sc->scopesym;
tomas@758 1397 sc = sc->push(sym);
tomas@758 1398
tomas@758 1399 sc->noctor++;
tomas@758 1400
tomas@758 1401 switch (tab->ty)
tomas@758 1402 {
tomas@758 1403 case Tarray:
tomas@758 1404 case Tsarray:
tomas@847 1405 if (!checkForArgTypes())
tomas@847 1406 return this;
tomas@847 1407
tomas@758 1408 if (dim < 1 || dim > 2)
tomas@758 1409 {
tomas@758 1410 error("only one or two arguments for array foreach");
tomas@758 1411 break;
tomas@758 1412 }
tomas@758 1413
tomas@758 1414 /* Look for special case of parsing char types out of char type
tomas@758 1415 * array.
tomas@758 1416 */
tomas@758 1417 tn = tab->nextOf()->toBasetype();
tomas@758 1418 if (tn->ty == Tchar || tn->ty == Twchar || tn->ty == Tdchar)
tomas@758 1419 { Argument *arg;
tomas@758 1420
tomas@847 1421 int i = (dim == 1) ? 0 : 1; // index of value
tomas@758 1422 arg = (Argument *)arguments->data[i];
tomas@758 1423 arg->type = arg->type->semantic(loc, sc);
tomas@758 1424 tnv = arg->type->toBasetype();
tomas@758 1425 if (tnv->ty != tn->ty &&
tomas@758 1426 (tnv->ty == Tchar || tnv->ty == Twchar || tnv->ty == Tdchar))
tomas@758 1427 {
tomas@758 1428 if (arg->storageClass & STCref)
tomas@758 1429 error("foreach: value of UTF conversion cannot be ref");
tomas@758 1430 if (dim == 2)
tomas@758 1431 { arg = (Argument *)arguments->data[0];
tomas@758 1432 if (arg->storageClass & STCref)
tomas@758 1433 error("foreach: key cannot be ref");
tomas@758 1434 }
tomas@758 1435 goto Lapply;
tomas@758 1436 }
tomas@758 1437 }
tomas@758 1438
tomas@847 1439 for (size_t i = 0; i < dim; i++)
tomas@758 1440 { // Declare args
tomas@758 1441 Argument *arg = (Argument *)arguments->data[i];
tomas@758 1442 VarDeclaration *var;
tomas@758 1443
tomas@758 1444 var = new VarDeclaration(loc, arg->type, arg->ident, NULL);
tomas@758 1445 var->storage_class |= STCforeach;
tomas@758 1446 var->storage_class |= arg->storageClass & (STCin | STCout | STCref | STCconst | STCinvariant);
tomas@758 1447 if (dim == 2 && i == 0)
tomas@758 1448 { key = var;
tomas@758 1449 //var->storage_class |= STCfinal;
tomas@758 1450 }
tomas@758 1451 else
tomas@758 1452 {
tomas@758 1453 value = var;
tomas@758 1454 /* Reference to immutable data should be marked as const
tomas@758 1455 */
tomas@758 1456 if (var->storage_class & STCref && !tn->isMutable())
tomas@758 1457 {
tomas@758 1458 var->storage_class |= STCconst;
tomas@758 1459 }
tomas@758 1460 }
tomas@758 1461 #if 1
tomas@758 1462 DeclarationExp *de = new DeclarationExp(loc, var);
tomas@758 1463 de->semantic(sc);
tomas@758 1464 #else
tomas@758 1465 var->semantic(sc);
tomas@758 1466 if (!sc->insert(var))
tomas@758 1467 error("%s already defined", var->ident->toChars());
tomas@758 1468 #endif
tomas@758 1469 }
tomas@758 1470
tomas@758 1471 sc->sbreak = this;
tomas@758 1472 sc->scontinue = this;
tomas@758 1473 body = body->semantic(sc);
tomas@758 1474
tomas@758 1475 if (tab->nextOf()->implicitConvTo(value->type) < MATCHconst)
tomas@758 1476 {
tomas@758 1477 if (aggr->op == TOKstring)
tomas@758 1478 aggr = aggr->implicitCastTo(sc, value->type->arrayOf());
tomas@758 1479 else
tomas@758 1480 error("foreach: %s is not an array of %s",
tomas@758 1481 tab->toChars(), value->type->toChars());
tomas@758 1482 }
tomas@758 1483
tomas@758 1484 if (key)
tomas@758 1485 {
tomas@758 1486 if (global.params.is64bit)
tomas@758 1487 {
tomas@758 1488 if (key->type->ty != Tint32 && key->type->ty != Tuns32 && key->type->ty != Tint64 && key->type->ty != Tuns64)
tomas@758 1489 {
tomas@758 1490 error("foreach: key type must be int, uint, long or ulong, not %s", key->type->toChars());
tomas@758 1491 }
tomas@758 1492 }
tomas@758 1493 else if (key->type->ty != Tint32 && key->type->ty != Tuns32)
tomas@758 1494 {
tomas@758 1495 error("foreach: key type must be int or uint, not %s", key->type->toChars());
tomas@758 1496 }
tomas@758 1497 }
tomas@758 1498
tomas@758 1499 if (key && key->storage_class & (STCout | STCref))
tomas@758 1500 error("foreach: key cannot be out or ref");
tomas@758 1501 break;
tomas@758 1502
tomas@758 1503 case Taarray:
tomas@847 1504 if (!checkForArgTypes())
tomas@847 1505 return this;
tomas@847 1506
tomas@758 1507 taa = (TypeAArray *)tab;
tomas@758 1508 if (dim < 1 || dim > 2)
tomas@758 1509 {
tomas@758 1510 error("only one or two arguments for associative array foreach");
tomas@758 1511 break;
tomas@758 1512 }
tomas@758 1513 if (op == TOKforeach_reverse)
tomas@758 1514 {
tomas@758 1515 error("no reverse iteration on associative arrays");
tomas@758 1516 }
tomas@758 1517 goto Lapply;
tomas@758 1518
tomas@758 1519 case Tclass:
tomas@758 1520 case Tstruct:
tomas@847 1521 #if DMDV2
tomas@847 1522 { /* Look for range iteration, i.e. the properties
tomas@847 1523 * .empty, .next, .retreat, .head and .rear
tomas@847 1524 * foreach (e; range) { ... }
tomas@847 1525 * translates to:
tomas@847 1526 * for (auto __r = range; !__r.empty; __r.next)
tomas@847 1527 * { auto e = __r.head;
tomas@847 1528 * ...
tomas@847 1529 * }
tomas@847 1530 */
tomas@847 1531 if (dim != 1) // only one argument allowed with ranges
tomas@847 1532 goto Lapply;
tomas@847 1533 AggregateDeclaration *ad = (tab->ty == Tclass)
tomas@847 1534 ? (AggregateDeclaration *)((TypeClass *)tab)->sym
tomas@847 1535 : (AggregateDeclaration *)((TypeStruct *)tab)->sym;
tomas@847 1536 Identifier *idhead;
tomas@847 1537 Identifier *idnext;
tomas@847 1538 if (op == TOKforeach)
tomas@847 1539 { idhead = Id::Fhead;
tomas@847 1540 idnext = Id::Fnext;
tomas@847 1541 }
tomas@847 1542 else
tomas@847 1543 { idhead = Id::Ftoe;
tomas@847 1544 idnext = Id::Fretreat;
tomas@847 1545 }
tomas@847 1546 Dsymbol *shead = search_function(ad, idhead);
tomas@847 1547 if (!shead)
tomas@847 1548 goto Lapply;
tomas@847 1549
tomas@847 1550 /* Generate a temporary __r and initialize it with the aggregate.
tomas@847 1551 */
tomas@847 1552 Identifier *id = Identifier::generateId("__r");
tomas@847 1553 VarDeclaration *r = new VarDeclaration(loc, NULL, id, new ExpInitializer(loc, aggr));
tomas@847 1554 r->semantic(sc);
tomas@847 1555 Statement *init = new DeclarationStatement(loc, r);
tomas@847 1556
tomas@847 1557 // !__r.empty
tomas@847 1558 Expression *e = new VarExp(loc, r);
tomas@847 1559 e = new DotIdExp(loc, e, Id::Fempty);
tomas@847 1560 Expression *condition = new NotExp(loc, e);
tomas@847 1561
tomas@847 1562 // __r.next
tomas@847 1563 e = new VarExp(loc, r);
tomas@847 1564 Expression *increment = new DotIdExp(loc, e, idnext);
tomas@847 1565
tomas@847 1566 /* Declaration statement for e:
tomas@847 1567 * auto e = __r.idhead;
tomas@847 1568 */
tomas@847 1569 e = new VarExp(loc, r);
tomas@847 1570 Expression *einit = new DotIdExp(loc, e, idhead);
tomas@847 1571 einit = einit->semantic(sc);
tomas@847 1572 Argument *arg = (Argument *)arguments->data[0];
tomas@847 1573 VarDeclaration *ve = new VarDeclaration(loc, arg->type, arg->ident, new ExpInitializer(loc, einit));
tomas@847 1574 ve->storage_class |= STCforeach;
tomas@847 1575 ve->storage_class |= arg->storageClass & (STCin | STCout | STCref | STCconst | STCinvariant);
tomas@847 1576
tomas@847 1577 DeclarationExp *de = new DeclarationExp(loc, ve);
tomas@847 1578
tomas@847 1579 Statement *body = new CompoundStatement(loc,
tomas@847 1580 new DeclarationStatement(loc, de), this->body);
tomas@847 1581
tomas@847 1582 s = new ForStatement(loc, init, condition, increment, body);
tomas@847 1583 s = s->semantic(sc);
tomas@847 1584 break;
tomas@847 1585 }
tomas@847 1586 #endif
tomas@758 1587 case Tdelegate:
tomas@758 1588 Lapply:
tomas@758 1589 { FuncDeclaration *fdapply;
tomas@758 1590 Arguments *args;
tomas@758 1591 Expression *ec;
tomas@758 1592 Expression *e;
tomas@758 1593 FuncLiteralDeclaration *fld;
tomas@758 1594 Argument *a;
tomas@758 1595 Type *t;
tomas@758 1596 Expression *flde;
tomas@758 1597 Identifier *id;
tomas@758 1598 Type *tret;
tomas@758 1599 TypeDelegate* dgty;
tomas@758 1600 TypeDelegate* dgty2;
tomas@758 1601 TypeDelegate* fldeTy;
tomas@758 1602
tomas@847 1603 if (!checkForArgTypes())
tomas@847 1604 return this;
tomas@847 1605
tomas@758 1606 tret = func->type->nextOf();
tomas@758 1607
tomas@758 1608 // Need a variable to hold value from any return statements in body.
tomas@758 1609 if (!sc->func->vresult && tret && tret != Type::tvoid)
tomas@758 1610 { VarDeclaration *v;
tomas@758 1611
tomas@758 1612 v = new VarDeclaration(loc, tret, Id::result, NULL);
tomas@758 1613 v->noauto = 1;
tomas@758 1614 v->semantic(sc);
tomas@758 1615 if (!sc->insert(v))
tomas@758 1616 assert(0);
tomas@758 1617 v->parent = sc->func;
tomas@758 1618 sc->func->vresult = v;
tomas@758 1619 }
tomas@758 1620
tomas@758 1621 /* Turn body into the function literal:
tomas@758 1622 * int delegate(ref T arg) { body }
tomas@758 1623 */
tomas@758 1624 args = new Arguments();
tomas@847 1625 for (size_t i = 0; i < dim; i++)
tomas@758 1626 { Argument *arg = (Argument *)arguments->data[i];
tomas@758 1627
tomas@758 1628 arg->type = arg->type->semantic(loc, sc);
tomas@758 1629 if (arg->storageClass & STCref)
tomas@758 1630 id = arg->ident;
tomas@758 1631 else
tomas@758 1632 { // Make a copy of the ref argument so it isn't
tomas@758 1633 // a reference.
tomas@758 1634 VarDeclaration *v;
tomas@758 1635 Initializer *ie;
tomas@758 1636
tomas@758 1637 id = Lexer::uniqueId("__applyArg", i);
tomas@758 1638
tomas@758 1639 ie = new ExpInitializer(0, new IdentifierExp(0, id));
tomas@758 1640 v = new VarDeclaration(0, arg->type, arg->ident, ie);
tomas@758 1641 s = new DeclarationStatement(0, v);
tomas@758 1642 body = new CompoundStatement(loc, s, body);
tomas@758 1643 }
tomas@758 1644 a = new Argument(STCref, arg->type, id, NULL);
tomas@758 1645 args->push(a);
tomas@758 1646 }
tomas@758 1647 t = new TypeFunction(args, Type::tint32, 0, LINKd);
tomas@758 1648 fld = new FuncLiteralDeclaration(loc, 0, t, TOKdelegate, this);
tomas@758 1649 fld->fbody = body;
tomas@758 1650 flde = new FuncExp(loc, fld);
tomas@758 1651 flde = flde->semantic(sc);
tomas@758 1652 fld->tookAddressOf = 0;
tomas@758 1653
tomas@758 1654 // Resolve any forward referenced goto's
tomas@758 1655 for (int i = 0; i < gotos.dim; i++)
tomas@758 1656 { CompoundStatement *cs = (CompoundStatement *)gotos.data[i];
tomas@758 1657 GotoStatement *gs = (GotoStatement *)cs->statements->data[0];
tomas@758 1658
tomas@758 1659 if (!gs->label->statement)
tomas@758 1660 { // 'Promote' it to this scope, and replace with a return
tomas@758 1661 cases.push(gs);
tomas@758 1662 s = new ReturnStatement(0, new IntegerExp(cases.dim + 1));
tomas@758 1663 cs->statements->data[0] = (void *)s;
tomas@758 1664 }
tomas@758 1665 }
tomas@758 1666
tomas@758 1667 if (tab->ty == Taarray)
tomas@758 1668 {
tomas@758 1669 // Check types
tomas@758 1670 Argument *arg = (Argument *)arguments->data[0];
tomas@758 1671 if (dim == 2)
tomas@758 1672 {
tomas@758 1673 if (arg->storageClass & STCref)
tomas@758 1674 error("foreach: index cannot be ref");
tomas@758 1675 if (!arg->type->equals(taa->index))
tomas@758 1676 error("foreach: index must be type %s, not %s", taa->index->toChars(), arg->type->toChars());
tomas@758 1677 arg = (Argument *)arguments->data[1];
tomas@758 1678 }
tomas@758 1679 if (!arg->type->equals(taa->nextOf()))
tomas@758 1680 error("foreach: value must be type %s, not %s", taa->nextOf()->toChars(), arg->type->toChars());
tomas@758 1681
tomas@758 1682 /* Call:
tomas@758 1683 * _aaApply(aggr, keysize, flde)
tomas@758 1684 */
tomas@758 1685 //LDC: Build arguments.
tomas@758 1686 static FuncDeclaration *aaApply2_fd = NULL;
tomas@758 1687 static TypeDelegate* aaApply2_dg;
tomas@758 1688 if(!aaApply2_fd) {
tomas@758 1689 Arguments* args = new Arguments;
tomas@758 1690 args->push(new Argument(STCin, Type::tvoid->pointerTo(), NULL, NULL));
tomas@758 1691 args->push(new Argument(STCin, Type::tsize_t, NULL, NULL));
tomas@758 1692 Arguments* dgargs = new Arguments;
tomas@758 1693 dgargs->push(new Argument(STCin, Type::tvoidptr, NULL, NULL));
tomas@758 1694 dgargs->push(new Argument(STCin, Type::tvoidptr, NULL, NULL));
tomas@758 1695 aaApply2_dg = new TypeDelegate(new TypeFunction(dgargs, Type::tindex, 0, LINKd));
tomas@758 1696 args->push(new Argument(STCin, aaApply2_dg, NULL, NULL));
tomas@758 1697 aaApply2_fd = FuncDeclaration::genCfunc(args, Type::tindex, "_aaApply2");
tomas@758 1698 }
tomas@758 1699 static FuncDeclaration *aaApply_fd = NULL;
tomas@758 1700 static TypeDelegate* aaApply_dg;
tomas@758 1701 if(!aaApply_fd) {
tomas@758 1702 Arguments* args = new Arguments;
tomas@758 1703 args->push(new Argument(STCin, Type::tvoid->pointerTo(), NULL, NULL));
tomas@758 1704 args->push(new Argument(STCin, Type::tsize_t, NULL, NULL));
tomas@758 1705 Arguments* dgargs = new Arguments;
tomas@758 1706 dgargs->push(new Argument(STCin, Type::tvoidptr, NULL, NULL));
tomas@758 1707 aaApply_dg = new TypeDelegate(new TypeFunction(dgargs, Type::tindex, 0, LINKd));
tomas@758 1708 args->push(new Argument(STCin, aaApply_dg, NULL, NULL));
tomas@758 1709 aaApply_fd = FuncDeclaration::genCfunc(args, Type::tindex, "_aaApply");
tomas@758 1710 }
tomas@758 1711 if (dim == 2) {
tomas@758 1712 fdapply = aaApply2_fd;
tomas@758 1713 fldeTy = aaApply2_dg;
tomas@758 1714 } else {
tomas@758 1715 fdapply = aaApply_fd;
tomas@758 1716 fldeTy = aaApply_dg;
tomas@758 1717 }
tomas@758 1718 ec = new VarExp(0, fdapply);
tomas@758 1719 Expressions *exps = new Expressions();
tomas@758 1720 exps->push(aggr);
tomas@758 1721 size_t keysize = taa->index->size();
tomas@765 1722 keysize = (keysize + (PTRSIZE-1)) & ~(PTRSIZE-1);
tomas@758 1723 exps->push(new IntegerExp(0, keysize, Type::tsize_t));
tomas@758 1724
tomas@758 1725 // LDC paint delegate argument to the type runtime expects
tomas@758 1726 if (!fldeTy->equals(flde->type))
tomas@758 1727 {
tomas@758 1728 flde = new CastExp(loc, flde, flde->type);
tomas@758 1729 flde->type = fldeTy;
tomas@758 1730 }
tomas@758 1731 exps->push(flde);
tomas@758 1732
tomas@758 1733 e = new CallExp(loc, ec, exps);
tomas@758 1734 e->type = Type::tindex; // don't run semantic() on e
tomas@758 1735 }
tomas@758 1736 else if (tab->ty == Tarray || tab->ty == Tsarray)
tomas@758 1737 {
tomas@758 1738 /* Call:
tomas@758 1739 * _aApply(aggr, flde)
tomas@758 1740 */
tomas@758 1741 static char fntab[9][3] =
tomas@758 1742 { "cc","cw","cd",
tomas@758 1743 "wc","cc","wd",
tomas@758 1744 "dc","dw","dd"
tomas@758 1745 };
tomas@758 1746 char fdname[7+1+2+ sizeof(dim)*3 + 1];
tomas@758 1747 int flag;
tomas@758 1748
tomas@758 1749 switch (tn->ty)
tomas@758 1750 {
tomas@758 1751 case Tchar: flag = 0; break;
tomas@758 1752 case Twchar: flag = 3; break;
tomas@758 1753 case Tdchar: flag = 6; break;
tomas@758 1754 default: assert(0);
tomas@758 1755 }
tomas@758 1756 switch (tnv->ty)
tomas@758 1757 {
tomas@758 1758 case Tchar: flag += 0; break;
tomas@758 1759 case Twchar: flag += 1; break;
tomas@758 1760 case Tdchar: flag += 2; break;
tomas@758 1761 default: assert(0);
tomas@758 1762 }
tomas@758 1763 const char *r = (op == TOKforeach_reverse) ? "R" : "";
tomas@758 1764 int j = sprintf(fdname, "_aApply%s%.*s%d", r, 2, fntab[flag], dim);
tomas@758 1765 assert(j < sizeof(fdname));
tomas@758 1766 //LDC: Build arguments.
tomas@758 1767 Arguments* args = new Arguments;
tomas@758 1768 args->push(new Argument(STCin, tn->arrayOf(), NULL, NULL));
tomas@758 1769 if (dim == 2) {
tomas@758 1770 Arguments* dgargs = new Arguments;
tomas@758 1771 dgargs->push(new Argument(STCin, Type::tvoidptr, NULL, NULL));
tomas@758 1772 dgargs->push(new Argument(STCin, Type::tvoidptr, NULL, NULL));
tomas@758 1773 dgty = new TypeDelegate(new TypeFunction(dgargs, Type::tindex, 0, LINKd));
tomas@758 1774 args->push(new Argument(STCin, dgty, NULL, NULL));
tomas@758 1775 fdapply = FuncDeclaration::genCfunc(args, Type::tindex, fdname);
tomas@758 1776 } else {
tomas@758 1777 Arguments* dgargs = new Arguments;
tomas@758 1778 dgargs->push(new Argument(STCin, Type::tvoidptr, NULL, NULL));
tomas@758 1779 dgty = new TypeDelegate(new TypeFunction(dgargs, Type::tindex, 0, LINKd));
tomas@758 1780 args->push(new Argument(STCin, dgty, NULL, NULL));
tomas@758 1781 fdapply = FuncDeclaration::genCfunc(args, Type::tindex, fdname);
tomas@758 1782 }
tomas@758 1783
tomas@758 1784 ec = new VarExp(0, fdapply);
tomas@758 1785 Expressions *exps = new Expressions();
tomas@758 1786 if (tab->ty == Tsarray)
tomas@758 1787 aggr = aggr->castTo(sc, tn->arrayOf());
tomas@758 1788 exps->push(aggr);
tomas@758 1789
tomas@758 1790 // LDC paint delegate argument to the type runtime expects
tomas@758 1791 if (!dgty->equals(flde->type))
tomas@758 1792 {
tomas@758 1793 flde = new CastExp(loc, flde, flde->type);
tomas@758 1794 flde->type = dgty;
tomas@758 1795 }
tomas@758 1796 exps->push(flde);
tomas@758 1797
tomas@758 1798 e = new CallExp(loc, ec, exps);
tomas@758 1799 e->type = Type::tindex; // don't run semantic() on e
tomas@758 1800 }
tomas@758 1801 else if (tab->ty == Tdelegate)
tomas@758 1802 {
tomas@758 1803 /* Call:
tomas@758 1804 * aggr(flde)
tomas@758 1805 */
tomas@758 1806 Expressions *exps = new Expressions();
tomas@758 1807 exps->push(flde);
tomas@758 1808 e = new CallExp(loc, aggr, exps);
tomas@758 1809 e = e->semantic(sc);
tomas@758 1810 if (e->type != Type::tint32)
tomas@758 1811 error("opApply() function for %s must return an int", tab->toChars());
tomas@758 1812 }
tomas@758 1813 else
tomas@758 1814 {
tomas@758 1815 assert(tab->ty == Tstruct || tab->ty == Tclass);
tomas@758 1816 Identifier *idapply = (op == TOKforeach_reverse)
tomas@758 1817 ? Id::applyReverse : Id::apply;
tomas@758 1818 Dsymbol *sapply = search_function((AggregateDeclaration *)tab->toDsymbol(sc), idapply);
tomas@758 1819 Expressions *exps = new Expressions();
tomas@758 1820 #if 0
tomas@758 1821 TemplateDeclaration *td;
tomas@758 1822 if (sapply &&
tomas@758 1823 (td = sapply->isTemplateDeclaration()) != NULL)
tomas@758 1824 { /* Call:
tomas@758 1825 * aggr.apply!(fld)()
tomas@758 1826 */
tomas@758 1827 TemplateInstance *ti = new TemplateInstance(loc, idapply);
tomas@758 1828 Objects *tiargs = new Objects();
tomas@758 1829 tiargs->push(fld);
tomas@758 1830 ti->tiargs = tiargs;
tomas@758 1831 ec = new DotTemplateInstanceExp(loc, aggr, ti);
tomas@758 1832 }
tomas@758 1833 else
tomas@758 1834 #endif
tomas@758 1835 {
tomas@758 1836 /* Call:
tomas@758 1837 * aggr.apply(flde)
tomas@758 1838 */
tomas@758 1839 ec = new DotIdExp(loc, aggr, idapply);
tomas@758 1840 exps->push(flde);
tomas@758 1841 }
tomas@758 1842 e = new CallExp(loc, ec, exps);
tomas@758 1843 e = e->semantic(sc);
tomas@758 1844 if (e->type != Type::tint32)
tomas@758 1845 error("opApply() function for %s must return an int", tab->toChars());
tomas@758 1846 }
tomas@758 1847
tomas@758 1848 if (!cases.dim)
tomas@758 1849 // Easy case, a clean exit from the loop
tomas@758 1850 s = new ExpStatement(loc, e);
tomas@758 1851 else
tomas@758 1852 { // Construct a switch statement around the return value
tomas@758 1853 // of the apply function.
tomas@758 1854 Statements *a = new Statements();
tomas@758 1855
tomas@758 1856 // default: break; takes care of cases 0 and 1
tomas@758 1857 s = new BreakStatement(0, NULL);
tomas@758 1858 s = new DefaultStatement(0, s);
tomas@758 1859 a->push(s);
tomas@758 1860
tomas@758 1861 // cases 2...
tomas@758 1862 for (int i = 0; i < cases.dim; i++)
tomas@758 1863 {
tomas@758 1864 s = (Statement *)cases.data[i];
tomas@758 1865 s = new CaseStatement(0, new IntegerExp(i + 2), s);
tomas@758 1866 a->push(s);
tomas@758 1867 }
tomas@758 1868
tomas@758 1869 s = new CompoundStatement(loc, a);
tomas@758 1870 s = new SwitchStatement(loc, e, s);
tomas@758 1871 s = s->semantic(sc);
tomas@758 1872 }
tomas@758 1873 break;
tomas@758 1874 }
tomas@758 1875
tomas@758 1876 default:
tomas@758 1877 error("foreach: %s is not an aggregate type", aggr->type->toChars());
tomas@758 1878 break;
tomas@758 1879 }
tomas@758 1880 sc->noctor--;
tomas@758 1881 sc->pop();
tomas@758 1882 return s;
tomas@758 1883 }
tomas@758 1884
tomas@847 1885 bool ForeachStatement::checkForArgTypes()
tomas@847 1886 {
tomas@847 1887 for (size_t i = 0; i < arguments->dim; i++)
tomas@847 1888 { Argument *arg = (Argument *)arguments->data[i];
tomas@847 1889 if (!arg->type)
tomas@847 1890 {
tomas@847 1891 error("cannot infer type for %s", arg->ident->toChars());
tomas@847 1892 return FALSE;
tomas@847 1893 }
tomas@847 1894 }
tomas@847 1895 return TRUE;
tomas@847 1896 }
tomas@847 1897
tomas@758 1898 int ForeachStatement::hasBreak()
tomas@758 1899 {
tomas@758 1900 return TRUE;
tomas@758 1901 }
tomas@758 1902
tomas@758 1903 int ForeachStatement::hasContinue()
tomas@758 1904 {
tomas@758 1905 return TRUE;
tomas@758 1906 }
tomas@758 1907
tomas@758 1908 int ForeachStatement::usesEH()
tomas@758 1909 {
tomas@758 1910 return body->usesEH();
tomas@758 1911 }
tomas@758 1912
tomas@758 1913 int ForeachStatement::blockExit()
tomas@758 1914 { int result = BEfallthru;
tomas@758 1915
tomas@758 1916 if (aggr->canThrow())
tomas@758 1917 result |= BEthrow;
tomas@758 1918
tomas@758 1919 if (body)
tomas@758 1920 {
tomas@758 1921 result |= body->blockExit() & ~(BEbreak | BEcontinue);
tomas@758 1922 }
tomas@758 1923 return result;
tomas@758 1924 }
tomas@758 1925
tomas@758 1926 int ForeachStatement::fallOffEnd()
tomas@758 1927 {
tomas@758 1928 if (body)
tomas@758 1929 body->fallOffEnd();
tomas@758 1930 return TRUE;
tomas@758 1931 }
tomas@758 1932
tomas@758 1933 int ForeachStatement::comeFrom()
tomas@758 1934 {
tomas@758 1935 if (body)
tomas@758 1936 return body->comeFrom();
tomas@758 1937 return FALSE;
tomas@758 1938 }
tomas@758 1939
tomas@758 1940 void ForeachStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
tomas@758 1941 {
tomas@758 1942 buf->writestring(Token::toChars(op));
tomas@758 1943 buf->writestring(" (");
tomas@758 1944 for (int i = 0; i < arguments->dim; i++)
tomas@758 1945 {
tomas@758 1946 Argument *a = (Argument *)arguments->data[i];
tomas@758 1947 if (i)
tomas@758 1948 buf->writestring(", ");
tomas@758 1949 if (a->storageClass & STCref)
tomas@758 1950 buf->writestring((global.params.Dversion == 1)
tomas@758 1951 ? (char*)"inout " : (char*)"ref ");
tomas@758 1952 if (a->type)
tomas@758 1953 a->type->toCBuffer(buf, a->ident, hgs);
tomas@758 1954 else
tomas@758 1955 buf->writestring(a->ident->toChars());
tomas@758 1956 }
tomas@758 1957 buf->writestring("; ");
tomas@758 1958 aggr->toCBuffer(buf, hgs);
tomas@758 1959 buf->writebyte(')');
tomas@758 1960 buf->writenl();
tomas@758 1961 buf->writebyte('{');
tomas@758 1962 buf->writenl();
tomas@758 1963 if (body)
tomas@758 1964 body->toCBuffer(buf, hgs);
tomas@758 1965 buf->writebyte('}');
tomas@758 1966 buf->writenl();
tomas@758 1967 }
tomas@758 1968
tomas@758 1969 /**************************** ForeachRangeStatement ***************************/
tomas@758 1970
tomas@847 1971 #if DMDV2
tomas@847 1972
tomas@758 1973 ForeachRangeStatement::ForeachRangeStatement(Loc loc, enum TOK op, Argument *arg,
tomas@758 1974 Expression *lwr, Expression *upr, Statement *body)
tomas@758 1975 : Statement(loc)
tomas@758 1976 {
tomas@758 1977 this->op = op;
tomas@758 1978 this->arg = arg;
tomas@758 1979 this->lwr = lwr;
tomas@758 1980 this->upr = upr;
tomas@758 1981 this->body = body;
tomas@758 1982
tomas@758 1983 this->enclosinghandler = NULL;
tomas@758 1984
tomas@758 1985 this->key = NULL;
tomas@758 1986 }
tomas@758 1987
tomas@758 1988 Statement *ForeachRangeStatement::syntaxCopy()
tomas@758 1989 {
tomas@758 1990 ForeachRangeStatement *s = new ForeachRangeStatement(loc, op,
tomas@758 1991 arg->syntaxCopy(),
tomas@758 1992 lwr->syntaxCopy(),
tomas@758 1993 upr->syntaxCopy(),
tomas@758 1994 body ? body->syntaxCopy() : NULL);
tomas@758 1995 return s;
tomas@758 1996 }
tomas@758 1997
tomas@758 1998 Statement *ForeachRangeStatement::semantic(Scope *sc)
tomas@758 1999 {
tomas@758 2000 //printf("ForeachRangeStatement::semantic() %p\n", this);
tomas@758 2001 ScopeDsymbol *sym;
tomas@758 2002 Statement *s = this;
tomas@758 2003
tomas@758 2004 enclosinghandler = sc->tfOfTry;
tomas@758 2005
tomas@758 2006 lwr = lwr->semantic(sc);
tomas@758 2007 lwr = resolveProperties(sc, lwr);
tomas@758 2008 lwr = lwr->optimize(WANTvalue);
tomas@758 2009 if (!lwr->type)
tomas@758 2010 {
tomas@758 2011 error("invalid range lower bound %s", lwr->toChars());
tomas@758 2012 return this;
tomas@758 2013 }
tomas@758 2014
tomas@758 2015 upr = upr->semantic(sc);
tomas@758 2016 upr = resolveProperties(sc, upr);
tomas@758 2017 upr = upr->optimize(WANTvalue);
tomas@758 2018 if (!upr->type)
tomas@758 2019 {
tomas@758 2020 error("invalid range upper bound %s", upr->toChars());
tomas@758 2021 return this;
tomas@758 2022 }
tomas@758 2023
tomas@758 2024 if (arg->type)
tomas@758 2025 {
tomas@758 2026 lwr = lwr->implicitCastTo(sc, arg->type);
tomas@758 2027 upr = upr->implicitCastTo(sc, arg->type);
tomas@758 2028 }
tomas@758 2029 else
tomas@758 2030 {
tomas@758 2031 /* Must infer types from lwr and upr
tomas@758 2032 */
tomas@758 2033 AddExp ea(loc, lwr, upr);
tomas@758 2034 ea.typeCombine(sc);
tomas@758 2035 arg->type = ea.type->mutableOf();
tomas@758 2036 lwr = ea.e1;
tomas@758 2037 upr = ea.e2;
tomas@758 2038 }
tomas@758 2039 if (!arg->type->isscalar())
tomas@758 2040 error("%s is not a scalar type", arg->type->toChars());
tomas@758 2041
tomas@758 2042 sym = new ScopeDsymbol();
tomas@758 2043 sym->parent = sc->scopesym;
tomas@758 2044 sc = sc->push(sym);
tomas@758 2045
tomas@758 2046 sc->noctor++;
tomas@758 2047
tomas@758 2048 key = new VarDeclaration(loc, arg->type, arg->ident, NULL);
tomas@758 2049 DeclarationExp *de = new DeclarationExp(loc, key);
tomas@758 2050 de->semantic(sc);
tomas@758 2051
tomas@758 2052 if (key->storage_class)
tomas@758 2053 error("foreach range: key cannot have storage class");
tomas@758 2054
tomas@758 2055 sc->sbreak = this;
tomas@758 2056 sc->scontinue = this;
tomas@758 2057 body = body->semantic(sc);
tomas@758 2058
tomas@758 2059 sc->noctor--;
tomas@758 2060 sc->pop();
tomas@758 2061 return s;
tomas@758 2062 }
tomas@758 2063
tomas@758 2064 int ForeachRangeStatement::hasBreak()
tomas@758 2065 {
tomas@758 2066 return TRUE;
tomas@758 2067 }
tomas@758 2068
tomas@758 2069 int ForeachRangeStatement::hasContinue()
tomas@758 2070 {
tomas@758 2071 return TRUE;
tomas@758 2072 }
tomas@758 2073
tomas@758 2074 int ForeachRangeStatement::usesEH()
tomas@758 2075 {
tomas@758 2076 return body->usesEH();
tomas@758 2077 }
tomas@758 2078
tomas@758 2079 int ForeachRangeStatement::blockExit()
tomas@758 2080 { int result = BEfallthru;
tomas@758 2081
tomas@758 2082 if (lwr && lwr->canThrow())
tomas@758 2083 result |= BEthrow;
tomas@758 2084 else if (upr && upr->canThrow())
tomas@758 2085 result |= BEthrow;
tomas@758 2086
tomas@758 2087 if (body)
tomas@758 2088 {
tomas@758 2089 result |= body->blockExit() & ~(BEbreak | BEcontinue);
tomas@758 2090 }
tomas@758 2091 return result;
tomas@758 2092 }
tomas@758 2093
tomas@758 2094 int ForeachRangeStatement::fallOffEnd()
tomas@758 2095 {
tomas@758 2096 if (body)
tomas@758 2097 body->fallOffEnd();
tomas@758 2098 return TRUE;
tomas@758 2099 }
tomas@758 2100
tomas@758 2101 int ForeachRangeStatement::comeFrom()
tomas@758 2102 {
tomas@758 2103 if (body)
tomas@758 2104 return body->comeFrom();
tomas@758 2105 return FALSE;
tomas@758 2106 }
tomas@758 2107
tomas@758 2108 void ForeachRangeStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
tomas@758 2109 {
tomas@758 2110 buf->writestring(Token::toChars(op));
tomas@758 2111 buf->writestring(" (");
tomas@758 2112
tomas@758 2113 if (arg->type)
tomas@758 2114 arg->type->toCBuffer(buf, arg->ident, hgs);
tomas@758 2115 else
tomas@758 2116 buf->writestring(arg->ident->toChars());
tomas@758 2117
tomas@758 2118 buf->writestring("; ");
tomas@758 2119 lwr->toCBuffer(buf, hgs);
tomas@758 2120 buf->writestring(" .. ");
tomas@758 2121 upr->toCBuffer(buf, hgs);
tomas@758 2122 buf->writebyte(')');
tomas@758 2123 buf->writenl();
tomas@758 2124 buf->writebyte('{');
tomas@758 2125 buf->writenl();
tomas@758 2126 if (body)
tomas@758 2127 body->toCBuffer(buf, hgs);
tomas@758 2128 buf->writebyte('}');
tomas@758 2129 buf->writenl();
tomas@758 2130 }
tomas@758 2131
tomas@847 2132 #endif
tomas@847 2133
tomas@758 2134 /******************************** IfStatement ***************************/
tomas@758 2135
tomas@758 2136 IfStatement::IfStatement(Loc loc, Argument *arg, Expression *condition, Statement *ifbody, Statement *elsebody)
tomas@758 2137 : Statement(loc)
tomas@758 2138 {
tomas@758 2139 this->arg = arg;
tomas@758 2140 this->condition = condition;
tomas@758 2141 this->ifbody = ifbody;
tomas@758 2142 this->elsebody = elsebody;
tomas@758 2143 this->match = NULL;
tomas@758 2144 }
tomas@758 2145
tomas@758 2146 Statement *IfStatement::syntaxCopy()
tomas@758 2147 {
tomas@758 2148 Statement *i = NULL;
tomas@758 2149 if (ifbody)
tomas@758 2150 i = ifbody->syntaxCopy();
tomas@758 2151
tomas@758 2152 Statement *e = NULL;
tomas@758 2153 if (elsebody)
tomas@758 2154 e = elsebody->syntaxCopy();
tomas@758 2155
tomas@758 2156 Argument *a = arg ? arg->syntaxCopy() : NULL;
tomas@758 2157 IfStatement *s = new IfStatement(loc, a, condition->syntaxCopy(), i, e);
tomas@758 2158 return s;
tomas@758 2159 }
tomas@758 2160
tomas@758 2161 Statement *IfStatement::semantic(Scope *sc)
tomas@758 2162 {
tomas@758 2163 condition = condition->semantic(sc);
tomas@758 2164 condition = resolveProperties(sc, condition);
tomas@758 2165 condition = condition->checkToBoolean();
tomas@758 2166
tomas@758 2167 // If we can short-circuit evaluate the if statement, don't do the
tomas@758 2168 // semantic analysis of the skipped code.
tomas@758 2169 // This feature allows a limited form of conditional compilation.
tomas@758 2170 condition = condition->optimize(WANTflags);
tomas@758 2171
tomas@758 2172 // Evaluate at runtime
tomas@758 2173 unsigned cs0 = sc->callSuper;
tomas@758 2174 unsigned cs1;
tomas@758 2175
tomas@758 2176 Scope *scd;
tomas@758 2177 if (arg)
tomas@758 2178 { /* Declare arg, which we will set to be the
tomas@758 2179 * result of condition.
tomas@758 2180 */
tomas@758 2181 ScopeDsymbol *sym = new ScopeDsymbol();
tomas@758 2182 sym->parent = sc->scopesym;
tomas@758 2183 scd = sc->push(sym);
tomas@758 2184
tomas@758 2185 Type *t = arg->type ? arg->type : condition->type;
tomas@758 2186 match = new VarDeclaration(loc, t, arg->ident, NULL);
tomas@758 2187 match->noauto = 1;
tomas@758 2188 match->semantic(scd);
tomas@758 2189 if (!scd->insert(match))
tomas@758 2190 assert(0);
tomas@758 2191 match->parent = sc->func;
tomas@758 2192
tomas@758 2193 /* Generate:
tomas@758 2194 * (arg = condition)
tomas@758 2195 */
tomas@758 2196 VarExp *v = new VarExp(0, match);
tomas@758 2197 condition = new AssignExp(loc, v, condition);
tomas@758 2198 condition = condition->semantic(scd);
tomas@758 2199 }
tomas@758 2200 else
tomas@758 2201 scd = sc->push();
tomas@758 2202 ifbody = ifbody->semantic(scd);
tomas@758 2203 scd->pop();
tomas@758 2204
tomas@758 2205 cs1 = sc->callSuper;
tomas@758 2206 sc->callSuper = cs0;
tomas@758 2207 if (elsebody)
tomas@758 2208 elsebody = elsebody->semanticScope(sc, NULL, NULL);
tomas@758 2209 sc->mergeCallSuper(loc, cs1);
tomas@758 2210
tomas@758 2211 return this;
tomas@758 2212 }
tomas@758 2213
tomas@758 2214 int IfStatement::usesEH()
tomas@758 2215 {
tomas@758 2216 return (ifbody && ifbody->usesEH()) || (elsebody && elsebody->usesEH());
tomas@758 2217 }
tomas@758 2218
tomas@758 2219 int IfStatement::blockExit()
tomas@758 2220 {
tomas@758 2221 //printf("IfStatement::blockExit(%p)\n", this);
tomas@758 2222
tomas@758 2223 int result = BEnone;
tomas@758 2224 if (condition->canThrow())
tomas@758 2225 result |= BEthrow;
tomas@758 2226 if (condition->isBool(TRUE))
tomas@758 2227 {
tomas@758 2228 if (ifbody)
tomas@758 2229 result |= ifbody->blockExit();
tomas@758 2230 else
tomas@758 2231 result |= BEfallthru;
tomas@758 2232 }
tomas@758 2233 else if (condition->isBool(FALSE))
tomas@758 2234 {
tomas@758 2235 if (elsebody)
tomas@758 2236 result |= elsebody->blockExit();
tomas@758 2237 else
tomas@758 2238 result |= BEfallthru;
tomas@758 2239 }
tomas@758 2240 else
tomas@758 2241 {
tomas@758 2242 if (ifbody)
tomas@758 2243 result |= ifbody->blockExit();
tomas@758 2244 else
tomas@758 2245 result |= BEfallthru;
tomas@758 2246 if (elsebody)
tomas@758 2247 result |= elsebody->blockExit();
tomas@758 2248 else
tomas@758 2249 result |= BEfallthru;
tomas@758 2250 }
tomas@758 2251 //printf("IfStatement::blockExit(%p) = x%x\n", this, result);
tomas@758 2252 return result;
tomas@758 2253 }
tomas@758 2254
tomas@758 2255 int IfStatement::fallOffEnd()
tomas@758 2256 {
tomas@758 2257 if (!ifbody || ifbody->fallOffEnd() ||
tomas@758 2258 !elsebody || elsebody->fallOffEnd())
tomas@758 2259 return TRUE;
tomas@758 2260 return FALSE;
tomas@758 2261 }
tomas@758 2262
tomas@758 2263
tomas@758 2264 void IfStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
tomas@758 2265 {
tomas@758 2266 buf->writestring("if (");
tomas@758 2267 if (arg)
tomas@758 2268 {
tomas@758 2269 if (arg->type)
tomas@758 2270 arg->type->toCBuffer(buf, arg->ident, hgs);
tomas@758 2271 else
tomas@758 2272 { buf->writestring("auto ");
tomas@758 2273 buf->writestring(arg->ident->toChars());
tomas@758 2274 }
tomas@758 2275 buf->writestring(" = ");
tomas@758 2276 }
tomas@758 2277 condition->toCBuffer(buf, hgs);
tomas@758 2278 buf->writebyte(')');
tomas@758 2279 buf->writenl();
tomas@758 2280 ifbody->toCBuffer(buf, hgs);
tomas@758 2281 if (elsebody)
tomas@758 2282 { buf->writestring("else");
tomas@758 2283 buf->writenl();
tomas@758 2284 elsebody->toCBuffer(buf, hgs);
tomas@758 2285 }
tomas@758 2286 }
tomas@758 2287
tomas@758 2288 /******************************** ConditionalStatement ***************************/
tomas@758 2289
tomas@758 2290 ConditionalStatement::ConditionalStatement(Loc loc, Condition *condition, Statement *ifbody, Statement *elsebody)
tomas@758 2291 : Statement(loc)
tomas@758 2292 {
tomas@758 2293 this->condition = condition;
tomas@758 2294 this->ifbody = ifbody;
tomas@758 2295 this->elsebody = elsebody;
tomas@758 2296 }
tomas@758 2297
tomas@758 2298 Statement *ConditionalStatement::syntaxCopy()
tomas@758 2299 {
tomas@758 2300 Statement *e = NULL;
tomas@758 2301 if (elsebody)
tomas@758 2302 e = elsebody->syntaxCopy();
tomas@758 2303 ConditionalStatement *s = new ConditionalStatement(loc,
tomas@758 2304 condition->syntaxCopy(), ifbody->syntaxCopy(), e);
tomas@758 2305 return s;
tomas@758 2306 }
tomas@758 2307
tomas@758 2308 Statement *ConditionalStatement::semantic(Scope *sc)
tomas@758 2309 {
tomas@758 2310 //printf("ConditionalStatement::semantic()\n");
tomas@758 2311
tomas@758 2312 // If we can short-circuit evaluate the if statement, don't do the
tomas@758 2313 // semantic analysis of the skipped code.
tomas@758 2314 // This feature allows a limited form of conditional compilation.
tomas@758 2315 if (condition->include(sc, NULL))
tomas@758 2316 {
tomas@758 2317 ifbody = ifbody->semantic(sc);
tomas@758 2318 return ifbody;
tomas@758 2319 }
tomas@758 2320 else
tomas@758 2321 {
tomas@758 2322 if (elsebody)
tomas@758 2323 elsebody = elsebody->semantic(sc);
tomas@758 2324 return elsebody;
tomas@758 2325 }
tomas@758 2326 }
tomas@758 2327
tomas@758 2328 Statements *ConditionalStatement::flatten(Scope *sc)
tomas@758 2329 {
tomas@758 2330 Statement *s;
tomas@758 2331
tomas@758 2332 if (condition->include(sc, NULL))
tomas@758 2333 s = ifbody;
tomas@758 2334 else
tomas@758 2335 s = elsebody;
tomas@758 2336
tomas@758 2337 Statements *a = new Statements();
tomas@758 2338 a->push(s);
tomas@758 2339 return a;
tomas@758 2340 }
tomas@758 2341
tomas@758 2342 int ConditionalStatement::usesEH()
tomas@758 2343 {
tomas@758 2344 return (ifbody && ifbody->usesEH()) || (elsebody && elsebody->usesEH());
tomas@758 2345 }
tomas@758 2346
tomas@758 2347 int ConditionalStatement::blockExit()
tomas@758 2348 {
tomas@758 2349 int result = ifbody->blockExit();
tomas@758 2350 if (elsebody)
tomas@758 2351 result |= elsebody->blockExit();
tomas@758 2352 return result;
tomas@758 2353 }
tomas@758 2354
tomas@758 2355 void ConditionalStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
tomas@758 2356 {
tomas@758 2357 condition->toCBuffer(buf, hgs);
tomas@758 2358 buf->writenl();
tomas@758 2359 buf->writeByte('{');
tomas@758 2360 buf->writenl();
tomas@758 2361 if (ifbody)
tomas@758 2362 ifbody->toCBuffer(buf, hgs);
tomas@758 2363 buf->writeByte('}');
tomas@758 2364 buf->writenl();
tomas@758 2365 if (elsebody)
tomas@758 2366 {
tomas@758 2367 buf->writestring("else");
tomas@758 2368 buf->writenl();
tomas@758 2369 buf->writeByte('{');
tomas@758 2370 buf->writenl();
tomas@758 2371 elsebody->toCBuffer(buf, hgs);
tomas@758 2372 buf->writeByte('}');
tomas@758 2373 buf->writenl();
tomas@758 2374 }
tomas@758 2375 buf->writenl();
tomas@758 2376 }
tomas@758 2377
tomas@758 2378
tomas@758 2379 /******************************** PragmaStatement ***************************/
tomas@758 2380
tomas@758 2381 PragmaStatement::PragmaStatement(Loc loc, Identifier *ident, Expressions *args, Statement *body)
tomas@758 2382 : Statement(loc)
tomas@758 2383 {
tomas@758 2384 this->ident = ident;
tomas@758 2385 this->args = args;
tomas@758 2386 this->body = body;
tomas@758 2387 }
tomas@758 2388
tomas@758 2389 Statement *PragmaStatement::syntaxCopy()
tomas@758 2390 {
tomas@758 2391 Statement *b = NULL;
tomas@758 2392 if (body)
tomas@758 2393 b = body->syntaxCopy();
tomas@758 2394 PragmaStatement *s = new PragmaStatement(loc,
tomas@758 2395 ident, Expression::arraySyntaxCopy(args), b);
tomas@758 2396 return s;
tomas@758 2397 }
tomas@758 2398
tomas@758 2399 Statement *PragmaStatement::semantic(Scope *sc)
tomas@758 2400 { // Should be merged with PragmaDeclaration
tomas@758 2401 //printf("PragmaStatement::semantic() %s\n", toChars());
tomas@758 2402 //printf("body = %p\n", body);
tomas@758 2403 if (ident == Id::msg)
tomas@758 2404 {
tomas@758 2405 if (args)
tomas@758 2406 {
tomas@758 2407 for (size_t i = 0; i < args->dim; i++)
tomas@758 2408 {
tomas@758 2409 Expression *e = (Expression *)args->data[i];
tomas@758 2410
tomas@758 2411 e = e->semantic(sc);
tomas@758 2412 e = e->optimize(WANTvalue | WANTinterpret);
tomas@758 2413 if (e->op == TOKstring)
tomas@758 2414 {
tomas@758 2415 StringExp *se = (StringExp *)e;
tomas@758 2416 fprintf(stdmsg, "%.*s", (int)se->len, se->string);
tomas@758 2417 }
tomas@758 2418 else
tomas@758 2419 error("string expected for message, not '%s'", e->toChars());
tomas@758 2420 }
tomas@758 2421 fprintf(stdmsg, "\n");
tomas@758 2422 }
tomas@758 2423 }
tomas@758 2424 else if (ident == Id::lib)
tomas@758 2425 {
tomas@847 2426 #if 1
tomas@847 2427 /* Should this be allowed?
tomas@847 2428 */
tomas@847 2429 error("pragma(lib) not allowed as statement");
tomas@847 2430 #else
tomas@758 2431 if (!args || args->dim != 1)
tomas@758 2432 error("string expected for library name");
tomas@758 2433 else
tomas@758 2434 {
tomas@758 2435 Expression *e = (Expression *)args->data[0];
tomas@758 2436
tomas@758 2437 e = e->semantic(sc);
tomas@758 2438 e = e->optimize(WANTvalue | WANTinterpret);
tomas@758 2439 args->data[0] = (void *)e;
tomas@758 2440 if (e->op != TOKstring)
tomas@758 2441 error("string expected for library name, not '%s'", e->toChars());
tomas@758 2442 else if (global.params.verbose)
tomas@758 2443 {
tomas@758 2444 StringExp *se = (StringExp *)e;
tomas@758 2445 char *name = (char *)mem.malloc(se->len + 1);
tomas@758 2446 memcpy(name, se->string, se->len);
tomas@758 2447 name[se->len] = 0;
tomas@758 2448 printf("library %s\n", name);
tomas@758 2449 mem.free(name);
tomas@758 2450 }
tomas@758 2451 }
tomas@847 2452 #endif
tomas@758 2453 }
tomas@758 2454 else if (ident == Id::startaddress)
tomas@758 2455 {
tomas@758 2456 if (!args || args->dim != 1)
tomas@758 2457 error("function name expected for start address");
tomas@758 2458 else
tomas@758 2459 {
tomas@758 2460 Expression *e = (Expression *)args->data[0];
tomas@758 2461 e = e->semantic(sc);
tomas@758 2462 e = e->optimize(WANTvalue | WANTinterpret);
tomas@758 2463 args->data[0] = (void *)e;
tomas@758 2464 Dsymbol *sa = getDsymbol(e);
tomas@758 2465 if (!sa || !sa->isFuncDeclaration())
tomas@758 2466 error("function name expected for start address, not '%s'", e->toChars());
tomas@758 2467 if (body)
tomas@758 2468 {
tomas@758 2469 body = body->semantic(sc);
tomas@758 2470 }
tomas@758 2471 return this;
tomas@758 2472 }
tomas@758 2473 }
tomas@758 2474 else
tomas@758 2475 error("unrecognized pragma(%s)", ident->toChars());
tomas@758 2476
tomas@758 2477 if (body)
tomas@758 2478 {
tomas@758 2479 body = body->semantic(sc);
tomas@758 2480 }
tomas@758 2481 return body;
tomas@758 2482 }
tomas@758 2483
tomas@758 2484 int PragmaStatement::usesEH()
tomas@758 2485 {
tomas@758 2486 return body && body->usesEH();
tomas@758 2487 }
tomas@758 2488
tomas@758 2489 int PragmaStatement::blockExit()
tomas@758 2490 {
tomas@758 2491 int result = BEfallthru;
tomas@758 2492 #if 0 // currently, no code is generated for Pragma's, so it's just fallthru
tomas@758 2493 if (arrayExpressionCanThrow(args))
tomas@758 2494 result |= BEthrow;
tomas@758 2495 if (body)
tomas@758 2496 result |= body->blockExit();
tomas@758 2497 #endif
tomas@758 2498 return result;
tomas@758 2499 }
tomas@758 2500
tomas@758 2501 int PragmaStatement::fallOffEnd()
tomas@758 2502 {
tomas@758 2503 if (body)
tomas@758 2504 return body->fallOffEnd();
tomas@758 2505 return TRUE;
tomas@758 2506 }
tomas@758 2507
tomas@758 2508 void PragmaStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
tomas@758 2509 {
tomas@758 2510 buf->writestring("pragma (");
tomas@758 2511 buf->writestring(ident->toChars());
tomas@758 2512 if (args && args->dim)
tomas@758 2513 {
tomas@758 2514 buf->writestring(", ");
tomas@758 2515 argsToCBuffer(buf, args, hgs);
tomas@758 2516 }
tomas@758 2517 buf->writeByte(')');
tomas@758 2518 if (body)
tomas@758 2519 {
tomas@758 2520 buf->writenl();
tomas@758 2521 buf->writeByte('{');
tomas@758 2522 buf->writenl();
tomas@758 2523
tomas@758 2524 body->toCBuffer(buf, hgs);
tomas@758 2525
tomas@758 2526 buf->writeByte('}');
tomas@758 2527 buf->writenl();
tomas@758 2528 }
tomas@758 2529 else
tomas@758 2530 {
tomas@758 2531 buf->writeByte(';');
tomas@758 2532 buf->writenl();
tomas@758 2533 }
tomas@758 2534 }
tomas@758 2535
tomas@758 2536
tomas@758 2537 /******************************** StaticAssertStatement ***************************/
tomas@758 2538
tomas@758 2539 StaticAssertStatement::StaticAssertStatement(StaticAssert *sa)
tomas@758 2540 : Statement(sa->loc)
tomas@758 2541 {
tomas@758 2542 this->sa = sa;
tomas@758 2543 }
tomas@758 2544
tomas@758 2545 Statement *StaticAssertStatement::syntaxCopy()
tomas@758 2546 {
tomas@758 2547 StaticAssertStatement *s = new StaticAssertStatement((StaticAssert *)sa->syntaxCopy(NULL));
tomas@758 2548 return s;
tomas@758 2549 }
tomas@758 2550
tomas@758 2551 Statement *StaticAssertStatement::semantic(Scope *sc)
tomas@758 2552 {
tomas@758 2553 sa->semantic2(sc);
tomas@758 2554 return NULL;
tomas@758 2555 }
tomas@758 2556
tomas@758 2557 void StaticAssertStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
tomas@758 2558 {
tomas@758 2559 sa->toCBuffer(buf, hgs);
tomas@758 2560 }
tomas@758 2561
tomas@758 2562
tomas@758 2563 /******************************** SwitchStatement ***************************/
tomas@758 2564
tomas@758 2565 SwitchStatement::SwitchStatement(Loc loc, Expression *c, Statement *b)
tomas@758 2566 : Statement(loc)
tomas@758 2567 {
tomas@758 2568 condition = c;
tomas@758 2569 body = b;
tomas@758 2570 sdefault = NULL;
tomas@758 2571 tf = NULL;
tomas@758 2572 cases = NULL;
tomas@758 2573 hasNoDefault = 0;
tomas@758 2574 hasVars = 0;
tomas@758 2575 // LDC
tomas@758 2576 enclosinghandler = NULL;
tomas@758 2577 }
tomas@758 2578
tomas@758 2579 Statement *SwitchStatement::syntaxCopy()
tomas@758 2580 {
tomas@758 2581 SwitchStatement *s = new SwitchStatement(loc,
tomas@758 2582 condition->syntaxCopy(), body->syntaxCopy());
tomas@758 2583 return s;
tomas@758 2584 }
tomas@758 2585
tomas@758 2586 Statement *SwitchStatement::semantic(Scope *sc)
tomas@758 2587 {
tomas@758 2588 //printf("SwitchStatement::semantic(%p)\n", this);
tomas@758 2589 tf = sc->tf;
tomas@758 2590 assert(!cases); // ensure semantic() is only run once
tomas@758 2591
tomas@758 2592 enclosinghandler = sc->tfOfTry;
tomas@758 2593
tomas@758 2594 condition = condition->semantic(sc);
tomas@758 2595 condition = resolveProperties(sc, condition);
tomas@758 2596 if (condition->type->isString())
tomas@758 2597 {
tomas@758 2598 // If it's not an array, cast it to one
tomas@758 2599 if (condition->type->ty != Tarray)
tomas@758 2600 {
tomas@758 2601 condition = condition->implicitCastTo(sc, condition->type->nextOf()->arrayOf());
tomas@758 2602 }
tomas@758 2603 condition->type = condition->type->constOf();
tomas@758 2604 }
tomas@758 2605 else
tomas@758 2606 { condition = condition->integralPromotions(sc);
tomas@758 2607 condition->checkIntegral();
tomas@758 2608 }
tomas@758 2609 condition = condition->optimize(WANTvalue);
tomas@758 2610
tomas@758 2611 sc = sc->push();
tomas@758 2612 sc->sbreak = this;
tomas@758 2613 sc->sw = this;
tomas@758 2614
tomas@758 2615 cases = new Array();
tomas@758 2616 sc->noctor++; // BUG: should use Scope::mergeCallSuper() for each case instead
tomas@758 2617 body = body->semantic(sc);
tomas@758 2618 sc->noctor--;
tomas@758 2619
tomas@758 2620 // Resolve any goto case's with exp
tomas@758 2621 for (int i = 0; i < gotoCases.dim; i++)
tomas@758 2622 {
tomas@758 2623 GotoCaseStatement *gcs = (GotoCaseStatement *)gotoCases.data[i];
tomas@758 2624
tomas@758 2625 if (!gcs->exp)
tomas@758 2626 {
tomas@758 2627 gcs->error("no case statement following goto case;");
tomas@758 2628 break;
tomas@758 2629 }
tomas@758 2630
tomas@758 2631 for (Scope *scx = sc; scx; scx = scx->enclosing)
tomas@758 2632 {
tomas@758 2633 if (!scx->sw)
tomas@758 2634 continue;
tomas@758 2635 for (int j = 0; j < scx->sw->cases->dim; j++)
tomas@758 2636 {
tomas@758 2637 CaseStatement *cs = (CaseStatement *)scx->sw->cases->data[j];
tomas@758 2638
tomas@758 2639 if (cs->exp->equals(gcs->exp))
tomas@758 2640 {
tomas@758 2641 gcs->cs = cs;
tomas@758 2642 goto Lfoundcase;
tomas@758 2643 }
tomas@758 2644 }
tomas@758 2645 }
tomas@758 2646 gcs->error("case %s not found", gcs->exp->toChars());
tomas@758 2647
tomas@758 2648 Lfoundcase:
tomas@758 2649 ;
tomas@758 2650 }
tomas@758 2651
tomas@758 2652 if (!sc->sw->sdefault)
tomas@758 2653 { hasNoDefault = 1;
tomas@758 2654
tomas@758 2655 if (global.params.warnings)
tomas@758 2656 { warning("%s: switch statement has no default", loc.toChars());
tomas@758 2657 }
tomas@758 2658
tomas@758 2659 // Generate runtime error if the default is hit
tomas@758 2660 Statements *a = new Statements();
tomas@758 2661 CompoundStatement *cs;
tomas@758 2662 Statement *s;
tomas@758 2663
tomas@758 2664 if (global.params.useSwitchError)
tomas@758 2665 s = new SwitchErrorStatement(loc);
tomas@758 2666 else
tomas@758 2667 { Expression *e = new HaltExp(loc);
tomas@758 2668 s = new ExpStatement(loc, e);
tomas@758 2669 }
tomas@758 2670
tomas@758 2671 a->reserve(4);
tomas@758 2672 a->push(body);
tomas@758 2673 a->push(new BreakStatement(loc, NULL));
tomas@758 2674 sc->sw->sdefault = new DefaultStatement(loc, s);
tomas@758 2675 a->push(sc->sw->sdefault);
tomas@758 2676 cs = new CompoundStatement(loc, a);
tomas@758 2677 body = cs;
tomas@758 2678 }
tomas@758 2679
tomas@758 2680 sc->pop();
tomas@758 2681 return this;
tomas@758 2682 }
tomas@758 2683
tomas@758 2684 int SwitchStatement::hasBreak()
tomas@758 2685 {
tomas@758 2686 return TRUE;
tomas@758 2687 }
tomas@758 2688
tomas@758 2689 int SwitchStatement::usesEH()
tomas@758 2690 {
tomas@758 2691 return body ? body->usesEH() : 0;
tomas@758 2692 }
tomas@758 2693
tomas@758 2694 int SwitchStatement::blockExit()
tomas@758 2695 { int result = BEnone;
tomas@758 2696 if (condition->canThrow())
tomas@758 2697 result |= BEthrow;
tomas@758 2698
tomas@758 2699 if (body)
tomas@758 2700 { result |= body->blockExit();
tomas@758 2701 if (result & BEbreak)
tomas@758 2702 { result |= BEfallthru;
tomas@758 2703 result &= ~BEbreak;
tomas@758 2704 }
tomas@758 2705 }
tomas@758 2706 else
tomas@758 2707 result |= BEfallthru;
tomas@758 2708
tomas@758 2709 return result;
tomas@758 2710 }
tomas@758 2711
tomas@758 2712 int SwitchStatement::fallOffEnd()
tomas@758 2713 {
tomas@758 2714 if (body)
tomas@758 2715 body->fallOffEnd();
tomas@758 2716 return TRUE; // need to do this better
tomas@758 2717 }
tomas@758 2718
tomas@758 2719 void SwitchStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
tomas@758 2720 {
tomas@758 2721 buf->writestring("switch (");
tomas@758 2722 condition->toCBuffer(buf, hgs);
tomas@758 2723 buf->writebyte(')');
tomas@758 2724 buf->writenl();
tomas@758 2725 if (body)
tomas@758 2726 {
tomas@758 2727 if (!body->isScopeStatement())
tomas@758 2728 { buf->writebyte('{');
tomas@758 2729 buf->writenl();
tomas@758 2730 body->toCBuffer(buf, hgs);
tomas@758 2731 buf->writebyte('}');
tomas@758 2732 buf->writenl();
tomas@758 2733 }
tomas@758 2734 else
tomas@758 2735 {
tomas@758 2736 body->toCBuffer(buf, hgs);
tomas@758 2737 }
tomas@758 2738 }
tomas@758 2739 }
tomas@758 2740
tomas@758 2741 /******************************** CaseStatement ***************************/
tomas@758 2742
tomas@758 2743 CaseStatement::CaseStatement(Loc loc, Expression *exp, Statement *s)
tomas@758 2744 : Statement(loc)
tomas@758 2745 {
tomas@758 2746 this->exp = exp;
tomas@758 2747 this->statement = s;
tomas@758 2748 index = 0;
tomas@758 2749 cblock = NULL;
tomas@758 2750 bodyBB = NULL;
tomas@758 2751 llvmIdx = NULL;
tomas@758 2752 }
tomas@758 2753
tomas@758 2754 Statement *CaseStatement::syntaxCopy()
tomas@758 2755 {
tomas@758 2756 CaseStatement *s = new CaseStatement(loc, exp->syntaxCopy(), statement->syntaxCopy());
tomas@758 2757 return s;
tomas@758 2758 }
tomas@758 2759
tomas@758 2760 Statement *CaseStatement::semantic(Scope *sc)
tomas@758 2761 { SwitchStatement *sw = sc->sw;
tomas@758 2762
tomas@758 2763 //printf("CaseStatement::semantic() %s\n", toChars());
tomas@758 2764 exp = exp->semantic(sc);
tomas@758 2765 if (sw)
tomas@758 2766 {
tomas@758 2767 exp = exp->implicitCastTo(sc, sw->condition->type);
tomas@758 2768 exp = exp->optimize(WANTvalue | WANTinterpret);
tomas@758 2769
tomas@758 2770 /* This is where variables are allowed as case expressions.
tomas@758 2771 */
tomas@758 2772 if (exp->op == TOKvar)
tomas@758 2773 { VarExp *ve = (VarExp *)exp;
tomas@758 2774 VarDeclaration *v = ve->var->isVarDeclaration();
tomas@758 2775 Type *t = exp->type->toBasetype();
tomas@758 2776 if (v && (t->isintegral() || t->ty == Tclass))
tomas@758 2777 { /* Flag that we need to do special code generation
tomas@758 2778 * for this, i.e. generate a sequence of if-then-else
tomas@758 2779 */
tomas@758 2780 sw->hasVars = 1;
tomas@758 2781 goto L1;
tomas@758 2782 }
tomas@758 2783 }
tomas@758 2784
tomas@758 2785 if (exp->op != TOKstring && exp->op != TOKint64)
tomas@758 2786 {
tomas@758 2787 error("case must be a string or an integral constant, not %s", exp->toChars());
tomas@758 2788 exp = new IntegerExp(0);
tomas@758 2789 }
tomas@758 2790
tomas@758 2791 L1:
tomas@758 2792 for (int i = 0; i < sw->cases->dim; i++)
tomas@758 2793 {
tomas@758 2794 CaseStatement *cs = (CaseStatement *)sw->cases->data[i];
tomas@758 2795
tomas@758 2796 //printf("comparing '%s' with '%s'\n", exp->toChars(), cs->exp->toChars());
tomas@758 2797 if (cs->exp->equals(exp))
tomas@758 2798 { error("duplicate case %s in switch statement", exp->toChars());
tomas@758 2799 break;
tomas@758 2800 }
tomas@758 2801 }
tomas@758 2802
tomas@758 2803 sw->cases->push(this);
tomas@758 2804
tomas@758 2805 // Resolve any goto case's with no exp to this case statement
tomas@758 2806 for (int i = 0; i < sw->gotoCases.dim; i++)
tomas@758 2807 {
tomas@758 2808 GotoCaseStatement *gcs = (GotoCaseStatement *)sw->gotoCases.data[i];
tomas@758 2809
tomas@758 2810 if (!gcs->exp)
tomas@758 2811 {
tomas@758 2812 gcs->cs = this;
tomas@758 2813 sw->gotoCases.remove(i); // remove from array
tomas@758 2814 }
tomas@758 2815 }
tomas@758 2816
tomas@758 2817 if (sc->sw->tf != sc->tf)
tomas@758 2818 error("switch and case are in different finally blocks");
tomas@758 2819 }
tomas@758 2820 else
tomas@758 2821 error("case not in switch statement");
tomas@758 2822 statement = statement->semantic(sc);
tomas@758 2823 return this;
tomas@758 2824 }
tomas@758 2825
tomas@758 2826 int CaseStatement::compare(Object *obj)
tomas@758 2827 {
tomas@758 2828 // Sort cases so we can do an efficient lookup
tomas@758 2829 CaseStatement *cs2 = (CaseStatement *)(obj);
tomas@758 2830
tomas@758 2831 return exp->compare(cs2->exp);
tomas@758 2832 }
tomas@758 2833
tomas@758 2834 int CaseStatement::usesEH()
tomas@758 2835 {
tomas@758 2836 return statement->usesEH();
tomas@758 2837 }
tomas@758 2838
tomas@758 2839 int CaseStatement::blockExit()
tomas@758 2840 {
tomas@758 2841 return statement->blockExit();
tomas@758 2842 }
tomas@758 2843
tomas@758 2844 int CaseStatement::fallOffEnd()
tomas@758 2845 {
tomas@758 2846 return statement->fallOffEnd();
tomas@758 2847 }
tomas@758 2848
tomas@758 2849 int CaseStatement::comeFrom()
tomas@758 2850 {
tomas@758 2851 return TRUE;
tomas@758 2852 }
tomas@758 2853
tomas@758 2854 void CaseStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
tomas@758 2855 {
tomas@758 2856 buf->writestring("case ");
tomas@758 2857 exp->toCBuffer(buf, hgs);
tomas@758 2858 buf->writebyte(':');
tomas@758 2859 buf->writenl();
tomas@758 2860 statement->toCBuffer(buf, hgs);
tomas@758 2861 }
tomas@758 2862
tomas@758 2863 /******************************** DefaultStatement ***************************/
tomas@758 2864
tomas@758 2865 DefaultStatement::DefaultStatement(Loc loc, Statement *s)
tomas@758 2866 : Statement(loc)
tomas@758 2867 {
tomas@758 2868 this->statement = s;
tomas@758 2869 #if IN_GCC
tomas@758 2870 + cblock = NULL;
tomas@758 2871 #endif
tomas@758 2872 bodyBB = NULL;
tomas@758 2873 }
tomas@758 2874
tomas@758 2875 Statement *DefaultStatement::syntaxCopy()
tomas@758 2876 {
tomas@758 2877 DefaultStatement *s = new DefaultStatement(loc, statement->syntaxCopy());
tomas@758 2878 return s;
tomas@758 2879 }
tomas@758 2880
tomas@758 2881 Statement *DefaultStatement::semantic(Scope *sc)
tomas@758 2882 {
tomas@758 2883 //printf("DefaultStatement::semantic()\n");
tomas@758 2884 if (sc->sw)
tomas@758 2885 {
tomas@758 2886 if (sc->sw->sdefault)
tomas@758 2887 {
tomas@758 2888 error("switch statement already has a default");
tomas@758 2889 }
tomas@758 2890 sc->sw->sdefault = this;
tomas@758 2891
tomas@758 2892 if (sc->sw->tf != sc->tf)
tomas@758 2893 error("switch and default are in different finally blocks");
tomas@758 2894 }
tomas@758 2895 else
tomas@758 2896 error("default not in switch statement");
tomas@758 2897 statement = statement->semantic(sc);
tomas@758 2898 return this;
tomas@758 2899 }
tomas@758 2900
tomas@758 2901 int DefaultStatement::usesEH()
tomas@758 2902 {
tomas@758 2903 return statement->usesEH();
tomas@758 2904 }
tomas@758 2905
tomas@758 2906 int DefaultStatement::blockExit()
tomas@758 2907 {
tomas@758 2908 return statement->blockExit();
tomas@758 2909 }
tomas@758 2910
tomas@758 2911 int DefaultStatement::fallOffEnd()
tomas@758 2912 {
tomas@758 2913 return statement->fallOffEnd();
tomas@758 2914 }
tomas@758 2915
tomas@758 2916 int DefaultStatement::comeFrom()
tomas@758 2917 {
tomas@758 2918 return TRUE;
tomas@758 2919 }
tomas@758 2920
tomas@758 2921 void DefaultStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
tomas@758 2922 {
tomas@758 2923 buf->writestring("default:\n");
tomas@758 2924 statement->toCBuffer(buf, hgs);
tomas@758 2925 }
tomas@758 2926
tomas@758 2927 /******************************** GotoDefaultStatement ***************************/
tomas@758 2928
tomas@758 2929 GotoDefaultStatement::GotoDefaultStatement(Loc loc)
tomas@758 2930 : Statement(loc)
tomas@758 2931 {
tomas@758 2932 sw = NULL;
tomas@758 2933 enclosinghandler = NULL;
tomas@758 2934 }
tomas@758 2935
tomas@758 2936 Statement *GotoDefaultStatement::syntaxCopy()
tomas@758 2937 {
tomas@758 2938 GotoDefaultStatement *s = new GotoDefaultStatement(loc);
tomas@758 2939 return s;
tomas@758 2940 }
tomas@758 2941
tomas@758 2942 Statement *GotoDefaultStatement::semantic(Scope *sc)
tomas@758 2943 {
tomas@758 2944 enclosinghandler = sc->tfOfTry;
tomas@758 2945 sw = sc->sw;
tomas@758 2946 if (!sw)
tomas@758 2947 error("goto default not in switch statement");
tomas@758 2948 return this;
tomas@758 2949 }
tomas@758 2950
tomas@758 2951 int GotoDefaultStatement::blockExit()
tomas@758 2952 {
tomas@758 2953 return BEgoto;
tomas@758 2954 }
tomas@758 2955
tomas@758 2956 int GotoDefaultStatement::fallOffEnd()
tomas@758 2957 {
tomas@758 2958 return FALSE;
tomas@758 2959 }
tomas@758 2960
tomas@758 2961 void GotoDefaultStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
tomas@758 2962 {
tomas@758 2963 buf->writestring("goto default;\n");
tomas@758 2964 }
tomas@758 2965
tomas@758 2966 /******************************** GotoCaseStatement ***************************/
tomas@758 2967
tomas@758 2968 GotoCaseStatement::GotoCaseStatement(Loc loc, Expression *exp)
tomas@758 2969 : Statement(loc)
tomas@758 2970 {
tomas@758 2971 cs = NULL;
tomas@758 2972 this->exp = exp;
tomas@758 2973 enclosinghandler = NULL;
tomas@758 2974 sw = NULL;
tomas@758 2975 }
tomas@758 2976
tomas@758 2977 Statement *GotoCaseStatement::syntaxCopy()
tomas@758 2978 {
tomas@758 2979 Expression *e = exp ? exp->syntaxCopy() : NULL;
tomas@758 2980 GotoCaseStatement *s = new GotoCaseStatement(loc, e);
tomas@758 2981 return s;
tomas@758 2982 }
tomas@758 2983
tomas@758 2984 Statement *GotoCaseStatement::semantic(Scope *sc)
tomas@758 2985 {
tomas@758 2986 enclosinghandler = sc->tfOfTry;
tomas@758 2987 if (exp)
tomas@758 2988 exp = exp->semantic(sc);
tomas@758 2989
tomas@758 2990 if (!sc->sw)
tomas@758 2991 error("goto case not in switch statement");
tomas@758 2992 else
tomas@758 2993 {
tomas@758 2994 sw = sc->sw;
tomas@758 2995 sc->sw->gotoCases.push(this);
tomas@758 2996 if (exp)
tomas@758 2997 {
tomas@758 2998 exp = exp->implicitCastTo(sc, sc->sw->condition->type);
tomas@758 2999 exp = exp->optimize(WANTvalue);
tomas@758 3000 }
tomas@758 3001 }
tomas@758 3002 return this;
tomas@758 3003 }
tomas@758 3004
tomas@758 3005 int GotoCaseStatement::blockExit()
tomas@758 3006 {
tomas@758 3007 return BEgoto;
tomas@758 3008 }
tomas@758 3009
tomas@758 3010 int GotoCaseStatement::fallOffEnd()
tomas@758 3011 {
tomas@758 3012 return FALSE;
tomas@758 3013 }
tomas@758 3014
tomas@758 3015 void GotoCaseStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
tomas@758 3016 {
tomas@758 3017 buf->writestring("goto case");
tomas@758 3018 if (exp)
tomas@758 3019 { buf->writebyte(' ');
tomas@758 3020 exp->toCBuffer(buf, hgs);
tomas@758 3021 }
tomas@758 3022 buf->writebyte(';');
tomas@758 3023 buf->writenl();
tomas@758 3024 }
tomas@758 3025
tomas@758 3026 /******************************** SwitchErrorStatement ***************************/
tomas@758 3027
tomas@758 3028 SwitchErrorStatement::SwitchErrorStatement(Loc loc)
tomas@758 3029 : Statement(loc)
tomas@758 3030 {
tomas@758 3031 }
tomas@758 3032
tomas@758 3033 int SwitchErrorStatement::blockExit()
tomas@758 3034 {
tomas@758 3035 return BEthrow;
tomas@758 3036 }
tomas@758 3037
tomas@758 3038 int SwitchErrorStatement::fallOffEnd()
tomas@758 3039 {
tomas@758 3040 return FALSE;
tomas@758 3041 }
tomas@758 3042
tomas@758 3043 void SwitchErrorStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
tomas@758 3044 {
tomas@758 3045 buf->writestring("SwitchErrorStatement::toCBuffer()");
tomas@758 3046 buf->writenl();
tomas@758 3047 }
tomas@758 3048
tomas@758 3049 /******************************** ReturnStatement ***************************/
tomas@758 3050
tomas@758 3051 ReturnStatement::ReturnStatement(Loc loc, Expression *exp)
tomas@758 3052 : Statement(loc)
tomas@758 3053 {
tomas@758 3054 this->exp = exp;
tomas@758 3055 this->enclosinghandler = NULL;
tomas@758 3056 }
tomas@758 3057
tomas@758 3058 Statement *ReturnStatement::syntaxCopy()
tomas@758 3059 {
tomas@758 3060 Expression *e = NULL;
tomas@758 3061 if (exp)
tomas@758 3062 e = exp->syntaxCopy();
tomas@758 3063 ReturnStatement *s = new ReturnStatement(loc, e);
tomas@758 3064 return s;
tomas@758 3065 }
tomas@758 3066
tomas@758 3067 Statement *ReturnStatement::semantic(Scope *sc)
tomas@758 3068 {
tomas@758 3069 //printf("ReturnStatement::semantic() %s\n", toChars());
tomas@758 3070 this->enclosinghandler = sc->tfOfTry;
tomas@758 3071
tomas@758 3072 FuncDeclaration *fd = sc->parent->isFuncDeclaration();
tomas@758 3073 Scope *scx = sc;
tomas@758 3074 int implicit0 = 0;
tomas@758 3075
tomas@758 3076 if (sc->fes)
tomas@758 3077 {
tomas@758 3078 // Find scope of function foreach is in
tomas@758 3079 for (; 1; scx = scx->enclosing)
tomas@758 3080 {
tomas@758 3081 assert(scx);
tomas@758 3082 if (scx->func != fd)
tomas@758 3083 { fd = scx->func; // fd is now function enclosing foreach
tomas@758 3084 break;
tomas@758 3085 }
tomas@758 3086 }
tomas@758 3087 }
tomas@758 3088
tomas@758 3089 Type *tret = fd->type->nextOf();
tomas@758 3090 if (fd->tintro)
tomas@758 3091 /* We'll be implicitly casting the return expression to tintro
tomas@758 3092 */
tomas@758 3093 tret = fd->tintro->nextOf();
tomas@758 3094 Type *tbret = NULL;
tomas@758 3095
tomas@758 3096 if (tret)
tomas@758 3097 tbret = tret->toBasetype();
tomas@758 3098
tomas@758 3099 // main() returns 0, even if it returns void
tomas@758 3100 if (!exp && (!tbret || tbret->ty == Tvoid) && fd->isMain())
tomas@758 3101 { implicit0 = 1;
tomas@758 3102 exp = new IntegerExp(0);
tomas@758 3103 }
tomas@758 3104
tomas@758 3105 if (sc->incontract || scx->incontract)
tomas@758 3106 error("return statements cannot be in contracts");
tomas@758 3107 if (sc->tf || scx->tf)
tomas@758 3108 error("return statements cannot be in finally, scope(exit) or scope(success) bodies");
tomas@758 3109
tomas@758 3110 if (fd->isCtorDeclaration())
tomas@758 3111 {
tomas@758 3112 // Constructors implicitly do:
tomas@758 3113 // return this;
tomas@758 3114 if (exp && exp->op != TOKthis)
tomas@758 3115 error("cannot return expression from constructor");
tomas@758 3116 exp = new ThisExp(0);
tomas@758 3117 }
tomas@758 3118
tomas@758 3119 if (!exp)
tomas@758 3120 fd->nrvo_can = 0;
tomas@758 3121
tomas@758 3122 if (exp)
tomas@758 3123 {
tomas@758 3124 fd->hasReturnExp |= 1;
tomas@758 3125
tomas@758 3126 exp = exp->semantic(sc);
tomas@758 3127 exp = resolveProperties(sc, exp);
tomas@758 3128 exp = exp->optimize(WANTvalue);
tomas@758 3129
tomas@758 3130 if (fd->nrvo_can && exp->op == TOKvar)
tomas@758 3131 { VarExp *ve = (VarExp *)exp;
tomas@758 3132 VarDeclaration *v = ve->var->isVarDeclaration();
tomas@758 3133
tomas@758 3134 if (((TypeFunction *)fd->type)->isref)
tomas@758 3135 // Function returns a reference
tomas@758 3136 fd->nrvo_can = 0;
tomas@758 3137 else if (!v || v->isOut() || v->isRef())
tomas@758 3138 fd->nrvo_can = 0;
tomas@758 3139 else if (tbret->ty == Tstruct && ((TypeStruct *)tbret)->sym->dtor)
tomas@758 3140 // Struct being returned has destructors
tomas@758 3141 fd->nrvo_can = 0;
tomas@758 3142 else if (fd->nrvo_var == NULL)
tomas@758 3143 { if (!v->isDataseg() && !v->isParameter() && v->toParent2() == fd)
tomas@758 3144 { //printf("Setting nrvo to %s\n", v->toChars());
tomas@758 3145 fd->nrvo_var = v;
tomas@758 3146 }
tomas@758 3147 else
tomas@758 3148 fd->nrvo_can = 0;
tomas@758 3149 }
tomas@758 3150 else if (fd->nrvo_var != v)
tomas@758 3151 fd->nrvo_can = 0;
tomas@758 3152 }
tomas@758 3153 else
tomas@758 3154 fd->nrvo_can = 0;
tomas@758 3155
tomas@758 3156 if (fd->returnLabel && tbret->ty != Tvoid)
tomas@758 3157 {
tomas@758 3158 }
tomas@758 3159 else if (fd->inferRetType)
tomas@758 3160 {
tomas@758 3161 if (fd->type->nextOf())
tomas@758 3162 {
tomas@758 3163 if (!exp->type->equals(fd->type->nextOf()))
tomas@758 3164 error("mismatched function return type inference of %s and %s",
tomas@758 3165 exp->type->toChars(), fd->type->nextOf()->toChars());
tomas@758 3166 }
tomas@758 3167 else
tomas@758 3168 {
tomas@758 3169 ((TypeFunction *)fd->type)->next = exp->type;
tomas@758 3170 fd->type = fd->type->semantic(loc, sc);
tomas@758 3171 if (!fd->tintro)
tomas@758 3172 { tret = fd->type->nextOf();
tomas@758 3173 tbret = tret->toBasetype();
tomas@758 3174 }
tomas@758 3175 }
tomas@758 3176 }
tomas@758 3177 else if (tbret->ty != Tvoid)
tomas@758 3178 {
tomas@758 3179 exp = exp->implicitCastTo(sc, tret);
tomas@758 3180 }
tomas@758 3181 }
tomas@758 3182 else if (fd->inferRetType)
tomas@758 3183 {
tomas@758 3184 if (fd->type->nextOf())
tomas@758 3185 {
tomas@758 3186 if (fd->type->nextOf()->ty != Tvoid)
tomas@758 3187 error("mismatched function return type inference of void and %s",
tomas@758 3188 fd->type->nextOf()->toChars());
tomas@758 3189 }
tomas@758 3190 else
tomas@758 3191 {
tomas@758 3192 ((TypeFunction *)fd->type)->next = Type::tvoid;
tomas@758 3193 fd->type = fd->type->semantic(loc, sc);
tomas@758 3194 if (!fd->tintro)
tomas@758 3195 { tret = Type::tvoid;
tomas@758 3196 tbret = tret;
tomas@758 3197 }
tomas@758 3198 }
tomas@758 3199 }
tomas@758 3200 else if (tbret->ty != Tvoid) // if non-void return
tomas@758 3201 error("return expression expected");
tomas@758 3202
tomas@758 3203 if (sc->fes)
tomas@758 3204 {
tomas@758 3205 Statement *s;
tomas@758 3206
tomas@758 3207 if (exp && !implicit0)
tomas@758 3208 {
tomas@758 3209 exp = exp->implicitCastTo(sc, tret);
tomas@758 3210 }
tomas@758 3211 if (!exp || exp->op == TOKint64 || exp->op == TOKfloat64 ||
tomas@758 3212 exp->op == TOKimaginary80 || exp->op == TOKcomplex80 ||
tomas@758 3213 exp->op == TOKthis || exp->op == TOKsuper || exp->op == TOKnull ||
tomas@758 3214 exp->op == TOKstring)
tomas@758 3215 {
tomas@758 3216 sc->fes->cases.push(this);
tomas@758 3217 // Construct: return cases.dim+1;
tomas@758 3218 s = new ReturnStatement(0, new IntegerExp(sc->fes->cases.dim + 1));
tomas@758 3219 }
tomas@758 3220 else if (fd->type->nextOf()->toBasetype() == Type::tvoid)
tomas@758 3221 {
tomas@758 3222 s = new ReturnStatement(0, NULL);
tomas@758 3223 sc->fes->cases.push(s);
tomas@758 3224
tomas@758 3225 // Construct: { exp; return cases.dim + 1; }
tomas@758 3226 Statement *s1 = new ExpStatement(loc, exp);
tomas@758 3227 Statement *s2 = new ReturnStatement(0, new IntegerExp(sc->fes->cases.dim + 1));
tomas@758 3228 s = new CompoundStatement(loc, s1, s2);
tomas@758 3229 }
tomas@758 3230 else
tomas@758 3231 {
tomas@758 3232 // Construct: return vresult;
tomas@758 3233 if (!fd->vresult)
tomas@758 3234 { // Declare vresult
tomas@758 3235 VarDeclaration *v = new VarDeclaration(loc, tret, Id::result, NULL);
tomas@758 3236 v->noauto = 1;
tomas@758 3237 v->semantic(scx);
tomas@758 3238 if (!scx->insert(v))
tomas@758 3239 assert(0);
tomas@758 3240 v->parent = fd;
tomas@758 3241 fd->vresult = v;
tomas@758 3242 }
tomas@758 3243
tomas@758 3244 s = new ReturnStatement(0, new VarExp(0, fd->vresult));
tomas@758 3245 sc->fes->cases.push(s);
tomas@758 3246
tomas@758 3247 // Construct: { vresult = exp; return cases.dim + 1; }
tomas@758 3248 exp = new AssignExp(loc, new VarExp(0, fd->vresult), exp);
tomas@758 3249 exp = exp->semantic(sc);
tomas@758 3250 Statement *s1 = new ExpStatement(loc, exp);
tomas@758 3251 Statement *s2 = new ReturnStatement(0, new IntegerExp(sc->fes->cases.dim + 1));
tomas@758 3252 s = new CompoundStatement(loc, s1, s2);
tomas@758 3253 }
tomas@758 3254 return s;
tomas@758 3255 }
tomas@758 3256
tomas@758 3257 if (exp)
tomas@758 3258 {
tomas@758 3259 if (fd->returnLabel && tbret->ty != Tvoid)
tomas@758 3260 {
tomas@758 3261 assert(fd->vresult);
tomas@758 3262 VarExp *v = new VarExp(0, fd->vresult);
tomas@758 3263
tomas@758 3264 exp = new AssignExp(loc, v, exp);
tomas@758 3265 exp = exp->semantic(sc);
tomas@758 3266 }
tomas@758 3267
tomas@758 3268 if (((TypeFunction *)fd->type)->isref)
tomas@758 3269 { // Function returns a reference
tomas@758 3270 if (tbret->isMutable())
tomas@758 3271 exp = exp->modifiableLvalue(sc, exp);
tomas@758 3272 else
tomas@758 3273 exp = exp->toLvalue(sc, exp);
tomas@758 3274
tomas@758 3275 if (exp->op == TOKvar)
tomas@758 3276 { VarExp *ve = (VarExp *)exp;
tomas@758 3277 VarDeclaration *v = ve->var->isVarDeclaration();
tomas@758 3278 if (v && !v->isDataseg() && !(v->storage_class & (STCref | STCout)))
tomas@758 3279 error("escaping reference to local variable %s", v->toChars());
tomas@758 3280 }
tomas@758 3281 }
tomas@758 3282
tomas@758 3283 //exp->dump(0);
tomas@758 3284 //exp->print();
tomas@758 3285 exp->checkEscape();
tomas@758 3286 }
tomas@758 3287
tomas@758 3288 /* BUG: need to issue an error on:
tomas@758 3289 * this
tomas@758 3290 * { if (x) return;
tomas@758 3291 * super();
tomas@758 3292 * }
tomas@758 3293 */
tomas@758 3294
tomas@758 3295 if (sc->callSuper & CSXany_ctor &&
tomas@758 3296 !(sc->callSuper & (CSXthis_ctor | CSXsuper_ctor)))
tomas@758 3297 error("return without calling constructor");
tomas@758 3298
tomas@758 3299 sc->callSuper |= CSXreturn;
tomas@758 3300
tomas@758 3301 // See if all returns are instead to be replaced with a goto returnLabel;
tomas@758 3302 if (fd->returnLabel)
tomas@758 3303 {
tomas@758 3304 GotoStatement *gs = new GotoStatement(loc, Id::returnLabel);
tomas@758 3305
tomas@758 3306 gs->label = fd->returnLabel;
tomas@758 3307 if (exp)
tomas@758 3308 { /* Replace: return exp;
tomas@758 3309 * with: exp; goto returnLabel;
tomas@758 3310 */
tomas@758 3311 Statement *s = new ExpStatement(0, exp);
tomas@758 3312 return new CompoundStatement(loc, s, gs);
tomas@758 3313 }
tomas@758 3314 return gs;
tomas@758 3315 }
tomas@758 3316
tomas@758 3317 if (exp && tbret->ty == Tvoid && !fd->isMain())
tomas@758 3318 {