2 * Semantic analysis for D types.
4 * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved
5 * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright)
6 * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
7 * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/typesem.d, _typesem.d)
8 * Documentation: https://dlang.org/phobos/dmd_typesem.html
9 * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/typesem.d
14 import core.checkedint;
15 import core.stdc.string;
16 import core.stdc.stdio;
22 import dmd.arraytypes;
23 import dmd.astcodegen;
27 import dmd.declaration;
35 import dmd.dsymbolsem;
38 import dmd.expression;
39 import dmd.expressionsem;
44 import dmd.identifier;
55 import dmd.root.complex;
56 import dmd.root.ctfloat;
58 import dmd.common.outbuffer;
59 import dmd.root.rootobject;
60 import dmd.root.string;
61 import dmd.root.stringtable;
64 import dmd.sideeffect;
68 /*************************************
69 * Resolve a tuple index, `s[oindex]`, by figuring out what `s[oindex]` represents.
70 * Setting one of pe/pt/ps.
72 * loc = location for error messages
74 * s = symbol being indexed - could be a tuple, could be an expression
75 * pe = set if s[oindex] is an Expression, otherwise null
76 * pt = set if s[oindex] is a Type, otherwise null
77 * ps = set if s[oindex] is a Dsymbol, otherwise null
78 * oindex = index into s
80 private void resolveTupleIndex(const ref Loc loc, Scope* sc, Dsymbol s, out Expression pe, out Type pt, out Dsymbol ps, RootObject oindex)
82 auto tup = s.isTupleDeclaration();
84 auto eindex = isExpression(oindex);
85 auto tindex = isType(oindex);
86 auto sindex = isDsymbol(oindex);
90 // It's really an index expression
92 eindex = new TypeExp(loc, tindex);
94 eindex = symbolToExp(sindex, loc, sc, false);
95 Expression e = new IndexExp(loc, symbolToExp(s, loc, sc, false), eindex);
96 e = e.expressionSemantic(sc);
97 resolveExp(e, pt, pe, ps);
101 // Convert oindex to Expression, then try to resolve to constant.
103 tindex.resolve(loc, sc, eindex, tindex, sindex);
105 eindex = symbolToExp(sindex, loc, sc, false);
108 .error(loc, "index `%s` is not an expression", oindex.toChars());
113 eindex = semanticLength(sc, tup, eindex);
114 eindex = eindex.ctfeInterpret();
115 if (eindex.op == EXP.error)
120 const(uinteger_t) d = eindex.toUInteger();
121 if (d >= tup.objects.length)
123 .error(loc, "tuple index `%llu` out of bounds `[0 .. %llu]`", d, cast(ulong)tup.objects.length);
128 RootObject o = (*tup.objects)[cast(size_t)d];
130 if (auto t = isType(o))
131 pt = t.typeSemantic(loc, sc);
132 if (auto e = isExpression(o))
133 resolveExp(e, pt, pe, ps);
136 /*************************************
137 * Takes an array of Identifiers and figures out if
138 * it represents a Type, Expression, or Dsymbol.
140 * mt = array of identifiers
141 * loc = location for error messages
143 * s = symbol to start search at
145 * pe = set if expression otherwise null
146 * pt = set if type otherwise null
147 * ps = set if symbol otherwise null
148 * typeid = set if in TypeidExpression https://dlang.org/spec/expression.html#TypeidExpression
150 private void resolveHelper(TypeQualified mt, const ref Loc loc, Scope* sc, Dsymbol s, Dsymbol scopesym,
151 out Expression pe, out Type pt, out Dsymbol ps, bool intypeid = false)
155 printf("TypeQualified::resolveHelper(sc = %p, idents = '%s')\n", sc, mt.toChars());
157 printf("\tscopesym = '%s'\n", scopesym.toChars());
162 /* Look for what user might have intended
164 const p = mt.mutableOf().unSharedOf().toChars();
165 auto id = Identifier.idPool(p, cast(uint)strlen(p));
166 if (const n = importHint(id.toString()))
167 error(loc, "`%s` is not defined, perhaps `import %.*s;` ?", p, cast(int)n.length, n.ptr);
168 else if (auto s2 = sc.search_correct(id))
169 error(loc, "undefined identifier `%s`, did you mean %s `%s`?", p, s2.kind(), s2.toChars());
170 else if (const q = Scope.search_correct_C(id))
171 error(loc, "undefined identifier `%s`, did you mean `%s`?", p, q);
172 else if ((id == Id.This && sc.getStructClassScope()) ||
173 (id == Id._super && sc.getClassScope()))
174 error(loc, "undefined identifier `%s`, did you mean `typeof(%s)`?", p, p);
176 error(loc, "undefined identifier `%s`", p);
182 //printf("\t1: s = '%s' %p, kind = '%s'\n",s.toChars(), s, s.kind());
183 Declaration d = s.isDeclaration();
184 if (d && (d.storage_class & STC.templateparameter))
188 // check for deprecated or disabled aliases
189 // functions are checked after overloading
190 // templates are checked after matching constraints
191 if (!s.isFuncDeclaration() && !s.isTemplateDeclaration())
192 s.checkDeprecated(loc, sc);
194 d.checkDisabled(loc, sc, true);
197 //printf("\t2: s = '%s' %p, kind = '%s'\n",s.toChars(), s, s.kind());
198 for (size_t i = 0; i < mt.idents.length; i++)
200 RootObject id = mt.idents[i];
201 switch (id.dyncast()) with (DYNCAST)
208 resolveTupleIndex(loc, sc, s, ex, tx, sx, id);
215 ex = new TypeExp(loc, tx);
218 ex = typeToExpressionHelper(mt, ex, i + 1);
219 ex = ex.expressionSemantic(sc);
220 resolveExp(ex, pt, pe, ps);
226 Type t = s.getType(); // type symbol, type alias, or type tuple?
227 uint errorsave = global.errors;
228 int flags = t is null ? SearchLocalsOnly : IgnorePrivateImports;
230 Dsymbol sm = s.searchX(loc, sc, id, flags);
233 if (!(sc.flags & SCOPE.ignoresymbolvisibility) && !symbolIsVisible(sc, sm))
235 .error(loc, "`%s` is not visible from module `%s`", sm.toPrettyChars(), sc._module.toChars());
238 // Same check as in dotIdSemanticProp(DotIdExp)
239 else if (sm.isPackage() && checkAccess(sc, sm.isPackage()))
241 // @@@DEPRECATED_2.106@@@
242 // Should be an error in 2.106. Just remove the deprecation call
243 // and uncomment the null assignment
244 deprecation(loc, "%s %s is not accessible here, perhaps add 'static import %s;'", sm.kind(), sm.toPrettyChars(), sm.toPrettyChars());
248 if (global.errors != errorsave)
257 VarDeclaration v = s.isVarDeclaration();
258 FuncDeclaration f = s.isFuncDeclaration();
259 if (intypeid || !v && !f)
260 e = symbolToExp(s, loc, sc, true);
262 e = new VarExp(loc, s.isDeclaration(), true);
264 e = typeToExpressionHelper(mt, e, i);
265 e = e.expressionSemantic(sc);
266 resolveExp(e, pt, pe, ps);
269 //printf("\t3: s = %p %s %s, sm = %p\n", s, s.kind(), s.toChars(), sm);
270 if (intypeid && !t && sm && sm.needThis())
273 if (VarDeclaration v = s.isVarDeclaration())
275 // https://issues.dlang.org/show_bug.cgi?id=19913
276 // v.type would be null if it is a forward referenced member.
278 v.dsymbolSemantic(sc);
279 if (v.storage_class & (STC.const_ | STC.immutable_ | STC.manifest) ||
280 v.type.isConst() || v.type.isImmutable())
282 // https://issues.dlang.org/show_bug.cgi?id=13087
283 // this.field is not constant always
284 if (!v.isThisDeclaration())
292 if (s.isDeclaration()) // var, func, or tuple declaration?
294 t = s.isDeclaration().type;
295 if (!t && s.isTupleDeclaration()) // expression tuple?
298 else if (s.isTemplateInstance() ||
299 s.isImport() || s.isPackage() || s.isModule())
306 sm = t.toDsymbol(sc);
307 if (sm && id.dyncast() == DYNCAST.identifier)
309 sm = sm.search(loc, cast(Identifier)id, IgnorePrivateImports);
318 if (id.dyncast() == DYNCAST.dsymbol)
320 // searchX already handles errors for template instances
321 assert(global.errors);
325 assert(id.dyncast() == DYNCAST.identifier);
326 sm = s.search_correct(cast(Identifier)id);
328 error(loc, "identifier `%s` of `%s` is not defined, did you mean %s `%s`?", id.toChars(), mt.toChars(), sm.kind(), sm.toChars());
330 error(loc, "identifier `%s` of `%s` is not defined", id.toChars(), mt.toChars());
339 if (auto em = s.isEnumMember())
341 // It's not a type, it's an expression
342 pe = em.getVarExp(loc, sc);
345 if (auto v = s.isVarDeclaration())
347 /* This is mostly same with DsymbolExp::semantic(), but we cannot use it
348 * because some variables used in type context need to prevent lowering
349 * to a literal or contextful expression. For example:
351 * enum a = 1; alias b = a;
352 * template X(alias e){ alias v = e; } alias x = X!(1);
353 * struct S { int v; alias w = v; }
354 * // TypeIdentifier 'a', 'e', and 'v' should be EXP.variable,
355 * // because getDsymbol() need to work in AliasDeclaration::semantic().
358 !v.type.deco && v.inuse)
360 if (v.inuse) // https://issues.dlang.org/show_bug.cgi?id=9494
361 error(loc, "circular reference to %s `%s`", v.kind(), v.toPrettyChars());
363 error(loc, "forward reference to %s `%s`", v.kind(), v.toPrettyChars());
367 if (v.type.ty == Terror)
370 pe = new VarExp(loc, v);
373 if (auto fld = s.isFuncLiteralDeclaration())
375 //printf("'%s' is a function literal\n", fld.toChars());
376 auto e = new FuncExp(loc, fld);
377 pe = e.expressionSemantic(sc);
382 if (FuncDeclaration fd = s.isFuncDeclaration())
384 pe = new DsymbolExp(loc, fd);
399 if (auto ti = t.isTypeInstance())
400 if (ti != mt && !ti.deco)
402 if (!ti.tempinst.errors)
403 error(loc, "forward reference to `%s`", ti.toChars());
414 /******************************************
415 * We've mistakenly parsed `t` as a type.
416 * Redo `t` as an Expression only if there are no type modifiers.
420 * t redone as Expression, null if cannot
422 Expression typeToExpression(Type t)
424 static Expression visitSArray(TypeSArray t)
426 if (auto e = t.next.typeToExpression())
427 return new ArrayExp(t.dim.loc, e, t.dim);
431 static Expression visitAArray(TypeAArray t)
433 if (auto e = t.next.typeToExpression())
435 if (auto ei = t.index.typeToExpression())
436 return new ArrayExp(t.loc, e, ei);
441 static Expression visitIdentifier(TypeIdentifier t)
443 return typeToExpressionHelper(t, new IdentifierExp(t.loc, t.ident));
446 static Expression visitInstance(TypeInstance t)
448 return typeToExpressionHelper(t, new ScopeExp(t.loc, t.tempinst));
451 // easy way to enable 'auto v = new int[mixin("exp")];' in 2.088+
452 static Expression visitMixin(TypeMixin t)
454 return new TypeExp(t.loc, t);
461 case Tsarray: return visitSArray(t.isTypeSArray());
462 case Taarray: return visitAArray(t.isTypeAArray());
463 case Tident: return visitIdentifier(t.isTypeIdentifier());
464 case Tinstance: return visitInstance(t.isTypeInstance());
465 case Tmixin: return visitMixin(t.isTypeMixin());
466 default: return null;
470 /******************************************
471 * Perform semantic analysis on a type.
473 * type = Type AST node
474 * loc = the location of the type
477 * `Type` with completed semantic analysis, `Terror` if errors
480 extern(C++) Type typeSemantic(Type type, const ref Loc loc, Scope* sc)
487 Type visitType(Type t)
489 // @@@DEPRECATED_2.110@@@
490 // Use of `cent` and `ucent` has always been an error.
491 // Starting from 2.100, recommend core.int128 as a replace for the
492 // lack of compiler support.
493 if (t.ty == Tint128 || t.ty == Tuns128)
495 .error(loc, "`cent` and `ucent` types are obsolete, use `core.int128.Cent` instead");
502 Type visitVector(TypeVector mtype)
504 const errors = global.errors;
505 mtype.basetype = mtype.basetype.typeSemantic(loc, sc);
506 if (errors != global.errors)
508 mtype.basetype = mtype.basetype.toBasetype().mutableOf();
509 if (mtype.basetype.ty != Tsarray)
511 .error(loc, "T in __vector(T) must be a static array, not `%s`", mtype.basetype.toChars());
514 TypeSArray t = mtype.basetype.isTypeSArray();
515 const sz = cast(int)t.size(loc);
516 final switch (target.isVectorTypeSupported(sz, t.nextOf()))
524 .error(loc, "SIMD vector types not supported on this platform");
529 .error(loc, "vector type `%s` is not supported on this platform", mtype.toChars());
534 .error(loc, "%d byte vector type `%s` is not supported on this platform", sz, mtype.toChars());
540 Type visitSArray(TypeSArray mtype)
542 //printf("TypeSArray::semantic() %s\n", toChars());
546 mtype.next.resolve(loc, sc, e, t, s);
548 if (auto tup = s ? s.isTupleDeclaration() : null)
550 mtype.dim = semanticLength(sc, tup, mtype.dim);
551 mtype.dim = mtype.dim.ctfeInterpret();
552 if (mtype.dim.op == EXP.error)
555 uinteger_t d = mtype.dim.toUInteger();
556 if (d >= tup.objects.length)
558 .error(loc, "tuple index `%llu` out of bounds `[0 .. %llu]`", cast(ulong)d, cast(ulong)tup.objects.length);
562 RootObject o = (*tup.objects)[cast(size_t)d];
563 if (o.dyncast() != DYNCAST.type)
565 .error(loc, "`%s` is not a type", mtype.toChars());
568 return (cast(Type)o).addMod(mtype.mod);
571 if (t && t.ty == Terror)
574 Type tn = mtype.next.typeSemantic(loc, sc);
578 Type tbn = tn.toBasetype();
581 auto errors = global.errors;
582 mtype.dim = semanticLength(sc, tbn, mtype.dim);
583 if (errors != global.errors)
586 mtype.dim = mtype.dim.optimize(WANTvalue);
587 mtype.dim = mtype.dim.ctfeInterpret();
588 if (mtype.dim.op == EXP.error)
591 errors = global.errors;
592 dinteger_t d1 = mtype.dim.toInteger();
593 if (errors != global.errors)
596 mtype.dim = mtype.dim.implicitCastTo(sc, Type.tsize_t);
597 mtype.dim = mtype.dim.optimize(WANTvalue);
598 if (mtype.dim.op == EXP.error)
601 errors = global.errors;
602 dinteger_t d2 = mtype.dim.toInteger();
603 if (errors != global.errors)
606 if (mtype.dim.op == EXP.error)
611 .error(loc, "`%s` size %llu * %llu exceeds 0x%llx size limit for static array",
612 mtype.toChars(), cast(ulong)tbn.size(loc), cast(ulong)d1, target.maxStaticDataSize);
617 return overflowError();
619 Type tbx = tbn.baseElemOf();
620 if (tbx.ty == Tstruct && !tbx.isTypeStruct().sym.members ||
621 tbx.ty == Tenum && !tbx.isTypeEnum().sym.members)
623 /* To avoid meaningless error message, skip the total size limit check
624 * when the bottom of element type is opaque.
627 else if (tbn.isTypeBasic() ||
628 tbn.ty == Tpointer ||
632 (tbn.ty == Tstruct && tbn.isTypeStruct().sym.sizeok == Sizeok.done) ||
635 /* Only do this for types that don't need to have semantic()
636 * run on them for the size, since they may be forward referenced.
638 bool overflow = false;
639 if (mulu(tbn.size(loc), d2, overflow) >= target.maxStaticDataSize || overflow)
640 return overflowError();
647 // Index the tuple to get the type
649 TypeTuple tt = tbn.isTypeTuple();
650 uinteger_t d = mtype.dim.toUInteger();
651 if (d >= tt.arguments.length)
653 .error(loc, "tuple index `%llu` out of bounds `[0 .. %llu]`", cast(ulong)d, cast(ulong)tt.arguments.length);
656 Type telem = (*tt.arguments)[cast(size_t)d].type;
657 return telem.addMod(mtype.mod);
662 .error(loc, "cannot have array of `%s`", tbn.toChars());
670 .error(loc, "cannot have array of scope `%s`", tbn.toChars());
674 /* Ensure things like const(immutable(T)[3]) become immutable(T[3])
675 * and const(T)[3] become const(T[3])
679 return mtype.addMod(tn.mod).merge();
682 Type visitDArray(TypeDArray mtype)
684 Type tn = mtype.next.typeSemantic(loc, sc);
685 Type tbn = tn.toBasetype();
693 .error(loc, "cannot have array of `%s`", tbn.toChars());
704 .error(loc, "cannot have array of scope `%s`", tn.toChars());
712 Type visitAArray(TypeAArray mtype)
714 //printf("TypeAArray::semantic() %s index.ty = %d\n", mtype.toChars(), mtype.index.ty);
724 // Deal with the case where we thought the index was a type, but
725 // in reality it was an expression.
726 if (mtype.index.ty == Tident || mtype.index.ty == Tinstance || mtype.index.ty == Tsarray || mtype.index.ty == Ttypeof || mtype.index.ty == Treturn || mtype.index.ty == Tmixin)
731 mtype.index.resolve(loc, sc, e, t, s);
733 // https://issues.dlang.org/show_bug.cgi?id=15478
735 e = symbolToExp(s, loc, sc, false);
739 // It was an expression -
740 // Rewrite as a static array
741 auto tsa = new TypeSArray(mtype.next, e);
742 return tsa.typeSemantic(loc, sc);
745 mtype.index = t.typeSemantic(loc, sc);
748 .error(loc, "index is not a type or an expression");
753 mtype.index = mtype.index.typeSemantic(loc, sc);
754 mtype.index = mtype.index.merge2();
756 if (mtype.index.nextOf() && !mtype.index.nextOf().isImmutable())
758 mtype.index = mtype.index.constOf().mutableOf();
761 printf("index is %p %s\n", mtype.index, mtype.index.toChars());
763 printf("index.mod = x%x\n", mtype.index.mod);
764 printf("index.ito = x%p\n", mtype.index.getMcache().ito);
765 if (mtype.index.getMcache().ito)
767 printf("index.ito.mod = x%x\n", mtype.index.getMcache().ito.mod);
768 printf("index.ito.ito = x%p\n", mtype.index.getMcache().ito.getMcache().ito);
773 switch (mtype.index.toBasetype().ty)
779 .error(loc, "cannot have associative array key of `%s`", mtype.index.toBasetype().toChars());
787 Type tbase = mtype.index.baseElemOf();
788 while (tbase.ty == Tarray)
789 tbase = tbase.nextOf().baseElemOf();
790 if (auto ts = tbase.isTypeStruct())
792 /* AA's need typeid(index).equals() and getHash(). Issue error if not correctly set up.
794 StructDeclaration sd = ts.sym;
795 if (sd.semanticRun < PASS.semanticdone)
796 sd.dsymbolSemantic(null);
798 // duplicate a part of StructDeclaration::semanticTypeInfoMembers
799 //printf("AA = %s, key: xeq = %p, xerreq = %p xhash = %p\n", toChars(), sd.xeq, sd.xerreq, sd.xhash);
801 if (sd.xeq && sd.xeq.isGenerated() && sd.xeq._scope && sd.xeq.semanticRun < PASS.semantic3done)
803 uint errors = global.startGagging();
804 sd.xeq.semantic3(sd.xeq._scope);
805 if (global.endGagging(errors))
810 //printf("AA = %s, key: xeq = %p, xhash = %p\n", toChars(), sd.xeq, sd.xhash);
811 const(char)* s = (mtype.index.toBasetype().ty != Tstruct) ? "bottom of " : "";
814 // If sd.xhash != NULL:
815 // sd or its fields have user-defined toHash.
816 // AA assumes that its result is consistent with bitwise equality.
818 // bitwise equality & hashing
820 else if (sd.xeq == sd.xerreq)
822 if (search_function(sd, Id.eq))
824 .error(loc, "%sAA key type `%s` does not have `bool opEquals(ref const %s) const`", s, sd.toChars(), sd.toChars());
828 .error(loc, "%sAA key type `%s` does not support const equality", s, sd.toChars());
834 if (search_function(sd, Id.eq))
836 .error(loc, "%sAA key type `%s` should have `extern (D) size_t toHash() const nothrow @safe` if `opEquals` defined", s, sd.toChars());
840 .error(loc, "%sAA key type `%s` supports const equality but doesn't support const hashing", s, sd.toChars());
846 // defined equality & hashing
847 assert(sd.xeq && sd.xhash);
849 /* xeq and xhash may be implicitly defined by compiler. For example:
850 * struct S { int[] arr; }
851 * With 'arr' field equality and hashing, compiler will implicitly
852 * generate functions for xopEquals and xtoHash in TypeInfo_Struct.
856 else if (tbase.ty == Tclass && !tbase.isTypeClass().sym.isInterfaceDeclaration())
858 ClassDeclaration cd = tbase.isTypeClass().sym;
859 if (cd.semanticRun < PASS.semanticdone)
860 cd.dsymbolSemantic(null);
862 if (!ClassDeclaration.object)
864 .error(Loc.initial, "missing or corrupt object.d");
868 __gshared FuncDeclaration feq = null;
869 __gshared FuncDeclaration fcmp = null;
870 __gshared FuncDeclaration fhash = null;
872 feq = search_function(ClassDeclaration.object, Id.eq).isFuncDeclaration();
874 fcmp = search_function(ClassDeclaration.object, Id.cmp).isFuncDeclaration();
876 fhash = search_function(ClassDeclaration.object, Id.tohash).isFuncDeclaration();
877 assert(fcmp && feq && fhash);
879 if (feq.vtblIndex < cd.vtbl.length && cd.vtbl[feq.vtblIndex] == feq)
883 if (fcmp.vtblIndex < cd.vtbl.length && cd.vtbl[fcmp.vtblIndex] != fcmp)
885 const(char)* s = (mtype.index.toBasetype().ty != Tclass) ? "bottom of " : "";
886 .error(loc, "%sAA key type `%s` now requires equality rather than comparison", s, cd.toChars());
887 errorSupplemental(loc, "Please override `Object.opEquals` and `Object.toHash`.");
892 mtype.next = mtype.next.typeSemantic(loc, sc).merge2();
895 switch (mtype.next.toBasetype().ty)
901 .error(loc, "cannot have associative array of `%s`", mtype.next.toChars());
908 if (mtype.next.isscope())
910 .error(loc, "cannot have array of scope `%s`", mtype.next.toChars());
916 Type visitPointer(TypePointer mtype)
918 //printf("TypePointer::semantic() %s\n", toChars());
923 Type n = mtype.next.typeSemantic(loc, sc);
924 switch (n.toBasetype().ty)
927 .error(loc, "cannot have pointer to `%s`", n.toChars());
939 if (mtype.next.ty != Tfunction)
950 mtype.deco = merge(mtype).deco;
951 /* Don't return merge(), because arg identifiers and default args
953 * even though the types match
959 Type visitReference(TypeReference mtype)
961 //printf("TypeReference::semantic()\n");
962 Type n = mtype.next.typeSemantic(loc, sc);
970 Type visitFunction(TypeFunction mtype)
972 if (mtype.deco) // if semantic() already run
974 //printf("already done\n");
977 //printf("TypeFunction::semantic() this = %p\n", mtype);
978 //printf("TypeFunction::semantic() %s, sc.stc = %llx\n", mtype.toChars(), sc.stc);
982 if (mtype.inuse > global.recursionLimit)
985 .error(loc, "recursive type");
989 /* Copy in order to not mess up original.
990 * This can produce redundant copies if inferring return type,
991 * as semantic() will get called again on this.
993 TypeFunction tf = mtype.copy().toTypeFunction();
994 if (mtype.parameterList.parameters)
996 tf.parameterList.parameters = mtype.parameterList.parameters.copy();
997 for (size_t i = 0; i < mtype.parameterList.parameters.length; i++)
999 Parameter p = cast(Parameter)mem.xmalloc(__traits(classInstanceSize, Parameter));
1000 memcpy(cast(void*)p, cast(void*)(*mtype.parameterList.parameters)[i], __traits(classInstanceSize, Parameter));
1001 (*tf.parameterList.parameters)[i] = p;
1005 if (sc.stc & STC.pure_)
1006 tf.purity = PURE.fwdref;
1007 if (sc.stc & STC.nothrow_)
1008 tf.isnothrow = true;
1009 if (sc.stc & STC.nogc)
1011 if (sc.stc & STC.ref_)
1013 if (sc.stc & STC.return_)
1015 if (sc.stc & STC.returnScope)
1016 tf.isreturnscope = true;
1017 if (sc.stc & STC.returninferred)
1018 tf.isreturninferred = true;
1019 if (sc.stc & STC.scope_)
1020 tf.isScopeQual = true;
1021 if (sc.stc & STC.scopeinferred)
1022 tf.isscopeinferred = true;
1024 // if (tf.isreturn && !tf.isref)
1025 // tf.isScopeQual = true; // return by itself means 'return scope'
1027 if (tf.trust == TRUST.default_)
1029 if (sc.stc & STC.safe)
1030 tf.trust = TRUST.safe;
1031 else if (sc.stc & STC.system)
1032 tf.trust = TRUST.system;
1033 else if (sc.stc & STC.trusted)
1034 tf.trust = TRUST.trusted;
1037 if (sc.stc & STC.property)
1038 tf.isproperty = true;
1039 if (sc.stc & STC.live)
1042 tf.linkage = sc.linkage;
1043 if (tf.linkage == LINK.system)
1044 tf.linkage = target.systemLinkage();
1048 /* If the parent is @safe, then this function defaults to safe
1050 * If the parent's @safe-ty is inferred, then this function's @safe-ty needs
1051 * to be inferred first.
1053 if (tf.trust == TRUST.default_)
1054 for (Dsymbol p = sc.func; p; p = p.toParent2())
1056 FuncDeclaration fd = p.isFuncDeclaration();
1059 if (fd.isSafeBypassingInference())
1060 tf.trust = TRUST.safe; // default to @safe
1066 bool wildreturn = false;
1070 sc.stc &= ~(STC.TYPECTOR | STC.FUNCATTR);
1071 tf.next = tf.next.typeSemantic(loc, sc);
1073 errors |= tf.checkRetType(loc);
1074 if (tf.next.isscope() && !tf.isctor)
1076 .error(loc, "functions cannot return `scope %s`", tf.next.toChars());
1079 if (tf.next.hasWild())
1082 if (tf.isreturn && !tf.isref && !tf.next.hasPointers())
1084 tf.isreturn = false;
1088 /// Perform semantic on the default argument to a parameter
1089 /// Modify the `defaultArg` field of `fparam`, which must not be `null`
1090 /// Returns `false` whether an error was encountered.
1091 static bool defaultArgSemantic (ref Parameter fparam, Scope* sc)
1093 Expression e = fparam.defaultArg;
1094 const isRefOrOut = fparam.isReference();
1095 const isAuto = fparam.storageClass & (STC.auto_ | STC.autoref);
1096 if (isRefOrOut && !isAuto)
1098 e = e.expressionSemantic(sc);
1099 e = resolveProperties(sc, e);
1103 e = inferType(e, fparam.type);
1104 Initializer iz = new ExpInitializer(e.loc, e);
1105 iz = iz.initializerSemantic(sc, fparam.type, INITnointerpret);
1106 e = iz.initializerToExpression();
1108 if (e.op == EXP.function_) // https://issues.dlang.org/show_bug.cgi?id=4820
1110 FuncExp fe = e.isFuncExp();
1111 // Replace function literal with a function symbol,
1112 // since default arg expression must be copied when used
1113 // and copying the literal itself is wrong.
1114 e = new VarExp(e.loc, fe.fd, false);
1115 e = new AddrExp(e.loc, e);
1116 e = e.expressionSemantic(sc);
1118 if (isRefOrOut && (!isAuto || e.isLvalue())
1119 && !MODimplicitConv(e.type.mod, fparam.type.mod))
1121 const(char)* errTxt = fparam.storageClass & STC.ref_ ? "ref" : "out";
1122 .error(e.loc, "expression `%s` of type `%s` is not implicitly convertible to type `%s %s` of parameter `%s`",
1123 e.toChars(), e.type.toChars(), errTxt, fparam.type.toChars(), fparam.toChars());
1125 e = e.implicitCastTo(sc, fparam.type);
1127 // default arg must be an lvalue
1128 if (isRefOrOut && !isAuto &&
1129 !(global.params.previewIn && (fparam.storageClass & STC.in_)) &&
1130 global.params.rvalueRefParam != FeatureState.enabled)
1131 e = e.toLvalue(sc, e);
1133 fparam.defaultArg = e;
1134 return (e.op != EXP.error);
1137 ubyte wildparams = 0;
1138 if (tf.parameterList.parameters)
1140 /* Create a scope for evaluating the default arguments for the parameters
1142 Scope* argsc = sc.push();
1143 argsc.stc = 0; // don't inherit storage class
1144 argsc.visibility = Visibility(Visibility.Kind.public_);
1147 size_t dim = tf.parameterList.length;
1148 for (size_t i = 0; i < dim; i++)
1150 Parameter fparam = tf.parameterList[i];
1151 fparam.storageClass |= STC.parameter;
1153 fparam.type = fparam.type.typeSemantic(loc, argsc);
1156 if (fparam.type.ty == Terror)
1162 fparam.type = fparam.type.addStorageClass(fparam.storageClass);
1164 if (fparam.storageClass & (STC.auto_ | STC.alias_ | STC.static_))
1170 fparam.type = fparam.type.cAdjustParamType(sc); // adjust C array and function parameter types
1172 Type t = fparam.type.toBasetype();
1174 /* If fparam after semantic() turns out to be a tuple, the number of parameters may
1177 if (auto tt = t.isTypeTuple())
1179 /* TypeFunction::parameter also is used as the storage of
1180 * Parameter objects for FuncDeclaration. So we should copy
1181 * the elements of TypeTuple::arguments to avoid unintended
1182 * sharing of Parameter object among other functions.
1184 if (tt.arguments && tt.arguments.length)
1186 /* Propagate additional storage class from tuple parameters to their
1187 * element-parameters.
1188 * Make a copy, as original may be referenced elsewhere.
1190 size_t tdim = tt.arguments.length;
1191 auto newparams = new Parameters(tdim);
1192 for (size_t j = 0; j < tdim; j++)
1194 Parameter narg = (*tt.arguments)[j];
1196 // https://issues.dlang.org/show_bug.cgi?id=12744
1197 // If the storage classes of narg
1198 // conflict with the ones in fparam, it's ignored.
1199 StorageClass stc = fparam.storageClass | narg.storageClass;
1200 StorageClass stc1 = fparam.storageClass & (STC.ref_ | STC.out_ | STC.lazy_);
1201 StorageClass stc2 = narg.storageClass & (STC.ref_ | STC.out_ | STC.lazy_);
1202 if (stc1 && stc2 && stc1 != stc2)
1204 OutBuffer buf1; stcToBuffer(&buf1, stc1 | ((stc1 & STC.ref_) ? (fparam.storageClass & STC.auto_) : 0));
1205 OutBuffer buf2; stcToBuffer(&buf2, stc2);
1207 .error(loc, "incompatible parameter storage classes `%s` and `%s`",
1208 buf1.peekChars(), buf2.peekChars());
1210 stc = stc1 | (stc & ~(STC.ref_ | STC.out_ | STC.lazy_));
1212 (*newparams)[j] = new Parameter(
1213 stc, narg.type, narg.ident, narg.defaultArg, narg.userAttribDecl);
1215 fparam.type = new TypeTuple(newparams);
1216 fparam.type = fparam.type.typeSemantic(loc, argsc);
1218 fparam.storageClass = STC.parameter;
1220 /* Reset number of parameters, and back up one to do this fparam again,
1221 * now that it is a tuple
1223 dim = tf.parameterList.length;
1228 // -preview=in: Always add `ref` when used with `extern(C++)` functions
1229 // Done here to allow passing opaque types with `in`
1230 if (global.params.previewIn && (fparam.storageClass & (STC.in_ | STC.ref_)) == STC.in_)
1235 fparam.storageClass |= STC.ref_;
1237 case LINK.default_, LINK.d:
1240 .error(loc, "cannot use `in` parameters with `extern(%s)` functions",
1241 linkageToChars(tf.linkage));
1242 .errorSupplemental(loc, "parameter `%s` declared as `in` here", fparam.toChars());
1247 if (t.ty == Tfunction)
1249 .error(loc, "cannot have parameter of function type `%s`", fparam.type.toChars());
1252 else if (!fparam.isReference() &&
1253 (t.ty == Tstruct || t.ty == Tsarray || t.ty == Tenum))
1255 Type tb2 = t.baseElemOf();
1256 if (tb2.ty == Tstruct && !tb2.isTypeStruct().sym.members ||
1257 tb2.ty == Tenum && !tb2.isTypeEnum().sym.memtype)
1259 if (global.params.previewIn && (fparam.storageClass & STC.in_))
1261 .error(loc, "cannot infer `ref` for `in` parameter `%s` of opaque type `%s`",
1262 fparam.toChars(), fparam.type.toChars());
1265 .error(loc, "cannot have parameter of opaque type `%s` by value",
1266 fparam.type.toChars());
1270 else if (!fparam.isLazy() && t.ty == Tvoid)
1272 .error(loc, "cannot have parameter of type `%s`", fparam.type.toChars());
1276 const bool isTypesafeVariadic = i + 1 == dim &&
1277 tf.parameterList.varargs == VarArg.typesafe &&
1278 (t.isTypeDArray() || t.isTypeClass());
1279 if (isTypesafeVariadic)
1281 /* typesafe variadic arguments are constructed on the stack, so must be `scope`
1283 fparam.storageClass |= STC.scope_ | STC.scopeinferred;
1286 if (fparam.storageClass & STC.return_)
1288 if (fparam.isReference())
1290 // Disabled for the moment awaiting improvement to allow return by ref
1291 // to be transformed into return by scope.
1294 auto stc = fparam.storageClass & (STC.ref_ | STC.out_);
1295 .error(loc, "parameter `%s` is `return %s` but function does not return by `ref`",
1296 fparam.ident ? fparam.ident.toChars() : "",
1297 stcToString(stc).ptr);
1303 if (!(fparam.storageClass & STC.scope_))
1304 fparam.storageClass |= STC.scope_ | STC.scopeinferred; // 'return' implies 'scope'
1308 else if (tf.next && !tf.next.hasPointers() && tf.next.toBasetype().ty != Tvoid)
1310 fparam.storageClass &= ~STC.return_; // https://issues.dlang.org/show_bug.cgi?id=18963
1314 if (isTypesafeVariadic)
1316 /* This is because they can be constructed on the stack
1317 * https://dlang.org/spec/function.html#typesafe_variadic_functions
1319 .error(loc, "typesafe variadic function parameter `%s` of type `%s` cannot be marked `return`",
1320 fparam.ident ? fparam.ident.toChars() : "", t.toChars());
1325 if (fparam.storageClass & STC.out_)
1327 if (ubyte m = fparam.type.mod & (MODFlags.immutable_ | MODFlags.const_ | MODFlags.wild))
1329 .error(loc, "cannot have `%s out` parameter of type `%s`", MODtoChars(m), t.toChars());
1334 Type tv = t.baseElemOf();
1335 if (tv.ty == Tstruct && tv.isTypeStruct().sym.noDefaultCtor)
1337 .error(loc, "cannot have `out` parameter of type `%s` because the default construction is disabled", fparam.type.toChars());
1346 //if (tf.next && !wildreturn)
1347 // error(loc, "inout on parameter means inout must be on return type as well (if from D1 code, replace with `ref`)");
1350 /* Scope attribute is not necessary if the parameter type does not have pointers
1352 const sr = buildScopeRef(fparam.storageClass);
1355 case ScopeRef.Scope:
1356 case ScopeRef.RefScope:
1357 case ScopeRef.ReturnRef_Scope:
1358 if (!fparam.type.hasPointers())
1359 fparam.storageClass &= ~STC.scope_;
1362 case ScopeRef.ReturnScope:
1363 case ScopeRef.Ref_ReturnScope:
1364 if (!fparam.type.hasPointers())
1365 fparam.storageClass &= ~(STC.return_ | STC.scope_ | STC.returnScope);
1372 // Remove redundant storage classes for type, they are already applied
1373 fparam.storageClass &= ~(STC.TYPECTOR);
1375 // -preview=in: add `ref` storage class to suited `in` params
1376 if (global.params.previewIn && (fparam.storageClass & (STC.in_ | STC.ref_)) == STC.in_)
1378 auto ts = t.baseElemOf().isTypeStruct();
1379 const isPOD = !ts || ts.sym.isPOD();
1380 if (!isPOD || target.preferPassByRef(t))
1381 fparam.storageClass |= STC.ref_;
1385 // Now that we completed semantic for the argument types,
1386 // run semantic on their default values,
1387 // bearing in mind tuples have been expanded.
1388 // We need to keep a pair of [oidx, eidx] (original index,
1389 // extended index), as we need to run semantic when `oidx` changes.
1390 size_t tupleOrigIdx = size_t.max;
1391 size_t tupleExtIdx = size_t.max;
1393 foreach (oidx, oparam, eidx, eparam; tf.parameterList)
1395 // oparam (original param) will always have the default arg
1396 // if there's one, but `eparam` will not if it's an expanded
1397 // tuple. When we see an expanded tuple, we need to save its
1398 // position to get the offset in it later on.
1399 if (oparam.defaultArg)
1402 // Get the obvious case out of the way
1403 if (oparam is eparam)
1404 errors |= !defaultArgSemantic(eparam, argsc);
1405 // We're seeing a new tuple
1406 else if (tupleOrigIdx == size_t.max || tupleOrigIdx < oidx)
1408 /* https://issues.dlang.org/show_bug.cgi?id=18572
1410 * If a tuple parameter has a default argument, when expanding the parameter
1411 * tuple the default argument tuple must also be expanded.
1413 tupleOrigIdx = oidx;
1415 errors |= !defaultArgSemantic(oparam, argsc);
1416 TupleExp te = oparam.defaultArg.isTupleExp();
1417 if (te && te.exps && te.exps.length)
1418 eparam.defaultArg = (*te.exps)[0];
1420 // Processing an already-seen tuple
1423 TupleExp te = oparam.defaultArg.isTupleExp();
1424 if (te && te.exps && te.exps.length)
1425 eparam.defaultArg = (*te.exps)[eidx - tupleExtIdx];
1428 else if (hasDefault)
1430 .error(loc, "default argument expected for `%s`", oparam.toChars());
1434 // We need to know the default argument to resolve `auto ref`,
1435 // hence why this has to take place as the very last step.
1436 /* Resolve "auto ref" storage class to be either ref or value,
1437 * based on the argument matching the parameter
1439 if (eparam.storageClass & STC.auto_)
1441 Expression farg = mtype.fargs && eidx < mtype.fargs.length ?
1442 (*mtype.fargs)[eidx] : eparam.defaultArg;
1443 if (farg && (eparam.storageClass & STC.ref_))
1445 if (!farg.isLvalue())
1446 eparam.storageClass &= ~STC.ref_; // value parameter
1447 eparam.storageClass &= ~STC.auto_; // https://issues.dlang.org/show_bug.cgi?id=14656
1448 eparam.storageClass |= STC.autoref;
1450 else if (mtype.incomplete && (eparam.storageClass & STC.ref_))
1452 // the default argument may have been temporarily removed,
1453 // see usage of `TypeFunction.incomplete`.
1454 // https://issues.dlang.org/show_bug.cgi?id=19891
1455 eparam.storageClass &= ~STC.auto_;
1456 eparam.storageClass |= STC.autoref;
1458 else if (eparam.storageClass & STC.ref_)
1460 .error(loc, "cannot explicitly instantiate template function with `auto ref` parameter");
1465 .error(loc, "`auto` can only be used as part of `auto ref` for template function parameters");
1476 if (wildreturn && !wildparams)
1478 .error(loc, "`inout` on `return` means `inout` must be on a parameter as well for `%s`", mtype.toChars());
1481 tf.isInOutParam = (wildparams & 1) != 0;
1482 tf.isInOutQual = (wildparams & 2) != 0;
1484 if (tf.isproperty && (tf.parameterList.varargs != VarArg.none || tf.parameterList.length > 2))
1486 .error(loc, "properties can only have zero, one, or two parameter");
1490 if (tf.parameterList.varargs == VarArg.variadic && tf.linkage != LINK.d && tf.parameterList.length == 0 &&
1491 !(sc.flags & SCOPE.Cfile))
1493 .error(loc, "variadic functions with non-D linkage must have at least one parameter");
1501 tf.deco = tf.merge().deco;
1503 /* Don't return merge(), because arg identifiers and default args
1505 * even though the types match
1510 Type visitDelegate(TypeDelegate mtype)
1512 //printf("TypeDelegate::semantic() %s\n", mtype.toChars());
1513 if (mtype.deco) // if semantic() already run
1515 //printf("already done\n");
1518 mtype.next = mtype.next.typeSemantic(loc, sc);
1519 if (mtype.next.ty != Tfunction)
1522 /* In order to deal with https://issues.dlang.org/show_bug.cgi?id=4028
1523 * perhaps default arguments should
1524 * be removed from next before the merge.
1528 return mtype.merge();
1532 /* Don't return merge(), because arg identifiers and default args
1534 * even though the types match
1536 mtype.deco = mtype.merge().deco;
1541 Type visitIdentifier(TypeIdentifier mtype)
1546 //printf("TypeIdentifier::semantic(%s)\n", mtype.toChars());
1547 mtype.resolve(loc, sc, e, t, s);
1550 //printf("\tit's a type %d, %s, %s\n", t.ty, t.toChars(), t.deco);
1551 return t.addMod(mtype.mod);
1557 auto td = s.isTemplateDeclaration;
1558 if (td && td.onemember && td.onemember.isAggregateDeclaration)
1559 .error(loc, "template %s `%s` is used as a type without instantiation"
1560 ~ "; to instantiate it use `%s!(arguments)`",
1561 s.kind, s.toPrettyChars, s.ident.toChars);
1563 .error(loc, "%s `%s` is used as a type", s.kind, s.toPrettyChars);
1566 else if (e.op == EXP.variable) // special case: variable is used as a type
1569 N.B. This branch currently triggers for the following code
1574 i.e. the compiler prints "variable x is used as a type"
1575 which isn't a particularly good error message (x is a variable?).
1577 Dsymbol varDecl = mtype.toDsymbol(sc);
1578 const(Loc) varDeclLoc = varDecl.getLoc();
1579 Module varDeclModule = varDecl.getModule(); //This can be null
1581 .error(loc, "variable `%s` is used as a type", mtype.toChars());
1582 //Check for null to avoid https://issues.dlang.org/show_bug.cgi?id=22574
1583 if ((varDeclModule !is null) && varDeclModule != sc._module) // variable is imported
1585 const(Loc) varDeclModuleImportLoc = varDeclModule.getLoc();
1587 varDeclModuleImportLoc,
1588 "variable `%s` is imported here from: `%s`",
1590 varDeclModule.toPrettyChars,
1594 .errorSupplemental(varDeclLoc, "variable `%s` is declared here", varDecl.toChars);
1597 .error(loc, "`%s` is used as a type", mtype.toChars());
1602 Type visitInstance(TypeInstance mtype)
1608 //printf("TypeInstance::semantic(%p, %s)\n", this, toChars());
1610 const errors = global.errors;
1611 mtype.resolve(loc, sc, e, t, s);
1612 // if we had an error evaluating the symbol, suppress further errors
1613 if (!t && errors != global.errors)
1619 if (!e && s && s.errors)
1621 // if there was an error evaluating the symbol, it might actually
1622 // be a type. Avoid misleading error messages.
1623 .error(loc, "`%s` had previous errors", mtype.toChars());
1626 .error(loc, "`%s` is used as a type", mtype.toChars());
1632 Type visitTypeof(TypeTypeof mtype)
1634 //printf("TypeTypeof::semantic() %s\n", mtype.toChars());
1638 mtype.resolve(loc, sc, e, t, s);
1639 if (s && (t = s.getType()) !is null)
1640 t = t.addMod(mtype.mod);
1643 .error(loc, "`%s` is used as a type", mtype.toChars());
1649 Type visitTraits(TypeTraits mtype)
1654 mtype.resolve(loc, sc, e, t, s);
1659 .error(mtype.loc, "`%s` does not give a valid type", mtype.toChars);
1665 Type visitReturn(TypeReturn mtype)
1667 //printf("TypeReturn::semantic() %s\n", toChars());
1671 mtype.resolve(loc, sc, e, t, s);
1672 if (s && (t = s.getType()) !is null)
1673 t = t.addMod(mtype.mod);
1676 .error(loc, "`%s` is used as a type", mtype.toChars());
1682 Type visitStruct(TypeStruct mtype)
1684 //printf("TypeStruct::semantic('%s')\n", mtype.toChars());
1688 /* Don't semantic for sym because it should be deferred until
1689 * sizeof needed or its members accessed.
1691 // instead, parent should be set correctly
1692 assert(mtype.sym.parent);
1694 if (mtype.sym.type.ty == Terror)
1697 return merge(mtype);
1700 Type visitEnum(TypeEnum mtype)
1702 //printf("TypeEnum::semantic() %s\n", toChars());
1703 return mtype.deco ? mtype : merge(mtype);
1706 Type visitClass(TypeClass mtype)
1708 //printf("TypeClass::semantic(%s)\n", mtype.toChars());
1712 /* Don't semantic for sym because it should be deferred until
1713 * sizeof needed or its members accessed.
1715 // instead, parent should be set correctly
1716 assert(mtype.sym.parent);
1718 if (mtype.sym.type.ty == Terror)
1721 return merge(mtype);
1724 Type visitTuple(TypeTuple mtype)
1726 //printf("TypeTuple::semantic(this = %p)\n", this);
1727 //printf("TypeTuple::semantic() %p, %s\n", this, toChars());
1729 mtype.deco = merge(mtype).deco;
1731 /* Don't return merge(), because a tuple with one type has the
1732 * same deco as that type.
1737 Type visitSlice(TypeSlice mtype)
1739 //printf("TypeSlice::semantic() %s\n", toChars());
1740 Type tn = mtype.next.typeSemantic(loc, sc);
1741 //printf("next: %s\n", tn.toChars());
1743 Type tbn = tn.toBasetype();
1744 if (tbn.ty != Ttuple)
1746 .error(loc, "can only slice tuple types, not `%s`", tbn.toChars());
1749 TypeTuple tt = cast(TypeTuple)tbn;
1751 mtype.lwr = semanticLength(sc, tbn, mtype.lwr);
1752 mtype.upr = semanticLength(sc, tbn, mtype.upr);
1753 mtype.lwr = mtype.lwr.ctfeInterpret();
1754 mtype.upr = mtype.upr.ctfeInterpret();
1755 if (mtype.lwr.op == EXP.error || mtype.upr.op == EXP.error)
1758 uinteger_t i1 = mtype.lwr.toUInteger();
1759 uinteger_t i2 = mtype.upr.toUInteger();
1760 if (!(i1 <= i2 && i2 <= tt.arguments.length))
1762 .error(loc, "slice `[%llu..%llu]` is out of range of `[0..%llu]`",
1763 cast(ulong)i1, cast(ulong)i2, cast(ulong)tt.arguments.length);
1770 auto args = new Parameters();
1771 args.reserve(cast(size_t)(i2 - i1));
1772 foreach (arg; (*tt.arguments)[cast(size_t)i1 .. cast(size_t)i2])
1776 Type t = new TypeTuple(args);
1777 return t.typeSemantic(loc, sc);
1780 Type visitMixin(TypeMixin mtype)
1782 //printf("TypeMixin::semantic() %s\n", toChars());
1787 mtype.resolve(loc, sc, e, t, s);
1789 if (t && t.ty != Terror)
1792 .error(mtype.loc, "`mixin(%s)` does not give a valid type", mtype.obj.toChars);
1796 Type visitTag(TypeTag mtype)
1798 //printf("TypeTag.semantic() %s\n", mtype.toChars());
1803 return mtype.resolved.addSTC(mtype.mod);
1806 /* Find the current scope by skipping tag scopes.
1807 * In C, tag scopes aren't considered scopes.
1813 auto scopesym = sc2.scopesym;
1814 if (scopesym.isStructDeclaration())
1816 sc2 = sc2.enclosing;
1822 /* Declare mtype as a struct/union/enum declaration
1826 void declare(ScopeDsymbol sd)
1828 sd.members = mtype.members;
1829 auto scopesym = sc2.inner().scopesym;
1830 if (scopesym.members)
1831 scopesym.members.push(sd);
1832 if (scopesym.symtab && !scopesym.symtabInsert(sd))
1834 Dsymbol s2 = scopesym.symtabLookup(sd, mtype.id);
1835 handleTagSymbols(*sc2, sd, s2, scopesym);
1837 sd.parent = sc2.parent;
1838 sd.dsymbolSemantic(sc2);
1844 auto ed = new EnumDeclaration(mtype.loc, mtype.id, mtype.base);
1846 mtype.resolved = visitEnum(new TypeEnum(ed));
1850 auto sd = new StructDeclaration(mtype.loc, mtype.id, false);
1852 mtype.resolved = visitStruct(new TypeStruct(sd));
1856 auto ud = new UnionDeclaration(mtype.loc, mtype.id);
1858 mtype.resolved = visitStruct(new TypeStruct(ud));
1866 /* If it doesn't have a tag by now, supply one.
1867 * It'll be unique, and therefore introducing.
1868 * Declare it, and done.
1872 mtype.id = Identifier.generateId("__tag"[]);
1874 return mtype.resolved.addSTC(mtype.mod);
1877 /* look for pre-existing declaration
1880 auto s = sc2.search(mtype.loc, mtype.id, &scopesym, IgnoreErrors | TagNameSpace);
1881 if (!s || s.isModule())
1883 // no pre-existing declaration, so declare it
1884 if (mtype.tok == TOK.enum_ && !mtype.members)
1885 .error(mtype.loc, "`enum %s` is incomplete without members", mtype.id.toChars()); // C11 6.7.2.3-3
1887 return mtype.resolved.addSTC(mtype.mod);
1890 /* A redeclaration only happens if both declarations are in
1893 const bool redeclar = (scopesym == sc2.inner().scopesym);
1897 if (mtype.tok == TOK.enum_ && s.isEnumDeclaration())
1899 auto ed = s.isEnumDeclaration();
1900 if (mtype.members && ed.members)
1901 .error(mtype.loc, "`%s` already has members", mtype.id.toChars());
1902 else if (!ed.members)
1904 ed.members = mtype.members;
1909 mtype.resolved = ed.type;
1911 else if (mtype.tok == TOK.union_ && s.isUnionDeclaration() ||
1912 mtype.tok == TOK.struct_ && s.isStructDeclaration())
1914 // Add members to original declaration
1915 auto sd = s.isStructDeclaration();
1916 if (mtype.members && sd.members)
1918 /* struct S { int b; };
1919 * struct S { int a; } *s;
1921 .error(mtype.loc, "`%s` already has members", mtype.id.toChars());
1923 else if (!sd.members)
1926 * struct S { int a; } *s;
1928 sd.members = mtype.members;
1929 if (sd.semanticRun == PASS.semanticdone)
1931 /* The first semantic pass marked `sd` as an opaque struct.
1932 * Re-run semantic so that all newly assigned members are
1933 * picked up and added to the symtab.
1935 sd.semanticRun = PASS.semantic;
1936 sd.dsymbolSemantic(sc2);
1941 /* struct S { int a; };
1945 mtype.resolved = sd.type;
1950 * struct S { int a; } *s;
1952 .error(mtype.loc, "redeclaration of `%s`", mtype.id.toChars());
1953 mtype.resolved = error();
1956 else if (mtype.members)
1959 * { struct S { int a; } *s; }
1965 if (mtype.tok == TOK.enum_ && s.isEnumDeclaration())
1967 mtype.resolved = s.isEnumDeclaration().type;
1969 else if (mtype.tok == TOK.union_ && s.isUnionDeclaration() ||
1970 mtype.tok == TOK.struct_ && s.isStructDeclaration())
1975 mtype.resolved = s.isStructDeclaration().type;
1982 .error(mtype.loc, "redeclaring `%s %s` as `%s %s`",
1983 s.kind(), s.toChars(), Token.toChars(mtype.tok), mtype.id.toChars());
1987 return mtype.resolved.addSTC(mtype.mod);
1992 default: return visitType(type);
1993 case Tvector: return visitVector(type.isTypeVector());
1994 case Tsarray: return visitSArray(type.isTypeSArray());
1995 case Tarray: return visitDArray(type.isTypeDArray());
1996 case Taarray: return visitAArray(type.isTypeAArray());
1997 case Tpointer: return visitPointer(type.isTypePointer());
1998 case Treference: return visitReference(type.isTypeReference());
1999 case Tfunction: return visitFunction(type.isTypeFunction());
2000 case Tdelegate: return visitDelegate(type.isTypeDelegate());
2001 case Tident: return visitIdentifier(type.isTypeIdentifier());
2002 case Tinstance: return visitInstance(type.isTypeInstance());
2003 case Ttypeof: return visitTypeof(type.isTypeTypeof());
2004 case Ttraits: return visitTraits(type.isTypeTraits());
2005 case Treturn: return visitReturn(type.isTypeReturn());
2006 case Tstruct: return visitStruct(type.isTypeStruct());
2007 case Tenum: return visitEnum(type.isTypeEnum());
2008 case Tclass: return visitClass(type.isTypeClass());
2009 case Ttuple: return visitTuple(type.isTypeTuple());
2010 case Tslice: return visitSlice(type.isTypeSlice());
2011 case Tmixin: return visitMixin(type.isTypeMixin());
2012 case Ttag: return visitTag(type.isTypeTag());
2016 /************************************
2017 * If an identical type to `type` is in `type.stringtable`, return
2018 * the latter one. Otherwise, add it to `type.stringtable`.
2019 * Some types don't get merged and are returned as-is.
2021 * type = Type to check against existing types
2023 * the type that was merged
2025 extern (C++) Type merge(Type type)
2035 return type; // don't merge placeholder types
2038 // prevents generating the mangle if the array dim is not yet known
2039 if (!type.isTypeSArray().dim.isIntegerExp())
2047 if (!type.isTypeAArray().index.merge().deco)
2052 if (type.nextOf() && !type.nextOf().deco)
2057 //printf("merge(%s)\n", toChars());
2063 mangleToBuffer(type, &buf);
2065 auto sv = type.stringtable.update(buf[]);
2071 import core.stdc.stdio;
2073 printf("t = %s\n", t.toChars());
2076 //printf("old value, deco = '%s' %p\n", t.deco, t.deco);
2081 Type t = stripDefaultArgs(type);
2083 type.deco = t.deco = cast(char*)sv.toDchars();
2084 //printf("new value, deco = '%s' %p\n", t.deco, t.deco);
2091 /***************************************
2092 * Calculate built-in properties which just the type is necessary.
2095 * t = the type for which the property is calculated
2096 * scope_ = the scope from which the property is being accessed. Used for visibility checks only.
2097 * loc = the location where the property is encountered
2098 * ident = the identifier of the property
2099 * flag = if flag & 1, don't report "not a property" error and just return NULL.
2100 * src = expression for type `t` or null.
2102 * expression representing the property, or null if not a property and (flag & 1)
2104 Expression getProperty(Type t, Scope* scope_, const ref Loc loc, Identifier ident, int flag,
2105 Expression src = null)
2107 Expression visitType(Type mt)
2110 static if (LOGDOTEXP)
2112 printf("Type::getProperty(type = '%s', ident = '%s')\n", mt.toChars(), ident.toChars());
2114 if (ident == Id.__sizeof)
2116 const sz = mt.size(loc);
2117 if (sz == SIZE_INVALID)
2118 return ErrorExp.get();
2119 e = new IntegerExp(loc, sz, Type.tsize_t);
2121 else if (ident == Id.__xalignof)
2123 const explicitAlignment = mt.alignment();
2124 const naturalAlignment = mt.alignsize();
2125 const actualAlignment = (explicitAlignment.isDefault() ? naturalAlignment : explicitAlignment.get());
2126 e = new IntegerExp(loc, actualAlignment, Type.tsize_t);
2128 else if (ident == Id._init)
2130 Type tb = mt.toBasetype();
2131 e = mt.defaultInitLiteral(loc);
2132 if (tb.ty == Tstruct && tb.needsNested())
2134 e.isStructLiteralExp().useStaticInit = true;
2137 else if (ident == Id._mangleof)
2141 error(loc, "forward reference of type `%s.mangleof`", mt.toChars());
2146 e = new StringExp(loc, mt.deco.toDString());
2148 e = e.expressionSemantic(&sc);
2151 else if (ident == Id.stringof)
2153 const s = mt.toChars();
2154 e = new StringExp(loc, s.toDString());
2156 e = e.expressionSemantic(&sc);
2158 else if (flag && mt != Type.terror)
2165 if (mt.ty == Tstruct || mt.ty == Tclass || mt.ty == Tenum)
2166 s = mt.toDsymbol(null);
2168 s = s.search_correct(ident);
2169 if (s && !symbolIsVisible(scope_, s))
2171 if (mt != Type.terror)
2174 error(loc, "no property `%s` for type `%s`, did you mean `%s`?", ident.toChars(), mt.toChars(), s.toPrettyChars());
2175 else if (ident == Id.call && mt.ty == Tclass)
2176 error(loc, "no property `%s` for type `%s`, did you mean `new %s`?", ident.toChars(), mt.toChars(), mt.toPrettyChars());
2178 else if (const n = importHint(ident.toString()))
2179 error(loc, "no property `%s` for type `%s`, perhaps `import %.*s;` is needed?", ident.toChars(), mt.toChars(), cast(int)n.length, n.ptr);
2183 error(loc, "no property `%s` for `%s` of type `%s`", ident.toChars(), src.toChars(), mt.toPrettyChars(true));
2185 error(loc, "no property `%s` for type `%s`", ident.toChars(), mt.toPrettyChars(true));
2186 if (auto dsym = mt.toDsymbol(scope_))
2187 if (auto sym = dsym.isAggregateDeclaration())
2189 if (auto fd = search_function(sym, Id.opDispatch))
2190 errorSupplemental(loc, "potentially malformed `opDispatch`. Use an explicit instantiation to get a better error message");
2191 else if (!sym.members)
2192 errorSupplemental(sym.loc, "`%s %s` is opaque and has no members.", sym.kind, mt.toPrettyChars(true));
2201 Expression visitError(TypeError)
2203 return ErrorExp.get();
2206 Expression visitBasic(TypeBasic mt)
2208 Expression integerValue(dinteger_t i)
2210 return new IntegerExp(loc, i, mt);
2213 Expression intValue(dinteger_t i)
2215 return new IntegerExp(loc, i, Type.tint32);
2218 Expression floatValue(real_t r)
2220 if (mt.isreal() || mt.isimaginary())
2221 return new RealExp(loc, r, mt);
2224 return new ComplexExp(loc, complex_t(r, r), mt);
2228 //printf("TypeBasic::getProperty('%s')\n", ident.toChars());
2229 if (ident == Id.max)
2233 case Tint8: return integerValue(byte.max);
2234 case Tuns8: return integerValue(ubyte.max);
2235 case Tint16: return integerValue(short.max);
2236 case Tuns16: return integerValue(ushort.max);
2237 case Tint32: return integerValue(int.max);
2238 case Tuns32: return integerValue(uint.max);
2239 case Tint64: return integerValue(long.max);
2240 case Tuns64: return integerValue(ulong.max);
2241 case Tbool: return integerValue(bool.max);
2242 case Tchar: return integerValue(char.max);
2243 case Twchar: return integerValue(wchar.max);
2244 case Tdchar: return integerValue(dchar.max);
2247 case Tfloat32: return floatValue(target.FloatProperties.max);
2250 case Tfloat64: return floatValue(target.DoubleProperties.max);
2253 case Tfloat80: return floatValue(target.RealProperties.max);
2257 else if (ident == Id.min)
2261 case Tint8: return integerValue(byte.min);
2269 case Tdchar: return integerValue(0);
2270 case Tint16: return integerValue(short.min);
2271 case Tint32: return integerValue(int.min);
2272 case Tint64: return integerValue(long.min);
2276 else if (ident == Id.min_normal)
2282 case Tfloat32: return floatValue(target.FloatProperties.min_normal);
2285 case Tfloat64: return floatValue(target.DoubleProperties.min_normal);
2288 case Tfloat80: return floatValue(target.RealProperties.min_normal);
2292 else if (ident == Id.nan)
2304 case Tfloat80: return floatValue(target.RealProperties.nan);
2308 else if (ident == Id.infinity)
2320 case Tfloat80: return floatValue(target.RealProperties.infinity);
2324 else if (ident == Id.dig)
2330 case Tfloat32: return intValue(target.FloatProperties.dig);
2333 case Tfloat64: return intValue(target.DoubleProperties.dig);
2336 case Tfloat80: return intValue(target.RealProperties.dig);
2340 else if (ident == Id.epsilon)
2346 case Tfloat32: return floatValue(target.FloatProperties.epsilon);
2349 case Tfloat64: return floatValue(target.DoubleProperties.epsilon);
2352 case Tfloat80: return floatValue(target.RealProperties.epsilon);
2356 else if (ident == Id.mant_dig)
2362 case Tfloat32: return intValue(target.FloatProperties.mant_dig);
2365 case Tfloat64: return intValue(target.DoubleProperties.mant_dig);
2368 case Tfloat80: return intValue(target.RealProperties.mant_dig);
2372 else if (ident == Id.max_10_exp)
2378 case Tfloat32: return intValue(target.FloatProperties.max_10_exp);
2381 case Tfloat64: return intValue(target.DoubleProperties.max_10_exp);
2384 case Tfloat80: return intValue(target.RealProperties.max_10_exp);
2388 else if (ident == Id.max_exp)
2394 case Tfloat32: return intValue(target.FloatProperties.max_exp);
2397 case Tfloat64: return intValue(target.DoubleProperties.max_exp);
2400 case Tfloat80: return intValue(target.RealProperties.max_exp);
2404 else if (ident == Id.min_10_exp)
2410 case Tfloat32: return intValue(target.FloatProperties.min_10_exp);
2413 case Tfloat64: return intValue(target.DoubleProperties.min_10_exp);
2416 case Tfloat80: return intValue(target.RealProperties.min_10_exp);
2420 else if (ident == Id.min_exp)
2426 case Tfloat32: return intValue(target.FloatProperties.min_exp);
2429 case Tfloat64: return intValue(target.DoubleProperties.min_exp);
2432 case Tfloat80: return intValue(target.RealProperties.min_exp);
2436 return visitType(mt);
2439 Expression visitVector(TypeVector mt)
2441 return visitType(mt);
2444 Expression visitEnum(TypeEnum mt)
2447 if (ident == Id.max || ident == Id.min)
2449 return mt.sym.getMaxMinValue(loc, ident);
2451 else if (ident == Id._init)
2453 e = mt.defaultInitLiteral(loc);
2455 else if (ident == Id.stringof)
2457 e = new StringExp(loc, mt.toString());
2459 e = e.expressionSemantic(&sc);
2461 else if (ident == Id._mangleof)
2467 e = mt.toBasetype().getProperty(scope_, loc, ident, flag);
2472 Expression visitTuple(TypeTuple mt)
2475 static if (LOGDOTEXP)
2477 printf("TypeTuple::getProperty(type = '%s', ident = '%s')\n", mt.toChars(), ident.toChars());
2479 if (ident == Id.length)
2481 e = new IntegerExp(loc, mt.arguments.length, Type.tsize_t);
2483 else if (ident == Id._init)
2485 e = mt.defaultInitLiteral(loc);
2493 error(loc, "no property `%s` for tuple `%s`", ident.toChars(), mt.toChars());
2501 default: return t.isTypeBasic() ?
2502 visitBasic(cast(TypeBasic)t) :
2505 case Terror: return visitError (t.isTypeError());
2506 case Tvector: return visitVector(t.isTypeVector());
2507 case Tenum: return visitEnum (t.isTypeEnum());
2508 case Ttuple: return visitTuple (t.isTypeTuple());
2512 /***************************************
2513 * Determine if Expression `exp` should instead be a Type, a Dsymbol, or remain an Expression.
2515 * exp = Expression to look at
2516 * t = if exp should be a Type, set t to that Type else null
2517 * s = if exp should be a Dsymbol, set s to that Dsymbol else null
2518 * e = if exp should remain an Expression, set e to that Expression else null
2521 private void resolveExp(Expression exp, out Type t, out Expression e, out Dsymbol s)
2523 if (exp.isTypeExp())
2525 else if (auto ve = exp.isVarExp())
2527 if (auto v = ve.var.isVarDeclaration())
2532 else if (auto te = exp.isTemplateExp())
2534 else if (auto se = exp.isScopeExp())
2536 else if (exp.isFuncExp())
2537 s = getDsymbol(exp);
2538 else if (auto dte = exp.isDotTemplateExp())
2540 else if (exp.isErrorExp())
2546 /************************************
2547 * Resolve type 'mt' to either type, symbol, or expression.
2548 * If errors happened, resolved to Type.terror.
2551 * mt = type to be resolved
2552 * loc = the location where the type is encountered
2553 * sc = the scope of the type
2554 * pe = is set if t is an expression
2555 * pt = is set if t is a type
2556 * ps = is set if t is a symbol
2557 * intypeid = true if in type id
2559 void resolve(Type mt, const ref Loc loc, Scope* sc, out Expression pe, out Type pt, out Dsymbol ps, bool intypeid = false)
2561 void returnExp(Expression e)
2568 void returnType(Type t)
2575 void returnSymbol(Dsymbol s)
2584 returnType(Type.terror);
2587 void visitType(Type mt)
2589 //printf("Type::resolve() %s, %d\n", mt.toChars(), mt.ty);
2590 Type t = typeSemantic(mt, loc, sc);
2595 void visitSArray(TypeSArray mt)
2597 //printf("TypeSArray::resolve() %s\n", mt.toChars());
2598 mt.next.resolve(loc, sc, pe, pt, ps, intypeid);
2599 //printf("s = %p, e = %p, t = %p\n", ps, pe, pt);
2602 // It's really an index expression
2603 if (Dsymbol s = getDsymbol(pe))
2604 pe = new DsymbolExp(loc, s);
2605 returnExp(new ArrayExp(loc, pe, mt.dim));
2610 if (auto tup = s.isTupleDeclaration())
2612 mt.dim = semanticLength(sc, tup, mt.dim);
2613 mt.dim = mt.dim.ctfeInterpret();
2614 if (mt.dim.op == EXP.error)
2615 return returnError();
2617 const d = mt.dim.toUInteger();
2618 if (d >= tup.objects.length)
2620 error(loc, "tuple index `%llu` out of bounds `[0 .. %llu]`", d, cast(ulong) tup.objects.length);
2621 return returnError();
2624 RootObject o = (*tup.objects)[cast(size_t)d];
2625 switch (o.dyncast()) with (DYNCAST)
2628 return returnSymbol(cast(Dsymbol)o);
2630 Expression e = cast(Expression)o;
2631 if (e.op == EXP.dSymbol)
2632 return returnSymbol(e.isDsymbolExp().s);
2634 return returnExp(e);
2636 return returnType((cast(Type)o).addMod(mt.mod));
2641 /* Create a new TupleDeclaration which
2642 * is a slice [d..d+1] out of the old one.
2643 * Do it this way because TemplateInstance::semanticTiargs()
2644 * can handle unresolved Objects this way.
2646 auto objects = new Objects(1);
2648 return returnSymbol(new TupleDeclaration(loc, tup.ident, objects));
2651 return visitType(mt);
2655 if (pt.ty != Terror)
2656 mt.next = pt; // prevent re-running semantic() on 'next'
2662 void visitDArray(TypeDArray mt)
2664 //printf("TypeDArray::resolve() %s\n", mt.toChars());
2665 mt.next.resolve(loc, sc, pe, pt, ps, intypeid);
2666 //printf("s = %p, e = %p, t = %p\n", ps, pe, pt);
2669 // It's really a slice expression
2670 if (Dsymbol s = getDsymbol(pe))
2671 pe = new DsymbolExp(loc, s);
2672 returnExp(new ArrayExp(loc, pe));
2676 if (auto tup = ps.isTupleDeclaration())
2685 if (pt.ty != Terror)
2686 mt.next = pt; // prevent re-running semantic() on 'next'
2691 void visitAArray(TypeAArray mt)
2693 //printf("TypeAArray::resolve() %s\n", mt.toChars());
2694 // Deal with the case where we thought the index was a type, but
2695 // in reality it was an expression.
2696 if (mt.index.ty == Tident || mt.index.ty == Tinstance || mt.index.ty == Tsarray)
2701 mt.index.resolve(loc, sc, e, t, s, intypeid);
2704 // It was an expression -
2705 // Rewrite as a static array
2706 auto tsa = new TypeSArray(mt.next, e);
2707 tsa.mod = mt.mod; // just copy mod field so tsa's semantic is not yet done
2708 return tsa.resolve(loc, sc, pe, pt, ps, intypeid);
2713 .error(loc, "index is not a type or an expression");
2718 /*************************************
2719 * Takes an array of Identifiers and figures out if
2720 * it represents a Type or an Expression.
2722 * if expression, pe is set
2723 * if type, pt is set
2725 void visitIdentifier(TypeIdentifier mt)
2727 //printf("TypeIdentifier::resolve(sc = %p, idents = '%s')\n", sc, mt.toChars());
2728 if (mt.ident == Id.ctfe)
2730 error(loc, "variable `__ctfe` cannot be read at compile time");
2731 return returnError();
2733 if (mt.ident == Id.builtin_va_list) // gcc has __builtin_va_xxxx for stdarg.h
2735 /* Since we don't support __builtin_va_start, -arg, -end, we don't
2736 * have to actually care what -list is. A void* will do.
2737 * If we ever do care, import core.stdc.stdarg and pull
2738 * the definition out of that, similarly to how std.math is handled for PowExp
2740 pt = target.va_listType(loc, sc);
2745 Dsymbol s = sc.search(loc, mt.ident, &scopesym);
2747 * https://issues.dlang.org/show_bug.cgi?id=1170
2748 * https://issues.dlang.org/show_bug.cgi?id=10739
2750 * If a symbol is not found, it might be declared in
2751 * a mixin-ed string or a mixin-ed template, so before
2752 * issuing an error semantically analyze all string/template
2753 * mixins that are members of the current ScopeDsymbol.
2755 if (!s && sc.enclosing)
2757 ScopeDsymbol sds = sc.enclosing.scopesym;
2758 if (sds && sds.members)
2760 void semanticOnMixin(Dsymbol member)
2762 if (auto compileDecl = member.isCompileDeclaration())
2763 compileDecl.dsymbolSemantic(sc);
2764 else if (auto mixinTempl = member.isTemplateMixin())
2765 mixinTempl.dsymbolSemantic(sc);
2767 sds.members.foreachDsymbol( s => semanticOnMixin(s) );
2768 s = sc.search(loc, mt.ident, &scopesym);
2774 // https://issues.dlang.org/show_bug.cgi?id=16042
2775 // If `f` is really a function template, then replace `f`
2776 // with the function template declaration.
2777 if (auto f = s.isFuncDeclaration())
2779 if (auto td = getFuncTemplateDecl(f))
2781 // If not at the beginning of the overloaded list of
2782 // `TemplateDeclaration`s, then get the beginning
2790 mt.resolveHelper(loc, sc, s, scopesym, pe, pt, ps, intypeid);
2792 pt = pt.addMod(mt.mod);
2795 void visitInstance(TypeInstance mt)
2797 // Note close similarity to TypeIdentifier::resolve()
2799 //printf("TypeInstance::resolve(sc = %p, tempinst = '%s')\n", sc, mt.tempinst.toChars());
2800 mt.tempinst.dsymbolSemantic(sc);
2801 if (!global.gag && mt.tempinst.errors)
2802 return returnError();
2804 mt.resolveHelper(loc, sc, mt.tempinst, null, pe, pt, ps, intypeid);
2806 pt = pt.addMod(mt.mod);
2807 //if (pt) printf("pt = %d '%s'\n", pt.ty, pt.toChars());
2810 void visitTypeof(TypeTypeof mt)
2812 //printf("TypeTypeof::resolve(this = %p, sc = %p, idents = '%s')\n", mt, sc, mt.toChars());
2813 //static int nest; if (++nest == 50) *(char*)0=0;
2816 error(loc, "invalid scope");
2817 return returnError();
2822 error(loc, "circular `typeof` definition");
2825 return returnError();
2829 /* Currently we cannot evaluate 'exp' in speculative context, because
2830 * the type implementation may leak to the final execution. Consider:
2833 * string toString() const { return "x"; }
2836 * alias X = typeof(S!int());
2837 * assert(typeid(X).toString() == "x");
2840 Scope* sc2 = sc.push();
2842 if (!mt.exp.isTypeidExp())
2843 /* Treat typeof(typeid(exp)) as needing
2844 * the full semantic analysis of the typeid.
2845 * https://issues.dlang.org/show_bug.cgi?id=20958
2849 auto exp2 = mt.exp.expressionSemantic(sc2);
2850 exp2 = resolvePropertiesOnly(sc2, exp2);
2853 if (exp2.op == EXP.error)
2861 if (mt.exp.op == EXP.type ||
2862 mt.exp.op == EXP.scope_)
2864 if (!(sc.flags & SCOPE.Cfile) && // in (extended) C typeof may be used on types as with sizeof
2868 /* Today, 'typeof(func)' returns void if func is a
2869 * function template (TemplateExp), or
2870 * template lambda (FuncExp).
2871 * It's actually used in Phobos as an idiom, to branch code for
2872 * template functions.
2875 if (auto f = mt.exp.op == EXP.variable ? mt.exp.isVarExp().var.isFuncDeclaration()
2876 : mt.exp.op == EXP.dotVariable ? mt.exp.isDotVarExp().var.isFuncDeclaration() : null)
2878 // f might be a unittest declaration which is incomplete when compiled
2879 // without -unittest. That causes a segfault in checkForwardRef, see
2880 // https://issues.dlang.org/show_bug.cgi?id=20626
2881 if ((!f.isUnitTestDeclaration() || global.params.useUnitTests) && f.checkForwardRef(loc))
2884 if (auto f = isFuncAddress(mt.exp))
2886 if (f.checkForwardRef(loc))
2890 Type t = mt.exp.type;
2893 error(loc, "expression `%s` has no type", mt.exp.toChars());
2896 if (t.ty == Ttypeof)
2898 error(loc, "forward reference to `%s`", mt.toChars());
2901 if (mt.idents.length == 0)
2903 returnType(t.addMod(mt.mod));
2907 if (Dsymbol s = t.toDsymbol(sc))
2908 mt.resolveHelper(loc, sc, s, null, pe, pt, ps, intypeid);
2911 auto e = typeToExpressionHelper(mt, new TypeExp(loc, t));
2912 e = e.expressionSemantic(sc);
2913 resolveExp(e, pt, pe, ps);
2916 pt = pt.addMod(mt.mod);
2921 void visitReturn(TypeReturn mt)
2923 //printf("TypeReturn::resolve(sc = %p, idents = '%s')\n", sc, mt.toChars());
2926 FuncDeclaration func = sc.func;
2929 error(loc, "`typeof(return)` must be inside function");
2930 return returnError();
2933 func = func.fes.func;
2934 t = func.type.nextOf();
2937 error(loc, "cannot use `typeof(return)` inside function `%s` with inferred return type", sc.func.toChars());
2938 return returnError();
2941 if (mt.idents.length == 0)
2943 return returnType(t.addMod(mt.mod));
2947 if (Dsymbol s = t.toDsymbol(sc))
2948 mt.resolveHelper(loc, sc, s, null, pe, pt, ps, intypeid);
2951 auto e = typeToExpressionHelper(mt, new TypeExp(loc, t));
2952 e = e.expressionSemantic(sc);
2953 resolveExp(e, pt, pe, ps);
2956 pt = pt.addMod(mt.mod);
2960 void visitSlice(TypeSlice mt)
2962 mt.next.resolve(loc, sc, pe, pt, ps, intypeid);
2965 // It's really a slice expression
2966 if (Dsymbol s = getDsymbol(pe))
2967 pe = new DsymbolExp(loc, s);
2968 return returnExp(new ArrayExp(loc, pe, new IntervalExp(loc, mt.lwr, mt.upr)));
2973 TupleDeclaration td = s.isTupleDeclaration();
2976 /* It's a slice of a TupleDeclaration
2978 ScopeDsymbol sym = new ArrayScopeSymbol(sc, td);
2979 sym.parent = sc.scopesym;
2981 sc = sc.startCTFE();
2982 mt.lwr = mt.lwr.expressionSemantic(sc);
2983 mt.upr = mt.upr.expressionSemantic(sc);
2987 mt.lwr = mt.lwr.ctfeInterpret();
2988 mt.upr = mt.upr.ctfeInterpret();
2989 const i1 = mt.lwr.toUInteger();
2990 const i2 = mt.upr.toUInteger();
2991 if (!(i1 <= i2 && i2 <= td.objects.length))
2993 error(loc, "slice `[%llu..%llu]` is out of range of [0..%llu]", i1, i2, cast(ulong) td.objects.length);
2994 return returnError();
2997 if (i1 == 0 && i2 == td.objects.length)
2999 return returnSymbol(td);
3002 /* Create a new TupleDeclaration which
3003 * is a slice [i1..i2] out of the old one.
3005 auto objects = new Objects(cast(size_t)(i2 - i1));
3006 for (size_t i = 0; i < objects.length; i++)
3008 (*objects)[i] = (*td.objects)[cast(size_t)i1 + i];
3011 return returnSymbol(new TupleDeclaration(loc, td.ident, objects));
3018 if (pt.ty != Terror)
3019 mt.next = pt; // prevent re-running semantic() on 'next'
3024 void visitMixin(TypeMixin mt)
3026 RootObject o = mt.obj;
3028 // if already resolved just set pe/pt/ps and return.
3031 pe = o.isExpression();
3037 o = mt.compileTypeMixin(loc, sc);
3038 if (auto t = o.isType())
3040 resolve(t, loc, sc, pe, pt, ps, intypeid);
3042 pt = pt.addMod(mt.mod);
3044 else if (auto e = o.isExpression())
3046 e = e.expressionSemantic(sc);
3047 if (auto et = e.isTypeExp())
3048 returnType(et.type.addMod(mt.mod));
3056 mt.obj = pe ? pe : (pt ? pt : ps);
3059 void visitTraits(TypeTraits mt)
3061 // if already resolved just return the cached object.
3064 pt = mt.obj.isType();
3065 ps = mt.obj.isDsymbol();
3066 pe = mt.obj.isExpression();
3070 import dmd.traits : semanticTraits;
3072 if (Expression e = semanticTraits(mt.exp, sc))
3076 case EXP.dotVariable:
3077 mt.obj = e.isDotVarExp().var;
3080 mt.obj = e.isVarExp().var;
3083 auto fe = e.isFuncExp();
3084 mt.obj = fe.td ? fe.td : fe.fd;
3086 case EXP.dotTemplateDeclaration:
3087 mt.obj = e.isDotTemplateExp().td;
3090 mt.obj = e.isDsymbolExp().s;
3093 mt.obj = e.isTemplateExp().td;
3096 mt.obj = e.isScopeExp().sds;
3099 TupleExp te = e.isTupleExp();
3100 Objects* elems = new Objects(te.exps.length);
3101 foreach (i; 0 .. elems.length)
3103 auto src = (*te.exps)[i];
3107 (*elems)[i] = src.isTypeExp().type;
3110 (*elems)[i] = src.isDotTypeExp().sym.isType();
3112 case EXP.overloadSet:
3113 (*elems)[i] = src.isOverExp().type;
3116 if (auto sym = isDsymbol(src))
3122 TupleDeclaration td = new TupleDeclaration(e.loc, Identifier.generateId("__aliastup"), elems);
3126 mt.obj = e.isDotTypeExp().sym.isType();
3129 mt.obj = e.isTypeExp().type;
3131 case EXP.overloadSet:
3132 mt.obj = e.isOverExp().type;
3144 if (auto t = mt.obj.isType())
3146 t = t.addMod(mt.mod);
3150 else if (auto s = mt.obj.isDsymbol())
3152 else if (auto e = mt.obj.isExpression())
3157 assert(global.errors);
3158 mt.obj = Type.terror;
3159 return returnError();
3165 default: visitType (mt); break;
3166 case Tsarray: visitSArray (mt.isTypeSArray()); break;
3167 case Tarray: visitDArray (mt.isTypeDArray()); break;
3168 case Taarray: visitAArray (mt.isTypeAArray()); break;
3169 case Tident: visitIdentifier(mt.isTypeIdentifier()); break;
3170 case Tinstance: visitInstance (mt.isTypeInstance()); break;
3171 case Ttypeof: visitTypeof (mt.isTypeTypeof()); break;
3172 case Treturn: visitReturn (mt.isTypeReturn()); break;
3173 case Tslice: visitSlice (mt.isTypeSlice()); break;
3174 case Tmixin: visitMixin (mt.isTypeMixin()); break;
3175 case Ttraits: visitTraits (mt.isTypeTraits()); break;
3179 /************************
3180 * Access the members of the object e. This type is same as e.type.
3182 * mt = type for which the dot expression is used
3183 * sc = instantiating scope
3184 * e = expression to convert
3185 * ident = identifier being used
3186 * flag = DotExpFlag bit flags
3189 * resulting expression with e.ident resolved
3191 Expression dotExp(Type mt, Scope* sc, Expression e, Identifier ident, int flag)
3193 Expression visitType(Type mt)
3195 VarDeclaration v = null;
3196 static if (LOGDOTEXP)
3198 printf("Type::dotExp(e = '%s', ident = '%s')\n", e.toChars(), ident.toChars());
3200 Expression ex = e.lastComma();
3201 if (ex.op == EXP.dotVariable)
3203 DotVarExp dv = cast(DotVarExp)ex;
3204 v = dv.var.isVarDeclaration();
3206 else if (ex.op == EXP.variable)
3208 VarExp ve = cast(VarExp)ex;
3209 v = ve.var.isVarDeclaration();
3213 if (ident == Id.offsetof)
3215 v.dsymbolSemantic(null);
3218 auto ad = v.isMember();
3219 objc.checkOffsetof(e, ad);
3221 if (ad.sizeok != Sizeok.done)
3222 return ErrorExp.get();
3223 return new IntegerExp(e.loc, v.offset, Type.tsize_t);
3226 else if (ident == Id._init)
3228 Type tb = mt.toBasetype();
3229 e = mt.defaultInitLiteral(e.loc);
3230 if (tb.ty == Tstruct && tb.needsNested())
3232 e.isStructLiteralExp().useStaticInit = true;
3237 if (ident == Id.stringof)
3239 /* https://issues.dlang.org/show_bug.cgi?id=3796
3240 * this should demangle e.type.deco rather than
3241 * pretty-printing the type.
3243 e = new StringExp(e.loc, e.toString());
3246 e = mt.getProperty(sc, e.loc, ident, flag & DotExpFlag.gag);
3250 e = e.expressionSemantic(sc);
3254 Expression visitError(TypeError)
3256 return ErrorExp.get();
3259 Expression visitBasic(TypeBasic mt)
3261 static if (LOGDOTEXP)
3263 printf("TypeBasic::dotExp(e = '%s', ident = '%s')\n", e.toChars(), ident.toChars());
3282 e = e.castTo(sc, t);
3302 e = new RealExp(e.loc, CTFloat.zero, t);
3306 e = mt.Type.getProperty(sc, e.loc, ident, flag);
3310 else if (ident == Id.im)
3316 t = mt.timaginary32;
3321 t = mt.timaginary64;
3326 t = mt.timaginary80;
3330 e = e.castTo(sc, t);
3353 e = new RealExp(e.loc, CTFloat.zero, mt);
3357 e = mt.Type.getProperty(sc, e.loc, ident, flag);
3363 return visitType(mt);
3365 if (!(flag & 1) || e)
3366 e = e.expressionSemantic(sc);
3370 Expression visitVector(TypeVector mt)
3372 static if (LOGDOTEXP)
3374 printf("TypeVector::dotExp(e = '%s', ident = '%s')\n", e.toChars(), ident.toChars());
3376 if (ident == Id.ptr && e.op == EXP.call)
3378 /* The trouble with EXP.call is the return ABI for float[4] is different from
3379 * __vector(float[4]), and a type paint won't do.
3381 e = new AddrExp(e.loc, e);
3382 e = e.expressionSemantic(sc);
3383 return e.castTo(sc, mt.basetype.nextOf().pointerTo());
3385 if (ident == Id.array)
3387 //e = e.castTo(sc, basetype);
3389 e = new VectorArrayExp(e.loc, e);
3390 e = e.expressionSemantic(sc);
3393 if (ident == Id._init || ident == Id.offsetof || ident == Id.stringof || ident == Id.__xalignof)
3395 // init should return a new VectorExp
3396 // https://issues.dlang.org/show_bug.cgi?id=12776
3397 // offsetof does not work on a cast expression, so use e directly
3398 // stringof should not add a cast to the output
3399 return visitType(mt);
3402 // Properties based on the vector element type and are values of the element type
3403 if (ident == Id.max || ident == Id.min || ident == Id.min_normal ||
3404 ident == Id.nan || ident == Id.infinity || ident == Id.epsilon)
3406 auto vet = mt.basetype.isTypeSArray().next; // vector element type
3407 if (auto ev = getProperty(vet, sc, e.loc, ident, DotExpFlag.gag))
3408 return ev.castTo(sc, mt); // 'broadcast' ev to the vector elements
3411 return mt.basetype.dotExp(sc, e.castTo(sc, mt.basetype), ident, flag);
3414 Expression visitArray(TypeArray mt)
3416 static if (LOGDOTEXP)
3418 printf("TypeArray::dotExp(e = '%s', ident = '%s')\n", e.toChars(), ident.toChars());
3423 if (!(flag & 1) || e)
3424 e = e.expressionSemantic(sc);
3428 Expression visitSArray(TypeSArray mt)
3430 static if (LOGDOTEXP)
3432 printf("TypeSArray::dotExp(e = '%s', ident = '%s')\n", e.toChars(), ident.toChars());
3434 if (ident == Id.length)
3440 else if (ident == Id.ptr)
3442 if (e.op == EXP.type)
3444 e.error("`%s` is not an expression", e.toChars());
3445 return ErrorExp.get();
3447 else if (mt.dim.toUInteger() < 1 && checkUnsafeDotExp(sc, e, ident, flag))
3449 // .ptr on static array is @safe unless size is 0
3450 // https://issues.dlang.org/show_bug.cgi?id=20853
3451 return ErrorExp.get();
3453 e = e.castTo(sc, e.type.nextOf().pointerTo());
3455 else if (ident == Id._tupleof)
3459 e.error("`.tupleof` cannot be used on type `%s`", mt.toChars);
3460 return ErrorExp.get();
3466 ev = extractSideEffect(sc, "__tup", e0, ev);
3468 const length = cast(size_t)mt.dim.toUInteger();
3469 auto exps = new Expressions();
3470 exps.reserve(length);
3471 foreach (i; 0 .. length)
3472 exps.push(new IndexExp(e.loc, ev, new IntegerExp(e.loc, i, Type.tsize_t)));
3473 e = new TupleExp(e.loc, e0, exps);
3480 if (!(flag & 1) || e)
3481 e = e.expressionSemantic(sc);
3485 Expression visitDArray(TypeDArray mt)
3487 static if (LOGDOTEXP)
3489 printf("TypeDArray::dotExp(e = '%s', ident = '%s')\n", e.toChars(), ident.toChars());
3491 if (e.op == EXP.type && (ident == Id.length || ident == Id.ptr))
3493 e.error("`%s` is not an expression", e.toChars());
3494 return ErrorExp.get();
3496 if (ident == Id.length)
3498 if (e.op == EXP.string_)
3500 StringExp se = cast(StringExp)e;
3501 return new IntegerExp(se.loc, se.len, Type.tsize_t);
3503 if (e.op == EXP.null_)
3505 return new IntegerExp(e.loc, 0, Type.tsize_t);
3507 if (checkNonAssignmentArrayOp(e))
3509 return ErrorExp.get();
3511 e = new ArrayLengthExp(e.loc, e);
3512 e.type = Type.tsize_t;
3515 else if (ident == Id.ptr)
3517 if (checkUnsafeDotExp(sc, e, ident, flag))
3518 return ErrorExp.get();
3519 return e.castTo(sc, mt.next.pointerTo());
3523 return visitArray(mt);
3527 Expression visitAArray(TypeAArray mt)
3529 static if (LOGDOTEXP)
3531 printf("TypeAArray::dotExp(e = '%s', ident = '%s')\n", e.toChars(), ident.toChars());
3533 if (ident == Id.length)
3535 __gshared FuncDeclaration fd_aaLen = null;
3536 if (fd_aaLen is null)
3538 auto fparams = new Parameters();
3539 fparams.push(new Parameter(STC.const_ | STC.scope_, mt, null, null, null));
3540 fd_aaLen = FuncDeclaration.genCfunc(fparams, Type.tsize_t, Id.aaLen);
3541 TypeFunction tf = fd_aaLen.type.toTypeFunction();
3542 tf.purity = PURE.const_;
3543 tf.isnothrow = true;
3546 Expression ev = new VarExp(e.loc, fd_aaLen, false);
3547 e = new CallExp(e.loc, ev, e);
3548 e.type = fd_aaLen.type.toTypeFunction().next;
3553 return visitType(mt);
3557 Expression visitReference(TypeReference mt)
3559 static if (LOGDOTEXP)
3561 printf("TypeReference::dotExp(e = '%s', ident = '%s')\n", e.toChars(), ident.toChars());
3563 // References just forward things along
3564 return mt.next.dotExp(sc, e, ident, flag);
3567 Expression visitDelegate(TypeDelegate mt)
3569 static if (LOGDOTEXP)
3571 printf("TypeDelegate::dotExp(e = '%s', ident = '%s')\n", e.toChars(), ident.toChars());
3573 if (ident == Id.ptr)
3575 e = new DelegatePtrExp(e.loc, e);
3576 e = e.expressionSemantic(sc);
3578 else if (ident == Id.funcptr)
3580 if (checkUnsafeDotExp(sc, e, ident, flag))
3582 return ErrorExp.get();
3584 e = new DelegateFuncptrExp(e.loc, e);
3585 e = e.expressionSemantic(sc);
3589 return visitType(mt);
3594 /***************************************
3595 * `ident` was not found as a member of `mt`.
3596 * Attempt to use overloaded opDot(), overloaded opDispatch(), or `alias this`.
3597 * If that fails, forward to visitType().
3599 * mt = class or struct
3601 * e = `this` for `ident`
3602 * ident = name of member
3603 * flag = flag & 1, don't report "not a property" error and just return NULL.
3604 * flag & DotExpFlag.noAliasThis, don't do 'alias this' resolution.
3606 * resolved expression if found, otherwise null
3608 Expression noMember(Type mt, Scope* sc, Expression e, Identifier ident, int flag)
3610 //printf("Type.noMember(e: %s ident: %s flag: %d)\n", e.toChars(), ident.toChars(), flag);
3612 bool gagError = flag & 1;
3614 __gshared int nest; // https://issues.dlang.org/show_bug.cgi?id=17380
3616 static Expression returnExp(Expression e)
3622 if (++nest > global.recursionLimit)
3624 .error(e.loc, "cannot resolve identifier `%s`", ident.toChars());
3625 return returnExp(gagError ? null : ErrorExp.get());
3629 assert(mt.ty == Tstruct || mt.ty == Tclass);
3630 auto sym = mt.toDsymbol(sc).isAggregateDeclaration();
3632 if (// https://issues.dlang.org/show_bug.cgi?id=22054
3633 // if a class or struct does not have a body
3634 // there is no point in searching for its members
3636 ident != Id.__sizeof &&
3637 ident != Id.__xalignof &&
3638 ident != Id._init &&
3639 ident != Id._mangleof &&
3640 ident != Id.stringof &&
3641 ident != Id.offsetof &&
3642 // https://issues.dlang.org/show_bug.cgi?id=15045
3643 // Don't forward special built-in member functions.
3646 ident != Id.__xdtor &&
3647 ident != Id.postblit &&
3648 ident != Id.__xpostblit)
3650 /* Look for overloaded opDot() to see if we should forward request
3653 if (auto fd = search_function(sym, Id.opDot))
3655 /* Rewrite e.ident as:
3658 e = build_overload(e.loc, sc, e, null, fd);
3659 // @@@DEPRECATED_2.110@@@.
3660 // Deprecated in 2.082, made an error in 2.100.
3661 e.error("`opDot` is obsolete. Use `alias this`");
3662 return ErrorExp.get();
3665 /* Look for overloaded opDispatch to see if we should forward request
3668 if (auto fd = search_function(sym, Id.opDispatch))
3670 /* Rewrite e.ident as:
3671 * e.opDispatch!("ident")
3673 TemplateDeclaration td = fd.isTemplateDeclaration();
3676 fd.error("must be a template `opDispatch(string s)`, not a %s", fd.kind());
3677 return returnExp(ErrorExp.get());
3679 auto se = new StringExp(e.loc, ident.toString());
3680 auto tiargs = new Objects();
3682 auto dti = new DotTemplateInstanceExp(e.loc, e, Id.opDispatch, tiargs);
3683 dti.ti.tempdecl = td;
3684 /* opDispatch, which doesn't need IFTI, may occur instantiate error.
3686 * template opDispatch(name) if (isValid!name) { ... }
3688 uint errors = gagError ? global.startGagging() : 0;
3689 e = dti.dotTemplateSemanticProp(sc, 0);
3690 if (gagError && global.endGagging(errors))
3692 return returnExp(e);
3695 /* See if we should forward to the alias this.
3697 auto alias_e = flag & DotExpFlag.noAliasThis ? null
3698 : resolveAliasThis(sc, e, gagError);
3699 if (alias_e && alias_e != e)
3701 /* Rewrite e.ident as:
3704 auto die = new DotIdExp(e.loc, alias_e, ident);
3706 auto errors = gagError ? 0 : global.startGagging();
3707 auto exp = die.dotIdSemanticProp(sc, gagError);
3710 global.endGagging(errors);
3711 if (exp && exp.op == EXP.error)
3715 if (exp && gagError)
3716 // now that we know that the alias this leads somewhere useful,
3717 // go back and print deprecations/warnings that we skipped earlier due to the gag
3718 resolveAliasThis(sc, e, false);
3720 return returnExp(exp);
3723 return returnExp(visitType(mt));
3726 Expression visitStruct(TypeStruct mt)
3729 static if (LOGDOTEXP)
3731 printf("TypeStruct::dotExp(e = '%s', ident = '%s')\n", e.toChars(), ident.toChars());
3733 assert(e.op != EXP.dot);
3735 // https://issues.dlang.org/show_bug.cgi?id=14010
3736 if (!(sc.flags & SCOPE.Cfile) && ident == Id._mangleof)
3738 return mt.getProperty(sc, e.loc, ident, flag & 1);
3743 if (ident == Id._tupleof)
3745 /* Create a TupleExp out of the fields of the struct e:
3746 * (e.field0, e.field1, e.field2, ...)
3748 e = e.expressionSemantic(sc); // do this before turning on noaccesscheck
3750 if (!mt.sym.determineFields())
3752 error(e.loc, "unable to determine fields of `%s` because of forward references", mt.toChars());
3756 Expression ev = e.op == EXP.type ? null : e;
3758 ev = extractSideEffect(sc, "__tup", e0, ev);
3760 auto exps = new Expressions();
3761 exps.reserve(mt.sym.fields.length);
3762 for (size_t i = 0; i < mt.sym.fields.length; i++)
3764 VarDeclaration v = mt.sym.fields[i];
3767 ex = new DotVarExp(e.loc, ev, v);
3770 ex = new VarExp(e.loc, v);
3771 ex.type = ex.type.addMod(e.type.mod);
3776 e = new TupleExp(e.loc, e0, exps);
3777 Scope* sc2 = sc.push();
3778 sc2.flags |= SCOPE.noaccesscheck;
3779 e = e.expressionSemantic(sc2);
3784 immutable flags = sc.flags & SCOPE.ignoresymbolvisibility ? IgnoreSymbolVisibility : 0;
3785 s = mt.sym.search(e.loc, ident, flags | IgnorePrivateImports);
3789 return noMember(mt, sc, e, ident, flag);
3791 if (!(sc.flags & SCOPE.ignoresymbolvisibility) && !symbolIsVisible(sc, s))
3793 return noMember(mt, sc, e, ident, flag);
3797 if (auto em = s.isEnumMember())
3799 return em.getVarExp(e.loc, sc);
3801 if (auto v = s.isVarDeclaration())
3803 v.checkDeprecated(e.loc, sc);
3804 v.checkDisabled(e.loc, sc);
3806 !v.type.deco && v.inuse)
3808 if (v.inuse) // https://issues.dlang.org/show_bug.cgi?id=9494
3809 e.error("circular reference to %s `%s`", v.kind(), v.toPrettyChars());
3811 e.error("forward reference to %s `%s`", v.kind(), v.toPrettyChars());
3812 return ErrorExp.get();
3814 if (v.type.ty == Terror)
3816 return ErrorExp.get();
3819 if ((v.storage_class & STC.manifest) && v._init)
3823 e.error("circular initialization of %s `%s`", v.kind(), v.toPrettyChars());
3824 return ErrorExp.get();
3826 checkAccess(e.loc, sc, null, v);
3827 Expression ve = new VarExp(e.loc, v);
3828 if (!isTrivialExp(e))
3830 ve = new CommaExp(e.loc, e, ve);
3832 return ve.expressionSemantic(sc);
3836 if (auto t = s.getType())
3838 return (new TypeExp(e.loc, t)).expressionSemantic(sc);
3841 TemplateMixin tm = s.isTemplateMixin();
3844 return new DotExp(e.loc, e, new ScopeExp(e.loc, tm)).expressionSemantic(sc);
3847 TemplateDeclaration td = s.isTemplateDeclaration();
3850 if (e.op == EXP.type)
3851 e = new TemplateExp(e.loc, td);
3853 e = new DotTemplateExp(e.loc, e, td);
3854 return e.expressionSemantic(sc);
3857 TemplateInstance ti = s.isTemplateInstance();
3860 if (!ti.semanticRun)
3862 ti.dsymbolSemantic(sc);
3863 if (!ti.inst || ti.errors) // if template failed to expand
3865 return ErrorExp.get();
3868 s = ti.inst.toAlias();
3869 if (!s.isTemplateInstance())
3871 if (e.op == EXP.type)
3872 e = new ScopeExp(e.loc, ti);
3874 e = new DotExp(e.loc, e, new ScopeExp(e.loc, ti));
3875 return e.expressionSemantic(sc);
3878 if (s.isImport() || s.isModule() || s.isPackage())
3880 return symbolToExp(s, e.loc, sc, false);
3883 OverloadSet o = s.isOverloadSet();
3886 auto oe = new OverExp(e.loc, o);
3887 if (e.op == EXP.type)
3891 return new DotExp(e.loc, e, oe);
3894 Declaration d = s.isDeclaration();
3897 e.error("`%s.%s` is not a declaration", e.toChars(), ident.toChars());
3898 return ErrorExp.get();
3901 if (e.op == EXP.type)
3906 if (TupleDeclaration tup = d.isTupleDeclaration())
3908 e = new TupleExp(e.loc, tup);
3909 return e.expressionSemantic(sc);
3911 if (d.needThis() && sc.intypeof != 1)
3918 e = new DotVarExp(e.loc, new ThisExp(e.loc), d);
3919 return e.expressionSemantic(sc);
3922 if (d.semanticRun == PASS.initial)
3923 d.dsymbolSemantic(null);
3924 checkAccess(e.loc, sc, e, d);
3925 auto ve = new VarExp(e.loc, d);
3926 if (d.isVarDeclaration() && d.needThis())
3927 ve.type = d.type.addMod(e.type.mod);
3931 bool unreal = e.op == EXP.variable && (cast(VarExp)e).var.isField();
3932 if (d.isDataseg() || unreal && d.isField())
3935 checkAccess(e.loc, sc, e, d);
3936 Expression ve = new VarExp(e.loc, d);
3937 e = unreal ? ve : new CommaExp(e.loc, e, ve);
3938 return e.expressionSemantic(sc);
3941 e = new DotVarExp(e.loc, e, d);
3942 return e.expressionSemantic(sc);
3945 Expression visitEnum(TypeEnum mt)
3947 static if (LOGDOTEXP)
3949 printf("TypeEnum::dotExp(e = '%s', ident = '%s') '%s'\n", e.toChars(), ident.toChars(), mt.toChars());
3951 // https://issues.dlang.org/show_bug.cgi?id=14010
3952 if (ident == Id._mangleof)
3954 return mt.getProperty(sc, e.loc, ident, flag & 1);
3957 if (mt.sym.semanticRun < PASS.semanticdone)
3958 mt.sym.dsymbolSemantic(null);
3960 Dsymbol s = mt.sym.search(e.loc, ident);
3963 if (ident == Id._init)
3965 return mt.getProperty(sc, e.loc, ident, flag & 1);
3968 /* Allow special enums to not need a member list
3970 if ((ident == Id.max || ident == Id.min) && (mt.sym.members || !mt.sym.isSpecial()))
3972 return mt.getProperty(sc, e.loc, ident, flag & 1);
3975 Expression res = mt.sym.getMemtype(Loc.initial).dotExp(sc, e, ident, 1);
3976 if (!(flag & 1) && !res)
3978 if (auto ns = mt.sym.search_correct(ident))
3979 e.error("no property `%s` for type `%s`. Did you mean `%s.%s` ?", ident.toChars(), mt.toChars(), mt.toChars(),
3982 e.error("no property `%s` for type `%s`", ident.toChars(),
3985 return ErrorExp.get();
3989 EnumMember m = s.isEnumMember();
3990 return m.getVarExp(e.loc, sc);
3993 Expression visitClass(TypeClass mt)
3996 static if (LOGDOTEXP)
3998 printf("TypeClass::dotExp(e = '%s', ident = '%s')\n", e.toChars(), ident.toChars());
4000 assert(e.op != EXP.dot);
4002 // https://issues.dlang.org/show_bug.cgi?id=12543
4003 if (ident == Id.__sizeof || ident == Id.__xalignof || ident == Id._mangleof)
4005 return mt.Type.getProperty(sc, e.loc, ident, 0);
4010 if (ident == Id._tupleof)
4012 objc.checkTupleof(e, mt);
4014 /* Create a TupleExp
4016 e = e.expressionSemantic(sc); // do this before turning on noaccesscheck
4018 mt.sym.size(e.loc); // do semantic of type
4021 Expression ev = e.op == EXP.type ? null : e;
4023 ev = extractSideEffect(sc, "__tup", e0, ev);
4025 auto exps = new Expressions();
4026 exps.reserve(mt.sym.fields.length);
4027 for (size_t i = 0; i < mt.sym.fields.length; i++)
4029 VarDeclaration v = mt.sym.fields[i];
4030 // Don't include hidden 'this' pointer
4031 if (v.isThisDeclaration())
4035 ex = new DotVarExp(e.loc, ev, v);
4038 ex = new VarExp(e.loc, v);
4039 ex.type = ex.type.addMod(e.type.mod);
4044 e = new TupleExp(e.loc, e0, exps);
4045 Scope* sc2 = sc.push();
4046 sc2.flags |= SCOPE.noaccesscheck;
4047 e = e.expressionSemantic(sc2);
4052 int flags = sc.flags & SCOPE.ignoresymbolvisibility ? IgnoreSymbolVisibility : 0;
4053 s = mt.sym.search(e.loc, ident, flags | IgnorePrivateImports);
4058 // See if it's a 'this' class or a base class
4059 if (mt.sym.ident == ident)
4061 if (e.op == EXP.type)
4063 return mt.Type.getProperty(sc, e.loc, ident, 0);
4065 e = new DotTypeExp(e.loc, e, mt.sym);
4066 e = e.expressionSemantic(sc);
4069 if (auto cbase = mt.sym.searchBase(ident))
4071 if (e.op == EXP.type)
4073 return mt.Type.getProperty(sc, e.loc, ident, 0);
4075 if (auto ifbase = cbase.isInterfaceDeclaration())
4076 e = new CastExp(e.loc, e, ifbase.type);
4078 e = new DotTypeExp(e.loc, e, cbase);
4079 e = e.expressionSemantic(sc);
4083 if (ident == Id.classinfo)
4085 if (!Type.typeinfoclass)
4087 error(e.loc, "`object.TypeInfo_Class` could not be found, but is implicitly used");
4088 return ErrorExp.get();
4091 Type t = Type.typeinfoclass.type;
4092 if (e.op == EXP.type || e.op == EXP.dotType)
4094 /* For type.classinfo, we know the classinfo
4097 if (!mt.sym.vclassinfo)
4098 mt.sym.vclassinfo = new TypeInfoClassDeclaration(mt.sym.type);
4099 e = new VarExp(e.loc, mt.sym.vclassinfo);
4101 e.type = t; // do this so we don't get redundant dereference
4105 /* For class objects, the classinfo reference is the first
4106 * entry in the vtbl[]
4108 e = new PtrExp(e.loc, e);
4109 e.type = t.pointerTo();
4110 if (mt.sym.isInterfaceDeclaration())
4112 if (mt.sym.isCPPinterface())
4114 /* C++ interface vtbl[]s are different in that the
4115 * first entry is always pointer to the first virtual
4116 * function, not classinfo.
4117 * We can't get a .classinfo for it.
4119 error(e.loc, "no `.classinfo` for C++ interface objects");
4121 /* For an interface, the first entry in the vtbl[]
4122 * is actually a pointer to an instance of struct Interface.
4123 * The first member of Interface is the .classinfo,
4124 * so add an extra pointer indirection.
4126 e.type = e.type.pointerTo();
4127 e = new PtrExp(e.loc, e);
4128 e.type = t.pointerTo();
4130 e = new PtrExp(e.loc, e, t);
4135 if (ident == Id.__vptr)
4137 /* The pointer to the vtbl[]
4138 * *cast(immutable(void*)**)e
4140 e = e.castTo(sc, mt.tvoidptr.immutableOf().pointerTo().pointerTo());
4141 e = new PtrExp(e.loc, e);
4142 e = e.expressionSemantic(sc);
4146 if (ident == Id.__monitor && mt.sym.hasMonitor())
4148 /* The handle to the monitor (call it a void*)
4149 * *(cast(void**)e + 1)
4151 e = e.castTo(sc, mt.tvoidptr.pointerTo());
4152 e = new AddExp(e.loc, e, IntegerExp.literal!1);
4153 e = new PtrExp(e.loc, e);
4154 e = e.expressionSemantic(sc);
4158 if (ident == Id.outer && mt.sym.vthis)
4160 if (mt.sym.vthis.semanticRun == PASS.initial)
4161 mt.sym.vthis.dsymbolSemantic(null);
4163 if (auto cdp = mt.sym.toParentLocal().isClassDeclaration())
4165 auto dve = new DotVarExp(e.loc, e, mt.sym.vthis);
4166 dve.type = cdp.type.addMod(e.type.mod);
4170 /* https://issues.dlang.org/show_bug.cgi?id=15839
4171 * Find closest parent class through nested functions.
4173 for (auto p = mt.sym.toParentLocal(); p; p = p.toParentLocal())
4175 auto fd = p.isFuncDeclaration();
4178 auto ad = fd.isThis();
4179 if (!ad && fd.isNested())
4183 if (auto cdp = ad.isClassDeclaration())
4185 auto ve = new ThisExp(e.loc);
4188 const nestedError = fd.vthis.checkNestedReference(sc, e.loc);
4189 assert(!nestedError);
4191 ve.type = cdp.type.addMod(fd.vthis.type.mod).addMod(e.type.mod);
4197 // Continue to show enclosing function's frame (stack or closure).
4198 auto dve = new DotVarExp(e.loc, e, mt.sym.vthis);
4199 dve.type = mt.sym.vthis.type.addMod(e.type.mod);
4203 return noMember(mt, sc, e, ident, flag & 1);
4205 if (!(sc.flags & SCOPE.ignoresymbolvisibility) && !symbolIsVisible(sc, s))
4207 return noMember(mt, sc, e, ident, flag);
4209 if (!s.isFuncDeclaration()) // because of overloading
4211 s.checkDeprecated(e.loc, sc);
4212 if (auto d = s.isDeclaration())
4213 d.checkDisabled(e.loc, sc);
4217 if (auto em = s.isEnumMember())
4219 return em.getVarExp(e.loc, sc);
4221 if (auto v = s.isVarDeclaration())
4224 !v.type.deco && v.inuse)
4226 if (v.inuse) // https://issues.dlang.org/show_bug.cgi?id=9494
4227 e.error("circular reference to %s `%s`", v.kind(), v.toPrettyChars());
4229 e.error("forward reference to %s `%s`", v.kind(), v.toPrettyChars());
4230 return ErrorExp.get();
4232 if (v.type.ty == Terror)
4234 return ErrorExp.get();
4237 if ((v.storage_class & STC.manifest) && v._init)
4241 e.error("circular initialization of %s `%s`", v.kind(), v.toPrettyChars());
4242 return ErrorExp.get();
4244 checkAccess(e.loc, sc, null, v);
4245 Expression ve = new VarExp(e.loc, v);
4246 ve = ve.expressionSemantic(sc);
4251 if (auto t = s.getType())
4253 return (new TypeExp(e.loc, t)).expressionSemantic(sc);
4256 TemplateMixin tm = s.isTemplateMixin();
4259 return new DotExp(e.loc, e, new ScopeExp(e.loc, tm)).expressionSemantic(sc);
4262 TemplateDeclaration td = s.isTemplateDeclaration();
4264 Expression toTemplateExp(TemplateDeclaration td)
4266 if (e.op == EXP.type)
4267 e = new TemplateExp(e.loc, td);
4269 e = new DotTemplateExp(e.loc, e, td);
4270 e = e.expressionSemantic(sc);
4276 return toTemplateExp(td);
4279 TemplateInstance ti = s.isTemplateInstance();
4282 if (!ti.semanticRun)
4284 ti.dsymbolSemantic(sc);
4285 if (!ti.inst || ti.errors) // if template failed to expand
4287 return ErrorExp.get();
4290 s = ti.inst.toAlias();
4291 if (!s.isTemplateInstance())
4293 if (e.op == EXP.type)
4294 e = new ScopeExp(e.loc, ti);
4296 e = new DotExp(e.loc, e, new ScopeExp(e.loc, ti));
4297 return e.expressionSemantic(sc);
4300 if (s.isImport() || s.isModule() || s.isPackage())
4302 e = symbolToExp(s, e.loc, sc, false);
4306 OverloadSet o = s.isOverloadSet();
4309 auto oe = new OverExp(e.loc, o);
4310 if (e.op == EXP.type)
4314 return new DotExp(e.loc, e, oe);
4317 Declaration d = s.isDeclaration();
4320 e.error("`%s.%s` is not a declaration", e.toChars(), ident.toChars());
4321 return ErrorExp.get();
4324 if (e.op == EXP.type)
4329 if (TupleDeclaration tup = d.isTupleDeclaration())
4331 e = new TupleExp(e.loc, tup);
4332 e = e.expressionSemantic(sc);
4336 if (mt.sym.classKind == ClassKind.objc
4337 && d.isFuncDeclaration()
4338 && d.isFuncDeclaration().isStatic
4339 && d.isFuncDeclaration().objc.selector)
4341 auto classRef = new ObjcClassReferenceExp(e.loc, mt.sym);
4342 return new DotVarExp(e.loc, classRef, d).expressionSemantic(sc);
4344 else if (d.needThis() && sc.intypeof != 1)
4349 AggregateDeclaration ad = d.isMemberLocal();
4350 if (auto f = hasThis(sc))
4352 // This is almost same as getRightThis() in expressionsem.d
4355 /* returns: true to continue, false to return */
4356 if (f.hasDualContext())
4358 if (f.followInstantiationContext(ad))
4360 e1 = new VarExp(e.loc, f.vthis);
4361 e1 = new PtrExp(e1.loc, e1);
4362 e1 = new IndexExp(e1.loc, e1, IntegerExp.literal!1);
4363 auto pd = f.toParent2().isDeclaration();
4365 t = pd.type.toBasetype();
4366 e1 = getThisSkipNestedFuncs(e1.loc, sc, f.toParent2(), ad, e1, t, d, true);
4369 e = new VarExp(e.loc, d);
4375 e1 = new ThisExp(e.loc);
4376 e1 = e1.expressionSemantic(sc);
4378 t = e1.type.toBasetype();
4379 ClassDeclaration cd = e.type.isClassHandle();
4380 ClassDeclaration tcd = t.isClassHandle();
4381 if (cd && tcd && (tcd == cd || cd.isBaseOf(tcd, null)))
4383 e = new DotTypeExp(e1.loc, e1, cd);
4384 e = new DotVarExp(e.loc, e, d);
4385 e = e.expressionSemantic(sc);
4388 if (tcd && tcd.isNested())
4390 /* e1 is the 'this' pointer for an inner class: tcd.
4391 * Rewrite it as the 'this' pointer for the outer class.
4393 auto vthis = tcd.followInstantiationContext(ad) ? tcd.vthis2 : tcd.vthis;
4394 e1 = new DotVarExp(e.loc, e1, vthis);
4395 e1.type = vthis.type;
4396 e1.type = e1.type.addMod(t.mod);
4397 // Do not call ensureStaticLinkTo()
4398 //e1 = e1.expressionSemantic(sc);
4400 // Skip up over nested functions, and get the enclosing
4402 e1 = getThisSkipNestedFuncs(e1.loc, sc, tcd.toParentP(ad), ad, e1, t, d, true);
4405 e = new VarExp(e.loc, d);
4412 //printf("e = %s, d = %s\n", e.toChars(), d.toChars());
4413 if (d.semanticRun == PASS.initial)
4414 d.dsymbolSemantic(null);
4416 // If static function, get the most visible overload.
4417 // Later on the call is checked for correctness.
4418 // https://issues.dlang.org/show_bug.cgi?id=12511
4420 if (auto fd = d.isFuncDeclaration())
4422 import dmd.access : mostVisibleOverload;
4423 d2 = mostVisibleOverload(fd, sc._module);
4426 checkAccess(e.loc, sc, e, d2);
4427 if (d2.isDeclaration())
4429 d = cast(Declaration)d2;
4430 auto ve = new VarExp(e.loc, d);
4431 if (d.isVarDeclaration() && d.needThis())
4432 ve.type = d.type.addMod(e.type.mod);
4435 else if (d2.isTemplateDeclaration())
4437 return toTemplateExp(cast(TemplateDeclaration)d2);
4443 bool unreal = e.op == EXP.variable && (cast(VarExp)e).var.isField();
4444 if (d.isDataseg() || unreal && d.isField())
4447 checkAccess(e.loc, sc, e, d);
4448 Expression ve = new VarExp(e.loc, d);
4449 e = unreal ? ve : new CommaExp(e.loc, e, ve);
4450 e = e.expressionSemantic(sc);
4454 e = new DotVarExp(e.loc, e, d);
4455 e = e.expressionSemantic(sc);
4461 case Tvector: return visitVector (mt.isTypeVector());
4462 case Tsarray: return visitSArray (mt.isTypeSArray());
4463 case Tstruct: return visitStruct (mt.isTypeStruct());
4464 case Tenum: return visitEnum (mt.isTypeEnum());
4465 case Terror: return visitError (mt.isTypeError());
4466 case Tarray: return visitDArray (mt.isTypeDArray());
4467 case Taarray: return visitAArray (mt.isTypeAArray());
4468 case Treference: return visitReference(mt.isTypeReference());
4469 case Tdelegate: return visitDelegate (mt.isTypeDelegate());
4470 case Tclass: return visitClass (mt.isTypeClass());
4472 default: return mt.isTypeBasic()
4473 ? visitBasic(cast(TypeBasic)mt)
4479 /************************
4480 * Get the default initialization expression for a type.
4482 * mt = the type for which the init expression is returned
4483 * loc = the location where the expression needs to be evaluated
4484 * isCfile = default initializers are different with C
4487 * The initialization expression for the type.
4489 extern (C++) Expression defaultInit(Type mt, const ref Loc loc, const bool isCfile = false)
4491 Expression visitBasic(TypeBasic mt)
4493 static if (LOGDEFAULTINIT)
4495 printf("TypeBasic::defaultInit() '%s' isCfile: %d\n", mt.toChars(), isCfile);
4497 dinteger_t value = 0;
4502 value = isCfile ? 0 : 0xFF;
4507 value = isCfile ? 0 : 0xFFFF;
4516 return new RealExp(loc, isCfile ? CTFloat.zero : target.RealProperties.nan, mt);
4522 // Can't use fvalue + I*fvalue (the im part becomes a quiet NaN).
4523 const cvalue = isCfile ? complex_t(CTFloat.zero, CTFloat.zero)
4524 : complex_t(target.RealProperties.nan, target.RealProperties.nan);
4525 return new ComplexExp(loc, cvalue, mt);
4529 error(loc, "`void` does not have a default initializer");
4530 return ErrorExp.get();
4535 return new IntegerExp(loc, value, mt);
4538 Expression visitVector(TypeVector mt)
4540 //printf("TypeVector::defaultInit()\n");
4541 assert(mt.basetype.ty == Tsarray);
4542 Expression e = mt.basetype.defaultInit(loc, isCfile);
4543 auto ve = new VectorExp(loc, e, mt);
4545 ve.dim = cast(int)(mt.basetype.size(loc) / mt.elementType().size(loc));
4549 Expression visitSArray(TypeSArray mt)
4551 static if (LOGDEFAULTINIT)
4553 printf("TypeSArray::defaultInit() '%s' isCfile %d\n", mt.toChars(), isCfile);
4555 if (mt.next.ty == Tvoid)
4556 return mt.tuns8.defaultInit(loc, isCfile);
4558 return mt.next.defaultInit(loc, isCfile);
4561 Expression visitFunction(TypeFunction mt)
4563 error(loc, "`function` does not have a default initializer");
4564 return ErrorExp.get();
4567 Expression visitStruct(TypeStruct mt)
4569 static if (LOGDEFAULTINIT)
4571 printf("TypeStruct::defaultInit() '%s'\n", mt.toChars());
4573 Declaration d = new SymbolDeclaration(mt.sym.loc, mt.sym);
4576 d.storage_class |= STC.rvalue; // https://issues.dlang.org/show_bug.cgi?id=14398
4577 return new VarExp(mt.sym.loc, d);
4580 Expression visitEnum(TypeEnum mt)
4582 static if (LOGDEFAULTINIT)
4584 printf("TypeEnum::defaultInit() '%s'\n", mt.toChars());
4586 // Initialize to first member of enum
4587 Expression e = mt.sym.getDefaultValue(loc);
4590 e.type = mt; // to deal with const, immutable, etc., variants
4594 Expression visitTuple(TypeTuple mt)
4596 static if (LOGDEFAULTINIT)
4598 printf("TypeTuple::defaultInit() '%s'\n", mt.toChars());
4600 auto exps = new Expressions(mt.arguments.length);
4601 for (size_t i = 0; i < mt.arguments.length; i++)
4603 Parameter p = (*mt.arguments)[i];
4605 Expression e = p.type.defaultInitLiteral(loc);
4606 if (e.op == EXP.error)
4612 return new TupleExp(loc, exps);
4615 Expression visitNoreturn(TypeNoreturn mt)
4617 static if (LOGDEFAULTINIT)
4619 printf("TypeNoreturn::defaultInit() '%s'\n", mt.toChars());
4621 auto cond = IntegerExp.createBool(false);
4622 auto msg = new StringExp(loc, "Accessed expression of type `noreturn`");
4623 msg.type = Type.tstring;
4624 auto ae = new AssertExp(loc, cond, msg);
4631 case Tvector: return visitVector (mt.isTypeVector());
4632 case Tsarray: return visitSArray (mt.isTypeSArray());
4633 case Tfunction: return visitFunction(mt.isTypeFunction());
4634 case Tstruct: return visitStruct (mt.isTypeStruct());
4635 case Tenum: return visitEnum (mt.isTypeEnum());
4636 case Ttuple: return visitTuple (mt.isTypeTuple());
4638 case Tnull: return new NullExp(Loc.initial, Type.tnull);
4640 case Terror: return ErrorExp.get();
4647 case Tclass: return new NullExp(loc, mt);
4648 case Tnoreturn: return visitNoreturn(mt.isTypeNoreturn());
4650 default: return mt.isTypeBasic() ?
4651 visitBasic(cast(TypeBasic)mt) :
4656 /******************************* Private *****************************************/
4660 /* Helper function for `typeToExpression`. Contains common code
4661 * for TypeQualified derived classes.
4663 Expression typeToExpressionHelper(TypeQualified t, Expression e, size_t i = 0)
4665 //printf("toExpressionHelper(e = %s %s)\n", EXPtoString(e.op).ptr, e.toChars());
4666 foreach (id; t.idents[i .. t.idents.length])
4668 //printf("\t[%d] e: '%s', id: '%s'\n", i, e.toChars(), id.toChars());
4670 final switch (id.dyncast())
4673 case DYNCAST.identifier:
4674 e = new DotIdExp(e.loc, e, cast(Identifier)id);
4677 // ... '. name!(tiargs)'
4678 case DYNCAST.dsymbol:
4679 auto ti = (cast(Dsymbol)id).isTemplateInstance();
4681 e = new DotTemplateInstanceExp(e.loc, e, ti.name, ti.tiargs);
4685 case DYNCAST.type: // https://issues.dlang.org/show_bug.cgi?id=1215
4686 e = new ArrayExp(t.loc, e, new TypeExp(t.loc, cast(Type)id));
4690 case DYNCAST.expression: // https://issues.dlang.org/show_bug.cgi?id=1215
4691 e = new ArrayExp(t.loc, e, cast(Expression)id);
4694 case DYNCAST.object:
4696 case DYNCAST.parameter:
4697 case DYNCAST.statement:
4698 case DYNCAST.condition:
4699 case DYNCAST.templateparameter:
4700 case DYNCAST.initializer:
4707 /**************************
4708 * This evaluates exp while setting length to be the number
4709 * of elements in the tuple t.
4711 Expression semanticLength(Scope* sc, Type t, Expression exp)
4713 if (auto tt = t.isTypeTuple())
4715 ScopeDsymbol sym = new ArrayScopeSymbol(sc, tt);
4716 sym.parent = sc.scopesym;
4718 sc = sc.startCTFE();
4719 exp = exp.expressionSemantic(sc);
4720 exp = resolveProperties(sc, exp);
4726 sc = sc.startCTFE();
4727 exp = exp.expressionSemantic(sc);
4728 exp = resolveProperties(sc, exp);
4734 Expression semanticLength(Scope* sc, TupleDeclaration tup, Expression exp)
4736 ScopeDsymbol sym = new ArrayScopeSymbol(sc, tup);
4737 sym.parent = sc.scopesym;
4740 sc = sc.startCTFE();
4741 exp = exp.expressionSemantic(sc);
4742 exp = resolveProperties(sc, exp);
4749 /************************************
4750 * Transitively search a type for all function types.
4751 * If any function types with parameters are found that have parameter identifiers
4752 * or default arguments, remove those and create a new type stripped of those.
4753 * This is used to determine the "canonical" version of a type which is useful for
4758 * `t` if no parameter identifiers or default arguments found, otherwise a new type that is
4759 * the same as t but with no parameter identifiers or default arguments.
4761 Type stripDefaultArgs(Type t)
4763 static Parameters* stripParams(Parameters* parameters)
4765 static Parameter stripParameter(Parameter p)
4767 Type t = stripDefaultArgs(p.type);
4768 return (t != p.type || p.defaultArg || p.ident || p.userAttribDecl)
4769 ? new Parameter(p.storageClass, t, null, null, null)
4775 foreach (i, p; *parameters)
4777 Parameter ps = stripParameter(p);
4780 // Replace params with a copy we can modify
4781 Parameters* nparams = new Parameters(parameters.length);
4783 foreach (j, ref np; *nparams)
4785 Parameter pj = (*parameters)[j];
4792 Parameter nps = stripParameter(pj);
4793 np = nps ? nps : pj;
4806 if (auto tf = t.isTypeFunction())
4808 Type tret = stripDefaultArgs(tf.next);
4809 Parameters* params = stripParams(tf.parameterList.parameters);
4810 if (tret == tf.next && params == tf.parameterList.parameters)
4812 TypeFunction tr = tf.copy().isTypeFunction();
4813 tr.parameterList.parameters = params;
4815 //printf("strip %s\n <- %s\n", tr.toChars(), t.toChars());
4818 else if (auto tt = t.isTypeTuple())
4820 Parameters* args = stripParams(tt.arguments);
4821 if (args == tt.arguments)
4823 TypeTuple tr = t.copy().isTypeTuple();
4824 tr.arguments = args;
4827 else if (t.ty == Tenum)
4829 // TypeEnum::nextOf() may be != NULL, but it's not necessary here.
4834 Type tn = t.nextOf();
4835 Type n = stripDefaultArgs(tn);
4838 TypeNext tr = cast(TypeNext)t.copy();
4844 /******************************
4845 * Get the value of the .max/.min property of `ed` as an Expression.
4846 * Lazily computes the value and caches it in maxval/minval.
4847 * Reports any errors.
4849 * ed = the EnumDeclaration being examined
4850 * loc = location to use for error messages
4851 * id = Id::max or Id::min
4853 * corresponding value of .max/.min
4855 Expression getMaxMinValue(EnumDeclaration ed, const ref Loc loc, Identifier id)
4857 //printf("EnumDeclaration::getMaxValue()\n");
4859 static Expression pvalToResult(Expression e, const ref Loc loc)
4861 if (e.op != EXP.error)
4869 Expression* pval = (id == Id.max) ? &ed.maxval : &ed.minval;
4871 Expression errorReturn()
4873 *pval = ErrorExp.get();
4879 ed.error(loc, "recursive definition of `.%s` property", id.toChars());
4880 return errorReturn();
4883 return pvalToResult(*pval, loc);
4886 dsymbolSemantic(ed, ed._scope);
4888 return errorReturn();
4891 ed.error(loc, "is opaque and has no `.%s`", id.toChars());
4892 return errorReturn();
4894 if (!(ed.memtype && ed.memtype.isintegral()))
4896 ed.error(loc, "has no `.%s` property because base type `%s` is not an integral type",
4897 id.toChars(), ed.memtype ? ed.memtype.toChars() : "");
4898 return errorReturn();
4902 for (size_t i = 0; i < ed.members.length; i++)
4904 EnumMember em = (*ed.members)[i].isEnumMember();
4913 if (em.semanticRun < PASS.semanticdone)
4915 em.error("is forward referenced looking for `.%s`", id.toChars());
4927 /* In order to work successfully with UDTs,
4928 * build expressions to do the comparisons,
4929 * and let the semantic analyzer and constant
4930 * folder give us the result.
4937 Expression e = em.value;
4938 Expression ec = new CmpExp(id == Id.max ? EXP.greaterThan : EXP.lessThan, em.loc, e, *pval);
4940 ec = ec.expressionSemantic(em._scope);
4942 ec = ec.ctfeInterpret();
4943 if (ec.op == EXP.error)
4952 return ed.errors ? errorReturn() : pvalToResult(*pval, loc);
4955 /******************************************
4956 * Compile the MixinType, returning the type or expression AST.
4958 * Doesn't run semantic() on the returned object.
4960 * tm = mixin to compile as a type or expression
4961 * loc = location for error messages
4964 * null if error, else RootObject AST as parsed
4966 RootObject compileTypeMixin(TypeMixin tm, Loc loc, Scope* sc)
4969 if (expressionsToString(buf, sc, tm.exps))
4972 const errors = global.errors;
4973 const len = buf.length;
4975 const str = buf.extractSlice()[0 .. len];
4976 scope p = new Parser!ASTCodegen(loc, sc._module, str, false);
4978 //printf("p.loc.linnum = %d\n", p.loc.linnum);
4980 auto o = p.parseTypeOrAssignExp(TOK.endOfFile);
4981 if (errors != global.errors)
4983 assert(global.errors != errors); // should have caught all these cases
4986 if (p.token.value != TOK.endOfFile)
4988 .error(loc, "incomplete mixin type `%s`", str.ptr);