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: // http://www.dsource.org/projects/dmd/browser/trunk/src/mtype.c
   8: // License for redistribution is by either the Artistic License
   9: // in artistic.txt, or the GNU General Public License in gnu.txt.
  10: // See the included readme.txt for details.
  11: 
  12: #define __C99FEATURES__ 1       // Needed on Solaris for NaN and more
  13: #define __USE_ISOC99 1          // so signbit() gets defined
  14: 
  15: #if (defined (__SVR4) && defined (__sun))
  16: #include <alloca.h>
  17: #endif
  18: 
  19: #include <math.h>
  20: 
  21: #include <stdio.h>
  22: static char __file__[] = __FILE__;      /* for tassert.h                */
  23: #include        "tassert.h"
  24: #include <float.h>
  25: 
  26: #if _MSC_VER
  27: #include <malloc.h>
  28: #include <complex>
  29: #include <limits>
  30: #elif __DMC__
  31: #include <complex.h>
  32: #elif __MINGW32__
  33: #include <malloc.h>
  34: #endif
  35: 
  36: #include "rmem.h"
  37: #include "port.h"
  38: 
  39: #include "dsymbol.h"
  40: #include "mtype.h"
  41: #include "scope.h"
  42: #include "init.h"
  43: #include "expression.h"
  44: #include "attrib.h"
  45: #include "declaration.h"
  46: #include "template.h"
  47: #include "id.h"
  48: #include "enum.h"
  49: #include "import.h"
  50: #include "aggregate.h"
  51: #include "hdrgen.h"
  52: 
  53: FuncDeclaration *hasThis(Scope *sc);
  54: 
  55: 
  56: #define LOGDOTEXP       0       // log ::dotExp()
  57: #define LOGDEFAULTINIT  0       // log ::defaultInit()
  58: 
  59: // Allow implicit conversion of T[] to T*
  60: #define IMPLICIT_ARRAY_TO_PTR   global.params.useDeprecated
  61: 
  62: /* These have default values for 32 bit code, they get
  63:  * adjusted for 64 bit code.
  64:  */
  65: 
  66: int PTRSIZE = 4;
  67: 
  68: /* REALSIZE = size a real consumes in memory
  69:  * REALPAD = 'padding' added to the CPU real size to bring it up to REALSIZE
  70:  * REALALIGNSIZE = alignment for reals
  71:  */
  72: #if TARGET_OSX
  73: int REALSIZE = 16;
  74: int REALPAD = 6;
  75: int REALALIGNSIZE = 16;
  76: #elif TARGET_LINUX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_SOLARIS
  77: int REALSIZE = 12;
  78: int REALPAD = 2;
  79: int REALALIGNSIZE = 4;
  80: #elif TARGET_WINDOS
  81: int REALSIZE = 10;
  82: int REALPAD = 0;
  83: int REALALIGNSIZE = 2;
  84: #else
  85: #error "fix this"
  86: #endif
  87: 
  88: int Tsize_t = Tuns32;
  89: int Tptrdiff_t = Tint32;
  90: 
  91: /***************************** Type *****************************/
  92: 
  93: ClassDeclaration *Type::typeinfo;
  94: ClassDeclaration *Type::typeinfoclass;
  95: ClassDeclaration *Type::typeinfointerface;
  96: ClassDeclaration *Type::typeinfostruct;
  97: ClassDeclaration *Type::typeinfotypedef;
  98: ClassDeclaration *Type::typeinfopointer;
  99: ClassDeclaration *Type::typeinfoarray;
 100: ClassDeclaration *Type::typeinfostaticarray;
 101: ClassDeclaration *Type::typeinfoassociativearray;
 102: ClassDeclaration *Type::typeinfoenum;
 103: ClassDeclaration *Type::typeinfofunction;
 104: ClassDeclaration *Type::typeinfodelegate;
 105: ClassDeclaration *Type::typeinfotypelist;
 106: ClassDeclaration *Type::typeinfoconst;
 107: ClassDeclaration *Type::typeinfoinvariant;
 108: ClassDeclaration *Type::typeinfoshared;
 109: ClassDeclaration *Type::typeinfowild;
 110: 
 111: TemplateDeclaration *Type::associativearray;
 112: 
 113: Type *Type::tvoidptr;
 114: Type *Type::tstring;
 115: Type *Type::basic[TMAX];
 116: unsigned char Type::mangleChar[TMAX];
 117: unsigned char Type::sizeTy[TMAX];
 118: StringTable Type::stringtable;
 119: 
 120: 
 121: Type::Type(TY ty)
 122: {
 123:     this->ty = ty;
 124:     this->mod = 0;
 125:     this->deco = NULL;
 126: #if DMDV2
 127:     this->cto = NULL;
 128:     this->ito = NULL;
 129:     this->sto = NULL;
 130:     this->scto = NULL;
 131:     this->wto = NULL;
 132:     this->swto = NULL;
 133: #endif
 134:     this->pto = NULL;
 135:     this->rto = NULL;
 136:     this->arrayof = NULL;
 137:     this->vtinfo = NULL;
 138:     this->ctype = NULL;
 139: }
 140: 
 141: Type *Type::syntaxCopy()
 142: {
 143:     print();
 144:     fprintf(stdmsg, "ty = %d\n", ty);
 145:     assert(0);
 146:     return this;
 147: }
 148: 
 149: int Type::equals(Object *o)
 150: {   Type *t;
 151: 
 152:     t = (Type *)o;
 153:     //printf("Type::equals(%s, %s)\n", toChars(), t->toChars());
 154:     if (this == o ||
 155:         (t && deco == t->deco) &&               // deco strings are unique
 156:          deco != NULL)                          // and semantic() has been run
 157:     {
 158:         //printf("deco = '%s', t->deco = '%s'\n", deco, t->deco);
 159:         return 1;
 160:     }
 161:     //if (deco && t && t->deco) printf("deco = '%s', t->deco = '%s'\n", deco, t->deco);
 162:     return 0;
 163: }
 164: 
 165: char Type::needThisPrefix()
 166: {
 167:     return 'M';         // name mangling prefix for functions needing 'this'
 168: }
 169: 
 170: void Type::init()
 171: {   int i;
 172:     int j;
warning C4101: 'j' : unreferenced local variable
173: 174: Lexer::initKeywords(); 175: 176: for (i = 0; i < TMAX; i++) 177: sizeTy[i] = sizeof(TypeBasic); 178: sizeTy[Tsarray] = sizeof(TypeSArray); 179: sizeTy[Tarray] = sizeof(TypeDArray); 180: sizeTy[Taarray] = sizeof(TypeAArray); 181: sizeTy[Tpointer] = sizeof(TypePointer); 182: sizeTy[Treference] = sizeof(TypeReference); 183: sizeTy[Tfunction] = sizeof(TypeFunction); 184: sizeTy[Tdelegate] = sizeof(TypeDelegate); 185: sizeTy[Tident] = sizeof(TypeIdentifier); 186: sizeTy[Tinstance] = sizeof(TypeInstance); 187: sizeTy[Ttypeof] = sizeof(TypeTypeof); 188: sizeTy[Tenum] = sizeof(TypeEnum); 189: sizeTy[Ttypedef] = sizeof(TypeTypedef); 190: sizeTy[Tstruct] = sizeof(TypeStruct); 191: sizeTy[Tclass] = sizeof(TypeClass); 192: sizeTy[Ttuple] = sizeof(TypeTuple); 193: sizeTy[Tslice] = sizeof(TypeSlice); 194: sizeTy[Treturn] = sizeof(TypeReturn); 195: 196: mangleChar[Tarray] = 'A'; 197: mangleChar[Tsarray] = 'G'; 198: mangleChar[Taarray] = 'H'; 199: mangleChar[Tpointer] = 'P'; 200: mangleChar[Treference] = 'R'; 201: mangleChar[Tfunction] = 'F'; 202: mangleChar[Tident] = 'I'; 203: mangleChar[Tclass] = 'C'; 204: mangleChar[Tstruct] = 'S'; 205: mangleChar[Tenum] = 'E'; 206: mangleChar[Ttypedef] = 'T'; 207: mangleChar[Tdelegate] = 'D'; 208: 209: mangleChar[Tnone] = 'n'; 210: mangleChar[Tvoid] = 'v'; 211: mangleChar[Tint8] = 'g'; 212: mangleChar[Tuns8] = 'h'; 213: mangleChar[Tint16] = 's'; 214: mangleChar[Tuns16] = 't'; 215: mangleChar[Tint32] = 'i'; 216: mangleChar[Tuns32] = 'k'; 217: mangleChar[Tint64] = 'l'; 218: mangleChar[Tuns64] = 'm'; 219: mangleChar[Tfloat32] = 'f'; 220: mangleChar[Tfloat64] = 'd'; 221: mangleChar[Tfloat80] = 'e'; 222: 223: mangleChar[Timaginary32] = 'o'; 224: mangleChar[Timaginary64] = 'p'; 225: mangleChar[Timaginary80] = 'j'; 226: mangleChar[Tcomplex32] = 'q'; 227: mangleChar[Tcomplex64] = 'r'; 228: mangleChar[Tcomplex80] = 'c'; 229: 230: mangleChar[Tbool] = 'b'; 231: mangleChar[Tascii] = 'a'; 232: mangleChar[Twchar] = 'u'; 233: mangleChar[Tdchar] = 'w'; 234: 235: // '@' shouldn't appear anywhere in the deco'd names 236: mangleChar[Tinstance] = '@'; 237: mangleChar[Terror] = '@'; 238: mangleChar[Ttypeof] = '@'; 239: mangleChar[Ttuple] = 'B'; 240: mangleChar[Tslice] = '@'; 241: mangleChar[Treturn] = '@'; 242: 243: for (i = 0; i < TMAX; i++) 244: { if (!mangleChar[i]) 245: fprintf(stdmsg, "ty = %d\n", i); 246: assert(mangleChar[i]); 247: } 248: 249: // Set basic types 250: static TY basetab[] = 251: { Tvoid, Tint8, Tuns8, Tint16, Tuns16, Tint32, Tuns32, Tint64, Tuns64, 252: Tfloat32, Tfloat64, Tfloat80, 253: Timaginary32, Timaginary64, Timaginary80, 254: Tcomplex32, Tcomplex64, Tcomplex80, 255: Tbool, 256: Tascii, Twchar, Tdchar }; 257: 258: for (i = 0; i < sizeof(basetab) / sizeof(basetab[0]); i++) 259: { Type *t = new TypeBasic(basetab[i]);
warning C6211: Leaking memory 't' due to an exception. Consider using a local catch block to clean up memory: Lines: 171, 172, 174, 176, 177, 176, 177, 176, 177, 176, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 223, 224, 225, 226, 227, 228, 230, 231, 232, 233, 236, 237, 238, 239, 240, 241, 243, 244, 246, 243, 244, 246, 243, 244, 246, 243, 250, 258, 259, 260, 261, 258, 259, 260, 261, 258, 259, 260, 261, 258, 263
260: t = t->merge(); 261: basic[basetab[i]] = t; 262: } 263: basic[Terror] = new TypeError(); 264: 265: tvoidptr = tvoid->pointerTo(); 266: tstring = tchar->invariantOf()->arrayOf(); 267: 268: if (global.params.is64bit) 269: { 270: PTRSIZE = 8; 271: if (global.params.isLinux || global.params.isFreeBSD || global.params.isSolaris) 272: { 273: REALSIZE = 16; 274: REALPAD = 6; 275: REALALIGNSIZE = 16; 276: } 277: Tsize_t = Tuns64; 278: Tptrdiff_t = Tint64; 279: } 280: else 281: { 282: PTRSIZE = 4; 283: #if TARGET_OSX 284: REALSIZE = 16; 285: REALPAD = 6; 286: #elif TARGET_LINUX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_SOLARIS 287: REALSIZE = 12; 288: REALPAD = 2; 289: #else 290: REALSIZE = 10; 291: REALPAD = 0; 292: #endif 293: Tsize_t = Tuns32; 294: Tptrdiff_t = Tint32; 295: } 296: } 297: 298: d_uns64 Type::size() 299: { 300: return size(0); 301: } 302: 303: d_uns64 Type::size(Loc loc) 304: { 305: error(loc, "no size for type %s", toChars()); 306: return 1; 307: } 308: 309: unsigned Type::alignsize() 310: { 311: return size(0);
warning C4244: 'return' : conversion from 'd_uns64' to 'unsigned int', possible loss of data
312: } 313: 314: Type *Type::semantic(Loc loc, Scope *sc) 315: { 316: return merge(); 317: } 318: 319: Type *Type::trySemantic(Loc loc, Scope *sc) 320: { 321: //printf("+trySemantic(%s) %d\n", toChars(), global.errors); 322: unsigned errors = global.errors; 323: global.gag++; // suppress printing of error messages 324: Type *t = semantic(loc, sc); 325: global.gag--; 326: if (errors != global.errors) // if any errors happened 327: { 328: global.errors = errors; 329: t = NULL; 330: } 331: //printf("-trySemantic(%s) %d\n", toChars(), global.errors); 332: return t; 333: } 334: 335: /******************************* 336: * Determine if converting 'this' to 'to' is an identity operation, 337: * a conversion to const operation, or the types aren't the same. 338: * Returns: 339: * MATCHequal 'this' == 'to' 340: * MATCHconst 'to' is const 341: * MATCHnomatch conversion to mutable or invariant 342: */ 343: 344: MATCH Type::constConv(Type *to) 345: { 346: if (equals(to)) 347: return MATCHexact; 348: if (ty == to->ty && MODimplicitConv(mod, to->mod)) 349: return MATCHconst; 350: return MATCHnomatch; 351: } 352: 353: /******************************** 354: * Convert to 'const'. 355: */ 356: 357: Type *Type::constOf() 358: { 359: //printf("Type::constOf() %p %s\n", this, toChars()); 360: if (mod == MODconst) 361: return this; 362: if (cto) 363: { assert(cto->mod == MODconst); 364: return cto; 365: } 366: Type *t = makeConst(); 367: t = t->merge(); 368: t->fixTo(this); 369: //printf("-Type::constOf() %p %s\n", t, toChars()); 370: return t; 371: } 372: 373: /******************************** 374: * Convert to 'immutable'. 375: */ 376: 377: Type *Type::invariantOf() 378: { 379: //printf("Type::invariantOf() %p %s\n", this, toChars()); 380: if (isImmutable()) 381: { 382: return this; 383: } 384: if (ito) 385: { 386: assert(ito->isImmutable()); 387: return ito; 388: } 389: Type *t = makeInvariant(); 390: t = t->merge(); 391: t->fixTo(this); 392: //printf("\t%p\n", t); 393: return t; 394: } 395: 396: /******************************** 397: * Make type mutable. 398: */ 399: 400: Type *Type::mutableOf() 401: { 402: //printf("Type::mutableOf() %p, %s\n", this, toChars()); 403: Type *t = this; 404: if (isConst()) 405: { if (isShared()) 406: t = sto; // shared const => shared 407: else 408: t = cto; // const => naked 409: assert(!t || t->isMutable()); 410: } 411: else if (isImmutable()) 412: { t = ito; // immutable => naked 413: assert(!t || (t->isMutable() && !t->isShared())); 414: } 415: else if (isWild()) 416: { 417: if (isShared()) 418: t = sto; // shared wild => shared 419: else 420: t = wto; // wild => naked 421: assert(!t || t->isMutable()); 422: } 423: if (!t) 424: { 425: t = makeMutable(); 426: t = t->merge(); 427: t->fixTo(this); 428: } 429: assert(t->isMutable()); 430: return t; 431: } 432: 433: Type *Type::sharedOf() 434: { 435: //printf("Type::sharedOf() %p, %s\n", this, toChars()); 436: if (mod == MODshared) 437: { 438: return this; 439: } 440: if (sto) 441: { 442: assert(sto->isShared()); 443: return sto; 444: } 445: Type *t = makeShared(); 446: t = t->merge(); 447: t->fixTo(this); 448: //printf("\t%p\n", t); 449: return t; 450: } 451: 452: Type *Type::sharedConstOf() 453: { 454: //printf("Type::sharedConstOf() %p, %s\n", this, toChars()); 455: if (mod == (MODshared | MODconst)) 456: { 457: return this; 458: } 459: if (scto) 460: { 461: assert(scto->mod == (MODshared | MODconst)); 462: return scto; 463: } 464: Type *t = makeSharedConst(); 465: t = t->merge(); 466: t->fixTo(this); 467: //printf("\t%p\n", t); 468: return t; 469: } 470: 471: 472: /******************************** 473: * Make type unshared. 474: * 0 => 0 475: * const => const 476: * immutable => immutable 477: * shared => 0 478: * shared const => const 479: * wild => wild 480: * shared wild => wild 481: */ 482: 483: Type *Type::unSharedOf() 484: { 485: //printf("Type::unSharedOf() %p, %s\n", this, toChars()); 486: Type *t = this; 487: 488: if (isShared()) 489: { 490: if (isConst()) 491: t = cto; // shared const => const 492: else if (isWild()) 493: t = wto; // shared wild => wild 494: else 495: t = sto; 496: assert(!t || !t->isShared()); 497: } 498: 499: if (!t) 500: { 501: unsigned sz = sizeTy[ty]; 502: t = (Type *)mem.malloc(sz); 503: memcpy(t, this, sz); 504: t->mod = mod & ~MODshared; 505: t->deco = NULL; 506: t->arrayof = NULL; 507: t->pto = NULL; 508: t->rto = NULL; 509: t->cto = NULL; 510: t->ito = NULL; 511: t->sto = NULL; 512: t->scto = NULL; 513: t->wto = NULL; 514: t->swto = NULL; 515: t->vtinfo = NULL; 516: t = t->merge(); 517: 518: t->fixTo(this); 519: } 520: assert(!t->isShared()); 521: return t; 522: } 523: 524: /******************************** 525: * Convert to 'wild'. 526: */ 527: 528: Type *Type::wildOf() 529: { 530: //printf("Type::wildOf() %p %s\n", this, toChars()); 531: if (mod == MODwild) 532: { 533: return this; 534: } 535: if (wto) 536: { 537: assert(wto->isWild()); 538: return wto; 539: } 540: Type *t = makeWild(); 541: t = t->merge(); 542: t->fixTo(this); 543: //printf("\t%p %s\n", t, t->toChars()); 544: return t; 545: } 546: 547: Type *Type::sharedWildOf() 548: { 549: //printf("Type::sharedWildOf() %p, %s\n", this, toChars()); 550: if (mod == (MODshared | MODwild)) 551: { 552: return this; 553: } 554: if (swto) 555: { 556: assert(swto->mod == (MODshared | MODwild)); 557: return swto; 558: } 559: Type *t = makeSharedWild(); 560: t = t->merge(); 561: t->fixTo(this); 562: //printf("\t%p\n", t); 563: return t; 564: } 565: 566: /********************************** 567: * For our new type 'this', which is type-constructed from t, 568: * fill in the cto, ito, sto, scto, wto shortcuts. 569: */ 570: 571: void Type::fixTo(Type *t) 572: { 573: ito = t->ito; 574: #if 0 575: /* Cannot do these because these are not fully transitive: 576: * there can be a shared ptr to immutable, for example. 577: * Immutable subtypes are always immutable, though. 578: */ 579: cto = t->cto; 580: sto = t->sto; 581: scto = t->scto; 582: #endif 583: 584: assert(mod != t->mod); 585: #define X(m, n) (((m) << 4) | (n)) 586: switch (X(mod, t->mod)) 587: { 588: case X(0, MODconst): 589: cto = t; 590: break; 591: 592: case X(0, MODimmutable): 593: ito = t; 594: break; 595: 596: case X(0, MODshared): 597: sto = t; 598: break; 599: 600: case X(0, MODshared | MODconst): 601: scto = t; 602: break; 603: 604: case X(0, MODwild): 605: wto = t; 606: break; 607: 608: case X(0, MODshared | MODwild): 609: swto = t; 610: break; 611: 612: 613: case X(MODconst, 0): 614: cto = NULL; 615: goto L2; 616: 617: case X(MODconst, MODimmutable): 618: ito = t; 619: goto L2; 620: 621: case X(MODconst, MODshared): 622: sto = t; 623: goto L2; 624: 625: case X(MODconst, MODshared | MODconst): 626: scto = t; 627: goto L2; 628: 629: case X(MODconst, MODwild): 630: wto = t; 631: goto L2; 632: 633: case X(MODconst, MODshared | MODwild): 634: swto = t; 635: L2: 636: t->cto = this; 637: break; 638: 639: 640: case X(MODimmutable, 0): 641: ito = NULL; 642: goto L3; 643: 644: case X(MODimmutable, MODconst): 645: cto = t; 646: goto L3; 647: 648: case X(MODimmutable, MODshared): 649: sto = t; 650: goto L3; 651: 652: case X(MODimmutable, MODshared | MODconst): 653: scto = t; 654: goto L3; 655: 656: case X(MODimmutable, MODwild): 657: wto = t; 658: goto L3; 659: 660: case X(MODimmutable, MODshared | MODwild): 661: swto = t; 662: L3: 663: t->ito = this; 664: if (t->cto) t->cto->ito = this; 665: if (t->sto) t->sto->ito = this; 666: if (t->scto) t->scto->ito = this; 667: if (t->wto) t->wto->ito = this; 668: if (t->swto) t->swto->ito = this; 669: break; 670: 671: 672: case X(MODshared, 0): 673: sto = NULL; 674: goto L4; 675: 676: case X(MODshared, MODconst): 677: cto = t; 678: goto L4; 679: 680: case X(MODshared, MODimmutable): 681: ito = t; 682: goto L4; 683: 684: case X(MODshared, MODshared | MODconst): 685: scto = t; 686: goto L4; 687: 688: case X(MODshared, MODwild): 689: wto = t; 690: goto L4; 691: 692: case X(MODshared, MODshared | MODwild): 693: swto = t; 694: L4: 695: t->sto = this; 696: break; 697: 698: 699: case X(MODshared | MODconst, 0): 700: scto = NULL; 701: goto L5; 702: 703: case X(MODshared | MODconst, MODconst): 704: cto = t; 705: goto L5; 706: 707: case X(MODshared | MODconst, MODimmutable): 708: ito = t; 709: goto L5; 710: 711: case X(MODshared | MODconst, MODwild): 712: wto = t; 713: goto L5; 714: 715: case X(MODshared | MODconst, MODshared): 716: sto = t; 717: goto L5; 718: 719: case X(MODshared | MODconst, MODshared | MODwild): 720: swto = t; 721: L5: 722: t->scto = this; 723: break; 724: 725: 726: case X(MODwild, 0): 727: wto = NULL; 728: goto L6; 729: 730: case X(MODwild, MODconst): 731: cto = t; 732: goto L6; 733: 734: case X(MODwild, MODimmutable): 735: ito = t; 736: goto L6; 737: 738: case X(MODwild, MODshared): 739: sto = t; 740: goto L6; 741: 742: case X(MODwild, MODshared | MODconst): 743: scto = t; 744: goto L6; 745: 746: case X(MODwild, MODshared | MODwild): 747: swto = t; 748: L6: 749: t->wto = this; 750: break; 751: 752: 753: case X(MODshared | MODwild, 0): 754: swto = NULL; 755: goto L7; 756: 757: case X(MODshared | MODwild, MODconst): 758: cto = t; 759: goto L7; 760: 761: case X(MODshared | MODwild, MODimmutable): 762: ito = t; 763: goto L7; 764: 765: case X(MODshared | MODwild, MODshared): 766: sto = t; 767: goto L7; 768: 769: case X(MODshared | MODwild, MODshared | MODconst): 770: scto = t; 771: goto L7; 772: 773: case X(MODshared | MODwild, MODwild): 774: wto = t; 775: L7: 776: t->swto = this; 777: break; 778: 779: 780: default: 781: assert(0); 782: } 783: #undef X 784: 785: check(); 786: t->check(); 787: //printf("fixTo: %s, %s\n", toChars(), t->toChars()); 788: } 789: 790: /*************************** 791: * Look for bugs in constructing types. 792: */ 793: 794: void Type::check() 795: { 796: switch (mod) 797: { 798: case 0: 799: if (cto) assert(cto->mod == MODconst); 800: if (ito) assert(ito->mod == MODimmutable); 801: if (sto) assert(sto->mod == MODshared); 802: if (scto) assert(scto->mod == (MODshared | MODconst)); 803: if (wto) assert(wto->mod == MODwild); 804: if (swto) assert(swto->mod == (MODshared | MODwild)); 805: break; 806: 807: case MODconst: 808: if (cto) assert(cto->mod == 0); 809: if (ito) assert(ito->mod == MODimmutable); 810: if (sto) assert(sto->mod == MODshared); 811: if (scto) assert(scto->mod == (MODshared | MODconst)); 812: if (wto) assert(wto->mod == MODwild); 813: if (swto) assert(swto->mod == (MODshared | MODwild)); 814: break; 815: 816: case MODimmutable: 817: if (cto) assert(cto->mod == MODconst); 818: if (ito) assert(ito->mod == 0); 819: if (sto) assert(sto->mod == MODshared); 820: if (scto) assert(scto->mod == (MODshared | MODconst)); 821: if (wto) assert(wto->mod == MODwild); 822: if (swto) assert(swto->mod == (MODshared | MODwild)); 823: break; 824: 825: case MODshared: 826: if (cto) assert(cto->mod == MODconst); 827: if (ito) assert(ito->mod == MODimmutable); 828: if (sto) assert(sto->mod == 0); 829: if (scto) assert(scto->mod == (MODshared | MODconst)); 830: if (wto) assert(wto->mod == MODwild); 831: if (swto) assert(swto->mod == (MODshared | MODwild)); 832: break; 833: 834: case MODshared | MODconst: 835: if (cto) assert(cto->mod == MODconst); 836: if (ito) assert(ito->mod == MODimmutable); 837: if (sto) assert(sto->mod == MODshared); 838: if (scto) assert(scto->mod == 0); 839: if (wto) assert(wto->mod == MODwild); 840: if (swto) assert(swto->mod == (MODshared | MODwild)); 841: break; 842: 843: case MODwild: 844: if (cto) assert(cto->mod == MODconst); 845: if (ito) assert(ito->mod == MODimmutable); 846: if (sto) assert(sto->mod == MODshared); 847: if (scto) assert(scto->mod == (MODshared | MODconst)); 848: if (wto) assert(wto->mod == 0); 849: if (swto) assert(swto->mod == (MODshared | MODwild)); 850: break; 851: 852: case MODshared | MODwild: 853: if (cto) assert(cto->mod == MODconst); 854: if (ito) assert(ito->mod == MODimmutable); 855: if (sto) assert(sto->mod == MODshared); 856: if (scto) assert(scto->mod == (MODshared | MODconst)); 857: if (wto) assert(wto->mod == MODwild); 858: if (swto) assert(swto->mod == 0); 859: break; 860: 861: default: 862: assert(0); 863: } 864: 865: Type *tn = nextOf(); 866: if (tn && ty != Tfunction && ty != Tdelegate) 867: { // Verify transitivity 868: switch (mod) 869: { 870: case 0: 871: break; 872: 873: case MODconst: 874: assert(tn->mod & MODimmutable || tn->mod & MODconst); 875: break; 876: 877: case MODimmutable: 878: assert(tn->mod == MODimmutable); 879: break; 880: 881: case MODshared: 882: assert(tn->mod & MODimmutable || tn->mod & MODshared); 883: break; 884: 885: case MODshared | MODconst: 886: assert(tn->mod & MODimmutable || tn->mod & (MODshared | MODconst)); 887: break; 888: 889: case MODwild: 890: assert(tn->mod); 891: break; 892: 893: case MODshared | MODwild: 894: assert(tn->mod == MODimmutable || tn->mod == (MODshared | MODconst) || tn->mod == (MODshared | MODwild)); 895: break; 896: 897: default: 898: assert(0); 899: } 900: tn->check(); 901: } 902: } 903: 904: Type *Type::makeConst() 905: { 906: //printf("Type::makeConst() %p, %s\n", this, toChars()); 907: if (cto) 908: return cto; 909: unsigned sz = sizeTy[ty]; 910: Type *t = (Type *)mem.malloc(sz); 911: memcpy(t, this, sz); 912: t->mod = MODconst; 913: t->deco = NULL; 914: t->arrayof = NULL; 915: t->pto = NULL; 916: t->rto = NULL; 917: t->cto = NULL; 918: t->ito = NULL; 919: t->sto = NULL; 920: t->scto = NULL; 921: t->wto = NULL; 922: t->swto = NULL; 923: t->vtinfo = NULL; 924: //printf("-Type::makeConst() %p, %s\n", t, toChars()); 925: return t; 926: } 927: 928: Type *Type::makeInvariant() 929: { 930: if (ito) 931: return ito; 932: unsigned sz = sizeTy[ty]; 933: Type *t = (Type *)mem.malloc(sz); 934: memcpy(t, this, sz); 935: t->mod = MODimmutable; 936: t->deco = NULL; 937: t->arrayof = NULL; 938: t->pto = NULL; 939: t->rto = NULL; 940: t->cto = NULL; 941: t->ito = NULL; 942: t->sto = NULL; 943: t->scto = NULL; 944: t->wto = NULL; 945: t->swto = NULL; 946: t->vtinfo = NULL; 947: return t; 948: } 949: 950: Type *Type::makeShared() 951: { 952: if (sto) 953: return sto; 954: unsigned sz = sizeTy[ty]; 955: Type *t = (Type *)mem.malloc(sz); 956: memcpy(t, this, sz); 957: t->mod = MODshared; 958: t->deco = NULL; 959: t->arrayof = NULL; 960: t->pto = NULL; 961: t->rto = NULL; 962: t->cto = NULL; 963: t->ito = NULL; 964: t->sto = NULL; 965: t->scto = NULL; 966: t->wto = NULL; 967: t->swto = NULL; 968: t->vtinfo = NULL; 969: return t; 970: } 971: 972: Type *Type::makeSharedConst() 973: { 974: if (scto) 975: return scto; 976: unsigned sz = sizeTy[ty]; 977: Type *t = (Type *)mem.malloc(sz); 978: memcpy(t, this, sz); 979: t->mod = MODshared | MODconst; 980: t->deco = NULL; 981: t->arrayof = NULL; 982: t->pto = NULL; 983: t->rto = NULL; 984: t->cto = NULL; 985: t->ito = NULL; 986: t->sto = NULL; 987: t->scto = NULL; 988: t->wto = NULL; 989: t->swto = NULL; 990: t->vtinfo = NULL; 991: return t; 992: } 993: 994: Type *Type::makeWild() 995: { 996: if (wto) 997: return wto; 998: unsigned sz = sizeTy[ty]; 999: Type *t = (Type *)mem.malloc(sz); 1000: memcpy(t, this, sz); 1001: t->mod = MODwild; 1002: t->deco = NULL; 1003: t->arrayof = NULL; 1004: t->pto = NULL; 1005: t->rto = NULL; 1006: t->cto = NULL; 1007: t->ito = NULL; 1008: t->sto = NULL; 1009: t->scto = NULL; 1010: t->wto = NULL; 1011: t->swto = NULL; 1012: t->vtinfo = NULL; 1013: return t; 1014: } 1015: 1016: Type *Type::makeSharedWild() 1017: { 1018: if (swto) 1019: return swto; 1020: unsigned sz = sizeTy[ty]; 1021: Type *t = (Type *)mem.malloc(sz); 1022: memcpy(t, this, sz); 1023: t->mod = MODshared | MODwild; 1024: t->deco = NULL; 1025: t->arrayof = NULL; 1026: t->pto = NULL; 1027: t->rto = NULL; 1028: t->cto = NULL; 1029: t->ito = NULL; 1030: t->sto = NULL; 1031: t->scto = NULL; 1032: t->wto = NULL; 1033: t->swto = NULL; 1034: t->vtinfo = NULL; 1035: return t; 1036: } 1037: 1038: Type *Type::makeMutable() 1039: { 1040: unsigned sz = sizeTy[ty]; 1041: Type *t = (Type *)mem.malloc(sz); 1042: memcpy(t, this, sz); 1043: t->mod = mod & MODshared; 1044: t->deco = NULL; 1045: t->arrayof = NULL; 1046: t->pto = NULL; 1047: t->rto = NULL; 1048: t->cto = NULL; 1049: t->ito = NULL; 1050: t->sto = NULL; 1051: t->scto = NULL; 1052: t->wto = NULL; 1053: t->swto = NULL; 1054: t->vtinfo = NULL; 1055: return t; 1056: } 1057: 1058: /************************************ 1059: * Apply MODxxxx bits to existing type. 1060: */ 1061: 1062: Type *Type::castMod(unsigned mod) 1063: { Type *t; 1064: 1065: switch (mod) 1066: { 1067: case 0: 1068: t = unSharedOf()->mutableOf(); 1069: break; 1070: 1071: case MODconst: 1072: t = unSharedOf()->constOf(); 1073: break; 1074: 1075: case MODimmutable: 1076: t = invariantOf(); 1077: break; 1078: 1079: case MODshared: 1080: t = mutableOf()->sharedOf(); 1081: break; 1082: 1083: case MODshared | MODconst: 1084: t = sharedConstOf(); 1085: break; 1086: 1087: case MODwild: 1088: t = unSharedOf()->wildOf(); 1089: break; 1090: 1091: case MODshared | MODwild: 1092: t = sharedWildOf(); 1093: break; 1094: 1095: default: 1096: assert(0); 1097: } 1098: return t; 1099: } 1100: 1101: /************************************ 1102: * Add MODxxxx bits to existing type. 1103: * We're adding, not replacing, so adding const to 1104: * a shared type => "shared const" 1105: */ 1106: 1107: Type *Type::addMod(unsigned mod) 1108: { Type *t = this; 1109: 1110: /* Add anything to immutable, and it remains immutable 1111: */ 1112: if (!t->isImmutable()) 1113: { 1114: //printf("addMod(%x) %s\n", mod, toChars()); 1115: switch (mod) 1116: { 1117: case 0: 1118: break; 1119: 1120: case MODconst: 1121: if (isShared()) 1122: t = sharedConstOf(); 1123: else 1124: t = constOf(); 1125: break; 1126: 1127: case MODimmutable: 1128: t = invariantOf(); 1129: break; 1130: 1131: case MODshared: 1132: if (isConst()) 1133: t = sharedConstOf(); 1134: else if (isWild()) 1135: t = sharedWildOf(); 1136: else 1137: t = sharedOf(); 1138: break; 1139: 1140: case MODshared | MODconst: 1141: t = sharedConstOf(); 1142: break; 1143: 1144: case MODwild: 1145: if (isConst()) 1146: ; 1147: else if (isShared()) 1148: t = sharedWildOf(); 1149: else 1150: t = wildOf(); 1151: break; 1152: 1153: case MODshared | MODwild: 1154: t = sharedWildOf(); 1155: break; 1156: 1157: default: 1158: assert(0); 1159: } 1160: } 1161: return t; 1162: } 1163: 1164: /************************************ 1165: * Add storage class modifiers to type. 1166: */ 1167: 1168: Type *Type::addStorageClass(StorageClass stc) 1169: { 1170: /* Just translate to MOD bits and let addMod() do the work 1171: */ 1172: unsigned mod = 0; 1173: 1174: if (stc & STCimmutable) 1175: mod = MODimmutable; 1176: else 1177: { if (stc & (STCconst | STCin)) 1178: mod = MODconst; 1179: else if (stc & STCwild) // const takes precedence over wild 1180: mod |= MODwild; 1181: if (stc & STCshared) 1182: mod |= MODshared; 1183: } 1184: return addMod(mod); 1185: } 1186: 1187: /************************** 1188: * Return type with the top level of it being mutable. 1189: */ 1190: Type *Type::toHeadMutable() 1191: { 1192: if (!mod) 1193: return this; 1194: return mutableOf(); 1195: } 1196: 1197: Type *Type::pointerTo() 1198: { 1199: if (ty == Terror) 1200: return this; 1201: if (!pto) 1202: { Type *t; 1203: 1204: t = new TypePointer(this); 1205: pto = t->merge(); 1206: } 1207: return pto; 1208: } 1209: 1210: Type *Type::referenceTo() 1211: { 1212: if (ty == Terror) 1213: return this; 1214: if (!rto) 1215: { Type *t; 1216: 1217: t = new TypeReference(this); 1218: rto = t->merge(); 1219: } 1220: return rto; 1221: } 1222: 1223: Type *Type::arrayOf() 1224: { 1225: if (ty == Terror) 1226: return this; 1227: if (!arrayof) 1228: { Type *t; 1229: 1230: t = new TypeDArray(this); 1231: arrayof = t->merge(); 1232: } 1233: return arrayof; 1234: } 1235: 1236: Dsymbol *Type::toDsymbol(Scope *sc) 1237: { 1238: return NULL; 1239: } 1240: 1241: /******************************* 1242: * If this is a shell around another type, 1243: * get that other type. 1244: */ 1245: 1246: Type *Type::toBasetype() 1247: { 1248: return this; 1249: } 1250: 1251: /*************************** 1252: * Return !=0 if modfrom can be implicitly converted to modto 1253: */ 1254: int MODimplicitConv(unsigned char modfrom, unsigned char modto) 1255: { 1256: if (modfrom == modto) 1257: return 1; 1258: 1259: //printf("MODimplicitConv(from = %x, to = %x)\n", modfrom, modto); 1260: #define X(m, n) (((m) << 4) | (n)) 1261: switch (X(modfrom, modto)) 1262: { 1263: case X(0, MODconst): 1264: case X(MODimmutable, MODconst): 1265: case X(MODwild, MODconst): 1266: case X(MODimmutable, MODconst | MODshared): 1267: case X(MODshared, MODconst | MODshared): 1268: case X(MODwild | MODshared, MODconst | MODshared): 1269: return 1; 1270: 1271: default: 1272: return 0; 1273: } 1274: #undef X 1275: } 1276: 1277: /*************************** 1278: * Merge mod bits to form common mod. 1279: */ 1280: int MODmerge(unsigned char mod1, unsigned char mod2) 1281: { 1282: if (mod1 == mod2) 1283: return mod1; 1284: 1285: //printf("MODmerge(1 = %x, 2 = %x)\n", modfrom, modto); 1286: #define X(m, n) (((m) << 4) | (n)) 1287: // cases are commutative 1288: #define Y(m, n) X(m, n): case X(n, m) 1289: switch (X(mod1, mod2)) 1290: { 1291: #if 0 1292: case X(0, 0): 1293: case X(MODconst, MODconst): 1294: case X(MODimmutable, MODimmutable): 1295: case X(MODshared, MODshared): 1296: case X(MODshared | MODconst, MODshared | MODconst): 1297: case X(MODwild, MODwild): 1298: case X(MODshared | MODwild, MODshared | MODwild): 1299: #endif 1300: 1301: case Y(0, MODconst): 1302: case Y(0, MODimmutable): 1303: case Y(MODconst, MODimmutable): 1304: case Y(MODconst, MODwild): 1305: case Y(0, MODwild): 1306: case Y(MODimmutable, MODwild): 1307: return MODconst; 1308: 1309: case Y(0, MODshared): 1310: return MODshared; 1311: 1312: case Y(0, MODshared | MODconst): 1313: case Y(MODconst, MODshared): 1314: case Y(MODconst, MODshared | MODconst): 1315: case Y(MODimmutable, MODshared): 1316: case Y(MODimmutable, MODshared | MODconst): 1317: case Y(MODshared, MODshared | MODconst): 1318: case Y(0, MODshared | MODwild): 1319: case Y(MODconst, MODshared | MODwild): 1320: case Y(MODimmutable, MODshared | MODwild): 1321: case Y(MODshared, MODwild): 1322: case Y(MODshared, MODshared | MODwild): 1323: case Y(MODshared | MODconst, MODwild): 1324: case Y(MODshared | MODconst, MODshared | MODwild): 1325: return MODshared | MODconst; 1326: 1327: case Y(MODwild, MODshared | MODwild): 1328: return MODshared | MODwild; 1329: 1330: default: 1331: assert(0); 1332: } 1333: #undef Y 1334: #undef X 1335: assert(0); 1336: return 0; 1337: } 1338: 1339: /********************************* 1340: * Mangling for mod. 1341: */ 1342: void MODtoDecoBuffer(OutBuffer *buf, unsigned char mod) 1343: { 1344: switch (mod) 1345: { case 0: 1346: break; 1347: case MODconst: 1348: buf->writeByte('x'); 1349: break; 1350: case MODimmutable: 1351: buf->writeByte('y'); 1352: break; 1353: case MODshared: 1354: buf->writeByte('O'); 1355: break; 1356: case MODshared | MODconst: 1357: buf->writestring("Ox"); 1358: break; 1359: case MODwild: 1360: buf->writestring("Ng"); 1361: break; 1362: case MODshared | MODwild: 1363: buf->writestring("ONg"); 1364: break; 1365: default: 1366: assert(0); 1367: } 1368: } 1369: 1370: /********************************* 1371: * Name for mod. 1372: */ 1373: void MODtoBuffer(OutBuffer *buf, unsigned char mod) 1374: { 1375: switch (mod) 1376: { case 0: 1377: break; 1378: 1379: case MODimmutable: 1380: buf->writestring(Token::tochars[TOKimmutable]); 1381: break; 1382: 1383: case MODshared: 1384: buf->writestring(Token::tochars[TOKshared]); 1385: break; 1386: 1387: case MODshared | MODconst: 1388: buf->writestring(Token::tochars[TOKshared]); 1389: buf->writeByte(' '); 1390: case MODconst: 1391: buf->writestring(Token::tochars[TOKconst]); 1392: break; 1393: 1394: case MODshared | MODwild: 1395: buf->writestring(Token::tochars[TOKshared]); 1396: buf->writeByte(' '); 1397: case MODwild: 1398: buf->writestring(Token::tochars[TOKwild]); 1399: break; 1400: default: 1401: assert(0); 1402: } 1403: } 1404: 1405: /******************************** 1406: * Name mangling. 1407: * Input: 1408: * flag 0x100 do not do const/invariant 1409: */ 1410: 1411: void Type::toDecoBuffer(OutBuffer *buf, int flag) 1412: { 1413: if (flag != mod && flag != 0x100) 1414: { 1415: MODtoDecoBuffer(buf, mod); 1416: } 1417: buf->writeByte(mangleChar[ty]); 1418: } 1419: 1420: /******************************** 1421: * For pretty-printing a type. 1422: */ 1423: 1424: char *Type::toChars() 1425: { OutBuffer *buf; 1426: HdrGenState hgs; 1427: 1428: buf = new OutBuffer(); 1429: toCBuffer(buf, NULL, &hgs); 1430: return buf->toChars(); 1431: } 1432: 1433: void Type::toCBuffer(OutBuffer *buf, Identifier *ident, HdrGenState *hgs) 1434: { 1435: toCBuffer2(buf, hgs, 0); 1436: if (ident) 1437: { buf->writeByte(' '); 1438: buf->writestring(ident->toChars()); 1439: } 1440: } 1441: 1442: void Type::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod) 1443: { 1444: if (mod != this->mod) 1445: { toCBuffer3(buf, hgs, mod); 1446: return; 1447: } 1448: buf->writestring(toChars()); 1449: } 1450: 1451: void Type::toCBuffer3(OutBuffer *buf, HdrGenState *hgs, int mod) 1452: { 1453: if (mod != this->mod) 1454: { 1455: if (this->mod & MODshared) 1456: { 1457: MODtoBuffer(buf, this->mod & MODshared); 1458: buf->writeByte('('); 1459: } 1460: if (this->mod & ~MODshared) 1461: { 1462: MODtoBuffer(buf, this->mod & ~MODshared); 1463: buf->writeByte('('); 1464: toCBuffer2(buf, hgs, this->mod); 1465: buf->writeByte(')'); 1466: } 1467: else 1468: toCBuffer2(buf, hgs, this->mod); 1469: if (this->mod & MODshared) 1470: { 1471: buf->writeByte(')'); 1472: } 1473: } 1474: } 1475: 1476: void Type::modToBuffer(OutBuffer *buf) 1477: { 1478: if (mod) 1479: { 1480: buf->writeByte(' '); 1481: MODtoBuffer(buf, mod); 1482: } 1483: } 1484: 1485: /************************************ 1486: */ 1487: 1488: Type *Type::merge() 1489: { Type *t; 1490: 1491: //printf("merge(%s)\n", toChars()); 1492: t = this; 1493: assert(t); 1494: if (!deco) 1495: { 1496: OutBuffer buf; 1497: StringValue *sv; 1498: 1499: //if (next) 1500: //next = next->merge(); 1501: toDecoBuffer(&buf); 1502: sv = stringtable.update((char *)buf.data, buf.offset); 1503: if (sv->ptrvalue) 1504: { t = (Type *) sv->ptrvalue; 1505: #ifdef DEBUG 1506: if (!t->deco) 1507: printf("t = %s\n", t->toChars()); 1508: #endif 1509: assert(t->deco); 1510: //printf("old value, deco = '%s' %p\n", t->deco, t->deco); 1511: } 1512: else 1513: { 1514: sv->ptrvalue = this; 1515: deco = sv->lstring.string; 1516: //printf("new value, deco = '%s' %p\n", t->deco, t->deco); 1517: } 1518: } 1519: return t; 1520: } 1521: 1522: /************************************* 1523: * This version does a merge even if the deco is already computed. 1524: * Necessary for types that have a deco, but are not merged. 1525: */ 1526: Type *Type::merge2() 1527: { 1528: //printf("merge2(%s)\n", toChars()); 1529: Type *t = this; 1530: assert(t); 1531: if (!t->deco) 1532: return t->merge(); 1533: 1534: StringValue *sv = stringtable.lookup((char *)t->deco, strlen(t->deco)); 1535: if (sv && sv->ptrvalue) 1536: { t = (Type *) sv->ptrvalue; 1537: assert(t->deco); 1538: } 1539: else 1540: assert(0); 1541: return t; 1542: } 1543: 1544: int Type::isintegral() 1545: { 1546: return FALSE; 1547: } 1548: 1549: int Type::isfloating() 1550: { 1551: return FALSE; 1552: } 1553: 1554: int Type::isreal() 1555: { 1556: return FALSE; 1557: } 1558: 1559: int Type::isimaginary() 1560: { 1561: return FALSE; 1562: } 1563: 1564: int Type::iscomplex() 1565: { 1566: return FALSE; 1567: } 1568: 1569: int Type::isscalar() 1570: { 1571: return FALSE; 1572: } 1573: 1574: int Type::isunsigned() 1575: { 1576: return FALSE; 1577: } 1578: 1579: ClassDeclaration *Type::isClassHandle() 1580: { 1581: return NULL; 1582: } 1583: 1584: int Type::isscope() 1585: { 1586: return FALSE; 1587: } 1588: 1589: int Type::isString() 1590: { 1591: return FALSE; 1592: } 1593: 1594: /************************** 1595: * Given: 1596: * T a, b; 1597: * Can we assign: 1598: * a = b; 1599: * ? 1600: */ 1601: int Type::isAssignable() 1602: { 1603: return TRUE; 1604: } 1605: 1606: int Type::checkBoolean() 1607: { 1608: return isscalar(); 1609: } 1610: 1611: /******************************** 1612: * TRUE if when type goes out of scope, it needs a destructor applied. 1613: * Only applies to value types, not ref types. 1614: */ 1615: int Type::needsDestruction() 1616: { 1617: return FALSE; 1618: } 1619: 1620: /********************************* 1621: * Check type to see if it is based on a deprecated symbol. 1622: */ 1623: 1624: void Type::checkDeprecated(Loc loc, Scope *sc) 1625: { 1626: Dsymbol *s = toDsymbol(sc); 1627: 1628: if (s) 1629: s->checkDeprecated(loc, sc); 1630: } 1631: 1632: 1633: Expression *Type::defaultInit(Loc loc) 1634: { 1635: #if LOGDEFAULTINIT 1636: printf("Type::defaultInit() '%s'\n", toChars()); 1637: #endif 1638: return NULL; 1639: } 1640: 1641: /*************************************** 1642: * Use when we prefer the default initializer to be a literal, 1643: * rather than a global immutable variable. 1644: */ 1645: Expression *Type::defaultInitLiteral(Loc loc) 1646: { 1647: #if LOGDEFAULTINIT 1648: printf("Type::defaultInitLiteral() '%s'\n", toChars()); 1649: #endif 1650: return defaultInit(loc); 1651: } 1652: 1653: int Type::isZeroInit(Loc loc) 1654: { 1655: return 0; // assume not 1656: } 1657: 1658: int Type::isBaseOf(Type *t, int *poffset) 1659: { 1660: return 0; // assume not 1661: } 1662: 1663: /******************************** 1664: * Determine if 'this' can be implicitly converted 1665: * to type 'to'. 1666: * Returns: 1667: * MATCHnomatch, MATCHconvert, MATCHconst, MATCHexact 1668: */ 1669: 1670: MATCH Type::implicitConvTo(Type *to) 1671: { 1672: //printf("Type::implicitConvTo(this=%p, to=%p)\n", this, to); 1673: //printf("from: %s\n", toChars()); 1674: //printf("to : %s\n", to->toChars()); 1675: if (this == to) 1676: return MATCHexact; 1677: return MATCHnomatch; 1678: } 1679: 1680: Expression *Type::getProperty(Loc loc, Identifier *ident) 1681: { Expression *e; 1682: 1683: #if LOGDOTEXP 1684: printf("Type::getProperty(type = '%s', ident = '%s')\n", toChars(), ident->toChars()); 1685: #endif 1686: if (ident == Id::__sizeof) 1687: { 1688: e = new IntegerExp(loc, size(loc), Type::tsize_t); 1689: } 1690: else if (ident == Id::size) 1691: { 1692: error(loc, ".size property should be replaced with .sizeof"); 1693: e = new ErrorExp(); 1694: } 1695: else if (ident == Id::__xalignof) 1696: { 1697: e = new IntegerExp(loc, alignsize(), Type::tsize_t); 1698: } 1699: else if (ident == Id::typeinfo) 1700: { 1701: if (!global.params.useDeprecated) 1702: error(loc, ".typeinfo deprecated, use typeid(type)"); 1703: e = getTypeInfo(NULL); 1704: } 1705: else if (ident == Id::init) 1706: { 1707: if (ty == Tvoid) 1708: error(loc, "void does not have an initializer"); 1709: if (ty == Tfunction) 1710: error(loc, "function does not have an initializer"); 1711: e = defaultInitLiteral(loc); 1712: } 1713: else if (ident == Id::mangleof) 1714: { const char *s; 1715: if (!deco) 1716: { s = toChars(); 1717: error(loc, "forward reference of type %s.mangleof", s); 1718: } 1719: else 1720: s = deco; 1721: e = new StringExp(loc, (char *)s, strlen(s), 'c'); 1722: Scope sc; 1723: e = e->semantic(&sc); 1724: } 1725: else if (ident == Id::stringof) 1726: { char *s = toChars(); 1727: e = new StringExp(loc, s, strlen(s), 'c'); 1728: Scope sc; 1729: e = e->semantic(&sc); 1730: } 1731: else 1732: { 1733: Dsymbol *s = NULL; 1734: if (ty == Tstruct || ty == Tclass || ty == Tenum || ty == Ttypedef) 1735: s = toDsymbol(NULL); 1736: if (s) 1737: s = s->search_correct(ident); 1738: if (this != Type::terror) 1739: { 1740: if (s) 1741: error(loc, "no property '%s' for type '%s', did you mean '%s'?", ident->toChars(), toChars(), s->toChars()); 1742: else 1743: error(loc, "no property '%s' for type '%s'", ident->toChars(), toChars()); 1744: } 1745: e = new ErrorExp(); 1746: } 1747: return e; 1748: } 1749: 1750: Expression *Type::dotExp(Scope *sc, Expression *e, Identifier *ident) 1751: { VarDeclaration *v = NULL; 1752: 1753: #if LOGDOTEXP 1754: printf("Type::dotExp(e = '%s', ident = '%s')\n", e->toChars(), ident->toChars()); 1755: #endif 1756: if (e->op == TOKdotvar) 1757: { 1758: DotVarExp *dv = (DotVarExp *)e; 1759: v = dv->var->isVarDeclaration(); 1760: } 1761: else if (e->op == TOKvar) 1762: { 1763: VarExp *ve = (VarExp *)e; 1764: v = ve->var->isVarDeclaration(); 1765: } 1766: if (v) 1767: { 1768: if (ident == Id::offset) 1769: { 1770: if (!global.params.useDeprecated) 1771: error(e->loc, ".offset deprecated, use .offsetof"); 1772: goto Loffset; 1773: } 1774: else if (ident == Id::offsetof) 1775: { 1776: Loffset: 1777: if (v->storage_class & STCfield) 1778: { 1779: e = new IntegerExp(e->loc, v->offset, Type::tsize_t); 1780: return e; 1781: } 1782: } 1783: else if (ident == Id::init) 1784: { 1785: #if 0 1786: if (v->init) 1787: { 1788: if (v->init->isVoidInitializer()) 1789: error(e->loc, "%s.init is void", v->toChars()); 1790: else 1791: { Loc loc = e->loc; 1792: e = v->init->toExpression(); 1793: if (e->op == TOKassign || e->op == TOKconstruct || e->op == TOKblit) 1794: { 1795: e = ((AssignExp *)e)->e2; 1796: 1797: /* Take care of case where we used a 0 1798: * to initialize the struct. 1799: */ 1800: if (e->type == Type::tint32 && 1801: e->isBool(0) && 1802: v->type->toBasetype()->ty == Tstruct) 1803: { 1804: e = v->type->defaultInit(e->loc); 1805: } 1806: } 1807: e = e->optimize(WANTvalue | WANTinterpret); 1808: // if (!e->isConst()) 1809: // error(loc, ".init cannot be evaluated at compile time"); 1810: } 1811: goto Lreturn; 1812: } 1813: #endif 1814: e = defaultInitLiteral(e->loc); 1815: goto Lreturn; 1816: } 1817: } 1818: if (ident == Id::typeinfo) 1819: { 1820: if (!global.params.useDeprecated) 1821: error(e->loc, ".typeinfo deprecated, use typeid(type)"); 1822: e = getTypeInfo(sc); 1823: } 1824: else if (ident == Id::stringof) 1825: { /* Bugzilla 3796: this should demangle e->type->deco rather than 1826: * pretty-printing the type. 1827: */ 1828: char *s = e->toChars(); 1829: e = new StringExp(e->loc, s, strlen(s), 'c'); 1830: } 1831: else 1832: e = getProperty(e->loc, ident); 1833: 1834: Lreturn: 1835: e = e->semantic(sc); 1836: return e; 1837: } 1838: 1839: /*************************************** 1840: * Figures out what to do with an undefined member reference 1841: * for classes and structs. 1842: */ 1843: Expression *Type::noMember(Scope *sc, Expression *e, Identifier *ident) 1844: { 1845: assert(ty == Tstruct || ty == Tclass); 1846: AggregateDeclaration *sym = toDsymbol(sc)->isAggregateDeclaration(); 1847: assert(sym); 1848: 1849: if (ident != Id::__sizeof && 1850: ident != Id::__xalignof && 1851: ident != Id::init && 1852: ident != Id::mangleof && 1853: ident != Id::stringof && 1854: ident != Id::offsetof) 1855: { 1856: /* See if we should forward to the alias this. 1857: */ 1858: if (sym->aliasthis) 1859: { /* Rewrite e.ident as: 1860: * e.aliasthis.ident 1861: */ 1862: e = new DotIdExp(e->loc, e, sym->aliasthis->ident); 1863: e = new DotIdExp(e->loc, e, ident); 1864: return e->semantic(sc); 1865: } 1866: 1867: /* Look for overloaded opDot() to see if we should forward request 1868: * to it. 1869: */ 1870: Dsymbol *fd = search_function(sym, Id::opDot); 1871: if (fd) 1872: { /* Rewrite e.ident as: 1873: * e.opDot().ident 1874: */ 1875: e = build_overload(e->loc, sc, e, NULL, fd); 1876: e = new DotIdExp(e->loc, e, ident); 1877: return e->semantic(sc); 1878: } 1879: 1880: /* Look for overloaded opDispatch to see if we should forward request 1881: * to it. 1882: */ 1883: fd = search_function(sym, Id::opDispatch); 1884: if (fd) 1885: { 1886: /* Rewrite e.ident as: 1887: * e.opDispatch!("ident") 1888: */ 1889: TemplateDeclaration *td = fd->isTemplateDeclaration(); 1890: if (!td) 1891: { 1892: fd->error("must be a template opDispatch(string s), not a %s", fd->kind()); 1893: return new ErrorExp(); 1894: } 1895: StringExp *se = new StringExp(e->loc, ident->toChars()); 1896: Objects *tiargs = new Objects(); 1897: tiargs->push(se); 1898: e = new DotTemplateInstanceExp(e->loc, e, Id::opDispatch, tiargs); 1899: ((DotTemplateInstanceExp *)e)->ti->tempdecl = td; 1900: return e; 1901: //return e->semantic(sc); 1902: } 1903: } 1904: 1905: return Type::dotExp(sc, e, ident); 1906: } 1907: 1908: unsigned Type::memalign(unsigned salign) 1909: { 1910: return salign; 1911: } 1912: 1913: void Type::error(Loc loc, const char *format, ...) 1914: { 1915: va_list ap; 1916: va_start(ap, format); 1917: ::verror(loc, format, ap); 1918: va_end( ap ); 1919: } 1920: 1921: void Type::warning(Loc loc, const char *format, ...) 1922: { 1923: va_list ap; 1924: va_start(ap, format); 1925: ::vwarning(loc, format, ap); 1926: va_end( ap ); 1927: } 1928: 1929: Identifier *Type::getTypeInfoIdent(int internal) 1930: { 1931: // _init_10TypeInfo_%s 1932: OutBuffer buf; 1933: Identifier *id; 1934: char *name; 1935: int len; 1936: 1937: if (internal) 1938: { buf.writeByte(mangleChar[ty]); 1939: if (ty == Tarray) 1940: buf.writeByte(mangleChar[((TypeArray *)this)->next->ty]); 1941: } 1942: else 1943: toDecoBuffer(&buf); 1944: len = buf.offset; 1945: name = (char *)alloca(19 + sizeof(len) * 3 + len + 1);
warning C6255: _alloca indicates failure by raising a stack overflow exception. Consider using _malloca instead
1946: buf.writeByte(0); 1947: #if TARGET_OSX 1948: // The LINKc will prepend the _ 1949: sprintf(name, "D%dTypeInfo_%s6__initZ", 9 + len, buf.data); 1950: #else 1951: sprintf(name, "_D%dTypeInfo_%s6__initZ", 9 + len, buf.data);
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'
1952: #endif 1953: if (global.params.isWindows) 1954: name++; // C mangling will add it back in 1955: //printf("name = %s\n", name); 1956: id = Lexer::idPool(name); 1957: return id; 1958: } 1959: 1960: TypeBasic *Type::isTypeBasic() 1961: { 1962: return NULL; 1963: } 1964: 1965: 1966: void Type::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps) 1967: { 1968: //printf("Type::resolve() %s, %d\n", toChars(), ty); 1969: Type *t = semantic(loc, sc); 1970: *pt = t; 1971: *pe = NULL; 1972: *ps = NULL; 1973: } 1974: 1975: /******************************* 1976: * If one of the subtypes of this type is a TypeIdentifier, 1977: * i.e. it's an unresolved type, return that type. 1978: */ 1979: 1980: Type *Type::reliesOnTident() 1981: { 1982: return NULL; 1983: } 1984: 1985: /*************************************** 1986: * Return !=0 if the type or any of its subtypes is wild. 1987: */ 1988: 1989: int Type::hasWild() 1990: { 1991: return mod & MODwild; 1992: } 1993: 1994: /*************************************** 1995: * Return MOD bits matching argument type (targ) to wild parameter type (this). 1996: */ 1997: 1998: unsigned Type::wildMatch(Type *targ) 1999: { 2000: return 0; 2001: } 2002: 2003: /******************************** 2004: * We've mistakenly parsed this as a type. 2005: * Redo it as an Expression. 2006: * NULL if cannot. 2007: */ 2008: 2009: Expression *Type::toExpression() 2010: { 2011: return NULL; 2012: } 2013: 2014: /*************************************** 2015: * Return !=0 if type has pointers that need to 2016: * be scanned by the GC during a collection cycle. 2017: */ 2018: 2019: int Type::hasPointers() 2020: { 2021: //printf("Type::hasPointers() %s, %d\n", toChars(), ty); 2022: return FALSE; 2023: } 2024: 2025: /************************************* 2026: * If this is a type of something, return that something. 2027: */ 2028: 2029: Type *Type::nextOf() 2030: { 2031: return NULL; 2032: } 2033: 2034: /**************************************** 2035: * Return the mask that an integral type will 2036: * fit into. 2037: */ 2038: uinteger_t Type::sizemask() 2039: { uinteger_t m; 2040: 2041: switch (toBasetype()->ty) 2042: { 2043: case Tbool: m = 1; break; 2044: case Tchar: 2045: case Tint8: 2046: case Tuns8: m = 0xFF; break; 2047: case Twchar: 2048: case Tint16: 2049: case Tuns16: m = 0xFFFFUL; break; 2050: case Tdchar: 2051: case Tint32: 2052: case Tuns32: m = 0xFFFFFFFFUL; break; 2053: case Tint64: 2054: case Tuns64: m = 0xFFFFFFFFFFFFFFFFULL; break; 2055: default: 2056: assert(0); 2057: } 2058: return m; 2059: } 2060: 2061: /* ============================= TypeError =========================== */ 2062: 2063: TypeError::TypeError() 2064: : Type(Terror) 2065: { 2066: } 2067: 2068: void TypeError::toCBuffer(OutBuffer *buf, Identifier *ident, HdrGenState *hgs) 2069: { 2070: buf->writestring("_error_"); 2071: } 2072: 2073: d_uns64 TypeError::size(Loc loc) { return 1; } 2074: Expression *TypeError::getProperty(Loc loc, Identifier *ident) { return new ErrorExp(); } 2075: Expression *TypeError::dotExp(Scope *sc, Expression *e, Identifier *ident) { return new ErrorExp(); } 2076: Expression *TypeError::defaultInit(Loc loc) { return new ErrorExp(); } 2077: Expression *TypeError::defaultInitLiteral(Loc loc) { return new ErrorExp(); } 2078: 2079: /* ============================= TypeNext =========================== */ 2080: 2081: TypeNext::TypeNext(TY ty, Type *next) 2082: : Type(ty) 2083: { 2084: this->next = next; 2085: } 2086: 2087: void TypeNext::toDecoBuffer(OutBuffer *buf, int flag) 2088: { 2089: Type::toDecoBuffer(buf, flag); 2090: assert(next != this); 2091: //printf("this = %p, ty = %d, next = %p, ty = %d\n", this, this->ty, next, next->ty); 2092: next->toDecoBuffer(buf, (flag & 0x100) ? 0 : mod); 2093: } 2094: 2095: void TypeNext::checkDeprecated(Loc loc, Scope *sc) 2096: { 2097: Type::checkDeprecated(loc, sc); 2098: if (next) // next can be NULL if TypeFunction and auto return type 2099: next->checkDeprecated(loc, sc); 2100: } 2101: 2102: 2103: Type *TypeNext::reliesOnTident() 2104: { 2105: return next->reliesOnTident(); 2106: } 2107: 2108: int TypeNext::hasWild() 2109: { 2110: return mod == MODwild || next->hasWild(); 2111: } 2112: 2113: /*************************************** 2114: * Return MOD bits matching argument type (targ) to wild parameter type (this). 2115: */ 2116: 2117: unsigned TypeNext::wildMatch(Type *targ) 2118: { unsigned mod; 2119: 2120: Type *tb = targ->nextOf(); 2121: if (!tb) 2122: return 0; 2123: tb = tb->toBasetype(); 2124: if (tb->isMutable()) 2125: mod = MODmutable; 2126: else if (tb->isConst() || tb->isWild()) 2127: return MODconst; 2128: else if (tb->isImmutable()) 2129: mod = MODimmutable; 2130: else 2131: assert(0); 2132: mod |= next->wildMatch(tb); 2133: return mod; 2134: } 2135: 2136: 2137: /******************************* 2138: * For TypeFunction, nextOf() can return NULL if the function return 2139: * type is meant to be inferred, and semantic() hasn't yet ben run 2140: * on the function. After semantic(), it must no longer be NULL. 2141: */ 2142: 2143: Type *TypeNext::nextOf() 2144: { 2145: return next; 2146: } 2147: 2148: Type *TypeNext::makeConst() 2149: { 2150: //printf("TypeNext::makeConst() %p, %s\n", this, toChars()); 2151: if (cto) 2152: { assert(cto->mod == MODconst); 2153: return cto; 2154: } 2155: TypeNext *t = (TypeNext *)Type::makeConst(); 2156: if (ty != Tfunction && ty != Tdelegate && 2157: //(next->deco || next->ty == Tfunction) && 2158: !next->isImmutable() && !next->isConst()) 2159: { if (next->isShared()) 2160: t->next = next->sharedConstOf(); 2161: else 2162: t->next = next->constOf(); 2163: } 2164: if (ty == Taarray) 2165: { 2166: ((TypeAArray *)t)->impl = NULL; // lazily recompute it 2167: } 2168: //printf("TypeNext::makeConst() returns %p, %s\n", t, t->toChars()); 2169: return t; 2170: } 2171: 2172: Type *TypeNext::makeInvariant() 2173: { 2174: //printf("TypeNext::makeInvariant() %s\n", toChars()); 2175: if (ito) 2176: { assert(ito->isImmutable()); 2177: return ito; 2178: } 2179: TypeNext *t = (TypeNext *)Type::makeInvariant(); 2180: if (ty != Tfunction && ty != Tdelegate && 2181: //(next->deco || next->ty == Tfunction) && 2182: !next->isImmutable()) 2183: { t->next = next->invariantOf(); 2184: } 2185: if (ty == Taarray) 2186: { 2187: ((TypeAArray *)t)->impl = NULL; // lazily recompute it 2188: } 2189: return t; 2190: } 2191: 2192: Type *TypeNext::makeShared() 2193: { 2194: //printf("TypeNext::makeShared() %s\n", toChars()); 2195: if (sto) 2196: { assert(sto->mod == MODshared); 2197: return sto; 2198: } 2199: TypeNext *t = (TypeNext *)Type::makeShared(); 2200: if (ty != Tfunction && ty != Tdelegate && 2201: //(next->deco || next->ty == Tfunction) && 2202: !next->isImmutable() && !next->isShared()) 2203: { 2204: if (next->isConst() || next->isWild()) 2205: t->next = next->sharedConstOf(); 2206: else 2207: t->next = next->sharedOf(); 2208: } 2209: if (ty == Taarray) 2210: { 2211: ((TypeAArray *)t)->impl = NULL; // lazily recompute it 2212: } 2213: //printf("TypeNext::makeShared() returns %p, %s\n", t, t->toChars()); 2214: return t; 2215: } 2216: 2217: Type *TypeNext::makeSharedConst() 2218: { 2219: //printf("TypeNext::makeSharedConst() %s\n", toChars()); 2220: if (scto) 2221: { assert(scto->mod == (MODshared | MODconst)); 2222: return scto; 2223: } 2224: TypeNext *t = (TypeNext *)Type::makeSharedConst(); 2225: if (ty != Tfunction && ty != Tdelegate && 2226: //(next->deco || next->ty == Tfunction) && 2227: !next->isImmutable() && !next->isSharedConst()) 2228: { 2229: t->next = next->sharedConstOf(); 2230: } 2231: if (ty == Taarray) 2232: { 2233: ((TypeAArray *)t)->impl = NULL; // lazily recompute it 2234: } 2235: //printf("TypeNext::makeSharedConst() returns %p, %s\n", t, t->toChars()); 2236: return t; 2237: } 2238: 2239: Type *TypeNext::makeWild() 2240: { 2241: //printf("TypeNext::makeWild() %s\n", toChars()); 2242: if (wto) 2243: { assert(wto->mod == MODwild); 2244: return wto; 2245: } 2246: TypeNext *t = (TypeNext *)Type::makeWild(); 2247: if (ty != Tfunction && ty != Tdelegate && 2248: //(next->deco || next->ty == Tfunction) && 2249: !next->isImmutable() && !next->isConst() && !next->isWild()) 2250: { 2251: if (next->isShared()) 2252: t->next = next->sharedWildOf(); 2253: else 2254: t->next = next->wildOf(); 2255: } 2256: if (ty == Taarray) 2257: { 2258: ((TypeAArray *)t)->impl = NULL; // lazily recompute it 2259: } 2260: //printf("TypeNext::makeWild() returns %p, %s\n", t, t->toChars()); 2261: return t; 2262: } 2263: 2264: Type *TypeNext::makeSharedWild() 2265: { 2266: //printf("TypeNext::makeSharedWild() %s\n", toChars()); 2267: if (swto) 2268: { assert(swto->isSharedWild()); 2269: return swto; 2270: } 2271: TypeNext *t = (TypeNext *)Type::makeSharedWild(); 2272: if (ty != Tfunction && ty != Tdelegate && 2273: //(next->deco || next->ty == Tfunction) && 2274: !next->isImmutable() && !next->isSharedConst()) 2275: { 2276: t->next = next->sharedWildOf(); 2277: } 2278: if (ty == Taarray) 2279: { 2280: ((TypeAArray *)t)->impl = NULL; // lazily recompute it 2281: } 2282: //printf("TypeNext::makeSharedWild() returns %p, %s\n", t, t->toChars()); 2283: return t; 2284: } 2285: 2286: Type *TypeNext::makeMutable() 2287: { 2288: //printf("TypeNext::makeMutable() %p, %s\n", this, toChars()); 2289: TypeNext *t = (TypeNext *)Type::makeMutable(); 2290: if ((ty != Tfunction && ty != Tdelegate && 2291: //(next->deco || next->ty == Tfunction) && 2292: next->isWild()) || ty == Tsarray) 2293: { 2294: t->next = next->mutableOf(); 2295: } 2296: if (ty == Taarray) 2297: { 2298: ((TypeAArray *)t)->impl = NULL; // lazily recompute it 2299: } 2300: //printf("TypeNext::makeMutable() returns %p, %s\n", t, t->toChars()); 2301: return t; 2302: } 2303: 2304: MATCH TypeNext::constConv(Type *to) 2305: { MATCH m = Type::constConv(to); 2306: 2307: if (m == MATCHconst && 2308: next->constConv(((TypeNext *)to)->next) == MATCHnomatch) 2309: m = MATCHnomatch; 2310: return m; 2311: } 2312: 2313: 2314: void TypeNext::transitive() 2315: { 2316: /* Invoke transitivity of type attributes 2317: */ 2318: next = next->addMod(mod); 2319: } 2320: 2321: /* ============================= TypeBasic =========================== */ 2322: 2323: TypeBasic::TypeBasic(TY ty) 2324: : Type(ty) 2325: { const char *d; 2326: unsigned flags; 2327: 2328: #define TFLAGSintegral 1 2329: #define TFLAGSfloating 2 2330: #define TFLAGSunsigned 4 2331: #define TFLAGSreal 8 2332: #define TFLAGSimaginary 0x10 2333: #define TFLAGScomplex 0x20 2334: 2335: flags = 0; 2336: switch (ty) 2337: { 2338: case Tvoid: d = Token::toChars(TOKvoid); 2339: break; 2340: 2341: case Tint8: d = Token::toChars(TOKint8); 2342: flags |= TFLAGSintegral; 2343: break; 2344: 2345: case Tuns8: d = Token::toChars(TOKuns8); 2346: flags |= TFLAGSintegral | TFLAGSunsigned; 2347: break; 2348: 2349: case Tint16: d = Token::toChars(TOKint16); 2350: flags |= TFLAGSintegral; 2351: break; 2352: 2353: case Tuns16: d = Token::toChars(TOKuns16); 2354: flags |= TFLAGSintegral | TFLAGSunsigned; 2355: break; 2356: 2357: case Tint32: d = Token::toChars(TOKint32); 2358: flags |= TFLAGSintegral; 2359: break; 2360: 2361: case Tuns32: d = Token::toChars(TOKuns32); 2362: flags |= TFLAGSintegral | TFLAGSunsigned; 2363: break; 2364: 2365: case Tfloat32: d = Token::toChars(TOKfloat32); 2366: flags |= TFLAGSfloating | TFLAGSreal; 2367: break; 2368: 2369: case Tint64: d = Token::toChars(TOKint64); 2370: flags |= TFLAGSintegral; 2371: break; 2372: 2373: case Tuns64: d = Token::toChars(TOKuns64); 2374: flags |= TFLAGSintegral | TFLAGSunsigned; 2375: break; 2376: 2377: case Tfloat64: d = Token::toChars(TOKfloat64); 2378: flags |= TFLAGSfloating | TFLAGSreal; 2379: break; 2380: 2381: case Tfloat80: d = Token::toChars(TOKfloat80); 2382: flags |= TFLAGSfloating | TFLAGSreal; 2383: break; 2384: 2385: case Timaginary32: d = Token::toChars(TOKimaginary32); 2386: flags |= TFLAGSfloating | TFLAGSimaginary; 2387: break; 2388: 2389: case Timaginary64: d = Token::toChars(TOKimaginary64); 2390: flags |= TFLAGSfloating | TFLAGSimaginary; 2391: break; 2392: 2393: case Timaginary80: d = Token::toChars(TOKimaginary80); 2394: flags |= TFLAGSfloating | TFLAGSimaginary; 2395: break; 2396: 2397: case Tcomplex32: d = Token::toChars(TOKcomplex32); 2398: flags |= TFLAGSfloating | TFLAGScomplex; 2399: break; 2400: 2401: case Tcomplex64: d = Token::toChars(TOKcomplex64); 2402: flags |= TFLAGSfloating | TFLAGScomplex; 2403: break; 2404: 2405: case Tcomplex80: d = Token::toChars(TOKcomplex80); 2406: flags |= TFLAGSfloating | TFLAGScomplex; 2407: break; 2408: 2409: case Tbool: d = "bool"; 2410: flags |= TFLAGSintegral | TFLAGSunsigned; 2411: break; 2412: 2413: case Tascii: d = Token::toChars(TOKchar); 2414: flags |= TFLAGSintegral | TFLAGSunsigned; 2415: break; 2416: 2417: case Twchar: d = Token::toChars(TOKwchar); 2418: flags |= TFLAGSintegral | TFLAGSunsigned; 2419: break; 2420: 2421: case Tdchar: d = Token::toChars(TOKdchar); 2422: flags |= TFLAGSintegral | TFLAGSunsigned; 2423: break; 2424: 2425: default: assert(0); 2426: } 2427: this->dstring = d; 2428: this->flags = flags; 2429: merge(); 2430: } 2431: 2432: Type *TypeBasic::syntaxCopy() 2433: { 2434: // No semantic analysis done on basic types, no need to copy 2435: return this; 2436: } 2437: 2438: 2439: char *TypeBasic::toChars() 2440: { 2441: return Type::toChars(); 2442: } 2443: 2444: void TypeBasic::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod) 2445: { 2446: //printf("TypeBasic::toCBuffer2(mod = %d, this->mod = %d)\n", mod, this->mod); 2447: if (mod != this->mod) 2448: { toCBuffer3(buf, hgs, mod); 2449: return; 2450: } 2451: buf->writestring(dstring); 2452: } 2453: 2454: d_uns64 TypeBasic::size(Loc loc) 2455: { unsigned size; 2456: 2457: //printf("TypeBasic::size()\n"); 2458: switch (ty) 2459: { 2460: case Tint8: 2461: case Tuns8: size = 1; break; 2462: case Tint16: 2463: case Tuns16: size = 2; break; 2464: case Tint32: 2465: case Tuns32: 2466: case Tfloat32: 2467: case Timaginary32: 2468: size = 4; break; 2469: case Tint64: 2470: case Tuns64: 2471: case Tfloat64: 2472: case Timaginary64: 2473: size = 8; break; 2474: case Tfloat80: 2475: case Timaginary80: 2476: size = REALSIZE; break; 2477: case Tcomplex32: 2478: size = 8; break; 2479: case Tcomplex64: 2480: size = 16; break; 2481: case Tcomplex80: 2482: size = REALSIZE * 2; break; 2483: 2484: case Tvoid: 2485: //size = Type::size(); // error message 2486: size = 1; 2487: break; 2488: 2489: case Tbool: size = 1; break; 2490: case Tascii: size = 1; break; 2491: case Twchar: size = 2; break; 2492: case Tdchar: size = 4; break; 2493: 2494: default: 2495: assert(0); 2496: break; 2497: } 2498: //printf("TypeBasic::size() = %d\n", size); 2499: return size; 2500: } 2501: 2502: unsigned TypeBasic::alignsize() 2503: { unsigned sz; 2504: 2505: switch (ty) 2506: { 2507: case Tfloat80: 2508: case Timaginary80: 2509: case Tcomplex80: 2510: sz = REALALIGNSIZE; 2511: break; 2512: 2513: #if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_SOLARIS 2514: case Tint64: 2515: case Tuns64: 2516: sz = global.params.is64bit ? 8 : 4; 2517: break; 2518: 2519: case Tfloat64: 2520: case Timaginary64: 2521: sz = global.params.is64bit ? 8 : 4; 2522: break; 2523: 2524: case Tcomplex32: 2525: sz = 4; 2526: break; 2527: 2528: case Tcomplex64: 2529: sz = global.params.is64bit ? 8 : 4; 2530: break; 2531: #endif 2532: 2533: default: 2534: sz = size(0);
warning C4244: '=' : conversion from 'd_uns64' to 'unsigned int', possible loss of data
2535: break; 2536: } 2537: return sz; 2538: } 2539: 2540: 2541: Expression *TypeBasic::getProperty(Loc loc, Identifier *ident) 2542: { 2543: Expression *e; 2544: d_int64 ivalue; 2545: #ifdef IN_GCC 2546: real_t fvalue; 2547: #else 2548: d_float80 fvalue; 2549: #endif 2550: 2551: //printf("TypeBasic::getProperty('%s')\n", ident->toChars()); 2552: if (ident == Id::max) 2553: { 2554: switch (ty) 2555: { 2556: case Tint8: ivalue = 0x7F; goto Livalue; 2557: case Tuns8: ivalue = 0xFF; goto Livalue; 2558: case Tint16: ivalue = 0x7FFFUL; goto Livalue; 2559: case Tuns16: ivalue = 0xFFFFUL; goto Livalue; 2560: case Tint32: ivalue = 0x7FFFFFFFUL; goto Livalue; 2561: case Tuns32: ivalue = 0xFFFFFFFFUL; goto Livalue; 2562: case Tint64: ivalue = 0x7FFFFFFFFFFFFFFFLL; goto Livalue; 2563: case Tuns64: ivalue = 0xFFFFFFFFFFFFFFFFULL; goto Livalue; 2564: case Tbool: ivalue = 1; goto Livalue; 2565: case Tchar: ivalue = 0xFF; goto Livalue; 2566: case Twchar: ivalue = 0xFFFFUL; goto Livalue; 2567: case Tdchar: ivalue = 0x10FFFFUL; goto Livalue; 2568: 2569: case Tcomplex32: 2570: case Timaginary32: 2571: case Tfloat32: fvalue = FLT_MAX; goto Lfvalue; 2572: case Tcomplex64: 2573: case Timaginary64: 2574: case Tfloat64: fvalue = DBL_MAX; goto Lfvalue; 2575: case Tcomplex80: 2576: case Timaginary80: 2577: case Tfloat80: fvalue = Port::ldbl_max; goto Lfvalue; 2578: } 2579: } 2580: else if (ident == Id::min) 2581: { 2582: switch (ty) 2583: { 2584: case Tint8: ivalue = -128; goto Livalue; 2585: case Tuns8: ivalue = 0; goto Livalue; 2586: case Tint16: ivalue = -32768; goto Livalue; 2587: case Tuns16: ivalue = 0; goto Livalue; 2588: case Tint32: ivalue = -2147483647L - 1; goto Livalue; 2589: case Tuns32: ivalue = 0; goto Livalue; 2590: case Tint64: ivalue = (-9223372036854775807LL-1LL); goto Livalue; 2591: case Tuns64: ivalue = 0; goto Livalue; 2592: case Tbool: ivalue = 0; goto Livalue; 2593: case Tchar: ivalue = 0; goto Livalue; 2594: case Twchar: ivalue = 0; goto Livalue; 2595: case Tdchar: ivalue = 0; goto Livalue; 2596: 2597: case Tcomplex32: 2598: case Timaginary32: 2599: case Tfloat32: 2600: case Tcomplex64: 2601: case Timaginary64: 2602: case Tfloat64: 2603: case Tcomplex80: 2604: case Timaginary80: 2605: case Tfloat80: 2606: // For backwards compatibility - eventually, deprecate 2607: goto Lmin_normal; 2608: } 2609: } 2610: else if (ident == Id::min_normal) 2611: { 2612: Lmin_normal: 2613: switch (ty) 2614: { 2615: case Tcomplex32: 2616: case Timaginary32: 2617: case Tfloat32: fvalue = FLT_MIN; goto Lfvalue; 2618: case Tcomplex64: 2619: case Timaginary64: 2620: case Tfloat64: fvalue = DBL_MIN; goto Lfvalue; 2621: case Tcomplex80: 2622: case Timaginary80: 2623: case Tfloat80: fvalue = LDBL_MIN; goto Lfvalue; 2624: } 2625: } 2626: else if (ident == Id::nan) 2627: { 2628: switch (ty) 2629: { 2630: case Tcomplex32: 2631: case Tcomplex64: 2632: case Tcomplex80: 2633: case Timaginary32: 2634: case Timaginary64: 2635: case Timaginary80: 2636: case Tfloat32: 2637: case Tfloat64: 2638: case Tfloat80: 2639: { 2640: fvalue = Port::nan; 2641: goto Lfvalue; 2642: } 2643: } 2644: } 2645: else if (ident == Id::infinity) 2646: { 2647: switch (ty) 2648: { 2649: case Tcomplex32: 2650: case Tcomplex64: 2651: case Tcomplex80: 2652: case Timaginary32: 2653: case Timaginary64: 2654: case Timaginary80: 2655: case Tfloat32: 2656: case Tfloat64: 2657: case Tfloat80: 2658: fvalue = Port::infinity; 2659: goto Lfvalue; 2660: } 2661: } 2662: else if (ident == Id::dig) 2663: { 2664: switch (ty) 2665: { 2666: case Tcomplex32: 2667: case Timaginary32: 2668: case Tfloat32: ivalue = FLT_DIG; goto Lint; 2669: case Tcomplex64: 2670: case Timaginary64: 2671: case Tfloat64: ivalue = DBL_DIG; goto Lint; 2672: case Tcomplex80: 2673: case Timaginary80: 2674: case Tfloat80: ivalue = LDBL_DIG; goto Lint; 2675: } 2676: } 2677: else if (ident == Id::epsilon) 2678: { 2679: switch (ty) 2680: { 2681: case Tcomplex32: 2682: case Timaginary32: 2683: case Tfloat32: fvalue = FLT_EPSILON; goto Lfvalue; 2684: case Tcomplex64: 2685: case Timaginary64: 2686: case Tfloat64: fvalue = DBL_EPSILON; goto Lfvalue; 2687: case Tcomplex80: 2688: case Timaginary80: 2689: case Tfloat80: fvalue = LDBL_EPSILON; goto Lfvalue; 2690: } 2691: } 2692: else if (ident == Id::mant_dig) 2693: { 2694: switch (ty) 2695: { 2696: case Tcomplex32: 2697: case Timaginary32: 2698: case Tfloat32: ivalue = FLT_MANT_DIG; goto Lint; 2699: case Tcomplex64: 2700: case Timaginary64: 2701: case Tfloat64: ivalue = DBL_MANT_DIG; goto Lint; 2702: case Tcomplex80: 2703: case Timaginary80: 2704: case Tfloat80: ivalue = LDBL_MANT_DIG; goto Lint; 2705: } 2706: } 2707: else if (ident == Id::max_10_exp) 2708: { 2709: switch (ty) 2710: { 2711: case Tcomplex32: 2712: case Timaginary32: 2713: case Tfloat32: ivalue = FLT_MAX_10_EXP; goto Lint; 2714: case Tcomplex64: 2715: case Timaginary64: 2716: case Tfloat64: ivalue = DBL_MAX_10_EXP; goto Lint; 2717: case Tcomplex80: 2718: case Timaginary80: 2719: case Tfloat80: ivalue = LDBL_MAX_10_EXP; goto Lint; 2720: } 2721: } 2722: else if (ident == Id::max_exp) 2723: { 2724: switch (ty) 2725: { 2726: case Tcomplex32: 2727: case Timaginary32: 2728: case Tfloat32: ivalue = FLT_MAX_EXP; goto Lint; 2729: case Tcomplex64: 2730: case Timaginary64: 2731: case Tfloat64: ivalue = DBL_MAX_EXP; goto Lint; 2732: case Tcomplex80: 2733: case Timaginary80: 2734: case Tfloat80: ivalue = LDBL_MAX_EXP; goto Lint; 2735: } 2736: } 2737: else if (ident == Id::min_10_exp) 2738: { 2739: switch (ty) 2740: { 2741: case Tcomplex32: 2742: case Timaginary32: 2743: case Tfloat32: ivalue = FLT_MIN_10_EXP; goto Lint; 2744: case Tcomplex64: 2745: case Timaginary64: 2746: case Tfloat64: ivalue = DBL_MIN_10_EXP; goto Lint; 2747: case Tcomplex80: 2748: case Timaginary80: 2749: case Tfloat80: ivalue = LDBL_MIN_10_EXP; goto Lint; 2750: } 2751: } 2752: else if (ident == Id::min_exp) 2753: { 2754: switch (ty) 2755: { 2756: case Tcomplex32: 2757: case Timaginary32: 2758: case Tfloat32: ivalue = FLT_MIN_EXP; goto Lint; 2759: case Tcomplex64: 2760: case Timaginary64: 2761: case Tfloat64: ivalue = DBL_MIN_EXP; goto Lint; 2762: case Tcomplex80: 2763: case Timaginary80: 2764: case Tfloat80: ivalue = LDBL_MIN_EXP; goto Lint; 2765: } 2766: } 2767: 2768: Ldefault:
warning C4102: 'Ldefault' : unreferenced label
2769: return Type::getProperty(loc, ident); 2770: 2771: Livalue: 2772: e = new IntegerExp(loc, ivalue, this); 2773: return e; 2774: 2775: Lfvalue: 2776: if (isreal() || isimaginary()) 2777: e = new RealExp(loc, fvalue, this); 2778: else 2779: { 2780: complex_t cvalue; 2781: 2782: #if __DMC__ 2783: //((real_t *)&cvalue)[0] = fvalue; 2784: //((real_t *)&cvalue)[1] = fvalue; 2785: cvalue = fvalue + fvalue * I; 2786: #else 2787: cvalue.re = fvalue; 2788: cvalue.im = fvalue; 2789: #endif 2790: //for (int i = 0; i < 20; i++) 2791: // printf("%02x ", ((unsigned char *)&cvalue)[i]); 2792: //printf("\n"); 2793: e = new ComplexExp(loc, cvalue, this); 2794: } 2795: return e; 2796: 2797: Lint: 2798: e = new IntegerExp(loc, ivalue, Type::tint32); 2799: return e; 2800: } 2801: 2802: Expression *TypeBasic::dotExp(Scope *sc, Expression *e, Identifier *ident) 2803: { 2804: #if LOGDOTEXP 2805: printf("TypeBasic::dotExp(e = '%s', ident = '%s')\n", e->toChars(), ident->toChars()); 2806: #endif 2807: Type *t; 2808: 2809: if (ident == Id::re) 2810: { 2811: switch (ty) 2812: { 2813: case Tcomplex32: t = tfloat32; goto L1; 2814: case Tcomplex64: t = tfloat64; goto L1; 2815: case Tcomplex80: t = tfloat80; goto L1; 2816: L1: 2817: e = e->castTo(sc, t); 2818: break; 2819: 2820: case Tfloat32: 2821: case Tfloat64: 2822: case Tfloat80: 2823: break; 2824: 2825: case Timaginary32: t = tfloat32; goto L2; 2826: case Timaginary64: t = tfloat64; goto L2; 2827: case Timaginary80: t = tfloat80; goto L2; 2828: L2: 2829: e = new RealExp(0, 0.0, t); 2830: break; 2831: 2832: default: 2833: e = Type::getProperty(e->loc, ident); 2834: break; 2835: } 2836: } 2837: else if (ident == Id::im) 2838: { Type *t2; 2839: 2840: switch (ty) 2841: { 2842: case Tcomplex32: t = timaginary32; t2 = tfloat32; goto L3; 2843: case Tcomplex64: t = timaginary64; t2 = tfloat64; goto L3; 2844: case Tcomplex80: t = timaginary80; t2 = tfloat80; goto L3; 2845: L3: 2846: e = e->castTo(sc, t); 2847: e->type = t2; 2848: break; 2849: 2850: case Timaginary32: t = tfloat32; goto L4; 2851: case Timaginary64: t = tfloat64; goto L4; 2852: case Timaginary80: t = tfloat80; goto L4; 2853: L4: 2854: e = e->copy(); 2855: e->type = t; 2856: break; 2857: 2858: case Tfloat32: 2859: case Tfloat64: 2860: case Tfloat80: 2861: e = new RealExp(0, 0.0, this); 2862: break; 2863: 2864: default: 2865: e = Type::getProperty(e->loc, ident); 2866: break; 2867: } 2868: } 2869: else 2870: { 2871: return Type::dotExp(sc, e, ident); 2872: } 2873: e = e->semantic(sc); 2874: return e; 2875: } 2876: 2877: Expression *TypeBasic::defaultInit(Loc loc) 2878: { dinteger_t value = 0; 2879: 2880: #if SNAN_DEFAULT_INIT 2881: /* 2882: * Use a payload which is different from the machine NaN, 2883: * so that uninitialised variables can be 2884: * detected even if exceptions are disabled. 2885: */ 2886: union 2887: { unsigned short us[8]; 2888: long double ld; 2889: } snan = {{ 0, 0, 0, 0xA000, 0x7FFF }}; 2890: /* 2891: * Although long doubles are 10 bytes long, some 2892: * C ABIs pad them out to 12 or even 16 bytes, so 2893: * leave enough space in the snan array. 2894: */ 2895: assert(REALSIZE <= sizeof(snan)); 2896: d_float80 fvalue = snan.ld; 2897: #endif 2898: 2899: #if LOGDEFAULTINIT 2900: printf("TypeBasic::defaultInit() '%s'\n", toChars()); 2901: #endif 2902: switch (ty) 2903: { 2904: case Tchar: 2905: value = 0xFF; 2906: break; 2907: 2908: case Twchar: 2909: case Tdchar: 2910: value = 0xFFFF; 2911: break; 2912: 2913: case Timaginary32: 2914: case Timaginary64: 2915: case Timaginary80: 2916: case Tfloat32: 2917: case Tfloat64: 2918: case Tfloat80: 2919: #if SNAN_DEFAULT_INIT 2920: return new RealExp(loc, fvalue, this); 2921: #else 2922: return getProperty(loc, Id::nan); 2923: #endif 2924: 2925: case Tcomplex32: 2926: case Tcomplex64: 2927: case Tcomplex80: 2928: #if SNAN_DEFAULT_INIT 2929: { // Can't use fvalue + I*fvalue (the im part becomes a quiet NaN). 2930: complex_t cvalue; 2931: ((real_t *)&cvalue)[0] = fvalue; 2932: ((real_t *)&cvalue)[1] = fvalue; 2933: return new ComplexExp(loc, cvalue, this); 2934: } 2935: #else 2936: return getProperty(loc, Id::nan); 2937: #endif 2938: 2939: case Tvoid: 2940: error(loc, "void does not have a default initializer"); 2941: return new ErrorExp(); 2942: } 2943: return new IntegerExp(loc, value, this); 2944: } 2945: 2946: int TypeBasic::isZeroInit(Loc loc) 2947: { 2948: switch (ty) 2949: { 2950: case Tchar: 2951: case Twchar: 2952: case Tdchar: 2953: case Timaginary32: 2954: case Timaginary64: 2955: case Timaginary80: 2956: case Tfloat32: 2957: case Tfloat64: 2958: case Tfloat80: 2959: case Tcomplex32: 2960: case Tcomplex64: 2961: case Tcomplex80: 2962: return 0; // no 2963: } 2964: return 1; // yes 2965: } 2966: 2967: int TypeBasic::isintegral() 2968: { 2969: //printf("TypeBasic::isintegral('%s') x%x\n", toChars(), flags); 2970: return flags & TFLAGSintegral; 2971: } 2972: 2973: int TypeBasic::isfloating() 2974: { 2975: return flags & TFLAGSfloating; 2976: } 2977: 2978: int TypeBasic::isreal() 2979: { 2980: return flags & TFLAGSreal; 2981: } 2982: 2983: int TypeBasic::isimaginary() 2984: { 2985: return flags & TFLAGSimaginary; 2986: } 2987: 2988: int TypeBasic::iscomplex() 2989: { 2990: return flags & TFLAGScomplex; 2991: } 2992: 2993: int TypeBasic::isunsigned() 2994: { 2995: return flags & TFLAGSunsigned; 2996: } 2997: 2998: int TypeBasic::isscalar() 2999: { 3000: return flags & (TFLAGSintegral | TFLAGSfloating); 3001: } 3002: 3003: MATCH TypeBasic::implicitConvTo(Type *to) 3004: { 3005: //printf("TypeBasic::implicitConvTo(%s) from %s\n", to->toChars(), toChars()); 3006: if (this == to) 3007: return MATCHexact; 3008: 3009: #if DMDV2 3010: if (ty == to->ty) 3011: { 3012: return (mod == to->mod) ? MATCHexact : MATCHconst; 3013: } 3014: #endif 3015: 3016: if (ty == Tvoid || to->ty == Tvoid) 3017: return MATCHnomatch; 3018: if (to->ty == Tbool) 3019: return MATCHnomatch; 3020: if (!to->isTypeBasic()) 3021: return MATCHnomatch; 3022: 3023: TypeBasic *tob = (TypeBasic *)to; 3024: if (flags & TFLAGSintegral) 3025: { 3026: // Disallow implicit conversion of integers to imaginary or complex 3027: if (tob->flags & (TFLAGSimaginary | TFLAGScomplex)) 3028: return MATCHnomatch; 3029: 3030: #if DMDV2 3031: // If converting from integral to integral 3032: if (1 && tob->flags & TFLAGSintegral) 3033: { d_uns64 sz = size(0); 3034: d_uns64 tosz = tob->size(0); 3035: 3036: /* Can't convert to smaller size 3037: */ 3038: if (sz > tosz) 3039: return MATCHnomatch; 3040: 3041: /* Can't change sign if same size 3042: */ 3043: /*if (sz == tosz && (flags ^ tob->flags) & TFLAGSunsigned) 3044: return MATCHnomatch;*/ 3045: } 3046: #endif 3047: } 3048: else if (flags & TFLAGSfloating) 3049: { 3050: // Disallow implicit conversion of floating point to integer 3051: if (tob->flags & TFLAGSintegral) 3052: return MATCHnomatch; 3053: 3054: assert(tob->flags & TFLAGSfloating); 3055: 3056: // Disallow implicit conversion from complex to non-complex 3057: if (flags & TFLAGScomplex && !(tob->flags & TFLAGScomplex)) 3058: return MATCHnomatch; 3059: 3060: // Disallow implicit conversion of real or imaginary to complex 3061: if (flags & (TFLAGSreal | TFLAGSimaginary) && 3062: tob->flags & TFLAGScomplex) 3063: return MATCHnomatch; 3064: 3065: // Disallow implicit conversion to-from real and imaginary 3066: if ((flags & (TFLAGSreal | TFLAGSimaginary)) != 3067: (tob->flags & (TFLAGSreal | TFLAGSimaginary))) 3068: return MATCHnomatch; 3069: } 3070: return MATCHconvert; 3071: } 3072: 3073: TypeBasic *TypeBasic::isTypeBasic() 3074: { 3075: return (TypeBasic *)this; 3076: } 3077: 3078: /***************************** TypeArray *****************************/ 3079: 3080: TypeArray::TypeArray(TY ty, Type *next) 3081: : TypeNext(ty, next) 3082: { 3083: } 3084: 3085: Expression *TypeArray::dotExp(Scope *sc, Expression *e, Identifier *ident) 3086: { 3087: Type *n = this->next->toBasetype(); // uncover any typedef's 3088: 3089: #if LOGDOTEXP 3090: printf("TypeArray::dotExp(e = '%s', ident = '%s')\n", e->toChars(), ident->toChars()); 3091: #endif 3092: if (ident == Id::reverse && (n->ty == Tchar || n->ty == Twchar)) 3093: { 3094: Expression *ec; 3095: FuncDeclaration *fd; 3096: Expressions *arguments; 3097: const char *nm; 3098: static const char *name[2] = { "_adReverseChar", "_adReverseWchar" }; 3099: 3100: nm = name[n->ty == Twchar]; 3101: fd = FuncDeclaration::genCfunc(Type::tindex, nm); 3102: ec = new VarExp(0, fd); 3103: e = e->castTo(sc, n->arrayOf()); // convert to dynamic array 3104: arguments = new Expressions(); 3105: arguments->push(e); 3106: e = new CallExp(e->loc, ec, arguments); 3107: e->type = next->arrayOf(); 3108: } 3109: else if (ident == Id::sort && (n->ty == Tchar || n->ty == Twchar)) 3110: { 3111: Expression *ec; 3112: FuncDeclaration *fd; 3113: Expressions *arguments; 3114: const char *nm; 3115: static const char *name[2] = { "_adSortChar", "_adSortWchar" }; 3116: 3117: nm = name[n->ty == Twchar]; 3118: fd = FuncDeclaration::genCfunc(Type::tindex, nm); 3119: ec = new VarExp(0, fd); 3120: e = e->castTo(sc, n->arrayOf()); // convert to dynamic array 3121: arguments = new Expressions(); 3122: arguments->push(e); 3123: e = new CallExp(e->loc, ec, arguments); 3124: e->type = next->arrayOf(); 3125: } 3126: else if (ident == Id::reverse || ident == Id::dup || ident == Id::idup) 3127: { 3128: Expression *ec; 3129: FuncDeclaration *fd; 3130: Expressions *arguments; 3131: int size = next->size(e->loc);
warning C4244: 'initializing' : conversion from 'd_uns64' to 'int', possible loss of data
3132: int dup; 3133: 3134: assert(size); 3135: dup = (ident == Id::dup || ident == Id::idup); 3136: fd = FuncDeclaration::genCfunc(Type::tindex, dup ? Id::adDup : Id::adReverse); 3137: ec = new VarExp(0, fd);
warning C6211: Leaking memory 'ec' due to an exception. Consider using a local catch block to clean up memory: Lines: 3087, 3092, 3109, 3126, 3128, 3129, 3130, 3131, 3132, 3134, 3135, 3136, 3137, 3138, 3139
3138: e = e->castTo(sc, n->arrayOf()); // convert to dynamic array 3139: arguments = new Expressions();
warning C6211: Leaking memory 'arguments' due to an exception. Consider using a local catch block to clean up memory: Lines: 3087, 3092, 3109, 3126, 3128, 3129, 3130, 3131, 3132, 3134, 3135, 3136, 3137, 3138, 3139, 3140, 3142, 3143, 3144
3140: if (dup) 3141: arguments->push(getTypeInfo(sc)); 3142: arguments->push(e); 3143: if (!dup) 3144: arguments->push(new IntegerExp(0, size, Type::tsize_t)); 3145: e = new CallExp(e->loc, ec, arguments); 3146: if (ident == Id::idup) 3147: { Type *einv = next->invariantOf(); 3148: if (next->implicitConvTo(einv) < MATCHconst) 3149: error(e->loc, "cannot implicitly convert element type %s to immutable", next->toChars()); 3150: e->type = einv->arrayOf(); 3151: } 3152: else 3153: e->type = next->mutableOf()->arrayOf(); 3154: } 3155: else if (ident == Id::sort) 3156: { 3157: Expression *ec; 3158: FuncDeclaration *fd; 3159: Expressions *arguments; 3160: 3161: fd = FuncDeclaration::genCfunc(tint32->arrayOf(), "_adSort"); 3162: ec = new VarExp(0, fd); 3163: e = e->castTo(sc, n->arrayOf()); // convert to dynamic array 3164: arguments = new Expressions(); 3165: arguments->push(e); 3166: arguments->push(n->ty == Tsarray 3167: ? n->getTypeInfo(sc) // don't convert to dynamic array 3168: : n->getInternalTypeInfo(sc)); 3169: e = new CallExp(e->loc, ec, arguments); 3170: e->type = next->arrayOf(); 3171: } 3172: else 3173: { 3174: e = Type::dotExp(sc, e, ident); 3175: } 3176: e = e->semantic(sc); 3177: return e; 3178: } 3179: 3180: 3181: /***************************** TypeSArray *****************************/ 3182: 3183: TypeSArray::TypeSArray(Type *t, Expression *dim) 3184: : TypeArray(Tsarray, t) 3185: { 3186: //printf("TypeSArray(%s)\n", dim->toChars()); 3187: this->dim = dim; 3188: } 3189: 3190: Type *TypeSArray::syntaxCopy() 3191: { 3192: Type *t = next->syntaxCopy(); 3193: Expression *e = dim->syntaxCopy(); 3194: t = new TypeSArray(t, e); 3195: t->mod = mod; 3196: return t; 3197: } 3198: 3199: d_uns64 TypeSArray::size(Loc loc) 3200: { dinteger_t sz; 3201: 3202: if (!dim) 3203: return Type::size(loc); 3204: sz = dim->toInteger(); 3205: 3206: { dinteger_t n, n2; 3207: 3208: n = next->size(); 3209: n2 = n * sz; 3210: if (n && (n2 / n) != sz) 3211: goto Loverflow; 3212: sz = n2; 3213: } 3214: return sz; 3215: 3216: Loverflow: 3217: error(loc, "index %jd overflow for static array", sz); 3218: return 1; 3219: } 3220: 3221: unsigned TypeSArray::alignsize() 3222: { 3223: return next->alignsize(); 3224: } 3225: 3226: /************************** 3227: * This evaluates exp while setting length to be the number 3228: * of elements in the tuple t. 3229: */ 3230: Expression *semanticLength(Scope *sc, Type *t, Expression *exp) 3231: { 3232: if (t->ty == Ttuple) 3233: { ScopeDsymbol *sym = new ArrayScopeSymbol(sc, (TypeTuple *)t); 3234: sym->parent = sc->scopesym; 3235: sc = sc->push(sym); 3236: 3237: exp = exp->semantic(sc); 3238: 3239: sc->pop(); 3240: } 3241: else 3242: exp = exp->semantic(sc); 3243: return exp; 3244: } 3245: 3246: Expression *semanticLength(Scope *sc, TupleDeclaration *s, Expression *exp) 3247: { 3248: ScopeDsymbol *sym = new ArrayScopeSymbol(sc, s); 3249: sym->parent = sc->scopesym; 3250: sc = sc->push(sym); 3251: 3252: exp = exp->semantic(sc); 3253: 3254: sc->pop(); 3255: return exp; 3256: } 3257: 3258: void TypeSArray::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps) 3259: { 3260: //printf("TypeSArray::resolve() %s\n", toChars()); 3261: next->resolve(loc, sc, pe, pt, ps); 3262: //printf("s = %p, e = %p, t = %p\n", *ps, *pe, *pt); 3263: if (*pe) 3264: { // It's really an index expression 3265: Expression *e = new IndexExp(loc, *pe, dim); 3266: *pe = e; 3267: } 3268: else if (*ps) 3269: { Dsymbol *s = *ps; 3270: TupleDeclaration *td = s->isTupleDeclaration(); 3271: if (td) 3272: { 3273: ScopeDsymbol *sym = new ArrayScopeSymbol(sc, td); 3274: sym->parent = sc->scopesym; 3275: sc = sc->push(sym); 3276: 3277: dim = dim->semantic(sc); 3278: dim = dim->optimize(WANTvalue | WANTinterpret); 3279: uinteger_t d = dim->toUInteger(); 3280: 3281: sc = sc->pop(); 3282: 3283: if (d >= td->objects->dim) 3284: { error(loc, "tuple index %ju exceeds length %u", d, td->objects->dim); 3285: goto Ldefault; 3286: } 3287: Object *o = td->objects->tdata()[(size_t)d]; 3288: if (o->dyncast() == DYNCAST_DSYMBOL) 3289: { 3290: *ps = (Dsymbol *)o; 3291: return; 3292: } 3293: if (o->dyncast() == DYNCAST_EXPRESSION) 3294: { 3295: *ps = NULL; 3296: *pe = (Expression *)o; 3297: return; 3298: } 3299: 3300: /* Create a new TupleDeclaration which 3301: * is a slice [d..d+1] out of the old one. 3302: * Do it this way because TemplateInstance::semanticTiargs() 3303: * can handle unresolved Objects this way. 3304: */ 3305: Objects *objects = new Objects; 3306: objects->setDim(1); 3307: objects->tdata()[0] = o; 3308: 3309: TupleDeclaration *tds = new TupleDeclaration(loc, td->ident, objects); 3310: *ps = tds; 3311: } 3312: else 3313: goto Ldefault; 3314: } 3315: else 3316: { 3317: Ldefault: 3318: Type::resolve(loc, sc, pe, pt, ps); 3319: } 3320: } 3321: 3322: Type *TypeSArray::semantic(Loc loc, Scope *sc) 3323: { 3324: //printf("TypeSArray::semantic() %s\n", toChars()); 3325: 3326: Type *t; 3327: Expression *e; 3328: Dsymbol *s; 3329: next->resolve(loc, sc, &e, &t, &s); 3330: if (dim && s && s->isTupleDeclaration()) 3331: { TupleDeclaration *sd = s->isTupleDeclaration(); 3332: 3333: dim = semanticLength(sc, sd, dim); 3334: dim = dim->optimize(WANTvalue | WANTinterpret); 3335: uinteger_t d = dim->toUInteger(); 3336: 3337: if (d >= sd->objects->dim) 3338: { error(loc, "tuple index %ju exceeds %u", d, sd->objects->dim); 3339: return Type::terror; 3340: } 3341: Object *o = sd->objects->tdata()[(size_t)d]; 3342: if (o->dyncast() != DYNCAST_TYPE) 3343: { error(loc, "%s is not a type", toChars()); 3344: return Type::terror; 3345: } 3346: t = (Type *)o; 3347: return t; 3348: } 3349: 3350: next = next->semantic(loc,sc); 3351: transitive(); 3352: 3353: Type *tbn = next->toBasetype(); 3354: 3355: if (dim) 3356: { dinteger_t n, n2; 3357: 3358: dim = semanticLength(sc, tbn, dim); 3359: 3360: dim = dim->optimize(WANTvalue); 3361: if (sc && sc->parameterSpecialization && dim->op == TOKvar && 3362: ((VarExp *)dim)->var->storage_class & STCtemplateparameter) 3363: { 3364: /* It could be a template parameter N which has no value yet: 3365: * template Foo(T : T[N], size_t N); 3366: */ 3367: return this; 3368: } 3369: dim = dim->optimize(WANTvalue | WANTinterpret); 3370: dinteger_t d1 = dim->toInteger(); 3371: dim = dim->implicitCastTo(sc, tsize_t); 3372: dim = dim->optimize(WANTvalue); 3373: dinteger_t d2 = dim->toInteger(); 3374: 3375: if (dim->op == TOKerror) 3376: goto Lerror; 3377: 3378: if (d1 != d2) 3379: goto Loverflow; 3380: 3381: if (tbn->isintegral() || 3382: tbn->isfloating() || 3383: tbn->ty == Tpointer || 3384: tbn->ty == Tarray || 3385: tbn->ty == Tsarray || 3386: tbn->ty == Taarray || 3387: tbn->ty == Tclass) 3388: { 3389: /* Only do this for types that don't need to have semantic() 3390: * run on them for the size, since they may be forward referenced. 3391: */ 3392: n = tbn->size(loc); 3393: n2 = n * d2; 3394: if ((int)n2 < 0) 3395: goto Loverflow; 3396: if (n2 >= 0x1000000) // put a 'reasonable' limit on it 3397: goto Loverflow; 3398: if (n && n2 / n != d2) 3399: { 3400: Loverflow: 3401: error(loc, "index %jd overflow for static array", d1); 3402: goto Lerror; 3403: } 3404: } 3405: } 3406: switch (tbn->ty) 3407: { 3408: case Ttuple: 3409: { // Index the tuple to get the type 3410: assert(dim); 3411: TypeTuple *tt = (TypeTuple *)tbn; 3412: uinteger_t d = dim->toUInteger(); 3413: 3414: if (d >= tt->arguments->dim) 3415: { error(loc, "tuple index %ju exceeds %u", d, tt->arguments->dim); 3416: goto Lerror; 3417: } 3418: Parameter *arg = tt->arguments->tdata()[(size_t)d]; 3419: return arg->type; 3420: } 3421: case Tstruct: 3422: { TypeStruct *ts = (TypeStruct *)tbn; 3423: if (0 && ts->sym->isnested) 3424: { error(loc, "cannot have static array of inner struct %s", ts->toChars()); 3425: goto Lerror; 3426: } 3427: break; 3428: } 3429: case Tfunction: 3430: case Tnone: 3431: error(loc, "can't have array of %s", tbn->toChars()); 3432: goto Lerror; 3433: } 3434: if (tbn->isscope()) 3435: { error(loc, "cannot have array of scope %s", tbn->toChars()); 3436: goto Lerror; 3437: } 3438: 3439: /* Ensure things like const(immutable(T)[3]) become immutable(T[3]) 3440: * and const(T)[3] become const(T[3]) 3441: */ 3442: t = addMod(next->mod); 3443: 3444: return t->merge(); 3445: 3446: Lerror: 3447: return Type::terror; 3448: } 3449: 3450: void TypeSArray::toDecoBuffer(OutBuffer *buf, int flag) 3451: { 3452: Type::toDecoBuffer(buf, flag); 3453: if (dim) 3454: buf->printf("%ju", dim->toInteger()); 3455: if (next) 3456: /* Note that static arrays are value types, so 3457: * for a parameter, propagate the 0x100 to the next 3458: * level, since for T[4][3], any const should apply to the T, 3459: * not the [4]. 3460: */ 3461: next->toDecoBuffer(buf, (flag & 0x100) ? flag : mod); 3462: } 3463: 3464: void TypeSArray::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod) 3465: { 3466: if (mod != this->mod) 3467: { toCBuffer3(buf, hgs, mod); 3468: return; 3469: } 3470: next->toCBuffer2(buf, hgs, this->mod); 3471: buf->printf("[%s]", dim->toChars()); 3472: } 3473: 3474: Expression *TypeSArray::dotExp(Scope *sc, Expression *e, Identifier *ident) 3475: { 3476: #if LOGDOTEXP 3477: printf("TypeSArray::dotExp(e = '%s', ident = '%s')\n", e->toChars(), ident->toChars()); 3478: #endif 3479: if (ident == Id::length) 3480: { 3481: e = dim; 3482: } 3483: else if (ident == Id::ptr) 3484: { 3485: e = e->castTo(sc, next->pointerTo()); 3486: } 3487: else 3488: { 3489: e = TypeArray::dotExp(sc, e, ident); 3490: } 3491: e = e->semantic(sc); 3492: return e; 3493: } 3494: 3495: int TypeSArray::isString() 3496: { 3497: TY nty = next->toBasetype()->ty; 3498: return nty == Tchar || nty == Twchar || nty == Tdchar; 3499: } 3500: 3501: unsigned TypeSArray::memalign(unsigned salign) 3502: { 3503: return next->memalign(salign); 3504: } 3505: 3506: MATCH TypeSArray::constConv(Type *to) 3507: { 3508: if (to->ty == Tsarray) 3509: { 3510: TypeSArray *tsa = (TypeSArray *)to; 3511: if (!dim->equals(tsa->dim)) 3512: return MATCHnomatch; 3513: } 3514: return TypeNext::constConv(to); 3515: } 3516: 3517: MATCH TypeSArray::implicitConvTo(Type *to) 3518: { 3519: //printf("TypeSArray::implicitConvTo(to = %s) this = %s\n", to->toChars(), toChars()); 3520: 3521: // Allow implicit conversion of static array to pointer or dynamic array 3522: if (IMPLICIT_ARRAY_TO_PTR && to->ty == Tpointer) 3523: { 3524: TypePointer *tp = (TypePointer *)to; 3525: 3526: if (!MODimplicitConv(next->mod, tp->next->mod)) 3527: return MATCHnomatch; 3528: 3529: if (tp->next->ty == Tvoid || next->constConv(tp->next) != MATCHnomatch) 3530: { 3531: return MATCHconvert; 3532: } 3533: return MATCHnomatch; 3534: } 3535: if (to->ty == Tarray) 3536: { int offset = 0; 3537: TypeDArray *ta = (TypeDArray *)to; 3538: 3539: if (!MODimplicitConv(next->mod, ta->next->mod)) 3540: return MATCHnomatch; 3541: 3542: if (next->equals(ta->next) || 3543: // next->implicitConvTo(ta->next) >= MATCHconst || 3544: next->constConv(ta->next) != MATCHnomatch || 3545: (ta->next->isBaseOf(next, &offset) && offset == 0) || 3546: ta->next->ty == Tvoid) 3547: return MATCHconvert; 3548: return MATCHnomatch; 3549: } 3550: if (to->ty == Tsarray) 3551: { 3552: if (this == to) 3553: return MATCHexact; 3554: 3555: TypeSArray *tsa = (TypeSArray *)to; 3556: 3557: if (dim->equals(tsa->dim)) 3558: { 3559: /* Since static arrays are value types, allow 3560: * conversions from const elements to non-const 3561: * ones, just like we allow conversion from const int 3562: * to int. 3563: */ 3564: MATCH m = next->implicitConvTo(tsa->next); 3565: if (m >= MATCHconst) 3566: { 3567: if (mod != to->mod) 3568: m = MATCHconst; 3569: return m; 3570: } 3571: } 3572: } 3573: return MATCHnomatch; 3574: } 3575: 3576: Expression *TypeSArray::defaultInit(Loc loc) 3577: { 3578: #if LOGDEFAULTINIT 3579: printf("TypeSArray::defaultInit() '%s'\n", toChars()); 3580: #endif 3581: return next->defaultInit(loc); 3582: } 3583: 3584: int TypeSArray::isZeroInit(Loc loc) 3585: { 3586: return next->isZeroInit(loc); 3587: } 3588: 3589: int TypeSArray::needsDestruction() 3590: { 3591: return next->needsDestruction(); 3592: } 3593: 3594: Expression *TypeSArray::defaultInitLiteral(Loc loc) 3595: { 3596: #if LOGDEFAULTINIT 3597: printf("TypeSArray::defaultInitLiteral() '%s'\n", toChars()); 3598: #endif 3599: size_t d = dim->toInteger();
warning C4244: 'initializing' : conversion from 'dinteger_t' to 'size_t', possible loss of data
3600: Expression *elementinit = next->defaultInitLiteral(loc); 3601: Expressions *elements = new Expressions(); 3602: elements->setDim(d); 3603: for (size_t i = 0; i < d; i++) 3604: elements->tdata()[i] = elementinit; 3605: ArrayLiteralExp *ae = new ArrayLiteralExp(0, elements); 3606: ae->type = this; 3607: return ae; 3608: } 3609: 3610: Expression *TypeSArray::toExpression() 3611: { 3612: Expression *e = next->toExpression(); 3613: if (e) 3614: { Expressions *arguments = new Expressions(); 3615: arguments->push(dim); 3616: e = new ArrayExp(dim->loc, e, arguments); 3617: } 3618: return e; 3619: } 3620: 3621: int TypeSArray::hasPointers() 3622: { 3623: /* Don't want to do this, because: 3624: * struct S { T* array[0]; } 3625: * may be a variable length struct. 3626: */ 3627: //if (dim->toInteger() == 0) 3628: //return FALSE; 3629: 3630: if (next->ty == Tvoid) 3631: // Arrays of void contain arbitrary data, which may include pointers 3632: return TRUE; 3633: else 3634: return next->hasPointers(); 3635: } 3636: 3637: /***************************** TypeDArray *****************************/ 3638: 3639: TypeDArray::TypeDArray(Type *t) 3640: : TypeArray(Tarray, t) 3641: { 3642: //printf("TypeDArray(t = %p)\n", t); 3643: } 3644: 3645: Type *TypeDArray::syntaxCopy() 3646: { 3647: Type *t = next->syntaxCopy(); 3648: if (t == next) 3649: t = this; 3650: else 3651: { t = new TypeDArray(t); 3652: t->mod = mod; 3653: } 3654: return t; 3655: } 3656: 3657: d_uns64 TypeDArray::size(Loc loc) 3658: { 3659: //printf("TypeDArray::size()\n"); 3660: return PTRSIZE * 2; 3661: } 3662: 3663: unsigned TypeDArray::alignsize() 3664: { 3665: // A DArray consists of two ptr-sized values, so align it on pointer size 3666: // boundary 3667: return PTRSIZE; 3668: } 3669: 3670: Type *TypeDArray::semantic(Loc loc, Scope *sc) 3671: { Type *tn = next; 3672: 3673: tn = next->semantic(loc,sc); 3674: Type *tbn = tn->toBasetype(); 3675: switch (tbn->ty) 3676: { 3677: case Tfunction: 3678: case Tnone: 3679: case Ttuple: 3680: error(loc, "can't have array of %s", tbn->toChars()); 3681: tn = next = tint32; 3682: break; 3683: case Tstruct: 3684: { TypeStruct *ts = (TypeStruct *)tbn; 3685: if (0 && ts->sym->isnested) 3686: error(loc, "cannot have dynamic array of inner struct %s", ts->toChars()); 3687: break; 3688: } 3689: } 3690: if (tn->isscope()) 3691: error(loc, "cannot have array of scope %s", tn->toChars()); 3692: 3693: next = tn; 3694: transitive(); 3695: return merge(); 3696: } 3697: 3698: void TypeDArray::toDecoBuffer(OutBuffer *buf, int flag) 3699: { 3700: Type::toDecoBuffer(buf, flag); 3701: if (next) 3702: next->toDecoBuffer(buf, (flag & 0x100) ? 0 : mod); 3703: } 3704: 3705: void TypeDArray::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod) 3706: { 3707: if (mod != this->mod) 3708: { toCBuffer3(buf, hgs, mod); 3709: return; 3710: } 3711: if (equals(tstring)) 3712: buf->writestring("string"); 3713: else 3714: { next->toCBuffer2(buf, hgs, this->mod); 3715: buf->writestring("[]"); 3716: } 3717: } 3718: 3719: Expression *TypeDArray::dotExp(Scope *sc, Expression *e, Identifier *ident) 3720: { 3721: #if LOGDOTEXP 3722: printf("TypeDArray::dotExp(e = '%s', ident = '%s')\n", e->toChars(), ident->toChars()); 3723: #endif 3724: if (ident == Id::length) 3725: { 3726: if (e->op == TOKstring) 3727: { StringExp *se = (StringExp *)e; 3728: 3729: return new IntegerExp(se->loc, se->len, Type::tindex); 3730: } 3731: e = new ArrayLengthExp(e->loc, e); 3732: e->type = Type::tsize_t; 3733: return e; 3734: } 3735: else if (ident == Id::ptr) 3736: { 3737: e = e->castTo(sc, next->pointerTo()); 3738: return e; 3739: } 3740: else 3741: { 3742: e = TypeArray::dotExp(sc, e, ident); 3743: } 3744: return e; 3745: } 3746: 3747: int TypeDArray::isString() 3748: { 3749: TY nty = next->toBasetype()->ty; 3750: return nty == Tchar || nty == Twchar || nty == Tdchar; 3751: } 3752: 3753: MATCH TypeDArray::implicitConvTo(Type *to) 3754: { 3755: //printf("TypeDArray::implicitConvTo(to = %s) this = %s\n", to->toChars(), toChars()); 3756: if (equals(to)) 3757: return MATCHexact; 3758: 3759: // Allow implicit conversion of array to pointer 3760: if (IMPLICIT_ARRAY_TO_PTR && to->ty == Tpointer) 3761: { 3762: TypePointer *tp = (TypePointer *)to; 3763: 3764: /* Allow conversion to void* 3765: */ 3766: if (tp->next->ty == Tvoid && 3767: MODimplicitConv(next->mod, tp->next->mod)) 3768: { 3769: return MATCHconvert; 3770: } 3771: 3772: return next->constConv(to); 3773: } 3774: 3775: if (to->ty == Tarray) 3776: { int offset = 0; 3777: TypeDArray *ta = (TypeDArray *)to; 3778: 3779: if (!MODimplicitConv(next->mod, ta->next->mod)) 3780: return MATCHnomatch; // not const-compatible 3781: 3782: /* Allow conversion to void[] 3783: */ 3784: if (next->ty != Tvoid && ta->next->ty == Tvoid) 3785: { 3786: return MATCHconvert; 3787: } 3788: 3789: MATCH m = next->constConv(ta->next); 3790: if (m != MATCHnomatch) 3791: { 3792: if (m == MATCHexact && mod != to->mod) 3793: m = MATCHconst; 3794: return m; 3795: } 3796: 3797: #if 0 3798: /* Allow conversions of T[][] to const(T)[][] 3799: */ 3800: if (mod == ta->mod && next->ty == Tarray && ta->next->ty == Tarray) 3801: { 3802: m = next->implicitConvTo(ta->next); 3803: if (m == MATCHconst) 3804: return m; 3805: } 3806: #endif 3807: 3808: /* Conversion of array of derived to array of base 3809: */ 3810: if (ta->next->isBaseOf(next, &offset) && offset == 0) 3811: return MATCHconvert; 3812: } 3813: return Type::implicitConvTo(to); 3814: } 3815: 3816: Expression *TypeDArray::defaultInit(Loc loc) 3817: { 3818: #if LOGDEFAULTINIT 3819: printf("TypeDArray::defaultInit() '%s'\n", toChars()); 3820: #endif 3821: return new NullExp(loc, this); 3822: } 3823: 3824: int TypeDArray::isZeroInit(Loc loc) 3825: { 3826: return 1; 3827: } 3828: 3829: int TypeDArray::checkBoolean() 3830: { 3831: return TRUE; 3832: } 3833: 3834: int TypeDArray::hasPointers() 3835: { 3836: return TRUE; 3837: } 3838: 3839: 3840: /***************************** TypeAArray *****************************/ 3841: 3842: TypeAArray::TypeAArray(Type *t, Type *index) 3843: : TypeArray(Taarray, t) 3844: { 3845: this->index = index; 3846: this->impl = NULL; 3847: this->loc = 0; 3848: this->sc = NULL; 3849: } 3850: 3851: Type *TypeAArray::syntaxCopy() 3852: { 3853: Type *t = next->syntaxCopy(); 3854: Type *ti = index->syntaxCopy(); 3855: if (t == next && ti == index) 3856: t = this; 3857: else 3858: { t = new TypeAArray(t, ti); 3859: t->mod = mod; 3860: } 3861: return t; 3862: } 3863: 3864: d_uns64 TypeAArray::size(Loc loc) 3865: { 3866: return PTRSIZE /* * 2*/; 3867: } 3868: 3869: 3870: Type *TypeAArray::semantic(Loc loc, Scope *sc) 3871: { 3872: //printf("TypeAArray::semantic() %s index->ty = %d\n", toChars(), index->ty); 3873: this->loc = loc; 3874: this->sc = sc; 3875: if (sc) 3876: sc->setNoFree(); 3877: 3878: // Deal with the case where we thought the index was a type, but 3879: // in reality it was an expression. 3880: if (index->ty == Tident || index->ty == Tinstance || index->ty == Tsarray) 3881: { 3882: Expression *e; 3883: Type *t; 3884: Dsymbol *s; 3885: 3886: index->resolve(loc, sc, &e, &t, &s); 3887: if (e) 3888: { // It was an expression - 3889: // Rewrite as a static array 3890: TypeSArray *tsa; 3891: 3892: tsa = new TypeSArray(next, e); 3893: return tsa->semantic(loc,sc); 3894: } 3895: else if (t) 3896: index = t; 3897: else 3898: { index->error(loc, "index is not a type or an expression"); 3899: return Type::terror; 3900: } 3901: } 3902: else 3903: index = index->semantic(loc,sc); 3904: 3905: if (index->nextOf() && !index->nextOf()->isImmutable()) 3906: { 3907: index = index->constOf()->mutableOf(); 3908: #if 0 3909: printf("index is %p %s\n", index, index->toChars()); 3910: index->check(); 3911: printf("index->mod = x%x\n", index->mod); 3912: printf("index->ito = x%x\n", index->ito); 3913: if (index->ito) { 3914: printf("index->ito->mod = x%x\n", index->ito->mod); 3915: printf("index->ito->ito = x%x\n", index->ito->ito); 3916: } 3917: #endif 3918: } 3919: 3920: switch (index->toBasetype()->ty) 3921: { 3922: case Tfunction: 3923: case Tvoid: 3924: case Tnone: 3925: case Ttuple: 3926: error(loc, "can't have associative array key of %s", index->toBasetype()->toChars()); 3927: return Type::terror; 3928: } 3929: next = next->semantic(loc,sc); 3930: transitive(); 3931: 3932: switch (next->toBasetype()->ty) 3933: { 3934: case Tfunction: 3935: case Tvoid: 3936: case Tnone: 3937: error(loc, "can't have associative array of %s", next->toChars()); 3938: return Type::terror; 3939: } 3940: if (next->isscope()) 3941: { error(loc, "cannot have array of scope %s", next->toChars()); 3942: return Type::terror; 3943: } 3944: return merge(); 3945: } 3946: 3947: StructDeclaration *TypeAArray::getImpl() 3948: { 3949: // Do it lazily 3950: if (!impl) 3951: { 3952: Type *index = this->index; 3953: Type *next = this->next; 3954: if (index->reliesOnTident() || next->reliesOnTident()) 3955: { 3956: error(loc, "cannot create associative array %s", toChars()); 3957: index = terror; 3958: next = terror; 3959: 3960: // Head off future failures 3961: StructDeclaration *s = new StructDeclaration(0, NULL); 3962: s->type = terror; 3963: impl = s; 3964: return impl; 3965: } 3966: /* This is really a proxy for the template instance AssocArray!(index, next) 3967: * But the instantiation can fail if it is a template specialization field 3968: * which has Tident's instead of real types. 3969: */ 3970: Objects *tiargs = new Objects(); 3971: tiargs->push(index); 3972: tiargs->push(next); 3973: 3974: // Create AssociativeArray!(index, next) 3975: #if 1 3976: TemplateInstance *ti = new TemplateInstance(loc, Type::associativearray, tiargs); 3977: #else 3978: //Expression *e = new IdentifierExp(loc, Id::object); 3979: Expression *e = new IdentifierExp(loc, Id::empty); 3980: //e = new DotIdExp(loc, e, Id::object); 3981: DotTemplateInstanceExp *dti = new DotTemplateInstanceExp(loc, 3982: e, 3983: Id::AssociativeArray, 3984: tiargs); 3985: dti->semantic(sc); 3986: TemplateInstance *ti = dti->ti; 3987: #endif 3988: ti->semantic(sc); 3989: ti->semantic2(sc); 3990: ti->semantic3(sc); 3991: impl = ti->toAlias()->isStructDeclaration(); 3992: #ifdef DEBUG 3993: if (!impl) 3994: { Dsymbol *s = ti->toAlias(); 3995: printf("%s %s\n", s->kind(), s->toChars()); 3996: } 3997: #endif 3998: assert(impl); 3999: } 4000: return impl; 4001: } 4002: 4003: void TypeAArray::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps) 4004: { 4005: //printf("TypeAArray::resolve() %s\n", toChars()); 4006: 4007: // Deal with the case where we thought the index was a type, but 4008: // in reality it was an expression. 4009: if (index->ty == Tident || index->ty == Tinstance || index->ty == Tsarray) 4010: { 4011: Expression *e; 4012: Type *t; 4013: Dsymbol *s; 4014: 4015: index->resolve(loc, sc, &e, &t, &s); 4016: if (e) 4017: { // It was an expression - 4018: // Rewrite as a static array 4019: 4020: TypeSArray *tsa = new TypeSArray(next, e); 4021: return tsa->resolve(loc, sc, pe, pt, ps); 4022: } 4023: else if (t) 4024: index = t; 4025: else 4026: index->error(loc, "index is not a type or an expression"); 4027: } 4028: Type::resolve(loc, sc, pe, pt, ps); 4029: } 4030: 4031: 4032: Expression *TypeAArray::dotExp(Scope *sc, Expression *e, Identifier *ident) 4033: { 4034: #if LOGDOTEXP 4035: printf("TypeAArray::dotExp(e = '%s', ident = '%s')\n", e->toChars(), ident->toChars()); 4036: #endif 4037: #if 0 4038: if (ident == Id::length) 4039: { 4040: Expression *ec; 4041: FuncDeclaration *fd; 4042: Expressions *arguments; 4043: 4044: fd = FuncDeclaration::genCfunc(Type::tsize_t, Id::aaLen); 4045: ec = new VarExp(0, fd); 4046: arguments = new Expressions(); 4047: arguments->push(e); 4048: e = new CallExp(e->loc, ec, arguments); 4049: e->type = ((TypeFunction *)fd->type)->next; 4050: } 4051: else 4052: if (ident == Id::keys) 4053: { 4054: Expression *ec; 4055: FuncDeclaration *fd; 4056: Expressions *arguments; 4057: int size = index->size(e->loc); 4058: 4059: assert(size); 4060: fd = FuncDeclaration::genCfunc(Type::tindex, Id::aaKeys); 4061: ec = new VarExp(0, fd); 4062: arguments = new Expressions(); 4063: arguments->push(e); 4064: arguments->push(new IntegerExp(0, size, Type::tsize_t)); 4065: e = new CallExp(e->loc, ec, arguments); 4066: e->type = index->arrayOf(); 4067: } 4068: else if (ident == Id::values) 4069: { 4070: Expression *ec; 4071: FuncDeclaration *fd; 4072: Expressions *arguments; 4073: 4074: fd = FuncDeclaration::genCfunc(Type::tindex, Id::aaValues); 4075: ec = new VarExp(0, fd); 4076: arguments = new Expressions(); 4077: arguments->push(e); 4078: size_t keysize = index->size(e->loc); 4079: keysize = (keysize + PTRSIZE - 1) & ~(PTRSIZE - 1); 4080: arguments->push(new IntegerExp(0, keysize, Type::tsize_t)); 4081: arguments->push(new IntegerExp(0, next->size(e->loc), Type::tsize_t)); 4082: e = new CallExp(e->loc, ec, arguments); 4083: e->type = next->arrayOf(); 4084: } 4085: else if (ident == Id::rehash) 4086: { 4087: Expression *ec; 4088: FuncDeclaration *fd; 4089: Expressions *arguments; 4090: 4091: fd = FuncDeclaration::genCfunc(Type::tint64, Id::aaRehash); 4092: ec = new VarExp(0, fd); 4093: arguments = new Expressions(); 4094: arguments->push(e->addressOf(sc)); 4095: arguments->push(index->getInternalTypeInfo(sc)); 4096: e = new CallExp(e->loc, ec, arguments); 4097: e->type = this; 4098: } 4099: else 4100: #endif 4101: { 4102: e->type = getImpl()->type; 4103: e = e->type->dotExp(sc, e, ident); 4104: //e = Type::dotExp(sc, e, ident); 4105: } 4106: return e; 4107: } 4108: 4109: void TypeAArray::toDecoBuffer(OutBuffer *buf, int flag) 4110: { 4111: Type::toDecoBuffer(buf, flag); 4112: index->toDecoBuffer(buf); 4113: next->toDecoBuffer(buf, (flag & 0x100) ? 0 : mod); 4114: } 4115: 4116: void TypeAArray::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod) 4117: { 4118: if (mod != this->mod) 4119: { toCBuffer3(buf, hgs, mod); 4120: return; 4121: } 4122: next->toCBuffer2(buf, hgs, this->mod); 4123: buf->writeByte('['); 4124: index->toCBuffer2(buf, hgs, 0); 4125: buf->writeByte(']'); 4126: } 4127: 4128: Expression *TypeAArray::defaultInit(Loc loc) 4129: { 4130: #if LOGDEFAULTINIT 4131: printf("TypeAArray::defaultInit() '%s'\n", toChars()); 4132: #endif 4133: return new NullExp(loc, this); 4134: } 4135: 4136: int TypeAArray::isZeroInit(Loc loc) 4137: { 4138: return TRUE; 4139: } 4140: 4141: int TypeAArray::checkBoolean() 4142: { 4143: return TRUE; 4144: } 4145: 4146: int TypeAArray::hasPointers() 4147: { 4148: return TRUE; 4149: } 4150: 4151: MATCH TypeAArray::implicitConvTo(Type *to) 4152: { 4153: //printf("TypeAArray::implicitConvTo(to = %s) this = %s\n", to->toChars(), toChars()); 4154: if (equals(to)) 4155: return MATCHexact; 4156: 4157: if (to->ty == Taarray) 4158: { TypeAArray *ta = (TypeAArray *)to; 4159: 4160: if (!MODimplicitConv(next->mod, ta->next->mod)) 4161: return MATCHnomatch; // not const-compatible 4162: 4163: if (!MODimplicitConv(index->mod, ta->index->mod)) 4164: return MATCHnomatch; // not const-compatible 4165: 4166: MATCH m = next->constConv(ta->next); 4167: MATCH mi = index->constConv(ta->index); 4168: if (m != MATCHnomatch && mi != MATCHnomatch) 4169: { 4170: if (m == MATCHexact && mod != to->mod) 4171: m = MATCHconst; 4172: if (mi < m) 4173: m = mi; 4174: return m; 4175: } 4176: } 4177: return Type::implicitConvTo(to); 4178: } 4179: 4180: MATCH TypeAArray::constConv(Type *to) 4181: { 4182: if (to->ty == Taarray) 4183: { 4184: TypeAArray *taa = (TypeAArray *)to; 4185: MATCH mindex = index->constConv(taa->index); 4186: MATCH mkey = next->constConv(taa->next); 4187: // Pick the worst match 4188: return mkey < mindex ? mkey : mindex; 4189: } 4190: else 4191: return Type::constConv(to); 4192: } 4193: 4194: /***************************** TypePointer *****************************/ 4195: 4196: TypePointer::TypePointer(Type *t) 4197: : TypeNext(Tpointer, t) 4198: { 4199: } 4200: 4201: Type *TypePointer::syntaxCopy() 4202: { 4203: Type *t = next->syntaxCopy(); 4204: if (t == next) 4205: t = this; 4206: else 4207: { t = new TypePointer(t); 4208: t->mod = mod; 4209: } 4210: return t; 4211: } 4212: 4213: Type *TypePointer::semantic(Loc loc, Scope *sc) 4214: { 4215: //printf("TypePointer::semantic()\n"); 4216: if (deco) 4217: return this; 4218: Type *n = next->semantic(loc, sc); 4219: switch (n->toBasetype()->ty) 4220: { 4221: case Ttuple: 4222: error(loc, "can't have pointer to %s", n->toChars()); 4223: n = tint32; 4224: break; 4225: } 4226: if (n != next) 4227: { 4228: deco = NULL; 4229: } 4230: next = n; 4231: transitive(); 4232: return merge(); 4233: } 4234: 4235: 4236: d_uns64 TypePointer::size(Loc loc) 4237: { 4238: return PTRSIZE; 4239: } 4240: 4241: void TypePointer::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod) 4242: { 4243: //printf("TypePointer::toCBuffer2() next = %d\n", next->ty); 4244: if (mod != this->mod) 4245: { toCBuffer3(buf, hgs, mod); 4246: return; 4247: } 4248: next->toCBuffer2(buf, hgs, this->mod); 4249: if (next->ty != Tfunction) 4250: buf->writeByte('*'); 4251: } 4252: 4253: MATCH TypePointer::implicitConvTo(Type *to) 4254: { 4255: //printf("TypePointer::implicitConvTo(to = %s) %s\n", to->toChars(), toChars()); 4256: 4257: if (equals(to)) 4258: return MATCHexact; 4259: if (to->ty == Tpointer) 4260: { TypePointer *tp = (TypePointer *)to; 4261: assert(tp->next); 4262: 4263: if (!MODimplicitConv(next->mod, tp->next->mod)) 4264: return MATCHnomatch; // not const-compatible 4265: 4266: /* Alloc conversion to void[] 4267: */ 4268: if (next->ty != Tvoid && tp->next->ty == Tvoid) 4269: { 4270: return MATCHconvert; 4271: } 4272: 4273: MATCH m = next->constConv(tp->next); 4274: if (m != MATCHnomatch) 4275: { 4276: if (m == MATCHexact && mod != to->mod) 4277: m = MATCHconst; 4278: return m; 4279: } 4280: 4281: /* Conversion of ptr to derived to ptr to base 4282: */ 4283: int offset = 0; 4284: if (tp->next->isBaseOf(next, &offset) && offset == 0) 4285: return MATCHconvert; 4286: } 4287: return MATCHnomatch; 4288: } 4289: 4290: int TypePointer::isscalar() 4291: { 4292: return TRUE; 4293: } 4294: 4295: Expression *TypePointer::defaultInit(Loc loc) 4296: { 4297: #if LOGDEFAULTINIT 4298: printf("TypePointer::defaultInit() '%s'\n", toChars()); 4299: #endif 4300: return new NullExp(loc, this); 4301: } 4302: 4303: int TypePointer::isZeroInit(Loc loc) 4304: { 4305: return 1; 4306: } 4307: 4308: int TypePointer::hasPointers() 4309: { 4310: return TRUE; 4311: } 4312: 4313: 4314: /***************************** TypeReference *****************************/ 4315: 4316: TypeReference::TypeReference(Type *t) 4317: : TypeNext(Treference, t) 4318: { 4319: // BUG: what about references to static arrays? 4320: } 4321: 4322: Type *TypeReference::syntaxCopy() 4323: { 4324: Type *t = next->syntaxCopy(); 4325: if (t == next) 4326: t = this; 4327: else 4328: { t = new TypeReference(t); 4329: t->mod = mod; 4330: } 4331: return t; 4332: } 4333: 4334: Type *TypeReference::semantic(Loc loc, Scope *sc) 4335: { 4336: //printf("TypeReference::semantic()\n"); 4337: Type *n = next->semantic(loc, sc); 4338: if (n != next) 4339: deco = NULL; 4340: next = n; 4341: transitive(); 4342: return merge(); 4343: } 4344: 4345: 4346: d_uns64 TypeReference::size(Loc loc) 4347: { 4348: return PTRSIZE; 4349: } 4350: 4351: void TypeReference::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod) 4352: { 4353: if (mod != this->mod) 4354: { toCBuffer3(buf, hgs, mod); 4355: return; 4356: } 4357: next->toCBuffer2(buf, hgs, this->mod); 4358: buf->writeByte('&'); 4359: } 4360: 4361: Expression *TypeReference::dotExp(Scope *sc, Expression *e, Identifier *ident) 4362: { 4363: #if LOGDOTEXP 4364: printf("TypeReference::dotExp(e = '%s', ident = '%s')\n", e->toChars(), ident->toChars()); 4365: #endif 4366: 4367: // References just forward things along 4368: return next->dotExp(sc, e, ident); 4369: } 4370: 4371: Expression *TypeReference::defaultInit(Loc loc) 4372: { 4373: #if LOGDEFAULTINIT 4374: printf("TypeReference::defaultInit() '%s'\n", toChars()); 4375: #endif 4376: return new NullExp(loc, this); 4377: } 4378: 4379: int TypeReference::isZeroInit(Loc loc) 4380: { 4381: return 1; 4382: } 4383: 4384: 4385: /***************************** TypeFunction *****************************/ 4386: 4387: TypeFunction::TypeFunction(Parameters *parameters, Type *treturn, int varargs, enum LINK linkage, StorageClass stc) 4388: : TypeNext(Tfunction, treturn) 4389: { 4390: //if (!treturn) *(char*)0=0; 4391: // assert(treturn); 4392: assert(0 <= varargs && varargs <= 2); 4393: this->parameters = parameters; 4394: this->varargs = varargs; 4395: this->linkage = linkage; 4396: this->inuse = 0; 4397: this->isnothrow = false; 4398: this->purity = PUREimpure; 4399: this->isproperty = false; 4400: this->isref = false; 4401: this->fargs = NULL; 4402: 4403: if (stc & STCpure) 4404: this->purity = PUREfwdref; 4405: if (stc & STCnothrow) 4406: this->isnothrow = true; 4407: if (stc & STCproperty) 4408: this->isproperty = true; 4409: 4410: this->trust = TRUSTdefault; 4411: if (stc & STCsafe) 4412: this->trust = TRUSTsafe; 4413: if (stc & STCsystem) 4414: this->trust = TRUSTsystem; 4415: if (stc & STCtrusted) 4416: this->trust = TRUSTtrusted; 4417: } 4418: 4419: Type *TypeFunction::syntaxCopy() 4420: { 4421: Type *treturn = next ? next->syntaxCopy() : NULL; 4422: Parameters *params = Parameter::arraySyntaxCopy(parameters); 4423: TypeFunction *t = new TypeFunction(params, treturn, varargs, linkage); 4424: t->mod = mod; 4425: t->isnothrow = isnothrow; 4426: t->purity = purity; 4427: t->isproperty = isproperty; 4428: t->isref = isref; 4429: t->trust = trust; 4430: t->fargs = fargs; 4431: return t; 4432: } 4433: 4434: /******************************* 4435: * Covariant means that 'this' can substitute for 't', 4436: * i.e. a pure function is a match for an impure type. 4437: * Returns: 4438: * 0 types are distinct 4439: * 1 this is covariant with t 4440: * 2 arguments match as far as overloading goes, 4441: * but types are not covariant 4442: * 3 cannot determine covariance because of forward references 4443: */ 4444: 4445: int Type::covariant(Type *t) 4446: { 4447: #if 0 4448: printf("Type::covariant(t = %s) %s\n", t->toChars(), toChars()); 4449: printf("deco = %p, %p\n", deco, t->deco); 4450: // printf("ty = %d\n", next->ty); 4451: printf("mod = %x, %x\n", mod, t->mod); 4452: #endif 4453: 4454: int inoutmismatch = 0; 4455: 4456: TypeFunction *t1; 4457: TypeFunction *t2; 4458: 4459: if (equals(t)) 4460: return 1; // covariant 4461: 4462: if (ty != Tfunction || t->ty != Tfunction) 4463: goto Ldistinct; 4464: 4465: t1 = (TypeFunction *)this; 4466: t2 = (TypeFunction *)t; 4467: 4468: if (t1->varargs != t2->varargs) 4469: goto Ldistinct; 4470: 4471: if (t1->parameters && t2->parameters) 4472: { 4473: size_t dim = Parameter::dim(t1->parameters); 4474: if (dim != Parameter::dim(t2->parameters)) 4475: goto Ldistinct; 4476: 4477: for (size_t i = 0; i < dim; i++) 4478: { Parameter *arg1 = Parameter::getNth(t1->parameters, i); 4479: Parameter *arg2 = Parameter::getNth(t2->parameters, i); 4480: 4481: if (!arg1->type->equals(arg2->type)) 4482: { 4483: #if 0 // turn on this for contravariant argument types, see bugzilla 3075 4484: // BUG: cannot convert ref to const to ref to immutable 4485: // We can add const, but not subtract it 4486: if (arg2->type->implicitConvTo(arg1->type) < MATCHconst) 4487: #endif 4488: goto Ldistinct; 4489: } 4490: const StorageClass sc = STCref | STCin | STCout | STClazy; 4491: if ((arg1->storageClass & sc) != (arg2->storageClass & sc)) 4492: inoutmismatch = 1; 4493: // We can add scope, but not subtract it 4494: if (!(arg1->storageClass & STCscope) && (arg2->storageClass & STCscope)) 4495: inoutmismatch = 1; 4496: } 4497: } 4498: else if (t1->parameters != t2->parameters) 4499: goto Ldistinct; 4500: 4501: // The argument lists match 4502: if (inoutmismatch) 4503: goto Lnotcovariant; 4504: if (t1->linkage != t2->linkage) 4505: goto Lnotcovariant; 4506: 4507: { 4508: // Return types 4509: Type *t1n = t1->next; 4510: Type *t2n = t2->next; 4511: 4512: if (!t1n || !t2n) // happens with return type inference 4513: goto Lnotcovariant; 4514: 4515: if (t1n->equals(t2n)) 4516: goto Lcovariant; 4517: if (t1n->ty == Tclass && t2n->ty == Tclass) 4518: { 4519: /* If same class type, but t2n is const, then it's 4520: * covariant. Do this test first because it can work on 4521: * forward references. 4522: */ 4523: if (((TypeClass *)t1n)->sym == ((TypeClass *)t2n)->sym && 4524: MODimplicitConv(t1n->mod, t2n->mod)) 4525: goto Lcovariant; 4526: 4527: // If t1n is forward referenced: 4528: ClassDeclaration *cd = ((TypeClass *)t1n)->sym; 4529: #if 0 4530: if (!cd->baseClass && cd->baseclasses->dim && !cd->isInterfaceDeclaration()) 4531: #else 4532: if (!cd->isBaseInfoComplete()) 4533: #endif 4534: { 4535: return 3; // forward references 4536: } 4537: } 4538: if (t1n->implicitConvTo(t2n)) 4539: goto Lcovariant; 4540: } 4541: goto Lnotcovariant; 4542: 4543: Lcovariant: 4544: /* Can convert mutable to const 4545: */ 4546: if (!MODimplicitConv(t2->mod, t1->mod)) 4547: goto Lnotcovariant; 4548: #if 0 4549: if (t1->mod != t2->mod) 4550: { 4551: if (!(t1->mod & MODconst) && (t2->mod & MODconst)) 4552: goto Lnotcovariant; 4553: if (!(t1->mod & MODshared) && (t2->mod & MODshared)) 4554: goto Lnotcovariant; 4555: } 4556: #endif 4557: 4558: /* Can convert pure to impure, and nothrow to throw 4559: */ 4560: if (!t1->purity && t2->purity) 4561: goto Lnotcovariant; 4562: 4563: if (!t1->isnothrow && t2->isnothrow) 4564: goto Lnotcovariant; 4565: 4566: if (t1->isref != t2->isref) 4567: goto Lnotcovariant; 4568: 4569: /* Can convert safe/trusted to system 4570: */ 4571: if (t1->trust <= TRUSTsystem && t2->trust >= TRUSTtrusted) 4572: goto Lnotcovariant; 4573: 4574: //printf("\tcovaraint: 1\n"); 4575: return 1; 4576: 4577: Ldistinct: 4578: //printf("\tcovaraint: 0\n"); 4579: return 0; 4580: 4581: Lnotcovariant: 4582: //printf("\tcovaraint: 2\n"); 4583: return 2; 4584: } 4585: 4586: void TypeFunction::toDecoBuffer(OutBuffer *buf, int flag) 4587: { unsigned char mc; 4588: 4589: //printf("TypeFunction::toDecoBuffer() this = %p %s\n", this, toChars()); 4590: //static int nest; if (++nest == 50) *(char*)0=0; 4591: if (inuse) 4592: { inuse = 2; // flag error to caller 4593: return; 4594: } 4595: inuse++; 4596: MODtoDecoBuffer(buf, mod); 4597: switch (linkage) 4598: { 4599: case LINKd: mc = 'F'; break; 4600: case LINKc: mc = 'U'; break; 4601: case LINKwindows: mc = 'W'; break; 4602: case LINKpascal: mc = 'V'; break; 4603: case LINKcpp: mc = 'R'; break; 4604: default: 4605: assert(0); 4606: } 4607: buf->writeByte(mc); 4608: if (purity || isnothrow || isproperty || isref || trust) 4609: { 4610: if (purity) 4611: buf->writestring("Na"); 4612: if (isnothrow) 4613: buf->writestring("Nb"); 4614: if (isref) 4615: buf->writestring("Nc"); 4616: if (isproperty) 4617: buf->writestring("Nd"); 4618: switch (trust) 4619: { 4620: case TRUSTtrusted: 4621: buf->writestring("Ne"); 4622: break; 4623: case TRUSTsafe: 4624: buf->writestring("Nf"); 4625: break; 4626: } 4627: } 4628: // Write argument types 4629: Parameter::argsToDecoBuffer(buf, parameters); 4630: //if (buf->data[buf->offset - 1] == '@') halt(); 4631: buf->writeByte('Z' - varargs); // mark end of arg list 4632: assert(next); 4633: next->toDecoBuffer(buf); 4634: inuse--; 4635: } 4636: 4637: void TypeFunction::toCBuffer(OutBuffer *buf, Identifier *ident, HdrGenState *hgs) 4638: { 4639: toCBufferWithAttributes(buf, ident, hgs, this, NULL); 4640: } 4641: 4642: void TypeFunction::toCBufferWithAttributes(OutBuffer *buf, Identifier *ident, HdrGenState* hgs, TypeFunction *attrs, TemplateDeclaration *td) 4643: { 4644: //printf("TypeFunction::toCBuffer() this = %p\n", this); 4645: const char *p = NULL; 4646: 4647: if (inuse) 4648: { inuse = 2; // flag error to caller 4649: return; 4650: } 4651: inuse++; 4652: 4653: /* Use 'storage class' style for attributes 4654: */ 4655: if (attrs->mod) 4656: { 4657: MODtoBuffer(buf, attrs->mod); 4658: buf->writeByte(' '); 4659: } 4660: 4661: if (attrs->purity) 4662: buf->writestring("pure "); 4663: if (attrs->isnothrow) 4664: buf->writestring("nothrow "); 4665: if (attrs->isproperty) 4666: buf->writestring("@property "); 4667: if (attrs->isref) 4668: buf->writestring("ref "); 4669: 4670: switch (attrs->trust) 4671: { 4672: case TRUSTsystem: 4673: buf->writestring("@system "); 4674: break; 4675: 4676: case TRUSTtrusted: 4677: buf->writestring("@trusted "); 4678: break; 4679: 4680: case TRUSTsafe: 4681: buf->writestring("@safe "); 4682: break; 4683: } 4684: 4685: if (next && (!ident || ident->toHChars2() == ident->toChars())) 4686: next->toCBuffer2(buf, hgs, 0); 4687: else if (hgs->ddoc && !next) 4688: buf->writestring("auto"); 4689: if (hgs->ddoc != 1) 4690: { 4691: switch (attrs->linkage) 4692: { 4693: case LINKd: p = NULL; break; 4694: case LINKc: p = "C "; break; 4695: case LINKwindows: p = "Windows "; break; 4696: case LINKpascal: p = "Pascal "; break; 4697: case LINKcpp: p = "C++ "; break; 4698: default: 4699: assert(0); 4700: } 4701: } 4702: 4703: if (!hgs->hdrgen && p) 4704: buf->writestring(p); 4705: if (ident) 4706: { buf->writeByte(' '); 4707: buf->writestring(ident->toHChars2()); 4708: } 4709: if (td) 4710: { buf->writeByte('('); 4711: for (int i = 0; i < td->origParameters->dim; i++)
warning C4018: '<' : signed/unsigned mismatch
4712: { 4713: TemplateParameter *tp = td->origParameters->tdata()[i]; 4714: if (i) 4715: buf->writestring(", "); 4716: tp->toCBuffer(buf, hgs); 4717: } 4718: buf->writeByte(')'); 4719: } 4720: Parameter::argsToCBuffer(buf, hgs, parameters, varargs); 4721: inuse--; 4722: } 4723: 4724: void TypeFunction::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod) 4725: { 4726: //printf("TypeFunction::toCBuffer2() this = %p, ref = %d\n", this, isref); 4727: const char *p = NULL; 4728: 4729: if (inuse) 4730: { inuse = 2; // flag error to caller 4731: return; 4732: } 4733: inuse++; 4734: if (next) 4735: next->toCBuffer2(buf, hgs, 0); 4736: if (hgs->ddoc != 1) 4737: { 4738: switch (linkage) 4739: { 4740: case LINKd: p = NULL; break; 4741: case LINKc: p = " C"; break; 4742: case LINKwindows: p = " Windows"; break; 4743: case LINKpascal: p = " Pascal"; break; 4744: case LINKcpp: p = " C++"; break; 4745: default: 4746: assert(0); 4747: } 4748: } 4749: 4750: if (!hgs->hdrgen && p) 4751: buf->writestring(p); 4752: buf->writestring(" function"); 4753: Parameter::argsToCBuffer(buf, hgs, parameters, varargs); 4754: attributesToCBuffer(buf, mod); 4755: inuse--; 4756: } 4757: 4758: void TypeFunction::attributesToCBuffer(OutBuffer *buf, int mod) 4759: { 4760: /* Use postfix style for attributes 4761: */ 4762: if (mod != this->mod) 4763: { 4764: modToBuffer(buf); 4765: } 4766: if (purity) 4767: buf->writestring(" pure"); 4768: if (isnothrow) 4769: buf->writestring(" nothrow"); 4770: if (isproperty) 4771: buf->writestring(" @property"); 4772: if (isref) 4773: buf->writestring(" ref"); 4774: 4775: switch (trust) 4776: { 4777: case TRUSTsystem: 4778: buf->writestring(" @system"); 4779: break; 4780: 4781: case TRUSTtrusted: 4782: buf->writestring(" @trusted"); 4783: break; 4784: 4785: case TRUSTsafe: 4786: buf->writestring(" @safe"); 4787: break; 4788: } 4789: } 4790: 4791: Type *TypeFunction::semantic(Loc loc, Scope *sc) 4792: { 4793: if (deco) // if semantic() already run 4794: { 4795: //printf("already done\n"); 4796: return this; 4797: } 4798: //printf("TypeFunction::semantic() this = %p\n", this); 4799: //printf("TypeFunction::semantic() %s, sc->stc = %llx, fargs = %p\n", toChars(), sc->stc, fargs); 4800: 4801: /* Copy in order to not mess up original. 4802: * This can produce redundant copies if inferring return type, 4803: * as semantic() will get called again on this. 4804: */ 4805: TypeFunction *tf = (TypeFunction *)mem.malloc(sizeof(TypeFunction)); 4806: memcpy(tf, this, sizeof(TypeFunction)); 4807: if (parameters) 4808: { tf->parameters = (Parameters *)parameters->copy(); 4809: for (size_t i = 0; i < parameters->dim; i++) 4810: { Parameter *arg = parameters->tdata()[i]; 4811: Parameter *cpy = (Parameter *)mem.malloc(sizeof(Parameter)); 4812: memcpy(cpy, arg, sizeof(Parameter)); 4813: tf->parameters->tdata()[i] = cpy; 4814: } 4815: } 4816: 4817: if (sc->stc & STCpure) 4818: tf->purity = PUREfwdref; 4819: if (sc->stc & STCnothrow) 4820: tf->isnothrow = TRUE; 4821: if (sc->stc & STCref) 4822: tf->isref = TRUE; 4823: if (sc->stc & STCsafe) 4824: tf->trust = TRUSTsafe; 4825: if (sc->stc & STCtrusted) 4826: tf->trust = TRUSTtrusted; 4827: if (sc->stc & STCproperty) 4828: tf->isproperty = TRUE; 4829: 4830: tf->linkage = sc->linkage; 4831: 4832: /* If the parent is @safe, then this function defaults to safe 4833: * too. 4834: */ 4835: if (tf->trust == TRUSTdefault) 4836: for (Dsymbol *p = sc->func; p; p = p->toParent2()) 4837: { FuncDeclaration *fd = p->isFuncDeclaration(); 4838: if (fd) 4839: { 4840: if (fd->isSafe()) 4841: tf->trust = TRUSTsafe; // default to @safe 4842: break; 4843: } 4844: } 4845: 4846: bool wildreturn = FALSE; 4847: if (tf->next) 4848: { 4849: tf->next = tf->next->semantic(loc,sc); 4850: #if !SARRAYVALUE 4851: if (tf->next->toBasetype()->ty == Tsarray) 4852: { error(loc, "functions cannot return static array %s", tf->next->toChars()); 4853: tf->next = Type::terror; 4854: } 4855: #endif 4856: if (tf->next->toBasetype()->ty == Tfunction) 4857: { error(loc, "functions cannot return a function"); 4858: tf->next = Type::terror; 4859: } 4860: if (tf->next->toBasetype()->ty == Ttuple) 4861: { error(loc, "functions cannot return a tuple"); 4862: tf->next = Type::terror; 4863: } 4864: if (tf->next->isscope() && !(sc->flags & SCOPEctor)) 4865: error(loc, "functions cannot return scope %s", tf->next->toChars()); 4866: if (tf->next->toBasetype()->ty == Tvoid) 4867: tf->isref = FALSE; // rewrite "ref void" as just "void" 4868: if (tf->next->isWild()) 4869: wildreturn = TRUE; 4870: } 4871: 4872: bool wildparams = FALSE; 4873: bool wildsubparams = FALSE; 4874: if (tf->parameters) 4875: { 4876: /* Create a scope for evaluating the default arguments for the parameters 4877: */ 4878: Scope *argsc = sc->push(); 4879: argsc->stc = 0; // don't inherit storage class 4880: argsc->protection = PROTpublic; 4881: 4882: size_t dim = Parameter::dim(tf->parameters); 4883: for (size_t i = 0; i < dim; i++) 4884: { Parameter *fparam = Parameter::getNth(tf->parameters, i); 4885: 4886: tf->inuse++; 4887: fparam->type = fparam->type->semantic(loc, argsc);
warning C6011: Dereferencing NULL pointer 'fparam->type': Lines: 4793, 4805, 4806, 4807, 4808, 4809, 4817, 4818, 4819, 4820, 4821, 4822, 4823, 4824, 4825, 4826, 4827, 4828, 4830, 4835, 4846, 4847, 4849, 4856, 4860, 4864, 4865, 4866, 4868, 4869, 4872, 4873, 4874, 4878, 4879, 4880, 4882, 4883, 4884, 4886, 4887
4888: if (tf->inuse == 1) tf->inuse--; 4889: 4890: fparam->type = fparam->type->addStorageClass(fparam->storageClass); 4891: 4892: if (fparam->storageClass & (STCauto | STCalias | STCstatic)) 4893: { 4894: if (!fparam->type) 4895: continue; 4896: } 4897: 4898: Type *t = fparam->type->toBasetype(); 4899: 4900: if (fparam->storageClass & (STCout | STCref | STClazy)) 4901: { 4902: //if (t->ty == Tsarray) 4903: //error(loc, "cannot have out or ref parameter of type %s", t->toChars()); 4904: if (fparam->storageClass & STCout && fparam->type->mod & (STCconst | STCimmutable)) 4905: error(loc, "cannot have const or immutable out parameter of type %s", t->toChars()); 4906: } 4907: if (!(fparam->storageClass & STClazy) && t->ty == Tvoid) 4908: error(loc, "cannot have parameter of type %s", fparam->type->toChars()); 4909: 4910: if (t->isWild()) 4911: { 4912: wildparams = TRUE; 4913: if (tf->next && !wildreturn) 4914: error(loc, "inout on parameter means inout must be on return type as well (if from D1 code, replace with 'ref')"); 4915: } 4916: else if (!wildsubparams && t->hasWild()) 4917: wildsubparams = TRUE; 4918: 4919: if (fparam->defaultArg) 4920: { 4921: fparam->defaultArg = fparam->defaultArg->semantic(argsc); 4922: fparam->defaultArg = resolveProperties(argsc, fparam->defaultArg); 4923: fparam->defaultArg = fparam->defaultArg->implicitCastTo(argsc, fparam->type); 4924: } 4925: 4926: /* If fparam turns out to be a tuple, the number of parameters may 4927: * change. 4928: */ 4929: if (t->ty == Ttuple) 4930: { 4931: // Propagate storage class from tuple parameters to their element-parameters. 4932: TypeTuple *tt = (TypeTuple *)t; 4933: if (tt->arguments) 4934: { 4935: size_t tdim = tt->arguments->dim; 4936: for (size_t j = 0; j < tdim; j++) 4937: { Parameter *narg = tt->arguments->tdata()[j]; 4938: narg->storageClass |= fparam->storageClass; 4939: } 4940: fparam->storageClass = 0; 4941: } 4942: 4943: /* Reset number of parameters, and back up one to do this fparam again, 4944: * now that it is the first element of a tuple 4945: */ 4946: dim = Parameter::dim(tf->parameters); 4947: i--; 4948: continue; 4949: } 4950: 4951: /* Resolve "auto ref" storage class to be either ref or value, 4952: * based on the argument matching the parameter 4953: */ 4954: if (fparam->storageClass & STCauto) 4955: { 4956: if (fargs && i < fargs->dim) 4957: { Expression *farg = fargs->tdata()[i]; 4958: if (farg->isLvalue()) 4959: ; // ref parameter 4960: else 4961: fparam->storageClass &= ~STCref; // value parameter 4962: } 4963: else 4964: error(loc, "auto can only be used for template function parameters"); 4965: } 4966: } 4967: argsc->pop(); 4968: } 4969: if (wildreturn && !wildparams) 4970: error(loc, "inout on return means inout must be on a parameter as well for %s", toChars()); 4971: if (wildsubparams && wildparams) 4972: error(loc, "inout must be all or none on top level for %s", toChars()); 4973: 4974: if (tf->next) 4975: tf->deco = tf->merge()->deco; 4976: 4977: if (tf->inuse) 4978: { error(loc, "recursive type"); 4979: tf->inuse = 0; 4980: return terror; 4981: } 4982: 4983: if (tf->isproperty && (tf->varargs || Parameter::dim(tf->parameters) > 1)) 4984: error(loc, "properties can only have zero or one parameter"); 4985: 4986: if (tf->varargs == 1 && tf->linkage != LINKd && Parameter::dim(tf->parameters) == 0) 4987: error(loc, "variadic functions with non-D linkage must have at least one parameter"); 4988: 4989: /* Don't return merge(), because arg identifiers and default args 4990: * can be different 4991: * even though the types match 4992: */ 4993: return tf; 4994: } 4995: 4996: 4997: /******************************************** 4998: * Do this lazily, as the parameter types might be forward referenced. 4999: */ 5000: void TypeFunction::purityLevel() 5001: { 5002: TypeFunction *tf = this; 5003: if (tf->purity == PUREfwdref) 5004: { /* Evaluate what kind of purity based on the modifiers for the parameters 5005: */ 5006: tf->purity = PUREstrong; // assume strong until something weakens it 5007: if (tf->parameters) 5008: { 5009: size_t dim = Parameter::dim(tf->parameters); 5010: for (size_t i = 0; i < dim; i++) 5011: { Parameter *fparam = Parameter::getNth(tf->parameters, i); 5012: if (fparam->storageClass & STClazy) 5013: { 5014: /* We could possibly allow this by doing further analysis on the 5015: * lazy parameter to see if it's pure. 5016: */ 5017: error(0, "cannot have lazy parameters to a pure function"); 5018: } 5019: if (fparam->storageClass & STCout) 5020: { 5021: tf->purity = PUREweak; 5022: break; 5023: } 5024: if (!fparam->type) 5025: continue; 5026: if (fparam->storageClass & STCref) 5027: { 5028: if (!(fparam->type->mod & (MODconst | MODimmutable | MODwild))) 5029: { tf->purity = PUREweak; 5030: break; 5031: } 5032: if (fparam->type->mod & MODconst) 5033: { tf->purity = PUREconst; 5034: continue; 5035: } 5036: } 5037: Type *t = fparam->type->toBasetype(); 5038: if (!t->hasPointers()) 5039: continue; 5040: if (t->mod & (MODimmutable | MODwild)) 5041: continue; 5042: /* The rest of this is too strict; fix later. 5043: * For example, the only pointer members of a struct may be immutable, 5044: * which would maintain strong purity. 5045: */ 5046: if (t->mod & MODconst) 5047: { tf->purity = PUREconst; 5048: continue; 5049: } 5050: Type *tn = t->nextOf(); 5051: if (tn) 5052: { tn = tn->toBasetype(); 5053: if (tn->ty == Tpointer || tn->ty == Tarray) 5054: { /* Accept immutable(T)* and immutable(T)[] as being strongly pure 5055: */ 5056: if (tn->mod & (MODimmutable | MODwild)) 5057: continue; 5058: if (tn->mod & MODconst) 5059: { tf->purity = PUREconst; 5060: continue; 5061: } 5062: } 5063: } 5064: /* Should catch delegates and function pointers, and fold in their purity 5065: */ 5066: tf->purity = PUREweak; // err on the side of too strict 5067: break; 5068: } 5069: } 5070: } 5071: } 5072: 5073: 5074: /******************************** 5075: * 'args' are being matched to function 'this' 5076: * Determine match level. 5077: * Input: 5078: * flag 1 performing a partial ordering match 5079: * Returns: 5080: * MATCHxxxx 5081: */ 5082: 5083: int TypeFunction::callMatch(Expression *ethis, Expressions *args, int flag) 5084: { 5085: //printf("TypeFunction::callMatch() %s\n", toChars()); 5086: MATCH match = MATCHexact; // assume exact match 5087: bool exactwildmatch = FALSE; 5088: bool wildmatch = FALSE; 5089: 5090: if (ethis) 5091: { Type *t = ethis->type; 5092: if (t->toBasetype()->ty == Tpointer) 5093: t = t->toBasetype()->nextOf(); // change struct* to struct 5094: if (t->mod != mod) 5095: { 5096: if (MODimplicitConv(t->mod, mod)) 5097: match = MATCHconst; 5098: else 5099: return MATCHnomatch; 5100: } 5101: } 5102: 5103: size_t nparams = Parameter::dim(parameters); 5104: size_t nargs = args ? args->dim : 0; 5105: if (nparams == nargs) 5106: ; 5107: else if (nargs > nparams) 5108: { 5109: if (varargs == 0) 5110: goto Nomatch; // too many args; no match 5111: match = MATCHconvert; // match ... with a "conversion" match level 5112: } 5113: 5114: for (size_t u = 0; u < nparams; u++) 5115: { MATCH m; 5116: Expression *arg; 5117: 5118: // BUG: what about out and ref? 5119: 5120: Parameter *p = Parameter::getNth(parameters, u); 5121: assert(p); 5122: if (u >= nargs) 5123: { 5124: if (p->defaultArg) 5125: continue; 5126: if (varargs == 2 && u + 1 == nparams) 5127: goto L1; 5128: goto Nomatch; // not enough arguments 5129: } 5130: arg = args->tdata()[u]; 5131: assert(arg); 5132: //printf("arg: %s, type: %s\n", arg->toChars(), arg->type->toChars()); 5133: 5134: // Non-lvalues do not match ref or out parameters 5135: if (p->storageClass & (STCref | STCout)) 5136: { if (!arg->isLvalue()) 5137: goto Nomatch; 5138: } 5139: 5140: if (p->storageClass & STCref) 5141: { 5142: /* Don't allow static arrays to be passed to mutable references 5143: * to static arrays if the argument cannot be modified. 5144: */ 5145: Type *targb = arg->type->toBasetype(); 5146: Type *tparb = p->type->toBasetype(); 5147: //printf("%s\n", targb->toChars()); 5148: //printf("%s\n", tparb->toChars()); 5149: if (targb->nextOf() && tparb->ty == Tsarray && 5150: !MODimplicitConv(targb->nextOf()->mod, tparb->nextOf()->mod)) 5151: goto Nomatch; 5152: } 5153: 5154: if (p->storageClass & STClazy && p->type->ty == Tvoid && 5155: arg->type->ty != Tvoid) 5156: m = MATCHconvert; 5157: else 5158: { 5159: //printf("%s of type %s implicitConvTo %s\n", arg->toChars(), arg->type->toChars(), p->type->toChars()); 5160: if (flag) 5161: // for partial ordering, value is an irrelevant mockup, just look at the type 5162: m = arg->type->implicitConvTo(p->type); 5163: else 5164: m = arg->implicitConvTo(p->type); 5165: //printf("match %d\n", m); 5166: if (p->type->isWild()) 5167: { 5168: if (m == MATCHnomatch) 5169: { 5170: m = arg->implicitConvTo(p->type->constOf()); 5171: if (m == MATCHnomatch) 5172: m = arg->implicitConvTo(p->type->sharedConstOf()); 5173: if (m != MATCHnomatch) 5174: wildmatch = TRUE; // mod matched to wild 5175: } 5176: else 5177: exactwildmatch = TRUE; // wild matched to wild 5178: 5179: /* If both are allowed, then there could be more than one 5180: * binding of mod to wild, leaving a gaping type hole. 5181: */ 5182: if (wildmatch && exactwildmatch) 5183: m = MATCHnomatch; 5184: } 5185: } 5186: 5187: //printf("\tm = %d\n", m); 5188: if (m == MATCHnomatch) // if no match 5189: { 5190: L1: 5191: if (varargs == 2 && u + 1 == nparams) // if last varargs param 5192: { Type *tb = p->type->toBasetype(); 5193: TypeSArray *tsa; 5194: dinteger_t sz; 5195: 5196: switch (tb->ty) 5197: { 5198: case Tsarray: 5199: tsa = (TypeSArray *)tb; 5200: sz = tsa->dim->toInteger(); 5201: if (sz != nargs - u) 5202: goto Nomatch; 5203: case Tarray: 5204: { TypeArray *ta = (TypeArray *)tb; 5205: for (; u < nargs; u++) 5206: { 5207: arg = args->tdata()[u]; 5208: assert(arg); 5209: #if 1 5210: /* If lazy array of delegates, 5211: * convert arg(s) to delegate(s) 5212: */ 5213: Type *tret = p->isLazyArray(); 5214: if (tret) 5215: { 5216: if (ta->next->equals(arg->type)) 5217: { m = MATCHexact; 5218: } 5219: else 5220: { 5221: m = arg->implicitConvTo(tret); 5222: if (m == MATCHnomatch) 5223: { 5224: if (tret->toBasetype()->ty == Tvoid) 5225: m = MATCHconvert; 5226: } 5227: } 5228: } 5229: else 5230: m = arg->implicitConvTo(ta->next); 5231: #else 5232: m = arg->implicitConvTo(ta->next); 5233: #endif 5234: if (m == MATCHnomatch) 5235: goto Nomatch; 5236: if (m < match) 5237: match = m; 5238: } 5239: goto Ldone; 5240: } 5241: case Tclass: 5242: // Should see if there's a constructor match? 5243: // Or just leave it ambiguous? 5244: goto Ldone; 5245: 5246: default: 5247: goto Nomatch; 5248: } 5249: } 5250: goto Nomatch; 5251: } 5252: if (m < match) 5253: match = m; // pick worst match 5254: } 5255: 5256: Ldone: 5257: //printf("match = %d\n", match); 5258: return match; 5259: 5260: Nomatch: 5261: //printf("no match\n"); 5262: return MATCHnomatch; 5263: } 5264: 5265: Type *TypeFunction::reliesOnTident() 5266: { 5267: size_t dim = Parameter::dim(parameters); 5268: for (size_t i = 0; i < dim; i++) 5269: { Parameter *fparam = Parameter::getNth(parameters, i); 5270: Type *t = fparam->type->reliesOnTident(); 5271: if (t) 5272: return t; 5273: } 5274: return next ? next->reliesOnTident() : NULL; 5275: } 5276: 5277: /******************************************** 5278: * Return TRUE if there are lazy parameters. 5279: */ 5280: bool TypeFunction::hasLazyParameters() 5281: { 5282: size_t dim = Parameter::dim(parameters); 5283: for (size_t i = 0; i < dim; i++) 5284: { Parameter *fparam = Parameter::getNth(parameters, i); 5285: if (fparam->storageClass & STClazy) 5286: return TRUE; 5287: } 5288: return FALSE; 5289: } 5290: 5291: /*************************** 5292: * Examine function signature for parameter p and see if 5293: * p can 'escape' the scope of the function. 5294: */ 5295: 5296: bool TypeFunction::parameterEscapes(Parameter *p) 5297: { 5298: 5299: /* Scope parameters do not escape. 5300: * Allow 'lazy' to imply 'scope' - 5301: * lazy parameters can be passed along 5302: * as lazy parameters to the next function, but that isn't 5303: * escaping. 5304: */ 5305: if (p->storageClass & (STCscope | STClazy)) 5306: return FALSE; 5307: 5308: if (purity) 5309: { /* With pure functions, we need only be concerned if p escapes 5310: * via any return statement. 5311: */ 5312: Type* tret = nextOf()->toBasetype(); 5313: if (!isref && !tret->hasPointers()) 5314: { /* The result has no references, so p could not be escaping 5315: * that way. 5316: */ 5317: return FALSE; 5318: } 5319: } 5320: 5321: /* Assume it escapes in the absence of better information. 5322: */ 5323: return TRUE; 5324: } 5325: 5326: Expression *TypeFunction::defaultInit(Loc loc) 5327: { 5328: error(loc, "function does not have a default initializer"); 5329: return new ErrorExp(); 5330: } 5331: 5332: /***************************** TypeDelegate *****************************/ 5333: 5334: TypeDelegate::TypeDelegate(Type *t) 5335: : TypeNext(Tfunction, t) 5336: { 5337: ty = Tdelegate; 5338: } 5339: 5340: Type *TypeDelegate::syntaxCopy() 5341: { 5342: Type *t = next->syntaxCopy(); 5343: if (t == next) 5344: t = this; 5345: else 5346: { t = new TypeDelegate(t); 5347: t->mod = mod; 5348: } 5349: return t; 5350: } 5351: 5352: Type *TypeDelegate::semantic(Loc loc, Scope *sc) 5353: { 5354: if (deco) // if semantic() already run 5355: { 5356: //printf("already done\n"); 5357: return this; 5358: } 5359: next = next->semantic(loc,sc); 5360: /* In order to deal with Bugzilla 4028, perhaps default arguments should 5361: * be removed from next before the merge. 5362: */ 5363: 5364: /* Don't return merge(), because arg identifiers and default args 5365: * can be different 5366: * even though the types match 5367: */ 5368: //deco = merge()->deco; 5369: //return this; 5370: return merge(); 5371: } 5372: 5373: d_uns64 TypeDelegate::size(Loc loc) 5374: { 5375: return PTRSIZE * 2; 5376: } 5377: 5378: unsigned TypeDelegate::alignsize() 5379: { 5380: #if DMDV1 5381: // See Bugzilla 942 for discussion 5382: if (!global.params.is64bit) 5383: return PTRSIZE * 2; 5384: #endif 5385: return PTRSIZE; 5386: } 5387: 5388: MATCH TypeDelegate::implicitConvTo(Type *to) 5389: { 5390: //printf("TypeDelegate::implicitConvTo(this=%p, to=%p)\n", this, to); 5391: //printf("from: %s\n", toChars()); 5392: //printf("to : %s\n", to->toChars()); 5393: if (this == to) 5394: return MATCHexact; 5395: #if 1 // not allowing covariant conversions because it interferes with overriding 5396: if (to->ty == Tdelegate && this->nextOf()->covariant(to->nextOf()) == 1) 5397: return MATCHconvert; 5398: #endif 5399: return MATCHnomatch; 5400: } 5401: 5402: void TypeDelegate::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod) 5403: { 5404: if (mod != this->mod) 5405: { toCBuffer3(buf, hgs, mod); 5406: return; 5407: } 5408: TypeFunction *tf = (TypeFunction *)next; 5409: 5410: tf->next->toCBuffer2(buf, hgs, 0); 5411: buf->writestring(" delegate"); 5412: Parameter::argsToCBuffer(buf, hgs, tf->parameters, tf->varargs); 5413: tf->attributesToCBuffer(buf, mod); 5414: } 5415: 5416: Expression *TypeDelegate::defaultInit(Loc loc) 5417: { 5418: #if LOGDEFAULTINIT 5419: printf("TypeDelegate::defaultInit() '%s'\n", toChars()); 5420: #endif 5421: return new NullExp(loc, this); 5422: } 5423: 5424: int TypeDelegate::isZeroInit(Loc loc) 5425: { 5426: return 1; 5427: } 5428: 5429: int TypeDelegate::checkBoolean() 5430: { 5431: return TRUE; 5432: } 5433: 5434: Expression *TypeDelegate::dotExp(Scope *sc, Expression *e, Identifier *ident) 5435: { 5436: #if LOGDOTEXP 5437: printf("TypeDelegate::dotExp(e = '%s', ident = '%s')\n", e->toChars(), ident->toChars()); 5438: #endif 5439: if (ident == Id::ptr) 5440: { 5441: e->type = tvoidptr; 5442: return e; 5443: } 5444: else if (ident == Id::funcptr) 5445: { 5446: e = e->addressOf(sc); 5447: e->type = tvoidptr; 5448: e = new AddExp(e->loc, e, new IntegerExp(PTRSIZE)); 5449: e->type = tvoidptr; 5450: e = new PtrExp(e->loc, e); 5451: e->type = next->pointerTo(); 5452: return e; 5453: } 5454: else 5455: { 5456: e = Type::dotExp(sc, e, ident); 5457: } 5458: return e; 5459: } 5460: 5461: int TypeDelegate::hasPointers() 5462: { 5463: return TRUE; 5464: } 5465: 5466: 5467: 5468: /***************************** TypeQualified *****************************/ 5469: 5470: TypeQualified::TypeQualified(TY ty, Loc loc) 5471: : Type(ty) 5472: { 5473: this->loc = loc; 5474: } 5475: 5476: void TypeQualified::syntaxCopyHelper(TypeQualified *t) 5477: { 5478: //printf("TypeQualified::syntaxCopyHelper(%s) %s\n", t->toChars(), toChars()); 5479: idents.setDim(t->idents.dim); 5480: for (int i = 0; i < idents.dim; i++)
warning C4018: '<' : signed/unsigned mismatch
5481: { 5482: Identifier *id = t->idents.tdata()[i]; 5483: if (id->dyncast() == DYNCAST_DSYMBOL) 5484: { 5485: TemplateInstance *ti = (TemplateInstance *)id; 5486: 5487: ti = (TemplateInstance *)ti->syntaxCopy(NULL); 5488: id = (Identifier *)ti; 5489: } 5490: idents.tdata()[i] = id; 5491: } 5492: } 5493: 5494: 5495: void TypeQualified::addIdent(Identifier *ident) 5496: { 5497: idents.push(ident); 5498: } 5499: 5500: void TypeQualified::toCBuffer2Helper(OutBuffer *buf, HdrGenState *hgs) 5501: { 5502: int i; 5503: 5504: for (i = 0; i < idents.dim; i++)
warning C4018: '<' : signed/unsigned mismatch
5505: { Identifier *id = idents.tdata()[i]; 5506: 5507: buf->writeByte('.'); 5508: 5509: if (id->dyncast() == DYNCAST_DSYMBOL) 5510: { 5511: TemplateInstance *ti = (TemplateInstance *)id; 5512: ti->toCBuffer(buf, hgs); 5513: } 5514: else 5515: buf->writestring(id->toChars()); 5516: } 5517: } 5518: 5519: d_uns64 TypeQualified::size(Loc loc) 5520: { 5521: error(this->loc, "size of type %s is not known", toChars()); 5522: return 1; 5523: } 5524: 5525: /************************************* 5526: * Takes an array of Identifiers and figures out if 5527: * it represents a Type or an Expression. 5528: * Output: 5529: * if expression, *pe is set 5530: * if type, *pt is set 5531: */ 5532: 5533: void TypeQualified::resolveHelper(Loc loc, Scope *sc, 5534: Dsymbol *s, Dsymbol *scopesym, 5535: Expression **pe, Type **pt, Dsymbol **ps) 5536: { 5537: VarDeclaration *v; 5538: FuncDeclaration *fd;
warning C4101: 'fd' : unreferenced local variable
5539: EnumMember *em; 5540: TupleDeclaration *td;
warning C4101: 'td' : unreferenced local variable
5541: Expression *e; 5542: 5543: #if 0 5544: printf("TypeQualified::resolveHelper(sc = %p, idents = '%s')\n", sc, toChars()); 5545: if (scopesym) 5546: printf("\tscopesym = '%s'\n", scopesym->toChars()); 5547: #endif 5548: *pe = NULL; 5549: *pt = NULL; 5550: *ps = NULL; 5551: if (s) 5552: { 5553: //printf("\t1: s = '%s' %p, kind = '%s'\n",s->toChars(), s, s->kind()); 5554: s->checkDeprecated(loc, sc); // check for deprecated aliases 5555: s = s->toAlias(); 5556: //printf("\t2: s = '%s' %p, kind = '%s'\n",s->toChars(), s, s->kind()); 5557: for (int i = 0; i < idents.dim; i++)
warning C4018: '<' : signed/unsigned mismatch
5558: { 5559: Identifier *id = idents.tdata()[i]; 5560: Dsymbol *sm = s->searchX(loc, sc, id); 5561: //printf("\t3: s = '%s' %p, kind = '%s'\n",s->toChars(), s, s->kind()); 5562: //printf("\tgetType = '%s'\n", s->getType()->toChars()); 5563: if (!sm) 5564: { Type *t; 5565: 5566: v = s->isVarDeclaration(); 5567: if (v && id == Id::length) 5568: { 5569: e = v->getConstInitializer(); 5570: if (!e) 5571: e = new VarExp(loc, v); 5572: t = e->type; 5573: if (!t) 5574: goto Lerror; 5575: goto L3; 5576: } 5577: else if (v && id == Id::stringof) 5578: { 5579: e = new DsymbolExp(loc, s, 0); 5580: do 5581: { 5582: id = idents.tdata()[i]; 5583: e = new DotIdExp(loc, e, id); 5584: } while (++i < idents.dim);
warning C4018: '<' : signed/unsigned mismatch
5585: e = e->semantic(sc); 5586: *pe = e; 5587: return; 5588: } 5589: 5590: t = s->getType(); 5591: if (!t && s->isDeclaration()) 5592: t = s->isDeclaration()->type; 5593: if (t) 5594: { 5595: sm = t->toDsymbol(sc); 5596: if (sm) 5597: { sm = sm->search(loc, id, 0); 5598: if (sm) 5599: goto L2; 5600: } 5601: //e = t->getProperty(loc, id); 5602: e = new TypeExp(loc, t); 5603: e = t->dotExp(sc, e, id); 5604: i++; 5605: L3: 5606: for (; i < idents.dim; i++)
warning C4018: '<' : signed/unsigned mismatch
5607: { 5608: id = idents.tdata()[i]; 5609: //printf("e: '%s', id: '%s', type = %p\n", e->toChars(), id->toChars(), e->type); 5610: if (id == Id::offsetof || !e->type) 5611: { e = new DotIdExp(e->loc, e, id); 5612: e = e->semantic(sc); 5613: } 5614: else 5615: e = e->type->dotExp(sc, e, id); 5616: } 5617: *pe = e; 5618: } 5619: else 5620: { 5621: Lerror: 5622: error(loc, "identifier '%s' of '%s' is not defined", id->toChars(), toChars()); 5623: *pe = new ErrorExp(); 5624: } 5625: return; 5626: } 5627: L2: 5628: s = sm->toAlias(); 5629: } 5630: 5631: v = s->isVarDeclaration(); 5632: if (v) 5633: { 5634: *pe = new VarExp(loc, v); 5635: return; 5636: } 5637: #if 0 5638: fd = s->isFuncDeclaration(); 5639: if (fd) 5640: { 5641: *pe = new DsymbolExp(loc, fd, 1); 5642: return; 5643: } 5644: #endif 5645: em = s->isEnumMember(); 5646: if (em) 5647: { 5648: // It's not a type, it's an expression 5649: *pe = em->value->copy(); 5650: return; 5651: } 5652: 5653: L1: 5654: Type *t = s->getType(); 5655: if (!t) 5656: { 5657: // If the symbol is an import, try looking inside the import 5658: Import *si; 5659: 5660: si = s->isImport(); 5661: if (si) 5662: { 5663: s = si->search(loc, s->ident, 0); 5664: if (s && s != si) 5665: goto L1; 5666: s = si; 5667: } 5668: *ps = s; 5669: return; 5670: } 5671: if (t->ty == Tinstance && t != this && !t->deco) 5672: { error(loc, "forward reference to '%s'", t->toChars()); 5673: return; 5674: } 5675: 5676: if (t != this) 5677: { 5678: if (t->reliesOnTident()) 5679: { 5680: if (s->scope) 5681: t = t->semantic(loc, s->scope); 5682: else 5683: { 5684: /* Attempt to find correct scope in which to evaluate t. 5685: * Not sure if this is right or not, or if we should just 5686: * give forward reference error if s->scope is not set. 5687: */ 5688: for (Scope *scx = sc; 1; scx = scx->enclosing) 5689: { 5690: if (!scx) 5691: { error(loc, "forward reference to '%s'", t->toChars()); 5692: return; 5693: } 5694: if (scx->scopesym == scopesym) 5695: { 5696: t = t->semantic(loc, scx); 5697: break; 5698: } 5699: } 5700: } 5701: } 5702: } 5703: if (t->ty == Ttuple) 5704: *pt = t; 5705: else 5706: *pt = t->merge(); 5707: } 5708: if (!s) 5709: { 5710: const char *p = toChars(); 5711: const char *n = importHint(p); 5712: if (n) 5713: error(loc, "'%s' is not defined, perhaps you need to import %s; ?", p, n); 5714: else 5715: { 5716: Identifier *id = new Identifier(p, TOKidentifier); 5717: s = sc->search_correct(id); 5718: if (s) 5719: error(loc, "undefined identifier %s, did you mean %s %s?", p, s->kind(), s->toChars()); 5720: else 5721: error(loc, "undefined identifier %s", p); 5722: } 5723: *pt = Type::terror; 5724: } 5725: } 5726: 5727: /***************************** TypeIdentifier *****************************/ 5728: 5729: TypeIdentifier::TypeIdentifier(Loc loc, Identifier *ident) 5730: : TypeQualified(Tident, loc) 5731: { 5732: this->ident = ident; 5733: } 5734: 5735: 5736: Type *TypeIdentifier::syntaxCopy() 5737: { 5738: TypeIdentifier *t; 5739: 5740: t = new TypeIdentifier(loc, ident); 5741: t->syntaxCopyHelper(this); 5742: t->mod = mod; 5743: return t; 5744: } 5745: 5746: void TypeIdentifier::toDecoBuffer(OutBuffer *buf, int flag) 5747: { unsigned len; 5748: char *name; 5749: 5750: Type::toDecoBuffer(buf, flag); 5751: name = ident->toChars(); 5752: len = strlen(name); 5753: buf->printf("%d%s", len, name); 5754: } 5755: 5756: void TypeIdentifier::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod) 5757: { 5758: if (mod != this->mod) 5759: { toCBuffer3(buf, hgs, mod); 5760: return; 5761: } 5762: buf->writestring(this->ident->toChars()); 5763: toCBuffer2Helper(buf, hgs); 5764: } 5765: 5766: /************************************* 5767: * Takes an array of Identifiers and figures out if 5768: * it represents a Type or an Expression. 5769: * Output: 5770: * if expression, *pe is set 5771: * if type, *pt is set 5772: */ 5773: 5774: void TypeIdentifier::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps) 5775: { 5776: Dsymbol *scopesym; 5777: 5778: //printf("TypeIdentifier::resolve(sc = %p, idents = '%s')\n", sc, toChars()); 5779: Dsymbol *s = sc->search(loc, ident, &scopesym); 5780: resolveHelper(loc, sc, s, scopesym, pe, pt, ps); 5781: if (*pt) 5782: (*pt) = (*pt)->addMod(mod); 5783: } 5784: 5785: /***************************************** 5786: * See if type resolves to a symbol, if so, 5787: * return that symbol. 5788: */ 5789: 5790: Dsymbol *TypeIdentifier::toDsymbol(Scope *sc) 5791: { 5792: //printf("TypeIdentifier::toDsymbol('%s')\n", toChars()); 5793: if (!sc) 5794: return NULL; 5795: //printf("ident = '%s'\n", ident->toChars()); 5796: 5797: Dsymbol *scopesym; 5798: Dsymbol *s = sc->search(loc, ident, &scopesym); 5799: if (s) 5800: { 5801: for (int i = 0; i < idents.dim; i++)
warning C4018: '<' : signed/unsigned mismatch
5802: { 5803: Identifier *id = idents.tdata()[i]; 5804: s = s->searchX(loc, sc, id); 5805: if (!s) // failed to find a symbol 5806: { //printf("\tdidn't find a symbol\n"); 5807: break; 5808: } 5809: } 5810: } 5811: return s; 5812: } 5813: 5814: Type *TypeIdentifier::semantic(Loc loc, Scope *sc) 5815: { 5816: Type *t; 5817: Expression *e; 5818: Dsymbol *s; 5819: 5820: //printf("TypeIdentifier::semantic(%s)\n", toChars()); 5821: resolve(loc, sc, &e, &t, &s); 5822: if (t) 5823: { 5824: //printf("\tit's a type %d, %s, %s\n", t->ty, t->toChars(), t->deco); 5825: 5826: if (t->ty == Ttypedef) 5827: { TypeTypedef *tt = (TypeTypedef *)t; 5828: 5829: if (tt->sym->sem == 1) 5830: error(loc, "circular reference of typedef %s", tt->toChars()); 5831: } 5832: t = t->addMod(mod); 5833: } 5834: else 5835: { 5836: #ifdef DEBUG 5837: if (!global.gag) 5838: printf("1: "); 5839: #endif 5840: if (s) 5841: { 5842: s->error(loc, "is used as a type"); 5843: //halt(); 5844: } 5845: else 5846: error(loc, "%s is used as a type", toChars()); 5847: t = terror; 5848: } 5849: //t->print(); 5850: return t; 5851: } 5852: 5853: Type *TypeIdentifier::reliesOnTident() 5854: { 5855: return this; 5856: } 5857: 5858: Expression *TypeIdentifier::toExpression() 5859: { 5860: Expression *e = new IdentifierExp(loc, ident); 5861: for (int i = 0; i < idents.dim; i++)
warning C4018: '<' : signed/unsigned mismatch
5862: { 5863: Identifier *id = idents.tdata()[i]; 5864: e = new DotIdExp(loc, e, id); 5865: } 5866: 5867: return e; 5868: } 5869: 5870: /***************************** TypeInstance *****************************/ 5871: 5872: TypeInstance::TypeInstance(Loc loc, TemplateInstance *tempinst) 5873: : TypeQualified(Tinstance, loc) 5874: { 5875: this->tempinst = tempinst; 5876: } 5877: 5878: Type *TypeInstance::syntaxCopy() 5879: { 5880: //printf("TypeInstance::syntaxCopy() %s, %d\n", toChars(), idents.dim); 5881: TypeInstance *t; 5882: 5883: t = new TypeInstance(loc, (TemplateInstance *)tempinst->syntaxCopy(NULL)); 5884: t->syntaxCopyHelper(this); 5885: t->mod = mod; 5886: return t; 5887: } 5888: 5889: 5890: void TypeInstance::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod) 5891: { 5892: if (mod != this->mod) 5893: { toCBuffer3(buf, hgs, mod); 5894: return; 5895: } 5896: tempinst->toCBuffer(buf, hgs); 5897: toCBuffer2Helper(buf, hgs); 5898: } 5899: 5900: void TypeInstance::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps) 5901: { 5902: // Note close similarity to TypeIdentifier::resolve() 5903: 5904: Dsymbol *s; 5905: 5906: *pe = NULL; 5907: *pt = NULL; 5908: *ps = NULL; 5909: 5910: #if 0 5911: if (!idents.dim) 5912: { 5913: error(loc, "template instance '%s' has no identifier", toChars()); 5914: return; 5915: } 5916: #endif 5917: //id = (Identifier *)idents.data[0]; 5918: //printf("TypeInstance::resolve(sc = %p, idents = '%s')\n", sc, id->toChars()); 5919: s = tempinst; 5920: if (s) 5921: s->semantic(sc); 5922: resolveHelper(loc, sc, s, NULL, pe, pt, ps); 5923: if (*pt) 5924: *pt = (*pt)->addMod(mod); 5925: //printf("pt = '%s'\n", (*pt)->toChars()); 5926: } 5927: 5928: Type *TypeInstance::semantic(Loc loc, Scope *sc) 5929: { 5930: Type *t; 5931: Expression *e; 5932: Dsymbol *s; 5933: 5934: //printf("TypeInstance::semantic(%s)\n", toChars()); 5935: 5936: if (sc->parameterSpecialization) 5937: { 5938: unsigned errors = global.errors; 5939: global.gag++; 5940: 5941: resolve(loc, sc, &e, &t, &s); 5942: 5943: global.gag--; 5944: if (errors != global.errors) 5945: { if (global.gag == 0) 5946: global.errors = errors; 5947: return this; 5948: } 5949: } 5950: else 5951: resolve(loc, sc, &e, &t, &s); 5952: 5953: if (!t) 5954: { 5955: error(loc, "%s is used as a type", toChars()); 5956: t = terror; 5957: } 5958: return t; 5959: } 5960: 5961: Dsymbol *TypeInstance::toDsymbol(Scope *sc) 5962: { 5963: Type *t; 5964: Expression *e; 5965: Dsymbol *s; 5966: 5967: //printf("TypeInstance::semantic(%s)\n", toChars()); 5968: 5969: if (sc->parameterSpecialization) 5970: { 5971: unsigned errors = global.errors; 5972: global.gag++; 5973: 5974: resolve(loc, sc, &e, &t, &s); 5975: 5976: global.gag--; 5977: if (errors != global.errors) 5978: { if (global.gag == 0) 5979: global.errors = errors; 5980: return NULL; 5981: } 5982: } 5983: else 5984: resolve(loc, sc, &e, &t, &s); 5985: 5986: return s; 5987: } 5988: 5989: 5990: /***************************** TypeTypeof *****************************/ 5991: 5992: TypeTypeof::TypeTypeof(Loc loc, Expression *exp) 5993: : TypeQualified(Ttypeof, loc) 5994: { 5995: this->exp = exp; 5996: inuse = 0; 5997: } 5998: 5999: Type *TypeTypeof::syntaxCopy() 6000: { 6001: //printf("TypeTypeof::syntaxCopy() %s\n", toChars()); 6002: TypeTypeof *t; 6003: 6004: t = new TypeTypeof(loc, exp->syntaxCopy()); 6005: t->syntaxCopyHelper(this); 6006: t->mod = mod; 6007: return t; 6008: } 6009: 6010: Dsymbol *TypeTypeof::toDsymbol(Scope *sc) 6011: { 6012: Type *t; 6013: 6014: t = semantic(loc, sc); 6015: if (t == this) 6016: return NULL; 6017: return t->toDsymbol(sc); 6018: } 6019: 6020: void TypeTypeof::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod) 6021: { 6022: if (mod != this->mod) 6023: { toCBuffer3(buf, hgs, mod); 6024: return; 6025: } 6026: buf->writestring("typeof("); 6027: exp->toCBuffer(buf, hgs); 6028: buf->writeByte(')'); 6029: toCBuffer2Helper(buf, hgs); 6030: } 6031: 6032: Type *TypeTypeof::semantic(Loc loc, Scope *sc) 6033: { Expression *e;
warning C4101: 'e' : unreferenced local variable
6034: Type *t; 6035: 6036: //printf("TypeTypeof::semantic() %s\n", toChars()); 6037: 6038: //static int nest; if (++nest == 50) *(char*)0=0; 6039: if (inuse) 6040: { 6041: inuse = 2; 6042: error(loc, "circular typeof definition"); 6043: return Type::terror; 6044: } 6045: inuse++; 6046: 6047: #if 0 6048: /* Special case for typeof(this) and typeof(super) since both 6049: * should work even if they are not inside a non-static member function 6050: */ 6051: if (exp->op == TOKthis || exp->op == TOKsuper) 6052: { 6053: // Find enclosing struct or class 6054: for (Dsymbol *s = sc->parent; 1; s = s->parent) 6055: { 6056: ClassDeclaration *cd; 6057: StructDeclaration *sd; 6058: 6059: if (!s) 6060: { 6061: error(loc, "%s is not in a struct or class scope", exp->toChars()); 6062: goto Lerr; 6063: } 6064: cd = s->isClassDeclaration(); 6065: if (cd) 6066: { 6067: if (exp->op == TOKsuper) 6068: { 6069: cd = cd->baseClass; 6070: if (!cd) 6071: { error(loc, "class %s has no 'super'", s->toChars()); 6072: goto Lerr; 6073: } 6074: } 6075: t = cd->type; 6076: break; 6077: } 6078: sd = s->isStructDeclaration(); 6079: if (sd) 6080: { 6081: if (exp->op == TOKsuper) 6082: { 6083: error(loc, "struct %s has no 'super'", sd->toChars()); 6084: goto Lerr; 6085: } 6086: t = sd->type->pointerTo(); 6087: break; 6088: } 6089: } 6090: } 6091: else 6092: #endif 6093: { 6094: Scope *sc2 = sc->push(); 6095: sc2->intypeof++; 6096: exp = exp->semantic(sc2); 6097: #if DMDV2 6098: if (exp->type && exp->type->ty == Tfunction && 6099: ((TypeFunction *)exp->type)->isproperty) 6100: exp = resolveProperties(sc2, exp); 6101: #endif 6102: sc2->pop(); 6103: if (exp->op == TOKtype) 6104: { 6105: error(loc, "argument %s to typeof is not an expression", exp->toChars()); 6106: goto Lerr; 6107: } 6108: t = exp->type; 6109: if (!t) 6110: { 6111: error(loc, "expression (%s) has no type", exp->toChars()); 6112: goto Lerr; 6113: } 6114: if (t->ty == Ttypeof) 6115: { error(loc, "forward reference to %s", toChars()); 6116: goto Lerr; 6117: } 6118: 6119: /* typeof should reflect the true type, 6120: * not what 'auto' would have gotten us. 6121: */ 6122: //t = t->toHeadMutable(); 6123: } 6124: if (idents.dim) 6125: { 6126: Dsymbol *s = t->toDsymbol(sc); 6127: for (size_t i = 0; i < idents.dim; i++) 6128: { 6129: if (!s) 6130: break; 6131: Identifier *id = idents.tdata()[i]; 6132: s = s->searchX(loc, sc, id); 6133: } 6134: 6135: if (s) 6136: { 6137: t = s->getType(); 6138: if (!t) 6139: { error(loc, "%s is not a type", s->toChars()); 6140: goto Lerr; 6141: } 6142: } 6143: else 6144: { error(loc, "cannot resolve .property for %s", toChars()); 6145: goto Lerr; 6146: } 6147: } 6148: inuse--; 6149: return t; 6150: 6151: Lerr: 6152: inuse--; 6153: return terror; 6154: } 6155: 6156: d_uns64 TypeTypeof::size(Loc loc) 6157: { 6158: if (exp->type) 6159: return exp->type->size(loc); 6160: else 6161: return TypeQualified::size(loc); 6162: } 6163: 6164: 6165: 6166: /***************************** TypeReturn *****************************/ 6167: 6168: TypeReturn::TypeReturn(Loc loc) 6169: : TypeQualified(Treturn, loc) 6170: { 6171: } 6172: 6173: Type *TypeReturn::syntaxCopy() 6174: { 6175: TypeReturn *t = new TypeReturn(loc); 6176: t->syntaxCopyHelper(this); 6177: t->mod = mod; 6178: return t; 6179: } 6180: 6181: Dsymbol *TypeReturn::toDsymbol(Scope *sc) 6182: { 6183: Type *t = semantic(0, sc); 6184: if (t == this) 6185: return NULL; 6186: return t->toDsymbol(sc); 6187: } 6188: 6189: Type *TypeReturn::semantic(Loc loc, Scope *sc) 6190: { 6191: Type *t; 6192: if (!sc->func) 6193: { error(loc, "typeof(return) must be inside function"); 6194: goto Lerr; 6195: } 6196: t = sc->func->type->nextOf(); 6197: if (!t) 6198: { 6199: error(loc, "cannot use typeof(return) inside function %s with inferred return type", sc->func->toChars()); 6200: goto Lerr; 6201: } 6202: t = t->addMod(mod); 6203: 6204: if (idents.dim) 6205: { 6206: Dsymbol *s = t->toDsymbol(sc); 6207: for (size_t i = 0; i < idents.dim; i++) 6208: { 6209: if (!s) 6210: break; 6211: Identifier *id = idents.tdata()[i]; 6212: s = s->searchX(loc, sc, id); 6213: } 6214: if (s) 6215: { 6216: t = s->getType(); 6217: if (!t) 6218: { error(loc, "%s is not a type", s->toChars()); 6219: goto Lerr; 6220: } 6221: } 6222: else 6223: { error(loc, "cannot resolve .property for %s", toChars()); 6224: goto Lerr; 6225: } 6226: } 6227: return t; 6228: 6229: Lerr: 6230: return terror; 6231: } 6232: 6233: void TypeReturn::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod) 6234: { 6235: if (mod != this->mod) 6236: { toCBuffer3(buf, hgs, mod); 6237: return; 6238: } 6239: buf->writestring("typeof(return)"); 6240: toCBuffer2Helper(buf, hgs); 6241: } 6242: 6243: 6244: /***************************** TypeEnum *****************************/ 6245: 6246: TypeEnum::TypeEnum(EnumDeclaration *sym) 6247: : Type(Tenum) 6248: { 6249: this->sym = sym; 6250: } 6251: 6252: char *TypeEnum::toChars(<