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