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
14 import core
.checkedint
;
15 import core
.stdc
.stdarg
;
16 import core
.stdc
.stdio
;
17 import core
.stdc
.stdlib
;
18 import core
.stdc
.string
;
21 import dmd
.arraytypes
;
25 import dmd
.declaration
;
32 import dmd
.expression
;
37 import dmd
.identifier
;
39 import dmd
.root
.ctfloat
;
40 import dmd
.common
.outbuffer
;
42 import dmd
.rootobject
;
43 import dmd
.root
.stringtable
;
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
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
):
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
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
;
119 return MATCH
.nomatch
;
123 /***************************
124 * Merge mod bits to form common mod.
126 MOD
MODmerge(MOD mod1
, MOD mod2
) pure nothrow @nogc @safe
131 //printf("MODmerge(1 = %x, 2 = %x)\n", mod1, mod2);
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_
;
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
;
156 /*********************************
157 * Store modifier name into buf.
159 void MODtoBuffer(ref OutBuffer buf
, MOD mod
) nothrow @safe
161 buf
.writestring(MODtoString(mod
));
164 /*********************************
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
;
176 string
MODtoString(MOD mod
) nothrow pure @safe
183 case MODFlags
.immutable_
:
186 case MODFlags
.shared_
:
189 case MODFlags
.shared_ | MODFlags
.const_
:
190 return "shared const";
192 case MODFlags
.const_
:
195 case MODFlags
.shared_ | MODFlags
.wild
:
196 return "shared 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
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_
)
246 if (mod
& MODFlags
.wild
)
248 if (mod
& MODFlags
.shared_
)
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
;
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
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
284 MOD mod
; // modifiers MODxxxx
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
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
);
408 final extern (D
) this(TY ty
) scope @safe
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
]);
427 fprintf(stderr
, "this = %s, ty = %d\n", toChars(), ty
);
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);
442 //if (deco && t && t.deco) printf("deco = '%s', t.deco = '%s'\n", deco, t.deco);
446 // kludge for template.isType()
447 override final DYNCAST
dyncast() const
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
;
460 final Mcache
* getMcache()
463 mcache
= cast(Mcache
*) mem
.xcalloc(Mcache
.sizeof
, 1);
467 /********************************
468 * For pretty-printing a type.
470 final override const(char)* toChars() const
472 return dmd
.hdrgen
.toChars(this);
476 final char* toPrettyChars(bool QualifyTypes
= false)
481 hgs
.fullQual
= QualifyTypes
;
483 toCBuffer(this, buf
, null, hgs
);
484 return buf
.extractChars();
489 stringtable
._init(14_000);
492 __gshared TY
* basetab
=
521 static Type
merge(Type t
)
523 import dmd
.basicmangle
: tyToDecoBuffer
;
528 if (t
.ty
== Tnoreturn
)
529 buf
.writestring("Nn");
531 tyToDecoBuffer(buf
, t
.ty
);
533 auto sv
= t
.stringtable
.update(buf
[]);
538 t
.deco
= cast(char*)sv
.toDchars();
544 for (size_t i
= 0; basetab
[i
] != Terror
; i
++)
546 Type t
= new TypeBasic(basetab
[i
]);
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
];
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
];
603 * Deinitializes the global state of the compiler.
605 * This can be used to restore the state set by `_init` to its original
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());
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
637 MODtoBuffer(buf
, mod
);
641 /*********************************
642 * Return this type's modifier name.
644 final char* modToChars() nothrow const
649 return buf
.extractChars();
657 // real, imaginary, or complex
698 /**************************
702 * Can we bitwise assign:
711 /**************************
712 * Returns true if T can be converted to boolean value.
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
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
782 (cast(TypeStruct
)t
).att
= AliasThisRec
.fwdref
;
784 (cast(TypeClass
)t
).att
= AliasThisRec
.fwdref
;
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.
798 if (!tn || ty
!= Tsarray
&& tn
.mod
== t
.nextOf().mod
)
806 case MODFlags
.const_
:
816 case MODFlags
.wildconst
:
821 case MODFlags
.shared_
:
826 case MODFlags
.shared_ | MODFlags
.const_
:
831 case MODFlags
.shared_ | MODFlags
.wild
:
836 case MODFlags
.shared_ | MODFlags
.wildconst
:
841 case MODFlags
.immutable_
:
850 assert(mod
!= t
.mod
);
862 case MODFlags
.const_
:
872 case MODFlags
.wildconst
:
874 t
.mcache
.wcto
= this;
877 case MODFlags
.shared_
:
882 case MODFlags
.shared_ | MODFlags
.const_
:
884 t
.mcache
.scto
= this;
887 case MODFlags
.shared_ | MODFlags
.wild
:
889 t
.mcache
.swto
= this;
892 case MODFlags
.shared_ | MODFlags
.wildconst
:
894 t
.mcache
.swcto
= this;
897 case MODFlags
.immutable_
:
900 t
.mcache
.cto
.getMcache().ito
= this;
902 t
.mcache
.sto
.getMcache().ito
= this;
904 t
.mcache
.scto
.getMcache().ito
= this;
906 t
.mcache
.wto
.getMcache().ito
= this;
908 t
.mcache
.wcto
.getMcache().ito
= this;
910 t
.mcache
.swto
.getMcache().ito
= this;
912 t
.mcache
.swcto
.getMcache().ito
= this;
921 //printf("fixTo: %s, %s\n", toChars(), t.toChars());
924 /***************************
925 * Look for bugs in constructing types.
927 extern (D
) final void check()
935 assert(cto
.mod
== MODFlags
.const_
);
937 assert(ito
.mod
== MODFlags
.immutable_
);
939 assert(sto
.mod
== MODFlags
.shared_
);
941 assert(scto
.mod
== (MODFlags
.shared_ | MODFlags
.const_
));
943 assert(wto
.mod
== MODFlags
.wild
);
945 assert(wcto
.mod
== MODFlags
.wildconst
);
947 assert(swto
.mod
== (MODFlags
.shared_ | MODFlags
.wild
));
949 assert(swcto
.mod
== (MODFlags
.shared_ | MODFlags
.wildconst
));
952 case MODFlags
.const_
:
954 assert(cto
.mod
== 0);
956 assert(ito
.mod
== MODFlags
.immutable_
);
958 assert(sto
.mod
== MODFlags
.shared_
);
960 assert(scto
.mod
== (MODFlags
.shared_ | MODFlags
.const_
));
962 assert(wto
.mod
== MODFlags
.wild
);
964 assert(wcto
.mod
== MODFlags
.wildconst
);
966 assert(swto
.mod
== (MODFlags
.shared_ | MODFlags
.wild
));
968 assert(swcto
.mod
== (MODFlags
.shared_ | MODFlags
.wildconst
));
973 assert(cto
.mod
== MODFlags
.const_
);
975 assert(ito
.mod
== MODFlags
.immutable_
);
977 assert(sto
.mod
== MODFlags
.shared_
);
979 assert(scto
.mod
== (MODFlags
.shared_ | MODFlags
.const_
));
981 assert(wto
.mod
== 0);
983 assert(wcto
.mod
== MODFlags
.wildconst
);
985 assert(swto
.mod
== (MODFlags
.shared_ | MODFlags
.wild
));
987 assert(swcto
.mod
== (MODFlags
.shared_ | MODFlags
.wildconst
));
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
));
1001 case MODFlags
.shared_
:
1003 assert(cto
.mod
== MODFlags
.const_
);
1005 assert(ito
.mod
== MODFlags
.immutable_
);
1007 assert(sto
.mod
== 0);
1009 assert(scto
.mod
== (MODFlags
.shared_ | MODFlags
.const_
));
1011 assert(wto
.mod
== MODFlags
.wild
);
1013 assert(wcto
.mod
== MODFlags
.wildconst
);
1015 assert(swto
.mod
== (MODFlags
.shared_ | MODFlags
.wild
));
1017 assert(swcto
.mod
== (MODFlags
.shared_ | MODFlags
.wildconst
));
1020 case MODFlags
.shared_ | MODFlags
.const_
:
1022 assert(cto
.mod
== MODFlags
.const_
);
1024 assert(ito
.mod
== MODFlags
.immutable_
);
1026 assert(sto
.mod
== MODFlags
.shared_
);
1028 assert(scto
.mod
== 0);
1030 assert(wto
.mod
== MODFlags
.wild
);
1032 assert(wcto
.mod
== MODFlags
.wildconst
);
1034 assert(swto
.mod
== (MODFlags
.shared_ | MODFlags
.wild
));
1036 assert(swcto
.mod
== (MODFlags
.shared_ | MODFlags
.wildconst
));
1039 case MODFlags
.shared_ | MODFlags
.wild
:
1041 assert(cto
.mod
== MODFlags
.const_
);
1043 assert(ito
.mod
== MODFlags
.immutable_
);
1045 assert(sto
.mod
== MODFlags
.shared_
);
1047 assert(scto
.mod
== (MODFlags
.shared_ | MODFlags
.const_
));
1049 assert(wto
.mod
== MODFlags
.wild
);
1051 assert(wcto
.mod
== MODFlags
.wildconst
);
1053 assert(swto
.mod
== 0);
1055 assert(swcto
.mod
== (MODFlags
.shared_ | MODFlags
.wildconst
));
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);
1069 case MODFlags
.immutable_
:
1071 assert(cto
.mod
== MODFlags
.const_
);
1073 assert(ito
.mod
== 0);
1075 assert(sto
.mod
== MODFlags
.shared_
);
1077 assert(scto
.mod
== (MODFlags
.shared_ | MODFlags
.const_
));
1079 assert(wto
.mod
== MODFlags
.wild
);
1081 assert(wcto
.mod
== MODFlags
.wildconst
);
1083 assert(swto
.mod
== (MODFlags
.shared_ | MODFlags
.wild
));
1085 assert(swcto
.mod
== (MODFlags
.shared_ | MODFlags
.wildconst
));
1093 if (tn
&& ty
!= Tfunction
&& tn
.ty
!= Tfunction
&& ty
!= Tenum
)
1095 // Verify transitivity
1099 case MODFlags
.const_
:
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
);
1117 /*************************************
1118 * Apply STCxxxx bits to existing type.
1119 * Use *before* semantic analysis is run.
1121 extern (D
) final Type
addSTC(StorageClass
stc)
1124 if (t
.isImmutable())
1127 else if (stc & STC
.immutable_
)
1129 t
= t
.makeImmutable();
1133 if ((stc & STC
.shared_
) && !t
.isShared())
1138 t
= t
.makeSharedWildConst();
1140 t
= t
.makeSharedWild();
1145 t
= t
.makeSharedConst();
1150 if ((stc & STC
.const_
) && !t
.isConst())
1155 t
= t
.makeSharedWildConst();
1157 t
= t
.makeSharedConst();
1162 t
= t
.makeWildConst();
1167 if ((stc & STC
.wild
) && !t
.isWild())
1172 t
= t
.makeSharedWildConst();
1174 t
= t
.makeSharedWild();
1179 t
= t
.makeWildConst();
1188 final bool hasDeprecatedAliasThis()
1190 auto ad
= isAggregate(this);
1191 return ad
&& ad
.aliasthis
&& (ad
.aliasthis
.isDeprecated || ad
.aliasthis
.sym
.isDeprecated
);
1196 //printf("Type::makeConst() %p, %s\n", this, toChars());
1197 if (mcache
&& mcache
.cto
)
1199 Type t
= this.nullAttributes();
1200 t
.mod
= MODFlags
.const_
;
1201 //printf("-Type::makeConst() %p, %s\n", t, toChars());
1205 Type
makeImmutable()
1207 if (mcache
&& mcache
.ito
)
1209 Type t
= this.nullAttributes();
1210 t
.mod
= MODFlags
.immutable_
;
1216 if (mcache
&& mcache
.sto
)
1218 Type t
= this.nullAttributes();
1219 t
.mod
= MODFlags
.shared_
;
1223 Type
makeSharedConst()
1225 if (mcache
&& mcache
.scto
)
1227 Type t
= this.nullAttributes();
1228 t
.mod
= MODFlags
.shared_ | MODFlags
.const_
;
1234 if (mcache
&& mcache
.wto
)
1236 Type t
= this.nullAttributes();
1237 t
.mod
= MODFlags
.wild
;
1241 Type
makeWildConst()
1243 if (mcache
&& mcache
.wcto
)
1245 Type t
= this.nullAttributes();
1246 t
.mod
= MODFlags
.wildconst
;
1250 Type
makeSharedWild()
1252 if (mcache
&& mcache
.swto
)
1254 Type t
= this.nullAttributes();
1255 t
.mod
= MODFlags
.shared_ | MODFlags
.wild
;
1259 Type
makeSharedWildConst()
1261 if (mcache
&& mcache
.swcto
)
1262 return mcache
.swcto
;
1263 Type t
= this.nullAttributes();
1264 t
.mod
= MODFlags
.shared_ | MODFlags
.wildconst
;
1270 Type t
= this.nullAttributes();
1271 t
.mod
= mod
& MODFlags
.shared_
;
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.
1285 return ((te
= isTypeEnum()) !is null) ? te
.toBasetype2() : this;
1288 /********************************
1289 * Determine if 'this' can be implicitly converted
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
))
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.
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());
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.
1325 * t = corresponding parameter type
1326 * isRef = parameter is `ref` or `out`
1330 MOD
deduceWild(Type t
, bool isRef
)
1332 //printf("Type::deduceWild this = '%s', tprm = '%s'\n", toChars(), tprm.toChars());
1336 return MODFlags
.immutable_
;
1337 else if (isWildConst())
1339 if (t
.isWildConst())
1340 return MODFlags
.wild
;
1342 return MODFlags
.wildconst
;
1345 return MODFlags
.wild
;
1347 return MODFlags
.const_
;
1348 else if (isMutable())
1349 return MODFlags
.mutable
;
1356 inout(ClassDeclaration
) isClassHandle() inout
1361 /************************************
1362 * Return alignment to use for this type.
1364 structalign_t
alignment()
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.
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.
1405 bool hasVoidInitPointers()
1410 /*************************************
1411 * Detect if this is an unsafe type because of the presence of `@system` members
1415 bool hasSystemFields()
1420 /***************************************
1421 * Returns: true if type has any invariants
1425 //printf("Type::hasInvariant() %s, %d\n", toChars(), ty);
1429 /*************************************
1430 * If this is a type of something, return that something.
1437 /*************************************
1438 * If this is a type of static array, return its base element type.
1440 final Type
baseElemOf()
1442 Type t
= toBasetype();
1444 while ((tsa
= t
.isTypeSArray()) !is null)
1445 t
= tsa
.next
.toBasetype();
1449 /*******************************************
1450 * Compute number of elements for a (possibly multidimensional) static array,
1451 * or 1 for other types.
1453 * loc = for error message
1455 * number of elements, uint.max on overflow
1457 final uint numberOfElems(const ref Loc loc
)
1459 //printf("Type::numberOfElems()\n");
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
);
1471 tb
= (cast(TypeSArray
)tb
).next
;
1476 /****************************************
1477 * Return the mask that an integral type will
1480 extern (D
) final uinteger_t
sizemask()
1483 switch (toBasetype().ty
)
1505 m
= 0xFFFFFFFFFFFFFFFFUL
;
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()
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()
1531 /*********************************
1539 // For eliminating dynamic_cast
1540 TypeBasic
isTypeBasic()
1545 final pure inout nothrow @nogc
1548 * Is this type a pointer to a function?
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
1560 * Is this type a function, delegate, or pointer to a function?
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
:
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
)
1609 final TypeFunction
toTypeFunction()
1611 if (ty
!= Tfunction
)
1613 return cast(TypeFunction
)this;
1616 extern (D
) static Types
* arraySyntaxCopy(Types
* types
)
1621 a
= new Types(types
.length
);
1622 foreach (i
, t
; *types
)
1624 (*a
)[i
] = t ? t
.syntaxCopy() : null;
1631 /***********************************************************
1633 extern (C
++) final class TypeError
: Type
1635 extern (D
) this() @safe
1640 override const(char)* kind() const
1645 override TypeError
syntaxCopy()
1647 // No semantic analysis done, no need to copy
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
)
1667 /***********************************************************
1669 extern (C
++) abstract class TypeNext
: Type
1673 final extern (D
) this(TY ty
, Type next
) @safe
1679 override final int hasWild() const
1681 if (ty
== Tfunction
)
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()
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_
);
1706 TypeNext t
= cast(TypeNext
)Type
.makeConst();
1707 if (ty
!= Tfunction
&& next
.ty
!= Tfunction
&& !next
.isImmutable())
1709 if (next
.isShared())
1712 t
.next
= next
.sharedWildConstOf();
1714 t
.next
= next
.sharedConstOf();
1719 t
.next
= next
.wildConstOf();
1721 t
.next
= next
.constOf();
1724 //printf("TypeNext::makeConst() returns %p, %s\n", t, t.toChars());
1728 override final Type
makeImmutable()
1730 //printf("TypeNext::makeImmutable() %s\n", toChars());
1731 if (mcache
&& mcache
.ito
)
1733 assert(mcache
.ito
.isImmutable());
1736 TypeNext t
= cast(TypeNext
)Type
.makeImmutable();
1737 if (ty
!= Tfunction
&& next
.ty
!= Tfunction
&& !next
.isImmutable())
1739 t
.next
= next
.immutableOf();
1744 override final Type
makeShared()
1746 //printf("TypeNext::makeShared() %s\n", toChars());
1747 if (mcache
&& mcache
.sto
)
1749 assert(mcache
.sto
.mod
== MODFlags
.shared_
);
1752 TypeNext t
= cast(TypeNext
)Type
.makeShared();
1753 if (ty
!= Tfunction
&& next
.ty
!= Tfunction
&& !next
.isImmutable())
1758 t
.next
= next
.sharedWildConstOf();
1760 t
.next
= next
.sharedWildOf();
1765 t
.next
= next
.sharedConstOf();
1767 t
.next
= next
.sharedOf();
1770 //printf("TypeNext::makeShared() returns %p, %s\n", t, t.toChars());
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_
));
1782 TypeNext t
= cast(TypeNext
)Type
.makeSharedConst();
1783 if (ty
!= Tfunction
&& next
.ty
!= Tfunction
&& !next
.isImmutable())
1786 t
.next
= next
.sharedWildConstOf();
1788 t
.next
= next
.sharedConstOf();
1790 //printf("TypeNext::makeSharedConst() returns %p, %s\n", t, t.toChars());
1794 override final Type
makeWild()
1796 //printf("TypeNext::makeWild() %s\n", toChars());
1797 if (mcache
&& mcache
.wto
)
1799 assert(mcache
.wto
.mod
== MODFlags
.wild
);
1802 TypeNext t
= cast(TypeNext
)Type
.makeWild();
1803 if (ty
!= Tfunction
&& next
.ty
!= Tfunction
&& !next
.isImmutable())
1805 if (next
.isShared())
1808 t
.next
= next
.sharedWildConstOf();
1810 t
.next
= next
.sharedWildOf();
1815 t
.next
= next
.wildConstOf();
1817 t
.next
= next
.wildOf();
1820 //printf("TypeNext::makeWild() returns %p, %s\n", t, t.toChars());
1824 override final Type
makeWildConst()
1826 //printf("TypeNext::makeWildConst() %s\n", toChars());
1827 if (mcache
&& mcache
.wcto
)
1829 assert(mcache
.wcto
.mod
== MODFlags
.wildconst
);
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();
1838 t
.next
= next
.wildConstOf();
1840 //printf("TypeNext::makeWildConst() returns %p, %s\n", t, t.toChars());
1844 override final Type
makeSharedWild()
1846 //printf("TypeNext::makeSharedWild() %s\n", toChars());
1847 if (mcache
&& mcache
.swto
)
1849 assert(mcache
.swto
.isSharedWild());
1852 TypeNext t
= cast(TypeNext
)Type
.makeSharedWild();
1853 if (ty
!= Tfunction
&& next
.ty
!= Tfunction
&& !next
.isImmutable())
1856 t
.next
= next
.sharedWildConstOf();
1858 t
.next
= next
.sharedWildOf();
1860 //printf("TypeNext::makeSharedWild() returns %p, %s\n", t, t.toChars());
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());
1881 override final Type
makeMutable()
1883 //printf("TypeNext::makeMutable() %p, %s\n", this, toChars());
1884 TypeNext t
= cast(TypeNext
)Type
.makeMutable();
1887 t
.next
= next
.mutableOf();
1889 //printf("TypeNext::makeMutable() returns %p, %s\n", t, t.toChars());
1893 override MATCH
constConv(Type to
)
1895 //printf("TypeNext::constConv from = %s, to = %s\n", toChars(), to.toChars());
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
;
1907 if (to
.isConst()) // whole tail const conversion
1909 // Recursive shared level check
1910 m
= next
.constConv(tn
);
1911 if (m
== MATCH
.exact
)
1916 //printf("\tnext => %s, to.next => %s\n", next.toChars(), tn.toChars());
1917 m
= next
.equals(tn
) ? MATCH
.constant
: MATCH
.nomatch
;
1922 override final MOD
deduceWild(Type t
, bool isRef
)
1924 if (ty
== Tfunction
)
1929 Type tn
= t
.nextOf();
1930 if (!isRef
&& (ty
== Tarray || ty
== Tpointer
) && tn
)
1932 wm
= next
.deduceWild(tn
, true);
1934 wm
= Type
.deduceWild(t
, true);
1938 wm
= Type
.deduceWild(t
, isRef
);
1940 wm
= next
.deduceWild(tn
, true);
1946 final void transitive()
1948 /* Invoke transitivity of type attributes
1950 next
= next
.addMod(mod
);
1953 override void accept(Visitor v
)
1959 /***********************************************************
1961 extern (C
++) final class TypeBasic
: Type
1963 const(char)* dstring
;
1966 extern (D
) this(TY ty
) scope
1974 d
= Token
.toChars(TOK
.void_
);
1978 d
= Token
.toChars(TOK
.int8
);
1979 flags |
= TFlags
.integral
;
1983 d
= Token
.toChars(TOK
.uns8
);
1984 flags |
= TFlags
.integral | TFlags
.unsigned
;
1988 d
= Token
.toChars(TOK
.int16
);
1989 flags |
= TFlags
.integral
;
1993 d
= Token
.toChars(TOK
.uns16
);
1994 flags |
= TFlags
.integral | TFlags
.unsigned
;
1998 d
= Token
.toChars(TOK
.int32
);
1999 flags |
= TFlags
.integral
;
2003 d
= Token
.toChars(TOK
.uns32
);
2004 flags |
= TFlags
.integral | TFlags
.unsigned
;
2008 d
= Token
.toChars(TOK
.float32
);
2009 flags |
= TFlags
.floating | TFlags
.real_
;
2013 d
= Token
.toChars(TOK
.int64
);
2014 flags |
= TFlags
.integral
;
2018 d
= Token
.toChars(TOK
.uns64
);
2019 flags |
= TFlags
.integral | TFlags
.unsigned
;
2023 d
= Token
.toChars(TOK
.int128
);
2024 flags |
= TFlags
.integral
;
2028 d
= Token
.toChars(TOK
.uns128
);
2029 flags |
= TFlags
.integral | TFlags
.unsigned
;
2033 d
= Token
.toChars(TOK
.float64
);
2034 flags |
= TFlags
.floating | TFlags
.real_
;
2038 d
= Token
.toChars(TOK
.float80
);
2039 flags |
= TFlags
.floating | TFlags
.real_
;
2043 d
= Token
.toChars(TOK
.imaginary32
);
2044 flags |
= TFlags
.floating | TFlags
.imaginary
;
2048 d
= Token
.toChars(TOK
.imaginary64
);
2049 flags |
= TFlags
.floating | TFlags
.imaginary
;
2053 d
= Token
.toChars(TOK
.imaginary80
);
2054 flags |
= TFlags
.floating | TFlags
.imaginary
;
2058 d
= Token
.toChars(TOK
.complex32
);
2059 flags |
= TFlags
.floating | TFlags
.complex
;
2063 d
= Token
.toChars(TOK
.complex64
);
2064 flags |
= TFlags
.floating | TFlags
.complex
;
2068 d
= Token
.toChars(TOK
.complex80
);
2069 flags |
= TFlags
.floating | TFlags
.complex
;
2074 flags |
= TFlags
.integral | TFlags
.unsigned
;
2078 d
= Token
.toChars(TOK
.char_
);
2079 flags |
= TFlags
.integral | TFlags
.unsigned
;
2083 d
= Token
.toChars(TOK
.wchar_
);
2084 flags |
= TFlags
.integral | TFlags
.unsigned
;
2088 d
= Token
.toChars(TOK
.dchar_
);
2089 flags |
= TFlags
.integral | TFlags
.unsigned
;
2100 override const(char)* kind() const
2105 override TypeBasic
syntaxCopy()
2107 // No semantic analysis done on basic types, no need to copy
2111 override uinteger_t
size(const ref Loc loc
)
2114 //printf("TypeBasic::size()\n");
2143 size
= target
.realsize
;
2157 size
= target
.realsize
* 2;
2161 //size = Type::size(); // error message
2184 //printf("TypeBasic::size() = %d\n", 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());
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
;
2244 return MATCH
.convert
;
2247 if (ty
== Tvoid || to
.ty
== Tvoid
)
2248 return MATCH
.nomatch
;
2250 return MATCH
.nomatch
;
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
;
2263 /* Special enums that allow implicit conversions to them
2264 * with a MATCH.convert
2266 tob
= to
.toBasetype().isTypeBasic();
2269 return MATCH
.nomatch
;
2272 tob
= to
.isTypeBasic();
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
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
)
2343 // For eliminating dynamic_cast
2344 override TypeBasic
isTypeBasic()
2349 override void accept(Visitor v
)
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]
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
2365 extern (D
) this(Type basetype
) @safe
2368 this.basetype
= basetype
;
2371 static TypeVector
create(Type basetype
) @safe
2373 return new TypeVector(basetype
);
2376 override const(char)* kind() const
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()
2422 override MATCH
implicitConvTo(Type to
)
2424 //printf("TypeVector::implicitConvTo(%s) from %s\n", to.toChars(), toChars());
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);
2452 ve
.dim
= cast(int)(basetype
.size(loc
) / elementType().size(loc
));
2456 TypeBasic
elementType()
2458 assert(basetype
.ty
== Tsarray
);
2459 TypeSArray t
= cast(TypeSArray
)basetype
;
2460 TypeBasic tb
= t
.nextOf().isTypeBasic();
2465 override bool isZeroInit(const ref Loc loc
)
2467 return basetype
.isZeroInit(loc
);
2470 override void accept(Visitor v
)
2476 /***********************************************************
2478 extern (C
++) abstract class TypeArray
: TypeNext
2480 final extern (D
) this(TY ty
, Type next
) @safe
2485 override void accept(Visitor v
)
2491 /***********************************************************
2492 * Static array, one with a fixed dimension
2494 extern (C
++) final class TypeSArray
: TypeArray
2498 extern (D
) this(Type t
, Expression dim
) @safe
2501 //printf("TypeSArray(%s)\n", dim.toChars());
2505 extern (D
) this(Type t
) // for incomplete type
2508 //printf("TypeSArray()\n");
2509 this.dim
= new IntegerExp(0);
2512 override const(char)* kind() const
2517 override TypeSArray
syntaxCopy()
2519 Type t
= next
.syntaxCopy();
2520 Expression e
= dim
.syntaxCopy();
2521 auto result
= new TypeSArray(t
, e
);
2527 * C11 6.7.6.2-4 incomplete array type
2528 * Returns: true if incomplete type
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
;
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())
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
&&
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
2630 if (m
>= MATCH
.constant
)
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
);
2652 elementinit
= next
.defaultInitLiteral(loc
);
2653 auto elements
= new Expressions(d
);
2654 foreach (ref e
; *elements
)
2656 auto ae
= new ArrayLiteralExp(Loc
.initial
, this, elementinit
, elements
);
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
)
2699 /***********************************************************
2700 * Dynamic array, no dimension
2702 extern (C
++) final class TypeDArray
: TypeArray
2704 extern (D
) this(Type t
) @safe
2707 //printf("TypeDArray(t = %p)\n", t);
2710 override const(char)* kind() const
2715 override TypeDArray
syntaxCopy()
2717 Type t
= next
.syntaxCopy();
2721 auto result
= new TypeDArray(t
);
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
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
)
2750 override bool isBoolean()
2755 override MATCH
implicitConvTo(Type to
)
2757 //printf("TypeDArray::implicitConvTo(to = %s) this = %s\n", to.toChars(), toChars());
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
)
2781 return Type
.implicitConvTo(to
);
2784 override void accept(Visitor v
)
2790 /***********************************************************
2792 extern (C
++) final class TypeAArray
: TypeArray
2794 Type index
; // key type
2797 extern (D
) this(Type t
, Type index
) @safe
2803 static TypeAArray
create(Type t
, Type index
) @safe
2805 return new TypeAArray(t
, index
);
2808 override const(char)* kind() const
2813 override TypeAArray
syntaxCopy()
2815 Type t
= next
.syntaxCopy();
2816 Type ti
= index
.syntaxCopy();
2817 if (t
== next
&& ti
== index
)
2820 auto result
= new TypeAArray(t
, ti
);
2825 override uinteger_t
size(const ref Loc loc
)
2827 return target
.ptrsize
;
2830 override bool isZeroInit(const ref Loc loc
)
2835 override bool isBoolean()
2840 override MATCH
implicitConvTo(Type to
)
2842 //printf("TypeAArray::implicitConvTo(to = %s) this = %s\n", to.toChars(), toChars());
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
)
2882 /***********************************************************
2884 extern (C
++) final class TypePointer
: TypeNext
2886 extern (D
) this(Type t
) @safe
2891 static TypePointer
create(Type t
) @safe
2893 return new TypePointer(t
);
2896 override const(char)* kind() const
2901 override TypePointer
syntaxCopy()
2903 Type t
= next
.syntaxCopy();
2907 auto result
= new TypePointer(t
);
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());
2923 // Only convert between pointers
2924 auto tp
= to
.isTypePointer();
2926 return MATCH
.nomatch
;
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
)
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
);
2963 return MATCH
.nomatch
;
2965 return TypeNext
.constConv(to
);
2968 override bool isscalar()
2973 override bool isZeroInit(const ref Loc loc
)
2978 override void accept(Visitor v
)
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
2999 override TypeReference
syntaxCopy()
3001 Type t
= next
.syntaxCopy();
3005 auto result
= new TypeReference(t
);
3010 override uinteger_t
size(const ref Loc loc
)
3012 return target
.ptrsize
;
3015 override bool isZeroInit(const ref Loc loc
)
3020 override void accept(Visitor v
)
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
;
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;
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;
3093 if (stc & STC
.property
)
3094 this.isproperty
= 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_
;
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
3130 override TypeFunction
syntaxCopy()
3132 Type treturn
= next ? next
.syntaxCopy() : null;
3133 auto t
= new TypeFunction(parameterList
.syntaxCopy(), treturn
, linkage
);
3135 t
.isnothrow
= isnothrow
;
3139 t
.isproperty
= isproperty
;
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
;
3154 /********************************************
3155 * Return true if there are lazy parameters.
3157 bool hasLazyParameters()
3159 foreach (i
, fparam
; parameterList
)
3161 if (fparam
.isLazy())
3167 /*******************************
3168 * Check for `extern (D) U func(T t, ...)` variadic function type,
3169 * which has `_arguments[]` added as the first argument.
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
)
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.
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
);
3203 bool hasNamedArgs
= false;
3204 foreach (i
, arg
; args
)
3211 auto name
= i
< names
.length ? names
[i
] : null;
3214 hasNamedArgs
= true;
3215 const pi
= findParameterIndex(name
);
3219 *pMessage
= getMatchError("no parameter named `%s`", name
.toChars());
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());
3233 while (ci
>= newArgs
.length
)
3240 *pMessage
= getMatchError("parameter `%s` assigned twice", parameterList
[ci
].toChars());
3243 (*newArgs
)[ci
++] = arg
;
3245 foreach (i
, arg
; (*newArgs
)[])
3247 if (arg || parameterList
[i
].defaultArg
)
3250 if (parameterList
.varargs
!= VarArg
.none
&& i
+ 1 == newArgs
.length
)
3254 *pMessage
= getMatchError("missing argument for parameter #%d: `%s`",
3255 i
+ 1, parameterToChars(parameterList
[i
], this, false));
3258 // strip trailing nulls from default arguments
3259 size_t e
= newArgs
.length
;
3260 while (e
> 0 && (*newArgs
)[e
- 1] is null)
3269 + Checks whether this function type is convertible to ` to`
3270 + when used in a function pointer / delegate.
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
)
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.
3296 * class C : Object, I {}
3297 * I function() dg = function C() {} // should be error
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");
3327 if (tb
.ty
== Ttuple
)
3329 error(loc
, "functions cannot return a sequence (use `std.typecons.Tuple`)");
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());
3343 if (tb
.ty
== Terror
)
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
)
3380 * Look for the index of parameter `ident` in the parameter list
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
)
3397 /***********************************************************
3399 extern (C
++) final class TypeDelegate
: TypeNext
3401 // .next is a TypeFunction
3403 extern (D
) this(TypeFunction t
) @safe
3405 super(Tfunction
, t
);
3409 static TypeDelegate
create(TypeFunction t
) @safe
3411 return new TypeDelegate(t
);
3414 override const(char)* kind() const
3419 override TypeDelegate
syntaxCopy()
3421 auto tf
= next
.syntaxCopy().isTypeFunction();
3425 auto result
= new TypeDelegate(tf
);
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
))
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
)
3460 return MATCH
.nomatch
;
3463 override bool isZeroInit(const ref Loc loc
)
3468 override bool isBoolean()
3473 override void accept(Visitor v
)
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
3488 /// The expression to resolve as type or symbol.
3490 /// Cached type/symbol after semantic analysis.
3493 final extern (D
) this(const ref Loc loc
, TraitsExp exp
) @safe
3500 override const(char)* kind() const
3505 override TypeTraits
syntaxCopy()
3507 TraitsExp te
= exp
.syntaxCopy();
3508 TypeTraits tt
= new TypeTraits(loc
, te
);
3513 override void accept(Visitor v
)
3518 override uinteger_t
size(const ref Loc loc
)
3520 return SIZE_INVALID
;
3525 * Implements mixin types.
3527 * Semantic analysis will convert it to a real type.
3529 extern (C
++) final class TypeMixin
: Type
3533 RootObject obj
; // cached result of semantic analysis.
3535 extern (D
) this(const ref Loc loc
, Expressions
* exps
) @safe
3542 override const(char)* kind() const
3547 override TypeMixin
syntaxCopy()
3549 return new TypeMixin(loc
, Expression
.arraySyntaxCopy(exps
));
3552 override void accept(Visitor v
)
3558 /***********************************************************
3560 extern (C
++) abstract class TypeQualified
: Type
3564 // array of Identifier and TypeInstance,
3565 // representing ident.ident!tiargs.ident. ... etc.
3568 final extern (D
) this(TY ty
, 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())
3590 Expression e
= cast(Expression
)id
;
3595 TemplateInstance ti
= cast(TemplateInstance
)id
;
3596 ti
= ti
.syntaxCopy(null);
3600 Type tx
= cast(Type
)id
;
3601 tx
= tx
.syntaxCopy();
3609 case templateparameter
:
3616 extern (D
) final void addIdent(Identifier ident
)
3621 extern (D
) final void addInst(TemplateInstance inst
)
3626 extern (D
) final void addIndex(RootObject 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
)
3643 /***********************************************************
3645 extern (C
++) final class TypeIdentifier
: TypeQualified
3649 // The symbol representing this identifier, before alias resolution
3650 Dsymbol originalSymbol
;
3652 extern (D
) this(const ref Loc loc
, Identifier 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);
3676 override void accept(Visitor v
)
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
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);
3709 override void accept(Visitor v
)
3715 /***********************************************************
3717 extern (C
++) final class TypeTypeof
: TypeQualified
3722 extern (D
) this(const ref Loc loc
, Expression exp
)
3724 super(Ttypeof
, loc
);
3728 override const(char)* kind() const
3733 override TypeTypeof
syntaxCopy()
3735 //printf("TypeTypeof::syntaxCopy() %s\n", toChars());
3736 auto t
= new TypeTypeof(loc
, exp
.syntaxCopy());
3737 t
.syntaxCopyHelper(this);
3742 override uinteger_t
size(const ref Loc loc
)
3745 return exp
.type
.size(loc
);
3747 return TypeQualified
.size(loc
);
3750 override void accept(Visitor v
)
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
3770 override TypeReturn
syntaxCopy()
3772 auto t
= new TypeReturn(loc
);
3773 t
.syntaxCopyHelper(this);
3778 override void accept(Visitor v
)
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
3798 static TypeStruct
create(StructDeclaration sym
) @safe
3800 return new TypeStruct(sym
);
3803 override const(char)* kind() const
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()
3824 override structalign_t
alignment()
3826 if (sym
.alignment
.isUnknown())
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());
3842 if (sym
.sizeok
!= Sizeok
.done
)
3843 return ErrorExp
.get();
3845 auto structelems
= new Expressions(sym
.nonHiddenFields());
3847 foreach (j
; 0 .. structelems
.length
)
3849 VarDeclaration vd
= sym
.fields
[j
];
3853 error(loc
, "circular reference to `%s`", vd
.toPrettyChars());
3854 return ErrorExp
.get();
3856 if (vd
.offset
< offset || vd
.type
.size() == 0)
3860 if (vd
._init
.isVoidInitializer())
3863 e
= vd
.getConstInitializer(false);
3866 e
= vd
.type
.defaultInitLiteral(loc
);
3867 if (e
&& e
.op
== EXP
.error
)
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;
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());
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.
3923 assignable
= v
.type
.isMutable() && v
.type
.isAssignable();
3925 //printf(" -> assignable = %d\n", assignable);
3931 override bool isBoolean()
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
3951 scope(exit
) inuse
= false;
3956 for (size_t i
= 0; i
< sym
.fields
.length
; i
++)
3958 VarDeclaration v
= sym
.fields
[i
];
3959 if (!v
.isDataseg() && v
.type
.needsNested())
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
)
3990 if (ty
== to
.ty
&& sym
== (cast(TypeStruct
)to
).sym
)
3992 m
= MATCH
.exact
; // exact match
3996 if (MODimplicitConv(mod
, to
.mod
))
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
];
4011 else if (v
.offset
== offset
)
4013 if (m
> MATCH
.nomatch
)
4018 if (m
== MATCH
.nomatch
)
4023 Type tvf
= v
.type
.addMod(mod
);
4026 Type tv
= v
.type
.addMod(to
.mod
);
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
)
4034 if (mf
< m
) // if field match is worse
4044 extern (D
) MATCH
implicitConvToThroughAliasThis(Type to
)
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
);
4056 m
= MATCH
.nomatch
; // no match
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
)
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
);
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
);
4097 override void accept(Visitor v
)
4103 /***********************************************************
4105 extern (C
++) final class TypeEnum
: Type
4107 EnumDeclaration sym
;
4109 extern (D
) this(EnumDeclaration sym
) @safe
4115 override const(char)* kind() const
4120 override TypeEnum
syntaxCopy()
4125 override uinteger_t
size(const ref Loc loc
)
4127 return sym
.getMemtype(loc
).size(loc
);
4132 return sym
.getMemtype(Loc
.initial
);
4135 override uint alignsize()
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
)
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
4217 m
= MATCH
.nomatch
; // no match
4221 override MATCH
constConv(Type to
)
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
)
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
)
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
4283 override const(char)* kind() const
4288 override uinteger_t
size(const ref Loc loc
)
4290 return target
.ptrsize
;
4293 override TypeClass
syntaxCopy()
4298 override inout(ClassDeclaration
) isClassHandle() inout
4303 extern (D
) MATCH
implicitConvToWithoutAliasThis(Type to
)
4305 ClassDeclaration cdto
= to
.isClassHandle();
4306 MATCH m
= constConv(to
);
4307 if (m
> MATCH
.nomatch
)
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
)
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
);
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
)
4344 if (ty
== to
.ty
&& sym
== (cast(TypeClass
)to
).sym
&& MODimplicitConv(mod
, to
.mod
))
4345 return MATCH
.constant
;
4347 /* Conversion derived to const(base)
4350 if (to
.isBaseOf(this, &offset
) && offset
== 0 && MODimplicitConv(mod
, to
.mod
))
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
);
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
);
4383 override bool isZeroInit(const ref Loc loc
)
4388 override bool isscope()
4393 override bool isBoolean()
4398 override void accept(Visitor v
)
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
4416 //printf("TypeTuple(this = %p)\n", this);
4417 this.arguments
= arguments
;
4418 //printf("TypeTuple() %p, %s\n", this, toChars());
4423 for (size_t i
= 0; i
< arguments
.length
; i
++)
4425 Parameter arg
= (*arguments
)[i
];
4426 assert(arg
&& arg
.type
);
4433 * Form TypeTuple from the types of the expressions.
4434 * Assume exps[] is already tuple expanded.
4436 extern (D
) this(Expressions
* exps
)
4439 auto arguments
= new Parameters(exps ? exps
.length
: 0);
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
4466 arguments
= new Parameters();
4469 extern (D
) this(Type t1
)
4472 arguments
= new Parameters();
4473 arguments
.push(new Parameter(Loc
.initial
, 0, t1
, null, null, null));
4476 extern (D
) this(Type t1
, Type t2
)
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
4504 override TypeTuple
syntaxCopy()
4506 Parameters
* args
= Parameter
.arraySyntaxCopy(arguments
);
4507 auto t
= new TypeTuple(args
);
4512 override bool equals(const RootObject o
) const
4514 Type t
= cast(Type
)o
;
4515 //printf("TypeTuple::equals(%s, %s)\n", toChars(), t.toChars());
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
))
4535 override MATCH
implicitConvTo(Type to
)
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
);
4555 return MATCH
.nomatch
;
4558 override void accept(Visitor v
)
4564 /***********************************************************
4565 * This is so we can slice a TypeTuple
4567 extern (C
++) final class TypeSlice
: TypeNext
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());
4580 override const(char)* kind() const
4585 override TypeSlice
syntaxCopy()
4587 auto t
= new TypeSlice(next
.syntaxCopy(), lwr
.syntaxCopy(), upr
.syntaxCopy());
4592 override void accept(Visitor v
)
4598 /***********************************************************
4600 extern (C
++) final class TypeNull
: Type
4602 extern (D
) this() @safe
4604 //printf("TypeNull %p\n", this);
4608 override const(char)* kind() const
4613 override TypeNull
syntaxCopy()
4615 // No semantic analysis done, no need to copy
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
)
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()
4644 override uinteger_t
size(const ref Loc loc
)
4646 return tvoidptr
.size(loc
);
4649 override void accept(Visitor v
)
4655 /***********************************************************
4657 extern (C
++) final class TypeNoreturn
: Type
4659 extern (D
) this() @safe
4661 //printf("TypeNoreturn %p\n", this);
4665 override const(char)* kind() const
4670 override TypeNoreturn
syntaxCopy()
4672 // No semantic analysis done, no need to copy
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
))
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
)
4708 override uint alignsize()
4713 override void accept(Visitor v
)
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);
4748 this.packalign
= packalign
;
4750 this.members
= members
;
4754 override const(char)* kind() const
4759 override TypeTag
syntaxCopy()
4761 //printf("TypeTag syntaxCopy()\n");
4762 // No semantic analysis done, no need to copy
4766 override void accept(Visitor v
)
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
;
4792 /// Returns the number of expanded parameters. Complexity: O(N).
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
))
4831 if (this.parameters
is other
.parameters
)
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
) {
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
)
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
)
4876 /***********************************************************
4878 extern (C
++) final class Parameter
: ASTNode
4880 import dmd
.attrib
: UserAttributeDeclaration
;
4883 StorageClass storageClass
;
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
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:
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
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
)
4959 extern (D
) static Parameters
* arraySyntaxCopy(Parameters
* parameters
)
4961 Parameters
* params
= null;
4964 params
= new Parameters(parameters
.length
);
4965 for (size_t i
= 0; i
< params
.length
; i
++)
4966 (*params
)[i
] = (*parameters
)[i
].syntaxCopy();
4971 /***************************************
4972 * Determine number of arguments, folding in tuples.
4974 static size_t
dim(Parameters
* parameters
)
4978 int dimDg(size_t n
, Parameter p
)
4984 _foreach(parameters
, &dimDg
);
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.
4996 * parameters = Array of `Parameter` to iterate over
4997 * nth = Index of the desired parameter.
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
)
5007 int getNthParamDg(size_t n
, Parameter p
)
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
));
5043 extern (D
) static int _foreach(
5044 Parameters
* parameters
, scope SemanticForeachDg dg
)
5046 assert(dg
!is null);
5047 if (parameters
is null)
5051 foreach (oidx
; 0 .. parameters
.length
)
5053 Parameter oparam
= (*parameters
)[oidx
];
5054 if (auto r
= _foreachImpl(dg
, oidx
, oparam
, eidx
, /* eparam */ oparam
))
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
)
5068 Type t
= eparam
.type
.toBasetype();
5069 if (auto tu
= t
.isTypeTuple())
5071 // Check for empty tuples
5072 if (tu
.arguments
is null)
5075 foreach (nidx
; 0 .. tu
.arguments
.length
)
5077 Parameter nextep
= (*tu
.arguments
)[nidx
];
5078 if (auto r
= _foreachImpl(dg
, oidx
, oparam
, eidx
, nextep
))
5084 if (auto r
= dg(oidx
, oparam
, eidx
, eparam
))
5086 // The only place where we should increment eidx is here,
5087 // as a TypeTuple doesn't count as a parameter (for arity)
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.
5104 * returnByRef = true if the function returns by ref
5105 * p = Parameter to compare with
5107 * true = `this` can be used in place of `p`
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
))
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
)
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_
))
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
5149 /* workaround until we get STC.returnScope reliably set correctly
5153 from
&= ~STC
.returnScope
;
5154 to
&= ~STC
.returnScope
;
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:
5173 From\To r rr rs rr-s r-rs
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;
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.
5211 * t1 = The first type to receive the type name for
5212 * t2 = The second type to receive the type name for
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);
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
)
5264 if (tf
.isreturn
&& !tf
.isreturninferred
)
5266 if (tf
.isScopeQual
&& !tf
.isscopeinferred
)
5271 TRUST trustAttrib
= tf
.trust
;
5273 if (trustAttrib
== TRUST
.default_
)
5275 if (trustFormat
!= TRUSTformatSystem
)
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,
5287 AggregateDeclaration
isAggregate(Type t
)
5291 return (cast(TypeClass
)t
).sym
;
5292 if (t
.ty
== Tstruct
)
5293 return (cast(TypeStruct
)t
).sym
;
5297 /***************************************************
5298 * Determine if type t can be indexed or sliced given that it is not an
5299 * aggregate with operator overloads.
5303 * true if an expression of type t can be e1 in an array expression
5305 bool isIndexableNonAggregate(Type t
)
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
5316 * stc = storage class of parameter
5318 * value from enum ScopeRef
5320 ScopeRef
buildScopeRef(StorageClass
stc) pure nothrow @nogc @safe
5323 stc |
= STC
.ref_
; // treat `out` and `ref` the same
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
;
5351 * Classification of 'scope-return-ref' possibilities
5366 /*********************************
5367 * Give us a nice string for debugging purposes.
5371 * corresponding string
5373 const(char)* ScopeRefToChars(ScopeRef sr
) pure nothrow @nogc @safe
5377 static immutable char*[ScopeRef
.max
+ 1] names
=
5381 ReturnScope
: "ReturnScope",
5383 ReturnRef
: "ReturnRef",
5384 RefScope
: "RefScope",
5385 ReturnRef_Scope
: "ReturnRef_Scope",
5386 Ref_ReturnScope
: "Ref_ReturnScope",
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
5402 * tv = The `TypeVector` to build a vector from.
5404 * A vector type suitable for the result of a vector comparison operation.
5406 TypeVector
toBooleanVector(TypeVector tv
)
5408 Type telem
= tv
.elementType();
5420 // No need to build an equivalent mask type.
5424 telem
= Type
.tuns32
;
5428 telem
= Type
.tuns64
;
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
)
5462 case TY
.Timaginary32
:
5463 case TY
.Timaginary64
:
5464 case TY
.Timaginary80
:
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.
5505 * handler = string for the name of the visit handler
5506 * Returns: boilerplate code for a case
5508 pure string
visitTYCase(string handler
) @safe
5514 enum isVoid = is(Result == void);
5515 auto tx = t.isType"~handler
~"();
5516 static if (__traits(compiles, visit"~handler
~"(tx)))
5520 visit"~handler
~"(tx);
5525 if (Result r = visit"~handler
~"(tx))
5530 else static if (__traits(compiles, visitDefaultCase(t)))
5534 visitDefaultCase(tx);
5539 if (Result r = visitDefaultCase(t))
5545 static assert(0, "~handler
~");
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
);
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
);