1 2/* Compiler implementation of the D programming language 3 * Copyright (C) 1999-2019 by The D Language Foundation, All Rights Reserved 4 * written by Walter Bright 5 * http://www.digitalmars.com 6 * Distributed under the Boost Software License, Version 1.0. 7 * http://www.boost.org/LICENSE_1_0.txt 8 * https://github.com/D-Programming-Language/dmd/blob/master/src/statement.c 9 */ 10 11#include "root/dsystem.h" 12 13#include "statement.h" 14#include "errors.h" 15#include "expression.h" 16#include "cond.h" 17#include "init.h" 18#include "staticassert.h" 19#include "scope.h" 20#include "declaration.h" 21#include "aggregate.h" 22#include "id.h" 23#include "hdrgen.h" 24#include "parse.h" 25#include "template.h" 26#include "attrib.h" 27#include "import.h" 28 29bool walkPostorder(Statement *s, StoppableVisitor *v); 30StorageClass mergeFuncAttrs(StorageClass s1, FuncDeclaration *f); 31bool checkEscapeRef(Scope *sc, Expression *e, bool gag); 32VarDeclaration *copyToTemp(StorageClass stc, const char *name, Expression *e); 33Expression *semantic(Expression *e, Scope *sc); 34StringExp *semanticString(Scope *sc, Expression *exp, const char *s); 35Statement *makeTupleForeachStatic(Scope *sc, ForeachStatement *fs, bool needExpansion); 36 37Identifier *fixupLabelName(Scope *sc, Identifier *ident) 38{ 39 unsigned flags = (sc->flags & SCOPEcontract); 40 const char *id = ident->toChars(); 41 if (flags && flags != SCOPEinvariant && 42 !(id[0] == '_' && id[1] == '_')) 43 { 44 /* CTFE requires FuncDeclaration::labtab for the interpretation. 45 * So fixing the label name inside in/out contracts is necessary 46 * for the uniqueness in labtab. 47 */ 48 const char *prefix = flags == SCOPErequire ? "__in_" : "__out_"; 49 OutBuffer buf; 50 buf.printf("%s%s", prefix, ident->toChars()); 51 52 const char *name = buf.extractString(); 53 ident = Identifier::idPool(name); 54 } 55 return ident; 56} 57 58LabelStatement *checkLabeledLoop(Scope *sc, Statement *statement) 59{ 60 if (sc->slabel && sc->slabel->statement == statement) 61 { 62 return sc->slabel; 63 } 64 return NULL; 65} 66 67/*********************************************************** 68 * Check an assignment is used as a condition. 69 * Intended to be use before the `semantic` call on `e`. 70 * Params: 71 * e = condition expression which is not yet run semantic analysis. 72 * Returns: 73 * `e` or ErrorExp. 74 */ 75Expression *checkAssignmentAsCondition(Expression *e) 76{ 77 Expression *ec = e; 78 while (ec->op == TOKcomma) 79 ec = ((CommaExp *)ec)->e2; 80 if (ec->op == TOKassign) 81 { 82 ec->error("assignment cannot be used as a condition, perhaps == was meant?"); 83 return new ErrorExp(); 84 } 85 return e; 86} 87 88/// Return a type identifier reference to 'object.Throwable' 89TypeIdentifier *getThrowable() 90{ 91 TypeIdentifier *tid = new TypeIdentifier(Loc(), Id::empty); 92 tid->addIdent(Id::object); 93 tid->addIdent(Id::Throwable); 94 return tid; 95} 96 97/******************************** Statement ***************************/ 98 99Statement::Statement(Loc loc) 100 : loc(loc) 101{ 102 // If this is an in{} contract scope statement (skip for determining 103 // inlineStatus of a function body for header content) 104} 105 106Statement *Statement::syntaxCopy() 107{ 108 assert(0); 109 return NULL; 110} 111 112void Statement::print() 113{ 114 fprintf(stderr, "%s\n", toChars()); 115 fflush(stderr); 116} 117 118const char *Statement::toChars() 119{ 120 HdrGenState hgs; 121 122 OutBuffer buf; 123 ::toCBuffer(this, &buf, &hgs); 124 return buf.extractString(); 125} 126 127 128void Statement::error(const char *format, ...) 129{ 130 va_list ap; 131 va_start(ap, format); 132 ::verror(loc, format, ap); 133 va_end( ap ); 134} 135 136void Statement::warning(const char *format, ...) 137{ 138 va_list ap; 139 va_start(ap, format); 140 ::vwarning(loc, format, ap); 141 va_end( ap ); 142} 143 144void Statement::deprecation(const char *format, ...) 145{ 146 va_list ap; 147 va_start(ap, format); 148 ::vdeprecation(loc, format, ap); 149 va_end( ap ); 150} 151 152bool Statement::hasBreak() 153{ 154 //printf("Statement::hasBreak()\n"); 155 return false; 156} 157 158bool Statement::hasContinue() 159{ 160 return false; 161} 162 163/* ============================================== */ 164// true if statement uses exception handling 165 166bool Statement::usesEH() 167{ 168 class UsesEH : public StoppableVisitor 169 { 170 public: 171 void visit(Statement *) {} 172 void visit(TryCatchStatement *) { stop = true; } 173 void visit(TryFinallyStatement *) { stop = true; } 174 void visit(OnScopeStatement *) { stop = true; } 175 void visit(SynchronizedStatement *) { stop = true; } 176 }; 177 178 UsesEH ueh; 179 return walkPostorder(this, &ueh); 180} 181 182/* ============================================== */ 183// true if statement 'comes from' somewhere else, like a goto 184 185bool Statement::comeFrom() 186{ 187 class ComeFrom : public StoppableVisitor 188 { 189 public: 190 void visit(Statement *) {} 191 void visit(CaseStatement *) { stop = true; } 192 void visit(DefaultStatement *) { stop = true; } 193 void visit(LabelStatement *) { stop = true; } 194 void visit(AsmStatement *) { stop = true; } 195 }; 196 197 ComeFrom cf; 198 return walkPostorder(this, &cf); 199} 200 201/* ============================================== */ 202// Return true if statement has executable code. 203 204bool Statement::hasCode() 205{ 206 class HasCode : public StoppableVisitor 207 { 208 public: 209 void visit(Statement *) 210 { 211 stop = true; 212 } 213 214 void visit(ExpStatement *s) 215 { 216 if (s->exp != NULL) 217 { 218 stop = s->exp->hasCode(); 219 } 220 } 221 222 void visit(CompoundStatement *) {} 223 void visit(ScopeStatement *) {} 224 void visit(ImportStatement *) {} 225 }; 226 227 HasCode hc; 228 return walkPostorder(this, &hc); 229} 230 231Statement *Statement::last() 232{ 233 return this; 234} 235 236/**************************************** 237 * If this statement has code that needs to run in a finally clause 238 * at the end of the current scope, return that code in the form of 239 * a Statement. 240 * Output: 241 * *sentry code executed upon entry to the scope 242 * *sexception code executed upon exit from the scope via exception 243 * *sfinally code executed in finally block 244 */ 245 246Statement *Statement::scopeCode(Scope *, Statement **sentry, Statement **sexception, Statement **sfinally) 247{ 248 //printf("Statement::scopeCode()\n"); 249 //print(); 250 *sentry = NULL; 251 *sexception = NULL; 252 *sfinally = NULL; 253 return this; 254} 255 256/********************************* 257 * Flatten out the scope by presenting the statement 258 * as an array of statements. 259 * Returns NULL if no flattening necessary. 260 */ 261 262Statements *Statement::flatten(Scope *) 263{ 264 return NULL; 265} 266 267 268/******************************** ErrorStatement ***************************/ 269 270ErrorStatement::ErrorStatement() 271 : Statement(Loc()) 272{ 273 assert(global.gaggedErrors || global.errors); 274} 275 276Statement *ErrorStatement::syntaxCopy() 277{ 278 return this; 279} 280 281/******************************** PeelStatement ***************************/ 282 283PeelStatement::PeelStatement(Statement *s) 284 : Statement(s->loc) 285{ 286 this->s = s; 287} 288 289/******************************** ExpStatement ***************************/ 290 291ExpStatement::ExpStatement(Loc loc, Expression *exp) 292 : Statement(loc) 293{ 294 this->exp = exp; 295} 296 297ExpStatement::ExpStatement(Loc loc, Dsymbol *declaration) 298 : Statement(loc) 299{ 300 this->exp = new DeclarationExp(loc, declaration); 301} 302 303ExpStatement *ExpStatement::create(Loc loc, Expression *exp) 304{ 305 return new ExpStatement(loc, exp); 306} 307 308Statement *ExpStatement::syntaxCopy() 309{ 310 return new ExpStatement(loc, exp ? exp->syntaxCopy() : NULL); 311} 312 313Statement *ExpStatement::scopeCode(Scope *, Statement **sentry, Statement **sexception, Statement **sfinally) 314{ 315 //printf("ExpStatement::scopeCode()\n"); 316 //print(); 317 318 *sentry = NULL; 319 *sexception = NULL; 320 *sfinally = NULL; 321 322 if (exp) 323 { 324 if (exp->op == TOKdeclaration) 325 { 326 DeclarationExp *de = (DeclarationExp *)(exp); 327 VarDeclaration *v = de->declaration->isVarDeclaration(); 328 if (v && !v->isDataseg()) 329 { 330 if (v->needsScopeDtor()) 331 { 332 //printf("dtor is: "); v->edtor->print(); 333 *sfinally = new DtorExpStatement(loc, v->edtor, v); 334 v->storage_class |= STCnodtor; // don't add in dtor again 335 } 336 } 337 } 338 } 339 return this; 340} 341 342/**************************************** 343 * Convert TemplateMixin members (== Dsymbols) to Statements. 344 */ 345Statement *toStatement(Dsymbol *s) 346{ 347 class ToStmt : public Visitor 348 { 349 public: 350 Statement *result; 351 352 ToStmt() 353 { 354 this->result = NULL; 355 } 356 357 Statement *visitMembers(Loc loc, Dsymbols *a) 358 { 359 if (!a) 360 return NULL; 361 362 Statements *statements = new Statements(); 363 for (size_t i = 0; i < a->dim; i++) 364 { 365 statements->push(toStatement((*a)[i])); 366 } 367 return new CompoundStatement(loc, statements); 368 } 369 370 void visit(Dsymbol *s) 371 { 372 ::error(Loc(), "Internal Compiler Error: cannot mixin %s %s\n", s->kind(), s->toChars()); 373 result = new ErrorStatement(); 374 } 375 376 void visit(TemplateMixin *tm) 377 { 378 Statements *a = new Statements(); 379 for (size_t i = 0; i < tm->members->dim; i++) 380 { 381 Statement *s = toStatement((*tm->members)[i]); 382 if (s) 383 a->push(s); 384 } 385 result = new CompoundStatement(tm->loc, a); 386 } 387 388 /* An actual declaration symbol will be converted to DeclarationExp 389 * with ExpStatement. 390 */ 391 Statement *declStmt(Dsymbol *s) 392 { 393 DeclarationExp *de = new DeclarationExp(s->loc, s); 394 de->type = Type::tvoid; // avoid repeated semantic 395 return new ExpStatement(s->loc, de); 396 } 397 void visit(VarDeclaration *d) { result = declStmt(d); } 398 void visit(AggregateDeclaration *d) { result = declStmt(d); } 399 void visit(FuncDeclaration *d) { result = declStmt(d); } 400 void visit(EnumDeclaration *d) { result = declStmt(d); } 401 void visit(AliasDeclaration *d) { result = declStmt(d); } 402 void visit(TemplateDeclaration *d) { result = declStmt(d); } 403 404 /* All attributes have been already picked by the semantic analysis of 405 * 'bottom' declarations (function, struct, class, etc). 406 * So we don't have to copy them. 407 */ 408 void visit(StorageClassDeclaration *d) { result = visitMembers(d->loc, d->decl); } 409 void visit(DeprecatedDeclaration *d) { result = visitMembers(d->loc, d->decl); } 410 void visit(LinkDeclaration *d) { result = visitMembers(d->loc, d->decl); } 411 void visit(ProtDeclaration *d) { result = visitMembers(d->loc, d->decl); } 412 void visit(AlignDeclaration *d) { result = visitMembers(d->loc, d->decl); } 413 void visit(UserAttributeDeclaration *d) { result = visitMembers(d->loc, d->decl); } 414 void visit(ForwardingAttribDeclaration *d) { result = visitMembers(d->loc, d->decl); } 415 416 void visit(StaticAssert *) {} 417 void visit(Import *) {} 418 void visit(PragmaDeclaration *) {} 419 420 void visit(ConditionalDeclaration *d) 421 { 422 result = visitMembers(d->loc, d->include(NULL, NULL)); 423 } 424 425 void visit(StaticForeachDeclaration *d) 426 { 427 assert(d->sfe && !!d->sfe->aggrfe ^ !!d->sfe->rangefe); 428 result = visitMembers(d->loc, d->include(NULL, NULL)); 429 } 430 431 void visit(CompileDeclaration *d) 432 { 433 result = visitMembers(d->loc, d->include(NULL, NULL)); 434 } 435 }; 436 437 if (!s) 438 return NULL; 439 440 ToStmt v; 441 s->accept(&v); 442 return v.result; 443} 444 445Statements *ExpStatement::flatten(Scope *sc) 446{ 447 /* Bugzilla 14243: expand template mixin in statement scope 448 * to handle variable destructors. 449 */ 450 if (exp && exp->op == TOKdeclaration) 451 { 452 Dsymbol *d = ((DeclarationExp *)exp)->declaration; 453 if (TemplateMixin *tm = d->isTemplateMixin()) 454 { 455 Expression *e = semantic(exp, sc); 456 if (e->op == TOKerror || tm->errors) 457 { 458 Statements *a = new Statements(); 459 a->push(new ErrorStatement()); 460 return a; 461 } 462 assert(tm->members); 463 464 Statement *s = toStatement(tm); 465 Statements *a = new Statements(); 466 a->push(s); 467 return a; 468 } 469 } 470 return NULL; 471} 472 473/******************************** DtorExpStatement ***************************/ 474 475DtorExpStatement::DtorExpStatement(Loc loc, Expression *exp, VarDeclaration *v) 476 : ExpStatement(loc, exp) 477{ 478 this->var = v; 479} 480 481Statement *DtorExpStatement::syntaxCopy() 482{ 483 return new DtorExpStatement(loc, exp ? exp->syntaxCopy() : NULL, var); 484} 485 486/******************************** CompileStatement ***************************/ 487 488CompileStatement::CompileStatement(Loc loc, Expression *exp) 489 : Statement(loc) 490{ 491 this->exp = exp; 492} 493 494Statement *CompileStatement::syntaxCopy() 495{ 496 return new CompileStatement(loc, exp->syntaxCopy()); 497} 498 499static Statements *errorStatements() 500{ 501 Statements *a = new Statements(); 502 a->push(new ErrorStatement()); 503 return a; 504} 505 506Statements *CompileStatement::flatten(Scope *sc) 507{ 508 //printf("CompileStatement::flatten() %s\n", exp->toChars()); 509 StringExp *se = semanticString(sc, exp, "argument to mixin"); 510 if (!se) 511 return errorStatements(); 512 se = se->toUTF8(sc); 513 514 unsigned errors = global.errors; 515 Parser p(loc, sc->_module, (utf8_t *)se->string, se->len, 0); 516 p.nextToken(); 517 518 Statements *a = new Statements(); 519 while (p.token.value != TOKeof) 520 { 521 Statement *s = p.parseStatement(PSsemi | PScurlyscope); 522 if (!s || p.errors) 523 { 524 assert(!p.errors || global.errors != errors); // make sure we caught all the cases 525 return errorStatements(); 526 } 527 a->push(s); 528 } 529 return a; 530} 531 532/******************************** CompoundStatement ***************************/ 533 534CompoundStatement::CompoundStatement(Loc loc, Statements *s) 535 : Statement(loc) 536{ 537 statements = s; 538} 539 540CompoundStatement::CompoundStatement(Loc loc, Statement *s1, Statement *s2) 541 : Statement(loc) 542{ 543 statements = new Statements(); 544 statements->reserve(2); 545 statements->push(s1); 546 statements->push(s2); 547} 548 549CompoundStatement::CompoundStatement(Loc loc, Statement *s1) 550 : Statement(loc) 551{ 552 statements = new Statements(); 553 statements->push(s1); 554} 555 556CompoundStatement *CompoundStatement::create(Loc loc, Statement *s1, Statement *s2) 557{ 558 return new CompoundStatement(loc, s1, s2); 559} 560 561Statement *CompoundStatement::syntaxCopy() 562{ 563 Statements *a = new Statements(); 564 a->setDim(statements->dim); 565 for (size_t i = 0; i < statements->dim; i++) 566 { 567 Statement *s = (*statements)[i]; 568 (*a)[i] = s ? s->syntaxCopy() : NULL; 569 } 570 return new CompoundStatement(loc, a); 571} 572 573Statements *CompoundStatement::flatten(Scope *) 574{ 575 return statements; 576} 577 578ReturnStatement *CompoundStatement::isReturnStatement() 579{ 580 ReturnStatement *rs = NULL; 581 582 for (size_t i = 0; i < statements->dim; i++) 583 { 584 Statement *s = (*statements)[i]; 585 if (s) 586 { 587 rs = s->isReturnStatement(); 588 if (rs) 589 break; 590 } 591 } 592 return rs; 593} 594 595Statement *CompoundStatement::last() 596{ 597 Statement *s = NULL; 598 599 for (size_t i = statements->dim; i; --i) 600 { s = (*statements)[i - 1]; 601 if (s) 602 { 603 s = s->last(); 604 if (s) 605 break; 606 } 607 } 608 return s; 609} 610 611/******************************** CompoundDeclarationStatement ***************************/ 612 613CompoundDeclarationStatement::CompoundDeclarationStatement(Loc loc, Statements *s) 614 : CompoundStatement(loc, s) 615{ 616 statements = s; 617} 618 619Statement *CompoundDeclarationStatement::syntaxCopy() 620{ 621 Statements *a = new Statements(); 622 a->setDim(statements->dim); 623 for (size_t i = 0; i < statements->dim; i++) 624 { 625 Statement *s = (*statements)[i]; 626 (*a)[i] = s ? s->syntaxCopy() : NULL; 627 } 628 return new CompoundDeclarationStatement(loc, a); 629} 630 631/**************************** UnrolledLoopStatement ***************************/ 632 633UnrolledLoopStatement::UnrolledLoopStatement(Loc loc, Statements *s) 634 : Statement(loc) 635{ 636 statements = s; 637} 638 639Statement *UnrolledLoopStatement::syntaxCopy() 640{ 641 Statements *a = new Statements(); 642 a->setDim(statements->dim); 643 for (size_t i = 0; i < statements->dim; i++) 644 { 645 Statement *s = (*statements)[i]; 646 (*a)[i] = s ? s->syntaxCopy() : NULL; 647 } 648 return new UnrolledLoopStatement(loc, a); 649} 650 651bool UnrolledLoopStatement::hasBreak() 652{ 653 return true; 654} 655 656bool UnrolledLoopStatement::hasContinue() 657{ 658 return true; 659} 660 661/******************************** ScopeStatement ***************************/ 662 663ScopeStatement::ScopeStatement(Loc loc, Statement *s, Loc endloc) 664 : Statement(loc) 665{ 666 this->statement = s; 667 this->endloc = endloc; 668} 669 670Statement *ScopeStatement::syntaxCopy() 671{ 672 return new ScopeStatement(loc, statement ? statement->syntaxCopy() : NULL, endloc); 673} 674 675ReturnStatement *ScopeStatement::isReturnStatement() 676{ 677 if (statement) 678 return statement->isReturnStatement(); 679 return NULL; 680} 681 682bool ScopeStatement::hasBreak() 683{ 684 //printf("ScopeStatement::hasBreak() %s\n", toChars()); 685 return statement ? statement->hasBreak() : false; 686} 687 688bool ScopeStatement::hasContinue() 689{ 690 return statement ? statement->hasContinue() : false; 691} 692 693/******************************** ForwardingStatement **********************/ 694 695/* Statement whose symbol table contains foreach index variables in a 696 * local scope and forwards other members to the parent scope. This 697 * wraps a statement. 698 * 699 * Also see: `ddmd.attrib.ForwardingAttribDeclaration` 700 */ 701 702ForwardingStatement::ForwardingStatement(Loc loc, ForwardingScopeDsymbol *sym, Statement *s) 703 : Statement(loc) 704{ 705 this->sym = sym; 706 assert(s); 707 this->statement = s; 708} 709 710ForwardingStatement::ForwardingStatement(Loc loc, Statement *s) 711 : Statement(loc) 712{ 713 this->sym = new ForwardingScopeDsymbol(NULL); 714 this->sym->symtab = new DsymbolTable(); 715 assert(s); 716 this->statement = s; 717} 718 719Statement *ForwardingStatement::syntaxCopy() 720{ 721 return new ForwardingStatement(loc, statement->syntaxCopy()); 722} 723 724/*********************** 725 * ForwardingStatements are distributed over the flattened 726 * sequence of statements. This prevents flattening to be 727 * "blocked" by a ForwardingStatement and is necessary, for 728 * example, to support generating scope guards with `static 729 * foreach`: 730 * 731 * static foreach(i; 0 .. 10) scope(exit) writeln(i); 732 * writeln("this is printed first"); 733 * // then, it prints 10, 9, 8, 7, ... 734 */ 735 736Statements *ForwardingStatement::flatten(Scope *sc) 737{ 738 if (!statement) 739 { 740 return NULL; 741 } 742 sc = sc->push(sym); 743 Statements *a = statement->flatten(sc); 744 sc = sc->pop(); 745 if (!a) 746 { 747 return a; 748 } 749 Statements *b = new Statements(); 750 b->setDim(a->dim); 751 for (size_t i = 0; i < a->dim; i++) 752 { 753 Statement *s = (*a)[i]; 754 (*b)[i] = s ? new ForwardingStatement(s->loc, sym, s) : NULL; 755 } 756 return b; 757} 758 759/******************************** WhileStatement ***************************/ 760 761WhileStatement::WhileStatement(Loc loc, Expression *c, Statement *b, Loc endloc) 762 : Statement(loc) 763{ 764 condition = c; 765 _body = b; 766 this->endloc = endloc; 767} 768 769Statement *WhileStatement::syntaxCopy() 770{ 771 return new WhileStatement(loc, 772 condition->syntaxCopy(), 773 _body ? _body->syntaxCopy() : NULL, 774 endloc); 775} 776 777bool WhileStatement::hasBreak() 778{ 779 return true; 780} 781 782bool WhileStatement::hasContinue() 783{ 784 return true; 785} 786 787/******************************** DoStatement ***************************/ 788 789DoStatement::DoStatement(Loc loc, Statement *b, Expression *c, Loc endloc) 790 : Statement(loc) 791{ 792 _body = b; 793 condition = c; 794 this->endloc = endloc; 795} 796 797Statement *DoStatement::syntaxCopy() 798{ 799 return new DoStatement(loc, 800 _body ? _body->syntaxCopy() : NULL, 801 condition->syntaxCopy(), 802 endloc); 803} 804 805bool DoStatement::hasBreak() 806{ 807 return true; 808} 809 810bool DoStatement::hasContinue() 811{ 812 return true; 813} 814 815/******************************** ForStatement ***************************/ 816 817ForStatement::ForStatement(Loc loc, Statement *init, Expression *condition, Expression *increment, Statement *body, Loc endloc) 818 : Statement(loc) 819{ 820 this->_init = init; 821 this->condition = condition; 822 this->increment = increment; 823 this->_body = body; 824 this->endloc = endloc; 825 this->relatedLabeled = NULL; 826} 827 828Statement *ForStatement::syntaxCopy() 829{ 830 return new ForStatement(loc, 831 _init ? _init->syntaxCopy() : NULL, 832 condition ? condition->syntaxCopy() : NULL, 833 increment ? increment->syntaxCopy() : NULL, 834 _body->syntaxCopy(), 835 endloc); 836} 837 838Statement *ForStatement::scopeCode(Scope *sc, Statement **sentry, Statement **sexception, Statement **sfinally) 839{ 840 //printf("ForStatement::scopeCode()\n"); 841 Statement::scopeCode(sc, sentry, sexception, sfinally); 842 return this; 843} 844 845bool ForStatement::hasBreak() 846{ 847 //printf("ForStatement::hasBreak()\n"); 848 return true; 849} 850 851bool ForStatement::hasContinue() 852{ 853 return true; 854} 855 856/******************************** ForeachStatement ***************************/ 857 858ForeachStatement::ForeachStatement(Loc loc, TOK op, Parameters *parameters, 859 Expression *aggr, Statement *body, Loc endloc) 860 : Statement(loc) 861{ 862 this->op = op; 863 this->parameters = parameters; 864 this->aggr = aggr; 865 this->_body = body; 866 this->endloc = endloc; 867 868 this->key = NULL; 869 this->value = NULL; 870 871 this->func = NULL; 872 873 this->cases = NULL; 874 this->gotos = NULL; 875} 876 877Statement *ForeachStatement::syntaxCopy() 878{ 879 return new ForeachStatement(loc, op, 880 Parameter::arraySyntaxCopy(parameters), 881 aggr->syntaxCopy(), 882 _body ? _body->syntaxCopy() : NULL, 883 endloc); 884} 885 886bool ForeachStatement::checkForArgTypes() 887{ 888 bool result = false; 889 890 for (size_t i = 0; i < parameters->dim; i++) 891 { 892 Parameter *p = (*parameters)[i]; 893 if (!p->type) 894 { 895 error("cannot infer type for %s", p->ident->toChars()); 896 p->type = Type::terror; 897 result = true; 898 } 899 } 900 return result; 901} 902 903bool ForeachStatement::hasBreak() 904{ 905 return true; 906} 907 908bool ForeachStatement::hasContinue() 909{ 910 return true; 911} 912 913/**************************** ForeachRangeStatement ***************************/ 914 915 916ForeachRangeStatement::ForeachRangeStatement(Loc loc, TOK op, Parameter *prm, 917 Expression *lwr, Expression *upr, Statement *body, Loc endloc) 918 : Statement(loc) 919{ 920 this->op = op; 921 this->prm = prm; 922 this->lwr = lwr; 923 this->upr = upr; 924 this->_body = body; 925 this->endloc = endloc; 926 927 this->key = NULL; 928} 929 930Statement *ForeachRangeStatement::syntaxCopy() 931{ 932 return new ForeachRangeStatement(loc, op, 933 prm->syntaxCopy(), 934 lwr->syntaxCopy(), 935 upr->syntaxCopy(), 936 _body ? _body->syntaxCopy() : NULL, 937 endloc); 938} 939 940bool ForeachRangeStatement::hasBreak() 941{ 942 return true; 943} 944 945bool ForeachRangeStatement::hasContinue() 946{ 947 return true; 948} 949 950/******************************** IfStatement ***************************/ 951 952IfStatement::IfStatement(Loc loc, Parameter *prm, Expression *condition, Statement *ifbody, Statement *elsebody, Loc endloc) 953 : Statement(loc) 954{ 955 this->prm = prm; 956 this->condition = condition; 957 this->ifbody = ifbody; 958 this->elsebody = elsebody; 959 this->endloc = endloc; 960 this->match = NULL; 961} 962 963Statement *IfStatement::syntaxCopy() 964{ 965 return new IfStatement(loc, 966 prm ? prm->syntaxCopy() : NULL, 967 condition->syntaxCopy(), 968 ifbody ? ifbody->syntaxCopy() : NULL, 969 elsebody ? elsebody->syntaxCopy() : NULL, 970 endloc); 971} 972 973/******************************** ConditionalStatement ***************************/ 974 975ConditionalStatement::ConditionalStatement(Loc loc, Condition *condition, Statement *ifbody, Statement *elsebody) 976 : Statement(loc) 977{ 978 this->condition = condition; 979 this->ifbody = ifbody; 980 this->elsebody = elsebody; 981} 982 983Statement *ConditionalStatement::syntaxCopy() 984{ 985 return new ConditionalStatement(loc, 986 condition->syntaxCopy(), 987 ifbody->syntaxCopy(), 988 elsebody ? elsebody->syntaxCopy() : NULL); 989} 990 991Statements *ConditionalStatement::flatten(Scope *sc) 992{ 993 Statement *s; 994 995 //printf("ConditionalStatement::flatten()\n"); 996 if (condition->include(sc, NULL)) 997 { 998 DebugCondition *dc = condition->isDebugCondition(); 999 if (dc) 1000 s = new DebugStatement(loc, ifbody); 1001 else 1002 s = ifbody; 1003 } 1004 else 1005 s = elsebody; 1006 1007 Statements *a = new Statements(); 1008 a->push(s); 1009 return a; 1010} 1011 1012/******************************** StaticForeachStatement ********************/ 1013 1014/* Static foreach statements, like: 1015 * void main() 1016 * { 1017 * static foreach(i; 0 .. 10) 1018 * { 1019 * pragma(msg, i); 1020 * } 1021 * } 1022 */ 1023 1024StaticForeachStatement::StaticForeachStatement(Loc loc, StaticForeach *sfe) 1025 : Statement(loc) 1026{ 1027 this->sfe = sfe; 1028} 1029 1030Statement *StaticForeachStatement::syntaxCopy() 1031{ 1032 return new StaticForeachStatement(loc, sfe->syntaxCopy()); 1033} 1034 1035Statements *StaticForeachStatement::flatten(Scope *sc) 1036{ 1037 staticForeachPrepare(sfe, sc); 1038 if (staticForeachReady(sfe)) 1039 { 1040 Statement *s = makeTupleForeachStatic(sc, sfe->aggrfe, sfe->needExpansion); 1041 Statements *result = s->flatten(sc); 1042 if (result) 1043 { 1044 return result; 1045 } 1046 result = new Statements(); 1047 result->push(s); 1048 return result; 1049 } 1050 else 1051 { 1052 Statements *result = new Statements(); 1053 result->push(new ErrorStatement()); 1054 return result; 1055 } 1056} 1057 1058/******************************** PragmaStatement ***************************/ 1059 1060PragmaStatement::PragmaStatement(Loc loc, Identifier *ident, Expressions *args, Statement *body) 1061 : Statement(loc) 1062{ 1063 this->ident = ident; 1064 this->args = args; 1065 this->_body = body; 1066} 1067 1068Statement *PragmaStatement::syntaxCopy() 1069{ 1070 return new PragmaStatement(loc, ident, 1071 Expression::arraySyntaxCopy(args), 1072 _body ? _body->syntaxCopy() : NULL); 1073} 1074 1075/******************************** StaticAssertStatement ***************************/ 1076 1077StaticAssertStatement::StaticAssertStatement(StaticAssert *sa) 1078 : Statement(sa->loc) 1079{ 1080 this->sa = sa; 1081} 1082 1083Statement *StaticAssertStatement::syntaxCopy() 1084{ 1085 return new StaticAssertStatement((StaticAssert *)sa->syntaxCopy(NULL)); 1086} 1087 1088/******************************** SwitchStatement ***************************/ 1089 1090SwitchStatement::SwitchStatement(Loc loc, Expression *c, Statement *b, bool isFinal) 1091 : Statement(loc) 1092{ 1093 this->condition = c; 1094 this->_body = b; 1095 this->isFinal = isFinal; 1096 sdefault = NULL; 1097 tf = NULL; 1098 cases = NULL; 1099 hasNoDefault = 0; 1100 hasVars = 0; 1101 lastVar = NULL; 1102} 1103 1104Statement *SwitchStatement::syntaxCopy() 1105{ 1106 return new SwitchStatement(loc, 1107 condition->syntaxCopy(), 1108 _body->syntaxCopy(), 1109 isFinal); 1110} 1111 1112bool SwitchStatement::hasBreak() 1113{ 1114 return true; 1115} 1116 1117static bool checkVar(SwitchStatement *s, VarDeclaration *vd) 1118{ 1119 if (!vd || vd->isDataseg() || (vd->storage_class & STCmanifest)) 1120 return false; 1121 1122 VarDeclaration *last = s->lastVar; 1123 while (last && last != vd) 1124 last = last->lastVar; 1125 if (last == vd) 1126 { 1127 // All good, the label's scope has no variables 1128 } 1129 else if (vd->storage_class & STCexptemp) 1130 { 1131 // Lifetime ends at end of expression, so no issue with skipping the statement 1132 } 1133 else if (vd->ident == Id::withSym) 1134 { 1135 s->deprecation("'switch' skips declaration of 'with' temporary at %s", vd->loc.toChars()); 1136 return true; 1137 } 1138 else 1139 { 1140 s->deprecation("'switch' skips declaration of variable %s at %s", vd->toPrettyChars(), vd->loc.toChars()); 1141 return true; 1142 } 1143 1144 return false; 1145} 1146 1147bool SwitchStatement::checkLabel() 1148{ 1149 const bool error = true; 1150 1151 if (sdefault && checkVar(this, sdefault->lastVar)) 1152 return !error; // return error once fully deprecated 1153 1154 for (size_t i = 0; i < cases->dim; i++) 1155 { 1156 CaseStatement *scase = (*cases)[i]; 1157 if (scase && checkVar(this, scase->lastVar)) 1158 return !error; // return error once fully deprecated 1159 } 1160 return !error; 1161} 1162 1163/******************************** CaseStatement ***************************/ 1164 1165CaseStatement::CaseStatement(Loc loc, Expression *exp, Statement *s) 1166 : Statement(loc) 1167{ 1168 this->exp = exp; 1169 this->statement = s; 1170 index = 0; 1171 lastVar = NULL; 1172} 1173 1174Statement *CaseStatement::syntaxCopy() 1175{ 1176 return new CaseStatement(loc, 1177 exp->syntaxCopy(), 1178 statement->syntaxCopy()); 1179} 1180 1181int CaseStatement::compare(RootObject *obj) 1182{ 1183 // Sort cases so we can do an efficient lookup 1184 CaseStatement *cs2 = (CaseStatement *)(obj); 1185 1186 return exp->compare(cs2->exp); 1187} 1188 1189/******************************** CaseRangeStatement ***************************/ 1190 1191 1192CaseRangeStatement::CaseRangeStatement(Loc loc, Expression *first, 1193 Expression *last, Statement *s) 1194 : Statement(loc) 1195{ 1196 this->first = first; 1197 this->last = last; 1198 this->statement = s; 1199} 1200 1201Statement *CaseRangeStatement::syntaxCopy() 1202{ 1203 return new CaseRangeStatement(loc, 1204 first->syntaxCopy(), 1205 last->syntaxCopy(), 1206 statement->syntaxCopy()); 1207} 1208 1209/******************************** DefaultStatement ***************************/ 1210 1211DefaultStatement::DefaultStatement(Loc loc, Statement *s) 1212 : Statement(loc) 1213{ 1214 this->statement = s; 1215 this->lastVar = NULL; 1216} 1217 1218Statement *DefaultStatement::syntaxCopy() 1219{ 1220 return new DefaultStatement(loc, statement->syntaxCopy()); 1221} 1222 1223/******************************** GotoDefaultStatement ***************************/ 1224 1225GotoDefaultStatement::GotoDefaultStatement(Loc loc) 1226 : Statement(loc) 1227{ 1228 sw = NULL; 1229} 1230 1231Statement *GotoDefaultStatement::syntaxCopy() 1232{ 1233 return new GotoDefaultStatement(loc); 1234} 1235 1236/******************************** GotoCaseStatement ***************************/ 1237 1238GotoCaseStatement::GotoCaseStatement(Loc loc, Expression *exp) 1239 : Statement(loc) 1240{ 1241 cs = NULL; 1242 this->exp = exp; 1243} 1244 1245Statement *GotoCaseStatement::syntaxCopy() 1246{ 1247 return new GotoCaseStatement(loc, exp ? exp->syntaxCopy() : NULL); 1248} 1249 1250/******************************** SwitchErrorStatement ***************************/ 1251 1252SwitchErrorStatement::SwitchErrorStatement(Loc loc) 1253 : Statement(loc) 1254{ 1255} 1256 1257/******************************** ReturnStatement ***************************/ 1258 1259ReturnStatement::ReturnStatement(Loc loc, Expression *exp) 1260 : Statement(loc) 1261{ 1262 this->exp = exp; 1263 this->caseDim = 0; 1264} 1265 1266Statement *ReturnStatement::syntaxCopy() 1267{ 1268 return new ReturnStatement(loc, exp ? exp->syntaxCopy() : NULL); 1269} 1270 1271/******************************** BreakStatement ***************************/ 1272 1273BreakStatement::BreakStatement(Loc loc, Identifier *ident) 1274 : Statement(loc) 1275{ 1276 this->ident = ident; 1277} 1278 1279Statement *BreakStatement::syntaxCopy() 1280{ 1281 return new BreakStatement(loc, ident); 1282} 1283 1284/******************************** ContinueStatement ***************************/ 1285 1286ContinueStatement::ContinueStatement(Loc loc, Identifier *ident) 1287 : Statement(loc) 1288{ 1289 this->ident = ident; 1290} 1291 1292Statement *ContinueStatement::syntaxCopy() 1293{ 1294 return new ContinueStatement(loc, ident); 1295} 1296 1297/******************************** SynchronizedStatement ***************************/ 1298 1299SynchronizedStatement::SynchronizedStatement(Loc loc, Expression *exp, Statement *body) 1300 : Statement(loc) 1301{ 1302 this->exp = exp; 1303 this->_body = body; 1304} 1305 1306Statement *SynchronizedStatement::syntaxCopy() 1307{ 1308 return new SynchronizedStatement(loc, 1309 exp ? exp->syntaxCopy() : NULL, 1310 _body ? _body->syntaxCopy() : NULL); 1311} 1312 1313bool SynchronizedStatement::hasBreak() 1314{ 1315 return false; //true; 1316} 1317 1318bool SynchronizedStatement::hasContinue() 1319{ 1320 return false; //true; 1321} 1322 1323/******************************** WithStatement ***************************/ 1324 1325WithStatement::WithStatement(Loc loc, Expression *exp, Statement *body, Loc endloc) 1326 : Statement(loc) 1327{ 1328 this->exp = exp; 1329 this->_body = body; 1330 this->endloc = endloc; 1331 wthis = NULL; 1332} 1333 1334Statement *WithStatement::syntaxCopy() 1335{ 1336 return new WithStatement(loc, 1337 exp->syntaxCopy(), 1338 _body ? _body->syntaxCopy() : NULL, endloc); 1339} 1340 1341/******************************** TryCatchStatement ***************************/ 1342 1343TryCatchStatement::TryCatchStatement(Loc loc, Statement *body, Catches *catches) 1344 : Statement(loc) 1345{ 1346 this->_body = body; 1347 this->catches = catches; 1348} 1349 1350Statement *TryCatchStatement::syntaxCopy() 1351{ 1352 Catches *a = new Catches(); 1353 a->setDim(catches->dim); 1354 for (size_t i = 0; i < a->dim; i++) 1355 { 1356 Catch *c = (*catches)[i]; 1357 (*a)[i] = c->syntaxCopy(); 1358 } 1359 return new TryCatchStatement(loc, _body->syntaxCopy(), a); 1360} 1361 1362bool TryCatchStatement::hasBreak() 1363{ 1364 return false; 1365} 1366 1367/******************************** Catch ***************************/ 1368 1369Catch::Catch(Loc loc, Type *t, Identifier *id, Statement *handler) 1370{ 1371 //printf("Catch(%s, loc = %s)\n", id->toChars(), loc.toChars()); 1372 this->loc = loc; 1373 this->type = t; 1374 this->ident = id; 1375 this->handler = handler; 1376 var = NULL; 1377 errors = false; 1378 internalCatch = false; 1379} 1380 1381Catch *Catch::syntaxCopy() 1382{ 1383 Catch *c = new Catch(loc, 1384 type ? type->syntaxCopy() : getThrowable(), 1385 ident, 1386 (handler ? handler->syntaxCopy() : NULL)); 1387 c->internalCatch = internalCatch; 1388 return c; 1389} 1390 1391/****************************** TryFinallyStatement ***************************/ 1392 1393TryFinallyStatement::TryFinallyStatement(Loc loc, Statement *body, Statement *finalbody) 1394 : Statement(loc) 1395{ 1396 this->_body = body; 1397 this->finalbody = finalbody; 1398} 1399 1400TryFinallyStatement *TryFinallyStatement::create(Loc loc, Statement *body, Statement *finalbody) 1401{ 1402 return new TryFinallyStatement(loc, body, finalbody); 1403} 1404 1405Statement *TryFinallyStatement::syntaxCopy() 1406{ 1407 return new TryFinallyStatement(loc, 1408 _body->syntaxCopy(), finalbody->syntaxCopy()); 1409} 1410 1411bool TryFinallyStatement::hasBreak() 1412{ 1413 return false; //true; 1414} 1415 1416bool TryFinallyStatement::hasContinue() 1417{ 1418 return false; //true; 1419} 1420 1421/****************************** OnScopeStatement ***************************/ 1422 1423OnScopeStatement::OnScopeStatement(Loc loc, TOK tok, Statement *statement) 1424 : Statement(loc) 1425{ 1426 this->tok = tok; 1427 this->statement = statement; 1428} 1429 1430Statement *OnScopeStatement::syntaxCopy() 1431{ 1432 return new OnScopeStatement(loc, tok, statement->syntaxCopy()); 1433} 1434 1435Statement *OnScopeStatement::scopeCode(Scope *sc, Statement **sentry, Statement **sexception, Statement **sfinally) 1436{ 1437 //printf("OnScopeStatement::scopeCode()\n"); 1438 //print(); 1439 *sentry = NULL; 1440 *sexception = NULL; 1441 *sfinally = NULL; 1442 1443 Statement *s = new PeelStatement(statement); 1444 1445 switch (tok) 1446 { 1447 case TOKon_scope_exit: 1448 *sfinally = s; 1449 break; 1450 1451 case TOKon_scope_failure: 1452 *sexception = s; 1453 break; 1454 1455 case TOKon_scope_success: 1456 { 1457 /* Create: 1458 * sentry: bool x = false; 1459 * sexception: x = true; 1460 * sfinally: if (!x) statement; 1461 */ 1462 VarDeclaration *v = copyToTemp(0, "__os", new IntegerExp(Loc(), 0, Type::tbool)); 1463 v->semantic(sc); 1464 *sentry = new ExpStatement(loc, v); 1465 1466 Expression *e = new IntegerExp(Loc(), 1, Type::tbool); 1467 e = new AssignExp(Loc(), new VarExp(Loc(), v), e); 1468 *sexception = new ExpStatement(Loc(), e); 1469 1470 e = new VarExp(Loc(), v); 1471 e = new NotExp(Loc(), e); 1472 *sfinally = new IfStatement(Loc(), NULL, e, s, NULL, Loc()); 1473 1474 break; 1475 } 1476 1477 default: 1478 assert(0); 1479 } 1480 return NULL; 1481} 1482 1483/******************************** ThrowStatement ***************************/ 1484 1485ThrowStatement::ThrowStatement(Loc loc, Expression *exp) 1486 : Statement(loc) 1487{ 1488 this->exp = exp; 1489 this->internalThrow = false; 1490} 1491 1492Statement *ThrowStatement::syntaxCopy() 1493{ 1494 ThrowStatement *s = new ThrowStatement(loc, exp->syntaxCopy()); 1495 s->internalThrow = internalThrow; 1496 return s; 1497} 1498 1499/******************************** DebugStatement **************************/ 1500 1501DebugStatement::DebugStatement(Loc loc, Statement *statement) 1502 : Statement(loc) 1503{ 1504 this->statement = statement; 1505} 1506 1507Statement *DebugStatement::syntaxCopy() 1508{ 1509 return new DebugStatement(loc, 1510 statement ? statement->syntaxCopy() : NULL); 1511} 1512 1513Statements *DebugStatement::flatten(Scope *sc) 1514{ 1515 Statements *a = statement ? statement->flatten(sc) : NULL; 1516 if (a) 1517 { 1518 for (size_t i = 0; i < a->dim; i++) 1519 { Statement *s = (*a)[i]; 1520 1521 s = new DebugStatement(loc, s); 1522 (*a)[i] = s; 1523 } 1524 } 1525 1526 return a; 1527} 1528 1529/******************************** GotoStatement ***************************/ 1530 1531GotoStatement::GotoStatement(Loc loc, Identifier *ident) 1532 : Statement(loc) 1533{ 1534 this->ident = ident; 1535 this->label = NULL; 1536 this->tf = NULL; 1537 this->os = NULL; 1538 this->lastVar = NULL; 1539} 1540 1541Statement *GotoStatement::syntaxCopy() 1542{ 1543 return new GotoStatement(loc, ident); 1544} 1545 1546bool GotoStatement::checkLabel() 1547{ 1548 if (!label->statement) 1549 { 1550 error("label '%s' is undefined", label->toChars()); 1551 return true; 1552 } 1553 1554 if (label->statement->os != os) 1555 { 1556 if (os && os->tok == TOKon_scope_failure && !label->statement->os) 1557 { 1558 // Jump out from scope(failure) block is allowed. 1559 } 1560 else 1561 { 1562 if (label->statement->os) 1563 error("cannot goto in to %s block", Token::toChars(label->statement->os->tok)); 1564 else 1565 error("cannot goto out of %s block", Token::toChars(os->tok)); 1566 return true; 1567 } 1568 } 1569 1570 if (label->statement->tf != tf) 1571 { 1572 error("cannot goto in or out of finally block"); 1573 return true; 1574 } 1575 1576 VarDeclaration *vd = label->statement->lastVar; 1577 if (!vd || vd->isDataseg() || (vd->storage_class & STCmanifest)) 1578 return false; 1579 1580 VarDeclaration *last = lastVar; 1581 while (last && last != vd) 1582 last = last->lastVar; 1583 if (last == vd) 1584 { 1585 // All good, the label's scope has no variables 1586 } 1587 else if (vd->ident == Id::withSym) 1588 { 1589 error("goto skips declaration of with temporary at %s", vd->loc.toChars()); 1590 return true; 1591 } 1592 else 1593 { 1594 error("goto skips declaration of variable %s at %s", vd->toPrettyChars(), vd->loc.toChars()); 1595 return true; 1596 } 1597 1598 return false; 1599} 1600 1601/******************************** LabelStatement ***************************/ 1602 1603LabelStatement::LabelStatement(Loc loc, Identifier *ident, Statement *statement) 1604 : Statement(loc) 1605{ 1606 this->ident = ident; 1607 this->statement = statement; 1608 this->tf = NULL; 1609 this->os = NULL; 1610 this->lastVar = NULL; 1611 this->gotoTarget = NULL; 1612 this->breaks = false; 1613} 1614 1615Statement *LabelStatement::syntaxCopy() 1616{ 1617 return new LabelStatement(loc, ident, statement ? statement->syntaxCopy() : NULL); 1618} 1619 1620Statement *LabelStatement::scopeCode(Scope *sc, Statement **sentry, Statement **sexit, Statement **sfinally) 1621{ 1622 //printf("LabelStatement::scopeCode()\n"); 1623 if (statement) 1624 statement = statement->scopeCode(sc, sentry, sexit, sfinally); 1625 else 1626 { 1627 *sentry = NULL; 1628 *sexit = NULL; 1629 *sfinally = NULL; 1630 } 1631 return this; 1632} 1633 1634Statements *LabelStatement::flatten(Scope *sc) 1635{ 1636 Statements *a = NULL; 1637 1638 if (statement) 1639 { 1640 a = statement->flatten(sc); 1641 if (a) 1642 { 1643 if (!a->dim) 1644 { 1645 a->push(new ExpStatement(loc, (Expression *)NULL)); 1646 } 1647 1648 // reuse 'this' LabelStatement 1649 this->statement = (*a)[0]; 1650 (*a)[0] = this; 1651 } 1652 } 1653 1654 return a; 1655} 1656 1657/******************************** LabelDsymbol ***************************/ 1658 1659LabelDsymbol::LabelDsymbol(Identifier *ident) 1660 : Dsymbol(ident) 1661{ 1662 statement = NULL; 1663} 1664 1665LabelDsymbol *LabelDsymbol::create(Identifier *ident) 1666{ 1667 return new LabelDsymbol(ident); 1668} 1669 1670LabelDsymbol *LabelDsymbol::isLabel() // is this a LabelDsymbol()? 1671{ 1672 return this; 1673} 1674 1675 1676/************************ AsmStatement ***************************************/ 1677 1678AsmStatement::AsmStatement(Loc loc, Token *tokens) 1679 : Statement(loc) 1680{ 1681 this->tokens = tokens; 1682} 1683 1684Statement *AsmStatement::syntaxCopy() 1685{ 1686 return new AsmStatement(loc, tokens); 1687} 1688 1689 1690/************************ InlineAsmStatement **********************************/ 1691 1692InlineAsmStatement::InlineAsmStatement(Loc loc, Token *tokens) 1693 : AsmStatement(loc, tokens) 1694{ 1695 asmcode = NULL; 1696 asmalign = 0; 1697 refparam = false; 1698 naked = false; 1699 regs = 0; 1700} 1701 1702Statement *InlineAsmStatement::syntaxCopy() 1703{ 1704 return new InlineAsmStatement(loc, tokens); 1705} 1706 1707 1708/************************ GccAsmStatement ***************************************/ 1709 1710GccAsmStatement::GccAsmStatement(Loc loc, Token *tokens) 1711 : AsmStatement(loc, tokens) 1712{ 1713 this->stc = STCundefined; 1714 this->insn = NULL; 1715 this->args = NULL; 1716 this->outputargs = 0; 1717 this->names = NULL; 1718 this->constraints = NULL; 1719 this->clobbers = NULL; 1720 this->labels = NULL; 1721 this->gotos = NULL; 1722} 1723 1724Statement *GccAsmStatement::syntaxCopy() 1725{ 1726 return new GccAsmStatement(loc, tokens); 1727} 1728 1729/************************ CompoundAsmStatement ***************************************/ 1730 1731CompoundAsmStatement::CompoundAsmStatement(Loc loc, Statements *s, StorageClass stc) 1732 : CompoundStatement(loc, s) 1733{ 1734 this->stc = stc; 1735} 1736 1737CompoundAsmStatement *CompoundAsmStatement::syntaxCopy() 1738{ 1739 Statements *a = new Statements(); 1740 a->setDim(statements->dim); 1741 for (size_t i = 0; i < statements->dim; i++) 1742 { 1743 Statement *s = (*statements)[i]; 1744 (*a)[i] = s ? s->syntaxCopy() : NULL; 1745 } 1746 return new CompoundAsmStatement(loc, a, stc); 1747} 1748 1749Statements *CompoundAsmStatement::flatten(Scope *) 1750{ 1751 return NULL; 1752} 1753 1754/************************ ImportStatement ***************************************/ 1755 1756ImportStatement::ImportStatement(Loc loc, Dsymbols *imports) 1757 : Statement(loc) 1758{ 1759 this->imports = imports; 1760} 1761 1762Statement *ImportStatement::syntaxCopy() 1763{ 1764 Dsymbols *m = new Dsymbols(); 1765 m->setDim(imports->dim); 1766 for (size_t i = 0; i < imports->dim; i++) 1767 { 1768 Dsymbol *s = (*imports)[i]; 1769 (*m)[i] = s->syntaxCopy(NULL); 1770 } 1771 return new ImportStatement(loc, m); 1772} 1773