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