1: 
    2: // Compiler implementation of the D programming language
    3: // Copyright (c) 1999-2011 by Digital Mars
    4: // All Rights Reserved
    5: // written by Walter Bright
    6: // http://www.digitalmars.com
    7: // License for redistribution is by either the Artistic License
    8: // in artistic.txt, or the GNU General Public License in gnu.txt.
    9: // See the included readme.txt for details.
   10: 
   11: #include <stdio.h>
   12: #include <stdlib.h>
   13: #include <ctype.h>
   14: #include <math.h>
   15: static char __file__[] = __FILE__;      /* for tassert.h                */
   16: #include        "tassert.h"
   17: #if _MSC_VER
   18: #include <complex>
   19: #else
   20: #include <complex.h>
   21: #endif
   22: 
   23: #if _WIN32 && __DMC__
   24: extern "C" char * __cdecl __locale_decpoint;
   25: #endif
   26: 
   27: #include "cdef.h"
   28: #include "rmem.h"
   29: #include "port.h"
   30: #include "root.h"
   31: 
   32: #include "mtype.h"
   33: #include "init.h"
   34: #include "expression.h"
   35: #include "template.h"
   36: #include "utf.h"
   37: #include "enum.h"
   38: #include "scope.h"
   39: #include "statement.h"
   40: #include "declaration.h"
   41: #include "aggregate.h"
   42: #include "import.h"
   43: #include "id.h"
   44: #include "dsymbol.h"
   45: #include "module.h"
   46: #include "attrib.h"
   47: #include "hdrgen.h"
   48: #include "parse.h"
   49: #include "doc.h"
   50: 
   51: 
   52: Expression *createTypeInfoArray(Scope *sc, Expression *args[], int dim);
   53: Expression *expandVar(int result, VarDeclaration *v);
   54: 
   55: #define LOGSEMANTIC     0
   56: 
   57: /*************************************************************
   58:  * Given var, we need to get the
   59:  * right 'this' pointer if var is in an outer class, but our
   60:  * existing 'this' pointer is in an inner class.
   61:  * Input:
   62:  *      e1      existing 'this'
   63:  *      ad      struct or class we need the correct 'this' for
   64:  *      var     the specific member of ad we're accessing
   65:  */
   66: 
   67: Expression *getRightThis(Loc loc, Scope *sc, AggregateDeclaration *ad,
   68:         Expression *e1, Declaration *var)
   69: {
   70:     //printf("\ngetRightThis(e1 = %s, ad = %s, var = %s)\n", e1->toChars(), ad->toChars(), var->toChars());
   71:  L1:
   72:     Type *t = e1->type->toBasetype();
   73:     //printf("e1->type = %s, var->type = %s\n", e1->type->toChars(), var->type->toChars());
   74: 
   75:     /* If e1 is not the 'this' pointer for ad
   76:      */
   77:     if (ad &&
   78:         !(t->ty == Tpointer && t->nextOf()->ty == Tstruct &&
   79:           ((TypeStruct *)t->nextOf())->sym == ad)
   80:         &&
   81:         !(t->ty == Tstruct &&
   82:           ((TypeStruct *)t)->sym == ad)
   83:        )
   84:     {
   85:         ClassDeclaration *cd = ad->isClassDeclaration();
   86:         ClassDeclaration *tcd = t->isClassHandle();
   87: 
   88:         /* e1 is the right this if ad is a base class of e1
   89:          */
   90:         if (!cd || !tcd ||
   91:             !(tcd == cd || cd->isBaseOf(tcd, NULL))
   92:            )
   93:         {
   94:             /* Only classes can be inner classes with an 'outer'
   95:              * member pointing to the enclosing class instance
   96:              */
   97:             if (tcd && tcd->isNested())
   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);
warning C6211: Leaking memory 'e1' due to an exception. Consider using a local catch block to clean up memory: Lines: 71, 72, 80, 85, 86, 90, 97, 102, 103, 109, 110, 111, 112, 130, 136, 137, 71, 72, 80, 85, 86, 90, 97, 102, 103, 109, 110, 111, 112, 130, 136, 137, 71, 72, 80, 85, 86, 90, 97, 102, 103, 109, 110, 111, 112, 114, 115, 118, 119
103: e1->type = tcd->vthis->type; 104: // Do not call checkNestedRef() 105: //e1 = e1->semantic(sc); 106: 107: // Skip up over nested functions, and get the enclosing 108: // class type. 109: int n = 0; 110: Dsymbol *s; 111: for (s = tcd->toParent(); 112: s && s->isFuncDeclaration(); 113: s = s->toParent()) 114: { FuncDeclaration *f = s->isFuncDeclaration(); 115: if (f->vthis) 116: { 117: //printf("rewriting e1 to %s's this\n", f->toChars()); 118: n++; 119: e1 = new VarExp(loc, f->vthis); 120: } 121: else 122: { 123: e1->error("need 'this' of type %s to access member %s" 124: " from static function %s", 125: ad->toChars(), var->toChars(), f->toChars()); 126: e1 = new ErrorExp(); 127: return e1; 128: } 129: } 130: if (s && s->isClassDeclaration()) 131: { e1->type = s->isClassDeclaration()->type; 132: if (n > 1) 133: e1 = e1->semantic(sc); 134: } 135: else 136: e1 = e1->semantic(sc); 137: goto L1; 138: } 139: /* Can't find a path from e1 to ad 140: */ 141: e1->error("this for %s needs to be type %s not type %s", 142: var->toChars(), ad->toChars(), t->toChars()); 143: e1 = new ErrorExp(); 144: } 145: } 146: return e1; 147: } 148: 149: /***************************************** 150: * Determine if 'this' is available. 151: * If it is, return the FuncDeclaration that has it. 152: */ 153: 154: FuncDeclaration *hasThis(Scope *sc) 155: { FuncDeclaration *fd; 156: FuncDeclaration *fdthis; 157: 158: //printf("hasThis()\n"); 159: fdthis = sc->parent->isFuncDeclaration(); 160: //printf("fdthis = %p, '%s'\n", fdthis, fdthis ? fdthis->toChars() : ""); 161: 162: // Go upwards until we find the enclosing member function 163: fd = fdthis; 164: while (1) 165: { 166: if (!fd) 167: { 168: goto Lno; 169: } 170: if (!fd->isNested()) 171: break; 172: 173: Dsymbol *parent = fd->parent; 174: while (parent) 175: { 176: TemplateInstance *ti = parent->isTemplateInstance(); 177: if (ti) 178: parent = ti->parent; 179: else 180: break; 181: } 182: 183: fd = parent->isFuncDeclaration();
warning C6011: Dereferencing NULL pointer 'parent': Lines: 155, 156, 159, 163, 164, 166, 170, 173, 174, 183
184: } 185: 186: if (!fd->isThis()) 187: { //printf("test '%s'\n", fd->toChars()); 188: goto Lno; 189: } 190: 191: assert(fd->vthis); 192: return fd; 193: 194: Lno: 195: return NULL; // don't have 'this' available 196: } 197: 198: 199: /*************************************** 200: * Pull out any properties. 201: */ 202: 203: Expression *resolveProperties(Scope *sc, Expression *e) 204: { 205: //printf("resolveProperties(%s)\n", e->toChars()); 206: if (e->type) 207: { 208: Type *t = e->type->toBasetype(); 209: 210: if (t->ty == Tfunction || e->op == TOKoverloadset) 211: { 212: #if 1 213: if (t->ty == Tfunction && !((TypeFunction *)t)->isproperty && 214: global.params.enforcePropertySyntax) 215: { 216: error(e->loc, "not a property %s\n", e->toChars()); 217: } 218: #endif 219: e = new CallExp(e->loc, e); 220: e = e->semantic(sc); 221: } 222: 223: /* Look for e being a lazy parameter; rewrite as delegate call 224: */ 225: else if (e->op == TOKvar) 226: { VarExp *ve = (VarExp *)e; 227: 228: if (ve->var->storage_class & STClazy) 229: { 230: e = new CallExp(e->loc, e); 231: e = e->semantic(sc); 232: } 233: } 234: 235: else if (e->op == TOKdotexp) 236: { 237: e->error("expression has no value"); 238: return new ErrorExp(); 239: } 240: 241: } 242: else if (e->op == TOKdottd) 243: { 244: e = new CallExp(e->loc, e); 245: e = e->semantic(sc); 246: } 247: return e; 248: } 249: 250: /****************************** 251: * Perform semantic() on an array of Expressions. 252: */ 253: 254: Expressions *arrayExpressionSemantic(Expressions *exps, Scope *sc) 255: { 256: if (exps) 257: { 258: for (size_t i = 0; i < exps->dim; i++) 259: { Expression *e = (*exps)[i]; 260: if (e) 261: { e = e->semantic(sc); 262: (*exps)[i] = e; 263: } 264: } 265: } 266: return exps; 267: } 268: 269: 270: /****************************** 271: * Perform canThrow() on an array of Expressions. 272: */ 273: 274: #if DMDV2 275: int arrayExpressionCanThrow(Expressions *exps, bool mustNotThrow) 276: { 277: if (exps) 278: { 279: for (size_t i = 0; i < exps->dim; i++) 280: { Expression *e = (*exps)[i]; 281: if (e && e->canThrow(mustNotThrow)) 282: return 1; 283: } 284: } 285: return 0; 286: } 287: #endif 288: 289: /**************************************** 290: * Expand tuples. 291: */ 292: 293: void expandTuples(Expressions *exps) 294: { 295: //printf("expandTuples()\n"); 296: if (exps) 297: { 298: for (size_t i = 0; i < exps->dim; i++) 299: { Expression *arg = (*exps)[i]; 300: if (!arg) 301: continue; 302: 303: // Look for tuple with 0 members 304: if (arg->op == TOKtype) 305: { TypeExp *e = (TypeExp *)arg; 306: if (e->type->toBasetype()->ty == Ttuple) 307: { TypeTuple *tt = (TypeTuple *)e->type->toBasetype(); 308: 309: if (!tt->arguments || tt->arguments->dim == 0) 310: { 311: exps->remove(i); 312: if (i == exps->dim) 313: return; 314: i--; 315: continue; 316: } 317: } 318: } 319: 320: // Inline expand all the tuples 321: while (arg->op == TOKtuple) 322: { TupleExp *te = (TupleExp *)arg; 323: 324: exps->remove(i); // remove arg 325: exps->insert(i, te->exps); // replace with tuple contents 326: if (i == exps->dim) 327: return; // empty tuple, no more arguments 328: arg = (*exps)[i]; 329: } 330: } 331: } 332: } 333: 334: Expressions *arrayExpressionToCommonType(Scope *sc, Expressions *exps, Type **pt) 335: { 336: #if DMDV1 337: /* The first element sets the type 338: */ 339: Type *t0 = NULL; 340: for (size_t i = 0; i < exps->dim; i++) 341: { Expression *e = (*exps)[i]; 342: 343: if (!e->type) 344: { error("%s has no value", e->toChars()); 345: e = new ErrorExp(); 346: } 347: e = resolveProperties(sc, e); 348: 349: if (!t0) 350: t0 = e->type; 351: else 352: e = e->implicitCastTo(sc, t0); 353: (*exps)[i] = e; 354: } 355: 356: if (!t0) 357: t0 = Type::tvoid; 358: if (pt) 359: *pt = t0; 360: 361: // Eventually, we want to make this copy-on-write 362: return exps; 363: #endif 364: #if DMDV2 365: /* The type is determined by applying ?: to each pair. 366: */ 367: /* Still have a problem with: 368: * ubyte[][] = [ cast(ubyte[])"hello", [1]]; 369: * which works if the array literal is initialized top down with the ubyte[][] 370: * type, but fails with this function doing bottom up typing. 371: */ 372: //printf("arrayExpressionToCommonType()\n"); 373: IntegerExp integerexp(0); 374: CondExp condexp(0, &integerexp, NULL, NULL); 375: 376: Type *t0 = NULL; 377: Expression *e0; 378: int j0; 379: for (size_t i = 0; i < exps->dim; i++) 380: { Expression *e = (*exps)[i]; 381: 382: e = resolveProperties(sc, e); 383: if (!e->type) 384: { error("%s has no value", e->toChars()); 385: e = new ErrorExp(); 386: } 387: 388: if (t0) 389: { if (t0 != e->type) 390: { 391: /* This applies ?: to merge the types. It's backwards; 392: * ?: should call this function to merge types. 393: */ 394: condexp.type = NULL; 395: condexp.e1 = e0; 396: condexp.e2 = e; 397: condexp.loc = e->loc; 398: condexp.semantic(sc); 399: (*exps)[j0] = condexp.e1; 400: e = condexp.e2; 401: j0 = i; 402: e0 = e; 403: t0 = e0->type; 404: } 405: } 406: else 407: { j0 = i; 408: e0 = e; 409: t0 = e->type; 410: } 411: (*exps)[i] = e; 412: } 413: 414: if (t0) 415: { 416: for (size_t i = 0; i < exps->dim; i++) 417: { Expression *e = (*exps)[i]; 418: e = e->implicitCastTo(sc, t0); 419: (*exps)[i] = e; 420: } 421: } 422: else 423: t0 = Type::tvoid; // [] is typed as void[] 424: if (pt) 425: *pt = t0; 426: 427: // Eventually, we want to make this copy-on-write 428: return exps; 429: #endif 430: } 431: 432: /**************************************** 433: * Get TemplateDeclaration enclosing FuncDeclaration. 434: */ 435: 436: TemplateDeclaration *getFuncTemplateDecl(Dsymbol *s) 437: { 438: FuncDeclaration *f = s->isFuncDeclaration(); 439: if (f && f->parent) 440: { TemplateInstance *ti = f->parent->isTemplateInstance(); 441: 442: if (ti && 443: !ti->isTemplateMixin() && 444: (ti->name == f->ident || 445: ti->toAlias()->ident == f->ident) 446: && 447: ti->tempdecl && ti->tempdecl->onemember) 448: { 449: return ti->tempdecl; 450: } 451: } 452: return NULL; 453: } 454: 455: /**************************************** 456: * Preprocess arguments to function. 457: */ 458: 459: void preFunctionParameters(Loc loc, Scope *sc, Expressions *exps) 460: { 461: if (exps) 462: { 463: expandTuples(exps); 464: 465: for (size_t i = 0; i < exps->dim; i++) 466: { Expression *arg = (*exps)[i]; 467: 468: if (!arg->type) 469: { 470: #ifdef DEBUG 471: if (!global.gag) 472: printf("1: \n"); 473: #endif 474: arg->error("%s is not an expression", arg->toChars()); 475: arg = new ErrorExp(); 476: } 477: 478: arg = resolveProperties(sc, arg); 479: (*exps)[i] = arg; 480: 481: //arg->rvalue(); 482: #if 0 483: if (arg->type->ty == Tfunction) 484: { 485: arg = new AddrExp(arg->loc, arg); 486: arg = arg->semantic(sc); 487: (*exps)[i] = arg; 488: } 489: #endif 490: } 491: } 492: } 493: 494: /************************************************ 495: * If we want the value of this expression, but do not want to call 496: * the destructor on it. 497: */ 498: 499: void valueNoDtor(Expression *e) 500: { 501: if (e->op == TOKcall) 502: { 503: /* The struct value returned from the function is transferred 504: * so do not call the destructor on it. 505: * Recognize: 506: * ((S _ctmp = S.init), _ctmp).this(...) 507: * and make sure the destructor is not called on _ctmp 508: * BUG: if e is a CommaExp, we should go down the right side. 509: */ 510: CallExp *ce = (CallExp *)e; 511: if (ce->e1->op == TOKdotvar) 512: { DotVarExp *dve = (DotVarExp *)ce->e1; 513: if (dve->var->isCtorDeclaration()) 514: { // It's a constructor call 515: if (dve->e1->op == TOKcomma) 516: { CommaExp *comma = (CommaExp *)dve->e1; 517: if (comma->e2->op == TOKvar) 518: { VarExp *ve = (VarExp *)comma->e2; 519: VarDeclaration *ctmp = ve->var->isVarDeclaration(); 520: if (ctmp) 521: ctmp->noscope = 1; 522: } 523: } 524: } 525: } 526: } 527: } 528: 529: /********************************************* 530: * Call copy constructor for struct value argument. 531: */ 532: #if DMDV2 533: Expression *callCpCtor(Loc loc, Scope *sc, Expression *e, int noscope) 534: { 535: Type *tb = e->type->toBasetype(); 536: assert(tb->ty == Tstruct); 537: StructDeclaration *sd = ((TypeStruct *)tb)->sym; 538: if (sd->cpctor) 539: { 540: /* Create a variable tmp, and replace the argument e with: 541: * (tmp = e),tmp 542: * and let AssignExp() handle the construction. 543: * This is not the most efficent, ideally tmp would be constructed 544: * directly onto the stack. 545: */ 546: Identifier *idtmp = Lexer::uniqueId("__cpcttmp"); 547: VarDeclaration *tmp = new VarDeclaration(loc, tb, idtmp, new ExpInitializer(0, e)); 548: tmp->storage_class |= STCctfe; 549: tmp->noscope = noscope; 550: Expression *ae = new DeclarationExp(loc, tmp); 551: e = new CommaExp(loc, ae, new VarExp(loc, tmp)); 552: e = e->semantic(sc); 553: } 554: return e; 555: } 556: #endif 557: 558: /**************************************** 559: * Now that we know the exact type of the function we're calling, 560: * the arguments[] need to be adjusted: 561: * 1. implicitly convert argument to the corresponding parameter type 562: * 2. add default arguments for any missing arguments 563: * 3. do default promotions on arguments corresponding to ... 564: * 4. add hidden _arguments[] argument 565: * 5. call copy constructor for struct value arguments 566: * Returns: 567: * return type from function 568: */ 569: 570: Type *functionParameters(Loc loc, Scope *sc, TypeFunction *tf, 571: Expressions *arguments, FuncDeclaration *fd) 572: { 573: //printf("functionParameters()\n"); 574: assert(arguments); 575: size_t nargs = arguments ? arguments->dim : 0; 576: size_t nparams = Parameter::dim(tf->parameters); 577: 578: if (nargs > nparams && tf->varargs == 0) 579: error(loc, "expected %"SIZE_T_FORMAT"u arguments, not %"SIZE_T_FORMAT"u for non-variadic function type %s", nparams, nargs, tf->toChars()); 580: 581: unsigned n = (nargs > nparams) ? nargs : nparams; // n = max(nargs, nparams) 582: 583: unsigned wildmatch = 0; 584: int done = 0; 585: for (size_t i = 0; i < n; i++) 586: { 587: Expression *arg; 588: 589: if (i < nargs) 590: arg = arguments->tdata()[i]; 591: else 592: arg = NULL; 593: Type *tb; 594: 595: if (i < nparams) 596: { 597: Parameter *p = Parameter::getNth(tf->parameters, i); 598: 599: if (!arg) 600: { 601: if (!p->defaultArg) 602: { 603: if (tf->varargs == 2 && i + 1 == nparams) 604: goto L2; 605: error(loc, "expected %"SIZE_T_FORMAT"u function arguments, not %"SIZE_T_FORMAT"u", nparams, nargs); 606: return tf->next; 607: } 608: arg = p->defaultArg; 609: arg = arg->inlineCopy(sc); 610: #if DMDV2 611: arg = arg->resolveLoc(loc, sc); // __FILE__ and __LINE__ 612: #endif 613: arguments->push(arg); 614: nargs++; 615: } 616: 617: if (tf->varargs == 2 && i + 1 == nparams) 618: { 619: //printf("\t\tvarargs == 2, p->type = '%s'\n", p->type->toChars()); 620: if (arg->implicitConvTo(p->type)) 621: { 622: if (nargs != nparams) 623: { error(loc, "expected %"SIZE_T_FORMAT"u function arguments, not %"SIZE_T_FORMAT"u", nparams, nargs); 624: return tf->next; 625: } 626: goto L1; 627: } 628: L2: 629: Type *tb = p->type->toBasetype();
warning C6246: Local declaration of 'tb' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '593' of 'c:\projects\extern\d\dmd\src\expression.c': Lines: 593
630: Type *tret = p->isLazyArray(); 631: switch (tb->ty) 632: { 633: case Tsarray: 634: case Tarray: 635: { // Create a static array variable v of type arg->type 636: #ifdef IN_GCC 637: /* GCC 4.0 does not like zero length arrays used like 638: this; pass a null array value instead. Could also 639: just make a one-element array. */ 640: if (nargs - i == 0) 641: { 642: arg = new NullExp(loc); 643: break; 644: } 645: #endif 646: Identifier *id = Lexer::uniqueId("__arrayArg"); 647: Type *t = new TypeSArray(((TypeArray *)tb)->next, new IntegerExp(nargs - i)); 648: t = t->semantic(loc, sc); 649: VarDeclaration *v = new VarDeclaration(loc, t, id, fd->isSafe() ? NULL : new VoidInitializer(loc)); 650: v->storage_class |= STCctfe; 651: v->semantic(sc); 652: v->parent = sc->parent; 653: //sc->insert(v); 654: 655: Expression *c = new DeclarationExp(0, v); 656: c->type = v->type; 657: 658: for (size_t u = i; u < nargs; u++) 659: { Expression *a = arguments->tdata()[u]; 660: if (tret && !((TypeArray *)tb)->next->equals(a->type)) 661: a = a->toDelegate(sc, tret); 662: 663: Expression *e = new VarExp(loc, v); 664: e = new IndexExp(loc, e, new IntegerExp(u + 1 - nparams)); 665: ConstructExp *ae = new ConstructExp(loc, e, a); 666: if (c) 667: c = new CommaExp(loc, c, ae); 668: else 669: c = ae; 670: } 671: arg = new VarExp(loc, v); 672: if (c) 673: arg = new CommaExp(loc, c, arg); 674: break; 675: } 676: case Tclass: 677: { /* Set arg to be: 678: * new Tclass(arg0, arg1, ..., argn) 679: */ 680: Expressions *args = new Expressions(); 681: args->setDim(nargs - i); 682: for (size_t u = i; u < nargs; u++) 683: args->tdata()[u - i] = arguments->tdata()[u]; 684: arg = new NewExp(loc, NULL, NULL, p->type, args); 685: break; 686: } 687: default: 688: if (!arg) 689: { error(loc, "not enough arguments"); 690: return tf->next; 691: } 692: break; 693: } 694: arg = arg->semantic(sc); 695: //printf("\targ = '%s'\n", arg->toChars()); 696: arguments->setDim(i + 1); 697: done = 1; 698: } 699: 700: L1: 701: if (!(p->storageClass & STClazy && p->type->ty == Tvoid)) 702: { 703: if (p->type != arg->type) 704: { 705: //printf("arg->type = %s, p->type = %s\n", arg->type->toChars(), p->type->toChars()); 706: if (arg->op == TOKtype) 707: { arg->error("cannot pass type %s as function argument", arg->toChars()); 708: arg = new ErrorExp(); 709: goto L3; 710: } 711: if (p->type->isWild() && tf->next->isWild()) 712: { Type *t = p->type; 713: MATCH m = arg->implicitConvTo(t); 714: if (m == MATCHnomatch) 715: { t = t->constOf(); 716: m = arg->implicitConvTo(t); 717: if (m == MATCHnomatch) 718: { t = t->sharedConstOf(); 719: m = arg->implicitConvTo(t); 720: } 721: wildmatch |= p->type->wildMatch(arg->type); 722: } 723: arg = arg->implicitCastTo(sc, t); 724: } 725: else 726: arg = arg->implicitCastTo(sc, p->type); 727: arg = arg->optimize(WANTvalue); 728: } 729: } 730: if (p->storageClass & STCref) 731: { 732: arg = arg->toLvalue(sc, arg); 733: } 734: else if (p->storageClass & STCout) 735: { 736: arg = arg->modifiableLvalue(sc, arg); 737: } 738: 739: tb = arg->type->toBasetype(); 740: #if !SARRAYVALUE 741: // Convert static arrays to pointers 742: if (tb->ty == Tsarray) 743: { 744: arg = arg->checkToPointer(); 745: } 746: #endif 747: #if DMDV2 748: if (tb->ty == Tstruct && !(p->storageClass & (STCref | STCout))) 749: { 750: if (arg->op == TOKcall) 751: { 752: /* The struct value returned from the function is transferred 753: * to the function, so the callee should not call the destructor 754: * on it. 755: */ 756: valueNoDtor(arg); 757: } 758: else 759: { /* Not transferring it, so call the copy constructor 760: */ 761: arg = callCpCtor(loc, sc, arg, 1); 762: } 763: } 764: #endif 765: 766: //printf("arg: %s\n", arg->toChars()); 767: //printf("type: %s\n", arg->type->toChars()); 768: 769: // Convert lazy argument to a delegate 770: if (p->storageClass & STClazy) 771: { 772: arg = arg->toDelegate(sc, p->type); 773: } 774: #if DMDV2 775: /* Look for arguments that cannot 'escape' from the called 776: * function. 777: */ 778: if (!tf->parameterEscapes(p)) 779: { 780: /* Function literals can only appear once, so if this 781: * appearance was scoped, there cannot be any others. 782: */ 783: if (arg->op == TOKfunction) 784: { FuncExp *fe = (FuncExp *)arg; 785: fe->fd->tookAddressOf = 0; 786: } 787: 788: /* For passing a delegate to a scoped parameter, 789: * this doesn't count as taking the address of it. 790: * We only worry about 'escaping' references to the function. 791: */ 792: else if (arg->op == TOKdelegate) 793: { DelegateExp *de = (DelegateExp *)arg; 794: if (de->e1->op == TOKvar) 795: { VarExp *ve = (VarExp *)de->e1; 796: FuncDeclaration *f = ve->var->isFuncDeclaration(); 797: if (f) 798: { f->tookAddressOf--; 799: //printf("tookAddressOf = %d\n", f->tookAddressOf); 800: } 801: } 802: } 803: } 804: #endif 805: } 806: else 807: { 808: 809: // If not D linkage, do promotions 810: if (tf->linkage != LINKd) 811: { 812: // Promote bytes, words, etc., to ints 813: arg = arg->integralPromotions(sc); 814: 815: // Promote floats to doubles 816: switch (arg->type->ty) 817: { 818: case Tfloat32: 819: arg = arg->castTo(sc, Type::tfloat64); 820: break; 821: 822: case Timaginary32: 823: arg = arg->castTo(sc, Type::timaginary64); 824: break; 825: } 826: } 827: 828: // Do not allow types that need destructors 829: if (arg->type->needsDestruction()) 830: arg->error("cannot pass types that need destruction as variadic arguments"); 831: 832: // Convert static arrays to dynamic arrays 833: // BUG: I don't think this is right for D2 834: tb = arg->type->toBasetype(); 835: if (tb->ty == Tsarray) 836: { TypeSArray *ts = (TypeSArray *)tb; 837: Type *ta = ts->next->arrayOf(); 838: if (ts->size(arg->loc) == 0) 839: arg = new NullExp(arg->loc, ta); 840: else 841: arg = arg->castTo(sc, ta); 842: } 843: #if DMDV2 844: if (tb->ty == Tstruct) 845: { 846: arg = callCpCtor(loc, sc, arg, 1); 847: } 848: #endif 849: 850: // Give error for overloaded function addresses 851: if (arg->op == TOKsymoff) 852: { SymOffExp *se = (SymOffExp *)arg; 853: if ( 854: #if DMDV2 855: se->hasOverloads && 856: #endif 857: !se->var->isFuncDeclaration()->isUnique()) 858: arg->error("function %s is overloaded", arg->toChars()); 859: } 860: arg->rvalue(); 861: } 862: arg = arg->optimize(WANTvalue); 863: L3: 864: arguments->tdata()[i] = arg; 865: if (done) 866: break; 867: } 868: 869: // If D linkage and variadic, add _arguments[] as first argument 870: if (tf->linkage == LINKd && tf->varargs == 1) 871: { 872: assert(arguments->dim >= nparams); 873: Expression *e = createTypeInfoArray(sc, (Expression **)&arguments->tdata()[nparams], 874: arguments->dim - nparams); 875: arguments->insert(0, e); 876: } 877: 878: // If inferring return type, and semantic3() needs to be run if not already run 879: if (!tf->next && fd->inferRetType) 880: fd->semantic3(fd->scope); 881: 882: Type *tret = tf->next; 883: if (wildmatch) 884: { /* Adjust function return type based on wildmatch 885: */ 886: //printf("wildmatch = x%x\n", wildmatch); 887: assert(tret->isWild()); 888: if (wildmatch & MODconst || wildmatch & (wildmatch - 1)) 889: tret = tret->constOf(); 890: else if (wildmatch & MODimmutable) 891: tret = tret->invariantOf(); 892: else 893: { assert(wildmatch & MODmutable); 894: tret = tret->mutableOf(); 895: } 896: } 897: return tret; 898: } 899: 900: /************************************************** 901: * Write expression out to buf, but wrap it 902: * in ( ) if its precedence is less than pr. 903: */ 904: 905: void expToCBuffer(OutBuffer *buf, HdrGenState *hgs, Expression *e, enum PREC pr) 906: { 907: #ifdef DEBUG 908: if (precedence[e->op] == PREC_zero) 909: printf("precedence not defined for token '%s'\n",Token::tochars[e->op]); 910: #endif 911: assert(precedence[e->op] != PREC_zero); 912: assert(pr != PREC_zero); 913: 914: //if (precedence[e->op] == 0) e->dump(0); 915: if (precedence[e->op] < pr || 916: /* Despite precedence, we don't allow a<b<c expressions. 917: * They must be parenthesized. 918: */ 919: (pr == PREC_rel && precedence[e->op] == pr)) 920: { 921: buf->writeByte('('); 922: e->toCBuffer(buf, hgs); 923: buf->writeByte(')'); 924: } 925: else 926: e->toCBuffer(buf, hgs); 927: } 928: 929: /************************************************** 930: * Write out argument list to buf. 931: */ 932: 933: void argsToCBuffer(OutBuffer *buf, Expressions *arguments, HdrGenState *hgs) 934: { 935: if (arguments) 936: { 937: for (size_t i = 0; i < arguments->dim; i++) 938: { Expression *arg = arguments->tdata()[i]; 939: 940: if (arg) 941: { if (i) 942: buf->writeByte(','); 943: expToCBuffer(buf, hgs, arg, PREC_assign); 944: } 945: } 946: } 947: } 948: 949: /************************************************** 950: * Write out argument types to buf. 951: */ 952: 953: void argExpTypesToCBuffer(OutBuffer *buf, Expressions *arguments, HdrGenState *hgs) 954: { 955: if (arguments) 956: { OutBuffer argbuf; 957: 958: for (size_t i = 0; i < arguments->dim; i++) 959: { Expression *arg = arguments->tdata()[i]; 960: 961: if (i) 962: buf->writeByte(','); 963: argbuf.reset(); 964: arg->type->toCBuffer2(&argbuf, hgs, 0); 965: buf->write(&argbuf); 966: } 967: } 968: } 969: 970: /******************************** Expression **************************/ 971: 972: Expression::Expression(Loc loc, enum TOK op, int size) 973: : loc(loc) 974: { 975: //printf("Expression::Expression(op = %d) this = %p\n", op, this); 976: this->loc = loc; 977: this->op = op; 978: this->size = size; 979: this->parens = 0; 980: type = NULL; 981: } 982: 983: Expression *Expression::syntaxCopy() 984: { 985: //printf("Expression::syntaxCopy()\n"); 986: //dump(0); 987: return copy(); 988: } 989: 990: /********************************* 991: * Does *not* do a deep copy. 992: */ 993: 994: Expression *Expression::copy() 995: { 996: Expression *e; 997: if (!size) 998: { 999: #ifdef DEBUG 1000: fprintf(stdmsg, "No expression copy for: %s\n", toChars()); 1001: printf("op = %d\n", op); 1002: dump(0); 1003: #endif 1004: assert(0); 1005: } 1006: e = (Expression *)mem.malloc(size); 1007: //printf("Expression::copy(op = %d) e = %p\n", op, e); 1008: return (Expression *)memcpy(e, this, size); 1009: } 1010: 1011: /************************** 1012: * Semantically analyze Expression. 1013: * Determine types, fold constants, etc. 1014: */ 1015: 1016: Expression *Expression::semantic(Scope *sc) 1017: { 1018: #if LOGSEMANTIC 1019: printf("Expression::semantic() %s\n", toChars()); 1020: #endif 1021: if (type) 1022: type = type->semantic(loc, sc); 1023: else 1024: type = Type::tvoid; 1025: return this; 1026: } 1027: 1028: /********************************** 1029: * Try to run semantic routines. 1030: * If they fail, return NULL. 1031: */ 1032: 1033: Expression *Expression::trySemantic(Scope *sc) 1034: { 1035: //printf("+trySemantic(%s)\n", toChars()); 1036: unsigned errors = global.errors; 1037: global.gag++; 1038: Expression *e = semantic(sc); 1039: global.gag--; 1040: if (errors != global.errors) 1041: { 1042: global.errors = errors; 1043: e = NULL; 1044: } 1045: //printf("-trySemantic(%s)\n", toChars()); 1046: return e; 1047: } 1048: 1049: void Expression::print() 1050: { 1051: fprintf(stdmsg, "%s\n", toChars()); 1052: fflush(stdmsg); 1053: } 1054: 1055: char *Expression::toChars() 1056: { OutBuffer *buf; 1057: HdrGenState hgs; 1058: 1059: memset(&hgs, 0, sizeof(hgs)); 1060: buf = new OutBuffer(); 1061: toCBuffer(buf, &hgs); 1062: return buf->toChars(); 1063: } 1064: 1065: void Expression::error(const char *format, ...) 1066: { 1067: if (type != Type::terror) 1068: { 1069: va_list ap; 1070: va_start(ap, format); 1071: ::verror(loc, format, ap); 1072: va_end( ap ); 1073: } 1074: } 1075: 1076: void Expression::warning(const char *format, ...) 1077: { 1078: if (type != Type::terror) 1079: { 1080: va_list ap; 1081: va_start(ap, format); 1082: ::vwarning(loc, format, ap); 1083: va_end( ap ); 1084: } 1085: } 1086: 1087: void Expression::rvalue() 1088: { 1089: if (type && type->toBasetype()->ty == Tvoid) 1090: { error("expression %s is void and has no value", toChars()); 1091: #if 0 1092: dump(0); 1093: halt(); 1094: #endif 1095: type = Type::terror; 1096: } 1097: } 1098: 1099: Expression *Expression::combine(Expression *e1, Expression *e2) 1100: { 1101: if (e1) 1102: { 1103: if (e2) 1104: { 1105: e1 = new CommaExp(e1->loc, e1, e2); 1106: e1->type = e2->type; 1107: } 1108: } 1109: else 1110: e1 = e2; 1111: return e1; 1112: } 1113: 1114: dinteger_t Expression::toInteger() 1115: { 1116: //printf("Expression %s\n", Token::toChars(op)); 1117: error("Integer constant expression expected instead of %s", toChars()); 1118: return 0; 1119: } 1120: 1121: uinteger_t Expression::toUInteger() 1122: { 1123: //printf("Expression %s\n", Token::toChars(op)); 1124: return (uinteger_t)toInteger(); 1125: } 1126: 1127: real_t Expression::toReal() 1128: { 1129: error("Floating point constant expression expected instead of %s", toChars()); 1130: return 0; 1131: } 1132: 1133: real_t Expression::toImaginary() 1134: { 1135: error("Floating point constant expression expected instead of %s", toChars()); 1136: return 0; 1137: } 1138: 1139: complex_t Expression::toComplex() 1140: { 1141: error("Floating point constant expression expected instead of %s", toChars()); 1142: #ifdef IN_GCC 1143: return complex_t(real_t(0)); // %% nicer 1144: #else 1145: return 0; 1146: #endif 1147: } 1148: 1149: void Expression::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 1150: { 1151: buf->writestring(Token::toChars(op)); 1152: } 1153: 1154: void Expression::toMangleBuffer(OutBuffer *buf) 1155: { 1156: error("expression %s is not a valid template value argument", toChars()); 1157: #ifdef DEBUG 1158: dump(0); 1159: #endif 1160: } 1161: 1162: /*************************************** 1163: * Return !=0 if expression is an lvalue. 1164: */ 1165: #if DMDV2 1166: int Expression::isLvalue() 1167: { 1168: return 0; 1169: } 1170: #endif 1171: 1172: /******************************* 1173: * Give error if we're not an lvalue. 1174: * If we can, convert expression to be an lvalue. 1175: */ 1176: 1177: Expression *Expression::toLvalue(Scope *sc, Expression *e) 1178: { 1179: if (!e) 1180: e = this; 1181: else if (!loc.filename) 1182: loc = e->loc; 1183: error("%s is not an lvalue", e->toChars()); 1184: return this; 1185: } 1186: 1187: Expression *Expression::modifiableLvalue(Scope *sc, Expression *e) 1188: { 1189: //printf("Expression::modifiableLvalue() %s, type = %s\n", toChars(), type->toChars()); 1190: 1191: // See if this expression is a modifiable lvalue (i.e. not const) 1192: #if DMDV2 1193: if (type && (!type->isMutable() || !type->isAssignable())) 1194: error("%s is not mutable", e->toChars()); 1195: #endif 1196: return toLvalue(sc, e); 1197: } 1198: 1199: /************************************ 1200: * Detect cases where pointers to the stack can 'escape' the 1201: * lifetime of the stack frame. 1202: */ 1203: 1204: void Expression::checkEscape() 1205: { 1206: } 1207: 1208: void Expression::checkEscapeRef() 1209: { 1210: } 1211: 1212: void Expression::checkScalar() 1213: { 1214: if (!type->isscalar() && type->toBasetype() != Type::terror) 1215: error("'%s' is not a scalar, it is a %s", toChars(), type->toChars()); 1216: rvalue(); 1217: } 1218: 1219: void Expression::checkNoBool() 1220: { 1221: if (type->toBasetype()->ty == Tbool) 1222: error("operation not allowed on bool '%s'", toChars()); 1223: } 1224: 1225: Expression *Expression::checkIntegral() 1226: { 1227: if (!type->isintegral()) 1228: { if (type->toBasetype() != Type::terror) 1229: error("'%s' is not of integral type, it is a %s", toChars(), type->toChars()); 1230: return new ErrorExp(); 1231: } 1232: rvalue(); 1233: return this; 1234: } 1235: 1236: Expression *Expression::checkArithmetic() 1237: { 1238: if (!type->isintegral() && !type->isfloating()) 1239: { if (type->toBasetype() != Type::terror) 1240: error("'%s' is not of arithmetic type, it is a %s", toChars(), type->toChars()); 1241: return new ErrorExp(); 1242: } 1243: rvalue(); 1244: return this; 1245: } 1246: 1247: void Expression::checkDeprecated(Scope *sc, Dsymbol *s) 1248: { 1249: s->checkDeprecated(loc, sc); 1250: } 1251: 1252: #if DMDV2 1253: /********************************************* 1254: * Calling function f. 1255: * Check the purity, i.e. if we're in a pure function 1256: * we can only call other pure functions. 1257: */ 1258: void Expression::checkPurity(Scope *sc, FuncDeclaration *f) 1259: { 1260: #if 1 1261: if (sc->func) 1262: { 1263: /* Given: 1264: * void f() 1265: * { pure void g() 1266: * { 1267: * void h() 1268: * { 1269: * void i() { } 1270: * } 1271: * } 1272: * } 1273: * g() can call h() but not f() 1274: * i() can call h() and g() but not f() 1275: */ 1276: FuncDeclaration *outerfunc = sc->func; 1277: // Find the closest pure parent of the calling function 1278: while (outerfunc->toParent2() && 1279: !outerfunc->isPure() && 1280: outerfunc->toParent2()->isFuncDeclaration()) 1281: { 1282: outerfunc = outerfunc->toParent2()->isFuncDeclaration(); 1283: } 1284: // Find the closest pure parent of the called function 1285: FuncDeclaration *calledparent = f; 1286: while (calledparent->toParent2() && !calledparent->isPure() 1287: && calledparent->toParent2()->isFuncDeclaration() ) 1288: { 1289: calledparent = calledparent->toParent2()->isFuncDeclaration(); 1290: } 1291: // If the caller has a pure parent, then either the called func must be pure, 1292: // OR, they must have the same pure parent. 1293: if (/*outerfunc->isPure() &&*/ // comment out because we deduce purity now 1294: !sc->intypeof && 1295: !(sc->flags & SCOPEdebug) && 1296: !(f->isPure() || (calledparent == outerfunc))) 1297: { 1298: if (outerfunc->setImpure()) 1299: error("pure function '%s' cannot call impure function '%s'", 1300: outerfunc->toChars(), f->toChars()); 1301: } 1302: } 1303: #else 1304: if (sc->func && sc->func->isPure() && !sc->intypeof && !f->isPure()) 1305: error("pure function '%s' cannot call impure function '%s'", 1306: sc->func->toChars(), f->toChars()); 1307: #endif 1308: } 1309: 1310: /******************************************* 1311: * Accessing variable v. 1312: * Check for purity and safety violations. 1313: * If ethis is not NULL, then ethis is the 'this' pointer as in ethis.v 1314: */ 1315: 1316: void Expression::checkPurity(Scope *sc, VarDeclaration *v, Expression *ethis) 1317: { 1318: /* Look for purity and safety violations when accessing variable v 1319: * from current function. 1320: */ 1321: if (sc->func && 1322: !sc->intypeof && // allow violations inside typeof(expression) 1323: !(sc->flags & SCOPEdebug) && // allow violations inside debug conditionals 1324: v->ident != Id::ctfe && // magic variable never violates pure and safe 1325: !v->isImmutable() && // always safe and pure to access immutables... 1326: !(v->isConst() && v->isDataseg() && !v->type->hasPointers()) && // const global value types are immutable 1327: !(v->storage_class & STCmanifest) // ...or manifest constants 1328: ) 1329: { 1330: if (v->isDataseg()) 1331: { 1332: /* Accessing global mutable state. 1333: * Therefore, this function and all its immediately enclosing 1334: * functions must be pure. 1335: */ 1336: bool msg = FALSE; 1337: for (Dsymbol *s = sc->func; s; s = s->toParent2()) 1338: { 1339: FuncDeclaration *ff = s->isFuncDeclaration(); 1340: if (!ff) 1341: break; 1342: if (ff->setImpure() && !msg) 1343: { error("pure function '%s' cannot access mutable static data '%s'", 1344: sc->func->toChars(), v->toChars()); 1345: msg = TRUE; // only need the innermost message 1346: } 1347: } 1348: } 1349: else 1350: { 1351: /* Given: 1352: * void f() 1353: * { int fx; 1354: * pure void g() 1355: * { int gx; 1356: * void h() 1357: * { int hx; 1358: * void i() { } 1359: * } 1360: * } 1361: * } 1362: * i() can modify hx and gx but not fx 1363: */ 1364: 1365: Dsymbol *vparent = v->toParent2(); 1366: for (Dsymbol *s = sc->func; s; s = s->toParent2()) 1367: { 1368: if (s == vparent) 1369: break; 1370: FuncDeclaration *ff = s->isFuncDeclaration(); 1371: if (!ff) 1372: break; 1373: if (ff->setImpure()) 1374: { error("pure nested function '%s' cannot access mutable data '%s'", 1375: ff->toChars(), v->toChars()); 1376: break; 1377: } 1378: } 1379: } 1380: 1381: /* Do not allow safe functions to access __gshared data 1382: */ 1383: if (v->storage_class & STCgshared) 1384: { 1385: if (sc->func->setUnsafe()) 1386: error("safe function '%s' cannot access __gshared data '%s'", 1387: sc->func->toChars(), v->toChars()); 1388: } 1389: 1390: L1: ;
warning C4102: 'L1' : unreferenced label
1391: } 1392: } 1393: 1394: void Expression::checkSafety(Scope *sc, FuncDeclaration *f) 1395: { 1396: if (sc->func && !sc->intypeof && 1397: !f->isSafe() && !f->isTrusted()) 1398: { 1399: if (sc->func->setUnsafe()) 1400: error("safe function '%s' cannot call system function '%s'", 1401: sc->func->toChars(), f->toChars()); 1402: } 1403: } 1404: #endif 1405: 1406: /******************************** 1407: * Check for expressions that have no use. 1408: * Input: 1409: * flag 0 not going to use the result, so issue error message if no 1410: * side effects 1411: * 1 the result of the expression is used, but still check 1412: * for useless subexpressions 1413: * 2 do not issue error messages, just return !=0 if expression 1414: * has side effects 1415: */ 1416: 1417: int Expression::checkSideEffect(int flag) 1418: { 1419: if (flag == 0) 1420: { 1421: if (op == TOKerror) 1422: { // Error should have already been printed 1423: } 1424: else if (op == TOKimport) 1425: { 1426: error("%s has no effect", toChars()); 1427: } 1428: else 1429: error("%s has no effect in expression (%s)", 1430: Token::toChars(op), toChars()); 1431: } 1432: return 0; 1433: } 1434: 1435: /***************************** 1436: * Check that expression can be tested for true or false. 1437: */ 1438: 1439: Expression *Expression::checkToBoolean(Scope *sc) 1440: { 1441: // Default is 'yes' - do nothing 1442: 1443: #ifdef DEBUG 1444: if (!type) 1445: dump(0); 1446: #endif 1447: 1448: // Structs can be converted to bool using opCast(bool)() 1449: Type *tb = type->toBasetype(); 1450: if (tb->ty == Tstruct) 1451: { AggregateDeclaration *ad = ((TypeStruct *)tb)->sym; 1452: /* Don't really need to check for opCast first, but by doing so we 1453: * get better error messages if it isn't there. 1454: */ 1455: Dsymbol *fd = search_function(ad, Id::cast); 1456: if (fd) 1457: { 1458: Expression *e = new CastExp(loc, this, Type::tbool); 1459: e = e->semantic(sc); 1460: return e; 1461: } 1462: 1463: // Forward to aliasthis. 1464: if (ad->aliasthis) 1465: { 1466: Expression *e = new DotIdExp(loc, this, ad->aliasthis->ident); 1467: e = e->semantic(sc); 1468: e = resolveProperties(sc, e); 1469: e = e->checkToBoolean(sc); 1470: return e; 1471: } 1472: } 1473: 1474: if (!type->checkBoolean()) 1475: { if (type->toBasetype() != Type::terror) 1476: error("expression %s of type %s does not have a boolean value", toChars(), type->toChars()); 1477: return new ErrorExp(); 1478: } 1479: return this; 1480: } 1481: 1482: /**************************** 1483: */ 1484: 1485: Expression *Expression::checkToPointer() 1486: { 1487: //printf("Expression::checkToPointer()\n"); 1488: Expression *e = this; 1489: 1490: #if !SARRAYVALUE 1491: // If C static array, convert to pointer 1492: Type *tb = type->toBasetype(); 1493: if (tb->ty == Tsarray) 1494: { TypeSArray *ts = (TypeSArray *)tb; 1495: if (ts->size(loc) == 0) 1496: e = new NullExp(loc); 1497: else 1498: e = new AddrExp(loc, this); 1499: e->type = ts->next->pointerTo(); 1500: } 1501: #endif 1502: return e; 1503: } 1504: 1505: /****************************** 1506: * Take address of expression. 1507: */ 1508: 1509: Expression *Expression::addressOf(Scope *sc) 1510: { 1511: Expression *e; 1512: 1513: //printf("Expression::addressOf()\n"); 1514: e = toLvalue(sc, NULL); 1515: e = new AddrExp(loc, e); 1516: e->type = type->pointerTo(); 1517: return e; 1518: } 1519: 1520: /****************************** 1521: * If this is a reference, dereference it. 1522: */ 1523: 1524: Expression *Expression::deref() 1525: { 1526: //printf("Expression::deref()\n"); 1527: // type could be null if forward referencing an 'auto' variable 1528: if (type && type->ty == Treference) 1529: { 1530: Expression *e = new PtrExp(loc, this); 1531: e->type = ((TypeReference *)type)->next; 1532: return e; 1533: } 1534: return this; 1535: } 1536: 1537: /******************************** 1538: * Does this expression statically evaluate to a boolean TRUE or FALSE? 1539: */ 1540: 1541: int Expression::isBool(int result) 1542: { 1543: return FALSE; 1544: } 1545: 1546: /******************************** 1547: * Does this expression result in either a 1 or a 0? 1548: */ 1549: 1550: int Expression::isBit() 1551: { 1552: return FALSE; 1553: } 1554: 1555: /******************************** 1556: * Can this expression throw an exception? 1557: * Valid only after semantic() pass. 1558: * 1559: * If 'mustNotThrow' is true, generate an error if it throws 1560: */ 1561: 1562: int Expression::canThrow(bool mustNotThrow) 1563: { 1564: #if DMDV2 1565: return FALSE; 1566: #else 1567: return TRUE; 1568: #endif 1569: } 1570: 1571: /**************************************** 1572: * Resolve __LINE__ and __FILE__ to loc. 1573: */ 1574: 1575: Expression *Expression::resolveLoc(Loc loc, Scope *sc) 1576: { 1577: return this; 1578: } 1579: 1580: Expressions *Expression::arraySyntaxCopy(Expressions *exps) 1581: { Expressions *a = NULL; 1582: 1583: if (exps) 1584: { 1585: a = new Expressions(); 1586: a->setDim(exps->dim); 1587: for (int i = 0; i < a->dim; i++)
warning C4018: '<' : signed/unsigned mismatch
1588: { Expression *e = (*exps)[i]; 1589: 1590: if (e) 1591: e = e->syntaxCopy(); 1592: a->tdata()[i] = e; 1593: } 1594: } 1595: return a; 1596: } 1597: 1598: /*************************************************** 1599: * Recognize expressions of the form: 1600: * ((T v = init), v) 1601: * where v is a temp. 1602: * This is used in optimizing out unnecessary temporary generation. 1603: * Returns initializer expression of v if so, NULL if not. 1604: */ 1605: 1606: Expression *Expression::isTemp() 1607: { 1608: //printf("isTemp() %s\n", toChars()); 1609: if (op == TOKcomma) 1610: { CommaExp *ec = (CommaExp *)this; 1611: if (ec->e1->op == TOKdeclaration && 1612: ec->e2->op == TOKvar) 1613: { DeclarationExp *de = (DeclarationExp *)ec->e1; 1614: VarExp *ve = (VarExp *)ec->e2; 1615: if (ve->var == de->declaration && ve->var->storage_class & STCctfe) 1616: { VarDeclaration *v = ve->var->isVarDeclaration(); 1617: if (v && v->init) 1618: { 1619: ExpInitializer *ei = v->init->isExpInitializer(); 1620: if (ei) 1621: { Expression *e = ei->exp; 1622: if (e->op == TOKconstruct) 1623: { ConstructExp *ce = (ConstructExp *)e; 1624: if (ce->e1->op == TOKvar && ((VarExp *)ce->e1)->var == ve->var) 1625: e = ce->e2; 1626: } 1627: return e; 1628: } 1629: } 1630: } 1631: } 1632: } 1633: return NULL; 1634: } 1635: 1636: /************************************************ 1637: * Destructors are attached to VarDeclarations. 1638: * Hence, if expression returns a temp that needs a destructor, 1639: * make sure and create a VarDeclaration for that temp. 1640: */ 1641: 1642: Expression *Expression::addDtorHook(Scope *sc) 1643: { 1644: return this; 1645: } 1646: 1647: /******************************** IntegerExp **************************/ 1648: 1649: IntegerExp::IntegerExp(Loc loc, dinteger_t value, Type *type) 1650: : Expression(loc, TOKint64, sizeof(IntegerExp)) 1651: { 1652: //printf("IntegerExp(value = %lld, type = '%s')\n", value, type ? type->toChars() : ""); 1653: if (type && !type->isscalar()) 1654: { 1655: //printf("%s, loc = %d\n", toChars(), loc.linnum); 1656: if (type->ty != Terror) 1657: error("integral constant must be scalar type, not %s", type->toChars()); 1658: type = Type::terror; 1659: } 1660: this->type = type; 1661: this->value = value; 1662: } 1663: 1664: IntegerExp::IntegerExp(dinteger_t value) 1665: : Expression(0, TOKint64, sizeof(IntegerExp)) 1666: { 1667: this->type = Type::tint32; 1668: this->value = value; 1669: } 1670: 1671: int IntegerExp::equals(Object *o) 1672: { IntegerExp *ne; 1673: 1674: if (this == o || 1675: (((Expression *)o)->op == TOKint64 && 1676: ((ne = (IntegerExp *)o), type->toHeadMutable()->equals(ne->type->toHeadMutable())) && 1677: value == ne->value)) 1678: return 1; 1679: return 0; 1680: } 1681: 1682: char *IntegerExp::toChars() 1683: { 1684: #if 1 1685: return Expression::toChars(); 1686: #else 1687: static char buffer[sizeof(value) * 3 + 1]; 1688: 1689: sprintf(buffer, "%jd", value); 1690: return buffer; 1691: #endif 1692: } 1693: 1694: dinteger_t IntegerExp::toInteger() 1695: { Type *t; 1696: 1697: t = type; 1698: while (t) 1699: { 1700: switch (t->ty) 1701: { 1702: case Tbool: value = (value != 0); break; 1703: case Tint8: value = (d_int8) value; break; 1704: case Tchar: 1705: case Tuns8: value = (d_uns8) value; break; 1706: case Tint16: value = (d_int16) value; break; 1707: case Twchar: 1708: case Tuns16: value = (d_uns16) value; break; 1709: case Tint32: value = (d_int32) value; break; 1710: case Tdchar: 1711: case Tuns32: value = (d_uns32) value; break; 1712: case Tint64: value = (d_int64) value; break; 1713: case Tuns64: value = (d_uns64) value; break; 1714: case Tpointer: 1715: if (PTRSIZE == 4) 1716: value = (d_uns32) value; 1717: else if (PTRSIZE == 8) 1718: value = (d_uns64) value; 1719: else 1720: assert(0); 1721: break; 1722: 1723: case Tenum: 1724: { 1725: TypeEnum *te = (TypeEnum *)t; 1726: t = te->sym->memtype; 1727: continue; 1728: } 1729: 1730: case Ttypedef: 1731: { 1732: TypeTypedef *tt = (TypeTypedef *)t; 1733: t = tt->sym->basetype; 1734: continue; 1735: } 1736: 1737: default: 1738: /* This can happen if errors, such as 1739: * the type is painted on like in fromConstInitializer(). 1740: */ 1741: if (!global.errors) 1742: { 1743: printf("e = %p, ty = %d\n", this, type->ty); 1744: type->print(); 1745: assert(0); 1746: } 1747: break; 1748: } 1749: break; 1750: } 1751: return value; 1752: } 1753: 1754: real_t IntegerExp::toReal() 1755: { 1756: Type *t; 1757: 1758: toInteger(); 1759: t = type->toBasetype(); 1760: if (t->ty == Tuns64) 1761: return (real_t)(d_uns64)value; 1762: else 1763: return (real_t)(d_int64)value; 1764: } 1765: 1766: real_t IntegerExp::toImaginary() 1767: { 1768: return (real_t) 0; 1769: } 1770: 1771: complex_t IntegerExp::toComplex() 1772: { 1773: return toReal(); 1774: } 1775: 1776: int IntegerExp::isBool(int result) 1777: { 1778: int r = toInteger() != 0; 1779: return result ? r : !r; 1780: } 1781: 1782: Expression *IntegerExp::semantic(Scope *sc) 1783: { 1784: if (!type) 1785: { 1786: // Determine what the type of this number is 1787: dinteger_t number = value; 1788: 1789: if (number & 0x8000000000000000LL) 1790: type = Type::tuns64; 1791: else if (number & 0xFFFFFFFF80000000LL) 1792: type = Type::tint64; 1793: else 1794: type = Type::tint32; 1795: } 1796: else 1797: { if (!type->deco) 1798: type = type->semantic(loc, sc); 1799: } 1800: return this; 1801: } 1802: 1803: Expression *IntegerExp::toLvalue(Scope *sc, Expression *e) 1804: { 1805: if (!e) 1806: e = this; 1807: else if (!loc.filename) 1808: loc = e->loc; 1809: e->error("constant %s is not an lvalue", e->toChars()); 1810: return this; 1811: } 1812: 1813: void IntegerExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 1814: { 1815: dinteger_t v = toInteger(); 1816: 1817: if (type) 1818: { Type *t = type; 1819: 1820: L1: 1821: switch (t->ty) 1822: { 1823: case Tenum: 1824: { TypeEnum *te = (TypeEnum *)t; 1825: buf->printf("cast(%s)", te->sym->toChars()); 1826: t = te->sym->memtype; 1827: goto L1; 1828: } 1829: 1830: case Ttypedef: 1831: { TypeTypedef *tt = (TypeTypedef *)t; 1832: buf->printf("cast(%s)", tt->sym->toChars()); 1833: t = tt->sym->basetype; 1834: goto L1; 1835: } 1836: 1837: case Twchar: // BUG: need to cast(wchar) 1838: case Tdchar: // BUG: need to cast(dchar) 1839: if ((uinteger_t)v > 0xFF) 1840: { 1841: buf->printf("'\\U%08x'", v); 1842: break; 1843: } 1844: case Tchar: 1845: { 1846: unsigned o = buf->offset; 1847: if (v == '\'') 1848: buf->writestring("'\\''"); 1849: else if (isprint(v) && v != '\\')
warning C4244: 'argument' : conversion from 'dinteger_t' to 'int', possible loss of data
1850: buf->printf("'%c'", (int)v); 1851: else 1852: buf->printf("'\\x%02x'", (int)v); 1853: if (hgs->ddoc) 1854: escapeDdocString(buf, o); 1855: break; 1856: } 1857: 1858: case Tint8: 1859: buf->writestring("cast(byte)"); 1860: goto L2; 1861: 1862: case Tint16: 1863: buf->writestring("cast(short)"); 1864: goto L2; 1865: 1866: case Tint32: 1867: L2: 1868: buf->printf("%d", (int)v); 1869: break; 1870: 1871: case Tuns8: 1872: buf->writestring("cast(ubyte)"); 1873: goto L3; 1874: 1875: case Tuns16: 1876: buf->writestring("cast(ushort)"); 1877: goto L3; 1878: 1879: case Tuns32: 1880: L3: 1881: buf->printf("%du", (unsigned)v); 1882: break; 1883: 1884: case Tint64: 1885: buf->printf("%jdL", v); 1886: break; 1887: 1888: case Tuns64: 1889: L4: 1890: buf->printf("%juLU", v); 1891: break; 1892: 1893: case Tbool: 1894: buf->writestring((char *)(v ? "true" : "false")); 1895: break; 1896: 1897: case Tpointer: 1898: buf->writestring("cast("); 1899: buf->writestring(t->toChars()); 1900: buf->writeByte(')'); 1901: if (PTRSIZE == 4) 1902: goto L3; 1903: else if (PTRSIZE == 8) 1904: goto L4; 1905: else 1906: assert(0); 1907: 1908: default: 1909: /* This can happen if errors, such as 1910: * the type is painted on like in fromConstInitializer(). 1911: */ 1912: if (!global.errors) 1913: { 1914: #ifdef DEBUG 1915: t->print(); 1916: #endif 1917: assert(0); 1918: } 1919: break; 1920: } 1921: } 1922: else if (v & 0x8000000000000000LL) 1923: buf->printf("0x%jx", v); 1924: else 1925: buf->printf("%jd", v); 1926: } 1927: 1928: void IntegerExp::toMangleBuffer(OutBuffer *buf) 1929: { 1930: if ((sinteger_t)value < 0) 1931: buf->printf("N%jd", -value);
warning C4146: unary minus operator applied to unsigned type, result still unsigned
1932: else 1933: { 1934: /* This is an awful hack to maintain backwards compatibility. 1935: * There really always should be an 'i' before a number, but 1936: * there wasn't in earlier implementations, so to maintain 1937: * backwards compatibility it is only done if necessary to disambiguate. 1938: * See bugzilla 3029 1939: */ 1940: if (buf->offset > 0 && isdigit(buf->data[buf->offset - 1])) 1941: buf->writeByte('i'); 1942: 1943: buf->printf("%jd", value); 1944: } 1945: } 1946: 1947: /******************************** ErrorExp **************************/ 1948: 1949: /* Use this expression for error recovery. 1950: * It should behave as a 'sink' to prevent further cascaded error messages. 1951: */ 1952: 1953: ErrorExp::ErrorExp() 1954: : IntegerExp(0, 0, Type::terror) 1955: { 1956: op = TOKerror; 1957: } 1958: 1959: Expression *ErrorExp::toLvalue(Scope *sc, Expression *e) 1960: { 1961: return this; 1962: } 1963: 1964: void ErrorExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 1965: { 1966: buf->writestring("__error"); 1967: } 1968: 1969: /******************************** RealExp **************************/ 1970: 1971: RealExp::RealExp(Loc loc, real_t value, Type *type) 1972: : Expression(loc, TOKfloat64, sizeof(RealExp)) 1973: { 1974: //printf("RealExp::RealExp(%Lg)\n", value); 1975: this->value = value; 1976: this->type = type; 1977: } 1978: 1979: char *RealExp::toChars() 1980: { 1981: char buffer[sizeof(value) * 3 + 8 + 1 + 1]; 1982: 1983: #ifdef IN_GCC 1984: value.format(buffer, sizeof(buffer)); 1985: if (type->isimaginary()) 1986: strcat(buffer, "i"); 1987: #else 1988: sprintf(buffer, type->isimaginary() ? "%Lgi" : "%Lg", value);
warning C4996: 'sprintf': This function or variable may be unsafe. Consider using sprintf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details. c:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\stdio.h(371) : see declaration of 'sprintf'
1989: #endif 1990: assert(strlen(buffer) < sizeof(buffer)); 1991: return mem.strdup(buffer); 1992: } 1993: 1994: dinteger_t RealExp::toInteger() 1995: { 1996: #ifdef IN_GCC 1997: return toReal().toInt(); 1998: #else 1999: return (sinteger_t) toReal(); 2000: #endif 2001: } 2002: 2003: uinteger_t RealExp::toUInteger() 2004: { 2005: #ifdef IN_GCC 2006: return (uinteger_t) toReal().toInt(); 2007: #else 2008: return (uinteger_t) toReal(); 2009: #endif 2010: } 2011: 2012: real_t RealExp::toReal() 2013: { 2014: return type->isreal() ? value : 0; 2015: } 2016: 2017: real_t RealExp::toImaginary() 2018: { 2019: return type->isreal() ? 0 : value; 2020: } 2021: 2022: complex_t RealExp::toComplex() 2023: { 2024: #ifdef __DMC__ 2025: return toReal() + toImaginary() * I; 2026: #else 2027: return complex_t(toReal(), toImaginary()); 2028: #endif 2029: } 2030: 2031: /******************************** 2032: * Test to see if two reals are the same. 2033: * Regard NaN's as equivalent. 2034: * Regard +0 and -0 as different. 2035: */ 2036: 2037: int RealEquals(real_t x1, real_t x2) 2038: { 2039: return (Port::isNan(x1) && Port::isNan(x2)) || 2040: /* In some cases, the REALPAD bytes get garbage in them, 2041: * so be sure and ignore them. 2042: */ 2043: memcmp(&x1, &x2, REALSIZE - REALPAD) == 0; 2044: } 2045: 2046: int RealExp::equals(Object *o) 2047: { RealExp *ne; 2048: 2049: if (this == o || 2050: (((Expression *)o)->op == TOKfloat64 && 2051: ((ne = (RealExp *)o), type->toHeadMutable()->equals(ne->type->toHeadMutable())) && 2052: RealEquals(value, ne->value) 2053: ) 2054: ) 2055: return 1; 2056: return 0; 2057: } 2058: 2059: Expression *RealExp::semantic(Scope *sc) 2060: { 2061: if (!type) 2062: type = Type::tfloat64; 2063: else 2064: type = type->semantic(loc, sc); 2065: return this; 2066: } 2067: 2068: int RealExp::isBool(int result) 2069: { 2070: #ifdef IN_GCC 2071: return result ? (! value.isZero()) : (value.isZero()); 2072: #else 2073: return result ? (value != 0) 2074: : (value == 0); 2075: #endif 2076: } 2077: 2078: void floatToBuffer(OutBuffer *buf, Type *type, real_t value) 2079: { 2080: /* In order to get an exact representation, try converting it 2081: * to decimal then back again. If it matches, use it. 2082: * If it doesn't, fall back to hex, which is 2083: * always exact. 2084: */ 2085: char buffer[25]; 2086: sprintf(buffer, "%Lg", value);
warning C4996: 'sprintf': This function or variable may be unsafe. Consider using sprintf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details. c:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\stdio.h(371) : see declaration of 'sprintf'
2087: assert(strlen(buffer) < sizeof(buffer)); 2088: #if _WIN32 && __DMC__ 2089: char *save = __locale_decpoint; 2090: __locale_decpoint = "."; 2091: real_t r = strtold(buffer, NULL); 2092: __locale_decpoint = save; 2093: #else 2094: real_t r = strtold(buffer, NULL); 2095: #endif 2096: if (r == value) // if exact duplication 2097: buf->writestring(buffer); 2098: else 2099: buf->printf("%La", value); // ensure exact duplication 2100: 2101: if (type) 2102: { 2103: Type *t = type->toBasetype(); 2104: switch (t->ty) 2105: { 2106: case Tfloat32: 2107: case Timaginary32: 2108: case Tcomplex32: 2109: buf->writeByte('F'); 2110: break; 2111: 2112: case Tfloat80: 2113: case Timaginary80: 2114: case Tcomplex80: 2115: buf->writeByte('L'); 2116: break; 2117: 2118: default: 2119: break; 2120: } 2121: if (t->isimaginary()) 2122: buf->writeByte('i'); 2123: } 2124: } 2125: 2126: void RealExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 2127: { 2128: floatToBuffer(buf, type, value); 2129: } 2130: 2131: void realToMangleBuffer(OutBuffer *buf, real_t value) 2132: { 2133: /* Rely on %A to get portable mangling. 2134: * Must munge result to get only identifier characters. 2135: * 2136: * Possible values from %A => mangled result 2137: * NAN => NAN 2138: * -INF => NINF 2139: * INF => INF 2140: * -0X1.1BC18BA997B95P+79 => N11BC18BA997B95P79 2141: * 0X1.9P+2 => 19P2 2142: */ 2143: 2144: if (Port::isNan(value)) 2145: buf->writestring("NAN"); // no -NAN bugs 2146: else 2147: { 2148: char buffer[32]; 2149: int n = sprintf(buffer, "%LA", value);
warning C4996: 'sprintf': This function or variable may be unsafe. Consider using sprintf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details. c:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\stdio.h(371) : see declaration of 'sprintf'
2150: assert(n > 0 && n < sizeof(buffer)); 2151: for (int i = 0; i < n; i++) 2152: { char c = buffer[i]; 2153: 2154: switch (c) 2155: { 2156: case '-': 2157: buf->writeByte('N'); 2158: break; 2159: 2160: case '+': 2161: case 'X': 2162: case '.': 2163: break; 2164: 2165: case '0': 2166: if (i < 2) 2167: break; // skip leading 0X 2168: default: 2169: buf->writeByte(c); 2170: break; 2171: } 2172: } 2173: } 2174: } 2175: 2176: void RealExp::toMangleBuffer(OutBuffer *buf) 2177: { 2178: buf->writeByte('e'); 2179: realToMangleBuffer(buf, value); 2180: } 2181: 2182: 2183: /******************************** ComplexExp **************************/ 2184: 2185: ComplexExp::ComplexExp(Loc loc, complex_t value, Type *type) 2186: : Expression(loc, TOKcomplex80, sizeof(ComplexExp)) 2187: { 2188: this->value = value; 2189: this->type = type; 2190: //printf("ComplexExp::ComplexExp(%s)\n", toChars()); 2191: } 2192: 2193: char *ComplexExp::toChars() 2194: { 2195: char buffer[sizeof(value) * 3 + 8 + 1]; 2196: 2197: #ifdef IN_GCC 2198: char buf1[sizeof(value) * 3 + 8 + 1]; 2199: char buf2[sizeof(value) * 3 + 8 + 1]; 2200: creall(value).format(buf1, sizeof(buf1)); 2201: cimagl(value).format(buf2, sizeof(buf2)); 2202: sprintf(buffer, "(%s+%si)", buf1, buf2); 2203: #else 2204: sprintf(buffer, "(%Lg+%Lgi)", creall(value), cimagl(value));
warning C4996: 'sprintf': This function or variable may be unsafe. Consider using sprintf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details. c:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\stdio.h(371) : see declaration of 'sprintf'
2205: assert(strlen(buffer) < sizeof(buffer)); 2206: #endif 2207: return mem.strdup(buffer); 2208: } 2209: 2210: dinteger_t ComplexExp::toInteger() 2211: { 2212: #ifdef IN_GCC 2213: return (sinteger_t) toReal().toInt(); 2214: #else 2215: return (sinteger_t) toReal(); 2216: #endif 2217: } 2218: 2219: uinteger_t ComplexExp::toUInteger() 2220: { 2221: #ifdef IN_GCC 2222: return (uinteger_t) toReal().toInt(); 2223: #else 2224: return (uinteger_t) toReal(); 2225: #endif 2226: } 2227: 2228: real_t ComplexExp::toReal() 2229: { 2230: return creall(value); 2231: } 2232: 2233: real_t ComplexExp::toImaginary() 2234: { 2235: return cimagl(value); 2236: } 2237: 2238: complex_t ComplexExp::toComplex() 2239: { 2240: return value; 2241: } 2242: 2243: int ComplexExp::equals(Object *o) 2244: { ComplexExp *ne; 2245: 2246: if (this == o || 2247: (((Expression *)o)->op == TOKcomplex80 && 2248: ((ne = (ComplexExp *)o), type->toHeadMutable()->equals(ne->type->toHeadMutable())) && 2249: RealEquals(creall(value), creall(ne->value)) && 2250: RealEquals(cimagl(value), cimagl(ne->value)) 2251: ) 2252: ) 2253: return 1; 2254: return 0; 2255: } 2256: 2257: Expression *ComplexExp::semantic(Scope *sc) 2258: { 2259: if (!type) 2260: type = Type::tcomplex80; 2261: else 2262: type = type->semantic(loc, sc); 2263: return this; 2264: } 2265: 2266: int ComplexExp::isBool(int result) 2267: { 2268: if (result) 2269: return (bool)(value); 2270: else 2271: return !value; 2272: } 2273: 2274: void ComplexExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 2275: { 2276: /* Print as: 2277: * (re+imi) 2278: */ 2279: #ifdef IN_GCC 2280: char buf1[sizeof(value) * 3 + 8 + 1]; 2281: char buf2[sizeof(value) * 3 + 8 + 1]; 2282: creall(value).format(buf1, sizeof(buf1)); 2283: cimagl(value).format(buf2, sizeof(buf2)); 2284: buf->printf("(%s+%si)", buf1, buf2); 2285: #else 2286: buf->writeByte('('); 2287: floatToBuffer(buf, type, creall(value)); 2288: buf->writeByte('+'); 2289: floatToBuffer(buf, type, cimagl(value)); 2290: buf->writestring("i)"); 2291: #endif 2292: } 2293: 2294: void ComplexExp::toMangleBuffer(OutBuffer *buf) 2295: { 2296: buf->writeByte('c'); 2297: real_t r = toReal(); 2298: realToMangleBuffer(buf, r); 2299: buf->writeByte('c'); // separate the two 2300: r = toImaginary(); 2301: realToMangleBuffer(buf, r); 2302: } 2303: 2304: /******************************** IdentifierExp **************************/ 2305: 2306: IdentifierExp::IdentifierExp(Loc loc, Identifier *ident) 2307: : Expression(loc, TOKidentifier, sizeof(IdentifierExp)) 2308: { 2309: this->ident = ident; 2310: } 2311: 2312: Expression *IdentifierExp::semantic(Scope *sc) 2313: { 2314: Dsymbol *s; 2315: Dsymbol *scopesym; 2316: 2317: #if LOGSEMANTIC 2318: printf("IdentifierExp::semantic('%s')\n", ident->toChars()); 2319: #endif 2320: s = sc->search(loc, ident, &scopesym); 2321: if (s) 2322: { Expression *e; 2323: WithScopeSymbol *withsym; 2324: 2325: /* See if the symbol was a member of an enclosing 'with' 2326: */ 2327: withsym = scopesym->isWithScopeSymbol(); 2328: if (withsym) 2329: { 2330: #if DMDV2 2331: /* Disallow shadowing 2332: */ 2333: // First find the scope of the with 2334: Scope *scwith = sc; 2335: while (scwith->scopesym != scopesym) 2336: { scwith = scwith->enclosing; 2337: assert(scwith); 2338: } 2339: // Look at enclosing scopes for symbols with the same name, 2340: // in the same function 2341: for (Scope *scx = scwith; scx && scx->func == scwith->func; scx = scx->enclosing) 2342: { Dsymbol *s2; 2343: 2344: if (scx->scopesym && scx->scopesym->symtab && 2345: (s2 = scx->scopesym->symtab->lookup(s->ident)) != NULL && 2346: s != s2) 2347: { 2348: error("with symbol %s is shadowing local symbol %s", s->toPrettyChars(), s2->toPrettyChars()); 2349: } 2350: } 2351: #endif 2352: s = s->toAlias(); 2353: 2354: // Same as wthis.ident 2355: if (s->needThis() || s->isTemplateDeclaration()) 2356: { 2357: e = new VarExp(loc, withsym->withstate->wthis); 2358: e = new DotIdExp(loc, e, ident); 2359: } 2360: else 2361: { Type *t = withsym->withstate->wthis->type; 2362: if (t->ty == Tpointer) 2363: t = ((TypePointer *)t)->next; 2364: e = typeDotIdExp(loc, t, ident); 2365: } 2366: } 2367: else 2368: { 2369: /* If f is really a function template, 2370: * then replace f with the function template declaration. 2371: */ 2372: FuncDeclaration *f = s->isFuncDeclaration(); 2373: if (f) 2374: { TemplateDeclaration *tempdecl = getFuncTemplateDecl(f); 2375: if (tempdecl) 2376: { 2377: if (tempdecl->overroot) // if not start of overloaded list of TemplateDeclaration's 2378: tempdecl = tempdecl->overroot; // then get the start 2379: e = new TemplateExp(loc, tempdecl); 2380: e = e->semantic(sc); 2381: return e; 2382: } 2383: } 2384: // Haven't done overload resolution yet, so pass 1 2385: e = new DsymbolExp(loc, s, 1); 2386: } 2387: return e->semantic(sc); 2388: } 2389: #if DMDV2 2390: if (ident == Id::ctfe) 2391: { // Create the magic __ctfe bool variable 2392: VarDeclaration *vd = new VarDeclaration(loc, Type::tbool, Id::ctfe, NULL); 2393: Expression *e = new VarExp(loc, vd); 2394: e = e->semantic(sc); 2395: return e; 2396: } 2397: #endif 2398: const char *n = importHint(ident->toChars()); 2399: if (n) 2400: error("'%s' is not defined, perhaps you need to import %s; ?", ident->toChars(), n); 2401: else 2402: { 2403: s = sc->search_correct(ident); 2404: if (s) 2405: error("undefined identifier %s, did you mean %s %s?", ident->toChars(), s->kind(), s->toChars()); 2406: else 2407: error("undefined identifier %s", ident->toChars()); 2408: } 2409: return new ErrorExp(); 2410: } 2411: 2412: char *IdentifierExp::toChars() 2413: { 2414: return ident->toChars(); 2415: } 2416: 2417: void IdentifierExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 2418: { 2419: if (hgs->hdrgen) 2420: buf->writestring(ident->toHChars2()); 2421: else 2422: buf->writestring(ident->toChars()); 2423: } 2424: 2425: #if DMDV2 2426: int IdentifierExp::isLvalue() 2427: { 2428: return 1; 2429: } 2430: #endif 2431: 2432: Expression *IdentifierExp::toLvalue(Scope *sc, Expression *e) 2433: { 2434: #if 0 2435: tym = tybasic(e1->ET->Tty); 2436: if (!(tyscalar(tym) || 2437: tym == TYstruct || 2438: tym == TYarray && e->Eoper == TOKaddr)) 2439: synerr(EM_lvalue); // lvalue expected 2440: #endif 2441: return this; 2442: } 2443: 2444: /******************************** DollarExp **************************/ 2445: 2446: DollarExp::DollarExp(Loc loc) 2447: : IdentifierExp(loc, Id::dollar) 2448: { 2449: } 2450: 2451: /******************************** DsymbolExp **************************/ 2452: 2453: DsymbolExp::DsymbolExp(Loc loc, Dsymbol *s, int hasOverloads) 2454: : Expression(loc, TOKdsymbol, sizeof(DsymbolExp)) 2455: { 2456: this->s = s; 2457: this->hasOverloads = hasOverloads; 2458: } 2459: 2460: Expression *DsymbolExp::semantic(Scope *sc) 2461: { 2462: #if LOGSEMANTIC 2463: printf("DsymbolExp::semantic('%s')\n", s->toChars()); 2464: #endif 2465: 2466: Lagain: 2467: EnumMember *em; 2468: Expression *e; 2469: VarDeclaration *v; 2470: FuncDeclaration *f; 2471: FuncLiteralDeclaration *fld; 2472: OverloadSet *o; 2473: Declaration *d;
warning C4101: 'd' : unreferenced local variable
2474: ClassDeclaration *cd; 2475: ClassDeclaration *thiscd = NULL; 2476: Import *imp; 2477: Package *pkg; 2478: Type *t; 2479: 2480: //printf("DsymbolExp:: %p '%s' is a symbol\n", this, toChars()); 2481: //printf("s = '%s', s->kind = '%s'\n", s->toChars(), s->kind()); 2482: if (type) 2483: return this; 2484: if (!s->isFuncDeclaration()) // functions are checked after overloading 2485: checkDeprecated(sc, s); 2486: s = s->toAlias(); 2487: //printf("s = '%s', s->kind = '%s', s->needThis() = %p\n", s->toChars(), s->kind(), s->needThis()); 2488: if (!s->isFuncDeclaration()) 2489: checkDeprecated(sc, s); 2490: 2491: if (sc->func) 2492: thiscd = sc->func->parent->isClassDeclaration(); 2493: 2494: // BUG: This should happen after overload resolution for functions, not before 2495: if (s->needThis()) 2496: { 2497: if (hasThis(sc) 2498: #if DMDV2 2499: && !s->isFuncDeclaration() 2500: #endif 2501: ) 2502: { 2503: // Supply an implicit 'this', as in 2504: // this.ident 2505: 2506: DotVarExp *de; 2507: 2508: de = new DotVarExp(loc, new ThisExp(loc), s->isDeclaration()); 2509: return de->semantic(sc); 2510: } 2511: } 2512: 2513: em = s->isEnumMember(); 2514: if (em) 2515: { 2516: e = em->value; 2517: e = e->semantic(sc); 2518: return e; 2519: } 2520: v = s->isVarDeclaration(); 2521: if (v) 2522: { 2523: //printf("Identifier '%s' is a variable, type '%s'\n", toChars(), v->type->toChars()); 2524: if (!type) 2525: { if ((!v->type || !v->type->deco) && v->scope) 2526: v->semantic(v->scope); 2527: type = v->type; 2528: if (!v->type) 2529: { error("forward reference of %s %s", v->kind(), v->toChars()); 2530: return new ErrorExp(); 2531: } 2532: } 2533: 2534: if ((v->storage_class & STCmanifest) && v->init) 2535: { 2536: e = v->init->toExpression(); 2537: if (!e) 2538: { error("cannot make expression out of initializer for %s", v->toChars()); 2539: return new ErrorExp(); 2540: } 2541: e = e->semantic(sc); 2542: return e; 2543: } 2544: 2545: e = new VarExp(loc, v); 2546: e->type = type; 2547: e = e->semantic(sc); 2548: return e->deref(); 2549: } 2550: fld = s->isFuncLiteralDeclaration(); 2551: if (fld) 2552: { //printf("'%s' is a function literal\n", fld->toChars()); 2553: e = new FuncExp(loc, fld); 2554: return e->semantic(sc); 2555: } 2556: f = s->isFuncDeclaration(); 2557: if (f) 2558: { //printf("'%s' is a function\n", f->toChars()); 2559: 2560: if (!f->originalType && f->scope) // semantic not yet run 2561: f->semantic(f->scope); 2562: 2563: // if inferring return type, sematic3 needs to be run 2564: if (f->inferRetType && f->scope && f->type && !f->type->nextOf()) 2565: f->semantic3(f->scope); 2566: 2567: if (f->isUnitTestDeclaration()) 2568: { 2569: error("cannot call unittest function %s", toChars()); 2570: return new ErrorExp(); 2571: } 2572: if (!f->type->deco)
warning C6011: Dereferencing NULL pointer 'f->type': Lines: 2466, 2467, 2468, 2469, 2470, 2471, 2472, 2473, 2474, 2475, 2476, 2477, 2478, 2482, 2484, 2485, 2486, 2488, 2489, 2491, 2492, 2495, 2499, 2513, 2514, 2520, 2521, 2550, 2551, 2556, 2557, 2560, 2561, 2564, 2567, 2572
2573: { 2574: error("forward reference to %s", toChars()); 2575: return new ErrorExp(); 2576: } 2577: return new VarExp(loc, f, hasOverloads); 2578: } 2579: o = s->isOverloadSet(); 2580: if (o) 2581: { //printf("'%s' is an overload set\n", o->toChars()); 2582: return new OverExp(o); 2583: } 2584: cd = s->isClassDeclaration(); 2585: if (cd && thiscd && cd->isBaseOf(thiscd, NULL) && sc->func->needThis()) 2586: { 2587: // We need to add an implicit 'this' if cd is this class or a base class. 2588: DotTypeExp *dte; 2589: 2590: dte = new DotTypeExp(loc, new ThisExp(loc), s); 2591: return dte->semantic(sc); 2592: } 2593: imp = s->isImport(); 2594: if (imp) 2595: { 2596: if (!imp->pkg) 2597: { error("forward reference of import %s", imp->toChars()); 2598: return new ErrorExp(); 2599: } 2600: ScopeExp *ie = new ScopeExp(loc, imp->pkg); 2601: return ie->semantic(sc); 2602: } 2603: pkg = s->isPackage(); 2604: if (pkg) 2605: { 2606: ScopeExp *ie; 2607: 2608: ie = new ScopeExp(loc, pkg); 2609: return ie->semantic(sc); 2610: } 2611: Module *mod = s->isModule(); 2612: if (mod) 2613: { 2614: ScopeExp *ie; 2615: 2616: ie = new ScopeExp(loc, mod); 2617: return ie->semantic(sc); 2618: } 2619: 2620: t = s->getType(); 2621: if (t) 2622: { 2623: return new TypeExp(loc, t); 2624: } 2625: 2626: TupleDeclaration *tup = s->isTupleDeclaration(); 2627: if (tup) 2628: { 2629: e = new TupleExp(loc, tup); 2630: e = e->semantic(sc); 2631: return e; 2632: } 2633: 2634: TemplateInstance *ti = s->isTemplateInstance(); 2635: if (ti && !global.errors) 2636: { if (!ti->semanticRun) 2637: ti->semantic(sc); 2638: s = ti->inst->toAlias(); 2639: if (!s->isTemplateInstance()) 2640: goto Lagain; 2641: e = new ScopeExp(loc, ti); 2642: e = e->semantic(sc); 2643: return e; 2644: } 2645: 2646: TemplateDeclaration *td = s->isTemplateDeclaration(); 2647: if (td) 2648: { 2649: e = new TemplateExp(loc, td); 2650: e = e->semantic(sc); 2651: return e; 2652: } 2653: 2654: Lerr:
warning C4102: 'Lerr' : unreferenced label
2655: error("%s '%s' is not a variable", s->kind(), s->toChars()); 2656: return new ErrorExp(); 2657: } 2658: 2659: char *DsymbolExp::toChars() 2660: { 2661: return s->toChars(); 2662: } 2663: 2664: void DsymbolExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 2665: { 2666: buf->writestring(s->toChars()); 2667: } 2668: 2669: #if DMDV2 2670: int DsymbolExp::isLvalue() 2671: { 2672: return 1; 2673: } 2674: #endif 2675: 2676: Expression *DsymbolExp::toLvalue(Scope *sc, Expression *e) 2677: { 2678: #if 0 2679: tym = tybasic(e1->ET->Tty); 2680: if (!(tyscalar(tym) || 2681: tym == TYstruct || 2682: tym == TYarray && e->Eoper == TOKaddr)) 2683: synerr(EM_lvalue); // lvalue expected 2684: #endif 2685: return this; 2686: } 2687: 2688: /******************************** ThisExp **************************/ 2689: 2690: ThisExp::ThisExp(Loc loc) 2691: : Expression(loc, TOKthis, sizeof(ThisExp)) 2692: { 2693: //printf("ThisExp::ThisExp() loc = %d\n", loc.linnum); 2694: var = NULL; 2695: } 2696: 2697: Expression *ThisExp::semantic(Scope *sc) 2698: { FuncDeclaration *fd; 2699: FuncDeclaration *fdthis; 2700: int nested = 0; 2701: 2702: #if LOGSEMANTIC 2703: printf("ThisExp::semantic()\n"); 2704: #endif 2705: if (type) 2706: { //assert(global.errors || var); 2707: return this; 2708: } 2709: 2710: /* Special case for typeof(this) and typeof(super) since both 2711: * should work even if they are not inside a non-static member function 2712: */ 2713: if (sc->intypeof) 2714: { 2715: // Find enclosing struct or class 2716: for (Dsymbol *s = sc->parent; 1; s = s->parent) 2717: { 2718: if (!s) 2719: { 2720: error("%s is not in a class or struct scope", toChars()); 2721: goto Lerr; 2722: } 2723: ClassDeclaration *cd = s->isClassDeclaration(); 2724: if (cd) 2725: { 2726: type = cd->type; 2727: return this; 2728: } 2729: StructDeclaration *sd = s->isStructDeclaration(); 2730: if (sd) 2731: { 2732: #if STRUCTTHISREF 2733: type = sd->type; 2734: #else 2735: type = sd->type->pointerTo(); 2736: #endif 2737: return this; 2738: } 2739: } 2740: } 2741: 2742: fdthis = sc->parent->isFuncDeclaration(); 2743: fd = hasThis(sc); // fd is the uplevel function with the 'this' variable 2744: if (!fd) 2745: goto Lerr; 2746: 2747: assert(fd->vthis); 2748: var = fd->vthis; 2749: assert(var->parent); 2750: type = var->type; 2751: var->isVarDeclaration()->checkNestedReference(sc, loc); 2752: if (!sc->intypeof) 2753: sc->callSuper |= CSXthis; 2754: return this; 2755: 2756: Lerr: 2757: error("'this' is only defined in non-static member functions, not %s", sc->parent->toChars());
warning C6011: Dereferencing NULL pointer 'sc->parent': Lines: 2698, 2699, 2700, 2705, 2713, 2716, 2718, 2720, 2721, 2756, 2757
2758: return new ErrorExp(); 2759: } 2760: 2761: int ThisExp::isBool(int result) 2762: { 2763: return result ? TRUE : FALSE; 2764: } 2765: 2766: void ThisExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 2767: { 2768: buf->writestring("this"); 2769: } 2770: 2771: #if DMDV2 2772: int ThisExp::isLvalue() 2773: { 2774: return 1; 2775: } 2776: #endif 2777: 2778: Expression *ThisExp::toLvalue(Scope *sc, Expression *e) 2779: { 2780: return this; 2781: } 2782: 2783: /******************************** SuperExp **************************/ 2784: 2785: SuperExp::SuperExp(Loc loc) 2786: : ThisExp(loc) 2787: { 2788: op = TOKsuper; 2789: } 2790: 2791: Expression *SuperExp::semantic(Scope *sc) 2792: { FuncDeclaration *fd; 2793: FuncDeclaration *fdthis; 2794: ClassDeclaration *cd; 2795: Dsymbol *s; 2796: 2797: #if LOGSEMANTIC 2798: printf("SuperExp::semantic('%s')\n", toChars()); 2799: #endif 2800: if (type) 2801: return this; 2802: 2803: /* Special case for typeof(this) and typeof(super) since both 2804: * should work even if they are not inside a non-static member function 2805: */ 2806: if (sc->intypeof) 2807: { 2808: // Find enclosing class 2809: for (Dsymbol *s = sc->parent; 1; s = s->parent)
warning C6246: Local declaration of 's' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '2795' of 'c:\projects\extern\d\dmd\src\expression.c': Lines: 2795
2810: { 2811: ClassDeclaration *cd;
warning C6246: Local declaration of 'cd' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '2794' of 'c:\projects\extern\d\dmd\src\expression.c': Lines: 2794
2812: 2813: if (!s) 2814: { 2815: error("%s is not in a class scope", toChars()); 2816: goto Lerr; 2817: } 2818: cd = s->isClassDeclaration(); 2819: if (cd) 2820: { 2821: cd = cd->baseClass; 2822: if (!cd) 2823: { error("class %s has no 'super'", s->toChars()); 2824: goto Lerr; 2825: } 2826: type = cd->type; 2827: return this; 2828: } 2829: } 2830: } 2831: 2832: fdthis = sc->parent->isFuncDeclaration(); 2833: fd = hasThis(sc); 2834: if (!fd) 2835: goto Lerr; 2836: assert(fd->vthis); 2837: var = fd->vthis; 2838: assert(var->parent); 2839: 2840: s = fd->toParent(); 2841: while (s && s->isTemplateInstance()) 2842: s = s->toParent(); 2843: assert(s); 2844: cd = s->isClassDeclaration(); 2845: //printf("parent is %s %s\n", fd->toParent()->kind(), fd->toParent()->toChars()); 2846: if (!cd) 2847: goto Lerr; 2848: if (!cd->baseClass) 2849: { 2850: error("no base class for %s", cd->toChars()); 2851: type = fd->vthis->type; 2852: } 2853: else 2854: { 2855: type = cd->baseClass->type; 2856: } 2857: 2858: var->isVarDeclaration()->checkNestedReference(sc, loc); 2859: 2860: if (!sc->intypeof) 2861: sc->callSuper |= CSXsuper; 2862: return this; 2863: 2864: 2865: Lerr: 2866: error("'super' is only allowed in non-static class member functions"); 2867: return new ErrorExp(); 2868: } 2869: 2870: void SuperExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 2871: { 2872: buf->writestring("super"); 2873: } 2874: 2875: 2876: /******************************** NullExp **************************/ 2877: 2878: NullExp::NullExp(Loc loc, Type *type) 2879: : Expression(loc, TOKnull, sizeof(NullExp)) 2880: { 2881: committed = 0; 2882: this->type = type; 2883: } 2884: 2885: Expression *NullExp::semantic(Scope *sc) 2886: { 2887: #if LOGSEMANTIC 2888: printf("NullExp::semantic('%s')\n", toChars()); 2889: #endif 2890: // NULL is the same as (void *)0 2891: if (!type) 2892: type = Type::tvoid->pointerTo(); 2893: return this; 2894: } 2895: 2896: int NullExp::isBool(int result) 2897: { 2898: return result ? FALSE : TRUE; 2899: } 2900: 2901: void NullExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 2902: { 2903: buf->writestring("null"); 2904: } 2905: 2906: void NullExp::toMangleBuffer(OutBuffer *buf) 2907: { 2908: buf->writeByte('n'); 2909: } 2910: 2911: /******************************** StringExp **************************/ 2912: 2913: StringExp::StringExp(Loc loc, char *string) 2914: : Expression(loc, TOKstring, sizeof(StringExp)) 2915: { 2916: this->string = string; 2917: this->len = strlen(string); 2918: this->sz = 1; 2919: this->committed = 0; 2920: this->postfix = 0; 2921: } 2922: 2923: StringExp::StringExp(Loc loc, void *string, size_t len) 2924: : Expression(loc, TOKstring, sizeof(StringExp)) 2925: { 2926: this->string = string; 2927: this->len = len; 2928: this->sz = 1; 2929: this->committed = 0; 2930: this->postfix = 0; 2931: } 2932: 2933: StringExp::StringExp(Loc loc, void *string, size_t len, unsigned char postfix) 2934: : Expression(loc, TOKstring, sizeof(StringExp)) 2935: { 2936: this->string = string; 2937: this->len = len; 2938: this->sz = 1; 2939: this->committed = 0; 2940: this->postfix = postfix; 2941: } 2942: 2943: #if 0 2944: Expression *StringExp::syntaxCopy() 2945: { 2946: printf("StringExp::syntaxCopy() %s\n", toChars()); 2947: return copy(); 2948: } 2949: #endif 2950: 2951: int StringExp::equals(Object *o) 2952: { 2953: //printf("StringExp::equals('%s') %s\n", o->toChars(), toChars()); 2954: if (o && o->dyncast() == DYNCAST_EXPRESSION) 2955: { Expression *e = (Expression *)o; 2956: 2957: if (e->op == TOKstring) 2958: { 2959: return compare(o) == 0; 2960: } 2961: } 2962: return FALSE; 2963: } 2964: 2965: char *StringExp::toChars() 2966: { 2967: OutBuffer buf; 2968: HdrGenState hgs; 2969: char *p; 2970: 2971: memset(&hgs, 0, sizeof(hgs)); 2972: toCBuffer(&buf, &hgs); 2973: buf.writeByte(0); 2974: p = (char *)buf.data; 2975: buf.data = NULL; 2976: return p; 2977: } 2978: 2979: Expression *StringExp::semantic(Scope *sc) 2980: { 2981: #if LOGSEMANTIC 2982: printf("StringExp::semantic() %s\n", toChars()); 2983: #endif 2984: if (!type) 2985: { OutBuffer buffer; 2986: size_t newlen = 0; 2987: const char *p; 2988: size_t u; 2989: unsigned c; 2990: 2991: switch (postfix) 2992: { 2993: case 'd': 2994: for (u = 0; u < len;) 2995: { 2996: p = utf_decodeChar((unsigned char *)string, len, &u, &c); 2997: if (p) 2998: { error("%s", p); 2999: return new ErrorExp(); 3000: } 3001: else 3002: { buffer.write4(c); 3003: newlen++; 3004: } 3005: } 3006: buffer.write4(0); 3007: string = buffer.extractData(); 3008: len = newlen; 3009: sz = 4; 3010: //type = new TypeSArray(Type::tdchar, new IntegerExp(loc, len, Type::tindex)); 3011: type = new TypeDArray(Type::tdchar->invariantOf()); 3012: committed = 1; 3013: break; 3014: 3015: case 'w': 3016: for (u = 0; u < len;) 3017: { 3018: p = utf_decodeChar((unsigned char *)string, len, &u, &c); 3019: if (p) 3020: { error("%s", p); 3021: return new ErrorExp(); 3022: } 3023: else 3024: { buffer.writeUTF16(c); 3025: newlen++; 3026: if (c >= 0x10000) 3027: newlen++; 3028: } 3029: } 3030: buffer.writeUTF16(0); 3031: string = buffer.extractData(); 3032: len = newlen; 3033: sz = 2; 3034: //type = new TypeSArray(Type::twchar, new IntegerExp(loc, len, Type::tindex)); 3035: type = new TypeDArray(Type::twchar->invariantOf()); 3036: committed = 1; 3037: break; 3038: 3039: case 'c': 3040: committed = 1; 3041: default: 3042: //type = new TypeSArray(Type::tchar, new IntegerExp(loc, len, Type::tindex)); 3043: type = new TypeDArray(Type::tchar->invariantOf()); 3044: break; 3045: } 3046: type = type->semantic(loc, sc); 3047: //type = type->invariantOf(); 3048: //printf("type = %s\n", type->toChars()); 3049: } 3050: return this; 3051: } 3052: 3053: /********************************** 3054: * Return length of string. 3055: */ 3056: 3057: size_t StringExp::length() 3058: { 3059: size_t result = 0; 3060: dchar_t c; 3061: const char *p; 3062: 3063: switch (sz) 3064: { 3065: case 1: 3066: for (size_t u = 0; u < len;) 3067: { 3068: p = utf_decodeChar((unsigned char *)string, len, &u, &c); 3069: if (p) 3070: { error("%s", p); 3071: return 0; 3072: } 3073: else 3074: result++; 3075: } 3076: break; 3077: 3078: case 2: 3079: for (size_t u = 0; u < len;) 3080: { 3081: p = utf_decodeWchar((unsigned short *)string, len, &u, &c); 3082: if (p) 3083: { error("%s", p); 3084: return 0; 3085: } 3086: else 3087: result++; 3088: } 3089: break; 3090: 3091: case 4: 3092: result = len; 3093: break; 3094: 3095: default: 3096: assert(0); 3097: } 3098: return result; 3099: } 3100: 3101: /**************************************** 3102: * Convert string to char[]. 3103: */ 3104: 3105: StringExp *StringExp::toUTF8(Scope *sc) 3106: { 3107: if (sz != 1) 3108: { // Convert to UTF-8 string 3109: committed = 0; 3110: Expression *e = castTo(sc, Type::tchar->arrayOf()); 3111: e = e->optimize(WANTvalue); 3112: assert(e->op == TOKstring); 3113: StringExp *se = (StringExp *)e; 3114: assert(se->sz == 1); 3115: return se; 3116: } 3117: return this; 3118: } 3119: 3120: int StringExp::compare(Object *obj) 3121: { 3122: //printf("StringExp::compare()\n"); 3123: // Used to sort case statement expressions so we can do an efficient lookup 3124: StringExp *se2 = (StringExp *)(obj); 3125: 3126: // This is a kludge so isExpression() in template.c will return 5 3127: // for StringExp's. 3128: if (!se2) 3129: return 5; 3130: 3131: assert(se2->op == TOKstring); 3132: 3133: int len1 = len; 3134: int len2 = se2->len; 3135: 3136: //printf("sz = %d, len1 = %d, len2 = %d\n", sz, len1, len2); 3137: if (len1 == len2) 3138: { 3139: switch (sz) 3140: { 3141: case 1: 3142: return memcmp((char *)string, (char *)se2->string, len1); 3143: 3144: case 2: 3145: { unsigned u; 3146: d_wchar *s1 = (d_wchar *)string; 3147: d_wchar *s2 = (d_wchar *)se2->string; 3148: 3149: for (u = 0; u < len; u++) 3150: { 3151: if (s1[u] != s2[u]) 3152: return s1[u] - s2[u]; 3153: } 3154: } 3155: 3156: case 4: 3157: { unsigned u; 3158: d_dchar *s1 = (d_dchar *)string; 3159: d_dchar *s2 = (d_dchar *)se2->string; 3160: 3161: for (u = 0; u < len; u++) 3162: { 3163: if (s1[u] != s2[u]) 3164: return s1[u] - s2[u]; 3165: } 3166: } 3167: break; 3168: 3169: default: 3170: assert(0); 3171: } 3172: } 3173: return len1 - len2; 3174: } 3175: 3176: int StringExp::isBool(int result) 3177: { 3178: return result ? TRUE : FALSE; 3179: } 3180: 3181: #if DMDV2 3182: int StringExp::isLvalue() 3183: { 3184: return 1; 3185: } 3186: #endif 3187: 3188: Expression *StringExp::toLvalue(Scope *sc, Expression *e) 3189: { 3190: //printf("StringExp::toLvalue(%s)\n", toChars()); 3191: return this; 3192: } 3193: 3194: unsigned StringExp::charAt(size_t i) 3195: { unsigned value; 3196: 3197: switch (sz) 3198: { 3199: case 1: 3200: value = ((unsigned char *)string)[i]; 3201: break; 3202: 3203: case 2: 3204: value = ((unsigned short *)string)[i]; 3205: break; 3206: 3207: case 4: 3208: value = ((unsigned int *)string)[i]; 3209: break; 3210: 3211: default: 3212: assert(0); 3213: break; 3214: } 3215: return value; 3216: } 3217: 3218: void StringExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 3219: { 3220: buf->writeByte('"'); 3221: unsigned o = buf->offset; 3222: for (size_t i = 0; i < len; i++) 3223: { unsigned c = charAt(i); 3224: 3225: switch (c) 3226: { 3227: case '"': 3228: case '\\': 3229: if (!hgs->console) 3230: buf->writeByte('\\'); 3231: default: 3232: if (c <= 0xFF) 3233: { if (c <= 0x7F && (isprint(c) || hgs->console)) 3234: buf->writeByte(c); 3235: else 3236: buf->printf("\\x%02x", c); 3237: } 3238: else if (c <= 0xFFFF) 3239: buf->printf("\\x%02x\\x%02x", c & 0xFF, c >> 8); 3240: else 3241: buf->printf("\\x%02x\\x%02x\\x%02x\\x%02x", 3242: c & 0xFF, (c >> 8) & 0xFF, (c >> 16) & 0xFF, c >> 24); 3243: break; 3244: } 3245: } 3246: if (hgs->ddoc) 3247: escapeDdocString(buf, o); 3248: buf->writeByte('"'); 3249: if (postfix) 3250: buf->writeByte(postfix); 3251: } 3252: 3253: void StringExp::toMangleBuffer(OutBuffer *buf) 3254: { char m; 3255: OutBuffer tmp; 3256: const char *p; 3257: unsigned c; 3258: size_t u; 3259: unsigned char *q; 3260: unsigned qlen; 3261: 3262: /* Write string in UTF-8 format 3263: */ 3264: switch (sz) 3265: { case 1: 3266: m = 'a'; 3267: q = (unsigned char *)string; 3268: qlen = len; 3269: break; 3270: case 2: 3271: m = 'w'; 3272: for (u = 0; u < len; ) 3273: { 3274: p = utf_decodeWchar((unsigned short *)string, len, &u, &c); 3275: if (p) 3276: error("%s", p); 3277: else 3278: tmp.writeUTF8(c); 3279: } 3280: q = tmp.data; 3281: qlen = tmp.offset; 3282: break; 3283: case 4: 3284: m = 'd'; 3285: for (u = 0; u < len; u++) 3286: { 3287: c = ((unsigned *)string)[u]; 3288: if (!utf_isValidDchar(c)) 3289: error("invalid UCS-32 char \\U%08x", c); 3290: else 3291: tmp.writeUTF8(c); 3292: } 3293: q = tmp.data; 3294: qlen = tmp.offset; 3295: break; 3296: default: 3297: assert(0); 3298: } 3299: buf->writeByte(m); 3300: buf->printf("%d_", qlen); 3301: for (size_t i = 0; i < qlen; i++) 3302: buf->printf("%02x", q[i]); 3303: } 3304: 3305: /************************ ArrayLiteralExp ************************************/ 3306: 3307: // [ e1, e2, e3, ... ] 3308: 3309: ArrayLiteralExp::ArrayLiteralExp(Loc loc, Expressions *elements) 3310: : Expression(loc, TOKarrayliteral, sizeof(ArrayLiteralExp)) 3311: { 3312: this->elements = elements; 3313: } 3314: 3315: ArrayLiteralExp::ArrayLiteralExp(Loc loc, Expression *e) 3316: : Expression(loc, TOKarrayliteral, sizeof(ArrayLiteralExp)) 3317: { 3318: elements = new Expressions; 3319: elements->push(e); 3320: } 3321: 3322: Expression *ArrayLiteralExp::syntaxCopy() 3323: { 3324: return new ArrayLiteralExp(loc, arraySyntaxCopy(elements)); 3325: } 3326: 3327: Expression *ArrayLiteralExp::semantic(Scope *sc) 3328: { 3329: #if LOGSEMANTIC 3330: printf("ArrayLiteralExp::semantic('%s')\n", toChars()); 3331: #endif 3332: if (type) 3333: return this; 3334: 3335: /* Perhaps an empty array literal [ ] should be rewritten as null? 3336: */ 3337: 3338: arrayExpressionSemantic(elements, sc); // run semantic() on each element 3339: expandTuples(elements); 3340: 3341: Type *t0; 3342: elements = arrayExpressionToCommonType(sc, elements, &t0); 3343: 3344: type = t0->arrayOf(); 3345: //type = new TypeSArray(t0, new IntegerExp(elements->dim)); 3346: type = type->semantic(loc, sc); 3347: 3348: /* Disallow array literals of type void being used. 3349: */ 3350: if (elements->dim > 0 && t0->ty == Tvoid) 3351: error("%s of type %s has no value", toChars(), type->toChars()); 3352: 3353: return this; 3354: } 3355: 3356: int ArrayLiteralExp::checkSideEffect(int flag) 3357: { int f = 0; 3358: 3359: for (size_t i = 0; i < elements->dim; i++) 3360: { Expression *e = elements->tdata()[i]; 3361: 3362: f |= e->checkSideEffect(2); 3363: } 3364: if (flag == 0 && f == 0) 3365: Expression::checkSideEffect(0); 3366: return f; 3367: } 3368: 3369: int ArrayLiteralExp::isBool(int result) 3370: { 3371: size_t dim = elements ? elements->dim : 0; 3372: return result ? (dim != 0) : (dim == 0); 3373: } 3374: 3375: #if DMDV2 3376: int ArrayLiteralExp::canThrow(bool mustNotThrow) 3377: { 3378: /* Memory allocation failures throw non-recoverable exceptions, which 3379: * we don't need to count as 'throwing'. 3380: */ 3381: return arrayExpressionCanThrow(elements, mustNotThrow); 3382: } 3383: #endif 3384: 3385: void ArrayLiteralExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 3386: { 3387: buf->writeByte('['); 3388: argsToCBuffer(buf, elements, hgs); 3389: buf->writeByte(']'); 3390: } 3391: 3392: void ArrayLiteralExp::toMangleBuffer(OutBuffer *buf) 3393: { 3394: size_t dim = elements ? elements->dim : 0; 3395: buf->printf("A%u", dim); 3396: for (size_t i = 0; i < dim; i++) 3397: { Expression *e = elements->tdata()[i]; 3398: e->toMangleBuffer(buf); 3399: } 3400: } 3401: 3402: /************************ AssocArrayLiteralExp ************************************/ 3403: 3404: // [ key0 : value0, key1 : value1, ... ] 3405: 3406: AssocArrayLiteralExp::AssocArrayLiteralExp(Loc loc, 3407: Expressions *keys, Expressions *values) 3408: : Expression(loc, TOKassocarrayliteral, sizeof(AssocArrayLiteralExp)) 3409: { 3410: assert(keys->dim == values->dim); 3411: this->keys = keys; 3412: this->values = values; 3413: } 3414: 3415: Expression *AssocArrayLiteralExp::syntaxCopy() 3416: { 3417: return new AssocArrayLiteralExp(loc, 3418: arraySyntaxCopy(keys), arraySyntaxCopy(values)); 3419: } 3420: 3421: Expression *AssocArrayLiteralExp::semantic(Scope *sc) 3422: { Expression *e;
warning C4101: 'e' : unreferenced local variable
3423: 3424: #if LOGSEMANTIC 3425: printf("AssocArrayLiteralExp::semantic('%s')\n", toChars()); 3426: #endif 3427: 3428: if (type) 3429: return this; 3430: 3431: // Run semantic() on each element 3432: arrayExpressionSemantic(keys, sc); 3433: arrayExpressionSemantic(values, sc); 3434: expandTuples(keys); 3435: expandTuples(values); 3436: if (keys->dim != values->dim) 3437: { 3438: error("number of keys is %u, must match number of values %u", keys->dim, values->dim); 3439: return new ErrorExp(); 3440: } 3441: 3442: Type *tkey = NULL; 3443: Type *tvalue = NULL; 3444: keys = arrayExpressionToCommonType(sc, keys, &tkey); 3445: values = arrayExpressionToCommonType(sc, values, &tvalue); 3446: 3447: type = new TypeAArray(tvalue, tkey); 3448: type = type->semantic(loc, sc); 3449: return this; 3450: } 3451: 3452: int AssocArrayLiteralExp::checkSideEffect(int flag) 3453: { int f = 0; 3454: 3455: for (size_t i = 0; i < keys->dim; i++) 3456: { Expression *key = keys->tdata()[i]; 3457: Expression *value = values->tdata()[i]; 3458: 3459: f |= key->checkSideEffect(2); 3460: f |= value->checkSideEffect(2); 3461: } 3462: if (flag == 0 && f == 0) 3463: Expression::checkSideEffect(0); 3464: return f; 3465: } 3466: 3467: int AssocArrayLiteralExp::isBool(int result) 3468: { 3469: size_t dim = keys->dim; 3470: return result ? (dim != 0) : (dim == 0); 3471: } 3472: 3473: #if DMDV2 3474: int AssocArrayLiteralExp::canThrow(bool mustNotThrow) 3475: { 3476: /* Memory allocation failures throw non-recoverable exceptions, which 3477: * we don't need to count as 'throwing'. 3478: */ 3479: return (arrayExpressionCanThrow(keys, mustNotThrow) || 3480: arrayExpressionCanThrow(values, mustNotThrow)); 3481: } 3482: #endif 3483: 3484: void AssocArrayLiteralExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 3485: { 3486: buf->writeByte('['); 3487: for (size_t i = 0; i < keys->dim; i++) 3488: { Expression *key = keys->tdata()[i]; 3489: Expression *value = values->tdata()[i]; 3490: 3491: if (i) 3492: buf->writeByte(','); 3493: expToCBuffer(buf, hgs, key, PREC_assign); 3494: buf->writeByte(':'); 3495: expToCBuffer(buf, hgs, value, PREC_assign); 3496: } 3497: buf->writeByte(']'); 3498: } 3499: 3500: void AssocArrayLiteralExp::toMangleBuffer(OutBuffer *buf) 3501: { 3502: size_t dim = keys->dim; 3503: buf->printf("A%u", dim); 3504: for (size_t i = 0; i < dim; i++) 3505: { Expression *key = keys->tdata()[i]; 3506: Expression *value = values->tdata()[i]; 3507: 3508: key->toMangleBuffer(buf); 3509: value->toMangleBuffer(buf); 3510: } 3511: } 3512: 3513: /************************ StructLiteralExp ************************************/ 3514: 3515: // sd( e1, e2, e3, ... ) 3516: 3517: StructLiteralExp::StructLiteralExp(Loc loc, StructDeclaration *sd, Expressions *elements, Type *stype) 3518: : Expression(loc, TOKstructliteral, sizeof(StructLiteralExp)) 3519: { 3520: this->sd = sd; 3521: this->elements = elements; 3522: this->stype = stype; 3523: this->sym = NULL; 3524: this->soffset = 0; 3525: this->fillHoles = 1; 3526: } 3527: 3528: Expression *StructLiteralExp::syntaxCopy() 3529: { 3530: return new StructLiteralExp(loc, sd, arraySyntaxCopy(elements), stype); 3531: } 3532: 3533: Expression *StructLiteralExp::semantic(Scope *sc) 3534: { Expression *e; 3535: int nfields = sd->fields.dim - sd->isnested; 3536: 3537: #if LOGSEMANTIC 3538: printf("StructLiteralExp::semantic('%s')\n", toChars()); 3539: #endif 3540: if (type) 3541: return this; 3542: 3543: elements = arrayExpressionSemantic(elements, sc); // run semantic() on each element 3544: expandTuples(elements); 3545: size_t offset = 0; 3546: for (size_t i = 0; i < elements->dim; i++) 3547: { e = elements->tdata()[i]; 3548: if (!e) 3549: continue; 3550: 3551: if (!e->type) 3552: { error("%s has no value", e->toChars()); 3553: return new ErrorExp(); 3554: } 3555: e = resolveProperties(sc, e); 3556: if (i >= nfields)
warning C4018: '>=' : signed/unsigned mismatch
3557: { error("more initializers than fields of %s", sd->toChars()); 3558: return new ErrorExp(); 3559: } 3560: Dsymbol *s = sd->fields.tdata()[i]; 3561: VarDeclaration *v = s->isVarDeclaration(); 3562: assert(v); 3563: if (v->offset < offset) 3564: { error("overlapping initialization for %s", v->toChars()); 3565: return new ErrorExp(); 3566: } 3567: offset = v->offset + v->type->size();
warning C4244: '=' : conversion from 'd_uns64' to 'size_t', possible loss of data
3568: 3569: Type *telem = v->type; 3570: if (stype) 3571: telem = telem->addMod(stype->mod); 3572: while (!e->implicitConvTo(telem) && telem->toBasetype()->ty == Tsarray) 3573: { /* Static array initialization, as in: 3574: * T[3][5] = e; 3575: */ 3576: telem = telem->toBasetype()->nextOf(); 3577: } 3578: 3579: e = e->implicitCastTo(sc, telem); 3580: 3581: elements->tdata()[i] = e; 3582: } 3583: 3584: /* Fill out remainder of elements[] with default initializers for fields[] 3585: */ 3586: for (size_t i = elements->dim; i < nfields; i++)
warning C4018: '<' : signed/unsigned mismatch
3587: { Dsymbol *s = sd->fields.tdata()[i]; 3588: VarDeclaration *v = s->isVarDeclaration(); 3589: assert(v); 3590: assert(!v->isThisDeclaration()); 3591: 3592: if (v->offset < offset) 3593: { e = NULL; 3594: sd->hasUnions = 1; 3595: } 3596: else 3597: { 3598: if (v->init) 3599: { if (v->init->isVoidInitializer()) 3600: e = NULL; 3601: else 3602: { e = v->init->toExpression(); 3603: if (!e) 3604: { error("cannot make expression out of initializer for %s", v->toChars()); 3605: return new ErrorExp(); 3606: } 3607: else if (v->scope) 3608: { // Do deferred semantic analysis 3609: Initializer *i2 = v->init->syntaxCopy(); 3610: i2 = i2->semantic(v->scope, v->type, WANTinterpret); 3611: e = i2->toExpression(); 3612: v->scope = NULL; 3613: } 3614: } 3615: } 3616: else 3617: e = v->type->defaultInitLiteral(loc); 3618: offset = v->offset + v->type->size();
warning C4244: '=' : conversion from 'd_uns64' to 'size_t', possible loss of data
3619: } 3620: elements->push(e); 3621: } 3622: 3623: type = stype ? stype : sd->type; 3624: 3625: /* If struct requires a destructor, rewrite as: 3626: * (S tmp = S()),tmp 3627: * so that the destructor can be hung on tmp. 3628: */ 3629: if (sd->dtor) 3630: { 3631: Identifier *idtmp = Lexer::uniqueId("__sl"); 3632: VarDeclaration *tmp = new VarDeclaration(loc, type, idtmp, new ExpInitializer(0, this)); 3633: tmp->storage_class |= STCctfe; 3634: Expression *ae = new DeclarationExp(loc, tmp); 3635: Expression *e = new CommaExp(loc, ae, new VarExp(loc, tmp));
warning C6246: Local declaration of 'e' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '3534' of 'c:\projects\extern\d\dmd\src\expression.c': Lines: 3534
3636: e = e->semantic(sc); 3637: return e; 3638: } 3639: 3640: return this; 3641: } 3642: 3643: /************************************** 3644: * Gets expression at offset of type. 3645: * Returns NULL if not found. 3646: */ 3647: 3648: Expression *StructLiteralExp::getField(Type *type, unsigned offset) 3649: { 3650: //printf("StructLiteralExp::getField(this = %s, type = %s, offset = %u)\n", 3651: // /*toChars()*/"", type->toChars(), offset); 3652: Expression *e = NULL; 3653: int i = getFieldIndex(type, offset); 3654: 3655: if (i != -1) 3656: { 3657: //printf("\ti = %d\n", i); 3658: assert(i < elements->dim);
warning C4018: '<' : signed/unsigned mismatch
3659: e = elements->tdata()[i]; 3660: if (e) 3661: { 3662: //printf("e = %s, e->type = %s\n", e->toChars(), e->type->toChars()); 3663: 3664: /* If type is a static array, and e is an initializer for that array, 3665: * then the field initializer should be an array literal of e. 3666: */ 3667: if (e->type->castMod(0) != type->castMod(0) && type->ty == Tsarray) 3668: { TypeSArray *tsa = (TypeSArray *)type; 3669: uinteger_t length = tsa->dim->toInteger(); 3670: Expressions *z = new Expressions; 3671: z->setDim(length);
warning C4244: 'argument' : conversion from 'uinteger_t' to 'unsigned int', possible loss of data
3672: for (int q = 0; q < length; ++q) 3673: z->tdata()[q] = e->copy(); 3674: e = new ArrayLiteralExp(loc, z); 3675: e->type = type; 3676: } 3677: else 3678: { 3679: e = e->copy(); 3680: e->type = type; 3681: } 3682: } 3683: } 3684: return e; 3685: } 3686: 3687: /************************************ 3688: * Get index of field. 3689: * Returns -1 if not found. 3690: */ 3691: 3692: int StructLiteralExp::getFieldIndex(Type *type, unsigned offset) 3693: { 3694: /* Find which field offset is by looking at the field offsets 3695: */ 3696: if (elements->dim) 3697: { 3698: for (size_t i = 0; i < sd->fields.dim; i++) 3699: { 3700: Dsymbol *s = sd->fields.tdata()[i]; 3701: VarDeclaration *v = s->isVarDeclaration(); 3702: assert(v); 3703: 3704: if (offset == v->offset && 3705: type->size() == v->type->size()) 3706: { Expression *e = elements->tdata()[i]; 3707: if (e) 3708: { 3709: return i; 3710: } 3711: break; 3712: } 3713: } 3714: } 3715: return -1; 3716: } 3717: 3718: #if DMDV2 3719: int StructLiteralExp::isLvalue() 3720: { 3721: return 1; 3722: } 3723: #endif 3724: 3725: Expression *StructLiteralExp::toLvalue(Scope *sc, Expression *e) 3726: { 3727: return this; 3728: } 3729: 3730: 3731: int StructLiteralExp::checkSideEffect(int flag) 3732: { int f = 0; 3733: 3734: for (size_t i = 0; i < elements->dim; i++) 3735: { Expression *e = elements->tdata()[i]; 3736: if (!e) 3737: continue; 3738: 3739: f |= e->checkSideEffect(2); 3740: } 3741: if (flag == 0 && f == 0) 3742: Expression::checkSideEffect(0); 3743: return f; 3744: } 3745: 3746: #if DMDV2 3747: int StructLiteralExp::canThrow(bool mustNotThrow) 3748: { 3749: return arrayExpressionCanThrow(elements, mustNotThrow); 3750: } 3751: #endif 3752: 3753: void StructLiteralExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 3754: { 3755: buf->writestring(sd->toChars()); 3756: buf->writeByte('('); 3757: argsToCBuffer(buf, elements, hgs); 3758: buf->writeByte(')'); 3759: } 3760: 3761: void StructLiteralExp::toMangleBuffer(OutBuffer *buf) 3762: { 3763: size_t dim = elements ? elements->dim : 0; 3764: buf->printf("S%u", dim); 3765: for (size_t i = 0; i < dim; i++) 3766: { Expression *e = elements->tdata()[i]; 3767: if (e) 3768: e->toMangleBuffer(buf); 3769: else 3770: buf->writeByte('v'); // 'v' for void 3771: } 3772: } 3773: 3774: /************************ TypeDotIdExp ************************************/ 3775: 3776: /* Things like: 3777: * int.size 3778: * foo.size 3779: * (foo).size 3780: * cast(foo).size 3781: */ 3782: 3783: Expression *typeDotIdExp(Loc loc, Type *type, Identifier *ident) 3784: { 3785: return new DotIdExp(loc, new TypeExp(loc, type), ident); 3786: } 3787: 3788: 3789: /************************************************************/ 3790: 3791: // Mainly just a placeholder 3792: 3793: TypeExp::TypeExp(Loc loc, Type *type) 3794: : Expression(loc, TOKtype, sizeof(TypeExp)) 3795: { 3796: //printf("TypeExp::TypeExp(%s)\n", type->toChars()); 3797: this->type = type; 3798: } 3799: 3800: Expression *TypeExp::syntaxCopy() 3801: { 3802: //printf("TypeExp::syntaxCopy()\n"); 3803: return new TypeExp(loc, type->syntaxCopy()); 3804: } 3805: 3806: Expression *TypeExp::semantic(Scope *sc) 3807: { 3808: //printf("TypeExp::semantic(%s)\n", type->toChars()); 3809: type = type->semantic(loc, sc); 3810: return this; 3811: } 3812: 3813: void TypeExp::rvalue() 3814: { 3815: error("type %s has no value", toChars()); 3816: } 3817: 3818: void TypeExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 3819: { 3820: type->toCBuffer(buf, NULL, hgs); 3821: } 3822: 3823: /************************************************************/ 3824: 3825: // Mainly just a placeholder 3826: 3827: ScopeExp::ScopeExp(Loc loc, ScopeDsymbol *pkg) 3828: : Expression(loc, TOKimport, sizeof(ScopeExp)) 3829: { 3830: //printf("ScopeExp::ScopeExp(pkg = '%s')\n", pkg->toChars()); 3831: //static int count; if (++count == 38) *(char*)0=0; 3832: this->sds = pkg; 3833: } 3834: 3835: Expression *ScopeExp::syntaxCopy() 3836: { 3837: ScopeExp *se = new ScopeExp(loc, (ScopeDsymbol *)sds->syntaxCopy(NULL)); 3838: return se; 3839: } 3840: 3841: Expression *ScopeExp::semantic(Scope *sc) 3842: { 3843: TemplateInstance *ti; 3844: ScopeDsymbol *sds2; 3845: 3846: #if LOGSEMANTIC 3847: printf("+ScopeExp::semantic('%s')\n", toChars()); 3848: #endif 3849: Lagain: 3850: ti = sds->isTemplateInstance(); 3851: if (ti && !global.errors) 3852: { 3853: if (!ti->semanticRun) 3854: ti->semantic(sc); 3855: if (ti->inst) 3856: { 3857: Dsymbol *s = ti->inst->toAlias(); 3858: sds2 = s->isScopeDsymbol(); 3859: if (!sds2) 3860: { Expression *e; 3861: 3862: //printf("s = %s, '%s'\n", s->kind(), s->toChars()); 3863: if (ti->withsym) 3864: { 3865: // Same as wthis.s 3866: e = new VarExp(loc, ti->withsym->withstate->wthis); 3867: e = new DotVarExp(loc, e, s->isDeclaration()); 3868: } 3869: else 3870: e = new DsymbolExp(loc, s); 3871: e = e->semantic(sc); 3872: //printf("-1ScopeExp::semantic()\n"); 3873: return e; 3874: } 3875: if (sds2 != sds) 3876: { 3877: sds = sds2; 3878: goto Lagain; 3879: } 3880: //printf("sds = %s, '%s'\n", sds->kind(), sds->toChars()); 3881: } 3882: if (global.errors) 3883: return new ErrorExp(); 3884: } 3885: else 3886: { 3887: //printf("sds = %s, '%s'\n", sds->kind(), sds->toChars()); 3888: //printf("\tparent = '%s'\n", sds->parent->toChars()); 3889: sds->semantic(sc); 3890: } 3891: type = Type::tvoid; 3892: //printf("-2ScopeExp::semantic() %s\n", toChars()); 3893: return this; 3894: } 3895: 3896: void ScopeExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 3897: { 3898: if (sds->isTemplateInstance()) 3899: { 3900: sds->toCBuffer(buf, hgs); 3901: } 3902: else 3903: { 3904: buf->writestring(sds->kind()); 3905: buf->writestring(" "); 3906: buf->writestring(sds->toChars()); 3907: } 3908: } 3909: 3910: /********************** TemplateExp **************************************/ 3911: 3912: // Mainly just a placeholder 3913: 3914: TemplateExp::TemplateExp(Loc loc, TemplateDeclaration *td) 3915: : Expression(loc, TOKtemplate, sizeof(TemplateExp)) 3916: { 3917: //printf("TemplateExp(): %s\n", td->toChars()); 3918: this->td = td; 3919: } 3920: 3921: void TemplateExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 3922: { 3923: buf->writestring(td->toChars()); 3924: } 3925: 3926: void TemplateExp::rvalue() 3927: { 3928: error("template %s has no value", toChars()); 3929: } 3930: 3931: /********************** NewExp **************************************/ 3932: 3933: /* thisexp.new(newargs) newtype(arguments) */ 3934: 3935: NewExp::NewExp(Loc loc, Expression *thisexp, Expressions *newargs, 3936: Type *newtype, Expressions *arguments) 3937: : Expression(loc, TOKnew, sizeof(NewExp)) 3938: { 3939: this->thisexp = thisexp; 3940: this->newargs = newargs; 3941: this->newtype = newtype; 3942: this->arguments = arguments; 3943: member = NULL; 3944: allocator = NULL; 3945: onstack = 0; 3946: } 3947: 3948: Expression *NewExp::syntaxCopy() 3949: { 3950: return new NewExp(loc, 3951: thisexp ? thisexp->syntaxCopy() : NULL, 3952: arraySyntaxCopy(newargs), 3953: newtype->syntaxCopy(), arraySyntaxCopy(arguments)); 3954: } 3955: 3956: 3957: Expression *NewExp::semantic(Scope *sc) 3958: { int i;
warning C4101: 'i' : unreferenced local variable
3959: Type *tb; 3960: ClassDeclaration *cdthis = NULL; 3961: 3962: #if LOGSEMANTIC 3963: printf("NewExp::semantic() %s\n", toChars()); 3964: if (thisexp) 3965: printf("\tthisexp = %s\n", thisexp->toChars()); 3966: printf("\tnewtype: %s\n", newtype->toChars()); 3967: #endif 3968: if (type) // if semantic() already run 3969: return this; 3970: 3971: Lagain: 3972: if (thisexp) 3973: { thisexp = thisexp->semantic(sc); 3974: cdthis = thisexp->type->isClassHandle(); 3975: if (cdthis) 3976: { 3977: sc = sc->push(cdthis); 3978: type = newtype->semantic(loc, sc); 3979: sc = sc->pop(); 3980: } 3981: else 3982: { 3983: error("'this' for nested class must be a class type, not %s", thisexp->type->toChars()); 3984: goto Lerr; 3985: } 3986: } 3987: else 3988: type = newtype->semantic(loc, sc); 3989: newtype = type; // in case type gets cast to something else 3990: tb = type->toBasetype(); 3991: //printf("tb: %s, deco = %s\n", tb->toChars(), tb->deco); 3992: 3993: arrayExpressionSemantic(newargs, sc); 3994: preFunctionParameters(loc, sc, newargs); 3995: arrayExpressionSemantic(arguments, sc); 3996: preFunctionParameters(loc, sc, arguments); 3997: 3998: if (thisexp && tb->ty != Tclass) 3999: { error("e.new is only for allocating nested classes, not %s", tb->toChars()); 4000: goto Lerr; 4001: } 4002: 4003: if (tb->ty == Tclass) 4004: { 4005: TypeClass *tc = (TypeClass *)(tb); 4006: ClassDeclaration *cd = tc->sym->isClassDeclaration(); 4007: if (cd->isInterfaceDeclaration()) 4008: { error("cannot create instance of interface %s", cd->toChars()); 4009: goto Lerr; 4010: } 4011: else if (cd->isAbstract()) 4012: { error("cannot create instance of abstract class %s", cd->toChars()); 4013: for (int i = 0; i < cd->vtbl.dim; i++)
warning C4018: '<' : signed/unsigned mismatch
warning C6246: Local declaration of 'i' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '3958' of 'c:\projects\extern\d\dmd\src\expression.c': Lines: 3958
4014: { FuncDeclaration *fd = cd->vtbl.tdata()[i]->isFuncDeclaration(); 4015: if (fd && fd->isAbstract()) 4016: error("function %s is abstract", fd->toChars()); 4017: } 4018: goto Lerr; 4019: } 4020: 4021: if (cd->noDefaultCtor && (!arguments || !arguments->dim)) 4022: error("default construction is disabled for type %s", cd->toChars()); 4023: 4024: checkDeprecated(sc, cd); 4025: if (cd->isNested()) 4026: { /* We need a 'this' pointer for the nested class. 4027: * Ensure we have the right one. 4028: */ 4029: Dsymbol *s = cd->toParent2(); 4030: ClassDeclaration *cdn = s->isClassDeclaration(); 4031: FuncDeclaration *fdn = s->isFuncDeclaration(); 4032: 4033: //printf("cd isNested, cdn = %s\n", cdn ? cdn->toChars() : "null"); 4034: if (cdn) 4035: { 4036: if (!cdthis) 4037: { 4038: // Supply an implicit 'this' and try again 4039: thisexp = new ThisExp(loc); 4040: for (Dsymbol *sp = sc->parent; 1; sp = sp->parent) 4041: { if (!sp) 4042: { 4043: error("outer class %s 'this' needed to 'new' nested class %s", cdn->toChars(), cd->toChars()); 4044: goto Lerr; 4045: } 4046: ClassDeclaration *cdp = sp->isClassDeclaration(); 4047: if (!cdp) 4048: continue; 4049: if (cdp == cdn || cdn->isBaseOf(cdp, NULL)) 4050: break; 4051: // Add a '.outer' and try again 4052: thisexp = new DotIdExp(loc, thisexp, Id::outer); 4053: } 4054: if (!global.errors) 4055: goto Lagain; 4056: } 4057: if (cdthis) 4058: { 4059: //printf("cdthis = %s\n", cdthis->toChars()); 4060: if (cdthis != cdn && !cdn->isBaseOf(cdthis, NULL)) 4061: { error("'this' for nested class must be of type %s, not %s", cdn->toChars(), thisexp->type->toChars()); 4062: goto Lerr; 4063: } 4064: } 4065: #if 0 4066: else 4067: { 4068: for (Dsymbol *sf = sc->func; 1; sf= sf->toParent2()->isFuncDeclaration()) 4069: { 4070: if (!sf) 4071: { 4072: error("outer class %s 'this' needed to 'new' nested class %s", cdn->toChars(), cd->toChars()); 4073: goto Lerr; 4074: } 4075: printf("sf = %s\n", sf->toChars()); 4076: AggregateDeclaration *ad = sf->isThis(); 4077: if (ad && (ad == cdn || cdn->isBaseOf(ad->isClassDeclaration(), NULL))) 4078: break; 4079: } 4080: } 4081: #endif 4082: } 4083: #if 1 4084: else if (thisexp) 4085: { error("e.new is only for allocating nested classes"); 4086: goto Lerr; 4087: } 4088: else if (fdn) 4089: { 4090: // make sure the parent context fdn of cd is reachable from sc 4091: for (Dsymbol *sp = sc->parent; 1; sp = sp->parent) 4092: { 4093: if (fdn == sp) 4094: break; 4095: FuncDeclaration *fsp = sp ? sp->isFuncDeclaration() : NULL; 4096: if (!sp || (fsp && fsp->isStatic())) 4097: { 4098: error("outer function context of %s is needed to 'new' nested class %s", fdn->toPrettyChars(), cd->toPrettyChars()); 4099: goto Lerr; 4100: } 4101: } 4102: } 4103: #else 4104: else if (fdn) 4105: { /* The nested class cd is nested inside a function, 4106: * we'll let getEthis() look for errors. 4107: */ 4108: //printf("nested class %s is nested inside function %s, we're in %s\n", cd->toChars(), fdn->toChars(), sc->func->toChars()); 4109: if (thisexp) 4110: { // Because thisexp cannot be a function frame pointer 4111: error("e.new is only for allocating nested classes"); 4112: goto Lerr; 4113: } 4114: } 4115: #endif 4116: else 4117: assert(0); 4118: } 4119: else if (thisexp) 4120: { error("e.new is only for allocating nested classes"); 4121: goto Lerr; 4122: } 4123: 4124: FuncDeclaration *f = NULL; 4125: if (cd->ctor) 4126: f = resolveFuncCall(sc, loc, cd->ctor, NULL, NULL, arguments, 0); 4127: if (f) 4128: { 4129: checkDeprecated(sc, f); 4130: member = f->isCtorDeclaration(); 4131: assert(member); 4132: 4133: cd->accessCheck(loc, sc, member); 4134: 4135: TypeFunction *tf = (TypeFunction *)f->type; 4136: 4137: if (!arguments) 4138: arguments = new Expressions(); 4139: functionParameters(loc, sc, tf, arguments, f); 4140: 4141: type = type->addMod(tf->nextOf()->mod); 4142: } 4143: else 4144: { 4145: if (arguments && arguments->dim) 4146: { error("no constructor for %s", cd->toChars()); 4147: goto Lerr; 4148: } 4149: } 4150: 4151: if (cd->aggNew) 4152: { 4153: // Prepend the size argument to newargs[] 4154: Expression *e = new IntegerExp(loc, cd->size(loc), Type::tsize_t); 4155: if (!newargs) 4156: newargs = new Expressions(); 4157: newargs->shift(e); 4158: 4159: f = cd->aggNew->overloadResolve(loc, NULL, newargs); 4160: allocator = f->isNewDeclaration(); 4161: assert(allocator); 4162: 4163: TypeFunction *tf = (TypeFunction *)f->type; 4164: functionParameters(loc, sc, tf, newargs, f); 4165: } 4166: else 4167: { 4168: if (newargs && newargs->dim) 4169: { error("no allocator for %s", cd->toChars()); 4170: goto Lerr; 4171: } 4172: } 4173: } 4174: else if (tb->ty == Tstruct) 4175: { 4176: TypeStruct *ts = (TypeStruct *)tb; 4177: StructDeclaration *sd = ts->sym; 4178: TypeFunction *tf; 4179: 4180: if (sd->noDefaultCtor && (!arguments || !arguments->dim)) 4181: error("default construction is disabled for type %s", sd->toChars()); 4182: 4183: FuncDeclaration *f = NULL; 4184: if (sd->ctor) 4185: f = resolveFuncCall(sc, loc, sd->ctor, NULL, NULL, arguments, 0); 4186: if (f) 4187: { 4188: checkDeprecated(sc, f); 4189: member = f->isCtorDeclaration(); 4190: assert(member); 4191: 4192: sd->accessCheck(loc, sc, member); 4193: 4194: tf = (TypeFunction *)f->type; 4195: type = tf->next; 4196: 4197: if (!arguments) 4198: arguments = new Expressions(); 4199: functionParameters(loc, sc, tf, arguments, f); 4200: } 4201: else 4202: { 4203: if (arguments && arguments->dim) 4204: { error("no constructor for %s", sd->toChars()); 4205: goto Lerr; 4206: } 4207: } 4208: 4209: 4210: if (sd->aggNew) 4211: { 4212: // Prepend the uint size argument to newargs[] 4213: Expression *e = new IntegerExp(loc, sd->size(loc), Type::tuns32); 4214: if (!newargs) 4215: newargs = new Expressions(); 4216: newargs->shift(e); 4217: 4218: f = sd->aggNew->overloadResolve(loc, NULL, newargs); 4219: allocator = f->isNewDeclaration(); 4220: assert(allocator); 4221: 4222: tf = (TypeFunction *)f->type; 4223: functionParameters(loc, sc, tf, newargs, f); 4224: #if 0 4225: e = new VarExp(loc, f); 4226: e = new CallExp(loc, e, newargs); 4227: e = e->semantic(sc); 4228: e->type = type->pointerTo(); 4229: return e; 4230: #endif 4231: } 4232: else 4233: { 4234: if (newargs && newargs->dim) 4235: { error("no allocator for %s", sd->toChars()); 4236: goto Lerr; 4237: } 4238: } 4239: 4240: type = type->pointerTo(); 4241: } 4242: else if (tb->ty == Tarray && (arguments && arguments->dim)) 4243: { 4244: for (size_t i = 0; i < arguments->dim; i++)
warning C6246: Local declaration of 'i' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '3958' of 'c:\projects\extern\d\dmd\src\expression.c': Lines: 3958
4245: { 4246: if (tb->ty != Tarray) 4247: { error("too many arguments for array"); 4248: goto Lerr; 4249: } 4250: 4251: Expression *arg = arguments->tdata()[i]; 4252: arg = resolveProperties(sc, arg); 4253: arg = arg->implicitCastTo(sc, Type::tsize_t); 4254: arg = arg->optimize(WANTvalue); 4255: if (arg->op == TOKint64 && (sinteger_t)arg->toInteger() < 0) 4256: { error("negative array index %s", arg->toChars()); 4257: goto Lerr; 4258: } 4259: arguments->tdata()[i] = arg; 4260: tb = ((TypeDArray *)tb)->next->toBasetype(); 4261: } 4262: } 4263: else if (tb->isscalar()) 4264: { 4265: if (arguments && arguments->dim) 4266: { error("no constructor for %s", type->toChars()); 4267: goto Lerr; 4268: } 4269: 4270: type = type->pointerTo(); 4271: } 4272: else 4273: { 4274: error("new can only create structs, dynamic arrays or class objects, not %s's", type->toChars()); 4275: goto Lerr; 4276: } 4277: 4278: //printf("NewExp: '%s'\n", toChars()); 4279: //printf("NewExp:type '%s'\n", type->toChars()); 4280: 4281: return this; 4282: 4283: Lerr: 4284: return new ErrorExp(); 4285: } 4286: 4287: int NewExp::checkSideEffect(int flag) 4288: { 4289: return 1; 4290: } 4291: 4292: #if DMDV2 4293: int NewExp::canThrow(bool mustNotThrow) 4294: { 4295: if (arrayExpressionCanThrow(newargs, mustNotThrow) || 4296: arrayExpressionCanThrow(arguments, mustNotThrow)) 4297: return 1; 4298: if (member) 4299: { 4300: // See if constructor call can throw 4301: Type *t = member->type->toBasetype(); 4302: if (t->ty == Tfunction && !((TypeFunction *)t)->isnothrow) 4303: { 4304: if (mustNotThrow) 4305: error("constructor %s is not nothrow", member->toChars()); 4306: return 1; 4307: } 4308: } 4309: // regard storage allocation failures as not recoverable 4310: return 0; 4311: } 4312: #endif 4313: 4314: void NewExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 4315: { int i;
warning C4101: 'i' : unreferenced local variable
4316: 4317: if (thisexp) 4318: { expToCBuffer(buf, hgs, thisexp, PREC_primary); 4319: buf->writeByte('.'); 4320: } 4321: buf->writestring("new "); 4322: if (newargs && newargs->dim) 4323: { 4324: buf->writeByte('('); 4325: argsToCBuffer(buf, newargs, hgs); 4326: buf->writeByte(')'); 4327: } 4328: newtype->toCBuffer(buf, NULL, hgs); 4329: if (arguments && arguments->dim) 4330: { 4331: buf->writeByte('('); 4332: argsToCBuffer(buf, arguments, hgs); 4333: buf->writeByte(')'); 4334: } 4335: } 4336: 4337: /********************** NewAnonClassExp **************************************/ 4338: 4339: NewAnonClassExp::NewAnonClassExp(Loc loc, Expression *thisexp, 4340: Expressions *newargs, ClassDeclaration *cd, Expressions *arguments) 4341: : Expression(loc, TOKnewanonclass, sizeof(NewAnonClassExp)) 4342: { 4343: this->thisexp = thisexp; 4344: this->newargs = newargs; 4345: this->cd = cd; 4346: this->arguments = arguments; 4347: } 4348: 4349: Expression *NewAnonClassExp::syntaxCopy() 4350: { 4351: return new NewAnonClassExp(loc, 4352: thisexp ? thisexp->syntaxCopy() : NULL, 4353: arraySyntaxCopy(newargs), 4354: (ClassDeclaration *)cd->syntaxCopy(NULL), 4355: arraySyntaxCopy(arguments)); 4356: } 4357: 4358: 4359: Expression *NewAnonClassExp::semantic(Scope *sc) 4360: { 4361: #if LOGSEMANTIC 4362: printf("NewAnonClassExp::semantic() %s\n", toChars()); 4363: //printf("thisexp = %p\n", thisexp); 4364: //printf("type: %s\n", type->toChars()); 4365: #endif 4366: 4367: Expression *d = new DeclarationExp(loc, cd);
warning C6211: Leaking memory 'd' due to an exception. Consider using a local catch block to clean up memory: Lines: 4367, 4368, 4370
4368: d = d->semantic(sc); 4369: 4370: Expression *n = new NewExp(loc, thisexp, newargs, cd->type, arguments); 4371: 4372: Expression *c = new CommaExp(loc, d, n); 4373: return c->semantic(sc); 4374: } 4375: 4376: int NewAnonClassExp::checkSideEffect(int flag) 4377: { 4378: return 1; 4379: } 4380: 4381: #if DMDV2 4382: int NewAnonClassExp::canThrow(bool mustNotThrow) 4383: { 4384: assert(0); // should have been lowered by semantic() 4385: return 1; 4386: } 4387: #endif 4388: 4389: void NewAnonClassExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 4390: { int i;
warning C4101: 'i' : unreferenced local variable
4391: 4392: if (thisexp) 4393: { expToCBuffer(buf, hgs, thisexp, PREC_primary); 4394: buf->writeByte('.'); 4395: } 4396: buf->writestring("new"); 4397: if (newargs && newargs->dim) 4398: { 4399: buf->writeByte('('); 4400: argsToCBuffer(buf, newargs, hgs); 4401: buf->writeByte(')'); 4402: } 4403: buf->writestring(" class "); 4404: if (arguments && arguments->dim) 4405: { 4406: buf->writeByte('('); 4407: argsToCBuffer(buf, arguments, hgs); 4408: buf->writeByte(')'); 4409: } 4410: //buf->writestring(" { }"); 4411: if (cd) 4412: { 4413: cd->toCBuffer(buf, hgs); 4414: } 4415: } 4416: 4417: /********************** SymbolExp **************************************/ 4418: 4419: #if DMDV2 4420: SymbolExp::SymbolExp(Loc loc, enum TOK op, int size, Declaration *var, int hasOverloads) 4421: : Expression(loc, op, size) 4422: { 4423: assert(var); 4424: this->var = var; 4425: this->hasOverloads = hasOverloads; 4426: } 4427: #endif 4428: 4429: /********************** SymOffExp **************************************/ 4430: 4431: SymOffExp::SymOffExp(Loc loc, Declaration *var, unsigned offset, int hasOverloads) 4432: : SymbolExp(loc, TOKsymoff, sizeof(SymOffExp), var, hasOverloads) 4433: { 4434: this->offset = offset; 4435: VarDeclaration *v = var->isVarDeclaration(); 4436: if (v && v->needThis()) 4437: error("need 'this' for address of %s", v->toChars()); 4438: } 4439: 4440: Expression *SymOffExp::semantic(Scope *sc) 4441: { 4442: #if LOGSEMANTIC 4443: printf("SymOffExp::semantic('%s')\n", toChars()); 4444: #endif 4445: //var->semantic(sc); 4446: if (!type) 4447: type = var->type->pointerTo(); 4448: VarDeclaration *v = var->isVarDeclaration(); 4449: if (v) 4450: v->checkNestedReference(sc, loc); 4451: return this; 4452: } 4453: 4454: int SymOffExp::isBool(int result) 4455: { 4456: return result ? TRUE : FALSE; 4457: } 4458: 4459: void SymOffExp::checkEscape() 4460: { 4461: VarDeclaration *v = var->isVarDeclaration(); 4462: if (v) 4463: { 4464: if (!v->isDataseg() && !(v->storage_class & (STCref | STCout))) 4465: { /* BUG: This should be allowed: 4466: * void foo() 4467: * { int a; 4468: * int* bar() { return &a; } 4469: * } 4470: */ 4471: error("escaping reference to local %s", v->toChars()); 4472: } 4473: } 4474: } 4475: 4476: void SymOffExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 4477: { 4478: if (offset) 4479: buf->printf("(& %s+%u)", var->toChars(), offset); 4480: else 4481: buf->printf("& %s", var->toChars()); 4482: } 4483: 4484: /******************************** VarExp **************************/ 4485: 4486: VarExp::VarExp(Loc loc, Declaration *var, int hasOverloads) 4487: : SymbolExp(loc, TOKvar, sizeof(VarExp), var, hasOverloads) 4488: { 4489: //printf("VarExp(this = %p, '%s', loc = %s)\n", this, var->toChars(), loc.toChars()); 4490: //if (strcmp(var->ident->toChars(), "func") == 0) halt(); 4491: this->type = var->type; 4492: } 4493: 4494: int VarExp::equals(Object *o) 4495: { VarExp *ne; 4496: 4497: if (this == o || 4498: (((Expression *)o)->op == TOKvar && 4499: ((ne = (VarExp *)o), type->toHeadMutable()->equals(ne->type->toHeadMutable())) && 4500: var == ne->var)) 4501: return 1; 4502: return 0; 4503: } 4504: 4505: Expression *VarExp::semantic(Scope *sc) 4506: { FuncLiteralDeclaration *fd;
warning C4101: 'fd' : unreferenced local variable
4507: 4508: #if LOGSEMANTIC 4509: printf("VarExp::semantic(%s)\n", toChars()); 4510: #endif 4511: // if (var->sem == SemanticStart && var->scope) // if forward referenced 4512: // var->semantic(sc); 4513: if (!type) 4514: { type = var->type; 4515: #if 0 4516: if (var->storage_class & STClazy) 4517: { 4518: TypeFunction *tf = new TypeFunction(NULL, type, 0, LINKd); 4519: type = new TypeDelegate(tf); 4520: type = type->semantic(loc, sc); 4521: } 4522: #endif 4523: } 4524: 4525: if (type && !type->deco) 4526: type = type->semantic(loc, sc); 4527: 4528: /* Fix for 1161 doesn't work because it causes protection 4529: * problems when instantiating imported templates passing private 4530: * variables as alias template parameters. 4531: */ 4532: //accessCheck(loc, sc, NULL, var); 4533: 4534: VarDeclaration *v = var->isVarDeclaration(); 4535: if (v) 4536: { 4537: v->checkNestedReference(sc, loc); 4538: #if DMDV2 4539: checkPurity(sc, v, NULL); 4540: #endif 4541: } 4542: #if 0 4543: else if ((fd = var->isFuncLiteralDeclaration()) != NULL) 4544: { Expression *e; 4545: e = new FuncExp(loc, fd); 4546: e->type = type; 4547: return e; 4548: } 4549: #endif 4550: 4551: return this; 4552: } 4553: 4554: char *VarExp::toChars() 4555: { 4556: return var->toChars(); 4557: } 4558: 4559: void VarExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 4560: { 4561: buf->writestring(var->toChars()); 4562: } 4563: 4564: void VarExp::checkEscape() 4565: { 4566: VarDeclaration *v = var->isVarDeclaration(); 4567: if (v) 4568: { Type *tb = v->type->toBasetype(); 4569: // if reference type 4570: if (tb->ty == Tarray || tb->ty == Tsarray || tb->ty == Tclass) 4571: { 4572: if (v->isScope() && !v->noscope) 4573: error("escaping reference to scope local %s", v->toChars()); 4574: else if (v->storage_class & STCvariadic) 4575: error("escaping reference to variadic parameter %s", v->toChars()); 4576: } 4577: } 4578: } 4579: 4580: void VarExp::checkEscapeRef() 4581: { 4582: VarDeclaration *v = var->isVarDeclaration(); 4583: if (v) 4584: { 4585: if (!v->isDataseg() && !(v->storage_class & (STCref | STCout))) 4586: error("escaping reference to local variable %s", v->toChars()); 4587: } 4588: } 4589: 4590: #if DMDV2 4591: int VarExp::isLvalue() 4592: { 4593: if (var->storage_class & STClazy) 4594: return 0; 4595: return 1; 4596: } 4597: #endif 4598: 4599: Expression *VarExp::toLvalue(Scope *sc, Expression *e) 4600: { 4601: #if 0 4602: tym = tybasic(e1->ET->Tty); 4603: if (!(tyscalar(tym) || 4604: tym == TYstruct || 4605: tym == TYarray && e->Eoper == TOKaddr)) 4606: synerr(EM_lvalue); // lvalue expected 4607: #endif 4608: if (var->storage_class & STClazy) 4609: { error("lazy variables cannot be lvalues"); 4610: return new ErrorExp(); 4611: } 4612: return this; 4613: } 4614: 4615: Expression *VarExp::modifiableLvalue(Scope *sc, Expression *e) 4616: { 4617: //printf("VarExp::modifiableLvalue('%s')\n", var->toChars()); 4618: //if (type && type->toBasetype()->ty == Tsarray) 4619: //error("cannot change reference to static array '%s'", var->toChars()); 4620: 4621: var->checkModify(loc, sc, type); 4622: 4623: // See if this expression is a modifiable lvalue (i.e. not const) 4624: return toLvalue(sc, e); 4625: } 4626: 4627: 4628: /******************************** OverExp **************************/ 4629: 4630: #if DMDV2 4631: OverExp::OverExp(OverloadSet *s) 4632: : Expression(loc, TOKoverloadset, sizeof(OverExp)) 4633: { 4634: //printf("OverExp(this = %p, '%s')\n", this, var->toChars()); 4635: vars = s; 4636: type = Type::tvoid; 4637: } 4638: 4639: int OverExp::isLvalue() 4640: { 4641: return 1; 4642: } 4643: 4644: Expression *OverExp::toLvalue(Scope *sc, Expression *e) 4645: { 4646: return this; 4647: } 4648: #endif 4649: 4650: 4651: /******************************** TupleExp **************************/ 4652: 4653: TupleExp::TupleExp(Loc loc, Expressions *exps) 4654: : Expression(loc, TOKtuple, sizeof(TupleExp)) 4655: { 4656: //printf("TupleExp(this = %p)\n", this); 4657: this->exps = exps; 4658: this->type = NULL; 4659: } 4660: 4661: 4662: TupleExp::TupleExp(Loc loc, TupleDeclaration *tup) 4663: : Expression(loc, TOKtuple, sizeof(TupleExp)) 4664: { 4665: exps = new Expressions(); 4666: type = NULL; 4667: 4668: exps->reserve(tup->objects->dim); 4669: for (size_t i = 0; i < tup->objects->dim; i++) 4670: { Object *o = tup->objects->tdata()[i]; 4671: if (o->dyncast() == DYNCAST_EXPRESSION) 4672: { 4673: Expression *e = (Expression *)o; 4674: if (e->op == TOKdsymbol) 4675: e = e->syntaxCopy(); 4676: exps->push(e); 4677: } 4678: else if (o->dyncast() == DYNCAST_DSYMBOL) 4679: { 4680: Dsymbol *s = (Dsymbol *)o; 4681: Expression *e = new DsymbolExp(loc, s); 4682: exps->push(e); 4683: } 4684: else if (o->dyncast() == DYNCAST_TYPE) 4685: { 4686: Type *t = (Type *)o; 4687: Expression *e = new TypeExp(loc, t); 4688: exps->push(e); 4689: } 4690: else 4691: { 4692: error("%s is not an expression", o->toChars()); 4693: } 4694: } 4695: } 4696: 4697: int TupleExp::equals(Object *o) 4698: { TupleExp *ne;
warning C4101: 'ne' : unreferenced local variable
4699: 4700: if (this == o) 4701: return 1; 4702: if (((Expression *)o)->op == TOKtuple) 4703: { 4704: TupleExp *te = (TupleExp *)o; 4705: if (exps->dim != te->exps->dim) 4706: return 0; 4707: for (size_t i = 0; i < exps->dim; i++) 4708: { Expression *e1 = (*exps)[i]; 4709: Expression *e2 = (*te->exps)[i]; 4710: 4711: if (!e1->equals(e2)) 4712: return 0; 4713: } 4714: return 1; 4715: } 4716: return 0; 4717: } 4718: 4719: Expression *TupleExp::syntaxCopy() 4720: { 4721: return new TupleExp(loc, arraySyntaxCopy(exps)); 4722: } 4723: 4724: Expression *TupleExp::semantic(Scope *sc) 4725: { 4726: #if LOGSEMANTIC 4727: printf("+TupleExp::semantic(%s)\n", toChars()); 4728: #endif 4729: if (type) 4730: return this; 4731: 4732: // Run semantic() on each argument 4733: for (size_t i = 0; i < exps->dim; i++) 4734: { Expression *e = (*exps)[i]; 4735: 4736: e = e->semantic(sc); 4737: if (!e->type) 4738: { error("%s has no value", e->toChars()); 4739: e = new ErrorExp(); 4740: } 4741: (*exps)[i] = e; 4742: } 4743: 4744: expandTuples(exps); 4745: if (0 && exps->dim == 1) 4746: { 4747: return (*exps)[0]; 4748: } 4749: type = new TypeTuple(exps); 4750: type = type->semantic(loc, sc); 4751: //printf("-TupleExp::semantic(%s)\n", toChars()); 4752: return this; 4753: } 4754: 4755: void TupleExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 4756: { 4757: buf->writestring("tuple("); 4758: argsToCBuffer(buf, exps, hgs); 4759: buf->writeByte(')'); 4760: } 4761: 4762: int TupleExp::checkSideEffect(int flag) 4763: { int f = 0; 4764: 4765: for (int i = 0; i < exps->dim; i++)
warning C4018: '<' : signed/unsigned mismatch
4766: { Expression *e = (*exps)[i]; 4767: 4768: f |= e->checkSideEffect(2); 4769: } 4770: if (flag == 0 && f == 0) 4771: Expression::checkSideEffect(0); 4772: return f; 4773: } 4774: 4775: #if DMDV2 4776: int TupleExp::canThrow(bool mustNotThrow) 4777: { 4778: return arrayExpressionCanThrow(exps, mustNotThrow); 4779: } 4780: #endif 4781: 4782: void TupleExp::checkEscape() 4783: { 4784: for (size_t i = 0; i < exps->dim; i++) 4785: { Expression *e = (*exps)[i]; 4786: e->checkEscape(); 4787: } 4788: } 4789: 4790: /******************************** FuncExp *********************************/ 4791: 4792: FuncExp::FuncExp(Loc loc, FuncLiteralDeclaration *fd) 4793: : Expression(loc, TOKfunction, sizeof(FuncExp)) 4794: { 4795: this->fd = fd; 4796: } 4797: 4798: Expression *FuncExp::syntaxCopy() 4799: { 4800: return new FuncExp(loc, (FuncLiteralDeclaration *)fd->syntaxCopy(NULL)); 4801: } 4802: 4803: Expression *FuncExp::semantic(Scope *sc) 4804: { 4805: #if LOGSEMANTIC 4806: printf("FuncExp::semantic(%s)\n", toChars()); 4807: #endif 4808: if (!type) 4809: { 4810: fd->semantic(sc); 4811: //fd->parent = sc->parent; 4812: if (global.errors) 4813: { 4814: } 4815: else 4816: { 4817: fd->semantic2(sc); 4818: if (!global.errors || 4819: // need to infer return type 4820: (fd->type && fd->type->ty == Tfunction && !fd->type->nextOf())) 4821: { 4822: fd->semantic3(sc); 4823: 4824: if (!global.errors && global.params.useInline) 4825: fd->inlineScan(); 4826: } 4827: } 4828: 4829: // need to infer return type 4830: if (global.errors && fd->type && fd->type->ty == Tfunction && !fd->type->nextOf()) 4831: ((TypeFunction *)fd->type)->next = Type::terror; 4832: 4833: // Type is a "delegate to" or "pointer to" the function literal 4834: if (fd->isNested()) 4835: { 4836: type = new TypeDelegate(fd->type); 4837: type = type->semantic(loc, sc); 4838: } 4839: else 4840: { 4841: type = fd->type->pointerTo();
warning C6011: Dereferencing NULL pointer 'fd->type': Lines: 4808, 4810, 4812, 4830, 4834, 4841
4842: } 4843: fd->tookAddressOf++; 4844: } 4845: return this; 4846: } 4847: 4848: char *FuncExp::toChars() 4849: { 4850: return fd->toChars(); 4851: } 4852: 4853: void FuncExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 4854: { 4855: fd->toCBuffer(buf, hgs); 4856: //buf->writestring(fd->toChars()); 4857: } 4858: 4859: 4860: /******************************** DeclarationExp **************************/ 4861: 4862: DeclarationExp::DeclarationExp(Loc loc, Dsymbol *declaration) 4863: : Expression(loc, TOKdeclaration, sizeof(DeclarationExp)) 4864: { 4865: this->declaration = declaration; 4866: } 4867: 4868: Expression *DeclarationExp::syntaxCopy() 4869: { 4870: return new DeclarationExp(loc, declaration->syntaxCopy(NULL)); 4871: } 4872: 4873: Expression *DeclarationExp::semantic(Scope *sc) 4874: { 4875: if (type) 4876: return this; 4877: 4878: #if LOGSEMANTIC 4879: printf("DeclarationExp::semantic() %s\n", toChars()); 4880: #endif 4881: 4882: /* This is here to support extern(linkage) declaration, 4883: * where the extern(linkage) winds up being an AttribDeclaration 4884: * wrapper. 4885: */ 4886: Dsymbol *s = declaration; 4887: 4888: AttribDeclaration *ad = declaration->isAttribDeclaration(); 4889: if (ad) 4890: { 4891: if (ad->decl && ad->decl->dim == 1) 4892: s = ad->decl->tdata()[0]; 4893: } 4894: 4895: if (s->isVarDeclaration()) 4896: { // Do semantic() on initializer first, so: 4897: // int a = a; 4898: // will be illegal. 4899: declaration->semantic(sc); 4900: s->parent = sc->parent; 4901: } 4902: 4903: //printf("inserting '%s' %p into sc = %p\n", s->toChars(), s, sc); 4904: // Insert into both local scope and function scope. 4905: // Must be unique in both. 4906: if (s->ident) 4907: { 4908: if (!sc->insert(s)) 4909: error("declaration %s is already defined", s->toPrettyChars()); 4910: else if (sc->func) 4911: { VarDeclaration *v = s->isVarDeclaration(); 4912: if ( (s->isFuncDeclaration() || s->isTypedefDeclaration() || 4913: s->isAggregateDeclaration() || s->isEnumDeclaration() || 4914: s->isInterfaceDeclaration()) && 4915: !sc->func->localsymtab->insert(s)) 4916: { 4917: error("declaration %s is already defined in another scope in %s", 4918: s->toPrettyChars(), sc->func->toChars()); 4919: } 4920: else if (!global.params.useDeprecated) 4921: { // Disallow shadowing 4922: 4923: for (Scope *scx = sc->enclosing; scx && scx->func == sc->func; scx = scx->enclosing) 4924: { Dsymbol *s2; 4925: 4926: if (scx->scopesym && scx->scopesym->symtab && 4927: (s2 = scx->scopesym->symtab->lookup(s->ident)) != NULL && 4928: s != s2) 4929: { 4930: error("shadowing declaration %s is deprecated", s->toPrettyChars()); 4931: } 4932: } 4933: } 4934: } 4935: } 4936: if (!s->isVarDeclaration()) 4937: { 4938: Scope *sc2 = sc; 4939: if (sc2->stc & (STCpure | STCnothrow)) 4940: sc2 = sc->push(); 4941: sc2->stc &= ~(STCpure | STCnothrow); 4942: declaration->semantic(sc2); 4943: if (sc2 != sc) 4944: sc2->pop(); 4945: s->parent = sc->parent; 4946: } 4947: if (!global.errors) 4948: { 4949: declaration->semantic2(sc); 4950: if (!global.errors) 4951: { 4952: declaration->semantic3(sc); 4953: 4954: if (!global.errors && global.params.useInline) 4955: declaration->inlineScan(); 4956: } 4957: } 4958: 4959: type = Type::tvoid; 4960: return this; 4961: } 4962: 4963: int DeclarationExp::checkSideEffect(int flag) 4964: { 4965: return 1; 4966: } 4967: 4968: #if DMDV2 4969: /************************************** 4970: * Does symbol, when initialized, throw? 4971: * Mirrors logic in Dsymbol_toElem(). 4972: */ 4973: 4974: int Dsymbol_canThrow(Dsymbol *s, bool mustNotThrow) 4975: { 4976: AttribDeclaration *ad; 4977: VarDeclaration *vd; 4978: TemplateMixin *tm; 4979: TupleDeclaration *td; 4980: 4981: //printf("Dsymbol_toElem() %s\n", s->toChars()); 4982: ad = s->isAttribDeclaration(); 4983: if (ad) 4984: { 4985: Dsymbols *decl = ad->include(NULL, NULL); 4986: if (decl && decl->dim) 4987: { 4988: for (size_t i = 0; i < decl->dim; i++) 4989: { 4990: s = decl->tdata()[i]; 4991: if (Dsymbol_canThrow(s, mustNotThrow)) 4992: return 1; 4993: } 4994: } 4995: } 4996: else if ((vd = s->isVarDeclaration()) != NULL) 4997: { 4998: s = s->toAlias(); 4999: if (s != vd) 5000: return Dsymbol_canThrow(s, mustNotThrow); 5001: if (vd->storage_class & STCmanifest) 5002: ; 5003: else if (vd->isStatic() || vd->storage_class & (STCextern | STCtls | STCgshared)) 5004: ; 5005: else 5006: { 5007: if (vd->init) 5008: { ExpInitializer *ie = vd->init->isExpInitializer(); 5009: if (ie && ie->exp->canThrow(mustNotThrow)) 5010: return 1; 5011: } 5012: if (vd->edtor && !vd->noscope) 5013: return vd->edtor->canThrow(mustNotThrow); 5014: } 5015: } 5016: else if ((tm = s->isTemplateMixin()) != NULL) 5017: { 5018: //printf("%s\n", tm->toChars()); 5019: if (tm->members) 5020: { 5021: for (size_t i = 0; i < tm->members->dim; i++) 5022: { 5023: Dsymbol *sm = tm->members->tdata()[i]; 5024: if (Dsymbol_canThrow(sm, mustNotThrow)) 5025: return 1; 5026: } 5027: } 5028: } 5029: else if ((td = s->isTupleDeclaration()) != NULL) 5030: { 5031: for (size_t i = 0; i < td->objects->dim; i++) 5032: { Object *o = td->objects->tdata()[i]; 5033: if (o->dyncast() == DYNCAST_EXPRESSION) 5034: { Expression *eo = (Expression *)o; 5035: if (eo->op == TOKdsymbol) 5036: { DsymbolExp *se = (DsymbolExp *)eo; 5037: if (Dsymbol_canThrow(se->s, mustNotThrow)) 5038: return 1; 5039: } 5040: } 5041: } 5042: } 5043: return 0; 5044: } 5045: 5046: 5047: int DeclarationExp::canThrow(bool mustNotThrow) 5048: { 5049: return Dsymbol_canThrow(declaration, mustNotThrow); 5050: } 5051: #endif 5052: 5053: void DeclarationExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 5054: { 5055: declaration->toCBuffer(buf, hgs); 5056: } 5057: 5058: 5059: /************************ TypeidExp ************************************/ 5060: 5061: /* 5062: * typeid(int) 5063: */ 5064: 5065: TypeidExp::TypeidExp(Loc loc, Object *o) 5066: : Expression(loc, TOKtypeid, sizeof(TypeidExp)) 5067: { 5068: this->obj = o; 5069: } 5070: 5071: 5072: Expression *TypeidExp::syntaxCopy() 5073: { 5074: return new TypeidExp(loc, objectSyntaxCopy(obj)); 5075: } 5076: 5077: 5078: Expression *TypeidExp::semantic(Scope *sc) 5079: { Expression *e; 5080: 5081: #if LOGSEMANTIC 5082: printf("TypeidExp::semantic() %s\n", toChars()); 5083: #endif 5084: Type *ta = isType(obj); 5085: Expression *ea = isExpression(obj); 5086: Dsymbol *sa = isDsymbol(obj); 5087: 5088: //printf("ta %p ea %p sa %p\n", ta, ea, sa); 5089: 5090: if (ta) 5091: { 5092: ta->resolve(loc, sc, &ea, &ta, &sa); 5093: } 5094: 5095: if (ea) 5096: { 5097: ea = ea->semantic(sc); 5098: ea = resolveProperties(sc, ea); 5099: ta = ea->type; 5100: if (ea->op == TOKtype) 5101: ea = NULL; 5102: } 5103: 5104: if (!ta) 5105: { 5106: //printf("ta %p ea %p sa %p\n", ta, ea, sa); 5107: error("no type for typeid(%s)", ea ? ea->toChars() : (sa ? sa->toChars() : "")); 5108: return new ErrorExp(); 5109: } 5110: 5111: if (ea && ta->toBasetype()->ty == Tclass) 5112: { /* Get the dynamic type, which is .classinfo 5113: */ 5114: e = new DotIdExp(ea->loc, ea, Id::classinfo); 5115: e = e->semantic(sc); 5116: } 5117: else 5118: { /* Get the static type 5119: */ 5120: e = ta->getTypeInfo(sc); 5121: if (e->loc.linnum == 0) 5122: e->loc = loc; // so there's at least some line number info 5123: if (ea) 5124: { 5125: e = new CommaExp(loc, ea, e); // execute ea 5126: e = e->semantic(sc); 5127: } 5128: } 5129: return e; 5130: } 5131: 5132: void TypeidExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 5133: { 5134: buf->writestring("typeid("); 5135: ObjectToCBuffer(buf, hgs, obj); 5136: buf->writeByte(')'); 5137: } 5138: 5139: /************************ TraitsExp ************************************/ 5140: #if DMDV2 5141: /* 5142: * __traits(identifier, args...) 5143: */ 5144: 5145: TraitsExp::TraitsExp(Loc loc, Identifier *ident, Objects *args) 5146: : Expression(loc, TOKtraits, sizeof(TraitsExp)) 5147: { 5148: this->ident = ident; 5149: this->args = args; 5150: } 5151: 5152: 5153: Expression *TraitsExp::syntaxCopy() 5154: { 5155: return new TraitsExp(loc, ident, TemplateInstance::arraySyntaxCopy(args)); 5156: } 5157: 5158: 5159: void TraitsExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 5160: { 5161: buf->writestring("__traits("); 5162: buf->writestring(ident->toChars()); 5163: if (args) 5164: { 5165: for (int i = 0; i < args->dim; i++)
warning C4018: '<' : signed/unsigned mismatch
5166: { 5167: buf->writeByte(','); 5168: Object *oarg = args->tdata()[i]; 5169: ObjectToCBuffer(buf, hgs, oarg); 5170: } 5171: } 5172: buf->writeByte(')'); 5173: } 5174: #endif 5175: 5176: /************************************************************/ 5177: 5178: HaltExp::HaltExp(Loc loc) 5179: : Expression(loc, TOKhalt, sizeof(HaltExp)) 5180: { 5181: } 5182: 5183: Expression *HaltExp::semantic(Scope *sc) 5184: { 5185: #if LOGSEMANTIC 5186: printf("HaltExp::semantic()\n"); 5187: #endif 5188: type = Type::tvoid; 5189: return this; 5190: } 5191: 5192: int HaltExp::checkSideEffect(int flag) 5193: { 5194: return 1; 5195: } 5196: 5197: void HaltExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 5198: { 5199: buf->writestring("halt"); 5200: } 5201: 5202: /************************************************************/ 5203: 5204: IsExp::IsExp(Loc loc, Type *targ, Identifier *id, enum TOK tok, 5205: Type *tspec, enum TOK tok2, TemplateParameters *parameters) 5206: : Expression(loc, TOKis, sizeof(IsExp)) 5207: { 5208: this->targ = targ; 5209: this->id = id; 5210: this->tok = tok; 5211: this->tspec = tspec; 5212: this->tok2 = tok2; 5213: this->parameters = parameters; 5214: } 5215: 5216: Expression *IsExp::syntaxCopy() 5217: { 5218: // This section is identical to that in TemplateDeclaration::syntaxCopy() 5219: TemplateParameters *p = NULL; 5220: if (parameters) 5221: { 5222: p = new TemplateParameters(); 5223: p->setDim(parameters->dim); 5224: for (int i = 0; i < p->dim; i++)
warning C4018: '<' : signed/unsigned mismatch
5225: { TemplateParameter *tp = parameters->tdata()[i]; 5226: p->tdata()[i] = tp->syntaxCopy(); 5227: } 5228: } 5229: 5230: return new IsExp(loc, 5231: targ->syntaxCopy(), 5232: id, 5233: tok, 5234: tspec ? tspec->syntaxCopy() : NULL, 5235: tok2, 5236: p); 5237: } 5238: 5239: Expression *IsExp::semantic(Scope *sc) 5240: { Type *tded; 5241: 5242: /* is(targ id tok tspec) 5243: * is(targ id : tok2) 5244: * is(targ id == tok2) 5245: */ 5246: 5247: //printf("IsExp::semantic(%s)\n", toChars()); 5248: if (id && !(sc->flags & (SCOPEstaticif | SCOPEstaticassert))) 5249: { error("can only declare type aliases within static if conditionals or static asserts"); 5250: return new ErrorExp(); 5251: } 5252: 5253: Type *t = targ->trySemantic(loc, sc); 5254: if (!t) 5255: goto Lno; // errors, so condition is false 5256: targ = t; 5257: if (tok2 != TOKreserved) 5258: { 5259: switch (tok2) 5260: { 5261: case TOKtypedef: 5262: if (targ->ty != Ttypedef) 5263: goto Lno; 5264: tded = ((TypeTypedef *)targ)->sym->basetype; 5265: break; 5266: 5267: case TOKstruct: 5268: if (targ->ty != Tstruct) 5269: goto Lno; 5270: if (((TypeStruct *)targ)->sym->isUnionDeclaration()) 5271: goto Lno; 5272: tded = targ; 5273: break; 5274: 5275: case TOKunion: 5276: if (targ->ty != Tstruct) 5277: goto Lno; 5278: if (!((TypeStruct *)targ)->sym->isUnionDeclaration()) 5279: goto Lno; 5280: tded = targ; 5281: break; 5282: 5283: case TOKclass: 5284: if (targ->ty != Tclass) 5285: goto Lno; 5286: if (((TypeClass *)targ)->sym->isInterfaceDeclaration()) 5287: goto Lno; 5288: tded = targ; 5289: break; 5290: 5291: case TOKinterface: 5292: if (targ->ty != Tclass) 5293: goto Lno; 5294: if (!((TypeClass *)targ)->sym->isInterfaceDeclaration()) 5295: goto Lno; 5296: tded = targ; 5297: break; 5298: #if DMDV2 5299: case TOKconst: 5300: if (!targ->isConst()) 5301: goto Lno; 5302: tded = targ; 5303: break; 5304: 5305: case TOKinvariant: 5306: if (!global.params.useDeprecated) 5307: error("use of 'invariant' rather than 'immutable' is deprecated"); 5308: case TOKimmutable: 5309: if (!targ->isImmutable()) 5310: goto Lno; 5311: tded = targ; 5312: break; 5313: 5314: case TOKshared: 5315: if (!targ->isShared()) 5316: goto Lno; 5317: tded = targ; 5318: break; 5319: 5320: case TOKwild: 5321: if (!targ->isWild()) 5322: goto Lno; 5323: tded = targ; 5324: break; 5325: #endif 5326: 5327: case TOKsuper: 5328: // If class or interface, get the base class and interfaces 5329: if (targ->ty != Tclass) 5330: goto Lno; 5331: else 5332: { ClassDeclaration *cd = ((TypeClass *)targ)->sym; 5333: Parameters *args = new Parameters; 5334: args->reserve(cd->baseclasses->dim); 5335: for (size_t i = 0; i < cd->baseclasses->dim; i++) 5336: { BaseClass *b = cd->baseclasses->tdata()[i]; 5337: args->push(new Parameter(STCin, b->type, NULL, NULL)); 5338: } 5339: tded = new TypeTuple(args); 5340: } 5341: break; 5342: 5343: case TOKenum: 5344: if (targ->ty != Tenum) 5345: goto Lno; 5346: tded = ((TypeEnum *)targ)->sym->memtype; 5347: break; 5348: 5349: case TOKdelegate: 5350: if (targ->ty != Tdelegate) 5351: goto Lno; 5352: tded = ((TypeDelegate *)targ)->next; // the underlying function type 5353: break; 5354: 5355: case TOKfunction: 5356: { 5357: if (targ->ty != Tfunction) 5358: goto Lno; 5359: tded = targ; 5360: 5361: /* Generate tuple from function parameter types. 5362: */ 5363: assert(tded->ty == Tfunction); 5364: Parameters *params = ((TypeFunction *)tded)->parameters; 5365: size_t dim = Parameter::dim(params); 5366: Parameters *args = new Parameters; 5367: args->reserve(dim); 5368: for (size_t i = 0; i < dim; i++) 5369: { Parameter *arg = Parameter::getNth(params, i); 5370: assert(arg && arg->type); 5371: args->push(new Parameter(arg->storageClass, arg->type, NULL, NULL)); 5372: } 5373: tded = new TypeTuple(args); 5374: break; 5375: } 5376: case TOKreturn: 5377: /* Get the 'return type' for the function, 5378: * delegate, or pointer to function. 5379: */ 5380: if (targ->ty == Tfunction) 5381: tded = ((TypeFunction *)targ)->next; 5382: else if (targ->ty == Tdelegate) 5383: { tded = ((TypeDelegate *)targ)->next; 5384: tded = ((TypeFunction *)tded)->next; 5385: } 5386: else if (targ->ty == Tpointer && 5387: ((TypePointer *)targ)->next->ty == Tfunction) 5388: { tded = ((TypePointer *)targ)->next; 5389: tded = ((TypeFunction *)tded)->next; 5390: } 5391: else 5392: goto Lno; 5393: break; 5394: 5395: case TOKargTypes: 5396: /* Generate a type tuple of the equivalent types used to determine if a 5397: * function argument of this type can be passed in registers. 5398: * The results of this are highly platform dependent, and intended 5399: * primarly for use in implementing va_arg(). 5400: */ 5401: tded = targ->toArgTypes(); 5402: if (!tded) 5403: goto Lno; // not valid for a parameter 5404: break; 5405: 5406: default: 5407: assert(0); 5408: } 5409: goto Lyes; 5410: } 5411: else if (id && tspec) 5412: { 5413: /* Evaluate to TRUE if targ matches tspec. 5414: * If TRUE, declare id as an alias for the specialized type. 5415: */ 5416: 5417: assert(parameters && parameters->dim); 5418: 5419: Objects dedtypes; 5420: dedtypes.setDim(parameters->dim); 5421: dedtypes.zero(); 5422: 5423: MATCH m = targ->deduceType(sc, tspec, parameters, &dedtypes); 5424: //printf("targ: %s\n", targ->toChars()); 5425: //printf("tspec: %s\n", tspec->toChars()); 5426: if (m == MATCHnomatch || 5427: (m != MATCHexact && tok == TOKequal)) 5428: { 5429: goto Lno; 5430: } 5431: else 5432: { 5433: tded = (Type *)dedtypes.tdata()[0]; 5434: if (!tded) 5435: tded = targ; 5436: #if DMDV2 5437: Objects tiargs; 5438: tiargs.setDim(1); 5439: tiargs.tdata()[0] = targ; 5440: 5441: /* Declare trailing parameters 5442: */ 5443: for (int i = 1; i < parameters->dim; i++)
warning C4018: '<' : signed/unsigned mismatch
5444: { TemplateParameter *tp = parameters->tdata()[i]; 5445: Declaration *s = NULL; 5446: 5447: m = tp->matchArg(sc, &tiargs, i, parameters, &dedtypes, &s); 5448: if (m == MATCHnomatch) 5449: goto Lno; 5450: s->semantic(sc); 5451: #if 0 5452: Type *o = dedtypes.tdata()[i]; 5453: Dsymbol *s = TemplateDeclaration::declareParameter(loc, sc, tp, o); 5454: #endif 5455: if (sc->sd) 5456: s->addMember(sc, sc->sd, 1); 5457: else if (!sc->insert(s)) 5458: error("declaration %s is already defined", s->toChars()); 5459: } 5460: #endif 5461: goto Lyes; 5462: } 5463: } 5464: else if (id) 5465: { 5466: /* Declare id as an alias for type targ. Evaluate to TRUE 5467: */ 5468: tded = targ; 5469: goto Lyes; 5470: } 5471: else if (tspec) 5472: { 5473: /* Evaluate to TRUE if targ matches tspec 5474: * is(targ == tspec) 5475: * is(targ : tspec) 5476: */ 5477: tspec = tspec->semantic(loc, sc); 5478: //printf("targ = %s, %s\n", targ->toChars(), targ->deco); 5479: //printf("tspec = %s, %s\n", tspec->toChars(), tspec->deco); 5480: if (tok == TOKcolon) 5481: { if (targ->implicitConvTo(tspec)) 5482: goto Lyes; 5483: else 5484: goto Lno; 5485: } 5486: else /* == */ 5487: { if (targ->equals(tspec)) 5488: goto Lyes; 5489: else 5490: goto Lno; 5491: } 5492: } 5493: 5494: Lyes: 5495: if (id) 5496: { 5497: Dsymbol *s = new AliasDeclaration(loc, id, tded); 5498: s->semantic(sc); 5499: if (!sc->insert(s)) 5500: error("declaration %s is already defined", s->toChars()); 5501: if (sc->sd) 5502: s->addMember(sc, sc->sd, 1); 5503: } 5504: //printf("Lyes\n"); 5505: return new IntegerExp(loc, 1, Type::tbool); 5506: 5507: Lno: 5508: //printf("Lno\n"); 5509: return new IntegerExp(loc, 0, Type::tbool); 5510: 5511: Lerr:
warning C4102: 'Lerr' : unreferenced label
5512: return new ErrorExp(); 5513: } 5514: 5515: void IsExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 5516: { 5517: buf->writestring("is("); 5518: targ->toCBuffer(buf, id, hgs); 5519: if (tok2 != TOKreserved) 5520: { 5521: buf->printf(" %s %s", Token::toChars(tok), Token::toChars(tok2)); 5522: } 5523: else if (tspec) 5524: { 5525: if (tok == TOKcolon) 5526: buf->writestring(" : "); 5527: else 5528: buf->writestring(" == "); 5529: tspec->toCBuffer(buf, NULL, hgs); 5530: } 5531: #if DMDV2 5532: if (parameters) 5533: { // First parameter is already output, so start with second 5534: for (int i = 1; i < parameters->dim; i++)
warning C4018: '<' : signed/unsigned mismatch
5535: { 5536: buf->writeByte(','); 5537: TemplateParameter *tp = parameters->tdata()[i]; 5538: tp->toCBuffer(buf, hgs); 5539: } 5540: } 5541: #endif 5542: buf->writeByte(')'); 5543: } 5544: 5545: 5546: /************************************************************/ 5547: 5548: UnaExp::UnaExp(Loc loc, enum TOK op, int size, Expression *e1) 5549: : Expression(loc, op, size) 5550: { 5551: this->e1 = e1; 5552: } 5553: 5554: Expression *UnaExp::syntaxCopy() 5555: { 5556: UnaExp *e = (UnaExp *)copy(); 5557: e->type = NULL; 5558: e->e1 = e->e1->syntaxCopy(); 5559: return e; 5560: } 5561: 5562: Expression *UnaExp::semantic(Scope *sc) 5563: { 5564: #if LOGSEMANTIC 5565: printf("UnaExp::semantic('%s')\n", toChars()); 5566: #endif 5567: e1 = e1->semantic(sc); 5568: // if (!e1->type) 5569: // error("%s has no value", e1->toChars()); 5570: return this; 5571: } 5572: 5573: #if DMDV2 5574: int UnaExp::canThrow(bool mustNotThrow) 5575: { 5576: return e1->canThrow(mustNotThrow); 5577: } 5578: #endif 5579: 5580: Expression *UnaExp::resolveLoc(Loc loc, Scope *sc) 5581: { 5582: e1 = e1->resolveLoc(loc, sc); 5583: return this; 5584: } 5585: 5586: void UnaExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 5587: { 5588: buf->writestring(Token::toChars(op)); 5589: expToCBuffer(buf, hgs, e1, precedence[op]); 5590: } 5591: 5592: /************************************************************/ 5593: 5594: BinExp::BinExp(Loc loc, enum TOK op, int size, Expression *e1, Expression *e2) 5595: : Expression(loc, op, size) 5596: { 5597: this->e1 = e1; 5598: this->e2 = e2; 5599: } 5600: 5601: Expression *BinExp::syntaxCopy() 5602: { 5603: BinExp *e = (BinExp *)copy(); 5604: e->type = NULL; 5605: e->e1 = e->e1->syntaxCopy(); 5606: e->e2 = e->e2->syntaxCopy(); 5607: return e; 5608: } 5609: 5610: Expression *BinExp::semantic(Scope *sc) 5611: { 5612: #if LOGSEMANTIC 5613: printf("BinExp::semantic('%s')\n", toChars()); 5614: #endif 5615: e1 = e1->semantic(sc); 5616: if (!e1->type && 5617: !(op == TOKassign && e1->op == TOKdottd)) // a.template = e2 5618: { 5619: error("%s has no value", e1->toChars()); 5620: return new ErrorExp(); 5621: } 5622: e2 = e2->semantic(sc); 5623: if (!e2->type) 5624: { 5625: error("%s has no value", e2->toChars()); 5626: return new ErrorExp(); 5627: } 5628: if (e1->op == TOKerror || e2->op == TOKerror) 5629: return new ErrorExp(); 5630: return this; 5631: } 5632: 5633: Expression *BinExp::semanticp(Scope *sc) 5634: { 5635: BinExp::semantic(sc); 5636: e1 = resolveProperties(sc, e1); 5637: e2 = resolveProperties(sc, e2); 5638: return this; 5639: } 5640: 5641: int BinExp::checkSideEffect(int flag) 5642: { 5643: if (op == TOKplusplus || 5644: op == TOKminusminus || 5645: op == TOKassign || 5646: op == TOKconstruct || 5647: op == TOKblit || 5648: op == TOKaddass || 5649: op == TOKminass || 5650: op == TOKcatass || 5651: op == TOKmulass || 5652: op == TOKdivass || 5653: op == TOKmodass || 5654: op == TOKshlass || 5655: op == TOKshrass || 5656: op == TOKushrass || 5657: op == TOKandass || 5658: op == TOKorass || 5659: op == TOKxorass || 5660: op == TOKpowass || 5661: op == TOKin || 5662: op == TOKremove) 5663: return 1; 5664: return Expression::checkSideEffect(flag); 5665: } 5666: 5667: // generate an error if this is a nonsensical *=,/=, or %=, eg real *= imaginary 5668: void BinExp::checkComplexMulAssign() 5669: { 5670: // Any multiplication by an imaginary or complex number yields a complex result. 5671: // r *= c, i*=c, r*=i, i*=i are all forbidden operations. 5672: const char *opstr = Token::toChars(op); 5673: if ( e1->type->isreal() && e2->type->iscomplex()) 5674: { 5675: error("%s %s %s is undefined. Did you mean %s %s %s.re ?", 5676: e1->type->toChars(), opstr, e2->type->toChars(), 5677: e1->type->toChars(), opstr, e2->type->toChars()); 5678: } 5679: else if (e1->type->isimaginary() && e2->type->iscomplex()) 5680: { 5681: error("%s %s %s is undefined. Did you mean %s %s %s.im ?", 5682: e1->type->toChars(), opstr, e2->type->toChars(), 5683: e1->type->toChars(), opstr, e2->type->toChars()); 5684: } 5685: else if ((e1->type->isreal() || e1->type->isimaginary()) && 5686: e2->type->isimaginary()) 5687: { 5688: error("%s %s %s is an undefined operation", e1->type->toChars(), 5689: opstr, e2->type->toChars()); 5690: } 5691: } 5692: 5693: // generate an error if this is a nonsensical += or -=, eg real += imaginary 5694: void BinExp::checkComplexAddAssign() 5695: { 5696: // Addition or subtraction of a real and an imaginary is a complex result. 5697: // Thus, r+=i, r+=c, i+=r, i+=c are all forbidden operations. 5698: if ( (e1->type->isreal() && (e2->type->isimaginary() || e2->type->iscomplex())) || 5699: (e1->type->isimaginary() && (e2->type->isreal() || e2->type->iscomplex())) 5700: ) 5701: { 5702: error("%s %s %s is undefined (result is complex)", 5703: e1->type->toChars(), Token::toChars(op), e2->type->toChars()); 5704: } 5705: } 5706: 5707: void BinExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 5708: { 5709: expToCBuffer(buf, hgs, e1, precedence[op]); 5710: buf->writeByte(' '); 5711: buf->writestring(Token::toChars(op)); 5712: buf->writeByte(' '); 5713: expToCBuffer(buf, hgs, e2, (enum PREC)(precedence[op] + 1)); 5714: } 5715: 5716: int BinExp::isunsigned() 5717: { 5718: return e1->type->isunsigned() || e2->type->isunsigned(); 5719: } 5720: 5721: #if DMDV2 5722: int BinExp::canThrow(bool mustNotThrow) 5723: { 5724: return e1->canThrow(mustNotThrow) || e2->canThrow(mustNotThrow); 5725: } 5726: #endif 5727: 5728: void BinExp::incompatibleTypes() 5729: { 5730: if (e1->type->toBasetype() != Type::terror && 5731: e2->type->toBasetype() != Type::terror 5732: ) 5733: error("incompatible types for ((%s) %s (%s)): '%s' and '%s'", 5734: e1->toChars(), Token::toChars(op), e2->toChars(), 5735: e1->type->toChars(), e2->type->toChars()); 5736: } 5737: 5738: /********************** BinAssignExp **************************************/ 5739: 5740: /*************************** 5741: * Common semantic routine for some xxxAssignExp's. 5742: */ 5743: 5744: Expression *BinAssignExp::commonSemanticAssign(Scope *sc) 5745: { Expression *e; 5746: 5747: if (!type) 5748: { 5749: if (e1->op == TOKarraylength) 5750: { 5751: e = ArrayLengthExp::rewriteOpAssign(this); 5752: e = e->semantic(sc); 5753: return e; 5754: } 5755: 5756: if (e1->op == TOKslice) 5757: { // T[] op= ... 5758: e = typeCombine(sc); 5759: if (e->op == TOKerror) 5760: return e; 5761: type = e1->type; 5762: return arrayOp(sc); 5763: } 5764: 5765: e1 = e1->modifiableLvalue(sc, e1); 5766: e1->checkScalar(); 5767: type = e1->type; 5768: if (type->toBasetype()->ty == Tbool) 5769: { 5770: error("operator not allowed on bool expression %s", toChars()); 5771: return new ErrorExp(); 5772: } 5773: typeCombine(sc); 5774: e1->checkArithmetic(); 5775: e2->checkArithmetic(); 5776: 5777: if (op == TOKmodass && e2->type->iscomplex()) 5778: { error("cannot perform modulo complex arithmetic"); 5779: return new ErrorExp(); 5780: } 5781: } 5782: return this; 5783: } 5784: 5785: Expression *BinAssignExp::commonSemanticAssignIntegral(Scope *sc) 5786: { Expression *e; 5787: 5788: if (!type) 5789: { 5790: e = op_overload(sc); 5791: if (e) 5792: return e; 5793: 5794: if (e1->op == TOKarraylength) 5795: { 5796: e = ArrayLengthExp::rewriteOpAssign(this); 5797: e = e->semantic(sc); 5798: return e; 5799: } 5800: 5801: if (e1->op == TOKslice) 5802: { // T[] op= ... 5803: e = typeCombine(sc); 5804: if (e->op == TOKerror) 5805: return e; 5806: type = e1->type; 5807: return arrayOp(sc); 5808: } 5809: 5810: e1 = e1->modifiableLvalue(sc, e1); 5811: e1->checkScalar(); 5812: type = e1->type; 5813: if (type->toBasetype()->ty == Tbool) 5814: { 5815: e2 = e2->implicitCastTo(sc, type); 5816: } 5817: 5818: typeCombine(sc); 5819: e1->checkIntegral(); 5820: e2->checkIntegral(); 5821: } 5822: return this; 5823: } 5824: 5825: #if DMDV2 5826: int BinAssignExp::isLvalue() 5827: { 5828: return 1; 5829: } 5830: 5831: Expression *BinAssignExp::toLvalue(Scope *sc, Expression *ex) 5832: { Expression *e; 5833: 5834: if (e1->op == TOKvar) 5835: { 5836: /* Convert (e1 op= e2) to 5837: * e1 op= e2; 5838: * e1 5839: */ 5840: e = e1->copy(); 5841: e = new CommaExp(loc, this, e); 5842: e = e->semantic(sc); 5843: } 5844: else 5845: { 5846: /* Convert (e1 op= e2) to 5847: * ref v = e1; 5848: * v op= e2; 5849: * v 5850: */ 5851: 5852: // ref v = e1; 5853: Identifier *id = Lexer::uniqueId("__assignop"); 5854: ExpInitializer *ei = new ExpInitializer(loc, e1); 5855: VarDeclaration *v = new VarDeclaration(loc, e1->type, id, ei); 5856: v->storage_class |= STCref | STCforeach; 5857: Expression *de = new DeclarationExp(loc, v);
warning C6211: Leaking memory 'de' due to an exception. Consider using a local catch block to clean up memory: Lines: 5832, 5834, 5853, 5854, 5855, 5856, 5857, 5860
5858: 5859: // v op= e2 5860: e1 = new VarExp(e1->loc, v); 5861: 5862: e = new CommaExp(loc, de, this); 5863: e = new CommaExp(loc, e, new VarExp(loc, v)); 5864: e = e->semantic(sc); 5865: } 5866: return e; 5867: } 5868: 5869: Expression *BinAssignExp::modifiableLvalue(Scope *sc, Expression *e) 5870: { 5871: return toLvalue(sc, this); 5872: } 5873: 5874: #endif 5875: 5876: /************************************************************/ 5877: 5878: CompileExp::CompileExp(Loc loc, Expression *e) 5879: : UnaExp(loc, TOKmixin, sizeof(CompileExp), e) 5880: { 5881: } 5882: 5883: Expression *CompileExp::semantic(Scope *sc) 5884: { 5885: #if LOGSEMANTIC 5886: printf("CompileExp::semantic('%s')\n", toChars()); 5887: #endif 5888: UnaExp::semantic(sc); 5889: e1 = resolveProperties(sc, e1); 5890: if (e1->op == TOKerror) 5891: return e1; 5892: if (!e1->type->isString()) 5893: { 5894: error("argument to mixin must be a string type, not %s\n", e1->type->toChars()); 5895: return new ErrorExp(); 5896: } 5897: e1 = e1->optimize(WANTvalue | WANTinterpret); 5898: if (e1->op != TOKstring) 5899: { error("argument to mixin must be a string, not (%s)", e1->toChars()); 5900: return new ErrorExp(); 5901: } 5902: StringExp *se = (StringExp *)e1; 5903: se = se->toUTF8(sc); 5904: Parser p(sc->module, (unsigned char *)se->string, se->len, 0); 5905: p.loc = loc; 5906: p.nextToken(); 5907: //printf("p.loc.linnum = %d\n", p.loc.linnum); 5908: Expression *e = p.parseExpression(); 5909: if (p.token.value != TOKeof) 5910: { error("incomplete mixin expression (%s)", se->toChars()); 5911: return new ErrorExp(); 5912: } 5913: return e->semantic(sc); 5914: } 5915: 5916: void CompileExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 5917: { 5918: buf->writestring("mixin("); 5919: expToCBuffer(buf, hgs, e1, PREC_assign); 5920: buf->writeByte(')'); 5921: } 5922: 5923: /************************************************************/ 5924: 5925: FileExp::FileExp(Loc loc, Expression *e) 5926: : UnaExp(loc, TOKmixin, sizeof(FileExp), e) 5927: { 5928: } 5929: 5930: Expression *FileExp::semantic(Scope *sc) 5931: { char *name; 5932: StringExp *se; 5933: 5934: #if LOGSEMANTIC 5935: printf("FileExp::semantic('%s')\n", toChars()); 5936: #endif 5937: UnaExp::semantic(sc); 5938: e1 = resolveProperties(sc, e1); 5939: e1 = e1->optimize(WANTvalue | WANTinterpret); 5940: if (e1->op != TOKstring) 5941: { error("file name argument must be a string, not (%s)", e1->toChars()); 5942: goto Lerror; 5943: } 5944: se = (StringExp *)e1; 5945: se = se->toUTF8(sc); 5946: name = (char *)se->string; 5947: 5948: if (!global.params.fileImppath) 5949: { error("need -Jpath switch to import text file %s", name); 5950: goto Lerror; 5951: } 5952: 5953: /* Be wary of CWE-22: Improper Limitation of a Pathname to a Restricted Directory 5954: * ('Path Traversal') attacks. 5955: * http://cwe.mitre.org/data/definitions/22.html 5956: */ 5957: 5958: name = FileName::safeSearchPath(global.filePath, name); 5959: if (!name) 5960: { error("file %s cannot be found or not in a path specified with -J", se->toChars()); 5961: goto Lerror; 5962: } 5963: 5964: if (global.params.verbose) 5965: printf("file %s\t(%s)\n", (char *)se->string, name); 5966: 5967: { File f(name); 5968: if (f.read()) 5969: { error("cannot read file %s", f.toChars()); 5970: goto Lerror; 5971: } 5972: else 5973: { 5974: f.ref = 1; 5975: se = new StringExp(loc, f.buffer, f.len); 5976: } 5977: } 5978: Lret:
warning C4102: 'Lret' : unreferenced label
5979: return se->semantic(sc); 5980: 5981: Lerror: 5982: return new ErrorExp(); 5983: } 5984: 5985: void FileExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 5986: { 5987: buf->writestring("import("); 5988: expToCBuffer(buf, hgs, e1, PREC_assign); 5989: buf->writeByte(')'); 5990: } 5991: 5992: /************************************************************/ 5993: 5994: AssertExp::AssertExp(Loc loc, Expression *e, Expression *msg) 5995: : UnaExp(loc, TOKassert, sizeof(AssertExp), e) 5996: { 5997: this->msg = msg; 5998: } 5999: 6000: Expression *AssertExp::syntaxCopy() 6001: { 6002: AssertExp *ae = new AssertExp(loc, e1->syntaxCopy(), 6003: msg ? msg->syntaxCopy() : NULL); 6004: return ae; 6005: } 6006: 6007: Expression *AssertExp::semantic(Scope *sc) 6008: { 6009: #if LOGSEMANTIC 6010: printf("AssertExp::semantic('%s')\n", toChars()); 6011: #endif 6012: UnaExp::semantic(sc); 6013: e1 = resolveProperties(sc, e1); 6014: // BUG: see if we can do compile time elimination of the Assert 6015: e1 = e1->optimize(WANTvalue); 6016: e1 = e1->checkToBoolean(sc); 6017: if (msg) 6018: { 6019: msg = msg->semantic(sc); 6020: msg = resolveProperties(sc, msg); 6021: msg = msg->implicitCastTo(sc, Type::tchar->constOf()->arrayOf()); 6022: msg = msg->optimize(WANTvalue); 6023: } 6024: if (e1->isBool(FALSE)) 6025: { 6026: FuncDeclaration *fd = sc->parent->isFuncDeclaration(); 6027: if (fd) 6028: fd->hasReturnExp |= 4; 6029: 6030: if (!global.params.useAssert) 6031: { Expression *e = new HaltExp(loc); 6032: e = e->semantic(sc); 6033: return e; 6034: } 6035: } 6036: type = Type::tvoid; 6037: return this; 6038: } 6039: 6040: int AssertExp::checkSideEffect(int flag) 6041: { 6042: return 1; 6043: } 6044: 6045: #if DMDV2 6046: int AssertExp::canThrow(bool mustNotThrow) 6047: { 6048: /* assert()s are non-recoverable errors, so functions that 6049: * use them can be considered "nothrow" 6050: */ 6051: return 0; //(global.params.useAssert != 0); 6052: } 6053: #endif 6054: 6055: void AssertExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 6056: { 6057: buf->writestring("assert("); 6058: expToCBuffer(buf, hgs, e1, PREC_assign); 6059: if (msg) 6060: { 6061: buf->writeByte(','); 6062: expToCBuffer(buf, hgs, msg, PREC_assign); 6063: } 6064: buf->writeByte(')'); 6065: } 6066: 6067: /************************************************************/ 6068: 6069: DotIdExp::DotIdExp(Loc loc, Expression *e, Identifier *ident) 6070: : UnaExp(loc, TOKdot, sizeof(DotIdExp), e) 6071: { 6072: this->ident = ident; 6073: } 6074: 6075: Expression *DotIdExp::semantic(Scope *sc) 6076: { 6077: // Indicate we didn't come from CallExp::semantic() 6078: return semantic(sc, 0); 6079: } 6080: 6081: Expression *DotIdExp::semantic(Scope *sc, int flag) 6082: { Expression *e; 6083: Expression *eleft; 6084: Expression *eright; 6085: 6086: #if LOGSEMANTIC 6087: printf("DotIdExp::semantic(this = %p, '%s')\n", this, toChars()); 6088: //printf("e1->op = %d, '%s'\n", e1->op, Token::toChars(e1->op)); 6089: #endif 6090: 6091: //{ static int z; fflush(stdout); if (++z == 10) *(char*)0=0; } 6092: 6093: #if 0 6094: /* Don't do semantic analysis if we'll be converting 6095: * it to a string. 6096: */ 6097: if (ident == Id::stringof) 6098: { char *s = e1->toChars(); 6099: e = new StringExp(loc, s, strlen(s), 'c'); 6100: e = e->semantic(sc); 6101: return e; 6102: } 6103: #endif 6104: 6105: /* Special case: rewrite this.id and super.id 6106: * to be classtype.id and baseclasstype.id 6107: * if we have no this pointer. 6108: */ 6109: if ((e1->op == TOKthis || e1->op == TOKsuper) && !hasThis(sc)) 6110: { ClassDeclaration *cd; 6111: StructDeclaration *sd; 6112: AggregateDeclaration *ad; 6113: 6114: ad = sc->getStructClassScope(); 6115: if (ad) 6116: { 6117: cd = ad->isClassDeclaration(); 6118: if (cd) 6119: { 6120: if (e1->op == TOKthis) 6121: { 6122: e = typeDotIdExp(loc, cd->type, ident); 6123: return e->semantic(sc); 6124: } 6125: else if (cd->baseClass && e1->op == TOKsuper) 6126: { 6127: e = typeDotIdExp(loc, cd->baseClass->type, ident); 6128: return e->semantic(sc); 6129: } 6130: } 6131: else 6132: { 6133: sd = ad->isStructDeclaration(); 6134: if (sd) 6135: { 6136: if (e1->op == TOKthis) 6137: { 6138: e = typeDotIdExp(loc, sd->type, ident); 6139: return e->semantic(sc); 6140: } 6141: } 6142: } 6143: } 6144: } 6145: 6146: UnaExp::semantic(sc); 6147: 6148: if (e1->op == TOKdotexp) 6149: { 6150: DotExp *de = (DotExp *)e1; 6151: eleft = de->e1; 6152: eright = de->e2; 6153: } 6154: else 6155: { 6156: if (e1->op != TOKtype) 6157: e1 = resolveProperties(sc, e1); 6158: eleft = NULL; 6159: eright = e1; 6160: } 6161: #if DMDV2 6162: if (e1->op == TOKtuple && ident == Id::offsetof) 6163: { /* 'distribute' the .offsetof to each of the tuple elements. 6164: */ 6165: TupleExp *te = (TupleExp *)e1; 6166: Expressions *exps = new Expressions(); 6167: exps->setDim(te->exps->dim); 6168: for (int i = 0; i < exps->dim; i++)
warning C4018: '<' : signed/unsigned mismatch
6169: { Expression *e = (*te->exps)[i];
warning C6246: Local declaration of 'e' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '6082' of 'c:\projects\extern\d\dmd\src\expression.c': Lines: 6082
6170: e = e->semantic(sc); 6171: e = new DotIdExp(e->loc, e, Id::offsetof); 6172: (*exps)[i] = e; 6173: } 6174: e = new TupleExp(loc, exps); 6175: e = e->semantic(sc); 6176: return e; 6177: } 6178: #endif 6179: 6180: if (e1->op == TOKtuple && ident == Id::length) 6181: { 6182: TupleExp *te = (TupleExp *)e1; 6183: e = new IntegerExp(loc, te->exps->dim, Type::tsize_t); 6184: return e; 6185: } 6186: 6187: if (e1->op == TOKdottd) 6188: { 6189: error("template %s does not have property %s", e1->toChars(), ident->toChars()); 6190: return new ErrorExp(); 6191: } 6192: 6193: if (!e1->type) 6194: { 6195: error("expression %s does not have property %s", e1->toChars(), ident->toChars()); 6196: return new ErrorExp(); 6197: } 6198: 6199: Type *t1b = e1->type->toBasetype(); 6200: 6201: if (eright->op == TOKimport) // also used for template alias's 6202: { 6203: ScopeExp *ie = (ScopeExp *)eright; 6204: 6205: /* Disable access to another module's private imports. 6206: * The check for 'is sds our current module' is because 6207: * the current module should have access to its own imports. 6208: */ 6209: Dsymbol *s = ie->sds->search(loc, ident, 6210: (ie->sds->isModule() && ie->sds != sc->module) ? 1 : 0); 6211: if (s) 6212: { 6213: s = s->toAlias(); 6214: checkDeprecated(sc, s); 6215: 6216: EnumMember *em = s->isEnumMember(); 6217: if (em) 6218: { 6219: e = em->value; 6220: e = e->semantic(sc); 6221: return e; 6222: } 6223: 6224: VarDeclaration *v = s->isVarDeclaration(); 6225: if (v) 6226: { 6227: //printf("DotIdExp:: Identifier '%s' is a variable, type '%s'\n", toChars(), v->type->toChars()); 6228: if (v->inuse) 6229: { 6230: error("circular reference to '%s'", v->toChars()); 6231: return new ErrorExp(); 6232: } 6233: type = v->type; 6234: if (v->needThis()) 6235: { 6236: if (!eleft) 6237: eleft = new ThisExp(loc); 6238: e = new DotVarExp(loc, eleft, v); 6239: e = e->semantic(sc); 6240: } 6241: else 6242: { 6243: e = new VarExp(loc, v); 6244: if (eleft) 6245: { e = new CommaExp(loc, eleft, e); 6246: e->type = v->type; 6247: } 6248: } 6249: e = e->deref(); 6250: return e->semantic(sc); 6251: } 6252: 6253: FuncDeclaration *f = s->isFuncDeclaration(); 6254: if (f) 6255: { 6256: //printf("it's a function\n"); 6257: if (f->needThis()) 6258: { 6259: if (!eleft) 6260: eleft = new ThisExp(loc); 6261: e = new DotVarExp(loc, eleft, f); 6262: e = e->semantic(sc); 6263: } 6264: else 6265: { 6266: e = new VarExp(loc, f, 1); 6267: if (eleft) 6268: { e = new CommaExp(loc, eleft, e); 6269: e->type = f->type; 6270: } 6271: } 6272: return e; 6273: } 6274: #if DMDV2 6275: OverloadSet *o = s->isOverloadSet(); 6276: if (o) 6277: { //printf("'%s' is an overload set\n", o->toChars()); 6278: return new OverExp(o); 6279: } 6280: #endif 6281: 6282: Type *t = s->getType(); 6283: if (t) 6284: { 6285: return new TypeExp(loc, t); 6286: } 6287: 6288: TupleDeclaration *tup = s->isTupleDeclaration(); 6289: if (tup) 6290: { 6291: if (eleft) 6292: { error("cannot have e.tuple"); 6293: return new ErrorExp(); 6294: } 6295: e = new TupleExp(loc, tup); 6296: e = e->semantic(sc); 6297: return e; 6298: } 6299: 6300: ScopeDsymbol *sds = s->isScopeDsymbol(); 6301: if (sds) 6302: { 6303: //printf("it's a ScopeDsymbol\n"); 6304: e = new ScopeExp(loc, sds); 6305: e = e->semantic(sc); 6306: if (eleft) 6307: e = new DotExp(loc, eleft, e); 6308: return e; 6309: } 6310: 6311: Import *imp = s->isImport(); 6312: if (imp) 6313: { 6314: ScopeExp *ie;
warning C6246: Local declaration of 'ie' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '6203' of 'c:\projects\extern\d\dmd\src\expression.c': Lines: 6203
6315: 6316: ie = new ScopeExp(loc, imp->pkg); 6317: return ie->semantic(sc); 6318: } 6319: 6320: // BUG: handle other cases like in IdentifierExp::semantic() 6321: #ifdef DEBUG 6322: printf("s = '%s', kind = '%s'\n", s->toChars(), s->kind()); 6323: #endif 6324: assert(0); 6325: } 6326: else if (ident == Id::stringof) 6327: { char *s = ie->toChars();
warning C6246: Local declaration of 's' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '6209' of 'c:\projects\extern\d\dmd\src\expression.c': Lines: 6209
6328: e = new StringExp(loc, s, strlen(s), 'c'); 6329: e = e->semantic(sc); 6330: return e; 6331: } 6332: error("undefined identifier %s", toChars()); 6333: return new ErrorExp(); 6334: } 6335: else if (t1b->ty == Tpointer && 6336: ident != Id::init && ident != Id::__sizeof && 6337: ident != Id::__xalignof && ident != Id::offsetof && 6338: ident != Id::mangleof && ident != Id::stringof) 6339: { /* Rewrite: 6340: * p.ident 6341: * as: 6342: * (*p).ident 6343: */ 6344: e = new PtrExp(loc, e1); 6345: e->type = ((TypePointer *)t1b)->next; 6346: return e->type->dotExp(sc, e, ident); 6347: } 6348: #if DMDV2 6349: else if (t1b->ty == Tarray || 6350: t1b->ty == Tsarray || 6351: t1b->ty == Taarray) 6352: { /* If ident is not a valid property, rewrite: 6353: * e1.ident 6354: * as: 6355: * .ident(e1) 6356: */ 6357: unsigned errors = global.errors; 6358: global.gag++; 6359: Type *t1 = e1->type; 6360: e = e1->type->dotExp(sc, e1, ident); 6361: global.gag--; 6362: if (errors != global.errors) // if failed to find the property 6363: { 6364: global.errors = errors; 6365: e1->type = t1; // kludge to restore type 6366: e = new DotIdExp(loc, new IdentifierExp(loc, Id::empty), ident); 6367: e = new CallExp(loc, e, e1); 6368: } 6369: e = e->semantic(sc); 6370: return e; 6371: } 6372: #endif 6373: else 6374: { 6375: e = e1->type->dotExp(sc, e1, ident); 6376: if (!(flag && e->op == TOKdotti)) // let CallExp::semantic() handle this 6377: e = e->semantic(sc); 6378: return e; 6379: } 6380: } 6381: 6382: void DotIdExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 6383: { 6384: //printf("DotIdExp::toCBuffer()\n"); 6385: expToCBuffer(buf, hgs, e1, PREC_primary); 6386: buf->writeByte('.'); 6387: buf->writestring(ident->toChars()); 6388: } 6389: 6390: /********************** DotTemplateExp ***********************************/ 6391: 6392: // Mainly just a placeholder 6393: 6394: DotTemplateExp::DotTemplateExp(Loc loc, Expression *e, TemplateDeclaration *td) 6395: : UnaExp(loc, TOKdottd, sizeof(DotTemplateExp), e) 6396: 6397: { 6398: this->td = td; 6399: } 6400: 6401: void DotTemplateExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 6402: { 6403: expToCBuffer(buf, hgs, e1, PREC_primary); 6404: buf->writeByte('.'); 6405: buf->writestring(td->toChars()); 6406: } 6407: 6408: 6409: /************************************************************/ 6410: 6411: DotVarExp::DotVarExp(Loc loc, Expression *e, Declaration *v, int hasOverloads) 6412: : UnaExp(loc, TOKdotvar, sizeof(DotVarExp), e) 6413: { 6414: //printf("DotVarExp()\n"); 6415: this->var = v; 6416: this->hasOverloads = hasOverloads; 6417: } 6418: 6419: Expression *DotVarExp::semantic(Scope *sc) 6420: { 6421: #if LOGSEMANTIC 6422: printf("DotVarExp::semantic('%s')\n", toChars()); 6423: #endif 6424: if (!type) 6425: { 6426: var = var->toAlias()->isDeclaration(); 6427: 6428: TupleDeclaration *tup = var->isTupleDeclaration(); 6429: if (tup) 6430: { /* Replace: 6431: * e1.tuple(a, b, c) 6432: * with: 6433: * tuple(e1.a, e1.b, e1.c) 6434: */ 6435: Expressions *exps = new Expressions;
warning C6211: Leaking memory 'exps' due to an exception. Consider using a local catch block to clean up memory: Lines: 6424, 6426, 6428, 6429, 6435, 6437, 6438, 6439, 6440, 6447, 6448, 6453, 6455
6436: 6437: exps->reserve(tup->objects->dim); 6438: for (size_t i = 0; i < tup->objects->dim; i++) 6439: { Object *o = tup->objects->tdata()[i]; 6440: if (o->dyncast() != DYNCAST_EXPRESSION) 6441: { 6442: error("%s is not an expression", o->toChars()); 6443: goto Lerr; 6444: } 6445: else 6446: { 6447: Expression *e = (Expression *)o; 6448: if (e->op != TOKdsymbol) 6449: { error("%s is not a member", e->toChars()); 6450: goto Lerr; 6451: } 6452: else 6453: { DsymbolExp *ve = (DsymbolExp *)e; 6454: 6455: e = new DotVarExp(loc, e1, ve->s->isDeclaration()); 6456: exps->push(e); 6457: } 6458: } 6459: } 6460: Expression *e = new TupleExp(loc, exps); 6461: e = e->semantic(sc); 6462: return e; 6463: } 6464: 6465: e1 = e1->semantic(sc); 6466: e1 = e1->addDtorHook(sc); 6467: type = var->type; 6468: if (!type && global.errors) 6469: { // var is goofed up, just return 0 6470: return new ErrorExp(); 6471: } 6472: assert(type); 6473: 6474: Type *t1 = e1->type; 6475: if (!var->isFuncDeclaration()) // for functions, do checks after overload resolution 6476: { 6477: if (t1->ty == Tpointer) 6478: t1 = t1->nextOf(); 6479: 6480: type = type->addMod(t1->mod); 6481: 6482: Dsymbol *vparent = var->toParent(); 6483: AggregateDeclaration *ad = vparent ? vparent->isAggregateDeclaration() : NULL; 6484: e1 = getRightThis(loc, sc, ad, e1, var); 6485: if (!sc->noaccesscheck) 6486: accessCheck(loc, sc, e1, var); 6487: 6488: VarDeclaration *v = var->isVarDeclaration(); 6489: Expression *e = expandVar(WANTvalue, v); 6490: if (e) 6491: return e; 6492: } 6493: Dsymbol *s; 6494: if (sc->func && !sc->intypeof && t1->hasPointers() && 6495: (s = t1->toDsymbol(sc)) != NULL) 6496: { 6497: AggregateDeclaration *ad = s->isAggregateDeclaration(); 6498: if (ad && ad->hasUnions) 6499: { 6500: if (sc->func->setUnsafe()) 6501: { error("union %s containing pointers are not allowed in @safe functions", t1->toChars()); 6502: goto Lerr; 6503: } 6504: } 6505: } 6506: } 6507: 6508: //printf("-DotVarExp::semantic('%s')\n", toChars()); 6509: return this; 6510: 6511: Lerr: 6512: return new ErrorExp(); 6513: } 6514: 6515: #if DMDV2 6516: int DotVarExp::isLvalue() 6517: { 6518: return 1; 6519: } 6520: #endif 6521: 6522: Expression *DotVarExp::toLvalue(Scope *sc, Expression *e) 6523: { 6524: //printf("DotVarExp::toLvalue(%s)\n", toChars()); 6525: return this; 6526: } 6527: 6528: Expression *DotVarExp::modifiableLvalue(Scope *sc, Expression *e) 6529: { 6530: #if 0 6531: printf("DotVarExp::modifiableLvalue(%s)\n", toChars()); 6532: printf("e1->type = %s\n", e1->type->toChars()); 6533: printf("var->type = %s\n", var->type->toChars()); 6534: #endif 6535: 6536: Type *t1 = e1->type->toBasetype(); 6537: 6538: if (!t1->isMutable() || 6539: (t1->ty == Tpointer && !t1->nextOf()->isMutable()) || 6540: !var->type->isMutable() || 6541: !var->type->isAssignable() || 6542: var->storage_class & STCmanifest 6543: ) 6544: { 6545: if (var->isCtorinit()) 6546: { // It's only modifiable if inside the right constructor 6547: Dsymbol *s = sc->func; 6548: while (1) 6549: { 6550: FuncDeclaration *fd = NULL; 6551: if (s) 6552: fd = s->isFuncDeclaration(); 6553: if (fd && 6554: ((fd->isCtorDeclaration() && var->storage_class & STCfield) || 6555: (fd->isStaticCtorDeclaration() && !(var->storage_class & STCfield))) && 6556: fd->toParent2() == var->toParent() && 6557: e1->op == TOKthis 6558: ) 6559: { 6560: VarDeclaration *v = var->isVarDeclaration(); 6561: assert(v); 6562: v->ctorinit = 1; 6563: //printf("setting ctorinit\n"); 6564: } 6565: else 6566: { 6567: if (s) 6568: { s = s->toParent2(); 6569: continue; 6570: } 6571: else 6572: { 6573: const char *p = var->isStatic() ? "static " : ""; 6574: error("can only initialize %sconst member %s inside %sconstructor", 6575: p, var->toChars(), p); 6576: } 6577: } 6578: break; 6579: } 6580: } 6581: else 6582: { 6583: error("cannot modify const/immutable/inout expression %s", toChars()); 6584: } 6585: } 6586: return this; 6587: } 6588: 6589: void DotVarExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 6590: { 6591: expToCBuffer(buf, hgs, e1, PREC_primary); 6592: buf->writeByte('.'); 6593: buf->writestring(var->toChars()); 6594: } 6595: 6596: /************************************************************/ 6597: 6598: /* Things like: 6599: * foo.bar!(args) 6600: */ 6601: 6602: DotTemplateInstanceExp::DotTemplateInstanceExp(Loc loc, Expression *e, Identifier *name, Objects *tiargs) 6603: : UnaExp(loc, TOKdotti, sizeof(DotTemplateInstanceExp), e) 6604: { 6605: //printf("DotTemplateInstanceExp()\n"); 6606: this->ti = new TemplateInstance(loc, name); 6607: this->ti->tiargs = tiargs; 6608: } 6609: 6610: Expression *DotTemplateInstanceExp::syntaxCopy() 6611: { 6612: DotTemplateInstanceExp *de = new DotTemplateInstanceExp(loc, 6613: e1->syntaxCopy(), 6614: ti->name, 6615: TemplateInstance::arraySyntaxCopy(ti->tiargs)); 6616: return de; 6617: } 6618: 6619: TemplateDeclaration *DotTemplateInstanceExp::getTempdecl(Scope *sc) 6620: { 6621: #if LOGSEMANTIC 6622: printf("DotTemplateInstanceExp::getTempdecl('%s')\n", toChars()); 6623: #endif 6624: if (!ti->tempdecl) 6625: { 6626: Expression *e = new DotIdExp(loc, e1, ti->name); 6627: e = e->semantic(sc); 6628: if (e->op == TOKdottd) 6629: { 6630: DotTemplateExp *dte = (DotTemplateExp *)e; 6631: ti->tempdecl = dte->td; 6632: } 6633: else if (e->op == TOKimport) 6634: { ScopeExp *se = (ScopeExp *)e; 6635: ti->tempdecl = se->sds->isTemplateDeclaration(); 6636: } 6637: } 6638: return ti->tempdecl; 6639: } 6640: 6641: Expression *DotTemplateInstanceExp::semantic(Scope *sc) 6642: { 6643: #if LOGSEMANTIC 6644: printf("DotTemplateInstanceExp::semantic('%s')\n", toChars()); 6645: #endif 6646: Expression *eleft; 6647: Expression *e = new DotIdExp(loc, e1, ti->name); 6648: L1: 6649: e = e->semantic(sc); 6650: if (e->op == TOKerror) 6651: return e; 6652: if (e->op == TOKdottd) 6653: { 6654: if (global.errors) 6655: return new ErrorExp(); // TemplateInstance::semantic() will fail anyway 6656: DotTemplateExp *dte = (DotTemplateExp *)e; 6657: TemplateDeclaration *td = dte->td; 6658: eleft = dte->e1; 6659: ti->tempdecl = td; 6660: ti->semantic(sc); 6661: if (!ti->inst) // if template failed to expand 6662: return new ErrorExp(); 6663: Dsymbol *s = ti->inst->toAlias(); 6664: Declaration *v = s->isDeclaration(); 6665: if (v) 6666: { 6667: /* Fix for Bugzilla 4003 6668: * The problem is a class template member function v returning a reference to the same 6669: * type as the enclosing template instantiation. This results in a nested instantiation, 6670: * which of course gets short circuited. The return type then gets set to 6671: * the template instance type before instantiation, rather than after. 6672: * We can detect this by the deco not being set. If so, go ahead and retry 6673: * the return type semantic. 6674: * The offending code is the return type from std.typecons.Tuple.slice: 6675: * ref Tuple!(Types[from .. to]) slice(uint from, uint to)() 6676: * { 6677: * return *cast(typeof(return) *) &(field[from]); 6678: * } 6679: * and this line from the following unittest: 6680: * auto s = a.slice!(1, 3); 6681: * where s's type wound up not having semantic() run on it. 6682: */ 6683: if (v->type && !v->type->deco) 6684: v->type = v->type->semantic(v->loc, sc); 6685: 6686: e = new DotVarExp(loc, eleft, v); 6687: e = e->semantic(sc); 6688: return e; 6689: } 6690: e = new ScopeExp(loc, ti); 6691: e = new DotExp(loc, eleft, e); 6692: e = e->semantic(sc); 6693: return e; 6694: } 6695: else if (e->op == TOKimport) 6696: { ScopeExp *se = (ScopeExp *)e; 6697: TemplateDeclaration *td = se->sds->isTemplateDeclaration(); 6698: if (!td) 6699: { error("%s is not a template", e->toChars()); 6700: return new ErrorExp(); 6701: } 6702: ti->tempdecl = td; 6703: e = new ScopeExp(loc, ti); 6704: e = e->semantic(sc); 6705: return e; 6706: } 6707: else if (e->op == TOKdotexp) 6708: { DotExp *de = (DotExp *)e; 6709: 6710: if (de->e2->op == TOKoverloadset) 6711: { 6712: return e; 6713: } 6714: 6715: if (de->e2->op == TOKimport) 6716: { // This should *really* be moved to ScopeExp::semantic() 6717: ScopeExp *se = (ScopeExp *)de->e2; 6718: de->e2 = new DsymbolExp(loc, se->sds); 6719: de->e2 = de->e2->semantic(sc); 6720: } 6721: 6722: if (de->e2->op == TOKtemplate) 6723: { TemplateExp *te = (TemplateExp *) de->e2; 6724: e = new DotTemplateExp(loc,de->e1,te->td); 6725: } 6726: goto L1; 6727: } 6728: error("%s isn't a template", e->toChars()); 6729: return new ErrorExp(); 6730: } 6731: 6732: void DotTemplateInstanceExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 6733: { 6734: expToCBuffer(buf, hgs, e1, PREC_primary); 6735: buf->writeByte('.'); 6736: ti->toCBuffer(buf, hgs); 6737: } 6738: 6739: /************************************************************/ 6740: 6741: DelegateExp::DelegateExp(Loc loc, Expression *e, FuncDeclaration *f, int hasOverloads) 6742: : UnaExp(loc, TOKdelegate, sizeof(DelegateExp), e) 6743: { 6744: this->func = f; 6745: this->hasOverloads = hasOverloads; 6746: } 6747: 6748: Expression *DelegateExp::semantic(Scope *sc) 6749: { 6750: #if LOGSEMANTIC 6751: printf("DelegateExp::semantic('%s')\n", toChars()); 6752: #endif 6753: if (!type) 6754: { 6755: e1 = e1->semantic(sc); 6756: type = new TypeDelegate(func->type); 6757: type = type->semantic(loc, sc); 6758: AggregateDeclaration *ad = func->toParent()->isAggregateDeclaration(); 6759: if (func->needThis()) 6760: e1 = getRightThis(loc, sc, ad, e1, func); 6761: if (ad && ad->isClassDeclaration() && ad->type != e1->type) 6762: { // A downcast is required for interfaces, see Bugzilla 3706 6763: e1 = new CastExp(loc, e1, ad->type); 6764: e1 = e1->semantic(sc); 6765: } 6766: } 6767: return this; 6768: } 6769: 6770: void DelegateExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 6771: { 6772: buf->writeByte('&'); 6773: if (!func->isNested()) 6774: { 6775: expToCBuffer(buf, hgs, e1, PREC_primary); 6776: buf->writeByte('.'); 6777: } 6778: buf->writestring(func->toChars()); 6779: } 6780: 6781: /************************************************************/ 6782: 6783: DotTypeExp::DotTypeExp(Loc loc, Expression *e, Dsymbol *s) 6784: : UnaExp(loc, TOKdottype, sizeof(DotTypeExp), e) 6785: { 6786: this->sym = s; 6787: this->type = s->getType(); 6788: } 6789: 6790: Expression *DotTypeExp::semantic(Scope *sc) 6791: { 6792: #if LOGSEMANTIC 6793: printf("DotTypeExp::semantic('%s')\n", toChars()); 6794: #endif 6795: UnaExp::semantic(sc); 6796: return this; 6797: } 6798: 6799: void DotTypeExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 6800: { 6801: expToCBuffer(buf, hgs, e1, PREC_primary); 6802: buf->writeByte('.'); 6803: buf->writestring(sym->toChars()); 6804: } 6805: 6806: /************************************************************/ 6807: 6808: CallExp::CallExp(Loc loc, Expression *e, Expressions *exps) 6809: : UnaExp(loc, TOKcall, sizeof(CallExp), e) 6810: { 6811: this->arguments = exps; 6812: } 6813: 6814: CallExp::CallExp(Loc loc, Expression *e) 6815: : UnaExp(loc, TOKcall, sizeof(CallExp), e) 6816: { 6817: this->arguments = NULL; 6818: } 6819: 6820: CallExp::CallExp(Loc loc, Expression *e, Expression *earg1) 6821: : UnaExp(loc, TOKcall, sizeof(CallExp), e) 6822: { 6823: Expressions *arguments = new Expressions(); 6824: if (earg1) 6825: { arguments->setDim(1); 6826: arguments->tdata()[0] = earg1; 6827: } 6828: this->arguments = arguments; 6829: } 6830: 6831: CallExp::CallExp(Loc loc, Expression *e, Expression *earg1, Expression *earg2) 6832: : UnaExp(loc, TOKcall, sizeof(CallExp), e) 6833: { 6834: Expressions *arguments = new Expressions(); 6835: arguments->setDim(2); 6836: arguments->tdata()[0] = earg1; 6837: arguments->tdata()[1] = earg2; 6838: 6839: this->arguments = arguments; 6840: } 6841: 6842: Expression *CallExp::syntaxCopy() 6843: { 6844: return new CallExp(loc, e1->syntaxCopy(), arraySyntaxCopy(arguments)); 6845: } 6846: 6847: 6848: Expression *CallExp::semantic(Scope *sc) 6849: { 6850: TypeFunction *tf; 6851: FuncDeclaration *f; 6852: int i;
warning C4101: 'i' : unreferenced local variable
6853: Type *t1; 6854: int istemp; 6855: Objects *targsi = NULL; // initial list of template arguments 6856: TemplateInstance *tierror = NULL; 6857: Expression *ethis = NULL; 6858: 6859: #if LOGSEMANTIC 6860: printf("CallExp::semantic() %s\n", toChars()); 6861: #endif 6862: if (type) 6863: return this; // semantic() already run 6864: #if 0 6865: if (arguments && arguments->dim) 6866: { 6867: Expression *earg = arguments->tdata()[0]; 6868: earg->print(); 6869: if (earg->type) earg->type->print(); 6870: } 6871: #endif 6872: 6873: if (e1->op == TOKdelegate) 6874: { DelegateExp *de = (DelegateExp *)e1; 6875: 6876: e1 = new DotVarExp(de->loc, de->e1, de->func); 6877: return semantic(sc); 6878: } 6879: 6880: /* Transform: 6881: * array.id(args) into .id(array,args) 6882: * aa.remove(arg) into delete aa[arg] 6883: */ 6884: if (e1->op == TOKdot) 6885: { 6886: // BUG: we should handle array.a.b.c.e(args) too 6887: 6888: DotIdExp *dotid = (DotIdExp *)(e1); 6889: dotid->e1 = dotid->e1->semantic(sc); 6890: assert(dotid->e1); 6891: if (dotid->e1->type) 6892: { 6893: TY e1ty = dotid->e1->type->toBasetype()->ty; 6894: if (e1ty == Taarray && dotid->ident == Id::remove) 6895: { 6896: if (!arguments || arguments->dim != 1) 6897: { error("expected key as argument to aa.remove()"); 6898: return new ErrorExp(); 6899: } 6900: Expression *key = arguments->tdata()[0]; 6901: key = key->semantic(sc); 6902: key = resolveProperties(sc, key); 6903: key->rvalue(); 6904: 6905: TypeAArray *taa = (TypeAArray *)dotid->e1->type->toBasetype(); 6906: key = key->implicitCastTo(sc, taa->index); 6907: 6908: return new RemoveExp(loc, dotid->e1, key); 6909: } 6910: else if (e1ty == Tarray || e1ty == Tsarray || 6911: (e1ty == Taarray && dotid->ident != Id::apply && dotid->ident != Id::applyReverse)) 6912: { 6913: if (e1ty == Taarray) 6914: { TypeAArray *taa = (TypeAArray *)dotid->e1->type->toBasetype(); 6915: assert(taa->ty == Taarray); 6916: StructDeclaration *sd = taa->getImpl(); 6917: Dsymbol *s = sd->search(0, dotid->ident, 2); 6918: if (s) 6919: goto L2; 6920: } 6921: if (!arguments) 6922: arguments = new Expressions(); 6923: arguments->shift(dotid->e1); 6924: #if DMDV2 6925: e1 = new DotIdExp(dotid->loc, new IdentifierExp(dotid->loc, Id::empty), dotid->ident); 6926: #else 6927: e1 = new IdentifierExp(dotid->loc, dotid->ident); 6928: #endif 6929: } 6930: 6931: L2: 6932: ; 6933: } 6934: } 6935: 6936: #if 1 6937: /* This recognizes: 6938: * foo!(tiargs)(funcargs) 6939: */ 6940: if (e1->op == TOKimport && !e1->type) 6941: { ScopeExp *se = (ScopeExp *)e1; 6942: TemplateInstance *ti = se->sds->isTemplateInstance(); 6943: if (ti && !ti->semanticRun) 6944: { 6945: /* Attempt to instantiate ti. If that works, go with it. 6946: * If not, go with partial explicit specialization. 6947: */ 6948: ti->semanticTiargs(sc); 6949: if (ti->needsTypeInference(sc)) 6950: { 6951: /* Go with partial explicit specialization 6952: */ 6953: targsi = ti->tiargs; 6954: tierror = ti; // for error reporting 6955: e1 = new IdentifierExp(loc, ti->name); 6956: } 6957: else 6958: { 6959: ti->semantic(sc); 6960: } 6961: } 6962: } 6963: 6964: /* This recognizes: 6965: * expr.foo!(tiargs)(funcargs) 6966: */ 6967: Ldotti: 6968: if (e1->op == TOKdotti && !e1->type) 6969: { DotTemplateInstanceExp *se = (DotTemplateInstanceExp *)e1; 6970: TemplateInstance *ti = se->ti; 6971: if (!ti->semanticRun) 6972: { 6973: /* Attempt to instantiate ti. If that works, go with it. 6974: * If not, go with partial explicit specialization. 6975: */ 6976: ti->semanticTiargs(sc); 6977: #if 0 6978: Expression *etmp = e1->trySemantic(sc); 6979: if (etmp) 6980: e1 = etmp; // it worked 6981: else // didn't work 6982: { 6983: targsi = ti->tiargs; 6984: tierror = ti; // for error reporting 6985: e1 = new DotIdExp(loc, se->e1, ti->name); 6986: } 6987: #else 6988: if (!ti->tempdecl) 6989: { 6990: se->getTempdecl(sc); 6991: } 6992: if (ti->tempdecl && ti->needsTypeInference(sc)) 6993: { 6994: /* Go with partial explicit specialization 6995: */ 6996: targsi = ti->tiargs; 6997: tierror = ti; // for error reporting 6998: e1 = new DotIdExp(loc, se->e1, ti->name); 6999: } 7000: else 7001: { 7002: e1 = e1->semantic(sc); 7003: } 7004: #endif 7005: } 7006: } 7007: #endif 7008: 7009: istemp = 0; 7010: Lagain: 7011: //printf("Lagain: %s\n", toChars()); 7012: f = NULL; 7013: if (e1->op == TOKthis || e1->op == TOKsuper) 7014: { 7015: // semantic() run later for these 7016: } 7017: else 7018: { 7019: if (e1->op == TOKdot) 7020: { DotIdExp *die = (DotIdExp *)e1; 7021: e1 = die->semantic(sc, 1); 7022: /* Look for e1 having been rewritten to expr.opDispatch!(string) 7023: * We handle such earlier, so go back. 7024: * Note that in the rewrite, we carefully did not run semantic() on e1 7025: */ 7026: if (e1->op == TOKdotti && !e1->type) 7027: { 7028: goto Ldotti; 7029: } 7030: } 7031: else 7032: UnaExp::semantic(sc); 7033: 7034: 7035: /* Look for e1 being a lazy parameter 7036: */ 7037: if (e1->op == TOKvar) 7038: { VarExp *ve = (VarExp *)e1; 7039: 7040: if (ve->var->storage_class & STClazy) 7041: { 7042: TypeFunction *tf = new TypeFunction(NULL, ve->var->type, 0, LINKd);
warning C6246: Local declaration of 'tf' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '6850' of 'c:\projects\extern\d\dmd\src\expression.c': Lines: 6850
7043: TypeDelegate *t = new TypeDelegate(tf); 7044: ve->type = t->semantic(loc, sc); 7045: } 7046: } 7047: 7048: if (e1->op == TOKimport) 7049: { // Perhaps this should be moved to ScopeExp::semantic() 7050: ScopeExp *se = (ScopeExp *)e1; 7051: e1 = new DsymbolExp(loc, se->sds); 7052: e1 = e1->semantic(sc); 7053: } 7054: #if 1 // patch for #540 by Oskar Linde 7055: else if (e1->op == TOKdotexp) 7056: { 7057: DotExp *de = (DotExp *) e1; 7058: 7059: if (de->e2->op == TOKoverloadset) 7060: { 7061: ethis = de->e1; 7062: e1 = de->e2; 7063: } 7064: 7065: if (de->e2->op == TOKimport) 7066: { // This should *really* be moved to ScopeExp::semantic() 7067: ScopeExp *se = (ScopeExp *)de->e2; 7068: de->e2 = new DsymbolExp(loc, se->sds); 7069: de->e2 = de->e2->semantic(sc); 7070: } 7071: 7072: if (de->e2->op == TOKtemplate) 7073: { TemplateExp *te = (TemplateExp *) de->e2; 7074: e1 = new DotTemplateExp(loc,de->e1,te->td); 7075: } 7076: } 7077: #endif 7078: } 7079: 7080: if (e1->op == TOKcomma) 7081: { /* Rewrite (a,b)(args) as (a,(b(args))) 7082: */ 7083: CommaExp *ce = (CommaExp *)e1; 7084: 7085: e1 = ce->e2; 7086: e1->type = ce->type; 7087: ce->e2 = this; 7088: ce->type = NULL; 7089: return ce->semantic(sc); 7090: } 7091: 7092: t1 = NULL; 7093: if (e1->type) 7094: t1 = e1->type->toBasetype(); 7095: 7096: // Check for call operator overload 7097: if (t1) 7098: { AggregateDeclaration *ad; 7099: 7100: if (t1->ty == Tstruct) 7101: { 7102: ad = ((TypeStruct *)t1)->sym; 7103: #if DMDV2 7104: // First look for constructor 7105: if (ad->ctor && arguments && arguments->dim) 7106: { 7107: // Create variable that will get constructed 7108: Identifier *idtmp = Lexer::uniqueId("__ctmp"); 7109: VarDeclaration *tmp = new VarDeclaration(loc, t1, idtmp, NULL); 7110: tmp->storage_class |= STCctfe; 7111: Expression *av = new DeclarationExp(loc, tmp); 7112: av = new CommaExp(loc, av, new VarExp(loc, tmp)); 7113: 7114: Expression *e; 7115: CtorDeclaration *cf = ad->ctor->isCtorDeclaration(); 7116: if (cf) 7117: e = new DotVarExp(loc, av, cf, 1); 7118: else 7119: { TemplateDeclaration *td = ad->ctor->isTemplateDeclaration(); 7120: assert(td); 7121: e = new DotTemplateExp(loc, av, td); 7122: } 7123: e = new CallExp(loc, e, arguments); 7124: #if !STRUCTTHISREF 7125: /* Constructors return a pointer to the instance 7126: */ 7127: e = new PtrExp(loc, e); 7128: #endif 7129: e = e->semantic(sc); 7130: return e; 7131: } 7132: #endif 7133: // No constructor, look for overload of opCall 7134: if (search_function(ad, Id::call)) 7135: goto L1; // overload of opCall, therefore it's a call 7136: 7137: if (e1->op != TOKtype) 7138: { error("%s %s does not overload ()", ad->kind(), ad->toChars()); 7139: return new ErrorExp(); 7140: } 7141: 7142: /* It's a struct literal 7143: */ 7144: Expression *e = new StructLiteralExp(loc, (StructDeclaration *)ad, arguments, e1->type); 7145: e = e->semantic(sc); 7146: return e; 7147: } 7148: else if (t1->ty == Tclass) 7149: { 7150: ad = ((TypeClass *)t1)->sym; 7151: goto L1; 7152: L1: 7153: // Rewrite as e1.call(arguments) 7154: Expression *e = new DotIdExp(loc, e1, Id::call); 7155: e = new CallExp(loc, e, arguments); 7156: e = e->semantic(sc); 7157: return e; 7158: } 7159: } 7160: 7161: arguments = arrayExpressionSemantic(arguments, sc); 7162: 7163: preFunctionParameters(loc, sc, arguments); 7164: 7165: // If there was an error processing any argument, or the call, 7166: // return an error without trying to resolve the function call. 7167: if (arguments && arguments->dim) 7168: { 7169: for (int k = 0; k < arguments->dim; k++)
warning C4018: '<' : signed/unsigned mismatch
7170: { Expression *checkarg = arguments->tdata()[k]; 7171: if (checkarg->op == TOKerror) 7172: return checkarg; 7173: } 7174: } 7175: if (e1->op == TOKerror) 7176: return e1; 7177: 7178: if (e1->op == TOKdotvar && t1->ty == Tfunction || 7179: e1->op == TOKdottd) 7180: { 7181: DotVarExp *dve; 7182: DotTemplateExp *dte; 7183: AggregateDeclaration *ad; 7184: UnaExp *ue = (UnaExp *)(e1); 7185: 7186: if (e1->op == TOKdotvar) 7187: { // Do overload resolution 7188: dve = (DotVarExp *)(e1); 7189: 7190: f = dve->var->isFuncDeclaration(); 7191: assert(f); 7192: f = f->overloadResolve(loc, ue->e1, arguments); 7193: 7194: ad = f->toParent()->isAggregateDeclaration(); 7195: } 7196: else 7197: { dte = (DotTemplateExp *)(e1); 7198: TemplateDeclaration *td = dte->td; 7199: assert(td); 7200: if (!arguments) 7201: // Should fix deduceFunctionTemplate() so it works on NULL argument 7202: arguments = new Expressions(); 7203: f = td->deduceFunctionTemplate(sc, loc, targsi, ue->e1, arguments); 7204: if (!f) 7205: { type = Type::terror; 7206: return this; 7207: } 7208: ad = td->toParent()->isAggregateDeclaration(); 7209: } 7210: if (f->needThis()) 7211: { 7212: ue->e1 = getRightThis(loc, sc, ad, ue->e1, f); 7213: } 7214: 7215: /* Cannot call public functions from inside invariant 7216: * (because then the invariant would have infinite recursion) 7217: */ 7218: if (sc->func && sc->func->isInvariantDeclaration() && 7219: ue->e1->op == TOKthis && 7220: f->addPostInvariant() 7221: ) 7222: { 7223: error("cannot call public/export function %s from invariant", f->toChars()); 7224: return new ErrorExp(); 7225: } 7226: 7227: checkDeprecated(sc, f); 7228: #if DMDV2 7229: checkPurity(sc, f); 7230: checkSafety(sc, f); 7231: #endif 7232: accessCheck(loc, sc, ue->e1, f); 7233: if (!f->needThis()) 7234: { 7235: VarExp *ve = new VarExp(loc, f); 7236: e1 = new CommaExp(loc, ue->e1, ve); 7237: e1->type = f->type; 7238: } 7239: else 7240: { 7241: if (e1->op == TOKdotvar) 7242: dve->var = f; 7243: else 7244: e1 = new DotVarExp(loc, dte->e1, f); 7245: e1->type = f->type; 7246: #if 0 7247: printf("ue->e1 = %s\n", ue->e1->toChars()); 7248: printf("f = %s\n", f->toChars()); 7249: printf("t = %s\n", t->toChars()); 7250: printf("e1 = %s\n", e1->toChars()); 7251: printf("e1->type = %s\n", e1->type->toChars()); 7252: #endif 7253: // Const member function can take const/immutable/mutable/inout this 7254: if (!(f->type->isConst())) 7255: { 7256: // Check for const/immutable compatibility 7257: Type *tthis = ue->e1->type->toBasetype(); 7258: if (tthis->ty == Tpointer) 7259: tthis = tthis->nextOf()->toBasetype(); 7260: #if 0 // this checking should have been already done 7261: if (f->type->isImmutable()) 7262: { 7263: if (tthis->mod != MODimmutable) 7264: error("%s can only be called with an immutable object", e1->toChars()); 7265: } 7266: else if (f->type->isShared()) 7267: { 7268: if (tthis->mod != MODimmutable && 7269: tthis->mod != MODshared && 7270: tthis->mod != (MODshared | MODconst)) 7271: error("shared %s can only be called with a shared or immutable object", e1->toChars()); 7272: } 7273: else 7274: { 7275: if (tthis->mod != 0) 7276: { //printf("mod = %x\n", tthis->mod); 7277: error("%s can only be called with a mutable object, not %s", e1->toChars(), tthis->toChars()); 7278: } 7279: } 7280: #endif 7281: /* Cannot call mutable method on a final struct 7282: */ 7283: if (tthis->ty == Tstruct && 7284: ue->e1->op == TOKvar) 7285: { VarExp *v = (VarExp *)ue->e1; 7286: if (v->var->storage_class & STCfinal) 7287: error("cannot call mutable method on final struct"); 7288: } 7289: } 7290: 7291: // See if we need to adjust the 'this' pointer 7292: AggregateDeclaration *ad = f->isThis();
warning C6246: Local declaration of 'ad' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '7183' of 'c:\projects\extern\d\dmd\src\expression.c': Lines: 7183
7293: ClassDeclaration *cd = ue->e1->type->isClassHandle(); 7294: if (ad && cd && ad->isClassDeclaration() && ad != cd && 7295: ue->e1->op != TOKsuper) 7296: { 7297: ue->e1 = ue->e1->castTo(sc, ad->type); //new CastExp(loc, ue->e1, ad->type); 7298: ue->e1 = ue->e1->semantic(sc); 7299: } 7300: } 7301: t1 = e1->type; 7302: } 7303: else if (e1->op == TOKsuper) 7304: { 7305: // Base class constructor call 7306: ClassDeclaration *cd = NULL; 7307: 7308: if (sc->func) 7309: cd = sc->func->toParent()->isClassDeclaration(); 7310: if (!cd || !cd->baseClass || !sc->func->isCtorDeclaration()) 7311: { 7312: error("super class constructor call must be in a constructor"); 7313: return new ErrorExp(); 7314: } 7315: else 7316: { 7317: if (!cd->baseClass->ctor) 7318: { error("no super class constructor for %s", cd->baseClass->toChars()); 7319: return new ErrorExp(); 7320: } 7321: else 7322: { 7323: if (!sc->intypeof) 7324: { 7325: #if 0 7326: if (sc->callSuper & (CSXthis | CSXsuper)) 7327: error("reference to this before super()"); 7328: #endif 7329: if (sc->noctor || sc->callSuper & CSXlabel) 7330: error("constructor calls not allowed in loops or after labels"); 7331: if (sc->callSuper & (CSXsuper_ctor | CSXthis_ctor)) 7332: error("multiple constructor calls"); 7333: sc->callSuper |= CSXany_ctor | CSXsuper_ctor; 7334: } 7335: 7336: f = resolveFuncCall(sc, loc, cd->baseClass->ctor, NULL, NULL, arguments, 0); 7337: checkDeprecated(sc, f); 7338: #if DMDV2 7339: checkPurity(sc, f); 7340: checkSafety(sc, f); 7341: #endif 7342: e1 = new DotVarExp(e1->loc, e1, f); 7343: e1 = e1->semantic(sc); 7344: t1 = e1->type; 7345: } 7346: } 7347: } 7348: else if (e1->op == TOKthis) 7349: { 7350: // same class constructor call 7351: AggregateDeclaration *cd = NULL; 7352: 7353: if (sc->func) 7354: cd = sc->func->toParent()->isAggregateDeclaration(); 7355: if (!cd || !sc->func->isCtorDeclaration()) 7356: { 7357: error("constructor call must be in a constructor"); 7358: return new ErrorExp(); 7359: } 7360: else 7361: { 7362: if (!sc->intypeof) 7363: { 7364: #if 0 7365: if (sc->callSuper & (CSXthis | CSXsuper)) 7366: error("reference to this before super()"); 7367: #endif 7368: if (sc->noctor || sc->callSuper & CSXlabel) 7369: error("constructor calls not allowed in loops or after labels"); 7370: if (sc->callSuper & (CSXsuper_ctor | CSXthis_ctor)) 7371: error("multiple constructor calls"); 7372: sc->callSuper |= CSXany_ctor | CSXthis_ctor; 7373: } 7374: 7375: f = resolveFuncCall(sc, loc, cd->ctor, NULL, NULL, arguments, 0); 7376: checkDeprecated(sc, f); 7377: #if DMDV2 7378: checkPurity(sc, f); 7379: checkSafety(sc, f); 7380: #endif 7381: e1 = new DotVarExp(e1->loc, e1, f); 7382: e1 = e1->semantic(sc); 7383: t1 = e1->type; 7384: 7385: // BUG: this should really be done by checking the static 7386: // call graph 7387: if (f == sc->func) 7388: { error("cyclic constructor call"); 7389: return new ErrorExp(); 7390: } 7391: } 7392: } 7393: else if (e1->op == TOKoverloadset) 7394: { 7395: OverExp *eo = (OverExp *)e1; 7396: FuncDeclaration *f = NULL;
warning C6246: Local declaration of 'f' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '6851' of 'c:\projects\extern\d\dmd\src\expression.c': Lines: 6851
7397: Dsymbol *s = NULL; 7398: for (int i = 0; i < eo->vars->a.dim; i++)
warning C4018: '<' : signed/unsigned mismatch
warning C6246: Local declaration of 'i' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '6852' of 'c:\projects\extern\d\dmd\src\expression.c': Lines: 6852
7399: { s = eo->vars->a.tdata()[i]; 7400: FuncDeclaration *f2 = s->isFuncDeclaration(); 7401: if (f2) 7402: { 7403: f2 = f2->overloadResolve(loc, ethis, arguments, 1); 7404: } 7405: else 7406: { TemplateDeclaration *td = s->isTemplateDeclaration(); 7407: assert(td); 7408: f2 = td->deduceFunctionTemplate(sc, loc, targsi, ethis, arguments, 1); 7409: } 7410: if (f2) 7411: { if (f) 7412: /* Error if match in more than one overload set, 7413: * even if one is a 'better' match than the other. 7414: */ 7415: ScopeDsymbol::multiplyDefined(loc, f, f2); 7416: else 7417: f = f2; 7418: } 7419: } 7420: if (!f) 7421: { /* No overload matches 7422: */ 7423: error("no overload matches for %s", s->toChars()); 7424: return new ErrorExp(); 7425: } 7426: if (ethis) 7427: e1 = new DotVarExp(loc, ethis, f); 7428: else 7429: e1 = new VarExp(loc, f); 7430: goto Lagain; 7431: } 7432: else if (!t1) 7433: { 7434: error("function expected before (), not '%s'", e1->toChars()); 7435: return new ErrorExp(); 7436: } 7437: else if (t1->ty != Tfunction) 7438: { 7439: if (t1->ty == Tdelegate) 7440: { TypeDelegate *td = (TypeDelegate *)t1; 7441: assert(td->next->ty == Tfunction); 7442: tf = (TypeFunction *)(td->next); 7443: if (sc->func && !tf->purity && !(sc->flags & SCOPEdebug)) 7444: { 7445: if (sc->func->setImpure()) 7446: error("pure function '%s' cannot call impure delegate '%s'", sc->func->toChars(), e1->toChars()); 7447: } 7448: if (sc->func && tf->trust <= TRUSTsystem) 7449: { 7450: if (sc->func->setUnsafe()) 7451: error("safe function '%s' cannot call system delegate '%s'", sc->func->toChars(), e1->toChars()); 7452: } 7453: goto Lcheckargs; 7454: } 7455: else if (t1->ty == Tpointer && ((TypePointer *)t1)->next->ty == Tfunction) 7456: { 7457: Expression *e = new PtrExp(loc, e1); 7458: t1 = ((TypePointer *)t1)->next; 7459: if (sc->func && !((TypeFunction *)t1)->purity && !(sc->flags & SCOPEdebug)) 7460: { 7461: if (sc->func->setImpure()) 7462: error("pure function '%s' cannot call impure function pointer '%s'", sc->func->toChars(), e1->toChars()); 7463: } 7464: if (sc->func && !((TypeFunction *)t1)->trust <= TRUSTsystem)
warning C4804: '<=' : unsafe use of type 'bool' in operation
7465: { 7466: if (sc->func->setUnsafe()) 7467: error("safe function '%s' cannot call system function pointer '%s'", sc->func->toChars(), e1->toChars()); 7468: } 7469: e->type = t1; 7470: e1 = e; 7471: } 7472: else if (e1->op == TOKtemplate) 7473: { 7474: TemplateExp *te = (TemplateExp *)e1; 7475: f = te->td->deduceFunctionTemplate(sc, loc, targsi, NULL, arguments); 7476: if (!f) 7477: { if (tierror) 7478: tierror->error("errors instantiating template"); // give better error message 7479: return new ErrorExp(); 7480: } 7481: if (f->needThis() && hasThis(sc)) 7482: { 7483: // Supply an implicit 'this', as in 7484: // this.ident 7485: 7486: e1 = new DotTemplateExp(loc, (new ThisExp(loc))->semantic(sc), te->td); 7487: goto Lagain; 7488: } 7489: 7490: e1 = new VarExp(loc, f); 7491: goto Lagain; 7492: } 7493: else 7494: { error("function expected before (), not %s of type %s", e1->toChars(), e1->type->toChars()); 7495: return new ErrorExp(); 7496: } 7497: } 7498: else if (e1->op == TOKvar) 7499: { 7500: // Do overload resolution 7501: VarExp *ve = (VarExp *)e1; 7502: 7503: f = ve->var->isFuncDeclaration(); 7504: assert(f); 7505: 7506: if (ve->hasOverloads) 7507: f = f->overloadResolve(loc, NULL, arguments); 7508: checkDeprecated(sc, f); 7509: #if DMDV2 7510: checkPurity(sc, f); 7511: checkSafety(sc, f); 7512: #endif 7513: 7514: if (f->needThis() && hasThis(sc)) 7515: { 7516: // Supply an implicit 'this', as in 7517: // this.ident 7518: 7519: e1 = new DotVarExp(loc, new ThisExp(loc), f); 7520: goto Lagain; 7521: } 7522: 7523: accessCheck(loc, sc, NULL, f); 7524: 7525: ve->var = f; 7526: // ve->hasOverloads = 0; 7527: ve->type = f->type; 7528: t1 = f->type; 7529: } 7530: assert(t1->ty == Tfunction); 7531: tf = (TypeFunction *)(t1); 7532: 7533: Lcheckargs: 7534: assert(tf->ty == Tfunction); 7535: 7536: if (!arguments) 7537: arguments = new Expressions(); 7538: type = functionParameters(loc, sc, tf, arguments, f); 7539: 7540: if (!type) 7541: { 7542: error("forward reference to inferred return type of function call %s", toChars()); 7543: return new ErrorExp(); 7544: } 7545: 7546: if (f && f->tintro) 7547: { 7548: Type *t = type; 7549: int offset = 0; 7550: TypeFunction *tf = (TypeFunction *)f->tintro;
warning C6246: Local declaration of 'tf' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '6850' of 'c:\projects\extern\d\dmd\src\expression.c': Lines: 6850
7551: 7552: if (tf->next->isBaseOf(t, &offset) && offset) 7553: { 7554: type = tf->next; 7555: return castTo(sc, t); 7556: } 7557: } 7558: 7559: return this; 7560: } 7561: 7562: int CallExp::checkSideEffect(int flag) 7563: { 7564: #if DMDV2 7565: int result = 1; 7566: 7567: /* Calling a function or delegate that is pure nothrow 7568: * has no side effects. 7569: */ 7570: if (e1->type) 7571: { 7572: Type *t = e1->type->toBasetype(); 7573: if ((t->ty == Tfunction && ((TypeFunction *)t)->purity > PUREweak && 7574: ((TypeFunction *)t)->isnothrow) 7575: || 7576: (t->ty == Tdelegate && ((TypeFunction *)((TypeDelegate *)t)->next)->purity > PUREweak && 7577: ((TypeFunction *)((TypeDelegate *)t)->next)->isnothrow) 7578: ) 7579: { 7580: result = 0; 7581: //if (flag == 0) 7582: //warning("pure nothrow function %s has no effect", e1->toChars()); 7583: } 7584: else 7585: result = 1; 7586: } 7587: 7588: result |= e1->checkSideEffect(1); 7589: 7590: /* If any of the arguments have side effects, this expression does 7591: */ 7592: for (size_t i = 0; i < arguments->dim; i++) 7593: { Expression *e = arguments->tdata()[i]; 7594: 7595: result |= e->checkSideEffect(1); 7596: } 7597: 7598: return result; 7599: #else 7600: return 1; 7601: #endif 7602: } 7603: 7604: #if DMDV2 7605: int CallExp::canThrow(bool mustNotThrow) 7606: { 7607: //printf("CallExp::canThrow() %s\n", toChars()); 7608: if (e1->canThrow(mustNotThrow)) 7609: return 1; 7610: 7611: /* If any of the arguments can throw, then this expression can throw 7612: */ 7613: if (arrayExpressionCanThrow(arguments, mustNotThrow)) 7614: return 1; 7615: 7616: if (global.errors && !e1->type) 7617: return 0; // error recovery 7618: 7619: /* If calling a function or delegate that is typed as nothrow, 7620: * then this expression cannot throw. 7621: * Note that pure functions can throw. 7622: */ 7623: Type *t = e1->type->toBasetype(); 7624: if (t->ty == Tfunction && ((TypeFunction *)t)->isnothrow) 7625: return 0; 7626: if (t->ty == Tdelegate && ((TypeFunction *)((TypeDelegate *)t)->next)->isnothrow) 7627: return 0; 7628: if (mustNotThrow) 7629: error("%s is not nothrow", e1->toChars()); 7630: return 1; 7631: } 7632: #endif 7633: 7634: #if DMDV2 7635: int CallExp::isLvalue() 7636: { 7637: // if (type->toBasetype()->ty == Tstruct) 7638: // return 1; 7639: Type *tb = e1->type->toBasetype(); 7640: if (tb->ty == Tfunction && ((TypeFunction *)tb)->isref) 7641: return 1; // function returns a reference 7642: return 0; 7643: } 7644: #endif 7645: 7646: Expression *CallExp::toLvalue(Scope *sc, Expression *e) 7647: { 7648: if (isLvalue()) 7649: return this; 7650: return Expression::toLvalue(sc, e); 7651: } 7652: 7653: Expression *CallExp::addDtorHook(Scope *sc) 7654: { 7655: /* Only need to add dtor hook if it's a type that needs destruction. 7656: * Use same logic as VarDeclaration::callScopeDtor() 7657: */ 7658: 7659: if (e1->type && e1->type->ty == Tfunction) 7660: { 7661: TypeFunction *tf = (TypeFunction *)e1->type; 7662: if (tf->isref) 7663: return this; 7664: } 7665: 7666: Type *tv = type->toBasetype(); 7667: while (tv->ty == Tsarray) 7668: { TypeSArray *ta = (TypeSArray *)tv; 7669: tv = tv->nextOf()->toBasetype(); 7670: } 7671: if (tv->ty == Tstruct) 7672: { TypeStruct *ts = (TypeStruct *)tv; 7673: StructDeclaration *sd = ts->sym; 7674: if (sd->dtor) 7675: { /* Type needs destruction, so declare a tmp 7676: * which the back end will recognize and call dtor on 7677: */ 7678: if (e1->op == TOKdotvar) 7679: { 7680: DotVarExp* dve = (DotVarExp*)e1; 7681: if (dve->e1->isTemp() != NULL) 7682: goto Lnone; // already got a tmp 7683: } 7684: 7685: Identifier *idtmp = Lexer::uniqueId("__tmpfordtor"); 7686: VarDeclaration *tmp = new VarDeclaration(loc, type, idtmp, new ExpInitializer(loc, this)); 7687: tmp->storage_class |= STCctfe; 7688: Expression *ae = new DeclarationExp(loc, tmp); 7689: Expression *e = new CommaExp(loc, ae, new VarExp(loc, tmp)); 7690: e = e->semantic(sc); 7691: return e; 7692: } 7693: } 7694: Lnone: 7695: return this; 7696: } 7697: 7698: void CallExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 7699: { 7700: if (e1->op == TOKtype) 7701: /* Avoid parens around type to prevent forbidden cast syntax: 7702: * (sometype)(arg1) 7703: * This is ok since types in constructor calls 7704: * can never depend on parens anyway 7705: */ 7706: e1->toCBuffer(buf, hgs); 7707: else 7708: expToCBuffer(buf, hgs, e1, precedence[op]); 7709: buf->writeByte('('); 7710: argsToCBuffer(buf, arguments, hgs); 7711: buf->writeByte(')'); 7712: } 7713: 7714: 7715: /************************************************************/ 7716: 7717: AddrExp::AddrExp(Loc loc, Expression *e) 7718: : UnaExp(loc, TOKaddress, sizeof(AddrExp), e) 7719: { 7720: } 7721: 7722: Expression *AddrExp::semantic(Scope *sc) 7723: { 7724: #if LOGSEMANTIC 7725: printf("AddrExp::semantic('%s')\n", toChars()); 7726: #endif 7727: if (!type) 7728: { 7729: UnaExp::semantic(sc); 7730: if (e1->type == Type::terror) 7731: return new ErrorExp(); 7732: e1 = e1->toLvalue(sc, NULL); 7733: if (e1->op == TOKerror) 7734: return e1; 7735: if (!e1->type) 7736: { 7737: error("cannot take address of %s", e1->toChars()); 7738: return new ErrorExp(); 7739: } 7740: if (!e1->type->deco) 7741: { 7742: /* No deco means semantic() was not run on the type. 7743: * We have to run semantic() on the symbol to get the right type: 7744: * auto x = &bar; 7745: * pure: int bar() { return 1;} 7746: * otherwise the 'pure' is missing from the type assigned to x. 7747: */ 7748: 7749: error("forward reference to %s", e1->toChars()); 7750: return new ErrorExp(); 7751: } 7752: 7753: type = e1->type->pointerTo(); 7754: 7755: // See if this should really be a delegate 7756: if (e1->op == TOKdotvar) 7757: { 7758: DotVarExp *dve = (DotVarExp *)e1; 7759: FuncDeclaration *f = dve->var->isFuncDeclaration(); 7760: 7761: if (f) 7762: { 7763: if (!dve->hasOverloads) 7764: f->tookAddressOf++; 7765: Expression *e = new DelegateExp(loc, dve->e1, f, dve->hasOverloads); 7766: e = e->semantic(sc); 7767: return e; 7768: } 7769: } 7770: else if (e1->op == TOKvar) 7771: { 7772: VarExp *ve = (VarExp *)e1; 7773: 7774: VarDeclaration *v = ve->var->isVarDeclaration(); 7775: if (v) 7776: { 7777: if (!v->canTakeAddressOf()) 7778: { error("cannot take address of %s", e1->toChars()); 7779: return new ErrorExp(); 7780: } 7781: 7782: if (sc->func && !sc->intypeof && !v->isDataseg()) 7783: { 7784: if (sc->func->setUnsafe()) 7785: { 7786: error("cannot take address of %s %s in @safe function %s", 7787: v->isParameter() ? "parameter" : "local", 7788: v->toChars(), 7789: sc->func->toChars()); 7790: } 7791: } 7792: } 7793: 7794: FuncDeclaration *f = ve->var->isFuncDeclaration(); 7795: 7796: if (f) 7797: { 7798: if (!ve->hasOverloads || 7799: /* Because nested functions cannot be overloaded, 7800: * mark here that we took its address because castTo() 7801: * may not be called with an exact match. 7802: */ 7803: f->toParent2()->isFuncDeclaration()) 7804: f->tookAddressOf++; 7805: if (f->isNested()) 7806: { 7807: Expression *e = new DelegateExp(loc, e1, f, ve->hasOverloads); 7808: e = e->semantic(sc); 7809: return e; 7810: } 7811: if (f->needThis() && hasThis(sc)) 7812: { 7813: /* Should probably supply 'this' after overload resolution, 7814: * not before. 7815: */ 7816: Expression *ethis = new ThisExp(loc); 7817: Expression *e = new DelegateExp(loc, ethis, f, ve->hasOverloads); 7818: e = e->semantic(sc); 7819: return e; 7820: } 7821: } 7822: } 7823: return optimize(WANTvalue); 7824: } 7825: return this; 7826: } 7827: 7828: void AddrExp::checkEscape() 7829: { 7830: e1->checkEscapeRef(); 7831: } 7832: 7833: /************************************************************/ 7834: 7835: PtrExp::PtrExp(Loc loc, Expression *e) 7836: : UnaExp(loc, TOKstar, sizeof(PtrExp), e) 7837: { 7838: // if (e->type) 7839: // type = ((TypePointer *)e->type)->next; 7840: } 7841: 7842: PtrExp::PtrExp(Loc loc, Expression *e, Type *t) 7843: : UnaExp(loc, TOKstar, sizeof(PtrExp), e) 7844: { 7845: type = t; 7846: } 7847: 7848: Expression *PtrExp::semantic(Scope *sc) 7849: { 7850: #if LOGSEMANTIC 7851: printf("PtrExp::semantic('%s')\n", toChars()); 7852: #endif 7853: if (!type) 7854: { 7855: Expression *e = op_overload(sc); 7856: if (e) 7857: return e; 7858: Type *tb = e1->type->toBasetype(); 7859: switch (tb->ty) 7860: { 7861: case Tpointer: 7862: type = ((TypePointer *)tb)->next; 7863: break; 7864: 7865: case Tsarray: 7866: case Tarray: 7867: type = ((TypeArray *)tb)->next; 7868: e1 = e1->castTo(sc, type->pointerTo()); 7869: break; 7870: 7871: default: 7872: error("can only * a pointer, not a '%s'", e1->type->toChars()); 7873: case Terror: 7874: return new ErrorExp(); 7875: } 7876: rvalue(); 7877: } 7878: return this; 7879: } 7880: 7881: #if DMDV2 7882: int PtrExp::isLvalue() 7883: { 7884: return 1; 7885: } 7886: #endif 7887: 7888: void PtrExp::checkEscapeRef() 7889: { 7890: e1->checkEscape(); 7891: } 7892: 7893: Expression *PtrExp::toLvalue(Scope *sc, Expression *e) 7894: { 7895: #if 0 7896: tym = tybasic(e1->ET->Tty); 7897: if (!(tyscalar(tym) || 7898: tym == TYstruct || 7899: tym == TYarray && e->Eoper == TOKaddr)) 7900: synerr(EM_lvalue); // lvalue expected 7901: #endif 7902: return this; 7903: } 7904: 7905: #if DMDV2 7906: Expression *PtrExp::modifiableLvalue(Scope *sc, Expression *e) 7907: { 7908: //printf("PtrExp::modifiableLvalue() %s, type %s\n", toChars(), type->toChars()); 7909: 7910: if (e1->op == TOKsymoff) 7911: { SymOffExp *se = (SymOffExp *)e1; 7912: se->var->checkModify(loc, sc, type); 7913: //return toLvalue(sc, e); 7914: } 7915: 7916: return Expression::modifiableLvalue(sc, e); 7917: } 7918: #endif 7919: 7920: void PtrExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 7921: { 7922: buf->writeByte('*'); 7923: expToCBuffer(buf, hgs, e1, precedence[op]); 7924: } 7925: 7926: /************************************************************/ 7927: 7928: NegExp::NegExp(Loc loc, Expression *e) 7929: : UnaExp(loc, TOKneg, sizeof(NegExp), e) 7930: { 7931: } 7932: 7933: Expression *NegExp::semantic(Scope *sc) 7934: { Expression *e; 7935: 7936: #if LOGSEMANTIC 7937: printf("NegExp::semantic('%s')\n", toChars()); 7938: #endif 7939: if (!type) 7940: { 7941: e = op_overload(sc); 7942: if (e) 7943: return e; 7944: 7945: e1->checkNoBool(); 7946: if (!e1->isArrayOperand()) 7947: e1->checkArithmetic(); 7948: type = e1->type; 7949: } 7950: return this; 7951: } 7952: 7953: /************************************************************/ 7954: 7955: UAddExp::UAddExp(Loc loc, Expression *e) 7956: : UnaExp(loc, TOKuadd, sizeof(UAddExp), e) 7957: { 7958: } 7959: 7960: Expression *UAddExp::semantic(Scope *sc) 7961: { Expression *e; 7962: 7963: #if LOGSEMANTIC 7964: printf("UAddExp::semantic('%s')\n", toChars()); 7965: #endif 7966: assert(!type); 7967: e = op_overload(sc); 7968: if (e) 7969: return e; 7970: e1->checkNoBool(); 7971: e1->checkArithmetic(); 7972: return e1; 7973: } 7974: 7975: /************************************************************/ 7976: 7977: ComExp::ComExp(Loc loc, Expression *e) 7978: : UnaExp(loc, TOKtilde, sizeof(ComExp), e) 7979: { 7980: } 7981: 7982: Expression *ComExp::semantic(Scope *sc) 7983: { Expression *e; 7984: 7985: if (!type) 7986: { 7987: e = op_overload(sc); 7988: if (e) 7989: return e; 7990: 7991: e1->checkNoBool(); 7992: if (!e1->isArrayOperand()) 7993: e1 = e1->checkIntegral(); 7994: type = e1->type; 7995: } 7996: return this; 7997: } 7998: 7999: /************************************************************/ 8000: 8001: NotExp::NotExp(Loc loc, Expression *e) 8002: : UnaExp(loc, TOKnot, sizeof(NotExp), e) 8003: { 8004: } 8005: 8006: Expression *NotExp::semantic(Scope *sc) 8007: { 8008: if (!type) 8009: { // Note there is no operator overload 8010: UnaExp::semantic(sc); 8011: e1 = resolveProperties(sc, e1); 8012: e1 = e1->checkToBoolean(sc); 8013: type = Type::tboolean; 8014: } 8015: return this; 8016: } 8017: 8018: int NotExp::isBit() 8019: { 8020: return TRUE; 8021: } 8022: 8023: 8024: 8025: /************************************************************/ 8026: 8027: BoolExp::BoolExp(Loc loc, Expression *e, Type *t) 8028: : UnaExp(loc, TOKtobool, sizeof(BoolExp), e) 8029: { 8030: type = t; 8031: } 8032: 8033: Expression *BoolExp::semantic(Scope *sc) 8034: { 8035: if (!type) 8036: { // Note there is no operator overload 8037: UnaExp::semantic(sc); 8038: e1 = resolveProperties(sc, e1); 8039: e1 = e1->checkToBoolean(sc); 8040: type = Type::tboolean; 8041: } 8042: return this; 8043: } 8044: 8045: int BoolExp::isBit() 8046: { 8047: return TRUE; 8048: } 8049: 8050: /************************************************************/ 8051: 8052: DeleteExp::DeleteExp(Loc loc, Expression *e) 8053: : UnaExp(loc, TOKdelete, sizeof(DeleteExp), e) 8054: { 8055: } 8056: 8057: Expression *DeleteExp::semantic(Scope *sc) 8058: { 8059: Type *tb; 8060: 8061: UnaExp::semantic(sc); 8062: e1 = resolveProperties(sc, e1); 8063: e1 = e1->toLvalue(sc, NULL); 8064: if (e1->op == TOKerror) 8065: return e1; 8066: type = Type::tvoid; 8067: 8068: tb = e1->type->toBasetype(); 8069: switch (tb->ty) 8070: { case Tclass: 8071: { TypeClass *tc = (TypeClass *)tb; 8072: ClassDeclaration *cd = tc->sym; 8073: 8074: if (cd->isCOMinterface()) 8075: { /* Because COM classes are deleted by IUnknown.Release() 8076: */ 8077: error("cannot delete instance of COM interface %s", cd->toChars()); 8078: } 8079: break; 8080: } 8081: case Tpointer: 8082: tb = ((TypePointer *)tb)->next->toBasetype(); 8083: if (tb->ty == Tstruct) 8084: { 8085: TypeStruct *ts = (TypeStruct *)tb; 8086: StructDeclaration *sd = ts->sym; 8087: FuncDeclaration *f = sd->aggDelete; 8088: FuncDeclaration *fd = sd->dtor; 8089: 8090: if (!f && !fd) 8091: break; 8092: 8093: /* Construct: 8094: * ea = copy e1 to a tmp to do side effects only once 8095: * eb = call destructor 8096: * ec = call deallocator 8097: */ 8098: Expression *ea = NULL; 8099: Expression *eb = NULL; 8100: Expression *ec = NULL; 8101: VarDeclaration *v; 8102: 8103: if (fd && f) 8104: { Identifier *id = Lexer::idPool("__tmp"); 8105: v = new VarDeclaration(loc, e1->type, id, new ExpInitializer(loc, e1)); 8106: v->semantic(sc); 8107: v->parent = sc->parent; 8108: ea = new DeclarationExp(loc, v); 8109: ea->type = v->type; 8110: } 8111: 8112: if (fd) 8113: { Expression *e = ea ? new VarExp(loc, v) : e1; 8114: e = new DotVarExp(0, e, fd, 0); 8115: eb = new CallExp(loc, e); 8116: eb = eb->semantic(sc); 8117: } 8118: 8119: if (f) 8120: { 8121: Type *tpv = Type::tvoid->pointerTo(); 8122: Expression *e = ea ? new VarExp(loc, v) : e1->castTo(sc, tpv); 8123: e = new CallExp(loc, new VarExp(loc, f), e); 8124: ec = e->semantic(sc); 8125: } 8126: ea = combine(ea, eb); 8127: ea = combine(ea, ec); 8128: assert(ea); 8129: return ea; 8130: } 8131: break; 8132: 8133: case Tarray: 8134: /* BUG: look for deleting arrays of structs with dtors. 8135: */ 8136: break; 8137: 8138: default: 8139: if (e1->op == TOKindex) 8140: { 8141: IndexExp *ae = (IndexExp *)(e1); 8142: Type *tb1 = ae->e1->type->toBasetype(); 8143: if (tb1->ty == Taarray) 8144: break; 8145: } 8146: error("cannot delete type %s", e1->type->toChars()); 8147: return new ErrorExp(); 8148: } 8149: 8150: if (e1->op == TOKindex) 8151: { 8152: IndexExp *ae = (IndexExp *)(e1); 8153: Type *tb1 = ae->e1->type->toBasetype(); 8154: if (tb1->ty == Taarray) 8155: { if (!global.params.useDeprecated) 8156: error("delete aa[key] deprecated, use aa.remove(key)"); 8157: } 8158: } 8159: 8160: return this; 8161: } 8162: 8163: int DeleteExp::checkSideEffect(int flag) 8164: { 8165: return 1; 8166: } 8167: 8168: Expression *DeleteExp::checkToBoolean(Scope *sc) 8169: { 8170: error("delete does not give a boolean result"); 8171: return new ErrorExp(); 8172: } 8173: 8174: void DeleteExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 8175: { 8176: buf->writestring("delete "); 8177: expToCBuffer(buf, hgs, e1, precedence[op]); 8178: } 8179: 8180: /************************************************************/ 8181: 8182: CastExp::CastExp(Loc loc, Expression *e, Type *t) 8183: : UnaExp(loc, TOKcast, sizeof(CastExp), e) 8184: { 8185: to = t; 8186: this->mod = ~0; 8187: } 8188: 8189: #if DMDV2 8190: /* For cast(const) and cast(immutable) 8191: */ 8192: CastExp::CastExp(Loc loc, Expression *e, unsigned mod) 8193: : UnaExp(loc, TOKcast, sizeof(CastExp), e) 8194: { 8195: to = NULL; 8196: this->mod = mod; 8197: } 8198: #endif 8199: 8200: Expression *CastExp::syntaxCopy() 8201: { 8202: return to ? new CastExp(loc, e1->syntaxCopy(), to->syntaxCopy()) 8203: : new CastExp(loc, e1->syntaxCopy(), mod); 8204: } 8205: 8206: 8207: Expression *CastExp::semantic(Scope *sc) 8208: { Expression *e; 8209: BinExp *b;
warning C4101: 'b' : unreferenced local variable
8210: UnaExp *u;
warning C4101: 'u' : unreferenced local variable
8211: 8212: #if LOGSEMANTIC 8213: printf("CastExp::semantic('%s')\n", toChars()); 8214: #endif 8215: 8216: //static int x; assert(++x < 10); 8217: 8218: if (type) 8219: return this; 8220: UnaExp::semantic(sc); 8221: if (e1->type) // if not a tuple 8222: { 8223: e1 = resolveProperties(sc, e1); 8224: 8225: if (!to) 8226: { 8227: /* Handle cast(const) and cast(immutable), etc. 8228: */ 8229: to = e1->type->castMod(mod); 8230: } 8231: else 8232: to = to->semantic(loc, sc); 8233: 8234: if (!to->equals(e1->type)) 8235: { 8236: e = op_overload(sc); 8237: if (e) 8238: { 8239: return e->implicitCastTo(sc, to); 8240: } 8241: } 8242: 8243: if (e1->op == TOKtemplate) 8244: { 8245: error("cannot cast template %s to type %s", e1->toChars(), to->toChars()); 8246: return new ErrorExp(); 8247: } 8248: 8249: Type *t1b = e1->type->toBasetype(); 8250: Type *tob = to->toBasetype(); 8251: if (tob->ty == Tstruct && 8252: !tob->equals(t1b) 8253: ) 8254: { 8255: /* Look to replace: 8256: * cast(S)t 8257: * with: 8258: * S(t) 8259: */ 8260: 8261: // Rewrite as to.call(e1) 8262: e = new TypeExp(loc, to); 8263: e = new CallExp(loc, e, e1); 8264: e = e->trySemantic(sc); 8265: if (e) 8266: return e; 8267: } 8268: 8269: // Struct casts are possible only when the sizes match 8270: if (tob->ty == Tstruct || t1b->ty == Tstruct) 8271: { 8272: size_t fromsize = t1b->size(loc);
warning C4244: 'initializing' : conversion from 'd_uns64' to 'size_t', possible loss of data
8273: size_t tosize = tob->size(loc);
warning C4244: 'initializing' : conversion from 'd_uns64' to 'size_t', possible loss of data
8274: if (fromsize != tosize) 8275: { 8276: error("cannot cast from %s to %s", e1->type->toChars(), to->toChars()); 8277: return new ErrorExp(); 8278: } 8279: } 8280: } 8281: else if (!to) 8282: { error("cannot cast tuple"); 8283: return new ErrorExp(); 8284: } 8285: 8286: if (!e1->type) 8287: { error("cannot cast %s", e1->toChars()); 8288: return new ErrorExp(); 8289: } 8290: 8291: // Check for unsafe casts 8292: if (sc->func && !sc->intypeof) 8293: { // Disallow unsafe casts 8294: Type *tob = to->toBasetype(); 8295: Type *t1b = e1->type->toBasetype(); 8296: 8297: // Implicit conversions are always safe 8298: if (t1b->implicitConvTo(tob)) 8299: goto Lsafe; 8300: 8301: if (!t1b->isMutable() && tob->isMutable()) 8302: goto Lunsafe; 8303: 8304: if (t1b->isShared() && !tob->isShared()) 8305: // Cast away shared 8306: goto Lunsafe; 8307: 8308: if (!tob->hasPointers()) 8309: goto Lsafe; 8310: 8311: if (tob->ty == Tclass && t1b->ty == Tclass) 8312: { 8313: ClassDeclaration *cdfrom = t1b->isClassHandle(); 8314: ClassDeclaration *cdto = tob->isClassHandle(); 8315: 8316: int offset; 8317: if (!cdfrom->isBaseOf(cdto, &offset)) 8318: goto Lunsafe; 8319: 8320: if (cdfrom->isCPPinterface() || 8321: cdto->isCPPinterface()) 8322: goto Lunsafe; 8323: 8324: goto Lsafe; 8325: } 8326: 8327: if (tob->ty == Tarray && t1b->ty == Tarray) 8328: { 8329: Type* tobn = tob->nextOf()->toBasetype(); 8330: Type* t1bn = t1b->nextOf()->toBasetype(); 8331: if (!tobn->hasPointers() && MODimplicitConv(t1bn->mod, tobn->mod)) 8332: goto Lsafe; 8333: } 8334: if (tob->ty == Tpointer && t1b->ty == Tpointer) 8335: { 8336: Type* tobn = tob->nextOf()->toBasetype(); 8337: Type* t1bn = t1b->nextOf()->toBasetype(); 8338: if (!tobn->hasPointers() && 8339: tobn->ty != Tfunction && t1bn->ty != Tfunction && 8340: tobn->size() <= t1bn->size() && 8341: MODimplicitConv(t1bn->mod, tobn->mod)) 8342: goto Lsafe; 8343: } 8344: 8345: Lunsafe: 8346: if (sc->func->setUnsafe()) 8347: { error("cast from %s to %s not allowed in safe code", e1->type->toChars(), to->toChars()); 8348: return new ErrorExp(); 8349: } 8350: } 8351: 8352: Lsafe: 8353: e = e1->castTo(sc, to); 8354: return e; 8355: } 8356: 8357: int CastExp::checkSideEffect(int flag) 8358: { 8359: /* if not: 8360: * cast(void) 8361: * cast(classtype)func() 8362: */ 8363: if (!to->equals(Type::tvoid) && 8364: !(to->ty == Tclass && e1->op == TOKcall && e1->type->ty == Tclass)) 8365: return Expression::checkSideEffect(flag); 8366: return 1; 8367: } 8368: 8369: void CastExp::checkEscape() 8370: { Type *tb = type->toBasetype(); 8371: if (tb->ty == Tarray && e1->op == TOKvar && 8372: e1->type->toBasetype()->ty == Tsarray) 8373: { VarExp *ve = (VarExp *)e1; 8374: VarDeclaration *v = ve->var->isVarDeclaration(); 8375: if (v) 8376: { 8377: if (!v->isDataseg() && !v->isParameter()) 8378: error("escaping reference to local %s", v->toChars()); 8379: } 8380: } 8381: } 8382: 8383: void CastExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 8384: { 8385: buf->writestring("cast("); 8386: #if DMDV1 8387: to->toCBuffer(buf, NULL, hgs); 8388: #else 8389: if (to) 8390: to->toCBuffer(buf, NULL, hgs); 8391: else 8392: { 8393: MODtoBuffer(buf, mod); 8394: } 8395: #endif 8396: buf->writeByte(')'); 8397: expToCBuffer(buf, hgs, e1, precedence[op]); 8398: } 8399: 8400: 8401: /************************************************************/ 8402: 8403: SliceExp::SliceExp(Loc loc, Expression *e1, Expression *lwr, Expression *upr) 8404: : UnaExp(loc, TOKslice, sizeof(SliceExp), e1) 8405: { 8406: this->upr = upr; 8407: this->lwr = lwr; 8408: lengthVar = NULL; 8409: } 8410: 8411: Expression *SliceExp::syntaxCopy() 8412: { 8413: Expression *lwr = NULL; 8414: if (this->lwr) 8415: lwr = this->lwr->syntaxCopy(); 8416: 8417: Expression *upr = NULL; 8418: if (this->upr) 8419: upr = this->upr->syntaxCopy(); 8420: 8421: return new SliceExp(loc, e1->syntaxCopy(), lwr, upr); 8422: } 8423: 8424: Expression *SliceExp::semantic(Scope *sc) 8425: { Expression *e; 8426: AggregateDeclaration *ad; 8427: //FuncDeclaration *fd; 8428: ScopeDsymbol *sym; 8429: 8430: #if LOGSEMANTIC 8431: printf("SliceExp::semantic('%s')\n", toChars()); 8432: #endif 8433: if (type) 8434: return this; 8435: 8436: UnaExp::semantic(sc); 8437: e1 = resolveProperties(sc, e1); 8438: 8439: e = this; 8440: 8441: Type *t = e1->type->toBasetype(); 8442: if (t->ty == Tpointer) 8443: { 8444: if (!lwr || !upr) 8445: { error("need upper and lower bound to slice pointer"); 8446: return new ErrorExp(); 8447: } 8448: } 8449: else if (t->ty == Tarray) 8450: { 8451: } 8452: else if (t->ty == Tsarray) 8453: { 8454: } 8455: else if (t->ty == Tclass) 8456: { 8457: ad = ((TypeClass *)t)->sym; 8458: goto L1; 8459: } 8460: else if (t->ty == Tstruct) 8461: { 8462: ad = ((TypeStruct *)t)->sym; 8463: 8464: L1: 8465: if (search_function(ad, Id::slice)) 8466: { 8467: // Rewrite as e1.slice(lwr, upr) 8468: e = new DotIdExp(loc, e1, Id::slice); 8469: 8470: if (lwr) 8471: { 8472: assert(upr); 8473: e = new CallExp(loc, e, lwr, upr); 8474: } 8475: else 8476: { assert(!upr); 8477: e = new CallExp(loc, e); 8478: } 8479: e = e->semantic(sc); 8480: return e; 8481: } 8482: goto Lerror; 8483: } 8484: else if (t->ty == Ttuple) 8485: { 8486: if (!lwr && !upr) 8487: return e1; 8488: if (!lwr || !upr) 8489: { error("need upper and lower bound to slice tuple"); 8490: goto Lerror; 8491: } 8492: } 8493: else if (t == Type::terror) 8494: goto Lerr; 8495: else 8496: goto Lerror; 8497: 8498: { 8499: Scope *sc2 = sc; 8500: if (t->ty == Tsarray || t->ty == Tarray || t->ty == Ttuple) 8501: { 8502: sym = new ArrayScopeSymbol(sc, this); 8503: sym->loc = loc; 8504: sym->parent = sc->scopesym; 8505: sc2 = sc->push(sym); 8506: } 8507: 8508: if (lwr) 8509: { lwr = lwr->semantic(sc2); 8510: lwr = resolveProperties(sc2, lwr); 8511: lwr = lwr->implicitCastTo(sc2, Type::tsize_t); 8512: if (lwr->type == Type::terror) 8513: goto Lerr; 8514: } 8515: if (upr) 8516: { upr = upr->semantic(sc2); 8517: upr = resolveProperties(sc2, upr); 8518: upr = upr->implicitCastTo(sc2, Type::tsize_t); 8519: if (upr->type == Type::terror) 8520: goto Lerr; 8521: } 8522: 8523: if (sc2 != sc) 8524: sc2->pop(); 8525: } 8526: 8527: if (t->ty == Ttuple) 8528: { 8529: lwr = lwr->optimize(WANTvalue | WANTinterpret); 8530: upr = upr->optimize(WANTvalue | WANTinterpret); 8531: uinteger_t i1 = lwr->toUInteger(); 8532: uinteger_t i2 = upr->toUInteger(); 8533: 8534: size_t length; 8535: TupleExp *te; 8536: TypeTuple *tup; 8537: 8538: if (e1->op == TOKtuple) // slicing an expression tuple 8539: { te = (TupleExp *)e1; 8540: length = te->exps->dim; 8541: } 8542: else if (e1->op == TOKtype) // slicing a type tuple 8543: { tup = (TypeTuple *)t; 8544: length = Parameter::dim(tup->arguments); 8545: } 8546: else 8547: assert(0); 8548: 8549: if (i1 <= i2 && i2 <= length) 8550: { size_t j1 = (size_t) i1; 8551: size_t j2 = (size_t) i2; 8552: 8553: if (e1->op == TOKtuple) 8554: { Expressions *exps = new Expressions; 8555: exps->setDim(j2 - j1); 8556: for (size_t i = 0; i < j2 - j1; i++) 8557: { Expression *e = (*te->exps)[j1 + i];
warning C6246: Local declaration of 'e' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '8425' of 'c:\projects\extern\d\dmd\src\expression.c': Lines: 8425
8558: (*exps)[i] = e; 8559: } 8560: e = new TupleExp(loc, exps); 8561: } 8562: else 8563: { Parameters *args = new Parameters; 8564: args->reserve(j2 - j1); 8565: for (size_t i = j1; i < j2; i++) 8566: { Parameter *arg = Parameter::getNth(tup->arguments, i); 8567: args->push(arg); 8568: } 8569: e = new TypeExp(e1->loc, new TypeTuple(args)); 8570: } 8571: e = e->semantic(sc); 8572: } 8573: else 8574: { 8575: error("string slice [%ju .. %ju] is out of bounds", i1, i2); 8576: goto Lerr; 8577: } 8578: return e; 8579: } 8580: 8581: if (t->ty == Tarray) 8582: { 8583: type = e1->type; 8584: } 8585: else 8586: type = t->nextOf()->arrayOf(); 8587: return e; 8588: 8589: Lerror: 8590: if (e1->op == TOKerror) 8591: return e1; 8592: char *s; 8593: if (t->ty == Tvoid) 8594: s = e1->toChars(); 8595: else 8596: s = t->toChars(); 8597: error("%s cannot be sliced with []", s); 8598: Lerr: 8599: e = new ErrorExp(); 8600: return e; 8601: } 8602: 8603: void SliceExp::checkEscape() 8604: { 8605: e1->checkEscape(); 8606: } 8607: 8608: void SliceExp::checkEscapeRef() 8609: { 8610: e1->checkEscapeRef(); 8611: } 8612: 8613: #if DMDV2 8614: int SliceExp::isLvalue() 8615: { 8616: return 1; 8617: } 8618: #endif 8619: 8620: Expression *SliceExp::toLvalue(Scope *sc, Expression *e) 8621: { 8622: return this; 8623: } 8624: 8625: Expression *SliceExp::modifiableLvalue(Scope *sc, Expression *e) 8626: { 8627: error("slice expression %s is not a modifiable lvalue", toChars()); 8628: return this; 8629: } 8630: 8631: int SliceExp::isBool(int result) 8632: { 8633: return e1->isBool(result); 8634: } 8635: 8636: void SliceExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 8637: { 8638: expToCBuffer(buf, hgs, e1, precedence[op]); 8639: buf->writeByte('['); 8640: if (upr || lwr) 8641: { 8642: if (lwr) 8643: expToCBuffer(buf, hgs, lwr, PREC_assign); 8644: else 8645: buf->writeByte('0'); 8646: buf->writestring(".."); 8647: if (upr) 8648: expToCBuffer(buf, hgs, upr, PREC_assign); 8649: else 8650: buf->writestring("length"); // BUG: should be array.length 8651: } 8652: buf->writeByte(']'); 8653: } 8654: 8655: int SliceExp::canThrow(bool mustNotThrow) 8656: { 8657: return UnaExp::canThrow(mustNotThrow) 8658: || (lwr != NULL && lwr->canThrow(mustNotThrow)) 8659: || (upr != NULL && upr->canThrow(mustNotThrow)); 8660: } 8661: 8662: /********************** ArrayLength **************************************/ 8663: 8664: ArrayLengthExp::ArrayLengthExp(Loc loc, Expression *e1) 8665: : UnaExp(loc, TOKarraylength, sizeof(ArrayLengthExp), e1) 8666: { 8667: } 8668: 8669: Expression *ArrayLengthExp::semantic(Scope *sc) 8670: { 8671: #if LOGSEMANTIC 8672: printf("ArrayLengthExp::semantic('%s')\n", toChars()); 8673: #endif 8674: if (!type) 8675: { 8676: UnaExp::semantic(sc); 8677: e1 = resolveProperties(sc, e1); 8678: 8679: type = Type::tsize_t; 8680: } 8681: return this; 8682: } 8683: 8684: Expression *opAssignToOp(Loc loc, enum TOK op, Expression *e1, Expression *e2) 8685: { Expression *e; 8686: 8687: switch (op) 8688: { 8689: case TOKaddass: e = new AddExp(loc, e1, e2); break; 8690: case TOKminass: e = new MinExp(loc, e1, e2); break; 8691: case TOKmulass: e = new MulExp(loc, e1, e2); break; 8692: case TOKdivass: e = new DivExp(loc, e1, e2); break; 8693: case TOKmodass: e = new ModExp(loc, e1, e2); break; 8694: case TOKandass: e = new AndExp(loc, e1, e2); break; 8695: case TOKorass: e = new OrExp (loc, e1, e2); break; 8696: case TOKxorass: e = new XorExp(loc, e1, e2); break; 8697: case TOKshlass: e = new ShlExp(loc, e1, e2); break; 8698: case TOKshrass: e = new ShrExp(loc, e1, e2); break; 8699: case TOKushrass: e = new UshrExp(loc, e1, e2); break; 8700: default: assert(0); 8701: } 8702: return e; 8703: } 8704: 8705: /********************* 8706: * Rewrite: 8707: * array.length op= e2 8708: * as: 8709: * array.length = array.length op e2 8710: * or: 8711: * auto tmp = &array; 8712: * (*tmp).length = (*tmp).length op e2 8713: */ 8714: 8715: Expression *ArrayLengthExp::rewriteOpAssign(BinExp *exp) 8716: { Expression *e; 8717: 8718: assert(exp->e1->op == TOKarraylength); 8719: ArrayLengthExp *ale = (ArrayLengthExp *)exp->e1; 8720: if (ale->e1->op == TOKvar) 8721: { e = opAssignToOp(exp->loc, exp->op, ale, exp->e2); 8722: e = new AssignExp(exp->loc, ale->syntaxCopy(), e); 8723: } 8724: else 8725: { 8726: /* auto tmp = &array; 8727: * (*tmp).length = (*tmp).length op e2 8728: */ 8729: Identifier *id = Lexer::uniqueId("__arraylength"); 8730: ExpInitializer *ei = new ExpInitializer(ale->loc, new AddrExp(ale->loc, ale->e1)); 8731: VarDeclaration *tmp = new VarDeclaration(ale->loc, ale->e1->type->pointerTo(), id, ei); 8732: 8733: Expression *e1 = new ArrayLengthExp(ale->loc, new PtrExp(ale->loc, new VarExp(ale->loc, tmp))); 8734: Expression *elvalue = e1->syntaxCopy(); 8735: e = opAssignToOp(exp->loc, exp->op, e1, exp->e2); 8736: e = new AssignExp(exp->loc, elvalue, e); 8737: e = new CommaExp(exp->loc, new DeclarationExp(ale->loc, tmp), e); 8738: } 8739: return e; 8740: } 8741: 8742: void ArrayLengthExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 8743: { 8744: expToCBuffer(buf, hgs, e1, PREC_primary); 8745: buf->writestring(".length"); 8746: } 8747: 8748: /*********************** ArrayExp *************************************/ 8749: 8750: // e1 [ i1, i2, i3, ... ] 8751: 8752: ArrayExp::ArrayExp(Loc loc, Expression *e1, Expressions *args) 8753: : UnaExp(loc, TOKarray, sizeof(ArrayExp), e1) 8754: { 8755: arguments = args; 8756: } 8757: 8758: Expression *ArrayExp::syntaxCopy() 8759: { 8760: return new ArrayExp(loc, e1->syntaxCopy(), arraySyntaxCopy(arguments)); 8761: } 8762: 8763: Expression *ArrayExp::semantic(Scope *sc) 8764: { Expression *e; 8765: Type *t1; 8766: 8767: #if LOGSEMANTIC 8768: printf("ArrayExp::semantic('%s')\n", toChars()); 8769: #endif 8770: UnaExp::semantic(sc); 8771: e1 = resolveProperties(sc, e1); 8772: 8773: t1 = e1->type->toBasetype(); 8774: if (t1->ty != Tclass && t1->ty != Tstruct) 8775: { // Convert to IndexExp 8776: if (arguments->dim != 1) 8777: { error("only one index allowed to index %s", t1->toChars()); 8778: goto Lerr; 8779: } 8780: e = new IndexExp(loc, e1, arguments->tdata()[0]); 8781: return e->semantic(sc); 8782: } 8783: 8784: // Run semantic() on each argument 8785: for (size_t i = 0; i < arguments->dim; i++) 8786: { e = arguments->tdata()[i]; 8787: 8788: e = e->semantic(sc); 8789: if (!e->type) 8790: { error("%s has no value", e->toChars()); 8791: goto Lerr; 8792: } 8793: else if (e->type == Type::terror) 8794: goto Lerr; 8795: arguments->tdata()[i] = e; 8796: } 8797: 8798: expandTuples(arguments); 8799: assert(arguments && arguments->dim); 8800: 8801: e = op_overload(sc); 8802: if (!e) 8803: { error("no [] operator overload for type %s", e1->type->toChars()); 8804: goto Lerr; 8805: } 8806: return e; 8807: 8808: Lerr: 8809: return new ErrorExp(); 8810: } 8811: 8812: #if DMDV2 8813: int ArrayExp::isLvalue() 8814: { 8815: if (type && type->toBasetype()->ty == Tvoid) 8816: return 0; 8817: return 1; 8818: } 8819: #endif 8820: 8821: Expression *ArrayExp::toLvalue(Scope *sc, Expression *e) 8822: { 8823: if (type && type->toBasetype()->ty == Tvoid) 8824: error("voids have no value"); 8825: return this; 8826: } 8827: 8828: 8829: void ArrayExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 8830: { 8831: expToCBuffer(buf, hgs, e1, PREC_primary); 8832: buf->writeByte('['); 8833: argsToCBuffer(buf, arguments, hgs); 8834: buf->writeByte(']'); 8835: } 8836: 8837: /************************* DotExp ***********************************/ 8838: 8839: DotExp::DotExp(Loc loc, Expression *e1, Expression *e2) 8840: : BinExp(loc, TOKdotexp, sizeof(DotExp), e1, e2) 8841: { 8842: } 8843: 8844: Expression *DotExp::semantic(Scope *sc) 8845: { 8846: #if LOGSEMANTIC 8847: printf("DotExp::semantic('%s')\n", toChars()); 8848: if (type) printf("\ttype = %s\n", type->toChars()); 8849: #endif 8850: e1 = e1->semantic(sc); 8851: e2 = e2->semantic(sc); 8852: if (e2->op == TOKimport) 8853: { 8854: ScopeExp *se = (ScopeExp *)e2; 8855: TemplateDeclaration *td = se->sds->isTemplateDeclaration(); 8856: if (td) 8857: { Expression *e = new DotTemplateExp(loc, e1, td); 8858: e = e->semantic(sc); 8859: return e; 8860: } 8861: } 8862: if (!type) 8863: type = e2->type; 8864: return this; 8865: } 8866: 8867: void DotExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 8868: { 8869: expToCBuffer(buf, hgs, e1, PREC_primary); 8870: buf->writeByte('.'); 8871: expToCBuffer(buf, hgs, e2, PREC_primary); 8872: } 8873: 8874: /************************* CommaExp ***********************************/ 8875: 8876: CommaExp::CommaExp(Loc loc, Expression *e1, Expression *e2) 8877: : BinExp(loc, TOKcomma, sizeof(CommaExp), e1, e2) 8878: { 8879: } 8880: 8881: Expression *CommaExp::semantic(Scope *sc) 8882: { 8883: if (!type) 8884: { BinExp::semanticp(sc); 8885: e1 = e1->addDtorHook(sc); 8886: type = e2->type; 8887: } 8888: return this; 8889: } 8890: 8891: void CommaExp::checkEscape() 8892: { 8893: e2->checkEscape(); 8894: } 8895: 8896: void CommaExp::checkEscapeRef() 8897: { 8898: e2->checkEscapeRef(); 8899: } 8900: 8901: #if DMDV2 8902: int CommaExp::isLvalue() 8903: { 8904: return e2->isLvalue(); 8905: } 8906: #endif 8907: 8908: Expression *CommaExp::toLvalue(Scope *sc, Expression *e) 8909: { 8910: e2 = e2->toLvalue(sc, NULL); 8911: return this; 8912: } 8913: 8914: Expression *CommaExp::modifiableLvalue(Scope *sc, Expression *e) 8915: { 8916: e2 = e2->modifiableLvalue(sc, e); 8917: return this; 8918: } 8919: 8920: int CommaExp::isBool(int result) 8921: { 8922: return e2->isBool(result); 8923: } 8924: 8925: int CommaExp::checkSideEffect(int flag) 8926: { 8927: /* Check for compiler-generated code of the form auto __tmp, e, __tmp; 8928: * In such cases, only check e for side effect (it's OK for __tmp to have 8929: * no side effect). 8930: * See Bugzilla 4231 for discussion 8931: */ 8932: CommaExp* firstComma = this; 8933: while (firstComma->e1->op == TOKcomma) 8934: firstComma = (CommaExp *)firstComma->e1; 8935: if (firstComma->e1->op == TOKdeclaration && 8936: e2->op == TOKvar && 8937: ((DeclarationExp *)firstComma->e1)->declaration == ((VarExp*)e2)->var) 8938: { 8939: return e1->checkSideEffect(flag); 8940: } 8941: 8942: if (flag == 2) 8943: return e1->checkSideEffect(2) || e2->checkSideEffect(2); 8944: else 8945: { 8946: // Don't check e1 until we cast(void) the a,b code generation 8947: return e2->checkSideEffect(flag); 8948: } 8949: } 8950: 8951: Expression *CommaExp::addDtorHook(Scope *sc) 8952: { 8953: e2 = e2->addDtorHook(sc); 8954: return this; 8955: } 8956: 8957: /************************** IndexExp **********************************/ 8958: 8959: // e1 [ e2 ] 8960: 8961: IndexExp::IndexExp(Loc loc, Expression *e1, Expression *e2) 8962: : BinExp(loc, TOKindex, sizeof(IndexExp), e1, e2) 8963: { 8964: //printf("IndexExp::IndexExp('%s')\n", toChars()); 8965: lengthVar = NULL; 8966: modifiable = 0; // assume it is an rvalue 8967: } 8968: 8969: Expression *IndexExp::semantic(Scope *sc) 8970: { Expression *e; 8971: BinExp *b;
warning C4101: 'b' : unreferenced local variable
8972: UnaExp *u;
warning C4101: 'u' : unreferenced local variable
8973: Type *t1; 8974: ScopeDsymbol *sym; 8975: 8976: #if LOGSEMANTIC 8977: printf("IndexExp::semantic('%s')\n", toChars()); 8978: #endif 8979: if (type) 8980: return this; 8981: if (!e1->type) 8982: e1 = e1->semantic(sc); 8983: assert(e1->type); // semantic() should already be run on it 8984: if (e1->op == TOKerror) 8985: goto Lerr; 8986: e = this; 8987: 8988: // Note that unlike C we do not implement the int[ptr] 8989: 8990: t1 = e1->type->toBasetype(); 8991: 8992: if (t1->ty == Tsarray || t1->ty == Tarray || t1->ty == Ttuple) 8993: { // Create scope for 'length' variable 8994: sym = new ArrayScopeSymbol(sc, this); 8995: sym->loc = loc; 8996: sym->parent = sc->scopesym; 8997: sc = sc->push(sym); 8998: } 8999: 9000: e2 = e2->semantic(sc); 9001: if (!e2->type) 9002: { 9003: error("%s has no value", e2->toChars()); 9004: goto Lerr; 9005: } 9006: if (e2->type->ty == Ttuple && ((TupleExp *)e2)->exps->dim == 1) // bug 4444 fix 9007: e2 = (Expression *)((TupleExp *)e2)->exps->data[0]; 9008: e2 = resolveProperties(sc, e2); 9009: if (e2->type == Type::terror) 9010: goto Lerr; 9011: 9012: if (t1->ty == Tsarray || t1->ty == Tarray || t1->ty == Ttuple) 9013: sc = sc->pop(); 9014: 9015: switch (t1->ty) 9016: { 9017: case Tpointer: 9018: case Tarray: 9019: e2 = e2->implicitCastTo(sc, Type::tsize_t); 9020: e->type = ((TypeNext *)t1)->next; 9021: break; 9022: 9023: case Tsarray: 9024: { 9025: e2 = e2->implicitCastTo(sc, Type::tsize_t); 9026: 9027: TypeSArray *tsa = (TypeSArray *)t1; 9028: 9029: #if 0 // Don't do now, because it might be short-circuit evaluated 9030: // Do compile time array bounds checking if possible 9031: e2 = e2->optimize(WANTvalue); 9032: if (e2->op == TOKint64) 9033: { 9034: dinteger_t index = e2->toInteger(); 9035: dinteger_t length = tsa->dim->toInteger(); 9036: if (index < 0 || index >= length) 9037: error("array index [%lld] is outside array bounds [0 .. %lld]", 9038: index, length); 9039: } 9040: #endif 9041: e->type = t1->nextOf(); 9042: break; 9043: } 9044: 9045: case Taarray: 9046: { TypeAArray *taa = (TypeAArray *)t1; 9047: /* We can skip the implicit conversion if they differ only by 9048: * constness (Bugzilla 2684, see also bug 2954b) 9049: */ 9050: if (!arrayTypeCompatibleWithoutCasting(e2->loc, e2->type, taa->index)) 9051: { 9052: e2 = e2->implicitCastTo(sc, taa->index); // type checking 9053: } 9054: type = taa->next; 9055: break; 9056: } 9057: 9058: case Ttuple: 9059: { 9060: e2 = e2->implicitCastTo(sc, Type::tsize_t); 9061: e2 = e2->optimize(WANTvalue | WANTinterpret); 9062: uinteger_t index = e2->toUInteger(); 9063: size_t length; 9064: TupleExp *te; 9065: TypeTuple *tup; 9066: 9067: if (e1->op == TOKtuple) 9068: { te = (TupleExp *)e1; 9069: length = te->exps->dim; 9070: } 9071: else if (e1->op == TOKtype) 9072: { 9073: tup = (TypeTuple *)t1; 9074: length = Parameter::dim(tup->arguments); 9075: } 9076: else 9077: assert(0); 9078: 9079: if (index < length) 9080: { 9081: 9082: if (e1->op == TOKtuple) 9083: e = (*te->exps)[(size_t)index]; 9084: else 9085: e = new TypeExp(e1->loc, Parameter::getNth(tup->arguments, (size_t)index)->type); 9086: } 9087: else 9088: { 9089: error("array index [%ju] is outside array bounds [0 .. %"SIZE_T_FORMAT"u]", 9090: index, length); 9091: e = e1; 9092: } 9093: break; 9094: } 9095: 9096: default: 9097: if (e1->op == TOKerror) 9098: goto Lerr; 9099: error("%s must be an array or pointer type, not %s", 9100: e1->toChars(), e1->type->toChars()); 9101: case Terror: 9102: goto Lerr; 9103: } 9104: return e; 9105: 9106: Lerr: 9107: return new ErrorExp(); 9108: } 9109: 9110: #if DMDV2 9111: int IndexExp::isLvalue() 9112: { 9113: return 1; 9114: } 9115: #endif 9116: 9117: Expression *IndexExp::toLvalue(Scope *sc, Expression *e) 9118: { 9119: // if (type && type->toBasetype()->ty == Tvoid) 9120: // error("voids have no value"); 9121: return this; 9122: } 9123: 9124: Expression *IndexExp::modifiableLvalue(Scope *sc, Expression *e) 9125: { 9126: //printf("IndexExp::modifiableLvalue(%s)\n", toChars()); 9127: modifiable = 1; 9128: if (e1->op == TOKstring) 9129: error("string literals are immutable"); 9130: if (type && (!type->isMutable() || !type->isAssignable())) 9131: error("%s isn't mutable", e->toChars()); 9132: Type *t1 = e1->type->toBasetype(); 9133: if (t1->ty == Taarray) 9134: { TypeAArray *taa = (TypeAArray *)t1; 9135: Type *t2b = e2->type->toBasetype(); 9136: if (t2b->ty == Tarray && t2b->nextOf()->isMutable()) 9137: error("associative arrays can only be assigned values with immutable keys, not %s", e2->type->toChars()); 9138: e1 = e1->modifiableLvalue(sc, e1); 9139: } 9140: return toLvalue(sc, e); 9141: } 9142: 9143: void IndexExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 9144: { 9145: expToCBuffer(buf, hgs, e1, PREC_primary); 9146: buf->writeByte('['); 9147: expToCBuffer(buf, hgs, e2, PREC_assign); 9148: buf->writeByte(']'); 9149: } 9150: 9151: 9152: /************************* PostExp ***********************************/ 9153: 9154: PostExp::PostExp(enum TOK op, Loc loc, Expression *e) 9155: : BinExp(loc, op, sizeof(PostExp), e, 9156: new IntegerExp(loc, 1, Type::tint32)) 9157: { 9158: } 9159: 9160: Expression *PostExp::semantic(Scope *sc) 9161: { Expression *e = this; 9162: 9163: if (!type) 9164: { 9165: BinExp::semantic(sc); 9166: e1 = resolveProperties(sc, e1); 9167: 9168: e = op_overload(sc); 9169: if (e) 9170: return e; 9171: 9172: e1 = e1->modifiableLvalue(sc, e1); 9173: 9174: Type *t1 = e1->type->toBasetype(); 9175: if (t1->ty == Tclass || t1->ty == Tstruct) 9176: { /* Check for operator overloading, 9177: * but rewrite in terms of ++e instead of e++ 9178: */ 9179: 9180: /* If e1 is not trivial, take a reference to it 9181: */ 9182: Expression *de = NULL; 9183: if (e1->op != TOKvar) 9184: { 9185: // ref v = e1; 9186: Identifier *id = Lexer::uniqueId("__postref"); 9187: ExpInitializer *ei = new ExpInitializer(loc, e1); 9188: VarDeclaration *v = new VarDeclaration(loc, e1->type, id, ei); 9189: v->storage_class |= STCref | STCforeach; 9190: de = new DeclarationExp(loc, v);
warning C6211: Leaking memory 'de' due to an exception. Consider using a local catch block to clean up memory: Lines: 9161, 9163, 9165, 9166, 9168, 9169, 9172, 9174, 9175, 9182, 9183, 9186, 9187, 9188, 9189, 9190, 9191
9191: e1 = new VarExp(e1->loc, v); 9192: } 9193: 9194: /* Rewrite as: 9195: * auto tmp = e1; ++e1; tmp 9196: */ 9197: Identifier *id = Lexer::uniqueId("__pitmp"); 9198: ExpInitializer *ei = new ExpInitializer(loc, e1); 9199: VarDeclaration *tmp = new VarDeclaration(loc, e1->type, id, ei); 9200: Expression *ea = new DeclarationExp(loc, tmp);
warning C6211: Leaking memory 'ea' due to an exception. Consider using a local catch block to clean up memory: Lines: 9161, 9163, 9165, 9166, 9168, 9169, 9172, 9174, 9175, 9182, 9183, 9197, 9198, 9199, 9200, 9202, 9203
9201: 9202: Expression *eb = e1->syntaxCopy(); 9203: eb = new PreExp(op == TOKplusplus ? TOKpreplusplus : TOKpreminusminus, loc, eb);
warning C6211: Leaking memory 'eb' due to an exception. Consider using a local catch block to clean up memory: Lines: 9161, 9163, 9165, 9166, 9168, 9169, 9172, 9174, 9175, 9182, 9183, 9197, 9198, 9199, 9200, 9202, 9203, 9205
9204: 9205: Expression *ec = new VarExp(loc, tmp);
warning C6211: Leaking memory 'ec' due to an exception. Consider using a local catch block to clean up memory: Lines: 9161, 9163, 9165, 9166, 9168, 9169, 9172, 9174, 9175, 9182, 9183, 9197, 9198, 9199, 9200, 9202, 9203, 9205, 9208, 9210
9206: 9207: // Combine de,ea,eb,ec 9208: if (de) 9209: ea = new CommaExp(loc, de, ea); 9210: e = new CommaExp(loc, ea, eb); 9211: e = new CommaExp(loc, e, ec); 9212: e = e->semantic(sc); 9213: return e; 9214: } 9215: 9216: e = this; 9217: e1->checkScalar(); 9218: e1->checkNoBool(); 9219: if (e1->type->ty == Tpointer) 9220: e = scaleFactor(sc); 9221: else 9222: e2 = e2->castTo(sc, e1->type); 9223: e->type = e1->type; 9224: } 9225: return e; 9226: } 9227: 9228: void PostExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 9229: { 9230: expToCBuffer(buf, hgs, e1, precedence[op]); 9231: buf->writestring(Token::toChars(op)); 9232: } 9233: 9234: /************************* PreExp ***********************************/ 9235: 9236: PreExp::PreExp(enum TOK op, Loc loc, Expression *e) 9237: : UnaExp(loc, op, sizeof(PreExp), e) 9238: { 9239: } 9240: 9241: Expression *PreExp::semantic(Scope *sc) 9242: { 9243: Expression *e; 9244: 9245: e = op_overload(sc); 9246: if (e) 9247: return e; 9248: 9249: // Rewrite as e1+=1 or e1-=1 9250: if (op == TOKpreplusplus) 9251: e = new AddAssignExp(loc, e1, new IntegerExp(loc, 1, Type::tint32)); 9252: else 9253: e = new MinAssignExp(loc, e1, new IntegerExp(loc, 1, Type::tint32)); 9254: return e->semantic(sc); 9255: } 9256: 9257: void PreExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 9258: { 9259: buf->writestring(Token::toChars(op)); 9260: expToCBuffer(buf, hgs, e1, precedence[op]); 9261: } 9262: 9263: /************************************************************/ 9264: 9265: /* op can be TOKassign, TOKconstruct, or TOKblit */ 9266: 9267: AssignExp::AssignExp(Loc loc, Expression *e1, Expression *e2) 9268: : BinExp(loc, TOKassign, sizeof(AssignExp), e1, e2) 9269: { 9270: ismemset = 0; 9271: } 9272: 9273: Expression *AssignExp::semantic(Scope *sc) 9274: { 9275: Expression *e1old = e1; 9276: 9277: #if LOGSEMANTIC 9278: printf("AssignExp::semantic('%s')\n", toChars()); 9279: #endif 9280: //printf("e1->op = %d, '%s'\n", e1->op, Token::toChars(e1->op)); 9281: //printf("e2->op = %d, '%s'\n", e2->op, Token::toChars(e2->op)); 9282: 9283: if (type) 9284: return this; 9285: 9286: if (e2->op == TOKcomma) 9287: { /* Rewrite to get rid of the comma from rvalue 9288: */ 9289: AssignExp *ea = new AssignExp(loc, e1, ((CommaExp *)e2)->e2); 9290: ea->op = op; 9291: Expression *e = new CommaExp(loc, ((CommaExp *)e2)->e1, ea); 9292: return e->semantic(sc); 9293: } 9294: 9295: /* Look for operator overloading of a[i]=value. 9296: * Do it before semantic() otherwise the a[i] will have been 9297: * converted to a.opIndex() already. 9298: */ 9299: if (e1->op == TOKarray) 9300: { 9301: ArrayExp *ae = (ArrayExp *)e1; 9302: AggregateDeclaration *ad; 9303: Identifier *id = Id::index; 9304: 9305: ae->e1 = ae->e1->semantic(sc); 9306: Type *t1 = ae->e1->type->toBasetype(); 9307: if (t1->ty == Tstruct) 9308: { 9309: ad = ((TypeStruct *)t1)->sym; 9310: goto L1; 9311: } 9312: else if (t1->ty == Tclass) 9313: { 9314: ad = ((TypeClass *)t1)->sym; 9315: L1: 9316: // Rewrite (a[i] = value) to (a.opIndexAssign(value, i)) 9317: if (search_function(ad, Id::indexass)) 9318: { Expression *e = new DotIdExp(loc, ae->e1, Id::indexass); 9319: Expressions *a = (Expressions *)ae->arguments->copy(); 9320: 9321: a->insert(0, e2); 9322: e = new CallExp(loc, e, a); 9323: e = e->semantic(sc); 9324: return e; 9325: } 9326: #if 0 // Turned off to allow rewriting (a[i]=value) to (a.opIndex(i)=value) 9327: else 9328: { 9329: // Rewrite (a[i] = value) to (a.opIndex(i, value)) 9330: if (search_function(ad, id)) 9331: { Expression *e = new DotIdExp(loc, ae->e1, id); 9332: 9333: if (1 || !global.params.useDeprecated) 9334: { error("operator [] assignment overload with opIndex(i, value) illegal, use opIndexAssign(value, i)"); 9335: return new ErrorExp(); 9336: } 9337: 9338: e = new CallExp(loc, e, ae->arguments->tdata()[0], e2); 9339: e = e->semantic(sc); 9340: return e; 9341: } 9342: } 9343: #endif 9344: } 9345: } 9346: /* Look for operator overloading of a[i..j]=value. 9347: * Do it before semantic() otherwise the a[i..j] will have been 9348: * converted to a.opSlice() already. 9349: */ 9350: if (e1->op == TOKslice) 9351: { Type *t1; 9352: SliceExp *ae = (SliceExp *)e1; 9353: AggregateDeclaration *ad; 9354: Identifier *id = Id::index; 9355: 9356: ae->e1 = ae->e1->semantic(sc); 9357: ae->e1 = resolveProperties(sc, ae->e1); 9358: t1 = ae->e1->type->toBasetype(); 9359: if (t1->ty == Tstruct) 9360: { 9361: ad = ((TypeStruct *)t1)->sym; 9362: goto L2; 9363: } 9364: else if (t1->ty == Tclass) 9365: { 9366: ad = ((TypeClass *)t1)->sym; 9367: L2: 9368: // Rewrite (a[i..j] = value) to (a.opSliceAssign(value, i, j)) 9369: if (search_function(ad, Id::sliceass)) 9370: { Expression *e = new DotIdExp(loc, ae->e1, Id::sliceass); 9371: Expressions *a = new Expressions(); 9372: 9373: a->push(e2); 9374: if (ae->lwr) 9375: { a->push(ae->lwr); 9376: assert(ae->upr); 9377: a->push(ae->upr); 9378: } 9379: else 9380: assert(!ae->upr); 9381: e = new CallExp(loc, e, a); 9382: e = e->semantic(sc); 9383: return e; 9384: } 9385: } 9386: } 9387: 9388: Expression *e = BinExp::semantic(sc); 9389: if (e->op == TOKerror) 9390: return e; 9391: 9392: if (e1->op == TOKdottd) 9393: { // Rewrite a.b=e2, when b is a template, as a.b(e2) 9394: Expression *e = new CallExp(loc, e1, e2);
warning C6246: Local declaration of 'e' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '9388' of 'c:\projects\extern\d\dmd\src\expression.c': Lines: 9388
9395: e = e->semantic(sc); 9396: return e; 9397: } 9398: 9399: e2 = resolveProperties(sc, e2); 9400: assert(e1->type); 9401: 9402: /* Rewrite tuple assignment as a tuple of assignments. 9403: */ 9404: if (e1->op == TOKtuple && e2->op == TOKtuple) 9405: { TupleExp *tup1 = (TupleExp *)e1; 9406: TupleExp *tup2 = (TupleExp *)e2; 9407: size_t dim = tup1->exps->dim; 9408: if (dim != tup2->exps->dim) 9409: { 9410: error("mismatched tuple lengths, %d and %d", (int)dim, (int)tup2->exps->dim); 9411: return new ErrorExp(); 9412: } 9413: else 9414: { Expressions *exps = new Expressions; 9415: exps->setDim(dim); 9416: 9417: for (int i = 0; i < dim; i++)
warning C4018: '<' : signed/unsigned mismatch
9418: { Expression *ex1 = (*tup1->exps)[i]; 9419: Expression *ex2 = (*tup2->exps)[i]; 9420: (*exps)[i] = new AssignExp(loc, ex1, ex2); 9421: } 9422: Expression *e = new TupleExp(loc, exps);
warning C6246: Local declaration of 'e' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '9388' of 'c:\projects\extern\d\dmd\src\expression.c': Lines: 9388
9423: e = e->semantic(sc); 9424: return e; 9425: } 9426: } 9427: 9428: // Determine if this is an initialization of a reference 9429: int refinit = 0; 9430: if (op == TOKconstruct && e1->op == TOKvar) 9431: { VarExp *ve = (VarExp *)e1; 9432: VarDeclaration *v = ve->var->isVarDeclaration(); 9433: if (v->storage_class & (STCout | STCref)) 9434: refinit = 1; 9435: } 9436: 9437: Type *t1 = e1->type->toBasetype(); 9438: 9439: if (t1->ty == Tfunction) 9440: { /* We have f=value. 9441: * Could mean: 9442: * f() = value 9443: * or: 9444: * f(value) 9445: */ 9446: TypeFunction *tf = (TypeFunction *)t1; 9447: if (tf->isref) 9448: { 9449: // Rewrite e1 = e2 to e1() = e2 9450: e1 = resolveProperties(sc, e1); 9451: } 9452: else 9453: { 9454: // Rewrite f=value to f(value) 9455: Expression *e = new CallExp(loc, e1, e2);
warning C6246: Local declaration of 'e' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '9388' of 'c:\projects\extern\d\dmd\src\expression.c': Lines: 9388
9456: e = e->semantic(sc); 9457: return e; 9458: } 9459: } 9460: 9461: /* If it is an assignment from a 'foreign' type, 9462: * check for operator overloading. 9463: */ 9464: if (t1->ty == Tstruct) 9465: { 9466: StructDeclaration *sd = ((TypeStruct *)t1)->sym; 9467: if (op == TOKassign) 9468: { 9469: Expression *e = op_overload(sc);
warning C6246: Local declaration of 'e' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '9388' of 'c:\projects\extern\d\dmd\src\expression.c': Lines: 9388
9470: if (e && e1->op == TOKindex && 9471: ((IndexExp *)e1)->e1->type->toBasetype()->ty == Taarray) 9472: { 9473: // Deal with AAs (Bugzilla 2451) 9474: // Rewrite as: 9475: // e1 = (typeof(aa.value) tmp = void, tmp = e2, tmp); 9476: Type * aaValueType = ((TypeAArray *)((IndexExp*)e1)->e1->type->toBasetype())->next; 9477: Identifier *id = Lexer::uniqueId("__aatmp"); 9478: VarDeclaration *v = new VarDeclaration(loc, aaValueType, 9479: id, new VoidInitializer(0)); 9480: v->storage_class |= STCctfe; 9481: v->semantic(sc); 9482: v->parent = sc->parent; 9483: 9484: Expression *de = new DeclarationExp(loc, v); 9485: VarExp *ve = new VarExp(loc, v); 9486: 9487: AssignExp *ae = new AssignExp(loc, ve, e2); 9488: e = ae->op_overload(sc); 9489: e2 = new CommaExp(loc, new CommaExp(loc, de, e), ve); 9490: e2 = e2->semantic(sc); 9491: } 9492: else if (e) 9493: return e; 9494: } 9495: else if (op == TOKconstruct && !refinit) 9496: { Type *t2 = e2->type->toBasetype(); 9497: if (t2->ty == Tstruct && 9498: sd == ((TypeStruct *)t2)->sym && 9499: sd->cpctor) 9500: { /* We have a copy constructor for this 9501: */ 9502: // Scan past commma's 9503: Expression *ec = NULL; 9504: while (e2->op == TOKcomma) 9505: { CommaExp *ecomma = (CommaExp *)e2; 9506: e2 = ecomma->e2; 9507: if (ec) 9508: ec = new CommaExp(ecomma->loc, ec, ecomma->e1); 9509: else 9510: ec = ecomma->e1; 9511: } 9512: if (e2->op == TOKquestion) 9513: { /* Write as: 9514: * a ? e1 = b : e1 = c; 9515: */ 9516: CondExp *econd = (CondExp *)e2; 9517: AssignExp *ea1 = new AssignExp(econd->e1->loc, e1, econd->e1); 9518: ea1->op = op; 9519: AssignExp *ea2 = new AssignExp(econd->e1->loc, e1, econd->e2); 9520: ea2->op = op; 9521: Expression *e = new CondExp(loc, econd->econd, ea1, ea2);
warning C6246: Local declaration of 'e' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '9388' of 'c:\projects\extern\d\dmd\src\expression.c': Lines: 9388
9522: if (ec) 9523: e = new CommaExp(loc, ec, e); 9524: return e->semantic(sc); 9525: } 9526: else if (e2->op == TOKvar || 9527: e2->op == TOKdotvar || 9528: e2->op == TOKstar || 9529: e2->op == TOKthis || 9530: e2->op == TOKindex) 9531: { /* Write as: 9532: * e1.cpctor(e2); 9533: */ 9534: Expression *e = new DotVarExp(loc, e1, sd->cpctor, 0);
warning C6246: Local declaration of 'e' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '9388' of 'c:\projects\extern\d\dmd\src\expression.c': Lines: 9388
9535: e = new CallExp(loc, e, e2); 9536: if (ec) 9537: e = new CommaExp(loc, ec, e); 9538: return e->semantic(sc); 9539: } 9540: else if (e2->op == TOKcall) 9541: { 9542: /* The struct value returned from the function is transferred 9543: * so should not call the destructor on it. 9544: */ 9545: valueNoDtor(e2); 9546: } 9547: } 9548: } 9549: } 9550: else if (t1->ty == Tclass) 9551: { // Disallow assignment operator overloads for same type 9552: if (!e2->type->implicitConvTo(e1->type)) 9553: { 9554: Expression *e = op_overload(sc);
warning C6246: Local declaration of 'e' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '9388' of 'c:\projects\extern\d\dmd\src\expression.c': Lines: 9388
9555: if (e) 9556: return e; 9557: } 9558: } 9559: 9560: if (t1->ty == Tsarray && !refinit) 9561: { 9562: if (e1->op == TOKindex && 9563: ((IndexExp *)e1)->e1->type->toBasetype()->ty == Taarray) 9564: { 9565: // Assignment to an AA of fixed-length arrays. 9566: // Convert T[n][U] = T[] into T[n][U] = T[n] 9567: e2 = e2->implicitCastTo(sc, e1->type); 9568: if (e2->type == Type::terror) 9569: return e2; 9570: } 9571: else 9572: { 9573: Type *t2 = e2->type->toBasetype(); 9574: // Convert e2 to e2[], unless e2-> e1[0] 9575: if (t2->ty == Tsarray && !t2->implicitConvTo(t1->nextOf())) 9576: { 9577: e2 = new SliceExp(e2->loc, e2, NULL, NULL); 9578: e2 = e2->semantic(sc); 9579: } 9580: 9581: // Convert e1 to e1[] 9582: Expression *e = new SliceExp(e1->loc, e1, NULL, NULL);
warning C6246: Local declaration of 'e' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '9388' of 'c:\projects\extern\d\dmd\src\expression.c': Lines: 9388
9583: e1 = e->semantic(sc); 9584: t1 = e1->type->toBasetype(); 9585: } 9586: } 9587: 9588: e2->rvalue(); 9589: 9590: if (e1->op == TOKarraylength) 9591: { 9592: // e1 is not an lvalue, but we let code generator handle it 9593: ArrayLengthExp *ale = (ArrayLengthExp *)e1; 9594: 9595: ale->e1 = ale->e1->modifiableLvalue(sc, e1); 9596: } 9597: else if (e1->op == TOKslice) 9598: { 9599: Type *tn = e1->type->nextOf(); 9600: if (op == TOKassign && tn && (!tn->isMutable() || !tn->isAssignable())) 9601: { error("slice %s is not mutable", e1->toChars()); 9602: return new ErrorExp(); 9603: } 9604: } 9605: else 9606: { // Try to do a decent error message with the expression 9607: // before it got constant folded 9608: if (e1->op != TOKvar) 9609: e1 = e1->optimize(WANTvalue); 9610: 9611: if (op != TOKconstruct) 9612: e1 = e1->modifiableLvalue(sc, e1old); 9613: } 9614: 9615: Type *t2 = e2->type; 9616: if (e1->op == TOKslice && 9617: t1->nextOf() && 9618: e2->implicitConvTo(t1->nextOf()) 9619: ) 9620: { // memset 9621: ismemset = 1; // make it easy for back end to tell what this is 9622: e2 = e2->implicitCastTo(sc, t1->nextOf()); 9623: } 9624: else if (t1->ty == Tsarray) 9625: { 9626: /* Should have already converted e1 => e1[] 9627: * unless it is an AA 9628: */ 9629: if (!(e1->op == TOKindex && t2->ty == Tsarray && 9630: ((IndexExp *)e1)->e1->type->toBasetype()->ty == Taarray)) 9631: { 9632: assert(op == TOKconstruct); 9633: } 9634: //error("cannot assign to static array %s", e1->toChars()); 9635: } 9636: else if (e1->op == TOKslice && t2->toBasetype()->ty == Tarray && 9637: t2->toBasetype()->nextOf()->implicitConvTo(t1->nextOf())) 9638: { 9639: e2 = e2->implicitCastTo(sc, e1->type->constOf()); 9640: } 9641: else 9642: { 9643: e2 = e2->implicitCastTo(sc, e1->type); 9644: } 9645: 9646: /* Look for array operations 9647: */ 9648: if (e1->op == TOKslice && !ismemset && 9649: (e2->op == TOKadd || e2->op == TOKmin || 9650: e2->op == TOKmul || e2->op == TOKdiv || 9651: e2->op == TOKmod || e2->op == TOKxor || 9652: e2->op == TOKand || e2->op == TOKor || 9653: e2->op == TOKtilde || e2->op == TOKneg)) 9654: { 9655: type = e1->type; 9656: return arrayOp(sc); 9657: } 9658: 9659: type = e1->type; 9660: assert(type); 9661: return this; 9662: } 9663: 9664: Expression *AssignExp::checkToBoolean(Scope *sc) 9665: { 9666: // Things like: 9667: // if (a = b) ... 9668: // are usually mistakes. 9669: 9670: error("'=' does not give a boolean result"); 9671: return new ErrorExp(); 9672: } 9673: 9674: /************************************************************/ 9675: 9676: ConstructExp::ConstructExp(Loc loc, Expression *e1, Expression *e2) 9677: : AssignExp(loc, e1, e2) 9678: { 9679: op = TOKconstruct; 9680: } 9681: 9682: /************************************************************/ 9683: 9684: AddAssignExp::AddAssignExp(Loc loc, Expression *e1, Expression *e2) 9685: : BinAssignExp(loc, TOKaddass, sizeof(AddAssignExp), e1, e2) 9686: { 9687: } 9688: 9689: Expression *AddAssignExp::semantic(Scope *sc) 9690: { Expression *e; 9691: 9692: if (type) 9693: return this; 9694: 9695: e = op_overload(sc); 9696: if (e) 9697: return e; 9698: 9699: Type *tb1 = e1->type->toBasetype(); 9700: Type *tb2 = e2->type->toBasetype(); 9701: 9702: if (e1->op == TOKarraylength) 9703: { 9704: e = ArrayLengthExp::rewriteOpAssign(this); 9705: e = e->semantic(sc); 9706: return e; 9707: } 9708: 9709: if (e1->op == TOKslice) 9710: { 9711: e = typeCombine(sc); 9712: if (e->op == TOKerror) 9713: return e; 9714: type = e1->type; 9715: return arrayOp(sc); 9716: } 9717: else 9718: { 9719: e1 = e1->modifiableLvalue(sc, e1); 9720: } 9721: 9722: if ((tb1->ty == Tarray || tb1->ty == Tsarray) && 9723: (tb2->ty == Tarray || tb2->ty == Tsarray) && 9724: tb1->nextOf()->equals(tb2->nextOf()) 9725: ) 9726: { 9727: type = e1->type; 9728: typeCombine(sc); 9729: e = this; 9730: } 9731: else 9732: { 9733: e1->checkScalar(); 9734: e1->checkNoBool(); 9735: if (tb1->ty == Tpointer && tb2->isintegral()) 9736: e = scaleFactor(sc); 9737: else if (tb1->ty == Tbool) 9738: { 9739: #if 0 9740: // Need to rethink this 9741: if (e1->op != TOKvar) 9742: { // Rewrite e1+=e2 to (v=&e1),*v=*v+e2 9743: VarDeclaration *v; 9744: Expression *ea; 9745: Expression *ex; 9746: 9747: Identifier *id = Lexer::uniqueId("__name"); 9748: 9749: v = new VarDeclaration(loc, tb1->pointerTo(), id, NULL); 9750: v->semantic(sc); 9751: if (!sc->insert(v)) 9752: assert(0); 9753: v->parent = sc->func; 9754: 9755: ea = new AddrExp(loc, e1); 9756: ea = new AssignExp(loc, new VarExp(loc, v), ea); 9757: 9758: ex = new VarExp(loc, v); 9759: ex = new PtrExp(loc, ex); 9760: e = new AddExp(loc, ex, e2); 9761: e = new CastExp(loc, e, e1->type); 9762: e = new AssignExp(loc, ex->syntaxCopy(), e); 9763: 9764: e = new CommaExp(loc, ea, e); 9765: } 9766: else 9767: #endif 9768: { // Rewrite e1+=e2 to e1=e1+e2 9769: // BUG: doesn't account for side effects in e1 9770: // BUG: other assignment operators for bits aren't handled at all 9771: e = new AddExp(loc, e1, e2); 9772: e = new CastExp(loc, e, e1->type); 9773: e = new AssignExp(loc, e1->syntaxCopy(), e); 9774: } 9775: e = e->semantic(sc); 9776: } 9777: else 9778: { 9779: type = e1->type; 9780: typeCombine(sc); 9781: e1->checkArithmetic(); 9782: e2->checkArithmetic(); 9783: checkComplexAddAssign(); 9784: if (type->isreal() || type->isimaginary()) 9785: { 9786: assert(global.errors || e2->type->isfloating()); 9787: e2 = e2->castTo(sc, e1->type); 9788: } 9789: e = this; 9790: } 9791: } 9792: return e; 9793: } 9794: 9795: /************************************************************/ 9796: 9797: MinAssignExp::MinAssignExp(Loc loc, Expression *e1, Expression *e2) 9798: : BinAssignExp(loc, TOKminass, sizeof(MinAssignExp), e1, e2) 9799: { 9800: } 9801: 9802: Expression *MinAssignExp::semantic(Scope *sc) 9803: { Expression *e; 9804: 9805: if (type) 9806: return this; 9807: 9808: e = op_overload(sc); 9809: if (e) 9810: return e; 9811: 9812: if (e1->op == TOKarraylength) 9813: { 9814: e = ArrayLengthExp::rewriteOpAssign(this); 9815: e = e->semantic(sc); 9816: return e; 9817: } 9818: 9819: if (e1->op == TOKslice) 9820: { // T[] -= ... 9821: e = typeCombine(sc); 9822: if (e->op == TOKerror) 9823: return e; 9824: type = e1->type; 9825: return arrayOp(sc); 9826: } 9827: 9828: e1 = e1->modifiableLvalue(sc, e1); 9829: e1->checkScalar(); 9830: e1->checkNoBool(); 9831: if (e1->type->ty == Tpointer && e2->type->isintegral()) 9832: e = scaleFactor(sc); 9833: else 9834: { 9835: e1 = e1->checkArithmetic(); 9836: e2 = e2->checkArithmetic(); 9837: checkComplexAddAssign(); 9838: type = e1->type; 9839: typeCombine(sc); 9840: if (type->isreal() || type->isimaginary()) 9841: { 9842: assert(e2->type->isfloating()); 9843: e2 = e2->castTo(sc, e1->type); 9844: } 9845: e = this; 9846: } 9847: return e; 9848: } 9849: 9850: /************************************************************/ 9851: 9852: CatAssignExp::CatAssignExp(Loc loc, Expression *e1, Expression *e2) 9853: : BinAssignExp(loc, TOKcatass, sizeof(CatAssignExp), e1, e2) 9854: { 9855: } 9856: 9857: Expression *CatAssignExp::semantic(Scope *sc) 9858: { Expression *e; 9859: 9860: //printf("CatAssignExp::semantic() %s\n", toChars()); 9861: e = op_overload(sc); 9862: if (e) 9863: return e; 9864: 9865: if (e1->op == TOKslice) 9866: { SliceExp *se = (SliceExp *)e1; 9867: 9868: if (se->e1->type->toBasetype()->ty == Tsarray) 9869: { error("cannot append to static array %s", se->e1->type->toChars()); 9870: return new ErrorExp(); 9871: } 9872: } 9873: 9874: e1 = e1->modifiableLvalue(sc, e1); 9875: 9876: Type *tb1 = e1->type->toBasetype(); 9877: Type *tb2 = e2->type->toBasetype(); 9878: 9879: e2->rvalue(); 9880: 9881: Type *tb1next = tb1->nextOf(); 9882: 9883: if ((tb1->ty == Tarray) && 9884: (tb2->ty == Tarray || tb2->ty == Tsarray) && 9885: (e2->implicitConvTo(e1->type) 9886: #if DMDV2 9887: || tb2->nextOf()->implicitConvTo(tb1next) 9888: #endif 9889: ) 9890: ) 9891: { // Append array 9892: e2 = e2->castTo(sc, e1->type); 9893: type = e1->type; 9894: e = this; 9895: } 9896: else if ((tb1->ty == Tarray) && 9897: e2->implicitConvTo(tb1next) 9898: ) 9899: { // Append element 9900: e2 = e2->castTo(sc, tb1next); 9901: type = e1->type; 9902: e = this; 9903: } 9904: else if (tb1->ty == Tarray && 9905: (tb1next->ty == Tchar || tb1next->ty == Twchar) && 9906: e2->type->ty != tb1next->ty && 9907: e2->implicitConvTo(Type::tdchar) 9908: ) 9909: { // Append dchar to char[] or wchar[] 9910: e2 = e2->castTo(sc, Type::tdchar); 9911: type = e1->type; 9912: e = this; 9913: 9914: /* Do not allow appending wchar to char[] because if wchar happens 9915: * to be a surrogate pair, nothing good can result. 9916: */ 9917: } 9918: else 9919: { 9920: if (tb1 != Type::terror && tb2 != Type::terror) 9921: error("cannot append type %s to type %s", tb2->toChars(), tb1->toChars()); 9922: e = new ErrorExp(); 9923: } 9924: return e; 9925: } 9926: 9927: /************************************************************/ 9928: 9929: MulAssignExp::MulAssignExp(Loc loc, Expression *e1, Expression *e2) 9930: : BinAssignExp(loc, TOKmulass, sizeof(MulAssignExp), e1, e2) 9931: { 9932: } 9933: 9934: Expression *MulAssignExp::semantic(Scope *sc) 9935: { Expression *e; 9936: 9937: e = op_overload(sc); 9938: if (e) 9939: return e; 9940: 9941: #if DMDV2 9942: if (e1->op == TOKarraylength) 9943: { 9944: e = ArrayLengthExp::rewriteOpAssign(this); 9945: e = e->semantic(sc); 9946: return e; 9947: } 9948: #endif 9949: 9950: if (e1->op == TOKslice) 9951: { // T[] *= ... 9952: e = typeCombine(sc); 9953: if (e->op == TOKerror) 9954: return e; 9955: return arrayOp(sc); 9956: } 9957: 9958: e1 = e1->modifiableLvalue(sc, e1); 9959: e1->checkScalar(); 9960: e1->checkNoBool(); 9961: type = e1->type; 9962: typeCombine(sc); 9963: e1->checkArithmetic(); 9964: e2->checkArithmetic(); 9965: checkComplexMulAssign(); 9966: if (e2->type->isfloating()) 9967: { Type *t1; 9968: Type *t2; 9969: 9970: t1 = e1->type; 9971: t2 = e2->type; 9972: if (t1->isreal()) 9973: { 9974: if (t2->isimaginary() || t2->iscomplex()) 9975: { 9976: e2 = e2->castTo(sc, t1); 9977: } 9978: } 9979: else if (t1->isimaginary()) 9980: { 9981: if (t2->isimaginary() || t2->iscomplex()) 9982: { 9983: switch (t1->ty) 9984: { 9985: case Timaginary32: t2 = Type::tfloat32; break; 9986: case Timaginary64: t2 = Type::tfloat64; break; 9987: case Timaginary80: t2 = Type::tfloat80; break; 9988: default: 9989: assert(0); 9990: } 9991: e2 = e2->castTo(sc, t2); 9992: } 9993: } 9994: } 9995: return this; 9996: } 9997: 9998: /************************************************************/ 9999: 10000: DivAssignExp::DivAssignExp(Loc loc, Expression *e1, Expression *e2) 10001: : BinAssignExp(loc, TOKdivass, sizeof(DivAssignExp), e1, e2) 10002: { 10003: } 10004: 10005: Expression *DivAssignExp::semantic(Scope *sc) 10006: { Expression *e; 10007: 10008: e = op_overload(sc); 10009: if (e) 10010: return e; 10011: 10012: #if DMDV2 10013: if (e1->op == TOKarraylength) 10014: { 10015: e = ArrayLengthExp::rewriteOpAssign(this); 10016: e = e->semantic(sc); 10017: return e; 10018: } 10019: #endif 10020: 10021: if (e1->op == TOKslice) 10022: { // T[] /= ... 10023: e = typeCombine(sc); 10024: if (e->op == TOKerror) 10025: return e; 10026: type = e1->type; 10027: return arrayOp(sc); 10028: } 10029: 10030: e1 = e1->modifiableLvalue(sc, e1); 10031: e1->checkScalar(); 10032: e1->checkNoBool(); 10033: type = e1->type; 10034: typeCombine(sc); 10035: e1->checkArithmetic(); 10036: e2->checkArithmetic(); 10037: checkComplexMulAssign(); 10038: if (e2->type->isimaginary()) 10039: { Type *t1; 10040: Type *t2; 10041: 10042: t1 = e1->type; 10043: if (t1->isreal()) 10044: { // x/iv = i(-x/v) 10045: // Therefore, the result is 0 10046: e2 = new CommaExp(loc, e2, new RealExp(loc, 0, t1)); 10047: e2->type = t1; 10048: e = new AssignExp(loc, e1, e2); 10049: e->type = t1; 10050: return e; 10051: } 10052: else if (t1->isimaginary()) 10053: { Expression *e;
warning C6246: Local declaration of 'e' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '10006' of 'c:\projects\extern\d\dmd\src\expression.c': Lines: 10006
10054: 10055: switch (t1->ty) 10056: { 10057: case Timaginary32: t2 = Type::tfloat32; break; 10058: case Timaginary64: t2 = Type::tfloat64; break; 10059: case Timaginary80: t2 = Type::tfloat80; break; 10060: default: 10061: assert(0); 10062: } 10063: e2 = e2->castTo(sc, t2); 10064: e = new AssignExp(loc, e1, e2); 10065: e->type = t1; 10066: return e; 10067: } 10068: } 10069: return this; 10070: } 10071: 10072: /************************************************************/ 10073: 10074: ModAssignExp::ModAssignExp(Loc loc, Expression *e1, Expression *e2) 10075: : BinAssignExp(loc, TOKmodass, sizeof(ModAssignExp), e1, e2) 10076: { 10077: } 10078: 10079: Expression *ModAssignExp::semantic(Scope *sc) 10080: { 10081: if (!type) 10082: { 10083: Expression *e = op_overload(sc); 10084: if (e) 10085: return e; 10086: 10087: checkComplexMulAssign(); 10088: return commonSemanticAssign(sc); 10089: } 10090: return this; 10091: } 10092: 10093: /************************************************************/ 10094: 10095: ShlAssignExp::ShlAssignExp(Loc loc, Expression *e1, Expression *e2) 10096: : BinAssignExp(loc, TOKshlass, sizeof(ShlAssignExp), e1, e2) 10097: { 10098: } 10099: 10100: Expression *ShlAssignExp::semantic(Scope *sc) 10101: { Expression *e; 10102: 10103: //printf("ShlAssignExp::semantic()\n"); 10104: 10105: e = op_overload(sc); 10106: if (e) 10107: return e; 10108: 10109: if (e1->op == TOKarraylength) 10110: { 10111: e = ArrayLengthExp::rewriteOpAssign(this); 10112: e = e->semantic(sc); 10113: return e; 10114: } 10115: 10116: e1 = e1->modifiableLvalue(sc, e1); 10117: e1->checkScalar(); 10118: e1->checkNoBool(); 10119: type = e1->type; 10120: typeCombine(sc); 10121: e1->checkIntegral(); 10122: e2 = e2->checkIntegral(); 10123: e2 = e2->castTo(sc, Type::tshiftcnt); 10124: return this; 10125: } 10126: 10127: /************************************************************/ 10128: 10129: ShrAssignExp::ShrAssignExp(Loc loc, Expression *e1, Expression *e2) 10130: : BinAssignExp(loc, TOKshrass, sizeof(ShrAssignExp), e1, e2) 10131: { 10132: } 10133: 10134: Expression *ShrAssignExp::semantic(Scope *sc) 10135: { Expression *e; 10136: 10137: e = op_overload(sc); 10138: if (e) 10139: return e; 10140: 10141: if (e1->op == TOKarraylength) 10142: { 10143: e = ArrayLengthExp::rewriteOpAssign(this); 10144: e = e->semantic(sc); 10145: return e; 10146: } 10147: 10148: e1 = e1->modifiableLvalue(sc, e1); 10149: e1->checkScalar(); 10150: e1->checkNoBool(); 10151: type = e1->type; 10152: typeCombine(sc); 10153: e1->checkIntegral(); 10154: e2 = e2->checkIntegral(); 10155: e2 = e2->castTo(sc, Type::tshiftcnt); 10156: return this; 10157: } 10158: 10159: /************************************************************/ 10160: 10161: UshrAssignExp::UshrAssignExp(Loc loc, Expression *e1, Expression *e2) 10162: : BinAssignExp(loc, TOKushrass, sizeof(UshrAssignExp), e1, e2) 10163: { 10164: } 10165: 10166: Expression *UshrAssignExp::semantic(Scope *sc) 10167: { Expression *e; 10168: 10169: e = op_overload(sc); 10170: if (e) 10171: return e; 10172: 10173: if (e1->op == TOKarraylength) 10174: { 10175: e = ArrayLengthExp::rewriteOpAssign(this); 10176: e = e->semantic(sc); 10177: return e; 10178: } 10179: 10180: e1 = e1->modifiableLvalue(sc, e1); 10181: e1->checkScalar(); 10182: e1->checkNoBool(); 10183: type = e1->type; 10184: typeCombine(sc); 10185: e1->checkIntegral(); 10186: e2 = e2->checkIntegral(); 10187: e2 = e2->castTo(sc, Type::tshiftcnt); 10188: return this; 10189: } 10190: 10191: /************************************************************/ 10192: 10193: AndAssignExp::AndAssignExp(Loc loc, Expression *e1, Expression *e2) 10194: : BinAssignExp(loc, TOKandass, sizeof(AndAssignExp), e1, e2) 10195: { 10196: } 10197: 10198: Expression *AndAssignExp::semantic(Scope *sc) 10199: { 10200: return commonSemanticAssignIntegral(sc); 10201: } 10202: 10203: /************************************************************/ 10204: 10205: OrAssignExp::OrAssignExp(Loc loc, Expression *e1, Expression *e2) 10206: : BinAssignExp(loc, TOKorass, sizeof(OrAssignExp), e1, e2) 10207: { 10208: } 10209: 10210: Expression *OrAssignExp::semantic(Scope *sc) 10211: { 10212: return commonSemanticAssignIntegral(sc); 10213: } 10214: 10215: /************************************************************/ 10216: 10217: XorAssignExp::XorAssignExp(Loc loc, Expression *e1, Expression *e2) 10218: : BinAssignExp(loc, TOKxorass, sizeof(XorAssignExp), e1, e2) 10219: { 10220: } 10221: 10222: Expression *XorAssignExp::semantic(Scope *sc) 10223: { 10224: return commonSemanticAssignIntegral(sc); 10225: } 10226: 10227: /***************** PowAssignExp *******************************************/ 10228: 10229: PowAssignExp::PowAssignExp(Loc loc, Expression *e1, Expression *e2) 10230: : BinAssignExp(loc, TOKpowass, sizeof(PowAssignExp), e1, e2) 10231: { 10232: } 10233: 10234: Expression *PowAssignExp::semantic(Scope *sc) 10235: { 10236: Expression *e; 10237: 10238: if (type) 10239: return this; 10240: 10241: e = op_overload(sc); 10242: if (e) 10243: return e; 10244: 10245: e1 = e1->modifiableLvalue(sc, e1); 10246: assert(e1->type && e2->type); 10247: 10248: if ( (e1->type->isintegral() || e1->type->isfloating()) && 10249: (e2->type->isintegral() || e2->type->isfloating())) 10250: { 10251: if (e1->op == TOKvar) 10252: { // Rewrite: e1 = e1 ^^ e2 10253: e = new PowExp(loc, e1->syntaxCopy(), e2); 10254: e = new AssignExp(loc, e1, e); 10255: } 10256: else 10257: { // Rewrite: ref tmp = e1; tmp = tmp ^^ e2 10258: Identifier *id = Lexer::uniqueId("__powtmp"); 10259: VarDeclaration *v = new VarDeclaration(e1->loc, e1->type, id, new ExpInitializer(loc, e1)); 10260: v->storage_class |= STCref | STCforeach; 10261: Expression *de = new DeclarationExp(e1->loc, v); 10262: VarExp *ve = new VarExp(e1->loc, v); 10263: e = new PowExp(loc, ve, e2); 10264: e = new AssignExp(loc, new VarExp(e1->loc, v), e); 10265: e = new CommaExp(loc, de, e); 10266: } 10267: e = e->semantic(sc); 10268: return e; 10269: } 10270: incompatibleTypes(); 10271: return new ErrorExp(); 10272: } 10273: 10274: 10275: /************************* AddExp *****************************/ 10276: 10277: AddExp::AddExp(Loc loc, Expression *e1, Expression *e2) 10278: : BinExp(loc, TOKadd, sizeof(AddExp), e1, e2) 10279: { 10280: } 10281: 10282: Expression *AddExp::semantic(Scope *sc) 10283: { Expression *e; 10284: 10285: #if LOGSEMANTIC 10286: printf("AddExp::semantic('%s')\n", toChars()); 10287: #endif 10288: if (!type) 10289: { 10290: BinExp::semanticp(sc); 10291: 10292: e = op_overload(sc); 10293: if (e) 10294: return e; 10295: 10296: Type *tb1 = e1->type->toBasetype(); 10297: Type *tb2 = e2->type->toBasetype(); 10298: 10299: if ((tb1->ty == Tarray || tb1->ty == Tsarray) && 10300: (tb2->ty == Tarray || tb2->ty == Tsarray) && 10301: tb1->nextOf()->equals(tb2->nextOf()) 10302: ) 10303: { 10304: type = e1->type; 10305: e = this; 10306: } 10307: else if (tb1->ty == Tpointer && e2->type->isintegral() || 10308: tb2->ty == Tpointer && e1->type->isintegral()) 10309: e = scaleFactor(sc); 10310: else if (tb1->ty == Tpointer && tb2->ty == Tpointer) 10311: { 10312: incompatibleTypes(); 10313: type = e1->type; 10314: e = this; 10315: } 10316: else 10317: { 10318: typeCombine(sc); 10319: if ((e1->type->isreal() && e2->type->isimaginary()) || 10320: (e1->type->isimaginary() && e2->type->isreal())) 10321: { 10322: switch (type->toBasetype()->ty) 10323: { 10324: case Tfloat32: 10325: case Timaginary32: 10326: type = Type::tcomplex32; 10327: break; 10328: 10329: case Tfloat64: 10330: case Timaginary64: 10331: type = Type::tcomplex64; 10332: break; 10333: 10334: case Tfloat80: 10335: case Timaginary80: 10336: type = Type::tcomplex80; 10337: break; 10338: 10339: default: 10340: assert(0); 10341: } 10342: } 10343: e = this; 10344: } 10345: return e; 10346: } 10347: return this; 10348: } 10349: 10350: /************************************************************/ 10351: 10352: MinExp::MinExp(Loc loc, Expression *e1, Expression *e2) 10353: : BinExp(loc, TOKmin, sizeof(MinExp), e1, e2) 10354: { 10355: } 10356: 10357: Expression *MinExp::semantic(Scope *sc) 10358: { Expression *e; 10359: Type *t1; 10360: Type *t2; 10361: 10362: #if LOGSEMANTIC 10363: printf("MinExp::semantic('%s')\n", toChars()); 10364: #endif 10365: if (type) 10366: return this; 10367: 10368: BinExp::semanticp(sc); 10369: 10370: e = op_overload(sc); 10371: if (e) 10372: return e; 10373: 10374: e = this; 10375: t1 = e1->type->toBasetype(); 10376: t2 = e2->type->toBasetype(); 10377: if (t1->ty == Tpointer) 10378: { 10379: if (t2->ty == Tpointer) 10380: { // Need to divide the result by the stride 10381: // Replace (ptr - ptr) with (ptr - ptr) / stride 10382: d_int64 stride; 10383: Expression *e;
warning C6246: Local declaration of 'e' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '10358' of 'c:\projects\extern\d\dmd\src\expression.c': Lines: 10358
10384: 10385: typeCombine(sc); // make sure pointer types are compatible 10386: type = Type::tptrdiff_t; 10387: stride = t2->nextOf()->size(); 10388: if (stride == 0) 10389: { 10390: e = new IntegerExp(loc, 0, Type::tptrdiff_t); 10391: } 10392: else 10393: { 10394: e = new DivExp(loc, this, new IntegerExp(0, stride, Type::tptrdiff_t)); 10395: e->type = Type::tptrdiff_t; 10396: } 10397: return e; 10398: } 10399: else if (t2->isintegral()) 10400: e = scaleFactor(sc); 10401: else 10402: { error("incompatible types for minus"); 10403: return new ErrorExp(); 10404: } 10405: } 10406: else if (t2->ty == Tpointer) 10407: { 10408: type = e2->type; 10409: error("can't subtract pointer from %s", e1->type->toChars()); 10410: return new ErrorExp(); 10411: } 10412: else 10413: { 10414: typeCombine(sc); 10415: t1 = e1->type->toBasetype(); 10416: t2 = e2->type->toBasetype(); 10417: if ((t1->isreal() && t2->isimaginary()) || 10418: (t1->isimaginary() && t2->isreal())) 10419: { 10420: switch (type->ty) 10421: { 10422: case Tfloat32: 10423: case Timaginary32: 10424: type = Type::tcomplex32; 10425: break; 10426: 10427: case Tfloat64: 10428: case Timaginary64: 10429: type = Type::tcomplex64; 10430: break; 10431: 10432: case Tfloat80: 10433: case Timaginary80: 10434: type = Type::tcomplex80; 10435: break; 10436: 10437: default: 10438: assert(0); 10439: } 10440: } 10441: } 10442: return e; 10443: } 10444: 10445: /************************* CatExp *****************************/ 10446: 10447: CatExp::CatExp(Loc loc, Expression *e1, Expression *e2) 10448: : BinExp(loc, TOKcat, sizeof(CatExp), e1, e2) 10449: { 10450: } 10451: 10452: Expression *CatExp::semantic(Scope *sc) 10453: { Expression *e; 10454: 10455: //printf("CatExp::semantic() %s\n", toChars()); 10456: if (!type) 10457: { 10458: BinExp::semanticp(sc); 10459: e = op_overload(sc); 10460: if (e) 10461: return e; 10462: 10463: Type *tb1 = e1->type->toBasetype(); 10464: Type *tb2 = e2->type->toBasetype(); 10465: 10466: 10467: /* BUG: Should handle things like: 10468: * char c; 10469: * c ~ ' ' 10470: * ' ' ~ c; 10471: */ 10472: 10473: #if 0 10474: e1->type->print(); 10475: e2->type->print(); 10476: #endif 10477: Type *tb1next = tb1->nextOf(); 10478: Type *tb2next = tb2->nextOf(); 10479: 10480: if ((tb1->ty == Tsarray || tb1->ty == Tarray) && 10481: e2->implicitConvTo(tb1next) >= MATCHconvert) 10482: { 10483: e2 = e2->implicitCastTo(sc, tb1next); 10484: type = tb1next->arrayOf(); 10485: if (tb2->ty == Tarray) 10486: { // Make e2 into [e2] 10487: e2 = new ArrayLiteralExp(e2->loc, e2); 10488: e2->type = type; 10489: } 10490: return this; 10491: } 10492: else if ((tb2->ty == Tsarray || tb2->ty == Tarray) && 10493: e1->implicitConvTo(tb2next) >= MATCHconvert) 10494: { 10495: e1 = e1->implicitCastTo(sc, tb2next); 10496: type = tb2next->arrayOf(); 10497: if (tb1->ty == Tarray) 10498: { // Make e1 into [e1] 10499: e1 = new ArrayLiteralExp(e1->loc, e1); 10500: e1->type = type; 10501: } 10502: return this; 10503: } 10504: 10505: if ((tb1->ty == Tsarray || tb1->ty == Tarray) && 10506: (tb2->ty == Tsarray || tb2->ty == Tarray) && 10507: (tb1next->mod || tb2next->mod) && 10508: (tb1next->mod != tb2next->mod) 10509: ) 10510: { 10511: Type *t1 = tb1next->mutableOf()->constOf()->arrayOf(); 10512: Type *t2 = tb2next->mutableOf()->constOf()->arrayOf(); 10513: if (e1->op == TOKstring && !((StringExp *)e1)->committed) 10514: e1->type = t1; 10515: else 10516: e1 = e1->castTo(sc, t1); 10517: if (e2->op == TOKstring && !((StringExp *)e2)->committed) 10518: e2->type = t2; 10519: else 10520: e2 = e2->castTo(sc, t2); 10521: } 10522: 10523: typeCombine(sc); 10524: type = type->toHeadMutable(); 10525: 10526: Type *tb = type->toBasetype(); 10527: if (tb->ty == Tsarray) 10528: type = tb->nextOf()->arrayOf(); 10529: if (type->ty == Tarray && tb1next && tb2next && 10530: tb1next->mod != tb2next->mod) 10531: { 10532: type = type->nextOf()->toHeadMutable()->arrayOf(); 10533: } 10534: #if 0 10535: e1->type->print(); 10536: e2->type->print(); 10537: type->print(); 10538: print(); 10539: #endif 10540: Type *t1 = e1->type->toBasetype(); 10541: Type *t2 = e2->type->toBasetype(); 10542: if (e1->op == TOKstring && e2->op == TOKstring) 10543: e = optimize(WANTvalue); 10544: else if ((t1->ty == Tarray || t1->ty == Tsarray) && 10545: (t2->ty == Tarray || t2->ty == Tsarray)) 10546: { 10547: e = this; 10548: } 10549: else 10550: { 10551: //printf("(%s) ~ (%s)\n", e1->toChars(), e2->toChars()); 10552: incompatibleTypes(); 10553: return new ErrorExp(); 10554: } 10555: e->type = e->type->semantic(loc, sc); 10556: return e; 10557: } 10558: return this; 10559: } 10560: 10561: /************************************************************/ 10562: 10563: MulExp::MulExp(Loc loc, Expression *e1, Expression *e2) 10564: : BinExp(loc, TOKmul, sizeof(MulExp), e1, e2) 10565: { 10566: } 10567: 10568: Expression *MulExp::semantic(Scope *sc) 10569: { Expression *e; 10570: 10571: #if 0 10572: printf("MulExp::semantic() %s\n", toChars()); 10573: #endif 10574: if (type) 10575: { 10576: return this; 10577: } 10578: 10579: BinExp::semanticp(sc); 10580: e = op_overload(sc); 10581: if (e) 10582: return e; 10583: 10584: typeCombine(sc); 10585: if (!e1->isArrayOperand()) 10586: e1->checkArithmetic(); 10587: if (!e2->isArrayOperand()) 10588: e2->checkArithmetic(); 10589: if (type->isfloating()) 10590: { Type *t1 = e1->type; 10591: Type *t2 = e2->type; 10592: 10593: if (t1->isreal()) 10594: { 10595: type = t2; 10596: } 10597: else if (t2->isreal()) 10598: { 10599: type = t1; 10600: } 10601: else if (t1->isimaginary()) 10602: { 10603: if (t2->isimaginary()) 10604: { Expression *e;
warning C6246: Local declaration of 'e' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '10569' of 'c:\projects\extern\d\dmd\src\expression.c': Lines: 10569
10605: 10606: switch (t1->toBasetype()->ty) 10607: { 10608: case Timaginary32: type = Type::tfloat32; break; 10609: case Timaginary64: type = Type::tfloat64; break; 10610: case Timaginary80: type = Type::tfloat80; break; 10611: default: assert(0); 10612: } 10613: 10614: // iy * iv = -yv 10615: e1->type = type; 10616: e2->type = type; 10617: e = new NegExp(loc, this); 10618: e = e->semantic(sc); 10619: return e; 10620: } 10621: else 10622: type = t2; // t2 is complex 10623: } 10624: else if (t2->isimaginary()) 10625: { 10626: type = t1; // t1 is complex 10627: } 10628: } 10629: return this; 10630: } 10631: 10632: /************************************************************/ 10633: 10634: DivExp::DivExp(Loc loc, Expression *e1, Expression *e2) 10635: : BinExp(loc, TOKdiv, sizeof(DivExp), e1, e2) 10636: { 10637: } 10638: 10639: Expression *DivExp::semantic(Scope *sc) 10640: { Expression *e; 10641: 10642: if (type) 10643: return this; 10644: 10645: BinExp::semanticp(sc); 10646: e = op_overload(sc); 10647: if (e) 10648: return e; 10649: 10650: typeCombine(sc); 10651: if (!e1->isArrayOperand()) 10652: e1->checkArithmetic(); 10653: if (!e2->isArrayOperand()) 10654: e2->checkArithmetic(); 10655: if (type->isfloating()) 10656: { Type *t1 = e1->type; 10657: Type *t2 = e2->type; 10658: 10659: if (t1->isreal()) 10660: { 10661: type = t2; 10662: if (t2->isimaginary()) 10663: { Expression *e;
warning C6246: Local declaration of 'e' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '10640' of 'c:\projects\extern\d\dmd\src\expression.c': Lines: 10640
10664: 10665: // x/iv = i(-x/v) 10666: e2->type = t1; 10667: e = new NegExp(loc, this); 10668: e = e->semantic(sc); 10669: return e; 10670: } 10671: } 10672: else if (t2->isreal()) 10673: { 10674: type = t1; 10675: } 10676: else if (t1->isimaginary()) 10677: { 10678: if (t2->isimaginary()) 10679: { 10680: switch (t1->toBasetype()->ty) 10681: { 10682: case Timaginary32: type = Type::tfloat32; break; 10683: case Timaginary64: type = Type::tfloat64; break; 10684: case Timaginary80: type = Type::tfloat80; break; 10685: default: assert(0); 10686: } 10687: } 10688: else 10689: type = t2; // t2 is complex 10690: } 10691: else if (t2->isimaginary()) 10692: { 10693: type = t1; // t1 is complex 10694: } 10695: } 10696: return this; 10697: } 10698: 10699: /************************************************************/ 10700: 10701: ModExp::ModExp(Loc loc, Expression *e1, Expression *e2) 10702: : BinExp(loc, TOKmod, sizeof(ModExp), e1, e2) 10703: { 10704: } 10705: 10706: Expression *ModExp::semantic(Scope *sc) 10707: { Expression *e; 10708: 10709: if (type) 10710: return this; 10711: 10712: BinExp::semanticp(sc); 10713: e = op_overload(sc); 10714: if (e) 10715: return e; 10716: 10717: typeCombine(sc); 10718: if (!e1->isArrayOperand()) 10719: e1->checkArithmetic(); 10720: if (!e2->isArrayOperand()) 10721: e2->checkArithmetic(); 10722: if (type->isfloating()) 10723: { type = e1->type; 10724: if (e2->type->iscomplex()) 10725: { error("cannot perform modulo complex arithmetic"); 10726: return new ErrorExp(); 10727: } 10728: } 10729: return this; 10730: } 10731: 10732: PowExp::PowExp(Loc loc, Expression *e1, Expression *e2) 10733: : BinExp(loc, TOKpow, sizeof(PowExp), e1, e2) 10734: { 10735: } 10736: 10737: Expression *PowExp::semantic(Scope *sc) 10738: { Expression *e; 10739: 10740: if (type) 10741: return this; 10742: 10743: //printf("PowExp::semantic() %s\n", toChars()); 10744: BinExp::semanticp(sc); 10745: e = op_overload(sc); 10746: if (e) 10747: return e; 10748: 10749: assert(e1->type && e2->type); 10750: if ( (e1->type->isintegral() || e1->type->isfloating()) && 10751: (e2->type->isintegral() || e2->type->isfloating())) 10752: { 10753: // For built-in numeric types, there are several cases. 10754: // TODO: backend support, especially for e1 ^^ 2. 10755: 10756: bool wantSqrt = false; 10757: e1 = e1->optimize(0); 10758: e2 = e2->optimize(0); 10759: 10760: // Replace 1 ^^ x or 1.0^^x by (x, 1) 10761: if ((e1->op == TOKint64 && e1->toInteger() == 1) || 10762: (e1->op == TOKfloat64 && e1->toReal() == 1.0)) 10763: { 10764: typeCombine(sc); 10765: e = new CommaExp(loc, e2, e1); 10766: e = e->semantic(sc); 10767: return e; 10768: } 10769: // Replace -1 ^^ x by (x&1) ? -1 : 1, where x is integral 10770: if (e2->type->isintegral() && e1->op == TOKint64 && (sinteger_t)e1->toInteger() == -1L) 10771: { 10772: typeCombine(sc); 10773: Type* resultType = type; 10774: e = new AndExp(loc, e2, new IntegerExp(loc, 1, e2->type)); 10775: e = new CondExp(loc, e, new IntegerExp(loc, -1L, resultType), new IntegerExp(loc, 1L, resultType)); 10776: e = e->semantic(sc); 10777: return e; 10778: } 10779: // Replace x ^^ 0 or x^^0.0 by (x, 1) 10780: if ((e2->op == TOKint64 && e2->toInteger() == 0) || 10781: (e2->op == TOKfloat64 && e2->toReal() == 0.0)) 10782: { 10783: if (e1->type->isintegral()) 10784: e = new IntegerExp(loc, 1, e1->type); 10785: else 10786: e = new RealExp(loc, 1.0, e1->type); 10787: 10788: typeCombine(sc); 10789: e = new CommaExp(loc, e1, e); 10790: e = e->semantic(sc); 10791: return e; 10792: } 10793: // Replace x ^^ 1 or x^^1.0 by (x) 10794: if ((e2->op == TOKint64 && e2->toInteger() == 1) || 10795: (e2->op == TOKfloat64 && e2->toReal() == 1.0)) 10796: { 10797: typeCombine(sc); 10798: return e1; 10799: } 10800: // Replace x ^^ -1.0 by (1.0 / x) 10801: if ((e2->op == TOKfloat64 && e2->toReal() == -1.0)) 10802: { 10803: typeCombine(sc); 10804: e = new DivExp(loc, new RealExp(loc, 1.0, e2->type), e1); 10805: e = e->semantic(sc); 10806: return e; 10807: } 10808: // All other negative integral powers are illegal 10809: if ((e1->type->isintegral()) && (e2->op == TOKint64) && (sinteger_t)e2->toInteger() < 0) 10810: { 10811: error("cannot raise %s to a negative integer power. Did you mean (cast(real)%s)^^%s ?", 10812: e1->type->toBasetype()->toChars(), e1->toChars(), e2->toChars()); 10813: return new ErrorExp(); 10814: } 10815: 10816: // Determine if we're raising to an integer power. 10817: sinteger_t intpow = 0; 10818: if (e2->op == TOKint64 && ((sinteger_t)e2->toInteger() == 2 || (sinteger_t)e2->toInteger() == 3)) 10819: intpow = e2->toInteger(); 10820: else if (e2->op == TOKfloat64 && (e2->toReal() == (sinteger_t)(e2->toReal()))) 10821: intpow = (sinteger_t)(e2->toReal()); 10822: 10823: // Deal with x^^2, x^^3 immediately, since they are of practical importance. 10824: if (intpow == 2 || intpow == 3) 10825: { 10826: typeCombine(sc); 10827: // Replace x^^2 with (tmp = x, tmp*tmp) 10828: // Replace x^^3 with (tmp = x, tmp*tmp*tmp) 10829: Identifier *idtmp = Lexer::uniqueId("__powtmp"); 10830: VarDeclaration *tmp = new VarDeclaration(loc, e1->type->toBasetype(), idtmp, new ExpInitializer(0, e1)); 10831: tmp->storage_class = STCctfe; 10832: Expression *ve = new VarExp(loc, tmp); 10833: Expression *ae = new DeclarationExp(loc, tmp); 10834: /* Note that we're reusing ve. This should be ok. 10835: */ 10836: Expression *me = new MulExp(loc, ve, ve); 10837: if (intpow == 3) 10838: me = new MulExp(loc, me, ve); 10839: e = new CommaExp(loc, ae, me); 10840: e = e->semantic(sc); 10841: return e; 10842: } 10843: 10844: static int importMathChecked = 0; 10845: if (!importMathChecked) 10846: { 10847: importMathChecked = 1; 10848: for (int i = 0; i < Module::amodules.dim; i++)
warning C4018: '<' : signed/unsigned mismatch
10849: { Module *mi = Module::amodules.tdata()[i]; 10850: //printf("\t[%d] %s\n", i, mi->toChars()); 10851: if (mi->ident == Id::math && 10852: mi->parent->ident == Id::std && 10853: !mi->parent->parent) 10854: goto L1; 10855: } 10856: error("must import std.math to use ^^ operator"); 10857: return new ErrorExp(); 10858: 10859: L1: ; 10860: } 10861: 10862: e = new IdentifierExp(loc, Id::empty); 10863: e = new DotIdExp(loc, e, Id::std); 10864: e = new DotIdExp(loc, e, Id::math); 10865: if (e2->op == TOKfloat64 && e2->toReal() == 0.5) 10866: { // Replace e1 ^^ 0.5 with .std.math.sqrt(x) 10867: typeCombine(sc); 10868: e = new CallExp(loc, new DotIdExp(loc, e, Id::_sqrt), e1); 10869: } 10870: else 10871: { 10872: // Replace e1 ^^ e2 with .std.math.pow(e1, e2) 10873: // We don't combine the types if raising to an integer power (because 10874: // integer powers are treated specially by std.math.pow). 10875: if (!e2->type->isintegral()) 10876: typeCombine(sc); 10877: // In fact, if it *could* have been an integer, make it one. 10878: if (e2->op == TOKfloat64 && intpow != 0) 10879: e2 = new IntegerExp(loc, intpow, Type::tint64); 10880: e = new CallExp(loc, new DotIdExp(loc, e, Id::_pow), e1, e2); 10881: } 10882: e = e->semantic(sc); 10883: // Always constant fold integer powers of literals. This will run the interpreter 10884: // on .std.math.pow 10885: if ((e1->op == TOKfloat64 || e1->op == TOKint64) && (e2->op == TOKint64)) 10886: e = e->optimize(WANTvalue | WANTinterpret); 10887: 10888: return e; 10889: } 10890: incompatibleTypes(); 10891: return new ErrorExp(); 10892: } 10893: 10894: /************************************************************/ 10895: 10896: ShlExp::ShlExp(Loc loc, Expression *e1, Expression *e2) 10897: : BinExp(loc, TOKshl, sizeof(ShlExp), e1, e2) 10898: { 10899: } 10900: 10901: Expression *ShlExp::semantic(Scope *sc) 10902: { Expression *e; 10903: 10904: //printf("ShlExp::semantic(), type = %p\n", type); 10905: if (!type) 10906: { BinExp::semanticp(sc); 10907: e = op_overload(sc); 10908: if (e) 10909: return e; 10910: e1 = e1->checkIntegral(); 10911: e2 = e2->checkIntegral(); 10912: e1 = e1->integralPromotions(sc); 10913: e2 = e2->castTo(sc, Type::tshiftcnt); 10914: type = e1->type; 10915: } 10916: return this; 10917: } 10918: 10919: /************************************************************/ 10920: 10921: ShrExp::ShrExp(Loc loc, Expression *e1, Expression *e2) 10922: : BinExp(loc, TOKshr, sizeof(ShrExp), e1, e2) 10923: { 10924: } 10925: 10926: Expression *ShrExp::semantic(Scope *sc) 10927: { Expression *e; 10928: 10929: if (!type) 10930: { BinExp::semanticp(sc); 10931: e = op_overload(sc); 10932: if (e) 10933: return e; 10934: e1 = e1->checkIntegral(); 10935: e2 = e2->checkIntegral(); 10936: e1 = e1->integralPromotions(sc); 10937: e2 = e2->castTo(sc, Type::tshiftcnt); 10938: type = e1->type; 10939: } 10940: return this; 10941: } 10942: 10943: /************************************************************/ 10944: 10945: UshrExp::UshrExp(Loc loc, Expression *e1, Expression *e2) 10946: : BinExp(loc, TOKushr, sizeof(UshrExp), e1, e2) 10947: { 10948: } 10949: 10950: Expression *UshrExp::semantic(Scope *sc) 10951: { Expression *e; 10952: 10953: if (!type) 10954: { BinExp::semanticp(sc); 10955: e = op_overload(sc); 10956: if (e) 10957: return e; 10958: e1 = e1->checkIntegral(); 10959: e2 = e2->checkIntegral(); 10960: e1 = e1->integralPromotions(sc); 10961: e2 = e2->castTo(sc, Type::tshiftcnt); 10962: type = e1->type; 10963: } 10964: return this; 10965: } 10966: 10967: /************************************************************/ 10968: 10969: AndExp::AndExp(Loc loc, Expression *e1, Expression *e2) 10970: : BinExp(loc, TOKand, sizeof(AndExp), e1, e2) 10971: { 10972: } 10973: 10974: Expression *AndExp::semantic(Scope *sc) 10975: { Expression *e; 10976: 10977: if (!type) 10978: { BinExp::semanticp(sc); 10979: e = op_overload(sc); 10980: if (e) 10981: return e; 10982: if (e1->type->toBasetype()->ty == Tbool && 10983: e2->type->toBasetype()->ty == Tbool) 10984: { 10985: type = e1->type; 10986: e = this; 10987: } 10988: else 10989: { 10990: typeCombine(sc); 10991: if (!e1->isArrayOperand()) 10992: e1->checkIntegral(); 10993: if (!e2->isArrayOperand()) 10994: e2->checkIntegral(); 10995: } 10996: } 10997: return this; 10998: } 10999: 11000: /************************************************************/ 11001: 11002: OrExp::OrExp(Loc loc, Expression *e1, Expression *e2) 11003: : BinExp(loc, TOKor, sizeof(OrExp), e1, e2) 11004: { 11005: } 11006: 11007: Expression *OrExp::semantic(Scope *sc) 11008: { Expression *e; 11009: 11010: if (!type) 11011: { BinExp::semanticp(sc); 11012: e = op_overload(sc); 11013: if (e) 11014: return e; 11015: if (e1->type->toBasetype()->ty == Tbool && 11016: e2->type->toBasetype()->ty == Tbool) 11017: { 11018: type = e1->type; 11019: e = this; 11020: } 11021: else 11022: { 11023: typeCombine(sc); 11024: if (!e1->isArrayOperand()) 11025: e1->checkIntegral(); 11026: if (!e2->isArrayOperand()) 11027: e2->checkIntegral(); 11028: } 11029: } 11030: return this; 11031: } 11032: 11033: /************************************************************/ 11034: 11035: XorExp::XorExp(Loc loc, Expression *e1, Expression *e2) 11036: : BinExp(loc, TOKxor, sizeof(XorExp), e1, e2) 11037: { 11038: } 11039: 11040: Expression *XorExp::semantic(Scope *sc) 11041: { Expression *e; 11042: 11043: if (!type) 11044: { BinExp::semanticp(sc); 11045: e = op_overload(sc); 11046: if (e) 11047: return e; 11048: if (e1->type->toBasetype()->ty == Tbool && 11049: e2->type->toBasetype()->ty == Tbool) 11050: { 11051: type = e1->type; 11052: e = this; 11053: } 11054: else 11055: { 11056: typeCombine(sc); 11057: if (!e1->isArrayOperand()) 11058: e1->checkIntegral(); 11059: if (!e2->isArrayOperand()) 11060: e2->checkIntegral(); 11061: } 11062: } 11063: return this; 11064: } 11065: 11066: 11067: /************************************************************/ 11068: 11069: OrOrExp::OrOrExp(Loc loc, Expression *e1, Expression *e2) 11070: : BinExp(loc, TOKoror, sizeof(OrOrExp), e1, e2) 11071: { 11072: } 11073: 11074: Expression *OrOrExp::semantic(Scope *sc) 11075: { 11076: unsigned cs1; 11077: 11078: // same as for AndAnd 11079: e1 = e1->semantic(sc); 11080: e1 = resolveProperties(sc, e1); 11081: e1 = e1->checkToPointer(); 11082: e1 = e1->checkToBoolean(sc); 11083: cs1 = sc->callSuper; 11084: 11085: if (sc->flags & SCOPEstaticif) 11086: { 11087: /* If in static if, don't evaluate e2 if we don't have to. 11088: */ 11089: e1 = e1->optimize(WANTflags); 11090: if (e1->isBool(TRUE)) 11091: { 11092: return new IntegerExp(loc, 1, Type::tboolean); 11093: } 11094: } 11095: 11096: e2 = e2->semantic(sc); 11097: sc->mergeCallSuper(loc, cs1); 11098: e2 = resolveProperties(sc, e2); 11099: e2 = e2->checkToPointer(); 11100: 11101: if (e2->type->ty == Tvoid) 11102: type = Type::tvoid; 11103: else 11104: { 11105: e2 = e2->checkToBoolean(sc); 11106: type = Type::tboolean; 11107: } 11108: if (e2->op == TOKtype || e2->op == TOKimport) 11109: { error("%s is not an expression", e2->toChars()); 11110: return new ErrorExp(); 11111: } 11112: if (e1->op == TOKerror) 11113: return e1; 11114: if (e2->op == TOKerror) 11115: return e2; 11116: return this; 11117: } 11118: 11119: Expression *OrOrExp::checkToBoolean(Scope *sc) 11120: { 11121: e2 = e2->checkToBoolean(sc); 11122: return this; 11123: } 11124: 11125: int OrOrExp::isBit() 11126: { 11127: return TRUE; 11128: } 11129: 11130: int OrOrExp::checkSideEffect(int flag) 11131: { 11132: if (flag == 2) 11133: { 11134: return e1->checkSideEffect(2) || e2->checkSideEffect(2); 11135: } 11136: else 11137: { e1->checkSideEffect(1); 11138: return e2->checkSideEffect(flag); 11139: } 11140: } 11141: 11142: /************************************************************/ 11143: 11144: AndAndExp::AndAndExp(Loc loc, Expression *e1, Expression *e2) 11145: : BinExp(loc, TOKandand, sizeof(AndAndExp), e1, e2) 11146: { 11147: } 11148: 11149: Expression *AndAndExp::semantic(Scope *sc) 11150: { 11151: unsigned cs1; 11152: 11153: // same as for OrOr 11154: e1 = e1->semantic(sc); 11155: e1 = resolveProperties(sc, e1); 11156: e1 = e1->checkToPointer(); 11157: e1 = e1->checkToBoolean(sc); 11158: cs1 = sc->callSuper; 11159: 11160: if (sc->flags & SCOPEstaticif) 11161: { 11162: /* If in static if, don't evaluate e2 if we don't have to. 11163: */ 11164: e1 = e1->optimize(WANTflags); 11165: if (e1->isBool(FALSE)) 11166: { 11167: return new IntegerExp(loc, 0, Type::tboolean); 11168: } 11169: } 11170: 11171: e2 = e2->semantic(sc); 11172: sc->mergeCallSuper(loc, cs1); 11173: e2 = resolveProperties(sc, e2); 11174: e2 = e2->checkToPointer(); 11175: 11176: if (e2->type->ty == Tvoid) 11177: type = Type::tvoid; 11178: else 11179: { 11180: e2 = e2->checkToBoolean(sc); 11181: type = Type::tboolean; 11182: } 11183: if (e2->op == TOKtype || e2->op == TOKimport) 11184: { error("%s is not an expression", e2->toChars()); 11185: return new ErrorExp(); 11186: } 11187: if (e1->op == TOKerror) 11188: return e1; 11189: if (e2->op == TOKerror) 11190: return e2; 11191: return this; 11192: } 11193: 11194: Expression *AndAndExp::checkToBoolean(Scope *sc) 11195: { 11196: e2 = e2->checkToBoolean(sc); 11197: return this; 11198: } 11199: 11200: int AndAndExp::isBit() 11201: { 11202: return TRUE; 11203: } 11204: 11205: int AndAndExp::checkSideEffect(int flag) 11206: { 11207: if (flag == 2) 11208: { 11209: return e1->checkSideEffect(2) || e2->checkSideEffect(2); 11210: } 11211: else 11212: { 11213: e1->checkSideEffect(1); 11214: return e2->checkSideEffect(flag); 11215: } 11216: } 11217: 11218: /************************************************************/ 11219: 11220: InExp::InExp(Loc loc, Expression *e1, Expression *e2) 11221: : BinExp(loc, TOKin, sizeof(InExp), e1, e2) 11222: { 11223: } 11224: 11225: Expression *InExp::semantic(Scope *sc) 11226: { Expression *e; 11227: 11228: if (type) 11229: return this; 11230: 11231: BinExp::semanticp(sc); 11232: e = op_overload(sc); 11233: if (e) 11234: return e; 11235: 11236: //type = Type::tboolean; 11237: Type *t2b = e2->type->toBasetype(); 11238: switch (t2b->ty) 11239: { 11240: case Taarray: 11241: { 11242: TypeAArray *ta = (TypeAArray *)t2b; 11243: 11244: #if DMDV2 11245: // Special handling for array keys 11246: if (!arrayTypeCompatible(e1->loc, e1->type, ta->index)) 11247: #endif 11248: { 11249: // Convert key to type of key 11250: e1 = e1->implicitCastTo(sc, ta->index); 11251: } 11252: 11253: // Return type is pointer to value 11254: type = ta->nextOf()->pointerTo(); 11255: break; 11256: } 11257: 11258: default: 11259: error("rvalue of in expression must be an associative array, not %s", e2->type->toChars()); 11260: case Terror: 11261: return new ErrorExp(); 11262: } 11263: return this; 11264: } 11265: 11266: int InExp::isBit() 11267: { 11268: return FALSE; 11269: } 11270: 11271: 11272: /************************************************************/ 11273: 11274: /* This deletes the key e1 from the associative array e2 11275: */ 11276: 11277: RemoveExp::RemoveExp(Loc loc, Expression *e1, Expression *e2) 11278: : BinExp(loc, TOKremove, sizeof(RemoveExp), e1, e2) 11279: { 11280: type = Type::tvoid; 11281: } 11282: 11283: void RemoveExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 11284: { 11285: expToCBuffer(buf, hgs, e1, PREC_primary); 11286: buf->writestring(".remove("); 11287: expToCBuffer(buf, hgs, e2, PREC_assign); 11288: buf->writestring(")"); 11289: } 11290: 11291: /************************************************************/ 11292: 11293: CmpExp::CmpExp(enum TOK op, Loc loc, Expression *e1, Expression *e2) 11294: : BinExp(loc, op, sizeof(CmpExp), e1, e2) 11295: { 11296: } 11297: 11298: Expression *CmpExp::semantic(Scope *sc) 11299: { Expression *e; 11300: 11301: #if LOGSEMANTIC 11302: printf("CmpExp::semantic('%s')\n", toChars()); 11303: #endif 11304: if (type) 11305: return this; 11306: 11307: BinExp::semanticp(sc); 11308: 11309: Type *t1 = e1->type->toBasetype(); 11310: Type *t2 = e2->type->toBasetype(); 11311: if (t1->ty == Tclass && e2->op == TOKnull || 11312: t2->ty == Tclass && e1->op == TOKnull) 11313: { 11314: error("do not use null when comparing class types"); 11315: return new ErrorExp(); 11316: } 11317: 11318: e = op_overload(sc); 11319: if (e) 11320: { 11321: if (!e->type->isscalar() && e->type->equals(e1->type)) 11322: { 11323: error("recursive opCmp expansion"); 11324: e = new ErrorExp(); 11325: } 11326: else 11327: { e = new CmpExp(op, loc, e, new IntegerExp(loc, 0, Type::tint32)); 11328: e = e->semantic(sc); 11329: } 11330: return e; 11331: } 11332: 11333: /* Disallow comparing T[]==T and T==T[] 11334: */ 11335: if (e1->op == TOKslice && t1->ty == Tarray && e2->implicitConvTo(t1->nextOf()) || 11336: e2->op == TOKslice && t2->ty == Tarray && e1->implicitConvTo(t2->nextOf())) 11337: { 11338: incompatibleTypes(); 11339: return new ErrorExp(); 11340: } 11341: 11342: typeCombine(sc); 11343: type = Type::tboolean; 11344: 11345: // Special handling for array comparisons 11346: t1 = e1->type->toBasetype(); 11347: t2 = e2->type->toBasetype(); 11348: if ((t1->ty == Tarray || t1->ty == Tsarray || t1->ty == Tpointer) && 11349: (t2->ty == Tarray || t2->ty == Tsarray || t2->ty == Tpointer)) 11350: { 11351: if (t1->nextOf()->implicitConvTo(t2->nextOf()) < MATCHconst && 11352: t2->nextOf()->implicitConvTo(t1->nextOf()) < MATCHconst && 11353: (t1->nextOf()->ty != Tvoid && t2->nextOf()->ty != Tvoid)) 11354: error("array comparison type mismatch, %s vs %s", t1->nextOf()->toChars(), t2->nextOf()->toChars()); 11355: e = this; 11356: } 11357: else if (t1->ty == Tstruct || t2->ty == Tstruct || 11358: (t1->ty == Tclass && t2->ty == Tclass)) 11359: { 11360: if (t2->ty == Tstruct) 11361: error("need member function opCmp() for %s %s to compare", t2->toDsymbol(sc)->kind(), t2->toChars()); 11362: else 11363: error("need member function opCmp() for %s %s to compare", t1->toDsymbol(sc)->kind(), t1->toChars()); 11364: e = new ErrorExp(); 11365: } 11366: #if 1 11367: else if (t1->iscomplex() || t2->iscomplex()) 11368: { 11369: error("compare not defined for complex operands"); 11370: e = new ErrorExp(); 11371: } 11372: #endif 11373: else 11374: { e1->rvalue(); 11375: e2->rvalue(); 11376: e = this; 11377: } 11378: //printf("CmpExp: %s, type = %s\n", e->toChars(), e->type->toChars()); 11379: return e; 11380: } 11381: 11382: int CmpExp::isBit() 11383: { 11384: return TRUE; 11385: } 11386: 11387: 11388: /************************************************************/ 11389: 11390: EqualExp::EqualExp(enum TOK op, Loc loc, Expression *e1, Expression *e2) 11391: : BinExp(loc, op, sizeof(EqualExp), e1, e2) 11392: { 11393: assert(op == TOKequal || op == TOKnotequal); 11394: } 11395: 11396: Expression *EqualExp::semantic(Scope *sc) 11397: { Expression *e; 11398: 11399: //printf("EqualExp::semantic('%s')\n", toChars()); 11400: if (type) 11401: return this; 11402: 11403: BinExp::semanticp(sc); 11404: 11405: /* Before checking for operator overloading, check to see if we're 11406: * comparing the addresses of two statics. If so, we can just see 11407: * if they are the same symbol. 11408: */ 11409: if (e1->op == TOKaddress && e2->op == TOKaddress) 11410: { AddrExp *ae1 = (AddrExp *)e1; 11411: AddrExp *ae2 = (AddrExp *)e2; 11412: 11413: if (ae1->e1->op == TOKvar && ae2->e1->op == TOKvar) 11414: { VarExp *ve1 = (VarExp *)ae1->e1; 11415: VarExp *ve2 = (VarExp *)ae2->e1; 11416: 11417: if (ve1->var == ve2->var /*|| ve1->var->toSymbol() == ve2->var->toSymbol()*/) 11418: { 11419: // They are the same, result is 'true' for ==, 'false' for != 11420: e = new IntegerExp(loc, (op == TOKequal), Type::tboolean); 11421: return e; 11422: } 11423: } 11424: } 11425: 11426: Type *t1 = e1->type->toBasetype(); 11427: Type *t2 = e2->type->toBasetype(); 11428: if (t1->ty == Tclass && e2->op == TOKnull || 11429: t2->ty == Tclass && e1->op == TOKnull) 11430: { 11431: error("use '%s' instead of '%s' when comparing with null", 11432: Token::toChars(op == TOKequal ? TOKidentity : TOKnotidentity), 11433: Token::toChars(op)); 11434: return new ErrorExp(); 11435: } 11436: 11437: if ((t1->ty == Tarray || t1->ty == Tsarray) && 11438: (t2->ty == Tarray || t2->ty == Tsarray)) 11439: { Type *t1n = t1->nextOf()->toBasetype(); 11440: Type *t2n = t2->nextOf()->toBasetype(); 11441: if (t1n->constOf() != t2n->constOf() && 11442: !((t1n->ty == Tchar || t1n->ty == Twchar || t1n->ty == Tdchar) && 11443: (t2n->ty == Tchar || t2n->ty == Twchar || t2n->ty == Tdchar)) && 11444: !(t1n->ty == Tvoid || t2n->ty == Tvoid) 11445: ) 11446: { /* Rewrite as: 11447: * _ArrayEq(e1, e2) 11448: */ 11449: Expression *eq = new IdentifierExp(loc, Id::_ArrayEq); 11450: Expressions *args = new Expressions(); 11451: args->push(e1); 11452: args->push(e2); 11453: e = new CallExp(loc, eq, args); 11454: if (op == TOKnotequal) 11455: e = new NotExp(loc, e); 11456: e = e->semantic(sc); 11457: return e; 11458: } 11459: } 11460: 11461: //if (e2->op != TOKnull) 11462: { 11463: e = op_overload(sc); 11464: if (e) 11465: { 11466: if (op == TOKnotequal) 11467: { 11468: e = new NotExp(e->loc, e); 11469: e = e->semantic(sc); 11470: } 11471: return e; 11472: } 11473: } 11474: 11475: /* Disallow comparing T[]==T and T==T[] 11476: */ 11477: if (e1->op == TOKslice && t1->ty == Tarray && e2->implicitConvTo(t1->nextOf()) || 11478: e2->op == TOKslice && t2->ty == Tarray && e1->implicitConvTo(t2->nextOf())) 11479: { 11480: incompatibleTypes(); 11481: return new ErrorExp(); 11482: } 11483: 11484: e = typeCombine(sc); 11485: type = Type::tboolean; 11486: 11487: // Special handling for array comparisons 11488: if (!arrayTypeCompatible(loc, e1->type, e2->type)) 11489: { 11490: if (e1->type != e2->type && e1->type->isfloating() && e2->type->isfloating()) 11491: { 11492: // Cast both to complex 11493: e1 = e1->castTo(sc, Type::tcomplex80); 11494: e2 = e2->castTo(sc, Type::tcomplex80); 11495: } 11496: } 11497: return e; 11498: } 11499: 11500: int EqualExp::isBit() 11501: { 11502: return TRUE; 11503: } 11504: 11505: 11506: 11507: /************************************************************/ 11508: 11509: IdentityExp::IdentityExp(enum TOK op, Loc loc, Expression *e1, Expression *e2) 11510: : BinExp(loc, op, sizeof(IdentityExp), e1, e2) 11511: { 11512: } 11513: 11514: Expression *IdentityExp::semantic(Scope *sc) 11515: { 11516: if (type) 11517: return this; 11518: 11519: BinExp::semanticp(sc); 11520: type = Type::tboolean; 11521: typeCombine(sc); 11522: if (e1->type != e2->type && e1->type->isfloating() && e2->type->isfloating()) 11523: { 11524: // Cast both to complex 11525: e1 = e1->castTo(sc, Type::tcomplex80); 11526: e2 = e2->castTo(sc, Type::tcomplex80); 11527: } 11528: return this; 11529: } 11530: 11531: int IdentityExp::isBit() 11532: { 11533: return TRUE; 11534: } 11535: 11536: 11537: /****************************************************************/ 11538: 11539: CondExp::CondExp(Loc loc, Expression *econd, Expression *e1, Expression *e2) 11540: : BinExp(loc, TOKquestion, sizeof(CondExp), e1, e2) 11541: { 11542: this->econd = econd; 11543: } 11544: 11545: Expression *CondExp::syntaxCopy() 11546: { 11547: return new CondExp(loc, econd->syntaxCopy(), e1->syntaxCopy(), e2->syntaxCopy()); 11548: } 11549: 11550: 11551: Expression *CondExp::semantic(Scope *sc) 11552: { Type *t1; 11553: Type *t2; 11554: unsigned cs0; 11555: unsigned cs1; 11556: 11557: #if LOGSEMANTIC 11558: printf("CondExp::semantic('%s')\n", toChars()); 11559: #endif 11560: if (type) 11561: return this; 11562: 11563: econd = econd->semantic(sc); 11564: econd = resolveProperties(sc, econd); 11565: econd = econd->checkToPointer(); 11566: econd = econd->checkToBoolean(sc); 11567: 11568: #if 0 /* this cannot work right because the types of e1 and e2 11569: * both contribute to the type of the result. 11570: */ 11571: if (sc->flags & SCOPEstaticif) 11572: { 11573: /* If in static if, don't evaluate what we don't have to. 11574: */ 11575: econd = econd->optimize(WANTflags); 11576: if (econd->isBool(TRUE)) 11577: { 11578: e1 = e1->semantic(sc); 11579: e1 = resolveProperties(sc, e1); 11580: return e1; 11581: } 11582: else if (econd->isBool(FALSE)) 11583: { 11584: e2 = e2->semantic(sc); 11585: e2 = resolveProperties(sc, e2); 11586: return e2; 11587: } 11588: } 11589: #endif 11590: 11591: 11592: cs0 = sc->callSuper; 11593: e1 = e1->semantic(sc); 11594: e1 = resolveProperties(sc, e1); 11595: cs1 = sc->callSuper; 11596: sc->callSuper = cs0; 11597: e2 = e2->semantic(sc); 11598: e2 = resolveProperties(sc, e2); 11599: sc->mergeCallSuper(loc, cs1); 11600: 11601: 11602: // If either operand is void, the result is void 11603: t1 = e1->type; 11604: t2 = e2->type; 11605: if (t1->ty == Tvoid || t2->ty == Tvoid) 11606: type = Type::tvoid; 11607: else if (t1 == t2) 11608: type = t1; 11609: else 11610: { 11611: typeCombine(sc); 11612: switch (e1->type->toBasetype()->ty) 11613: { 11614: case Tcomplex32: 11615: case Tcomplex64: 11616: case Tcomplex80: 11617: e2 = e2->castTo(sc, e1->type); 11618: break; 11619: } 11620: switch (e2->type->toBasetype()->ty) 11621: { 11622: case Tcomplex32: 11623: case Tcomplex64: 11624: case Tcomplex80: 11625: e1 = e1->castTo(sc, e2->type); 11626: break; 11627: } 11628: if (type->toBasetype()->ty == Tarray) 11629: { 11630: e1 = e1->castTo(sc, type); 11631: e2 = e2->castTo(sc, type); 11632: } 11633: } 11634: #if 0 11635: printf("res: %s\n", type->toChars()); 11636: printf("e1 : %s\n", e1->type->toChars()); 11637: printf("e2 : %s\n", e2->type->toChars()); 11638: #endif 11639: return this; 11640: } 11641: 11642: #if DMDV2 11643: int CondExp::isLvalue() 11644: { 11645: return e1->isLvalue() && e2->isLvalue(); 11646: } 11647: #endif 11648: 11649: Expression *CondExp::toLvalue(Scope *sc, Expression *ex) 11650: { 11651: PtrExp *e; 11652: 11653: // convert (econd ? e1 : e2) to *(econd ? &e1 : &e2) 11654: e = new PtrExp(loc, this, type); 11655: 11656: e1 = e1->addressOf(sc); 11657: //e1 = e1->toLvalue(sc, NULL); 11658: 11659: e2 = e2->addressOf(sc); 11660: //e2 = e2->toLvalue(sc, NULL); 11661: 11662: typeCombine(sc); 11663: 11664: type = e2->type; 11665: return e; 11666: } 11667: 11668: Expression *CondExp::modifiableLvalue(Scope *sc, Expression *e) 11669: { 11670: //error("conditional expression %s is not a modifiable lvalue", toChars()); 11671: e1 = e1->modifiableLvalue(sc, e1); 11672: e2 = e2->modifiableLvalue(sc, e1); 11673: return toLvalue(sc, this); 11674: } 11675: 11676: void CondExp::checkEscape() 11677: { 11678: e1->checkEscape(); 11679: e2->checkEscape(); 11680: } 11681: 11682: void CondExp::checkEscapeRef() 11683: { 11684: e1->checkEscapeRef(); 11685: e2->checkEscapeRef(); 11686: } 11687: 11688: 11689: Expression *CondExp::checkToBoolean(Scope *sc) 11690: { 11691: e1 = e1->checkToBoolean(sc); 11692: e2 = e2->checkToBoolean(sc); 11693: return this; 11694: } 11695: 11696: int CondExp::checkSideEffect(int flag) 11697: { 11698: if (flag == 2) 11699: { 11700: return econd->checkSideEffect(2) || 11701: e1->checkSideEffect(2) || 11702: e2->checkSideEffect(2); 11703: } 11704: else 11705: { 11706: econd->checkSideEffect(1); 11707: e1->checkSideEffect(flag); 11708: return e2->checkSideEffect(flag); 11709: } 11710: } 11711: 11712: #if DMDV2 11713: int CondExp::canThrow(bool mustNotThrow) 11714: { 11715: return econd->canThrow(mustNotThrow) || e1->canThrow(mustNotThrow) || e2->canThrow(mustNotThrow); 11716: } 11717: #endif 11718: 11719: void CondExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 11720: { 11721: expToCBuffer(buf, hgs, econd, PREC_oror); 11722: buf->writestring(" ? "); 11723: expToCBuffer(buf, hgs, e1, PREC_expr); 11724: buf->writestring(" : "); 11725: expToCBuffer(buf, hgs, e2, PREC_cond); 11726: } 11727: 11728: 11729: /****************************************************************/ 11730: 11731: DefaultInitExp::DefaultInitExp(Loc loc, enum TOK subop, int size) 11732: : Expression(loc, TOKdefault, size) 11733: { 11734: this->subop = subop; 11735: } 11736: 11737: void DefaultInitExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 11738: { 11739: buf->writestring(Token::toChars(subop)); 11740: } 11741: 11742: /****************************************************************/ 11743: 11744: FileInitExp::FileInitExp(Loc loc) 11745: : DefaultInitExp(loc, TOKfile, sizeof(FileInitExp)) 11746: { 11747: } 11748: 11749: Expression *FileInitExp::semantic(Scope *sc) 11750: { 11751: //printf("FileInitExp::semantic()\n"); 11752: type = Type::tchar->invariantOf()->arrayOf(); 11753: return this; 11754: } 11755: 11756: Expression *FileInitExp::resolveLoc(Loc loc, Scope *sc) 11757: { 11758: //printf("FileInitExp::resolve() %s\n", toChars()); 11759: const char *s = loc.filename ? loc.filename : sc->module->ident->toChars(); 11760: Expression *e = new StringExp(loc, (char *)s); 11761: e = e->semantic(sc); 11762: e = e->castTo(sc, type); 11763: return e; 11764: } 11765: 11766: /****************************************************************/ 11767: 11768: LineInitExp::LineInitExp(Loc loc) 11769: : DefaultInitExp(loc, TOKline, sizeof(LineInitExp)) 11770: { 11771: } 11772: 11773: Expression *LineInitExp::semantic(Scope *sc) 11774: { 11775: type = Type::tint32; 11776: return this; 11777: } 11778: 11779: Expression *LineInitExp::resolveLoc(Loc loc, Scope *sc) 11780: { 11781: Expression *e = new IntegerExp(loc, loc.linnum, Type::tint32); 11782: e = e->castTo(sc, type); 11783: return e; 11784: } 11785: 11786: 11787: