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