d: Merge upstream dmd, druntime f8bae04558, phobos ba2ade9dec
[official-gcc.git] / gcc / d / dmd / mtype.d
blob2c9e058bf325c465e597a3b35550ec1ffb9e6061
1 /**
2 * Defines a D type.
4 * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved
5 * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright)
6 * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
7 * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/mtype.d, _mtype.d)
8 * Documentation: https://dlang.org/phobos/dmd_mtype.html
9 * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/mtype.d
12 module dmd.mtype;
14 import core.checkedint;
15 import core.stdc.stdarg;
16 import core.stdc.stdio;
17 import core.stdc.stdlib;
18 import core.stdc.string;
20 import dmd.aggregate;
21 import dmd.arraytypes;
22 import dmd.astenums;
23 import dmd.ast_node;
24 import dmd.dclass;
25 import dmd.declaration;
26 import dmd.denum;
27 import dmd.dstruct;
28 import dmd.dsymbol;
29 import dmd.dtemplate;
30 import dmd.enumsem;
31 import dmd.errors;
32 import dmd.expression;
33 import dmd.funcsem;
34 import dmd.globals;
35 import dmd.hdrgen;
36 import dmd.id;
37 import dmd.identifier;
38 import dmd.location;
39 import dmd.root.ctfloat;
40 import dmd.common.outbuffer;
41 import dmd.root.rmem;
42 import dmd.rootobject;
43 import dmd.root.stringtable;
44 import dmd.target;
45 import dmd.tokens;
46 import dmd.typesem;
47 import dmd.visitor;
49 enum LOGDOTEXP = 0; // log ::dotExp()
50 enum LOGDEFAULTINIT = 0; // log ::defaultInit()
52 enum SIZE_INVALID = (~cast(uinteger_t)0); // error return from size() functions
54 static if (__VERSION__ < 2095)
56 // Fix linker errors when building with older compilers.
57 // See: https://issues.dlang.org/show_bug.cgi?id=21299
58 private alias StringValueType = StringValue!Type;
61 /***************************
62 * Return !=0 if modfrom can be implicitly converted to modto
64 bool MODimplicitConv(MOD modfrom, MOD modto) pure nothrow @nogc @safe
66 if (modfrom == modto)
67 return true;
69 //printf("MODimplicitConv(from = %x, to = %x)\n", modfrom, modto);
70 auto X(T, U)(T m, U n)
72 return ((m << 4) | n);
75 switch (X(modfrom & ~MODFlags.shared_, modto & ~MODFlags.shared_))
77 case X(0, MODFlags.const_):
78 case X(MODFlags.wild, MODFlags.const_):
79 case X(MODFlags.wild, MODFlags.wildconst):
80 case X(MODFlags.wildconst, MODFlags.const_):
81 return (modfrom & MODFlags.shared_) == (modto & MODFlags.shared_);
83 case X(MODFlags.immutable_, MODFlags.const_):
84 case X(MODFlags.immutable_, MODFlags.wildconst):
85 return true;
86 default:
87 return false;
91 /***************************
92 * Return MATCH.exact or MATCH.constant if a method of type '() modfrom' can call a method of type '() modto'.
94 MATCH MODmethodConv(MOD modfrom, MOD modto) pure nothrow @nogc @safe
96 if (modfrom == modto)
97 return MATCH.exact;
98 if (MODimplicitConv(modfrom, modto))
99 return MATCH.constant;
101 auto X(T, U)(T m, U n)
103 return ((m << 4) | n);
106 switch (X(modfrom, modto))
108 case X(0, MODFlags.wild):
109 case X(MODFlags.immutable_, MODFlags.wild):
110 case X(MODFlags.const_, MODFlags.wild):
111 case X(MODFlags.wildconst, MODFlags.wild):
112 case X(MODFlags.shared_, MODFlags.shared_ | MODFlags.wild):
113 case X(MODFlags.shared_ | MODFlags.immutable_, MODFlags.shared_ | MODFlags.wild):
114 case X(MODFlags.shared_ | MODFlags.const_, MODFlags.shared_ | MODFlags.wild):
115 case X(MODFlags.shared_ | MODFlags.wildconst, MODFlags.shared_ | MODFlags.wild):
116 return MATCH.constant;
118 default:
119 return MATCH.nomatch;
123 /***************************
124 * Merge mod bits to form common mod.
126 MOD MODmerge(MOD mod1, MOD mod2) pure nothrow @nogc @safe
128 if (mod1 == mod2)
129 return mod1;
131 //printf("MODmerge(1 = %x, 2 = %x)\n", mod1, mod2);
132 MOD result = 0;
133 if ((mod1 | mod2) & MODFlags.shared_)
135 // If either type is shared, the result will be shared
136 result |= MODFlags.shared_;
137 mod1 &= ~MODFlags.shared_;
138 mod2 &= ~MODFlags.shared_;
140 if (mod1 == 0 || mod1 == MODFlags.mutable || mod1 == MODFlags.const_ || mod2 == 0 || mod2 == MODFlags.mutable || mod2 == MODFlags.const_)
142 // If either type is mutable or const, the result will be const.
143 result |= MODFlags.const_;
145 else
147 // MODFlags.immutable_ vs MODFlags.wild
148 // MODFlags.immutable_ vs MODFlags.wildconst
149 // MODFlags.wild vs MODFlags.wildconst
150 assert(mod1 & MODFlags.wild || mod2 & MODFlags.wild);
151 result |= MODFlags.wildconst;
153 return result;
156 /*********************************
157 * Store modifier name into buf.
159 void MODtoBuffer(ref OutBuffer buf, MOD mod) nothrow @safe
161 buf.writestring(MODtoString(mod));
164 /*********************************
165 * Returns:
166 * a human readable representation of `mod`,
167 * which is the token `mod` corresponds to
169 const(char)* MODtoChars(MOD mod) nothrow pure
171 /// Works because we return a literal
172 return MODtoString(mod).ptr;
175 /// Ditto
176 string MODtoString(MOD mod) nothrow pure @safe
178 final switch (mod)
180 case 0:
181 return "";
183 case MODFlags.immutable_:
184 return "immutable";
186 case MODFlags.shared_:
187 return "shared";
189 case MODFlags.shared_ | MODFlags.const_:
190 return "shared const";
192 case MODFlags.const_:
193 return "const";
195 case MODFlags.shared_ | MODFlags.wild:
196 return "shared inout";
198 case MODFlags.wild:
199 return "inout";
201 case MODFlags.shared_ | MODFlags.wildconst:
202 return "shared inout const";
204 case MODFlags.wildconst:
205 return "inout const";
209 /*************************************************
210 * Pick off one of the trust flags from trust,
211 * and return a string representation of it.
213 string trustToString(TRUST trust) pure nothrow @nogc @safe
215 final switch (trust)
217 case TRUST.default_:
218 return null;
219 case TRUST.system:
220 return "@system";
221 case TRUST.trusted:
222 return "@trusted";
223 case TRUST.safe:
224 return "@safe";
228 unittest
230 assert(trustToString(TRUST.default_) == "");
231 assert(trustToString(TRUST.system) == "@system");
232 assert(trustToString(TRUST.trusted) == "@trusted");
233 assert(trustToString(TRUST.safe) == "@safe");
236 /************************************
237 * Convert MODxxxx to STCxxx
239 StorageClass ModToStc(uint mod) pure nothrow @nogc @safe
241 StorageClass stc = 0;
242 if (mod & MODFlags.immutable_)
243 stc |= STC.immutable_;
244 if (mod & MODFlags.const_)
245 stc |= STC.const_;
246 if (mod & MODFlags.wild)
247 stc |= STC.wild;
248 if (mod & MODFlags.shared_)
249 stc |= STC.shared_;
250 return stc;
253 ///Returns true if ty is char, wchar, or dchar
254 bool isSomeChar(TY ty) pure nothrow @nogc @safe
256 return ty == Tchar || ty == Twchar || ty == Tdchar;
259 /****************
260 * dotExp() bit flags
262 enum DotExpFlag
264 none = 0,
265 gag = 1, // don't report "not a property" error and just return null
266 noDeref = 2, // the use of the expression will not attempt a dereference
267 noAliasThis = 4, // don't do 'alias this' resolution
270 /// Result of a check whether two types are covariant
271 enum Covariant
273 distinct = 0, /// types are distinct
274 yes = 1, /// types are covariant
275 no = 2, /// arguments match as far as overloading goes, but types are not covariant
276 fwdref = 3, /// cannot determine covariance because of forward references
279 /***********************************************************
281 extern (C++) abstract class Type : ASTNode
283 TY ty;
284 MOD mod; // modifiers MODxxxx
285 char* deco;
287 static struct Mcache
289 /* These are cached values that are lazily evaluated by constOf(), immutableOf(), etc.
290 * They should not be referenced by anybody but mtype.d.
291 * They can be null if not lazily evaluated yet.
292 * Note that there is no "shared immutable", because that is just immutable
293 * The point of this is to reduce the size of each Type instance as
294 * we bank on the idea that usually only one of variants exist.
295 * It will also speed up code because these are rarely referenced and
296 * so need not be in the cache.
298 Type cto; // MODFlags.const_
299 Type ito; // MODFlags.immutable_
300 Type sto; // MODFlags.shared_
301 Type scto; // MODFlags.shared_ | MODFlags.const_
302 Type wto; // MODFlags.wild
303 Type wcto; // MODFlags.wildconst
304 Type swto; // MODFlags.shared_ | MODFlags.wild
305 Type swcto; // MODFlags.shared_ | MODFlags.wildconst
307 Mcache* mcache;
309 Type pto; // merged pointer to this type
310 Type rto; // reference to this type
311 Type arrayof; // array of this type
313 TypeInfoDeclaration vtinfo; // TypeInfo object for this Type
315 void* ctype; // for back end
317 extern (C++) __gshared Type tvoid;
318 extern (C++) __gshared Type tint8;
319 extern (C++) __gshared Type tuns8;
320 extern (C++) __gshared Type tint16;
321 extern (C++) __gshared Type tuns16;
322 extern (C++) __gshared Type tint32;
323 extern (C++) __gshared Type tuns32;
324 extern (C++) __gshared Type tint64;
325 extern (C++) __gshared Type tuns64;
326 extern (C++) __gshared Type tint128;
327 extern (C++) __gshared Type tuns128;
328 extern (C++) __gshared Type tfloat32;
329 extern (C++) __gshared Type tfloat64;
330 extern (C++) __gshared Type tfloat80;
331 extern (C++) __gshared Type timaginary32;
332 extern (C++) __gshared Type timaginary64;
333 extern (C++) __gshared Type timaginary80;
334 extern (C++) __gshared Type tcomplex32;
335 extern (C++) __gshared Type tcomplex64;
336 extern (C++) __gshared Type tcomplex80;
337 extern (C++) __gshared Type tbool;
338 extern (C++) __gshared Type tchar;
339 extern (C++) __gshared Type twchar;
340 extern (C++) __gshared Type tdchar;
342 // Some special types
343 extern (C++) __gshared Type tshiftcnt;
344 extern (C++) __gshared Type tvoidptr; // void*
345 extern (C++) __gshared Type tstring; // immutable(char)[]
346 extern (C++) __gshared Type twstring; // immutable(wchar)[]
347 extern (C++) __gshared Type tdstring; // immutable(dchar)[]
348 extern (C++) __gshared Type terror; // for error recovery
349 extern (C++) __gshared Type tnull; // for null type
350 extern (C++) __gshared Type tnoreturn; // for bottom type typeof(*null)
352 extern (C++) __gshared Type tsize_t; // matches size_t alias
353 extern (C++) __gshared Type tptrdiff_t; // matches ptrdiff_t alias
354 extern (C++) __gshared Type thash_t; // matches hash_t alias
356 extern (C++) __gshared ClassDeclaration dtypeinfo;
357 extern (C++) __gshared ClassDeclaration typeinfoclass;
358 extern (C++) __gshared ClassDeclaration typeinfointerface;
359 extern (C++) __gshared ClassDeclaration typeinfostruct;
360 extern (C++) __gshared ClassDeclaration typeinfopointer;
361 extern (C++) __gshared ClassDeclaration typeinfoarray;
362 extern (C++) __gshared ClassDeclaration typeinfostaticarray;
363 extern (C++) __gshared ClassDeclaration typeinfoassociativearray;
364 extern (C++) __gshared ClassDeclaration typeinfovector;
365 extern (C++) __gshared ClassDeclaration typeinfoenum;
366 extern (C++) __gshared ClassDeclaration typeinfofunction;
367 extern (C++) __gshared ClassDeclaration typeinfodelegate;
368 extern (C++) __gshared ClassDeclaration typeinfotypelist;
369 extern (C++) __gshared ClassDeclaration typeinfoconst;
370 extern (C++) __gshared ClassDeclaration typeinfoinvariant;
371 extern (C++) __gshared ClassDeclaration typeinfoshared;
372 extern (C++) __gshared ClassDeclaration typeinfowild;
374 extern (C++) __gshared TemplateDeclaration rtinfo;
376 extern (C++) __gshared Type[TMAX] basic;
378 extern (D) __gshared StringTable!Type stringtable;
379 extern (D) private static immutable ubyte[TMAX] sizeTy = ()
381 ubyte[TMAX] sizeTy = __traits(classInstanceSize, TypeBasic);
382 sizeTy[Tsarray] = __traits(classInstanceSize, TypeSArray);
383 sizeTy[Tarray] = __traits(classInstanceSize, TypeDArray);
384 sizeTy[Taarray] = __traits(classInstanceSize, TypeAArray);
385 sizeTy[Tpointer] = __traits(classInstanceSize, TypePointer);
386 sizeTy[Treference] = __traits(classInstanceSize, TypeReference);
387 sizeTy[Tfunction] = __traits(classInstanceSize, TypeFunction);
388 sizeTy[Tdelegate] = __traits(classInstanceSize, TypeDelegate);
389 sizeTy[Tident] = __traits(classInstanceSize, TypeIdentifier);
390 sizeTy[Tinstance] = __traits(classInstanceSize, TypeInstance);
391 sizeTy[Ttypeof] = __traits(classInstanceSize, TypeTypeof);
392 sizeTy[Tenum] = __traits(classInstanceSize, TypeEnum);
393 sizeTy[Tstruct] = __traits(classInstanceSize, TypeStruct);
394 sizeTy[Tclass] = __traits(classInstanceSize, TypeClass);
395 sizeTy[Ttuple] = __traits(classInstanceSize, TypeTuple);
396 sizeTy[Tslice] = __traits(classInstanceSize, TypeSlice);
397 sizeTy[Treturn] = __traits(classInstanceSize, TypeReturn);
398 sizeTy[Terror] = __traits(classInstanceSize, TypeError);
399 sizeTy[Tnull] = __traits(classInstanceSize, TypeNull);
400 sizeTy[Tvector] = __traits(classInstanceSize, TypeVector);
401 sizeTy[Ttraits] = __traits(classInstanceSize, TypeTraits);
402 sizeTy[Tmixin] = __traits(classInstanceSize, TypeMixin);
403 sizeTy[Tnoreturn] = __traits(classInstanceSize, TypeNoreturn);
404 sizeTy[Ttag] = __traits(classInstanceSize, TypeTag);
405 return sizeTy;
406 }();
408 final extern (D) this(TY ty) scope @safe
410 this.ty = ty;
413 const(char)* kind() const nothrow pure @nogc @safe
415 assert(false); // should be overridden
418 final Type copy() nothrow const
420 Type t = cast(Type)mem.xmalloc(sizeTy[ty]);
421 memcpy(cast(void*)t, cast(void*)this, sizeTy[ty]);
422 return t;
425 Type syntaxCopy()
427 fprintf(stderr, "this = %s, ty = %d\n", toChars(), ty);
428 assert(0);
431 override bool equals(const RootObject o) const
433 Type t = cast(Type)o;
434 //printf("Type::equals(%s, %s)\n", toChars(), t.toChars());
435 // deco strings are unique
436 // and semantic() has been run
437 if (this == o || ((t && deco == t.deco) && deco !is null))
439 //printf("deco = '%s', t.deco = '%s'\n", deco, t.deco);
440 return true;
442 //if (deco && t && t.deco) printf("deco = '%s', t.deco = '%s'\n", deco, t.deco);
443 return false;
446 // kludge for template.isType()
447 override final DYNCAST dyncast() const
449 return DYNCAST.type;
452 /// Returns a non-zero unique ID for this Type, or returns 0 if the Type does not (yet) have a unique ID.
453 /// If `semantic()` has not been run, 0 is returned.
454 final size_t getUniqueID() const
456 return cast(size_t) deco;
459 extern (D)
460 final Mcache* getMcache()
462 if (!mcache)
463 mcache = cast(Mcache*) mem.xcalloc(Mcache.sizeof, 1);
464 return mcache;
467 /********************************
468 * For pretty-printing a type.
470 final override const(char)* toChars() const
472 return dmd.hdrgen.toChars(this);
475 /// ditto
476 final char* toPrettyChars(bool QualifyTypes = false)
478 OutBuffer buf;
479 buf.reserve(16);
480 HdrGenState hgs;
481 hgs.fullQual = QualifyTypes;
483 toCBuffer(this, buf, null, hgs);
484 return buf.extractChars();
487 static void _init()
489 stringtable._init(14_000);
491 // Set basic types
492 __gshared TY* basetab =
494 Tvoid,
495 Tint8,
496 Tuns8,
497 Tint16,
498 Tuns16,
499 Tint32,
500 Tuns32,
501 Tint64,
502 Tuns64,
503 Tint128,
504 Tuns128,
505 Tfloat32,
506 Tfloat64,
507 Tfloat80,
508 Timaginary32,
509 Timaginary64,
510 Timaginary80,
511 Tcomplex32,
512 Tcomplex64,
513 Tcomplex80,
514 Tbool,
515 Tchar,
516 Twchar,
517 Tdchar,
518 Terror
521 static Type merge(Type t)
523 import dmd.basicmangle : tyToDecoBuffer;
525 OutBuffer buf;
526 buf.reserve(3);
528 if (t.ty == Tnoreturn)
529 buf.writestring("Nn");
530 else
531 tyToDecoBuffer(buf, t.ty);
533 auto sv = t.stringtable.update(buf[]);
534 if (sv.value)
535 return sv.value;
536 else
538 t.deco = cast(char*)sv.toDchars();
539 sv.value = t;
540 return t;
544 for (size_t i = 0; basetab[i] != Terror; i++)
546 Type t = new TypeBasic(basetab[i]);
547 t = merge(t);
548 basic[basetab[i]] = t;
550 basic[Terror] = new TypeError();
552 tnoreturn = new TypeNoreturn();
553 tnoreturn.deco = merge(tnoreturn).deco;
554 basic[Tnoreturn] = tnoreturn;
556 tvoid = basic[Tvoid];
557 tint8 = basic[Tint8];
558 tuns8 = basic[Tuns8];
559 tint16 = basic[Tint16];
560 tuns16 = basic[Tuns16];
561 tint32 = basic[Tint32];
562 tuns32 = basic[Tuns32];
563 tint64 = basic[Tint64];
564 tuns64 = basic[Tuns64];
565 tint128 = basic[Tint128];
566 tuns128 = basic[Tuns128];
567 tfloat32 = basic[Tfloat32];
568 tfloat64 = basic[Tfloat64];
569 tfloat80 = basic[Tfloat80];
571 timaginary32 = basic[Timaginary32];
572 timaginary64 = basic[Timaginary64];
573 timaginary80 = basic[Timaginary80];
575 tcomplex32 = basic[Tcomplex32];
576 tcomplex64 = basic[Tcomplex64];
577 tcomplex80 = basic[Tcomplex80];
579 tbool = basic[Tbool];
580 tchar = basic[Tchar];
581 twchar = basic[Twchar];
582 tdchar = basic[Tdchar];
584 tshiftcnt = tint32;
585 terror = basic[Terror];
586 tnoreturn = basic[Tnoreturn];
587 tnull = new TypeNull();
588 tnull.deco = merge(tnull).deco;
590 tvoidptr = tvoid.pointerTo();
591 tstring = tchar.immutableOf().arrayOf();
592 twstring = twchar.immutableOf().arrayOf();
593 tdstring = tdchar.immutableOf().arrayOf();
595 const isLP64 = target.isLP64;
597 tsize_t = basic[isLP64 ? Tuns64 : Tuns32];
598 tptrdiff_t = basic[isLP64 ? Tint64 : Tint32];
599 thash_t = tsize_t;
603 * Deinitializes the global state of the compiler.
605 * This can be used to restore the state set by `_init` to its original
606 * state.
608 static void deinitialize()
610 stringtable = stringtable.init;
613 final uinteger_t size()
615 return size(Loc.initial);
618 uinteger_t size(const ref Loc loc)
620 error(loc, "no size for type `%s`", toChars());
621 return SIZE_INVALID;
624 uint alignsize()
626 return cast(uint)size(Loc.initial);
629 /*********************************
630 * Store this type's modifier name into buf.
632 final void modToBuffer(ref OutBuffer buf) nothrow const
634 if (mod)
636 buf.writeByte(' ');
637 MODtoBuffer(buf, mod);
641 /*********************************
642 * Return this type's modifier name.
644 final char* modToChars() nothrow const
646 OutBuffer buf;
647 buf.reserve(16);
648 modToBuffer(buf);
649 return buf.extractChars();
652 bool isintegral()
654 return false;
657 // real, imaginary, or complex
658 bool isfloating()
660 return false;
663 bool isreal()
665 return false;
668 bool isimaginary()
670 return false;
673 bool iscomplex()
675 return false;
678 bool isscalar()
680 return false;
683 bool isunsigned()
685 return false;
688 bool isscope()
690 return false;
693 bool isString()
695 return false;
698 /**************************
699 * When T is mutable,
700 * Given:
701 * T a, b;
702 * Can we bitwise assign:
703 * a = b;
706 bool isAssignable()
708 return true;
711 /**************************
712 * Returns true if T can be converted to boolean value.
714 bool isBoolean()
716 return isscalar();
719 final bool isConst() const nothrow pure @nogc @safe
721 return (mod & MODFlags.const_) != 0;
724 final bool isImmutable() const nothrow pure @nogc @safe
726 return (mod & MODFlags.immutable_) != 0;
729 final bool isMutable() const nothrow pure @nogc @safe
731 return (mod & (MODFlags.const_ | MODFlags.immutable_ | MODFlags.wild)) == 0;
734 final bool isShared() const nothrow pure @nogc @safe
736 return (mod & MODFlags.shared_) != 0;
739 final bool isSharedConst() const nothrow pure @nogc @safe
741 return (mod & (MODFlags.shared_ | MODFlags.const_)) == (MODFlags.shared_ | MODFlags.const_);
744 final bool isWild() const nothrow pure @nogc @safe
746 return (mod & MODFlags.wild) != 0;
749 final bool isWildConst() const nothrow pure @nogc @safe
751 return (mod & MODFlags.wildconst) == MODFlags.wildconst;
754 final bool isSharedWild() const nothrow pure @nogc @safe
756 return (mod & (MODFlags.shared_ | MODFlags.wild)) == (MODFlags.shared_ | MODFlags.wild);
759 final bool isNaked() const nothrow pure @nogc @safe
761 return mod == 0;
764 /********************************
765 * Return a copy of this type with all attributes null-initialized.
766 * Useful for creating a type with different modifiers.
768 final Type nullAttributes() nothrow const
770 uint sz = sizeTy[ty];
771 Type t = cast(Type)mem.xmalloc(sz);
772 memcpy(cast(void*)t, cast(void*)this, sz);
773 // t.mod = NULL; // leave mod unchanged
774 t.deco = null;
775 t.arrayof = null;
776 t.pto = null;
777 t.rto = null;
778 t.vtinfo = null;
779 t.ctype = null;
780 t.mcache = null;
781 if (t.ty == Tstruct)
782 (cast(TypeStruct)t).att = AliasThisRec.fwdref;
783 if (t.ty == Tclass)
784 (cast(TypeClass)t).att = AliasThisRec.fwdref;
785 return t;
788 /**********************************
789 * For our new type 'this', which is type-constructed from t,
790 * fill in the cto, ito, sto, scto, wto shortcuts.
792 extern (D) final void fixTo(Type t)
794 // If fixing this: immutable(T*) by t: immutable(T)*,
795 // cache t to this.xto won't break transitivity.
796 Type mto = null;
797 Type tn = nextOf();
798 if (!tn || ty != Tsarray && tn.mod == t.nextOf().mod)
800 switch (t.mod)
802 case 0:
803 mto = t;
804 break;
806 case MODFlags.const_:
807 getMcache();
808 mcache.cto = t;
809 break;
811 case MODFlags.wild:
812 getMcache();
813 mcache.wto = t;
814 break;
816 case MODFlags.wildconst:
817 getMcache();
818 mcache.wcto = t;
819 break;
821 case MODFlags.shared_:
822 getMcache();
823 mcache.sto = t;
824 break;
826 case MODFlags.shared_ | MODFlags.const_:
827 getMcache();
828 mcache.scto = t;
829 break;
831 case MODFlags.shared_ | MODFlags.wild:
832 getMcache();
833 mcache.swto = t;
834 break;
836 case MODFlags.shared_ | MODFlags.wildconst:
837 getMcache();
838 mcache.swcto = t;
839 break;
841 case MODFlags.immutable_:
842 getMcache();
843 mcache.ito = t;
844 break;
846 default:
847 break;
850 assert(mod != t.mod);
852 if (mod)
854 getMcache();
855 t.getMcache();
857 switch (mod)
859 case 0:
860 break;
862 case MODFlags.const_:
863 mcache.cto = mto;
864 t.mcache.cto = this;
865 break;
867 case MODFlags.wild:
868 mcache.wto = mto;
869 t.mcache.wto = this;
870 break;
872 case MODFlags.wildconst:
873 mcache.wcto = mto;
874 t.mcache.wcto = this;
875 break;
877 case MODFlags.shared_:
878 mcache.sto = mto;
879 t.mcache.sto = this;
880 break;
882 case MODFlags.shared_ | MODFlags.const_:
883 mcache.scto = mto;
884 t.mcache.scto = this;
885 break;
887 case MODFlags.shared_ | MODFlags.wild:
888 mcache.swto = mto;
889 t.mcache.swto = this;
890 break;
892 case MODFlags.shared_ | MODFlags.wildconst:
893 mcache.swcto = mto;
894 t.mcache.swcto = this;
895 break;
897 case MODFlags.immutable_:
898 t.mcache.ito = this;
899 if (t.mcache.cto)
900 t.mcache.cto.getMcache().ito = this;
901 if (t.mcache.sto)
902 t.mcache.sto.getMcache().ito = this;
903 if (t.mcache.scto)
904 t.mcache.scto.getMcache().ito = this;
905 if (t.mcache.wto)
906 t.mcache.wto.getMcache().ito = this;
907 if (t.mcache.wcto)
908 t.mcache.wcto.getMcache().ito = this;
909 if (t.mcache.swto)
910 t.mcache.swto.getMcache().ito = this;
911 if (t.mcache.swcto)
912 t.mcache.swcto.getMcache().ito = this;
913 break;
915 default:
916 assert(0);
919 check();
920 t.check();
921 //printf("fixTo: %s, %s\n", toChars(), t.toChars());
924 /***************************
925 * Look for bugs in constructing types.
927 extern (D) final void check()
929 if (mcache)
930 with (mcache)
931 switch (mod)
933 case 0:
934 if (cto)
935 assert(cto.mod == MODFlags.const_);
936 if (ito)
937 assert(ito.mod == MODFlags.immutable_);
938 if (sto)
939 assert(sto.mod == MODFlags.shared_);
940 if (scto)
941 assert(scto.mod == (MODFlags.shared_ | MODFlags.const_));
942 if (wto)
943 assert(wto.mod == MODFlags.wild);
944 if (wcto)
945 assert(wcto.mod == MODFlags.wildconst);
946 if (swto)
947 assert(swto.mod == (MODFlags.shared_ | MODFlags.wild));
948 if (swcto)
949 assert(swcto.mod == (MODFlags.shared_ | MODFlags.wildconst));
950 break;
952 case MODFlags.const_:
953 if (cto)
954 assert(cto.mod == 0);
955 if (ito)
956 assert(ito.mod == MODFlags.immutable_);
957 if (sto)
958 assert(sto.mod == MODFlags.shared_);
959 if (scto)
960 assert(scto.mod == (MODFlags.shared_ | MODFlags.const_));
961 if (wto)
962 assert(wto.mod == MODFlags.wild);
963 if (wcto)
964 assert(wcto.mod == MODFlags.wildconst);
965 if (swto)
966 assert(swto.mod == (MODFlags.shared_ | MODFlags.wild));
967 if (swcto)
968 assert(swcto.mod == (MODFlags.shared_ | MODFlags.wildconst));
969 break;
971 case MODFlags.wild:
972 if (cto)
973 assert(cto.mod == MODFlags.const_);
974 if (ito)
975 assert(ito.mod == MODFlags.immutable_);
976 if (sto)
977 assert(sto.mod == MODFlags.shared_);
978 if (scto)
979 assert(scto.mod == (MODFlags.shared_ | MODFlags.const_));
980 if (wto)
981 assert(wto.mod == 0);
982 if (wcto)
983 assert(wcto.mod == MODFlags.wildconst);
984 if (swto)
985 assert(swto.mod == (MODFlags.shared_ | MODFlags.wild));
986 if (swcto)
987 assert(swcto.mod == (MODFlags.shared_ | MODFlags.wildconst));
988 break;
990 case MODFlags.wildconst:
991 assert(!cto || cto.mod == MODFlags.const_);
992 assert(!ito || ito.mod == MODFlags.immutable_);
993 assert(!sto || sto.mod == MODFlags.shared_);
994 assert(!scto || scto.mod == (MODFlags.shared_ | MODFlags.const_));
995 assert(!wto || wto.mod == MODFlags.wild);
996 assert(!wcto || wcto.mod == 0);
997 assert(!swto || swto.mod == (MODFlags.shared_ | MODFlags.wild));
998 assert(!swcto || swcto.mod == (MODFlags.shared_ | MODFlags.wildconst));
999 break;
1001 case MODFlags.shared_:
1002 if (cto)
1003 assert(cto.mod == MODFlags.const_);
1004 if (ito)
1005 assert(ito.mod == MODFlags.immutable_);
1006 if (sto)
1007 assert(sto.mod == 0);
1008 if (scto)
1009 assert(scto.mod == (MODFlags.shared_ | MODFlags.const_));
1010 if (wto)
1011 assert(wto.mod == MODFlags.wild);
1012 if (wcto)
1013 assert(wcto.mod == MODFlags.wildconst);
1014 if (swto)
1015 assert(swto.mod == (MODFlags.shared_ | MODFlags.wild));
1016 if (swcto)
1017 assert(swcto.mod == (MODFlags.shared_ | MODFlags.wildconst));
1018 break;
1020 case MODFlags.shared_ | MODFlags.const_:
1021 if (cto)
1022 assert(cto.mod == MODFlags.const_);
1023 if (ito)
1024 assert(ito.mod == MODFlags.immutable_);
1025 if (sto)
1026 assert(sto.mod == MODFlags.shared_);
1027 if (scto)
1028 assert(scto.mod == 0);
1029 if (wto)
1030 assert(wto.mod == MODFlags.wild);
1031 if (wcto)
1032 assert(wcto.mod == MODFlags.wildconst);
1033 if (swto)
1034 assert(swto.mod == (MODFlags.shared_ | MODFlags.wild));
1035 if (swcto)
1036 assert(swcto.mod == (MODFlags.shared_ | MODFlags.wildconst));
1037 break;
1039 case MODFlags.shared_ | MODFlags.wild:
1040 if (cto)
1041 assert(cto.mod == MODFlags.const_);
1042 if (ito)
1043 assert(ito.mod == MODFlags.immutable_);
1044 if (sto)
1045 assert(sto.mod == MODFlags.shared_);
1046 if (scto)
1047 assert(scto.mod == (MODFlags.shared_ | MODFlags.const_));
1048 if (wto)
1049 assert(wto.mod == MODFlags.wild);
1050 if (wcto)
1051 assert(wcto.mod == MODFlags.wildconst);
1052 if (swto)
1053 assert(swto.mod == 0);
1054 if (swcto)
1055 assert(swcto.mod == (MODFlags.shared_ | MODFlags.wildconst));
1056 break;
1058 case MODFlags.shared_ | MODFlags.wildconst:
1059 assert(!cto || cto.mod == MODFlags.const_);
1060 assert(!ito || ito.mod == MODFlags.immutable_);
1061 assert(!sto || sto.mod == MODFlags.shared_);
1062 assert(!scto || scto.mod == (MODFlags.shared_ | MODFlags.const_));
1063 assert(!wto || wto.mod == MODFlags.wild);
1064 assert(!wcto || wcto.mod == MODFlags.wildconst);
1065 assert(!swto || swto.mod == (MODFlags.shared_ | MODFlags.wild));
1066 assert(!swcto || swcto.mod == 0);
1067 break;
1069 case MODFlags.immutable_:
1070 if (cto)
1071 assert(cto.mod == MODFlags.const_);
1072 if (ito)
1073 assert(ito.mod == 0);
1074 if (sto)
1075 assert(sto.mod == MODFlags.shared_);
1076 if (scto)
1077 assert(scto.mod == (MODFlags.shared_ | MODFlags.const_));
1078 if (wto)
1079 assert(wto.mod == MODFlags.wild);
1080 if (wcto)
1081 assert(wcto.mod == MODFlags.wildconst);
1082 if (swto)
1083 assert(swto.mod == (MODFlags.shared_ | MODFlags.wild));
1084 if (swcto)
1085 assert(swcto.mod == (MODFlags.shared_ | MODFlags.wildconst));
1086 break;
1088 default:
1089 assert(0);
1092 Type tn = nextOf();
1093 if (tn && ty != Tfunction && tn.ty != Tfunction && ty != Tenum)
1095 // Verify transitivity
1096 switch (mod)
1098 case 0:
1099 case MODFlags.const_:
1100 case MODFlags.wild:
1101 case MODFlags.wildconst:
1102 case MODFlags.shared_:
1103 case MODFlags.shared_ | MODFlags.const_:
1104 case MODFlags.shared_ | MODFlags.wild:
1105 case MODFlags.shared_ | MODFlags.wildconst:
1106 case MODFlags.immutable_:
1107 assert(tn.mod == MODFlags.immutable_ || (tn.mod & mod) == mod);
1108 break;
1110 default:
1111 assert(0);
1113 tn.check();
1117 /*************************************
1118 * Apply STCxxxx bits to existing type.
1119 * Use *before* semantic analysis is run.
1121 extern (D) final Type addSTC(StorageClass stc)
1123 Type t = this;
1124 if (t.isImmutable())
1127 else if (stc & STC.immutable_)
1129 t = t.makeImmutable();
1131 else
1133 if ((stc & STC.shared_) && !t.isShared())
1135 if (t.isWild())
1137 if (t.isConst())
1138 t = t.makeSharedWildConst();
1139 else
1140 t = t.makeSharedWild();
1142 else
1144 if (t.isConst())
1145 t = t.makeSharedConst();
1146 else
1147 t = t.makeShared();
1150 if ((stc & STC.const_) && !t.isConst())
1152 if (t.isShared())
1154 if (t.isWild())
1155 t = t.makeSharedWildConst();
1156 else
1157 t = t.makeSharedConst();
1159 else
1161 if (t.isWild())
1162 t = t.makeWildConst();
1163 else
1164 t = t.makeConst();
1167 if ((stc & STC.wild) && !t.isWild())
1169 if (t.isShared())
1171 if (t.isConst())
1172 t = t.makeSharedWildConst();
1173 else
1174 t = t.makeSharedWild();
1176 else
1178 if (t.isConst())
1179 t = t.makeWildConst();
1180 else
1181 t = t.makeWild();
1185 return t;
1188 final bool hasDeprecatedAliasThis()
1190 auto ad = isAggregate(this);
1191 return ad && ad.aliasthis && (ad.aliasthis.isDeprecated || ad.aliasthis.sym.isDeprecated);
1194 Type makeConst()
1196 //printf("Type::makeConst() %p, %s\n", this, toChars());
1197 if (mcache && mcache.cto)
1198 return mcache.cto;
1199 Type t = this.nullAttributes();
1200 t.mod = MODFlags.const_;
1201 //printf("-Type::makeConst() %p, %s\n", t, toChars());
1202 return t;
1205 Type makeImmutable()
1207 if (mcache && mcache.ito)
1208 return mcache.ito;
1209 Type t = this.nullAttributes();
1210 t.mod = MODFlags.immutable_;
1211 return t;
1214 Type makeShared()
1216 if (mcache && mcache.sto)
1217 return mcache.sto;
1218 Type t = this.nullAttributes();
1219 t.mod = MODFlags.shared_;
1220 return t;
1223 Type makeSharedConst()
1225 if (mcache && mcache.scto)
1226 return mcache.scto;
1227 Type t = this.nullAttributes();
1228 t.mod = MODFlags.shared_ | MODFlags.const_;
1229 return t;
1232 Type makeWild()
1234 if (mcache && mcache.wto)
1235 return mcache.wto;
1236 Type t = this.nullAttributes();
1237 t.mod = MODFlags.wild;
1238 return t;
1241 Type makeWildConst()
1243 if (mcache && mcache.wcto)
1244 return mcache.wcto;
1245 Type t = this.nullAttributes();
1246 t.mod = MODFlags.wildconst;
1247 return t;
1250 Type makeSharedWild()
1252 if (mcache && mcache.swto)
1253 return mcache.swto;
1254 Type t = this.nullAttributes();
1255 t.mod = MODFlags.shared_ | MODFlags.wild;
1256 return t;
1259 Type makeSharedWildConst()
1261 if (mcache && mcache.swcto)
1262 return mcache.swcto;
1263 Type t = this.nullAttributes();
1264 t.mod = MODFlags.shared_ | MODFlags.wildconst;
1265 return t;
1268 Type makeMutable()
1270 Type t = this.nullAttributes();
1271 t.mod = mod & MODFlags.shared_;
1272 return t;
1275 /*******************************
1276 * If this is a shell around another type,
1277 * get that other type.
1279 final Type toBasetype()
1281 /* This function is used heavily.
1282 * De-virtualize it so it can be easily inlined.
1284 TypeEnum te;
1285 return ((te = isTypeEnum()) !is null) ? te.toBasetype2() : this;
1288 /********************************
1289 * Determine if 'this' can be implicitly converted
1290 * to type 'to'.
1291 * Returns:
1292 * MATCH.nomatch, MATCH.convert, MATCH.constant, MATCH.exact
1294 MATCH implicitConvTo(Type to)
1296 //printf("Type::implicitConvTo(this=%p, to=%p)\n", this, to);
1297 //printf("from: %s\n", toChars());
1298 //printf("to : %s\n", to.toChars());
1299 if (this.equals(to))
1300 return MATCH.exact;
1301 return MATCH.nomatch;
1304 /*******************************
1305 * Determine if converting 'this' to 'to' is an identity operation,
1306 * a conversion to const operation, or the types aren't the same.
1307 * Returns:
1308 * MATCH.exact 'this' == 'to'
1309 * MATCH.constant 'to' is const
1310 * MATCH.nomatch conversion to mutable or invariant
1312 MATCH constConv(Type to)
1314 //printf("Type::constConv(this = %s, to = %s)\n", toChars(), to.toChars());
1315 if (equals(to))
1316 return MATCH.exact;
1317 if (ty == to.ty && MODimplicitConv(mod, to.mod))
1318 return MATCH.constant;
1319 return MATCH.nomatch;
1322 /***************************************
1323 * Compute MOD bits matching `this` argument type to wild parameter type.
1324 * Params:
1325 * t = corresponding parameter type
1326 * isRef = parameter is `ref` or `out`
1327 * Returns:
1328 * MOD bits
1330 MOD deduceWild(Type t, bool isRef)
1332 //printf("Type::deduceWild this = '%s', tprm = '%s'\n", toChars(), tprm.toChars());
1333 if (t.isWild())
1335 if (isImmutable())
1336 return MODFlags.immutable_;
1337 else if (isWildConst())
1339 if (t.isWildConst())
1340 return MODFlags.wild;
1341 else
1342 return MODFlags.wildconst;
1344 else if (isWild())
1345 return MODFlags.wild;
1346 else if (isConst())
1347 return MODFlags.const_;
1348 else if (isMutable())
1349 return MODFlags.mutable;
1350 else
1351 assert(0);
1353 return 0;
1356 inout(ClassDeclaration) isClassHandle() inout
1358 return null;
1361 /************************************
1362 * Return alignment to use for this type.
1364 structalign_t alignment()
1366 structalign_t s;
1367 s.setDefault();
1368 return s;
1371 /***************************************
1372 * Use when we prefer the default initializer to be a literal,
1373 * rather than a global immutable variable.
1375 Expression defaultInitLiteral(const ref Loc loc)
1377 static if (LOGDEFAULTINIT)
1379 printf("Type::defaultInitLiteral() '%s'\n", toChars());
1381 return defaultInit(this, loc);
1384 // if initializer is 0
1385 bool isZeroInit(const ref Loc loc)
1387 return false; // assume not
1390 /***************************************
1391 * Return !=0 if the type or any of its subtypes is wild.
1393 int hasWild() const
1395 return mod & MODFlags.wild;
1398 /*************************************
1399 * Detect if type has pointer fields that are initialized to void.
1400 * Local stack variables with such void fields can remain uninitialized,
1401 * leading to pointer bugs.
1402 * Returns:
1403 * true if so
1405 bool hasVoidInitPointers()
1407 return false;
1410 /*************************************
1411 * Detect if this is an unsafe type because of the presence of `@system` members
1412 * Returns:
1413 * true if so
1415 bool hasSystemFields()
1417 return false;
1420 /***************************************
1421 * Returns: true if type has any invariants
1423 bool hasInvariant()
1425 //printf("Type::hasInvariant() %s, %d\n", toChars(), ty);
1426 return false;
1429 /*************************************
1430 * If this is a type of something, return that something.
1432 Type nextOf()
1434 return null;
1437 /*************************************
1438 * If this is a type of static array, return its base element type.
1440 final Type baseElemOf()
1442 Type t = toBasetype();
1443 TypeSArray tsa;
1444 while ((tsa = t.isTypeSArray()) !is null)
1445 t = tsa.next.toBasetype();
1446 return t;
1449 /*******************************************
1450 * Compute number of elements for a (possibly multidimensional) static array,
1451 * or 1 for other types.
1452 * Params:
1453 * loc = for error message
1454 * Returns:
1455 * number of elements, uint.max on overflow
1457 final uint numberOfElems(const ref Loc loc)
1459 //printf("Type::numberOfElems()\n");
1460 uinteger_t n = 1;
1461 Type tb = this;
1462 while ((tb = tb.toBasetype()).ty == Tsarray)
1464 bool overflow = false;
1465 n = mulu(n, (cast(TypeSArray)tb).dim.toUInteger(), overflow);
1466 if (overflow || n >= uint.max)
1468 error(loc, "static array `%s` size overflowed to %llu", toChars(), cast(ulong)n);
1469 return uint.max;
1471 tb = (cast(TypeSArray)tb).next;
1473 return cast(uint)n;
1476 /****************************************
1477 * Return the mask that an integral type will
1478 * fit into.
1480 extern (D) final uinteger_t sizemask()
1482 uinteger_t m;
1483 switch (toBasetype().ty)
1485 case Tbool:
1486 m = 1;
1487 break;
1488 case Tchar:
1489 case Tint8:
1490 case Tuns8:
1491 m = 0xFF;
1492 break;
1493 case Twchar:
1494 case Tint16:
1495 case Tuns16:
1496 m = 0xFFFFU;
1497 break;
1498 case Tdchar:
1499 case Tint32:
1500 case Tuns32:
1501 m = 0xFFFFFFFFU;
1502 break;
1503 case Tint64:
1504 case Tuns64:
1505 m = 0xFFFFFFFFFFFFFFFFUL;
1506 break;
1507 default:
1508 assert(0);
1510 return m;
1513 /********************************
1514 * true if when type goes out of scope, it needs a destructor applied.
1515 * Only applies to value types, not ref types.
1517 bool needsDestruction()
1519 return false;
1522 /********************************
1523 * true if when type is copied, it needs a copy constructor or postblit
1524 * applied. Only applies to value types, not ref types.
1526 bool needsCopyOrPostblit()
1528 return false;
1531 /*********************************
1534 bool needsNested()
1536 return false;
1539 // For eliminating dynamic_cast
1540 TypeBasic isTypeBasic()
1542 return null;
1545 final pure inout nothrow @nogc
1547 /****************
1548 * Is this type a pointer to a function?
1549 * Returns:
1550 * the function type if it is
1552 inout(TypeFunction) isPtrToFunction()
1554 return (ty == Tpointer && (cast(TypePointer)this).next.ty == Tfunction)
1555 ? cast(typeof(return))(cast(TypePointer)this).next
1556 : null;
1559 /*****************
1560 * Is this type a function, delegate, or pointer to a function?
1561 * Returns:
1562 * the function type if it is
1564 inout(TypeFunction) isFunction_Delegate_PtrToFunction()
1566 return ty == Tfunction ? cast(typeof(return))this :
1568 ty == Tdelegate ? cast(typeof(return))(cast(TypePointer)this).next :
1570 ty == Tpointer && (cast(TypePointer)this).next.ty == Tfunction ?
1571 cast(typeof(return))(cast(TypePointer)this).next :
1573 null;
1577 final pure inout nothrow @nogc @safe
1579 inout(TypeError) isTypeError() { return ty == Terror ? cast(typeof(return))this : null; }
1580 inout(TypeVector) isTypeVector() { return ty == Tvector ? cast(typeof(return))this : null; }
1581 inout(TypeSArray) isTypeSArray() { return ty == Tsarray ? cast(typeof(return))this : null; }
1582 inout(TypeDArray) isTypeDArray() { return ty == Tarray ? cast(typeof(return))this : null; }
1583 inout(TypeAArray) isTypeAArray() { return ty == Taarray ? cast(typeof(return))this : null; }
1584 inout(TypePointer) isTypePointer() { return ty == Tpointer ? cast(typeof(return))this : null; }
1585 inout(TypeReference) isTypeReference() { return ty == Treference ? cast(typeof(return))this : null; }
1586 inout(TypeFunction) isTypeFunction() { return ty == Tfunction ? cast(typeof(return))this : null; }
1587 inout(TypeDelegate) isTypeDelegate() { return ty == Tdelegate ? cast(typeof(return))this : null; }
1588 inout(TypeIdentifier) isTypeIdentifier() { return ty == Tident ? cast(typeof(return))this : null; }
1589 inout(TypeInstance) isTypeInstance() { return ty == Tinstance ? cast(typeof(return))this : null; }
1590 inout(TypeTypeof) isTypeTypeof() { return ty == Ttypeof ? cast(typeof(return))this : null; }
1591 inout(TypeReturn) isTypeReturn() { return ty == Treturn ? cast(typeof(return))this : null; }
1592 inout(TypeStruct) isTypeStruct() { return ty == Tstruct ? cast(typeof(return))this : null; }
1593 inout(TypeEnum) isTypeEnum() { return ty == Tenum ? cast(typeof(return))this : null; }
1594 inout(TypeClass) isTypeClass() { return ty == Tclass ? cast(typeof(return))this : null; }
1595 inout(TypeTuple) isTypeTuple() { return ty == Ttuple ? cast(typeof(return))this : null; }
1596 inout(TypeSlice) isTypeSlice() { return ty == Tslice ? cast(typeof(return))this : null; }
1597 inout(TypeNull) isTypeNull() { return ty == Tnull ? cast(typeof(return))this : null; }
1598 inout(TypeMixin) isTypeMixin() { return ty == Tmixin ? cast(typeof(return))this : null; }
1599 inout(TypeTraits) isTypeTraits() { return ty == Ttraits ? cast(typeof(return))this : null; }
1600 inout(TypeNoreturn) isTypeNoreturn() { return ty == Tnoreturn ? cast(typeof(return))this : null; }
1601 inout(TypeTag) isTypeTag() { return ty == Ttag ? cast(typeof(return))this : null; }
1604 override void accept(Visitor v)
1606 v.visit(this);
1609 final TypeFunction toTypeFunction()
1611 if (ty != Tfunction)
1612 assert(0);
1613 return cast(TypeFunction)this;
1616 extern (D) static Types* arraySyntaxCopy(Types* types)
1618 Types* a = null;
1619 if (types)
1621 a = new Types(types.length);
1622 foreach (i, t; *types)
1624 (*a)[i] = t ? t.syntaxCopy() : null;
1627 return a;
1631 /***********************************************************
1633 extern (C++) final class TypeError : Type
1635 extern (D) this() @safe
1637 super(Terror);
1640 override const(char)* kind() const
1642 return "error";
1645 override TypeError syntaxCopy()
1647 // No semantic analysis done, no need to copy
1648 return this;
1651 override uinteger_t size(const ref Loc loc)
1653 return SIZE_INVALID;
1656 override Expression defaultInitLiteral(const ref Loc loc)
1658 return ErrorExp.get();
1661 override void accept(Visitor v)
1663 v.visit(this);
1667 /***********************************************************
1669 extern (C++) abstract class TypeNext : Type
1671 Type next;
1673 final extern (D) this(TY ty, Type next) @safe
1675 super(ty);
1676 this.next = next;
1679 override final int hasWild() const
1681 if (ty == Tfunction)
1682 return 0;
1683 if (ty == Tdelegate)
1684 return Type.hasWild();
1685 return mod & MODFlags.wild || (next && next.hasWild());
1688 /*******************************
1689 * For TypeFunction, nextOf() can return NULL if the function return
1690 * type is meant to be inferred, and semantic() hasn't yet ben run
1691 * on the function. After semantic(), it must no longer be NULL.
1693 override final Type nextOf()
1695 return next;
1698 override final Type makeConst()
1700 //printf("TypeNext::makeConst() %p, %s\n", this, toChars());
1701 if (mcache && mcache.cto)
1703 assert(mcache.cto.mod == MODFlags.const_);
1704 return mcache.cto;
1706 TypeNext t = cast(TypeNext)Type.makeConst();
1707 if (ty != Tfunction && next.ty != Tfunction && !next.isImmutable())
1709 if (next.isShared())
1711 if (next.isWild())
1712 t.next = next.sharedWildConstOf();
1713 else
1714 t.next = next.sharedConstOf();
1716 else
1718 if (next.isWild())
1719 t.next = next.wildConstOf();
1720 else
1721 t.next = next.constOf();
1724 //printf("TypeNext::makeConst() returns %p, %s\n", t, t.toChars());
1725 return t;
1728 override final Type makeImmutable()
1730 //printf("TypeNext::makeImmutable() %s\n", toChars());
1731 if (mcache && mcache.ito)
1733 assert(mcache.ito.isImmutable());
1734 return mcache.ito;
1736 TypeNext t = cast(TypeNext)Type.makeImmutable();
1737 if (ty != Tfunction && next.ty != Tfunction && !next.isImmutable())
1739 t.next = next.immutableOf();
1741 return t;
1744 override final Type makeShared()
1746 //printf("TypeNext::makeShared() %s\n", toChars());
1747 if (mcache && mcache.sto)
1749 assert(mcache.sto.mod == MODFlags.shared_);
1750 return mcache.sto;
1752 TypeNext t = cast(TypeNext)Type.makeShared();
1753 if (ty != Tfunction && next.ty != Tfunction && !next.isImmutable())
1755 if (next.isWild())
1757 if (next.isConst())
1758 t.next = next.sharedWildConstOf();
1759 else
1760 t.next = next.sharedWildOf();
1762 else
1764 if (next.isConst())
1765 t.next = next.sharedConstOf();
1766 else
1767 t.next = next.sharedOf();
1770 //printf("TypeNext::makeShared() returns %p, %s\n", t, t.toChars());
1771 return t;
1774 override final Type makeSharedConst()
1776 //printf("TypeNext::makeSharedConst() %s\n", toChars());
1777 if (mcache && mcache.scto)
1779 assert(mcache.scto.mod == (MODFlags.shared_ | MODFlags.const_));
1780 return mcache.scto;
1782 TypeNext t = cast(TypeNext)Type.makeSharedConst();
1783 if (ty != Tfunction && next.ty != Tfunction && !next.isImmutable())
1785 if (next.isWild())
1786 t.next = next.sharedWildConstOf();
1787 else
1788 t.next = next.sharedConstOf();
1790 //printf("TypeNext::makeSharedConst() returns %p, %s\n", t, t.toChars());
1791 return t;
1794 override final Type makeWild()
1796 //printf("TypeNext::makeWild() %s\n", toChars());
1797 if (mcache && mcache.wto)
1799 assert(mcache.wto.mod == MODFlags.wild);
1800 return mcache.wto;
1802 TypeNext t = cast(TypeNext)Type.makeWild();
1803 if (ty != Tfunction && next.ty != Tfunction && !next.isImmutable())
1805 if (next.isShared())
1807 if (next.isConst())
1808 t.next = next.sharedWildConstOf();
1809 else
1810 t.next = next.sharedWildOf();
1812 else
1814 if (next.isConst())
1815 t.next = next.wildConstOf();
1816 else
1817 t.next = next.wildOf();
1820 //printf("TypeNext::makeWild() returns %p, %s\n", t, t.toChars());
1821 return t;
1824 override final Type makeWildConst()
1826 //printf("TypeNext::makeWildConst() %s\n", toChars());
1827 if (mcache && mcache.wcto)
1829 assert(mcache.wcto.mod == MODFlags.wildconst);
1830 return mcache.wcto;
1832 TypeNext t = cast(TypeNext)Type.makeWildConst();
1833 if (ty != Tfunction && next.ty != Tfunction && !next.isImmutable())
1835 if (next.isShared())
1836 t.next = next.sharedWildConstOf();
1837 else
1838 t.next = next.wildConstOf();
1840 //printf("TypeNext::makeWildConst() returns %p, %s\n", t, t.toChars());
1841 return t;
1844 override final Type makeSharedWild()
1846 //printf("TypeNext::makeSharedWild() %s\n", toChars());
1847 if (mcache && mcache.swto)
1849 assert(mcache.swto.isSharedWild());
1850 return mcache.swto;
1852 TypeNext t = cast(TypeNext)Type.makeSharedWild();
1853 if (ty != Tfunction && next.ty != Tfunction && !next.isImmutable())
1855 if (next.isConst())
1856 t.next = next.sharedWildConstOf();
1857 else
1858 t.next = next.sharedWildOf();
1860 //printf("TypeNext::makeSharedWild() returns %p, %s\n", t, t.toChars());
1861 return t;
1864 override final Type makeSharedWildConst()
1866 //printf("TypeNext::makeSharedWildConst() %s\n", toChars());
1867 if (mcache && mcache.swcto)
1869 assert(mcache.swcto.mod == (MODFlags.shared_ | MODFlags.wildconst));
1870 return mcache.swcto;
1872 TypeNext t = cast(TypeNext)Type.makeSharedWildConst();
1873 if (ty != Tfunction && next.ty != Tfunction && !next.isImmutable())
1875 t.next = next.sharedWildConstOf();
1877 //printf("TypeNext::makeSharedWildConst() returns %p, %s\n", t, t.toChars());
1878 return t;
1881 override final Type makeMutable()
1883 //printf("TypeNext::makeMutable() %p, %s\n", this, toChars());
1884 TypeNext t = cast(TypeNext)Type.makeMutable();
1885 if (ty == Tsarray)
1887 t.next = next.mutableOf();
1889 //printf("TypeNext::makeMutable() returns %p, %s\n", t, t.toChars());
1890 return t;
1893 override MATCH constConv(Type to)
1895 //printf("TypeNext::constConv from = %s, to = %s\n", toChars(), to.toChars());
1896 if (equals(to))
1897 return MATCH.exact;
1899 if (!(ty == to.ty && MODimplicitConv(mod, to.mod)))
1900 return MATCH.nomatch;
1902 Type tn = to.nextOf();
1903 if (!(tn && next.ty == tn.ty))
1904 return MATCH.nomatch;
1906 MATCH m;
1907 if (to.isConst()) // whole tail const conversion
1909 // Recursive shared level check
1910 m = next.constConv(tn);
1911 if (m == MATCH.exact)
1912 m = MATCH.constant;
1914 else
1916 //printf("\tnext => %s, to.next => %s\n", next.toChars(), tn.toChars());
1917 m = next.equals(tn) ? MATCH.constant : MATCH.nomatch;
1919 return m;
1922 override final MOD deduceWild(Type t, bool isRef)
1924 if (ty == Tfunction)
1925 return 0;
1927 ubyte wm;
1929 Type tn = t.nextOf();
1930 if (!isRef && (ty == Tarray || ty == Tpointer) && tn)
1932 wm = next.deduceWild(tn, true);
1933 if (!wm)
1934 wm = Type.deduceWild(t, true);
1936 else
1938 wm = Type.deduceWild(t, isRef);
1939 if (!wm && tn)
1940 wm = next.deduceWild(tn, true);
1943 return wm;
1946 final void transitive()
1948 /* Invoke transitivity of type attributes
1950 next = next.addMod(mod);
1953 override void accept(Visitor v)
1955 v.visit(this);
1959 /***********************************************************
1961 extern (C++) final class TypeBasic : Type
1963 const(char)* dstring;
1964 uint flags;
1966 extern (D) this(TY ty) scope
1968 super(ty);
1969 const(char)* d;
1970 uint flags = 0;
1971 switch (ty)
1973 case Tvoid:
1974 d = Token.toChars(TOK.void_);
1975 break;
1977 case Tint8:
1978 d = Token.toChars(TOK.int8);
1979 flags |= TFlags.integral;
1980 break;
1982 case Tuns8:
1983 d = Token.toChars(TOK.uns8);
1984 flags |= TFlags.integral | TFlags.unsigned;
1985 break;
1987 case Tint16:
1988 d = Token.toChars(TOK.int16);
1989 flags |= TFlags.integral;
1990 break;
1992 case Tuns16:
1993 d = Token.toChars(TOK.uns16);
1994 flags |= TFlags.integral | TFlags.unsigned;
1995 break;
1997 case Tint32:
1998 d = Token.toChars(TOK.int32);
1999 flags |= TFlags.integral;
2000 break;
2002 case Tuns32:
2003 d = Token.toChars(TOK.uns32);
2004 flags |= TFlags.integral | TFlags.unsigned;
2005 break;
2007 case Tfloat32:
2008 d = Token.toChars(TOK.float32);
2009 flags |= TFlags.floating | TFlags.real_;
2010 break;
2012 case Tint64:
2013 d = Token.toChars(TOK.int64);
2014 flags |= TFlags.integral;
2015 break;
2017 case Tuns64:
2018 d = Token.toChars(TOK.uns64);
2019 flags |= TFlags.integral | TFlags.unsigned;
2020 break;
2022 case Tint128:
2023 d = Token.toChars(TOK.int128);
2024 flags |= TFlags.integral;
2025 break;
2027 case Tuns128:
2028 d = Token.toChars(TOK.uns128);
2029 flags |= TFlags.integral | TFlags.unsigned;
2030 break;
2032 case Tfloat64:
2033 d = Token.toChars(TOK.float64);
2034 flags |= TFlags.floating | TFlags.real_;
2035 break;
2037 case Tfloat80:
2038 d = Token.toChars(TOK.float80);
2039 flags |= TFlags.floating | TFlags.real_;
2040 break;
2042 case Timaginary32:
2043 d = Token.toChars(TOK.imaginary32);
2044 flags |= TFlags.floating | TFlags.imaginary;
2045 break;
2047 case Timaginary64:
2048 d = Token.toChars(TOK.imaginary64);
2049 flags |= TFlags.floating | TFlags.imaginary;
2050 break;
2052 case Timaginary80:
2053 d = Token.toChars(TOK.imaginary80);
2054 flags |= TFlags.floating | TFlags.imaginary;
2055 break;
2057 case Tcomplex32:
2058 d = Token.toChars(TOK.complex32);
2059 flags |= TFlags.floating | TFlags.complex;
2060 break;
2062 case Tcomplex64:
2063 d = Token.toChars(TOK.complex64);
2064 flags |= TFlags.floating | TFlags.complex;
2065 break;
2067 case Tcomplex80:
2068 d = Token.toChars(TOK.complex80);
2069 flags |= TFlags.floating | TFlags.complex;
2070 break;
2072 case Tbool:
2073 d = "bool";
2074 flags |= TFlags.integral | TFlags.unsigned;
2075 break;
2077 case Tchar:
2078 d = Token.toChars(TOK.char_);
2079 flags |= TFlags.integral | TFlags.unsigned;
2080 break;
2082 case Twchar:
2083 d = Token.toChars(TOK.wchar_);
2084 flags |= TFlags.integral | TFlags.unsigned;
2085 break;
2087 case Tdchar:
2088 d = Token.toChars(TOK.dchar_);
2089 flags |= TFlags.integral | TFlags.unsigned;
2090 break;
2092 default:
2093 assert(0);
2095 this.dstring = d;
2096 this.flags = flags;
2097 merge(this);
2100 override const(char)* kind() const
2102 return dstring;
2105 override TypeBasic syntaxCopy()
2107 // No semantic analysis done on basic types, no need to copy
2108 return this;
2111 override uinteger_t size(const ref Loc loc)
2113 uint size;
2114 //printf("TypeBasic::size()\n");
2115 switch (ty)
2117 case Tint8:
2118 case Tuns8:
2119 size = 1;
2120 break;
2122 case Tint16:
2123 case Tuns16:
2124 size = 2;
2125 break;
2127 case Tint32:
2128 case Tuns32:
2129 case Tfloat32:
2130 case Timaginary32:
2131 size = 4;
2132 break;
2134 case Tint64:
2135 case Tuns64:
2136 case Tfloat64:
2137 case Timaginary64:
2138 size = 8;
2139 break;
2141 case Tfloat80:
2142 case Timaginary80:
2143 size = target.realsize;
2144 break;
2146 case Tcomplex32:
2147 size = 8;
2148 break;
2150 case Tcomplex64:
2151 case Tint128:
2152 case Tuns128:
2153 size = 16;
2154 break;
2156 case Tcomplex80:
2157 size = target.realsize * 2;
2158 break;
2160 case Tvoid:
2161 //size = Type::size(); // error message
2162 size = 1;
2163 break;
2165 case Tbool:
2166 size = 1;
2167 break;
2169 case Tchar:
2170 size = 1;
2171 break;
2173 case Twchar:
2174 size = 2;
2175 break;
2177 case Tdchar:
2178 size = 4;
2179 break;
2181 default:
2182 assert(0);
2184 //printf("TypeBasic::size() = %d\n", size);
2185 return size;
2188 override uint alignsize()
2190 return target.alignsize(this);
2193 override bool isintegral()
2195 //printf("TypeBasic::isintegral('%s') x%x\n", toChars(), flags);
2196 return (flags & TFlags.integral) != 0;
2199 override bool isfloating()
2201 return (flags & TFlags.floating) != 0;
2204 override bool isreal()
2206 return (flags & TFlags.real_) != 0;
2209 override bool isimaginary()
2211 return (flags & TFlags.imaginary) != 0;
2214 override bool iscomplex()
2216 return (flags & TFlags.complex) != 0;
2219 override bool isscalar()
2221 return (flags & (TFlags.integral | TFlags.floating)) != 0;
2224 override bool isunsigned()
2226 return (flags & TFlags.unsigned) != 0;
2229 override MATCH implicitConvTo(Type to)
2231 //printf("TypeBasic::implicitConvTo(%s) from %s\n", to.toChars(), toChars());
2232 if (this == to)
2233 return MATCH.exact;
2235 if (ty == to.ty)
2237 if (mod == to.mod)
2238 return MATCH.exact;
2239 else if (MODimplicitConv(mod, to.mod))
2240 return MATCH.constant;
2241 else if (!((mod ^ to.mod) & MODFlags.shared_)) // for wild matching
2242 return MATCH.constant;
2243 else
2244 return MATCH.convert;
2247 if (ty == Tvoid || to.ty == Tvoid)
2248 return MATCH.nomatch;
2249 if (to.ty == Tbool)
2250 return MATCH.nomatch;
2252 TypeBasic tob;
2253 if (to.ty == Tvector && to.deco)
2255 TypeVector tv = cast(TypeVector)to;
2256 tob = tv.elementType();
2258 else if (auto te = to.isTypeEnum())
2260 EnumDeclaration ed = te.sym;
2261 if (ed.isSpecial())
2263 /* Special enums that allow implicit conversions to them
2264 * with a MATCH.convert
2266 tob = to.toBasetype().isTypeBasic();
2268 else
2269 return MATCH.nomatch;
2271 else
2272 tob = to.isTypeBasic();
2273 if (!tob)
2274 return MATCH.nomatch;
2276 if (flags & TFlags.integral)
2278 // Disallow implicit conversion of integers to imaginary or complex
2279 if (tob.flags & (TFlags.imaginary | TFlags.complex))
2280 return MATCH.nomatch;
2282 // If converting from integral to integral
2283 if (tob.flags & TFlags.integral)
2285 const sz = size(Loc.initial);
2286 const tosz = tob.size(Loc.initial);
2288 /* Can't convert to smaller size
2290 if (sz > tosz)
2291 return MATCH.nomatch;
2292 /* Can't change sign if same size
2294 //if (sz == tosz && (flags ^ tob.flags) & TFlags.unsigned)
2295 // return MATCH.nomatch;
2298 else if (flags & TFlags.floating)
2300 // Disallow implicit conversion of floating point to integer
2301 if (tob.flags & TFlags.integral)
2302 return MATCH.nomatch;
2304 assert(tob.flags & TFlags.floating || to.ty == Tvector);
2306 // Disallow implicit conversion from complex to non-complex
2307 if (flags & TFlags.complex && !(tob.flags & TFlags.complex))
2308 return MATCH.nomatch;
2310 // Disallow implicit conversion of real or imaginary to complex
2311 if (flags & (TFlags.real_ | TFlags.imaginary) && tob.flags & TFlags.complex)
2312 return MATCH.nomatch;
2314 // Disallow implicit conversion to-from real and imaginary
2315 if ((flags & (TFlags.real_ | TFlags.imaginary)) != (tob.flags & (TFlags.real_ | TFlags.imaginary)))
2316 return MATCH.nomatch;
2318 return MATCH.convert;
2321 override bool isZeroInit(const ref Loc loc)
2323 switch (ty)
2325 case Tchar:
2326 case Twchar:
2327 case Tdchar:
2328 case Timaginary32:
2329 case Timaginary64:
2330 case Timaginary80:
2331 case Tfloat32:
2332 case Tfloat64:
2333 case Tfloat80:
2334 case Tcomplex32:
2335 case Tcomplex64:
2336 case Tcomplex80:
2337 return false; // no
2338 default:
2339 return true; // yes
2343 // For eliminating dynamic_cast
2344 override TypeBasic isTypeBasic()
2346 return this;
2349 override void accept(Visitor v)
2351 v.visit(this);
2355 /***********************************************************
2356 * The basetype must be one of:
2357 * byte[16],ubyte[16],short[8],ushort[8],int[4],uint[4],long[2],ulong[2],float[4],double[2]
2358 * For AVX:
2359 * byte[32],ubyte[32],short[16],ushort[16],int[8],uint[8],long[4],ulong[4],float[8],double[4]
2361 extern (C++) final class TypeVector : Type
2363 Type basetype;
2365 extern (D) this(Type basetype) @safe
2367 super(Tvector);
2368 this.basetype = basetype;
2371 static TypeVector create(Type basetype) @safe
2373 return new TypeVector(basetype);
2376 override const(char)* kind() const
2378 return "vector";
2381 override TypeVector syntaxCopy()
2383 return new TypeVector(basetype.syntaxCopy());
2386 override uinteger_t size(const ref Loc loc)
2388 return basetype.size();
2391 override uint alignsize()
2393 return cast(uint)basetype.size();
2396 override bool isintegral()
2398 //printf("TypeVector::isintegral('%s') x%x\n", toChars(), flags);
2399 return basetype.nextOf().isintegral();
2402 override bool isfloating()
2404 return basetype.nextOf().isfloating();
2407 override bool isscalar()
2409 return basetype.nextOf().isscalar();
2412 override bool isunsigned()
2414 return basetype.nextOf().isunsigned();
2417 override bool isBoolean()
2419 return false;
2422 override MATCH implicitConvTo(Type to)
2424 //printf("TypeVector::implicitConvTo(%s) from %s\n", to.toChars(), toChars());
2425 if (this == to)
2426 return MATCH.exact;
2427 if (to.ty != Tvector)
2428 return MATCH.nomatch;
2430 TypeVector tv = cast(TypeVector)to;
2431 assert(basetype.ty == Tsarray && tv.basetype.ty == Tsarray);
2433 // Can't convert to a vector which has different size.
2434 if (basetype.size() != tv.basetype.size())
2435 return MATCH.nomatch;
2437 // Allow conversion to void[]
2438 if (tv.basetype.nextOf().ty == Tvoid)
2439 return MATCH.convert;
2441 // Otherwise implicitly convertible only if basetypes are.
2442 return basetype.implicitConvTo(tv.basetype);
2445 override Expression defaultInitLiteral(const ref Loc loc)
2447 //printf("TypeVector::defaultInitLiteral()\n");
2448 assert(basetype.ty == Tsarray);
2449 Expression e = basetype.defaultInitLiteral(loc);
2450 auto ve = new VectorExp(loc, e, this);
2451 ve.type = this;
2452 ve.dim = cast(int)(basetype.size(loc) / elementType().size(loc));
2453 return ve;
2456 TypeBasic elementType()
2458 assert(basetype.ty == Tsarray);
2459 TypeSArray t = cast(TypeSArray)basetype;
2460 TypeBasic tb = t.nextOf().isTypeBasic();
2461 assert(tb);
2462 return tb;
2465 override bool isZeroInit(const ref Loc loc)
2467 return basetype.isZeroInit(loc);
2470 override void accept(Visitor v)
2472 v.visit(this);
2476 /***********************************************************
2478 extern (C++) abstract class TypeArray : TypeNext
2480 final extern (D) this(TY ty, Type next) @safe
2482 super(ty, next);
2485 override void accept(Visitor v)
2487 v.visit(this);
2491 /***********************************************************
2492 * Static array, one with a fixed dimension
2494 extern (C++) final class TypeSArray : TypeArray
2496 Expression dim;
2498 extern (D) this(Type t, Expression dim) @safe
2500 super(Tsarray, t);
2501 //printf("TypeSArray(%s)\n", dim.toChars());
2502 this.dim = dim;
2505 extern (D) this(Type t) // for incomplete type
2507 super(Tsarray, t);
2508 //printf("TypeSArray()\n");
2509 this.dim = new IntegerExp(0);
2512 override const(char)* kind() const
2514 return "sarray";
2517 override TypeSArray syntaxCopy()
2519 Type t = next.syntaxCopy();
2520 Expression e = dim.syntaxCopy();
2521 auto result = new TypeSArray(t, e);
2522 result.mod = mod;
2523 return result;
2526 /***
2527 * C11 6.7.6.2-4 incomplete array type
2528 * Returns: true if incomplete type
2530 bool isIncomplete()
2532 return dim.isIntegerExp() && dim.isIntegerExp().getInteger() == 0;
2535 override uinteger_t size(const ref Loc loc)
2537 //printf("TypeSArray::size()\n");
2538 const n = numberOfElems(loc);
2539 const elemsize = baseElemOf().size(loc);
2540 bool overflow = false;
2541 const sz = mulu(n, elemsize, overflow);
2542 if (overflow || sz >= uint.max)
2544 if (elemsize != SIZE_INVALID && n != uint.max)
2545 error(loc, "static array `%s` size overflowed to %lld", toChars(), cast(long)sz);
2546 return SIZE_INVALID;
2548 return sz;
2551 override uint alignsize()
2553 return next.alignsize();
2556 override bool isString()
2558 TY nty = next.toBasetype().ty;
2559 return nty.isSomeChar;
2562 override bool isZeroInit(const ref Loc loc)
2564 return next.isZeroInit(loc);
2567 override structalign_t alignment()
2569 return next.alignment();
2572 override MATCH constConv(Type to)
2574 if (auto tsa = to.isTypeSArray())
2576 if (!dim.equals(tsa.dim))
2577 return MATCH.nomatch;
2579 return TypeNext.constConv(to);
2582 override MATCH implicitConvTo(Type to)
2584 //printf("TypeSArray::implicitConvTo(to = %s) this = %s\n", to.toChars(), toChars());
2585 if (auto ta = to.isTypeDArray())
2587 if (!MODimplicitConv(next.mod, ta.next.mod))
2588 return MATCH.nomatch;
2590 /* Allow conversion to void[]
2592 if (ta.next.ty == Tvoid)
2594 return MATCH.convert;
2597 MATCH m = next.constConv(ta.next);
2598 if (m > MATCH.nomatch)
2600 return MATCH.convert;
2602 return MATCH.nomatch;
2604 if (auto tsa = to.isTypeSArray())
2606 if (this == to)
2607 return MATCH.exact;
2609 if (dim.equals(tsa.dim))
2611 MATCH m = next.implicitConvTo(tsa.next);
2613 /* Allow conversion to non-interface base class.
2615 if (m == MATCH.convert &&
2616 next.ty == Tclass)
2618 if (auto toc = tsa.next.isTypeClass)
2620 if (!toc.sym.isInterfaceDeclaration)
2621 return MATCH.convert;
2625 /* Since static arrays are value types, allow
2626 * conversions from const elements to non-const
2627 * ones, just like we allow conversion from const int
2628 * to int.
2630 if (m >= MATCH.constant)
2632 if (mod != to.mod)
2633 m = MATCH.constant;
2634 return m;
2638 return MATCH.nomatch;
2641 override Expression defaultInitLiteral(const ref Loc loc)
2643 static if (LOGDEFAULTINIT)
2645 printf("TypeSArray::defaultInitLiteral() '%s'\n", toChars());
2647 size_t d = cast(size_t)dim.toInteger();
2648 Expression elementinit;
2649 if (next.ty == Tvoid)
2650 elementinit = tuns8.defaultInitLiteral(loc);
2651 else
2652 elementinit = next.defaultInitLiteral(loc);
2653 auto elements = new Expressions(d);
2654 foreach (ref e; *elements)
2655 e = null;
2656 auto ae = new ArrayLiteralExp(Loc.initial, this, elementinit, elements);
2657 return ae;
2660 override bool hasSystemFields()
2662 return next.hasSystemFields();
2665 override bool hasVoidInitPointers()
2667 return next.hasVoidInitPointers();
2670 override bool hasInvariant()
2672 return next.hasInvariant();
2675 override bool needsDestruction()
2677 return next.needsDestruction();
2680 override bool needsCopyOrPostblit()
2682 return next.needsCopyOrPostblit();
2685 /*********************************
2688 override bool needsNested()
2690 return next.needsNested();
2693 override void accept(Visitor v)
2695 v.visit(this);
2699 /***********************************************************
2700 * Dynamic array, no dimension
2702 extern (C++) final class TypeDArray : TypeArray
2704 extern (D) this(Type t) @safe
2706 super(Tarray, t);
2707 //printf("TypeDArray(t = %p)\n", t);
2710 override const(char)* kind() const
2712 return "darray";
2715 override TypeDArray syntaxCopy()
2717 Type t = next.syntaxCopy();
2718 if (t == next)
2719 return this;
2721 auto result = new TypeDArray(t);
2722 result.mod = mod;
2723 return result;
2726 override uinteger_t size(const ref Loc loc)
2728 //printf("TypeDArray::size()\n");
2729 return target.ptrsize * 2;
2732 override uint alignsize()
2734 // A DArray consists of two ptr-sized values, so align it on pointer size
2735 // boundary
2736 return target.ptrsize;
2739 override bool isString()
2741 TY nty = next.toBasetype().ty;
2742 return nty.isSomeChar;
2745 override bool isZeroInit(const ref Loc loc)
2747 return true;
2750 override bool isBoolean()
2752 return true;
2755 override MATCH implicitConvTo(Type to)
2757 //printf("TypeDArray::implicitConvTo(to = %s) this = %s\n", to.toChars(), toChars());
2758 if (equals(to))
2759 return MATCH.exact;
2761 if (auto ta = to.isTypeDArray())
2763 if (!MODimplicitConv(next.mod, ta.next.mod))
2764 return MATCH.nomatch; // not const-compatible
2766 /* Allow conversion to void[]
2768 if (next.ty != Tvoid && ta.next.ty == Tvoid)
2770 return MATCH.convert;
2773 MATCH m = next.constConv(ta.next);
2774 if (m > MATCH.nomatch)
2776 if (m == MATCH.exact && mod != to.mod)
2777 m = MATCH.constant;
2778 return m;
2781 return Type.implicitConvTo(to);
2784 override void accept(Visitor v)
2786 v.visit(this);
2790 /***********************************************************
2792 extern (C++) final class TypeAArray : TypeArray
2794 Type index; // key type
2795 Loc loc;
2797 extern (D) this(Type t, Type index) @safe
2799 super(Taarray, t);
2800 this.index = index;
2803 static TypeAArray create(Type t, Type index) @safe
2805 return new TypeAArray(t, index);
2808 override const(char)* kind() const
2810 return "aarray";
2813 override TypeAArray syntaxCopy()
2815 Type t = next.syntaxCopy();
2816 Type ti = index.syntaxCopy();
2817 if (t == next && ti == index)
2818 return this;
2820 auto result = new TypeAArray(t, ti);
2821 result.mod = mod;
2822 return result;
2825 override uinteger_t size(const ref Loc loc)
2827 return target.ptrsize;
2830 override bool isZeroInit(const ref Loc loc)
2832 return true;
2835 override bool isBoolean()
2837 return true;
2840 override MATCH implicitConvTo(Type to)
2842 //printf("TypeAArray::implicitConvTo(to = %s) this = %s\n", to.toChars(), toChars());
2843 if (equals(to))
2844 return MATCH.exact;
2846 if (auto ta = to.isTypeAArray())
2848 if (!MODimplicitConv(next.mod, ta.next.mod))
2849 return MATCH.nomatch; // not const-compatible
2851 if (!MODimplicitConv(index.mod, ta.index.mod))
2852 return MATCH.nomatch; // not const-compatible
2854 MATCH m = next.constConv(ta.next);
2855 MATCH mi = index.constConv(ta.index);
2856 if (m > MATCH.nomatch && mi > MATCH.nomatch)
2858 return MODimplicitConv(mod, to.mod) ? MATCH.constant : MATCH.nomatch;
2861 return Type.implicitConvTo(to);
2864 override MATCH constConv(Type to)
2866 if (auto taa = to.isTypeAArray())
2868 MATCH mindex = index.constConv(taa.index);
2869 MATCH mkey = next.constConv(taa.next);
2870 // Pick the worst match
2871 return mkey < mindex ? mkey : mindex;
2873 return Type.constConv(to);
2876 override void accept(Visitor v)
2878 v.visit(this);
2882 /***********************************************************
2884 extern (C++) final class TypePointer : TypeNext
2886 extern (D) this(Type t) @safe
2888 super(Tpointer, t);
2891 static TypePointer create(Type t) @safe
2893 return new TypePointer(t);
2896 override const(char)* kind() const
2898 return "pointer";
2901 override TypePointer syntaxCopy()
2903 Type t = next.syntaxCopy();
2904 if (t == next)
2905 return this;
2907 auto result = new TypePointer(t);
2908 result.mod = mod;
2909 return result;
2912 override uinteger_t size(const ref Loc loc)
2914 return target.ptrsize;
2917 override MATCH implicitConvTo(Type to)
2919 //printf("TypePointer::implicitConvTo(to = %s) %s\n", to.toChars(), toChars());
2920 if (equals(to))
2921 return MATCH.exact;
2923 // Only convert between pointers
2924 auto tp = to.isTypePointer();
2925 if (!tp)
2926 return MATCH.nomatch;
2928 assert(this.next);
2929 assert(tp.next);
2931 // Conversion to void*
2932 if (tp.next.ty == Tvoid)
2934 // Function pointer conversion doesn't check constness?
2935 if (this.next.ty == Tfunction)
2936 return MATCH.convert;
2938 if (!MODimplicitConv(next.mod, tp.next.mod))
2939 return MATCH.nomatch; // not const-compatible
2941 return this.next.ty == Tvoid ? MATCH.constant : MATCH.convert;
2944 // Conversion between function pointers
2945 if (auto thisTf = this.next.isTypeFunction())
2946 return thisTf.implicitPointerConv(tp.next);
2948 // Default, no implicit conversion between the pointer targets
2949 MATCH m = next.constConv(tp.next);
2951 if (m == MATCH.exact && mod != to.mod)
2952 m = MATCH.constant;
2953 return m;
2956 override MATCH constConv(Type to)
2958 if (next.ty == Tfunction)
2960 if (to.nextOf() && next.equals((cast(TypeNext)to).next))
2961 return Type.constConv(to);
2962 else
2963 return MATCH.nomatch;
2965 return TypeNext.constConv(to);
2968 override bool isscalar()
2970 return true;
2973 override bool isZeroInit(const ref Loc loc)
2975 return true;
2978 override void accept(Visitor v)
2980 v.visit(this);
2984 /***********************************************************
2986 extern (C++) final class TypeReference : TypeNext
2988 extern (D) this(Type t) @safe
2990 super(Treference, t);
2991 // BUG: what about references to static arrays?
2994 override const(char)* kind() const
2996 return "reference";
2999 override TypeReference syntaxCopy()
3001 Type t = next.syntaxCopy();
3002 if (t == next)
3003 return this;
3005 auto result = new TypeReference(t);
3006 result.mod = mod;
3007 return result;
3010 override uinteger_t size(const ref Loc loc)
3012 return target.ptrsize;
3015 override bool isZeroInit(const ref Loc loc)
3017 return true;
3020 override void accept(Visitor v)
3022 v.visit(this);
3026 enum RET : int
3028 regs = 1, // returned in registers
3029 stack = 2, // returned on stack
3032 enum TRUSTformat : int
3034 TRUSTformatDefault, // do not emit @system when trust == TRUST.default_
3035 TRUSTformatSystem, // emit @system when trust == TRUST.default_
3038 alias TRUSTformatDefault = TRUSTformat.TRUSTformatDefault;
3039 alias TRUSTformatSystem = TRUSTformat.TRUSTformatSystem;
3041 /***********************************************************
3043 extern (C++) final class TypeFunction : TypeNext
3045 // .next is the return type
3047 ParameterList parameterList; // function parameters
3049 // These flags can be accessed like `bool` properties,
3050 // getters and setters are generated for them
3051 private extern (D) static struct BitFields
3053 bool isnothrow; /// nothrow
3054 bool isnogc; /// is @nogc
3055 bool isproperty; /// can be called without parentheses
3056 bool isref; /// returns a reference
3057 bool isreturn; /// 'this' is returned by ref
3058 bool isScopeQual; /// 'this' is scope
3059 bool isreturninferred; /// 'this' is return from inference
3060 bool isscopeinferred; /// 'this' is scope from inference
3061 bool islive; /// is @live
3062 bool incomplete; /// return type or default arguments removed
3063 bool isInOutParam; /// inout on the parameters
3064 bool isInOutQual; /// inout on the qualifier
3065 bool isctor; /// the function is a constructor
3066 bool isreturnscope; /// `this` is returned by value
3069 import dmd.common.bitfields : generateBitFields;
3070 mixin(generateBitFields!(BitFields, ushort));
3072 LINK linkage; // calling convention
3073 TRUST trust; // level of trust
3074 PURE purity = PURE.impure;
3075 byte inuse;
3076 Expressions* fargs; // function arguments
3078 extern (D) this(ParameterList pl, Type treturn, LINK linkage, StorageClass stc = 0) @safe
3080 super(Tfunction, treturn);
3081 //if (!treturn) *(char*)0=0;
3082 // assert(treturn);
3083 assert(VarArg.none <= pl.varargs && pl.varargs <= VarArg.max);
3084 this.parameterList = pl;
3085 this.linkage = linkage;
3087 if (stc & STC.pure_)
3088 this.purity = PURE.fwdref;
3089 if (stc & STC.nothrow_)
3090 this.isnothrow = true;
3091 if (stc & STC.nogc)
3092 this.isnogc = true;
3093 if (stc & STC.property)
3094 this.isproperty = true;
3095 if (stc & STC.live)
3096 this.islive = true;
3098 if (stc & STC.ref_)
3099 this.isref = true;
3100 if (stc & STC.return_)
3101 this.isreturn = true;
3102 if (stc & STC.returnScope)
3103 this.isreturnscope = true;
3104 if (stc & STC.returninferred)
3105 this.isreturninferred = true;
3106 if (stc & STC.scope_)
3107 this.isScopeQual = true;
3108 if (stc & STC.scopeinferred)
3109 this.isscopeinferred = true;
3111 this.trust = TRUST.default_;
3112 if (stc & STC.safe)
3113 this.trust = TRUST.safe;
3114 else if (stc & STC.system)
3115 this.trust = TRUST.system;
3116 else if (stc & STC.trusted)
3117 this.trust = TRUST.trusted;
3120 static TypeFunction create(Parameters* parameters, Type treturn, ubyte varargs, LINK linkage, StorageClass stc = 0) @safe
3122 return new TypeFunction(ParameterList(parameters, cast(VarArg)varargs), treturn, linkage, stc);
3125 override const(char)* kind() const
3127 return "function";
3130 override TypeFunction syntaxCopy()
3132 Type treturn = next ? next.syntaxCopy() : null;
3133 auto t = new TypeFunction(parameterList.syntaxCopy(), treturn, linkage);
3134 t.mod = mod;
3135 t.isnothrow = isnothrow;
3136 t.isnogc = isnogc;
3137 t.islive = islive;
3138 t.purity = purity;
3139 t.isproperty = isproperty;
3140 t.isref = isref;
3141 t.isreturn = isreturn;
3142 t.isreturnscope = isreturnscope;
3143 t.isScopeQual = isScopeQual;
3144 t.isreturninferred = isreturninferred;
3145 t.isscopeinferred = isscopeinferred;
3146 t.isInOutParam = isInOutParam;
3147 t.isInOutQual = isInOutQual;
3148 t.trust = trust;
3149 t.fargs = fargs;
3150 t.isctor = isctor;
3151 return t;
3154 /********************************************
3155 * Return true if there are lazy parameters.
3157 bool hasLazyParameters()
3159 foreach (i, fparam; parameterList)
3161 if (fparam.isLazy())
3162 return true;
3164 return false;
3167 /*******************************
3168 * Check for `extern (D) U func(T t, ...)` variadic function type,
3169 * which has `_arguments[]` added as the first argument.
3170 * Returns:
3171 * true if D-style variadic
3173 bool isDstyleVariadic() const pure nothrow
3175 return linkage == LINK.d && parameterList.varargs == VarArg.variadic;
3178 extern(D) static const(char)* getMatchError(A...)(const(char)* format, A args)
3180 if (global.gag && !global.params.v.showGaggedErrors)
3181 return null;
3182 OutBuffer buf;
3183 buf.printf(format, args);
3184 return buf.extractChars();
3187 /********************************
3188 * Convert an `argumentList`, which may contain named arguments, into
3189 * a list of arguments in the order of the parameter list.
3191 * Params:
3192 * argumentList = array of function arguments
3193 * pMessage = address to store error message, or `null`
3194 * Returns: re-ordered argument list, or `null` on error
3196 extern(D) Expressions* resolveNamedArgs(ArgumentList argumentList, const(char)** pMessage)
3198 Expression[] args = argumentList.arguments ? (*argumentList.arguments)[] : null;
3199 Identifier[] names = argumentList.names ? (*argumentList.names)[] : null;
3200 auto newArgs = new Expressions(parameterList.length);
3201 newArgs.zero();
3202 size_t ci = 0;
3203 bool hasNamedArgs = false;
3204 foreach (i, arg; args)
3206 if (!arg)
3208 ci++;
3209 continue;
3211 auto name = i < names.length ? names[i] : null;
3212 if (name)
3214 hasNamedArgs = true;
3215 const pi = findParameterIndex(name);
3216 if (pi == -1)
3218 if (pMessage)
3219 *pMessage = getMatchError("no parameter named `%s`", name.toChars());
3220 return null;
3222 ci = pi;
3224 if (ci >= newArgs.length)
3226 if (!parameterList.varargs)
3228 // Without named args, let the caller diagnose argument overflow
3229 if (hasNamedArgs && pMessage)
3230 *pMessage = getMatchError("argument `%s` goes past end of parameter list", arg.toChars());
3231 return null;
3233 while (ci >= newArgs.length)
3234 newArgs.push(null);
3237 if ((*newArgs)[ci])
3239 if (pMessage)
3240 *pMessage = getMatchError("parameter `%s` assigned twice", parameterList[ci].toChars());
3241 return null;
3243 (*newArgs)[ci++] = arg;
3245 foreach (i, arg; (*newArgs)[])
3247 if (arg || parameterList[i].defaultArg)
3248 continue;
3250 if (parameterList.varargs != VarArg.none && i + 1 == newArgs.length)
3251 continue;
3253 if (pMessage)
3254 *pMessage = getMatchError("missing argument for parameter #%d: `%s`",
3255 i + 1, parameterToChars(parameterList[i], this, false));
3256 return null;
3258 // strip trailing nulls from default arguments
3259 size_t e = newArgs.length;
3260 while (e > 0 && (*newArgs)[e - 1] is null)
3262 --e;
3264 newArgs.setDim(e);
3265 return newArgs;
3269 + Checks whether this function type is convertible to ` to`
3270 + when used in a function pointer / delegate.
3272 + Params:
3273 + to = target type
3275 + Returns:
3276 + MATCH.nomatch: `to` is not a covaraint function
3277 + MATCH.convert: `to` is a covaraint function
3278 + MATCH.exact: `to` is identical to this function
3280 private MATCH implicitPointerConv(Type to)
3282 assert(to);
3284 if (this.equals(to))
3285 return MATCH.constant;
3287 if (this.covariant(to) == Covariant.yes)
3289 Type tret = this.nextOf();
3290 Type toret = to.nextOf();
3291 if (tret.ty == Tclass && toret.ty == Tclass)
3293 /* https://issues.dlang.org/show_bug.cgi?id=10219
3294 * Check covariant interface return with offset tweaking.
3295 * interface I {}
3296 * class C : Object, I {}
3297 * I function() dg = function C() {} // should be error
3299 int offset = 0;
3300 if (toret.isBaseOf(tret, &offset) && offset != 0)
3301 return MATCH.nomatch;
3303 return MATCH.convert;
3306 return MATCH.nomatch;
3309 /** Extends TypeNext.constConv by also checking for matching attributes **/
3310 override MATCH constConv(Type to)
3312 // Attributes need to match exactly, otherwise it's an implicit conversion
3313 if (this.ty != to.ty || !this.attributesEqual(cast(TypeFunction) to))
3314 return MATCH.nomatch;
3316 return super.constConv(to);
3319 extern (D) bool checkRetType(const ref Loc loc)
3321 Type tb = next.toBasetype();
3322 if (tb.ty == Tfunction)
3324 error(loc, "functions cannot return a function");
3325 next = Type.terror;
3327 if (tb.ty == Ttuple)
3329 error(loc, "functions cannot return a sequence (use `std.typecons.Tuple`)");
3330 next = Type.terror;
3332 if (!isref && (tb.ty == Tstruct || tb.ty == Tsarray))
3334 if (auto ts = tb.baseElemOf().isTypeStruct())
3336 if (!ts.sym.members)
3338 error(loc, "functions cannot return opaque type `%s` by value", tb.toChars());
3339 next = Type.terror;
3343 if (tb.ty == Terror)
3344 return true;
3345 return false;
3349 /// Returns: `true` the function is `isInOutQual` or `isInOutParam` ,`false` otherwise.
3350 bool iswild() const pure nothrow @safe @nogc
3352 return isInOutParam || isInOutQual;
3355 /// Returns: whether `this` function type has the same attributes (`@safe`,...) as `other`
3356 extern (D) bool attributesEqual(const scope TypeFunction other, bool trustSystemEqualsDefault = true) const pure nothrow @safe @nogc
3358 // @@@DEPRECATED_2.112@@@
3359 // See semantic2.d Semantic2Visitor.visit(FuncDeclaration):
3360 // Two overloads that are identical except for one having an explicit `@system`
3361 // attribute is currently in deprecation, and will become an error in 2.104 for
3362 // `extern(C)`, and 2.112 for `extern(D)` code respectively. Once the deprecation
3363 // period has passed, the trustSystemEqualsDefault=true behaviour should be made
3364 // the default, then we can remove the `cannot overload extern(...) function`
3365 // errors as they will become dead code as a result.
3366 return (this.trust == other.trust ||
3367 (trustSystemEqualsDefault && this.trust <= TRUST.system && other.trust <= TRUST.system)) &&
3368 this.purity == other.purity &&
3369 this.isnothrow == other.isnothrow &&
3370 this.isnogc == other.isnogc &&
3371 this.islive == other.islive;
3374 override void accept(Visitor v)
3376 v.visit(this);
3380 * Look for the index of parameter `ident` in the parameter list
3382 * Params:
3383 * ident = identifier of parameter to search for
3384 * Returns: index of parameter with name `ident` or -1 if not found
3386 private extern(D) ptrdiff_t findParameterIndex(Identifier ident)
3388 foreach (i, p; this.parameterList)
3390 if (p.ident == ident)
3391 return i;
3393 return -1;
3397 /***********************************************************
3399 extern (C++) final class TypeDelegate : TypeNext
3401 // .next is a TypeFunction
3403 extern (D) this(TypeFunction t) @safe
3405 super(Tfunction, t);
3406 ty = Tdelegate;
3409 static TypeDelegate create(TypeFunction t) @safe
3411 return new TypeDelegate(t);
3414 override const(char)* kind() const
3416 return "delegate";
3419 override TypeDelegate syntaxCopy()
3421 auto tf = next.syntaxCopy().isTypeFunction();
3422 if (tf == next)
3423 return this;
3425 auto result = new TypeDelegate(tf);
3426 result.mod = mod;
3427 return result;
3430 override uinteger_t size(const ref Loc loc)
3432 return target.ptrsize * 2;
3435 override uint alignsize()
3437 return target.ptrsize;
3440 override MATCH implicitConvTo(Type to)
3442 //printf("TypeDelegate.implicitConvTo(this=%p, to=%p)\n", this, to);
3443 //printf("from: %s\n", toChars());
3444 //printf("to : %s\n", to.toChars());
3445 if (this.equals(to))
3446 return MATCH.exact;
3448 if (auto toDg = to.isTypeDelegate())
3450 MATCH m = this.next.isTypeFunction().implicitPointerConv(toDg.next);
3452 // Retain the old behaviour for this refactoring
3453 // Should probably be changed to constant to match function pointers
3454 if (m > MATCH.convert)
3455 m = MATCH.convert;
3457 return m;
3460 return MATCH.nomatch;
3463 override bool isZeroInit(const ref Loc loc)
3465 return true;
3468 override bool isBoolean()
3470 return true;
3473 override void accept(Visitor v)
3475 v.visit(this);
3480 * This is a shell containing a TraitsExp that can be
3481 * either resolved to a type or to a symbol.
3483 * The point is to allow AliasDeclarationY to use `__traits()`, see https://issues.dlang.org/show_bug.cgi?id=7804.
3485 extern (C++) final class TypeTraits : Type
3487 Loc loc;
3488 /// The expression to resolve as type or symbol.
3489 TraitsExp exp;
3490 /// Cached type/symbol after semantic analysis.
3491 RootObject obj;
3493 final extern (D) this(const ref Loc loc, TraitsExp exp) @safe
3495 super(Ttraits);
3496 this.loc = loc;
3497 this.exp = exp;
3500 override const(char)* kind() const
3502 return "traits";
3505 override TypeTraits syntaxCopy()
3507 TraitsExp te = exp.syntaxCopy();
3508 TypeTraits tt = new TypeTraits(loc, te);
3509 tt.mod = mod;
3510 return tt;
3513 override void accept(Visitor v)
3515 v.visit(this);
3518 override uinteger_t size(const ref Loc loc)
3520 return SIZE_INVALID;
3524 /******
3525 * Implements mixin types.
3527 * Semantic analysis will convert it to a real type.
3529 extern (C++) final class TypeMixin : Type
3531 Loc loc;
3532 Expressions* exps;
3533 RootObject obj; // cached result of semantic analysis.
3535 extern (D) this(const ref Loc loc, Expressions* exps) @safe
3537 super(Tmixin);
3538 this.loc = loc;
3539 this.exps = exps;
3542 override const(char)* kind() const
3544 return "mixin";
3547 override TypeMixin syntaxCopy()
3549 return new TypeMixin(loc, Expression.arraySyntaxCopy(exps));
3552 override void accept(Visitor v)
3554 v.visit(this);
3558 /***********************************************************
3560 extern (C++) abstract class TypeQualified : Type
3562 Loc loc;
3564 // array of Identifier and TypeInstance,
3565 // representing ident.ident!tiargs.ident. ... etc.
3566 Objects idents;
3568 final extern (D) this(TY ty, Loc loc)
3570 super(ty);
3571 this.loc = loc;
3574 // abstract override so that using `TypeQualified.syntaxCopy` gets
3575 // us a `TypeQualified`
3576 abstract override TypeQualified syntaxCopy();
3578 extern (D) final void syntaxCopyHelper(TypeQualified t)
3580 //printf("TypeQualified::syntaxCopyHelper(%s) %s\n", t.toChars(), toChars());
3581 idents.setDim(t.idents.length);
3582 for (size_t i = 0; i < idents.length; i++)
3584 RootObject id = t.idents[i];
3585 with (DYNCAST) final switch (id.dyncast())
3587 case object:
3588 break;
3589 case expression:
3590 Expression e = cast(Expression)id;
3591 e = e.syntaxCopy();
3592 id = e;
3593 break;
3594 case dsymbol:
3595 TemplateInstance ti = cast(TemplateInstance)id;
3596 ti = ti.syntaxCopy(null);
3597 id = ti;
3598 break;
3599 case type:
3600 Type tx = cast(Type)id;
3601 tx = tx.syntaxCopy();
3602 id = tx;
3603 break;
3604 case identifier:
3605 case tuple:
3606 case parameter:
3607 case statement:
3608 case condition:
3609 case templateparameter:
3610 case initializer:
3612 idents[i] = id;
3616 extern (D) final void addIdent(Identifier ident)
3618 idents.push(ident);
3621 extern (D) final void addInst(TemplateInstance inst)
3623 idents.push(inst);
3626 extern (D) final void addIndex(RootObject e)
3628 idents.push(e);
3631 override uinteger_t size(const ref Loc loc)
3633 error(this.loc, "size of type `%s` is not known", toChars());
3634 return SIZE_INVALID;
3637 override void accept(Visitor v)
3639 v.visit(this);
3643 /***********************************************************
3645 extern (C++) final class TypeIdentifier : TypeQualified
3647 Identifier ident;
3649 // The symbol representing this identifier, before alias resolution
3650 Dsymbol originalSymbol;
3652 extern (D) this(const ref Loc loc, Identifier ident)
3654 super(Tident, loc);
3655 this.ident = ident;
3658 static TypeIdentifier create(const ref Loc loc, Identifier ident)
3660 return new TypeIdentifier(loc, ident);
3663 override const(char)* kind() const
3665 return "identifier";
3668 override TypeIdentifier syntaxCopy()
3670 auto t = new TypeIdentifier(loc, ident);
3671 t.syntaxCopyHelper(this);
3672 t.mod = mod;
3673 return t;
3676 override void accept(Visitor v)
3678 v.visit(this);
3682 /***********************************************************
3683 * Similar to TypeIdentifier, but with a TemplateInstance as the root
3685 extern (C++) final class TypeInstance : TypeQualified
3687 TemplateInstance tempinst;
3689 extern (D) this(const ref Loc loc, TemplateInstance tempinst)
3691 super(Tinstance, loc);
3692 this.tempinst = tempinst;
3695 override const(char)* kind() const
3697 return "instance";
3700 override TypeInstance syntaxCopy()
3702 //printf("TypeInstance::syntaxCopy() %s, %d\n", toChars(), idents.length);
3703 auto t = new TypeInstance(loc, tempinst.syntaxCopy(null));
3704 t.syntaxCopyHelper(this);
3705 t.mod = mod;
3706 return t;
3709 override void accept(Visitor v)
3711 v.visit(this);
3715 /***********************************************************
3717 extern (C++) final class TypeTypeof : TypeQualified
3719 Expression exp;
3720 int inuse;
3722 extern (D) this(const ref Loc loc, Expression exp)
3724 super(Ttypeof, loc);
3725 this.exp = exp;
3728 override const(char)* kind() const
3730 return "typeof";
3733 override TypeTypeof syntaxCopy()
3735 //printf("TypeTypeof::syntaxCopy() %s\n", toChars());
3736 auto t = new TypeTypeof(loc, exp.syntaxCopy());
3737 t.syntaxCopyHelper(this);
3738 t.mod = mod;
3739 return t;
3742 override uinteger_t size(const ref Loc loc)
3744 if (exp.type)
3745 return exp.type.size(loc);
3746 else
3747 return TypeQualified.size(loc);
3750 override void accept(Visitor v)
3752 v.visit(this);
3756 /***********************************************************
3758 extern (C++) final class TypeReturn : TypeQualified
3760 extern (D) this(const ref Loc loc)
3762 super(Treturn, loc);
3765 override const(char)* kind() const
3767 return "return";
3770 override TypeReturn syntaxCopy()
3772 auto t = new TypeReturn(loc);
3773 t.syntaxCopyHelper(this);
3774 t.mod = mod;
3775 return t;
3778 override void accept(Visitor v)
3780 v.visit(this);
3784 /***********************************************************
3786 extern (C++) final class TypeStruct : Type
3788 StructDeclaration sym;
3789 AliasThisRec att = AliasThisRec.fwdref;
3790 bool inuse = false; // struct currently subject of recursive method call
3792 extern (D) this(StructDeclaration sym) @safe
3794 super(Tstruct);
3795 this.sym = sym;
3798 static TypeStruct create(StructDeclaration sym) @safe
3800 return new TypeStruct(sym);
3803 override const(char)* kind() const
3805 return "struct";
3808 override uinteger_t size(const ref Loc loc)
3810 return sym.size(loc);
3813 override uint alignsize()
3815 sym.size(Loc.initial); // give error for forward references
3816 return sym.alignsize;
3819 override TypeStruct syntaxCopy()
3821 return this;
3824 override structalign_t alignment()
3826 if (sym.alignment.isUnknown())
3827 sym.size(sym.loc);
3828 return sym.alignment;
3831 /***************************************
3832 * Use when we prefer the default initializer to be a literal,
3833 * rather than a global immutable variable.
3835 override Expression defaultInitLiteral(const ref Loc loc)
3837 static if (LOGDEFAULTINIT)
3839 printf("TypeStruct::defaultInitLiteral() '%s'\n", toChars());
3841 sym.size(loc);
3842 if (sym.sizeok != Sizeok.done)
3843 return ErrorExp.get();
3845 auto structelems = new Expressions(sym.nonHiddenFields());
3846 uint offset = 0;
3847 foreach (j; 0 .. structelems.length)
3849 VarDeclaration vd = sym.fields[j];
3850 Expression e;
3851 if (vd.inuse)
3853 error(loc, "circular reference to `%s`", vd.toPrettyChars());
3854 return ErrorExp.get();
3856 if (vd.offset < offset || vd.type.size() == 0)
3857 e = null;
3858 else if (vd._init)
3860 if (vd._init.isVoidInitializer())
3861 e = null;
3862 else
3863 e = vd.getConstInitializer(false);
3865 else
3866 e = vd.type.defaultInitLiteral(loc);
3867 if (e && e.op == EXP.error)
3868 return e;
3869 if (e)
3870 offset = vd.offset + cast(uint)vd.type.size();
3871 (*structelems)[j] = e;
3873 auto structinit = new StructLiteralExp(loc, sym, structelems);
3875 /* Copy from the initializer symbol for larger symbols,
3876 * otherwise the literals expressed as code get excessively large.
3878 if (size(loc) > target.ptrsize * 4 && !needsNested())
3879 structinit.useStaticInit = true;
3881 structinit.type = this;
3882 return structinit;
3885 override bool isZeroInit(const ref Loc loc)
3887 // Determine zeroInit here, as this can be called before semantic2
3888 sym.determineSize(sym.loc);
3889 return sym.zeroInit;
3892 override bool isAssignable()
3894 bool assignable = true;
3895 uint offset = ~0; // dead-store initialize to prevent spurious warning
3897 sym.determineSize(sym.loc);
3899 /* If any of the fields are const or immutable,
3900 * then one cannot assign this struct.
3902 for (size_t i = 0; i < sym.fields.length; i++)
3904 VarDeclaration v = sym.fields[i];
3905 //printf("%s [%d] v = (%s) %s, v.offset = %d, v.parent = %s\n", sym.toChars(), i, v.kind(), v.toChars(), v.offset, v.parent.kind());
3906 if (i == 0)
3909 else if (v.offset == offset)
3911 /* If any fields of anonymous union are assignable,
3912 * then regard union as assignable.
3913 * This is to support unsafe things like Rebindable templates.
3915 if (assignable)
3916 continue;
3918 else
3920 if (!assignable)
3921 return false;
3923 assignable = v.type.isMutable() && v.type.isAssignable();
3924 offset = v.offset;
3925 //printf(" -> assignable = %d\n", assignable);
3928 return assignable;
3931 override bool isBoolean()
3933 return false;
3936 override bool needsDestruction()
3938 return sym.dtor !is null;
3941 override bool needsCopyOrPostblit()
3943 return sym.hasCopyCtor || sym.postblit;
3946 override bool needsNested()
3948 if (inuse) return false; // circular type, error instead of crashing
3950 inuse = true;
3951 scope(exit) inuse = false;
3953 if (sym.isNested())
3954 return true;
3956 for (size_t i = 0; i < sym.fields.length; i++)
3958 VarDeclaration v = sym.fields[i];
3959 if (!v.isDataseg() && v.type.needsNested())
3960 return true;
3962 return false;
3965 override bool hasVoidInitPointers()
3967 sym.size(Loc.initial); // give error for forward references
3968 sym.determineTypeProperties();
3969 return sym.hasVoidInitPointers;
3972 override bool hasSystemFields()
3974 sym.size(Loc.initial); // give error for forward references
3975 sym.determineTypeProperties();
3976 return sym.hasSystemFields;
3979 override bool hasInvariant()
3981 sym.size(Loc.initial); // give error for forward references
3982 sym.determineTypeProperties();
3983 return sym.hasInvariant() || sym.hasFieldWithInvariant;
3986 extern (D) MATCH implicitConvToWithoutAliasThis(Type to)
3988 MATCH m;
3990 if (ty == to.ty && sym == (cast(TypeStruct)to).sym)
3992 m = MATCH.exact; // exact match
3993 if (mod != to.mod)
3995 m = MATCH.constant;
3996 if (MODimplicitConv(mod, to.mod))
3999 else
4001 /* Check all the fields. If they can all be converted,
4002 * allow the conversion.
4004 uint offset = ~0; // dead-store to prevent spurious warning
4005 for (size_t i = 0; i < sym.fields.length; i++)
4007 VarDeclaration v = sym.fields[i];
4008 if (i == 0)
4011 else if (v.offset == offset)
4013 if (m > MATCH.nomatch)
4014 continue;
4016 else
4018 if (m == MATCH.nomatch)
4019 return m;
4022 // 'from' type
4023 Type tvf = v.type.addMod(mod);
4025 // 'to' type
4026 Type tv = v.type.addMod(to.mod);
4028 // field match
4029 MATCH mf = tvf.implicitConvTo(tv);
4030 //printf("\t%s => %s, match = %d\n", v.type.toChars(), tv.toChars(), mf);
4032 if (mf == MATCH.nomatch)
4033 return mf;
4034 if (mf < m) // if field match is worse
4035 m = mf;
4036 offset = v.offset;
4041 return m;
4044 extern (D) MATCH implicitConvToThroughAliasThis(Type to)
4046 MATCH m;
4047 if (!(ty == to.ty && sym == (cast(TypeStruct)to).sym) && sym.aliasthis && !(att & AliasThisRec.tracing))
4049 if (auto ato = aliasthisOf(this))
4051 att = cast(AliasThisRec)(att | AliasThisRec.tracing);
4052 m = ato.implicitConvTo(to);
4053 att = cast(AliasThisRec)(att & ~AliasThisRec.tracing);
4055 else
4056 m = MATCH.nomatch; // no match
4058 return m;
4061 override MATCH implicitConvTo(Type to)
4063 //printf("TypeStruct::implicitConvTo(%s => %s)\n", toChars(), to.toChars());
4064 MATCH m = implicitConvToWithoutAliasThis(to);
4065 return m ? m : implicitConvToThroughAliasThis(to);
4068 override MATCH constConv(Type to)
4070 if (equals(to))
4071 return MATCH.exact;
4072 if (ty == to.ty && sym == (cast(TypeStruct)to).sym && MODimplicitConv(mod, to.mod))
4073 return MATCH.constant;
4074 return MATCH.nomatch;
4077 override MOD deduceWild(Type t, bool isRef)
4079 if (ty == t.ty && sym == (cast(TypeStruct)t).sym)
4080 return Type.deduceWild(t, isRef);
4082 ubyte wm = 0;
4084 if (t.hasWild() && sym.aliasthis && !(att & AliasThisRec.tracing))
4086 if (auto ato = aliasthisOf(this))
4088 att = cast(AliasThisRec)(att | AliasThisRec.tracing);
4089 wm = ato.deduceWild(t, isRef);
4090 att = cast(AliasThisRec)(att & ~AliasThisRec.tracing);
4094 return wm;
4097 override void accept(Visitor v)
4099 v.visit(this);
4103 /***********************************************************
4105 extern (C++) final class TypeEnum : Type
4107 EnumDeclaration sym;
4109 extern (D) this(EnumDeclaration sym) @safe
4111 super(Tenum);
4112 this.sym = sym;
4115 override const(char)* kind() const
4117 return "enum";
4120 override TypeEnum syntaxCopy()
4122 return this;
4125 override uinteger_t size(const ref Loc loc)
4127 return sym.getMemtype(loc).size(loc);
4130 Type memType()
4132 return sym.getMemtype(Loc.initial);
4135 override uint alignsize()
4137 Type t = memType();
4138 if (t.ty == Terror)
4139 return 4;
4140 return t.alignsize();
4143 override bool isintegral()
4145 return memType().isintegral();
4148 override bool isfloating()
4150 return memType().isfloating();
4153 override bool isreal()
4155 return memType().isreal();
4158 override bool isimaginary()
4160 return memType().isimaginary();
4163 override bool iscomplex()
4165 return memType().iscomplex();
4168 override bool isscalar()
4170 return memType().isscalar();
4173 override bool isunsigned()
4175 return memType().isunsigned();
4178 override bool isBoolean()
4180 return memType().isBoolean();
4183 override bool isString()
4185 return memType().isString();
4188 override bool isAssignable()
4190 return memType().isAssignable();
4193 override bool needsDestruction()
4195 return memType().needsDestruction();
4198 override bool needsCopyOrPostblit()
4200 return memType().needsCopyOrPostblit();
4203 override bool needsNested()
4205 return memType().needsNested();
4208 override MATCH implicitConvTo(Type to)
4210 MATCH m;
4211 //printf("TypeEnum::implicitConvTo() %s to %s\n", toChars(), to.toChars());
4212 if (ty == to.ty && sym == (cast(TypeEnum)to).sym)
4213 m = (mod == to.mod) ? MATCH.exact : MATCH.constant;
4214 else if (sym.getMemtype(Loc.initial).implicitConvTo(to))
4215 m = MATCH.convert; // match with conversions
4216 else
4217 m = MATCH.nomatch; // no match
4218 return m;
4221 override MATCH constConv(Type to)
4223 if (equals(to))
4224 return MATCH.exact;
4225 if (ty == to.ty && sym == (cast(TypeEnum)to).sym && MODimplicitConv(mod, to.mod))
4226 return MATCH.constant;
4227 return MATCH.nomatch;
4230 extern (D) Type toBasetype2()
4232 if (!sym.members && !sym.memtype)
4233 return this;
4234 auto tb = sym.getMemtype(Loc.initial).toBasetype();
4235 return tb.castMod(mod); // retain modifier bits from 'this'
4238 override bool isZeroInit(const ref Loc loc)
4240 return sym.getDefaultValue(loc).toBool().hasValue(false);
4243 override bool hasVoidInitPointers()
4245 return memType().hasVoidInitPointers();
4248 override bool hasSystemFields()
4250 return memType().hasSystemFields();
4253 override bool hasInvariant()
4255 return memType().hasInvariant();
4258 override Type nextOf()
4260 return memType().nextOf();
4263 override void accept(Visitor v)
4265 v.visit(this);
4269 /***********************************************************
4271 extern (C++) final class TypeClass : Type
4273 ClassDeclaration sym;
4274 AliasThisRec att = AliasThisRec.fwdref;
4275 CPPMANGLE cppmangle = CPPMANGLE.def;
4277 extern (D) this(ClassDeclaration sym) @safe
4279 super(Tclass);
4280 this.sym = sym;
4283 override const(char)* kind() const
4285 return "class";
4288 override uinteger_t size(const ref Loc loc)
4290 return target.ptrsize;
4293 override TypeClass syntaxCopy()
4295 return this;
4298 override inout(ClassDeclaration) isClassHandle() inout
4300 return sym;
4303 extern (D) MATCH implicitConvToWithoutAliasThis(Type to)
4305 ClassDeclaration cdto = to.isClassHandle();
4306 MATCH m = constConv(to);
4307 if (m > MATCH.nomatch)
4308 return m;
4310 if (cdto && cdto.isBaseOf(sym, null) && MODimplicitConv(mod, to.mod))
4312 //printf("'to' is base\n");
4313 return MATCH.convert;
4315 return MATCH.nomatch;
4318 extern (D) MATCH implicitConvToThroughAliasThis(Type to)
4320 MATCH m;
4321 if (sym.aliasthis && !(att & AliasThisRec.tracing))
4323 if (auto ato = aliasthisOf(this))
4325 att = cast(AliasThisRec)(att | AliasThisRec.tracing);
4326 m = ato.implicitConvTo(to);
4327 att = cast(AliasThisRec)(att & ~AliasThisRec.tracing);
4330 return m;
4333 override MATCH implicitConvTo(Type to)
4335 //printf("TypeClass::implicitConvTo(to = '%s') %s\n", to.toChars(), toChars());
4336 MATCH m = implicitConvToWithoutAliasThis(to);
4337 return m ? m : implicitConvToThroughAliasThis(to);
4340 override MATCH constConv(Type to)
4342 if (equals(to))
4343 return MATCH.exact;
4344 if (ty == to.ty && sym == (cast(TypeClass)to).sym && MODimplicitConv(mod, to.mod))
4345 return MATCH.constant;
4347 /* Conversion derived to const(base)
4349 int offset = 0;
4350 if (to.isBaseOf(this, &offset) && offset == 0 && MODimplicitConv(mod, to.mod))
4352 // Disallow:
4353 // derived to base
4354 // inout(derived) to inout(base)
4355 if (!to.isMutable() && !to.isWild())
4356 return MATCH.convert;
4359 return MATCH.nomatch;
4362 override MOD deduceWild(Type t, bool isRef)
4364 ClassDeclaration cd = t.isClassHandle();
4365 if (cd && (sym == cd || cd.isBaseOf(sym, null)))
4366 return Type.deduceWild(t, isRef);
4368 ubyte wm = 0;
4370 if (t.hasWild() && sym.aliasthis && !(att & AliasThisRec.tracing))
4372 if (auto ato = aliasthisOf(this))
4374 att = cast(AliasThisRec)(att | AliasThisRec.tracing);
4375 wm = ato.deduceWild(t, isRef);
4376 att = cast(AliasThisRec)(att & ~AliasThisRec.tracing);
4380 return wm;
4383 override bool isZeroInit(const ref Loc loc)
4385 return true;
4388 override bool isscope()
4390 return sym.stack;
4393 override bool isBoolean()
4395 return true;
4398 override void accept(Visitor v)
4400 v.visit(this);
4404 /***********************************************************
4406 extern (C++) final class TypeTuple : Type
4408 // 'logically immutable' cached global - don't modify!
4409 __gshared TypeTuple empty = new TypeTuple();
4411 Parameters* arguments; // types making up the tuple
4413 extern (D) this(Parameters* arguments) @safe
4415 super(Ttuple);
4416 //printf("TypeTuple(this = %p)\n", this);
4417 this.arguments = arguments;
4418 //printf("TypeTuple() %p, %s\n", this, toChars());
4419 debug
4421 if (arguments)
4423 for (size_t i = 0; i < arguments.length; i++)
4425 Parameter arg = (*arguments)[i];
4426 assert(arg && arg.type);
4432 /****************
4433 * Form TypeTuple from the types of the expressions.
4434 * Assume exps[] is already tuple expanded.
4436 extern (D) this(Expressions* exps)
4438 super(Ttuple);
4439 auto arguments = new Parameters(exps ? exps.length : 0);
4440 if (exps)
4442 for (size_t i = 0; i < exps.length; i++)
4444 Expression e = (*exps)[i];
4445 if (e.type.ty == Ttuple)
4446 error(e.loc, "cannot form sequence of sequences");
4447 auto arg = new Parameter(e.loc, STC.undefined_, e.type, null, null, null);
4448 (*arguments)[i] = arg;
4451 this.arguments = arguments;
4452 //printf("TypeTuple() %p, %s\n", this, toChars());
4455 static TypeTuple create(Parameters* arguments) @safe
4457 return new TypeTuple(arguments);
4460 /*******************************************
4461 * Type tuple with 0, 1 or 2 types in it.
4463 extern (D) this() @safe
4465 super(Ttuple);
4466 arguments = new Parameters();
4469 extern (D) this(Type t1)
4471 super(Ttuple);
4472 arguments = new Parameters();
4473 arguments.push(new Parameter(Loc.initial, 0, t1, null, null, null));
4476 extern (D) this(Type t1, Type t2)
4478 super(Ttuple);
4479 arguments = new Parameters();
4480 arguments.push(new Parameter(Loc.initial, 0, t1, null, null, null));
4481 arguments.push(new Parameter(Loc.initial, 0, t2, null, null, null));
4484 static TypeTuple create() @safe
4486 return new TypeTuple();
4489 static TypeTuple create(Type t1)
4491 return new TypeTuple(t1);
4494 static TypeTuple create(Type t1, Type t2)
4496 return new TypeTuple(t1, t2);
4499 override const(char)* kind() const
4501 return "sequence";
4504 override TypeTuple syntaxCopy()
4506 Parameters* args = Parameter.arraySyntaxCopy(arguments);
4507 auto t = new TypeTuple(args);
4508 t.mod = mod;
4509 return t;
4512 override bool equals(const RootObject o) const
4514 Type t = cast(Type)o;
4515 //printf("TypeTuple::equals(%s, %s)\n", toChars(), t.toChars());
4516 if (this == t)
4517 return true;
4518 if (auto tt = t.isTypeTuple())
4520 if (arguments.length == tt.arguments.length)
4522 for (size_t i = 0; i < tt.arguments.length; i++)
4524 const Parameter arg1 = (*arguments)[i];
4525 Parameter arg2 = (*tt.arguments)[i];
4526 if (!arg1.type.equals(arg2.type))
4527 return false;
4529 return true;
4532 return false;
4535 override MATCH implicitConvTo(Type to)
4537 if (this == to)
4538 return MATCH.exact;
4539 if (auto tt = to.isTypeTuple())
4541 if (arguments.length == tt.arguments.length)
4543 MATCH m = MATCH.exact;
4544 for (size_t i = 0; i < tt.arguments.length; i++)
4546 Parameter arg1 = (*arguments)[i];
4547 Parameter arg2 = (*tt.arguments)[i];
4548 MATCH mi = arg1.type.implicitConvTo(arg2.type);
4549 if (mi < m)
4550 m = mi;
4552 return m;
4555 return MATCH.nomatch;
4558 override void accept(Visitor v)
4560 v.visit(this);
4564 /***********************************************************
4565 * This is so we can slice a TypeTuple
4567 extern (C++) final class TypeSlice : TypeNext
4569 Expression lwr;
4570 Expression upr;
4572 extern (D) this(Type next, Expression lwr, Expression upr) @safe
4574 super(Tslice, next);
4575 //printf("TypeSlice[%s .. %s]\n", lwr.toChars(), upr.toChars());
4576 this.lwr = lwr;
4577 this.upr = upr;
4580 override const(char)* kind() const
4582 return "slice";
4585 override TypeSlice syntaxCopy()
4587 auto t = new TypeSlice(next.syntaxCopy(), lwr.syntaxCopy(), upr.syntaxCopy());
4588 t.mod = mod;
4589 return t;
4592 override void accept(Visitor v)
4594 v.visit(this);
4598 /***********************************************************
4600 extern (C++) final class TypeNull : Type
4602 extern (D) this() @safe
4604 //printf("TypeNull %p\n", this);
4605 super(Tnull);
4608 override const(char)* kind() const
4610 return "null";
4613 override TypeNull syntaxCopy()
4615 // No semantic analysis done, no need to copy
4616 return this;
4619 override MATCH implicitConvTo(Type to)
4621 //printf("TypeNull::implicitConvTo(this=%p, to=%p)\n", this, to);
4622 //printf("from: %s\n", toChars());
4623 //printf("to : %s\n", to.toChars());
4624 MATCH m = Type.implicitConvTo(to);
4625 if (m != MATCH.nomatch)
4626 return m;
4628 // NULL implicitly converts to any pointer type or dynamic array
4629 //if (type.ty == Tpointer && type.nextOf().ty == Tvoid)
4631 Type tb = to.toBasetype();
4632 if (tb.ty == Tnull || tb.ty == Tpointer || tb.ty == Tarray || tb.ty == Taarray || tb.ty == Tclass || tb.ty == Tdelegate)
4633 return MATCH.constant;
4636 return MATCH.nomatch;
4639 override bool isBoolean()
4641 return true;
4644 override uinteger_t size(const ref Loc loc)
4646 return tvoidptr.size(loc);
4649 override void accept(Visitor v)
4651 v.visit(this);
4655 /***********************************************************
4657 extern (C++) final class TypeNoreturn : Type
4659 extern (D) this() @safe
4661 //printf("TypeNoreturn %p\n", this);
4662 super(Tnoreturn);
4665 override const(char)* kind() const
4667 return "noreturn";
4670 override TypeNoreturn syntaxCopy()
4672 // No semantic analysis done, no need to copy
4673 return this;
4676 override MATCH implicitConvTo(Type to)
4678 //printf("TypeNoreturn::implicitConvTo(this=%p, to=%p)\n", this, to);
4679 //printf("from: %s\n", toChars());
4680 //printf("to : %s\n", to.toChars());
4681 if (this.equals(to))
4682 return MATCH.exact;
4684 // Different qualifiers?
4685 if (to.ty == Tnoreturn)
4686 return MATCH.constant;
4688 // Implicitly convertible to any type
4689 return MATCH.convert;
4692 override MATCH constConv(Type to)
4694 // Either another noreturn or conversion to any type
4695 return this.implicitConvTo(to);
4698 override bool isBoolean()
4700 return true; // bottom type can be implicitly converted to any other type
4703 override uinteger_t size(const ref Loc loc)
4705 return 0;
4708 override uint alignsize()
4710 return 0;
4713 override void accept(Visitor v)
4715 v.visit(this);
4719 /***********************************************************
4720 * Unlike D, C can declare/define struct/union/enum tag names
4721 * inside Declarators, instead of separately as in D.
4722 * The order these appear in the symbol table must be in lexical
4723 * order. There isn't enough info at the parsing stage to determine if
4724 * it's a declaration or a reference to an existing name, so this Type
4725 * collects the necessary info and defers it to semantic().
4727 extern (C++) final class TypeTag : Type
4729 Loc loc; /// location of declaration
4730 TOK tok; /// TOK.struct_, TOK.union_, TOK.enum_
4731 structalign_t packalign; /// alignment of struct/union fields
4732 Identifier id; /// tag name identifier
4733 Type base; /// base type for enums otherwise null
4734 Dsymbols* members; /// members of struct, null if none
4736 Type resolved; /// type after semantic() in case there are more others
4737 /// pointing to this instance, which can happen with
4738 /// struct S { int a; } s1, *s2;
4739 MOD mod; /// modifiers to apply after type is resolved (only MODFlags.const_ at the moment)
4741 extern (D) this(const ref Loc loc, TOK tok, Identifier id, structalign_t packalign, Type base, Dsymbols* members) @safe
4743 //printf("TypeTag ctor %s %p\n", id ? id.toChars() : "null".ptr, this);
4744 super(Ttag);
4745 this.loc = loc;
4746 this.tok = tok;
4747 this.id = id;
4748 this.packalign = packalign;
4749 this.base = base;
4750 this.members = members;
4751 this.mod = 0;
4754 override const(char)* kind() const
4756 return "tag";
4759 override TypeTag syntaxCopy()
4761 //printf("TypeTag syntaxCopy()\n");
4762 // No semantic analysis done, no need to copy
4763 return this;
4766 override void accept(Visitor v)
4768 v.visit(this);
4772 /***********************************************************
4773 * Represents a function's formal parameters + variadics info.
4774 * Length, indexing and iteration are based on a depth-first tuple expansion.
4775 * https://dlang.org/spec/function.html#ParameterList
4777 extern (C++) struct ParameterList
4779 /// The raw (unexpanded) formal parameters, possibly containing tuples.
4780 Parameters* parameters;
4781 StorageClass stc; // storage class of ...
4782 VarArg varargs = VarArg.none;
4783 bool hasIdentifierList; // true if C identifier-list style
4785 this(Parameters* parameters, VarArg varargs = VarArg.none, StorageClass stc = 0) @safe
4787 this.parameters = parameters;
4788 this.varargs = varargs;
4789 this.stc = stc;
4792 /// Returns the number of expanded parameters. Complexity: O(N).
4793 size_t length()
4795 return Parameter.dim(parameters);
4798 /// Returns the expanded parameter at the given index, or null if out of
4799 /// bounds. Complexity: O(i).
4800 Parameter opIndex(size_t i)
4802 return Parameter.getNth(parameters, i);
4805 /// Iterates over the expanded parameters. Complexity: O(N).
4806 /// Prefer this to avoid the O(N + N^2/2) complexity of calculating length
4807 /// and calling N times opIndex.
4808 extern (D) int opApply(scope Parameter.ForeachDg dg)
4810 return Parameter._foreach(parameters, dg);
4813 /// Iterates over the expanded parameters, matching them with the unexpanded
4814 /// ones, for semantic processing
4815 extern (D) int opApply(scope Parameter.SemanticForeachDg dg)
4817 return Parameter._foreach(this.parameters, dg);
4820 extern (D) ParameterList syntaxCopy()
4822 return ParameterList(Parameter.arraySyntaxCopy(parameters), varargs);
4825 /// Compares this to another ParameterList (and expands tuples if necessary)
4826 extern (D) bool opEquals(scope ref ParameterList other) const
4828 if (stc != other.stc || varargs != other.varargs || (!parameters != !other.parameters))
4829 return false;
4831 if (this.parameters is other.parameters)
4832 return true;
4834 size_t idx;
4835 bool diff;
4837 // Pairwise compare each parameter
4838 // Can this avoid the O(n) indexing for the second list?
4839 foreach (_, p1; cast() this)
4841 auto p2 = other[idx++];
4842 if (!p2 || p1 != p2) {
4843 diff = true;
4844 break;
4848 // Ensure no remaining parameters in `other`
4849 return !diff && other[idx] is null;
4852 /// Returns: `true` if any parameter has a default argument
4853 extern(D) bool hasDefaultArgs()
4855 foreach (oidx, oparam, eidx, eparam; this)
4857 if (eparam.defaultArg)
4858 return true;
4860 return false;
4863 // Returns: `true` if any parameter doesn't have a default argument
4864 extern(D) bool hasArgsWithoutDefault()
4866 foreach (oidx, oparam, eidx, eparam; this)
4868 if (!eparam.defaultArg)
4869 return true;
4871 return false;
4876 /***********************************************************
4878 extern (C++) final class Parameter : ASTNode
4880 import dmd.attrib : UserAttributeDeclaration;
4882 Loc loc;
4883 StorageClass storageClass;
4884 Type type;
4885 Identifier ident;
4886 Expression defaultArg;
4887 UserAttributeDeclaration userAttribDecl; // user defined attributes
4889 extern (D) this(const ref Loc loc, StorageClass storageClass, Type type, Identifier ident, Expression defaultArg, UserAttributeDeclaration userAttribDecl) @safe
4891 this.loc = loc;
4892 this.type = type;
4893 this.ident = ident;
4894 this.storageClass = storageClass;
4895 this.defaultArg = defaultArg;
4896 this.userAttribDecl = userAttribDecl;
4899 static Parameter create(const ref Loc loc, StorageClass storageClass, Type type, Identifier ident, Expression defaultArg, UserAttributeDeclaration userAttribDecl) @safe
4901 return new Parameter(loc, storageClass, type, ident, defaultArg, userAttribDecl);
4904 Parameter syntaxCopy()
4906 return new Parameter(loc, storageClass, type ? type.syntaxCopy() : null, ident, defaultArg ? defaultArg.syntaxCopy() : null, userAttribDecl ? userAttribDecl.syntaxCopy(null) : null);
4909 /****************************************************
4910 * Determine if parameter is a lazy array of delegates.
4911 * If so, return the return type of those delegates.
4912 * If not, return NULL.
4914 * Returns T if the type is one of the following forms:
4915 * T delegate()[]
4916 * T delegate()[dim]
4918 Type isLazyArray()
4920 Type tb = type.toBasetype();
4921 if (tb.ty == Tsarray || tb.ty == Tarray)
4923 Type tel = (cast(TypeArray)tb).next.toBasetype();
4924 if (auto td = tel.isTypeDelegate())
4926 TypeFunction tf = td.next.toTypeFunction();
4927 if (tf.parameterList.varargs == VarArg.none && tf.parameterList.length == 0)
4929 return tf.next; // return type of delegate
4933 return null;
4936 /// Returns: Whether the function parameter is lazy
4937 bool isLazy() const @safe pure nothrow @nogc
4939 return (this.storageClass & (STC.lazy_)) != 0;
4942 /// Returns: Whether the function parameter is a reference (out / ref)
4943 bool isReference() const @safe pure nothrow @nogc
4945 return (this.storageClass & (STC.ref_ | STC.out_)) != 0;
4948 // kludge for template.isType()
4949 override DYNCAST dyncast() const
4951 return DYNCAST.parameter;
4954 override void accept(Visitor v)
4956 v.visit(this);
4959 extern (D) static Parameters* arraySyntaxCopy(Parameters* parameters)
4961 Parameters* params = null;
4962 if (parameters)
4964 params = new Parameters(parameters.length);
4965 for (size_t i = 0; i < params.length; i++)
4966 (*params)[i] = (*parameters)[i].syntaxCopy();
4968 return params;
4971 /***************************************
4972 * Determine number of arguments, folding in tuples.
4974 static size_t dim(Parameters* parameters)
4976 size_t nargs = 0;
4978 int dimDg(size_t n, Parameter p)
4980 ++nargs;
4981 return 0;
4984 _foreach(parameters, &dimDg);
4985 return nargs;
4989 * Get nth `Parameter`, folding in tuples.
4991 * Since `parameters` can include tuples, which would increase its
4992 * length, this function allows to get the `nth` parameter as if
4993 * all tuples transitively contained in `parameters` were flattened.
4995 * Params:
4996 * parameters = Array of `Parameter` to iterate over
4997 * nth = Index of the desired parameter.
4999 * Returns:
5000 * The parameter at index `nth` (taking tuples into account),
5001 * or `null` if out of bound.
5003 static Parameter getNth(Parameters* parameters, size_t nth)
5005 Parameter param;
5007 int getNthParamDg(size_t n, Parameter p)
5009 if (n == nth)
5011 param = p;
5012 return 1;
5014 return 0;
5017 int res = _foreach(parameters, &getNthParamDg);
5018 return res ? param : null;
5021 /// Type of delegate when iterating solely on the parameters
5022 alias ForeachDg = extern (D) int delegate(size_t paramidx, Parameter param);
5023 /// Type of delegate when iterating on both the original set of parameters,
5024 /// and the type tuple. Useful for semantic analysis.
5025 /// 'o' stands for 'original' and 'e' stands for 'expanded'.
5026 alias SemanticForeachDg = extern (D) int delegate(
5027 size_t oidx, Parameter oparam, size_t eidx, Parameter eparam);
5029 /***************************************
5030 * Expands tuples in args in depth first order. Calls
5031 * dg(void *ctx, size_t argidx, Parameter *arg) for each Parameter.
5032 * If dg returns !=0, stops and returns that value else returns 0.
5033 * Use this function to avoid the O(N + N^2/2) complexity of
5034 * calculating dim and calling N times getNth.
5036 extern (D) static int _foreach(Parameters* parameters, scope ForeachDg dg)
5038 assert(dg !is null);
5039 return _foreach(parameters, (_oidx, _oparam, idx, param) => dg(idx, param));
5042 /// Ditto
5043 extern (D) static int _foreach(
5044 Parameters* parameters, scope SemanticForeachDg dg)
5046 assert(dg !is null);
5047 if (parameters is null)
5048 return 0;
5050 size_t eidx;
5051 foreach (oidx; 0 .. parameters.length)
5053 Parameter oparam = (*parameters)[oidx];
5054 if (auto r = _foreachImpl(dg, oidx, oparam, eidx, /* eparam */ oparam))
5055 return r;
5057 return 0;
5060 /// Implementation of the iteration process, which recurses in itself
5061 /// and just forwards `oidx` and `oparam`.
5062 extern (D) private static int _foreachImpl(scope SemanticForeachDg dg,
5063 size_t oidx, Parameter oparam, ref size_t eidx, Parameter eparam)
5065 if (eparam is null)
5066 return 0;
5068 Type t = eparam.type.toBasetype();
5069 if (auto tu = t.isTypeTuple())
5071 // Check for empty tuples
5072 if (tu.arguments is null)
5073 return 0;
5075 foreach (nidx; 0 .. tu.arguments.length)
5077 Parameter nextep = (*tu.arguments)[nidx];
5078 if (auto r = _foreachImpl(dg, oidx, oparam, eidx, nextep))
5079 return r;
5082 else
5084 if (auto r = dg(oidx, oparam, eidx, eparam))
5085 return r;
5086 // The only place where we should increment eidx is here,
5087 // as a TypeTuple doesn't count as a parameter (for arity)
5088 // it it is empty.
5089 eidx++;
5091 return 0;
5094 override const(char)* toChars() const
5096 return ident ? ident.toChars() : "__anonymous_param";
5099 /*********************************
5100 * Compute covariance of parameters `this` and `p`
5101 * as determined by the storage classes of both.
5103 * Params:
5104 * returnByRef = true if the function returns by ref
5105 * p = Parameter to compare with
5106 * Returns:
5107 * true = `this` can be used in place of `p`
5108 * false = nope
5110 bool isCovariant(bool returnByRef, const Parameter p)
5111 const pure nothrow @nogc @safe
5113 ulong thisSTC = this.storageClass;
5114 ulong otherSTC = p.storageClass;
5116 if (thisSTC & STC.constscoperef)
5117 thisSTC |= STC.scope_;
5118 if (otherSTC & STC.constscoperef)
5119 otherSTC |= STC.scope_;
5121 const mask = STC.ref_ | STC.out_ | STC.lazy_ | (((thisSTC | otherSTC) & STC.constscoperef) ? STC.in_ : 0);
5122 if ((thisSTC & mask) != (otherSTC & mask))
5123 return false;
5124 return isCovariantScope(returnByRef, thisSTC, otherSTC);
5127 extern (D) static bool isCovariantScope(bool returnByRef, StorageClass from, StorageClass to) pure nothrow @nogc @safe
5129 // Workaround for failing covariance when finding a common type of delegates,
5130 // some of which have parameters with inferred scope
5131 // https://issues.dlang.org/show_bug.cgi?id=21285
5132 // The root cause is that scopeinferred is not part of the mangle, and mangle
5133 // is used for type equality checks
5134 if (to & STC.returninferred)
5135 to &= ~STC.return_;
5136 // note: f(return int* x) currently 'infers' scope without inferring `return`, in that case keep STC.scope
5137 if (to & STC.scopeinferred && !(to & STC.return_))
5138 to &= ~STC.scope_;
5140 if (from == to)
5141 return true;
5143 /* result is true if the 'from' can be used as a 'to'
5146 if ((from ^ to) & STC.ref_) // differing in 'ref' means no covariance
5147 return false;
5149 /* workaround until we get STC.returnScope reliably set correctly
5151 if (returnByRef)
5153 from &= ~STC.returnScope;
5154 to &= ~STC.returnScope;
5156 else
5158 from |= STC.returnScope;
5159 to |= STC.returnScope;
5161 return covariant[buildScopeRef(from)][buildScopeRef(to)];
5164 extern (D) private static bool[ScopeRef.max + 1][ScopeRef.max + 1] covariantInit() pure nothrow @nogc @safe
5166 /* Initialize covariant[][] with this:
5168 From\To n rs s
5169 None X
5170 ReturnScope X X
5171 Scope X X X
5173 From\To r rr rs rr-s r-rs
5174 Ref X X
5175 ReturnRef X
5176 RefScope X X X X X
5177 ReturnRef-Scope X X
5178 Ref-ReturnScope X X X
5180 bool[ScopeRef.max + 1][ScopeRef.max + 1] covariant;
5182 foreach (i; 0 .. ScopeRef.max + 1)
5184 covariant[i][i] = true;
5185 covariant[ScopeRef.RefScope][i] = true;
5187 covariant[ScopeRef.ReturnScope][ScopeRef.None] = true;
5188 covariant[ScopeRef.Scope ][ScopeRef.None] = true;
5189 covariant[ScopeRef.Scope ][ScopeRef.ReturnScope] = true;
5191 covariant[ScopeRef.Ref ][ScopeRef.ReturnRef] = true;
5192 covariant[ScopeRef.ReturnRef_Scope][ScopeRef.ReturnRef] = true;
5193 covariant[ScopeRef.Ref_ReturnScope][ScopeRef.Ref ] = true;
5194 covariant[ScopeRef.Ref_ReturnScope][ScopeRef.ReturnRef] = true;
5196 return covariant;
5199 extern (D) private static immutable bool[ScopeRef.max + 1][ScopeRef.max + 1] covariant = covariantInit();
5201 extern (D) bool opEquals(const Parameter other) const
5203 return this.storageClass == other.storageClass
5204 && this.type == other.type;
5208 /*************************************************************
5209 * For printing two types with qualification when necessary.
5210 * Params:
5211 * t1 = The first type to receive the type name for
5212 * t2 = The second type to receive the type name for
5213 * Returns:
5214 * The fully-qualified names of both types if the two type names are not the same,
5215 * or the unqualified names of both types if the two type names are the same.
5217 const(char*)[2] toAutoQualChars(Type t1, Type t2)
5219 auto s1 = t1.toChars();
5220 auto s2 = t2.toChars();
5221 // show qualification only if it's different
5222 if (!t1.equals(t2) && strcmp(s1, s2) == 0)
5224 s1 = t1.toPrettyChars(true);
5225 s2 = t2.toPrettyChars(true);
5227 return [s1, s2];
5232 * For each active modifier (MODFlags.const_, MODFlags.immutable_, etc) call `fp` with a
5233 * void* for the work param and a string representation of the attribute.
5235 void modifiersApply(const TypeFunction tf, void delegate(string) dg)
5237 immutable ubyte[4] modsArr = [MODFlags.const_, MODFlags.immutable_, MODFlags.wild, MODFlags.shared_];
5239 foreach (modsarr; modsArr)
5241 if (tf.mod & modsarr)
5243 dg(MODtoString(modsarr));
5249 * For each active attribute (ref/const/nogc/etc) call `fp` with a void* for the
5250 * work param and a string representation of the attribute.
5252 void attributesApply(const TypeFunction tf, void delegate(string) dg, TRUSTformat trustFormat = TRUSTformatDefault)
5254 if (tf.purity)
5255 dg("pure");
5256 if (tf.isnothrow)
5257 dg("nothrow");
5258 if (tf.isnogc)
5259 dg("@nogc");
5260 if (tf.isproperty)
5261 dg("@property");
5262 if (tf.isref)
5263 dg("ref");
5264 if (tf.isreturn && !tf.isreturninferred)
5265 dg("return");
5266 if (tf.isScopeQual && !tf.isscopeinferred)
5267 dg("scope");
5268 if (tf.islive)
5269 dg("@live");
5271 TRUST trustAttrib = tf.trust;
5273 if (trustAttrib == TRUST.default_)
5275 if (trustFormat != TRUSTformatSystem)
5276 return;
5277 trustAttrib = TRUST.system; // avoid calling with an empty string
5280 dg(trustToString(trustAttrib));
5284 * If the type is a class or struct, returns the symbol for it,
5285 * else null.
5287 AggregateDeclaration isAggregate(Type t)
5289 t = t.toBasetype();
5290 if (t.ty == Tclass)
5291 return (cast(TypeClass)t).sym;
5292 if (t.ty == Tstruct)
5293 return (cast(TypeStruct)t).sym;
5294 return null;
5297 /***************************************************
5298 * Determine if type t can be indexed or sliced given that it is not an
5299 * aggregate with operator overloads.
5300 * Params:
5301 * t = type to check
5302 * Returns:
5303 * true if an expression of type t can be e1 in an array expression
5305 bool isIndexableNonAggregate(Type t)
5307 t = t.toBasetype();
5308 return (t.ty == Tpointer || t.ty == Tsarray || t.ty == Tarray || t.ty == Taarray ||
5309 t.ty == Ttuple || t.ty == Tvector);
5312 /***************************************
5313 * Computes how a parameter may be returned.
5314 * Shrinking the representation is necessary because StorageClass is so wide
5315 * Params:
5316 * stc = storage class of parameter
5317 * Returns:
5318 * value from enum ScopeRef
5320 ScopeRef buildScopeRef(StorageClass stc) pure nothrow @nogc @safe
5322 if (stc & STC.out_)
5323 stc |= STC.ref_; // treat `out` and `ref` the same
5325 ScopeRef result;
5326 final switch (stc & (STC.ref_ | STC.scope_ | STC.return_))
5328 case 0: result = ScopeRef.None; break;
5330 /* can occur in case test/compilable/testsctreturn.d
5331 * related to https://issues.dlang.org/show_bug.cgi?id=20149
5332 * where inout adds `return` without `scope` or `ref`
5334 case STC.return_: result = ScopeRef.Return; break;
5336 case STC.ref_: result = ScopeRef.Ref; break;
5337 case STC.scope_: result = ScopeRef.Scope; break;
5338 case STC.return_ | STC.ref_: result = ScopeRef.ReturnRef; break;
5339 case STC.return_ | STC.scope_: result = ScopeRef.ReturnScope; break;
5340 case STC.ref_ | STC.scope_: result = ScopeRef.RefScope; break;
5342 case STC.return_ | STC.ref_ | STC.scope_:
5343 result = stc & STC.returnScope ? ScopeRef.Ref_ReturnScope
5344 : ScopeRef.ReturnRef_Scope;
5345 break;
5347 return result;
5351 * Classification of 'scope-return-ref' possibilities
5353 enum ScopeRef
5355 None,
5356 Scope,
5357 ReturnScope,
5358 Ref,
5359 ReturnRef,
5360 RefScope,
5361 ReturnRef_Scope,
5362 Ref_ReturnScope,
5363 Return,
5366 /*********************************
5367 * Give us a nice string for debugging purposes.
5368 * Params:
5369 * sr = value
5370 * Returns:
5371 * corresponding string
5373 const(char)* ScopeRefToChars(ScopeRef sr) pure nothrow @nogc @safe
5375 with (ScopeRef)
5377 static immutable char*[ScopeRef.max + 1] names =
5379 None: "None",
5380 Scope: "Scope",
5381 ReturnScope: "ReturnScope",
5382 Ref: "Ref",
5383 ReturnRef: "ReturnRef",
5384 RefScope: "RefScope",
5385 ReturnRef_Scope: "ReturnRef_Scope",
5386 Ref_ReturnScope: "Ref_ReturnScope",
5387 Return: "Return",
5389 return names[sr];
5394 * Creates an appropriate vector type for `tv` that will hold one boolean
5395 * result for each element of the vector type. The result of vector comparisons
5396 * is a single or doubleword mask of all 1s (comparison true) or all 0s
5397 * (comparison false). This SIMD mask type does not have an equivalent D type,
5398 * however its closest equivalent would be an integer vector of the same unit
5399 * size and length.
5401 * Params:
5402 * tv = The `TypeVector` to build a vector from.
5403 * Returns:
5404 * A vector type suitable for the result of a vector comparison operation.
5406 TypeVector toBooleanVector(TypeVector tv)
5408 Type telem = tv.elementType();
5409 switch (telem.ty)
5411 case Tvoid:
5412 case Tint8:
5413 case Tuns8:
5414 case Tint16:
5415 case Tuns16:
5416 case Tint32:
5417 case Tuns32:
5418 case Tint64:
5419 case Tuns64:
5420 // No need to build an equivalent mask type.
5421 return tv;
5423 case Tfloat32:
5424 telem = Type.tuns32;
5425 break;
5427 case Tfloat64:
5428 telem = Type.tuns64;
5429 break;
5431 default:
5432 assert(0);
5435 TypeSArray tsa = tv.basetype.isTypeSArray();
5436 assert(tsa !is null);
5438 return new TypeVector(new TypeSArray(telem, tsa.dim));
5441 /*************************************************
5442 * Dispatch to function based on static type of Type.
5444 mixin template VisitType(Result)
5446 Result VisitType(Type t)
5448 final switch (t.ty)
5450 case TY.Tvoid:
5451 case TY.Tint8:
5452 case TY.Tuns8:
5453 case TY.Tint16:
5454 case TY.Tuns16:
5455 case TY.Tint32:
5456 case TY.Tuns32:
5457 case TY.Tint64:
5458 case TY.Tuns64:
5459 case TY.Tfloat32:
5460 case TY.Tfloat64:
5461 case TY.Tfloat80:
5462 case TY.Timaginary32:
5463 case TY.Timaginary64:
5464 case TY.Timaginary80:
5465 case TY.Tcomplex32:
5466 case TY.Tcomplex64:
5467 case TY.Tcomplex80:
5468 case TY.Tbool:
5469 case TY.Tchar:
5470 case TY.Twchar:
5471 case TY.Tdchar:
5472 case TY.Tint128:
5473 case TY.Tuns128: mixin(visitTYCase("Basic"));
5474 case TY.Tarray: mixin(visitTYCase("DArray"));
5475 case TY.Tsarray: mixin(visitTYCase("SArray"));
5476 case TY.Taarray: mixin(visitTYCase("AArray"));
5477 case TY.Tpointer: mixin(visitTYCase("Pointer"));
5478 case TY.Treference: mixin(visitTYCase("Reference"));
5479 case TY.Tfunction: mixin(visitTYCase("Function"));
5480 case TY.Tident: mixin(visitTYCase("Identifier"));
5481 case TY.Tclass: mixin(visitTYCase("Class"));
5482 case TY.Tstruct: mixin(visitTYCase("Struct"));
5483 case TY.Tenum: mixin(visitTYCase("Enum"));
5484 case TY.Tdelegate: mixin(visitTYCase("Delegate"));
5485 case TY.Terror: mixin(visitTYCase("Error"));
5486 case TY.Tinstance: mixin(visitTYCase("Instance"));
5487 case TY.Ttypeof: mixin(visitTYCase("Typeof"));
5488 case TY.Ttuple: mixin(visitTYCase("Tuple"));
5489 case TY.Tslice: mixin(visitTYCase("Slice"));
5490 case TY.Treturn: mixin(visitTYCase("Return"));
5491 case TY.Tnull: mixin(visitTYCase("Null"));
5492 case TY.Tvector: mixin(visitTYCase("Vector"));
5493 case TY.Ttraits: mixin(visitTYCase("Traits"));
5494 case TY.Tmixin: mixin(visitTYCase("Mixin"));
5495 case TY.Tnoreturn: mixin(visitTYCase("Noreturn"));
5496 case TY.Ttag: mixin(visitTYCase("Tag"));
5497 case TY.Tnone: assert(0);
5502 /****************************************
5503 * CTFE-only helper function for VisitInitializer.
5504 * Params:
5505 * handler = string for the name of the visit handler
5506 * Returns: boilerplate code for a case
5508 pure string visitTYCase(string handler) @safe
5510 if (__ctfe)
5512 return
5514 enum isVoid = is(Result == void);
5515 auto tx = t.isType"~handler~"();
5516 static if (__traits(compiles, visit"~handler~"(tx)))
5518 static if (isVoid)
5520 visit"~handler~"(tx);
5521 return;
5523 else
5525 if (Result r = visit"~handler~"(tx))
5526 return r;
5527 return Result.init;
5530 else static if (__traits(compiles, visitDefaultCase(t)))
5532 static if (isVoid)
5534 visitDefaultCase(tx);
5535 return;
5537 else
5539 if (Result r = visitDefaultCase(t))
5540 return r;
5541 return Result.init;
5544 else
5545 static assert(0, "~handler~");
5548 assert(0);
5553 * Returns:
5554 * `TypeIdentifier` corresponding to `object.Throwable`
5556 TypeIdentifier getThrowable()
5558 auto tid = new TypeIdentifier(Loc.initial, Id.empty);
5559 tid.addIdent(Id.object);
5560 tid.addIdent(Id.Throwable);
5561 return tid;
5565 * Returns:
5566 * TypeIdentifier corresponding to `object.Exception`
5568 TypeIdentifier getException()
5570 auto tid = new TypeIdentifier(Loc.initial, Id.empty);
5571 tid.addIdent(Id.object);
5572 tid.addIdent(Id.Exception);
5573 return tid;