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