1 /** 2 * Compiler implementation of the 3 * $(LINK2 http://www.dlang.org, D programming language). 4 * 5 * Copyright: Copyright (c) 1999-2016 by Digital Mars, All Rights Reserved 6 * Authors: $(LINK2 http://www.digitalmars.com, Walter Bright) 7 * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) 8 * Source: $(DMDSRC _mtype.d) 9 */ 10 11 module ddmd.mtype; 12 13 import core.checkedint; 14 import core.stdc.stdarg; 15 import core.stdc.stdio; 16 import core.stdc.stdlib; 17 import core.stdc..string; 18 19 import ddmd.access; 20 import ddmd.aggregate; 21 import ddmd.aliasthis; 22 import ddmd.arrayop; 23 import ddmd.arraytypes; 24 import ddmd.gluelayer; 25 import ddmd.complex; 26 import ddmd.dcast; 27 import ddmd.dclass; 28 import ddmd.declaration; 29 import ddmd.denum; 30 import ddmd.dimport; 31 import ddmd.dmangle; 32 import ddmd.dscope; 33 import ddmd.dstruct; 34 import ddmd.dsymbol; 35 import ddmd.dtemplate; 36 import ddmd.errors; 37 import ddmd.expression; 38 import ddmd.func; 39 import ddmd.globals; 40 import ddmd.hdrgen; 41 import ddmd.id; 42 import ddmd.identifier; 43 import ddmd.imphint; 44 import ddmd.init; 45 import ddmd.opover; 46 import ddmd.root.ctfloat; 47 import ddmd.root.outbuffer; 48 import ddmd.root.rmem; 49 import ddmd.root.rootobject; 50 import ddmd.root.stringtable; 51 import ddmd.sideeffect; 52 import ddmd.target; 53 import ddmd.tokens; 54 import ddmd.visitor; 55 56 enum LOGDOTEXP = 0; // log ::dotExp() 57 enum LOGDEFAULTINIT = 0; // log ::defaultInit() 58 59 extern (C++) __gshared int Tsize_t = Tuns32; 60 extern (C++) __gshared int Tptrdiff_t = Tint32; 61 62 enum SIZE_INVALID = (~cast(d_uns64)0); // error return from size() functions 63 64 65 /*************************** 66 * Return !=0 if modfrom can be implicitly converted to modto 67 */ 68 bool MODimplicitConv(MOD modfrom, MOD modto) pure nothrow @nogc @safe 69 { 70 if (modfrom == modto) 71 return true; 72 73 //printf("MODimplicitConv(from = %x, to = %x)\n", modfrom, modto); 74 auto X(T, U)(T m, U n) 75 { 76 return ((m << 4) | n); 77 } 78 79 switch (X(modfrom & ~MODshared, modto & ~MODshared)) 80 { 81 case X(0, MODconst): 82 case X(MODwild, MODconst): 83 case X(MODwild, MODwildconst): 84 case X(MODwildconst, MODconst): 85 return (modfrom & MODshared) == (modto & MODshared); 86 87 case X(MODimmutable, MODconst): 88 case X(MODimmutable, MODwildconst): 89 return true; 90 default: 91 return false; 92 } 93 } 94 95 /*************************** 96 * Return MATCHexact or MATCHconst if a method of type '() modfrom' can call a method of type '() modto'. 97 */ 98 MATCH MODmethodConv(MOD modfrom, MOD modto) pure nothrow @nogc @safe 99 { 100 if (modfrom == modto) 101 return MATCHexact; 102 if (MODimplicitConv(modfrom, modto)) 103 return MATCHconst; 104 105 auto X(T, U)(T m, U n) 106 { 107 return ((m << 4) | n); 108 } 109 110 switch (X(modfrom, modto)) 111 { 112 case X(0, MODwild): 113 case X(MODimmutable, MODwild): 114 case X(MODconst, MODwild): 115 case X(MODwildconst, MODwild): 116 case X(MODshared, MODshared | MODwild): 117 case X(MODshared | MODimmutable, MODshared | MODwild): 118 case X(MODshared | MODconst, MODshared | MODwild): 119 case X(MODshared | MODwildconst, MODshared | MODwild): 120 return MATCHconst; 121 122 default: 123 return MATCHnomatch; 124 } 125 } 126 127 /*************************** 128 * Merge mod bits to form common mod. 129 */ 130 MOD MODmerge(MOD mod1, MOD mod2) pure nothrow @nogc @safe 131 { 132 if (mod1 == mod2) 133 return mod1; 134 135 //printf("MODmerge(1 = %x, 2 = %x)\n", mod1, mod2); 136 MOD result = 0; 137 if ((mod1 | mod2) & MODshared) 138 { 139 // If either type is shared, the result will be shared 140 result |= MODshared; 141 mod1 &= ~MODshared; 142 mod2 &= ~MODshared; 143 } 144 if (mod1 == 0 || mod1 == MODmutable || mod1 == MODconst || mod2 == 0 || mod2 == MODmutable || mod2 == MODconst) 145 { 146 // If either type is mutable or const, the result will be const. 147 result |= MODconst; 148 } 149 else 150 { 151 // MODimmutable vs MODwild 152 // MODimmutable vs MODwildconst 153 // MODwild vs MODwildconst 154 assert(mod1 & MODwild || mod2 & MODwild); 155 result |= MODwildconst; 156 } 157 return result; 158 } 159 160 /********************************* 161 * Store modifier name into buf. 162 */ 163 void MODtoBuffer(OutBuffer* buf, MOD mod) 164 { 165 switch (mod) 166 { 167 case 0: 168 break; 169 170 case MODimmutable: 171 buf.writestring(Token.toString(TOKimmutable)); 172 break; 173 174 case MODshared: 175 buf.writestring(Token.toString(TOKshared)); 176 break; 177 178 case MODshared | MODconst: 179 buf.writestring(Token.toString(TOKshared)); 180 buf.writeByte(' '); 181 goto case; /+ fall through +/ 182 case MODconst: 183 buf.writestring(Token.toString(TOKconst)); 184 break; 185 186 case MODshared | MODwild: 187 buf.writestring(Token.toString(TOKshared)); 188 buf.writeByte(' '); 189 goto case; /+ fall through +/ 190 case MODwild: 191 buf.writestring(Token.toString(TOKwild)); 192 break; 193 194 case MODshared | MODwildconst: 195 buf.writestring(Token.toString(TOKshared)); 196 buf.writeByte(' '); 197 goto case; /+ fall through +/ 198 case MODwildconst: 199 buf.writestring(Token.toString(TOKwild)); 200 buf.writeByte(' '); 201 buf.writestring(Token.toString(TOKconst)); 202 break; 203 204 default: 205 assert(0); 206 } 207 } 208 209 /********************************* 210 * Return modifier name. 211 */ 212 char* MODtoChars(MOD mod) 213 { 214 OutBuffer buf; 215 buf.reserve(16); 216 MODtoBuffer(&buf, mod); 217 return buf.extractString(); 218 } 219 220 /************************************ 221 * Convert MODxxxx to STCxxx 222 */ 223 StorageClass ModToStc(uint mod) pure nothrow @nogc @safe 224 { 225 StorageClass stc = 0; 226 if (mod & MODimmutable) 227 stc |= STCimmutable; 228 if (mod & MODconst) 229 stc |= STCconst; 230 if (mod & MODwild) 231 stc |= STCwild; 232 if (mod & MODshared) 233 stc |= STCshared; 234 return stc; 235 } 236 237 /************************************ 238 * Strip all parameter's idenfiers and their default arguments for merging types. 239 * If some of parameter types or return type are function pointer, delegate, or 240 * the types which contains either, then strip also from them. 241 */ 242 private Type stripDefaultArgs(Type t) 243 { 244 static Parameters* stripParams(Parameters* parameters) 245 { 246 Parameters* params = parameters; 247 if (params && params.dim > 0) 248 { 249 foreach (i; 0 .. params.dim) 250 { 251 Parameter p = (*params)[i]; 252 Type ta = stripDefaultArgs(p.type); 253 if (ta != p.type || p.defaultArg || p.ident) 254 { 255 if (params == parameters) 256 { 257 params = new Parameters(); 258 params.setDim(parameters.dim); 259 foreach (j; 0 .. params.dim) 260 (*params)[j] = (*parameters)[j]; 261 } 262 (*params)[i] = new Parameter(p.storageClass, ta, null, null); 263 } 264 } 265 } 266 return params; 267 } 268 269 if (t is null) 270 return t; 271 272 if (t.ty == Tfunction) 273 { 274 TypeFunction tf = cast(TypeFunction)t; 275 Type tret = stripDefaultArgs(tf.next); 276 Parameters* params = stripParams(tf.parameters); 277 if (tret == tf.next && params == tf.parameters) 278 goto Lnot; 279 tf = cast(TypeFunction)tf.copy(); 280 tf.parameters = params; 281 tf.next = tret; 282 //printf("strip %s\n <- %s\n", tf->toChars(), t->toChars()); 283 t = tf; 284 } 285 else if (t.ty == Ttuple) 286 { 287 TypeTuple tt = cast(TypeTuple)t; 288 Parameters* args = stripParams(tt.arguments); 289 if (args == tt.arguments) 290 goto Lnot; 291 t = t.copy(); 292 (cast(TypeTuple)t).arguments = args; 293 } 294 else if (t.ty == Tenum) 295 { 296 // TypeEnum::nextOf() may be != NULL, but it's not necessary here. 297 goto Lnot; 298 } 299 else 300 { 301 Type tn = t.nextOf(); 302 Type n = stripDefaultArgs(tn); 303 if (n == tn) 304 goto Lnot; 305 t = t.copy(); 306 (cast(TypeNext)t).next = n; 307 } 308 //printf("strip %s\n", t->toChars()); 309 Lnot: 310 return t; 311 } 312 313 enum TFLAGSintegral = 1; 314 enum TFLAGSfloating = 2; 315 enum TFLAGSunsigned = 4; 316 enum TFLAGSreal = 8; 317 enum TFLAGSimaginary = 0x10; 318 enum TFLAGScomplex = 0x20; 319 320 private Expression semanticLength(Scope* sc, TupleDeclaration tup, Expression exp) 321 { 322 ScopeDsymbol sym = new ArrayScopeSymbol(sc, tup); 323 sym.parent = sc.scopesym; 324 325 sc = sc.push(sym); 326 sc = sc.startCTFE(); 327 exp = exp.semantic(sc); 328 sc = sc.endCTFE(); 329 sc.pop(); 330 331 return exp; 332 } 333 334 /************************** 335 * This evaluates exp while setting length to be the number 336 * of elements in the tuple t. 337 */ 338 private Expression semanticLength(Scope* sc, Type t, Expression exp) 339 { 340 if (t.ty == Ttuple) 341 { 342 ScopeDsymbol sym = new ArrayScopeSymbol(sc, cast(TypeTuple)t); 343 sym.parent = sc.scopesym; 344 sc = sc.push(sym); 345 sc = sc.startCTFE(); 346 exp = exp.semantic(sc); 347 sc = sc.endCTFE(); 348 sc.pop(); 349 } 350 else 351 { 352 sc = sc.startCTFE(); 353 exp = exp.semantic(sc); 354 sc = sc.endCTFE(); 355 } 356 return exp; 357 } 358 359 enum ENUMTY : int 360 { 361 Tarray, // slice array, aka T[] 362 Tsarray, // static array, aka T[dimension] 363 Taarray, // associative array, aka T[type] 364 Tpointer, 365 Treference, 366 Tfunction, 367 Tident, 368 Tclass, 369 Tstruct, 370 Tenum, 371 372 Tdelegate, 373 Tnone, 374 Tvoid, 375 Tint8, 376 Tuns8, 377 Tint16, 378 Tuns16, 379 Tint32, 380 Tuns32, 381 Tint64, 382 383 Tuns64, 384 Tfloat32, 385 Tfloat64, 386 Tfloat80, 387 Timaginary32, 388 Timaginary64, 389 Timaginary80, 390 Tcomplex32, 391 Tcomplex64, 392 Tcomplex80, 393 394 Tbool, 395 Tchar, 396 Twchar, 397 Tdchar, 398 Terror, 399 Tinstance, 400 Ttypeof, 401 Ttuple, 402 Tslice, 403 Treturn, 404 405 Tnull, 406 Tvector, 407 Tint128, 408 Tuns128, 409 TMAX, 410 } 411 412 alias Tarray = ENUMTY.Tarray; 413 alias Tsarray = ENUMTY.Tsarray; 414 alias Taarray = ENUMTY.Taarray; 415 alias Tpointer = ENUMTY.Tpointer; 416 alias Treference = ENUMTY.Treference; 417 alias Tfunction = ENUMTY.Tfunction; 418 alias Tident = ENUMTY.Tident; 419 alias Tclass = ENUMTY.Tclass; 420 alias Tstruct = ENUMTY.Tstruct; 421 alias Tenum = ENUMTY.Tenum; 422 alias Tdelegate = ENUMTY.Tdelegate; 423 alias Tnone = ENUMTY.Tnone; 424 alias Tvoid = ENUMTY.Tvoid; 425 alias Tint8 = ENUMTY.Tint8; 426 alias Tuns8 = ENUMTY.Tuns8; 427 alias Tint16 = ENUMTY.Tint16; 428 alias Tuns16 = ENUMTY.Tuns16; 429 alias Tint32 = ENUMTY.Tint32; 430 alias Tuns32 = ENUMTY.Tuns32; 431 alias Tint64 = ENUMTY.Tint64; 432 alias Tuns64 = ENUMTY.Tuns64; 433 alias Tfloat32 = ENUMTY.Tfloat32; 434 alias Tfloat64 = ENUMTY.Tfloat64; 435 alias Tfloat80 = ENUMTY.Tfloat80; 436 alias Timaginary32 = ENUMTY.Timaginary32; 437 alias Timaginary64 = ENUMTY.Timaginary64; 438 alias Timaginary80 = ENUMTY.Timaginary80; 439 alias Tcomplex32 = ENUMTY.Tcomplex32; 440 alias Tcomplex64 = ENUMTY.Tcomplex64; 441 alias Tcomplex80 = ENUMTY.Tcomplex80; 442 alias Tbool = ENUMTY.Tbool; 443 alias Tchar = ENUMTY.Tchar; 444 alias Twchar = ENUMTY.Twchar; 445 alias Tdchar = ENUMTY.Tdchar; 446 alias Terror = ENUMTY.Terror; 447 alias Tinstance = ENUMTY.Tinstance; 448 alias Ttypeof = ENUMTY.Ttypeof; 449 alias Ttuple = ENUMTY.Ttuple; 450 alias Tslice = ENUMTY.Tslice; 451 alias Treturn = ENUMTY.Treturn; 452 alias Tnull = ENUMTY.Tnull; 453 alias Tvector = ENUMTY.Tvector; 454 alias Tint128 = ENUMTY.Tint128; 455 alias Tuns128 = ENUMTY.Tuns128; 456 alias TMAX = ENUMTY.TMAX; 457 458 alias TY = ubyte; 459 460 enum MODFlags : int 461 { 462 MODconst = 1, // type is const 463 MODimmutable = 4, // type is immutable 464 MODshared = 2, // type is shared 465 MODwild = 8, // type is wild 466 MODwildconst = (MODwild | MODconst), // type is wild const 467 MODmutable = 0x10, // type is mutable (only used in wildcard matching) 468 } 469 470 alias MODconst = MODFlags.MODconst; 471 alias MODimmutable = MODFlags.MODimmutable; 472 alias MODshared = MODFlags.MODshared; 473 alias MODwild = MODFlags.MODwild; 474 alias MODwildconst = MODFlags.MODwildconst; 475 alias MODmutable = MODFlags.MODmutable; 476 477 alias MOD = ubyte; 478 479 /*********************************************************** 480 */ 481 extern (C++) abstract class Type : RootObject 482 { 483 TY ty; 484 MOD mod; // modifiers MODxxxx 485 char* deco; 486 487 /* These are cached values that are lazily evaluated by constOf(), immutableOf(), etc. 488 * They should not be referenced by anybody but mtype.c. 489 * They can be NULL if not lazily evaluated yet. 490 * Note that there is no "shared immutable", because that is just immutable 491 * Naked == no MOD bits 492 */ 493 Type cto; // MODconst ? naked version of this type : const version 494 Type ito; // MODimmutable ? naked version of this type : immutable version 495 Type sto; // MODshared ? naked version of this type : shared mutable version 496 Type scto; // MODshared | MODconst ? naked version of this type : shared const version 497 Type wto; // MODwild ? naked version of this type : wild version 498 Type wcto; // MODwildconst ? naked version of this type : wild const version 499 Type swto; // MODshared | MODwild ? naked version of this type : shared wild version 500 Type swcto; // MODshared | MODwildconst ? naked version of this type : shared wild const version 501 502 Type pto; // merged pointer to this type 503 Type rto; // reference to this type 504 Type arrayof; // array of this type 505 506 TypeInfoDeclaration vtinfo; // TypeInfo object for this Type 507 508 type* ctype; // for back end 509 510 extern (C++) static __gshared Type tvoid; 511 extern (C++) static __gshared Type tint8; 512 extern (C++) static __gshared Type tuns8; 513 extern (C++) static __gshared Type tint16; 514 extern (C++) static __gshared Type tuns16; 515 extern (C++) static __gshared Type tint32; 516 extern (C++) static __gshared Type tuns32; 517 extern (C++) static __gshared Type tint64; 518 extern (C++) static __gshared Type tuns64; 519 extern (C++) static __gshared Type tint128; 520 extern (C++) static __gshared Type tuns128; 521 extern (C++) static __gshared Type tfloat32; 522 extern (C++) static __gshared Type tfloat64; 523 extern (C++) static __gshared Type tfloat80; 524 extern (C++) static __gshared Type timaginary32; 525 extern (C++) static __gshared Type timaginary64; 526 extern (C++) static __gshared Type timaginary80; 527 extern (C++) static __gshared Type tcomplex32; 528 extern (C++) static __gshared Type tcomplex64; 529 extern (C++) static __gshared Type tcomplex80; 530 extern (C++) static __gshared Type tbool; 531 extern (C++) static __gshared Type tchar; 532 extern (C++) static __gshared Type twchar; 533 extern (C++) static __gshared Type tdchar; 534 535 // Some special types 536 extern (C++) static __gshared Type tshiftcnt; 537 extern (C++) static __gshared Type tvoidptr; // void* 538 extern (C++) static __gshared Type tstring; // immutable(char)[] 539 extern (C++) static __gshared Type twstring; // immutable(wchar)[] 540 extern (C++) static __gshared Type tdstring; // immutable(dchar)[] 541 extern (C++) static __gshared Type tvalist; // va_list alias 542 extern (C++) static __gshared Type terror; // for error recovery 543 extern (C++) static __gshared Type tnull; // for null type 544 545 extern (C++) static __gshared Type tsize_t; // matches size_t alias 546 extern (C++) static __gshared Type tptrdiff_t; // matches ptrdiff_t alias 547 extern (C++) static __gshared Type thash_t; // matches hash_t alias 548 549 extern (C++) static __gshared ClassDeclaration dtypeinfo; 550 extern (C++) static __gshared ClassDeclaration typeinfoclass; 551 extern (C++) static __gshared ClassDeclaration typeinfointerface; 552 extern (C++) static __gshared ClassDeclaration typeinfostruct; 553 extern (C++) static __gshared ClassDeclaration typeinfopointer; 554 extern (C++) static __gshared ClassDeclaration typeinfoarray; 555 extern (C++) static __gshared ClassDeclaration typeinfostaticarray; 556 extern (C++) static __gshared ClassDeclaration typeinfoassociativearray; 557 extern (C++) static __gshared ClassDeclaration typeinfovector; 558 extern (C++) static __gshared ClassDeclaration typeinfoenum; 559 extern (C++) static __gshared ClassDeclaration typeinfofunction; 560 extern (C++) static __gshared ClassDeclaration typeinfodelegate; 561 extern (C++) static __gshared ClassDeclaration typeinfotypelist; 562 extern (C++) static __gshared ClassDeclaration typeinfoconst; 563 extern (C++) static __gshared ClassDeclaration typeinfoinvariant; 564 extern (C++) static __gshared ClassDeclaration typeinfoshared; 565 extern (C++) static __gshared ClassDeclaration typeinfowild; 566 567 extern (C++) static __gshared TemplateDeclaration rtinfo; 568 569 extern (C++) static __gshared Type[TMAX] basic; 570 extern (C++) static __gshared StringTable stringtable; 571 572 extern (C++) static __gshared ubyte[TMAX] sizeTy = () 573 { 574 ubyte[TMAX] sizeTy = __traits(classInstanceSize, TypeBasic); 575 sizeTy[Tsarray] = __traits(classInstanceSize, TypeSArray); 576 sizeTy[Tarray] = __traits(classInstanceSize, TypeDArray); 577 sizeTy[Taarray] = __traits(classInstanceSize, TypeAArray); 578 sizeTy[Tpointer] = __traits(classInstanceSize, TypePointer); 579 sizeTy[Treference] = __traits(classInstanceSize, TypeReference); 580 sizeTy[Tfunction] = __traits(classInstanceSize, TypeFunction); 581 sizeTy[Tdelegate] = __traits(classInstanceSize, TypeDelegate); 582 sizeTy[Tident] = __traits(classInstanceSize, TypeIdentifier); 583 sizeTy[Tinstance] = __traits(classInstanceSize, TypeInstance); 584 sizeTy[Ttypeof] = __traits(classInstanceSize, TypeTypeof); 585 sizeTy[Tenum] = __traits(classInstanceSize, TypeEnum); 586 sizeTy[Tstruct] = __traits(classInstanceSize, TypeStruct); 587 sizeTy[Tclass] = __traits(classInstanceSize, TypeClass); 588 sizeTy[Ttuple] = __traits(classInstanceSize, TypeTuple); 589 sizeTy[Tslice] = __traits(classInstanceSize, TypeSlice); 590 sizeTy[Treturn] = __traits(classInstanceSize, TypeReturn); 591 sizeTy[Terror] = __traits(classInstanceSize, TypeError); 592 sizeTy[Tnull] = __traits(classInstanceSize, TypeNull); 593 sizeTy[Tvector] = __traits(classInstanceSize, TypeVector); 594 return sizeTy; 595 }(); 596 597 final extern (D) this(TY ty) 598 { 599 this.ty = ty; 600 } 601 602 const(char)* kind() const 603 { 604 assert(false); // should be overridden 605 } 606 607 final Type copy() 608 { 609 Type t = cast(Type)mem.xmalloc(sizeTy[ty]); 610 memcpy(cast(void*)t, cast(void*)this, sizeTy[ty]); 611 return t; 612 } 613 614 Type syntaxCopy() 615 { 616 print(); 617 fprintf(stderr, "ty = %d\n", ty); 618 assert(0); 619 } 620 621 override bool equals(RootObject o) 622 { 623 Type t = cast(Type)o; 624 //printf("Type::equals(%s, %s)\n", toChars(), t->toChars()); 625 // deco strings are unique 626 // and semantic() has been run 627 if (this == o || ((t && deco == t.deco) && deco !is null)) 628 { 629 //printf("deco = '%s', t->deco = '%s'\n", deco, t->deco); 630 return true; 631 } 632 //if (deco && t && t->deco) printf("deco = '%s', t->deco = '%s'\n", deco, t->deco); 633 return false; 634 } 635 636 final bool equivalent(Type t) 637 { 638 return immutableOf().equals(t.immutableOf()); 639 } 640 641 // kludge for template.isType() 642 override final int dyncast() 643 { 644 return DYNCAST_TYPE; 645 } 646 647 /******************************* 648 * Covariant means that 'this' can substitute for 't', 649 * i.e. a pure function is a match for an impure type. 650 * Returns: 651 * 0 types are distinct 652 * 1 this is covariant with t 653 * 2 arguments match as far as overloading goes, 654 * but types are not covariant 655 * 3 cannot determine covariance because of forward references 656 * *pstc STCxxxx which would make it covariant 657 */ 658 final int covariant(Type t, StorageClass* pstc = null) 659 { 660 version (none) 661 { 662 printf("Type::covariant(t = %s) %s\n", t.toChars(), toChars()); 663 printf("deco = %p, %p\n", deco, t.deco); 664 // printf("ty = %d\n", next->ty); 665 printf("mod = %x, %x\n", mod, t.mod); 666 } 667 if (pstc) 668 *pstc = 0; 669 StorageClass stc = 0; 670 671 int inoutmismatch = 0; 672 673 TypeFunction t1; 674 TypeFunction t2; 675 676 if (equals(t)) 677 return 1; // covariant 678 679 if (ty != Tfunction || t.ty != Tfunction) 680 goto Ldistinct; 681 682 t1 = cast(TypeFunction)this; 683 t2 = cast(TypeFunction)t; 684 685 if (t1.varargs != t2.varargs) 686 goto Ldistinct; 687 688 if (t1.parameters && t2.parameters) 689 { 690 size_t dim = Parameter.dim(t1.parameters); 691 if (dim != Parameter.dim(t2.parameters)) 692 goto Ldistinct; 693 694 for (size_t i = 0; i < dim; i++) 695 { 696 Parameter fparam1 = Parameter.getNth(t1.parameters, i); 697 Parameter fparam2 = Parameter.getNth(t2.parameters, i); 698 699 if (!fparam1.type.equals(fparam2.type)) 700 { 701 goto Ldistinct; 702 } 703 const(StorageClass) sc = STCref | STCin | STCout | STClazy; 704 if ((fparam1.storageClass & sc) != (fparam2.storageClass & sc)) 705 inoutmismatch = 1; 706 // We can add scope, but not subtract it 707 if (!(fparam1.storageClass & STCscope) && (fparam2.storageClass & STCscope)) 708 inoutmismatch = 1; 709 // We can subtract return, but not add it 710 if ((fparam1.storageClass & STCreturn) && !(fparam2.storageClass & STCreturn)) 711 inoutmismatch = 1; 712 } 713 } 714 else if (t1.parameters != t2.parameters) 715 { 716 size_t dim1 = !t1.parameters ? 0 : t1.parameters.dim; 717 size_t dim2 = !t2.parameters ? 0 : t2.parameters.dim; 718 if (dim1 || dim2) 719 goto Ldistinct; 720 } 721 722 // The argument lists match 723 if (inoutmismatch) 724 goto Lnotcovariant; 725 if (t1.linkage != t2.linkage) 726 goto Lnotcovariant; 727 728 { 729 // Return types 730 Type t1n = t1.next; 731 Type t2n = t2.next; 732 733 if (!t1n || !t2n) // happens with return type inference 734 goto Lnotcovariant; 735 736 if (t1n.equals(t2n)) 737 goto Lcovariant; 738 if (t1n.ty == Tclass && t2n.ty == Tclass) 739 { 740 /* If same class type, but t2n is const, then it's 741 * covariant. Do this test first because it can work on 742 * forward references. 743 */ 744 if ((cast(TypeClass)t1n).sym == (cast(TypeClass)t2n).sym && MODimplicitConv(t1n.mod, t2n.mod)) 745 goto Lcovariant; 746 747 // If t1n is forward referenced: 748 ClassDeclaration cd = (cast(TypeClass)t1n).sym; 749 if (cd._scope) 750 cd.semantic(null); 751 if (!cd.isBaseInfoComplete()) 752 { 753 return 3; // forward references 754 } 755 } 756 if (t1n.ty == Tstruct && t2n.ty == Tstruct) 757 { 758 if ((cast(TypeStruct)t1n).sym == (cast(TypeStruct)t2n).sym && MODimplicitConv(t1n.mod, t2n.mod)) 759 goto Lcovariant; 760 } 761 else if (t1n.ty == t2n.ty && t1n.implicitConvTo(t2n)) 762 goto Lcovariant; 763 else if (t1n.ty == Tnull && t1n.implicitConvTo(t2n) && t1n.size() == t2n.size()) 764 goto Lcovariant; 765 } 766 goto Lnotcovariant; 767 768 Lcovariant: 769 if (t1.isref != t2.isref) 770 goto Lnotcovariant; 771 772 // We can subtract 'return' from 'this', but cannot add it 773 if (t1.isreturn && !t2.isreturn) 774 goto Lnotcovariant; 775 776 /* Can convert mutable to const 777 */ 778 if (!MODimplicitConv(t2.mod, t1.mod)) 779 { 780 version (none) 781 { 782 //stop attribute inference with const 783 // If adding 'const' will make it covariant 784 if (MODimplicitConv(t2.mod, MODmerge(t1.mod, MODconst))) 785 stc |= STCconst; 786 else 787 goto Lnotcovariant; 788 } 789 else 790 { 791 goto Ldistinct; 792 } 793 } 794 795 /* Can convert pure to impure, nothrow to throw, and nogc to gc 796 */ 797 if (!t1.purity && t2.purity) 798 stc |= STCpure; 799 800 if (!t1.isnothrow && t2.isnothrow) 801 stc |= STCnothrow; 802 803 if (!t1.isnogc && t2.isnogc) 804 stc |= STCnogc; 805 806 /* Can convert safe/trusted to system 807 */ 808 if (t1.trust <= TRUSTsystem && t2.trust >= TRUSTtrusted) 809 { 810 // Should we infer trusted or safe? Go with safe. 811 stc |= STCsafe; 812 } 813 814 if (stc) 815 { 816 if (pstc) 817 *pstc = stc; 818 goto Lnotcovariant; 819 } 820 821 //printf("\tcovaraint: 1\n"); 822 return 1; 823 824 Ldistinct: 825 //printf("\tcovaraint: 0\n"); 826 return 0; 827 828 Lnotcovariant: 829 //printf("\tcovaraint: 2\n"); 830 return 2; 831 } 832 833 /******************************** 834 * For pretty-printing a type. 835 */ 836 final override const(char)* toChars() 837 { 838 OutBuffer buf; 839 buf.reserve(16); 840 HdrGenState hgs; 841 hgs.fullQual = (ty == Tclass && !mod); 842 843 .toCBuffer(this, &buf, null, &hgs); 844 return buf.extractString(); 845 } 846 847 final char* toPrettyChars(bool QualifyTypes = false) 848 { 849 OutBuffer buf; 850 buf.reserve(16); 851 HdrGenState hgs; 852 hgs.fullQual = QualifyTypes; 853 854 .toCBuffer(this, &buf, null, &hgs); 855 return buf.extractString(); 856 } 857 858 static void _init() 859 { 860 stringtable._init(14000); 861 862 // Set basic types 863 static __gshared TY* basetab = 864 [ 865 Tvoid, 866 Tint8, 867 Tuns8, 868 Tint16, 869 Tuns16, 870 Tint32, 871 Tuns32, 872 Tint64, 873 Tuns64, 874 Tint128, 875 Tuns128, 876 Tfloat32, 877 Tfloat64, 878 Tfloat80, 879 Timaginary32, 880 Timaginary64, 881 Timaginary80, 882 Tcomplex32, 883 Tcomplex64, 884 Tcomplex80, 885 Tbool, 886 Tchar, 887 Twchar, 888 Tdchar, 889 Terror 890 ]; 891 892 for (size_t i = 0; basetab[i] != Terror; i++) 893 { 894 Type t = new TypeBasic(basetab[i]); 895 t = t.merge(); 896 basic[basetab[i]] = t; 897 } 898 basic[Terror] = new TypeError(); 899 900 tvoid = basic[Tvoid]; 901 tint8 = basic[Tint8]; 902 tuns8 = basic[Tuns8]; 903 tint16 = basic[Tint16]; 904 tuns16 = basic[Tuns16]; 905 tint32 = basic[Tint32]; 906 tuns32 = basic[Tuns32]; 907 tint64 = basic[Tint64]; 908 tuns64 = basic[Tuns64]; 909 tint128 = basic[Tint128]; 910 tuns128 = basic[Tuns128]; 911 tfloat32 = basic[Tfloat32]; 912 tfloat64 = basic[Tfloat64]; 913 tfloat80 = basic[Tfloat80]; 914 915 timaginary32 = basic[Timaginary32]; 916 timaginary64 = basic[Timaginary64]; 917 timaginary80 = basic[Timaginary80]; 918 919 tcomplex32 = basic[Tcomplex32]; 920 tcomplex64 = basic[Tcomplex64]; 921 tcomplex80 = basic[Tcomplex80]; 922 923 tbool = basic[Tbool]; 924 tchar = basic[Tchar]; 925 twchar = basic[Twchar]; 926 tdchar = basic[Tdchar]; 927 928 tshiftcnt = tint32; 929 terror = basic[Terror]; 930 tnull = basic[Tnull]; 931 tnull = new TypeNull(); 932 tnull.deco = tnull.merge().deco; 933 934 tvoidptr = tvoid.pointerTo(); 935 tstring = tchar.immutableOf().arrayOf(); 936 twstring = twchar.immutableOf().arrayOf(); 937 tdstring = tdchar.immutableOf().arrayOf(); 938 tvalist = Target.va_listType(); 939 940 if (global.params.isLP64) 941 { 942 Tsize_t = Tuns64; 943 Tptrdiff_t = Tint64; 944 } 945 else 946 { 947 Tsize_t = Tuns32; 948 Tptrdiff_t = Tint32; 949 } 950 951 tsize_t = basic[Tsize_t]; 952 tptrdiff_t = basic[Tptrdiff_t]; 953 thash_t = tsize_t; 954 } 955 956 final d_uns64 size() 957 { 958 return size(Loc()); 959 } 960 961 d_uns64 size(Loc loc) 962 { 963 error(loc, "no size for type %s", toChars()); 964 return SIZE_INVALID; 965 } 966 967 uint alignsize() 968 { 969 return cast(uint)size(Loc()); 970 } 971 972 Type semantic(Loc loc, Scope* sc) 973 { 974 if (ty == Tint128 || ty == Tuns128) 975 { 976 error(loc, "cent and ucent types not implemented"); 977 return terror; 978 } 979 980 return merge(); 981 } 982 983 final Type trySemantic(Loc loc, Scope* sc) 984 { 985 //printf("+trySemantic(%s) %d\n", toChars(), global.errors); 986 uint errors = global.startGagging(); 987 Type t = semantic(loc, sc); 988 if (global.endGagging(errors) || t.ty == Terror) // if any errors happened 989 { 990 t = null; 991 } 992 //printf("-trySemantic(%s) %d\n", toChars(), global.errors); 993 return t; 994 } 995 996 /************************************ 997 */ 998 final Type merge() 999 { 1000 if (ty == Terror) 1001 return this; 1002 if (ty == Ttypeof) 1003 return this; 1004 if (ty == Tident) 1005 return this; 1006 if (ty == Tinstance) 1007 return this; 1008 if (ty == Taarray && !(cast(TypeAArray)this).index.merge().deco) 1009 return this; 1010 if (ty != Tenum && nextOf() && !nextOf().deco) 1011 return this; 1012 1013 //printf("merge(%s)\n", toChars()); 1014 Type t = this; 1015 assert(t); 1016 if (!deco) 1017 { 1018 OutBuffer buf; 1019 buf.reserve(32); 1020 1021 mangleToBuffer(this, &buf); 1022 1023 StringValue* sv = stringtable.update(cast(char*)buf.data, buf.offset); 1024 if (sv.ptrvalue) 1025 { 1026 t = cast(Type)sv.ptrvalue; 1027 debug 1028 { 1029 if (!t.deco) 1030 printf("t = %s\n", t.toChars()); 1031 } 1032 assert(t.deco); 1033 //printf("old value, deco = '%s' %p\n", t->deco, t->deco); 1034 } 1035 else 1036 { 1037 sv.ptrvalue = cast(char*)(t = stripDefaultArgs(t)); 1038 deco = t.deco = cast(char*)sv.toDchars(); 1039 //printf("new value, deco = '%s' %p\n", t->deco, t->deco); 1040 } 1041 } 1042 return t; 1043 } 1044 1045 /************************************* 1046 * This version does a merge even if the deco is already computed. 1047 * Necessary for types that have a deco, but are not merged. 1048 */ 1049 final Type merge2() 1050 { 1051 //printf("merge2(%s)\n", toChars()); 1052 Type t = this; 1053 assert(t); 1054 if (!t.deco) 1055 return t.merge(); 1056 1057 StringValue* sv = stringtable.lookup(t.deco, strlen(t.deco)); 1058 if (sv && sv.ptrvalue) 1059 { 1060 t = cast(Type)sv.ptrvalue; 1061 assert(t.deco); 1062 } 1063 else 1064 assert(0); 1065 return t; 1066 } 1067 1068 /********************************* 1069 * Store this type's modifier name into buf. 1070 */ 1071 final void modToBuffer(OutBuffer* buf) 1072 { 1073 if (mod) 1074 { 1075 buf.writeByte(' '); 1076 MODtoBuffer(buf, mod); 1077 } 1078 } 1079 1080 /********************************* 1081 * Return this type's modifier name. 1082 */ 1083 final char* modToChars() 1084 { 1085 OutBuffer buf; 1086 buf.reserve(16); 1087 modToBuffer(&buf); 1088 return buf.extractString(); 1089 } 1090 1091 /** For each active modifier (MODconst, MODimmutable, etc) call fp with a 1092 void* for the work param and a string representation of the attribute. */ 1093 final int modifiersApply(void* param, int function(void*, const(char)*) fp) 1094 { 1095 immutable ubyte[4] modsArr = [MODconst, MODimmutable, MODwild, MODshared]; 1096 1097 foreach (modsarr; modsArr) 1098 { 1099 if (mod & modsarr) 1100 { 1101 if (int res = fp(param, MODtoChars(modsarr))) 1102 return res; 1103 } 1104 } 1105 1106 return 0; 1107 } 1108 1109 bool isintegral() 1110 { 1111 return false; 1112 } 1113 1114 // real, imaginary, or complex 1115 bool isfloating() 1116 { 1117 return false; 1118 } 1119 1120 bool isreal() 1121 { 1122 return false; 1123 } 1124 1125 bool isimaginary() 1126 { 1127 return false; 1128 } 1129 1130 bool iscomplex() 1131 { 1132 return false; 1133 } 1134 1135 bool isscalar() 1136 { 1137 return false; 1138 } 1139 1140 bool isunsigned() 1141 { 1142 return false; 1143 } 1144 1145 bool isscope() 1146 { 1147 return false; 1148 } 1149 1150 bool isString() 1151 { 1152 return false; 1153 } 1154 1155 /************************** 1156 * When T is mutable, 1157 * Given: 1158 * T a, b; 1159 * Can we bitwise assign: 1160 * a = b; 1161 * ? 1162 */ 1163 bool isAssignable() 1164 { 1165 return true; 1166 } 1167 1168 /************************** 1169 * Returns true if T can be converted to boolean value. 1170 */ 1171 bool isBoolean() 1172 { 1173 return isscalar(); 1174 } 1175 1176 /********************************* 1177 * Check type to see if it is based on a deprecated symbol. 1178 */ 1179 void checkDeprecated(Loc loc, Scope* sc) 1180 { 1181 Dsymbol s = toDsymbol(sc); 1182 if (s) 1183 s.checkDeprecated(loc, sc); 1184 } 1185 1186 final bool isConst() const 1187 { 1188 return (mod & MODconst) != 0; 1189 } 1190 1191 final bool isImmutable() const 1192 { 1193 return (mod & MODimmutable) != 0; 1194 } 1195 1196 final bool isMutable() const 1197 { 1198 return (mod & (MODconst | MODimmutable | MODwild)) == 0; 1199 } 1200 1201 final bool isShared() const 1202 { 1203 return (mod & MODshared) != 0; 1204 } 1205 1206 final bool isSharedConst() const 1207 { 1208 return (mod & (MODshared | MODconst)) == (MODshared | MODconst); 1209 } 1210 1211 final bool isWild() const 1212 { 1213 return (mod & MODwild) != 0; 1214 } 1215 1216 final bool isWildConst() const 1217 { 1218 return (mod & MODwildconst) == MODwildconst; 1219 } 1220 1221 final bool isSharedWild() const 1222 { 1223 return (mod & (MODshared | MODwild)) == (MODshared | MODwild); 1224 } 1225 1226 final bool isNaked() const 1227 { 1228 return mod == 0; 1229 } 1230 1231 /******************************** 1232 * Return a copy of this type with all attributes null-initialized. 1233 * Useful for creating a type with different modifiers. 1234 */ 1235 final Type nullAttributes() 1236 { 1237 uint sz = sizeTy[ty]; 1238 Type t = cast(Type)mem.xmalloc(sz); 1239 memcpy(cast(void*)t, cast(void*)this, sz); 1240 // t->mod = NULL; // leave mod unchanged 1241 t.deco = null; 1242 t.arrayof = null; 1243 t.pto = null; 1244 t.rto = null; 1245 t.cto = null; 1246 t.ito = null; 1247 t.sto = null; 1248 t.scto = null; 1249 t.wto = null; 1250 t.wcto = null; 1251 t.swto = null; 1252 t.swcto = null; 1253 t.vtinfo = null; 1254 t.ctype = null; 1255 if (t.ty == Tstruct) 1256 (cast(TypeStruct)t).att = RECfwdref; 1257 if (t.ty == Tclass) 1258 (cast(TypeClass)t).att = RECfwdref; 1259 return t; 1260 } 1261 1262 /******************************** 1263 * Convert to 'const'. 1264 */ 1265 final Type constOf() 1266 { 1267 //printf("Type::constOf() %p %s\n", this, toChars()); 1268 if (mod == MODconst) 1269 return this; 1270 if (cto) 1271 { 1272 assert(cto.mod == MODconst); 1273 return cto; 1274 } 1275 Type t = makeConst(); 1276 t = t.merge(); 1277 t.fixTo(this); 1278 //printf("-Type::constOf() %p %s\n", t, t->toChars()); 1279 return t; 1280 } 1281 1282 /******************************** 1283 * Convert to 'immutable'. 1284 */ 1285 final Type immutableOf() 1286 { 1287 //printf("Type::immutableOf() %p %s\n", this, toChars()); 1288 if (isImmutable()) 1289 return this; 1290 if (ito) 1291 { 1292 assert(ito.isImmutable()); 1293 return ito; 1294 } 1295 Type t = makeImmutable(); 1296 t = t.merge(); 1297 t.fixTo(this); 1298 //printf("\t%p\n", t); 1299 return t; 1300 } 1301 1302 /******************************** 1303 * Make type mutable. 1304 */ 1305 final Type mutableOf() 1306 { 1307 //printf("Type::mutableOf() %p, %s\n", this, toChars()); 1308 Type t = this; 1309 if (isImmutable()) 1310 { 1311 t = ito; // immutable => naked 1312 assert(!t || (t.isMutable() && !t.isShared())); 1313 } 1314 else if (isConst()) 1315 { 1316 if (isShared()) 1317 { 1318 if (isWild()) 1319 t = swcto; // shared wild const -> shared 1320 else 1321 t = sto; // shared const => shared 1322 } 1323 else 1324 { 1325 if (isWild()) 1326 t = wcto; // wild const -> naked 1327 else 1328 t = cto; // const => naked 1329 } 1330 assert(!t || t.isMutable()); 1331 } 1332 else if (isWild()) 1333 { 1334 if (isShared()) 1335 t = sto; // shared wild => shared 1336 else 1337 t = wto; // wild => naked 1338 assert(!t || t.isMutable()); 1339 } 1340 if (!t) 1341 { 1342 t = makeMutable(); 1343 t = t.merge(); 1344 t.fixTo(this); 1345 } 1346 else 1347 t = t.merge(); 1348 assert(t.isMutable()); 1349 return t; 1350 } 1351 1352 final Type sharedOf() 1353 { 1354 //printf("Type::sharedOf() %p, %s\n", this, toChars()); 1355 if (mod == MODshared) 1356 return this; 1357 if (sto) 1358 { 1359 assert(sto.mod == MODshared); 1360 return sto; 1361 } 1362 Type t = makeShared(); 1363 t = t.merge(); 1364 t.fixTo(this); 1365 //printf("\t%p\n", t); 1366 return t; 1367 } 1368 1369 final Type sharedConstOf() 1370 { 1371 //printf("Type::sharedConstOf() %p, %s\n", this, toChars()); 1372 if (mod == (MODshared | MODconst)) 1373 return this; 1374 if (scto) 1375 { 1376 assert(scto.mod == (MODshared | MODconst)); 1377 return scto; 1378 } 1379 Type t = makeSharedConst(); 1380 t = t.merge(); 1381 t.fixTo(this); 1382 //printf("\t%p\n", t); 1383 return t; 1384 } 1385 1386 /******************************** 1387 * Make type unshared. 1388 * 0 => 0 1389 * const => const 1390 * immutable => immutable 1391 * shared => 0 1392 * shared const => const 1393 * wild => wild 1394 * wild const => wild const 1395 * shared wild => wild 1396 * shared wild const => wild const 1397 */ 1398 final Type unSharedOf() 1399 { 1400 //printf("Type::unSharedOf() %p, %s\n", this, toChars()); 1401 Type t = this; 1402 1403 if (isShared()) 1404 { 1405 if (isWild()) 1406 { 1407 if (isConst()) 1408 t = wcto; // shared wild const => wild const 1409 else 1410 t = wto; // shared wild => wild 1411 } 1412 else 1413 { 1414 if (isConst()) 1415 t = cto; // shared const => const 1416 else 1417 t = sto; // shared => naked 1418 } 1419 assert(!t || !t.isShared()); 1420 } 1421 1422 if (!t) 1423 { 1424 t = this.nullAttributes(); 1425 t.mod = mod & ~MODshared; 1426 t.ctype = ctype; 1427 t = t.merge(); 1428 t.fixTo(this); 1429 } 1430 else 1431 t = t.merge(); 1432 assert(!t.isShared()); 1433 return t; 1434 } 1435 1436 /******************************** 1437 * Convert to 'wild'. 1438 */ 1439 final Type wildOf() 1440 { 1441 //printf("Type::wildOf() %p %s\n", this, toChars()); 1442 if (mod == MODwild) 1443 return this; 1444 if (wto) 1445 { 1446 assert(wto.mod == MODwild); 1447 return wto; 1448 } 1449 Type t = makeWild(); 1450 t = t.merge(); 1451 t.fixTo(this); 1452 //printf("\t%p %s\n", t, t->toChars()); 1453 return t; 1454 } 1455 1456 final Type wildConstOf() 1457 { 1458 //printf("Type::wildConstOf() %p %s\n", this, toChars()); 1459 if (mod == MODwildconst) 1460 return this; 1461 if (wcto) 1462 { 1463 assert(wcto.mod == MODwildconst); 1464 return wcto; 1465 } 1466 Type t = makeWildConst(); 1467 t = t.merge(); 1468 t.fixTo(this); 1469 //printf("\t%p %s\n", t, t->toChars()); 1470 return t; 1471 } 1472 1473 final Type sharedWildOf() 1474 { 1475 //printf("Type::sharedWildOf() %p, %s\n", this, toChars()); 1476 if (mod == (MODshared | MODwild)) 1477 return this; 1478 if (swto) 1479 { 1480 assert(swto.mod == (MODshared | MODwild)); 1481 return swto; 1482 } 1483 Type t = makeSharedWild(); 1484 t = t.merge(); 1485 t.fixTo(this); 1486 //printf("\t%p %s\n", t, t->toChars()); 1487 return t; 1488 } 1489 1490 final Type sharedWildConstOf() 1491 { 1492 //printf("Type::sharedWildConstOf() %p, %s\n", this, toChars()); 1493 if (mod == (MODshared | MODwildconst)) 1494 return this; 1495 if (swcto) 1496 { 1497 assert(swcto.mod == (MODshared | MODwildconst)); 1498 return swcto; 1499 } 1500 Type t = makeSharedWildConst(); 1501 t = t.merge(); 1502 t.fixTo(this); 1503 //printf("\t%p %s\n", t, t->toChars()); 1504 return t; 1505 } 1506 1507 /********************************** 1508 * For our new type 'this', which is type-constructed from t, 1509 * fill in the cto, ito, sto, scto, wto shortcuts. 1510 */ 1511 final void fixTo(Type t) 1512 { 1513 // If fixing this: immutable(T*) by t: immutable(T)*, 1514 // cache t to this->xto won't break transitivity. 1515 Type mto = null; 1516 Type tn = nextOf(); 1517 if (!tn || ty != Tsarray && tn.mod == t.nextOf().mod) 1518 { 1519 switch (t.mod) 1520 { 1521 case 0: 1522 mto = t; 1523 break; 1524 1525 case MODconst: 1526 cto = t; 1527 break; 1528 1529 case MODwild: 1530 wto = t; 1531 break; 1532 1533 case MODwildconst: 1534 wcto = t; 1535 break; 1536 1537 case MODshared: 1538 sto = t; 1539 break; 1540 1541 case MODshared | MODconst: 1542 scto = t; 1543 break; 1544 1545 case MODshared | MODwild: 1546 swto = t; 1547 break; 1548 1549 case MODshared | MODwildconst: 1550 swcto = t; 1551 break; 1552 1553 case MODimmutable: 1554 ito = t; 1555 break; 1556 1557 default: 1558 break; 1559 } 1560 } 1561 assert(mod != t.mod); 1562 1563 auto X(T, U)(T m, U n) 1564 { 1565 return ((m << 4) | n); 1566 } 1567 1568 switch (mod) 1569 { 1570 case 0: 1571 break; 1572 1573 case MODconst: 1574 cto = mto; 1575 t.cto = this; 1576 break; 1577 1578 case MODwild: 1579 wto = mto; 1580 t.wto = this; 1581 break; 1582 1583 case MODwildconst: 1584 wcto = mto; 1585 t.wcto = this; 1586 break; 1587 1588 case MODshared: 1589 sto = mto; 1590 t.sto = this; 1591 break; 1592 1593 case MODshared | MODconst: 1594 scto = mto; 1595 t.scto = this; 1596 break; 1597 1598 case MODshared | MODwild: 1599 swto = mto; 1600 t.swto = this; 1601 break; 1602 1603 case MODshared | MODwildconst: 1604 swcto = mto; 1605 t.swcto = this; 1606 break; 1607 1608 case MODimmutable: 1609 t.ito = this; 1610 if (t.cto) 1611 t.cto.ito = this; 1612 if (t.sto) 1613 t.sto.ito = this; 1614 if (t.scto) 1615 t.scto.ito = this; 1616 if (t.wto) 1617 t.wto.ito = this; 1618 if (t.wcto) 1619 t.wcto.ito = this; 1620 if (t.swto) 1621 t.swto.ito = this; 1622 if (t.swcto) 1623 t.swcto.ito = this; 1624 break; 1625 1626 default: 1627 assert(0); 1628 } 1629 1630 check(); 1631 t.check(); 1632 //printf("fixTo: %s, %s\n", toChars(), t->toChars()); 1633 } 1634 1635 /*************************** 1636 * Look for bugs in constructing types. 1637 */ 1638 final void check() 1639 { 1640 switch (mod) 1641 { 1642 case 0: 1643 if (cto) 1644 assert(cto.mod == MODconst); 1645 if (ito) 1646 assert(ito.mod == MODimmutable); 1647 if (sto) 1648 assert(sto.mod == MODshared); 1649 if (scto) 1650 assert(scto.mod == (MODshared | MODconst)); 1651 if (wto) 1652 assert(wto.mod == MODwild); 1653 if (wcto) 1654 assert(wcto.mod == MODwildconst); 1655 if (swto) 1656 assert(swto.mod == (MODshared | MODwild)); 1657 if (swcto) 1658 assert(swcto.mod == (MODshared | MODwildconst)); 1659 break; 1660 1661 case MODconst: 1662 if (cto) 1663 assert(cto.mod == 0); 1664 if (ito) 1665 assert(ito.mod == MODimmutable); 1666 if (sto) 1667 assert(sto.mod == MODshared); 1668 if (scto) 1669 assert(scto.mod == (MODshared | MODconst)); 1670 if (wto) 1671 assert(wto.mod == MODwild); 1672 if (wcto) 1673 assert(wcto.mod == MODwildconst); 1674 if (swto) 1675 assert(swto.mod == (MODshared | MODwild)); 1676 if (swcto) 1677 assert(swcto.mod == (MODshared | MODwildconst)); 1678 break; 1679 1680 case MODwild: 1681 if (cto) 1682 assert(cto.mod == MODconst); 1683 if (ito) 1684 assert(ito.mod == MODimmutable); 1685 if (sto) 1686 assert(sto.mod == MODshared); 1687 if (scto) 1688 assert(scto.mod == (MODshared | MODconst)); 1689 if (wto) 1690 assert(wto.mod == 0); 1691 if (wcto) 1692 assert(wcto.mod == MODwildconst); 1693 if (swto) 1694 assert(swto.mod == (MODshared | MODwild)); 1695 if (swcto) 1696 assert(swcto.mod == (MODshared | MODwildconst)); 1697 break; 1698 1699 case MODwildconst: 1700 assert(!cto || cto.mod == MODconst); 1701 assert(!ito || ito.mod == MODimmutable); 1702 assert(!sto || sto.mod == MODshared); 1703 assert(!scto || scto.mod == (MODshared | MODconst)); 1704 assert(!wto || wto.mod == MODwild); 1705 assert(!wcto || wcto.mod == 0); 1706 assert(!swto || swto.mod == (MODshared | MODwild)); 1707 assert(!swcto || swcto.mod == (MODshared | MODwildconst)); 1708 break; 1709 1710 case MODshared: 1711 if (cto) 1712 assert(cto.mod == MODconst); 1713 if (ito) 1714 assert(ito.mod == MODimmutable); 1715 if (sto) 1716 assert(sto.mod == 0); 1717 if (scto) 1718 assert(scto.mod == (MODshared | MODconst)); 1719 if (wto) 1720 assert(wto.mod == MODwild); 1721 if (wcto) 1722 assert(wcto.mod == MODwildconst); 1723 if (swto) 1724 assert(swto.mod == (MODshared | MODwild)); 1725 if (swcto) 1726 assert(swcto.mod == (MODshared | MODwildconst)); 1727 break; 1728 1729 case MODshared | MODconst: 1730 if (cto) 1731 assert(cto.mod == MODconst); 1732 if (ito) 1733 assert(ito.mod == MODimmutable); 1734 if (sto) 1735 assert(sto.mod == MODshared); 1736 if (scto) 1737 assert(scto.mod == 0); 1738 if (wto) 1739 assert(wto.mod == MODwild); 1740 if (wcto) 1741 assert(wcto.mod == MODwildconst); 1742 if (swto) 1743 assert(swto.mod == (MODshared | MODwild)); 1744 if (swcto) 1745 assert(swcto.mod == (MODshared | MODwildconst)); 1746 break; 1747 1748 case MODshared | MODwild: 1749 if (cto) 1750 assert(cto.mod == MODconst); 1751 if (ito) 1752 assert(ito.mod == MODimmutable); 1753 if (sto) 1754 assert(sto.mod == MODshared); 1755 if (scto) 1756 assert(scto.mod == (MODshared | MODconst)); 1757 if (wto) 1758 assert(wto.mod == MODwild); 1759 if (wcto) 1760 assert(wcto.mod == MODwildconst); 1761 if (swto) 1762 assert(swto.mod == 0); 1763 if (swcto) 1764 assert(swcto.mod == (MODshared | MODwildconst)); 1765 break; 1766 1767 case MODshared | MODwildconst: 1768 assert(!cto || cto.mod == MODconst); 1769 assert(!ito || ito.mod == MODimmutable); 1770 assert(!sto || sto.mod == MODshared); 1771 assert(!scto || scto.mod == (MODshared | MODconst)); 1772 assert(!wto || wto.mod == MODwild); 1773 assert(!wcto || wcto.mod == MODwildconst); 1774 assert(!swto || swto.mod == (MODshared | MODwild)); 1775 assert(!swcto || swcto.mod == 0); 1776 break; 1777 1778 case MODimmutable: 1779 if (cto) 1780 assert(cto.mod == MODconst); 1781 if (ito) 1782 assert(ito.mod == 0); 1783 if (sto) 1784 assert(sto.mod == MODshared); 1785 if (scto) 1786 assert(scto.mod == (MODshared | MODconst)); 1787 if (wto) 1788 assert(wto.mod == MODwild); 1789 if (wcto) 1790 assert(wcto.mod == MODwildconst); 1791 if (swto) 1792 assert(swto.mod == (MODshared | MODwild)); 1793 if (swcto) 1794 assert(swcto.mod == (MODshared | MODwildconst)); 1795 break; 1796 1797 default: 1798 assert(0); 1799 } 1800 1801 Type tn = nextOf(); 1802 if (tn && ty != Tfunction && tn.ty != Tfunction && ty != Tenum) 1803 { 1804 // Verify transitivity 1805 switch (mod) 1806 { 1807 case 0: 1808 case MODconst: 1809 case MODwild: 1810 case MODwildconst: 1811 case MODshared: 1812 case MODshared | MODconst: 1813 case MODshared | MODwild: 1814 case MODshared | MODwildconst: 1815 case MODimmutable: 1816 assert(tn.mod == MODimmutable || (tn.mod & mod) == mod); 1817 break; 1818 1819 default: 1820 assert(0); 1821 } 1822 tn.check(); 1823 } 1824 } 1825 1826 /************************************* 1827 * Apply STCxxxx bits to existing type. 1828 * Use *before* semantic analysis is run. 1829 */ 1830 final Type addSTC(StorageClass stc) 1831 { 1832 Type t = this; 1833 if (t.isImmutable()) 1834 { 1835 } 1836 else if (stc & STCimmutable) 1837 { 1838 t = t.makeImmutable(); 1839 } 1840 else 1841 { 1842 if ((stc & STCshared) && !t.isShared()) 1843 { 1844 if (t.isWild()) 1845 { 1846 if (t.isConst()) 1847 t = t.makeSharedWildConst(); 1848 else 1849 t = t.makeSharedWild(); 1850 } 1851 else 1852 { 1853 if (t.isConst()) 1854 t = t.makeSharedConst(); 1855 else 1856 t = t.makeShared(); 1857 } 1858 } 1859 if ((stc & STCconst) && !t.isConst()) 1860 { 1861 if (t.isShared()) 1862 { 1863 if (t.isWild()) 1864 t = t.makeSharedWildConst(); 1865 else 1866 t = t.makeSharedConst(); 1867 } 1868 else 1869 { 1870 if (t.isWild()) 1871 t = t.makeWildConst(); 1872 else 1873 t = t.makeConst(); 1874 } 1875 } 1876 if ((stc & STCwild) && !t.isWild()) 1877 { 1878 if (t.isShared()) 1879 { 1880 if (t.isConst()) 1881 t = t.makeSharedWildConst(); 1882 else 1883 t = t.makeSharedWild(); 1884 } 1885 else 1886 { 1887 if (t.isConst()) 1888 t = t.makeWildConst(); 1889 else 1890 t = t.makeWild(); 1891 } 1892 } 1893 } 1894 return t; 1895 } 1896 1897 /************************************ 1898 * Apply MODxxxx bits to existing type. 1899 */ 1900 final Type castMod(MOD mod) 1901 { 1902 Type t; 1903 switch (mod) 1904 { 1905 case 0: 1906 t = unSharedOf().mutableOf(); 1907 break; 1908 1909 case MODconst: 1910 t = unSharedOf().constOf(); 1911 break; 1912 1913 case MODwild: 1914 t = unSharedOf().wildOf(); 1915 break; 1916 1917 case MODwildconst: 1918 t = unSharedOf().wildConstOf(); 1919 break; 1920 1921 case MODshared: 1922 t = mutableOf().sharedOf(); 1923 break; 1924 1925 case MODshared | MODconst: 1926 t = sharedConstOf(); 1927 break; 1928 1929 case MODshared | MODwild: 1930 t = sharedWildOf(); 1931 break; 1932 1933 case MODshared | MODwildconst: 1934 t = sharedWildConstOf(); 1935 break; 1936 1937 case MODimmutable: 1938 t = immutableOf(); 1939 break; 1940 1941 default: 1942 assert(0); 1943 } 1944 return t; 1945 } 1946 1947 /************************************ 1948 * Add MODxxxx bits to existing type. 1949 * We're adding, not replacing, so adding const to 1950 * a shared type => "shared const" 1951 */ 1952 final Type addMod(MOD mod) 1953 { 1954 /* Add anything to immutable, and it remains immutable 1955 */ 1956 Type t = this; 1957 if (!t.isImmutable()) 1958 { 1959 //printf("addMod(%x) %s\n", mod, toChars()); 1960 switch (mod) 1961 { 1962 case 0: 1963 break; 1964 1965 case MODconst: 1966 if (isShared()) 1967 { 1968 if (isWild()) 1969 t = sharedWildConstOf(); 1970 else 1971 t = sharedConstOf(); 1972 } 1973 else 1974 { 1975 if (isWild()) 1976 t = wildConstOf(); 1977 else 1978 t = constOf(); 1979 } 1980 break; 1981 1982 case MODwild: 1983 if (isShared()) 1984 { 1985 if (isConst()) 1986 t = sharedWildConstOf(); 1987 else 1988 t = sharedWildOf(); 1989 } 1990 else 1991 { 1992 if (isConst()) 1993 t = wildConstOf(); 1994 else 1995 t = wildOf(); 1996 } 1997 break; 1998 1999 case MODwildconst: 2000 if (isShared()) 2001 t = sharedWildConstOf(); 2002 else 2003 t = wildConstOf(); 2004 break; 2005 2006 case MODshared: 2007 if (isWild()) 2008 { 2009 if (isConst()) 2010 t = sharedWildConstOf(); 2011 else 2012 t = sharedWildOf(); 2013 } 2014 else 2015 { 2016 if (isConst()) 2017 t = sharedConstOf(); 2018 else 2019 t = sharedOf(); 2020 } 2021 break; 2022 2023 case MODshared | MODconst: 2024 if (isWild()) 2025 t = sharedWildConstOf(); 2026 else 2027 t = sharedConstOf(); 2028 break; 2029 2030 case MODshared | MODwild: 2031 if (isConst()) 2032 t = sharedWildConstOf(); 2033 else 2034 t = sharedWildOf(); 2035 break; 2036 2037 case MODshared | MODwildconst: 2038 t = sharedWildConstOf(); 2039 break; 2040 2041 case MODimmutable: 2042 t = immutableOf(); 2043 break; 2044 2045 default: 2046 assert(0); 2047 } 2048 } 2049 return t; 2050 } 2051 2052 /************************************ 2053 * Add storage class modifiers to type. 2054 */ 2055 Type addStorageClass(StorageClass stc) 2056 { 2057 /* Just translate to MOD bits and let addMod() do the work 2058 */ 2059 MOD mod = 0; 2060 if (stc & STCimmutable) 2061 mod = MODimmutable; 2062 else 2063 { 2064 if (stc & (STCconst | STCin)) 2065 mod |= MODconst; 2066 if (stc & STCwild) 2067 mod |= MODwild; 2068 if (stc & STCshared) 2069 mod |= MODshared; 2070 } 2071 return addMod(mod); 2072 } 2073 2074 final Type pointerTo() 2075 { 2076 if (ty == Terror) 2077 return this; 2078 if (!pto) 2079 { 2080 Type t = new TypePointer(this); 2081 if (ty == Tfunction) 2082 { 2083 t.deco = t.merge().deco; 2084 pto = t; 2085 } 2086 else 2087 pto = t.merge(); 2088 } 2089 return pto; 2090 } 2091 2092 final Type referenceTo() 2093 { 2094 if (ty == Terror) 2095 return this; 2096 if (!rto) 2097 { 2098 Type t = new TypeReference(this); 2099 rto = t.merge(); 2100 } 2101 return rto; 2102 } 2103 2104 final Type arrayOf() 2105 { 2106 if (ty == Terror) 2107 return this; 2108 if (!arrayof) 2109 { 2110 Type t = new TypeDArray(this); 2111 arrayof = t.merge(); 2112 } 2113 return arrayof; 2114 } 2115 2116 // Make corresponding static array type without semantic 2117 final Type sarrayOf(dinteger_t dim) 2118 { 2119 assert(deco); 2120 Type t = new TypeSArray(this, new IntegerExp(Loc(), dim, Type.tsize_t)); 2121 // according to TypeSArray::semantic() 2122 t = t.addMod(mod); 2123 t = t.merge(); 2124 return t; 2125 } 2126 2127 final Type aliasthisOf() 2128 { 2129 auto ad = isAggregate(this); 2130 if (!ad || !ad.aliasthis) 2131 return null; 2132 2133 auto s = ad.aliasthis; 2134 if (s.isAliasDeclaration()) 2135 s = s.toAlias(); 2136 2137 if (s.isTupleDeclaration()) 2138 return null; 2139 2140 if (auto vd = s.isVarDeclaration()) 2141 { 2142 auto t = vd.type; 2143 if (vd.needThis()) 2144 t = t.addMod(this.mod); 2145 return t; 2146 } 2147 if (auto fd = s.isFuncDeclaration()) 2148 { 2149 fd = resolveFuncCall(Loc(), null, fd, null, this, null, 1); 2150 if (!fd || fd.errors || !fd.functionSemantic()) 2151 return Type.terror; 2152 2153 auto t = fd.type.nextOf(); 2154 if (!t) // issue 14185 2155 return Type.terror; 2156 t = t.substWildTo(mod == 0 ? MODmutable : mod); 2157 return t; 2158 } 2159 if (auto d = s.isDeclaration()) 2160 { 2161 assert(d.type); 2162 return d.type; 2163 } 2164 if (auto ed = s.isEnumDeclaration()) 2165 { 2166 return ed.type; 2167 } 2168 if (auto td = s.isTemplateDeclaration()) 2169 { 2170 assert(td._scope); 2171 auto fd = resolveFuncCall(Loc(), null, td, null, this, null, 1); 2172 if (!fd || fd.errors || !fd.functionSemantic()) 2173 return Type.terror; 2174 2175 auto t = fd.type.nextOf(); 2176 if (!t) 2177 return Type.terror; 2178 t = t.substWildTo(mod == 0 ? MODmutable : mod); 2179 return t; 2180 } 2181 2182 //printf("%s\n", s.kind()); 2183 return null; 2184 } 2185 2186 final bool checkAliasThisRec() 2187 { 2188 Type tb = toBasetype(); 2189 AliasThisRec* pflag; 2190 if (tb.ty == Tstruct) 2191 pflag = &(cast(TypeStruct)tb).att; 2192 else if (tb.ty == Tclass) 2193 pflag = &(cast(TypeClass)tb).att; 2194 else 2195 return false; 2196 2197 AliasThisRec flag = cast(AliasThisRec)(*pflag & RECtypeMask); 2198 if (flag == RECfwdref) 2199 { 2200 Type att = aliasthisOf(); 2201 flag = att && att.implicitConvTo(this) ? RECyes : RECno; 2202 } 2203 *pflag = cast(AliasThisRec)(flag | (*pflag & ~RECtypeMask)); 2204 return flag == RECyes; 2205 } 2206 2207 Type makeConst() 2208 { 2209 //printf("Type::makeConst() %p, %s\n", this, toChars()); 2210 if (cto) 2211 return cto; 2212 Type t = this.nullAttributes(); 2213 t.mod = MODconst; 2214 //printf("-Type::makeConst() %p, %s\n", t, toChars()); 2215 return t; 2216 } 2217 2218 Type makeImmutable() 2219 { 2220 if (ito) 2221 return ito; 2222 Type t = this.nullAttributes(); 2223 t.mod = MODimmutable; 2224 return t; 2225 } 2226 2227 Type makeShared() 2228 { 2229 if (sto) 2230 return sto; 2231 Type t = this.nullAttributes(); 2232 t.mod = MODshared; 2233 return t; 2234 } 2235 2236 Type makeSharedConst() 2237 { 2238 if (scto) 2239 return scto; 2240 Type t = this.nullAttributes(); 2241 t.mod = MODshared | MODconst; 2242 return t; 2243 } 2244 2245 Type makeWild() 2246 { 2247 if (wto) 2248 return wto; 2249 Type t = this.nullAttributes(); 2250 t.mod = MODwild; 2251 return t; 2252 } 2253 2254 Type makeWildConst() 2255 { 2256 if (wcto) 2257 return wcto; 2258 Type t = this.nullAttributes(); 2259 t.mod = MODwildconst; 2260 return t; 2261 } 2262 2263 Type makeSharedWild() 2264 { 2265 if (swto) 2266 return swto; 2267 Type t = this.nullAttributes(); 2268 t.mod = MODshared | MODwild; 2269 return t; 2270 } 2271 2272 Type makeSharedWildConst() 2273 { 2274 if (swcto) 2275 return swcto; 2276 Type t = this.nullAttributes(); 2277 t.mod = MODshared | MODwildconst; 2278 return t; 2279 } 2280 2281 Type makeMutable() 2282 { 2283 Type t = this.nullAttributes(); 2284 t.mod = mod & MODshared; 2285 return t; 2286 } 2287 2288 Dsymbol toDsymbol(Scope* sc) 2289 { 2290 return null; 2291 } 2292 2293 /******************************* 2294 * If this is a shell around another type, 2295 * get that other type. 2296 */ 2297 Type toBasetype() 2298 { 2299 return this; 2300 } 2301 2302 bool isBaseOf(Type t, int* poffset) 2303 { 2304 return 0; // assume not 2305 } 2306 2307 /******************************** 2308 * Determine if 'this' can be implicitly converted 2309 * to type 'to'. 2310 * Returns: 2311 * MATCHnomatch, MATCHconvert, MATCHconst, MATCHexact 2312 */ 2313 MATCH implicitConvTo(Type to) 2314 { 2315 //printf("Type::implicitConvTo(this=%p, to=%p)\n", this, to); 2316 //printf("from: %s\n", toChars()); 2317 //printf("to : %s\n", to->toChars()); 2318 if (this.equals(to)) 2319 return MATCHexact; 2320 return MATCHnomatch; 2321 } 2322 2323 /******************************* 2324 * Determine if converting 'this' to 'to' is an identity operation, 2325 * a conversion to const operation, or the types aren't the same. 2326 * Returns: 2327 * MATCHexact 'this' == 'to' 2328 * MATCHconst 'to' is const 2329 * MATCHnomatch conversion to mutable or invariant 2330 */ 2331 MATCH constConv(Type to) 2332 { 2333 //printf("Type::constConv(this = %s, to = %s)\n", toChars(), to->toChars()); 2334 if (equals(to)) 2335 return MATCHexact; 2336 if (ty == to.ty && MODimplicitConv(mod, to.mod)) 2337 return MATCHconst; 2338 return MATCHnomatch; 2339 } 2340 2341 /*************************************** 2342 * Return MOD bits matching this type to wild parameter type (tprm). 2343 */ 2344 ubyte deduceWild(Type t, bool isRef) 2345 { 2346 //printf("Type::deduceWild this = '%s', tprm = '%s'\n", toChars(), tprm->toChars()); 2347 if (t.isWild()) 2348 { 2349 if (isImmutable()) 2350 return MODimmutable; 2351 else if (isWildConst()) 2352 { 2353 if (t.isWildConst()) 2354 return MODwild; 2355 else 2356 return MODwildconst; 2357 } 2358 else if (isWild()) 2359 return MODwild; 2360 else if (isConst()) 2361 return MODconst; 2362 else if (isMutable()) 2363 return MODmutable; 2364 else 2365 assert(0); 2366 } 2367 return 0; 2368 } 2369 2370 Type substWildTo(uint mod) 2371 { 2372 //printf("+Type::substWildTo this = %s, mod = x%x\n", toChars(), mod); 2373 Type t; 2374 2375 if (Type tn = nextOf()) 2376 { 2377 // substitution has no effect on function pointer type. 2378 if (ty == Tpointer && tn.ty == Tfunction) 2379 { 2380 t = this; 2381 goto L1; 2382 } 2383 2384 t = tn.substWildTo(mod); 2385 if (t == tn) 2386 t = this; 2387 else 2388 { 2389 if (ty == Tpointer) 2390 t = t.pointerTo(); 2391 else if (ty == Tarray) 2392 t = t.arrayOf(); 2393 else if (ty == Tsarray) 2394 t = new TypeSArray(t, (cast(TypeSArray)this).dim.syntaxCopy()); 2395 else if (ty == Taarray) 2396 { 2397 t = new TypeAArray(t, (cast(TypeAArray)this).index.syntaxCopy()); 2398 (cast(TypeAArray)t).sc = (cast(TypeAArray)this).sc; // duplicate scope 2399 } 2400 else if (ty == Tdelegate) 2401 { 2402 t = new TypeDelegate(t); 2403 } 2404 else 2405 assert(0); 2406 2407 t = t.merge(); 2408 } 2409 } 2410 else 2411 t = this; 2412 2413 L1: 2414 if (isWild()) 2415 { 2416 if (mod == MODimmutable) 2417 { 2418 t = t.immutableOf(); 2419 } 2420 else if (mod == MODwildconst) 2421 { 2422 t = t.wildConstOf(); 2423 } 2424 else if (mod == MODwild) 2425 { 2426 if (isWildConst()) 2427 t = t.wildConstOf(); 2428 else 2429 t = t.wildOf(); 2430 } 2431 else if (mod == MODconst) 2432 { 2433 t = t.constOf(); 2434 } 2435 else 2436 { 2437 if (isWildConst()) 2438 t = t.constOf(); 2439 else 2440 t = t.mutableOf(); 2441 } 2442 } 2443 if (isConst()) 2444 t = t.addMod(MODconst); 2445 if (isShared()) 2446 t = t.addMod(MODshared); 2447 2448 //printf("-Type::substWildTo t = %s\n", t->toChars()); 2449 return t; 2450 } 2451 2452 final Type unqualify(uint m) 2453 { 2454 Type t = mutableOf().unSharedOf(); 2455 2456 Type tn = ty == Tenum ? null : nextOf(); 2457 if (tn && tn.ty != Tfunction) 2458 { 2459 Type utn = tn.unqualify(m); 2460 if (utn != tn) 2461 { 2462 if (ty == Tpointer) 2463 t = utn.pointerTo(); 2464 else if (ty == Tarray) 2465 t = utn.arrayOf(); 2466 else if (ty == Tsarray) 2467 t = new TypeSArray(utn, (cast(TypeSArray)this).dim); 2468 else if (ty == Taarray) 2469 { 2470 t = new TypeAArray(utn, (cast(TypeAArray)this).index); 2471 (cast(TypeAArray)t).sc = (cast(TypeAArray)this).sc; // duplicate scope 2472 } 2473 else 2474 assert(0); 2475 2476 t = t.merge(); 2477 } 2478 } 2479 t = t.addMod(mod & ~m); 2480 return t; 2481 } 2482 2483 /************************** 2484 * Return type with the top level of it being mutable. 2485 */ 2486 Type toHeadMutable() 2487 { 2488 if (!mod) 2489 return this; 2490 return mutableOf(); 2491 } 2492 2493 ClassDeclaration isClassHandle() 2494 { 2495 return null; 2496 } 2497 2498 /*************************************** 2499 * Calculate built-in properties which just the type is necessary. 2500 * 2501 * If flag & 1, don't report "not a property" error and just return NULL. 2502 */ 2503 Expression getProperty(Loc loc, Identifier ident, int flag) 2504 { 2505 Expression e; 2506 static if (LOGDOTEXP) 2507 { 2508 printf("Type::getProperty(type = '%s', ident = '%s')\n", toChars(), ident.toChars()); 2509 } 2510 if (ident == Id.__sizeof) 2511 { 2512 d_uns64 sz = size(loc); 2513 if (sz == SIZE_INVALID) 2514 return new ErrorExp(); 2515 e = new IntegerExp(loc, sz, Type.tsize_t); 2516 } 2517 else if (ident == Id.__xalignof) 2518 { 2519 e = new IntegerExp(loc, alignsize(), Type.tsize_t); 2520 } 2521 else if (ident == Id._init) 2522 { 2523 Type tb = toBasetype(); 2524 e = defaultInitLiteral(loc); 2525 if (tb.ty == Tstruct && tb.needsNested()) 2526 { 2527 StructLiteralExp se = cast(StructLiteralExp)e; 2528 se.useStaticInit = true; 2529 } 2530 } 2531 else if (ident == Id._mangleof) 2532 { 2533 if (!deco) 2534 { 2535 error(loc, "forward reference of type %s.mangleof", toChars()); 2536 e = new ErrorExp(); 2537 } 2538 else 2539 { 2540 e = new StringExp(loc, deco); 2541 Scope sc; 2542 e = e.semantic(&sc); 2543 } 2544 } 2545 else if (ident == Id.stringof) 2546 { 2547 const s = toChars(); 2548 e = new StringExp(loc, cast(char*)s); 2549 Scope sc; 2550 e = e.semantic(&sc); 2551 } 2552 else if (flag && this != Type.terror) 2553 { 2554 return null; 2555 } 2556 else 2557 { 2558 Dsymbol s = null; 2559 if (ty == Tstruct || ty == Tclass || ty == Tenum) 2560 s = toDsymbol(null); 2561 if (s) 2562 s = s.search_correct(ident); 2563 if (this != Type.terror) 2564 { 2565 if (s) 2566 error(loc, "no property '%s' for type '%s', did you mean '%s'?", ident.toChars(), toChars(), s.toChars()); 2567 else 2568 error(loc, "no property '%s' for type '%s'", ident.toChars(), toChars()); 2569 } 2570 e = new ErrorExp(); 2571 } 2572 return e; 2573 } 2574 2575 /**************** 2576 * dotExp() bit flags 2577 */ 2578 enum DotExpFlag 2579 { 2580 gag = 1, // don't report "not a property" error and just return null 2581 noDeref = 2, // the use of the expression will not attempt a dereference 2582 } 2583 2584 /*************************************** 2585 * Access the members of the object e. This type is same as e->type. 2586 * Params: 2587 * flag = DotExpFlag bit flags 2588 * Returns: 2589 * resulting expression with e.ident resolved 2590 */ 2591 Expression dotExp(Scope* sc, Expression e, Identifier ident, int flag) 2592 { 2593 VarDeclaration v = null; 2594 static if (LOGDOTEXP) 2595 { 2596 printf("Type::dotExp(e = '%s', ident = '%s')\n", e.toChars(), ident.toChars()); 2597 } 2598 Expression ex = e; 2599 while (ex.op == TOKcomma) 2600 ex = (cast(CommaExp)ex).e2; 2601 if (ex.op == TOKdotvar) 2602 { 2603 DotVarExp dv = cast(DotVarExp)ex; 2604 v = dv.var.isVarDeclaration(); 2605 } 2606 else if (ex.op == TOKvar) 2607 { 2608 VarExp ve = cast(VarExp)ex; 2609 v = ve.var.isVarDeclaration(); 2610 } 2611 if (v) 2612 { 2613 if (ident == Id.offsetof) 2614 { 2615 if (v.isField()) 2616 { 2617 auto ad = v.toParent().isAggregateDeclaration(); 2618 ad.size(e.loc); 2619 if (ad.sizeok != SIZEOKdone) 2620 return new ErrorExp(); 2621 e = new IntegerExp(e.loc, v.offset, Type.tsize_t); 2622 return e; 2623 } 2624 } 2625 else if (ident == Id._init) 2626 { 2627 Type tb = toBasetype(); 2628 e = defaultInitLiteral(e.loc); 2629 if (tb.ty == Tstruct && tb.needsNested()) 2630 { 2631 StructLiteralExp se = cast(StructLiteralExp)e; 2632 se.useStaticInit = true; 2633 } 2634 goto Lreturn; 2635 } 2636 } 2637 if (ident == Id.stringof) 2638 { 2639 /* Bugzilla 3796: this should demangle e->type->deco rather than 2640 * pretty-printing the type. 2641 */ 2642 const s = e.toChars(); 2643 e = new StringExp(e.loc, cast(char*)s); 2644 } 2645 else 2646 e = getProperty(e.loc, ident, flag & DotExpFlag.gag); 2647 2648 Lreturn: 2649 if (!(flag & DotExpFlag.gag) || e) 2650 e = e.semantic(sc); 2651 return e; 2652 } 2653 2654 /************************************ 2655 * Return alignment to use for this type. 2656 */ 2657 structalign_t alignment() 2658 { 2659 return STRUCTALIGN_DEFAULT; 2660 } 2661 2662 /*************************************** 2663 * Figures out what to do with an undefined member reference 2664 * for classes and structs. 2665 * 2666 * If flag & 1, don't report "not a property" error and just return NULL. 2667 */ 2668 final Expression noMember(Scope* sc, Expression e, Identifier ident, int flag) 2669 { 2670 assert(ty == Tstruct || ty == Tclass); 2671 auto sym = toDsymbol(sc).isAggregateDeclaration(); 2672 assert(sym); 2673 if (ident != Id.__sizeof && 2674 ident != Id.__xalignof && 2675 ident != Id._init && 2676 ident != Id._mangleof && 2677 ident != Id.stringof && 2678 ident != Id.offsetof && 2679 // Bugzilla 15045: Don't forward special built-in member functions. 2680 ident != Id.ctor && 2681 ident != Id.dtor && 2682 ident != Id.__xdtor && 2683 ident != Id.postblit && 2684 ident != Id.__xpostblit) 2685 { 2686 /* Look for overloaded opDot() to see if we should forward request 2687 * to it. 2688 */ 2689 if (auto fd = search_function(sym, Id.opDot)) 2690 { 2691 /* Rewrite e.ident as: 2692 * e.opDot().ident 2693 */ 2694 e = build_overload(e.loc, sc, e, null, fd); 2695 e = new DotIdExp(e.loc, e, ident); 2696 return e.semantic(sc); 2697 } 2698 2699 /* Look for overloaded opDispatch to see if we should forward request 2700 * to it. 2701 */ 2702 if (auto fd = search_function(sym, Id.opDispatch)) 2703 { 2704 /* Rewrite e.ident as: 2705 * e.opDispatch!("ident") 2706 */ 2707 TemplateDeclaration td = fd.isTemplateDeclaration(); 2708 if (!td) 2709 { 2710 fd.error("must be a template opDispatch(string s), not a %s", fd.kind()); 2711 return new ErrorExp(); 2712 } 2713 auto se = new StringExp(e.loc, cast(char*)ident.toChars()); 2714 auto tiargs = new Objects(); 2715 tiargs.push(se); 2716 auto dti = new DotTemplateInstanceExp(e.loc, e, Id.opDispatch, tiargs); 2717 dti.ti.tempdecl = td; 2718 /* opDispatch, which doesn't need IFTI, may occur instantiate error. 2719 * It should be gagged if flag & 1. 2720 * e.g. 2721 * template opDispatch(name) if (isValid!name) { ... } 2722 */ 2723 uint errors = flag & 1 ? global.startGagging() : 0; 2724 e = dti.semanticY(sc, 0); 2725 if (flag & 1 && global.endGagging(errors)) 2726 e = null; 2727 return e; 2728 } 2729 2730 /* See if we should forward to the alias this. 2731 */ 2732 if (sym.aliasthis) 2733 { 2734 /* Rewrite e.ident as: 2735 * e.aliasthis.ident 2736 */ 2737 e = resolveAliasThis(sc, e); 2738 auto die = new DotIdExp(e.loc, e, ident); 2739 return die.semanticY(sc, flag & 1); 2740 } 2741 } 2742 return Type.dotExp(sc, e, ident, flag); 2743 } 2744 2745 Expression defaultInit(Loc loc = Loc()) 2746 { 2747 static if (LOGDEFAULTINIT) 2748 { 2749 printf("Type::defaultInit() '%s'\n", toChars()); 2750 } 2751 return null; 2752 } 2753 2754 /*************************************** 2755 * Use when we prefer the default initializer to be a literal, 2756 * rather than a global immutable variable. 2757 */ 2758 Expression defaultInitLiteral(Loc loc) 2759 { 2760 static if (LOGDEFAULTINIT) 2761 { 2762 printf("Type::defaultInitLiteral() '%s'\n", toChars()); 2763 } 2764 return defaultInit(loc); 2765 } 2766 2767 // if initializer is 0 2768 bool isZeroInit(Loc loc = Loc()) 2769 { 2770 return false; // assume not 2771 } 2772 2773 final Identifier getTypeInfoIdent() 2774 { 2775 // _init_10TypeInfo_%s 2776 OutBuffer buf; 2777 buf.reserve(32); 2778 mangleToBuffer(this, &buf); 2779 2780 const slice = buf.peekSlice(); 2781 2782 // Allocate buffer on stack, fail over to using malloc() 2783 char[128] namebuf; 2784 const namelen = 19 + size_t.sizeof * 3 + slice.length + 1; 2785 auto name = namelen <= namebuf.length ? namebuf.ptr : cast(char*)malloc(namelen); 2786 assert(name); 2787 2788 const length = sprintf(name, "_D%lluTypeInfo_%.*s6__initZ", 2789 cast(ulong)(9 + slice.length), cast(int)slice.length, slice.ptr); 2790 //printf("%p %s, deco = %s, name = %s\n", this, toChars(), deco, name); 2791 assert(0 < length && length < namelen); // don't overflow the buffer 2792 2793 int off = 0; 2794 static if (!IN_GCC) 2795 { 2796 if (global.params.isOSX || global.params.isWindows && !global.params.is64bit) 2797 ++off; // C mangling will add '_' back in 2798 } 2799 auto id = Identifier.idPool(name + off, length - off); 2800 2801 if (name != namebuf.ptr) 2802 free(name); 2803 return id; 2804 } 2805 2806 /*************************************** 2807 * Resolve 'this' type to either type, symbol, or expression. 2808 * If errors happened, resolved to Type.terror. 2809 */ 2810 void resolve(Loc loc, Scope* sc, Expression* pe, Type* pt, Dsymbol* ps, bool intypeid = false) 2811 { 2812 //printf("Type::resolve() %s, %d\n", toChars(), ty); 2813 Type t = semantic(loc, sc); 2814 *pt = t; 2815 *pe = null; 2816 *ps = null; 2817 } 2818 2819 /*************************************** 2820 * Normalize `e` as the result of Type.resolve() process. 2821 */ 2822 final void resolveExp(Expression e, Type *pt, Expression *pe, Dsymbol* ps) 2823 { 2824 *pt = null; 2825 *pe = null; 2826 *ps = null; 2827 2828 Dsymbol s; 2829 switch (e.op) 2830 { 2831 case TOKerror: 2832 *pt = Type.terror; 2833 return; 2834 2835 case TOKtype: 2836 *pt = e.type; 2837 return; 2838 2839 case TOKvar: 2840 s = (cast(VarExp)e).var; 2841 if (s.isVarDeclaration()) 2842 goto default; 2843 //if (s.isOverDeclaration()) 2844 // todo; 2845 break; 2846 2847 case TOKtemplate: 2848 // TemplateDeclaration 2849 s = (cast(TemplateExp)e).td; 2850 break; 2851 2852 case TOKscope: 2853 s = (cast(ScopeExp)e).sds; 2854 // TemplateDeclaration, TemplateInstance, Import, Package, Module 2855 break; 2856 2857 case TOKfunction: 2858 s = getDsymbol(e); 2859 break; 2860 2861 //case TOKthis: 2862 //case TOKsuper: 2863 2864 //case TOKtuple: 2865 2866 //case TOKoverloadset: 2867 2868 //case TOKdotvar: 2869 //case TOKdottd: 2870 //case TOKdotti: 2871 //case TOKdottype: 2872 //case TOKdotid: 2873 2874 default: 2875 *pe = e; 2876 return; 2877 } 2878 2879 *ps = s; 2880 } 2881 2882 /*************************************** 2883 * Return !=0 if the type or any of its subtypes is wild. 2884 */ 2885 int hasWild() const 2886 { 2887 return mod & MODwild; 2888 } 2889 2890 /******************************** 2891 * We've mistakenly parsed this as a type. 2892 * Redo it as an Expression. 2893 * NULL if cannot. 2894 */ 2895 Expression toExpression() 2896 { 2897 return null; 2898 } 2899 2900 /*************************************** 2901 * Return !=0 if type has pointers that need to 2902 * be scanned by the GC during a collection cycle. 2903 */ 2904 bool hasPointers() 2905 { 2906 //printf("Type::hasPointers() %s, %d\n", toChars(), ty); 2907 return false; 2908 } 2909 2910 /************************************* 2911 * Detect if type has pointer fields that are initialized to void. 2912 * Local stack variables with such void fields can remain uninitialized, 2913 * leading to pointer bugs. 2914 * Returns: 2915 * true if so 2916 */ 2917 bool hasVoidInitPointers() 2918 { 2919 return false; 2920 } 2921 2922 /************************************* 2923 * If this is a type of something, return that something. 2924 */ 2925 Type nextOf() 2926 { 2927 return null; 2928 } 2929 2930 /************************************* 2931 * If this is a type of static array, return its base element type. 2932 */ 2933 final Type baseElemOf() 2934 { 2935 Type t = toBasetype(); 2936 while (t.ty == Tsarray) 2937 t = (cast(TypeSArray)t).next.toBasetype(); 2938 return t; 2939 } 2940 2941 /**************************************** 2942 * Return the mask that an integral type will 2943 * fit into. 2944 */ 2945 final uinteger_t sizemask() 2946 { 2947 uinteger_t m; 2948 switch (toBasetype().ty) 2949 { 2950 case Tbool: 2951 m = 1; 2952 break; 2953 case Tchar: 2954 case Tint8: 2955 case Tuns8: 2956 m = 0xFF; 2957 break; 2958 case Twchar: 2959 case Tint16: 2960 case Tuns16: 2961 m = 0xFFFFU; 2962 break; 2963 case Tdchar: 2964 case Tint32: 2965 case Tuns32: 2966 m = 0xFFFFFFFFU; 2967 break; 2968 case Tint64: 2969 case Tuns64: 2970 m = 0xFFFFFFFFFFFFFFFFUL; 2971 break; 2972 default: 2973 assert(0); 2974 } 2975 return m; 2976 } 2977 2978 /******************************** 2979 * true if when type goes out of scope, it needs a destructor applied. 2980 * Only applies to value types, not ref types. 2981 */ 2982 bool needsDestruction() 2983 { 2984 return false; 2985 } 2986 2987 /********************************* 2988 * 2989 */ 2990 bool needsNested() 2991 { 2992 return false; 2993 } 2994 2995 /************************************* 2996 * Bugzilla 14488: Check if the inner most base type is complex or imaginary. 2997 * Should only give alerts when set to emit transitional messages. 2998 */ 2999 final void checkComplexTransition(Loc loc) 3000 { 3001 Type t = baseElemOf(); 3002 while (t.ty == Tpointer || t.ty == Tarray) 3003 t = t.nextOf().baseElemOf(); 3004 3005 if (t.isimaginary() || t.iscomplex()) 3006 { 3007 const(char)* p = loc.toChars(); 3008 Type rt; 3009 switch (t.ty) 3010 { 3011 case Tcomplex32: 3012 case Timaginary32: 3013 rt = Type.tfloat32; 3014 break; 3015 3016 case Tcomplex64: 3017 case Timaginary64: 3018 rt = Type.tfloat64; 3019 break; 3020 3021 case Tcomplex80: 3022 case Timaginary80: 3023 rt = Type.tfloat80; 3024 break; 3025 3026 default: 3027 assert(0); 3028 } 3029 if (t.iscomplex()) 3030 { 3031 fprintf(global.stdmsg, "%s: use of complex type '%s' is scheduled for deprecation, use 'std.complex.Complex!(%s)' instead\n", p ? p : "", toChars(), rt.toChars()); 3032 } 3033 else 3034 { 3035 fprintf(global.stdmsg, "%s: use of imaginary type '%s' is scheduled for deprecation, use '%s' instead\n", p ? p : "", toChars(), rt.toChars()); 3036 } 3037 } 3038 } 3039 3040 static void error(Loc loc, const(char)* format, ...) 3041 { 3042 va_list ap; 3043 va_start(ap, format); 3044 .verror(loc, format, ap); 3045 va_end(ap); 3046 } 3047 3048 static void warning(Loc loc, const(char)* format, ...) 3049 { 3050 va_list ap; 3051 va_start(ap, format); 3052 .vwarning(loc, format, ap); 3053 va_end(ap); 3054 } 3055 3056 // For eliminating dynamic_cast 3057 TypeBasic isTypeBasic() 3058 { 3059 return null; 3060 } 3061 3062 void accept(Visitor v) 3063 { 3064 v.visit(this); 3065 } 3066 } 3067 3068 /*********************************************************** 3069 */ 3070 extern (C++) final class TypeError : Type 3071 { 3072 extern (D) this() 3073 { 3074 super(Terror); 3075 } 3076 3077 override Type syntaxCopy() 3078 { 3079 // No semantic analysis done, no need to copy 3080 return this; 3081 } 3082 3083 override d_uns64 size(Loc loc) 3084 { 3085 return SIZE_INVALID; 3086 } 3087 3088 override Expression getProperty(Loc loc, Identifier ident, int flag) 3089 { 3090 return new ErrorExp(); 3091 } 3092 3093 override Expression dotExp(Scope* sc, Expression e, Identifier ident, int flag) 3094 { 3095 return new ErrorExp(); 3096 } 3097 3098 override Expression defaultInit(Loc loc) 3099 { 3100 return new ErrorExp(); 3101 } 3102 3103 override Expression defaultInitLiteral(Loc loc) 3104 { 3105 return new ErrorExp(); 3106 } 3107 3108 override void accept(Visitor v) 3109 { 3110 v.visit(this); 3111 } 3112 } 3113 3114 /*********************************************************** 3115 */ 3116 extern (C++) abstract class TypeNext : Type 3117 { 3118 Type next; 3119 3120 final extern (D) this(TY ty, Type next) 3121 { 3122 super(ty); 3123 this.next = next; 3124 } 3125 3126 override final void checkDeprecated(Loc loc, Scope* sc) 3127 { 3128 Type.checkDeprecated(loc, sc); 3129 if (next) // next can be NULL if TypeFunction and auto return type 3130 next.checkDeprecated(loc, sc); 3131 } 3132 3133 override final int hasWild() const 3134 { 3135 if (ty == Tfunction) 3136 return 0; 3137 if (ty == Tdelegate) 3138 return Type.hasWild(); 3139 return mod & MODwild || (next && next.hasWild()); 3140 } 3141 3142 /******************************* 3143 * For TypeFunction, nextOf() can return NULL if the function return 3144 * type is meant to be inferred, and semantic() hasn't yet ben run 3145 * on the function. After semantic(), it must no longer be NULL. 3146 */ 3147 override final Type nextOf() 3148 { 3149 return next; 3150 } 3151 3152 override final Type makeConst() 3153 { 3154 //printf("TypeNext::makeConst() %p, %s\n", this, toChars()); 3155 if (cto) 3156 { 3157 assert(cto.mod == MODconst); 3158 return cto; 3159 } 3160 TypeNext t = cast(TypeNext)Type.makeConst(); 3161 if (ty != Tfunction && next.ty != Tfunction && !next.isImmutable()) 3162 { 3163 if (next.isShared()) 3164 { 3165 if (next.isWild()) 3166 t.next = next.sharedWildConstOf(); 3167 else 3168 t.next = next.sharedConstOf(); 3169 } 3170 else 3171 { 3172 if (next.isWild()) 3173 t.next = next.wildConstOf(); 3174 else 3175 t.next = next.constOf(); 3176 } 3177 } 3178 //printf("TypeNext::makeConst() returns %p, %s\n", t, t->toChars()); 3179 return t; 3180 } 3181 3182 override final Type makeImmutable() 3183 { 3184 //printf("TypeNext::makeImmutable() %s\n", toChars()); 3185 if (ito) 3186 { 3187 assert(ito.isImmutable()); 3188 return ito; 3189 } 3190 TypeNext t = cast(TypeNext)Type.makeImmutable(); 3191 if (ty != Tfunction && next.ty != Tfunction && !next.isImmutable()) 3192 { 3193 t.next = next.immutableOf(); 3194 } 3195 return t; 3196 } 3197 3198 override final Type makeShared() 3199 { 3200 //printf("TypeNext::makeShared() %s\n", toChars()); 3201 if (sto) 3202 { 3203 assert(sto.mod == MODshared); 3204 return sto; 3205 } 3206 TypeNext t = cast(TypeNext)Type.makeShared(); 3207 if (ty != Tfunction && next.ty != Tfunction && !next.isImmutable()) 3208 { 3209 if (next.isWild()) 3210 { 3211 if (next.isConst()) 3212 t.next = next.sharedWildConstOf(); 3213 else 3214 t.next = next.sharedWildOf(); 3215 } 3216 else 3217 { 3218 if (next.isConst()) 3219 t.next = next.sharedConstOf(); 3220 else 3221 t.next = next.sharedOf(); 3222 } 3223 } 3224 //printf("TypeNext::makeShared() returns %p, %s\n", t, t->toChars()); 3225 return t; 3226 } 3227 3228 override final Type makeSharedConst() 3229 { 3230 //printf("TypeNext::makeSharedConst() %s\n", toChars()); 3231 if (scto) 3232 { 3233 assert(scto.mod == (MODshared | MODconst)); 3234 return scto; 3235 } 3236 TypeNext t = cast(TypeNext)Type.makeSharedConst(); 3237 if (ty != Tfunction && next.ty != Tfunction && !next.isImmutable()) 3238 { 3239 if (next.isWild()) 3240 t.next = next.sharedWildConstOf(); 3241 else 3242 t.next = next.sharedConstOf(); 3243 } 3244 //printf("TypeNext::makeSharedConst() returns %p, %s\n", t, t->toChars()); 3245 return t; 3246 } 3247 3248 override final Type makeWild() 3249 { 3250 //printf("TypeNext::makeWild() %s\n", toChars()); 3251 if (wto) 3252 { 3253 assert(wto.mod == MODwild); 3254 return wto; 3255 } 3256 TypeNext t = cast(TypeNext)Type.makeWild(); 3257 if (ty != Tfunction && next.ty != Tfunction && !next.isImmutable()) 3258 { 3259 if (next.isShared()) 3260 { 3261 if (next.isConst()) 3262 t.next = next.sharedWildConstOf(); 3263 else 3264 t.next = next.sharedWildOf(); 3265 } 3266 else 3267 { 3268 if (next.isConst()) 3269 t.next = next.wildConstOf(); 3270 else 3271 t.next = next.wildOf(); 3272 } 3273 } 3274 //printf("TypeNext::makeWild() returns %p, %s\n", t, t->toChars()); 3275 return t; 3276 } 3277 3278 override final Type makeWildConst() 3279 { 3280 //printf("TypeNext::makeWildConst() %s\n", toChars()); 3281 if (wcto) 3282 { 3283 assert(wcto.mod == MODwildconst); 3284 return wcto; 3285 } 3286 TypeNext t = cast(TypeNext)Type.makeWildConst(); 3287 if (ty != Tfunction && next.ty != Tfunction && !next.isImmutable()) 3288 { 3289 if (next.isShared()) 3290 t.next = next.sharedWildConstOf(); 3291 else 3292 t.next = next.wildConstOf(); 3293 } 3294 //printf("TypeNext::makeWildConst() returns %p, %s\n", t, t->toChars()); 3295 return t; 3296 } 3297 3298 override final Type makeSharedWild() 3299 { 3300 //printf("TypeNext::makeSharedWild() %s\n", toChars()); 3301 if (swto) 3302 { 3303 assert(swto.isSharedWild()); 3304 return swto; 3305 } 3306 TypeNext t = cast(TypeNext)Type.makeSharedWild(); 3307 if (ty != Tfunction && next.ty != Tfunction && !next.isImmutable()) 3308 { 3309 if (next.isConst()) 3310 t.next = next.sharedWildConstOf(); 3311 else 3312 t.next = next.sharedWildOf(); 3313 } 3314 //printf("TypeNext::makeSharedWild() returns %p, %s\n", t, t->toChars()); 3315 return t; 3316 } 3317 3318 override final Type makeSharedWildConst() 3319 { 3320 //printf("TypeNext::makeSharedWildConst() %s\n", toChars()); 3321 if (swcto) 3322 { 3323 assert(swcto.mod == (MODshared | MODwildconst)); 3324 return swcto; 3325 } 3326 TypeNext t = cast(TypeNext)Type.makeSharedWildConst(); 3327 if (ty != Tfunction && next.ty != Tfunction && !next.isImmutable()) 3328 { 3329 t.next = next.sharedWildConstOf(); 3330 } 3331 //printf("TypeNext::makeSharedWildConst() returns %p, %s\n", t, t->toChars()); 3332 return t; 3333 } 3334 3335 override final Type makeMutable() 3336 { 3337 //printf("TypeNext::makeMutable() %p, %s\n", this, toChars()); 3338 TypeNext t = cast(TypeNext)Type.makeMutable(); 3339 if (ty == Tsarray) 3340 { 3341 t.next = next.mutableOf(); 3342 } 3343 //printf("TypeNext::makeMutable() returns %p, %s\n", t, t->toChars()); 3344 return t; 3345 } 3346 3347 override MATCH constConv(Type to) 3348 { 3349 //printf("TypeNext::constConv from = %s, to = %s\n", toChars(), to->toChars()); 3350 if (equals(to)) 3351 return MATCHexact; 3352 3353 if (!(ty == to.ty && MODimplicitConv(mod, to.mod))) 3354 return MATCHnomatch; 3355 3356 Type tn = to.nextOf(); 3357 if (!(tn && next.ty == tn.ty)) 3358 return MATCHnomatch; 3359 3360 MATCH m; 3361 if (to.isConst()) // whole tail const conversion 3362 { 3363 // Recursive shared level check 3364 m = next.constConv(tn); 3365 if (m == MATCHexact) 3366 m = MATCHconst; 3367 } 3368 else 3369 { 3370 //printf("\tnext => %s, to->next => %s\n", next->toChars(), tn->toChars()); 3371 m = next.equals(tn) ? MATCHconst : MATCHnomatch; 3372 } 3373 return m; 3374 } 3375 3376 override final ubyte deduceWild(Type t, bool isRef) 3377 { 3378 if (ty == Tfunction) 3379 return 0; 3380 3381 ubyte wm; 3382 3383 Type tn = t.nextOf(); 3384 if (!isRef && (ty == Tarray || ty == Tpointer) && tn) 3385 { 3386 wm = next.deduceWild(tn, true); 3387 if (!wm) 3388 wm = Type.deduceWild(t, true); 3389 } 3390 else 3391 { 3392 wm = Type.deduceWild(t, isRef); 3393 if (!wm && tn) 3394 wm = next.deduceWild(tn, true); 3395 } 3396 3397 return wm; 3398 } 3399 3400 final void transitive() 3401 { 3402 /* Invoke transitivity of type attributes 3403 */ 3404 next = next.addMod(mod); 3405 } 3406 3407 override void accept(Visitor v) 3408 { 3409 v.visit(this); 3410 } 3411 } 3412 3413 /*********************************************************** 3414 */ 3415 extern (C++) final class TypeBasic : Type 3416 { 3417 const(char)* dstring; 3418 uint flags; 3419 3420 extern (D) this(TY ty) 3421 { 3422 super(ty); 3423 const(char)* d; 3424 uint flags = 0; 3425 switch (ty) 3426 { 3427 case Tvoid: 3428 d = Token.toChars(TOKvoid); 3429 break; 3430 3431 case Tint8: 3432 d = Token.toChars(TOKint8); 3433 flags |= TFLAGSintegral; 3434 break; 3435 3436 case Tuns8: 3437 d = Token.toChars(TOKuns8); 3438 flags |= TFLAGSintegral | TFLAGSunsigned; 3439 break; 3440 3441 case Tint16: 3442 d = Token.toChars(TOKint16); 3443 flags |= TFLAGSintegral; 3444 break; 3445 3446 case Tuns16: 3447 d = Token.toChars(TOKuns16); 3448 flags |= TFLAGSintegral | TFLAGSunsigned; 3449 break; 3450 3451 case Tint32: 3452 d = Token.toChars(TOKint32); 3453 flags |= TFLAGSintegral; 3454 break; 3455 3456 case Tuns32: 3457 d = Token.toChars(TOKuns32); 3458 flags |= TFLAGSintegral | TFLAGSunsigned; 3459 break; 3460 3461 case Tfloat32: 3462 d = Token.toChars(TOKfloat32); 3463 flags |= TFLAGSfloating | TFLAGSreal; 3464 break; 3465 3466 case Tint64: 3467 d = Token.toChars(TOKint64); 3468 flags |= TFLAGSintegral; 3469 break; 3470 3471 case Tuns64: 3472 d = Token.toChars(TOKuns64); 3473 flags |= TFLAGSintegral | TFLAGSunsigned; 3474 break; 3475 3476 case Tint128: 3477 d = Token.toChars(TOKint128); 3478 flags |= TFLAGSintegral; 3479 break; 3480 3481 case Tuns128: 3482 d = Token.toChars(TOKuns128); 3483 flags |= TFLAGSintegral | TFLAGSunsigned; 3484 break; 3485 3486 case Tfloat64: 3487 d = Token.toChars(TOKfloat64); 3488 flags |= TFLAGSfloating | TFLAGSreal; 3489 break; 3490 3491 case Tfloat80: 3492 d = Token.toChars(TOKfloat80); 3493 flags |= TFLAGSfloating | TFLAGSreal; 3494 break; 3495 3496 case Timaginary32: 3497 d = Token.toChars(TOKimaginary32); 3498 flags |= TFLAGSfloating | TFLAGSimaginary; 3499 break; 3500 3501 case Timaginary64: 3502 d = Token.toChars(TOKimaginary64); 3503 flags |= TFLAGSfloating | TFLAGSimaginary; 3504 break; 3505 3506 case Timaginary80: 3507 d = Token.toChars(TOKimaginary80); 3508 flags |= TFLAGSfloating | TFLAGSimaginary; 3509 break; 3510 3511 case Tcomplex32: 3512 d = Token.toChars(TOKcomplex32); 3513 flags |= TFLAGSfloating | TFLAGScomplex; 3514 break; 3515 3516 case Tcomplex64: 3517 d = Token.toChars(TOKcomplex64); 3518 flags |= TFLAGSfloating | TFLAGScomplex; 3519 break; 3520 3521 case Tcomplex80: 3522 d = Token.toChars(TOKcomplex80); 3523 flags |= TFLAGSfloating | TFLAGScomplex; 3524 break; 3525 3526 case Tbool: 3527 d = "bool"; 3528 flags |= TFLAGSintegral | TFLAGSunsigned; 3529 break; 3530 3531 case Tchar: 3532 d = Token.toChars(TOKchar); 3533 flags |= TFLAGSintegral | TFLAGSunsigned; 3534 break; 3535 3536 case Twchar: 3537 d = Token.toChars(TOKwchar); 3538 flags |= TFLAGSintegral | TFLAGSunsigned; 3539 break; 3540 3541 case Tdchar: 3542 d = Token.toChars(TOKdchar); 3543 flags |= TFLAGSintegral | TFLAGSunsigned; 3544 break; 3545 3546 default: 3547 assert(0); 3548 } 3549 this.dstring = d; 3550 this.flags = flags; 3551 merge(); 3552 } 3553 3554 override const(char)* kind() const 3555 { 3556 return dstring; 3557 } 3558 3559 override Type syntaxCopy() 3560 { 3561 // No semantic analysis done on basic types, no need to copy 3562 return this; 3563 } 3564 3565 override d_uns64 size(Loc loc) const 3566 { 3567 uint size; 3568 //printf("TypeBasic::size()\n"); 3569 switch (ty) 3570 { 3571 case Tint8: 3572 case Tuns8: 3573 size = 1; 3574 break; 3575 3576 case Tint16: 3577 case Tuns16: 3578 size = 2; 3579 break; 3580 3581 case Tint32: 3582 case Tuns32: 3583 case Tfloat32: 3584 case Timaginary32: 3585 size = 4; 3586 break; 3587 3588 case Tint64: 3589 case Tuns64: 3590 case Tfloat64: 3591 case Timaginary64: 3592 size = 8; 3593 break; 3594 3595 case Tfloat80: 3596 case Timaginary80: 3597 size = Target.realsize; 3598 break; 3599 3600 case Tcomplex32: 3601 size = 8; 3602 break; 3603 3604 case Tcomplex64: 3605 case Tint128: 3606 case Tuns128: 3607 size = 16; 3608 break; 3609 3610 case Tcomplex80: 3611 size = Target.realsize * 2; 3612 break; 3613 3614 case Tvoid: 3615 //size = Type::size(); // error message 3616 size = 1; 3617 break; 3618 3619 case Tbool: 3620 size = 1; 3621 break; 3622 3623 case Tchar: 3624 size = 1; 3625 break; 3626 3627 case Twchar: 3628 size = 2; 3629 break; 3630 3631 case Tdchar: 3632 size = 4; 3633 break; 3634 3635 default: 3636 assert(0); 3637 } 3638 //printf("TypeBasic::size() = %d\n", size); 3639 return size; 3640 } 3641 3642 override uint alignsize() 3643 { 3644 return Target.alignsize(this); 3645 } 3646 3647 override Expression getProperty(Loc loc, Identifier ident, int flag) 3648 { 3649 Expression e; 3650 dinteger_t ivalue; 3651 real_t fvalue = 0; 3652 //printf("TypeBasic::getProperty('%s')\n", ident->toChars()); 3653 if (ident == Id.max) 3654 { 3655 switch (ty) 3656 { 3657 case Tint8: 3658 ivalue = 0x7F; 3659 goto Livalue; 3660 case Tuns8: 3661 ivalue = 0xFF; 3662 goto Livalue; 3663 case Tint16: 3664 ivalue = 0x7FFFU; 3665 goto Livalue; 3666 case Tuns16: 3667 ivalue = 0xFFFFU; 3668 goto Livalue; 3669 case Tint32: 3670 ivalue = 0x7FFFFFFFU; 3671 goto Livalue; 3672 case Tuns32: 3673 ivalue = 0xFFFFFFFFU; 3674 goto Livalue; 3675 case Tint64: 3676 ivalue = 0x7FFFFFFFFFFFFFFFL; 3677 goto Livalue; 3678 case Tuns64: 3679 ivalue = 0xFFFFFFFFFFFFFFFFUL; 3680 goto Livalue; 3681 case Tbool: 3682 ivalue = 1; 3683 goto Livalue; 3684 case Tchar: 3685 ivalue = 0xFF; 3686 goto Livalue; 3687 case Twchar: 3688 ivalue = 0xFFFFU; 3689 goto Livalue; 3690 case Tdchar: 3691 ivalue = 0x10FFFFU; 3692 goto Livalue; 3693 case Tcomplex32: 3694 case Timaginary32: 3695 case Tfloat32: 3696 fvalue = Target.FloatProperties.max; 3697 goto Lfvalue; 3698 case Tcomplex64: 3699 case Timaginary64: 3700 case Tfloat64: 3701 fvalue = Target.DoubleProperties.max; 3702 goto Lfvalue; 3703 case Tcomplex80: 3704 case Timaginary80: 3705 case Tfloat80: 3706 fvalue = Target.RealProperties.max; 3707 goto Lfvalue; 3708 default: 3709 break; 3710 } 3711 } 3712 else if (ident == Id.min) 3713 { 3714 switch (ty) 3715 { 3716 case Tint8: 3717 ivalue = -128; 3718 goto Livalue; 3719 case Tuns8: 3720 ivalue = 0; 3721 goto Livalue; 3722 case Tint16: 3723 ivalue = -32768; 3724 goto Livalue; 3725 case Tuns16: 3726 ivalue = 0; 3727 goto Livalue; 3728 case Tint32: 3729 ivalue = -2147483647 - 1; 3730 goto Livalue; 3731 case Tuns32: 3732 ivalue = 0; 3733 goto Livalue; 3734 case Tint64: 3735 ivalue = (-9223372036854775807L - 1L); 3736 goto Livalue; 3737 case Tuns64: 3738 ivalue = 0; 3739 goto Livalue; 3740 case Tbool: 3741 ivalue = 0; 3742 goto Livalue; 3743 case Tchar: 3744 ivalue = 0; 3745 goto Livalue; 3746 case Twchar: 3747 ivalue = 0; 3748 goto Livalue; 3749 case Tdchar: 3750 ivalue = 0; 3751 goto Livalue; 3752 default: 3753 break; 3754 } 3755 } 3756 else if (ident == Id.min_normal) 3757 { 3758 Lmin_normal: 3759 switch (ty) 3760 { 3761 case Tcomplex32: 3762 case Timaginary32: 3763 case Tfloat32: 3764 fvalue = Target.FloatProperties.min_normal; 3765 goto Lfvalue; 3766 case Tcomplex64: 3767 case Timaginary64: 3768 case Tfloat64: 3769 fvalue = Target.DoubleProperties.min_normal; 3770 goto Lfvalue; 3771 case Tcomplex80: 3772 case Timaginary80: 3773 case Tfloat80: 3774 fvalue = Target.RealProperties.min_normal; 3775 goto Lfvalue; 3776 default: 3777 break; 3778 } 3779 } 3780 else if (ident == Id.nan) 3781 { 3782 switch (ty) 3783 { 3784 case Tcomplex32: 3785 case Tcomplex64: 3786 case Tcomplex80: 3787 case Timaginary32: 3788 case Timaginary64: 3789 case Timaginary80: 3790 case Tfloat32: 3791 case Tfloat64: 3792 case Tfloat80: 3793 fvalue = Target.RealProperties.nan; 3794 goto Lfvalue; 3795 default: 3796 break; 3797 } 3798 } 3799 else if (ident == Id.infinity) 3800 { 3801 switch (ty) 3802 { 3803 case Tcomplex32: 3804 case Tcomplex64: 3805 case Tcomplex80: 3806 case Timaginary32: 3807 case Timaginary64: 3808 case Timaginary80: 3809 case Tfloat32: 3810 case Tfloat64: 3811 case Tfloat80: 3812 fvalue = Target.RealProperties.infinity; 3813 goto Lfvalue; 3814 default: 3815 break; 3816 } 3817 } 3818 else if (ident == Id.dig) 3819 { 3820 switch (ty) 3821 { 3822 case Tcomplex32: 3823 case Timaginary32: 3824 case Tfloat32: 3825 ivalue = Target.FloatProperties.dig; 3826 goto Lint; 3827 case Tcomplex64: 3828 case Timaginary64: 3829 case Tfloat64: 3830 ivalue = Target.DoubleProperties.dig; 3831 goto Lint; 3832 case Tcomplex80: 3833 case Timaginary80: 3834 case Tfloat80: 3835 ivalue = Target.RealProperties.dig; 3836 goto Lint; 3837 default: 3838 break; 3839 } 3840 } 3841 else if (ident == Id.epsilon) 3842 { 3843 switch (ty) 3844 { 3845 case Tcomplex32: 3846 case Timaginary32: 3847 case Tfloat32: 3848 fvalue = Target.FloatProperties.epsilon; 3849 goto Lfvalue; 3850 case Tcomplex64: 3851 case Timaginary64: 3852 case Tfloat64: 3853 fvalue = Target.DoubleProperties.epsilon; 3854 goto Lfvalue; 3855 case Tcomplex80: 3856 case Timaginary80: 3857 case Tfloat80: 3858 fvalue = Target.RealProperties.epsilon; 3859 goto Lfvalue; 3860 default: 3861 break; 3862 } 3863 } 3864 else if (ident == Id.mant_dig) 3865 { 3866 switch (ty) 3867 { 3868 case Tcomplex32: 3869 case Timaginary32: 3870 case Tfloat32: 3871 ivalue = Target.FloatProperties.mant_dig; 3872 goto Lint; 3873 case Tcomplex64: 3874 case Timaginary64: 3875 case Tfloat64: 3876 ivalue = Target.DoubleProperties.mant_dig; 3877 goto Lint; 3878 case Tcomplex80: 3879 case Timaginary80: 3880 case Tfloat80: 3881 ivalue = Target.RealProperties.mant_dig; 3882 goto Lint; 3883 default: 3884 break; 3885 } 3886 } 3887 else if (ident == Id.max_10_exp) 3888 { 3889 switch (ty) 3890 { 3891 case Tcomplex32: 3892 case Timaginary32: 3893 case Tfloat32: 3894 ivalue = Target.FloatProperties.max_10_exp; 3895 goto Lint; 3896 case Tcomplex64: 3897 case Timaginary64: 3898 case Tfloat64: 3899 ivalue = Target.DoubleProperties.max_10_exp; 3900 goto Lint; 3901 case Tcomplex80: 3902 case Timaginary80: 3903 case Tfloat80: 3904 ivalue = Target.RealProperties.max_10_exp; 3905 goto Lint; 3906 default: 3907 break; 3908 } 3909 } 3910 else if (ident == Id.max_exp) 3911 { 3912 switch (ty) 3913 { 3914 case Tcomplex32: 3915 case Timaginary32: 3916 case Tfloat32: 3917 ivalue = Target.FloatProperties.max_exp; 3918 goto Lint; 3919 case Tcomplex64: 3920 case Timaginary64: 3921 case Tfloat64: 3922 ivalue = Target.DoubleProperties.max_exp; 3923 goto Lint; 3924 case Tcomplex80: 3925 case Timaginary80: 3926 case Tfloat80: 3927 ivalue = Target.RealProperties.max_exp; 3928 goto Lint; 3929 default: 3930 break; 3931 } 3932 } 3933 else if (ident == Id.min_10_exp) 3934 { 3935 switch (ty) 3936 { 3937 case Tcomplex32: 3938 case Timaginary32: 3939 case Tfloat32: 3940 ivalue = Target.FloatProperties.min_10_exp; 3941 goto Lint; 3942 case Tcomplex64: 3943 case Timaginary64: 3944 case Tfloat64: 3945 ivalue = Target.DoubleProperties.min_10_exp; 3946 goto Lint; 3947 case Tcomplex80: 3948 case Timaginary80: 3949 case Tfloat80: 3950 ivalue = Target.RealProperties.min_10_exp; 3951 goto Lint; 3952 default: 3953 break; 3954 } 3955 } 3956 else if (ident == Id.min_exp) 3957 { 3958 switch (ty) 3959 { 3960 case Tcomplex32: 3961 case Timaginary32: 3962 case Tfloat32: 3963 ivalue = Target.FloatProperties.min_exp; 3964 goto Lint; 3965 case Tcomplex64: 3966 case Timaginary64: 3967 case Tfloat64: 3968 ivalue = Target.DoubleProperties.min_exp; 3969 goto Lint; 3970 case Tcomplex80: 3971 case Timaginary80: 3972 case Tfloat80: 3973 ivalue = Target.RealProperties.min_exp; 3974 goto Lint; 3975 default: 3976 break; 3977 } 3978 } 3979 return Type.getProperty(loc, ident, flag); 3980 3981 Livalue: 3982 e = new IntegerExp(loc, ivalue, this); 3983 return e; 3984 3985 Lfvalue: 3986 if (isreal() || isimaginary()) 3987 e = new RealExp(loc, fvalue, this); 3988 else 3989 { 3990 const cvalue = complex_t(fvalue, fvalue); 3991 //for (int i = 0; i < 20; i++) 3992 // printf("%02x ", ((unsigned char *)&cvalue)[i]); 3993 //printf("\n"); 3994 e = new ComplexExp(loc, cvalue, this); 3995 } 3996 return e; 3997 3998 Lint: 3999 e = new IntegerExp(loc, ivalue, Type.tint32); 4000 return e; 4001 } 4002 4003 override Expression dotExp(Scope* sc, Expression e, Identifier ident, int flag) 4004 { 4005 static if (LOGDOTEXP) 4006 { 4007 printf("TypeBasic::dotExp(e = '%s', ident = '%s')\n", e.toChars(), ident.toChars()); 4008 } 4009 Type t; 4010 if (ident == Id.re) 4011 { 4012 switch (ty) 4013 { 4014 case Tcomplex32: 4015 t = tfloat32; 4016 goto L1; 4017 4018 case Tcomplex64: 4019 t = tfloat64; 4020 goto L1; 4021 4022 case Tcomplex80: 4023 t = tfloat80; 4024 goto L1; 4025 L1: 4026 e = e.castTo(sc, t); 4027 break; 4028 4029 case Tfloat32: 4030 case Tfloat64: 4031 case Tfloat80: 4032 break; 4033 4034 case Timaginary32: 4035 t = tfloat32; 4036 goto L2; 4037 4038 case Timaginary64: 4039 t = tfloat64; 4040 goto L2; 4041 4042 case Timaginary80: 4043 t = tfloat80; 4044 goto L2; 4045 L2: 4046 e = new RealExp(e.loc, CTFloat.zero, t); 4047 break; 4048 4049 default: 4050 e = Type.getProperty(e.loc, ident, flag); 4051 break; 4052 } 4053 } 4054 else if (ident == Id.im) 4055 { 4056 Type t2; 4057 switch (ty) 4058 { 4059 case Tcomplex32: 4060 t = timaginary32; 4061 t2 = tfloat32; 4062 goto L3; 4063 4064 case Tcomplex64: 4065 t = timaginary64; 4066 t2 = tfloat64; 4067 goto L3; 4068 4069 case Tcomplex80: 4070 t = timaginary80; 4071 t2 = tfloat80; 4072 goto L3; 4073 L3: 4074 e = e.castTo(sc, t); 4075 e.type = t2; 4076 break; 4077 4078 case Timaginary32: 4079 t = tfloat32; 4080 goto L4; 4081 4082 case Timaginary64: 4083 t = tfloat64; 4084 goto L4; 4085 4086 case Timaginary80: 4087 t = tfloat80; 4088 goto L4; 4089 L4: 4090 e = e.copy(); 4091 e.type = t; 4092 break; 4093 4094 case Tfloat32: 4095 case Tfloat64: 4096 case Tfloat80: 4097 e = new RealExp(e.loc, CTFloat.zero, this); 4098 break; 4099 4100 default: 4101 e = Type.getProperty(e.loc, ident, flag); 4102 break; 4103 } 4104 } 4105 else 4106 { 4107 return Type.dotExp(sc, e, ident, flag); 4108 } 4109 if (!(flag & 1) || e) 4110 e = e.semantic(sc); 4111 return e; 4112 } 4113 4114 override bool isintegral() 4115 { 4116 //printf("TypeBasic::isintegral('%s') x%x\n", toChars(), flags); 4117 return (flags & TFLAGSintegral) != 0; 4118 } 4119 4120 override bool isfloating() const 4121 { 4122 return (flags & TFLAGSfloating) != 0; 4123 } 4124 4125 override bool isreal() const 4126 { 4127 return (flags & TFLAGSreal) != 0; 4128 } 4129 4130 override bool isimaginary() const 4131 { 4132 return (flags & TFLAGSimaginary) != 0; 4133 } 4134 4135 override bool iscomplex() const 4136 { 4137 return (flags & TFLAGScomplex) != 0; 4138 } 4139 4140 override bool isscalar() const 4141 { 4142 return (flags & (TFLAGSintegral | TFLAGSfloating)) != 0; 4143 } 4144 4145 override bool isunsigned() const 4146 { 4147 return (flags & TFLAGSunsigned) != 0; 4148 } 4149 4150 override MATCH implicitConvTo(Type to) 4151 { 4152 //printf("TypeBasic::implicitConvTo(%s) from %s\n", to->toChars(), toChars()); 4153 if (this == to) 4154 return MATCHexact; 4155 4156 if (ty == to.ty) 4157 { 4158 if (mod == to.mod) 4159 return MATCHexact; 4160 else if (MODimplicitConv(mod, to.mod)) 4161 return MATCHconst; 4162 else if (!((mod ^ to.mod) & MODshared)) // for wild matching 4163 return MATCHconst; 4164 else 4165 return MATCHconvert; 4166 } 4167 4168 if (ty == Tvoid || to.ty == Tvoid) 4169 return MATCHnomatch; 4170 if (to.ty == Tbool) 4171 return MATCHnomatch; 4172 4173 TypeBasic tob; 4174 if (to.ty == Tvector && to.deco) 4175 { 4176 TypeVector tv = cast(TypeVector)to; 4177 tob = tv.elementType(); 4178 } 4179 else 4180 tob = to.isTypeBasic(); 4181 if (!tob) 4182 return MATCHnomatch; 4183 4184 if (flags & TFLAGSintegral) 4185 { 4186 // Disallow implicit conversion of integers to imaginary or complex 4187 if (tob.flags & (TFLAGSimaginary | TFLAGScomplex)) 4188 return MATCHnomatch; 4189 4190 // If converting from integral to integral 4191 if (tob.flags & TFLAGSintegral) 4192 { 4193 d_uns64 sz = size(Loc()); 4194 d_uns64 tosz = tob.size(Loc()); 4195 4196 /* Can't convert to smaller size 4197 */ 4198 if (sz > tosz) 4199 return MATCHnomatch; 4200 /* Can't change sign if same size 4201 */ 4202 //if (sz == tosz && (flags ^ tob->flags) & TFLAGSunsigned) 4203 // return MATCHnomatch; 4204 } 4205 } 4206 else if (flags & TFLAGSfloating) 4207 { 4208 // Disallow implicit conversion of floating point to integer 4209 if (tob.flags & TFLAGSintegral) 4210 return MATCHnomatch; 4211 4212 assert(tob.flags & TFLAGSfloating || to.ty == Tvector); 4213 4214 // Disallow implicit conversion from complex to non-complex 4215 if (flags & TFLAGScomplex && !(tob.flags & TFLAGScomplex)) 4216 return MATCHnomatch; 4217 4218 // Disallow implicit conversion of real or imaginary to complex 4219 if (flags & (TFLAGSreal | TFLAGSimaginary) && tob.flags & TFLAGScomplex) 4220 return MATCHnomatch; 4221 4222 // Disallow implicit conversion to-from real and imaginary 4223 if ((flags & (TFLAGSreal | TFLAGSimaginary)) != (tob.flags & (TFLAGSreal | TFLAGSimaginary))) 4224 return MATCHnomatch; 4225 } 4226 return MATCHconvert; 4227 } 4228 4229 override Expression defaultInit(Loc loc) 4230 { 4231 static if (LOGDEFAULTINIT) 4232 { 4233 printf("TypeBasic::defaultInit() '%s'\n", toChars()); 4234 } 4235 dinteger_t value = 0; 4236 4237 switch (ty) 4238 { 4239 case Tchar: 4240 value = 0xFF; 4241 break; 4242 4243 case Twchar: 4244 case Tdchar: 4245 value = 0xFFFF; 4246 break; 4247 4248 case Timaginary32: 4249 case Timaginary64: 4250 case Timaginary80: 4251 case Tfloat32: 4252 case Tfloat64: 4253 case Tfloat80: 4254 return new RealExp(loc, Target.RealProperties.snan, this); 4255 4256 case Tcomplex32: 4257 case Tcomplex64: 4258 case Tcomplex80: 4259 { 4260 // Can't use fvalue + I*fvalue (the im part becomes a quiet NaN). 4261 const cvalue = complex_t(Target.RealProperties.snan, Target.RealProperties.snan); 4262 return new ComplexExp(loc, cvalue, this); 4263 } 4264 4265 case Tvoid: 4266 error(loc, "void does not have a default initializer"); 4267 return new ErrorExp(); 4268 4269 default: 4270 break; 4271 } 4272 return new IntegerExp(loc, value, this); 4273 } 4274 4275 override bool isZeroInit(Loc loc) const 4276 { 4277 switch (ty) 4278 { 4279 case Tchar: 4280 case Twchar: 4281 case Tdchar: 4282 case Timaginary32: 4283 case Timaginary64: 4284 case Timaginary80: 4285 case Tfloat32: 4286 case Tfloat64: 4287 case Tfloat80: 4288 case Tcomplex32: 4289 case Tcomplex64: 4290 case Tcomplex80: 4291 return false; // no 4292 default: 4293 return true; // yes 4294 } 4295 } 4296 4297 // For eliminating dynamic_cast 4298 override TypeBasic isTypeBasic() 4299 { 4300 return this; 4301 } 4302 4303 override void accept(Visitor v) 4304 { 4305 v.visit(this); 4306 } 4307 } 4308 4309 /*********************************************************** 4310 * The basetype must be one of: 4311 * byte[16],ubyte[16],short[8],ushort[8],int[4],uint[4],long[2],ulong[2],float[4],double[2] 4312 * For AVX: 4313 * byte[32],ubyte[32],short[16],ushort[16],int[8],uint[8],long[4],ulong[4],float[8],double[4] 4314 */ 4315 extern (C++) final class TypeVector : Type 4316 { 4317 Type basetype; 4318 4319 extern (D) this(Loc loc, Type basetype) 4320 { 4321 super(Tvector); 4322 this.basetype = basetype; 4323 } 4324 4325 override const(char)* kind() const 4326 { 4327 return "vector"; 4328 } 4329 4330 override Type syntaxCopy() 4331 { 4332 return new TypeVector(Loc(), basetype.syntaxCopy()); 4333 } 4334 4335 override Type semantic(Loc loc, Scope* sc) 4336 { 4337 uint errors = global.errors; 4338 basetype = basetype.semantic(loc, sc); 4339 if (errors != global.errors) 4340 return terror; 4341 basetype = basetype.toBasetype().mutableOf(); 4342 if (basetype.ty != Tsarray) 4343 { 4344 error(loc, "T in __vector(T) must be a static array, not %s", basetype.toChars()); 4345 return terror; 4346 } 4347 TypeSArray t = cast(TypeSArray)basetype; 4348 int sz = cast(int)t.size(loc); 4349 switch (Target.checkVectorType(sz, t.nextOf())) 4350 { 4351 case 0: 4352 // valid 4353 break; 4354 case 1: 4355 // no support at all 4356 error(loc, "SIMD vector types not supported on this platform"); 4357 return terror; 4358 case 2: 4359 // invalid size 4360 error(loc, "%d byte vector type %s is not supported on this platform", sz, toChars()); 4361 return terror; 4362 case 3: 4363 // invalid base type 4364 error(loc, "vector type %s is not supported on this platform", toChars()); 4365 return terror; 4366 default: 4367 assert(0); 4368 } 4369 return merge(); 4370 } 4371 4372 override d_uns64 size(Loc loc) 4373 { 4374 return basetype.size(); 4375 } 4376 4377 override uint alignsize() 4378 { 4379 return cast(uint)basetype.size(); 4380 } 4381 4382 override Expression getProperty(Loc loc, Identifier ident, int flag) 4383 { 4384 return Type.getProperty(loc, ident, flag); 4385 } 4386 4387 override Expression dotExp(Scope* sc, Expression e, Identifier ident, int flag) 4388 { 4389 static if (LOGDOTEXP) 4390 { 4391 printf("TypeVector::dotExp(e = '%s', ident = '%s')\n", e.toChars(), ident.toChars()); 4392 } 4393 if (ident == Id.array) 4394 { 4395 //e = e->castTo(sc, basetype); 4396 // Keep lvalue-ness 4397 e = e.copy(); 4398 e.type = basetype; 4399 return e; 4400 } 4401 if (ident == Id._init || ident == Id.offsetof || ident == Id.stringof) 4402 { 4403 // init should return a new VectorExp (Bugzilla 12776) 4404 // offsetof does not work on a cast expression, so use e directly 4405 // stringof should not add a cast to the output 4406 return Type.dotExp(sc, e, ident, flag); 4407 } 4408 return basetype.dotExp(sc, e.castTo(sc, basetype), ident, flag); 4409 } 4410 4411 override bool isintegral() 4412 { 4413 //printf("TypeVector::isintegral('%s') x%x\n", toChars(), flags); 4414 return basetype.nextOf().isintegral(); 4415 } 4416 4417 override bool isfloating() 4418 { 4419 return basetype.nextOf().isfloating(); 4420 } 4421 4422 override bool isscalar() 4423 { 4424 return basetype.nextOf().isscalar(); 4425 } 4426 4427 override bool isunsigned() 4428 { 4429 return basetype.nextOf().isunsigned(); 4430 } 4431 4432 override bool isBoolean() const 4433 { 4434 return false; 4435 } 4436 4437 override MATCH implicitConvTo(Type to) 4438 { 4439 //printf("TypeVector::implicitConvTo(%s) from %s\n", to->toChars(), toChars()); 4440 if (this == to) 4441 return MATCHexact; 4442 if (ty == to.ty) 4443 return MATCHconvert; 4444 return MATCHnomatch; 4445 } 4446 4447 override Expression defaultInit(Loc loc) 4448 { 4449 //printf("TypeVector::defaultInit()\n"); 4450 assert(basetype.ty == Tsarray); 4451 Expression e = basetype.defaultInit(loc); 4452 auto ve = new VectorExp(loc, e, this); 4453 ve.type = this; 4454 ve.dim = cast(int)(basetype.size(loc) / elementType().size(loc)); 4455 return ve; 4456 } 4457 4458 override Expression defaultInitLiteral(Loc loc) 4459 { 4460 //printf("TypeVector::defaultInitLiteral()\n"); 4461 assert(basetype.ty == Tsarray); 4462 Expression e = basetype.defaultInitLiteral(loc); 4463 auto ve = new VectorExp(loc, e, this); 4464 ve.type = this; 4465 ve.dim = cast(int)(basetype.size(loc) / elementType().size(loc)); 4466 return ve; 4467 } 4468 4469 TypeBasic elementType() 4470 { 4471 assert(basetype.ty == Tsarray); 4472 TypeSArray t = cast(TypeSArray)basetype; 4473 TypeBasic tb = t.nextOf().isTypeBasic(); 4474 assert(tb); 4475 return tb; 4476 } 4477 4478 override bool isZeroInit(Loc loc) 4479 { 4480 return basetype.isZeroInit(loc); 4481 } 4482 4483 override void accept(Visitor v) 4484 { 4485 v.visit(this); 4486 } 4487 } 4488 4489 /*********************************************************** 4490 */ 4491 extern (C++) class TypeArray : TypeNext 4492 { 4493 final extern (D) this(TY ty, Type next) 4494 { 4495 super(ty, next); 4496 } 4497 4498 override Expression dotExp(Scope* sc, Expression e, Identifier ident, int flag) 4499 { 4500 Type n = this.next.toBasetype(); // uncover any typedef's 4501 static if (LOGDOTEXP) 4502 { 4503 printf("TypeArray::dotExp(e = '%s', ident = '%s')\n", e.toChars(), ident.toChars()); 4504 } 4505 if (e.op == TOKtype) 4506 { 4507 if (ident == Id.sort || ident == Id.reverse) 4508 { 4509 e.error("%s is not an expression", e.toChars()); 4510 return new ErrorExp(); 4511 } 4512 } 4513 if (!n.isMutable()) 4514 { 4515 if (ident == Id.sort || ident == Id.reverse) 4516 { 4517 error(e.loc, "can only %s a mutable array", ident.toChars()); 4518 goto Lerror; 4519 } 4520 } 4521 if (ident == Id.reverse && (n.ty == Tchar || n.ty == Twchar)) 4522 { 4523 static __gshared const(char)** reverseName = ["_adReverseChar", "_adReverseWchar"]; 4524 static __gshared FuncDeclaration* reverseFd = [null, null]; 4525 4526 deprecation(e.loc, "use std.algorithm.reverse instead of .reverse property"); 4527 int i = n.ty == Twchar; 4528 if (!reverseFd[i]) 4529 { 4530 auto params = new Parameters(); 4531 Type next = n.ty == Twchar ? Type.twchar : Type.tchar; 4532 Type arrty = next.arrayOf(); 4533 params.push(new Parameter(0, arrty, null, null)); 4534 reverseFd[i] = FuncDeclaration.genCfunc(params, arrty, reverseName[i]); 4535 } 4536 4537 Expression ec = new VarExp(Loc(), reverseFd[i], false); 4538 e = e.castTo(sc, n.arrayOf()); // convert to dynamic array 4539 auto arguments = new Expressions(); 4540 arguments.push(e); 4541 e = new CallExp(e.loc, ec, arguments); 4542 e.type = next.arrayOf(); 4543 } 4544 else if (ident == Id.sort && (n.ty == Tchar || n.ty == Twchar)) 4545 { 4546 static __gshared const(char)** sortName = ["_adSortChar", "_adSortWchar"]; 4547 static __gshared FuncDeclaration* sortFd = [null, null]; 4548 4549 deprecation(e.loc, "use std.algorithm.sort instead of .sort property"); 4550 int i = n.ty == Twchar; 4551 if (!sortFd[i]) 4552 { 4553 auto params = new Parameters(); 4554 Type next = n.ty == Twchar ? Type.twchar : Type.tchar; 4555 Type arrty = next.arrayOf(); 4556 params.push(new Parameter(0, arrty, null, null)); 4557 sortFd[i] = FuncDeclaration.genCfunc(params, arrty, sortName[i]); 4558 } 4559 4560 Expression ec = new VarExp(Loc(), sortFd[i], false); 4561 e = e.castTo(sc, n.arrayOf()); // convert to dynamic array 4562 auto arguments = new Expressions(); 4563 arguments.push(e); 4564 e = new CallExp(e.loc, ec, arguments); 4565 e.type = next.arrayOf(); 4566 } 4567 else if (ident == Id.reverse) 4568 { 4569 Expression ec; 4570 FuncDeclaration fd; 4571 Expressions* arguments; 4572 dinteger_t size = next.size(e.loc); 4573 4574 deprecation(e.loc, "use std.algorithm.reverse instead of .reverse property"); 4575 assert(size); 4576 4577 static __gshared FuncDeclaration adReverse_fd = null; 4578 if (!adReverse_fd) 4579 { 4580 auto params = new Parameters(); 4581 params.push(new Parameter(0, Type.tvoid.arrayOf(), null, null)); 4582 params.push(new Parameter(0, Type.tsize_t, null, null)); 4583 adReverse_fd = FuncDeclaration.genCfunc(params, Type.tvoid.arrayOf(), Id.adReverse); 4584 } 4585 fd = adReverse_fd; 4586 4587 ec = new VarExp(Loc(), fd, false); 4588 e = e.castTo(sc, n.arrayOf()); // convert to dynamic array 4589 arguments = new Expressions(); 4590 arguments.push(e); 4591 arguments.push(new IntegerExp(Loc(), size, Type.tsize_t)); 4592 e = new CallExp(e.loc, ec, arguments); 4593 e.type = next.mutableOf().arrayOf(); 4594 } 4595 else if (ident == Id.sort) 4596 { 4597 static __gshared FuncDeclaration fd = null; 4598 Expression ec; 4599 Expressions* arguments; 4600 4601 deprecation(e.loc, "use std.algorithm.sort instead of .sort property"); 4602 if (!fd) 4603 { 4604 auto params = new Parameters(); 4605 params.push(new Parameter(0, Type.tvoid.arrayOf(), null, null)); 4606 params.push(new Parameter(0, Type.dtypeinfo.type, null, null)); 4607 fd = FuncDeclaration.genCfunc(params, Type.tvoid.arrayOf(), "_adSort"); 4608 } 4609 4610 ec = new VarExp(Loc(), fd, false); 4611 e = e.castTo(sc, n.arrayOf()); // convert to dynamic array 4612 arguments = new Expressions(); 4613 arguments.push(e); 4614 // don't convert to dynamic array 4615 Expression tid = new TypeidExp(e.loc, n); 4616 tid = tid.semantic(sc); 4617 arguments.push(tid); 4618 e = new CallExp(e.loc, ec, arguments); 4619 e.type = next.arrayOf(); 4620 } 4621 else 4622 { 4623 e = Type.dotExp(sc, e, ident, flag); 4624 } 4625 if (!(flag & 1) || e) 4626 e = e.semantic(sc); 4627 return e; 4628 4629 Lerror: 4630 return new ErrorExp(); 4631 } 4632 4633 override void accept(Visitor v) 4634 { 4635 v.visit(this); 4636 } 4637 } 4638 4639 /*********************************************************** 4640 * Static array, one with a fixed dimension 4641 */ 4642 extern (C++) final class TypeSArray : TypeArray 4643 { 4644 Expression dim; 4645 4646 extern (D) this(Type t, Expression dim) 4647 { 4648 super(Tsarray, t); 4649 //printf("TypeSArray(%s)\n", dim->toChars()); 4650 this.dim = dim; 4651 } 4652 4653 override const(char)* kind() const 4654 { 4655 return "sarray"; 4656 } 4657 4658 override Type syntaxCopy() 4659 { 4660 Type t = next.syntaxCopy(); 4661 Expression e = dim.syntaxCopy(); 4662 t = new TypeSArray(t, e); 4663 t.mod = mod; 4664 return t; 4665 } 4666 4667 override d_uns64 size(Loc loc) 4668 { 4669 //printf("TypeSArray::size()\n"); 4670 dinteger_t sz; 4671 if (!dim) 4672 return Type.size(loc); 4673 sz = dim.toInteger(); 4674 { 4675 bool overflow = false; 4676 sz = mulu(next.size(), sz, overflow); 4677 if (overflow) 4678 goto Loverflow; 4679 } 4680 if (sz > uint.max) 4681 goto Loverflow; 4682 return sz; 4683 4684 Loverflow: 4685 error(loc, "static array %s size overflowed to %lld", toChars(), cast(long)sz); 4686 return SIZE_INVALID; 4687 } 4688 4689 override uint alignsize() 4690 { 4691 return next.alignsize(); 4692 } 4693 4694 override Type semantic(Loc loc, Scope* sc) 4695 { 4696 //printf("TypeSArray::semantic() %s\n", toChars()); 4697 Type t; 4698 Expression e; 4699 Dsymbol s; 4700 next.resolve(loc, sc, &e, &t, &s); 4701 4702 if (auto tup = s ? s.isTupleDeclaration() : null) 4703 { 4704 dim = semanticLength(sc, tup, dim); 4705 dim = dim.ctfeInterpret(); 4706 if (dim.op == TOKerror) 4707 return Type.terror; 4708 uinteger_t d = dim.toUInteger(); 4709 if (d >= tup.objects.dim) 4710 { 4711 error(loc, "tuple index %llu exceeds %u", d, tup.objects.dim); 4712 return Type.terror; 4713 } 4714 4715 RootObject o = (*tup.objects)[cast(size_t)d]; 4716 if (o.dyncast() != DYNCAST_TYPE) 4717 { 4718 error(loc, "%s is not a type", toChars()); 4719 return Type.terror; 4720 } 4721 t = (cast(Type)o).addMod(this.mod); 4722 return t; 4723 } 4724 4725 Type tn = next.semantic(loc, sc); 4726 if (tn.ty == Terror) 4727 return terror; 4728 4729 Type tbn = tn.toBasetype(); 4730 if (dim) 4731 { 4732 uint errors = global.errors; 4733 dim = semanticLength(sc, tbn, dim); 4734 if (errors != global.errors) 4735 goto Lerror; 4736 4737 dim = dim.optimize(WANTvalue); 4738 dim = dim.ctfeInterpret(); 4739 if (dim.op == TOKerror) 4740 goto Lerror; 4741 errors = global.errors; 4742 dinteger_t d1 = dim.toInteger(); 4743 if (errors != global.errors) 4744 goto Lerror; 4745 4746 dim = dim.implicitCastTo(sc, tsize_t); 4747 dim = dim.optimize(WANTvalue); 4748 if (dim.op == TOKerror) 4749 goto Lerror; 4750 errors = global.errors; 4751 dinteger_t d2 = dim.toInteger(); 4752 if (errors != global.errors) 4753 goto Lerror; 4754 4755 if (dim.op == TOKerror) 4756 goto Lerror; 4757 4758 if (d1 != d2) 4759 { 4760 Loverflow: 4761 error(loc, "%s size %llu * %llu exceeds 16MiB size limit for static array", toChars(), cast(ulong)tbn.size(loc), cast(ulong)d1); 4762 goto Lerror; 4763 } 4764 Type tbx = tbn.baseElemOf(); 4765 if (tbx.ty == Tstruct && !(cast(TypeStruct)tbx).sym.members || tbx.ty == Tenum && !(cast(TypeEnum)tbx).sym.members) 4766 { 4767 /* To avoid meaningess error message, skip the total size limit check 4768 * when the bottom of element type is opaque. 4769 */ 4770 } 4771 else if (tbn.isintegral() || tbn.isfloating() || tbn.ty == Tpointer || tbn.ty == Tarray || tbn.ty == Tsarray || tbn.ty == Taarray || (tbn.ty == Tstruct && ((cast(TypeStruct)tbn).sym.sizeok == SIZEOKdone)) || tbn.ty == Tclass) 4772 { 4773 /* Only do this for types that don't need to have semantic() 4774 * run on them for the size, since they may be forward referenced. 4775 */ 4776 bool overflow = false; 4777 if (mulu(tbn.size(loc), d2, overflow) >= 0x100_0000 || overflow) // put a 'reasonable' limit on it 4778 goto Loverflow; 4779 } 4780 } 4781 switch (tbn.ty) 4782 { 4783 case Ttuple: 4784 { 4785 // Index the tuple to get the type 4786 assert(dim); 4787 TypeTuple tt = cast(TypeTuple)tbn; 4788 uinteger_t d = dim.toUInteger(); 4789 if (d >= tt.arguments.dim) 4790 { 4791 error(loc, "tuple index %llu exceeds %u", d, tt.arguments.dim); 4792 goto Lerror; 4793 } 4794 Type telem = (*tt.arguments)[cast(size_t)d].type; 4795 return telem.addMod(this.mod); 4796 } 4797 case Tfunction: 4798 case Tnone: 4799 error(loc, "can't have array of %s", tbn.toChars()); 4800 goto Lerror; 4801 default: 4802 break; 4803 } 4804 if (tbn.isscope()) 4805 { 4806 error(loc, "cannot have array of scope %s", tbn.toChars()); 4807 goto Lerror; 4808 } 4809 4810 /* Ensure things like const(immutable(T)[3]) become immutable(T[3]) 4811 * and const(T)[3] become const(T[3]) 4812 */ 4813 next = tn; 4814 transitive(); 4815 t = addMod(tn.mod); 4816 4817 return t.merge(); 4818 4819 Lerror: 4820 return Type.terror; 4821 } 4822 4823 override void resolve(Loc loc, Scope* sc, Expression* pe, Type* pt, Dsymbol* ps, bool intypeid = false) 4824 { 4825 //printf("TypeSArray::resolve() %s\n", toChars()); 4826 next.resolve(loc, sc, pe, pt, ps, intypeid); 4827 //printf("s = %p, e = %p, t = %p\n", *ps, *pe, *pt); 4828 if (*pe) 4829 { 4830 // It's really an index expression 4831 if (Dsymbol s = getDsymbol(*pe)) 4832 *pe = new DsymbolExp(loc, s); 4833 *pe = new ArrayExp(loc, *pe, dim); 4834 } 4835 else if (*ps) 4836 { 4837 Dsymbol s = *ps; 4838 if (auto tup = s.isTupleDeclaration()) 4839 { 4840 dim = semanticLength(sc, tup, dim); 4841 dim = dim.ctfeInterpret(); 4842 if (dim.op == TOKerror) 4843 { 4844 *ps = null; 4845 *pt = Type.terror; 4846 return; 4847 } 4848 uinteger_t d = dim.toUInteger(); 4849 if (d >= tup.objects.dim) 4850 { 4851 error(loc, "tuple index %llu exceeds length %u", d, tup.objects.dim); 4852 *ps = null; 4853 *pt = Type.terror; 4854 return; 4855 } 4856 4857 RootObject o = (*tup.objects)[cast(size_t)d]; 4858 if (o.dyncast() == DYNCAST_DSYMBOL) 4859 { 4860 *ps = cast(Dsymbol)o; 4861 return; 4862 } 4863 if (o.dyncast() == DYNCAST_EXPRESSION) 4864 { 4865 Expression e = cast(Expression)o; 4866 if (e.op == TOKdsymbol) 4867 { 4868 *ps = (cast(DsymbolExp)e).s; 4869 *pe = null; 4870 } 4871 else 4872 { 4873 *ps = null; 4874 *pe = e; 4875 } 4876 return; 4877 } 4878 if (o.dyncast() == DYNCAST_TYPE) 4879 { 4880 *ps = null; 4881 *pt = (cast(Type)o).addMod(this.mod); 4882 return; 4883 } 4884 4885 /* Create a new TupleDeclaration which 4886 * is a slice [d..d+1] out of the old one. 4887 * Do it this way because TemplateInstance::semanticTiargs() 4888 * can handle unresolved Objects this way. 4889 */ 4890 auto objects = new Objects(); 4891 objects.setDim(1); 4892 (*objects)[0] = o; 4893 *ps = new TupleDeclaration(loc, tup.ident, objects); 4894 } 4895 else 4896 goto Ldefault; 4897 } 4898 else 4899 { 4900 if ((*pt).ty != Terror) 4901 next = *pt; // prevent re-running semantic() on 'next' 4902 Ldefault: 4903 Type.resolve(loc, sc, pe, pt, ps, intypeid); 4904 } 4905 } 4906 4907 override Expression dotExp(Scope* sc, Expression e, Identifier ident, int flag) 4908 { 4909 static if (LOGDOTEXP) 4910 { 4911 printf("TypeSArray::dotExp(e = '%s', ident = '%s')\n", e.toChars(), ident.toChars()); 4912 } 4913 if (ident == Id.length) 4914 { 4915 Loc oldLoc = e.loc; 4916 e = dim.copy(); 4917 e.loc = oldLoc; 4918 } 4919 else if (ident == Id.ptr) 4920 { 4921 if (e.op == TOKtype) 4922 { 4923 e.error("%s is not an expression", e.toChars()); 4924 return new ErrorExp(); 4925 } 4926 e = e.castTo(sc, e.type.nextOf().pointerTo()); 4927 } 4928 else 4929 { 4930 e = TypeArray.dotExp(sc, e, ident, flag); 4931 } 4932 if (!(flag & 1) || e) 4933 e = e.semantic(sc); 4934 return e; 4935 } 4936 4937 override bool isString() 4938 { 4939 TY nty = next.toBasetype().ty; 4940 return nty == Tchar || nty == Twchar || nty == Tdchar; 4941 } 4942 4943 override bool isZeroInit(Loc loc) 4944 { 4945 return next.isZeroInit(loc); 4946 } 4947 4948 override structalign_t alignment() 4949 { 4950 return next.alignment(); 4951 } 4952 4953 override MATCH constConv(Type to) 4954 { 4955 if (to.ty == Tsarray) 4956 { 4957 TypeSArray tsa = cast(TypeSArray)to; 4958 if (!dim.equals(tsa.dim)) 4959 return MATCHnomatch; 4960 } 4961 return TypeNext.constConv(to); 4962 } 4963 4964 override MATCH implicitConvTo(Type to) 4965 { 4966 //printf("TypeSArray::implicitConvTo(to = %s) this = %s\n", to->toChars(), toChars()); 4967 if (to.ty == Tarray) 4968 { 4969 TypeDArray ta = cast(TypeDArray)to; 4970 if (!MODimplicitConv(next.mod, ta.next.mod)) 4971 return MATCHnomatch; 4972 4973 /* Allow conversion to void[] 4974 */ 4975 if (ta.next.ty == Tvoid) 4976 { 4977 return MATCHconvert; 4978 } 4979 4980 MATCH m = next.constConv(ta.next); 4981 if (m > MATCHnomatch) 4982 { 4983 return MATCHconvert; 4984 } 4985 return MATCHnomatch; 4986 } 4987 if (to.ty == Tsarray) 4988 { 4989 if (this == to) 4990 return MATCHexact; 4991 4992 TypeSArray tsa = cast(TypeSArray)to; 4993 if (dim.equals(tsa.dim)) 4994 { 4995 /* Since static arrays are value types, allow 4996 * conversions from const elements to non-const 4997 * ones, just like we allow conversion from const int 4998 * to int. 4999 */ 5000 MATCH m = next.implicitConvTo(tsa.next); 5001 if (m >= MATCHconst) 5002 { 5003 if (mod != to.mod) 5004 m = MATCHconst; 5005 return m; 5006 } 5007 } 5008 } 5009 return MATCHnomatch; 5010 } 5011 5012 override Expression defaultInit(Loc loc) 5013 { 5014 static if (LOGDEFAULTINIT) 5015 { 5016 printf("TypeSArray::defaultInit() '%s'\n", toChars()); 5017 } 5018 if (next.ty == Tvoid) 5019 return tuns8.defaultInit(loc); 5020 else 5021 return next.defaultInit(loc); 5022 } 5023 5024 override Expression defaultInitLiteral(Loc loc) 5025 { 5026 static if (LOGDEFAULTINIT) 5027 { 5028 printf("TypeSArray::defaultInitLiteral() '%s'\n", toChars()); 5029 } 5030 size_t d = cast(size_t)dim.toInteger(); 5031 Expression elementinit; 5032 if (next.ty == Tvoid) 5033 elementinit = tuns8.defaultInitLiteral(loc); 5034 else 5035 elementinit = next.defaultInitLiteral(loc); 5036 auto elements = new Expressions(); 5037 elements.setDim(d); 5038 for (size_t i = 0; i < d; i++) 5039 (*elements)[i] = null; 5040 auto ae = new ArrayLiteralExp(Loc(), elementinit, elements); 5041 ae.type = this; 5042 return ae; 5043 } 5044 5045 override Expression toExpression() 5046 { 5047 Expression e = next.toExpression(); 5048 if (e) 5049 e = new ArrayExp(dim.loc, e, dim); 5050 return e; 5051 } 5052 5053 override bool hasPointers() 5054 { 5055 /* Don't want to do this, because: 5056 * struct S { T* array[0]; } 5057 * may be a variable length struct. 5058 */ 5059 //if (dim->toInteger() == 0) 5060 // return false; 5061 5062 if (next.ty == Tvoid) 5063 { 5064 // Arrays of void contain arbitrary data, which may include pointers 5065 return true; 5066 } 5067 else 5068 return next.hasPointers(); 5069 } 5070 5071 override bool needsDestruction() 5072 { 5073 return next.needsDestruction(); 5074 } 5075 5076 /********************************* 5077 * 5078 */ 5079 override bool needsNested() 5080 { 5081 return next.needsNested(); 5082 } 5083 5084 override void accept(Visitor v) 5085 { 5086 v.visit(this); 5087 } 5088 } 5089 5090 /*********************************************************** 5091 * Dynamic array, no dimension 5092 */ 5093 extern (C++) final class TypeDArray : TypeArray 5094 { 5095 extern (D) this(Type t) 5096 { 5097 super(Tarray, t); 5098 //printf("TypeDArray(t = %p)\n", t); 5099 } 5100 5101 override const(char)* kind() const 5102 { 5103 return "darray"; 5104 } 5105 5106 override Type syntaxCopy() 5107 { 5108 Type t = next.syntaxCopy(); 5109 if (t == next) 5110 t = this; 5111 else 5112 { 5113 t = new TypeDArray(t); 5114 t.mod = mod; 5115 } 5116 return t; 5117 } 5118 5119 override d_uns64 size(Loc loc) const 5120 { 5121 //printf("TypeDArray::size()\n"); 5122 return Target.ptrsize * 2; 5123 } 5124 5125 override uint alignsize() const 5126 { 5127 // A DArray consists of two ptr-sized values, so align it on pointer size 5128 // boundary 5129 return Target.ptrsize; 5130 } 5131 5132 override Type semantic(Loc loc, Scope* sc) 5133 { 5134 Type tn = next.semantic(loc, sc); 5135 Type tbn = tn.toBasetype(); 5136 switch (tbn.ty) 5137 { 5138 case Ttuple: 5139 return tbn; 5140 case Tfunction: 5141 case Tnone: 5142 error(loc, "can't have array of %s", tbn.toChars()); 5143 return Type.terror; 5144 case Terror: 5145 return Type.terror; 5146 default: 5147 break; 5148 } 5149 if (tn.isscope()) 5150 { 5151 error(loc, "cannot have array of scope %s", tn.toChars()); 5152 return Type.terror; 5153 } 5154 next = tn; 5155 transitive(); 5156 return merge(); 5157 } 5158 5159 override void resolve(Loc loc, Scope* sc, Expression* pe, Type* pt, Dsymbol* ps, bool intypeid = false) 5160 { 5161 //printf("TypeDArray::resolve() %s\n", toChars()); 5162 next.resolve(loc, sc, pe, pt, ps, intypeid); 5163 //printf("s = %p, e = %p, t = %p\n", *ps, *pe, *pt); 5164 if (*pe) 5165 { 5166 // It's really a slice expression 5167 if (Dsymbol s = getDsymbol(*pe)) 5168 *pe = new DsymbolExp(loc, s); 5169 *pe = new ArrayExp(loc, *pe); 5170 } 5171 else if (*ps) 5172 { 5173 if (auto tup = (*ps).isTupleDeclaration()) 5174 { 5175 // keep *ps 5176 } 5177 else 5178 goto Ldefault; 5179 } 5180 else 5181 { 5182 if ((*pt).ty != Terror) 5183 next = *pt; // prevent re-running semantic() on 'next' 5184 Ldefault: 5185 Type.resolve(loc, sc, pe, pt, ps, intypeid); 5186 } 5187 } 5188 5189 override Expression dotExp(Scope* sc, Expression e, Identifier ident, int flag) 5190 { 5191 static if (LOGDOTEXP) 5192 { 5193 printf("TypeDArray::dotExp(e = '%s', ident = '%s')\n", e.toChars(), ident.toChars()); 5194 } 5195 if (e.op == TOKtype && (ident == Id.length || ident == Id.ptr)) 5196 { 5197 e.error("%s is not an expression", e.toChars()); 5198 return new ErrorExp(); 5199 } 5200 if (ident == Id.length) 5201 { 5202 if (e.op == TOKstring) 5203 { 5204 StringExp se = cast(StringExp)e; 5205 return new IntegerExp(se.loc, se.len, Type.tsize_t); 5206 } 5207 if (e.op == TOKnull) 5208 return new IntegerExp(e.loc, 0, Type.tsize_t); 5209 if (checkNonAssignmentArrayOp(e)) 5210 return new ErrorExp(); 5211 e = new ArrayLengthExp(e.loc, e); 5212 e.type = Type.tsize_t; 5213 return e; 5214 } 5215 else if (ident == Id.ptr) 5216 { 5217 e = e.castTo(sc, next.pointerTo()); 5218 return e; 5219 } 5220 else 5221 { 5222 e = TypeArray.dotExp(sc, e, ident, flag); 5223 } 5224 return e; 5225 } 5226 5227 override bool isString() 5228 { 5229 TY nty = next.toBasetype().ty; 5230 return nty == Tchar || nty == Twchar || nty == Tdchar; 5231 } 5232 5233 override bool isZeroInit(Loc loc) const 5234 { 5235 return true; 5236 } 5237 5238 override bool isBoolean() const 5239 { 5240 return true; 5241 } 5242 5243 override MATCH implicitConvTo(Type to) 5244 { 5245 //printf("TypeDArray::implicitConvTo(to = %s) this = %s\n", to->toChars(), toChars()); 5246 if (equals(to)) 5247 return MATCHexact; 5248 5249 if (to.ty == Tarray) 5250 { 5251 TypeDArray ta = cast(TypeDArray)to; 5252 5253 if (!MODimplicitConv(next.mod, ta.next.mod)) 5254 return MATCHnomatch; // not const-compatible 5255 5256 /* Allow conversion to void[] 5257 */ 5258 if (next.ty != Tvoid && ta.next.ty == Tvoid) 5259 { 5260 return MATCHconvert; 5261 } 5262 5263 MATCH m = next.constConv(ta.next); 5264 if (m > MATCHnomatch) 5265 { 5266 if (m == MATCHexact && mod != to.mod) 5267 m = MATCHconst; 5268 return m; 5269 } 5270 } 5271 return Type.implicitConvTo(to); 5272 } 5273 5274 override Expression defaultInit(Loc loc) 5275 { 5276 static if (LOGDEFAULTINIT) 5277 { 5278 printf("TypeDArray::defaultInit() '%s'\n", toChars()); 5279 } 5280 return new NullExp(loc, this); 5281 } 5282 5283 override bool hasPointers() const 5284 { 5285 return true; 5286 } 5287 5288 override void accept(Visitor v) 5289 { 5290 v.visit(this); 5291 } 5292 } 5293 5294 /*********************************************************** 5295 */ 5296 extern (C++) final class TypeAArray : TypeArray 5297 { 5298 Type index; // key type 5299 Loc loc; 5300 Scope* sc; 5301 5302 extern (D) this(Type t, Type index) 5303 { 5304 super(Taarray, t); 5305 this.index = index; 5306 } 5307 5308 static TypeAArray create(Type t, Type index) 5309 { 5310 return new TypeAArray(t, index); 5311 } 5312 5313 override const(char)* kind() const 5314 { 5315 return "aarray"; 5316 } 5317 5318 override Type syntaxCopy() 5319 { 5320 Type t = next.syntaxCopy(); 5321 Type ti = index.syntaxCopy(); 5322 if (t == next && ti == index) 5323 t = this; 5324 else 5325 { 5326 t = new TypeAArray(t, ti); 5327 t.mod = mod; 5328 } 5329 return t; 5330 } 5331 5332 override d_uns64 size(Loc loc) 5333 { 5334 return Target.ptrsize; 5335 } 5336 5337 override Type semantic(Loc loc, Scope* sc) 5338 { 5339 //printf("TypeAArray::semantic() %s index->ty = %d\n", toChars(), index->ty); 5340 if (deco) 5341 return this; 5342 5343 this.loc = loc; 5344 this.sc = sc; 5345 if (sc) 5346 sc.setNoFree(); 5347 5348 // Deal with the case where we thought the index was a type, but 5349 // in reality it was an expression. 5350 if (index.ty == Tident || index.ty == Tinstance || index.ty == Tsarray || index.ty == Ttypeof || index.ty == Treturn) 5351 { 5352 Expression e; 5353 Type t; 5354 Dsymbol s; 5355 index.resolve(loc, sc, &e, &t, &s); 5356 if (e) 5357 { 5358 // It was an expression - 5359 // Rewrite as a static array 5360 auto tsa = new TypeSArray(next, e); 5361 return tsa.semantic(loc, sc); 5362 } 5363 else if (t) 5364 index = t.semantic(loc, sc); 5365 else 5366 { 5367 index.error(loc, "index is not a type or an expression"); 5368 return Type.terror; 5369 } 5370 } 5371 else 5372 index = index.semantic(loc, sc); 5373 index = index.merge2(); 5374 5375 if (index.nextOf() && !index.nextOf().isImmutable()) 5376 { 5377 index = index.constOf().mutableOf(); 5378 version (none) 5379 { 5380 printf("index is %p %s\n", index, index.toChars()); 5381 index.check(); 5382 printf("index->mod = x%x\n", index.mod); 5383 printf("index->ito = x%x\n", index.ito); 5384 if (index.ito) 5385 { 5386 printf("index->ito->mod = x%x\n", index.ito.mod); 5387 printf("index->ito->ito = x%x\n", index.ito.ito); 5388 } 5389 } 5390 } 5391 5392 switch (index.toBasetype().ty) 5393 { 5394 case Tfunction: 5395 case Tvoid: 5396 case Tnone: 5397 case Ttuple: 5398 error(loc, "can't have associative array key of %s", index.toBasetype().toChars()); 5399 goto case Terror; 5400 case Terror: 5401 return Type.terror; 5402 default: 5403 break; 5404 } 5405 Type tbase = index.baseElemOf(); 5406 while (tbase.ty == Tarray) 5407 tbase = tbase.nextOf().baseElemOf(); 5408 if (tbase.ty == Tstruct) 5409 { 5410 /* AA's need typeid(index).equals() and getHash(). Issue error if not correctly set up. 5411 */ 5412 StructDeclaration sd = (cast(TypeStruct)tbase).sym; 5413 if (sd._scope) 5414 sd.semantic(null); 5415 5416 // duplicate a part of StructDeclaration::semanticTypeInfoMembers 5417 if (sd.xeq && sd.xeq._scope && sd.xeq.semanticRun < PASSsemantic3done) 5418 { 5419 uint errors = global.startGagging(); 5420 sd.xeq.semantic3(sd.xeq._scope); 5421 if (global.endGagging(errors)) 5422 sd.xeq = sd.xerreq; 5423 } 5424 5425 //printf("AA = %s, key: xeq = %p, xhash = %p\n", toChars(), sd->xeq, sd->xhash); 5426 const(char)* s = (index.toBasetype().ty != Tstruct) ? "bottom of " : ""; 5427 if (!sd.xeq) 5428 { 5429 // If sd->xhash != NULL: 5430 // sd or its fields have user-defined toHash. 5431 // AA assumes that its result is consistent with bitwise equality. 5432 // else: 5433 // bitwise equality & hashing 5434 } 5435 else if (sd.xeq == sd.xerreq) 5436 { 5437 if (search_function(sd, Id.eq)) 5438 { 5439 error(loc, "%sAA key type %s does not have 'bool opEquals(ref const %s) const'", s, sd.toChars(), sd.toChars()); 5440 } 5441 else 5442 { 5443 error(loc, "%sAA key type %s does not support const equality", s, sd.toChars()); 5444 } 5445 return Type.terror; 5446 } 5447 else if (!sd.xhash) 5448 { 5449 if (search_function(sd, Id.eq)) 5450 { 5451 error(loc, "%sAA key type %s should have 'size_t toHash() const nothrow @safe' if opEquals defined", s, sd.toChars()); 5452 } 5453 else 5454 { 5455 error(loc, "%sAA key type %s supports const equality but doesn't support const hashing", s, sd.toChars()); 5456 } 5457 return Type.terror; 5458 } 5459 else 5460 { 5461 // defined equality & hashing 5462 assert(sd.xeq && sd.xhash); 5463 5464 /* xeq and xhash may be implicitly defined by compiler. For example: 5465 * struct S { int[] arr; } 5466 * With 'arr' field equality and hashing, compiler will implicitly 5467 * generate functions for xopEquals and xtoHash in TypeInfo_Struct. 5468 */ 5469 } 5470 } 5471 else if (tbase.ty == Tclass && !(cast(TypeClass)tbase).sym.isInterfaceDeclaration()) 5472 { 5473 ClassDeclaration cd = (cast(TypeClass)tbase).sym; 5474 if (cd._scope) 5475 cd.semantic(null); 5476 5477 if (!ClassDeclaration.object) 5478 { 5479 error(Loc(), "missing or corrupt object.d"); 5480 fatal(); 5481 } 5482 5483 static __gshared FuncDeclaration feq = null; 5484 static __gshared FuncDeclaration fcmp = null; 5485 static __gshared FuncDeclaration fhash = null; 5486 if (!feq) 5487 feq = search_function(ClassDeclaration.object, Id.eq).isFuncDeclaration(); 5488 if (!fcmp) 5489 fcmp = search_function(ClassDeclaration.object, Id.cmp).isFuncDeclaration(); 5490 if (!fhash) 5491 fhash = search_function(ClassDeclaration.object, Id.tohash).isFuncDeclaration(); 5492 assert(fcmp && feq && fhash); 5493 5494 if (feq.vtblIndex < cd.vtbl.dim && cd.vtbl[feq.vtblIndex] == feq) 5495 { 5496 version (all) 5497 { 5498 if (fcmp.vtblIndex < cd.vtbl.dim && cd.vtbl[fcmp.vtblIndex] != fcmp) 5499 { 5500 const(char)* s = (index.toBasetype().ty != Tclass) ? "bottom of " : ""; 5501 error(loc, "%sAA key type %s now requires equality rather than comparison", s, cd.toChars()); 5502 errorSupplemental(loc, "Please override Object.opEquals and toHash."); 5503 } 5504 } 5505 } 5506 } 5507 next = next.semantic(loc, sc).merge2(); 5508 transitive(); 5509 5510 switch (next.toBasetype().ty) 5511 { 5512 case Tfunction: 5513 case Tvoid: 5514 case Tnone: 5515 case Ttuple: 5516 error(loc, "can't have associative array of %s", next.toChars()); 5517 goto case Terror; 5518 case Terror: 5519 return Type.terror; 5520 default: 5521 break; 5522 } 5523 if (next.isscope()) 5524 { 5525 error(loc, "cannot have array of scope %s", next.toChars()); 5526 return Type.terror; 5527 } 5528 return merge(); 5529 } 5530 5531 override void resolve(Loc loc, Scope* sc, Expression* pe, Type* pt, Dsymbol* ps, bool intypeid = false) 5532 { 5533 //printf("TypeAArray::resolve() %s\n", toChars()); 5534 // Deal with the case where we thought the index was a type, but 5535 // in reality it was an expression. 5536 if (index.ty == Tident || index.ty == Tinstance || index.ty == Tsarray) 5537 { 5538 Expression e; 5539 Type t; 5540 Dsymbol s; 5541 index.resolve(loc, sc, &e, &t, &s, intypeid); 5542 if (e) 5543 { 5544 // It was an expression - 5545 // Rewrite as a static array 5546 auto tsa = new TypeSArray(next, e); 5547 tsa.mod = this.mod; // just copy mod field so tsa's semantic is not yet done 5548 return tsa.resolve(loc, sc, pe, pt, ps, intypeid); 5549 } 5550 else if (t) 5551 index = t; 5552 else 5553 index.error(loc, "index is not a type or an expression"); 5554 } 5555 Type.resolve(loc, sc, pe, pt, ps, intypeid); 5556 } 5557 5558 override Expression dotExp(Scope* sc, Expression e, Identifier ident, int flag) 5559 { 5560 static if (LOGDOTEXP) 5561 { 5562 printf("TypeAArray::dotExp(e = '%s', ident = '%s')\n", e.toChars(), ident.toChars()); 5563 } 5564 if (ident == Id.length) 5565 { 5566 static __gshared FuncDeclaration fd_aaLen = null; 5567 if (fd_aaLen is null) 5568 { 5569 auto fparams = new Parameters(); 5570 fparams.push(new Parameter(STCin, this, null, null)); 5571 fd_aaLen = FuncDeclaration.genCfunc(fparams, Type.tsize_t, Id.aaLen); 5572 TypeFunction tf = cast(TypeFunction)fd_aaLen.type; 5573 tf.purity = PUREconst; 5574 tf.isnothrow = true; 5575 tf.isnogc = false; 5576 } 5577 Expression ev = new VarExp(e.loc, fd_aaLen, false); 5578 e = new CallExp(e.loc, ev, e); 5579 e.type = (cast(TypeFunction)fd_aaLen.type).next; 5580 } 5581 else 5582 e = Type.dotExp(sc, e, ident, flag); 5583 return e; 5584 } 5585 5586 override Expression defaultInit(Loc loc) 5587 { 5588 static if (LOGDEFAULTINIT) 5589 { 5590 printf("TypeAArray::defaultInit() '%s'\n", toChars()); 5591 } 5592 return new NullExp(loc, this); 5593 } 5594 5595 override bool isZeroInit(Loc loc) const 5596 { 5597 return true; 5598 } 5599 5600 override bool isBoolean() const 5601 { 5602 return true; 5603 } 5604 5605 override Expression toExpression() 5606 { 5607 Expression e = next.toExpression(); 5608 if (e) 5609 { 5610 Expression ei = index.toExpression(); 5611 if (ei) 5612 return new ArrayExp(loc, e, ei); 5613 } 5614 return null; 5615 } 5616 5617 override bool hasPointers() const 5618 { 5619 return true; 5620 } 5621 5622 override MATCH implicitConvTo(Type to) 5623 { 5624 //printf("TypeAArray::implicitConvTo(to = %s) this = %s\n", to->toChars(), toChars()); 5625 if (equals(to)) 5626 return MATCHexact; 5627 5628 if (to.ty == Taarray) 5629 { 5630 TypeAArray ta = cast(TypeAArray)to; 5631 5632 if (!MODimplicitConv(next.mod, ta.next.mod)) 5633 return MATCHnomatch; // not const-compatible 5634 5635 if (!MODimplicitConv(index.mod, ta.index.mod)) 5636 return MATCHnomatch; // not const-compatible 5637 5638 MATCH m = next.constConv(ta.next); 5639 MATCH mi = index.constConv(ta.index); 5640 if (m > MATCHnomatch && mi > MATCHnomatch) 5641 { 5642 return MODimplicitConv(mod, to.mod) ? MATCHconst : MATCHnomatch; 5643 } 5644 } 5645 return Type.implicitConvTo(to); 5646 } 5647 5648 override MATCH constConv(Type to) 5649 { 5650 if (to.ty == Taarray) 5651 { 5652 TypeAArray taa = cast(TypeAArray)to; 5653 MATCH mindex = index.constConv(taa.index); 5654 MATCH mkey = next.constConv(taa.next); 5655 // Pick the worst match 5656 return mkey < mindex ? mkey : mindex; 5657 } 5658 return Type.constConv(to); 5659 } 5660 5661 override void accept(Visitor v) 5662 { 5663 v.visit(this); 5664 } 5665 } 5666 5667 /*********************************************************** 5668 */ 5669 extern (C++) final class TypePointer : TypeNext 5670 { 5671 extern (D) this(Type t) 5672 { 5673 super(Tpointer, t); 5674 } 5675 5676 override const(char)* kind() const 5677 { 5678 return "pointer"; 5679 } 5680 5681 override Type syntaxCopy() 5682 { 5683 Type t = next.syntaxCopy(); 5684 if (t == next) 5685 t = this; 5686 else 5687 { 5688 t = new TypePointer(t); 5689 t.mod = mod; 5690 } 5691 return t; 5692 } 5693 5694 override Type semantic(Loc loc, Scope* sc) 5695 { 5696 //printf("TypePointer::semantic() %s\n", toChars()); 5697 if (deco) 5698 return this; 5699 Type n = next.semantic(loc, sc); 5700 switch (n.toBasetype().ty) 5701 { 5702 case Ttuple: 5703 error(loc, "can't have pointer to %s", n.toChars()); 5704 goto case Terror; 5705 case Terror: 5706 return Type.terror; 5707 default: 5708 break; 5709 } 5710 if (n != next) 5711 { 5712 deco = null; 5713 } 5714 next = n; 5715 if (next.ty != Tfunction) 5716 { 5717 transitive(); 5718 return merge(); 5719 } 5720 version (none) 5721 { 5722 return merge(); 5723 } 5724 else 5725 { 5726 deco = merge().deco; 5727 /* Don't return merge(), because arg identifiers and default args 5728 * can be different 5729 * even though the types match 5730 */ 5731 return this; 5732 } 5733 } 5734 5735 override d_uns64 size(Loc loc) const 5736 { 5737 return Target.ptrsize; 5738 } 5739 5740 override MATCH implicitConvTo(Type to) 5741 { 5742 //printf("TypePointer::implicitConvTo(to = %s) %s\n", to->toChars(), toChars()); 5743 if (equals(to)) 5744 return MATCHexact; 5745 5746 if (next.ty == Tfunction) 5747 { 5748 if (to.ty == Tpointer) 5749 { 5750 TypePointer tp = cast(TypePointer)to; 5751 if (tp.next.ty == Tfunction) 5752 { 5753 if (next.equals(tp.next)) 5754 return MATCHconst; 5755 5756 if (next.covariant(tp.next) == 1) 5757 { 5758 Type tret = this.next.nextOf(); 5759 Type toret = tp.next.nextOf(); 5760 if (tret.ty == Tclass && toret.ty == Tclass) 5761 { 5762 /* Bugzilla 10219: Check covariant interface return with offset tweaking. 5763 * interface I {} 5764 * class C : Object, I {} 5765 * I function() dg = function C() {} // should be error 5766 */ 5767 int offset = 0; 5768 if (toret.isBaseOf(tret, &offset) && offset != 0) 5769 return MATCHnomatch; 5770 } 5771 return MATCHconvert; 5772 } 5773 } 5774 else if (tp.next.ty == Tvoid) 5775 { 5776 // Allow conversions to void* 5777 return MATCHconvert; 5778 } 5779 } 5780 return MATCHnomatch; 5781 } 5782 else if (to.ty == Tpointer) 5783 { 5784 TypePointer tp = cast(TypePointer)to; 5785 assert(tp.next); 5786 5787 if (!MODimplicitConv(next.mod, tp.next.mod)) 5788 return MATCHnomatch; // not const-compatible 5789 5790 /* Alloc conversion to void* 5791 */ 5792 if (next.ty != Tvoid && tp.next.ty == Tvoid) 5793 { 5794 return MATCHconvert; 5795 } 5796 5797 MATCH m = next.constConv(tp.next); 5798 if (m > MATCHnomatch) 5799 { 5800 if (m == MATCHexact && mod != to.mod) 5801 m = MATCHconst; 5802 return m; 5803 } 5804 } 5805 return MATCHnomatch; 5806 } 5807 5808 override MATCH constConv(Type to) 5809 { 5810 if (next.ty == Tfunction) 5811 { 5812 if (to.nextOf() && next.equals((cast(TypeNext)to).next)) 5813 return Type.constConv(to); 5814 else 5815 return MATCHnomatch; 5816 } 5817 return TypeNext.constConv(to); 5818 } 5819 5820 override bool isscalar() const 5821 { 5822 return true; 5823 } 5824 5825 override Expression defaultInit(Loc loc) 5826 { 5827 static if (LOGDEFAULTINIT) 5828 { 5829 printf("TypePointer::defaultInit() '%s'\n", toChars()); 5830 } 5831 return new NullExp(loc, this); 5832 } 5833 5834 override bool isZeroInit(Loc loc) const 5835 { 5836 return true; 5837 } 5838 5839 override bool hasPointers() const 5840 { 5841 return true; 5842 } 5843 5844 override void accept(Visitor v) 5845 { 5846 v.visit(this); 5847 } 5848 } 5849 5850 /*********************************************************** 5851 */ 5852 extern (C++) final class TypeReference : TypeNext 5853 { 5854 extern (D) this(Type t) 5855 { 5856 super(Treference, t); 5857 // BUG: what about references to static arrays? 5858 } 5859 5860 override const(char)* kind() const 5861 { 5862 return "reference"; 5863 } 5864 5865 override Type syntaxCopy() 5866 { 5867 Type t = next.syntaxCopy(); 5868 if (t == next) 5869 t = this; 5870 else 5871 { 5872 t = new TypeReference(t); 5873 t.mod = mod; 5874 } 5875 return t; 5876 } 5877 5878 override Type semantic(Loc loc, Scope* sc) 5879 { 5880 //printf("TypeReference::semantic()\n"); 5881 Type n = next.semantic(loc, sc); 5882 if (n != next) 5883 deco = null; 5884 next = n; 5885 transitive(); 5886 return merge(); 5887 } 5888 5889 override d_uns64 size(Loc loc) const 5890 { 5891 return Target.ptrsize; 5892 } 5893 5894 override Expression dotExp(Scope* sc, Expression e, Identifier ident, int flag) 5895 { 5896 static if (LOGDOTEXP) 5897 { 5898 printf("TypeReference::dotExp(e = '%s', ident = '%s')\n", e.toChars(), ident.toChars()); 5899 } 5900 // References just forward things along 5901 return next.dotExp(sc, e, ident, flag); 5902 } 5903 5904 override Expression defaultInit(Loc loc) 5905 { 5906 static if (LOGDEFAULTINIT) 5907 { 5908 printf("TypeReference::defaultInit() '%s'\n", toChars()); 5909 } 5910 return new NullExp(loc, this); 5911 } 5912 5913 override bool isZeroInit(Loc loc) const 5914 { 5915 return true; 5916 } 5917 5918 override void accept(Visitor v) 5919 { 5920 v.visit(this); 5921 } 5922 } 5923 5924 enum RET : int 5925 { 5926 RETregs = 1, // returned in registers 5927 RETstack = 2, // returned on stack 5928 } 5929 5930 alias RETregs = RET.RETregs; 5931 alias RETstack = RET.RETstack; 5932 5933 enum TRUST : int 5934 { 5935 TRUSTdefault = 0, 5936 TRUSTsystem = 1, // @system (same as TRUSTdefault) 5937 TRUSTtrusted = 2, // @trusted 5938 TRUSTsafe = 3, // @safe 5939 } 5940 5941 alias TRUSTdefault = TRUST.TRUSTdefault; 5942 alias TRUSTsystem = TRUST.TRUSTsystem; 5943 alias TRUSTtrusted = TRUST.TRUSTtrusted; 5944 alias TRUSTsafe = TRUST.TRUSTsafe; 5945 5946 enum TRUSTformat : int 5947 { 5948 TRUSTformatDefault, // do not emit @system when trust == TRUSTdefault 5949 TRUSTformatSystem, // emit @system when trust == TRUSTdefault 5950 } 5951 5952 alias TRUSTformatDefault = TRUSTformat.TRUSTformatDefault; 5953 alias TRUSTformatSystem = TRUSTformat.TRUSTformatSystem; 5954 5955 enum PURE : int 5956 { 5957 PUREimpure = 0, // not pure at all 5958 PUREfwdref = 1, // it's pure, but not known which level yet 5959 PUREweak = 2, // no mutable globals are read or written 5960 PUREconst = 3, // parameters are values or const 5961 PUREstrong = 4, // parameters are values or immutable 5962 } 5963 5964 alias PUREimpure = PURE.PUREimpure; 5965 alias PUREfwdref = PURE.PUREfwdref; 5966 alias PUREweak = PURE.PUREweak; 5967 alias PUREconst = PURE.PUREconst; 5968 alias PUREstrong = PURE.PUREstrong; 5969 5970 /*********************************************************** 5971 */ 5972 extern (C++) final class TypeFunction : TypeNext 5973 { 5974 // .next is the return type 5975 5976 Parameters* parameters; // function parameters 5977 int varargs; // 1: T t, ...) style for variable number of arguments 5978 // 2: T t ...) style for variable number of arguments 5979 bool isnothrow; // true: nothrow 5980 bool isnogc; // true: is @nogc 5981 bool isproperty; // can be called without parentheses 5982 bool isref; // true: returns a reference 5983 bool isreturn; // true: 'this' is returned by ref 5984 bool isscope; // true: 'this' is scope 5985 LINK linkage; // calling convention 5986 TRUST trust; // level of trust 5987 PURE purity = PUREimpure; 5988 ubyte iswild; // bit0: inout on params, bit1: inout on qualifier 5989 Expressions* fargs; // function arguments 5990 int inuse; 5991 5992 extern (D) this(Parameters* parameters, Type treturn, int varargs, LINK linkage, StorageClass stc = 0) 5993 { 5994 super(Tfunction, treturn); 5995 //if (!treturn) *(char*)0=0; 5996 // assert(treturn); 5997 assert(0 <= varargs && varargs <= 2); 5998 this.parameters = parameters; 5999 this.varargs = varargs; 6000 this.linkage = linkage; 6001 6002 if (stc & STCpure) 6003 this.purity = PUREfwdref; 6004 if (stc & STCnothrow) 6005 this.isnothrow = true; 6006 if (stc & STCnogc) 6007 this.isnogc = true; 6008 if (stc & STCproperty) 6009 this.isproperty = true; 6010 6011 if (stc & STCref) 6012 this.isref = true; 6013 if (stc & STCreturn) 6014 this.isreturn = true; 6015 if (stc & STCscope) 6016 this.isscope = true; 6017 6018 this.trust = TRUSTdefault; 6019 if (stc & STCsafe) 6020 this.trust = TRUSTsafe; 6021 if (stc & STCsystem) 6022 this.trust = TRUSTsystem; 6023 if (stc & STCtrusted) 6024 this.trust = TRUSTtrusted; 6025 } 6026 6027 static TypeFunction create(Parameters* parameters, Type treturn, int varargs, LINK linkage, StorageClass stc = 0) 6028 { 6029 return new TypeFunction(parameters, treturn, varargs, linkage, stc); 6030 } 6031 6032 override const(char)* kind() const 6033 { 6034 return "function"; 6035 } 6036 6037 override Type syntaxCopy() 6038 { 6039 Type treturn = next ? next.syntaxCopy() : null; 6040 Parameters* params = Parameter.arraySyntaxCopy(parameters); 6041 auto t = new TypeFunction(params, treturn, varargs, linkage); 6042 t.mod = mod; 6043 t.isnothrow = isnothrow; 6044 t.isnogc = isnogc; 6045 t.purity = purity; 6046 t.isproperty = isproperty; 6047 t.isref = isref; 6048 t.isreturn = isreturn; 6049 t.isscope = isscope; 6050 t.iswild = iswild; 6051 t.trust = trust; 6052 t.fargs = fargs; 6053 return t; 6054 } 6055 6056 override Type semantic(Loc loc, Scope* sc) 6057 { 6058 if (deco) // if semantic() already run 6059 { 6060 //printf("already done\n"); 6061 return this; 6062 } 6063 //printf("TypeFunction::semantic() this = %p\n", this); 6064 //printf("TypeFunction::semantic() %s, sc->stc = %llx, fargs = %p\n", toChars(), sc->stc, fargs); 6065 6066 bool errors = false; 6067 6068 /* Copy in order to not mess up original. 6069 * This can produce redundant copies if inferring return type, 6070 * as semantic() will get called again on this. 6071 */ 6072 TypeFunction tf = cast(TypeFunction)copy(); 6073 if (parameters) 6074 { 6075 tf.parameters = parameters.copy(); 6076 for (size_t i = 0; i < parameters.dim; i++) 6077 { 6078 Parameter p = cast(Parameter)mem.xmalloc(__traits(classInstanceSize, Parameter)); 6079 memcpy(cast(void*)p, cast(void*)(*parameters)[i], __traits(classInstanceSize, Parameter)); 6080 (*tf.parameters)[i] = p; 6081 } 6082 } 6083 6084 if (sc.stc & STCpure) 6085 tf.purity = PUREfwdref; 6086 if (sc.stc & STCnothrow) 6087 tf.isnothrow = true; 6088 if (sc.stc & STCnogc) 6089 tf.isnogc = true; 6090 if (sc.stc & STCref) 6091 tf.isref = true; 6092 if (sc.stc & STCreturn) 6093 tf.isreturn = true; 6094 if (sc.stc & STCscope) 6095 tf.isscope = true; 6096 6097 if ((sc.stc & (STCreturn | STCref)) == STCreturn) 6098 tf.isscope = true; // return by itself means 'return scope' 6099 6100 if (tf.trust == TRUSTdefault) 6101 { 6102 if (sc.stc & STCsafe) 6103 tf.trust = TRUSTsafe; 6104 else if (sc.stc & STCsystem) 6105 tf.trust = TRUSTsystem; 6106 else if (sc.stc & STCtrusted) 6107 tf.trust = TRUSTtrusted; 6108 } 6109 6110 if (sc.stc & STCproperty) 6111 tf.isproperty = true; 6112 6113 tf.linkage = sc.linkage; 6114 version (none) 6115 { 6116 /* If the parent is @safe, then this function defaults to safe 6117 * too. 6118 * If the parent's @safe-ty is inferred, then this function's @safe-ty needs 6119 * to be inferred first. 6120 */ 6121 if (tf.trust == TRUSTdefault) 6122 for (Dsymbol p = sc.func; p; p = p.toParent2()) 6123 { 6124 FuncDeclaration fd = p.isFuncDeclaration(); 6125 if (fd) 6126 { 6127 if (fd.isSafeBypassingInference()) 6128 tf.trust = TRUSTsafe; // default to @safe 6129 break; 6130 } 6131 } 6132 } 6133 6134 bool wildreturn = false; 6135 if (tf.next) 6136 { 6137 sc = sc.push(); 6138 sc.stc &= ~(STC_TYPECTOR | STC_FUNCATTR); 6139 tf.next = tf.next.semantic(loc, sc); 6140 sc = sc.pop(); 6141 errors |= tf.checkRetType(loc); 6142 if (tf.next.isscope() && !(sc.flags & SCOPEctor)) 6143 { 6144 error(loc, "functions cannot return scope %s", tf.next.toChars()); 6145 errors = true; 6146 } 6147 if (tf.next.hasWild()) 6148 wildreturn = true; 6149 6150 if (tf.isreturn && !tf.isref && !tf.next.hasPointers()) 6151 { 6152 error(loc, "function has 'return' but does not return any indirections"); 6153 } 6154 } 6155 6156 ubyte wildparams = 0; 6157 if (tf.parameters) 6158 { 6159 /* Create a scope for evaluating the default arguments for the parameters 6160 */ 6161 Scope* argsc = sc.push(); 6162 argsc.stc = 0; // don't inherit storage class 6163 argsc.protection = Prot(PROTpublic); 6164 argsc.func = null; 6165 6166 size_t dim = Parameter.dim(tf.parameters); 6167 for (size_t i = 0; i < dim; i++) 6168 { 6169 Parameter fparam = Parameter.getNth(tf.parameters, i); 6170 tf.inuse++; 6171 fparam.type = fparam.type.semantic(loc, argsc); 6172 if (tf.inuse == 1) 6173 tf.inuse--; 6174 if (fparam.type.ty == Terror) 6175 { 6176 errors = true; 6177 continue; 6178 } 6179 6180 fparam.type = fparam.type.addStorageClass(fparam.storageClass); 6181 6182 if (fparam.storageClass & (STCauto | STCalias | STCstatic)) 6183 { 6184 if (!fparam.type) 6185 continue; 6186 } 6187 6188 Type t = fparam.type.toBasetype(); 6189 6190 if (t.ty == Tfunction) 6191 { 6192 error(loc, "cannot have parameter of function type %s", fparam.type.toChars()); 6193 errors = true; 6194 } 6195 else if (!(fparam.storageClass & (STCref | STCout)) && 6196 (t.ty == Tstruct || t.ty == Tsarray || t.ty == Tenum)) 6197 { 6198 Type tb2 = t.baseElemOf(); 6199 if (tb2.ty == Tstruct && !(cast(TypeStruct)tb2).sym.members || 6200 tb2.ty == Tenum && !(cast(TypeEnum)tb2).sym.memtype) 6201 { 6202 error(loc, "cannot have parameter of opaque type %s by value", fparam.type.toChars()); 6203 errors = true; 6204 } 6205 } 6206 else if (!(fparam.storageClass & STClazy) && t.ty == Tvoid) 6207 { 6208 error(loc, "cannot have parameter of type %s", fparam.type.toChars()); 6209 errors = true; 6210 } 6211 6212 if ((fparam.storageClass & (STCref | STCwild)) == (STCref | STCwild)) 6213 { 6214 // 'ref inout' implies 'return' 6215 fparam.storageClass |= STCreturn; 6216 } 6217 6218 if (fparam.storageClass & STCreturn) 6219 { 6220 if (fparam.storageClass & (STCref | STCout)) 6221 { 6222 // Disabled for the moment awaiting improvement to allow return by ref 6223 // to be transformed into return by scope. 6224 if (0 && !tf.isref) 6225 { 6226 auto stc = fparam.storageClass & (STCref | STCout); 6227 error(loc, "parameter %s is 'return %s' but function does not return by ref", 6228 fparam.ident ? fparam.ident.toChars() : "", 6229 stcToChars(stc)); 6230 errors = true; 6231 } 6232 } 6233 else 6234 { 6235 fparam.storageClass |= STCscope; // 'return' implies 'scope' 6236 if (tf.isref) 6237 { 6238 error(loc, "parameter %s is 'return' but function returns 'ref'", 6239 fparam.ident ? fparam.ident.toChars() : ""); 6240 errors = true; 6241 } 6242 else if (tf.next && !tf.next.hasPointers()) 6243 { 6244 error(loc, "parameter %s is 'return' but function does not return any indirections", 6245 fparam.ident ? fparam.ident.toChars() : ""); 6246 errors = true; 6247 } 6248 } 6249 } 6250 6251 if (fparam.storageClass & (STCref | STClazy)) 6252 { 6253 } 6254 else if (fparam.storageClass & STCout) 6255 { 6256 if (ubyte m = fparam.type.mod & (MODimmutable | MODconst | MODwild)) 6257 { 6258 error(loc, "cannot have %s out parameter of type %s", MODtoChars(m), t.toChars()); 6259 errors = true; 6260 } 6261 else 6262 { 6263 Type tv = t; 6264 while (tv.ty == Tsarray) 6265 tv = tv.nextOf().toBasetype(); 6266 if (tv.ty == Tstruct && (cast(TypeStruct)tv).sym.noDefaultCtor) 6267 { 6268 error(loc, "cannot have out parameter of type %s because the default construction is disabled", fparam.type.toChars()); 6269 errors = true; 6270 } 6271 } 6272 } 6273 6274 if (fparam.storageClass & STCscope && !fparam.type.hasPointers()) 6275 fparam.storageClass &= ~(STCreturn | STCscope); 6276 6277 if (t.hasWild()) 6278 { 6279 wildparams |= 1; 6280 //if (tf->next && !wildreturn) 6281 // error(loc, "inout on parameter means inout must be on return type as well (if from D1 code, replace with 'ref')"); 6282 } 6283 6284 if (fparam.defaultArg) 6285 { 6286 Expression e = fparam.defaultArg; 6287 if (fparam.storageClass & (STCref | STCout)) 6288 { 6289 e = e.semantic(argsc); 6290 e = resolveProperties(argsc, e); 6291 } 6292 else 6293 { 6294 e = inferType(e, fparam.type); 6295 Initializer iz = new ExpInitializer(e.loc, e); 6296 iz = iz.semantic(argsc, fparam.type, INITnointerpret); 6297 e = iz.toExpression(); 6298 } 6299 if (e.op == TOKfunction) // see Bugzilla 4820 6300 { 6301 FuncExp fe = cast(FuncExp)e; 6302 // Replace function literal with a function symbol, 6303 // since default arg expression must be copied when used 6304 // and copying the literal itself is wrong. 6305 e = new VarExp(e.loc, fe.fd, false); 6306 e = new AddrExp(e.loc, e); 6307 e = e.semantic(argsc); 6308 } 6309 e = e.implicitCastTo(argsc, fparam.type); 6310 6311 // default arg must be an lvalue 6312 if (fparam.storageClass & (STCout | STCref)) 6313 e = e.toLvalue(argsc, e); 6314 6315 fparam.defaultArg = e; 6316 if (e.op == TOKerror) 6317 errors = true; 6318 } 6319 6320 /* If fparam after semantic() turns out to be a tuple, the number of parameters may 6321 * change. 6322 */ 6323 if (t.ty == Ttuple) 6324 { 6325 /* TypeFunction::parameter also is used as the storage of 6326 * Parameter objects for FuncDeclaration. So we should copy 6327 * the elements of TypeTuple::arguments to avoid unintended 6328 * sharing of Parameter object among other functions. 6329 */ 6330 TypeTuple tt = cast(TypeTuple)t; 6331 if (tt.arguments && tt.arguments.dim) 6332 { 6333 /* Propagate additional storage class from tuple parameters to their 6334 * element-parameters. 6335 * Make a copy, as original may be referenced elsewhere. 6336 */ 6337 size_t tdim = tt.arguments.dim; 6338 auto newparams = new Parameters(); 6339 newparams.setDim(tdim); 6340 for (size_t j = 0; j < tdim; j++) 6341 { 6342 Parameter narg = (*tt.arguments)[j]; 6343 6344 // Bugzilla 12744: If the storage classes of narg 6345 // conflict with the ones in fparam, it's ignored. 6346 StorageClass stc = fparam.storageClass | narg.storageClass; 6347 StorageClass stc1 = fparam.storageClass & (STCref | STCout | STClazy); 6348 StorageClass stc2 = narg.storageClass & (STCref | STCout | STClazy); 6349 if (stc1 && stc2 && stc1 != stc2) 6350 { 6351 OutBuffer buf1; stcToBuffer(&buf1, stc1 | ((stc1 & STCref) ? (fparam.storageClass & STCauto) : 0)); 6352 OutBuffer buf2; stcToBuffer(&buf2, stc2); 6353 6354 error(loc, "incompatible parameter storage classes '%s' and '%s'", 6355 buf1.peekString(), buf2.peekString()); 6356 errors = true; 6357 stc = stc1 | (stc & ~(STCref | STCout | STClazy)); 6358 } 6359 6360 (*newparams)[j] = new Parameter( 6361 stc, narg.type, narg.ident, narg.defaultArg); 6362 } 6363 fparam.type = new TypeTuple(newparams); 6364 } 6365 fparam.storageClass = 0; 6366 6367 /* Reset number of parameters, and back up one to do this fparam again, 6368 * now that it is a tuple 6369 */ 6370 dim = Parameter.dim(tf.parameters); 6371 i--; 6372 continue; 6373 } 6374 6375 /* Resolve "auto ref" storage class to be either ref or value, 6376 * based on the argument matching the parameter 6377 */ 6378 if (fparam.storageClass & STCauto) 6379 { 6380 if (fargs && i < fargs.dim && (fparam.storageClass & STCref)) 6381 { 6382 Expression farg = (*fargs)[i]; 6383 if (farg.isLvalue()) 6384 { 6385 // ref parameter 6386 } 6387 else 6388 fparam.storageClass &= ~STCref; // value parameter 6389 fparam.storageClass &= ~STCauto; // Bugzilla 14656 6390 fparam.storageClass |= STCautoref; 6391 } 6392 else 6393 { 6394 error(loc, "'auto' can only be used as part of 'auto ref' for template function parameters"); 6395 errors = true; 6396 } 6397 } 6398 6399 // Remove redundant storage classes for type, they are already applied 6400 fparam.storageClass &= ~(STC_TYPECTOR | STCin); 6401 } 6402 argsc.pop(); 6403 } 6404 if (tf.isWild()) 6405 wildparams |= 2; 6406 6407 if (wildreturn && !wildparams) 6408 { 6409 error(loc, "inout on return means inout must be on a parameter as well for %s", toChars()); 6410 errors = true; 6411 } 6412 tf.iswild = wildparams; 6413 6414 if (tf.inuse) 6415 { 6416 error(loc, "recursive type"); 6417 tf.inuse = 0; 6418 errors = true; 6419 } 6420 6421 if (tf.isproperty && (tf.varargs || Parameter.dim(tf.parameters) > 2)) 6422 { 6423 error(loc, "properties can only have zero, one, or two parameter"); 6424 errors = true; 6425 } 6426 6427 if (tf.varargs == 1 && tf.linkage != LINKd && Parameter.dim(tf.parameters) == 0) 6428 { 6429 error(loc, "variadic functions with non-D linkage must have at least one parameter"); 6430 errors = true; 6431 } 6432 6433 if (errors) 6434 return terror; 6435 6436 if (tf.next) 6437 tf.deco = tf.merge().deco; 6438 6439 /* Don't return merge(), because arg identifiers and default args 6440 * can be different 6441 * even though the types match 6442 */ 6443 return tf; 6444 } 6445 6446 /******************************************** 6447 * Do this lazily, as the parameter types might be forward referenced. 6448 */ 6449 void purityLevel() 6450 { 6451 TypeFunction tf = this; 6452 if (tf.purity != PUREfwdref) 6453 return; 6454 6455 /* Evaluate what kind of purity based on the modifiers for the parameters 6456 */ 6457 tf.purity = PUREstrong; // assume strong until something weakens it 6458 6459 size_t dim = Parameter.dim(tf.parameters); 6460 if (!dim) 6461 return; 6462 for (size_t i = 0; i < dim; i++) 6463 { 6464 Parameter fparam = Parameter.getNth(tf.parameters, i); 6465 Type t = fparam.type; 6466 if (!t) 6467 continue; 6468 6469 if (fparam.storageClass & (STClazy | STCout)) 6470 { 6471 tf.purity = PUREweak; 6472 break; 6473 } 6474 if (fparam.storageClass & STCref) 6475 { 6476 if (t.mod & MODimmutable) 6477 continue; 6478 if (t.mod & (MODconst | MODwild)) 6479 { 6480 tf.purity = PUREconst; 6481 continue; 6482 } 6483 tf.purity = PUREweak; 6484 break; 6485 } 6486 6487 t = t.baseElemOf(); 6488 if (!t.hasPointers()) 6489 continue; 6490 if (t.mod & MODimmutable) 6491 continue; 6492 6493 /* Accept immutable(T)[] and immutable(T)* as being strongly pure 6494 */ 6495 if (t.ty == Tarray || t.ty == Tpointer) 6496 { 6497 Type tn = t.nextOf().toBasetype(); 6498 if (tn.mod & MODimmutable) 6499 continue; 6500 if (tn.mod & (MODconst | MODwild)) 6501 { 6502 tf.purity = PUREconst; 6503 continue; 6504 } 6505 } 6506 6507 /* The rest of this is too strict; fix later. 6508 * For example, the only pointer members of a struct may be immutable, 6509 * which would maintain strong purity. 6510 */ 6511 if (t.mod & (MODconst | MODwild)) 6512 { 6513 tf.purity = PUREconst; 6514 continue; 6515 } 6516 6517 /* Should catch delegates and function pointers, and fold in their purity 6518 */ 6519 tf.purity = PUREweak; // err on the side of too strict 6520 break; 6521 } 6522 } 6523 6524 /******************************************** 6525 * Return true if there are lazy parameters. 6526 */ 6527 bool hasLazyParameters() 6528 { 6529 size_t dim = Parameter.dim(parameters); 6530 for (size_t i = 0; i < dim; i++) 6531 { 6532 Parameter fparam = Parameter.getNth(parameters, i); 6533 if (fparam.storageClass & STClazy) 6534 return true; 6535 } 6536 return false; 6537 } 6538 6539 /*************************** 6540 * Examine function signature for parameter p and see if 6541 * p can 'escape' the scope of the function. 6542 */ 6543 bool parameterEscapes(Parameter p) 6544 { 6545 purityLevel(); 6546 6547 /* Scope parameters do not escape. 6548 * Allow 'lazy' to imply 'scope' - 6549 * lazy parameters can be passed along 6550 * as lazy parameters to the next function, but that isn't 6551 * escaping. 6552 */ 6553 if (p.storageClass & (STCscope | STClazy)) 6554 return false; 6555 if (p.storageClass & STCreturn) 6556 return true; 6557 6558 /* If haven't inferred the return type yet, assume it escapes 6559 */ 6560 if (!nextOf()) 6561 return true; 6562 6563 if (purity > PUREweak) 6564 { 6565 /* With pure functions, we need only be concerned if p escapes 6566 * via any return statement. 6567 */ 6568 Type tret = nextOf().toBasetype(); 6569 if (!isref && !tret.hasPointers()) 6570 { 6571 /* The result has no references, so p could not be escaping 6572 * that way. 6573 */ 6574 return false; 6575 } 6576 } 6577 6578 /* Assume it escapes in the absence of better information. 6579 */ 6580 return true; 6581 } 6582 6583 override Type addStorageClass(StorageClass stc) 6584 { 6585 TypeFunction t = cast(TypeFunction)Type.addStorageClass(stc); 6586 if ((stc & STCpure && !t.purity) || (stc & STCnothrow && !t.isnothrow) || (stc & STCnogc && !t.isnogc) || (stc & STCsafe && t.trust < TRUSTtrusted)) 6587 { 6588 // Klunky to change these 6589 auto tf = new TypeFunction(t.parameters, t.next, t.varargs, t.linkage, 0); 6590 tf.mod = t.mod; 6591 tf.fargs = fargs; 6592 tf.purity = t.purity; 6593 tf.isnothrow = t.isnothrow; 6594 tf.isnogc = t.isnogc; 6595 tf.isproperty = t.isproperty; 6596 tf.isref = t.isref; 6597 tf.isreturn = t.isreturn; 6598 tf.isscope = t.isscope; 6599 tf.trust = t.trust; 6600 tf.iswild = t.iswild; 6601 6602 if (stc & STCpure) 6603 tf.purity = PUREfwdref; 6604 if (stc & STCnothrow) 6605 tf.isnothrow = true; 6606 if (stc & STCnogc) 6607 tf.isnogc = true; 6608 if (stc & STCsafe) 6609 tf.trust = TRUSTsafe; 6610 6611 tf.deco = tf.merge().deco; 6612 t = tf; 6613 } 6614 return t; 6615 } 6616 6617 /** For each active attribute (ref/const/nogc/etc) call fp with a void* for the 6618 work param and a string representation of the attribute. */ 6619 int attributesApply(void* param, int function(void*, const(char)*) fp, TRUSTformat trustFormat = TRUSTformatDefault) 6620 { 6621 int res = 0; 6622 if (purity) 6623 res = fp(param, "pure"); 6624 if (res) 6625 return res; 6626 6627 if (isnothrow) 6628 res = fp(param, "nothrow"); 6629 if (res) 6630 return res; 6631 6632 if (isnogc) 6633 res = fp(param, "@nogc"); 6634 if (res) 6635 return res; 6636 6637 if (isproperty) 6638 res = fp(param, "@property"); 6639 if (res) 6640 return res; 6641 6642 if (isref) 6643 res = fp(param, "ref"); 6644 if (res) 6645 return res; 6646 6647 if (isreturn) 6648 res = fp(param, "return"); 6649 if (res) 6650 return res; 6651 6652 if (isscope) 6653 res = fp(param, "scope"); 6654 if (res) 6655 return res; 6656 6657 TRUST trustAttrib = trust; 6658 6659 if (trustAttrib == TRUSTdefault) 6660 { 6661 // Print out "@system" when trust equals TRUSTdefault (if desired). 6662 if (trustFormat == TRUSTformatSystem) 6663 trustAttrib = TRUSTsystem; 6664 else 6665 return res; // avoid calling with an empty string 6666 } 6667 6668 return fp(param, trustToChars(trustAttrib)); 6669 } 6670 6671 override Type substWildTo(uint) 6672 { 6673 if (!iswild && !(mod & MODwild)) 6674 return this; 6675 6676 // Substitude inout qualifier of function type to mutable or immutable 6677 // would break type system. Instead substitude inout to the most weak 6678 // qualifer - const. 6679 uint m = MODconst; 6680 6681 assert(next); 6682 Type tret = next.substWildTo(m); 6683 Parameters* params = parameters; 6684 if (mod & MODwild) 6685 params = parameters.copy(); 6686 for (size_t i = 0; i < params.dim; i++) 6687 { 6688 Parameter p = (*params)[i]; 6689 Type t = p.type.substWildTo(m); 6690 if (t == p.type) 6691 continue; 6692 if (params == parameters) 6693 params = parameters.copy(); 6694 (*params)[i] = new Parameter(p.storageClass, t, null, null); 6695 } 6696 if (next == tret && params == parameters) 6697 return this; 6698 6699 // Similar to TypeFunction::syntaxCopy; 6700 auto t = new TypeFunction(params, tret, varargs, linkage); 6701 t.mod = ((mod & MODwild) ? (mod & ~MODwild) | MODconst : mod); 6702 t.isnothrow = isnothrow; 6703 t.isnogc = isnogc; 6704 t.purity = purity; 6705 t.isproperty = isproperty; 6706 t.isref = isref; 6707 t.isreturn = isreturn; 6708 t.isscope = isscope; 6709 t.iswild = 0; 6710 t.trust = trust; 6711 t.fargs = fargs; 6712 return t.merge(); 6713 } 6714 6715 /******************************** 6716 * 'args' are being matched to function 'this' 6717 * Determine match level. 6718 * Input: 6719 * flag 1 performing a partial ordering match 6720 * Returns: 6721 * MATCHxxxx 6722 */ 6723 MATCH callMatch(Type tthis, Expressions* args, int flag = 0) 6724 { 6725 //printf("TypeFunction::callMatch() %s\n", toChars()); 6726 MATCH match = MATCHexact; // assume exact match 6727 ubyte wildmatch = 0; 6728 6729 if (tthis) 6730 { 6731 Type t = tthis; 6732 if (t.toBasetype().ty == Tpointer) 6733 t = t.toBasetype().nextOf(); // change struct* to struct 6734 if (t.mod != mod) 6735 { 6736 if (MODimplicitConv(t.mod, mod)) 6737 match = MATCHconst; 6738 else if ((mod & MODwild) && MODimplicitConv(t.mod, (mod & ~MODwild) | MODconst)) 6739 { 6740 match = MATCHconst; 6741 } 6742 else 6743 return MATCHnomatch; 6744 } 6745 if (isWild()) 6746 { 6747 if (t.isWild()) 6748 wildmatch |= MODwild; 6749 else if (t.isConst()) 6750 wildmatch |= MODconst; 6751 else if (t.isImmutable()) 6752 wildmatch |= MODimmutable; 6753 else 6754 wildmatch |= MODmutable; 6755 } 6756 } 6757 6758 size_t nparams = Parameter.dim(parameters); 6759 size_t nargs = args ? args.dim : 0; 6760 if (nparams == nargs) 6761 { 6762 } 6763 else if (nargs > nparams) 6764 { 6765 if (varargs == 0) 6766 goto Nomatch; 6767 // too many args; no match 6768 match = MATCHconvert; // match ... with a "conversion" match level 6769 } 6770 6771 for (size_t u = 0; u < nargs; u++) 6772 { 6773 if (u >= nparams) 6774 break; 6775 Parameter p = Parameter.getNth(parameters, u); 6776 Expression arg = (*args)[u]; 6777 assert(arg); 6778 Type tprm = p.type; 6779 Type targ = arg.type; 6780 6781 if (!(p.storageClass & STClazy && tprm.ty == Tvoid && targ.ty != Tvoid)) 6782 { 6783 bool isRef = (p.storageClass & (STCref | STCout)) != 0; 6784 wildmatch |= targ.deduceWild(tprm, isRef); 6785 } 6786 } 6787 if (wildmatch) 6788 { 6789 /* Calculate wild matching modifier 6790 */ 6791 if (wildmatch & MODconst || wildmatch & (wildmatch - 1)) 6792 wildmatch = MODconst; 6793 else if (wildmatch & MODimmutable) 6794 wildmatch = MODimmutable; 6795 else if (wildmatch & MODwild) 6796 wildmatch = MODwild; 6797 else 6798 { 6799 assert(wildmatch & MODmutable); 6800 wildmatch = MODmutable; 6801 } 6802 } 6803 6804 for (size_t u = 0; u < nparams; u++) 6805 { 6806 MATCH m; 6807 6808 Parameter p = Parameter.getNth(parameters, u); 6809 assert(p); 6810 if (u >= nargs) 6811 { 6812 if (p.defaultArg) 6813 continue; 6814 goto L1; 6815 // try typesafe variadics 6816 } 6817 { 6818 Expression arg = (*args)[u]; 6819 assert(arg); 6820 //printf("arg: %s, type: %s\n", arg->toChars(), arg->type->toChars()); 6821 6822 Type targ = arg.type; 6823 Type tprm = wildmatch ? p.type.substWildTo(wildmatch) : p.type; 6824 6825 if (p.storageClass & STClazy && tprm.ty == Tvoid && targ.ty != Tvoid) 6826 m = MATCHconvert; 6827 else 6828 { 6829 //printf("%s of type %s implicitConvTo %s\n", arg->toChars(), targ->toChars(), tprm->toChars()); 6830 if (flag) 6831 { 6832 // for partial ordering, value is an irrelevant mockup, just look at the type 6833 m = targ.implicitConvTo(tprm); 6834 } 6835 else 6836 m = arg.implicitConvTo(tprm); 6837 //printf("match %d\n", m); 6838 } 6839 6840 // Non-lvalues do not match ref or out parameters 6841 if (p.storageClass & (STCref | STCout)) 6842 { 6843 // Bugzilla 13783: Don't use toBasetype() to handle enum types. 6844 Type ta = targ; 6845 Type tp = tprm; 6846 //printf("fparam[%d] ta = %s, tp = %s\n", u, ta->toChars(), tp->toChars()); 6847 6848 if (m && !arg.isLvalue()) 6849 { 6850 if (p.storageClass & STCout) 6851 goto Nomatch; 6852 6853 if (arg.op == TOKstring && tp.ty == Tsarray) 6854 { 6855 if (ta.ty != Tsarray) 6856 { 6857 Type tn = tp.nextOf().castMod(ta.nextOf().mod); 6858 dinteger_t dim = (cast(StringExp)arg).len; 6859 ta = tn.sarrayOf(dim); 6860 } 6861 } 6862 else if (arg.op == TOKslice && tp.ty == Tsarray) 6863 { 6864 // Allow conversion from T[lwr .. upr] to ref T[upr-lwr] 6865 if (ta.ty != Tsarray) 6866 { 6867 Type tn = ta.nextOf(); 6868 dinteger_t dim = (cast(TypeSArray)tp).dim.toUInteger(); 6869 ta = tn.sarrayOf(dim); 6870 } 6871 } 6872 else 6873 goto Nomatch; 6874 } 6875 6876 /* Find most derived alias this type being matched. 6877 * Bugzilla 15674: Allow on both ref and out parameters. 6878 */ 6879 while (1) 6880 { 6881 Type tat = ta.toBasetype().aliasthisOf(); 6882 if (!tat || !tat.implicitConvTo(tprm)) 6883 break; 6884 ta = tat; 6885 } 6886 6887 /* A ref variable should work like a head-const reference. 6888 * e.g. disallows: 6889 * ref T <- an lvalue of const(T) argument 6890 * ref T[dim] <- an lvalue of const(T[dim]) argument 6891 */ 6892 if (!ta.constConv(tp)) 6893 goto Nomatch; 6894 } 6895 } 6896 6897 /* prefer matching the element type rather than the array 6898 * type when more arguments are present with T[]... 6899 */ 6900 if (varargs == 2 && u + 1 == nparams && nargs > nparams) 6901 goto L1; 6902 6903 //printf("\tm = %d\n", m); 6904 if (m == MATCHnomatch) // if no match 6905 { 6906 L1: 6907 if (varargs == 2 && u + 1 == nparams) // if last varargs param 6908 { 6909 Type tb = p.type.toBasetype(); 6910 TypeSArray tsa; 6911 dinteger_t sz; 6912 6913 switch (tb.ty) 6914 { 6915 case Tsarray: 6916 tsa = cast(TypeSArray)tb; 6917 sz = tsa.dim.toInteger(); 6918 if (sz != nargs - u) 6919 goto Nomatch; 6920 goto case Tarray; 6921 case Tarray: 6922 { 6923 TypeArray ta = cast(TypeArray)tb; 6924 for (; u < nargs; u++) 6925 { 6926 Expression arg = (*args)[u]; 6927 assert(arg); 6928 6929 /* If lazy array of delegates, 6930 * convert arg(s) to delegate(s) 6931 */ 6932 Type tret = p.isLazyArray(); 6933 if (tret) 6934 { 6935 if (ta.next.equals(arg.type)) 6936 m = MATCHexact; 6937 else if (tret.toBasetype().ty == Tvoid) 6938 m = MATCHconvert; 6939 else 6940 { 6941 m = arg.implicitConvTo(tret); 6942 if (m == MATCHnomatch) 6943 m = arg.implicitConvTo(ta.next); 6944 } 6945 } 6946 else 6947 m = arg.implicitConvTo(ta.next); 6948 6949 if (m == MATCHnomatch) 6950 goto Nomatch; 6951 if (m < match) 6952 match = m; 6953 } 6954 goto Ldone; 6955 } 6956 case Tclass: 6957 // Should see if there's a constructor match? 6958 // Or just leave it ambiguous? 6959 goto Ldone; 6960 6961 default: 6962 goto Nomatch; 6963 } 6964 } 6965 goto Nomatch; 6966 } 6967 if (m < match) 6968 match = m; // pick worst match 6969 } 6970 6971 Ldone: 6972 //printf("match = %d\n", match); 6973 return match; 6974 6975 Nomatch: 6976 //printf("no match\n"); 6977 return MATCHnomatch; 6978 } 6979 6980 bool checkRetType(Loc loc) 6981 { 6982 Type tb = next.toBasetype(); 6983 if (tb.ty == Tfunction) 6984 { 6985 error(loc, "functions cannot return a function"); 6986 next = Type.terror; 6987 } 6988 if (tb.ty == Ttuple) 6989 { 6990 error(loc, "functions cannot return a tuple"); 6991 next = Type.terror; 6992 } 6993 if (!isref && (tb.ty == Tstruct || tb.ty == Tsarray)) 6994 { 6995 Type tb2 = tb.baseElemOf(); 6996 if (tb2.ty == Tstruct && !(cast(TypeStruct)tb2).sym.members) 6997 { 6998 error(loc, "functions cannot return opaque type %s by value", tb.toChars()); 6999 next = Type.terror; 7000 } 7001 } 7002 if (tb.ty == Terror) 7003 return true; 7004 return false; 7005 } 7006 7007 override Expression defaultInit(Loc loc) const 7008 { 7009 error(loc, "function does not have a default initializer"); 7010 return new ErrorExp(); 7011 } 7012 7013 override void accept(Visitor v) 7014 { 7015 v.visit(this); 7016 } 7017 } 7018 7019 /*********************************************************** 7020 */ 7021 extern (C++) final class TypeDelegate : TypeNext 7022 { 7023 // .next is a TypeFunction 7024 7025 extern (D) this(Type t) 7026 { 7027 super(Tfunction, t); 7028 ty = Tdelegate; 7029 } 7030 7031 override const(char)* kind() const 7032 { 7033 return "delegate"; 7034 } 7035 7036 override Type syntaxCopy() 7037 { 7038 Type t = next.syntaxCopy(); 7039 if (t == next) 7040 t = this; 7041 else 7042 { 7043 t = new TypeDelegate(t); 7044 t.mod = mod; 7045 } 7046 return t; 7047 } 7048 7049 override Type semantic(Loc loc, Scope* sc) 7050 { 7051 //printf("TypeDelegate::semantic() %s\n", toChars()); 7052 if (deco) // if semantic() already run 7053 { 7054 //printf("already done\n"); 7055 return this; 7056 } 7057 next = next.semantic(loc, sc); 7058 if (next.ty != Tfunction) 7059 return terror; 7060 7061 /* In order to deal with Bugzilla 4028, perhaps default arguments should 7062 * be removed from next before the merge. 7063 */ 7064 version (none) 7065 { 7066 return merge(); 7067 } 7068 else 7069 { 7070 /* Don't return merge(), because arg identifiers and default args 7071 * can be different 7072 * even though the types match 7073 */ 7074 deco = merge().deco; 7075 return this; 7076 } 7077 } 7078 7079 override d_uns64 size(Loc loc) const 7080 { 7081 return Target.ptrsize * 2; 7082 } 7083 7084 override uint alignsize() const 7085 { 7086 return Target.ptrsize; 7087 } 7088 7089 override MATCH implicitConvTo(Type to) 7090 { 7091 //printf("TypeDelegate::implicitConvTo(this=%p, to=%p)\n", this, to); 7092 //printf("from: %s\n", toChars()); 7093 //printf("to : %s\n", to->toChars()); 7094 if (this == to) 7095 return MATCHexact; 7096 7097 version (all) 7098 { 7099 // not allowing covariant conversions because it interferes with overriding 7100 if (to.ty == Tdelegate && this.nextOf().covariant(to.nextOf()) == 1) 7101 { 7102 Type tret = this.next.nextOf(); 7103 Type toret = (cast(TypeDelegate)to).next.nextOf(); 7104 if (tret.ty == Tclass && toret.ty == Tclass) 7105 { 7106 /* Bugzilla 10219: Check covariant interface return with offset tweaking. 7107 * interface I {} 7108 * class C : Object, I {} 7109 * I delegate() dg = delegate C() {} // should be error 7110 */ 7111 int offset = 0; 7112 if (toret.isBaseOf(tret, &offset) && offset != 0) 7113 return MATCHnomatch; 7114 } 7115 return MATCHconvert; 7116 } 7117 } 7118 7119 return MATCHnomatch; 7120 } 7121 7122 override Expression defaultInit(Loc loc) 7123 { 7124 static if (LOGDEFAULTINIT) 7125 { 7126 printf("TypeDelegate::defaultInit() '%s'\n", toChars()); 7127 } 7128 return new NullExp(loc, this); 7129 } 7130 7131 override bool isZeroInit(Loc loc) const 7132 { 7133 return true; 7134 } 7135 7136 override bool isBoolean() const 7137 { 7138 return true; 7139 } 7140 7141 override Expression dotExp(Scope* sc, Expression e, Identifier ident, int flag) 7142 { 7143 static if (LOGDOTEXP) 7144 { 7145 printf("TypeDelegate::dotExp(e = '%s', ident = '%s')\n", e.toChars(), ident.toChars()); 7146 } 7147 if (ident == Id.ptr) 7148 { 7149 e = new DelegatePtrExp(e.loc, e); 7150 e = e.semantic(sc); 7151 } 7152 else if (ident == Id.funcptr) 7153 { 7154 if (!(flag & DotExpFlag.noDeref) && sc.func && !sc.intypeof && sc.func.setUnsafe()) 7155 { 7156 e.error("%s.funcptr cannot be used in @safe code", e.toChars()); 7157 return new ErrorExp(); 7158 } 7159 e = new DelegateFuncptrExp(e.loc, e); 7160 e = e.semantic(sc); 7161 } 7162 else 7163 { 7164 e = Type.dotExp(sc, e, ident, flag); 7165 } 7166 return e; 7167 } 7168 7169 override bool hasPointers() const 7170 { 7171 return true; 7172 } 7173 7174 override void accept(Visitor v) 7175 { 7176 v.visit(this); 7177 } 7178 } 7179 7180 /*********************************************************** 7181 */ 7182 extern (C++) abstract class TypeQualified : Type 7183 { 7184 Loc loc; 7185 7186 // array of Identifier and TypeInstance, 7187 // representing ident.ident!tiargs.ident. ... etc. 7188 Objects idents; 7189 7190 final extern (D) this(TY ty, Loc loc) 7191 { 7192 super(ty); 7193 this.loc = loc; 7194 } 7195 7196 final void syntaxCopyHelper(TypeQualified t) 7197 { 7198 //printf("TypeQualified::syntaxCopyHelper(%s) %s\n", t->toChars(), toChars()); 7199 idents.setDim(t.idents.dim); 7200 for (size_t i = 0; i < idents.dim; i++) 7201 { 7202 RootObject id = t.idents[i]; 7203 if (id.dyncast() == DYNCAST_DSYMBOL) 7204 { 7205 TemplateInstance ti = cast(TemplateInstance)id; 7206 ti = cast(TemplateInstance)ti.syntaxCopy(null); 7207 id = ti; 7208 } 7209 else if (id.dyncast() == DYNCAST_EXPRESSION) 7210 { 7211 Expression e = cast(Expression)id; 7212 e = e.syntaxCopy(); 7213 id = e; 7214 } 7215 else if (id.dyncast() == DYNCAST_TYPE) 7216 { 7217 Type tx = cast(Type)id; 7218 tx = tx.syntaxCopy(); 7219 id = tx; 7220 } 7221 idents[i] = id; 7222 } 7223 } 7224 7225 final void addIdent(Identifier ident) 7226 { 7227 idents.push(ident); 7228 } 7229 7230 final void addInst(TemplateInstance inst) 7231 { 7232 idents.push(inst); 7233 } 7234 7235 final void addIndex(RootObject e) 7236 { 7237 idents.push(e); 7238 } 7239 7240 override d_uns64 size(Loc loc) 7241 { 7242 error(this.loc, "size of type %s is not known", toChars()); 7243 return SIZE_INVALID; 7244 } 7245 7246 /************************************* 7247 * Resolve a tuple index. 7248 */ 7249 final void resolveTupleIndex(Loc loc, Scope* sc, Dsymbol s, Expression* pe, Type* pt, Dsymbol* ps, RootObject oindex) 7250 { 7251 *pt = null; 7252 *ps = null; 7253 *pe = null; 7254 7255 auto tup = s.isTupleDeclaration(); 7256 7257 auto eindex = isExpression(oindex); 7258 auto tindex = isType(oindex); 7259 auto sindex = isDsymbol(oindex); 7260 7261 if (!tup) 7262 { 7263 // It's really an index expression 7264 if (tindex) 7265 eindex = new TypeExp(loc, tindex); 7266 else if (sindex) 7267 eindex = DsymbolExp.resolve(loc, sc, sindex, false); 7268 Expression e = new IndexExp(loc, DsymbolExp.resolve(loc, sc, s, false), eindex); 7269 e = e.semantic(sc); 7270 resolveExp(e, pt, pe, ps); 7271 return; 7272 } 7273 7274 // Convert oindex to Expression, then try to resolve to constant. 7275 if (tindex) 7276 tindex.resolve(loc, sc, &eindex, &tindex, &sindex); 7277 if (sindex) 7278 eindex = DsymbolExp.resolve(loc, sc, sindex, false); 7279 if (!eindex) 7280 { 7281 .error(loc, "index is %s not an expression", oindex.toChars()); 7282 *pt = Type.terror; 7283 return; 7284 } 7285 7286 eindex = semanticLength(sc, tup, eindex); 7287 eindex = eindex.ctfeInterpret(); 7288 if (eindex.op == TOKerror) 7289 { 7290 *pt = Type.terror; 7291 return; 7292 } 7293 const(uinteger_t) d = eindex.toUInteger(); 7294 if (d >= tup.objects.dim) 7295 { 7296 .error(loc, "tuple index %llu exceeds length %u", d, tup.objects.dim); 7297 *pt = Type.terror; 7298 return; 7299 } 7300 7301 RootObject o = (*tup.objects)[cast(size_t)d]; 7302 *pt = isType(o); 7303 *ps = isDsymbol(o); 7304 *pe = isExpression(o); 7305 if (*pt) 7306 *pt = (*pt).semantic(loc, sc); 7307 if (*pe) 7308 resolveExp(*pe, pt, pe, ps); 7309 } 7310 7311 final Expression toExpressionHelper(Expression e, size_t i = 0) 7312 { 7313 //printf("toExpressionHelper(e = %s %s)\n", Token.toChars(e.op), e.toChars()); 7314 for (; i < idents.dim; i++) 7315 { 7316 RootObject id = idents[i]; 7317 //printf("\t[%d] e: '%s', id: '%s'\n", i, e.toChars(), id.toChars()); 7318 7319 switch (id.dyncast()) 7320 { 7321 // ... '. ident' 7322 case DYNCAST_IDENTIFIER: 7323 e = new DotIdExp(e.loc, e, cast(Identifier)id); 7324 break; 7325 7326 // ... '. name!(tiargs)' 7327 case DYNCAST_DSYMBOL: 7328 auto ti = (cast(Dsymbol)id).isTemplateInstance(); 7329 assert(ti); 7330 e = new DotTemplateInstanceExp(e.loc, e, ti.name, ti.tiargs); 7331 break; 7332 7333 // ... '[type]' 7334 case DYNCAST_TYPE: // Bugzilla 1215 7335 e = new ArrayExp(loc, e, new TypeExp(loc, cast(Type)id)); 7336 break; 7337 7338 // ... '[expr]' 7339 case DYNCAST_EXPRESSION: // Bugzilla 1215 7340 e = new ArrayExp(loc, e, cast(Expression)id); 7341 break; 7342 7343 default: 7344 assert(0); 7345 } 7346 } 7347 return e; 7348 } 7349 7350 /************************************* 7351 * Takes an array of Identifiers and figures out if 7352 * it represents a Type or an Expression. 7353 * Output: 7354 * if expression, *pe is set 7355 * if type, *pt is set 7356 */ 7357 final void resolveHelper(Loc loc, Scope* sc, Dsymbol s, Dsymbol scopesym, 7358 Expression* pe, Type* pt, Dsymbol* ps, bool intypeid = false) 7359 { 7360 version (none) 7361 { 7362 printf("TypeQualified::resolveHelper(sc = %p, idents = '%s')\n", sc, toChars()); 7363 if (scopesym) 7364 printf("\tscopesym = '%s'\n", scopesym.toChars()); 7365 } 7366 *pe = null; 7367 *pt = null; 7368 *ps = null; 7369 if (s) 7370 { 7371 //printf("\t1: s = '%s' %p, kind = '%s'\n",s->toChars(), s, s->kind()); 7372 Declaration d = s.isDeclaration(); 7373 if (d && (d.storage_class & STCtemplateparameter)) 7374 s = s.toAlias(); 7375 else 7376 s.checkDeprecated(loc, sc); // check for deprecated aliases 7377 s = s.toAlias(); 7378 //printf("\t2: s = '%s' %p, kind = '%s'\n",s->toChars(), s, s->kind()); 7379 for (size_t i = 0; i < idents.dim; i++) 7380 { 7381 RootObject id = idents[i]; 7382 if (id.dyncast() == DYNCAST_EXPRESSION || 7383 id.dyncast() == DYNCAST_TYPE) 7384 { 7385 Type tx; 7386 Expression ex; 7387 Dsymbol sx; 7388 resolveTupleIndex(loc, sc, s, &ex, &tx, &sx, id); 7389 if (sx) 7390 { 7391 s = sx.toAlias(); 7392 continue; 7393 } 7394 if (tx) 7395 ex = new TypeExp(loc, tx); 7396 assert(ex); 7397 7398 ex = toExpressionHelper(ex, i + 1); 7399 ex = ex.semantic(sc); 7400 resolveExp(ex, pt, pe, ps); 7401 return; 7402 } 7403 7404 Type t = s.getType(); // type symbol, type alias, or type tuple? 7405 uint errorsave = global.errors; 7406 Dsymbol sm = s.searchX(loc, sc, id); 7407 if (sm && !symbolIsVisible(sc, sm)) 7408 { 7409 .deprecation(loc, "%s is not visible from module %s", sm.toPrettyChars(), sc._module.toChars()); 7410 // sm = null; 7411 } 7412 if (global.errors != errorsave) 7413 { 7414 *pt = Type.terror; 7415 return; 7416 } 7417 //printf("\t3: s = %p %s %s, sm = %p\n", s, s->kind(), s->toChars(), sm); 7418 if (intypeid && !t && sm && sm.needThis()) 7419 goto L3; 7420 if (VarDeclaration v = s.isVarDeclaration()) 7421 { 7422 if (v.storage_class & (STCconst | STCimmutable | STCmanifest) || 7423 v.type.isConst() || v.type.isImmutable()) 7424 { 7425 // Bugzilla 13087: this.field is not constant always 7426 if (!v.isThisDeclaration()) 7427 goto L3; 7428 } 7429 } 7430 if (!sm) 7431 { 7432 if (!t) 7433 { 7434 if (s.isDeclaration()) // var, func, or tuple declaration? 7435 { 7436 t = s.isDeclaration().type; 7437 if (!t && s.isTupleDeclaration()) // expression tuple? 7438 goto L3; 7439 } 7440 else if (s.isTemplateInstance() || 7441 s.isImport() || s.isPackage() || s.isModule()) 7442 { 7443 goto L3; 7444 } 7445 } 7446 if (t) 7447 { 7448 sm = t.toDsymbol(sc); 7449 if (sm && id.dyncast() == DYNCAST_IDENTIFIER) 7450 { 7451 sm = sm.search(loc, cast(Identifier)id); 7452 if (sm) 7453 goto L2; 7454 } 7455 L3: 7456 Expression e; 7457 VarDeclaration v = s.isVarDeclaration(); 7458 FuncDeclaration f = s.isFuncDeclaration(); 7459 if (intypeid || !v && !f) 7460 e = DsymbolExp.resolve(loc, sc, s, true); 7461 else 7462 e = new VarExp(loc, s.isDeclaration(), true); 7463 7464 e = toExpressionHelper(e, i); 7465 e = e.semantic(sc); 7466 resolveExp(e, pt, pe, ps); 7467 return; 7468 } 7469 else 7470 { 7471 if (id.dyncast() == DYNCAST_DSYMBOL) 7472 { 7473 // searchX already handles errors for template instances 7474 assert(global.errors); 7475 } 7476 else 7477 { 7478 assert(id.dyncast() == DYNCAST_IDENTIFIER); 7479 sm = s.search_correct(cast(Identifier)id); 7480 if (sm) 7481 error(loc, "identifier '%s' of '%s' is not defined, did you mean %s '%s'?", id.toChars(), toChars(), sm.kind(), sm.toChars()); 7482 else 7483 error(loc, "identifier '%s' of '%s' is not defined", id.toChars(), toChars()); 7484 } 7485 *pe = new ErrorExp(); 7486 } 7487 return; 7488 } 7489 L2: 7490 s = sm.toAlias(); 7491 } 7492 7493 if (auto em = s.isEnumMember()) 7494 { 7495 // It's not a type, it's an expression 7496 *pe = em.getVarExp(loc, sc); 7497 return; 7498 } 7499 if (auto v = s.isVarDeclaration()) 7500 { 7501 /* This is mostly same with DsymbolExp::semantic(), but we cannot use it 7502 * because some variables used in type context need to prevent lowering 7503 * to a literal or contextful expression. For example: 7504 * 7505 * enum a = 1; alias b = a; 7506 * template X(alias e){ alias v = e; } alias x = X!(1); 7507 * struct S { int v; alias w = v; } 7508 * // TypeIdentifier 'a', 'e', and 'v' should be TOKvar, 7509 * // because getDsymbol() need to work in AliasDeclaration::semantic(). 7510 */ 7511 if (!v.type || 7512 !v.type.deco && v.inuse) 7513 { 7514 if (v.inuse) // Bugzilla 9494 7515 error(loc, "circular reference to %s '%s'", v.kind(), v.toPrettyChars()); 7516 else 7517 error(loc, "forward reference to %s '%s'", v.kind(), v.toPrettyChars()); 7518 *pt = Type.terror; 7519 return; 7520 } 7521 if (v.type.ty == Terror) 7522 *pt = Type.terror; 7523 else 7524 *pe = new VarExp(loc, v); 7525 return; 7526 } 7527 if (auto fld = s.isFuncLiteralDeclaration()) 7528 { 7529 //printf("'%s' is a function literal\n", fld.toChars()); 7530 *pe = new FuncExp(loc, fld); 7531 *pe = (*pe).semantic(sc); 7532 return; 7533 } 7534 version (none) 7535 { 7536 if (FuncDeclaration fd = s.isFuncDeclaration()) 7537 { 7538 *pe = new DsymbolExp(loc, fd); 7539 return; 7540 } 7541 } 7542 7543 L1: 7544 Type t = s.getType(); 7545 if (!t) 7546 { 7547 // If the symbol is an import, try looking inside the import 7548 if (Import si = s.isImport()) 7549 { 7550 s = si.search(loc, s.ident); 7551 if (s && s != si) 7552 goto L1; 7553 s = si; 7554 } 7555 *ps = s; 7556 return; 7557 } 7558 if (t.ty == Tinstance && t != this && !t.deco) 7559 { 7560 if (!(cast(TypeInstance)t).tempinst.errors) 7561 error(loc, "forward reference to '%s'", t.toChars()); 7562 *pt = Type.terror; 7563 return; 7564 } 7565 7566 if (t.ty == Ttuple) 7567 *pt = t; 7568 else 7569 *pt = t.merge(); 7570 } 7571 if (!s) 7572 { 7573 const(char)* p = mutableOf().unSharedOf().toChars(); 7574 const(char)* n = importHint(p); 7575 if (n) 7576 error(loc, "'%s' is not defined, perhaps you need to import %s; ?", p, n); 7577 else 7578 { 7579 auto id = new Identifier(p); 7580 s = sc.search_correct(id); 7581 if (s) 7582 error(loc, "undefined identifier '%s', did you mean %s '%s'?", p, s.kind(), s.toChars()); 7583 else 7584 error(loc, "undefined identifier '%s'", p); 7585 } 7586 *pt = Type.terror; 7587 } 7588 } 7589 7590 override void accept(Visitor v) 7591 { 7592 v.visit(this); 7593 } 7594 } 7595 7596 /*********************************************************** 7597 */ 7598 extern (C++) final class TypeIdentifier : TypeQualified 7599 { 7600 Identifier ident; 7601 7602 // The symbol representing this identifier, before alias resolution 7603 Dsymbol originalSymbol; 7604 7605 extern (D) this(Loc loc, Identifier ident) 7606 { 7607 super(Tident, loc); 7608 this.ident = ident; 7609 } 7610 7611 override const(char)* kind() const 7612 { 7613 return "identifier"; 7614 } 7615 7616 override Type syntaxCopy() 7617 { 7618 auto t = new TypeIdentifier(loc, ident); 7619 t.syntaxCopyHelper(this); 7620 t.mod = mod; 7621 return t; 7622 } 7623 7624 /************************************* 7625 * Takes an array of Identifiers and figures out if 7626 * it represents a Type or an Expression. 7627 * Output: 7628 * if expression, *pe is set 7629 * if type, *pt is set 7630 */ 7631 override void resolve(Loc loc, Scope* sc, Expression* pe, Type* pt, Dsymbol* ps, bool intypeid = false) 7632 { 7633 //printf("TypeIdentifier::resolve(sc = %p, idents = '%s')\n", sc, toChars()); 7634 if ((ident.equals(Id._super) || ident.equals(Id.This)) && !hasThis(sc)) 7635 { 7636 AggregateDeclaration ad = sc.getStructClassScope(); 7637 if (ad) 7638 { 7639 ClassDeclaration cd = ad.isClassDeclaration(); 7640 if (cd) 7641 { 7642 if (ident.equals(Id.This)) 7643 ident = cd.ident; 7644 else if (cd.baseClass && ident.equals(Id._super)) 7645 ident = cd.baseClass.ident; 7646 } 7647 else 7648 { 7649 StructDeclaration sd = ad.isStructDeclaration(); 7650 if (sd && ident.equals(Id.This)) 7651 ident = sd.ident; 7652 } 7653 } 7654 } 7655 if (ident == Id.ctfe) 7656 { 7657 error(loc, "variable __ctfe cannot be read at compile time"); 7658 *pe = null; 7659 *ps = null; 7660 *pt = Type.terror; 7661 return; 7662 } 7663 7664 Dsymbol scopesym; 7665 Dsymbol s = sc.search(loc, ident, &scopesym); 7666 resolveHelper(loc, sc, s, scopesym, pe, pt, ps, intypeid); 7667 if (*pt) 7668 (*pt) = (*pt).addMod(mod); 7669 } 7670 7671 /***************************************** 7672 * See if type resolves to a symbol, if so, 7673 * return that symbol. 7674 */ 7675 override Dsymbol toDsymbol(Scope* sc) 7676 { 7677 //printf("TypeIdentifier::toDsymbol('%s')\n", toChars()); 7678 if (!sc) 7679 return null; 7680 7681 Type t; 7682 Expression e; 7683 Dsymbol s; 7684 resolve(loc, sc, &e, &t, &s); 7685 if (t && t.ty != Tident) 7686 s = t.toDsymbol(sc); 7687 if (e) 7688 s = getDsymbol(e); 7689 7690 return s; 7691 } 7692 7693 override Type semantic(Loc loc, Scope* sc) 7694 { 7695 Type t; 7696 Expression e; 7697 Dsymbol s; 7698 //printf("TypeIdentifier::semantic(%s)\n", toChars()); 7699 resolve(loc, sc, &e, &t, &s); 7700 if (t) 7701 { 7702 //printf("\tit's a type %d, %s, %s\n", t->ty, t->toChars(), t->deco); 7703 t = t.addMod(mod); 7704 } 7705 else 7706 { 7707 if (s) 7708 { 7709 s.error(loc, "is used as a type"); 7710 //assert(0); 7711 } 7712 else 7713 error(loc, "%s is used as a type", toChars()); 7714 t = terror; 7715 } 7716 //t->print(); 7717 return t; 7718 } 7719 7720 override Expression toExpression() 7721 { 7722 return toExpressionHelper(new IdentifierExp(loc, ident)); 7723 } 7724 7725 override void accept(Visitor v) 7726 { 7727 v.visit(this); 7728 } 7729 } 7730 7731 /*********************************************************** 7732 * Similar to TypeIdentifier, but with a TemplateInstance as the root 7733 */ 7734 extern (C++) final class TypeInstance : TypeQualified 7735 { 7736 TemplateInstance tempinst; 7737 7738 extern (D) this(Loc loc, TemplateInstance tempinst) 7739 { 7740 super(Tinstance, loc); 7741 this.tempinst = tempinst; 7742 } 7743 7744 override const(char)* kind() const 7745 { 7746 return "instance"; 7747 } 7748 7749 override Type syntaxCopy() 7750 { 7751 //printf("TypeInstance::syntaxCopy() %s, %d\n", toChars(), idents.dim); 7752 auto t = new TypeInstance(loc, cast(TemplateInstance)tempinst.syntaxCopy(null)); 7753 t.syntaxCopyHelper(this); 7754 t.mod = mod; 7755 return t; 7756 } 7757 7758 override void resolve(Loc loc, Scope* sc, Expression* pe, Type* pt, Dsymbol* ps, bool intypeid = false) 7759 { 7760 // Note close similarity to TypeIdentifier::resolve() 7761 *pe = null; 7762 *pt = null; 7763 *ps = null; 7764 7765 //printf("TypeInstance::resolve(sc = %p, tempinst = '%s')\n", sc, tempinst.toChars()); 7766 tempinst.semantic(sc); 7767 if (!global.gag && tempinst.errors) 7768 { 7769 *pt = terror; 7770 return; 7771 } 7772 7773 resolveHelper(loc, sc, tempinst, null, pe, pt, ps, intypeid); 7774 if (*pt) 7775 *pt = (*pt).addMod(mod); 7776 //if (*pt) printf("*pt = %d '%s'\n", (*pt).ty, (*pt).toChars()); 7777 } 7778 7779 override Type semantic(Loc loc, Scope* sc) 7780 { 7781 Type t; 7782 Expression e; 7783 Dsymbol s; 7784 7785 //printf("TypeInstance::semantic(%p, %s)\n", this, toChars()); 7786 { 7787 uint errors = global.errors; 7788 resolve(loc, sc, &e, &t, &s); 7789 // if we had an error evaluating the symbol, suppress further errors 7790 if (!t && errors != global.errors) 7791 return terror; 7792 } 7793 7794 if (!t) 7795 { 7796 if (!e && s && s.errors) 7797 { 7798 // if there was an error evaluating the symbol, it might actually 7799 // be a type. Avoid misleading error messages. 7800 error(loc, "%s had previous errors", toChars()); 7801 } 7802 else 7803 error(loc, "%s is used as a type", toChars()); 7804 t = terror; 7805 } 7806 return t; 7807 } 7808 7809 override Dsymbol toDsymbol(Scope* sc) 7810 { 7811 Type t; 7812 Expression e; 7813 Dsymbol s; 7814 //printf("TypeInstance::semantic(%s)\n", toChars()); 7815 resolve(loc, sc, &e, &t, &s); 7816 if (t && t.ty != Tinstance) 7817 s = t.toDsymbol(sc); 7818 return s; 7819 } 7820 7821 override Expression toExpression() 7822 { 7823 return toExpressionHelper(new ScopeExp(loc, tempinst)); 7824 } 7825 7826 override void accept(Visitor v) 7827 { 7828 v.visit(this); 7829 } 7830 } 7831 7832 /*********************************************************** 7833 */ 7834 extern (C++) final class TypeTypeof : TypeQualified 7835 { 7836 Expression exp; 7837 int inuse; 7838 7839 extern (D) this(Loc loc, Expression exp) 7840 { 7841 super(Ttypeof, loc); 7842 this.exp = exp; 7843 } 7844 7845 override const(char)* kind() const 7846 { 7847 return "typeof"; 7848 } 7849 7850 override Type syntaxCopy() 7851 { 7852 //printf("TypeTypeof::syntaxCopy() %s\n", toChars()); 7853 auto t = new TypeTypeof(loc, exp.syntaxCopy()); 7854 t.syntaxCopyHelper(this); 7855 t.mod = mod; 7856 return t; 7857 } 7858 7859 override Dsymbol toDsymbol(Scope* sc) 7860 { 7861 //printf("TypeTypeof::toDsymbol('%s')\n", toChars()); 7862 Expression e; 7863 Type t; 7864 Dsymbol s; 7865 resolve(loc, sc, &e, &t, &s); 7866 return s; 7867 } 7868 7869 override void resolve(Loc loc, Scope* sc, Expression* pe, Type* pt, Dsymbol* ps, bool intypeid = false) 7870 { 7871 *pe = null; 7872 *pt = null; 7873 *ps = null; 7874 7875 //printf("TypeTypeof::resolve(sc = %p, idents = '%s')\n", sc, toChars()); 7876 //static int nest; if (++nest == 50) *(char*)0=0; 7877 if (inuse) 7878 { 7879 inuse = 2; 7880 error(loc, "circular typeof definition"); 7881 Lerr: 7882 *pt = Type.terror; 7883 inuse--; 7884 return; 7885 } 7886 inuse++; 7887 7888 /* Currently we cannot evalute 'exp' in speculative context, because 7889 * the type implementation may leak to the final execution. Consider: 7890 * 7891 * struct S(T) { 7892 * string toString() const { return "x"; } 7893 * } 7894 * void main() { 7895 * alias X = typeof(S!int()); 7896 * assert(typeid(X).xtoString(null) == "x"); 7897 * } 7898 */ 7899 Scope* sc2 = sc.push(); 7900 sc2.intypeof = 1; 7901 auto exp2 = exp.semantic(sc2); 7902 exp2 = resolvePropertiesOnly(sc2, exp2); 7903 sc2.pop(); 7904 7905 if (exp2.op == TOKerror) 7906 { 7907 if (!global.gag) 7908 exp = exp2; 7909 goto Lerr; 7910 } 7911 exp = exp2; 7912 7913 if (exp.op == TOKtype || 7914 exp.op == TOKscope) 7915 { 7916 if (exp.checkType()) 7917 goto Lerr; 7918 7919 /* Today, 'typeof(func)' returns void if func is a 7920 * function template (TemplateExp), or 7921 * template lambda (FuncExp). 7922 * It's actually used in Phobos as an idiom, to branch code for 7923 * template functions. 7924 */ 7925 } 7926 if (auto f = exp.op == TOKvar ? (cast( VarExp)exp).var.isFuncDeclaration() 7927 : exp.op == TOKdotvar ? (cast(DotVarExp)exp).var.isFuncDeclaration() : null) 7928 { 7929 if (f.checkForwardRef(loc)) 7930 goto Lerr; 7931 } 7932 if (auto f = isFuncAddress(exp)) 7933 { 7934 if (f.checkForwardRef(loc)) 7935 goto Lerr; 7936 } 7937 7938 Type t = exp.type; 7939 if (!t) 7940 { 7941 error(loc, "expression (%s) has no type", exp.toChars()); 7942 goto Lerr; 7943 } 7944 if (t.ty == Ttypeof) 7945 { 7946 error(loc, "forward reference to %s", toChars()); 7947 goto Lerr; 7948 } 7949 if (idents.dim == 0) 7950 *pt = t; 7951 else 7952 { 7953 if (Dsymbol s = t.toDsymbol(sc)) 7954 resolveHelper(loc, sc, s, null, pe, pt, ps, intypeid); 7955 else 7956 { 7957 auto e = toExpressionHelper(new TypeExp(loc, t)); 7958 e = e.semantic(sc); 7959 resolveExp(e, pt, pe, ps); 7960 } 7961 } 7962 if (*pt) 7963 (*pt) = (*pt).addMod(mod); 7964 inuse--; 7965 return; 7966 } 7967 7968 override Type semantic(Loc loc, Scope* sc) 7969 { 7970 //printf("TypeTypeof::semantic() %s\n", toChars()); 7971 Expression e; 7972 Type t; 7973 Dsymbol s; 7974 resolve(loc, sc, &e, &t, &s); 7975 if (s && (t = s.getType()) !is null) 7976 t = t.addMod(mod); 7977 if (!t) 7978 { 7979 error(loc, "%s is used as a type", toChars()); 7980 t = Type.terror; 7981 } 7982 return t; 7983 } 7984 7985 override d_uns64 size(Loc loc) 7986 { 7987 if (exp.type) 7988 return exp.type.size(loc); 7989 else 7990 return TypeQualified.size(loc); 7991 } 7992 7993 override void accept(Visitor v) 7994 { 7995 v.visit(this); 7996 } 7997 } 7998 7999 /*********************************************************** 8000 */ 8001 extern (C++) final class TypeReturn : TypeQualified 8002 { 8003 extern (D) this(Loc loc) 8004 { 8005 super(Treturn, loc); 8006 } 8007 8008 override const(char)* kind() const 8009 { 8010 return "return"; 8011 } 8012 8013 override Type syntaxCopy() 8014 { 8015 auto t = new TypeReturn(loc); 8016 t.syntaxCopyHelper(this); 8017 t.mod = mod; 8018 return t; 8019 } 8020 8021 override Dsymbol toDsymbol(Scope* sc) 8022 { 8023 Expression e; 8024 Type t; 8025 Dsymbol s; 8026 resolve(loc, sc, &e, &t, &s); 8027 return s; 8028 } 8029 8030 override void resolve(Loc loc, Scope* sc, Expression* pe, Type* pt, Dsymbol* ps, bool intypeid = false) 8031 { 8032 *pe = null; 8033 *pt = null; 8034 *ps = null; 8035 8036 //printf("TypeReturn::resolve(sc = %p, idents = '%s')\n", sc, toChars()); 8037 Type t; 8038 { 8039 FuncDeclaration func = sc.func; 8040 if (!func) 8041 { 8042 error(loc, "typeof(return) must be inside function"); 8043 goto Lerr; 8044 } 8045 if (func.fes) 8046 func = func.fes.func; 8047 t = func.type.nextOf(); 8048 if (!t) 8049 { 8050 error(loc, "cannot use typeof(return) inside function %s with inferred return type", sc.func.toChars()); 8051 goto Lerr; 8052 } 8053 } 8054 if (idents.dim == 0) 8055 *pt = t; 8056 else 8057 { 8058 if (Dsymbol s = t.toDsymbol(sc)) 8059 resolveHelper(loc, sc, s, null, pe, pt, ps, intypeid); 8060 else 8061 { 8062 auto e = toExpressionHelper(new TypeExp(loc, t)); 8063 e = e.semantic(sc); 8064 resolveExp(e, pt, pe, ps); 8065 } 8066 } 8067 if (*pt) 8068 (*pt) = (*pt).addMod(mod); 8069 return; 8070 8071 Lerr: 8072 *pt = Type.terror; 8073 return; 8074 } 8075 8076 override Type semantic(Loc loc, Scope* sc) 8077 { 8078 //printf("TypeReturn::semantic() %s\n", toChars()); 8079 Expression e; 8080 Type t; 8081 Dsymbol s; 8082 resolve(loc, sc, &e, &t, &s); 8083 if (s && (t = s.getType()) !is null) 8084 t = t.addMod(mod); 8085 if (!t) 8086 { 8087 error(loc, "%s is used as a type", toChars()); 8088 t = Type.terror; 8089 } 8090 return t; 8091 } 8092 8093 override void accept(Visitor v) 8094 { 8095 v.visit(this); 8096 } 8097 } 8098 8099 // Whether alias this dependency is recursive or not. 8100 enum AliasThisRec : int 8101 { 8102 RECno = 0, // no alias this recursion 8103 RECyes = 1, // alias this has recursive dependency 8104 RECfwdref = 2, // not yet known 8105 RECtypeMask = 3, // mask to read no/yes/fwdref 8106 RECtracing = 0x4, // mark in progress of implicitConvTo/deduceWild 8107 RECtracingDT = 0x8, // mark in progress of deduceType 8108 } 8109 8110 alias RECno = AliasThisRec.RECno; 8111 alias RECyes = AliasThisRec.RECyes; 8112 alias RECfwdref = AliasThisRec.RECfwdref; 8113 alias RECtypeMask = AliasThisRec.RECtypeMask; 8114 alias RECtracing = AliasThisRec.RECtracing; 8115 alias RECtracingDT = AliasThisRec.RECtracingDT; 8116 8117 /*********************************************************** 8118 */ 8119 extern (C++) final class TypeStruct : Type 8120 { 8121 StructDeclaration sym; 8122 AliasThisRec att = RECfwdref; 8123 CPPMANGLE cppmangle = CPPMANGLE.def; 8124 8125 extern (D) this(StructDeclaration sym) 8126 { 8127 super(Tstruct); 8128 this.sym = sym; 8129 } 8130 8131 override const(char)* kind() const 8132 { 8133 return "struct"; 8134 } 8135 8136 override d_uns64 size(Loc loc) 8137 { 8138 return sym.size(loc); 8139 } 8140 8141 override uint alignsize() 8142 { 8143 sym.size(Loc()); // give error for forward references 8144 return sym.alignsize; 8145 } 8146 8147 override Type syntaxCopy() 8148 { 8149 return this; 8150 } 8151 8152 override Type semantic(Loc loc, Scope* sc) 8153 { 8154 //printf("TypeStruct::semantic('%s')\n", sym.toChars()); 8155 if (deco) 8156 { 8157 if (sc && sc.cppmangle != CPPMANGLE.def) 8158 { 8159 if (this.cppmangle == CPPMANGLE.def) 8160 this.cppmangle = sc.cppmangle; 8161 else 8162 assert(this.cppmangle == sc.cppmangle); 8163 } 8164 return this; 8165 } 8166 8167 /* Don't semantic for sym because it should be deferred until 8168 * sizeof needed or its members accessed. 8169 */ 8170 // instead, parent should be set correctly 8171 assert(sym.parent); 8172 8173 if (sym.type.ty == Terror) 8174 return Type.terror; 8175 if (sc) 8176 this.cppmangle = sc.cppmangle; 8177 return merge(); 8178 } 8179 8180 override Dsymbol toDsymbol(Scope* sc) 8181 { 8182 return sym; 8183 } 8184 8185 override Expression dotExp(Scope* sc, Expression e, Identifier ident, int flag) 8186 { 8187 Dsymbol s; 8188 static if (LOGDOTEXP) 8189 { 8190 printf("TypeStruct::dotExp(e = '%s', ident = '%s')\n", e.toChars(), ident.toChars()); 8191 } 8192 assert(e.op != TOKdot); 8193 8194 // Bugzilla 14010 8195 if (ident == Id._mangleof) 8196 return getProperty(e.loc, ident, flag & 1); 8197 8198 /* If e.tupleof 8199 */ 8200 if (ident == Id._tupleof) 8201 { 8202 /* Create a TupleExp out of the fields of the struct e: 8203 * (e.field0, e.field1, e.field2, ...) 8204 */ 8205 e = e.semantic(sc); // do this before turning on noaccesscheck 8206 8207 sym.size(e.loc); // do semantic of type 8208 8209 Expression e0; 8210 Expression ev = e.op == TOKtype ? null : e; 8211 if (ev) 8212 ev = extractSideEffect(sc, "__tup", e0, ev); 8213 8214 auto exps = new Expressions(); 8215 exps.reserve(sym.fields.dim); 8216 for (size_t i = 0; i < sym.fields.dim; i++) 8217 { 8218 VarDeclaration v = sym.fields[i]; 8219 Expression ex; 8220 if (ev) 8221 ex = new DotVarExp(e.loc, ev, v); 8222 else 8223 { 8224 ex = new VarExp(e.loc, v); 8225 ex.type = ex.type.addMod(e.type.mod); 8226 } 8227 exps.push(ex); 8228 } 8229 8230 e = new TupleExp(e.loc, e0, exps); 8231 Scope* sc2 = sc.push(); 8232 sc2.flags = sc.flags | SCOPEnoaccesscheck; 8233 e = e.semantic(sc2); 8234 sc2.pop(); 8235 return e; 8236 } 8237 8238 Dsymbol searchSym() 8239 { 8240 int flags = 0; 8241 Dsymbol sold = void; 8242 if (global.params.bug10378 || global.params.check10378) 8243 { 8244 sold = sym.search(e.loc, ident, flags); 8245 if (!global.params.check10378) 8246 return sold; 8247 } 8248 8249 auto s = sym.search(e.loc, ident, flags | SearchLocalsOnly); 8250 if (global.params.check10378) 8251 { 8252 alias snew = s; 8253 if (sold !is snew) 8254 Scope.deprecation10378(e.loc, sold, snew); 8255 if (global.params.bug10378) 8256 s = sold; 8257 } 8258 return s; 8259 } 8260 8261 s = searchSym(); 8262 L1: 8263 if (!s) 8264 { 8265 return noMember(sc, e, ident, flag); 8266 } 8267 if (!symbolIsVisible(sc, s)) 8268 { 8269 .deprecation(e.loc, "%s is not visible from module %s", s.toPrettyChars(), sc._module.toPrettyChars()); 8270 // return noMember(sc, e, ident, flag); 8271 } 8272 if (!s.isFuncDeclaration()) // because of overloading 8273 s.checkDeprecated(e.loc, sc); 8274 s = s.toAlias(); 8275 8276 if (auto em = s.isEnumMember()) 8277 { 8278 return em.getVarExp(e.loc, sc); 8279 } 8280 if (auto v = s.isVarDeclaration()) 8281 { 8282 if (!v.type || 8283 !v.type.deco && v.inuse) 8284 { 8285 if (v.inuse) // Bugzilla 9494 8286 e.error("circular reference to %s '%s'", v.kind(), v.toPrettyChars()); 8287 else 8288 e.error("forward reference to %s '%s'", v.kind(), v.toPrettyChars()); 8289 return new ErrorExp(); 8290 } 8291 if (v.type.ty == Terror) 8292 return new ErrorExp(); 8293 8294 if ((v.storage_class & STCmanifest) && v._init) 8295 { 8296 if (v.inuse) 8297 { 8298 e.error("circular initialization of %s '%s'", v.kind(), v.toPrettyChars()); 8299 return new ErrorExp(); 8300 } 8301 checkAccess(e.loc, sc, null, v); 8302 Expression ve = new VarExp(e.loc, v); 8303 ve = ve.semantic(sc); 8304 return ve; 8305 } 8306 } 8307 8308 if (auto t = s.getType()) 8309 { 8310 return (new TypeExp(e.loc, t)).semantic(sc); 8311 } 8312 8313 TemplateMixin tm = s.isTemplateMixin(); 8314 if (tm) 8315 { 8316 Expression de = new DotExp(e.loc, e, new ScopeExp(e.loc, tm)); 8317 de.type = e.type; 8318 return de; 8319 } 8320 8321 TemplateDeclaration td = s.isTemplateDeclaration(); 8322 if (td) 8323 { 8324 if (e.op == TOKtype) 8325 e = new TemplateExp(e.loc, td); 8326 else 8327 e = new DotTemplateExp(e.loc, e, td); 8328 e = e.semantic(sc); 8329 return e; 8330 } 8331 8332 TemplateInstance ti = s.isTemplateInstance(); 8333 if (ti) 8334 { 8335 if (!ti.semanticRun) 8336 { 8337 ti.semantic(sc); 8338 if (!ti.inst || ti.errors) // if template failed to expand 8339 return new ErrorExp(); 8340 } 8341 s = ti.inst.toAlias(); 8342 if (!s.isTemplateInstance()) 8343 goto L1; 8344 if (e.op == TOKtype) 8345 e = new ScopeExp(e.loc, ti); 8346 else 8347 e = new DotExp(e.loc, e, new ScopeExp(e.loc, ti)); 8348 return e.semantic(sc); 8349 } 8350 8351 if (s.isImport() || s.isModule() || s.isPackage()) 8352 { 8353 e = DsymbolExp.resolve(e.loc, sc, s, false); 8354 return e; 8355 } 8356 8357 OverloadSet o = s.isOverloadSet(); 8358 if (o) 8359 { 8360 auto oe = new OverExp(e.loc, o); 8361 if (e.op == TOKtype) 8362 return oe; 8363 return new DotExp(e.loc, e, oe); 8364 } 8365 8366 Declaration d = s.isDeclaration(); 8367 if (!d) 8368 { 8369 e.error("%s.%s is not a declaration", e.toChars(), ident.toChars()); 8370 return new ErrorExp(); 8371 } 8372 8373 if (e.op == TOKtype) 8374 { 8375 /* It's: 8376 * Struct.d 8377 */ 8378 if (TupleDeclaration tup = d.isTupleDeclaration()) 8379 { 8380 e = new TupleExp(e.loc, tup); 8381 e = e.semantic(sc); 8382 return e; 8383 } 8384 if (d.needThis() && sc.intypeof != 1) 8385 { 8386 /* Rewrite as: 8387 * this.d 8388 */ 8389 if (hasThis(sc)) 8390 { 8391 e = new DotVarExp(e.loc, new ThisExp(e.loc), d); 8392 e = e.semantic(sc); 8393 return e; 8394 } 8395 } 8396 if (d.semanticRun == PASSinit && d._scope) 8397 d.semantic(d._scope); 8398 checkAccess(e.loc, sc, e, d); 8399 auto ve = new VarExp(e.loc, d); 8400 if (d.isVarDeclaration() && d.needThis()) 8401 ve.type = d.type.addMod(e.type.mod); 8402 return ve; 8403 } 8404 8405 bool unreal = e.op == TOKvar && (cast(VarExp)e).var.isField(); 8406 if (d.isDataseg() || unreal && d.isField()) 8407 { 8408 // (e, d) 8409 checkAccess(e.loc, sc, e, d); 8410 Expression ve = new VarExp(e.loc, d); 8411 e = unreal ? ve : new CommaExp(e.loc, e, ve); 8412 e = e.semantic(sc); 8413 return e; 8414 } 8415 8416 e = new DotVarExp(e.loc, e, d); 8417 e = e.semantic(sc); 8418 return e; 8419 } 8420 8421 override structalign_t alignment() 8422 { 8423 if (sym.alignment == 0) 8424 sym.size(sym.loc); 8425 return sym.alignment; 8426 } 8427 8428 override Expression defaultInit(Loc loc) 8429 { 8430 static if (LOGDEFAULTINIT) 8431 { 8432 printf("TypeStruct::defaultInit() '%s'\n", toChars()); 8433 } 8434 Declaration d = new SymbolDeclaration(sym.loc, sym); 8435 assert(d); 8436 d.type = this; 8437 d.storage_class |= STCrvalue; // Bugzilla 14398 8438 return new VarExp(sym.loc, d); 8439 } 8440 8441 /*************************************** 8442 * Use when we prefer the default initializer to be a literal, 8443 * rather than a global immutable variable. 8444 */ 8445 override Expression defaultInitLiteral(Loc loc) 8446 { 8447 static if (LOGDEFAULTINIT) 8448 { 8449 printf("TypeStruct::defaultInitLiteral() '%s'\n", toChars()); 8450 } 8451 sym.size(loc); 8452 if (sym.sizeok != SIZEOKdone) 8453 return new ErrorExp(); 8454 8455 auto structelems = new Expressions(); 8456 structelems.setDim(sym.fields.dim - sym.isNested()); 8457 uint offset = 0; 8458 for (size_t j = 0; j < structelems.dim; j++) 8459 { 8460 VarDeclaration vd = sym.fields[j]; 8461 Expression e; 8462 if (vd.inuse) 8463 { 8464 error(loc, "circular reference to '%s'", vd.toPrettyChars()); 8465 return new ErrorExp(); 8466 } 8467 if (vd.offset < offset || vd.type.size() == 0) 8468 e = null; 8469 else if (vd._init) 8470 { 8471 if (vd._init.isVoidInitializer()) 8472 e = null; 8473 else 8474 e = vd.getConstInitializer(false); 8475 } 8476 else 8477 e = vd.type.defaultInitLiteral(loc); 8478 if (e && e.op == TOKerror) 8479 return e; 8480 if (e) 8481 offset = vd.offset + cast(uint)vd.type.size(); 8482 (*structelems)[j] = e; 8483 } 8484 auto structinit = new StructLiteralExp(loc, sym, structelems); 8485 8486 /* Copy from the initializer symbol for larger symbols, 8487 * otherwise the literals expressed as code get excessively large. 8488 */ 8489 if (size(loc) > Target.ptrsize * 4 && !needsNested()) 8490 structinit.useStaticInit = true; 8491 8492 structinit.type = this; 8493 return structinit; 8494 } 8495 8496 override bool isZeroInit(Loc loc) const 8497 { 8498 return sym.zeroInit != 0; 8499 } 8500 8501 override bool isAssignable() 8502 { 8503 bool assignable = true; 8504 uint offset = ~0; // dead-store initialize to prevent spurious warning 8505 8506 /* If any of the fields are const or immutable, 8507 * then one cannot assign this struct. 8508 */ 8509 for (size_t i = 0; i < sym.fields.dim; i++) 8510 { 8511 VarDeclaration v = sym.fields[i]; 8512 //printf("%s [%d] v = (%s) %s, v->offset = %d, v->parent = %s", sym->toChars(), i, v->kind(), v->toChars(), v->offset, v->parent->kind()); 8513 if (i == 0) 8514 { 8515 } 8516 else if (v.offset == offset) 8517 { 8518 /* If any fields of anonymous union are assignable, 8519 * then regard union as assignable. 8520 * This is to support unsafe things like Rebindable templates. 8521 */ 8522 if (assignable) 8523 continue; 8524 } 8525 else 8526 { 8527 if (!assignable) 8528 return false; 8529 } 8530 assignable = v.type.isMutable() && v.type.isAssignable(); 8531 offset = v.offset; 8532 //printf(" -> assignable = %d\n", assignable); 8533 } 8534 8535 return assignable; 8536 } 8537 8538 override bool isBoolean() const 8539 { 8540 return false; 8541 } 8542 8543 override bool needsDestruction() const 8544 { 8545 return sym.dtor !is null; 8546 } 8547 8548 override bool needsNested() 8549 { 8550 if (sym.isNested()) 8551 return true; 8552 8553 for (size_t i = 0; i < sym.fields.dim; i++) 8554 { 8555 VarDeclaration v = sym.fields[i]; 8556 if (!v.isDataseg() && v.type.needsNested()) 8557 return true; 8558 } 8559 return false; 8560 } 8561 8562 override bool hasPointers() 8563 { 8564 // Probably should cache this information in sym rather than recompute 8565 StructDeclaration s = sym; 8566 8567 sym.size(Loc()); // give error for forward references 8568 foreach (VarDeclaration v; s.fields) 8569 { 8570 if (v.storage_class & STCref || v.hasPointers()) 8571 return true; 8572 } 8573 return false; 8574 } 8575 8576 override bool hasVoidInitPointers() 8577 { 8578 // Probably should cache this information in sym rather than recompute 8579 StructDeclaration s = sym; 8580 8581 sym.size(Loc()); // give error for forward references 8582 foreach (VarDeclaration v; s.fields) 8583 { 8584 if (v._init && v._init.isVoidInitializer() && v.type.hasPointers()) 8585 return true; 8586 if (!v._init && v.type.hasVoidInitPointers()) 8587 return true; 8588 } 8589 return false; 8590 } 8591 8592 override MATCH implicitConvTo(Type to) 8593 { 8594 MATCH m; 8595 8596 //printf("TypeStruct::implicitConvTo(%s => %s)\n", toChars(), to.toChars()); 8597 if (ty == to.ty && sym == (cast(TypeStruct)to).sym) 8598 { 8599 m = MATCHexact; // exact match 8600 if (mod != to.mod) 8601 { 8602 m = MATCHconst; 8603 if (MODimplicitConv(mod, to.mod)) 8604 { 8605 } 8606 else 8607 { 8608 /* Check all the fields. If they can all be converted, 8609 * allow the conversion. 8610 */ 8611 uint offset = ~0; // dead-store to prevent spurious warning 8612 for (size_t i = 0; i < sym.fields.dim; i++) 8613 { 8614 VarDeclaration v = sym.fields[i]; 8615 if (i == 0) 8616 { 8617 } 8618 else if (v.offset == offset) 8619 { 8620 if (m > MATCHnomatch) 8621 continue; 8622 } 8623 else 8624 { 8625 if (m <= MATCHnomatch) 8626 return m; 8627 } 8628 8629 // 'from' type 8630 Type tvf = v.type.addMod(mod); 8631 8632 // 'to' type 8633 Type tv = v.type.addMod(to.mod); 8634 8635 // field match 8636 MATCH mf = tvf.implicitConvTo(tv); 8637 //printf("\t%s => %s, match = %d\n", v->type->toChars(), tv->toChars(), mf); 8638 8639 if (mf <= MATCHnomatch) 8640 return mf; 8641 if (mf < m) // if field match is worse 8642 m = mf; 8643 offset = v.offset; 8644 } 8645 } 8646 } 8647 } 8648 else if (sym.aliasthis && !(att & RECtracing)) 8649 { 8650 att = cast(AliasThisRec)(att | RECtracing); 8651 m = aliasthisOf().implicitConvTo(to); 8652 att = cast(AliasThisRec)(att & ~RECtracing); 8653 } 8654 else 8655 m = MATCHnomatch; // no match 8656 return m; 8657 } 8658 8659 override MATCH constConv(Type to) 8660 { 8661 if (equals(to)) 8662 return MATCHexact; 8663 if (ty == to.ty && sym == (cast(TypeStruct)to).sym && MODimplicitConv(mod, to.mod)) 8664 return MATCHconst; 8665 return MATCHnomatch; 8666 } 8667 8668 override ubyte deduceWild(Type t, bool isRef) 8669 { 8670 if (ty == t.ty && sym == (cast(TypeStruct)t).sym) 8671 return Type.deduceWild(t, isRef); 8672 8673 ubyte wm = 0; 8674 8675 if (t.hasWild() && sym.aliasthis && !(att & RECtracing)) 8676 { 8677 att = cast(AliasThisRec)(att | RECtracing); 8678 wm = aliasthisOf().deduceWild(t, isRef); 8679 att = cast(AliasThisRec)(att & ~RECtracing); 8680 } 8681 8682 return wm; 8683 } 8684 8685 override Type toHeadMutable() 8686 { 8687 return this; 8688 } 8689 8690 override void accept(Visitor v) 8691 { 8692 v.visit(this); 8693 } 8694 } 8695 8696 /*********************************************************** 8697 */ 8698 extern (C++) final class TypeEnum : Type 8699 { 8700 EnumDeclaration sym; 8701 8702 extern (D) this(EnumDeclaration sym) 8703 { 8704 super(Tenum); 8705 this.sym = sym; 8706 } 8707 8708 override const(char)* kind() const 8709 { 8710 return "enum"; 8711 } 8712 8713 override Type syntaxCopy() 8714 { 8715 return this; 8716 } 8717 8718 override d_uns64 size(Loc loc) 8719 { 8720 return sym.getMemtype(loc).size(loc); 8721 } 8722 8723 override uint alignsize() 8724 { 8725 Type t = sym.getMemtype(Loc()); 8726 if (t.ty == Terror) 8727 return 4; 8728 return t.alignsize(); 8729 } 8730 8731 override Type semantic(Loc loc, Scope* sc) 8732 { 8733 //printf("TypeEnum::semantic() %s\n", toChars()); 8734 if (deco) 8735 return this; 8736 return merge(); 8737 } 8738 8739 override Dsymbol toDsymbol(Scope* sc) 8740 { 8741 return sym; 8742 } 8743 8744 override Expression dotExp(Scope* sc, Expression e, Identifier ident, int flag) 8745 { 8746 static if (LOGDOTEXP) 8747 { 8748 printf("TypeEnum::dotExp(e = '%s', ident = '%s') '%s'\n", e.toChars(), ident.toChars(), toChars()); 8749 } 8750 // Bugzilla 14010 8751 if (ident == Id._mangleof) 8752 return getProperty(e.loc, ident, flag & 1); 8753 8754 if (sym._scope) 8755 sym.semantic(sym._scope); 8756 if (!sym.members) 8757 { 8758 if (!(flag & 1)) 8759 { 8760 sym.error("is forward referenced when looking for '%s'", ident.toChars()); 8761 e = new ErrorExp(); 8762 } 8763 else 8764 e = null; 8765 return e; 8766 } 8767 8768 Dsymbol s = sym.search(e.loc, ident); 8769 if (!s) 8770 { 8771 if (ident == Id.max || ident == Id.min || ident == Id._init) 8772 { 8773 return getProperty(e.loc, ident, flag & 1); 8774 } 8775 8776 Expression res = sym.getMemtype(Loc()).dotExp(sc, e, ident, 1); 8777 if (!(flag & 1) && !res) 8778 { 8779 if (auto ns = sym.search_correct(ident)) 8780 e.error("no property '%s' for type '%s'. Did you mean '%s.%s' ?", ident.toChars(), toChars(), toChars(), 8781 ns.toChars()); 8782 else 8783 e.error("no property '%s' for type '%s'", ident.toChars(), 8784 toChars()); 8785 8786 return new ErrorExp(); 8787 } 8788 return res; 8789 } 8790 EnumMember m = s.isEnumMember(); 8791 return m.getVarExp(e.loc, sc); 8792 } 8793 8794 override Expression getProperty(Loc loc, Identifier ident, int flag) 8795 { 8796 Expression e; 8797 if (ident == Id.max || ident == Id.min) 8798 { 8799 return sym.getMaxMinValue(loc, ident); 8800 } 8801 else if (ident == Id._init) 8802 { 8803 e = defaultInitLiteral(loc); 8804 } 8805 else if (ident == Id.stringof) 8806 { 8807 const s = toChars(); 8808 e = new StringExp(loc, cast(char*)s); 8809 Scope sc; 8810 e = e.semantic(&sc); 8811 } 8812 else if (ident == Id._mangleof) 8813 { 8814 e = Type.getProperty(loc, ident, flag); 8815 } 8816 else 8817 { 8818 e = toBasetype().getProperty(loc, ident, flag); 8819 } 8820 return e; 8821 } 8822 8823 override bool isintegral() 8824 { 8825 return sym.getMemtype(Loc()).isintegral(); 8826 } 8827 8828 override bool isfloating() 8829 { 8830 return sym.getMemtype(Loc()).isfloating(); 8831 } 8832 8833 override bool isreal() 8834 { 8835 return sym.getMemtype(Loc()).isreal(); 8836 } 8837 8838 override bool isimaginary() 8839 { 8840 return sym.getMemtype(Loc()).isimaginary(); 8841 } 8842 8843 override bool iscomplex() 8844 { 8845 return sym.getMemtype(Loc()).iscomplex(); 8846 } 8847 8848 override bool isscalar() 8849 { 8850 return sym.getMemtype(Loc()).isscalar(); 8851 } 8852 8853 override bool isunsigned() 8854 { 8855 return sym.getMemtype(Loc()).isunsigned(); 8856 } 8857 8858 override bool isBoolean() 8859 { 8860 return sym.getMemtype(Loc()).isBoolean(); 8861 } 8862 8863 override bool isString() 8864 { 8865 return sym.getMemtype(Loc()).isString(); 8866 } 8867 8868 override bool isAssignable() 8869 { 8870 return sym.getMemtype(Loc()).isAssignable(); 8871 } 8872 8873 override bool needsDestruction() 8874 { 8875 return sym.getMemtype(Loc()).needsDestruction(); 8876 } 8877 8878 override bool needsNested() 8879 { 8880 return sym.getMemtype(Loc()).needsNested(); 8881 } 8882 8883 override MATCH implicitConvTo(Type to) 8884 { 8885 MATCH m; 8886 //printf("TypeEnum::implicitConvTo()\n"); 8887 if (ty == to.ty && sym == (cast(TypeEnum)to).sym) 8888 m = (mod == to.mod) ? MATCHexact : MATCHconst; 8889 else if (sym.getMemtype(Loc()).implicitConvTo(to)) 8890 m = MATCHconvert; // match with conversions 8891 else 8892 m = MATCHnomatch; // no match 8893 return m; 8894 } 8895 8896 override MATCH constConv(Type to) 8897 { 8898 if (equals(to)) 8899 return MATCHexact; 8900 if (ty == to.ty && sym == (cast(TypeEnum)to).sym && MODimplicitConv(mod, to.mod)) 8901 return MATCHconst; 8902 return MATCHnomatch; 8903 } 8904 8905 override Type toBasetype() 8906 { 8907 if (!sym.members && !sym.memtype) 8908 return this; 8909 auto tb = sym.getMemtype(Loc()).toBasetype(); 8910 return tb.castMod(mod); // retain modifier bits from 'this' 8911 } 8912 8913 override Expression defaultInit(Loc loc) 8914 { 8915 static if (LOGDEFAULTINIT) 8916 { 8917 printf("TypeEnum::defaultInit() '%s'\n", toChars()); 8918 } 8919 // Initialize to first member of enum 8920 Expression e = sym.getDefaultValue(loc); 8921 e = e.copy(); 8922 e.loc = loc; 8923 e.type = this; // to deal with const, immutable, etc., variants 8924 return e; 8925 } 8926 8927 override bool isZeroInit(Loc loc) 8928 { 8929 return sym.getDefaultValue(loc).isBool(false); 8930 } 8931 8932 override bool hasPointers() 8933 { 8934 return sym.getMemtype(Loc()).hasPointers(); 8935 } 8936 8937 override bool hasVoidInitPointers() 8938 { 8939 return sym.getMemtype(Loc()).hasVoidInitPointers(); 8940 } 8941 8942 override Type nextOf() 8943 { 8944 return sym.getMemtype(Loc()).nextOf(); 8945 } 8946 8947 override void accept(Visitor v) 8948 { 8949 v.visit(this); 8950 } 8951 } 8952 8953 /*********************************************************** 8954 */ 8955 extern (C++) final class TypeClass : Type 8956 { 8957 ClassDeclaration sym; 8958 AliasThisRec att = RECfwdref; 8959 CPPMANGLE cppmangle = CPPMANGLE.def; 8960 8961 extern (D) this(ClassDeclaration sym) 8962 { 8963 super(Tclass); 8964 this.sym = sym; 8965 } 8966 8967 override const(char)* kind() const 8968 { 8969 return "class"; 8970 } 8971 8972 override d_uns64 size(Loc loc) const 8973 { 8974 return Target.ptrsize; 8975 } 8976 8977 override Type syntaxCopy() 8978 { 8979 return this; 8980 } 8981 8982 override Type semantic(Loc loc, Scope* sc) 8983 { 8984 //printf("TypeClass::semantic(%s)\n", sym.toChars()); 8985 if (deco) 8986 { 8987 if (sc && sc.cppmangle != CPPMANGLE.def) 8988 { 8989 if (this.cppmangle == CPPMANGLE.def) 8990 this.cppmangle = sc.cppmangle; 8991 else 8992 assert(this.cppmangle == sc.cppmangle); 8993 } 8994 return this; 8995 } 8996 8997 /* Don't semantic for sym because it should be deferred until 8998 * sizeof needed or its members accessed. 8999 */ 9000 // instead, parent should be set correctly 9001 assert(sym.parent); 9002 9003 if (sym.type.ty == Terror) 9004 return Type.terror; 9005 if (sc) 9006 this.cppmangle = sc.cppmangle; 9007 return merge(); 9008 } 9009 9010 override Dsymbol toDsymbol(Scope* sc) 9011 { 9012 return sym; 9013 } 9014 9015 override Expression dotExp(Scope* sc, Expression e, Identifier ident, int flag) 9016 { 9017 Dsymbol s; 9018 static if (LOGDOTEXP) 9019 { 9020 printf("TypeClass::dotExp(e = '%s', ident = '%s')\n", e.toChars(), ident.toChars()); 9021 } 9022 assert(e.op != TOKdot); 9023 9024 // Bugzilla 12543 9025 if (ident == Id.__sizeof || ident == Id.__xalignof || ident == Id._mangleof) 9026 { 9027 return Type.getProperty(e.loc, ident, 0); 9028 } 9029 9030 /* If e.tupleof 9031 */ 9032 if (ident == Id._tupleof) 9033 { 9034 /* Create a TupleExp 9035 */ 9036 e = e.semantic(sc); // do this before turning on noaccesscheck 9037 9038 sym.size(e.loc); // do semantic of type 9039 9040 Expression e0; 9041 Expression ev = e.op == TOKtype ? null : e; 9042 if (ev) 9043 ev = extractSideEffect(sc, "__tup", e0, ev); 9044 9045 auto exps = new Expressions(); 9046 exps.reserve(sym.fields.dim); 9047 for (size_t i = 0; i < sym.fields.dim; i++) 9048 { 9049 VarDeclaration v = sym.fields[i]; 9050 // Don't include hidden 'this' pointer 9051 if (v.isThisDeclaration()) 9052 continue; 9053 Expression ex; 9054 if (ev) 9055 ex = new DotVarExp(e.loc, ev, v); 9056 else 9057 { 9058 ex = new VarExp(e.loc, v); 9059 ex.type = ex.type.addMod(e.type.mod); 9060 } 9061 exps.push(ex); 9062 } 9063 9064 e = new TupleExp(e.loc, e0, exps); 9065 Scope* sc2 = sc.push(); 9066 sc2.flags = sc.flags | SCOPEnoaccesscheck; 9067 e = e.semantic(sc2); 9068 sc2.pop(); 9069 return e; 9070 } 9071 9072 Dsymbol searchSym() 9073 { 9074 int flags = 0; 9075 Dsymbol sold = void; 9076 if (global.params.bug10378 || global.params.check10378) 9077 { 9078 sold = sym.search(e.loc, ident, flags | IgnoreSymbolVisibility); 9079 if (!global.params.check10378) 9080 return sold; 9081 } 9082 9083 auto s = sym.search(e.loc, ident, flags | SearchLocalsOnly); 9084 if (!s) 9085 { 9086 s = sym.search(e.loc, ident, flags | SearchLocalsOnly | IgnoreSymbolVisibility); 9087 if (s && !(flags & IgnoreErrors)) 9088 .deprecation(e.loc, "%s is not visible from class %s", s.toPrettyChars(), sym.toChars()); 9089 } 9090 if (global.params.check10378) 9091 { 9092 alias snew = s; 9093 if (sold !is snew) 9094 Scope.deprecation10378(e.loc, sold, snew); 9095 if (global.params.bug10378) 9096 s = sold; 9097 } 9098 return s; 9099 } 9100 9101 s = searchSym(); 9102 L1: 9103 if (!s) 9104 { 9105 // See if it's 'this' class or a base class 9106 if (sym.ident == ident) 9107 { 9108 if (e.op == TOKtype) 9109 return Type.getProperty(e.loc, ident, 0); 9110 e = new DotTypeExp(e.loc, e, sym); 9111 e = e.semantic(sc); 9112 return e; 9113 } 9114 if (auto cbase = sym.searchBase(ident)) 9115 { 9116 if (e.op == TOKtype) 9117 return Type.getProperty(e.loc, ident, 0); 9118 if (auto ifbase = cbase.isInterfaceDeclaration()) 9119 e = new CastExp(e.loc, e, ifbase.type); 9120 else 9121 e = new DotTypeExp(e.loc, e, cbase); 9122 e = e.semantic(sc); 9123 return e; 9124 } 9125 9126 if (ident == Id.classinfo) 9127 { 9128 assert(Type.typeinfoclass); 9129 Type t = Type.typeinfoclass.type; 9130 if (e.op == TOKtype || e.op == TOKdottype) 9131 { 9132 /* For type.classinfo, we know the classinfo 9133 * at compile time. 9134 */ 9135 if (!sym.vclassinfo) 9136 sym.vclassinfo = new TypeInfoClassDeclaration(sym.type); 9137 e = new VarExp(e.loc, sym.vclassinfo); 9138 e = e.addressOf(); 9139 e.type = t; // do this so we don't get redundant dereference 9140 } 9141 else 9142 { 9143 /* For class objects, the classinfo reference is the first 9144 * entry in the vtbl[] 9145 */ 9146 e = new PtrExp(e.loc, e); 9147 e.type = t.pointerTo(); 9148 if (sym.isInterfaceDeclaration()) 9149 { 9150 if (sym.isCPPinterface()) 9151 { 9152 /* C++ interface vtbl[]s are different in that the 9153 * first entry is always pointer to the first virtual 9154 * function, not classinfo. 9155 * We can't get a .classinfo for it. 9156 */ 9157 error(e.loc, "no .classinfo for C++ interface objects"); 9158 } 9159 /* For an interface, the first entry in the vtbl[] 9160 * is actually a pointer to an instance of struct Interface. 9161 * The first member of Interface is the .classinfo, 9162 * so add an extra pointer indirection. 9163 */ 9164 e.type = e.type.pointerTo(); 9165 e = new PtrExp(e.loc, e); 9166 e.type = t.pointerTo(); 9167 } 9168 e = new PtrExp(e.loc, e, t); 9169 } 9170 return e; 9171 } 9172 9173 if (ident == Id.__vptr) 9174 { 9175 /* The pointer to the vtbl[] 9176 * *cast(immutable(void*)**)e 9177 */ 9178 e = e.castTo(sc, tvoidptr.immutableOf().pointerTo().pointerTo()); 9179 e = new PtrExp(e.loc, e); 9180 e = e.semantic(sc); 9181 return e; 9182 } 9183 9184 if (ident == Id.__monitor) 9185 { 9186 /* The handle to the monitor (call it a void*) 9187 * *(cast(void**)e + 1) 9188 */ 9189 e = e.castTo(sc, tvoidptr.pointerTo()); 9190 e = new AddExp(e.loc, e, new IntegerExp(1)); 9191 e = new PtrExp(e.loc, e); 9192 e = e.semantic(sc); 9193 return e; 9194 } 9195 9196 if (ident == Id.outer && sym.vthis) 9197 { 9198 if (sym.vthis._scope) 9199 sym.vthis.semantic(null); 9200 9201 if (auto cdp = sym.toParent2().isClassDeclaration()) 9202 { 9203 auto dve = new DotVarExp(e.loc, e, sym.vthis); 9204 dve.type = cdp.type.addMod(e.type.mod); 9205 return dve; 9206 } 9207 9208 /* Bugzilla 15839: Find closest parent class through nested functions. 9209 */ 9210 for (auto p = sym.toParent2(); p; p = p.toParent2()) 9211 { 9212 auto fd = p.isFuncDeclaration(); 9213 if (!fd) 9214 break; 9215 if (fd.isNested()) 9216 continue; 9217 auto ad = fd.isThis(); 9218 if (!ad) 9219 break; 9220 if (auto cdp = ad.isClassDeclaration()) 9221 { 9222 auto ve = new ThisExp(e.loc); 9223 9224 ve.var = fd.vthis; 9225 const nestedError = fd.vthis.checkNestedReference(sc, e.loc); 9226 assert(!nestedError); 9227 9228 ve.type = fd.vthis.type.addMod(e.type.mod); 9229 return ve; 9230 } 9231 break; 9232 } 9233 9234 // Continue to show enclosing function's frame (stack or closure). 9235 auto dve = new DotVarExp(e.loc, e, sym.vthis); 9236 dve.type = sym.vthis.type.addMod(e.type.mod); 9237 return dve; 9238 } 9239 9240 return noMember(sc, e, ident, flag & 1); 9241 } 9242 if (!symbolIsVisible(sc, s)) 9243 { 9244 .deprecation(e.loc, "%s is not visible from module %s", s.toPrettyChars(), sc._module.toPrettyChars()); 9245 // return noMember(sc, e, ident, flag); 9246 } 9247 if (!s.isFuncDeclaration()) // because of overloading 9248 s.checkDeprecated(e.loc, sc); 9249 s = s.toAlias(); 9250 9251 if (auto em = s.isEnumMember()) 9252 { 9253 return em.getVarExp(e.loc, sc); 9254 } 9255 if (auto v = s.isVarDeclaration()) 9256 { 9257 if (!v.type || 9258 !v.type.deco && v.inuse) 9259 { 9260 if (v.inuse) // Bugzilla 9494 9261 e.error("circular reference to %s '%s'", v.kind(), v.toPrettyChars()); 9262 else 9263 e.error("forward reference to %s '%s'", v.kind(), v.toPrettyChars()); 9264 return new ErrorExp(); 9265 } 9266 if (v.type.ty == Terror) 9267 return new ErrorExp(); 9268 9269 if ((v.storage_class & STCmanifest) && v._init) 9270 { 9271 if (v.inuse) 9272 { 9273 e.error("circular initialization of %s '%s'", v.kind(), v.toPrettyChars()); 9274 return new ErrorExp(); 9275 } 9276 checkAccess(e.loc, sc, null, v); 9277 Expression ve = new VarExp(e.loc, v); 9278 ve = ve.semantic(sc); 9279 return ve; 9280 } 9281 } 9282 9283 if (auto t = s.getType()) 9284 { 9285 return (new TypeExp(e.loc, t)).semantic(sc); 9286 } 9287 9288 TemplateMixin tm = s.isTemplateMixin(); 9289 if (tm) 9290 { 9291 Expression de = new DotExp(e.loc, e, new ScopeExp(e.loc, tm)); 9292 de.type = e.type; 9293 return de; 9294 } 9295 9296 TemplateDeclaration td = s.isTemplateDeclaration(); 9297 if (td) 9298 { 9299 if (e.op == TOKtype) 9300 e = new TemplateExp(e.loc, td); 9301 else 9302 e = new DotTemplateExp(e.loc, e, td); 9303 e = e.semantic(sc); 9304 return e; 9305 } 9306 9307 TemplateInstance ti = s.isTemplateInstance(); 9308 if (ti) 9309 { 9310 if (!ti.semanticRun) 9311 { 9312 ti.semantic(sc); 9313 if (!ti.inst || ti.errors) // if template failed to expand 9314 return new ErrorExp(); 9315 } 9316 s = ti.inst.toAlias(); 9317 if (!s.isTemplateInstance()) 9318 goto L1; 9319 if (e.op == TOKtype) 9320 e = new ScopeExp(e.loc, ti); 9321 else 9322 e = new DotExp(e.loc, e, new ScopeExp(e.loc, ti)); 9323 return e.semantic(sc); 9324 } 9325 9326 if (s.isImport() || s.isModule() || s.isPackage()) 9327 { 9328 e = DsymbolExp.resolve(e.loc, sc, s, false); 9329 return e; 9330 } 9331 9332 OverloadSet o = s.isOverloadSet(); 9333 if (o) 9334 { 9335 auto oe = new OverExp(e.loc, o); 9336 if (e.op == TOKtype) 9337 return oe; 9338 return new DotExp(e.loc, e, oe); 9339 } 9340 9341 Declaration d = s.isDeclaration(); 9342 if (!d) 9343 { 9344 e.error("%s.%s is not a declaration", e.toChars(), ident.toChars()); 9345 return new ErrorExp(); 9346 } 9347 9348 if (e.op == TOKtype) 9349 { 9350 /* It's: 9351 * Class.d 9352 */ 9353 if (TupleDeclaration tup = d.isTupleDeclaration()) 9354 { 9355 e = new TupleExp(e.loc, tup); 9356 e = e.semantic(sc); 9357 return e; 9358 } 9359 if (d.needThis() && sc.intypeof != 1) 9360 { 9361 /* Rewrite as: 9362 * this.d 9363 */ 9364 if (hasThis(sc)) 9365 { 9366 // This is almost same as getRightThis() in expression.c 9367 Expression e1 = new ThisExp(e.loc); 9368 e1 = e1.semantic(sc); 9369 L2: 9370 Type t = e1.type.toBasetype(); 9371 ClassDeclaration cd = e.type.isClassHandle(); 9372 ClassDeclaration tcd = t.isClassHandle(); 9373 if (cd && tcd && (tcd == cd || cd.isBaseOf(tcd, null))) 9374 { 9375 e = new DotTypeExp(e1.loc, e1, cd); 9376 e = new DotVarExp(e.loc, e, d); 9377 e = e.semantic(sc); 9378 return e; 9379 } 9380 if (tcd && tcd.isNested()) 9381 { 9382 /* e1 is the 'this' pointer for an inner class: tcd. 9383 * Rewrite it as the 'this' pointer for the outer class. 9384 */ 9385 e1 = new DotVarExp(e.loc, e1, tcd.vthis); 9386 e1.type = tcd.vthis.type; 9387 e1.type = e1.type.addMod(t.mod); 9388 // Do not call checkNestedRef() 9389 //e1 = e1->semantic(sc); 9390 9391 // Skip up over nested functions, and get the enclosing 9392 // class type. 9393 int n = 0; 9394 for (s = tcd.toParent(); s && s.isFuncDeclaration(); s = s.toParent()) 9395 { 9396 FuncDeclaration f = s.isFuncDeclaration(); 9397 if (f.vthis) 9398 { 9399 //printf("rewriting e1 to %s's this\n", f->toChars()); 9400 n++; 9401 e1 = new VarExp(e.loc, f.vthis); 9402 } 9403 else 9404 { 9405 e = new VarExp(e.loc, d); 9406 return e; 9407 } 9408 } 9409 if (s && s.isClassDeclaration()) 9410 { 9411 e1.type = s.isClassDeclaration().type; 9412 e1.type = e1.type.addMod(t.mod); 9413 if (n > 1) 9414 e1 = e1.semantic(sc); 9415 } 9416 else 9417 e1 = e1.semantic(sc); 9418 goto L2; 9419 } 9420 } 9421 } 9422 //printf("e = %s, d = %s\n", e->toChars(), d->toChars()); 9423 if (d.semanticRun == PASSinit && d._scope) 9424 d.semantic(d._scope); 9425 checkAccess(e.loc, sc, e, d); 9426 auto ve = new VarExp(e.loc, d); 9427 if (d.isVarDeclaration() && d.needThis()) 9428 ve.type = d.type.addMod(e.type.mod); 9429 return ve; 9430 } 9431 9432 bool unreal = e.op == TOKvar && (cast(VarExp)e).var.isField(); 9433 if (d.isDataseg() || unreal && d.isField()) 9434 { 9435 // (e, d) 9436 checkAccess(e.loc, sc, e, d); 9437 Expression ve = new VarExp(e.loc, d); 9438 e = unreal ? ve : new CommaExp(e.loc, e, ve); 9439 e = e.semantic(sc); 9440 return e; 9441 } 9442 9443 e = new DotVarExp(e.loc, e, d); 9444 e = e.semantic(sc); 9445 return e; 9446 } 9447 9448 override ClassDeclaration isClassHandle() 9449 { 9450 return sym; 9451 } 9452 9453 override bool isBaseOf(Type t, int* poffset) 9454 { 9455 if (t && t.ty == Tclass) 9456 { 9457 ClassDeclaration cd = (cast(TypeClass)t).sym; 9458 if (sym.isBaseOf(cd, poffset)) 9459 return true; 9460 } 9461 return false; 9462 } 9463 9464 override MATCH implicitConvTo(Type to) 9465 { 9466 //printf("TypeClass::implicitConvTo(to = '%s') %s\n", to->toChars(), toChars()); 9467 MATCH m = constConv(to); 9468 if (m > MATCHnomatch) 9469 return m; 9470 9471 ClassDeclaration cdto = to.isClassHandle(); 9472 if (cdto) 9473 { 9474 //printf("TypeClass::implicitConvTo(to = '%s') %s, isbase = %d %d\n", to->toChars(), toChars(), cdto->isBaseInfoComplete(), sym->isBaseInfoComplete()); 9475 if (cdto._scope && !cdto.isBaseInfoComplete()) 9476 cdto.semantic(null); 9477 if (sym._scope && !sym.isBaseInfoComplete()) 9478 sym.semantic(null); 9479 if (cdto.isBaseOf(sym, null) && MODimplicitConv(mod, to.mod)) 9480 { 9481 //printf("'to' is base\n"); 9482 return MATCHconvert; 9483 } 9484 } 9485 9486 m = MATCHnomatch; 9487 if (sym.aliasthis && !(att & RECtracing)) 9488 { 9489 att = cast(AliasThisRec)(att | RECtracing); 9490 m = aliasthisOf().implicitConvTo(to); 9491 att = cast(AliasThisRec)(att & ~RECtracing); 9492 } 9493 9494 return m; 9495 } 9496 9497 override MATCH constConv(Type to) 9498 { 9499 if (equals(to)) 9500 return MATCHexact; 9501 if (ty == to.ty && sym == (cast(TypeClass)to).sym && MODimplicitConv(mod, to.mod)) 9502 return MATCHconst; 9503 9504 /* Conversion derived to const(base) 9505 */ 9506 int offset = 0; 9507 if (to.isBaseOf(this, &offset) && offset == 0 && MODimplicitConv(mod, to.mod)) 9508 { 9509 // Disallow: 9510 // derived to base 9511 // inout(derived) to inout(base) 9512 if (!to.isMutable() && !to.isWild()) 9513 return MATCHconvert; 9514 } 9515 9516 return MATCHnomatch; 9517 } 9518 9519 override ubyte deduceWild(Type t, bool isRef) 9520 { 9521 ClassDeclaration cd = t.isClassHandle(); 9522 if (cd && (sym == cd || cd.isBaseOf(sym, null))) 9523 return Type.deduceWild(t, isRef); 9524 9525 ubyte wm = 0; 9526 9527 if (t.hasWild() && sym.aliasthis && !(att & RECtracing)) 9528 { 9529 att = cast(AliasThisRec)(att | RECtracing); 9530 wm = aliasthisOf().deduceWild(t, isRef); 9531 att = cast(AliasThisRec)(att & ~RECtracing); 9532 } 9533 9534 return wm; 9535 } 9536 9537 override Type toHeadMutable() 9538 { 9539 return this; 9540 } 9541 9542 override Expression defaultInit(Loc loc) 9543 { 9544 static if (LOGDEFAULTINIT) 9545 { 9546 printf("TypeClass::defaultInit() '%s'\n", toChars()); 9547 } 9548 return new NullExp(loc, this); 9549 } 9550 9551 override bool isZeroInit(Loc loc) const 9552 { 9553 return true; 9554 } 9555 9556 override bool isscope() const 9557 { 9558 return sym.isscope; 9559 } 9560 9561 override bool isBoolean() const 9562 { 9563 return true; 9564 } 9565 9566 override bool hasPointers() const 9567 { 9568 return true; 9569 } 9570 9571 override void accept(Visitor v) 9572 { 9573 v.visit(this); 9574 } 9575 } 9576 9577 /*********************************************************** 9578 */ 9579 extern (C++) final class TypeTuple : Type 9580 { 9581 Parameters* arguments; // types making up the tuple 9582 9583 extern (D) this(Parameters* arguments) 9584 { 9585 super(Ttuple); 9586 //printf("TypeTuple(this = %p)\n", this); 9587 this.arguments = arguments; 9588 //printf("TypeTuple() %p, %s\n", this, toChars()); 9589 debug 9590 { 9591 if (arguments) 9592 { 9593 for (size_t i = 0; i < arguments.dim; i++) 9594 { 9595 Parameter arg = (*arguments)[i]; 9596 assert(arg && arg.type); 9597 } 9598 } 9599 } 9600 } 9601 9602 /**************** 9603 * Form TypeTuple from the types of the expressions. 9604 * Assume exps[] is already tuple expanded. 9605 */ 9606 extern (D) this(Expressions* exps) 9607 { 9608 super(Ttuple); 9609 auto arguments = new Parameters(); 9610 if (exps) 9611 { 9612 arguments.setDim(exps.dim); 9613 for (size_t i = 0; i < exps.dim; i++) 9614 { 9615 Expression e = (*exps)[i]; 9616 if (e.type.ty == Ttuple) 9617 e.error("cannot form tuple of tuples"); 9618 auto arg = new Parameter(STCundefined, e.type, null, null); 9619 (*arguments)[i] = arg; 9620 } 9621 } 9622 this.arguments = arguments; 9623 //printf("TypeTuple() %p, %s\n", this, toChars()); 9624 } 9625 9626 static TypeTuple create(Parameters* arguments) 9627 { 9628 return new TypeTuple(arguments); 9629 } 9630 9631 /******************************************* 9632 * Type tuple with 0, 1 or 2 types in it. 9633 */ 9634 extern (D) this() 9635 { 9636 super(Ttuple); 9637 arguments = new Parameters(); 9638 } 9639 9640 extern (D) this(Type t1) 9641 { 9642 super(Ttuple); 9643 arguments = new Parameters(); 9644 arguments.push(new Parameter(0, t1, null, null)); 9645 } 9646 9647 extern (D) this(Type t1, Type t2) 9648 { 9649 super(Ttuple); 9650 arguments = new Parameters(); 9651 arguments.push(new Parameter(0, t1, null, null)); 9652 arguments.push(new Parameter(0, t2, null, null)); 9653 } 9654 9655 override const(char)* kind() const 9656 { 9657 return "tuple"; 9658 } 9659 9660 override Type syntaxCopy() 9661 { 9662 Parameters* args = Parameter.arraySyntaxCopy(arguments); 9663 Type t = new TypeTuple(args); 9664 t.mod = mod; 9665 return t; 9666 } 9667 9668 override Type semantic(Loc loc, Scope* sc) 9669 { 9670 //printf("TypeTuple::semantic(this = %p)\n", this); 9671 //printf("TypeTuple::semantic() %p, %s\n", this, toChars()); 9672 if (!deco) 9673 deco = merge().deco; 9674 9675 /* Don't return merge(), because a tuple with one type has the 9676 * same deco as that type. 9677 */ 9678 return this; 9679 } 9680 9681 override bool equals(RootObject o) 9682 { 9683 Type t = cast(Type)o; 9684 //printf("TypeTuple::equals(%s, %s)\n", toChars(), t->toChars()); 9685 if (this == t) 9686 return true; 9687 if (t.ty == Ttuple) 9688 { 9689 TypeTuple tt = cast(TypeTuple)t; 9690 if (arguments.dim == tt.arguments.dim) 9691 { 9692 for (size_t i = 0; i < tt.arguments.dim; i++) 9693 { 9694 Parameter arg1 = (*arguments)[i]; 9695 Parameter arg2 = (*tt.arguments)[i]; 9696 if (!arg1.type.equals(arg2.type)) 9697 return false; 9698 } 9699 return true; 9700 } 9701 } 9702 return false; 9703 } 9704 9705 override Expression getProperty(Loc loc, Identifier ident, int flag) 9706 { 9707 Expression e; 9708 static if (LOGDOTEXP) 9709 { 9710 printf("TypeTuple::getProperty(type = '%s', ident = '%s')\n", toChars(), ident.toChars()); 9711 } 9712 if (ident == Id.length) 9713 { 9714 e = new IntegerExp(loc, arguments.dim, Type.tsize_t); 9715 } 9716 else if (ident == Id._init) 9717 { 9718 e = defaultInitLiteral(loc); 9719 } 9720 else if (flag) 9721 { 9722 e = null; 9723 } 9724 else 9725 { 9726 error(loc, "no property '%s' for tuple '%s'", ident.toChars(), toChars()); 9727 e = new ErrorExp(); 9728 } 9729 return e; 9730 } 9731 9732 override Expression defaultInit(Loc loc) 9733 { 9734 auto exps = new Expressions(); 9735 exps.setDim(arguments.dim); 9736 for (size_t i = 0; i < arguments.dim; i++) 9737 { 9738 Parameter p = (*arguments)[i]; 9739 assert(p.type); 9740 Expression e = p.type.defaultInitLiteral(loc); 9741 if (e.op == TOKerror) 9742 return e; 9743 (*exps)[i] = e; 9744 } 9745 return new TupleExp(loc, exps); 9746 } 9747 9748 override void accept(Visitor v) 9749 { 9750 v.visit(this); 9751 } 9752 } 9753 9754 /*********************************************************** 9755 * This is so we can slice a TypeTuple 9756 */ 9757 extern (C++) final class TypeSlice : TypeNext 9758 { 9759 Expression lwr; 9760 Expression upr; 9761 9762 extern (D) this(Type next, Expression lwr, Expression upr) 9763 { 9764 super(Tslice, next); 9765 //printf("TypeSlice[%s .. %s]\n", lwr->toChars(), upr->toChars()); 9766 this.lwr = lwr; 9767 this.upr = upr; 9768 } 9769 9770 override const(char)* kind() const 9771 { 9772 return "slice"; 9773 } 9774 9775 override Type syntaxCopy() 9776 { 9777 Type t = new TypeSlice(next.syntaxCopy(), lwr.syntaxCopy(), upr.syntaxCopy()); 9778 t.mod = mod; 9779 return t; 9780 } 9781 9782 override Type semantic(Loc loc, Scope* sc) 9783 { 9784 //printf("TypeSlice::semantic() %s\n", toChars()); 9785 Type tn = next.semantic(loc, sc); 9786 //printf("next: %s\n", tn->toChars()); 9787 9788 Type tbn = tn.toBasetype(); 9789 if (tbn.ty != Ttuple) 9790 { 9791 error(loc, "can only slice tuple types, not %s", tbn.toChars()); 9792 return Type.terror; 9793 } 9794 TypeTuple tt = cast(TypeTuple)tbn; 9795 9796 lwr = semanticLength(sc, tbn, lwr); 9797 upr = semanticLength(sc, tbn, upr); 9798 lwr = lwr.ctfeInterpret(); 9799 upr = upr.ctfeInterpret(); 9800 if (lwr.op == TOKerror || upr.op == TOKerror) 9801 return Type.terror; 9802 9803 uinteger_t i1 = lwr.toUInteger(); 9804 uinteger_t i2 = upr.toUInteger(); 9805 if (!(i1 <= i2 && i2 <= tt.arguments.dim)) 9806 { 9807 error(loc, "slice [%llu..%llu] is out of range of [0..%u]", i1, i2, tt.arguments.dim); 9808 return Type.terror; 9809 } 9810 9811 next = tn; 9812 transitive(); 9813 9814 auto args = new Parameters(); 9815 args.reserve(cast(size_t)(i2 - i1)); 9816 for (size_t i = cast(size_t)i1; i < cast(size_t)i2; i++) 9817 { 9818 Parameter arg = (*tt.arguments)[i]; 9819 args.push(arg); 9820 } 9821 Type t = new TypeTuple(args); 9822 return t.semantic(loc, sc); 9823 } 9824 9825 override void resolve(Loc loc, Scope* sc, Expression* pe, Type* pt, Dsymbol* ps, bool intypeid = false) 9826 { 9827 next.resolve(loc, sc, pe, pt, ps, intypeid); 9828 if (*pe) 9829 { 9830 // It's really a slice expression 9831 if (Dsymbol s = getDsymbol(*pe)) 9832 *pe = new DsymbolExp(loc, s); 9833 *pe = new ArrayExp(loc, *pe, new IntervalExp(loc, lwr, upr)); 9834 } 9835 else if (*ps) 9836 { 9837 Dsymbol s = *ps; 9838 TupleDeclaration td = s.isTupleDeclaration(); 9839 if (td) 9840 { 9841 /* It's a slice of a TupleDeclaration 9842 */ 9843 ScopeDsymbol sym = new ArrayScopeSymbol(sc, td); 9844 sym.parent = sc.scopesym; 9845 sc = sc.push(sym); 9846 sc = sc.startCTFE(); 9847 lwr = lwr.semantic(sc); 9848 upr = upr.semantic(sc); 9849 sc = sc.endCTFE(); 9850 sc = sc.pop(); 9851 9852 lwr = lwr.ctfeInterpret(); 9853 upr = upr.ctfeInterpret(); 9854 uinteger_t i1 = lwr.toUInteger(); 9855 uinteger_t i2 = upr.toUInteger(); 9856 if (!(i1 <= i2 && i2 <= td.objects.dim)) 9857 { 9858 error(loc, "slice [%llu..%llu] is out of range of [0..%u]", i1, i2, td.objects.dim); 9859 *ps = null; 9860 *pt = Type.terror; 9861 return; 9862 } 9863 9864 if (i1 == 0 && i2 == td.objects.dim) 9865 { 9866 *ps = td; 9867 return; 9868 } 9869 9870 /* Create a new TupleDeclaration which 9871 * is a slice [i1..i2] out of the old one. 9872 */ 9873 auto objects = new Objects(); 9874 objects.setDim(cast(size_t)(i2 - i1)); 9875 for (size_t i = 0; i < objects.dim; i++) 9876 { 9877 (*objects)[i] = (*td.objects)[cast(size_t)i1 + i]; 9878 } 9879 9880 auto tds = new TupleDeclaration(loc, td.ident, objects); 9881 *ps = tds; 9882 } 9883 else 9884 goto Ldefault; 9885 } 9886 else 9887 { 9888 if ((*pt).ty != Terror) 9889 next = *pt; // prevent re-running semantic() on 'next' 9890 Ldefault: 9891 Type.resolve(loc, sc, pe, pt, ps, intypeid); 9892 } 9893 } 9894 9895 override void accept(Visitor v) 9896 { 9897 v.visit(this); 9898 } 9899 } 9900 9901 /*********************************************************** 9902 */ 9903 extern (C++) final class TypeNull : Type 9904 { 9905 extern (D) this() 9906 { 9907 super(Tnull); 9908 } 9909 9910 override const(char)* kind() const 9911 { 9912 return "null"; 9913 } 9914 9915 override Type syntaxCopy() 9916 { 9917 // No semantic analysis done, no need to copy 9918 return this; 9919 } 9920 9921 override MATCH implicitConvTo(Type to) 9922 { 9923 //printf("TypeNull::implicitConvTo(this=%p, to=%p)\n", this, to); 9924 //printf("from: %s\n", toChars()); 9925 //printf("to : %s\n", to->toChars()); 9926 MATCH m = Type.implicitConvTo(to); 9927 if (m != MATCHnomatch) 9928 return m; 9929 9930 // NULL implicitly converts to any pointer type or dynamic array 9931 //if (type->ty == Tpointer && type->nextOf()->ty == Tvoid) 9932 { 9933 Type tb = to.toBasetype(); 9934 if (tb.ty == Tnull || tb.ty == Tpointer || tb.ty == Tarray || tb.ty == Taarray || tb.ty == Tclass || tb.ty == Tdelegate) 9935 return MATCHconst; 9936 } 9937 9938 return MATCHnomatch; 9939 } 9940 9941 override bool isBoolean() const 9942 { 9943 return true; 9944 } 9945 9946 override d_uns64 size(Loc loc) const 9947 { 9948 return tvoidptr.size(loc); 9949 } 9950 9951 override Expression defaultInit(Loc loc) const 9952 { 9953 return new NullExp(Loc(), Type.tnull); 9954 } 9955 9956 override void accept(Visitor v) 9957 { 9958 v.visit(this); 9959 } 9960 } 9961 9962 /*********************************************************** 9963 */ 9964 extern (C++) final class Parameter : RootObject 9965 { 9966 StorageClass storageClass; 9967 Type type; 9968 Identifier ident; 9969 Expression defaultArg; 9970 9971 extern (D) this(StorageClass storageClass, Type type, Identifier ident, Expression defaultArg) 9972 { 9973 this.type = type; 9974 this.ident = ident; 9975 this.storageClass = storageClass; 9976 this.defaultArg = defaultArg; 9977 } 9978 9979 static Parameter create(StorageClass storageClass, Type type, Identifier ident, Expression defaultArg) 9980 { 9981 return new Parameter(storageClass, type, ident, defaultArg); 9982 } 9983 9984 Parameter syntaxCopy() 9985 { 9986 return new Parameter(storageClass, type ? type.syntaxCopy() : null, ident, defaultArg ? defaultArg.syntaxCopy() : null); 9987 } 9988 9989 /**************************************************** 9990 * Determine if parameter is a lazy array of delegates. 9991 * If so, return the return type of those delegates. 9992 * If not, return NULL. 9993 * 9994 * Returns T if the type is one of the following forms: 9995 * T delegate()[] 9996 * T delegate()[dim] 9997 */ 9998 Type isLazyArray() 9999 { 10000 Type tb = type.toBasetype(); 10001 if (tb.ty == Tsarray || tb.ty == Tarray) 10002 { 10003 Type tel = (cast(TypeArray)tb).next.toBasetype(); 10004 if (tel.ty == Tdelegate) 10005 { 10006 TypeDelegate td = cast(TypeDelegate)tel; 10007 TypeFunction tf = cast(TypeFunction)td.next; 10008 if (!tf.varargs && Parameter.dim(tf.parameters) == 0) 10009 { 10010 return tf.next; // return type of delegate 10011 } 10012 } 10013 } 10014 return null; 10015 } 10016 10017 // kludge for template.isType() 10018 override int dyncast() 10019 { 10020 return DYNCAST_PARAMETER; 10021 } 10022 10023 void accept(Visitor v) 10024 { 10025 v.visit(this); 10026 } 10027 10028 static Parameters* arraySyntaxCopy(Parameters* parameters) 10029 { 10030 Parameters* params = null; 10031 if (parameters) 10032 { 10033 params = new Parameters(); 10034 params.setDim(parameters.dim); 10035 for (size_t i = 0; i < params.dim; i++) 10036 (*params)[i] = (*parameters)[i].syntaxCopy(); 10037 } 10038 return params; 10039 } 10040 10041 /**************************************** 10042 * Determine if parameter list is really a template parameter list 10043 * (i.e. it has auto or alias parameters) 10044 */ 10045 extern (D) static int isTPL(Parameters* parameters) 10046 { 10047 //printf("Parameter::isTPL()\n"); 10048 10049 int isTPLDg(size_t n, Parameter p) 10050 { 10051 if (p.storageClass & (STCalias | STCauto | STCstatic)) 10052 return 1; 10053 return 0; 10054 } 10055 10056 return _foreach(parameters, &isTPLDg); 10057 } 10058 10059 /*************************************** 10060 * Determine number of arguments, folding in tuples. 10061 */ 10062 static size_t dim(Parameters* parameters) 10063 { 10064 size_t nargs = 0; 10065 10066 int dimDg(size_t n, Parameter p) 10067 { 10068 ++nargs; 10069 return 0; 10070 } 10071 10072 _foreach(parameters, &dimDg); 10073 return nargs; 10074 } 10075 10076 /*************************************** 10077 * Get nth Parameter, folding in tuples. 10078 * Returns: 10079 * Parameter* nth Parameter 10080 * NULL not found, *pn gets incremented by the number 10081 * of Parameters 10082 */ 10083 static Parameter getNth(Parameters* parameters, size_t nth, size_t* pn = null) 10084 { 10085 Parameter param; 10086 10087 int getNthParamDg(size_t n, Parameter p) 10088 { 10089 if (n == nth) 10090 { 10091 param = p; 10092 return 1; 10093 } 10094 return 0; 10095 } 10096 10097 int res = _foreach(parameters, &getNthParamDg); 10098 return res ? param : null; 10099 } 10100 10101 alias ForeachDg = extern (D) int delegate(size_t paramidx, Parameter param); 10102 10103 /*************************************** 10104 * Expands tuples in args in depth first order. Calls 10105 * dg(void *ctx, size_t argidx, Parameter *arg) for each Parameter. 10106 * If dg returns !=0, stops and returns that value else returns 0. 10107 * Use this function to avoid the O(N + N^2/2) complexity of 10108 * calculating dim and calling N times getNth. 10109 */ 10110 extern (D) static int _foreach(Parameters* parameters, scope ForeachDg dg, size_t* pn = null) 10111 { 10112 assert(dg); 10113 if (!parameters) 10114 return 0; 10115 10116 size_t n = pn ? *pn : 0; // take over index 10117 int result = 0; 10118 foreach (i; 0 .. parameters.dim) 10119 { 10120 Parameter p = (*parameters)[i]; 10121 Type t = p.type.toBasetype(); 10122 10123 if (t.ty == Ttuple) 10124 { 10125 TypeTuple tu = cast(TypeTuple)t; 10126 result = _foreach(tu.arguments, dg, &n); 10127 } 10128 else 10129 result = dg(n++, p); 10130 10131 if (result) 10132 break; 10133 } 10134 10135 if (pn) 10136 *pn = n; // update index 10137 return result; 10138 } 10139 10140 override const(char)* toChars() const 10141 { 10142 return ident ? ident.toChars() : "__anonymous_param"; 10143 } 10144 }