1 /**
2  * Semantic analysis for D types.
3  *
4  * Copyright:   Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
5  * Authors:     $(LINK2 http://www.digitalmars.com, Walter Bright)
6  * License:     $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
7  * Source:      $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/typesem.d, _typesem.d)
8  * Documentation:  https://dlang.org/phobos/dmd_typesem.html
9  * Coverage:    https://codecov.io/gh/dlang/dmd/src/master/src/dmd/typesem.d
10  */
11 
12 module dmd.typesem;
13 
14 import core.checkedint;
15 import core.stdc.string;
16 import core.stdc.stdio;
17 
18 import dmd.access;
19 import dmd.aggregate;
20 import dmd.aliasthis;
21 import dmd.arrayop;
22 import dmd.arraytypes;
23 import dmd.astcodegen;
24 import dmd.complex;
25 import dmd.dcast;
26 import dmd.dclass;
27 import dmd.declaration;
28 import dmd.denum;
29 import dmd.dimport;
30 import dmd.dmangle;
31 import dmd.dmodule : Module;
32 import dmd.dscope;
33 import dmd.dstruct;
34 import dmd.dsymbol;
35 import dmd.dsymbolsem;
36 import dmd.dtemplate;
37 import dmd.errors;
38 import dmd.expression;
39 import dmd.expressionsem;
40 import dmd.func;
41 import dmd.globals;
42 import dmd.hdrgen;
43 import dmd.id;
44 import dmd.identifier;
45 import dmd.imphint;
46 import dmd.init;
47 import dmd.initsem;
48 import dmd.visitor;
49 import dmd.mtype;
50 import dmd.objc;
51 import dmd.opover;
52 import dmd.parse;
53 import dmd.root.ctfloat;
54 import dmd.root.rmem;
55 import dmd.root.outbuffer;
56 import dmd.root.rootobject;
57 import dmd.root.string;
58 import dmd.root.stringtable;
59 import dmd.semantic3;
60 import dmd.sideeffect;
61 import dmd.target;
62 import dmd.tokens;
63 import dmd.typesem;
64 
65 /**************************
66  * This evaluates exp while setting length to be the number
67  * of elements in the tuple t.
68  */
69 private Expression semanticLength(Scope* sc, Type t, Expression exp)
70 {
71     if (auto tt = t.isTypeTuple())
72     {
73         ScopeDsymbol sym = new ArrayScopeSymbol(sc, tt);
74         sym.parent = sc.scopesym;
75         sc = sc.push(sym);
76         sc = sc.startCTFE();
77         exp = exp.expressionSemantic(sc);
78         sc = sc.endCTFE();
79         sc.pop();
80     }
81     else
82     {
83         sc = sc.startCTFE();
84         exp = exp.expressionSemantic(sc);
85         sc = sc.endCTFE();
86     }
87     return exp;
88 }
89 
90 private Expression semanticLength(Scope* sc, TupleDeclaration tup, Expression exp)
91 {
92     ScopeDsymbol sym = new ArrayScopeSymbol(sc, tup);
93     sym.parent = sc.scopesym;
94 
95     sc = sc.push(sym);
96     sc = sc.startCTFE();
97     exp = exp.expressionSemantic(sc);
98     sc = sc.endCTFE();
99     sc.pop();
100 
101     return exp;
102 }
103 
104 /*************************************
105  * Resolve a tuple index.
106  */
107 private void resolveTupleIndex(const ref Loc loc, Scope* sc, Dsymbol s, Expression* pe, Type* pt, Dsymbol* ps, RootObject oindex)
108 {
109     *pt = null;
110     *ps = null;
111     *pe = null;
112 
113     auto tup = s.isTupleDeclaration();
114 
115     auto eindex = isExpression(oindex);
116     auto tindex = isType(oindex);
117     auto sindex = isDsymbol(oindex);
118 
119     if (!tup)
120     {
121         // It's really an index expression
122         if (tindex)
123             eindex = new TypeExp(loc, tindex);
124         else if (sindex)
125             eindex = symbolToExp(sindex, loc, sc, false);
126         Expression e = new IndexExp(loc, symbolToExp(s, loc, sc, false), eindex);
127         e = e.expressionSemantic(sc);
128         resolveExp(e, pt, pe, ps);
129         return;
130     }
131 
132     // Convert oindex to Expression, then try to resolve to constant.
133     if (tindex)
134         tindex.resolve(loc, sc, &eindex, &tindex, &sindex);
135     if (sindex)
136         eindex = symbolToExp(sindex, loc, sc, false);
137     if (!eindex)
138     {
139         .error(loc, "index `%s` is not an expression", oindex.toChars());
140         *pt = Type.terror;
141         return;
142     }
143 
144     eindex = semanticLength(sc, tup, eindex);
145     eindex = eindex.ctfeInterpret();
146     if (eindex.op == TOK.error)
147     {
148         *pt = Type.terror;
149         return;
150     }
151     const(uinteger_t) d = eindex.toUInteger();
152     if (d >= tup.objects.dim)
153     {
154         .error(loc, "tuple index `%llu` exceeds length %u", d, tup.objects.dim);
155         *pt = Type.terror;
156         return;
157     }
158 
159     RootObject o = (*tup.objects)[cast(size_t)d];
160     *pt = isType(o);
161     *ps = isDsymbol(o);
162     *pe = isExpression(o);
163     if (*pt)
164         *pt = (*pt).typeSemantic(loc, sc);
165     if (*pe)
166         resolveExp(*pe, pt, pe, ps);
167 }
168 
169 /*************************************
170  * Takes an array of Identifiers and figures out if
171  * it represents a Type, Expression, or Dsymbol.
172  * Params:
173  *      mt = array of identifiers
174  *      loc = location for error messages
175  *      sc = context
176  *      s = symbol to start search at
177  *      scopesym = unused
178  *      pe = set if expression
179  *      pt = set if type
180  *      ps = set if symbol
181  *      typeid = set if in TypeidExpression https://dlang.org/spec/expression.html#TypeidExpression
182  */
183 private void resolveHelper(TypeQualified mt, const ref Loc loc, Scope* sc, Dsymbol s, Dsymbol scopesym,
184     Expression* pe, Type* pt, Dsymbol* ps, bool intypeid = false)
185 {
186     version (none)
187     {
188         printf("TypeQualified::resolveHelper(sc = %p, idents = '%s')\n", sc, mt.toChars());
189         if (scopesym)
190             printf("\tscopesym = '%s'\n", scopesym.toChars());
191     }
192     *pe = null;
193     *pt = null;
194     *ps = null;
195 
196     if (!s)
197     {
198         /* Look for what user might have intended
199          */
200         const p = mt.mutableOf().unSharedOf().toChars();
201         auto id = Identifier.idPool(p, cast(uint)strlen(p));
202         if (const n = importHint(id.toString()))
203             error(loc, "`%s` is not defined, perhaps `import %.*s;` ?", p, cast(int)n.length, n.ptr);
204         else if (auto s2 = sc.search_correct(id))
205             error(loc, "undefined identifier `%s`, did you mean %s `%s`?", p, s2.kind(), s2.toChars());
206         else if (const q = Scope.search_correct_C(id))
207             error(loc, "undefined identifier `%s`, did you mean `%s`?", p, q);
208         else
209             error(loc, "undefined identifier `%s`", p);
210 
211         *pt = Type.terror;
212         return;
213     }
214 
215     //printf("\t1: s = '%s' %p, kind = '%s'\n",s.toChars(), s, s.kind());
216     Declaration d = s.isDeclaration();
217     if (d && (d.storage_class & STC.templateparameter))
218         s = s.toAlias();
219     else
220     {
221         // check for deprecated or disabled aliases
222         s.checkDeprecated(loc, sc);
223         if (d)
224             d.checkDisabled(loc, sc, true);
225     }
226     s = s.toAlias();
227     //printf("\t2: s = '%s' %p, kind = '%s'\n",s.toChars(), s, s.kind());
228     for (size_t i = 0; i < mt.idents.dim; i++)
229     {
230         RootObject id = mt.idents[i];
231         if (id.dyncast() == DYNCAST.expression ||
232             id.dyncast() == DYNCAST.type)
233         {
234             Type tx;
235             Expression ex;
236             Dsymbol sx;
237             resolveTupleIndex(loc, sc, s, &ex, &tx, &sx, id);
238             if (sx)
239             {
240                 s = sx.toAlias();
241                 continue;
242             }
243             if (tx)
244                 ex = new TypeExp(loc, tx);
245             assert(ex);
246 
247             ex = typeToExpressionHelper(mt, ex, i + 1);
248             ex = ex.expressionSemantic(sc);
249             resolveExp(ex, pt, pe, ps);
250             return;
251         }
252 
253         Type t = s.getType(); // type symbol, type alias, or type tuple?
254         uint errorsave = global.errors;
255         int flags = t is null ? SearchLocalsOnly : IgnorePrivateImports;
256 
257         Dsymbol sm = s.searchX(loc, sc, id, flags);
258         if (sm && !(sc.flags & SCOPE.ignoresymbolvisibility) && !symbolIsVisible(sc, sm))
259         {
260             .error(loc, "`%s` is not visible from module `%s`", sm.toPrettyChars(), sc._module.toChars());
261             sm = null;
262         }
263         if (global.errors != errorsave)
264         {
265             *pt = Type.terror;
266             return;
267         }
268 
269         void helper3()
270         {
271             Expression e;
272             VarDeclaration v = s.isVarDeclaration();
273             FuncDeclaration f = s.isFuncDeclaration();
274             if (intypeid || !v && !f)
275                 e = symbolToExp(s, loc, sc, true);
276             else
277                 e = new VarExp(loc, s.isDeclaration(), true);
278 
279             e = typeToExpressionHelper(mt, e, i);
280             e = e.expressionSemantic(sc);
281             resolveExp(e, pt, pe, ps);
282         }
283 
284         //printf("\t3: s = %p %s %s, sm = %p\n", s, s.kind(), s.toChars(), sm);
285         if (intypeid && !t && sm && sm.needThis())
286             return helper3();
287 
288         if (VarDeclaration v = s.isVarDeclaration())
289         {
290             // https://issues.dlang.org/show_bug.cgi?id=19913
291             // v.type would be null if it is a forward referenced member.
292             if (v.type is null)
293                 v.dsymbolSemantic(sc);
294             if (v.storage_class & (STC.const_ | STC.immutable_ | STC.manifest) ||
295                 v.type.isConst() || v.type.isImmutable())
296             {
297                 // https://issues.dlang.org/show_bug.cgi?id=13087
298                 // this.field is not constant always
299                 if (!v.isThisDeclaration())
300                     return helper3();
301             }
302         }
303         if (!sm)
304         {
305             if (!t)
306             {
307                 if (s.isDeclaration()) // var, func, or tuple declaration?
308                 {
309                     t = s.isDeclaration().type;
310                     if (!t && s.isTupleDeclaration()) // expression tuple?
311                         return helper3();
312                 }
313                 else if (s.isTemplateInstance() ||
314                          s.isImport() || s.isPackage() || s.isModule())
315                 {
316                     return helper3();
317                 }
318             }
319             if (t)
320             {
321                 sm = t.toDsymbol(sc);
322                 if (sm && id.dyncast() == DYNCAST.identifier)
323                 {
324                     sm = sm.search(loc, cast(Identifier)id, IgnorePrivateImports);
325                     if (!sm)
326                         return helper3();
327                 }
328                 else
329                     return helper3();
330             }
331             else
332             {
333                 if (id.dyncast() == DYNCAST.dsymbol)
334                 {
335                     // searchX already handles errors for template instances
336                     assert(global.errors);
337                 }
338                 else
339                 {
340                     assert(id.dyncast() == DYNCAST.identifier);
341                     sm = s.search_correct(cast(Identifier)id);
342                     if (sm)
343                         error(loc, "identifier `%s` of `%s` is not defined, did you mean %s `%s`?", id.toChars(), mt.toChars(), sm.kind(), sm.toChars());
344                     else
345                         error(loc, "identifier `%s` of `%s` is not defined", id.toChars(), mt.toChars());
346                 }
347                 *pe = new ErrorExp();
348                 return;
349             }
350         }
351         s = sm.toAlias();
352     }
353 
354     if (auto em = s.isEnumMember())
355     {
356         // It's not a type, it's an expression
357         *pe = em.getVarExp(loc, sc);
358         return;
359     }
360     if (auto v = s.isVarDeclaration())
361     {
362         /* This is mostly same with DsymbolExp::semantic(), but we cannot use it
363          * because some variables used in type context need to prevent lowering
364          * to a literal or contextful expression. For example:
365          *
366          *  enum a = 1; alias b = a;
367          *  template X(alias e){ alias v = e; }  alias x = X!(1);
368          *  struct S { int v; alias w = v; }
369          *      // TypeIdentifier 'a', 'e', and 'v' should be TOK.variable,
370          *      // because getDsymbol() need to work in AliasDeclaration::semantic().
371          */
372         if (!v.type ||
373             !v.type.deco && v.inuse)
374         {
375             if (v.inuse) // https://issues.dlang.org/show_bug.cgi?id=9494
376                 error(loc, "circular reference to %s `%s`", v.kind(), v.toPrettyChars());
377             else
378                 error(loc, "forward reference to %s `%s`", v.kind(), v.toPrettyChars());
379             *pt = Type.terror;
380             return;
381         }
382         if (v.type.ty == Terror)
383             *pt = Type.terror;
384         else
385             *pe = new VarExp(loc, v);
386         return;
387     }
388     if (auto fld = s.isFuncLiteralDeclaration())
389     {
390         //printf("'%s' is a function literal\n", fld.toChars());
391         *pe = new FuncExp(loc, fld);
392         *pe = (*pe).expressionSemantic(sc);
393         return;
394     }
395     version (none)
396     {
397         if (FuncDeclaration fd = s.isFuncDeclaration())
398         {
399             *pe = new DsymbolExp(loc, fd);
400             return;
401         }
402     }
403 
404     Type t;
405     while (1)
406     {
407         t = s.getType();
408         if (t)
409             break;
410         // If the symbol is an import, try looking inside the import
411         if (Import si = s.isImport())
412         {
413             s = si.search(loc, s.ident);
414             if (s && s != si)
415                 continue;
416             s = si;
417         }
418         *ps = s;
419         return;
420     }
421 
422     if (auto ti = t.isTypeInstance())
423         if (ti != mt && !ti.deco)
424         {
425             if (!ti.tempinst.errors)
426                 error(loc, "forward reference to `%s`", ti.toChars());
427             *pt = Type.terror;
428             return;
429         }
430 
431     if (t.ty == Ttuple)
432         *pt = t;
433     else
434         *pt = t.merge();
435 }
436 
437 /************************************
438  * Transitively search a type for all function types.
439  * If any function types with parameters are found that have parameter identifiers
440  * or default arguments, remove those and create a new type stripped of those.
441  * This is used to determine the "canonical" version of a type which is useful for
442  * comparisons.
443  * Params:
444  *      t = type to scan
445  * Returns:
446  *      `t` if no parameter identifiers or default arguments found, otherwise a new type that is
447  *      the same as t but with no parameter identifiers or default arguments.
448  */
449 private Type stripDefaultArgs(Type t)
450 {
451     static Parameters* stripParams(Parameters* parameters)
452     {
453         static Parameter stripParameter(Parameter p)
454         {
455             Type t = stripDefaultArgs(p.type);
456             return (t != p.type || p.defaultArg || p.ident || p.userAttribDecl)
457                 ? new Parameter(p.storageClass, t, null, null, null)
458                 : null;
459         }
460 
461         if (parameters)
462         {
463             foreach (i, p; *parameters)
464             {
465                 Parameter ps = stripParameter(p);
466                 if (ps)
467                 {
468                     // Replace params with a copy we can modify
469                     Parameters* nparams = new Parameters(parameters.dim);
470 
471                     foreach (j, ref np; *nparams)
472                     {
473                         Parameter pj = (*parameters)[j];
474                         if (j < i)
475                             np = pj;
476                         else if (j == i)
477                             np = ps;
478                         else
479                         {
480                             Parameter nps = stripParameter(pj);
481                             np = nps ? nps : pj;
482                         }
483                     }
484                     return nparams;
485                 }
486             }
487         }
488         return parameters;
489     }
490 
491     if (t is null)
492         return t;
493 
494     if (auto tf = t.isTypeFunction())
495     {
496         Type tret = stripDefaultArgs(tf.next);
497         Parameters* params = stripParams(tf.parameterList.parameters);
498         if (tret == tf.next && params == tf.parameterList.parameters)
499             return t;
500         TypeFunction tr = cast(TypeFunction)tf.copy();
501         tr.parameterList.parameters = params;
502         tr.next = tret;
503         //printf("strip %s\n   <- %s\n", tr.toChars(), t.toChars());
504         return tr;
505     }
506     else if (auto tt = t.isTypeTuple())
507     {
508         Parameters* args = stripParams(tt.arguments);
509         if (args == tt.arguments)
510             return t;
511         TypeTuple tr = cast(TypeTuple)t.copy();
512         tr.arguments = args;
513         return tr;
514     }
515     else if (t.ty == Tenum)
516     {
517         // TypeEnum::nextOf() may be != NULL, but it's not necessary here.
518         return t;
519     }
520     else
521     {
522         Type tn = t.nextOf();
523         Type n = stripDefaultArgs(tn);
524         if (n == tn)
525             return t;
526         TypeNext tr = cast(TypeNext)t.copy();
527         tr.next = n;
528         return tr;
529     }
530 }
531 
532 /******************************************
533  * We've mistakenly parsed `t` as a type.
534  * Redo `t` as an Expression.
535  * Params:
536  *      t = mistaken type
537  * Returns:
538  *      t redone as Expression, null if cannot
539  */
540 Expression typeToExpression(Type t)
541 {
542     static Expression visitSArray(TypeSArray t)
543     {
544         if (auto e = t.next.typeToExpression())
545             return new ArrayExp(t.dim.loc, e, t.dim);
546         return null;
547     }
548 
549     static Expression visitAArray(TypeAArray t)
550     {
551         if (auto e = t.next.typeToExpression())
552         {
553             if (auto ei = t.index.typeToExpression())
554                 return new ArrayExp(t.loc, e, ei);
555         }
556         return null;
557     }
558 
559     static Expression visitIdentifier(TypeIdentifier t)
560     {
561         return typeToExpressionHelper(t, new IdentifierExp(t.loc, t.ident));
562     }
563 
564     static Expression visitInstance(TypeInstance t)
565     {
566         return typeToExpressionHelper(t, new ScopeExp(t.loc, t.tempinst));
567     }
568 
569     // easy way to enable 'auto v = new int[mixin("exp")];' in 2.088+
570     static Expression visitMixin(TypeMixin t)
571     {
572         return new TypeExp(t.loc, t);
573     }
574 
575     switch (t.ty)
576     {
577         case Tsarray:   return visitSArray(cast(TypeSArray) t);
578         case Taarray:   return visitAArray(cast(TypeAArray) t);
579         case Tident:    return visitIdentifier(cast(TypeIdentifier) t);
580         case Tinstance: return visitInstance(cast(TypeInstance) t);
581         case Tmixin:    return visitMixin(cast(TypeMixin) t);
582         default:        return null;
583     }
584 }
585 
586 /* Helper function for `typeToExpression`. Contains common code
587  * for TypeQualified derived classes.
588  */
589 Expression typeToExpressionHelper(TypeQualified t, Expression e, size_t i = 0)
590 {
591     //printf("toExpressionHelper(e = %s %s)\n", Token.toChars(e.op), e.toChars());
592     foreach (id; t.idents[i .. t.idents.dim])
593     {
594         //printf("\t[%d] e: '%s', id: '%s'\n", i, e.toChars(), id.toChars());
595 
596         final switch (id.dyncast())
597         {
598             // ... '. ident'
599             case DYNCAST.identifier:
600                 e = new DotIdExp(e.loc, e, cast(Identifier)id);
601                 break;
602 
603             // ... '. name!(tiargs)'
604             case DYNCAST.dsymbol:
605                 auto ti = (cast(Dsymbol)id).isTemplateInstance();
606                 assert(ti);
607                 e = new DotTemplateInstanceExp(e.loc, e, ti.name, ti.tiargs);
608                 break;
609 
610             // ... '[type]'
611             case DYNCAST.type:          // https://issues.dlang.org/show_bug.cgi?id=1215
612                 e = new ArrayExp(t.loc, e, new TypeExp(t.loc, cast(Type)id));
613                 break;
614 
615             // ... '[expr]'
616             case DYNCAST.expression:    // https://issues.dlang.org/show_bug.cgi?id=1215
617                 e = new ArrayExp(t.loc, e, cast(Expression)id);
618                 break;
619 
620             case DYNCAST.object:
621             case DYNCAST.tuple:
622             case DYNCAST.parameter:
623             case DYNCAST.statement:
624             case DYNCAST.condition:
625             case DYNCAST.templateparameter:
626                 assert(0);
627         }
628     }
629     return e;
630 }
631 
632 /******************************************
633  * Perform semantic analysis on a type.
634  * Params:
635  *      t = Type AST node
636  *      loc = the location of the type
637  *      sc = context
638  * Returns:
639  *      `Type` with completed semantic analysis, `Terror` if errors
640  *      were encountered
641  */
642 extern(C++) Type typeSemantic(Type t, const ref Loc loc, Scope* sc)
643 {
644     static Type error()
645     {
646         return Type.terror;
647     }
648 
649     Type visitType(Type t)
650     {
651         if (t.ty == Tint128 || t.ty == Tuns128)
652         {
653             .error(loc, "`cent` and `ucent` types not implemented");
654             return error();
655         }
656 
657         return t.merge();
658     }
659 
660     Type visitVector(TypeVector mtype)
661     {
662         const errors = global.errors;
663         mtype.basetype = mtype.basetype.typeSemantic(loc, sc);
664         if (errors != global.errors)
665             return error();
666         mtype.basetype = mtype.basetype.toBasetype().mutableOf();
667         if (mtype.basetype.ty != Tsarray)
668         {
669             .error(loc, "T in __vector(T) must be a static array, not `%s`", mtype.basetype.toChars());
670             return error();
671         }
672         TypeSArray t = cast(TypeSArray)mtype.basetype;
673         const sz = cast(int)t.size(loc);
674         final switch (target.isVectorTypeSupported(sz, t.nextOf()))
675         {
676         case 0:
677             // valid
678             break;
679 
680         case 1:
681             // no support at all
682             .error(loc, "SIMD vector types not supported on this platform");
683             return error();
684 
685         case 2:
686             // invalid base type
687             .error(loc, "vector type `%s` is not supported on this platform", mtype.toChars());
688             return error();
689 
690         case 3:
691             // invalid size
692             .error(loc, "%d byte vector type `%s` is not supported on this platform", sz, mtype.toChars());
693             return error();
694         }
695         return merge(mtype);
696     }
697 
698     Type visitSArray(TypeSArray mtype)
699     {
700         //printf("TypeSArray::semantic() %s\n", toChars());
701         Type t;
702         Expression e;
703         Dsymbol s;
704         mtype.next.resolve(loc, sc, &e, &t, &s);
705 
706         if (auto tup = s ? s.isTupleDeclaration() : null)
707         {
708             mtype.dim = semanticLength(sc, tup, mtype.dim);
709             mtype.dim = mtype.dim.ctfeInterpret();
710             if (mtype.dim.op == TOK.error)
711                 return error();
712 
713             uinteger_t d = mtype.dim.toUInteger();
714             if (d >= tup.objects.dim)
715             {
716                 .error(loc, "tuple index %llu exceeds %llu", cast(ulong)d, cast(ulong)tup.objects.dim);
717                 return error();
718             }
719 
720             RootObject o = (*tup.objects)[cast(size_t)d];
721             if (o.dyncast() != DYNCAST.type)
722             {
723                 .error(loc, "`%s` is not a type", mtype.toChars());
724                 return error();
725             }
726             return (cast(Type)o).addMod(mtype.mod);
727         }
728 
729         Type tn = mtype.next.typeSemantic(loc, sc);
730         if (tn.ty == Terror)
731             return error();
732 
733         Type tbn = tn.toBasetype();
734         if (mtype.dim)
735         {
736             //https://issues.dlang.org/show_bug.cgi?id=15478
737             if (mtype.dim.isDotVarExp())
738             {
739                 if (Declaration vd = mtype.dim.isDotVarExp().var)
740                 {
741                     FuncDeclaration fd = vd.toAlias().isFuncDeclaration();
742                     if (fd)
743                         mtype.dim = new CallExp(loc, fd, null);
744                 }
745             }
746 
747             auto errors = global.errors;
748             mtype.dim = semanticLength(sc, tbn, mtype.dim);
749             if (errors != global.errors)
750                 return error();
751 
752             mtype.dim = mtype.dim.optimize(WANTvalue);
753             mtype.dim = mtype.dim.ctfeInterpret();
754             if (mtype.dim.op == TOK.error)
755                 return error();
756 
757             errors = global.errors;
758             dinteger_t d1 = mtype.dim.toInteger();
759             if (errors != global.errors)
760                 return error();
761 
762             mtype.dim = mtype.dim.implicitCastTo(sc, Type.tsize_t);
763             mtype.dim = mtype.dim.optimize(WANTvalue);
764             if (mtype.dim.op == TOK.error)
765                 return error();
766 
767             errors = global.errors;
768             dinteger_t d2 = mtype.dim.toInteger();
769             if (errors != global.errors)
770                 return error();
771 
772             if (mtype.dim.op == TOK.error)
773                 return error();
774 
775             Type overflowError()
776             {
777                 .error(loc, "`%s` size %llu * %llu exceeds 0x%llx size limit for static array",
778                         mtype.toChars(), cast(ulong)tbn.size(loc), cast(ulong)d1, target.maxStaticDataSize);
779                 return error();
780             }
781 
782             if (d1 != d2)
783                 return overflowError();
784 
785             Type tbx = tbn.baseElemOf();
786             if (tbx.ty == Tstruct && !(cast(TypeStruct)tbx).sym.members ||
787                 tbx.ty == Tenum && !(cast(TypeEnum)tbx).sym.members)
788             {
789                 /* To avoid meaningless error message, skip the total size limit check
790                  * when the bottom of element type is opaque.
791                  */
792             }
793             else if (tbn.isTypeBasic() ||
794                      tbn.ty == Tpointer ||
795                      tbn.ty == Tarray ||
796                      tbn.ty == Tsarray ||
797                      tbn.ty == Taarray ||
798                      (tbn.ty == Tstruct && ((cast(TypeStruct)tbn).sym.sizeok == Sizeok.done)) ||
799                      tbn.ty == Tclass)
800             {
801                 /* Only do this for types that don't need to have semantic()
802                  * run on them for the size, since they may be forward referenced.
803                  */
804                 bool overflow = false;
805                 if (mulu(tbn.size(loc), d2, overflow) >= target.maxStaticDataSize || overflow)
806                     return overflowError();
807             }
808         }
809         switch (tbn.ty)
810         {
811         case Ttuple:
812             {
813                 // Index the tuple to get the type
814                 assert(mtype.dim);
815                 TypeTuple tt = cast(TypeTuple)tbn;
816                 uinteger_t d = mtype.dim.toUInteger();
817                 if (d >= tt.arguments.dim)
818                 {
819                     .error(loc, "tuple index %llu exceeds %llu", cast(ulong)d, cast(ulong)tt.arguments.dim);
820                     return error();
821                 }
822                 Type telem = (*tt.arguments)[cast(size_t)d].type;
823                 return telem.addMod(mtype.mod);
824             }
825 
826         case Tfunction:
827         case Tnone:
828             .error(loc, "cannot have array of `%s`", tbn.toChars());
829             return error();
830 
831         default:
832             break;
833         }
834         if (tbn.isscope())
835         {
836             .error(loc, "cannot have array of scope `%s`", tbn.toChars());
837             return error();
838         }
839 
840         /* Ensure things like const(immutable(T)[3]) become immutable(T[3])
841          * and const(T)[3] become const(T[3])
842          */
843         mtype.next = tn;
844         mtype.transitive();
845         return mtype.addMod(tn.mod).merge();
846     }
847 
848     Type visitDArray(TypeDArray mtype)
849     {
850         Type tn = mtype.next.typeSemantic(loc, sc);
851         Type tbn = tn.toBasetype();
852         switch (tbn.ty)
853         {
854         case Ttuple:
855             return tbn;
856 
857         case Tfunction:
858         case Tnone:
859             .error(loc, "cannot have array of `%s`", tbn.toChars());
860             return error();
861 
862         case Terror:
863             return error();
864 
865         default:
866             break;
867         }
868         if (tn.isscope())
869         {
870             .error(loc, "cannot have array of scope `%s`", tn.toChars());
871             return error();
872         }
873         mtype.next = tn;
874         mtype.transitive();
875         return merge(mtype);
876     }
877 
878     Type visitAArray(TypeAArray mtype)
879     {
880         //printf("TypeAArray::semantic() %s index.ty = %d\n", mtype.toChars(), mtype.index.ty);
881         if (mtype.deco)
882         {
883             return mtype;
884         }
885 
886         mtype.loc = loc;
887         mtype.sc = sc;
888         if (sc)
889             sc.setNoFree();
890 
891         // Deal with the case where we thought the index was a type, but
892         // in reality it was an expression.
893         if (mtype.index.ty == Tident || mtype.index.ty == Tinstance || mtype.index.ty == Tsarray || mtype.index.ty == Ttypeof || mtype.index.ty == Treturn || mtype.index.ty == Tmixin)
894         {
895             Expression e;
896             Type t;
897             Dsymbol s;
898             mtype.index.resolve(loc, sc, &e, &t, &s);
899 
900             //https://issues.dlang.org/show_bug.cgi?id=15478
901             if (s)
902             {
903                 if (FuncDeclaration fd = s.toAlias().isFuncDeclaration())
904                     e = new CallExp(loc, fd, null);
905             }
906 
907             if (e)
908             {
909                 // It was an expression -
910                 // Rewrite as a static array
911                 auto tsa = new TypeSArray(mtype.next, e);
912                 return tsa.typeSemantic(loc, sc);
913             }
914             else if (t)
915                 mtype.index = t.typeSemantic(loc, sc);
916             else
917             {
918                 .error(loc, "index is not a type or an expression");
919                 return error();
920             }
921         }
922         else
923             mtype.index = mtype.index.typeSemantic(loc, sc);
924         mtype.index = mtype.index.merge2();
925 
926         if (mtype.index.nextOf() && !mtype.index.nextOf().isImmutable())
927         {
928             mtype.index = mtype.index.constOf().mutableOf();
929             version (none)
930             {
931                 printf("index is %p %s\n", mtype.index, mtype.index.toChars());
932                 mtype.index.check();
933                 printf("index.mod = x%x\n", mtype.index.mod);
934                 printf("index.ito = x%x\n", mtype.index.ito);
935                 if (mtype.index.ito)
936                 {
937                     printf("index.ito.mod = x%x\n", mtype.index.ito.mod);
938                     printf("index.ito.ito = x%x\n", mtype.index.ito.ito);
939                 }
940             }
941         }
942 
943         switch (mtype.index.toBasetype().ty)
944         {
945         case Tfunction:
946         case Tvoid:
947         case Tnone:
948         case Ttuple:
949             .error(loc, "cannot have associative array key of `%s`", mtype.index.toBasetype().toChars());
950             goto case Terror;
951         case Terror:
952             return error();
953 
954         default:
955             break;
956         }
957         Type tbase = mtype.index.baseElemOf();
958         while (tbase.ty == Tarray)
959             tbase = tbase.nextOf().baseElemOf();
960         if (auto ts = tbase.isTypeStruct())
961         {
962             /* AA's need typeid(index).equals() and getHash(). Issue error if not correctly set up.
963              */
964             StructDeclaration sd = ts.sym;
965             if (sd.semanticRun < PASS.semanticdone)
966                 sd.dsymbolSemantic(null);
967 
968             // duplicate a part of StructDeclaration::semanticTypeInfoMembers
969             //printf("AA = %s, key: xeq = %p, xerreq = %p xhash = %p\n", toChars(), sd.xeq, sd.xerreq, sd.xhash);
970             if (sd.xeq && sd.xeq._scope && sd.xeq.semanticRun < PASS.semantic3done)
971             {
972                 uint errors = global.startGagging();
973                 sd.xeq.semantic3(sd.xeq._scope);
974                 if (global.endGagging(errors))
975                     sd.xeq = sd.xerreq;
976             }
977 
978             //printf("AA = %s, key: xeq = %p, xhash = %p\n", toChars(), sd.xeq, sd.xhash);
979             const(char)* s = (mtype.index.toBasetype().ty != Tstruct) ? "bottom of " : "";
980             if (!sd.xeq)
981             {
982                 // If sd.xhash != NULL:
983                 //   sd or its fields have user-defined toHash.
984                 //   AA assumes that its result is consistent with bitwise equality.
985                 // else:
986                 //   bitwise equality & hashing
987             }
988             else if (sd.xeq == sd.xerreq)
989             {
990                 if (search_function(sd, Id.eq))
991                 {
992                     .error(loc, "%sAA key type `%s` does not have `bool opEquals(ref const %s) const`", s, sd.toChars(), sd.toChars());
993                 }
994                 else
995                 {
996                     .error(loc, "%sAA key type `%s` does not support const equality", s, sd.toChars());
997                 }
998                 return error();
999             }
1000             else if (!sd.xhash)
1001             {
1002                 if (search_function(sd, Id.eq))
1003                 {
1004                     .error(loc, "%sAA key type `%s` should have `extern (D) size_t toHash() const nothrow @safe` if `opEquals` defined", s, sd.toChars());
1005                 }
1006                 else
1007                 {
1008                     .error(loc, "%sAA key type `%s` supports const equality but doesn't support const hashing", s, sd.toChars());
1009                 }
1010                 return error();
1011             }
1012             else
1013             {
1014                 // defined equality & hashing
1015                 assert(sd.xeq && sd.xhash);
1016 
1017                 /* xeq and xhash may be implicitly defined by compiler. For example:
1018                  *   struct S { int[] arr; }
1019                  * With 'arr' field equality and hashing, compiler will implicitly
1020                  * generate functions for xopEquals and xtoHash in TypeInfo_Struct.
1021                  */
1022             }
1023         }
1024         else if (tbase.ty == Tclass && !(cast(TypeClass)tbase).sym.isInterfaceDeclaration())
1025         {
1026             ClassDeclaration cd = (cast(TypeClass)tbase).sym;
1027             if (cd.semanticRun < PASS.semanticdone)
1028                 cd.dsymbolSemantic(null);
1029 
1030             if (!ClassDeclaration.object)
1031             {
1032                 .error(Loc.initial, "missing or corrupt object.d");
1033                 fatal();
1034             }
1035 
1036             __gshared FuncDeclaration feq = null;
1037             __gshared FuncDeclaration fcmp = null;
1038             __gshared FuncDeclaration fhash = null;
1039             if (!feq)
1040                 feq = search_function(ClassDeclaration.object, Id.eq).isFuncDeclaration();
1041             if (!fcmp)
1042                 fcmp = search_function(ClassDeclaration.object, Id.cmp).isFuncDeclaration();
1043             if (!fhash)
1044                 fhash = search_function(ClassDeclaration.object, Id.tohash).isFuncDeclaration();
1045             assert(fcmp && feq && fhash);
1046 
1047             if (feq.vtblIndex < cd.vtbl.dim && cd.vtbl[feq.vtblIndex] == feq)
1048             {
1049                 version (all)
1050                 {
1051                     if (fcmp.vtblIndex < cd.vtbl.dim && cd.vtbl[fcmp.vtblIndex] != fcmp)
1052                     {
1053                         const(char)* s = (mtype.index.toBasetype().ty != Tclass) ? "bottom of " : "";
1054                         .error(loc, "%sAA key type `%s` now requires equality rather than comparison", s, cd.toChars());
1055                         errorSupplemental(loc, "Please override `Object.opEquals` and `Object.toHash`.");
1056                     }
1057                 }
1058             }
1059         }
1060         mtype.next = mtype.next.typeSemantic(loc, sc).merge2();
1061         mtype.transitive();
1062 
1063         switch (mtype.next.toBasetype().ty)
1064         {
1065         case Tfunction:
1066         case Tvoid:
1067         case Tnone:
1068         case Ttuple:
1069             .error(loc, "cannot have associative array of `%s`", mtype.next.toChars());
1070             goto case Terror;
1071         case Terror:
1072             return error();
1073         default:
1074             break;
1075         }
1076         if (mtype.next.isscope())
1077         {
1078             .error(loc, "cannot have array of scope `%s`", mtype.next.toChars());
1079             return error();
1080         }
1081         return merge(mtype);
1082     }
1083 
1084     Type visitPointer(TypePointer mtype)
1085     {
1086         //printf("TypePointer::semantic() %s\n", toChars());
1087         if (mtype.deco)
1088         {
1089             return mtype;
1090         }
1091         Type n = mtype.next.typeSemantic(loc, sc);
1092         switch (n.toBasetype().ty)
1093         {
1094         case Ttuple:
1095             .error(loc, "cannot have pointer to `%s`", n.toChars());
1096             goto case Terror;
1097         case Terror:
1098             return error();
1099         default:
1100             break;
1101         }
1102         if (n != mtype.next)
1103         {
1104             mtype.deco = null;
1105         }
1106         mtype.next = n;
1107         if (mtype.next.ty != Tfunction)
1108         {
1109             mtype.transitive();
1110             return merge(mtype);
1111         }
1112         version (none)
1113         {
1114             return merge(mtype);
1115         }
1116         else
1117         {
1118             mtype.deco = merge(mtype).deco;
1119             /* Don't return merge(), because arg identifiers and default args
1120              * can be different
1121              * even though the types match
1122              */
1123             return mtype;
1124         }
1125     }
1126 
1127     Type visitReference(TypeReference mtype)
1128     {
1129         //printf("TypeReference::semantic()\n");
1130         Type n = mtype.next.typeSemantic(loc, sc);
1131         if (n != mtype.next)
1132            mtype.deco = null;
1133         mtype.next = n;
1134         mtype.transitive();
1135         return merge(mtype);
1136     }
1137 
1138     Type visitFunction(TypeFunction mtype)
1139     {
1140         if (mtype.deco) // if semantic() already run
1141         {
1142             //printf("already done\n");
1143             return mtype;
1144         }
1145         //printf("TypeFunction::semantic() this = %p\n", this);
1146         //printf("TypeFunction::semantic() %s, sc.stc = %llx, fargs = %p\n", toChars(), sc.stc, fargs);
1147 
1148         bool errors = false;
1149 
1150         if (mtype.inuse > global.recursionLimit)
1151         {
1152             mtype.inuse = 0;
1153             .error(loc, "recursive type");
1154             return error();
1155         }
1156 
1157         /* Copy in order to not mess up original.
1158          * This can produce redundant copies if inferring return type,
1159          * as semantic() will get called again on this.
1160          */
1161         TypeFunction tf = mtype.copy().toTypeFunction();
1162         if (mtype.parameterList.parameters)
1163         {
1164             tf.parameterList.parameters = mtype.parameterList.parameters.copy();
1165             for (size_t i = 0; i < mtype.parameterList.parameters.dim; i++)
1166             {
1167                 Parameter p = cast(Parameter)mem.xmalloc(__traits(classInstanceSize, Parameter));
1168                 memcpy(cast(void*)p, cast(void*)(*mtype.parameterList.parameters)[i], __traits(classInstanceSize, Parameter));
1169                 (*tf.parameterList.parameters)[i] = p;
1170             }
1171         }
1172 
1173         if (sc.stc & STC.pure_)
1174             tf.purity = PURE.fwdref;
1175         if (sc.stc & STC.nothrow_)
1176             tf.isnothrow = true;
1177         if (sc.stc & STC.nogc)
1178             tf.isnogc = true;
1179         if (sc.stc & STC.ref_)
1180             tf.isref = true;
1181         if (sc.stc & STC.return_)
1182             tf.isreturn = true;
1183         if (sc.stc & STC.returninferred)
1184             tf.isreturninferred = true;
1185         if (sc.stc & STC.scope_)
1186             tf.isscope = true;
1187         if (sc.stc & STC.scopeinferred)
1188             tf.isscopeinferred = true;
1189 
1190 //        if (tf.isreturn && !tf.isref)
1191 //            tf.isscope = true;                                  // return by itself means 'return scope'
1192 
1193         if (tf.trust == TRUST.default_)
1194         {
1195             if (sc.stc & STC.safe)
1196                 tf.trust = TRUST.safe;
1197             else if (sc.stc & STC.system)
1198                 tf.trust = TRUST.system;
1199             else if (sc.stc & STC.trusted)
1200                 tf.trust = TRUST.trusted;
1201         }
1202 
1203         if (sc.stc & STC.property)
1204             tf.isproperty = true;
1205         if (sc.stc & STC.live)
1206             tf.islive = true;
1207 
1208         tf.linkage = sc.linkage;
1209         version (none)
1210         {
1211             /* If the parent is @safe, then this function defaults to safe
1212              * too.
1213              * If the parent's @safe-ty is inferred, then this function's @safe-ty needs
1214              * to be inferred first.
1215              */
1216             if (tf.trust == TRUST.default_)
1217                 for (Dsymbol p = sc.func; p; p = p.toParent2())
1218                 {
1219                     FuncDeclaration fd = p.isFuncDeclaration();
1220                     if (fd)
1221                     {
1222                         if (fd.isSafeBypassingInference())
1223                             tf.trust = TRUST.safe; // default to @safe
1224                         break;
1225                     }
1226                 }
1227         }
1228 
1229         bool wildreturn = false;
1230         if (tf.next)
1231         {
1232             sc = sc.push();
1233             sc.stc &= ~(STC.TYPECTOR | STC.FUNCATTR);
1234             tf.next = tf.next.typeSemantic(loc, sc);
1235             sc = sc.pop();
1236             errors |= tf.checkRetType(loc);
1237             if (tf.next.isscope() && !(sc.flags & SCOPE.ctor))
1238             {
1239                 .error(loc, "functions cannot return `scope %s`", tf.next.toChars());
1240                 errors = true;
1241             }
1242             if (tf.next.hasWild())
1243                 wildreturn = true;
1244 
1245             if (tf.isreturn && !tf.isref && !tf.next.hasPointers())
1246             {
1247                 tf.isreturn = false;
1248             }
1249         }
1250 
1251         ubyte wildparams = 0;
1252         if (tf.parameterList.parameters)
1253         {
1254             /* Create a scope for evaluating the default arguments for the parameters
1255              */
1256             Scope* argsc = sc.push();
1257             argsc.stc = 0; // don't inherit storage class
1258             argsc.protection = Prot(Prot.Kind.public_);
1259             argsc.func = null;
1260 
1261             size_t dim = tf.parameterList.length;
1262             for (size_t i = 0; i < dim; i++)
1263             {
1264                 Parameter fparam = tf.parameterList[i];
1265                 mtype.inuse++;
1266                 fparam.type = fparam.type.typeSemantic(loc, argsc);
1267                 mtype.inuse--;
1268                 if (fparam.type.ty == Terror)
1269                 {
1270                     errors = true;
1271                     continue;
1272                 }
1273 
1274                 fparam.type = fparam.type.addStorageClass(fparam.storageClass);
1275 
1276                 if (fparam.storageClass & (STC.auto_ | STC.alias_ | STC.static_))
1277                 {
1278                     if (!fparam.type)
1279                         continue;
1280                 }
1281 
1282                 Type t = fparam.type.toBasetype();
1283 
1284                 if (t.ty == Tfunction)
1285                 {
1286                     .error(loc, "cannot have parameter of function type `%s`", fparam.type.toChars());
1287                     errors = true;
1288                 }
1289                 else if (!(fparam.storageClass & (STC.ref_ | STC.out_)) &&
1290                          (t.ty == Tstruct || t.ty == Tsarray || t.ty == Tenum))
1291                 {
1292                     Type tb2 = t.baseElemOf();
1293                     if (tb2.ty == Tstruct && !(cast(TypeStruct)tb2).sym.members ||
1294                         tb2.ty == Tenum && !(cast(TypeEnum)tb2).sym.memtype)
1295                     {
1296                         .error(loc, "cannot have parameter of opaque type `%s` by value", fparam.type.toChars());
1297                         errors = true;
1298                     }
1299                 }
1300                 else if (!(fparam.storageClass & STC.lazy_) && t.ty == Tvoid)
1301                 {
1302                     .error(loc, "cannot have parameter of type `%s`", fparam.type.toChars());
1303                     errors = true;
1304                 }
1305 
1306                 if ((fparam.storageClass & (STC.ref_ | STC.wild)) == (STC.ref_ | STC.wild))
1307                 {
1308                     // 'ref inout' implies 'return'
1309                     fparam.storageClass |= STC.return_;
1310                 }
1311 
1312                 if (fparam.storageClass & STC.return_)
1313                 {
1314                     if (fparam.storageClass & (STC.ref_ | STC.out_))
1315                     {
1316                         // Disabled for the moment awaiting improvement to allow return by ref
1317                         // to be transformed into return by scope.
1318                         if (0 && !tf.isref)
1319                         {
1320                             auto stc = fparam.storageClass & (STC.ref_ | STC.out_);
1321                             .error(loc, "parameter `%s` is `return %s` but function does not return by `ref`",
1322                                 fparam.ident ? fparam.ident.toChars() : "",
1323                                 stcToChars(stc));
1324                             errors = true;
1325                         }
1326                     }
1327                     else
1328                     {
1329                         if (!(fparam.storageClass & STC.scope_))
1330                             fparam.storageClass |= STC.scope_ | STC.scopeinferred; // 'return' implies 'scope'
1331                         if (tf.isref)
1332                         {
1333                         }
1334                         else if (tf.next && !tf.next.hasPointers() && tf.next.toBasetype().ty != Tvoid)
1335                         {
1336                             fparam.storageClass &= ~STC.return_;   // https://issues.dlang.org/show_bug.cgi?id=18963
1337                         }
1338                     }
1339                 }
1340 
1341                 if (fparam.storageClass & (STC.ref_ | STC.lazy_))
1342                 {
1343                 }
1344                 else if (fparam.storageClass & STC.out_)
1345                 {
1346                     if (ubyte m = fparam.type.mod & (MODFlags.immutable_ | MODFlags.const_ | MODFlags.wild))
1347                     {
1348                         .error(loc, "cannot have `%s out` parameter of type `%s`", MODtoChars(m), t.toChars());
1349                         errors = true;
1350                     }
1351                     else
1352                     {
1353                         Type tv = t.baseElemOf();
1354                         if (tv.ty == Tstruct && (cast(TypeStruct)tv).sym.noDefaultCtor)
1355                         {
1356                             .error(loc, "cannot have `out` parameter of type `%s` because the default construction is disabled", fparam.type.toChars());
1357                             errors = true;
1358                         }
1359                     }
1360                 }
1361 
1362                 if (fparam.storageClass & STC.scope_ && !fparam.type.hasPointers() && fparam.type.ty != Ttuple)
1363                 {
1364                     /*     X foo(ref return scope X) => Ref-ReturnScope
1365                      * ref X foo(ref return scope X) => ReturnRef-Scope
1366                      * But X has no pointers, we don't need the scope part, so:
1367                      *     X foo(ref return scope X) => Ref
1368                      * ref X foo(ref return scope X) => ReturnRef
1369                      * Constructors are treated as if they are being returned through the hidden parameter,
1370                      * which is by ref, and the ref there is ignored.
1371                      */
1372                     fparam.storageClass &= ~STC.scope_;
1373                     if (!tf.isref || (sc.flags & SCOPE.ctor))
1374                         fparam.storageClass &= ~STC.return_;
1375                 }
1376 
1377                 if (t.hasWild())
1378                 {
1379                     wildparams |= 1;
1380                     //if (tf.next && !wildreturn)
1381                     //    error(loc, "inout on parameter means inout must be on return type as well (if from D1 code, replace with `ref`)");
1382                 }
1383 
1384                 if (fparam.defaultArg)
1385                 {
1386                     Expression e = fparam.defaultArg;
1387                     const isRefOrOut = fparam.storageClass & (STC.ref_ | STC.out_);
1388                     const isAuto = fparam.storageClass & (STC.auto_ | STC.autoref);
1389                     if (isRefOrOut && !isAuto)
1390                     {
1391                         e = e.expressionSemantic(argsc);
1392                         e = resolveProperties(argsc, e);
1393                     }
1394                     else
1395                     {
1396                         e = inferType(e, fparam.type);
1397                         Initializer iz = new ExpInitializer(e.loc, e);
1398                         iz = iz.initializerSemantic(argsc, fparam.type, INITnointerpret);
1399                         e = iz.initializerToExpression();
1400                     }
1401                     if (e.op == TOK.function_) // https://issues.dlang.org/show_bug.cgi?id=4820
1402                     {
1403                         FuncExp fe = cast(FuncExp)e;
1404                         // Replace function literal with a function symbol,
1405                         // since default arg expression must be copied when used
1406                         // and copying the literal itself is wrong.
1407                         e = new VarExp(e.loc, fe.fd, false);
1408                         e = new AddrExp(e.loc, e);
1409                         e = e.expressionSemantic(argsc);
1410                     }
1411                     e = e.implicitCastTo(argsc, fparam.type);
1412 
1413                     // default arg must be an lvalue
1414                     if (isRefOrOut && !isAuto)
1415                         e = e.toLvalue(argsc, e);
1416 
1417                     fparam.defaultArg = e;
1418                     if (e.op == TOK.error)
1419                         errors = true;
1420                 }
1421 
1422                 /* If fparam after semantic() turns out to be a tuple, the number of parameters may
1423                  * change.
1424                  */
1425                 if (auto tt = t.isTypeTuple())
1426                 {
1427                     /* TypeFunction::parameter also is used as the storage of
1428                      * Parameter objects for FuncDeclaration. So we should copy
1429                      * the elements of TypeTuple::arguments to avoid unintended
1430                      * sharing of Parameter object among other functions.
1431                      */
1432                     if (tt.arguments && tt.arguments.dim)
1433                     {
1434                         /* Propagate additional storage class from tuple parameters to their
1435                          * element-parameters.
1436                          * Make a copy, as original may be referenced elsewhere.
1437                          */
1438                         size_t tdim = tt.arguments.dim;
1439                         auto newparams = new Parameters(tdim);
1440                         for (size_t j = 0; j < tdim; j++)
1441                         {
1442                             Parameter narg = (*tt.arguments)[j];
1443 
1444                             // https://issues.dlang.org/show_bug.cgi?id=12744
1445                             // If the storage classes of narg
1446                             // conflict with the ones in fparam, it's ignored.
1447                             StorageClass stc  = fparam.storageClass | narg.storageClass;
1448                             StorageClass stc1 = fparam.storageClass & (STC.ref_ | STC.out_ | STC.lazy_);
1449                             StorageClass stc2 =   narg.storageClass & (STC.ref_ | STC.out_ | STC.lazy_);
1450                             if (stc1 && stc2 && stc1 != stc2)
1451                             {
1452                                 OutBuffer buf1;  stcToBuffer(&buf1, stc1 | ((stc1 & STC.ref_) ? (fparam.storageClass & STC.auto_) : 0));
1453                                 OutBuffer buf2;  stcToBuffer(&buf2, stc2);
1454 
1455                                 .error(loc, "incompatible parameter storage classes `%s` and `%s`",
1456                                     buf1.peekChars(), buf2.peekChars());
1457                                 errors = true;
1458                                 stc = stc1 | (stc & ~(STC.ref_ | STC.out_ | STC.lazy_));
1459                             }
1460 
1461                             /* https://issues.dlang.org/show_bug.cgi?id=18572
1462                              *
1463                              * If a tuple parameter has a default argument, when expanding the parameter
1464                              * tuple the default argument tuple must also be expanded.
1465                              */
1466                             Expression paramDefaultArg = narg.defaultArg;
1467                             TupleExp te = fparam.defaultArg ? fparam.defaultArg.isTupleExp() : null;
1468                             if (te && te.exps && te.exps.length)
1469                                 paramDefaultArg = (*te.exps)[j];
1470 
1471                             (*newparams)[j] = new Parameter(
1472                                 stc, narg.type, narg.ident, paramDefaultArg, narg.userAttribDecl);
1473                         }
1474                         fparam.type = new TypeTuple(newparams);
1475                     }
1476                     fparam.storageClass = 0;
1477 
1478                     /* Reset number of parameters, and back up one to do this fparam again,
1479                      * now that it is a tuple
1480                      */
1481                     dim = tf.parameterList.length;
1482                     i--;
1483                     continue;
1484                 }
1485 
1486                 /* Resolve "auto ref" storage class to be either ref or value,
1487                  * based on the argument matching the parameter
1488                  */
1489                 if (fparam.storageClass & STC.auto_)
1490                 {
1491                     Expression farg = mtype.fargs && i < mtype.fargs.dim ? (*mtype.fargs)[i] : fparam.defaultArg;
1492                     if (farg && (fparam.storageClass & STC.ref_))
1493                     {
1494                         if (farg.isLvalue())
1495                         {
1496                             // ref parameter
1497                         }
1498                         else
1499                             fparam.storageClass &= ~STC.ref_; // value parameter
1500                         fparam.storageClass &= ~STC.auto_;    // https://issues.dlang.org/show_bug.cgi?id=14656
1501                         fparam.storageClass |= STC.autoref;
1502                     }
1503                     else if (mtype.incomplete && (fparam.storageClass & STC.ref_))
1504                     {
1505                         // the default argument may have been temporarily removed,
1506                         // see usage of `TypeFunction.incomplete`.
1507                         // https://issues.dlang.org/show_bug.cgi?id=19891
1508                         fparam.storageClass &= ~STC.auto_;
1509                         fparam.storageClass |= STC.autoref;
1510                     }
1511                     else
1512                     {
1513                         .error(loc, "`auto` can only be used as part of `auto ref` for template function parameters");
1514                         errors = true;
1515                     }
1516                 }
1517 
1518                 // Remove redundant storage classes for type, they are already applied
1519                 fparam.storageClass &= ~(STC.TYPECTOR | STC.in_);
1520             }
1521             argsc.pop();
1522         }
1523         if (tf.isWild())
1524             wildparams |= 2;
1525 
1526         if (wildreturn && !wildparams)
1527         {
1528             .error(loc, "`inout` on `return` means `inout` must be on a parameter as well for `%s`", mtype.toChars());
1529             errors = true;
1530         }
1531         tf.iswild = wildparams;
1532 
1533         if (tf.isproperty && (tf.parameterList.varargs != VarArg.none || tf.parameterList.length > 2))
1534         {
1535             .error(loc, "properties can only have zero, one, or two parameter");
1536             errors = true;
1537         }
1538 
1539         if (tf.parameterList.varargs == VarArg.variadic && tf.linkage != LINK.d && tf.parameterList.length == 0)
1540         {
1541             .error(loc, "variadic functions with non-D linkage must have at least one parameter");
1542             errors = true;
1543         }
1544 
1545         if (errors)
1546             return error();
1547 
1548         if (tf.next)
1549             tf.deco = tf.merge().deco;
1550 
1551         /* Don't return merge(), because arg identifiers and default args
1552          * can be different
1553          * even though the types match
1554          */
1555         return tf;
1556     }
1557 
1558     Type visitDelegate(TypeDelegate mtype)
1559     {
1560         //printf("TypeDelegate::semantic() %s\n", toChars());
1561         if (mtype.deco) // if semantic() already run
1562         {
1563             //printf("already done\n");
1564             return mtype;
1565         }
1566         mtype.next = mtype.next.typeSemantic(loc, sc);
1567         if (mtype.next.ty != Tfunction)
1568             return error();
1569 
1570         /* In order to deal with https://issues.dlang.org/show_bug.cgi?id=4028
1571          * perhaps default arguments should
1572          * be removed from next before the merge.
1573          */
1574         version (none)
1575         {
1576             return mtype.merge();
1577         }
1578         else
1579         {
1580             /* Don't return merge(), because arg identifiers and default args
1581              * can be different
1582              * even though the types match
1583              */
1584             mtype.deco = mtype.merge().deco;
1585             return mtype;
1586         }
1587     }
1588 
1589     Type visitIdentifier(TypeIdentifier mtype)
1590     {
1591         Type t;
1592         Expression e;
1593         Dsymbol s;
1594         //printf("TypeIdentifier::semantic(%s)\n", mtype.toChars());
1595         mtype.resolve(loc, sc, &e, &t, &s);
1596         if (t)
1597         {
1598             //printf("\tit's a type %d, %s, %s\n", t.ty, t.toChars(), t.deco);
1599             return t.addMod(mtype.mod);
1600         }
1601         else
1602         {
1603             if (s)
1604             {
1605                 auto td = s.isTemplateDeclaration;
1606                 if (td && td.onemember && td.onemember.isAggregateDeclaration)
1607                     .error(loc, "template %s `%s` is used as a type without instantiation"
1608                         ~ "; to instantiate it use `%s!(arguments)`",
1609                         s.kind, s.toPrettyChars, s.ident.toChars);
1610                 else
1611                     .error(loc, "%s `%s` is used as a type", s.kind, s.toPrettyChars);
1612                 //assert(0);
1613             }
1614             else if (e.op == TOK.variable) // special case: variable is used as a type
1615             {
1616                 Dsymbol varDecl = mtype.toDsymbol(sc);
1617                 const(Loc) varDeclLoc = varDecl.getLoc();
1618                 Module varDeclModule = varDecl.getModule();
1619 
1620                 .error(loc, "variable `%s` is used as a type", mtype.toChars());
1621 
1622                 if (varDeclModule != sc._module) // variable is imported
1623                 {
1624                     const(Loc) varDeclModuleImportLoc = varDeclModule.getLoc();
1625                     .errorSupplemental(
1626                         varDeclModuleImportLoc,
1627                         "variable `%s` is imported here from: `%s`",
1628                         varDecl.toChars,
1629                         varDeclModule.toPrettyChars,
1630                     );
1631                 }
1632 
1633                 .errorSupplemental(varDeclLoc, "variable `%s` is declared here", varDecl.toChars);
1634             }
1635             else
1636                 .error(loc, "`%s` is used as a type", mtype.toChars());
1637             return error();
1638         }
1639     }
1640 
1641     Type visitInstance(TypeInstance mtype)
1642     {
1643         Type t;
1644         Expression e;
1645         Dsymbol s;
1646 
1647         //printf("TypeInstance::semantic(%p, %s)\n", this, toChars());
1648         {
1649             const errors = global.errors;
1650             mtype.resolve(loc, sc, &e, &t, &s);
1651             // if we had an error evaluating the symbol, suppress further errors
1652             if (!t && errors != global.errors)
1653                 return error();
1654         }
1655 
1656         if (!t)
1657         {
1658             if (!e && s && s.errors)
1659             {
1660                 // if there was an error evaluating the symbol, it might actually
1661                 // be a type. Avoid misleading error messages.
1662                .error(loc, "`%s` had previous errors", mtype.toChars());
1663             }
1664             else
1665                .error(loc, "`%s` is used as a type", mtype.toChars());
1666             return error();
1667         }
1668         return t;
1669     }
1670 
1671     Type visitTypeof(TypeTypeof mtype)
1672     {
1673         //printf("TypeTypeof::semantic() %s\n", mtype.toChars());
1674         Expression e;
1675         Type t;
1676         Dsymbol s;
1677         mtype.resolve(loc, sc, &e, &t, &s);
1678         if (s && (t = s.getType()) !is null)
1679             t = t.addMod(mtype.mod);
1680         if (!t)
1681         {
1682             .error(loc, "`%s` is used as a type", mtype.toChars());
1683             return error();
1684         }
1685         return t;
1686     }
1687 
1688     Type visitTraits(TypeTraits mtype)
1689     {
1690         if (mtype.ty == Terror)
1691             return mtype;
1692 
1693         const inAlias = (sc.flags & SCOPE.alias_) != 0;
1694         if (mtype.exp.ident != Id.allMembers &&
1695             mtype.exp.ident != Id.derivedMembers &&
1696             mtype.exp.ident != Id.getMember &&
1697             mtype.exp.ident != Id.parent &&
1698             mtype.exp.ident != Id.getOverloads &&
1699             mtype.exp.ident != Id.getVirtualFunctions &&
1700             mtype.exp.ident != Id.getVirtualMethods &&
1701             mtype.exp.ident != Id.getAttributes &&
1702             mtype.exp.ident != Id.getUnitTests &&
1703             mtype.exp.ident != Id.getAliasThis)
1704         {
1705             static immutable (const(char)*)[2] ctxt = ["as type", "in alias"];
1706             .error(mtype.loc, "trait `%s` is either invalid or not supported %s",
1707                  mtype.exp.ident.toChars, ctxt[inAlias]);
1708             mtype.ty = Terror;
1709             return mtype;
1710         }
1711 
1712         import dmd.traits : semanticTraits;
1713         Type result;
1714 
1715         if (Expression e = semanticTraits(mtype.exp, sc))
1716         {
1717             switch (e.op)
1718             {
1719             case TOK.dotVariable:
1720                 mtype.sym = (cast(DotVarExp)e).var;
1721                 break;
1722             case TOK.variable:
1723                 mtype.sym = (cast(VarExp)e).var;
1724                 break;
1725             case TOK.function_:
1726                 auto fe = cast(FuncExp)e;
1727                 mtype.sym = fe.td ? fe.td : fe.fd;
1728                 break;
1729             case TOK.dotTemplateDeclaration:
1730                 mtype.sym = (cast(DotTemplateExp)e).td;
1731                 break;
1732             case TOK.dSymbol:
1733                 mtype.sym = (cast(DsymbolExp)e).s;
1734                 break;
1735             case TOK.template_:
1736                 mtype.sym = (cast(TemplateExp)e).td;
1737                 break;
1738             case TOK.scope_:
1739                 mtype.sym = (cast(ScopeExp)e).sds;
1740                 break;
1741             case TOK.tuple:
1742                 TupleExp te = e.toTupleExp();
1743                 Objects* elems = new Objects(te.exps.dim);
1744                 foreach (i; 0 .. elems.dim)
1745                 {
1746                     auto src = (*te.exps)[i];
1747                     switch (src.op)
1748                     {
1749                     case TOK.type:
1750                         (*elems)[i] = (cast(TypeExp)src).type;
1751                         break;
1752                     case TOK.dotType:
1753                         (*elems)[i] = (cast(DotTypeExp)src).sym.isType();
1754                         break;
1755                     case TOK.overloadSet:
1756                         (*elems)[i] = (cast(OverExp)src).type;
1757                         break;
1758                     default:
1759                         if (auto sym = isDsymbol(src))
1760                             (*elems)[i] = sym;
1761                         else
1762                             (*elems)[i] = src;
1763                     }
1764                 }
1765                 TupleDeclaration td = new TupleDeclaration(e.loc, Identifier.generateId("__aliastup"), elems);
1766                 mtype.sym = td;
1767                 break;
1768             case TOK.dotType:
1769                 result = (cast(DotTypeExp)e).sym.isType();
1770                 break;
1771             case TOK.type:
1772                 result = (cast(TypeExp)e).type;
1773                 break;
1774             case TOK.overloadSet:
1775                 result = (cast(OverExp)e).type;
1776                 break;
1777             default:
1778                 break;
1779             }
1780         }
1781 
1782         if (result)
1783             result = result.addMod(mtype.mod);
1784         if (!inAlias && !result)
1785         {
1786             if (!global.errors)
1787                 .error(mtype.loc, "`%s` does not give a valid type", mtype.toChars);
1788             return error();
1789         }
1790 
1791         return result;
1792     }
1793 
1794     Type visitReturn(TypeReturn mtype)
1795     {
1796         //printf("TypeReturn::semantic() %s\n", toChars());
1797         Expression e;
1798         Type t;
1799         Dsymbol s;
1800         mtype.resolve(loc, sc, &e, &t, &s);
1801         if (s && (t = s.getType()) !is null)
1802             t = t.addMod(mtype.mod);
1803         if (!t)
1804         {
1805             .error(loc, "`%s` is used as a type", mtype.toChars());
1806             return error();
1807         }
1808         return t;
1809     }
1810 
1811     Type visitStruct(TypeStruct mtype)
1812     {
1813         //printf("TypeStruct::semantic('%s')\n", mtype.toChars());
1814         if (mtype.deco)
1815             return mtype;
1816 
1817         /* Don't semantic for sym because it should be deferred until
1818          * sizeof needed or its members accessed.
1819          */
1820         // instead, parent should be set correctly
1821         assert(mtype.sym.parent);
1822 
1823         if (mtype.sym.type.ty == Terror)
1824             return error();
1825 
1826         return merge(mtype);
1827     }
1828 
1829     Type visitEnum(TypeEnum mtype)
1830     {
1831         //printf("TypeEnum::semantic() %s\n", toChars());
1832         return mtype.deco ? mtype : merge(mtype);
1833     }
1834 
1835     Type visitClass(TypeClass mtype)
1836     {
1837         //printf("TypeClass::semantic(%s)\n", mtype.toChars());
1838         if (mtype.deco)
1839             return mtype;
1840 
1841         /* Don't semantic for sym because it should be deferred until
1842          * sizeof needed or its members accessed.
1843          */
1844         // instead, parent should be set correctly
1845         assert(mtype.sym.parent);
1846 
1847         if (mtype.sym.type.ty == Terror)
1848             return error();
1849 
1850         return merge(mtype);
1851     }
1852 
1853     Type visitTuple(TypeTuple mtype)
1854     {
1855         //printf("TypeTuple::semantic(this = %p)\n", this);
1856         //printf("TypeTuple::semantic() %p, %s\n", this, toChars());
1857         if (!mtype.deco)
1858             mtype.deco = merge(mtype).deco;
1859 
1860         /* Don't return merge(), because a tuple with one type has the
1861          * same deco as that type.
1862          */
1863         return mtype;
1864     }
1865 
1866     Type visitSlice(TypeSlice mtype)
1867     {
1868         //printf("TypeSlice::semantic() %s\n", toChars());
1869         Type tn = mtype.next.typeSemantic(loc, sc);
1870         //printf("next: %s\n", tn.toChars());
1871 
1872         Type tbn = tn.toBasetype();
1873         if (tbn.ty != Ttuple)
1874         {
1875             .error(loc, "can only slice tuple types, not `%s`", tbn.toChars());
1876             return error();
1877         }
1878         TypeTuple tt = cast(TypeTuple)tbn;
1879 
1880         mtype.lwr = semanticLength(sc, tbn, mtype.lwr);
1881         mtype.upr = semanticLength(sc, tbn, mtype.upr);
1882         mtype.lwr = mtype.lwr.ctfeInterpret();
1883         mtype.upr = mtype.upr.ctfeInterpret();
1884         if (mtype.lwr.op == TOK.error || mtype.upr.op == TOK.error)
1885             return error();
1886 
1887         uinteger_t i1 = mtype.lwr.toUInteger();
1888         uinteger_t i2 = mtype.upr.toUInteger();
1889         if (!(i1 <= i2 && i2 <= tt.arguments.dim))
1890         {
1891             .error(loc, "slice `[%llu..%llu]` is out of range of `[0..%llu]`",
1892                 cast(ulong)i1, cast(ulong)i2, cast(ulong)tt.arguments.dim);
1893             return error();
1894         }
1895 
1896         mtype.next = tn;
1897         mtype.transitive();
1898 
1899         auto args = new Parameters();
1900         args.reserve(cast(size_t)(i2 - i1));
1901         foreach (arg; (*tt.arguments)[cast(size_t)i1 .. cast(size_t)i2])
1902         {
1903             args.push(arg);
1904         }
1905         Type t = new TypeTuple(args);
1906         return t.typeSemantic(loc, sc);
1907     }
1908 
1909     Type visitMixin(TypeMixin mtype)
1910     {
1911         //printf("TypeMixin::semantic() %s\n", toChars());
1912         auto o = mtype.compileTypeMixin(loc, sc);
1913         if (auto t = o.isType())
1914         {
1915             return t.typeSemantic(loc, sc);
1916         }
1917         else if (auto e = o.isExpression())
1918         {
1919             e = e.expressionSemantic(sc);
1920             if (auto et = e.isTypeExp())
1921                 return et.type;
1922             else
1923             {
1924                 if (!global.errors)
1925                     .error(e.loc, "`%s` does not give a valid type", o.toChars);
1926             }
1927         }
1928         return error();
1929     }
1930 
1931     switch (t.ty)
1932     {
1933         default:         return visitType(t);
1934         case Tvector:    return visitVector(cast(TypeVector)t);
1935         case Tsarray:    return visitSArray(cast(TypeSArray)t);
1936         case Tarray:     return visitDArray(cast(TypeDArray)t);
1937         case Taarray:    return visitAArray(cast(TypeAArray)t);
1938         case Tpointer:   return visitPointer(cast(TypePointer)t);
1939         case Treference: return visitReference(cast(TypeReference)t);
1940         case Tfunction:  return visitFunction(cast(TypeFunction)t);
1941         case Tdelegate:  return visitDelegate(cast(TypeDelegate)t);
1942         case Tident:     return visitIdentifier(cast(TypeIdentifier)t);
1943         case Tinstance:  return visitInstance(cast(TypeInstance)t);
1944         case Ttypeof:    return visitTypeof(cast(TypeTypeof)t);
1945         case Ttraits:    return visitTraits(cast(TypeTraits)t);
1946         case Treturn:    return visitReturn(cast(TypeReturn)t);
1947         case Tstruct:    return visitStruct(cast(TypeStruct)t);
1948         case Tenum:      return visitEnum(cast(TypeEnum)t);
1949         case Tclass:     return visitClass(cast(TypeClass)t);
1950         case Ttuple:     return visitTuple (cast(TypeTuple)t);
1951         case Tslice:     return visitSlice(cast(TypeSlice)t);
1952         case Tmixin:     return visitMixin(cast(TypeMixin)t);
1953     }
1954 }
1955 
1956 /******************************************
1957  * Compile the MixinType, returning the type or expression AST.
1958  *
1959  * Doesn't run semantic() on the returned object.
1960  * Params:
1961  *      tm = mixin to compile as a type or expression
1962  *      loc = location for error messages
1963  *      sc = context
1964  * Return:
1965  *      null if error, else RootObject AST as parsed
1966  */
1967 RootObject compileTypeMixin(TypeMixin tm, Loc loc, Scope* sc)
1968 {
1969     OutBuffer buf;
1970     if (expressionsToString(buf, sc, tm.exps))
1971         return null;
1972 
1973     const errors = global.errors;
1974     const len = buf.length;
1975     buf.writeByte(0);
1976     const str = buf.extractSlice()[0 .. len];
1977     scope p = new Parser!ASTCodegen(loc, sc._module, str, false);
1978     p.nextToken();
1979     //printf("p.loc.linnum = %d\n", p.loc.linnum);
1980 
1981     auto o = p.parseTypeOrAssignExp(TOK.endOfFile);
1982     p.reportDiagnostics();
1983     if (errors != global.errors)
1984     {
1985         assert(global.errors != errors); // should have caught all these cases
1986         return null;
1987     }
1988     if (p.token.value != TOK.endOfFile)
1989     {
1990         .error(loc, "incomplete mixin type `%s`", str.ptr);
1991         return null;
1992     }
1993 
1994     Type t = o.isType();
1995     Expression e = t ? t.typeToExpression() : o.isExpression();
1996 
1997     return (!e && t) ? t : e;
1998 }
1999 
2000 
2001 /************************************
2002  * If an identical type to `type` is in `type.stringtable`, return
2003  * the latter one. Otherwise, add it to `type.stringtable`.
2004  * Some types don't get merged and are returned as-is.
2005  * Params:
2006  *      type = Type to check against existing types
2007  * Returns:
2008  *      the type that was merged
2009  */
2010 Type merge(Type type)
2011 {
2012     switch (type.ty)
2013     {
2014         case Terror:
2015         case Ttypeof:
2016         case Tident:
2017         case Tinstance:
2018         case Tmixin:
2019             return type;
2020 
2021         case Tsarray:
2022             // prevents generating the mangle if the array dim is not yet known
2023             if (!(cast(TypeSArray) type).dim.isIntegerExp())
2024                 return type;
2025             goto default;
2026 
2027         case Tenum:
2028             break;
2029 
2030         case Taarray:
2031             if (!(cast(TypeAArray)type).index.merge().deco)
2032                 return type;
2033             goto default;
2034 
2035         default:
2036             if (type.nextOf() && !type.nextOf().deco)
2037                 return type;
2038             break;
2039     }
2040 
2041     //printf("merge(%s)\n", toChars());
2042     if (!type.deco)
2043     {
2044         OutBuffer buf;
2045         buf.reserve(32);
2046 
2047         mangleToBuffer(type, &buf);
2048 
2049         auto sv = type.stringtable.update(buf[]);
2050         if (sv.value)
2051         {
2052             Type t = sv.value;
2053             debug
2054             {
2055                 import core.stdc.stdio;
2056                 if (!t.deco)
2057                     printf("t = %s\n", t.toChars());
2058             }
2059             assert(t.deco);
2060             //printf("old value, deco = '%s' %p\n", t.deco, t.deco);
2061             return t;
2062         }
2063         else
2064         {
2065             Type t = stripDefaultArgs(type);
2066             sv.value = t;
2067             type.deco = t.deco = cast(char*)sv.toDchars();
2068             //printf("new value, deco = '%s' %p\n", t.deco, t.deco);
2069             return t;
2070         }
2071     }
2072     return type;
2073 }
2074 
2075 /***************************************
2076  * Calculate built-in properties which just the type is necessary.
2077  *
2078  * Params:
2079  *  t = the type for which the property is calculated
2080  *  scope_ = the scope from which the property is being accessed. Used for visibility checks only.
2081  *  loc = the location where the property is encountered
2082  *  ident = the identifier of the property
2083  *  flag = if flag & 1, don't report "not a property" error and just return NULL.
2084  * Returns:
2085  *      expression representing the property, or null if not a property and (flag & 1)
2086  */
2087 Expression getProperty(Type t, Scope* scope_, const ref Loc loc, Identifier ident, int flag)
2088 {
2089     Expression visitType(Type mt)
2090     {
2091         Expression e;
2092         static if (LOGDOTEXP)
2093         {
2094             printf("Type::getProperty(type = '%s', ident = '%s')\n", mt.toChars(), ident.toChars());
2095         }
2096         if (ident == Id.__sizeof)
2097         {
2098             d_uns64 sz = mt.size(loc);
2099             if (sz == SIZE_INVALID)
2100                 return new ErrorExp();
2101             e = new IntegerExp(loc, sz, Type.tsize_t);
2102         }
2103         else if (ident == Id.__xalignof)
2104         {
2105             const explicitAlignment = mt.alignment();
2106             const naturalAlignment = mt.alignsize();
2107             const actualAlignment = (explicitAlignment == STRUCTALIGN_DEFAULT ? naturalAlignment : explicitAlignment);
2108             e = new IntegerExp(loc, actualAlignment, Type.tsize_t);
2109         }
2110         else if (ident == Id._init)
2111         {
2112             Type tb = mt.toBasetype();
2113             e = mt.defaultInitLiteral(loc);
2114             if (tb.ty == Tstruct && tb.needsNested())
2115             {
2116                 e.isStructLiteralExp().useStaticInit = true;
2117             }
2118         }
2119         else if (ident == Id._mangleof)
2120         {
2121             if (!mt.deco)
2122             {
2123                 error(loc, "forward reference of type `%s.mangleof`", mt.toChars());
2124                 e = new ErrorExp();
2125             }
2126             else
2127             {
2128                 e = new StringExp(loc, mt.deco.toDString());
2129                 Scope sc;
2130                 e = e.expressionSemantic(&sc);
2131             }
2132         }
2133         else if (ident == Id.stringof)
2134         {
2135             const s = mt.toChars();
2136             e = new StringExp(loc, s.toDString());
2137             Scope sc;
2138             e = e.expressionSemantic(&sc);
2139         }
2140         else if (flag && mt != Type.terror)
2141         {
2142             return null;
2143         }
2144         else
2145         {
2146             Dsymbol s = null;
2147             if (mt.ty == Tstruct || mt.ty == Tclass || mt.ty == Tenum)
2148                 s = mt.toDsymbol(null);
2149             if (s)
2150                 s = s.search_correct(ident);
2151             if (s && !symbolIsVisible(scope_, s))
2152                 s = null;
2153             if (mt != Type.terror)
2154             {
2155                 if (s)
2156                     error(loc, "no property `%s` for type `%s`, did you mean `%s`?", ident.toChars(), mt.toChars(), s.toPrettyChars());
2157                 else
2158                 {
2159                     if (ident == Id.call && mt.ty == Tclass)
2160                         error(loc, "no property `%s` for type `%s`, did you mean `new %s`?", ident.toChars(), mt.toChars(), mt.toPrettyChars());
2161                     else
2162                     {
2163                         if (const n = importHint(ident.toString()))
2164                             error(loc, "no property `%s` for type `%s`, perhaps `import %.*s;` is needed?", ident.toChars(), mt.toChars(), cast(int)n.length, n.ptr);
2165                         else
2166                             error(loc, "no property `%s` for type `%s`", ident.toChars(), mt.toPrettyChars(true));
2167                     }
2168                 }
2169             }
2170             e = new ErrorExp();
2171         }
2172         return e;
2173     }
2174 
2175     Expression visitError(TypeError)
2176     {
2177         return new ErrorExp();
2178     }
2179 
2180     Expression visitBasic(TypeBasic mt)
2181     {
2182         Expression integerValue(dinteger_t i)
2183         {
2184             return new IntegerExp(loc, i, mt);
2185         }
2186 
2187         Expression intValue(dinteger_t i)
2188         {
2189             return new IntegerExp(loc, i, Type.tint32);
2190         }
2191 
2192         Expression floatValue(real_t r)
2193         {
2194             if (mt.isreal() || mt.isimaginary())
2195                 return new RealExp(loc, r, mt);
2196             else
2197             {
2198                 return new ComplexExp(loc, complex_t(r, r), mt);
2199             }
2200         }
2201 
2202         //printf("TypeBasic::getProperty('%s')\n", ident.toChars());
2203         if (ident == Id.max)
2204         {
2205             switch (mt.ty)
2206             {
2207             case Tint8:        return integerValue(byte.max);
2208             case Tuns8:        return integerValue(ubyte.max);
2209             case Tint16:       return integerValue(short.max);
2210             case Tuns16:       return integerValue(ushort.max);
2211             case Tint32:       return integerValue(int.max);
2212             case Tuns32:       return integerValue(uint.max);
2213             case Tint64:       return integerValue(long.max);
2214             case Tuns64:       return integerValue(ulong.max);
2215             case Tbool:        return integerValue(bool.max);
2216             case Tchar:        return integerValue(char.max);
2217             case Twchar:       return integerValue(wchar.max);
2218             case Tdchar:       return integerValue(dchar.max);
2219             case Tcomplex32:
2220             case Timaginary32:
2221             case Tfloat32:     return floatValue(target.FloatProperties.max);
2222             case Tcomplex64:
2223             case Timaginary64:
2224             case Tfloat64:     return floatValue(target.DoubleProperties.max);
2225             case Tcomplex80:
2226             case Timaginary80:
2227             case Tfloat80:     return floatValue(target.RealProperties.max);
2228             default:           break;
2229             }
2230         }
2231         else if (ident == Id.min)
2232         {
2233             switch (mt.ty)
2234             {
2235             case Tint8:        return integerValue(byte.min);
2236             case Tuns8:
2237             case Tuns16:
2238             case Tuns32:
2239             case Tuns64:
2240             case Tbool:
2241             case Tchar:
2242             case Twchar:
2243             case Tdchar:       return integerValue(0);
2244             case Tint16:       return integerValue(short.min);
2245             case Tint32:       return integerValue(int.min);
2246             case Tint64:       return integerValue(long.min);
2247             default:           break;
2248             }
2249         }
2250         else if (ident == Id.min_normal)
2251         {
2252             switch (mt.ty)
2253             {
2254             case Tcomplex32:
2255             case Timaginary32:
2256             case Tfloat32:     return floatValue(target.FloatProperties.min_normal);
2257             case Tcomplex64:
2258             case Timaginary64:
2259             case Tfloat64:     return floatValue(target.DoubleProperties.min_normal);
2260             case Tcomplex80:
2261             case Timaginary80:
2262             case Tfloat80:     return floatValue(target.RealProperties.min_normal);
2263             default:           break;
2264             }
2265         }
2266         else if (ident == Id.nan)
2267         {
2268             switch (mt.ty)
2269             {
2270             case Tcomplex32:
2271             case Tcomplex64:
2272             case Tcomplex80:
2273             case Timaginary32:
2274             case Timaginary64:
2275             case Timaginary80:
2276             case Tfloat32:
2277             case Tfloat64:
2278             case Tfloat80:     return floatValue(target.RealProperties.nan);
2279             default:           break;
2280             }
2281         }
2282         else if (ident == Id.infinity)
2283         {
2284             switch (mt.ty)
2285             {
2286             case Tcomplex32:
2287             case Tcomplex64:
2288             case Tcomplex80:
2289             case Timaginary32:
2290             case Timaginary64:
2291             case Timaginary80:
2292             case Tfloat32:
2293             case Tfloat64:
2294             case Tfloat80:     return floatValue(target.RealProperties.infinity);
2295             default:           break;
2296             }
2297         }
2298         else if (ident == Id.dig)
2299         {
2300             switch (mt.ty)
2301             {
2302             case Tcomplex32:
2303             case Timaginary32:
2304             case Tfloat32:     return intValue(target.FloatProperties.dig);
2305             case Tcomplex64:
2306             case Timaginary64:
2307             case Tfloat64:     return intValue(target.DoubleProperties.dig);
2308             case Tcomplex80:
2309             case Timaginary80:
2310             case Tfloat80:     return intValue(target.RealProperties.dig);
2311             default:           break;
2312             }
2313         }
2314         else if (ident == Id.epsilon)
2315         {
2316             switch (mt.ty)
2317             {
2318             case Tcomplex32:
2319             case Timaginary32:
2320             case Tfloat32:     return floatValue(target.FloatProperties.epsilon);
2321             case Tcomplex64:
2322             case Timaginary64:
2323             case Tfloat64:     return floatValue(target.DoubleProperties.epsilon);
2324             case Tcomplex80:
2325             case Timaginary80:
2326             case Tfloat80:     return floatValue(target.RealProperties.epsilon);
2327             default:           break;
2328             }
2329         }
2330         else if (ident == Id.mant_dig)
2331         {
2332             switch (mt.ty)
2333             {
2334             case Tcomplex32:
2335             case Timaginary32:
2336             case Tfloat32:     return intValue(target.FloatProperties.mant_dig);
2337             case Tcomplex64:
2338             case Timaginary64:
2339             case Tfloat64:     return intValue(target.DoubleProperties.mant_dig);
2340             case Tcomplex80:
2341             case Timaginary80:
2342             case Tfloat80:     return intValue(target.RealProperties.mant_dig);
2343             default:           break;
2344             }
2345         }
2346         else if (ident == Id.max_10_exp)
2347         {
2348             switch (mt.ty)
2349             {
2350             case Tcomplex32:
2351             case Timaginary32:
2352             case Tfloat32:     return intValue(target.FloatProperties.max_10_exp);
2353             case Tcomplex64:
2354             case Timaginary64:
2355             case Tfloat64:     return intValue(target.DoubleProperties.max_10_exp);
2356             case Tcomplex80:
2357             case Timaginary80:
2358             case Tfloat80:     return intValue(target.RealProperties.max_10_exp);
2359             default:           break;
2360             }
2361         }
2362         else if (ident == Id.max_exp)
2363         {
2364             switch (mt.ty)
2365             {
2366             case Tcomplex32:
2367             case Timaginary32:
2368             case Tfloat32:     return intValue(target.FloatProperties.max_exp);
2369             case Tcomplex64:
2370             case Timaginary64:
2371             case Tfloat64:     return intValue(target.DoubleProperties.max_exp);
2372             case Tcomplex80:
2373             case Timaginary80:
2374             case Tfloat80:     return intValue(target.RealProperties.max_exp);
2375             default:           break;
2376             }
2377         }
2378         else if (ident == Id.min_10_exp)
2379         {
2380             switch (mt.ty)
2381             {
2382             case Tcomplex32:
2383             case Timaginary32:
2384             case Tfloat32:     return intValue(target.FloatProperties.min_10_exp);
2385             case Tcomplex64:
2386             case Timaginary64:
2387             case Tfloat64:     return intValue(target.DoubleProperties.min_10_exp);
2388             case Tcomplex80:
2389             case Timaginary80:
2390             case Tfloat80:     return intValue(target.RealProperties.min_10_exp);
2391             default:           break;
2392             }
2393         }
2394         else if (ident == Id.min_exp)
2395         {
2396             switch (mt.ty)
2397             {
2398             case Tcomplex32:
2399             case Timaginary32:
2400             case Tfloat32:     return intValue(target.FloatProperties.min_exp);
2401             case Tcomplex64:
2402             case Timaginary64:
2403             case Tfloat64:     return intValue(target.DoubleProperties.min_exp);
2404             case Tcomplex80:
2405             case Timaginary80:
2406             case Tfloat80:     return intValue(target.RealProperties.min_exp);
2407             default:           break;
2408             }
2409         }
2410         return visitType(mt);
2411     }
2412 
2413     Expression visitVector(TypeVector mt)
2414     {
2415         return visitType(mt);
2416     }
2417 
2418     Expression visitEnum(TypeEnum mt)
2419     {
2420         Expression e;
2421         if (ident == Id.max || ident == Id.min)
2422         {
2423             return mt.sym.getMaxMinValue(loc, ident);
2424         }
2425         else if (ident == Id._init)
2426         {
2427             e = mt.defaultInitLiteral(loc);
2428         }
2429         else if (ident == Id.stringof)
2430         {
2431             e = new StringExp(loc, mt.toString());
2432             Scope sc;
2433             e = e.expressionSemantic(&sc);
2434         }
2435         else if (ident == Id._mangleof)
2436         {
2437             e = visitType(mt);
2438         }
2439         else
2440         {
2441             e = mt.toBasetype().getProperty(scope_, loc, ident, flag);
2442         }
2443         return e;
2444     }
2445 
2446     Expression visitTuple(TypeTuple mt)
2447     {
2448         Expression e;
2449         static if (LOGDOTEXP)
2450         {
2451             printf("TypeTuple::getProperty(type = '%s', ident = '%s')\n", mt.toChars(), ident.toChars());
2452         }
2453         if (ident == Id.length)
2454         {
2455             e = new IntegerExp(loc, mt.arguments.dim, Type.tsize_t);
2456         }
2457         else if (ident == Id._init)
2458         {
2459             e = mt.defaultInitLiteral(loc);
2460         }
2461         else if (flag)
2462         {
2463             e = null;
2464         }
2465         else
2466         {
2467             error(loc, "no property `%s` for tuple `%s`", ident.toChars(), mt.toChars());
2468             e = new ErrorExp();
2469         }
2470         return e;
2471     }
2472 
2473     switch (t.ty)
2474     {
2475         default:        return t.isTypeBasic() ?
2476                                 visitBasic(cast(TypeBasic)t) :
2477                                 visitType(t);
2478 
2479         case Terror:    return visitError (cast(TypeError)t);
2480         case Tvector:   return visitVector(cast(TypeVector)t);
2481         case Tenum:     return visitEnum  (cast(TypeEnum)t);
2482         case Ttuple:    return visitTuple (cast(TypeTuple)t);
2483     }
2484 }
2485 
2486 /***************************************
2487  * Normalize `e` as the result of resolve() process.
2488  */
2489 private void resolveExp(Expression e, Type *pt, Expression *pe, Dsymbol* ps)
2490 {
2491     *pt = null;
2492     *pe = null;
2493     *ps = null;
2494 
2495     Dsymbol s;
2496     switch (e.op)
2497     {
2498         case TOK.error:
2499             *pt = Type.terror;
2500             return;
2501 
2502         case TOK.type:
2503             *pt = e.type;
2504             return;
2505 
2506         case TOK.variable:
2507             s = (cast(VarExp)e).var;
2508             if (s.isVarDeclaration())
2509                 goto default;
2510             //if (s.isOverDeclaration())
2511             //    todo;
2512             break;
2513 
2514         case TOK.template_:
2515             // TemplateDeclaration
2516             s = (cast(TemplateExp)e).td;
2517             break;
2518 
2519         case TOK.scope_:
2520             s = (cast(ScopeExp)e).sds;
2521             // TemplateDeclaration, TemplateInstance, Import, Package, Module
2522             break;
2523 
2524         case TOK.function_:
2525             s = getDsymbol(e);
2526             break;
2527 
2528         case TOK.dotTemplateDeclaration:
2529             s = (cast(DotTemplateExp)e).td;
2530             break;
2531 
2532         //case TOK.this_:
2533         //case TOK.super_:
2534 
2535         //case TOK.tuple:
2536 
2537         //case TOK.overloadSet:
2538 
2539         //case TOK.dotVariable:
2540         //case TOK.dotTemplateInstance:
2541         //case TOK.dotType:
2542         //case TOK.dotIdentifier:
2543 
2544         default:
2545             *pe = e;
2546             return;
2547     }
2548 
2549     *ps = s;
2550 }
2551 
2552 /************************************
2553  * Resolve type 'mt' to either type, symbol, or expression.
2554  * If errors happened, resolved to Type.terror.
2555  *
2556  * Params:
2557  *  mt = type to be resolved
2558  *  loc = the location where the type is encountered
2559  *  sc = the scope of the type
2560  *  pe = is set if t is an expression
2561  *  pt = is set if t is a type
2562  *  ps = is set if t is a symbol
2563  *  intypeid = true if in type id
2564  */
2565 void resolve(Type mt, const ref Loc loc, Scope* sc, Expression* pe, Type* pt, Dsymbol* ps, bool intypeid = false)
2566 {
2567     void returnExp(Expression e)
2568     {
2569         *pt = null;
2570         *pe = e;
2571         *ps = null;
2572     }
2573 
2574     void returnType(Type t)
2575     {
2576         *pt = t;
2577         *pe = null;
2578         *ps = null;
2579     }
2580 
2581     void returnSymbol(Dsymbol s)
2582     {
2583         *pt = null;
2584         *pe = null;
2585         *ps = s;
2586     }
2587 
2588     void returnError()
2589     {
2590         returnType(Type.terror);
2591     }
2592 
2593     void visitType(Type mt)
2594     {
2595         //printf("Type::resolve() %s, %d\n", mt.toChars(), mt.ty);
2596         Type t = typeSemantic(mt, loc, sc);
2597         assert(t);
2598         returnType(t);
2599     }
2600 
2601     void visitSArray(TypeSArray mt)
2602     {
2603         //printf("TypeSArray::resolve() %s\n", mt.toChars());
2604         mt.next.resolve(loc, sc, pe, pt, ps, intypeid);
2605         //printf("s = %p, e = %p, t = %p\n", *ps, *pe, *pt);
2606         if (*pe)
2607         {
2608             // It's really an index expression
2609             if (Dsymbol s = getDsymbol(*pe))
2610                 *pe = new DsymbolExp(loc, s);
2611             returnExp(new ArrayExp(loc, *pe, mt.dim));
2612         }
2613         else if (*ps)
2614         {
2615             Dsymbol s = *ps;
2616             if (auto tup = s.isTupleDeclaration())
2617             {
2618                 mt.dim = semanticLength(sc, tup, mt.dim);
2619                 mt.dim = mt.dim.ctfeInterpret();
2620                 if (mt.dim.op == TOK.error)
2621                     return returnError();
2622 
2623                 const d = mt.dim.toUInteger();
2624                 if (d >= tup.objects.dim)
2625                 {
2626                     error(loc, "tuple index `%llu` exceeds length %u", d, tup.objects.dim);
2627                     return returnError();
2628                 }
2629 
2630                 RootObject o = (*tup.objects)[cast(size_t)d];
2631                 if (o.dyncast() == DYNCAST.dsymbol)
2632                 {
2633                     return returnSymbol(cast(Dsymbol)o);
2634                 }
2635                 if (o.dyncast() == DYNCAST.expression)
2636                 {
2637                     Expression e = cast(Expression)o;
2638                     if (e.op == TOK.dSymbol)
2639                         return returnSymbol((cast(DsymbolExp)e).s);
2640                     else
2641                         return returnExp(e);
2642                 }
2643                 if (o.dyncast() == DYNCAST.type)
2644                 {
2645                     return returnType((cast(Type)o).addMod(mt.mod));
2646                 }
2647 
2648                 /* Create a new TupleDeclaration which
2649                  * is a slice [d..d+1] out of the old one.
2650                  * Do it this way because TemplateInstance::semanticTiargs()
2651                  * can handle unresolved Objects this way.
2652                  */
2653                 auto objects = new Objects(1);
2654                 (*objects)[0] = o;
2655                 return returnSymbol(new TupleDeclaration(loc, tup.ident, objects));
2656             }
2657             else
2658                 return visitType(mt);
2659         }
2660         else
2661         {
2662             if ((*pt).ty != Terror)
2663                 mt.next = *pt; // prevent re-running semantic() on 'next'
2664             visitType(mt);
2665         }
2666 
2667     }
2668 
2669     void visitDArray(TypeDArray mt)
2670     {
2671         //printf("TypeDArray::resolve() %s\n", mt.toChars());
2672         mt.next.resolve(loc, sc, pe, pt, ps, intypeid);
2673         //printf("s = %p, e = %p, t = %p\n", *ps, *pe, *pt);
2674         if (*pe)
2675         {
2676             // It's really a slice expression
2677             if (Dsymbol s = getDsymbol(*pe))
2678                 *pe = new DsymbolExp(loc, s);
2679             returnExp(new ArrayExp(loc, *pe));
2680         }
2681         else if (*ps)
2682         {
2683             if (auto tup = (*ps).isTupleDeclaration())
2684             {
2685                 // keep *ps
2686             }
2687             else
2688                 visitType(mt);
2689         }
2690         else
2691         {
2692             if ((*pt).ty != Terror)
2693                 mt.next = *pt; // prevent re-running semantic() on 'next'
2694             visitType(mt);
2695         }
2696     }
2697 
2698     void visitAArray(TypeAArray mt)
2699     {
2700         //printf("TypeAArray::resolve() %s\n", mt.toChars());
2701         // Deal with the case where we thought the index was a type, but
2702         // in reality it was an expression.
2703         if (mt.index.ty == Tident || mt.index.ty == Tinstance || mt.index.ty == Tsarray)
2704         {
2705             Expression e;
2706             Type t;
2707             Dsymbol s;
2708             mt.index.resolve(loc, sc, &e, &t, &s, intypeid);
2709             if (e)
2710             {
2711                 // It was an expression -
2712                 // Rewrite as a static array
2713                 auto tsa = new TypeSArray(mt.next, e);
2714                 tsa.mod = mt.mod; // just copy mod field so tsa's semantic is not yet done
2715                 return tsa.resolve(loc, sc, pe, pt, ps, intypeid);
2716             }
2717             else if (t)
2718                 mt.index = t;
2719             else
2720                 .error(loc, "index is not a type or an expression");
2721         }
2722         visitType(mt);
2723     }
2724 
2725     /*************************************
2726      * Takes an array of Identifiers and figures out if
2727      * it represents a Type or an Expression.
2728      * Output:
2729      *      if expression, *pe is set
2730      *      if type, *pt is set
2731      */
2732     void visitIdentifier(TypeIdentifier mt)
2733     {
2734         //printf("TypeIdentifier::resolve(sc = %p, idents = '%s')\n", sc, mt.toChars());
2735         if ((mt.ident.equals(Id._super) || mt.ident.equals(Id.This)) && !hasThis(sc))
2736         {
2737             // @@@DEPRECATED_v2.091@@@.
2738             // Made an error in 2.086.
2739             // Eligible for removal in 2.091.
2740             if (mt.ident.equals(Id._super))
2741             {
2742                 error(mt.loc, "Using `super` as a type is obsolete. Use `typeof(super)` instead");
2743             }
2744              // @@@DEPRECATED_v2.091@@@.
2745             // Made an error in 2.086.
2746             // Eligible for removal in 2.091.
2747             if (mt.ident.equals(Id.This))
2748             {
2749                 error(mt.loc, "Using `this` as a type is obsolete. Use `typeof(this)` instead");
2750             }
2751             if (AggregateDeclaration ad = sc.getStructClassScope())
2752             {
2753                 if (ClassDeclaration cd = ad.isClassDeclaration())
2754                 {
2755                     if (mt.ident.equals(Id.This))
2756                         mt.ident = cd.ident;
2757                     else if (cd.baseClass && mt.ident.equals(Id._super))
2758                         mt.ident = cd.baseClass.ident;
2759                 }
2760                 else
2761                 {
2762                     StructDeclaration sd = ad.isStructDeclaration();
2763                     if (sd && mt.ident.equals(Id.This))
2764                         mt.ident = sd.ident;
2765                 }
2766             }
2767         }
2768         if (mt.ident == Id.ctfe)
2769         {
2770             error(loc, "variable `__ctfe` cannot be read at compile time");
2771             return returnError();
2772         }
2773 
2774         Dsymbol scopesym;
2775         Dsymbol s = sc.search(loc, mt.ident, &scopesym);
2776         /*
2777          * https://issues.dlang.org/show_bug.cgi?id=1170
2778          * https://issues.dlang.org/show_bug.cgi?id=10739
2779          *
2780          * If a symbol is not found, it might be declared in
2781          * a mixin-ed string or a mixin-ed template, so before
2782          * issuing an error semantically analyze all string/template
2783          * mixins that are members of the current ScopeDsymbol.
2784          */
2785         if (!s && sc.enclosing)
2786         {
2787             ScopeDsymbol sds = sc.enclosing.scopesym;
2788             if (sds && sds.members)
2789             {
2790                 void semanticOnMixin(Dsymbol member)
2791                 {
2792                     if (auto compileDecl = member.isCompileDeclaration())
2793                         compileDecl.dsymbolSemantic(sc);
2794                     else if (auto mixinTempl = member.isTemplateMixin())
2795                         mixinTempl.dsymbolSemantic(sc);
2796                 }
2797                 sds.members.foreachDsymbol( s => semanticOnMixin(s) );
2798                 s = sc.search(loc, mt.ident, &scopesym);
2799             }
2800         }
2801 
2802         if (s)
2803         {
2804             // https://issues.dlang.org/show_bug.cgi?id=16042
2805             // If `f` is really a function template, then replace `f`
2806             // with the function template declaration.
2807             if (auto f = s.isFuncDeclaration())
2808             {
2809                 if (auto td = getFuncTemplateDecl(f))
2810                 {
2811                     // If not at the beginning of the overloaded list of
2812                     // `TemplateDeclaration`s, then get the beginning
2813                     if (td.overroot)
2814                         td = td.overroot;
2815                     s = td;
2816                 }
2817             }
2818         }
2819 
2820         mt.resolveHelper(loc, sc, s, scopesym, pe, pt, ps, intypeid);
2821         if (*pt)
2822             (*pt) = (*pt).addMod(mt.mod);
2823     }
2824 
2825     void visitInstance(TypeInstance mt)
2826     {
2827         // Note close similarity to TypeIdentifier::resolve()
2828 
2829         //printf("TypeInstance::resolve(sc = %p, tempinst = '%s')\n", sc, mt.tempinst.toChars());
2830         mt.tempinst.dsymbolSemantic(sc);
2831         if (!global.gag && mt.tempinst.errors)
2832             return returnError();
2833 
2834         mt.resolveHelper(loc, sc, mt.tempinst, null, pe, pt, ps, intypeid);
2835         if (*pt)
2836             *pt = (*pt).addMod(mt.mod);
2837         //if (*pt) printf("*pt = %d '%s'\n", (*pt).ty, (*pt).toChars());
2838     }
2839 
2840     void visitTypeof(TypeTypeof mt)
2841     {
2842         //printf("TypeTypeof::resolve(this = %p, sc = %p, idents = '%s')\n", mt, sc, mt.toChars());
2843         //static int nest; if (++nest == 50) *(char*)0=0;
2844         if (sc is null)
2845         {
2846             error(loc, "Invalid scope.");
2847             return returnError();
2848         }
2849         if (mt.inuse)
2850         {
2851             mt.inuse = 2;
2852             error(loc, "circular `typeof` definition");
2853         Lerr:
2854             mt.inuse--;
2855             return returnError();
2856         }
2857         mt.inuse++;
2858 
2859         /* Currently we cannot evaluate 'exp' in speculative context, because
2860          * the type implementation may leak to the final execution. Consider:
2861          *
2862          * struct S(T) {
2863          *   string toString() const { return "x"; }
2864          * }
2865          * void main() {
2866          *   alias X = typeof(S!int());
2867          *   assert(typeid(X).toString() == "x");
2868          * }
2869          */
2870         Scope* sc2 = sc.push();
2871         sc2.intypeof = 1;
2872         auto exp2 = mt.exp.expressionSemantic(sc2);
2873         exp2 = resolvePropertiesOnly(sc2, exp2);
2874         sc2.pop();
2875 
2876         if (exp2.op == TOK.error)
2877         {
2878             if (!global.gag)
2879                 mt.exp = exp2;
2880             goto Lerr;
2881         }
2882         mt.exp = exp2;
2883 
2884         if (mt.exp.op == TOK.type ||
2885             mt.exp.op == TOK.scope_)
2886         {
2887             if (mt.exp.checkType())
2888                 goto Lerr;
2889 
2890             /* Today, 'typeof(func)' returns void if func is a
2891              * function template (TemplateExp), or
2892              * template lambda (FuncExp).
2893              * It's actually used in Phobos as an idiom, to branch code for
2894              * template functions.
2895              */
2896         }
2897         if (auto f = mt.exp.op == TOK.variable    ? (cast(   VarExp)mt.exp).var.isFuncDeclaration()
2898                    : mt.exp.op == TOK.dotVariable ? (cast(DotVarExp)mt.exp).var.isFuncDeclaration() : null)
2899         {
2900             if (f.checkForwardRef(loc))
2901                 goto Lerr;
2902         }
2903         if (auto f = isFuncAddress(mt.exp))
2904         {
2905             if (f.checkForwardRef(loc))
2906                 goto Lerr;
2907         }
2908 
2909         Type t = mt.exp.type;
2910         if (!t)
2911         {
2912             error(loc, "expression `%s` has no type", mt.exp.toChars());
2913             goto Lerr;
2914         }
2915         if (t.ty == Ttypeof)
2916         {
2917             error(loc, "forward reference to `%s`", mt.toChars());
2918             goto Lerr;
2919         }
2920         if (mt.idents.dim == 0)
2921         {
2922             returnType(t.addMod(mt.mod));
2923         }
2924         else
2925         {
2926             if (Dsymbol s = t.toDsymbol(sc))
2927                 mt.resolveHelper(loc, sc, s, null, pe, pt, ps, intypeid);
2928             else
2929             {
2930                 auto e = typeToExpressionHelper(mt, new TypeExp(loc, t));
2931                 e = e.expressionSemantic(sc);
2932                 resolveExp(e, pt, pe, ps);
2933             }
2934             if (*pt)
2935                 (*pt) = (*pt).addMod(mt.mod);
2936         }
2937         mt.inuse--;
2938     }
2939 
2940     void visitReturn(TypeReturn mt)
2941     {
2942         //printf("TypeReturn::resolve(sc = %p, idents = '%s')\n", sc, mt.toChars());
2943         Type t;
2944         {
2945             FuncDeclaration func = sc.func;
2946             if (!func)
2947             {
2948                 error(loc, "`typeof(return)` must be inside function");
2949                 return returnError();
2950             }
2951             if (func.fes)
2952                 func = func.fes.func;
2953             t = func.type.nextOf();
2954             if (!t)
2955             {
2956                 error(loc, "cannot use `typeof(return)` inside function `%s` with inferred return type", sc.func.toChars());
2957                 return returnError();
2958             }
2959         }
2960         if (mt.idents.dim == 0)
2961         {
2962             return returnType(t.addMod(mt.mod));
2963         }
2964         else
2965         {
2966             if (Dsymbol s = t.toDsymbol(sc))
2967                 mt.resolveHelper(loc, sc, s, null, pe, pt, ps, intypeid);
2968             else
2969             {
2970                 auto e = typeToExpressionHelper(mt, new TypeExp(loc, t));
2971                 e = e.expressionSemantic(sc);
2972                 resolveExp(e, pt, pe, ps);
2973             }
2974             if (*pt)
2975                 (*pt) = (*pt).addMod(mt.mod);
2976         }
2977     }
2978 
2979     void visitSlice(TypeSlice mt)
2980     {
2981         mt.next.resolve(loc, sc, pe, pt, ps, intypeid);
2982         if (*pe)
2983         {
2984             // It's really a slice expression
2985             if (Dsymbol s = getDsymbol(*pe))
2986                 *pe = new DsymbolExp(loc, s);
2987             return returnExp(new ArrayExp(loc, *pe, new IntervalExp(loc, mt.lwr, mt.upr)));
2988         }
2989         else if (*ps)
2990         {
2991             Dsymbol s = *ps;
2992             TupleDeclaration td = s.isTupleDeclaration();
2993             if (td)
2994             {
2995                 /* It's a slice of a TupleDeclaration
2996                  */
2997                 ScopeDsymbol sym = new ArrayScopeSymbol(sc, td);
2998                 sym.parent = sc.scopesym;
2999                 sc = sc.push(sym);
3000                 sc = sc.startCTFE();
3001                 mt.lwr = mt.lwr.expressionSemantic(sc);
3002                 mt.upr = mt.upr.expressionSemantic(sc);
3003                 sc = sc.endCTFE();
3004                 sc = sc.pop();
3005 
3006                 mt.lwr = mt.lwr.ctfeInterpret();
3007                 mt.upr = mt.upr.ctfeInterpret();
3008                 const i1 = mt.lwr.toUInteger();
3009                 const i2 = mt.upr.toUInteger();
3010                 if (!(i1 <= i2 && i2 <= td.objects.dim))
3011                 {
3012                     error(loc, "slice `[%llu..%llu]` is out of range of [0..%u]", i1, i2, td.objects.dim);
3013                     return returnError();
3014                 }
3015 
3016                 if (i1 == 0 && i2 == td.objects.dim)
3017                 {
3018                     return returnSymbol(td);
3019                 }
3020 
3021                 /* Create a new TupleDeclaration which
3022                  * is a slice [i1..i2] out of the old one.
3023                  */
3024                 auto objects = new Objects(cast(size_t)(i2 - i1));
3025                 for (size_t i = 0; i < objects.dim; i++)
3026                 {
3027                     (*objects)[i] = (*td.objects)[cast(size_t)i1 + i];
3028                 }
3029 
3030                 return returnSymbol(new TupleDeclaration(loc, td.ident, objects));
3031             }
3032             else
3033                 visitType(mt);
3034         }
3035         else
3036         {
3037             if ((*pt).ty != Terror)
3038                 mt.next = *pt; // prevent re-running semantic() on 'next'
3039             visitType(mt);
3040         }
3041     }
3042 
3043     void visitMixin(TypeMixin mt)
3044     {
3045         auto o = mt.compileTypeMixin(loc, sc);
3046 
3047         if (auto t = o.isType())
3048         {
3049             resolve(t, loc, sc, pe, pt, ps, intypeid);
3050         }
3051         else if (auto e = o.isExpression())
3052         {
3053             e = e.expressionSemantic(sc);
3054             if (auto et = e.isTypeExp())
3055                 return returnType(et.type);
3056             else
3057                 returnExp(e);
3058         }
3059         else
3060             returnError();
3061     }
3062 
3063     void visitTraits(TypeTraits tt)
3064     {
3065         if (Type t = typeSemantic(tt, loc, sc))
3066             returnType(t);
3067         else if (tt.sym)
3068             returnSymbol(tt.sym);
3069         else
3070             return returnError();
3071     }
3072 
3073     switch (mt.ty)
3074     {
3075         default:        visitType      (mt);                     break;
3076         case Tsarray:   visitSArray    (cast(TypeSArray)mt);     break;
3077         case Tarray:    visitDArray    (cast(TypeDArray)mt);     break;
3078         case Taarray:   visitAArray    (cast(TypeAArray)mt);     break;
3079         case Tident:    visitIdentifier(cast(TypeIdentifier)mt); break;
3080         case Tinstance: visitInstance  (cast(TypeInstance)mt);   break;
3081         case Ttypeof:   visitTypeof    (cast(TypeTypeof)mt);     break;
3082         case Treturn:   visitReturn    (cast(TypeReturn)mt);     break;
3083         case Tslice:    visitSlice     (cast(TypeSlice)mt);      break;
3084         case Tmixin:    visitMixin     (cast(TypeMixin)mt);      break;
3085         case Ttraits:   visitTraits    (cast(TypeTraits)mt);     break;
3086     }
3087 }
3088 
3089 /************************
3090  * Access the members of the object e. This type is same as e.type.
3091  * Params:
3092  *  mt = type for which the dot expression is used
3093  *  sc = instantiating scope
3094  *  e = expression to convert
3095  *  ident = identifier being used
3096  *  flag = DotExpFlag bit flags
3097  *
3098  * Returns:
3099  *  resulting expression with e.ident resolved
3100  */
3101 Expression dotExp(Type mt, Scope* sc, Expression e, Identifier ident, int flag)
3102 {
3103     Expression visitType(Type mt)
3104     {
3105         VarDeclaration v = null;
3106         static if (LOGDOTEXP)
3107         {
3108             printf("Type::dotExp(e = '%s', ident = '%s')\n", e.toChars(), ident.toChars());
3109         }
3110         Expression ex = e.lastComma();
3111         if (ex.op == TOK.dotVariable)
3112         {
3113             DotVarExp dv = cast(DotVarExp)ex;
3114             v = dv.var.isVarDeclaration();
3115         }
3116         else if (ex.op == TOK.variable)
3117         {
3118             VarExp ve = cast(VarExp)ex;
3119             v = ve.var.isVarDeclaration();
3120         }
3121         if (v)
3122         {
3123             if (ident == Id.offsetof)
3124             {
3125                 if (v.isField())
3126                 {
3127                     auto ad = v.toParent().isAggregateDeclaration();
3128                     objc.checkOffsetof(e, ad);
3129                     ad.size(e.loc);
3130                     if (ad.sizeok != Sizeok.done)
3131                         return new ErrorExp();
3132                     return new IntegerExp(e.loc, v.offset, Type.tsize_t);
3133                 }
3134             }
3135             else if (ident == Id._init)
3136             {
3137                 Type tb = mt.toBasetype();
3138                 e = mt.defaultInitLiteral(e.loc);
3139                 if (tb.ty == Tstruct && tb.needsNested())
3140                 {
3141                     e.isStructLiteralExp().useStaticInit = true;
3142                 }
3143                 goto Lreturn;
3144             }
3145         }
3146         if (ident == Id.stringof)
3147         {
3148             /* https://issues.dlang.org/show_bug.cgi?id=3796
3149              * this should demangle e.type.deco rather than
3150              * pretty-printing the type.
3151              */
3152             e = new StringExp(e.loc, e.toString());
3153         }
3154         else
3155             e = mt.getProperty(sc, e.loc, ident, flag & DotExpFlag.gag);
3156 
3157     Lreturn:
3158         if (e)
3159             e = e.expressionSemantic(sc);
3160         return e;
3161     }
3162 
3163     Expression visitError(TypeError)
3164     {
3165         return new ErrorExp();
3166     }
3167 
3168     Expression visitBasic(TypeBasic mt)
3169     {
3170         static if (LOGDOTEXP)
3171         {
3172             printf("TypeBasic::dotExp(e = '%s', ident = '%s')\n", e.toChars(), ident.toChars());
3173         }
3174         Type t;
3175         if (ident == Id.re)
3176         {
3177             switch (mt.ty)
3178             {
3179             case Tcomplex32:
3180                 t = mt.tfloat32;
3181                 goto L1;
3182 
3183             case Tcomplex64:
3184                 t = mt.tfloat64;
3185                 goto L1;
3186 
3187             case Tcomplex80:
3188                 t = mt.tfloat80;
3189                 goto L1;
3190             L1:
3191                 e = e.castTo(sc, t);
3192                 break;
3193 
3194             case Tfloat32:
3195             case Tfloat64:
3196             case Tfloat80:
3197                 break;
3198 
3199             case Timaginary32:
3200                 t = mt.tfloat32;
3201                 goto L2;
3202 
3203             case Timaginary64:
3204                 t = mt.tfloat64;
3205                 goto L2;
3206 
3207             case Timaginary80:
3208                 t = mt.tfloat80;
3209                 goto L2;
3210             L2:
3211                 e = new RealExp(e.loc, CTFloat.zero, t);
3212                 break;
3213 
3214             default:
3215                 e = mt.Type.getProperty(sc, e.loc, ident, flag);
3216                 break;
3217             }
3218         }
3219         else if (ident == Id.im)
3220         {
3221             Type t2;
3222             switch (mt.ty)
3223             {
3224             case Tcomplex32:
3225                 t = mt.timaginary32;
3226                 t2 = mt.tfloat32;
3227                 goto L3;
3228 
3229             case Tcomplex64:
3230                 t = mt.timaginary64;
3231                 t2 = mt.tfloat64;
3232                 goto L3;
3233 
3234             case Tcomplex80:
3235                 t = mt.timaginary80;
3236                 t2 = mt.tfloat80;
3237                 goto L3;
3238             L3:
3239                 e = e.castTo(sc, t);
3240                 e.type = t2;
3241                 break;
3242 
3243             case Timaginary32:
3244                 t = mt.tfloat32;
3245                 goto L4;
3246 
3247             case Timaginary64:
3248                 t = mt.tfloat64;
3249                 goto L4;
3250 
3251             case Timaginary80:
3252                 t = mt.tfloat80;
3253                 goto L4;
3254             L4:
3255                 e = e.copy();
3256                 e.type = t;
3257                 break;
3258 
3259             case Tfloat32:
3260             case Tfloat64:
3261             case Tfloat80:
3262                 e = new RealExp(e.loc, CTFloat.zero, mt);
3263                 break;
3264 
3265             default:
3266                 e = mt.Type.getProperty(sc, e.loc, ident, flag);
3267                 break;
3268             }
3269         }
3270         else
3271         {
3272             return visitType(mt);
3273         }
3274         if (!(flag & 1) || e)
3275             e = e.expressionSemantic(sc);
3276         return e;
3277     }
3278 
3279     Expression visitVector(TypeVector mt)
3280     {
3281         static if (LOGDOTEXP)
3282         {
3283             printf("TypeVector::dotExp(e = '%s', ident = '%s')\n", e.toChars(), ident.toChars());
3284         }
3285         if (ident == Id.ptr && e.op == TOK.call)
3286         {
3287             /* The trouble with TOK.call is the return ABI for float[4] is different from
3288              * __vector(float[4]), and a type paint won't do.
3289              */
3290             e = new AddrExp(e.loc, e);
3291             e = e.expressionSemantic(sc);
3292             return e.castTo(sc, mt.basetype.nextOf().pointerTo());
3293         }
3294         if (ident == Id.array)
3295         {
3296             //e = e.castTo(sc, basetype);
3297             // Keep lvalue-ness
3298             e = new VectorArrayExp(e.loc, e);
3299             e = e.expressionSemantic(sc);
3300             return e;
3301         }
3302         if (ident == Id._init || ident == Id.offsetof || ident == Id.stringof || ident == Id.__xalignof)
3303         {
3304             // init should return a new VectorExp
3305             // https://issues.dlang.org/show_bug.cgi?id=12776
3306             // offsetof does not work on a cast expression, so use e directly
3307             // stringof should not add a cast to the output
3308             return visitType(mt);
3309         }
3310         return mt.basetype.dotExp(sc, e.castTo(sc, mt.basetype), ident, flag);
3311     }
3312 
3313     Expression visitArray(TypeArray mt)
3314     {
3315         static if (LOGDOTEXP)
3316         {
3317             printf("TypeArray::dotExp(e = '%s', ident = '%s')\n", e.toChars(), ident.toChars());
3318         }
3319 
3320         e = visitType(mt);
3321 
3322         if (!(flag & 1) || e)
3323             e = e.expressionSemantic(sc);
3324         return e;
3325     }
3326 
3327     Expression visitSArray(TypeSArray mt)
3328     {
3329         static if (LOGDOTEXP)
3330         {
3331             printf("TypeSArray::dotExp(e = '%s', ident = '%s')\n", e.toChars(), ident.toChars());
3332         }
3333         if (ident == Id.length)
3334         {
3335             Loc oldLoc = e.loc;
3336             e = mt.dim.copy();
3337             e.loc = oldLoc;
3338         }
3339         else if (ident == Id.ptr)
3340         {
3341             if (e.op == TOK.type)
3342             {
3343                 e.error("`%s` is not an expression", e.toChars());
3344                 return new ErrorExp();
3345             }
3346             else if (!(flag & DotExpFlag.noDeref) && sc.func && !sc.intypeof && !(sc.flags & SCOPE.debug_) && sc.func.setUnsafe())
3347             {
3348                 e.error("`%s.ptr` cannot be used in `@safe` code, use `&%s[0]` instead", e.toChars(), e.toChars());
3349                 return new ErrorExp();
3350             }
3351             e = e.castTo(sc, e.type.nextOf().pointerTo());
3352         }
3353         else
3354         {
3355             e = visitArray(mt);
3356         }
3357         if (!(flag & 1) || e)
3358             e = e.expressionSemantic(sc);
3359         return e;
3360     }
3361 
3362     Expression visitDArray(TypeDArray mt)
3363     {
3364         static if (LOGDOTEXP)
3365         {
3366             printf("TypeDArray::dotExp(e = '%s', ident = '%s')\n", e.toChars(), ident.toChars());
3367         }
3368         if (e.op == TOK.type && (ident == Id.length || ident == Id.ptr))
3369         {
3370             e.error("`%s` is not an expression", e.toChars());
3371             return new ErrorExp();
3372         }
3373         if (ident == Id.length)
3374         {
3375             if (e.op == TOK.string_)
3376             {
3377                 StringExp se = cast(StringExp)e;
3378                 return new IntegerExp(se.loc, se.len, Type.tsize_t);
3379             }
3380             if (e.op == TOK.null_)
3381             {
3382                 return new IntegerExp(e.loc, 0, Type.tsize_t);
3383             }
3384             if (checkNonAssignmentArrayOp(e))
3385             {
3386                 return new ErrorExp();
3387             }
3388             e = new ArrayLengthExp(e.loc, e);
3389             e.type = Type.tsize_t;
3390             return e;
3391         }
3392         else if (ident == Id.ptr)
3393         {
3394             if (!(flag & DotExpFlag.noDeref) && sc.func && !sc.intypeof && !(sc.flags & SCOPE.debug_) && sc.func.setUnsafe())
3395             {
3396                 e.error("`%s.ptr` cannot be used in `@safe` code, use `&%s[0]` instead", e.toChars(), e.toChars());
3397                 return new ErrorExp();
3398             }
3399             return e.castTo(sc, mt.next.pointerTo());
3400         }
3401         else
3402         {
3403             return visitArray(mt);
3404         }
3405     }
3406 
3407     Expression visitAArray(TypeAArray mt)
3408     {
3409         static if (LOGDOTEXP)
3410         {
3411             printf("TypeAArray::dotExp(e = '%s', ident = '%s')\n", e.toChars(), ident.toChars());
3412         }
3413         if (ident == Id.length)
3414         {
3415             __gshared FuncDeclaration fd_aaLen = null;
3416             if (fd_aaLen is null)
3417             {
3418                 auto fparams = new Parameters();
3419                 fparams.push(new Parameter(STC.in_, mt, null, null, null));
3420                 fd_aaLen = FuncDeclaration.genCfunc(fparams, Type.tsize_t, Id.aaLen);
3421                 TypeFunction tf = fd_aaLen.type.toTypeFunction();
3422                 tf.purity = PURE.const_;
3423                 tf.isnothrow = true;
3424                 tf.isnogc = false;
3425             }
3426             Expression ev = new VarExp(e.loc, fd_aaLen, false);
3427             e = new CallExp(e.loc, ev, e);
3428             e.type = fd_aaLen.type.toTypeFunction().next;
3429             return e;
3430         }
3431         else
3432         {
3433             return visitType(mt);
3434         }
3435     }
3436 
3437     Expression visitReference(TypeReference mt)
3438     {
3439         static if (LOGDOTEXP)
3440         {
3441             printf("TypeReference::dotExp(e = '%s', ident = '%s')\n", e.toChars(), ident.toChars());
3442         }
3443         // References just forward things along
3444         return mt.next.dotExp(sc, e, ident, flag);
3445     }
3446 
3447     Expression visitDelegate(TypeDelegate mt)
3448     {
3449         static if (LOGDOTEXP)
3450         {
3451             printf("TypeDelegate::dotExp(e = '%s', ident = '%s')\n", e.toChars(), ident.toChars());
3452         }
3453         if (ident == Id.ptr)
3454         {
3455             e = new DelegatePtrExp(e.loc, e);
3456             e = e.expressionSemantic(sc);
3457         }
3458         else if (ident == Id.funcptr)
3459         {
3460             if (!(flag & DotExpFlag.noDeref) && sc.func && !sc.intypeof && !(sc.flags & SCOPE.debug_) && sc.func.setUnsafe())
3461             {
3462                 e.error("`%s.funcptr` cannot be used in `@safe` code", e.toChars());
3463                 return new ErrorExp();
3464             }
3465             e = new DelegateFuncptrExp(e.loc, e);
3466             e = e.expressionSemantic(sc);
3467         }
3468         else
3469         {
3470             return visitType(mt);
3471         }
3472         return e;
3473     }
3474 
3475     /***************************************
3476      * Figures out what to do with an undefined member reference
3477      * for classes and structs.
3478      *
3479      * If flag & 1, don't report "not a property" error and just return NULL.
3480      */
3481     Expression noMember(Type mt, Scope* sc, Expression e, Identifier ident, int flag)
3482     {
3483         //printf("Type.noMember(e: %s ident: %s flag: %d)\n", e.toChars(), ident.toChars(), flag);
3484 
3485         bool gagError = flag & 1;
3486 
3487         __gshared int nest;      // https://issues.dlang.org/show_bug.cgi?id=17380
3488 
3489         static Expression returnExp(Expression e)
3490         {
3491             --nest;
3492             return e;
3493         }
3494 
3495         if (++nest > global.recursionLimit)
3496         {
3497             .error(e.loc, "cannot resolve identifier `%s`", ident.toChars());
3498             return returnExp(gagError ? null : new ErrorExp());
3499         }
3500 
3501 
3502         assert(mt.ty == Tstruct || mt.ty == Tclass);
3503         auto sym = mt.toDsymbol(sc).isAggregateDeclaration();
3504         assert(sym);
3505         if (ident != Id.__sizeof &&
3506             ident != Id.__xalignof &&
3507             ident != Id._init &&
3508             ident != Id._mangleof &&
3509             ident != Id.stringof &&
3510             ident != Id.offsetof &&
3511             // https://issues.dlang.org/show_bug.cgi?id=15045
3512             // Don't forward special built-in member functions.
3513             ident != Id.ctor &&
3514             ident != Id.dtor &&
3515             ident != Id.__xdtor &&
3516             ident != Id.postblit &&
3517             ident != Id.__xpostblit)
3518         {
3519             /* Look for overloaded opDot() to see if we should forward request
3520              * to it.
3521              */
3522             if (auto fd = search_function(sym, Id.opDot))
3523             {
3524                 /* Rewrite e.ident as:
3525                  *  e.opDot().ident
3526                  */
3527                 e = build_overload(e.loc, sc, e, null, fd);
3528                 // @@@DEPRECATED_2.087@@@.
3529                 e.deprecation("`opDot` is deprecated. Use `alias this`");
3530                 e = new DotIdExp(e.loc, e, ident);
3531                 return returnExp(e.expressionSemantic(sc));
3532             }
3533 
3534             /* Look for overloaded opDispatch to see if we should forward request
3535              * to it.
3536              */
3537             if (auto fd = search_function(sym, Id.opDispatch))
3538             {
3539                 /* Rewrite e.ident as:
3540                  *  e.opDispatch!("ident")
3541                  */
3542                 TemplateDeclaration td = fd.isTemplateDeclaration();
3543                 if (!td)
3544                 {
3545                     fd.error("must be a template `opDispatch(string s)`, not a %s", fd.kind());
3546                     return returnExp(new ErrorExp());
3547                 }
3548                 auto se = new StringExp(e.loc, ident.toString());
3549                 auto tiargs = new Objects();
3550                 tiargs.push(se);
3551                 auto dti = new DotTemplateInstanceExp(e.loc, e, Id.opDispatch, tiargs);
3552                 dti.ti.tempdecl = td;
3553                 /* opDispatch, which doesn't need IFTI,  may occur instantiate error.
3554                  * e.g.
3555                  *  template opDispatch(name) if (isValid!name) { ... }
3556                  */
3557                 uint errors = gagError ? global.startGagging() : 0;
3558                 e = dti.semanticY(sc, 0);
3559                 if (gagError && global.endGagging(errors))
3560                     e = null;
3561                 return returnExp(e);
3562             }
3563 
3564             /* See if we should forward to the alias this.
3565              */
3566             auto alias_e = resolveAliasThis(sc, e, gagError);
3567             if (alias_e && alias_e != e)
3568             {
3569                 /* Rewrite e.ident as:
3570                  *  e.aliasthis.ident
3571                  */
3572                 auto die = new DotIdExp(e.loc, alias_e, ident);
3573 
3574                 auto errors = gagError ? 0 : global.startGagging();
3575                 auto exp = die.semanticY(sc, gagError);
3576                 if (!gagError)
3577                 {
3578                     global.endGagging(errors);
3579                     if (exp && exp.op == TOK.error)
3580                         exp = null;
3581                 }
3582 
3583                 if (exp && gagError)
3584                     // now that we know that the alias this leads somewhere useful,
3585                     // go back and print deprecations/warnings that we skipped earlier due to the gag
3586                     resolveAliasThis(sc, e, false);
3587 
3588                 return returnExp(exp);
3589             }
3590         }
3591         return returnExp(visitType(mt));
3592     }
3593 
3594     Expression visitStruct(TypeStruct mt)
3595     {
3596         Dsymbol s;
3597         static if (LOGDOTEXP)
3598         {
3599             printf("TypeStruct::dotExp(e = '%s', ident = '%s')\n", e.toChars(), ident.toChars());
3600         }
3601         assert(e.op != TOK.dot);
3602 
3603         // https://issues.dlang.org/show_bug.cgi?id=14010
3604         if (ident == Id._mangleof)
3605         {
3606             return mt.getProperty(sc, e.loc, ident, flag & 1);
3607         }
3608 
3609         /* If e.tupleof
3610          */
3611         if (ident == Id._tupleof)
3612         {
3613             /* Create a TupleExp out of the fields of the struct e:
3614              * (e.field0, e.field1, e.field2, ...)
3615              */
3616             e = e.expressionSemantic(sc); // do this before turning on noaccesscheck
3617 
3618             if (!mt.sym.determineFields())
3619             {
3620                 error(e.loc, "unable to determine fields of `%s` because of forward references", mt.toChars());
3621             }
3622 
3623             Expression e0;
3624             Expression ev = e.op == TOK.type ? null : e;
3625             if (ev)
3626                 ev = extractSideEffect(sc, "__tup", e0, ev);
3627 
3628             auto exps = new Expressions();
3629             exps.reserve(mt.sym.fields.dim);
3630             for (size_t i = 0; i < mt.sym.fields.dim; i++)
3631             {
3632                 VarDeclaration v = mt.sym.fields[i];
3633                 Expression ex;
3634                 if (ev)
3635                     ex = new DotVarExp(e.loc, ev, v);
3636                 else
3637                 {
3638                     ex = new VarExp(e.loc, v);
3639                     ex.type = ex.type.addMod(e.type.mod);
3640                 }
3641                 exps.push(ex);
3642             }
3643 
3644             e = new TupleExp(e.loc, e0, exps);
3645             Scope* sc2 = sc.push();
3646             sc2.flags |= global.params.vsafe ? SCOPE.onlysafeaccess : SCOPE.noaccesscheck;
3647             e = e.expressionSemantic(sc2);
3648             sc2.pop();
3649             return e;
3650         }
3651 
3652         immutable flags = sc.flags & SCOPE.ignoresymbolvisibility ? IgnoreSymbolVisibility : 0;
3653         s = mt.sym.search(e.loc, ident, flags | IgnorePrivateImports);
3654     L1:
3655         if (!s)
3656         {
3657             return noMember(mt, sc, e, ident, flag);
3658         }
3659         if (!(sc.flags & SCOPE.ignoresymbolvisibility) && !symbolIsVisible(sc, s))
3660         {
3661             return noMember(mt, sc, e, ident, flag);
3662         }
3663         if (!s.isFuncDeclaration()) // because of overloading
3664         {
3665             s.checkDeprecated(e.loc, sc);
3666             if (auto d = s.isDeclaration())
3667                 d.checkDisabled(e.loc, sc);
3668         }
3669         s = s.toAlias();
3670 
3671         if (auto em = s.isEnumMember())
3672         {
3673             return em.getVarExp(e.loc, sc);
3674         }
3675         if (auto v = s.isVarDeclaration())
3676         {
3677             if (!v.type ||
3678                 !v.type.deco && v.inuse)
3679             {
3680                 if (v.inuse) // https://issues.dlang.org/show_bug.cgi?id=9494
3681                     e.error("circular reference to %s `%s`", v.kind(), v.toPrettyChars());
3682                 else
3683                     e.error("forward reference to %s `%s`", v.kind(), v.toPrettyChars());
3684                 return new ErrorExp();
3685             }
3686             if (v.type.ty == Terror)
3687             {
3688                 return new ErrorExp();
3689             }
3690 
3691             if ((v.storage_class & STC.manifest) && v._init)
3692             {
3693                 if (v.inuse)
3694                 {
3695                     e.error("circular initialization of %s `%s`", v.kind(), v.toPrettyChars());
3696                     return new ErrorExp();
3697                 }
3698                 checkAccess(e.loc, sc, null, v);
3699                 Expression ve = new VarExp(e.loc, v);
3700                 if (!isTrivialExp(e))
3701                 {
3702                     ve = new CommaExp(e.loc, e, ve);
3703                 }
3704                 return ve.expressionSemantic(sc);
3705             }
3706         }
3707 
3708         if (auto t = s.getType())
3709         {
3710             return (new TypeExp(e.loc, t)).expressionSemantic(sc);
3711         }
3712 
3713         TemplateMixin tm = s.isTemplateMixin();
3714         if (tm)
3715         {
3716             Expression de = new DotExp(e.loc, e, new ScopeExp(e.loc, tm));
3717             de.type = e.type;
3718             return de;
3719         }
3720 
3721         TemplateDeclaration td = s.isTemplateDeclaration();
3722         if (td)
3723         {
3724             if (e.op == TOK.type)
3725                 e = new TemplateExp(e.loc, td);
3726             else
3727                 e = new DotTemplateExp(e.loc, e, td);
3728             return e.expressionSemantic(sc);
3729         }
3730 
3731         TemplateInstance ti = s.isTemplateInstance();
3732         if (ti)
3733         {
3734             if (!ti.semanticRun)
3735             {
3736                 ti.dsymbolSemantic(sc);
3737                 if (!ti.inst || ti.errors) // if template failed to expand
3738                 {
3739                     return new ErrorExp();
3740                 }
3741             }
3742             s = ti.inst.toAlias();
3743             if (!s.isTemplateInstance())
3744                 goto L1;
3745             if (e.op == TOK.type)
3746                 e = new ScopeExp(e.loc, ti);
3747             else
3748                 e = new DotExp(e.loc, e, new ScopeExp(e.loc, ti));
3749             return e.expressionSemantic(sc);
3750         }
3751 
3752         if (s.isImport() || s.isModule() || s.isPackage())
3753         {
3754             return symbolToExp(s, e.loc, sc, false);
3755         }
3756 
3757         OverloadSet o = s.isOverloadSet();
3758         if (o)
3759         {
3760             auto oe = new OverExp(e.loc, o);
3761             if (e.op == TOK.type)
3762             {
3763                 return oe;
3764             }
3765             return new DotExp(e.loc, e, oe);
3766         }
3767 
3768         Declaration d = s.isDeclaration();
3769         if (!d)
3770         {
3771             e.error("`%s.%s` is not a declaration", e.toChars(), ident.toChars());
3772             return new ErrorExp();
3773         }
3774 
3775         if (e.op == TOK.type)
3776         {
3777             /* It's:
3778              *    Struct.d
3779              */
3780             if (TupleDeclaration tup = d.isTupleDeclaration())
3781             {
3782                 e = new TupleExp(e.loc, tup);
3783                 return e.expressionSemantic(sc);
3784             }
3785             if (d.needThis() && sc.intypeof != 1)
3786             {
3787                 /* Rewrite as:
3788                  *  this.d
3789                  */
3790                 if (hasThis(sc))
3791                 {
3792                     e = new DotVarExp(e.loc, new ThisExp(e.loc), d);
3793                     return e.expressionSemantic(sc);
3794                 }
3795             }
3796             if (d.semanticRun == PASS.init)
3797                 d.dsymbolSemantic(null);
3798             checkAccess(e.loc, sc, e, d);
3799             auto ve = new VarExp(e.loc, d);
3800             if (d.isVarDeclaration() && d.needThis())
3801                 ve.type = d.type.addMod(e.type.mod);
3802             return ve;
3803         }
3804 
3805         bool unreal = e.op == TOK.variable && (cast(VarExp)e).var.isField();
3806         if (d.isDataseg() || unreal && d.isField())
3807         {
3808             // (e, d)
3809             checkAccess(e.loc, sc, e, d);
3810             Expression ve = new VarExp(e.loc, d);
3811             e = unreal ? ve : new CommaExp(e.loc, e, ve);
3812             return e.expressionSemantic(sc);
3813         }
3814 
3815         e = new DotVarExp(e.loc, e, d);
3816         return e.expressionSemantic(sc);
3817     }
3818 
3819     Expression visitEnum(TypeEnum mt)
3820     {
3821         static if (LOGDOTEXP)
3822         {
3823             printf("TypeEnum::dotExp(e = '%s', ident = '%s') '%s'\n", e.toChars(), ident.toChars(), mt.toChars());
3824         }
3825         // https://issues.dlang.org/show_bug.cgi?id=14010
3826         if (ident == Id._mangleof)
3827         {
3828             return mt.getProperty(sc, e.loc, ident, flag & 1);
3829         }
3830 
3831         if (mt.sym.semanticRun < PASS.semanticdone)
3832             mt.sym.dsymbolSemantic(null);
3833         if (!mt.sym.members)
3834         {
3835             if (mt.sym.isSpecial())
3836             {
3837                 /* Special enums forward to the base type
3838                  */
3839                 e = mt.sym.memtype.dotExp(sc, e, ident, flag);
3840             }
3841             else if (!(flag & 1))
3842             {
3843                 mt.sym.error("is forward referenced when looking for `%s`", ident.toChars());
3844                 e = new ErrorExp();
3845             }
3846             else
3847                 e = null;
3848             return e;
3849         }
3850 
3851         Dsymbol s = mt.sym.search(e.loc, ident);
3852         if (!s)
3853         {
3854             if (ident == Id.max || ident == Id.min || ident == Id._init)
3855             {
3856                 return mt.getProperty(sc, e.loc, ident, flag & 1);
3857             }
3858 
3859             Expression res = mt.sym.getMemtype(Loc.initial).dotExp(sc, e, ident, 1);
3860             if (!(flag & 1) && !res)
3861             {
3862                 if (auto ns = mt.sym.search_correct(ident))
3863                     e.error("no property `%s` for type `%s`. Did you mean `%s.%s` ?", ident.toChars(), mt.toChars(), mt.toChars(),
3864                         ns.toChars());
3865                 else
3866                     e.error("no property `%s` for type `%s`", ident.toChars(),
3867                         mt.toChars());
3868 
3869                 return new ErrorExp();
3870             }
3871             return res;
3872         }
3873         EnumMember m = s.isEnumMember();
3874         return m.getVarExp(e.loc, sc);
3875     }
3876 
3877     Expression visitClass(TypeClass mt)
3878     {
3879         Dsymbol s;
3880         static if (LOGDOTEXP)
3881         {
3882             printf("TypeClass::dotExp(e = '%s', ident = '%s')\n", e.toChars(), ident.toChars());
3883         }
3884         assert(e.op != TOK.dot);
3885 
3886         // https://issues.dlang.org/show_bug.cgi?id=12543
3887         if (ident == Id.__sizeof || ident == Id.__xalignof || ident == Id._mangleof)
3888         {
3889             return mt.Type.getProperty(sc, e.loc, ident, 0);
3890         }
3891 
3892         /* If e.tupleof
3893          */
3894         if (ident == Id._tupleof)
3895         {
3896             objc.checkTupleof(e, mt);
3897 
3898             /* Create a TupleExp
3899              */
3900             e = e.expressionSemantic(sc); // do this before turning on noaccesscheck
3901 
3902             mt.sym.size(e.loc); // do semantic of type
3903 
3904             Expression e0;
3905             Expression ev = e.op == TOK.type ? null : e;
3906             if (ev)
3907                 ev = extractSideEffect(sc, "__tup", e0, ev);
3908 
3909             auto exps = new Expressions();
3910             exps.reserve(mt.sym.fields.dim);
3911             for (size_t i = 0; i < mt.sym.fields.dim; i++)
3912             {
3913                 VarDeclaration v = mt.sym.fields[i];
3914                 // Don't include hidden 'this' pointer
3915                 if (v.isThisDeclaration())
3916                     continue;
3917                 Expression ex;
3918                 if (ev)
3919                     ex = new DotVarExp(e.loc, ev, v);
3920                 else
3921                 {
3922                     ex = new VarExp(e.loc, v);
3923                     ex.type = ex.type.addMod(e.type.mod);
3924                 }
3925                 exps.push(ex);
3926             }
3927 
3928             e = new TupleExp(e.loc, e0, exps);
3929             Scope* sc2 = sc.push();
3930             sc2.flags |= global.params.vsafe ? SCOPE.onlysafeaccess : SCOPE.noaccesscheck;
3931             e = e.expressionSemantic(sc2);
3932             sc2.pop();
3933             return e;
3934         }
3935 
3936         int flags = sc.flags & SCOPE.ignoresymbolvisibility ? IgnoreSymbolVisibility : 0;
3937         s = mt.sym.search(e.loc, ident, flags | IgnorePrivateImports);
3938 
3939     L1:
3940         if (!s)
3941         {
3942             // See if it's 'this' class or a base class
3943             if (mt.sym.ident == ident)
3944             {
3945                 if (e.op == TOK.type)
3946                 {
3947                     return mt.Type.getProperty(sc, e.loc, ident, 0);
3948                 }
3949                 e = new DotTypeExp(e.loc, e, mt.sym);
3950                 e = e.expressionSemantic(sc);
3951                 return e;
3952             }
3953             if (auto cbase = mt.sym.searchBase(ident))
3954             {
3955                 if (e.op == TOK.type)
3956                 {
3957                     return mt.Type.getProperty(sc, e.loc, ident, 0);
3958                 }
3959                 if (auto ifbase = cbase.isInterfaceDeclaration())
3960                     e = new CastExp(e.loc, e, ifbase.type);
3961                 else
3962                     e = new DotTypeExp(e.loc, e, cbase);
3963                 e = e.expressionSemantic(sc);
3964                 return e;
3965             }
3966 
3967             if (ident == Id.classinfo)
3968             {
3969                 if (!Type.typeinfoclass)
3970                 {
3971                     error(e.loc, "`object.TypeInfo_Class` could not be found, but is implicitly used");
3972                     return new ErrorExp();
3973                 }
3974 
3975                 Type t = Type.typeinfoclass.type;
3976                 if (e.op == TOK.type || e.op == TOK.dotType)
3977                 {
3978                     /* For type.classinfo, we know the classinfo
3979                      * at compile time.
3980                      */
3981                     if (!mt.sym.vclassinfo)
3982                         mt.sym.vclassinfo = new TypeInfoClassDeclaration(mt.sym.type);
3983                     e = new VarExp(e.loc, mt.sym.vclassinfo);
3984                     e = e.addressOf();
3985                     e.type = t; // do this so we don't get redundant dereference
3986                 }
3987                 else
3988                 {
3989                     /* For class objects, the classinfo reference is the first
3990                      * entry in the vtbl[]
3991                      */
3992                     e = new PtrExp(e.loc, e);
3993                     e.type = t.pointerTo();
3994                     if (mt.sym.isInterfaceDeclaration())
3995                     {
3996                         if (mt.sym.isCPPinterface())
3997                         {
3998                             /* C++ interface vtbl[]s are different in that the
3999                              * first entry is always pointer to the first virtual
4000                              * function, not classinfo.
4001                              * We can't get a .classinfo for it.
4002                              */
4003                             error(e.loc, "no `.classinfo` for C++ interface objects");
4004                         }
4005                         /* For an interface, the first entry in the vtbl[]
4006                          * is actually a pointer to an instance of struct Interface.
4007                          * The first member of Interface is the .classinfo,
4008                          * so add an extra pointer indirection.
4009                          */
4010                         e.type = e.type.pointerTo();
4011                         e = new PtrExp(e.loc, e);
4012                         e.type = t.pointerTo();
4013                     }
4014                     e = new PtrExp(e.loc, e, t);
4015                 }
4016                 return e;
4017             }
4018 
4019             if (ident == Id.__vptr)
4020             {
4021                 /* The pointer to the vtbl[]
4022                  * *cast(immutable(void*)**)e
4023                  */
4024                 e = e.castTo(sc, mt.tvoidptr.immutableOf().pointerTo().pointerTo());
4025                 e = new PtrExp(e.loc, e);
4026                 e = e.expressionSemantic(sc);
4027                 return e;
4028             }
4029 
4030             if (ident == Id.__monitor && mt.sym.hasMonitor())
4031             {
4032                 /* The handle to the monitor (call it a void*)
4033                  * *(cast(void**)e + 1)
4034                  */
4035                 e = e.castTo(sc, mt.tvoidptr.pointerTo());
4036                 e = new AddExp(e.loc, e, IntegerExp.literal!1);
4037                 e = new PtrExp(e.loc, e);
4038                 e = e.expressionSemantic(sc);
4039                 return e;
4040             }
4041 
4042             if (ident == Id.outer && mt.sym.vthis)
4043             {
4044                 if (mt.sym.vthis.semanticRun == PASS.init)
4045                     mt.sym.vthis.dsymbolSemantic(null);
4046 
4047                 if (auto cdp = mt.sym.toParentLocal().isClassDeclaration())
4048                 {
4049                     auto dve = new DotVarExp(e.loc, e, mt.sym.vthis);
4050                     dve.type = cdp.type.addMod(e.type.mod);
4051                     return dve;
4052                 }
4053 
4054                 /* https://issues.dlang.org/show_bug.cgi?id=15839
4055                  * Find closest parent class through nested functions.
4056                  */
4057                 for (auto p = mt.sym.toParentLocal(); p; p = p.toParentLocal())
4058                 {
4059                     auto fd = p.isFuncDeclaration();
4060                     if (!fd)
4061                         break;
4062                     auto ad = fd.isThis();
4063                     if (!ad && fd.isNested())
4064                         continue;
4065                     if (!ad)
4066                         break;
4067                     if (auto cdp = ad.isClassDeclaration())
4068                     {
4069                         auto ve = new ThisExp(e.loc);
4070 
4071                         ve.var = fd.vthis;
4072                         const nestedError = fd.vthis.checkNestedReference(sc, e.loc);
4073                         assert(!nestedError);
4074 
4075                         ve.type = cdp.type.addMod(fd.vthis.type.mod).addMod(e.type.mod);
4076                         return ve;
4077                     }
4078                     break;
4079                 }
4080 
4081                 // Continue to show enclosing function's frame (stack or closure).
4082                 auto dve = new DotVarExp(e.loc, e, mt.sym.vthis);
4083                 dve.type = mt.sym.vthis.type.addMod(e.type.mod);
4084                 return dve;
4085             }
4086 
4087             return noMember(mt, sc, e, ident, flag & 1);
4088         }
4089         if (!(sc.flags & SCOPE.ignoresymbolvisibility) && !symbolIsVisible(sc, s))
4090         {
4091             return noMember(mt, sc, e, ident, flag);
4092         }
4093         if (!s.isFuncDeclaration()) // because of overloading
4094         {
4095             s.checkDeprecated(e.loc, sc);
4096             if (auto d = s.isDeclaration())
4097                 d.checkDisabled(e.loc, sc);
4098         }
4099         s = s.toAlias();
4100 
4101         if (auto em = s.isEnumMember())
4102         {
4103             return em.getVarExp(e.loc, sc);
4104         }
4105         if (auto v = s.isVarDeclaration())
4106         {
4107             if (!v.type ||
4108                 !v.type.deco && v.inuse)
4109             {
4110                 if (v.inuse) // https://issues.dlang.org/show_bug.cgi?id=9494
4111                     e.error("circular reference to %s `%s`", v.kind(), v.toPrettyChars());
4112                 else
4113                     e.error("forward reference to %s `%s`", v.kind(), v.toPrettyChars());
4114                 return new ErrorExp();
4115             }
4116             if (v.type.ty == Terror)
4117             {
4118                 return new ErrorExp();
4119             }
4120 
4121             if ((v.storage_class & STC.manifest) && v._init)
4122             {
4123                 if (v.inuse)
4124                 {
4125                     e.error("circular initialization of %s `%s`", v.kind(), v.toPrettyChars());
4126                     return new ErrorExp();
4127                 }
4128                 checkAccess(e.loc, sc, null, v);
4129                 Expression ve = new VarExp(e.loc, v);
4130                 ve = ve.expressionSemantic(sc);
4131                 return ve;
4132             }
4133         }
4134 
4135         if (auto t = s.getType())
4136         {
4137             return (new TypeExp(e.loc, t)).expressionSemantic(sc);
4138         }
4139 
4140         TemplateMixin tm = s.isTemplateMixin();
4141         if (tm)
4142         {
4143             Expression de = new DotExp(e.loc, e, new ScopeExp(e.loc, tm));
4144             de.type = e.type;
4145             return de;
4146         }
4147 
4148         TemplateDeclaration td = s.isTemplateDeclaration();
4149         if (td)
4150         {
4151             if (e.op == TOK.type)
4152                 e = new TemplateExp(e.loc, td);
4153             else
4154                 e = new DotTemplateExp(e.loc, e, td);
4155             e = e.expressionSemantic(sc);
4156             return e;
4157         }
4158 
4159         TemplateInstance ti = s.isTemplateInstance();
4160         if (ti)
4161         {
4162             if (!ti.semanticRun)
4163             {
4164                 ti.dsymbolSemantic(sc);
4165                 if (!ti.inst || ti.errors) // if template failed to expand
4166                 {
4167                     return new ErrorExp();
4168                 }
4169             }
4170             s = ti.inst.toAlias();
4171             if (!s.isTemplateInstance())
4172                 goto L1;
4173             if (e.op == TOK.type)
4174                 e = new ScopeExp(e.loc, ti);
4175             else
4176                 e = new DotExp(e.loc, e, new ScopeExp(e.loc, ti));
4177             return e.expressionSemantic(sc);
4178         }
4179 
4180         if (s.isImport() || s.isModule() || s.isPackage())
4181         {
4182             e = symbolToExp(s, e.loc, sc, false);
4183             return e;
4184         }
4185 
4186         OverloadSet o = s.isOverloadSet();
4187         if (o)
4188         {
4189             auto oe = new OverExp(e.loc, o);
4190             if (e.op == TOK.type)
4191             {
4192                 return oe;
4193             }
4194             return new DotExp(e.loc, e, oe);
4195         }
4196 
4197         Declaration d = s.isDeclaration();
4198         if (!d)
4199         {
4200             e.error("`%s.%s` is not a declaration", e.toChars(), ident.toChars());
4201             return new ErrorExp();
4202         }
4203 
4204         if (e.op == TOK.type)
4205         {
4206             /* It's:
4207              *    Class.d
4208              */
4209             if (TupleDeclaration tup = d.isTupleDeclaration())
4210             {
4211                 e = new TupleExp(e.loc, tup);
4212                 e = e.expressionSemantic(sc);
4213                 return e;
4214             }
4215 
4216             if (mt.sym.classKind == ClassKind.objc
4217                 && d.isFuncDeclaration()
4218                 && d.isFuncDeclaration().isStatic
4219                 && d.isFuncDeclaration().selector)
4220             {
4221                 auto classRef = new ObjcClassReferenceExp(e.loc, mt.sym);
4222                 return new DotVarExp(e.loc, classRef, d).expressionSemantic(sc);
4223             }
4224             else if (d.needThis() && sc.intypeof != 1)
4225             {
4226                 /* Rewrite as:
4227                  *  this.d
4228                  */
4229                 AggregateDeclaration ad = d.isMemberLocal();
4230                 if (auto f = hasThis(sc))
4231                 {
4232                     // This is almost same as getRightThis() in expressionsem.d
4233                     Expression e1;
4234                     Type t;
4235                     /* returns: true to continue, false to return */
4236                     if (f.isThis2)
4237                     {
4238                         if (f.followInstantiationContext(ad))
4239                         {
4240                             e1 = new VarExp(e.loc, f.vthis);
4241                             e1 = new PtrExp(e1.loc, e1);
4242                             e1 = new IndexExp(e1.loc, e1, IntegerExp.literal!1);
4243                             auto pd = f.toParent2().isDeclaration();
4244                             assert(pd);
4245                             t = pd.type.toBasetype();
4246                             e1 = getThisSkipNestedFuncs(e1.loc, sc, f.toParent2(), ad, e1, t, d, true);
4247                             if (!e1)
4248                             {
4249                                 e = new VarExp(e.loc, d);
4250                                 return e;
4251                             }
4252                             goto L2;
4253                         }
4254                     }
4255                     e1 = new ThisExp(e.loc);
4256                     e1 = e1.expressionSemantic(sc);
4257                 L2:
4258                     t = e1.type.toBasetype();
4259                     ClassDeclaration cd = e.type.isClassHandle();
4260                     ClassDeclaration tcd = t.isClassHandle();
4261                     if (cd && tcd && (tcd == cd || cd.isBaseOf(tcd, null)))
4262                     {
4263                         e = new DotTypeExp(e1.loc, e1, cd);
4264                         e = new DotVarExp(e.loc, e, d);
4265                         e = e.expressionSemantic(sc);
4266                         return e;
4267                     }
4268                     if (tcd && tcd.isNested())
4269                     {
4270                         /* e1 is the 'this' pointer for an inner class: tcd.
4271                          * Rewrite it as the 'this' pointer for the outer class.
4272                          */
4273                         auto vthis = tcd.followInstantiationContext(ad) ? tcd.vthis2 : tcd.vthis;
4274                         e1 = new DotVarExp(e.loc, e1, vthis);
4275                         e1.type = vthis.type;
4276                         e1.type = e1.type.addMod(t.mod);
4277                         // Do not call ensureStaticLinkTo()
4278                         //e1 = e1.expressionSemantic(sc);
4279 
4280                         // Skip up over nested functions, and get the enclosing
4281                         // class type.
4282                         e1 = getThisSkipNestedFuncs(e1.loc, sc, tcd.toParentP(ad), ad, e1, t, d, true);
4283                         if (!e1)
4284                         {
4285                             e = new VarExp(e.loc, d);
4286                             return e;
4287                         }
4288                         goto L2;
4289                     }
4290                 }
4291             }
4292             //printf("e = %s, d = %s\n", e.toChars(), d.toChars());
4293             if (d.semanticRun == PASS.init)
4294                 d.dsymbolSemantic(null);
4295 
4296             // If static function, get the most visible overload.
4297             // Later on the call is checked for correctness.
4298             // https://issues.dlang.org/show_bug.cgi?id=12511
4299             if (auto fd = d.isFuncDeclaration())
4300             {
4301                 import dmd.access : mostVisibleOverload;
4302                 d = cast(Declaration)mostVisibleOverload(fd, sc._module);
4303             }
4304 
4305             checkAccess(e.loc, sc, e, d);
4306             auto ve = new VarExp(e.loc, d);
4307             if (d.isVarDeclaration() && d.needThis())
4308                 ve.type = d.type.addMod(e.type.mod);
4309             return ve;
4310         }
4311 
4312         bool unreal = e.op == TOK.variable && (cast(VarExp)e).var.isField();
4313         if (d.isDataseg() || unreal && d.isField())
4314         {
4315             // (e, d)
4316             checkAccess(e.loc, sc, e, d);
4317             Expression ve = new VarExp(e.loc, d);
4318             e = unreal ? ve : new CommaExp(e.loc, e, ve);
4319             e = e.expressionSemantic(sc);
4320             return e;
4321         }
4322 
4323         e = new DotVarExp(e.loc, e, d);
4324         e = e.expressionSemantic(sc);
4325         return e;
4326     }
4327 
4328     switch (mt.ty)
4329     {
4330         case Tvector:    return visitVector   (cast(TypeVector)mt);
4331         case Tsarray:    return visitSArray   (cast(TypeSArray)mt);
4332         case Tstruct:    return visitStruct   (cast(TypeStruct)mt);
4333         case Tenum:      return visitEnum     (cast(TypeEnum)mt);
4334         case Terror:     return visitError    (cast(TypeError)mt);
4335         case Tarray:     return visitDArray   (cast(TypeDArray)mt);
4336         case Taarray:    return visitAArray   (cast(TypeAArray)mt);
4337         case Treference: return visitReference(cast(TypeReference)mt);
4338         case Tdelegate:  return visitDelegate (cast(TypeDelegate)mt);
4339         case Tclass:     return visitClass    (cast(TypeClass)mt);
4340 
4341         default:         return mt.isTypeBasic()
4342                                 ? visitBasic(cast(TypeBasic)mt)
4343                                 : visitType(mt);
4344     }
4345 }
4346 
4347 
4348 /************************
4349  * Get the the default initialization expression for a type.
4350  * Params:
4351  *  mt = the type for which the init expression is returned
4352  *  loc = the location where the expression needs to be evaluated
4353  *
4354  * Returns:
4355  *  The initialization expression for the type.
4356  */
4357 Expression defaultInit(Type mt, const ref Loc loc)
4358 {
4359     Expression visitBasic(TypeBasic mt)
4360     {
4361         static if (LOGDEFAULTINIT)
4362         {
4363             printf("TypeBasic::defaultInit() '%s'\n", mt.toChars());
4364         }
4365         dinteger_t value = 0;
4366 
4367         switch (mt.ty)
4368         {
4369         case Tchar:
4370             value = 0xFF;
4371             break;
4372 
4373         case Twchar:
4374         case Tdchar:
4375             value = 0xFFFF;
4376             break;
4377 
4378         case Timaginary32:
4379         case Timaginary64:
4380         case Timaginary80:
4381         case Tfloat32:
4382         case Tfloat64:
4383         case Tfloat80:
4384             return new RealExp(loc, target.RealProperties.nan, mt);
4385 
4386         case Tcomplex32:
4387         case Tcomplex64:
4388         case Tcomplex80:
4389             {
4390                 // Can't use fvalue + I*fvalue (the im part becomes a quiet NaN).
4391                 const cvalue = complex_t(target.RealProperties.nan, target.RealProperties.nan);
4392                 return new ComplexExp(loc, cvalue, mt);
4393             }
4394 
4395         case Tvoid:
4396             error(loc, "`void` does not have a default initializer");
4397             return new ErrorExp();
4398 
4399         default:
4400             break;
4401         }
4402         return new IntegerExp(loc, value, mt);
4403     }
4404 
4405     Expression visitVector(TypeVector mt)
4406     {
4407         //printf("TypeVector::defaultInit()\n");
4408         assert(mt.basetype.ty == Tsarray);
4409         Expression e = mt.basetype.defaultInit(loc);
4410         auto ve = new VectorExp(loc, e, mt);
4411         ve.type = mt;
4412         ve.dim = cast(int)(mt.basetype.size(loc) / mt.elementType().size(loc));
4413         return ve;
4414     }
4415 
4416     Expression visitSArray(TypeSArray mt)
4417     {
4418         static if (LOGDEFAULTINIT)
4419         {
4420             printf("TypeSArray::defaultInit() '%s'\n", mt.toChars());
4421         }
4422         if (mt.next.ty == Tvoid)
4423             return mt.tuns8.defaultInit(loc);
4424         else
4425             return mt.next.defaultInit(loc);
4426     }
4427 
4428     Expression visitFunction(TypeFunction mt)
4429     {
4430         error(loc, "`function` does not have a default initializer");
4431         return new ErrorExp();
4432     }
4433 
4434     Expression visitStruct(TypeStruct mt)
4435     {
4436         static if (LOGDEFAULTINIT)
4437         {
4438             printf("TypeStruct::defaultInit() '%s'\n", mt.toChars());
4439         }
4440         Declaration d = new SymbolDeclaration(mt.sym.loc, mt.sym);
4441         assert(d);
4442         d.type = mt;
4443         d.storage_class |= STC.rvalue; // https://issues.dlang.org/show_bug.cgi?id=14398
4444         return new VarExp(mt.sym.loc, d);
4445     }
4446 
4447     Expression visitEnum(TypeEnum mt)
4448     {
4449         static if (LOGDEFAULTINIT)
4450         {
4451             printf("TypeEnum::defaultInit() '%s'\n", mt.toChars());
4452         }
4453         // Initialize to first member of enum
4454         Expression e = mt.sym.getDefaultValue(loc);
4455         e = e.copy();
4456         e.loc = loc;
4457         e.type = mt; // to deal with const, immutable, etc., variants
4458         return e;
4459     }
4460 
4461     Expression visitTuple(TypeTuple mt)
4462     {
4463         static if (LOGDEFAULTINIT)
4464         {
4465             printf("TypeTuple::defaultInit() '%s'\n", mt.toChars());
4466         }
4467         auto exps = new Expressions(mt.arguments.dim);
4468         for (size_t i = 0; i < mt.arguments.dim; i++)
4469         {
4470             Parameter p = (*mt.arguments)[i];
4471             assert(p.type);
4472             Expression e = p.type.defaultInitLiteral(loc);
4473             if (e.op == TOK.error)
4474             {
4475                 return e;
4476             }
4477             (*exps)[i] = e;
4478         }
4479         return new TupleExp(loc, exps);
4480     }
4481 
4482     switch (mt.ty)
4483     {
4484         case Tvector:   return visitVector  (cast(TypeVector)mt);
4485         case Tsarray:   return visitSArray  (cast(TypeSArray)mt);
4486         case Tfunction: return visitFunction(cast(TypeFunction)mt);
4487         case Tstruct:   return visitStruct  (cast(TypeStruct)mt);
4488         case Tenum:     return visitEnum    (cast(TypeEnum)mt);
4489         case Ttuple:    return visitTuple   (cast(TypeTuple)mt);
4490 
4491         case Tnull:     return new NullExp(Loc.initial, Type.tnull);
4492 
4493         case Terror:    return new ErrorExp();
4494 
4495         case Tarray:
4496         case Taarray:
4497         case Tpointer:
4498         case Treference:
4499         case Tdelegate:
4500         case Tclass:    return new NullExp(loc, mt);
4501 
4502         default:        return mt.isTypeBasic() ?
4503                                 visitBasic(cast(TypeBasic)mt) :
4504                                 null;
4505     }
4506 }