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