2 /* Compiler implementation of the D programming language
3 * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
4 * written by Walter Bright
5 * http://www.digitalmars.com
6 * Distributed under the Boost Software License, Version 1.0.
7 * http://www.boost.org/LICENSE_1_0.txt
8 * https://github.com/D-Programming-Language/dmd/blob/master/src/mtype.c
11 #include "root/dsystem.h"
12 #include "root/checkedint.h"
13 #include "root/rmem.h"
21 #include "expression.h"
22 #include "statement.h"
24 #include "declaration.h"
30 #include "aggregate.h"
34 bool symbolIsVisible(Scope
*sc
, Dsymbol
*s
);
35 typedef int (*ForeachDg
)(void *ctx
, size_t paramidx
, Parameter
*param
);
36 int Parameter_foreach(Parameters
*parameters
, ForeachDg dg
, void *ctx
, size_t *pn
= NULL
);
37 FuncDeclaration
*isFuncAddress(Expression
*e
, bool *hasOverloads
= NULL
);
38 Expression
*extractSideEffect(Scope
*sc
, const char *name
, Expression
**e0
, Expression
*e
, bool alwaysCopy
= false);
39 Expression
*resolve(Loc loc
, Scope
*sc
, Dsymbol
*s
, bool hasOverloads
);
40 Expression
*typeToExpression(Type
*t
);
41 Expression
*typeToExpressionHelper(TypeQualified
*t
, Expression
*e
, size_t i
= 0);
42 RootObject
*compileTypeMixin(TypeMixin
*tm
, Loc loc
, Scope
*sc
);
44 /***************************** Type *****************************/
46 ClassDeclaration
*Type::dtypeinfo
;
47 ClassDeclaration
*Type::typeinfoclass
;
48 ClassDeclaration
*Type::typeinfointerface
;
49 ClassDeclaration
*Type::typeinfostruct
;
50 ClassDeclaration
*Type::typeinfopointer
;
51 ClassDeclaration
*Type::typeinfoarray
;
52 ClassDeclaration
*Type::typeinfostaticarray
;
53 ClassDeclaration
*Type::typeinfoassociativearray
;
54 ClassDeclaration
*Type::typeinfovector
;
55 ClassDeclaration
*Type::typeinfoenum
;
56 ClassDeclaration
*Type::typeinfofunction
;
57 ClassDeclaration
*Type::typeinfodelegate
;
58 ClassDeclaration
*Type::typeinfotypelist
;
59 ClassDeclaration
*Type::typeinfoconst
;
60 ClassDeclaration
*Type::typeinfoinvariant
;
61 ClassDeclaration
*Type::typeinfoshared
;
62 ClassDeclaration
*Type::typeinfowild
;
64 TemplateDeclaration
*Type::rtinfo
;
81 Type
*Type::timaginary32
;
82 Type
*Type::timaginary64
;
83 Type
*Type::timaginary80
;
85 Type
*Type::tcomplex32
;
86 Type
*Type::tcomplex64
;
87 Type
*Type::tcomplex80
;
94 Type
*Type::tshiftcnt
;
97 Type
*Type::tnoreturn
;
100 Type
*Type::tptrdiff_t
;
103 Type
*Type::tvoidptr
;
105 Type
*Type::twstring
;
106 Type
*Type::tdstring
;
107 Type
*Type::basic
[TMAX
];
108 unsigned char Type::sizeTy
[TMAX
];
109 StringTable
Type::stringtable
;
111 void initTypeMangle();
128 this->arrayof
= NULL
;
133 const char *Type::kind()
135 assert(false); // should be overridden
141 void *pt
= mem
.xmalloc(sizeTy
[ty
]);
142 Type
*t
= (Type
*)memcpy(pt
, (void *)this, sizeTy
[ty
]);
146 Type
*Type::syntaxCopy()
149 fprintf(stderr
, "ty = %d\n", ty
);
154 bool Type::equals(RootObject
*o
)
157 //printf("Type::equals(%s, %s)\n", toChars(), t->toChars());
158 // deco strings are unique
159 // and semantic() has been run
160 if (this == o
|| ((t
&& deco
== t
->deco
) && deco
!= NULL
))
162 //printf("deco = '%s', t->deco = '%s'\n", deco, t->deco);
165 //if (deco && t && t->deco) printf("deco = '%s', t->deco = '%s'\n", deco, t->deco);
169 bool Type::equivalent(Type
*t
)
171 return immutableOf()->equals(t
->immutableOf());
176 stringtable
._init(14000);
178 for (size_t i
= 0; i
< TMAX
; i
++)
179 sizeTy
[i
] = sizeof(TypeBasic
);
180 sizeTy
[Tsarray
] = sizeof(TypeSArray
);
181 sizeTy
[Tarray
] = sizeof(TypeDArray
);
182 sizeTy
[Taarray
] = sizeof(TypeAArray
);
183 sizeTy
[Tpointer
] = sizeof(TypePointer
);
184 sizeTy
[Treference
] = sizeof(TypeReference
);
185 sizeTy
[Tfunction
] = sizeof(TypeFunction
);
186 sizeTy
[Tdelegate
] = sizeof(TypeDelegate
);
187 sizeTy
[Tident
] = sizeof(TypeIdentifier
);
188 sizeTy
[Tinstance
] = sizeof(TypeInstance
);
189 sizeTy
[Ttypeof
] = sizeof(TypeTypeof
);
190 sizeTy
[Tenum
] = sizeof(TypeEnum
);
191 sizeTy
[Tstruct
] = sizeof(TypeStruct
);
192 sizeTy
[Tclass
] = sizeof(TypeClass
);
193 sizeTy
[Ttuple
] = sizeof(TypeTuple
);
194 sizeTy
[Tslice
] = sizeof(TypeSlice
);
195 sizeTy
[Treturn
] = sizeof(TypeReturn
);
196 sizeTy
[Terror
] = sizeof(TypeError
);
197 sizeTy
[Tnull
] = sizeof(TypeNull
);
198 sizeTy
[Tvector
] = sizeof(TypeVector
);
199 sizeTy
[Ttraits
] = sizeof(TypeTraits
);
200 sizeTy
[Tmixin
] = sizeof(TypeMixin
);
201 sizeTy
[Tnoreturn
] = sizeof(TypeNoreturn
);
206 static TY basetab
[] =
207 { Tvoid
, Tint8
, Tuns8
, Tint16
, Tuns16
, Tint32
, Tuns32
, Tint64
, Tuns64
,
209 Tfloat32
, Tfloat64
, Tfloat80
,
210 Timaginary32
, Timaginary64
, Timaginary80
,
211 Tcomplex32
, Tcomplex64
, Tcomplex80
,
213 Tchar
, Twchar
, Tdchar
, Terror
};
215 for (size_t i
= 0; basetab
[i
] != Terror
; i
++)
217 Type
*t
= new TypeBasic(basetab
[i
]);
219 basic
[basetab
[i
]] = t
;
221 basic
[Terror
] = new TypeError();
223 tnoreturn
= new TypeNoreturn();
224 tnoreturn
->deco
= tnoreturn
->merge()->deco
;
225 basic
[Tnoreturn
] = tnoreturn
;
227 tvoid
= basic
[Tvoid
];
228 tint8
= basic
[Tint8
];
229 tuns8
= basic
[Tuns8
];
230 tint16
= basic
[Tint16
];
231 tuns16
= basic
[Tuns16
];
232 tint32
= basic
[Tint32
];
233 tuns32
= basic
[Tuns32
];
234 tint64
= basic
[Tint64
];
235 tuns64
= basic
[Tuns64
];
236 tint128
= basic
[Tint128
];
237 tuns128
= basic
[Tuns128
];
238 tfloat32
= basic
[Tfloat32
];
239 tfloat64
= basic
[Tfloat64
];
240 tfloat80
= basic
[Tfloat80
];
242 timaginary32
= basic
[Timaginary32
];
243 timaginary64
= basic
[Timaginary64
];
244 timaginary80
= basic
[Timaginary80
];
246 tcomplex32
= basic
[Tcomplex32
];
247 tcomplex64
= basic
[Tcomplex64
];
248 tcomplex80
= basic
[Tcomplex80
];
250 tbool
= basic
[Tbool
];
251 tchar
= basic
[Tchar
];
252 twchar
= basic
[Twchar
];
253 tdchar
= basic
[Tdchar
];
256 terror
= basic
[Terror
];
257 tnoreturn
= basic
[Tnoreturn
];
258 tnull
= new TypeNull();
259 tnull
->deco
= tnull
->merge()->deco
;
261 tvoidptr
= tvoid
->pointerTo();
262 tstring
= tchar
->immutableOf()->arrayOf();
263 twstring
= twchar
->immutableOf()->arrayOf();
264 tdstring
= tdchar
->immutableOf()->arrayOf();
266 const bool isLP64
= global
.params
.isLP64
;
268 tsize_t
= basic
[isLP64
? Tuns64
: Tuns32
];
269 tptrdiff_t
= basic
[isLP64
? Tint64
: Tint32
];
278 d_uns64
Type::size(Loc loc
)
280 error(loc
, "no size for type %s", toChars());
284 unsigned Type::alignsize()
286 return (unsigned)size(Loc());
289 Type
*Type::trySemantic(Loc loc
, Scope
*sc
)
291 //printf("+trySemantic(%s) %d\n", toChars(), global.errors);
292 unsigned errors
= global
.startGagging();
293 Type
*t
= typeSemantic(this, loc
, sc
);
294 if (global
.endGagging(errors
) || t
->ty
== Terror
) // if any errors happened
298 //printf("-trySemantic(%s) %d\n", toChars(), global.errors);
302 /********************************
303 * Return a copy of this type with all attributes null-initialized.
304 * Useful for creating a type with different modifiers.
307 Type
*Type::nullAttributes()
309 unsigned sz
= sizeTy
[ty
];
310 void *pt
= mem
.xmalloc(sz
);
311 Type
*t
= (Type
*)memcpy(pt
, (void *)this, sz
);
326 if (t
->ty
== Tstruct
) ((TypeStruct
*)t
)->att
= RECfwdref
;
327 if (t
->ty
== Tclass
) ((TypeClass
*)t
)->att
= RECfwdref
;
331 /********************************
332 * Convert to 'const'.
335 Type
*Type::constOf()
337 //printf("Type::constOf() %p %s\n", this, toChars());
342 assert(cto
->mod
== MODconst
);
345 Type
*t
= makeConst();
348 //printf("-Type::constOf() %p %s\n", t, t->toChars());
352 /********************************
353 * Convert to 'immutable'.
356 Type
*Type::immutableOf()
358 //printf("Type::immutableOf() %p %s\n", this, toChars());
363 assert(ito
->isImmutable());
366 Type
*t
= makeImmutable();
369 //printf("\t%p\n", t);
373 /********************************
377 Type
*Type::mutableOf()
379 //printf("Type::mutableOf() %p, %s\n", this, toChars());
383 t
= ito
; // immutable => naked
384 assert(!t
|| (t
->isMutable() && !t
->isShared()));
391 t
= swcto
; // shared wild const -> shared
393 t
= sto
; // shared const => shared
398 t
= wcto
; // wild const -> naked
400 t
= cto
; // const => naked
402 assert(!t
|| t
->isMutable());
407 t
= sto
; // shared wild => shared
409 t
= wto
; // wild => naked
410 assert(!t
|| t
->isMutable());
420 assert(t
->isMutable());
424 Type
*Type::sharedOf()
426 //printf("Type::sharedOf() %p, %s\n", this, toChars());
427 if (mod
== MODshared
)
431 assert(sto
->mod
== MODshared
);
434 Type
*t
= makeShared();
437 //printf("\t%p\n", t);
441 Type
*Type::sharedConstOf()
443 //printf("Type::sharedConstOf() %p, %s\n", this, toChars());
444 if (mod
== (MODshared
| MODconst
))
448 assert(scto
->mod
== (MODshared
| MODconst
));
451 Type
*t
= makeSharedConst();
454 //printf("\t%p\n", t);
459 /********************************
460 * Make type unshared.
463 * immutable => immutable
465 * shared const => const
467 * wild const => wild const
468 * shared wild => wild
469 * shared wild const => wild const
472 Type
*Type::unSharedOf()
474 //printf("Type::unSharedOf() %p, %s\n", this, toChars());
482 t
= wcto
; // shared wild const => wild const
484 t
= wto
; // shared wild => wild
489 t
= cto
; // shared const => const
491 t
= sto
; // shared => naked
493 assert(!t
|| !t
->isShared());
498 t
= this->nullAttributes();
499 t
->mod
= mod
& ~MODshared
;
507 assert(!t
->isShared());
511 /********************************
517 //printf("Type::wildOf() %p %s\n", this, toChars());
522 assert(wto
->mod
== MODwild
);
525 Type
*t
= makeWild();
528 //printf("\t%p %s\n", t, t->toChars());
532 Type
*Type::wildConstOf()
534 //printf("Type::wildConstOf() %p %s\n", this, toChars());
535 if (mod
== MODwildconst
)
539 assert(wcto
->mod
== MODwildconst
);
542 Type
*t
= makeWildConst();
545 //printf("\t%p %s\n", t, t->toChars());
549 Type
*Type::sharedWildOf()
551 //printf("Type::sharedWildOf() %p, %s\n", this, toChars());
552 if (mod
== (MODshared
| MODwild
))
556 assert(swto
->mod
== (MODshared
| MODwild
));
559 Type
*t
= makeSharedWild();
562 //printf("\t%p %s\n", t, t->toChars());
566 Type
*Type::sharedWildConstOf()
568 //printf("Type::sharedWildConstOf() %p, %s\n", this, toChars());
569 if (mod
== (MODshared
| MODwildconst
))
573 assert(swcto
->mod
== (MODshared
| MODwildconst
));
576 Type
*t
= makeSharedWildConst();
579 //printf("\t%p %s\n", t, t->toChars());
583 /**********************************
584 * For our new type 'this', which is type-constructed from t,
585 * fill in the cto, ito, sto, scto, wto shortcuts.
588 void Type::fixTo(Type
*t
)
590 // If fixing this: immutable(T*) by t: immutable(T)*,
591 // cache t to this->xto won't break transitivity.
594 if (!tn
|| (ty
!= Tsarray
&& tn
->mod
== t
->nextOf()->mod
))
598 case 0: mto
= t
; break;
599 case MODconst
: cto
= t
; break;
600 case MODwild
: wto
= t
; break;
601 case MODwildconst
: wcto
= t
; break;
602 case MODshared
: sto
= t
; break;
603 case MODshared
| MODconst
: scto
= t
; break;
604 case MODshared
| MODwild
: swto
= t
; break;
605 case MODshared
| MODwildconst
: swcto
= t
; break;
606 case MODimmutable
: ito
= t
; break;
610 assert(mod
!= t
->mod
);
611 #define X(m, n) (((m) << 4) | (n))
637 case MODshared
| MODconst
:
642 case MODshared
| MODwild
:
647 case MODshared
| MODwildconst
:
654 if (t
-> cto
) t
-> cto
->ito
= this;
655 if (t
-> sto
) t
-> sto
->ito
= this;
656 if (t
-> scto
) t
-> scto
->ito
= this;
657 if (t
-> wto
) t
-> wto
->ito
= this;
658 if (t
-> wcto
) t
-> wcto
->ito
= this;
659 if (t
-> swto
) t
-> swto
->ito
= this;
660 if (t
->swcto
) t
->swcto
->ito
= this;
670 //printf("fixTo: %s, %s\n", toChars(), t->toChars());
673 /***************************
674 * Look for bugs in constructing types.
682 if (cto
) assert(cto
->mod
== MODconst
);
683 if (ito
) assert(ito
->mod
== MODimmutable
);
684 if (sto
) assert(sto
->mod
== MODshared
);
685 if (scto
) assert(scto
->mod
== (MODshared
| MODconst
));
686 if (wto
) assert(wto
->mod
== MODwild
);
687 if (wcto
) assert(wcto
->mod
== MODwildconst
);
688 if (swto
) assert(swto
->mod
== (MODshared
| MODwild
));
689 if (swcto
) assert(swcto
->mod
== (MODshared
| MODwildconst
));
693 if (cto
) assert(cto
->mod
== 0);
694 if (ito
) assert(ito
->mod
== MODimmutable
);
695 if (sto
) assert(sto
->mod
== MODshared
);
696 if (scto
) assert(scto
->mod
== (MODshared
| MODconst
));
697 if (wto
) assert(wto
->mod
== MODwild
);
698 if (wcto
) assert(wcto
->mod
== MODwildconst
);
699 if (swto
) assert(swto
->mod
== (MODshared
| MODwild
));
700 if (swcto
) assert(swcto
->mod
== (MODshared
| MODwildconst
));
704 if (cto
) assert(cto
->mod
== MODconst
);
705 if (ito
) assert(ito
->mod
== MODimmutable
);
706 if (sto
) assert(sto
->mod
== MODshared
);
707 if (scto
) assert(scto
->mod
== (MODshared
| MODconst
));
708 if (wto
) assert(wto
->mod
== 0);
709 if (wcto
) assert(wcto
->mod
== MODwildconst
);
710 if (swto
) assert(swto
->mod
== (MODshared
| MODwild
));
711 if (swcto
) assert(swcto
->mod
== (MODshared
| MODwildconst
));
715 assert(! cto
|| cto
->mod
== MODconst
);
716 assert(! ito
|| ito
->mod
== MODimmutable
);
717 assert(! sto
|| sto
->mod
== MODshared
);
718 assert(! scto
|| scto
->mod
== (MODshared
| MODconst
));
719 assert(! wto
|| wto
->mod
== MODwild
);
720 assert(! wcto
|| wcto
->mod
== 0);
721 assert(! swto
|| swto
->mod
== (MODshared
| MODwild
));
722 assert(!swcto
|| swcto
->mod
== (MODshared
| MODwildconst
));
726 if (cto
) assert(cto
->mod
== MODconst
);
727 if (ito
) assert(ito
->mod
== MODimmutable
);
728 if (sto
) assert(sto
->mod
== 0);
729 if (scto
) assert(scto
->mod
== (MODshared
| MODconst
));
730 if (wto
) assert(wto
->mod
== MODwild
);
731 if (wcto
) assert(wcto
->mod
== MODwildconst
);
732 if (swto
) assert(swto
->mod
== (MODshared
| MODwild
));
733 if (swcto
) assert(swcto
->mod
== (MODshared
| MODwildconst
));
736 case MODshared
| MODconst
:
737 if (cto
) assert(cto
->mod
== MODconst
);
738 if (ito
) assert(ito
->mod
== MODimmutable
);
739 if (sto
) assert(sto
->mod
== MODshared
);
740 if (scto
) assert(scto
->mod
== 0);
741 if (wto
) assert(wto
->mod
== MODwild
);
742 if (wcto
) assert(wcto
->mod
== MODwildconst
);
743 if (swto
) assert(swto
->mod
== (MODshared
| MODwild
));
744 if (swcto
) assert(swcto
->mod
== (MODshared
| MODwildconst
));
747 case MODshared
| MODwild
:
748 if (cto
) assert(cto
->mod
== MODconst
);
749 if (ito
) assert(ito
->mod
== MODimmutable
);
750 if (sto
) assert(sto
->mod
== MODshared
);
751 if (scto
) assert(scto
->mod
== (MODshared
| MODconst
));
752 if (wto
) assert(wto
->mod
== MODwild
);
753 if (wcto
) assert(wcto
->mod
== MODwildconst
);
754 if (swto
) assert(swto
->mod
== 0);
755 if (swcto
) assert(swcto
->mod
== (MODshared
| MODwildconst
));
758 case MODshared
| MODwildconst
:
759 assert(! cto
|| cto
->mod
== MODconst
);
760 assert(! ito
|| ito
->mod
== MODimmutable
);
761 assert(! sto
|| sto
->mod
== MODshared
);
762 assert(! scto
|| scto
->mod
== (MODshared
| MODconst
));
763 assert(! wto
|| wto
->mod
== MODwild
);
764 assert(! wcto
|| wcto
->mod
== MODwildconst
);
765 assert(! swto
|| swto
->mod
== (MODshared
| MODwild
));
766 assert(!swcto
|| swcto
->mod
== 0);
770 if (cto
) assert(cto
->mod
== MODconst
);
771 if (ito
) assert(ito
->mod
== 0);
772 if (sto
) assert(sto
->mod
== MODshared
);
773 if (scto
) assert(scto
->mod
== (MODshared
| MODconst
));
774 if (wto
) assert(wto
->mod
== MODwild
);
775 if (wcto
) assert(wcto
->mod
== MODwildconst
);
776 if (swto
) assert(swto
->mod
== (MODshared
| MODwild
));
777 if (swcto
) assert(swcto
->mod
== (MODshared
| MODwildconst
));
785 if (tn
&& ty
!= Tfunction
&& tn
->ty
!= Tfunction
&& ty
!= Tenum
)
787 // Verify transitivity
795 case MODshared
| MODconst
:
796 case MODshared
| MODwild
:
797 case MODshared
| MODwildconst
:
799 assert(tn
->mod
== MODimmutable
|| (tn
->mod
& mod
) == mod
);
809 Type
*Type::makeConst()
811 //printf("Type::makeConst() %p, %s\n", this, toChars());
813 Type
*t
= this->nullAttributes();
815 //printf("-Type::makeConst() %p, %s\n", t, toChars());
819 Type
*Type::makeImmutable()
822 Type
*t
= this->nullAttributes();
823 t
->mod
= MODimmutable
;
827 Type
*Type::makeShared()
830 Type
*t
= this->nullAttributes();
835 Type
*Type::makeSharedConst()
837 if (scto
) return scto
;
838 Type
*t
= this->nullAttributes();
839 t
->mod
= MODshared
| MODconst
;
843 Type
*Type::makeWild()
846 Type
*t
= this->nullAttributes();
851 Type
*Type::makeWildConst()
853 if (wcto
) return wcto
;
854 Type
*t
= this->nullAttributes();
855 t
->mod
= MODwildconst
;
859 Type
*Type::makeSharedWild()
861 if (swto
) return swto
;
862 Type
*t
= this->nullAttributes();
863 t
->mod
= MODshared
| MODwild
;
867 Type
*Type::makeSharedWildConst()
869 if (swcto
) return swcto
;
870 Type
*t
= this->nullAttributes();
871 t
->mod
= MODshared
| MODwildconst
;
875 Type
*Type::makeMutable()
877 Type
*t
= this->nullAttributes();
878 t
->mod
= mod
& MODshared
;
882 /*************************************
883 * Apply STCxxxx bits to existing type.
884 * Use *before* semantic analysis is run.
887 Type
*Type::addSTC(StorageClass stc
)
890 if (t
->isImmutable())
892 else if (stc
& STCimmutable
)
894 t
= t
->makeImmutable();
898 if ((stc
& STCshared
) && !t
->isShared())
903 t
= t
->makeSharedWildConst();
905 t
= t
->makeSharedWild();
910 t
= t
->makeSharedConst();
915 if ((stc
& STCconst
) && !t
->isConst())
920 t
= t
->makeSharedWildConst();
922 t
= t
->makeSharedConst();
927 t
= t
->makeWildConst();
932 if ((stc
& STCwild
) && !t
->isWild())
937 t
= t
->makeSharedWildConst();
939 t
= t
->makeSharedWild();
944 t
= t
->makeWildConst();
953 /************************************
954 * Convert MODxxxx to STCxxx
957 StorageClass
ModToStc(unsigned mod
)
959 StorageClass stc
= 0;
960 if (mod
& MODimmutable
) stc
|= STCimmutable
;
961 if (mod
& MODconst
) stc
|= STCconst
;
962 if (mod
& MODwild
) stc
|= STCwild
;
963 if (mod
& MODshared
) stc
|= STCshared
;
967 /************************************
968 * Apply MODxxxx bits to existing type.
971 Type
*Type::castMod(MOD mod
)
977 t
= unSharedOf()->mutableOf();
981 t
= unSharedOf()->constOf();
985 t
= unSharedOf()->wildOf();
989 t
= unSharedOf()->wildConstOf();
993 t
= mutableOf()->sharedOf();
996 case MODshared
| MODconst
:
1000 case MODshared
| MODwild
:
1004 case MODshared
| MODwildconst
:
1005 t
= sharedWildConstOf();
1018 /************************************
1019 * Add MODxxxx bits to existing type.
1020 * We're adding, not replacing, so adding const to
1021 * a shared type => "shared const"
1024 Type
*Type::addMod(MOD mod
)
1026 /* Add anything to immutable, and it remains immutable
1029 if (!t
->isImmutable())
1031 //printf("addMod(%x) %s\n", mod, toChars());
1041 t
= sharedWildConstOf();
1043 t
= sharedConstOf();
1058 t
= sharedWildConstOf();
1073 t
= sharedWildConstOf();
1082 t
= sharedWildConstOf();
1089 t
= sharedConstOf();
1095 case MODshared
| MODconst
:
1097 t
= sharedWildConstOf();
1099 t
= sharedConstOf();
1102 case MODshared
| MODwild
:
1104 t
= sharedWildConstOf();
1109 case MODshared
| MODwildconst
:
1110 t
= sharedWildConstOf();
1124 /************************************
1125 * Add storage class modifiers to type.
1128 Type
*Type::addStorageClass(StorageClass stc
)
1130 /* Just translate to MOD bits and let addMod() do the work
1134 if (stc
& STCimmutable
)
1138 if (stc
& (STCconst
| STCin
))
1142 if (stc
& STCshared
)
1148 Type
*Type::pointerTo()
1154 Type
*t
= new TypePointer(this);
1155 if (ty
== Tfunction
)
1157 t
->deco
= t
->merge()->deco
;
1166 Type
*Type::referenceTo()
1172 Type
*t
= new TypeReference(this);
1178 Type
*Type::arrayOf()
1184 Type
*t
= new TypeDArray(this);
1185 arrayof
= t
->merge();
1190 // Make corresponding static array type without semantic
1191 Type
*Type::sarrayOf(dinteger_t dim
)
1194 Type
*t
= new TypeSArray(this, new IntegerExp(Loc(), dim
, Type::tsize_t
));
1196 // according to TypeSArray::semantic()
1203 Type
*Type::aliasthisOf()
1205 AggregateDeclaration
*ad
= isAggregate(this);
1206 if (ad
&& ad
->aliasthis
)
1208 Dsymbol
*s
= ad
->aliasthis
;
1209 if (s
->isAliasDeclaration())
1211 Declaration
*d
= s
->isDeclaration();
1212 if (d
&& !d
->isTupleDeclaration())
1216 if (d
->isVarDeclaration() && d
->needThis())
1218 t
= t
->addMod(this->mod
);
1220 else if (d
->isFuncDeclaration())
1222 FuncDeclaration
*fd
= resolveFuncCall(Loc(), NULL
, d
, NULL
, this, NULL
, 1);
1223 if (fd
&& fd
->errors
)
1224 return Type::terror
;
1225 if (fd
&& !fd
->type
->nextOf() && !fd
->functionSemantic())
1229 t
= fd
->type
->nextOf();
1230 if (!t
) // issue 14185
1231 return Type::terror
;
1232 t
= t
->substWildTo(mod
== 0 ? MODmutable
: (MODFlags
)mod
);
1235 return Type::terror
;
1239 EnumDeclaration
*ed
= s
->isEnumDeclaration();
1245 TemplateDeclaration
*td
= s
->isTemplateDeclaration();
1249 FuncDeclaration
*fd
= resolveFuncCall(Loc(), NULL
, td
, NULL
, this, NULL
, 1);
1250 if (fd
&& fd
->errors
)
1251 return Type::terror
;
1252 if (fd
&& fd
->functionSemantic())
1254 Type
*t
= fd
->type
->nextOf();
1255 t
= t
->substWildTo(mod
== 0 ? MODmutable
: (MODFlags
)mod
);
1259 return Type::terror
;
1261 //printf("%s\n", s->kind());
1266 bool Type::checkAliasThisRec()
1268 Type
*tb
= toBasetype();
1269 AliasThisRec
* pflag
;
1270 if (tb
->ty
== Tstruct
)
1271 pflag
= &((TypeStruct
*)tb
)->att
;
1272 else if (tb
->ty
== Tclass
)
1273 pflag
= &((TypeClass
*)tb
)->att
;
1277 AliasThisRec flag
= (AliasThisRec
)(*pflag
& RECtypeMask
);
1278 if (flag
== RECfwdref
)
1280 Type
*att
= aliasthisOf();
1281 flag
= att
&& att
->implicitConvTo(this) ? RECyes
: RECno
;
1283 *pflag
= (AliasThisRec
)(flag
| (*pflag
& ~RECtypeMask
));
1284 return flag
== RECyes
;
1287 Dsymbol
*Type::toDsymbol(Scope
*)
1292 /*******************************
1293 * If this is a shell around another type,
1294 * get that other type.
1297 Type
*Type::toBasetype()
1302 /***************************
1303 * Return !=0 if modfrom can be implicitly converted to modto
1305 bool MODimplicitConv(MOD modfrom
, MOD modto
)
1307 if (modfrom
== modto
)
1310 //printf("MODimplicitConv(from = %x, to = %x)\n", modfrom, modto);
1311 #define X(m, n) (((m) << 4) | (n))
1312 switch (X(modfrom
& ~MODshared
, modto
& ~MODshared
))
1314 case X(0, MODconst
):
1315 case X(MODwild
, MODconst
):
1316 case X(MODwild
, MODwildconst
):
1317 case X(MODwildconst
, MODconst
):
1318 return (modfrom
& MODshared
) == (modto
& MODshared
);
1320 case X(MODimmutable
, MODconst
):
1321 case X(MODimmutable
, MODwildconst
):
1330 /***************************
1331 * Return MATCHexact or MATCHconst if a method of type '() modfrom' can call a method of type '() modto'.
1333 MATCH
MODmethodConv(MOD modfrom
, MOD modto
)
1335 if (modfrom
== modto
)
1337 if (MODimplicitConv(modfrom
, modto
))
1340 #define X(m, n) (((m) << 4) | (n))
1341 switch (X(modfrom
, modto
))
1344 case X(MODimmutable
, MODwild
):
1345 case X(MODconst
, MODwild
):
1346 case X(MODwildconst
, MODwild
):
1347 case X(MODshared
, MODshared
|MODwild
):
1348 case X(MODshared
|MODimmutable
, MODshared
|MODwild
):
1349 case X(MODshared
|MODconst
, MODshared
|MODwild
):
1350 case X(MODshared
|MODwildconst
, MODshared
|MODwild
):
1354 return MATCHnomatch
;
1359 /***************************
1360 * Merge mod bits to form common mod.
1362 MOD
MODmerge(MOD mod1
, MOD mod2
)
1367 //printf("MODmerge(1 = %x, 2 = %x)\n", mod1, mod2);
1369 if ((mod1
| mod2
) & MODshared
)
1371 // If either type is shared, the result will be shared
1372 result
|= MODshared
;
1376 if (mod1
== 0 || mod1
== MODmutable
|| mod1
== MODconst
||
1377 mod2
== 0 || mod2
== MODmutable
|| mod2
== MODconst
)
1379 // If either type is mutable or const, the result will be const.
1384 // MODimmutable vs MODwild
1385 // MODimmutable vs MODwildconst
1386 // MODwild vs MODwildconst
1387 assert(mod1
& MODwild
|| mod2
& MODwild
);
1388 result
|= MODwildconst
;
1393 /*********************************
1394 * Store modifier name into buf.
1396 void MODtoBuffer(OutBuffer
*buf
, MOD mod
)
1404 buf
->writestring(Token::tochars
[TOKimmutable
]);
1408 buf
->writestring(Token::tochars
[TOKshared
]);
1411 case MODshared
| MODconst
:
1412 buf
->writestring(Token::tochars
[TOKshared
]);
1413 buf
->writeByte(' ');
1416 buf
->writestring(Token::tochars
[TOKconst
]);
1419 case MODshared
| MODwild
:
1420 buf
->writestring(Token::tochars
[TOKshared
]);
1421 buf
->writeByte(' ');
1424 buf
->writestring(Token::tochars
[TOKwild
]);
1427 case MODshared
| MODwildconst
:
1428 buf
->writestring(Token::tochars
[TOKshared
]);
1429 buf
->writeByte(' ');
1432 buf
->writestring(Token::tochars
[TOKwild
]);
1433 buf
->writeByte(' ');
1434 buf
->writestring(Token::tochars
[TOKconst
]);
1443 /*********************************
1444 * Return modifier name.
1446 char *MODtoChars(MOD mod
)
1450 MODtoBuffer(&buf
, mod
);
1451 return buf
.extractChars();
1454 /********************************
1455 * For pretty-printing a type.
1458 const char *Type::toChars()
1463 hgs
.fullQual
= (ty
== Tclass
&& !mod
);
1465 ::toCBuffer(this, &buf
, NULL
, &hgs
);
1466 return buf
.extractChars();
1469 char *Type::toPrettyChars(bool QualifyTypes
)
1474 hgs
.fullQual
= QualifyTypes
;
1476 ::toCBuffer(this, &buf
, NULL
, &hgs
);
1477 return buf
.extractChars();
1480 /*********************************
1481 * Store this type's modifier name into buf.
1483 void Type::modToBuffer(OutBuffer
*buf
)
1487 buf
->writeByte(' ');
1488 MODtoBuffer(buf
, mod
);
1492 /*********************************
1493 * Return this type's modifier name.
1495 char *Type::modToChars()
1500 return buf
.extractChars();
1503 /** For each active modifier (MODconst, MODimmutable, etc) call fp with a
1504 void* for the work param and a string representation of the attribute. */
1505 int Type::modifiersApply(void *param
, int (*fp
)(void *, const char *))
1507 static unsigned char modsArr
[] = { MODconst
, MODimmutable
, MODwild
, MODshared
};
1509 for (size_t idx
= 0; idx
< 4; ++idx
)
1511 if (mod
& modsArr
[idx
])
1513 if (int res
= fp(param
, MODtoChars(modsArr
[idx
])))
1520 /************************************
1521 * Strip all parameter's idenfiers and their default arguments for merging types.
1522 * If some of parameter types or return type are function pointer, delegate, or
1523 * the types which contains either, then strip also from them.
1526 Type
*stripDefaultArgs(Type
*t
)
1530 static Parameters
*stripParams(Parameters
*parameters
)
1532 Parameters
*params
= parameters
;
1533 if (params
&& params
->length
> 0)
1535 for (size_t i
= 0; i
< params
->length
; i
++)
1537 Parameter
*p
= (*params
)[i
];
1538 Type
*ta
= stripDefaultArgs(p
->type
);
1539 if (ta
!= p
->type
|| p
->defaultArg
|| p
->ident
|| p
->userAttribDecl
)
1541 if (params
== parameters
)
1543 params
= new Parameters();
1544 params
->setDim(parameters
->length
);
1545 for (size_t j
= 0; j
< params
->length
; j
++)
1546 (*params
)[j
] = (*parameters
)[j
];
1548 (*params
)[i
] = new Parameter(p
->storageClass
, ta
, NULL
, NULL
, NULL
);
1559 if (t
->ty
== Tfunction
)
1561 TypeFunction
*tf
= (TypeFunction
*)t
;
1562 Type
*tret
= stripDefaultArgs(tf
->next
);
1563 Parameters
*params
= N::stripParams(tf
->parameterList
.parameters
);
1564 if (tret
== tf
->next
&& params
== tf
->parameterList
.parameters
)
1566 tf
= (TypeFunction
*)tf
->copy();
1567 tf
->parameterList
.parameters
= params
;
1569 //printf("strip %s\n <- %s\n", tf->toChars(), t->toChars());
1572 else if (t
->ty
== Ttuple
)
1574 TypeTuple
*tt
= (TypeTuple
*)t
;
1575 Parameters
*args
= N::stripParams(tt
->arguments
);
1576 if (args
== tt
->arguments
)
1579 ((TypeTuple
*)t
)->arguments
= args
;
1581 else if (t
->ty
== Tenum
)
1583 // TypeEnum::nextOf() may be != NULL, but it's not necessary here.
1588 Type
*tn
= t
->nextOf();
1589 Type
*n
= stripDefaultArgs(tn
);
1593 ((TypeNext
*)t
)->next
= n
;
1595 //printf("strip %s\n", t->toChars());
1600 /************************************
1605 if (ty
== Terror
) return this;
1606 if (ty
== Ttypeof
) return this;
1607 if (ty
== Tident
) return this;
1608 if (ty
== Tinstance
) return this;
1609 if (ty
== Taarray
&& !((TypeAArray
*)this)->index
->merge()->deco
)
1611 if (ty
!= Tenum
&& nextOf() && !nextOf()->deco
)
1614 //printf("merge(%s)\n", toChars());
1622 mangleToBuffer(this, &buf
);
1624 StringValue
*sv
= stringtable
.update((char *)buf
.slice().ptr
, buf
.length());
1627 t
= (Type
*) sv
->ptrvalue
;
1629 //printf("old value, deco = '%s' %p\n", t->deco, t->deco);
1633 sv
->ptrvalue
= (char *)(t
= stripDefaultArgs(t
));
1634 deco
= t
->deco
= const_cast<char *>(sv
->toDchars());
1635 //printf("new value, deco = '%s' %p\n", t->deco, t->deco);
1641 /*************************************
1642 * This version does a merge even if the deco is already computed.
1643 * Necessary for types that have a deco, but are not merged.
1645 Type
*Type::merge2()
1647 //printf("merge2(%s)\n", toChars());
1653 StringValue
*sv
= stringtable
.lookup((char *)t
->deco
, strlen(t
->deco
));
1654 if (sv
&& sv
->ptrvalue
)
1655 { t
= (Type
*) sv
->ptrvalue
;
1663 bool Type::isintegral()
1668 bool Type::isfloating()
1678 bool Type::isimaginary()
1683 bool Type::iscomplex()
1688 bool Type::isscalar()
1693 bool Type::isunsigned()
1698 ClassDeclaration
*Type::isClassHandle()
1703 bool Type::isscope()
1708 bool Type::isString()
1713 /**************************
1714 * When T is mutable,
1717 * Can we bitwise assign:
1721 bool Type::isAssignable()
1726 /**************************
1727 * Returns true if T can be converted to boolean value.
1729 bool Type::isBoolean()
1734 /********************************
1735 * true if when type goes out of scope, it needs a destructor applied.
1736 * Only applies to value types, not ref types.
1738 bool Type::needsDestruction()
1743 /*********************************
1747 bool Type::needsNested()
1752 /*********************************
1753 * Check type to see if it is based on a deprecated symbol.
1756 void Type::checkDeprecated(Loc loc
, Scope
*sc
)
1758 if (Dsymbol
*s
= toDsymbol(sc
))
1760 s
->checkDeprecated(loc
, sc
);
1765 Expression
*Type::defaultInit(Loc
)
1770 /***************************************
1771 * Use when we prefer the default initializer to be a literal,
1772 * rather than a global immutable variable.
1774 Expression
*Type::defaultInitLiteral(Loc loc
)
1776 return defaultInit(loc
);
1779 bool Type::isZeroInit(Loc
)
1781 return false; // assume not
1784 bool Type::isBaseOf(Type
*, int *)
1786 return 0; // assume not
1789 /********************************
1790 * Determine if 'this' can be implicitly converted
1793 * MATCHnomatch, MATCHconvert, MATCHconst, MATCHexact
1796 MATCH
Type::implicitConvTo(Type
*to
)
1798 //printf("Type::implicitConvTo(this=%p, to=%p)\n", this, to);
1799 //printf("from: %s\n", toChars());
1800 //printf("to : %s\n", to->toChars());
1801 if (this->equals(to
))
1803 return MATCHnomatch
;
1806 /*******************************
1807 * Determine if converting 'this' to 'to' is an identity operation,
1808 * a conversion to const operation, or the types aren't the same.
1810 * MATCHexact 'this' == 'to'
1811 * MATCHconst 'to' is const
1812 * MATCHnomatch conversion to mutable or invariant
1815 MATCH
Type::constConv(Type
*to
)
1817 //printf("Type::constConv(this = %s, to = %s)\n", toChars(), to->toChars());
1820 if (ty
== to
->ty
&& MODimplicitConv(mod
, to
->mod
))
1822 return MATCHnomatch
;
1825 /***************************************
1826 * Return MOD bits matching this type to wild parameter type (tprm).
1829 unsigned char Type::deduceWild(Type
*t
, bool)
1831 //printf("Type::deduceWild this = '%s', tprm = '%s'\n", toChars(), tprm->toChars());
1836 return MODimmutable
;
1837 else if (isWildConst())
1839 if (t
->isWildConst())
1842 return MODwildconst
;
1848 else if (isMutable())
1856 Type
*Type::unqualify(unsigned m
)
1858 Type
*t
= mutableOf()->unSharedOf();
1860 Type
*tn
= ty
== Tenum
? NULL
: nextOf();
1861 if (tn
&& tn
->ty
!= Tfunction
)
1863 Type
*utn
= tn
->unqualify(m
);
1867 t
= utn
->pointerTo();
1868 else if (ty
== Tarray
)
1870 else if (ty
== Tsarray
)
1871 t
= new TypeSArray(utn
, ((TypeSArray
*)this)->dim
);
1872 else if (ty
== Taarray
)
1874 t
= new TypeAArray(utn
, ((TypeAArray
*)this)->index
);
1875 ((TypeAArray
*)t
)->sc
= ((TypeAArray
*)this)->sc
; // duplicate scope
1883 t
= t
->addMod(mod
& ~m
);
1887 Type
*Type::substWildTo(unsigned mod
)
1889 //printf("+Type::substWildTo this = %s, mod = x%x\n", toChars(), mod);
1892 if (Type
*tn
= nextOf())
1894 // substitution has no effect on function pointer type.
1895 if (ty
== Tpointer
&& tn
->ty
== Tfunction
)
1901 t
= tn
->substWildTo(mod
);
1908 else if (ty
== Tarray
)
1910 else if (ty
== Tsarray
)
1911 t
= new TypeSArray(t
, ((TypeSArray
*)this)->dim
->syntaxCopy());
1912 else if (ty
== Taarray
)
1914 t
= new TypeAArray(t
, ((TypeAArray
*)this)->index
->syntaxCopy());
1915 ((TypeAArray
*)t
)->sc
= ((TypeAArray
*)this)->sc
; // duplicate scope
1917 else if (ty
== Tdelegate
)
1919 t
= new TypeDelegate(t
);
1933 if (mod
== MODimmutable
)
1935 t
= t
->immutableOf();
1937 else if (mod
== MODwildconst
)
1939 t
= t
->wildConstOf();
1941 else if (mod
== MODwild
)
1944 t
= t
->wildConstOf();
1948 else if (mod
== MODconst
)
1961 t
= t
->addMod(MODconst
);
1963 t
= t
->addMod(MODshared
);
1965 //printf("-Type::substWildTo t = %s\n", t->toChars());
1969 Type
*TypeFunction::substWildTo(unsigned)
1971 if (!iswild
&& !(mod
& MODwild
))
1974 // Substitude inout qualifier of function type to mutable or immutable
1975 // would break type system. Instead substitude inout to the most weak
1976 // qualifer - const.
1977 unsigned m
= MODconst
;
1980 Type
*tret
= next
->substWildTo(m
);
1981 Parameters
*params
= parameterList
.parameters
;
1983 params
= parameterList
.parameters
->copy();
1984 for (size_t i
= 0; i
< params
->length
; i
++)
1986 Parameter
*p
= (*params
)[i
];
1987 Type
*t
= p
->type
->substWildTo(m
);
1990 if (params
== parameterList
.parameters
)
1991 params
= parameterList
.parameters
->copy();
1992 (*params
)[i
] = new Parameter(p
->storageClass
, t
, NULL
, NULL
, NULL
);
1994 if (next
== tret
&& params
== parameterList
.parameters
)
1997 // Similar to TypeFunction::syntaxCopy;
1998 TypeFunction
*t
= new TypeFunction(ParameterList(params
, parameterList
.varargs
),
2000 t
->mod
= ((mod
& MODwild
) ? (mod
& ~MODwild
) | MODconst
: mod
);
2001 t
->isnothrow
= isnothrow
;
2004 t
->isproperty
= isproperty
;
2006 t
->isreturn
= isreturn
;
2007 t
->isscope
= isscope
;
2008 t
->isscopeinferred
= isscopeinferred
;
2015 /**************************
2016 * Return type with the top level of it being mutable.
2018 Type
*Type::toHeadMutable()
2025 /***************************************
2026 * Calculate built-in properties which just the type is necessary.
2028 * If flag & 1, don't report "not a property" error and just return NULL.
2030 Expression
*Type::getProperty(Loc loc
, Identifier
*ident
, int flag
)
2034 if (ident
== Id::__sizeof
)
2036 d_uns64 sz
= size(loc
);
2037 if (sz
== SIZE_INVALID
)
2038 return new ErrorExp();
2039 e
= new IntegerExp(loc
, sz
, Type::tsize_t
);
2041 else if (ident
== Id::__xalignof
)
2043 e
= new IntegerExp(loc
, alignsize(), Type::tsize_t
);
2045 else if (ident
== Id::_init
)
2047 Type
*tb
= toBasetype();
2048 e
= defaultInitLiteral(loc
);
2049 if (tb
->ty
== Tstruct
&& tb
->needsNested())
2051 StructLiteralExp
*se
= (StructLiteralExp
*)e
;
2052 se
->useStaticInit
= true;
2055 else if (ident
== Id::_mangleof
)
2059 error(loc
, "forward reference of type %s.mangleof", toChars());
2064 e
= new StringExp(loc
, (char *)deco
, strlen(deco
));
2066 e
= expressionSemantic(e
, &sc
);
2069 else if (ident
== Id::stringof
)
2071 const char *s
= toChars();
2072 e
= new StringExp(loc
, const_cast<char *>(s
), strlen(s
));
2074 e
= expressionSemantic(e
, &sc
);
2076 else if (flag
&& this != Type::terror
)
2083 if (ty
== Tstruct
|| ty
== Tclass
|| ty
== Tenum
)
2084 s
= toDsymbol(NULL
);
2086 s
= s
->search_correct(ident
);
2087 if (this != Type::terror
)
2090 error(loc
, "no property `%s` for type `%s`, did you mean `%s`?", ident
->toChars(), toChars(), s
->toPrettyChars());
2092 error(loc
, "no property `%s` for type `%s`", ident
->toChars(), toChars());
2099 /***************************************
2100 * Access the members of the object e. This type is same as e->type.
2102 * If flag & 1, don't report "not a property" error and just return NULL.
2104 Expression
*Type::dotExp(Scope
*sc
, Expression
*e
, Identifier
*ident
, int flag
)
2106 VarDeclaration
*v
= NULL
;
2109 while (ex
->op
== TOKcomma
)
2110 ex
= ((CommaExp
*)ex
)->e2
;
2111 if (ex
->op
== TOKdotvar
)
2113 DotVarExp
*dv
= (DotVarExp
*)ex
;
2114 v
= dv
->var
->isVarDeclaration();
2116 else if (ex
->op
== TOKvar
)
2118 VarExp
*ve
= (VarExp
*)ex
;
2119 v
= ve
->var
->isVarDeclaration();
2123 if (ident
== Id::offsetof
)
2127 AggregateDeclaration
*ad
= v
->toParent()->isAggregateDeclaration();
2129 if (ad
->sizeok
!= SIZEOKdone
)
2130 return new ErrorExp();
2131 e
= new IntegerExp(e
->loc
, v
->offset
, Type::tsize_t
);
2135 else if (ident
== Id::_init
)
2137 Type
*tb
= toBasetype();
2138 e
= defaultInitLiteral(e
->loc
);
2139 if (tb
->ty
== Tstruct
&& tb
->needsNested())
2141 StructLiteralExp
*se
= (StructLiteralExp
*)e
;
2142 se
->useStaticInit
= true;
2147 if (ident
== Id::stringof
)
2149 /* Bugzilla 3796: this should demangle e->type->deco rather than
2150 * pretty-printing the type.
2152 const char *s
= e
->toChars();
2153 e
= new StringExp(e
->loc
, const_cast<char *>(s
), strlen(s
));
2156 e
= getProperty(e
->loc
, ident
, flag
& 1);
2160 e
= expressionSemantic(e
, sc
);
2164 /************************************
2165 * Return alignment to use for this type.
2168 structalign_t
Type::alignment()
2170 return STRUCTALIGN_DEFAULT
;
2173 /***************************************
2174 * Figures out what to do with an undefined member reference
2175 * for classes and structs.
2177 * If flag & 1, don't report "not a property" error and just return NULL.
2179 Expression
*Type::noMember(Scope
*sc
, Expression
*e
, Identifier
*ident
, int flag
)
2181 //printf("Type::noMember(e: %s ident: %s flag: %d)\n", e->toChars(), ident->toChars(), flag);
2183 static int nest
; // https://issues.dlang.org/show_bug.cgi?id=17380
2185 if (++nest
> global
.recursionLimit
)
2187 ::error(e
->loc
, "cannot resolve identifier `%s`", ident
->toChars());
2189 return (flag
& 1) ? NULL
: new ErrorExp();
2192 assert(ty
== Tstruct
|| ty
== Tclass
);
2193 AggregateDeclaration
*sym
= toDsymbol(sc
)->isAggregateDeclaration();
2196 if (ident
!= Id::__sizeof
&&
2197 ident
!= Id::__xalignof
&&
2198 ident
!= Id::_init
&&
2199 ident
!= Id::_mangleof
&&
2200 ident
!= Id::stringof
&&
2201 ident
!= Id::offsetof
&&
2202 // Bugzilla 15045: Don't forward special built-in member functions.
2203 ident
!= Id::ctor
&&
2204 ident
!= Id::dtor
&&
2205 ident
!= Id::__xdtor
&&
2206 ident
!= Id::postblit
&&
2207 ident
!= Id::__xpostblit
)
2209 /* Look for overloaded opDot() to see if we should forward request
2212 if (Dsymbol
*fd
= search_function(sym
, Id::opDot
))
2214 /* Rewrite e.ident as:
2217 e
= build_overload(e
->loc
, sc
, e
, NULL
, fd
);
2218 e
= new DotIdExp(e
->loc
, e
, ident
);
2219 e
= expressionSemantic(e
, sc
);
2224 /* Look for overloaded opDispatch to see if we should forward request
2227 if (Dsymbol
*fd
= search_function(sym
, Id::opDispatch
))
2229 /* Rewrite e.ident as:
2230 * e.opDispatch!("ident")
2232 TemplateDeclaration
*td
= fd
->isTemplateDeclaration();
2235 fd
->error("must be a template opDispatch(string s), not a %s", fd
->kind());
2237 return new ErrorExp();
2239 StringExp
*se
= new StringExp(e
->loc
, const_cast<char *>(ident
->toChars()));
2240 Objects
*tiargs
= new Objects();
2242 DotTemplateInstanceExp
*dti
= new DotTemplateInstanceExp(e
->loc
, e
, Id::opDispatch
, tiargs
);
2243 dti
->ti
->tempdecl
= td
;
2245 /* opDispatch, which doesn't need IFTI, may occur instantiate error.
2246 * It should be gagged if flag & 1.
2248 * template opDispatch(name) if (isValid!name) { ... }
2250 unsigned errors
= flag
& 1 ? global
.startGagging() : 0;
2251 e
= semanticY(dti
, sc
, 0);
2252 if (flag
& 1 && global
.endGagging(errors
))
2258 /* See if we should forward to the alias this.
2261 { /* Rewrite e.ident as:
2264 e
= resolveAliasThis(sc
, e
);
2265 DotIdExp
*die
= new DotIdExp(e
->loc
, e
, ident
);
2266 e
= semanticY(die
, sc
, flag
& 1);
2272 e
= Type::dotExp(sc
, e
, ident
, flag
);
2277 void Type::error(Loc loc
, const char *format
, ...)
2280 va_start(ap
, format
);
2281 ::verror(loc
, format
, ap
);
2285 void Type::warning(Loc loc
, const char *format
, ...)
2288 va_start(ap
, format
);
2289 ::vwarning(loc
, format
, ap
);
2293 Identifier
*Type::getTypeInfoIdent()
2295 // _init_10TypeInfo_%s
2298 mangleToBuffer(this, &buf
);
2300 size_t len
= buf
.length();
2303 // Allocate buffer on stack, fail over to using malloc()
2305 size_t namelen
= 19 + sizeof(len
) * 3 + len
+ 1;
2306 char *name
= namelen
<= sizeof(namebuf
) ? namebuf
: (char *)mem
.xmalloc(namelen
);
2308 int length
= sprintf(name
, "_D%lluTypeInfo_%s6__initZ", (unsigned long long) 9 + len
, buf
.slice().ptr
);
2309 //printf("%p, deco = %s, name = %s\n", this, deco, name);
2310 assert(0 < length
&& (size_t)length
< namelen
); // don't overflow the buffer
2312 Identifier
*id
= Identifier::idPool(name
, length
);
2314 if (name
!= namebuf
)
2319 TypeBasic
*Type::isTypeBasic()
2324 TypeError
*Type::isTypeError()
2326 return ty
== Terror
? (TypeError
*)this : NULL
;
2329 TypeVector
*Type::isTypeVector()
2331 return ty
== Tvector
? (TypeVector
*)this : NULL
;
2334 TypeSArray
*Type::isTypeSArray()
2336 return ty
== Tsarray
? (TypeSArray
*)this : NULL
;
2339 TypeDArray
*Type::isTypeDArray()
2341 return ty
== Tarray
? (TypeDArray
*)this : NULL
;
2344 TypeAArray
*Type::isTypeAArray()
2346 return ty
== Taarray
? (TypeAArray
*)this : NULL
;
2349 TypePointer
*Type::isTypePointer()
2351 return ty
== Tpointer
? (TypePointer
*)this : NULL
;
2354 TypeReference
*Type::isTypeReference()
2356 return ty
== Treference
? (TypeReference
*)this : NULL
;
2359 TypeFunction
*Type::isTypeFunction()
2361 return ty
== Tfunction
? (TypeFunction
*)this : NULL
;
2364 TypeDelegate
*Type::isTypeDelegate()
2366 return ty
== Tdelegate
? (TypeDelegate
*)this : NULL
;
2369 TypeIdentifier
*Type::isTypeIdentifier()
2371 return ty
== Tident
? (TypeIdentifier
*)this : NULL
;
2374 TypeInstance
*Type::isTypeInstance()
2376 return ty
== Tinstance
? (TypeInstance
*)this : NULL
;
2379 TypeTypeof
*Type::isTypeTypeof()
2381 return ty
== Ttypeof
? (TypeTypeof
*)this : NULL
;
2384 TypeReturn
*Type::isTypeReturn()
2386 return ty
== Treturn
? (TypeReturn
*)this : NULL
;
2389 TypeStruct
*Type::isTypeStruct()
2391 return ty
== Tstruct
? (TypeStruct
*)this : NULL
;
2394 TypeEnum
*Type::isTypeEnum()
2396 return ty
== Tenum
? (TypeEnum
*)this : NULL
;
2399 TypeClass
*Type::isTypeClass()
2401 return ty
== Tclass
? (TypeClass
*)this : NULL
;
2404 TypeTuple
*Type::isTypeTuple()
2406 return ty
== Ttuple
? (TypeTuple
*)this : NULL
;
2409 TypeSlice
*Type::isTypeSlice()
2411 return ty
== Tslice
? (TypeSlice
*)this : NULL
;
2414 TypeNull
*Type::isTypeNull()
2416 return ty
== Tnull
? (TypeNull
*)this : NULL
;
2419 TypeTraits
*Type::isTypeTraits()
2421 return ty
== Ttraits
? (TypeTraits
*)this : NULL
;
2424 TypeMixin
*Type::isTypeMixin()
2426 return ty
== Tmixin
? (TypeMixin
*)this : NULL
;
2429 TypeNoreturn
*Type::isTypeNoreturn()
2431 return ty
== Tnoreturn
? (TypeNoreturn
*)this : NULL
;
2434 TypeFunction
*Type::toTypeFunction()
2436 if (ty
!= Tfunction
)
2438 return (TypeFunction
*)this;
2441 /***************************************
2442 * Resolve 'this' type to either type, symbol, or expression.
2443 * If errors happened, resolved to Type.terror.
2445 void Type::resolve(Loc loc
, Scope
*sc
, Expression
**pe
, Type
**pt
, Dsymbol
**ps
, bool)
2447 //printf("Type::resolve() %s, %d\n", toChars(), ty);
2448 Type
*t
= typeSemantic(this, loc
, sc
);
2454 /***************************************
2455 * Normalize `e` as the result of Type::resolve() process.
2457 void Type::resolveExp(Expression
*e
, Type
**pt
, Expression
**pe
, Dsymbol
**ps
)
2475 s
= ((VarExp
*)e
)->var
;
2476 if (s
->isVarDeclaration())
2478 //if (s->isOverDeclaration())
2483 // TemplateDeclaration
2484 s
= ((TemplateExp
*)e
)->td
;
2488 s
= ((ScopeExp
*)e
)->sds
;
2489 // TemplateDeclaration, TemplateInstance, Import, Package, Module
2501 //case TOKoverloadset:
2518 /***************************************
2519 * Return !=0 if the type or any of its subtypes is wild.
2522 int Type::hasWild() const
2524 return mod
& MODwild
;
2527 /***************************************
2528 * Return !=0 if type has pointers that need to
2529 * be scanned by the GC during a collection cycle.
2531 bool Type::hasPointers()
2533 //printf("Type::hasPointers() %s, %d\n", toChars(), ty);
2537 /*************************************
2538 * Detect if type has pointer fields that are initialized to void.
2539 * Local stack variables with such void fields can remain uninitialized,
2540 * leading to pointer bugs.
2544 bool Type::hasVoidInitPointers()
2549 /*************************************
2550 * If this is a type of something, return that something.
2553 Type
*Type::nextOf()
2558 /*************************************
2559 * If this is a type of static array, return its base element type.
2562 Type
*Type::baseElemOf()
2564 Type
*t
= toBasetype();
2565 while (t
->ty
== Tsarray
)
2566 t
= ((TypeSArray
*)t
)->next
->toBasetype();
2570 /*************************************
2571 * Bugzilla 14488: Check if the inner most base type is complex or imaginary.
2572 * Should only give alerts when set to emit transitional messages.
2575 void Type::checkComplexTransition(Loc loc
)
2577 Type
*t
= baseElemOf();
2578 while (t
->ty
== Tpointer
|| t
->ty
== Tarray
)
2579 t
= t
->nextOf()->baseElemOf();
2581 if (t
->isimaginary() || t
->iscomplex())
2588 rt
= Type::tfloat32
; break;
2591 rt
= Type::tfloat64
; break;
2594 rt
= Type::tfloat80
; break;
2600 message(loc
, "use of complex type `%s` is scheduled for deprecation, "
2601 "use `std.complex.Complex!(%s)` instead", toChars(), rt
->toChars());
2605 message(loc
, "use of imaginary type `%s` is scheduled for deprecation, "
2606 "use `%s` instead\n", toChars(), rt
->toChars());
2611 /*******************************************
2612 * Compute number of elements for a (possibly multidimensional) static array,
2613 * or 1 for other types.
2615 * loc = for error message
2617 * number of elements, uint.max on overflow
2619 unsigned Type::numberOfElems(const Loc
&loc
)
2621 //printf("Type::numberOfElems()\n");
2624 while ((tb
= tb
->toBasetype())->ty
== Tsarray
)
2626 bool overflow
= false;
2627 n
= mulu(n
, ((TypeSArray
*)tb
)->dim
->toUInteger(), overflow
);
2628 if (overflow
|| n
>= UINT32_MAX
)
2630 error(loc
, "static array `%s` size overflowed to %llu", toChars(), (unsigned long long)n
);
2633 tb
= ((TypeSArray
*)tb
)->next
;
2638 /****************************************
2639 * Return the mask that an integral type will
2642 uinteger_t
Type::sizemask()
2645 switch (toBasetype()->ty
)
2647 case Tbool
: m
= 1; break;
2650 case Tuns8
: m
= 0xFF; break;
2653 case Tuns16
: m
= 0xFFFFUL
; break;
2656 case Tuns32
: m
= 0xFFFFFFFFUL
; break;
2658 case Tuns64
: m
= 0xFFFFFFFFFFFFFFFFULL
; break;
2665 /* ============================= TypeError =========================== */
2667 TypeError::TypeError()
2672 Type
*TypeError::syntaxCopy()
2674 // No semantic analysis done, no need to copy
2678 d_uns64
TypeError::size(Loc
) { return SIZE_INVALID
; }
2679 Expression
*TypeError::getProperty(Loc
, Identifier
*, int) { return new ErrorExp(); }
2680 Expression
*TypeError::dotExp(Scope
*, Expression
*, Identifier
*, int) { return new ErrorExp(); }
2681 Expression
*TypeError::defaultInit(Loc
) { return new ErrorExp(); }
2682 Expression
*TypeError::defaultInitLiteral(Loc
) { return new ErrorExp(); }
2684 /* ============================= TypeNext =========================== */
2686 TypeNext::TypeNext(TY ty
, Type
*next
)
2692 void TypeNext::checkDeprecated(Loc loc
, Scope
*sc
)
2694 Type::checkDeprecated(loc
, sc
);
2695 if (next
) // next can be NULL if TypeFunction and auto return type
2696 next
->checkDeprecated(loc
, sc
);
2699 int TypeNext::hasWild() const
2701 if (ty
== Tfunction
)
2703 if (ty
== Tdelegate
)
2704 return Type::hasWild();
2705 return mod
& MODwild
|| (next
&& next
->hasWild());
2709 /*******************************
2710 * For TypeFunction, nextOf() can return NULL if the function return
2711 * type is meant to be inferred, and semantic() hasn't yet ben run
2712 * on the function. After semantic(), it must no longer be NULL.
2715 Type
*TypeNext::nextOf()
2720 Type
*TypeNext::makeConst()
2722 //printf("TypeNext::makeConst() %p, %s\n", this, toChars());
2725 assert(cto
->mod
== MODconst
);
2728 TypeNext
*t
= (TypeNext
*)Type::makeConst();
2729 if (ty
!= Tfunction
&& next
->ty
!= Tfunction
&&
2730 !next
->isImmutable())
2732 if (next
->isShared())
2735 t
->next
= next
->sharedWildConstOf();
2737 t
->next
= next
->sharedConstOf();
2742 t
->next
= next
->wildConstOf();
2744 t
->next
= next
->constOf();
2747 //printf("TypeNext::makeConst() returns %p, %s\n", t, t->toChars());
2751 Type
*TypeNext::makeImmutable()
2753 //printf("TypeNext::makeImmutable() %s\n", toChars());
2756 assert(ito
->isImmutable());
2759 TypeNext
*t
= (TypeNext
*)Type::makeImmutable();
2760 if (ty
!= Tfunction
&& next
->ty
!= Tfunction
&&
2761 !next
->isImmutable())
2763 t
->next
= next
->immutableOf();
2768 Type
*TypeNext::makeShared()
2770 //printf("TypeNext::makeShared() %s\n", toChars());
2773 assert(sto
->mod
== MODshared
);
2776 TypeNext
*t
= (TypeNext
*)Type::makeShared();
2777 if (ty
!= Tfunction
&& next
->ty
!= Tfunction
&&
2778 !next
->isImmutable())
2782 if (next
->isConst())
2783 t
->next
= next
->sharedWildConstOf();
2785 t
->next
= next
->sharedWildOf();
2789 if (next
->isConst())
2790 t
->next
= next
->sharedConstOf();
2792 t
->next
= next
->sharedOf();
2795 //printf("TypeNext::makeShared() returns %p, %s\n", t, t->toChars());
2799 Type
*TypeNext::makeSharedConst()
2801 //printf("TypeNext::makeSharedConst() %s\n", toChars());
2804 assert(scto
->mod
== (MODshared
| MODconst
));
2807 TypeNext
*t
= (TypeNext
*)Type::makeSharedConst();
2808 if (ty
!= Tfunction
&& next
->ty
!= Tfunction
&&
2809 !next
->isImmutable())
2812 t
->next
= next
->sharedWildConstOf();
2814 t
->next
= next
->sharedConstOf();
2816 //printf("TypeNext::makeSharedConst() returns %p, %s\n", t, t->toChars());
2820 Type
*TypeNext::makeWild()
2822 //printf("TypeNext::makeWild() %s\n", toChars());
2825 assert(wto
->mod
== MODwild
);
2828 TypeNext
*t
= (TypeNext
*)Type::makeWild();
2829 if (ty
!= Tfunction
&& next
->ty
!= Tfunction
&&
2830 !next
->isImmutable())
2832 if (next
->isShared())
2834 if (next
->isConst())
2835 t
->next
= next
->sharedWildConstOf();
2837 t
->next
= next
->sharedWildOf();
2841 if (next
->isConst())
2842 t
->next
= next
->wildConstOf();
2844 t
->next
= next
->wildOf();
2847 //printf("TypeNext::makeWild() returns %p, %s\n", t, t->toChars());
2851 Type
*TypeNext::makeWildConst()
2853 //printf("TypeNext::makeWildConst() %s\n", toChars());
2856 assert(wcto
->mod
== MODwildconst
);
2859 TypeNext
*t
= (TypeNext
*)Type::makeWildConst();
2860 if (ty
!= Tfunction
&& next
->ty
!= Tfunction
&&
2861 !next
->isImmutable())
2863 if (next
->isShared())
2864 t
->next
= next
->sharedWildConstOf();
2866 t
->next
= next
->wildConstOf();
2868 //printf("TypeNext::makeWildConst() returns %p, %s\n", t, t->toChars());
2872 Type
*TypeNext::makeSharedWild()
2874 //printf("TypeNext::makeSharedWild() %s\n", toChars());
2877 assert(swto
->isSharedWild());
2880 TypeNext
*t
= (TypeNext
*)Type::makeSharedWild();
2881 if (ty
!= Tfunction
&& next
->ty
!= Tfunction
&&
2882 !next
->isImmutable())
2884 if (next
->isConst())
2885 t
->next
= next
->sharedWildConstOf();
2887 t
->next
= next
->sharedWildOf();
2889 //printf("TypeNext::makeSharedWild() returns %p, %s\n", t, t->toChars());
2893 Type
*TypeNext::makeSharedWildConst()
2895 //printf("TypeNext::makeSharedWildConst() %s\n", toChars());
2898 assert(swcto
->mod
== (MODshared
| MODwildconst
));
2901 TypeNext
*t
= (TypeNext
*)Type::makeSharedWildConst();
2902 if (ty
!= Tfunction
&& next
->ty
!= Tfunction
&&
2903 !next
->isImmutable())
2905 t
->next
= next
->sharedWildConstOf();
2907 //printf("TypeNext::makeSharedWildConst() returns %p, %s\n", t, t->toChars());
2911 Type
*TypeNext::makeMutable()
2913 //printf("TypeNext::makeMutable() %p, %s\n", this, toChars());
2914 TypeNext
*t
= (TypeNext
*)Type::makeMutable();
2917 t
->next
= next
->mutableOf();
2919 //printf("TypeNext::makeMutable() returns %p, %s\n", t, t->toChars());
2923 MATCH
TypeNext::constConv(Type
*to
)
2925 //printf("TypeNext::constConv from = %s, to = %s\n", toChars(), to->toChars());
2929 if (!(ty
== to
->ty
&& MODimplicitConv(mod
, to
->mod
)))
2930 return MATCHnomatch
;
2932 Type
*tn
= to
->nextOf();
2933 if (!(tn
&& next
->ty
== tn
->ty
))
2934 return MATCHnomatch
;
2937 if (to
->isConst()) // whole tail const conversion
2938 { // Recursive shared level check
2939 m
= next
->constConv(tn
);
2940 if (m
== MATCHexact
)
2944 { //printf("\tnext => %s, to->next => %s\n", next->toChars(), tn->toChars());
2945 m
= next
->equals(tn
) ? MATCHconst
: MATCHnomatch
;
2950 unsigned char TypeNext::deduceWild(Type
*t
, bool isRef
)
2952 if (ty
== Tfunction
)
2957 Type
*tn
= t
->nextOf();
2958 if (!isRef
&& (ty
== Tarray
|| ty
== Tpointer
) && tn
)
2960 wm
= next
->deduceWild(tn
, true);
2962 wm
= Type::deduceWild(t
, true);
2966 wm
= Type::deduceWild(t
, isRef
);
2968 wm
= next
->deduceWild(tn
, true);
2975 void TypeNext::transitive()
2977 /* Invoke transitivity of type attributes
2979 next
= next
->addMod(mod
);
2982 /* ============================= TypeBasic =========================== */
2984 #define TFLAGSintegral 1
2985 #define TFLAGSfloating 2
2986 #define TFLAGSunsigned 4
2987 #define TFLAGSreal 8
2988 #define TFLAGSimaginary 0x10
2989 #define TFLAGScomplex 0x20
2991 TypeBasic::TypeBasic(TY ty
)
2999 case Tvoid
: d
= Token::toChars(TOKvoid
);
3002 case Tint8
: d
= Token::toChars(TOKint8
);
3003 flags
|= TFLAGSintegral
;
3006 case Tuns8
: d
= Token::toChars(TOKuns8
);
3007 flags
|= TFLAGSintegral
| TFLAGSunsigned
;
3010 case Tint16
: d
= Token::toChars(TOKint16
);
3011 flags
|= TFLAGSintegral
;
3014 case Tuns16
: d
= Token::toChars(TOKuns16
);
3015 flags
|= TFLAGSintegral
| TFLAGSunsigned
;
3018 case Tint32
: d
= Token::toChars(TOKint32
);
3019 flags
|= TFLAGSintegral
;
3022 case Tuns32
: d
= Token::toChars(TOKuns32
);
3023 flags
|= TFLAGSintegral
| TFLAGSunsigned
;
3026 case Tfloat32
: d
= Token::toChars(TOKfloat32
);
3027 flags
|= TFLAGSfloating
| TFLAGSreal
;
3030 case Tint64
: d
= Token::toChars(TOKint64
);
3031 flags
|= TFLAGSintegral
;
3034 case Tuns64
: d
= Token::toChars(TOKuns64
);
3035 flags
|= TFLAGSintegral
| TFLAGSunsigned
;
3038 case Tint128
: d
= Token::toChars(TOKint128
);
3039 flags
|= TFLAGSintegral
;
3042 case Tuns128
: d
= Token::toChars(TOKuns128
);
3043 flags
|= TFLAGSintegral
| TFLAGSunsigned
;
3046 case Tfloat64
: d
= Token::toChars(TOKfloat64
);
3047 flags
|= TFLAGSfloating
| TFLAGSreal
;
3050 case Tfloat80
: d
= Token::toChars(TOKfloat80
);
3051 flags
|= TFLAGSfloating
| TFLAGSreal
;
3054 case Timaginary32
: d
= Token::toChars(TOKimaginary32
);
3055 flags
|= TFLAGSfloating
| TFLAGSimaginary
;
3058 case Timaginary64
: d
= Token::toChars(TOKimaginary64
);
3059 flags
|= TFLAGSfloating
| TFLAGSimaginary
;
3062 case Timaginary80
: d
= Token::toChars(TOKimaginary80
);
3063 flags
|= TFLAGSfloating
| TFLAGSimaginary
;
3066 case Tcomplex32
: d
= Token::toChars(TOKcomplex32
);
3067 flags
|= TFLAGSfloating
| TFLAGScomplex
;
3070 case Tcomplex64
: d
= Token::toChars(TOKcomplex64
);
3071 flags
|= TFLAGSfloating
| TFLAGScomplex
;
3074 case Tcomplex80
: d
= Token::toChars(TOKcomplex80
);
3075 flags
|= TFLAGSfloating
| TFLAGScomplex
;
3078 case Tbool
: d
= "bool";
3079 flags
|= TFLAGSintegral
| TFLAGSunsigned
;
3082 case Tchar
: d
= Token::toChars(TOKchar
);
3083 flags
|= TFLAGSintegral
| TFLAGSunsigned
;
3086 case Twchar
: d
= Token::toChars(TOKwchar
);
3087 flags
|= TFLAGSintegral
| TFLAGSunsigned
;
3090 case Tdchar
: d
= Token::toChars(TOKdchar
);
3091 flags
|= TFLAGSintegral
| TFLAGSunsigned
;
3097 this->flags
= flags
;
3101 const char *TypeBasic::kind()
3106 Type
*TypeBasic::syntaxCopy()
3108 // No semantic analysis done on basic types, no need to copy
3112 d_uns64
TypeBasic::size(Loc
)
3115 //printf("TypeBasic::size()\n");
3119 case Tuns8
: size
= 1; break;
3121 case Tuns16
: size
= 2; break;
3134 size
= target
.realsize
; break;
3142 size
= target
.realsize
* 2; break;
3145 //size = Type::size(); // error message
3149 case Tbool
: size
= 1; break;
3150 case Tchar
: size
= 1; break;
3151 case Twchar
: size
= 2; break;
3152 case Tdchar
: size
= 4; break;
3158 //printf("TypeBasic::size() = %d\n", size);
3162 unsigned TypeBasic::alignsize()
3164 return target
.alignsize(this);
3168 Expression
*TypeBasic::getProperty(Loc loc
, Identifier
*ident
, int flag
)
3174 //printf("TypeBasic::getProperty('%s')\n", ident->toChars());
3175 if (ident
== Id::max
)
3192 ivalue
= 0x7FFFFFFFUL
;
3195 ivalue
= 0xFFFFFFFFUL
;
3198 ivalue
= 0x7FFFFFFFFFFFFFFFLL
;
3201 ivalue
= 0xFFFFFFFFFFFFFFFFULL
;
3213 ivalue
= 0x10FFFFUL
;
3218 fvalue
= target
.FloatProperties
.max
;
3223 fvalue
= target
.DoubleProperties
.max
;
3228 fvalue
= target
.RealProperties
.max
;
3232 else if (ident
== Id::min
)
3249 ivalue
= -2147483647L - 1;
3255 ivalue
= (-9223372036854775807LL-1LL);
3282 error(loc
, "use .min_normal property instead of .min");
3283 return new ErrorExp();
3286 else if (ident
== Id::min_normal
)
3293 fvalue
= target
.FloatProperties
.min_normal
;
3298 fvalue
= target
.DoubleProperties
.min_normal
;
3303 fvalue
= target
.RealProperties
.min_normal
;
3307 else if (ident
== Id::nan
)
3320 fvalue
= target
.RealProperties
.nan
;
3324 else if (ident
== Id::infinity
)
3337 fvalue
= target
.RealProperties
.infinity
;
3341 else if (ident
== Id::dig
)
3348 ivalue
= target
.FloatProperties
.dig
;
3353 ivalue
= target
.DoubleProperties
.dig
;
3358 ivalue
= target
.RealProperties
.dig
;
3362 else if (ident
== Id::epsilon
)
3369 fvalue
= target
.FloatProperties
.epsilon
;
3374 fvalue
= target
.DoubleProperties
.epsilon
;
3379 fvalue
= target
.RealProperties
.epsilon
;
3383 else if (ident
== Id::mant_dig
)
3390 ivalue
= target
.FloatProperties
.mant_dig
;
3395 ivalue
= target
.DoubleProperties
.mant_dig
;
3400 ivalue
= target
.RealProperties
.mant_dig
;
3404 else if (ident
== Id::max_10_exp
)
3411 ivalue
= target
.FloatProperties
.max_10_exp
;
3416 ivalue
= target
.DoubleProperties
.max_10_exp
;
3421 ivalue
= target
.RealProperties
.max_10_exp
;
3425 else if (ident
== Id::max_exp
)
3432 ivalue
= target
.FloatProperties
.max_exp
;
3437 ivalue
= target
.DoubleProperties
.max_exp
;
3442 ivalue
= target
.RealProperties
.max_exp
;
3446 else if (ident
== Id::min_10_exp
)
3453 ivalue
= target
.FloatProperties
.min_10_exp
;
3458 ivalue
= target
.DoubleProperties
.min_10_exp
;
3463 ivalue
= target
.RealProperties
.min_10_exp
;
3467 else if (ident
== Id::min_exp
)
3474 ivalue
= target
.FloatProperties
.min_exp
;
3479 ivalue
= target
.DoubleProperties
.min_exp
;
3484 ivalue
= target
.RealProperties
.min_exp
;
3489 return Type::getProperty(loc
, ident
, flag
);
3492 e
= new IntegerExp(loc
, ivalue
, this);
3496 if (isreal() || isimaginary())
3497 e
= new RealExp(loc
, fvalue
, this);
3500 complex_t cvalue
= complex_t(fvalue
, fvalue
);
3501 //for (int i = 0; i < 20; i++)
3502 // printf("%02x ", ((unsigned char *)&cvalue)[i]);
3504 e
= new ComplexExp(loc
, cvalue
, this);
3509 e
= new IntegerExp(loc
, ivalue
, Type::tint32
);
3513 Expression
*TypeBasic::dotExp(Scope
*sc
, Expression
*e
, Identifier
*ident
, int flag
)
3517 if (ident
== Id::re
)
3521 case Tcomplex32
: t
= tfloat32
; goto L1
;
3522 case Tcomplex64
: t
= tfloat64
; goto L1
;
3523 case Tcomplex80
: t
= tfloat80
; goto L1
;
3525 e
= e
->castTo(sc
, t
);
3533 case Timaginary32
: t
= tfloat32
; goto L2
;
3534 case Timaginary64
: t
= tfloat64
; goto L2
;
3535 case Timaginary80
: t
= tfloat80
; goto L2
;
3537 e
= new RealExp(e
->loc
, CTFloat::zero
, t
);
3541 e
= Type::getProperty(e
->loc
, ident
, flag
);
3545 else if (ident
== Id::im
)
3550 case Tcomplex32
: t
= timaginary32
; t2
= tfloat32
; goto L3
;
3551 case Tcomplex64
: t
= timaginary64
; t2
= tfloat64
; goto L3
;
3552 case Tcomplex80
: t
= timaginary80
; t2
= tfloat80
; goto L3
;
3554 e
= e
->castTo(sc
, t
);
3558 case Timaginary32
: t
= tfloat32
; goto L4
;
3559 case Timaginary64
: t
= tfloat64
; goto L4
;
3560 case Timaginary80
: t
= tfloat80
; goto L4
;
3569 e
= new RealExp(e
->loc
, CTFloat::zero
, this);
3573 e
= Type::getProperty(e
->loc
, ident
, flag
);
3579 return Type::dotExp(sc
, e
, ident
, flag
);
3581 if (!(flag
& 1) || e
)
3582 e
= expressionSemantic(e
, sc
);
3586 Expression
*TypeBasic::defaultInit(Loc loc
)
3588 dinteger_t value
= 0;
3607 return new RealExp(loc
, target
.RealProperties
.snan
, this);
3612 { // Can't use fvalue + I*fvalue (the im part becomes a quiet NaN).
3613 complex_t cvalue
= complex_t(target
.RealProperties
.snan
, target
.RealProperties
.snan
);
3614 return new ComplexExp(loc
, cvalue
, this);
3618 error(loc
, "void does not have a default initializer");
3619 return new ErrorExp();
3621 return new IntegerExp(loc
, value
, this);
3624 bool TypeBasic::isZeroInit(Loc
)
3646 bool TypeBasic::isintegral()
3648 //printf("TypeBasic::isintegral('%s') x%x\n", toChars(), flags);
3649 return (flags
& TFLAGSintegral
) != 0;
3652 bool TypeBasic::isfloating()
3654 return (flags
& TFLAGSfloating
) != 0;
3657 bool TypeBasic::isreal()
3659 return (flags
& TFLAGSreal
) != 0;
3662 bool TypeBasic::isimaginary()
3664 return (flags
& TFLAGSimaginary
) != 0;
3667 bool TypeBasic::iscomplex()
3669 return (flags
& TFLAGScomplex
) != 0;
3672 bool TypeBasic::isunsigned()
3674 return (flags
& TFLAGSunsigned
) != 0;
3677 bool TypeBasic::isscalar()
3679 return (flags
& (TFLAGSintegral
| TFLAGSfloating
)) != 0;
3682 MATCH
TypeBasic::implicitConvTo(Type
*to
)
3684 //printf("TypeBasic::implicitConvTo(%s) from %s\n", to->toChars(), toChars());
3692 else if (MODimplicitConv(mod
, to
->mod
))
3694 else if (!((mod
^ to
->mod
) & MODshared
)) // for wild matching
3697 return MATCHconvert
;
3700 if (ty
== Tvoid
|| to
->ty
== Tvoid
)
3701 return MATCHnomatch
;
3702 if (to
->ty
== Tbool
)
3703 return MATCHnomatch
;
3706 if (to
->ty
== Tvector
&& to
->deco
)
3708 TypeVector
*tv
= (TypeVector
*)to
;
3709 tob
= tv
->elementType();
3711 else if (to
->ty
== Tenum
)
3713 EnumDeclaration
*ed
= ((TypeEnum
*)to
)->sym
;
3714 if (ed
->isSpecial())
3716 /* Special enums that allow implicit conversions to them. */
3717 tob
= to
->toBasetype()->isTypeBasic();
3719 return implicitConvTo(tob
);
3722 return MATCHnomatch
;
3725 tob
= to
->isTypeBasic();
3727 return MATCHnomatch
;
3729 if (flags
& TFLAGSintegral
)
3731 // Disallow implicit conversion of integers to imaginary or complex
3732 if (tob
->flags
& (TFLAGSimaginary
| TFLAGScomplex
))
3733 return MATCHnomatch
;
3735 // If converting from integral to integral
3736 if (tob
->flags
& TFLAGSintegral
)
3737 { d_uns64 sz
= size(Loc());
3738 d_uns64 tosz
= tob
->size(Loc());
3740 /* Can't convert to smaller size
3743 return MATCHnomatch
;
3745 /* Can't change sign if same size
3747 /*if (sz == tosz && (flags ^ tob->flags) & TFLAGSunsigned)
3748 return MATCHnomatch;*/
3751 else if (flags
& TFLAGSfloating
)
3753 // Disallow implicit conversion of floating point to integer
3754 if (tob
->flags
& TFLAGSintegral
)
3755 return MATCHnomatch
;
3757 assert(tob
->flags
& TFLAGSfloating
|| to
->ty
== Tvector
);
3759 // Disallow implicit conversion from complex to non-complex
3760 if (flags
& TFLAGScomplex
&& !(tob
->flags
& TFLAGScomplex
))
3761 return MATCHnomatch
;
3763 // Disallow implicit conversion of real or imaginary to complex
3764 if (flags
& (TFLAGSreal
| TFLAGSimaginary
) &&
3765 tob
->flags
& TFLAGScomplex
)
3766 return MATCHnomatch
;
3768 // Disallow implicit conversion to-from real and imaginary
3769 if ((flags
& (TFLAGSreal
| TFLAGSimaginary
)) !=
3770 (tob
->flags
& (TFLAGSreal
| TFLAGSimaginary
)))
3771 return MATCHnomatch
;
3773 return MATCHconvert
;
3776 TypeBasic
*TypeBasic::isTypeBasic()
3778 return (TypeBasic
*)this;
3781 /* ============================= TypeVector =========================== */
3783 /* The basetype must be one of:
3784 * byte[16],ubyte[16],short[8],ushort[8],int[4],uint[4],long[2],ulong[2],float[4],double[2]
3786 * byte[32],ubyte[32],short[16],ushort[16],int[8],uint[8],long[4],ulong[4],float[8],double[4]
3788 TypeVector::TypeVector(Type
*basetype
)
3791 this->basetype
= basetype
;
3794 TypeVector
*TypeVector::create(Type
*basetype
)
3796 return new TypeVector(basetype
);
3799 const char *TypeVector::kind()
3804 Type
*TypeVector::syntaxCopy()
3806 return new TypeVector(basetype
->syntaxCopy());
3809 TypeBasic
*TypeVector::elementType()
3811 assert(basetype
->ty
== Tsarray
);
3812 TypeSArray
*t
= (TypeSArray
*)basetype
;
3813 TypeBasic
*tb
= t
->nextOf()->isTypeBasic();
3818 bool TypeVector::isBoolean()
3823 d_uns64
TypeVector::size(Loc
)
3825 return basetype
->size();
3828 unsigned TypeVector::alignsize()
3830 return (unsigned)basetype
->size();
3833 Expression
*TypeVector::getProperty(Loc loc
, Identifier
*ident
, int flag
)
3835 return Type::getProperty(loc
, ident
, flag
);
3838 Expression
*TypeVector::dotExp(Scope
*sc
, Expression
*e
, Identifier
*ident
, int flag
)
3840 if (ident
== Id::ptr
&& e
->op
== TOKcall
)
3842 /* The trouble with TOKcall is the return ABI for float[4] is different from
3843 * __vector(float[4]), and a type paint won't do.
3845 e
= new AddrExp(e
->loc
, e
);
3846 e
= expressionSemantic(e
, sc
);
3847 e
= e
->castTo(sc
, basetype
->nextOf()->pointerTo());
3850 if (ident
== Id::array
)
3852 //e = e->castTo(sc, basetype);
3854 e
= new VectorArrayExp(e
->loc
, e
);
3855 e
= expressionSemantic(e
, sc
);
3858 if (ident
== Id::_init
|| ident
== Id::offsetof
|| ident
== Id::stringof
|| ident
== Id::__xalignof
)
3860 // init should return a new VectorExp (Bugzilla 12776)
3861 // offsetof does not work on a cast expression, so use e directly
3862 // stringof should not add a cast to the output
3863 return Type::dotExp(sc
, e
, ident
, flag
);
3865 return basetype
->dotExp(sc
, e
->castTo(sc
, basetype
), ident
, flag
);
3868 Expression
*TypeVector::defaultInit(Loc loc
)
3870 //printf("TypeVector::defaultInit()\n");
3871 assert(basetype
->ty
== Tsarray
);
3872 Expression
*e
= basetype
->defaultInit(loc
);
3873 VectorExp
*ve
= new VectorExp(loc
, e
, this);
3875 ve
->dim
= (int)(basetype
->size(loc
) / elementType()->size(loc
));
3879 Expression
*TypeVector::defaultInitLiteral(Loc loc
)
3881 //printf("TypeVector::defaultInitLiteral()\n");
3882 assert(basetype
->ty
== Tsarray
);
3883 Expression
*e
= basetype
->defaultInitLiteral(loc
);
3884 VectorExp
*ve
= new VectorExp(loc
, e
, this);
3886 ve
->dim
= (int)(basetype
->size(loc
) / elementType()->size(loc
));
3890 bool TypeVector::isZeroInit(Loc loc
)
3892 return basetype
->isZeroInit(loc
);
3895 bool TypeVector::isintegral()
3897 //printf("TypeVector::isintegral('%s') x%x\n", toChars(), flags);
3898 return basetype
->nextOf()->isintegral();
3901 bool TypeVector::isfloating()
3903 return basetype
->nextOf()->isfloating();
3906 bool TypeVector::isunsigned()
3908 return basetype
->nextOf()->isunsigned();
3911 bool TypeVector::isscalar()
3913 return basetype
->nextOf()->isscalar();
3916 MATCH
TypeVector::implicitConvTo(Type
*to
)
3918 //printf("TypeVector::implicitConvTo(%s) from %s\n", to->toChars(), toChars());
3922 if (to
->ty
== Tvector
)
3924 TypeVector
*tv
= (TypeVector
*)to
;
3925 assert(basetype
->ty
== Tsarray
&& tv
->basetype
->ty
== Tsarray
);
3927 // Can't convert to a vector which has different size.
3928 if (basetype
->size() != tv
->basetype
->size())
3929 return MATCHnomatch
;
3931 // Allow conversion to void[]
3932 if (tv
->basetype
->nextOf()->ty
== Tvoid
)
3933 return MATCHconvert
;
3935 // Otherwise implicitly convertible only if basetypes are.
3936 return basetype
->implicitConvTo(tv
->basetype
);
3940 return MATCHconvert
;
3942 return MATCHnomatch
;
3945 /***************************** TypeArray *****************************/
3947 TypeArray::TypeArray(TY ty
, Type
*next
)
3948 : TypeNext(ty
, next
)
3952 Expression
*TypeArray::dotExp(Scope
*sc
, Expression
*e
, Identifier
*ident
, int flag
)
3954 e
= Type::dotExp(sc
, e
, ident
, flag
);
3956 if (!(flag
& 1) || e
)
3957 e
= expressionSemantic(e
, sc
);
3962 /***************************** TypeSArray *****************************/
3964 TypeSArray::TypeSArray(Type
*t
, Expression
*dim
)
3965 : TypeArray(Tsarray
, t
)
3967 //printf("TypeSArray(%s)\n", dim->toChars());
3971 const char *TypeSArray::kind()
3976 Type
*TypeSArray::syntaxCopy()
3978 Type
*t
= next
->syntaxCopy();
3979 Expression
*e
= dim
->syntaxCopy();
3980 t
= new TypeSArray(t
, e
);
3985 d_uns64
TypeSArray::size(Loc loc
)
3987 //printf("TypeSArray::size()\n");
3988 uinteger_t n
= numberOfElems(loc
);
3989 uinteger_t elemsize
= baseElemOf()->size();
3990 bool overflow
= false;
3991 uinteger_t sz
= mulu(n
, elemsize
, overflow
);
3992 if (overflow
|| sz
>= UINT32_MAX
)
3994 if (elemsize
!= SIZE_INVALID
&& n
!= UINT32_MAX
)
3995 error(loc
, "static array `%s` size overflowed to %lld", toChars(), (long long)sz
);
3996 return SIZE_INVALID
;
4001 unsigned TypeSArray::alignsize()
4003 return next
->alignsize();
4006 void TypeSArray::resolve(Loc loc
, Scope
*sc
, Expression
**pe
, Type
**pt
, Dsymbol
**ps
, bool intypeid
)
4008 //printf("TypeSArray::resolve() %s\n", toChars());
4009 next
->resolve(loc
, sc
, pe
, pt
, ps
, intypeid
);
4010 //printf("s = %p, e = %p, t = %p\n", *ps, *pe, *pt);
4013 // It's really an index expression
4014 if (Dsymbol
*s
= getDsymbol(*pe
))
4015 *pe
= new DsymbolExp(loc
, s
);
4016 *pe
= new ArrayExp(loc
, *pe
, dim
);
4021 TupleDeclaration
*td
= s
->isTupleDeclaration();
4024 ScopeDsymbol
*sym
= new ArrayScopeSymbol(sc
, td
);
4025 sym
->parent
= sc
->scopesym
;
4027 sc
= sc
->startCTFE();
4028 dim
= expressionSemantic(dim
, sc
);
4032 dim
= dim
->ctfeInterpret();
4033 uinteger_t d
= dim
->toUInteger();
4035 if (d
>= td
->objects
->length
)
4037 error(loc
, "tuple index %llu exceeds length %u", d
, td
->objects
->length
);
4042 RootObject
*o
= (*td
->objects
)[(size_t)d
];
4043 if (o
->dyncast() == DYNCAST_DSYMBOL
)
4048 if (o
->dyncast() == DYNCAST_EXPRESSION
)
4050 Expression
*e
= (Expression
*)o
;
4051 if (e
->op
== TOKdsymbol
)
4053 *ps
= ((DsymbolExp
*)e
)->s
;
4063 if (o
->dyncast() == DYNCAST_TYPE
)
4066 *pt
= ((Type
*)o
)->addMod(this->mod
);
4070 /* Create a new TupleDeclaration which
4071 * is a slice [d..d+1] out of the old one.
4072 * Do it this way because TemplateInstance::semanticTiargs()
4073 * can handle unresolved Objects this way.
4075 Objects
*objects
= new Objects
;
4079 TupleDeclaration
*tds
= new TupleDeclaration(loc
, td
->ident
, objects
);
4087 if ((*pt
)->ty
!= Terror
)
4088 next
= *pt
; // prevent re-running semantic() on 'next'
4090 Type::resolve(loc
, sc
, pe
, pt
, ps
, intypeid
);
4094 Expression
*TypeSArray::dotExp(Scope
*sc
, Expression
*e
, Identifier
*ident
, int flag
)
4096 if (ident
== Id::length
)
4098 Loc oldLoc
= e
->loc
;
4102 else if (ident
== Id::ptr
)
4104 if (e
->op
== TOKtype
)
4106 e
->error("%s is not an expression", e
->toChars());
4107 return new ErrorExp();
4109 else if (!(flag
& 2) && sc
->func
&& !sc
->intypeof
&& sc
->func
->setUnsafe())
4111 e
->deprecation("%s.ptr cannot be used in @safe code, use &%s[0] instead", e
->toChars(), e
->toChars());
4112 // return new ErrorExp();
4114 e
= e
->castTo(sc
, e
->type
->nextOf()->pointerTo());
4118 e
= TypeArray::dotExp(sc
, e
, ident
, flag
);
4120 if (!(flag
& 1) || e
)
4121 e
= expressionSemantic(e
, sc
);
4125 structalign_t
TypeSArray::alignment()
4127 return next
->alignment();
4130 bool TypeSArray::isString()
4132 TY nty
= next
->toBasetype()->ty
;
4133 return nty
== Tchar
|| nty
== Twchar
|| nty
== Tdchar
;
4136 MATCH
TypeSArray::constConv(Type
*to
)
4138 if (to
->ty
== Tsarray
)
4140 TypeSArray
*tsa
= (TypeSArray
*)to
;
4141 if (!dim
->equals(tsa
->dim
))
4142 return MATCHnomatch
;
4144 return TypeNext::constConv(to
);
4147 MATCH
TypeSArray::implicitConvTo(Type
*to
)
4149 //printf("TypeSArray::implicitConvTo(to = %s) this = %s\n", to->toChars(), toChars());
4151 if (to
->ty
== Tarray
)
4153 TypeDArray
*ta
= (TypeDArray
*)to
;
4155 if (!MODimplicitConv(next
->mod
, ta
->next
->mod
))
4156 return MATCHnomatch
;
4158 /* Allow conversion to void[]
4160 if (ta
->next
->ty
== Tvoid
)
4162 return MATCHconvert
;
4165 MATCH m
= next
->constConv(ta
->next
);
4166 if (m
> MATCHnomatch
)
4168 return MATCHconvert
;
4170 return MATCHnomatch
;
4173 if (to
->ty
== Tsarray
)
4178 TypeSArray
*tsa
= (TypeSArray
*)to
;
4180 if (dim
->equals(tsa
->dim
))
4182 /* Since static arrays are value types, allow
4183 * conversions from const elements to non-const
4184 * ones, just like we allow conversion from const int
4187 MATCH m
= next
->implicitConvTo(tsa
->next
);
4188 if (m
>= MATCHconst
)
4196 return MATCHnomatch
;
4199 Expression
*TypeSArray::defaultInit(Loc loc
)
4201 if (next
->ty
== Tvoid
)
4202 return tuns8
->defaultInit(loc
);
4204 return next
->defaultInit(loc
);
4207 bool TypeSArray::isZeroInit(Loc loc
)
4209 return next
->isZeroInit(loc
);
4212 bool TypeSArray::needsDestruction()
4214 return next
->needsDestruction();
4217 /*********************************
4221 bool TypeSArray::needsNested()
4223 return next
->needsNested();
4226 Expression
*TypeSArray::defaultInitLiteral(Loc loc
)
4228 size_t d
= (size_t)dim
->toInteger();
4229 Expression
*elementinit
;
4230 if (next
->ty
== Tvoid
)
4231 elementinit
= tuns8
->defaultInitLiteral(loc
);
4233 elementinit
= next
->defaultInitLiteral(loc
);
4234 Expressions
*elements
= new Expressions();
4235 elements
->setDim(d
);
4236 for (size_t i
= 0; i
< d
; i
++)
4237 (*elements
)[i
] = NULL
;
4238 ArrayLiteralExp
*ae
= new ArrayLiteralExp(Loc(), this, elementinit
, elements
);
4242 bool TypeSArray::hasPointers()
4244 /* Don't want to do this, because:
4245 * struct S { T* array[0]; }
4246 * may be a variable length struct.
4248 //if (dim->toInteger() == 0)
4251 if (next
->ty
== Tvoid
)
4253 // Arrays of void contain arbitrary data, which may include pointers
4257 return next
->hasPointers();
4260 /***************************** TypeDArray *****************************/
4262 TypeDArray::TypeDArray(Type
*t
)
4263 : TypeArray(Tarray
, t
)
4265 //printf("TypeDArray(t = %p)\n", t);
4268 const char *TypeDArray::kind()
4273 Type
*TypeDArray::syntaxCopy()
4275 Type
*t
= next
->syntaxCopy();
4280 t
= new TypeDArray(t
);
4286 d_uns64
TypeDArray::size(Loc
)
4288 //printf("TypeDArray::size()\n");
4289 return target
.ptrsize
* 2;
4292 unsigned TypeDArray::alignsize()
4294 // A DArray consists of two ptr-sized values, so align it on pointer size
4296 return target
.ptrsize
;
4299 void TypeDArray::resolve(Loc loc
, Scope
*sc
, Expression
**pe
, Type
**pt
, Dsymbol
**ps
, bool intypeid
)
4301 //printf("TypeDArray::resolve() %s\n", toChars());
4302 next
->resolve(loc
, sc
, pe
, pt
, ps
, intypeid
);
4303 //printf("s = %p, e = %p, t = %p\n", *ps, *pe, *pt);
4306 // It's really a slice expression
4307 if (Dsymbol
*s
= getDsymbol(*pe
))
4308 *pe
= new DsymbolExp(loc
, s
);
4309 *pe
= new ArrayExp(loc
, *pe
);
4313 TupleDeclaration
*td
= (*ps
)->isTupleDeclaration();
4321 if ((*pt
)->ty
!= Terror
)
4322 next
= *pt
; // prevent re-running semantic() on 'next'
4324 Type::resolve(loc
, sc
, pe
, pt
, ps
, intypeid
);
4328 Expression
*TypeDArray::dotExp(Scope
*sc
, Expression
*e
, Identifier
*ident
, int flag
)
4330 if (e
->op
== TOKtype
&&
4331 (ident
== Id::length
|| ident
== Id::ptr
))
4333 e
->error("%s is not an expression", e
->toChars());
4334 return new ErrorExp();
4336 if (ident
== Id::length
)
4338 if (e
->op
== TOKstring
)
4340 StringExp
*se
= (StringExp
*)e
;
4341 return new IntegerExp(se
->loc
, se
->len
, Type::tsize_t
);
4343 if (e
->op
== TOKnull
)
4344 return new IntegerExp(e
->loc
, 0, Type::tsize_t
);
4345 if (checkNonAssignmentArrayOp(e
))
4346 return new ErrorExp();
4347 e
= new ArrayLengthExp(e
->loc
, e
);
4348 e
->type
= Type::tsize_t
;
4351 else if (ident
== Id::ptr
)
4353 if (!(flag
& 2) && sc
->func
&& !sc
->intypeof
&& sc
->func
->setUnsafe())
4355 e
->deprecation("%s.ptr cannot be used in @safe code, use &%s[0] instead", e
->toChars(), e
->toChars());
4356 // return new ErrorExp();
4358 e
= e
->castTo(sc
, next
->pointerTo());
4363 e
= TypeArray::dotExp(sc
, e
, ident
, flag
);
4368 bool TypeDArray::isString()
4370 TY nty
= next
->toBasetype()->ty
;
4371 return nty
== Tchar
|| nty
== Twchar
|| nty
== Tdchar
;
4374 MATCH
TypeDArray::implicitConvTo(Type
*to
)
4376 //printf("TypeDArray::implicitConvTo(to = %s) this = %s\n", to->toChars(), toChars());
4380 if (to
->ty
== Tarray
)
4382 TypeDArray
*ta
= (TypeDArray
*)to
;
4384 if (!MODimplicitConv(next
->mod
, ta
->next
->mod
))
4385 return MATCHnomatch
; // not const-compatible
4387 /* Allow conversion to void[]
4389 if (next
->ty
!= Tvoid
&& ta
->next
->ty
== Tvoid
)
4391 return MATCHconvert
;
4394 MATCH m
= next
->constConv(ta
->next
);
4395 if (m
> MATCHnomatch
)
4397 if (m
== MATCHexact
&& mod
!= to
->mod
)
4402 return Type::implicitConvTo(to
);
4405 Expression
*TypeDArray::defaultInit(Loc loc
)
4407 return new NullExp(loc
, this);
4410 bool TypeDArray::isZeroInit(Loc
)
4415 bool TypeDArray::isBoolean()
4420 bool TypeDArray::hasPointers()
4426 /***************************** TypeAArray *****************************/
4428 TypeAArray::TypeAArray(Type
*t
, Type
*index
)
4429 : TypeArray(Taarray
, t
)
4431 this->index
= index
;
4436 TypeAArray
*TypeAArray::create(Type
*t
, Type
*index
)
4438 return new TypeAArray(t
, index
);
4441 const char *TypeAArray::kind()
4446 Type
*TypeAArray::syntaxCopy()
4448 Type
*t
= next
->syntaxCopy();
4449 Type
*ti
= index
->syntaxCopy();
4450 if (t
== next
&& ti
== index
)
4454 t
= new TypeAArray(t
, ti
);
4460 d_uns64
TypeAArray::size(Loc
)
4462 return target
.ptrsize
;
4465 void TypeAArray::resolve(Loc loc
, Scope
*sc
, Expression
**pe
, Type
**pt
, Dsymbol
**ps
, bool intypeid
)
4467 //printf("TypeAArray::resolve() %s\n", toChars());
4469 // Deal with the case where we thought the index was a type, but
4470 // in reality it was an expression.
4471 if (index
->ty
== Tident
|| index
->ty
== Tinstance
|| index
->ty
== Tsarray
)
4477 index
->resolve(loc
, sc
, &e
, &t
, &s
, intypeid
);
4480 // It was an expression -
4481 // Rewrite as a static array
4482 TypeSArray
*tsa
= new TypeSArray(next
, e
);
4483 tsa
->mod
= this->mod
; // just copy mod field so tsa's semantic is not yet done
4484 return tsa
->resolve(loc
, sc
, pe
, pt
, ps
, intypeid
);
4489 index
->error(loc
, "index is not a type or an expression");
4491 Type::resolve(loc
, sc
, pe
, pt
, ps
, intypeid
);
4495 Expression
*TypeAArray::dotExp(Scope
*sc
, Expression
*e
, Identifier
*ident
, int flag
)
4497 if (ident
== Id::length
)
4499 static FuncDeclaration
*fd_aaLen
= NULL
;
4500 if (fd_aaLen
== NULL
)
4502 Parameters
*fparams
= new Parameters();
4503 fparams
->push(new Parameter(STCin
, this, NULL
, NULL
, NULL
));
4504 fd_aaLen
= FuncDeclaration::genCfunc(fparams
, Type::tsize_t
, Id::aaLen
);
4505 TypeFunction
*tf
= fd_aaLen
->type
->toTypeFunction();
4506 tf
->purity
= PUREconst
;
4507 tf
->isnothrow
= true;
4510 Expression
*ev
= new VarExp(e
->loc
, fd_aaLen
, false);
4511 e
= new CallExp(e
->loc
, ev
, e
);
4512 e
->type
= fd_aaLen
->type
->toTypeFunction()->next
;
4515 e
= Type::dotExp(sc
, e
, ident
, flag
);
4519 Expression
*TypeAArray::defaultInit(Loc loc
)
4521 return new NullExp(loc
, this);
4524 bool TypeAArray::isZeroInit(Loc
)
4529 bool TypeAArray::isBoolean()
4534 bool TypeAArray::hasPointers()
4539 MATCH
TypeAArray::implicitConvTo(Type
*to
)
4541 //printf("TypeAArray::implicitConvTo(to = %s) this = %s\n", to->toChars(), toChars());
4545 if (to
->ty
== Taarray
)
4546 { TypeAArray
*ta
= (TypeAArray
*)to
;
4548 if (!MODimplicitConv(next
->mod
, ta
->next
->mod
))
4549 return MATCHnomatch
; // not const-compatible
4551 if (!MODimplicitConv(index
->mod
, ta
->index
->mod
))
4552 return MATCHnomatch
; // not const-compatible
4554 MATCH m
= next
->constConv(ta
->next
);
4555 MATCH mi
= index
->constConv(ta
->index
);
4556 if (m
> MATCHnomatch
&& mi
> MATCHnomatch
)
4558 return MODimplicitConv(mod
, to
->mod
) ? MATCHconst
: MATCHnomatch
;
4561 return Type::implicitConvTo(to
);
4564 MATCH
TypeAArray::constConv(Type
*to
)
4566 if (to
->ty
== Taarray
)
4568 TypeAArray
*taa
= (TypeAArray
*)to
;
4569 MATCH mindex
= index
->constConv(taa
->index
);
4570 MATCH mkey
= next
->constConv(taa
->next
);
4571 // Pick the worst match
4572 return mkey
< mindex
? mkey
: mindex
;
4574 return Type::constConv(to
);
4577 /***************************** TypePointer *****************************/
4579 TypePointer::TypePointer(Type
*t
)
4580 : TypeNext(Tpointer
, t
)
4584 TypePointer
*TypePointer::create(Type
*t
)
4586 return new TypePointer(t
);
4589 const char *TypePointer::kind()
4594 Type
*TypePointer::syntaxCopy()
4596 Type
*t
= next
->syntaxCopy();
4601 t
= new TypePointer(t
);
4607 d_uns64
TypePointer::size(Loc
)
4609 return target
.ptrsize
;
4612 MATCH
TypePointer::implicitConvTo(Type
*to
)
4614 //printf("TypePointer::implicitConvTo(to = %s) %s\n", to->toChars(), toChars());
4618 if (next
->ty
== Tfunction
)
4620 if (to
->ty
== Tpointer
)
4622 TypePointer
*tp
= (TypePointer
*)to
;
4623 if (tp
->next
->ty
== Tfunction
)
4625 if (next
->equals(tp
->next
))
4628 if (next
->covariant(tp
->next
) == 1)
4630 Type
*tret
= this->next
->nextOf();
4631 Type
*toret
= tp
->next
->nextOf();
4632 if (tret
->ty
== Tclass
&& toret
->ty
== Tclass
)
4634 /* Bugzilla 10219: Check covariant interface return with offset tweaking.
4636 * class C : Object, I {}
4637 * I function() dg = function C() {} // should be error
4640 if (toret
->isBaseOf(tret
, &offset
) && offset
!= 0)
4641 return MATCHnomatch
;
4643 return MATCHconvert
;
4646 else if (tp
->next
->ty
== Tvoid
)
4648 // Allow conversions to void*
4649 return MATCHconvert
;
4652 return MATCHnomatch
;
4654 else if (to
->ty
== Tpointer
)
4656 TypePointer
*tp
= (TypePointer
*)to
;
4659 if (!MODimplicitConv(next
->mod
, tp
->next
->mod
))
4660 return MATCHnomatch
; // not const-compatible
4662 /* Alloc conversion to void*
4664 if (next
->ty
!= Tvoid
&& tp
->next
->ty
== Tvoid
)
4666 return MATCHconvert
;
4669 MATCH m
= next
->constConv(tp
->next
);
4670 if (m
> MATCHnomatch
)
4672 if (m
== MATCHexact
&& mod
!= to
->mod
)
4677 return MATCHnomatch
;
4680 MATCH
TypePointer::constConv(Type
*to
)
4682 if (next
->ty
== Tfunction
)
4684 if (to
->nextOf() && next
->equals(((TypeNext
*)to
)->next
))
4685 return Type::constConv(to
);
4687 return MATCHnomatch
;
4689 return TypeNext::constConv(to
);
4692 bool TypePointer::isscalar()
4697 Expression
*TypePointer::defaultInit(Loc loc
)
4699 return new NullExp(loc
, this);
4702 bool TypePointer::isZeroInit(Loc
)
4707 bool TypePointer::hasPointers()
4713 /***************************** TypeReference *****************************/
4715 TypeReference::TypeReference(Type
*t
)
4716 : TypeNext(Treference
, t
)
4718 // BUG: what about references to static arrays?
4721 const char *TypeReference::kind()
4726 Type
*TypeReference::syntaxCopy()
4728 Type
*t
= next
->syntaxCopy();
4733 t
= new TypeReference(t
);
4739 d_uns64
TypeReference::size(Loc
)
4741 return target
.ptrsize
;
4744 Expression
*TypeReference::dotExp(Scope
*sc
, Expression
*e
, Identifier
*ident
, int flag
)
4746 // References just forward things along
4747 return next
->dotExp(sc
, e
, ident
, flag
);
4750 Expression
*TypeReference::defaultInit(Loc loc
)
4752 return new NullExp(loc
, this);
4755 bool TypeReference::isZeroInit(Loc
)
4761 /***************************** TypeFunction *****************************/
4763 TypeFunction::TypeFunction(const ParameterList
&pl
, Type
*treturn
, LINK linkage
, StorageClass stc
)
4764 : TypeNext(Tfunction
, treturn
)
4766 //if (!treturn) *(char*)0=0;
4768 assert(VARARGnone
<= pl
.varargs
&& pl
.varargs
<= VARARGtypesafe
);
4769 this->parameterList
= pl
;
4770 this->linkage
= linkage
;
4772 this->isnothrow
= false;
4773 this->isnogc
= false;
4774 this->purity
= PUREimpure
;
4775 this->isproperty
= false;
4776 this->isref
= false;
4777 this->isreturn
= false;
4778 this->isscope
= false;
4779 this->isscopeinferred
= false;
4784 this->purity
= PUREfwdref
;
4785 if (stc
& STCnothrow
)
4786 this->isnothrow
= true;
4788 this->isnogc
= true;
4789 if (stc
& STCproperty
)
4790 this->isproperty
= true;
4794 if (stc
& STCreturn
)
4795 this->isreturn
= true;
4797 this->isscope
= true;
4798 if (stc
& STCscopeinferred
)
4799 this->isscopeinferred
= true;
4801 this->trust
= TRUSTdefault
;
4803 this->trust
= TRUSTsafe
;
4804 if (stc
& STCsystem
)
4805 this->trust
= TRUSTsystem
;
4806 if (stc
& STCtrusted
)
4807 this->trust
= TRUSTtrusted
;
4810 TypeFunction
*TypeFunction::create(Parameters
*parameters
, Type
*treturn
, VarArg varargs
, LINK linkage
, StorageClass stc
)
4812 return new TypeFunction(ParameterList(parameters
, varargs
), treturn
, linkage
, stc
);
4815 const char *TypeFunction::kind()
4820 Type
*TypeFunction::syntaxCopy()
4822 Type
*treturn
= next
? next
->syntaxCopy() : NULL
;
4823 Parameters
*parameters
= Parameter::arraySyntaxCopy(parameterList
.parameters
);
4824 TypeFunction
*t
= new TypeFunction(ParameterList(parameters
, parameterList
.varargs
),
4827 t
->isnothrow
= isnothrow
;
4830 t
->isproperty
= isproperty
;
4832 t
->isreturn
= isreturn
;
4833 t
->isscope
= isscope
;
4834 t
->isscopeinferred
= isscopeinferred
;
4841 /*******************************
4842 * Covariant means that 'this' can substitute for 't',
4843 * i.e. a pure function is a match for an impure type.
4845 * t = type 'this' is covariant with
4846 * pstc = if not null, store STCxxxx which would make it covariant
4847 * fix17349 = enable fix https://issues.dlang.org/show_bug.cgi?id=17349
4849 * 0 types are distinct
4850 * 1 this is covariant with t
4851 * 2 arguments match as far as overloading goes,
4852 * but types are not covariant
4853 * 3 cannot determine covariance because of forward references
4854 * *pstc STCxxxx which would make it covariant
4857 int Type::covariant(Type
*t
, StorageClass
*pstc
, bool fix17349
)
4861 StorageClass stc
= 0;
4863 bool notcovariant
= false;
4869 return 1; // covariant
4871 if (ty
!= Tfunction
|| t
->ty
!= Tfunction
)
4874 t1
= (TypeFunction
*)this;
4875 t2
= (TypeFunction
*)t
;
4877 if (t1
->parameterList
.varargs
!= t2
->parameterList
.varargs
)
4880 if (t1
->parameterList
.parameters
&& t2
->parameterList
.parameters
)
4882 size_t dim
= t1
->parameterList
.length();
4883 if (dim
!= t2
->parameterList
.length())
4886 for (size_t i
= 0; i
< dim
; i
++)
4888 Parameter
*fparam1
= t1
->parameterList
[i
];
4889 Parameter
*fparam2
= t2
->parameterList
[i
];
4891 if (!fparam1
->type
->equals(fparam2
->type
))
4895 Type
*tp1
= fparam1
->type
;
4896 Type
*tp2
= fparam2
->type
;
4897 if (tp1
->ty
== tp2
->ty
)
4899 if (tp1
->ty
== Tclass
)
4901 if (((TypeClass
*)tp1
)->sym
== ((TypeClass
*)tp2
)->sym
&& MODimplicitConv(tp2
->mod
, tp1
->mod
))
4904 else if (tp1
->ty
== Tstruct
)
4906 if (((TypeStruct
*)tp1
)->sym
== ((TypeStruct
*)tp2
)->sym
&& MODimplicitConv(tp2
->mod
, tp1
->mod
))
4909 else if (tp1
->ty
== Tpointer
)
4911 if (tp2
->implicitConvTo(tp1
))
4914 else if (tp1
->ty
== Tarray
)
4916 if (tp2
->implicitConvTo(tp1
))
4919 else if (tp1
->ty
== Tdelegate
)
4921 if (tp1
->implicitConvTo(tp2
))
4928 notcovariant
|= !fparam1
->isCovariant(t1
->isref
, fparam2
);
4931 else if (t1
->parameterList
.parameters
!= t2
->parameterList
.parameters
)
4933 size_t dim1
= t1
->parameterList
.length();
4934 size_t dim2
= t2
->parameterList
.length();
4939 // The argument lists match
4942 if (t1
->linkage
!= t2
->linkage
)
4947 Type
*t1n
= t1
->next
;
4948 Type
*t2n
= t2
->next
;
4950 if (!t1n
|| !t2n
) // happens with return type inference
4953 if (t1n
->equals(t2n
))
4955 if (t1n
->ty
== Tclass
&& t2n
->ty
== Tclass
)
4957 /* If same class type, but t2n is const, then it's
4958 * covariant. Do this test first because it can work on
4959 * forward references.
4961 if (((TypeClass
*)t1n
)->sym
== ((TypeClass
*)t2n
)->sym
&&
4962 MODimplicitConv(t1n
->mod
, t2n
->mod
))
4965 // If t1n is forward referenced:
4966 ClassDeclaration
*cd
= ((TypeClass
*)t1n
)->sym
;
4967 if (cd
->semanticRun
< PASSsemanticdone
&& !cd
->isBaseInfoComplete())
4968 dsymbolSemantic(cd
, NULL
);
4969 if (!cd
->isBaseInfoComplete())
4971 return 3; // forward references
4974 if (t1n
->ty
== Tstruct
&& t2n
->ty
== Tstruct
)
4976 if (((TypeStruct
*)t1n
)->sym
== ((TypeStruct
*)t2n
)->sym
&&
4977 MODimplicitConv(t1n
->mod
, t2n
->mod
))
4980 else if (t1n
->ty
== t2n
->ty
&& t1n
->implicitConvTo(t2n
))
4982 else if (t1n
->ty
== Tnull
)
4984 // NULL is covariant with any pointer type, but not with any
4985 // dynamic arrays, associative arrays or delegates.
4986 // https://issues.dlang.org/show_bug.cgi?id=8589
4987 // https://issues.dlang.org/show_bug.cgi?id=19618
4988 Type
*t2bn
= t2n
->toBasetype();
4989 if (t2bn
->ty
== Tnull
|| t2bn
->ty
== Tpointer
|| t2bn
->ty
== Tclass
)
4996 if (t1
->isref
!= t2
->isref
)
4999 if (!t1
->isref
&& (t1
->isscope
|| t2
->isscope
))
5001 StorageClass stc1
= t1
->isscope
? STCscope
: 0;
5002 StorageClass stc2
= t2
->isscope
? STCscope
: 0;
5015 if (!Parameter::isCovariantScope(t1
->isref
, stc1
, stc2
))
5019 // We can subtract 'return ref' from 'this', but cannot add it
5020 else if (t1
->isreturn
&& !t2
->isreturn
)
5023 /* Can convert mutable to const
5025 if (!MODimplicitConv(t2
->mod
, t1
->mod
))
5030 /* Can convert pure to impure, nothrow to throw, and nogc to gc
5032 if (!t1
->purity
&& t2
->purity
)
5035 if (!t1
->isnothrow
&& t2
->isnothrow
)
5038 if (!t1
->isnogc
&& t2
->isnogc
)
5041 /* Can convert safe/trusted to system
5043 if (t1
->trust
<= TRUSTsystem
&& t2
->trust
>= TRUSTtrusted
)
5045 // Should we infer trusted or safe? Go with safe.
5055 //printf("\tcovaraint: 1\n");
5059 //printf("\tcovaraint: 0\n");
5063 //printf("\tcovaraint: 2\n");
5067 bool TypeFunction::checkRetType(Loc loc
)
5069 Type
*tb
= next
->toBasetype();
5070 if (tb
->ty
== Tfunction
)
5072 error(loc
, "functions cannot return a function");
5073 next
= Type::terror
;
5075 if (tb
->ty
== Ttuple
)
5077 error(loc
, "functions cannot return a tuple");
5078 next
= Type::terror
;
5080 if (!isref
&& (tb
->ty
== Tstruct
|| tb
->ty
== Tsarray
))
5082 Type
*tb2
= tb
->baseElemOf();
5083 if (tb2
->ty
== Tstruct
&& !((TypeStruct
*)tb2
)->sym
->members
)
5085 error(loc
, "functions cannot return opaque type %s by value", tb
->toChars());
5086 next
= Type::terror
;
5089 if (tb
->ty
== Terror
)
5095 /* Determine purity level based on mutability of t
5096 * and whether it is a 'ref' type or not.
5098 static PURE
purityOfType(bool isref
, Type
*t
)
5102 if (t
->mod
& MODimmutable
)
5104 if (t
->mod
& (MODconst
| MODwild
))
5109 t
= t
->baseElemOf();
5111 if (!t
->hasPointers() || t
->mod
& MODimmutable
)
5114 /* Accept immutable(T)[] and immutable(T)* as being strongly pure
5116 if (t
->ty
== Tarray
|| t
->ty
== Tpointer
)
5118 Type
*tn
= t
->nextOf()->toBasetype();
5119 if (tn
->mod
& MODimmutable
)
5121 if (tn
->mod
& (MODconst
| MODwild
))
5125 /* The rest of this is too strict; fix later.
5126 * For example, the only pointer members of a struct may be immutable,
5127 * which would maintain strong purity.
5128 * (Just like for dynamic arrays and pointers above.)
5130 if (t
->mod
& (MODconst
| MODwild
))
5133 /* Should catch delegates and function pointers, and fold in their purity
5138 /********************************************
5139 * Set 'purity' field of 'this'.
5140 * Do this lazily, as the parameter types might be forward referenced.
5142 void TypeFunction::purityLevel()
5144 TypeFunction
*tf
= this;
5145 if (tf
->purity
!= PUREfwdref
)
5148 purity
= PUREstrong
; // assume strong until something weakens it
5150 /* Evaluate what kind of purity based on the modifiers for the parameters
5152 const size_t dim
= tf
->parameterList
.length();
5153 for (size_t i
= 0; i
< dim
; i
++)
5155 Parameter
*fparam
= tf
->parameterList
[i
];
5156 Type
*t
= fparam
->type
;
5160 if (fparam
->storageClass
& (STClazy
| STCout
))
5165 switch (purityOfType((fparam
->storageClass
& STCref
) != 0, t
))
5181 break; // since PUREweak, no need to check further
5184 if (purity
> PUREweak
&& tf
->nextOf())
5186 /* Adjust purity based on mutability of return type.
5187 * https://issues.dlang.org/show_bug.cgi?id=15862
5189 const PURE purity2
= purityOfType(tf
->isref
, tf
->nextOf());
5190 if (purity2
< purity
)
5193 tf
->purity
= purity
;
5196 // arguments get specially formatted
5197 static const char *getParamError(TypeFunction
*tf
, Expression
*arg
, Parameter
*par
)
5199 if (global
.gag
&& !global
.params
.showGaggedErrors
)
5201 // show qualification when toChars() is the same but types are different
5202 const char *at
= arg
->type
->toChars();
5203 bool qual
= !arg
->type
->equals(par
->type
) && strcmp(at
, par
->type
->toChars()) == 0;
5205 at
= arg
->type
->toPrettyChars(true);
5207 // only mention rvalue if it's relevant
5208 const bool rv
= !arg
->isLvalue() && (par
->storageClass
& (STCref
| STCout
)) != 0;
5209 buf
.printf("cannot pass %sargument `%s` of type `%s` to parameter `%s`",
5210 rv
? "rvalue " : "", arg
->toChars(), at
,
5211 parameterToChars(par
, tf
, qual
));
5212 return buf
.extractChars();
5215 static const char *getMatchError(const char *format
, ...)
5217 if (global
.gag
&& !global
.params
.showGaggedErrors
)
5221 va_start(ap
, format
);
5222 buf
.vprintf(format
, ap
);
5224 return buf
.extractChars();
5227 /********************************
5228 * 'args' are being matched to function 'this'
5229 * Determine match level.
5231 * flag 1 performing a partial ordering match
5232 * pMessage address to store error message, or null
5237 MATCH
TypeFunction::callMatch(Type
*tthis
, Expressions
*args
, int flag
, const char **pMessage
)
5239 //printf("TypeFunction::callMatch() %s\n", toChars());
5240 MATCH match
= MATCHexact
; // assume exact match
5241 unsigned char wildmatch
= 0;
5246 if (t
->toBasetype()->ty
== Tpointer
)
5247 t
= t
->toBasetype()->nextOf(); // change struct* to struct
5250 if (MODimplicitConv(t
->mod
, mod
))
5252 else if ((mod
& MODwild
) && MODimplicitConv(t
->mod
, (mod
& ~MODwild
) | MODconst
))
5257 return MATCHnomatch
;
5262 wildmatch
|= MODwild
;
5263 else if (t
->isConst())
5264 wildmatch
|= MODconst
;
5265 else if (t
->isImmutable())
5266 wildmatch
|= MODimmutable
;
5268 wildmatch
|= MODmutable
;
5272 size_t nparams
= parameterList
.length();
5273 size_t nargs
= args
? args
->length
: 0;
5274 if (nargs
> nparams
)
5276 if (parameterList
.varargs
== VARARGnone
)
5278 // suppress early exit if an error message is wanted,
5279 // so we can check any matching args are valid
5281 goto Nomatch
; // too many args; no match
5283 match
= MATCHconvert
; // match ... with a "conversion" match level
5286 for (size_t u
= 0; u
< nargs
; u
++)
5290 Parameter
*p
= parameterList
[u
];
5291 Expression
*arg
= (*args
)[u
];
5293 Type
*tprm
= p
->type
;
5294 Type
*targ
= arg
->type
;
5296 if (!(p
->storageClass
& STClazy
&& tprm
->ty
== Tvoid
&& targ
->ty
!= Tvoid
))
5298 bool isRef
= (p
->storageClass
& (STCref
| STCout
)) != 0;
5299 wildmatch
|= targ
->deduceWild(tprm
, isRef
);
5304 /* Calculate wild matching modifier
5306 if (wildmatch
& MODconst
|| wildmatch
& (wildmatch
- 1))
5307 wildmatch
= MODconst
;
5308 else if (wildmatch
& MODimmutable
)
5309 wildmatch
= MODimmutable
;
5310 else if (wildmatch
& MODwild
)
5311 wildmatch
= MODwild
;
5314 assert(wildmatch
& MODmutable
);
5315 wildmatch
= MODmutable
;
5319 for (size_t u
= 0; u
< nparams
; u
++)
5323 Parameter
*p
= parameterList
[u
];
5329 goto L1
; // try typesafe variadics
5332 Expression
*arg
= (*args
)[u
];
5334 //printf("arg: %s, type: %s\n", arg->toChars(), arg->type->toChars());
5336 Type
*targ
= arg
->type
;
5337 Type
*tprm
= wildmatch
? p
->type
->substWildTo(wildmatch
) : p
->type
;
5339 if (p
->storageClass
& STClazy
&& tprm
->ty
== Tvoid
&& targ
->ty
!= Tvoid
)
5343 //printf("%s of type %s implicitConvTo %s\n", arg->toChars(), targ->toChars(), tprm->toChars());
5346 // for partial ordering, value is an irrelevant mockup, just look at the type
5347 m
= targ
->implicitConvTo(tprm
);
5350 m
= arg
->implicitConvTo(tprm
);
5351 //printf("match %d\n", m);
5354 // Non-lvalues do not match ref or out parameters
5355 if (p
->storageClass
& (STCref
| STCout
))
5357 // Bugzilla 13783: Don't use toBasetype() to handle enum types.
5360 //printf("fparam[%d] ta = %s, tp = %s\n", u, ta->toChars(), tp->toChars());
5362 if (m
&& !arg
->isLvalue())
5364 if (p
->storageClass
& STCout
)
5366 if (pMessage
) *pMessage
= getParamError(this, arg
, p
);
5370 if (arg
->op
== TOKstring
&& tp
->ty
== Tsarray
)
5372 if (ta
->ty
!= Tsarray
)
5374 Type
*tn
= tp
->nextOf()->castMod(ta
->nextOf()->mod
);
5375 dinteger_t dim
= ((StringExp
*)arg
)->len
;
5376 ta
= tn
->sarrayOf(dim
);
5379 else if (arg
->op
== TOKslice
&& tp
->ty
== Tsarray
)
5381 // Allow conversion from T[lwr .. upr] to ref T[upr-lwr]
5382 if (ta
->ty
!= Tsarray
)
5384 Type
*tn
= ta
->nextOf();
5385 dinteger_t dim
= ((TypeSArray
*)tp
)->dim
->toUInteger();
5386 ta
= tn
->sarrayOf(dim
);
5391 if (pMessage
) *pMessage
= getParamError(this, arg
, p
);
5396 /* Find most derived alias this type being matched.
5397 * Bugzilla 15674: Allow on both ref and out parameters.
5401 Type
*tat
= ta
->toBasetype()->aliasthisOf();
5402 if (!tat
|| !tat
->implicitConvTo(tprm
))
5407 /* A ref variable should work like a head-const reference.
5409 * ref T <- an lvalue of const(T) argument
5410 * ref T[dim] <- an lvalue of const(T[dim]) argument
5412 if (!ta
->constConv(tp
))
5414 if (pMessage
) *pMessage
= getParamError(this, arg
, p
);
5420 /* prefer matching the element type rather than the array
5421 * type when more arguments are present with T[]...
5423 if (parameterList
.varargs
== VARARGtypesafe
&& u
+ 1 == nparams
&& nargs
> nparams
)
5426 //printf("\tm = %d\n", m);
5427 if (m
== MATCHnomatch
) // if no match
5430 if (parameterList
.varargs
== VARARGtypesafe
&& u
+ 1 == nparams
) // if last varargs param
5432 Type
*tb
= p
->type
->toBasetype();
5439 tsa
= (TypeSArray
*)tb
;
5440 sz
= tsa
->dim
->toInteger();
5441 if (sz
!= nargs
- u
)
5444 *pMessage
= getMatchError("expected %llu variadic argument(s), not %zu", sz
, nargs
- u
);
5450 TypeArray
*ta
= (TypeArray
*)tb
;
5451 for (; u
< nargs
; u
++)
5453 Expression
*arg
= (*args
)[u
];
5456 /* If lazy array of delegates,
5457 * convert arg(s) to delegate(s)
5459 Type
*tret
= p
->isLazyArray();
5462 if (ta
->next
->equals(arg
->type
))
5464 else if (tret
->toBasetype()->ty
== Tvoid
)
5468 m
= arg
->implicitConvTo(tret
);
5469 if (m
== MATCHnomatch
)
5470 m
= arg
->implicitConvTo(ta
->next
);
5474 m
= arg
->implicitConvTo(ta
->next
);
5476 if (m
== MATCHnomatch
)
5478 if (pMessage
) *pMessage
= getParamError(this, arg
, p
);
5487 // Should see if there's a constructor match?
5488 // Or just leave it ambiguous?
5495 if (pMessage
&& u
< nargs
)
5496 *pMessage
= getParamError(this, (*args
)[u
], p
);
5498 *pMessage
= getMatchError("missing argument for parameter #%d: `%s`",
5499 u
+ 1, parameterToChars(p
, this, false));
5503 match
= m
; // pick worst match
5507 if (pMessage
&& !parameterList
.varargs
&& nargs
> nparams
)
5509 // all parameters had a match, but there are surplus args
5510 *pMessage
= getMatchError("expected %d argument(s), not %d", nparams
, nargs
);
5513 //printf("match = %d\n", match);
5517 //printf("no match\n");
5518 return MATCHnomatch
;
5521 /********************************************
5522 * Return true if there are lazy parameters.
5524 bool TypeFunction::hasLazyParameters()
5526 size_t dim
= parameterList
.length();
5527 for (size_t i
= 0; i
< dim
; i
++)
5529 Parameter
*fparam
= parameterList
[i
];
5530 if (fparam
->storageClass
& STClazy
)
5536 /*******************************
5537 * Check for `extern (D) U func(T t, ...)` variadic function type,
5538 * which has `_arguments[]` added as the first argument.
5540 * true if D-style variadic
5542 bool TypeFunction::isDstyleVariadic() const
5544 return linkage
== LINKd
&& parameterList
.varargs
== VARARGvariadic
;
5547 /***************************
5548 * Examine function signature for parameter p and see if
5549 * the value of p can 'escape' the scope of the function.
5550 * This is useful to minimize the needed annotations for the parameters.
5552 * p = parameter to this function
5554 * true if escapes via assignment to global or through a parameter
5557 bool TypeFunction::parameterEscapes(Parameter
*p
)
5559 /* Scope parameters do not escape.
5560 * Allow 'lazy' to imply 'scope' -
5561 * lazy parameters can be passed along
5562 * as lazy parameters to the next function, but that isn't
5565 if (parameterStorageClass(p
) & (STCscope
| STClazy
))
5570 /************************************
5571 * Take the specified storage class for p,
5572 * and use the function signature to infer whether
5573 * STCscope and STCreturn should be OR'd in.
5574 * (This will not affect the name mangling.)
5576 * p = one of the parameters to 'this'
5578 * storage class with STCscope or STCreturn OR'd in
5580 StorageClass
TypeFunction::parameterStorageClass(Parameter
*p
)
5582 StorageClass stc
= p
->storageClass
;
5583 if (!global
.params
.vsafe
)
5586 if (stc
& (STCscope
| STCreturn
| STClazy
) || purity
== PUREimpure
)
5589 /* If haven't inferred the return type yet, can't infer storage classes
5596 // See if p can escape via any of the other parameters
5597 if (purity
== PUREweak
)
5599 const size_t dim
= parameterList
.length();
5600 for (size_t i
= 0; i
< dim
; i
++)
5602 Parameter
*fparam
= parameterList
[i
];
5603 Type
*t
= fparam
->type
;
5606 t
= t
->baseElemOf();
5607 if (t
->isMutable() && t
->hasPointers())
5609 if (fparam
->storageClass
& (STCref
| STCout
))
5612 else if (t
->ty
== Tarray
|| t
->ty
== Tpointer
)
5614 Type
*tn
= t
->nextOf()->toBasetype();
5615 if (!(tn
->isMutable() && tn
->hasPointers()))
5625 /* Inferring STCreturn here has false positives
5626 * for pure functions, producing spurious error messages
5627 * about escaping references.
5628 * Give up on it for now.
5633 Expression
*TypeFunction::defaultInit(Loc loc
)
5635 error(loc
, "function does not have a default initializer");
5636 return new ErrorExp();
5639 Type
*TypeFunction::addStorageClass(StorageClass stc
)
5641 //printf("addStorageClass(%llx) %d\n", stc, (stc & STCscope) != 0);
5642 TypeFunction
*t
= Type::addStorageClass(stc
)->toTypeFunction();
5643 if ((stc
& STCpure
&& !t
->purity
) ||
5644 (stc
& STCnothrow
&& !t
->isnothrow
) ||
5645 (stc
& STCnogc
&& !t
->isnogc
) ||
5646 (stc
& STCscope
&& !t
->isscope
) ||
5647 (stc
& STCsafe
&& t
->trust
< TRUSTtrusted
))
5649 // Klunky to change these
5650 TypeFunction
*tf
= new TypeFunction(t
->parameterList
, t
->next
, t
->linkage
, 0);
5653 tf
->purity
= t
->purity
;
5654 tf
->isnothrow
= t
->isnothrow
;
5655 tf
->isnogc
= t
->isnogc
;
5656 tf
->isproperty
= t
->isproperty
;
5657 tf
->isref
= t
->isref
;
5658 tf
->isreturn
= t
->isreturn
;
5659 tf
->isscope
= t
->isscope
;
5660 tf
->isscopeinferred
= t
->isscopeinferred
;
5661 tf
->trust
= t
->trust
;
5662 tf
->iswild
= t
->iswild
;
5665 tf
->purity
= PUREfwdref
;
5666 if (stc
& STCnothrow
)
5667 tf
->isnothrow
= true;
5671 tf
->trust
= TRUSTsafe
;
5675 if (stc
& STCscopeinferred
)
5676 tf
->isscopeinferred
= true;
5679 tf
->deco
= tf
->merge()->deco
;
5685 /** For each active attribute (ref/const/nogc/etc) call fp with a void* for the
5686 work param and a string representation of the attribute. */
5687 int TypeFunction::attributesApply(void *param
, int (*fp
)(void *, const char *), TRUSTformat trustFormat
)
5691 if (purity
) res
= fp(param
, "pure");
5692 if (res
) return res
;
5694 if (isnothrow
) res
= fp(param
, "nothrow");
5695 if (res
) return res
;
5697 if (isnogc
) res
= fp(param
, "@nogc");
5698 if (res
) return res
;
5700 if (isproperty
) res
= fp(param
, "@property");
5701 if (res
) return res
;
5703 if (isref
) res
= fp(param
, "ref");
5704 if (res
) return res
;
5706 if (isreturn
) res
= fp(param
, "return");
5707 if (res
) return res
;
5709 if (isscope
&& !isscopeinferred
) res
= fp(param
, "scope");
5710 if (res
) return res
;
5712 TRUST trustAttrib
= trust
;
5714 if (trustAttrib
== TRUSTdefault
)
5716 // Print out "@system" when trust equals TRUSTdefault (if desired).
5717 if (trustFormat
== TRUSTformatSystem
)
5718 trustAttrib
= TRUSTsystem
;
5720 return res
; // avoid calling with an empty string
5723 return fp(param
, trustToChars(trustAttrib
));
5726 /***************************** TypeDelegate *****************************/
5728 TypeDelegate::TypeDelegate(Type
*t
)
5729 : TypeNext(Tfunction
, t
)
5734 TypeDelegate
*TypeDelegate::create(Type
*t
)
5736 return new TypeDelegate(t
);
5739 const char *TypeDelegate::kind()
5744 Type
*TypeDelegate::syntaxCopy()
5746 Type
*t
= next
->syntaxCopy();
5751 t
= new TypeDelegate(t
);
5757 Type
*TypeDelegate::addStorageClass(StorageClass stc
)
5759 TypeDelegate
*t
= (TypeDelegate
*)Type::addStorageClass(stc
);
5760 if (!global
.params
.vsafe
)
5763 /* The rest is meant to add 'scope' to a delegate declaration if it is of the form:
5764 * alias dg_t = void* delegate();
5765 * scope dg_t dg = ...;
5769 Type
*n
= t
->next
->addStorageClass(STCscope
| STCscopeinferred
);
5773 t
->deco
= t
->merge()->deco
; // mangling supposed to not be changed due to STCscopeinferrred
5779 d_uns64
TypeDelegate::size(Loc
)
5781 return target
.ptrsize
* 2;
5784 unsigned TypeDelegate::alignsize()
5786 return target
.ptrsize
;
5789 MATCH
TypeDelegate::implicitConvTo(Type
*to
)
5791 //printf("TypeDelegate::implicitConvTo(this=%p, to=%p)\n", this, to);
5792 //printf("from: %s\n", toChars());
5793 //printf("to : %s\n", to->toChars());
5796 #if 1 // not allowing covariant conversions because it interferes with overriding
5797 if (to
->ty
== Tdelegate
&& this->nextOf()->covariant(to
->nextOf()) == 1)
5799 Type
*tret
= this->next
->nextOf();
5800 Type
*toret
= ((TypeDelegate
*)to
)->next
->nextOf();
5801 if (tret
->ty
== Tclass
&& toret
->ty
== Tclass
)
5803 /* Bugzilla 10219: Check covariant interface return with offset tweaking.
5805 * class C : Object, I {}
5806 * I delegate() dg = delegate C() {} // should be error
5809 if (toret
->isBaseOf(tret
, &offset
) && offset
!= 0)
5810 return MATCHnomatch
;
5812 return MATCHconvert
;
5815 return MATCHnomatch
;
5818 Expression
*TypeDelegate::defaultInit(Loc loc
)
5820 return new NullExp(loc
, this);
5823 bool TypeDelegate::isZeroInit(Loc
)
5828 bool TypeDelegate::isBoolean()
5833 Expression
*TypeDelegate::dotExp(Scope
*sc
, Expression
*e
, Identifier
*ident
, int flag
)
5835 if (ident
== Id::ptr
)
5837 e
= new DelegatePtrExp(e
->loc
, e
);
5838 e
= expressionSemantic(e
, sc
);
5840 else if (ident
== Id::funcptr
)
5842 if (!(flag
& 2) && sc
->func
&& !sc
->intypeof
&& sc
->func
->setUnsafe())
5844 e
->error("%s.funcptr cannot be used in @safe code", e
->toChars());
5845 return new ErrorExp();
5847 e
= new DelegateFuncptrExp(e
->loc
, e
);
5848 e
= expressionSemantic(e
, sc
);
5852 e
= Type::dotExp(sc
, e
, ident
, flag
);
5857 bool TypeDelegate::hasPointers()
5862 /***************************** TypeTraits ********************************/
5864 TypeTraits::TypeTraits(const Loc
&loc
, TraitsExp
*exp
)
5872 Type
*TypeTraits::syntaxCopy()
5874 TraitsExp
*te
= (TraitsExp
*) exp
->syntaxCopy();
5875 TypeTraits
*tt
= new TypeTraits(loc
, te
);
5880 Dsymbol
*TypeTraits::toDsymbol(Scope
*sc
)
5883 Expression
*e
= NULL
;
5885 resolve(loc
, sc
, &e
, &t
, &s
);
5886 if (t
&& t
->ty
!= Terror
)
5887 s
= t
->toDsymbol(sc
);
5894 void TypeTraits::resolve(Loc loc
, Scope
*sc
, Expression
**pe
, Type
**pt
, Dsymbol
**ps
, bool)
5900 if (Type
*t
= typeSemantic(this, loc
, sc
))
5908 d_uns64
TypeTraits::size(Loc
)
5910 return SIZE_INVALID
;
5913 /***************************** TypeMixin *****************************/
5916 * Implements mixin types.
5918 * Semantic analysis will convert it to a real type.
5920 TypeMixin::TypeMixin(const Loc
&loc
, Expressions
*exps
)
5925 this->obj
= NULL
; // cached result of semantic analysis.
5928 const char *TypeMixin::kind()
5933 Type
*TypeMixin::syntaxCopy()
5935 return new TypeMixin(loc
, Expression::arraySyntaxCopy(exps
));
5938 Dsymbol
*TypeMixin::toDsymbol(Scope
*sc
)
5941 Expression
*e
= NULL
;
5943 resolve(loc
, sc
, &e
, &t
, &s
);
5945 s
= t
->toDsymbol(sc
);
5952 void TypeMixin::resolve(Loc loc
, Scope
*sc
, Expression
**pe
, Type
**pt
, Dsymbol
**ps
, bool intypeid
)
5954 // if already resolved just set pe/pt/ps and return.
5957 *pe
= isExpression(obj
);
5959 *ps
= isDsymbol(obj
);
5963 RootObject
*o
= compileTypeMixin(this, loc
, sc
);
5964 if (Type
*t
= isType(o
))
5966 t
->resolve(loc
, sc
, pe
, pt
, ps
, intypeid
);
5968 (*pt
) = (*pt
)->addMod(mod
);
5970 else if (Expression
*e
= isExpression(o
))
5972 e
= expressionSemantic(e
, sc
);
5973 if (TypeExp
*et
= e
->isTypeExp())
5976 *pt
= et
->type
->addMod(mod
);
5994 obj
= *pe
? (RootObject
*)*pe
: (*pt
? (RootObject
*)*pt
: (RootObject
*)*ps
);
5997 /***************************** TypeQualified *****************************/
5999 TypeQualified::TypeQualified(TY ty
, Loc loc
)
6005 void TypeQualified::syntaxCopyHelper(TypeQualified
*t
)
6007 //printf("TypeQualified::syntaxCopyHelper(%s) %s\n", t->toChars(), toChars());
6008 idents
.setDim(t
->idents
.length
);
6009 for (size_t i
= 0; i
< idents
.length
; i
++)
6011 RootObject
*id
= t
->idents
[i
];
6012 if (id
->dyncast() == DYNCAST_DSYMBOL
)
6014 TemplateInstance
*ti
= (TemplateInstance
*)id
;
6016 ti
= (TemplateInstance
*)ti
->syntaxCopy(NULL
);
6019 else if (id
->dyncast() == DYNCAST_EXPRESSION
)
6021 Expression
*e
= (Expression
*)id
;
6022 e
= e
->syntaxCopy();
6025 else if (id
->dyncast() == DYNCAST_TYPE
)
6027 Type
*tx
= (Type
*)id
;
6028 tx
= tx
->syntaxCopy();
6035 void TypeQualified::addIdent(Identifier
*ident
)
6040 void TypeQualified::addInst(TemplateInstance
*inst
)
6045 void TypeQualified::addIndex(RootObject
*e
)
6050 d_uns64
TypeQualified::size(Loc
)
6052 error(this->loc
, "size of type %s is not known", toChars());
6053 return SIZE_INVALID
;
6056 /*************************************
6057 * Resolve a tuple index.
6059 void TypeQualified::resolveTupleIndex(Loc loc
, Scope
*sc
, Dsymbol
*s
,
6060 Expression
**pe
, Type
**pt
, Dsymbol
**ps
, RootObject
*oindex
)
6066 TupleDeclaration
*td
= s
->isTupleDeclaration();
6068 Expression
*eindex
= isExpression(oindex
);
6069 Type
*tindex
= isType(oindex
);
6070 Dsymbol
*sindex
= isDsymbol(oindex
);
6074 // It's really an index expression
6076 eindex
= new TypeExp(loc
, tindex
);
6078 eindex
= ::resolve(loc
, sc
, sindex
, false);
6079 Expression
*e
= new IndexExp(loc
, ::resolve(loc
, sc
, s
, false), eindex
);
6080 e
= expressionSemantic(e
, sc
);
6081 resolveExp(e
, pt
, pe
, ps
);
6085 // Convert oindex to Expression, then try to resolve to constant.
6087 tindex
->resolve(loc
, sc
, &eindex
, &tindex
, &sindex
);
6089 eindex
= ::resolve(loc
, sc
, sindex
, false);
6092 ::error(loc
, "index is %s not an expression", oindex
->toChars());
6096 sc
= sc
->startCTFE();
6097 eindex
= expressionSemantic(eindex
, sc
);
6100 eindex
= eindex
->ctfeInterpret();
6101 if (eindex
->op
== TOKerror
)
6107 const uinteger_t d
= eindex
->toUInteger();
6108 if (d
>= td
->objects
->length
)
6110 ::error(loc
, "tuple index %llu exceeds length %u", (ulonglong
)d
, (unsigned)td
->objects
->length
);
6115 RootObject
*o
= (*td
->objects
)[(size_t)d
];
6118 *pe
= isExpression(o
);
6121 *pt
= typeSemantic(*pt
, loc
, sc
);
6123 resolveExp(*pe
, pt
, pe
, ps
);
6126 /*************************************
6127 * Takes an array of Identifiers and figures out if
6128 * it represents a Type or an Expression.
6130 * if expression, *pe is set
6131 * if type, *pt is set
6133 void TypeQualified::resolveHelper(Loc loc
, Scope
*sc
,
6134 Dsymbol
*s
, Dsymbol
*,
6135 Expression
**pe
, Type
**pt
, Dsymbol
**ps
, bool intypeid
)
6142 //printf("\t1: s = '%s' %p, kind = '%s'\n",s->toChars(), s, s->kind());
6143 Declaration
*d
= s
->isDeclaration();
6144 if (d
&& (d
->storage_class
& STCtemplateparameter
))
6148 // check for deprecated aliases
6149 s
->checkDeprecated(loc
, sc
);
6151 d
->checkDisabled(loc
, sc
, true);
6155 //printf("\t2: s = '%s' %p, kind = '%s'\n",s->toChars(), s, s->kind());
6156 for (size_t i
= 0; i
< idents
.length
; i
++)
6158 RootObject
*id
= idents
[i
];
6160 if (id
->dyncast() == DYNCAST_EXPRESSION
||
6161 id
->dyncast() == DYNCAST_TYPE
)
6166 resolveTupleIndex(loc
, sc
, s
, &ex
, &tx
, &sx
, id
);
6173 ex
= new TypeExp(loc
, tx
);
6176 ex
= typeToExpressionHelper(this, ex
, i
+ 1);
6177 ex
= expressionSemantic(ex
, sc
);
6178 resolveExp(ex
, pt
, pe
, ps
);
6182 Type
*t
= s
->getType(); // type symbol, type alias, or type tuple?
6183 unsigned errorsave
= global
.errors
;
6184 int flags
= t
== NULL
? SearchLocalsOnly
: IgnorePrivateImports
;
6185 Dsymbol
*sm
= s
->searchX(loc
, sc
, id
, flags
);
6188 if (!(sc
->flags
& SCOPEignoresymbolvisibility
) && !symbolIsVisible(sc
, sm
))
6190 ::error(loc
, "`%s` is not visible from module `%s`", sm
->toPrettyChars(), sc
->_module
->toChars());
6193 // Same check as in Expression::semanticY(DotIdExp)
6194 else if (sm
->isPackage() && checkAccess(sc
, (Package
*)sm
))
6196 // @@@DEPRECATED_2.096@@@
6197 // Should be an error in 2.106. Just remove the deprecation call
6198 // and uncomment the null assignment
6199 ::deprecation(loc
, "%s %s is not accessible here, perhaps add 'static import %s;'",
6200 sm
->kind(), sm
->toPrettyChars(), sm
->toPrettyChars());
6204 if (global
.errors
!= errorsave
)
6209 //printf("\t3: s = %p %s %s, sm = %p\n", s, s->kind(), s->toChars(), sm);
6210 if (intypeid
&& !t
&& sm
&& sm
->needThis())
6212 if (VarDeclaration
*v
= s
->isVarDeclaration())
6214 // https://issues.dlang.org/show_bug.cgi?id=19913
6215 // v->type would be null if it is a forward referenced member.
6216 if (v
->type
== NULL
)
6217 dsymbolSemantic(v
, sc
);
6218 if (v
->storage_class
& (STCconst
| STCimmutable
| STCmanifest
) ||
6219 v
->type
->isConst() || v
->type
->isImmutable())
6221 // Bugzilla 13087: this.field is not constant always
6222 if (!v
->isThisDeclaration())
6230 if (s
->isDeclaration()) // var, func, or tuple declaration?
6232 t
= s
->isDeclaration()->type
;
6233 if (!t
&& s
->isTupleDeclaration()) // expression tuple?
6236 else if (s
->isTemplateInstance() ||
6237 s
->isImport() || s
->isPackage() || s
->isModule())
6244 sm
= t
->toDsymbol(sc
);
6245 if (sm
&& id
->dyncast() == DYNCAST_IDENTIFIER
)
6247 sm
= sm
->search(loc
, (Identifier
*)id
, IgnorePrivateImports
);
6253 VarDeclaration
*v
= s
->isVarDeclaration();
6254 FuncDeclaration
*f
= s
->isFuncDeclaration();
6255 if (intypeid
|| (!v
&& !f
))
6256 e
= ::resolve(loc
, sc
, s
, true);
6258 e
= new VarExp(loc
, s
->isDeclaration(), true);
6260 e
= typeToExpressionHelper(this, e
, i
);
6261 e
= expressionSemantic(e
, sc
);
6262 resolveExp(e
, pt
, pe
, ps
);
6267 if (id
->dyncast() == DYNCAST_DSYMBOL
)
6269 // searchX already handles errors for template instances
6270 assert(global
.errors
);
6274 assert(id
->dyncast() == DYNCAST_IDENTIFIER
);
6275 sm
= s
->search_correct((Identifier
*)id
);
6277 error(loc
, "identifier `%s` of `%s` is not defined, did you mean %s `%s`?",
6278 id
->toChars(), toChars(), sm
->kind(), sm
->toChars());
6280 error(loc
, "identifier `%s` of `%s` is not defined", id
->toChars(), toChars());
6282 *pe
= new ErrorExp();
6290 if (EnumMember
*em
= s
->isEnumMember())
6292 // It's not a type, it's an expression
6293 *pe
= em
->getVarExp(loc
, sc
);
6296 if (VarDeclaration
*v
= s
->isVarDeclaration())
6298 /* This is mostly same with DsymbolExp::semantic(), but we cannot use it
6299 * because some variables used in type context need to prevent lowering
6300 * to a literal or contextful expression. For example:
6302 * enum a = 1; alias b = a;
6303 * template X(alias e){ alias v = e; } alias x = X!(1);
6304 * struct S { int v; alias w = v; }
6305 * // TypeIdentifier 'a', 'e', and 'v' should be TOKvar,
6306 * // because getDsymbol() need to work in AliasDeclaration::semantic().
6309 (!v
->type
->deco
&& v
->inuse
))
6311 if (v
->inuse
) // Bugzilla 9494
6312 error(loc
, "circular reference to %s `%s`", v
->kind(), v
->toPrettyChars());
6314 error(loc
, "forward reference to %s `%s`", v
->kind(), v
->toPrettyChars());
6318 if (v
->type
->ty
== Terror
)
6321 *pe
= new VarExp(loc
, v
);
6324 if (FuncLiteralDeclaration
*fld
= s
->isFuncLiteralDeclaration())
6326 //printf("'%s' is a function literal\n", fld->toChars());
6327 *pe
= new FuncExp(loc
, fld
);
6328 *pe
= expressionSemantic(*pe
, sc
);
6332 Type
*t
= s
->getType();
6335 // If the symbol is an import, try looking inside the import
6336 if (Import
*si
= s
->isImport())
6338 s
= si
->search(loc
, s
->ident
);
6346 if (t
->ty
== Tinstance
&& t
!= this && !t
->deco
)
6348 if (!((TypeInstance
*)t
)->tempinst
->errors
)
6349 error(loc
, "forward reference to `%s`", t
->toChars());
6354 if (t
->ty
== Ttuple
)
6361 /* Look for what user might have intended
6363 const char *p
= mutableOf()->unSharedOf()->toChars();
6364 Identifier
*id
= Identifier::idPool(p
, strlen(p
));
6365 if (const char *n
= importHint(p
))
6366 error(loc
, "`%s` is not defined, perhaps `import %s;` ?", p
, n
);
6367 else if (Dsymbol
*s2
= sc
->search_correct(id
))
6368 error(loc
, "undefined identifier `%s`, did you mean %s `%s`?", p
, s2
->kind(), s2
->toChars());
6369 else if (const char *q
= Scope::search_correct_C(id
))
6370 error(loc
, "undefined identifier `%s`, did you mean `%s`?", p
, q
);
6372 error(loc
, "undefined identifier `%s`", p
);
6378 /***************************** TypeIdentifier *****************************/
6380 TypeIdentifier::TypeIdentifier(Loc loc
, Identifier
*ident
)
6381 : TypeQualified(Tident
, loc
)
6383 this->ident
= ident
;
6386 const char *TypeIdentifier::kind()
6388 return "identifier";
6391 Type
*TypeIdentifier::syntaxCopy()
6393 TypeIdentifier
*t
= new TypeIdentifier(loc
, ident
);
6394 t
->syntaxCopyHelper(this);
6399 /*************************************
6400 * Takes an array of Identifiers and figures out if
6401 * it represents a Type or an Expression.
6403 * if expression, *pe is set
6404 * if type, *pt is set
6407 void TypeIdentifier::resolve(Loc loc
, Scope
*sc
, Expression
**pe
, Type
**pt
, Dsymbol
**ps
, bool intypeid
)
6409 //printf("TypeIdentifier::resolve(sc = %p, idents = '%s')\n", sc, toChars());
6411 if ((ident
->equals(Id::_super
) || ident
->equals(Id::This
)) && !hasThis(sc
))
6413 AggregateDeclaration
*ad
= sc
->getStructClassScope();
6416 ClassDeclaration
*cd
= ad
->isClassDeclaration();
6419 if (ident
->equals(Id::This
))
6421 else if (cd
->baseClass
&& ident
->equals(Id::_super
))
6422 ident
= cd
->baseClass
->ident
;
6426 StructDeclaration
*sd
= ad
->isStructDeclaration();
6427 if (sd
&& ident
->equals(Id::This
))
6432 if (ident
== Id::ctfe
)
6434 error(loc
, "variable __ctfe cannot be read at compile time");
6442 Dsymbol
*s
= sc
->search(loc
, ident
, &scopesym
);
6443 resolveHelper(loc
, sc
, s
, scopesym
, pe
, pt
, ps
, intypeid
);
6445 (*pt
) = (*pt
)->addMod(mod
);
6448 /*****************************************
6449 * See if type resolves to a symbol, if so,
6450 * return that symbol.
6453 Dsymbol
*TypeIdentifier::toDsymbol(Scope
*sc
)
6455 //printf("TypeIdentifier::toDsymbol('%s')\n", toChars());
6463 resolve(loc
, sc
, &e
, &t
, &s
);
6464 if (t
&& t
->ty
!= Tident
)
6465 s
= t
->toDsymbol(sc
);
6472 /***************************** TypeInstance *****************************/
6474 TypeInstance::TypeInstance(Loc loc
, TemplateInstance
*tempinst
)
6475 : TypeQualified(Tinstance
, loc
)
6477 this->tempinst
= tempinst
;
6480 const char *TypeInstance::kind()
6485 Type
*TypeInstance::syntaxCopy()
6487 //printf("TypeInstance::syntaxCopy() %s, %d\n", toChars(), idents.length);
6488 TypeInstance
*t
= new TypeInstance(loc
, (TemplateInstance
*)tempinst
->syntaxCopy(NULL
));
6489 t
->syntaxCopyHelper(this);
6494 void TypeInstance::resolve(Loc loc
, Scope
*sc
, Expression
**pe
, Type
**pt
, Dsymbol
**ps
, bool intypeid
)
6496 // Note close similarity to TypeIdentifier::resolve()
6500 //printf("TypeInstance::resolve(sc = %p, tempinst = '%s')\n", sc, tempinst->toChars());
6501 dsymbolSemantic(tempinst
, sc
);
6502 if (!global
.gag
&& tempinst
->errors
)
6508 resolveHelper(loc
, sc
, tempinst
, NULL
, pe
, pt
, ps
, intypeid
);
6510 *pt
= (*pt
)->addMod(mod
);
6511 //if (*pt) printf("pt = '%s'\n", (*pt)->toChars());
6514 Dsymbol
*TypeInstance::toDsymbol(Scope
*sc
)
6520 //printf("TypeInstance::semantic(%s)\n", toChars());
6521 resolve(loc
, sc
, &e
, &t
, &s
);
6522 if (t
&& t
->ty
!= Tinstance
)
6523 s
= t
->toDsymbol(sc
);
6529 /***************************** TypeTypeof *****************************/
6531 TypeTypeof::TypeTypeof(Loc loc
, Expression
*exp
)
6532 : TypeQualified(Ttypeof
, loc
)
6538 const char *TypeTypeof::kind()
6543 Type
*TypeTypeof::syntaxCopy()
6545 //printf("TypeTypeof::syntaxCopy() %s\n", toChars());
6546 TypeTypeof
*t
= new TypeTypeof(loc
, exp
->syntaxCopy());
6547 t
->syntaxCopyHelper(this);
6552 Dsymbol
*TypeTypeof::toDsymbol(Scope
*sc
)
6554 //printf("TypeTypeof::toDsymbol('%s')\n", toChars());
6558 resolve(loc
, sc
, &e
, &t
, &s
);
6563 void TypeTypeof::resolve(Loc loc
, Scope
*sc
, Expression
**pe
, Type
**pt
, Dsymbol
**ps
, bool intypeid
)
6569 //printf("TypeTypeof::resolve(sc = %p, idents = '%s')\n", sc, toChars());
6570 //static int nest; if (++nest == 50) *(char*)0=0;
6574 error(loc
, "Invalid scope.");
6580 error(loc
, "circular typeof definition");
6590 /* Currently we cannot evalute 'exp' in speculative context, because
6591 * the type implementation may leak to the final execution. Consider:
6594 * string toString() const { return "x"; }
6597 * alias X = typeof(S!int());
6598 * assert(typeid(X).xtoString(null) == "x");
6601 Scope
*sc2
= sc
->push();
6603 Expression
*exp2
= expressionSemantic(exp
, sc2
);
6604 exp2
= resolvePropertiesOnly(sc2
, exp2
);
6607 if (exp2
->op
== TOKerror
)
6615 if (exp
->op
== TOKtype
||
6616 exp
->op
== TOKscope
)
6618 if (exp
->checkType())
6621 /* Today, 'typeof(func)' returns void if func is a
6622 * function template (TemplateExp), or
6623 * template lambda (FuncExp).
6624 * It's actually used in Phobos as an idiom, to branch code for
6625 * template functions.
6628 if (FuncDeclaration
*f
= exp
->op
== TOKvar
? (( VarExp
*)exp
)->var
->isFuncDeclaration()
6629 : exp
->op
== TOKdotvar
? ((DotVarExp
*)exp
)->var
->isFuncDeclaration() : NULL
)
6631 if (f
->checkForwardRef(loc
))
6634 if (FuncDeclaration
*f
= isFuncAddress(exp
))
6636 if (f
->checkForwardRef(loc
))
6643 error(loc
, "expression (%s) has no type", exp
->toChars());
6646 if (t
->ty
== Ttypeof
)
6648 error(loc
, "forward reference to %s", toChars());
6652 if (idents
.length
== 0)
6656 if (Dsymbol
*s
= t
->toDsymbol(sc
))
6657 resolveHelper(loc
, sc
, s
, NULL
, pe
, pt
, ps
, intypeid
);
6660 Expression
*e
= typeToExpressionHelper(this, new TypeExp(loc
, t
));
6661 e
= expressionSemantic(e
, sc
);
6662 resolveExp(e
, pt
, pe
, ps
);
6666 (*pt
) = (*pt
)->addMod(mod
);
6671 d_uns64
TypeTypeof::size(Loc loc
)
6674 return exp
->type
->size(loc
);
6676 return TypeQualified::size(loc
);
6681 /***************************** TypeReturn *****************************/
6683 TypeReturn::TypeReturn(Loc loc
)
6684 : TypeQualified(Treturn
, loc
)
6688 const char *TypeReturn::kind()
6693 Type
*TypeReturn::syntaxCopy()
6695 TypeReturn
*t
= new TypeReturn(loc
);
6696 t
->syntaxCopyHelper(this);
6701 Dsymbol
*TypeReturn::toDsymbol(Scope
*sc
)
6706 resolve(loc
, sc
, &e
, &t
, &s
);
6711 void TypeReturn::resolve(Loc loc
, Scope
*sc
, Expression
**pe
, Type
**pt
, Dsymbol
**ps
, bool intypeid
)
6717 //printf("TypeReturn::resolve(sc = %p, idents = '%s')\n", sc, toChars());
6720 FuncDeclaration
*func
= sc
->func
;
6723 error(loc
, "typeof(return) must be inside function");
6727 func
= func
->fes
->func
;
6729 t
= func
->type
->nextOf();
6732 error(loc
, "cannot use typeof(return) inside function %s with inferred return type", sc
->func
->toChars());
6736 if (idents
.length
== 0)
6740 if (Dsymbol
*s
= t
->toDsymbol(sc
))
6741 resolveHelper(loc
, sc
, s
, NULL
, pe
, pt
, ps
, intypeid
);
6744 Expression
*e
= typeToExpressionHelper(this, new TypeExp(loc
, t
));
6745 e
= expressionSemantic(e
, sc
);
6746 resolveExp(e
, pt
, pe
, ps
);
6750 (*pt
) = (*pt
)->addMod(mod
);
6758 /***************************** TypeEnum *****************************/
6760 TypeEnum::TypeEnum(EnumDeclaration
*sym
)
6766 const char *TypeEnum::kind()
6771 Type
*TypeEnum::syntaxCopy()
6776 d_uns64
TypeEnum::size(Loc loc
)
6778 return sym
->getMemtype(loc
)->size(loc
);
6781 unsigned TypeEnum::alignsize()
6783 Type
*t
= sym
->getMemtype(Loc());
6784 if (t
->ty
== Terror
)
6786 return t
->alignsize();
6789 Dsymbol
*TypeEnum::toDsymbol(Scope
*)
6794 Type
*TypeEnum::toBasetype()
6796 if (!sym
->members
&& !sym
->memtype
)
6798 Type
*tb
= sym
->getMemtype(Loc())->toBasetype();
6799 return tb
->castMod(mod
); // retain modifier bits from 'this'
6802 Expression
*TypeEnum::dotExp(Scope
*sc
, Expression
*e
, Identifier
*ident
, int flag
)
6805 if (ident
== Id::_mangleof
)
6806 return getProperty(e
->loc
, ident
, flag
& 1);
6808 if (sym
->semanticRun
< PASSsemanticdone
)
6809 dsymbolSemantic(sym
, NULL
);
6811 Dsymbol
*s
= sym
->search(e
->loc
, ident
);
6814 if (ident
== Id::max
||
6818 return getProperty(e
->loc
, ident
, flag
& 1);
6820 Expression
*res
= sym
->getMemtype(Loc())->dotExp(sc
, e
, ident
, 1);
6821 if (!(flag
& 1) && !res
)
6823 if (Dsymbol
*ns
= sym
->search_correct(ident
))
6824 e
->error("no property `%s` for type `%s`. Did you mean `%s.%s` ?",
6825 ident
->toChars(), toChars(), toChars(), ns
->toChars());
6827 e
->error("no property `%s` for type `%s`",
6828 ident
->toChars(), toChars());
6830 return new ErrorExp();
6834 EnumMember
*m
= s
->isEnumMember();
6835 return m
->getVarExp(e
->loc
, sc
);
6838 Expression
*TypeEnum::getProperty(Loc loc
, Identifier
*ident
, int flag
)
6841 if (ident
== Id::max
|| ident
== Id::min
)
6843 return sym
->getMaxMinValue(loc
, ident
);
6845 else if (ident
== Id::_init
)
6847 e
= defaultInitLiteral(loc
);
6849 else if (ident
== Id::stringof
)
6851 const char *s
= toChars();
6852 e
= new StringExp(loc
, const_cast<char *>(s
), strlen(s
));
6854 e
= expressionSemantic(e
, &sc
);
6856 else if (ident
== Id::_mangleof
)
6858 e
= Type::getProperty(loc
, ident
, flag
);
6862 e
= toBasetype()->getProperty(loc
, ident
, flag
);
6867 bool TypeEnum::isintegral()
6869 return sym
->getMemtype(Loc())->isintegral();
6872 bool TypeEnum::isfloating()
6874 return sym
->getMemtype(Loc())->isfloating();
6877 bool TypeEnum::isreal()
6879 return sym
->getMemtype(Loc())->isreal();
6882 bool TypeEnum::isimaginary()
6884 return sym
->getMemtype(Loc())->isimaginary();
6887 bool TypeEnum::iscomplex()
6889 return sym
->getMemtype(Loc())->iscomplex();
6892 bool TypeEnum::isunsigned()
6894 return sym
->getMemtype(Loc())->isunsigned();
6897 bool TypeEnum::isscalar()
6899 return sym
->getMemtype(Loc())->isscalar();
6902 bool TypeEnum::isString()
6904 return sym
->getMemtype(Loc())->isString();
6907 bool TypeEnum::isAssignable()
6909 return sym
->getMemtype(Loc())->isAssignable();
6912 bool TypeEnum::isBoolean()
6914 return sym
->getMemtype(Loc())->isBoolean();
6917 bool TypeEnum::needsDestruction()
6919 return sym
->getMemtype(Loc())->needsDestruction();
6922 bool TypeEnum::needsNested()
6924 return sym
->getMemtype(Loc())->needsNested();
6927 MATCH
TypeEnum::implicitConvTo(Type
*to
)
6931 //printf("TypeEnum::implicitConvTo()\n");
6932 if (ty
== to
->ty
&& sym
== ((TypeEnum
*)to
)->sym
)
6933 m
= (mod
== to
->mod
) ? MATCHexact
: MATCHconst
;
6934 else if (sym
->getMemtype(Loc())->implicitConvTo(to
))
6935 m
= MATCHconvert
; // match with conversions
6937 m
= MATCHnomatch
; // no match
6941 MATCH
TypeEnum::constConv(Type
*to
)
6945 if (ty
== to
->ty
&& sym
== ((TypeEnum
*)to
)->sym
&&
6946 MODimplicitConv(mod
, to
->mod
))
6948 return MATCHnomatch
;
6952 Expression
*TypeEnum::defaultInit(Loc loc
)
6954 // Initialize to first member of enum
6955 Expression
*e
= sym
->getDefaultValue(loc
);
6958 e
->type
= this; // to deal with const, immutable, etc., variants
6962 bool TypeEnum::isZeroInit(Loc loc
)
6964 return sym
->getDefaultValue(loc
)->isBool(false);
6967 bool TypeEnum::hasPointers()
6969 return sym
->getMemtype(Loc())->hasPointers();
6972 bool TypeEnum::hasVoidInitPointers()
6974 return sym
->getMemtype(Loc())->hasVoidInitPointers();
6977 Type
*TypeEnum::nextOf()
6979 return sym
->getMemtype(Loc())->nextOf();
6982 /***************************** TypeStruct *****************************/
6984 TypeStruct::TypeStruct(StructDeclaration
*sym
)
6988 this->att
= RECfwdref
;
6989 this->cppmangle
= CPPMANGLEdefault
;
6992 TypeStruct
*TypeStruct::create(StructDeclaration
*sym
)
6994 return new TypeStruct(sym
);
6997 const char *TypeStruct::kind()
7002 Type
*TypeStruct::syntaxCopy()
7007 d_uns64
TypeStruct::size(Loc loc
)
7009 return sym
->size(loc
);
7012 unsigned TypeStruct::alignsize()
7014 sym
->size(Loc()); // give error for forward references
7015 return sym
->alignsize
;
7018 Dsymbol
*TypeStruct::toDsymbol(Scope
*)
7023 Expression
*TypeStruct::dotExp(Scope
*sc
, Expression
*e
, Identifier
*ident
, int flag
)
7027 assert(e
->op
!= TOKdot
);
7030 if (ident
== Id::_mangleof
)
7031 return getProperty(e
->loc
, ident
, flag
& 1);
7035 if (ident
== Id::_tupleof
)
7037 /* Create a TupleExp out of the fields of the struct e:
7038 * (e.field0, e.field1, e.field2, ...)
7040 e
= expressionSemantic(e
, sc
); // do this before turning on noaccesscheck
7042 sym
->size(e
->loc
); // do semantic of type
7044 Expression
*e0
= NULL
;
7045 Expression
*ev
= e
->op
== TOKtype
? NULL
: e
;
7047 ev
= extractSideEffect(sc
, "__tup", &e0
, ev
);
7049 Expressions
*exps
= new Expressions
;
7050 exps
->reserve(sym
->fields
.length
);
7051 for (size_t i
= 0; i
< sym
->fields
.length
; i
++)
7053 VarDeclaration
*v
= sym
->fields
[i
];
7056 ex
= new DotVarExp(e
->loc
, ev
, v
);
7059 ex
= new VarExp(e
->loc
, v
);
7060 ex
->type
= ex
->type
->addMod(e
->type
->mod
);
7065 e
= new TupleExp(e
->loc
, e0
, exps
);
7066 Scope
*sc2
= sc
->push();
7067 sc2
->flags
= sc
->flags
| SCOPEnoaccesscheck
;
7068 e
= expressionSemantic(e
, sc2
);
7073 const int flags
= sc
->flags
& SCOPEignoresymbolvisibility
? IgnoreSymbolVisibility
: 0;
7074 s
= sym
->search(e
->loc
, ident
, flags
| IgnorePrivateImports
);
7078 return noMember(sc
, e
, ident
, flag
);
7080 if (!(sc
->flags
& SCOPEignoresymbolvisibility
) && !symbolIsVisible(sc
, s
))
7082 return noMember(sc
, e
, ident
, flag
);
7084 if (!s
->isFuncDeclaration()) // because of overloading
7086 s
->checkDeprecated(e
->loc
, sc
);
7087 if (Declaration
*d
= s
->isDeclaration())
7088 d
->checkDisabled(e
->loc
, sc
);
7092 EnumMember
*em
= s
->isEnumMember();
7095 return em
->getVarExp(e
->loc
, sc
);
7098 if (VarDeclaration
*v
= s
->isVarDeclaration())
7101 (!v
->type
->deco
&& v
->inuse
))
7103 if (v
->inuse
) // Bugzilla 9494
7104 e
->error("circular reference to %s `%s`", v
->kind(), v
->toPrettyChars());
7106 e
->error("forward reference to %s `%s`", v
->kind(), v
->toPrettyChars());
7107 return new ErrorExp();
7109 if (v
->type
->ty
== Terror
)
7110 return new ErrorExp();
7112 if ((v
->storage_class
& STCmanifest
) && v
->_init
)
7116 e
->error("circular initialization of %s `%s`", v
->kind(), v
->toPrettyChars());
7117 return new ErrorExp();
7119 checkAccess(e
->loc
, sc
, NULL
, v
);
7120 Expression
*ve
= new VarExp(e
->loc
, v
);
7121 ve
= expressionSemantic(ve
, sc
);
7126 if (Type
*t
= s
->getType())
7128 return expressionSemantic(new TypeExp(e
->loc
, t
), sc
);
7131 TemplateMixin
*tm
= s
->isTemplateMixin();
7134 Expression
*de
= new DotExp(e
->loc
, e
, new ScopeExp(e
->loc
, tm
));
7139 TemplateDeclaration
*td
= s
->isTemplateDeclaration();
7142 if (e
->op
== TOKtype
)
7143 e
= new TemplateExp(e
->loc
, td
);
7145 e
= new DotTemplateExp(e
->loc
, e
, td
);
7146 e
= expressionSemantic(e
, sc
);
7150 TemplateInstance
*ti
= s
->isTemplateInstance();
7153 if (!ti
->semanticRun
)
7155 dsymbolSemantic(ti
, sc
);
7156 if (!ti
->inst
|| ti
->errors
) // if template failed to expand
7157 return new ErrorExp();
7159 s
= ti
->inst
->toAlias();
7160 if (!s
->isTemplateInstance())
7162 if (e
->op
== TOKtype
)
7163 e
= new ScopeExp(e
->loc
, ti
);
7165 e
= new DotExp(e
->loc
, e
, new ScopeExp(e
->loc
, ti
));
7166 return expressionSemantic(e
, sc
);
7169 if (s
->isImport() || s
->isModule() || s
->isPackage())
7171 e
= ::resolve(e
->loc
, sc
, s
, false);
7175 OverloadSet
*o
= s
->isOverloadSet();
7178 OverExp
*oe
= new OverExp(e
->loc
, o
);
7179 if (e
->op
== TOKtype
)
7181 return new DotExp(e
->loc
, e
, oe
);
7184 Declaration
*d
= s
->isDeclaration();
7187 e
->error("%s.%s is not a declaration", e
->toChars(), ident
->toChars());
7188 return new ErrorExp();
7191 if (e
->op
== TOKtype
)
7196 if (TupleDeclaration
*tup
= d
->isTupleDeclaration())
7198 e
= new TupleExp(e
->loc
, tup
);
7199 e
= expressionSemantic(e
, sc
);
7202 if (d
->needThis() && sc
->intypeof
!= 1)
7209 e
= new DotVarExp(e
->loc
, new ThisExp(e
->loc
), d
);
7210 e
= expressionSemantic(e
, sc
);
7214 if (d
->semanticRun
== PASSinit
)
7215 dsymbolSemantic(d
, NULL
);
7216 checkAccess(e
->loc
, sc
, e
, d
);
7217 VarExp
*ve
= new VarExp(e
->loc
, d
);
7218 if (d
->isVarDeclaration() && d
->needThis())
7219 ve
->type
= d
->type
->addMod(e
->type
->mod
);
7223 bool unreal
= e
->op
== TOKvar
&& ((VarExp
*)e
)->var
->isField();
7224 if (d
->isDataseg() || (unreal
&& d
->isField()))
7227 checkAccess(e
->loc
, sc
, e
, d
);
7228 Expression
*ve
= new VarExp(e
->loc
, d
);
7229 e
= unreal
? ve
: new CommaExp(e
->loc
, e
, ve
);
7230 e
= expressionSemantic(e
, sc
);
7234 e
= new DotVarExp(e
->loc
, e
, d
);
7235 e
= expressionSemantic(e
, sc
);
7239 structalign_t
TypeStruct::alignment()
7241 if (sym
->alignment
== 0)
7242 sym
->size(sym
->loc
);
7243 return sym
->alignment
;
7246 Expression
*TypeStruct::defaultInit(Loc
)
7248 Declaration
*d
= new SymbolDeclaration(sym
->loc
, sym
);
7251 d
->storage_class
|= STCrvalue
; // Bugzilla 14398
7252 return new VarExp(sym
->loc
, d
);
7255 /***************************************
7256 * Use when we prefer the default initializer to be a literal,
7257 * rather than a global immutable variable.
7259 Expression
*TypeStruct::defaultInitLiteral(Loc loc
)
7262 if (sym
->sizeok
!= SIZEOKdone
)
7263 return new ErrorExp();
7264 Expressions
*structelems
= new Expressions();
7265 structelems
->setDim(sym
->fields
.length
- sym
->isNested());
7266 unsigned offset
= 0;
7267 for (size_t j
= 0; j
< structelems
->length
; j
++)
7269 VarDeclaration
*vd
= sym
->fields
[j
];
7273 error(loc
, "circular reference to `%s`", vd
->toPrettyChars());
7274 return new ErrorExp();
7276 if (vd
->offset
< offset
|| vd
->type
->size() == 0)
7280 if (vd
->_init
->isVoidInitializer())
7283 e
= vd
->getConstInitializer(false);
7286 e
= vd
->type
->defaultInitLiteral(loc
);
7287 if (e
&& e
->op
== TOKerror
)
7290 offset
= vd
->offset
+ (unsigned)vd
->type
->size();
7291 (*structelems
)[j
] = e
;
7293 StructLiteralExp
*structinit
= new StructLiteralExp(loc
, (StructDeclaration
*)sym
, structelems
);
7295 /* Copy from the initializer symbol for larger symbols,
7296 * otherwise the literals expressed as code get excessively large.
7298 if (size(loc
) > target
.ptrsize
* 4U && !needsNested())
7299 structinit
->useStaticInit
= true;
7301 structinit
->type
= this;
7306 bool TypeStruct::isZeroInit(Loc
)
7308 return sym
->zeroInit
!= 0;
7311 bool TypeStruct::isBoolean()
7316 bool TypeStruct::needsDestruction()
7318 return sym
->dtor
!= NULL
;
7321 bool TypeStruct::needsNested()
7323 if (sym
->isNested())
7326 for (size_t i
= 0; i
< sym
->fields
.length
; i
++)
7328 VarDeclaration
*v
= sym
->fields
[i
];
7329 if (!v
->isDataseg() && v
->type
->needsNested())
7335 bool TypeStruct::isAssignable()
7337 bool assignable
= true;
7338 unsigned offset
= ~0; // dead-store initialize to prevent spurious warning
7340 /* If any of the fields are const or immutable,
7341 * then one cannot assign this struct.
7343 for (size_t i
= 0; i
< sym
->fields
.length
; i
++)
7345 VarDeclaration
*v
= sym
->fields
[i
];
7346 //printf("%s [%d] v = (%s) %s, v->offset = %d, v->parent = %s", sym->toChars(), i, v->kind(), v->toChars(), v->offset, v->parent->kind());
7349 else if (v
->offset
== offset
)
7351 /* If any fields of anonymous union are assignable,
7352 * then regard union as assignable.
7353 * This is to support unsafe things like Rebindable templates.
7363 assignable
= v
->type
->isMutable() && v
->type
->isAssignable();
7365 //printf(" -> assignable = %d\n", assignable);
7371 bool TypeStruct::hasPointers()
7373 // Probably should cache this information in sym rather than recompute
7374 StructDeclaration
*s
= sym
;
7376 sym
->size(Loc()); // give error for forward references
7377 for (size_t i
= 0; i
< s
->fields
.length
; i
++)
7379 Declaration
*d
= s
->fields
[i
];
7380 if (d
->storage_class
& STCref
|| d
->hasPointers())
7386 bool TypeStruct::hasVoidInitPointers()
7388 // Probably should cache this information in sym rather than recompute
7389 StructDeclaration
*s
= sym
;
7391 sym
->size(Loc()); // give error for forward references
7392 for (size_t i
= 0; i
< s
->fields
.length
; i
++)
7394 VarDeclaration
*v
= s
->fields
[i
];
7395 if (v
->_init
&& v
->_init
->isVoidInitializer() && v
->type
->hasPointers())
7397 if (!v
->_init
&& v
->type
->hasVoidInitPointers())
7403 MATCH
TypeStruct::implicitConvTo(Type
*to
)
7406 //printf("TypeStruct::implicitConvTo(%s => %s)\n", toChars(), to->toChars());
7408 if (ty
== to
->ty
&& sym
== ((TypeStruct
*)to
)->sym
)
7410 m
= MATCHexact
; // exact match
7414 if (MODimplicitConv(mod
, to
->mod
))
7418 /* Check all the fields. If they can all be converted,
7419 * allow the conversion.
7421 unsigned offset
= ~0; // dead-store to prevent spurious warning
7422 for (size_t i
= 0; i
< sym
->fields
.length
; i
++)
7424 VarDeclaration
*v
= sym
->fields
[i
];
7427 else if (v
->offset
== offset
)
7429 if (m
> MATCHnomatch
)
7434 if (m
<= MATCHnomatch
)
7439 Type
*tvf
= v
->type
->addMod(mod
);
7442 Type
*tv
= v
->type
->addMod(to
->mod
);
7445 MATCH mf
= tvf
->implicitConvTo(tv
);
7446 //printf("\t%s => %s, match = %d\n", v->type->toChars(), tv->toChars(), mf);
7448 if (mf
<= MATCHnomatch
)
7450 if (mf
< m
) // if field match is worse
7457 else if (sym
->aliasthis
&& !(att
& RECtracing
))
7459 att
= (AliasThisRec
)(att
| RECtracing
);
7460 m
= aliasthisOf()->implicitConvTo(to
);
7461 att
= (AliasThisRec
)(att
& ~RECtracing
);
7464 m
= MATCHnomatch
; // no match
7468 MATCH
TypeStruct::constConv(Type
*to
)
7472 if (ty
== to
->ty
&& sym
== ((TypeStruct
*)to
)->sym
&&
7473 MODimplicitConv(mod
, to
->mod
))
7475 return MATCHnomatch
;
7478 unsigned char TypeStruct::deduceWild(Type
*t
, bool isRef
)
7480 if (ty
== t
->ty
&& sym
== ((TypeStruct
*)t
)->sym
)
7481 return Type::deduceWild(t
, isRef
);
7483 unsigned char wm
= 0;
7485 if (t
->hasWild() && sym
->aliasthis
&& !(att
& RECtracing
))
7487 att
= (AliasThisRec
)(att
| RECtracing
);
7488 wm
= aliasthisOf()->deduceWild(t
, isRef
);
7489 att
= (AliasThisRec
)(att
& ~RECtracing
);
7495 Type
*TypeStruct::toHeadMutable()
7501 /***************************** TypeClass *****************************/
7503 TypeClass::TypeClass(ClassDeclaration
*sym
)
7507 this->att
= RECfwdref
;
7508 this->cppmangle
= CPPMANGLEdefault
;
7511 const char *TypeClass::kind()
7516 Type
*TypeClass::syntaxCopy()
7521 d_uns64
TypeClass::size(Loc
)
7523 return target
.ptrsize
;
7526 Dsymbol
*TypeClass::toDsymbol(Scope
*)
7531 Expression
*TypeClass::dotExp(Scope
*sc
, Expression
*e
, Identifier
*ident
, int flag
)
7534 assert(e
->op
!= TOKdot
);
7537 if (ident
== Id::__sizeof
|| ident
== Id::__xalignof
|| ident
== Id::_mangleof
)
7539 return Type::getProperty(e
->loc
, ident
, 0);
7544 if (ident
== Id::_tupleof
)
7546 /* Create a TupleExp
7548 e
= expressionSemantic(e
, sc
); // do this before turning on noaccesscheck
7550 sym
->size(e
->loc
); // do semantic of type
7552 Expression
*e0
= NULL
;
7553 Expression
*ev
= e
->op
== TOKtype
? NULL
: e
;
7555 ev
= extractSideEffect(sc
, "__tup", &e0
, ev
);
7557 Expressions
*exps
= new Expressions
;
7558 exps
->reserve(sym
->fields
.length
);
7559 for (size_t i
= 0; i
< sym
->fields
.length
; i
++)
7561 VarDeclaration
*v
= sym
->fields
[i
];
7562 // Don't include hidden 'this' pointer
7563 if (v
->isThisDeclaration())
7567 ex
= new DotVarExp(e
->loc
, ev
, v
);
7570 ex
= new VarExp(e
->loc
, v
);
7571 ex
->type
= ex
->type
->addMod(e
->type
->mod
);
7576 e
= new TupleExp(e
->loc
, e0
, exps
);
7577 Scope
*sc2
= sc
->push();
7578 sc2
->flags
= sc
->flags
| SCOPEnoaccesscheck
;
7579 e
= expressionSemantic(e
, sc2
);
7584 int flags
= sc
->flags
& SCOPEignoresymbolvisibility
? IgnoreSymbolVisibility
: 0;
7585 s
= sym
->search(e
->loc
, ident
, flags
| IgnorePrivateImports
);
7590 // See if it's 'this' class or a base class
7591 if (sym
->ident
== ident
)
7593 if (e
->op
== TOKtype
)
7594 return Type::getProperty(e
->loc
, ident
, 0);
7595 e
= new DotTypeExp(e
->loc
, e
, sym
);
7596 e
= expressionSemantic(e
, sc
);
7599 if (ClassDeclaration
*cbase
= sym
->searchBase(ident
))
7601 if (e
->op
== TOKtype
)
7602 return Type::getProperty(e
->loc
, ident
, 0);
7603 if (InterfaceDeclaration
*ifbase
= cbase
->isInterfaceDeclaration())
7604 e
= new CastExp(e
->loc
, e
, ifbase
->type
);
7606 e
= new DotTypeExp(e
->loc
, e
, cbase
);
7607 e
= expressionSemantic(e
, sc
);
7611 if (ident
== Id::classinfo
)
7613 if (!Type::typeinfoclass
)
7615 error(e
->loc
, "`object.TypeInfo_Class` could not be found, but is implicitly used");
7616 return new ErrorExp();
7619 Type
*t
= Type::typeinfoclass
->type
;
7620 if (e
->op
== TOKtype
|| e
->op
== TOKdottype
)
7622 /* For type.classinfo, we know the classinfo
7625 if (!sym
->vclassinfo
)
7626 sym
->vclassinfo
= new TypeInfoClassDeclaration(sym
->type
);
7627 e
= new VarExp(e
->loc
, sym
->vclassinfo
);
7629 e
->type
= t
; // do this so we don't get redundant dereference
7633 /* For class objects, the classinfo reference is the first
7634 * entry in the vtbl[]
7636 e
= new PtrExp(e
->loc
, e
);
7637 e
->type
= t
->pointerTo();
7638 if (sym
->isInterfaceDeclaration())
7640 if (sym
->isCPPinterface())
7642 /* C++ interface vtbl[]s are different in that the
7643 * first entry is always pointer to the first virtual
7644 * function, not classinfo.
7645 * We can't get a .classinfo for it.
7647 error(e
->loc
, "no .classinfo for C++ interface objects");
7649 /* For an interface, the first entry in the vtbl[]
7650 * is actually a pointer to an instance of struct Interface.
7651 * The first member of Interface is the .classinfo,
7652 * so add an extra pointer indirection.
7654 e
->type
= e
->type
->pointerTo();
7655 e
= new PtrExp(e
->loc
, e
);
7656 e
->type
= t
->pointerTo();
7658 e
= new PtrExp(e
->loc
, e
, t
);
7663 if (ident
== Id::__vptr
)
7665 /* The pointer to the vtbl[]
7666 * *cast(immutable(void*)**)e
7668 e
= e
->castTo(sc
, tvoidptr
->immutableOf()->pointerTo()->pointerTo());
7669 e
= new PtrExp(e
->loc
, e
);
7670 e
= expressionSemantic(e
, sc
);
7674 if (ident
== Id::__monitor
&& sym
->hasMonitor())
7676 /* The handle to the monitor (call it a void*)
7677 * *(cast(void**)e + 1)
7679 e
= e
->castTo(sc
, tvoidptr
->pointerTo());
7680 e
= new AddExp(e
->loc
, e
, new IntegerExp(1));
7681 e
= new PtrExp(e
->loc
, e
);
7682 e
= expressionSemantic(e
, sc
);
7686 if (ident
== Id::outer
&& sym
->vthis
)
7688 if (sym
->vthis
->semanticRun
== PASSinit
)
7689 dsymbolSemantic(sym
->vthis
, NULL
);
7691 if (ClassDeclaration
*cdp
= sym
->toParent2()->isClassDeclaration())
7693 DotVarExp
*dve
= new DotVarExp(e
->loc
, e
, sym
->vthis
);
7694 dve
->type
= cdp
->type
->addMod(e
->type
->mod
);
7698 /* Bugzilla 15839: Find closest parent class through nested functions.
7700 for (Dsymbol
*p
= sym
->toParent2(); p
; p
= p
->toParent2())
7702 FuncDeclaration
*fd
= p
->isFuncDeclaration();
7707 AggregateDeclaration
*ad
= fd
->isThis();
7710 if (ad
->isClassDeclaration())
7712 ThisExp
*ve
= new ThisExp(e
->loc
);
7714 ve
->var
= fd
->vthis
;
7715 const bool nestedError
= fd
->vthis
->checkNestedReference(sc
, e
->loc
);
7716 assert(!nestedError
);
7718 ve
->type
= fd
->vthis
->type
->addMod(e
->type
->mod
);
7724 // Continue to show enclosing function's frame (stack or closure).
7725 DotVarExp
*dve
= new DotVarExp(e
->loc
, e
, sym
->vthis
);
7726 dve
->type
= sym
->vthis
->type
->addMod(e
->type
->mod
);
7730 return noMember(sc
, e
, ident
, flag
& 1);
7732 if (!(sc
->flags
& SCOPEignoresymbolvisibility
) && !symbolIsVisible(sc
, s
))
7734 return noMember(sc
, e
, ident
, flag
);
7736 if (!s
->isFuncDeclaration()) // because of overloading
7738 s
->checkDeprecated(e
->loc
, sc
);
7739 if (Declaration
*d
= s
->isDeclaration())
7740 d
->checkDisabled(e
->loc
, sc
);
7744 EnumMember
*em
= s
->isEnumMember();
7747 return em
->getVarExp(e
->loc
, sc
);
7750 if (VarDeclaration
*v
= s
->isVarDeclaration())
7753 (!v
->type
->deco
&& v
->inuse
))
7755 if (v
->inuse
) // Bugzilla 9494
7756 e
->error("circular reference to %s `%s`", v
->kind(), v
->toPrettyChars());
7758 e
->error("forward reference to %s `%s`", v
->kind(), v
->toPrettyChars());
7759 return new ErrorExp();
7761 if (v
->type
->ty
== Terror
)
7762 return new ErrorExp();
7764 if ((v
->storage_class
& STCmanifest
) && v
->_init
)
7768 e
->error("circular initialization of %s `%s`", v
->kind(), v
->toPrettyChars());
7769 return new ErrorExp();
7771 checkAccess(e
->loc
, sc
, NULL
, v
);
7772 Expression
*ve
= new VarExp(e
->loc
, v
);
7773 ve
= expressionSemantic(ve
, sc
);
7778 if (Type
*t
= s
->getType())
7780 return expressionSemantic(new TypeExp(e
->loc
, t
), sc
);
7783 TemplateMixin
*tm
= s
->isTemplateMixin();
7786 Expression
*de
= new DotExp(e
->loc
, e
, new ScopeExp(e
->loc
, tm
));
7791 TemplateDeclaration
*td
= s
->isTemplateDeclaration();
7794 if (e
->op
== TOKtype
)
7795 e
= new TemplateExp(e
->loc
, td
);
7797 e
= new DotTemplateExp(e
->loc
, e
, td
);
7798 e
= expressionSemantic(e
, sc
);
7802 TemplateInstance
*ti
= s
->isTemplateInstance();
7805 if (!ti
->semanticRun
)
7807 dsymbolSemantic(ti
, sc
);
7808 if (!ti
->inst
|| ti
->errors
) // if template failed to expand
7809 return new ErrorExp();
7811 s
= ti
->inst
->toAlias();
7812 if (!s
->isTemplateInstance())
7814 if (e
->op
== TOKtype
)
7815 e
= new ScopeExp(e
->loc
, ti
);
7817 e
= new DotExp(e
->loc
, e
, new ScopeExp(e
->loc
, ti
));
7818 return expressionSemantic(e
, sc
);
7821 if (s
->isImport() || s
->isModule() || s
->isPackage())
7823 e
= ::resolve(e
->loc
, sc
, s
, false);
7827 OverloadSet
*o
= s
->isOverloadSet();
7830 OverExp
*oe
= new OverExp(e
->loc
, o
);
7831 if (e
->op
== TOKtype
)
7833 return new DotExp(e
->loc
, e
, oe
);
7836 Declaration
*d
= s
->isDeclaration();
7839 e
->error("%s.%s is not a declaration", e
->toChars(), ident
->toChars());
7840 return new ErrorExp();
7843 if (e
->op
== TOKtype
)
7848 if (TupleDeclaration
*tup
= d
->isTupleDeclaration())
7850 e
= new TupleExp(e
->loc
, tup
);
7851 e
= expressionSemantic(e
, sc
);
7854 if (d
->needThis() && sc
->intypeof
!= 1)
7861 // This is almost same as getRightThis() in expression.c
7862 Expression
*e1
= new ThisExp(e
->loc
);
7863 e1
= expressionSemantic(e1
, sc
);
7865 Type
*t
= e1
->type
->toBasetype();
7866 ClassDeclaration
*cd
= e
->type
->isClassHandle();
7867 ClassDeclaration
*tcd
= t
->isClassHandle();
7868 if (cd
&& tcd
&& (tcd
== cd
|| cd
->isBaseOf(tcd
, NULL
)))
7870 e
= new DotTypeExp(e1
->loc
, e1
, cd
);
7871 e
= new DotVarExp(e
->loc
, e
, d
);
7872 e
= expressionSemantic(e
, sc
);
7875 if (tcd
&& tcd
->isNested())
7876 { /* e1 is the 'this' pointer for an inner class: tcd.
7877 * Rewrite it as the 'this' pointer for the outer class.
7880 e1
= new DotVarExp(e
->loc
, e1
, tcd
->vthis
);
7881 e1
->type
= tcd
->vthis
->type
;
7882 e1
->type
= e1
->type
->addMod(t
->mod
);
7883 // Do not call checkNestedRef()
7884 //e1 = expressionSemantic(e1, sc);
7886 // Skip up over nested functions, and get the enclosing
7889 for (s
= tcd
->toParent();
7890 s
&& s
->isFuncDeclaration();
7892 { FuncDeclaration
*f
= s
->isFuncDeclaration();
7895 //printf("rewriting e1 to %s's this\n", f->toChars());
7897 e1
= new VarExp(e
->loc
, f
->vthis
);
7901 e
= new VarExp(e
->loc
, d
);
7905 if (s
&& s
->isClassDeclaration())
7906 { e1
->type
= s
->isClassDeclaration()->type
;
7907 e1
->type
= e1
->type
->addMod(t
->mod
);
7909 e1
= expressionSemantic(e1
, sc
);
7912 e1
= expressionSemantic(e1
, sc
);
7917 //printf("e = %s, d = %s\n", e->toChars(), d->toChars());
7918 if (d
->semanticRun
== PASSinit
)
7919 dsymbolSemantic(d
, NULL
);
7920 checkAccess(e
->loc
, sc
, e
, d
);
7921 VarExp
*ve
= new VarExp(e
->loc
, d
);
7922 if (d
->isVarDeclaration() && d
->needThis())
7923 ve
->type
= d
->type
->addMod(e
->type
->mod
);
7927 bool unreal
= e
->op
== TOKvar
&& ((VarExp
*)e
)->var
->isField();
7928 if (d
->isDataseg() || (unreal
&& d
->isField()))
7931 checkAccess(e
->loc
, sc
, e
, d
);
7932 Expression
*ve
= new VarExp(e
->loc
, d
);
7933 e
= unreal
? ve
: new CommaExp(e
->loc
, e
, ve
);
7934 e
= expressionSemantic(e
, sc
);
7938 e
= new DotVarExp(e
->loc
, e
, d
);
7939 e
= expressionSemantic(e
, sc
);
7943 ClassDeclaration
*TypeClass::isClassHandle()
7948 bool TypeClass::isscope()
7950 return sym
->isscope
;
7953 bool TypeClass::isBaseOf(Type
*t
, int *poffset
)
7955 if (t
&& t
->ty
== Tclass
)
7957 ClassDeclaration
*cd
= ((TypeClass
*)t
)->sym
;
7958 if (sym
->isBaseOf(cd
, poffset
))
7964 MATCH
TypeClass::implicitConvTo(Type
*to
)
7966 //printf("TypeClass::implicitConvTo(to = '%s') %s\n", to->toChars(), toChars());
7967 MATCH m
= constConv(to
);
7968 if (m
> MATCHnomatch
)
7971 ClassDeclaration
*cdto
= to
->isClassHandle();
7974 //printf("TypeClass::implicitConvTo(to = '%s') %s, isbase = %d %d\n", to->toChars(), toChars(), cdto->isBaseInfoComplete(), sym->isBaseInfoComplete());
7975 if (cdto
->semanticRun
< PASSsemanticdone
&& !cdto
->isBaseInfoComplete())
7976 dsymbolSemantic(cdto
, NULL
);
7977 if (sym
->semanticRun
< PASSsemanticdone
&& !sym
->isBaseInfoComplete())
7978 dsymbolSemantic(sym
, NULL
);
7979 if (cdto
->isBaseOf(sym
, NULL
) && MODimplicitConv(mod
, to
->mod
))
7981 //printf("'to' is base\n");
7982 return MATCHconvert
;
7987 if (sym
->aliasthis
&& !(att
& RECtracing
))
7989 att
= (AliasThisRec
)(att
| RECtracing
);
7990 m
= aliasthisOf()->implicitConvTo(to
);
7991 att
= (AliasThisRec
)(att
& ~RECtracing
);
7997 MATCH
TypeClass::constConv(Type
*to
)
8001 if (ty
== to
->ty
&& sym
== ((TypeClass
*)to
)->sym
&&
8002 MODimplicitConv(mod
, to
->mod
))
8005 /* Conversion derived to const(base)
8008 if (to
->isBaseOf(this, &offset
) && offset
== 0 &&
8009 MODimplicitConv(mod
, to
->mod
))
8013 // inout(derived) to inout(base)
8014 if (!to
->isMutable() && !to
->isWild())
8015 return MATCHconvert
;
8018 return MATCHnomatch
;
8021 unsigned char TypeClass::deduceWild(Type
*t
, bool isRef
)
8023 ClassDeclaration
*cd
= t
->isClassHandle();
8024 if (cd
&& (sym
== cd
|| cd
->isBaseOf(sym
, NULL
)))
8025 return Type::deduceWild(t
, isRef
);
8027 unsigned char wm
= 0;
8029 if (t
->hasWild() && sym
->aliasthis
&& !(att
& RECtracing
))
8031 att
= (AliasThisRec
)(att
| RECtracing
);
8032 wm
= aliasthisOf()->deduceWild(t
, isRef
);
8033 att
= (AliasThisRec
)(att
& ~RECtracing
);
8039 Type
*TypeClass::toHeadMutable()
8044 Expression
*TypeClass::defaultInit(Loc loc
)
8046 return new NullExp(loc
, this);
8049 bool TypeClass::isZeroInit(Loc
)
8054 bool TypeClass::isBoolean()
8059 bool TypeClass::hasPointers()
8064 /***************************** TypeTuple *****************************/
8066 TypeTuple::TypeTuple(Parameters
*arguments
)
8069 //printf("TypeTuple(this = %p)\n", this);
8070 this->arguments
= arguments
;
8071 //printf("TypeTuple() %p, %s\n", this, toChars());
8075 * Form TypeTuple from the types of the expressions.
8076 * Assume exps[] is already tuple expanded.
8079 TypeTuple::TypeTuple(Expressions
*exps
)
8082 Parameters
*arguments
= new Parameters
;
8085 arguments
->setDim(exps
->length
);
8086 for (size_t i
= 0; i
< exps
->length
; i
++)
8087 { Expression
*e
= (*exps
)[i
];
8088 if (e
->type
->ty
== Ttuple
)
8089 e
->error("cannot form tuple of tuples");
8090 Parameter
*arg
= new Parameter(STCundefined
, e
->type
, NULL
, NULL
, NULL
);
8091 (*arguments
)[i
] = arg
;
8094 this->arguments
= arguments
;
8095 //printf("TypeTuple() %p, %s\n", this, toChars());
8098 TypeTuple
*TypeTuple::create(Parameters
*arguments
)
8100 return new TypeTuple(arguments
);
8103 /*******************************************
8104 * Type tuple with 0, 1 or 2 types in it.
8106 TypeTuple::TypeTuple()
8109 arguments
= new Parameters();
8112 TypeTuple::TypeTuple(Type
*t1
)
8115 arguments
= new Parameters();
8116 arguments
->push(new Parameter(0, t1
, NULL
, NULL
, NULL
));
8119 TypeTuple::TypeTuple(Type
*t1
, Type
*t2
)
8122 arguments
= new Parameters();
8123 arguments
->push(new Parameter(0, t1
, NULL
, NULL
, NULL
));
8124 arguments
->push(new Parameter(0, t2
, NULL
, NULL
, NULL
));
8127 const char *TypeTuple::kind()
8132 Type
*TypeTuple::syntaxCopy()
8134 Parameters
*args
= Parameter::arraySyntaxCopy(arguments
);
8135 Type
*t
= new TypeTuple(args
);
8140 bool TypeTuple::equals(RootObject
*o
)
8142 Type
*t
= (Type
*)o
;
8143 //printf("TypeTuple::equals(%s, %s)\n", toChars(), t->toChars());
8146 if (t
->ty
== Ttuple
)
8148 TypeTuple
*tt
= (TypeTuple
*)t
;
8149 if (arguments
->length
== tt
->arguments
->length
)
8151 for (size_t i
= 0; i
< tt
->arguments
->length
; i
++)
8153 Parameter
*arg1
= (*arguments
)[i
];
8154 Parameter
*arg2
= (*tt
->arguments
)[i
];
8155 if (!arg1
->type
->equals(arg2
->type
))
8164 Expression
*TypeTuple::getProperty(Loc loc
, Identifier
*ident
, int flag
)
8168 if (ident
== Id::length
)
8170 e
= new IntegerExp(loc
, arguments
->length
, Type::tsize_t
);
8172 else if (ident
== Id::_init
)
8174 e
= defaultInitLiteral(loc
);
8182 error(loc
, "no property `%s` for tuple `%s`", ident
->toChars(), toChars());
8188 Expression
*TypeTuple::defaultInit(Loc loc
)
8190 Expressions
*exps
= new Expressions();
8191 exps
->setDim(arguments
->length
);
8192 for (size_t i
= 0; i
< arguments
->length
; i
++)
8194 Parameter
*p
= (*arguments
)[i
];
8196 Expression
*e
= p
->type
->defaultInitLiteral(loc
);
8197 if (e
->op
== TOKerror
)
8201 return new TupleExp(loc
, exps
);
8204 /***************************** TypeSlice *****************************/
8206 /* This is so we can slice a TypeTuple */
8208 TypeSlice::TypeSlice(Type
*next
, Expression
*lwr
, Expression
*upr
)
8209 : TypeNext(Tslice
, next
)
8211 //printf("TypeSlice[%s .. %s]\n", lwr->toChars(), upr->toChars());
8216 const char *TypeSlice::kind()
8221 Type
*TypeSlice::syntaxCopy()
8223 Type
*t
= new TypeSlice(next
->syntaxCopy(), lwr
->syntaxCopy(), upr
->syntaxCopy());
8228 void TypeSlice::resolve(Loc loc
, Scope
*sc
, Expression
**pe
, Type
**pt
, Dsymbol
**ps
, bool intypeid
)
8230 next
->resolve(loc
, sc
, pe
, pt
, ps
, intypeid
);
8233 // It's really a slice expression
8234 if (Dsymbol
*s
= getDsymbol(*pe
))
8235 *pe
= new DsymbolExp(loc
, s
);
8236 *pe
= new ArrayExp(loc
, *pe
, new IntervalExp(loc
, lwr
, upr
));
8241 TupleDeclaration
*td
= s
->isTupleDeclaration();
8244 /* It's a slice of a TupleDeclaration
8246 ScopeDsymbol
*sym
= new ArrayScopeSymbol(sc
, td
);
8247 sym
->parent
= sc
->scopesym
;
8249 sc
= sc
->startCTFE();
8250 lwr
= expressionSemantic(lwr
, sc
);
8251 upr
= expressionSemantic(upr
, sc
);
8255 lwr
= lwr
->ctfeInterpret();
8256 upr
= upr
->ctfeInterpret();
8257 uinteger_t i1
= lwr
->toUInteger();
8258 uinteger_t i2
= upr
->toUInteger();
8260 if (!(i1
<= i2
&& i2
<= td
->objects
->length
))
8262 error(loc
, "slice [%llu..%llu] is out of range of [0..%u]", i1
, i2
, td
->objects
->length
);
8268 if (i1
== 0 && i2
== td
->objects
->length
)
8274 /* Create a new TupleDeclaration which
8275 * is a slice [i1..i2] out of the old one.
8277 Objects
*objects
= new Objects
;
8278 objects
->setDim((size_t)(i2
- i1
));
8279 for (size_t i
= 0; i
< objects
->length
; i
++)
8281 (*objects
)[i
] = (*td
->objects
)[(size_t)i1
+ i
];
8284 TupleDeclaration
*tds
= new TupleDeclaration(loc
, td
->ident
, objects
);
8292 if ((*pt
)->ty
!= Terror
)
8293 next
= *pt
; // prevent re-running semantic() on 'next'
8295 Type::resolve(loc
, sc
, pe
, pt
, ps
, intypeid
);
8299 /***************************** TypeNull *****************************/
8301 TypeNull::TypeNull()
8306 const char *TypeNull::kind()
8311 Type
*TypeNull::syntaxCopy()
8313 // No semantic analysis done, no need to copy
8317 MATCH
TypeNull::implicitConvTo(Type
*to
)
8319 //printf("TypeNull::implicitConvTo(this=%p, to=%p)\n", this, to);
8320 //printf("from: %s\n", toChars());
8321 //printf("to : %s\n", to->toChars());
8322 MATCH m
= Type::implicitConvTo(to
);
8323 if (m
!= MATCHnomatch
)
8326 // NULL implicitly converts to any pointer type or dynamic array
8327 //if (type->ty == Tpointer && type->nextOf()->ty == Tvoid)
8329 Type
*tb
= to
->toBasetype();
8330 if (tb
->ty
== Tnull
||
8331 tb
->ty
== Tpointer
|| tb
->ty
== Tarray
||
8332 tb
->ty
== Taarray
|| tb
->ty
== Tclass
||
8333 tb
->ty
== Tdelegate
)
8337 return MATCHnomatch
;
8340 bool TypeNull::isBoolean()
8345 d_uns64
TypeNull::size(Loc loc
)
8347 return tvoidptr
->size(loc
);
8350 Expression
*TypeNull::defaultInit(Loc
)
8352 return new NullExp(Loc(), Type::tnull
);
8355 /***************************** TypeNoreturn *****************************/
8357 TypeNoreturn::TypeNoreturn()
8360 //printf("TypeNoreturn %p\n", this);
8363 const char *TypeNoreturn::kind()
8368 Type
*TypeNoreturn::syntaxCopy()
8370 // No semantic analysis done, no need to copy
8374 MATCH
TypeNoreturn::implicitConvTo(Type
*to
)
8376 //printf("TypeNoreturn::implicitConvTo(this=%p, to=%p)\n", this, to);
8377 //printf("from: %s\n", toChars());
8378 //printf("to : %s\n", to.toChars());
8379 MATCH m
= Type::implicitConvTo(to
);
8380 return (m
== MATCHexact
) ? MATCHexact
: MATCHconvert
;
8383 bool TypeNoreturn::isBoolean()
8385 return true; // bottom type can be implicitly converted to any other type
8388 d_uns64
TypeNoreturn::size(Loc
)
8393 unsigned TypeNoreturn::alignsize()
8398 /***********************************************************
8399 * Encapsulate Parameters* so .length and [i] can be used on it.
8400 * https://dlang.org/spec/function.html#ParameterList
8403 ParameterList::ParameterList(Parameters
*parameters
, VarArg varargs
)
8405 this->parameters
= parameters
;
8406 this->varargs
= varargs
;
8409 size_t ParameterList::length()
8411 return Parameter::dim(parameters
);
8414 /***************************** Parameter *****************************/
8416 Parameter::Parameter(StorageClass storageClass
, Type
*type
, Identifier
*ident
,
8417 Expression
*defaultArg
, UserAttributeDeclaration
*userAttribDecl
)
8420 this->ident
= ident
;
8421 this->storageClass
= storageClass
;
8422 this->defaultArg
= defaultArg
;
8423 this->userAttribDecl
= userAttribDecl
;
8426 Parameter
*Parameter::create(StorageClass storageClass
, Type
*type
, Identifier
*ident
,
8427 Expression
*defaultArg
, UserAttributeDeclaration
*userAttribDecl
)
8429 return new Parameter(storageClass
, type
, ident
, defaultArg
, userAttribDecl
);
8432 Parameter
*Parameter::syntaxCopy()
8434 return new Parameter(storageClass
,
8435 type
? type
->syntaxCopy() : NULL
,
8437 defaultArg
? defaultArg
->syntaxCopy() : NULL
,
8438 userAttribDecl
? (UserAttributeDeclaration
*) userAttribDecl
->syntaxCopy(NULL
) : NULL
);
8441 Parameters
*Parameter::arraySyntaxCopy(Parameters
*parameters
)
8443 Parameters
*params
= NULL
;
8446 params
= new Parameters();
8447 params
->setDim(parameters
->length
);
8448 for (size_t i
= 0; i
< params
->length
; i
++)
8449 (*params
)[i
] = (*parameters
)[i
]->syntaxCopy();
8454 /****************************************************
8455 * Determine if parameter is a lazy array of delegates.
8456 * If so, return the return type of those delegates.
8457 * If not, return NULL.
8459 * Returns T if the type is one of the following forms:
8464 Type
*Parameter::isLazyArray()
8466 Type
*tb
= type
->toBasetype();
8467 if (tb
->ty
== Tsarray
|| tb
->ty
== Tarray
)
8469 Type
*tel
= ((TypeArray
*)tb
)->next
->toBasetype();
8470 if (tel
->ty
== Tdelegate
)
8472 TypeDelegate
*td
= (TypeDelegate
*)tel
;
8473 TypeFunction
*tf
= td
->next
->toTypeFunction();
8475 if (tf
->parameterList
.varargs
== VARARGnone
&& tf
->parameterList
.length() == 0)
8477 return tf
->next
; // return type of delegate
8484 /***************************************
8485 * Determine number of arguments, folding in tuples.
8488 static int dimDg(void *ctx
, size_t, Parameter
*)
8494 size_t Parameter::dim(Parameters
*parameters
)
8497 Parameter_foreach(parameters
, &dimDg
, &n
);
8501 /***************************************
8502 * Get nth Parameter, folding in tuples.
8504 * Parameter* nth Parameter
8505 * NULL not found, *pn gets incremented by the number
8509 struct GetNthParamCtx
8515 static int getNthParamDg(void *ctx
, size_t n
, Parameter
*p
)
8517 GetNthParamCtx
*c
= (GetNthParamCtx
*)ctx
;
8526 Parameter
*Parameter::getNth(Parameters
*parameters
, size_t nth
, size_t *)
8528 GetNthParamCtx ctx
= { nth
, NULL
};
8529 int res
= Parameter_foreach(parameters
, &getNthParamDg
, &ctx
);
8530 return res
? ctx
.param
: NULL
;
8533 /***************************************
8534 * Expands tuples in args in depth first order. Calls
8535 * dg(void *ctx, size_t argidx, Parameter *arg) for each Parameter.
8536 * If dg returns !=0, stops and returns that value else returns 0.
8537 * Use this function to avoid the O(N + N^2/2) complexity of
8538 * calculating dim and calling N times getNth.
8541 int Parameter_foreach(Parameters
*parameters
, ForeachDg dg
, void *ctx
, size_t *pn
)
8547 size_t n
= pn
? *pn
: 0; // take over index
8549 for (size_t i
= 0; i
< parameters
->length
; i
++)
8551 Parameter
*p
= (*parameters
)[i
];
8552 Type
*t
= p
->type
->toBasetype();
8554 if (t
->ty
== Ttuple
)
8556 TypeTuple
*tu
= (TypeTuple
*)t
;
8557 result
= Parameter_foreach(tu
->arguments
, dg
, ctx
, &n
);
8560 result
= dg(ctx
, n
++, p
);
8567 *pn
= n
; // update index
8572 const char *Parameter::toChars()
8574 return ident
? ident
->toChars() : "__anonymous_param";
8577 /*********************************
8578 * Compute covariance of parameters `this` and `p`
8579 * as determined by the storage classes of both.
8581 * p = Parameter to compare with
8583 * true = `this` can be used in place of `p`
8586 bool Parameter::isCovariant(bool returnByRef
, const Parameter
*p
) const
8588 const StorageClass stc
= STCref
| STCin
| STCout
| STClazy
;
8589 if ((this->storageClass
& stc
) != (p
->storageClass
& stc
))
8592 return isCovariantScope(returnByRef
, this->storageClass
, p
->storageClass
);
8595 bool Parameter::isCovariantScope(bool returnByRef
, StorageClass from
, StorageClass to
)
8602 /* Classification of 'scope-return-ref' possibilities
8617 /* Shrinking the representation is necessary because StorageClass is so wide
8619 * returnByRef = true if the function returns by ref
8620 * stc = storage class of parameter
8622 static unsigned buildSR(bool returnByRef
, StorageClass stc
)
8625 StorageClass stc2
= stc
& (STCref
| STCscope
| STCreturn
);
8628 else if (stc2
== STCref
)
8630 else if (stc2
== STCscope
)
8632 else if (stc2
== (STCscope
| STCreturn
))
8633 result
= SRReturnScope
;
8634 else if (stc2
== (STCref
| STCreturn
))
8635 result
= SRReturnRef
;
8636 else if (stc2
== (STCscope
| STCref
))
8637 result
= SRRefScope
;
8638 else if (stc2
== (STCscope
| STCref
| STCreturn
))
8639 result
= returnByRef
? SRReturnRef_Scope
: SRRef_ReturnScope
;
8645 static void covariantInit(bool covariant
[SRMAX
][SRMAX
])
8647 /* Initialize covariant[][] with this:
8654 From\To r rr rs rr-s r-rs
8659 Ref-ReturnScope X X X
8661 for (int i
= 0; i
< SRMAX
; i
++)
8663 covariant
[i
][i
] = true;
8664 covariant
[SRRefScope
][i
] = true;
8666 covariant
[SRReturnScope
][SRNone
] = true;
8667 covariant
[SRScope
][SRNone
] = true;
8668 covariant
[SRScope
][SRReturnScope
] = true;
8670 covariant
[SRRef
][SRReturnRef
] = true;
8671 covariant
[SRReturnRef_Scope
][SRReturnRef
] = true;
8672 covariant
[SRRef_ReturnScope
][SRRef
] = true;
8673 covariant
[SRRef_ReturnScope
][SRReturnRef
] = true;
8677 /* result is true if the 'from' can be used as a 'to'
8680 if ((from
^ to
) & STCref
) // differing in 'ref' means no covariance
8683 static bool covariant
[SR::SRMAX
][SR::SRMAX
];
8684 static bool init
= false;
8687 SR::covariantInit(covariant
);
8691 return covariant
[SR::buildSR(returnByRef
, from
)][SR::buildSR(returnByRef
, to
)];
8695 * For printing two types with qualification when necessary.
8697 * t1 = The first type to receive the type name for
8698 * t2 = The second type to receive the type name for
8700 * The fully-qualified names of both types if the two type names are not the same,
8701 * or the unqualified names of both types if the two type names are the same.
8703 void toAutoQualChars(const char **result
, Type
*t1
, Type
*t2
)
8705 const char *s1
= t1
->toChars();
8706 const char *s2
= t2
->toChars();
8707 if (strcmp(s1
, s2
) == 0)
8709 s1
= t1
->toPrettyChars(true);
8710 s2
= t2
->toPrettyChars(true);