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/expression.c 9 */ 10 11#include "root/dsystem.h" 12#include "root/rmem.h" 13#include "root/root.h" 14 15#include "errors.h" 16#include "mtype.h" 17#include "init.h" 18#include "expression.h" 19#include "template.h" 20#include "utf.h" 21#include "enum.h" 22#include "scope.h" 23#include "statement.h" 24#include "declaration.h" 25#include "aggregate.h" 26#include "import.h" 27#include "id.h" 28#include "dsymbol.h" 29#include "module.h" 30#include "attrib.h" 31#include "hdrgen.h" 32#include "parse.h" 33#include "doc.h" 34#include "root/aav.h" 35#include "nspace.h" 36#include "ctfe.h" 37#include "target.h" 38 39bool walkPostorder(Expression *e, StoppableVisitor *v); 40bool checkParamArgumentEscape(Scope *sc, FuncDeclaration *fdc, Identifier *par, Expression *arg, bool gag); 41bool checkAccess(AggregateDeclaration *ad, Loc loc, Scope *sc, Dsymbol *smember); 42VarDeclaration *copyToTemp(StorageClass stc, const char *name, Expression *e); 43Expression *extractSideEffect(Scope *sc, const char *name, Expression **e0, Expression *e, bool alwaysCopy = false); 44char *MODtoChars(MOD mod); 45bool MODimplicitConv(MOD modfrom, MOD modto); 46MOD MODmerge(MOD mod1, MOD mod2); 47void MODMatchToBuffer(OutBuffer *buf, unsigned char lhsMod, unsigned char rhsMod); 48Expression *trySemantic(Expression *e, Scope *sc); 49Expression *semantic(Expression *e, Scope *sc); 50Expression *semanticX(DotIdExp *exp, Scope *sc); 51Expression *semanticY(DotIdExp *exp, Scope *sc, int flag); 52Expression *semanticY(DotTemplateInstanceExp *exp, Scope *sc, int flag); 53Expression *resolve(Loc loc, Scope *sc, Dsymbol *s, bool hasOverloads); 54bool checkUnsafeAccess(Scope *sc, Expression *e, bool readonly, bool printmsg); 55 56/************************************************************* 57 * Given var, we need to get the 58 * right 'this' pointer if var is in an outer class, but our 59 * existing 'this' pointer is in an inner class. 60 * Input: 61 * e1 existing 'this' 62 * ad struct or class we need the correct 'this' for 63 * var the specific member of ad we're accessing 64 */ 65 66Expression *getRightThis(Loc loc, Scope *sc, AggregateDeclaration *ad, 67 Expression *e1, Declaration *var, int flag = 0) 68{ 69 //printf("\ngetRightThis(e1 = %s, ad = %s, var = %s)\n", e1->toChars(), ad->toChars(), var->toChars()); 70 L1: 71 Type *t = e1->type->toBasetype(); 72 //printf("e1->type = %s, var->type = %s\n", e1->type->toChars(), var->type->toChars()); 73 74 /* If e1 is not the 'this' pointer for ad 75 */ 76 if (ad && 77 !(t->ty == Tpointer && t->nextOf()->ty == Tstruct && 78 ((TypeStruct *)t->nextOf())->sym == ad) 79 && 80 !(t->ty == Tstruct && 81 ((TypeStruct *)t)->sym == ad) 82 ) 83 { 84 ClassDeclaration *cd = ad->isClassDeclaration(); 85 ClassDeclaration *tcd = t->isClassHandle(); 86 87 /* e1 is the right this if ad is a base class of e1 88 */ 89 if (!cd || !tcd || 90 !(tcd == cd || cd->isBaseOf(tcd, NULL)) 91 ) 92 { 93 /* Only classes can be inner classes with an 'outer' 94 * member pointing to the enclosing class instance 95 */ 96 if (tcd && tcd->isNested()) 97 { 98 /* e1 is the 'this' pointer for an inner class: tcd. 99 * Rewrite it as the 'this' pointer for the outer class. 100 */ 101 102 e1 = new DotVarExp(loc, e1, tcd->vthis); 103 e1->type = tcd->vthis->type; 104 e1->type = e1->type->addMod(t->mod); 105 // Do not call checkNestedRef() 106 //e1 = semantic(e1, sc); 107 108 // Skip up over nested functions, and get the enclosing 109 // class type. 110 int n = 0; 111 Dsymbol *s; 112 for (s = tcd->toParent(); 113 s && s->isFuncDeclaration(); 114 s = s->toParent()) 115 { 116 FuncDeclaration *f = s->isFuncDeclaration(); 117 if (f->vthis) 118 { 119 //printf("rewriting e1 to %s's this\n", f->toChars()); 120 n++; 121 e1 = new VarExp(loc, f->vthis); 122 } 123 else 124 { 125 e1->error("need 'this' of type %s to access member %s" 126 " from static function %s", 127 ad->toChars(), var->toChars(), f->toChars()); 128 e1 = new ErrorExp(); 129 return e1; 130 } 131 } 132 if (s && s->isClassDeclaration()) 133 { 134 e1->type = s->isClassDeclaration()->type; 135 e1->type = e1->type->addMod(t->mod); 136 if (n > 1) 137 e1 = semantic(e1, sc); 138 } 139 else 140 e1 = semantic(e1, sc); 141 goto L1; 142 } 143 144 /* Can't find a path from e1 to ad 145 */ 146 if (flag) 147 return NULL; 148 e1->error("this for %s needs to be type %s not type %s", 149 var->toChars(), ad->toChars(), t->toChars()); 150 return new ErrorExp(); 151 } 152 } 153 return e1; 154} 155 156/***************************************** 157 * Determine if 'this' is available. 158 * If it is, return the FuncDeclaration that has it. 159 */ 160 161FuncDeclaration *hasThis(Scope *sc) 162{ 163 //printf("hasThis()\n"); 164 Dsymbol *p = sc->parent; 165 while (p && p->isTemplateMixin()) 166 p = p->parent; 167 FuncDeclaration *fdthis = p ? p->isFuncDeclaration() : NULL; 168 //printf("fdthis = %p, '%s'\n", fdthis, fdthis ? fdthis->toChars() : ""); 169 170 // Go upwards until we find the enclosing member function 171 FuncDeclaration *fd = fdthis; 172 while (1) 173 { 174 if (!fd) 175 { 176 goto Lno; 177 } 178 if (!fd->isNested()) 179 break; 180 181 Dsymbol *parent = fd->parent; 182 while (1) 183 { 184 if (!parent) 185 goto Lno; 186 TemplateInstance *ti = parent->isTemplateInstance(); 187 if (ti) 188 parent = ti->parent; 189 else 190 break; 191 } 192 fd = parent->isFuncDeclaration(); 193 } 194 195 if (!fd->isThis()) 196 { //printf("test '%s'\n", fd->toChars()); 197 goto Lno; 198 } 199 200 assert(fd->vthis); 201 return fd; 202 203Lno: 204 return NULL; // don't have 'this' available 205} 206 207bool isNeedThisScope(Scope *sc, Declaration *d) 208{ 209 if (sc->intypeof == 1) 210 return false; 211 212 AggregateDeclaration *ad = d->isThis(); 213 if (!ad) 214 return false; 215 //printf("d = %s, ad = %s\n", d->toChars(), ad->toChars()); 216 217 for (Dsymbol *s = sc->parent; s; s = s->toParent2()) 218 { 219 //printf("\ts = %s %s, toParent2() = %p\n", s->kind(), s->toChars(), s->toParent2()); 220 if (AggregateDeclaration *ad2 = s->isAggregateDeclaration()) 221 { 222 if (ad2 == ad) 223 return false; 224 else if (ad2->isNested()) 225 continue; 226 else 227 return true; 228 } 229 if (FuncDeclaration *f = s->isFuncDeclaration()) 230 { 231 if (f->isMember2()) 232 break; 233 } 234 } 235 return true; 236} 237 238/*************************************** 239 * Pull out any properties. 240 */ 241 242Expression *resolvePropertiesX(Scope *sc, Expression *e1, Expression *e2 = NULL) 243{ 244 //printf("resolvePropertiesX, e1 = %s %s, e2 = %s\n", Token::toChars(e1->op), e1->toChars(), e2 ? e2->toChars() : NULL); 245 Loc loc = e1->loc; 246 247 OverloadSet *os; 248 Dsymbol *s; 249 Objects *tiargs; 250 Type *tthis; 251 if (e1->op == TOKdot) 252 { 253 DotExp *de = (DotExp *)e1; 254 if (de->e2->op == TOKoverloadset) 255 { 256 tiargs = NULL; 257 tthis = de->e1->type; 258 os = ((OverExp *)de->e2)->vars; 259 goto Los; 260 } 261 } 262 else if (e1->op == TOKoverloadset) 263 { 264 tiargs = NULL; 265 tthis = NULL; 266 os = ((OverExp *)e1)->vars; 267 Los: 268 assert(os); 269 FuncDeclaration *fd = NULL; 270 if (e2) 271 { 272 e2 = semantic(e2, sc); 273 if (e2->op == TOKerror) 274 return new ErrorExp(); 275 e2 = resolveProperties(sc, e2); 276 277 Expressions a; 278 a.push(e2); 279 280 for (size_t i = 0; i < os->a.dim; i++) 281 { 282 FuncDeclaration *f = resolveFuncCall(loc, sc, os->a[i], tiargs, tthis, &a, 1); 283 if (f) 284 { 285 if (f->errors) 286 return new ErrorExp(); 287 fd = f; 288 assert(fd->type->ty == Tfunction); 289 } 290 } 291 if (fd) 292 { 293 Expression *e = new CallExp(loc, e1, e2); 294 return semantic(e, sc); 295 } 296 } 297 { 298 for (size_t i = 0; i < os->a.dim; i++) 299 { 300 FuncDeclaration *f = resolveFuncCall(loc, sc, os->a[i], tiargs, tthis, NULL, 1); 301 if (f) 302 { 303 if (f->errors) 304 return new ErrorExp(); 305 fd = f; 306 assert(fd->type->ty == Tfunction); 307 TypeFunction *tf = (TypeFunction *)fd->type; 308 if (!tf->isref && e2) 309 goto Leproplvalue; 310 } 311 } 312 if (fd) 313 { 314 Expression *e = new CallExp(loc, e1); 315 if (e2) 316 e = new AssignExp(loc, e, e2); 317 return semantic(e, sc); 318 } 319 } 320 if (e2) 321 goto Leprop; 322 } 323 else if (e1->op == TOKdotti) 324 { 325 DotTemplateInstanceExp* dti = (DotTemplateInstanceExp *)e1; 326 if (!dti->findTempDecl(sc)) 327 goto Leprop; 328 if (!dti->ti->semanticTiargs(sc)) 329 goto Leprop; 330 tiargs = dti->ti->tiargs; 331 tthis = dti->e1->type; 332 if ((os = dti->ti->tempdecl->isOverloadSet()) != NULL) 333 goto Los; 334 if ((s = dti->ti->tempdecl) != NULL) 335 goto Lfd; 336 } 337 else if (e1->op == TOKdottd) 338 { 339 DotTemplateExp *dte = (DotTemplateExp *)e1; 340 s = dte->td; 341 tiargs = NULL; 342 tthis = dte->e1->type; 343 goto Lfd; 344 } 345 else if (e1->op == TOKscope) 346 { 347 s = ((ScopeExp *)e1)->sds; 348 TemplateInstance *ti = s->isTemplateInstance(); 349 if (ti && !ti->semanticRun && ti->tempdecl) 350 { 351 //assert(ti->needsTypeInference(sc)); 352 if (!ti->semanticTiargs(sc)) 353 goto Leprop; 354 tiargs = ti->tiargs; 355 tthis = NULL; 356 if ((os = ti->tempdecl->isOverloadSet()) != NULL) 357 goto Los; 358 if ((s = ti->tempdecl) != NULL) 359 goto Lfd; 360 } 361 } 362 else if (e1->op == TOKtemplate) 363 { 364 s = ((TemplateExp *)e1)->td; 365 tiargs = NULL; 366 tthis = NULL; 367 goto Lfd; 368 } 369 else if (e1->op == TOKdotvar && e1->type && e1->type->toBasetype()->ty == Tfunction) 370 { 371 DotVarExp *dve = (DotVarExp *)e1; 372 s = dve->var->isFuncDeclaration(); 373 tiargs = NULL; 374 tthis = dve->e1->type; 375 goto Lfd; 376 } 377 else if (e1->op == TOKvar && e1->type && e1->type->toBasetype()->ty == Tfunction) 378 { 379 s = ((VarExp *)e1)->var->isFuncDeclaration(); 380 tiargs = NULL; 381 tthis = NULL; 382 Lfd: 383 assert(s); 384 if (e2) 385 { 386 e2 = semantic(e2, sc); 387 if (e2->op == TOKerror) 388 return new ErrorExp(); 389 e2 = resolveProperties(sc, e2); 390 391 Expressions a; 392 a.push(e2); 393 394 FuncDeclaration *fd = resolveFuncCall(loc, sc, s, tiargs, tthis, &a, 1); 395 if (fd && fd->type) 396 { 397 if (fd->errors) 398 return new ErrorExp(); 399 assert(fd->type->ty == Tfunction); 400 Expression *e = new CallExp(loc, e1, e2); 401 return semantic(e, sc); 402 } 403 } 404 { 405 FuncDeclaration *fd = resolveFuncCall(loc, sc, s, tiargs, tthis, NULL, 1); 406 if (fd && fd->type) 407 { 408 if (fd->errors) 409 return new ErrorExp(); 410 assert(fd->type->ty == Tfunction); 411 TypeFunction *tf = (TypeFunction *)fd->type; 412 if (!e2 || tf->isref) 413 { 414 Expression *e = new CallExp(loc, e1); 415 if (e2) 416 e = new AssignExp(loc, e, e2); 417 return semantic(e, sc); 418 } 419 } 420 } 421 if (FuncDeclaration *fd = s->isFuncDeclaration()) 422 { 423 // Keep better diagnostic message for invalid property usage of functions 424 assert(fd->type->ty == Tfunction); 425 Expression *e = new CallExp(loc, e1, e2); 426 return semantic(e, sc); 427 } 428 if (e2) 429 goto Leprop; 430 } 431 if (e1->op == TOKvar) 432 { 433 VarExp *ve = (VarExp *)e1; 434 VarDeclaration *v = ve->var->isVarDeclaration(); 435 if (v && ve->checkPurity(sc, v)) 436 return new ErrorExp(); 437 } 438 if (e2) 439 return NULL; 440 441 if (e1->type && 442 e1->op != TOKtype) // function type is not a property 443 { 444 /* Look for e1 being a lazy parameter; rewrite as delegate call 445 */ 446 if (e1->op == TOKvar) 447 { 448 VarExp *ve = (VarExp *)e1; 449 450 if (ve->var->storage_class & STClazy) 451 { 452 Expression *e = new CallExp(loc, e1); 453 return semantic(e, sc); 454 } 455 } 456 else if (e1->op == TOKdotvar) 457 { 458 // Check for reading overlapped pointer field in @safe code. 459 if (checkUnsafeAccess(sc, e1, true, true)) 460 return new ErrorExp(); 461 } 462 else if (e1->op == TOKcall) 463 { 464 CallExp *ce = (CallExp *)e1; 465 // Check for reading overlapped pointer field in @safe code. 466 if (checkUnsafeAccess(sc, ce->e1, true, true)) 467 return new ErrorExp(); 468 } 469 } 470 471 if (!e1->type) 472 { 473 error(loc, "cannot resolve type for %s", e1->toChars()); 474 e1 = new ErrorExp(); 475 } 476 return e1; 477 478Leprop: 479 error(loc, "not a property %s", e1->toChars()); 480 return new ErrorExp(); 481 482Leproplvalue: 483 error(loc, "%s is not an lvalue", e1->toChars()); 484 return new ErrorExp(); 485} 486 487Expression *resolveProperties(Scope *sc, Expression *e) 488{ 489 //printf("resolveProperties(%s)\n", e->toChars()); 490 491 e = resolvePropertiesX(sc, e); 492 if (e->checkRightThis(sc)) 493 return new ErrorExp(); 494 return e; 495} 496 497/****************************** 498 * Check the tail CallExp is really property function call. 499 */ 500static bool checkPropertyCall(Expression *e) 501{ 502 while (e->op == TOKcomma) 503 e = ((CommaExp *)e)->e2; 504 505 if (e->op == TOKcall) 506 { 507 CallExp *ce = (CallExp *)e; 508 TypeFunction *tf; 509 if (ce->f) 510 { 511 tf = (TypeFunction *)ce->f->type; 512 /* If a forward reference to ce->f, try to resolve it 513 */ 514 if (!tf->deco && ce->f->semanticRun < PASSsemanticdone) 515 { 516 ce->f->semantic(NULL); 517 tf = (TypeFunction *)ce->f->type; 518 } 519 } 520 else if (ce->e1->type->ty == Tfunction) 521 tf = (TypeFunction *)ce->e1->type; 522 else if (ce->e1->type->ty == Tdelegate) 523 tf = (TypeFunction *)ce->e1->type->nextOf(); 524 else if (ce->e1->type->ty == Tpointer && ce->e1->type->nextOf()->ty == Tfunction) 525 tf = (TypeFunction *)ce->e1->type->nextOf(); 526 else 527 assert(0); 528 } 529 return false; 530} 531 532/****************************** 533 * If e1 is a property function (template), resolve it. 534 */ 535 536Expression *resolvePropertiesOnly(Scope *sc, Expression *e1) 537{ 538 //printf("e1 = %s %s\n", Token::toChars(e1->op), e1->toChars()); 539 OverloadSet *os; 540 FuncDeclaration *fd; 541 TemplateDeclaration *td; 542 543 if (e1->op == TOKdot) 544 { 545 DotExp *de = (DotExp *)e1; 546 if (de->e2->op == TOKoverloadset) 547 { 548 os = ((OverExp *)de->e2)->vars; 549 goto Los; 550 } 551 } 552 else if (e1->op == TOKoverloadset) 553 { 554 os = ((OverExp *)e1)->vars; 555 Los: 556 assert(os); 557 for (size_t i = 0; i < os->a.dim; i++) 558 { 559 Dsymbol *s = os->a[i]; 560 fd = s->isFuncDeclaration(); 561 td = s->isTemplateDeclaration(); 562 if (fd) 563 { 564 if (((TypeFunction *)fd->type)->isproperty) 565 return resolveProperties(sc, e1); 566 } 567 else if (td && td->onemember && 568 (fd = td->onemember->isFuncDeclaration()) != NULL) 569 { 570 if (((TypeFunction *)fd->type)->isproperty || 571 (fd->storage_class2 & STCproperty) || 572 (td->_scope->stc & STCproperty)) 573 { 574 return resolveProperties(sc, e1); 575 } 576 } 577 } 578 } 579 else if (e1->op == TOKdotti) 580 { 581 DotTemplateInstanceExp* dti = (DotTemplateInstanceExp *)e1; 582 if (dti->ti->tempdecl && (td = dti->ti->tempdecl->isTemplateDeclaration()) != NULL) 583 goto Ltd; 584 } 585 else if (e1->op == TOKdottd) 586 { 587 td = ((DotTemplateExp *)e1)->td; 588 goto Ltd; 589 } 590 else if (e1->op == TOKscope) 591 { 592 Dsymbol *s = ((ScopeExp *)e1)->sds; 593 TemplateInstance *ti = s->isTemplateInstance(); 594 if (ti && !ti->semanticRun && ti->tempdecl) 595 { 596 if ((td = ti->tempdecl->isTemplateDeclaration()) != NULL) 597 goto Ltd; 598 } 599 } 600 else if (e1->op == TOKtemplate) 601 { 602 td = ((TemplateExp *)e1)->td; 603 Ltd: 604 assert(td); 605 if (td->onemember && 606 (fd = td->onemember->isFuncDeclaration()) != NULL) 607 { 608 if (((TypeFunction *)fd->type)->isproperty || 609 (fd->storage_class2 & STCproperty) || 610 (td->_scope->stc & STCproperty)) 611 { 612 return resolveProperties(sc, e1); 613 } 614 } 615 } 616 else if (e1->op == TOKdotvar && e1->type->ty == Tfunction) 617 { 618 DotVarExp *dve = (DotVarExp *)e1; 619 fd = dve->var->isFuncDeclaration(); 620 goto Lfd; 621 } 622 else if (e1->op == TOKvar && e1->type->ty == Tfunction && 623 (sc->intypeof || !((VarExp *)e1)->var->needThis())) 624 { 625 fd = ((VarExp *)e1)->var->isFuncDeclaration(); 626 Lfd: 627 assert(fd); 628 if (((TypeFunction *)fd->type)->isproperty) 629 return resolveProperties(sc, e1); 630 } 631 return e1; 632} 633 634 635// TODO: merge with Scope::search::searchScopes() 636static Dsymbol *searchScopes(Scope *sc, Loc loc, Identifier *ident, int flags) 637{ 638 Dsymbol *s = NULL; 639 for (Scope *scx = sc; scx; scx = scx->enclosing) 640 { 641 if (!scx->scopesym) 642 continue; 643 if (scx->scopesym->isModule()) 644 flags |= SearchUnqualifiedModule; // tell Module.search() that SearchLocalsOnly is to be obeyed 645 s = scx->scopesym->search(loc, ident, flags); 646 if (s) 647 { 648 // overload set contains only module scope symbols. 649 if (s->isOverloadSet()) 650 break; 651 // selective/renamed imports also be picked up 652 if (AliasDeclaration *ad = s->isAliasDeclaration()) 653 { 654 if (ad->_import) 655 break; 656 } 657 // See only module scope symbols for UFCS target. 658 Dsymbol *p = s->toParent2(); 659 if (p && p->isModule()) 660 break; 661 } 662 s = NULL; 663 664 // Stop when we hit a module, but keep going if that is not just under the global scope 665 if (scx->scopesym->isModule() && !(scx->enclosing && !scx->enclosing->enclosing)) 666 break; 667 } 668 return s; 669} 670 671/****************************** 672 * Find symbol in accordance with the UFCS name look up rule 673 */ 674 675Expression *searchUFCS(Scope *sc, UnaExp *ue, Identifier *ident) 676{ 677 //printf("searchUFCS(ident = %s)\n", ident->toChars()); 678 Loc loc = ue->loc; 679 int flags = 0; 680 Dsymbol *s = NULL; 681 682 if (sc->flags & SCOPEignoresymbolvisibility) 683 flags |= IgnoreSymbolVisibility; 684 685 Dsymbol *sold = NULL; 686 if (global.params.bug10378 || global.params.check10378) 687 { 688 sold = searchScopes(sc, loc, ident, flags | IgnoreSymbolVisibility); 689 if (!global.params.check10378) 690 { 691 s = sold; 692 goto Lsearchdone; 693 } 694 } 695 696 // First look in local scopes 697 s = searchScopes(sc, loc, ident, flags | SearchLocalsOnly); 698 if (!s) 699 { 700 // Second look in imported modules 701 s = searchScopes(sc, loc, ident, flags | SearchImportsOnly); 702 703 /** Still find private symbols, so that symbols that weren't access 704 * checked by the compiler remain usable. Once the deprecation is over, 705 * this should be moved to search_correct instead. 706 */ 707 if (!s && !(flags & IgnoreSymbolVisibility)) 708 { 709 s = searchScopes(sc, loc, ident, flags | SearchLocalsOnly | IgnoreSymbolVisibility); 710 if (!s) 711 s = searchScopes(sc, loc, ident, flags | SearchImportsOnly | IgnoreSymbolVisibility); 712 if (s) 713 ::deprecation(loc, "%s is not visible from module %s", s->toPrettyChars(), sc->_module->toChars()); 714 } 715 } 716 if (global.params.check10378) 717 { 718 Dsymbol *snew = s; 719 if (sold != snew) 720 Scope::deprecation10378(loc, sold, snew); 721 if (global.params.bug10378) 722 s = sold; 723 } 724Lsearchdone: 725 726 if (!s) 727 return ue->e1->type->Type::getProperty(loc, ident, 0); 728 729 FuncDeclaration *f = s->isFuncDeclaration(); 730 if (f) 731 { 732 TemplateDeclaration *td = getFuncTemplateDecl(f); 733 if (td) 734 { 735 if (td->overroot) 736 td = td->overroot; 737 s = td; 738 } 739 } 740 741 if (ue->op == TOKdotti) 742 { 743 DotTemplateInstanceExp *dti = (DotTemplateInstanceExp *)ue; 744 TemplateInstance *ti = new TemplateInstance(loc, s->ident); 745 ti->tiargs = dti->ti->tiargs; // for better diagnostic message 746 if (!ti->updateTempDecl(sc, s)) 747 return new ErrorExp(); 748 return new ScopeExp(loc, ti); 749 } 750 else 751 { 752 //printf("-searchUFCS() %s\n", s->toChars()); 753 return new DsymbolExp(loc, s); 754 } 755} 756 757/****************************** 758 * check e is exp.opDispatch!(tiargs) or not 759 * It's used to switch to UFCS the semantic analysis path 760 */ 761 762bool isDotOpDispatch(Expression *e) 763{ 764 return e->op == TOKdotti && 765 ((DotTemplateInstanceExp *)e)->ti->name == Id::opDispatch; 766} 767 768/****************************** 769 * Pull out callable entity with UFCS. 770 */ 771 772Expression *resolveUFCS(Scope *sc, CallExp *ce) 773{ 774 Loc loc = ce->loc; 775 Expression *eleft; 776 Expression *e; 777 778 if (ce->e1->op == TOKdotid) 779 { 780 DotIdExp *die = (DotIdExp *)ce->e1; 781 Identifier *ident = die->ident; 782 783 Expression *ex = semanticX(die, sc); 784 if (ex != die) 785 { 786 ce->e1 = ex; 787 return NULL; 788 } 789 eleft = die->e1; 790 791 Type *t = eleft->type->toBasetype(); 792 if (t->ty == Tarray || t->ty == Tsarray || 793 t->ty == Tnull || (t->isTypeBasic() && t->ty != Tvoid)) 794 { 795 /* Built-in types and arrays have no callable properties, so do shortcut. 796 * It is necessary in: e.init() 797 */ 798 } 799 else if (t->ty == Taarray) 800 { 801 if (ident == Id::remove) 802 { 803 /* Transform: 804 * aa.remove(arg) into delete aa[arg] 805 */ 806 if (!ce->arguments || ce->arguments->dim != 1) 807 { 808 ce->error("expected key as argument to aa.remove()"); 809 return new ErrorExp(); 810 } 811 if (!eleft->type->isMutable()) 812 { 813 ce->error("cannot remove key from %s associative array %s", 814 MODtoChars(t->mod), eleft->toChars()); 815 return new ErrorExp(); 816 } 817 Expression *key = (*ce->arguments)[0]; 818 key = semantic(key, sc); 819 key = resolveProperties(sc, key); 820 821 TypeAArray *taa = (TypeAArray *)t; 822 key = key->implicitCastTo(sc, taa->index); 823 824 if (key->checkValue()) 825 return new ErrorExp(); 826 827 semanticTypeInfo(sc, taa->index); 828 829 return new RemoveExp(loc, eleft, key); 830 } 831 } 832 else 833 { 834 if (Expression *ey = semanticY(die, sc, 1)) 835 { 836 if (ey->op == TOKerror) 837 return ey; 838 ce->e1 = ey; 839 if (isDotOpDispatch(ey)) 840 { 841 unsigned errors = global.startGagging(); 842 e = semantic(ce->syntaxCopy(), sc); 843 if (!global.endGagging(errors)) 844 return e; 845 /* fall down to UFCS */ 846 } 847 else 848 return NULL; 849 } 850 } 851 e = searchUFCS(sc, die, ident); 852 } 853 else if (ce->e1->op == TOKdotti) 854 { 855 DotTemplateInstanceExp *dti = (DotTemplateInstanceExp *)ce->e1; 856 if (Expression *ey = semanticY(dti, sc, 1)) 857 { 858 ce->e1 = ey; 859 return NULL; 860 } 861 eleft = dti->e1; 862 e = searchUFCS(sc, dti, dti->ti->name); 863 } 864 else 865 return NULL; 866 867 // Rewrite 868 ce->e1 = e; 869 if (!ce->arguments) 870 ce->arguments = new Expressions(); 871 ce->arguments->shift(eleft); 872 873 return NULL; 874} 875 876/****************************** 877 * Pull out property with UFCS. 878 */ 879 880Expression *resolveUFCSProperties(Scope *sc, Expression *e1, Expression *e2 = NULL) 881{ 882 Loc loc = e1->loc; 883 Expression *eleft; 884 Expression *e; 885 886 if (e1->op == TOKdotid) 887 { 888 DotIdExp *die = (DotIdExp *)e1; 889 eleft = die->e1; 890 e = searchUFCS(sc, die, die->ident); 891 } 892 else if (e1->op == TOKdotti) 893 { 894 DotTemplateInstanceExp *dti; 895 dti = (DotTemplateInstanceExp *)e1; 896 eleft = dti->e1; 897 e = searchUFCS(sc, dti, dti->ti->name); 898 } 899 else 900 return NULL; 901 902 if (e == NULL) 903 return NULL; 904 905 // Rewrite 906 if (e2) 907 { 908 // run semantic without gagging 909 e2 = semantic(e2, sc); 910 911 /* f(e1) = e2 912 */ 913 Expression *ex = e->copy(); 914 Expressions *a1 = new Expressions(); 915 a1->setDim(1); 916 (*a1)[0] = eleft; 917 ex = new CallExp(loc, ex, a1); 918 ex = trySemantic(ex, sc); 919 920 /* f(e1, e2) 921 */ 922 Expressions *a2 = new Expressions(); 923 a2->setDim(2); 924 (*a2)[0] = eleft; 925 (*a2)[1] = e2; 926 e = new CallExp(loc, e, a2); 927 if (ex) 928 { // if fallback setter exists, gag errors 929 e = trySemantic(e, sc); 930 if (!e) 931 { checkPropertyCall(ex); 932 ex = new AssignExp(loc, ex, e2); 933 return semantic(ex, sc); 934 } 935 } 936 else 937 { // strict setter prints errors if fails 938 e = semantic(e, sc); 939 } 940 checkPropertyCall(e); 941 return e; 942 } 943 else 944 { 945 /* f(e1) 946 */ 947 Expressions *arguments = new Expressions(); 948 arguments->setDim(1); 949 (*arguments)[0] = eleft; 950 e = new CallExp(loc, e, arguments); 951 e = semantic(e, sc); 952 checkPropertyCall(e); 953 return semantic(e, sc); 954 } 955} 956 957/****************************** 958 * Perform semantic() on an array of Expressions. 959 */ 960 961bool arrayExpressionSemantic(Expressions *exps, Scope *sc, bool preserveErrors) 962{ 963 bool err = false; 964 if (exps) 965 { 966 for (size_t i = 0; i < exps->dim; i++) 967 { 968 Expression *e = (*exps)[i]; 969 if (e) 970 { 971 e = semantic(e, sc); 972 if (e->op == TOKerror) 973 err = true; 974 if (preserveErrors || e->op != TOKerror) 975 (*exps)[i] = e; 976 } 977 } 978 } 979 return err; 980} 981 982/**************************************** 983 * Expand tuples. 984 * Input: 985 * exps aray of Expressions 986 * Output: 987 * exps rewritten in place 988 */ 989 990void expandTuples(Expressions *exps) 991{ 992 //printf("expandTuples()\n"); 993 if (exps) 994 { 995 for (size_t i = 0; i < exps->dim; i++) 996 { 997 Expression *arg = (*exps)[i]; 998 if (!arg) 999 continue; 1000 1001 // Look for tuple with 0 members 1002 if (arg->op == TOKtype) 1003 { 1004 TypeExp *e = (TypeExp *)arg; 1005 if (e->type->toBasetype()->ty == Ttuple) 1006 { 1007 TypeTuple *tt = (TypeTuple *)e->type->toBasetype(); 1008 1009 if (!tt->arguments || tt->arguments->dim == 0) 1010 { 1011 exps->remove(i); 1012 if (i == exps->dim) 1013 return; 1014 i--; 1015 continue; 1016 } 1017 } 1018 } 1019 1020 // Inline expand all the tuples 1021 while (arg->op == TOKtuple) 1022 { 1023 TupleExp *te = (TupleExp *)arg; 1024 exps->remove(i); // remove arg 1025 exps->insert(i, te->exps); // replace with tuple contents 1026 if (i == exps->dim) 1027 return; // empty tuple, no more arguments 1028 (*exps)[i] = Expression::combine(te->e0, (*exps)[i]); 1029 arg = (*exps)[i]; 1030 } 1031 } 1032 } 1033} 1034 1035/**************************************** 1036 * Expand alias this tuples. 1037 */ 1038 1039TupleDeclaration *isAliasThisTuple(Expression *e) 1040{ 1041 if (!e->type) 1042 return NULL; 1043 1044 Type *t = e->type->toBasetype(); 1045Lagain: 1046 if (Dsymbol *s = t->toDsymbol(NULL)) 1047 { 1048 AggregateDeclaration *ad = s->isAggregateDeclaration(); 1049 if (ad) 1050 { 1051 s = ad->aliasthis; 1052 if (s && s->isVarDeclaration()) 1053 { 1054 TupleDeclaration *td = s->isVarDeclaration()->toAlias()->isTupleDeclaration(); 1055 if (td && td->isexp) 1056 return td; 1057 } 1058 if (Type *att = t->aliasthisOf()) 1059 { 1060 t = att; 1061 goto Lagain; 1062 } 1063 } 1064 } 1065 return NULL; 1066} 1067 1068int expandAliasThisTuples(Expressions *exps, size_t starti) 1069{ 1070 if (!exps || exps->dim == 0) 1071 return -1; 1072 1073 for (size_t u = starti; u < exps->dim; u++) 1074 { 1075 Expression *exp = (*exps)[u]; 1076 TupleDeclaration *td = isAliasThisTuple(exp); 1077 if (td) 1078 { 1079 exps->remove(u); 1080 for (size_t i = 0; i<td->objects->dim; ++i) 1081 { 1082 Expression *e = isExpression((*td->objects)[i]); 1083 assert(e); 1084 assert(e->op == TOKdsymbol); 1085 DsymbolExp *se = (DsymbolExp *)e; 1086 Declaration *d = se->s->isDeclaration(); 1087 assert(d); 1088 e = new DotVarExp(exp->loc, exp, d); 1089 assert(d->type); 1090 e->type = d->type; 1091 exps->insert(u + i, e); 1092 } 1093 return (int)u; 1094 } 1095 } 1096 1097 return -1; 1098} 1099 1100/**************************************** 1101 * The common type is determined by applying ?: to each pair. 1102 * Output: 1103 * exps[] properties resolved, implicitly cast to common type, rewritten in place 1104 * *pt if pt is not NULL, set to the common type 1105 * Returns: 1106 * true a semantic error was detected 1107 */ 1108 1109bool arrayExpressionToCommonType(Scope *sc, Expressions *exps, Type **pt) 1110{ 1111 /* Still have a problem with: 1112 * ubyte[][] = [ cast(ubyte[])"hello", [1]]; 1113 * which works if the array literal is initialized top down with the ubyte[][] 1114 * type, but fails with this function doing bottom up typing. 1115 */ 1116 //printf("arrayExpressionToCommonType()\n"); 1117 IntegerExp integerexp(0); 1118 CondExp condexp(Loc(), &integerexp, NULL, NULL); 1119 1120 Type *t0 = NULL; 1121 Expression *e0 = NULL; // dead-store to prevent spurious warning 1122 size_t j0 = ~0; // dead-store to prevent spurious warning 1123 bool foundType = false; 1124 1125 for (size_t i = 0; i < exps->dim; i++) 1126 { 1127 Expression *e = (*exps)[i]; 1128 if (!e) 1129 continue; 1130 1131 e = resolveProperties(sc, e); 1132 if (!e->type) 1133 { 1134 e->error("%s has no value", e->toChars()); 1135 t0 = Type::terror; 1136 continue; 1137 } 1138 if (e->op == TOKtype) 1139 { 1140 foundType = true; // do not break immediately, there might be more errors 1141 e->checkValue(); // report an error "type T has no value" 1142 t0 = Type::terror; 1143 continue; 1144 } 1145 if (e->type->ty == Tvoid) 1146 { 1147 // void expressions do not concur to the determination of the common 1148 // type. 1149 continue; 1150 } 1151 if (checkNonAssignmentArrayOp(e)) 1152 { 1153 t0 = Type::terror; 1154 continue; 1155 } 1156 1157 e = doCopyOrMove(sc, e); 1158 1159 if (!foundType && t0 && !t0->equals(e->type)) 1160 { 1161 /* This applies ?: to merge the types. It's backwards; 1162 * ?: should call this function to merge types. 1163 */ 1164 condexp.type = NULL; 1165 condexp.e1 = e0; 1166 condexp.e2 = e; 1167 condexp.loc = e->loc; 1168 Expression *ex = semantic(&condexp, sc); 1169 if (ex->op == TOKerror) 1170 e = ex; 1171 else 1172 { 1173 (*exps)[j0] = condexp.e1; 1174 e = condexp.e2; 1175 } 1176 } 1177 j0 = i; 1178 e0 = e; 1179 t0 = e->type; 1180 if (e->op != TOKerror) 1181 (*exps)[i] = e; 1182 } 1183 1184 if (!t0) 1185 t0 = Type::tvoid; // [] is typed as void[] 1186 else if (t0->ty != Terror) 1187 { 1188 for (size_t i = 0; i < exps->dim; i++) 1189 { 1190 Expression *e = (*exps)[i]; 1191 if (!e) 1192 continue; 1193 1194 e = e->implicitCastTo(sc, t0); 1195 //assert(e->op != TOKerror); 1196 if (e->op == TOKerror) 1197 { 1198 /* Bugzilla 13024: a workaround for the bug in typeMerge - 1199 * it should paint e1 and e2 by deduced common type, 1200 * but doesn't in this particular case. 1201 */ 1202 t0 = Type::terror; 1203 break; 1204 } 1205 (*exps)[i] = e; 1206 } 1207 } 1208 if (pt) 1209 *pt = t0; 1210 1211 return (t0 == Type::terror); 1212} 1213 1214/**************************************** 1215 * Get TemplateDeclaration enclosing FuncDeclaration. 1216 */ 1217 1218TemplateDeclaration *getFuncTemplateDecl(Dsymbol *s) 1219{ 1220 FuncDeclaration *f = s->isFuncDeclaration(); 1221 if (f && f->parent) 1222 { 1223 TemplateInstance *ti = f->parent->isTemplateInstance(); 1224 if (ti && !ti->isTemplateMixin() && 1225 ti->tempdecl && ((TemplateDeclaration *)ti->tempdecl)->onemember && 1226 ti->tempdecl->ident == f->ident) 1227 { 1228 return (TemplateDeclaration *)ti->tempdecl; 1229 } 1230 } 1231 return NULL; 1232} 1233 1234/************************************************ 1235 * If we want the value of this expression, but do not want to call 1236 * the destructor on it. 1237 */ 1238 1239Expression *valueNoDtor(Expression *e) 1240{ 1241 if (e->op == TOKcall) 1242 { 1243 /* The struct value returned from the function is transferred 1244 * so do not call the destructor on it. 1245 * Recognize: 1246 * ((S _ctmp = S.init), _ctmp).this(...) 1247 * and make sure the destructor is not called on _ctmp 1248 * BUG: if e is a CommaExp, we should go down the right side. 1249 */ 1250 CallExp *ce = (CallExp *)e; 1251 if (ce->e1->op == TOKdotvar) 1252 { 1253 DotVarExp *dve = (DotVarExp *)ce->e1; 1254 if (dve->var->isCtorDeclaration()) 1255 { 1256 // It's a constructor call 1257 if (dve->e1->op == TOKcomma) 1258 { 1259 CommaExp *comma = (CommaExp *)dve->e1; 1260 if (comma->e2->op == TOKvar) 1261 { 1262 VarExp *ve = (VarExp *)comma->e2; 1263 VarDeclaration *ctmp = ve->var->isVarDeclaration(); 1264 if (ctmp) 1265 { 1266 ctmp->storage_class |= STCnodtor; 1267 assert(!ce->isLvalue()); 1268 } 1269 } 1270 } 1271 } 1272 } 1273 } 1274 else if (e->op == TOKvar) 1275 { 1276 VarDeclaration *vtmp = ((VarExp *)e)->var->isVarDeclaration(); 1277 if (vtmp && vtmp->storage_class & STCrvalue) 1278 { 1279 vtmp->storage_class |= STCnodtor; 1280 } 1281 } 1282 return e; 1283} 1284 1285/******************************************** 1286 * Issue an error if default construction is disabled for type t. 1287 * Default construction is required for arrays and 'out' parameters. 1288 * Returns: 1289 * true an error was issued 1290 */ 1291bool checkDefCtor(Loc loc, Type *t) 1292{ 1293 t = t->baseElemOf(); 1294 if (t->ty == Tstruct) 1295 { 1296 StructDeclaration *sd = ((TypeStruct *)t)->sym; 1297 if (sd->noDefaultCtor) 1298 { 1299 sd->error(loc, "default construction is disabled"); 1300 return true; 1301 } 1302 } 1303 return false; 1304} 1305 1306/********************************************* 1307 * If e is an instance of a struct, and that struct has a copy constructor, 1308 * rewrite e as: 1309 * (tmp = e),tmp 1310 * Input: 1311 * sc just used to specify the scope of created temporary variable 1312 */ 1313Expression *callCpCtor(Scope *sc, Expression *e) 1314{ 1315 Type *tv = e->type->baseElemOf(); 1316 if (tv->ty == Tstruct) 1317 { 1318 StructDeclaration *sd = ((TypeStruct *)tv)->sym; 1319 if (sd->postblit) 1320 { 1321 /* Create a variable tmp, and replace the argument e with: 1322 * (tmp = e),tmp 1323 * and let AssignExp() handle the construction. 1324 * This is not the most efficent, ideally tmp would be constructed 1325 * directly onto the stack. 1326 */ 1327 VarDeclaration *tmp = copyToTemp(STCrvalue, "__copytmp", e); 1328 tmp->storage_class |= STCnodtor; 1329 tmp->semantic(sc); 1330 Expression *de = new DeclarationExp(e->loc, tmp); 1331 Expression *ve = new VarExp(e->loc, tmp); 1332 de->type = Type::tvoid; 1333 ve->type = e->type; 1334 e = Expression::combine(de, ve); 1335 } 1336 } 1337 return e; 1338} 1339 1340/************************************************ 1341 * Handle the postblit call on lvalue, or the move of rvalue. 1342 */ 1343Expression *doCopyOrMove(Scope *sc, Expression *e) 1344{ 1345 if (e->op == TOKquestion) 1346 { 1347 CondExp *ce = (CondExp *)e; 1348 ce->e1 = doCopyOrMove(sc, ce->e1); 1349 ce->e2 = doCopyOrMove(sc, ce->e2); 1350 } 1351 else 1352 { 1353 e = e->isLvalue() ? callCpCtor(sc, e) : valueNoDtor(e); 1354 } 1355 return e; 1356} 1357 1358/**************************************** 1359 * Now that we know the exact type of the function we're calling, 1360 * the arguments[] need to be adjusted: 1361 * 1. implicitly convert argument to the corresponding parameter type 1362 * 2. add default arguments for any missing arguments 1363 * 3. do default promotions on arguments corresponding to ... 1364 * 4. add hidden _arguments[] argument 1365 * 5. call copy constructor for struct value arguments 1366 * Input: 1367 * tf type of the function 1368 * fd the function being called, NULL if called indirectly 1369 * Output: 1370 * *prettype return type of function 1371 * *peprefix expression to execute before arguments[] are evaluated, NULL if none 1372 * Returns: 1373 * true errors happened 1374 */ 1375 1376bool functionParameters(Loc loc, Scope *sc, TypeFunction *tf, 1377 Type *tthis, Expressions *arguments, FuncDeclaration *fd, Type **prettype, Expression **peprefix) 1378{ 1379 //printf("functionParameters()\n"); 1380 assert(arguments); 1381 assert(fd || tf->next); 1382 size_t nargs = arguments ? arguments->dim : 0; 1383 size_t nparams = Parameter::dim(tf->parameters); 1384 unsigned olderrors = global.errors; 1385 bool err = false; 1386 *prettype = Type::terror; 1387 Expression *eprefix = NULL; 1388 *peprefix = NULL; 1389 1390 if (nargs > nparams && tf->varargs == 0) 1391 { 1392 error(loc, "expected %llu arguments, not %llu for non-variadic function type %s", (ulonglong)nparams, (ulonglong)nargs, tf->toChars()); 1393 return true; 1394 } 1395 1396 // If inferring return type, and semantic3() needs to be run if not already run 1397 if (!tf->next && fd->inferRetType) 1398 { 1399 fd->functionSemantic(); 1400 } 1401 else if (fd && fd->parent) 1402 { 1403 TemplateInstance *ti = fd->parent->isTemplateInstance(); 1404 if (ti && ti->tempdecl) 1405 { 1406 fd->functionSemantic3(); 1407 } 1408 } 1409 bool isCtorCall = fd && fd->needThis() && fd->isCtorDeclaration(); 1410 1411 size_t n = (nargs > nparams) ? nargs : nparams; // n = max(nargs, nparams) 1412 1413 /* If the function return type has wildcards in it, we'll need to figure out the actual type 1414 * based on the actual argument types. 1415 */ 1416 MOD wildmatch = 0; 1417 if (tthis && tf->isWild() && !isCtorCall) 1418 { 1419 Type *t = tthis; 1420 if (t->isImmutable()) 1421 wildmatch = MODimmutable; 1422 else if (t->isWildConst()) 1423 wildmatch = MODwildconst; 1424 else if (t->isWild()) 1425 wildmatch = MODwild; 1426 else if (t->isConst()) 1427 wildmatch = MODconst; 1428 else 1429 wildmatch = MODmutable; 1430 } 1431 1432 int done = 0; 1433 for (size_t i = 0; i < n; i++) 1434 { 1435 Expression *arg; 1436 1437 if (i < nargs) 1438 arg = (*arguments)[i]; 1439 else 1440 arg = NULL; 1441 1442 if (i < nparams) 1443 { 1444 Parameter *p = Parameter::getNth(tf->parameters, i); 1445 1446 if (!arg) 1447 { 1448 if (!p->defaultArg) 1449 { 1450 if (tf->varargs == 2 && i + 1 == nparams) 1451 goto L2; 1452 error(loc, "expected %llu function arguments, not %llu", (ulonglong)nparams, (ulonglong)nargs); 1453 return true; 1454 } 1455 arg = p->defaultArg; 1456 arg = inlineCopy(arg, sc); 1457 // __FILE__, __LINE__, __MODULE__, __FUNCTION__, and __PRETTY_FUNCTION__ 1458 arg = arg->resolveLoc(loc, sc); 1459 arguments->push(arg); 1460 nargs++; 1461 } 1462 1463 if (tf->varargs == 2 && i + 1 == nparams) 1464 { 1465 //printf("\t\tvarargs == 2, p->type = '%s'\n", p->type->toChars()); 1466 { 1467 MATCH m; 1468 if ((m = arg->implicitConvTo(p->type)) > MATCHnomatch) 1469 { 1470 if (p->type->nextOf() && arg->implicitConvTo(p->type->nextOf()) >= m) 1471 goto L2; 1472 else if (nargs != nparams) 1473 { error(loc, "expected %llu function arguments, not %llu", (ulonglong)nparams, (ulonglong)nargs); 1474 return true; 1475 } 1476 goto L1; 1477 } 1478 } 1479 L2: 1480 Type *tb = p->type->toBasetype(); 1481 Type *tret = p->isLazyArray(); 1482 switch (tb->ty) 1483 { 1484 case Tsarray: 1485 case Tarray: 1486 { 1487 /* Create a static array variable v of type arg->type: 1488 * T[dim] __arrayArg = [ arguments[i], ..., arguments[nargs-1] ]; 1489 * 1490 * The array literal in the initializer of the hidden variable 1491 * is now optimized. See Bugzilla 2356. 1492 */ 1493 Type *tbn = ((TypeArray *)tb)->next; 1494 1495 Expressions *elements = new Expressions(); 1496 elements->setDim(nargs - i); 1497 for (size_t u = 0; u < elements->dim; u++) 1498 { 1499 Expression *a = (*arguments)[i + u]; 1500 if (tret && a->implicitConvTo(tret)) 1501 { 1502 a = a->implicitCastTo(sc, tret); 1503 a = a->optimize(WANTvalue); 1504 a = toDelegate(a, a->type, sc); 1505 } 1506 else 1507 a = a->implicitCastTo(sc, tbn); 1508 (*elements)[u] = a; 1509 } 1510 // Bugzilla 14395: Convert to a static array literal, or its slice. 1511 arg = new ArrayLiteralExp(loc, tbn->sarrayOf(nargs - i), elements); 1512 if (tb->ty == Tarray) 1513 { 1514 arg = new SliceExp(loc, arg, NULL, NULL); 1515 arg->type = p->type; 1516 } 1517 break; 1518 } 1519 case Tclass: 1520 { 1521 /* Set arg to be: 1522 * new Tclass(arg0, arg1, ..., argn) 1523 */ 1524 Expressions *args = new Expressions(); 1525 args->setDim(nargs - i); 1526 for (size_t u = i; u < nargs; u++) 1527 (*args)[u - i] = (*arguments)[u]; 1528 arg = new NewExp(loc, NULL, NULL, p->type, args); 1529 break; 1530 } 1531 default: 1532 if (!arg) 1533 { 1534 error(loc, "not enough arguments"); 1535 return true; 1536 } 1537 break; 1538 } 1539 arg = semantic(arg, sc); 1540 //printf("\targ = '%s'\n", arg->toChars()); 1541 arguments->setDim(i + 1); 1542 (*arguments)[i] = arg; 1543 nargs = i + 1; 1544 done = 1; 1545 } 1546 1547 L1: 1548 if (!(p->storageClass & STClazy && p->type->ty == Tvoid)) 1549 { 1550 bool isRef = (p->storageClass & (STCref | STCout)) != 0; 1551 if (unsigned char wm = arg->type->deduceWild(p->type, isRef)) 1552 { 1553 if (wildmatch) 1554 wildmatch = MODmerge(wildmatch, wm); 1555 else 1556 wildmatch = wm; 1557 //printf("[%d] p = %s, a = %s, wm = %d, wildmatch = %d\n", i, p->type->toChars(), arg->type->toChars(), wm, wildmatch); 1558 } 1559 } 1560 } 1561 if (done) 1562 break; 1563 } 1564 if ((wildmatch == MODmutable || wildmatch == MODimmutable) && 1565 tf->next->hasWild() && 1566 (tf->isref || !tf->next->implicitConvTo(tf->next->immutableOf()))) 1567 { 1568 if (fd) 1569 { 1570 /* If the called function may return the reference to 1571 * outer inout data, it should be rejected. 1572 * 1573 * void foo(ref inout(int) x) { 1574 * ref inout(int) bar(inout(int)) { return x; } 1575 * struct S { ref inout(int) bar() inout { return x; } } 1576 * bar(int.init) = 1; // bad! 1577 * S().bar() = 1; // bad! 1578 * } 1579 */ 1580 Dsymbol *s = NULL; 1581 if (fd->isThis() || fd->isNested()) 1582 s = fd->toParent2(); 1583 for (; s; s = s->toParent2()) 1584 { 1585 if (AggregateDeclaration *ad = s->isAggregateDeclaration()) 1586 { 1587 if (ad->isNested()) 1588 continue; 1589 break; 1590 } 1591 if (FuncDeclaration *ff = s->isFuncDeclaration()) 1592 { 1593 if (((TypeFunction *)ff->type)->iswild) 1594 goto Linouterr; 1595 1596 if (ff->isNested() || ff->isThis()) 1597 continue; 1598 } 1599 break; 1600 } 1601 } 1602 else if (tf->isWild()) 1603 { 1604 Linouterr: 1605 const char *s = wildmatch == MODmutable ? "mutable" : MODtoChars(wildmatch); 1606 error(loc, "modify inout to %s is not allowed inside inout function", s); 1607 return true; 1608 } 1609 } 1610 1611 assert(nargs >= nparams); 1612 for (size_t i = 0; i < nargs; i++) 1613 { 1614 Expression *arg = (*arguments)[i]; 1615 assert(arg); 1616 if (i < nparams) 1617 { 1618 Parameter *p = Parameter::getNth(tf->parameters, i); 1619 1620 if (!(p->storageClass & STClazy && p->type->ty == Tvoid)) 1621 { 1622 Type *tprm = p->type; 1623 if (p->type->hasWild()) 1624 tprm = p->type->substWildTo(wildmatch); 1625 if (!tprm->equals(arg->type)) 1626 { 1627 //printf("arg->type = %s, p->type = %s\n", arg->type->toChars(), p->type->toChars()); 1628 arg = arg->implicitCastTo(sc, tprm); 1629 arg = arg->optimize(WANTvalue, (p->storageClass & (STCref | STCout)) != 0); 1630 } 1631 } 1632 if (p->storageClass & STCref) 1633 { 1634 arg = arg->toLvalue(sc, arg); 1635 1636 // Look for mutable misaligned pointer, etc., in @safe mode 1637 err |= checkUnsafeAccess(sc, arg, false, true); 1638 } 1639 else if (p->storageClass & STCout) 1640 { 1641 Type *t = arg->type; 1642 if (!t->isMutable() || !t->isAssignable()) // check blit assignable 1643 { 1644 arg->error("cannot modify struct %s with immutable members", arg->toChars()); 1645 err = true; 1646 } 1647 else 1648 { 1649 // Look for misaligned pointer, etc., in @safe mode 1650 err |= checkUnsafeAccess(sc, arg, false, true); 1651 err |= checkDefCtor(arg->loc, t); // t must be default constructible 1652 } 1653 arg = arg->toLvalue(sc, arg); 1654 } 1655 else if (p->storageClass & STClazy) 1656 { 1657 // Convert lazy argument to a delegate 1658 if (p->type->ty == Tvoid) 1659 arg = toDelegate(arg, p->type, sc); 1660 else 1661 arg = toDelegate(arg, arg->type, sc); 1662 } 1663 1664 //printf("arg: %s\n", arg->toChars()); 1665 //printf("type: %s\n", arg->type->toChars()); 1666 if (tf->parameterEscapes(p)) 1667 { 1668 /* Argument value can escape from the called function. 1669 * Check arg to see if it matters. 1670 */ 1671 if (global.params.vsafe) 1672 err |= checkParamArgumentEscape(sc, fd, p->ident, arg, false); 1673 } 1674 else 1675 { 1676 /* Argument value cannot escape from the called function. 1677 */ 1678 Expression *a = arg; 1679 if (a->op == TOKcast) 1680 a = ((CastExp *)a)->e1; 1681 1682 if (a->op == TOKfunction) 1683 { 1684 /* Function literals can only appear once, so if this 1685 * appearance was scoped, there cannot be any others. 1686 */ 1687 FuncExp *fe = (FuncExp *)a; 1688 fe->fd->tookAddressOf = 0; 1689 } 1690 else if (a->op == TOKdelegate) 1691 { 1692 /* For passing a delegate to a scoped parameter, 1693 * this doesn't count as taking the address of it. 1694 * We only worry about 'escaping' references to the function. 1695 */ 1696 DelegateExp *de = (DelegateExp *)a; 1697 if (de->e1->op == TOKvar) 1698 { VarExp *ve = (VarExp *)de->e1; 1699 FuncDeclaration *f = ve->var->isFuncDeclaration(); 1700 if (f) 1701 { f->tookAddressOf--; 1702 //printf("tookAddressOf = %d\n", f->tookAddressOf); 1703 } 1704 } 1705 } 1706 } 1707 arg = arg->optimize(WANTvalue, (p->storageClass & (STCref | STCout)) != 0); 1708 } 1709 else 1710 { 1711 // These will be the trailing ... arguments 1712 1713 // If not D linkage, do promotions 1714 if (tf->linkage != LINKd) 1715 { 1716 // Promote bytes, words, etc., to ints 1717 arg = integralPromotions(arg, sc); 1718 1719 // Promote floats to doubles 1720 switch (arg->type->ty) 1721 { 1722 case Tfloat32: 1723 arg = arg->castTo(sc, Type::tfloat64); 1724 break; 1725 1726 case Timaginary32: 1727 arg = arg->castTo(sc, Type::timaginary64); 1728 break; 1729 } 1730 1731 if (tf->varargs == 1) 1732 { 1733 const char *p = tf->linkage == LINKc ? "extern(C)" : "extern(C++)"; 1734 if (arg->type->ty == Tarray) 1735 { 1736 arg->error("cannot pass dynamic arrays to %s vararg functions", p); 1737 err = true; 1738 } 1739 if (arg->type->ty == Tsarray) 1740 { 1741 arg->error("cannot pass static arrays to %s vararg functions", p); 1742 err = true; 1743 } 1744 } 1745 } 1746 1747 // Do not allow types that need destructors 1748 if (arg->type->needsDestruction()) 1749 { 1750 arg->error("cannot pass types that need destruction as variadic arguments"); 1751 err = true; 1752 } 1753 1754 // Convert static arrays to dynamic arrays 1755 // BUG: I don't think this is right for D2 1756 Type *tb = arg->type->toBasetype(); 1757 if (tb->ty == Tsarray) 1758 { 1759 TypeSArray *ts = (TypeSArray *)tb; 1760 Type *ta = ts->next->arrayOf(); 1761 if (ts->size(arg->loc) == 0) 1762 arg = new NullExp(arg->loc, ta); 1763 else 1764 arg = arg->castTo(sc, ta); 1765 } 1766 if (tb->ty == Tstruct) 1767 { 1768 //arg = callCpCtor(sc, arg); 1769 } 1770 1771 // Give error for overloaded function addresses 1772 if (arg->op == TOKsymoff) 1773 { SymOffExp *se = (SymOffExp *)arg; 1774 if (se->hasOverloads && 1775 !se->var->isFuncDeclaration()->isUnique()) 1776 { arg->error("function %s is overloaded", arg->toChars()); 1777 err = true; 1778 } 1779 } 1780 if (arg->checkValue()) 1781 err = true; 1782 arg = arg->optimize(WANTvalue); 1783 } 1784 (*arguments)[i] = arg; 1785 } 1786 1787 /* Remaining problems: 1788 * 1. order of evaluation - some function push L-to-R, others R-to-L. Until we resolve what array assignment does (which is 1789 * implemented by calling a function) we'll defer this for now. 1790 * 2. value structs (or static arrays of them) that need to be copy constructed 1791 * 3. value structs (or static arrays of them) that have destructors, and subsequent arguments that may throw before the 1792 * function gets called (functions normally destroy their parameters) 1793 * 2 and 3 are handled by doing the argument construction in 'eprefix' so that if a later argument throws, they are cleaned 1794 * up properly. Pushing arguments on the stack then cannot fail. 1795 */ 1796 if (1) 1797 { 1798 /* TODO: tackle problem 1) 1799 */ 1800 const bool leftToRight = true; // TODO: something like !fd.isArrayOp 1801 if (!leftToRight) 1802 assert(nargs == nparams); // no variadics for RTL order, as they would probably be evaluated LTR and so add complexity 1803 1804 const ptrdiff_t start = (leftToRight ? 0 : (ptrdiff_t)nargs - 1); 1805 const ptrdiff_t end = (leftToRight ? (ptrdiff_t)nargs : -1); 1806 const ptrdiff_t step = (leftToRight ? 1 : -1); 1807 1808 /* Compute indices of last throwing argument and first arg needing destruction. 1809 * Used to not set up destructors unless an arg needs destruction on a throw 1810 * in a later argument. 1811 */ 1812 ptrdiff_t lastthrow = -1; 1813 ptrdiff_t firstdtor = -1; 1814 for (ptrdiff_t i = start; i != end; i += step) 1815 { 1816 Expression *arg = (*arguments)[i]; 1817 if (canThrow(arg, sc->func, false)) 1818 lastthrow = i; 1819 if (firstdtor == -1 && arg->type->needsDestruction()) 1820 { 1821 Parameter *p = (i >= (ptrdiff_t)nparams ? NULL : Parameter::getNth(tf->parameters, i)); 1822 if (!(p && (p->storageClass & (STClazy | STCref | STCout)))) 1823 firstdtor = i; 1824 } 1825 } 1826 1827 /* Does problem 3) apply to this call? 1828 */ 1829 const bool needsPrefix = (firstdtor >= 0 && lastthrow >= 0 1830 && (lastthrow - firstdtor) * step > 0); 1831 1832 /* If so, initialize 'eprefix' by declaring the gate 1833 */ 1834 VarDeclaration *gate = NULL; 1835 if (needsPrefix) 1836 { 1837 // eprefix => bool __gate [= false] 1838 Identifier *idtmp = Identifier::generateId("__gate"); 1839 gate = new VarDeclaration(loc, Type::tbool, idtmp, NULL); 1840 gate->storage_class |= STCtemp | STCctfe | STCvolatile; 1841 gate->semantic(sc); 1842 1843 Expression *ae = new DeclarationExp(loc, gate); 1844 eprefix = semantic(ae, sc); 1845 } 1846 1847 for (ptrdiff_t i = start; i != end; i += step) 1848 { 1849 Expression *arg = (*arguments)[i]; 1850 1851 Parameter *parameter = (i >= (ptrdiff_t)nparams ? NULL : Parameter::getNth(tf->parameters, i)); 1852 const bool isRef = (parameter && (parameter->storageClass & (STCref | STCout))); 1853 const bool isLazy = (parameter && (parameter->storageClass & STClazy)); 1854 1855 /* Skip lazy parameters 1856 */ 1857 if (isLazy) 1858 continue; 1859 1860 /* Do we have a gate? Then we have a prefix and we're not yet past the last throwing arg. 1861 * Declare a temporary variable for this arg and append that declaration to 'eprefix', 1862 * which will implicitly take care of potential problem 2) for this arg. 1863 * 'eprefix' will therefore finally contain all args up to and including the last 1864 * potentially throwing arg, excluding all lazy parameters. 1865 */ 1866 if (gate) 1867 { 1868 const bool needsDtor = (!isRef && arg->type->needsDestruction() && i != lastthrow); 1869 1870 /* Declare temporary 'auto __pfx = arg' (needsDtor) or 'auto __pfy = arg' (!needsDtor) 1871 */ 1872 VarDeclaration *tmp = copyToTemp(0, 1873 needsDtor ? "__pfx" : "__pfy", 1874 !isRef ? arg : arg->addressOf()); 1875 tmp->semantic(sc); 1876 1877 /* Modify the destructor so it only runs if gate==false, i.e., 1878 * only if there was a throw while constructing the args 1879 */ 1880 if (!needsDtor) 1881 { 1882 if (tmp->edtor) 1883 { 1884 assert(i == lastthrow); 1885 tmp->edtor = NULL; 1886 } 1887 } 1888 else 1889 { 1890 // edtor => (__gate || edtor) 1891 assert(tmp->edtor); 1892 Expression *e = tmp->edtor; 1893 e = new OrOrExp(e->loc, new VarExp(e->loc, gate), e); 1894 tmp->edtor = semantic(e, sc); 1895 //printf("edtor: %s\n", tmp->edtor->toChars()); 1896 } 1897 1898 // eprefix => (eprefix, auto __pfx/y = arg) 1899 DeclarationExp *ae = new DeclarationExp(loc, tmp); 1900 eprefix = Expression::combine(eprefix, semantic(ae, sc)); 1901 1902 // arg => __pfx/y 1903 arg = new VarExp(loc, tmp); 1904 arg = semantic(arg, sc); 1905 if (isRef) 1906 { 1907 arg = new PtrExp(loc, arg); 1908 arg = semantic(arg, sc); 1909 } 1910 1911 /* Last throwing arg? Then finalize eprefix => (eprefix, gate = true), 1912 * i.e., disable the dtors right after constructing the last throwing arg. 1913 * From now on, the callee will take care of destructing the args because 1914 * the args are implicitly moved into function parameters. 1915 * 1916 * Set gate to null to let the next iterations know they don't need to 1917 * append to eprefix anymore. 1918 */ 1919 if (i == lastthrow) 1920 { 1921 Expression *e = new AssignExp(gate->loc, new VarExp(gate->loc, gate), new IntegerExp(gate->loc, 1, Type::tbool)); 1922 eprefix = Expression::combine(eprefix, semantic(e, sc)); 1923 gate = NULL; 1924 } 1925 } 1926 else 1927 { 1928 /* No gate, no prefix to append to. 1929 * Handle problem 2) by calling the copy constructor for value structs 1930 * (or static arrays of them) if appropriate. 1931 */ 1932 Type *tv = arg->type->baseElemOf(); 1933 if (!isRef && tv->ty == Tstruct) 1934 arg = doCopyOrMove(sc, arg); 1935 } 1936 1937 (*arguments)[i] = arg; 1938 } 1939 } 1940 //if (eprefix) printf("eprefix: %s\n", eprefix->toChars()); 1941 1942 // If D linkage and variadic, add _arguments[] as first argument 1943 if (tf->linkage == LINKd && tf->varargs == 1) 1944 { 1945 assert(arguments->dim >= nparams); 1946 1947 Parameters *args = new Parameters; 1948 args->setDim(arguments->dim - nparams); 1949 for (size_t i = 0; i < arguments->dim - nparams; i++) 1950 { 1951 Parameter *arg = new Parameter(STCin, (*arguments)[nparams + i]->type, NULL, NULL); 1952 (*args)[i] = arg; 1953 } 1954 1955 TypeTuple *tup = new TypeTuple(args); 1956 Expression *e = new TypeidExp(loc, tup); 1957 e = semantic(e, sc); 1958 arguments->insert(0, e); 1959 } 1960 1961 Type *tret = tf->next; 1962 if (isCtorCall) 1963 { 1964 //printf("[%s] fd = %s %s, %d %d %d\n", loc.toChars(), fd->toChars(), fd->type->toChars(), 1965 // wildmatch, tf->isWild(), fd->isolateReturn()); 1966 if (!tthis) 1967 { 1968 assert(sc->intypeof || global.errors); 1969 tthis = fd->isThis()->type->addMod(fd->type->mod); 1970 } 1971 if (tf->isWild() && !fd->isolateReturn()) 1972 { 1973 if (wildmatch) 1974 tret = tret->substWildTo(wildmatch); 1975 int offset; 1976 if (!tret->implicitConvTo(tthis) && 1977 !(MODimplicitConv(tret->mod, tthis->mod) && tret->isBaseOf(tthis, &offset) && offset == 0)) 1978 { 1979 const char* s1 = tret ->isNaked() ? " mutable" : tret ->modToChars(); 1980 const char* s2 = tthis->isNaked() ? " mutable" : tthis->modToChars(); 1981 ::error(loc, "inout constructor %s creates%s object, not%s", 1982 fd->toPrettyChars(), s1, s2); 1983 err = true; 1984 } 1985 } 1986 tret = tthis; 1987 } 1988 else if (wildmatch && tret) 1989 { 1990 /* Adjust function return type based on wildmatch 1991 */ 1992 //printf("wildmatch = x%x, tret = %s\n", wildmatch, tret->toChars()); 1993 tret = tret->substWildTo(wildmatch); 1994 } 1995 *prettype = tret; 1996 *peprefix = eprefix; 1997 return (err || olderrors != global.errors); 1998} 1999 2000/******************************** Expression **************************/ 2001 2002Expression::Expression(Loc loc, TOK op, int size) 2003{ 2004 //printf("Expression::Expression(op = %d) this = %p\n", op, this); 2005 this->loc = loc; 2006 this->op = op; 2007 this->size = (unsigned char)size; 2008 this->parens = 0; 2009 type = NULL; 2010} 2011 2012void Expression::_init() 2013{ 2014 CTFEExp::cantexp = new CTFEExp(TOKcantexp); 2015 CTFEExp::voidexp = new CTFEExp(TOKvoidexp); 2016 CTFEExp::breakexp = new CTFEExp(TOKbreak); 2017 CTFEExp::continueexp = new CTFEExp(TOKcontinue); 2018 CTFEExp::gotoexp = new CTFEExp(TOKgoto); 2019} 2020 2021Expression *Expression::syntaxCopy() 2022{ 2023 //printf("Expression::syntaxCopy()\n"); 2024 //print(); 2025 return copy(); 2026} 2027 2028/********************************* 2029 * Does *not* do a deep copy. 2030 */ 2031 2032Expression *Expression::copy() 2033{ 2034 Expression *e; 2035 if (!size) 2036 { 2037 assert(0); 2038 } 2039 void *pe = mem.xmalloc(size); 2040 //printf("Expression::copy(op = %d) e = %p\n", op, pe); 2041 e = (Expression *)memcpy(pe, (void *)this, size); 2042 return e; 2043} 2044 2045void Expression::print() 2046{ 2047 fprintf(stderr, "%s\n", toChars()); 2048 fflush(stderr); 2049} 2050 2051const char *Expression::toChars() 2052{ 2053 OutBuffer buf; 2054 HdrGenState hgs; 2055 toCBuffer(this, &buf, &hgs); 2056 return buf.extractString(); 2057} 2058 2059void Expression::error(const char *format, ...) const 2060{ 2061 if (type != Type::terror) 2062 { 2063 va_list ap; 2064 va_start(ap, format); 2065 ::verror(loc, format, ap); 2066 va_end( ap ); 2067 } 2068} 2069 2070void Expression::warning(const char *format, ...) const 2071{ 2072 if (type != Type::terror) 2073 { 2074 va_list ap; 2075 va_start(ap, format); 2076 ::vwarning(loc, format, ap); 2077 va_end( ap ); 2078 } 2079} 2080 2081void Expression::deprecation(const char *format, ...) const 2082{ 2083 if (type != Type::terror) 2084 { 2085 va_list ap; 2086 va_start(ap, format); 2087 ::vdeprecation(loc, format, ap); 2088 va_end( ap ); 2089 } 2090} 2091 2092/********************************** 2093 * Combine e1 and e2 by CommaExp if both are not NULL. 2094 */ 2095Expression *Expression::combine(Expression *e1, Expression *e2) 2096{ 2097 if (e1) 2098 { 2099 if (e2) 2100 { 2101 e1 = new CommaExp(e1->loc, e1, e2); 2102 e1->type = e2->type; 2103 } 2104 } 2105 else 2106 e1 = e2; 2107 return e1; 2108} 2109 2110/********************************** 2111 * If 'e' is a tree of commas, returns the leftmost expression 2112 * by stripping off it from the tree. The remained part of the tree 2113 * is returned via *pe0. 2114 * Otherwise 'e' is directly returned and *pe0 is set to NULL. 2115 */ 2116Expression *Expression::extractLast(Expression *e, Expression **pe0) 2117{ 2118 if (e->op != TOKcomma) 2119 { 2120 *pe0 = NULL; 2121 return e; 2122 } 2123 2124 CommaExp *ce = (CommaExp *)e; 2125 if (ce->e2->op != TOKcomma) 2126 { 2127 *pe0 = ce->e1; 2128 return ce->e2; 2129 } 2130 else 2131 { 2132 *pe0 = e; 2133 2134 Expression **pce = &ce->e2; 2135 while (((CommaExp *)(*pce))->e2->op == TOKcomma) 2136 { 2137 pce = &((CommaExp *)(*pce))->e2; 2138 } 2139 assert((*pce)->op == TOKcomma); 2140 ce = (CommaExp *)(*pce); 2141 *pce = ce->e1; 2142 2143 return ce->e2; 2144 } 2145} 2146 2147dinteger_t Expression::toInteger() 2148{ 2149 //printf("Expression %s\n", Token::toChars(op)); 2150 error("integer constant expression expected instead of %s", toChars()); 2151 return 0; 2152} 2153 2154uinteger_t Expression::toUInteger() 2155{ 2156 //printf("Expression %s\n", Token::toChars(op)); 2157 return (uinteger_t)toInteger(); 2158} 2159 2160real_t Expression::toReal() 2161{ 2162 error("floating point constant expression expected instead of %s", toChars()); 2163 return CTFloat::zero; 2164} 2165 2166real_t Expression::toImaginary() 2167{ 2168 error("floating point constant expression expected instead of %s", toChars()); 2169 return CTFloat::zero; 2170} 2171 2172complex_t Expression::toComplex() 2173{ 2174 error("floating point constant expression expected instead of %s", toChars()); 2175 return complex_t(CTFloat::zero); 2176} 2177 2178StringExp *Expression::toStringExp() 2179{ 2180 return NULL; 2181} 2182 2183TupleExp *Expression::toTupleExp() 2184{ 2185 return NULL; 2186} 2187 2188/*************************************** 2189 * Return !=0 if expression is an lvalue. 2190 */ 2191 2192bool Expression::isLvalue() 2193{ 2194 return false; 2195} 2196 2197/******************************* 2198 * Give error if we're not an lvalue. 2199 * If we can, convert expression to be an lvalue. 2200 */ 2201 2202Expression *Expression::toLvalue(Scope *, Expression *e) 2203{ 2204 if (!e) 2205 e = this; 2206 else if (!loc.filename) 2207 loc = e->loc; 2208 2209 if (e->op == TOKtype) 2210 error("%s '%s' is a type, not an lvalue", e->type->kind(), e->type->toChars()); 2211 else 2212 error("%s is not an lvalue", e->toChars()); 2213 2214 return new ErrorExp(); 2215} 2216 2217/*************************************** 2218 * Parameters: 2219 * sc: scope 2220 * flag: 1: do not issue error message for invalid modification 2221 * Returns: 2222 * 0: is not modifiable 2223 * 1: is modifiable in default == being related to type->isMutable() 2224 * 2: is modifiable, because this is a part of initializing. 2225 */ 2226 2227int Expression::checkModifiable(Scope *, int) 2228{ 2229 return type ? 1 : 0; // default modifiable 2230} 2231 2232Expression *Expression::modifiableLvalue(Scope *sc, Expression *e) 2233{ 2234 //printf("Expression::modifiableLvalue() %s, type = %s\n", toChars(), type->toChars()); 2235 2236 // See if this expression is a modifiable lvalue (i.e. not const) 2237 if (checkModifiable(sc) == 1) 2238 { 2239 assert(type); 2240 if (!type->isMutable()) 2241 { 2242 error("cannot modify %s expression %s", MODtoChars(type->mod), toChars()); 2243 return new ErrorExp(); 2244 } 2245 else if (!type->isAssignable()) 2246 { 2247 error("cannot modify struct %s %s with immutable members", toChars(), type->toChars()); 2248 return new ErrorExp(); 2249 } 2250 } 2251 return toLvalue(sc, e); 2252} 2253 2254/**************************************** 2255 * Check that the expression has a valid type. 2256 * If not, generates an error "... has no type". 2257 * Returns: 2258 * true if the expression is not valid. 2259 * Note: 2260 * When this function returns true, `checkValue()` should also return true. 2261 */ 2262bool Expression::checkType() 2263{ 2264 return false; 2265} 2266 2267/**************************************** 2268 * Check that the expression has a valid value. 2269 * If not, generates an error "... has no value". 2270 * Returns: 2271 * true if the expression is not valid or has void type. 2272 */ 2273bool Expression::checkValue() 2274{ 2275 if (type && type->toBasetype()->ty == Tvoid) 2276 { 2277 error("expression %s is void and has no value", toChars()); 2278 //print(); halt(); 2279 if (!global.gag) 2280 type = Type::terror; 2281 return true; 2282 } 2283 return false; 2284} 2285 2286bool Expression::checkScalar() 2287{ 2288 if (op == TOKerror) 2289 return true; 2290 if (type->toBasetype()->ty == Terror) 2291 return true; 2292 if (!type->isscalar()) 2293 { 2294 error("'%s' is not a scalar, it is a %s", toChars(), type->toChars()); 2295 return true; 2296 } 2297 return checkValue(); 2298} 2299 2300bool Expression::checkNoBool() 2301{ 2302 if (op == TOKerror) 2303 return true; 2304 if (type->toBasetype()->ty == Terror) 2305 return true; 2306 if (type->toBasetype()->ty == Tbool) 2307 { 2308 error("operation not allowed on bool '%s'", toChars()); 2309 return true; 2310 } 2311 return false; 2312} 2313 2314bool Expression::checkIntegral() 2315{ 2316 if (op == TOKerror) 2317 return true; 2318 if (type->toBasetype()->ty == Terror) 2319 return true; 2320 if (!type->isintegral()) 2321 { 2322 error("'%s' is not of integral type, it is a %s", toChars(), type->toChars()); 2323 return true; 2324 } 2325 return checkValue(); 2326} 2327 2328bool Expression::checkArithmetic() 2329{ 2330 if (op == TOKerror) 2331 return true; 2332 if (type->toBasetype()->ty == Terror) 2333 return true; 2334 if (!type->isintegral() && !type->isfloating()) 2335 { 2336 error("'%s' is not of arithmetic type, it is a %s", toChars(), type->toChars()); 2337 return true; 2338 } 2339 return checkValue(); 2340} 2341 2342void Expression::checkDeprecated(Scope *sc, Dsymbol *s) 2343{ 2344 s->checkDeprecated(loc, sc); 2345} 2346 2347/********************************************* 2348 * Calling function f. 2349 * Check the purity, i.e. if we're in a pure function 2350 * we can only call other pure functions. 2351 * Returns true if error occurs. 2352 */ 2353bool Expression::checkPurity(Scope *sc, FuncDeclaration *f) 2354{ 2355 if (!sc->func) 2356 return false; 2357 if (sc->func == f) 2358 return false; 2359 if (sc->intypeof == 1) 2360 return false; 2361 if (sc->flags & (SCOPEctfe | SCOPEdebug)) 2362 return false; 2363 2364 /* Given: 2365 * void f() { 2366 * pure void g() { 2367 * /+pure+/ void h() { 2368 * /+pure+/ void i() { } 2369 * } 2370 * } 2371 * } 2372 * g() can call h() but not f() 2373 * i() can call h() and g() but not f() 2374 */ 2375 2376 // Find the closest pure parent of the calling function 2377 FuncDeclaration *outerfunc = sc->func; 2378 FuncDeclaration *calledparent = f; 2379 2380 if (outerfunc->isInstantiated()) 2381 { 2382 // The attributes of outerfunc should be inferred from the call of f. 2383 } 2384 else if (f->isInstantiated()) 2385 { 2386 // The attributes of f are inferred from its body. 2387 } 2388 else if (f->isFuncLiteralDeclaration()) 2389 { 2390 // The attributes of f are always inferred in its declared place. 2391 } 2392 else 2393 { 2394 /* Today, static local functions are impure by default, but they cannot 2395 * violate purity of enclosing functions. 2396 * 2397 * auto foo() pure { // non instantiated funciton 2398 * static auto bar() { // static, without pure attribute 2399 * impureFunc(); // impure call 2400 * // Although impureFunc is called inside bar, f(= impureFunc) 2401 * // is not callable inside pure outerfunc(= foo <- bar). 2402 * } 2403 * 2404 * bar(); 2405 * // Although bar is called inside foo, f(= bar) is callable 2406 * // bacause calledparent(= foo) is same with outerfunc(= foo). 2407 * } 2408 */ 2409 2410 while (outerfunc->toParent2() && 2411 outerfunc->isPureBypassingInference() == PUREimpure && 2412 outerfunc->toParent2()->isFuncDeclaration()) 2413 { 2414 outerfunc = outerfunc->toParent2()->isFuncDeclaration(); 2415 if (outerfunc->type->ty == Terror) 2416 return true; 2417 } 2418 while (calledparent->toParent2() && 2419 calledparent->isPureBypassingInference() == PUREimpure && 2420 calledparent->toParent2()->isFuncDeclaration()) 2421 { 2422 calledparent = calledparent->toParent2()->isFuncDeclaration(); 2423 if (calledparent->type->ty == Terror) 2424 return true; 2425 } 2426 } 2427 2428 // If the caller has a pure parent, then either the called func must be pure, 2429 // OR, they must have the same pure parent. 2430 if (!f->isPure() && calledparent != outerfunc) 2431 { 2432 FuncDeclaration *ff = outerfunc; 2433 if (sc->flags & SCOPEcompile ? ff->isPureBypassingInference() >= PUREweak : ff->setImpure()) 2434 { 2435 error("pure %s '%s' cannot call impure %s '%s'", 2436 ff->kind(), ff->toPrettyChars(), f->kind(), f->toPrettyChars()); 2437 return true; 2438 } 2439 } 2440 return false; 2441} 2442 2443/******************************************* 2444 * Accessing variable v. 2445 * Check for purity and safety violations. 2446 * Returns true if error occurs. 2447 */ 2448bool Expression::checkPurity(Scope *sc, VarDeclaration *v) 2449{ 2450 //printf("v = %s %s\n", v->type->toChars(), v->toChars()); 2451 2452 /* Look for purity and safety violations when accessing variable v 2453 * from current function. 2454 */ 2455 if (!sc->func) 2456 return false; 2457 if (sc->intypeof == 1) 2458 return false; // allow violations inside typeof(expression) 2459 if (sc->flags & (SCOPEctfe | SCOPEdebug)) 2460 return false; // allow violations inside compile-time evaluated expressions and debug conditionals 2461 if (v->ident == Id::ctfe) 2462 return false; // magic variable never violates pure and safe 2463 if (v->isImmutable()) 2464 return false; // always safe and pure to access immutables... 2465 if (v->isConst() && !v->isRef() && (v->isDataseg() || v->isParameter()) && 2466 v->type->implicitConvTo(v->type->immutableOf())) 2467 return false; // or const global/parameter values which have no mutable indirections 2468 if (v->storage_class & STCmanifest) 2469 return false; // ...or manifest constants 2470 2471 bool err = false; 2472 if (v->isDataseg()) 2473 { 2474 // Bugzilla 7533: Accessing implicit generated __gate is pure. 2475 if (v->ident == Id::gate) 2476 return false; 2477 2478 /* Accessing global mutable state. 2479 * Therefore, this function and all its immediately enclosing 2480 * functions must be pure. 2481 */ 2482 /* Today, static local functions are impure by default, but they cannot 2483 * violate purity of enclosing functions. 2484 * 2485 * auto foo() pure { // non instantiated funciton 2486 * static auto bar() { // static, without pure attribute 2487 * globalData++; // impure access 2488 * // Although globalData is accessed inside bar, 2489 * // it is not accessible inside pure foo. 2490 * } 2491 * } 2492 */ 2493 for (Dsymbol *s = sc->func; s; s = s->toParent2()) 2494 { 2495 FuncDeclaration *ff = s->isFuncDeclaration(); 2496 if (!ff) 2497 break; 2498 if (sc->flags & SCOPEcompile ? ff->isPureBypassingInference() >= PUREweak : ff->setImpure()) 2499 { 2500 error("pure %s '%s' cannot access mutable static data '%s'", 2501 ff->kind(), ff->toPrettyChars(), v->toChars()); 2502 err = true; 2503 break; 2504 } 2505 /* If the enclosing is an instantiated function or a lambda, its 2506 * attribute inference result is preferred. 2507 */ 2508 if (ff->isInstantiated()) 2509 break; 2510 if (ff->isFuncLiteralDeclaration()) 2511 break; 2512 } 2513 } 2514 else 2515 { 2516 /* Given: 2517 * void f() { 2518 * int fx; 2519 * pure void g() { 2520 * int gx; 2521 * /+pure+/ void h() { 2522 * int hx; 2523 * /+pure+/ void i() { } 2524 * } 2525 * } 2526 * } 2527 * i() can modify hx and gx but not fx 2528 */ 2529 2530 Dsymbol *vparent = v->toParent2(); 2531 for (Dsymbol *s = sc->func; !err && s; s = s->toParent2()) 2532 { 2533 if (s == vparent) 2534 break; 2535 2536 if (AggregateDeclaration *ad = s->isAggregateDeclaration()) 2537 { 2538 if (ad->isNested()) 2539 continue; 2540 break; 2541 } 2542 FuncDeclaration *ff = s->isFuncDeclaration(); 2543 if (!ff) 2544 break; 2545 if (ff->isNested() || ff->isThis()) 2546 { 2547 if (ff->type->isImmutable() || 2548 (ff->type->isShared() && !MODimplicitConv(ff->type->mod, v->type->mod))) 2549 { 2550 OutBuffer ffbuf; 2551 OutBuffer vbuf; 2552 MODMatchToBuffer(&ffbuf, ff->type->mod, v->type->mod); 2553 MODMatchToBuffer(&vbuf, v->type->mod, ff->type->mod); 2554 error("%s%s '%s' cannot access %sdata '%s'", 2555 ffbuf.peekString(), ff->kind(), ff->toPrettyChars(), vbuf.peekString(), v->toChars()); 2556 err = true; 2557 break; 2558 } 2559 continue; 2560 } 2561 break; 2562 } 2563 } 2564 2565 /* Do not allow safe functions to access __gshared data 2566 */ 2567 if (v->storage_class & STCgshared) 2568 { 2569 if (sc->func->setUnsafe()) 2570 { 2571 error("safe %s '%s' cannot access __gshared data '%s'", 2572 sc->func->kind(), sc->func->toChars(), v->toChars()); 2573 err = true; 2574 } 2575 } 2576 2577 return err; 2578} 2579 2580/********************************************* 2581 * Calling function f. 2582 * Check the safety, i.e. if we're in a @safe function 2583 * we can only call @safe or @trusted functions. 2584 * Returns true if error occurs. 2585 */ 2586bool Expression::checkSafety(Scope *sc, FuncDeclaration *f) 2587{ 2588 if (!sc->func) 2589 return false; 2590 if (sc->func == f) 2591 return false; 2592 if (sc->intypeof == 1) 2593 return false; 2594 if (sc->flags & SCOPEctfe) 2595 return false; 2596 2597 if (!f->isSafe() && !f->isTrusted()) 2598 { 2599 if (sc->flags & SCOPEcompile ? sc->func->isSafeBypassingInference() : sc->func->setUnsafe()) 2600 { 2601 if (loc.linnum == 0) // e.g. implicitly generated dtor 2602 loc = sc->func->loc; 2603 2604 error("@safe %s '%s' cannot call @system %s '%s'", 2605 sc->func->kind(), sc->func->toPrettyChars(), f->kind(), f->toPrettyChars()); 2606 return true; 2607 } 2608 } 2609 return false; 2610} 2611 2612/********************************************* 2613 * Calling function f. 2614 * Check the @nogc-ness, i.e. if we're in a @nogc function 2615 * we can only call other @nogc functions. 2616 * Returns true if error occurs. 2617 */ 2618bool Expression::checkNogc(Scope *sc, FuncDeclaration *f) 2619{ 2620 if (!sc->func) 2621 return false; 2622 if (sc->func == f) 2623 return false; 2624 if (sc->intypeof == 1) 2625 return false; 2626 if (sc->flags & SCOPEctfe) 2627 return false; 2628 2629 if (!f->isNogc()) 2630 { 2631 if (sc->flags & SCOPEcompile ? sc->func->isNogcBypassingInference() : sc->func->setGC()) 2632 { 2633 if (loc.linnum == 0) // e.g. implicitly generated dtor 2634 loc = sc->func->loc; 2635 2636 error("@nogc %s '%s' cannot call non-@nogc %s '%s'", 2637 sc->func->kind(), sc->func->toPrettyChars(), f->kind(), f->toPrettyChars()); 2638 return true; 2639 } 2640 } 2641 return false; 2642} 2643 2644/******************************************** 2645 * Check that the postblit is callable if t is an array of structs. 2646 * Returns true if error happens. 2647 */ 2648bool Expression::checkPostblit(Scope *sc, Type *t) 2649{ 2650 t = t->baseElemOf(); 2651 if (t->ty == Tstruct) 2652 { 2653 if (global.params.useTypeInfo && Type::dtypeinfo) 2654 { 2655 // Bugzilla 11395: Require TypeInfo generation for array concatenation 2656 semanticTypeInfo(sc, t); 2657 } 2658 2659 StructDeclaration *sd = ((TypeStruct *)t)->sym; 2660 if (sd->postblit) 2661 { 2662 if (sd->postblit->storage_class & STCdisable) 2663 { 2664 sd->error(loc, "is not copyable because it is annotated with @disable"); 2665 return true; 2666 } 2667 //checkDeprecated(sc, sd->postblit); // necessary? 2668 checkPurity(sc, sd->postblit); 2669 checkSafety(sc, sd->postblit); 2670 checkNogc(sc, sd->postblit); 2671 //checkAccess(sd, loc, sc, sd->postblit); // necessary? 2672 return false; 2673 } 2674 } 2675 return false; 2676} 2677 2678bool Expression::checkRightThis(Scope *sc) 2679{ 2680 if (op == TOKerror) 2681 return true; 2682 if (op == TOKvar && type->ty != Terror) 2683 { 2684 VarExp *ve = (VarExp *)this; 2685 if (isNeedThisScope(sc, ve->var)) 2686 { 2687 //printf("checkRightThis sc->intypeof = %d, ad = %p, func = %p, fdthis = %p\n", 2688 // sc->intypeof, sc->getStructClassScope(), func, fdthis); 2689 error("need 'this' for '%s' of type '%s'", ve->var->toChars(), ve->var->type->toChars()); 2690 return true; 2691 } 2692 } 2693 return false; 2694} 2695 2696/******************************* 2697 * Check whether the expression allows RMW operations, error with rmw operator diagnostic if not. 2698 * ex is the RHS expression, or NULL if ++/-- is used (for diagnostics) 2699 * Returns true if error occurs. 2700 */ 2701bool Expression::checkReadModifyWrite(TOK rmwOp, Expression *ex) 2702{ 2703 //printf("Expression::checkReadModifyWrite() %s %s", toChars(), ex ? ex->toChars() : ""); 2704 if (!type || !type->isShared()) 2705 return false; 2706 2707 // atomicOp uses opAssign (+=/-=) rather than opOp (++/--) for the CT string literal. 2708 switch (rmwOp) 2709 { 2710 case TOKplusplus: 2711 case TOKpreplusplus: 2712 rmwOp = TOKaddass; 2713 break; 2714 2715 case TOKminusminus: 2716 case TOKpreminusminus: 2717 rmwOp = TOKminass; 2718 break; 2719 2720 default: 2721 break; 2722 } 2723 2724 deprecation("read-modify-write operations are not allowed for shared variables. " 2725 "Use core.atomic.atomicOp!\"%s\"(%s, %s) instead.", 2726 Token::tochars[rmwOp], toChars(), ex ? ex->toChars() : "1"); 2727 return false; 2728 2729 // note: enable when deprecation becomes an error. 2730 // return true; 2731} 2732 2733/***************************** 2734 * If expression can be tested for true or false, 2735 * returns the modified expression. 2736 * Otherwise returns ErrorExp. 2737 */ 2738Expression *Expression::toBoolean(Scope *sc) 2739{ 2740 // Default is 'yes' - do nothing 2741 Expression *e = this; 2742 Type *t = type; 2743 Type *tb = type->toBasetype(); 2744 Type *att = NULL; 2745Lagain: 2746 // Structs can be converted to bool using opCast(bool)() 2747 if (tb->ty == Tstruct) 2748 { 2749 AggregateDeclaration *ad = ((TypeStruct *)tb)->sym; 2750 /* Don't really need to check for opCast first, but by doing so we 2751 * get better error messages if it isn't there. 2752 */ 2753 Dsymbol *fd = search_function(ad, Id::_cast); 2754 if (fd) 2755 { 2756 e = new CastExp(loc, e, Type::tbool); 2757 e = semantic(e, sc); 2758 return e; 2759 } 2760 2761 // Forward to aliasthis. 2762 if (ad->aliasthis && tb != att) 2763 { 2764 if (!att && tb->checkAliasThisRec()) 2765 att = tb; 2766 e = resolveAliasThis(sc, e); 2767 t = e->type; 2768 tb = e->type->toBasetype(); 2769 goto Lagain; 2770 } 2771 } 2772 2773 if (!t->isBoolean()) 2774 { 2775 if (tb != Type::terror) 2776 error("expression %s of type %s does not have a boolean value", toChars(), t->toChars()); 2777 return new ErrorExp(); 2778 } 2779 return e; 2780} 2781 2782/****************************** 2783 * Take address of expression. 2784 */ 2785 2786Expression *Expression::addressOf() 2787{ 2788 //printf("Expression::addressOf()\n"); 2789 Expression *e = new AddrExp(loc, this); 2790 e->type = type->pointerTo(); 2791 return e; 2792} 2793 2794/****************************** 2795 * If this is a reference, dereference it. 2796 */ 2797 2798Expression *Expression::deref() 2799{ 2800 //printf("Expression::deref()\n"); 2801 // type could be null if forward referencing an 'auto' variable 2802 if (type && type->ty == Treference) 2803 { 2804 Expression *e = new PtrExp(loc, this); 2805 e->type = ((TypeReference *)type)->next; 2806 return e; 2807 } 2808 return this; 2809} 2810 2811/******************************** 2812 * Does this expression statically evaluate to a boolean 'result' (true or false)? 2813 */ 2814bool Expression::isBool(bool) 2815{ 2816 return false; 2817} 2818 2819/**************************************** 2820 * Resolve __FILE__, __LINE__, __MODULE__, __FUNCTION__, __PRETTY_FUNCTION__ to loc. 2821 */ 2822 2823Expression *Expression::resolveLoc(Loc, Scope *) 2824{ 2825 return this; 2826} 2827 2828Expressions *Expression::arraySyntaxCopy(Expressions *exps) 2829{ 2830 Expressions *a = NULL; 2831 if (exps) 2832 { 2833 a = new Expressions(); 2834 a->setDim(exps->dim); 2835 for (size_t i = 0; i < a->dim; i++) 2836 { 2837 Expression *e = (*exps)[i]; 2838 (*a)[i] = e ? e->syntaxCopy() : NULL; 2839 } 2840 } 2841 return a; 2842} 2843 2844/************************************************ 2845 * Destructors are attached to VarDeclarations. 2846 * Hence, if expression returns a temp that needs a destructor, 2847 * make sure and create a VarDeclaration for that temp. 2848 */ 2849 2850Expression *Expression::addDtorHook(Scope *) 2851{ 2852 return this; 2853} 2854 2855/******************************** IntegerExp **************************/ 2856 2857IntegerExp::IntegerExp(Loc loc, dinteger_t value, Type *type) 2858 : Expression(loc, TOKint64, sizeof(IntegerExp)) 2859{ 2860 //printf("IntegerExp(value = %lld, type = '%s')\n", value, type ? type->toChars() : ""); 2861 assert(type); 2862 if (!type->isscalar()) 2863 { 2864 //printf("%s, loc = %d\n", toChars(), loc.linnum); 2865 if (type->ty != Terror) 2866 error("integral constant must be scalar type, not %s", type->toChars()); 2867 type = Type::terror; 2868 } 2869 this->type = type; 2870 setInteger(value); 2871} 2872 2873IntegerExp::IntegerExp(dinteger_t value) 2874 : Expression(Loc(), TOKint64, sizeof(IntegerExp)) 2875{ 2876 this->type = Type::tint32; 2877 this->value = (d_int32) value; 2878} 2879 2880IntegerExp *IntegerExp::create(Loc loc, dinteger_t value, Type *type) 2881{ 2882 return new IntegerExp(loc, value, type); 2883} 2884 2885bool IntegerExp::equals(RootObject *o) 2886{ 2887 if (this == o) 2888 return true; 2889 if (((Expression *)o)->op == TOKint64) 2890 { 2891 IntegerExp *ne = (IntegerExp *)o; 2892 if (type->toHeadMutable()->equals(ne->type->toHeadMutable()) && 2893 value == ne->value) 2894 { 2895 return true; 2896 } 2897 } 2898 return false; 2899} 2900 2901void IntegerExp::setInteger(dinteger_t value) 2902{ 2903 this->value = value; 2904 normalize(); 2905} 2906 2907void IntegerExp::normalize() 2908{ 2909 /* 'Normalize' the value of the integer to be in range of the type 2910 */ 2911 switch (type->toBasetype()->ty) 2912 { 2913 case Tbool: value = (value != 0); break; 2914 case Tint8: value = (d_int8) value; break; 2915 case Tchar: 2916 case Tuns8: value = (d_uns8) value; break; 2917 case Tint16: value = (d_int16) value; break; 2918 case Twchar: 2919 case Tuns16: value = (d_uns16) value; break; 2920 case Tint32: value = (d_int32) value; break; 2921 case Tdchar: 2922 case Tuns32: value = (d_uns32) value; break; 2923 case Tint64: value = (d_int64) value; break; 2924 case Tuns64: value = (d_uns64) value; break; 2925 case Tpointer: 2926 if (Target::ptrsize == 8) 2927 value = (d_uns64) value; 2928 else if (Target::ptrsize == 4) 2929 value = (d_uns32) value; 2930 else if (Target::ptrsize == 2) 2931 value = (d_uns16) value; 2932 else 2933 assert(0); 2934 break; 2935 default: 2936 break; 2937 } 2938} 2939 2940dinteger_t IntegerExp::toInteger() 2941{ 2942 normalize(); // necessary until we fix all the paints of 'type' 2943 return value; 2944} 2945 2946real_t IntegerExp::toReal() 2947{ 2948 normalize(); // necessary until we fix all the paints of 'type' 2949 Type *t = type->toBasetype(); 2950 if (t->ty == Tuns64) 2951 return ldouble((d_uns64)value); 2952 else 2953 return ldouble((d_int64)value); 2954} 2955 2956real_t IntegerExp::toImaginary() 2957{ 2958 return CTFloat::zero; 2959} 2960 2961complex_t IntegerExp::toComplex() 2962{ 2963 return (complex_t)toReal(); 2964} 2965 2966bool IntegerExp::isBool(bool result) 2967{ 2968 bool r = toInteger() != 0; 2969 return result ? r : !r; 2970} 2971 2972Expression *IntegerExp::toLvalue(Scope *, Expression *e) 2973{ 2974 if (!e) 2975 e = this; 2976 else if (!loc.filename) 2977 loc = e->loc; 2978 e->error("constant %s is not an lvalue", e->toChars()); 2979 return new ErrorExp(); 2980} 2981 2982/******************************** ErrorExp **************************/ 2983 2984/* Use this expression for error recovery. 2985 * It should behave as a 'sink' to prevent further cascaded error messages. 2986 */ 2987 2988ErrorExp::ErrorExp() 2989 : Expression(Loc(), TOKerror, sizeof(ErrorExp)) 2990{ 2991 type = Type::terror; 2992} 2993 2994Expression *ErrorExp::toLvalue(Scope *, Expression *) 2995{ 2996 return this; 2997} 2998 2999/******************************** RealExp **************************/ 3000 3001RealExp::RealExp(Loc loc, real_t value, Type *type) 3002 : Expression(loc, TOKfloat64, sizeof(RealExp)) 3003{ 3004 //printf("RealExp::RealExp(%Lg)\n", value); 3005 this->value = value; 3006 this->type = type; 3007} 3008 3009RealExp *RealExp::create(Loc loc, real_t value, Type *type) 3010{ 3011 return new RealExp(loc, value,type); 3012} 3013 3014dinteger_t RealExp::toInteger() 3015{ 3016 return (sinteger_t) toReal(); 3017} 3018 3019uinteger_t RealExp::toUInteger() 3020{ 3021 return (uinteger_t) toReal(); 3022} 3023 3024real_t RealExp::toReal() 3025{ 3026 return type->isreal() ? value : CTFloat::zero; 3027} 3028 3029real_t RealExp::toImaginary() 3030{ 3031 return type->isreal() ? CTFloat::zero : value; 3032} 3033 3034complex_t RealExp::toComplex() 3035{ 3036 return complex_t(toReal(), toImaginary()); 3037} 3038 3039/******************************** 3040 * Test to see if two reals are the same. 3041 * Regard NaN's as equivalent. 3042 * Regard +0 and -0 as different. 3043 */ 3044 3045int RealEquals(real_t x1, real_t x2) 3046{ 3047 return (CTFloat::isNaN(x1) && CTFloat::isNaN(x2)) || 3048 CTFloat::isIdentical(x1, x2); 3049} 3050 3051bool RealExp::equals(RootObject *o) 3052{ 3053 if (this == o) 3054 return true; 3055 if (((Expression *)o)->op == TOKfloat64) 3056 { 3057 RealExp *ne = (RealExp *)o; 3058 if (type->toHeadMutable()->equals(ne->type->toHeadMutable()) && 3059 RealEquals(value, ne->value)) 3060 { 3061 return true; 3062 } 3063 } 3064 return false; 3065} 3066 3067bool RealExp::isBool(bool result) 3068{ 3069 return result ? (bool)value : !(bool)value; 3070} 3071 3072/******************************** ComplexExp **************************/ 3073 3074ComplexExp::ComplexExp(Loc loc, complex_t value, Type *type) 3075 : Expression(loc, TOKcomplex80, sizeof(ComplexExp)), value(value) 3076{ 3077 this->type = type; 3078 //printf("ComplexExp::ComplexExp(%s)\n", toChars()); 3079} 3080 3081ComplexExp *ComplexExp::create(Loc loc, complex_t value, Type *type) 3082{ 3083 return new ComplexExp(loc, value, type); 3084} 3085 3086dinteger_t ComplexExp::toInteger() 3087{ 3088 return (sinteger_t) toReal(); 3089} 3090 3091uinteger_t ComplexExp::toUInteger() 3092{ 3093 return (uinteger_t) toReal(); 3094} 3095 3096real_t ComplexExp::toReal() 3097{ 3098 return creall(value); 3099} 3100 3101real_t ComplexExp::toImaginary() 3102{ 3103 return cimagl(value); 3104} 3105 3106complex_t ComplexExp::toComplex() 3107{ 3108 return value; 3109} 3110 3111bool ComplexExp::equals(RootObject *o) 3112{ 3113 if (this == o) 3114 return true; 3115 if (((Expression *)o)->op == TOKcomplex80) 3116 { 3117 ComplexExp *ne = (ComplexExp *)o; 3118 if (type->toHeadMutable()->equals(ne->type->toHeadMutable()) && 3119 RealEquals(creall(value), creall(ne->value)) && 3120 RealEquals(cimagl(value), cimagl(ne->value))) 3121 { 3122 return true; 3123 } 3124 } 3125 return false; 3126} 3127 3128bool ComplexExp::isBool(bool result) 3129{ 3130 if (result) 3131 return (bool)(value); 3132 else 3133 return !value; 3134} 3135 3136/******************************** IdentifierExp **************************/ 3137 3138IdentifierExp::IdentifierExp(Loc loc, Identifier *ident) 3139 : Expression(loc, TOKidentifier, sizeof(IdentifierExp)) 3140{ 3141 this->ident = ident; 3142} 3143 3144IdentifierExp *IdentifierExp::create(Loc loc, Identifier *ident) 3145{ 3146 return new IdentifierExp(loc, ident); 3147} 3148 3149bool IdentifierExp::isLvalue() 3150{ 3151 return true; 3152} 3153 3154Expression *IdentifierExp::toLvalue(Scope *, Expression *) 3155{ 3156 return this; 3157} 3158 3159/******************************** DollarExp **************************/ 3160 3161DollarExp::DollarExp(Loc loc) 3162 : IdentifierExp(loc, Id::dollar) 3163{ 3164} 3165 3166/******************************** DsymbolExp **************************/ 3167 3168DsymbolExp::DsymbolExp(Loc loc, Dsymbol *s, bool hasOverloads) 3169 : Expression(loc, TOKdsymbol, sizeof(DsymbolExp)) 3170{ 3171 this->s = s; 3172 this->hasOverloads = hasOverloads; 3173} 3174 3175/**************************************** 3176 * Resolve a symbol `s` and wraps it in an expression object. 3177 * Params: 3178 * hasOverloads = works if the aliased symbol is a function. 3179 * true: it's overloaded and will be resolved later. 3180 * false: it's exact function symbol. 3181 */ 3182Expression *resolve(Loc loc, Scope *sc, Dsymbol *s, bool hasOverloads) 3183{ 3184Lagain: 3185 Expression *e; 3186 3187 //printf("DsymbolExp:: %p '%s' is a symbol\n", this, toChars()); 3188 //printf("s = '%s', s->kind = '%s'\n", s->toChars(), s->kind()); 3189 Dsymbol *olds = s; 3190 Declaration *d = s->isDeclaration(); 3191 if (d && (d->storage_class & STCtemplateparameter)) 3192 { 3193 s = s->toAlias(); 3194 } 3195 else 3196 { 3197 if (!s->isFuncDeclaration()) // functions are checked after overloading 3198 s->checkDeprecated(loc, sc); 3199 3200 // Bugzilla 12023: if 's' is a tuple variable, the tuple is returned. 3201 s = s->toAlias(); 3202 3203 //printf("s = '%s', s->kind = '%s', s->needThis() = %p\n", s->toChars(), s->kind(), s->needThis()); 3204 if (s != olds && !s->isFuncDeclaration()) 3205 s->checkDeprecated(loc, sc); 3206 } 3207 3208 if (EnumMember *em = s->isEnumMember()) 3209 { 3210 return em->getVarExp(loc, sc); 3211 } 3212 if (VarDeclaration *v = s->isVarDeclaration()) 3213 { 3214 //printf("Identifier '%s' is a variable, type '%s'\n", toChars(), v->type->toChars()); 3215 if (!v->type || // during variable type inference 3216 (!v->type->deco && v->inuse)) // during variable type semantic 3217 { 3218 if (v->inuse) // variable type depends on the variable itself 3219 ::error(loc, "circular reference to %s '%s'", v->kind(), v->toPrettyChars()); 3220 else // variable type cannot be determined 3221 ::error(loc, "forward reference to %s '%s'", v->kind(), v->toPrettyChars()); 3222 return new ErrorExp(); 3223 } 3224 if (v->type->ty == Terror) 3225 return new ErrorExp(); 3226 3227 if ((v->storage_class & STCmanifest) && v->_init) 3228 { 3229 if (v->inuse) 3230 { 3231 ::error(loc, "circular initialization of %s '%s'", v->kind(), v->toPrettyChars()); 3232 return new ErrorExp(); 3233 } 3234 3235 e = v->expandInitializer(loc); 3236 v->inuse++; 3237 e = semantic(e, sc); 3238 v->inuse--; 3239 return e; 3240 } 3241 3242 // Change the ancestor lambdas to delegate before hasThis(sc) call. 3243 if (v->checkNestedReference(sc, loc)) 3244 return new ErrorExp(); 3245 3246 if (v->needThis() && hasThis(sc)) 3247 e = new DotVarExp(loc, new ThisExp(loc), v); 3248 else 3249 e = new VarExp(loc, v); 3250 e = semantic(e, sc); 3251 return e; 3252 } 3253 if (FuncLiteralDeclaration *fld = s->isFuncLiteralDeclaration()) 3254 { 3255 //printf("'%s' is a function literal\n", fld->toChars()); 3256 e = new FuncExp(loc, fld); 3257 return semantic(e, sc); 3258 } 3259 if (FuncDeclaration *f = s->isFuncDeclaration()) 3260 { 3261 f = f->toAliasFunc(); 3262 if (!f->functionSemantic()) 3263 return new ErrorExp(); 3264 3265 if (!hasOverloads && f->checkForwardRef(loc)) 3266 return new ErrorExp(); 3267 3268 FuncDeclaration *fd = s->isFuncDeclaration(); 3269 fd->type = f->type; 3270 return new VarExp(loc, fd, hasOverloads); 3271 } 3272 if (OverDeclaration *od = s->isOverDeclaration()) 3273 { 3274 e = new VarExp(loc, od, true); 3275 e->type = Type::tvoid; 3276 return e; 3277 } 3278 if (OverloadSet *o = s->isOverloadSet()) 3279 { 3280 //printf("'%s' is an overload set\n", o->toChars()); 3281 return new OverExp(loc, o); 3282 } 3283 3284 if (Import *imp = s->isImport()) 3285 { 3286 if (!imp->pkg) 3287 { 3288 ::error(loc, "forward reference of import %s", imp->toChars()); 3289 return new ErrorExp(); 3290 } 3291 ScopeExp *ie = new ScopeExp(loc, imp->pkg); 3292 return semantic(ie, sc); 3293 } 3294 if (Package *pkg = s->isPackage()) 3295 { 3296 ScopeExp *ie = new ScopeExp(loc, pkg); 3297 return semantic(ie, sc); 3298 } 3299 if (Module *mod = s->isModule()) 3300 { 3301 ScopeExp *ie = new ScopeExp(loc, mod); 3302 return semantic(ie, sc); 3303 } 3304 3305 if (Nspace *ns = s->isNspace()) 3306 { 3307 ScopeExp *ie = new ScopeExp(loc, ns); 3308 return semantic(ie, sc); 3309 } 3310 3311 if (Type *t = s->getType()) 3312 { 3313 return semantic(new TypeExp(loc, t), sc); 3314 } 3315 3316 if (TupleDeclaration *tup = s->isTupleDeclaration()) 3317 { 3318 if (tup->needThis() && hasThis(sc)) 3319 e = new DotVarExp(loc, new ThisExp(loc), tup); 3320 else 3321 e = new TupleExp(loc, tup); 3322 e = semantic(e, sc); 3323 return e; 3324 } 3325 3326 if (TemplateInstance *ti = s->isTemplateInstance()) 3327 { 3328 ti->semantic(sc); 3329 if (!ti->inst || ti->errors) 3330 return new ErrorExp(); 3331 s = ti->toAlias(); 3332 if (!s->isTemplateInstance()) 3333 goto Lagain; 3334 e = new ScopeExp(loc, ti); 3335 e = semantic(e, sc); 3336 return e; 3337 } 3338 if (TemplateDeclaration *td = s->isTemplateDeclaration()) 3339 { 3340 Dsymbol *p = td->toParent2(); 3341 FuncDeclaration *fdthis = hasThis(sc); 3342 AggregateDeclaration *ad = p ? p->isAggregateDeclaration() : NULL; 3343 if (fdthis && ad && isAggregate(fdthis->vthis->type) == ad && 3344 (td->_scope->stc & STCstatic) == 0) 3345 { 3346 e = new DotTemplateExp(loc, new ThisExp(loc), td); 3347 } 3348 else 3349 e = new TemplateExp(loc, td); 3350 e = semantic(e, sc); 3351 return e; 3352 } 3353 3354 ::error(loc, "%s '%s' is not a variable", s->kind(), s->toChars()); 3355 return new ErrorExp(); 3356} 3357 3358bool DsymbolExp::isLvalue() 3359{ 3360 return true; 3361} 3362 3363Expression *DsymbolExp::toLvalue(Scope *, Expression *) 3364{ 3365 return this; 3366} 3367 3368/******************************** ThisExp **************************/ 3369 3370ThisExp::ThisExp(Loc loc) 3371 : Expression(loc, TOKthis, sizeof(ThisExp)) 3372{ 3373 //printf("ThisExp::ThisExp() loc = %d\n", loc.linnum); 3374 var = NULL; 3375} 3376 3377bool ThisExp::isBool(bool result) 3378{ 3379 return result ? true : false; 3380} 3381 3382bool ThisExp::isLvalue() 3383{ 3384 // Class `this` should be an rvalue; struct `this` should be an lvalue. 3385 return type->toBasetype()->ty != Tclass; 3386} 3387 3388Expression *ThisExp::toLvalue(Scope *sc, Expression *e) 3389{ 3390 if (type->toBasetype()->ty == Tclass) 3391 { 3392 // Class `this` is an rvalue; struct `this` is an lvalue. 3393 return Expression::toLvalue(sc, e); 3394 } 3395 return this; 3396} 3397 3398/******************************** SuperExp **************************/ 3399 3400SuperExp::SuperExp(Loc loc) 3401 : ThisExp(loc) 3402{ 3403 op = TOKsuper; 3404} 3405 3406/******************************** NullExp **************************/ 3407 3408NullExp::NullExp(Loc loc, Type *type) 3409 : Expression(loc, TOKnull, sizeof(NullExp)) 3410{ 3411 committed = 0; 3412 this->type = type; 3413} 3414 3415bool NullExp::equals(RootObject *o) 3416{ 3417 if (o && o->dyncast() == DYNCAST_EXPRESSION) 3418 { 3419 Expression *e = (Expression *)o; 3420 if (e->op == TOKnull && 3421 type->equals(e->type)) 3422 { 3423 return true; 3424 } 3425 } 3426 return false; 3427} 3428 3429bool NullExp::isBool(bool result) 3430{ 3431 return result ? false : true; 3432} 3433 3434StringExp *NullExp::toStringExp() 3435{ 3436 if (implicitConvTo(Type::tstring)) 3437 { 3438 StringExp *se = new StringExp(loc, (char*)mem.xcalloc(1, 1), 0); 3439 se->type = Type::tstring; 3440 return se; 3441 } 3442 return NULL; 3443} 3444 3445/******************************** StringExp **************************/ 3446 3447StringExp::StringExp(Loc loc, char *string) 3448 : Expression(loc, TOKstring, sizeof(StringExp)) 3449{ 3450 this->string = string; 3451 this->len = strlen(string); 3452 this->sz = 1; 3453 this->committed = 0; 3454 this->postfix = 0; 3455 this->ownedByCtfe = OWNEDcode; 3456} 3457 3458StringExp::StringExp(Loc loc, void *string, size_t len) 3459 : Expression(loc, TOKstring, sizeof(StringExp)) 3460{ 3461 this->string = string; 3462 this->len = len; 3463 this->sz = 1; 3464 this->committed = 0; 3465 this->postfix = 0; 3466 this->ownedByCtfe = OWNEDcode; 3467} 3468 3469StringExp::StringExp(Loc loc, void *string, size_t len, utf8_t postfix) 3470 : Expression(loc, TOKstring, sizeof(StringExp)) 3471{ 3472 this->string = string; 3473 this->len = len; 3474 this->sz = 1; 3475 this->committed = 0; 3476 this->postfix = postfix; 3477 this->ownedByCtfe = OWNEDcode; 3478} 3479 3480StringExp *StringExp::create(Loc loc, char *s) 3481{ 3482 return new StringExp(loc, s); 3483} 3484 3485StringExp *StringExp::create(Loc loc, void *string, size_t len) 3486{ 3487 return new StringExp(loc, string, len); 3488} 3489 3490bool StringExp::equals(RootObject *o) 3491{ 3492 //printf("StringExp::equals('%s') %s\n", o->toChars(), toChars()); 3493 if (o && o->dyncast() == DYNCAST_EXPRESSION) 3494 { 3495 Expression *e = (Expression *)o; 3496 if (e->op == TOKstring) 3497 { 3498 return compare(o) == 0; 3499 } 3500 } 3501 return false; 3502} 3503 3504/********************************** 3505 * Return the number of code units the string would be if it were re-encoded 3506 * as tynto. 3507 * Params: 3508 * tynto = code unit type of the target encoding 3509 * Returns: 3510 * number of code units 3511 */ 3512 3513size_t StringExp::numberOfCodeUnits(int tynto) const 3514{ 3515 int encSize; 3516 switch (tynto) 3517 { 3518 case 0: return len; 3519 case Tchar: encSize = 1; break; 3520 case Twchar: encSize = 2; break; 3521 case Tdchar: encSize = 4; break; 3522 default: 3523 assert(0); 3524 } 3525 if (sz == encSize) 3526 return len; 3527 3528 size_t result = 0; 3529 dchar_t c; 3530 3531 switch (sz) 3532 { 3533 case 1: 3534 for (size_t u = 0; u < len;) 3535 { 3536 if (const char *p = utf_decodeChar((utf8_t *)string, len, &u, &c)) 3537 { 3538 error("%s", p); 3539 return 0; 3540 } 3541 result += utf_codeLength(encSize, c); 3542 } 3543 break; 3544 3545 case 2: 3546 for (size_t u = 0; u < len;) 3547 { 3548 if (const char *p = utf_decodeWchar((utf16_t *)string, len, &u, &c)) 3549 { 3550 error("%s", p); 3551 return 0; 3552 } 3553 result += utf_codeLength(encSize, c); 3554 } 3555 break; 3556 3557 case 4: 3558 for (size_t u = 0; u < len;) 3559 { 3560 c = *((utf32_t *)((char *)string + u)); 3561 u += 4; 3562 result += utf_codeLength(encSize, c); 3563 } 3564 break; 3565 3566 default: 3567 assert(0); 3568 } 3569 return result; 3570} 3571 3572/********************************************** 3573 * Write the contents of the string to dest. 3574 * Use numberOfCodeUnits() to determine size of result. 3575 * Params: 3576 * dest = destination 3577 * tyto = encoding type of the result 3578 * zero = add terminating 0 3579 */ 3580void StringExp::writeTo(void *dest, bool zero, int tyto) const 3581{ 3582 int encSize; 3583 switch (tyto) 3584 { 3585 case 0: encSize = sz; break; 3586 case Tchar: encSize = 1; break; 3587 case Twchar: encSize = 2; break; 3588 case Tdchar: encSize = 4; break; 3589 default: 3590 assert(0); 3591 } 3592 if (sz == encSize) 3593 { 3594 memcpy(dest, string, len * sz); 3595 if (zero) 3596 memset((char *)dest + len * sz, 0, sz); 3597 } 3598 else 3599 assert(0); 3600} 3601 3602/************************************************** 3603 * If the string data is UTF-8 and can be accessed directly, 3604 * return a pointer to it. 3605 * Do not assume a terminating 0. 3606 * Returns: 3607 * pointer to string data if possible, null if not 3608 */ 3609char *StringExp::toPtr() 3610{ 3611 return (sz == 1) ? (char*)string : NULL; 3612} 3613 3614StringExp *StringExp::toStringExp() 3615{ 3616 return this; 3617} 3618 3619/**************************************** 3620 * Convert string to char[]. 3621 */ 3622 3623StringExp *StringExp::toUTF8(Scope *sc) 3624{ 3625 if (sz != 1) 3626 { // Convert to UTF-8 string 3627 committed = 0; 3628 Expression *e = castTo(sc, Type::tchar->arrayOf()); 3629 e = e->optimize(WANTvalue); 3630 assert(e->op == TOKstring); 3631 StringExp *se = (StringExp *)e; 3632 assert(se->sz == 1); 3633 return se; 3634 } 3635 return this; 3636} 3637 3638int StringExp::compare(RootObject *obj) 3639{ 3640 //printf("StringExp::compare()\n"); 3641 // Used to sort case statement expressions so we can do an efficient lookup 3642 StringExp *se2 = (StringExp *)(obj); 3643 3644 // This is a kludge so isExpression() in template.c will return 5 3645 // for StringExp's. 3646 if (!se2) 3647 return 5; 3648 3649 assert(se2->op == TOKstring); 3650 3651 size_t len1 = len; 3652 size_t len2 = se2->len; 3653 3654 //printf("sz = %d, len1 = %d, len2 = %d\n", sz, (int)len1, (int)len2); 3655 if (len1 == len2) 3656 { 3657 switch (sz) 3658 { 3659 case 1: 3660 return memcmp((char *)string, (char *)se2->string, len1); 3661 3662 case 2: 3663 { 3664 d_uns16 *s1 = (d_uns16 *)string; 3665 d_uns16 *s2 = (d_uns16 *)se2->string; 3666 3667 for (size_t u = 0; u < len; u++) 3668 { 3669 if (s1[u] != s2[u]) 3670 return s1[u] - s2[u]; 3671 } 3672 } 3673 break; 3674 3675 case 4: 3676 { 3677 d_uns32 *s1 = (d_uns32 *)string; 3678 d_uns32 *s2 = (d_uns32 *)se2->string; 3679 3680 for (size_t u = 0; u < len; u++) 3681 { 3682 if (s1[u] != s2[u]) 3683 return s1[u] - s2[u]; 3684 } 3685 } 3686 break; 3687 3688 default: 3689 assert(0); 3690 } 3691 } 3692 return (int)(len1 - len2); 3693} 3694 3695bool StringExp::isBool(bool result) 3696{ 3697 return result ? true : false; 3698} 3699 3700 3701bool StringExp::isLvalue() 3702{ 3703 /* string literal is rvalue in default, but 3704 * conversion to reference of static array is only allowed. 3705 */ 3706 return (type && type->toBasetype()->ty == Tsarray); 3707} 3708 3709Expression *StringExp::toLvalue(Scope *sc, Expression *e) 3710{ 3711 //printf("StringExp::toLvalue(%s) type = %s\n", toChars(), type ? type->toChars() : NULL); 3712 return (type && type->toBasetype()->ty == Tsarray) 3713 ? this : Expression::toLvalue(sc, e); 3714} 3715 3716Expression *StringExp::modifiableLvalue(Scope *, Expression *) 3717{ 3718 error("cannot modify string literal %s", toChars()); 3719 return new ErrorExp(); 3720} 3721 3722unsigned StringExp::charAt(uinteger_t i) const 3723{ unsigned value; 3724 3725 switch (sz) 3726 { 3727 case 1: 3728 value = ((utf8_t *)string)[(size_t)i]; 3729 break; 3730 3731 case 2: 3732 value = ((unsigned short *)string)[(size_t)i]; 3733 break; 3734 3735 case 4: 3736 value = ((unsigned int *)string)[(size_t)i]; 3737 break; 3738 3739 default: 3740 assert(0); 3741 break; 3742 } 3743 return value; 3744} 3745 3746/************************ ArrayLiteralExp ************************************/ 3747 3748// [ e1, e2, e3, ... ] 3749 3750ArrayLiteralExp::ArrayLiteralExp(Loc loc, Type *type, Expressions *elements) 3751 : Expression(loc, TOKarrayliteral, sizeof(ArrayLiteralExp)) 3752{ 3753 this->basis = NULL; 3754 this->type = type; 3755 this->elements = elements; 3756 this->ownedByCtfe = OWNEDcode; 3757} 3758 3759ArrayLiteralExp::ArrayLiteralExp(Loc loc, Type *type, Expression *e) 3760 : Expression(loc, TOKarrayliteral, sizeof(ArrayLiteralExp)) 3761{ 3762 this->basis = NULL; 3763 this->type = type; 3764 elements = new Expressions; 3765 elements->push(e); 3766 this->ownedByCtfe = OWNEDcode; 3767} 3768 3769ArrayLiteralExp::ArrayLiteralExp(Loc loc, Type *type, Expression *basis, Expressions *elements) 3770 : Expression(loc, TOKarrayliteral, sizeof(ArrayLiteralExp)) 3771{ 3772 this->basis = basis; 3773 this->type = type; 3774 this->elements = elements; 3775 this->ownedByCtfe = OWNEDcode; 3776} 3777 3778ArrayLiteralExp *ArrayLiteralExp::create(Loc loc, Expressions *elements) 3779{ 3780 return new ArrayLiteralExp(loc, NULL, elements); 3781} 3782 3783bool ArrayLiteralExp::equals(RootObject *o) 3784{ 3785 if (this == o) 3786 return true; 3787 if (o && o->dyncast() == DYNCAST_EXPRESSION && 3788 ((Expression *)o)->op == TOKarrayliteral) 3789 { 3790 ArrayLiteralExp *ae = (ArrayLiteralExp *)o; 3791 if (elements->dim != ae->elements->dim) 3792 return false; 3793 if (elements->dim == 0 && 3794 !type->equals(ae->type)) 3795 { 3796 return false; 3797 } 3798 for (size_t i = 0; i < elements->dim; i++) 3799 { 3800 Expression *e1 = (*elements)[i]; 3801 Expression *e2 = (*ae->elements)[i]; 3802 if (!e1) 3803 e1 = basis; 3804 if (!e2) 3805 e2 = basis; 3806 if (e1 != e2 && 3807 (!e1 || !e2 || !e1->equals(e2))) 3808 return false; 3809 } 3810 return true; 3811 } 3812 return false; 3813} 3814 3815Expression *ArrayLiteralExp::syntaxCopy() 3816{ 3817 return new ArrayLiteralExp(loc, 3818 NULL, 3819 basis ? basis->syntaxCopy() : NULL, 3820 arraySyntaxCopy(elements)); 3821} 3822 3823Expression *ArrayLiteralExp::getElement(d_size_t i) 3824{ 3825 Expression *el = (*elements)[i]; 3826 if (!el) 3827 el = basis; 3828 return el; 3829} 3830 3831static void appendArrayLiteral(Expressions *elems, ArrayLiteralExp *ale) 3832{ 3833 if (!ale->elements) 3834 return; 3835 size_t d = elems->dim; 3836 elems->append(ale->elements); 3837 for (size_t i = d; i < elems->dim; i++) 3838 { 3839 Expression *el = (*elems)[i]; 3840 if (!el) 3841 (*elems)[i] = ale->basis; 3842 } 3843} 3844 3845/* Copy element `Expressions` in the parameters when they're `ArrayLiteralExp`s. 3846 * Params: 3847 * e1 = If it's ArrayLiteralExp, its `elements` will be copied. 3848 * Otherwise, `e1` itself will be pushed into the new `Expressions`. 3849 * e2 = If it's not `null`, it will be pushed/appended to the new 3850 * `Expressions` by the same way with `e1`. 3851 * Returns: 3852 * Newly allocated `Expressions`. Note that it points to the original 3853 * `Expression` values in e1 and e2. 3854 */ 3855Expressions* ArrayLiteralExp::copyElements(Expression *e1, Expression *e2) 3856{ 3857 Expressions *elems = new Expressions(); 3858 3859 if (e1->op == TOKarrayliteral) 3860 appendArrayLiteral(elems, (ArrayLiteralExp *)e1); 3861 else 3862 elems->push(e1); 3863 3864 if (e2) 3865 { 3866 if (e2->op == TOKarrayliteral) 3867 appendArrayLiteral(elems, (ArrayLiteralExp *)e2); 3868 else 3869 elems->push(e2); 3870 } 3871 3872 return elems; 3873} 3874 3875bool ArrayLiteralExp::isBool(bool result) 3876{ 3877 size_t dim = elements ? elements->dim : 0; 3878 return result ? (dim != 0) : (dim == 0); 3879} 3880 3881StringExp *ArrayLiteralExp::toStringExp() 3882{ 3883 TY telem = type->nextOf()->toBasetype()->ty; 3884 3885 if (telem == Tchar || telem == Twchar || telem == Tdchar || 3886 (telem == Tvoid && (!elements || elements->dim == 0))) 3887 { 3888 unsigned char sz = 1; 3889 if (telem == Twchar) sz = 2; 3890 else if (telem == Tdchar) sz = 4; 3891 3892 OutBuffer buf; 3893 if (elements) 3894 { 3895 for (size_t i = 0; i < elements->dim; ++i) 3896 { 3897 Expression *ch = getElement(i); 3898 if (ch->op != TOKint64) 3899 return NULL; 3900 if (sz == 1) 3901 buf.writeByte((unsigned)ch->toInteger()); 3902 else if (sz == 2) 3903 buf.writeword((unsigned)ch->toInteger()); 3904 else 3905 buf.write4((unsigned)ch->toInteger()); 3906 } 3907 } 3908 char prefix; 3909 if (sz == 1) { prefix = 'c'; buf.writeByte(0); } 3910 else if (sz == 2) { prefix = 'w'; buf.writeword(0); } 3911 else { prefix = 'd'; buf.write4(0); } 3912 3913 const size_t len = buf.offset / sz - 1; 3914 StringExp *se = new StringExp(loc, buf.extractData(), len, prefix); 3915 se->sz = sz; 3916 se->type = type; 3917 return se; 3918 } 3919 return NULL; 3920} 3921 3922/************************ AssocArrayLiteralExp ************************************/ 3923 3924// [ key0 : value0, key1 : value1, ... ] 3925 3926AssocArrayLiteralExp::AssocArrayLiteralExp(Loc loc, 3927 Expressions *keys, Expressions *values) 3928 : Expression(loc, TOKassocarrayliteral, sizeof(AssocArrayLiteralExp)) 3929{ 3930 assert(keys->dim == values->dim); 3931 this->keys = keys; 3932 this->values = values; 3933 this->ownedByCtfe = OWNEDcode; 3934} 3935 3936bool AssocArrayLiteralExp::equals(RootObject *o) 3937{ 3938 if (this == o) 3939 return true; 3940 if (o && o->dyncast() == DYNCAST_EXPRESSION && 3941 ((Expression *)o)->op == TOKassocarrayliteral) 3942 { 3943 AssocArrayLiteralExp *ae = (AssocArrayLiteralExp *)o; 3944 if (keys->dim != ae->keys->dim) 3945 return false; 3946 size_t count = 0; 3947 for (size_t i = 0; i < keys->dim; i++) 3948 { 3949 for (size_t j = 0; j < ae->keys->dim; j++) 3950 { 3951 if ((*keys)[i]->equals((*ae->keys)[j])) 3952 { 3953 if (!(*values)[i]->equals((*ae->values)[j])) 3954 return false; 3955 ++count; 3956 } 3957 } 3958 } 3959 return count == keys->dim; 3960 } 3961 return false; 3962} 3963 3964Expression *AssocArrayLiteralExp::syntaxCopy() 3965{ 3966 return new AssocArrayLiteralExp(loc, 3967 arraySyntaxCopy(keys), arraySyntaxCopy(values)); 3968} 3969 3970bool AssocArrayLiteralExp::isBool(bool result) 3971{ 3972 size_t dim = keys->dim; 3973 return result ? (dim != 0) : (dim == 0); 3974} 3975 3976/************************ StructLiteralExp ************************************/ 3977 3978// sd( e1, e2, e3, ... ) 3979 3980StructLiteralExp::StructLiteralExp(Loc loc, StructDeclaration *sd, Expressions *elements, Type *stype) 3981 : Expression(loc, TOKstructliteral, sizeof(StructLiteralExp)) 3982{ 3983 this->sd = sd; 3984 if (!elements) 3985 elements = new Expressions(); 3986 this->elements = elements; 3987 this->stype = stype; 3988 this->useStaticInit = false; 3989 this->sym = NULL; 3990 this->ownedByCtfe = OWNEDcode; 3991 this->origin = this; 3992 this->stageflags = 0; 3993 this->inlinecopy = NULL; 3994 //printf("StructLiteralExp::StructLiteralExp(%s)\n", toChars()); 3995} 3996 3997StructLiteralExp *StructLiteralExp::create(Loc loc, StructDeclaration *sd, void *elements, Type *stype) 3998{ 3999 return new StructLiteralExp(loc, sd, (Expressions *)elements, stype); 4000} 4001 4002bool StructLiteralExp::equals(RootObject *o) 4003{ 4004 if (this == o) 4005 return true; 4006 if (o && o->dyncast() == DYNCAST_EXPRESSION && 4007 ((Expression *)o)->op == TOKstructliteral) 4008 { 4009 StructLiteralExp *se = (StructLiteralExp *)o; 4010 if (!type->equals(se->type)) 4011 return false; 4012 if (elements->dim != se->elements->dim) 4013 return false; 4014 for (size_t i = 0; i < elements->dim; i++) 4015 { 4016 Expression *e1 = (*elements)[i]; 4017 Expression *e2 = (*se->elements)[i]; 4018 if (e1 != e2 && 4019 (!e1 || !e2 || !e1->equals(e2))) 4020 return false; 4021 } 4022 return true; 4023 } 4024 return false; 4025} 4026 4027Expression *StructLiteralExp::syntaxCopy() 4028{ 4029 StructLiteralExp *exp = new StructLiteralExp(loc, sd, arraySyntaxCopy(elements), type ? type : stype); 4030 exp->origin = this; 4031 return exp; 4032} 4033 4034Expression *StructLiteralExp::addDtorHook(Scope *sc) 4035{ 4036 /* If struct requires a destructor, rewrite as: 4037 * (S tmp = S()),tmp 4038 * so that the destructor can be hung on tmp. 4039 */ 4040 if (sd->dtor && sc->func) 4041 { 4042 /* Make an identifier for the temporary of the form: 4043 * __sl%s%d, where %s is the struct name 4044 */ 4045 const size_t len = 10; 4046 char buf[len + 1]; 4047 buf[len] = 0; 4048 strcpy(buf, "__sl"); 4049 strncat(buf, sd->ident->toChars(), len - 4 - 1); 4050 assert(buf[len] == 0); 4051 4052 VarDeclaration *tmp = copyToTemp(0, buf, this); 4053 Expression *ae = new DeclarationExp(loc, tmp); 4054 Expression *e = new CommaExp(loc, ae, new VarExp(loc, tmp)); 4055 e = semantic(e, sc); 4056 return e; 4057 } 4058 return this; 4059} 4060 4061/************************************** 4062 * Gets expression at offset of type. 4063 * Returns NULL if not found. 4064 */ 4065 4066Expression *StructLiteralExp::getField(Type *type, unsigned offset) 4067{ 4068 //printf("StructLiteralExp::getField(this = %s, type = %s, offset = %u)\n", 4069 // /*toChars()*/"", type->toChars(), offset); 4070 Expression *e = NULL; 4071 int i = getFieldIndex(type, offset); 4072 4073 if (i != -1) 4074 { 4075 //printf("\ti = %d\n", i); 4076 if (i == (int)sd->fields.dim - 1 && sd->isNested()) 4077 return NULL; 4078 4079 assert(i < (int)elements->dim); 4080 e = (*elements)[i]; 4081 if (e) 4082 { 4083 //printf("e = %s, e->type = %s\n", e->toChars(), e->type->toChars()); 4084 4085 /* If type is a static array, and e is an initializer for that array, 4086 * then the field initializer should be an array literal of e. 4087 */ 4088 if (e->type->castMod(0) != type->castMod(0) && type->ty == Tsarray) 4089 { TypeSArray *tsa = (TypeSArray *)type; 4090 size_t length = (size_t)tsa->dim->toInteger(); 4091 Expressions *z = new Expressions; 4092 z->setDim(length); 4093 for (size_t q = 0; q < length; ++q) 4094 (*z)[q] = e->copy(); 4095 e = new ArrayLiteralExp(loc, type, z); 4096 } 4097 else 4098 { 4099 e = e->copy(); 4100 e->type = type; 4101 } 4102 if (useStaticInit && e->op == TOKstructliteral && 4103 e->type->needsNested()) 4104 { 4105 StructLiteralExp *se = (StructLiteralExp *)e; 4106 se->useStaticInit = true; 4107 } 4108 } 4109 } 4110 return e; 4111} 4112 4113/************************************ 4114 * Get index of field. 4115 * Returns -1 if not found. 4116 */ 4117 4118int StructLiteralExp::getFieldIndex(Type *type, unsigned offset) 4119{ 4120 /* Find which field offset is by looking at the field offsets 4121 */ 4122 if (elements->dim) 4123 { 4124 for (size_t i = 0; i < sd->fields.dim; i++) 4125 { 4126 VarDeclaration *v = sd->fields[i]; 4127 4128 if (offset == v->offset && 4129 type->size() == v->type->size()) 4130 { 4131 /* context field might not be filled. */ 4132 if (i == sd->fields.dim - 1 && sd->isNested()) 4133 return (int)i; 4134 Expression *e = (*elements)[i]; 4135 if (e) 4136 { 4137 return (int)i; 4138 } 4139 break; 4140 } 4141 } 4142 } 4143 return -1; 4144} 4145 4146/************************ TypeDotIdExp ************************************/ 4147 4148/* Things like: 4149 * int.size 4150 * foo.size 4151 * (foo).size 4152 * cast(foo).size 4153 */ 4154 4155DotIdExp *typeDotIdExp(Loc loc, Type *type, Identifier *ident) 4156{ 4157 return new DotIdExp(loc, new TypeExp(loc, type), ident); 4158} 4159 4160 4161/************************************************************/ 4162 4163// Mainly just a placeholder 4164 4165TypeExp::TypeExp(Loc loc, Type *type) 4166 : Expression(loc, TOKtype, sizeof(TypeExp)) 4167{ 4168 //printf("TypeExp::TypeExp(%s)\n", type->toChars()); 4169 this->type = type; 4170} 4171 4172Expression *TypeExp::syntaxCopy() 4173{ 4174 return new TypeExp(loc, type->syntaxCopy()); 4175} 4176 4177bool TypeExp::checkType() 4178{ 4179 error("type %s is not an expression", toChars()); 4180 return true; 4181} 4182 4183bool TypeExp::checkValue() 4184{ 4185 error("type %s has no value", toChars()); 4186 return true; 4187} 4188 4189/************************************************************/ 4190 4191/*********************************************************** 4192 * Mainly just a placeholder of 4193 * Package, Module, Nspace, and TemplateInstance (including TemplateMixin) 4194 * 4195 * A template instance that requires IFTI: 4196 * foo!tiargs(fargs) // foo!tiargs 4197 * is left until CallExp::semantic() or resolveProperties() 4198 */ 4199ScopeExp::ScopeExp(Loc loc, ScopeDsymbol *sds) 4200 : Expression(loc, TOKscope, sizeof(ScopeExp)) 4201{ 4202 //printf("ScopeExp::ScopeExp(sds = '%s')\n", sds->toChars()); 4203 //static int count; if (++count == 38) *(char*)0=0; 4204 this->sds = sds; 4205 assert(!sds->isTemplateDeclaration()); // instead, you should use TemplateExp 4206} 4207 4208Expression *ScopeExp::syntaxCopy() 4209{ 4210 return new ScopeExp(loc, (ScopeDsymbol *)sds->syntaxCopy(NULL)); 4211} 4212 4213bool ScopeExp::checkType() 4214{ 4215 if (sds->isPackage()) 4216 { 4217 error("%s %s has no type", sds->kind(), sds->toChars()); 4218 return true; 4219 } 4220 if (TemplateInstance *ti = sds->isTemplateInstance()) 4221 { 4222 //assert(ti->needsTypeInference(sc)); 4223 if (ti->tempdecl && 4224 ti->semantictiargsdone && 4225 ti->semanticRun == PASSinit) 4226 { 4227 error("partial %s %s has no type", sds->kind(), toChars()); 4228 return true; 4229 } 4230 } 4231 return false; 4232} 4233 4234bool ScopeExp::checkValue() 4235{ 4236 error("%s %s has no value", sds->kind(), sds->toChars()); 4237 return true; 4238} 4239 4240/********************** TemplateExp **************************************/ 4241 4242// Mainly just a placeholder 4243 4244TemplateExp::TemplateExp(Loc loc, TemplateDeclaration *td, FuncDeclaration *fd) 4245 : Expression(loc, TOKtemplate, sizeof(TemplateExp)) 4246{ 4247 //printf("TemplateExp(): %s\n", td->toChars()); 4248 this->td = td; 4249 this->fd = fd; 4250} 4251 4252bool TemplateExp::checkType() 4253{ 4254 error("%s %s has no type", td->kind(), toChars()); 4255 return true; 4256} 4257 4258bool TemplateExp::checkValue() 4259{ 4260 error("%s %s has no value", td->kind(), toChars()); 4261 return true; 4262} 4263 4264bool TemplateExp::isLvalue() 4265{ 4266 return fd != NULL; 4267} 4268 4269Expression *TemplateExp::toLvalue(Scope *sc, Expression *e) 4270{ 4271 if (!fd) 4272 return Expression::toLvalue(sc, e); 4273 4274 assert(sc); 4275 return resolve(loc, sc, fd, true); 4276} 4277 4278/********************** NewExp **************************************/ 4279 4280/* thisexp.new(newargs) newtype(arguments) */ 4281 4282NewExp::NewExp(Loc loc, Expression *thisexp, Expressions *newargs, 4283 Type *newtype, Expressions *arguments) 4284 : Expression(loc, TOKnew, sizeof(NewExp)) 4285{ 4286 this->thisexp = thisexp; 4287 this->newargs = newargs; 4288 this->newtype = newtype; 4289 this->arguments = arguments; 4290 argprefix = NULL; 4291 member = NULL; 4292 allocator = NULL; 4293 onstack = 0; 4294} 4295 4296NewExp *NewExp::create(Loc loc, Expression *thisexp, Expressions *newargs, 4297 Type *newtype, Expressions *arguments) 4298{ 4299 return new NewExp(loc, thisexp, newargs, newtype, arguments); 4300} 4301 4302Expression *NewExp::syntaxCopy() 4303{ 4304 return new NewExp(loc, 4305 thisexp ? thisexp->syntaxCopy() : NULL, 4306 arraySyntaxCopy(newargs), 4307 newtype->syntaxCopy(), arraySyntaxCopy(arguments)); 4308} 4309 4310/********************** NewAnonClassExp **************************************/ 4311 4312NewAnonClassExp::NewAnonClassExp(Loc loc, Expression *thisexp, 4313 Expressions *newargs, ClassDeclaration *cd, Expressions *arguments) 4314 : Expression(loc, TOKnewanonclass, sizeof(NewAnonClassExp)) 4315{ 4316 this->thisexp = thisexp; 4317 this->newargs = newargs; 4318 this->cd = cd; 4319 this->arguments = arguments; 4320} 4321 4322Expression *NewAnonClassExp::syntaxCopy() 4323{ 4324 return new NewAnonClassExp(loc, 4325 thisexp ? thisexp->syntaxCopy() : NULL, 4326 arraySyntaxCopy(newargs), 4327 (ClassDeclaration *)cd->syntaxCopy(NULL), 4328 arraySyntaxCopy(arguments)); 4329} 4330 4331/********************** SymbolExp **************************************/ 4332 4333SymbolExp::SymbolExp(Loc loc, TOK op, int size, Declaration *var, bool hasOverloads) 4334 : Expression(loc, op, size) 4335{ 4336 assert(var); 4337 this->var = var; 4338 this->hasOverloads = hasOverloads; 4339} 4340 4341/********************** SymOffExp **************************************/ 4342 4343SymOffExp::SymOffExp(Loc loc, Declaration *var, dinteger_t offset, bool hasOverloads) 4344 : SymbolExp(loc, TOKsymoff, sizeof(SymOffExp), var, 4345 var->isVarDeclaration() ? false : hasOverloads) 4346{ 4347 if (VarDeclaration *v = var->isVarDeclaration()) 4348 { 4349 // FIXME: This error report will never be handled anyone. 4350 // It should be done before the SymOffExp construction. 4351 if (v->needThis()) 4352 ::error(loc, "need 'this' for address of %s", v->toChars()); 4353 } 4354 this->offset = offset; 4355} 4356 4357bool SymOffExp::isBool(bool result) 4358{ 4359 return result ? true : false; 4360} 4361 4362/******************************** VarExp **************************/ 4363 4364VarExp::VarExp(Loc loc, Declaration *var, bool hasOverloads) 4365 : SymbolExp(loc, TOKvar, sizeof(VarExp), var, 4366 var->isVarDeclaration() ? false : hasOverloads) 4367{ 4368 //printf("VarExp(this = %p, '%s', loc = %s)\n", this, var->toChars(), loc.toChars()); 4369 //if (strcmp(var->ident->toChars(), "func") == 0) halt(); 4370 this->type = var->type; 4371} 4372 4373VarExp *VarExp::create(Loc loc, Declaration *var, bool hasOverloads) 4374{ 4375 return new VarExp(loc, var, hasOverloads); 4376} 4377 4378bool VarExp::equals(RootObject *o) 4379{ 4380 if (this == o) 4381 return true; 4382 if (((Expression *)o)->op == TOKvar) 4383 { 4384 VarExp *ne = (VarExp *)o; 4385 if (type->toHeadMutable()->equals(ne->type->toHeadMutable()) && 4386 var == ne->var) 4387 { 4388 return true; 4389 } 4390 } 4391 return false; 4392} 4393 4394bool VarExp::isLvalue() 4395{ 4396 if (var->storage_class & (STClazy | STCrvalue | STCmanifest)) 4397 return false; 4398 return true; 4399} 4400 4401Expression *VarExp::toLvalue(Scope *, Expression *) 4402{ 4403 if (var->storage_class & STCmanifest) 4404 { 4405 error("manifest constant '%s' is not lvalue", var->toChars()); 4406 return new ErrorExp(); 4407 } 4408 if (var->storage_class & STClazy) 4409 { 4410 error("lazy variables cannot be lvalues"); 4411 return new ErrorExp(); 4412 } 4413 if (var->ident == Id::ctfe) 4414 { 4415 error("compiler-generated variable __ctfe is not an lvalue"); 4416 return new ErrorExp(); 4417 } 4418 if (var->ident == Id::dollar) // Bugzilla 13574 4419 { 4420 error("'$' is not an lvalue"); 4421 return new ErrorExp(); 4422 } 4423 return this; 4424} 4425 4426int VarExp::checkModifiable(Scope *sc, int flag) 4427{ 4428 //printf("VarExp::checkModifiable %s", toChars()); 4429 assert(type); 4430 return var->checkModify(loc, sc, type, NULL, flag); 4431} 4432 4433Expression *VarExp::modifiableLvalue(Scope *sc, Expression *e) 4434{ 4435 //printf("VarExp::modifiableLvalue('%s')\n", var->toChars()); 4436 if (var->storage_class & STCmanifest) 4437 { 4438 error("cannot modify manifest constant '%s'", toChars()); 4439 return new ErrorExp(); 4440 } 4441 // See if this expression is a modifiable lvalue (i.e. not const) 4442 return Expression::modifiableLvalue(sc, e); 4443} 4444 4445 4446/******************************** OverExp **************************/ 4447 4448OverExp::OverExp(Loc loc, OverloadSet *s) 4449 : Expression(loc, TOKoverloadset, sizeof(OverExp)) 4450{ 4451 //printf("OverExp(this = %p, '%s')\n", this, var->toChars()); 4452 vars = s; 4453 type = Type::tvoid; 4454} 4455 4456bool OverExp::isLvalue() 4457{ 4458 return true; 4459} 4460 4461Expression *OverExp::toLvalue(Scope *, Expression *) 4462{ 4463 return this; 4464} 4465 4466/******************************** TupleExp **************************/ 4467 4468TupleExp::TupleExp(Loc loc, Expression *e0, Expressions *exps) 4469 : Expression(loc, TOKtuple, sizeof(TupleExp)) 4470{ 4471 //printf("TupleExp(this = %p)\n", this); 4472 this->e0 = e0; 4473 this->exps = exps; 4474} 4475 4476TupleExp::TupleExp(Loc loc, Expressions *exps) 4477 : Expression(loc, TOKtuple, sizeof(TupleExp)) 4478{ 4479 //printf("TupleExp(this = %p)\n", this); 4480 this->e0 = NULL; 4481 this->exps = exps; 4482} 4483 4484TupleExp::TupleExp(Loc loc, TupleDeclaration *tup) 4485 : Expression(loc, TOKtuple, sizeof(TupleExp)) 4486{ 4487 this->e0 = NULL; 4488 this->exps = new Expressions(); 4489 4490 this->exps->reserve(tup->objects->dim); 4491 for (size_t i = 0; i < tup->objects->dim; i++) 4492 { RootObject *o = (*tup->objects)[i]; 4493 if (Dsymbol *s = getDsymbol(o)) 4494 { 4495 /* If tuple element represents a symbol, translate to DsymbolExp 4496 * to supply implicit 'this' if needed later. 4497 */ 4498 Expression *e = new DsymbolExp(loc, s); 4499 this->exps->push(e); 4500 } 4501 else if (o->dyncast() == DYNCAST_EXPRESSION) 4502 { 4503 Expression *e = ((Expression *)o)->copy(); 4504 e->loc = loc; // Bugzilla 15669 4505 this->exps->push(e); 4506 } 4507 else if (o->dyncast() == DYNCAST_TYPE) 4508 { 4509 Type *t = (Type *)o; 4510 Expression *e = new TypeExp(loc, t); 4511 this->exps->push(e); 4512 } 4513 else 4514 { 4515 error("%s is not an expression", o->toChars()); 4516 } 4517 } 4518} 4519 4520bool TupleExp::equals(RootObject *o) 4521{ 4522 if (this == o) 4523 return true; 4524 if (((Expression *)o)->op == TOKtuple) 4525 { 4526 TupleExp *te = (TupleExp *)o; 4527 if (exps->dim != te->exps->dim) 4528 return false; 4529 if ((e0 && !e0->equals(te->e0)) || (!e0 && te->e0)) 4530 return false; 4531 for (size_t i = 0; i < exps->dim; i++) 4532 { 4533 Expression *e1 = (*exps)[i]; 4534 Expression *e2 = (*te->exps)[i]; 4535 if (!e1->equals(e2)) 4536 return false; 4537 } 4538 return true; 4539 } 4540 return false; 4541} 4542 4543Expression *TupleExp::syntaxCopy() 4544{ 4545 return new TupleExp(loc, e0 ? e0->syntaxCopy() : NULL, arraySyntaxCopy(exps)); 4546} 4547 4548TupleExp *TupleExp::toTupleExp() 4549{ 4550 return this; 4551} 4552 4553/******************************** FuncExp *********************************/ 4554 4555FuncExp::FuncExp(Loc loc, Dsymbol *s) 4556 : Expression(loc, TOKfunction, sizeof(FuncExp)) 4557{ 4558 this->td = s->isTemplateDeclaration(); 4559 this->fd = s->isFuncLiteralDeclaration(); 4560 if (td) 4561 { 4562 assert(td->literal); 4563 assert(td->members && td->members->dim == 1); 4564 fd = (*td->members)[0]->isFuncLiteralDeclaration(); 4565 } 4566 tok = fd->tok; // save original kind of function/delegate/(infer) 4567 assert(fd->fbody); 4568} 4569 4570bool FuncExp::equals(RootObject *o) 4571{ 4572 if (this == o) 4573 return true; 4574 if (o->dyncast() != DYNCAST_EXPRESSION) 4575 return false; 4576 if (((Expression *)o)->op == TOKfunction) 4577 { 4578 FuncExp *fe = (FuncExp *)o; 4579 return fd == fe->fd; 4580 } 4581 return false; 4582} 4583 4584void FuncExp::genIdent(Scope *sc) 4585{ 4586 if (fd->ident == Id::empty) 4587 { 4588 const char *s; 4589 if (fd->fes) s = "__foreachbody"; 4590 else if (fd->tok == TOKreserved) s = "__lambda"; 4591 else if (fd->tok == TOKdelegate) s = "__dgliteral"; 4592 else s = "__funcliteral"; 4593 4594 DsymbolTable *symtab; 4595 if (FuncDeclaration *func = sc->parent->isFuncDeclaration()) 4596 { 4597 if (func->localsymtab == NULL) 4598 { 4599 // Inside template constraint, symtab is not set yet. 4600 // Initialize it lazily. 4601 func->localsymtab = new DsymbolTable(); 4602 } 4603 symtab = func->localsymtab; 4604 } 4605 else 4606 { 4607 ScopeDsymbol *sds = sc->parent->isScopeDsymbol(); 4608 if (!sds->symtab) 4609 { 4610 // Inside template constraint, symtab may not be set yet. 4611 // Initialize it lazily. 4612 assert(sds->isTemplateInstance()); 4613 sds->symtab = new DsymbolTable(); 4614 } 4615 symtab = sds->symtab; 4616 } 4617 assert(symtab); 4618 int num = (int)dmd_aaLen(symtab->tab) + 1; 4619 Identifier *id = Identifier::generateId(s, num); 4620 fd->ident = id; 4621 if (td) td->ident = id; 4622 symtab->insert(td ? (Dsymbol *)td : (Dsymbol *)fd); 4623 } 4624} 4625 4626Expression *FuncExp::syntaxCopy() 4627{ 4628 if (td) 4629 return new FuncExp(loc, td->syntaxCopy(NULL)); 4630 else if (fd->semanticRun == PASSinit) 4631 return new FuncExp(loc, fd->syntaxCopy(NULL)); 4632 else // Bugzilla 13481: Prevent multiple semantic analysis of lambda body. 4633 return new FuncExp(loc, fd); 4634} 4635 4636MATCH FuncExp::matchType(Type *to, Scope *sc, FuncExp **presult, int flag) 4637{ 4638 //printf("FuncExp::matchType('%s'), to=%s\n", type ? type->toChars() : "null", to->toChars()); 4639 if (presult) 4640 *presult = NULL; 4641 4642 TypeFunction *tof = NULL; 4643 if (to->ty == Tdelegate) 4644 { 4645 if (tok == TOKfunction) 4646 { 4647 if (!flag) 4648 error("cannot match function literal to delegate type '%s'", to->toChars()); 4649 return MATCHnomatch; 4650 } 4651 tof = (TypeFunction *)to->nextOf(); 4652 } 4653 else if (to->ty == Tpointer && to->nextOf()->ty == Tfunction) 4654 { 4655 if (tok == TOKdelegate) 4656 { 4657 if (!flag) 4658 error("cannot match delegate literal to function pointer type '%s'", to->toChars()); 4659 return MATCHnomatch; 4660 } 4661 tof = (TypeFunction *)to->nextOf(); 4662 } 4663 4664 if (td) 4665 { 4666 if (!tof) 4667 { 4668 L1: 4669 if (!flag) 4670 error("cannot infer parameter types from %s", to->toChars()); 4671 return MATCHnomatch; 4672 } 4673 4674 // Parameter types inference from 'tof' 4675 assert(td->_scope); 4676 TypeFunction *tf = (TypeFunction *)fd->type; 4677 //printf("\ttof = %s\n", tof->toChars()); 4678 //printf("\ttf = %s\n", tf->toChars()); 4679 size_t dim = Parameter::dim(tf->parameters); 4680 4681 if (Parameter::dim(tof->parameters) != dim || 4682 tof->varargs != tf->varargs) 4683 goto L1; 4684 4685 Objects *tiargs = new Objects(); 4686 tiargs->reserve(td->parameters->dim); 4687 4688 for (size_t i = 0; i < td->parameters->dim; i++) 4689 { 4690 TemplateParameter *tp = (*td->parameters)[i]; 4691 size_t u = 0; 4692 for (; u < dim; u++) 4693 { 4694 Parameter *p = Parameter::getNth(tf->parameters, u); 4695 if (p->type->ty == Tident && 4696 ((TypeIdentifier *)p->type)->ident == tp->ident) 4697 { 4698 break; 4699 } 4700 } 4701 assert(u < dim); 4702 Parameter *pto = Parameter::getNth(tof->parameters, u); 4703 Type *t = pto->type; 4704 if (t->ty == Terror) 4705 goto L1; 4706 tiargs->push(t); 4707 } 4708 4709 // Set target of return type inference 4710 if (!tf->next && tof->next) 4711 fd->treq = to; 4712 4713 TemplateInstance *ti = new TemplateInstance(loc, td, tiargs); 4714 Expression *ex = new ScopeExp(loc, ti); 4715 ex = ::semantic(ex, td->_scope); 4716 4717 // Reset inference target for the later re-semantic 4718 fd->treq = NULL; 4719 4720 if (ex->op == TOKerror) 4721 return MATCHnomatch; 4722 if (ex->op != TOKfunction) 4723 goto L1; 4724 return ((FuncExp *)ex)->matchType(to, sc, presult, flag); 4725 } 4726 4727 if (!tof || !tof->next) 4728 return MATCHnomatch; 4729 4730 assert(type && type != Type::tvoid); 4731 TypeFunction *tfx = (TypeFunction *)fd->type; 4732 bool convertMatch = (type->ty != to->ty); 4733 4734 if (fd->inferRetType && tfx->next->implicitConvTo(tof->next) == MATCHconvert) 4735 { 4736 /* If return type is inferred and covariant return, 4737 * tweak return statements to required return type. 4738 * 4739 * interface I {} 4740 * class C : Object, I{} 4741 * 4742 * I delegate() dg = delegate() { return new class C(); } 4743 */ 4744 convertMatch = true; 4745 4746 TypeFunction *tfy = new TypeFunction(tfx->parameters, tof->next, tfx->varargs, tfx->linkage, STCundefined); 4747 tfy->mod = tfx->mod; 4748 tfy->isnothrow = tfx->isnothrow; 4749 tfy->isnogc = tfx->isnogc; 4750 tfy->purity = tfx->purity; 4751 tfy->isproperty = tfx->isproperty; 4752 tfy->isref = tfx->isref; 4753 tfy->iswild = tfx->iswild; 4754 tfy->deco = tfy->merge()->deco; 4755 4756 tfx = tfy; 4757 } 4758 4759 Type *tx; 4760 if (tok == TOKdelegate || 4761 (tok == TOKreserved && (type->ty == Tdelegate || 4762 (type->ty == Tpointer && to->ty == Tdelegate)))) 4763 { 4764 // Allow conversion from implicit function pointer to delegate 4765 tx = new TypeDelegate(tfx); 4766 tx->deco = tx->merge()->deco; 4767 } 4768 else 4769 { 4770 assert(tok == TOKfunction || 4771 (tok == TOKreserved && type->ty == Tpointer)); 4772 tx = tfx->pointerTo(); 4773 } 4774 //printf("\ttx = %s, to = %s\n", tx->toChars(), to->toChars()); 4775 4776 MATCH m = tx->implicitConvTo(to); 4777 if (m > MATCHnomatch) 4778 { 4779 // MATCHexact: exact type match 4780 // MATCHconst: covairiant type match (eg. attributes difference) 4781 // MATCHconvert: context conversion 4782 m = convertMatch ? MATCHconvert : tx->equals(to) ? MATCHexact : MATCHconst; 4783 4784 if (presult) 4785 { 4786 (*presult) = (FuncExp *)copy(); 4787 (*presult)->type = to; 4788 4789 // Bugzilla 12508: Tweak function body for covariant returns. 4790 (*presult)->fd->modifyReturns(sc, tof->next); 4791 } 4792 } 4793 else if (!flag) 4794 { 4795 error("cannot implicitly convert expression (%s) of type %s to %s", 4796 toChars(), tx->toChars(), to->toChars()); 4797 } 4798 return m; 4799} 4800 4801const char *FuncExp::toChars() 4802{ 4803 return fd->toChars(); 4804} 4805 4806bool FuncExp::checkType() 4807{ 4808 if (td) 4809 { 4810 error("template lambda has no type"); 4811 return true; 4812 } 4813 return false; 4814} 4815 4816bool FuncExp::checkValue() 4817{ 4818 if (td) 4819 { 4820 error("template lambda has no value"); 4821 return true; 4822 } 4823 return false; 4824} 4825 4826/******************************** DeclarationExp **************************/ 4827 4828DeclarationExp::DeclarationExp(Loc loc, Dsymbol *declaration) 4829 : Expression(loc, TOKdeclaration, sizeof(DeclarationExp)) 4830{ 4831 this->declaration = declaration; 4832} 4833 4834Expression *DeclarationExp::syntaxCopy() 4835{ 4836 return new DeclarationExp(loc, declaration->syntaxCopy(NULL)); 4837} 4838 4839bool DeclarationExp::hasCode() 4840{ 4841 if (VarDeclaration *vd = declaration->isVarDeclaration()) 4842 { 4843 return !(vd->storage_class & (STCmanifest | STCstatic)); 4844 } 4845 return false; 4846} 4847 4848/************************ TypeidExp ************************************/ 4849 4850/* 4851 * typeid(int) 4852 */ 4853 4854TypeidExp::TypeidExp(Loc loc, RootObject *o) 4855 : Expression(loc, TOKtypeid, sizeof(TypeidExp)) 4856{ 4857 this->obj = o; 4858} 4859 4860Expression *TypeidExp::syntaxCopy() 4861{ 4862 return new TypeidExp(loc, objectSyntaxCopy(obj)); 4863} 4864 4865/************************ TraitsExp ************************************/ 4866/* 4867 * __traits(identifier, args...) 4868 */ 4869 4870TraitsExp::TraitsExp(Loc loc, Identifier *ident, Objects *args) 4871 : Expression(loc, TOKtraits, sizeof(TraitsExp)) 4872{ 4873 this->ident = ident; 4874 this->args = args; 4875} 4876 4877Expression *TraitsExp::syntaxCopy() 4878{ 4879 return new TraitsExp(loc, ident, TemplateInstance::arraySyntaxCopy(args)); 4880} 4881 4882/************************************************************/ 4883 4884HaltExp::HaltExp(Loc loc) 4885 : Expression(loc, TOKhalt, sizeof(HaltExp)) 4886{ 4887} 4888 4889/************************************************************/ 4890 4891IsExp::IsExp(Loc loc, Type *targ, Identifier *id, TOK tok, 4892 Type *tspec, TOK tok2, TemplateParameters *parameters) 4893 : Expression(loc, TOKis, sizeof(IsExp)) 4894{ 4895 this->targ = targ; 4896 this->id = id; 4897 this->tok = tok; 4898 this->tspec = tspec; 4899 this->tok2 = tok2; 4900 this->parameters = parameters; 4901} 4902 4903Expression *IsExp::syntaxCopy() 4904{ 4905 // This section is identical to that in TemplateDeclaration::syntaxCopy() 4906 TemplateParameters *p = NULL; 4907 if (parameters) 4908 { 4909 p = new TemplateParameters(); 4910 p->setDim(parameters->dim); 4911 for (size_t i = 0; i < p->dim; i++) 4912 (*p)[i] = (*parameters)[i]->syntaxCopy(); 4913 } 4914 return new IsExp(loc, 4915 targ->syntaxCopy(), 4916 id, 4917 tok, 4918 tspec ? tspec->syntaxCopy() : NULL, 4919 tok2, 4920 p); 4921} 4922 4923void unSpeculative(Scope *sc, RootObject *o); 4924 4925/************************************************************/ 4926 4927UnaExp::UnaExp(Loc loc, TOK op, int size, Expression *e1) 4928 : Expression(loc, op, size) 4929{ 4930 this->e1 = e1; 4931 this->att1 = NULL; 4932} 4933 4934Expression *UnaExp::syntaxCopy() 4935{ 4936 UnaExp *e = (UnaExp *)copy(); 4937 e->type = NULL; 4938 e->e1 = e->e1->syntaxCopy(); 4939 return e; 4940} 4941 4942/******************************** 4943 * The type for a unary expression is incompatible. 4944 * Print error message. 4945 * Returns: 4946 * ErrorExp 4947 */ 4948Expression *UnaExp::incompatibleTypes() 4949{ 4950 if (e1->type->toBasetype() == Type::terror) 4951 return e1; 4952 4953 if (e1->op == TOKtype) 4954 { 4955 error("incompatible type for (%s(%s)): cannot use '%s' with types", 4956 Token::toChars(op), e1->toChars(), Token::toChars(op)); 4957 } 4958 else 4959 { 4960 error("incompatible type for (%s(%s)): '%s'", 4961 Token::toChars(op), e1->toChars(), e1->type->toChars()); 4962 } 4963 return new ErrorExp(); 4964} 4965 4966Expression *UnaExp::resolveLoc(Loc loc, Scope *sc) 4967{ 4968 e1 = e1->resolveLoc(loc, sc); 4969 return this; 4970} 4971 4972/************************************************************/ 4973 4974BinExp::BinExp(Loc loc, TOK op, int size, Expression *e1, Expression *e2) 4975 : Expression(loc, op, size) 4976{ 4977 this->e1 = e1; 4978 this->e2 = e2; 4979 4980 this->att1 = NULL; 4981 this->att2 = NULL; 4982} 4983 4984Expression *BinExp::syntaxCopy() 4985{ 4986 BinExp *e = (BinExp *)copy(); 4987 e->type = NULL; 4988 e->e1 = e->e1->syntaxCopy(); 4989 e->e2 = e->e2->syntaxCopy(); 4990 return e; 4991} 4992 4993Expression *BinExp::checkOpAssignTypes(Scope *sc) 4994{ 4995 // At that point t1 and t2 are the merged types. type is the original type of the lhs. 4996 Type *t1 = e1->type; 4997 Type *t2 = e2->type; 4998 4999 // T opAssign floating yields a floating. Prevent truncating conversions (float to int). 5000 // See issue 3841. 5001 // Should we also prevent double to float (type->isfloating() && type->size() < t2 ->size()) ? 5002 if (op == TOKaddass || op == TOKminass || 5003 op == TOKmulass || op == TOKdivass || op == TOKmodass || 5004 op == TOKpowass) 5005 { 5006 if ((type->isintegral() && t2->isfloating())) 5007 { 5008 warning("%s %s %s is performing truncating conversion", 5009 type->toChars(), Token::toChars(op), t2->toChars()); 5010 } 5011 } 5012 5013 // generate an error if this is a nonsensical *=,/=, or %=, eg real *= imaginary 5014 if (op == TOKmulass || op == TOKdivass || op == TOKmodass) 5015 { 5016 // Any multiplication by an imaginary or complex number yields a complex result. 5017 // r *= c, i*=c, r*=i, i*=i are all forbidden operations. 5018 const char *opstr = Token::toChars(op); 5019 if (t1->isreal() && t2->iscomplex()) 5020 { 5021 error("%s %s %s is undefined. Did you mean %s %s %s.re ?", 5022 t1->toChars(), opstr, t2->toChars(), 5023 t1->toChars(), opstr, t2->toChars()); 5024 return new ErrorExp(); 5025 } 5026 else if (t1->isimaginary() && t2->iscomplex()) 5027 { 5028 error("%s %s %s is undefined. Did you mean %s %s %s.im ?", 5029 t1->toChars(), opstr, t2->toChars(), 5030 t1->toChars(), opstr, t2->toChars()); 5031 return new ErrorExp(); 5032 } 5033 else if ((t1->isreal() || t1->isimaginary()) && 5034 t2->isimaginary()) 5035 { 5036 error("%s %s %s is an undefined operation", t1->toChars(), opstr, t2->toChars()); 5037 return new ErrorExp(); 5038 } 5039 } 5040 5041 // generate an error if this is a nonsensical += or -=, eg real += imaginary 5042 if (op == TOKaddass || op == TOKminass) 5043 { 5044 // Addition or subtraction of a real and an imaginary is a complex result. 5045 // Thus, r+=i, r+=c, i+=r, i+=c are all forbidden operations. 5046 if ((t1->isreal() && (t2->isimaginary() || t2->iscomplex())) || 5047 (t1->isimaginary() && (t2->isreal() || t2->iscomplex()))) 5048 { 5049 error("%s %s %s is undefined (result is complex)", 5050 t1->toChars(), Token::toChars(op), t2->toChars()); 5051 return new ErrorExp(); 5052 } 5053 if (type->isreal() || type->isimaginary()) 5054 { 5055 assert(global.errors || t2->isfloating()); 5056 e2 = e2->castTo(sc, t1); 5057 } 5058 } 5059 5060 if (op == TOKmulass) 5061 { 5062 if (t2->isfloating()) 5063 { 5064 if (t1->isreal()) 5065 { 5066 if (t2->isimaginary() || t2->iscomplex()) 5067 { 5068 e2 = e2->castTo(sc, t1); 5069 } 5070 } 5071 else if (t1->isimaginary()) 5072 { 5073 if (t2->isimaginary() || t2->iscomplex()) 5074 { 5075 switch (t1->ty) 5076 { 5077 case Timaginary32: t2 = Type::tfloat32; break; 5078 case Timaginary64: t2 = Type::tfloat64; break; 5079 case Timaginary80: t2 = Type::tfloat80; break; 5080 default: 5081 assert(0); 5082 } 5083 e2 = e2->castTo(sc, t2); 5084 } 5085 } 5086 } 5087 } 5088 else if (op == TOKdivass) 5089 { 5090 if (t2->isimaginary()) 5091 { 5092 if (t1->isreal()) 5093 { 5094 // x/iv = i(-x/v) 5095 // Therefore, the result is 0 5096 e2 = new CommaExp(loc, e2, new RealExp(loc, CTFloat::zero, t1)); 5097 e2->type = t1; 5098 Expression *e = new AssignExp(loc, e1, e2); 5099 e->type = t1; 5100 return e; 5101 } 5102 else if (t1->isimaginary()) 5103 { 5104 Type *t3; 5105 switch (t1->ty) 5106 { 5107 case Timaginary32: t3 = Type::tfloat32; break; 5108 case Timaginary64: t3 = Type::tfloat64; break; 5109 case Timaginary80: t3 = Type::tfloat80; break; 5110 default: 5111 assert(0); 5112 } 5113 e2 = e2->castTo(sc, t3); 5114 Expression *e = new AssignExp(loc, e1, e2); 5115 e->type = t1; 5116 return e; 5117 } 5118 } 5119 } 5120 else if (op == TOKmodass) 5121 { 5122 if (t2->iscomplex()) 5123 { 5124 error("cannot perform modulo complex arithmetic"); 5125 return new ErrorExp(); 5126 } 5127 } 5128 return this; 5129} 5130 5131/******************************** 5132 * The types for a binary expression are incompatible. 5133 * Print error message. 5134 * Returns: 5135 * ErrorExp 5136 */ 5137Expression *BinExp::incompatibleTypes() 5138{ 5139 if (e1->type->toBasetype() == Type::terror) 5140 return e1; 5141 if (e2->type->toBasetype() == Type::terror) 5142 return e2; 5143 5144 // CondExp uses 'a ? b : c' but we're comparing 'b : c' 5145 TOK thisOp = (op == TOKquestion) ? TOKcolon : op; 5146 if (e1->op == TOKtype || e2->op == TOKtype) 5147 { 5148 error("incompatible types for ((%s) %s (%s)): cannot use '%s' with types", 5149 e1->toChars(), Token::toChars(thisOp), e2->toChars(), Token::toChars(op)); 5150 } 5151 else 5152 { 5153 error("incompatible types for ((%s) %s (%s)): '%s' and '%s'", 5154 e1->toChars(), Token::toChars(thisOp), e2->toChars(), 5155 e1->type->toChars(), e2->type->toChars()); 5156 } 5157 return new ErrorExp(); 5158} 5159 5160bool BinExp::checkIntegralBin() 5161{ 5162 bool r1 = e1->checkIntegral(); 5163 bool r2 = e2->checkIntegral(); 5164 return (r1 || r2); 5165} 5166 5167bool BinExp::checkArithmeticBin() 5168{ 5169 bool r1 = e1->checkArithmetic(); 5170 bool r2 = e2->checkArithmetic(); 5171 return (r1 || r2); 5172} 5173 5174/********************** BinAssignExp **************************************/ 5175 5176BinAssignExp::BinAssignExp(Loc loc, TOK op, int size, Expression *e1, Expression *e2) 5177 : BinExp(loc, op, size, e1, e2) 5178{ 5179} 5180 5181bool BinAssignExp::isLvalue() 5182{ 5183 return true; 5184} 5185 5186Expression *BinAssignExp::toLvalue(Scope *, Expression *) 5187{ 5188 // Lvalue-ness will be handled in glue layer. 5189 return this; 5190} 5191 5192Expression *BinAssignExp::modifiableLvalue(Scope *sc, Expression *) 5193{ 5194 // should check e1->checkModifiable() ? 5195 return toLvalue(sc, this); 5196} 5197 5198/************************************************************/ 5199 5200CompileExp::CompileExp(Loc loc, Expression *e) 5201 : UnaExp(loc, TOKmixin, sizeof(CompileExp), e) 5202{ 5203} 5204 5205/************************************************************/ 5206 5207ImportExp::ImportExp(Loc loc, Expression *e) 5208 : UnaExp(loc, TOKimport, sizeof(ImportExp), e) 5209{ 5210} 5211 5212/************************************************************/ 5213 5214AssertExp::AssertExp(Loc loc, Expression *e, Expression *msg) 5215 : UnaExp(loc, TOKassert, sizeof(AssertExp), e) 5216{ 5217 this->msg = msg; 5218} 5219 5220Expression *AssertExp::syntaxCopy() 5221{ 5222 return new AssertExp(loc, e1->syntaxCopy(), msg ? msg->syntaxCopy() : NULL); 5223} 5224 5225/************************************************************/ 5226 5227DotIdExp::DotIdExp(Loc loc, Expression *e, Identifier *ident) 5228 : UnaExp(loc, TOKdotid, sizeof(DotIdExp), e) 5229{ 5230 this->ident = ident; 5231 this->wantsym = false; 5232 this->noderef = false; 5233} 5234 5235DotIdExp *DotIdExp::create(Loc loc, Expression *e, Identifier *ident) 5236{ 5237 return new DotIdExp(loc, e, ident); 5238} 5239 5240/********************** DotTemplateExp ***********************************/ 5241 5242// Mainly just a placeholder 5243 5244DotTemplateExp::DotTemplateExp(Loc loc, Expression *e, TemplateDeclaration *td) 5245 : UnaExp(loc, TOKdottd, sizeof(DotTemplateExp), e) 5246 5247{ 5248 this->td = td; 5249} 5250 5251bool DotTemplateExp::checkType() 5252{ 5253 error("%s %s has no type", td->kind(), toChars()); 5254 return true; 5255} 5256 5257bool DotTemplateExp::checkValue() 5258{ 5259 error("%s %s has no value", td->kind(), toChars()); 5260 return true; 5261} 5262 5263/************************************************************/ 5264 5265DotVarExp::DotVarExp(Loc loc, Expression *e, Declaration *var, bool hasOverloads) 5266 : UnaExp(loc, TOKdotvar, sizeof(DotVarExp), e) 5267{ 5268 //printf("DotVarExp()\n"); 5269 this->var = var; 5270 this->hasOverloads = var->isVarDeclaration() ? false : hasOverloads; 5271} 5272 5273bool DotVarExp::isLvalue() 5274{ 5275 return true; 5276} 5277 5278Expression *DotVarExp::toLvalue(Scope *, Expression *) 5279{ 5280 //printf("DotVarExp::toLvalue(%s)\n", toChars()); 5281 return this; 5282} 5283 5284/*********************************************** 5285 * Mark variable v as modified if it is inside a constructor that var 5286 * is a field in. 5287 */ 5288int modifyFieldVar(Loc loc, Scope *sc, VarDeclaration *var, Expression *e1) 5289{ 5290 //printf("modifyFieldVar(var = %s)\n", var->toChars()); 5291 Dsymbol *s = sc->func; 5292 while (1) 5293 { 5294 FuncDeclaration *fd = NULL; 5295 if (s) 5296 fd = s->isFuncDeclaration(); 5297 if (fd && 5298 ((fd->isCtorDeclaration() && var->isField()) || 5299 (fd->isStaticCtorDeclaration() && !var->isField())) && 5300 fd->toParent2() == var->toParent2() && 5301 (!e1 || e1->op == TOKthis) 5302 ) 5303 { 5304 bool result = true; 5305 5306 var->ctorinit = true; 5307 //printf("setting ctorinit\n"); 5308 5309 if (var->isField() && sc->fieldinit && !sc->intypeof) 5310 { 5311 assert(e1); 5312 bool mustInit = ((var->storage_class & STCnodefaultctor) != 0 || 5313 var->type->needsNested()); 5314 5315 size_t dim = sc->fieldinit_dim; 5316 AggregateDeclaration *ad = fd->isMember2(); 5317 assert(ad); 5318 size_t i; 5319 for (i = 0; i < dim; i++) // same as findFieldIndexByName in ctfeexp.c ? 5320 { 5321 if (ad->fields[i] == var) 5322 break; 5323 } 5324 assert(i < dim); 5325 unsigned fi = sc->fieldinit[i]; 5326 5327 if (fi & CSXthis_ctor) 5328 { 5329 if (var->type->isMutable() && e1->type->isMutable()) 5330 result = false; 5331 else 5332 { 5333 const char *modStr = !var->type->isMutable() ? MODtoChars(var->type->mod) : MODtoChars(e1->type->mod); 5334 ::error(loc, "%s field '%s' initialized multiple times", modStr, var->toChars()); 5335 } 5336 } 5337 else if (sc->noctor || (fi & CSXlabel)) 5338 { 5339 if (!mustInit && var->type->isMutable() && e1->type->isMutable()) 5340 result = false; 5341 else 5342 { 5343 const char *modStr = !var->type->isMutable() ? MODtoChars(var->type->mod) : MODtoChars(e1->type->mod); 5344 ::error(loc, "%s field '%s' initialization is not allowed in loops or after labels", modStr, var->toChars()); 5345 } 5346 } 5347 sc->fieldinit[i] |= CSXthis_ctor; 5348 if (var->overlapped) // Bugzilla 15258 5349 { 5350 for (size_t j = 0; j < ad->fields.dim; j++) 5351 { 5352 VarDeclaration *v = ad->fields[j]; 5353 if (v == var || !var->isOverlappedWith(v)) 5354 continue; 5355 v->ctorinit = true; 5356 sc->fieldinit[j] = CSXthis_ctor; 5357 } 5358 } 5359 } 5360 else if (fd != sc->func) 5361 { 5362 if (var->type->isMutable()) 5363 result = false; 5364 else if (sc->func->fes) 5365 { 5366 const char *p = var->isField() ? "field" : var->kind(); 5367 ::error(loc, "%s %s '%s' initialization is not allowed in foreach loop", 5368 MODtoChars(var->type->mod), p, var->toChars()); 5369 } 5370 else 5371 { 5372 const char *p = var->isField() ? "field" : var->kind(); 5373 ::error(loc, "%s %s '%s' initialization is not allowed in nested function '%s'", 5374 MODtoChars(var->type->mod), p, var->toChars(), sc->func->toChars()); 5375 } 5376 } 5377 return result; 5378 } 5379 else 5380 { 5381 if (s) 5382 { 5383 s = s->toParent2(); 5384 continue; 5385 } 5386 } 5387 break; 5388 } 5389 return false; 5390} 5391 5392int DotVarExp::checkModifiable(Scope *sc, int flag) 5393{ 5394 //printf("DotVarExp::checkModifiable %s %s\n", toChars(), type->toChars()); 5395 if (checkUnsafeAccess(sc, this, false, !flag)) 5396 return 2; 5397 5398 if (e1->op == TOKthis) 5399 return var->checkModify(loc, sc, type, e1, flag); 5400 5401 //printf("\te1 = %s\n", e1->toChars()); 5402 return e1->checkModifiable(sc, flag); 5403} 5404 5405Expression *DotVarExp::modifiableLvalue(Scope *sc, Expression *e) 5406{ 5407 return Expression::modifiableLvalue(sc, e); 5408} 5409 5410/************************************************************/ 5411 5412/* Things like: 5413 * foo.bar!(args) 5414 */ 5415 5416DotTemplateInstanceExp::DotTemplateInstanceExp(Loc loc, Expression *e, Identifier *name, Objects *tiargs) 5417 : UnaExp(loc, TOKdotti, sizeof(DotTemplateInstanceExp), e) 5418{ 5419 //printf("DotTemplateInstanceExp()\n"); 5420 this->ti = new TemplateInstance(loc, name); 5421 this->ti->tiargs = tiargs; 5422} 5423 5424DotTemplateInstanceExp::DotTemplateInstanceExp(Loc loc, Expression *e, TemplateInstance *ti) 5425 : UnaExp(loc, TOKdotti, sizeof(DotTemplateInstanceExp), e) 5426{ 5427 this->ti = ti; 5428} 5429 5430Expression *DotTemplateInstanceExp::syntaxCopy() 5431{ 5432 return new DotTemplateInstanceExp(loc, 5433 e1->syntaxCopy(), 5434 ti->name, 5435 TemplateInstance::arraySyntaxCopy(ti->tiargs)); 5436} 5437 5438bool DotTemplateInstanceExp::findTempDecl(Scope *sc) 5439{ 5440 if (ti->tempdecl) 5441 return true; 5442 5443 Expression *e = new DotIdExp(loc, e1, ti->name); 5444 e = semantic(e, sc); 5445 if (e->op == TOKdot) 5446 e = ((DotExp *)e)->e2; 5447 5448 Dsymbol *s = NULL; 5449 switch (e->op) 5450 { 5451 case TOKoverloadset: s = ((OverExp *)e)->vars; break; 5452 case TOKdottd: s = ((DotTemplateExp *)e)->td; break; 5453 case TOKscope: s = ((ScopeExp *)e)->sds; break; 5454 case TOKdotvar: s = ((DotVarExp *)e)->var; break; 5455 case TOKvar: s = ((VarExp *)e)->var; break; 5456 default: return false; 5457 } 5458 return ti->updateTempDecl(sc, s); 5459} 5460 5461/************************************************************/ 5462 5463DelegateExp::DelegateExp(Loc loc, Expression *e, FuncDeclaration *f, bool hasOverloads) 5464 : UnaExp(loc, TOKdelegate, sizeof(DelegateExp), e) 5465{ 5466 this->func = f; 5467 this->hasOverloads = hasOverloads; 5468} 5469 5470/************************************************************/ 5471 5472DotTypeExp::DotTypeExp(Loc loc, Expression *e, Dsymbol *s) 5473 : UnaExp(loc, TOKdottype, sizeof(DotTypeExp), e) 5474{ 5475 this->sym = s; 5476 this->type = NULL; 5477} 5478 5479/************************************************************/ 5480 5481CallExp::CallExp(Loc loc, Expression *e, Expressions *exps) 5482 : UnaExp(loc, TOKcall, sizeof(CallExp), e) 5483{ 5484 this->arguments = exps; 5485 this->f = NULL; 5486 this->directcall = false; 5487} 5488 5489CallExp::CallExp(Loc loc, Expression *e) 5490 : UnaExp(loc, TOKcall, sizeof(CallExp), e) 5491{ 5492 this->arguments = NULL; 5493 this->f = NULL; 5494 this->directcall = false; 5495} 5496 5497CallExp::CallExp(Loc loc, Expression *e, Expression *earg1) 5498 : UnaExp(loc, TOKcall, sizeof(CallExp), e) 5499{ 5500 Expressions *arguments = new Expressions(); 5501 if (earg1) 5502 { 5503 arguments->setDim(1); 5504 (*arguments)[0] = earg1; 5505 } 5506 this->arguments = arguments; 5507 this->f = NULL; 5508 this->directcall = false; 5509} 5510 5511CallExp::CallExp(Loc loc, Expression *e, Expression *earg1, Expression *earg2) 5512 : UnaExp(loc, TOKcall, sizeof(CallExp), e) 5513{ 5514 Expressions *arguments = new Expressions(); 5515 arguments->setDim(2); 5516 (*arguments)[0] = earg1; 5517 (*arguments)[1] = earg2; 5518 5519 this->arguments = arguments; 5520 this->f = NULL; 5521 this->directcall = false; 5522} 5523 5524CallExp *CallExp::create(Loc loc, Expression *e, Expressions *exps) 5525{ 5526 return new CallExp(loc, e, exps); 5527} 5528 5529CallExp *CallExp::create(Loc loc, Expression *e) 5530{ 5531 return new CallExp(loc, e); 5532} 5533 5534CallExp *CallExp::create(Loc loc, Expression *e, Expression *earg1) 5535{ 5536 return new CallExp(loc, e, earg1); 5537} 5538 5539Expression *CallExp::syntaxCopy() 5540{ 5541 return new CallExp(loc, e1->syntaxCopy(), arraySyntaxCopy(arguments)); 5542} 5543 5544bool CallExp::isLvalue() 5545{ 5546 Type *tb = e1->type->toBasetype(); 5547 if (tb->ty == Tdelegate || tb->ty == Tpointer) 5548 tb = tb->nextOf(); 5549 if (tb->ty == Tfunction && ((TypeFunction *)tb)->isref) 5550 { 5551 if (e1->op == TOKdotvar) 5552 if (((DotVarExp *)e1)->var->isCtorDeclaration()) 5553 return false; 5554 return true; // function returns a reference 5555 } 5556 return false; 5557} 5558 5559Expression *CallExp::toLvalue(Scope *sc, Expression *e) 5560{ 5561 if (isLvalue()) 5562 return this; 5563 return Expression::toLvalue(sc, e); 5564} 5565 5566Expression *CallExp::addDtorHook(Scope *sc) 5567{ 5568 /* Only need to add dtor hook if it's a type that needs destruction. 5569 * Use same logic as VarDeclaration::callScopeDtor() 5570 */ 5571 5572 if (e1->type && e1->type->ty == Tfunction) 5573 { 5574 TypeFunction *tf = (TypeFunction *)e1->type; 5575 if (tf->isref) 5576 return this; 5577 } 5578 5579 Type *tv = type->baseElemOf(); 5580 if (tv->ty == Tstruct) 5581 { 5582 TypeStruct *ts = (TypeStruct *)tv; 5583 StructDeclaration *sd = ts->sym; 5584 if (sd->dtor) 5585 { 5586 /* Type needs destruction, so declare a tmp 5587 * which the back end will recognize and call dtor on 5588 */ 5589 VarDeclaration *tmp = copyToTemp(0, "__tmpfordtor", this); 5590 DeclarationExp *de = new DeclarationExp(loc, tmp); 5591 VarExp *ve = new VarExp(loc, tmp); 5592 Expression *e = new CommaExp(loc, de, ve); 5593 e = semantic(e, sc); 5594 return e; 5595 } 5596 } 5597 return this; 5598} 5599 5600FuncDeclaration *isFuncAddress(Expression *e, bool *hasOverloads = NULL) 5601{ 5602 if (e->op == TOKaddress) 5603 { 5604 Expression *ae1 = ((AddrExp *)e)->e1; 5605 if (ae1->op == TOKvar) 5606 { 5607 VarExp *ve = (VarExp *)ae1; 5608 if (hasOverloads) 5609 *hasOverloads = ve->hasOverloads; 5610 return ve->var->isFuncDeclaration(); 5611 } 5612 if (ae1->op == TOKdotvar) 5613 { 5614 DotVarExp *dve = (DotVarExp *)ae1; 5615 if (hasOverloads) 5616 *hasOverloads = dve->hasOverloads; 5617 return dve->var->isFuncDeclaration(); 5618 } 5619 } 5620 else 5621 { 5622 if (e->op == TOKsymoff) 5623 { 5624 SymOffExp *soe = (SymOffExp *)e; 5625 if (hasOverloads) 5626 *hasOverloads = soe->hasOverloads; 5627 return soe->var->isFuncDeclaration(); 5628 } 5629 if (e->op == TOKdelegate) 5630 { 5631 DelegateExp *dge = (DelegateExp *)e; 5632 if (hasOverloads) 5633 *hasOverloads = dge->hasOverloads; 5634 return dge->func->isFuncDeclaration(); 5635 } 5636 } 5637 return NULL; 5638} 5639 5640/************************************************************/ 5641 5642AddrExp::AddrExp(Loc loc, Expression *e) 5643 : UnaExp(loc, TOKaddress, sizeof(AddrExp), e) 5644{ 5645} 5646 5647AddrExp::AddrExp(Loc loc, Expression *e, Type *t) 5648 : UnaExp(loc, TOKaddress, sizeof(AddrExp), e) 5649{ 5650 type = t; 5651} 5652 5653/************************************************************/ 5654 5655PtrExp::PtrExp(Loc loc, Expression *e) 5656 : UnaExp(loc, TOKstar, sizeof(PtrExp), e) 5657{ 5658// if (e->type) 5659// type = ((TypePointer *)e->type)->next; 5660} 5661 5662PtrExp::PtrExp(Loc loc, Expression *e, Type *t) 5663 : UnaExp(loc, TOKstar, sizeof(PtrExp), e) 5664{ 5665 type = t; 5666} 5667 5668bool PtrExp::isLvalue() 5669{ 5670 return true; 5671} 5672 5673Expression *PtrExp::toLvalue(Scope *, Expression *) 5674{ 5675 return this; 5676} 5677 5678int PtrExp::checkModifiable(Scope *sc, int flag) 5679{ 5680 if (e1->op == TOKsymoff) 5681 { SymOffExp *se = (SymOffExp *)e1; 5682 return se->var->checkModify(loc, sc, type, NULL, flag); 5683 } 5684 else if (e1->op == TOKaddress) 5685 { 5686 AddrExp *ae = (AddrExp *)e1; 5687 return ae->e1->checkModifiable(sc, flag); 5688 } 5689 return 1; 5690} 5691 5692Expression *PtrExp::modifiableLvalue(Scope *sc, Expression *e) 5693{ 5694 //printf("PtrExp::modifiableLvalue() %s, type %s\n", toChars(), type->toChars()); 5695 return Expression::modifiableLvalue(sc, e); 5696} 5697 5698/************************************************************/ 5699 5700NegExp::NegExp(Loc loc, Expression *e) 5701 : UnaExp(loc, TOKneg, sizeof(NegExp), e) 5702{ 5703} 5704 5705/************************************************************/ 5706 5707UAddExp::UAddExp(Loc loc, Expression *e) 5708 : UnaExp(loc, TOKuadd, sizeof(UAddExp), e) 5709{ 5710} 5711 5712/************************************************************/ 5713 5714ComExp::ComExp(Loc loc, Expression *e) 5715 : UnaExp(loc, TOKtilde, sizeof(ComExp), e) 5716{ 5717} 5718 5719/************************************************************/ 5720 5721NotExp::NotExp(Loc loc, Expression *e) 5722 : UnaExp(loc, TOKnot, sizeof(NotExp), e) 5723{ 5724} 5725 5726/************************************************************/ 5727 5728DeleteExp::DeleteExp(Loc loc, Expression *e, bool isRAII) 5729 : UnaExp(loc, TOKdelete, sizeof(DeleteExp), e) 5730{ 5731 this->isRAII = isRAII; 5732} 5733 5734Expression *DeleteExp::toBoolean(Scope *) 5735{ 5736 error("delete does not give a boolean result"); 5737 return new ErrorExp(); 5738} 5739 5740/************************************************************/ 5741 5742CastExp::CastExp(Loc loc, Expression *e, Type *t) 5743 : UnaExp(loc, TOKcast, sizeof(CastExp), e) 5744{ 5745 this->to = t; 5746 this->mod = (unsigned char)~0; 5747} 5748 5749/* For cast(const) and cast(immutable) 5750 */ 5751CastExp::CastExp(Loc loc, Expression *e, unsigned char mod) 5752 : UnaExp(loc, TOKcast, sizeof(CastExp), e) 5753{ 5754 this->to = NULL; 5755 this->mod = mod; 5756} 5757 5758Expression *CastExp::syntaxCopy() 5759{ 5760 return to ? new CastExp(loc, e1->syntaxCopy(), to->syntaxCopy()) 5761 : new CastExp(loc, e1->syntaxCopy(), mod); 5762} 5763 5764/************************************************************/ 5765 5766VectorExp::VectorExp(Loc loc, Expression *e, Type *t) 5767 : UnaExp(loc, TOKvector, sizeof(VectorExp), e) 5768{ 5769 assert(t->ty == Tvector); 5770 to = (TypeVector *)t; 5771 dim = ~0; 5772 ownedByCtfe = OWNEDcode; 5773} 5774 5775VectorExp *VectorExp::create(Loc loc, Expression *e, Type *t) 5776{ 5777 return new VectorExp(loc, e, t); 5778} 5779 5780Expression *VectorExp::syntaxCopy() 5781{ 5782 return new VectorExp(loc, e1->syntaxCopy(), to->syntaxCopy()); 5783} 5784 5785/************************************************************/ 5786 5787VectorArrayExp::VectorArrayExp(Loc loc, Expression *e1) 5788 : UnaExp(loc, TOKvectorarray, sizeof(VectorArrayExp), e1) 5789{ 5790} 5791 5792bool VectorArrayExp::isLvalue() 5793{ 5794 return e1->isLvalue(); 5795} 5796 5797Expression *VectorArrayExp::toLvalue(Scope *sc, Expression *e) 5798{ 5799 e1 = e1->toLvalue(sc, e); 5800 return this; 5801} 5802 5803/************************************************************/ 5804 5805SliceExp::SliceExp(Loc loc, Expression *e1, IntervalExp *ie) 5806 : UnaExp(loc, TOKslice, sizeof(SliceExp), e1) 5807{ 5808 this->upr = ie ? ie->upr : NULL; 5809 this->lwr = ie ? ie->lwr : NULL; 5810 lengthVar = NULL; 5811 upperIsInBounds = false; 5812 lowerIsLessThanUpper = false; 5813 arrayop = false; 5814} 5815 5816SliceExp::SliceExp(Loc loc, Expression *e1, Expression *lwr, Expression *upr) 5817 : UnaExp(loc, TOKslice, sizeof(SliceExp), e1) 5818{ 5819 this->upr = upr; 5820 this->lwr = lwr; 5821 lengthVar = NULL; 5822 upperIsInBounds = false; 5823 lowerIsLessThanUpper = false; 5824 arrayop = false; 5825} 5826 5827Expression *SliceExp::syntaxCopy() 5828{ 5829 SliceExp *se = new SliceExp(loc, e1->syntaxCopy(), 5830 lwr ? lwr->syntaxCopy() : NULL, 5831 upr ? upr->syntaxCopy() : NULL); 5832 se->lengthVar = this->lengthVar; // bug7871 5833 return se; 5834} 5835 5836int SliceExp::checkModifiable(Scope *sc, int flag) 5837{ 5838 //printf("SliceExp::checkModifiable %s\n", toChars()); 5839 if (e1->type->ty == Tsarray || 5840 (e1->op == TOKindex && e1->type->ty != Tarray) || 5841 e1->op == TOKslice) 5842 { 5843 return e1->checkModifiable(sc, flag); 5844 } 5845 return 1; 5846} 5847 5848bool SliceExp::isLvalue() 5849{ 5850 /* slice expression is rvalue in default, but 5851 * conversion to reference of static array is only allowed. 5852 */ 5853 return (type && type->toBasetype()->ty == Tsarray); 5854} 5855 5856Expression *SliceExp::toLvalue(Scope *sc, Expression *e) 5857{ 5858 //printf("SliceExp::toLvalue(%s) type = %s\n", toChars(), type ? type->toChars() : NULL); 5859 return (type && type->toBasetype()->ty == Tsarray) 5860 ? this : Expression::toLvalue(sc, e); 5861} 5862 5863Expression *SliceExp::modifiableLvalue(Scope *, Expression *) 5864{ 5865 error("slice expression %s is not a modifiable lvalue", toChars()); 5866 return this; 5867} 5868 5869bool SliceExp::isBool(bool result) 5870{ 5871 return e1->isBool(result); 5872} 5873 5874/********************** ArrayLength **************************************/ 5875 5876ArrayLengthExp::ArrayLengthExp(Loc loc, Expression *e1) 5877 : UnaExp(loc, TOKarraylength, sizeof(ArrayLengthExp), e1) 5878{ 5879} 5880 5881Expression *opAssignToOp(Loc loc, TOK op, Expression *e1, Expression *e2) 5882{ Expression *e; 5883 5884 switch (op) 5885 { 5886 case TOKaddass: e = new AddExp(loc, e1, e2); break; 5887 case TOKminass: e = new MinExp(loc, e1, e2); break; 5888 case TOKmulass: e = new MulExp(loc, e1, e2); break; 5889 case TOKdivass: e = new DivExp(loc, e1, e2); break; 5890 case TOKmodass: e = new ModExp(loc, e1, e2); break; 5891 case TOKandass: e = new AndExp(loc, e1, e2); break; 5892 case TOKorass: e = new OrExp (loc, e1, e2); break; 5893 case TOKxorass: e = new XorExp(loc, e1, e2); break; 5894 case TOKshlass: e = new ShlExp(loc, e1, e2); break; 5895 case TOKshrass: e = new ShrExp(loc, e1, e2); break; 5896 case TOKushrass: e = new UshrExp(loc, e1, e2); break; 5897 default: assert(0); 5898 } 5899 return e; 5900} 5901 5902/********************* 5903 * Rewrite: 5904 * array.length op= e2 5905 * as: 5906 * array.length = array.length op e2 5907 * or: 5908 * auto tmp = &array; 5909 * (*tmp).length = (*tmp).length op e2 5910 */ 5911 5912Expression *ArrayLengthExp::rewriteOpAssign(BinExp *exp) 5913{ 5914 Expression *e; 5915 5916 assert(exp->e1->op == TOKarraylength); 5917 ArrayLengthExp *ale = (ArrayLengthExp *)exp->e1; 5918 if (ale->e1->op == TOKvar) 5919 { 5920 e = opAssignToOp(exp->loc, exp->op, ale, exp->e2); 5921 e = new AssignExp(exp->loc, ale->syntaxCopy(), e); 5922 } 5923 else 5924 { 5925 /* auto tmp = &array; 5926 * (*tmp).length = (*tmp).length op e2 5927 */ 5928 VarDeclaration *tmp = copyToTemp(0, "__arraylength", new AddrExp(ale->loc, ale->e1)); 5929 5930 Expression *e1 = new ArrayLengthExp(ale->loc, new PtrExp(ale->loc, new VarExp(ale->loc, tmp))); 5931 Expression *elvalue = e1->syntaxCopy(); 5932 e = opAssignToOp(exp->loc, exp->op, e1, exp->e2); 5933 e = new AssignExp(exp->loc, elvalue, e); 5934 e = new CommaExp(exp->loc, new DeclarationExp(ale->loc, tmp), e); 5935 } 5936 return e; 5937} 5938 5939/*********************** IntervalExp ********************************/ 5940 5941// Mainly just a placeholder 5942 5943IntervalExp::IntervalExp(Loc loc, Expression *lwr, Expression *upr) 5944 : Expression(loc, TOKinterval, sizeof(IntervalExp)) 5945{ 5946 this->lwr = lwr; 5947 this->upr = upr; 5948} 5949 5950Expression *IntervalExp::syntaxCopy() 5951{ 5952 return new IntervalExp(loc, lwr->syntaxCopy(), upr->syntaxCopy()); 5953} 5954 5955/********************** DelegatePtrExp **************************************/ 5956 5957DelegatePtrExp::DelegatePtrExp(Loc loc, Expression *e1) 5958 : UnaExp(loc, TOKdelegateptr, sizeof(DelegatePtrExp), e1) 5959{ 5960} 5961 5962bool DelegatePtrExp::isLvalue() 5963{ 5964 return e1->isLvalue(); 5965} 5966 5967Expression *DelegatePtrExp::toLvalue(Scope *sc, Expression *e) 5968{ 5969 e1 = e1->toLvalue(sc, e); 5970 return this; 5971} 5972 5973Expression *DelegatePtrExp::modifiableLvalue(Scope *sc, Expression *e) 5974{ 5975 if (sc->func->setUnsafe()) 5976 { 5977 error("cannot modify delegate pointer in @safe code %s", toChars()); 5978 return new ErrorExp(); 5979 } 5980 return Expression::modifiableLvalue(sc, e); 5981} 5982 5983/********************** DelegateFuncptrExp **************************************/ 5984 5985DelegateFuncptrExp::DelegateFuncptrExp(Loc loc, Expression *e1) 5986 : UnaExp(loc, TOKdelegatefuncptr, sizeof(DelegateFuncptrExp), e1) 5987{ 5988} 5989 5990bool DelegateFuncptrExp::isLvalue() 5991{ 5992 return e1->isLvalue(); 5993} 5994 5995Expression *DelegateFuncptrExp::toLvalue(Scope *sc, Expression *e) 5996{ 5997 e1 = e1->toLvalue(sc, e); 5998 return this; 5999} 6000 6001Expression *DelegateFuncptrExp::modifiableLvalue(Scope *sc, Expression *e) 6002{ 6003 if (sc->func->setUnsafe()) 6004 { 6005 error("cannot modify delegate function pointer in @safe code %s", toChars()); 6006 return new ErrorExp(); 6007 } 6008 return Expression::modifiableLvalue(sc, e); 6009} 6010 6011/*********************** ArrayExp *************************************/ 6012 6013// e1 [ i1, i2, i3, ... ] 6014 6015ArrayExp::ArrayExp(Loc loc, Expression *e1, Expression *index) 6016 : UnaExp(loc, TOKarray, sizeof(ArrayExp), e1) 6017{ 6018 arguments = new Expressions(); 6019 if (index) 6020 arguments->push(index); 6021 lengthVar = NULL; 6022 currentDimension = 0; 6023} 6024 6025ArrayExp::ArrayExp(Loc loc, Expression *e1, Expressions *args) 6026 : UnaExp(loc, TOKarray, sizeof(ArrayExp), e1) 6027{ 6028 arguments = args; 6029 lengthVar = NULL; 6030 currentDimension = 0; 6031} 6032 6033Expression *ArrayExp::syntaxCopy() 6034{ 6035 ArrayExp *ae = new ArrayExp(loc, e1->syntaxCopy(), arraySyntaxCopy(arguments)); 6036 ae->lengthVar = this->lengthVar; // bug7871 6037 return ae; 6038} 6039 6040bool ArrayExp::isLvalue() 6041{ 6042 if (type && type->toBasetype()->ty == Tvoid) 6043 return false; 6044 return true; 6045} 6046 6047Expression *ArrayExp::toLvalue(Scope *, Expression *) 6048{ 6049 if (type && type->toBasetype()->ty == Tvoid) 6050 error("voids have no value"); 6051 return this; 6052} 6053 6054/************************* DotExp ***********************************/ 6055 6056DotExp::DotExp(Loc loc, Expression *e1, Expression *e2) 6057 : BinExp(loc, TOKdot, sizeof(DotExp), e1, e2) 6058{ 6059} 6060 6061/************************* CommaExp ***********************************/ 6062 6063CommaExp::CommaExp(Loc loc, Expression *e1, Expression *e2, bool generated) 6064 : BinExp(loc, TOKcomma, sizeof(CommaExp), e1, e2) 6065{ 6066 isGenerated = generated; 6067 allowCommaExp = generated; 6068} 6069 6070bool CommaExp::isLvalue() 6071{ 6072 return e2->isLvalue(); 6073} 6074 6075Expression *CommaExp::toLvalue(Scope *sc, Expression *) 6076{ 6077 e2 = e2->toLvalue(sc, NULL); 6078 return this; 6079} 6080 6081int CommaExp::checkModifiable(Scope *sc, int flag) 6082{ 6083 return e2->checkModifiable(sc, flag); 6084} 6085 6086Expression *CommaExp::modifiableLvalue(Scope *sc, Expression *e) 6087{ 6088 e2 = e2->modifiableLvalue(sc, e); 6089 return this; 6090} 6091 6092bool CommaExp::isBool(bool result) 6093{ 6094 return e2->isBool(result); 6095} 6096 6097Expression *CommaExp::toBoolean(Scope *sc) 6098{ 6099 Expression *ex2 = e2->toBoolean(sc); 6100 if (ex2->op == TOKerror) 6101 return ex2; 6102 e2 = ex2; 6103 type = e2->type; 6104 return this; 6105} 6106 6107Expression *CommaExp::addDtorHook(Scope *sc) 6108{ 6109 e2 = e2->addDtorHook(sc); 6110 return this; 6111} 6112 6113/************************** IndexExp **********************************/ 6114 6115// e1 [ e2 ] 6116 6117IndexExp::IndexExp(Loc loc, Expression *e1, Expression *e2) 6118 : BinExp(loc, TOKindex, sizeof(IndexExp), e1, e2) 6119{ 6120 //printf("IndexExp::IndexExp('%s')\n", toChars()); 6121 lengthVar = NULL; 6122 modifiable = false; // assume it is an rvalue 6123 indexIsInBounds = false; 6124} 6125 6126Expression *IndexExp::syntaxCopy() 6127{ 6128 IndexExp *ie = new IndexExp(loc, e1->syntaxCopy(), e2->syntaxCopy()); 6129 ie->lengthVar = this->lengthVar; // bug7871 6130 return ie; 6131} 6132 6133bool IndexExp::isLvalue() 6134{ 6135 return true; 6136} 6137 6138Expression *IndexExp::toLvalue(Scope *, Expression *) 6139{ 6140 return this; 6141} 6142 6143int IndexExp::checkModifiable(Scope *sc, int flag) 6144{ 6145 if (e1->type->ty == Tsarray || 6146 e1->type->ty == Taarray || 6147 (e1->op == TOKindex && e1->type->ty != Tarray) || 6148 e1->op == TOKslice) 6149 { 6150 return e1->checkModifiable(sc, flag); 6151 } 6152 return 1; 6153} 6154 6155Expression *IndexExp::modifiableLvalue(Scope *sc, Expression *e) 6156{ 6157 //printf("IndexExp::modifiableLvalue(%s)\n", toChars()); 6158 Expression *ex = markSettingAAElem(); 6159 if (ex->op == TOKerror) 6160 return ex; 6161 6162 return Expression::modifiableLvalue(sc, e); 6163} 6164 6165Expression *IndexExp::markSettingAAElem() 6166{ 6167 if (e1->type->toBasetype()->ty == Taarray) 6168 { 6169 Type *t2b = e2->type->toBasetype(); 6170 if (t2b->ty == Tarray && t2b->nextOf()->isMutable()) 6171 { 6172 error("associative arrays can only be assigned values with immutable keys, not %s", e2->type->toChars()); 6173 return new ErrorExp(); 6174 } 6175 modifiable = true; 6176 6177 if (e1->op == TOKindex) 6178 { 6179 Expression *ex = ((IndexExp *)e1)->markSettingAAElem(); 6180 if (ex->op == TOKerror) 6181 return ex; 6182 assert(ex == e1); 6183 } 6184 } 6185 return this; 6186} 6187 6188/************************* PostExp ***********************************/ 6189 6190PostExp::PostExp(TOK op, Loc loc, Expression *e) 6191 : BinExp(loc, op, sizeof(PostExp), e, 6192 new IntegerExp(loc, 1, Type::tint32)) 6193{ 6194} 6195 6196/************************* PreExp ***********************************/ 6197 6198PreExp::PreExp(TOK op, Loc loc, Expression *e) 6199 : UnaExp(loc, op, sizeof(PreExp), e) 6200{ 6201} 6202 6203/************************************************************/ 6204 6205/* op can be TOKassign, TOKconstruct, or TOKblit */ 6206 6207AssignExp::AssignExp(Loc loc, Expression *e1, Expression *e2) 6208 : BinExp(loc, TOKassign, sizeof(AssignExp), e1, e2) 6209{ 6210 memset = 0; 6211} 6212 6213bool AssignExp::isLvalue() 6214{ 6215 // Array-op 'x[] = y[]' should make an rvalue. 6216 // Setting array length 'x.length = v' should make an rvalue. 6217 if (e1->op == TOKslice || 6218 e1->op == TOKarraylength) 6219 { 6220 return false; 6221 } 6222 return true; 6223} 6224 6225Expression *AssignExp::toLvalue(Scope *sc, Expression *ex) 6226{ 6227 if (e1->op == TOKslice || 6228 e1->op == TOKarraylength) 6229 { 6230 return Expression::toLvalue(sc, ex); 6231 } 6232 6233 /* In front-end level, AssignExp should make an lvalue of e1. 6234 * Taking the address of e1 will be handled in low level layer, 6235 * so this function does nothing. 6236 */ 6237 return this; 6238} 6239 6240Expression *AssignExp::toBoolean(Scope *) 6241{ 6242 // Things like: 6243 // if (a = b) ... 6244 // are usually mistakes. 6245 6246 error("assignment cannot be used as a condition, perhaps == was meant?"); 6247 return new ErrorExp(); 6248} 6249 6250/************************************************************/ 6251 6252ConstructExp::ConstructExp(Loc loc, Expression *e1, Expression *e2) 6253 : AssignExp(loc, e1, e2) 6254{ 6255 op = TOKconstruct; 6256} 6257 6258ConstructExp::ConstructExp(Loc loc, VarDeclaration *v, Expression *e2) 6259 : AssignExp(loc, new VarExp(loc, v), e2) 6260{ 6261 assert(v->type && e1->type); 6262 op = TOKconstruct; 6263 6264 if (v->storage_class & (STCref | STCout)) 6265 memset |= referenceInit; 6266} 6267 6268/************************************************************/ 6269 6270BlitExp::BlitExp(Loc loc, Expression *e1, Expression *e2) 6271 : AssignExp(loc, e1, e2) 6272{ 6273 op = TOKblit; 6274} 6275 6276BlitExp::BlitExp(Loc loc, VarDeclaration *v, Expression *e2) 6277 : AssignExp(loc, new VarExp(loc, v), e2) 6278{ 6279 assert(v->type && e1->type); 6280 op = TOKblit; 6281 6282 if (v->storage_class & (STCref | STCout)) 6283 memset |= referenceInit; 6284} 6285 6286/************************************************************/ 6287 6288AddAssignExp::AddAssignExp(Loc loc, Expression *e1, Expression *e2) 6289 : BinAssignExp(loc, TOKaddass, sizeof(AddAssignExp), e1, e2) 6290{ 6291} 6292 6293/************************************************************/ 6294 6295MinAssignExp::MinAssignExp(Loc loc, Expression *e1, Expression *e2) 6296 : BinAssignExp(loc, TOKminass, sizeof(MinAssignExp), e1, e2) 6297{ 6298} 6299 6300/************************************************************/ 6301 6302CatAssignExp::CatAssignExp(Loc loc, Expression *e1, Expression *e2) 6303 : BinAssignExp(loc, TOKcatass, sizeof(CatAssignExp), e1, e2) 6304{ 6305} 6306 6307/************************************************************/ 6308 6309MulAssignExp::MulAssignExp(Loc loc, Expression *e1, Expression *e2) 6310 : BinAssignExp(loc, TOKmulass, sizeof(MulAssignExp), e1, e2) 6311{ 6312} 6313 6314/************************************************************/ 6315 6316DivAssignExp::DivAssignExp(Loc loc, Expression *e1, Expression *e2) 6317 : BinAssignExp(loc, TOKdivass, sizeof(DivAssignExp), e1, e2) 6318{ 6319} 6320 6321/************************************************************/ 6322 6323ModAssignExp::ModAssignExp(Loc loc, Expression *e1, Expression *e2) 6324 : BinAssignExp(loc, TOKmodass, sizeof(ModAssignExp), e1, e2) 6325{ 6326} 6327 6328/************************************************************/ 6329 6330ShlAssignExp::ShlAssignExp(Loc loc, Expression *e1, Expression *e2) 6331 : BinAssignExp(loc, TOKshlass, sizeof(ShlAssignExp), e1, e2) 6332{ 6333} 6334 6335/************************************************************/ 6336 6337ShrAssignExp::ShrAssignExp(Loc loc, Expression *e1, Expression *e2) 6338 : BinAssignExp(loc, TOKshrass, sizeof(ShrAssignExp), e1, e2) 6339{ 6340} 6341 6342/************************************************************/ 6343 6344UshrAssignExp::UshrAssignExp(Loc loc, Expression *e1, Expression *e2) 6345 : BinAssignExp(loc, TOKushrass, sizeof(UshrAssignExp), e1, e2) 6346{ 6347} 6348 6349/************************************************************/ 6350 6351AndAssignExp::AndAssignExp(Loc loc, Expression *e1, Expression *e2) 6352 : BinAssignExp(loc, TOKandass, sizeof(AndAssignExp), e1, e2) 6353{ 6354} 6355 6356/************************************************************/ 6357 6358OrAssignExp::OrAssignExp(Loc loc, Expression *e1, Expression *e2) 6359 : BinAssignExp(loc, TOKorass, sizeof(OrAssignExp), e1, e2) 6360{ 6361} 6362 6363/************************************************************/ 6364 6365XorAssignExp::XorAssignExp(Loc loc, Expression *e1, Expression *e2) 6366 : BinAssignExp(loc, TOKxorass, sizeof(XorAssignExp), e1, e2) 6367{ 6368} 6369 6370/***************** PowAssignExp *******************************************/ 6371 6372PowAssignExp::PowAssignExp(Loc loc, Expression *e1, Expression *e2) 6373 : BinAssignExp(loc, TOKpowass, sizeof(PowAssignExp), e1, e2) 6374{ 6375} 6376 6377/************************* AddExp *****************************/ 6378 6379AddExp::AddExp(Loc loc, Expression *e1, Expression *e2) 6380 : BinExp(loc, TOKadd, sizeof(AddExp), e1, e2) 6381{ 6382} 6383 6384/************************************************************/ 6385 6386MinExp::MinExp(Loc loc, Expression *e1, Expression *e2) 6387 : BinExp(loc, TOKmin, sizeof(MinExp), e1, e2) 6388{ 6389} 6390 6391/************************* CatExp *****************************/ 6392 6393CatExp::CatExp(Loc loc, Expression *e1, Expression *e2) 6394 : BinExp(loc, TOKcat, sizeof(CatExp), e1, e2) 6395{ 6396} 6397 6398/************************************************************/ 6399 6400MulExp::MulExp(Loc loc, Expression *e1, Expression *e2) 6401 : BinExp(loc, TOKmul, sizeof(MulExp), e1, e2) 6402{ 6403} 6404 6405/************************************************************/ 6406 6407DivExp::DivExp(Loc loc, Expression *e1, Expression *e2) 6408 : BinExp(loc, TOKdiv, sizeof(DivExp), e1, e2) 6409{ 6410} 6411 6412/************************************************************/ 6413 6414ModExp::ModExp(Loc loc, Expression *e1, Expression *e2) 6415 : BinExp(loc, TOKmod, sizeof(ModExp), e1, e2) 6416{ 6417} 6418 6419/************************************************************/ 6420 6421PowExp::PowExp(Loc loc, Expression *e1, Expression *e2) 6422 : BinExp(loc, TOKpow, sizeof(PowExp), e1, e2) 6423{ 6424} 6425 6426/************************************************************/ 6427 6428ShlExp::ShlExp(Loc loc, Expression *e1, Expression *e2) 6429 : BinExp(loc, TOKshl, sizeof(ShlExp), e1, e2) 6430{ 6431} 6432 6433/************************************************************/ 6434 6435ShrExp::ShrExp(Loc loc, Expression *e1, Expression *e2) 6436 : BinExp(loc, TOKshr, sizeof(ShrExp), e1, e2) 6437{ 6438} 6439 6440/************************************************************/ 6441 6442UshrExp::UshrExp(Loc loc, Expression *e1, Expression *e2) 6443 : BinExp(loc, TOKushr, sizeof(UshrExp), e1, e2) 6444{ 6445} 6446 6447/************************************************************/ 6448 6449AndExp::AndExp(Loc loc, Expression *e1, Expression *e2) 6450 : BinExp(loc, TOKand, sizeof(AndExp), e1, e2) 6451{ 6452} 6453 6454/************************************************************/ 6455 6456OrExp::OrExp(Loc loc, Expression *e1, Expression *e2) 6457 : BinExp(loc, TOKor, sizeof(OrExp), e1, e2) 6458{ 6459} 6460 6461/************************************************************/ 6462 6463XorExp::XorExp(Loc loc, Expression *e1, Expression *e2) 6464 : BinExp(loc, TOKxor, sizeof(XorExp), e1, e2) 6465{ 6466} 6467 6468/************************************************************/ 6469 6470OrOrExp::OrOrExp(Loc loc, Expression *e1, Expression *e2) 6471 : BinExp(loc, TOKoror, sizeof(OrOrExp), e1, e2) 6472{ 6473} 6474 6475Expression *OrOrExp::toBoolean(Scope *sc) 6476{ 6477 Expression *ex2 = e2->toBoolean(sc); 6478 if (ex2->op == TOKerror) 6479 return ex2; 6480 e2 = ex2; 6481 return this; 6482} 6483 6484/************************************************************/ 6485 6486AndAndExp::AndAndExp(Loc loc, Expression *e1, Expression *e2) 6487 : BinExp(loc, TOKandand, sizeof(AndAndExp), e1, e2) 6488{ 6489} 6490 6491Expression *AndAndExp::toBoolean(Scope *sc) 6492{ 6493 Expression *ex2 = e2->toBoolean(sc); 6494 if (ex2->op == TOKerror) 6495 return ex2; 6496 e2 = ex2; 6497 return this; 6498} 6499 6500/************************************************************/ 6501 6502InExp::InExp(Loc loc, Expression *e1, Expression *e2) 6503 : BinExp(loc, TOKin, sizeof(InExp), e1, e2) 6504{ 6505} 6506 6507/************************************************************/ 6508 6509/* This deletes the key e1 from the associative array e2 6510 */ 6511 6512RemoveExp::RemoveExp(Loc loc, Expression *e1, Expression *e2) 6513 : BinExp(loc, TOKremove, sizeof(RemoveExp), e1, e2) 6514{ 6515 type = Type::tbool; 6516} 6517 6518/************************************************************/ 6519 6520CmpExp::CmpExp(TOK op, Loc loc, Expression *e1, Expression *e2) 6521 : BinExp(loc, op, sizeof(CmpExp), e1, e2) 6522{ 6523} 6524 6525/************************************************************/ 6526 6527EqualExp::EqualExp(TOK op, Loc loc, Expression *e1, Expression *e2) 6528 : BinExp(loc, op, sizeof(EqualExp), e1, e2) 6529{ 6530 assert(op == TOKequal || op == TOKnotequal); 6531} 6532 6533/************************************************************/ 6534 6535IdentityExp::IdentityExp(TOK op, Loc loc, Expression *e1, Expression *e2) 6536 : BinExp(loc, op, sizeof(IdentityExp), e1, e2) 6537{ 6538} 6539 6540/****************************************************************/ 6541 6542CondExp::CondExp(Loc loc, Expression *econd, Expression *e1, Expression *e2) 6543 : BinExp(loc, TOKquestion, sizeof(CondExp), e1, e2) 6544{ 6545 this->econd = econd; 6546} 6547 6548Expression *CondExp::syntaxCopy() 6549{ 6550 return new CondExp(loc, econd->syntaxCopy(), e1->syntaxCopy(), e2->syntaxCopy()); 6551} 6552 6553void CondExp::hookDtors(Scope *sc) 6554{ 6555 class DtorVisitor : public StoppableVisitor 6556 { 6557 public: 6558 Scope *sc; 6559 CondExp *ce; 6560 VarDeclaration *vcond; 6561 bool isThen; 6562 6563 DtorVisitor(Scope *sc, CondExp *ce) 6564 { 6565 this->sc = sc; 6566 this->ce = ce; 6567 this->vcond = NULL; 6568 } 6569 6570 void visit(Expression *) 6571 { 6572 //printf("(e = %s)\n", e->toChars()); 6573 } 6574 6575 void visit(DeclarationExp *e) 6576 { 6577 VarDeclaration *v = e->declaration->isVarDeclaration(); 6578 if (v && !v->isDataseg()) 6579 { 6580 if (v->_init) 6581 { 6582 ExpInitializer *ei = v->_init->isExpInitializer(); 6583 if (ei) 6584 ei->exp->accept(this); 6585 } 6586 6587 if (v->needsScopeDtor()) 6588 { 6589 if (!vcond) 6590 { 6591 vcond = copyToTemp(STCvolatile, "__cond", ce->econd); 6592 vcond->semantic(sc); 6593 6594 Expression *de = new DeclarationExp(ce->econd->loc, vcond); 6595 de = semantic(de, sc); 6596 6597 Expression *ve = new VarExp(ce->econd->loc, vcond); 6598 ce->econd = Expression::combine(de, ve); 6599 } 6600 6601 //printf("\t++v = %s, v->edtor = %s\n", v->toChars(), v->edtor->toChars()); 6602 Expression *ve = new VarExp(vcond->loc, vcond); 6603 if (isThen) 6604 v->edtor = new AndAndExp(v->edtor->loc, ve, v->edtor); 6605 else 6606 v->edtor = new OrOrExp(v->edtor->loc, ve, v->edtor); 6607 v->edtor = semantic(v->edtor, sc); 6608 //printf("\t--v = %s, v->edtor = %s\n", v->toChars(), v->edtor->toChars()); 6609 } 6610 } 6611 } 6612 }; 6613 6614 DtorVisitor v(sc, this); 6615 //printf("+%s\n", toChars()); 6616 v.isThen = true; walkPostorder(e1, &v); 6617 v.isThen = false; walkPostorder(e2, &v); 6618 //printf("-%s\n", toChars()); 6619} 6620 6621bool CondExp::isLvalue() 6622{ 6623 return e1->isLvalue() && e2->isLvalue(); 6624} 6625 6626 6627Expression *CondExp::toLvalue(Scope *sc, Expression *) 6628{ 6629 // convert (econd ? e1 : e2) to *(econd ? &e1 : &e2) 6630 CondExp *e = (CondExp *)copy(); 6631 e->e1 = e1->toLvalue(sc, NULL)->addressOf(); 6632 e->e2 = e2->toLvalue(sc, NULL)->addressOf(); 6633 e->type = type->pointerTo(); 6634 return new PtrExp(loc, e, type); 6635} 6636 6637int CondExp::checkModifiable(Scope *sc, int flag) 6638{ 6639 return e1->checkModifiable(sc, flag) && e2->checkModifiable(sc, flag); 6640} 6641 6642Expression *CondExp::modifiableLvalue(Scope *sc, Expression *) 6643{ 6644 //error("conditional expression %s is not a modifiable lvalue", toChars()); 6645 e1 = e1->modifiableLvalue(sc, e1); 6646 e2 = e2->modifiableLvalue(sc, e2); 6647 return toLvalue(sc, this); 6648} 6649 6650Expression *CondExp::toBoolean(Scope *sc) 6651{ 6652 Expression *ex1 = e1->toBoolean(sc); 6653 Expression *ex2 = e2->toBoolean(sc); 6654 if (ex1->op == TOKerror) 6655 return ex1; 6656 if (ex2->op == TOKerror) 6657 return ex2; 6658 e1 = ex1; 6659 e2 = ex2; 6660 return this; 6661} 6662 6663/****************************************************************/ 6664 6665DefaultInitExp::DefaultInitExp(Loc loc, TOK subop, int size) 6666 : Expression(loc, TOKdefault, size) 6667{ 6668 this->subop = subop; 6669} 6670 6671/****************************************************************/ 6672 6673FileInitExp::FileInitExp(Loc loc, TOK tok) 6674 : DefaultInitExp(loc, tok, sizeof(FileInitExp)) 6675{ 6676} 6677 6678Expression *FileInitExp::resolveLoc(Loc loc, Scope *sc) 6679{ 6680 //printf("FileInitExp::resolve() %s\n", toChars()); 6681 const char *s = loc.filename ? loc.filename : sc->_module->ident->toChars(); 6682 if (subop == TOKfilefullpath) 6683 s = FileName::combine(sc->_module->srcfilePath, s); 6684 Expression *e = new StringExp(loc, const_cast<char *>(s)); 6685 e = semantic(e, sc); 6686 e = e->castTo(sc, type); 6687 return e; 6688} 6689 6690/****************************************************************/ 6691 6692LineInitExp::LineInitExp(Loc loc) 6693 : DefaultInitExp(loc, TOKline, sizeof(LineInitExp)) 6694{ 6695} 6696 6697Expression *LineInitExp::resolveLoc(Loc loc, Scope *sc) 6698{ 6699 Expression *e = new IntegerExp(loc, loc.linnum, Type::tint32); 6700 e = e->castTo(sc, type); 6701 return e; 6702} 6703 6704/****************************************************************/ 6705 6706ModuleInitExp::ModuleInitExp(Loc loc) 6707 : DefaultInitExp(loc, TOKmodulestring, sizeof(ModuleInitExp)) 6708{ 6709} 6710 6711Expression *ModuleInitExp::resolveLoc(Loc loc, Scope *sc) 6712{ 6713 const char *s; 6714 if (sc->callsc) 6715 s = sc->callsc->_module->toPrettyChars(); 6716 else 6717 s = sc->_module->toPrettyChars(); 6718 Expression *e = new StringExp(loc, const_cast<char *>(s)); 6719 e = semantic(e, sc); 6720 e = e->castTo(sc, type); 6721 return e; 6722} 6723 6724/****************************************************************/ 6725 6726FuncInitExp::FuncInitExp(Loc loc) 6727 : DefaultInitExp(loc, TOKfuncstring, sizeof(FuncInitExp)) 6728{ 6729} 6730 6731Expression *FuncInitExp::resolveLoc(Loc loc, Scope *sc) 6732{ 6733 const char *s; 6734 if (sc->callsc && sc->callsc->func) 6735 s = sc->callsc->func->Dsymbol::toPrettyChars(); 6736 else if (sc->func) 6737 s = sc->func->Dsymbol::toPrettyChars(); 6738 else 6739 s = ""; 6740 Expression *e = new StringExp(loc, const_cast<char *>(s)); 6741 e = semantic(e, sc); 6742 e->type = Type::tstring; 6743 return e; 6744} 6745 6746/****************************************************************/ 6747 6748PrettyFuncInitExp::PrettyFuncInitExp(Loc loc) 6749 : DefaultInitExp(loc, TOKprettyfunc, sizeof(PrettyFuncInitExp)) 6750{ 6751} 6752 6753Expression *PrettyFuncInitExp::resolveLoc(Loc loc, Scope *sc) 6754{ 6755 FuncDeclaration *fd; 6756 if (sc->callsc && sc->callsc->func) 6757 fd = sc->callsc->func; 6758 else 6759 fd = sc->func; 6760 6761 const char *s; 6762 if (fd) 6763 { 6764 const char *funcStr = fd->Dsymbol::toPrettyChars(); 6765 OutBuffer buf; 6766 functionToBufferWithIdent((TypeFunction *)fd->type, &buf, funcStr); 6767 s = buf.extractString(); 6768 } 6769 else 6770 { 6771 s = ""; 6772 } 6773 6774 Expression *e = new StringExp(loc, const_cast<char *>(s)); 6775 e = semantic(e, sc); 6776 e->type = Type::tstring; 6777 return e; 6778} 6779 6780/****************************************************************/ 6781 6782Expression *extractOpDollarSideEffect(Scope *sc, UnaExp *ue) 6783{ 6784 Expression *e0; 6785 Expression *e1 = Expression::extractLast(ue->e1, &e0); 6786 // Bugzilla 12585: Extract the side effect part if ue->e1 is comma. 6787 6788 if (!isTrivialExp(e1)) 6789 { 6790 /* Even if opDollar is needed, 'e1' should be evaluate only once. So 6791 * Rewrite: 6792 * e1.opIndex( ... use of $ ... ) 6793 * e1.opSlice( ... use of $ ... ) 6794 * as: 6795 * (ref __dop = e1, __dop).opIndex( ... __dop.opDollar ...) 6796 * (ref __dop = e1, __dop).opSlice( ... __dop.opDollar ...) 6797 */ 6798 e1 = extractSideEffect(sc, "__dop", &e0, e1, false); 6799 assert(e1->op == TOKvar); 6800 VarExp *ve = (VarExp *)e1; 6801 ve->var->storage_class |= STCexptemp; // lifetime limited to expression 6802 } 6803 ue->e1 = e1; 6804 return e0; 6805} 6806 6807/************************************** 6808 * Runs semantic on ae->arguments. Declares temporary variables 6809 * if '$' was used. 6810 */ 6811Expression *resolveOpDollar(Scope *sc, ArrayExp *ae, Expression **pe0) 6812{ 6813 assert(!ae->lengthVar); 6814 6815 *pe0 = NULL; 6816 6817 AggregateDeclaration *ad = isAggregate(ae->e1->type); 6818 Dsymbol *slice = search_function(ad, Id::slice); 6819 //printf("slice = %s %s\n", slice->kind(), slice->toChars()); 6820 6821 for (size_t i = 0; i < ae->arguments->dim; i++) 6822 { 6823 if (i == 0) 6824 *pe0 = extractOpDollarSideEffect(sc, ae); 6825 6826 Expression *e = (*ae->arguments)[i]; 6827 if (e->op == TOKinterval && !(slice && slice->isTemplateDeclaration())) 6828 { 6829 Lfallback: 6830 if (ae->arguments->dim == 1) 6831 return NULL; 6832 ae->error("multi-dimensional slicing requires template opSlice"); 6833 return new ErrorExp(); 6834 } 6835 //printf("[%d] e = %s\n", i, e->toChars()); 6836 6837 // Create scope for '$' variable for this dimension 6838 ArrayScopeSymbol *sym = new ArrayScopeSymbol(sc, ae); 6839 sym->loc = ae->loc; 6840 sym->parent = sc->scopesym; 6841 sc = sc->push(sym); 6842 ae->lengthVar = NULL; // Create it only if required 6843 ae->currentDimension = i; // Dimension for $, if required 6844 6845 e = semantic(e, sc); 6846 e = resolveProperties(sc, e); 6847 6848 if (ae->lengthVar && sc->func) 6849 { 6850 // If $ was used, declare it now 6851 Expression *de = new DeclarationExp(ae->loc, ae->lengthVar); 6852 de = semantic(de, sc); 6853 *pe0 = Expression::combine(*pe0, de); 6854 } 6855 sc = sc->pop(); 6856 6857 if (e->op == TOKinterval) 6858 { 6859 IntervalExp *ie = (IntervalExp *)e; 6860 6861 Objects *tiargs = new Objects(); 6862 Expression *edim = new IntegerExp(ae->loc, i, Type::tsize_t); 6863 edim = semantic(edim, sc); 6864 tiargs->push(edim); 6865 6866 Expressions *fargs = new Expressions(); 6867 fargs->push(ie->lwr); 6868 fargs->push(ie->upr); 6869 6870 unsigned xerrors = global.startGagging(); 6871 sc = sc->push(); 6872 FuncDeclaration *fslice = resolveFuncCall(ae->loc, sc, slice, tiargs, ae->e1->type, fargs, 1); 6873 sc = sc->pop(); 6874 global.endGagging(xerrors); 6875 if (!fslice) 6876 goto Lfallback; 6877 6878 e = new DotTemplateInstanceExp(ae->loc, ae->e1, slice->ident, tiargs); 6879 e = new CallExp(ae->loc, e, fargs); 6880 e = semantic(e, sc); 6881 } 6882 6883 if (!e->type) 6884 { 6885 ae->error("%s has no value", e->toChars()); 6886 e = new ErrorExp(); 6887 } 6888 if (e->op == TOKerror) 6889 return e; 6890 6891 (*ae->arguments)[i] = e; 6892 } 6893 6894 return ae; 6895} 6896 6897/*********************************************************** 6898 * Resolve `exp` as a compile-time known string. 6899 * Params: 6900 * sc = scope 6901 * exp = Expression which expected as a string 6902 * s = What the string is expected for, will be used in error diagnostic. 6903 * Returns: 6904 * String literal, or `null` if error happens. 6905 */ 6906StringExp *semanticString(Scope *sc, Expression *exp, const char *s) 6907{ 6908 sc = sc->startCTFE(); 6909 exp = semantic(exp, sc); 6910 exp = resolveProperties(sc, exp); 6911 sc = sc->endCTFE(); 6912 6913 if (exp->op == TOKerror) 6914 return NULL; 6915 6916 Expression *e = exp; 6917 if (exp->type->isString()) 6918 { 6919 e = e->ctfeInterpret(); 6920 if (e->op == TOKerror) 6921 return NULL; 6922 } 6923 6924 StringExp *se = e->toStringExp(); 6925 if (!se) 6926 { 6927 exp->error("string expected for %s, not (%s) of type %s", 6928 s, exp->toChars(), exp->type->toChars()); 6929 return NULL; 6930 } 6931 return se; 6932} 6933 6934/************************************** 6935 * Runs semantic on se->lwr and se->upr. Declares a temporary variable 6936 * if '$' was used. 6937 */ 6938Expression *resolveOpDollar(Scope *sc, ArrayExp *ae, IntervalExp *ie, Expression **pe0) 6939{ 6940 //assert(!ae->lengthVar); 6941 if (!ie) 6942 return ae; 6943 6944 VarDeclaration *lengthVar = ae->lengthVar; 6945 6946 // create scope for '$' 6947 ArrayScopeSymbol *sym = new ArrayScopeSymbol(sc, ae); 6948 sym->loc = ae->loc; 6949 sym->parent = sc->scopesym; 6950 sc = sc->push(sym); 6951 6952 for (size_t i = 0; i < 2; ++i) 6953 { 6954 Expression *e = i == 0 ? ie->lwr : ie->upr; 6955 e = semantic(e, sc); 6956 e = resolveProperties(sc, e); 6957 if (!e->type) 6958 { 6959 ae->error("%s has no value", e->toChars()); 6960 return new ErrorExp(); 6961 } 6962 (i == 0 ? ie->lwr : ie->upr) = e; 6963 } 6964 6965 if (lengthVar != ae->lengthVar && sc->func) 6966 { 6967 // If $ was used, declare it now 6968 Expression *de = new DeclarationExp(ae->loc, ae->lengthVar); 6969 de = semantic(de, sc); 6970 *pe0 = Expression::combine(*pe0, de); 6971 } 6972 sc = sc->pop(); 6973 6974 return ae; 6975} 6976 6977Expression *BinExp::reorderSettingAAElem(Scope *sc) 6978{ 6979 BinExp *be = this; 6980 6981 if (be->e1->op != TOKindex) 6982 return be; 6983 IndexExp *ie = (IndexExp *)be->e1; 6984 if (ie->e1->type->toBasetype()->ty != Taarray) 6985 return be; 6986 6987 /* Fix evaluation order of setting AA element. (Bugzilla 3825) 6988 * Rewrite: 6989 * aa[k1][k2][k3] op= val; 6990 * as: 6991 * auto ref __aatmp = aa; 6992 * auto ref __aakey3 = k1, __aakey2 = k2, __aakey1 = k3; 6993 * auto ref __aaval = val; 6994 * __aatmp[__aakey3][__aakey2][__aakey1] op= __aaval; // assignment 6995 */ 6996 6997 Expression *e0 = NULL; 6998 while (1) 6999 { 7000 Expression *de = NULL; 7001 ie->e2 = extractSideEffect(sc, "__aakey", &de, ie->e2); 7002 e0 = Expression::combine(de, e0); 7003 7004 Expression *ie1 = ie->e1; 7005 if (ie1->op != TOKindex || 7006 ((IndexExp *)ie1)->e1->type->toBasetype()->ty != Taarray) 7007 { 7008 break; 7009 } 7010 ie = (IndexExp *)ie1; 7011 } 7012 assert(ie->e1->type->toBasetype()->ty == Taarray); 7013 7014 Expression *de = NULL; 7015 ie->e1 = extractSideEffect(sc, "__aatmp", &de, ie->e1); 7016 e0 = Expression::combine(de, e0); 7017 7018 be->e2 = extractSideEffect(sc, "__aaval", &e0, be->e2, true); 7019 7020 //printf("-e0 = %s, be = %s\n", e0->toChars(), be->toChars()); 7021 return Expression::combine(e0, be); 7022} 7023